diff --git a/src/gui/generic/serverguiwrapper.cpp b/src/gui/generic/serverguiwrapper.cpp index 29a99ae5..19ae89fa 100644 --- a/src/gui/generic/serverguiwrapper.cpp +++ b/src/gui/generic/serverguiwrapper.cpp @@ -118,6 +118,7 @@ void ServerGuiWrapper::SignalNetClientGameInfo(int actionID) { if (myClientcb) m void ServerGuiWrapper::SignalNetClientError(int errorID, int osErrorID) { if (myClientcb) myClientcb->SignalNetClientError(errorID, osErrorID); } void ServerGuiWrapper::SignalNetClientNotification(int notificationId) { if (myClientcb) myClientcb->SignalNetClientNotification(notificationId); } void ServerGuiWrapper::SignalNetClientStatsUpdate(const ServerStats &stats) { if (myClientcb) myClientcb->SignalNetClientStatsUpdate(stats); } +void ServerGuiWrapper::SignalNetClientShowTimeoutDialog(NetTimeoutReason reason, unsigned remainingSec) { if (myClientcb) myClientcb->SignalNetClientShowTimeoutDialog(reason, remainingSec); } void ServerGuiWrapper::SignalNetClientRemovedFromGame(int notificationId) { if (myClientcb) myClientcb->SignalNetClientRemovedFromGame(notificationId); } void ServerGuiWrapper::SignalNetClientSelfJoined(unsigned playerId, const string &playerName, PlayerRights rights) { if (myClientcb) myClientcb->SignalNetClientSelfJoined(playerId, playerName, rights); } void ServerGuiWrapper::SignalNetClientPlayerJoined(unsigned playerId, const string &playerName, PlayerRights rights) { if (myClientcb) myClientcb->SignalNetClientPlayerJoined(playerId, playerName, rights); } diff --git a/src/gui/generic/serverguiwrapper.h b/src/gui/generic/serverguiwrapper.h index 347b5ceb..d6c47b2c 100644 --- a/src/gui/generic/serverguiwrapper.h +++ b/src/gui/generic/serverguiwrapper.h @@ -101,6 +101,7 @@ public: void SignalNetClientError(int errorID, int osErrorID); void SignalNetClientNotification(int notificationId); void SignalNetClientStatsUpdate(const ServerStats &stats); + void SignalNetClientShowTimeoutDialog(NetTimeoutReason reason, unsigned remainingSec); void SignalNetClientRemovedFromGame(int notificationId); void SignalNetClientSelfJoined(unsigned playerId, const std::string &playerName, PlayerRights rights); void SignalNetClientPlayerJoined(unsigned playerId, const std::string &playerName, PlayerRights rights); diff --git a/src/gui/qt/guiwrapper.cpp b/src/gui/qt/guiwrapper.cpp index 6e426431..736b5e52 100644 --- a/src/gui/qt/guiwrapper.cpp +++ b/src/gui/qt/guiwrapper.cpp @@ -120,7 +120,7 @@ void GuiWrapper::SignalNetClientGameInfo(int actionID) { myW->signalNetClientGam void GuiWrapper::SignalNetClientError(int errorID, int osErrorID) { myW->signalNetClientError(errorID, osErrorID); } void GuiWrapper::SignalNetClientNotification(int notificationId) { myW->signalNetClientNotification(notificationId); } void GuiWrapper::SignalNetClientStatsUpdate(const ServerStats &stats) { myW->signalNetClientStatsUpdate(stats); } -void GuiWrapper::SignalNetClientShowTimeoutDialog(int msgID, int duration) { myW->signalNetClientShowTimeoutDialog(msgID, duration); } +void GuiWrapper::SignalNetClientShowTimeoutDialog(NetTimeoutReason reason, unsigned remainingSec) { myW->signalNetClientShowTimeoutDialog(reason, remainingSec); } void GuiWrapper::SignalNetClientRemovedFromGame(int notificationId) { myW->signalNetClientRemovedFromGame(notificationId); } void GuiWrapper::SignalNetClientSelfJoined(unsigned playerId, const string &playerName, PlayerRights rights) { myW->signalNetClientSelfJoined(playerId, QString::fromUtf8(playerName.c_str()), rights); } void GuiWrapper::SignalNetClientPlayerJoined(unsigned playerId, const string &playerName, PlayerRights rights) { myW->signalNetClientPlayerJoined(playerId, QString::fromUtf8(playerName.c_str()), rights); } diff --git a/src/gui/qt/guiwrapper.h b/src/gui/qt/guiwrapper.h index 74e57ca3..91706719 100644 --- a/src/gui/qt/guiwrapper.h +++ b/src/gui/qt/guiwrapper.h @@ -108,7 +108,7 @@ public: void SignalNetClientError(int errorID, int osErrorID); void SignalNetClientNotification(int notificationId); void SignalNetClientStatsUpdate(const ServerStats &stats); - void SignalNetClientShowTimeoutDialog(int, int); + void SignalNetClientShowTimeoutDialog(NetTimeoutReason reason, unsigned remainingSec); void SignalNetClientRemovedFromGame(int notificationId); void SignalNetClientSelfJoined(unsigned playerId, const std::string &playerName, PlayerRights rights); void SignalNetClientPlayerJoined(unsigned playerId, const std::string &playerName, PlayerRights rights); diff --git a/src/gui/qt/mainwindow/mainwindowimpl.cpp b/src/gui/qt/mainwindow/mainwindowimpl.cpp index ee0d90ec..4a3b3b67 100755 --- a/src/gui/qt/mainwindow/mainwindowimpl.cpp +++ b/src/gui/qt/mainwindow/mainwindowimpl.cpp @@ -639,7 +639,7 @@ mainWindowImpl::mainWindowImpl(ConfigFile *c, QMainWindow *parent) connect(this, SIGNAL(signalNetClientGameListPlayerLeft(unsigned, unsigned)), myGameLobbyDialog, SLOT(gameRemovePlayer(unsigned, unsigned))); connect(this, SIGNAL(signalNetClientRemovedFromGame(int)), myGameLobbyDialog, SLOT(removedFromGame(int))); connect(this, SIGNAL(signalNetClientStatsUpdate(ServerStats)), myGameLobbyDialog, SLOT(updateStats(ServerStats))); - connect(this, SIGNAL(signalNetClientShowTimeoutDialog(int, int)), this, SLOT(showTimeoutDialog(int, int))); + connect(this, SIGNAL(signalNetClientShowTimeoutDialog(int, unsigned)), this, SLOT(showTimeoutDialog(int, unsigned))); // Errors are handled globally, not within one dialog. connect(this, SIGNAL(signalNetClientError(int, int)), this, SLOT(networkError(int, int))); @@ -3777,10 +3777,10 @@ void mainWindowImpl::leaveCurrentNetworkGame() { } -void mainWindowImpl::showTimeoutDialog(int msgID, int duration) { +void mainWindowImpl::showTimeoutDialog(int msgID, unsigned duration) { myTimeoutDialog->setMySession(mySession); - myTimeoutDialog->setMsgID(msgID); + myTimeoutDialog->setMsgID((NetTimeoutReason)msgID); myTimeoutDialog->setTimeoutDuration(duration); myTimeoutDialog->show(); myTimeoutDialog->raise(); diff --git a/src/gui/qt/mainwindow/mainwindowimpl.h b/src/gui/qt/mainwindow/mainwindowimpl.h index e9e668df..70dcb489 100755 --- a/src/gui/qt/mainwindow/mainwindowimpl.h +++ b/src/gui/qt/mainwindow/mainwindowimpl.h @@ -132,7 +132,7 @@ signals: void signalNetClientError(int errorID, int osErrorID); void signalNetClientNotification(int notificationId); void signalNetClientStatsUpdate(ServerStats stats); - void signalNetClientShowTimeoutDialog(int, int); + void signalNetClientShowTimeoutDialog(int, unsigned); void signalNetClientRemovedFromGame(int notificationId); void signalNetServerError(int errorID, int osErrorID); void signalNetClientSelfJoined(unsigned playerId, QString playerName, int rights); @@ -334,7 +334,7 @@ public slots: void showMaximized (); void quitPokerTH(); - void showTimeoutDialog(int msgID, int duration); + void showTimeoutDialog(int msgID, unsigned duration); void hideTimeoutDialog(); // void paintEvent(QPaintEvent *); diff --git a/src/gui/qt/timeoutmsgbox/timeoutmsgboximpl.cpp b/src/gui/qt/timeoutmsgbox/timeoutmsgboximpl.cpp index f7d03416..d24eb81e 100644 --- a/src/gui/qt/timeoutmsgbox/timeoutmsgboximpl.cpp +++ b/src/gui/qt/timeoutmsgbox/timeoutmsgboximpl.cpp @@ -59,5 +59,5 @@ void timeoutMsgBoxImpl::timerRefresh() { void timeoutMsgBoxImpl::stopTimeout() { -// mySession->stopTimeout + mySession->resetNetworkTimeout(); } diff --git a/src/net/clientcallback.h b/src/net/clientcallback.h index 7955c4e9..6e7a770f 100644 --- a/src/net/clientcallback.h +++ b/src/net/clientcallback.h @@ -39,6 +39,7 @@ public: virtual void SignalNetClientError(int errorID, int osErrorID) = 0; virtual void SignalNetClientNotification(int notificationId) = 0; virtual void SignalNetClientStatsUpdate(const ServerStats &stats) = 0; + virtual void SignalNetClientShowTimeoutDialog(NetTimeoutReason reason, unsigned remainingSec) = 0; virtual void SignalNetClientRemovedFromGame(int notificationId) = 0; virtual void SignalNetClientGameListNew(unsigned gameId) = 0; @@ -57,6 +58,6 @@ public: virtual void SignalNetClientChatMsg(const std::string &playerName, const std::string &msg) = 0; virtual void SignalNetClientWaitDialog() = 0; -}; + }; #endif diff --git a/src/net/clientthread.h b/src/net/clientthread.h index 276d7298..69b3c485 100644 --- a/src/net/clientthread.h +++ b/src/net/clientthread.h @@ -65,6 +65,7 @@ public: void SendJoinFirstGame(const std::string &password); void SendJoinGame(unsigned gameId, const std::string &password); void SendCreateGame(const GameData &gameData, const std::string &name, const std::string &password); + void SendResetTimeout(); GameInfo GetGameInfo(unsigned gameId) const; PlayerInfo GetPlayerInfo(unsigned playerId) const; diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index 6e4735b8..d4f80fc6 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -417,6 +417,12 @@ AbstractClientStateReceiving::Process(ClientThread &client) client.GetCallback().SignalNetClientRemovedFromGame(removedData.removeReason); client.SetState(ClientStateWaitJoin::Instance()); } + else if (tmpPacket->ToNetPacketTimeoutWarning()) + { + NetPacketTimeoutWarning::Data warningData; + tmpPacket->ToNetPacketTimeoutWarning()->GetData(warningData); + client.GetCallback().SignalNetClientShowTimeoutDialog(warningData.timeoutReason, warningData.remainingSeconds); + } else if (tmpPacket->ToNetPacketChatText()) { // Chat message - display it in the GUI. diff --git a/src/net/common/clientthread.cpp b/src/net/common/clientthread.cpp index c1f47fca..3c63d38a 100644 --- a/src/net/common/clientthread.cpp +++ b/src/net/common/clientthread.cpp @@ -241,6 +241,14 @@ ClientThread::SendCreateGame(const GameData &gameData, const std::string &name, } } +void +ClientThread::SendResetTimeout() +{ + boost::shared_ptr reset(new NetPacketResetTimeout); + boost::mutex::scoped_lock lock(m_outPacketListMutex); + m_outPacketList.push_back(reset); +} + GameInfo ClientThread::GetGameInfo(unsigned gameId) const { diff --git a/src/net/common/netpacket.cpp b/src/net/common/netpacket.cpp index 99af0eab..0e5487cc 100644 --- a/src/net/common/netpacket.cpp +++ b/src/net/common/netpacket.cpp @@ -4354,6 +4354,7 @@ NetPacketTimeoutWarning::SetData(const NetPacketTimeoutWarning::Data &inData) tmpData->timeoutReason = htons(NET_TIMEOUT_OTHER_REASON); break; } + tmpData->remainingSeconds = htons(inData.remainingSeconds); // Check the packet - just in case. Check(GetRawData()); @@ -4374,6 +4375,7 @@ NetPacketTimeoutWarning::GetData(NetPacketTimeoutWarning::Data &outData) const outData.timeoutReason = NETWORK_TIMEOUT_GENERIC; break; } + outData.remainingSeconds = ntohs(tmpData->remainingSeconds); } const NetPacketTimeoutWarning * diff --git a/src/net/common/servergamestate.cpp b/src/net/common/servergamestate.cpp index 1fe649a6..89571561 100644 --- a/src/net/common/servergamestate.cpp +++ b/src/net/common/servergamestate.cpp @@ -175,6 +175,8 @@ AbstractServerGameStateReceiving::Process(ServerGameThread &server) // Delegate to Lobby. server.GetLobbyThread().HandleGameRetrieveAvatar(session, *packet->ToNetPacketRetrieveAvatar()); } + else if (packet->ToNetPacketResetTimeout()) + {} else if (packet->ToNetPacketLeaveCurrentGame()) { server.MoveSessionToLobby(session, NTF_NET_REMOVED_ON_REQUEST); diff --git a/src/net/common/serverlobbythread.cpp b/src/net/common/serverlobbythread.cpp index 42c855d8..dd5009f9 100644 --- a/src/net/common/serverlobbythread.cpp +++ b/src/net/common/serverlobbythread.cpp @@ -34,11 +34,15 @@ #include #include -#define SERVER_MAX_NUM_SESSIONS 512 // Maximum number of idle users in lobby. -#define SERVER_CACHE_CLEANUP_INTERVAL_SEC 86400 // 1 day -#define SERVER_SAVE_STATISTICS_INTERVAL_SEC 60 -#define SERVER_INIT_SESSION_TIMEOUT_SEC 20 -#define SERVER_INIT_AVATAR_CLIENT_LOCK_SEC 30 // Forbid a client to send an additional avatar. +#define SERVER_MAX_NUM_SESSIONS 512 // Maximum number of idle users in lobby. +#define SERVER_CACHE_CLEANUP_INTERVAL_SEC 86400 // 1 day +#define SERVER_SAVE_STATISTICS_INTERVAL_SEC 60 +#define SERVER_INIT_AVATAR_CLIENT_LOCK_SEC 30 // Forbid a client to send an additional avatar. + +#define SERVER_INIT_SESSION_TIMEOUT_SEC 20 +#define SERVER_TIMEOUT_WARNING_REMAINING_SEC 60 +#define SERVER_SESSION_ACTIVITY_TIMEOUT_SEC 90 // MUST be > SERVER_TIMEOUT_WARNING_REMAINING_SEC +#define SERVER_SESSION_FORCED_TIMEOUT_SEC 300 // Should be quite large. #define SERVER_STATISTICS_FILE_NAME "server_statistics.log" #define SERVER_STATISTICS_STR_TOTAL_PLAYERS "TotalNumPlayersLoggedIn" @@ -142,10 +146,6 @@ ServerLobbyThread::RemoveSessionFromGame(SessionWrapper session) void ServerLobbyThread::CloseSession(SessionWrapper session) { - { - boost::mutex::scoped_lock lock(m_initTimerSessionMapMutex); - m_initTimerSessionMap.erase(session.sessionData->GetId()); - } m_sessionManager.RemoveSession(session.sessionData->GetId()); m_gameSessionManager.RemoveSession(session.sessionData->GetId()); @@ -308,12 +308,13 @@ ServerLobbyThread::Main() NewSessionLoop(); // Main loop. ProcessLoop(); - // Close sessions. - CloseSessionLoop(); // Remove games. RemoveGameLoop(); // Kick players. KickPlayerLoop(); + // Check session timeouts. + m_sessionManager.ForEachRemoveIf(boost::bind(&ServerLobbyThread::CheckSessionTimeouts, boost::ref(*this), _1)); + m_gameSessionManager.ForEachRemoveIf(boost::bind(&ServerLobbyThread::CheckSessionTimeouts, boost::ref(*this), _1)); // Update avatar limitation lock. UpdateAvatarClientTimerLoop(); // Cleanup cache. @@ -383,6 +384,8 @@ ServerLobbyThread::ProcessLoop() HandleNetPacketRetrievePlayerInfo(session, *packet->ToNetPacketRetrievePlayerInfo()); else if (packet->ToNetPacketRetrieveAvatar()) HandleNetPacketRetrieveAvatar(session, *packet->ToNetPacketRetrieveAvatar()); + else if (packet->ToNetPacketResetTimeout()) + {} else if (packet->ToNetPacketCreateGame()) HandleNetPacketCreateGame(session, *packet->ToNetPacketCreateGame()); else if (packet->ToNetPacketJoinGame()) @@ -697,10 +700,6 @@ ServerLobbyThread::EstablishSession(SessionWrapper session) SendGameList(session.sessionData); // Session is now established. - { - boost::mutex::scoped_lock lock(m_initTimerSessionMapMutex); - m_initTimerSessionMap.erase(session.sessionData->GetId()); - } session.sessionData->SetState(SessionData::Established); { @@ -764,27 +763,6 @@ ServerLobbyThread::NewSessionLoop() HandleReAddedSession(tmpSession); } -void -ServerLobbyThread::CloseSessionLoop() -{ - boost::mutex::scoped_lock lock(m_initTimerSessionMapMutex); - TimerSessionMap::iterator i = m_initTimerSessionMap.begin(); - TimerSessionMap::iterator end = m_initTimerSessionMap.end(); - - // Remove sessions if they do not initialize within a certain period. - while (i != end) - { - TimerSessionMap::iterator next = i; - ++next; - if (i->second.elapsed().total_seconds() > SERVER_INIT_SESSION_TIMEOUT_SEC) - { - m_sessionManager.RemoveSession(i->first); - m_initTimerSessionMap.erase(i); - } - i = next; - } -} - void ServerLobbyThread::RemoveGameLoop() { @@ -956,8 +934,6 @@ ServerLobbyThread::HandleNewConnection(boost::shared_ptr connData) tmpAddress[sizeof(tmpAddress) - 1] = 0; // paranoia sessionData->SetClientAddr(tmpAddress); } - boost::mutex::scoped_lock lock(m_initTimerSessionMapMutex); - m_initTimerSessionMap[sessionData->GetId()] = boost::timers::portable::microsec_timer(); } else { @@ -987,6 +963,39 @@ ServerLobbyThread::HandleReAddedSession(SessionWrapper session) } } +bool +ServerLobbyThread::CheckSessionTimeouts(SessionWrapper session) +{ + bool retVal = false; + if (session.sessionData.get()) + { + if (session.sessionData->GetState() == SessionData::Init && session.sessionData->GetAutoDisconnectTimerElapsedSec() >= SERVER_INIT_SESSION_TIMEOUT_SEC) + retVal = true; + else if (session.sessionData->GetActivityTimerElapsedSec() >= SERVER_SESSION_ACTIVITY_TIMEOUT_SEC - SERVER_TIMEOUT_WARNING_REMAINING_SEC + && !session.sessionData->HasActivityNoticeBeenSent()) + { + session.sessionData->MarkActivityNotice(); + boost::shared_ptr packet(new NetPacketTimeoutWarning); + NetPacketTimeoutWarning::Data warningData; + warningData.timeoutReason = NETWORK_TIMEOUT_GENERIC; + warningData.remainingSeconds = SERVER_TIMEOUT_WARNING_REMAINING_SEC; + static_cast(packet.get())->SetData(warningData); + GetSender().Send(session.sessionData, packet); + } + else if (session.sessionData->GetActivityTimerElapsedSec() >= SERVER_SESSION_ACTIVITY_TIMEOUT_SEC) + { + // TODO SendError(session.sessionData, errorCode); + retVal = true; + } + else if (session.sessionData->GetAutoDisconnectTimerElapsedSec() >= SERVER_SESSION_FORCED_TIMEOUT_SEC) + { + // TODO SendError(session.sessionData, errorCode); + retVal = true; + } + } + return retVal; +} + void ServerLobbyThread::CleanupConnectQueue() { diff --git a/src/net/common/sessiondata.cpp b/src/net/common/sessiondata.cpp index cd82e060..a0621c38 100644 --- a/src/net/common/sessiondata.cpp +++ b/src/net/common/sessiondata.cpp @@ -20,7 +20,8 @@ #include SessionData::SessionData(SOCKET sockfd, SessionId id) -: m_sockfd(sockfd), m_id(id), m_state(SessionData::Init), m_readyFlag(false) +: m_sockfd(sockfd), m_id(id), m_state(SessionData::Init), m_readyFlag(false), + m_activityTimeoutNoticeSent(false) { } @@ -100,3 +101,40 @@ SessionData::GetReceiveBuffer() return m_receiveBuffer; } +void +SessionData::ResetActivityTimer() +{ + boost::mutex::scoped_lock lock(m_dataMutex); + m_activityTimeoutNoticeSent = false; + m_activityTimer.reset(); + m_activityTimer.start(); +} + +unsigned +SessionData::GetActivityTimerElapsedSec() const +{ + boost::mutex::scoped_lock lock(m_dataMutex); + return m_activityTimer.elapsed().total_seconds(); +} + +bool +SessionData::HasActivityNoticeBeenSent() const +{ + boost::mutex::scoped_lock lock(m_dataMutex); + return m_activityTimeoutNoticeSent; +} + +void +SessionData::MarkActivityNotice() +{ + boost::mutex::scoped_lock lock(m_dataMutex); + m_activityTimeoutNoticeSent = true; +} + +unsigned +SessionData::GetAutoDisconnectTimerElapsedSec() const +{ + boost::mutex::scoped_lock lock(m_dataMutex); + return m_autoDisconnectTimer.elapsed().total_seconds(); +} + diff --git a/src/net/common/sessionmanager.cpp b/src/net/common/sessionmanager.cpp index bb507470..a7a61bb8 100644 --- a/src/net/common/sessionmanager.cpp +++ b/src/net/common/sessionmanager.cpp @@ -147,6 +147,8 @@ SessionManager::Select(unsigned timeoutMsec) } } } + if (retSession.sessionData.get()) + retSession.sessionData->ResetActivityTimer(); return retSession; } @@ -294,6 +296,24 @@ SessionManager::ForEach(boost::function func) } } +void +SessionManager::ForEachRemoveIf(boost::function func) +{ + boost::mutex::scoped_lock lock(m_sessionMapMutex); + + SessionMap::iterator i = m_sessionMap.begin(); + SessionMap::iterator end = m_sessionMap.end(); + + while (i != end) + { + SessionMap::iterator next = i; + next++; + if (func((*i).second)) + m_sessionMap.erase(i); + i = next; + } +} + unsigned SessionManager::CountReadySessions() const { diff --git a/src/net/serverlobbythread.h b/src/net/serverlobbythread.h index 5f289199..51c867d4 100644 --- a/src/net/serverlobbythread.h +++ b/src/net/serverlobbythread.h @@ -113,7 +113,6 @@ protected: void RequestPlayerAvatar(SessionWrapper session); void NewConnectionLoop(); void NewSessionLoop(); - void CloseSessionLoop(); void RemoveGameLoop(); void KickPlayerLoop(); void UpdateAvatarClientTimerLoop(); @@ -128,7 +127,7 @@ protected: void HandleNewConnection(boost::shared_ptr connData); void HandleReAddedSession(SessionWrapper session); - SOCKET Select(); + bool CheckSessionTimeouts(SessionWrapper session); void CleanupConnectQueue(); void CleanupSessionMap(); @@ -166,9 +165,6 @@ private: SessionManager m_sessionManager; SessionManager m_gameSessionManager; - TimerSessionMap m_initTimerSessionMap; - mutable boost::mutex m_initTimerSessionMapMutex; - TimerClientAddressMap m_timerAvatarClientAddressMap; mutable boost::mutex m_timerAvatarClientAddressMapMutex; diff --git a/src/net/sessiondata.h b/src/net/sessiondata.h index a99a3160..0b0a708b 100644 --- a/src/net/sessiondata.h +++ b/src/net/sessiondata.h @@ -25,6 +25,7 @@ #include #include #include +#include #define INVALID_SESSION 0 #define SESSION_ID_INIT INVALID_SESSION @@ -60,6 +61,12 @@ public: ReceiveBuffer &GetReceiveBuffer(); + void ResetActivityTimer(); + unsigned GetActivityTimerElapsedSec() const; + bool HasActivityNoticeBeenSent() const; + void MarkActivityNotice(); + unsigned GetAutoDisconnectTimerElapsedSec() const; + private: SOCKET m_sockfd; const SessionId m_id; @@ -67,6 +74,9 @@ private: std::string m_clientAddr; ReceiveBuffer m_receiveBuffer; bool m_readyFlag; + boost::timers::portable::microsec_timer m_activityTimer; + bool m_activityTimeoutNoticeSent; + boost::timers::portable::microsec_timer m_autoDisconnectTimer; mutable boost::mutex m_dataMutex; }; diff --git a/src/net/sessionmanager.h b/src/net/sessionmanager.h index 4b5983c5..24db2461 100644 --- a/src/net/sessionmanager.h +++ b/src/net/sessionmanager.h @@ -66,6 +66,7 @@ public: bool IsPlayerConnected(unsigned uniqueId) const; void ForEach(boost::function func); + void ForEachRemoveIf(boost::function func); unsigned CountReadySessions() const; void ResetAllReadyFlags(); diff --git a/src/session.cpp b/src/session.cpp index 85c7960a..137ba407 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -368,6 +368,13 @@ void Session::kickPlayer(unsigned playerId) myNetClient->SendKickPlayer(playerId); } +void Session::resetNetworkTimeout() +{ + if (!myNetClient) + return; // only act if client is running. + myNetClient->SendResetTimeout(); +} + void Session::kickPlayer(const string &playerName) { if (!myNetClient) diff --git a/src/session.h b/src/session.h index be0f0ec5..f8924662 100755 --- a/src/session.h +++ b/src/session.h @@ -80,6 +80,8 @@ public: void sendChatMessage(const std::string &message); void kickPlayer(unsigned playerId); void kickPlayer(const std::string &playerName); + + void resetNetworkTimeout(); bool isNetworkClientRunning() const; // TODO hack bool isNetworkServerRunning() const; // TODO hack