forked from ravinet/mahimahi
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathaddress.cc
113 lines (89 loc) · 2.49 KB
/
address.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/* -*-mode:c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <assert.h>
#include <arpa/inet.h>
#include "address.hh"
#include "exception.hh"
#include "socket.hh"
#include "util.hh"
using namespace std;
Address::Address( const sockaddr_in & s_addr )
: addr_( s_addr )
{
}
Address::Address( const sockaddr & s_addr )
: addr_()
{
if ( s_addr.sa_family != AF_INET ) {
throw Exception( "Address()", "sockaddr is not of family AF_INET" );
}
addr_ = *reinterpret_cast<const sockaddr_in *>( &s_addr );
}
Address::Address()
: addr_()
{
zero( addr_ );
addr_.sin_family = AF_INET;
}
bool Address::operator==( const Address & other ) const
{
return 0 == memcmp( &addr_, &other.addr_, sizeof( addr_ ) );
}
bool Address::operator<( const Address & other ) const
{
return (memcmp( &addr_, &other.addr_, sizeof( addr_ ) ) < 0 );
}
Address::Address( const string & ip, const uint16_t port )
: addr_()
{
addr_.sin_family = AF_INET;
if ( 1 != inet_pton( AF_INET, ip.c_str(), &addr_.sin_addr ) ) {
throw Exception( "inet_pton (" + ip + ")" );
}
addr_.sin_port = htons( port );
}
Address Address::cgnat( const uint8_t last_octet )
{
return Address( "100.64.0." + to_string( last_octet ), 0 );
}
Address::Address( const string & hostname, const string & service )
: addr_()
{
/* give hints to resolver */
addrinfo hints;
zero( hints );
hints.ai_family = AF_INET;
/* prepare for the answer */
addrinfo *res;
/* look up the name or names */
int gai_ret = getaddrinfo( hostname.c_str(), service.c_str(), &hints, &res );
if ( gai_ret != 0 ) {
throw Exception( "getaddrinfo", gai_strerror( gai_ret ) );
}
/* if success, should always have at least one entry */
assert( res );
/* should match our request */
assert( res->ai_family == AF_INET );
assert( res->ai_addrlen == sizeof( addr_ ) );
/* assign to our private member variable */
addr_ = *reinterpret_cast<sockaddr_in *>( res->ai_addr );
freeaddrinfo( res );
}
string Address::str( const string port_separator ) const
{
return ip() + port_separator + to_string( port() );
}
uint16_t Address::port( void ) const
{
return ntohs( addr_.sin_port );
}
string Address::ip( void ) const
{
char addrstr[ INET_ADDRSTRLEN ] = {};
if ( nullptr == inet_ntop( AF_INET, &addr_.sin_addr, addrstr, INET_ADDRSTRLEN ) ) {
throw Exception( "inet_ntop" );
}
return addrstr;
}