ServerMessageHandler.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 ////////////////////////////////////////////////////////////////////////////////
00020 
00021 #include <server/ServerMessageHandler.h>
00022 #include <server/ScorchedServer.h>
00023 #include <server/ScorchedServerUtil.h>
00024 #include <server/ServerCommon.h>
00025 #include <server/ServerBanned.h>
00026 #include <server/ServerKeepAliveHandler.h>
00027 #include <server/ServerChannelManager.h>
00028 #include <server/ServerState.h>
00029 #include <tank/TankDeadContainer.h>
00030 #include <tank/TankState.h>
00031 #include <tank/TankContainer.h>
00032 #include <tankai/TankAIStore.h>
00033 #include <coms/ComsRmPlayerMessage.h>
00034 #include <coms/ComsMessageSender.h>
00035 #include <net/NetInterface.h>
00036 #include <common/Logger.h>
00037 #include <common/OptionsScorched.h>
00038 #include <common/StatsLogger.h>
00039 
00040 ServerMessageHandler::DestinationInfo::DestinationInfo() :
00041         adminTries(0), admin(false)
00042 {
00043 }
00044 
00045 ServerMessageHandler::DestinationInfo *ServerMessageHandler::getDestinationInfo(unsigned int destinationId)
00046 {
00047         std::map<unsigned int, DestinationInfo>::iterator itor = 
00048                 destinationInfos_.find(destinationId);
00049         if (itor == destinationInfos_.end()) return 0;
00050         return &itor->second;
00051 }
00052 
00053 ServerMessageHandler *ServerMessageHandler::instance_ = 0;
00054 
00055 ServerMessageHandler *ServerMessageHandler::instance()
00056 {
00057         if (!instance_)
00058         {
00059                 instance_ = new ServerMessageHandler;
00060         }
00061         return instance_;
00062 }
00063 
00064 ServerMessageHandler::ServerMessageHandler()
00065 {
00066 }
00067 
00068 ServerMessageHandler::~ServerMessageHandler()
00069 {
00070 }
00071 
00072 void ServerMessageHandler::messageRecv(unsigned int destinationId)
00073 {
00074         ServerKeepAliveHandler::instance()->keepAlive(destinationId);
00075 }
00076 
00077 void ServerMessageHandler::messageSent(unsigned int destinationId)
00078 {
00079 }
00080 
00081 void ServerMessageHandler::clientConnected(NetMessage &message)
00082 {
00083         // Check if this destination has been banned
00084         if (message.getIpAddress() != 0 &&
00085                 ScorchedServerUtil::instance()->bannedPlayers.getBanned(message.getIpAddress()) == 
00086                 ServerBanned::Banned)
00087         {
00088                 Logger::log(S3D::formatStringBuffer("Banned client connected dest=\"%i\" ip=\"%s\"", 
00089                         message.getDestinationId(),
00090                         NetInterface::getIpName(message.getIpAddress())));
00091                 ScorchedServer::instance()->getNetInterface().
00092                         disconnectClient(message.getDestinationId());
00093                 return;
00094         }
00095 
00096         // Check if a player from this destination has connected already
00097         std::map<unsigned int, Tank *> &playingTanks = 
00098                 ScorchedServer::instance()->getTankContainer().getPlayingTanks();
00099         std::map<unsigned int, Tank *>::iterator playingItor;
00100         for (playingItor = playingTanks.begin();
00101                 playingItor != playingTanks.end();
00102                 playingItor++)
00103         {
00104                 Tank *current = (*playingItor).second;
00105                 if (current->getDestinationId() == message.getDestinationId())
00106                 {
00107                         Logger::log(S3D::formatStringBuffer("Duplicate connection from destination \"%i\"", 
00108                                 message.getDestinationId()));
00109                         ScorchedServer::instance()->getNetInterface().
00110                                 disconnectClient(message.getDestinationId());
00111                         return;
00112                 }
00113                 
00114                 if (!ScorchedServer::instance()->getOptionsGame().getAllowSameIP() &&
00115                         message.getIpAddress() != 0)
00116                 {
00117                         if (message.getIpAddress() == current->getIpAddress())
00118                         {
00119                                 Logger::log(S3D::formatStringBuffer("Duplicate ip connection from ip address \"%s\"", 
00120                                         NetInterface::getIpName(message.getIpAddress())));
00121                                 ScorchedServer::instance()->getNetInterface().
00122                                         disconnectClient(message.getDestinationId());
00123                                 return;
00124                         }
00125                 }
00126         }
00127 
00128         // Add to list of destinations
00129         destinationInfos_[message.getDestinationId()] = DestinationInfo();
00130 
00131         Logger::log(S3D::formatStringBuffer("Client connected dest=\"%i\" ip=\"%s\"", 
00132                 message.getDestinationId(),
00133                 NetInterface::getIpName(message.getIpAddress())));
00134 }
00135 
00136 void ServerMessageHandler::clientDisconnected(NetMessage &message)
00137 {
00138         const char *reason = "Unknown";
00139         if (message.getFlags() == NetMessage::UserDisconnect) reason = "User";
00140         else if (message.getFlags() == NetMessage::KickDisconnect) reason = "Kicked";
00141         else if (message.getFlags() == NetMessage::TimeoutDisconnect) reason = "Timeout";
00142 
00143         Logger::log(S3D::formatStringBuffer("Client disconnected dest=\"%i\" ip=\"%s\" reason=\"%s\"", 
00144                 message.getDestinationId(),
00145                 NetInterface::getIpName(message.getIpAddress()),
00146                 reason));
00147 
00148         // Build up a list of players at this destination
00149         std::list<unsigned int> removePlayers;
00150         unsigned int destinationId = message.getDestinationId();
00151         std::map<unsigned int, Tank *>::iterator itor;
00152         std::map<unsigned int, Tank *> &tanks = 
00153                 ScorchedServer::instance()->getTankContainer().getPlayingTanks();
00154         for (itor = tanks.begin();
00155                 itor != tanks.end();
00156                 itor++)
00157         {
00158                 Tank *tank = (*itor).second;
00159                 if (tank->getDestinationId() == destinationId)
00160                 {
00161                         removePlayers.push_back(tank->getPlayerId());
00162                 }
00163         }
00164 
00165         // Remove all players for this destination
00166         std::list<unsigned int>::iterator remItor;
00167         for (remItor = removePlayers.begin();
00168                  remItor != removePlayers.end();
00169                  remItor++)
00170         {
00171                 unsigned int playerId = *remItor;
00172                 destroyPlayer(playerId, reason);
00173         }
00174 
00175         // Inform the channel manager
00176         ServerChannelManager::instance()->destinationDisconnected(message.getDestinationId());
00177 
00178         // Remove from list of destinations
00179         destinationInfos_.erase(message.getDestinationId());
00180 }
00181 
00182 void ServerMessageHandler::destroyPlayer(unsigned int tankId, const char *reason)
00183 {
00184         // Try to remove this player
00185         Tank *tank = ScorchedServer::instance()->getTankContainer().getTankById(tankId);
00186         if (!tank)
00187         {
00188                 Logger::log(S3D::formatStringBuffer("Unknown player disconnected id=\"%i\" (%s)", 
00189                         tankId, reason));
00190                 return;
00191         }
00192 
00193         // Log disconnect
00194         Logger::log( 
00195                 S3D::formatStringBuffer("Player disconnected dest=\"%i\" id=\"%i\" name=\"%s\" reason=\"%s\"", 
00196                 tank->getDestinationId(),
00197                 tankId, 
00198                 tank->getCStrName().c_str(),
00199                 reason));
00200         ServerChannelManager::instance()->sendText(
00201                 ChannelText("info", 
00202                         "PLAYER_DISCONNECTED", 
00203                         "Player disconnected \"{0}\" ({1})",
00204                         tank->getTargetName(), reason),
00205                 true);
00206 
00207         // Check if we can remove player
00208         if (tank->getState().getState() == TankState::sNormal &&
00209                 ScorchedServer::instance()->getGameState().getState() == ServerState::ServerStateShot)
00210         {
00211                 // Store a residual copy, that will be over written when the player is actual deleted
00212                 ScorchedServer::instance()->getTankDeadContainer().addTank(tank);
00213 
00214                 // We are in a state where we cannot remove the player straight away
00215                 tank->getState().setDestroy(true);
00216 
00217                 // Make this player a computer controlled player
00218                 if (tank->getDestinationId() != 0)
00219                 {
00220                         TankAI *ai = ScorchedServer::instance()->getTankAIs().getAIByName("Random");
00221                         tank->setTankAI(ai->createCopy(tank));
00222                         tank->setDestinationId(0);
00223                         tank->setKeepAlive(0);
00224                 }
00225         }
00226         else
00227         {
00228                 // Destroy the player straight away
00229                 actualDestroyPlayer(tankId);
00230         }
00231 }
00232 
00233 void ServerMessageHandler::destroyTaggedPlayers()
00234 {
00235         std::map<unsigned int, Tank *> tanks = 
00236                 ScorchedServer::instance()->getTankContainer().getAllTanks();
00237         std::map<unsigned int, Tank *>::iterator itor;
00238         for (itor = tanks.begin();
00239                 itor != tanks.end();
00240                 itor++)
00241         {
00242                 Tank *tank = itor->second;
00243                 if (tank->getState().getDestroy())
00244                 {
00245                         actualDestroyPlayer(tank->getPlayerId());
00246                 }
00247         }
00248 }
00249 
00250 void ServerMessageHandler::actualDestroyPlayer(unsigned int tankId)
00251 {
00252         // Try to remove this player
00253         Tank *tank = ScorchedServer::instance()->getTankContainer().removeTank(tankId);
00254         if (!tank) return;
00255 
00256         StatsLogger::instance()->tankDisconnected(tank);
00257 
00258         // Tell all the clients to remove this player
00259         ComsRmPlayerMessage rmPlayerMessage(
00260                 tankId);
00261         ComsMessageSender::sendToAllConnectedClients(rmPlayerMessage);
00262 
00263         // Tidy player
00264         ScorchedServer::instance()->getTankDeadContainer().addTank(tank);
00265         delete tank;
00266 }
00267 
00268 void ServerMessageHandler::clientError(NetMessage &message,
00269                 const char *errorString)
00270 {
00271         Logger::log(S3D::formatStringBuffer("Client \"%i\", ***Server Error*** \"%s\"", 
00272                 message.getDestinationId(),
00273                 errorString));
00274         ServerCommon::kickDestination(message.getDestinationId());
00275 }

Generated on Mon Feb 16 15:14:53 2009 for Scorched3D by  doxygen 1.5.3