Add: use Game Coordinator to annouce public servers

This commit is contained in:
Patric Stout
2021-07-03 11:04:32 +02:00
committed by Patric Stout
parent e1e2212e0e
commit b1280fd17e
13 changed files with 569 additions and 39 deletions

View File

@@ -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

View File

@@ -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 */

View File

@@ -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); }

View File

@@ -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 */