2007-11-16 22:34:38 +00:00
/***************************************************************************
* 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. *
***************************************************************************/
2008-04-16 20:38:11 +00:00
#include <net/socket_helper.h>
2007-11-16 22:34:38 +00:00
#include <net/servermanager.h>
#include <net/ircthread.h>
#include <net/serverlobbythread.h>
2009-05-10 22:21:20 +00:00
#include <net/serveraccepthelper.h>
2009-06-18 20:16:22 +00:00
#include <net/serverbanmanager.h>
2007-11-16 22:34:38 +00:00
#include <net/serverexception.h>
#include <net/socket_msg.h>
#include <net/socket_startup.h>
#include <core/loghelper.h>
#include <boost/bind.hpp>
#include <boost/algorithm/string/predicate.hpp>
2008-11-02 21:25:42 +00:00
#define SERVER_RESTART_IRC_BOT_INTERVAL_SEC 86400 // 1 day
2007-11-16 22:34:38 +00:00
using namespace std ;
ServerManager :: ServerManager ( GuiInterface & gui , ConfigFile * config , AvatarManager & avatarManager )
: m_gui ( gui ), m_playerConfig ( config ), m_avatarManager ( avatarManager )
{
2009-06-14 22:07:41 +00:00
m_ioService . reset ( new boost :: asio :: io_service );
2007-11-16 22:34:38 +00:00
}
ServerManager ::~ ServerManager ()
{
}
void
ServerManager :: Init ( unsigned serverPort , bool ipv6 , ServerNetworkMode mode , const string & pwd , const string & logDir , boost :: shared_ptr < IrcThread > ircThread )
{
2009-05-04 21:11:29 +00:00
m_lobbyThread . reset ( new ServerLobbyThread ( GetGui (), m_playerConfig , m_avatarManager , m_ioService ));
2007-11-16 22:34:38 +00:00
GetLobbyThread (). Init ( pwd , logDir );
if ( mode & NETWORK_MODE_TCP )
{
2009-05-10 22:21:20 +00:00
boost :: shared_ptr < ServerAcceptHelper > tcpAcceptHelper ( new ServerAcceptHelper ( GetGui (), m_ioService ));
tcpAcceptHelper -> Listen ( serverPort , ipv6 , false , pwd , logDir , m_lobbyThread );
m_acceptHelperPool . push_back ( tcpAcceptHelper );
2007-11-16 22:34:38 +00:00
}
2009-07-22 20:26:29 +00:00
/* if (mode & NETWORK_MODE_SCTP)
2007-11-16 22:34:38 +00:00
{
2009-05-10 22:21:20 +00:00
boost::shared_ptr<ServerAcceptHelper> sctpAcceptHelper(new ServerAcceptHelper(GetGui(), m_ioService));
sctpAcceptHelper->Listen(serverPort, ipv6, true, pwd, logDir, m_lobbyThread);
m_acceptHelperPool.push_back(sctpAcceptHelper);
2009-07-22 20:26:29 +00:00
}*/
2007-11-16 22:34:38 +00:00
m_ircThread = ircThread ;
}
GuiInterface &
ServerManager :: GetGui ()
{
return m_gui ;
}
void
ServerManager :: SignalIrcConnect ( const std :: string & server )
{
LOG_MSG ( "Connected to IRC server " << server << "." );
}
void
ServerManager :: SignalIrcSelfJoined ( const std :: string & nickName , const std :: string & channel )
{
LOG_MSG ( "Joined IRC channel " << channel << " as user " << nickName << "." );
m_ircNick = nickName ;
}
void
ServerManager :: SignalIrcChatMsg ( const std :: string & nickName , const std :: string & msg )
{
if ( m_ircThread )
{
2009-04-10 21:04:08 +00:00
try
2007-11-16 22:34:38 +00:00
{
2009-04-10 21:04:08 +00:00
istringstream msgStream ( msg );
string target ;
msgStream >> target ;
if ( boost :: algorithm :: iequals ( target , m_ircNick + ":" ))
2007-11-16 22:34:38 +00:00
{
2009-04-10 21:04:08 +00:00
string command ;
msgStream >> command ;
if ( command == "kick" )
2007-11-16 22:34:38 +00:00
{
2009-04-10 21:04:08 +00:00
while ( msgStream . peek () == ' ' )
msgStream . get ();
string playerName ( msgStream . str (). substr ( msgStream . tellg ()));
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." );
}
}
2009-04-10 21:54:59 +00:00
else if ( command == "showip" )
{
while ( msgStream . peek () == ' ' )
msgStream . get ();
string playerName ( msgStream . str (). substr ( msgStream . tellg ()));
if ( ! playerName . empty ())
{
string ipAddress ( GetLobbyThread (). GetPlayerIPAddress ( playerName ));
if ( ! ipAddress . empty ())
2009-04-11 11:03:22 +00:00
m_ircThread -> SendChatMessage ( nickName + ": The IP address of player \" " + playerName + " \" is: \" " + ipAddress + " \" " );
2009-04-10 21:54:59 +00:00
else
m_ircThread -> SendChatMessage ( nickName + ": The IP address of player \" " + playerName + " \" is unknown." );
}
}
2009-04-11 11:03:22 +00:00
else if ( command == "bannick" )
2009-04-10 21:04:08 +00:00
{
while ( msgStream . peek () == ' ' )
msgStream . get ();
string playerRegex ( msgStream . str (). substr ( msgStream . tellg ()));
if ( ! playerRegex . empty ())
{
2009-06-18 20:16:22 +00:00
GetLobbyThread (). GetBanManager (). BanPlayerRegex ( playerRegex );
2009-04-10 21:04:08 +00:00
m_ircThread -> SendChatMessage ( nickName + ": The regex \" " + playerRegex + " \" was added to the player ban list." );
}
}
2009-04-11 11:03:22 +00:00
else if ( command == "banip" )
{
while ( msgStream . peek () == ' ' )
msgStream . get ();
2009-06-18 21:32:01 +00:00
string ipAddress ;
unsigned durationHours = 12 ;
msgStream >> ipAddress ;
while ( msgStream . peek () == ' ' )
msgStream . get ();
if ( ! msgStream . eof ())
msgStream >> durationHours ;
2009-04-11 11:03:22 +00:00
if ( ! ipAddress . empty ())
{
2009-06-18 21:32:01 +00:00
ostringstream durationStr ;
durationStr << durationHours ;
GetLobbyThread (). GetBanManager (). BanIPAddress ( ipAddress , durationHours );
m_ircThread -> SendChatMessage ( nickName + ": The IP address \" " + ipAddress + " \" was added to the IP address ban list for " + durationStr . str () + ( durationHours == 1 ? " hour." : " hours." ));
2009-04-11 11:03:22 +00:00
}
}
2009-04-10 21:54:59 +00:00
else if ( command == "listban" )
2009-04-10 21:04:08 +00:00
{
list < string > banList ;
2009-06-18 20:16:22 +00:00
GetLobbyThread (). GetBanManager (). GetBanList ( banList );
2009-04-10 21:04:08 +00:00
list < string >:: const_iterator i = banList . begin ();
list < string >:: const_iterator end = banList . end ();
while ( i != end )
{
m_ircThread -> SendChatMessage ( * i );
++ i ;
}
2009-04-10 21:32:08 +00:00
ostringstream banListStream ;
banListStream
2009-04-10 21:54:59 +00:00
<< nickName << ": Total count of bans: " << banList . size ();
2009-04-10 21:32:08 +00:00
m_ircThread -> SendChatMessage ( banListStream . str ());
2009-04-10 21:04:08 +00:00
}
2009-04-10 21:54:59 +00:00
else if ( command == "removeban" )
2009-04-10 21:04:08 +00:00
{
unsigned banId = 0 ;
msgStream >> banId ;
2009-06-18 20:16:22 +00:00
if ( GetLobbyThread (). GetBanManager (). UnBan ( banId ))
2009-04-11 11:14:12 +00:00
m_ircThread -> SendChatMessage ( nickName + ": The ban was successfully removed." );
2007-11-16 22:34:38 +00:00
else
2009-04-11 11:14:12 +00:00
m_ircThread -> SendChatMessage ( nickName + ": This ban does not exist." );
2007-11-16 22:34:38 +00:00
}
2009-04-10 21:54:59 +00:00
else if ( command == "clearban" )
2009-04-07 22:09:52 +00:00
{
2009-06-18 20:16:22 +00:00
GetLobbyThread (). GetBanManager (). ClearBanList ();
2009-04-10 21:54:59 +00:00
m_ircThread -> SendChatMessage ( nickName + ": All ban lists were cleared." );
2009-04-07 22:09:52 +00:00
}
2009-04-10 21:04:08 +00:00
else if ( command == "stat" )
2007-11-28 23:31:34 +00:00
{
2009-04-10 21:04:08 +00:00
ServerStats tmpStats = GetLobbyThread (). GetStats ();
{
boost :: posix_time :: time_duration timeDiff ( boost :: posix_time :: second_clock :: local_time () - GetLobbyThread (). GetStartTime ());
ostringstream statStream ;
statStream
<< "Server uptime................ " << timeDiff . hours () / 24 << " days " << timeDiff . hours () % 24 << " hours " << timeDiff . minutes () << " minutes " << timeDiff . seconds () << " seconds" ;
m_ircThread -> SendChatMessage ( statStream . str ());
}
{
ostringstream statStream ;
statStream
<< "Players currently on Server.. " << tmpStats . numberOfPlayersOnServer ;
m_ircThread -> SendChatMessage ( statStream . str ());
}
{
ostringstream statStream ;
statStream
<< "Games currently open......... " << tmpStats . numberOfGamesOpen ;
m_ircThread -> SendChatMessage ( statStream . str ());
}
{
ostringstream statStream ;
statStream
<< "Total players ever logged in. " << tmpStats . totalPlayersEverLoggedIn
<< " (Max at a time: " << tmpStats . maxPlayersLoggedIn << ")" ;
m_ircThread -> SendChatMessage ( statStream . str ());
}
{
ostringstream statStream ;
statStream
<< "Total games ever open........ " << tmpStats . totalGamesEverCreated
<< " (Max at a time: " << tmpStats . maxGamesOpen << ")" ;
m_ircThread -> SendChatMessage ( statStream . str ());
}
2007-11-28 23:31:34 +00:00
}
2009-04-10 21:04:08 +00:00
else if ( command == "chat" )
2007-11-22 22:16:52 +00:00
{
2009-04-10 21:04:08 +00:00
while ( msgStream . peek () == ' ' )
msgStream . get ();
string chat ( msgStream . str (). substr ( msgStream . tellg ()));
if ( ! chat . empty () && chat . size () < MAX_CHAT_TEXT_SIZE )
{
GetLobbyThread (). SendGlobalChat ( chat );
m_ircThread -> SendChatMessage ( nickName + ": Global chat message sent." );
}
else
m_ircThread -> SendChatMessage ( nickName + ": Invalid message." );
2008-04-02 21:41:39 +00:00
}
2009-04-10 21:04:08 +00:00
else if ( command == "msg" )
2008-04-02 21:41:39 +00:00
{
2009-04-10 21:04:08 +00:00
while ( msgStream . peek () == ' ' )
msgStream . get ();
string message ( msgStream . str (). substr ( msgStream . tellg ()));
if ( ! message . empty () && message . size () < MAX_CHAT_TEXT_SIZE )
{
GetLobbyThread (). SendGlobalMsgBox ( message );
m_ircThread -> SendChatMessage ( nickName + ": Global message box sent." );
}
else
m_ircThread -> SendChatMessage ( nickName + ": Invalid message." );
2008-12-26 16:47:14 +00:00
}
else
2009-04-10 21:04:08 +00:00
m_ircThread -> SendChatMessage ( nickName + ": Invalid command \" " + command + " \" ." );
2008-12-26 16:47:14 +00:00
}
2009-04-10 21:04:08 +00:00
} catch (...)
{
m_ircThread -> SendChatMessage ( nickName + ": Syntax error. Please check the command." );
2007-11-16 22:34:38 +00:00
}
}
}
void
ServerManager :: SignalIrcError ( int errorCode )
{
LOG_MSG ( "IRC error " << errorCode << "." );
}
void
ServerManager :: SignalIrcServerError ( int errorCode )
{
LOG_MSG ( "IRC server error " << errorCode << "." );
}
void
ServerManager :: RunAll ()
{
if ( m_ircThread )
m_ircThread -> Run ();
GetLobbyThread (). Run ();
}
2008-11-02 21:25:42 +00:00
void
ServerManager :: Process ()
{
if ( m_ircRestartTimer . elapsed (). total_seconds () > SERVER_RESTART_IRC_BOT_INTERVAL_SEC )
{
if ( m_ircThread )
{
m_ircThread -> SignalTermination ();
if ( m_ircThread -> Join ( NET_ADMIN_IRC_TERMINATE_TIMEOUT_MSEC ))
{
boost :: shared_ptr < IrcThread > tmpIrcThread ( new IrcThread ( * m_ircThread ));
tmpIrcThread -> Run ();
m_ircThread = tmpIrcThread ;
}
}
m_ircRestartTimer . reset ();
m_ircRestartTimer . start ();
}
}
2007-11-16 22:34:38 +00:00
void
ServerManager :: SignalTerminationAll ()
{
if ( m_ircThread )
m_ircThread -> SignalTermination ();
GetLobbyThread (). SignalTermination ();
}
bool
ServerManager :: JoinAll ( bool wait )
{
if ( m_ircThread )
m_ircThread -> Join ( wait ? NET_ADMIN_IRC_TERMINATE_TIMEOUT_MSEC : 0 );
2009-05-10 14:57:51 +00:00
return GetLobbyThread (). Join ( wait ? NET_LOBBY_THREAD_TERMINATE_TIMEOUT_MSEC : 0 );
2007-11-16 22:34:38 +00:00
}
ServerLobbyThread &
ServerManager :: GetLobbyThread ()
{
assert ( m_lobbyThread . get ());
return * m_lobbyThread ;
}