From d5f0ddc20b192cf1f17b27347dd467cddf493a6d Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Thu, 6 Apr 2006 20:48:35 +0000 Subject: Add the ability to query the current state of servers, and '-query' command line option to do so. Subversion-branch: /trunk/chocolate-doom Subversion-revision: 464 --- src/d_main.c | 15 ++++- src/net_defs.h | 4 +- src/net_query.c | 197 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/net_query.h | 33 ++++++++++ src/net_server.c | 44 ++++++++++++- 5 files changed, 289 insertions(+), 4 deletions(-) create mode 100644 src/net_query.c create mode 100644 src/net_query.h diff --git a/src/d_main.c b/src/d_main.c index 78bd7c37..6a60edc5 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: d_main.c 455 2006-03-30 19:08:37Z fraggle $ +// $Id: d_main.c 464 2006-04-06 20:48:35Z fraggle $ // // Copyright(C) 1993-1996 Id Software, Inc. // Copyright(C) 2005 Simon Howard @@ -184,7 +184,7 @@ //----------------------------------------------------------------------------- -static const char rcsid[] = "$Id: d_main.c 455 2006-03-30 19:08:37Z fraggle $"; +static const char rcsid[] = "$Id: d_main.c 464 2006-04-06 20:48:35Z fraggle $"; #define BGCOLOR 7 #define FGCOLOR 8 @@ -240,6 +240,7 @@ static const char rcsid[] = "$Id: d_main.c 455 2006-03-30 19:08:37Z fraggle $"; #include "am_map.h" #include "net_client.h" #include "net_dedicated.h" +#include "net_query.h" #include "p_setup.h" #include "r_local.h" @@ -1358,6 +1359,16 @@ void D_DoomMain (void) // Never returns } + // Query network servers? + + p = M_CheckParm("-query"); + + if (p > 0) + { + NET_QueryAddress(myargv[p+1]); + } + + #ifdef FEATURE_DEHACKED printf("DEH_Init: Init Dehacked support.\n"); DEH_Init(); diff --git a/src/net_defs.h b/src/net_defs.h index e9db14fd..055bba7d 100644 --- a/src/net_defs.h +++ b/src/net_defs.h @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: net_defs.h 462 2006-04-06 19:31:45Z fraggle $ +// $Id: net_defs.h 464 2006-04-06 20:48:35Z fraggle $ // // Copyright(C) 2005 Simon Howard // @@ -163,6 +163,8 @@ typedef enum NET_PACKET_TYPE_RELIABLE_ACK, NET_PACKET_TYPE_GAMEDATA_RESEND, NET_PACKET_TYPE_CONSOLE_MESSAGE, + NET_PACKET_TYPE_QUERY, + NET_PACKET_TYPE_QUERY_RESPONSE, } net_packet_type_t; typedef struct diff --git a/src/net_query.c b/src/net_query.c new file mode 100644 index 00000000..b6a604f8 --- /dev/null +++ b/src/net_query.c @@ -0,0 +1,197 @@ +// Emacs style mode select -*- C++ -*- +//----------------------------------------------------------------------------- +// +// $Id: net_client.c 462 2006-04-06 19:31:45Z fraggle $ +// +// Copyright(C) 2005 Simon Howard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. +// +// DESCRIPTION: +// Querying servers to find their current status. +// + +#include +#include + +#include "i_system.h" +#include "i_timer.h" + +#include "net_common.h" +#include "net_defs.h" +#include "net_io.h" +#include "net_packet.h" +#include "net_query.h" +#include "net_sdl.h" + +static net_context_t *query_context; +static int num_responses; + +static void NET_Query_SendQuery(net_addr_t *addr) +{ + net_packet_t *request; + + request = NET_NewPacket(10); + NET_WriteInt16(request, NET_PACKET_TYPE_QUERY); + NET_SendPacket(addr, request); + NET_FreePacket(request); +} + +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) + { + putchar(' '); + ++i; + } +} + +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"; + } +} + +static void NET_Query_ParsePacket(net_addr_t *addr, net_packet_t *packet) +{ + unsigned int packet_type; + char *server_version; + unsigned int in_game; + unsigned int num_players, max_players; + unsigned int servermode, servermission; + char *server_description; + int i; + + if (!NET_ReadInt16(packet, &packet_type) + || !(server_version = NET_ReadString(packet)) + || !NET_ReadInt8(packet, &in_game) + || !NET_ReadInt8(packet, &num_players) + || !NET_ReadInt8(packet, &max_players) + || !NET_ReadInt8(packet, &servermode) + || !NET_ReadInt8(packet, &servermission) + || !(server_description = NET_ReadString(packet))) + { + return; + } + + if (num_responses <= 0) + { + // If this is the first response, print the table header + + formatted_printf(18, "Address"); + formatted_printf(8, "Players"); + puts("Description"); + + for (i=0; i<70; ++i) + putchar('='); + putchar('\n'); + } + + formatted_printf(18, "%s: ", NET_AddrToString(addr)); + formatted_printf(8, "%i/%i", num_players, max_players); + + if (servermode != indetermined) + { + printf("(%s) ", GameDescription(servermode, servermission)); + } + + if (in_game) + { + printf("(game running) "); + } + + NET_SafePuts(server_description); + + ++num_responses; +} + +static void NET_Query_GetResponse(void) +{ + net_addr_t *addr; + net_packet_t *packet; + + if (NET_RecvPacket(query_context, &addr, &packet)) + { + NET_Query_ParsePacket(addr, packet); + } +} + +void NET_Query_Init(void) +{ + query_context = NET_NewContext(); + NET_AddModule(query_context, &net_sdl_module); + net_sdl_module.InitClient(); + + num_responses = 0; +} + +void NET_QueryAddress(char *addr) +{ + int start_time; + net_addr_t *net_addr; + + NET_Query_Init(); + + net_addr = NET_ResolveAddress(query_context, addr); + + if (net_addr == NULL) + { + I_Error("NET_QueryAddress: Host '%s' not found!", addr); + } + + printf("\nQuerying '%s'...\n\n", addr); + + NET_Query_SendQuery(net_addr); + + start_time = I_GetTimeMS(); + + while (num_responses <= 0 && I_GetTimeMS() < start_time + 5000) + { + NET_Query_GetResponse(); + I_Sleep(100); + } + + if (num_responses <= 0) + { + I_Error("No response from '%s'", addr); + } + + exit(0); +} + diff --git a/src/net_query.h b/src/net_query.h new file mode 100644 index 00000000..f2b6cbc0 --- /dev/null +++ b/src/net_query.h @@ -0,0 +1,33 @@ +// Emacs style mode select -*- C++ -*- +//----------------------------------------------------------------------------- +// +// $Id: net_client.c 462 2006-04-06 19:31:45Z fraggle $ +// +// Copyright(C) 2005 Simon Howard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA. +// +// DESCRIPTION: +// Querying servers to find their current status. +// + +#ifndef NET_QUERY_H +#define NET_QUERY_H + +extern void NET_QueryAddress(char *addr); + +#endif /* #ifndef NET_QUERY_H */ + diff --git a/src/net_server.c b/src/net_server.c index 3a01f3b9..c57ef61a 100644 --- a/src/net_server.c +++ b/src/net_server.c @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// $Id: net_server.c 461 2006-04-06 17:53:43Z fraggle $ +// $Id: net_server.c 464 2006-04-06 20:48:35Z fraggle $ // // Copyright(C) 2005 Simon Howard // @@ -1058,6 +1058,42 @@ static void NET_SV_ParseResendRequest(net_packet_t *packet, net_client_t *client NET_SV_SendTics(client, start, last); } +// Send a response back to the client + +void NET_SV_SendQueryResponse(net_addr_t *addr) +{ + net_packet_t *reply; + + reply = NET_NewPacket(64); + NET_WriteInt16(reply, NET_PACKET_TYPE_QUERY_RESPONSE); + + // Version + + NET_WriteString(reply, PACKAGE_STRING); + + // Server state + + NET_WriteInt8(reply, server_state); + + // Number of players/maximum players + + NET_WriteInt8(reply, NET_SV_NumClients()); + NET_WriteInt8(reply, MAXPLAYERS); + + // Game mode/mission + + NET_WriteInt8(reply, sv_gamemode); + NET_WriteInt8(reply, sv_gamemission); + + // Server description. This is currently hard-coded. + + NET_WriteString(reply, "Chocolate Doom server"); + + // Send it and we're done. + + NET_SendPacket(addr, reply); + NET_FreePacket(reply); +} // Process a packet received by the server @@ -1083,6 +1119,10 @@ static void NET_SV_Packet(net_packet_t *packet, net_addr_t *addr) { NET_SV_ParseSYN(packet, client, addr); } + else if (packet_type == NET_PACKET_TYPE_QUERY) + { + NET_SV_SendQueryResponse(addr); + } else if (client == NULL) { // Must come from a valid client; ignore otherwise @@ -1299,6 +1339,7 @@ static void NET_SV_RunClient(net_client_t *client) if (NET_SV_NumClients() <= 0) { server_state = SERVER_WAITING_START; + sv_gamemode = indetermined; } } @@ -1355,6 +1396,7 @@ void NET_SV_Init(void) } server_state = SERVER_WAITING_START; + sv_gamemode = indetermined; server_initialised = true; } -- cgit v1.2.3