X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;ds=sidebyside;f=folly%2FSocketAddress.h;h=480a37d94941f02a577942f62e9373f716fd02e7;hb=b3e7df8220f410398011fea71b280ba8be459fcc;hp=ac1771c484064760d445605a3a8a7179e964b776;hpb=45c8738bf65a76678248189fc8f1f2eb2f35f628;p=folly.git diff --git a/folly/SocketAddress.h b/folly/SocketAddress.h index ac1771c4..480a37d9 100644 --- a/folly/SocketAddress.h +++ b/folly/SocketAddress.h @@ -1,5 +1,5 @@ /* - * Copyright 2014 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,24 +17,20 @@ #pragma once #include -#include -#include -#include -#include -#include #include -#include +#include #include #include +#include +#include +#include namespace folly { class SocketAddress { public: - SocketAddress() { - storage_.addr = folly::IPAddress(); - } + SocketAddress() = default; /** * Construct a SocketAddress from a hostname and port. @@ -75,17 +71,22 @@ class SocketAddress { } } + SocketAddress(const IPAddress& ipAddr, uint16_t port) { + setFromIpAddrPort(ipAddr, port); + } + SocketAddress(const SocketAddress& addr) { - storage_ = addr.storage_; port_ = addr.port_; if (addr.getFamily() == AF_UNIX) { storage_.un.init(addr.storage_.un); + } else { + storage_ = addr.storage_; } external_ = addr.external_; } SocketAddress& operator=(const SocketAddress& addr) { - if (getFamily() != AF_UNIX) { + if (!external_) { if (addr.getFamily() != AF_UNIX) { storage_ = addr.storage_; } else { @@ -105,7 +106,7 @@ class SocketAddress { return *this; } - SocketAddress(SocketAddress&& addr) { + SocketAddress(SocketAddress&& addr) noexcept { storage_ = addr.storage_; port_ = addr.port_; external_ = addr.external_; @@ -120,7 +121,7 @@ class SocketAddress { } ~SocketAddress() { - if (getFamily() == AF_UNIX) { + if (external_) { storage_.un.free(); } } @@ -150,7 +151,11 @@ class SocketAddress { bool isLoopbackAddress() const; void reset() { - prepFamilyChange(AF_UNSPEC); + if (external_) { + storage_.un.free(); + } + storage_.addr = folly::IPAddress(); + external_ = false; } /** @@ -191,6 +196,14 @@ class SocketAddress { setFromIpPort(ip.c_str(), port); } + /** + * Initialize this SocketAddress from an IPAddress struct and port. + * + * @param ip The IP address in IPAddress format + * @param port The port (in host byte order) + */ + void setFromIpAddrPort(const IPAddress& ip, uint16_t port); + /** * Initialize this SocketAddress from a local port number. * @@ -262,21 +275,36 @@ class SocketAddress { return setFromHostPort(hostAndPort.c_str()); } + /** + * Returns the port number from the given socketaddr structure. + * + * Currently only IPv4 and IPv6 are supported. + * + * Returns -1 for unsupported socket families. + */ + static int getPortFrom(const struct sockaddr* address); + + /** + * Returns the family name from the given socketaddr structure (e.g.: AF_INET6 + * for IPv6). + * + * Returns `defaultResult` for unsupported socket families. + */ + static const char* getFamilyNameFrom( + const struct sockaddr* address, + const char* defaultResult = nullptr); + /** * Initialize this SocketAddress from a local unix path. * * Raises std::invalid_argument on error. */ - void setFromPath(const char* path) { - setFromPath(path, strlen(path)); - } + void setFromPath(StringPiece path); - void setFromPath(const std::string& path) { - setFromPath(path.data(), path.length()); + void setFromPath(const char* path, size_t length) { + setFromPath(StringPiece{path, length}); } - void setFromPath(const char* path, size_t length); - /** * Initialize this SocketAddress from a socket's peer address. * @@ -292,7 +320,7 @@ class SocketAddress { void setFromLocalAddress(int socket); /** - * Initialize this TSocketAddress from a struct sockaddr. + * Initialize this folly::SocketAddress from a struct sockaddr. * * Raises std::system_error on error. * @@ -349,7 +377,7 @@ class SocketAddress { * Returns the actual size of the storage used. */ socklen_t getAddress(sockaddr_storage* addr) const { - if (getFamily() != AF_UNIX) { + if (!external_) { return storage_.addr.toSockaddrStorage(addr, htons(port_)); } else { memcpy(addr, storage_.un.addr, sizeof(*storage_.un.addr)); @@ -363,7 +391,8 @@ class SocketAddress { socklen_t getActualSize() const; sa_family_t getFamily() const { - return external_ ? AF_UNIX : storage_.addr.family(); + DCHECK(external_ || AF_UNIX != storage_.addr.family()); + return external_ ? sa_family_t(AF_UNIX) : storage_.addr.family(); } bool empty() const { @@ -386,6 +415,11 @@ class SocketAddress { */ void getAddressStr(char* buf, size_t buflen) const; + /** + * Return true if it is a valid IPv4 or IPv6 address. + */ + bool isFamilyInet() const; + /** * For v4 & v6 addresses, return the fully qualified address string */ @@ -509,29 +543,38 @@ class SocketAddress { struct sockaddr_un *addr; socklen_t len; + /* For debugging only, will be removed */ + uint64_t magic; + static constexpr uint64_t kMagic = 0x1234faceb00c; + socklen_t pathLength() const { - return len - offsetof(struct sockaddr_un, sun_path); + return socklen_t(len - offsetof(struct sockaddr_un, sun_path)); } void init() { addr = new sockaddr_un; + magic = kMagic; addr->sun_family = AF_UNIX; len = 0; } void init(const ExternalUnixAddr &other) { addr = new sockaddr_un; + magic = kMagic; len = other.len; - memcpy(addr, other.addr, len); + memcpy(addr, other.addr, size_t(len)); // Fill the rest with 0s, just for safety memset(reinterpret_cast(addr) + len, 0, sizeof(struct sockaddr_un) - len); } void copy(const ExternalUnixAddr &other) { + CHECK(magic == kMagic); len = other.len; - memcpy(addr, other.addr, len); + memcpy(addr, other.addr, size_t(len)); } void free() { + CHECK(magic == kMagic); delete addr; + magic = 0; } }; @@ -545,20 +588,6 @@ class SocketAddress { void updateUnixAddressLength(socklen_t addrlen); - void prepFamilyChange(sa_family_t newFamily) { - if (newFamily != AF_UNIX) { - if (getFamily() == AF_UNIX) { - storage_.un.free(); - } - external_ = false; - } else { - if (getFamily() != AF_UNIX) { - storage_.un.init(); - } - external_ = true; - } - } - /* * storage_ contains room for a full IPv4 or IPv6 address, so they can be * stored inline without a separate allocation on the heap. @@ -566,10 +595,11 @@ class SocketAddress { * If we need to store a Unix socket address, ExternalUnixAddr is a shim to * track a struct sockaddr_un allocated separately on the heap. */ - union { - folly::IPAddress addr{}; + union AddrStorage { + folly::IPAddress addr; ExternalUnixAddr un; - } storage_; + AddrStorage() : addr() {} + } storage_{}; // IPAddress class does nto save zone or port, and must be saved here uint16_t port_;