1efbfdb0cSShuo Chen#include "InetAddress.h" 2efbfdb0cSShuo Chen 324ca08a8SShuo Chen#include <memory> 424ca08a8SShuo Chen 55b543c9cSShuo Chen#include <assert.h> 65b543c9cSShuo Chen#include <arpa/inet.h> 724ca08a8SShuo Chen#include <netdb.h> 824ca08a8SShuo Chen 924ca08a8SShuo Chenstatic_assert(sizeof(InetAddress) == sizeof(struct sockaddr_in6), 1024ca08a8SShuo Chen "InetAddress is same size as sockaddr_in6"); 1114ca1249SShuo Chen#ifdef __linux 1224ca08a8SShuo Chenstatic_assert(offsetof(sockaddr_in, sin_family) == 0, "sin_family offset 0"); 1324ca08a8SShuo Chenstatic_assert(offsetof(sockaddr_in6, sin6_family) == 0, "sin6_family offset 0"); 14e146b157SShuo Chen#endif 15e146b157SShuo Chenstatic_assert(offsetof(sockaddr_in, sin_family) == offsetof(sockaddr_in6, sin6_family), 16e146b157SShuo Chen "sin_family/sin6_family offset"); 1724ca08a8SShuo Chenstatic_assert(offsetof(sockaddr_in, sin_port) == 2, "sin_port offset 2"); 1824ca08a8SShuo Chenstatic_assert(offsetof(sockaddr_in6, sin6_port) == 2, "sin6_port offset 2"); 195b543c9cSShuo Chen 20aafef3ccSShuo ChenInetAddress::InetAddress(StringArg ip, uint16_t port) 21aafef3ccSShuo Chen{ 2224ca08a8SShuo Chen setPort(port); 2324ca08a8SShuo Chen 2424ca08a8SShuo Chen int result = 0; 2524ca08a8SShuo Chen if (strchr(ip.c_str(), ':') == NULL) 2624ca08a8SShuo Chen { 2724ca08a8SShuo Chen result = ::inet_pton(AF_INET, ip.c_str(), &addr_.sin_addr); 28246b2f80SShuo Chen addr_.sin_family = AF_INET; 2924ca08a8SShuo Chen } 3024ca08a8SShuo Chen else 3124ca08a8SShuo Chen { 3224ca08a8SShuo Chen result = ::inet_pton(AF_INET6, ip.c_str(), &addr6_.sin6_addr); 33246b2f80SShuo Chen addr6_.sin6_family = AF_INET6; 3424ca08a8SShuo Chen } 3524ca08a8SShuo Chen 3624ca08a8SShuo Chen assert(result == 1 && "Invalid IP format"); 37aafef3ccSShuo Chen} 38efbfdb0cSShuo Chen 3924ca08a8SShuo ChenInetAddress::InetAddress(uint16_t port, bool ipv6) 40efbfdb0cSShuo Chen{ 4124ca08a8SShuo Chen static_assert(offsetof(InetAddress, addr6_) == 0, "addr6_ offset 0"); 4224ca08a8SShuo Chen static_assert(offsetof(InetAddress, addr_) == 0, "addr_ offset 0"); 4324ca08a8SShuo Chen bool loopbackOnly = false; 4424ca08a8SShuo Chen if (ipv6) 4524ca08a8SShuo Chen { 4624ca08a8SShuo Chen memZero(&addr6_, sizeof addr6_); 4724ca08a8SShuo Chen addr6_.sin6_family = AF_INET6; 4824ca08a8SShuo Chen in6_addr ip = loopbackOnly ? in6addr_loopback : in6addr_any; 4924ca08a8SShuo Chen addr6_.sin6_addr = ip; 5024ca08a8SShuo Chen addr6_.sin6_port = htons(port); 5124ca08a8SShuo Chen } 5224ca08a8SShuo Chen else 5324ca08a8SShuo Chen { 5424ca08a8SShuo Chen memZero(&addr_, sizeof addr_); 5524ca08a8SShuo Chen addr_.sin_family = AF_INET; 5624ca08a8SShuo Chen in_addr_t ip = loopbackOnly ? INADDR_LOOPBACK : INADDR_ANY; 5724ca08a8SShuo Chen addr_.sin_addr.s_addr = htonl(ip); 5824ca08a8SShuo Chen addr_.sin_port = htons(port); 5924ca08a8SShuo Chen } 6024ca08a8SShuo Chen} 6124ca08a8SShuo Chen 6224ca08a8SShuo ChenInetAddress::InetAddress(const struct sockaddr& saddr) 6324ca08a8SShuo Chen{ 6424ca08a8SShuo Chen if (saddr.sa_family == AF_INET) 6524ca08a8SShuo Chen { 6624ca08a8SShuo Chen memcpy(&addr_, &saddr, sizeof addr_); 6724ca08a8SShuo Chen } 6824ca08a8SShuo Chen else if (saddr.sa_family == AF_INET6) 6924ca08a8SShuo Chen { 7024ca08a8SShuo Chen memcpy(&addr6_, &saddr, sizeof addr6_); 7124ca08a8SShuo Chen } 7224ca08a8SShuo Chen else 7324ca08a8SShuo Chen { 7424ca08a8SShuo Chen assert(false); 7524ca08a8SShuo Chen } 76efbfdb0cSShuo Chen} 775b543c9cSShuo Chen 785b543c9cSShuo Chenstd::string InetAddress::toIp() const 795b543c9cSShuo Chen{ 8024ca08a8SShuo Chen char buf[64] = ""; 8124ca08a8SShuo Chen static_assert(sizeof buf >= INET_ADDRSTRLEN); 8224ca08a8SShuo Chen static_assert(sizeof buf >= INET6_ADDRSTRLEN); 8324ca08a8SShuo Chen 8424ca08a8SShuo Chen if (family() == AF_INET) 8524ca08a8SShuo Chen { 8624ca08a8SShuo Chen ::inet_ntop(AF_INET, &addr_.sin_addr, buf, static_cast<socklen_t>(sizeof buf)); 8724ca08a8SShuo Chen } 8824ca08a8SShuo Chen else if (family() == AF_INET6) 8924ca08a8SShuo Chen { 9024ca08a8SShuo Chen ::inet_ntop(AF_INET6, &addr6_.sin6_addr, buf, static_cast<socklen_t>(sizeof buf)); 9124ca08a8SShuo Chen } 9224ca08a8SShuo Chen 935b543c9cSShuo Chen return buf; 945b543c9cSShuo Chen} 955b543c9cSShuo Chen 965b543c9cSShuo Chenstd::string InetAddress::toIpPort() const 975b543c9cSShuo Chen{ 9824ca08a8SShuo Chen char buf[32] = ""; 9924ca08a8SShuo Chen snprintf(buf, sizeof buf, ":%u", port()); 100e0ccc29fSShuo Chen 101e0ccc29fSShuo Chen if (family() == AF_INET6) 102e0ccc29fSShuo Chen return "[" + toIp() + "]" + buf; 103e0ccc29fSShuo Chen 10424ca08a8SShuo Chen return toIp() + buf; 1055b543c9cSShuo Chen} 1065b543c9cSShuo Chen 10724ca08a8SShuo Chenbool InetAddress::operator==(const InetAddress& rhs) const 108503bffb0SShuo Chen{ 10924ca08a8SShuo Chen if (family() == rhs.family()) 110503bffb0SShuo Chen { 11124ca08a8SShuo Chen if (family() == AF_INET) 112503bffb0SShuo Chen { 11324ca08a8SShuo Chen return addr_.sin_port == rhs.addr_.sin_port && 11424ca08a8SShuo Chen addr_.sin_addr.s_addr == rhs.addr_.sin_addr.s_addr; 115503bffb0SShuo Chen } 11624ca08a8SShuo Chen else if (family() == AF_INET6) 117503bffb0SShuo Chen { 11824ca08a8SShuo Chen return addr6_.sin6_port == rhs.addr6_.sin6_port && 11924ca08a8SShuo Chen memcmp(&addr6_.sin6_addr, &rhs.addr6_.sin6_addr, sizeof addr6_.sin6_addr) == 0; 120503bffb0SShuo Chen } 121503bffb0SShuo Chen } 122503bffb0SShuo Chen return false; 123503bffb0SShuo Chen} 124503bffb0SShuo Chen 12524ca08a8SShuo Chen// static 12624ca08a8SShuo Chenbool InetAddress::resolve(StringArg hostname, uint16_t port, InetAddress* out) 1275b543c9cSShuo Chen{ 1285b543c9cSShuo Chen assert(out); 12924ca08a8SShuo Chen std::vector<InetAddress> addrs = resolveAll(hostname, port); 13024ca08a8SShuo Chen 13124ca08a8SShuo Chen if (addrs.empty()) 13224ca08a8SShuo Chen return false; 13324ca08a8SShuo Chen 13424ca08a8SShuo Chen // Read the first result 13524ca08a8SShuo Chen *out = addrs[0]; 13624ca08a8SShuo Chen 13724ca08a8SShuo Chen return true; 13824ca08a8SShuo Chen} 13924ca08a8SShuo Chen 14024ca08a8SShuo Chen// static 14124ca08a8SShuo Chenstd::vector<InetAddress> InetAddress::resolveAll(StringArg hostname, uint16_t port) 14224ca08a8SShuo Chen{ 14324ca08a8SShuo Chen std::vector<InetAddress> addrs; 14424ca08a8SShuo Chen 14524ca08a8SShuo Chen struct addrinfo* result = NULL; 14624ca08a8SShuo Chen int error = getaddrinfo(hostname.c_str(), NULL, NULL, &result); 14724ca08a8SShuo Chen if (error != 0) 1485b543c9cSShuo Chen { 14924ca08a8SShuo Chen if (error == EAI_SYSTEM) 15024ca08a8SShuo Chen { 15124ca08a8SShuo Chen perror("InetAddress::resolve"); 15224ca08a8SShuo Chen } 15324ca08a8SShuo Chen else 15424ca08a8SShuo Chen { 15524ca08a8SShuo Chen fprintf(stderr, "InetAddress::resolve: %s\n", gai_strerror(error)); 15624ca08a8SShuo Chen } 15724ca08a8SShuo Chen return addrs; 1585b543c9cSShuo Chen } 15924ca08a8SShuo Chen 16024ca08a8SShuo Chen assert(result); 16124ca08a8SShuo Chen std::unique_ptr<struct addrinfo, decltype(&freeaddrinfo)> freeResult(result, freeaddrinfo); 16224ca08a8SShuo Chen 16324ca08a8SShuo Chen for (struct addrinfo* ai = result; ai != NULL; ai = ai->ai_next) 1645b543c9cSShuo Chen { 16524ca08a8SShuo Chen InetAddress addr(*ai->ai_addr); 16624ca08a8SShuo Chen addr.setPort(port); 16724ca08a8SShuo Chen addrs.push_back(addr); 1685b543c9cSShuo Chen } 16924ca08a8SShuo Chen return addrs; 1705b543c9cSShuo Chen} 171