From 3e53b69676d68767f350ba3e549b75a4adfd70be Mon Sep 17 00:00:00 2001 From: Mark Vejvoda Date: Fri, 9 Jul 2010 15:01:49 +0000 Subject: [PATCH] - added client side ping style packet for linux socket disconnect checking --- .../menu/menu_state_connected_game.cpp | 8 +++++ .../menu/menu_state_connected_game.h | 1 + .../glest_game/network/client_interface.cpp | 34 +++++++++++++++++++ source/glest_game/network/client_interface.h | 2 ++ source/glest_game/network/connection_slot.cpp | 26 ++++++-------- .../glest_game/network/network_interface.cpp | 2 +- source/glest_game/network/network_message.cpp | 23 +++++++++++++ source/glest_game/network/network_message.h | 30 +++++++++++++++- .../glest_game/network/server_interface.cpp | 10 ++++++ .../include/platform/posix/socket.h | 2 +- .../sources/platform/posix/socket.cpp | 24 ++++--------- 11 files changed, 127 insertions(+), 35 deletions(-) diff --git a/source/glest_game/menu/menu_state_connected_game.cpp b/source/glest_game/menu/menu_state_connected_game.cpp index 93600a6b..2bb1d32f 100644 --- a/source/glest_game/menu/menu_state_connected_game.cpp +++ b/source/glest_game/menu/menu_state_connected_game.cpp @@ -48,6 +48,8 @@ struct FormatString { MenuStateConnectedGame::MenuStateConnectedGame(Program *program, MainMenu *mainMenu,JoinMenu joinMenuInfo, bool openNetworkSlots): MenuState(program, mainMenu, "connected-game") //← set on connected-game { + lastNetworkSend = time(NULL); + returnMenuInfo=joinMenuInfo; Lang &lang= Lang::getInstance(); NetworkManager &networkManager= NetworkManager::getInstance(); @@ -360,6 +362,12 @@ void MenuStateConnectedGame::update() ClientInterface* clientInterface= NetworkManager::getInstance().getClientInterface(); Lang &lang= Lang::getInstance(); + const int pingFrequency = 5; + if(difftime(time(NULL),lastNetworkSend) >= pingFrequency) { + lastNetworkSend = time(NULL); + clientInterface->sendPingMessage(pingFrequency, time(NULL)); + } + //update status label if(clientInterface != NULL && clientInterface->isConnected()) { buttonDisconnect.setText(lang.get("Disconnect")); diff --git a/source/glest_game/menu/menu_state_connected_game.h b/source/glest_game/menu/menu_state_connected_game.h index 51edbc58..33e80d8e 100644 --- a/source/glest_game/menu/menu_state_connected_game.h +++ b/source/glest_game/menu/menu_state_connected_game.h @@ -71,6 +71,7 @@ private: string currentMap; JoinMenu returnMenuInfo; bool settingsReceivedFromServer; + time_t lastNetworkSend; public: diff --git a/source/glest_game/network/client_interface.cpp b/source/glest_game/network/client_interface.cpp index 76acc7b6..aaa09ff9 100755 --- a/source/glest_game/network/client_interface.cpp +++ b/source/glest_game/network/client_interface.cpp @@ -266,6 +266,17 @@ void ClientInterface::updateLobby() } break; + case nmtPing: + { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtPing\n",__FILE__,__FUNCTION__); + + NetworkMessagePing networkMessagePing; + if(receiveMessage(&networkMessagePing)) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + } + } + break; + case nmtSynchNetworkGameData: { NetworkMessageSynchNetworkGameData networkMessageSynchNetworkGameData; @@ -540,6 +551,17 @@ void ClientInterface::updateKeyframe(int frameCount) } break; + case nmtPing: + { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtPing\n",__FILE__,__FUNCTION__); + + NetworkMessagePing networkMessagePing; + if(receiveMessage(&networkMessagePing)) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + } + } + break; + case nmtQuit: { NetworkMessageQuit networkMessageQuit; @@ -746,6 +768,11 @@ void ClientInterface::sendTextMessage(const string &text, int teamIndex, bool ec } +void ClientInterface::sendPingMessage(int32 pingFrequency, int64 pingTime) { + NetworkMessagePing networkMessagePing(pingFrequency,pingTime); + sendMessage(&networkMessagePing); +} + string ClientInterface::getNetworkStatus() { std::string label = Lang::getInstance().get("Server") + ": " + serverName; //float pingTime = getThreadedPingMS(getServerIpAddress().c_str()); @@ -866,6 +893,13 @@ bool ClientInterface::shouldDiscardNetworkMessage(NetworkMessageType networkMess this->receiveMessage(&msg); } break; + case nmtPing: + { + discard = true; + NetworkMessagePing msg = NetworkMessagePing(); + this->receiveMessage(&msg); + } + break; case nmtLaunch: { discard = true; diff --git a/source/glest_game/network/client_interface.h b/source/glest_game/network/client_interface.h index df818b1a..144313cc 100644 --- a/source/glest_game/network/client_interface.h +++ b/source/glest_game/network/client_interface.h @@ -94,6 +94,8 @@ public: int getCurrentFrameCount() const { return currentFrameCount; } + virtual void sendPingMessage(int32 pingFrequency, int64 pingTime); + protected: Mutex * getServerSynchAccessor() { return NULL; } diff --git a/source/glest_game/network/connection_slot.cpp b/source/glest_game/network/connection_slot.cpp index 27234e73..28cf38c3 100644 --- a/source/glest_game/network/connection_slot.cpp +++ b/source/glest_game/network/connection_slot.cpp @@ -170,11 +170,6 @@ ConnectionSlot::ConnectionSlot(ServerInterface* serverInterface, int playerIndex networkGameDataSynchCheckOkMap = false; networkGameDataSynchCheckOkTile = false; networkGameDataSynchCheckOkTech = false; - //networkGameDataSynchCheckOkFogOfWar = false; - - //chatText.clear(); - //chatSender.clear(); - //chatTeamIndex= -1; this->clearChatInfo(); } @@ -229,9 +224,6 @@ void ConnectionSlot::update(bool checkForNewClients) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] accepted new client connection, serverInterface->getOpenSlotCount() = %d\n",__FILE__,__FUNCTION__,serverInterface->getOpenSlotCount()); connectedTime = time(NULL); - //chatText.clear(); - //chatSender.clear(); - //chatTeamIndex= -1; this->clearChatInfo(); if(hasOpenSlots == false) { @@ -255,9 +247,6 @@ void ConnectionSlot::update(bool checkForNewClients) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); if(socket->isConnected()) { - //chatText.clear(); - //chatSender.clear(); - //chatTeamIndex= -1; this->clearChatInfo(); if(socket->hasDataToRead() == true) { @@ -272,16 +261,23 @@ void ConnectionSlot::update(bool checkForNewClients) { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d] got nmtInvalid\n",__FILE__,__FUNCTION__,__LINE__); break; + case nmtPing: + { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtPing\n",__FILE__,__FUNCTION__); + + NetworkMessagePing networkMessagePing; + if(receiveMessage(&networkMessagePing)) { + SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + } + } + break; + case nmtText: { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] got nmtText\n",__FILE__,__FUNCTION__); NetworkMessageText networkMessageText; if(receiveMessage(&networkMessageText)) { - //chatText = networkMessageText.getText(); - //chatSender = networkMessageText.getSender(); - //chatTeamIndex = networkMessageText.getTeamIndex(); - ChatMsgInfo msg(networkMessageText.getText().c_str(),networkMessageText.getSender().c_str(),networkMessageText.getTeamIndex()); this->addChatInfo(msg); diff --git a/source/glest_game/network/network_interface.cpp b/source/glest_game/network/network_interface.cpp index 32081a0e..5acf3ced 100644 --- a/source/glest_game/network/network_interface.cpp +++ b/source/glest_game/network/network_interface.cpp @@ -32,7 +32,7 @@ namespace Glest{ namespace Game{ // class NetworkInterface // ===================================================== -const int NetworkInterface::readyWaitTimeout= 120000; // 2 minutes +const int NetworkInterface::readyWaitTimeout= 180000; // 3 minutes bool NetworkInterface::allowGameDataSynchCheck = false; bool NetworkInterface::allowDownloadDataSynch = false; diff --git a/source/glest_game/network/network_message.cpp b/source/glest_game/network/network_message.cpp index 4706d6fa..67f805f1 100644 --- a/source/glest_game/network/network_message.cpp +++ b/source/glest_game/network/network_message.cpp @@ -141,6 +141,29 @@ void NetworkMessageIntro::send(Socket* socket) const{ NetworkMessage::send(socket, &data, sizeof(data)); } +// ===================================================== +// class NetworkMessagePing +// ===================================================== + +NetworkMessagePing::NetworkMessagePing(){ + data.messageType= nmtPing; +} + +NetworkMessagePing::NetworkMessagePing(int32 pingFrequency, int64 pingTime){ + data.messageType= nmtPing; + data.pingFrequency= pingFrequency; + data.pingTime= pingTime; +} + +bool NetworkMessagePing::receive(Socket* socket){ + return NetworkMessage::receive(socket, &data, sizeof(data)); +} + +void NetworkMessagePing::send(Socket* socket) const{ + assert(data.messageType==nmtPing); + NetworkMessage::send(socket, &data, sizeof(data)); +} + // ===================================================== // class NetworkMessageReady // ===================================================== diff --git a/source/glest_game/network/network_message.h b/source/glest_game/network/network_message.h index 44bbd737..8f036ba7 100644 --- a/source/glest_game/network/network_message.h +++ b/source/glest_game/network/network_message.h @@ -106,10 +106,38 @@ public: virtual void send(Socket* socket) const; }; +// ===================================================== +// class NetworkMessagePing +// +// Message sent at any time +// ===================================================== + +class NetworkMessagePing: public NetworkMessage{ +private: + struct Data{ + int8 messageType; + int32 pingFrequency; + int64 pingTime; + }; + +private: + Data data; + +public: + NetworkMessagePing(); + NetworkMessagePing(int32 pingFrequency, int64 pingTime); + + int32 getPingFrequency() const {return data.pingFrequency;} + int64 getPingTime() const {return data.pingTime;} + + virtual bool receive(Socket* socket); + virtual void send(Socket* socket) const; +}; + // ===================================================== // class NetworkMessageReady // -// Message sent at the beggining of the game +// Message sent at the beginning of the game // ===================================================== class NetworkMessageReady: public NetworkMessage{ diff --git a/source/glest_game/network/server_interface.cpp b/source/glest_game/network/server_interface.cpp index 07eddff0..5062c1b8 100644 --- a/source/glest_game/network/server_interface.cpp +++ b/source/glest_game/network/server_interface.cpp @@ -567,6 +567,7 @@ void ServerInterface::update() { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); //process text messages +/* if(this->getChatTextList().empty() == true) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); @@ -607,6 +608,7 @@ void ServerInterface::update() { } SystemFlags::OutputDebug(SystemFlags::debugNetwork,"In [%s::%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); +*/ } } } @@ -683,6 +685,14 @@ bool ServerInterface::shouldDiscardNetworkMessage(NetworkMessageType networkMess connectionSlot->receiveMessage(&msg); } break; + case nmtPing: + { + discard = true; + NetworkMessagePing msg = NetworkMessagePing(); + connectionSlot->receiveMessage(&msg); + } + break; + case nmtLaunch: { discard = true; diff --git a/source/shared_lib/include/platform/posix/socket.h b/source/shared_lib/include/platform/posix/socket.h index b7b209eb..dc6afd72 100644 --- a/source/shared_lib/include/platform/posix/socket.h +++ b/source/shared_lib/include/platform/posix/socket.h @@ -117,7 +117,7 @@ public: PLATFORM_SOCKET getSocketId() const { return sock; } - int getDataToRead(); + int getDataToRead(bool wantImmediateReply=false); int send(const void *data, int dataSize); int receive(void *data, int dataSize); int peek(void *data, int dataSize); diff --git a/source/shared_lib/sources/platform/posix/socket.cpp b/source/shared_lib/sources/platform/posix/socket.cpp index 34bc6eb2..ee1e3e4f 100644 --- a/source/shared_lib/sources/platform/posix/socket.cpp +++ b/source/shared_lib/sources/platform/posix/socket.cpp @@ -696,8 +696,7 @@ Socket::Socket() { this->pingThread = NULL; sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if(isSocketValid() == false) - { + if(isSocketValid() == false) { throwException("Error creating socket"); } } @@ -877,7 +876,7 @@ bool Socket::hasDataToRead(PLATFORM_SOCKET socket) return bResult; } -int Socket::getDataToRead(){ +int Socket::getDataToRead(bool wantImmediateReply) { unsigned long size = 0; //fd_set rfds; @@ -927,6 +926,10 @@ int Socket::getDataToRead(){ break; } + if(wantImmediateReply == true) { + break; + } + loopCount++; } } @@ -1091,7 +1094,6 @@ bool Socket::isReadable() { SystemFlags::OutputDebug(SystemFlags::debugNetwork,"[%s::%s] error while selecting socket data, err = %d, error = %s\n",__FILE__,__FUNCTION__,i,getLastSocketErrorFormattedText().c_str()); } } - //return (i == 1 && FD_ISSET(sock, &set)); bool result = (i == 1); return result; } @@ -1153,24 +1155,12 @@ bool Socket::isConnected() { //if the socket is readable it is connected if we can read a byte from it if(isReadable()) { char tmp; - int err = peek(&tmp, sizeof(tmp)); + int err = peek(&tmp, 1); if(err <= 0) { return false; } } -#ifndef WIN32 - // Need this extra check for proper linux disconnect checking - struct sockaddr name; - socklen_t namelen = sizeof (name); - - int peer_result = getpeername(sock, &name, &namelen); - if(peer_result != 0) { - return false; - } - -#endif - //otherwise the socket is connected return true; }