Support different IPv4 formats in IPAddress::init_host_port.

GitOrigin-RevId: 122239f0ba24a1274b0cc50913e8fac3ad25ddc3
This commit is contained in:
levlam 2018-11-27 21:26:32 +03:00
parent 4c618b6f92
commit 8e9c2721ef

View File

@ -4,6 +4,8 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#define _WINSOCK_DEPRECATED_NO_WARNINGS // we need to use inet_addr instead of inet_pton
#include "td/utils/port/IPAddress.h"
#include "td/utils/format.h"
@ -170,6 +172,25 @@ Result<string> idn_to_ascii(CSlice host) {
#endif
}
static CSlice get_ip_str(int family, const void *addr) {
const int buf_size = INET6_ADDRSTRLEN;
static TD_THREAD_LOCAL char *buf;
init_thread_local<char[]>(buf, buf_size);
const char *res = inet_ntop(family,
#if TD_WINDOWS
const_cast<PVOID>(addr),
#else
addr,
#endif
buf, buf_size);
if (res == nullptr) {
return CSlice();
} else {
return CSlice(res);
}
}
IPAddress::IPAddress() : is_valid_(false) {
}
@ -327,6 +348,7 @@ Status IPAddress::init_host_port(CSlice host, int port, bool prefer_ipv6) {
}
Status IPAddress::init_host_port(CSlice host, CSlice port, bool prefer_ipv6) {
is_valid_ = false;
if (host.empty()) {
return Status::Error("Host is empty");
}
@ -338,6 +360,13 @@ Status IPAddress::init_host_port(CSlice host, CSlice port, bool prefer_ipv6) {
TRY_RESULT(ascii_host, idn_to_ascii(host));
host = ascii_host;
// some getaddrinfo implementations use inet_pton instead of inet_aton and support only decimal-dotted IPv4 form,
// and so doesn't recognize 0x12.0x34.0x56.0x78, or 0x12345678, or 0x7f.001 as valid IPv4 addresses
auto ipv4_numeric_addr = inet_addr(host.c_str());
if (ipv4_numeric_addr != INADDR_NONE) {
host = ::td::get_ip_str(AF_INET, &ipv4_numeric_addr);
}
addrinfo hints;
addrinfo *info = nullptr;
std::memset(&hints, 0, sizeof(hints));
@ -437,25 +466,6 @@ Status IPAddress::init_peer_address(const SocketFd &socket_fd) {
return Status::OK();
}
static CSlice get_ip_str(int family, const void *addr) {
const int buf_size = INET6_ADDRSTRLEN;
static TD_THREAD_LOCAL char *buf;
init_thread_local<char[]>(buf, buf_size);
const char *res = inet_ntop(family,
#if TD_WINDOWS
const_cast<PVOID>(addr),
#else
addr,
#endif
buf, buf_size);
if (res == nullptr) {
return CSlice();
} else {
return CSlice(res);
}
}
CSlice IPAddress::ipv4_to_str(uint32 ipv4) {
ipv4 = ntohl(ipv4);
return ::td::get_ip_str(AF_INET, &ipv4);