From 727c7b33d97173282fcdfb6ac60247caccb5e1b9 Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Wed, 18 May 2011 21:14:14 +0000 Subject: [PATCH] - fixed server side detection of dropped socket connection when socket is not reporting a disconnect (we periodically do lag checks) --- .../glest_game/network/server_interface.cpp | 90 ++++++++++++++++++- source/glest_game/network/server_interface.h | 2 + 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/source/glest_game/network/server_interface.cpp b/source/glest_game/network/server_interface.cpp index 60389aa0..d1d162a9 100644 --- a/source/glest_game/network/server_interface.cpp +++ b/source/glest_game/network/server_interface.cpp @@ -56,6 +56,7 @@ ServerInterface::ServerInterface(bool publishEnabled) :GameNetworkInterface() { needToRepublishToMasterserver = false; ftpServer = NULL; inBroadcastMessage = false; + lastGlobalLagCheckTime = 0; maxFrameCountLagAllowed = Config::getInstance().getInt("MaxFrameCountLagAllowed", intToStr(maxFrameCountLagAllowed).c_str()); maxFrameCountLagAllowedEver = Config::getInstance().getInt("MaxFrameCountLagAllowedEver", intToStr(maxFrameCountLagAllowedEver).c_str()); @@ -415,6 +416,17 @@ std::pair ServerInterface::clientLagCheck(ConnectionSlot *connectionS std::pair clientLagExceededOrWarned = std::make_pair(false, false); static bool alreadyInLagCheck = false; + +// { +// if(connectionSlot != NULL && connectionSlot->isConnected() == true) { +// double clientLag = this->getCurrentFrameCount() - connectionSlot->getCurrentFrameCount(); +// double clientLagCount = (gameSettings.getNetworkFramePeriod() > 0 ? (clientLag / gameSettings.getNetworkFramePeriod()) : 0); +// double clientLagTime = difftime(time(NULL),connectionSlot->getLastReceiveCommandListTime()); +// +// printf("\n\nmaxClientLagTimeAllowedEver [%f] - [%f] alreadyInLagCheck = %d\n\n",maxClientLagTimeAllowedEver,clientLagTime,alreadyInLagCheck); +// } +// } + if(alreadyInLagCheck == true) { return clientLagExceededOrWarned; } @@ -455,11 +467,12 @@ std::pair ServerInterface::clientLagCheck(ConnectionSlot *connectionS */ // END test + // New lag check if((maxFrameCountLagAllowed > 0 && clientLagCount > maxFrameCountLagAllowed) || (maxClientLagTimeAllowed > 0 && clientLagTime > maxClientLagTimeAllowed) || - ((maxFrameCountLagAllowedEver > 0 && clientLagCount > maxFrameCountLagAllowedEver) || - maxClientLagTimeAllowedEver > 0 && clientLagTime > maxClientLagTimeAllowedEver)) { + (maxFrameCountLagAllowedEver > 0 && clientLagCount > maxFrameCountLagAllowedEver) || + ( maxClientLagTimeAllowedEver > 0 && clientLagTime > maxClientLagTimeAllowedEver)) { clientLagExceededOrWarned.first = true; Lang &lang= Lang::getInstance(); @@ -472,8 +485,8 @@ std::pair ServerInterface::clientLagCheck(ConnectionSlot *connectionS msgTemplate = lang.get("ClientLagDropping",languageList[i]); } if(gameSettings.getNetworkPauseGameForLaggedClients() == true && - (maxFrameCountLagAllowedEver <= 0 || clientLagCount <= maxFrameCountLagAllowedEver || - maxClientLagTimeAllowedEver <= 0 || clientLagTime <= maxClientLagTimeAllowedEver)) { + ((maxFrameCountLagAllowedEver <= 0 || clientLagCount <= maxFrameCountLagAllowedEver) && + (maxClientLagTimeAllowedEver <= 0 || clientLagTime <= maxClientLagTimeAllowedEver))) { msgTemplate = "PAUSING GAME TEMPORARILY for %s, exceeded max allowed LAG count of %f [time = %f], clientLag = %f [%f], waiting for client to catch up..."; if(lang.hasString("ClientLagPausing") == true) { msgTemplate = lang.get("ClientLagPausing",languageList[i]); @@ -672,6 +685,7 @@ void ServerInterface::checForLaggingClients(std::map &mapSlotSignalled std::map &eventList, std::map &socketTriggeredList, std::vector &errorMsgList) { + bool lastGlobalLagCheckTimeUpdate = false; time_t waitForClientsElapsed = time(NULL); time_t waitForThreadElapsed = time(NULL); std::map slotsCompleted; @@ -752,8 +766,44 @@ void ServerInterface::checForLaggingClients(std::map &mapSlotSignalled errorMsgList.push_back(ex.what()); } } + + if(connectionSlot != NULL && connectionSlot->isConnected() == true) { + try { + if(gameHasBeenInitiated == true && + difftime(time(NULL),lastGlobalLagCheckTime) >= LAG_CHECK_GRACE_PERIOD) { + + printf("\n\n\n^^^^^^^^^^^^^^ PART A\n\n\n"); + + // New lag check + std::pair clientLagExceededOrWarned = std::make_pair(false,false); + if( gameHasBeenInitiated == true && connectionSlot != NULL && + connectionSlot->isConnected() == true) { + + printf("\n\n\n^^^^^^^^^^^^^^ PART B\n\n\n"); + + lastGlobalLagCheckTimeUpdate = true; + clientLagExceededOrWarned = clientLagCheck(connectionSlot,slotsWarnedList[i]); + + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] clientLagExceededOrWarned.first = %d, clientLagExceededOrWarned.second = %d, gameSettings.getNetworkPauseGameForLaggedClients() = %d\n",__FILE__,__FUNCTION__,__LINE__,clientLagExceededOrWarned.first,clientLagExceededOrWarned.second,gameSettings.getNetworkPauseGameForLaggedClients()); + + if(clientLagExceededOrWarned.first == true) { + slotsWarnedList[i] = true; + } + } + } + } + catch(const exception &ex) { + SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what()); + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error detected [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what()); + errorMsgList.push_back(ex.what()); + } + } } } + + if(lastGlobalLagCheckTimeUpdate == true) { + lastGlobalLagCheckTime = time(NULL); + } } void ServerInterface::executeNetworkCommandsFromClients() { @@ -825,26 +875,36 @@ void ServerInterface::update() { Chrono chrono; if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start(); + //printf("\nServerInterface::update -- A\n"); + std::vector errorMsgList; try { // The first thing we will do is check all clients to ensure they have // properly identified themselves within the alloted time period validateConnectedClients(); + //printf("\nServerInterface::update -- B\n"); + if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); processTextMessageQueue(); processBroadCastMessageQueue(); + //printf("\nServerInterface::update -- C\n"); + if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); std::map socketTriggeredList; //update all slots updateSocketTriggeredList(socketTriggeredList); + //printf("\nServerInterface::update -- D\n"); + if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); if(gameHasBeenInitiated == false || socketTriggeredList.size() > 0) { + //printf("\nServerInterface::update -- E\n"); + std::map eventList; bool hasData = Socket::hasDataToRead(socketTriggeredList); @@ -885,11 +945,33 @@ void ServerInterface::update() { if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); } + else if(gameHasBeenInitiated == true && + difftime(time(NULL),lastGlobalLagCheckTime) >= LAG_CHECK_GRACE_PERIOD) { + //printf("\nServerInterface::update -- E1\n"); + + //std::map eventList; + std::map mapSlotSignalledList; + + checForLaggingClients(mapSlotSignalledList, eventList, socketTriggeredList,errorMsgList); + } if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); } + else if(gameHasBeenInitiated == true && + difftime(time(NULL),lastGlobalLagCheckTime) >= LAG_CHECK_GRACE_PERIOD) { + //printf("\nServerInterface::update -- F\n"); + + std::map eventList; + std::map mapSlotSignalledList; + + checForLaggingClients(mapSlotSignalledList, eventList, socketTriggeredList,errorMsgList); + } + + //printf("\nServerInterface::update -- G\n"); } catch(const exception &ex) { + //printf("\nServerInterface::update -- H\n"); + SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what()); if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] error detected [%s]\n",__FILE__,__FUNCTION__,__LINE__,ex.what()); errorMsgList.push_back(ex.what()); diff --git a/source/glest_game/network/server_interface.h b/source/glest_game/network/server_interface.h index c1809b67..191b9d5d 100644 --- a/source/glest_game/network/server_interface.h +++ b/source/glest_game/network/server_interface.h @@ -59,6 +59,8 @@ private: time_t gameStartTime; + time_t lastGlobalLagCheckTime; + SimpleTaskThread *publishToMasterserverThread; Mutex masterServerThreadAccessor; time_t lastMasterserverHeartbeatTime;