From ae3329975849880d5eb69e27db5987f07cf549c2 Mon Sep 17 00:00:00 2001 From: lotodore Date: Fri, 26 Oct 2007 14:54:57 +0000 Subject: [PATCH] If a client does not initialize properly within a certain time, remove the network session. --- src/net/common/serverlobbythread.cpp | 110 ++++++++++++++++++--------- src/net/serverlobbythread.h | 5 ++ 2 files changed, 77 insertions(+), 38 deletions(-) diff --git a/src/net/common/serverlobbythread.cpp b/src/net/common/serverlobbythread.cpp index d1bff883..e41d8a82 100644 --- a/src/net/common/serverlobbythread.cpp +++ b/src/net/common/serverlobbythread.cpp @@ -33,6 +33,7 @@ #define SERVER_CLOSE_SESSION_DELAY_SEC 1 #define SERVER_MAX_NUM_SESSIONS 512 // Maximum number of idle users in lobby. #define SERVER_CACHE_CLEANUP_INTERVAL_SEC 86400 // 1 day +#define SERVER_INIT_SESSION_TIMEOUT_SEC 20 #define SERVER_COMPUTER_PLAYER_NAME "Computer" @@ -122,6 +123,7 @@ ServerLobbyThread::RemoveSessionFromGame(SessionWrapper session) void ServerLobbyThread::CloseSessionDelayed(SessionWrapper session) { + m_initTimerSessionMap.erase(session.sessionData->GetSocket()); m_sessionManager.RemoveSession(session.sessionData->GetSocket()); m_gameSessionManager.RemoveSession(session.sessionData->GetSocket()); @@ -253,35 +255,11 @@ ServerLobbyThread::Main() { while (!ShouldTerminate()) { - { - // Handle one incoming connection at a time. - boost::shared_ptr tmpData; - { - boost::mutex::scoped_lock lock(m_connectQueueMutex); - if (!m_connectQueue.empty()) - { - tmpData = m_connectQueue.front(); - m_connectQueue.pop_front(); - } - } - if (tmpData.get()) - HandleNewConnection(tmpData); - } - { - // Handle one incoming session at a time. - SessionWrapper tmpSession; - { - boost::mutex::scoped_lock lock(m_sessionQueueMutex); - if (!m_sessionQueue.empty()) - { - tmpSession = m_sessionQueue.front(); - m_sessionQueue.pop_front(); - } - } - if (tmpSession.sessionData.get() && tmpSession.playerData.get()) - HandleReAddedSession(tmpSession); - } - // Process loop. + // Process new connections. + NewConnectionLoop(); + // Process re-added sessions. + NewSessionLoop(); + // Main loop. ProcessLoop(); // Close sessions. CloseSessionLoop(); @@ -320,6 +298,7 @@ ServerLobbyThread::ProcessLoop() } catch (const NetException &) { // On error: Close this session. + m_initTimerSessionMap.erase(session.sessionData->GetSocket()); m_sessionManager.RemoveSession(session.sessionData->GetSocket()); // Update stats (if needed). BroadcastStatisticsUpdate(); @@ -647,6 +626,7 @@ ServerLobbyThread::EstablishSession(SessionWrapper session) SendGameList(session.sessionData->GetSocket()); // Session is now established. + m_initTimerSessionMap.erase(session.sessionData->GetSocket()); session.sessionData->SetState(SessionData::Established); ++m_totalPlayersLoggedIn; @@ -667,20 +647,73 @@ ServerLobbyThread::RequestPlayerAvatar(SessionWrapper session) GetSender().Send(session.sessionData->GetSocket(), retrieveAvatar); } +void +ServerLobbyThread::NewConnectionLoop() +{ + // Handle one incoming connection at a time. + boost::shared_ptr tmpData; + { + boost::mutex::scoped_lock lock(m_connectQueueMutex); + if (!m_connectQueue.empty()) + { + tmpData = m_connectQueue.front(); + m_connectQueue.pop_front(); + } + } + if (tmpData.get()) + HandleNewConnection(tmpData); +} + +void +ServerLobbyThread::NewSessionLoop() +{ + // Handle one incoming session at a time. + SessionWrapper tmpSession; + { + boost::mutex::scoped_lock lock(m_sessionQueueMutex); + if (!m_sessionQueue.empty()) + { + tmpSession = m_sessionQueue.front(); + m_sessionQueue.pop_front(); + } + } + if (tmpSession.sessionData.get() && tmpSession.playerData.get()) + HandleReAddedSession(tmpSession); +} + void ServerLobbyThread::CloseSessionLoop() { - boost::mutex::scoped_lock lock(m_closeSessionListMutex); - - CloseSessionList::iterator i = m_closeSessionList.begin(); - CloseSessionList::iterator end = m_closeSessionList.end(); - - while (i != end) { - CloseSessionList::iterator cur = i++; + InitTimerSessionMap::iterator i = m_initTimerSessionMap.begin(); + InitTimerSessionMap::iterator end = m_initTimerSessionMap.end(); - if (cur->first.elapsed().total_seconds() >= SERVER_CLOSE_SESSION_DELAY_SEC) - m_closeSessionList.erase(cur); + // Remove sessions if they do not initialize within a certain period. + while (i != end) + { + InitTimerSessionMap::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; + } + } + { + boost::mutex::scoped_lock lock(m_closeSessionListMutex); + + CloseSessionList::iterator i = m_closeSessionList.begin(); + CloseSessionList::iterator end = m_closeSessionList.end(); + + while (i != end) + { + CloseSessionList::iterator cur = i++; + + if (cur->first.elapsed().total_seconds() >= SERVER_CLOSE_SESSION_DELAY_SEC) + m_closeSessionList.erase(cur); + } } } @@ -780,6 +813,7 @@ ServerLobbyThread::HandleNewConnection(boost::shared_ptr connData) // Create a new session. boost::shared_ptr sessionData(new SessionData(connData->ReleaseSocket(), sessionId)); m_sessionManager.AddSession(sessionData); + m_initTimerSessionMap[sessionData->GetSocket()] = boost::timers::portable::microsec_timer(); } else { diff --git a/src/net/serverlobbythread.h b/src/net/serverlobbythread.h index 4c811f82..a9b9ed2b 100644 --- a/src/net/serverlobbythread.h +++ b/src/net/serverlobbythread.h @@ -82,6 +82,7 @@ protected: typedef std::deque SessionQueue; typedef std::list SessionList; typedef std::list > > CloseSessionList; + typedef std::map InitTimerSessionMap; typedef std::map > GameMap; typedef std::list RemoveGameList; @@ -100,6 +101,8 @@ protected: void HandleNetPacketJoinGame(SessionWrapper session, const NetPacketJoinGame &tmpPacket); void EstablishSession(SessionWrapper session); void RequestPlayerAvatar(SessionWrapper session); + void NewConnectionLoop(); + void NewSessionLoop(); void CloseSessionLoop(); void RemoveGameLoop(); void CleanupAvatarCache(); @@ -147,6 +150,8 @@ private: SessionManager m_sessionManager; SessionManager m_gameSessionManager; + InitTimerSessionMap m_initTimerSessionMap; + CloseSessionList m_closeSessionList; mutable boost::mutex m_closeSessionListMutex;