InetAddress.cc revision 24ca08a8
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); 2424ca08a8SShuo Chen } 2524ca08a8SShuo Chen else 2624ca08a8SShuo Chen { 2724ca08a8SShuo Chen result = ::inet_pton(AF_INET6, ip.c_str(), &addr6_.sin6_addr); 2824ca08a8SShuo Chen } 2924ca08a8SShuo Chen 3024ca08a8SShuo Chen assert(result == 1 && "Invalid IP format"); 31aafef3ccSShuo Chen} 32efbfdb0cSShuo Chen 3324ca08a8SShuo ChenInetAddress::InetAddress(uint16_t port, bool ipv6) 34efbfdb0cSShuo Chen{ 3524ca08a8SShuo Chen static_assert(offsetof(InetAddress, addr6_) == 0, "addr6_ offset 0"); 3624ca08a8SShuo Chen static_assert(offsetof(InetAddress, addr_) == 0, "addr_ offset 0"); 3724ca08a8SShuo Chen bool loopbackOnly = false; 3824ca08a8SShuo Chen if (ipv6) 3924ca08a8SShuo Chen { 4024ca08a8SShuo Chen memZero(&addr6_, sizeof addr6_); 4124ca08a8SShuo Chen addr6_.sin6_family = AF_INET6; 4224ca08a8SShuo Chen in6_addr ip = loopbackOnly ? in6addr_loopback : in6addr_any; 4324ca08a8SShuo Chen addr6_.sin6_addr = ip; 4424ca08a8SShuo Chen addr6_.sin6_port = htons(port); 4524ca08a8SShuo Chen } 4624ca08a8SShuo Chen else 4724ca08a8SShuo Chen { 4824ca08a8SShuo Chen memZero(&addr_, sizeof addr_); 4924ca08a8SShuo Chen addr_.sin_family = AF_INET; 5024ca08a8SShuo Chen in_addr_t ip = loopbackOnly ? INADDR_LOOPBACK : INADDR_ANY; 5124ca08a8SShuo Chen addr_.sin_addr.s_addr = htonl(ip); 5224ca08a8SShuo Chen addr_.sin_port = htons(port); 5324ca08a8SShuo Chen } 5424ca08a8SShuo Chen} 5524ca08a8SShuo Chen 5624ca08a8SShuo ChenInetAddress::InetAddress(const struct sockaddr& saddr) 5724ca08a8SShuo Chen{ 5824ca08a8SShuo Chen if (saddr.sa_family == AF_INET) 5924ca08a8SShuo Chen { 6024ca08a8SShuo Chen memcpy(&addr_, &saddr, sizeof addr_); 6124ca08a8SShuo Chen } 6224ca08a8SShuo Chen else if (saddr.sa_family == AF_INET6) 6324ca08a8SShuo Chen { 6424ca08a8SShuo Chen memcpy(&addr6_, &saddr, sizeof addr6_); 6524ca08a8SShuo Chen } 6624ca08a8SShuo Chen else 6724ca08a8SShuo Chen { 6824ca08a8SShuo Chen assert(false); 6924ca08a8SShuo Chen } 70efbfdb0cSShuo Chen} 715b543c9cSShuo Chen 725b543c9cSShuo Chenstd::string InetAddress::toIp() const 735b543c9cSShuo Chen{ 7424ca08a8SShuo Chen char buf[64] = ""; 7524ca08a8SShuo Chen static_assert(sizeof buf >= INET_ADDRSTRLEN); 7624ca08a8SShuo Chen static_assert(sizeof buf >= INET6_ADDRSTRLEN); 7724ca08a8SShuo Chen 7824ca08a8SShuo Chen if (family() == AF_INET) 7924ca08a8SShuo Chen { 8024ca08a8SShuo Chen ::inet_ntop(AF_INET, &addr_.sin_addr, buf, static_cast<socklen_t>(sizeof buf)); 8124ca08a8SShuo Chen } 8224ca08a8SShuo Chen else if (family() == AF_INET6) 8324ca08a8SShuo Chen { 8424ca08a8SShuo Chen ::inet_ntop(AF_INET6, &addr6_.sin6_addr, buf, static_cast<socklen_t>(sizeof buf)); 8524ca08a8SShuo Chen } 8624ca08a8SShuo Chen 875b543c9cSShuo Chen return buf; 885b543c9cSShuo Chen} 895b543c9cSShuo Chen 905b543c9cSShuo Chenstd::string InetAddress::toIpPort() const 915b543c9cSShuo Chen{ 9224ca08a8SShuo Chen char buf[32] = ""; 9324ca08a8SShuo Chen snprintf(buf, sizeof buf, ":%u", port()); 9424ca08a8SShuo Chen return toIp() + buf; 955b543c9cSShuo Chen} 965b543c9cSShuo Chen 9724ca08a8SShuo Chenbool InetAddress::operator==(const InetAddress& rhs) const 98503bffb0SShuo Chen{ 9924ca08a8SShuo Chen if (family() == rhs.family()) 100503bffb0SShuo Chen { 10124ca08a8SShuo Chen if (family() == AF_INET) 102503bffb0SShuo Chen { 10324ca08a8SShuo Chen return addr_.sin_port == rhs.addr_.sin_port && 10424ca08a8SShuo Chen addr_.sin_addr.s_addr == rhs.addr_.sin_addr.s_addr; 105503bffb0SShuo Chen } 10624ca08a8SShuo Chen else if (family() == AF_INET6) 107503bffb0SShuo Chen { 10824ca08a8SShuo Chen return addr6_.sin6_port == rhs.addr6_.sin6_port && 10924ca08a8SShuo Chen memcmp(&addr6_.sin6_addr, &rhs.addr6_.sin6_addr, sizeof addr6_.sin6_addr) == 0; 110503bffb0SShuo Chen } 111503bffb0SShuo Chen } 112503bffb0SShuo Chen return false; 113503bffb0SShuo Chen} 114503bffb0SShuo Chen 11524ca08a8SShuo Chen// static 11624ca08a8SShuo Chenbool InetAddress::resolve(StringArg hostname, uint16_t port, InetAddress* out) 1175b543c9cSShuo Chen{ 1185b543c9cSShuo Chen assert(out); 11924ca08a8SShuo Chen std::vector<InetAddress> addrs = resolveAll(hostname, port); 12024ca08a8SShuo Chen 12124ca08a8SShuo Chen if (addrs.empty()) 12224ca08a8SShuo Chen return false; 12324ca08a8SShuo Chen 12424ca08a8SShuo Chen // Read the first result 12524ca08a8SShuo Chen *out = addrs[0]; 12624ca08a8SShuo Chen 12724ca08a8SShuo Chen return true; 12824ca08a8SShuo Chen} 12924ca08a8SShuo Chen 13024ca08a8SShuo Chen// static 13124ca08a8SShuo Chenstd::vector<InetAddress> InetAddress::resolveAll(StringArg hostname, uint16_t port) 13224ca08a8SShuo Chen{ 13324ca08a8SShuo Chen std::vector<InetAddress> addrs; 13424ca08a8SShuo Chen 13524ca08a8SShuo Chen struct addrinfo* result = NULL; 13624ca08a8SShuo Chen int error = getaddrinfo(hostname.c_str(), NULL, NULL, &result); 13724ca08a8SShuo Chen if (error != 0) 1385b543c9cSShuo Chen { 13924ca08a8SShuo Chen if (error == EAI_SYSTEM) 14024ca08a8SShuo Chen { 14124ca08a8SShuo Chen perror("InetAddress::resolve"); 14224ca08a8SShuo Chen } 14324ca08a8SShuo Chen else 14424ca08a8SShuo Chen { 14524ca08a8SShuo Chen fprintf(stderr, "InetAddress::resolve: %s\n", gai_strerror(error)); 14624ca08a8SShuo Chen } 14724ca08a8SShuo Chen return addrs; 1485b543c9cSShuo Chen } 14924ca08a8SShuo Chen 15024ca08a8SShuo Chen assert(result); 15124ca08a8SShuo Chen std::unique_ptr<struct addrinfo, decltype(&freeaddrinfo)> freeResult(result, freeaddrinfo); 15224ca08a8SShuo Chen 15324ca08a8SShuo Chen for (struct addrinfo* ai = result; ai != NULL; ai = ai->ai_next) 1545b543c9cSShuo Chen { 15524ca08a8SShuo Chen InetAddress addr(*ai->ai_addr); 15624ca08a8SShuo Chen addr.setPort(port); 15724ca08a8SShuo Chen addrs.push_back(addr); 1585b543c9cSShuo Chen } 15924ca08a8SShuo Chen return addrs; 1605b543c9cSShuo Chen} 161