From ba5aafb9bba4887b502dba32e56747fe10af604e Mon Sep 17 00:00:00 2001 From: rubidium Date: Fri, 3 Apr 2009 00:33:00 +0000 Subject: [PATCH] (svn r15921) -Fix: some OSes don't like sizeof(sockaddr_storage) but want sizeof(sockaddr) or whatever is 'valid' for the given protocol --- src/network/core/address.cpp | 17 +++++++++++++---- src/network/core/address.h | 29 ++++++++++++++++++++--------- src/network/core/udp.cpp | 4 ++-- src/network/network.cpp | 11 +---------- 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/network/core/address.cpp b/src/network/core/address.cpp index 28ab988871..c1313fe747 100644 --- a/src/network/core/address.cpp +++ b/src/network/core/address.cpp @@ -15,8 +15,10 @@ const char *NetworkAddress::GetHostname() { if (this->hostname == NULL) { + assert(this->address_length != 0); + char buf[NETWORK_HOSTNAME_LENGTH] = { '\0' }; - getnameinfo((struct sockaddr *)&this->address, sizeof(this->address), buf, sizeof(buf), NULL, 0, NI_NUMERICHOST); + getnameinfo((struct sockaddr *)&this->address, this->address_length, buf, sizeof(buf), NULL, 0, NI_NUMERICHOST); this->hostname = strdup(buf); } return this->hostname; @@ -56,9 +58,9 @@ const char *NetworkAddress::GetAddressAsString() const sockaddr_storage *NetworkAddress::GetAddress() { - if (!this->resolved) { + if (!this->IsResolved()) { ((struct sockaddr_in *)&this->address)->sin_addr.s_addr = NetworkResolveHost(this->hostname); - this->resolved = true; + this->address_length = sizeof(sockaddr); } return &this->address; } @@ -90,11 +92,18 @@ SOCKET NetworkAddress::Connect() if (!SetNoDelay(sock)) DEBUG(net, 1, "Setting TCP_NODELAY failed"); - if (connect(sock, runp->ai_addr, runp->ai_addrlen) != 0) continue; + if (connect(sock, runp->ai_addr, runp->ai_addrlen) != 0) { + closesocket(sock); + sock = INVALID_SOCKET; + continue; + } /* Connection succeeded */ if (!SetNonBlocking(sock)) DEBUG(net, 0, "Setting non-blocking mode failed"); + this->address_length = runp->ai_addrlen; + assert(sizeof(this->address) >= runp->ai_addrlen); + memcpy(&this->address, runp->ai_addr, runp->ai_addrlen); break; } freeaddrinfo (ai); diff --git a/src/network/core/address.h b/src/network/core/address.h index 598cd305ef..3e8ca03432 100644 --- a/src/network/core/address.h +++ b/src/network/core/address.h @@ -16,8 +16,8 @@ */ class NetworkAddress { private: - bool resolved; ///< Has the IP address been resolved char *hostname; ///< The hostname, NULL if there isn't one + size_t address_length; ///< The length of the resolved address sockaddr_storage address; ///< The resolved address public: @@ -27,8 +27,8 @@ public: * @param port the port */ NetworkAddress(in_addr_t ip, uint16 port) : - resolved(true), - hostname(NULL) + hostname(NULL), + address_length(sizeof(sockaddr)) { memset(&this->address, 0, sizeof(this->address)); this->address.ss_family = AF_INET; @@ -40,9 +40,9 @@ public: * Create a network address based on a resolved IP and port * @param address the IP address with port */ - NetworkAddress(struct sockaddr_storage &address) : - resolved(true), + NetworkAddress(struct sockaddr_storage &address, size_t address_length) : hostname(NULL), + address_length(address_length), address(address) { } @@ -53,8 +53,8 @@ public: * @param port the port */ NetworkAddress(const char *hostname = NULL, uint16 port = 0) : - resolved(false), - hostname(hostname == NULL ? NULL : strdup(hostname)) + hostname(hostname == NULL ? NULL : strdup(hostname)), + address_length(0) { memset(&this->address, 0, sizeof(this->address)); this->address.ss_family = AF_INET; @@ -66,8 +66,8 @@ public: * @param address the address to clone */ NetworkAddress(const NetworkAddress &address) : - resolved(address.resolved), hostname(address.hostname == NULL ? NULL : strdup(address.hostname)), + address_length(address.address_length), address(address.address) { } @@ -97,6 +97,17 @@ public: */ const sockaddr_storage *GetAddress(); + /** + * Get the (valid) length of the address. + * @return the length + */ + size_t GetAddressLength() + { + /* Resolve it if we didn't do it already */ + if (!this->IsResolved()) this->GetAddress(); + return this->address_length; + } + /** * Get the port * @return the port @@ -115,7 +126,7 @@ public: */ bool IsResolved() const { - return this->resolved; + return this->address_length != 0; } /** diff --git a/src/network/core/udp.cpp b/src/network/core/udp.cpp index 110cec2f23..4818767d90 100644 --- a/src/network/core/udp.cpp +++ b/src/network/core/udp.cpp @@ -89,7 +89,7 @@ void NetworkUDPSocketHandler::SendPacket(Packet *p, NetworkAddress *recv) p->PrepareToSend(); /* Send the buffer */ - res = sendto(this->sock, (const char*)p->buffer, p->size, 0, (struct sockaddr *)recv->GetAddress(), sizeof(*recv->GetAddress())); + res = sendto(this->sock, (const char*)p->buffer, p->size, 0, (struct sockaddr *)recv->GetAddress(), recv->GetAddressLength()); /* Check for any errors, but ignore it otherwise */ if (res == -1) DEBUG(net, 1, "[udp] sendto failed with: %i", GET_LAST_ERROR()); @@ -119,7 +119,7 @@ void NetworkUDPSocketHandler::ReceivePackets() /* We got some bytes for the base header of the packet. */ if (nbytes > 2) { - NetworkAddress address(client_addr); + NetworkAddress address(client_addr, client_len); p.PrepareToRead(); /* If the size does not match the packet must be corrupted. diff --git a/src/network/network.cpp b/src/network/network.cpp index ebd10980dc..74e0dadc16 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -1090,24 +1090,15 @@ static void NetworkGenerateUniqueId() void NetworkStartDebugLog(NetworkAddress address) { extern SOCKET _debug_socket; // Comes from debug.c - SOCKET s; DEBUG(net, 0, "Redirecting DEBUG() to %s:%d", address.GetHostname(), address.GetPort()); - s = socket(AF_INET, SOCK_STREAM, 0); + SOCKET s = address.Connect(); if (s == INVALID_SOCKET) { DEBUG(net, 0, "Failed to open socket for redirection DEBUG()"); return; } - if (!SetNoDelay(s)) DEBUG(net, 1, "Setting TCP_NODELAY failed"); - - if (connect(s, (struct sockaddr *)address.GetAddress(), sizeof(*address.GetAddress())) != 0) { - DEBUG(net, 0, "Failed to redirection DEBUG() to %s", address.GetAddressAsString()); - return; - } - - if (!SetNonBlocking(s)) DEBUG(net, 0, "Setting non-blocking mode failed"); _debug_socket = s; DEBUG(net, 0, "DEBUG() is now redirected");