1 ////////////////////////////////////////////////////////////////////////////////
2 // Scorched3D (c) 2000-2011
3 //
4 // This file is part of Scorched3D.
5 //
6 // Scorched3D is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // Scorched3D is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License along
17 // with this program; if not, write to the Free Software Foundation, Inc.,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 ////////////////////////////////////////////////////////////////////////////////
20
21 #include <server/ServerMessageHandler.h>
22 #include <server/ScorchedServer.h>
23 #include <server/ServerCommon.h>
24 #include <server/ServerBanned.h>
25 #include <server/ServerChannelManager.h>
26 #include <server/ServerDestinations.h>
27 #include <server/ServerSimulator.h>
28 #include <server/ServerState.h>
29 #include <tank/TankDeadContainer.h>
30 #include <target/TargetContainer.h>
31 #include <tank/TankState.h>
32 #include <tankai/TankAINone.h>
33 #include <simactions/TankRemoveSimAction.h>
34 #include <coms/ComsMessageSender.h>
35 #include <net/NetInterface.h>
36 #include <common/Logger.h>
37 #include <common/OptionsScorched.h>
38 #include <common/StatsLogger.h>
39
ServerMessageHandler()40 ServerMessageHandler::ServerMessageHandler()
41 {
42 }
43
~ServerMessageHandler()44 ServerMessageHandler::~ServerMessageHandler()
45 {
46 }
47
messageRecv(unsigned int destinationId)48 void ServerMessageHandler::messageRecv(unsigned int destinationId)
49 {
50 }
51
messageSent(unsigned int destinationId)52 void ServerMessageHandler::messageSent(unsigned int destinationId)
53 {
54 }
55
clientConnected(NetMessage & message)56 void ServerMessageHandler::clientConnected(NetMessage &message)
57 {
58 // Check if this destination has been banned
59 if (message.getIpAddress() != 0 &&
60 ScorchedServer::instance()->getBannedPlayers().getBanned(message.getIpAddress()) ==
61 ServerBanned::Banned)
62 {
63 Logger::log(S3D::formatStringBuffer("Banned client connected dest=\"%i\" ip=\"%s\"",
64 message.getDestinationId(),
65 NetInterface::getIpName(message.getIpAddress())));
66 ScorchedServer::instance()->getNetInterface().
67 disconnectClient(message.getDestinationId());
68 return;
69 }
70
71 // Check if a player from this destination has connected already
72 std::map<unsigned int, ServerDestination *> &destinations =
73 ScorchedServer::instance()->getServerDestinations().getServerDestinations();
74 std::map<unsigned int, ServerDestination *>::iterator destItor;
75 for (destItor = destinations.begin();
76 destItor != destinations.end();
77 ++destItor)
78 {
79 unsigned int serverDestinationId = destItor->first;
80 ServerDestination *serverDestination = destItor->second;
81 if (serverDestinationId == message.getDestinationId())
82 {
83 Logger::log(S3D::formatStringBuffer("Duplicate connection from destination \"%i\"",
84 message.getDestinationId()));
85 ScorchedServer::instance()->getNetInterface().
86 disconnectClient(message.getDestinationId());
87 return;
88 }
89
90 if (!ScorchedServer::instance()->getOptionsGame().getAllowSameIP() &&
91 message.getIpAddress() != 0)
92 {
93 if (message.getIpAddress() == serverDestination->getIpAddress())
94 {
95 Logger::log(S3D::formatStringBuffer("Duplicate ip connection from ip address \"%s\"",
96 NetInterface::getIpName(message.getIpAddress())));
97 ScorchedServer::instance()->getNetInterface().
98 disconnectClient(message.getDestinationId());
99 return;
100 }
101 }
102 }
103
104 // Add to list of destinations
105 ScorchedServer::instance()->getServerDestinations().addDestination(
106 message.getDestinationId(), message.getIpAddress());
107
108 Logger::log(S3D::formatStringBuffer("Client connected dest=\"%i\" ip=\"%s\"",
109 message.getDestinationId(),
110 NetInterface::getIpName(message.getIpAddress())));
111 }
112
clientDisconnected(NetMessage & message)113 void ServerMessageHandler::clientDisconnected(NetMessage &message)
114 {
115 const char *reason = "Unknown";
116 if (message.getFlags() == NetMessage::UserDisconnect) reason = "User";
117 else if (message.getFlags() == NetMessage::KickDisconnect) reason = "Kicked";
118 else if (message.getFlags() == NetMessage::TimeoutDisconnect) reason = "Timeout";
119
120 Logger::log(S3D::formatStringBuffer("Client disconnected dest=\"%i\" ip=\"%s\" reason=\"%s\"",
121 message.getDestinationId(),
122 NetInterface::getIpName(message.getIpAddress()),
123 reason));
124
125 // Build up a list of players at this destination
126 std::list<unsigned int> removePlayers;
127 unsigned int destinationId = message.getDestinationId();
128 std::map<unsigned int, Tank *>::iterator itor;
129 std::map<unsigned int, Tank *> &tanks =
130 ScorchedServer::instance()->getTargetContainer().getTanks();
131 for (itor = tanks.begin();
132 itor != tanks.end();
133 ++itor)
134 {
135 Tank *tank = (*itor).second;
136 if (tank->getDestinationId() == destinationId)
137 {
138 removePlayers.push_back(tank->getPlayerId());
139 }
140 }
141
142 // Remove all players for this destination
143 std::list<unsigned int>::iterator remItor;
144 for (remItor = removePlayers.begin();
145 remItor != removePlayers.end();
146 ++remItor)
147 {
148 unsigned int playerId = *remItor;
149 destroyPlayer(playerId, reason);
150 }
151
152 // Inform the channel manager
153 ScorchedServer::instance()->getServerChannelManager().destinationDisconnected(message.getDestinationId());
154
155 // Remove from list of destinations
156 ScorchedServer::instance()->getServerDestinations().removeDestination(
157 message.getDestinationId());
158 }
159
destroyPlayer(unsigned int tankId,const char * reason)160 void ServerMessageHandler::destroyPlayer(unsigned int tankId, const char *reason)
161 {
162 // Try to remove this player
163 Tank *tank = ScorchedServer::instance()->getTargetContainer().getTankById(tankId);
164 if (!tank)
165 {
166 Logger::log(S3D::formatStringBuffer("Unknown player disconnected id=\"%i\" (%s)",
167 tankId, reason));
168 return;
169 }
170
171 // Log disconnect
172 Logger::log(
173 S3D::formatStringBuffer("Player disconnected dest=\"%i\" ip=\"%s\" id=\"%i\" name=\"%s\" reason=\"%s\"",
174 tank->getDestinationId(),
175 NetInterface::getIpName(tank->getIpAddress()),
176 tankId,
177 tank->getCStrName().c_str(),
178 reason));
179 ScorchedServer::instance()->getServerChannelManager().sendText(
180 ChannelText("info",
181 "PLAYER_DISCONNECTED",
182 "Player disconnected [p:{0}] ({1})",
183 tank->getTargetName(), reason),
184 true);
185
186 // Add tank to tank dead container to remember its stats
187 if (ScorchedServer::instance()->getOptionsGame().getResidualPlayers())
188 {
189 if (tank->getState().getTankPlaying() &&
190 tank->getDestinationId() != 0)
191 {
192 if (tank->getUniqueId()[0])
193 {
194 ScorchedServer::instance()->getTankDeadContainer().addDeadTank(tank, tank->getUniqueId());
195 }
196 else if (tank->getSUI()[0])
197 {
198 ScorchedServer::instance()->getTankDeadContainer().addDeadTank(tank, tank->getSUI());
199 }
200 }
201 }
202
203 // The time to actualy remove the tank after
204 fixed removalTime = 0;
205
206 // Check if we can remove player
207 if (tank->getState().getState() == TankState::sNormal &&
208 ScorchedServer::instance()->getServerState().getState() ==
209 ServerState::ServerPlayingState &&
210 tank->getDestinationId() != 0)
211 {
212 // Actualy remove the tank after a few seconds have passed
213 removalTime = ScorchedServer::instance()->getOptionsGame().getRemoveTime();
214 }
215
216 // Log the removal
217 StatsLogger::instance()->tankDisconnected(tank);
218
219 // Actualy remove the tank from the client and server
220 TankRemoveSimAction *removeSimAction =
221 new TankRemoveSimAction(tankId, removalTime);
222 ScorchedServer::instance()->getServerSimulator().
223 addSimulatorAction(removeSimAction);
224 }
225
clientError(NetMessage & message,const std::string & errorString)226 void ServerMessageHandler::clientError(NetMessage &message,
227 const std::string &errorString)
228 {
229 Logger::log(S3D::formatStringBuffer("Client \"%i\", ***Server Error*** \"%s\"",
230 message.getDestinationId(),
231 errorString.c_str()));
232 ServerCommon::kickDestination(message.getDestinationId(),
233 "Coms message error");
234 }
235