Server support for unsubscribing/resubscribing of lobby messages. Not yet used by the client.

This commit is contained in:
lotodore
2008-05-11 21:41:30 +00:00
parent c60fd58ec9
commit 0ef69297d1
9 changed files with 156 additions and 25 deletions
+1 -1
View File
@@ -22,7 +22,7 @@
#define _OPENSSL_WRAPPER_H_
#ifndef HAVE_SSIZE_T
# define HAVE_SSIZE_T
#define HAVE_SSIZE_T
#include <sys/types.h>
#ifdef _WIN32 // This is only for Windows. Supports only Win32.
#ifndef _SSIZE_T_
+6
View File
@@ -1013,8 +1013,14 @@ ClientStateSynchronizeStart::Process(ClientThread &client)
if (client.IsSynchronized())
{
// Acknowledge start.
boost::shared_ptr<NetPacket> startAck(new NetPacketStartEventAck);
client.GetSender().Send(client.GetContext().GetSessionData(), startAck);
// Unsubscribe lobby messages.
// TODO
//boost::shared_ptr<NetPacket> unsubscr(new NetPacketUnsubscribeGameList);
//client.GetSender().Send(client.GetContext().GetSessionData(), unsubscr);
client.SetState(ClientStateWaitStart::Instance());
}
+12
View File
@@ -213,6 +213,18 @@ AbstractServerGameStateReceiving::Process(ServerGameThread &server)
server.SendToAllPlayers(outChat, SessionData::Game);
}
}
else if (packet->ToNetPacketUnsubscribeGameList())
{
// We can do this directly in this thread.
session.sessionData->ResetWantsLobbyMsg();
}
else if (packet->ToNetPacketResubscribeGameList())
{
// This needs to be performed in the lobby thread,
// because a new game list needs to be sent.
if (!session.sessionData->WantsLobbyMsg())
server.GetLobbyThread().ResubscribeLobbyMsg(session);
}
else
{
// Packet processing in subclass.
+72 -23
View File
@@ -159,6 +159,13 @@ ServerLobbyThread::CloseSession(SessionWrapper session)
UpdateStatisticsNumberOfPlayers();
}
void
ServerLobbyThread::ResubscribeLobbyMsg(SessionWrapper session)
{
boost::mutex::scoped_lock lock(m_resubscribeListMutex);
m_resubscribeList.push_back(session.sessionData->GetId());
}
void
ServerLobbyThread::NotifyPlayerJoinedGame(unsigned gameId, unsigned playerId)
{
@@ -168,8 +175,8 @@ ServerLobbyThread::NotifyPlayerJoinedGame(unsigned gameId, unsigned playerId)
packetData.gameId = gameId;
packetData.playerId = playerId;
static_cast<NetPacketGameListPlayerJoined *>(packet.get())->SetData(packetData);
m_sessionManager.SendToAllSessions(GetSender(), packet, SessionData::Established);
m_gameSessionManager.SendToAllSessions(GetSender(), packet, SessionData::Game);
m_sessionManager.SendLobbyMsgToAllSessions(GetSender(), packet, SessionData::Established);
m_gameSessionManager.SendLobbyMsgToAllSessions(GetSender(), packet, SessionData::Game);
}
void
@@ -181,8 +188,8 @@ ServerLobbyThread::NotifyPlayerLeftGame(unsigned gameId, unsigned playerId)
packetData.gameId = gameId;
packetData.playerId = playerId;
static_cast<NetPacketGameListPlayerLeft *>(packet.get())->SetData(packetData);
m_sessionManager.SendToAllSessions(GetSender(), packet, SessionData::Established);
m_gameSessionManager.SendToAllSessions(GetSender(), packet, SessionData::Game);
m_sessionManager.SendLobbyMsgToAllSessions(GetSender(), packet, SessionData::Established);
m_gameSessionManager.SendLobbyMsgToAllSessions(GetSender(), packet, SessionData::Game);
}
void
@@ -194,24 +201,24 @@ ServerLobbyThread::NotifyGameAdminChanged(unsigned gameId, unsigned newAdminPlay
packetData.gameId = gameId;
packetData.newAdminplayerId = newAdminPlayerId;
static_cast<NetPacketGameListAdminChanged *>(packet.get())->SetData(packetData);
m_sessionManager.SendToAllSessions(GetSender(), packet, SessionData::Established);
m_gameSessionManager.SendToAllSessions(GetSender(), packet, SessionData::Game);
m_sessionManager.SendLobbyMsgToAllSessions(GetSender(), packet, SessionData::Established);
m_gameSessionManager.SendLobbyMsgToAllSessions(GetSender(), packet, SessionData::Game);
}
void
ServerLobbyThread::NotifyStartingGame(unsigned gameId)
{
boost::shared_ptr<NetPacket> packet = CreateNetPacketGameListUpdate(gameId, GAME_MODE_STARTED);
m_sessionManager.SendToAllSessions(GetSender(), packet, SessionData::Established);
m_gameSessionManager.SendToAllSessions(GetSender(), packet, SessionData::Game);
m_sessionManager.SendLobbyMsgToAllSessions(GetSender(), packet, SessionData::Established);
m_gameSessionManager.SendLobbyMsgToAllSessions(GetSender(), packet, SessionData::Game);
}
void
ServerLobbyThread::NotifyReopeningGame(unsigned gameId)
{
boost::shared_ptr<NetPacket> packet = CreateNetPacketGameListUpdate(gameId, GAME_MODE_CREATED);
m_sessionManager.SendToAllSessions(GetSender(), packet, SessionData::Established);
m_gameSessionManager.SendToAllSessions(GetSender(), packet, SessionData::Game);
m_sessionManager.SendLobbyMsgToAllSessions(GetSender(), packet, SessionData::Established);
m_gameSessionManager.SendLobbyMsgToAllSessions(GetSender(), packet, SessionData::Game);
}
void
@@ -324,6 +331,8 @@ ServerLobbyThread::Main()
RemoveGameLoop();
// Kick players.
RemovePlayerLoop();
// Resubscribe Lobby Messages if needed.
ResubscribeLobbyMsgLoop();
// Check session timeouts.
CheckSessionTimeoutsLoop();
// Update avatar limitation lock.
@@ -402,6 +411,10 @@ ServerLobbyThread::ProcessLoop()
HandleNetPacketRetrieveAvatar(session, *packet->ToNetPacketRetrieveAvatar());
else if (packet->ToNetPacketResetTimeout())
{}
else if (packet->ToNetPacketUnsubscribeGameList())
session.sessionData->ResetWantsLobbyMsg();
else if (packet->ToNetPacketResubscribeGameList())
InternalResubscribeMsg(session);
else if (packet->ToNetPacketCreateGame())
HandleNetPacketCreateGame(session, *packet->ToNetPacketCreateGame());
else if (packet->ToNetPacketJoinGame())
@@ -813,15 +826,41 @@ ServerLobbyThread::RemovePlayerLoop()
{
boost::mutex::scoped_lock lock(m_removePlayerListMutex);
RemovePlayerList::iterator i = m_removePlayerList.begin();
RemovePlayerList::iterator end = m_removePlayerList.end();
while (i != end)
if (!m_removePlayerList.empty())
{
InternalRemovePlayer(i->first, i->second);
++i;
RemovePlayerList::iterator i = m_removePlayerList.begin();
RemovePlayerList::iterator end = m_removePlayerList.end();
while (i != end)
{
InternalRemovePlayer(i->first, i->second);
++i;
}
m_removePlayerList.clear();
}
}
void
ServerLobbyThread::ResubscribeLobbyMsgLoop()
{
boost::mutex::scoped_lock lock(m_resubscribeListMutex);
if (!m_resubscribeList.empty())
{
SessionIdList::iterator i = m_resubscribeList.begin();
SessionIdList::iterator end = m_resubscribeList.end();
while (i != end)
{
SessionWrapper tmpSession = m_gameSessionManager.GetSessionById(*i);
if (!tmpSession.sessionData.get())
tmpSession = m_sessionManager.GetSessionById(*i);
if (tmpSession.sessionData.get());
InternalResubscribeMsg(tmpSession);
++i;
}
m_resubscribeList.clear();
}
m_removePlayerList.clear();
}
void
@@ -875,8 +914,8 @@ ServerLobbyThread::InternalAddGame(boost::shared_ptr<ServerGameThread> game)
// Add game to list.
m_gameMap.insert(GameMap::value_type(game->GetId(), game));
// Notify all players.
m_sessionManager.SendToAllSessions(GetSender(), CreateNetPacketGameListNew(*game), SessionData::Established);
m_gameSessionManager.SendToAllSessions(GetSender(), CreateNetPacketGameListNew(*game), SessionData::Game);
m_sessionManager.SendLobbyMsgToAllSessions(GetSender(), CreateNetPacketGameListNew(*game), SessionData::Established);
m_gameSessionManager.SendLobbyMsgToAllSessions(GetSender(), CreateNetPacketGameListNew(*game), SessionData::Game);
{
boost::mutex::scoped_lock lock(m_statMutex);
@@ -906,8 +945,8 @@ ServerLobbyThread::InternalRemoveGame(boost::shared_ptr<ServerGameThread> game)
game->RemoveAllSessions();
// Notify all players.
boost::shared_ptr<NetPacket> packet = CreateNetPacketGameListUpdate(game->GetId(), GAME_MODE_CLOSED);
m_sessionManager.SendToAllSessions(GetSender(), packet, SessionData::Established);
m_gameSessionManager.SendToAllSessions(GetSender(), packet, SessionData::Game);
m_sessionManager.SendLobbyMsgToAllSessions(GetSender(), packet, SessionData::Established);
m_gameSessionManager.SendLobbyMsgToAllSessions(GetSender(), packet, SessionData::Game);
}
void
@@ -935,6 +974,16 @@ ServerLobbyThread::InternalRemovePlayer(unsigned playerId, unsigned errorCode)
}
}
void
ServerLobbyThread::InternalResubscribeMsg(SessionWrapper session)
{
if (!session.sessionData->WantsLobbyMsg())
{
session.sessionData->SetWantsLobbyMsg();
SendGameList(session.sessionData);
}
}
void
ServerLobbyThread::TerminateGames()
{
@@ -1129,8 +1178,8 @@ ServerLobbyThread::BroadcastStatisticsUpdate(const ServerStats &stats)
try {
static_cast<NetPacketStatisticsChanged *>(packet.get())->SetData(statData);
m_sessionManager.SendToAllSessions(GetSender(), packet, SessionData::Established);
m_gameSessionManager.SendToAllSessions(GetSender(), packet, SessionData::Game);
m_sessionManager.SendLobbyMsgToAllSessions(GetSender(), packet, SessionData::Established);
m_gameSessionManager.SendLobbyMsgToAllSessions(GetSender(), packet, SessionData::Game);
} catch (const NetException &)
{
// Ignore errors for now.
+22 -1
View File
@@ -21,7 +21,7 @@
SessionData::SessionData(SOCKET sockfd, SessionId id)
: m_sockfd(sockfd), m_id(id), m_state(SessionData::Init), m_readyFlag(false),
m_activityTimeoutNoticeSent(false)
m_wantsLobbyMsg(true), m_activityTimeoutNoticeSent(false)
{
}
@@ -80,6 +80,27 @@ SessionData::IsReady() const
return m_readyFlag;
}
void
SessionData::SetWantsLobbyMsg()
{
boost::mutex::scoped_lock lock(m_dataMutex);
m_wantsLobbyMsg = true;
}
void
SessionData::ResetWantsLobbyMsg()
{
boost::mutex::scoped_lock lock(m_dataMutex);
m_wantsLobbyMsg = false;
}
bool
SessionData::WantsLobbyMsg() const
{
boost::mutex::scoped_lock lock(m_dataMutex);
return m_wantsLobbyMsg;
}
const std::string &
SessionData::GetClientAddr() const
{
+31
View File
@@ -150,6 +150,17 @@ SessionManager::Select(unsigned timeoutMsec)
return retSession;
}
SessionWrapper
SessionManager::GetSessionById(SessionId id) const
{
SessionWrapper tmpSession;
boost::recursive_mutex::scoped_lock lock(m_sessionMapMutex);
SessionMap::const_iterator pos = m_sessionMap.find(id);
if (pos != m_sessionMap.end())
tmpSession = pos->second;
return tmpSession;
}
SessionWrapper
SessionManager::GetSessionByPlayerName(const string playerName) const
{
@@ -365,6 +376,26 @@ SessionManager::SendToAllSessions(SenderThread &sender, boost::shared_ptr<NetPac
}
}
void
SessionManager::SendLobbyMsgToAllSessions(SenderThread &sender, boost::shared_ptr<NetPacket> packet, SessionData::State state)
{
boost::recursive_mutex::scoped_lock lock(m_sessionMapMutex);
SessionMap::iterator i = m_sessionMap.begin();
SessionMap::iterator end = m_sessionMap.end();
while (i != end)
{
if (!i->second.sessionData.get())
throw ServerException(__FILE__, __LINE__, ERR_NET_INVALID_SESSION, 0);
// Send each client (with a certain state) a copy of the packet.
if (i->second.sessionData->GetState() == state && i->second.sessionData->WantsLobbyMsg())
sender.Send(i->second.sessionData, boost::shared_ptr<NetPacket>(packet->Clone()));
++i;
}
}
void
SessionManager::SendToAllButOneSessions(SenderThread &sender, boost::shared_ptr<NetPacket> packet, SessionId except, SessionData::State state)
{
+6
View File
@@ -58,6 +58,7 @@ public:
void MoveSessionToGame(ServerGameThread &game, SessionWrapper session);
void RemoveSessionFromGame(SessionWrapper session);
void SessionError(SessionWrapper session, int errorCode);
void ResubscribeLobbyMsg(SessionWrapper session);
void NotifyPlayerJoinedGame(unsigned gameId, unsigned playerId);
void NotifyPlayerLeftGame(unsigned gameId, unsigned playerId);
void NotifyGameAdminChanged(unsigned gameId, unsigned newAdminPlayerId);
@@ -91,6 +92,7 @@ protected:
typedef std::deque<boost::shared_ptr<ConnectData> > ConnectQueue;
typedef std::deque<SessionWrapper> SessionQueue;
typedef std::list<SessionWrapper> SessionList;
typedef std::list<SessionId> SessionIdList;
typedef std::map<SessionId, boost::timers::portable::microsec_timer> TimerSessionMap;
typedef std::map<unsigned, boost::shared_ptr<ServerGameThread> > GameMap;
typedef std::map<std::string, boost::timers::portable::microsec_timer> TimerClientAddressMap;
@@ -116,6 +118,7 @@ protected:
void NewSessionLoop();
void RemoveGameLoop();
void RemovePlayerLoop();
void ResubscribeLobbyMsgLoop();
void CheckSessionTimeoutsLoop();
void UpdateAvatarClientTimerLoop();
void CleanupAvatarCache();
@@ -123,6 +126,7 @@ protected:
void InternalAddGame(boost::shared_ptr<ServerGameThread> game);
void InternalRemoveGame(boost::shared_ptr<ServerGameThread> game);
void InternalRemovePlayer(unsigned playerId, unsigned errorCode);
void InternalResubscribeMsg(SessionWrapper session);
void TerminateGames();
@@ -179,6 +183,8 @@ private:
PlayerDataMap m_computerPlayers;
mutable boost::mutex m_computerPlayersMutex;
SessionIdList m_resubscribeList;
mutable boost::mutex m_resubscribeListMutex;
GameMap m_gameMap;
+4
View File
@@ -50,6 +50,9 @@ public:
void SetReadyFlag();
void ResetReadyFlag();
bool IsReady() const;
void SetWantsLobbyMsg();
void ResetWantsLobbyMsg();
bool WantsLobbyMsg() const;
const std::string &GetClientAddr() const;
void SetClientAddr(const std::string &addr);
@@ -69,6 +72,7 @@ private:
std::string m_clientAddr;
ReceiveBuffer m_receiveBuffer;
bool m_readyFlag;
bool m_wantsLobbyMsg;
boost::timers::portable::microsec_timer m_activityTimer;
bool m_activityTimeoutNoticeSent;
boost::timers::portable::microsec_timer m_autoDisconnectTimer;
+2
View File
@@ -55,6 +55,7 @@ public:
void RemoveSession(SessionId session);
SessionWrapper Select(unsigned timeoutMsec);
SessionWrapper GetSessionById(SessionId id) const;
SessionWrapper GetSessionByPlayerName(const std::string playerName) const;
SessionWrapper GetSessionByUniquePlayerId(unsigned uniqueId) const;
@@ -74,6 +75,7 @@ public:
unsigned GetRawSessionCount();
void SendToAllSessions(SenderThread &sender, boost::shared_ptr<NetPacket> packet, SessionData::State state);
void SendLobbyMsgToAllSessions(SenderThread &sender, boost::shared_ptr<NetPacket> packet, SessionData::State state);
void SendToAllButOneSessions(SenderThread &sender, boost::shared_ptr<NetPacket> packet, SessionId except, SessionData::State state);
protected: