ref: d5f0ddc20b192cf1f17b27347dd467cddf493a6d
parent: 7355700d83fbab08c96fa8181b5aa3938464197e
author: Simon Howard <fraggle@gmail.com>
date: Thu Apr 6 16:48:35 EDT 2006
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
--- 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 @@
#include "am_map.h"
#include "net_client.h"
#include "net_dedicated.h"
+#include "net_query.h"
#include "p_setup.h"
#include "r_local.h"
@@ -1357,6 +1358,16 @@
// 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");
--- 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 @@
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
--- /dev/null
+++ b/src/net_query.c
@@ -1,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 <stdarg.h>
+#include <stdlib.h>
+
+#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);
+}
+
--- /dev/null
+++ b/src/net_query.h
@@ -1,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 */
+
--- 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,7 +1058,43 @@
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
static void NET_SV_Packet(net_packet_t *packet, net_addr_t *addr)
@@ -1083,6 +1119,10 @@
{
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 @@
if (NET_SV_NumClients() <= 0)
{
server_state = SERVER_WAITING_START;
+ sv_gamemode = indetermined;
}
}
@@ -1355,6 +1396,7 @@
}
server_state = SERVER_WAITING_START;
+ sv_gamemode = indetermined;
server_initialised = true;
}