diff options
author | Simon Howard | 2010-12-02 20:11:24 +0000 |
---|---|---|
committer | Simon Howard | 2010-12-02 20:11:24 +0000 |
commit | b11030cbfee0d4d4a46673001992e94abc146c8c (patch) | |
tree | 3d0f9f026777efc7b763acf521fe3d3fc6e38021 | |
parent | bfbffcf197a5d78e90d463945d12c84d0f7deadf (diff) | |
download | chocolate-doom-b11030cbfee0d4d4a46673001992e94abc146c8c.tar.gz chocolate-doom-b11030cbfee0d4d4a46673001992e94abc146c8c.tar.bz2 chocolate-doom-b11030cbfee0d4d4a46673001992e94abc146c8c.zip |
More refactoring of querying code, to not be specific to the purpose of
printing out a list.
Subversion-branch: /trunk/chocolate-doom
Subversion-revision: 2184
-rw-r--r-- | src/d_main.c | 13 | ||||
-rw-r--r-- | src/net_query.c | 372 | ||||
-rw-r--r-- | src/net_query.h | 11 |
3 files changed, 218 insertions, 178 deletions
diff --git a/src/d_main.c b/src/d_main.c index 22fdb142..c0804b5d 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -852,7 +852,10 @@ void D_DoomMain (void) if (M_CheckParm("-masterquery")) { - NET_MasterQuery(); + printf("\nSearching for servers on Internet ...\n\n"); + p = NET_MasterQuery(NET_QueryPrintCallback, NULL); + printf("%i server(s) found.\n", p); + exit(0); } //! @@ -868,6 +871,7 @@ void D_DoomMain (void) if (p > 0) { NET_QueryAddress(myargv[p+1]); + exit(0); } //! @@ -877,7 +881,12 @@ void D_DoomMain (void) // if (M_CheckParm("-search")) - NET_LANQuery(); + { + printf("\nSearching for servers on local LAN ...\n"); + p = NET_LANQuery(NET_QueryPrintCallback, NULL); + printf("\n%i server(s) found.\n", p); + exit(0); + } #endif diff --git a/src/net_query.c b/src/net_query.c index 681411c2..3dee1b00 100644 --- a/src/net_query.c +++ b/src/net_query.c @@ -71,6 +71,7 @@ static net_context_t *query_context; static query_target_t *targets; static int num_targets; +static boolean query_loop_running = false; static boolean printed_header = false; // Resolve the master server address. @@ -205,7 +206,9 @@ static void NET_Query_SendQuery(net_addr_t *addr) NET_FreePacket(request); } -static void NET_Query_ParseResponse(net_addr_t *addr, net_packet_t *packet) +static void NET_Query_ParseResponse(net_addr_t *addr, net_packet_t *packet, + net_query_callback_t callback, + void *user_data) { unsigned int packet_type; net_querydata_t querydata; @@ -231,8 +234,15 @@ static void NET_Query_ParseResponse(net_addr_t *addr, net_packet_t *packet) target = GetTargetForAddr(addr, true); - target->state = QUERY_TARGET_RESPONDED; - memcpy(&target->data, &querydata, sizeof(net_querydata_t)); + if (target->state != QUERY_TARGET_RESPONDED) + { + target->state = QUERY_TARGET_RESPONDED; + memcpy(&target->data, &querydata, sizeof(net_querydata_t)); + + // Invoke callback to signal that we have a new address. + + callback(addr, &target->data, user_data); + } } // Parse a response packet from the master server. @@ -282,7 +292,9 @@ static void NET_Query_ParseMasterResponse(net_addr_t *master_addr, target->state = QUERY_TARGET_RESPONDED; } -static void NET_Query_ParsePacket(net_addr_t *addr, net_packet_t *packet) +static void NET_Query_ParsePacket(net_addr_t *addr, net_packet_t *packet, + net_query_callback_t callback, + void *user_data) { query_target_t *target; @@ -296,18 +308,19 @@ static void NET_Query_ParsePacket(net_addr_t *addr, net_packet_t *packet) } else { - NET_Query_ParseResponse(addr, packet); + NET_Query_ParseResponse(addr, packet, callback, user_data); } } -static void NET_Query_GetResponse(void) +static void NET_Query_GetResponse(net_query_callback_t callback, + void *user_data) { net_addr_t *addr; net_packet_t *packet; if (NET_RecvPacket(query_context, &addr, &packet)) { - NET_Query_ParsePacket(addr, packet); + NET_Query_ParsePacket(addr, packet, callback, user_data); NET_FreePacket(packet); } } @@ -354,25 +367,6 @@ static void SendOneQuery(void) targets[i].query_time = I_GetTimeMS(); } -// Search the targets list and find a target that has responded. -// If none have responded yet, returns NULL. - -static query_target_t *FindFirstResponder(void) -{ - unsigned int i; - - for (i = 0; i < num_targets; ++i) - { - if (targets[i].type == QUERY_TARGET_SERVER - && targets[i].state == QUERY_TARGET_RESPONDED) - { - return &targets[i]; - } - } - - return NULL; -} - // Time out servers that have been queried and not responded. static void CheckTargetTimeouts(void) @@ -410,197 +404,165 @@ static boolean AllTargetsDone(void) return true; } -static void formatted_printf(int wide, char *s, ...) -{ - va_list args; - int i; - - va_start(args, s); - i = vprintf(s, args); - va_end(args); +// Stop the query loop - while (i < wide) - { - putchar(' '); - ++i; - } +static void NET_Query_ExitLoop(void) +{ + query_loop_running = false; } -static char *GameDescription(GameMode_t mode, GameMission_t mission) +// 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) { - switch (mode) + query_loop_running = true; + + while (query_loop_running && !AllTargetsDone()) { - case shareware: - return "shareware"; - case registered: - return "registered"; - case retail: - return "ultimate"; - case commercial: - if (mission == doom2) - return "doom2"; - else if (mission == pack_tnt) - return "tnt"; - else if (mission == pack_plut) - return "plutonia"; - default: - return "unknown"; - } -} + // Send a query. This will only send a single query. + // Because of the delay below, this is therefore rate limited. -static void PrintHeader(void) -{ - int i; + SendOneQuery(); - formatted_printf(18, "Address"); - formatted_printf(8, "Players"); - puts("Description"); + // Check for a response - for (i=0; i<70; ++i) - putchar('='); - putchar('\n'); + NET_Query_GetResponse(callback, user_data); + + // Don't thrash the CPU + + I_Sleep(100); + + CheckTargetTimeouts(); + } } -static void PrintResponse(query_target_t *target) +void NET_Query_Init(void) { - formatted_printf(18, "%s: ", NET_AddrToString(target->addr)); - formatted_printf(8, "%i/%i", target->data.num_players, - target->data.max_players); + query_context = NET_NewContext(); + NET_AddModule(query_context, &net_sdl_module); + net_sdl_module.InitClient(); - if (target->data.gamemode != indetermined) - { - printf("(%s) ", GameDescription(target->data.gamemode, - target->data.gamemission)); - } + targets = NULL; + num_targets = 0; - if (target->data.server_state) - { - printf("(game running) "); - } + printed_header = false; +} + +// Callback that exits the query loop when the first server is found. - NET_SafePuts(target->data.description); +static void NET_Query_ExitCallback(net_addr_t *addr, net_querydata_t *data, + void *user_data) +{ + NET_Query_ExitLoop(); } -// Check for printing information about servers that have responded. +// Search the targets list and find a target that has responded. +// If none have responded, returns NULL. -static void CheckPrintOutput(void) +static query_target_t *FindFirstResponder(void) { unsigned int i; for (i = 0; i < num_targets; ++i) { if (targets[i].type == QUERY_TARGET_SERVER - && targets[i].state == QUERY_TARGET_RESPONDED - && !targets[i].printed) + && targets[i].state == QUERY_TARGET_RESPONDED) { - if (!printed_header) - { - PrintHeader(); - printed_header = true; - } - - PrintResponse(&targets[i]); - targets[i].printed = true; + return &targets[i]; } } + + return NULL; } -// Loop waiting for responses. +// Return a count of the number of responses. -static net_addr_t *NET_Query_QueryLoop(boolean find_first, - boolean silent) +static int GetNumResponses(void) { - query_target_t *responder; - int start_time; - int last_send_time; + unsigned int i; + int result; - last_send_time = -1; - start_time = I_GetTimeMS(); + result = 0; - while (!AllTargetsDone()) + for (i = 0; i < num_targets; ++i) { - // Send a query. This will only send a single query. - // Because of the delay below, this is therefore rate limited. + if (targets[i].type == QUERY_TARGET_SERVER + && targets[i].state == QUERY_TARGET_RESPONDED) + { + ++result; + } + } - SendOneQuery(); + return result; +} - // Check for a response +void NET_QueryAddress(char *addr_str) +{ + net_addr_t *addr; + query_target_t *target; - NET_Query_GetResponse(); + NET_Query_Init(); - // Output the responses + addr = NET_ResolveAddress(query_context, addr_str); - if (!silent) - { - CheckPrintOutput(); - } + if (addr == NULL) + { + I_Error("NET_QueryAddress: Host '%s' not found!", addr_str); + } - // Found a response? + // Add the address to the list of targets. - if (find_first && FindFirstResponder()) - { - break; - } + target = GetTargetForAddr(addr, true); - // Don't thrash the CPU + printf("\nQuerying '%s'...\n", addr_str); - I_Sleep(100); + // Run query loop. - CheckTargetTimeouts(); - } + NET_Query_QueryLoop(NET_Query_ExitCallback, NULL); - responder = FindFirstResponder(); + // Check if the target responded. - if (responder != NULL) + if (target->state == QUERY_TARGET_RESPONDED) { - return responder->addr; + NET_QueryPrintCallback(addr, &target->data, NULL); } else { - return NULL; + I_Error("No response from '%s'", addr_str); } } -void NET_Query_Init(void) -{ - query_context = NET_NewContext(); - NET_AddModule(query_context, &net_sdl_module); - net_sdl_module.InitClient(); - - targets = NULL; - num_targets = 0; - - printed_header = false; -} - -void NET_QueryAddress(char *addr) +net_addr_t *NET_FindLANServer(void) { - net_addr_t *net_addr; + query_target_t *target; + query_target_t *responder; NET_Query_Init(); - net_addr = NET_ResolveAddress(query_context, addr); + // Add a broadcast target to the list. - if (net_addr == NULL) - { - I_Error("NET_QueryAddress: Host '%s' not found!", addr); - } + target = GetTargetForAddr(NULL, true); + target->type = QUERY_TARGET_BROADCAST; - // Add the address to the list of targets. + // Run the query loop, and stop at the first target found. - GetTargetForAddr(net_addr, true); + NET_Query_QueryLoop(NET_Query_ExitCallback, NULL); - printf("\nQuerying '%s'...\n\n", addr); + responder = FindFirstResponder(); - if (!NET_Query_QueryLoop(true, false)) + if (responder != NULL) { - I_Error("No response from '%s'", addr); + return responder->addr; + } + else + { + return NULL; } - - exit(0); } -net_addr_t *NET_FindLANServer(void) +int NET_LANQuery(net_query_callback_t callback, void *user_data) { query_target_t *target; @@ -611,54 +573,116 @@ net_addr_t *NET_FindLANServer(void) target = GetTargetForAddr(NULL, true); target->type = QUERY_TARGET_BROADCAST; - return NET_Query_QueryLoop(true, true); + NET_Query_QueryLoop(callback, user_data); + + return GetNumResponses(); } -void NET_LANQuery(void) +int NET_MasterQuery(net_query_callback_t callback, void *user_data) { + net_addr_t *master; query_target_t *target; NET_Query_Init(); - printf("\nSearching for servers on local LAN ...\n\n"); + // Resolve master address and add to targets list. - // Add a broadcast target to the list. + master = NET_Query_ResolveMaster(query_context); - target = GetTargetForAddr(NULL, true); - target->type = QUERY_TARGET_BROADCAST; + if (master == NULL) + { + return 0; + } + + target = GetTargetForAddr(master, true); + target->type = QUERY_TARGET_MASTER; - if (!NET_Query_QueryLoop(false, false)) + NET_Query_QueryLoop(callback, user_data); + + return GetNumResponses(); +} + +static void formatted_printf(int wide, char *s, ...) +{ + va_list args; + int i; + + va_start(args, s); + i = vprintf(s, args); + va_end(args); + + while (i < wide) { - I_Error("No servers found"); + putchar(' '); + ++i; } +} - exit(0); +static char *GameDescription(GameMode_t mode, GameMission_t mission) +{ + switch (mode) + { + case shareware: + return "shareware"; + case registered: + return "registered"; + case retail: + return "ultimate"; + case commercial: + if (mission == doom2) + return "doom2"; + else if (mission == pack_tnt) + return "tnt"; + else if (mission == pack_plut) + return "plutonia"; + default: + return "unknown"; + } } -void NET_MasterQuery(void) +static void PrintHeader(void) { - net_addr_t *master; - query_target_t *target; + int i; - NET_Query_Init(); + putchar('\n'); + formatted_printf(18, "Address"); + formatted_printf(8, "Players"); + puts("Description"); - printf("\nSearching for servers on Internet ...\n\n"); + for (i=0; i<70; ++i) + putchar('='); + putchar('\n'); +} - // Resolve master address and add to targets list. +// Callback function that just prints information in a table. - master = NET_Query_ResolveMaster(query_context); +void NET_QueryPrintCallback(net_addr_t *addr, + net_querydata_t *data, + void *user_data) +{ + // If this is the first server, print the header. - if (master == NULL) + if (!printed_header) { - I_Error("Failed to resolve master server address"); + PrintHeader(); + printed_header = true; } - target = GetTargetForAddr(master, true); - target->type = QUERY_TARGET_MASTER; + formatted_printf(18, "%s: ", NET_AddrToString(addr)); + formatted_printf(8, "%i/%i", data->num_players, + data->max_players); - if (!NET_Query_QueryLoop(false, false)) + if (data->gamemode != indetermined) { - I_Error("No servers found"); + printf("(%s) ", GameDescription(data->gamemode, + data->gamemission)); } + + if (data->server_state) + { + printf("(game running) "); + } + + NET_SafePuts(data->description); } diff --git a/src/net_query.h b/src/net_query.h index 21c89ecb..98931593 100644 --- a/src/net_query.h +++ b/src/net_query.h @@ -27,10 +27,17 @@ #include "net_defs.h" +typedef void (*net_query_callback_t)(net_addr_t *addr, + net_querydata_t *querydata, + 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 void NET_QueryAddress(char *addr); -extern void NET_LANQuery(void); extern net_addr_t *NET_FindLANServer(void); -extern void NET_MasterQuery(void); + +extern void NET_QueryPrintCallback(net_addr_t *addr, net_querydata_t *data, + void *user_data); extern net_addr_t *NET_Query_ResolveMaster(net_context_t *context); extern void NET_Query_AddToMaster(net_addr_t *master_addr); |