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