diff options
author | Patric Stout <truebrain@openttd.org> | 2021-07-03 11:04:32 +0200 |
---|---|---|
committer | Patric Stout <github@truebrain.nl> | 2021-07-10 20:17:07 +0200 |
commit | b1280fd17ebaf9e4df086b63074d0bd8b8c9155d (patch) | |
tree | 6a421d4e079a765ba21181ad01ab21d13434ba9a /src/network/core | |
parent | e1e2212e0e09c7739f2eb8a4421a9ed7982801f5 (diff) | |
download | openttd-b1280fd17ebaf9e4df086b63074d0bd8b8c9155d.tar.xz |
Add: use Game Coordinator to annouce public servers
Diffstat (limited to 'src/network/core')
-rw-r--r-- | src/network/core/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/network/core/config.h | 73 | ||||
-rw-r--r-- | src/network/core/tcp_coordinator.cpp | 80 | ||||
-rw-r--r-- | src/network/core/tcp_coordinator.h | 115 |
4 files changed, 236 insertions, 34 deletions
diff --git a/src/network/core/CMakeLists.txt b/src/network/core/CMakeLists.txt index bf713be99..6eb255f6f 100644 --- a/src/network/core/CMakeLists.txt +++ b/src/network/core/CMakeLists.txt @@ -20,6 +20,8 @@ add_files( tcp_content.cpp tcp_content.h tcp_content_type.h + tcp_coordinator.cpp + tcp_coordinator.h tcp_game.cpp tcp_game.h tcp_http.cpp diff --git a/src/network/core/config.h b/src/network/core/config.h index 6d6038ec7..e0ec63a0c 100644 --- a/src/network/core/config.h +++ b/src/network/core/config.h @@ -14,6 +14,8 @@ /** DNS hostname of the masterserver */ static const char * const NETWORK_MASTER_SERVER_HOST = "master.openttd.org"; +/** DNS hostname of the Game Coordinator server */ +static const char * const NETWORK_COORDINATOR_SERVER_HOST = "coordinator.openttd.org"; /** DNS hostname of the content server */ static const char * const NETWORK_CONTENT_SERVER_HOST = "content.openttd.org"; /** DNS hostname of the HTTP-content mirror server */ @@ -23,14 +25,15 @@ static const char * const NETWORK_CONTENT_MIRROR_URL = "/bananas"; /** Message sent to the masterserver to 'identify' this client as OpenTTD */ static const char * const NETWORK_MASTER_SERVER_WELCOME_MESSAGE = "OpenTTDRegister"; -static const uint16 NETWORK_MASTER_SERVER_PORT = 3978; ///< The default port of the master server (UDP) -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 to (TCP) +static const uint16 NETWORK_MASTER_SERVER_PORT = 3978; ///< The default port of the master server (UDP) +static const uint16 NETWORK_COORDINATOR_SERVER_PORT = 3976; ///< The default port of the Game Coordinator server (TCP) +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 to (TCP) -static const uint16 UDP_MTU = 1460; ///< Number of bytes we can pack in a single UDP packet +static const uint16 UDP_MTU = 1460; ///< Number of bytes we can pack in a single UDP packet /* * Technically a TCP packet could become 64kiB, however the high bit is kept so it becomes possible in the future * to go to (significantly) larger packets if needed. This would entail a strategy such as employed for UTF-8. @@ -45,40 +48,42 @@ static const uint16 UDP_MTU = 1460; ///< Number of * Send_uint16(GB(size, 16, 14) | 0b10 << 14) * Send_uint16(GB(size, 0, 16)) */ -static const uint16 TCP_MTU = 32767; ///< Number of bytes we can pack in a single TCP packet -static const uint16 COMPAT_MTU = 1460; ///< Number of bytes we can pack in a single packet for backward compatibility +static const uint16 TCP_MTU = 32767; ///< Number of bytes we can pack in a single TCP packet +static const uint16 COMPAT_MTU = 1460; ///< Number of bytes we can pack in a single packet for backward compatibility -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? +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? +static const byte NETWORK_COORDINATOR_VERSION = 1; ///< What version of game-coordinator-protocol do we use? -static const uint NETWORK_NAME_LENGTH = 80; ///< The maximum length of the server name and map name, in bytes including '\0' -static const uint NETWORK_COMPANY_NAME_LENGTH = 128; ///< The maximum length of the company name, in bytes including '\0' -static const uint NETWORK_HOSTNAME_LENGTH = 80; ///< The maximum length of the host name, in bytes including '\0' -static const uint NETWORK_HOSTNAME_PORT_LENGTH = 80 + 6; ///< The maximum length of the host name + port, in bytes including '\0'. The extra six is ":" + port number (with a max of 65536) -static const uint NETWORK_SERVER_ID_LENGTH = 33; ///< The maximum length of the network id of the servers, in bytes including '\0' -static const uint NETWORK_REVISION_LENGTH = 33; ///< The maximum length of the revision, in bytes including '\0' -static const uint NETWORK_PASSWORD_LENGTH = 33; ///< The maximum length of the password, in bytes including '\0' (must be >= NETWORK_SERVER_ID_LENGTH) -static const uint NETWORK_CLIENTS_LENGTH = 200; ///< The maximum length for the list of clients that controls a company, in bytes including '\0' -static const uint NETWORK_CLIENT_NAME_LENGTH = 25; ///< The maximum length of a client's name, in bytes including '\0' -static const uint NETWORK_RCONCOMMAND_LENGTH = 500; ///< The maximum length of a rconsole command, in bytes including '\0' -static const uint NETWORK_GAMESCRIPT_JSON_LENGTH = COMPAT_MTU-3; ///< The maximum length of a gamescript json string, in bytes including '\0'. Must not be longer than COMPAT_MTU including header (3 bytes) -static const uint NETWORK_CHAT_LENGTH = 900; ///< The maximum length of a chat message, in bytes including '\0' -static const uint NETWORK_CONTENT_FILENAME_LENGTH = 48; ///< The maximum length of a content's filename, in bytes including '\0'. -static const uint NETWORK_CONTENT_NAME_LENGTH = 32; ///< The maximum length of a content's name, in bytes including '\0'. -static const uint NETWORK_CONTENT_VERSION_LENGTH = 16; ///< The maximum length of a content's version, in bytes including '\0'. -static const uint NETWORK_CONTENT_URL_LENGTH = 96; ///< The maximum length of a content's url, in bytes including '\0'. -static const uint NETWORK_CONTENT_DESC_LENGTH = 512; ///< The maximum length of a content's description, in bytes including '\0'. -static const uint NETWORK_CONTENT_TAG_LENGTH = 32; ///< The maximum length of a content's tag, in bytes including '\0'. +static const uint NETWORK_NAME_LENGTH = 80; ///< The maximum length of the server name and map name, in bytes including '\0' +static const uint NETWORK_COMPANY_NAME_LENGTH = 128; ///< The maximum length of the company name, in bytes including '\0' +static const uint NETWORK_HOSTNAME_LENGTH = 80; ///< The maximum length of the host name, in bytes including '\0' +static const uint NETWORK_HOSTNAME_PORT_LENGTH = 80 + 6; ///< The maximum length of the host name + port, in bytes including '\0'. The extra six is ":" + port number (with a max of 65536) +static const uint NETWORK_SERVER_ID_LENGTH = 33; ///< The maximum length of the network id of the servers, in bytes including '\0' +static const uint NETWORK_REVISION_LENGTH = 33; ///< The maximum length of the revision, in bytes including '\0' +static const uint NETWORK_PASSWORD_LENGTH = 33; ///< The maximum length of the password, in bytes including '\0' (must be >= NETWORK_SERVER_ID_LENGTH) +static const uint NETWORK_CLIENTS_LENGTH = 200; ///< The maximum length for the list of clients that controls a company, in bytes including '\0' +static const uint NETWORK_CLIENT_NAME_LENGTH = 25; ///< The maximum length of a client's name, in bytes including '\0' +static const uint NETWORK_RCONCOMMAND_LENGTH = 500; ///< The maximum length of a rconsole command, in bytes including '\0' +static const uint NETWORK_GAMESCRIPT_JSON_LENGTH = COMPAT_MTU - 3; ///< The maximum length of a gamescript json string, in bytes including '\0'. Must not be longer than COMPAT_MTU including header (3 bytes) +static const uint NETWORK_CHAT_LENGTH = 900; ///< The maximum length of a chat message, in bytes including '\0' +static const uint NETWORK_CONTENT_FILENAME_LENGTH = 48; ///< The maximum length of a content's filename, in bytes including '\0'. +static const uint NETWORK_CONTENT_NAME_LENGTH = 32; ///< The maximum length of a content's name, in bytes including '\0'. +static const uint NETWORK_CONTENT_VERSION_LENGTH = 16; ///< The maximum length of a content's version, in bytes including '\0'. +static const uint NETWORK_CONTENT_URL_LENGTH = 96; ///< The maximum length of a content's url, in bytes including '\0'. +static const uint NETWORK_CONTENT_DESC_LENGTH = 512; ///< The maximum length of a content's description, in bytes including '\0'. +static const uint NETWORK_CONTENT_TAG_LENGTH = 32; ///< The maximum length of a content's tag, in bytes including '\0'. +static const uint NETWORK_ERROR_DETAIL_LENGTH = 100; ///< The maximum length of the error detail, in bytes including '\0' -static const uint NETWORK_GRF_NAME_LENGTH = 80; ///< Maximum length of the name of a GRF +static const uint NETWORK_GRF_NAME_LENGTH = 80; ///< Maximum length of the name of a GRF /** * Maximum number of GRFs that can be sent. * This limit is reached when PACKET_UDP_SERVER_RESPONSE reaches the maximum size of UDP_MTU bytes. */ -static const uint NETWORK_MAX_GRF_COUNT = 62; +static const uint NETWORK_MAX_GRF_COUNT = 62; /** * The number of landscapes in OpenTTD. @@ -88,6 +93,6 @@ static const uint NETWORK_MAX_GRF_COUNT = 62; * there is a compile assertion to check that this NUM_LANDSCAPE is equal * to NETWORK_NUM_LANDSCAPES. */ -static const uint NETWORK_NUM_LANDSCAPES = 4; +static const uint NETWORK_NUM_LANDSCAPES = 4; #endif /* NETWORK_CORE_CONFIG_H */ diff --git a/src/network/core/tcp_coordinator.cpp b/src/network/core/tcp_coordinator.cpp new file mode 100644 index 000000000..1cf5cd676 --- /dev/null +++ b/src/network/core/tcp_coordinator.cpp @@ -0,0 +1,80 @@ +/* + * 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_coordinator.cpp Basic functions to receive and send Game Coordinator packets. + */ + +#include "../../stdafx.h" +#include "../../date_func.h" +#include "../../debug.h" +#include "tcp_coordinator.h" + +#include "../../safeguards.h" + +/** + * Handle the given packet, i.e. pass it to the right. + * parser receive command. + * @param p The packet to handle. + * @return True iff we should immediately handle further packets. + */ +bool NetworkCoordinatorSocketHandler::HandlePacket(Packet *p) +{ + PacketCoordinatorType type = (PacketCoordinatorType)p->Recv_uint8(); + + switch (type) { + case PACKET_COORDINATOR_GC_ERROR: return this->Receive_GC_ERROR(p); + case PACKET_COORDINATOR_SERVER_REGISTER: return this->Receive_SERVER_REGISTER(p); + case PACKET_COORDINATOR_GC_REGISTER_ACK: return this->Receive_GC_REGISTER_ACK(p); + case PACKET_COORDINATOR_SERVER_UPDATE: return this->Receive_SERVER_UPDATE(p); + + default: + Debug(net, 0, "[tcp/coordinator] Received invalid packet type {}", type); + return false; + } +} + +/** + * Receive a packet at TCP level. + * @return Whether at least one packet was received. + */ +bool NetworkCoordinatorSocketHandler::ReceivePackets() +{ + /* + * We read only a few of the packets. This allows the GUI to update when + * a large set of servers is being received. Otherwise the interface + * "hangs" while the game is updating the server-list. + * + * What arbitrary number to choose is the ultimate question though. + */ + Packet *p; + static const int MAX_PACKETS_TO_RECEIVE = 42; + int i = MAX_PACKETS_TO_RECEIVE; + while (--i != 0 && (p = this->ReceivePacket()) != nullptr) { + bool cont = this->HandlePacket(p); + delete p; + if (!cont) return true; + } + + return i != MAX_PACKETS_TO_RECEIVE - 1; +} + +/** + * Helper for logging receiving invalid packets. + * @param type The received packet type. + * @return Always false, as it's an error. + */ +bool NetworkCoordinatorSocketHandler::ReceiveInvalidPacket(PacketCoordinatorType type) +{ + Debug(net, 0, "[tcp/coordinator] Received illegal packet type {}", type); + return false; +} + +bool NetworkCoordinatorSocketHandler::Receive_GC_ERROR(Packet *p) { return this->ReceiveInvalidPacket(PACKET_COORDINATOR_GC_ERROR); } +bool NetworkCoordinatorSocketHandler::Receive_SERVER_REGISTER(Packet *p) { return this->ReceiveInvalidPacket(PACKET_COORDINATOR_SERVER_REGISTER); } +bool NetworkCoordinatorSocketHandler::Receive_GC_REGISTER_ACK(Packet *p) { return this->ReceiveInvalidPacket(PACKET_COORDINATOR_GC_REGISTER_ACK); } +bool NetworkCoordinatorSocketHandler::Receive_SERVER_UPDATE(Packet *p) { return this->ReceiveInvalidPacket(PACKET_COORDINATOR_SERVER_UPDATE); } diff --git a/src/network/core/tcp_coordinator.h b/src/network/core/tcp_coordinator.h new file mode 100644 index 000000000..a438f07aa --- /dev/null +++ b/src/network/core/tcp_coordinator.h @@ -0,0 +1,115 @@ +/* + * 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_coordinator.h Basic functions to receive and send TCP packets to/from the Game Coordinator server. + */ + +#ifndef NETWORK_CORE_TCP_COORDINATOR_H +#define NETWORK_CORE_TCP_COORDINATOR_H + +#include "os_abstraction.h" +#include "tcp.h" +#include "packet.h" +#include "game_info.h" + +/** + * Enum with all types of TCP Game Coordinator packets. The order MUST not be changed. + * + * GC -> packets from Game Coordinator to either Client or Server. + * SERVER -> packets from Server to Game Coordinator. + * CLIENT -> packets from Client to Game Coordinator. + **/ +enum PacketCoordinatorType { + PACKET_COORDINATOR_GC_ERROR, ///< Game Coordinator indicates there was an error. + PACKET_COORDINATOR_SERVER_REGISTER, ///< Server registration. + PACKET_COORDINATOR_GC_REGISTER_ACK, ///< Game Coordinator accepts the registration. + PACKET_COORDINATOR_SERVER_UPDATE, ///< Server sends an set intervals an update of the server. + PACKET_COORDINATOR_END, ///< Must ALWAYS be on the end of this list!! (period). +}; + +/** + * The type of connection the Game Coordinator can detect we have. + */ +enum ConnectionType { + CONNECTION_TYPE_UNKNOWN, ///< The Game Coordinator hasn't informed us yet what type of connection we have. + CONNECTION_TYPE_ISOLATED, ///< The Game Coordinator failed to find a way to connect to your server. Nobody will be able to join. + CONNECTION_TYPE_DIRECT, ///< The Game Coordinator can directly connect to your server. +}; + +/** + * The type of error from the Game Coordinator. + */ +enum NetworkCoordinatorErrorType { + NETWORK_COORDINATOR_ERROR_UNKNOWN, ///< There was an unknown error. + NETWORK_COORDINATOR_ERROR_REGISTRATION_FAILED, ///< Your request for registration failed. +}; + +/** Base socket handler for all Game Coordinator TCP sockets. */ +class NetworkCoordinatorSocketHandler : public NetworkTCPSocketHandler { +protected: + bool ReceiveInvalidPacket(PacketCoordinatorType type); + + /** + * Game Coordinator indicates there was an error. This can either be a + * permanent error causing the connection to be dropped, or in response + * to a request that is invalid. + * + * uint8 Type of error (see NetworkCoordinatorErrorType). + * string Details of the error. + * + * @param p The packet that was just received. + * @return True upon success, otherwise false. + */ + virtual bool Receive_GC_ERROR(Packet *p); + + /** + * Server is starting a multiplayer game and wants to let the + * Game Coordinator know. + * + * uint8 Game Coordinator protocol version. + * uint8 Type of game (see ServerGameType). + * uint16 Local port of the server. + * + * @param p The packet that was just received. + * @return True upon success, otherwise false. + */ + virtual bool Receive_SERVER_REGISTER(Packet *p); + + /** + * Game Coordinator acknowledges the registration. + * + * uint8 Type of connection was detected (see ConnectionType). + * + * @param p The packet that was just received. + * @return True upon success, otherwise false. + */ + virtual bool Receive_GC_REGISTER_ACK(Packet *p); + + /** + * Send an update of the current state of the server to the Game Coordinator. + * + * uint8 Game Coordinator protocol version. + * Serialized NetworkGameInfo. See game_info.hpp for details. + * + * @param p The packet that was just received. + * @return True upon success, otherwise false. + */ + virtual bool Receive_SERVER_UPDATE(Packet *p); + + bool HandlePacket(Packet *p); +public: + /** + * Create a new cs socket handler for a given cs. + * @param s The socket we are connected with. + */ + NetworkCoordinatorSocketHandler(SOCKET s = INVALID_SOCKET) : NetworkTCPSocketHandler(s) {} + + bool ReceivePackets(); +}; + +#endif /* NETWORK_CORE_TCP_COORDINATOR_H */ |