1 |
1 |
2 #include "Address.hh" |
2 #include "Address.hh" |
3 |
3 |
4 #include <sstream> |
4 #include <cstdlib> |
5 |
5 |
6 NetworkEndpoint::NetworkEndpoint (void) : |
6 NetworkAddress::NetworkAddress (void) : |
7 hostname(), service() |
7 NetworkEndpoint(), address_length(0) |
8 { |
8 { |
9 |
9 |
10 } |
10 } |
11 |
11 |
12 NetworkEndpoint::NetworkEndpoint (std::string service) : |
12 NetworkAddress::NetworkAddress (const sockaddr *addr, socklen_t len) : |
13 hostname(), service(service) |
13 NetworkEndpoint(), address_length(0) |
14 { |
14 { |
|
15 // proxy to set_sockaddr |
|
16 set_sockaddr(addr, len); |
|
17 } |
|
18 |
|
19 void NetworkAddress::set_sockaddr (const sockaddr *addr, socklen_t len) { |
|
20 // invalid length? |
|
21 if (len <= 0 || len > sizeof(address)) |
|
22 throw NetworkAddressError(*this, "set_sockaddr", "invalid sockaddr length"); |
15 |
23 |
16 } |
24 // copy over to address |
17 |
25 memcpy(&address, addr, len); |
18 NetworkEndpoint::NetworkEndpoint (std::string hostname, std::string service) : |
|
19 hostname(hostname), service(service) |
|
20 { |
|
21 |
|
22 } |
|
23 |
|
24 addrinfo* NetworkEndpoint::get_addrinfo (int family, int socktype, int protocol, int flags) const { |
|
25 addrinfo hints, *results; |
|
26 int err; |
|
27 |
26 |
28 // initialize flags |
27 // set address_length |
29 hints.ai_flags = flags; |
28 address_length = len; |
30 hints.ai_family = family; |
29 |
31 hints.ai_socktype = socktype; |
30 // update |
32 hints.ai_protocol = protocol; |
31 update(); |
33 hints.ai_addrlen = 0; |
|
34 hints.ai_canonname = NULL; |
|
35 hints.ai_next = NULL; |
|
36 |
|
37 // hostname + service may be NULL |
|
38 const char *hostname = this->hostname.empty() ? NULL : this->hostname.c_str(); |
|
39 const char *service = this->service.empty() ? NULL : this->service.c_str(); |
|
40 |
|
41 // do getaddrinfo() |
|
42 if ((err = getaddrinfo(hostname, service, &hints, &results))) |
|
43 throw NetworkAddressError(*this, "getaddrinfo", gai_strerror(err)); |
|
44 |
|
45 // done |
|
46 return results; |
|
47 } |
|
48 |
|
49 void NetworkEndpoint::free_addrinfo (addrinfo *info) const { |
|
50 freeaddrinfo(info); |
|
51 } |
32 } |
52 |
33 |
53 std::ostream& operator<< (std::ostream &s, const NetworkEndpoint &addr) { |
34 void NetworkAddress::update (void) { |
54 s << "[" << addr.get_hostname() << ":" << addr.get_service() << "]"; |
35 char host_buf[NI_MAXHOST], serv_buf[NI_MAXSERV]; |
|
36 int err; |
55 |
37 |
56 return s; |
38 // do getnameinfo() |
57 |
39 if ((err = getnameinfo((sockaddr *) &address, address_length, host_buf, NI_MAXHOST, serv_buf, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV))) |
58 } |
40 throw NetworkAddressError(*this, "getnameinfo", gai_strerror(err)); |
59 |
41 |
60 std::string NetworkAddressError::build_str (const NetworkEndpoint &addr, const char *op, const char *msg) { |
42 // update hostname + service |
61 std::stringstream ss; |
43 hostname = host_buf; |
62 |
44 service = serv_buf; |
63 ss << op << ": " << addr << ": " << msg; |
|
64 |
|
65 return ss.str(); |
|
66 } |
45 } |
67 |
46 |
68 NetworkAddressError::NetworkAddressError (const NetworkEndpoint &addr, const char *op, const char *msg) : |
47 addrinfo* NetworkAddress::get_addrinfo (int family, int socktype, int protocol, int flags) const { |
69 Error(build_str(addr, op, msg)) |
48 (void) flags; |
70 { |
|
71 |
49 |
|
50 // get my family from address |
|
51 int my_family = address.ss_family; |
|
52 |
|
53 // right family? |
|
54 if (family && family != my_family) |
|
55 throw NetworkAddressError(*this, "fake_getaddrinfo", "ai_family mismatch"); |
|
56 |
|
57 // alllocate new addrinfo |
|
58 addrinfo *r = new addrinfo; |
|
59 |
|
60 // set it up |
|
61 r->ai_flags = 0; |
|
62 r->ai_family = my_family; |
|
63 r->ai_socktype = socktype; |
|
64 r->ai_protocol = protocol; |
|
65 r->ai_addrlen = get_socklen(); |
|
66 r->ai_addr = const_cast<sockaddr *>(get_sockaddr()); |
|
67 r->ai_canonname = const_cast<char *>(get_hostname().c_str()); |
|
68 r->ai_next = NULL; |
|
69 |
|
70 // return it |
|
71 return r; |
72 } |
72 } |
73 |
73 |
|
74 void NetworkAddress::free_addrinfo (addrinfo *info) const { |
|
75 delete info; |
|
76 } |