Merge branch 'master' of feistymeow.org:feisty_meow
[feisty_meow.git] / octopi / library / sockets / subnet_calculator.cpp
1
2
3
4 /*****************************************************************************\
5 *                                                                             *
6 *  Name   : subnet_calculator                                                 *
7 *  Author : Chris Koeritz                                                     *
8 *                                                                             *
9 *******************************************************************************
10 * Copyright (c) 1997-$now By Author.  This program is free software; you can  *
11 * redistribute it and/or modify it under the terms of the GNU General Public  *
12 * License as published by the Free Software Foundation; either version 2 of   *
13 * the License or (at your option) any later version.  This is online at:      *
14 *     http://www.fsf.org/copyleft/gpl.html                                    *
15 * Please send any updates to: fred@gruntose.com                               *
16 \*****************************************************************************/
17
18 //hmmm: this class only handles 32 bit (4 byte) internet addresses.  it should
19 //      use an arbitrary length integer object to overcome differences in the
20 //      sizes of internet addresses.
21 //      really we should just start using the machine uid underneath...
22
23 #include "subnet_calculator.h"
24
25 #include <basis/functions.h>
26 #include <basis/astring.h>
27
28 using namespace basis;
29
30 namespace sockets {
31
32 subnet_calculator::subnet_calculator(const astring &mask, const astring &samp)
33 : _valid(false),
34   _subnet_mask(new astring(mask)),
35   _ip_address(new astring(samp)),
36   _low_end(new astring("")),
37   _high_end(new astring(""))
38 { calculate(); }
39
40 subnet_calculator::~subnet_calculator()
41 {
42   WHACK(_subnet_mask);
43   WHACK(_ip_address);
44   WHACK(_low_end);
45   WHACK(_high_end);
46   _valid = false;
47 }
48
49 const astring &subnet_calculator::subnet_mask() const { return *_subnet_mask; }
50
51 const astring &subnet_calculator::ip_address() const { return *_ip_address; }
52
53 void subnet_calculator::subnet_mask(const astring &new_mask)
54 {
55   _valid = false;
56   *_subnet_mask = new_mask;
57 }
58
59 void subnet_calculator::ip_address(const astring &new_address)
60 {
61   _valid = false;
62   *_ip_address = new_address;
63 }
64
65 const astring &subnet_calculator::low_end()
66 {
67   calculate();
68   return *_low_end;
69 }
70
71 const astring &subnet_calculator::high_end()
72 {
73   calculate();
74   return *_high_end;
75 }
76
77 astring subnet_calculator::convert(basis::un_int num_format)
78 {
79   astring to_return;
80   basis::un_int temp_num = num_format;
81   for (int i = 0; i < 4; i++) {
82     if (to_return.t())
83       to_return = astring(".") + to_return;
84     // shave a byte off for inclusion in the string.
85     basis::un_int new_byte = temp_num % 256;
86     temp_num >>= 8;
87     to_return = astring(astring::SPRINTF, "%d", new_byte) + to_return;
88   }
89   return to_return;
90 }
91
92 un_int subnet_calculator::convert(const astring &ip_format)
93 {
94   basis::un_int to_return = 0;
95   astring ip_temp = ip_format;
96   for (int i = 0; i < 3; i++) {
97     int indy = ip_temp.find(".");
98     if (indy < 0) return to_return;
99     astring this_piece = ip_temp.substring(0, indy - 1);
100     to_return <<= 8;
101     to_return += this_piece.convert(0);
102     ip_temp.zap(0, indy);
103   }
104
105   if (ip_temp.length()) {
106     to_return <<= 8;
107     to_return += ip_temp.convert(0);
108   }
109
110   return to_return;
111 }
112
113 void subnet_calculator::calculate()
114 {
115   if (valid()) return;  // already valid.
116
117   basis::un_int ip = convert(*_ip_address);
118   basis::un_int sub = convert(*_subnet_mask);
119
120   basis::un_int low_end = sub & ip;
121     // strips off the host part of the ip address and leaves just the network
122     // component that comes from the ip address.
123
124   basis::un_int temp_sub = sub;
125   int bits_to_add = 0;
126   // we shift the subnet mask until we find it's first lowest order "1" bit.
127   // this tells us how many bits are in the host portion (unless the mask is
128   // zero, in which case the host is all of the bits).
129   while (temp_sub && !(temp_sub % 2)) {
130     temp_sub >>= 1;  // shift off a bit.
131     bits_to_add++;  // record that the place we were at had a zero bit.
132   }
133   if (!sub) bits_to_add = 32;
134     // account for a blank subnet mask, meaning there is no network and all
135     // bits are used for host addresses.
136   basis::un_int add_in_for_bcast = 0;
137     // the part added in to make a broadcast address.  this is all ones.
138   for (int i = 0; i < bits_to_add; i++) {
139     add_in_for_bcast <<= 1;  // shift the existing add_in to the left.
140     add_in_for_bcast++;  // make a new one bit in the ones place.
141   }
142
143   basis::un_int high_end = low_end + add_in_for_bcast;
144
145   *_low_end = convert(low_end);
146   *_high_end = convert(high_end);
147   _valid = true;
148 }
149
150 } //namespace.
151
152