32 #include <sys/types.h>
39 const char * port_separators =
":/." ;
40 char port_separator =
':' ;
43 unsigned short GNet::Address4::family()
48 int GNet::Address4::domain()
53 void GNet::Address4::init()
55 static specific_type zero ;
56 m_inet.specific = zero ;
57 m_inet.specific.sin_family = family() ;
58 m_inet.specific.sin_port = 0 ;
63 GNet::Address4::Address4(
unsigned int port )
66 m_inet.specific.sin_addr.s_addr = htonl(INADDR_ANY);
67 const char * reason = setPort( m_inet , port ) ;
68 if( reason )
throw Address::Error(reason) ;
71 GNet::Address4::Address4(
unsigned int port ,
int )
74 m_inet.specific.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
75 const char * reason = setPort( m_inet , port ) ;
76 if( reason )
throw Address::Error(reason) ;
79 GNet::Address4::Address4(
const sockaddr * addr , socklen_t len )
83 throw Address::Error() ;
84 if( addr->sa_family != family() || static_cast<size_t>(len) <
sizeof(specific_type) )
85 throw Address::BadFamily() ;
87 m_inet.specific = *(
reinterpret_cast<const specific_type*
>(addr)) ;
90 GNet::Address4::Address4(
const Address4 & other )
92 m_inet.specific = other.m_inet.specific ;
95 GNet::Address4::Address4(
const std::string & host_part ,
unsigned int port )
98 const char * reason = setHostAddress( m_inet , host_part ) ;
100 reason = setPort( m_inet , port ) ;
102 throw Address::BadString( std::string(reason) +
": " + host_part ) ;
105 GNet::Address4::Address4(
const std::string & host_part ,
const std::string & port_part )
108 const char * reason = setHostAddress( m_inet , host_part ) ;
110 reason = setPort( m_inet , port_part ) ;
112 throw Address::BadString( std::string(reason) +
": [" + host_part +
"][" + port_part +
"]" ) ;
115 GNet::Address4::Address4(
const std::string & display_string )
118 const char * reason = setAddress( m_inet , display_string ) ;
120 throw Address::BadString( std::string(reason) +
": " + display_string ) ;
123 const char * GNet::Address4::setAddress( union_type & inet ,
const std::string & display_string )
125 const std::string::size_type pos = display_string.find_last_of( port_separators ) ;
126 if( pos == std::string::npos )
127 return "no port separator" ;
129 std::string host_part =
G::Str::head( display_string , pos ) ;
130 std::string port_part =
G::Str::tail( display_string , pos ) ;
132 const char * reason = setHostAddress( inet , host_part ) ;
134 reason = setPort( inet , port_part ) ;
138 const char * GNet::Address4::setHostAddress( union_type & inet ,
const std::string & host_part )
141 if( !Address4::format(host_part) )
142 return "invalid ipv4 network address format" ;
144 int rc = inet_pton( family() , host_part.c_str() , &inet.specific.sin_addr ) ;
145 return rc == 1 ?
nullptr :
"invalid ipv4 network address" ;
167 void GNet::Address4::setPort(
unsigned int port )
169 const char * reason = setPort( m_inet , port ) ;
171 throw Address::Error(
"invalid port number" ) ;
174 const char * GNet::Address4::setPort( union_type & inet ,
const std::string & port_part )
176 if( port_part.length() == 0U )
return "empty port string" ;
181 const char * GNet::Address4::setPort( union_type & inet ,
unsigned int port )
183 if( port > 0xFFFFU )
return "port number too big" ;
184 const g_port_t in_port =
static_cast<g_port_t
>(port) ;
185 inet.specific.sin_port = htons( in_port ) ;
196 std::string GNet::Address4::displayString()
const
198 std::ostringstream ss ;
199 ss << hostPartString() ;
200 ss << port_separator << port() ;
207 std::string GNet::Address4::hostPartString()
const
209 char buffer[INET_ADDRSTRLEN+1U] ;
210 const void * vp = & m_inet.specific.sin_addr ;
211 const char * p = inet_ntop( family() , const_cast<void*>(vp) , buffer ,
sizeof(buffer) ) ;
213 throw Address::Error(
"inet_ntop() failure" ) ;
214 buffer[
sizeof(buffer)-1U] =
'\0' ;
215 return std::string(buffer) ;
218 bool GNet::Address4::validData(
const sockaddr * addr , socklen_t len )
220 return addr !=
nullptr && addr->sa_family == family() && len ==
sizeof(specific_type) ;
223 bool GNet::Address4::validString(
const std::string & s , std::string * reason_p )
226 const char * reason = setAddress( inet , s ) ;
227 if( reason && reason_p )
228 *reason_p = std::string(reason) ;
229 return reason == nullptr ;
232 bool GNet::Address4::validStrings(
const std::string & host_part ,
const std::string & port_part , std::string * reason_p )
235 const char * reason = setHostAddress( inet , host_part ) ;
237 reason = setPort( inet , port_part ) ;
238 if( reason && reason_p )
239 *reason_p = std::string(reason) ;
240 return reason == nullptr ;
243 bool GNet::Address4::validPort(
unsigned int port )
246 const char * reason = setPort( inet , port ) ;
247 return reason == nullptr ;
250 bool GNet::Address4::same(
const Address4 & other )
const
253 m_inet.specific.sin_family == family() &&
254 other.m_inet.specific.sin_family == family() &&
255 sameAddr( m_inet.specific.sin_addr , other.m_inet.specific.sin_addr ) &&
256 m_inet.specific.sin_port == other.m_inet.specific.sin_port ;
259 bool GNet::Address4::sameHostPart(
const Address4 & other )
const
262 m_inet.specific.sin_family == family() &&
263 other.m_inet.specific.sin_family == family() &&
264 sameAddr( m_inet.specific.sin_addr , other.m_inet.specific.sin_addr ) ;
267 bool GNet::Address4::sameAddr( const ::in_addr & a , const ::in_addr & b )
269 return a.s_addr == b.s_addr ;
277 unsigned int GNet::Address4::port()
const
279 return ntohs( m_inet.specific.sin_port ) ;
287 const sockaddr * GNet::Address4::address()
const
289 return & m_inet.general ;
292 sockaddr * GNet::Address4::address()
294 return & m_inet.general ;
297 socklen_t GNet::Address4::length()
299 return sizeof(specific_type) ;
304 std::string ip_string = hostPartString() ;
307 result.reserve( 38U ) ;
308 result.push_back( ip_string ) ;
314 G_ASSERT( part.size() == 4U ) ;
315 if( part.size() != 4U ||
329 std::string part_0_1_2 = part[0] ;
330 part_0_1_2.append( 1U ,
'.' ) ;
331 part_0_1_2.append( part[1] ) ;
332 part_0_1_2.append( 1U ,
'.' ) ;
333 part_0_1_2.append( part[2] ) ;
334 part_0_1_2.append( 1U ,
'.' ) ;
336 std::string part_0_1 = part[0] ;
337 part_0_1.append( 1U ,
'.' ) ;
338 part_0_1.append( part[1] ) ;
339 part_0_1.append( 1U ,
'.' ) ;
341 std::string part_0 = part[0] ;
342 part_0.append( 1U ,
'.' ) ;
344 const std::string empty ;
346 add( result , part_0_1_2 , n3 & 0xff ,
"/32" ) ;
347 add( result , part_0_1_2 , n3 & 0xfe ,
"/31" ) ;
348 add( result , part_0_1_2 , n3 & 0xfc ,
"/30" ) ;
349 add( result , part_0_1_2 , n3 & 0xf8 ,
"/29" ) ;
350 add( result , part_0_1_2 , n3 & 0xf0 ,
"/28" ) ;
351 add( result , part_0_1_2 , n3 & 0xe0 ,
"/27" ) ;
352 add( result , part_0_1_2 , n3 & 0xc0 ,
"/26" ) ;
353 add( result , part_0_1_2 , n3 & 0x80 ,
"/25" ) ;
354 add( result , part_0_1_2 , 0 ,
"/24" ) ;
355 add( result , part_0_1_2 ,
"*" ) ;
356 add( result , part_0_1 , n2 & 0xfe ,
".0/23" ) ;
357 add( result , part_0_1 , n2 & 0xfc ,
".0/22" ) ;
358 add( result , part_0_1 , n2 & 0xfc ,
".0/21" ) ;
359 add( result , part_0_1 , n2 & 0xf8 ,
".0/20" ) ;
360 add( result , part_0_1 , n2 & 0xf0 ,
".0/19" ) ;
361 add( result , part_0_1 , n2 & 0xe0 ,
".0/18" ) ;
362 add( result , part_0_1 , n2 & 0xc0 ,
".0/17" ) ;
363 add( result , part_0_1 , 0 ,
".0/16" ) ;
364 add( result , part_0_1 ,
"*.*" ) ;
365 add( result , part_0 , n1 & 0xfe ,
".0.0/15" ) ;
366 add( result , part_0 , n1 & 0xfc ,
".0.0/14" ) ;
367 add( result , part_0 , n1 & 0xf8 ,
".0.0/13" ) ;
368 add( result , part_0 , n1 & 0xf0 ,
".0.0/12" ) ;
369 add( result , part_0 , n1 & 0xe0 ,
".0.0/11" ) ;
370 add( result , part_0 , n1 & 0xc0 ,
".0.0/10" ) ;
371 add( result , part_0 , n1 & 0x80 ,
".0.0/9" ) ;
372 add( result , part_0 , 0 ,
".0.0/8" ) ;
373 add( result , part_0 ,
"*.*.*" ) ;
374 add( result , empty , n0 & 0xfe ,
".0.0.0/7" ) ;
375 add( result , empty , n0 & 0xfc ,
".0.0.0/6" ) ;
376 add( result , empty , n0 & 0xf8 ,
".0.0.0/5" ) ;
377 add( result , empty , n0 & 0xf0 ,
".0.0.0/4" ) ;
378 add( result , empty , n0 & 0xe0 ,
".0.0.0/3" ) ;
379 add( result , empty , n0 & 0xc0 ,
".0.0.0/2" ) ;
380 add( result , empty , n0 & 0x80 ,
".0.0.0/1" ) ;
381 add( result , empty , 0 ,
".0.0.0/0" ) ;
382 add( result , empty ,
"*.*.*.*" ) ;
387 void GNet::Address4::add(
G::StringArray & result ,
const std::string & head ,
unsigned int n ,
const char * tail )
389 std::string s = head ;
392 result.push_back( s ) ;
395 void GNet::Address4::add(
G::StringArray & result ,
const std::string & head ,
const char * tail )
397 result.push_back( head + tail ) ;
400 bool GNet::Address4::format( std::string s )
404 if( s.empty() || s.find_first_not_of(
"0123456789.") != std::string::npos ||
405 std::count(s.begin(),s.end(),
'.') != 3U || s.at(0U) ==
'.' ||
406 s.at(s.length()-1U) ==
'.' || s.find(
"..") != std::string::npos )
409 unsigned int n = 0U ;
410 for( std::string::iterator pp = s.begin() ; pp != s.end() ; ++pp )
412 n = (*pp) ==
'.' ? 0U : ( ( n * 10U ) + (static_cast<unsigned int>(*pp)-
static_cast<unsigned int>(
'0')) ) ;
419 bool GNet::Address4::isLoopback()
const
422 return ( ntohl(m_inet.specific.sin_addr.s_addr) >> 24 ) == 127U ;
425 bool GNet::Address4::isLocal( std::string & reason )
const
436 std::ostringstream ss ;
437 ss << hostPartString() <<
" is not a loopback address" ;
std::vector< std::string > StringArray
A std::vector of std::strings.
static bool isNumeric(const std::string &s, bool allow_minus_sign=false)
Returns true if every character is a decimal digit.
static std::string tail(const std::string &in, std::string::size_type pos, const std::string &default_=std::string())
Returns the last part of the string after the given position.
static unsigned int toUInt(const std::string &s)
Converts string 's' to an unsigned int.
static std::string fromUInt(unsigned int ui)
Converts unsigned int 'ui' to a string.
static std::string head(const std::string &in, std::string::size_type pos, const std::string &default_=std::string())
Returns the first part of the string up to just before the given position.
This file is formatted for side-by-side comparison with gaddress6.h.
static bool isUInt(const std::string &s)
Returns true if the string can be converted into an unsigned integer without throwing an exception...
static void splitIntoFields(const std::string &in, StringArray &out, const std::string &seperators, char escape= '\0', bool remove_escapes=true)
Splits the string into fields.