diff options
Diffstat (limited to 'src/net')
-rw-r--r-- | src/net/packetlimiter.cpp | 267 | ||||
-rw-r--r-- | src/net/packetlimiter.h | 57 |
2 files changed, 324 insertions, 0 deletions
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 |