00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <server/ServerConnectAuthHandler.h>
00022 #include <server/ServerConnectHandler.h>
00023 #include <server/ServerChannelManager.h>
00024 #include <server/ServerState.h>
00025 #include <server/ServerBanned.h>
00026 #include <server/ScorchedServer.h>
00027 #include <server/ScorchedServerUtil.h>
00028 #include <server/TurnController.h>
00029 #include <server/ServerCommon.h>
00030 #include <tank/TankColorGenerator.h>
00031 #include <tank/TankContainer.h>
00032 #include <tank/TankModelContainer.h>
00033 #include <tank/TankAvatar.h>
00034 #include <tank/TankState.h>
00035 #include <tank/TankScore.h>
00036 #include <tankai/TankAIAdder.h>
00037 #include <tankai/TankAIStrings.h>
00038 #include <common/Defines.h>
00039 #include <common/FileLines.h>
00040 #include <common/OptionsScorched.h>
00041 #include <common/StatsLogger.h>
00042 #include <common/Logger.h>
00043 #include <net/NetInterface.h>
00044 #include <coms/ComsPlayerStateMessage.h>
00045 #include <coms/ComsAddPlayerMessage.h>
00046 #include <coms/ComsConnectAcceptMessage.h>
00047 #include <coms/ComsConnectMessage.h>
00048 #include <coms/ComsMessageSender.h>
00049
00050 ServerConnectAuthHandler *ServerConnectAuthHandler::instance_ = 0;
00051
00052 ServerConnectAuthHandler *ServerConnectAuthHandler::instance()
00053 {
00054 if (!instance_)
00055 {
00056 instance_ = new ServerConnectAuthHandler;
00057 }
00058 return instance_;
00059 }
00060
00061 ServerConnectAuthHandler::ServerConnectAuthHandler()
00062 {
00063 ScorchedServer::instance()->getComsMessageHandler().addHandler(
00064 "ComsConnectAuthMessage",
00065 this);
00066 }
00067
00068 ServerConnectAuthHandler::~ServerConnectAuthHandler()
00069 {
00070 }
00071
00072 bool ServerConnectAuthHandler::processMessage(
00073 NetMessage &netMessage,
00074 const char *messageType, NetBufferReader &reader)
00075 {
00076 unsigned int destinationId = netMessage.getDestinationId();
00077 unsigned int ipAddress = netMessage.getIpAddress();
00078
00079
00080 if (!ServerConnectHandler::instance()->checkStandardParams(destinationId, ipAddress)) return true;
00081
00082
00083 ComsConnectAuthMessage message;
00084 if (!message.readMessage(reader))
00085 {
00086 ServerCommon::serverLog("Invalid auth message format");
00087 ServerCommon::kickDestination(destinationId);
00088 return true;
00089 }
00090
00091
00092 if (message.getNoPlayers() >
00093 (unsigned int)
00094 (ScorchedServer::instance()->getOptionsGame().getNoMaxPlayers() -
00095 ScorchedServer::instance()->getTankContainer().getNoOfTanks()))
00096 {
00097 std::string kickMessage =
00098 S3D::formatStringBuffer(
00099 "--------------------------------------------------\n"
00100 "This server is full, you cannot join!\n"
00101 "--------------------------------------------------");
00102 ServerCommon::serverLog("Server full, kicking");
00103 ServerCommon::kickDestination(destinationId, kickMessage);
00104 return true;
00105 }
00106
00107
00108
00109 ServerAuthHandler *authHandler =
00110 ScorchedServerUtil::instance()->getAuthHandler();
00111 if (authHandler)
00112 {
00113 std::string resultMessage;
00114 if (!authHandler->authenticateUser(message, resultMessage))
00115 {
00116 std::string kickMessage =
00117 S3D::formatStringBuffer(
00118 "--------------------------------------------------\n"
00119 "%s"
00120 "Connection failed.\n"
00121 "--------------------------------------------------",
00122 resultMessage.c_str());
00123 Logger::log(S3D::formatStringBuffer("User failed authentication \"%s\"",
00124 message.getUserName()));
00125
00126 ServerCommon::kickDestination(destinationId, kickMessage);
00127 return true;
00128 }
00129 }
00130
00131 std::string uniqueId = message.getUniqueId();
00132 if (!uniqueId.c_str()[0])
00133 {
00134
00135
00136
00137
00138
00139
00140 uniqueId = StatsLogger::instance()->allocateId();
00141 }
00142 std::string SUid = message.getSUI();
00143
00144
00145 unsigned int compatVer = message.getCompatabilityVer();
00146
00147
00148
00149
00150 ServerBanned::BannedType type =
00151 ScorchedServerUtil::instance()->bannedPlayers.getBanned(uniqueId.c_str(), SUid.c_str());
00152 if (type == ServerBanned::Banned)
00153 {
00154 Logger::log(S3D::formatStringBuffer("Banned uniqueid/suid connection from destination \"%i\"",
00155 destinationId));
00156 ServerCommon::kickDestination(destinationId);
00157 return true;
00158 }
00159
00160
00161 if (!ScorchedServer::instance()->getOptionsGame().getAllowSameUniqueId())
00162 {
00163 std::map<unsigned int, Tank *> &playingTanks =
00164 ScorchedServer::instance()->getTankContainer().getPlayingTanks();
00165 std::map<unsigned int, Tank *>::iterator playingItor;
00166 for (playingItor = playingTanks.begin();
00167 playingItor != playingTanks.end();
00168 playingItor++)
00169 {
00170 Tank *current = (*playingItor).second;
00171
00172 if (uniqueId.c_str()[0])
00173 {
00174 if (0 == strcmp(current->getUniqueId(), uniqueId.c_str()))
00175 {
00176 Logger::log(S3D::formatStringBuffer("Duplicate uniqueid connection from destination \"%i\"",
00177 destinationId));
00178 ServerCommon::kickDestination(destinationId);
00179 return true;
00180 }
00181 }
00182 if (SUid.c_str()[0])
00183 {
00184 if (0 == strcmp(current->getSUI(), SUid.c_str()))
00185 {
00186 Logger::log(S3D::formatStringBuffer("Duplicate SUI connection from destination \"%i\"",
00187 destinationId));
00188 ServerCommon::kickDestination(destinationId);
00189 return true;
00190 }
00191 }
00192 }
00193 }
00194
00195
00196 ComsConnectAcceptMessage acceptMessage(
00197 destinationId,
00198 ScorchedServer::instance()->getOptionsGame().getServerName(),
00199 ScorchedServer::instance()->getOptionsGame().getPublishAddress(),
00200 uniqueId.c_str());
00201
00202 #ifdef S3D_SERVER
00203 {
00204 std::string fileName =
00205 S3D::getSettingsFile(S3D::formatStringBuffer("icon-%i.png",
00206 ScorchedServer::instance()->getOptionsGame().getPortNo()));
00207 FILE *in = fopen(fileName.c_str(), "rb");
00208 if (in)
00209 {
00210 acceptMessage.getServerPng().reset();
00211 unsigned char readBuf[512];
00212 while (unsigned int size = fread(readBuf, sizeof(unsigned char), 512, in))
00213 {
00214 acceptMessage.getServerPng().addDataToBuffer(readBuf, size);
00215 }
00216 fclose(in);
00217 }
00218 }
00219 #endif
00220 if (!ComsMessageSender::sendToSingleClient(acceptMessage, destinationId))
00221 {
00222 Logger::log(S3D::formatStringBuffer(
00223 "Failed to send accept to client \"%i\"",
00224 destinationId));
00225 ServerCommon::kickDestination(destinationId);
00226 return true;
00227 }
00228
00229
00230 std::map<unsigned int, Tank *>::iterator itor;
00231 std::map<unsigned int, Tank *> &tankList =
00232 ScorchedServer::instance()->getTankContainer().getPlayingTanks();
00233 for (itor = tankList.begin();
00234 itor != tankList.end();
00235 itor++)
00236 {
00237 Tank *tank = (*itor).second;
00238
00239 ComsAddPlayerMessage oldPlayerMessage(
00240 tank->getPlayerId(),
00241 tank->getTargetName(),
00242 tank->getColor(),
00243 tank->getModelContainer().getTankModelName(),
00244 tank->getModelContainer().getTankTypeName(),
00245 tank->getDestinationId(),
00246 tank->getTeam(),
00247 "");
00248 oldPlayerMessage.setPlayerIconName(tank->getAvatar().getName());
00249 oldPlayerMessage.getPlayerIcon().addDataToBuffer(
00250 tank->getAvatar().getFile().getBuffer(),
00251 tank->getAvatar().getFile().getBufferUsed());
00252 ComsMessageSender::sendToSingleClient(oldPlayerMessage, destinationId);
00253 }
00254
00255
00256 for (unsigned int i=0; i<message.getNoPlayers(); i++)
00257 {
00258 addNextTank(destinationId,
00259 ipAddress,
00260 uniqueId.c_str(),
00261 SUid.c_str(),
00262 message.getHostDesc(),
00263 false);
00264 }
00265
00266
00267
00268
00269
00270 #ifndef S3D_SERVER
00271 {
00272 addNextTank(destinationId,
00273 ipAddress,
00274 uniqueId.c_str(),
00275 SUid.c_str(),
00276 message.getHostDesc(),
00277 true);
00278 }
00279 #endif
00280
00281
00282 ComsPlayerStateMessage comsPlayerStateMessage(false, false);
00283 if (!ComsMessageSender::sendToSingleClient(
00284 comsPlayerStateMessage, destinationId)) return false;
00285
00286 return true;
00287 }
00288
00289 void ServerConnectAuthHandler::addNextTank(unsigned int destinationId,
00290 unsigned int ipAddress,
00291 const char *sentUniqueId,
00292 const char *sentSUI,
00293 const char *sentHostDesc,
00294 bool extraSpectator)
00295 {
00296
00297 Vector color;
00298 unsigned int tankId = 0;
00299 LangString playerName;
00300
00301 if (extraSpectator)
00302 {
00303 tankId = TargetID::SPEC_TANK_ID;
00304 playerName = LANG_STRING("Spectator");
00305 color = Vector(0.7f, 0.7f, 0.7f);
00306 }
00307 else
00308 {
00309 playerName = LANG_STRING(TankAIStrings::instance()->getPlayerName());
00310 color = TankColorGenerator::instance()->getNextColor(
00311 ScorchedServer::instance()->getTankContainer().getPlayingTanks());
00312 tankId = TankAIAdder::getNextTankId(
00313 sentUniqueId,
00314 ScorchedServer::instance()->getContext());
00315 }
00316
00317
00318 for (char *h=(char *)sentHostDesc; *h; h++) if (*h == '\"') *h=' ';
00319
00320
00321 Tank *tank = new Tank(
00322 ScorchedServer::instance()->getContext(),
00323 tankId,
00324 destinationId,
00325 playerName,
00326 color,
00327 "Random",
00328 "none");
00329 tank->setUniqueId(sentUniqueId);
00330 tank->setSUI(sentSUI);
00331 tank->setIpAddress(ipAddress);
00332 tank->setHostDesc(sentHostDesc);
00333 tank->getState().setSpectator(true);
00334
00335
00336 std::list<std::string> aliases =
00337 StatsLogger::instance()->getAliases(tank->getUniqueId());
00338 if (!aliases.empty())
00339 {
00340 LangString alias = LANG_STRING(aliases.front());
00341 tank->setName(alias);
00342 }
00343
00344
00345 ScorchedServer::instance()->getTankContainer().addTank(tank);
00346
00347
00348 ComsAddPlayerMessage addPlayerMessage(
00349 tank->getPlayerId(),
00350 tank->getTargetName(),
00351 tank->getColor(),
00352 tank->getModelContainer().getTankModelName(),
00353 tank->getModelContainer().getTankTypeName(),
00354 tank->getDestinationId(),
00355 tank->getTeam(),
00356 "");
00357 ComsMessageSender::sendToAllConnectedClients(addPlayerMessage);
00358
00359
00360 #ifdef S3D_SERVER
00361 {
00362
00363 Logger::log(S3D::formatStringBuffer("Player connected dest=\"%i\" id=\"%i\" name=\"%s\" unique=[%s] SUI=[%s]",
00364 tank->getDestinationId(),
00365 tank->getPlayerId(),
00366 tank->getCStrName().c_str(),
00367 tank->getUniqueId(),
00368 tank->getSUI()));
00369
00370 ServerChannelManager::instance()->sendText(
00371 ChannelText("info",
00372 "PLAYER_CONNECTED",
00373 "Player connected \"{0}\"",
00374 tank->getTargetName()),
00375 true);
00376 }
00377 #endif
00378
00379
00380 StatsLogger::instance()->tankConnected(tank);
00381
00382
00383 if (ipAddress != 0)
00384 {
00385 ServerBanned::BannedType type =
00386 ScorchedServerUtil::instance()->bannedPlayers.getBanned(tank->getUniqueId(), tank->getSUI());
00387 if (type == ServerBanned::Muted)
00388 {
00389 tank->getState().setMuted(true);
00390 ServerChannelManager::instance()->sendText(
00391 ChannelText("admin",
00392 "PLAYER_ADMIN_MUTED",
00393 "Player admin muted \"{0}\"",
00394 tank->getTargetName()),
00395 true);
00396 }
00397 else if (type == ServerBanned::Flagged)
00398 {
00399 ServerChannelManager::instance()->sendText(
00400 ChannelText("admin",
00401 "PLAYER_ADMIN_FLAGGED",
00402 "Player admin flagged \"{0}\"",
00403 tank->getTargetName()),
00404 true);
00405 }
00406 }
00407 }