From 9d63df9218f2d3a7987c4804b322e1651bd567e1 Mon Sep 17 00:00:00 2001 From: lotodore Date: Mon, 20 Aug 2007 15:30:22 +0000 Subject: [PATCH] More work on server redesign. Network mode still broken. --- src/game.cpp | 7 +- src/game.h | 1 + src/net/common/serveracceptthread.cpp | 3 +- ...erverrecvstate.cpp => servergamestate.cpp} | 399 +++++++----------- src/net/common/servergamethread.cpp | 371 ++++++++++++++++ src/net/common/serverlobbythread.cpp | 54 +-- src/net/common/sessionmanager.cpp | 62 ++- src/net/serveracceptthread.h | 3 +- src/net/servergamestate.h | 380 +++++++++++++++++ src/net/servergamethread.h | 132 ++++++ src/net/serverlobbythread.h | 5 +- src/net/serverrecvstate.h | 378 ----------------- src/net/sessiondata.h | 2 +- src/net/sessionmanager.h | 7 +- src/playerdata.h | 2 + src/session.cpp | 3 +- 16 files changed, 1143 insertions(+), 666 deletions(-) rename src/net/common/{serverrecvstate.cpp => servergamestate.cpp} (66%) create mode 100644 src/net/common/servergamethread.cpp create mode 100644 src/net/servergamestate.h create mode 100644 src/net/servergamethread.h delete mode 100644 src/net/serverrecvstate.h diff --git a/src/game.cpp b/src/game.cpp index 21a3539d..c5598cef 100755 --- a/src/game.cpp +++ b/src/game.cpp @@ -114,7 +114,12 @@ Game::~Game() } -HandInterface * Game::getCurrentHand() +HandInterface *Game::getCurrentHand() +{ + return actualHand; +} + +const HandInterface *Game::getCurrentHand() const { return actualHand; } diff --git a/src/game.h b/src/game.h index df7a5e5a..ab912946 100755 --- a/src/game.h +++ b/src/game.h @@ -48,6 +48,7 @@ public: void startHand(); HandInterface *getCurrentHand(); + const HandInterface *getCurrentHand() const; std::vector > getPlayerArray() {return playerArray;} diff --git a/src/net/common/serveracceptthread.cpp b/src/net/common/serveracceptthread.cpp index aa3e8f39..23aee13f 100644 --- a/src/net/common/serveracceptthread.cpp +++ b/src/net/common/serveracceptthread.cpp @@ -42,8 +42,7 @@ ServerAcceptThread::~ServerAcceptThread() } void -ServerAcceptThread::Init(unsigned serverPort, bool ipv6, bool sctp, const std::string &pwd, - const GameData &gameData) +ServerAcceptThread::Init(unsigned serverPort, bool ipv6, bool sctp, const std::string &pwd) { if (IsRunning()) return; // TODO: throw exception diff --git a/src/net/common/serverrecvstate.cpp b/src/net/common/servergamestate.cpp similarity index 66% rename from src/net/common/serverrecvstate.cpp rename to src/net/common/servergamestate.cpp index e6cd077b..3695442b 100644 --- a/src/net/common/serverrecvstate.cpp +++ b/src/net/common/servergamestate.cpp @@ -17,8 +17,8 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -#include -#include +#include +#include #include #include #include @@ -50,14 +50,13 @@ using namespace std; // Helper functions // TODO: these are hacks. -static void SendPlayerAction(ServerRecvThread &server, boost::shared_ptr player) +static void SendPlayerAction(ServerGameThread &server, boost::shared_ptr player) { - Game &curGame = server.GetGame(); assert(player); boost::shared_ptr notifyActionDone(new NetPacketPlayersActionDone); NetPacketPlayersActionDone::Data actionDoneData; - actionDoneData.gameState = static_cast(curGame.getCurrentHand()->getActualRound()); + actionDoneData.gameState = server.GetCurRound(); actionDoneData.playerId = player->getMyUniqueID(); actionDoneData.playerAction = static_cast(player->getMyAction()); actionDoneData.totalPlayerBet = player->getMySet(); @@ -66,7 +65,7 @@ static void SendPlayerAction(ServerRecvThread &server, boost::shared_ptr packet; try { // Receive the packet. - packet = server.GetReceiver().Recv(recvSock); + packet = server.GetReceiver().Recv(session.sessionData->GetSocket()); } catch (const NetException &) { server.CloseSessionDelayed(session); @@ -184,16 +178,16 @@ AbstractServerRecvStateReceiving::Process(ServerRecvThread &server) //----------------------------------------------------------------------------- -AbstractServerRecvStateTimer::AbstractServerRecvStateTimer() +AbstractServerGameStateTimer::AbstractServerGameStateTimer() { } -AbstractServerRecvStateTimer::~AbstractServerRecvStateTimer() +AbstractServerGameStateTimer::~AbstractServerGameStateTimer() { } void -AbstractServerRecvStateTimer::Init() +AbstractServerGameStateTimer::Init() { m_timer.reset(); m_timer.start(); @@ -201,139 +195,74 @@ AbstractServerRecvStateTimer::Init() //----------------------------------------------------------------------------- -boost::thread_specific_ptr ServerRecvStateInit::Ptr; +boost::thread_specific_ptr ServerGameStateInit::Ptr; -ServerRecvStateInit & -ServerRecvStateInit::Instance() +ServerGameStateInit & +ServerGameStateInit::Instance() { if (!Ptr.get()) - Ptr.reset(new ServerRecvStateInit); + Ptr.reset(new ServerGameStateInit); return *Ptr; } -ServerRecvStateInit::ServerRecvStateInit() +ServerGameStateInit::ServerGameStateInit() : m_curUniquePlayerId(0) { } -ServerRecvStateInit::~ServerRecvStateInit() +ServerGameStateInit::~ServerGameStateInit() { } void -ServerRecvStateInit::HandleNewConnection(ServerRecvThread &server, boost::shared_ptr connData) +ServerGameStateInit::HandleNewSession(ServerGameThread &server, SessionWrapper session) { - // Create a random session id. - // This id can be used to reconnect to the server if the connection was lost. - unsigned sessionId; - RandomBytes((unsigned char *)&sessionId, sizeof(sessionId)); // TODO: check for collisions. - - // Create a new session. - boost::shared_ptr sessionData(new SessionData(connData->ReleaseSocket(), sessionId)); - server.AddSession(sessionData); -} - -int -ServerRecvStateInit::InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr packet) -{ - int retVal = MSG_SOCK_INIT_DONE; - - if (packet->ToNetPacketJoinGame()) + if (session.sessionData.get() && session.playerData.get()) { - // Session should be in initial state. - if (session.sessionData->GetState() != SessionData::Init) - { - server.SessionError(session, ERR_SOCK_INVALID_STATE); - return retVal; - } - - const NetPacketJoinGame *tmpPacket = packet->ToNetPacketJoinGame(); - - NetPacketJoinGame::Data joinGameData; - tmpPacket->GetData(joinGameData); - - // Check the protocol version. - if (joinGameData.versionMajor != NET_VERSION_MAJOR) - { - server.SessionError(session, ERR_NET_VERSION_NOT_SUPPORTED); - return retVal; - } - size_t curNumPlayers = server.GetCurNumberOfPlayers(); // Check the number of players. if (curNumPlayers >= (size_t)server.GetGameData().maxNumberOfPlayers) { server.SessionError(session, ERR_NET_SERVER_FULL); - return retVal; } - - // Check the server password. - if (!server.CheckPassword(joinGameData.password)) + else { - server.SessionError(session, ERR_NET_INVALID_PASSWORD); - return retVal; + if (curNumPlayers == 0) + { + // First player is admin. + session.playerData->SetRights(PLAYER_RIGHTS_ADMIN); + } + else + { + // Send notifications for connected players to client. + PlayerDataList tmpPlayerList = server.GetSessionManager().GetPlayerDataList(); + PlayerDataList::iterator player_i = tmpPlayerList.begin(); + PlayerDataList::iterator player_end = tmpPlayerList.end(); + while (player_i != player_end) + { + server.GetSender().Send(session.sessionData->GetSocket(), CreateNetPacketPlayerJoined(*(*player_i))); + ++player_i; + } + + // Send "Player Joined" to other fully connected clients. + server.SendToAllPlayers(CreateNetPacketPlayerJoined(*session.playerData)); + } + // Session is now in game state. + session.sessionData->SetState(SessionData::Game); + // Accept session. + server.GetSessionManager().AddSession(session); } - - // Check whether the player name is correct. - // Partly, this is also done in netpacket. - // However, some disallowed names are checked only here. - if (joinGameData.playerName.empty() || joinGameData.playerName.size() > MAX_NAME_SIZE - || joinGameData.playerName.substr(0, sizeof(SERVER_COMPUTER_PLAYER_NAME) - 1) == SERVER_COMPUTER_PLAYER_NAME) - { - server.SessionError(session, ERR_NET_INVALID_PLAYER_NAME); - return retVal; - } - - // Check whether this player is already connected. - if (server.IsPlayerConnected(joinGameData.playerName)) - { - server.SessionError(session, ERR_NET_PLAYER_NAME_IN_USE); - return retVal; - } - - // Create player data object. - // TODO HACK first player is admin - PlayerRights rights = PLAYER_RIGHTS_NORMAL; - if (server.GetCurNumberOfPlayers() == 0) - rights = PLAYER_RIGHTS_ADMIN; - boost::shared_ptr tmpPlayerData( - new PlayerData(m_curUniquePlayerId++, 0, PLAYER_TYPE_HUMAN, rights)); - tmpPlayerData->SetName(joinGameData.playerName); - tmpPlayerData->SetNetSessionData(session.sessionData); - - // Send ACK to client. - boost::shared_ptr answer(new NetPacketJoinGameAck); - NetPacketJoinGameAck::Data joinGameAckData; - joinGameAckData.sessionId = session.sessionData->GetId(); // TODO: currently unused. - joinGameAckData.yourPlayerUniqueId = tmpPlayerData->GetUniqueId(); - joinGameAckData.gameData = server.GetGameData(); - joinGameAckData.ptype = tmpPlayerData->GetType(); - joinGameAckData.prights = tmpPlayerData->GetRights(); - static_cast(answer.get())->SetData(joinGameAckData); - server.GetSender().Send(session.sessionData->GetSocket(), answer); - - // Send notifications for connected players to client. - PlayerDataList tmpPlayerList = server.GetPlayerDataList(); - PlayerDataList::iterator player_i = tmpPlayerList.begin(); - PlayerDataList::iterator player_end = tmpPlayerList.end(); - while (player_i != player_end) - { - server.GetSender().Send(session.sessionData->GetSocket(), CreateNetPacketPlayerJoined(*(*player_i))); - ++player_i; - } - - // Send "Player Joined" to other fully connected clients. - server.SendToAllPlayers(CreateNetPacketPlayerJoined(*tmpPlayerData)); - - // Set player data for session. - server.SetSessionPlayerData(session.sessionData, tmpPlayerData); - - // Session is now established. - session.sessionData->SetState(SessionData::Established); } - else if (packet->ToNetPacketStartEvent()) +} + +int +ServerGameStateInit::InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet) +{ + int retVal = MSG_SOCK_INIT_DONE; + + if (packet->ToNetPacketStartEvent()) { server.ResetComputerPlayerList(); int remainingSlots = server.GetGameData().maxNumberOfPlayers - server.GetCurNumberOfPlayers(); @@ -370,7 +299,7 @@ ServerRecvStateInit::InternalProcess(ServerRecvThread &server, SessionWrapper se } boost::shared_ptr -ServerRecvStateInit::CreateNetPacketPlayerJoined(const PlayerData &playerData) +ServerGameStateInit::CreateNetPacketPlayerJoined(const PlayerData &playerData) { boost::shared_ptr thisPlayerJoined(new NetPacketPlayerJoined); NetPacketPlayerJoined::Data thisPlayerJoinedData; @@ -384,44 +313,44 @@ ServerRecvStateInit::CreateNetPacketPlayerJoined(const PlayerData &playerData) //----------------------------------------------------------------------------- -AbstractServerRecvStateRunning::AbstractServerRecvStateRunning() +AbstractServerGameStateRunning::AbstractServerGameStateRunning() { } -AbstractServerRecvStateRunning::~AbstractServerRecvStateRunning() +AbstractServerGameStateRunning::~AbstractServerGameStateRunning() { } void -AbstractServerRecvStateRunning::HandleNewConnection(ServerRecvThread &server, boost::shared_ptr connData) +AbstractServerGameStateRunning::HandleNewSession(ServerGameThread &server, SessionWrapper session) { - // Do not accept new connections in this state. - server.RejectNewConnection(connData); + // Do not accept new sessions in this state. + server.RejectSession(session); } //----------------------------------------------------------------------------- -boost::thread_specific_ptr ServerRecvStateStartGame::Ptr; +boost::thread_specific_ptr ServerGameStateStartGame::Ptr; -ServerRecvStateStartGame & -ServerRecvStateStartGame::Instance() +ServerGameStateStartGame & +ServerGameStateStartGame::Instance() { if (!Ptr.get()) - Ptr.reset(new ServerRecvStateStartGame); + Ptr.reset(new ServerGameStateStartGame); return *Ptr; } -ServerRecvStateStartGame::ServerRecvStateStartGame() +ServerGameStateStartGame::ServerGameStateStartGame() { } -ServerRecvStateStartGame::~ServerRecvStateStartGame() +ServerGameStateStartGame::~ServerGameStateStartGame() { } int -ServerRecvStateStartGame::Process(ServerRecvThread &server) +ServerGameStateStartGame::Process(ServerGameThread &server) { boost::shared_ptr answer(new NetPacketGameStart); @@ -430,7 +359,7 @@ ServerRecvStateStartGame::Process(ServerRecvThread &server) // Send player order to clients. // Assume player list is sorted by number. - PlayerDataList tmpPlayerList = server.GetPlayerDataList(); + PlayerDataList tmpPlayerList = server.GetSessionManager().GetPlayerDataList(); PlayerDataList::iterator player_i = tmpPlayerList.begin(); PlayerDataList::iterator player_end = tmpPlayerList.end(); while (player_i != player_end) @@ -445,34 +374,34 @@ ServerRecvStateStartGame::Process(ServerRecvThread &server) static_cast(answer.get())->SetData(gameStartData); server.SendToAllPlayers(answer); - server.SetState(ServerRecvStateStartHand::Instance()); + server.SetState(ServerGameStateStartHand::Instance()); return MSG_NET_GAME_SERVER_START; } //----------------------------------------------------------------------------- -boost::thread_specific_ptr ServerRecvStateStartHand::Ptr; +boost::thread_specific_ptr ServerGameStateStartHand::Ptr; -ServerRecvStateStartHand & -ServerRecvStateStartHand::Instance() +ServerGameStateStartHand & +ServerGameStateStartHand::Instance() { if (!Ptr.get()) - Ptr.reset(new ServerRecvStateStartHand); + Ptr.reset(new ServerGameStateStartHand); return *Ptr; } -ServerRecvStateStartHand::ServerRecvStateStartHand() +ServerGameStateStartHand::ServerGameStateStartHand() { } -ServerRecvStateStartHand::~ServerRecvStateStartHand() +ServerGameStateStartHand::~ServerGameStateStartHand() { } int -ServerRecvStateStartHand::Process(ServerRecvThread &server) +ServerGameStateStartHand::Process(ServerGameThread &server) { boost::shared_ptr answer(new NetPacketHandStart); @@ -542,34 +471,34 @@ ServerRecvStateStartHand::Process(ServerRecvThread &server) } } - server.SetState(ServerRecvStateStartRound::Instance()); + server.SetState(ServerGameStateStartRound::Instance()); return MSG_NET_GAME_SERVER_HAND_START; } //----------------------------------------------------------------------------- -boost::thread_specific_ptr ServerRecvStateStartRound::Ptr; +boost::thread_specific_ptr ServerGameStateStartRound::Ptr; -ServerRecvStateStartRound & -ServerRecvStateStartRound::Instance() +ServerGameStateStartRound & +ServerGameStateStartRound::Instance() { if (!Ptr.get()) - Ptr.reset(new ServerRecvStateStartRound); + Ptr.reset(new ServerGameStateStartRound); return *Ptr; } -ServerRecvStateStartRound::ServerRecvStateStartRound() +ServerGameStateStartRound::ServerGameStateStartRound() { } -ServerRecvStateStartRound::~ServerRecvStateStartRound() +ServerGameStateStartRound::~ServerGameStateStartRound() { } int -ServerRecvStateStartRound::Process(ServerRecvThread &server) +ServerGameStateStartRound::Process(ServerGameThread &server) { int retVal = MSG_SOCK_INTERNAL_PENDING; Game &curGame = server.GetGame(); @@ -616,14 +545,14 @@ ServerRecvStateStartRound::Process(ServerRecvThread &server) server.SendToAllPlayers(allIn); curGame.getCurrentHand()->setCardsShown(true); - server.SetState(ServerRecvStateShowCardsDelay::Instance()); + server.SetState(ServerGameStateShowCardsDelay::Instance()); retVal = MSG_NET_GAME_SERVER_CARDS_DELAY; } else { SendNewRoundCards(server, curGame, newRound); - server.SetState(ServerRecvStateDealCardsDelay::Instance()); + server.SetState(ServerGameStateDealCardsDelay::Instance()); retVal = MSG_NET_GAME_SERVER_CARDS_DELAY; } } @@ -646,7 +575,7 @@ ServerRecvStateStartRound::Process(ServerRecvThread &server) server.SendToAllPlayers(notification); - server.SetState(ServerRecvStateWaitPlayerAction::Instance()); + server.SetState(ServerGameStateWaitPlayerAction::Instance()); retVal = MSG_NET_GAME_SERVER_ROUND; } @@ -722,12 +651,12 @@ ServerRecvStateStartRound::Process(ServerRecvThread &server) if (playersPositiveCashCounter == 1) { // View a dialog for a new game - delayed. - server.SetState(ServerRecvStateNextGameDelay::Instance()); + server.SetState(ServerGameStateNextGameDelay::Instance()); retVal = MSG_NET_GAME_SERVER_END; } else { - server.SetState(ServerRecvStateNextHandDelay::Instance()); + server.SetState(ServerGameStateNextHandDelay::Instance()); retVal = MSG_NET_GAME_SERVER_HAND_END; } } @@ -736,7 +665,7 @@ ServerRecvStateStartRound::Process(ServerRecvThread &server) } std::list > -ServerRecvStateStartRound::GetActivePlayers(Game &curGame) +ServerGameStateStartRound::GetActivePlayers(Game &curGame) { std::list > activePlayers; for (int i = 0; i < curGame.getStartQuantityPlayers() ; i++) @@ -752,27 +681,27 @@ ServerRecvStateStartRound::GetActivePlayers(Game &curGame) //----------------------------------------------------------------------------- -boost::thread_specific_ptr ServerRecvStateWaitPlayerAction::Ptr; +boost::thread_specific_ptr ServerGameStateWaitPlayerAction::Ptr; -ServerRecvStateWaitPlayerAction & -ServerRecvStateWaitPlayerAction::Instance() +ServerGameStateWaitPlayerAction & +ServerGameStateWaitPlayerAction::Instance() { if (!Ptr.get()) - Ptr.reset(new ServerRecvStateWaitPlayerAction); + Ptr.reset(new ServerGameStateWaitPlayerAction); return *Ptr; } -ServerRecvStateWaitPlayerAction::ServerRecvStateWaitPlayerAction() +ServerGameStateWaitPlayerAction::ServerGameStateWaitPlayerAction() { } -ServerRecvStateWaitPlayerAction::~ServerRecvStateWaitPlayerAction() +ServerGameStateWaitPlayerAction::~ServerGameStateWaitPlayerAction() { } int -ServerRecvStateWaitPlayerAction::Process(ServerRecvThread &server) +ServerGameStateWaitPlayerAction::Process(ServerGameThread &server) { int retVal; @@ -783,15 +712,15 @@ ServerRecvStateWaitPlayerAction::Process(ServerRecvThread &server) // If the player is computer controlled, let the engine act. if (tmpPlayer->getMyType() == PLAYER_TYPE_COMPUTER) { - server.SetState(ServerRecvStateComputerAction::Instance()); + server.SetState(ServerGameStateComputerAction::Instance()); retVal = MSG_SOCK_INTERNAL_PENDING; } // If the player we are waiting for left, continue without him. - else if (!server.IsPlayerConnected(tmpPlayer->getMyName())) + else if (!server.GetSessionManager().IsPlayerConnected(tmpPlayer->getMyName())) { PerformPlayerAction(server, tmpPlayer, PLAYER_ACTION_FOLD, 0); - server.SetState(ServerRecvStateStartRound::Instance()); + server.SetState(ServerGameStateStartRound::Instance()); retVal = MSG_NET_GAME_SERVER_ACTION; } else if (GetTimer().elapsed().total_seconds() >= server.GetGameData().playerActionTimeoutSec + SERVER_PLAYER_TIMEOUT_ADD_DELAY_SEC) @@ -802,17 +731,17 @@ ServerRecvStateWaitPlayerAction::Process(ServerRecvThread &server) else PerformPlayerAction(server, tmpPlayer, PLAYER_ACTION_FOLD, 0); - server.SetState(ServerRecvStateStartRound::Instance()); + server.SetState(ServerGameStateStartRound::Instance()); retVal = MSG_NET_GAME_SERVER_ACTION; } else - retVal = AbstractServerRecvStateReceiving::Process(server); + retVal = AbstractServerGameStateReceiving::Process(server); return retVal; } int -ServerRecvStateWaitPlayerAction::InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr packet) +ServerGameStateWaitPlayerAction::InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet) { int retVal = MSG_SOCK_INTERNAL_PENDING; @@ -829,7 +758,7 @@ ServerRecvStateWaitPlayerAction::InternalProcess(ServerRecvThread &server, Sessi PerformPlayerAction(server, tmpPlayer, actionData.playerAction, actionData.playerBet); - server.SetState(ServerRecvStateStartRound::Instance()); + server.SetState(ServerGameStateStartRound::Instance()); retVal = MSG_NET_GAME_SERVER_ACTION; } @@ -837,7 +766,7 @@ ServerRecvStateWaitPlayerAction::InternalProcess(ServerRecvThread &server, Sessi } void -ServerRecvStateWaitPlayerAction::PerformPlayerAction(ServerRecvThread &server, boost::shared_ptr player, PlayerAction action, int bet) +ServerGameStateWaitPlayerAction::PerformPlayerAction(ServerGameThread &server, boost::shared_ptr player, PlayerAction action, int bet) { Game &curGame = server.GetGame(); assert(player); @@ -858,29 +787,29 @@ ServerRecvStateWaitPlayerAction::PerformPlayerAction(ServerRecvThread &server, b //----------------------------------------------------------------------------- -boost::thread_specific_ptr ServerRecvStateComputerAction::Ptr; +boost::thread_specific_ptr ServerGameStateComputerAction::Ptr; -ServerRecvStateComputerAction & -ServerRecvStateComputerAction::Instance() +ServerGameStateComputerAction & +ServerGameStateComputerAction::Instance() { if (!Ptr.get()) - Ptr.reset(new ServerRecvStateComputerAction); + Ptr.reset(new ServerGameStateComputerAction); return *Ptr; } -ServerRecvStateComputerAction::ServerRecvStateComputerAction() +ServerGameStateComputerAction::ServerGameStateComputerAction() { } -ServerRecvStateComputerAction::~ServerRecvStateComputerAction() +ServerGameStateComputerAction::~ServerGameStateComputerAction() { } int -ServerRecvStateComputerAction::Process(ServerRecvThread &server) +ServerGameStateComputerAction::Process(ServerGameThread &server) { - int retVal = AbstractServerRecvStateReceiving::Process(server); + int retVal = AbstractServerGameStateReceiving::Process(server); if (GetTimer().elapsed().total_seconds() >= SERVER_COMPUTER_ACTION_DELAY_SEC) { @@ -889,7 +818,7 @@ ServerRecvStateComputerAction::Process(ServerRecvThread &server) tmpPlayer->action(); SendPlayerAction(server, tmpPlayer); - server.SetState(ServerRecvStateStartRound::Instance()); + server.SetState(ServerGameStateStartRound::Instance()); retVal = MSG_NET_GAME_SERVER_ACTION; } @@ -897,36 +826,36 @@ ServerRecvStateComputerAction::Process(ServerRecvThread &server) } int -ServerRecvStateComputerAction::InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr packet) +ServerGameStateComputerAction::InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet) { return MSG_SOCK_INTERNAL_PENDING; } //----------------------------------------------------------------------------- -boost::thread_specific_ptr ServerRecvStateDealCardsDelay::Ptr; +boost::thread_specific_ptr ServerGameStateDealCardsDelay::Ptr; -ServerRecvStateDealCardsDelay & -ServerRecvStateDealCardsDelay::Instance() +ServerGameStateDealCardsDelay & +ServerGameStateDealCardsDelay::Instance() { if (!Ptr.get()) - Ptr.reset(new ServerRecvStateDealCardsDelay); + Ptr.reset(new ServerGameStateDealCardsDelay); return *Ptr; } -ServerRecvStateDealCardsDelay::ServerRecvStateDealCardsDelay() +ServerGameStateDealCardsDelay::ServerGameStateDealCardsDelay() { } -ServerRecvStateDealCardsDelay::~ServerRecvStateDealCardsDelay() +ServerGameStateDealCardsDelay::~ServerGameStateDealCardsDelay() { } int -ServerRecvStateDealCardsDelay::Process(ServerRecvThread &server) +ServerGameStateDealCardsDelay::Process(ServerGameThread &server) { - int retVal = AbstractServerRecvStateReceiving::Process(server); + int retVal = AbstractServerGameStateReceiving::Process(server); Game &curGame = server.GetGame(); @@ -946,49 +875,49 @@ ServerRecvStateDealCardsDelay::Process(ServerRecvThread &server) break; } if (!delay || GetTimer().elapsed().total_seconds() >= delay) - server.SetState(ServerRecvStateStartRound::Instance()); + server.SetState(ServerGameStateStartRound::Instance()); return retVal; } int -ServerRecvStateDealCardsDelay::InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr packet) +ServerGameStateDealCardsDelay::InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet) { return MSG_SOCK_INTERNAL_PENDING; } //----------------------------------------------------------------------------- -boost::thread_specific_ptr ServerRecvStateShowCardsDelay::Ptr; +boost::thread_specific_ptr ServerGameStateShowCardsDelay::Ptr; -ServerRecvStateShowCardsDelay & -ServerRecvStateShowCardsDelay::Instance() +ServerGameStateShowCardsDelay & +ServerGameStateShowCardsDelay::Instance() { if (!Ptr.get()) - Ptr.reset(new ServerRecvStateShowCardsDelay); + Ptr.reset(new ServerGameStateShowCardsDelay); return *Ptr; } -ServerRecvStateShowCardsDelay::ServerRecvStateShowCardsDelay() +ServerGameStateShowCardsDelay::ServerGameStateShowCardsDelay() { } -ServerRecvStateShowCardsDelay::~ServerRecvStateShowCardsDelay() +ServerGameStateShowCardsDelay::~ServerGameStateShowCardsDelay() { } int -ServerRecvStateShowCardsDelay::Process(ServerRecvThread &server) +ServerGameStateShowCardsDelay::Process(ServerGameThread &server) { - int retVal = AbstractServerRecvStateReceiving::Process(server); + int retVal = AbstractServerGameStateReceiving::Process(server); if (GetTimer().elapsed().total_seconds() >= SERVER_SHOW_CARDS_DELAY_SEC) { Game &curGame = server.GetGame(); SendNewRoundCards(server, curGame, curGame.getCurrentHand()->getActualRound()); - server.SetState(ServerRecvStateDealCardsDelay::Instance()); + server.SetState(ServerGameStateDealCardsDelay::Instance()); retVal = MSG_NET_GAME_SERVER_CARDS_DELAY; } @@ -996,74 +925,74 @@ ServerRecvStateShowCardsDelay::Process(ServerRecvThread &server) } int -ServerRecvStateShowCardsDelay::InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr packet) +ServerGameStateShowCardsDelay::InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet) { return MSG_SOCK_INTERNAL_PENDING; } //----------------------------------------------------------------------------- -boost::thread_specific_ptr ServerRecvStateNextHandDelay::Ptr; +boost::thread_specific_ptr ServerGameStateNextHandDelay::Ptr; -ServerRecvStateNextHandDelay & -ServerRecvStateNextHandDelay::Instance() +ServerGameStateNextHandDelay & +ServerGameStateNextHandDelay::Instance() { if (!Ptr.get()) - Ptr.reset(new ServerRecvStateNextHandDelay); + Ptr.reset(new ServerGameStateNextHandDelay); return *Ptr; } -ServerRecvStateNextHandDelay::ServerRecvStateNextHandDelay() +ServerGameStateNextHandDelay::ServerGameStateNextHandDelay() { } -ServerRecvStateNextHandDelay::~ServerRecvStateNextHandDelay() +ServerGameStateNextHandDelay::~ServerGameStateNextHandDelay() { } int -ServerRecvStateNextHandDelay::Process(ServerRecvThread &server) +ServerGameStateNextHandDelay::Process(ServerGameThread &server) { - int retVal = AbstractServerRecvStateReceiving::Process(server); + int retVal = AbstractServerGameStateReceiving::Process(server); if (GetTimer().elapsed().total_seconds() >= SERVER_DELAY_NEXT_HAND_SEC) - server.SetState(ServerRecvStateStartHand::Instance()); + server.SetState(ServerGameStateStartHand::Instance()); return retVal; } int -ServerRecvStateNextHandDelay::InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr packet) +ServerGameStateNextHandDelay::InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet) { return MSG_SOCK_INTERNAL_PENDING; } //----------------------------------------------------------------------------- -boost::thread_specific_ptr ServerRecvStateNextGameDelay::Ptr; +boost::thread_specific_ptr ServerGameStateNextGameDelay::Ptr; -ServerRecvStateNextGameDelay & -ServerRecvStateNextGameDelay::Instance() +ServerGameStateNextGameDelay & +ServerGameStateNextGameDelay::Instance() { if (!Ptr.get()) - Ptr.reset(new ServerRecvStateNextGameDelay); + Ptr.reset(new ServerGameStateNextGameDelay); return *Ptr; } -ServerRecvStateNextGameDelay::ServerRecvStateNextGameDelay() +ServerGameStateNextGameDelay::ServerGameStateNextGameDelay() { } -ServerRecvStateNextGameDelay::~ServerRecvStateNextGameDelay() +ServerGameStateNextGameDelay::~ServerGameStateNextGameDelay() { } int -ServerRecvStateNextGameDelay::Process(ServerRecvThread &server) +ServerGameStateNextGameDelay::Process(ServerGameThread &server) { - int retVal = AbstractServerRecvStateReceiving::Process(server); + int retVal = AbstractServerGameStateReceiving::Process(server); if (GetTimer().elapsed().total_seconds() >= SERVER_DELAY_NEXT_GAME_SEC) { @@ -1085,41 +1014,41 @@ ServerRecvStateNextGameDelay::Process(ServerRecvThread &server) server.SendToAllPlayers(endGame); // Wait for the start of a new game. - server.SetState(ServerRecvStateInit::Instance()); + server.SetState(ServerGameStateInit::Instance()); } return retVal; } int -ServerRecvStateNextGameDelay::InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr packet) +ServerGameStateNextGameDelay::InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet) { return MSG_SOCK_INTERNAL_PENDING; } //----------------------------------------------------------------------------- -boost::thread_specific_ptr ServerRecvStateFinal::Ptr; +boost::thread_specific_ptr ServerGameStateFinal::Ptr; -ServerRecvStateFinal & -ServerRecvStateFinal::Instance() +ServerGameStateFinal & +ServerGameStateFinal::Instance() { if (!Ptr.get()) - Ptr.reset(new ServerRecvStateFinal); + Ptr.reset(new ServerGameStateFinal); return *Ptr; } -ServerRecvStateFinal::ServerRecvStateFinal() +ServerGameStateFinal::ServerGameStateFinal() { } -ServerRecvStateFinal::~ServerRecvStateFinal() +ServerGameStateFinal::~ServerGameStateFinal() { } int -ServerRecvStateFinal::InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr packet) +ServerGameStateFinal::InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet) { return MSG_SOCK_INTERNAL_PENDING; } diff --git a/src/net/common/servergamethread.cpp b/src/net/common/servergamethread.cpp new file mode 100644 index 00000000..9da6e966 --- /dev/null +++ b/src/net/common/servergamethread.cpp @@ -0,0 +1,371 @@ +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + + +class ServerSenderCallback : public SenderCallback +{ +public: + ServerSenderCallback(ServerGameThread &server) : m_server(server) {} + virtual ~ServerSenderCallback() {} + + virtual void SignalNetError(SOCKET sock, int errorID, int osErrorID) + { + // We just ignore send errors for now, on server side. + // A serious send error should trigger a read error or a read + // returning 0 afterwards, and we will handle this error. + } + +private: + ServerGameThread &m_server; +}; + + +ServerGameThread::ServerGameThread(ServerLobbyThread &lobbyThread, GuiInterface &gui, ConfigFile *playerConfig) +: m_lobbyThread(lobbyThread), m_gui(gui), m_gameId(0), m_playerConfig(playerConfig), m_curState(NULL) +{ + m_senderCallback.reset(new ServerSenderCallback(*this)); + m_sender.reset(new SenderThread(GetSenderCallback())); + m_receiver.reset(new ReceiverHelper); +} + +ServerGameThread::~ServerGameThread() +{ +} + +void +ServerGameThread::Init(const string &pwd, const GameData &gameData) +{ + m_password = pwd; + m_gameData = gameData; +} + +void +ServerGameThread::AddSession(SessionWrapper session) +{ + GetState().HandleNewSession(*this, session); +} + +GameState +ServerGameThread::GetCurRound() const +{ + return static_cast(GetGame().getCurrentHand()->getActualRound()); +} + +void +ServerGameThread::SendToAllPlayers(boost::shared_ptr packet) +{ + GetSessionManager().SendToAllSessions(GetSender(), packet); +} + +void +ServerGameThread::Main() +{ + SetState(SERVER_INITIAL_STATE::Instance()); + GetSender().Run(); + + try + { + while (!ShouldTerminate()) + { + // Process current state. + GetState().Process(*this); + } + } catch (const NetException &e) + { + GetCallback().SignalNetServerError(e.GetErrorId(), e.GetOsErrorCode()); + } + GetSender().SignalTermination(); + GetSender().Join(SENDER_THREAD_TERMINATE_TIMEOUT); +} + +void +ServerGameThread::InternalStartGame() +{ + // Set order of players. + AssignPlayerNumbers(); + + // Initialize the game. + GuiInterface &gui = GetGui(); + PlayerDataList playerData = GetSessionManager().GetPlayerDataList(); + + // Create EngineFactory + boost::shared_ptr factory(new LocalEngineFactory(m_playerConfig)); // LocalEngine erstellen + + // Set start data. + StartData startData; + startData.numberOfPlayers = playerData.size(); + + int tmpDealerPos = 0; + Tools::getRandNumber(0, startData.numberOfPlayers-1, 1, &tmpDealerPos, 0); + // The Player Id is not continuous. Therefore, the start dealer position + // needs to be converted to a player Id, and cannot be directly generated + // as player Id. + PlayerDataList::const_iterator player_i = playerData.begin(); + PlayerDataList::const_iterator player_end = playerData.end(); + + bool randDealerFound = false; + while (player_i != player_end) + { + if ((*player_i)->GetNumber() == tmpDealerPos) + { + // Get ID of the dealer. + startData.startDealerPlayerId = static_cast((*player_i)->GetUniqueId()); + randDealerFound = true; + break; + } + ++player_i; + } + assert(randDealerFound); // TODO: Throw exception. + + SetStartData(startData); + + m_game.reset(new Game(&gui, factory, playerData, GetGameData(), GetStartData(), GetNextGameId())); +} + +void +ServerGameThread::InternalKickPlayer(unsigned playerId) +{ +// SessionWrapper tmpSession = GetSessionByUniquePlayerId(uniqueId); +// SessionError(tmpSession, ERR_NET_PLAYER_KICKED); +} + +void +ServerGameThread::AddComputerPlayer(boost::shared_ptr player) +{ + m_computerPlayers.push_back(player); +} + +void +ServerGameThread::ResetComputerPlayerList() +{ + m_computerPlayers.clear(); +} + +void +ServerGameThread::SessionError(SessionWrapper session, int errorCode) +{ + if (session.sessionData.get()) + { + SendError(session.sessionData->GetSocket(), errorCode); + CloseSessionDelayed(session); + } +} + +void +ServerGameThread::CloseSessionDelayed(SessionWrapper session) +{ + GetSessionManager().RemoveSession(session.sessionData->GetSocket()); + + boost::shared_ptr tmpPlayerData = session.playerData; + if (tmpPlayerData.get() && !tmpPlayerData->GetName().empty()) + { + // Send "Player Left" to clients. + boost::shared_ptr thisPlayerLeft(new NetPacketPlayerLeft); + NetPacketPlayerLeft::Data thisPlayerLeftData; + thisPlayerLeftData.playerId = tmpPlayerData->GetUniqueId(); + static_cast(thisPlayerLeft.get())->SetData(thisPlayerLeftData); + GetSessionManager().SendToAllSessions(GetSender(), thisPlayerLeft); + + GetCallback().SignalNetServerPlayerLeft(tmpPlayerData->GetName()); + } + + GetLobbyThread().CloseSessionDelayed(session); +} + +void +ServerGameThread::SendError(SOCKET s, int errorCode) +{ + boost::shared_ptr packet(new NetPacketError); + NetPacketError::Data errorData; + errorData.errorCode = errorCode; + static_cast(packet.get())->SetData(errorData); + GetSender().Send(s, packet); +} + +void +ServerGameThread::RejectSession(SessionWrapper session) +{ + // TODO +} + +void +ServerGameThread::RemoveDisconnectedPlayers() +{ + // This should only be called between hands. + if (m_game.get()) + { + for (int i = 0; i < m_game->getStartQuantityPlayers(); i++) + { + boost::shared_ptr tmpPlayer = m_game->getPlayerArray()[i]; + if (!GetSessionManager().IsPlayerConnected(tmpPlayer->getMyUniqueID()) && tmpPlayer->getMyType() == PLAYER_TYPE_HUMAN) + { + tmpPlayer->setMyCash(0); + tmpPlayer->setMyActiveStatus(false); + tmpPlayer->setNetSessionData(boost::shared_ptr()); + } + } + } +} + +size_t +ServerGameThread::GetCurNumberOfPlayers() const +{ + return GetSessionManager().GetPlayerDataList().size(); +} + +void +ServerGameThread::AssignPlayerNumbers() +{ + int playerNumber = 0; + + PlayerDataList playerList = GetSessionManager().GetPlayerDataList(); + PlayerDataList::iterator player_i = playerList.begin(); + PlayerDataList::iterator player_end = playerList.end(); + + while (player_i != player_end) + { + (*player_i)->SetNumber(playerNumber); + ++playerNumber; + ++player_i; + } +} + +unsigned +ServerGameThread::GetNextGameId() +{ + return m_gameId++; +} + +SessionManager & +ServerGameThread::GetSessionManager() +{ + return m_sessionManager; +} + +const SessionManager & +ServerGameThread::GetSessionManager() const +{ + return m_sessionManager; +} + +ServerLobbyThread & +ServerGameThread::GetLobbyThread() +{ + return m_lobbyThread; +} + +ServerCallback & +ServerGameThread::GetCallback() +{ + return m_gui; +} + +ServerGameState & +ServerGameThread::GetState() +{ + assert(m_curState); + return *m_curState; +} + +void +ServerGameThread::SetState(ServerGameState &newState) +{ + newState.Init(); + m_curState = &newState; +} + +SenderThread & +ServerGameThread::GetSender() +{ + assert(m_sender.get()); + return *m_sender; +} + +ReceiverHelper & +ServerGameThread::GetReceiver() +{ + assert(m_receiver.get()); + return *m_receiver; +} + +Game & +ServerGameThread::GetGame() +{ + assert(m_game.get()); + return *m_game; +} + +const Game & +ServerGameThread::GetGame() const +{ + assert(m_game.get()); + return *m_game; +} + +const GameData & +ServerGameThread::GetGameData() const +{ + return m_gameData; +} + +const StartData & +ServerGameThread::GetStartData() const +{ + return m_startData; +} + +void +ServerGameThread::SetStartData(const StartData &startData) +{ + m_startData = startData; +} + +bool +ServerGameThread::CheckPassword(const string &password) const +{ + return (password == m_password); +} + +ServerSenderCallback & +ServerGameThread::GetSenderCallback() +{ + assert(m_senderCallback.get()); + return *m_senderCallback; +} + +GuiInterface & +ServerGameThread::GetGui() +{ + return m_gui; +} + diff --git a/src/net/common/serverlobbythread.cpp b/src/net/common/serverlobbythread.cpp index a91dedcc..e2851d92 100644 --- a/src/net/common/serverlobbythread.cpp +++ b/src/net/common/serverlobbythread.cpp @@ -79,6 +79,19 @@ ServerLobbyThread::AddConnection(boost::shared_ptr data) m_connectQueue.push_back(data); } +void +ServerLobbyThread::CloseSessionDelayed(SessionWrapper session) +{ + m_sessionManager.RemoveSession(session.sessionData->GetSocket()); + + boost::microsec_timer closeTimer; + closeTimer.start(); + CloseSessionList::value_type closeSessionData(closeTimer, session.sessionData); + + boost::mutex::scoped_lock lock(m_closeSessionListMutex); + m_closeSessionList.push_back(closeSessionData); +} + u_int32_t ServerLobbyThread::GetNextUniquePlayerId() { @@ -198,7 +211,7 @@ ServerLobbyThread::HandleNetPacketInit(SessionWrapper session, const NetPacketIn } // Check whether this player is already connected. - if (IsPlayerConnected(initData.playerName)) + if (m_sessionManager.IsPlayerConnected(initData.playerName)) { SessionError(session, ERR_NET_PLAYER_NAME_IN_USE); return; @@ -247,6 +260,8 @@ ServerLobbyThread::HandleNetPacketJoinGame(SessionWrapper session, const NetPack void ServerLobbyThread::CloseSessionLoop() { + boost::mutex::scoped_lock lock(m_closeSessionListMutex); + CloseSessionList::iterator i = m_closeSessionList.begin(); CloseSessionList::iterator end = m_closeSessionList.end(); @@ -302,30 +317,6 @@ ServerLobbyThread::SessionError(SessionWrapper session, int errorCode) } } -void -ServerLobbyThread::CloseSessionDelayed(SessionWrapper session) -{ - m_sessionManager.RemoveSession(session.sessionData->GetSocket()); - - boost::shared_ptr tmpPlayerData = session.playerData; - if (tmpPlayerData.get() && !tmpPlayerData->GetName().empty()) - { - // Send "Player Left" to clients. - boost::shared_ptr thisPlayerLeft(new NetPacketPlayerLeft); - NetPacketPlayerLeft::Data thisPlayerLeftData; - thisPlayerLeftData.playerId = tmpPlayerData->GetUniqueId(); - static_cast(thisPlayerLeft.get())->SetData(thisPlayerLeftData); - m_sessionManager.SendToAllSessions(GetSender(), thisPlayerLeft); - - GetCallback().SignalNetServerPlayerLeft(tmpPlayerData->GetName()); - } - - boost::microsec_timer closeTimer; - closeTimer.start(); - CloseSessionList::value_type closeSessionData(closeTimer, session.sessionData); - m_closeSessionList.push_back(closeSessionData); -} - void ServerLobbyThread::SendError(SOCKET s, int errorCode) { @@ -336,19 +327,6 @@ ServerLobbyThread::SendError(SOCKET s, int errorCode) GetSender().Send(s, packet); } -bool -ServerLobbyThread::IsPlayerConnected(const string &playerName) const -{ - bool retVal = false; - - SessionWrapper tmpSession = m_sessionManager.GetSessionByPlayerName(playerName); - - if (tmpSession.sessionData.get() && tmpSession.playerData.get()) - retVal = true; - - return retVal; -} - ServerCallback & ServerLobbyThread::GetCallback() { diff --git a/src/net/common/sessionmanager.cpp b/src/net/common/sessionmanager.cpp index 082bfdcf..ca41fb05 100644 --- a/src/net/common/sessionmanager.cpp +++ b/src/net/common/sessionmanager.cpp @@ -36,18 +36,24 @@ SessionManager::~SessionManager() void SessionManager::AddSession(boost::shared_ptr sessionData) +{ + AddSession(SessionWrapper(sessionData, boost::shared_ptr())); +} + +void +SessionManager::AddSession(SessionWrapper session) { boost::mutex::scoped_lock lock(m_sessionMapMutex); - SessionMap::iterator pos = m_sessionMap.lower_bound(sessionData->GetSocket()); + SessionMap::iterator pos = m_sessionMap.lower_bound(session.sessionData->GetSocket()); // If pos points to a pair whose key is equivalent to the socket, this handle // already exists within the list. - if (pos != m_sessionMap.end() && sessionData->GetSocket() == pos->first) + if (pos != m_sessionMap.end() && session.sessionData->GetSocket() == pos->first) { throw ServerException(ERR_SOCK_CONN_EXISTS, 0); } - m_sessionMap.insert(pos, SessionMap::value_type(sessionData->GetSocket(), SessionWrapper(sessionData, boost::shared_ptr()))); + m_sessionMap.insert(pos, SessionMap::value_type(session.sessionData->GetSocket(), session)); } void @@ -182,6 +188,56 @@ SessionManager::GetSessionByUniquePlayerId(unsigned uniqueId) const return tmpSession; } +PlayerDataList +SessionManager::GetPlayerDataList() const +{ + PlayerDataList playerList; + boost::mutex::scoped_lock lock(m_sessionMapMutex); + + SessionMap::const_iterator session_i = m_sessionMap.begin(); + SessionMap::const_iterator session_end = m_sessionMap.end(); + + while (session_i != session_end) + { + // Get all players which are fully connected. + if (session_i->second.sessionData->GetState() == SessionData::Established) + { + boost::shared_ptr tmpPlayer(session_i->second.playerData); + assert(tmpPlayer.get()); + assert(!tmpPlayer->GetName().empty()); + playerList.push_back(tmpPlayer); + } + ++session_i; + } + return playerList; +} + +bool +SessionManager::IsPlayerConnected(const string &playerName) const +{ + bool retVal = false; + + SessionWrapper tmpSession = GetSessionByPlayerName(playerName); + + if (tmpSession.sessionData.get() && tmpSession.playerData.get()) + retVal = true; + + return retVal; +} + +bool +SessionManager::IsPlayerConnected(unsigned uniqueId) const +{ + bool retVal = false; + + SessionWrapper tmpSession = GetSessionByUniquePlayerId(uniqueId); + + if (tmpSession.sessionData.get() && tmpSession.playerData.get()) + retVal = true; + + return retVal; +} + void SessionManager::Clear() { diff --git a/src/net/serveracceptthread.h b/src/net/serveracceptthread.h index df7681b6..cc051b1a 100644 --- a/src/net/serveracceptthread.h +++ b/src/net/serveracceptthread.h @@ -41,8 +41,7 @@ public: virtual ~ServerAcceptThread(); // Set the parameters. - void Init(unsigned serverPort, bool ipv6, bool sctp, const std::string &pwd, - const GameData &gameData); + void Init(unsigned serverPort, bool ipv6, bool sctp, const std::string &pwd); ServerCallback &GetCallback(); GuiInterface &GetGui(); diff --git a/src/net/servergamestate.h b/src/net/servergamestate.h new file mode 100644 index 00000000..50b1c001 --- /dev/null +++ b/src/net/servergamestate.h @@ -0,0 +1,380 @@ +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* State of network server. */ + +#ifndef _SERVERGAMESTATE_H_ +#define _SERVERGAMESTATE_H_ + +#include +#include +#include + + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4250) +#endif + +#define SERVER_INITIAL_STATE ServerGameStateInit +#define SERVER_START_GAME_STATE ServerGameStateStartGame + +class Game; +class PlayerInterface; +class ServerCallback; + +class ServerGameState +{ +public: + virtual ~ServerGameState(); + + // Initialize after switching to this state. + virtual void Init() = 0; + + // Handling of a new TCP connection. + virtual void HandleNewSession(ServerGameThread &server, SessionWrapper session) = 0; + + // Main processing function of the current state. + virtual int Process(ServerGameThread &server) = 0; +}; + +// Abstract State: Receiving. +class AbstractServerGameStateReceiving : virtual public ServerGameState +{ +public: + virtual ~AbstractServerGameStateReceiving(); + + // Globally handle packets which are allowed in all running states. + // Calls InternalProcess if packet has not been processed. + virtual int Process(ServerGameThread &server); + +protected: + + AbstractServerGameStateReceiving(); + + virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet) = 0; +}; + +// Abstract State: Timer. +class AbstractServerGameStateTimer : virtual public ServerGameState +{ +public: + virtual ~AbstractServerGameStateTimer(); + + virtual void Init(); + + const boost::microsec_timer &GetTimer() const {return m_timer;} + +protected: + + AbstractServerGameStateTimer(); + +private: + boost::microsec_timer m_timer; +}; + +// Abstract State: Game is running. +class AbstractServerGameStateRunning : virtual public ServerGameState +{ +public: + virtual ~AbstractServerGameStateRunning(); + + // Reject new connections. + virtual void HandleNewSession(ServerGameThread &server, SessionWrapper session); + +protected: + + AbstractServerGameStateRunning(); +}; + +// State: Initialization. +class ServerGameStateInit : public AbstractServerGameStateReceiving +{ +public: + // Access the state singleton. + static ServerGameStateInit &Instance(); + + virtual ~ServerGameStateInit(); + + virtual void Init() {} + // + virtual void HandleNewSession(ServerGameThread &server, SessionWrapper session); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateInit(); + + virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); + + static boost::shared_ptr CreateNetPacketPlayerJoined(const PlayerData &playerData); + +private: + + u_int32_t m_curUniquePlayerId; + static boost::thread_specific_ptr Ptr; +}; + +// State: Start server game. +class ServerGameStateStartGame : public AbstractServerGameStateRunning +{ +public: + // Access the state singleton. + static ServerGameStateStartGame &Instance(); + + virtual ~ServerGameStateStartGame(); + + virtual void Init() {} + + // + virtual int Process(ServerGameThread &server); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateStartGame(); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +// State: Start new hand. +class ServerGameStateStartHand : public AbstractServerGameStateRunning +{ +public: + // Access the state singleton. + static ServerGameStateStartHand &Instance(); + + virtual ~ServerGameStateStartHand(); + + virtual void Init() {} + + // + virtual int Process(ServerGameThread &server); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateStartHand(); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +// State: Start new round. +class ServerGameStateStartRound : public AbstractServerGameStateRunning +{ +public: + // Access the state singleton. + static ServerGameStateStartRound &Instance(); + + virtual ~ServerGameStateStartRound(); + + virtual void Init() {} + + // + virtual int Process(ServerGameThread &server); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateStartRound(); + + static std::list > GetActivePlayers(Game &curGame); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +// State: Wait for a player action. +class ServerGameStateWaitPlayerAction : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning, public AbstractServerGameStateTimer +{ +public: + // Access the state singleton. + static ServerGameStateWaitPlayerAction &Instance(); + + virtual ~ServerGameStateWaitPlayerAction(); + + // Handle leaving players. + virtual int Process(ServerGameThread &server); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateWaitPlayerAction(); + + virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); + + static void PerformPlayerAction(ServerGameThread &server, boost::shared_ptr player, PlayerAction action, int bet); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +// State: Delay and computer action +class ServerGameStateComputerAction : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning, public AbstractServerGameStateTimer +{ +public: + // Access the state singleton. + static ServerGameStateComputerAction &Instance(); + + virtual ~ServerGameStateComputerAction(); + + // Overwrite default processing + virtual int Process(ServerGameThread &server); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateComputerAction(); + + virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +// State: Delay after dealing cards +class ServerGameStateDealCardsDelay : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning, public AbstractServerGameStateTimer +{ +public: + // Access the state singleton. + static ServerGameStateDealCardsDelay &Instance(); + + virtual ~ServerGameStateDealCardsDelay(); + + // Overwrite default processing + virtual int Process(ServerGameThread &server); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateDealCardsDelay(); + + virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +// State: Delay after showing cards (all in) +class ServerGameStateShowCardsDelay : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning, public AbstractServerGameStateTimer +{ +public: + // Access the state singleton. + static ServerGameStateShowCardsDelay &Instance(); + + virtual ~ServerGameStateShowCardsDelay(); + + // Overwrite default processing + virtual int Process(ServerGameThread &server); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateShowCardsDelay(); + + virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +// State: Delay before next hand. +class ServerGameStateNextHandDelay : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning, public AbstractServerGameStateTimer +{ +public: + // Access the state singleton. + static ServerGameStateNextHandDelay &Instance(); + + virtual ~ServerGameStateNextHandDelay(); + + // Overwrite default processing + virtual int Process(ServerGameThread &server); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateNextHandDelay(); + + virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +// State: Delay before next hand. +class ServerGameStateNextGameDelay : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning, public AbstractServerGameStateTimer +{ +public: + // Access the state singleton. + static ServerGameStateNextGameDelay &Instance(); + + virtual ~ServerGameStateNextGameDelay(); + + // Overwrite default processing + virtual int Process(ServerGameThread &server); + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateNextGameDelay(); + + virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +// State: Final. +class ServerGameStateFinal : public AbstractServerGameStateReceiving, public AbstractServerGameStateRunning +{ +public: + // Access the state singleton. + static ServerGameStateFinal &Instance(); + + virtual ~ServerGameStateFinal(); + + virtual void Init() {} + +protected: + + // Protected constructor - this is a singleton. + ServerGameStateFinal(); + + virtual int InternalProcess(ServerGameThread &server, SessionWrapper session, boost::shared_ptr packet); + +private: + + static boost::thread_specific_ptr Ptr; +}; + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif diff --git a/src/net/servergamethread.h b/src/net/servergamethread.h new file mode 100644 index 00000000..fde9e9d1 --- /dev/null +++ b/src/net/servergamethread.h @@ -0,0 +1,132 @@ +/*************************************************************************** + * Copyright (C) 2007 by Lothar May * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +/* Network server game thread. */ + +#ifndef _SERVERGAMETHREAD_H_ +#define _SERVERGAMETHREAD_H_ + +#include +#include +#include + +#define GAME_THREAD_TERMINATE_TIMEOUT 200 + + +class SenderThread; +class ReceiverHelper; +class ServerLobbyThread; +class ServerSenderCallback; +class ServerGameState; +class ConfigFile; +struct GameData; +class Game; + +class ServerGameThread : public Thread +{ +public: + ServerGameThread(ServerLobbyThread &lobbyThread, GuiInterface &gui, ConfigFile *playerConfig); + virtual ~ServerGameThread(); + + void Init(const std::string &pwd, const GameData &gameData); + + void AddSession(SessionWrapper session); + + ServerCallback &GetCallback(); + GameState GetCurRound() const; + + void SendToAllPlayers(boost::shared_ptr packet); + +protected: + + // Main function of the thread. + virtual void Main(); + + void InternalStartGame(); + void InternalKickPlayer(unsigned playerId); + + void AddComputerPlayer(boost::shared_ptr player); + void ResetComputerPlayerList(); + + void SessionError(SessionWrapper session, int errorCode); + void CloseSessionDelayed(SessionWrapper session); + void SendError(SOCKET s, int errorCode); + void RejectSession(SessionWrapper session); + + void RemoveDisconnectedPlayers(); + size_t GetCurNumberOfPlayers() const; + void AssignPlayerNumbers(); + + unsigned GetNextGameId(); + + SessionManager &GetSessionManager(); + const SessionManager &GetSessionManager() const; + ServerLobbyThread &GetLobbyThread(); + + ServerGameState &GetState(); + void SetState(ServerGameState &newState); + + SenderThread &GetSender(); + ReceiverHelper &GetReceiver(); + + Game &GetGame(); + const Game &GetGame() const; + const GameData &GetGameData() const; + + const StartData &GetStartData() const; + void SetStartData(const StartData &startData); + + bool CheckPassword(const std::string &password) const; + + ServerSenderCallback &GetSenderCallback(); + GuiInterface &GetGui(); + +private: + + SessionManager m_sessionManager; + PlayerDataList m_computerPlayers; + + ServerLobbyThread &m_lobbyThread; + std::auto_ptr m_receiver; + std::auto_ptr m_sender; + std::auto_ptr m_senderCallback; + GuiInterface &m_gui; + + GameData m_gameData; + StartData m_startData; + std::auto_ptr m_game; + unsigned m_gameId; + std::string m_password; + ConfigFile *m_playerConfig; + ServerGameState *m_curState; + +friend class AbstractServerGameStateReceiving; +friend class AbstractServerGameStateRunning; +friend class ServerGameStateInit; +friend class ServerGameStateStartGame; +friend class ServerGameStateStartHand; +friend class ServerGameStateStartRound; +friend class ServerGameStateWaitPlayerAction; +friend class ServerGameStateComputerAction; +friend class ServerGameStateDealCardsDelay; +friend class ServerGameStateShowCardsDelay; +friend class ServerGameStateNextHandDelay; +friend class ServerGameStateNextGameDelay; +}; + +#endif diff --git a/src/net/serverlobbythread.h b/src/net/serverlobbythread.h index 8baf48c1..c831e4b6 100644 --- a/src/net/serverlobbythread.h +++ b/src/net/serverlobbythread.h @@ -50,6 +50,7 @@ public: void Init(const std::string &pwd); void AddConnection(boost::shared_ptr data); + void CloseSessionDelayed(SessionWrapper session); u_int32_t GetNextUniquePlayerId(); ServerCallback &GetCallback(); @@ -77,11 +78,8 @@ protected: void CleanupSessionMap(); void SessionError(SessionWrapper session, int errorCode); - void CloseSessionDelayed(SessionWrapper session); void SendError(SOCKET s, int errorCode); - bool IsPlayerConnected(const std::string &playerName) const; - SenderThread &GetSender(); ReceiverHelper &GetReceiver(); @@ -98,6 +96,7 @@ private: SessionManager m_sessionManager; CloseSessionList m_closeSessionList; + mutable boost::mutex m_closeSessionListMutex; std::auto_ptr m_receiver; std::auto_ptr m_sender; diff --git a/src/net/serverrecvstate.h b/src/net/serverrecvstate.h deleted file mode 100644 index 3e13dfee..00000000 --- a/src/net/serverrecvstate.h +++ /dev/null @@ -1,378 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Lothar May * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -/* State of network server. */ - -#ifndef _SERVERRECVSTATE_H_ -#define _SERVERRECVSTATE_H_ - -#include -#include - -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4250) -#endif - -#define SERVER_INITIAL_STATE ServerRecvStateInit -#define SERVER_START_GAME_STATE ServerRecvStateStartGame - -class Game; -class PlayerInterface; -class ServerCallback; - -class ServerRecvState -{ -public: - virtual ~ServerRecvState(); - - // Initialize after switching to this state. - virtual void Init() = 0; - - // Handling of a new TCP connection. - virtual void HandleNewConnection(ServerRecvThread &server, boost::shared_ptr connData) = 0; - - // Main processing function of the current state. - virtual int Process(ServerRecvThread &server) = 0; -}; - -// Abstract State: Receiving. -class AbstractServerRecvStateReceiving : virtual public ServerRecvState -{ -public: - virtual ~AbstractServerRecvStateReceiving(); - - // Globally handle packets which are allowed in all running states. - // Calls InternalProcess if packet has not been processed. - virtual int Process(ServerRecvThread &server); - -protected: - - AbstractServerRecvStateReceiving(); - - virtual int InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr packet) = 0; -}; - -// Abstract State: Timer. -class AbstractServerRecvStateTimer : virtual public ServerRecvState -{ -public: - virtual ~AbstractServerRecvStateTimer(); - - virtual void Init(); - - const boost::microsec_timer &GetTimer() const {return m_timer;} - -protected: - - AbstractServerRecvStateTimer(); - -private: - boost::microsec_timer m_timer; -}; - -// Abstract State: Game is running. -class AbstractServerRecvStateRunning : virtual public ServerRecvState -{ -public: - virtual ~AbstractServerRecvStateRunning(); - - // Reject new connections. - virtual void HandleNewConnection(ServerRecvThread &server, boost::shared_ptr data); - -protected: - - AbstractServerRecvStateRunning(); -}; - -// State: Initialization. -class ServerRecvStateInit : public AbstractServerRecvStateReceiving -{ -public: - // Access the state singleton. - static ServerRecvStateInit &Instance(); - - virtual ~ServerRecvStateInit(); - - virtual void Init() {} - // - virtual void HandleNewConnection(ServerRecvThread &server, boost::shared_ptr data); - -protected: - - // Protected constructor - this is a singleton. - ServerRecvStateInit(); - - virtual int InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr packet); - - static boost::shared_ptr CreateNetPacketPlayerJoined(const PlayerData &playerData); - -private: - - u_int32_t m_curUniquePlayerId; - static boost::thread_specific_ptr Ptr; -}; - -// State: Start server game. -class ServerRecvStateStartGame : public AbstractServerRecvStateRunning -{ -public: - // Access the state singleton. - static ServerRecvStateStartGame &Instance(); - - virtual ~ServerRecvStateStartGame(); - - virtual void Init() {} - - // - virtual int Process(ServerRecvThread &server); - -protected: - - // Protected constructor - this is a singleton. - ServerRecvStateStartGame(); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -// State: Start new hand. -class ServerRecvStateStartHand : public AbstractServerRecvStateRunning -{ -public: - // Access the state singleton. - static ServerRecvStateStartHand &Instance(); - - virtual ~ServerRecvStateStartHand(); - - virtual void Init() {} - - // - virtual int Process(ServerRecvThread &server); - -protected: - - // Protected constructor - this is a singleton. - ServerRecvStateStartHand(); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -// State: Start new round. -class ServerRecvStateStartRound : public AbstractServerRecvStateRunning -{ -public: - // Access the state singleton. - static ServerRecvStateStartRound &Instance(); - - virtual ~ServerRecvStateStartRound(); - - virtual void Init() {} - - // - virtual int Process(ServerRecvThread &server); - -protected: - - // Protected constructor - this is a singleton. - ServerRecvStateStartRound(); - - static std::list > GetActivePlayers(Game &curGame); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -// State: Wait for a player action. -class ServerRecvStateWaitPlayerAction : public AbstractServerRecvStateReceiving, public AbstractServerRecvStateRunning, public AbstractServerRecvStateTimer -{ -public: - // Access the state singleton. - static ServerRecvStateWaitPlayerAction &Instance(); - - virtual ~ServerRecvStateWaitPlayerAction(); - - // Handle leaving players. - virtual int Process(ServerRecvThread &server); - -protected: - - // Protected constructor - this is a singleton. - ServerRecvStateWaitPlayerAction(); - - virtual int InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr packet); - - static void PerformPlayerAction(ServerRecvThread &server, boost::shared_ptr player, PlayerAction action, int bet); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -// State: Delay and computer action -class ServerRecvStateComputerAction : public AbstractServerRecvStateReceiving, public AbstractServerRecvStateRunning, public AbstractServerRecvStateTimer -{ -public: - // Access the state singleton. - static ServerRecvStateComputerAction &Instance(); - - virtual ~ServerRecvStateComputerAction(); - - // Overwrite default processing - virtual int Process(ServerRecvThread &server); - -protected: - - // Protected constructor - this is a singleton. - ServerRecvStateComputerAction(); - - virtual int InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr packet); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -// State: Delay after dealing cards -class ServerRecvStateDealCardsDelay : public AbstractServerRecvStateReceiving, public AbstractServerRecvStateRunning, public AbstractServerRecvStateTimer -{ -public: - // Access the state singleton. - static ServerRecvStateDealCardsDelay &Instance(); - - virtual ~ServerRecvStateDealCardsDelay(); - - // Overwrite default processing - virtual int Process(ServerRecvThread &server); - -protected: - - // Protected constructor - this is a singleton. - ServerRecvStateDealCardsDelay(); - - virtual int InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr packet); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -// State: Delay after showing cards (all in) -class ServerRecvStateShowCardsDelay : public AbstractServerRecvStateReceiving, public AbstractServerRecvStateRunning, public AbstractServerRecvStateTimer -{ -public: - // Access the state singleton. - static ServerRecvStateShowCardsDelay &Instance(); - - virtual ~ServerRecvStateShowCardsDelay(); - - // Overwrite default processing - virtual int Process(ServerRecvThread &server); - -protected: - - // Protected constructor - this is a singleton. - ServerRecvStateShowCardsDelay(); - - virtual int InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr packet); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -// State: Delay before next hand. -class ServerRecvStateNextHandDelay : public AbstractServerRecvStateReceiving, public AbstractServerRecvStateRunning, public AbstractServerRecvStateTimer -{ -public: - // Access the state singleton. - static ServerRecvStateNextHandDelay &Instance(); - - virtual ~ServerRecvStateNextHandDelay(); - - // Overwrite default processing - virtual int Process(ServerRecvThread &server); - -protected: - - // Protected constructor - this is a singleton. - ServerRecvStateNextHandDelay(); - - virtual int InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr packet); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -// State: Delay before next hand. -class ServerRecvStateNextGameDelay : public AbstractServerRecvStateReceiving, public AbstractServerRecvStateRunning, public AbstractServerRecvStateTimer -{ -public: - // Access the state singleton. - static ServerRecvStateNextGameDelay &Instance(); - - virtual ~ServerRecvStateNextGameDelay(); - - // Overwrite default processing - virtual int Process(ServerRecvThread &server); - -protected: - - // Protected constructor - this is a singleton. - ServerRecvStateNextGameDelay(); - - virtual int InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr packet); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -// State: Final. -class ServerRecvStateFinal : public AbstractServerRecvStateReceiving, public AbstractServerRecvStateRunning -{ -public: - // Access the state singleton. - static ServerRecvStateFinal &Instance(); - - virtual ~ServerRecvStateFinal(); - - virtual void Init() {} - -protected: - - // Protected constructor - this is a singleton. - ServerRecvStateFinal(); - - virtual int InternalProcess(ServerRecvThread &server, SessionWrapper session, boost::shared_ptr packet); - -private: - - static boost::thread_specific_ptr Ptr; -}; - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -#endif diff --git a/src/net/sessiondata.h b/src/net/sessiondata.h index c2b99a21..94faa6a5 100644 --- a/src/net/sessiondata.h +++ b/src/net/sessiondata.h @@ -29,7 +29,7 @@ class SessionData { public: - enum State { Init, Established }; + enum State { Init, Established, Game }; SessionData(SOCKET sockfd, unsigned id); ~SessionData(); diff --git a/src/net/sessionmanager.h b/src/net/sessionmanager.h index 41230b8b..f6955a9e 100644 --- a/src/net/sessionmanager.h +++ b/src/net/sessionmanager.h @@ -46,7 +46,8 @@ public: SessionManager(); virtual ~SessionManager(); - void AddSession(boost::shared_ptr sessionData); // new Sessions have no player data + void AddSession(boost::shared_ptr sessionData); // new Sessions without player data + void AddSession(SessionWrapper session); void SetSessionPlayerData(SOCKET session, boost::shared_ptr playerData); void RemoveSession(SOCKET session); @@ -54,6 +55,10 @@ public: SessionWrapper GetSessionByPlayerName(const std::string playerName) const; SessionWrapper GetSessionByUniquePlayerId(unsigned uniqueId) const; + PlayerDataList GetPlayerDataList() const; + bool IsPlayerConnected(const std::string &playerName) const; + bool IsPlayerConnected(unsigned uniqueId) const; + void Clear(); unsigned GetRawSessionCount(); diff --git a/src/playerdata.h b/src/playerdata.h index 16473986..3e27a8f2 100644 --- a/src/playerdata.h +++ b/src/playerdata.h @@ -62,6 +62,8 @@ public: {return m_type;} PlayerRights GetRights() const {return m_rights;} + void SetRights(PlayerRights rights) + {m_rights = rights;} unsigned GetUniqueId() const {return m_uniqueId;} int GetNumber() const diff --git a/src/session.cpp b/src/session.cpp index edc098b3..5d80ce3d 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -169,8 +169,7 @@ void Session::startNetworkServer(const GameData &gameData) myConfig->readConfigInt("ServerPort"), myConfig->readConfigInt("ServerUseIpv6") == 1, myConfig->readConfigInt("ServerUseSctp") == 1, - myConfig->readConfigString("ServerPassword"), - gameData); + myConfig->readConfigString("ServerPassword")); myNetServer->Run(); }