mirror of
https://github.com/solemnwarning/directplay-lite
synced 2024-12-30 16:45:37 +01:00
IDirectPlay8Peer: Randomly select dynamic ports in Connect() method.
It turns out disabling SO_LINGER on Windows doesn't /really/ make the socket go away by the time closesocket() returns, just very shortly afterwards, so rapidly destroying and re-creating connections on a slow machine can fail due to a connect() address conflict.
This commit is contained in:
parent
6df47cee60
commit
9c1345f44a
@ -482,17 +482,32 @@ HRESULT DirectPlay8Peer::Connect(CONST DPN_APPLICATION_DESC* CONST pdnAppDesc, I
|
||||
|
||||
if(l_port == 0)
|
||||
{
|
||||
/* Start at a random point in the ephemeral port range and try each one, wrapping
|
||||
* around when we reach the end.
|
||||
*
|
||||
* Gets the "random" point by querying the performance counter rather than calling
|
||||
* rand() just in case the application relies on the RNG state.
|
||||
*/
|
||||
|
||||
LARGE_INTEGER p_counter;
|
||||
QueryPerformanceCounter(&p_counter);
|
||||
|
||||
int port_range = AUTO_PORT_MAX - AUTO_PORT_MIN;
|
||||
int base_port = p_counter.QuadPart % port_range;
|
||||
|
||||
for(int p = AUTO_PORT_MIN; p <= AUTO_PORT_MAX; ++p)
|
||||
{
|
||||
/* TODO: Only continue if creation failed due to address conflict. */
|
||||
|
||||
udp_socket = create_udp_socket(l_ipaddr, p);
|
||||
int port = AUTO_PORT_MIN + ((base_port + p) % (port_range + 1));
|
||||
|
||||
udp_socket = create_udp_socket(l_ipaddr, port);
|
||||
if(udp_socket == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
listener_socket = create_listener_socket(l_ipaddr, p);
|
||||
listener_socket = create_listener_socket(l_ipaddr, port);
|
||||
if(listener_socket == -1)
|
||||
{
|
||||
closesocket(udp_socket);
|
||||
@ -502,7 +517,7 @@ HRESULT DirectPlay8Peer::Connect(CONST DPN_APPLICATION_DESC* CONST pdnAppDesc, I
|
||||
}
|
||||
|
||||
local_ip = l_ipaddr;
|
||||
local_port = p;
|
||||
local_port = port;
|
||||
|
||||
break;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user