Rewriting boost asio timer stuff. (Did I mention I dislike the asio "cancel" semantics?!). TimerManager is no longer used. Should be stable now, but might leak some memory (needs further testing).

This commit is contained in:
lotodore
2009-06-12 15:48:34 +00:00
parent a33d9b7c3b
commit 3b25e18fde
6 changed files with 681 additions and 595 deletions
+30 -25
View File
@@ -38,10 +38,10 @@
using namespace std; using namespace std;
ServerGame::ServerGame(ServerLobbyThread &lobbyThread, u_int32_t id, const string &name, const string &pwd, const GameData &gameData, unsigned adminPlayerId, GuiInterface &gui, ConfigFile *playerConfig) ServerGame::ServerGame(boost::shared_ptr<ServerLobbyThread> lobbyThread, u_int32_t id, const string &name, const string &pwd, const GameData &gameData, unsigned adminPlayerId, GuiInterface &gui, ConfigFile *playerConfig)
: m_adminPlayerId(adminPlayerId), m_lobbyThread(lobbyThread), m_gui(gui), : m_adminPlayerId(adminPlayerId), m_lobbyThread(lobbyThread), m_gui(gui),
m_gameData(gameData), m_curState(NULL), m_id(id), m_name(name), m_password(pwd), m_playerConfig(playerConfig), m_gameData(gameData), m_curState(NULL), m_id(id), m_name(name), m_password(pwd), m_playerConfig(playerConfig),
m_gameNum(1), m_curPetitionId(1), m_stateTimerId(0) m_gameNum(1), m_curPetitionId(1), m_voteKickTimer(lobbyThread->GetIOService()), m_stateTimer(lobbyThread->GetIOService())
{ {
LOG_VERBOSE("Game object " << GetId() << " created."); LOG_VERBOSE("Game object " << GetId() << " created.");
@@ -56,10 +56,11 @@ ServerGame::~ServerGame()
void void
ServerGame::Init() ServerGame::Init()
{ {
m_voteKickTimerId = GetLobbyThread().GetTimerManager().RegisterTimer( m_voteKickTimer.expires_from_now(
SERVER_CHECK_VOTE_KICK_INTERVAL_MSEC, boost::posix_time::milliseconds(SERVER_CHECK_VOTE_KICK_INTERVAL_MSEC));
boost::bind(&ServerGame::TimerVoteKick, this), m_voteKickTimer.async_wait(
true); boost::bind(
&ServerGame::TimerVoteKick, shared_from_this(), boost::asio::placeholders::error));
SetState(SERVER_INITIAL_STATE::Instance()); SetState(SERVER_INITIAL_STATE::Instance());
} }
@@ -67,8 +68,9 @@ ServerGame::Init()
void void
ServerGame::Exit() ServerGame::Exit()
{ {
GetLobbyThread().GetTimerManager().UnregisterTimer(m_voteKickTimerId); m_voteKickTimer.cancel();
GetLobbyThread().GetTimerManager().UnregisterTimer(m_stateTimerId); if (m_curState)
m_curState->Exit(shared_from_this());
} }
u_int32_t u_int32_t
@@ -87,7 +89,7 @@ void
ServerGame::AddSession(SessionWrapper session) ServerGame::AddSession(SessionWrapper session)
{ {
if (session.sessionData) if (session.sessionData)
GetState().HandleNewSession(*this, session); GetState().HandleNewSession(shared_from_this(), session);
} }
void void
@@ -103,7 +105,7 @@ void
ServerGame::HandlePacket(SessionWrapper session, boost::shared_ptr<NetPacket> packet) ServerGame::HandlePacket(SessionWrapper session, boost::shared_ptr<NetPacket> packet)
{ {
if (session.sessionData && packet) if (session.sessionData && packet)
GetState().ProcessPacket(*this, session, packet); GetState().ProcessPacket(shared_from_this(), session, packet);
} }
GameState GameState
@@ -123,12 +125,14 @@ ServerGame::RemoveAllSessions()
{ {
// Called from lobby thread. // Called from lobby thread.
// Clean up ALL sessions which are left. // Clean up ALL sessions which are left.
GetSessionManager().ForEach(boost::bind(&ServerLobbyThread::RemoveSessionFromGame, boost::ref(m_lobbyThread), _1)); GetSessionManager().ForEach(boost::bind(&ServerLobbyThread::RemoveSessionFromGame, boost::ref(*m_lobbyThread), _1));
} }
void void
ServerGame::TimerVoteKick() ServerGame::TimerVoteKick(const boost::system::error_code &ec)
{ {
if (!ec)
{
// Check whether someone should be kicked, or whether a vote kick should be aborted. // Check whether someone should be kicked, or whether a vote kick should be aborted.
// Only one vote kick can be active at a time. // Only one vote kick can be active at a time.
if (m_voteKickData) if (m_voteKickData)
@@ -195,6 +199,12 @@ ServerGame::TimerVoteKick()
m_voteKickData.reset(); m_voteKickData.reset();
} }
} }
m_voteKickTimer.expires_from_now(
boost::posix_time::milliseconds(SERVER_CHECK_VOTE_KICK_INTERVAL_MSEC));
m_voteKickTimer.async_wait(
boost::bind(
&ServerGame::TimerVoteKick, shared_from_this(), boost::asio::placeholders::error));
}
} }
void void
@@ -545,7 +555,7 @@ ServerGame::RemovePlayerData(boost::shared_ptr<PlayerData> player, int reason)
SetAdminPlayerId(newAdmin->GetUniqueId()); SetAdminPlayerId(newAdmin->GetUniqueId());
newAdmin->SetRights(PLAYER_RIGHTS_ADMIN); newAdmin->SetRights(PLAYER_RIGHTS_ADMIN);
// Notify game state on admin change // Notify game state on admin change
GetState().NotifyGameAdminChanged(*this); GetState().NotifyGameAdminChanged(shared_from_this());
// Send "Game Admin Changed" to clients. // Send "Game Admin Changed" to clients.
boost::shared_ptr<NetPacket> adminChanged(new NetPacketGameAdminChanged); boost::shared_ptr<NetPacket> adminChanged(new NetPacketGameAdminChanged);
NetPacketGameAdminChanged::Data adminChangedData; NetPacketGameAdminChanged::Data adminChangedData;
@@ -666,7 +676,8 @@ ServerGame::GetSessionManager() const
ServerLobbyThread & ServerLobbyThread &
ServerGame::GetLobbyThread() ServerGame::GetLobbyThread()
{ {
return m_lobbyThread; assert(m_lobbyThread);
return *m_lobbyThread;
} }
ServerCallback & ServerCallback &
@@ -686,21 +697,15 @@ void
ServerGame::SetState(ServerGameState &newState) ServerGame::SetState(ServerGameState &newState)
{ {
if (m_curState) if (m_curState)
m_curState->Exit(*this); m_curState->Exit(shared_from_this());
m_curState = &newState; m_curState = &newState;
m_curState->Enter(*this); m_curState->Enter(shared_from_this());
} }
unsigned boost::asio::deadline_timer &
ServerGame::GetStateTimerId() const ServerGame::GetStateTimer()
{ {
return m_stateTimerId; return m_stateTimer;
}
void
ServerGame::SetStateTimerId(unsigned newTimerId)
{
m_stateTimerId = newTimerId;
} }
ReceiverHelper & ReceiverHelper &
+212 -178
View File
@@ -183,7 +183,7 @@ AbstractServerGameStateReceiving::~AbstractServerGameStateReceiving()
} }
int int
AbstractServerGameStateReceiving::ProcessPacket(ServerGame &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet) AbstractServerGameStateReceiving::ProcessPacket(boost::shared_ptr<ServerGame> server, SessionWrapper session, boost::shared_ptr<NetPacket> packet)
{ {
// This is the receive loop for the server. // This is the receive loop for the server.
int retVal = MSG_SOCK_INTERNAL_PENDING; int retVal = MSG_SOCK_INTERNAL_PENDING;
@@ -193,27 +193,27 @@ AbstractServerGameStateReceiving::ProcessPacket(ServerGame &server, SessionWrapp
if (packet->ToNetPacketRetrievePlayerInfo()) if (packet->ToNetPacketRetrievePlayerInfo())
{ {
// Delegate to Lobby. // Delegate to Lobby.
server.GetLobbyThread().HandleGameRetrievePlayerInfo(session, *packet->ToNetPacketRetrievePlayerInfo()); server->GetLobbyThread().HandleGameRetrievePlayerInfo(session, *packet->ToNetPacketRetrievePlayerInfo());
} }
else if (packet->ToNetPacketRetrieveAvatar()) else if (packet->ToNetPacketRetrieveAvatar())
{ {
// Delegate to Lobby. // Delegate to Lobby.
server.GetLobbyThread().HandleGameRetrieveAvatar(session, *packet->ToNetPacketRetrieveAvatar()); server->GetLobbyThread().HandleGameRetrieveAvatar(session, *packet->ToNetPacketRetrieveAvatar());
} }
else if (packet->ToNetPacketLeaveCurrentGame()) else if (packet->ToNetPacketLeaveCurrentGame())
{ {
server.MoveSessionToLobby(session, NTF_NET_REMOVED_ON_REQUEST); server->MoveSessionToLobby(session, NTF_NET_REMOVED_ON_REQUEST);
} }
else if (packet->ToNetPacketKickPlayer()) else if (packet->ToNetPacketKickPlayer())
{ {
// Only admins are allowed to kick, and only in the lobby. // Only admins are allowed to kick, and only in the lobby.
// After leaving the lobby, a vote needs to be initiated to kick. // After leaving the lobby, a vote needs to be initiated to kick.
if (session.playerData->GetRights() == PLAYER_RIGHTS_ADMIN && !server.IsRunning()) if (session.playerData->GetRights() == PLAYER_RIGHTS_ADMIN && !server->IsRunning())
{ {
NetPacketKickPlayer::Data kickPlayerData; NetPacketKickPlayer::Data kickPlayerData;
packet->ToNetPacketKickPlayer()->GetData(kickPlayerData); packet->ToNetPacketKickPlayer()->GetData(kickPlayerData);
server.InternalKickPlayer(kickPlayerData.playerId); server->InternalKickPlayer(kickPlayerData.playerId);
} }
} }
else if (packet->ToNetPacketAskKickPlayer()) else if (packet->ToNetPacketAskKickPlayer())
@@ -223,7 +223,7 @@ AbstractServerGameStateReceiving::ProcessPacket(ServerGame &server, SessionWrapp
NetPacketAskKickPlayer::Data askKickData; NetPacketAskKickPlayer::Data askKickData;
packet->ToNetPacketAskKickPlayer()->GetData(askKickData); packet->ToNetPacketAskKickPlayer()->GetData(askKickData);
server.InternalAskVoteKick(session, askKickData.playerId, SERVER_VOTE_KICK_TIMEOUT_SEC); server->InternalAskVoteKick(session, askKickData.playerId, SERVER_VOTE_KICK_TIMEOUT_SEC);
} }
} }
else if (packet->ToNetPacketVoteKickPlayer()) else if (packet->ToNetPacketVoteKickPlayer())
@@ -233,7 +233,7 @@ AbstractServerGameStateReceiving::ProcessPacket(ServerGame &server, SessionWrapp
NetPacketVoteKickPlayer::Data voteData; NetPacketVoteKickPlayer::Data voteData;
packet->ToNetPacketVoteKickPlayer()->GetData(voteData); packet->ToNetPacketVoteKickPlayer()->GetData(voteData);
server.InternalVoteKick(session, voteData.petitionId, voteData.vote); server->InternalVoteKick(session, voteData.petitionId, voteData.vote);
} }
} }
// Chat text is always allowed. // Chat text is always allowed.
@@ -251,7 +251,7 @@ AbstractServerGameStateReceiving::ProcessPacket(ServerGame &server, SessionWrapp
outChatData.playerId = session.playerData->GetUniqueId(); outChatData.playerId = session.playerData->GetUniqueId();
outChatData.text = inChatData.text; outChatData.text = inChatData.text;
static_cast<NetPacketChatText *>(outChat.get())->SetData(outChatData); static_cast<NetPacketChatText *>(outChat.get())->SetData(outChatData);
server.SendToAllPlayers(outChat, SessionData::Game); server->SendToAllPlayers(outChat, SessionData::Game);
} }
} }
else if (packet->ToNetPacketUnsubscribeGameList()) else if (packet->ToNetPacketUnsubscribeGameList())
@@ -264,7 +264,7 @@ AbstractServerGameStateReceiving::ProcessPacket(ServerGame &server, SessionWrapp
// This needs to be performed in the lobby thread, // This needs to be performed in the lobby thread,
// because a new game list needs to be sent. // because a new game list needs to be sent.
if (!session.sessionData->WantsLobbyMsg()) if (!session.sessionData->WantsLobbyMsg())
server.GetLobbyThread().ResubscribeLobbyMsg(session); server->GetLobbyThread().ResubscribeLobbyMsg(session);
} }
else else
{ {
@@ -294,44 +294,44 @@ ServerGameStateInit::~ServerGameStateInit()
} }
void void
ServerGameStateInit::Enter(ServerGame &server) ServerGameStateInit::Enter(boost::shared_ptr<ServerGame> server)
{ {
RegisterAdminTimer(server); RegisterAdminTimer(server);
} }
void void
ServerGameStateInit::Exit(ServerGame &server) ServerGameStateInit::Exit(boost::shared_ptr<ServerGame> server)
{ {
UnregisterAdminTimer(server); UnregisterAdminTimer(server);
} }
void void
ServerGameStateInit::NotifyGameAdminChanged(ServerGame &server) ServerGameStateInit::NotifyGameAdminChanged(boost::shared_ptr<ServerGame> server)
{ {
UnregisterAdminTimer(server); UnregisterAdminTimer(server);
RegisterAdminTimer(server); RegisterAdminTimer(server);
} }
void void
ServerGameStateInit::HandleNewSession(ServerGame &server, SessionWrapper session) ServerGameStateInit::HandleNewSession(boost::shared_ptr<ServerGame> server, SessionWrapper session)
{ {
if (session.sessionData.get() && session.playerData.get()) if (session.sessionData.get() && session.playerData.get())
{ {
size_t curNumPlayers = server.GetCurNumberOfPlayers(); size_t curNumPlayers = server->GetCurNumberOfPlayers();
// Check the number of players. // Check the number of players.
if (curNumPlayers >= (size_t)server.GetGameData().maxNumberOfPlayers) if (curNumPlayers >= (size_t)server->GetGameData().maxNumberOfPlayers)
{ {
server.MoveSessionToLobby(session, NTF_NET_REMOVED_GAME_FULL); server->MoveSessionToLobby(session, NTF_NET_REMOVED_GAME_FULL);
} }
// Check whether the client supports the current game. // Check whether the client supports the current game.
else if ((size_t)server.GetGameData().maxNumberOfPlayers > session.sessionData->GetMaxNumPlayers()) else if ((size_t)server->GetGameData().maxNumberOfPlayers > session.sessionData->GetMaxNumPlayers())
{ {
server.MoveSessionToLobby(session, NTF_NET_REMOVED_GAME_FULL); server->MoveSessionToLobby(session, NTF_NET_REMOVED_GAME_FULL);
} }
else else
{ {
if (session.playerData->GetUniqueId() == server.GetAdminPlayerId()) if (session.playerData->GetUniqueId() == server->GetAdminPlayerId())
{ {
// This is the admin player. // This is the admin player.
session.playerData->SetRights(PLAYER_RIGHTS_ADMIN); session.playerData->SetRights(PLAYER_RIGHTS_ADMIN);
@@ -340,55 +340,57 @@ ServerGameStateInit::HandleNewSession(ServerGame &server, SessionWrapper session
// Send ack to client. // Send ack to client.
boost::shared_ptr<NetPacket> joinGameAck(new NetPacketJoinGameAck); boost::shared_ptr<NetPacket> joinGameAck(new NetPacketJoinGameAck);
NetPacketJoinGameAck::Data joinGameAckData; NetPacketJoinGameAck::Data joinGameAckData;
joinGameAckData.gameId = server.GetId(); joinGameAckData.gameId = server->GetId();
joinGameAckData.prights = session.playerData->GetRights(); joinGameAckData.prights = session.playerData->GetRights();
joinGameAckData.gameData = server.GetGameData(); joinGameAckData.gameData = server->GetGameData();
static_cast<NetPacketJoinGameAck *>(joinGameAck.get())->SetData(joinGameAckData); static_cast<NetPacketJoinGameAck *>(joinGameAck.get())->SetData(joinGameAckData);
server.GetLobbyThread().GetSender().Send(session.sessionData, joinGameAck); server->GetLobbyThread().GetSender().Send(session.sessionData, joinGameAck);
// Send notifications for connected players to client. // Send notifications for connected players to client.
PlayerDataList tmpPlayerList = server.GetFullPlayerDataList(); PlayerDataList tmpPlayerList = server->GetFullPlayerDataList();
PlayerDataList::iterator player_i = tmpPlayerList.begin(); PlayerDataList::iterator player_i = tmpPlayerList.begin();
PlayerDataList::iterator player_end = tmpPlayerList.end(); PlayerDataList::iterator player_end = tmpPlayerList.end();
while (player_i != player_end) while (player_i != player_end)
{ {
server.GetLobbyThread().GetSender().Send(session.sessionData, CreateNetPacketPlayerJoined(*(*player_i))); server->GetLobbyThread().GetSender().Send(session.sessionData, CreateNetPacketPlayerJoined(*(*player_i)));
++player_i; ++player_i;
} }
// Send "Player Joined" to other fully connected clients. // Send "Player Joined" to other fully connected clients.
server.SendToAllPlayers(CreateNetPacketPlayerJoined(*session.playerData), SessionData::Game); server->SendToAllPlayers(CreateNetPacketPlayerJoined(*session.playerData), SessionData::Game);
// Accept session. // Accept session.
server.GetSessionManager().AddSession(session); server->GetSessionManager().AddSession(session);
// Notify lobby. // Notify lobby.
server.GetLobbyThread().NotifyPlayerJoinedGame(server.GetId(), session.playerData->GetUniqueId()); server->GetLobbyThread().NotifyPlayerJoinedGame(server->GetId(), session.playerData->GetUniqueId());
} }
} }
} }
void void
ServerGameStateInit::RegisterAdminTimer(ServerGame &server) ServerGameStateInit::RegisterAdminTimer(boost::shared_ptr<ServerGame> server)
{ {
server.SetStateTimerId( server->GetStateTimer().expires_from_now(
server.GetLobbyThread().GetTimerManager().RegisterTimer( boost::posix_time::seconds(SERVER_GAME_ADMIN_TIMEOUT_SEC - SERVER_GAME_ADMIN_WARNING_REMAINING_SEC));
(SERVER_GAME_ADMIN_TIMEOUT_SEC - SERVER_GAME_ADMIN_WARNING_REMAINING_SEC) * 1000, server->GetStateTimer().async_wait(
boost::bind(&ServerGameStateInit::TimerAdminWarning, this, boost::ref(server)))); boost::bind(
&ServerGameStateInit::TimerAdminWarning, this, boost::asio::placeholders::error, server));
} }
void void
ServerGameStateInit::UnregisterAdminTimer(ServerGame &server) ServerGameStateInit::UnregisterAdminTimer(boost::shared_ptr<ServerGame> server)
{ {
server.GetLobbyThread().GetTimerManager().UnregisterTimer(server.GetStateTimerId()); server->GetStateTimer().cancel();
server.SetStateTimerId(0);
} }
void void
ServerGameStateInit::TimerAdminWarning(ServerGame &server) ServerGameStateInit::TimerAdminWarning(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server)
{ {
if (!ec && &server->GetState() == this)
{
// Find game admin. // Find game admin.
SessionWrapper session = server.GetSessionManager().GetSessionByUniquePlayerId(server.GetAdminPlayerId()); SessionWrapper session = server->GetSessionManager().GetSessionByUniquePlayerId(server->GetAdminPlayerId());
if (session.sessionData.get()) if (session.sessionData.get())
{ {
// Send him a warning. // Send him a warning.
@@ -397,29 +399,34 @@ ServerGameStateInit::TimerAdminWarning(ServerGame &server)
warningData.timeoutReason = NETWORK_TIMEOUT_GAME_ADMIN_IDLE; warningData.timeoutReason = NETWORK_TIMEOUT_GAME_ADMIN_IDLE;
warningData.remainingSeconds = SERVER_GAME_ADMIN_WARNING_REMAINING_SEC; warningData.remainingSeconds = SERVER_GAME_ADMIN_WARNING_REMAINING_SEC;
static_cast<NetPacketTimeoutWarning *>(warning.get())->SetData(warningData); static_cast<NetPacketTimeoutWarning *>(warning.get())->SetData(warningData);
server.GetLobbyThread().GetSender().Send(session.sessionData, warning); server->GetLobbyThread().GetSender().Send(session.sessionData, warning);
} }
// Start timeout timer. // Start timeout timer.
server.SetStateTimerId( server->GetStateTimer().expires_from_now(
server.GetLobbyThread().GetTimerManager().RegisterTimer( boost::posix_time::seconds(SERVER_GAME_ADMIN_WARNING_REMAINING_SEC));
SERVER_GAME_ADMIN_WARNING_REMAINING_SEC * 1000, server->GetStateTimer().async_wait(
boost::bind(&ServerGameStateInit::TimerAdminTimeout, this, boost::ref(server)))); boost::bind(
&ServerGameStateInit::TimerAdminTimeout, this, boost::asio::placeholders::error, server));
}
} }
void void
ServerGameStateInit::TimerAdminTimeout(ServerGame &server) ServerGameStateInit::TimerAdminTimeout(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server)
{ {
if (!ec && &server->GetState() == this)
{
// Find game admin. // Find game admin.
SessionWrapper session = server.GetSessionManager().GetSessionByUniquePlayerId(server.GetAdminPlayerId()); SessionWrapper session = server->GetSessionManager().GetSessionByUniquePlayerId(server->GetAdminPlayerId());
if (session.sessionData.get()) if (session.sessionData.get())
{ {
// Remove him from the game. // Remove him from the game.
server.MoveSessionToLobby(session, NTF_NET_REMOVED_TIMEOUT); server->MoveSessionToLobby(session, NTF_NET_REMOVED_TIMEOUT);
}
} }
} }
int int
ServerGameStateInit::InternalProcessPacket(ServerGame &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet) ServerGameStateInit::InternalProcessPacket(boost::shared_ptr<ServerGame> server, SessionWrapper session, boost::shared_ptr<NetPacket> packet)
{ {
int retVal = MSG_SOCK_INTERNAL_PENDING; int retVal = MSG_SOCK_INTERNAL_PENDING;
@@ -432,45 +439,44 @@ ServerGameStateInit::InternalProcessPacket(ServerGame &server, SessionWrapper se
packet->ToNetPacketStartEvent()->GetData(startData); packet->ToNetPacketStartEvent()->GetData(startData);
// Fill up with computer players. // Fill up with computer players.
server.ResetComputerPlayerList(); server->ResetComputerPlayerList();
if (startData.fillUpWithCpuPlayers) if (startData.fillUpWithCpuPlayers)
{ {
int remainingSlots = server.GetGameData().maxNumberOfPlayers - server.GetCurNumberOfPlayers(); int remainingSlots = server->GetGameData().maxNumberOfPlayers - server->GetCurNumberOfPlayers();
for (int i = 1; i <= remainingSlots; i++) for (int i = 1; i <= remainingSlots; i++)
{ {
boost::shared_ptr<PlayerData> tmpPlayerData( boost::shared_ptr<PlayerData> tmpPlayerData(
new PlayerData(server.GetLobbyThread().GetNextUniquePlayerId(), 0, PLAYER_TYPE_COMPUTER, PLAYER_RIGHTS_NORMAL)); new PlayerData(server->GetLobbyThread().GetNextUniquePlayerId(), 0, PLAYER_TYPE_COMPUTER, PLAYER_RIGHTS_NORMAL));
ostringstream name; ostringstream name;
name << SERVER_COMPUTER_PLAYER_NAME << i; name << SERVER_COMPUTER_PLAYER_NAME << i;
tmpPlayerData->SetName(name.str()); tmpPlayerData->SetName(name.str());
server.AddComputerPlayer(tmpPlayerData); server->AddComputerPlayer(tmpPlayerData);
// Send "Player Joined" to other fully connected clients. // Send "Player Joined" to other fully connected clients.
server.SendToAllPlayers(CreateNetPacketPlayerJoined(*tmpPlayerData), SessionData::Game); server->SendToAllPlayers(CreateNetPacketPlayerJoined(*tmpPlayerData), SessionData::Game);
// Notify lobby. // Notify lobby.
server.GetLobbyThread().NotifyPlayerJoinedGame(server.GetId(), tmpPlayerData->GetUniqueId()); server->GetLobbyThread().NotifyPlayerJoinedGame(server->GetId(), tmpPlayerData->GetUniqueId());
} }
} }
// Wait for all players to confirm start of game. // Wait for all players to confirm start of game.
server.SendToAllPlayers(boost::shared_ptr<NetPacket>(packet->Clone()), SessionData::Game); server->SendToAllPlayers(boost::shared_ptr<NetPacket>(packet->Clone()), SessionData::Game);
server.SetState(ServerGameStateStartGame::Instance()); server->SetState(ServerGameStateStartGame::Instance());
} }
} }
else if (packet->ToNetPacketResetTimeout()) else if (packet->ToNetPacketResetTimeout())
{ {
if (session.playerData->GetRights() == PLAYER_RIGHTS_ADMIN) if (session.playerData->GetRights() == PLAYER_RIGHTS_ADMIN)
{ {
UnregisterAdminTimer(server);
RegisterAdminTimer(server); RegisterAdminTimer(server);
} }
} }
else else
{ {
server.SessionError(session, ERR_SOCK_INVALID_PACKET); server->SessionError(session, ERR_SOCK_INVALID_PACKET);
} }
return retVal; return retVal;
@@ -506,40 +512,40 @@ ServerGameStateStartGame::~ServerGameStateStartGame()
} }
void void
ServerGameStateStartGame::Enter(ServerGame &server) ServerGameStateStartGame::Enter(boost::shared_ptr<ServerGame> server)
{ {
server.SetStateTimerId( server->GetStateTimer().expires_from_now(
server.GetLobbyThread().GetTimerManager().RegisterTimer( boost::posix_time::seconds(SERVER_START_GAME_TIMEOUT_SEC));
SERVER_START_GAME_TIMEOUT_SEC * 1000, server->GetStateTimer().async_wait(
boost::bind(&ServerGameStateStartGame::TimerTimeout, this, boost::ref(server)))); boost::bind(
&ServerGameStateStartGame::TimerTimeout, this, boost::asio::placeholders::error, server));
} }
void void
ServerGameStateStartGame::Exit(ServerGame &server) ServerGameStateStartGame::Exit(boost::shared_ptr<ServerGame> server)
{ {
server.GetLobbyThread().GetTimerManager().UnregisterTimer(server.GetStateTimerId()); server->GetStateTimer().cancel();
server.SetStateTimerId(0);
} }
void void
ServerGameStateStartGame::HandleNewSession(ServerGame &server, SessionWrapper session) ServerGameStateStartGame::HandleNewSession(boost::shared_ptr<ServerGame> server, SessionWrapper session)
{ {
// Do not accept new sessions in this state. // Do not accept new sessions in this state.
server.MoveSessionToLobby(session, NTF_NET_REMOVED_ALREADY_RUNNING); server->MoveSessionToLobby(session, NTF_NET_REMOVED_ALREADY_RUNNING);
} }
int int
ServerGameStateStartGame::InternalProcessPacket(ServerGame &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet) ServerGameStateStartGame::InternalProcessPacket(boost::shared_ptr<ServerGame> server, SessionWrapper session, boost::shared_ptr<NetPacket> packet)
{ {
int retVal = MSG_SOCK_INTERNAL_PENDING; int retVal = MSG_SOCK_INTERNAL_PENDING;
if (packet->ToNetPacketStartEventAck()) if (packet->ToNetPacketStartEventAck())
{ {
session.sessionData->SetReadyFlag(); session.sessionData->SetReadyFlag();
if (server.GetSessionManager().CountReadySessions() == server.GetSessionManager().GetRawSessionCount()) if (server->GetSessionManager().CountReadySessions() == server->GetSessionManager().GetRawSessionCount())
{ {
// Everyone is ready. // Everyone is ready.
server.GetSessionManager().ResetAllReadyFlags(); server->GetSessionManager().ResetAllReadyFlags();
DoStart(server); DoStart(server);
retVal = MSG_SOCK_INIT_DONE; retVal = MSG_SOCK_INIT_DONE;
} }
@@ -549,37 +555,40 @@ ServerGameStateStartGame::InternalProcessPacket(ServerGame &server, SessionWrapp
} }
void void
ServerGameStateStartGame::TimerTimeout(ServerGame &server) ServerGameStateStartGame::TimerTimeout(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server)
{ {
if (!ec && &server->GetState() == this)
{
// On timeout: start anyway. // On timeout: start anyway.
server.GetSessionManager().ResetAllReadyFlags(); server->GetSessionManager().ResetAllReadyFlags();
// TODO report successful start! -> new callback?! // TODO report successful start! -> new callback?!
//retVal = MSG_SOCK_INIT_DONE; //retVal = MSG_SOCK_INIT_DONE;
DoStart(server); DoStart(server);
}
} }
void void
ServerGameStateStartGame::DoStart(ServerGame &server) ServerGameStateStartGame::DoStart(boost::shared_ptr<ServerGame> server)
{ {
PlayerDataList tmpPlayerList = server.GetFullPlayerDataList(); PlayerDataList tmpPlayerList = server->GetFullPlayerDataList();
if (tmpPlayerList.size() <= 1) if (tmpPlayerList.size() <= 1)
{ {
if (!tmpPlayerList.empty()) if (!tmpPlayerList.empty())
{ {
boost::shared_ptr<PlayerData> tmpPlayer(tmpPlayerList.front()); boost::shared_ptr<PlayerData> tmpPlayer(tmpPlayerList.front());
SessionWrapper tmpSession = server.GetSessionManager().GetSessionByUniquePlayerId(tmpPlayer->GetUniqueId()); SessionWrapper tmpSession = server->GetSessionManager().GetSessionByUniquePlayerId(tmpPlayer->GetUniqueId());
if (tmpSession.sessionData.get()) if (tmpSession.sessionData.get())
server.MoveSessionToLobby(tmpSession, NTF_NET_REMOVED_START_FAILED); server->MoveSessionToLobby(tmpSession, NTF_NET_REMOVED_START_FAILED);
} }
} }
else else
{ {
server.InternalStartGame(); server->InternalStartGame();
boost::shared_ptr<NetPacket> answer(new NetPacketGameStart); boost::shared_ptr<NetPacket> answer(new NetPacketGameStart);
NetPacketGameStart::Data gameStartData; NetPacketGameStart::Data gameStartData;
gameStartData.startData = server.GetStartData(); gameStartData.startData = server->GetStartData();
// Send player order to clients. // Send player order to clients.
// Assume player list is sorted by number. // Assume player list is sorted by number.
@@ -595,11 +604,11 @@ ServerGameStateStartGame::DoStart(ServerGame &server)
} }
static_cast<NetPacketGameStart *>(answer.get())->SetData(gameStartData); static_cast<NetPacketGameStart *>(answer.get())->SetData(gameStartData);
server.SendToAllPlayers(answer, SessionData::Game); server->SendToAllPlayers(answer, SessionData::Game);
// Start the first hand. // Start the first hand.
ServerGameStateHand::StartNewHand(server); ServerGameStateHand::StartNewHand(server);
server.SetState(ServerGameStateHand::Instance()); server->SetState(ServerGameStateHand::Instance());
} }
} }
@@ -622,39 +631,41 @@ ServerGameStateHand::~ServerGameStateHand()
} }
void void
ServerGameStateHand::Enter(ServerGame &server) ServerGameStateHand::Enter(boost::shared_ptr<ServerGame> server)
{ {
server.SetStateTimerId( server->GetStateTimer().expires_from_now(
server.GetLobbyThread().GetTimerManager().RegisterTimer( boost::posix_time::milliseconds(SERVER_LOOP_DELAY_MSEC));
SERVER_LOOP_DELAY_MSEC, server->GetStateTimer().async_wait(
boost::bind(&ServerGameStateHand::TimerLoop, this, boost::ref(server)))); boost::bind(
&ServerGameStateHand::TimerLoop, this, boost::asio::placeholders::error, server));
} }
void void
ServerGameStateHand::Exit(ServerGame &server) ServerGameStateHand::Exit(boost::shared_ptr<ServerGame> server)
{ {
server.GetLobbyThread().GetTimerManager().UnregisterTimer(server.GetStateTimerId()); server->GetStateTimer().cancel();
server.SetStateTimerId(0);
} }
void void
ServerGameStateHand::HandleNewSession(ServerGame &server, SessionWrapper session) ServerGameStateHand::HandleNewSession(boost::shared_ptr<ServerGame> server, SessionWrapper session)
{ {
// Do not accept new sessions in this state. // Do not accept new sessions in this state.
server.MoveSessionToLobby(session, NTF_NET_REMOVED_ALREADY_RUNNING); server->MoveSessionToLobby(session, NTF_NET_REMOVED_ALREADY_RUNNING);
} }
int int
ServerGameStateHand::InternalProcessPacket(ServerGame &/*server*/, SessionWrapper /*session*/, boost::shared_ptr<NetPacket> /*packet*/) ServerGameStateHand::InternalProcessPacket(boost::shared_ptr<ServerGame> /*server*/, SessionWrapper /*session*/, boost::shared_ptr<NetPacket> /*packet*/)
{ {
// TODO: maybe reject packet. // TODO: maybe reject packet.
return MSG_SOCK_INTERNAL_PENDING; return MSG_SOCK_INTERNAL_PENDING;
} }
void void
ServerGameStateHand::TimerLoop(ServerGame &server) ServerGameStateHand::TimerLoop(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server)
{ {
Game &curGame = server.GetGame(); if (!ec && &server->GetState() == this)
{
Game &curGame = server->GetGame();
// Main game loop. // Main game loop.
int curRound = curGame.getCurrentHand()->getCurrentRound(); int curRound = curGame.getCurrentHand()->getCurrentRound();
@@ -698,22 +709,24 @@ ServerGameStateHand::TimerLoop(ServerGame &server)
++i; ++i;
} }
static_cast<NetPacketAllInShowCards *>(allIn.get())->SetData(allInData); static_cast<NetPacketAllInShowCards *>(allIn.get())->SetData(allInData);
server.SendToAllPlayers(allIn, SessionData::Game); server->SendToAllPlayers(allIn, SessionData::Game);
curGame.getCurrentHand()->setCardsShown(true); curGame.getCurrentHand()->setCardsShown(true);
server.SetStateTimerId( server->GetStateTimer().expires_from_now(
server.GetLobbyThread().GetTimerManager().RegisterTimer( boost::posix_time::seconds(SERVER_SHOW_CARDS_DELAY_SEC));
SERVER_SHOW_CARDS_DELAY_SEC * 1000, server->GetStateTimer().async_wait(
boost::bind(&ServerGameStateHand::TimerLoop, this, boost::ref(server)))); boost::bind(
&ServerGameStateHand::TimerLoop, this, boost::asio::placeholders::error, server));
} }
else else
{ {
SendNewRoundCards(server, curGame, newRound); SendNewRoundCards(*server, curGame, newRound);
server.SetStateTimerId( server->GetStateTimer().expires_from_now(
server.GetLobbyThread().GetTimerManager().RegisterTimer( boost::posix_time::seconds(GetDealCardsDelaySec(*server)));
GetDealCardsDelaySec(server) * 1000, server->GetStateTimer().async_wait(
boost::bind(&ServerGameStateHand::TimerLoop, this, boost::ref(server)))); boost::bind(
&ServerGameStateHand::TimerLoop, this, boost::asio::placeholders::error, server));
} }
} }
else else
@@ -736,28 +749,31 @@ ServerGameStateHand::TimerLoop(ServerGame &server)
playersTurnData.playerId = curPlayer->getMyUniqueID(); playersTurnData.playerId = curPlayer->getMyUniqueID();
static_cast<NetPacketPlayersTurn *>(notification.get())->SetData(playersTurnData); static_cast<NetPacketPlayersTurn *>(notification.get())->SetData(playersTurnData);
server.SendToAllPlayers(notification, SessionData::Game); server->SendToAllPlayers(notification, SessionData::Game);
// If the player is computer controlled, let the engine act. // If the player is computer controlled, let the engine act.
if (curPlayer->getMyType() == PLAYER_TYPE_COMPUTER) if (curPlayer->getMyType() == PLAYER_TYPE_COMPUTER)
{ {
server.SetStateTimerId( server->GetStateTimer().expires_from_now(
server.GetLobbyThread().GetTimerManager().RegisterTimer( boost::posix_time::seconds(SERVER_COMPUTER_ACTION_DELAY_SEC));
SERVER_COMPUTER_ACTION_DELAY_SEC * 1000, server->GetStateTimer().async_wait(
boost::bind(&ServerGameStateHand::TimerComputerAction, this, boost::ref(server)))); boost::bind(
&ServerGameStateHand::TimerComputerAction, this, boost::asio::placeholders::error, server));
} }
// If the player we are waiting for left, continue without him. // If the player we are waiting for left, continue without him.
else if (!server.GetSessionManager().IsPlayerConnected(curPlayer->getMyName())) else if (!server->GetSessionManager().IsPlayerConnected(curPlayer->getMyName()))
{ {
PerformPlayerAction(server, curPlayer, PLAYER_ACTION_FOLD, 0); PerformPlayerAction(*server, curPlayer, PLAYER_ACTION_FOLD, 0);
server.SetStateTimerId(
server.GetLobbyThread().GetTimerManager().RegisterTimer( server->GetStateTimer().expires_from_now(
SERVER_LOOP_DELAY_MSEC, boost::posix_time::milliseconds(SERVER_LOOP_DELAY_MSEC));
boost::bind(&ServerGameStateHand::TimerLoop, this, boost::ref(server)))); server->GetStateTimer().async_wait(
boost::bind(
&ServerGameStateHand::TimerLoop, this, boost::asio::placeholders::error, server));
} }
else else
{ {
server.SetState(ServerGameStateWaitPlayerAction::Instance()); server->SetState(ServerGameStateWaitPlayerAction::Instance());
} }
} }
else // hand is over else // hand is over
@@ -780,7 +796,7 @@ ServerGameStateHand::TimerLoop(ServerGame &server)
endHandData.playerMoney = player->getMyCash(); endHandData.playerMoney = player->getMyCash();
static_cast<NetPacketEndOfHandHideCards *>(endHand.get())->SetData(endHandData); static_cast<NetPacketEndOfHandHideCards *>(endHand.get())->SetData(endHandData);
server.SendToAllPlayers(endHand, SessionData::Game); server->SendToAllPlayers(endHand, SessionData::Game);
} }
else else
{ {
@@ -815,11 +831,11 @@ ServerGameStateHand::TimerLoop(ServerGame &server)
} }
static_cast<NetPacketEndOfHandShowCards *>(endHand.get())->SetData(endHandData); static_cast<NetPacketEndOfHandShowCards *>(endHand.get())->SetData(endHandData);
server.SendToAllPlayers(endHand, SessionData::Game); server->SendToAllPlayers(endHand, SessionData::Game);
} }
// Remove disconnected players. This is the one and only place to do this. // Remove disconnected players. This is the one and only place to do this.
server.RemoveDisconnectedPlayers(); server->RemoveDisconnectedPlayers();
// Start next hand - if enough players are left. // Start next hand - if enough players are left.
list<boost::shared_ptr<PlayerInterface> > playersWithCash = *curGame.getActivePlayerList(); list<boost::shared_ptr<PlayerInterface> > playersWithCash = *curGame.getActivePlayerList();
@@ -828,60 +844,75 @@ ServerGameStateHand::TimerLoop(ServerGame &server)
if (playersWithCash.empty()) if (playersWithCash.empty())
{ {
// No more players left - restart. // No more players left - restart.
server.SetState(SERVER_INITIAL_STATE::Instance()); server->SetState(SERVER_INITIAL_STATE::Instance());
} }
else if (playersWithCash.size() == 1) else if (playersWithCash.size() == 1)
{ {
// View a dialog for a new game - delayed. // View a dialog for a new game - delayed.
server.SetStateTimerId( server->GetStateTimer().expires_from_now(
server.GetLobbyThread().GetTimerManager().RegisterTimer( boost::posix_time::seconds(SERVER_DELAY_NEXT_GAME_SEC));
SERVER_DELAY_NEXT_GAME_SEC * 1000, server->GetStateTimer().async_wait(
boost::bind(&ServerGameStateHand::TimerNextGame, this, boost::ref(server)))); boost::bind(
&ServerGameStateHand::TimerNextGame, this, boost::asio::placeholders::error, server));
} }
else else
{ {
server.SetStateTimerId( server->GetStateTimer().expires_from_now(
server.GetLobbyThread().GetTimerManager().RegisterTimer( boost::posix_time::seconds(SERVER_DELAY_NEXT_HAND_SEC));
SERVER_DELAY_NEXT_HAND_SEC * 1000, server->GetStateTimer().async_wait(
boost::bind(&ServerGameStateHand::TimerNextHand, this, boost::ref(server)))); boost::bind(
&ServerGameStateHand::TimerNextHand, this, boost::asio::placeholders::error, server));
}
} }
} }
} }
} }
void void
ServerGameStateHand::TimerShowCards(ServerGame &server) ServerGameStateHand::TimerShowCards(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server)
{ {
Game &curGame = server.GetGame(); if (!ec && &server->GetState() == this)
SendNewRoundCards(server, curGame, curGame.getCurrentHand()->getCurrentRound()); {
Game &curGame = server->GetGame();
SendNewRoundCards(*server, curGame, curGame.getCurrentHand()->getCurrentRound());
server.SetStateTimerId( server->GetStateTimer().expires_from_now(
server.GetLobbyThread().GetTimerManager().RegisterTimer( boost::posix_time::seconds(GetDealCardsDelaySec(*server)));
GetDealCardsDelaySec(server) * 1000, server->GetStateTimer().async_wait(
boost::bind(&ServerGameStateHand::TimerLoop, this, boost::ref(server)))); boost::bind(
&ServerGameStateHand::TimerLoop, this, boost::asio::placeholders::error, server));
}
} }
void void
ServerGameStateHand::TimerComputerAction(ServerGame &server) ServerGameStateHand::TimerComputerAction(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server)
{ {
boost::shared_ptr<PlayerInterface> tmpPlayer = server.GetGame().getCurrentPlayer(); if (!ec && &server->GetState() == this)
{
boost::shared_ptr<PlayerInterface> tmpPlayer = server->GetGame().getCurrentPlayer();
tmpPlayer->action(); tmpPlayer->action();
SendPlayerAction(server, tmpPlayer); SendPlayerAction(*server, tmpPlayer);
TimerLoop(server); TimerLoop(ec, server);
}
} }
void void
ServerGameStateHand::TimerNextHand(ServerGame &server) ServerGameStateHand::TimerNextHand(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server)
{ {
if (!ec && &server->GetState() == this)
{
StartNewHand(server); StartNewHand(server);
TimerLoop(server); TimerLoop(ec, server);
}
} }
void void
ServerGameStateHand::TimerNextGame(ServerGame &server) ServerGameStateHand::TimerNextGame(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server)
{ {
Game &curGame = server.GetGame(); if (!ec && &server->GetState() == this)
{
Game &curGame = server->GetGame();
// The game has ended. Notify all clients. // The game has ended. Notify all clients.
boost::shared_ptr<PlayerInterface> winnerPlayer; boost::shared_ptr<PlayerInterface> winnerPlayer;
PlayerListIterator i = curGame.getActivePlayerList()->begin(); PlayerListIterator i = curGame.getActivePlayerList()->begin();
@@ -899,13 +930,14 @@ ServerGameStateHand::TimerNextGame(ServerGame &server)
endGameData.winnerPlayerId = winnerPlayer->getMyUniqueID(); endGameData.winnerPlayerId = winnerPlayer->getMyUniqueID();
static_cast<NetPacketEndOfGame *>(endGame.get())->SetData(endGameData); static_cast<NetPacketEndOfGame *>(endGame.get())->SetData(endGameData);
server.SendToAllPlayers(endGame, SessionData::Game); server->SendToAllPlayers(endGame, SessionData::Game);
// Wait for the start of a new game. // Wait for the start of a new game.
server.ResetComputerPlayerList(); server->ResetComputerPlayerList();
server.ResetGame(); server->ResetGame();
server.GetLobbyThread().NotifyReopeningGame(server.GetId()); server->GetLobbyThread().NotifyReopeningGame(server->GetId());
server.SetState(ServerGameStateInit::Instance()); server->SetState(ServerGameStateInit::Instance());
}
} }
int int
@@ -931,10 +963,10 @@ ServerGameStateHand::GetDealCardsDelaySec(ServerGame &server)
} }
void void
ServerGameStateHand::StartNewHand(ServerGame &server) ServerGameStateHand::StartNewHand(boost::shared_ptr<ServerGame> server)
{ {
// Initialize hand. // Initialize hand.
Game &curGame = server.GetGame(); Game &curGame = server->GetGame();
curGame.initHand(); curGame.initHand();
// HACK: Skip GUI notification run // HACK: Skip GUI notification run
@@ -962,7 +994,7 @@ ServerGameStateHand::StartNewHand(ServerGame &server)
handStartData.smallBlind = curGame.getCurrentHand()->getSmallBlind(); handStartData.smallBlind = curGame.getCurrentHand()->getSmallBlind();
static_cast<NetPacketHandStart *>(notifyCards.get())->SetData(handStartData); static_cast<NetPacketHandStart *>(notifyCards.get())->SetData(handStartData);
server.GetLobbyThread().GetSender().Send(tmpPlayer->getNetSessionData(), notifyCards); server->GetLobbyThread().GetSender().Send(tmpPlayer->getNetSessionData(), notifyCards);
} }
++i; ++i;
} }
@@ -986,10 +1018,10 @@ ServerGameStateHand::StartNewHand(ServerGame &server)
actionDoneData.playerAction = (PlayerAction)tmpPlayer->getMyAction(); actionDoneData.playerAction = (PlayerAction)tmpPlayer->getMyAction();
actionDoneData.totalPlayerBet = tmpPlayer->getMySet(); actionDoneData.totalPlayerBet = tmpPlayer->getMySet();
actionDoneData.playerMoney = tmpPlayer->getMyCash(); actionDoneData.playerMoney = tmpPlayer->getMyCash();
actionDoneData.highestSet = server.GetGame().getCurrentHand()->getCurrentBeRo()->getHighestSet(); actionDoneData.highestSet = server->GetGame().getCurrentHand()->getCurrentBeRo()->getHighestSet();
actionDoneData.minimumRaise = server.GetGame().getCurrentHand()->getCurrentBeRo()->getMinimumRaise(); actionDoneData.minimumRaise = server->GetGame().getCurrentHand()->getCurrentBeRo()->getMinimumRaise();
static_cast<NetPacketPlayersActionDone *>(notifySmallBlind.get())->SetData(actionDoneData); static_cast<NetPacketPlayersActionDone *>(notifySmallBlind.get())->SetData(actionDoneData);
server.SendToAllPlayers(notifySmallBlind, SessionData::Game); server->SendToAllPlayers(notifySmallBlind, SessionData::Game);
break; break;
} }
++i; ++i;
@@ -1009,10 +1041,10 @@ ServerGameStateHand::StartNewHand(ServerGame &server)
actionDoneData.playerAction = (PlayerAction)tmpPlayer->getMyAction(); actionDoneData.playerAction = (PlayerAction)tmpPlayer->getMyAction();
actionDoneData.totalPlayerBet = tmpPlayer->getMySet(); actionDoneData.totalPlayerBet = tmpPlayer->getMySet();
actionDoneData.playerMoney = tmpPlayer->getMyCash(); actionDoneData.playerMoney = tmpPlayer->getMyCash();
actionDoneData.highestSet = server.GetGame().getCurrentHand()->getCurrentBeRo()->getHighestSet(); actionDoneData.highestSet = server->GetGame().getCurrentHand()->getCurrentBeRo()->getHighestSet();
actionDoneData.minimumRaise = server.GetGame().getCurrentHand()->getCurrentBeRo()->getMinimumRaise(); actionDoneData.minimumRaise = server->GetGame().getCurrentHand()->getCurrentBeRo()->getMinimumRaise();
static_cast<NetPacketPlayersActionDone *>(notifyBigBlind.get())->SetData(actionDoneData); static_cast<NetPacketPlayersActionDone *>(notifyBigBlind.get())->SetData(actionDoneData);
server.SendToAllPlayers(notifyBigBlind, SessionData::Game); server->SendToAllPlayers(notifyBigBlind, SessionData::Game);
break; break;
} }
++i; ++i;
@@ -1039,36 +1071,35 @@ ServerGameStateWaitPlayerAction::~ServerGameStateWaitPlayerAction()
} }
void void
ServerGameStateWaitPlayerAction::Enter(ServerGame &server) ServerGameStateWaitPlayerAction::Enter(boost::shared_ptr<ServerGame> server)
{ {
#ifdef SERVER_TEST #ifdef SERVER_TEST
int timeoutSec = 0; int timeoutSec = 0;
#else #else
int timeoutSec = server.GetGameData().playerActionTimeoutSec + SERVER_PLAYER_TIMEOUT_ADD_DELAY_SEC; int timeoutSec = server->GetGameData().playerActionTimeoutSec + SERVER_PLAYER_TIMEOUT_ADD_DELAY_SEC;
#endif #endif
server.SetStateTimerId( server->GetStateTimer().expires_from_now(boost::posix_time::seconds(timeoutSec));
server.GetLobbyThread().GetTimerManager().RegisterTimer( server->GetStateTimer().async_wait(
timeoutSec * 1000, boost::bind(
boost::bind(&ServerGameStateWaitPlayerAction::TimerTimeout, this, boost::ref(server)))); &ServerGameStateWaitPlayerAction::TimerTimeout, this, boost::asio::placeholders::error, server));
} }
void void
ServerGameStateWaitPlayerAction::Exit(ServerGame &server) ServerGameStateWaitPlayerAction::Exit(boost::shared_ptr<ServerGame> server)
{ {
server.GetLobbyThread().GetTimerManager().UnregisterTimer(server.GetStateTimerId()); server->GetStateTimer().cancel();
server.SetStateTimerId(0);
} }
void void
ServerGameStateWaitPlayerAction::HandleNewSession(ServerGame &server, SessionWrapper session) ServerGameStateWaitPlayerAction::HandleNewSession(boost::shared_ptr<ServerGame> server, SessionWrapper session)
{ {
// Do not accept new sessions in this state. // Do not accept new sessions in this state.
server.MoveSessionToLobby(session, NTF_NET_REMOVED_ALREADY_RUNNING); server->MoveSessionToLobby(session, NTF_NET_REMOVED_ALREADY_RUNNING);
} }
int int
ServerGameStateWaitPlayerAction::InternalProcessPacket(ServerGame &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet) ServerGameStateWaitPlayerAction::InternalProcessPacket(boost::shared_ptr<ServerGame> server, SessionWrapper session, boost::shared_ptr<NetPacket> packet)
{ {
int retVal = MSG_SOCK_INTERNAL_PENDING; int retVal = MSG_SOCK_INTERNAL_PENDING;
@@ -1077,7 +1108,7 @@ ServerGameStateWaitPlayerAction::InternalProcessPacket(ServerGame &server, Sessi
NetPacketPlayersAction::Data actionData; NetPacketPlayersAction::Data actionData;
packet->ToNetPacketPlayersAction()->GetData(actionData); packet->ToNetPacketPlayersAction()->GetData(actionData);
Game &curGame = server.GetGame(); Game &curGame = server->GetGame();
boost::shared_ptr<PlayerInterface> tmpPlayer = curGame.getPlayerByUniqueId(session.playerData->GetUniqueId()); boost::shared_ptr<PlayerInterface> tmpPlayer = curGame.getPlayerByUniqueId(session.playerData->GetUniqueId());
if (!tmpPlayer.get()) if (!tmpPlayer.get())
throw ServerException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0); throw ServerException(__FILE__, __LINE__, ERR_NET_UNKNOWN_PLAYER_ID, 0);
@@ -1088,7 +1119,7 @@ ServerGameStateWaitPlayerAction::InternalProcessPacket(ServerGame &server, Sessi
code = ACTION_CODE_INVALID_STATE; code = ACTION_CODE_INVALID_STATE;
// Check whether this is the correct player. // Check whether this is the correct player.
boost::shared_ptr<PlayerInterface> curPlayer = server.GetGame().getCurrentPlayer(); boost::shared_ptr<PlayerInterface> curPlayer = server->GetGame().getCurrentPlayer();
if (code == ACTION_CODE_VALID if (code == ACTION_CODE_VALID
&& (curPlayer->getMyUniqueID() != tmpPlayer->getMyUniqueID())) && (curPlayer->getMyUniqueID() != tmpPlayer->getMyUniqueID()))
{ {
@@ -1120,8 +1151,8 @@ ServerGameStateWaitPlayerAction::InternalProcessPacket(ServerGame &server, Sessi
if (code == ACTION_CODE_VALID) if (code == ACTION_CODE_VALID)
{ {
PerformPlayerAction(server, tmpPlayer, actionData.playerAction, actionData.playerBet); PerformPlayerAction(*server, tmpPlayer, actionData.playerAction, actionData.playerBet);
server.SetState(ServerGameStateHand::Instance()); server->SetState(ServerGameStateHand::Instance());
retVal = MSG_NET_GAME_SERVER_ACTION; retVal = MSG_NET_GAME_SERVER_ACTION;
} }
else else
@@ -1134,7 +1165,7 @@ ServerGameStateWaitPlayerAction::InternalProcessPacket(ServerGame &server, Sessi
rejectData.playerBet = actionData.playerBet; rejectData.playerBet = actionData.playerBet;
rejectData.rejectionReason = code; rejectData.rejectionReason = code;
static_cast<NetPacketPlayersActionRejected *>(reject.get())->SetData(rejectData); static_cast<NetPacketPlayersActionRejected *>(reject.get())->SetData(rejectData);
server.GetLobbyThread().GetSender().Send(session.sessionData, reject); server->GetLobbyThread().GetSender().Send(session.sessionData, reject);
} }
} }
@@ -1142,9 +1173,11 @@ ServerGameStateWaitPlayerAction::InternalProcessPacket(ServerGame &server, Sessi
} }
void void
ServerGameStateWaitPlayerAction::TimerTimeout(ServerGame &server) ServerGameStateWaitPlayerAction::TimerTimeout(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server)
{ {
Game &curGame = server.GetGame(); if (!ec && &server->GetState() == this)
{
Game &curGame = server->GetGame();
// Retrieve current player. // Retrieve current player.
boost::shared_ptr<PlayerInterface> curPlayer = curGame.getCurrentPlayer(); boost::shared_ptr<PlayerInterface> curPlayer = curGame.getCurrentPlayer();
if (!curPlayer.get()) if (!curPlayer.get())
@@ -1152,11 +1185,12 @@ ServerGameStateWaitPlayerAction::TimerTimeout(ServerGame &server)
// Player did not act fast enough. Act for him. // Player did not act fast enough. Act for him.
if (curGame.getCurrentHand()->getCurrentBeRo()->getHighestSet() == curPlayer->getMySet()) if (curGame.getCurrentHand()->getCurrentBeRo()->getHighestSet() == curPlayer->getMySet())
PerformPlayerAction(server, curPlayer, PLAYER_ACTION_CHECK, 0); PerformPlayerAction(*server, curPlayer, PLAYER_ACTION_CHECK, 0);
else else
PerformPlayerAction(server, curPlayer, PLAYER_ACTION_FOLD, 0); PerformPlayerAction(*server, curPlayer, PLAYER_ACTION_FOLD, 0);
server.SetState(ServerGameStateHand::Instance()); server->SetState(ServerGameStateHand::Instance());
}
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
+82 -42
View File
@@ -89,9 +89,12 @@ private:
ServerLobbyThread::ServerLobbyThread(GuiInterface &gui, ConfigFile *playerConfig, AvatarManager &avatarManager, ServerLobbyThread::ServerLobbyThread(GuiInterface &gui, ConfigFile *playerConfig, AvatarManager &avatarManager,
boost::shared_ptr<boost::asio::io_service> ioService) boost::shared_ptr<boost::asio::io_service> ioService)
: m_ioService(ioService), m_timerManager(ioService), m_curBanId(0), m_gui(gui), m_avatarManager(avatarManager), : m_ioService(ioService), m_curBanId(0), m_gui(gui), m_avatarManager(avatarManager),
m_playerConfig(playerConfig), m_curGameId(0), m_curUniquePlayerId(0), m_curSessionId(INVALID_SESSION + 1), m_playerConfig(playerConfig), m_curGameId(0), m_curUniquePlayerId(0), m_curSessionId(INVALID_SESSION + 1),
m_statDataChanged(false), m_startTime(boost::posix_time::second_clock::local_time()) m_statDataChanged(false), m_removeGameTimer(*ioService), m_removePlayerTimer(*ioService),
m_sessionTimeoutTimer(*ioService), m_avatarCleanupTimer(*ioService),
m_saveStatisticsTimer(*ioService), m_avatarLockTimer(*ioService),
m_startTime(boost::posix_time::second_clock::local_time())
{ {
m_senderCallback.reset(new ServerSenderCallback(*this)); m_senderCallback.reset(new ServerSenderCallback(*this));
m_sender.reset(new SenderHelper(*m_senderCallback, m_ioService)); m_sender.reset(new SenderHelper(*m_senderCallback, m_ioService));
@@ -449,12 +452,6 @@ ServerLobbyThread::RemoveComputerPlayer(boost::shared_ptr<PlayerData> player)
m_computerPlayers.erase(player->GetUniqueId()); m_computerPlayers.erase(player->GetUniqueId());
} }
TimerManager &
ServerLobbyThread::GetTimerManager()
{
return m_timerManager;
}
AvatarManager & AvatarManager &
ServerLobbyThread::GetAvatarManager() ServerLobbyThread::GetAvatarManager()
{ {
@@ -481,6 +478,13 @@ ServerLobbyThread::GetSender()
return *m_sender; return *m_sender;
} }
boost::asio::io_service &
ServerLobbyThread::GetIOService()
{
assert(m_ioService);
return *m_ioService;
}
u_int32_t u_int32_t
ServerLobbyThread::GetNextUniquePlayerId() ServerLobbyThread::GetNextUniquePlayerId()
{ {
@@ -505,11 +509,10 @@ ServerLobbyThread::GetNextGameId()
void void
ServerLobbyThread::Main() ServerLobbyThread::Main()
{ {
try
{
// Register all timers. // Register all timers.
RegisterTimers(); RegisterTimers();
try
{
m_work.reset(new boost::asio::io_service::work(*m_ioService)); m_work.reset(new boost::asio::io_service::work(*m_ioService));
m_ioService->run(); // Will only be aborted asynchronously. m_ioService->run(); // Will only be aborted asynchronously.
m_work.reset(); m_work.reset();
@@ -525,41 +528,60 @@ ServerLobbyThread::Main()
GetCallback().SignalNetServerError(e.GetErrorId(), e.GetOsErrorCode()); GetCallback().SignalNetServerError(e.GetErrorId(), e.GetOsErrorCode());
LOG_ERROR(e.what()); LOG_ERROR(e.what());
} }
// Cancel pending timer callbacks.
CancelTimers();
} }
void void
ServerLobbyThread::RegisterTimers() ServerLobbyThread::RegisterTimers()
{ {
// Remove closed games. // Remove closed games.
m_timerManager.RegisterTimer( m_removeGameTimer.expires_from_now(
SERVER_REMOVE_GAME_INTERVAL_MSEC, boost::posix_time::milliseconds(SERVER_REMOVE_GAME_INTERVAL_MSEC));
boost::bind(&ServerLobbyThread::TimerRemoveGame, this), m_removeGameTimer.async_wait(
true); boost::bind(
&ServerLobbyThread::TimerRemoveGame, shared_from_this(), boost::asio::placeholders::error));
// Remove inactive/kicked players. // Remove inactive/kicked players.
m_timerManager.RegisterTimer( m_removePlayerTimer.expires_from_now(
SERVER_REMOVE_PLAYER_INTERVAL_MSEC, boost::posix_time::milliseconds(SERVER_REMOVE_PLAYER_INTERVAL_MSEC));
boost::bind(&ServerLobbyThread::TimerRemovePlayer, this), m_removePlayerTimer.async_wait(
true); boost::bind(
&ServerLobbyThread::TimerRemovePlayer, shared_from_this(), boost::asio::placeholders::error));
// Check the timeout of sessions which have not been initialised. // Check the timeout of sessions which have not been initialised.
m_timerManager.RegisterTimer( m_sessionTimeoutTimer.expires_from_now(
SERVER_CHECK_SESSION_TIMEOUTS_INTERVAL_MSEC, boost::posix_time::milliseconds(SERVER_CHECK_SESSION_TIMEOUTS_INTERVAL_MSEC));
boost::bind(&ServerLobbyThread::TimerCheckSessionTimeouts, this), m_sessionTimeoutTimer.async_wait(
true); boost::bind(
&ServerLobbyThread::TimerCheckSessionTimeouts, shared_from_this(), boost::asio::placeholders::error));
// Cleanup the avatar cache. Note: Only works if there are no users on the server. // Cleanup the avatar cache. Note: Only works if there are no users on the server.
m_timerManager.RegisterTimer( m_avatarCleanupTimer.expires_from_now(
SERVER_CACHE_CLEANUP_INTERVAL_SEC * 1000, boost::posix_time::seconds(SERVER_CACHE_CLEANUP_INTERVAL_SEC));
boost::bind(&ServerLobbyThread::TimerCleanupAvatarCache, this), m_avatarCleanupTimer.async_wait(
true); boost::bind(
&ServerLobbyThread::TimerCleanupAvatarCache, shared_from_this(), boost::asio::placeholders::error));
// Update the statistics file. // Update the statistics file.
m_timerManager.RegisterTimer( m_saveStatisticsTimer.expires_from_now(
SERVER_SAVE_STATISTICS_INTERVAL_SEC * 1000, boost::posix_time::seconds(SERVER_SAVE_STATISTICS_INTERVAL_SEC));
boost::bind(&ServerLobbyThread::TimerSaveStatisticsFile, this), m_saveStatisticsTimer.async_wait(
true); boost::bind(
&ServerLobbyThread::TimerSaveStatisticsFile, shared_from_this(), boost::asio::placeholders::error));
// Update the avatar upload locks. // Update the avatar upload locks.
m_timerManager.RegisterTimer( m_avatarLockTimer.expires_from_now(
SERVER_UPDATE_AVATAR_LOCK_INTERVAL_MSEC, boost::posix_time::milliseconds(SERVER_UPDATE_AVATAR_LOCK_INTERVAL_MSEC));
boost::bind(&ServerLobbyThread::TimerUpdateClientAvatarLock, this), m_avatarLockTimer.async_wait(
true); boost::bind(
&ServerLobbyThread::TimerUpdateClientAvatarLock, shared_from_this(), boost::asio::placeholders::error));
}
void
ServerLobbyThread::CancelTimers()
{
m_removeGameTimer.cancel();
m_removePlayerTimer.cancel();
m_sessionTimeoutTimer.cancel();
m_avatarCleanupTimer.cancel();
m_saveStatisticsTimer.cancel();
m_avatarLockTimer.cancel();
} }
void void
@@ -941,7 +963,7 @@ ServerLobbyThread::HandleNetPacketCreateGame(SessionWrapper session, const NetPa
boost::shared_ptr<ServerGame> game( boost::shared_ptr<ServerGame> game(
new ServerGame( new ServerGame(
*this, shared_from_this(),
GetNextGameId(), GetNextGameId(),
createGameData.gameName, createGameData.gameName,
createGameData.password, createGameData.password,
@@ -1032,8 +1054,10 @@ ServerLobbyThread::RequestPlayerAvatar(SessionWrapper session)
} }
void void
ServerLobbyThread::TimerRemoveGame() ServerLobbyThread::TimerRemoveGame(const boost::system::error_code &ec)
{ {
if (!ec)
{
// Synchronously remove games which have been closed. // Synchronously remove games which have been closed.
GameMap::iterator i = m_gameMap.begin(); GameMap::iterator i = m_gameMap.begin();
GameMap::iterator end = m_gameMap.end(); GameMap::iterator end = m_gameMap.end();
@@ -1046,11 +1070,14 @@ ServerLobbyThread::TimerRemoveGame()
InternalRemoveGame(tmpGame); // This will delete the game. InternalRemoveGame(tmpGame); // This will delete the game.
i = next; i = next;
} }
}
} }
void void
ServerLobbyThread::TimerRemovePlayer() ServerLobbyThread::TimerRemovePlayer(const boost::system::error_code &ec)
{ {
if (!ec)
{
boost::mutex::scoped_lock lock(m_removePlayerListMutex); boost::mutex::scoped_lock lock(m_removePlayerListMutex);
if (!m_removePlayerList.empty()) if (!m_removePlayerList.empty())
@@ -1065,11 +1092,14 @@ ServerLobbyThread::TimerRemovePlayer()
} }
m_removePlayerList.clear(); m_removePlayerList.clear();
} }
}
} }
void void
ServerLobbyThread::TimerUpdateClientAvatarLock() ServerLobbyThread::TimerUpdateClientAvatarLock(const boost::system::error_code &ec)
{ {
if (!ec)
{
boost::mutex::scoped_lock lock(m_timerAvatarClientAddressMapMutex); boost::mutex::scoped_lock lock(m_timerAvatarClientAddressMapMutex);
TimerClientAddressMap::iterator i = m_timerAvatarClientAddressMap.begin(); TimerClientAddressMap::iterator i = m_timerAvatarClientAddressMap.begin();
@@ -1083,18 +1113,24 @@ ServerLobbyThread::TimerUpdateClientAvatarLock()
m_timerAvatarClientAddressMap.erase(i); m_timerAvatarClientAddressMap.erase(i);
i = next; i = next;
} }
}
} }
void void
ServerLobbyThread::TimerCheckSessionTimeouts() ServerLobbyThread::TimerCheckSessionTimeouts(const boost::system::error_code &ec)
{ {
if (!ec)
{
m_sessionManager.ForEach(boost::bind(&ServerLobbyThread::InternalCheckSessionTimeouts, boost::ref(*this), _1)); m_sessionManager.ForEach(boost::bind(&ServerLobbyThread::InternalCheckSessionTimeouts, boost::ref(*this), _1));
m_gameSessionManager.ForEach(boost::bind(&ServerLobbyThread::InternalCheckSessionTimeouts, boost::ref(*this), _1)); m_gameSessionManager.ForEach(boost::bind(&ServerLobbyThread::InternalCheckSessionTimeouts, boost::ref(*this), _1));
}
} }
void void
ServerLobbyThread::TimerCleanupAvatarCache() ServerLobbyThread::TimerCleanupAvatarCache(const boost::system::error_code &ec)
{ {
if (!ec)
{
// Only act if there are no sessions. // Only act if there are no sessions.
if (!m_sessionManager.HasSessions() && !m_gameSessionManager.HasSessions()) if (!m_sessionManager.HasSessions() && !m_gameSessionManager.HasSessions())
{ {
@@ -1102,6 +1138,7 @@ ServerLobbyThread::TimerCleanupAvatarCache()
m_avatarManager.RemoveOldAvatarCacheEntries(); m_avatarManager.RemoveOldAvatarCacheEntries();
} }
}
} }
boost::shared_ptr<ServerGame> boost::shared_ptr<ServerGame>
@@ -1380,8 +1417,10 @@ ServerLobbyThread::ReadStatisticsFile()
} }
void void
ServerLobbyThread::TimerSaveStatisticsFile() ServerLobbyThread::TimerSaveStatisticsFile(const boost::system::error_code &ec)
{ {
if (!ec)
{
LOG_VERBOSE("Saving statistics."); LOG_VERBOSE("Saving statistics.");
boost::mutex::scoped_lock lock(m_statMutex); boost::mutex::scoped_lock lock(m_statMutex);
if (m_statDataChanged) if (m_statDataChanged)
@@ -1398,6 +1437,7 @@ ServerLobbyThread::TimerSaveStatisticsFile()
m_statDataChanged = false; m_statDataChanged = false;
} }
} }
}
} }
ServerCallback & ServerCallback &
+8 -8
View File
@@ -21,6 +21,7 @@
#ifndef _SERVERGAME_H_ #ifndef _SERVERGAME_H_
#define _SERVERGAME_H_ #define _SERVERGAME_H_
#include <boost/enable_shared_from_this.hpp>
#include <third_party/boost/timers.hpp> #include <third_party/boost/timers.hpp>
#include <deque> #include <deque>
@@ -36,11 +37,11 @@ class ConfigFile;
struct GameData; struct GameData;
class Game; class Game;
class ServerGame class ServerGame : public boost::enable_shared_from_this<ServerGame>
{ {
public: public:
ServerGame( ServerGame(
ServerLobbyThread &lobbyThread, u_int32_t id, const std::string &name, const std::string &pwd, const GameData &gameData, unsigned adminPlayerId, GuiInterface &gui, ConfigFile *playerConfig); boost::shared_ptr<ServerLobbyThread> lobbyThread, u_int32_t id, const std::string &name, const std::string &pwd, const GameData &gameData, unsigned adminPlayerId, GuiInterface &gui, ConfigFile *playerConfig);
virtual ~ServerGame(); virtual ~ServerGame();
void Init(); void Init();
@@ -81,7 +82,7 @@ protected:
typedef std::deque<SessionWrapper> SessionQueue; typedef std::deque<SessionWrapper> SessionQueue;
void TimerVoteKick(); void TimerVoteKick(const boost::system::error_code &ec);
void InternalStartGame(); void InternalStartGame();
void ResetGame(); void ResetGame();
@@ -115,8 +116,7 @@ protected:
ServerGameState &GetState(); ServerGameState &GetState();
void SetState(ServerGameState &newState); void SetState(ServerGameState &newState);
unsigned GetStateTimerId() const; boost::asio::deadline_timer &GetStateTimer();
void SetStateTimerId(unsigned newTimerId);
ReceiverHelper &GetReceiver(); ReceiverHelper &GetReceiver();
@@ -141,7 +141,7 @@ private:
boost::shared_ptr<VoteKickData> m_voteKickData; boost::shared_ptr<VoteKickData> m_voteKickData;
ServerLobbyThread &m_lobbyThread; boost::shared_ptr<ServerLobbyThread> m_lobbyThread;
boost::shared_ptr<ReceiverHelper> m_receiver; boost::shared_ptr<ReceiverHelper> m_receiver;
GuiInterface &m_gui; GuiInterface &m_gui;
@@ -156,8 +156,8 @@ private:
ConfigFile *m_playerConfig; ConfigFile *m_playerConfig;
unsigned m_gameNum; unsigned m_gameNum;
unsigned m_curPetitionId; unsigned m_curPetitionId;
unsigned m_voteKickTimerId; boost::asio::deadline_timer m_voteKickTimer;
unsigned m_stateTimerId; boost::asio::deadline_timer m_stateTimer;
friend class ServerLobbyThread; friend class ServerLobbyThread;
friend class AbstractServerGameStateReceiving; friend class AbstractServerGameStateReceiving;
+40 -40
View File
@@ -41,16 +41,16 @@ class ServerGameState
{ {
public: public:
virtual ~ServerGameState(); virtual ~ServerGameState();
virtual void Enter(ServerGame &server) = 0; virtual void Enter(boost::shared_ptr<ServerGame> server) = 0;
virtual void Exit(ServerGame &server) = 0; virtual void Exit(boost::shared_ptr<ServerGame> server) = 0;
virtual void NotifyGameAdminChanged(ServerGame &server) = 0; virtual void NotifyGameAdminChanged(boost::shared_ptr<ServerGame> server) = 0;
// Handling of a new session. // Handling of a new session.
virtual void HandleNewSession(ServerGame &server, SessionWrapper session) = 0; virtual void HandleNewSession(boost::shared_ptr<ServerGame> server, SessionWrapper session) = 0;
// Main processing function of the current state. // Main processing function of the current state.
virtual int ProcessPacket(ServerGame &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet) = 0; virtual int ProcessPacket(boost::shared_ptr<ServerGame> server, SessionWrapper session, boost::shared_ptr<NetPacket> packet) = 0;
}; };
// Abstract State: Receiving. // Abstract State: Receiving.
@@ -61,11 +61,11 @@ public:
// Globally handle packets which are allowed in all running states. // Globally handle packets which are allowed in all running states.
// Calls InternalProcess if packet has not been processed. // Calls InternalProcess if packet has not been processed.
virtual int ProcessPacket(ServerGame &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet); virtual int ProcessPacket(boost::shared_ptr<ServerGame> server, SessionWrapper session, boost::shared_ptr<NetPacket> packet);
protected: protected:
virtual int InternalProcessPacket(ServerGame &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet) = 0; virtual int InternalProcessPacket(boost::shared_ptr<ServerGame> server, SessionWrapper session, boost::shared_ptr<NetPacket> packet) = 0;
}; };
// State: Initialization. // State: Initialization.
@@ -73,24 +73,24 @@ class ServerGameStateInit : public AbstractServerGameStateReceiving
{ {
public: public:
static ServerGameStateInit &Instance(); static ServerGameStateInit &Instance();
virtual void Enter(ServerGame &server); virtual void Enter(boost::shared_ptr<ServerGame> server);
virtual void Exit(ServerGame &server); virtual void Exit(boost::shared_ptr<ServerGame> server);
virtual ~ServerGameStateInit(); virtual ~ServerGameStateInit();
virtual void NotifyGameAdminChanged(ServerGame &server); virtual void NotifyGameAdminChanged(boost::shared_ptr<ServerGame> server);
virtual void HandleNewSession(ServerGame &server, SessionWrapper session); virtual void HandleNewSession(boost::shared_ptr<ServerGame> server, SessionWrapper session);
protected: protected:
ServerGameStateInit(); ServerGameStateInit();
void RegisterAdminTimer(ServerGame &server); void RegisterAdminTimer(boost::shared_ptr<ServerGame> server);
void UnregisterAdminTimer(ServerGame &server); void UnregisterAdminTimer(boost::shared_ptr<ServerGame> server);
void TimerAdminWarning(ServerGame &server); void TimerAdminWarning(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server);
void TimerAdminTimeout(ServerGame &server); void TimerAdminTimeout(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server);
virtual int InternalProcessPacket(ServerGame &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet); virtual int InternalProcessPacket(boost::shared_ptr<ServerGame> server, SessionWrapper session, boost::shared_ptr<NetPacket> packet);
static boost::shared_ptr<NetPacket> CreateNetPacketPlayerJoined(const PlayerData &playerData); static boost::shared_ptr<NetPacket> CreateNetPacketPlayerJoined(const PlayerData &playerData);
@@ -103,20 +103,20 @@ class ServerGameStateStartGame : public AbstractServerGameStateReceiving
{ {
public: public:
static ServerGameStateStartGame &Instance(); static ServerGameStateStartGame &Instance();
virtual void Enter(ServerGame &server); virtual void Enter(boost::shared_ptr<ServerGame> server);
virtual void Exit(ServerGame &server); virtual void Exit(boost::shared_ptr<ServerGame> server);
virtual ~ServerGameStateStartGame(); virtual ~ServerGameStateStartGame();
virtual void NotifyGameAdminChanged(ServerGame &/*server*/) {} virtual void NotifyGameAdminChanged(boost::shared_ptr<ServerGame> /*server*/) {}
virtual void HandleNewSession(ServerGame &server, SessionWrapper session); virtual void HandleNewSession(boost::shared_ptr<ServerGame> server, SessionWrapper session);
protected: protected:
ServerGameStateStartGame(); ServerGameStateStartGame();
virtual int InternalProcessPacket(ServerGame &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet); virtual int InternalProcessPacket(boost::shared_ptr<ServerGame> server, SessionWrapper session, boost::shared_ptr<NetPacket> packet);
void TimerTimeout(ServerGame &server); void TimerTimeout(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server);
void DoStart(ServerGame &server); void DoStart(boost::shared_ptr<ServerGame> server);
private: private:
static ServerGameStateStartGame s_state; static ServerGameStateStartGame s_state;
@@ -127,25 +127,25 @@ class ServerGameStateHand : public AbstractServerGameStateReceiving
{ {
public: public:
static ServerGameStateHand &Instance(); static ServerGameStateHand &Instance();
virtual void Enter(ServerGame &server); virtual void Enter(boost::shared_ptr<ServerGame> server);
virtual void Exit(ServerGame &server); virtual void Exit(boost::shared_ptr<ServerGame> server);
virtual ~ServerGameStateHand(); virtual ~ServerGameStateHand();
virtual void NotifyGameAdminChanged(ServerGame &/*server*/) {} virtual void NotifyGameAdminChanged(boost::shared_ptr<ServerGame> /*server*/) {}
virtual void HandleNewSession(ServerGame &server, SessionWrapper session); virtual void HandleNewSession(boost::shared_ptr<ServerGame> server, SessionWrapper session);
protected: protected:
ServerGameStateHand(); ServerGameStateHand();
virtual int InternalProcessPacket(ServerGame &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet); virtual int InternalProcessPacket(boost::shared_ptr<ServerGame> server, SessionWrapper session, boost::shared_ptr<NetPacket> packet);
void TimerLoop(ServerGame &server); void TimerLoop(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server);
void TimerShowCards(ServerGame &server); void TimerShowCards(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server);
void TimerComputerAction(ServerGame &server); void TimerComputerAction(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server);
void TimerNextHand(ServerGame &server); void TimerNextHand(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server);
void TimerNextGame(ServerGame &server); void TimerNextGame(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server);
int GetDealCardsDelaySec(ServerGame &server); int GetDealCardsDelaySec(ServerGame &server);
static void StartNewHand(ServerGame &server); static void StartNewHand(boost::shared_ptr<ServerGame> server);
private: private:
static ServerGameStateHand s_state; static ServerGameStateHand s_state;
@@ -158,19 +158,19 @@ class ServerGameStateWaitPlayerAction : public AbstractServerGameStateReceiving
{ {
public: public:
static ServerGameStateWaitPlayerAction &Instance(); static ServerGameStateWaitPlayerAction &Instance();
virtual void Enter(ServerGame &server); virtual void Enter(boost::shared_ptr<ServerGame> server);
virtual void Exit(ServerGame &server); virtual void Exit(boost::shared_ptr<ServerGame> server);
virtual ~ServerGameStateWaitPlayerAction(); virtual ~ServerGameStateWaitPlayerAction();
virtual void NotifyGameAdminChanged(ServerGame &/*server*/) {} virtual void NotifyGameAdminChanged(boost::shared_ptr<ServerGame> /*server*/) {}
virtual void HandleNewSession(ServerGame &server, SessionWrapper session); virtual void HandleNewSession(boost::shared_ptr<ServerGame> server, SessionWrapper session);
protected: protected:
ServerGameStateWaitPlayerAction(); ServerGameStateWaitPlayerAction();
virtual int InternalProcessPacket(ServerGame &server, SessionWrapper session, boost::shared_ptr<NetPacket> packet); virtual int InternalProcessPacket(boost::shared_ptr<ServerGame> server, SessionWrapper session, boost::shared_ptr<NetPacket> packet);
void TimerTimeout(ServerGame &server); void TimerTimeout(const boost::system::error_code &ec, boost::shared_ptr<ServerGame> server);
private: private:
static ServerGameStateWaitPlayerAction s_state; static ServerGameStateWaitPlayerAction s_state;
+17 -10
View File
@@ -24,8 +24,8 @@
#include <boost/asio.hpp> #include <boost/asio.hpp>
#include <deque> #include <deque>
#include <boost/regex.hpp> #include <boost/regex.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <core/timermanager.h>
#include <net/sessionmanager.h> #include <net/sessionmanager.h>
#include <net/netpacket.h> #include <net/netpacket.h>
#include <gui/guiinterface.h> #include <gui/guiinterface.h>
@@ -45,7 +45,7 @@ class AvatarManager;
struct GameData; struct GameData;
class Game; class Game;
class ServerLobbyThread : public Thread class ServerLobbyThread : public Thread, public boost::enable_shared_from_this<ServerLobbyThread>
{ {
public: public:
ServerLobbyThread(GuiInterface &gui, ConfigFile *playerConfig, AvatarManager &avatarManager, ServerLobbyThread(GuiInterface &gui, ConfigFile *playerConfig, AvatarManager &avatarManager,
@@ -89,13 +89,13 @@ public:
u_int32_t GetNextGameId(); u_int32_t GetNextGameId();
ServerCallback &GetCallback(); ServerCallback &GetCallback();
TimerManager &GetTimerManager();
AvatarManager &GetAvatarManager(); AvatarManager &GetAvatarManager();
ServerStats GetStats() const; ServerStats GetStats() const;
boost::posix_time::ptime GetStartTime() const; boost::posix_time::ptime GetStartTime() const;
SenderHelper &GetSender(); SenderHelper &GetSender();
boost::asio::io_service &GetIOService();
protected: protected:
@@ -113,6 +113,7 @@ protected:
// Main function of the thread. // Main function of the thread.
virtual void Main(); virtual void Main();
void RegisterTimers(); void RegisterTimers();
void CancelTimers();
void HandleRead(SessionId sessionId, const boost::system::error_code &error, size_t bytesRead); void HandleRead(SessionId sessionId, const boost::system::error_code &error, size_t bytesRead);
void HandlePacket(SessionWrapper session, boost::shared_ptr<NetPacket> packet); void HandlePacket(SessionWrapper session, boost::shared_ptr<NetPacket> packet);
@@ -127,11 +128,11 @@ 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 TimerRemoveGame(); void TimerRemoveGame(const boost::system::error_code &ec);
void TimerRemovePlayer(); void TimerRemovePlayer(const boost::system::error_code &ec);
void TimerUpdateClientAvatarLock(); void TimerUpdateClientAvatarLock(const boost::system::error_code &ec);
void TimerCheckSessionTimeouts(); void TimerCheckSessionTimeouts(const boost::system::error_code &ec);
void TimerCleanupAvatarCache(); void TimerCleanupAvatarCache(const boost::system::error_code &ec);
boost::shared_ptr<ServerGame> InternalGetGameFromId(unsigned gameId); boost::shared_ptr<ServerGame> InternalGetGameFromId(unsigned gameId);
void InternalAddGame(boost::shared_ptr<ServerGame> game); void InternalAddGame(boost::shared_ptr<ServerGame> game);
@@ -153,7 +154,7 @@ protected:
void BroadcastStatisticsUpdate(const ServerStats &stats); void BroadcastStatisticsUpdate(const ServerStats &stats);
void ReadStatisticsFile(); void ReadStatisticsFile();
void TimerSaveStatisticsFile(); void TimerSaveStatisticsFile(const boost::system::error_code &ec);
ReceiverHelper &GetReceiver(); ReceiverHelper &GetReceiver();
@@ -180,7 +181,6 @@ private:
SessionManager m_sessionManager; SessionManager m_sessionManager;
SessionManager m_gameSessionManager; SessionManager m_gameSessionManager;
TimerManager m_timerManager;
TimerClientAddressMap m_timerAvatarClientAddressMap; TimerClientAddressMap m_timerAvatarClientAddressMap;
mutable boost::mutex m_timerAvatarClientAddressMapMutex; mutable boost::mutex m_timerAvatarClientAddressMapMutex;
@@ -217,6 +217,13 @@ private:
bool m_statDataChanged; bool m_statDataChanged;
mutable boost::mutex m_statMutex; mutable boost::mutex m_statMutex;
boost::asio::deadline_timer m_removeGameTimer;
boost::asio::deadline_timer m_removePlayerTimer;
boost::asio::deadline_timer m_sessionTimeoutTimer;
boost::asio::deadline_timer m_avatarCleanupTimer;
boost::asio::deadline_timer m_saveStatisticsTimer;
boost::asio::deadline_timer m_avatarLockTimer;
const boost::posix_time::ptime m_startTime; const boost::posix_time::ptime m_startTime;
}; };