1 /***************************************************************************** 2 * PokerTH - The open source texas holdem engine * 3 * Copyright (C) 2006-2012 Felix Hammer, Florian Thauer, Lothar May * 4 * * 5 * This program is free software: you can redistribute it and/or modify * 6 * it under the terms of the GNU Affero General Public License as * 7 * published by the Free Software Foundation, either version 3 of the * 8 * License, or (at your option) any later version. * 9 * * 10 * This program is distributed in the hope that it will be useful, * 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 * GNU Affero General Public License for more details. * 14 * * 15 * You should have received a copy of the GNU Affero General Public License * 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 17 * * 18 * * 19 * Additional permission under GNU AGPL version 3 section 7 * 20 * * 21 * If you modify this program, or any covered work, by linking or * 22 * combining it with the OpenSSL project's OpenSSL library (or a * 23 * modified version of that library), containing parts covered by the * 24 * terms of the OpenSSL or SSLeay licenses, the authors of PokerTH * 25 * (Felix Hammer, Florian Thauer, Lothar May) grant you additional * 26 * permission to convey the resulting work. * 27 * Corresponding Source for a non-source form of such a combination * 28 * shall include the source code for the parts of OpenSSL used as well * 29 * as that of the covered work. * 30 *****************************************************************************/ 31 /* Network server lobby thread. */ 32 33 #ifndef _SERVERLOBBYTHREAD_H_ 34 #define _SERVERLOBBYTHREAD_H_ 35 36 #include <boost/asio.hpp> 37 #include <boost/asio/steady_timer.hpp> 38 #include <boost/enable_shared_from_this.hpp> 39 #include <boost/uuid/uuid_generators.hpp> 40 41 #include <net/sessionmanager.h> 42 #include <net/netpacket.h> 43 #include <db/serverdbcallback.h> 44 #include <gui/guiinterface.h> 45 #include <gamedata.h> 46 47 #define NET_LOBBY_THREAD_TERMINATE_TIMEOUT_MSEC 20000 48 #define NET_ADMIN_IRC_TERMINATE_TIMEOUT_MSEC 4000 49 50 51 class SenderHelper; 52 class InternalServerCallback; 53 class ServerIrcBotCallback; 54 class ServerGame; 55 class ServerBanManager; 56 class ConfigFile; 57 class AvatarManager; 58 class ChatCleanerManager; 59 class ServerDBInterface; 60 struct GameData; 61 class Game; 62 struct Gsasl; 63 64 class ServerLobbyThread : public Thread, public boost::enable_shared_from_this<ServerLobbyThread> 65 { 66 public: 67 ServerLobbyThread(GuiInterface &gui, ServerMode mode, ServerIrcBotCallback &ircBotCb, ConfigFile &serverConfig, AvatarManager &avatarManager, 68 boost::shared_ptr<boost::asio::io_service> ioService); 69 virtual ~ServerLobbyThread(); 70 71 void Init(const std::string &logDir); 72 virtual void SignalTermination(); 73 74 void AddConnection(boost::shared_ptr<SessionData> sessionData); 75 void ReAddSession(boost::shared_ptr<SessionData> session, int reason, unsigned gameId); 76 void MoveSessionToGame(boost::shared_ptr<ServerGame> game, boost::shared_ptr<SessionData> session, bool autoLeave, bool spectateOnly); 77 void SessionError(boost::shared_ptr<SessionData> session, int errorCode); 78 void ResubscribeLobbyMsg(boost::shared_ptr<SessionData> session); 79 void NotifyPlayerJoinedLobby(unsigned playerId); 80 void NotifyPlayerLeftLobby(unsigned playerId); 81 void NotifyPlayerJoinedGame(unsigned gameId, unsigned playerId); 82 void NotifyPlayerLeftGame(unsigned gameId, unsigned playerId); 83 void NotifySpectatorJoinedGame(unsigned gameId, unsigned playerId); 84 void NotifySpectatorLeftGame(unsigned gameId, unsigned playerId); 85 void NotifyGameAdminChanged(unsigned gameId, unsigned newAdminPlayerId); 86 void NotifyStartingGame(unsigned gameId); 87 void NotifyReopeningGame(unsigned gameId); 88 89 void DispatchPacket(boost::shared_ptr<SessionData> session, boost::shared_ptr<NetPacket> packet); 90 void HandleGameRetrievePlayerInfo(boost::shared_ptr<SessionData> session, const PlayerInfoRequestMessage &playerInfoRequest); 91 void HandleGameRetrieveAvatar(boost::shared_ptr<SessionData> session, const AvatarRequestMessage &retrieveAvatar); 92 void HandleGameReportGame(boost::shared_ptr<SessionData> session, const ReportGameMessage &reportGame); 93 void HandleChatRequest(boost::shared_ptr<SessionData> session, const ChatRequestMessage &chatRequest); 94 void HandleAdminRemoveGame(boost::shared_ptr<SessionData> session, const AdminRemoveGameMessage &removeGame); 95 void HandleAdminBanPlayer(boost::shared_ptr<SessionData> session, const AdminBanPlayerMessage &banPlayer); 96 97 bool KickPlayerByName(const std::string &playerName); 98 bool RemoveGameByPlayerName(const std::string &playerName); 99 std::string GetPlayerIPAddress(const std::string &playerName) const; 100 std::string GetPlayerNameFromId(unsigned playerId) const; 101 void RemovePlayer(unsigned playerId, unsigned errorCode); 102 void MutePlayerInGame(unsigned playerId); 103 104 void SendGlobalChat(const std::string &message); 105 void SendGlobalMsgBox(const std::string &message); 106 void SendChatBotMsg(const std::string &message); 107 void SendChatBotMsg(unsigned gameId, const std::string &message); 108 void ReconnectChatBot(); 109 110 void AddComputerPlayer(boost::shared_ptr<PlayerData> player); 111 void RemoveComputerPlayer(boost::shared_ptr<PlayerData> player); 112 113 bool SendToLobbyPlayer(unsigned playerId, boost::shared_ptr<NetPacket> packet); 114 115 u_int32_t GetNextSessionId(); 116 u_int32_t GetNextUniquePlayerId(); 117 u_int32_t GetNextGameId(); 118 ServerCallback &GetCallback(); 119 120 AvatarManager &GetAvatarManager(); 121 ChatCleanerManager &GetChatCleaner(); 122 123 ServerStats GetStats() const; 124 boost::posix_time::ptime GetStartTime() const; 125 ServerMode GetServerMode() const; 126 127 SenderHelper &GetSender(); 128 boost::asio::io_service &GetIOService(); 129 boost::shared_ptr<ServerDBInterface> GetDatabase(); 130 ServerBanManager &GetBanManager(); 131 132 SessionDataCallback &GetSessionDataCallback(); 133 134 protected: 135 136 typedef std::deque<boost::shared_ptr<boost::asio::ip::tcp::socket> > ConnectQueue; 137 typedef std::list<boost::shared_ptr<SessionData> > SessionList; 138 typedef std::list<SessionId> SessionIdList; 139 typedef std::map<SessionId, boost::timers::portable::microsec_timer> TimerSessionMap; 140 typedef std::map<unsigned, boost::shared_ptr<ServerGame> > GameMap; 141 typedef std::map<std::string, boost::timers::portable::microsec_timer> TimerClientAddressMap; 142 typedef std::list<unsigned> RemoveGameList; 143 144 // Main function of the thread. 145 virtual void Main(); 146 void RegisterTimers(); 147 void CancelTimers(); 148 void InitAuthContext(); 149 void ClearAuthContext(); 150 void InitChatCleaner(); 151 152 void HandlePacket(boost::shared_ptr<SessionData> session, boost::shared_ptr<NetPacket> packet); 153 void HandleNetPacketInit(boost::shared_ptr<SessionData> session, const InitMessage &initMessage); 154 void HandleNetPacketAuthClientResponse(boost::shared_ptr<SessionData> session, const AuthClientResponseMessage &clientResponse); 155 void HandleNetPacketAvatarHeader(boost::shared_ptr<SessionData> session, const AvatarHeaderMessage &avatarHeader); 156 void HandleNetPacketUnknownAvatar(boost::shared_ptr<SessionData> session, const UnknownAvatarMessage &unknownAvatar); 157 void HandleNetPacketAvatarFile(boost::shared_ptr<SessionData> session, const AvatarDataMessage &avatarData); 158 void HandleNetPacketAvatarEnd(boost::shared_ptr<SessionData> session, const AvatarEndMessage &avatarEnd); 159 void HandleNetPacketRetrievePlayerInfo(boost::shared_ptr<SessionData> session, const PlayerInfoRequestMessage &playerInfoRequest); 160 void HandleNetPacketRetrieveAvatar(boost::shared_ptr<SessionData> session, const AvatarRequestMessage &retrieveAvatar); 161 void HandleNetPacketCreateGame(boost::shared_ptr<SessionData> session, const JoinNewGameMessage &newGame); 162 void HandleNetPacketJoinGame(boost::shared_ptr<SessionData> session, const JoinExistingGameMessage &joinGame); 163 void HandleNetPacketRejoinGame(boost::shared_ptr<SessionData> session, const RejoinExistingGameMessage &rejoinGame); 164 void HandleNetPacketChatRequest(boost::shared_ptr<SessionData> session, const ChatRequestMessage &chatRequest); 165 void HandleNetPacketRejectGameInvitation(boost::shared_ptr<SessionData> session, const RejectGameInvitationMessage &reject); 166 void HandleNetPacketReportGame(boost::shared_ptr<SessionData> session, const ReportGameMessage &report); 167 void HandleNetPacketAdminRemoveGame(boost::shared_ptr<SessionData> session, const AdminRemoveGameMessage &removeGame); 168 void HandleNetPacketAdminBanPlayer(boost::shared_ptr<SessionData> session, const AdminBanPlayerMessage &banPlayer); 169 // TODO would be better to use state pattern here. 170 void AuthChallenge(boost::shared_ptr<SessionData> session, const std::string &secret); 171 void CheckAvatarBlacklist(boost::shared_ptr<SessionData> session); 172 void AvatarBlacklisted(unsigned playerId); 173 void AvatarOK(unsigned playerId); 174 void InitAfterLogin(boost::shared_ptr<SessionData> session); 175 void EstablishSession(boost::shared_ptr<SessionData> session); 176 void AuthenticatePlayer(boost::shared_ptr<SessionData> session); 177 void UserValid(unsigned playerId, const DBPlayerData &dbPlayerData); 178 void UserInvalid(unsigned playerId); 179 void UserBlocked(unsigned playerId); 180 181 void SendReportAvatarResult(unsigned byPlayerId, unsigned reportedPlayerId, bool success); 182 void SendReportGameResult(unsigned byPlayerId, unsigned reportedGameId, bool success); 183 void SendAdminBanPlayerResult(unsigned byPlayerId, unsigned reportedPlayerId, bool success); 184 void RequestPlayerAvatar(boost::shared_ptr<SessionData> session); 185 void TimerRemoveGame(const boost::system::error_code &ec); 186 void TimerRemovePlayer(const boost::system::error_code &ec); 187 void TimerUpdateClientLoginLock(const boost::system::error_code &ec); 188 void TimerCleanupAvatarCache(const boost::system::error_code &ec); 189 190 bool IsGameNameInUse(const std::string &gameName) const; 191 boost::shared_ptr<ServerGame> InternalGetGameFromId(unsigned gameId); 192 void InternalAddGame(boost::shared_ptr<ServerGame> game); 193 void InternalRemoveGame(boost::shared_ptr<ServerGame> game); 194 void InternalRemovePlayer(unsigned playerId, unsigned errorCode); 195 void InternalMutePlayerInGame(unsigned playerId); 196 void InternalResubscribeMsg(boost::shared_ptr<SessionData> session); 197 198 void HandleReAddedSession(boost::shared_ptr<SessionData> session); 199 200 void SessionTimeoutWarning(boost::shared_ptr<SessionData> session, unsigned remainingSec); 201 202 void CleanupSessionMap(); 203 204 void CloseSession(boost::shared_ptr<SessionData> session); 205 void SendError(boost::shared_ptr<SessionData> s, int errorCode); 206 void SendJoinGameFailed(boost::shared_ptr<SessionData> s, unsigned gameId, int reason); 207 void SendPlayerList(boost::shared_ptr<SessionData> s); 208 void SendGameList(boost::shared_ptr<SessionData> s); 209 void UpdateStatisticsNumberOfPlayers(); 210 void BroadcastStatisticsUpdate(const ServerStats &stats); 211 212 void ReadStatisticsFile(); 213 void TimerSaveStatisticsFile(const boost::system::error_code &ec); 214 215 InternalServerCallback &GetSenderCallback(); 216 GuiInterface &GetGui(); 217 ServerIrcBotCallback &GetIrcBotCallback(); 218 219 unsigned GetPlayerId(const std::string &name) const; 220 221 static boost::shared_ptr<NetPacket> CreateNetPacketPlayerListNew(unsigned playerId); 222 static boost::shared_ptr<NetPacket> CreateNetPacketPlayerListLeft(unsigned playerId); 223 static boost::shared_ptr<NetPacket> CreateNetPacketGameListNew(const ServerGame &game); 224 static boost::shared_ptr<NetPacket> CreateNetPacketGameListUpdate(unsigned gameId, GameMode mode); 225 226 u_int32_t GetRejoinGameIdForPlayer(const std::string &playerName, const std::string &guid, unsigned &outPlayerUniqueId); 227 228 private: 229 230 boost::shared_ptr<boost::asio::io_service> m_ioService; 231 232 boost::shared_ptr<InternalServerCallback> m_internalServerCallback; 233 boost::shared_ptr<SenderHelper> m_sender; 234 235 SessionManager m_sessionManager; 236 SessionManager m_gameSessionManager; 237 238 Gsasl *m_authContext; 239 240 TimerClientAddressMap m_timerClientAddressMap; 241 mutable boost::mutex m_timerClientAddressMapMutex; 242 243 RemoveGameList m_removeGameList; 244 mutable boost::mutex m_removeGameListMutex; 245 246 PlayerDataMap m_computerPlayers; 247 mutable boost::mutex m_computerPlayersMutex; 248 249 GameMap m_gameMap; 250 251 GuiInterface &m_gui; 252 ServerIrcBotCallback &m_ircBotCb; 253 AvatarManager &m_avatarManager; 254 255 const ServerMode m_mode; 256 std::string m_statisticsFileName; 257 ConfigFile &m_serverConfig; 258 u_int32_t m_curGameId; 259 260 u_int32_t m_curUniquePlayerId; 261 u_int32_t m_curSessionId; 262 mutable boost::mutex m_curUniquePlayerIdMutex; 263 264 ServerStats m_statData; 265 bool m_statDataChanged; 266 mutable boost::mutex m_statMutex; 267 268 boost::shared_ptr<ServerBanManager> m_banManager; 269 boost::shared_ptr<ChatCleanerManager> m_chatCleanerManager; 270 boost::shared_ptr<ServerDBInterface> m_database; 271 272 boost::asio::steady_timer m_removeGameTimer; 273 boost::asio::steady_timer m_saveStatisticsTimer; 274 boost::asio::steady_timer m_loginLockTimer; 275 276 boost::uuids::random_generator m_sessionIdGenerator; 277 278 const boost::posix_time::ptime m_startTime; 279 280 friend class InternalServerCallback; 281 }; 282 283 #endif 284