Add a default timeout parameter to HHWheelTimer.
[folly.git] / folly / SocketAddress.cpp
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 #ifndef __STDC_FORMAT_MACROS
18   #define __STDC_FORMAT_MACROS
19 #endif
20
21 #include <folly/SocketAddress.h>
22
23 #include <folly/Hash.h>
24
25 #include <boost/functional/hash.hpp>
26 #include <boost/static_assert.hpp>
27 #include <string.h>
28 #include <stdio.h>
29 #include <errno.h>
30 #include <sstream>
31 #include <string>
32
33 namespace {
34
35 /**
36  * A structure to free a struct addrinfo when it goes out of scope.
37  */
38 struct ScopedAddrInfo {
39   explicit ScopedAddrInfo(struct addrinfo* info) : info(info) {}
40   ~ScopedAddrInfo() {
41     freeaddrinfo(info);
42   }
43
44   struct addrinfo* info;
45 };
46
47 /**
48  * A simple data structure for parsing a host-and-port string.
49  *
50  * Accepts a string of the form "<host>:<port>" or just "<port>",
51  * and contains two string pointers to the host and the port portion of the
52  * string.
53  *
54  * The HostAndPort may contain pointers into the original string.  It is
55  * responsible for the user to ensure that the input string is valid for the
56  * lifetime of the HostAndPort structure.
57  */
58 struct HostAndPort {
59   HostAndPort(const char* str, bool hostRequired)
60     : host(nullptr),
61       port(nullptr),
62       allocated(nullptr) {
63
64     // Look for the last colon
65     const char* colon = strrchr(str, ':');
66     if (colon == nullptr) {
67       // No colon, just a port number.
68       if (hostRequired) {
69         throw std::invalid_argument(
70           "expected a host and port string of the "
71           "form \"<host>:<port>\"");
72       }
73       port = str;
74       return;
75     }
76
77     // We have to make a copy of the string so we can modify it
78     // and change the colon to a NUL terminator.
79     allocated = strdup(str);
80     if (!allocated) {
81       throw std::bad_alloc();
82     }
83
84     char *allocatedColon = allocated + (colon - str);
85     *allocatedColon = '\0';
86     host = allocated;
87     port = allocatedColon + 1;
88     // bracketed IPv6 address, remove the brackets
89     // allocatedColon[-1] is fine, as allocatedColon >= host and
90     // *allocatedColon != *host therefore allocatedColon > host
91     if (*host == '[' && allocatedColon[-1] == ']') {
92       allocatedColon[-1] = '\0';
93       ++host;
94     }
95   }
96
97   ~HostAndPort() {
98     free(allocated);
99   }
100
101   const char* host;
102   const char* port;
103   char* allocated;
104 };
105
106 } // unnamed namespace
107
108 namespace folly {
109
110 bool SocketAddress::isPrivateAddress() const {
111   auto family = getFamily();
112   if (family == AF_INET || family == AF_INET6) {
113     return storage_.addr.isPrivate() ||
114       (storage_.addr.isV6() && storage_.addr.asV6().isLinkLocal());
115   } else if (external_) {
116     // Unix addresses are always local to a host.  Return true,
117     // since this conforms to the semantics of returning true for IP loopback
118     // addresses.
119     return true;
120   }
121   return false;
122 }
123
124 bool SocketAddress::isLoopbackAddress() const {
125   auto family = getFamily();
126   if (family == AF_INET || family == AF_INET6) {
127     return storage_.addr.isLoopback();
128   } else if (external_) {
129     // Return true for UNIX addresses, since they are always local to a host.
130     return true;
131   }
132   return false;
133 }
134
135 void SocketAddress::setFromHostPort(const char* host, uint16_t port) {
136   ScopedAddrInfo results(getAddrInfo(host, port, 0));
137   setFromAddrInfo(results.info);
138 }
139
140 void SocketAddress::setFromIpPort(const char* ip, uint16_t port) {
141   ScopedAddrInfo results(getAddrInfo(ip, port, AI_NUMERICHOST));
142   setFromAddrInfo(results.info);
143 }
144
145 void SocketAddress::setFromIpAddrPort(const IPAddress& ipAddr, uint16_t port) {
146   if (external_) {
147     storage_.un.free();
148     external_ = false;
149   }
150   storage_.addr = ipAddr;
151   port_ = port;
152 }
153
154 void SocketAddress::setFromLocalPort(uint16_t port) {
155   ScopedAddrInfo results(getAddrInfo(nullptr, port, AI_ADDRCONFIG));
156   setFromLocalAddr(results.info);
157 }
158
159 void SocketAddress::setFromLocalPort(const char* port) {
160   ScopedAddrInfo results(getAddrInfo(nullptr, port, AI_ADDRCONFIG));
161   setFromLocalAddr(results.info);
162 }
163
164 void SocketAddress::setFromLocalIpPort(const char* addressAndPort) {
165   HostAndPort hp(addressAndPort, false);
166   ScopedAddrInfo results(getAddrInfo(hp.host, hp.port,
167                                      AI_NUMERICHOST | AI_ADDRCONFIG));
168   setFromLocalAddr(results.info);
169 }
170
171 void SocketAddress::setFromIpPort(const char* addressAndPort) {
172   HostAndPort hp(addressAndPort, true);
173   ScopedAddrInfo results(getAddrInfo(hp.host, hp.port, AI_NUMERICHOST));
174   setFromAddrInfo(results.info);
175 }
176
177 void SocketAddress::setFromHostPort(const char* hostAndPort) {
178   HostAndPort hp(hostAndPort, true);
179   ScopedAddrInfo results(getAddrInfo(hp.host, hp.port, 0));
180   setFromAddrInfo(results.info);
181 }
182
183 void SocketAddress::setFromPath(const char* path, size_t len) {
184   if (!external_) {
185     storage_.un.init();
186     external_ = true;
187   }
188
189   storage_.un.len = offsetof(struct sockaddr_un, sun_path) + len;
190   if (len > sizeof(storage_.un.addr->sun_path)) {
191     throw std::invalid_argument(
192       "socket path too large to fit into sockaddr_un");
193   } else if (len == sizeof(storage_.un.addr->sun_path)) {
194     // Note that there will be no terminating NUL in this case.
195     // We allow this since getsockname() and getpeername() may return
196     // Unix socket addresses with paths that fit exactly in sun_path with no
197     // terminating NUL.
198     memcpy(storage_.un.addr->sun_path, path, len);
199   } else {
200     memcpy(storage_.un.addr->sun_path, path, len + 1);
201   }
202 }
203
204 void SocketAddress::setFromPeerAddress(SocketDesc socket) {
205   setFromSocket(socket, getpeername);
206 }
207
208 void SocketAddress::setFromLocalAddress(SocketDesc socket) {
209   setFromSocket(socket, getsockname);
210 }
211
212 void SocketAddress::setFromSockaddr(const struct sockaddr* address) {
213   uint16_t port;
214
215   if (address->sa_family == AF_INET) {
216     port = ntohs(((sockaddr_in*)address)->sin_port);
217   } else if (address->sa_family == AF_INET6) {
218     port = ntohs(((sockaddr_in6*)address)->sin6_port);
219   } else if (address->sa_family == AF_UNIX) {
220     // We need an explicitly specified length for AF_UNIX addresses,
221     // to be able to distinguish anonymous addresses from addresses
222     // in Linux's abstract namespace.
223     throw std::invalid_argument(
224       "SocketAddress::setFromSockaddr(): the address "
225       "length must be explicitly specified when "
226       "setting AF_UNIX addresses");
227   } else {
228     throw std::invalid_argument(
229       "SocketAddress::setFromSockaddr() called "
230       "with unsupported address type");
231   }
232
233   setFromIpAddrPort(folly::IPAddress(address), port);
234 }
235
236 void SocketAddress::setFromSockaddr(const struct sockaddr* address,
237                                      socklen_t addrlen) {
238   // Check the length to make sure we can access address->sa_family
239   if (addrlen < (offsetof(struct sockaddr, sa_family) +
240                  sizeof(address->sa_family))) {
241     throw std::invalid_argument(
242       "SocketAddress::setFromSockaddr() called "
243       "with length too short for a sockaddr");
244   }
245
246   if (address->sa_family == AF_INET) {
247     if (addrlen < sizeof(struct sockaddr_in)) {
248       throw std::invalid_argument(
249         "SocketAddress::setFromSockaddr() called "
250         "with length too short for a sockaddr_in");
251     }
252     setFromSockaddr(reinterpret_cast<const struct sockaddr_in*>(address));
253   } else if (address->sa_family == AF_INET6) {
254     if (addrlen < sizeof(struct sockaddr_in6)) {
255       throw std::invalid_argument(
256         "SocketAddress::setFromSockaddr() called "
257         "with length too short for a sockaddr_in6");
258     }
259     setFromSockaddr(reinterpret_cast<const struct sockaddr_in6*>(address));
260   } else if (address->sa_family == AF_UNIX) {
261     setFromSockaddr(reinterpret_cast<const struct sockaddr_un*>(address),
262                     addrlen);
263   } else {
264     throw std::invalid_argument(
265       "SocketAddress::setFromSockaddr() called "
266       "with unsupported address type");
267   }
268 }
269
270 void SocketAddress::setFromSockaddr(const struct sockaddr_in* address) {
271   assert(address->sin_family == AF_INET);
272   setFromSockaddr((sockaddr*)address);
273 }
274
275 void SocketAddress::setFromSockaddr(const struct sockaddr_in6* address) {
276   assert(address->sin6_family == AF_INET6);
277   setFromSockaddr((sockaddr*)address);
278 }
279
280 void SocketAddress::setFromSockaddr(const struct sockaddr_un* address,
281                                      socklen_t addrlen) {
282   assert(address->sun_family == AF_UNIX);
283   if (addrlen > sizeof(struct sockaddr_un)) {
284     throw std::invalid_argument(
285       "SocketAddress::setFromSockaddr() called "
286       "with length too long for a sockaddr_un");
287   }
288
289   prepFamilyChange(AF_UNIX);
290   memcpy(storage_.un.addr, address, addrlen);
291   updateUnixAddressLength(addrlen);
292
293   // Fill the rest with 0s, just for safety
294   if (addrlen < sizeof(struct sockaddr_un)) {
295     char *p = reinterpret_cast<char*>(storage_.un.addr);
296     memset(p + addrlen, 0, sizeof(struct sockaddr_un) - addrlen);
297   }
298 }
299
300 const folly::IPAddress& SocketAddress::getIPAddress() const {
301   auto family = getFamily();
302   if (family != AF_INET && family != AF_INET6) {
303     throw InvalidAddressFamilyException(family);
304   }
305   return storage_.addr;
306 }
307
308 socklen_t SocketAddress::getActualSize() const {
309   if (external_) {
310     return storage_.un.len;
311   }
312   switch (getFamily()) {
313     case AF_UNSPEC:
314     case AF_INET:
315       return sizeof(struct sockaddr_in);
316     case AF_INET6:
317       return sizeof(struct sockaddr_in6);
318     default:
319       throw std::invalid_argument(
320         "SocketAddress::getActualSize() called "
321         "with unrecognized address family");
322   }
323 }
324
325 std::string SocketAddress::getFullyQualified() const {
326   auto family = getFamily();
327   if (family != AF_INET && family != AF_INET6) {
328     throw std::invalid_argument("Can't get address str for non ip address");
329   }
330   return storage_.addr.toFullyQualified();
331 }
332
333 std::string SocketAddress::getAddressStr() const {
334   char buf[INET6_ADDRSTRLEN];
335   getAddressStr(buf, sizeof(buf));
336   return buf;
337 }
338
339 void SocketAddress::getAddressStr(char* buf, size_t buflen) const {
340   auto family = getFamily();
341   if (family != AF_INET && family != AF_INET6) {
342     throw std::invalid_argument("Can't get address str for non ip address");
343   }
344   std::string ret = storage_.addr.str();
345   size_t len = std::min(buflen, ret.size());
346   memcpy(buf, ret.data(), len);
347   buf[len] = '\0';
348 }
349
350 uint16_t SocketAddress::getPort() const {
351   switch (getFamily()) {
352     case AF_INET:
353     case AF_INET6:
354       return port_;
355     default:
356       throw std::invalid_argument(
357         "SocketAddress::getPort() called on non-IP "
358         "address");
359   }
360 }
361
362 void SocketAddress::setPort(uint16_t port) {
363   switch (getFamily()) {
364     case AF_INET:
365     case AF_INET6:
366       port_ = port;
367       return;
368     default:
369       throw std::invalid_argument(
370         "SocketAddress::setPort() called on non-IP "
371         "address");
372   }
373 }
374
375 void SocketAddress::convertToIPv4() {
376   if (!tryConvertToIPv4()) {
377     throw std::invalid_argument(
378       "convertToIPv4() called on an addresse that is "
379       "not an IPv4-mapped address");
380   }
381 }
382
383 bool SocketAddress::tryConvertToIPv4() {
384   if (!isIPv4Mapped()) {
385     return false;
386   }
387
388   storage_.addr = folly::IPAddress::createIPv4(storage_.addr);
389   return true;
390 }
391
392 bool SocketAddress::mapToIPv6() {
393   if (getFamily() != AF_INET) {
394     return false;
395   }
396
397   storage_.addr = folly::IPAddress::createIPv6(storage_.addr);
398   return true;
399 }
400
401 std::string SocketAddress::getHostStr() const {
402   return getIpString(0);
403 }
404
405 std::string SocketAddress::getPath() const {
406   if (!external_) {
407     throw std::invalid_argument(
408       "SocketAddress: attempting to get path "
409       "for a non-Unix address");
410   }
411
412   if (storage_.un.pathLength() == 0) {
413     // anonymous address
414     return std::string();
415   }
416   if (storage_.un.addr->sun_path[0] == '\0') {
417     // abstract namespace
418     return std::string(storage_.un.addr->sun_path, storage_.un.pathLength());
419   }
420
421   return std::string(storage_.un.addr->sun_path,
422                      strnlen(storage_.un.addr->sun_path,
423                              storage_.un.pathLength()));
424 }
425
426 std::string SocketAddress::describe() const {
427   if (external_) {
428     if (storage_.un.pathLength() == 0) {
429       return "<anonymous unix address>";
430     }
431
432     if (storage_.un.addr->sun_path[0] == '\0') {
433       // Linux supports an abstract namespace for unix socket addresses
434       return "<abstract unix address>";
435     }
436
437     return std::string(storage_.un.addr->sun_path,
438                        strnlen(storage_.un.addr->sun_path,
439                                storage_.un.pathLength()));
440   }
441   switch (getFamily()) {
442     case AF_UNSPEC:
443       return "<uninitialized address>";
444     case AF_INET:
445     {
446       char buf[NI_MAXHOST + 16];
447       getAddressStr(buf, sizeof(buf));
448       size_t iplen = strlen(buf);
449       snprintf(buf + iplen, sizeof(buf) - iplen, ":%" PRIu16, getPort());
450       return buf;
451     }
452     case AF_INET6:
453     {
454       char buf[NI_MAXHOST + 18];
455       buf[0] = '[';
456       getAddressStr(buf + 1, sizeof(buf) - 1);
457       size_t iplen = strlen(buf);
458       snprintf(buf + iplen, sizeof(buf) - iplen, "]:%" PRIu16, getPort());
459       return buf;
460     }
461     default:
462     {
463       char buf[64];
464       snprintf(buf, sizeof(buf), "<unknown address family %d>",
465                getFamily());
466       return buf;
467     }
468   }
469 }
470
471 bool SocketAddress::operator==(const SocketAddress& other) const {
472   if (external_ != other.external_ || other.getFamily() != getFamily()) {
473     return false;
474   }
475   if (external_) {
476     // anonymous addresses are never equal to any other addresses
477     if (storage_.un.pathLength() == 0 ||
478         other.storage_.un.pathLength() == 0) {
479       return false;
480     }
481
482     if (storage_.un.len != other.storage_.un.len) {
483       return false;
484     }
485     int cmp = memcmp(storage_.un.addr->sun_path,
486                      other.storage_.un.addr->sun_path,
487                      storage_.un.pathLength());
488     return cmp == 0;
489   }
490
491   switch (getFamily()) {
492     case AF_INET:
493     case AF_INET6:
494       return (other.storage_.addr == storage_.addr) &&
495         (other.port_ == port_);
496     default:
497       throw std::invalid_argument(
498         "SocketAddress: unsupported address family "
499         "for comparison");
500   }
501 }
502
503 bool SocketAddress::prefixMatch(const SocketAddress& other,
504     unsigned prefixLength) const {
505   if (other.getFamily() != getFamily()) {
506     return false;
507   }
508   int mask_length = 128;
509   switch (getFamily()) {
510     case AF_INET:
511       mask_length = 32;
512       // fallthrough
513     case AF_INET6:
514     {
515       auto prefix = folly::IPAddress::longestCommonPrefix(
516         {storage_.addr, mask_length},
517         {other.storage_.addr, mask_length});
518       return prefix.second >= prefixLength;
519     }
520     default:
521       return false;
522   }
523 }
524
525
526 size_t SocketAddress::hash() const {
527   size_t seed = folly::hash::twang_mix64(getFamily());
528
529   if (external_) {
530     enum { kUnixPathMax = sizeof(storage_.un.addr->sun_path) };
531     const char *path = storage_.un.addr->sun_path;
532     size_t pathLength = storage_.un.pathLength();
533     // TODO: this probably could be made more efficient
534     for (unsigned int n = 0; n < pathLength; ++n) {
535       boost::hash_combine(seed, folly::hash::twang_mix64(path[n]));
536     }
537   }
538
539   switch (getFamily()) {
540     case AF_INET:
541     case AF_INET6: {
542       boost::hash_combine(seed, port_);
543       boost::hash_combine(seed, storage_.addr.hash());
544       break;
545     }
546     case AF_UNIX:
547       DCHECK(external_);
548       break;
549     case AF_UNSPEC:
550     default:
551       throw std::invalid_argument(
552         "SocketAddress: unsupported address family "
553         "for hashing");
554   }
555
556   return seed;
557 }
558
559 struct addrinfo* SocketAddress::getAddrInfo(const char* host,
560                                              uint16_t port,
561                                              int flags) {
562   // getaddrinfo() requires the port number as a string
563   char portString[sizeof("65535")];
564   snprintf(portString, sizeof(portString), "%" PRIu16, port);
565
566   return getAddrInfo(host, portString, flags);
567 }
568
569 struct addrinfo* SocketAddress::getAddrInfo(const char* host,
570                                              const char* port,
571                                              int flags) {
572   struct addrinfo hints;
573   memset(&hints, 0, sizeof(hints));
574   hints.ai_family = AF_UNSPEC;
575   hints.ai_socktype = SOCK_STREAM;
576   hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV | flags;
577
578   struct addrinfo *results;
579   int error = getaddrinfo(host, port, &hints, &results);
580   if (error != 0) {
581     auto os = folly::to<std::string>(
582       "Failed to resolve address for \"", host,  "\": ",
583       gai_strerror(error), " (error=", error,  ")");
584     throw std::system_error(error, std::generic_category(), os);
585   }
586
587   return results;
588 }
589
590 void SocketAddress::setFromAddrInfo(const struct addrinfo* info) {
591   setFromSockaddr(info->ai_addr, info->ai_addrlen);
592 }
593
594 void SocketAddress::setFromLocalAddr(const struct addrinfo* info) {
595   // If an IPv6 address is present, prefer to use it, since IPv4 addresses
596   // can be mapped into IPv6 space.
597   for (const struct addrinfo* ai = info; ai != nullptr; ai = ai->ai_next) {
598     if (ai->ai_family == AF_INET6) {
599       setFromSockaddr(ai->ai_addr, ai->ai_addrlen);
600       return;
601     }
602   }
603
604   // Otherwise, just use the first address in the list.
605   setFromSockaddr(info->ai_addr, info->ai_addrlen);
606 }
607
608 void SocketAddress::setFromSocket(SocketDesc socket, GetPeerNameFunc fn) {
609   // Try to put the address into a local storage buffer.
610   sockaddr_storage tmp_sock;
611   socklen_t addrLen = sizeof(tmp_sock);
612   if (fn(socket, (sockaddr*)&tmp_sock, &addrLen) != 0) {
613     folly::throwSystemError("setFromSocket() failed");
614   }
615
616   setFromSockaddr((sockaddr*)&tmp_sock, addrLen);
617 }
618
619 std::string SocketAddress::getIpString(int flags) const {
620   char addrString[NI_MAXHOST];
621   getIpString(addrString, sizeof(addrString), flags);
622   return std::string(addrString);
623 }
624
625 void SocketAddress::getIpString(char *buf, size_t buflen, int flags) const {
626   auto family = getFamily();
627   if (family != AF_INET &&
628       family != AF_INET6) {
629     throw std::invalid_argument(
630       "SocketAddress: attempting to get IP address "
631       "for a non-IP address");
632   }
633
634   sockaddr_storage tmp_sock;
635   storage_.addr.toSockaddrStorage(&tmp_sock, port_);
636   int rc = getnameinfo((sockaddr*)&tmp_sock, sizeof(sockaddr_storage),
637                        buf, buflen, nullptr, 0, flags);
638   if (rc != 0) {
639     auto os = folly::to<std::string>(
640       "getnameinfo() failed in getIpString() error = ",
641       gai_strerror(rc));
642     throw std::system_error(rc, std::generic_category(), os);
643   }
644 }
645
646 void SocketAddress::updateUnixAddressLength(socklen_t addrlen) {
647   if (addrlen < offsetof(struct sockaddr_un, sun_path)) {
648     throw std::invalid_argument(
649       "SocketAddress: attempted to set a Unix socket "
650       "with a length too short for a sockaddr_un");
651   }
652
653   storage_.un.len = addrlen;
654   if (storage_.un.pathLength() == 0) {
655     // anonymous address
656     return;
657   }
658
659   if (storage_.un.addr->sun_path[0] == '\0') {
660     // abstract namespace.  honor the specified length
661   } else {
662     // Call strnlen(), just in case the length was overspecified.
663     socklen_t maxLength = addrlen - offsetof(struct sockaddr_un, sun_path);
664     size_t pathLength = strnlen(storage_.un.addr->sun_path, maxLength);
665     storage_.un.len = offsetof(struct sockaddr_un, sun_path) + pathLength;
666   }
667 }
668
669 bool SocketAddress::operator<(const SocketAddress& other) const {
670   if (getFamily() != other.getFamily()) {
671     return getFamily() < other.getFamily();
672   }
673
674   if (external_) {
675     // Anonymous addresses can't be compared to anything else.
676     // Return that they are never less than anything.
677     //
678     // Note that this still meets the requirements for a strict weak
679     // ordering, so we can use this operator<() with standard C++ containers.
680     size_t thisPathLength = storage_.un.pathLength();
681     if (thisPathLength == 0) {
682       return false;
683     }
684     size_t otherPathLength = other.storage_.un.pathLength();
685     if (otherPathLength == 0) {
686       return true;
687     }
688
689     // Compare based on path length first, for efficiency
690     if (thisPathLength != otherPathLength) {
691       return thisPathLength < otherPathLength;
692     }
693     int cmp = memcmp(storage_.un.addr->sun_path,
694                      other.storage_.un.addr->sun_path,
695                      thisPathLength);
696     return cmp < 0;
697   }
698   switch (getFamily()) {
699     case AF_INET:
700     case AF_INET6: {
701       if (port_ != other.port_) {
702         return port_ < other.port_;
703       }
704
705       return
706         storage_.addr < other.storage_.addr;
707     }
708     case AF_UNSPEC:
709     default:
710       throw std::invalid_argument(
711         "SocketAddress: unsupported address family for comparing");
712   }
713 }
714
715 size_t hash_value(const SocketAddress& address) {
716   return address.hash();
717 }
718
719 std::ostream& operator<<(std::ostream& os, const SocketAddress& addr) {
720   os << addr.describe();
721   return os;
722 }
723
724 } // folly