Merge with develop
This commit is contained in:
commit
5d9d57d541
2 changed files with 173 additions and 45 deletions
|
@ -24,7 +24,9 @@
|
||||||
|
|
||||||
|
|
||||||
struct sockaddr_in;
|
struct sockaddr_in;
|
||||||
|
struct sockaddr_in6;
|
||||||
struct in_addr;
|
struct in_addr;
|
||||||
|
struct in6_addr;
|
||||||
|
|
||||||
|
|
||||||
#ifdef NL_OS_WINDOWS
|
#ifdef NL_OS_WINDOWS
|
||||||
|
@ -89,17 +91,25 @@ public:
|
||||||
/// Sets hostname and port (ex: www.nevrax.com:80)
|
/// Sets hostname and port (ex: www.nevrax.com:80)
|
||||||
void setNameAndPort( const std::string& hostNameAndPort );
|
void setNameAndPort( const std::string& hostNameAndPort );
|
||||||
|
|
||||||
/** Sets internal socket address directly (contents is copied).
|
/** Sets internal IPv4 socket address directly (contents is copied).
|
||||||
* It also retrieves the host name if CInetAddress::RetrieveNames is true.
|
* It also retrieves the host name if CInetAddress::RetrieveNames is true.
|
||||||
*/
|
*/
|
||||||
void setSockAddr( const sockaddr_in* saddr );
|
void setSockAddr( const sockaddr_in* saddr );
|
||||||
|
|
||||||
|
/** Sets internal IPv6 socket address directly (contents is copied).
|
||||||
|
* It also retrieves the host name if CInetAddress::RetrieveNames is true.
|
||||||
|
*/
|
||||||
|
void setSockAddr6( const sockaddr_in6* saddr6 );
|
||||||
|
|
||||||
/// Returns if object (address and port) is valid
|
/// Returns if object (address and port) is valid
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
|
|
||||||
/// Returns internal socket address (read only)
|
/// Returns internal IPv4 socket address (read only)
|
||||||
const sockaddr_in *sockAddr() const;
|
const sockaddr_in *sockAddr() const;
|
||||||
|
|
||||||
|
/// Returns internal IPv6 socket address (read only)
|
||||||
|
const sockaddr_in6 *sockAddr6() const;
|
||||||
|
|
||||||
/// Returns internal IP address
|
/// Returns internal IP address
|
||||||
uint32 internalIPAddress() const;
|
uint32 internalIPAddress() const;
|
||||||
|
|
||||||
|
@ -140,9 +150,12 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/// Constructor with ip address, port=0
|
/// Constructor with IPv4 address, port=0
|
||||||
CInetAddress( const in_addr *ip, const char *hostname = 0);
|
CInetAddress( const in_addr *ip, const char *hostname = 0);
|
||||||
|
|
||||||
|
/// Constructor with IPv6 address, port=0
|
||||||
|
CInetAddress( const in6_addr *ip, const char *hostname = 0);
|
||||||
|
|
||||||
/// Update _HostName from _SockAddr
|
/// Update _HostName from _SockAddr
|
||||||
void updateHostName();
|
void updateHostName();
|
||||||
|
|
||||||
|
@ -153,6 +166,7 @@ private:
|
||||||
|
|
||||||
std::string _HostName;
|
std::string _HostName;
|
||||||
sockaddr_in *_SockAddr;
|
sockaddr_in *_SockAddr;
|
||||||
|
sockaddr_in6 *_SockAddr6;
|
||||||
bool _Valid;
|
bool _Valid;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#ifdef NL_OS_WINDOWS
|
#ifdef NL_OS_WINDOWS
|
||||||
# include <winsock2.h>
|
# include <winsock2.h>
|
||||||
# include <ws2tcpip.h>
|
# include <ws2tcpip.h>
|
||||||
|
# include <ws2ipdef.h>
|
||||||
// for Windows 2000 compatibility
|
// for Windows 2000 compatibility
|
||||||
# include <wspiapi.h>
|
# include <wspiapi.h>
|
||||||
#elif defined NL_OS_UNIX
|
#elif defined NL_OS_UNIX
|
||||||
|
@ -58,20 +59,32 @@ bool CInetAddress::RetrieveNames = false;
|
||||||
CInetAddress::CInetAddress()
|
CInetAddress::CInetAddress()
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
|
|
||||||
|
// IPv4
|
||||||
_SockAddr->sin_port = 0; // same as htons(0)
|
_SockAddr->sin_port = 0; // same as htons(0)
|
||||||
memset( &_SockAddr->sin_addr, 0, sizeof(in_addr) ); // same as htonl(INADDR_ANY)
|
memset( &_SockAddr->sin_addr, 0, sizeof(in_addr) ); // same as htonl(INADDR_ANY)
|
||||||
|
|
||||||
|
// IPv6
|
||||||
|
_SockAddr6->sin6_port = 0;
|
||||||
|
memset( &_SockAddr6->sin6_addr, 0, sizeof(in6_addr) ); // same as htonl(INADDR_ANY)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constructor with ip address, port=0
|
* Constructor with IPv4 address, port=0
|
||||||
*/
|
*/
|
||||||
CInetAddress::CInetAddress( const in_addr *ip, const char *hostname )
|
CInetAddress::CInetAddress( const in_addr *ip, const char *hostname )
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
|
|
||||||
|
// IPv4
|
||||||
_SockAddr->sin_port = 0;
|
_SockAddr->sin_port = 0;
|
||||||
memcpy( &_SockAddr->sin_addr, ip, sizeof(in_addr) );
|
memcpy( &_SockAddr->sin_addr, ip, sizeof(in_addr) );
|
||||||
|
|
||||||
|
// invalid IPv6
|
||||||
|
_SockAddr6->sin6_port = 0;
|
||||||
|
memset( &_SockAddr6->sin6_addr, 0, sizeof(in6_addr) );
|
||||||
|
|
||||||
// get the host name to be displayed
|
// get the host name to be displayed
|
||||||
if(hostname)
|
if(hostname)
|
||||||
{
|
{
|
||||||
|
@ -81,6 +94,36 @@ CInetAddress::CInetAddress( const in_addr *ip, const char *hostname )
|
||||||
{
|
{
|
||||||
updateHostName();
|
updateHostName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_Valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Constructor with IPv6 address, port=0
|
||||||
|
*/
|
||||||
|
CInetAddress::CInetAddress( const in6_addr *ip, const char *hostname )
|
||||||
|
{
|
||||||
|
init();
|
||||||
|
|
||||||
|
// IPv6
|
||||||
|
_SockAddr6->sin6_port = 0;
|
||||||
|
memcpy( &_SockAddr6->sin6_addr, ip, sizeof(in6_addr) );
|
||||||
|
|
||||||
|
// invalid IPv4
|
||||||
|
_SockAddr->sin_port = 0;
|
||||||
|
memset( &_SockAddr->sin_addr, 0, sizeof(in_addr) );
|
||||||
|
|
||||||
|
// get the host name to be displayed
|
||||||
|
if(hostname)
|
||||||
|
{
|
||||||
|
_HostName = hostname;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
updateHostName();
|
||||||
|
}
|
||||||
|
|
||||||
_Valid = true;
|
_Valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +135,20 @@ void CInetAddress::updateHostName()
|
||||||
{
|
{
|
||||||
char host[NI_MAXHOST];
|
char host[NI_MAXHOST];
|
||||||
|
|
||||||
sint status = getnameinfo((struct sockaddr *) _SockAddr, sizeof (struct sockaddr), host, NI_MAXHOST, NULL, 0, NI_NUMERICSERV);
|
// if unable to resolve DNS, returns an error and use IP address instead
|
||||||
|
sint status = 1;
|
||||||
|
|
||||||
|
// check if IPv4 is valid
|
||||||
|
if (_SockAddr->sin_addr.s_addr != 0)
|
||||||
|
{
|
||||||
|
// IPv4
|
||||||
|
status = getnameinfo((struct sockaddr *) _SockAddr, sizeof (sockaddr_in), host, NI_MAXHOST, NULL, 0, NI_NUMERICSERV | NI_NAMEREQD);
|
||||||
|
}
|
||||||
|
else if (!IN6_IS_ADDR_UNSPECIFIED(&_SockAddr6->sin6_addr))
|
||||||
|
{
|
||||||
|
// IPv6
|
||||||
|
status = getnameinfo((struct sockaddr *) _SockAddr6, sizeof (sockaddr_in6), host, NI_MAXHOST, NULL, 0, NI_NUMERICSERV | NI_NAMEREQD);
|
||||||
|
}
|
||||||
|
|
||||||
if ( status )
|
if ( status )
|
||||||
{
|
{
|
||||||
|
@ -134,6 +190,7 @@ CInetAddress::CInetAddress( const CInetAddress& other )
|
||||||
init();
|
init();
|
||||||
_HostName = other._HostName;
|
_HostName = other._HostName;
|
||||||
memcpy( _SockAddr, other._SockAddr, sizeof( *_SockAddr ) );
|
memcpy( _SockAddr, other._SockAddr, sizeof( *_SockAddr ) );
|
||||||
|
memcpy( _SockAddr6, other._SockAddr6, sizeof( *_SockAddr6 ) );
|
||||||
_Valid = other._Valid;
|
_Valid = other._Valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,6 +202,7 @@ CInetAddress& CInetAddress::operator=( const CInetAddress& other )
|
||||||
{
|
{
|
||||||
_HostName = other._HostName;
|
_HostName = other._HostName;
|
||||||
memcpy( _SockAddr, other._SockAddr, sizeof( *_SockAddr ) );
|
memcpy( _SockAddr, other._SockAddr, sizeof( *_SockAddr ) );
|
||||||
|
memcpy( _SockAddr6, other._SockAddr6, sizeof( *_SockAddr6 ) );
|
||||||
_Valid = other._Valid;
|
_Valid = other._Valid;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -185,9 +243,15 @@ void CInetAddress::init()
|
||||||
|
|
||||||
_Valid = false;
|
_Valid = false;
|
||||||
|
|
||||||
|
// IPv4
|
||||||
_SockAddr = new sockaddr_in;
|
_SockAddr = new sockaddr_in;
|
||||||
|
memset(_SockAddr, 0, sizeof(_SockAddr));
|
||||||
_SockAddr->sin_family = AF_INET;
|
_SockAddr->sin_family = AF_INET;
|
||||||
memset( _SockAddr->sin_zero, 0, 8 );
|
|
||||||
|
// IPv6
|
||||||
|
_SockAddr6 = new sockaddr_in6;
|
||||||
|
memset(_SockAddr6, 0, sizeof(_SockAddr6));
|
||||||
|
_SockAddr6->sin6_family = AF_INET6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -197,6 +261,7 @@ void CInetAddress::init()
|
||||||
CInetAddress::~CInetAddress()
|
CInetAddress::~CInetAddress()
|
||||||
{
|
{
|
||||||
delete _SockAddr;
|
delete _SockAddr;
|
||||||
|
delete _SockAddr6;
|
||||||
// _Valid = false;
|
// _Valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,12 +290,41 @@ void CInetAddress::setNameAndPort( const std::string& hostNameAndPort )
|
||||||
/*
|
/*
|
||||||
* Resolves a name
|
* Resolves a name
|
||||||
*/
|
*/
|
||||||
CInetAddress& CInetAddress::setByName( const std::string& hostName )
|
CInetAddress& CInetAddress::setByName(const std::string& hostName)
|
||||||
{
|
{
|
||||||
// Try to convert directly for addresses such as a.b.c.d
|
// invalid IPv4
|
||||||
in_addr iaddr;
|
memset(&_SockAddr->sin_addr, 0, sizeof(in_addr));
|
||||||
iaddr.s_addr = inet_addr( hostName.c_str() );
|
|
||||||
if ( iaddr.s_addr == INADDR_NONE )
|
// invalid IPv6
|
||||||
|
memset(&_SockAddr6->sin6_addr, 0, sizeof(in6_addr));
|
||||||
|
|
||||||
|
// Try to convert directly for addresses such as a.b.c.d and a:b:c:d:e:f:g:h
|
||||||
|
in_addr ipv4;
|
||||||
|
sint res = inet_pton(AF_INET, hostName.c_str(), &ipv4);
|
||||||
|
|
||||||
|
if (res == 1)
|
||||||
|
{
|
||||||
|
// hostname is a valid IPv4
|
||||||
|
memcpy(&_SockAddr->sin_addr, &ipv4, sizeof(in_addr));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
in6_addr ipv6;
|
||||||
|
res = inet_pton(AF_INET6, hostName.c_str(), &ipv6);
|
||||||
|
|
||||||
|
if (res == 1)
|
||||||
|
{
|
||||||
|
// hostname is a valid IPv6
|
||||||
|
memcpy(&_SockAddr6->sin6_addr, &ipv6, sizeof(in6_addr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res == 1)
|
||||||
|
{
|
||||||
|
// use IPv4 or IPv6 as hostname
|
||||||
|
_HostName = hostName;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
// Otherwise use the traditional DNS look-up
|
// Otherwise use the traditional DNS look-up
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
|
@ -249,6 +343,9 @@ CInetAddress& CInetAddress::setByName( const std::string& hostName )
|
||||||
throw ESocket( (string("Hostname resolution failed for ")+hostName).c_str() );
|
throw ESocket( (string("Hostname resolution failed for ")+hostName).c_str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hostname is valid, use it
|
||||||
|
_HostName = hostName;
|
||||||
|
|
||||||
struct addrinfo *p = res;
|
struct addrinfo *p = res;
|
||||||
|
|
||||||
// process all addresses
|
// process all addresses
|
||||||
|
@ -260,20 +357,14 @@ CInetAddress& CInetAddress::setByName( const std::string& hostName )
|
||||||
// ipv4
|
// ipv4
|
||||||
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
|
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
|
||||||
|
|
||||||
// convert the IP to a string
|
|
||||||
_HostName = string(inet_ntoa(ipv4->sin_addr));
|
|
||||||
memcpy( &_SockAddr->sin_addr, &ipv4->sin_addr, sizeof(in_addr) );
|
memcpy( &_SockAddr->sin_addr, &ipv4->sin_addr, sizeof(in_addr) );
|
||||||
}
|
}
|
||||||
else if (p->ai_family == AF_INET6)
|
else if (p->ai_family == AF_INET6)
|
||||||
{
|
{
|
||||||
// ipv6
|
// ipv6
|
||||||
// TODO: modify class to be able to handle IPv6
|
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
|
||||||
|
|
||||||
// struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
|
memcpy( &_SockAddr6->sin6_addr, &ipv6->sin6_addr, sizeof(in6_addr) );
|
||||||
|
|
||||||
// convert the IP to a string
|
|
||||||
// inet_ntop(p->ai_family, addr, ipstr, sizeof(ipstr));
|
|
||||||
// memcpy( &_SockAddr->sin_addr, &ipv6->sin_addr, sizeof(in_addr) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// process next address
|
// process next address
|
||||||
|
@ -283,11 +374,7 @@ CInetAddress& CInetAddress::setByName( const std::string& hostName )
|
||||||
// free the linked list
|
// free the linked list
|
||||||
freeaddrinfo(res);
|
freeaddrinfo(res);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
_HostName = hostName;
|
|
||||||
memcpy( &_SockAddr->sin_addr, &iaddr, sizeof(iaddr) );
|
|
||||||
}
|
|
||||||
_Valid = true;
|
_Valid = true;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -296,10 +383,10 @@ CInetAddress& CInetAddress::setByName( const std::string& hostName )
|
||||||
/*
|
/*
|
||||||
* Sets port
|
* Sets port
|
||||||
*/
|
*/
|
||||||
void CInetAddress::setPort( uint16 port )
|
void CInetAddress::setPort(uint16 port)
|
||||||
{
|
{
|
||||||
_SockAddr->sin_port = htons( port );
|
_SockAddr->sin_port = htons(port);
|
||||||
|
_SockAddr6->sin6_port = htons(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -308,7 +395,10 @@ void CInetAddress::setPort( uint16 port )
|
||||||
*/
|
*/
|
||||||
void CInetAddress::setSockAddr( const sockaddr_in* saddr )
|
void CInetAddress::setSockAddr( const sockaddr_in* saddr )
|
||||||
{
|
{
|
||||||
memcpy( _SockAddr, saddr, sizeof(*saddr) );
|
memcpy(_SockAddr, saddr, sizeof(*saddr) );
|
||||||
|
|
||||||
|
// invalid IPv6
|
||||||
|
memset(&_SockAddr6->sin6_addr, 0, sizeof(in6_addr));
|
||||||
|
|
||||||
// Get host name
|
// Get host name
|
||||||
// Warning: when it can't find it, it take more than 4 seconds
|
// Warning: when it can't find it, it take more than 4 seconds
|
||||||
|
@ -316,6 +406,28 @@ void CInetAddress::setSockAddr( const sockaddr_in* saddr )
|
||||||
{
|
{
|
||||||
updateHostName();
|
updateHostName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_Valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Sets internal socket address directly (contents is copied).
|
||||||
|
* It also retrieves the host name if CInetAddress::RetrieveNames is true.
|
||||||
|
*/
|
||||||
|
void CInetAddress::setSockAddr6( const sockaddr_in6* saddr6 )
|
||||||
|
{
|
||||||
|
memcpy( _SockAddr6, saddr6, sizeof(*saddr6) );
|
||||||
|
|
||||||
|
// invalid IPv4
|
||||||
|
memset(&_SockAddr->sin_addr, 0, sizeof(in_addr));
|
||||||
|
|
||||||
|
// Get host name
|
||||||
|
// Warning: when it can't find it, it take more than 4 seconds
|
||||||
|
if ( CInetAddress::RetrieveNames )
|
||||||
|
{
|
||||||
|
updateHostName();
|
||||||
|
}
|
||||||
|
|
||||||
_Valid = true;
|
_Valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,7 +442,7 @@ bool CInetAddress::isValid() const
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns internal socket address (read only)
|
* Returns internal IPv4 socket address (read only)
|
||||||
*/
|
*/
|
||||||
const sockaddr_in *CInetAddress::sockAddr() const
|
const sockaddr_in *CInetAddress::sockAddr() const
|
||||||
{
|
{
|
||||||
|
@ -338,6 +450,15 @@ const sockaddr_in *CInetAddress::sockAddr() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns internal IPv6 socket address (read only)
|
||||||
|
*/
|
||||||
|
const sockaddr_in6 *CInetAddress::sockAddr6() const
|
||||||
|
{
|
||||||
|
return _SockAddr6;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns internal IP address
|
* Returns internal IP address
|
||||||
*/
|
*/
|
||||||
|
@ -383,10 +504,13 @@ uint32 CInetAddress::internalNetAddress() const
|
||||||
*/
|
*/
|
||||||
string CInetAddress::ipAddress() const
|
string CInetAddress::ipAddress() const
|
||||||
{
|
{
|
||||||
/*stringstream ss; // or use inet_ntoa
|
// longer size is IPv6
|
||||||
ss << inet_ntoa ( _SockAddr->sin_addr );
|
char straddr[INET6_ADDRSTRLEN];
|
||||||
return ss.str();*/
|
const char *name = inet_ntop(AF_INET, &_SockAddr->sin_addr, straddr, INET_ADDRSTRLEN);
|
||||||
const char *name = inet_ntoa ( _SockAddr->sin_addr );
|
|
||||||
|
// IPv4 is invalid, return IPv6
|
||||||
|
if (name == NULL || strcmp(name, "0.0.0.0") == 0) name = inet_ntop(AF_INET6, &_SockAddr6->sin6_addr, straddr, INET6_ADDRSTRLEN);
|
||||||
|
|
||||||
return name ? string (name) : "";
|
return name ? string (name) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,9 +538,6 @@ uint16 CInetAddress::port() const
|
||||||
*/
|
*/
|
||||||
std::string CInetAddress::asString() const
|
std::string CInetAddress::asString() const
|
||||||
{
|
{
|
||||||
// stringstream ss;
|
|
||||||
// ss << hostName() << ":" << port() << " (" << ipAddress() << ")";
|
|
||||||
// return ss.str();
|
|
||||||
return hostName() + ":" + NLMISC::toString(port()) + " (" + ipAddress() + ")";
|
return hostName() + ":" + NLMISC::toString(port()) + " (" + ipAddress() + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -426,9 +547,6 @@ std::string CInetAddress::asString() const
|
||||||
*/
|
*/
|
||||||
std::string CInetAddress::asIPString() const
|
std::string CInetAddress::asIPString() const
|
||||||
{
|
{
|
||||||
// stringstream ss;
|
|
||||||
// ss << ipAddress() << ":" << port();
|
|
||||||
// return ss.str();
|
|
||||||
return ipAddress() + ":" + NLMISC::toString(port());
|
return ipAddress() + ":" + NLMISC::toString(port());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,13 +655,9 @@ std::vector<CInetAddress> CInetAddress::localAddresses()
|
||||||
else if (p->ai_family == AF_INET6)
|
else if (p->ai_family == AF_INET6)
|
||||||
{
|
{
|
||||||
// ipv6
|
// ipv6
|
||||||
// TODO: modify class to be able to handle IPv6
|
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
|
||||||
|
|
||||||
// struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
|
vect.push_back( CInetAddress( &ipv6->sin6_addr, localhost ) );
|
||||||
|
|
||||||
// convert the IP to a string
|
|
||||||
// inet_ntop(p->ai_family, addr, ipstr, sizeof(ipstr));
|
|
||||||
// memcpy( &_SockAddr->sin_addr, &ipv6->sin_addr, sizeof(in_addr) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// process next address
|
// process next address
|
||||||
|
|
Loading…
Reference in a new issue