35 if( f == Address::Family::ipv4 && Address4::af() == 0 )
37 else if( f == Address::Family::ipv6 && Address6::af() == 0 )
39 else if( f == Address::Family::local && AddressLocal::af() == 0 )
47 return af == Address4::af() || af == Address6::af() || af == AddressLocal::af() ;
52 return domain == Address4::domain() || domain == Address6::domain() || domain == AddressLocal::domain() ;
57 if( Address4::af() && f == Address::Family::ipv4 )
58 m_ipv4 = std::make_unique<Address4>(
port ) ;
59 else if( Address6::af() && f == Address::Family::ipv6 )
60 m_ipv6 = std::make_unique<Address6>(
port ) ;
61 else if( AddressLocal::af() && f == Address::Family::local )
62 m_local = std::make_unique<AddressLocal>(
port ) ;
64 throw Address::BadFamily() ;
69 if( addr ==
nullptr || len <
static_cast<socklen_t
>(
sizeof(sockaddr::sa_family)) )
70 throw Address::Error() ;
71 else if( addr->sa_family == 0 )
72 throw Address::BadFamily() ;
73 else if( Address4::af() && addr->sa_family == Address4::af() )
74 m_ipv4 = std::make_unique<Address4>( addr , len ) ;
75 else if( Address6::af() && addr->sa_family == Address6::af() )
76 m_ipv6 = std::make_unique<Address6>( addr , len , ipv6_scope_id_fixup ) ;
77 else if( AddressLocal::af() && addr->sa_family == AddressLocal::af() )
78 m_local = std::make_unique<AddressLocal>( addr , len ) ;
80 throw Address::BadFamily() ;
89 Address(storage.p(),storage.n(),false)
96 throw Address::Error(
"empty string" ) ;
100 if( with_local && AddressLocal::af() && isFamilyLocal(s) )
101 m_local = std::make_unique<AddressLocal>( s ) ;
102 else if( Address4::af() && Address4::validString(s,&r1) )
103 m_ipv4 = std::make_unique<Address4>( s ) ;
104 else if( Address6::af() && Address6::validString(s,&r2) )
105 m_ipv6 = std::make_unique<Address6>( s ) ;
112 if( host_part.empty() )
113 throw Address::Error(
"empty string" ) ;
117 if( AddressLocal::af() && isFamilyLocal( host_part ) )
118 m_local = std::make_unique<AddressLocal>( host_part ) ;
119 else if( Address4::af() && Address4::validStrings(host_part,port_part,&r1) )
120 m_ipv4 = std::make_unique<Address4>( host_part , port_part ) ;
121 else if( Address6::af() && Address6::validStrings(host_part,port_part,&r2) )
122 m_ipv6 = std::make_unique<Address6>( host_part , port_part ) ;
128 Address(host_part,
G::Str::fromUInt(port))
134 if( Address4::af() && f == Address::Family::ipv4 )
135 m_ipv4 = std::make_unique<Address4>( port , loopback_overload ) ;
136 else if( Address6::af() && f == Address::Family::ipv6 )
137 m_ipv6 = std::make_unique<Address6>( port , loopback_overload ) ;
138 else if( AddressLocal::af() && f == Address::Family::local )
139 m_local = std::make_unique<AddressLocal>( port , loopback_overload ) ;
141 throw Address::BadFamily() ;
146 G_ASSERT( other.m_ipv4 || other.m_ipv6 || other.m_local ) ;
148 m_ipv4 = std::make_unique<Address4>( *other.m_ipv4 ) ;
150 m_ipv6 = std::make_unique<Address6>( *other.m_ipv6 ) ;
152 m_local = std::make_unique<AddressLocal>( *other.m_local ) ;
164 swap( m_ipv4 , other.m_ipv4 ) ;
165 swap( m_ipv6 , other.m_ipv6 ) ;
166 swap( m_local , other.m_local ) ;
180 return { s ,
true } ;
185 return { s ,
false } ;
190 return { host_part , port } ;
196 return { host_part , port_part } ;
202 return supports( Family::local ) && !s.empty() && s[0] ==
'/' ;
207 return { Family::ipv4 , 0U } ;
212 return { f , port , 1 } ;
222 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
223 if( m_ipv4 ) m_ipv4->setPort( port ) ;
224 if( m_ipv6 ) m_ipv6->setPort( port ) ;
225 if( m_local ) m_local->setPort( port ) ;
232 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
233 if( m_ipv4 ) m_ipv4->setZone( ipv6_zone ) ;
234 if( m_ipv6 ) m_ipv6->setZone( ipv6_zone ) ;
235 if( m_local ) m_local->setZone( ipv6_zone ) ;
242 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
243 if( m_ipv4 ) m_ipv4->setScopeId( ipv6_scope_id ) ;
244 if( m_ipv6 ) m_ipv6->setScopeId( ipv6_scope_id ) ;
245 if( m_local ) m_local->setScopeId( ipv6_scope_id ) ;
251 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
252 if( m_ipv4 )
return m_ipv4->bits() ;
253 if( m_ipv6 )
return m_ipv6->bits() ;
254 if( m_local )
return m_local->bits() ;
260 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
262 ( m_ipv4 && m_ipv4->isLoopback() ) ||
263 ( m_ipv6 && m_ipv6->isLoopback() ) ||
264 ( m_local && m_local->isLoopback() ) ;
269 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
271 ( m_ipv4 && m_ipv4->isLocal(reason) ) ||
272 ( m_ipv6 && m_ipv6->isLocal(reason) ) ||
273 ( m_local && m_local->isLocal(reason) ) ;
278 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
280 ( m_ipv4 && m_ipv4->isLinkLocal() ) ||
281 ( m_ipv6 && m_ipv6->isLinkLocal() ) ||
282 ( m_local && m_local->isLinkLocal() ) ;
288 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
290 ( m_ipv4 && m_ipv4->isMulticast() ) ||
291 ( m_ipv6 && m_ipv6->isMulticast() ) ||
292 ( m_local && m_local->isMulticast() ) ;
298 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
300 ( m_ipv4 && m_ipv4->isUniqueLocal() ) ||
301 ( m_ipv6 && m_ipv6->isUniqueLocal() ) ||
302 ( m_local && m_local->isUniqueLocal() ) ;
307 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
309 ( m_ipv4 && m_ipv4->isAny() ) ||
310 ( m_ipv6 && m_ipv6->isAny() ) ||
311 ( m_local && m_local->isAny() ) ;
326 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
328 ( m_ipv4 && other.m_ipv4 && m_ipv4->same(*other.m_ipv4,ipv6_compare_with_scope) ) ||
329 ( m_ipv6 && other.m_ipv6 && m_ipv6->same(*other.m_ipv6,ipv6_compare_with_scope) ) ||
330 ( m_local && other.m_local && m_local->same(*other.m_local,ipv6_compare_with_scope) ) ;
335 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
337 ( m_ipv4 && other.m_ipv4 && m_ipv4->same(*other.m_ipv4) ) ||
338 ( m_ipv6 && other.m_ipv6 && m_ipv6->same(*other.m_ipv6) ) ||
339 ( m_local && other.m_local && m_local->same(*other.m_local) ) ;
344 return !( *
this == other ) ;
350 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
352 ( m_ipv4 && other.m_ipv4 && m_ipv4->sameHostPart(*other.m_ipv4) ) ||
353 ( m_ipv6 && other.m_ipv6 && m_ipv6->sameHostPart(*other.m_ipv6) ) ||
354 ( m_local && other.m_local && m_local->sameHostPart(*other.m_local) ) ;
360 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
361 if( m_ipv4 )
return m_ipv4->displayString( ipv6_with_scope_id ) ;
362 if( m_ipv6 )
return m_ipv6->displayString( ipv6_with_scope_id ) ;
363 if( m_local )
return m_local->displayString( ipv6_with_scope_id ) ;
369 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
370 if( m_ipv4 )
return m_ipv4->hostPartString() ;
371 if( m_ipv6 )
return m_ipv6->hostPartString() ;
372 if( m_local )
return m_local->hostPartString() ;
378 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
379 if( m_ipv4 )
return m_ipv4->queryString() ;
380 if( m_ipv6 )
return m_ipv6->queryString() ;
381 if( m_local )
return m_local->queryString() ;
388 Address4::validString( s , reason_p ) ||
389 Address6::validString( s , reason_p ) ||
390 AddressLocal::validString( s , reason_p ) ;
396 Address4::validString( s , reason_p ) ||
397 Address6::validString( s , reason_p ) ;
403 Address4::validStrings( s1 , s2 , reason_p ) ||
404 Address6::validStrings( s1 , s2 , reason_p ) ||
405 AddressLocal::validStrings( s1 , s2 , reason_p ) ;
411 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
412 if( m_ipv4 )
return m_ipv4->address() ;
413 if( m_ipv6 )
return m_ipv6->address() ;
414 if( m_local )
return m_local->address() ;
421 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
422 if( m_ipv4 )
return m_ipv4->address() ;
423 if( m_ipv6 )
return m_ipv6->address() ;
424 if( m_local )
return m_local->address() ;
430 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
431 if( m_ipv4 )
return Address4::length() ;
432 if( m_ipv6 )
return Address6::length() ;
433 if( m_local )
return m_local->length() ;
439 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
440 if( m_ipv4 )
return m_ipv4->port() ;
441 if( m_ipv6 )
return m_ipv6->port() ;
442 if( m_local )
return m_local->port() ;
448 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
449 if( m_ipv4 )
return m_ipv4->scopeId( default_ ) ;
450 if( m_ipv6 )
return m_ipv6->scopeId( default_ ) ;
451 if( m_local )
return m_local->scopeId( default_ ) ;
457 return Address4::validPort( port ) ;
463 Address4::validData( addr , len ) ||
464 Address6::validData( addr , len ) ||
465 AddressLocal::validData( addr , len ) ;
470 if( family == Family::ipv4 )
return Address4::domain() ;
471 if( family == Family::ipv6 )
return Address6::domain() ;
472 if( family == Family::local )
return AddressLocal::domain() ;
478 if( m_ipv4 )
return Family::ipv4 ;
479 if( m_ipv6 )
return Family::ipv6 ;
480 if( m_local )
return Family::local ;
481 return Family::ipv4 ;
486 if( m_ipv4 )
return Address4::af() ;
487 if( m_ipv6 )
return Address6::af() ;
488 if( m_local )
return AddressLocal::af() ;
494 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
495 if( m_ipv4 )
return m_ipv4->wildcards() ;
496 if( m_ipv6 )
return m_ipv6->wildcards() ;
497 if( m_local )
return m_local->wildcards() ;
506class GNet::AddressStorageImp
516 m_imp(
std::make_unique<AddressStorageImp>())
518 static_assert(
sizeof(Address4::sockaddr_type) <=
sizeof(sockaddr_storage) ,
"" ) ;
519 static_assert(
sizeof(Address6::sockaddr_type) <=
sizeof(sockaddr_storage) ,
"" ) ;
520 static_assert(
sizeof(AddressLocal::sockaddr_type) <=
sizeof(sockaddr_storage) ,
"" ) ;
522 static_assert(
alignof(Address4::sockaddr_type) <=
alignof(sockaddr_storage) ,
"" ) ;
523 static_assert(
alignof(Address6::sockaddr_type) <=
alignof(sockaddr_storage) ,
"" ) ;
524 static_assert(
alignof(AddressLocal::sockaddr_type) <=
alignof(sockaddr_storage) ,
"" ) ;
526 m_imp->n =
sizeof( sockaddr_storage ) ;
534 return reinterpret_cast<sockaddr*
>(&(m_imp->u)) ;
544 return reinterpret_cast<const sockaddr*
>(&(m_imp->u)) ;
554#if ! GCONFIG_HAVE_INET_PTON
557int GNet::inet_pton_imp(
int f ,
const char * p ,
void * result )
559 if( p ==
nullptr || result ==
nullptr )
return 0 ;
560 struct addrinfo ai_hint ;
561 std::memset( &ai_hint , 0 ,
sizeof(ai_hint) ) ;
562 ai_hint.ai_family = f ;
563 ai_hint.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV ;
564 struct addrinfo * ai_p = nullptr ;
565 int rc = getaddrinfo( p ,
nullptr , &ai_hint , &ai_p ) ;
566 bool ok = rc == 0 && ai_p != nullptr ;
567 if( ok && ai_p->ai_addr ==
nullptr ) { freeaddrinfo(ai_p) ;
return 1 ; }
570 struct sockaddr * sa_p = ai_p->ai_addr ;
571 if( ai_p->ai_family == AF_INET )
573 struct sockaddr_in sa ;
574 std::memcpy( &sa , sa_p ,
sizeof(sa) ) ;
575 std::memcpy( result , &sa.sin_addr ,
sizeof(sa.sin_addr) ) ;
577 else if( ai_p->ai_family == AF_INET6 )
579 struct sockaddr_in6 sa ;
580 std::memcpy( &sa , sa_p ,
sizeof(sa) ) ;
581 std::memcpy( result , &sa.sin6_addr ,
sizeof(sa.sin6_addr) ) ;
587 freeaddrinfo( ai_p ) ;
594#if ! GCONFIG_HAVE_INET_NTOP
597const char * GNet::inet_ntop_imp(
int f ,
void * ap ,
char * buffer , std::size_t n )
602 std::ostringstream ss ;
604 std::memcpy( &a , ap ,
sizeof(a) ) ;
605 ss << inet_ntoa( a ) ;
608 else if( f == AF_INET6 )
611 std::memcpy( &a , ap ,
sizeof(a) ) ;
612 std::ostringstream ss ;
613 const char * sep =
":" ;
614 const char * hexmap =
"0123456789abcdef" ;
615 for(
int i = 0 ; i < 16 ; i++ , sep = *sep ?
"" :
":" )
617 unsigned int nn =
static_cast<unsigned int>(a.s6_addr[i]) % 256U ;
618 ss << sep << hexmap[(nn>>4U)%16U] << hexmap[(nn&15U)%16U] ;
623 for( std::string::size_type pos = s.find(
":0") ; pos != std::string::npos ; pos = s.find(
":0",pos) )
626 while( s.at(pos) ==
'0' && s.at(pos+1U) !=
':' )
627 s.erase( pos , 1U ) ;
630 std::string run =
":0:0:0:0:0:0:0:0:" ;
631 while( run.length() >= 5U )
633 std::string::size_type pos = s.find( run ) ;
634 if( pos != std::string::npos )
636 std::string::size_type r = 2U ;
637 if( pos == 0U ) r++ ;
638 if( (pos + run.length()) == s.length() ) r++ ;
639 s.replace( pos , run.length() , std::string(
"::::").substr(0U,r) ) ;
642 run.erase( 0U , 2U ) ;
645 G_ASSERT( s.length() > 2U ) ;
647 s.erase( s.length()-1U , 1U ) ;
654 if( n <= s.length() )
return nullptr ;
655 std::strncpy( buffer , s.c_str() , n ) ;
A helper class for calling accept(), getsockname() and getpeername() and hiding the definition of soc...
sockaddr * p1()
Returns the sockaddr pointer for accept()/getsockname()/getpeername() to write into.
const sockaddr * p() const
Returns the pointer, typically set via p1().
socklen_t * p2()
Returns the length pointer for accept()/getsockname()/getpeername() to write into.
AddressStorage()
Default constructor, with n() reflecting the size of the largest supported address type.
~AddressStorage()
Destructor.
socklen_t n() const
Returns the length, typically modified via p2().
The GNet::Address class encapsulates a TCP/UDP transport address.
bool setZone(const std::string &)
Sets the zone.
Address & setScopeId(unsigned long)
Sets the scope-id.
Address(const Address &)
Copy constructor.
bool is6() const noexcept
Returns true if family() is ipv6.
bool operator!=(const Address &) const
Comparison operator.
bool isLinkLocal() const
Returns true if this is a link-local address.
bool operator==(const Address &) const
Comparison operator.
static bool isFamilyLocal(const std::string &display_string) noexcept
Returns true if the given address display string looks will parse to Family::local and Family::local ...
int af() const noexcept
Returns the address family number such as AF_INET or AFINET6.
std::string queryString() const
Returns a string that can be used as a prefix for rDNS or DNSBL queries.
G::StringArray wildcards() const
Returns an ordered list of wildcard strings that match this address.
static bool validData(const sockaddr *, socklen_t len)
Returns true if the sockaddr data is valid.
static int domain(Family) noexcept
Returns the address 'domain' for the given family, eg.
static Address loopback(Family, unsigned int port=0U)
Returns a loopback address.
bool is4() const noexcept
Returns true if family() is ipv4.
static bool validPort(unsigned int n)
Returns true if the port number is within the valid range.
bool isUniqueLocal() const
Returns true if this is a locally administered address.
static bool validStrings(const std::string &ip, const std::string &port_string, std::string *reason=nullptr)
Returns true if the combined network-address string and port string is valid.
void swap(Address &other) noexcept
Swaps this with other.
socklen_t length() const
Returns the size of the sockaddr address. See address().
bool isLocal(std::string &reason) const
Returns true if this seems to be a 'local' address, ie.
static Address defaultAddress()
Returns a default address, being the IPv4 wildcard address with a zero port number.
Address & operator=(const Address &)
Assignment operator.
bool isAny() const
Returns true if this is the address family's 'any' address.
static Address parse(const std::string &display_string)
Factory function for any address family.
static bool validString(const std::string &display_string, std::string *reason=nullptr)
Returns true if the transport-address display string is valid.
static bool supports(Family) noexcept
Returns true if the implementation supports the given address family.
bool sameHostPart(const Address &other) const
Returns true if the two addresses have the same host part (ie.
unsigned int bits() const
Returns the number of leading bits set, relevant only to netmask addresses.
std::string displayString(bool with_scope_id=false) const
Returns a printable string that represents the transport address.
unsigned int port() const
Returns port part of the address.
std::string hostPartString() const
Returns a printable string that represents the network address.
bool isMulticast() const
Returns true if this is a multicast address.
bool isLoopback() const
Returns true if this is a loopback address.
const sockaddr * address() const
Returns the sockaddr address.
unsigned long scopeId(unsigned long default_=0UL) const
Returns the scope-id.
Address & setPort(unsigned int port)
Sets the port number.
Family family() const noexcept
Returns the address family enumeration.
bool same(const Address &, bool ipv6_compare_with_scope) const
Comparison function.
A structure that holds a network address as a string with no dependency on any low-level network libr...
static std::string printable(const std::string &in, char escape='\\')
Returns a printable representation of the given input string, using chacter code ranges 0x20 to 0x7e ...
std::vector< std::string > StringArray
A std::vector of std::strings.
Overload discriminator for Address::supports()
Overload discriminator for Address::parse()