1
0
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:
Daniel Collins 2018-11-10 22:37:02 +00:00
parent 6df47cee60
commit 9c1345f44a

View File

@ -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;
}