groupsock/NetAddress.cpp

Go to the documentation of this file.
00001 /**********
00002 This library is free software; you can redistribute it and/or modify it under
00003 the terms of the GNU Lesser General Public License as published by the
00004 Free Software Foundation; either version 2.1 of the License, or (at your
00005 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
00006 
00007 This library is distributed in the hope that it will be useful, but WITHOUT
00008 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00009 FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
00010 more details.
00011 
00012 You should have received a copy of the GNU Lesser General Public License
00013 along with this library; if not, write to the Free Software Foundation, Inc.,
00014 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
00015 **********/
00016 // "mTunnel" multicast access service
00017 // Copyright (c) 1996-2012 Live Networks, Inc.  All rights reserved.
00018 // Network Addresses
00019 // Implementation
00020 
00021 #include "NetAddress.hh"
00022 #include "GroupsockHelper.hh"
00023 
00024 #include <stddef.h>
00025 #include <stdio.h>
00026 #if defined(__WIN32__) || defined(_WIN32)
00027 #define USE_GETHOSTBYNAME 1 /*because at least some Windows don't have getaddrinfo()*/
00028 #else
00029 #ifndef INADDR_NONE
00030 #define INADDR_NONE 0xFFFFFFFF
00031 #endif
00032 #endif
00033 
00035 
00036 NetAddress::NetAddress(u_int8_t const* data, unsigned length) {
00037   assign(data, length);
00038 }
00039 
00040 NetAddress::NetAddress(unsigned length) {
00041   fData = new u_int8_t[length];
00042   if (fData == NULL) {
00043     fLength = 0;
00044     return;
00045   }
00046 
00047   for (unsigned i = 0; i < length; ++i) fData[i] = 0;
00048   fLength = length;
00049 }
00050 
00051 NetAddress::NetAddress(NetAddress const& orig) {
00052   assign(orig.data(), orig.length());
00053 }
00054 
00055 NetAddress& NetAddress::operator=(NetAddress const& rightSide) {
00056   if (&rightSide != this) {
00057     clean();
00058     assign(rightSide.data(), rightSide.length());
00059   }
00060   return *this;
00061 }
00062 
00063 NetAddress::~NetAddress() {
00064   clean();
00065 }
00066 
00067 void NetAddress::assign(u_int8_t const* data, unsigned length) {
00068   fData = new u_int8_t[length];
00069   if (fData == NULL) {
00070     fLength = 0;
00071     return;
00072   }
00073 
00074   for (unsigned i = 0; i < length; ++i) fData[i] = data[i];
00075   fLength = length;
00076 }
00077 
00078 void NetAddress::clean() {
00079   delete[] fData; fData = NULL;
00080   fLength = 0;
00081 }
00082 
00083 
00085 
00086 NetAddressList::NetAddressList(char const* hostname)
00087   : fNumAddresses(0), fAddressArray(NULL) {
00088   // First, check whether "hostname" is an IP address string:
00089   netAddressBits addr = our_inet_addr((char*)hostname);
00090   if (addr != INADDR_NONE) {
00091     // Yes, it was an IP address string.  Return a 1-element list with this address:
00092     fNumAddresses = 1;
00093     fAddressArray = new NetAddress*[fNumAddresses];
00094     if (fAddressArray == NULL) return;
00095 
00096     fAddressArray[0] = new NetAddress((u_int8_t*)&addr, sizeof (netAddressBits));
00097     return;
00098   }
00099     
00100   // "hostname" is not an IP address string; try resolving it as a real host name instead:
00101 #if defined(USE_GETHOSTBYNAME) || defined(VXWORKS)
00102   struct hostent* host;
00103 #if defined(VXWORKS)
00104   char hostentBuf[512];
00105 
00106   host = (struct hostent*)resolvGetHostByName((char*)hostname, (char*)&hostentBuf, sizeof hostentBuf);
00107 #else
00108   host = gethostbyname((char*)hostname);
00109 #endif
00110   if (host == NULL || host->h_length != 4 || host->h_addr_list == NULL) return; // no luck
00111 
00112   u_int8_t const** const hAddrPtr = (u_int8_t const**)host->h_addr_list;
00113   // First, count the number of addresses:
00114   u_int8_t const** hAddrPtr1 = hAddrPtr;
00115   while (*hAddrPtr1 != NULL) {
00116     ++fNumAddresses;
00117     ++hAddrPtr1;
00118   }
00119 
00120   // Next, set up the list:
00121   fAddressArray = new NetAddress*[fNumAddresses];
00122   if (fAddressArray == NULL) return;
00123 
00124   for (unsigned i = 0; i < fNumAddresses; ++i) {
00125     fAddressArray[i] = new NetAddress(hAddrPtr[i], host->h_length);
00126   }
00127 #else
00128   // Use "getaddrinfo()" (rather than the older, deprecated "gethostbyname()"):
00129   struct addrinfo addrinfoHints;
00130   memset(&addrinfoHints, 0, sizeof addrinfoHints);
00131   addrinfoHints.ai_family = AF_INET; // For now, we're interested in IPv4 addresses only
00132   struct addrinfo* addrinfoResultPtr = NULL;
00133   int result = getaddrinfo(hostname, NULL, &addrinfoHints, &addrinfoResultPtr);
00134   if (result != 0 || addrinfoResultPtr == NULL) return; // no luck
00135 
00136   // First, count the number of addresses:
00137   const struct addrinfo* p = addrinfoResultPtr;
00138   while (p != NULL) {
00139     if (p->ai_addrlen < 4) continue; // sanity check: skip over addresses that are too small
00140     ++fNumAddresses;
00141     p = p->ai_next;
00142   }
00143 
00144   // Next, set up the list:
00145   fAddressArray = new NetAddress*[fNumAddresses];
00146   if (fAddressArray == NULL) return;
00147 
00148   unsigned i = 0;
00149   p = addrinfoResultPtr;
00150   while (p != NULL) {
00151     if (p->ai_addrlen < 4) continue;
00152     fAddressArray[i++] = new NetAddress((u_int8_t const*)&(((struct sockaddr_in*)p->ai_addr)->sin_addr.s_addr), 4);
00153     p = p->ai_next;
00154   }
00155 
00156   // Finally, free the data that we had allocated by calling "getaddrinfo()":
00157   freeaddrinfo(addrinfoResultPtr);
00158 #endif
00159 }
00160 
00161 NetAddressList::NetAddressList(NetAddressList const& orig) {
00162   assign(orig.numAddresses(), orig.fAddressArray);
00163 }
00164 
00165 NetAddressList& NetAddressList::operator=(NetAddressList const& rightSide) {
00166   if (&rightSide != this) {
00167     clean();
00168     assign(rightSide.numAddresses(), rightSide.fAddressArray);
00169   }
00170   return *this;
00171 }
00172 
00173 NetAddressList::~NetAddressList() {
00174   clean();
00175 }
00176 
00177 void NetAddressList::assign(unsigned numAddresses, NetAddress** addressArray) {
00178   fAddressArray = new NetAddress*[numAddresses];
00179   if (fAddressArray == NULL) {
00180     fNumAddresses = 0;
00181     return;
00182   }
00183 
00184   for (unsigned i = 0; i < numAddresses; ++i) {
00185     fAddressArray[i] = new NetAddress(*addressArray[i]);
00186   }
00187   fNumAddresses = numAddresses;
00188 }
00189 
00190 void NetAddressList::clean() {
00191   while (fNumAddresses-- > 0) {
00192     delete fAddressArray[fNumAddresses];
00193   }
00194   delete[] fAddressArray; fAddressArray = NULL;
00195 }
00196 
00197 NetAddress const* NetAddressList::firstAddress() const {
00198   if (fNumAddresses == 0) return NULL;
00199 
00200   return fAddressArray[0];
00201 }
00202 
00204 NetAddressList::Iterator::Iterator(NetAddressList const& addressList)
00205   : fAddressList(addressList), fNextIndex(0) {}
00206 
00207 NetAddress const* NetAddressList::Iterator::nextAddress() {
00208   if (fNextIndex >= fAddressList.numAddresses()) return NULL; // no more
00209   return fAddressList.fAddressArray[fNextIndex++];
00210 }
00211 
00212 
00214 
00215 Port::Port(portNumBits num /* in host byte order */) {
00216   fPortNum = htons(num);
00217 }
00218 
00219 UsageEnvironment& operator<<(UsageEnvironment& s, const Port& p) {
00220   return s << ntohs(p.num());
00221 }
00222 
00223 
00225 
00226 AddressPortLookupTable::AddressPortLookupTable()
00227   : fTable(HashTable::create(3)) { // three-word keys are used
00228 }
00229 
00230 AddressPortLookupTable::~AddressPortLookupTable() {
00231   delete fTable;
00232 }
00233 
00234 void* AddressPortLookupTable::Add(netAddressBits address1,
00235                                   netAddressBits address2,
00236                                   Port port, void* value) {
00237   int key[3];
00238   key[0] = (int)address1;
00239   key[1] = (int)address2;
00240   key[2] = (int)port.num();
00241   return fTable->Add((char*)key, value);
00242 }
00243 
00244 void* AddressPortLookupTable::Lookup(netAddressBits address1,
00245                                      netAddressBits address2,
00246                                      Port port) {
00247   int key[3];
00248   key[0] = (int)address1;
00249   key[1] = (int)address2;
00250   key[2] = (int)port.num();
00251   return fTable->Lookup((char*)key);
00252 }
00253 
00254 Boolean AddressPortLookupTable::Remove(netAddressBits address1,
00255                                        netAddressBits address2,
00256                                        Port port) {
00257   int key[3];
00258   key[0] = (int)address1;
00259   key[1] = (int)address2;
00260   key[2] = (int)port.num();
00261   return fTable->Remove((char*)key);
00262 }
00263 
00264 AddressPortLookupTable::Iterator::Iterator(AddressPortLookupTable& table)
00265   : fIter(HashTable::Iterator::create(*(table.fTable))) {
00266 }
00267 
00268 AddressPortLookupTable::Iterator::~Iterator() {
00269   delete fIter;
00270 }
00271 
00272 void* AddressPortLookupTable::Iterator::next() {
00273   char const* key; // dummy
00274   return fIter->next(key);
00275 }
00276 
00277 
00279 
00280 Boolean IsMulticastAddress(netAddressBits address) {
00281   // Note: We return False for addresses in the range 224.0.0.0
00282   // through 224.0.0.255, because these are non-routable
00283   // Note: IPv4-specific #####
00284   netAddressBits addressInNetworkOrder = htonl(address);
00285   return addressInNetworkOrder >  0xE00000FF &&
00286          addressInNetworkOrder <= 0xEFFFFFFF;
00287 }
00288 
00289 
00291 
00292 AddressString::AddressString(struct sockaddr_in const& addr) {
00293   init(addr.sin_addr.s_addr);
00294 }
00295 
00296 AddressString::AddressString(struct in_addr const& addr) {
00297   init(addr.s_addr);
00298 }
00299 
00300 AddressString::AddressString(netAddressBits addr) {
00301   init(addr);
00302 }
00303 
00304 void AddressString::init(netAddressBits addr) {
00305   fVal = new char[16]; // large enough for "abc.def.ghi.jkl"
00306   netAddressBits addrNBO = htonl(addr); // make sure we have a value in a known byte order: big endian
00307   sprintf(fVal, "%u.%u.%u.%u", (addrNBO>>24)&0xFF, (addrNBO>>16)&0xFF, (addrNBO>>8)&0xFF, addrNBO&0xFF);
00308 }
00309 
00310 AddressString::~AddressString() {
00311   delete[] fVal;
00312 }

Generated on Thu Feb 2 23:51:29 2012 for live by  doxygen 1.5.2