move socketaddress to folly
[folly.git] / folly / SocketAddress.h
1 /*
2  * Copyright 2014 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #pragma once
18
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <sys/un.h>
22 #include <netinet/in.h>
23 #include <features.h>
24 #include <netdb.h>
25 #include <cstddef>
26 #include <iostream>
27 #include <string>
28
29 #include <folly/IPAddress.h>
30
31 namespace folly {
32
33 class SocketAddress {
34  public:
35   SocketAddress() {
36     storage_.addr = folly::IPAddress();
37   }
38
39   /**
40    * Construct a SocketAddress from a hostname and port.
41    *
42    * Note: If the host parameter is not a numeric IP address, hostname
43    * resolution will be performed, which can be quite slow.
44    *
45    * Raises std::system_error on error.
46    *
47    * @param host The IP address (or hostname, if allowNameLookup is true)
48    * @param port The port (in host byte order)
49    * @pram allowNameLookup  If true, attempt to perform hostname lookup
50    *        if the hostname does not appear to be a numeric IP address.
51    *        This is potentially a very slow operation, so is disabled by
52    *        default.
53    */
54   SocketAddress(const char* host, uint16_t port,
55                  bool allowNameLookup = false) {
56     // Initialize the address family first,
57     // since setFromHostPort() and setFromIpPort() will check it.
58
59     if (allowNameLookup) {
60       setFromHostPort(host, port);
61     } else {
62       setFromIpPort(host, port);
63     }
64   }
65
66   SocketAddress(const std::string& host, uint16_t port,
67                  bool allowNameLookup = false) {
68     // Initialize the address family first,
69     // since setFromHostPort() and setFromIpPort() will check it.
70
71     if (allowNameLookup) {
72       setFromHostPort(host.c_str(), port);
73     } else {
74       setFromIpPort(host.c_str(), port);
75     }
76   }
77
78   SocketAddress(const SocketAddress& addr) {
79     storage_ = addr.storage_;
80     port_ = addr.port_;
81     if (addr.getFamily() == AF_UNIX) {
82       storage_.un.init(addr.storage_.un);
83     }
84     external_ = addr.external_;
85   }
86
87   SocketAddress& operator=(const SocketAddress& addr) {
88     if (getFamily() != AF_UNIX) {
89       if (addr.getFamily() != AF_UNIX) {
90         storage_ = addr.storage_;
91       } else {
92         storage_ = addr.storage_;
93         storage_.un.init(addr.storage_.un);
94       }
95     } else {
96       if (addr.getFamily() == AF_UNIX) {
97         storage_.un.copy(addr.storage_.un);
98       } else {
99         storage_.un.free();
100         storage_ = addr.storage_;
101       }
102     }
103     port_ = addr.port_;
104     external_ = addr.external_;
105     return *this;
106   }
107
108   SocketAddress(SocketAddress&& addr) {
109     storage_ = addr.storage_;
110     port_ = addr.port_;
111     external_ = addr.external_;
112     addr.external_ = false;
113   }
114
115   SocketAddress& operator=(SocketAddress&& addr) {
116     std::swap(storage_, addr.storage_);
117     std::swap(port_, addr.port_);
118     std::swap(external_, addr.external_);
119     return *this;
120   }
121
122   ~SocketAddress() {
123     if (getFamily() == AF_UNIX) {
124       storage_.un.free();
125     }
126   }
127
128   bool isInitialized() const {
129     return (getFamily() != AF_UNSPEC);
130   }
131
132   /**
133    * Return whether this address is within private network.
134    *
135    * According to RFC1918, the 10/8 prefix, 172.16/12 prefix, and 192.168/16
136    * prefix are reserved for private networks.
137    * fc00::/7 is the IPv6 version, defined in RFC4139.  IPv6 link-local
138    * addresses (fe80::/10) are also considered private addresses.
139    *
140    * The loopback addresses 127/8 and ::1 are also regarded as private networks
141    * for the purpose of this function.
142    *
143    * Returns true if this is a private network address, and false otherwise.
144    */
145   bool isPrivateAddress() const;
146
147   /**
148    * Return whether this address is a loopback address.
149    */
150   bool isLoopbackAddress() const;
151
152   void reset() {
153     prepFamilyChange(AF_UNSPEC);
154   }
155
156   /**
157    * Initialize this SocketAddress from a hostname and port.
158    *
159    * Note: If the host parameter is not a numeric IP address, hostname
160    * resolution will be performed, which can be quite slow.
161    *
162    * If the hostname resolves to multiple addresses, only the first will be
163    * returned.
164    *
165    * Raises std::system_error on error.
166    *
167    * @param host The hostname or IP address
168    * @param port The port (in host byte order)
169    */
170   void setFromHostPort(const char* host, uint16_t port);
171
172   void setFromHostPort(const std::string& host, uint16_t port) {
173     setFromHostPort(host.c_str(), port);
174   }
175
176   /**
177    * Initialize this SocketAddress from an IP address and port.
178    *
179    * This is similar to setFromHostPort(), but only accepts numeric IP
180    * addresses.  If the IP string does not look like an IP address, it throws a
181    * std::invalid_argument rather than trying to perform a hostname resolution.
182    *
183    * Raises std::system_error on error.
184    *
185    * @param ip The IP address, as a human-readable string.
186    * @param port The port (in host byte order)
187    */
188   void setFromIpPort(const char* ip, uint16_t port);
189
190   void setFromIpPort(const std::string& ip, uint16_t port) {
191     setFromIpPort(ip.c_str(), port);
192   }
193
194   /**
195    * Initialize this SocketAddress from a local port number.
196    *
197    * This is intended to be used by server code to determine the address to
198    * listen on.
199    *
200    * If the current machine has any IPv6 addresses configured, an IPv6 address
201    * will be returned (since connections from IPv4 clients can be mapped to the
202    * IPv6 address).  If the machine does not have any IPv6 addresses, an IPv4
203    * address will be returned.
204    */
205   void setFromLocalPort(uint16_t port);
206
207   /**
208    * Initialize this SocketAddress from a local port number.
209    *
210    * This version of setFromLocalPort() accepts the port as a string.  A
211    * std::invalid_argument will be raised if the string does not refer to a port
212    * number.  Non-numeric service port names are not accepted.
213    */
214   void setFromLocalPort(const char* port);
215   void setFromLocalPort(const std::string& port) {
216     return setFromLocalPort(port.c_str());
217   }
218
219   /**
220    * Initialize this SocketAddress from a local port number and optional IP
221    * address.
222    *
223    * The addressAndPort string may be specified either as "<ip>:<port>", or
224    * just as "<port>".  If the IP is not specified, the address will be
225    * initialized to 0, so that a server socket bound to this address will
226    * accept connections on all local IP addresses.
227    *
228    * Both the IP address and port number must be numeric.  DNS host names and
229    * non-numeric service port names are not accepted.
230    */
231   void setFromLocalIpPort(const char* addressAndPort);
232   void setFromLocalIpPort(const std::string& addressAndPort) {
233     return setFromLocalIpPort(addressAndPort.c_str());
234   }
235
236   /**
237    * Initialize this SocketAddress from an IP address and port number.
238    *
239    * The addressAndPort string must be of the form "<ip>:<port>".  E.g.,
240    * "10.0.0.1:1234".
241    *
242    * Both the IP address and port number must be numeric.  DNS host names and
243    * non-numeric service port names are not accepted.
244    */
245   void setFromIpPort(const char* addressAndPort);
246   void setFromIpPort(const std::string& addressAndPort) {
247     return setFromIpPort(addressAndPort.c_str());
248   }
249
250   /**
251    * Initialize this SocketAddress from a host name and port number.
252    *
253    * The addressAndPort string must be of the form "<host>:<port>".  E.g.,
254    * "www.facebook.com:443".
255    *
256    * If the host name is not a numeric IP address, a DNS lookup will be
257    * performed.  Beware that the DNS lookup may be very slow.  The port number
258    * must be numeric; non-numeric service port names are not accepted.
259    */
260   void setFromHostPort(const char* hostAndPort);
261   void setFromHostPort(const std::string& hostAndPort) {
262     return setFromHostPort(hostAndPort.c_str());
263   }
264
265   /**
266    * Initialize this SocketAddress from a local unix path.
267    *
268    * Raises std::invalid_argument on error.
269    */
270   void setFromPath(const char* path) {
271     setFromPath(path, strlen(path));
272   }
273
274   void setFromPath(const std::string& path) {
275     setFromPath(path.data(), path.length());
276   }
277
278   void setFromPath(const char* path, size_t length);
279
280   /**
281    * Initialize this SocketAddress from a socket's peer address.
282    *
283    * Raises std::system_error on error.
284    */
285   void setFromPeerAddress(int socket);
286
287   /**
288    * Initialize this SocketAddress from a socket's local address.
289    *
290    * Raises std::system_error on error.
291    */
292   void setFromLocalAddress(int socket);
293
294   /**
295    * Initialize this TSocketAddress from a struct sockaddr.
296    *
297    * Raises std::system_error on error.
298    *
299    * This method is not supported for AF_UNIX addresses.  For unix addresses,
300    * the address length must be explicitly specified.
301    *
302    * @param address  A struct sockaddr.  The size of the address is implied
303    *                 from address->sa_family.
304    */
305   void setFromSockaddr(const struct sockaddr* address);
306
307   /**
308    * Initialize this SocketAddress from a struct sockaddr.
309    *
310    * Raises std::system_error on error.
311    *
312    * @param address  A struct sockaddr.
313    * @param addrlen  The length of address data available.  This must be long
314    *                 enough for the full address type required by
315    *                 address->sa_family.
316    */
317   void setFromSockaddr(const struct sockaddr* address,
318                        socklen_t addrlen);
319
320   /**
321    * Initialize this SocketAddress from a struct sockaddr_in.
322    */
323   void setFromSockaddr(const struct sockaddr_in* address);
324
325   /**
326    * Initialize this SocketAddress from a struct sockaddr_in6.
327    */
328   void setFromSockaddr(const struct sockaddr_in6* address);
329
330   /**
331    * Initialize this SocketAddress from a struct sockaddr_un.
332    *
333    * Note that the addrlen parameter is necessary to properly detect anonymous
334    * addresses, which have 0 valid path bytes, and may not even have a NUL
335    * character at the start of the path.
336    *
337    * @param address  A struct sockaddr_un.
338    * @param addrlen  The length of address data.  This should include all of
339    *                 the valid bytes of sun_path, not including any NUL
340    *                 terminator.
341    */
342   void setFromSockaddr(const struct sockaddr_un* address,
343                        socklen_t addrlen);
344
345
346   /**
347    * Fill in a given sockaddr_storage with the ip or unix address.
348    *
349    * Returns the actual size of the storage used.
350    */
351   socklen_t getAddress(sockaddr_storage* addr) const {
352     if (getFamily() != AF_UNIX) {
353       return storage_.addr.toSockaddrStorage(addr, htons(port_));
354     } else {
355       memcpy(addr, storage_.un.addr, sizeof(*storage_.un.addr));
356       return storage_.un.len;
357     }
358   }
359
360   const folly::IPAddress& getIPAddress() const;
361
362   // Deprecated: getAddress() above returns the same size as getActualSize()
363   socklen_t getActualSize() const;
364
365   sa_family_t getFamily() const {
366     return external_ ? AF_UNIX : storage_.addr.family();
367   }
368
369   bool empty() const {
370     return getFamily() == AF_UNSPEC;
371   }
372
373   /**
374    * Get a string representation of the IPv4 or IPv6 address.
375    *
376    * Raises std::invalid_argument if an error occurs (for example, if
377    * the address is not an IPv4 or IPv6 address).
378    */
379   std::string getAddressStr() const;
380
381   /**
382    * Get a string representation of the IPv4 or IPv6 address.
383    *
384    * Raises std::invalid_argument if an error occurs (for example, if
385    * the address is not an IPv4 or IPv6 address).
386    */
387   void getAddressStr(char* buf, size_t buflen) const;
388
389   /**
390    * For v4 & v6 addresses, return the fully qualified address string
391    */
392   std::string getFullyQualified() const;
393
394   /**
395    * Get the IPv4 or IPv6 port for this address.
396    *
397    * Raises std::invalid_argument if this is not an IPv4 or IPv6 address.
398    *
399    * @return Returns the port, in host byte order.
400    */
401   uint16_t getPort() const;
402
403   /**
404    * Set the IPv4 or IPv6 port for this address.
405    *
406    * Raises std::invalid_argument if this is not an IPv4 or IPv6 address.
407    */
408   void setPort(uint16_t port);
409
410   /**
411    * Return true if this is an IPv4-mapped IPv6 address.
412    */
413   bool isIPv4Mapped() const {
414     return (getFamily() == AF_INET6 &&
415             storage_.addr.isIPv4Mapped());
416   }
417
418   /**
419    * Convert an IPv4-mapped IPv6 address to an IPv4 address.
420    *
421    * Raises std::invalid_argument if this is not an IPv4-mapped IPv6 address.
422    */
423   void convertToIPv4();
424
425   /**
426    * Try to convert an address to IPv4.
427    *
428    * This attempts to convert an address to an IPv4 address if possible.
429    * If the address is an IPv4-mapped IPv6 address, it is converted to an IPv4
430    * address and true is returned.  Otherwise nothing is done, and false is
431    * returned.
432    */
433   bool tryConvertToIPv4();
434
435   /**
436    * Convert an IPv4 address to IPv6 [::ffff:a.b.c.d]
437    */
438
439   bool mapToIPv6();
440
441   /**
442    * Get string representation of the host name (or IP address if the host name
443    * cannot be resolved).
444    *
445    * Warning: Using this method is strongly discouraged.  It performs a
446    * DNS lookup, which may block for many seconds.
447    *
448    * Raises std::invalid_argument if an error occurs.
449    */
450   std::string getHostStr() const;
451
452   /**
453    * Get the path name for a Unix domain socket.
454    *
455    * Returns a std::string containing the path.  For anonymous sockets, an
456    * empty string is returned.
457    *
458    * For addresses in the abstract namespace (Linux-specific), a std::string
459    * containing binary data is returned.  In this case the first character will
460    * always be a NUL character.
461    *
462    * Raises std::invalid_argument if called on a non-Unix domain socket.
463    */
464   std::string getPath() const;
465
466   /**
467    * Get human-readable string representation of the address.
468    *
469    * This prints a string representation of the address, for human consumption.
470    * For IP addresses, the string is of the form "<IP>:<port>".
471    */
472   std::string describe() const;
473
474   bool operator==(const SocketAddress& other) const;
475   bool operator!=(const SocketAddress& other) const {
476     return !(*this == other);
477   }
478
479   /**
480    * Check whether the first N bits of this address match the first N
481    * bits of another address.
482    * @note returns false if the addresses are not from the same
483    *       address family or if the family is neither IPv4 nor IPv6
484    */
485   bool prefixMatch(const SocketAddress& other, unsigned prefixLength) const;
486
487   /**
488    * Use this operator for storing maps based on SocketAddress.
489    */
490   bool operator<(const SocketAddress& other) const;
491
492   /**
493    * Compuate a hash of a SocketAddress.
494    */
495   size_t hash() const;
496
497  private:
498   /**
499    * Unix socket addresses require more storage than IPv4 and IPv6 addresses,
500    * and are comparatively little-used.
501    *
502    * Therefore SocketAddress' internal storage_ member variable doesn't
503    * contain room for a full unix address, to avoid wasting space in the common
504    * case.  When we do need to store a Unix socket address, we use this
505    * ExternalUnixAddr structure to allocate a struct sockaddr_un separately on
506    * the heap.
507    */
508   struct ExternalUnixAddr {
509     struct sockaddr_un *addr;
510     socklen_t len;
511
512     socklen_t pathLength() const {
513       return len - offsetof(struct sockaddr_un, sun_path);
514     }
515
516     void init() {
517       addr = new sockaddr_un;
518       addr->sun_family = AF_UNIX;
519       len = 0;
520     }
521     void init(const ExternalUnixAddr &other) {
522       addr = new sockaddr_un;
523       len = other.len;
524       memcpy(addr, other.addr, len);
525       // Fill the rest with 0s, just for safety
526       memset(reinterpret_cast<char*>(addr) + len, 0,
527              sizeof(struct sockaddr_un) - len);
528     }
529     void copy(const ExternalUnixAddr &other) {
530       len = other.len;
531       memcpy(addr, other.addr, len);
532     }
533     void free() {
534       delete addr;
535     }
536   };
537
538   struct addrinfo* getAddrInfo(const char* host, uint16_t port, int flags);
539   struct addrinfo* getAddrInfo(const char* host, const char* port, int flags);
540   void setFromAddrInfo(const struct addrinfo* results);
541   void setFromLocalAddr(const struct addrinfo* results);
542   void setFromSocket(int socket, int (*fn)(int, struct sockaddr*, socklen_t*));
543   std::string getIpString(int flags) const;
544   void getIpString(char *buf, size_t buflen, int flags) const;
545
546   void updateUnixAddressLength(socklen_t addrlen);
547
548   void prepFamilyChange(sa_family_t newFamily) {
549     if (newFamily != AF_UNIX) {
550       if (getFamily() == AF_UNIX) {
551         storage_.un.free();
552       }
553       external_ = false;
554     } else {
555       if (getFamily() != AF_UNIX) {
556         storage_.un.init();
557       }
558       external_ = true;
559     }
560   }
561
562   /*
563    * storage_ contains room for a full IPv4 or IPv6 address, so they can be
564    * stored inline without a separate allocation on the heap.
565    *
566    * If we need to store a Unix socket address, ExternalUnixAddr is a shim to
567    * track a struct sockaddr_un allocated separately on the heap.
568    */
569   union {
570     folly::IPAddress addr{};
571     ExternalUnixAddr un;
572   } storage_;
573   // IPAddress class does nto save zone or port, and must be saved here
574   uint16_t port_;
575
576   bool external_{false};
577 };
578
579 /**
580  * Hash a SocketAddress object.
581  *
582  * boost::hash uses hash_value(), so this allows boost::hash to automatically
583  * work for SocketAddress.
584  */
585 size_t hash_value(const SocketAddress& address);
586
587 std::ostream& operator<<(std::ostream& os, const SocketAddress& addr);
588
589 }
590
591 namespace std {
592
593 // Provide an implementation for std::hash<SocketAddress>
594 template<>
595 struct hash<folly::SocketAddress> {
596   size_t operator()(
597       const folly::SocketAddress& addr) const {
598     return addr.hash();
599   }
600 };
601
602 }