From 246f4b326ff9ec1d791c81357ca36aa9ce94858b Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Sat, 3 Mar 2012 23:59:44 +0000 Subject: [PATCH] - attempt to see if threaded client network receive improves performance (ThreadedNetworkClient=true to enable on a client) --- source/glest_game/game/game.h | 2 - source/glest_game/graphics/renderer.h | 5 +- source/glest_game/main/program.h | 2 +- .../glest_game/network/client_interface.cpp | 676 +++++++++++++----- source/glest_game/network/client_interface.h | 14 +- source/glest_game/network/network_interface.h | 4 +- .../glest_game/network/server_interface.cpp | 25 +- source/glest_game/network/server_interface.h | 3 + .../include/platform/posix/socket.h | 1 - 9 files changed, 533 insertions(+), 199 deletions(-) diff --git a/source/glest_game/game/game.h b/source/glest_game/game/game.h index 9afdb403..fd6e6a22 100644 --- a/source/glest_game/game/game.h +++ b/source/glest_game/game/game.h @@ -49,8 +49,6 @@ enum LoadGameItem { // // Main game class // ===================================================== - -//class Game: public ProgramState, public SimpleTaskCallbackInterface { class Game: public ProgramState, public FileCRCPreCacheThreadCallbackInterface { public: enum Speed{ diff --git a/source/glest_game/graphics/renderer.h b/source/glest_game/graphics/renderer.h index b0603a30..1403bd62 100644 --- a/source/glest_game/graphics/renderer.h +++ b/source/glest_game/graphics/renderer.h @@ -171,7 +171,10 @@ public: }; -class Renderer : public RendererInterface, public BaseRenderer, public SimpleTaskCallbackInterface { +class Renderer : public RendererInterface, + public BaseRenderer, + // This is for screen saver thread + public SimpleTaskCallbackInterface { public: //progress bar static const int maxProgressBar; diff --git a/source/glest_game/main/program.h b/source/glest_game/main/program.h index 1dbcfc55..3c723f0c 100644 --- a/source/glest_game/main/program.h +++ b/source/glest_game/main/program.h @@ -108,7 +108,7 @@ protected: // class Program // =============================== -class Program : public SimpleTaskCallbackInterface { +class Program { private: static const int maxTimes; SimpleTaskThread *soundThreadManager; diff --git a/source/glest_game/network/client_interface.cpp b/source/glest_game/network/client_interface.cpp index dfb12e84..23f4417e 100644 --- a/source/glest_game/network/client_interface.cpp +++ b/source/glest_game/network/client_interface.cpp @@ -48,6 +48,10 @@ const int ClientInterface::maxNetworkCommandListSendTimeWait = 4; ClientInterface::ClientInterface() : GameNetworkInterface() { if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] constructor for %p\n",__FILE__,__FUNCTION__,__LINE__,this); + networkCommandListThreadAccessor = new Mutex(); + networkCommandListThread = NULL; + cachedPendingCommandsIndex = 0; + clientSocket= NULL; sessionKey = 0; launchGame= false; @@ -66,9 +70,28 @@ ClientInterface::ClientInterface() : GameNetworkInterface() { this->setReceivedDataSynchCheck(false); } +void ClientInterface::shutdownNetworkCommandListThread() { + //MutexSafeWrapper safeMutex(masterServerThreadAccessor,CODE_AT_LINE); + + if(networkCommandListThread != NULL) { + time_t elapsed = time(NULL); + networkCommandListThread->signalQuit(); + for(;networkCommandListThread->canShutdown(false) == false && + difftime(time(NULL),elapsed) <= 15;) { + //sleep(150); + } + if(networkCommandListThread->canShutdown(true)) { + delete networkCommandListThread; + networkCommandListThread = NULL; + } + } +} + ClientInterface::~ClientInterface() { if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] destructor for %p\n",__FILE__,__FUNCTION__,__LINE__,this); + shutdownNetworkCommandListThread(); + if(clientSocket != NULL && clientSocket->isConnected() == true) { if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); @@ -90,6 +113,9 @@ ClientInterface::~ClientInterface() { delete clientSocket; clientSocket = NULL; + delete networkCommandListThreadAccessor; + networkCommandListThreadAccessor = NULL; + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } @@ -520,204 +546,484 @@ void ClientInterface::updateLobby() { } } +void ClientInterface::updateFrame(int *checkFrame) { + if(isConnected() == true && quit == false) { + Chrono chrono; + if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start(); + + int simulateLag = Config::getInstance().getInt("SimulateClientLag","0"); + bool done= false; + while(done == false) { + //wait for the next message + NetworkMessageType networkMessageType = waitForMessage(); + + // START: Test simulating lag for the client + if(simulateLag > 0) { + if(clientSimulationLagStartTime == 0) { + clientSimulationLagStartTime = time(NULL); + } + if(difftime(time(NULL),clientSimulationLagStartTime) <= Config::getInstance().getInt("SimulateClientLagDurationSeconds","0")) { + sleep(Config::getInstance().getInt("SimulateClientLag","0")); + } + } + // END: Test simulating lag for the client + + //check we have an expected message + //NetworkMessageType networkMessageType= getNextMessageType(); + + switch(networkMessageType) + { + case nmtCommandList: + { + + int waitCount = 0; + //make sure we read the message + time_t receiveTimeElapsed = time(NULL); + NetworkMessageCommandList networkMessageCommandList; + bool gotCmd = receiveMessage(&networkMessageCommandList); + if(gotCmd == false) { + throw runtime_error("error retrieving nmtCommandList returned false!"); + } + + // while(receiveMessage(&networkMessageCommandList) == false && + // isConnected() == true && + // difftime(time(NULL),receiveTimeElapsed) <= (messageWaitTimeout / 2000)) { + // waitCount++; + // } + + if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] receiveMessage took %lld msecs, waitCount = %d\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),waitCount); + if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start(); + //check that we are in the right frame + if(checkFrame != NULL) { + if(networkMessageCommandList.getFrameCount() != *checkFrame) { + string sErr = "Player: " + getHumanPlayerName() + + " got a Network synchronization error, frame counts do not match, server frameCount = " + + intToStr(networkMessageCommandList.getFrameCount()) + ", local frameCount = " + + intToStr(*checkFrame); + sendTextMessage(sErr,-1, true,""); + DisplayErrorMessage(sErr); + sleep(1); + + quit= true; + close(); + return; + } + } + + MutexSafeWrapper safeMutex(networkCommandListThreadAccessor,CODE_AT_LINE); + // give all commands + for(int i= 0; i < networkMessageCommandList.getCommandCount(); ++i) { + //pendingCommands.push_back(*networkMessageCommandList.getCommand(i)); + cachedPendingCommands[networkMessageCommandList.getFrameCount()].push_back(*networkMessageCommandList.getCommand(i)); + } + if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] transfer network commands took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + + done= true; + } + break; + + case nmtPing: + { + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtPing\n",__FILE__,__FUNCTION__); + + NetworkMessagePing networkMessagePing; + if(receiveMessage(&networkMessagePing)) { + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + lastPingInfo = networkMessagePing; + } + + 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()); + } + break; + + case nmtQuit: + { + time_t receiveTimeElapsed = time(NULL); + NetworkMessageQuit networkMessageQuit; + // while(receiveMessage(&networkMessageQuit) == false && + // isConnected() == true && + // difftime(time(NULL),receiveTimeElapsed) <= (messageWaitTimeout / 2000)) { + // } + bool gotCmd = receiveMessage(&networkMessageQuit); + if(gotCmd == false) { + throw runtime_error("error retrieving nmtQuit returned false!"); + } + + quit= true; + done= true; + } + break; + + case nmtText: + { + time_t receiveTimeElapsed = time(NULL); + NetworkMessageText networkMessageText; + // while(receiveMessage(&networkMessageText) == false && + // isConnected() == true && + // difftime(time(NULL),receiveTimeElapsed) <= (messageWaitTimeout / 1000)) { + // } + bool gotCmd = receiveMessage(&networkMessageText); + if(gotCmd == false) { + throw runtime_error("error retrieving nmtText returned false!"); + } + + 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()); + + ChatMsgInfo msg(networkMessageText.getText().c_str(),networkMessageText.getTeamIndex(),networkMessageText.getPlayerIndex(),networkMessageText.getTargetLanguage()); + this->addChatInfo(msg); + + 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()); + } + break; + + case nmtLaunch: + case nmtBroadCastSetup: + { + NetworkMessageLaunch networkMessageLaunch; + if(receiveMessage(&networkMessageLaunch)) { + if(networkMessageLaunch.getMessageType() == nmtLaunch) { + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got nmtLaunch\n",__FILE__,__FUNCTION__,__LINE__); + } + else if(networkMessageLaunch.getMessageType() == nmtBroadCastSetup) { + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got nmtBroadCastSetup\n",__FILE__,__FUNCTION__,__LINE__); + } + else { + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got networkMessageLaunch.getMessageType() = %d\n",__FILE__,__FUNCTION__,__LINE__,networkMessageLaunch.getMessageType()); + + char szBuf[1024]=""; + snprintf(szBuf,1023,"In [%s::%s Line: %d] Invalid networkMessageLaunch.getMessageType() = %d",__FILE__,__FUNCTION__,__LINE__,networkMessageLaunch.getMessageType()); + throw runtime_error(szBuf); + } + + networkMessageLaunch.buildGameSettings(&gameSettings); + + if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got networkMessageLaunch.getMessageType() = %d\n",__FILE__,__FUNCTION__,__LINE__,networkMessageLaunch.getMessageType()); + //replace server player by network + for(int i= 0; igetQuitStatus() == false && quit == false) { + updateFrame(NULL); + } + 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()); +} + +bool ClientInterface::getNetworkCommand(int frameCount, int currentCachedPendingCommandsIndex) { + bool result = false; + + //for(;quit == false;) { + MutexSafeWrapper safeMutex(networkCommandListThreadAccessor,CODE_AT_LINE); + if(cachedPendingCommands.find(frameCount) != cachedPendingCommands.end()) { + Commands &frameCmdList = cachedPendingCommands[frameCount]; + for(int i= 0; i < frameCmdList.size(); ++i) { + pendingCommands.push_back(frameCmdList[i]); + } + cachedPendingCommands.erase(frameCount); + + result = true; + //break; + } + else { + if(cachedPendingCommandsIndex > currentCachedPendingCommandsIndex) { + //break; + } + } + //} + + return result; +} + void ClientInterface::updateKeyframe(int frameCount) { currentFrameCount = frameCount; Chrono chrono; if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start(); + //chrono.start(); - int simulateLag = Config::getInstance().getInt("SimulateClientLag","0"); - bool done= false; - while(done == false) { - //wait for the next message - NetworkMessageType networkMessageType = waitForMessage(); - - // START: Test simulating lag for the client - if(simulateLag > 0) { - if(clientSimulationLagStartTime == 0) { - clientSimulationLagStartTime = time(NULL); - } - if(difftime(time(NULL),clientSimulationLagStartTime) <= Config::getInstance().getInt("SimulateClientLagDurationSeconds","0")) { - sleep(Config::getInstance().getInt("SimulateClientLag","0")); + if(quit == false) { + bool testThreaded = Config::getInstance().getBool("ThreadedNetworkClient","false"); + if(testThreaded == false) { + updateFrame(&frameCount); + Commands &frameCmdList = cachedPendingCommands[frameCount]; + for(int i= 0; i < frameCmdList.size(); ++i) { + pendingCommands.push_back(frameCmdList[i]); } + cachedPendingCommands.erase(frameCount); } - // END: Test simulating lag for the client - - //check we have an expected message - //NetworkMessageType networkMessageType= getNextMessageType(); - - switch(networkMessageType) - { - case nmtCommandList: - { - - int waitCount = 0; - //make sure we read the message - time_t receiveTimeElapsed = time(NULL); - NetworkMessageCommandList networkMessageCommandList; - bool gotCmd = receiveMessage(&networkMessageCommandList); - if(gotCmd == false) { - throw runtime_error("error retrieving nmtCommandList returned false!"); - } - -// while(receiveMessage(&networkMessageCommandList) == false && -// isConnected() == true && -// difftime(time(NULL),receiveTimeElapsed) <= (messageWaitTimeout / 2000)) { -// waitCount++; -// } - - if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] receiveMessage took %lld msecs, waitCount = %d\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),waitCount); - if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start(); - //check that we are in the right frame - if(networkMessageCommandList.getFrameCount() != frameCount) { - string sErr = "Player: " + getHumanPlayerName() + - " got a Network synchronization error, frame counts do not match, server frameCount = " + - intToStr(networkMessageCommandList.getFrameCount()) + ", local frameCount = " + - intToStr(frameCount); - sendTextMessage(sErr,-1, true,""); - DisplayErrorMessage(sErr); - sleep(1); - - quit= true; - close(); - return; - } - - // give all commands - for(int i= 0; i < networkMessageCommandList.getCommandCount(); ++i) { - pendingCommands.push_back(*networkMessageCommandList.getCommand(i)); - } - - if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] transfer network commands took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); - - done= true; + else { + if(networkCommandListThread == NULL) { + networkCommandListThread = new SimpleTaskThread(this,0,0); + networkCommandListThread->setUniqueID(__FILE__); + networkCommandListThread->start(); } - break; - case nmtPing: - { - if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtPing\n",__FILE__,__FUNCTION__); - - NetworkMessagePing networkMessagePing; - if(receiveMessage(&networkMessagePing)) { - if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - lastPingInfo = networkMessagePing; - } - - 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()); - } - break; - - case nmtQuit: - { - time_t receiveTimeElapsed = time(NULL); - NetworkMessageQuit networkMessageQuit; -// while(receiveMessage(&networkMessageQuit) == false && -// isConnected() == true && -// difftime(time(NULL),receiveTimeElapsed) <= (messageWaitTimeout / 2000)) { -// } - bool gotCmd = receiveMessage(&networkMessageQuit); - if(gotCmd == false) { - throw runtime_error("error retrieving nmtQuit returned false!"); - } - - quit= true; - done= true; - } - break; - - case nmtText: - { - time_t receiveTimeElapsed = time(NULL); - NetworkMessageText networkMessageText; -// while(receiveMessage(&networkMessageText) == false && -// isConnected() == true && -// difftime(time(NULL),receiveTimeElapsed) <= (messageWaitTimeout / 1000)) { -// } - bool gotCmd = receiveMessage(&networkMessageText); - if(gotCmd == false) { - throw runtime_error("error retrieving nmtText returned false!"); - } - - 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()); - - ChatMsgInfo msg(networkMessageText.getText().c_str(),networkMessageText.getTeamIndex(),networkMessageText.getPlayerIndex(),networkMessageText.getTargetLanguage()); - this->addChatInfo(msg); - - 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()); - } - break; - - case nmtLaunch: - case nmtBroadCastSetup: - { - NetworkMessageLaunch networkMessageLaunch; - if(receiveMessage(&networkMessageLaunch)) { - if(networkMessageLaunch.getMessageType() == nmtLaunch) { - if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got nmtLaunch\n",__FILE__,__FUNCTION__,__LINE__); - } - else if(networkMessageLaunch.getMessageType() == nmtBroadCastSetup) { - if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got nmtBroadCastSetup\n",__FILE__,__FUNCTION__,__LINE__); - } - else { - if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got networkMessageLaunch.getMessageType() = %d\n",__FILE__,__FUNCTION__,__LINE__,networkMessageLaunch.getMessageType()); - - char szBuf[1024]=""; - snprintf(szBuf,1023,"In [%s::%s Line: %d] Invalid networkMessageLaunch.getMessageType() = %d",__FILE__,__FUNCTION__,__LINE__,networkMessageLaunch.getMessageType()); - throw runtime_error(szBuf); - } - - networkMessageLaunch.buildGameSettings(&gameSettings); - - if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got networkMessageLaunch.getMessageType() = %d\n",__FILE__,__FUNCTION__,__LINE__,networkMessageLaunch.getMessageType()); - //replace server player by network - for(int i= 0; i 0) { +// if(clientSimulationLagStartTime == 0) { +// clientSimulationLagStartTime = time(NULL); +// } +// if(difftime(time(NULL),clientSimulationLagStartTime) <= Config::getInstance().getInt("SimulateClientLagDurationSeconds","0")) { +// sleep(Config::getInstance().getInt("SimulateClientLag","0")); +// } +// } +// // END: Test simulating lag for the client +// +// //check we have an expected message +// //NetworkMessageType networkMessageType= getNextMessageType(); +// +// switch(networkMessageType) +// { +// case nmtCommandList: +// { +// +// int waitCount = 0; +// //make sure we read the message +// time_t receiveTimeElapsed = time(NULL); +// NetworkMessageCommandList networkMessageCommandList; +// bool gotCmd = receiveMessage(&networkMessageCommandList); +// if(gotCmd == false) { +// throw runtime_error("error retrieving nmtCommandList returned false!"); +// } +// +//// while(receiveMessage(&networkMessageCommandList) == false && +//// isConnected() == true && +//// difftime(time(NULL),receiveTimeElapsed) <= (messageWaitTimeout / 2000)) { +//// waitCount++; +//// } +// +// if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] receiveMessage took %lld msecs, waitCount = %d\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),waitCount); +// if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start(); +// //check that we are in the right frame +// if(networkMessageCommandList.getFrameCount() != frameCount) { +// string sErr = "Player: " + getHumanPlayerName() + +// " got a Network synchronization error, frame counts do not match, server frameCount = " + +// intToStr(networkMessageCommandList.getFrameCount()) + ", local frameCount = " + +// intToStr(frameCount); +// sendTextMessage(sErr,-1, true,""); +// DisplayErrorMessage(sErr); +// sleep(1); +// +// quit= true; +// close(); +// return; +// } +// +// // give all commands +// for(int i= 0; i < networkMessageCommandList.getCommandCount(); ++i) { +// pendingCommands.push_back(*networkMessageCommandList.getCommand(i)); +// } +// +// if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] transfer network commands took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); +// +// done= true; +// } +// break; +// +// case nmtPing: +// { +// if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtPing\n",__FILE__,__FUNCTION__); +// +// NetworkMessagePing networkMessagePing; +// if(receiveMessage(&networkMessagePing)) { +// if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); +// lastPingInfo = networkMessagePing; +// } +// +// 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()); +// } +// break; +// +// case nmtQuit: +// { +// time_t receiveTimeElapsed = time(NULL); +// NetworkMessageQuit networkMessageQuit; +//// while(receiveMessage(&networkMessageQuit) == false && +//// isConnected() == true && +//// difftime(time(NULL),receiveTimeElapsed) <= (messageWaitTimeout / 2000)) { +//// } +// bool gotCmd = receiveMessage(&networkMessageQuit); +// if(gotCmd == false) { +// throw runtime_error("error retrieving nmtQuit returned false!"); +// } +// +// quit= true; +// done= true; +// } +// break; +// +// case nmtText: +// { +// time_t receiveTimeElapsed = time(NULL); +// NetworkMessageText networkMessageText; +//// while(receiveMessage(&networkMessageText) == false && +//// isConnected() == true && +//// difftime(time(NULL),receiveTimeElapsed) <= (messageWaitTimeout / 1000)) { +//// } +// bool gotCmd = receiveMessage(&networkMessageText); +// if(gotCmd == false) { +// throw runtime_error("error retrieving nmtText returned false!"); +// } +// +// 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()); +// +// ChatMsgInfo msg(networkMessageText.getText().c_str(),networkMessageText.getTeamIndex(),networkMessageText.getPlayerIndex(),networkMessageText.getTargetLanguage()); +// this->addChatInfo(msg); +// +// 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()); +// } +// break; +// +// case nmtLaunch: +// case nmtBroadCastSetup: +// { +// NetworkMessageLaunch networkMessageLaunch; +// if(receiveMessage(&networkMessageLaunch)) { +// if(networkMessageLaunch.getMessageType() == nmtLaunch) { +// if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got nmtLaunch\n",__FILE__,__FUNCTION__,__LINE__); +// } +// else if(networkMessageLaunch.getMessageType() == nmtBroadCastSetup) { +// if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got nmtBroadCastSetup\n",__FILE__,__FUNCTION__,__LINE__); +// } +// else { +// if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got networkMessageLaunch.getMessageType() = %d\n",__FILE__,__FUNCTION__,__LINE__,networkMessageLaunch.getMessageType()); +// +// char szBuf[1024]=""; +// snprintf(szBuf,1023,"In [%s::%s Line: %d] Invalid networkMessageLaunch.getMessageType() = %d",__FILE__,__FUNCTION__,__LINE__,networkMessageLaunch.getMessageType()); +// throw runtime_error(szBuf); +// } +// +// networkMessageLaunch.buildGameSettings(&gameSettings); +// +// if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Lined: %d] got networkMessageLaunch.getMessageType() = %d\n",__FILE__,__FUNCTION__,__LINE__,networkMessageLaunch.getMessageType()); +// //replace server player by network +// for(int i= 0; i 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + //printf("In [%s::%s Line: %d] took %lld msecs\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); } bool ClientInterface::isMasterServerAdminOverride() { diff --git a/source/glest_game/network/client_interface.h b/source/glest_game/network/client_interface.h index 52eaaa5b..05652376 100644 --- a/source/glest_game/network/client_interface.h +++ b/source/glest_game/network/client_interface.h @@ -28,7 +28,8 @@ namespace Glest{ namespace Game{ // class ClientInterface // ===================================================== -class ClientInterface: public GameNetworkInterface { +class ClientInterface: public GameNetworkInterface, + public SimpleTaskCallbackInterface { private: static const int messageWaitTimeout; static const int waitSleepTime; @@ -57,6 +58,11 @@ private: int sessionKey; int serverFTPPort; + SimpleTaskThread *networkCommandListThread; + Mutex *networkCommandListThreadAccessor; + std::map cachedPendingCommands; //commands ready to be given + uint64 cachedPendingCommandsIndex; + public: ClientInterface(); virtual ~ClientInterface(); @@ -120,11 +126,17 @@ public: void broadcastGameSetup(const GameSettings *gameSettings); void broadcastGameStart(const GameSettings *gameSettings); + virtual void simpleTask(BaseThread *callingThread); + protected: Mutex * getServerSynchAccessor() { return NULL; } NetworkMessageType waitForMessage(); bool shouldDiscardNetworkMessage(NetworkMessageType networkMessageType); + + void updateFrame(int *checkFrame); + void shutdownNetworkCommandListThread(); + bool getNetworkCommand(int frameCount, int currentCachedPendingCommandsIndex); }; }}//end namespace diff --git a/source/glest_game/network/network_interface.h b/source/glest_game/network/network_interface.h index 8f07705c..27ae42d1 100644 --- a/source/glest_game/network/network_interface.h +++ b/source/glest_game/network/network_interface.h @@ -171,10 +171,10 @@ public: // ===================================================== class GameNetworkInterface: public NetworkInterface { -private: - typedef vector Commands; protected: + typedef vector Commands; + Commands requestedCommands; //commands requested by the user Commands pendingCommands; //commands ready to be given bool quit; diff --git a/source/glest_game/network/server_interface.cpp b/source/glest_game/network/server_interface.cpp index c5800be1..3a163d6c 100644 --- a/source/glest_game/network/server_interface.cpp +++ b/source/glest_game/network/server_interface.cpp @@ -189,6 +189,23 @@ void ServerInterface::setPublishEnabled(bool value) { } } +void ServerInterface::shutdownMasterserverPublishThread() { + MutexSafeWrapper safeMutex(masterServerThreadAccessor,CODE_AT_LINE); + + if(publishToMasterserverThread != NULL) { + time_t elapsed = time(NULL); + publishToMasterserverThread->signalQuit(); + for(;publishToMasterserverThread->canShutdown(false) == false && + difftime(time(NULL),elapsed) <= 15;) { + //sleep(150); + } + if(publishToMasterserverThread->canShutdown(true)) { + delete publishToMasterserverThread; + publishToMasterserverThread = NULL; + } + } +} + ServerInterface::~ServerInterface() { //printf("===> Destructor for ServerInterface\n"); @@ -214,10 +231,7 @@ ServerInterface::~ServerInterface() { delete ftpServer; ftpServer = NULL; } - MutexSafeWrapper safeMutex(masterServerThreadAccessor,CODE_AT_LINE); - delete publishToMasterserverThread; - publishToMasterserverThread = NULL; - safeMutex.ReleaseLock(); + shutdownMasterserverPublishThread(); lastMasterserverHeartbeatTime = 0; if(needToRepublishToMasterserver == true) { @@ -1703,9 +1717,8 @@ bool ServerInterface::launchGame(const GameSettings *gameSettings) { if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] needToRepublishToMasterserver = %d\n",__FILE__,__FUNCTION__,__LINE__,needToRepublishToMasterserver); + shutdownMasterserverPublishThread(); MutexSafeWrapper safeMutex(masterServerThreadAccessor,CODE_AT_LINE); - delete publishToMasterserverThread; - publishToMasterserverThread = NULL; lastMasterserverHeartbeatTime = 0; if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] ftpServer = %p\n",__FILE__,__FUNCTION__,__LINE__,ftpServer); diff --git a/source/glest_game/network/server_interface.h b/source/glest_game/network/server_interface.h index ec48d5a9..5a46477d 100644 --- a/source/glest_game/network/server_interface.h +++ b/source/glest_game/network/server_interface.h @@ -35,6 +35,7 @@ namespace Glest{ namespace Game{ class ServerInterface: public GameNetworkInterface, public ConnectionSlotCallbackInterface, + // This is for publishing game status to the masterserver public SimpleTaskCallbackInterface, public FTPClientValidationInterface { @@ -212,6 +213,8 @@ protected: void checkForLaggingClients(std::map &mapSlotSignalledList, std::map &eventList, std::map &socketTriggeredList,std::vector &errorMsgList); void executeNetworkCommandsFromClients(); void dispatchPendingChatMessages(std::vector &errorMsgList); + + void shutdownMasterserverPublishThread(); }; }}//end namespace diff --git a/source/shared_lib/include/platform/posix/socket.h b/source/shared_lib/include/platform/posix/socket.h index 351b8928..23939155 100644 --- a/source/shared_lib/include/platform/posix/socket.h +++ b/source/shared_lib/include/platform/posix/socket.h @@ -102,7 +102,6 @@ public: }; #endif -//class Socket : public SimpleTaskCallbackInterface { class Socket { protected: