summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/d_main.c13
-rw-r--r--src/net_query.c372
-rw-r--r--src/net_query.h11
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);