diff --git a/docs/admin_network.txt b/docs/admin_network.txt index b73553d205..b81368e428 100644 --- a/docs/admin_network.txt +++ b/docs/admin_network.txt @@ -113,6 +113,9 @@ Admin Network - 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 Network - 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 @@ Admin Network 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. diff --git a/src/command_type.h b/src/command_type.h index 9b0179adcf..160b36cc91 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -269,6 +269,8 @@ enum Commands { 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) }; /** diff --git a/src/network/core/tcp_admin.cpp b/src/network/core/tcp_admin.cpp index aaa3c425a2..3765b070c8 100644 --- a/src/network/core/tcp_admin.cpp +++ b/src/network/core/tcp_admin.cpp @@ -80,6 +80,8 @@ NetworkRecvStatus NetworkAdminSocketHandler::HandlePacket(Packet *p) 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_COMPANY_STATS) 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 */ diff --git a/src/network/core/tcp_admin.h b/src/network/core/tcp_admin.h index ee1e6f2db1..1d15f398ac 100644 --- a/src/network/core/tcp_admin.h +++ b/src/network/core/tcp_admin.h @@ -56,6 +56,8 @@ enum PacketAdminType { 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 @@ enum AdminUpdateType { 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 @@ protected: */ 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); diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp index 47b05542d6..fe76f164d4 100644 --- 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 @@ static const AdminUpdateFrequency _admin_update_type_frequencies[] = { 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 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::SendConsole(const char *origi 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 @@ DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_POLL) 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); @@ -746,6 +803,23 @@ void NetworkAdminConsole(const char *origin, const char *string) } } +/** + * 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 */ diff --git a/src/network/network_admin.h b/src/network/network_admin.h index 4dad755f08..501c91dc02 100644 --- a/src/network/network_admin.h +++ b/src/network/network_admin.h @@ -64,6 +64,8 @@ public: 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 NetworkAdminChat(NetworkAction action, DestType desttype, ClientID client_i 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 */ diff --git a/src/network/network_command.cpp b/src/network/network_command.cpp index 9af6bfca10..5d39336adc 100644 --- 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 @@ static void DistributeQueue(CommandQueue *queue, const NetworkClientSocket *owne CommandPacket *cp; while (--to_go >= 0 && (cp = queue->Pop(true)) != NULL) { DistributeCommandPacket(*cp, owner); + NetworkAdminCmdLogging(owner, cp); free(cp); } }