shithub: choc

Download patch

ref: 76178ee71572e399ede72eac8d448595e6daac63
parent: 660cad3966afdcd745a3468e23416e48aee88c28
author: Simon Howard <fraggle@soulsphere.org>
date: Sat Feb 9 14:25:33 EST 2019

net: Add initial server code for NAT hole punching.

This allows the master server to send a hole punch request to servers
that will assist clients in connecting to them if they are behind
firewalls / NAT gateways. However, this is just the first piece in
implementation of #469 and more work is needed.

--- a/src/net_defs.h
+++ b/src/net_defs.h
@@ -149,6 +149,7 @@
     NET_PACKET_TYPE_QUERY,
     NET_PACKET_TYPE_QUERY_RESPONSE,
     NET_PACKET_TYPE_LAUNCH,
+    NET_PACKET_TYPE_NAT_HOLE_PUNCH,
 } net_packet_type_t;
 
 typedef enum
@@ -163,6 +164,7 @@
     NET_MASTER_PACKET_TYPE_SIGN_START_RESPONSE,
     NET_MASTER_PACKET_TYPE_SIGN_END,
     NET_MASTER_PACKET_TYPE_SIGN_END_RESPONSE,
+    NET_MASTER_PACKET_TYPE_NAT_HOLE_PUNCH,
 } net_master_packet_type_t;
 
 // Settings specified when the client connects to the server.
--- a/src/net_query.c
+++ b/src/net_query.c
@@ -120,40 +120,35 @@
 
 // Process a packet received from the master server.
 
-void NET_Query_MasterResponse(net_packet_t *packet)
+void NET_Query_AddResponse(net_packet_t *packet)
 {
-    unsigned int packet_type;
     unsigned int result;
 
-    if (!NET_ReadInt16(packet, &packet_type)
-     || !NET_ReadInt16(packet, &result))
+    if (!NET_ReadInt16(packet, &result))
     {
         return;
     }
 
-    if (packet_type == NET_MASTER_PACKET_TYPE_ADD_RESPONSE)
+    if (result != 0)
     {
-        if (result != 0)
-        {
-            // Only show the message once.
+        // Only show the message once.
 
-            if (!registered_with_master)
-            {
-                printf("Registered with master server at %s\n",
-                       MASTER_SERVER_ADDRESS);
-                registered_with_master = true;
-            }
-        }
-        else
+        if (!registered_with_master)
         {
-            // Always show rejections.
-
-            printf("Failed to register with master server at %s\n",
+            printf("Registered with master server at %s\n",
                    MASTER_SERVER_ADDRESS);
+            registered_with_master = true;
         }
+    }
+    else
+    {
+        // Always show rejections.
 
-        got_master_response = true;
+        printf("Failed to register with master server at %s\n",
+               MASTER_SERVER_ADDRESS);
     }
+
+    got_master_response = true;
 }
 
 boolean NET_Query_CheckAddedToMaster(boolean *result)
--- a/src/net_query.h
+++ b/src/net_query.h
@@ -38,7 +38,7 @@
 extern net_addr_t *NET_Query_ResolveMaster(net_context_t *context);
 extern void NET_Query_AddToMaster(net_addr_t *master_addr);
 extern boolean NET_Query_CheckAddedToMaster(boolean *result);
-extern void NET_Query_MasterResponse(net_packet_t *packet);
+extern void NET_Query_AddResponse(net_packet_t *packet);
 
 #endif /* #ifndef NET_QUERY_H */
 
--- a/src/net_server.c
+++ b/src/net_server.c
@@ -1423,6 +1423,63 @@
     NET_FreePacket(reply);
 }
 
+static void NET_SV_ParseHolePunch(net_packet_t *packet)
+{
+    const char *addr_string;
+    net_packet_t *sendpacket;
+    net_addr_t *addr;
+
+    addr_string = NET_ReadString(packet);
+    if (addr_string == NULL)
+    {
+        NET_Log("server: error: hole punch request but no address provided");
+        return;
+    }
+
+    addr = NET_ResolveAddress(server_context, addr_string);
+    if (addr == NULL)
+    {
+        NET_Log("server: error: failed to resolve address: %s", addr_string);
+        return;
+    }
+
+    sendpacket = NET_NewPacket(16);
+    NET_WriteInt16(sendpacket, NET_PACKET_TYPE_NAT_HOLE_PUNCH);
+    NET_SendPacket(addr, sendpacket);
+    NET_FreePacket(sendpacket);
+
+    // TODO: We should NET_FreeAddress(addr) here, but this could cause a
+    // problem if the client has already connected. The address system needs
+    // to be changed to use a reference-counting system to prevent this.
+}
+
+static void NET_SV_MasterPacket(net_packet_t *packet)
+{
+    unsigned int packet_type;
+
+    // Read the packet type
+
+    if (!NET_ReadInt16(packet, &packet_type))
+    {
+        NET_Log("server: error: no packet type in master server message");
+        return;
+    }
+
+    NET_Log("server: packet from master server; type %d", packet_type);
+    NET_LogPacket(packet);
+
+    switch (packet_type)
+    {
+        case NET_MASTER_PACKET_TYPE_ADD_RESPONSE:
+            NET_Query_AddResponse(packet);
+            break;
+
+        case NET_MASTER_PACKET_TYPE_NAT_HOLE_PUNCH:
+            NET_SV_ParseHolePunch(packet);
+            break;
+    }
+}
+
 // Process a packet received by the server
 
 static void NET_SV_Packet(net_packet_t *packet, net_addr_t *addr)
@@ -1434,7 +1491,7 @@
 
     if (addr != NULL && addr == master_server)
     {
-        NET_Query_MasterResponse(packet);
+        NET_SV_MasterPacket(packet);
         return;
     }