From 00860813b2f887aed0207701162539382a90ddc0 Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Mon, 28 Jun 2010 00:21:12 +0000 Subject: [PATCH] - bugfixes for LAG checking: - proper disconnect for clients passed MAX lag - proper lag packet time initialzation for clients sending LAG update info to the server --- .../glest_game/network/client_interface.cpp | 5 +- .../glest_game/network/server_interface.cpp | 98 ++++++++++--------- source/glest_game/network/server_interface.h | 2 +- 3 files changed, 59 insertions(+), 46 deletions(-) diff --git a/source/glest_game/network/client_interface.cpp b/source/glest_game/network/client_interface.cpp index db2110df0..7dd27d609 100755 --- a/source/glest_game/network/client_interface.cpp +++ b/source/glest_game/network/client_interface.cpp @@ -37,7 +37,7 @@ namespace Glest{ namespace Game{ const int ClientInterface::messageWaitTimeout= 10000; //10 seconds const int ClientInterface::waitSleepTime= 10; -const int ClientInterface::maxNetworkCommandListSendTimeWait = 5; +const int ClientInterface::maxNetworkCommandListSendTimeWait = 4; ClientInterface::ClientInterface(){ clientSocket= NULL; @@ -682,6 +682,9 @@ void ClientInterface::waitUntilReady(Checksum* checksum) { //delay the start a bit, so clients have more room to get messages //sleep(GameConstants::networkExtraLatency); + // This triggers LAG update packets to begin as required + lastNetworkCommandListSendTime = time(NULL); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END\n",__FILE__,__FUNCTION__); } diff --git a/source/glest_game/network/server_interface.cpp b/source/glest_game/network/server_interface.cpp index 551b2c1b4..15e125fb0 100644 --- a/source/glest_game/network/server_interface.cpp +++ b/source/glest_game/network/server_interface.cpp @@ -45,10 +45,14 @@ double warnFrameCountLagPercent = 0.65; // Should we wait for lagged clients instead of disconnect them? bool pauseGameForLaggedClients = false; +// Seconds grace period before we start checking LAG +double LAG_CHECK_GRACE_PERIOD = 15; + ServerInterface::ServerInterface(){ gameHasBeenInitiated = false; gameSettingsUpdateCount = 0; currentFrameCount = 0; + gameStartTime = 0; enabledThreadedClientCommandBroadcast = Config::getInstance().getBool("EnableThreadedClientCommandBroadcast","false"); maxFrameCountLagAllowed = Config::getInstance().getInt("MaxFrameCountLagAllowed",intToStr(maxFrameCountLagAllowed).c_str()); @@ -218,58 +222,60 @@ void ServerInterface::updateSlot(ConnectionSlotEvent *event) { // Only call when client has just sent us data bool ServerInterface::clientLagCheck(ConnectionSlot* connectionSlot) { bool clientLagExceeded = false; - if(connectionSlot != NULL && connectionSlot->isConnected() == true) { - int clientLag = this->getCurrentFrameCount() - connectionSlot->getCurrentFrameCount(); - int clientLagCount = (gameSettings.getNetworkFramePeriod() > 0 ? (clientLag / gameSettings.getNetworkFramePeriod()) : 0); - connectionSlot->setCurrentLagCount(clientLagCount); + if(difftime(time(NULL),gameStartTime) >= LAG_CHECK_GRACE_PERIOD) { + if(connectionSlot != NULL && connectionSlot->isConnected() == true) { + int clientLag = this->getCurrentFrameCount() - connectionSlot->getCurrentFrameCount(); + int clientLagCount = (gameSettings.getNetworkFramePeriod() > 0 ? (clientLag / gameSettings.getNetworkFramePeriod()) : 0); + connectionSlot->setCurrentLagCount(clientLagCount); - if(this->getCurrentFrameCount() > 0) { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, clientLag = %d, clientLagCount = %d, this->getCurrentFrameCount() = %d, connectionSlot->getCurrentFrameCount() = %d\n",__FILE__,__FUNCTION__,__LINE__,connectionSlot->getPlayerIndex(),clientLag,clientLagCount,this->getCurrentFrameCount(),connectionSlot->getCurrentFrameCount()); - } - - // New lag check - if(maxFrameCountLagAllowed > 0 && clientLagCount > maxFrameCountLagAllowed) { - clientLagExceeded = true; - char szBuf[4096]=""; - - const char* msgTemplate = "%s exceeded max allowed LAG count of %d, clientLag = %d, disconnecting client."; - if(pauseGameForLaggedClients == true) { - msgTemplate = "%s exceeded max allowed LAG count of %d, clientLag = %d, pausing game to wait for client to catch up..."; + if(this->getCurrentFrameCount() > 0) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] playerIndex = %d, clientLag = %d, clientLagCount = %d, this->getCurrentFrameCount() = %d, connectionSlot->getCurrentFrameCount() = %d\n",__FILE__,__FUNCTION__,__LINE__,connectionSlot->getPlayerIndex(),clientLag,clientLagCount,this->getCurrentFrameCount(),connectionSlot->getCurrentFrameCount()); } -#ifdef WIN32 - _snprintf(szBuf,4095,msgTemplate,Config::getInstance().getString("NetPlayerName",Socket::getHostName().c_str()).c_str(),maxFrameCountLagAllowed,clientLagCount); -#else - snprintf(szBuf,4095,msgTemplate,Config::getInstance().getString("NetPlayerName",Socket::getHostName().c_str()).c_str(),maxFrameCountLagAllowed,clientLagCount); -#endif - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,szBuf); - - string sMsg = szBuf; - sendTextMessage(sMsg,-1); - - if(pauseGameForLaggedClients == true) { - connectionSlot->close(); - } - } - // New lag check warning - else if(maxFrameCountLagAllowed > 0 && warnFrameCountLagPercent > 0 && - (clientLagCount > (maxFrameCountLagAllowed * warnFrameCountLagPercent))) { - if(connectionSlot->getLagCountWarning() == false) { - connectionSlot->setLagCountWarning(true); + // New lag check + if(maxFrameCountLagAllowed > 0 && clientLagCount > maxFrameCountLagAllowed) { + clientLagExceeded = true; char szBuf[4096]=""; -#ifdef WIN32 - _snprintf(szBuf,4095,"%s may exceed max allowed LAG count of %d, clientLag = %d, WARNING...",Config::getInstance().getString("NetPlayerName",Socket::getHostName().c_str()).c_str(),maxFrameCountLagAllowed,clientLagCount); -#else - snprintf(szBuf,4095,"%s may exceed max allowed LAG count of %d, clientLag = %d, WARNING...",Config::getInstance().getString("NetPlayerName",Socket::getHostName().c_str()).c_str(),maxFrameCountLagAllowed,clientLagCount); -#endif + + const char* msgTemplate = "%s exceeded max allowed LAG count of %d, clientLag = %d, disconnecting client."; + if(pauseGameForLaggedClients == true) { + msgTemplate = "%s exceeded max allowed LAG count of %d, clientLag = %d, pausing game to wait for client to catch up..."; + } + #ifdef WIN32 + _snprintf(szBuf,4095,msgTemplate,Config::getInstance().getString("NetPlayerName",Socket::getHostName().c_str()).c_str(),maxFrameCountLagAllowed,clientLagCount); + #else + snprintf(szBuf,4095,msgTemplate,Config::getInstance().getString("NetPlayerName",Socket::getHostName().c_str()).c_str(),maxFrameCountLagAllowed,clientLagCount); + #endif SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,szBuf); string sMsg = szBuf; sendTextMessage(sMsg,-1); + + if(pauseGameForLaggedClients == false) { + connectionSlot->close(); + } + } + // New lag check warning + else if(maxFrameCountLagAllowed > 0 && warnFrameCountLagPercent > 0 && + (clientLagCount > (maxFrameCountLagAllowed * warnFrameCountLagPercent))) { + if(connectionSlot->getLagCountWarning() == false) { + connectionSlot->setLagCountWarning(true); + + char szBuf[4096]=""; + #ifdef WIN32 + _snprintf(szBuf,4095,"%s may exceed max allowed LAG count of %d, clientLag = %d, WARNING...",Config::getInstance().getString("NetPlayerName",Socket::getHostName().c_str()).c_str(),maxFrameCountLagAllowed,clientLagCount); + #else + snprintf(szBuf,4095,"%s may exceed max allowed LAG count of %d, clientLag = %d, WARNING...",Config::getInstance().getString("NetPlayerName",Socket::getHostName().c_str()).c_str(),maxFrameCountLagAllowed,clientLagCount); + #endif + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,szBuf); + + string sMsg = szBuf; + sendTextMessage(sMsg,-1); + } + } + else if(connectionSlot->getLagCountWarning() == true) { + connectionSlot->setLagCountWarning(false); } - } - else if(connectionSlot->getLagCountWarning() == true) { - connectionSlot->setLagCountWarning(false); } } @@ -345,6 +351,7 @@ void ServerInterface::update() { ConnectionSlot* connectionSlot = slots[i]; if(connectionSlot != NULL && slotsCompleted.find(i) == slotsCompleted.end()) { std::vector errorList = connectionSlot->getThreadErrorList(); + // Show any collected errors from threads if(errorList.size() > 0) { for(int iErrIdx = 0; iErrIdx < errorList.size(); ++iErrIdx) { string &sErr = errorList[iErrIdx]; @@ -353,6 +360,7 @@ void ServerInterface::update() { connectionSlot->clearThreadErrorList(); } + // Not done waiting for data yet if(connectionSlot->updateCompleted() == false) { threadsDone = false; break; @@ -374,7 +382,7 @@ void ServerInterface::update() { } } } - sleep(0); + //sleep(0); } // Step #3 dispatch network commands to the pending list so that they are done in proper order @@ -670,6 +678,8 @@ void ServerInterface::waitUntilReady(Checksum* checksum){ } } + gameStartTime = time(NULL); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s] END\n",__FUNCTION__); } diff --git a/source/glest_game/network/server_interface.h b/source/glest_game/network/server_interface.h index b4534a54e..13c99cd6e 100644 --- a/source/glest_game/network/server_interface.h +++ b/source/glest_game/network/server_interface.h @@ -39,7 +39,7 @@ private: Mutex serverSynchAccessor; int currentFrameCount; - //ConnectionSlotThread* slotThreads[GameConstants::maxPlayers]; + time_t gameStartTime; public: ServerInterface();