summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/doom/d_main.c8
-rw-r--r--src/net_query.c276
-rw-r--r--src/net_query.h10
3 files changed, 181 insertions, 113 deletions
diff --git a/src/doom/d_main.c b/src/doom/d_main.c
index 0e5324b4..b425d11a 100644
--- a/src/doom/d_main.c
+++ b/src/doom/d_main.c
@@ -1151,9 +1151,7 @@ void D_DoomMain (void)
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 @@ void D_DoomMain (void)
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);
}
diff --git a/src/net_query.c b/src/net_query.c
index ae56dea6..06391a14 100644
--- 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 int num_targets;
static boolean query_loop_running = false;
static boolean printed_header = false;
+static int last_query_time = 0;
// Resolve the master server address.
@@ -243,10 +245,35 @@ static void NET_Query_ParseResponse(net_addr_t *addr, net_packet_t *packet,
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)
{
@@ -352,6 +379,13 @@ static void SendOneQuery(void)
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 @@ static void SendOneQuery(void)
//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 @@ static void CheckTargetTimeouts(void)
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 @@ static void CheckTargetTimeouts(void)
&& 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 @@ static boolean AllTargetsDone(void)
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 @@ static void NET_Query_ExitLoop(void)
// 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,71 +586,7 @@ static int GetNumResponses(void)
return result;
}
-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;
- }
-}
-
-int NET_LANQuery(net_query_callback_t callback, void *user_data)
+int NET_StartLANQuery(void)
{
query_target_t *target;
@@ -605,12 +597,10 @@ int NET_LANQuery(net_query_callback_t callback, void *user_data)
target = GetTargetForAddr(NULL, true);
target->type = QUERY_TARGET_BROADCAST;
- NET_Query_QueryLoop(callback, user_data);
-
- return GetNumResponses();
+ return 1;
}
-int NET_MasterQuery(net_query_callback_t callback, void *user_data)
+int NET_StartMasterQuery(void)
{
net_addr_t *master;
query_target_t *target;
@@ -629,19 +619,11 @@ int NET_MasterQuery(net_query_callback_t callback, void *user_data)
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 @@ static void PrintHeader(void)
// 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.
@@ -729,3 +711,91 @@ void NET_QueryPrintCallback(net_addr_t *addr,
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;
+ }
+}
+
diff --git a/src/net_query.h b/src/net_query.h
index 01e059cb..5a30bd0d 100644
--- a/src/net_query.h
+++ b/src/net_query.h
@@ -32,13 +32,15 @@ typedef void (*net_query_callback_t)(net_addr_t *addr,
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);