diff options
-rw-r--r-- | projects/openttd_vs100.vcxproj | 4 | ||||
-rw-r--r-- | projects/openttd_vs100.vcxproj.filters | 12 | ||||
-rw-r--r-- | projects/openttd_vs80.vcproj | 16 | ||||
-rw-r--r-- | projects/openttd_vs90.vcproj | 16 | ||||
-rw-r--r-- | source.list | 4 | ||||
-rw-r--r-- | src/network/core/config.h | 2 | ||||
-rw-r--r-- | src/network/core/tcp_admin.cpp | 119 | ||||
-rw-r--r-- | src/network/core/tcp_admin.h | 137 | ||||
-rw-r--r-- | src/network/network_admin.cpp | 202 | ||||
-rw-r--r-- | src/network/network_admin.h | 62 | ||||
-rw-r--r-- | src/network/network_type.h | 8 | ||||
-rw-r--r-- | src/settings_type.h | 1 | ||||
-rw-r--r-- | src/table/settings.h | 1 |
13 files changed, 584 insertions, 0 deletions
diff --git a/projects/openttd_vs100.vcxproj b/projects/openttd_vs100.vcxproj index 69e635eed..34173c190 100644 --- a/projects/openttd_vs100.vcxproj +++ b/projects/openttd_vs100.vcxproj @@ -331,6 +331,7 @@ <ClCompile Include="..\src\mixer.cpp" /> <ClCompile Include="..\src\music.cpp" /> <ClCompile Include="..\src\network\network.cpp" /> + <ClCompile Include="..\src\network\network_admin.cpp" /> <ClCompile Include="..\src\network\network_client.cpp" /> <ClCompile Include="..\src\network\network_command.cpp" /> <ClCompile Include="..\src\network\network_content.cpp" /> @@ -457,6 +458,7 @@ <ClInclude Include="..\src\map_type.h" /> <ClInclude Include="..\src\mixer.h" /> <ClInclude Include="..\src\network\network.h" /> + <ClInclude Include="..\src\network\network_admin.h" /> <ClInclude Include="..\src\network\network_base.h" /> <ClInclude Include="..\src\network\network_client.h" /> <ClInclude Include="..\src\network\network_content.h" /> @@ -1039,6 +1041,8 @@ <ClInclude Include="..\src\network\core\tcp_content.h" /> <ClCompile Include="..\src\network\core\tcp_game.cpp" /> <ClInclude Include="..\src\network\core\tcp_game.h" /> + <ClCompile Include="..\src\network\core\tcp_admin.cpp" /> + <ClInclude Include="..\src\network\core\tcp_admin.h" /> <ClCompile Include="..\src\network\core\tcp_http.cpp" /> <ClInclude Include="..\src\network\core\tcp_http.h" /> <ClInclude Include="..\src\network\core\tcp_listen.h" /> diff --git a/projects/openttd_vs100.vcxproj.filters b/projects/openttd_vs100.vcxproj.filters index 98740669e..af54dea30 100644 --- a/projects/openttd_vs100.vcxproj.filters +++ b/projects/openttd_vs100.vcxproj.filters @@ -213,6 +213,9 @@ <ClCompile Include="..\src\network\network.cpp"> <Filter>Source Files</Filter> </ClCompile> + <ClCompile Include="..\src\network\network_admin.cpp"> + <Filter>Source Files</Filter> + </ClCompile> <ClCompile Include="..\src\network\network_client.cpp"> <Filter>Source Files</Filter> </ClCompile> @@ -591,6 +594,9 @@ <ClInclude Include="..\src\network\network.h"> <Filter>Header Files</Filter> </ClInclude> + <ClInclude Include="..\src\network\network_admin.h"> + <Filter>Header Files</Filter> + </ClInclude> <ClInclude Include="..\src\network\network_base.h"> <Filter>Header Files</Filter> </ClInclude> @@ -2337,6 +2343,12 @@ <ClInclude Include="..\src\network\core\tcp_game.h"> <Filter>Network Core</Filter> </ClInclude> + <ClCompile Include="..\src\network\core\tcp_admin.cpp"> + <Filter>Network Core</Filter> + </ClCompile> + <ClInclude Include="..\src\network\core\tcp_admin.h"> + <Filter>Network Core</Filter> + </ClInclude> <ClCompile Include="..\src\network\core\tcp_http.cpp"> <Filter>Network Core</Filter> </ClCompile> diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index 1e8fa9d97..eb9d856b3 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -595,6 +595,10 @@ > </File> <File + RelativePath=".\..\src\network\network_admin.cpp" + > + </File> + <File RelativePath=".\..\src\network\network_client.cpp" > </File> @@ -1103,6 +1107,10 @@ > </File> <File + RelativePath=".\..\src\network\network_admin.h" + > + </File> + <File RelativePath=".\..\src\network\network_base.h" > </File> @@ -3511,6 +3519,14 @@ > </File> <File + RelativePath=".\..\src\network\core\tcp_admin.cpp" + > + </File> + <File + RelativePath=".\..\src\network\core\tcp_admin.h" + > + </File> + <File RelativePath=".\..\src\network\core\tcp_http.cpp" > </File> diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj index dde8192f0..1afdab103 100644 --- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -592,6 +592,10 @@ > </File> <File + RelativePath=".\..\src\network\network_admin.cpp" + > + </File> + <File RelativePath=".\..\src\network\network_client.cpp" > </File> @@ -1100,6 +1104,10 @@ > </File> <File + RelativePath=".\..\src\network\network_admin.h" + > + </File> + <File RelativePath=".\..\src\network\network_base.h" > </File> @@ -3508,6 +3516,14 @@ > </File> <File + RelativePath=".\..\src\network\core\tcp_admin.cpp" + > + </File> + <File + RelativePath=".\..\src\network\core\tcp_admin.h" + > + </File> + <File RelativePath=".\..\src\network\core\tcp_http.cpp" > </File> diff --git a/source.list b/source.list index c59f96d4d..528a7b987 100644 --- a/source.list +++ b/source.list @@ -39,6 +39,7 @@ misc.cpp mixer.cpp music.cpp network/network.cpp +network/network_admin.cpp network/network_client.cpp network/network_command.cpp network/network_content.cpp @@ -190,6 +191,7 @@ map_func.h map_type.h mixer.h network/network.h +network/network_admin.h network/network_base.h network/network_client.h network/network_content.h @@ -834,6 +836,8 @@ network/core/tcp_content.cpp network/core/tcp_content.h network/core/tcp_game.cpp network/core/tcp_game.h +network/core/tcp_admin.cpp +network/core/tcp_admin.h network/core/tcp_http.cpp network/core/tcp_http.h network/core/tcp_listen.h diff --git a/src/network/core/config.h b/src/network/core/config.h index 2df6162e2..584e0382a 100644 --- a/src/network/core/config.h +++ b/src/network/core/config.h @@ -29,10 +29,12 @@ static const uint16 NETWORK_MASTER_SERVER_PORT = 3978; ///< The default port static const uint16 NETWORK_CONTENT_SERVER_PORT = 3978; ///< The default port of the content server (TCP) static const uint16 NETWORK_CONTENT_MIRROR_PORT = 80; ///< The default port of the content mirror (TCP) static const uint16 NETWORK_DEFAULT_PORT = 3979; ///< The default port of the game server (TCP & UDP) +static const uint16 NETWORK_ADMIN_PORT = 3977; ///< The default port for admin network static const uint16 NETWORK_DEFAULT_DEBUGLOG_PORT = 3982; ///< The default port debug-log is sent too (TCP) static const uint16 SEND_MTU = 1460; ///< Number of bytes we can pack in a single packet +static const byte NETWORK_GAME_ADMIN_VERSION = 1; ///< What version of the admin network do we use? static const byte NETWORK_GAME_INFO_VERSION = 4; ///< What version of game-info do we use? static const byte NETWORK_COMPANY_INFO_VERSION = 6; ///< What version of company info is this? static const byte NETWORK_MASTER_SERVER_VERSION = 2; ///< What version of master-server-protocol do we use? diff --git a/src/network/core/tcp_admin.cpp b/src/network/core/tcp_admin.cpp new file mode 100644 index 000000000..2d68fc68b --- /dev/null +++ b/src/network/core/tcp_admin.cpp @@ -0,0 +1,119 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD 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, version 2. + * OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * @file tcp_admin.cpp Basic functions to receive and send TCP packets to and from the admin network. + */ + +#ifdef ENABLE_NETWORK + +#include "../../stdafx.h" + +#include "../network_internal.h" +#include "tcp_admin.h" +#include "../../debug.h" + +NetworkAdminSocketHandler::NetworkAdminSocketHandler(SOCKET s) +{ + this->sock = s; +} + +NetworkAdminSocketHandler::~NetworkAdminSocketHandler() +{ +} + +NetworkRecvStatus NetworkAdminSocketHandler::CloseConnection(bool error) +{ + delete this; + return NETWORK_RECV_STATUS_CONN_LOST; +} + +/** + * Defines a simple (switch) case for each network packet. + * @param type the packet type to create the case for. + */ +#define ADMIN_COMMAND(type) case type: return this->NetworkPacketReceive_ ## type ## _command(p); break; + +/** + * Handle the given packet, i.e. pass it to the right parser receive command. + * @param p the packet to handle. + * @return #NetworkRecvStatus of handling. + */ +NetworkRecvStatus NetworkAdminSocketHandler::HandlePacket(Packet *p) +{ + PacketAdminType type = (PacketAdminType)p->Recv_uint8(); + + switch (this->HasClientQuit() ? INVALID_ADMIN_PACKET : type) { + ADMIN_COMMAND(ADMIN_PACKET_ADMIN_JOIN) + ADMIN_COMMAND(ADMIN_PACKET_ADMIN_QUIT) + + ADMIN_COMMAND(ADMIN_PACKET_SERVER_FULL) + ADMIN_COMMAND(ADMIN_PACKET_SERVER_BANNED) + ADMIN_COMMAND(ADMIN_PACKET_SERVER_ERROR) + ADMIN_COMMAND(ADMIN_PACKET_SERVER_PROTOCOL) + ADMIN_COMMAND(ADMIN_PACKET_SERVER_WELCOME) + ADMIN_COMMAND(ADMIN_PACKET_SERVER_NEWGAME) + ADMIN_COMMAND(ADMIN_PACKET_SERVER_SHUTDOWN) + + default: + if (this->HasClientQuit()) { + DEBUG(net, 0, "[tcp/admin] received invalid packet type %d from '%s' (%s)", type, this->admin_name, this->admin_version); + } else { + DEBUG(net, 0, "[tcp/admin] received illegal packet from '%s' (%s)", this->admin_name, this->admin_version); + } + + this->CloseConnection(); + return NETWORK_RECV_STATUS_MALFORMED_PACKET; + } +} + +/** + * Do the actual receiving of packets. + * As long as HandlePacket returns OKAY packets are handled. Upon + * failure, or no more packets to process the last result of + * HandlePacket is returned. + * @return #NetworkRecvStatus of the last handled packet. + */ +NetworkRecvStatus NetworkAdminSocketHandler::Recv_Packets() +{ + Packet *p; + while ((p = this->Recv_Packet()) != NULL) { + NetworkRecvStatus res = HandlePacket(p); + if (res != NETWORK_RECV_STATUS_OKAY) return res; + } + + return NETWORK_RECV_STATUS_OKAY; +} + +/** + * Create stub implementations for all receive commands that only + * show a warning that the given command is not available for the + * socket where the packet came from. + * @param type the packet type to create the stub for. + */ +#define DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(type) \ +NetworkRecvStatus NetworkAdminSocketHandler::NetworkPacketReceive_## type ##_command(Packet *p) \ +{ \ + DEBUG(net, 0, "[tcp/admin] received illegal packet type %d from admin %s (%s)", \ + type, this->admin_name, this->admin_version); \ + return NETWORK_RECV_STATUS_MALFORMED_PACKET; \ +} + +DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_ADMIN_JOIN) +DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_ADMIN_QUIT) + +DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_FULL) +DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_BANNED) +DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_ERROR) +DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_PROTOCOL) +DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_WELCOME) +DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_NEWGAME) +DEFINE_UNAVAILABLE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_SHUTDOWN) + +#endif /* ENABLE_NETWORK */ diff --git a/src/network/core/tcp_admin.h b/src/network/core/tcp_admin.h new file mode 100644 index 000000000..dae41c5f5 --- /dev/null +++ b/src/network/core/tcp_admin.h @@ -0,0 +1,137 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD 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, version 2. + * OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>. + */ + +/** + * @file tcp_admin.h Basic functions to receive and send TCP packets to and from the admin network. + */ + +#ifndef NETWORK_CORE_TCP_ADMIN_H +#define NETWORK_CORE_TCP_ADMIN_H + +#include "os_abstraction.h" +#include "tcp.h" +#include "../network_type.h" +#include "../../core/pool_type.hpp" + +#ifdef ENABLE_NETWORK + +/** + * Enum with types of TCP packets specific to the admin network. + * This protocol may only be extended to ensure stability. + */ +enum PacketAdminType { + ADMIN_PACKET_ADMIN_JOIN, ///< The admin announces and authenticates itself to the server. + ADMIN_PACKET_ADMIN_QUIT, ///< The admin tells the server that it is quitting. + + ADMIN_PACKET_SERVER_FULL = 100, ///< The server tells the admin it cannot accept the admin. + ADMIN_PACKET_SERVER_BANNED, ///< The server tells the admin it is banned. + ADMIN_PACKET_SERVER_ERROR, ///< The server tells the admin an error has occurred. + ADMIN_PACKET_SERVER_PROTOCOL, ///< The server tells the admin its protocol version. + ADMIN_PACKET_SERVER_WELCOME, ///< The server welcomes the admin to a game. + ADMIN_PACKET_SERVER_NEWGAME, ///< The server tells the admin its going to start a new game. + ADMIN_PACKET_SERVER_SHUTDOWN, ///< The server tells the admin its shutting down. + + INVALID_ADMIN_PACKET = 0xFF, ///< An invalid marker for admin packets. +}; + +/** Status of an admin. */ +enum AdminStatus { + ADMIN_STATUS_INACTIVE, ///< The admin is not connected nor active. + ADMIN_STATUS_ACTIVE, ///< The admin is active. + ADMIN_STATUS_END ///< Must ALWAYS be on the end of this list!! (period) +}; + +#define DECLARE_ADMIN_RECEIVE_COMMAND(type) virtual NetworkRecvStatus NetworkPacketReceive_## type ##_command(Packet *p) +#define DEF_ADMIN_RECEIVE_COMMAND(cls, type) NetworkRecvStatus cls ##NetworkAdminSocketHandler::NetworkPacketReceive_ ## type ## _command(Packet *p) + +/** Main socket handler for admin related connections. */ +class NetworkAdminSocketHandler : public NetworkTCPSocketHandler { +protected: + char admin_name[NETWORK_CLIENT_NAME_LENGTH]; ///< Name of the admin. + char admin_version[NETWORK_REVISION_LENGTH]; ///< Version string of the admin. + AdminStatus status; ///< Status of this admin. + + /** + * Join the admin network: + * string Password the server is expecting for this network. + * string Name of the application being used to connect. + * string Version string of the application being used to connect. + */ + DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_ADMIN_JOIN); + + /** + * Notification to the server that this admin is quitting. + */ + DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_ADMIN_QUIT); + + /** + * The server is full (connection gets closed). + */ + DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_FULL); + + /** + * The source IP address is banned (connection gets closed). + */ + DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_BANNED); + + /** + * An error was caused by this admin connection (connection gets closed). + * uint8 NetworkErrorCode the error caused. + */ + DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_ERROR); + + /** + * Inform a just joined admin about the protocol specifics: + * uint8 Protocol version. + * bool Further protocol data follows (repeats through all update packet types). + * uint16 Update packet type. + * uint16 Frequencies allowed for this update packet (bitwise). + */ + DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_PROTOCOL); + + /** + * Welcome a connected admin to the game: + * string Name of the Server (e.g. as advertised to master server). + * string OpenTTD version string. + * bool Server is dedicated. + * string Name of the Map. + * uint32 Random seed of the Map. + * uint8 Landscape of the Map. + * uint32 Start date of the Map. + * uint16 Map width. + * uint16 Map height. + */ + DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_WELCOME); + + /** + * Notification about a newgame. + */ + DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_NEWGAME); + + /** + * Notification about the server shutting down. + */ + DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_SERVER_SHUTDOWN); + + NetworkRecvStatus HandlePacket(Packet *p); +public: + NetworkRecvStatus CloseConnection(bool error = true); + + NetworkAdminSocketHandler(SOCKET s); + ~NetworkAdminSocketHandler(); + + NetworkRecvStatus Recv_Packets(); + + const char *Recv_Command(Packet *p, CommandPacket *cp); + void Send_Command(Packet *p, const CommandPacket *cp); +}; + +#endif /* ENABLE_NETWORK */ + +#endif /* NETWORK_CORE_TCP_ADMIN_H */ diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp new file mode 100644 index 000000000..90da9ac6a --- /dev/null +++ b/src/network/network_admin.cpp @@ -0,0 +1,202 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD 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, version 2. + * OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>. + */ + +/** @file network_admin.cpp Server part of the admin network protocol. */ + +#ifdef ENABLE_NETWORK + +#include "../stdafx.h" +#include "../debug.h" +#include "../strings_func.h" +#include "../date_func.h" +#include "network_admin.h" +#include "network.h" +#include "network_base.h" +#include "../company_base.h" +#include "../console_func.h" +#include "../core/pool_func.hpp" +#include "../map_func.h" +#include "../rev.h" + +#include "table/strings.h" + +/* This file handles all the admin network commands. */ + +/** The amount of admins connected. */ +byte _network_admins_connected = 0; + +NetworkAdminSocketPool _networkadminsocket_pool("NetworkAdminSocket"); +INSTANTIATE_POOL_METHODS(NetworkAdminSocket) + +/** + * Create a new socket for the server side of the admin network. + * @param s The socket to connect with. + */ +ServerNetworkAdminSocketHandler::ServerNetworkAdminSocketHandler(SOCKET s) : NetworkAdminSocketHandler(s) +{ + _network_admins_connected++; + this->status = ADMIN_STATUS_INACTIVE; +} + +/** + * Clear everything related to this admin. + */ +ServerNetworkAdminSocketHandler::~ServerNetworkAdminSocketHandler() +{ + _network_admins_connected--; + DEBUG(net, 1, "[admin] '%s' (%s) has disconnected", this->admin_name, this->admin_version); +} + +/** + * Whether a connection is allowed or not at this moment. + * @return Whether the connection is allowed. + */ +/* static */ bool ServerNetworkAdminSocketHandler::AllowConnection() +{ + return !StrEmpty(_settings_client.network.admin_password) && _network_admins_connected < MAX_ADMINS; +} + +/** Send the packets for the server sockets. */ +/* static */ void ServerNetworkAdminSocketHandler::Send() +{ + ServerNetworkAdminSocketHandler *as; + FOR_ALL_ADMIN_SOCKETS(as) { + if (as->writable) { + as->Send_Packets(); + } + } +} + +/* static */ void ServerNetworkAdminSocketHandler::AcceptConnection(SOCKET s, const NetworkAddress &address) +{ + ServerNetworkAdminSocketHandler *as = new ServerNetworkAdminSocketHandler(s); + as->address = address; // Save the IP of the client +} + +/*********** + * Sending functions for admin network + ************/ + +NetworkRecvStatus ServerNetworkAdminSocketHandler::SendError(NetworkErrorCode error) +{ + Packet *p = new Packet(ADMIN_PACKET_SERVER_ERROR); + + p->Send_uint8(error); + this->Send_Packet(p); + + char str[100]; + StringID strid = GetNetworkErrorMsg(error); + GetString(str, strid, lastof(str)); + + DEBUG(net, 1, "[admin] the admin '%s' (%s) made an error and has been disconnected. Reason: '%s'", this->admin_name, this->admin_version, str); + + return this->CloseConnection(true); +} + +NetworkRecvStatus ServerNetworkAdminSocketHandler::SendProtocol() +{ + Packet *p = new Packet(ADMIN_PACKET_SERVER_PROTOCOL); + + /* announce the protocol version */ + p->Send_uint8(NETWORK_GAME_ADMIN_VERSION); + + p->Send_bool(false); + this->Send_Packet(p); + + return this->SendWelcome(); +} + +NetworkRecvStatus ServerNetworkAdminSocketHandler::SendWelcome() +{ + this->status = ADMIN_STATUS_ACTIVE; + + Packet *p = new Packet(ADMIN_PACKET_SERVER_WELCOME); + + p->Send_string(_settings_client.network.server_name); + p->Send_string(_openttd_revision); + p->Send_bool (_network_dedicated); + + p->Send_string(_network_game_info.map_name); + p->Send_uint32(_settings_game.game_creation.generation_seed); + p->Send_uint8 (_settings_game.game_creation.landscape); + p->Send_uint32(ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1)); + p->Send_uint16(MapSizeX()); + p->Send_uint16(MapSizeY()); + + this->Send_Packet(p); + + return NETWORK_RECV_STATUS_OKAY; +} + +NetworkRecvStatus ServerNetworkAdminSocketHandler::SendNewGame() +{ + Packet *p = new Packet(ADMIN_PACKET_SERVER_NEWGAME); + this->Send_Packet(p); + return NETWORK_RECV_STATUS_OKAY; +} + +NetworkRecvStatus ServerNetworkAdminSocketHandler::SendShutdown() +{ + Packet *p = new Packet(ADMIN_PACKET_SERVER_SHUTDOWN); + this->Send_Packet(p); + return NETWORK_RECV_STATUS_OKAY; +} + +/*********** + * Receiving functions + ************/ + +DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_JOIN) +{ + if (this->status != ADMIN_STATUS_INACTIVE) return this->SendError(NETWORK_ERROR_NOT_EXPECTED); + + char password[NETWORK_PASSWORD_LENGTH]; + p->Recv_string(password, sizeof(password)); + + if (StrEmpty(_settings_client.network.admin_password) || + strcmp(password, _settings_client.network.admin_password) != 0) { + /* Password is invalid */ + return this->SendError(NETWORK_ERROR_WRONG_PASSWORD); + } + + p->Recv_string(this->admin_name, sizeof(this->admin_name)); + p->Recv_string(this->admin_version, sizeof(this->admin_version)); + + if (StrEmpty(this->admin_name) || StrEmpty(this->admin_version)) { + /* no name or version supplied */ + return this->SendError(NETWORK_ERROR_ILLEGAL_PACKET); + } + + DEBUG(net, 1, "[admin] '%s' (%s) has connected", this->admin_name, this->admin_version); + + return this->SendProtocol(); +} + +DEF_ADMIN_RECEIVE_COMMAND(Server, ADMIN_PACKET_ADMIN_QUIT) +{ + /* The admin is leaving nothing else to do */ + return this->CloseConnection(); +} + +/* + * Useful wrapper functions + */ + +/** + * Send a Welcome packet to all connected admins + */ +void ServerNetworkAdminSocketHandler::WelcomeAll() +{ + ServerNetworkAdminSocketHandler *as; + FOR_ALL_ADMIN_SOCKETS(as) { + as->SendWelcome(); + } +} + +#endif /* ENABLE_NETWORK */ diff --git a/src/network/network_admin.h b/src/network/network_admin.h new file mode 100644 index 000000000..ffa37ed44 --- /dev/null +++ b/src/network/network_admin.h @@ -0,0 +1,62 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD 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, version 2. + * OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>. + */ + +/** @file network_admin.h Server part of the admin network protocol. */ + +#ifndef NETWORK_ADMIN_H +#define NETWORK_ADMIN_H + +#ifdef ENABLE_NETWORK + +#include "network_internal.h" +#include "core/tcp_listen.h" +#include "core/tcp_admin.h" + +class ServerNetworkAdminSocketHandler; +typedef Pool<ServerNetworkAdminSocketHandler, AdminIndex, 2, MAX_ADMINS> NetworkAdminSocketPool; +extern NetworkAdminSocketPool _networkadminsocket_pool; + +/** Class for handling the server side of the game connection. */ +class ServerNetworkAdminSocketHandler : public NetworkAdminSocketPool::PoolItem<&_networkadminsocket_pool>, public NetworkAdminSocketHandler, public TCPListenHandler<ServerNetworkAdminSocketHandler, ADMIN_PACKET_SERVER_FULL, ADMIN_PACKET_SERVER_BANNED> { +protected: + DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_ADMIN_JOIN); + DECLARE_ADMIN_RECEIVE_COMMAND(ADMIN_PACKET_ADMIN_QUIT); + + NetworkRecvStatus SendProtocol(); +public: + NetworkAddress address; ///< Address of the admin. + + ServerNetworkAdminSocketHandler(SOCKET s); + ~ServerNetworkAdminSocketHandler(); + + NetworkRecvStatus SendError(NetworkErrorCode error); + NetworkRecvStatus SendWelcome(); + NetworkRecvStatus SendNewGame(); + NetworkRecvStatus SendShutdown(); + + static void Send(); + static void AcceptConnection(SOCKET s, const NetworkAddress &address); + static bool AllowConnection(); + static void WelcomeAll(); + + /** + * Get the name used by the listener. + * @return the name to show in debug logs and the like. + */ + static const char *GetName() + { + return "admin"; + } +}; + +#define FOR_ALL_ADMIN_SOCKETS_FROM(var, start) FOR_ALL_ITEMS_FROM(ServerNetworkAdminSocketHandler, adminsocket_index, var, start) +#define FOR_ALL_ADMIN_SOCKETS(var) FOR_ALL_ADMIN_SOCKETS_FROM(var, 0) + +#endif /* ENABLE_NETWORK */ +#endif /* NETWORK_ADMIN_H */ diff --git a/src/network/network_type.h b/src/network/network_type.h index 5b83620e6..f40a1cdd5 100644 --- a/src/network/network_type.h +++ b/src/network/network_type.h @@ -49,6 +49,14 @@ enum ClientID { /** Indices into the client tables */ typedef uint8 ClientIndex; +/** Indices into the admin tables. */ +typedef uint8 AdminIndex; + +/** Maximum number of allowed admins. */ +static const AdminIndex MAX_ADMINS = 16; +/** An invalid admin marker. */ +static const AdminIndex INVALID_ADMIN_ID = UINT8_MAX; + /** Simple calculated statistics of a company */ struct NetworkCompanyStats { uint16 num_vehicle[NETWORK_VEH_END]; ///< How many vehicles are there of this type? diff --git a/src/settings_type.h b/src/settings_type.h index e12507938..381e78c3e 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -136,6 +136,7 @@ struct NetworkSettings { char server_name[NETWORK_NAME_LENGTH]; ///< name of the server char server_password[NETWORK_PASSWORD_LENGTH]; ///< passowrd for joining this server char rcon_password[NETWORK_PASSWORD_LENGTH]; ///< passowrd for rconsole (server side) + char admin_password[NETWORK_PASSWORD_LENGTH]; ///< password for the admin network bool server_advertise; ///< advertise the server to the masterserver uint8 lan_internet; ///< search on the LAN or internet for servers char client_name[NETWORK_CLIENT_NAME_LENGTH]; ///< name of the player (as client) diff --git a/src/table/settings.h b/src/table/settings.h index 330fd918c..d2416ad2f 100644 --- a/src/table/settings.h +++ b/src/table/settings.h @@ -636,6 +636,7 @@ const SettingDesc _settings[] = { SDTC_STR(network.client_name, SLE_STRB, S, 0, NULL, STR_NULL, UpdateClientName), SDTC_STR(network.server_password, SLE_STRB, S, NO, NULL, STR_NULL, UpdateServerPassword), SDTC_STR(network.rcon_password, SLE_STRB, S, NO, NULL, STR_NULL, UpdateRconPassword), + SDTC_STR(network.admin_password, SLE_STRB, S, NO, NULL, STR_NULL, NULL), SDTC_STR(network.default_company_pass, SLE_STRB, S, 0, NULL, STR_NULL, NULL), SDTC_STR(network.server_name, SLE_STRB, S, NO, NULL, STR_NULL, NULL), SDTC_STR(network.connect_to_ip, SLE_STRB, S, 0, NULL, STR_NULL, NULL), |