From cdd21250ded37a01f5b2c550f201160f2026819b Mon Sep 17 00:00:00 2001 From: lotodore Date: Fri, 16 Nov 2007 00:58:23 +0000 Subject: [PATCH] Added support for password protected irc channels. Added server IRC mode for admin use, to allow requesting statistics and kicking players. --- src/config/configfile.cpp | 9 ++- src/game_defs.h | 8 +-- src/net/common/clientthread.cpp | 4 +- src/net/common/ircthread.cpp | 6 +- src/net/common/netpacket.cpp | 8 +-- src/net/common/serveracceptthread.cpp | 77 ++++++++++++++++++++- src/net/common/servergamethread.cpp | 27 ++++++++ src/net/common/serverlobbythread.cpp | 97 +++++++++++++++++++++++---- src/net/ircthread.h | 2 +- src/net/serveracceptthread.h | 19 +++++- src/net/servergamethread.h | 5 ++ src/net/serverlobbythread.h | 12 +++- src/session.cpp | 50 +++++++++----- src/session.h | 3 +- 14 files changed, 277 insertions(+), 50 deletions(-) diff --git a/src/config/configfile.cpp b/src/config/configfile.cpp index ccea6642..b4acdf81 100644 --- a/src/config/configfile.cpp +++ b/src/config/configfile.cpp @@ -53,7 +53,7 @@ ConfigFile::ConfigFile(int argc, char **argv) : noWriteAccess(0) if(strcmp(argv[i], "--nowriteaccess") == 0) { noWriteAccess = 1; } } // !!!! Revisionsnummer der Configdefaults !!!!! - configRev = 51; + configRev = 52; //standard defaults logOnOffDefault = "1"; @@ -216,6 +216,13 @@ ConfigFile::ConfigFile(int argc, char **argv) : noWriteAccess(0) configList.push_back(ConfigInfo("IRCChannel", CONFIG_TYPE_STRING, "#pokerth-lobby")); configList.push_back(ConfigInfo("IRCChannelPassword", CONFIG_TYPE_STRING, "")); configList.push_back(ConfigInfo("IRCServerUseIpv6", CONFIG_TYPE_INT, "0")); + configList.push_back(ConfigInfo("UseAdminIRC", CONFIG_TYPE_INT, "0")); + configList.push_back(ConfigInfo("AdminIRCServerAddress", CONFIG_TYPE_STRING, "chat.freenode.net")); + configList.push_back(ConfigInfo("AdminIRCServerPort", CONFIG_TYPE_INT, "6667")); + configList.push_back(ConfigInfo("AdminIRCChannel", CONFIG_TYPE_STRING, "#test")); + configList.push_back(ConfigInfo("AdminIRCChannelPassword", CONFIG_TYPE_STRING, "")); + configList.push_back(ConfigInfo("AdminIRCServerUseIpv6", CONFIG_TYPE_INT, "0")); + configList.push_back(ConfigInfo("AdminIRCServerNick", CONFIG_TYPE_INT, "PokerTH")); configList.push_back(ConfigInfo("MyName", CONFIG_TYPE_STRING, "Human Player")); configList.push_back(ConfigInfo("MyAvatar", CONFIG_TYPE_STRING, "")); configList.push_back(ConfigInfo("Opponent1Name", CONFIG_TYPE_STRING, "Player 1")); diff --git a/src/game_defs.h b/src/game_defs.h index 91d59020..e8a8428a 100644 --- a/src/game_defs.h +++ b/src/game_defs.h @@ -70,12 +70,12 @@ enum Button { struct ServerStats { ServerStats() - : numberOfPlayersOnServer(0), totalPlayersEverLoggedIn(0), totalGamesEverStarted(0), - maxGamesRunning(0), maxPlayersLoggedIn(0) {} + : numberOfPlayersOnServer(0), totalPlayersEverLoggedIn(0), totalGamesEverCreated(0), + maxGamesOpen(0), maxPlayersLoggedIn(0) {} unsigned numberOfPlayersOnServer; unsigned totalPlayersEverLoggedIn; - unsigned totalGamesEverStarted; - unsigned maxGamesRunning; + unsigned totalGamesEverCreated; + unsigned maxGamesOpen; unsigned maxPlayersLoggedIn; }; diff --git a/src/net/common/clientthread.cpp b/src/net/common/clientthread.cpp index 849d76b8..938128b0 100644 --- a/src/net/common/clientthread.cpp +++ b/src/net/common/clientthread.cpp @@ -956,8 +956,8 @@ ClientThread::UpdateStatData(const ServerStats &stats) if (stats.totalPlayersEverLoggedIn) m_curStats.totalPlayersEverLoggedIn = stats.totalPlayersEverLoggedIn; - if (stats.totalGamesEverStarted) - m_curStats.totalGamesEverStarted = stats.totalGamesEverStarted; + if (stats.totalGamesEverCreated) + m_curStats.totalGamesEverCreated = stats.totalGamesEverCreated; GetCallback().SignalNetClientStatsUpdate(m_curStats); } diff --git a/src/net/common/ircthread.cpp b/src/net/common/ircthread.cpp index 6feb7a6c..ee538f31 100644 --- a/src/net/common/ircthread.cpp +++ b/src/net/common/ircthread.cpp @@ -43,6 +43,7 @@ struct IrcContext bool useIPv6; string nick; string channel; + string channelPassword; unsigned renameTries; }; @@ -106,7 +107,7 @@ irc_event_connect(irc_session_t *session, const char * /*irc_event*/, const char IrcContext *context = (IrcContext *) irc_get_ctx(session); context->ircThread.GetCallback().SignalIrcConnect(origin); - irc_cmd_join(session, context->channel.c_str(), 0); + irc_cmd_join(session, context->channel.c_str(), context->channelPassword.c_str()); } void @@ -259,7 +260,7 @@ IrcThread::~IrcThread() } void -IrcThread::Init(const std::string &serverAddress, unsigned serverPort, bool ipv6, const std::string &nick, const std::string &channel) +IrcThread::Init(const std::string &serverAddress, unsigned serverPort, bool ipv6, const std::string &nick, const std::string &channel, const std::string &channelPassword) { if (IsRunning() || serverAddress.empty() || nick.empty() || channel.empty()) return; // TODO: throw exception @@ -271,6 +272,7 @@ IrcThread::Init(const std::string &serverAddress, unsigned serverPort, bool ipv6 context.useIPv6 = ipv6; context.nick = nick; context.channel = channel; + context.channelPassword = channelPassword; // Initialize libirc stuff. irc_callbacks_t callbacks; diff --git a/src/net/common/netpacket.cpp b/src/net/common/netpacket.cpp index f39a6715..d252608a 100644 --- a/src/net/common/netpacket.cpp +++ b/src/net/common/netpacket.cpp @@ -4092,7 +4092,7 @@ NetPacketStatisticsChanged::SetData(const NetPacketStatisticsChanged::Data &inDa ++numValues; if (inData.stats.totalPlayersEverLoggedIn) ++numValues; - if (inData.stats.totalGamesEverStarted) + if (inData.stats.totalGamesEverCreated) ++numValues; // Resize the packet so that the data fits in. @@ -4118,10 +4118,10 @@ NetPacketStatisticsChanged::SetData(const NetPacketStatisticsChanged::Data &inDa curStatisticsData->statisticsValue = htonl(inData.stats.totalPlayersEverLoggedIn); ++curStatisticsData; } - if (inData.stats.totalGamesEverStarted) + if (inData.stats.totalGamesEverCreated) { curStatisticsData->statisticsType = htonl(NET_STAT_TOTAL_GAMES_EVER_ON_SERVER); - curStatisticsData->statisticsValue = htonl(inData.stats.totalGamesEverStarted); + curStatisticsData->statisticsValue = htonl(inData.stats.totalGamesEverCreated); } // Check the packet - just in case. @@ -4148,7 +4148,7 @@ NetPacketStatisticsChanged::GetData(NetPacketStatisticsChanged::Data &outData) c outData.stats.totalPlayersEverLoggedIn = ntohl(curStatisticsData->statisticsValue); break; case NET_STAT_TOTAL_GAMES_EVER_ON_SERVER: - outData.stats.totalGamesEverStarted = ntohl(curStatisticsData->statisticsValue); + outData.stats.totalGamesEverCreated = ntohl(curStatisticsData->statisticsValue); break; } } diff --git a/src/net/common/serveracceptthread.cpp b/src/net/common/serveracceptthread.cpp index c1ef66ed..9ee9e06d 100644 --- a/src/net/common/serveracceptthread.cpp +++ b/src/net/common/serveracceptthread.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -27,6 +28,8 @@ #include #include +#include + #define ACCEPT_TIMEOUT_MSEC 50 #define NET_SERVER_LISTEN_BACKLOG 5 @@ -44,7 +47,7 @@ ServerAcceptThread::~ServerAcceptThread() } void -ServerAcceptThread::Init(unsigned serverPort, bool ipv6, bool sctp, const string &pwd, const string &logDir) +ServerAcceptThread::Init(unsigned serverPort, bool ipv6, bool sctp, const string &pwd, const string &logDir, boost::shared_ptr ircThread) { if (IsRunning()) { @@ -61,6 +64,7 @@ ServerAcceptThread::Init(unsigned serverPort, bool ipv6, bool sctp, const string context.SetServerPort(serverPort); GetLobbyThread().Init(pwd, logDir); + m_ircThread = ircThread; } ServerCallback & @@ -75,12 +79,75 @@ ServerAcceptThread::GetGui() return m_gui; } +void +ServerAcceptThread::SignalIrcConnect(const std::string &server) +{ + LOG_MSG("Connected to IRC server " << server << "."); +} + +void +ServerAcceptThread::SignalIrcSelfJoined(const std::string &nickName, const std::string &channel) +{ + LOG_MSG("Joined IRC channel " << channel << " as user " << nickName << "."); + m_ircNick = nickName; +} + +void +ServerAcceptThread::SignalIrcChatMsg(const std::string &nickName, const std::string &msg) +{ + if (m_ircThread) + { + istringstream msgStream(msg); + string target; + msgStream >> target; + if (boost::algorithm::iequals(target, m_ircNick + ":")) + { + string command; + msgStream >> command; + if (command == "kick") + { + string playerName; + msgStream >> playerName; + if (!playerName.empty()) + { + if (GetLobbyThread().KickPlayerByName(playerName)) + m_ircThread->SendChatMessage(nickName + ": Successfully kicked player \"" + playerName + "\" from the server."); + else + m_ircThread->SendChatMessage(nickName + ": Player \"" + playerName + "\" was not found on the server."); + } + } + else if (command == "stat") + { + ServerStats tmpStats = GetLobbyThread().GetStats(); + ostringstream statStream; + statStream + << "Players on Server: " << tmpStats.numberOfPlayersOnServer; + m_ircThread->SendChatMessage(statStream.str()); + } + else + m_ircThread->SendChatMessage(nickName + ": Invalid command \"" + command + "\"."); + } + } +} + +void +ServerAcceptThread::SignalIrcError(int errorCode) +{ +} + +void +ServerAcceptThread::SignalIrcServerError(int errorCode) +{ +} + void ServerAcceptThread::Main() { try { Listen(); + if (m_ircThread) + m_ircThread->Run(); GetLobbyThread().Run(); while (!ShouldTerminate() && !GetLobbyThread().Join(0)) @@ -94,7 +161,13 @@ ServerAcceptThread::Main() LOG_ERROR(e.what()); } GetLobbyThread().SignalTermination(); - GetLobbyThread().Join(LOBBY_THREAD_TERMINATE_TIMEOUT); + GetLobbyThread().Join(LOBBY_THREAD_TERMINATE_TIMEOUT_MSEC); + + if (m_ircThread) + { + m_ircThread->SignalTermination(); + m_ircThread->Join(ADMIN_IRC_TERMINATE_TIMEOUT_MSEC); + } } void diff --git a/src/net/common/servergamethread.cpp b/src/net/common/servergamethread.cpp index a18e8bc8..23129752 100644 --- a/src/net/common/servergamethread.cpp +++ b/src/net/common/servergamethread.cpp @@ -87,6 +87,13 @@ ServerGameThread::AddSession(SessionWrapper session) m_sessionQueue.push_back(session); } +void +ServerGameThread::KickPlayer(unsigned playerId) +{ + boost::mutex::scoped_lock lock(m_kickPlayerListMutex); + m_kickPlayerList.push_back(playerId); +} + GameState ServerGameThread::GetCurRound() const { @@ -141,6 +148,7 @@ ServerGameThread::Main() } // Process current state. GetState().Process(*this); + KickPlayerLoop(); } while (!ShouldTerminate() && GetSessionManager().HasSessions()); } catch (const PokerTHException &e) { @@ -155,6 +163,25 @@ ServerGameThread::Main() GetLobbyThread().RemoveGame(GetId()); } +void +ServerGameThread::KickPlayerLoop() +{ + boost::mutex::scoped_lock lock(m_kickPlayerListMutex); + + PlayerIdList::iterator i = m_kickPlayerList.begin(); + PlayerIdList::iterator end = m_kickPlayerList.end(); + + while (i != end) + { + SessionWrapper tmpSession = GetSessionManager().GetSessionByUniquePlayerId(*i); + // Only kick if the player was found. + if (tmpSession.sessionData.get()) + SessionError(tmpSession, ERR_NET_PLAYER_KICKED); + ++i; + } + m_kickPlayerList.clear(); +} + void ServerGameThread::InternalStartGame() { diff --git a/src/net/common/serverlobbythread.cpp b/src/net/common/serverlobbythread.cpp index 1c4e1994..a91f1e55 100644 --- a/src/net/common/serverlobbythread.cpp +++ b/src/net/common/serverlobbythread.cpp @@ -43,8 +43,8 @@ #define SERVER_STATISTICS_FILE_NAME "server_statistics.log" #define SERVER_STATISTICS_STR_TOTAL_PLAYERS "TotalNumPlayersLoggedIn" -#define SERVER_STATISTICS_STR_TOTAL_GAMES "TotalNumGamesStarted" -#define SERVER_STATISTICS_STR_MAX_GAMES "MaxGamesRunning" +#define SERVER_STATISTICS_STR_TOTAL_GAMES "TotalNumGamesCreated" +#define SERVER_STATISTICS_STR_MAX_GAMES "MaxGamesOpen" #define SERVER_STATISTICS_STR_MAX_PLAYERS "MaxPlayersLoggedIn" using namespace std; @@ -201,14 +201,6 @@ ServerLobbyThread::NotifyStartingGame(unsigned gameId) boost::shared_ptr packet = CreateNetPacketGameListUpdate(gameId, GAME_MODE_STARTED); m_sessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Established); m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Game); - - { - boost::mutex::scoped_lock lock(m_statMutex); - ++m_statData.totalGamesEverStarted; - if (m_statData.totalGamesEverStarted > m_statData.maxGamesRunning) - m_statData.maxGamesRunning = m_statData.totalGamesEverStarted; - m_statDataChanged = true; - } } void @@ -233,6 +225,24 @@ ServerLobbyThread::HandleGameRetrieveAvatar(SessionWrapper session, const NetPac HandleNetPacketRetrieveAvatar(session, tmpPacket); } +bool +ServerLobbyThread::KickPlayerByName(const std::string &playerName) +{ + bool retVal = false; + SessionWrapper session = m_sessionManager.GetSessionByPlayerName(playerName); + if (!session.sessionData.get()) + session = m_gameSessionManager.GetSessionByPlayerName(playerName); + + if (session.sessionData.get() && session.playerData.get()) + { + boost::mutex::scoped_lock lock(m_kickPlayerListMutex); + m_kickPlayerList.push_back(session.playerData->GetUniqueId()); + retVal = true; + } + + return retVal; +} + void ServerLobbyThread::AddComputerPlayer(boost::shared_ptr player) { @@ -260,6 +270,13 @@ ServerLobbyThread::GetAvatarManager() return m_avatarManager; } +ServerStats +ServerLobbyThread::GetStats() const +{ + boost::mutex::scoped_lock lock(m_statMutex); + return m_statData; +} + u_int32_t ServerLobbyThread::GetNextUniquePlayerId() { @@ -293,6 +310,8 @@ ServerLobbyThread::Main() CloseSessionLoop(); // Remove games. RemoveGameLoop(); + // Kick players. + KickPlayerLoop(); // Cleanup cache. CleanupAvatarCache(); // Save statistics if needed. @@ -773,6 +792,22 @@ ServerLobbyThread::RemoveGameLoop() m_removeGameList.clear(); } +void +ServerLobbyThread::KickPlayerLoop() +{ + boost::mutex::scoped_lock lock(m_kickPlayerListMutex); + + PlayerIdList::iterator i = m_kickPlayerList.begin(); + PlayerIdList::iterator end = m_kickPlayerList.end(); + + while (i != end) + { + InternalKickPlayer(*i); + ++i; + } + m_kickPlayerList.clear(); +} + void ServerLobbyThread::CleanupAvatarCache() { @@ -794,6 +829,15 @@ ServerLobbyThread::InternalAddGame(boost::shared_ptr game) // Notify all players. m_sessionManager.SendToAllSessionsLowPrio(GetSender(), CreateNetPacketGameListNew(*game), SessionData::Established); m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), CreateNetPacketGameListNew(*game), SessionData::Game); + + { + boost::mutex::scoped_lock lock(m_statMutex); + ++m_statData.totalGamesEverCreated; + unsigned numGames = static_cast(m_gameMap.size()); + if (numGames > m_statData.maxGamesOpen) + m_statData.maxGamesOpen = numGames; + m_statDataChanged = true; + } } void @@ -809,6 +853,31 @@ ServerLobbyThread::InternalRemoveGame(boost::shared_ptr game) m_gameSessionManager.SendToAllSessionsLowPrio(GetSender(), packet, SessionData::Game); } +void +ServerLobbyThread::InternalKickPlayer(unsigned playerId) +{ + SessionWrapper session = m_sessionManager.GetSessionByUniquePlayerId(playerId); + if (session.sessionData.get()) + SessionError(session, ERR_NET_PLAYER_KICKED); + else + { + // Scan games for the player. + GameMap::iterator i = m_gameMap.begin(); + GameMap::iterator end = m_gameMap.end(); + + while (i != end) + { + boost::shared_ptr tmpGame = i->second; + if (tmpGame->GetPlayerDataByUniqueId(playerId).get()) + { + tmpGame->KickPlayer(playerId); + break; + } + ++i; + } + } +} + void ServerLobbyThread::TerminateGames() { @@ -982,11 +1051,11 @@ ServerLobbyThread::ReadStatisticsFile() if (statisticsType == SERVER_STATISTICS_STR_TOTAL_PLAYERS) m_statData.totalPlayersEverLoggedIn = statisticsValue; else if (statisticsType == SERVER_STATISTICS_STR_TOTAL_GAMES) - m_statData.totalGamesEverStarted = statisticsValue; + m_statData.totalGamesEverCreated = statisticsValue; else if (statisticsType == SERVER_STATISTICS_STR_MAX_PLAYERS) m_statData.maxPlayersLoggedIn = statisticsValue; else if (statisticsType == SERVER_STATISTICS_STR_MAX_GAMES) - m_statData.maxGamesRunning = statisticsValue; + m_statData.maxGamesOpen = statisticsValue; } while (!i.fail() && !i.eof()); m_statDataChanged = false; } @@ -1005,9 +1074,9 @@ ServerLobbyThread::SaveStatisticsFile() if (!o.fail()) { o << SERVER_STATISTICS_STR_TOTAL_PLAYERS " " << m_statData.totalPlayersEverLoggedIn << endl; - o << SERVER_STATISTICS_STR_TOTAL_GAMES " " << m_statData.totalGamesEverStarted << endl; + o << SERVER_STATISTICS_STR_TOTAL_GAMES " " << m_statData.totalGamesEverCreated << endl; o << SERVER_STATISTICS_STR_MAX_PLAYERS " " << m_statData.maxPlayersLoggedIn << endl; - o << SERVER_STATISTICS_STR_MAX_GAMES " " << m_statData.maxGamesRunning << endl; + o << SERVER_STATISTICS_STR_MAX_GAMES " " << m_statData.maxGamesOpen << endl; m_statDataChanged = false; } } diff --git a/src/net/ircthread.h b/src/net/ircthread.h index beebe22e..fac67d82 100644 --- a/src/net/ircthread.h +++ b/src/net/ircthread.h @@ -35,7 +35,7 @@ public: virtual ~IrcThread(); // Set the parameters. - void Init(const std::string &serverAddress, unsigned serverPort, bool ipv6, const std::string &nick, const std::string &channel); + void Init(const std::string &serverAddress, unsigned serverPort, bool ipv6, const std::string &nick, const std::string &channel, const std::string &channelPassword); // Send a chat message to the channel. void SendChatMessage(const std::string &msg); diff --git a/src/net/serveracceptthread.h b/src/net/serveracceptthread.h index 3087a3dc..c7540ae4 100644 --- a/src/net/serveracceptthread.h +++ b/src/net/serveracceptthread.h @@ -23,6 +23,7 @@ #include #include + #include #include @@ -32,20 +33,31 @@ class ServerSenderCallback; class SenderThread; class ConfigFile; class AvatarManager; +class IrcThread; struct GameData; -class ServerAcceptThread : public Thread +class ServerAcceptThread : public Thread, public IrcCallback { public: ServerAcceptThread(GuiInterface &gui, ConfigFile *config, AvatarManager &avatarManager); virtual ~ServerAcceptThread(); // Set the parameters. - void Init(unsigned serverPort, bool ipv6, bool sctp, const std::string &pwd, const std::string &logDir); + void Init(unsigned serverPort, bool ipv6, bool sctp, const std::string &pwd, const std::string &logDir, boost::shared_ptr ircThread); ServerCallback &GetCallback(); GuiInterface &GetGui(); + virtual void SignalIrcConnect(const std::string &server); + virtual void SignalIrcSelfJoined(const std::string &nickName, const std::string &channel); + virtual void SignalIrcPlayerJoined(const std::string & /*nickName*/) {} + virtual void SignalIrcPlayerChanged(const std::string & /*oldNick*/, const std::string & /*newNick*/) {} + virtual void SignalIrcPlayerKicked(const std::string & /*nickName*/, const std::string & /*byWhom*/, const std::string & /*reason*/) {} + virtual void SignalIrcPlayerLeft(const std::string & /*nickName*/) {} + virtual void SignalIrcChatMsg(const std::string &nickName, const std::string &msg); + virtual void SignalIrcError(int errorCode); + virtual void SignalIrcServerError(int errorCode); + protected: // Main function of the thread. @@ -64,6 +76,9 @@ private: boost::shared_ptr m_lobbyThread; GuiInterface &m_gui; + + std::string m_ircNick; + boost::shared_ptr m_ircThread; }; #endif diff --git a/src/net/servergamethread.h b/src/net/servergamethread.h index f06b96e1..2c2a38ba 100644 --- a/src/net/servergamethread.h +++ b/src/net/servergamethread.h @@ -50,6 +50,7 @@ public: const std::string &GetName() const; void AddSession(SessionWrapper session); + void KickPlayer(unsigned playerId); ServerCallback &GetCallback(); GameState GetCurRound() const; @@ -80,6 +81,7 @@ protected: // Main function of the thread. virtual void Main(); + void KickPlayerLoop(); void InternalStartGame(); void ResetGame(); @@ -129,6 +131,9 @@ private: PlayerDataList m_computerPlayerList; mutable boost::mutex m_computerPlayerListMutex; + PlayerIdList m_kickPlayerList; + mutable boost::mutex m_kickPlayerListMutex; + unsigned m_adminPlayerId; mutable boost::mutex m_adminPlayerIdMutex; diff --git a/src/net/serverlobbythread.h b/src/net/serverlobbythread.h index 9f5c6919..fc23f9ad 100644 --- a/src/net/serverlobbythread.h +++ b/src/net/serverlobbythread.h @@ -31,7 +31,8 @@ #include #include -#define LOBBY_THREAD_TERMINATE_TIMEOUT 20000 +#define LOBBY_THREAD_TERMINATE_TIMEOUT_MSEC 20000 +#define ADMIN_IRC_TERMINATE_TIMEOUT_MSEC 2000 class SenderThread; @@ -65,6 +66,8 @@ public: void HandleGameRetrievePlayerInfo(SessionWrapper session, const NetPacketRetrievePlayerInfo &tmpPacket); void HandleGameRetrieveAvatar(SessionWrapper session, const NetPacketRetrieveAvatar &tmpPacket); + bool KickPlayerByName(const std::string &playerName); + void AddComputerPlayer(boost::shared_ptr player); void RemoveComputerPlayer(boost::shared_ptr player); @@ -76,6 +79,8 @@ public: AvatarManager &GetAvatarManager(); + ServerStats GetStats() const; + protected: typedef std::deque > ConnectQueue; @@ -105,10 +110,12 @@ protected: void NewSessionLoop(); void CloseSessionLoop(); void RemoveGameLoop(); + void KickPlayerLoop(); void CleanupAvatarCache(); void InternalAddGame(boost::shared_ptr game); void InternalRemoveGame(boost::shared_ptr game); + void InternalKickPlayer(unsigned playerId); void TerminateGames(); @@ -160,6 +167,9 @@ private: RemoveGameList m_removeGameList; mutable boost::mutex m_removeGameListMutex; + PlayerIdList m_kickPlayerList; + mutable boost::mutex m_kickPlayerListMutex; + PlayerDataMap m_computerPlayers; mutable boost::mutex m_computerPlayersMutex; diff --git a/src/session.cpp b/src/session.cpp index ab2d2cc8..a8c8bbe2 100755 --- a/src/session.cpp +++ b/src/session.cpp @@ -39,7 +39,7 @@ using namespace std; Session::Session(GuiInterface *g, ConfigFile *c) -: currentGameNum(0), myNetClient(NULL), myNetServer(NULL), myIrcThread(NULL), +: currentGameNum(0), myNetClient(NULL), myNetServer(NULL), myClientIrcThread(NULL), myGui(g), myConfig(c), myGameType(GAME_TYPE_NONE) { } @@ -139,7 +139,7 @@ boost::shared_ptr Session::getAvatarManager() void Session::startInternetClient() { - if (myNetClient || myIrcThread || !myGui) + if (myNetClient || myClientIrcThread || !myGui) { assert(false); return; @@ -148,14 +148,15 @@ void Session::startInternetClient() if (myConfig->readConfigInt("UseIRCLobbyChat")) { - myIrcThread = new IrcThread(*myGui); - myIrcThread->Init( + myClientIrcThread = new IrcThread(*myGui); + myClientIrcThread->Init( myConfig->readConfigString("IRCServerAddress"), myConfig->readConfigInt("IRCServerPort"), myConfig->readConfigInt("IRCServerUseIpv6") == 1, myIrcNick, - myConfig->readConfigString("IRCChannel")); - myIrcThread->Run(); + myConfig->readConfigString("IRCChannel"), + myConfig->readConfigString("IRCChannelPassword")); + myClientIrcThread->Run(); } myNetClient = new ClientThread(*myGui, *myAvatarManager); @@ -221,17 +222,17 @@ void Session::terminateNetworkClient() if (!myNetClient) return; // already terminated myNetClient->SignalTermination(); - if (myIrcThread) - myIrcThread->SignalTermination(); + if (myClientIrcThread) + myClientIrcThread->SignalTermination(); // Give the threads some time to terminate. if (myNetClient->Join(NET_CLIENT_TERMINATE_TIMEOUT_MSEC)) delete myNetClient; - if (myIrcThread && myIrcThread->Join(NET_IRC_TERMINATE_TIMEOUT_MSEC)) - delete myIrcThread; + if (myClientIrcThread && myClientIrcThread->Join(NET_IRC_TERMINATE_TIMEOUT_MSEC)) + delete myClientIrcThread; // If termination fails, leave a memory leak to prevent a crash. myNetClient = 0; - myIrcThread = 0; + myClientIrcThread = 0; myGameType = GAME_TYPE_NONE; } @@ -256,13 +257,32 @@ void Session::startNetworkServer() assert(false); return; } + myNetServer = new ServerAcceptThread(*myGui, myConfig, *myAvatarManager); + + boost::shared_ptr tmpIrcThread; + if (myConfig->readConfigInt("UseAdminIRC")) + { + tmpIrcThread = boost::shared_ptr(new IrcThread(*myNetServer)); + + tmpIrcThread->Init( + myConfig->readConfigString("AdminIRCServerAddress"), + myConfig->readConfigInt("AdminIRCServerPort"), + myConfig->readConfigInt("AdminIRCServerUseIpv6") == 1, + myConfig->readConfigString("AdminIRCServerNick"), + myConfig->readConfigString("AdminIRCChannel"), + myConfig->readConfigString("AdminIRCChannelPassword")); + } + myNetServer->Init( myConfig->readConfigInt("ServerPort"), myConfig->readConfigInt("ServerUseIpv6") == 1, myConfig->readConfigInt("ServerUseSctp") == 1, myConfig->readConfigString("ServerPassword"), - myConfig->readConfigString("LogDir")); + myConfig->readConfigString("LogDir"), + tmpIrcThread + ); + myNetServer->Run(); } @@ -273,9 +293,7 @@ void Session::terminateNetworkServer() myNetServer->SignalTermination(); // Give the thread some time to terminate. if (myNetServer->Join(NET_SERVER_TERMINATE_TIMEOUT_MSEC)) - { delete myNetServer; - } // If termination fails, leave a memory leak to prevent a crash. myNetServer = 0; } @@ -299,9 +317,9 @@ bool Session::waitForNetworkServer(unsigned timeoutMsec) void Session::sendIrcChatMessage(const std::string &message) { - if (!myIrcThread) + if (!myClientIrcThread) return; - myIrcThread->SendChatMessage(message); + myClientIrcThread->SendChatMessage(message); } void Session::sendLeaveCurrentGame() diff --git a/src/session.h b/src/session.h index b9d5f314..6e91238b 100755 --- a/src/session.h +++ b/src/session.h @@ -96,7 +96,8 @@ private: ClientThread *myNetClient; ServerAcceptThread *myNetServer; - IrcThread *myIrcThread; + IrcThread *myClientIrcThread; + boost::shared_ptr myAvatarManager; boost::shared_ptr currentGame;