shithub: choc

Download patch

ref: d1f2b422e6cbcf2b50b0e02b989cb3fbb314eb9e
parent: 48f038cc625fc63cbb17a853134fa1676c7bb55c
author: Simon Howard <fraggle@soulsphere.org>
date: Sat Feb 9 18:00:33 EST 2019

net: Send hole punch requests on connect.

To avoid spurious requests, only send requests if no response is received
after 2 seconds - most connect requests should complete before that if the
server port is publicly accessible.

--- a/src/net_client.c
+++ b/src/net_client.c
@@ -35,6 +35,7 @@
 #include "net_gui.h"
 #include "net_io.h"
 #include "net_packet.h"
+#include "net_query.h"
 #include "net_server.h"
 #include "net_structrw.h"
 #include "w_checksum.h"
@@ -1024,6 +1025,7 @@
 {
     int start_time;
     int last_send_time;
+    boolean sent_hole_punch;
 
     server_addr = addr;
     NET_ReferenceAddress(addr);
@@ -1032,13 +1034,10 @@
     memcpy(net_local_deh_sha1sum, data->deh_sha1sum, sizeof(sha1_digest_t));
     net_local_is_freedoom = data->is_freedoom;
 
-    // create a new network I/O context and add just the
-    // necessary module
-
+    // create a new network I/O context and add just the necessary module
     client_context = NET_NewContext();
 
     // initialize module for client mode
-
     if (!addr->module->InitClient())
     {
         return false;
@@ -1048,13 +1047,11 @@
 
     net_client_connected = true;
     net_client_received_wait_data = false;
+    sent_hole_punch = false;
 
-    // Initialize connection
-
     NET_Conn_InitClient(&client_connection, addr, NET_PROTOCOL_UNKNOWN);
 
     // try to connect
-
     start_time = I_GetTimeMS();
     last_send_time = -1;
 
@@ -1063,7 +1060,6 @@
         int nowtime = I_GetTimeMS();
 
         // Send a SYN packet every second.
-
         if (nowtime - last_send_time > 1000 || last_send_time < 0)
         {
             NET_CL_SendSYN(data);
@@ -1071,23 +1067,25 @@
         }
 
         // time out after 5 seconds
-
         if (nowtime - start_time > 5000)
         {
             break;
         }
 
-        // run client code
+        if (!sent_hole_punch && nowtime - start_time > 2000)
+        {
+            NET_Log("client: no response to SYN, requesting hole punch");
+            NET_RequestHolePunch(client_context, addr);
+            sent_hole_punch = true;
+        }
 
+        // run client code
         NET_CL_Run();
 
-        // run the server, just incase we are doing a loopback
-        // connect
-
+        // run the server, just in case we are doing a loopback connect
         NET_SV_Run();
 
         // Don't hog the CPU
-
         I_Sleep(1);
     }
 
--- a/src/net_query.c
+++ b/src/net_query.c
@@ -176,6 +176,28 @@
     NET_FreePacket(packet);
 }
 
+// Send a hole punch request to the master server for the server at the
+// given address.
+void NET_RequestHolePunch(net_context_t *context, net_addr_t *addr)
+{
+    net_addr_t *master_addr;
+    net_packet_t *packet;
+
+    master_addr = NET_Query_ResolveMaster(context);
+    if (master_addr == NULL)
+    {
+        return;
+    }
+
+    packet = NET_NewPacket(32);
+    NET_WriteInt16(packet, NET_MASTER_PACKET_TYPE_NAT_HOLE_PUNCH);
+    NET_WriteString(packet, NET_AddrToString(addr));
+    NET_SendPacket(master_addr, packet);
+
+    NET_FreePacket(packet);
+    NET_ReleaseAddress(master_addr);
+}
+
 // Given the specified address, find the target associated.  If no
 // target is found, and 'create' is true, a new target is created.
 
--- a/src/net_query.h
+++ b/src/net_query.h
@@ -39,6 +39,7 @@
 extern void NET_Query_AddToMaster(net_addr_t *master_addr);
 extern boolean NET_Query_CheckAddedToMaster(boolean *result);
 extern void NET_Query_AddResponse(net_packet_t *packet);
+extern void NET_RequestHolePunch(net_context_t *context, net_addr_t *addr);
 
 #endif /* #ifndef NET_QUERY_H */