From fe12d38024038f90b8e81259d457288f8046bc5f Mon Sep 17 00:00:00 2001 From: Rubidium Date: Wed, 13 Mar 2024 21:33:28 +0100 Subject: [PATCH] Codechange: split initiating of joining and identification of the client --- src/network/core/tcp_game.cpp | 2 ++ src/network/core/tcp_game.h | 24 +++++++++++++++++++----- src/network/network_client.cpp | 13 +++++++++++-- src/network/network_client.h | 1 + src/network/network_server.cpp | 23 ++++++++++++++++++++--- src/network/network_server.h | 2 ++ 6 files changed, 55 insertions(+), 10 deletions(-) diff --git a/src/network/core/tcp_game.cpp b/src/network/core/tcp_game.cpp index 4bd32ec153..f1b4b05e2a 100644 --- a/src/network/core/tcp_game.cpp +++ b/src/network/core/tcp_game.cpp @@ -81,6 +81,7 @@ NetworkRecvStatus NetworkGameSocketHandler::HandlePacket(Packet &p) case PACKET_CLIENT_GAME_INFO: return this->Receive_CLIENT_GAME_INFO(p); case PACKET_SERVER_GAME_INFO: return this->Receive_SERVER_GAME_INFO(p); case PACKET_SERVER_CLIENT_INFO: return this->Receive_SERVER_CLIENT_INFO(p); + case PACKET_CLIENT_IDENTIFY: return this->Receive_CLIENT_IDENTIFY(p); case PACKET_SERVER_NEED_GAME_PASSWORD: return this->Receive_SERVER_NEED_GAME_PASSWORD(p); case PACKET_SERVER_NEED_COMPANY_PASSWORD: return this->Receive_SERVER_NEED_COMPANY_PASSWORD(p); case PACKET_CLIENT_GAME_PASSWORD: return this->Receive_CLIENT_GAME_PASSWORD(p); @@ -162,6 +163,7 @@ NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_ERROR(Packet &) { ret NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_GAME_INFO(Packet &) { return this->ReceiveInvalidPacket(PACKET_CLIENT_GAME_INFO); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_GAME_INFO); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_CLIENT_INFO); } +NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_IDENTIFY(Packet &) { return this->ReceiveInvalidPacket(PACKET_CLIENT_IDENTIFY); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_NEED_GAME_PASSWORD(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_NEED_GAME_PASSWORD); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_NEED_COMPANY_PASSWORD(Packet &) { return this->ReceiveInvalidPacket(PACKET_SERVER_NEED_COMPANY_PASSWORD); } NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_GAME_PASSWORD(Packet &) { return this->ReceiveInvalidPacket(PACKET_CLIENT_GAME_PASSWORD); } diff --git a/src/network/core/tcp_game.h b/src/network/core/tcp_game.h index ce031aa07b..7aed964d51 100644 --- a/src/network/core/tcp_game.h +++ b/src/network/core/tcp_game.h @@ -56,7 +56,10 @@ enum PacketGameType : uint8_t { * the map and other important data. */ - /* After the join step, the first is checking NewGRFs. */ + /* After the initial join, the next step is identification. */ + PACKET_CLIENT_IDENTIFY, ///< Client telling the server the client's name and requested company. + + /* After the identify step, the next is checking NewGRFs. */ PACKET_SERVER_CHECK_NEWGRFS, ///< Server sends NewGRF IDs and MD5 checksums for the client to check. PACKET_CLIENT_NEWGRFS_CHECKED, ///< Client acknowledges that it has all required NewGRFs. @@ -162,10 +165,13 @@ protected: /** * Try to join the server: - * string OpenTTD revision (norev000 if no revision). - * string Name of the client (max NETWORK_NAME_LENGTH). - * uint8_t ID of the company to play as (1..MAX_COMPANIES). - * uint8_t ID of the clients Language. + * string OpenTTD revision (norev000 if no revision). + * uint32_t NewGRF version (added in 1.2). + * string Name of the client (max NETWORK_NAME_LENGTH) (removed in 15). + * uint8_t ID of the company to play as (1..MAX_COMPANIES) (removed in 15). + * uint8_t ID of the clients Language (removed in 15). + * string Client's unique identifier (removed in 1.0). + * * @param p The packet that was just received. */ virtual NetworkRecvStatus Receive_CLIENT_JOIN(Packet &p); @@ -199,6 +205,14 @@ protected: */ virtual NetworkRecvStatus Receive_SERVER_CLIENT_INFO(Packet &p); + /** + * The client tells the server about the identity of the client: + * string Name of the client (max NETWORK_NAME_LENGTH). + * uint8_t ID of the company to play as (1..MAX_COMPANIES). + * @param p The packet that was just received. + */ + virtual NetworkRecvStatus Receive_CLIENT_IDENTIFY(Packet &p); + /** * Indication to the client that the server needs a game password. * @param p The packet that was just received. diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index ded54f0bae..db56f0b209 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -347,9 +347,18 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendJoin() auto p = std::make_unique(my_client, PACKET_CLIENT_JOIN); p->Send_string(GetNetworkRevisionString()); p->Send_uint32(_openttd_newgrf_version); + my_client->SendPacket(std::move(p)); + + return ClientNetworkGameSocketHandler::SendIdentify(); +} + +NetworkRecvStatus ClientNetworkGameSocketHandler::SendIdentify() +{ + Debug(net, 9, "Client::SendIdentify()"); + + auto p = std::make_unique(my_client, PACKET_CLIENT_IDENTIFY); p->Send_string(_settings_client.network.client_name); // Client name - p->Send_uint8 (_network_join.company); // PlayAs - p->Send_uint8 (0); // Used to be language + p->Send_uint8(_network_join.company); // PlayAs my_client->SendPacket(std::move(p)); return NETWORK_RECV_STATUS_OKAY; } diff --git a/src/network/network_client.h b/src/network/network_client.h index d314ddc41a..72da871700 100644 --- a/src/network/network_client.h +++ b/src/network/network_client.h @@ -71,6 +71,7 @@ protected: static NetworkRecvStatus SendNewGRFsOk(); static NetworkRecvStatus SendGetMap(); static NetworkRecvStatus SendMapOk(); + static NetworkRecvStatus SendIdentify(); void CheckConnection(); public: ClientNetworkGameSocketHandler(SOCKET s, const std::string &connection_string); diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 2e6c51920e..72567c2ef9 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -400,8 +400,8 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendNewGRFCheck() { Debug(net, 9, "client[{}] SendNewGRFCheck()", this->client_id); - /* Invalid packet when status is anything but STATUS_INACTIVE. */ - if (this->status != STATUS_INACTIVE) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET); + /* Invalid packet when status is anything but STATUS_IDENTIFY. */ + if (this->status != STATUS_IDENTIFY) return this->CloseConnection(NETWORK_RECV_STATUS_MALFORMED_PACKET); Debug(net, 9, "client[{}] status = NEWGRFS_CHECK", this->client_id); this->status = STATUS_NEWGRFS_CHECK; @@ -891,6 +891,21 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet &p) return this->SendError(NETWORK_ERROR_WRONG_REVISION); } + Debug(net, 9, "client[{}] status = IDENTIFY", this->client_id); + this->status = STATUS_IDENTIFY; + + /* Reset 'lag' counters */ + this->last_frame = this->last_frame_server = _frame_counter; + + return NETWORK_RECV_STATUS_OKAY; +} + +NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_IDENTIFY(Packet &p) +{ + if (this->status != STATUS_IDENTIFY) return this->SendError(NETWORK_ERROR_NOT_EXPECTED); + + Debug(net, 9, "client[{}] Receive_CLIENT_IDENTIFY()", this->client_id); + std::string client_name = p.Recv_string(NETWORK_CLIENT_NAME_LENGTH); CompanyID playas = (Owner)p.Recv_uint8(); @@ -905,7 +920,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet &p) break; case COMPANY_SPECTATOR: // Spectator break; - default: // Join another company (companies 1-8 (index 0-7)) + default: // Join another company (companies 1..MAX_COMPANIES (index 0..(MAX_COMPANIES-1))) if (!Company::IsValidHumanID(playas)) { return this->SendError(NETWORK_ERROR_COMPANY_MISMATCH); } @@ -1770,6 +1785,7 @@ void NetworkServer_Tick(bool send_frame) break; case NetworkClientSocket::STATUS_INACTIVE: + case NetworkClientSocket::STATUS_IDENTIFY: case NetworkClientSocket::STATUS_NEWGRFS_CHECK: case NetworkClientSocket::STATUS_AUTHORIZED: /* NewGRF check and authorized states should be handled almost instantly. @@ -1962,6 +1978,7 @@ void NetworkServerShowStatusToConsole() { static const char * const stat_str[] = { "inactive", + "identifing client", "checking NewGRFs", "authorizing (server password)", "authorizing (company password)", diff --git a/src/network/network_server.h b/src/network/network_server.h index bbf9817248..f67aeeb404 100644 --- a/src/network/network_server.h +++ b/src/network/network_server.h @@ -24,6 +24,7 @@ extern NetworkClientSocketPool _networkclientsocket_pool; class ServerNetworkGameSocketHandler : public NetworkClientSocketPool::PoolItem<&_networkclientsocket_pool>, public NetworkGameSocketHandler, public TCPListenHandler { protected: NetworkRecvStatus Receive_CLIENT_JOIN(Packet &p) override; + NetworkRecvStatus Receive_CLIENT_IDENTIFY(Packet &p) override; NetworkRecvStatus Receive_CLIENT_GAME_INFO(Packet &p) override; NetworkRecvStatus Receive_CLIENT_GAME_PASSWORD(Packet &p) override; NetworkRecvStatus Receive_CLIENT_COMPANY_PASSWORD(Packet &p) override; @@ -50,6 +51,7 @@ public: /** Status of a client */ enum ClientStatus { STATUS_INACTIVE, ///< The client is not connected nor active. + STATUS_IDENTIFY, ///< The client is identifying itself. STATUS_NEWGRFS_CHECK, ///< The client is checking NewGRFs. STATUS_AUTH_GAME, ///< The client is authorizing with game (server) password. STATUS_AUTH_COMPANY, ///< The client is authorizing with company password.