Mercurial > hg > openttd
changeset 11558:93f83100b0bb draft
(svn r15924) -Codechange: replace NetworkResolveHost with something less AF dependant.
author | rubidium <rubidium@openttd.org> |
---|---|
date | Fri, 03 Apr 2009 09:07:16 +0000 |
parents | 39f9d11c789a |
children | 61f34aed5412 |
files | src/network/core/address.cpp src/network/core/address.h src/network/core/host.cpp src/network/core/host.h |
diffstat | 4 files changed, 94 insertions(+), 114 deletions(-) [+] |
line wrap: on
line diff
--- a/src/network/core/address.cpp +++ b/src/network/core/address.cpp @@ -56,24 +56,31 @@ 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 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 @@ 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; - - /* 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()); - - int e = getaddrinfo(this->GetHostname(), port_name, &hints, &ai); - if (e != 0) { - DEBUG(net, 0, "getaddrinfo failed: %s", gai_strerror(e)); + 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; } - 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 (!SetNoDelay(sock)) DEBUG(net, 1, "Setting TCP_NODELAY failed"); - if (socktype != SOCK_DGRAM && listen(sock, 1) != 0) { - DEBUG(net, 1, "could not listen: %s", strerror(errno)); - closesocket(sock); - sock = INVALID_SOCKET; - continue; - } + if (connect(sock, runp->ai_addr, runp->ai_addrlen) != 0) { + DEBUG(net, 1, "Could not connect socket: %s", strerror(errno)); + return INVALID_SOCKET; + } - /* 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; - } - freeaddrinfo (ai); + /* Connection succeeded */ + if (!SetNonBlocking(sock)) DEBUG(net, 0, "Setting non-blocking mode failed"); 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; + } + + 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 */
--- a/src/network/core/address.h +++ b/src/network/core/address.h @@ -20,6 +20,22 @@ 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
--- a/src/network/core/host.cpp +++ b/src/network/core/host.cpp @@ -204,50 +204,4 @@ } } - -/** - * 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 */