machine_uid.cpp

Go to the documentation of this file.
00001 /*****************************************************************************\
00002 *                                                                             *
00003 *  Name   : machine_uid                                                       *
00004 *  Author : Chris Koeritz                                                     *
00005 *                                                                             *
00006 *******************************************************************************
00007 * Copyright (c) 2000-$now By Author.  This program is free software; you can  *
00008 * redistribute it and/or modify it under the terms of the GNU General Public  *
00009 * License as published by the Free Software Foundation; either version 2 of   *
00010 * the License or (at your option) any later version.  This is online at:      *
00011 *     http://www.fsf.org/copyleft/gpl.html                                    *
00012 * Please send any updates to: fred@gruntose.com                               *
00013 \*****************************************************************************/
00014 
00015 //#include "internet_address.h"
00016 #include "machine_uid.h"
00017 
00018 #include <basis/byte_array.h>
00019 #include <basis/functions.h>
00020 #include <basis/astring.h>
00021 #include <basis/mutex.h>
00022 #include <structures/checksums.h>
00023 #include <structures/object_packers.h>
00024 #include <structures/static_memory_gremlin.h>
00025 #include <textual/byte_formatter.h>
00026 
00027 using namespace basis;
00028 using namespace structures;
00029 using namespace textual;
00030 
00031 namespace sockets {
00032 
00033 machine_uid::machine_uid()
00034 : _contents(new byte_array)
00035 { *_contents += abyte(INVALID_LOCATION); }
00036 
00037 machine_uid::machine_uid(known_location_types type,
00038     const byte_array &address)
00039 : _contents(new byte_array)
00040 {
00041   *_contents += abyte(type); 
00042   *_contents += address;
00043 }
00044 
00045 machine_uid::machine_uid(const machine_uid &to_copy)
00046 : packable(),
00047   _contents(new byte_array)
00048 { *this = to_copy; }
00049 
00050 machine_uid::~machine_uid() { WHACK(_contents); }
00051 
00052 void machine_uid::reset(known_location_types type, const byte_array &address)
00053 {
00054   _contents->reset();
00055   *_contents += abyte(type); 
00056   *_contents += address;
00057 }
00058 
00059 const byte_array &machine_uid::raw() const { return *_contents; }
00060 
00061 const astring &machine_uid::type_name(known_location_types type)
00062 {
00063   static astring TCPIP_NAME = "TCPIP";
00064   static astring IPX_NAME = "IPX";
00065   static astring NETBIOS_NAME = "NETBIOS";
00066   static astring UNKNOWN_NAME = "INVALID";
00067 
00068   switch (type) {
00069     case TCPIP_LOCATION: return TCPIP_NAME;
00070     case IPX_LOCATION: return IPX_NAME;
00071     case NETBIOS_LOCATION: return NETBIOS_NAME;
00072     default: return UNKNOWN_NAME;
00073   }
00074 }
00075 
00076 machine_uid &machine_uid::operator = (const machine_uid &to_copy)
00077 {
00078   if (this == &to_copy) return *this;
00079   *_contents = *to_copy._contents;
00080   return *this;
00081 }
00082 
00083 astring machine_uid::text_form() const
00084 {
00085   astring to_return;
00086   to_return += type_name(type()) + "[";
00087   for (int i = 1; i < _contents->length(); i++) {
00088     if (type() == TCPIP_LOCATION)
00089       to_return += a_sprintf("%d", int(_contents->get(i)));
00090     else
00091       to_return += a_sprintf("%02x", int(_contents->get(i)));
00092     if (i < _contents->length() - 1)
00093       to_return += ".";
00094   }
00095   to_return += "]";
00096   return to_return;
00097 }
00098 
00099 astring machine_uid::compact_form() const
00100 {
00101   astring to_return;
00102   byte_formatter::bytes_to_shifted_string(*_contents, to_return);
00103   return to_return;
00104 }
00105 
00106 machine_uid machine_uid::expand(const astring &compacted)
00107 {
00108   machine_uid to_return;
00109   to_return._contents->reset();
00110   byte_formatter::shifted_string_to_bytes(compacted, *to_return._contents);
00111   return to_return;
00112 }
00113 
00114 bool machine_uid::operator == (const machine_uid &to_compare) const
00115 {
00116   // an empty id is only equal to another empty id.
00117   if (!_contents->length() || !to_compare._contents->length())
00118     return !_contents->length() && !to_compare._contents->length();
00119   if (_contents->length() != to_compare._contents->length()) return false;
00120   for (int i = 0; i < _contents->length(); i++)
00121     if (_contents->get(i) != to_compare._contents->get(i)) return false;
00122   return true;
00123 }
00124 
00125 machine_uid::known_location_types machine_uid::type() const
00126 {
00127   if (!_contents->length()) return INVALID_LOCATION;
00128   return known_location_types(_contents->get(0));
00129 }
00130 
00131 int machine_uid::packed_size() const
00132 {
00133   return PACKED_SIZE_INT32 + _contents->length();
00134 }
00135 
00136 void machine_uid::pack(byte_array &packed_form) const
00137 {
00138   structures::attach(packed_form, _contents->length());
00139   packed_form += *_contents;
00140 }
00141 
00142 bool machine_uid::unpack(byte_array &packed_form)
00143 {
00144   int len = 0;
00145   if (!structures::detach(packed_form, len)) return false;
00146     // there's no length even?
00147   if (packed_form.length() < len) return false;
00148     // not enough size left for the length specified.
00149   *_contents = packed_form.subarray(0, len - 1);
00150   packed_form.zap(0, len - 1);
00151   return true;
00152 }
00153 
00154 byte_array machine_uid::native() const
00155 {
00156   if (_contents->length() <= 1) return byte_array();  // invalid.
00157   return _contents->subarray(1, _contents->last());
00158 }
00159 
00161 
00162 class internal_machine_uid_array : public array<machine_uid> {};
00163 
00164 machine_uid_array::machine_uid_array()
00165 : _uids(new internal_machine_uid_array)
00166 {}
00167 
00168 machine_uid_array::machine_uid_array(const machine_uid_array &to_copy)
00169 : root_object(),
00170   _uids(new internal_machine_uid_array(*to_copy._uids))
00171 {
00172 }
00173 
00174 machine_uid_array::~machine_uid_array()
00175 {
00176   WHACK(_uids);
00177 }
00178 
00179 SAFE_STATIC_CONST(machine_uid_array, machine_uid_array::blank_array, )
00180 
00181 machine_uid_array &machine_uid_array::operator =
00182     (const machine_uid_array &to_copy)
00183 {
00184   if (this != &to_copy) {
00185     *_uids = *to_copy._uids;
00186   }
00187   return *this;
00188 }
00189 
00190 bool machine_uid_array::operator += (const machine_uid &to_add)
00191 {
00192   if (member(to_add)) return false;
00193   _uids->concatenate(to_add);
00194   return true;
00195 }
00196 
00197 int machine_uid_array::elements() const { return _uids->length(); }
00198 
00199 astring machine_uid_array::text_form() const
00200 {
00201   astring to_return;
00202   for (int i = 0; i < _uids->length(); i++) {
00203     to_return += _uids->get(i).text_form() + " ";
00204   }
00205   return to_return;
00206 }
00207 
00208 machine_uid &machine_uid_array::operator [] (int index)
00209 { return _uids->use(index); }
00210 
00211 const machine_uid &machine_uid_array::operator [] (int index) const
00212 { return _uids->get(index); }
00213 
00214 void machine_uid_array::reset() { _uids->reset(); }
00215 
00216 bool machine_uid_array::member(const machine_uid &to_test) const
00217 {
00218   const int test_len = to_test.raw().length();
00219   for (int i = 0; i < _uids->length(); i++) {
00220     const machine_uid &curr = _uids->get(i);
00221     // test for the length first since that's cheaper.
00222     if ( (test_len == curr.raw().length()) && (curr == to_test) ) {
00223       return true;
00224     } else if (!to_test.valid() && !curr.valid()) return true;
00225       // both are invalid, so the item to find is present.
00226 
00227 /*
00228       if (!to_test.valid() || !curr.valid()) continue;
00229         // one is invalid but the other is not; not a match.
00230 all bogus!
00231 //hmmm: weird partial matching being allowed here.
00232       bool to_return = true;  // assume it's good until told otherwise.
00233       // if the first parts of the addresses agree, then assume we're
00234       for (int j = 0; j < minimum(test_len, curr.raw().length()); j++) {
00235         if (curr.raw().get(j) != to_test.raw().get(j)) {
00236           to_return = false;
00237         }
00238       }
00239       if (to_return)
00240         return true;
00241     }
00242 */
00243   }
00244   return false;
00245 }
00246 
00248 
00249 internet_machine_uid::internet_machine_uid(const astring &hostname,
00250     const byte_array &ip_address)
00251 {
00252   byte_array addr(ip_address);
00253   basis::un_short fletch = checksums::fletcher_checksum((const abyte *)hostname.observe(),
00254       hostname.length());
00255   structures::attach(addr, fletch);
00256   reset(machine_uid::TCPIP_LOCATION, addr);
00257 }
00258 
00259 } //namespace.
00260 
Generated on Sat Jan 28 04:22:43 2012 for hoople2 project by  doxygen 1.6.3