From a844b79d3eb8b97b3c5db9e1f94b11eadfc356ef Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Sat, 18 Dec 2010 23:03:53 +0000 Subject: [PATCH] - fixed an evil socket bug! Sockets in Linux were NOT properly set as non blocking and vice versa as expected. PErhaps this helps with the menu bug --- .../menu/menu_state_custom_game.cpp | 114 ++++++++---------- .../glest_game/menu/menu_state_join_game.cpp | 9 +- .../include/platform/common/base_thread.h | 28 ++++- .../sources/platform/common/base_thread.cpp | 5 +- .../sources/platform/posix/socket.cpp | 48 ++++---- 5 files changed, 106 insertions(+), 98 deletions(-) diff --git a/source/glest_game/menu/menu_state_custom_game.cpp b/source/glest_game/menu/menu_state_custom_game.cpp index b52fe4cb..65aba5b1 100644 --- a/source/glest_game/menu/menu_state_custom_game.cpp +++ b/source/glest_game/menu/menu_state_custom_game.cpp @@ -1075,10 +1075,9 @@ void MenuStateCustomGame::PlayNow() { if(listBoxControls[i].getSelectedItemIndex() == ctNetwork) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); - ConnectionSlot* connectionSlot= serverInterface->getSlot(i); - if( connectionSlot != NULL && connectionSlot->isConnected() && - connectionSlot->getAllowGameDataSynchCheck() == true && - connectionSlot->getNetworkGameDataSynchCheckOk() == false) { + if( serverInterface->getSlot(i) != NULL && serverInterface->getSlot(i)->isConnected() && + serverInterface->getSlot(i)->getAllowGameDataSynchCheck() == true && + serverInterface->getSlot(i)->getNetworkGameDataSynchCheckOk() == false) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); dataSynchCheckOk = false; break; @@ -1515,68 +1514,53 @@ void MenuStateCustomGame::update() { if(listBoxControls[i].getSelectedItemIndex() == ctNetwork) { //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); - ConnectionSlot* connectionSlot= serverInterface->getSlot(i); - //assert(connectionSlot!=NULL); - - //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line %d]\n",__FILE__,__FUNCTION__,__LINE__); - hasOneNetworkSlotOpen=true; //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] A - ctNetwork\n",__FILE__,__FUNCTION__); - if(connectionSlot != NULL && connectionSlot->isConnected()) { - connectionSlot->setName(labelPlayerNames[i].getText()); + if(serverInterface->getSlot(i) != NULL && + serverInterface->getSlot(i)->isConnected()) { + serverInterface->getSlot(i)->setName(labelPlayerNames[i].getText()); //printf("FYI we have at least 1 client connected, slot = %d'\n",i); haveAtLeastOneNetworkClientConnected = true; - if(connectionSlot->getConnectHasHandshaked()) + if(serverInterface->getSlot(i) != NULL && + serverInterface->getSlot(i)->getConnectHasHandshaked()) { currentConnectionCount++; + } //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] B - ctNetwork\n",__FILE__,__FUNCTION__); + string label = (serverInterface->getSlot(i) != NULL ? serverInterface->getSlot(i)->getVersionString() : ""); - //string label = connectionSlot->getName() + ", " + connectionSlot->getVersionString(); - string label = connectionSlot->getVersionString(); - - if(connectionSlot != NULL && - connectionSlot->getAllowDownloadDataSynch() == true && - connectionSlot->getAllowGameDataSynchCheck() == true) - { - if(connectionSlot->getNetworkGameDataSynchCheckOk() == false) - { + if(serverInterface->getSlot(i) != NULL && + serverInterface->getSlot(i)->getAllowDownloadDataSynch() == true && + serverInterface->getSlot(i)->getAllowGameDataSynchCheck() == true) { + if(serverInterface->getSlot(i)->getNetworkGameDataSynchCheckOk() == false) { label += " -waiting to synch:"; - if(connectionSlot->getNetworkGameDataSynchCheckOkMap() == false) - { + if(serverInterface->getSlot(i)->getNetworkGameDataSynchCheckOkMap() == false) { label = label + " map"; } - if(connectionSlot->getNetworkGameDataSynchCheckOkTile() == false) - { + if(serverInterface->getSlot(i)->getNetworkGameDataSynchCheckOkTile() == false) { label = label + " tile"; } - if(connectionSlot->getNetworkGameDataSynchCheckOkTech() == false) - { + if(serverInterface->getSlot(i)->getNetworkGameDataSynchCheckOkTech() == false) { label = label + " techtree"; } } - else - { + else { label += " - data synch is ok"; } } - else - { - //label = connectionSlot->getName(); - - connectionSlot= serverInterface->getSlot(i); - if(connectionSlot != NULL && - connectionSlot->getAllowGameDataSynchCheck() == true && - connectionSlot->getNetworkGameDataSynchCheckOk() == false) - { + else { + if(serverInterface->getSlot(i) != NULL && + serverInterface->getSlot(i)->getAllowGameDataSynchCheck() == true && + serverInterface->getSlot(i)->getNetworkGameDataSynchCheckOk() == false) { label += " -synch mismatch:"; - connectionSlot= serverInterface->getSlot(i); - if(connectionSlot != NULL && connectionSlot->getNetworkGameDataSynchCheckOkMap() == false) { + + if(serverInterface->getSlot(i) != NULL && serverInterface->getSlot(i)->getNetworkGameDataSynchCheckOkMap() == false) { label = label + " map"; - if(connectionSlot->getReceivedDataSynchCheck() == true && + if(serverInterface->getSlot(i)->getReceivedDataSynchCheck() == true && lastMapDataSynchError != "map CRC mismatch, " + listBoxMap.getSelectedItem()) { lastMapDataSynchError = "map CRC mismatch, " + listBoxMap.getSelectedItem(); ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface(); @@ -1584,11 +1568,11 @@ void MenuStateCustomGame::update() { } } - connectionSlot= serverInterface->getSlot(i); - if(connectionSlot != NULL && connectionSlot->getNetworkGameDataSynchCheckOkTile() == false) { + if(serverInterface->getSlot(i) != NULL && + serverInterface->getSlot(i)->getNetworkGameDataSynchCheckOkTile() == false) { label = label + " tile"; - if(connectionSlot->getReceivedDataSynchCheck() == true && + if(serverInterface->getSlot(i)->getReceivedDataSynchCheck() == true && lastTileDataSynchError != "tile CRC mismatch, " + listBoxTileset.getSelectedItem()) { lastTileDataSynchError = "tile CRC mismatch, " + listBoxTileset.getSelectedItem(); ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface(); @@ -1596,14 +1580,13 @@ void MenuStateCustomGame::update() { } } - connectionSlot= serverInterface->getSlot(i); - if(connectionSlot != NULL && connectionSlot->getNetworkGameDataSynchCheckOkTech() == false) - { + if(serverInterface->getSlot(i) != NULL && + serverInterface->getSlot(i)->getNetworkGameDataSynchCheckOkTech() == false) { label = label + " techtree"; - if(connectionSlot->getReceivedDataSynchCheck() == true) { + if(serverInterface->getSlot(i)->getReceivedDataSynchCheck() == true) { ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface(); - string report = connectionSlot->getNetworkGameDataSynchCheckTechMismatchReport(); + string report = serverInterface->getSlot(i)->getNetworkGameDataSynchCheckTechMismatchReport(); if(lastTechtreeDataSynchError != "techtree CRC mismatch" + report) { lastTechtreeDataSynchError = "techtree CRC mismatch" + report; @@ -1620,22 +1603,20 @@ void MenuStateCustomGame::update() { } } - connectionSlot= serverInterface->getSlot(i); - if(connectionSlot != NULL) { - connectionSlot->setReceivedDataSynchCheck(false); + if(serverInterface->getSlot(i) != NULL) { + serverInterface->getSlot(i)->setReceivedDataSynchCheck(false); } } } - //float pingTime = connectionSlot->getThreadedPingMS(connectionSlot->getIpAddress().c_str()); + //float pingTime = serverInterface->getSlot(i)->getThreadedPingMS(serverInterface->getSlot(i)->getIpAddress().c_str()); char szBuf[1024]=""; //sprintf(szBuf,"%s, ping = %.2fms",label.c_str(),pingTime); sprintf(szBuf,"%s",label.c_str()); labelNetStatus[i].setText(szBuf); } - else - { + else { //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] C - ctNetwork\n",__FILE__,__FUNCTION__); string port = intToStr(config.getInt("ServerPort")); if(port != intToStr(GameConstants::serverPort)){ @@ -1821,14 +1802,12 @@ void MenuStateCustomGame::publishToMasterserver() if(listBoxControls[i].getSelectedItemIndex() == ctNetwork) { slotCountHumans++; - ConnectionSlot* connectionSlot= serverInterface->getSlot(i); - if((connectionSlot!=NULL) && (connectionSlot->isConnected())) - { + if(serverInterface->getSlot(i) != NULL && + serverInterface->getSlot(i)->isConnected()) { slotCountConnectedPlayers++; } } - else if(listBoxControls[i].getSelectedItemIndex() == ctHuman) - { + else if(listBoxControls[i].getSelectedItemIndex() == ctHuman) { slotCountHumans++; slotCountConnectedPlayers++; } @@ -2046,12 +2025,12 @@ void MenuStateCustomGame::loadGameSettings(GameSettings *gameSettings) { if(listBoxControls[i].getSelectedItemIndex() == ctNetwork) { - ConnectionSlot* connectionSlot= serverInterface->getSlot(i); - if(connectionSlot != NULL && connectionSlot->isConnected()) { - SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] i = %d, connectionSlot->getName() [%s]\n",__FILE__,__FUNCTION__,__LINE__,i,connectionSlot->getName().c_str()); + if(serverInterface->getSlot(i) != NULL && + serverInterface->getSlot(i)->isConnected()) { + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] i = %d, connectionSlot->getName() [%s]\n",__FILE__,__FUNCTION__,__LINE__,i,serverInterface->getSlot(i)->getName().c_str()); - gameSettings->setNetworkPlayerName(slotIndex, connectionSlot->getName()); - labelPlayerNames[i].setText(connectionSlot->getName()); + gameSettings->setNetworkPlayerName(slotIndex, serverInterface->getSlot(i)->getName()); + labelPlayerNames[i].setText(serverInterface->getSlot(i)->getName()); } else { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] i = %d, playername unconnected\n",__FILE__,__FUNCTION__,__LINE__,i); @@ -2511,8 +2490,9 @@ void MenuStateCustomGame::closeUnusedSlots(){ try { ServerInterface* serverInterface= NetworkManager::getInstance().getServerInterface(); for(int i= 0; igetSlot(i)->isConnected()){ + if(listBoxControls[i].getSelectedItemIndex() == ctNetwork){ + if(serverInterface->getSlot(i) == NULL || + serverInterface->getSlot(i)->isConnected() == false) { listBoxControls[i].setSelectedItemIndex(ctClosed); } } diff --git a/source/glest_game/menu/menu_state_join_game.cpp b/source/glest_game/menu/menu_state_join_game.cpp index d2ea282a..ce6ecf97 100644 --- a/source/glest_game/menu/menu_state_join_game.cpp +++ b/source/glest_game/menu/menu_state_join_game.cpp @@ -223,16 +223,13 @@ void MenuStateJoinGame::mouseClick(int x, int y, MouseButton mouseButton) } //return - if(buttonReturn.mouseClick(x, y)) - { + if(buttonReturn.mouseClick(x, y)) { soundRenderer.playFx(coreData.getClickSoundA()); clientInterface->stopServerDiscovery(); - if(clientInterface->getSocket() != NULL) - { - if(clientInterface->isConnected() == true) - { + if(clientInterface->getSocket() != NULL) { + if(clientInterface->isConnected() == true) { string sQuitText = Config::getInstance().getString("NetPlayerName",Socket::getHostName().c_str()) + " has chosen to leave the game!"; clientInterface->sendTextMessage(sQuitText,-1); } diff --git a/source/shared_lib/include/platform/common/base_thread.h b/source/shared_lib/include/platform/common/base_thread.h index 36a7a26d..762f77ce 100644 --- a/source/shared_lib/include/platform/common/base_thread.h +++ b/source/shared_lib/include/platform/common/base_thread.h @@ -37,7 +37,6 @@ protected: string uniqueID; bool hasBeginExecution; - virtual void setRunningStatus(bool value); virtual void setQuitStatus(bool value); public: @@ -57,6 +56,33 @@ public: void setUniqueID(string value) { uniqueID = value; } string getUniqueID() { return uniqueID; } + + virtual void setRunningStatus(bool value); +}; + +class RunningStatusSafeWrapper { +protected: + BaseThread *thread; +public: + + RunningStatusSafeWrapper(BaseThread *thread) { + this->thread = thread; + Enable(); + } + ~RunningStatusSafeWrapper() { + Disable(); + } + + void Enable() { + if(this->thread != NULL) { + this->thread->setRunningStatus(true); + } + } + void Disable() { + if(this->thread != NULL) { + this->thread->setRunningStatus(false); + } + } }; }}//end namespace diff --git a/source/shared_lib/sources/platform/common/base_thread.cpp b/source/shared_lib/sources/platform/common/base_thread.cpp index 9b233091..1609c5d5 100644 --- a/source/shared_lib/sources/platform/common/base_thread.cpp +++ b/source/shared_lib/sources/platform/common/base_thread.cpp @@ -137,10 +137,10 @@ bool BaseThread::shutdownAndWait() { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str()); pThread->signalQuit(); - //sleep(0); + sleep(0); ret = false; - int maxWaitSeconds = 7; + int maxWaitSeconds = 5; if(pThread->canShutdown() == false) { maxWaitSeconds = 2; } @@ -156,6 +156,7 @@ bool BaseThread::shutdownAndWait() { } //sleep(0); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] uniqueID [%s]\n",__FILE__,__FUNCTION__,__LINE__,uniqueID.c_str()); + sleep(0); } } //sleep(0); diff --git a/source/shared_lib/sources/platform/posix/socket.cpp b/source/shared_lib/sources/platform/posix/socket.cpp index aadc8f2a..a601d64f 100644 --- a/source/shared_lib/sources/platform/posix/socket.cpp +++ b/source/shared_lib/sources/platform/posix/socket.cpp @@ -1170,10 +1170,10 @@ void Socket::setBlock(bool block, PLATFORM_SOCKET socket){ #ifndef WIN32 int currentFlags = fcntl(socket, F_GETFL); if(block == true) { - currentFlags |= O_NONBLOCK; + currentFlags &= (~O_NONBLOCK); } else { - currentFlags &= (~O_NONBLOCK); + currentFlags |= O_NONBLOCK; } int err= fcntl(socket, F_SETFL, currentFlags); #else @@ -1356,6 +1356,7 @@ void ClientSocket::stopBroadCastClientThread() { if(broadCastClientThread != NULL) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + broadCastClientThread->shutdownAndWait(); delete broadCastClientThread; broadCastClientThread = NULL; SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); @@ -1392,13 +1393,11 @@ void ClientSocket::connect(const Ip &ip, int port) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Connecting to host [%s] on port = %d\n", ip.getString().c_str(),port); int err= ::connect(sock, reinterpret_cast(&addr), sizeof(addr)); - if(err < 0) - { + if(err < 0) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] #2 Error connecting socket for IP: %s for Port: %d err = %d error = %s\n",__FILE__,__FUNCTION__,ip.getString().c_str(),port,err,getLastSocketErrorFormattedText().c_str()); if (getLastSocketError() == PLATFORM_SOCKET_INPROGRESS || - getLastSocketError() == PLATFORM_SOCKET_TRY_AGAIN) - { + getLastSocketError() == PLATFORM_SOCKET_TRY_AGAIN) { fd_set myset; struct timeval tv; int valopt; @@ -1406,8 +1405,7 @@ void ClientSocket::connect(const Ip &ip, int port) SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] PLATFORM_SOCKET_INPROGRESS in connect() - selecting\n",__FILE__,__FUNCTION__); - do - { + do { tv.tv_sec = 10; tv.tv_usec = 0; @@ -1501,8 +1499,9 @@ BroadCastClientSocketThread::BroadCastClientSocketThread(DiscoveredServersInterf // void BroadCastClientSocketThread::execute() { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + //setRunningStatus(true); + RunningStatusSafeWrapper runningStatus(this); - setRunningStatus(true); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast Client thread is running\n"); std::vector foundServers; @@ -1545,14 +1544,17 @@ void BroadCastClientSocketThread::execute() { Socket::setBlock(false, bcfd); - try - { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + + try { // Keep getting packets forever. - for( time_t elapsed = time(NULL); difftime(time(NULL),elapsed) <= 5; ) - { + for( time_t elapsed = time(NULL); difftime(time(NULL),elapsed) <= 5; ) { alen = sizeof(struct sockaddr); - if( (nb = recvfrom(bcfd, buff, 10024, 0, (struct sockaddr *) &bcSender, &alen)) <= 0 ) - { + //SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + bool gotData = (nb = recvfrom(bcfd, buff, 10024, 0, (struct sockaddr *) &bcSender, &alen)) > 0; + //SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] gotData = %d\n",__FILE__,__FUNCTION__,__LINE__,gotData); + + if(gotData == false) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"recvfrom failed: %s\n", getLastSocketErrorFormattedText().c_str()); //exit(-1); } @@ -1578,6 +1580,10 @@ void BroadCastClientSocketThread::execute() { break; } sleep( 100 ); // send out broadcast every 1 seconds + if(getQuitStatus() == true) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + break; + } } } catch(const exception &ex) { @@ -1605,14 +1611,12 @@ void BroadCastClientSocketThread::execute() { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); // Here we callback into the implementer class - if(discoveredServersCB != NULL) { + if(getQuitStatus() == false && discoveredServersCB != NULL) { discoveredServersCB->DiscoveredServers(foundServers); } SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast Client thread is exiting\n"); - setRunningStatus(false); - - + //setRunningStatus(false); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); } @@ -1811,10 +1815,10 @@ BroadCastSocketThread::BroadCastSocketThread() : BaseThread() { // the current broadcast message is // void BroadCastSocketThread::execute() { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + //setRunningStatus(true); + RunningStatusSafeWrapper runningStatus(this); - setRunningStatus(true); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"Broadcast thread is running\n"); const int MAX_NIC_COUNT = 10; @@ -1951,7 +1955,7 @@ void BroadCastSocketThread::execute() { } SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] Broadcast thread is exiting\n",__FILE__,__FUNCTION__,__LINE__); - setRunningStatus(false); + //setRunningStatus(false); } double Socket::getAveragePingMS(std::string host, int pingCount) {