00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "stdnet.h"
00027
00028 #include "nel/misc/common.h"
00029
00030 #include "nel/net/inet_address.h"
00031 #include "nel/net/sock.h"
00032
00033 #ifdef NL_OS_WINDOWS
00034
00035 #include <winsock2.h>
00036
00037 #elif defined NL_OS_UNIX
00038
00039 #include <unistd.h>
00040 #include <sys/socket.h>
00041 #include <arpa/inet.h>
00042 #include <netinet/in.h>
00043 #include <netdb.h>
00044
00045 #define WSAGetLastError() 0
00046 #define SOCKET_ERROR -1
00047
00048 #endif
00049
00050
00051 using namespace std;
00052 using namespace NLMISC;
00053
00054
00055 namespace NLNET
00056 {
00057
00058 bool CInetAddress::RetrieveNames = false;
00059
00060
00061
00062
00063
00064 CInetAddress::CInetAddress()
00065 {
00066 init();
00067 _SockAddr->sin_port = 0;
00068 memset( &_SockAddr->sin_addr, 0, sizeof(in_addr) );
00069 }
00070
00071
00072
00073
00074
00075 CInetAddress::CInetAddress( const in_addr *ip )
00076 {
00077 init();
00078 _SockAddr->sin_port = 0;
00079 memcpy( &_SockAddr->sin_addr, ip, sizeof(in_addr) );
00080
00081
00082 hostent *phostent = gethostbyaddr( (char*)&ip->s_addr, 4, AF_INET );
00083 if ( phostent == NULL )
00084 {
00085 _HostName = ipAddress();
00086 }
00087 else
00088 {
00089 _HostName = string( phostent->h_name );
00090 }
00091 _Valid = true;
00092 }
00093
00094
00095
00096
00097
00098 CInetAddress::CInetAddress( const std::string& hostName, uint16 port )
00099 {
00100 init();
00101 setPort( port );
00102 setByName( hostName );
00103 }
00104
00105
00106
00107
00108
00109 CInetAddress::CInetAddress( const std::string& hostNameAndPort )
00110 {
00111 init();
00112 setNameAndPort( hostNameAndPort );
00113 }
00114
00115
00116
00117
00118
00119 CInetAddress::CInetAddress( const CInetAddress& other )
00120 {
00121 init();
00122 _HostName = other._HostName;
00123 memcpy( _SockAddr, other._SockAddr, sizeof( *_SockAddr ) );
00124 _Valid = other._Valid;
00125 }
00126
00127
00128
00129
00130
00131 CInetAddress& CInetAddress::operator=( const CInetAddress& other )
00132 {
00133 _HostName = other._HostName;
00134 memcpy( _SockAddr, other._SockAddr, sizeof( *_SockAddr ) );
00135 _Valid = other._Valid;
00136 return *this;
00137 }
00138
00139
00140
00141
00142
00143 bool operator==( const CInetAddress& a1, const CInetAddress& a2 )
00144 {
00145
00146 return ( memcmp( a1._SockAddr, a2._SockAddr, sizeof(sockaddr_in)-8 ) == 0 );
00147 }
00148
00149
00150
00151
00152
00153 bool operator<( const CInetAddress& a1, const CInetAddress& a2 )
00154 {
00155 #ifdef NL_OS_WINDOWS
00156 if ( a1._SockAddr->sin_addr.S_un.S_addr == a2._SockAddr->sin_addr.S_un.S_addr )
00157 {
00158 return ( a1.port() < a2.port() );
00159 }
00160 else
00161 {
00162 return ( a1._SockAddr->sin_addr.S_un.S_addr < a2._SockAddr->sin_addr.S_un.S_addr );
00163 }
00164 #elif defined NL_OS_UNIX
00165 if ( a1._SockAddr->sin_addr.s_addr == a2._SockAddr->sin_addr.s_addr )
00166 {
00167 return ( a1.port() < a2.port() );
00168 }
00169 else
00170 {
00171 return ( a1._SockAddr->sin_addr.s_addr < a2._SockAddr->sin_addr.s_addr );
00172 }
00173 #endif
00174 }
00175
00176
00177
00178
00179
00180 void CInetAddress::init()
00181 {
00182 CSock::initNetwork();
00183
00184 _Valid = false;
00185
00186 _SockAddr = new sockaddr_in;
00187 _SockAddr->sin_family = AF_INET;
00188 memset( _SockAddr->sin_zero, 0, 8 );
00189 }
00190
00191
00192
00193
00194
00195 CInetAddress::~CInetAddress()
00196 {
00197 delete _SockAddr;
00198
00199 }
00200
00201
00202
00203
00204 void CInetAddress::setNameAndPort( const std::string& hostNameAndPort )
00205 {
00206 uint32 pos = hostNameAndPort.find_first_of (':');
00207 if (pos != string::npos)
00208 {
00209 setPort( atoi(hostNameAndPort.substr(pos + 1).c_str()) );
00210 }
00211 else
00212 {
00213 setPort( 0 );
00214 }
00215
00216
00217 setByName( hostNameAndPort.substr (0, pos) );
00218 }
00219
00220
00221
00222
00223
00224 CInetAddress& CInetAddress::setByName( const std::string& hostName )
00225 {
00226
00227 in_addr iaddr;
00228 #ifdef NL_OS_WINDOWS
00229 iaddr.S_un.S_addr = inet_addr( hostName.c_str() );
00230 if ( iaddr.S_un.S_addr == INADDR_NONE )
00231 #elif defined NL_OS_UNIX
00232 iaddr.s_addr = inet_addr( hostName.c_str() );
00233 if ( iaddr.s_addr == INADDR_NONE )
00234 #endif
00235 {
00236
00237
00238 hostent *phostent = gethostbyname( hostName.c_str() );
00239 if ( phostent == NULL )
00240 {
00241 _Valid = false;
00242 nldebug( "LNETL0: Network error: resolution of hostname '%s' failed", hostName.c_str() );
00243
00244 throw ESocket( (string("Hostname resolution failed for ")+hostName).c_str() );
00245 }
00246 _HostName = string( phostent->h_name );
00247 memcpy( &_SockAddr->sin_addr, phostent->h_addr, sizeof(in_addr) );
00248 }
00249 else
00250 {
00251 _HostName = hostName;
00252 memcpy( &_SockAddr->sin_addr, &iaddr, sizeof(iaddr) );
00253 }
00254 _Valid = true;
00255 return *this;
00256 }
00257
00258
00259
00260
00261
00262 void CInetAddress::setPort( uint16 port )
00263 {
00264 _SockAddr->sin_port = htons( port );
00265
00266 }
00267
00268
00269
00270
00271
00272 void CInetAddress::setSockAddr( const sockaddr_in* saddr )
00273 {
00274 memcpy( _SockAddr, saddr, sizeof(*saddr) );
00275
00276
00277
00278 if ( CInetAddress::RetrieveNames )
00279 {
00280 hostent *phostent = gethostbyaddr( (char*)&saddr->sin_addr.s_addr, 4, AF_INET );
00281 if ( phostent == NULL )
00282 {
00283 _HostName = ipAddress();
00284 }
00285 else
00286 {
00287 _HostName = string( phostent->h_name );
00288 }
00289 }
00290 _Valid = true;
00291 }
00292
00293
00294
00295
00296
00297 bool CInetAddress::isValid() const
00298 {
00299 return ( _Valid && _SockAddr->sin_port!=0 );
00300 }
00301
00302
00303
00304
00305
00306 const sockaddr_in *CInetAddress::sockAddr() const
00307 {
00308 return _SockAddr;
00309 }
00310
00311
00312
00313
00314
00315 uint32 CInetAddress::internalIPAddress() const
00316 {
00317 return _SockAddr->sin_addr.s_addr;
00318 }
00319
00320 uint32 CInetAddress::internalNetAddress() const
00321 {
00322 uint32 ip = internalIPAddress();
00323 if ((ip&0x00000080) == 0)
00324 {
00325
00326 return ip & 0x000000FF;
00327 }
00328 else if ((ip&0x00000040) == 0)
00329 {
00330
00331 return ip & 0x0000FFFF;
00332 }
00333 else if ((ip&0x00000020) == 0)
00334 {
00335
00336 return ip & 0x00FFFFFF;
00337 }
00338 else if ((ip&0x00000010) == 0)
00339 {
00340
00341 return ip & 0xFFFFFFFF;
00342 }
00343 else
00344 {
00345 return ip;
00346 }
00347 }
00348
00349
00350
00351
00352
00353
00354
00355 string CInetAddress::ipAddress() const
00356 {
00357
00358
00359
00360 return string( inet_ntoa( _SockAddr->sin_addr ) );
00361 }
00362
00363
00364
00365
00366
00367 const string& CInetAddress::hostName() const
00368 {
00369 return _HostName;
00370 }
00371
00372
00373
00374
00375
00376 uint16 CInetAddress::port() const
00377 {
00378 return ntohs( _SockAddr->sin_port );
00379 }
00380
00381
00382
00383
00384
00385 std::string CInetAddress::asString() const
00386 {
00387 stringstream ss;
00388 ss << hostName() << ":" << port() << " (" << ipAddress() << ")";
00389 return ss.str();
00390 }
00391
00392
00393
00394
00395
00396 std::string CInetAddress::asIPString() const
00397 {
00398 stringstream ss;
00399 ss << ipAddress() << ":" << port();
00400 return ss.str();
00401 }
00402
00403
00404
00405
00406
00407 void CInetAddress::serial( NLMISC::IStream& s )
00408 {
00409 NLMISC::CMemStream *ms = dynamic_cast<NLMISC::CMemStream*>(&s);
00410 if ( ms && ms->stringMode() )
00411 {
00412
00413 string addrs;
00414 if ( ms->isReading() )
00415 {
00416 ms->serial( addrs );
00417 setNameAndPort( addrs );
00418 }
00419 else
00420 {
00421 addrs = asIPString();
00422 ms->serial( addrs );
00423 }
00424 s.serial( _Valid );
00425 }
00426 else
00427 {
00428
00429 s.serialBuffer( (uint8*)_SockAddr, sizeof(*_SockAddr) );
00430 s.serial( _Valid );
00431
00432 if(_Valid)
00433 {
00434
00435 setSockAddr (_SockAddr);
00436 }
00437
00438 }
00439 }
00440
00441
00442
00443
00444
00445 CInetAddress CInetAddress::localHost()
00446 {
00447 const uint maxlength = 80;
00448 char localhost [maxlength];
00449 if ( gethostname( localhost, maxlength ) != 0 )
00450 throw ESocket( "Unable to get local hostname" );
00451 CInetAddress localaddr = CInetAddress( string(localhost) );
00452
00453 if ( localaddr.ipAddress() == "127.0.0.1" )
00454 {
00455 nlwarning ("*** No network card detected! using localhost (127.0.0.1)");
00456 }
00457
00458 return localaddr;
00459 }
00460
00461
00462
00463
00464
00465 std::vector<CInetAddress> CInetAddress::localAddresses()
00466 {
00467
00468 const uint maxlength = 80;
00469 char localhost [maxlength];
00470 if ( gethostname( localhost, maxlength ) == SOCKET_ERROR )
00471 {
00472 throw ESocket( "Unable to get local hostname" );
00473 }
00474
00475
00476 hostent *phostent = gethostbyname( localhost );
00477 if ( phostent == NULL )
00478 {
00479 throw ESocket( (string("Hostname resolution failed for ")+string(localhost)).c_str() );
00480 }
00481 uint i;
00482 vector<CInetAddress> vect;
00483 for ( i=0; phostent->h_addr_list[i]!=0; ++i )
00484 {
00485 vect.push_back( CInetAddress( (const in_addr*)(phostent->h_addr_list[i]) ) );
00486 }
00487
00488 if(vect.empty())
00489 {
00490 throw ESocket( (string("No network card detected for ")+string(localhost)).c_str() );
00491 }
00492
00493 return vect;
00494 }
00495
00496 bool CInetAddress::is127001 () const
00497 {
00498 return (internalIPAddress () == htonl(0x7F000001));
00499 }
00500
00501
00502 std::string vectorCInetAddressToString(const std::vector<CInetAddress> &addrs)
00503 {
00504 string str;
00505
00506 for (uint i = 0; i < addrs.size(); i++)
00507 {
00508 if (i != 0)
00509 str += " ";
00510 str += addrs[i].asString().c_str ();
00511 }
00512 return str;
00513 }
00514
00515 uint32 stringToInternalIPAddress (const std::string &addr)
00516 {
00517 return inet_addr( addr.c_str() );
00518 }
00519
00520 std::string internalIPAddressToString (uint32 addr)
00521 {
00522 string res;
00523 res = toString((addr)&0xFF);
00524 res += ".";
00525 res += toString((addr>>8)&0xFF);
00526 res += ".";
00527 res += toString((addr>>16)&0xFF);
00528 res += ".";
00529 res += toString((addr>>24)&0xFF);
00530 return res;
00531 }
00532
00533
00534 }