changeset 11555:e33ab0599ab6 draft

(svn r15920) -Codechange: make the (TCP) connecting less AF dependent.
author rubidium <rubidium@openttd.org>
date Thu, 02 Apr 2009 23:59:43 +0000
parents 2a8e3e39662f
children e3b2f1cda105
files src/network/core/address.cpp src/network/core/address.h src/network/core/tcp_connect.cpp
diffstat 3 files changed, 53 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/src/network/core/address.cpp
+++ b/src/network/core/address.cpp
@@ -10,6 +10,7 @@
 #include "config.h"
 #include "host.h"
 #include "../../string_func.h"
+#include "../../debug.h"
 
 const char *NetworkAddress::GetHostname()
 {
@@ -62,4 +63,43 @@
 	return &this->address;
 }
 
+SOCKET NetworkAddress::Connect()
+{
+	DEBUG(net, 1, "Connecting to %s", this->GetAddressAsString());
+
+	struct addrinfo *ai;
+	struct addrinfo hints;
+	memset(&hints, 0, sizeof (hints));
+	hints.ai_flags    = AI_ADDRCONFIG;
+	hints.ai_socktype = SOCK_STREAM;
+
+	/* The port needs to be a string. Six is enough to contain all characters + '\0'. */
+	char port_name[6];
+	seprintf(port_name, lastof(port_name), "%u", this->GetPort());
+
+	int e = getaddrinfo(this->GetHostname(), port_name, &hints, &ai);
+	if (e != 0) {
+		DEBUG(net, 0, "getaddrinfo failed: %s", gai_strerror(e));
+		return false;
+	}
+
+	SOCKET sock = INVALID_SOCKET;
+	for (struct addrinfo *runp = ai; runp != NULL; runp = runp->ai_next) {
+		sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
+		if (sock == INVALID_SOCKET) continue;
+
+		if (!SetNoDelay(sock)) DEBUG(net, 1, "Setting TCP_NODELAY failed");
+
+		if (connect(sock, runp->ai_addr, runp->ai_addrlen) != 0) continue;
+
+		/* Connection succeeded */
+		if (!SetNonBlocking(sock)) DEBUG(net, 0, "Setting non-blocking mode failed");
+
+		break;
+	}
+	freeaddrinfo (ai);
+
+	return sock;
+}
+
 #endif /* ENABLE_NETWORK */
--- a/src/network/core/address.h
+++ b/src/network/core/address.h
@@ -128,6 +128,11 @@
 		return this->GetPort() == address.GetPort() && strcmp(this->GetHostname(), address.GetHostname()) == 0;
 	}
 
+	/**
+	 * Assign another address to ourself
+	 * @param other obviously the address to assign to us
+	 * @return 'this'
+	 */
 	NetworkAddress& operator = (const NetworkAddress &other)
 	{
 		if (this != &other) { // protect against invalid self-assignment
@@ -138,6 +143,11 @@
 		return *this;
 	}
 
+	/**
+	 * Connect to the given address.
+	 * @return the connected socket or INVALID_SOCKET.
+	 */
+	SOCKET Connect();
 };
 
 #endif /* ENABLE_NETWORK */
--- a/src/network/core/tcp_connect.cpp
+++ b/src/network/core/tcp_connect.cpp
@@ -31,27 +31,12 @@
 
 void TCPConnecter::Connect()
 {
-	DEBUG(net, 1, "Connecting to %s %d", address.GetHostname(), address.GetPort());
-
-	this->sock = socket(AF_INET, SOCK_STREAM, 0);
+	this->sock = this->address.Connect();
 	if (this->sock == INVALID_SOCKET) {
 		this->aborted = true;
-		return;
+	} else {
+		this->connected = true;
 	}
-
-	if (!SetNoDelay(this->sock)) DEBUG(net, 1, "Setting TCP_NODELAY failed");
-
-	/* We failed to connect for which reason what so ever */
-	if (connect(this->sock, (struct sockaddr*)this->address.GetAddress(), sizeof(*this->address.GetAddress())) != 0) {
-		closesocket(this->sock);
-		this->sock = INVALID_SOCKET;
-		this->aborted = true;
-		return;
-	}
-
-	if (!SetNonBlocking(this->sock)) DEBUG(net, 0, "Setting non-blocking mode failed");
-
-	this->connected = true;
 }