shithub: choc

Download patch

ref: 1f170ff1ce5cf9b9b55b3a09c0840e237432477c
parent: 1981657e650bb78821a1e0829285ad2b1415a68d
parent: e7e8858adbf310c319dcca1a13667984d22826f6
author: Simon Howard <fraggle@gmail.com>
date: Sat Sep 17 12:08:08 EDT 2011

Merge from trunk.

Subversion-branch: /branches/v2-branch
Subversion-revision: 2381

--- a/src/doom/d_main.c
+++ b/src/doom/d_main.c
@@ -1151,9 +1151,7 @@
 
     if (M_CheckParm("-search"))
     {
-        printf("\nSearching for servers on Internet ...\n");
-        p = NET_MasterQuery(NET_QueryPrintCallback, NULL);
-        printf("\n%i server(s) found.\n", p);
+        NET_MasterQuery();
         exit(0);
     }
 
@@ -1181,9 +1179,7 @@
 
     if (M_CheckParm("-localsearch"))
     {
-        printf("\nSearching for servers on local LAN ...\n");
-        p = NET_LANQuery(NET_QueryPrintCallback, NULL);
-        printf("\n%i server(s) found.\n", p);
+        NET_LANQuery();
         exit(0);
     }
 
--- a/src/net_query.c
+++ b/src/net_query.c
@@ -25,6 +25,7 @@
 #include <stdio.h>
 #include <stdarg.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include "i_system.h"
 #include "i_timer.h"
@@ -86,6 +87,7 @@
 
 static boolean query_loop_running = false;
 static boolean printed_header = false;
+static int last_query_time = 0;
 
 // Resolve the master server address.
 
@@ -243,11 +245,36 @@
         return;
     }
 
-    // Find the target that responded, or potentially add a new target
-    // if it was not already known (for LAN broadcast search)
+    // Find the target that responded.
 
-    target = GetTargetForAddr(addr, true);
+    target = GetTargetForAddr(addr, false);
 
+    // If the target is not found, it may be because we are doing
+    // a LAN broadcast search, in which case we need to create a
+    // target for the new responder.
+
+    if (target == NULL)
+    {
+        query_target_t *broadcast_target;
+
+        broadcast_target = GetTargetForAddr(NULL, false);
+
+        // Not in broadcast mode, unexpected response that came out
+        // of nowhere. Ignore.
+
+        if (broadcast_target == NULL
+         || broadcast_target->state != QUERY_TARGET_QUERIED)
+        {
+            return;
+        }
+
+        // Create new target.
+
+        target = GetTargetForAddr(addr, true);
+        target->state = QUERY_TARGET_QUERIED;
+        target->query_time = broadcast_target->query_time;
+    }
+
     if (target->state != QUERY_TARGET_RESPONDED)
     {
         target->state = QUERY_TARGET_RESPONDED;
@@ -352,6 +379,13 @@
 
     now = I_GetTimeMS();
 
+    // Rate limit - only send one query every 50ms.
+
+    if (now - last_query_time < 50)
+    {
+        return;
+    }
+
     for (i = 0; i < num_targets; ++i)
     {
         // Not queried yet?
@@ -390,8 +424,10 @@
 
     //printf("Queried %s\n", NET_AddrToString(targets[i].addr));
     targets[i].state = QUERY_TARGET_QUERIED;
-    targets[i].query_time = I_GetTimeMS();
+    targets[i].query_time = now;
     ++targets[i].query_attempts;
+
+    last_query_time = now;
 }
 
 // Time out servers that have been queried and not responded.
@@ -405,6 +441,12 @@
 
     for (i = 0; i < num_targets; ++i)
     {
+        /*
+        printf("target %i: state %i, queries %i, query time %i\n",
+               i, targets[i].state, targets[i].query_attempts,
+               now - targets[i].query_time);
+        */
+
         // We declare a target to be "no response" when we've sent
         // multiple query packets to it (QUERY_MAX_ATTEMPTS) and
         // received no response to any of them.
@@ -414,6 +456,12 @@
          && now - targets[i].query_time > QUERY_TIMEOUT_SECS * 1000)
         {
             targets[i].state = QUERY_TARGET_NO_RESPONSE;
+
+            if (targets[i].type == QUERY_TARGET_MASTER)
+            {
+                fprintf(stderr, "NET_MasterQuery: no response "
+                                "from master server.\n");
+            }
         }
     }
 }
@@ -436,6 +484,26 @@
     return true;
 }
 
+// Polling function, invoked periodically to send queries and
+// interpret new responses received from remote servers.
+// Returns zero when the query sequence has completed and all targets
+// have returned responses or timed out.
+
+int NET_Query_Poll(net_query_callback_t callback, void *user_data)
+{
+    CheckTargetTimeouts();
+
+    // Send a query.  This will only send a single query at once.
+
+    SendOneQuery();
+
+    // Check for a response
+
+    NET_Query_GetResponse(callback, user_data);
+
+    return !AllTargetsDone();
+}
+
 // Stop the query loop
 
 static void NET_Query_ExitLoop(void)
@@ -446,27 +514,15 @@
 // Loop waiting for responses.
 // The specified callback is invoked when a new server responds.
 
-static void NET_Query_QueryLoop(net_query_callback_t callback,
-                                void *user_data)
+static void NET_Query_QueryLoop(net_query_callback_t callback, void *user_data)
 {
     query_loop_running = true;
 
-    while (query_loop_running && !AllTargetsDone())
+    while (query_loop_running && NET_Query_Poll(callback, user_data))
     {
-        // Send a query.  This will only send a single query.
-        // Because of the delay below, this is therefore rate limited.
-
-        SendOneQuery();
-
-        // Check for a response
-
-        NET_Query_GetResponse(callback, user_data);
-
         // Don't thrash the CPU
 
-        I_Sleep(50);
-
-        CheckTargetTimeouts();
+        I_Sleep(1);
     }
 }
 
@@ -530,88 +586,22 @@
     return result;
 }
 
-void NET_QueryAddress(char *addr_str)
+int NET_StartLANQuery(void)
 {
-    net_addr_t *addr;
     query_target_t *target;
 
     NET_Query_Init();
 
-    addr = NET_ResolveAddress(query_context, addr_str);
-
-    if (addr == NULL)
-    {
-        I_Error("NET_QueryAddress: Host '%s' not found!", addr_str);
-    }
-
-    // Add the address to the list of targets.
-
-    target = GetTargetForAddr(addr, true);
-
-    printf("\nQuerying '%s'...\n", addr_str);
-
-    // Run query loop.
-
-    NET_Query_QueryLoop(NET_Query_ExitCallback, NULL);
-
-    // Check if the target responded.
-
-    if (target->state == QUERY_TARGET_RESPONDED)
-    {
-        NET_QueryPrintCallback(addr, &target->data, target->ping_time, NULL);
-    }
-    else
-    {
-        I_Error("No response from '%s'", addr_str);
-    }
-}
-
-net_addr_t *NET_FindLANServer(void)
-{
-    query_target_t *target;
-    query_target_t *responder;
-
-    NET_Query_Init();
-
     // Add a broadcast target to the list.
 
     target = GetTargetForAddr(NULL, true);
     target->type = QUERY_TARGET_BROADCAST;
 
-    // Run the query loop, and stop at the first target found.
-
-    NET_Query_QueryLoop(NET_Query_ExitCallback, NULL);
-
-    responder = FindFirstResponder();
-
-    if (responder != NULL)
-    {
-        return responder->addr;
-    }
-    else
-    {
-        return NULL;
-    }
+    return 1;
 }
 
-int NET_LANQuery(net_query_callback_t callback, void *user_data)
+int NET_StartMasterQuery(void)
 {
-    query_target_t *target;
-
-    NET_Query_Init();
-
-    // Add a broadcast target to the list.
-
-    target = GetTargetForAddr(NULL, true);
-    target->type = QUERY_TARGET_BROADCAST;
-
-    NET_Query_QueryLoop(callback, user_data);
-
-    return GetNumResponses();
-}
-
-int NET_MasterQuery(net_query_callback_t callback, void *user_data)
-{
     net_addr_t *master;
     query_target_t *target;
 
@@ -629,19 +619,11 @@
     target = GetTargetForAddr(master, true);
     target->type = QUERY_TARGET_MASTER;
 
-    NET_Query_QueryLoop(callback, user_data);
-
-    // Check that we got a response from the master, and display
-    // a warning if we didn't.
-
-    if (target->state == QUERY_TARGET_NO_RESPONSE)
-    {
-        fprintf(stderr, "NET_MasterQuery: no response from master server.\n");
-    }
-
-    return GetNumResponses();
+    return 1;
 }
 
+// -----------------------------------------------------------------------
+
 static void formatted_printf(int wide, char *s, ...)
 {
     va_list args;
@@ -697,10 +679,10 @@
 
 // Callback function that just prints information in a table.
 
-void NET_QueryPrintCallback(net_addr_t *addr,
-                            net_querydata_t *data,
-                            unsigned int ping_time,
-                            void *user_data)
+static void NET_QueryPrintCallback(net_addr_t *addr,
+                                   net_querydata_t *data,
+                                   unsigned int ping_time,
+                                   void *user_data)
 {
     // If this is the first server, print the header.
 
@@ -727,5 +709,93 @@
     }
 
     NET_SafePuts(data->description);
+}
+
+void NET_LANQuery(void)
+{
+    if (NET_StartLANQuery())
+    {
+        printf("\nSearching for servers on local LAN ...\n");
+
+        NET_Query_QueryLoop(NET_QueryPrintCallback, NULL);
+
+        printf("\n%i server(s) found.\n", GetNumResponses());
+    }
+}
+
+void NET_MasterQuery(void)
+{
+    if (NET_StartMasterQuery())
+    {
+        printf("\nSearching for servers on Internet ...\n");
+
+        NET_Query_QueryLoop(NET_QueryPrintCallback, NULL);
+
+        printf("\n%i server(s) found.\n", GetNumResponses());
+    }
+}
+
+void NET_QueryAddress(char *addr_str)
+{
+    net_addr_t *addr;
+    query_target_t *target;
+
+    NET_Query_Init();
+
+    addr = NET_ResolveAddress(query_context, addr_str);
+
+    if (addr == NULL)
+    {
+        I_Error("NET_QueryAddress: Host '%s' not found!", addr_str);
+    }
+
+    // Add the address to the list of targets.
+
+    target = GetTargetForAddr(addr, true);
+
+    printf("\nQuerying '%s'...\n", addr_str);
+
+    // Run query loop.
+
+    NET_Query_QueryLoop(NET_Query_ExitCallback, NULL);
+
+    // Check if the target responded.
+
+    if (target->state == QUERY_TARGET_RESPONDED)
+    {
+        NET_QueryPrintCallback(addr, &target->data, target->ping_time, NULL);
+    }
+    else
+    {
+        I_Error("No response from '%s'", addr_str);
+    }
+}
+
+net_addr_t *NET_FindLANServer(void)
+{
+    query_target_t *target;
+    query_target_t *responder;
+
+    NET_Query_Init();
+
+    // Add a broadcast target to the list.
+
+    target = GetTargetForAddr(NULL, true);
+    target->type = QUERY_TARGET_BROADCAST;
+
+    // Run the query loop, and stop at the first target found.
+
+    NET_Query_QueryLoop(NET_Query_ExitCallback, NULL);
+
+    responder = FindFirstResponder();
+
+    if (responder != NULL)
+    {
+        return responder->addr;
+    }
+    else
+    {
+        return NULL;
+    }
 }
 
--- a/src/net_query.h
+++ b/src/net_query.h
@@ -32,13 +32,15 @@
                                      unsigned int ping_time,
                                      void *user_data);
 
-extern int NET_LANQuery(net_query_callback_t callback, void *user_data);
-extern int NET_MasterQuery(net_query_callback_t callback, void *user_data);
+extern int NET_StartLANQuery(void);
+extern int NET_StartMasterQuery(void);
+
+extern void NET_LANQuery(void);
+extern void NET_MasterQuery(void);
 extern void NET_QueryAddress(char *addr);
 extern net_addr_t *NET_FindLANServer(void);
 
-extern void NET_QueryPrintCallback(net_addr_t *addr, net_querydata_t *data,
-                                   unsigned int ping_time, void *user_data);
+extern int NET_Query_Poll(net_query_callback_t callback, void *user_data);
 
 extern net_addr_t *NET_Query_ResolveMaster(net_context_t *context);
 extern void NET_Query_AddToMaster(net_addr_t *master_addr);