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