1 #ifndef NETWORK_ADDRESS_HH |
1 #ifndef NETWORK_ADDRESS_H |
2 #define NETWORK_ADDRESS_HH |
2 #define NETWORK_ADDRESS_H |
3 |
3 |
4 #include "../Error.hh" |
4 #include "Endpoint.hh" |
5 |
5 |
6 /* |
6 /* |
7 * Platform-specific includes |
7 * Platform-specific includes |
8 */ |
8 */ |
9 #ifndef WIN32 |
9 #ifndef WIN32 |
10 // linux |
10 // linux |
11 #include <sys/types.h> |
11 #include <netinet/in.h> |
12 #include <netdb.h> |
|
13 #else |
12 #else |
14 #error "This network code won't compile on win32 :)" |
13 #error "This network code won't compile on win32 :)" |
15 #endif |
14 #endif |
16 |
15 |
17 #include <string> |
|
18 |
|
19 // assume... |
|
20 #if INET6_ADDRSTRLEN < INET_ADDRSTRLEN |
|
21 #error INET6_ADDRSTRLEN is smaller than INET_ADDRSTRLEN |
|
22 #endif |
|
23 |
|
24 /** |
16 /** |
25 * Length of a network address |
17 * This represents a `struct sockaddr` as used by the socket API. |
|
18 * |
|
19 * It can be used like a NetworkEndpoint, but it's also suitable for use with recvfrom/sendto |
26 */ |
20 */ |
27 const socklen_t NETWORK_ADDRESS_LENGTH = INET6_ADDRSTRLEN; |
21 class NetworkAddress : public NetworkEndpoint { |
28 |
|
29 /** |
|
30 * We use ClanLib's IPAddress API, but with our own name |
|
31 */ |
|
32 class NetworkEndpoint { |
|
33 protected: |
22 protected: |
34 /** |
23 /** |
35 * Our human-readable hostname |
24 * The machine-readable address |
36 */ |
25 */ |
37 std::string hostname; |
26 sockaddr_storage address; |
38 |
27 |
39 /** |
28 /** |
40 * Our human-readable service |
29 * The address length |
41 */ |
30 */ |
42 std::string service; |
31 socklen_t address_length; |
43 |
32 |
44 public: |
33 public: |
45 /** |
34 /** |
46 * Construct an empty NetworkEndpoint |
35 * Construct an empty SockAddr for later update() |
47 */ |
36 */ |
48 NetworkEndpoint (void); |
37 NetworkAddress (void); |
49 |
38 |
50 /** |
39 /** |
51 * Construct a NetworkEndpoint with a NULL hostname, and a specific service |
40 * Construct a NetworkAddress from a machine-readable address of the given length |
52 */ |
41 */ |
53 explicit NetworkEndpoint (std::string service); |
42 NetworkAddress (const sockaddr *addr, socklen_t len); |
54 |
43 |
55 /** |
44 /** |
56 * Construct a NetworkEndpoint on a specific hostname and service |
45 * Get a const sockaddr* in this address |
|
46 * |
|
47 * @return read-only sockaddr pointer |
57 */ |
48 */ |
58 NetworkEndpoint (std::string hostname, std::string service); |
49 const sockaddr* get_sockaddr (void) const { return (const sockaddr *) &address; } |
|
50 |
|
51 /** |
|
52 * Get a mutable sockaddr* in this address |
|
53 * |
|
54 * @return writeable sockaddr pointer |
|
55 */ |
|
56 sockaddr* get_sockaddr (void) { return (sockaddr *) &address; } |
|
57 |
|
58 /** |
|
59 * Get the current address length |
|
60 * |
|
61 * @return address length |
|
62 */ |
|
63 socklen_t get_socklen (void) const { return address_length; } |
|
64 |
|
65 /** |
|
66 * Get a the address length pointer, initialized to the size of our sockaddr_storage. |
|
67 * |
|
68 * @return address length pointer |
|
69 */ |
|
70 socklen_t* get_socklen_ptr (void) { address_length = sizeof(address); return &address_length; } |
|
71 |
|
72 /** |
|
73 * Copy given sockaddr/len + update |
|
74 */ |
|
75 void set_sockaddr (const sockaddr *addr, socklen_t len); |
|
76 |
|
77 /** |
|
78 * Update internal state for NetworkAddress after sockaddr/socklen_ptr have been modified. |
|
79 */ |
|
80 void update (void); |
59 |
81 |
60 /* |
|
61 * We can use the default copy-constructor and assignment operator |
|
62 */ |
|
63 |
|
64 public: |
|
65 /** |
82 /** |
66 * Get a addrinfo* for this address using the given family/type/protocol/flags. |
83 * Returns a "fake" addrinfo |
67 * |
|
68 * Remember to free the returned pointer using freeaddrinfo() after use. |
|
69 * |
|
70 * @param family the socket family for hints.ai_family |
|
71 * @param socktype the socket type for hints.ai_socktype |
|
72 * @param protoocl the socket protocol for hints.ai_protocol |
|
73 * @param flags the flags for hints.ai_flags |
|
74 * @return linked list of addrinfo's |
|
75 * @throw NetworkAddressError if resolving this address fails |
|
76 */ |
84 */ |
77 virtual addrinfo* get_addrinfo (int family, int socktype, int protocol = 0, int flags = 0) const; |
85 virtual addrinfo* get_addrinfo (int family, int socktype, int protocol = 0, int flags = 0) const; |
78 |
86 |
79 /** |
87 /** |
80 * Free an addrinfo returned by get_addrinfo |
88 * Free an addrinfo returned by get_addrinfo |
81 */ |
89 */ |
82 virtual void free_addrinfo (addrinfo *info) const; |
90 virtual void free_addrinfo (addrinfo *info) const; |
83 |
91 |
84 /** |
92 /** |
85 * Get the human-readable hostname |
93 * Equal-to comparison operator. Invalid addresses compare equal and are always smaller |
86 */ |
94 */ |
87 virtual std::string get_hostname (void) const { return hostname; } |
95 bool operator== (const NetworkAddress &other) const { |
|
96 return (address_length == other.address_length) && memcmp(&address, &other.address, address_length) == 0; |
|
97 } |
88 |
98 |
89 /** |
99 /** |
90 * Get the human-readable service name |
100 * Not-equal-to comparison operator. Invalid addresses compare equal and are always smaller |
91 */ |
101 */ |
92 virtual std::string get_service (void) const { return service; } |
102 bool operator!= (const NetworkAddress &other) const { |
|
103 return (address_length != other.address_length) || memcmp(&address, &other.address, address_length) != 0; |
|
104 } |
|
105 |
|
106 /** |
|
107 * Less-than comparison operator. Smaller addresses are always lesser. |
|
108 */ |
|
109 bool operator< (const NetworkAddress &other) const { |
|
110 return (address_length < other.address_length) || memcmp(&address, &other.address, other.address_length) < 0; |
|
111 } |
|
112 |
|
113 /** |
|
114 * Greater-than comparison operator. Bigger addresses are always greater. |
|
115 */ |
|
116 bool operator> (const NetworkAddress &other) const { |
|
117 return (address_length > other.address_length) || memcmp(&address, &other.address, address_length) > 0; |
|
118 } |
93 }; |
119 }; |
94 |
120 |
95 /** |
121 #endif |
96 * Formatted as [<addr>:<port>] |
|
97 */ |
|
98 std::ostream& operator<< (std::ostream &s, const NetworkEndpoint &addr); |
|
99 |
|
100 /** |
|
101 * |
|
102 */ |
|
103 class NetworkAddressError : public Error { |
|
104 protected: |
|
105 static std::string build_str (const NetworkEndpoint &addr, const char *op, const char *msg); |
|
106 |
|
107 public: |
|
108 NetworkAddressError (const NetworkEndpoint &addr, const char *op, const char *msg); |
|
109 }; |
|
110 |
|
111 #endif /* NETWORK_ADDRESS_HH */ |
|