ManaPlus
packetlimiter.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2011-2019 The ManaPlus Developers
4  * Copyright (C) 2019-2021 Andrei Karas
5  *
6  * This file is part of The ManaPlus Client.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "net/packetlimiter.h"
23 
24 #include "configuration.h"
25 #include "settings.h"
26 
27 #include "utils/cast.h"
28 #include "utils/checkutils.h"
29 #include "utils/timer.h"
30 
31 #include <fstream>
32 #include <sys/stat.h>
33 
34 #include "debug.h"
35 
37 {
39 
40  int lastTime;
41  int timeLimit;
42  int cnt;
43  int cntLimit;
44 };
45 
47 
49 {
50  // here i setting packet limits. but current server is broken,
51  // and this limits may not help.
52 
61 
62  // 10
71 
72  // 10 5
81 
82  // 100
91 
100 
101  // 50
110 
111  // 10
120 
121  // 100
130 
139 
140  // 2+
149 
158 
167 
168  // 300ms + 50 fix
177 
178  if (!settings.serverConfigDir.empty())
179  {
180  const std::string packetLimitsName = settings.serverConfigDir
181  + "/packetlimiter.txt";
182 
183  std::ifstream inPacketFile;
184  struct stat statbuf;
185 
186  if ((stat(packetLimitsName.c_str(), &statbuf) != 0)
187  || !S_ISREG(statbuf.st_mode))
188  {
189  // wtiting new file
190  writePacketLimits(packetLimitsName);
191  }
192  else
193  { // reading existent file
194  inPacketFile.open(packetLimitsName.c_str(), std::ios::in);
195  char line[101];
196 
197  if (!inPacketFile.is_open() || !inPacketFile.getline(line, 100))
198  {
199  inPacketFile.close();
200  return;
201  }
202 
203  const int ver = atoi(line);
204 
205  for (int f = 0;
207  f ++)
208  {
209  if (!inPacketFile.getline(line, 100))
210  break;
211 
212  if (!(ver == 1 &&
213  (static_cast<PacketTypeT>(f) == PacketType::PACKET_DROP ||
214  static_cast<PacketTypeT>(f)
216  {
217  mPacketLimits[f].timeLimit = atoi(line);
218  }
219  }
220  inPacketFile.close();
221  if (ver < 5)
222  writePacketLimits(packetLimitsName);
223  }
224  }
225 }
226 
227 void PacketLimiter::writePacketLimits(const std::string &packetLimitsName)
228 {
229  std::ofstream outPacketFile;
230  outPacketFile.open(packetLimitsName.c_str(), std::ios::out);
231  if (!outPacketFile.is_open())
232  {
233  reportAlways("Error opening file for writing: %s",
234  packetLimitsName.c_str())
235  outPacketFile.close();
236  return;
237  }
238  outPacketFile << "4" << std::endl;
239  for (int f = 0; f < CAST_S32(PacketType::PACKET_SIZE); f ++)
240  {
241  outPacketFile << toString(mPacketLimits[f].timeLimit)
242  << std::endl;
243  }
244 
245  outPacketFile.close();
246 }
247 
249 {
250  if (type > PacketType::PACKET_SIZE)
251  return false;
252 
253  if (!serverConfig.getValueBool("enableBuggyServers", true))
254  return true;
255 
256  const PacketLimit &limit = mPacketLimits[CAST_SIZE(type)];
257  const int timeLimit = limit.timeLimit;
258 
259  if (timeLimit == 0)
260  return true;
261 
262  const int time = tick_time;
263  const int lastTime = limit.lastTime;
264  const int cnt = limit.cnt;
265  const int cntLimit = limit.cntLimit;
266 
267  if (lastTime > tick_time)
268  {
269 // instance()->mPacketLimits[type].lastTime = time;
270 // instance()->mPacketLimits[type].cnt = 0;
271 
272  return true;
273  }
274  else if (lastTime + timeLimit > time)
275  {
276  if (cnt >= cntLimit)
277  {
278  return false;
279  }
280 // instance()->mPacketLimits[type].cnt ++;
281  return true;
282  }
283 // instance()->mPacketLimits[type].lastTime = time;
284 // instance()->mPacketLimits[type].cnt = 1;
285  return true;
286 }
287 
289 {
290  if (CAST_S32(type) < 0 || type > PacketType::PACKET_SIZE)
291  return false;
292 
293  if (!serverConfig.getValueBool("enableBuggyServers", true))
294  return true;
295 
296  PacketLimit &pack = mPacketLimits[CAST_SIZE(type)];
297  const int timeLimit = pack.timeLimit;
298 
299  if (timeLimit == 0)
300  return true;
301 
302  const int time = tick_time;
303  const int lastTime = pack.lastTime;
304  const int cnt = pack.cnt;
305  const int cntLimit = pack.cntLimit;
306 
307  if (lastTime > tick_time)
308  {
309  pack.lastTime = time;
310  pack.cnt = 0;
311  return true;
312  }
313  else if (lastTime + timeLimit > time)
314  {
315  if (cnt >= cntLimit)
316  {
317  return false;
318  }
319  pack.cnt ++;
320  return true;
321  }
322  pack.lastTime = time;
323  pack.cnt = 1;
324  return true;
325 }
#define CAST_S32
Definition: cast.h:30
#define CAST_SIZE
Definition: cast.h:34
#define reportAlways(...)
Definition: checkutils.h:253
bool getValueBool(const std::string &key, const bool deflt) const
std::string serverConfigDir
Definition: settings.h:117
Configuration serverConfig
#define final
Definition: localconsts.h:46
#define A_DEFAULT_COPY(func)
Definition: localconsts.h:41
volatile int tick_time
Definition: timer.cpp:53
std::string toString(T const &value)
converts any type to a string
Definition: catch.hpp:1774
bool checkPackets(const PacketTypeT type)
void initPacketLimiter()
void writePacketLimits(const std::string &packetLimitsName)
bool limitPackets(const PacketTypeT type)
@ PACKET_ATTACK
Definition: packettype.h:38
@ PACKET_EMOTE
Definition: packettype.h:35
@ PACKET_ONLINELIST
Definition: packettype.h:40
@ PACKET_WHISPER
Definition: packettype.h:41
@ PACKET_NPC_TALK
Definition: packettype.h:33
@ PACKET_DIRECTION
Definition: packettype.h:37
@ PACKET_STOPATTACK
Definition: packettype.h:39
@ PACKET_NPC_INPUT
Definition: packettype.h:34
@ PACKET_PICKUP
Definition: packettype.h:30
@ PACKET_NPC_NEXT
Definition: packettype.h:32
PacketLimit mPacketLimits[static_cast< size_t >(PacketType::PACKET_SIZE)+1]
PacketType ::T PacketTypeT
Definition: packettype.h:44
Settings settings
Definition: settings.cpp:32