diff options
-rw-r--r-- | src/network/core/address.cpp | 40 | ||||
-rw-r--r-- | src/network/core/address.h | 10 | ||||
-rw-r--r-- | src/network/core/tcp_connect.cpp | 21 |
3 files changed, 53 insertions, 18 deletions
diff --git a/src/network/core/address.cpp b/src/network/core/address.cpp index 888625dc1..28ab98887 100644 --- 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 @@ const sockaddr_storage *NetworkAddress::GetAddress() 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 */ diff --git a/src/network/core/address.h b/src/network/core/address.h index 3a4b8c06e..598cd305e 100644 --- a/src/network/core/address.h +++ b/src/network/core/address.h @@ -128,6 +128,11 @@ public: 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 @@ public: return *this; } + /** + * Connect to the given address. + * @return the connected socket or INVALID_SOCKET. + */ + SOCKET Connect(); }; #endif /* ENABLE_NETWORK */ diff --git a/src/network/core/tcp_connect.cpp b/src/network/core/tcp_connect.cpp index a994fc6d2..2e292b5d0 100644 --- a/src/network/core/tcp_connect.cpp +++ b/src/network/core/tcp_connect.cpp @@ -31,27 +31,12 @@ TCPConnecter::TCPConnecter(const NetworkAddress &address) : 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; } |