If a client does not initialize properly within a certain time, remove the network session.
This commit is contained in:
@@ -33,6 +33,7 @@
|
|||||||
#define SERVER_CLOSE_SESSION_DELAY_SEC 1
|
#define SERVER_CLOSE_SESSION_DELAY_SEC 1
|
||||||
#define SERVER_MAX_NUM_SESSIONS 512 // Maximum number of idle users in lobby.
|
#define SERVER_MAX_NUM_SESSIONS 512 // Maximum number of idle users in lobby.
|
||||||
#define SERVER_CACHE_CLEANUP_INTERVAL_SEC 86400 // 1 day
|
#define SERVER_CACHE_CLEANUP_INTERVAL_SEC 86400 // 1 day
|
||||||
|
#define SERVER_INIT_SESSION_TIMEOUT_SEC 20
|
||||||
|
|
||||||
#define SERVER_COMPUTER_PLAYER_NAME "Computer"
|
#define SERVER_COMPUTER_PLAYER_NAME "Computer"
|
||||||
|
|
||||||
@@ -122,6 +123,7 @@ ServerLobbyThread::RemoveSessionFromGame(SessionWrapper session)
|
|||||||
void
|
void
|
||||||
ServerLobbyThread::CloseSessionDelayed(SessionWrapper session)
|
ServerLobbyThread::CloseSessionDelayed(SessionWrapper session)
|
||||||
{
|
{
|
||||||
|
m_initTimerSessionMap.erase(session.sessionData->GetSocket());
|
||||||
m_sessionManager.RemoveSession(session.sessionData->GetSocket());
|
m_sessionManager.RemoveSession(session.sessionData->GetSocket());
|
||||||
m_gameSessionManager.RemoveSession(session.sessionData->GetSocket());
|
m_gameSessionManager.RemoveSession(session.sessionData->GetSocket());
|
||||||
|
|
||||||
@@ -253,35 +255,11 @@ ServerLobbyThread::Main()
|
|||||||
{
|
{
|
||||||
while (!ShouldTerminate())
|
while (!ShouldTerminate())
|
||||||
{
|
{
|
||||||
{
|
// Process new connections.
|
||||||
// Handle one incoming connection at a time.
|
NewConnectionLoop();
|
||||||
boost::shared_ptr<ConnectData> tmpData;
|
// Process re-added sessions.
|
||||||
{
|
NewSessionLoop();
|
||||||
boost::mutex::scoped_lock lock(m_connectQueueMutex);
|
// Main loop.
|
||||||
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.
|
|
||||||
ProcessLoop();
|
ProcessLoop();
|
||||||
// Close sessions.
|
// Close sessions.
|
||||||
CloseSessionLoop();
|
CloseSessionLoop();
|
||||||
@@ -320,6 +298,7 @@ ServerLobbyThread::ProcessLoop()
|
|||||||
} catch (const NetException &)
|
} catch (const NetException &)
|
||||||
{
|
{
|
||||||
// On error: Close this session.
|
// On error: Close this session.
|
||||||
|
m_initTimerSessionMap.erase(session.sessionData->GetSocket());
|
||||||
m_sessionManager.RemoveSession(session.sessionData->GetSocket());
|
m_sessionManager.RemoveSession(session.sessionData->GetSocket());
|
||||||
// Update stats (if needed).
|
// Update stats (if needed).
|
||||||
BroadcastStatisticsUpdate();
|
BroadcastStatisticsUpdate();
|
||||||
@@ -647,6 +626,7 @@ ServerLobbyThread::EstablishSession(SessionWrapper session)
|
|||||||
SendGameList(session.sessionData->GetSocket());
|
SendGameList(session.sessionData->GetSocket());
|
||||||
|
|
||||||
// Session is now established.
|
// Session is now established.
|
||||||
|
m_initTimerSessionMap.erase(session.sessionData->GetSocket());
|
||||||
session.sessionData->SetState(SessionData::Established);
|
session.sessionData->SetState(SessionData::Established);
|
||||||
|
|
||||||
++m_totalPlayersLoggedIn;
|
++m_totalPlayersLoggedIn;
|
||||||
@@ -667,20 +647,73 @@ ServerLobbyThread::RequestPlayerAvatar(SessionWrapper session)
|
|||||||
GetSender().Send(session.sessionData->GetSocket(), retrieveAvatar);
|
GetSender().Send(session.sessionData->GetSocket(), retrieveAvatar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ServerLobbyThread::NewConnectionLoop()
|
||||||
|
{
|
||||||
|
// Handle one incoming connection at a time.
|
||||||
|
boost::shared_ptr<ConnectData> 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
|
void
|
||||||
ServerLobbyThread::CloseSessionLoop()
|
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)
|
// Remove sessions if they do not initialize within a certain period.
|
||||||
m_closeSessionList.erase(cur);
|
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<ConnectData> connData)
|
|||||||
// Create a new session.
|
// Create a new session.
|
||||||
boost::shared_ptr<SessionData> sessionData(new SessionData(connData->ReleaseSocket(), sessionId));
|
boost::shared_ptr<SessionData> sessionData(new SessionData(connData->ReleaseSocket(), sessionId));
|
||||||
m_sessionManager.AddSession(sessionData);
|
m_sessionManager.AddSession(sessionData);
|
||||||
|
m_initTimerSessionMap[sessionData->GetSocket()] = boost::timers::portable::microsec_timer();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ protected:
|
|||||||
typedef std::deque<SessionWrapper> SessionQueue;
|
typedef std::deque<SessionWrapper> SessionQueue;
|
||||||
typedef std::list<SessionWrapper> SessionList;
|
typedef std::list<SessionWrapper> SessionList;
|
||||||
typedef std::list<std::pair<boost::timers::portable::microsec_timer, boost::shared_ptr<SessionData> > > CloseSessionList;
|
typedef std::list<std::pair<boost::timers::portable::microsec_timer, boost::shared_ptr<SessionData> > > CloseSessionList;
|
||||||
|
typedef std::map<SOCKET, boost::timers::portable::microsec_timer> InitTimerSessionMap;
|
||||||
typedef std::map<unsigned, boost::shared_ptr<ServerGameThread> > GameMap;
|
typedef std::map<unsigned, boost::shared_ptr<ServerGameThread> > GameMap;
|
||||||
typedef std::list<unsigned> RemoveGameList;
|
typedef std::list<unsigned> RemoveGameList;
|
||||||
|
|
||||||
@@ -100,6 +101,8 @@ protected:
|
|||||||
void HandleNetPacketJoinGame(SessionWrapper session, const NetPacketJoinGame &tmpPacket);
|
void HandleNetPacketJoinGame(SessionWrapper session, const NetPacketJoinGame &tmpPacket);
|
||||||
void EstablishSession(SessionWrapper session);
|
void EstablishSession(SessionWrapper session);
|
||||||
void RequestPlayerAvatar(SessionWrapper session);
|
void RequestPlayerAvatar(SessionWrapper session);
|
||||||
|
void NewConnectionLoop();
|
||||||
|
void NewSessionLoop();
|
||||||
void CloseSessionLoop();
|
void CloseSessionLoop();
|
||||||
void RemoveGameLoop();
|
void RemoveGameLoop();
|
||||||
void CleanupAvatarCache();
|
void CleanupAvatarCache();
|
||||||
@@ -147,6 +150,8 @@ private:
|
|||||||
SessionManager m_sessionManager;
|
SessionManager m_sessionManager;
|
||||||
SessionManager m_gameSessionManager;
|
SessionManager m_gameSessionManager;
|
||||||
|
|
||||||
|
InitTimerSessionMap m_initTimerSessionMap;
|
||||||
|
|
||||||
CloseSessionList m_closeSessionList;
|
CloseSessionList m_closeSessionList;
|
||||||
mutable boost::mutex m_closeSessionListMutex;
|
mutable boost::mutex m_closeSessionListMutex;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user