InetAddress.cc revision 246b2f80
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"); 1124ca08a8SShuo Chenstatic_assert(offsetof(sockaddr_in, sin_family) == 0, "sin_family offset 0"); 1224ca08a8SShuo Chenstatic_assert(offsetof(sockaddr_in6, sin6_family) == 0, "sin6_family offset 0"); 1324ca08a8SShuo Chenstatic_assert(offsetof(sockaddr_in, sin_port) == 2, "sin_port offset 2"); 1424ca08a8SShuo Chenstatic_assert(offsetof(sockaddr_in6, sin6_port) == 2, "sin6_port offset 2"); 155b543c9cSShuo Chen 16aafef3ccSShuo ChenInetAddress::InetAddress(StringArg ip, uint16_t port) 17aafef3ccSShuo Chen{ 1824ca08a8SShuo Chen setPort(port); 1924ca08a8SShuo Chen 2024ca08a8SShuo Chen int result = 0; 2124ca08a8SShuo Chen if (strchr(ip.c_str(), ':') == NULL) 2224ca08a8SShuo Chen { 2324ca08a8SShuo Chen result = ::inet_pton(AF_INET, ip.c_str(), &addr_.sin_addr); 24246b2f80SShuo Chen addr_.sin_family = AF_INET; 2524ca08a8SShuo Chen } 2624ca08a8SShuo Chen else 2724ca08a8SShuo Chen { 2824ca08a8SShuo Chen result = ::inet_pton(AF_INET6, ip.c_str(), &addr6_.sin6_addr); 29246b2f80SShuo Chen addr6_.sin6_family = AF_INET6; 3024ca08a8SShuo Chen } 3124ca08a8SShuo Chen 3224ca08a8SShuo Chen assert(result == 1 && "Invalid IP format"); 33aafef3ccSShuo Chen} 34efbfdb0cSShuo Chen 3524ca08a8SShuo ChenInetAddress::InetAddress(uint16_t port, bool ipv6) 36efbfdb0cSShuo Chen{ 3724ca08a8SShuo Chen static_assert(offsetof(InetAddress, addr6_) == 0, "addr6_ offset 0"); 3824ca08a8SShuo Chen static_assert(offsetof(InetAddress, addr_) == 0, "addr_ offset 0"); 3924ca08a8SShuo Chen bool loopbackOnly = false; 4024ca08a8SShuo Chen if (ipv6) 4124ca08a8SShuo Chen { 4224ca08a8SShuo Chen memZero(&addr6_, sizeof addr6_); 4324ca08a8SShuo Chen addr6_.sin6_family = AF_INET6; 4424ca08a8SShuo Chen in6_addr ip = loopbackOnly ? in6addr_loopback : in6addr_any; 4524ca08a8SShuo Chen addr6_.sin6_addr = ip; 4624ca08a8SShuo Chen addr6_.sin6_port = htons(port); 4724ca08a8SShuo Chen } 4824ca08a8SShuo Chen else 4924ca08a8SShuo Chen { 5024ca08a8SShuo Chen memZero(&addr_, sizeof addr_); 5124ca08a8SShuo Chen addr_.sin_family = AF_INET; 5224ca08a8SShuo Chen in_addr_t ip = loopbackOnly ? INADDR_LOOPBACK : INADDR_ANY; 5324ca08a8SShuo Chen addr_.sin_addr.s_addr = htonl(ip); 5424ca08a8SShuo Chen addr_.sin_port = htons(port); 5524ca08a8SShuo Chen } 5624ca08a8SShuo Chen} 5724ca08a8SShuo Chen 5824ca08a8SShuo ChenInetAddress::InetAddress(const struct sockaddr& saddr) 5924ca08a8SShuo Chen{ 6024ca08a8SShuo Chen if (saddr.sa_family == AF_INET) 6124ca08a8SShuo Chen { 6224ca08a8SShuo Chen memcpy(&addr_, &saddr, sizeof addr_); 6324ca08a8SShuo Chen } 6424ca08a8SShuo Chen else if (saddr.sa_family == AF_INET6) 6524ca08a8SShuo Chen { 6624ca08a8SShuo Chen memcpy(&addr6_, &saddr, sizeof addr6_); 6724ca08a8SShuo Chen } 6824ca08a8SShuo Chen else 6924ca08a8SShuo Chen { 7024ca08a8SShuo Chen assert(false); 7124ca08a8SShuo Chen } 72efbfdb0cSShuo Chen} 735b543c9cSShuo Chen 745b543c9cSShuo Chenstd::string InetAddress::toIp() const 755b543c9cSShuo Chen{ 7624ca08a8SShuo Chen char buf[64] = ""; 7724ca08a8SShuo Chen static_assert(sizeof buf >= INET_ADDRSTRLEN); 7824ca08a8SShuo Chen static_assert(sizeof buf >= INET6_ADDRSTRLEN); 7924ca08a8SShuo Chen 8024ca08a8SShuo Chen if (family() == AF_INET) 8124ca08a8SShuo Chen { 8224ca08a8SShuo Chen ::inet_ntop(AF_INET, &addr_.sin_addr, buf, static_cast<socklen_t>(sizeof buf)); 8324ca08a8SShuo Chen } 8424ca08a8SShuo Chen else if (family() == AF_INET6) 8524ca08a8SShuo Chen { 8624ca08a8SShuo Chen ::inet_ntop(AF_INET6, &addr6_.sin6_addr, buf, static_cast<socklen_t>(sizeof buf)); 8724ca08a8SShuo Chen } 8824ca08a8SShuo Chen 895b543c9cSShuo Chen return buf; 905b543c9cSShuo Chen} 915b543c9cSShuo Chen 925b543c9cSShuo Chenstd::string InetAddress::toIpPort() const 935b543c9cSShuo Chen{ 9424ca08a8SShuo Chen char buf[32] = ""; 9524ca08a8SShuo Chen snprintf(buf, sizeof buf, ":%u", port()); 96e0ccc29fSShuo Chen 97e0ccc29fSShuo Chen if (family() == AF_INET6) 98e0ccc29fSShuo Chen return "[" + toIp() + "]" + buf; 99e0ccc29fSShuo Chen 10024ca08a8SShuo Chen return toIp() + buf; 1015b543c9cSShuo Chen} 1025b543c9cSShuo Chen 10324ca08a8SShuo Chenbool InetAddress::operator==(const InetAddress& rhs) const 104503bffb0SShuo Chen{ 10524ca08a8SShuo Chen if (family() == rhs.family()) 106503bffb0SShuo Chen { 10724ca08a8SShuo Chen if (family() == AF_INET) 108503bffb0SShuo Chen { 10924ca08a8SShuo Chen return addr_.sin_port == rhs.addr_.sin_port && 11024ca08a8SShuo Chen addr_.sin_addr.s_addr == rhs.addr_.sin_addr.s_addr; 111503bffb0SShuo Chen } 11224ca08a8SShuo Chen else if (family() == AF_INET6) 113503bffb0SShuo Chen { 11424ca08a8SShuo Chen return addr6_.sin6_port == rhs.addr6_.sin6_port && 11524ca08a8SShuo Chen memcmp(&addr6_.sin6_addr, &rhs.addr6_.sin6_addr, sizeof addr6_.sin6_addr) == 0; 116503bffb0SShuo Chen } 117503bffb0SShuo Chen } 118503bffb0SShuo Chen return false; 119503bffb0SShuo Chen} 120503bffb0SShuo Chen 12124ca08a8SShuo Chen// static 12224ca08a8SShuo Chenbool InetAddress::resolve(StringArg hostname, uint16_t port, InetAddress* out) 1235b543c9cSShuo Chen{ 1245b543c9cSShuo Chen assert(out); 12524ca08a8SShuo Chen std::vector<InetAddress> addrs = resolveAll(hostname, port); 12624ca08a8SShuo Chen 12724ca08a8SShuo Chen if (addrs.empty()) 12824ca08a8SShuo Chen return false; 12924ca08a8SShuo Chen 13024ca08a8SShuo Chen // Read the first result 13124ca08a8SShuo Chen *out = addrs[0]; 13224ca08a8SShuo Chen 13324ca08a8SShuo Chen return true; 13424ca08a8SShuo Chen} 13524ca08a8SShuo Chen 13624ca08a8SShuo Chen// static 13724ca08a8SShuo Chenstd::vector<InetAddress> InetAddress::resolveAll(StringArg hostname, uint16_t port) 13824ca08a8SShuo Chen{ 13924ca08a8SShuo Chen std::vector<InetAddress> addrs; 14024ca08a8SShuo Chen 14124ca08a8SShuo Chen struct addrinfo* result = NULL; 14224ca08a8SShuo Chen int error = getaddrinfo(hostname.c_str(), NULL, NULL, &result); 14324ca08a8SShuo Chen if (error != 0) 1445b543c9cSShuo Chen { 14524ca08a8SShuo Chen if (error == EAI_SYSTEM) 14624ca08a8SShuo Chen { 14724ca08a8SShuo Chen perror("InetAddress::resolve"); 14824ca08a8SShuo Chen } 14924ca08a8SShuo Chen else 15024ca08a8SShuo Chen { 15124ca08a8SShuo Chen fprintf(stderr, "InetAddress::resolve: %s\n", gai_strerror(error)); 15224ca08a8SShuo Chen } 15324ca08a8SShuo Chen return addrs; 1545b543c9cSShuo Chen } 15524ca08a8SShuo Chen 15624ca08a8SShuo Chen assert(result); 15724ca08a8SShuo Chen std::unique_ptr<struct addrinfo, decltype(&freeaddrinfo)> freeResult(result, freeaddrinfo); 15824ca08a8SShuo Chen 15924ca08a8SShuo Chen for (struct addrinfo* ai = result; ai != NULL; ai = ai->ai_next) 1605b543c9cSShuo Chen { 16124ca08a8SShuo Chen InetAddress addr(*ai->ai_addr); 16224ca08a8SShuo Chen addr.setPort(port); 16324ca08a8SShuo Chen addrs.push_back(addr); 1645b543c9cSShuo Chen } 16524ca08a8SShuo Chen return addrs; 1665b543c9cSShuo Chen} 167