17 #ifndef __STDC_FORMAT_MACROS 18 #define __STDC_FORMAT_MACROS 28 #include <system_error> 30 #include <boost/functional/hash.hpp> 44 struct ScopedAddrInfo {
45 explicit ScopedAddrInfo(
struct addrinfo* addrinfo) :
info(addrinfo) {}
50 struct addrinfo*
info;
65 HostAndPort(
const char* str,
bool hostRequired)
66 : host(
nullptr), port(
nullptr),
allocated(
nullptr) {
68 const char* colon = strrchr(str,
':');
69 if (colon ==
nullptr) {
72 throw std::invalid_argument(
73 "expected a host and port string of the " 74 "form \"<host>:<port>\"");
84 throw std::bad_alloc();
87 char* allocatedColon =
allocated + (colon - str);
88 *allocatedColon =
'\0';
90 port = allocatedColon + 1;
94 if (*host ==
'[' && allocatedColon[-1] ==
']') {
95 allocatedColon[-1] =
'\0';
113 bool SocketAddress::isPrivateAddress()
const {
114 auto family = getFamily();
115 if (family == AF_INET || family == AF_INET6) {
116 return storage_.addr.isPrivate() ||
117 (storage_.addr.isV6() && storage_.addr.asV6().isLinkLocal());
118 }
else if (external_) {
127 bool SocketAddress::isLoopbackAddress()
const {
128 auto family = getFamily();
129 if (family == AF_INET || family == AF_INET6) {
130 return storage_.addr.isLoopback();
131 }
else if (external_) {
138 void SocketAddress::setFromHostPort(
const char* host,
uint16_t port) {
139 ScopedAddrInfo results(getAddrInfo(host, port, 0));
140 setFromAddrInfo(results.info);
143 void SocketAddress::setFromIpPort(
const char* ip,
uint16_t port) {
144 ScopedAddrInfo results(getAddrInfo(ip, port, AI_NUMERICHOST));
145 setFromAddrInfo(results.info);
148 void SocketAddress::setFromIpAddrPort(
const IPAddress& ipAddr,
uint16_t port) {
153 storage_.addr = ipAddr;
157 void SocketAddress::setFromLocalPort(
uint16_t port) {
158 ScopedAddrInfo results(getAddrInfo(
nullptr, port, AI_ADDRCONFIG));
159 setFromLocalAddr(results.info);
162 void SocketAddress::setFromLocalPort(
const char* port) {
163 ScopedAddrInfo results(getAddrInfo(
nullptr, port, AI_ADDRCONFIG));
164 setFromLocalAddr(results.info);
167 void SocketAddress::setFromLocalIpPort(
const char* addressAndPort) {
168 HostAndPort hp(addressAndPort,
false);
169 ScopedAddrInfo results(
170 getAddrInfo(hp.host, hp.port, AI_NUMERICHOST | AI_ADDRCONFIG));
171 setFromLocalAddr(results.info);
174 void SocketAddress::setFromIpPort(
const char* addressAndPort) {
175 HostAndPort hp(addressAndPort,
true);
176 ScopedAddrInfo results(getAddrInfo(hp.host, hp.port, AI_NUMERICHOST));
177 setFromAddrInfo(results.info);
180 void SocketAddress::setFromHostPort(
const char* hostAndPort) {
181 HostAndPort hp(hostAndPort,
true);
182 ScopedAddrInfo results(getAddrInfo(hp.host, hp.port, 0));
183 setFromAddrInfo(results.info);
186 int SocketAddress::getPortFrom(
const struct sockaddr* address) {
187 switch (address->sa_family) {
189 return ntohs(((sockaddr_in*)address)->sin_port);
192 return ntohs(((sockaddr_in6*)address)->sin6_port);
199 const char* SocketAddress::getFamilyNameFrom(
200 const struct sockaddr* address,
201 const char* defaultResult) {
202 #define GETFAMILYNAMEFROM_IMPL(Family) \ 206 switch (address->sa_family) {
213 return defaultResult;
216 #undef GETFAMILYNAMEFROM_IMPL 223 if (path.
size() >
sizeof(storage_.un.addr->sun_path)) {
224 throw std::invalid_argument(
225 "socket path too large to fit into sockaddr_un");
233 size_t len = path.
size();
234 storage_.un.len = socklen_t(offsetof(
struct sockaddr_un, sun_path) + len);
235 memcpy(storage_.un.addr->sun_path, path.
data(), len);
240 if (len <
sizeof(storage_.un.addr->sun_path)) {
241 storage_.un.addr->sun_path[len] =
'\0';
245 void SocketAddress::setFromPeerAddress(
int socket) {
246 setFromPeerAddress(NetworkSocket::fromFd(socket));
253 void SocketAddress::setFromLocalAddress(
int socket) {
254 setFromLocalAddress(NetworkSocket::fromFd(socket));
261 void SocketAddress::setFromSockaddr(
const struct sockaddr* address) {
264 if (address->sa_family == AF_INET) {
265 port = ntohs(((sockaddr_in*)address)->sin_port);
266 }
else if (address->sa_family == AF_INET6) {
267 port = ntohs(((sockaddr_in6*)address)->sin6_port);
268 }
else if (address->sa_family == AF_UNIX) {
272 throw std::invalid_argument(
273 "SocketAddress::setFromSockaddr(): the address " 274 "length must be explicitly specified when " 275 "setting AF_UNIX addresses");
277 throw std::invalid_argument(
278 "SocketAddress::setFromSockaddr() called " 279 "with unsupported address type");
282 setFromIpAddrPort(folly::IPAddress(address), port);
285 void SocketAddress::setFromSockaddr(
286 const struct sockaddr* address,
290 (offsetof(
struct sockaddr, sa_family) +
sizeof(address->sa_family))) {
291 throw std::invalid_argument(
292 "SocketAddress::setFromSockaddr() called " 293 "with length too short for a sockaddr");
296 if (address->sa_family == AF_INET) {
297 if (addrlen <
sizeof(
struct sockaddr_in)) {
298 throw std::invalid_argument(
299 "SocketAddress::setFromSockaddr() called " 300 "with length too short for a sockaddr_in");
302 setFromSockaddr(reinterpret_cast<const struct sockaddr_in*>(address));
303 }
else if (address->sa_family == AF_INET6) {
304 if (addrlen <
sizeof(
struct sockaddr_in6)) {
305 throw std::invalid_argument(
306 "SocketAddress::setFromSockaddr() called " 307 "with length too short for a sockaddr_in6");
309 setFromSockaddr(reinterpret_cast<const struct sockaddr_in6*>(address));
310 }
else if (address->sa_family == AF_UNIX) {
312 reinterpret_cast<const struct sockaddr_un*>(address), addrlen);
314 throw std::invalid_argument(
315 "SocketAddress::setFromSockaddr() called " 316 "with unsupported address type");
320 void SocketAddress::setFromSockaddr(
const struct sockaddr_in* address) {
321 assert(address->sin_family == AF_INET);
322 setFromSockaddr((sockaddr*)address);
325 void SocketAddress::setFromSockaddr(
const struct sockaddr_in6* address) {
326 assert(address->sin6_family == AF_INET6);
327 setFromSockaddr((sockaddr*)address);
330 void SocketAddress::setFromSockaddr(
331 const struct sockaddr_un* address,
333 assert(address->sun_family == AF_UNIX);
334 if (addrlen >
sizeof(
struct sockaddr_un)) {
335 throw std::invalid_argument(
336 "SocketAddress::setFromSockaddr() called " 337 "with length too long for a sockaddr_un");
344 memcpy(storage_.un.addr, address,
size_t(addrlen));
345 updateUnixAddressLength(addrlen);
348 if (addrlen <
sizeof(
struct sockaddr_un)) {
349 char* p =
reinterpret_cast<char*
>(storage_.un.addr);
350 memset(p + addrlen, 0,
sizeof(
struct sockaddr_un) - addrlen);
354 const folly::IPAddress& SocketAddress::getIPAddress()
const {
355 auto family = getFamily();
356 if (family != AF_INET && family != AF_INET6) {
359 return storage_.addr;
362 socklen_t SocketAddress::getActualSize()
const {
364 return storage_.un.len;
366 switch (getFamily()) {
369 return sizeof(
struct sockaddr_in);
371 return sizeof(
struct sockaddr_in6);
373 throw std::invalid_argument(
374 "SocketAddress::getActualSize() called " 375 "with unrecognized address family");
380 if (!isFamilyInet()) {
381 throw std::invalid_argument(
"Can't get address str for non ip address");
383 return storage_.addr.toFullyQualified();
387 if (!isFamilyInet()) {
388 throw std::invalid_argument(
"Can't get address str for non ip address");
390 return storage_.addr.str();
393 bool SocketAddress::isFamilyInet()
const {
394 auto family = getFamily();
395 return family == AF_INET || family == AF_INET6;
398 void SocketAddress::getAddressStr(
char* buf,
size_t buflen)
const {
399 auto ret = getAddressStr();
400 size_t len =
std::min(buflen - 1, ret.size());
401 memcpy(buf, ret.data(), len);
406 switch (getFamily()) {
411 throw std::invalid_argument(
412 "SocketAddress::getPort() called on non-IP " 418 switch (getFamily()) {
424 throw std::invalid_argument(
425 "SocketAddress::setPort() called on non-IP " 430 void SocketAddress::convertToIPv4() {
431 if (!tryConvertToIPv4()) {
432 throw std::invalid_argument(
433 "convertToIPv4() called on an addresse that is " 434 "not an IPv4-mapped address");
438 bool SocketAddress::tryConvertToIPv4() {
439 if (!isIPv4Mapped()) {
443 storage_.addr = folly::IPAddress::createIPv4(storage_.addr);
447 bool SocketAddress::mapToIPv6() {
448 if (getFamily() != AF_INET) {
452 storage_.addr = folly::IPAddress::createIPv6(storage_.addr);
457 return getIpString(0);
462 throw std::invalid_argument(
463 "SocketAddress: attempting to get path " 464 "for a non-Unix address");
467 if (storage_.un.pathLength() == 0) {
471 if (storage_.un.addr->sun_path[0] ==
'\0') {
474 storage_.un.addr->sun_path,
size_t(storage_.un.pathLength()));
478 storage_.un.addr->sun_path,
479 strnlen(storage_.un.addr->sun_path,
size_t(storage_.un.pathLength())));
484 if (storage_.un.pathLength() == 0) {
485 return "<anonymous unix address>";
488 if (storage_.un.addr->sun_path[0] ==
'\0') {
490 return "<abstract unix address>";
494 storage_.un.addr->sun_path,
495 strnlen(storage_.un.addr->sun_path,
size_t(storage_.un.pathLength())));
497 switch (getFamily()) {
499 return "<uninitialized address>";
501 char buf[NI_MAXHOST + 16];
502 getAddressStr(buf,
sizeof(buf));
503 size_t iplen = strlen(buf);
504 snprintf(buf + iplen,
sizeof(buf) - iplen,
":%" PRIu16, getPort());
508 char buf[NI_MAXHOST + 18];
510 getAddressStr(buf + 1,
sizeof(buf) - 1);
511 size_t iplen = strlen(buf);
512 snprintf(buf + iplen,
sizeof(buf) - iplen,
"]:%" PRIu16, getPort());
517 snprintf(buf,
sizeof(buf),
"<unknown address family %d>", getFamily());
537 storage_.un.addr->sun_path,
539 size_t(storage_.un.pathLength()));
543 switch (getFamily()) {
548 throw std::invalid_argument(
549 "SocketAddress: unsupported address family " 554 bool SocketAddress::prefixMatch(
556 unsigned prefixLength)
const {
561 switch (getFamily()) {
566 auto prefix = folly::IPAddress::longestCommonPrefix(
567 {storage_.addr, mask_length}, {other.
storage_.
addr, mask_length});
568 return prefix.second >= prefixLength;
575 size_t SocketAddress::hash()
const {
579 enum { kUnixPathMax =
sizeof(storage_.un.addr->sun_path) };
580 const char* path = storage_.un.addr->sun_path;
581 auto pathLength = storage_.un.pathLength();
583 for (off_t n = 0; n < pathLength; ++n) {
588 switch (getFamily()) {
600 throw std::invalid_argument(
601 "SocketAddress: unsupported address family " 611 char portString[
sizeof(
"65535")];
612 snprintf(portString,
sizeof(portString),
"%" PRIu16, port);
614 return getAddrInfo(host, portString, flags);
618 SocketAddress::getAddrInfo(
const char* host,
const char* port,
int flags) {
619 struct addrinfo hints;
620 memset(&hints, 0,
sizeof(hints));
621 hints.ai_family = AF_UNSPEC;
622 hints.ai_socktype = SOCK_STREAM;
623 hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV |
flags;
625 struct addrinfo* results;
626 int error = getaddrinfo(host, port, &hints, &results);
629 "Failed to resolve address for '{}': {} (error={})",
633 throw std::system_error(error, std::generic_category(), os);
639 void SocketAddress::setFromAddrInfo(
const struct addrinfo*
info) {
640 setFromSockaddr(info->ai_addr, socklen_t(info->ai_addrlen));
643 void SocketAddress::setFromLocalAddr(
const struct addrinfo*
info) {
646 for (
const struct addrinfo* ai = info; ai !=
nullptr; ai = ai->ai_next) {
647 if (ai->ai_family == AF_INET6) {
648 setFromSockaddr(ai->ai_addr, socklen_t(ai->ai_addrlen));
654 setFromSockaddr(info->ai_addr, socklen_t(info->ai_addrlen));
657 void SocketAddress::setFromSocket(
661 sockaddr_storage tmp_sock;
662 socklen_t addrLen =
sizeof(tmp_sock);
663 if (fn(socket, (sockaddr*)&tmp_sock, &addrLen) != 0) {
667 setFromSockaddr((sockaddr*)&tmp_sock, addrLen);
671 char addrString[NI_MAXHOST];
672 getIpString(addrString,
sizeof(addrString), flags);
676 void SocketAddress::getIpString(
char* buf,
size_t buflen,
int flags)
const {
677 auto family = getFamily();
678 if (family != AF_INET && family != AF_INET6) {
679 throw std::invalid_argument(
680 "SocketAddress: attempting to get IP address " 681 "for a non-IP address");
684 sockaddr_storage tmp_sock;
685 storage_.addr.toSockaddrStorage(&tmp_sock, port_);
686 int rc = getnameinfo(
687 (sockaddr*)&tmp_sock,
688 sizeof(sockaddr_storage),
696 "getnameinfo() failed in getIpString() error = {}", gai_strerror(rc));
697 throw std::system_error(rc, std::generic_category(), os);
701 void SocketAddress::updateUnixAddressLength(socklen_t addrlen) {
702 if (addrlen < offsetof(
struct sockaddr_un, sun_path)) {
703 throw std::invalid_argument(
704 "SocketAddress: attempted to set a Unix socket " 705 "with a length too short for a sockaddr_un");
708 storage_.un.len = addrlen;
709 if (storage_.un.pathLength() == 0) {
714 if (storage_.un.addr->sun_path[0] ==
'\0') {
718 size_t maxLength = addrlen - offsetof(
struct sockaddr_un, sun_path);
719 size_t pathLength = strnlen(storage_.un.addr->sun_path, maxLength);
721 socklen_t(offsetof(
struct sockaddr_un, sun_path) + pathLength);
736 auto thisPathLength = storage_.un.pathLength();
737 if (thisPathLength == 0) {
741 if (otherPathLength == 0) {
746 if (thisPathLength != otherPathLength) {
747 return thisPathLength < otherPathLength;
750 storage_.un.addr->sun_path,
752 size_t(thisPathLength));
755 switch (getFamily()) {
758 if (port_ != other.
port_) {
759 return port_ < other.
port_;
766 throw std::invalid_argument(
767 "SocketAddress: unsupported address family for comparing");
772 return address.
hash();
bool operator==(const char *c, CStringRange::Sentinel)
std::string sformat(StringPiece fmt, Args &&...args)
constexpr size_type size() const
#define GETFAMILYNAMEFROM_IMPL(Family)
—— Concurrent Priority Queue Implementation ——
std::string describe() const
bool prefix(Cursor &c, uint32_t expected)
requires And< SemiMovable< VN >... > &&SemiMovable< E > auto error(E e)
std::ostream & operator<<(std::ostream &os, const SocketAddress &addr)
int getsockname(NetworkSocket s, sockaddr *name, socklen_t *namelen)
sa_family_t getFamily() const
size_t hash_combine(const T &t, const Ts &...ts) noexcept(noexcept(hash_combine_generic(StdHasher{}, t, ts...)))
constexpr Iter data() const
NetworkSocket socket(int af, int type, int protocol)
union folly::SocketAddress::AddrStorage storage_
uint64_t twang_mix64(uint64_t key) noexcept
int getpeername(NetworkSocket s, sockaddr *name, socklen_t *namelen)
static unsigned long long allocated
socklen_t pathLength() const
size_t hash_value(const SocketAddress &address)
void throwSystemError(Args &&...args)
ThreadPoolListHook * addr
struct sockaddr_un * addr
#define FOLLY_FALLTHROUGH
std::enable_if< IsLessThanComparable< Value >::value, bool >::type operator<(const Expected< Value, Error > &lhs, const Expected< Value, Error > &rhs)