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