E-MailRelay
gaddress.cpp
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2023 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file gaddress.cpp
19///
20
21#include "gdef.h"
22#include "gaddress4.h"
23#include "gaddress6.h"
24#include "gaddresslocal.h"
25#include "gaddress.h"
26#include "gstr.h"
27#include "gassert.h"
28#include <algorithm> // std::swap()
29#include <utility> // std::swap()
30#include <sstream>
31#include <cstring>
32
33bool GNet::Address::supports( Family f ) noexcept
34{
35 if( f == Address::Family::ipv4 && Address4::af() == 0 )
36 return false ; // fwiw
37 else if( f == Address::Family::ipv6 && Address6::af() == 0 )
38 return false ; // fwiw
39 else if( f == Address::Family::local && AddressLocal::af() == 0 )
40 return false ;
41 else
42 return true ;
43}
44
45bool GNet::Address::supports( int af , int ) noexcept
46{
47 return af == Address4::af() || af == Address6::af() || af == AddressLocal::af() ;
48}
49
50bool GNet::Address::supports( const Address::Domain & , int domain ) noexcept
51{
52 return domain == Address4::domain() || domain == Address6::domain() || domain == AddressLocal::domain() ;
53}
54
55GNet::Address::Address( Family f , unsigned int port )
56{
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 ) ;
63 else
64 throw Address::BadFamily() ;
65}
66
67GNet::Address::Address( const sockaddr * addr , socklen_t len , bool ipv6_scope_id_fixup )
68{
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 ) ;
79 else
80 throw Address::BadFamily() ;
81}
82
83GNet::Address::Address( const sockaddr * addr , socklen_t len ) :
84 Address(addr,len,false)
85{
86}
87
89 Address(storage.p(),storage.n(),false)
90{
91}
92
93GNet::Address::Address( const std::string & s , bool with_local )
94{
95 if( s.empty() )
96 throw Address::Error( "empty string" ) ;
97
98 std::string r1 ;
99 std::string r2 ;
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 ) ;
106 else
107 throw Address::Error( r1 , r1==r2?std::string():r2 , G::Str::printable(s) ) ;
108}
109
110GNet::Address::Address( const std::string & host_part , const std::string & port_part )
111{
112 if( host_part.empty() )
113 throw Address::Error( "empty string" ) ;
114
115 std::string r1 ;
116 std::string r2 ;
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 ) ;
123 else
124 throw Address::Error( r1 , r1==r2?std::string():r2 , G::Str::printable(host_part) , G::Str::printable(port_part) ) ;
125}
126
127GNet::Address::Address( const std::string & host_part , unsigned int port ) :
128 Address(host_part,G::Str::fromUInt(port))
129{
130}
131
132GNet::Address::Address( Family f , unsigned int port , int loopback_overload )
133{
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 ) ;
140 else
141 throw Address::BadFamily() ;
142}
143
145{
146 G_ASSERT( other.m_ipv4 || other.m_ipv6 || other.m_local ) ;
147 if( other.m_ipv4 )
148 m_ipv4 = std::make_unique<Address4>( *other.m_ipv4 ) ;
149 if( other.m_ipv6 )
150 m_ipv6 = std::make_unique<Address6>( *other.m_ipv6 ) ;
151 if( other.m_local )
152 m_local = std::make_unique<AddressLocal>( *other.m_local ) ;
153}
154
155GNet::Address::Address( Address && other ) noexcept
156= default ;
157
159= default;
160
161void GNet::Address::swap( Address & other ) noexcept
162{
163 using std::swap ;
164 swap( m_ipv4 , other.m_ipv4 ) ;
165 swap( m_ipv6 , other.m_ipv6 ) ;
166 swap( m_local , other.m_local ) ;
167}
168
170{
171 Address(other).swap( *this ) ;
172 return *this ;
173}
174
176= default ;
177
178GNet::Address GNet::Address::parse( const std::string & s )
179{
180 return { s , true } ;
181}
182
184{
185 return { s , false } ;
186}
187
188GNet::Address GNet::Address::parse( const std::string & host_part , unsigned int port )
189{
190 return { host_part , port } ;
191}
192
193#ifndef G_LIB_SMALL
194GNet::Address GNet::Address::parse( const std::string & host_part , const std::string & port_part )
195{
196 return { host_part , port_part } ;
197}
198#endif
199
200bool GNet::Address::isFamilyLocal( const std::string & s ) noexcept
201{
202 return supports( Family::local ) && !s.empty() && s[0] == '/' ;
203}
204
206{
207 return { Family::ipv4 , 0U } ;
208}
209
210GNet::Address GNet::Address::loopback( Family f , unsigned int port )
211{
212 return { f , port , 1 } ;
213}
214
215GNet::Address::operator G::BasicAddress() const
216{
217 return G::BasicAddress( displayString() ) ;
218}
219
221{
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 ) ;
226 return *this ;
227}
228
229#ifndef G_LIB_SMALL
230bool GNet::Address::setZone( const std::string & ipv6_zone )
231{
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 ) ;
236 return true ;
237}
238#endif
239
240GNet::Address & GNet::Address::setScopeId( unsigned long ipv6_scope_id )
241{
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 ) ;
246 return *this ;
247}
248
249unsigned int GNet::Address::bits() const
250{
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() ;
255 return 0U ;
256}
257
259{
260 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
261 return
262 ( m_ipv4 && m_ipv4->isLoopback() ) ||
263 ( m_ipv6 && m_ipv6->isLoopback() ) ||
264 ( m_local && m_local->isLoopback() ) ;
265}
266
267bool GNet::Address::isLocal( std::string & reason ) const
268{
269 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
270 return
271 ( m_ipv4 && m_ipv4->isLocal(reason) ) ||
272 ( m_ipv6 && m_ipv6->isLocal(reason) ) ||
273 ( m_local && m_local->isLocal(reason) ) ;
274}
275
277{
278 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
279 return
280 ( m_ipv4 && m_ipv4->isLinkLocal() ) ||
281 ( m_ipv6 && m_ipv6->isLinkLocal() ) ||
282 ( m_local && m_local->isLinkLocal() ) ;
283}
284
285#ifndef G_LIB_SMALL
287{
288 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
289 return
290 ( m_ipv4 && m_ipv4->isMulticast() ) ||
291 ( m_ipv6 && m_ipv6->isMulticast() ) ||
292 ( m_local && m_local->isMulticast() ) ;
293}
294#endif
295
297{
298 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
299 return
300 ( m_ipv4 && m_ipv4->isUniqueLocal() ) ||
301 ( m_ipv6 && m_ipv6->isUniqueLocal() ) ||
302 ( m_local && m_local->isUniqueLocal() ) ;
303}
304
306{
307 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
308 return
309 ( m_ipv4 && m_ipv4->isAny() ) ||
310 ( m_ipv6 && m_ipv6->isAny() ) ||
311 ( m_local && m_local->isAny() ) ;
312}
313
314bool GNet::Address::is4() const noexcept
315{
316 return !!m_ipv4 ;
317}
318
319bool GNet::Address::is6() const noexcept
320{
321 return !!m_ipv6 ;
322}
323
324bool GNet::Address::same( const Address & other , bool ipv6_compare_with_scope ) const
325{
326 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
327 return
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) ) ;
331}
332
333bool GNet::Address::operator==( const Address & other ) const
334{
335 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
336 return
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) ) ;
340}
341
342bool GNet::Address::operator!=( const Address & other ) const
343{
344 return !( *this == other ) ;
345}
346
347#ifndef G_LIB_SMALL
348bool GNet::Address::sameHostPart( const Address & other ) const
349{
350 G_ASSERT( m_ipv4 || m_ipv6 || m_local ) ;
351 return
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) ) ;
355}
356#endif
357
358std::string GNet::Address::displayString( bool ipv6_with_scope_id ) const
359{
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 ) ;
364 return {} ;
365}
366
368{
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() ;
373 return {} ;
374}
375
376std::string GNet::Address::queryString() const
377{
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() ;
382 return {} ;
383}
384
385bool GNet::Address::validString( const std::string & s , std::string * reason_p )
386{
387 return
388 Address4::validString( s , reason_p ) ||
389 Address6::validString( s , reason_p ) ||
390 AddressLocal::validString( s , reason_p ) ;
391}
392
393bool GNet::Address::validString( const std::string & s , NotLocal , std::string * reason_p )
394{
395 return
396 Address4::validString( s , reason_p ) ||
397 Address6::validString( s , reason_p ) ;
398}
399
400bool GNet::Address::validStrings( const std::string & s1 , const std::string & s2 , std::string * reason_p )
401{
402 return
403 Address4::validStrings( s1 , s2 , reason_p ) ||
404 Address6::validStrings( s1 , s2 , reason_p ) ||
405 AddressLocal::validStrings( s1 , s2 , reason_p ) ;
406}
407
408#ifndef G_LIB_SMALL
410{
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() ;
415 return nullptr ;
416}
417#endif
418
419const sockaddr * GNet::Address::address() const
420{
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() ;
425 return nullptr ;
426}
427
428socklen_t GNet::Address::length() const
429{
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() ;
434 return 0 ;
435}
436
437unsigned int GNet::Address::port() const
438{
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() ;
443 return 0 ;
444}
445
446unsigned long GNet::Address::scopeId( unsigned long default_ ) const
447{
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_ ) ;
452 return default_ ;
453}
454
455bool GNet::Address::validPort( unsigned int port )
456{
457 return Address4::validPort( port ) ;
458}
459
460bool GNet::Address::validData( const sockaddr * addr , socklen_t len )
461{
462 return
463 Address4::validData( addr , len ) ||
464 Address6::validData( addr , len ) ||
465 AddressLocal::validData( addr , len ) ;
466}
467
468int GNet::Address::domain( Family family ) noexcept
469{
470 if( family == Family::ipv4 ) return Address4::domain() ;
471 if( family == Family::ipv6 ) return Address6::domain() ;
472 if( family == Family::local ) return AddressLocal::domain() ;
473 return 0 ;
474}
475
476GNet::Address::Family GNet::Address::family() const noexcept
477{
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 ;
482}
483
484int GNet::Address::af() const noexcept
485{
486 if( m_ipv4 ) return Address4::af() ;
487 if( m_ipv6 ) return Address6::af() ;
488 if( m_local ) return AddressLocal::af() ;
489 return 0 ;
490}
491
493{
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() ;
498 return {} ;
499}
500
501// ===
502
503//| \class GNet::AddressStorageImp
504/// A pimple-pattern implementation class used by GNet::AddressStorage.
505///
506class GNet::AddressStorageImp
507{
508public:
509 sockaddr_storage u ;
510 socklen_t n ;
511} ;
512
513// ==
514
516 m_imp(std::make_unique<AddressStorageImp>())
517{
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) , "" ) ;
521
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) , "" ) ;
525
526 m_imp->n = sizeof( sockaddr_storage ) ;
527}
528
530= default ;
531
533{
534 return reinterpret_cast<sockaddr*>(&(m_imp->u)) ;
535}
536
538{
539 return &m_imp->n ;
540}
541
542const sockaddr * GNet::AddressStorage::p() const
543{
544 return reinterpret_cast<const sockaddr*>(&(m_imp->u)) ;
545}
546
547socklen_t GNet::AddressStorage::n() const
548{
549 return m_imp->n ;
550}
551
552// ==
553
554#if ! GCONFIG_HAVE_INET_PTON
555// fallback implementation for inet_pton() using getaddrinfo() -- see gdef.h
556#ifndef G_LIB_SMALL
557int GNet::inet_pton_imp( int f , const char * p , void * result )
558{
559 if( p == nullptr || result == nullptr ) return 0 ; // just in case
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 ; } // just in case
568 if( ok )
569 {
570 struct sockaddr * sa_p = ai_p->ai_addr ;
571 if( ai_p->ai_family == AF_INET )
572 {
573 struct sockaddr_in sa ;
574 std::memcpy( &sa , sa_p , sizeof(sa) ) ;
575 std::memcpy( result , &sa.sin_addr , sizeof(sa.sin_addr) ) ;
576 }
577 else if( ai_p->ai_family == AF_INET6 )
578 {
579 struct sockaddr_in6 sa ;
580 std::memcpy( &sa , sa_p , sizeof(sa) ) ;
581 std::memcpy( result , &sa.sin6_addr , sizeof(sa.sin6_addr) ) ;
582 }
583 else
584 {
585 ok = false ;
586 }
587 freeaddrinfo( ai_p ) ;
588 }
589 return ok ? 1 : 0 ;
590}
591#endif
592#endif
593
594#if ! GCONFIG_HAVE_INET_NTOP
595// fallback implementation for inet_ntop() using inet_ntoa() for ipv4 and by hand for ipv6 -- see gdef.h
596#ifndef G_LIB_SMALL
597const char * GNet::inet_ntop_imp( int f , void * ap , char * buffer , std::size_t n )
598{
599 std::string s ;
600 if( f == AF_INET )
601 {
602 std::ostringstream ss ;
603 struct in_addr a ;
604 std::memcpy( &a , ap , sizeof(a) ) ;
605 ss << inet_ntoa( a ) ; // ignore warnings - this code is not used if inet_ntop is available
606 s = ss.str() ;
607 }
608 else if( f == AF_INET6 )
609 {
610 struct in6_addr a ;
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 ? "" : ":" ) // sep alternates
616 {
617 unsigned int nn = static_cast<unsigned int>(a.s6_addr[i]) % 256U ;
618 ss << sep << hexmap[(nn>>4U)%16U] << hexmap[(nn&15U)%16U] ;
619 }
620 ss << ":" ;
621 // eg. ":0001:0002:0000:0000:0005:0006:dead:beef:"
622 s = ss.str() ;
623 for( std::string::size_type pos = s.find(":0") ; pos != std::string::npos ; pos = s.find(":0",pos) )
624 {
625 pos += 1U ;
626 while( s.at(pos) == '0' && s.at(pos+1U) != ':' )
627 s.erase( pos , 1U ) ;
628 }
629 // eg. ":1:2:0:0:5:6:dead:beef:"
630 std::string run = ":0:0:0:0:0:0:0:0:" ;
631 while( run.length() >= 5U ) // (single zero fields are not elided)
632 {
633 std::string::size_type pos = s.find( run ) ;
634 if( pos != std::string::npos )
635 {
636 std::string::size_type r = 2U ; // ":1:0:0:2:" -> ":1::2:"
637 if( pos == 0U ) r++ ; // ":0:0:1:2:" -> ":::1:2:"
638 if( (pos + run.length()) == s.length() ) r++ ; // ":1:0:0:" -> ":1:::", ":0:0:0:" -> "::::"
639 s.replace( pos , run.length() , std::string("::::").substr(0U,r) ) ;
640 break ;
641 }
642 run.erase( 0U , 2U ) ;
643 }
644 // eg. ":1:2::5:6:dead:beef:"
645 G_ASSERT( s.length() > 2U ) ;
646 s.erase( 0U , 1U ) ;
647 s.erase( s.length()-1U , 1U ) ;
648 // eg. "1:2::5:6:dead:beef"
649 }
650 else
651 {
652 return nullptr ;
653 }
654 if( n <= s.length() ) return nullptr ;
655 std::strncpy( buffer , s.c_str() , n ) ;
656 return buffer ;
657}
658#endif
659#endif
660
A helper class for calling accept(), getsockname() and getpeername() and hiding the definition of soc...
Definition: gaddress.h:309
sockaddr * p1()
Returns the sockaddr pointer for accept()/getsockname()/getpeername() to write into.
Definition: gaddress.cpp:532
const sockaddr * p() const
Returns the pointer, typically set via p1().
Definition: gaddress.cpp:542
socklen_t * p2()
Returns the length pointer for accept()/getsockname()/getpeername() to write into.
Definition: gaddress.cpp:537
AddressStorage()
Default constructor, with n() reflecting the size of the largest supported address type.
Definition: gaddress.cpp:515
~AddressStorage()
Destructor.
socklen_t n() const
Returns the length, typically modified via p2().
Definition: gaddress.cpp:547
The GNet::Address class encapsulates a TCP/UDP transport address.
Definition: gaddress.h:62
bool setZone(const std::string &)
Sets the zone.
Definition: gaddress.cpp:230
Address & setScopeId(unsigned long)
Sets the scope-id.
Definition: gaddress.cpp:240
Address(const Address &)
Copy constructor.
Definition: gaddress.cpp:144
bool is6() const noexcept
Returns true if family() is ipv6.
Definition: gaddress.cpp:319
bool operator!=(const Address &) const
Comparison operator.
Definition: gaddress.cpp:342
bool isLinkLocal() const
Returns true if this is a link-local address.
Definition: gaddress.cpp:276
bool operator==(const Address &) const
Comparison operator.
Definition: gaddress.cpp:333
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 ...
Definition: gaddress.cpp:200
int af() const noexcept
Returns the address family number such as AF_INET or AFINET6.
Definition: gaddress.cpp:484
std::string queryString() const
Returns a string that can be used as a prefix for rDNS or DNSBL queries.
Definition: gaddress.cpp:376
G::StringArray wildcards() const
Returns an ordered list of wildcard strings that match this address.
Definition: gaddress.cpp:492
static bool validData(const sockaddr *, socklen_t len)
Returns true if the sockaddr data is valid.
Definition: gaddress.cpp:460
static int domain(Family) noexcept
Returns the address 'domain' for the given family, eg.
Definition: gaddress.cpp:468
static Address loopback(Family, unsigned int port=0U)
Returns a loopback address.
Definition: gaddress.cpp:210
bool is4() const noexcept
Returns true if family() is ipv4.
Definition: gaddress.cpp:314
static bool validPort(unsigned int n)
Returns true if the port number is within the valid range.
Definition: gaddress.cpp:455
bool isUniqueLocal() const
Returns true if this is a locally administered address.
Definition: gaddress.cpp:296
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.
Definition: gaddress.cpp:400
void swap(Address &other) noexcept
Swaps this with other.
Definition: gaddress.cpp:161
socklen_t length() const
Returns the size of the sockaddr address. See address().
Definition: gaddress.cpp:428
bool isLocal(std::string &reason) const
Returns true if this seems to be a 'local' address, ie.
Definition: gaddress.cpp:267
static Address defaultAddress()
Returns a default address, being the IPv4 wildcard address with a zero port number.
Definition: gaddress.cpp:205
Address & operator=(const Address &)
Assignment operator.
Definition: gaddress.cpp:169
bool isAny() const
Returns true if this is the address family's 'any' address.
Definition: gaddress.cpp:305
~Address()
Destructor.
static Address parse(const std::string &display_string)
Factory function for any address family.
Definition: gaddress.cpp:178
static bool validString(const std::string &display_string, std::string *reason=nullptr)
Returns true if the transport-address display string is valid.
Definition: gaddress.cpp:385
static bool supports(Family) noexcept
Returns true if the implementation supports the given address family.
Definition: gaddress.cpp:33
bool sameHostPart(const Address &other) const
Returns true if the two addresses have the same host part (ie.
Definition: gaddress.cpp:348
unsigned int bits() const
Returns the number of leading bits set, relevant only to netmask addresses.
Definition: gaddress.cpp:249
std::string displayString(bool with_scope_id=false) const
Returns a printable string that represents the transport address.
Definition: gaddress.cpp:358
unsigned int port() const
Returns port part of the address.
Definition: gaddress.cpp:437
std::string hostPartString() const
Returns a printable string that represents the network address.
Definition: gaddress.cpp:367
bool isMulticast() const
Returns true if this is a multicast address.
Definition: gaddress.cpp:286
bool isLoopback() const
Returns true if this is a loopback address.
Definition: gaddress.cpp:258
const sockaddr * address() const
Returns the sockaddr address.
Definition: gaddress.cpp:419
unsigned long scopeId(unsigned long default_=0UL) const
Returns the scope-id.
Definition: gaddress.cpp:446
Address & setPort(unsigned int port)
Sets the port number.
Definition: gaddress.cpp:220
Family family() const noexcept
Returns the address family enumeration.
Definition: gaddress.cpp:476
bool same(const Address &, bool ipv6_compare_with_scope) const
Comparison function.
Definition: gaddress.cpp:324
A structure that holds a network address as a string with no dependency on any low-level network libr...
Definition: gbasicaddress.h:37
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 ...
Definition: gstr.cpp:916
Low-level classes.
Definition: garg.h:30
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstringarray.h:30
STL namespace.
Overload discriminator for Address::supports()
Definition: gaddress.h:71
Overload discriminator for Address::parse()
Definition: gaddress.h:125