diff options
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/actionmanager.cpp | 8 | ||||
-rw-r--r-- | src/actormanager.cpp | 17 | ||||
-rw-r--r-- | src/being/being.cpp | 3 | ||||
-rw-r--r-- | src/being/localplayer.cpp | 45 | ||||
-rw-r--r-- | src/client.cpp | 229 | ||||
-rw-r--r-- | src/client.h | 36 | ||||
-rw-r--r-- | src/dropshortcut.cpp | 6 | ||||
-rw-r--r-- | src/gui/windows/npcdialog.cpp | 11 | ||||
-rw-r--r-- | src/gui/windows/whoisonline.cpp | 5 | ||||
-rw-r--r-- | src/guildmanager.cpp | 7 | ||||
-rw-r--r-- | src/net/packetlimiter.cpp | 267 | ||||
-rw-r--r-- | src/net/packetlimiter.h | 57 |
14 files changed, 386 insertions, 309 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 929a1042a..8e8de9371 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -511,6 +511,8 @@ SET(SRCS net/worldinfo.h net/packetcounters.cpp net/packetcounters.h + net/packetlimiter.cpp + net/packetlimiter.h resources/action.cpp resources/action.h resources/ambientlayer.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 0104db56a..842b0e17d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -633,6 +633,8 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ net/worldinfo.h \ net/packetcounters.cpp \ net/packetcounters.h \ + net/packetlimiter.cpp \ + net/packetlimiter.h \ resources/action.cpp \ resources/action.h \ resources/ambientlayer.cpp \ diff --git a/src/actionmanager.cpp b/src/actionmanager.cpp index 12e13845a..10b51cb41 100644 --- a/src/actionmanager.cpp +++ b/src/actionmanager.cpp @@ -932,7 +932,7 @@ impHandler0(directUp) { if (player_node->getDirection() != BeingDirection::UP) { -// if (client->limitPackets(PACKET_DIRECTION)) +// if (PacketLimiter::limitPackets(PACKET_DIRECTION)) { player_node->setDirection(BeingDirection::UP); if (Net::getPlayerHandler()) @@ -950,7 +950,7 @@ impHandler0(directDown) { if (player_node->getDirection() != BeingDirection::DOWN) { -// if (client->limitPackets(PACKET_DIRECTION)) +// if (PacketLimiter::limitPackets(PACKET_DIRECTION)) { player_node->setDirection(BeingDirection::DOWN); if (Net::getPlayerHandler()) @@ -971,7 +971,7 @@ impHandler0(directLeft) { if (player_node->getDirection() != BeingDirection::LEFT) { -// if (client->limitPackets(PACKET_DIRECTION)) +// if (PacketLimiter::limitPackets(PACKET_DIRECTION)) { player_node->setDirection(BeingDirection::LEFT); if (Net::getPlayerHandler()) @@ -992,7 +992,7 @@ impHandler0(directRight) { if (player_node->getDirection() != BeingDirection::RIGHT) { -// if (client->limitPackets(PACKET_DIRECTION)) +// if (PacketLimiter::limitPackets(PACKET_DIRECTION)) { player_node->setDirection(BeingDirection::RIGHT); if (Net::getPlayerHandler()) diff --git a/src/actormanager.cpp b/src/actormanager.cpp index 699eb7fbd..c7e091900 100644 --- a/src/actormanager.cpp +++ b/src/actormanager.cpp @@ -45,6 +45,7 @@ #include "utils/gettext.h" #include "net/net.h" +#include "net/packetlimiter.h" #include "net/playerhandler.h" #include <algorithm> @@ -566,7 +567,7 @@ bool ActorManager::pickUpAll(const int x1, const int y1, } } } - else if (client->checkPackets(PACKET_PICKUP)) + else if (PacketLimiter::checkPackets(PACKET_PICKUP)) { FloorItem *item = nullptr; unsigned cnt = 65535; @@ -1151,7 +1152,7 @@ void ActorManager::heal(const Being *const target) const && PlayerInfo::getAttribute(Attributes::HP) != PlayerInfo::getAttribute(Attributes::MAX_HP)) { - if (!client->limitPackets(PACKET_CHAT)) + if (!PacketLimiter::limitPackets(PACKET_CHAT)) return; chatWindow->localChatInput(mSpellHeal1); } @@ -1164,7 +1165,7 @@ void ActorManager::heal(const Being *const target) const { if (target && target->getType() != ActorType::MONSTER) { - if (!client->limitPackets(PACKET_CHAT)) + if (!PacketLimiter::limitPackets(PACKET_CHAT)) return; chatWindow->localChatInput(mSpellHeal1 + " " + target->getName()); @@ -1172,7 +1173,7 @@ void ActorManager::heal(const Being *const target) const else if (PlayerInfo::getAttribute(Attributes::HP) != PlayerInfo::getAttribute(Attributes::MAX_HP)) { - if (!client->limitPackets(PACKET_CHAT)) + if (!PacketLimiter::limitPackets(PACKET_CHAT)) return; chatWindow->localChatInput(mSpellHeal1); } @@ -1189,7 +1190,7 @@ void ActorManager::heal(const Being *const target) const if (player_relations.getRelation(target->getName()) != PlayerRelation::ENEMY2) { - if (!client->limitPackets(PACKET_CHAT)) + if (!PacketLimiter::limitPackets(PACKET_CHAT)) return; chatWindow->localChatInput(mSpellHeal2 + " " + target->getName()); @@ -1197,7 +1198,7 @@ void ActorManager::heal(const Being *const target) const // target enemy else { - if (!client->limitPackets(PACKET_CHAT)) + if (!PacketLimiter::limitPackets(PACKET_CHAT)) return; chatWindow->localChatInput(mSpellHeal1); } @@ -1208,7 +1209,7 @@ void ActorManager::heal(const Being *const target) const && PlayerInfo::getAttribute(Attributes::HP) != PlayerInfo::getAttribute(Attributes::MAX_HP)) { - if (!client->limitPackets(PACKET_CHAT)) + if (!PacketLimiter::limitPackets(PACKET_CHAT)) return; chatWindow->localChatInput(mSpellHeal1); } @@ -1223,7 +1224,7 @@ void ActorManager::itenplz() const return; } - if (!client->limitPackets(PACKET_CHAT)) + if (!PacketLimiter::limitPackets(PACKET_CHAT)) return; chatWindow->localChatInput(mSpellItenplz); diff --git a/src/being/being.cpp b/src/being/being.cpp index 6bdf8f166..8da2d43da 100644 --- a/src/being/being.cpp +++ b/src/being/being.cpp @@ -59,6 +59,7 @@ #include "net/gamehandler.h" #include "net/net.h" #include "net/npchandler.h" +#include "net/packetlimiter.h" #include "net/pethandler.h" #include "net/playerhandler.h" @@ -2332,7 +2333,7 @@ void Being::setGM(const bool gm) void Being::talkTo() const { - if (!client->limitPackets(PACKET_NPC_TALK)) + if (!PacketLimiter::limitPackets(PACKET_NPC_TALK)) return; Net::getNpcHandler()->talk(mId); diff --git a/src/being/localplayer.cpp b/src/being/localplayer.cpp index ddc29629e..617671198 100644 --- a/src/being/localplayer.cpp +++ b/src/being/localplayer.cpp @@ -63,6 +63,7 @@ #include "net/chathandler.h" #include "net/inventoryhandler.h" #include "net/net.h" +#include "net/packetlimiter.h" #include "net/pethandler.h" #include "net/playerhandler.h" @@ -474,7 +475,7 @@ bool LocalPlayer::pickUp(FloorItem *const item) if (!item) return false; - if (!client->limitPackets(PACKET_PICKUP)) + if (!PacketLimiter::limitPackets(PACKET_PICKUP)) return false; const int dx = item->getTileX() - mX; @@ -584,7 +585,7 @@ void LocalPlayer::setDestination(const int x, const int y) Net::getPlayerHandler()->setDestination(x, y, newDir); -// if (client->limitPackets(PACKET_DIRECTION)) +// if (PacketLimiter::limitPackets(PACKET_DIRECTION)) { setDirection(newDir); Net::getPlayerHandler()->setDirection(newDir); @@ -651,7 +652,7 @@ void LocalPlayer::startWalking(const unsigned char dir) { // If the being can't move, just change direction -// if (client->limitPackets(PACKET_DIRECTION)) +// if (PacketLimiter::limitPackets(PACKET_DIRECTION)) { Net::getPlayerHandler()->setDirection(dir); setDirection(dir); @@ -687,7 +688,7 @@ void LocalPlayer::stopWalking(const bool sendToServer) bool LocalPlayer::toggleSit() const { - if (!client->limitPackets(PACKET_SIT)) + if (!PacketLimiter::limitPackets(PACKET_SIT)) return false; BeingAction::Action newAction; @@ -714,7 +715,7 @@ bool LocalPlayer::toggleSit() const bool LocalPlayer::updateSit() const { - if (!client->limitPackets(PACKET_SIT)) + if (!PacketLimiter::limitPackets(PACKET_SIT)) return false; Net::getPlayerHandler()->changeAction(mAction); @@ -723,7 +724,7 @@ bool LocalPlayer::updateSit() const bool LocalPlayer::emote(const uint8_t emotion) { - if (!client->limitPackets(PACKET_EMOTE)) + if (!PacketLimiter::limitPackets(PACKET_EMOTE)) return false; Net::getPlayerHandler()->emote(emotion); @@ -770,7 +771,7 @@ void LocalPlayer::attack(Being *const target, const bool keep, { setAction(BeingAction::ATTACK); - if (!client->limitPackets(PACKET_ATTACK)) + if (!PacketLimiter::limitPackets(PACKET_ATTACK)) return; if (!dontChangeEquipment) @@ -785,7 +786,7 @@ void LocalPlayer::attack(Being *const target, const bool keep, void LocalPlayer::stopAttack(const bool keepAttack) { - if (!client->limitPackets(PACKET_STOPATTACK)) + if (!PacketLimiter::limitPackets(PACKET_STOPATTACK)) return; if (mServerAttack && mAction == BeingAction::ATTACK) @@ -1849,7 +1850,7 @@ void LocalPlayer::crazyMove1() if (mAction == BeingAction::MOVE) return; -// if (!client->limitPackets(PACKET_DIRECTION)) +// if (!PacketLimiter::limitPackets(PACKET_DIRECTION)) // return; if (mDirection == BeingDirection::UP) @@ -1883,7 +1884,7 @@ void LocalPlayer::crazyMove2() if (mAction == BeingAction::MOVE) return; -// if (!client->limitPackets(PACKET_DIRECTION)) +// if (!PacketLimiter::limitPackets(PACKET_DIRECTION)) // return; if (mDirection == BeingDirection::UP) @@ -1943,7 +1944,7 @@ void LocalPlayer::crazyMove3() break; } -// if (!client->limitPackets(PACKET_DIRECTION)) +// if (!PacketLimiter::limitPackets(PACKET_DIRECTION)) // return; setDirection(BeingDirection::DOWN); @@ -2286,7 +2287,7 @@ void LocalPlayer::crazyMoveA() { case 'd': -// if (client->limitPackets(PACKET_DIRECTION)) +// if (PacketLimiter::limitPackets(PACKET_DIRECTION)) { setDirection(BeingDirection::DOWN); Net::getPlayerHandler()->setDirection( @@ -2294,7 +2295,7 @@ void LocalPlayer::crazyMoveA() } break; case 'u': -// if (client->limitPackets(PACKET_DIRECTION)) +// if (PacketLimiter::limitPackets(PACKET_DIRECTION)) { setDirection(BeingDirection::UP); Net::getPlayerHandler()->setDirection( @@ -2302,7 +2303,7 @@ void LocalPlayer::crazyMoveA() } break; case 'l': -// if (client->limitPackets(PACKET_DIRECTION)) +// if (PacketLimiter::limitPackets(PACKET_DIRECTION)) { setDirection(BeingDirection::LEFT); Net::getPlayerHandler()->setDirection( @@ -2310,7 +2311,7 @@ void LocalPlayer::crazyMoveA() } break; case 'r': -// if (client->limitPackets(PACKET_DIRECTION)) +// if (PacketLimiter::limitPackets(PACKET_DIRECTION)) { setDirection(BeingDirection::RIGHT); Net::getPlayerHandler()->setDirection( @@ -2318,7 +2319,7 @@ void LocalPlayer::crazyMoveA() } break; case 'L': -// if (client->limitPackets(PACKET_DIRECTION)) +// if (PacketLimiter::limitPackets(PACKET_DIRECTION)) { uint8_t dir = 0; switch (mDirection) @@ -2343,7 +2344,7 @@ void LocalPlayer::crazyMoveA() } break; case 'R': -// if (client->limitPackets(PACKET_DIRECTION)) +// if (PacketLimiter::limitPackets(PACKET_DIRECTION)) { uint8_t dir = 0; switch (mDirection) @@ -2368,7 +2369,7 @@ void LocalPlayer::crazyMoveA() } break; case 'b': -// if (client->limitPackets(PACKET_DIRECTION)) +// if (PacketLimiter::limitPackets(PACKET_DIRECTION)) { uint8_t dir = 0; switch (mDirection) @@ -2465,7 +2466,7 @@ void LocalPlayer::crazyMoveA() } if (mMoveProgram[mCrazyMoveState - 1] == 'e') emote(emoteId); - else if (client->limitPackets(PACKET_CHAT)) + else if (PacketLimiter::limitPackets(PACKET_CHAT)) Net::getPetHandler()->emote(emoteId, 0); mCrazyMoveState ++; @@ -2744,7 +2745,7 @@ void LocalPlayer::tryMagic(const std::string &spell, const int baseMagic, { if (PlayerInfo::getAttribute(Attributes::MP) >= mana) { - if (!client->limitPackets(PACKET_CHAT)) + if (!PacketLimiter::limitPackets(PACKET_CHAT)) return; chatWindow->localChatInput(spell); @@ -3222,7 +3223,7 @@ void LocalPlayer::targetMoved() const if (mTarget && mServerAttack) { logger->log("LocalPlayer::targetMoved0"); - if (!client->limitPackets(PACKET_ATTACK)) + if (!PacketLimiter::limitPackets(PACKET_ATTACK)) return; logger->log("LocalPlayer::targetMoved"); Net::getPlayerHandler()->attack(mTarget->getId(), mServerAttack); @@ -3396,7 +3397,7 @@ void LocalPlayer::imitateDirection(const Being *const being, if (!mPlayerImitated.empty() && being->getName() == mPlayerImitated) { - if (!client->limitPackets(PACKET_DIRECTION)) + if (!PacketLimiter::limitPackets(PACKET_DIRECTION)) return; if (mFollowMode == 2) diff --git a/src/client.cpp b/src/client.cpp index 081fe3996..86369030a 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -91,6 +91,7 @@ #include "net/loginhandler.h" #include "net/net.h" #include "net/netconsts.h" +#include "net/packetlimiter.h" #include "net/partyhandler.h" #include "particle/particle.h" @@ -328,7 +329,7 @@ void Client::gameInit() } atexit(SDL_Quit); - initPacketLimiter(); + PacketLimiter::initPacketLimiter(); #ifndef USE_SDL2 SDL_EnableUNICODE(1); #endif @@ -853,7 +854,7 @@ int Client::gameExec() { settings.serverName = mCurrentServer.hostname; ConfigManager::initServerConfig(mCurrentServer.hostname); - initPacketLimiter(); + PacketLimiter::initPacketLimiter(); initTradeFilter(); Dirs::initUsersDir(); player_relations.init(); @@ -1749,230 +1750,6 @@ void Client::initTradeFilter() const } } -void Client::initPacketLimiter() -{ - // here i setting packet limits. but current server is broken, - // and this limits may not help. - - mPacketLimits[PACKET_CHAT].timeLimit = 10 + 5; - mPacketLimits[PACKET_CHAT].lastTime = 0; - mPacketLimits[PACKET_CHAT].cntLimit = 1; - mPacketLimits[PACKET_CHAT].cnt = 0; - - // 10 - mPacketLimits[PACKET_PICKUP].timeLimit = 10 + 5; - mPacketLimits[PACKET_PICKUP].lastTime = 0; - mPacketLimits[PACKET_PICKUP].cntLimit = 1; - mPacketLimits[PACKET_PICKUP].cnt = 0; - - // 10 5 - mPacketLimits[PACKET_DROP].timeLimit = 5; - mPacketLimits[PACKET_DROP].lastTime = 0; - mPacketLimits[PACKET_DROP].cntLimit = 1; - mPacketLimits[PACKET_DROP].cnt = 0; - - // 100 - mPacketLimits[PACKET_NPC_NEXT].timeLimit = 0; - mPacketLimits[PACKET_NPC_NEXT].lastTime = 0; - mPacketLimits[PACKET_NPC_NEXT].cntLimit = 1; - mPacketLimits[PACKET_NPC_NEXT].cnt = 0; - - mPacketLimits[PACKET_NPC_INPUT].timeLimit = 100; - mPacketLimits[PACKET_NPC_INPUT].lastTime = 0; - mPacketLimits[PACKET_NPC_INPUT].cntLimit = 1; - mPacketLimits[PACKET_NPC_INPUT].cnt = 0; - - // 50 - mPacketLimits[PACKET_NPC_TALK].timeLimit = 60; - mPacketLimits[PACKET_NPC_TALK].lastTime = 0; - mPacketLimits[PACKET_NPC_TALK].cntLimit = 1; - mPacketLimits[PACKET_NPC_TALK].cnt = 0; - - // 10 - mPacketLimits[PACKET_EMOTE].timeLimit = 10 + 5; - mPacketLimits[PACKET_EMOTE].lastTime = 0; - mPacketLimits[PACKET_EMOTE].cntLimit = 1; - mPacketLimits[PACKET_EMOTE].cnt = 0; - - // 100 - mPacketLimits[PACKET_SIT].timeLimit = 100; - mPacketLimits[PACKET_SIT].lastTime = 0; - mPacketLimits[PACKET_SIT].cntLimit = 1; - mPacketLimits[PACKET_SIT].cnt = 0; - - mPacketLimits[PACKET_DIRECTION].timeLimit = 50; - mPacketLimits[PACKET_DIRECTION].lastTime = 0; - mPacketLimits[PACKET_DIRECTION].cntLimit = 1; - mPacketLimits[PACKET_DIRECTION].cnt = 0; - - // 2+ - mPacketLimits[PACKET_ATTACK].timeLimit = 2 + 10; - mPacketLimits[PACKET_ATTACK].lastTime = 0; - mPacketLimits[PACKET_ATTACK].cntLimit = 1; - mPacketLimits[PACKET_ATTACK].cnt = 0; - - mPacketLimits[PACKET_STOPATTACK].timeLimit = 2 + 10; - mPacketLimits[PACKET_STOPATTACK].lastTime = 0; - mPacketLimits[PACKET_STOPATTACK].cntLimit = 1; - mPacketLimits[PACKET_STOPATTACK].cnt = 0; - - mPacketLimits[PACKET_ONLINELIST].timeLimit = 1800; - mPacketLimits[PACKET_ONLINELIST].lastTime = 0; - mPacketLimits[PACKET_ONLINELIST].cntLimit = 1; - mPacketLimits[PACKET_ONLINELIST].cnt = 0; - - // 300ms + 50 fix - mPacketLimits[PACKET_WHISPER].timeLimit = 30 + 5; - mPacketLimits[PACKET_WHISPER].lastTime = 0; - mPacketLimits[PACKET_WHISPER].cntLimit = 1; - mPacketLimits[PACKET_WHISPER].cnt = 0; - - if (!settings.serverConfigDir.empty()) - { - const std::string packetLimitsName = settings.serverConfigDir - + "/packetlimiter.txt"; - - std::ifstream inPacketFile; - struct stat statbuf; - - if (stat(packetLimitsName.c_str(), &statbuf) - || !S_ISREG(statbuf.st_mode)) - { - // wtiting new file - writePacketLimits(packetLimitsName); - } - else - { // reading existent file - inPacketFile.open(packetLimitsName.c_str(), std::ios::in); - char line[101]; - - if (!inPacketFile.is_open() || !inPacketFile.getline(line, 100)) - { - inPacketFile.close(); - return; - } - - const int ver = atoi(line); - - for (int f = 0; f < PACKET_SIZE; f ++) - { - if (!inPacketFile.getline(line, 100)) - break; - - if (!(ver == 1 && (f == PACKET_DROP || f == PACKET_NPC_NEXT))) - mPacketLimits[f].timeLimit = atoi(line); - } - inPacketFile.close(); - if (ver < 5) - writePacketLimits(packetLimitsName); - } - } -} - -void Client::writePacketLimits(const std::string &packetLimitsName) const -{ - std::ofstream outPacketFile; - outPacketFile.open(packetLimitsName.c_str(), std::ios::out); - if (!outPacketFile.is_open()) - { - outPacketFile.close(); - return; - } - outPacketFile << "4" << std::endl; - for (int f = 0; f < PACKET_SIZE; f ++) - { - outPacketFile << toString(mPacketLimits[f].timeLimit) - << std::endl; - } - - outPacketFile.close(); -} - -bool Client::checkPackets(const int type) const -{ - if (type > PACKET_SIZE) - return false; - - if (!serverConfig.getValueBool("enableBuggyServers", true)) - return true; - - const PacketLimit &limit = mPacketLimits[type]; - const int timeLimit = limit.timeLimit; - - if (!timeLimit) - return true; - - const int time = tick_time; - const int lastTime = limit.lastTime; - const int cnt = limit.cnt; - const int cntLimit = limit.cntLimit; - - if (lastTime > tick_time) - { -// instance()->mPacketLimits[type].lastTime = time; -// instance()->mPacketLimits[type].cnt = 0; - - return true; - } - else if (lastTime + timeLimit > time) - { - if (cnt >= cntLimit) - { - return false; - } - else - { -// instance()->mPacketLimits[type].cnt ++; - return true; - } - } -// instance()->mPacketLimits[type].lastTime = time; -// instance()->mPacketLimits[type].cnt = 1; - return true; -} - -bool Client::limitPackets(const int type) -{ - if (type < 0 || type > PACKET_SIZE) - return false; - - if (!serverConfig.getValueBool("enableBuggyServers", true)) - return true; - - PacketLimit &pack = mPacketLimits[type]; - const int timeLimit = pack.timeLimit; - - if (!timeLimit) - return true; - - const int time = tick_time; - const int lastTime = pack.lastTime; - const int cnt = pack.cnt; - const int cntLimit = pack.cntLimit; - - if (lastTime > tick_time) - { - pack.lastTime = time; - pack.cnt = 0; - return true; - } - else if (lastTime + timeLimit > time) - { - if (cnt >= cntLimit) - { - return false; - } - else - { - pack.cnt ++; - return true; - } - } - pack.lastTime = time; - pack.cnt = 1; - return true; -} - void Client::setFramerate(const int fpsLimit) const { if (!fpsLimit) diff --git a/src/client.h b/src/client.h index 28dc27e75..96ca7d2c8 100644 --- a/src/client.h +++ b/src/client.h @@ -61,32 +61,6 @@ extern int textures_count; extern std::string errorMessage; extern LoginData loginData; -enum PacketTypes -{ - PACKET_CHAT = 0, - PACKET_PICKUP = 1, - PACKET_DROP = 2, - PACKET_NPC_NEXT = 3, - PACKET_NPC_TALK = 4, - PACKET_NPC_INPUT = 5, - PACKET_EMOTE = 6, - PACKET_SIT = 7, - PACKET_DIRECTION = 8, - PACKET_ATTACK = 9, - PACKET_STOPATTACK = 10, - PACKET_ONLINELIST = 11, - PACKET_WHISPER = 12, - PACKET_SIZE -}; - -struct PacketLimit -{ - int lastTime; - int timeLimit; - int cnt; - int cntLimit; -}; - /** * The core part of the client. This class initializes all subsystems, runs * the event loop, and shuts everything down again. @@ -162,22 +136,12 @@ public: void initTradeFilter() const; - void initPacketLimiter(); - - void writePacketLimits(const std::string &packetLimitsName) const; - void resizeVideo(int actualWidth, int actualHeight, const bool always); void applyScale(); - bool limitPackets(const int type) A_WARN_UNUSED; - - bool checkPackets(const int type) const A_WARN_UNUSED; - - PacketLimit mPacketLimits[PACKET_SIZE + 1]; - void windowRemoved(const Window *const window); void updateScreenKeyboard(const int height) diff --git a/src/dropshortcut.cpp b/src/dropshortcut.cpp index 90245d5af..9283294e1 100644 --- a/src/dropshortcut.cpp +++ b/src/dropshortcut.cpp @@ -30,6 +30,8 @@ #include "being/localplayer.h" #include "being/playerinfo.h" +#include "net/packetlimiter.h" + #include "debug.h" DropShortcut *dropShortcut = nullptr; @@ -94,7 +96,7 @@ void DropShortcut::dropFirst() const if (!player_node) return; - if (!client->limitPackets(PACKET_DROP)) + if (!PacketLimiter::limitPackets(PACKET_DROP)) return; const int itemId = getItem(0); @@ -139,7 +141,7 @@ void DropShortcut::dropItems(const int cnt) { for (int i = 0; i < sz; i++) { - if (!client->limitPackets(PACKET_DROP)) + if (!PacketLimiter::limitPackets(PACKET_DROP)) return; if (dropItem()) n++; diff --git a/src/gui/windows/npcdialog.cpp b/src/gui/windows/npcdialog.cpp index 47ad71f32..11ba96933 100644 --- a/src/gui/windows/npcdialog.cpp +++ b/src/gui/windows/npcdialog.cpp @@ -57,6 +57,7 @@ #include "net/net.h" #include "net/npchandler.h" +#include "net/packetlimiter.h" #include "utils/copynpaste.h" #include "utils/delete2.h" @@ -282,7 +283,7 @@ void NpcDialog::action(const ActionEvent &event) { if (mActionState == NPC_ACTION_NEXT) { - if (!client->limitPackets(PACKET_NPC_NEXT)) + if (!PacketLimiter::limitPackets(PACKET_NPC_NEXT)) return; nextDialog(); @@ -307,7 +308,7 @@ void NpcDialog::action(const ActionEvent &event) if (selectedIndex >= static_cast<int>(mItems.size()) || selectedIndex < 0 - || !client->limitPackets(PACKET_NPC_INPUT)) + || !PacketLimiter::limitPackets(PACKET_NPC_INPUT)) { return; } @@ -320,7 +321,7 @@ void NpcDialog::action(const ActionEvent &event) } case NPC_INPUT_STRING: { - if (!client->limitPackets(PACKET_NPC_INPUT)) + if (!PacketLimiter::limitPackets(PACKET_NPC_INPUT)) return; printText = mTextField->getText(); Net::getNpcHandler()->stringInput(mNpcId, printText); @@ -328,7 +329,7 @@ void NpcDialog::action(const ActionEvent &event) } case NPC_INPUT_INTEGER: { - if (!client->limitPackets(PACKET_NPC_INPUT)) + if (!PacketLimiter::limitPackets(PACKET_NPC_INPUT)) return; printText = strprintf("%d", mIntField->getValue()); Net::getNpcHandler()->integerInput( @@ -337,7 +338,7 @@ void NpcDialog::action(const ActionEvent &event) } case NPC_INPUT_ITEM: { - if (!client->limitPackets(PACKET_NPC_INPUT)) + if (!PacketLimiter::limitPackets(PACKET_NPC_INPUT)) return; std::string str; diff --git a/src/gui/windows/whoisonline.cpp b/src/gui/windows/whoisonline.cpp index 0cb2fd5d5..ff2f15427 100644 --- a/src/gui/windows/whoisonline.cpp +++ b/src/gui/windows/whoisonline.cpp @@ -45,6 +45,7 @@ #include "net/download.h" #include "net/net.h" +#include "net/packetlimiter.h" #include "net/playerhandler.h" #include "utils/gettext.h" @@ -590,7 +591,7 @@ void WhoIsOnline::download() } else { - if (client->limitPackets(PACKET_ONLINELIST)) + if (PacketLimiter::limitPackets(PACKET_ONLINELIST)) Net::getPlayerHandler()->requestOnlineList(); } } @@ -688,7 +689,7 @@ void WhoIsOnline::action(const ActionEvent &event) } else { - if (client->limitPackets(PACKET_ONLINELIST)) + if (PacketLimiter::limitPackets(PACKET_ONLINELIST)) { mUpdateTimer = cur_time; Net::getPlayerHandler()->requestOnlineList(); diff --git a/src/guildmanager.cpp b/src/guildmanager.cpp index df2c8686f..809343daa 100644 --- a/src/guildmanager.cpp +++ b/src/guildmanager.cpp @@ -36,6 +36,7 @@ #include "net/chathandler.h" #include "net/net.h" +#include "net/packetlimiter.h" #include "utils/delete2.h" #include "utils/timer.h" @@ -141,7 +142,7 @@ void GuildManager::requestGuildInfo() if (!mGotName && !mSentNameRequest) { - if (!client->limitPackets(PACKET_WHISPER)) + if (!PacketLimiter::limitPackets(PACKET_WHISPER)) return; send("!info " + toString(tick_time)); mRequest = true; @@ -150,7 +151,7 @@ void GuildManager::requestGuildInfo() } else if (!mGotInfo && !mSentInfoRequest && !mSentNameRequest) { - if (!client->limitPackets(PACKET_WHISPER)) + if (!PacketLimiter::limitPackets(PACKET_WHISPER)) return; send("!getonlineinfo " + toString(tick_time)); mRequest = true; @@ -163,7 +164,7 @@ void GuildManager::slowLogic() { if (!mGotOnlineInfo && mGotName && mRequestTime < cur_time) { - if (!client->limitPackets(PACKET_WHISPER)) + if (!PacketLimiter::limitPackets(PACKET_WHISPER)) return; send("!getonlineinfo " + toString(tick_time)); mRequest = true; diff --git a/src/net/packetlimiter.cpp b/src/net/packetlimiter.cpp new file mode 100644 index 000000000..b5dfd159a --- /dev/null +++ b/src/net/packetlimiter.cpp @@ -0,0 +1,267 @@ +/* + * The ManaPlus Client + * Copyright (C) 2011-2014 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * 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 + * 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, see <http://www.gnu.org/licenses/>. + */ + +#include "net/packetlimiter.h" + +#include "configuration.h" +#include "settings.h" + +#include "utils/stringutils.h" +#include "utils/timer.h" + +#include <fstream> + +#include <sys/stat.h> + +#include "debug.h" + +struct PacketLimit final +{ + int lastTime; + int timeLimit; + int cnt; + int cntLimit; +}; + +PacketLimit mPacketLimits[PACKET_SIZE + 1]; + +void PacketLimiter::initPacketLimiter() +{ + // here i setting packet limits. but current server is broken, + // and this limits may not help. + + mPacketLimits[PACKET_CHAT].timeLimit = 10 + 5; + mPacketLimits[PACKET_CHAT].lastTime = 0; + mPacketLimits[PACKET_CHAT].cntLimit = 1; + mPacketLimits[PACKET_CHAT].cnt = 0; + + // 10 + mPacketLimits[PACKET_PICKUP].timeLimit = 10 + 5; + mPacketLimits[PACKET_PICKUP].lastTime = 0; + mPacketLimits[PACKET_PICKUP].cntLimit = 1; + mPacketLimits[PACKET_PICKUP].cnt = 0; + + // 10 5 + mPacketLimits[PACKET_DROP].timeLimit = 5; + mPacketLimits[PACKET_DROP].lastTime = 0; + mPacketLimits[PACKET_DROP].cntLimit = 1; + mPacketLimits[PACKET_DROP].cnt = 0; + + // 100 + mPacketLimits[PACKET_NPC_NEXT].timeLimit = 0; + mPacketLimits[PACKET_NPC_NEXT].lastTime = 0; + mPacketLimits[PACKET_NPC_NEXT].cntLimit = 1; + mPacketLimits[PACKET_NPC_NEXT].cnt = 0; + + mPacketLimits[PACKET_NPC_INPUT].timeLimit = 100; + mPacketLimits[PACKET_NPC_INPUT].lastTime = 0; + mPacketLimits[PACKET_NPC_INPUT].cntLimit = 1; + mPacketLimits[PACKET_NPC_INPUT].cnt = 0; + + // 50 + mPacketLimits[PACKET_NPC_TALK].timeLimit = 60; + mPacketLimits[PACKET_NPC_TALK].lastTime = 0; + mPacketLimits[PACKET_NPC_TALK].cntLimit = 1; + mPacketLimits[PACKET_NPC_TALK].cnt = 0; + + // 10 + mPacketLimits[PACKET_EMOTE].timeLimit = 10 + 5; + mPacketLimits[PACKET_EMOTE].lastTime = 0; + mPacketLimits[PACKET_EMOTE].cntLimit = 1; + mPacketLimits[PACKET_EMOTE].cnt = 0; + + // 100 + mPacketLimits[PACKET_SIT].timeLimit = 100; + mPacketLimits[PACKET_SIT].lastTime = 0; + mPacketLimits[PACKET_SIT].cntLimit = 1; + mPacketLimits[PACKET_SIT].cnt = 0; + + mPacketLimits[PACKET_DIRECTION].timeLimit = 50; + mPacketLimits[PACKET_DIRECTION].lastTime = 0; + mPacketLimits[PACKET_DIRECTION].cntLimit = 1; + mPacketLimits[PACKET_DIRECTION].cnt = 0; + + // 2+ + mPacketLimits[PACKET_ATTACK].timeLimit = 2 + 10; + mPacketLimits[PACKET_ATTACK].lastTime = 0; + mPacketLimits[PACKET_ATTACK].cntLimit = 1; + mPacketLimits[PACKET_ATTACK].cnt = 0; + + mPacketLimits[PACKET_STOPATTACK].timeLimit = 2 + 10; + mPacketLimits[PACKET_STOPATTACK].lastTime = 0; + mPacketLimits[PACKET_STOPATTACK].cntLimit = 1; + mPacketLimits[PACKET_STOPATTACK].cnt = 0; + + mPacketLimits[PACKET_ONLINELIST].timeLimit = 1800; + mPacketLimits[PACKET_ONLINELIST].lastTime = 0; + mPacketLimits[PACKET_ONLINELIST].cntLimit = 1; + mPacketLimits[PACKET_ONLINELIST].cnt = 0; + + // 300ms + 50 fix + mPacketLimits[PACKET_WHISPER].timeLimit = 30 + 5; + mPacketLimits[PACKET_WHISPER].lastTime = 0; + mPacketLimits[PACKET_WHISPER].cntLimit = 1; + mPacketLimits[PACKET_WHISPER].cnt = 0; + + if (!settings.serverConfigDir.empty()) + { + const std::string packetLimitsName = settings.serverConfigDir + + "/packetlimiter.txt"; + + std::ifstream inPacketFile; + struct stat statbuf; + + if (stat(packetLimitsName.c_str(), &statbuf) + || !S_ISREG(statbuf.st_mode)) + { + // wtiting new file + writePacketLimits(packetLimitsName); + } + else + { // reading existent file + inPacketFile.open(packetLimitsName.c_str(), std::ios::in); + char line[101]; + + if (!inPacketFile.is_open() || !inPacketFile.getline(line, 100)) + { + inPacketFile.close(); + return; + } + + const int ver = atoi(line); + + for (int f = 0; f < PACKET_SIZE; f ++) + { + if (!inPacketFile.getline(line, 100)) + break; + + if (!(ver == 1 && (f == PACKET_DROP || f == PACKET_NPC_NEXT))) + mPacketLimits[f].timeLimit = atoi(line); + } + inPacketFile.close(); + if (ver < 5) + writePacketLimits(packetLimitsName); + } + } +} + +void PacketLimiter::writePacketLimits(const std::string &packetLimitsName) +{ + std::ofstream outPacketFile; + outPacketFile.open(packetLimitsName.c_str(), std::ios::out); + if (!outPacketFile.is_open()) + { + outPacketFile.close(); + return; + } + outPacketFile << "4" << std::endl; + for (int f = 0; f < PACKET_SIZE; f ++) + { + outPacketFile << toString(mPacketLimits[f].timeLimit) + << std::endl; + } + + outPacketFile.close(); +} + +bool PacketLimiter::checkPackets(const int type) +{ + if (type > PACKET_SIZE) + return false; + + if (!serverConfig.getValueBool("enableBuggyServers", true)) + return true; + + const PacketLimit &limit = mPacketLimits[type]; + const int timeLimit = limit.timeLimit; + + if (!timeLimit) + return true; + + const int time = tick_time; + const int lastTime = limit.lastTime; + const int cnt = limit.cnt; + const int cntLimit = limit.cntLimit; + + if (lastTime > tick_time) + { +// instance()->mPacketLimits[type].lastTime = time; +// instance()->mPacketLimits[type].cnt = 0; + + return true; + } + else if (lastTime + timeLimit > time) + { + if (cnt >= cntLimit) + { + return false; + } + else + { +// instance()->mPacketLimits[type].cnt ++; + return true; + } + } +// instance()->mPacketLimits[type].lastTime = time; +// instance()->mPacketLimits[type].cnt = 1; + return true; +} + +bool PacketLimiter::limitPackets(const int type) +{ + if (type < 0 || type > PACKET_SIZE) + return false; + + if (!serverConfig.getValueBool("enableBuggyServers", true)) + return true; + + PacketLimit &pack = mPacketLimits[type]; + const int timeLimit = pack.timeLimit; + + if (!timeLimit) + return true; + + const int time = tick_time; + const int lastTime = pack.lastTime; + const int cnt = pack.cnt; + const int cntLimit = pack.cntLimit; + + if (lastTime > tick_time) + { + pack.lastTime = time; + pack.cnt = 0; + return true; + } + else if (lastTime + timeLimit > time) + { + if (cnt >= cntLimit) + { + return false; + } + else + { + pack.cnt ++; + return true; + } + } + pack.lastTime = time; + pack.cnt = 1; + return true; +} diff --git a/src/net/packetlimiter.h b/src/net/packetlimiter.h new file mode 100644 index 000000000..f86ef457a --- /dev/null +++ b/src/net/packetlimiter.h @@ -0,0 +1,57 @@ +/* + * The ManaPlus Client + * Copyright (C) 2011-2014 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * 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 + * 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, see <http://www.gnu.org/licenses/>. + */ + +#ifndef NET_PACKETLIMITER_H +#define NET_PACKETLIMITER_H + +#include <string> + +#include "localconsts.h" + +enum PacketTypes +{ + PACKET_CHAT = 0, + PACKET_PICKUP = 1, + PACKET_DROP = 2, + PACKET_NPC_NEXT = 3, + PACKET_NPC_TALK = 4, + PACKET_NPC_INPUT = 5, + PACKET_EMOTE = 6, + PACKET_SIT = 7, + PACKET_DIRECTION = 8, + PACKET_ATTACK = 9, + PACKET_STOPATTACK = 10, + PACKET_ONLINELIST = 11, + PACKET_WHISPER = 12, + PACKET_SIZE +}; + +namespace PacketLimiter +{ + void initPacketLimiter(); + + void writePacketLimits(const std::string &packetLimitsName); + + bool limitPackets(const int type) A_WARN_UNUSED; + + bool checkPackets(const int type) A_WARN_UNUSED; +} + +#endif // NET_PACKETLIMITER_H |