summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/network/core/address.cpp141
-rw-r--r--src/network/core/address.h16
-rw-r--r--src/network/core/host.cpp46
-rw-r--r--src/network/core/host.h1
4 files changed, 92 insertions, 112 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 */
diff --git a/src/network/core/address.h b/src/network/core/address.h
index c42805add..eea66cabb 100644
--- a/src/network/core/address.h
+++ b/src/network/core/address.h
@@ -20,6 +20,22 @@ private:
size_t address_length; ///< The length of the resolved address
sockaddr_storage address; ///< The resolved address
+ /**
+ * Helper function to resolve something to a socket.
+ * @param runp information about the socket to try not
+ * @return the opened socket or INVALID_SOCKET
+ */
+ typedef SOCKET (*LoopProc)(addrinfo *runp);
+
+ /**
+ * Resolve this address into a socket
+ * @param family the type of 'protocol' (IPv4, IPv6)
+ * @param socktype the type of socket (TCP, UDP, etc)
+ * @param flags the flags to send to getaddrinfo
+ * @param func the inner working while looping over the address info
+ * @return the resolved socket or INVALID_SOCKET.
+ */
+ SOCKET Resolve(int family, int socktype, int flags, LoopProc func);
public:
/**
* Create a network address based on a resolved IP and port
diff --git a/src/network/core/host.cpp b/src/network/core/host.cpp
index bcd317f8c..4f83c1b37 100644
--- a/src/network/core/host.cpp
+++ b/src/network/core/host.cpp
@@ -204,50 +204,4 @@ void NetworkFindBroadcastIPs(uint32 *broadcast, int limit)
}
}
-
-/**
- * Resolve a hostname to an ip.
- * @param hsotname the hostname to resolve
- * @return the IP belonging to that hostname, or 0 on failure.
- */
-uint32 NetworkResolveHost(const char *hostname)
-{
- /* Is this an IP address? */
- in_addr_t ip = inet_addr(hostname);
-
- if (ip != INADDR_NONE) return ip;
-
- /* No, try to resolve the name */
- struct in_addr addr;
-#if !defined(PSP)
- struct hostent *he = gethostbyname(hostname);
- if (he == NULL) {
- DEBUG(net, 0, "[NET] Cannot resolve %s", hostname);
- return 0;
- }
- addr = *(struct in_addr *)he->h_addr_list[0];
-#else
- int rid = -1;
- char buf[1024];
-
- /* Create a resolver */
- if (sceNetResolverCreate(&rid, buf, sizeof(buf)) < 0) {
- DEBUG(net, 0, "[NET] Error connecting resolver");
- return 0;
- }
-
- /* Try to resolve the name */
- if (sceNetResolverStartNtoA(rid, hostname, &addr, 2, 3) < 0) {
- DEBUG(net, 0, "[NET] Cannot resolve %s", hostname);
- sceNetResolverDelete(rid);
- return 0;
- }
- sceNetResolverDelete(rid);
-#endif /* PSP */
-
- DEBUG(net, 1, "[NET] Resolved %s to %s", hostname, inet_ntoa(addr));
- ip = addr.s_addr;
- return ip;
-}
-
#endif /* ENABLE_NETWORK */
diff --git a/src/network/core/host.h b/src/network/core/host.h
index 9735cce84..b54819912 100644
--- a/src/network/core/host.h
+++ b/src/network/core/host.h
@@ -7,6 +7,5 @@
#ifndef NETWORK_CORE_HOST_H
void NetworkFindBroadcastIPs(uint32 *broadcast, int limit);
-uint32 NetworkResolveHost(const char *hostname);
#endif /* NETWORK_CORE_HOST_H */