From 4b0f702e7e7d5ff4f339d7b79275116bccdb1592 Mon Sep 17 00:00:00 2001 From: Arseniy Shestakov Date: Wed, 31 May 2017 09:45:26 +0300 Subject: [PATCH] Add LeaveGame netpack and avoid replying on it and CloseServer --- client/CPreGame.cpp | 2 +- client/Client.cpp | 6 ++++ lib/NetPacks.h | 7 +++++ lib/registerTypes/RegisterTypes.h | 1 + server/CGameHandler.cpp | 52 ++++++++++++++++++++++++------- server/CGameHandler.h | 6 ++++ server/NetPacksServer.cpp | 6 ++++ 7 files changed, 68 insertions(+), 12 deletions(-) diff --git a/client/CPreGame.cpp b/client/CPreGame.cpp index e0d0e7867..b20b4561b 100644 --- a/client/CPreGame.cpp +++ b/client/CPreGame.cpp @@ -83,7 +83,7 @@ struct EvilHlpStruct void reset() { - vstd::clear_pointer(serv); +// vstd::clear_pointer(serv); vstd::clear_pointer(sInfo); } diff --git a/client/Client.cpp b/client/Client.cpp index ae7bd3958..99cb331e9 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -701,6 +701,12 @@ void CClient::stopConnection() sendRequest(&close_server, PlayerColor::NEUTRAL); logNetwork->infoStream() << "Sent closing signal to the server"; } + else + { + LeaveGame leave_Game; + sendRequest(&leave_Game, PlayerColor::NEUTRAL); + logNetwork->infoStream() << "Sent leaving signal to the server"; + } if(connectionHandler)//end connection handler { diff --git a/lib/NetPacks.h b/lib/NetPacks.h index 758e7ded8..629f942af 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -1774,6 +1774,13 @@ struct CloseServer : public CPackForServer {} }; +struct LeaveGame : public CPackForServer +{ + bool applyGh(CGameHandler *gh); + template void serialize(Handler &h, const int version) + {} +}; + struct EndTurn : public CPackForServer { bool applyGh(CGameHandler *gh); diff --git a/lib/registerTypes/RegisterTypes.h b/lib/registerTypes/RegisterTypes.h index f6a74c10f..4d79e5dfa 100644 --- a/lib/registerTypes/RegisterTypes.h +++ b/lib/registerTypes/RegisterTypes.h @@ -314,6 +314,7 @@ void registerTypesServerPacks(Serializer &s) { s.template registerType(); s.template registerType(); + s.template registerType(); s.template registerType(); s.template registerType(); s.template registerType(); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index df758743f..2e8d7cd3a 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -1031,6 +1031,21 @@ void CGameHandler::handleConnection(std::set players, CConnection & { setThreadName("CGameHandler::handleConnection"); + auto handleDisconnection = [&](const std::exception & e) + { + assert(!c.connected); //make sure that connection has been marked as broken + logGlobal->error(e.what()); + conns -= &c; + for(auto playerConn : connections) + { + if(playerConn.second == &c) + { + gs->getPlayer(playerConn.first)->enteredLosingCheatCode = 1; + checkVictoryLossConditionsForPlayer(playerConn.first); + } + } + }; + try { while(1)//server should never shut connection first //was: while(!end2) @@ -1042,6 +1057,8 @@ void CGameHandler::handleConnection(std::set players, CConnection & { boost::unique_lock lock(*c.rmx); + if(!c.connected) + throw clientDisconnectedException(); c >> player >> requestID >> pack; //get the package if (!pack) @@ -1060,6 +1077,11 @@ void CGameHandler::handleConnection(std::set players, CConnection & //prepare struct informing that action was applied auto sendPackageResponse = [&](bool succesfullyApplied) { + //dont reply to disconnected client + //TODO: this must be implemented as option of CPackForServer + if(dynamic_cast(pack) || dynamic_cast(pack)) + return; + PackageApplied applied; applied.player = player; applied.result = succesfullyApplied; @@ -1095,17 +1117,11 @@ void CGameHandler::handleConnection(std::set players, CConnection & } catch(boost::system::system_error &e) //for boost errors just log, not crash - probably client shut down connection { - assert(!c.connected); //make sure that connection has been marked as broken - logGlobal->error(e.what()); - conns -= &c; - for(auto playerConn : connections) - { - if(playerConn.second == &c) - { - gs->getPlayer(playerConn.first)->enteredLosingCheatCode = 1; - checkVictoryLossConditionsForPlayer(playerConn.first); - } - } + handleDisconnection(e); + } + catch(clientDisconnectedException & e) + { + handleDisconnection(e); } catch(...) { @@ -2728,6 +2744,20 @@ void CGameHandler::close() exit(0); } +void CGameHandler::playerLeftGame(int cid) +{ + for (auto & elem : conns) + { + if(elem->isOpen() && elem->connectionID == cid) + { + boost::unique_lock lock(*(elem)->wmx); + elem->close(); + elem->connected = false; + break; + } + } +} + bool CGameHandler::arrangeStacks(ObjectInstanceID id1, ObjectInstanceID id2, ui8 what, SlotID p1, SlotID p2, si32 val, PlayerColor player) { const CArmedInstance * s1 = static_cast(getObjInstance(id1)), diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 1faf3e70a..5e1fe9a8b 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -223,6 +223,7 @@ public: bool arrangeStacks( ObjectInstanceID id1, ObjectInstanceID id2, ui8 what, SlotID p1, SlotID p2, si32 val, PlayerColor player); void save(const std::string &fname); void close(); + void playerLeftGame(int cid); void handleTimeEvents(); void handleTownEvents(CGTownInstance *town, NewTurn &n); bool complain(const std::string &problem); //sends message to all clients, prints on the logs and return true @@ -298,4 +299,9 @@ private: void checkVictoryLossConditionsForAll(); }; +class clientDisconnectedException : public std::exception +{ + +}; + void makeStackDoNothing(); diff --git a/server/NetPacksServer.cpp b/server/NetPacksServer.cpp index 756f20486..956eb0220 100644 --- a/server/NetPacksServer.cpp +++ b/server/NetPacksServer.cpp @@ -65,6 +65,12 @@ bool CloseServer::applyGh( CGameHandler *gh ) return true; } +bool LeaveGame::applyGh( CGameHandler *gh ) +{ + gh->playerLeftGame(c->connectionID); + return true; +} + bool EndTurn::applyGh( CGameHandler *gh ) { PlayerColor player = GS(gh)->currentPlayer;