changeset 16933:dc6070bda35a draft

(svn r21668) -Feature: command logging using the admin interface (dihedral)
author rubidium <rubidium@openttd.org>
date Thu, 30 Dec 2010 18:14:37 +0000
parents fa03c4909b6f
children d1b67cd26a1c
files docs/admin_network.txt src/command_type.h src/network/core/tcp_admin.cpp src/network/core/tcp_admin.h src/network/network_admin.cpp src/network/network_admin.h src/network/network_command.cpp
diffstat 7 files changed, 135 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/docs/admin_network.txt
+++ b/docs/admin_network.txt
@@ -113,6 +113,9 @@
     - ADMIN_PACKET_SERVER_CONSOLE
 
 
+  ADMIN_UPDATE_CMD_LOGGING results in the server sending:
+    - ADMIN_PACKET_SERVER_CMD_LOGGING
+
 3. Polling manually
 -------------------
 
@@ -122,6 +125,7 @@
     - ADMIN_UPDATE_COMPANY_INFO
     - ADMIN_UPDATE_COMPANY_ECONOMY
     - ADMIN_UPDATE_COMPANY_STATS
+    - ADMIN_UPDATE_CMD_NAMES
 
   ADMIN_UPDATE_CLIENT_INFO and ADMIN_UPDATE_COMPANY_INFO accept an additional
   parameter. This parameter is used to specify a certain client or company.
@@ -202,4 +206,9 @@
     a CLIENT_JOIN / COMPANY_NEW packet without having received the INFO packet
     it may be a good idea to POLL for the specific ID.
 
+  ADMIN_PACKET_SERVER_CMD_NAMES and ADMIN_PACKET_SERVER_CMD_LOGGING
+    Data provided with these packets is not stable and will not be
+    treated as such. Do not rely on IDs or names to be constant
+    across different versions / revisions of OpenTTD.
+    Data provided in this packet is for logging purposes only.
 
--- a/src/command_type.h
+++ b/src/command_type.h
@@ -269,6 +269,8 @@
 	CMD_SET_VEHICLE_ON_TIME,          ///< set the vehicle on time feature (timetable)
 	CMD_AUTOFILL_TIMETABLE,           ///< autofill the timetable
 	CMD_SET_TIMETABLE_START,          ///< set the date that a timetable should start
+
+	CMD_END                           ///< Must ALWAYS be on the end of this list!! (period)
 };
 
 /**
--- a/src/network/core/tcp_admin.cpp
+++ b/src/network/core/tcp_admin.cpp
@@ -80,6 +80,8 @@
 		ADMIN_COMMAND(ADMIN_PACKET_SERVER_CHAT)
 		ADMIN_COMMAND(ADMIN_PACKET_SERVER_RCON)
 		ADMIN_COMMAND(ADMIN_PACKET_SERVER_CONSOLE)
+		ADMIN_COMMAND(ADMIN_PACKET_SERVER_CMD_NAMES)
+		ADMIN_COMMAND(ADMIN_PACKET_SERVER_CMD_LOGGING)
 
 		default:
 			if (this->HasClientQuit()) {
@@ -155,5 +157,7 @@
 DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_CHAT)
 DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_RCON)
 DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_CONSOLE)
+DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_CMD_NAMES)
+DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_CMD_LOGGING)
 
 #endif /* ENABLE_NETWORK */
--- a/src/network/core/tcp_admin.h
+++ b/src/network/core/tcp_admin.h
@@ -56,6 +56,8 @@
 	ADMIN_PACKET_SERVER_CHAT,            ///< The server received a chat message and relays it.
 	ADMIN_PACKET_SERVER_RCON,            ///< The server's reply to a remove console command.
 	ADMIN_PACKET_SERVER_CONSOLE,         ///< The server gives the admin the data that got printed to its console.
+	ADMIN_PACKET_SERVER_CMD_NAMES,       ///< The server sends out the names of the DoCommands to the admins.
+	ADMIN_PACKET_SERVER_CMD_LOGGING,     ///< The server gives the admin copies of incoming command packets.
 
 	INVALID_ADMIN_PACKET = 0xFF,         ///< An invalid marker for admin packets.
 };
@@ -76,6 +78,8 @@
 	ADMIN_UPDATE_COMPANY_STATS,   ///< Updates about the statistics of companies.
 	ADMIN_UPDATE_CHAT,            ///< The admin would like to have chat messages.
 	ADMIN_UPDATE_CONSOLE,         ///< The admin would like to have console messages.
+	ADMIN_UPDATE_CMD_NAMES,       ///< The admin would like a list of all DoCommand names.
+	ADMIN_UPDATE_CMD_LOGGING,     ///< The admin would like to have DoCommand information.
 	ADMIN_UPDATE_END              ///< Must ALWAYS be on the end of this list!! (period)
 };
 
@@ -340,6 +344,43 @@
 	 */
 	DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_CONSOLE);
 
+	/**
+	 * Send DoCommand names to the bot upon request only.
+	 * Multiple of these packets can follow each other in order to provide
+	 * all known DoCommand names.
+	 *
+	 * NOTICE: Data provided with this packet is not stable and will not be
+	 *         treated as such. Do not rely on IDs or names to be constant
+	 *         across different versions / revisions of OpenTTD.
+	 *         Data provided in this packet is for logging purposes only.
+	 *
+	 * These three fields are repeated until the packet is full:
+	 * bool    Data to follow.
+	 * uint16  ID of the DoCommand.
+	 * string  Name of DoCommand.
+	 */
+	DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_CMD_NAMES);
+
+	/**
+	 * Send incoming command packets to the admin network.
+	 * This is for logging purposes only.
+	 *
+	 * NOTICE: Data provided with this packet is not stable and will not be
+	 *         treated as such. Do not rely on IDs or names to be constant
+	 *         across different versions / revisions of OpenTTD.
+	 *         Data provided in this packet is for logging purposes only.
+	 *
+	 * uint32  ID of the client sending the command.
+	 * uint8   ID of the company (0..MAX_COMPANIES-1).
+	 * uint16  ID of the command.
+	 * uint32  P1 (variable data passed to the command).
+	 * uint32  P2 (variable data passed to the command).
+	 * uint32  Tile where this is taking place.
+	 * string  Text passed to the command.
+	 * uint32  Frame of execution.
+	 */
+	DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_CMD_LOGGING);
+
 	NetworkRecvStatus HandlePacket(Packet *p);
 public:
 	NetworkRecvStatus CloseConnection(bool error = true);
--- a/src/network/network_admin.cpp
+++ b/src/network/network_admin.cpp
@@ -18,6 +18,8 @@
 #include "network_admin.h"
 #include "network.h"
 #include "network_base.h"
+#include "network_server.h"
+#include "../command_func.h"
 #include "../company_base.h"
 #include "../console_func.h"
 #include "../core/pool_func.hpp"
@@ -25,6 +27,7 @@
 #include "../rev.h"
 
 #include "table/strings.h"
+#include "network_client.h"
 
 /* This file handles all the admin network commands. */
 
@@ -50,6 +53,8 @@
 	ADMIN_FREQUENCY_POLL |                         ADMIN_FREQUENCY_WEEKLY | ADMIN_FREQUENCY_MONTHLY | ADMIN_FREQUENCY_QUARTERLY | ADMIN_FREQUENCY_ANUALLY, ///< ADMIN_UPDATE_COMPANY_STATS
 	                       ADMIN_FREQUENCY_AUTOMATIC,                                                                                                      ///< ADMIN_UPDATE_CHAT
 	                       ADMIN_FREQUENCY_AUTOMATIC,                                                                                                      ///< ADMIN_UPDATE_CONSOLE
+	ADMIN_FREQUENCY_POLL,                                                                                                                                  ///< ADMIN_UPDATE_CMD_NAMES
+	                       ADMIN_FREQUENCY_AUTOMATIC,                                                                                                      ///< ADMIN_UPDATE_CMD_LOGGING
 };
 assert_compile(lengthof(_admin_update_type_frequencies) == ADMIN_UPDATE_END);
 
@@ -448,6 +453,53 @@
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
+NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdNames()
+{
+	Packet *p = new Packet(ADMIN_PACKET_SERVER_CMD_NAMES);
+
+	for (uint i = 0; i < CMD_END; i++) {
+		const char *cmdname = GetCommandName(i);
+
+		/* Should SEND_MTU be exceeded, start a new packet
+		 * (magic 5: 1 bool "more data" and one uint16 "command id", one
+    * byte for string '\0' termination and 1 bool "no more data" */
+		if (p->size + strlen(cmdname) + 5 >= SEND_MTU) {
+			p->Send_bool(false);
+			this->SendPacket(p);
+
+			p = new Packet(ADMIN_PACKET_SERVER_CMD_NAMES);
+		}
+
+		p->Send_bool(true);
+		p->Send_uint16(i);
+		p->Send_string(cmdname);
+	}
+
+	/* Marker to notify the end of the packet has been reached. */
+	p->Send_bool(false);
+	this->SendPacket(p);
+
+	return NETWORK_RECV_STATUS_OKAY;
+}
+
+NetworkRecvStatus ServerNetworkAdminSocketHandler::SendCmdLogging(ClientID client_id, const CommandPacket *cp)
+{
+	Packet *p = new Packet(ADMIN_PACKET_SERVER_CMD_LOGGING);
+
+	p->Send_uint32(client_id);
+	p->Send_uint8 (cp->company);
+	p->Send_uint16(cp->cmd & CMD_ID_MASK);
+	p->Send_uint32(cp->p1);
+	p->Send_uint32(cp->p2);
+	p->Send_uint32(cp->tile);
+	p->Send_string(cp->text);
+	p->Send_uint32(cp->frame);
+
+	this->SendPacket(p);
+
+	return NETWORK_RECV_STATUS_OKAY;
+}
+
 /***********
  * Receiving functions
  ************/
@@ -551,6 +603,11 @@
 			this->SendCompanyStats();
 			break;
 
+		case ADMIN_UPDATE_CMD_NAMES:
+			/* The admin is requesting the names of DoCommands. */
+			this->SendCmdNames();
+			break;
+
 		default:
 			/* An unsupported "poll" update type. */
 			DEBUG(net, 3, "[admin] Not supported poll %d (%d) from '%s' (%s).", type, d1, this->admin_name, this->admin_version);
@@ -747,6 +804,23 @@
 }
 
 /**
+ * Distribute CommandPacket details over the admin network for logging purposes.
+ * @param owner The owner of the CommandPacket (who sent us the CommandPacket).
+ * @param cp    The CommandPacket to be distributed.
+ */
+void NetworkAdminCmdLogging(const NetworkClientSocket *owner, const CommandPacket *cp)
+{
+	ClientID client_id = owner == NULL ? _network_own_client_id : owner->client_id;
+
+	ServerNetworkAdminSocketHandler *as;
+	FOR_ALL_ADMIN_SOCKETS(as) {
+		if (as->update_frequency[ADMIN_UPDATE_CMD_LOGGING] & ADMIN_FREQUENCY_AUTOMATIC) {
+			as->SendCmdLogging(client_id, cp);
+		}
+	}
+}
+
+/**
  * Send a Welcome packet to all connected admins
  */
 void ServerNetworkAdminSocketHandler::WelcomeAll()
--- a/src/network/network_admin.h
+++ b/src/network/network_admin.h
@@ -64,6 +64,8 @@
 	NetworkRecvStatus SendChat(NetworkAction action, DestType desttype, ClientID client_id, const char *msg, int64 data);
 	NetworkRecvStatus SendRcon(uint16 colour, const char *command);
 	NetworkRecvStatus SendConsole(const char *origin, const char *command);
+	NetworkRecvStatus SendCmdNames();
+	NetworkRecvStatus SendCmdLogging(ClientID client_id, const CommandPacket *cp);
 
 	static void Send();
 	static void AcceptConnection(SOCKET s, const NetworkAddress &address);
@@ -95,6 +97,7 @@
 void NetworkAdminUpdate(AdminUpdateFrequency freq);
 void NetworkServerSendAdminRcon(AdminIndex admin_index, ConsoleColour colour_code, const char *string);
 void NetworkAdminConsole(const char *origin, const char *string);
+void NetworkAdminCmdLogging(const NetworkClientSocket *owner, const CommandPacket *cp);
 
 #endif /* ENABLE_NETWORK */
 #endif /* NETWORK_ADMIN_H */
--- a/src/network/network_command.cpp
+++ b/src/network/network_command.cpp
@@ -13,6 +13,7 @@
 
 #include "../stdafx.h"
 #include "../debug.h"
+#include "network_admin.h"
 #include "network_client.h"
 #include "network_server.h"
 #include "network.h"
@@ -267,6 +268,7 @@
 	CommandPacket *cp;
 	while (--to_go >= 0 && (cp = queue->Pop(true)) != NULL) {
 		DistributeCommandPacket(*cp, owner);
+		NetworkAdminCmdLogging(owner, cp);
 		free(cp);
 	}
 }