From 3b070cdaad39d0ebd56292f9ba5d0ef778e2108e Mon Sep 17 00:00:00 2001 From: Benau Date: Thu, 13 Sep 2018 10:46:37 +0800 Subject: [PATCH] Fix ranked server player reconnection handling --- src/network/protocols/server_lobby.cpp | 27 ++++++++++++++++++-------- src/network/stk_host.cpp | 2 ++ src/network/stk_peer.cpp | 4 ++++ src/network/stk_peer.hpp | 5 ++++- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/network/protocols/server_lobby.cpp b/src/network/protocols/server_lobby.cpp index 0b788efdc..40e3c0a3e 100644 --- a/src/network/protocols/server_lobby.cpp +++ b/src/network/protocols/server_lobby.cpp @@ -369,11 +369,13 @@ void ServerLobby::asynchronousUpdate() // Check if server owner has left updateServerOwner(); + if (ServerConfig::m_ranked && m_state.load() == WAITING_FOR_START_GAME) + clearDisconnectedRankedPlayer(); + if (allowJoinedPlayersWaiting() || (m_game_setup->isGrandPrix() && m_state.load() == WAITING_FOR_START_GAME)) { updateWaitingPlayers(); - clearDisconnectedRankedPlayer(); // Only poll the STK server if this is a WAN server. if (NetworkConfig::get()->isWAN()) checkIncomingConnectionRequests(); @@ -1460,13 +1462,17 @@ void ServerLobby::connectionRequested(Event* event) // Reject non-valiated player joinning if WAN server and not disabled // encforement of validation, unless it's player from localhost or lan // And no duplicated online id or split screen players in ranked server + bool duplicated_ranked_player = + m_ranked_players.find(online_id) != m_ranked_players.end() && + !m_ranked_players.at(online_id).expired(); + if (((encrypted_size == 0 || online_id == 0) && !(peer->getAddress().isPublicAddressLocalhost() || peer->getAddress().isLAN()) && NetworkConfig::get()->isWAN() && ServerConfig::m_validating_player) || - ((player_count != 1 || online_id == 0 || - m_scores.find(online_id) != m_scores.end()) && ServerConfig::m_ranked)) + (ServerConfig::m_ranked && + (player_count != 1 || online_id == 0 || duplicated_ranked_player))) { NetworkString* message = getNetworkString(2); message->setSynchronous(true); @@ -1516,9 +1522,11 @@ void ServerLobby::handleUnencryptedConnection(std::shared_ptr peer, return; } - // Check again for duplicated online id in ranked server - if (m_scores.find(online_id) != m_scores.end() && - ServerConfig::m_ranked) + // Check again for duplicated player in ranked server + bool duplicated_ranked_player = + m_ranked_players.find(online_id) != m_ranked_players.end() && + !m_ranked_players.at(online_id).expired(); + if (ServerConfig::m_ranked && duplicated_ranked_player) { NetworkString* message = getNetworkString(2); message->setSynchronous(true); @@ -2321,13 +2329,16 @@ void ServerLobby::addWaitingPlayersToGame() uint32_t online_id = npp->getOnlineId(); if (ServerConfig::m_ranked) { - if (m_scores.find(online_id) != m_scores.end()) + bool duplicated_ranked_player = + m_ranked_players.find(online_id) != m_ranked_players.end() && + !m_ranked_players.at(online_id).expired(); + if (duplicated_ranked_player) { NetworkString* message = getNetworkString(2); message->setSynchronous(true); message->addUInt8(LE_CONNECTION_REFUSED) .addUInt8(RR_INVALID_PLAYER); - peer->sendPacket(message, true/*reliable*/, false/*encrypted*/); + peer->sendPacket(message, true/*reliable*/); peer->reset(); delete message; Log::verbose("ServerLobby", "Player refused: invalid player"); diff --git a/src/network/stk_host.cpp b/src/network/stk_host.cpp index af6d5c122..10f7ede5c 100644 --- a/src/network/stk_host.cpp +++ b/src/network/stk_host.cpp @@ -1221,6 +1221,8 @@ std::vector > std::unique_lock lock(m_peers_mutex); for (auto peer : m_peers) { + if (peer.second->isDisconnected()) + continue; auto peer_profile = peer.second->getPlayerProfiles(); p.insert(p.end(), peer_profile.begin(), peer_profile.end()); } diff --git a/src/network/stk_peer.cpp b/src/network/stk_peer.cpp index fda50c719..d645d9eac 100644 --- a/src/network/stk_peer.cpp +++ b/src/network/stk_peer.cpp @@ -41,6 +41,7 @@ STKPeer::STKPeer(ENetPeer *enet_peer, STKHost* host, uint32_t host_id) m_validated.store(false); m_average_ping.store(0); m_waiting_for_game.store(true); + m_disconnected.store(false); } // STKPeer //----------------------------------------------------------------------------- @@ -55,6 +56,7 @@ void STKPeer::disconnect() if (m_enet_peer->state != ENET_PEER_STATE_CONNECTED || a != m_peer_address) return; + m_disconnected.store(true); m_host->addEnetCommand(m_enet_peer, NULL, PDI_NORMAL, ECT_DISCONNECT); } // disconnect @@ -67,6 +69,7 @@ void STKPeer::kick() if (m_enet_peer->state != ENET_PEER_STATE_CONNECTED || a != m_peer_address) return; + m_disconnected.store(true); m_host->addEnetCommand(m_enet_peer, NULL, PDI_KICK, ECT_DISCONNECT); } // kick @@ -79,6 +82,7 @@ void STKPeer::reset() if (m_enet_peer->state != ENET_PEER_STATE_CONNECTED || a != m_peer_address) return; + m_disconnected.store(true); m_host->addEnetCommand(m_enet_peer, NULL, 0, ECT_RESET); } // reset diff --git a/src/network/stk_peer.hpp b/src/network/stk_peer.hpp index 2e67db9a0..fbf6c45f4 100644 --- a/src/network/stk_peer.hpp +++ b/src/network/stk_peer.hpp @@ -67,6 +67,8 @@ protected: /** True if this peer is waiting for game. */ std::atomic_bool m_waiting_for_game; + std::atomic_bool m_disconnected; + /** Host id of this peer. */ uint32_t m_host_id; @@ -177,7 +179,8 @@ public: void setWaitingForGame(bool val) { m_waiting_for_game.store(val); } // ------------------------------------------------------------------------ bool isWaitingForGame() const { return m_waiting_for_game.load(); } - + // ------------------------------------------------------------------------ + bool isDisconnected() const { return m_disconnected.load(); } }; // STKPeer #endif // STK_PEER_HPP