00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <server/ServerChannelManager.h>
00022 #include <server/ScorchedServer.h>
00023 #include <server/ScorchedServerUtil.h>
00024 #include <server/ServerCommon.h>
00025 #include <lua/LUAScriptHook.h>
00026 #include <coms/ComsMessageSender.h>
00027 #include <coms/ComsChannelMessage.h>
00028 #include <coms/ComsChannelTextMessage.h>
00029 #include <common/OptionsScorched.h>
00030 #include <tank/TankContainer.h>
00031 #include <tank/TankState.h>
00032 #include <lang/LangResource.h>
00033
00034 ServerChannelManager::ChannelEntry::ChannelEntry(
00035 ChannelDefinition def,
00036 ServerChannelFilter *filter,
00037 ServerChannelAuth *auth) :
00038 channelDef_(def),
00039 filter_(filter),
00040 auth_(auth)
00041 {
00042 ScorchedServer::instance()->getLUAScriptHook().addHookProvider("server_channeltext");
00043 }
00044
00045 ServerChannelManager::ChannelEntry::~ChannelEntry()
00046 {
00047 }
00048
00049 ServerChannelManager::DestinationLocalEntry::DestinationLocalEntry(
00050 unsigned int localId) :
00051 localId_(localId)
00052 {
00053 }
00054
00055 ServerChannelManager::DestinationEntry::DestinationEntry(
00056 unsigned int destinationId) :
00057 destinationId_(destinationId),
00058 messageCount_(0), muteTime_(0)
00059 {
00060 }
00061
00062 bool ServerChannelManager::DestinationEntry::hasChannel(const std::string &channel)
00063 {
00064 return (channels_.find(channel) != channels_.end());
00065 }
00066
00067 void ServerChannelManager::DestinationEntry::addChannel(const std::string &channel, unsigned int localId, bool current)
00068 {
00069 if (!hasLocalId(localId)) return;
00070
00071 if (current)
00072 {
00073 localEntries_[localId].getChannels().insert(channel);
00074 localEntries_[localId].getAvailableChannels().erase(channel);
00075 }
00076 else
00077 {
00078 localEntries_[localId].getChannels().erase(channel);
00079 localEntries_[localId].getAvailableChannels().insert(channel);
00080 }
00081
00082 updateChannels();
00083 }
00084
00085 void ServerChannelManager::DestinationEntry::removeChannel(const std::string &channel, unsigned int localId)
00086 {
00087 if (!hasLocalId(localId)) return;
00088 localEntries_[localId].getChannels().erase(channel);
00089 localEntries_[localId].getAvailableChannels().erase(channel);
00090 updateChannels();
00091 }
00092
00093 void ServerChannelManager::DestinationEntry::getLocalIds(const std::string &channel, std::list<unsigned int> &ids)
00094 {
00095 std::map<unsigned int, DestinationLocalEntry>::iterator itor;
00096 for (itor = localEntries_.begin();
00097 itor != localEntries_.end();
00098 itor++)
00099 {
00100 DestinationLocalEntry &entry = (*itor).second;
00101 if (entry.getChannels().find(channel) != entry.getChannels().end())
00102 {
00103 ids.push_back((*itor).first);
00104 }
00105 }
00106 }
00107
00108 bool ServerChannelManager::DestinationEntry::hasLocalId(unsigned int localId)
00109 {
00110 return (localEntries_.find(localId) != localEntries_.end());
00111 }
00112
00113 void ServerChannelManager::DestinationEntry::addLocalId(unsigned int localId)
00114 {
00115 if (hasLocalId(localId)) return;
00116 localEntries_[localId] = DestinationLocalEntry(localId);
00117 updateChannels();
00118 }
00119
00120 void ServerChannelManager::DestinationEntry::removeLocalId(unsigned int localId)
00121 {
00122 if (!hasLocalId(localId)) return;
00123 localEntries_.erase(localId);
00124 updateChannels();
00125 }
00126
00127 void ServerChannelManager::DestinationEntry::updateChannels()
00128 {
00129 channels_.clear();
00130 std::map<unsigned int, DestinationLocalEntry>::iterator itor;
00131 for (itor = localEntries_.begin();
00132 itor != localEntries_.end();
00133 itor++)
00134 {
00135 DestinationLocalEntry &entry = (*itor).second;
00136 channels_.insert(entry.getChannels().begin(), entry.getChannels().end());
00137 }
00138 }
00139
00140 ServerChannelManager *ServerChannelManager::instance_ = 0;
00141
00142 ServerChannelManager *ServerChannelManager::instance()
00143 {
00144 if (!instance_)
00145 {
00146 instance_ = new ServerChannelManager;
00147 }
00148 return instance_;
00149 }
00150
00151 ServerChannelManager::ServerChannelManager() :
00152 totalTime_(0.0f), lastMessageId_(0)
00153 {
00154
00155 ScorchedServer::instance()->getComsMessageHandler().addHandler(
00156 "ComsChannelMessage",
00157 this);
00158 ScorchedServer::instance()->getComsMessageHandler().addHandler(
00159 "ComsChannelTextMessage",
00160 this);
00161
00162
00163 channelEntries_.push_back(new ChannelEntry(
00164 ChannelDefinition("announce", ChannelDefinition::eReadOnlyChannel)));
00165 channelEntries_.push_back(new ChannelEntry(
00166 ChannelDefinition("info", ChannelDefinition::eReadOnlyChannel)));
00167 channelEntries_.push_back(new ChannelEntry(
00168 ChannelDefinition("general")));
00169 channelEntries_.push_back(new ChannelEntry(
00170 ChannelDefinition("team"),
00171 new ServerChannelFilterTeams()));
00172 channelEntries_.push_back(new ChannelEntry(
00173 ChannelDefinition("spam")));
00174 channelEntries_.push_back(new ChannelEntry(
00175 ChannelDefinition("combat", ChannelDefinition::eReadOnlyChannel)));
00176 channelEntries_.push_back(new ChannelEntry(
00177 ChannelDefinition("banner", ChannelDefinition::eReadOnlyChannel)));
00178 channelEntries_.push_back(new ChannelEntry(
00179 ChannelDefinition("admin"),
00180 0,
00181 new ServerChannelAuthAdmin()));
00182 channelEntries_.push_back(new ChannelEntry(
00183 ChannelDefinition("whisper", ChannelDefinition::eWhisperChannel)));
00184 }
00185
00186 ServerChannelManager::~ServerChannelManager()
00187 {
00188 }
00189
00190 void ServerChannelManager::simulate(float frameTime)
00191 {
00192 const int MuteTime = 60;
00193 const int MuteThreshold = 10;
00194
00195 totalTime_ += frameTime;
00196 if (totalTime_ > 10.0f)
00197 {
00198 totalTime_ = 0.0f;
00199
00200
00201
00202
00203 std::map<unsigned int, DestinationEntry *>::iterator itor;
00204 for (itor = destinationEntries_.begin();
00205 itor != destinationEntries_.end();
00206 itor++)
00207 {
00208 DestinationEntry *entry = itor->second;
00209 if (entry->getMessageCount() > MuteThreshold)
00210 {
00211 time_t t = time(0);
00212 entry->setMuteTime(t);
00213
00214 ChannelText text("info",
00215 LANG_RESOURCE_1("CHANNEL_AUTO_MUTED",
00216 "You have been muted for {0} seconds for spamming!",
00217 MuteTime));
00218 sendText(text, entry->getDestinationId(), true);
00219 }
00220 else if (entry->getMuteTime())
00221 {
00222 time_t t = time(0);
00223 if (t - entry->getMuteTime() > MuteTime)
00224 {
00225 entry->setMuteTime(0);
00226
00227 ChannelText text("info",
00228 LANG_RESOURCE("CHANNEL_AUTO_UNMUTED",
00229 "You have been unmuted."));
00230 sendText(text, entry->getDestinationId(), true);
00231 }
00232 }
00233 entry->setMessageCount(0);
00234 }
00235 }
00236 }
00237
00238 void ServerChannelManager::destinationDisconnected(unsigned int destinationId)
00239 {
00240 DestinationEntry *entry = getDestinationEntryById(destinationId);
00241 if (!entry) return;
00242
00243 destinationEntries_.erase(destinationId);
00244 delete entry;
00245 }
00246
00247 ServerChannelManager::ChannelEntry *ServerChannelManager::getChannelEntryByName(const std::string &name)
00248 {
00249 std::list<ChannelEntry *>::iterator itor;
00250 for (itor = channelEntries_.begin();
00251 itor != channelEntries_.end();
00252 itor++)
00253 {
00254 ChannelEntry *entry = *itor;
00255 if (name == entry->getName()) return entry;
00256 }
00257 return 0;
00258 }
00259
00260 ServerChannelManager::DestinationEntry *ServerChannelManager::getDestinationEntryById(
00261 unsigned int destinationId)
00262 {
00263 std::map<unsigned int, DestinationEntry *>::iterator findItor =
00264 destinationEntries_.find(destinationId);
00265 if (findItor == destinationEntries_.end()) return 0;
00266
00267 return (*findItor).second;
00268 }
00269
00270 std::list<std::string> ServerChannelManager::getAllChannels()
00271 {
00272 std::list<std::string> result;
00273 std::list<ChannelEntry *>::iterator itor;
00274 for (itor = channelEntries_.begin();
00275 itor != channelEntries_.end();
00276 itor++)
00277 {
00278 ChannelEntry *channelEntry = (*itor);
00279 result.push_back(channelEntry->getName());
00280 }
00281 return result;
00282 }
00283
00284 void ServerChannelManager::registerClient(unsigned int destinationId, unsigned int localId,
00285 std::list<ChannelDefinition> &startChannels)
00286 {
00287
00288 DestinationEntry *destEntry = getDestinationEntryById(destinationId);
00289 if (destEntry && destEntry->hasLocalId(localId)) return;
00290
00291
00292 if (!destEntry)
00293 {
00294 destEntry = new DestinationEntry(destinationId);
00295 destinationEntries_[destinationId] = destEntry;
00296 }
00297
00298 if (!destEntry->hasLocalId(localId))
00299 {
00300 destEntry->addLocalId(localId);
00301 }
00302
00303
00304 joinClient(destinationId, localId, startChannels);
00305 }
00306
00307 void ServerChannelManager::deregisterClient(unsigned int destinationId, unsigned int localId)
00308 {
00309
00310 DestinationEntry *destEntry = getDestinationEntryById(destinationId);
00311 if (!destEntry || !destEntry->hasLocalId(localId)) return;
00312
00313
00314 destEntry->removeLocalId(localId);
00315 }
00316
00317 void ServerChannelManager::refreshDestination(unsigned int destinationId)
00318 {
00319
00320 DestinationEntry *destEntry = getDestinationEntryById(destinationId);
00321
00322
00323
00324 std::map<unsigned int, DestinationLocalEntry> &localEntries =
00325 destEntry->getLocalEntries();
00326 std::map<unsigned int, DestinationLocalEntry>::iterator localItor;
00327 for (localItor = localEntries.begin();
00328 localItor != localEntries.end();
00329 localItor++)
00330 {
00331 unsigned int localId = localItor->first;
00332 DestinationLocalEntry &localEntry = localItor->second;
00333
00334 ComsChannelMessage message(ComsChannelMessage::eJoinRequest, localId);
00335 bool differentMessage = false;
00336 std::list<ChannelEntry *>::iterator itor;
00337 for (itor = channelEntries_.begin();
00338 itor != channelEntries_.end();
00339 itor++)
00340 {
00341 ChannelEntry *channelEntry = (*itor);
00342
00343
00344 bool allowedChannel = (!channelEntry->getAuth() ||
00345 channelEntry->getAuth()->allowConnection(
00346 channelEntry->getName(), destinationId));
00347
00348
00349 if (localEntry.getChannels().find(channelEntry->getName()) !=
00350 localEntry.getChannels().end())
00351 {
00352
00353
00354 if (allowedChannel)
00355 {
00356
00357
00358 message.getChannels().push_back(
00359 channelEntry->getDefinition());
00360 }
00361 else
00362 {
00363
00364
00365 destEntry->removeChannel(channelEntry->getName(), localId);
00366 differentMessage = true;
00367 }
00368 }
00369 else if (localEntry.getAvailableChannels().find(channelEntry->getName()) !=
00370 localEntry.getAvailableChannels().end())
00371 {
00372
00373
00374 if (allowedChannel)
00375 {
00376
00377
00378 message.getAvailableChannels().push_back(
00379 channelEntry->getDefinition());
00380 }
00381 else
00382 {
00383
00384
00385 destEntry->removeChannel(channelEntry->getName(), localId);
00386 differentMessage = true;
00387 }
00388 }
00389 else
00390 {
00391
00392 if (allowedChannel)
00393 {
00394
00395
00396 message.getAvailableChannels().push_back(
00397 channelEntry->getDefinition());
00398 destEntry->addChannel(channelEntry->getName(), localId, false);
00399 differentMessage = true;
00400 }
00401 }
00402 }
00403
00404 if (differentMessage)
00405 {
00406
00407
00408 ComsMessageSender::sendToSingleClient(message, destinationId);
00409 }
00410 }
00411 }
00412
00413 void ServerChannelManager::joinClient(unsigned int destinationId, unsigned int localId,
00414 std::list<ChannelDefinition> &startChannels)
00415 {
00416
00417 DestinationEntry *destEntry = getDestinationEntryById(destinationId);
00418 if (!destEntry || !destEntry->hasLocalId(localId)) return;
00419
00420
00421
00422 ComsChannelMessage message(ComsChannelMessage::eJoinRequest, localId);
00423 std::list<ChannelEntry *>::iterator itor;
00424 for (itor = channelEntries_.begin();
00425 itor != channelEntries_.end();
00426 itor++)
00427 {
00428 ChannelEntry *channelEntry = (*itor);
00429
00430
00431 if (channelEntry->getAuth() &&
00432 !channelEntry->getAuth()->allowConnection(
00433 channelEntry->getName(), destinationId))
00434 {
00435 destEntry->removeChannel(channelEntry->getName(), localId);
00436 continue;
00437 }
00438
00439
00440 bool current = false;
00441 std::list<ChannelDefinition>::iterator startItor;
00442 for (startItor = startChannels.begin();
00443 startItor != startChannels.end();
00444 startItor++)
00445 {
00446 const char *startChannel = startItor->getChannel();
00447 if (0 == strcmp(startChannel, channelEntry->getName()))
00448 {
00449 current = true;
00450 break;
00451 }
00452 }
00453
00454 destEntry->addChannel(channelEntry->getName(), localId, current);
00455 if (current) message.getChannels().push_back(channelEntry->getDefinition());
00456 else message.getAvailableChannels().push_back(channelEntry->getDefinition());
00457 }
00458 ComsMessageSender::sendToSingleClient(message, destinationId);
00459 }
00460
00461 void ServerChannelManager::sendText(const ChannelText &constText,
00462 unsigned int destination, bool log, bool filter)
00463 {
00464 DestinationEntry *destinationEntry = getDestinationEntryById(
00465 destination);
00466 if (destinationEntry)
00467 {
00468 std::map<unsigned int, DestinationEntry *> destinations;
00469 destinations[destination] = destinationEntry;
00470 actualSend(constText, destinations, log, filter);
00471 }
00472 }
00473
00474 void ServerChannelManager::sendText(const ChannelText &constText, bool log, bool filter)
00475 {
00476 actualSend(constText, destinationEntries_, log, filter);
00477 }
00478
00479 void ServerChannelManager::actualSend(const ChannelText &constText,
00480 std::map<unsigned int, DestinationEntry *> &destinations, bool log, bool filter)
00481 {
00482 ChannelText text = constText;
00483
00484
00485 Tank *tank = ScorchedServer::instance()->getTankContainer().getTankById(
00486 text.getSrcPlayerId());
00487
00488
00489 ChannelEntry *channelEntry = getChannelEntryByName(text.getChannel());
00490 if (!channelEntry)
00491 {
00492
00493 return;
00494 }
00495
00496 LangString filteredText(text.getMessage());
00497 if (filter)
00498 {
00499
00500 ScorchedServerUtil::instance()->textFilter.filterString(filteredText);
00501
00502
00503 for (unsigned int *r = (unsigned int *) filteredText.c_str(); *r; r++)
00504 {
00505 if (*r == '%' || *r < 0) *r = ' ';
00506 else if (*r == '[') *r = '(';
00507 else if (*r == ']') *r = ')';
00508 }
00509 if (!ScorchedServer::instance()->getOptionsGame().getAllowMultiLingualChat())
00510 {
00511 for (unsigned int *r = (unsigned int *) filteredText.c_str(); *r; r++)
00512 {
00513 if (*r > 127) *r = '?';
00514 }
00515 }
00516 }
00517
00518
00519 std::string logtext;
00520 if (log)
00521 {
00522 std::string logMessage = LangStringUtil::convertFromLang(filteredText);
00523 if (tank)
00524 {
00525 logtext = S3D::formatStringBuffer("[%s][%s] : \"%s\"",
00526 text.getChannel().c_str(),
00527 tank->getCStrName().c_str(),
00528 logMessage.c_str());
00529 }
00530 else if (text.getAdminPlayer()[0])
00531 {
00532 logtext = S3D::formatStringBuffer("[%s][%s (Admin)] : \"%s\"",
00533 text.getChannel().c_str(),
00534 text.getAdminPlayer().c_str(),
00535 logMessage.c_str());
00536 }
00537 else
00538 {
00539 logtext = S3D::formatStringBuffer("[%s] : \"%s\"",
00540 text.getChannel().c_str(),
00541 logMessage.c_str());
00542 }
00543 }
00544 if (logtext[0])
00545 {
00546 ServerCommon::serverLog(logtext);
00547 MessageEntry messageEntry;
00548 messageEntry.message = logtext;
00549 messageEntry.messageid = ++lastMessageId_;
00550 lastMessages_.push_back(messageEntry);
00551 if (lastMessages_.size() > 25) lastMessages_.pop_front();
00552 }
00553
00554
00555 text.setMessage(filteredText);
00556
00557
00558 ScorchedServer::instance()->getLUAScriptHook().callHook("server_channeltext",
00559 fixed(true, tank?tank->getPlayerId():0),
00560 text.getChannel(),
00561 text.getMessage());
00562
00563
00564 std::map<unsigned int, DestinationEntry *>::iterator destItor;
00565 for (destItor = destinations.begin();
00566 destItor != destinations.end();
00567 destItor++)
00568 {
00569 DestinationEntry *entry = (*destItor).second;
00570 if (!channelEntry->getFilter() || channelEntry->getFilter()->sentToDestination(
00571 text, entry->getDestinationId()))
00572 {
00573 if (entry->hasChannel(text.getChannel()))
00574 {
00575 ComsChannelTextMessage newTextMessage(text);
00576 entry->getLocalIds(text.getChannel(), newTextMessage.getIds());
00577 ComsMessageSender::sendToSingleClient(
00578 newTextMessage, entry->getDestinationId());
00579 }
00580 }
00581 }
00582 }
00583
00584 bool ServerChannelManager::processMessage(
00585 NetMessage &netNessage,
00586 const char *messageType,
00587 NetBufferReader &reader)
00588 {
00589
00590 if (0 == strcmp("ComsChannelMessage", messageType))
00591 {
00592
00593 ComsChannelMessage channelMessage;
00594 if (!channelMessage.readMessage(reader)) return false;
00595
00596
00597 switch (channelMessage.getType())
00598 {
00599 case ComsChannelMessage::eRegisterRequest:
00600 registerClient(netNessage.getDestinationId(), channelMessage.getId(),
00601 channelMessage.getChannels());
00602 break;
00603 case ComsChannelMessage::eDeregisterRequest:
00604 deregisterClient(netNessage.getDestinationId(), channelMessage.getId());
00605 break;
00606 case ComsChannelMessage::eJoinRequest:
00607 joinClient(netNessage.getDestinationId(), channelMessage.getId(),
00608 channelMessage.getChannels());
00609 break;
00610 }
00611 }
00612 else if (0 == strcmp("ComsChannelTextMessage", messageType))
00613 {
00614
00615 ComsChannelTextMessage textMessage;
00616 if (!textMessage.readMessage(reader)) return false;
00617 textMessage.getChannelText().setAdminPlayer("");
00618 textMessage.getChannelText().setMessageKey("");
00619 textMessage.getChannelText().setMessageValue("");
00620
00621
00622 Tank *tank = ScorchedServer::instance()->getTankContainer().getTankById(
00623 textMessage.getChannelText().getSrcPlayerId());
00624 if (!tank || tank->getDestinationId() !=
00625 netNessage.getDestinationId()) return true;
00626
00627
00628 DestinationEntry *destEntry =
00629 getDestinationEntryById(netNessage.getDestinationId());
00630 if (!destEntry || !destEntry->hasChannel(
00631 textMessage.getChannelText().getChannel()))
00632 {
00633
00634 return true;
00635 }
00636
00637
00638 ChannelEntry *channelEntry = getChannelEntryByName(
00639 textMessage.getChannelText().getChannel());
00640 if (!channelEntry)
00641 {
00642
00643 return true;
00644 }
00645 if (channelEntry->getDefinition().getType() &
00646 ChannelDefinition::eReadOnlyChannel)
00647 {
00648
00649 return true;
00650 }
00651 if ((!(channelEntry->getDefinition().getType() &
00652 ChannelDefinition::eWhisperChannel) &&
00653 textMessage.getChannelText().getDestPlayerId()) ||
00654
00655 ((channelEntry->getDefinition().getType() &
00656 ChannelDefinition::eWhisperChannel) &&
00657 !textMessage.getChannelText().getDestPlayerId()))
00658 {
00659
00660
00661
00662 return true;
00663 }
00664 if ((channelEntry->getDefinition().getType() &
00665 ChannelDefinition::eWhisperChannel) &&
00666 textMessage.getChannelText().getDestPlayerId() ==
00667 textMessage.getChannelText().getSrcPlayerId())
00668 {
00669
00670 return true;
00671 }
00672
00673
00674 if (textMessage.getChannelText().getMessage().size() > 1024) return true;
00675
00676
00677 destEntry->setMessageCount(destEntry->getMessageCount() + 1);
00678
00679
00680
00681 if (tank->getState().getMuted() ||
00682 destEntry->getMuteTime())
00683 {
00684 ChannelText mutedText(textMessage.getChannelText());
00685 mutedText.setMessage(
00686 LANG_RESOURCE("SERVER_MUTED_MESSAGE", "**muted** ") +
00687 mutedText.getMessage());
00688 ChannelText adminText(mutedText);
00689 adminText.setChannel("admin");
00690
00691 sendText(mutedText, tank->getDestinationId(), true);
00692 sendText(adminText, false);
00693 return true;
00694 }
00695
00696
00697 if (textMessage.getChannelText().getDestPlayerId())
00698 {
00699
00700 Tank *destTank = ScorchedServer::instance()->getTankContainer().
00701 getTankById(textMessage.getChannelText().getDestPlayerId());
00702 if (destTank && destTank->getDestinationId())
00703 {
00704
00705 sendText(textMessage.getChannelText(),
00706 destTank->getDestinationId(), true);
00707
00708
00709 if (tank->getDestinationId() !=
00710 destTank->getDestinationId())
00711 {
00712 sendText(textMessage.getChannelText(),
00713 tank->getDestinationId(), true);
00714 }
00715 }
00716 }
00717 else
00718 {
00719
00720 sendText(textMessage.getChannelText(), true);
00721 }
00722 }
00723 else return false;
00724
00725 return true;
00726 }