Skip to content
Permalink
Browse files
return error when random port pool is empty
fixes #232
  • Loading branch information
robgjansen committed Sep 5, 2014
1 parent 3c0b3ee commit 3acc9c2fbcad0d2d57ed476277736c90961585dc
Showing with 34 additions and 14 deletions.
  1. +28 −14 src/host/shd-host.c
  2. +5 −0 src/host/shd-network-interface.c
  3. +1 −0 src/host/shd-network-interface.h
@@ -664,22 +664,24 @@ static gboolean _host_isInterfaceAvailable(Host* host, in_addr_t interfaceIP,
}


static in_port_t _host_getRandomFreePort(Host* host, in_addr_t interfaceIP,
DescriptorType type) {
MAGIC_ASSERT(host);

in_port_t randomNetworkPort = 0;
gboolean available = FALSE;
static in_port_t _host_getRandomFreePort(Host* host, in_addr_t interfaceIP, DescriptorType type) {
MAGIC_ASSERT(host);

while(!available) {
gdouble randomFraction = random_nextDouble(host->random);
in_port_t randomHostPort = (in_port_t) (randomFraction * (UINT16_MAX - MIN_RANDOM_PORT)) + MIN_RANDOM_PORT;
utility_assert(randomHostPort >= MIN_RANDOM_PORT);
randomNetworkPort = htons(randomHostPort);
available = _host_isInterfaceAvailable(host, interfaceIP, type, randomNetworkPort);
}
NetworkInterface* interface = host_lookupInterface(host, interfaceIP);
in_port_t randomNetworkPort = 0;

if (interface && networkinterface_hasFreePorts(interface)) {
gboolean freePortFound = FALSE;
while (!freePortFound) {
gdouble randomFraction = random_nextDouble(host->random);
in_port_t randomHostPort = (in_port_t) (randomFraction * (UINT16_MAX - MIN_RANDOM_PORT)) + MIN_RANDOM_PORT;
utility_assert(randomHostPort >= MIN_RANDOM_PORT);
randomNetworkPort = htons(randomHostPort);
freePortFound = _host_isInterfaceAvailable(host, interfaceIP, type, randomNetworkPort);
}
}

return randomNetworkPort;
return randomNetworkPort;
}

gint host_bindToInterface(Host* host, gint handle, const struct sockaddr* address) {
@@ -737,6 +739,9 @@ gint host_bindToInterface(Host* host, gint handle, const struct sockaddr* addres
if(bindPort == 0) {
/* we know it will be available */
bindPort = _host_getRandomFreePort(host, bindAddress, type);
if(!bindPort) {
return EADDRNOTAVAIL;
}
} else {
/* make sure their port is available at that address for this protocol. */
if(!_host_isInterfaceAvailable(host, bindAddress, type, bindPort)) {
@@ -842,6 +847,9 @@ gint host_connectToPeer(Host* host, gint handle, const struct sockaddr* address)

in_addr_t bindAddress = loIP == peerIP ? loIP : defaultIP;
in_port_t bindPort = _host_getRandomFreePort(host, bindAddress, type);
if(!bindPort) {
return EADDRNOTAVAIL;
}

_host_associateInterface(host, socket, bindAddress, bindPort);
}
@@ -877,6 +885,9 @@ gint host_listenForPeer(Host* host, gint handle, gint backlog) {
/* implicit bind */
in_addr_t bindAddress = htonl(INADDR_ANY);
in_port_t bindPort = _host_getRandomFreePort(host, bindAddress, type);
if(!bindPort) {
return EADDRNOTAVAIL;
}

_host_associateInterface(host, socket, bindAddress, bindPort);
}
@@ -1059,6 +1070,9 @@ gint host_sendUserData(Host* host, gint handle, gconstpointer buffer, gsize nByt
in_addr_t bindAddress = ip == htonl(INADDR_LOOPBACK) ? htonl(INADDR_LOOPBACK) :
networkinterface_getIPAddress(host->defaultInterface);
in_port_t bindPort = _host_getRandomFreePort(host, bindAddress, type);
if(!bindPort) {
return EADDRNOTAVAIL;
}

/* bind port and set associations */
_host_associateInterface(host, socket, bindAddress, bindPort);
@@ -224,6 +224,11 @@ gboolean networkinterface_isAssociated(NetworkInterface* interface, gint key) {
}
}

gboolean networkinterface_hasFreePorts(NetworkInterface* interface) {
MAGIC_ASSERT(interface);
return g_hash_table_size(interface->boundSockets) < (UINT16_MAX - MIN_RANDOM_PORT) ? TRUE : FALSE;
}

void networkinterface_associate(NetworkInterface* interface, Socket* socket) {
MAGIC_ASSERT(interface);

@@ -24,6 +24,7 @@ guint32 networkinterface_getSpeedDownKiBps(NetworkInterface* interface);
gboolean networkinterface_isAssociated(NetworkInterface* interface, gint key);
void networkinterface_associate(NetworkInterface* interface, Socket* transport);
void networkinterface_disassociate(NetworkInterface* interface, Socket* transport);
gboolean networkinterface_hasFreePorts(NetworkInterface* interface);

void networkinterface_packetArrived(NetworkInterface* interface, Packet* packet);
void networkinterface_packetDropped(NetworkInterface* interface, Packet* packet);

0 comments on commit 3acc9c2

Please sign in to comment.