summaryrefslogtreecommitdiff
path: root/src/network/core/address.cpp
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2009-04-03 09:07:16 +0000
committerrubidium <rubidium@openttd.org>2009-04-03 09:07:16 +0000
commitdccfba6e20cdc4bb6d068f075e9b6d7fefee0fb0 (patch)
tree344540fa511b17f15af59a39a41c98460ffcda9f /src/network/core/address.cpp
parent632d74c6b1a17f3bc3419158dfc1bb5a2e5f77b5 (diff)
downloadopenttd-dccfba6e20cdc4bb6d068f075e9b6d7fefee0fb0.tar.xz
(svn r15924) -Codechange: replace NetworkResolveHost with something less AF dependant.
Diffstat (limited to 'src/network/core/address.cpp')
-rw-r--r--src/network/core/address.cpp141
1 files changed, 76 insertions, 65 deletions
diff --git a/src/network/core/address.cpp b/src/network/core/address.cpp
index 68eb692b1..d8420b206 100644
--- a/src/network/core/address.cpp
+++ b/src/network/core/address.cpp
@@ -56,24 +56,31 @@ const char *NetworkAddress::GetAddressAsString()
return buf;
}
+/**
+ * Helper function to resolve without opening a socket.
+ * @param runp information about the socket to try not
+ * @return the opened socket or INVALID_SOCKET
+ */
+static SOCKET ResolveLoopProc(addrinfo *runp)
+{
+ /* We just want the first 'entry', so return a valid socket. */
+ return !INVALID_SOCKET;
+}
+
const sockaddr_storage *NetworkAddress::GetAddress()
{
- if (!this->IsResolved()) {
- ((struct sockaddr_in *)&this->address)->sin_addr.s_addr = NetworkResolveHost(this->hostname);
- this->address_length = sizeof(sockaddr);
- }
+ if (!this->IsResolved()) this->Resolve(this->address.ss_family, 0, AI_ADDRCONFIG, ResolveLoopProc);
return &this->address;
}
-SOCKET NetworkAddress::Connect()
+SOCKET NetworkAddress::Resolve(int family, int socktype, int flags, LoopProc func)
{
- 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;
+ hints.ai_family = family;
+ hints.ai_flags = flags;
+ hints.ai_socktype = socktype;
/* The port needs to be a string. Six is enough to contain all characters + '\0'. */
char port_name[6];
@@ -87,20 +94,9 @@ SOCKET NetworkAddress::Connect()
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);
+ sock = func(runp);
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) {
- 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);
@@ -111,60 +107,75 @@ SOCKET NetworkAddress::Connect()
return sock;
}
-SOCKET NetworkAddress::Listen(int family, int socktype)
+/**
+ * Helper function to resolve a connected socket.
+ * @param runp information about the socket to try not
+ * @return the opened socket or INVALID_SOCKET
+ */
+static SOCKET ConnectLoopProc(addrinfo *runp)
{
- struct addrinfo *ai;
- struct addrinfo hints;
- memset(&hints, 0, sizeof (hints));
- hints.ai_family = family;
- hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;
- hints.ai_socktype = socktype;
+ SOCKET sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
+ if (sock == INVALID_SOCKET) {
+ DEBUG(net, 1, "Could not create socket: %s", strerror(errno));
+ return INVALID_SOCKET;
+ }
- /* The port needs to be a string. Six is enough to contain all characters + '\0'. */
- char port_name[6] = { '0' };
- seprintf(port_name, lastof(port_name), "%u", this->GetPort());
+ if (!SetNoDelay(sock)) DEBUG(net, 1, "Setting TCP_NODELAY failed");
- int e = getaddrinfo(this->GetHostname(), port_name, &hints, &ai);
- if (e != 0) {
- DEBUG(net, 0, "getaddrinfo failed: %s", gai_strerror(e));
+ if (connect(sock, runp->ai_addr, runp->ai_addrlen) != 0) {
+ DEBUG(net, 1, "Could not connect socket: %s", strerror(errno));
return INVALID_SOCKET;
}
- 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) {
- DEBUG(net, 1, "could not create socket: %s", strerror(errno));
- continue;
- }
-
- if (!SetNoDelay(sock)) DEBUG(net, 1, "Setting TCP_NODELAY failed");
-
- if (bind(sock, runp->ai_addr, runp->ai_addrlen) != 0) {
- DEBUG(net, 1, "could not bind: %s", strerror(errno));
- closesocket(sock);
- sock = INVALID_SOCKET;
- continue;
- }
-
- if (socktype != SOCK_DGRAM && listen(sock, 1) != 0) {
- DEBUG(net, 1, "could not listen: %s", strerror(errno));
- closesocket(sock);
- sock = INVALID_SOCKET;
- continue;
- }
-
- /* Connection succeeded */
- if (!SetNonBlocking(sock)) DEBUG(net, 0, "Setting non-blocking mode failed");
+ /* 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;
+ return sock;
+}
+
+SOCKET NetworkAddress::Connect()
+{
+ DEBUG(net, 1, "Connecting to %s", this->GetAddressAsString());
+
+ return this->Resolve(0, SOCK_STREAM, AI_ADDRCONFIG, ConnectLoopProc);
+}
+
+/**
+ * Helper function to resolve a listening.
+ * @param runp information about the socket to try not
+ * @return the opened socket or INVALID_SOCKET
+ */
+static SOCKET ListenLoopProc(addrinfo *runp)
+{
+ SOCKET sock = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);
+ if (sock == INVALID_SOCKET) {
+ DEBUG(net, 1, "Could not create socket: %s", strerror(errno));
+ return INVALID_SOCKET;
}
- freeaddrinfo (ai);
+
+ if (!SetNoDelay(sock)) DEBUG(net, 1, "Setting TCP_NODELAY failed");
+
+ if (bind(sock, runp->ai_addr, runp->ai_addrlen) != 0) {
+ DEBUG(net, 1, "Could not bind: %s", strerror(errno));
+ closesocket(sock);
+ return INVALID_SOCKET;
+ }
+
+ if (runp->ai_socktype != SOCK_DGRAM && listen(sock, 1) != 0) {
+ DEBUG(net, 1, "Could not listen: %s", strerror(errno));
+ closesocket(sock);
+ return INVALID_SOCKET;
+ }
+
+ /* Connection succeeded */
+ if (!SetNonBlocking(sock)) DEBUG(net, 0, "Setting non-blocking mode failed");
return sock;
}
+SOCKET NetworkAddress::Listen(int family, int socktype)
+{
+ return this->Resolve(family, socktype, AI_ADDRCONFIG | AI_PASSIVE, ListenLoopProc);
+}
+
#endif /* ENABLE_NETWORK */