gaddress_ipv4.cpp
Go to the documentation of this file.
1 //
2 // Copyright (C) 2001-2013 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 // gaddress_ipv4.cpp
19 //
20 
21 #include "gdef.h"
22 #include "gnet.h"
23 #include "gaddress.h"
24 #include "gstrings.h"
25 #include "gstr.h"
26 #include "gassert.h"
27 #include "gdebug.h"
28 #include <climits>
29 #include <algorithm> // std::swap
30 #include <utility> // std::swap
31 #include <sys/types.h>
32 
37 {
38 public:
39  typedef sockaddr general_type ;
40  typedef sockaddr_in address_type ;
41  typedef sockaddr storage_type ;
43  union Sockaddr
44  { address_type specific ; general_type general ; storage_type storage ; } ;
45 
46  explicit AddressImp( unsigned int port ) ; // (not in_port_t -- see validPort(), setPort() etc)
47  explicit AddressImp( const servent & s ) ;
48  explicit AddressImp( const std::string & s ) ;
49  AddressImp( const std::string & s , unsigned int port ) ;
50  AddressImp( unsigned int port , Address::Localhost ) ;
51  AddressImp( unsigned int port , Address::Broadcast ) ;
52  AddressImp( const hostent & h , unsigned int port ) ;
53  AddressImp( const hostent & h , const servent & s ) ;
54  AddressImp( const sockaddr * addr , size_t len ) ;
55  AddressImp( const AddressImp & other ) ;
56 
57  const sockaddr * raw() const ;
58  sockaddr * raw() ;
59 
60  unsigned int port() const ;
61  void setPort( unsigned int port ) ;
62 
63  static bool validString( const std::string & s , std::string * reason_p = NULL ) ;
64  static bool validPort( unsigned int port ) ;
65 
66  bool same( const AddressImp & other ) const ;
67  bool sameHost( const AddressImp & other ) const ;
68  static G::Strings wildcards( const std::string & display_string ) ;
69 
70  std::string displayString() const ;
71  std::string hostString() const ;
72 
73 private:
74  void init() ;
75  static unsigned short family() ;
76  void set( const sockaddr * general ) ;
77  bool setAddress( const std::string & display_string , std::string & reason ) ;
78  static bool validPart( const std::string & s ) ;
79  static bool validPortNumber( const std::string & s ) ;
80  static bool validNumber( const std::string & s ) ;
81  void setHost( const hostent & h ) ;
82  static bool sameAddr( const ::in_addr & a , const ::in_addr & b ) ;
83  static char portSeparator() ;
84  static void add( G::Strings & , const std::string & , unsigned int , const char * ) ;
85  static void add( G::Strings & , const std::string & , const char * ) ;
86 
87 private:
88  Sockaddr m_inet ;
89 } ;
90 
91 // ===
92 
97 {
98 public:
100  socklen_t n ;
101 } ;
102 
103 // ===
104 
105 unsigned short GNet::AddressImp::family()
106 {
107  return AF_INET ;
108 }
109 
110 void GNet::AddressImp::init()
111 {
112  static address_type zero ;
113  m_inet.specific = zero ;
114  m_inet.specific.sin_family = family() ;
115  m_inet.specific.sin_port = 0 ;
116 }
117 
118 GNet::AddressImp::AddressImp( unsigned int port )
119 {
120  init() ;
121  m_inet.specific.sin_addr.s_addr = htonl(INADDR_ANY);
122  setPort( port ) ;
123 }
124 
126 {
127  init() ;
128  m_inet.specific.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
129  setPort( port ) ;
130 }
131 
133 {
134  init() ;
135  m_inet.specific.sin_addr.s_addr = htonl(INADDR_BROADCAST);
136  setPort( port ) ;
137 }
138 
139 GNet::AddressImp::AddressImp( const hostent & h , unsigned int port )
140 {
141  init() ;
142  setHost( h ) ;
143  setPort( port ) ;
144 }
145 
146 GNet::AddressImp::AddressImp( const hostent & h , const servent & s )
147 {
148  init() ;
149  setHost( h ) ;
150  m_inet.specific.sin_port = s.s_port ;
151 }
152 
153 GNet::AddressImp::AddressImp( const servent & s )
154 {
155  init() ;
156  m_inet.specific.sin_addr.s_addr = htonl(INADDR_ANY);
157  m_inet.specific.sin_port = s.s_port ;
158 }
159 
160 GNet::AddressImp::AddressImp( const sockaddr * addr , size_t len )
161 {
162  init() ;
163 
164  if( addr == NULL )
165  throw Address::Error() ;
166 
167  if( addr->sa_family != family() || len != sizeof(address_type) )
168  throw Address::BadFamily() ;
169 
170  set( addr ) ;
171 }
172 
174 {
175  m_inet = other.m_inet ;
176 }
177 
178 GNet::AddressImp::AddressImp( const std::string & s , unsigned int port )
179 {
180  init() ;
181 
182  std::string reason ;
183  if( ! setAddress( s + portSeparator() + "0" , reason ) )
184  throw Address::BadString( reason + ": " + s ) ;
185 
186  setPort( port ) ;
187 }
188 
189 GNet::AddressImp::AddressImp( const std::string & s )
190 {
191  init() ;
192 
193  std::string reason ;
194  if( ! setAddress( s , reason ) )
195  throw Address::BadString( reason + ": " + s ) ;
196 }
197 
198 bool GNet::AddressImp::setAddress( const std::string & display_string , std::string & reason )
199 {
200  if( !validString(display_string,&reason) )
201  return false ;
202 
203  const std::string::size_type pos = display_string.rfind(portSeparator()) ;
204  std::string host_part = display_string.substr(0U,pos) ;
205  std::string port_part = display_string.substr(pos+1U) ;
206 
207  m_inet.specific.sin_family = family() ;
208  m_inet.specific.sin_addr.s_addr = ::inet_addr( host_part.c_str() ) ;
209  setPort( G::Str::toUInt(port_part) ) ;
210 
211  G_ASSERT( displayString() == display_string ) ;
212  return true ;
213 }
214 
215 void GNet::AddressImp::setPort( unsigned int port )
216 {
217  if( ! validPort(port) )
218  throw Address::Error( "invalid port number" ) ;
219 
220  const g_port_t in_port = static_cast<g_port_t>(port) ;
221  m_inet.specific.sin_port = htons( in_port ) ;
222 }
223 
224 void GNet::AddressImp::setHost( const hostent & h )
225 {
226  if( h.h_addrtype != family() || h.h_addr_list[0] == NULL )
227  throw Address::BadFamily() ;
228 
229  const char * first = h.h_addr_list[0U] ;
230  const in_addr * raw = reinterpret_cast<const in_addr*>(first) ;
231  m_inet.specific.sin_addr = *raw ;
232 }
233 
235 {
236  std::ostringstream ss ;
237  ss << hostString() ;
238  ss << portSeparator() << port() ;
239  return ss.str() ;
240 }
241 
242 std::string GNet::AddressImp::hostString() const
243 {
244  std::ostringstream ss ;
245  ss << ::inet_ntoa(m_inet.specific.sin_addr) ;
246  return ss.str() ;
247 }
248 
249 bool GNet::AddressImp::validPort( unsigned int port )
250 {
251  return port <= 0xFFFFU ; // port numbers are now explicitly 16 bits, not short ints
252 }
253 
254 bool GNet::AddressImp::validString( const std::string & s , std::string * reason_p )
255 {
256  std::string buffer ;
257  if( reason_p == NULL ) reason_p = &buffer ;
258  std::string & reason = *reason_p ;
259 
260  const std::string::size_type pos = s.rfind(portSeparator()) ;
261  if( pos == std::string::npos )
262  {
263  reason = "no port separator" ;
264  return false ;
265  }
266 
267  std::string port_part = s.substr(pos+1U) ;
268  if( !validPortNumber(port_part) )
269  {
270  reason = std::string() + "invalid port number: [" + port_part + "]" ;
271  return false ;
272  }
273 
274  std::string host_part = s.substr(0U,pos) ;
275 
276  // (could test the string by passing it
277  // to inet_addr() here, but the man page points
278  // out that the error return value is not
279  // definitive)
280 
281  G::Strings parts ;
282  G::Str::splitIntoFields( host_part , parts , "." ) ;
283  if( parts.size() != 4U )
284  {
285  reason = "invalid number of dotted parts" ;
286  return false ;
287  }
288 
289  G::Strings::iterator p = parts.begin() ;
290  reason = "invalid dotted part" ;
291  if( ! validPart(*p) ) return false ; p++ ;
292  if( ! validPart(*p) ) return false ; p++ ;
293  if( ! validPart(*p) ) return false ; p++ ;
294  if( ! validPart(*p) ) return false ;
295 
296  reason = "" ;
297  return true ;
298 }
299 
300 bool GNet::AddressImp::validPortNumber( const std::string & s )
301 {
302  return validNumber(s) && G::Str::isUInt(s) && validPort(G::Str::toUInt(s)) ;
303 }
304 
305 bool GNet::AddressImp::validNumber( const std::string & s )
306 {
307  return s.length() != 0U && G::Str::isNumeric(s) ;
308 }
309 
310 bool GNet::AddressImp::validPart( const std::string & s )
311 {
312  return validNumber(s) && G::Str::toUInt(s,true) <= 255U ;
313 }
314 
315 bool GNet::AddressImp::same( const AddressImp & other ) const
316 {
317  return
318  m_inet.specific.sin_family == other.m_inet.specific.sin_family &&
319  m_inet.specific.sin_family == family() &&
320  sameAddr( m_inet.specific.sin_addr , other.m_inet.specific.sin_addr ) &&
321  m_inet.specific.sin_port == other.m_inet.specific.sin_port ;
322 }
323 
324 bool GNet::AddressImp::sameHost( const AddressImp & other ) const
325 {
326  return
327  m_inet.specific.sin_family == other.m_inet.specific.sin_family &&
328  m_inet.specific.sin_family == family() &&
329  sameAddr( m_inet.specific.sin_addr , other.m_inet.specific.sin_addr ) ;
330 }
331 
332 bool GNet::AddressImp::sameAddr( const ::in_addr & a , const ::in_addr & b )
333 {
334  return a.s_addr == b.s_addr ;
335 }
336 
337 unsigned int GNet::AddressImp::port() const
338 {
339  return ntohs( m_inet.specific.sin_port ) ;
340 }
341 
342 const sockaddr * GNet::AddressImp::raw() const
343 {
344  return & m_inet.general ;
345 }
346 
348 {
349  return & m_inet.general ;
350 }
351 
352 void GNet::AddressImp::set( const sockaddr * general )
353 {
354  m_inet.general = *general ;
355 }
356 
357 char GNet::AddressImp::portSeparator()
358 {
359  return ':' ;
360 }
361 
362 G::Strings GNet::AddressImp::wildcards( const std::string & display_string )
363 {
364  G::Strings result ;
365  result.push_back( display_string ) ;
366 
367  G::StringArray part ;
368  G::Str::splitIntoFields( display_string , part , "." ) ;
369 
370  G_ASSERT( part.size() == 4U ) ;
371  if( part.size() != 4U ||
372  !G::Str::isUInt(part[0]) ||
373  !G::Str::isUInt(part[1]) ||
374  !G::Str::isUInt(part[2]) ||
375  !G::Str::isUInt(part[3]) )
376  {
377  return result ;
378  }
379 
380  unsigned int n0 = G::Str::toUInt(part[0]) ;
381  unsigned int n1 = G::Str::toUInt(part[1]) ;
382  unsigned int n2 = G::Str::toUInt(part[2]) ;
383  unsigned int n3 = G::Str::toUInt(part[3]) ;
384 
385  std::string part_0_1_2 = part[0] ;
386  part_0_1_2.append( 1U , '.' ) ;
387  part_0_1_2.append( part[1] ) ;
388  part_0_1_2.append( 1U , '.' ) ;
389  part_0_1_2.append( part[2] ) ;
390  part_0_1_2.append( 1U , '.' ) ;
391 
392  std::string part_0_1 = part[0] ;
393  part_0_1.append( 1U , '.' ) ;
394  part_0_1.append( part[1] ) ;
395  part_0_1.append( 1U , '.' ) ;
396 
397  std::string part_0 = part[0] ;
398  part_0.append( 1U , '.' ) ;
399 
400  const std::string empty ;
401 
402  add( result , part_0_1_2 , n3 & 0xff , "/32" ) ;
403  add( result , part_0_1_2 , n3 & 0xfe , "/31" ) ;
404  add( result , part_0_1_2 , n3 & 0xfc , "/30" ) ;
405  add( result , part_0_1_2 , n3 & 0xf8 , "/29" ) ;
406  add( result , part_0_1_2 , n3 & 0xf0 , "/28" ) ;
407  add( result , part_0_1_2 , n3 & 0xe0 , "/27" ) ;
408  add( result , part_0_1_2 , n3 & 0xc0 , "/26" ) ;
409  add( result , part_0_1_2 , n3 & 0x80 , "/25" ) ;
410  add( result , part_0_1_2 , 0 , "/24" ) ;
411  add( result , part_0_1_2 , "*" ) ;
412  add( result , part_0_1 , n2 & 0xfe , ".0/23" ) ;
413  add( result , part_0_1 , n2 & 0xfc , ".0/22" ) ;
414  add( result , part_0_1 , n2 & 0xfc , ".0/21" ) ;
415  add( result , part_0_1 , n2 & 0xf8 , ".0/20" ) ;
416  add( result , part_0_1 , n2 & 0xf0 , ".0/19" ) ;
417  add( result , part_0_1 , n2 & 0xe0 , ".0/18" ) ;
418  add( result , part_0_1 , n2 & 0xc0 , ".0/17" ) ;
419  add( result , part_0_1 , 0 , ".0/16" ) ;
420  add( result , part_0_1 , "*.*" ) ;
421  add( result , part_0 , n1 & 0xfe , ".0.0/15" ) ;
422  add( result , part_0 , n1 & 0xfc , ".0.0/14" ) ;
423  add( result , part_0 , n1 & 0xf8 , ".0.0/13" ) ;
424  add( result , part_0 , n1 & 0xf0 , ".0.0/12" ) ;
425  add( result , part_0 , n1 & 0xe0 , ".0.0/11" ) ;
426  add( result , part_0 , n1 & 0xc0 , ".0.0/10" ) ;
427  add( result , part_0 , n1 & 0x80 , ".0.0/9" ) ;
428  add( result , part_0 , 0 , ".0.0/8" ) ;
429  add( result , part_0 , "*.*.*" ) ;
430  add( result , empty , n0 & 0xfe , ".0.0.0/7" ) ;
431  add( result , empty , n0 & 0xfc , ".0.0.0/6" ) ;
432  add( result , empty , n0 & 0xf8 , ".0.0.0/5" ) ;
433  add( result , empty , n0 & 0xf0 , ".0.0.0/4" ) ;
434  add( result , empty , n0 & 0xe0 , ".0.0.0/3" ) ;
435  add( result , empty , n0 & 0xc0 , ".0.0.0/2" ) ;
436  add( result , empty , n0 & 0x80 , ".0.0.0/1" ) ;
437  add( result , empty , 0 , ".0.0.0/0" ) ;
438  add( result , empty , "*.*.*.*" ) ;
439 
440  return result ;
441 }
442 
443 void GNet::AddressImp::add( G::Strings & result , const std::string & head , unsigned int n , const char * tail )
444 {
445  std::string s = head ;
446  s.append( G::Str::fromUInt( n ) ) ;
447  s.append( tail ) ;
448  result.push_back( s ) ;
449 }
450 
451 void GNet::AddressImp::add( G::Strings & result , const std::string & head , const char * tail )
452 {
453  result.push_back( head + tail ) ;
454 }
455 
456 // ===
457 
459 {
460  return Address( 0U ) ;
461 }
462 
464 {
465  return Address( port , Localhost() ) ;
466 }
467 
469 {
470  return Address( port , Broadcast() ) ;
471 }
472 
473 GNet::Address::Address( unsigned int port ) :
474  m_imp( new AddressImp(port) )
475 {
476 }
477 
478 GNet::Address::Address( unsigned int port , Localhost dummy ) :
479  m_imp( new AddressImp(port,dummy) )
480 {
481 }
482 
483 GNet::Address::Address( unsigned int port , Broadcast dummy ) :
484  m_imp( new AddressImp(port,dummy) )
485 {
486 }
487 
488 GNet::Address::Address( const hostent & h , unsigned int port ) :
489  m_imp( new AddressImp(h,port) )
490 {
491 }
492 
493 GNet::Address::Address( const hostent & h , const servent & s ) :
494  m_imp( new AddressImp(h,s) )
495 {
496 }
497 
498 GNet::Address::Address( const servent & s ) :
499  m_imp( new AddressImp(s) )
500 {
501 }
502 
504  m_imp( new AddressImp(storage.p(),storage.n()) )
505 {
506 }
507 
508 GNet::Address::Address( const sockaddr * addr , socklen_t len ) :
509  m_imp( new AddressImp(addr,len) )
510 {
511 }
512 
513 GNet::Address::Address( const std::string & s ) :
514  m_imp( new AddressImp(s) )
515 {
516 }
517 
518 GNet::Address::Address( const std::string & s , unsigned int port ) :
519  m_imp( new AddressImp(s,port) )
520 {
521 }
522 
523 GNet::Address::Address( const Address & other ) :
524  m_imp( new AddressImp(*other.m_imp) )
525 {
526 }
527 
528 void GNet::Address::operator=( const Address & addr )
529 {
530  Address temp( addr ) ;
531  std::swap( m_imp , temp.m_imp ) ;
532 }
533 
535 {
536  delete m_imp ;
537 }
538 
539 void GNet::Address::setPort( unsigned int port )
540 {
541  m_imp->setPort( port ) ;
542 }
543 
544 bool GNet::Address::operator==( const Address & other ) const
545 {
546  return m_imp->same(*other.m_imp) ;
547 }
548 
549 bool GNet::Address::isLocal( std::string & reason ) const
550 {
551  if( sameHost(localhost()) )
552  return true ;
553 
554  std::ostringstream ss ;
555  ss << displayString(false) << " is not " << localhost().displayString(false) ;
556  reason = ss.str() ;
557 
558  return false ;
559 }
560 
561 bool GNet::Address::isLocal( std::string & reason , const Address & local_hint ) const
562 {
563  if( sameHost(localhost()) || sameHost(local_hint) )
564  return true ;
565 
566  std::ostringstream ss ;
567  ss
568  << displayString(false) << " is not one of "
569  << localhost().displayString(false) << ","
570  << local_hint.displayString(false) ;
571  reason = ss.str() ;
572 
573  return false ;
574 }
575 
576 bool GNet::Address::sameHost( const Address & other ) const
577 {
578  return m_imp->sameHost(*other.m_imp) ;
579 }
580 
581 std::string GNet::Address::displayString( bool with_port , bool ) const
582 {
583  return with_port ? m_imp->displayString() : m_imp->hostString() ;
584 }
585 
586 std::string GNet::Address::hostString() const
587 {
588  return m_imp->hostString() ;
589 }
590 
591 bool GNet::Address::validString( const std::string & s , std::string * reason_p )
592 {
593  return AddressImp::validString( s , reason_p ) ;
594 }
595 
597 {
598  return m_imp->raw() ;
599 }
600 
601 const sockaddr * GNet::Address::address() const
602 {
603  return m_imp->raw() ;
604 }
605 
606 socklen_t GNet::Address::length() const
607 {
608  return sizeof(AddressImp::address_type) ;
609 }
610 
611 unsigned int GNet::Address::port() const
612 {
613  return m_imp->port() ;
614 }
615 
616 unsigned long GNet::Address::scopeId( unsigned long default_ ) const
617 {
618  return default_ ;
619 }
620 
621 bool GNet::Address::validPort( unsigned int port )
622 {
623  return AddressImp::validPort( port ) ;
624 }
625 
627 {
628  return PF_INET ;
629 }
630 
632 {
633  return defaultDomain() ;
634 }
635 
637 {
638  return AddressImp::wildcards( displayString(false) ) ;
639 }
640 
641 // ===
642 
644  m_imp( new AddressStorageImp )
645 {
646  m_imp->n = sizeof(AddressImp::Sockaddr) ;
647 }
648 
650 {
651  delete m_imp ;
652 }
653 
655 {
656  return &(m_imp->u.general) ;
657 }
658 
660 {
661  return &m_imp->n ;
662 }
663 
664 const sockaddr * GNet::AddressStorage::p() const
665 {
666  return &m_imp->u.general ;
667 }
668 
669 socklen_t GNet::AddressStorage::n() const
670 {
671  return m_imp->n ;
672 }
673 
G::Strings wildcards() const
Returns an ordered list of wildcard strings that match this address.
A pimple-pattern implementation class for GNet::Address.
static Address broadcastAddress(unsigned int port)
Returns a broadcast address.
std::string displayString() const
static int defaultDomain()
Returns the default address 'domain', eg. PF_INET.
void setPort(unsigned int port)
static Address localhost(unsigned int port=0U)
Returns a localhost ("loopback") address.
static unsigned int toUInt(const std::string &s, bool limited=false)
Converts string 's' to an unsigned int.
Definition: gstr.cpp:346
std::list< std::string > Strings
A std::list of std::strings.
Definition: gstrings.h:39
AddressImp::Sockaddr u
static void splitIntoFields(const std::string &in, Strings &out, const std::string &seperators, char escape= '\0', bool discard_bogus_escapes=true)
Splits the string into fields.
Definition: gstr.cpp:765
A helper class for calling getsockname() and getpeername() and hiding the definition of sockaddr_stor...
Definition: gaddress.h:225
The Address class encapsulates an IP transport address.
Definition: gaddress.h:48
std::vector< std::string > StringArray
A std::vector of std::strings.
Definition: gstrings.h:44
socklen_t * p2()
Returns the length pointer for getsockname()/getpeername() to write into.
std::string::size_type size_type
A std::size_t type.
Definition: md5.h:43
sockaddr * p1()
Returns the sockaddr pointer for getsockname()/getpeername() to write into.
static Address invalidAddress()
Returns an invalid address.
static bool isNumeric(const std::string &s, bool allow_minus_sign=false)
Returns true if every character is a decimal digit.
Definition: gstr.cpp:152
A pimple-pattern implementation class for GNet::AddressStorage.
const sockaddr * address() const
Returns the sockaddr address.
std::string hostString() const
Returns a string which represents the host part of the address for debugging and diagnostics purposes...
unsigned int port() const
Returns port part of address.
bool operator==(const Address &) const
Comparison operator.
std::string hostString() const
const sockaddr * p() const
Returns the pointer.
AddressImp(unsigned int port)
Address(const Address &addr)
Copy constructor.
static G::Strings wildcards(const std::string &display_string)
#define G_ASSERT(test)
Definition: gassert.h:30
static std::string fromUInt(unsigned int ui)
Converts unsigned int 'ui' to a string.
Definition: gstr.cpp:257
AddressStorage()
Default constructor.
std::string displayString(bool with_port=true, bool with_scope_id=false) const
Returns a string which represents the address for debugging and diagnostics purposes.
Used by GNet::AddressImp to cast between sockaddr and sockaddr_in.
static bool validPort(unsigned int port)
socklen_t length() const
Returns the size of the sockaddr address.
bool sameHost(const AddressImp &other) const
bool sameHost(const Address &other) const
Returns true if the two addresses have the same host part (ie.
unsigned long scopeId(unsigned long default_=0UL) const
Returns the scope-id.
int domain() const
Returns the address 'domain', eg. PF_INET.
~Address()
Destructor.
~AddressStorage()
Destructor.
static bool validPort(unsigned int n)
Returns true if the port number is within the valid range.
bool isLocal(std::string &reason) const
Returns true if the address is definitely local.
static bool validString(const std::string &s, std::string *reason_p=NULL)
bool same(const AddressImp &other) const
An overload discriminator class for GNet::Address.
Definition: gaddress.h:58
An overload discriminator class for GNet::Address.
Definition: gaddress.h:55
void operator=(const Address &addr)
Assignment operator.
static bool validString(const std::string &display_string, std::string *reason=NULL)
Returns true if the display string is valid.
static bool isUInt(const std::string &s)
Returns true if the string can be converted into an unsigned integer without throwing an exception...
Definition: gstr.cpp:190
void setPort(unsigned int port)
Sets the port number.
socklen_t n() const
Returns the length.
const sockaddr * raw() const
unsigned int port() const
sockaddr_in address_type