From 22a8e37dbede0d879f15252830b93234a7483fb3 Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Sat, 17 Sep 2011 13:44:58 +0000 Subject: Fix ping calculation with LAN search. Subversion-branch: /trunk/chocolate-doom Subversion-revision: 2378 --- src/net_query.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/net_query.c b/src/net_query.c index 2797ea2e..24af1863 100644 --- a/src/net_query.c +++ b/src/net_query.c @@ -242,10 +242,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) { -- cgit v1.2.3 From 7fc842b93009cd594961f71c84dc3fe23a55b6b8 Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Sat, 17 Sep 2011 15:43:25 +0000 Subject: Refactor query code so that it is possible to query by polling, rather than blocking on a query function. Subversion-branch: /trunk/chocolate-doom Subversion-revision: 2379 --- src/d_main.c | 8 +- src/net_query.c | 242 +++++++++++++++++++++++++++++++++----------------------- src/net_query.h | 10 ++- 3 files changed, 151 insertions(+), 109 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index c6979712..613db3c1 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -890,9 +890,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); } @@ -920,9 +918,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 24af1863..0e35bccf 100644 --- a/src/net_query.c +++ b/src/net_query.c @@ -85,6 +85,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. @@ -376,6 +377,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? @@ -414,8 +422,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. @@ -429,6 +439,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. @@ -438,6 +454,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"); + } } } } @@ -460,6 +482,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) @@ -470,27 +512,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(); } } @@ -554,87 +584,21 @@ static int GetNumResponses(void) 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) -{ - 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) +int NET_StartMasterQuery(void) { net_addr_t *master; query_target_t *target; @@ -653,19 +617,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; @@ -721,10 +677,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. @@ -753,3 +709,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); -- cgit v1.2.3 From e7e8858adbf310c319dcca1a13667984d22826f6 Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Sat, 17 Sep 2011 15:55:08 +0000 Subject: Change query loop to sleep for 1ms rather than 50ms intervals, so that precision is not lost in ping times. Subversion-branch: /trunk/chocolate-doom Subversion-revision: 2380 --- src/net_query.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/net_query.c b/src/net_query.c index 0e35bccf..0262791b 100644 --- a/src/net_query.c +++ b/src/net_query.c @@ -520,7 +520,7 @@ static void NET_Query_QueryLoop(net_query_callback_t callback, void *user_data) { // Don't thrash the CPU - I_Sleep(50); + I_Sleep(1); } } -- cgit v1.2.3