shithub: choc

Download patch

ref: 0ff67f43d6d13d9675e305abc652188ea95a88fe
parent: 59d2ed0f2de6b2156142c87d48b0f55fa56b2acf
author: Simon Howard <fraggle@gmail.com>
date: Thu Dec 2 16:34:51 EST 2010

Make multiple query attempts to servers before giving up. Display a
warning if the master server does not respond.

Subversion-branch: /trunk/chocolate-doom
Subversion-revision: 2187

--- a/src/net_query.c
+++ b/src/net_query.c
@@ -36,8 +36,18 @@
 #include "net_structrw.h"
 #include "net_sdl.h"
 
+// DNS address of the Internet master server.
+
 #define MASTER_SERVER_ADDRESS "master.chocolate-doom.org"
 
+// Time to wait for a response before declaring a timeout.
+
+#define QUERY_TIMEOUT_SECS 1
+
+// Number of query attempts to make before giving up on a server.
+
+#define QUERY_MAX_ATTEMPTS 5
+
 typedef enum
 {
     QUERY_TARGET_SERVER,       // Normal server target.
@@ -50,7 +60,7 @@
     QUERY_TARGET_QUEUED,       // Query not yet sent
     QUERY_TARGET_QUERIED,      // Query sent, waiting response
     QUERY_TARGET_RESPONDED,    // Response received
-    QUERY_TARGET_TIMED_OUT
+    QUERY_TARGET_NO_RESPONSE
 } query_target_state_t;
 
 typedef struct
@@ -60,6 +70,7 @@
     net_addr_t *addr;
     net_querydata_t data;
     unsigned int query_time;
+    unsigned int query_attempts;
     boolean printed;
 } query_target_t;
 
@@ -179,6 +190,7 @@
     target->type = QUERY_TARGET_SERVER;
     target->state = QUERY_TARGET_QUEUED;
     target->printed = false;
+    target->query_attempts = 0;
     target->addr = addr;
     ++num_targets;
 
@@ -329,11 +341,19 @@
 
 static void SendOneQuery(void)
 {
+    unsigned int now;
     unsigned int i;
 
+    now = I_GetTimeMS();
+
     for (i = 0; i < num_targets; ++i)
     {
-        if (targets[i].state == QUERY_TARGET_QUEUED)
+        // Not queried yet?
+        // Or last query timed out without a response?
+
+        if (targets[i].state == QUERY_TARGET_QUEUED
+         || (targets[i].state == QUERY_TARGET_QUERIED
+             && now - targets[i].query_time > QUERY_TIMEOUT_SECS * 1000))
         {
             break;
         }
@@ -365,6 +385,7 @@
     //printf("Queried %s\n", NET_AddrToString(targets[i].addr));
     targets[i].state = QUERY_TARGET_QUERIED;
     targets[i].query_time = I_GetTimeMS();
+    ++targets[i].query_attempts;
 }
 
 // Time out servers that have been queried and not responded.
@@ -378,10 +399,15 @@
 
     for (i = 0; i < num_targets; ++i)
     {
+        // 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.
+
         if (targets[i].state == QUERY_TARGET_QUERIED
-         && now - targets[i].query_time > 5000)
+         && targets[i].query_attempts >= QUERY_MAX_ATTEMPTS
+         && now - targets[i].query_time > QUERY_TIMEOUT_SECS * 1000)
         {
-            targets[i].state = QUERY_TARGET_TIMED_OUT;
+            targets[i].state = QUERY_TARGET_NO_RESPONSE;
         }
     }
 }
@@ -395,7 +421,7 @@
     for (i = 0; i < num_targets; ++i)
     {
         if (targets[i].state != QUERY_TARGET_RESPONDED
-         && targets[i].state != QUERY_TARGET_TIMED_OUT)
+         && targets[i].state != QUERY_TARGET_NO_RESPONSE)
         {
             return false;
         }
@@ -432,7 +458,7 @@
 
         // Don't thrash the CPU
 
-        I_Sleep(100);
+        I_Sleep(50);
 
         CheckTargetTimeouts();
     }
@@ -598,6 +624,14 @@
     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();
 }