1
0
Fork 0

(svn r15970) -Codechange: make it possible to resolve a single address into multiple sockets.

release/1.0
rubidium 2009-04-07 19:52:01 +00:00
parent 82f8badc07
commit 6db7f15b3a
2 changed files with 28 additions and 14 deletions

View File

@ -87,7 +87,7 @@ const sockaddr_storage *NetworkAddress::GetAddress()
* bothered to implement the specifications and allow '0' as value * bothered to implement the specifications and allow '0' as value
* that means "don't care whether it is SOCK_STREAM or SOCK_DGRAM". * that means "don't care whether it is SOCK_STREAM or SOCK_DGRAM".
*/ */
this->Resolve(this->address.ss_family, SOCK_STREAM, AI_ADDRCONFIG, ResolveLoopProc); this->Resolve(this->address.ss_family, SOCK_STREAM, AI_ADDRCONFIG, NULL, ResolveLoopProc);
} }
return &this->address; return &this->address;
} }
@ -146,7 +146,7 @@ bool NetworkAddress::IsInNetmask(char *netmask)
return true; return true;
} }
SOCKET NetworkAddress::Resolve(int family, int socktype, int flags, LoopProc func) SOCKET NetworkAddress::Resolve(int family, int socktype, int flags, SocketList *sockets, LoopProc func)
{ {
struct addrinfo *ai; struct addrinfo *ai;
struct addrinfo hints; struct addrinfo hints;
@ -159,6 +159,9 @@ SOCKET NetworkAddress::Resolve(int family, int socktype, int flags, LoopProc fun
char port_name[6]; char port_name[6];
seprintf(port_name, lastof(port_name), "%u", this->GetPort()); seprintf(port_name, lastof(port_name), "%u", this->GetPort());
/* Setting both hostname to NULL and port to 0 is not allowed.
* As port 0 means bind to any port, the other must mean that
* we want to bind to 'all' IPs. */
if (this->address_length == 0 && StrEmpty(this->hostname)) { if (this->address_length == 0 && StrEmpty(this->hostname)) {
strecpy(this->hostname, this->address.ss_family == AF_INET ? "0.0.0.0" : "::", lastof(this->hostname)); strecpy(this->hostname, this->address.ss_family == AF_INET ? "0.0.0.0" : "::", lastof(this->hostname));
} }
@ -174,10 +177,16 @@ SOCKET NetworkAddress::Resolve(int family, int socktype, int flags, LoopProc fun
sock = func(runp); sock = func(runp);
if (sock == INVALID_SOCKET) continue; if (sock == INVALID_SOCKET) continue;
this->address_length = runp->ai_addrlen; if (sockets == NULL) {
assert(sizeof(this->address) >= runp->ai_addrlen); this->address_length = runp->ai_addrlen;
memcpy(&this->address, runp->ai_addr, runp->ai_addrlen); assert(sizeof(this->address) >= runp->ai_addrlen);
break; memcpy(&this->address, runp->ai_addr, runp->ai_addrlen);
break;
}
NetworkAddress addr(runp->ai_addr, runp->ai_addrlen);
(*sockets)[addr] = sock;
sock = INVALID_SOCKET;
} }
freeaddrinfo (ai); freeaddrinfo (ai);
@ -215,7 +224,7 @@ SOCKET NetworkAddress::Connect()
{ {
DEBUG(net, 1, "Connecting to %s", this->GetAddressAsString()); DEBUG(net, 1, "Connecting to %s", this->GetAddressAsString());
return this->Resolve(0, SOCK_STREAM, AI_ADDRCONFIG, ConnectLoopProc); return this->Resolve(0, SOCK_STREAM, AI_ADDRCONFIG, NULL, ConnectLoopProc);
} }
/** /**
@ -231,7 +240,9 @@ static SOCKET ListenLoopProc(addrinfo *runp)
return INVALID_SOCKET; return INVALID_SOCKET;
} }
if (!SetNoDelay(sock)) DEBUG(net, 1, "Setting TCP_NODELAY failed"); if (runp->ai_socktype == SOCK_STREAM && !SetNoDelay(sock)) {
DEBUG(net, 1, "Setting TCP_NODELAY failed");
}
int on = 1; int on = 1;
/* The (const char*) cast is needed for windows!! */ /* The (const char*) cast is needed for windows!! */
@ -262,9 +273,9 @@ static SOCKET ListenLoopProc(addrinfo *runp)
return sock; return sock;
} }
SOCKET NetworkAddress::Listen(int family, int socktype) SOCKET NetworkAddress::Listen(int family, int socktype, SocketList *sockets)
{ {
return this->Resolve(family, socktype, AI_ADDRCONFIG | AI_PASSIVE, ListenLoopProc); return this->Resolve(family, socktype, AI_ADDRCONFIG | AI_PASSIVE, sockets, ListenLoopProc);
} }
#endif /* ENABLE_NETWORK */ #endif /* ENABLE_NETWORK */

View File

@ -10,10 +10,11 @@
#include "os_abstraction.h" #include "os_abstraction.h"
#include "config.h" #include "config.h"
#include "../../string_func.h" #include "../../string_func.h"
#include "../../core/smallvec_type.hpp" #include "../../core/smallmap_type.hpp"
class NetworkAddress; class NetworkAddress;
typedef SmallVector<NetworkAddress, 4> NetworkAddressList; typedef SmallVector<NetworkAddress, 4> NetworkAddressList;
typedef SmallMap<NetworkAddress, SOCKET, 4> SocketList;
/** /**
* Wrapper for (un)resolved network addresses; there's no reason to transform * Wrapper for (un)resolved network addresses; there's no reason to transform
@ -38,10 +39,11 @@ private:
* @param family the type of 'protocol' (IPv4, IPv6) * @param family the type of 'protocol' (IPv4, IPv6)
* @param socktype the type of socket (TCP, UDP, etc) * @param socktype the type of socket (TCP, UDP, etc)
* @param flags the flags to send to getaddrinfo * @param flags the flags to send to getaddrinfo
* @param sockets the list of sockets to add the sockets to
* @param func the inner working while looping over the address info * @param func the inner working while looping over the address info
* @return the resolved socket or INVALID_SOCKET. * @return the resolved socket or INVALID_SOCKET.
*/ */
SOCKET Resolve(int family, int socktype, int flags, LoopProc func); SOCKET Resolve(int family, int socktype, int flags, SocketList *sockets, LoopProc func);
public: public:
/** /**
* Create a network address based on a resolved IP and port * Create a network address based on a resolved IP and port
@ -217,9 +219,10 @@ public:
* Make the given socket listen. * Make the given socket listen.
* @param family the type of 'protocol' (IPv4, IPv6) * @param family the type of 'protocol' (IPv4, IPv6)
* @param socktype the type of socket (TCP, UDP, etc) * @param socktype the type of socket (TCP, UDP, etc)
* @return the listening socket or INVALID_SOCKET. * @param sockets the list of sockets to add the sockets to
* @return the socket (if sockets != NULL)
*/ */
SOCKET Listen(int family, int socktype); SOCKET Listen(int family, int socktype, SocketList *sockets = NULL);
}; };
#endif /* ENABLE_NETWORK */ #endif /* ENABLE_NETWORK */