Codechange: [Network] Use std::string for NetworkAddress' host name

pull/332/head
rubidium42 3 years ago committed by rubidium42
parent dcef3209a6
commit 6c4a65eeb8

@ -23,11 +23,13 @@ static const int DEFAULT_CONNECT_TIMEOUT_SECONDS = 3; ///< Allow connect() three
*/ */
const char *NetworkAddress::GetHostname() const char *NetworkAddress::GetHostname()
{ {
if (StrEmpty(this->hostname) && this->address.ss_family != AF_UNSPEC) { if (this->hostname.empty() && this->address.ss_family != AF_UNSPEC) {
assert(this->address_length != 0); assert(this->address_length != 0);
getnameinfo((struct sockaddr *)&this->address, this->address_length, this->hostname, sizeof(this->hostname), nullptr, 0, NI_NUMERICHOST); char buffer[NETWORK_HOSTNAME_LENGTH];
getnameinfo((struct sockaddr *)&this->address, this->address_length, buffer, sizeof(buffer), nullptr, 0, NI_NUMERICHOST);
this->hostname = buffer;
} }
return this->hostname; return this->hostname.c_str();
} }
/** /**
@ -234,32 +236,32 @@ SOCKET NetworkAddress::Resolve(int family, int socktype, int flags, SocketList *
/* Setting both hostname to nullptr and port to 0 is not allowed. /* Setting both hostname to nullptr and port to 0 is not allowed.
* As port 0 means bind to any port, the other must mean that * As port 0 means bind to any port, the other must mean that
* we want to bind to 'all' IPs. */ * we want to bind to 'all' IPs. */
if (StrEmpty(this->hostname) && this->address_length == 0 && this->GetPort() == 0) { if (this->hostname.empty() && this->address_length == 0 && this->GetPort() == 0) {
reset_hostname = true; reset_hostname = true;
int fam = this->address.ss_family; int fam = this->address.ss_family;
if (fam == AF_UNSPEC) fam = family; if (fam == AF_UNSPEC) fam = family;
strecpy(this->hostname, fam == AF_INET ? "0.0.0.0" : "::", lastof(this->hostname)); this->hostname = fam == AF_INET ? "0.0.0.0" : "::";
} }
static bool _resolve_timeout_error_message_shown = false; static bool _resolve_timeout_error_message_shown = false;
auto start = std::chrono::steady_clock::now(); auto start = std::chrono::steady_clock::now();
int e = getaddrinfo(StrEmpty(this->hostname) ? nullptr : this->hostname, port_name, &hints, &ai); int e = getaddrinfo(this->hostname.empty() ? nullptr : this->hostname.c_str(), port_name, &hints, &ai);
auto end = std::chrono::steady_clock::now(); auto end = std::chrono::steady_clock::now();
std::chrono::seconds duration = std::chrono::duration_cast<std::chrono::seconds>(end - start); std::chrono::seconds duration = std::chrono::duration_cast<std::chrono::seconds>(end - start);
if (!_resolve_timeout_error_message_shown && duration >= std::chrono::seconds(5)) { if (!_resolve_timeout_error_message_shown && duration >= std::chrono::seconds(5)) {
DEBUG(net, 0, "getaddrinfo for hostname \"%s\", port %s, address family %s and socket type %s took %i seconds", DEBUG(net, 0, "getaddrinfo for hostname \"%s\", port %s, address family %s and socket type %s took %i seconds",
this->hostname, port_name, AddressFamilyAsString(family), SocketTypeAsString(socktype), (int)duration.count()); this->hostname.c_str(), port_name, AddressFamilyAsString(family), SocketTypeAsString(socktype), (int)duration.count());
DEBUG(net, 0, " this is likely an issue in the DNS name resolver's configuration causing it to time out"); DEBUG(net, 0, " this is likely an issue in the DNS name resolver's configuration causing it to time out");
_resolve_timeout_error_message_shown = true; _resolve_timeout_error_message_shown = true;
} }
if (reset_hostname) strecpy(this->hostname, "", lastof(this->hostname)); if (reset_hostname) this->hostname.clear();
if (e != 0) { if (e != 0) {
if (func != ResolveLoopProc) { if (func != ResolveLoopProc) {
DEBUG(net, 0, "getaddrinfo for hostname \"%s\", port %s, address family %s and socket type %s failed: %s", DEBUG(net, 0, "getaddrinfo for hostname \"%s\", port %s, address family %s and socket type %s failed: %s",
this->hostname, port_name, AddressFamilyAsString(family), SocketTypeAsString(socktype), FS2OTTD(gai_strerror(e)).c_str()); this->hostname.c_str(), port_name, AddressFamilyAsString(family), SocketTypeAsString(socktype), FS2OTTD(gai_strerror(e)).c_str());
} }
return INVALID_SOCKET; return INVALID_SOCKET;
} }
@ -442,11 +444,11 @@ void NetworkAddress::Listen(int socktype, SocketList *sockets)
{ {
assert(sockets != nullptr); assert(sockets != nullptr);
/* Setting both hostname to nullptr and port to 0 is not allowed. /* Setting both hostname to "" and port to 0 is not allowed.
* As port 0 means bind to any port, the other must mean that * As port 0 means bind to any port, the other must mean that
* we want to bind to 'all' IPs. */ * we want to bind to 'all' IPs. */
if (this->address_length == 0 && this->address.ss_family == AF_UNSPEC && if (this->address_length == 0 && this->address.ss_family == AF_UNSPEC &&
StrEmpty(this->hostname) && this->GetPort() == 0) { this->hostname.empty() && this->GetPort() == 0) {
this->Resolve(AF_INET, socktype, AI_ADDRCONFIG | AI_PASSIVE, sockets, ListenLoopProc); this->Resolve(AF_INET, socktype, AI_ADDRCONFIG | AI_PASSIVE, sockets, ListenLoopProc);
this->Resolve(AF_INET6, socktype, AI_ADDRCONFIG | AI_PASSIVE, sockets, ListenLoopProc); this->Resolve(AF_INET6, socktype, AI_ADDRCONFIG | AI_PASSIVE, sockets, ListenLoopProc);
} else { } else {

@ -28,10 +28,10 @@ typedef SmallMap<NetworkAddress, SOCKET> SocketList; ///< Type for a mapping
*/ */
class NetworkAddress { class NetworkAddress {
private: private:
char hostname[NETWORK_HOSTNAME_LENGTH]; ///< The hostname std::string hostname; ///< The hostname
int address_length; ///< The length of the resolved address int address_length; ///< The length of the resolved address
sockaddr_storage address; ///< The resolved address sockaddr_storage address; ///< The resolved address
bool resolved; ///< Whether the address has been (tried to be) resolved bool resolved; ///< Whether the address has been (tried to be) resolved
/** /**
* Helper function to resolve something to a socket. * Helper function to resolve something to a socket.
@ -52,7 +52,6 @@ public:
address(address), address(address),
resolved(address_length != 0) resolved(address_length != 0)
{ {
*this->hostname = '\0';
} }
/** /**
@ -64,7 +63,6 @@ public:
address_length(address_length), address_length(address_length),
resolved(address_length != 0) resolved(address_length != 0)
{ {
*this->hostname = '\0';
memset(&this->address, 0, sizeof(this->address)); memset(&this->address, 0, sizeof(this->address));
memcpy(&this->address, address, address_length); memcpy(&this->address, address, address_length);
} }
@ -75,16 +73,15 @@ public:
* @param port the port * @param port the port
* @param family the address family * @param family the address family
*/ */
NetworkAddress(const char *hostname = "", uint16 port = 0, int family = AF_UNSPEC) : NetworkAddress(std::string_view hostname = "", uint16 port = 0, int family = AF_UNSPEC) :
address_length(0), address_length(0),
resolved(false) resolved(false)
{ {
/* Also handle IPv6 bracket enclosed hostnames */ if (!hostname.empty() && hostname.front() == '[' && hostname.back() == ']') {
if (StrEmpty(hostname)) hostname = ""; hostname.remove_prefix(1);
if (*hostname == '[') hostname++; hostname.remove_suffix(1);
strecpy(this->hostname, StrEmpty(hostname) ? "" : hostname, lastof(this->hostname)); }
char *tmp = strrchr(this->hostname, ']'); this->hostname = hostname;
if (tmp != nullptr) *tmp = '\0';
memset(&this->address, 0, sizeof(this->address)); memset(&this->address, 0, sizeof(this->address));
this->address.ss_family = family; this->address.ss_family = family;

@ -28,11 +28,11 @@ NetworkUDPSocketHandler::NetworkUDPSocketHandler(NetworkAddressList *bind)
this->bind.push_back(addr); this->bind.push_back(addr);
} }
} else { } else {
/* As hostname nullptr and port 0/nullptr don't go well when /* As an empty hostname and port 0 don't go well when
* resolving it we need to add an address for each of * resolving it we need to add an address for each of
* the address families we support. */ * the address families we support. */
this->bind.emplace_back(nullptr, 0, AF_INET); this->bind.emplace_back("", 0, AF_INET);
this->bind.emplace_back(nullptr, 0, AF_INET6); this->bind.emplace_back("", 0, AF_INET6);
} }
} }

Loading…
Cancel
Save