summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/Makefile.am2
-rw-r--r--src/actionmanager.cpp8
-rw-r--r--src/actormanager.cpp17
-rw-r--r--src/being/being.cpp3
-rw-r--r--src/being/localplayer.cpp45
-rw-r--r--src/client.cpp229
-rw-r--r--src/client.h36
-rw-r--r--src/dropshortcut.cpp6
-rw-r--r--src/gui/windows/npcdialog.cpp11
-rw-r--r--src/gui/windows/whoisonline.cpp5
-rw-r--r--src/guildmanager.cpp7
-rw-r--r--src/net/packetlimiter.cpp267
-rw-r--r--src/net/packetlimiter.h57
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