From 7d8af94a44ab7dfa824d54cae8817144bf6b55a0 Mon Sep 17 00:00:00 2001 From: SoftCoder Date: Wed, 8 Jan 2014 12:48:56 -0800 Subject: [PATCH] - attempt to fix null pointer segfault on masterserver found by tomreyn --- source/glest_game/game/commander.cpp | 11 +- source/glest_game/game/game.cpp | 74 +++++--- .../menu/menu_state_custom_game.cpp | 166 +++++++++--------- source/glest_game/network/connection_slot.cpp | 12 +- source/glest_game/network/connection_slot.h | 3 +- .../glest_game/network/server_interface.cpp | 8 +- source/glest_game/network/server_interface.h | 3 +- 7 files changed, 158 insertions(+), 119 deletions(-) diff --git a/source/glest_game/game/commander.cpp b/source/glest_game/game/commander.cpp index fe2ecdad..c978daee 100644 --- a/source/glest_game/game/commander.cpp +++ b/source/glest_game/game/commander.cpp @@ -764,14 +764,21 @@ void Commander::giveNetworkCommand(NetworkCommand* networkCommand) const { if(gameNetworkInterface != NULL) { ServerInterface *server = networkManager.getServerInterface(); if(server->isClientConnected(playerIndex) == true) { - ConnectionSlot *slot = server->getSlot(playerIndex); + + MutexSafeWrapper safeMutex(server->getSlotMutex(playerIndex),CODE_AT_LINE); + ConnectionSlot *slot = server->getSlot(playerIndex,false); if(slot != NULL) { + safeMutex.ReleaseLock(true); NetworkMessageQuit networkMessageQuit; slot->sendMessage(&networkMessageQuit); sleep(5); //printf("Sending nctDisconnectNetworkPlayer\n"); - slot->close(); + safeMutex.Lock(); + slot = server->getSlot(playerIndex,false); + if(slot != NULL) { + slot->close(); + } } } } diff --git a/source/glest_game/game/game.cpp b/source/glest_game/game/game.cpp index 25e3172d..604137e8 100644 --- a/source/glest_game/game/game.cpp +++ b/source/glest_game/game/game.cpp @@ -1638,7 +1638,9 @@ void Game::setupPopupMenus(bool checkClientAdminOverrideOnly) { if(serverInterface != NULL && checkClientAdminOverrideOnly == true) { for(int i = 0; i < world.getFactionCount(); ++i) { Faction *faction = world.getFaction(i); - ConnectionSlot *slot = serverInterface->getSlot(faction->getStartLocationIndex()); + + MutexSafeWrapper safeMutex(serverInterface->getSlotMutex(faction->getStartLocationIndex()),CODE_AT_LINE); + ConnectionSlot *slot = serverInterface->getSlot(faction->getStartLocationIndex(),false); if(slot != NULL && slot->getConnectHasHandshaked() == true && slot->getCurrentFrameCount() <= 0) { //printf("Connected slot can be disconnected: %d\n",slot->getPlayerIndex()); @@ -2338,7 +2340,9 @@ void Game::update() { bool clientNeedsGameSetup = false; for(int i = 0; i < world.getFactionCount(); ++i) { Faction *faction = world.getFaction(i); - ConnectionSlot *slot = server->getSlot(faction->getStartLocationIndex()); + + MutexSafeWrapper safeMutex(server->getSlotMutex(faction->getStartLocationIndex()),CODE_AT_LINE); + ConnectionSlot *slot = server->getSlot(faction->getStartLocationIndex(),false); if(slot != NULL && slot->getPauseForInGameConnection() == true) { clientNeedsGameSetup = true; break; @@ -2362,10 +2366,13 @@ void Game::update() { //printf("Slot: %d faction name: %s GS faction: %s\n",i,faction->getType()->getName().c_str(),server->gameSettings.getFactionTypeName(i).c_str()); server->gameSettings.setFactionControl(i,ctNetwork); - ConnectionSlot *slot = server->getSlot(faction->getStartLocationIndex()); + + MutexSafeWrapper safeMutex(server->getSlotMutex(faction->getStartLocationIndex()),CODE_AT_LINE); + ConnectionSlot *slot = server->getSlot(faction->getStartLocationIndex(),false); server->gameSettings.setNetworkPlayerName(i,slot->getName()); server->gameSettings.setNetworkPlayerUUID(i,slot->getUUID()); server->gameSettings.setNetworkPlayerPlatform(i,slot->getPlatform()); + safeMutex.ReleaseLock(); server->gameSettings.setNetworkPlayerStatuses(i,npst_None); this->gameSettings.setFactionControl(i,ctNetwork); @@ -2382,7 +2389,8 @@ void Game::update() { for(int i = 0; i < world.getFactionCount(); ++i) { Faction *faction = world.getFaction(i); - ConnectionSlot *slot = server->getSlot(faction->getStartLocationIndex()); + MutexSafeWrapper safeMutex(server->getSlotMutex(faction->getStartLocationIndex()),CODE_AT_LINE); + ConnectionSlot *slot = server->getSlot(faction->getStartLocationIndex(),false); if(slot != NULL && slot->getPauseForInGameConnection() == true) { slot->setPauseForInGameConnection(false); } @@ -2399,7 +2407,9 @@ void Game::update() { bool pauseAndSaveGameForNewClient = false; for(int i = 0; i < world.getFactionCount(); ++i) { Faction *faction = world.getFaction(i); - ConnectionSlot *slot = server->getSlot(faction->getStartLocationIndex()); + + MutexSafeWrapper safeMutex(server->getSlotMutex(faction->getStartLocationIndex()),CODE_AT_LINE); + ConnectionSlot *slot = server->getSlot(faction->getStartLocationIndex(),false); if(slot != NULL && slot->getStartInGameConnectionLaunch() == true) { //slot->setStartInGameConnectionLaunch(false); @@ -2407,6 +2417,7 @@ void Game::update() { } if(slot != NULL && slot->getJoinGameInProgress() == true) { //printf("$$$ signalling client to start game [deleting AI player] factionIndex: %d slot: %d startlocation: %d!\n",i,slot->getPlayerIndex(),faction->getStartLocationIndex()); + safeMutex.ReleaseLock(); this->gameSettings.setFactionControl(i,ctNetwork); this->gameSettings.setNetworkPlayerName(i,server->gameSettings.getNetworkPlayerName(i)); @@ -2430,10 +2441,15 @@ void Game::update() { else if((slot == NULL || slot->isConnected() == false) && this->gameSettings.getFactionControl(i) == ctNetwork && aiInterfaces[i] == NULL) { + + safeMutex.ReleaseLock(); faction->setFactionDisconnectHandled(false); //this->gameSettings.setNetworkPlayerName(i,lang.getString("AI") + intToStr(i+1)); //server->gameSettings.setNetworkPlayerName(i,lang.getString("AI") + intToStr(i+1)); } + else { + safeMutex.ReleaseLock(); + } } if(pauseAndSaveGameForNewClient == true && pausedForJoinGame == false && @@ -2454,10 +2470,11 @@ void Game::update() { if(server->getUnPauseForInGameConnection() == true) { //printf("^^^ getUnPauseForInGameConnection triggered!\n"); - //this->speed = 1; for(int i = 0; i < world.getFactionCount(); ++i) { Faction *faction = world.getFaction(i); - ConnectionSlot *slot = server->getSlot(faction->getStartLocationIndex()); + + MutexSafeWrapper safeMutex(server->getSlotMutex(faction->getStartLocationIndex()),CODE_AT_LINE); + ConnectionSlot *slot = server->getSlot(faction->getStartLocationIndex(),false); if(slot != NULL && slot->getUnPauseForInGameConnection() == true) { slot->setUnPauseForInGameConnection(false); faction->setFactionDisconnectHandled(false); @@ -2465,24 +2482,10 @@ void Game::update() { } //printf("Resuming game for join in progress game resumeRequestSent: %d...\n",resumeRequestSent); - //commander.tryResumeGame(true,false); if(pausedBeforeJoinGame == false && resumeRequestSent == false) { commander.tryResumeGame(true,true); resumeRequestSent = true; } - -// server->setAllowInGameConnections(false); -// for(int i = 0; i < world.getFactionCount(); ++i) { -// Faction *faction = world.getFaction(i); -// ConnectionSlot *slot = server->getSlot(faction->getStartLocationIndex()); -// if(slot != NULL && slot->isConnected() == false) { -// server->setAllowInGameConnections(false); -// server->removeSlot(faction->getStartLocationIndex()); -// } -// } - - //server->shutdownFTPServer(); - //return; } else if(server->getStartInGameConnectionLaunch() == true) { bool saveNetworkGame = false; @@ -2490,7 +2493,9 @@ void Game::update() { ServerInterface *server = NetworkManager::getInstance().getServerInterface(); for(int i = 0; i < world.getFactionCount(); ++i) { Faction *faction = world.getFaction(i); - ConnectionSlot *slot = server->getSlot(faction->getStartLocationIndex()); + + MutexSafeWrapper safeMutex(server->getSlotMutex(faction->getStartLocationIndex()),CODE_AT_LINE); + ConnectionSlot *slot = server->getSlot(faction->getStartLocationIndex(),false); if(slot != NULL && slot->getJoinGameInProgress() == true && slot->getStartInGameConnectionLaunch() == true && slot->getSentSavedGameInfo() == false) { @@ -2532,13 +2537,20 @@ void Game::update() { for(int i = 0; i < world.getFactionCount(); ++i) { Faction *faction = world.getFaction(i); - ConnectionSlot *slot = server->getSlot(faction->getStartLocationIndex()); + + MutexSafeWrapper safeMutex(server->getSlotMutex(faction->getStartLocationIndex()),CODE_AT_LINE); + ConnectionSlot *slot = server->getSlot(faction->getStartLocationIndex(),false); if(slot != NULL && slot->getJoinGameInProgress() == true && slot->getSentSavedGameInfo() == false) { - NetworkMessageReady networkMessageReady(0); + + safeMutex.ReleaseLock(); + NetworkMessageReady networkMessageReady(0); slot->sendMessage(&networkMessageReady); - slot->setSentSavedGameInfo(true); + slot = server->getSlot(faction->getStartLocationIndex(),false); + if(slot != NULL) { + slot->setSentSavedGameInfo(true); + } } } } @@ -3759,7 +3771,9 @@ void Game::mouseDownLeft(int x, int y) { bool isSlotJoinInProgressClient = false; if(serverInterface != NULL) { - ConnectionSlot *slot = serverInterface->getSlot(faction->getStartLocationIndex()); + + MutexSafeWrapper safeMutex(serverInterface->getSlotMutex(faction->getStartLocationIndex()),CODE_AT_LINE); + ConnectionSlot *slot = serverInterface->getSlot(faction->getStartLocationIndex(),false); if(slot != NULL && slot->getConnectHasHandshaked() == true && slot->getCurrentFrameCount() <= 0) { isSlotJoinInProgressClient = true; @@ -5994,9 +6008,12 @@ void Game::setPaused(bool value,bool forceAllowPauseStateChange,bool clearCaches bool haveClientConnectedButNoReady = false; for(int i = 0; i < world.getFactionCount(); ++i) { Faction *faction = world.getFaction(i); - ConnectionSlot *slot = server->getSlot(faction->getStartLocationIndex()); + + MutexSafeWrapper safeMutex(server->getSlotMutex(faction->getStartLocationIndex()),CODE_AT_LINE); + ConnectionSlot *slot = server->getSlot(faction->getStartLocationIndex(),false); if(slot != NULL && slot->isConnected() == true && slot->isReady() == false) { for(unsigned int i = 0; i < languageList.size(); ++i) { + char szMsg[8096]=""; if(lang.hasString("JoinPlayerToCurrentGameLaunch",languageList[i]) == true) { snprintf(szMsg,8096,lang.getString("JoinPlayerToCurrentGameLaunch",languageList[i]).c_str(), slot->getName().c_str()); @@ -6004,6 +6021,9 @@ void Game::setPaused(bool value,bool forceAllowPauseStateChange,bool clearCaches else { snprintf(szMsg,8096,"Player: %s is about to join the game, please wait...",slot->getName().c_str()); } + + safeMutex.ReleaseLock(); + bool localEcho = lang.isLanguageLocal(languageList[i]); server->sendTextMessage(szMsg,-1, localEcho,languageList[i]); sleep(1); diff --git a/source/glest_game/menu/menu_state_custom_game.cpp b/source/glest_game/menu/menu_state_custom_game.cpp index 38d24cb1..f690fa85 100644 --- a/source/glest_game/menu/menu_state_custom_game.cpp +++ b/source/glest_game/menu/menu_state_custom_game.cpp @@ -1355,7 +1355,7 @@ void MenuStateCustomGame::mouseClick(int x, int y, MouseButton mouseButton) { //ensure thet only 1 human player is present ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface(); - ConnectionSlot *slot = serverInterface->getSlot(i); + ConnectionSlot *slot = serverInterface->getSlot(i,true); bool checkControTypeClicked = false; int selectedControlItemIndex = listBoxControls[i].getSelectedItemIndex(); @@ -1459,28 +1459,28 @@ void MenuStateCustomGame::mouseClick(int x, int y, MouseButton mouseButton) { ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface(); if(serverInterface != NULL) { - if(serverInterface->getSlot(i) != NULL && - serverInterface->getSlot(i)->isConnected()) { + if(serverInterface->getSlot(i,true) != NULL && + serverInterface->getSlot(i,true)->isConnected()) { ServerSocket *serverSocket = serverInterface->getServerSocket(); if(serverSocket != NULL) { - serverSocket->addIPAddressToBlockedList(serverInterface->getSlot(i)->getIpAddress()); + serverSocket->addIPAddressToBlockedList(serverInterface->getSlot(i,true)->getIpAddress()); Lang &lang= Lang::getInstance(); const vector languageList = serverInterface->getGameSettings()->getUniqueNetworkPlayerLanguages(); for(unsigned int j = 0; j < languageList.size(); ++j) { char szMsg[8096]=""; if(lang.hasString("BlockPlayerServerMsg",languageList[j]) == true) { - snprintf(szMsg,8096,lang.getString("BlockPlayerServerMsg",languageList[j]).c_str(),serverInterface->getSlot(i)->getIpAddress().c_str()); + snprintf(szMsg,8096,lang.getString("BlockPlayerServerMsg",languageList[j]).c_str(),serverInterface->getSlot(i,true)->getIpAddress().c_str()); } else { - snprintf(szMsg,8096,"The server has temporarily blocked IP Address [%s] from this game.",serverInterface->getSlot(i)->getIpAddress().c_str()); + snprintf(szMsg,8096,"The server has temporarily blocked IP Address [%s] from this game.",serverInterface->getSlot(i,true)->getIpAddress().c_str()); } serverInterface->sendTextMessage(szMsg,-1, true,languageList[j]); } sleep(1); - serverInterface->getSlot(i)->close(); + serverInterface->getSlot(i,true)->close(); } } } @@ -1660,7 +1660,9 @@ bool MenuStateCustomGame::checkNetworkPlayerDataSynch(bool checkMapCRC, bool dataSynchCheckOk = true; for(int i= 0; i < mapInfo.players; ++i) { if(listBoxControls[i].getSelectedItemIndex() == ctNetwork) { - ConnectionSlot *slot = serverInterface->getSlot(i); + + MutexSafeWrapper safeMutex(serverInterface->getSlotMutex(i),CODE_AT_LINE); + ConnectionSlot *slot = serverInterface->getSlot(i,false); if( slot != NULL && slot->isConnected() && (slot->getAllowDownloadDataSynch() == true || slot->getAllowGameDataSynchCheck() == true)) { @@ -2140,8 +2142,8 @@ void MenuStateCustomGame::render() { if(listBoxControls[i].getSelectedItemIndex() == ctNetwork || listBoxControls[i].getSelectedItemIndex() == ctNetworkUnassigned) { ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface(); if( serverInterface != NULL && - serverInterface->getSlot(i) != NULL && - serverInterface->getSlot(i)->isConnected()) { + serverInterface->getSlot(i,true) != NULL && + serverInterface->getSlot(i,true)->isConnected()) { renderer.renderButton(&buttonBlockPlayers[i]); } } @@ -2287,7 +2289,7 @@ void MenuStateCustomGame::switchSetupForSlots(SwitchSetupRequest **switchSetupRe if(serverInterface->switchSlot(switchFactionIdx,newFactionIdx)) { try { ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface(); - ConnectionSlot *slot = serverInterface->getSlot(newFactionIdx); + ConnectionSlot *slot = serverInterface->getSlot(newFactionIdx,true); if(switchSetupRequests[i]->getSelectedFactionName() != "" && (slot != NULL && @@ -2325,7 +2327,7 @@ void MenuStateCustomGame::switchSetupForSlots(SwitchSetupRequest **switchSetupRe try { int factionIdx = switchSetupRequests[i]->getCurrentSlotIndex(); ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface(); - ConnectionSlot *slot = serverInterface->getSlot(factionIdx); + ConnectionSlot *slot = serverInterface->getSlot(factionIdx,true); if(switchSetupRequests[i]->getSelectedFactionName() != "" && (slot != NULL && @@ -2555,11 +2557,11 @@ void MenuStateCustomGame::update() { listBoxControls[i].getSelectedItemIndex() == ctNetworkUnassigned) { hasOneNetworkSlotOpen=true; - if(serverInterface->getSlot(i) != NULL && - serverInterface->getSlot(i)->isConnected()) { + if(serverInterface->getSlot(i,true) != NULL && + serverInterface->getSlot(i,true)->isConnected()) { if(hasNetworkGameSettings() == true) { - switch(serverInterface->getSlot(i)->getNetworkPlayerStatus()) { + switch(serverInterface->getSlot(i,true)->getNetworkPlayerStatus()) { case npst_BeRightBack: labelPlayerStatus[i].setTexture(CoreData::getInstance().getStatusBRBTexture()); break; @@ -2573,29 +2575,29 @@ void MenuStateCustomGame::update() { } } - serverInterface->getSlot(i)->setName(labelPlayerNames[i].getText()); + serverInterface->getSlot(i,true)->setName(labelPlayerNames[i].getText()); //printf("FYI we have at least 1 client connected, slot = %d'\n",i); //haveAtLeastOneNetworkClientConnected = true; - if(serverInterface->getSlot(i) != NULL && - serverInterface->getSlot(i)->getConnectHasHandshaked()) { + if(serverInterface->getSlot(i,true) != NULL && + serverInterface->getSlot(i,true)->getConnectHasHandshaked()) { currentConnectionCount++; } - string label = (serverInterface->getSlot(i) != NULL ? serverInterface->getSlot(i)->getVersionString() : ""); + string label = (serverInterface->getSlot(i,true) != NULL ? serverInterface->getSlot(i,true)->getVersionString() : ""); - if(serverInterface->getSlot(i) != NULL && - serverInterface->getSlot(i)->getAllowDownloadDataSynch() == true && - serverInterface->getSlot(i)->getAllowGameDataSynchCheck() == true) { - if(serverInterface->getSlot(i)->getNetworkGameDataSynchCheckOk() == false) { + if(serverInterface->getSlot(i,true) != NULL && + serverInterface->getSlot(i,true)->getAllowDownloadDataSynch() == true && + serverInterface->getSlot(i,true)->getAllowGameDataSynchCheck() == true) { + if(serverInterface->getSlot(i,true)->getNetworkGameDataSynchCheckOk() == false) { label += " -waiting to synch:"; - if(serverInterface->getSlot(i)->getNetworkGameDataSynchCheckOkMap() == false) { + if(serverInterface->getSlot(i,true)->getNetworkGameDataSynchCheckOkMap() == false) { label = label + " map"; } - if(serverInterface->getSlot(i)->getNetworkGameDataSynchCheckOkTile() == false) { + if(serverInterface->getSlot(i,true)->getNetworkGameDataSynchCheckOkTile() == false) { label = label + " tile"; } - if(serverInterface->getSlot(i)->getNetworkGameDataSynchCheckOkTech() == false) { + if(serverInterface->getSlot(i,true)->getNetworkGameDataSynchCheckOkTech() == false) { label = label + " techtree"; } } @@ -2604,15 +2606,15 @@ void MenuStateCustomGame::update() { } } else { - if(serverInterface->getSlot(i) != NULL && - serverInterface->getSlot(i)->getAllowGameDataSynchCheck() == true && - serverInterface->getSlot(i)->getNetworkGameDataSynchCheckOk() == false) { + if(serverInterface->getSlot(i,true) != NULL && + serverInterface->getSlot(i,true)->getAllowGameDataSynchCheck() == true && + serverInterface->getSlot(i,true)->getNetworkGameDataSynchCheckOk() == false) { label += " -synch mismatch:"; - if(serverInterface->getSlot(i) != NULL && serverInterface->getSlot(i)->getNetworkGameDataSynchCheckOkMap() == false) { + if(serverInterface->getSlot(i,true) != NULL && serverInterface->getSlot(i,true)->getNetworkGameDataSynchCheckOkMap() == false) { label = label + " map"; - if(serverInterface->getSlot(i)->getReceivedDataSynchCheck() == true && + if(serverInterface->getSlot(i,true)->getReceivedDataSynchCheck() == true && lastMapDataSynchError != "map CRC mismatch, " + listBoxMap.getSelectedItem()) { lastMapDataSynchError = "map CRC mismatch, " + listBoxMap.getSelectedItem(); ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface(); @@ -2620,11 +2622,11 @@ void MenuStateCustomGame::update() { } } - if(serverInterface->getSlot(i) != NULL && - serverInterface->getSlot(i)->getNetworkGameDataSynchCheckOkTile() == false) { + if(serverInterface->getSlot(i,true) != NULL && + serverInterface->getSlot(i,true)->getNetworkGameDataSynchCheckOkTile() == false) { label = label + " tile"; - if(serverInterface->getSlot(i)->getReceivedDataSynchCheck() == true && + if(serverInterface->getSlot(i,true)->getReceivedDataSynchCheck() == true && lastTileDataSynchError != "tile CRC mismatch, " + listBoxTileset.getSelectedItem()) { lastTileDataSynchError = "tile CRC mismatch, " + listBoxTileset.getSelectedItem(); ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface(); @@ -2632,13 +2634,13 @@ void MenuStateCustomGame::update() { } } - if(serverInterface->getSlot(i) != NULL && - serverInterface->getSlot(i)->getNetworkGameDataSynchCheckOkTech() == false) { + if(serverInterface->getSlot(i,true) != NULL && + serverInterface->getSlot(i,true)->getNetworkGameDataSynchCheckOkTech() == false) { label = label + " techtree"; - if(serverInterface->getSlot(i)->getReceivedDataSynchCheck() == true) { + if(serverInterface->getSlot(i,true)->getReceivedDataSynchCheck() == true) { ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface(); - string report = serverInterface->getSlot(i)->getNetworkGameDataSynchCheckTechMismatchReport(); + string report = serverInterface->getSlot(i,true)->getNetworkGameDataSynchCheckTechMismatchReport(); if(lastTechtreeDataSynchError != "techtree CRC mismatch" + report) { lastTechtreeDataSynchError = "techtree CRC mismatch" + report; @@ -2655,8 +2657,8 @@ void MenuStateCustomGame::update() { } } - if(serverInterface->getSlot(i) != NULL) { - serverInterface->getSlot(i)->setReceivedDataSynchCheck(false); + if(serverInterface->getSlot(i,true) != NULL) { + serverInterface->getSlot(i,true)->setReceivedDataSynchCheck(false); } } } @@ -2691,7 +2693,7 @@ void MenuStateCustomGame::update() { //printf("In [%s::%s] Line: %d i = %d mapInfo.players = %d\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,i,mapInfo.players); } else if(listBoxControls[i].getSelectedItemIndex() != ctNetworkUnassigned) { - ConnectionSlot *slot = serverInterface->getSlot(i); + ConnectionSlot *slot = serverInterface->getSlot(i,true); if((listBoxControls[i].getSelectedItemIndex() != ctNetwork) || (listBoxControls[i].getSelectedItemIndex() == ctNetwork && (slot == NULL || slot->isConnected() == false))) { listBoxControls[i].setEditable(true); @@ -2747,7 +2749,7 @@ void MenuStateCustomGame::update() { MutexSafeWrapper safeMutex((publishToMasterserverThread != NULL ? publishToMasterserverThread->getMutexThreadObjectAccessor() : NULL),string(__FILE__) + "_" + intToStr(__LINE__)); ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface(); - ConnectionSlot *slot = serverInterface->getSlot(i); + ConnectionSlot *slot = serverInterface->getSlot(i,true); if(slot != NULL && slot->isConnected() == true) { anyoneConnected = true; break; @@ -3025,8 +3027,8 @@ void MenuStateCustomGame::publishToMasterserver() { if(listBoxControls[i].getSelectedItemIndex() == ctNetwork || listBoxControls[i].getSelectedItemIndex() == ctNetworkUnassigned) { slotCountHumans++; - if(serverInterface->getSlot(i) != NULL && - serverInterface->getSlot(i)->isConnected()) { + if(serverInterface->getSlot(i,true) != NULL && + serverInterface->getSlot(i,true)->isConnected()) { slotCountConnectedPlayers++; } } @@ -3505,8 +3507,8 @@ void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings,bool force if(forceCloseUnusedSlots == true && (ct == ctNetworkUnassigned || ct == ctNetwork)) { if(serverInterface != NULL && - (serverInterface->getSlot(i) == NULL || - serverInterface->getSlot(i)->isConnected() == false)) { + (serverInterface->getSlot(i,true) == NULL || + serverInterface->getSlot(i,true)->isConnected() == false)) { if(checkBoxScenario.getValue() == false) { //printf("Closed A [%d] [%s]\n",i,labelPlayerNames[i].getText().c_str()); @@ -3534,8 +3536,8 @@ void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings,bool force Lang &lang= Lang::getInstance(); gameSettings->setNetworkPlayerLanguages(slotIndex, lang.getLanguage()); } - else if(serverInterface != NULL && serverInterface->getSlot(i) != NULL) { - gameSettings->setNetworkPlayerLanguages(slotIndex, serverInterface->getSlot(i)->getNetworkPlayerLanguage()); + else if(serverInterface != NULL && serverInterface->getSlot(i,true) != NULL) { + gameSettings->setNetworkPlayerLanguages(slotIndex, serverInterface->getSlot(i,true)->getNetworkPlayerLanguage()); } //if(slotIndex == 0) printf("slotIndex = %d, i = %d, multiplier = %d\n",slotIndex,i,listBoxRMultiplier[i].getSelectedItemIndex()); @@ -3582,17 +3584,17 @@ void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings,bool force if(listBoxControls[i].getSelectedItemIndex() == ctNetwork || listBoxControls[i].getSelectedItemIndex() == ctNetworkUnassigned) { if(serverInterface != NULL && - serverInterface->getSlot(i) != NULL && - serverInterface->getSlot(i)->isConnected()) { + serverInterface->getSlot(i,true) != NULL && + serverInterface->getSlot(i,true)->isConnected()) { - gameSettings->setNetworkPlayerStatuses(slotIndex,serverInterface->getSlot(i)->getNetworkPlayerStatus()); + gameSettings->setNetworkPlayerStatuses(slotIndex,serverInterface->getSlot(i,true)->getNetworkPlayerStatus()); - if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] i = %d, connectionSlot->getName() [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,i,serverInterface->getSlot(i)->getName().c_str()); + if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] i = %d, connectionSlot->getName() [%s]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,i,serverInterface->getSlot(i,true)->getName().c_str()); - gameSettings->setNetworkPlayerName(slotIndex, serverInterface->getSlot(i)->getName()); - gameSettings->setNetworkPlayerUUID(i,serverInterface->getSlot(i)->getUUID()); - gameSettings->setNetworkPlayerPlatform(i,serverInterface->getSlot(i)->getPlatform()); - labelPlayerNames[i].setText(serverInterface->getSlot(i)->getName()); + gameSettings->setNetworkPlayerName(slotIndex, serverInterface->getSlot(i,true)->getName()); + gameSettings->setNetworkPlayerUUID(i,serverInterface->getSlot(i,true)->getUUID()); + gameSettings->setNetworkPlayerPlatform(i,serverInterface->getSlot(i,true)->getPlatform()); + labelPlayerNames[i].setText(serverInterface->getSlot(i,true)->getName()); } else { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] i = %d, playername unconnected\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,i); @@ -3612,9 +3614,9 @@ void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings,bool force if (listBoxControls[i].getSelectedItemIndex() == ctHuman) { setSlotHuman(i); } - if(serverInterface != NULL && serverInterface->getSlot(i) != NULL) { - gameSettings->setNetworkPlayerUUID(slotIndex,serverInterface->getSlot(i)->getUUID()); - gameSettings->setNetworkPlayerPlatform(slotIndex,serverInterface->getSlot(i)->getPlatform()); + if(serverInterface != NULL && serverInterface->getSlot(i,true) != NULL) { + gameSettings->setNetworkPlayerUUID(slotIndex,serverInterface->getSlot(i,true)->getUUID()); + gameSettings->setNetworkPlayerPlatform(slotIndex,serverInterface->getSlot(i,true)->getPlatform()); } factionCount++; @@ -3754,20 +3756,20 @@ void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings,bool force if(listBoxControls[i].getSelectedItemIndex() == ctNetwork || listBoxControls[i].getSelectedItemIndex() == ctNetworkUnassigned) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); - if( serverInterface->getSlot(i) != NULL && serverInterface->getSlot(i)->isConnected()) { + if( serverInterface->getSlot(i,true) != NULL && serverInterface->getSlot(i,true)->isConnected()) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //printf("slot = %d serverInterface->getSlot(i)->getConnectedTime() = %d session key [%d]\n",i,serverInterface->getSlot(i)->getConnectedTime(),serverInterface->getSlot(i)->getSessionKey()); if(clientConnectedTime == 0 || - (serverInterface->getSlot(i)->getConnectedTime() > 0 && serverInterface->getSlot(i)->getConnectedTime() < clientConnectedTime)) { - clientConnectedTime = serverInterface->getSlot(i)->getConnectedTime(); - gameSettings->setMasterserver_admin(serverInterface->getSlot(i)->getSessionKey()); - gameSettings->setMasterserver_admin_faction_index(serverInterface->getSlot(i)->getPlayerIndex()); - labelGameName.setText(serverInterface->getSlot(i)->getName()+" controls"); + (serverInterface->getSlot(i,true)->getConnectedTime() > 0 && serverInterface->getSlot(i,true)->getConnectedTime() < clientConnectedTime)) { + clientConnectedTime = serverInterface->getSlot(i,true)->getConnectedTime(); + gameSettings->setMasterserver_admin(serverInterface->getSlot(i,true)->getSessionKey()); + gameSettings->setMasterserver_admin_faction_index(serverInterface->getSlot(i,true)->getPlayerIndex()); + labelGameName.setText(serverInterface->getSlot(i,true)->getName()+" controls"); //printf("slot = %d, admin key [%d] slot connected time[" MG_SIZE_T_SPECIFIER "] clientConnectedTime [" MG_SIZE_T_SPECIFIER "]\n",i,gameSettings->getMasterserver_admin(),serverInterface->getSlot(i)->getConnectedTime(),clientConnectedTime); } - if(serverInterface->getSlot(i)->getSessionKey() == gameSettings->getMasterserver_admin()){ + if(serverInterface->getSlot(i,true)->getSessionKey() == gameSettings->getMasterserver_admin()){ masterserver_admin_found=true; } } @@ -3778,20 +3780,20 @@ void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings,bool force ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface(); //ConnectionSlot *slot = serverInterface->getSlot(i); - if( serverInterface->getSlot(i) != NULL && serverInterface->getSlot(i)->isConnected()) { + if( serverInterface->getSlot(i,true) != NULL && serverInterface->getSlot(i,true)->isConnected()) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__); //printf("slot = %d serverInterface->getSlot(i)->getConnectedTime() = %d session key [%d]\n",i,serverInterface->getSlot(i)->getConnectedTime(),serverInterface->getSlot(i)->getSessionKey()); if(clientConnectedTime == 0 || - (serverInterface->getSlot(i)->getConnectedTime() > 0 && serverInterface->getSlot(i)->getConnectedTime() < clientConnectedTime)) { - clientConnectedTime = serverInterface->getSlot(i)->getConnectedTime(); - gameSettings->setMasterserver_admin(serverInterface->getSlot(i)->getSessionKey()); - gameSettings->setMasterserver_admin_faction_index(serverInterface->getSlot(i)->getPlayerIndex()); - labelGameName.setText(serverInterface->getSlot(i)->getName()+" controls"); + (serverInterface->getSlot(i,true)->getConnectedTime() > 0 && serverInterface->getSlot(i,true)->getConnectedTime() < clientConnectedTime)) { + clientConnectedTime = serverInterface->getSlot(i,true)->getConnectedTime(); + gameSettings->setMasterserver_admin(serverInterface->getSlot(i,true)->getSessionKey()); + gameSettings->setMasterserver_admin_faction_index(serverInterface->getSlot(i,true)->getPlayerIndex()); + labelGameName.setText(serverInterface->getSlot(i,true)->getName()+" controls"); //printf("slot = %d, admin key [%d] slot connected time[" MG_SIZE_T_SPECIFIER "] clientConnectedTime [" MG_SIZE_T_SPECIFIER "]\n",i,gameSettings->getMasterserver_admin(),serverInterface->getSlot(i)->getConnectedTime(),clientConnectedTime); } - if(serverInterface->getSlot(i)->getSessionKey() == gameSettings->getMasterserver_admin()){ + if(serverInterface->getSlot(i,true)->getSessionKey() == gameSettings->getMasterserver_admin()){ masterserver_admin_found=true; } } @@ -4088,10 +4090,10 @@ void MenuStateCustomGame::loadMapInfo(string file, MapInfo *mapInfo, bool loadMa if(MapPreview::loadMapInfo(file, mapInfo, lang.getString("MaxPlayers"),lang.getString("Size"),true) == true) { ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface(); for(int i = 0; i < GameConstants::maxPlayers; ++i) { - if(serverInterface->getSlot(i) != NULL && + if(serverInterface->getSlot(i,true) != NULL && (listBoxControls[i].getSelectedItemIndex() == ctNetwork || listBoxControls[i].getSelectedItemIndex() == ctNetworkUnassigned)) { - if(serverInterface->getSlot(i)->isConnected() == true) { + if(serverInterface->getSlot(i,true)->isConnected() == true) { if(i+1 > mapInfo->players && listBoxControls[i].getSelectedItemIndex() != ctNetworkUnassigned) { listBoxControls[i].setSelectedItemIndex(ctNetworkUnassigned); @@ -4162,7 +4164,7 @@ void MenuStateCustomGame::updateControlers() { if(foundNewSlotForHuman == false) { ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface(); - ConnectionSlot *slot = serverInterface->getSlot(0); + ConnectionSlot *slot = serverInterface->getSlot(0,true); if(slot != NULL && slot->isConnected() == true) { serverInterface->removeSlot(0); } @@ -4196,9 +4198,9 @@ void MenuStateCustomGame::closeUnusedSlots(){ for(int i= 0; i < GameConstants::maxPlayers; ++i){ if(listBoxControls[i].getSelectedItemIndex() == ctNetwork || listBoxControls[i].getSelectedItemIndex() == ctNetworkUnassigned) { - if(serverInterface->getSlot(i) == NULL || - serverInterface->getSlot(i)->isConnected() == false || - serverInterface->getSlot(i)->getConnectHasHandshaked() == false) { + if(serverInterface->getSlot(i,true) == NULL || + serverInterface->getSlot(i,true)->isConnected() == false || + serverInterface->getSlot(i,true)->getConnectHasHandshaked() == false) { //printf("Closed A [%d] [%s]\n",i,labelPlayerNames[i].getText().c_str()); listBoxControls[i].setSelectedItemIndex(ctClosed); @@ -4236,7 +4238,7 @@ void MenuStateCustomGame::updateNetworkSlots() { } for(int i= 0; i < GameConstants::maxPlayers; ++i) { - ConnectionSlot *slot = serverInterface->getSlot(i); + ConnectionSlot *slot = serverInterface->getSlot(i,true); //printf("A i = %d control type = %d slot [%p]\n",i,listBoxControls[i].getSelectedItemIndex(),slot); if(slot == NULL && @@ -4261,7 +4263,7 @@ void MenuStateCustomGame::updateNetworkSlots() { listBoxControls[i].setSelectedItemIndex(ctCpu); } } - slot = serverInterface->getSlot(i); + slot = serverInterface->getSlot(i,true); if(slot != NULL) { if((listBoxControls[i].getSelectedItemIndex() != ctNetwork) || (listBoxControls[i].getSelectedItemIndex() == ctNetwork && @@ -4586,7 +4588,7 @@ void MenuStateCustomGame::processScenario() { listBoxRMultiplier[i].setSelectedItem(floatToStr(scenarioInfo.resourceMultipliers[i],1)); ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface(); - ConnectionSlot *slot = serverInterface->getSlot(i); + ConnectionSlot *slot = serverInterface->getSlot(i,true); int selectedControlItemIndex = listBoxControls[i].getSelectedItemIndex(); if(selectedControlItemIndex != ctNetwork || diff --git a/source/glest_game/network/connection_slot.cpp b/source/glest_game/network/connection_slot.cpp index 51be54db..d9647656 100644 --- a/source/glest_game/network/connection_slot.cpp +++ b/source/glest_game/network/connection_slot.cpp @@ -209,7 +209,7 @@ void ConnectionSlotThread::execute() { ConnectionSlotEvent eventCopy; eventCopy.eventType = eReceiveSocketData; - eventCopy.connectionSlot = this->slotInterface->getSlot(slotIndex); + eventCopy.connectionSlot = this->slotInterface->getSlot(slotIndex,true); if(getQuitStatus() == true) { if(SystemFlags::getSystemSettingType(SystemFlags::debugNetwork).enabled) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); @@ -233,7 +233,8 @@ void ConnectionSlotThread::execute() { // If the slot or socket are NULL the connection was lost // so exit the thread - ConnectionSlot *slot = this->slotInterface->getSlot(slotIndex); + MutexSafeWrapper safeMutex(this->slotInterface->getSlotMutex(slotIndex),CODE_AT_LINE); + ConnectionSlot *slot = this->slotInterface->getSlot(slotIndex,false); if(slot == NULL) { break; } @@ -242,13 +243,16 @@ void ConnectionSlotThread::execute() { break; } + PLATFORM_SOCKET socketId = socket->getSocketId(); + safeMutex.ReleaseLock(); + // Avoid mutex locking //bool socketHasReadData = Socket::hasDataToRead(socket->getSocketId()); - bool socketHasReadData = Socket::hasDataToReadWithWait(socket->getSocketId(),150000); + bool socketHasReadData = Socket::hasDataToReadWithWait(socketId,150000); ConnectionSlotEvent eventCopy; eventCopy.eventType = eReceiveSocketData; - eventCopy.connectionSlot = slot; + eventCopy.connectionSlot = this->slotInterface->getSlot(slotIndex,true); eventCopy.eventId = slotIndex; eventCopy.socketTriggered = socketHasReadData; diff --git a/source/glest_game/network/connection_slot.h b/source/glest_game/network/connection_slot.h index e0b584ae..9e84e952 100644 --- a/source/glest_game/network/connection_slot.h +++ b/source/glest_game/network/connection_slot.h @@ -69,7 +69,8 @@ class ConnectionSlotCallbackInterface { public: virtual bool isClientConnected(int index) = 0; virtual bool getAllowInGameConnections() const = 0; - virtual ConnectionSlot *getSlot(int index) = 0; + virtual ConnectionSlot *getSlot(int index, bool lockMutex) = 0; + virtual Mutex *getSlotMutex(int index) = 0; virtual void slotUpdateTask(ConnectionSlotEvent *event) = 0; virtual ~ConnectionSlotCallbackInterface() {} diff --git a/source/glest_game/network/server_interface.cpp b/source/glest_game/network/server_interface.cpp index fe57bde5..9acdb80f 100644 --- a/source/glest_game/network/server_interface.cpp +++ b/source/glest_game/network/server_interface.cpp @@ -606,14 +606,18 @@ bool ServerInterface::switchSlot(int fromPlayerIndex, int toPlayerIndex) { return result; } -ConnectionSlot *ServerInterface::getSlot(int playerIndex) { +Mutex *ServerInterface::getSlotMutex(int playerIndex) { + return slotAccessorMutexes[playerIndex]; +} + +ConnectionSlot *ServerInterface::getSlot(int playerIndex, bool lockMutex) { if(playerIndex < 0 || playerIndex >= GameConstants::maxPlayers) { char szBuf[8096]=""; snprintf(szBuf,8096,"In [%s::%s %d] playerIndex is invalid = %d",extractFileFromDirectoryPath(extractFileFromDirectoryPath(__FILE__).c_str()).c_str(),__FUNCTION__,__LINE__,playerIndex); throw megaglest_runtime_error(szBuf); } - MutexSafeWrapper safeMutexSlot(slotAccessorMutexes[playerIndex],CODE_AT_LINE_X(playerIndex)); + MutexSafeWrapper safeMutexSlot((lockMutex == true ? slotAccessorMutexes[playerIndex] : NULL),CODE_AT_LINE_X(playerIndex)); ConnectionSlot *result = slots[playerIndex]; return result; } diff --git a/source/glest_game/network/server_interface.h b/source/glest_game/network/server_interface.h index b5dde684..ecc7870d 100644 --- a/source/glest_game/network/server_interface.h +++ b/source/glest_game/network/server_interface.h @@ -168,7 +168,8 @@ public: void addSlot(int playerIndex); bool switchSlot(int fromPlayerIndex, int toPlayerIndex); void removeSlot(int playerIndex, int lockedSlotIndex = -1); - virtual ConnectionSlot *getSlot(int playerIndex); + virtual ConnectionSlot *getSlot(int playerIndex, bool lockMutex); + virtual Mutex *getSlotMutex(int playerIndex); int getSlotCount(); int getConnectedSlotCount(bool authenticated);