1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
/*
* Modification History
*
* 2001-December-14 Jason Rohrer
* Created.
* Fixed a typo.
* Added a missing include.
*
* 2002-March-25 Jason Rohrer
* Added function for conversion to numerical addresses.
*
* 2002-March-26 Jason Rohrer
* Changed to use strdup.
* Fixed problem on some platforms where local address does
* not include domain name.
* Fixed so that numerical address is actually retrieved by
* getNumericalAddress().
*
* 2002-April-6 Jason Rohrer
* Replaced use of strdup.
*
* 2002-April-8 Jason Rohrer
* Changed to return numerical address from getLocalAddress,
* since it is simpler, and we probably want the numerical
* address anyway.
* This new implementation also fixes a BSD domain-name lookup bug.
* Changed to check if address is numerical before
* performing a lookup on it.
*
* 2002-July-10 Jason Rohrer
* Fixed a bug that occurs when fetching numerical address fails.
*
* 2004-January-4 Jason Rohrer
* Added use of network function locks.
*
* 2009-December-22 Jason Rohrer
* New method of getting local address.
*
* 2010-April-23 Jason Rohrer
* ifa->if_addr can be NULL.
*/
#include "minorGems/network/HostAddress.h"
#include "minorGems/network/NetworkFunctionLocks.h"
#include "minorGems/util/stringUtils.h"
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <sys/socket.h>
HostAddress *HostAddress::getLocalAddress() {
int bufferLength = 200;
char *buffer = new char[ bufferLength ];
// old method, tended to return a 127.0.0.1 address
//gethostname( buffer, bufferLength );
// new method, iterate through interfaces
struct ifaddrs *ifaddr, *ifa;
if( getifaddrs( &ifaddr ) == -1 ) {
delete [] buffer;
return NULL;
}
// Walk through linked list, maintaining head pointer so we
// can free list later
// stop when we find an addr other than 127.0.0.1
char found = false;
for( ifa = ifaddr; ifa != NULL && !found; ifa = ifa->ifa_next) {
// only consider IPv4
// NULL check, too, because on at least one VPN, NULL
// addresses are present in list?
if( ifa->ifa_addr != NULL && ifa->ifa_addr->sa_family == AF_INET ) {
int s = getnameinfo( ifa->ifa_addr,
sizeof( struct sockaddr_in ),
buffer,
bufferLength, NULL, 0, NI_NUMERICHOST );
if( s != 0 ) {
printf("getnameinfo() failed: %s\n", gai_strerror( s ) );
delete [] buffer;
return NULL;
}
if( strcmp( buffer, "127.0.0.1" ) != 0 ) {
found = true;
}
}
}
freeifaddrs(ifaddr);
if( found ) {
char *numerical = stringDuplicate( buffer );
delete [] buffer;
// this class will destroy name for us
HostAddress *numericalAddress = new HostAddress( numerical, 0 );
return numericalAddress;
}
else {
delete [] buffer;
return NULL;
}
}
HostAddress *HostAddress::getNumericalAddress() {
// make sure we're not already numerical
if( this->isNumerical() ) {
return this->copy();
}
// need to use two function locks here
// first, lock for gethostbyname
NetworkFunctionLocks::mGetHostByNameLock.lock();
struct hostent *host = gethostbyname( mAddressString );
if (host != NULL) {
// this line adapted from the
// Unix Socket FAQ
struct in_addr *inetAddress = (struct in_addr *) *host->h_addr_list;
// now lock for inet_ntoa
NetworkFunctionLocks::mInet_ntoaLock.lock();
// the returned string is statically allocated, so copy it
char *inetAddressString = stringDuplicate( inet_ntoa( *inetAddress ) );
NetworkFunctionLocks::mInet_ntoaLock.unlock();
// done with returned hostent now, so unlock first lock
NetworkFunctionLocks::mGetHostByNameLock.unlock();
return new HostAddress( inetAddressString, mPort );
}
else {
// unlock first lock before returning
NetworkFunctionLocks::mGetHostByNameLock.unlock();
return NULL;
}
}
char HostAddress::isNumerical() {
struct in_addr addressStruct;
int isValid = inet_aton( mAddressString, &addressStruct );
if( isValid == 0 ) {
return false;
}
else {
return true;
}
}
|