changeset 11556:e3b2f1cda105 draft

(svn r15921) -Fix: some OSes don't like sizeof(sockaddr_storage) but want sizeof(sockaddr) or whatever is 'valid' for the given protocol
author rubidium <rubidium@openttd.org>
date Fri, 03 Apr 2009 00:33:00 +0000
parents e33ab0599ab6
children 39f9d11c789a
files src/network/core/address.cpp src/network/core/address.h src/network/core/udp.cpp src/network/network.cpp
diffstat 4 files changed, 36 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- 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 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 @@
 
 		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);
--- 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 @@
 	 * @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 @@
 	 * 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 @@
 	 * @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 @@
 	 * @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)
 	{
 	}
@@ -98,6 +98,17 @@
 	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 @@
 	 */
 	bool IsResolved() const
 	{
-		return this->resolved;
+		return this->address_length != 0;
 	}
 
 	/**
--- a/src/network/core/udp.cpp
+++ b/src/network/core/udp.cpp
@@ -89,7 +89,7 @@
 	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 @@
 
 	/* 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.
--- a/src/network/network.cpp
+++ b/src/network/network.cpp
@@ -1090,24 +1090,15 @@
 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");