1 |
1 |
2 #include "Address.hh" |
2 #include "Address.hh" |
3 |
3 |
4 #include <sstream> |
4 #include <sstream> |
5 |
5 |
|
6 NetworkAddress::NetworkAddress (void) : |
|
7 hostname(), service(), address_length(0) |
|
8 { |
|
9 |
|
10 } |
|
11 |
|
12 NetworkAddress::NetworkAddress (std::string service) : |
|
13 hostname(), service(service), address_length(0) |
|
14 { |
|
15 |
|
16 } |
|
17 |
|
18 NetworkAddress::NetworkAddress (std::string hostname, std::string service) : |
|
19 hostname(hostname), service(service), address_length(0) |
|
20 { |
|
21 |
|
22 } |
|
23 |
|
24 NetworkAddress::NetworkAddress (const sockaddr *addr, socklen_t len) : |
|
25 hostname(hostname), service(service), address_length(0) |
|
26 { |
|
27 // proxy to set_sockaddr |
|
28 set_sockaddr(addr, len); |
|
29 } |
|
30 |
|
31 addrinfo* NetworkAddress::get_addrinfo (int family, int socktype, int protocol, int flags) const { |
|
32 addrinfo hints, *results; |
|
33 int err; |
|
34 |
|
35 // initialize flags |
|
36 hints.ai_flags = flags; |
|
37 hints.ai_family = family; |
|
38 hints.ai_socktype = socktype; |
|
39 hints.ai_protocol = protocol; |
|
40 hints.ai_addrlen = 0; |
|
41 hints.ai_canonname = NULL; |
|
42 hints.ai_next = NULL; |
|
43 |
|
44 // hostname + service may be NULL |
|
45 const char *hostname = this->hostname.empty() ? NULL : this->hostname.c_str(); |
|
46 const char *service = this->service.empty() ? NULL : this->service.c_str(); |
|
47 |
|
48 // do getaddrinfo() |
|
49 if ((err = getaddrinfo(hostname, service, &hints, &results))) |
|
50 throw NetworkAddressError(*this, "getaddrinfo", gai_strerror(err)); |
|
51 |
|
52 // done |
|
53 return results; |
|
54 } |
|
55 |
|
56 const sockaddr* NetworkAddress::get_sockaddr (socklen_t &len_ref) const { |
|
57 // we can't figure this out ourselves... |
|
58 if (address_length == 0) |
|
59 throw Error("NetworkAddress::get_sockaddr called without a valid sockaddr set"); |
|
60 |
|
61 // update len |
|
62 len_ref = address_length; |
|
63 |
|
64 // and return a pointer to our internal address |
|
65 return (const sockaddr*) &address; |
|
66 } |
|
67 |
|
68 void NetworkAddress::set_sockaddr (const sockaddr *addr, socklen_t len) { |
|
69 char host_buf[NI_MAXHOST], serv_buf[NI_MAXSERV]; |
|
70 int err; |
|
71 |
|
72 // invalid length? |
|
73 if (len > sizeof(this->address)) |
|
74 throw NetworkAddressError(*this, "set_sockaddr", "invalid sockaddr length"); |
|
75 |
|
76 // do getnameinfo() |
|
77 if ((err = getnameinfo(addr, len, host_buf, NI_MAXHOST, serv_buf, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV))) |
|
78 throw NetworkAddressError(*this, "getnameinfo", gai_strerror(err)); |
|
79 |
|
80 // copy over to address |
|
81 memcpy(&this->address, addr, len); |
|
82 } |
|
83 |
6 std::ostream& operator<< (std::ostream &s, const NetworkAddress &addr) { |
84 std::ostream& operator<< (std::ostream &s, const NetworkAddress &addr) { |
7 s << "[" << addr.get_address() << ":" << addr.get_port() << "]"; |
85 s << "[" << addr.get_hostname() << ":" << addr.get_service() << "]"; |
8 |
86 |
9 return s; |
87 return s; |
10 |
88 |
11 } |
89 } |
12 |
90 |
|
91 std::string NetworkAddressError::build_str (const NetworkAddress &addr, const char *op, const char *msg) { |
|
92 std::stringstream ss; |
|
93 |
|
94 ss << op << ": " << addr << ": " << msg; |
|
95 |
|
96 return ss.str(); |
|
97 } |
|
98 |
|
99 NetworkAddressError::NetworkAddressError (const NetworkAddress &addr, const char *op, const char *msg) : |
|
100 Error(build_str(addr, op, msg)) |
|
101 { |
|
102 |
|
103 } |
|
104 |
|
105 |
|
106 |