feisty meow concerns codebase  2.140
machine_uid.cpp
Go to the documentation of this file.
1 /*****************************************************************************\
2 * *
3 * Name : machine_uid *
4 * Author : Chris Koeritz *
5 * *
6 *******************************************************************************
7 * Copyright (c) 2000-$now By Author. This program is free software; you can *
8 * redistribute it and/or modify it under the terms of the GNU General Public *
9 * License as published by the Free Software Foundation; either version 2 of *
10 * the License or (at your option) any later version. This is online at: *
11 * http://www.fsf.org/copyleft/gpl.html *
12 * Please send any updates to: fred@gruntose.com *
13 \*****************************************************************************/
14 
15 //#include "internet_address.h"
16 #include "machine_uid.h"
17 
18 #include <basis/byte_array.h>
19 #include <basis/functions.h>
20 #include <basis/astring.h>
21 #include <basis/mutex.h>
22 #include <structures/checksums.h>
25 #include <textual/byte_formatter.h>
26 
27 using namespace basis;
28 using namespace structures;
29 using namespace textual;
30 
31 namespace sockets {
32 
33 machine_uid::machine_uid()
34 : _contents(new byte_array)
35 { *_contents += abyte(INVALID_LOCATION); }
36 
38  const byte_array &address)
39 : _contents(new byte_array)
40 {
41  *_contents += abyte(type);
42  *_contents += address;
43 }
44 
46 : packable(),
47  _contents(new byte_array)
48 { *this = to_copy; }
49 
51 
53 {
54  _contents->reset();
55  *_contents += abyte(type);
56  *_contents += address;
57 }
58 
59 const byte_array &machine_uid::raw() const { return *_contents; }
60 
62 {
63  static astring TCPIP_NAME = "TCPIP";
64  static astring IPX_NAME = "IPX";
65  static astring NETBIOS_NAME = "NETBIOS";
66  static astring UNKNOWN_NAME = "INVALID";
67 
68  switch (type) {
69  case TCPIP_LOCATION: return TCPIP_NAME;
70  case IPX_LOCATION: return IPX_NAME;
71  case NETBIOS_LOCATION: return NETBIOS_NAME;
72  default: return UNKNOWN_NAME;
73  }
74 }
75 
77 {
78  if (this == &to_copy) return *this;
79  *_contents = *to_copy._contents;
80  return *this;
81 }
82 
84 {
85  astring to_return;
86  to_return += type_name(type()) + "[";
87  for (int i = 1; i < _contents->length(); i++) {
88  if (type() == TCPIP_LOCATION)
89  to_return += a_sprintf("%d", int(_contents->get(i)));
90  else
91  to_return += a_sprintf("%02x", int(_contents->get(i)));
92  if (i < _contents->length() - 1)
93  to_return += ".";
94  }
95  to_return += "]";
96  return to_return;
97 }
98 
100 {
101  astring to_return;
102  byte_formatter::bytes_to_shifted_string(*_contents, to_return);
103  return to_return;
104 }
105 
107 {
108  machine_uid to_return;
109  to_return._contents->reset();
110  byte_formatter::shifted_string_to_bytes(compacted, *to_return._contents);
111  return to_return;
112 }
113 
114 bool machine_uid::operator == (const machine_uid &to_compare) const
115 {
116  // an empty id is only equal to another empty id.
117  if (!_contents->length() || !to_compare._contents->length())
118  return !_contents->length() && !to_compare._contents->length();
119  if (_contents->length() != to_compare._contents->length()) return false;
120  for (int i = 0; i < _contents->length(); i++)
121  if (_contents->get(i) != to_compare._contents->get(i)) return false;
122  return true;
123 }
124 
126 {
127  if (!_contents->length()) return INVALID_LOCATION;
128  return known_location_types(_contents->get(0));
129 }
130 
132 {
133  return PACKED_SIZE_INT32 + _contents->length();
134 }
135 
136 void machine_uid::pack(byte_array &packed_form) const
137 {
138  structures::attach(packed_form, _contents->length());
139  packed_form += *_contents;
140 }
141 
142 bool machine_uid::unpack(byte_array &packed_form)
143 {
144  int len = 0;
145  if (!structures::detach(packed_form, len)) return false;
146  // there's no length even?
147  if (packed_form.length() < len) return false;
148  // not enough size left for the length specified.
149  *_contents = packed_form.subarray(0, len - 1);
150  packed_form.zap(0, len - 1);
151  return true;
152 }
153 
155 {
156  if (_contents->length() <= 1) return byte_array(); // invalid.
157  return _contents->subarray(1, _contents->last());
158 }
159 
161 
162 class internal_machine_uid_array : public array<machine_uid> {};
163 
165 : _uids(new internal_machine_uid_array)
166 {}
167 
169 : root_object(),
170  _uids(new internal_machine_uid_array(*to_copy._uids))
171 {
172 }
173 
175 {
176  WHACK(_uids);
177 }
178 
180 
182  (const machine_uid_array &to_copy)
183 {
184  if (this != &to_copy) {
185  *_uids = *to_copy._uids;
186  }
187  return *this;
188 }
189 
191 {
192  if (member(to_add)) return false;
193  _uids->concatenate(to_add);
194  return true;
195 }
196 
197 int machine_uid_array::elements() const { return _uids->length(); }
198 
200 {
201  astring to_return;
202  for (int i = 0; i < _uids->length(); i++) {
203  to_return += _uids->get(i).text_form() + " ";
204  }
205  return to_return;
206 }
207 
209 { return _uids->use(index); }
210 
212 { return _uids->get(index); }
213 
214 void machine_uid_array::reset() { _uids->reset(); }
215 
216 bool machine_uid_array::member(const machine_uid &to_test) const
217 {
218  const int test_len = to_test.raw().length();
219  for (int i = 0; i < _uids->length(); i++) {
220  const machine_uid &curr = _uids->get(i);
221  // test for the length first since that's cheaper.
222  if ( (test_len == curr.raw().length()) && (curr == to_test) ) {
223  return true;
224  } else if (!to_test.valid() && !curr.valid()) return true;
225  // both are invalid, so the item to find is present.
226 
227 /*
228  if (!to_test.valid() || !curr.valid()) continue;
229  // one is invalid but the other is not; not a match.
230 all bogus!
231 //hmmm: weird partial matching being allowed here.
232  bool to_return = true; // assume it's good until told otherwise.
233  // if the first parts of the addresses agree, then assume we're
234  for (int j = 0; j < minimum(test_len, curr.raw().length()); j++) {
235  if (curr.raw().get(j) != to_test.raw().get(j)) {
236  to_return = false;
237  }
238  }
239  if (to_return)
240  return true;
241  }
242 */
243  }
244  return false;
245 }
246 
248 
250  const byte_array &ip_address)
251 {
252  byte_array addr(ip_address);
253  basis::un_short fletch = checksums::fletcher_checksum((const abyte *)hostname.observe(),
254  hostname.length());
255  structures::attach(addr, fletch);
257 }
258 
259 } //namespace.
260 
a_sprintf is a specialization of astring that provides printf style support.
Definition: astring.h:440
Represents a sequential, ordered, contiguous collection of objects.
Definition: array.h:54
void reset(int number=0, const contents *initial_contents=NULL_POINTER)
Resizes this array and sets the contents from an array of contents.
Definition: array.h:349
array subarray(int start, int end) const
Returns the array segment between the indices "start" and "end".
Definition: array.h:443
const contents & get(int index) const
Accesses individual objects stored in "this" at the "index" position.
Definition: array.h:372
int length() const
Returns the current reported length of the allocated C array.
Definition: array.h:115
outcome zap(int start, int end)
Deletes from "this" the objects inclusively between "start" and "end".
Definition: array.h:769
int last() const
Returns the last valid element in the array.
Definition: array.h:118
Provides a dynamically resizable ASCII character string.
Definition: astring.h:35
int length() const
Returns the current length of the string.
Definition: astring.cpp:132
virtual const char * observe() const
observes the underlying pointer to the zero-terminated string.
Definition: astring.cpp:140
A very common template for a dynamic array of bytes.
Definition: byte_array.h:36
A base class for objects that can pack into an array of bytes.
Definition: byte_array.h:87
internet_machine_uid(const basis::astring &hostname, const basis::byte_array &ip_address)
static const machine_uid_array & blank_array()
machine_uid & operator[](int index)
bool operator+=(const machine_uid &to_add)
bool member(const machine_uid &to_test) const
basis::astring text_form() const
virtual int packed_size() const
Estimates the space needed for the packed structure.
virtual bool unpack(basis::byte_array &packed_form)
Restores the packable from the "packed_form".
basis::byte_array native() const
static machine_uid expand(const basis::astring &compacted)
basis::astring text_form() const
Definition: machine_uid.cpp:83
known_location_types type() const
const basis::byte_array & raw() const
Definition: machine_uid.cpp:59
static const basis::astring & type_name(known_location_types type)
Definition: machine_uid.cpp:61
void reset(known_location_types type, const basis::byte_array &address)
Definition: machine_uid.cpp:52
virtual void pack(basis::byte_array &packed_form) const
Creates a packed form of the packable object in "packed_form".
machine_uid & operator=(const machine_uid &to_copy)
Definition: machine_uid.cpp:76
bool operator==(const machine_uid &to_compare) const
basis::astring compact_form() const
Definition: machine_uid.cpp:99
bool valid() const
Definition: machine_uid.h:68
The guards collection helps in testing preconditions and reporting errors.
Definition: array.h:30
void WHACK(contents *&ptr)
deletion with clearing of the pointer.
Definition: functions.h:121
unsigned char abyte
A fairly important unit which is seldom defined...
Definition: definitions.h:51
unsigned short un_short
Abbreviated name for unsigned short integers.
Definition: definitions.h:64
Provides access to the operating system's socket methods.
Definition: base_address.h:26
SAFE_STATIC_CONST(byte_array, internet_address::localhost,(ADDRESS_SIZE, localhosts_bytes)) bool internet_address
A dynamic container class that holds any kind of object via pointers.
Definition: amorph.h:55
void attach(byte_array &packed_form, const byte_array &to_attach)
Packs a byte_array "to_attach" into "packed_form".
const int PACKED_SIZE_INT32
bool detach(byte_array &packed_form, byte_array &to_detach)
Unpacks a byte_array "to_detach" from "packed_form".