diff options
-rw-r--r-- | src/network/core/address.cpp | 141 | ||||
-rw-r--r-- | src/network/core/address.h | 16 | ||||
-rw-r--r-- | src/network/core/host.cpp | 46 | ||||
-rw-r--r-- | src/network/core/host.h | 1 |
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 */ |