Thrill  0.1
socket_address.hpp
Go to the documentation of this file.
1 /*******************************************************************************
2  * thrill/net/tcp/socket_address.hpp
3  *
4  * Implements lookups and conversions to low-level socket address structs.
5  *
6  * Part of Project Thrill - http://project-thrill.org
7  *
8  * Copyright (C) 2015 Timo Bingmann <[email protected]>
9  *
10  * All rights reserved. Published under the BSD-2 license in the LICENSE file.
11  ******************************************************************************/
12 
13 #pragma once
14 #ifndef THRILL_NET_TCP_SOCKET_ADDRESS_HEADER
15 #define THRILL_NET_TCP_SOCKET_ADDRESS_HEADER
16 
17 #include <netinet/in.h>
18 #include <sys/socket.h>
19 
20 #include <cstdint>
21 #include <cstring>
22 #include <iosfwd>
23 #include <string>
24 #include <vector>
25 
26 namespace thrill {
27 namespace net {
28 namespace tcp {
29 
30 //! \addtogroup net_tcp TCP Socket API
31 //! \{
32 
33 /*!
34  * SocketAddress is a super class used to unify the two different IPv4 and IPv6
35  * socket address representation. It is derived into IPv4Address and IPv6Address
36  * only for direct initialization, in general one just uses
37  * SocketAddress("localhost:1234") for appropriate resolution into a
38  * sockaddr. The SocketAddress object can then be given to various Connect(),
39  * Bind() and similar functions of Socket.
40  */
42 {
43  static constexpr bool debug = false;
44 
45 protected:
46  //! Enclosed IPv4, IPv6 or other socket address structure. Used as a struct
47  //! sockaddr_in or a struct sockaddr_in6. sizeof(sockaddr_in6) is
48  //! (currently) 28.
49  union SockAddrUnion {
50  struct sockaddr generic;
51  struct sockaddr_in in;
52  struct sockaddr_in6 in6;
53  } sockaddr_;
54 
55 private:
56  //! Return value of the last getaddrinfo() call. Used to output nice user
57  //! messages.
59 
60 public:
61  //! Create empty invalid address object by clearing all bytes.
63  : resolve_error_(0) {
64  memset(&sockaddr_, 0, sizeof(sockaddr_));
65  }
66 
67  //! Create a socket address object with the given sockaddr data.
68  SocketAddress(struct sockaddr* sa, socklen_t salen);
69 
70  //! Create a socket address object and resolve the given host:port using
71  //! getaddrinfo(). Check result with IsValid().
72  explicit SocketAddress(const std::string& hostport);
73 
74  //! Create a socket address object and resolve the given host name using
75  //! getaddrinfo(). Check result with IsValid().
76  SocketAddress(const char* hostname, const char* servicename);
77 
78  //! Return pointer to enclosed address as a generic sockattr struct.
79  struct sockaddr * sockaddr() {
80  return &sockaddr_.generic;
81  }
82 
83  //! Return pointer to enclosed address as a generic sockattr struct.
84  const struct sockaddr * sockaddr() const {
85  return &sockaddr_.generic;
86  }
87 
88  //! Return total length of enclosed sockaddr structure.
89  socklen_t socklen() const {
90  return socklen_t(
91  sockaddr()->sa_family == AF_INET ? sizeof(sockaddr_.in) :
92  sockaddr()->sa_family == AF_INET6 ? sizeof(sockaddr_.in6) :
93  0);
94  }
95 
96  //! Returns true if the enclosed socket address is a valid IPv4 or IPv6
97  //! address.
98  bool IsValid() const {
99  return (sockaddr()->sa_family == AF_INET) ||
100  (sockaddr()->sa_family == AF_INET6);
101  }
102 
103  //! Returns true if the enclosed socket address is a IPv4 address.
104  bool IsIPv4() const {
105  return (sockaddr()->sa_family == AF_INET);
106  }
107 
108  //! Returns true if the enclosed socket address is a IPv6 address.
109  bool IsIPv6() const {
110  return (sockaddr()->sa_family == AF_INET6);
111  }
112 
113  //! Cast the enclosed sockaddr into the sockaddr_in IPv4 structure.
115  return &sockaddr_.in;
116  }
117 
118  //! Cast the enclosed sockaddr into the sockaddr_in IPv4 structure. Const
119  //! version.
120  const struct sockaddr_in * sockaddr_in() const {
121  return &sockaddr_.in;
122  }
123 
124  //! Cast the enclosed sockaddr into the sockaddr_in6 IPv6 structure.
126  return &sockaddr_.in6;
127  }
128 
129  //! Cast the enclosed sockaddr into the sockaddr_in6 IPv6 structure. Const
130  //! version.
131  const struct sockaddr_in6 * sockaddr_in6() const {
132  return &sockaddr_.in6;
133  }
134 
135  //! Return the enclosed socket address as a string without the port number.
136  std::string ToStringHost() const;
137 
138  //! Return the enclosed socket address as a string with the port number.
140 
141  //! Make the socket address ostream-able: outputs address:port
142  friend std::ostream& operator << (std::ostream& os,
143  const SocketAddress& sa);
144 
145  //! Return the currently set port address in host byte-order.
146  uint16_t GetPort() const {
147  if (sockaddr()->sa_family == AF_INET) {
148  return ntohs(sockaddr_in()->sin_port);
149  }
150  else if (sockaddr()->sa_family == AF_INET6) {
151  return ntohs(sockaddr_in6()->sin6_port);
152  }
153  else
154  return 0;
155  }
156 
157  //! Change the currently set port address.
158  void SetPort(uint16_t port) {
159  if (sockaddr()->sa_family == AF_INET) {
160  sockaddr_in()->sin_port = htons(port);
161  }
162  else if (sockaddr()->sa_family == AF_INET6) {
163  sockaddr_in6()->sin6_port = htons(port);
164  }
165  }
166 
167  //! Resolve the given host name using getaddrinfo() and replace this object
168  //! with the first socket address if found.
169  bool Resolve(const char* hostname,
170  const char* servicename = nullptr);
171 
172  //! Resolve the given host name using getaddrinfo() and return only the
173  //! first socket address if found.
174  static SocketAddress ResolveOne(const char* hostname,
175  const char* servicename = nullptr);
176 
177  //! Parse the address for a :port notation and then resolve the
178  //! given host name using getaddrinfo() and return only the first
179  //! socket address if found. Uses defaultservice if no port is
180  //! found in the hostname.
181  static SocketAddress ResolveWithPort(const char* hostname,
182  const char* defaultservice);
183 
184  //! Resolve the given host name using getaddrinfo() and return all
185  //! resulting socket addresses as a vector.
186  static std::vector<SocketAddress>
187  ResolveAll(const char* hostname, const char* servicename = nullptr);
188 
189  //! Return textual message of the last error occurring in the resolve
190  //! method.
191  const char * GetResolveError() const;
192 };
193 
194 /*!
195  * IPv4 Subclass of SocketAddress for direct initialization from a known IPv4
196  * address, known either in binary format, numerals, or as "ddd.ddd.ddd.ddd"
197  * format. No name lookup or resolution takes place in these functions.
198  */
200 {
201 public:
202  //! Create uninitialized IPv4 address
204  sockaddr_.in.sin_family = AF_INET;
205  }
206 
207  //! Create an IPv4 address and initialize only the port part.
208  explicit IPv4Address(uint16_t port)
209  : SocketAddress() {
210  sockaddr_.in.sin_family = AF_INET;
211  sockaddr_.in.sin_port = htons(port);
212  }
213 
214  //! Create an IPv4 address object with initialized address and port parts.
215  IPv4Address(uint32_t addr, uint16_t port)
216  : SocketAddress() {
217  sockaddr_.in.sin_family = AF_INET;
218  sockaddr_.in.sin_addr.s_addr = addr;
219  sockaddr_.in.sin_port = htons(port);
220  }
221 
222  //! Create an IPv4 address object with initialized address and port parts.
223  IPv4Address(struct in_addr& addr, uint16_t port)
224  : SocketAddress() {
225  sockaddr_.in.sin_family = AF_INET;
226  sockaddr_.in.sin_addr = addr;
227  sockaddr_.in.sin_port = htons(port);
228  }
229 
230  //! Create an IPv4 address object and copy the given sockaddr_in structure.
231  explicit IPv4Address(struct sockaddr_in& sa)
232  : SocketAddress() {
233  sockaddr_.in = sa;
234  }
235 
236  //! Create an IPv4 address object and initialize it with the given ip
237  //! address string, which is given in "ddd.ddd.ddd.ddd" format. You must
238  //! check with IsValid() if the conversion was successfull.
239  explicit IPv4Address(const char* ipstring, uint16_t port = 0);
240 };
241 
242 /*!
243  * IPv6 Subclass of SocketAddress for direct initialization from a known IPv6
244  * address, known either in binary format, numerals, or in some IPv6 format. No
245  * name lookup or resolution takes place in these functions.
246  */
248 {
249 public:
250  //! Create uninitialized IPv6 address
252  sockaddr_.in6.sin6_family = AF_INET6;
253  }
254 
255  //! Create an IPv6 address and initialize only the port part.
256  explicit IPv6Address(uint16_t port)
257  : SocketAddress() {
258  sockaddr_.in6.sin6_family = AF_INET6;
259  sockaddr_.in6.sin6_port = htons(port);
260  }
261 
262  //! Create an IPv6 address object with initialized address and port parts.
263  IPv6Address(uint8_t addr[16], uint16_t port)
264  : SocketAddress() {
265  sockaddr_.in6.sin6_family = AF_INET6;
266  memcpy(&sockaddr_.in6.sin6_addr, addr, 16 * sizeof(uint8_t));
267  sockaddr_.in6.sin6_port = htons(port);
268  }
269 
270  //! Create an IPv4 address object with initialized address and port parts.
271  IPv6Address(struct in6_addr& addr, uint16_t port)
272  : SocketAddress() {
273  sockaddr_.in6.sin6_family = AF_INET6;
274  sockaddr_.in6.sin6_addr = addr;
275  sockaddr_.in6.sin6_port = htons(port);
276  }
277 
278  //! Create an IPv4 address object and copy the given sockaddr_in structure.
279  explicit IPv6Address(struct sockaddr_in6& sa)
280  : SocketAddress() {
281  sockaddr_.in6 = sa;
282  }
283 
284  //! Create an IPv6 address object and initialize it with the given ip
285  //! address string, which is given in some IPv6 format. You must check with
286  //! IsValid() if the conversion was successfull.
287  explicit IPv6Address(const char* ipstring, uint16_t port = 0);
288 };
289 
290 // \}
291 
292 } // namespace tcp
293 } // namespace net
294 } // namespace thrill
295 
296 #endif // !THRILL_NET_TCP_SOCKET_ADDRESS_HEADER
297 
298 /******************************************************************************/
const struct sockaddr * sockaddr() const
Return pointer to enclosed address as a generic sockattr struct.
static SocketAddress ResolveOne(const char *hostname, const char *servicename=nullptr)
IPv6Address(struct in6_addr &addr, uint16_t port)
Create an IPv4 address object with initialized address and port parts.
IPv6Address(uint8_t addr[16], uint16_t port)
Create an IPv6 address object with initialized address and port parts.
static SocketAddress ResolveWithPort(const char *hostname, const char *defaultservice)
IPv4Address(struct in_addr &addr, uint16_t port)
Create an IPv4 address object with initialized address and port parts.
const struct sockaddr_in * sockaddr_in() const
bool Resolve(const char *hostname, const char *servicename=nullptr)
void SetPort(uint16_t port)
Change the currently set port address.
const struct sockaddr_in6 * sockaddr_in6() const
SocketAddress is a super class used to unify the two different IPv4 and IPv6 socket address represent...
SocketAddress()
Create empty invalid address object by clearing all bytes.
IPv6 Subclass of SocketAddress for direct initialization from a known IPv6 address, known either in binary format, numerals, or in some IPv6 format.
bool IsIPv6() const
Returns true if the enclosed socket address is a IPv6 address.
IPv6Address()
Create uninitialized IPv6 address.
union thrill::net::tcp::SocketAddress::SockAddrUnion sockaddr_
IPv4 Subclass of SocketAddress for direct initialization from a known IPv4 address, known either in binary format, numerals, or as "ddd.ddd.ddd.ddd" format.
static std::vector< SocketAddress > ResolveAll(const char *hostname, const char *servicename=nullptr)
friend std::ostream & operator<<(std::ostream &os, const SocketAddress &sa)
Make the socket address ostream-able: outputs address:port.
IPv4Address(struct sockaddr_in &sa)
Create an IPv4 address object and copy the given sockaddr_in structure.
uint16_t GetPort() const
Return the currently set port address in host byte-order.
IPv4Address(uint32_t addr, uint16_t port)
Create an IPv4 address object with initialized address and port parts.
const char * GetResolveError() const
struct sockaddr_in * sockaddr_in()
Cast the enclosed sockaddr into the sockaddr_in IPv4 structure.
IPv4Address(uint16_t port)
Create an IPv4 address and initialize only the port part.
std::string ToStringHost() const
Return the enclosed socket address as a string without the port number.
std::basic_string< char, std::char_traits< char >, Allocator< char > > string
string with Manager tracking
Definition: allocator.hpp:220
socklen_t socklen() const
Return total length of enclosed sockaddr structure.
IPv4Address()
Create uninitialized IPv4 address.
bool IsIPv4() const
Returns true if the enclosed socket address is a IPv4 address.
struct sockaddr * sockaddr()
Return pointer to enclosed address as a generic sockattr struct.
std::string ToStringHostPort() const
Return the enclosed socket address as a string with the port number.
struct sockaddr_in6 * sockaddr_in6()
Cast the enclosed sockaddr into the sockaddr_in6 IPv6 structure.
IPv6Address(uint16_t port)
Create an IPv6 address and initialize only the port part.
IPv6Address(struct sockaddr_in6 &sa)
Create an IPv4 address object and copy the given sockaddr_in structure.