From 7e39d3f24ac22a99df86ce6456157c6a7e88e582 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Fri, 17 Sep 2021 23:44:59 +0100 Subject: [PATCH] Support sending extended game info in response to PACKET_CLIENT_GAME_INFO --- src/network/core/game_info.cpp | 4 ++-- src/network/core/game_info.h | 2 +- src/network/core/tcp_game.cpp | 3 +++ src/network/core/tcp_game.h | 9 +++++++++ src/network/network_client.cpp | 30 +++++++++++++++++++++++++++++- src/network/network_client.h | 1 + src/network/network_internal.h | 2 ++ src/network/network_server.cpp | 22 +++++++++++++++++++++- src/network/network_server.h | 1 + src/network/network_udp.cpp | 3 +-- 10 files changed, 70 insertions(+), 7 deletions(-) diff --git a/src/network/core/game_info.cpp b/src/network/core/game_info.cpp index c80a7573e7..815c281c31 100644 --- a/src/network/core/game_info.cpp +++ b/src/network/core/game_info.cpp @@ -110,10 +110,10 @@ bool IsNetworkCompatibleVersion(const char *other, bool extended) /** * Check if an game entry is compatible with our client. */ -void CheckGameCompatibility(NetworkGameInfo &ngi) +void CheckGameCompatibility(NetworkGameInfo &ngi, bool extended) { /* Check if we are allowed on this server based on the revision-check. */ - ngi.version_compatible = IsNetworkCompatibleVersion(ngi.server_revision); + ngi.version_compatible = IsNetworkCompatibleVersion(ngi.server_revision, extended); ngi.compatible = ngi.version_compatible; /* Check if we have all the GRFs on the client-system too. */ diff --git a/src/network/core/game_info.h b/src/network/core/game_info.h index ce889b7c42..4a93bb485d 100644 --- a/src/network/core/game_info.h +++ b/src/network/core/game_info.h @@ -94,7 +94,7 @@ extern NetworkServerGameInfo _network_game_info; const char *GetNetworkRevisionString(); bool IsNetworkCompatibleVersion(const char *other, bool extended = false); -void CheckGameCompatibility(NetworkGameInfo &ngi); +void CheckGameCompatibility(NetworkGameInfo &ngi, bool extended = false); void FillNetworkGameInfo(NetworkGameInfo &ngi); diff --git a/src/network/core/tcp_game.cpp b/src/network/core/tcp_game.cpp index 3540bc0f61..f31189fe9d 100644 --- a/src/network/core/tcp_game.cpp +++ b/src/network/core/tcp_game.cpp @@ -29,6 +29,7 @@ static const char* _packet_game_type_names[] { "SERVER_COMPANY_INFO", "CLIENT_GAME_INFO", "SERVER_GAME_INFO", + "SERVER_GAME_INFO_EXTENDED", "SERVER_CHECK_NEWGRFS", "CLIENT_NEWGRFS_CHECKED", "SERVER_NEED_GAME_PASSWORD", @@ -139,6 +140,7 @@ NetworkRecvStatus NetworkGameSocketHandler::HandlePacket(Packet *p) case PACKET_SERVER_ERROR: return this->Receive_SERVER_ERROR(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_GAME_INFO_EXTENDED: return this->Receive_SERVER_GAME_INFO_EXTENDED(p); case PACKET_CLIENT_COMPANY_INFO: return this->Receive_CLIENT_COMPANY_INFO(p); case PACKET_SERVER_COMPANY_INFO: return this->Receive_SERVER_COMPANY_INFO(p); case PACKET_SERVER_CLIENT_INFO: return this->Receive_SERVER_CLIENT_INFO(p); @@ -231,6 +233,7 @@ NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_JOIN(Packet *p) { ret NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_ERROR(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_ERROR); } NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_GAME_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CLIENT_GAME_INFO); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_GAME_INFO); } +NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_GAME_INFO_EXTENDED(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_GAME_INFO_EXTENDED); } NetworkRecvStatus NetworkGameSocketHandler::Receive_CLIENT_COMPANY_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_CLIENT_COMPANY_INFO); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_COMPANY_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_COMPANY_INFO); } NetworkRecvStatus NetworkGameSocketHandler::Receive_SERVER_CLIENT_INFO(Packet *p) { return this->ReceiveInvalidPacket(PACKET_SERVER_CLIENT_INFO); } diff --git a/src/network/core/tcp_game.h b/src/network/core/tcp_game.h index e0f1fc65d1..61dc5d31f9 100644 --- a/src/network/core/tcp_game.h +++ b/src/network/core/tcp_game.h @@ -57,6 +57,8 @@ enum PacketGameType { * the map and other important data. */ + PACKET_SERVER_GAME_INFO_EXTENDED, ///< Information about the server (extended). Note that the server should not use this ID directly. + /* After the join step, the first 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. @@ -212,6 +214,13 @@ protected: */ virtual NetworkRecvStatus Receive_SERVER_GAME_INFO(Packet *p); + /** + * Sends information about the game (extended). + * Serialized NetworkGameInfo. See game_info.h for details. + * @param p The packet that was just received. + */ + virtual NetworkRecvStatus Receive_SERVER_GAME_INFO_EXTENDED(Packet *p); + /** * Request company information (in detail). * @param p The packet that was just received. diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 2dd21fd10b..fcd4e327c8 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -414,7 +414,13 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::SendInformationQuery() _network_join_status = NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO; SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN); - my_client->SendPacket(new Packet(PACKET_CLIENT_GAME_INFO)); + Packet *p = new Packet(PACKET_CLIENT_GAME_INFO); + p->Send_uint32(FIND_SERVER_EXTENDED_TOKEN); + p->Send_uint8(PACKET_SERVER_GAME_INFO_EXTENDED); // reply type + p->Send_uint16(0); // flags + p->Send_uint16(0); // version + my_client->SendPacket(p); + my_client->SendPacket(new Packet(PACKET_CLIENT_COMPANY_INFO)); return NETWORK_RECV_STATUS_OKAY; @@ -712,6 +718,28 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_GAME_INFO(Packe return NETWORK_RECV_STATUS_CLOSE_QUERY; } +NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_GAME_INFO_EXTENDED(Packet *p) +{ + if (this->status != STATUS_COMPANY_INFO && this->status != STATUS_INACTIVE) return NETWORK_RECV_STATUS_MALFORMED_PACKET; + + NetworkGameList *item = GetLobbyGameInfo(); + + /* Clear any existing GRFConfig chain. */ + ClearGRFConfigList(&item->info.grfconfig); + /* Retrieve the NetworkGameInfo from the packet. */ + DeserializeNetworkGameInfoExtended(p, &item->info); + /* Check for compatability with the client. */ + CheckGameCompatibility(item->info, true); + /* Ensure we consider the server online. */ + item->online = true; + + SetWindowDirty(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_LOBBY); + + /* We will receive company info next, so keep connection open. */ + if (this->status == STATUS_COMPANY_INFO) return NETWORK_RECV_STATUS_OKAY; + return NETWORK_RECV_STATUS_CLOSE_QUERY; +} + NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_COMPANY_INFO(Packet *p) { if (this->status != STATUS_COMPANY_INFO) return NETWORK_RECV_STATUS_MALFORMED_PACKET; diff --git a/src/network/network_client.h b/src/network/network_client.h index a8fd11c2a8..fd1ad6a88a 100644 --- a/src/network/network_client.h +++ b/src/network/network_client.h @@ -51,6 +51,7 @@ protected: NetworkRecvStatus Receive_SERVER_BANNED(Packet *p) override; NetworkRecvStatus Receive_SERVER_ERROR(Packet *p) override; NetworkRecvStatus Receive_SERVER_GAME_INFO(Packet *p) override; + NetworkRecvStatus Receive_SERVER_GAME_INFO_EXTENDED(Packet *p) override; NetworkRecvStatus Receive_SERVER_COMPANY_INFO(Packet *p) override; NetworkRecvStatus Receive_SERVER_CLIENT_INFO(Packet *p) override; NetworkRecvStatus Receive_SERVER_NEED_GAME_PASSWORD(Packet *p) override; diff --git a/src/network/network_internal.h b/src/network/network_internal.h index e792ac514c..f1c591ff40 100644 --- a/src/network/network_internal.h +++ b/src/network/network_internal.h @@ -16,6 +16,8 @@ #include "../command_type.h" #include "../date_type.h" +static const uint32 FIND_SERVER_EXTENDED_TOKEN = 0x2A49582A; + #ifdef RANDOM_DEBUG /** * If this line is enable, every frame will have a sync test diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 0aec81d395..c27bebcbc6 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -371,6 +371,19 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendGameInfo() return NETWORK_RECV_STATUS_OKAY; } +NetworkRecvStatus ServerNetworkGameSocketHandler::SendGameInfoExtended(PacketGameType reply_type, uint16 flags, uint16 version) +{ + NetworkGameInfo ngi; + FillNetworkGameInfo(ngi); + + Packet *p = new Packet(reply_type, SHRT_MAX); + SerializeNetworkGameInfoExtended(p, &ngi, flags, version); + + this->SendPacket(p); + + return NETWORK_RECV_STATUS_OKAY; +} + /** Send the client information about the companies. */ NetworkRecvStatus ServerNetworkGameSocketHandler::SendCompanyInfo() { @@ -881,7 +894,14 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendSettingsAccessUpdate(bool NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_GAME_INFO(Packet *p) { - return this->SendGameInfo(); + if (p->CanReadFromPacket(9) && p->Recv_uint32() == FIND_SERVER_EXTENDED_TOKEN) { + PacketGameType reply_type = (PacketGameType)p->Recv_uint8(); + uint16 flags = p->Recv_uint16(); + uint16 version = p->Recv_uint16(); + return this->SendGameInfoExtended(reply_type, flags, version); + } else { + return this->SendGameInfo(); + } } NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_COMPANY_INFO(Packet *p) diff --git a/src/network/network_server.h b/src/network/network_server.h index 566f54dff4..9bbd570ee0 100644 --- a/src/network/network_server.h +++ b/src/network/network_server.h @@ -45,6 +45,7 @@ protected: NetworkRecvStatus Receive_CLIENT_MOVE(Packet *p) override; NetworkRecvStatus SendGameInfo(); + NetworkRecvStatus SendGameInfoExtended(PacketGameType reply_type, uint16 flags, uint16 version); NetworkRecvStatus SendCompanyInfo(); NetworkRecvStatus SendNewGRFCheck(); NetworkRecvStatus SendWelcome(); diff --git a/src/network/network_udp.cpp b/src/network/network_udp.cpp index 0df07f052d..cc223323c9 100644 --- a/src/network/network_udp.cpp +++ b/src/network/network_udp.cpp @@ -40,7 +40,6 @@ #include "../safeguards.h" extern const uint8 _out_of_band_grf_md5[16] { 0x00, 0xB0, 0xC0, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xC0, 0xDE, 0x00, 0x00, 0x00, 0x00 }; -static const uint32 FIND_SERVER_EXTENDED_TOKEN = 0x2A49582A; /** Mutex for all out threaded udp resolution and such. */ static std::mutex _network_udp_mutex; @@ -410,7 +409,7 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_RESPONSE_Common(Packet *p, Ne DeserializeNetworkGameInfo(p, &item->info); } /* Check for compatability with the client. */ - CheckGameCompatibility(item->info); + CheckGameCompatibility(item->info, extended); /* Ensure we consider the server online. */ item->online = true;