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 } ;
195 return { host_part , port_part } ;
200 return supports( Family::local ) && !s.empty() && s[0] ==
'/' ;
205 return { Family::ipv4 , 0U } ;
210 return { f , port , 1 } ;
220 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
221 if( m_ipv4 ) m_ipv4->setPort( port ) ;
222 if( m_ipv6 ) m_ipv6->setPort( port ) ;
223 if( m_local ) m_local->setPort( port ) ;
230 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
231 if( m_ipv4 ) m_ipv4->setZone( ipv6_zone ) ;
232 if( m_ipv6 ) m_ipv6->setZone( ipv6_zone ) ;
233 if( m_local ) m_local->setZone( ipv6_zone ) ;
240 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
241 if( m_ipv4 ) m_ipv4->setScopeId( ipv6_scope_id ) ;
242 if( m_ipv6 ) m_ipv6->setScopeId( ipv6_scope_id ) ;
243 if( m_local ) m_local->setScopeId( ipv6_scope_id ) ;
249 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
250 if( m_ipv4 )
return m_ipv4->bits() ;
251 if( m_ipv6 )
return m_ipv6->bits() ;
252 if( m_local )
return m_local->bits() ;
258 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
260 ( m_ipv4 && m_ipv4->isLoopback() ) ||
261 ( m_ipv6 && m_ipv6->isLoopback() ) ||
262 ( m_local && m_local->isLoopback() ) ;
267 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
269 ( m_ipv4 && m_ipv4->isLocal(reason) ) ||
270 ( m_ipv6 && m_ipv6->isLocal(reason) ) ||
271 ( m_local && m_local->isLocal(reason) ) ;
276 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
278 ( m_ipv4 && m_ipv4->isLinkLocal() ) ||
279 ( m_ipv6 && m_ipv6->isLinkLocal() ) ||
280 ( m_local && m_local->isLinkLocal() ) ;
286 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
288 ( m_ipv4 && m_ipv4->isMulticast() ) ||
289 ( m_ipv6 && m_ipv6->isMulticast() ) ||
290 ( m_local && m_local->isMulticast() ) ;
296 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
298 ( m_ipv4 && m_ipv4->isUniqueLocal() ) ||
299 ( m_ipv6 && m_ipv6->isUniqueLocal() ) ||
300 ( m_local && m_local->isUniqueLocal() ) ;
305 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
307 ( m_ipv4 && m_ipv4->isAny() ) ||
308 ( m_ipv6 && m_ipv6->isAny() ) ||
309 ( m_local && m_local->isAny() ) ;
324 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
326 ( m_ipv4 && other.m_ipv4 && m_ipv4->same(*other.m_ipv4,ipv6_compare_with_scope) ) ||
327 ( m_ipv6 && other.m_ipv6 && m_ipv6->same(*other.m_ipv6,ipv6_compare_with_scope) ) ||
328 ( m_local && other.m_local && m_local->same(*other.m_local,ipv6_compare_with_scope) ) ;
333 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
335 ( m_ipv4 && other.m_ipv4 && m_ipv4->same(*other.m_ipv4) ) ||
336 ( m_ipv6 && other.m_ipv6 && m_ipv6->same(*other.m_ipv6) ) ||
337 ( m_local && other.m_local && m_local->same(*other.m_local) ) ;
342 return !( *
this == other ) ;
348 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
350 ( m_ipv4 && other.m_ipv4 && m_ipv4->sameHostPart(*other.m_ipv4) ) ||
351 ( m_ipv6 && other.m_ipv6 && m_ipv6->sameHostPart(*other.m_ipv6) ) ||
352 ( m_local && other.m_local && m_local->sameHostPart(*other.m_local) ) ;
358 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
359 if( m_ipv4 )
return m_ipv4->displayString( ipv6_with_scope_id ) ;
360 if( m_ipv6 )
return m_ipv6->displayString( ipv6_with_scope_id ) ;
361 if( m_local )
return m_local->displayString( ipv6_with_scope_id ) ;
367 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
368 if( m_ipv4 )
return m_ipv4->hostPartString() ;
369 if( m_ipv6 )
return m_ipv6->hostPartString() ;
370 if( m_local )
return m_local->hostPartString() ;
376 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
377 if( m_ipv4 )
return m_ipv4->queryString() ;
378 if( m_ipv6 )
return m_ipv6->queryString() ;
379 if( m_local )
return m_local->queryString() ;
386 Address4::validString( s , reason_p ) ||
387 Address6::validString( s , reason_p ) ||
388 AddressLocal::validString( s , reason_p ) ;
394 Address4::validString( s , reason_p ) ||
395 Address6::validString( s , reason_p ) ;
401 Address4::validStrings( s1 , s2 , reason_p ) ||
402 Address6::validStrings( s1 , s2 , reason_p ) ||
403 AddressLocal::validStrings( s1 , s2 , reason_p ) ;
409 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
410 if( m_ipv4 )
return m_ipv4->address() ;
411 if( m_ipv6 )
return m_ipv6->address() ;
412 if( m_local )
return m_local->address() ;
419 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
420 if( m_ipv4 )
return m_ipv4->address() ;
421 if( m_ipv6 )
return m_ipv6->address() ;
422 if( m_local )
return m_local->address() ;
428 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
429 if( m_ipv4 )
return Address4::length() ;
430 if( m_ipv6 )
return Address6::length() ;
431 if( m_local )
return m_local->length() ;
437 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
438 if( m_ipv4 )
return m_ipv4->port() ;
439 if( m_ipv6 )
return m_ipv6->port() ;
440 if( m_local )
return m_local->port() ;
446 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
447 if( m_ipv4 )
return m_ipv4->scopeId( default_ ) ;
448 if( m_ipv6 )
return m_ipv6->scopeId( default_ ) ;
449 if( m_local )
return m_local->scopeId( default_ ) ;
455 return Address4::validPort( port ) ;
461 Address4::validData( addr , len ) ||
462 Address6::validData( addr , len ) ||
463 AddressLocal::validData( addr , len ) ;
468 if( family == Family::ipv4 )
return Address4::domain() ;
469 if( family == Family::ipv6 )
return Address6::domain() ;
470 if( family == Family::local )
return AddressLocal::domain() ;
476 if( m_ipv4 )
return Family::ipv4 ;
477 if( m_ipv6 )
return Family::ipv6 ;
478 if( m_local )
return Family::local ;
479 return Family::ipv4 ;
484 if( m_ipv4 )
return Address4::af() ;
485 if( m_ipv6 )
return Address6::af() ;
486 if( m_local )
return AddressLocal::af() ;
492 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
493 if( m_ipv4 )
return m_ipv4->wildcards() ;
494 if( m_ipv6 )
return m_ipv6->wildcards() ;
495 if( m_local )
return m_local->wildcards() ;
504class GNet::AddressStorageImp
514 m_imp(
std::make_unique<AddressStorageImp>())
516 static_assert(
sizeof(Address4::sockaddr_type) <=
sizeof(sockaddr_storage) ,
"" ) ;
517 static_assert(
sizeof(Address6::sockaddr_type) <=
sizeof(sockaddr_storage) ,
"" ) ;
518 static_assert(
sizeof(AddressLocal::sockaddr_type) <=
sizeof(sockaddr_storage) ,
"" ) ;
520 static_assert(
alignof(Address4::sockaddr_type) <=
alignof(sockaddr_storage) ,
"" ) ;
521 static_assert(
alignof(Address6::sockaddr_type) <=
alignof(sockaddr_storage) ,
"" ) ;
522 static_assert(
alignof(AddressLocal::sockaddr_type) <=
alignof(sockaddr_storage) ,
"" ) ;
524 m_imp->n =
sizeof( sockaddr_storage ) ;
532 return reinterpret_cast<sockaddr*
>(&(m_imp->u)) ;
542 return reinterpret_cast<const sockaddr*
>(&(m_imp->u)) ;
552#if ! GCONFIG_HAVE_INET_PTON
555int GNet::inet_pton_imp(
int f ,
const char * p ,
void * result )
557 if( p ==
nullptr || result ==
nullptr )
return 0 ;
558 struct addrinfo ai_hint ;
559 std::memset( &ai_hint , 0 ,
sizeof(ai_hint) ) ;
560 ai_hint.ai_family = f ;
561 ai_hint.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV ;
562 struct addrinfo * ai_p = nullptr ;
563 int rc = getaddrinfo( p ,
nullptr , &ai_hint , &ai_p ) ;
564 bool ok = rc == 0 && ai_p != nullptr ;
565 if( ok && ai_p->ai_addr ==
nullptr ) { freeaddrinfo(ai_p) ;
return 1 ; }
568 struct sockaddr * sa_p = ai_p->ai_addr ;
569 if( ai_p->ai_family == AF_INET )
571 struct sockaddr_in sa ;
572 std::memcpy( &sa , sa_p ,
sizeof(sa) ) ;
573 std::memcpy( result , &sa.sin_addr ,
sizeof(sa.sin_addr) ) ;
575 else if( ai_p->ai_family == AF_INET6 )
577 struct sockaddr_in6 sa ;
578 std::memcpy( &sa , sa_p ,
sizeof(sa) ) ;
579 std::memcpy( result , &sa.sin6_addr ,
sizeof(sa.sin6_addr) ) ;
585 freeaddrinfo( ai_p ) ;
592#if ! GCONFIG_HAVE_INET_NTOP
595const char * GNet::inet_ntop_imp(
int f ,
void * ap ,
char * buffer , std::size_t n )
600 std::ostringstream ss ;
602 std::memcpy( &a , ap ,
sizeof(a) ) ;
603 ss << inet_ntoa( a ) ;
606 else if( f == AF_INET6 )
609 std::memcpy( &a , ap ,
sizeof(a) ) ;
610 std::ostringstream ss ;
611 const char * sep =
":" ;
612 const char * hexmap =
"0123456789abcdef" ;
613 for(
int i = 0 ; i < 16 ; i++ , sep = *sep ?
"" :
":" )
615 unsigned int nn =
static_cast<unsigned int>(a.s6_addr[i]) % 256U ;
616 ss << sep << hexmap[(nn>>4U)%16U] << hexmap[(nn&15U)%16U] ;
621 for( std::string::size_type pos = s.find(
":0") ; pos != std::string::npos ; pos = s.find(
":0",pos) )
624 while( s.at(pos) ==
'0' && s.at(pos+1U) !=
':' )
625 s.erase( pos , 1U ) ;
628 std::string run =
":0:0:0:0:0:0:0:0:" ;
629 while( run.length() >= 5U )
631 std::string::size_type pos = s.find( run ) ;
632 if( pos != std::string::npos )
634 std::string::size_type r = 2U ;
635 if( pos == 0U ) r++ ;
636 if( (pos + run.length()) == s.length() ) r++ ;
637 s.replace( pos , run.length() , std::string(
"::::").substr(0U,r) ) ;
640 run.erase( 0U , 2U ) ;
643 G_ASSERT( s.length() > 2U ) ;
645 s.erase( s.length()-1U , 1U ) ;
652 if( n <= s.length() )
return nullptr ;
653 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.
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 bool validString(std::string_view display_string, std::string *reason=nullptr)
Returns true if the transport-address display string is valid.
static bool validStrings(std::string_view ip, std::string_view port_string, std::string *reason=nullptr)
Returns true if the combined network-address string and port string is valid.
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.
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 bool isFamilyLocal(std::string_view display_string) noexcept
Returns true if the given address display string looks will parse to Family::local and Family::local ...
static Address parse(std::string_view display_string)
Factory function for any address family.
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()