diff --git a/source/glest_game/game/game_constants.h b/source/glest_game/game/game_constants.h index 3ee2f871..eb05fdca 100644 --- a/source/glest_game/game/game_constants.h +++ b/source/glest_game/game/game_constants.h @@ -39,6 +39,7 @@ public: static const int cameraFps= 100; static const int networkFramePeriod= 10; static const int networkExtraLatency= 200; + static const int maxClientConnectHandshakeSecs= 10; static const char *folder_path_maps; static const char *folder_path_scenarios; diff --git a/source/glest_game/network/client_interface.cpp b/source/glest_game/network/client_interface.cpp index 9faf2aa9..c8de78a0 100755 --- a/source/glest_game/network/client_interface.cpp +++ b/source/glest_game/network/client_interface.cpp @@ -44,6 +44,7 @@ ClientInterface::ClientInterface(){ introDone= false; playerIndex= -1; gameSettingsReceived=false; + gotIntro = false; networkGameDataSynchCheckOkMap = false; networkGameDataSynchCheckOkTile = false; @@ -78,6 +79,7 @@ void ClientInterface::connect(const Ip &ip, int port) clientSocket= new ClientSocket(); clientSocket->setBlock(false); clientSocket->connect(ip, port); + connectedTime = time(NULL); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END - socket = %d\n",__FILE__,__FUNCTION__,clientSocket->getSocketId()); } @@ -133,13 +135,13 @@ void ClientInterface::updateLobby() { NetworkMessageIntro networkMessageIntro; - if(receiveMessage(&networkMessageIntro)) - { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got NetworkMessageIntro\n",__FILE__,__FUNCTION__); + if(receiveMessage(&networkMessageIntro)) { + gotIntro = true; + + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got NetworkMessageIntro, networkMessageIntro.getGameState() = %d\n",__FILE__,__FUNCTION__,networkMessageIntro.getGameState()); //check consistency - if(networkMessageIntro.getVersionString() != getNetworkVersionString()) - { + if(networkMessageIntro.getVersionString() != getNetworkVersionString()) { bool versionMatched = false; string platformFreeVersion = getNetworkPlatformFreeVersionString(); string sErr = ""; @@ -165,8 +167,8 @@ void ClientInterface::updateLobby() sendTextMessage(" Client: "+ getNetworkVersionString(),-1); } - if(Config::getInstance().getBool("PlatformConsistencyChecks","true") && versionMatched == false) - {// error message and disconnect only if checked + if(Config::getInstance().getBool("PlatformConsistencyChecks","true") && + versionMatched == false) { // error message and disconnect only if checked DisplayErrorMessage(sErr); quit= true; close(); @@ -174,15 +176,31 @@ void ClientInterface::updateLobby() } } - //send intro message - NetworkMessageIntro sendNetworkMessageIntro(getNetworkVersionString(), Config::getInstance().getString("NetPlayerName",Socket::getHostName().c_str()), -1); + if(networkMessageIntro.getGameState() == nmgstOk) { + //send intro message + NetworkMessageIntro sendNetworkMessageIntro(getNetworkVersionString(), Config::getInstance().getString("NetPlayerName",Socket::getHostName().c_str()), -1, nmgstOk); - playerIndex= networkMessageIntro.getPlayerIndex(); - serverName= networkMessageIntro.getName(); - sendMessage(&sendNetworkMessageIntro); + playerIndex= networkMessageIntro.getPlayerIndex(); + serverName= networkMessageIntro.getName(); + sendMessage(&sendNetworkMessageIntro); - assert(playerIndex>=0 && playerIndex=0 && playerIndex GameConstants::maxClientConnectHandshakeSecs) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] difftime(time(NULL),connectedTime) = %d\n",__FILE__,__FUNCTION__,__LINE__,difftime(time(NULL),connectedTime)); + close(); + } } void ClientInterface::updateKeyframe(int frameCount) @@ -699,6 +722,9 @@ void ClientInterface::close() delete clientSocket; clientSocket= NULL; + + connectedTime = 0; + gotIntro = false; } void ClientInterface::discoverServers(DiscoveredServersInterface *cb) { diff --git a/source/glest_game/network/client_interface.h b/source/glest_game/network/client_interface.h index 4c20eb03..08b1af0b 100644 --- a/source/glest_game/network/client_interface.h +++ b/source/glest_game/network/client_interface.h @@ -42,6 +42,8 @@ private: bool launchGame; int playerIndex; bool gameSettingsReceived; + time_t connectedTime; + bool gotIntro; Ip ip; int port; diff --git a/source/glest_game/network/connection_slot.cpp b/source/glest_game/network/connection_slot.cpp index d029bda7..f6c523a8 100644 --- a/source/glest_game/network/connection_slot.cpp +++ b/source/glest_game/network/connection_slot.cpp @@ -39,6 +39,7 @@ ConnectionSlot::ConnectionSlot(ServerInterface* serverInterface, int playerIndex this->playerIndex= playerIndex; socket= NULL; ready= false; + gotIntro = false; networkGameDataSynchCheckOkMap = false; networkGameDataSynchCheckOkTile = false; @@ -77,20 +78,36 @@ void ConnectionSlot::update(bool checkForNewClients) //if(serverInterface->getServerSocket()->isReadable() == true) if(checkForNewClients == true) { - socket = serverInterface->getServerSocket()->accept(); + //SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] BEFORE accept new client connection, serverInterface->getOpenSlotCount() = %d\n",__FILE__,__FUNCTION__,serverInterface->getOpenSlotCount()); + bool hasOpenSlots = (serverInterface->getOpenSlotCount() > 0); + if(serverInterface->getServerSocket()->hasDataToRead() == true) { + socket = serverInterface->getServerSocket()->accept(); + serverInterface->updateListen(); + } + //send intro message when connected + if(socket != NULL) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] accepted new client connection, serverInterface->getOpenSlotCount() = %d\n",__FILE__,__FUNCTION__,serverInterface->getOpenSlotCount()); + connectedTime = time(NULL); - //send intro message when connected - if(socket != NULL) - { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] accepted new client connection\n",__FILE__,__FUNCTION__); + chatText.clear(); + chatSender.clear(); + chatTeamIndex= -1; - chatText.clear(); - chatSender.clear(); - chatTeamIndex= -1; + if(hasOpenSlots == false) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] no open slots, disconnecting client\n",__FILE__,__FUNCTION__); - NetworkMessageIntro networkMessageIntro(getNetworkVersionString(), socket->getHostName(), playerIndex); - sendMessage(&networkMessageIntro); - } + NetworkMessageIntro networkMessageIntro(getNetworkVersionString(), socket->getHostName(), playerIndex, nmgstNoSlots); + sendMessage(&networkMessageIntro); + + close(); + } + else { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] client will be assigned to the next open slot\n",__FILE__,__FUNCTION__); + + NetworkMessageIntro networkMessageIntro(getNetworkVersionString(), socket->getHostName(), playerIndex, nmgstOk); + sendMessage(&networkMessageIntro); + } + } } } else @@ -144,12 +161,12 @@ void ConnectionSlot::update(bool checkForNewClients) //process intro messages case nmtIntro: { - SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtIntro\n",__FILE__,__FUNCTION__); NetworkMessageIntro networkMessageIntro; if(receiveMessage(&networkMessageIntro)) { + gotIntro = true; name= networkMessageIntro.getName(); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got name [%s]\n",__FILE__,__FUNCTION__,name.c_str()); @@ -189,11 +206,7 @@ void ConnectionSlot::update(bool checkForNewClients) } //tileset - //world.loadTileset(config.getPathListForType(ptTilesets,scenarioDir), tilesetName, &checksum); - - //int32 tilesetCRC = getFolderTreeContentsCheckSumRecursively(string(GameConstants::folder_path_tilesets) + "/" + serverInterface->getGameSettings()->getTileset() + "/*", ".xml", NULL); int32 tilesetCRC = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptTilesets,scenarioDir), string("/") + serverInterface->getGameSettings()->getTileset() + string("/*"), ".xml", NULL); - //int32 techCRC = getFolderTreeContentsCheckSumRecursively(string(GameConstants::folder_path_techs) + "/" + serverInterface->getGameSettings()->getTech() + "/*", ".xml", NULL); int32 techCRC = getFolderTreeContentsCheckSumRecursively(config.getPathListForType(ptTechs,scenarioDir), "/" + serverInterface->getGameSettings()->getTech() + "/*", ".xml", NULL); Checksum checksum; string file = Map::getMapPath(serverInterface->getGameSettings()->getMap(),scenarioDir); @@ -342,6 +355,11 @@ void ConnectionSlot::update(bool checkForNewClients) return; } } + + if(gotIntro == false && difftime(time(NULL),connectedTime) > GameConstants::maxClientConnectHandshakeSecs) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] difftime(time(NULL),connectedTime) = %d\n",__FILE__,__FUNCTION__,__LINE__,difftime(time(NULL),connectedTime)); + close(); + } } else { @@ -362,6 +380,10 @@ void ConnectionSlot::close() chatText.clear(); chatSender.clear(); chatTeamIndex= -1; + ready = false; + gotIntro = false; + + serverInterface->updateListen(); SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] END\n",__FILE__,__FUNCTION__); } diff --git a/source/glest_game/network/connection_slot.h b/source/glest_game/network/connection_slot.h index cbd1e193..8e7f248a 100644 --- a/source/glest_game/network/connection_slot.h +++ b/source/glest_game/network/connection_slot.h @@ -13,10 +13,9 @@ #define _GLEST_GAME_CONNECTIONSLOT_H_ #include - #include "socket.h" - #include "network_interface.h" +#include using Shared::Platform::ServerSocket; using Shared::Platform::Socket; @@ -39,6 +38,8 @@ private: bool ready; vector > vctFileList; bool receivedNetworkGameStatus; + time_t connectedTime; + bool gotIntro; public: ConnectionSlot(ServerInterface* serverInterface, int playerIndex); diff --git a/source/glest_game/network/network_message.cpp b/source/glest_game/network/network_message.cpp index 65d9ce2b..85cb5717 100644 --- a/source/glest_game/network/network_message.cpp +++ b/source/glest_game/network/network_message.cpp @@ -119,13 +119,15 @@ void NetworkMessage::send(Socket* socket, const void* data, int dataSize) const NetworkMessageIntro::NetworkMessageIntro(){ data.messageType= -1; data.playerIndex= -1; + data.gameState = nmgstInvalid; } -NetworkMessageIntro::NetworkMessageIntro(const string &versionString, const string &name, int playerIndex){ - data.messageType=nmtIntro; - data.versionString= versionString; - data.name= name; - data.playerIndex= static_cast(playerIndex); +NetworkMessageIntro::NetworkMessageIntro(const string &versionString, const string &name, int playerIndex, NetworkGameStateType gameState) { + data.messageType = nmtIntro; + data.versionString = versionString; + data.name = name; + data.playerIndex = static_cast(playerIndex); + data.gameState = static_cast(gameState); } bool NetworkMessageIntro::receive(Socket* socket){ diff --git a/source/glest_game/network/network_message.h b/source/glest_game/network/network_message.h index f1795931..0bcd387c 100644 --- a/source/glest_game/network/network_message.h +++ b/source/glest_game/network/network_message.h @@ -45,6 +45,14 @@ enum NetworkMessageType { nmtCount }; +enum NetworkGameStateType { + nmgstInvalid, + nmgstOk, + nmgstNoSlots, + + nmgstCount +}; + const int32 commandListHeaderSize = 6; // ===================================================== @@ -81,6 +89,7 @@ private: NetworkString versionString; NetworkString name; int16 playerIndex; + int8 gameState; }; private: @@ -88,11 +97,12 @@ private: public: NetworkMessageIntro(); - NetworkMessageIntro(const string &versionString, const string &name, int playerIndex); + NetworkMessageIntro(const string &versionString, const string &name, int playerIndex, NetworkGameStateType gameState); - string getVersionString() const {return data.versionString.getString();} - string getName() const {return data.name.getString();} - int getPlayerIndex() const {return data.playerIndex;} + string getVersionString() const { return data.versionString.getString(); } + string getName() const { return data.name.getString(); } + int getPlayerIndex() const { return data.playerIndex; } + NetworkGameStateType getGameState() const { return static_cast(data.gameState); } virtual bool receive(Socket* socket); virtual void send(Socket* socket) const; diff --git a/source/glest_game/network/server_interface.cpp b/source/glest_game/network/server_interface.cpp index e7480eb9..eea20193 100644 --- a/source/glest_game/network/server_interface.cpp +++ b/source/glest_game/network/server_interface.cpp @@ -602,7 +602,6 @@ void ServerInterface::broadcastMessageToConnectedClients(const NetworkMessage* n void ServerInterface::updateListen() { int openSlotCount= 0; - for(int i= 0; iisConnected() == false) @@ -614,6 +613,20 @@ void ServerInterface::updateListen() serverSocket.listen(openSlotCount); } +int ServerInterface::getOpenSlotCount() { + int openSlotCount= 0; + + for(int i= 0; iisConnected() == false) + { + ++openSlotCount; + } + } + + return openSlotCount; +} + void ServerInterface::setGameSettings(GameSettings *serverGameSettings, bool waitForClientAck) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] START gameSettingsUpdateCount = %d, waitForClientAck = %d\n",__FILE__,__FUNCTION__,gameSettingsUpdateCount,waitForClientAck); diff --git a/source/glest_game/network/server_interface.h b/source/glest_game/network/server_interface.h index efbd7590..525232a3 100644 --- a/source/glest_game/network/server_interface.h +++ b/source/glest_game/network/server_interface.h @@ -73,14 +73,15 @@ public: void removeSlot(int playerIndex); ConnectionSlot* getSlot(int playerIndex); int getConnectedSlotCount(); + int getOpenSlotCount(); bool launchGame(const GameSettings* gameSettings); virtual void setGameSettings(GameSettings *serverGameSettings, bool waitForClientAck = false); void broadcastGameSetup(const GameSettings* gameSettings); + void updateListen(); private: void broadcastMessage(const NetworkMessage* networkMessage, int excludeSlot= -1); - void updateListen(); void broadcastMessageToConnectedClients(const NetworkMessage* networkMessage, int excludeSlot = -1); bool shouldDiscardNetworkMessage(NetworkMessageType networkMessageType,ConnectionSlot* connectionSlot); }; diff --git a/source/shared_lib/include/platform/posix/socket.h b/source/shared_lib/include/platform/posix/socket.h index 99f1f1f3..21141b82 100644 --- a/source/shared_lib/include/platform/posix/socket.h +++ b/source/shared_lib/include/platform/posix/socket.h @@ -181,6 +181,7 @@ public: protected: + int boundPort; BroadCastSocketThread *broadCastThread; void startBroadCastThread(); bool isBroadCastThreadRunning(); diff --git a/source/shared_lib/sources/platform/posix/socket.cpp b/source/shared_lib/sources/platform/posix/socket.cpp index 228d41ae..fa91e490 100644 --- a/source/shared_lib/sources/platform/posix/socket.cpp +++ b/source/shared_lib/sources/platform/posix/socket.cpp @@ -1504,6 +1504,7 @@ bool ServerSocket::isBroadCastThreadRunning() { void ServerSocket::bind(int port) { + boundPort = port; //sockaddr structure sockaddr_in addr; addr.sin_family= AF_INET; @@ -1527,14 +1528,31 @@ void ServerSocket::bind(int port) } } -void ServerSocket::listen(int connectionQueueSize) -{ - int err= ::listen(sock, connectionQueueSize); - if(err < 0) - { - char szBuf[1024]=""; - sprintf(szBuf, "In [%s::%s] Error listening socket sock = %d, err = %d, error = %s\n",__FILE__,__FUNCTION__,sock,err,getLastSocketErrorFormattedText().c_str()); - throwException(szBuf); +void ServerSocket::listen(int connectionQueueSize) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d connectionQueueSize = %d\n",__FILE__,__FUNCTION__,__LINE__,connectionQueueSize); + + if(connectionQueueSize > 0) { + if(isSocketValid() == false) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + + sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if(isSocketValid() == false) { + throwException("Error creating socket"); + } + setBlock(false); + bind(boundPort); + } + + int err= ::listen(sock, connectionQueueSize); + if(err < 0) { + char szBuf[1024]=""; + sprintf(szBuf, "In [%s::%s] Error listening socket sock = %d, err = %d, error = %s\n",__FILE__,__FUNCTION__,sock,err,getLastSocketErrorFormattedText().c_str()); + throwException(szBuf); + } + } + else { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + disconnectSocket(); } if(connectionQueueSize > 0) { @@ -1545,7 +1563,6 @@ void ServerSocket::listen(int connectionQueueSize) else { stopBroadCastThread(); } - } Socket *ServerSocket::accept() @@ -1555,6 +1572,7 @@ Socket *ServerSocket::accept() { char szBuf[1024]=""; sprintf(szBuf, "In [%s::%s] Error accepting socket connection sock = %d, err = %d, error = %s\n",__FILE__,__FUNCTION__,sock,newSock,getLastSocketErrorFormattedText().c_str()); + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] %s\n",__FILE__,__FUNCTION__,__LINE__,szBuf); if(getLastSocketError() == PLATFORM_SOCKET_TRY_AGAIN) { @@ -1563,6 +1581,9 @@ Socket *ServerSocket::accept() throwException(szBuf); } + else { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got connection, newSock = %d\n",__FILE__,__FUNCTION__,__LINE__,newSock); + } return new Socket(newSock); }