diff options
-rw-r--r-- | src/doom/d_main.c | 8 | ||||
-rw-r--r-- | src/net_query.c | 276 | ||||
-rw-r--r-- | src/net_query.h | 10 |
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); |