GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/packetlimiter.cpp Lines: 0 118 0.0 %
Date: 2018-05-19 03:07:18 Branches: 0 86 0.0 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2011-2018  The ManaPlus Developers
4
 *
5
 *  This file is part of The ManaPlus Client.
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 2 of the License, or
10
 *  any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU General Public License
18
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
 */
20
21
#include "net/packetlimiter.h"
22
23
#include "configuration.h"
24
#include "settings.h"
25
26
#include "utils/cast.h"
27
#include "utils/checkutils.h"
28
#include "utils/timer.h"
29
30
#include <fstream>
31
#include <sys/stat.h>
32
33
#include "debug.h"
34
35
struct PacketLimit final
36
{
37
    A_DEFAULT_COPY(PacketLimit)
38
39
    int lastTime;
40
    int timeLimit;
41
    int cnt;
42
    int cntLimit;
43
};
44
45
PacketLimit mPacketLimits[CAST_SIZE(PacketType::PACKET_SIZE) + 1];
46
47
void PacketLimiter::initPacketLimiter()
48
{
49
    // here i setting packet limits. but current server is broken,
50
    // and this limits may not help.
51
52
    mPacketLimits[CAST_SIZE(
53
        PacketType::PACKET_CHAT)].timeLimit = 10 + 5;
54
    mPacketLimits[CAST_SIZE(
55
        PacketType::PACKET_CHAT)].lastTime = 0;
56
    mPacketLimits[CAST_SIZE(
57
        PacketType::PACKET_CHAT)].cntLimit = 1;
58
    mPacketLimits[CAST_SIZE(
59
        PacketType::PACKET_CHAT)].cnt = 0;
60
61
    // 10
62
    mPacketLimits[CAST_SIZE(
63
        PacketType::PACKET_PICKUP)].timeLimit = 10 + 5;
64
    mPacketLimits[CAST_SIZE(
65
        PacketType::PACKET_PICKUP)].lastTime = 0;
66
    mPacketLimits[CAST_SIZE(
67
        PacketType::PACKET_PICKUP)].cntLimit = 1;
68
    mPacketLimits[CAST_SIZE(
69
        PacketType::PACKET_PICKUP)].cnt = 0;
70
71
    // 10 5
72
    mPacketLimits[CAST_SIZE(
73
        PacketType::PACKET_DROP)].timeLimit = 5;
74
    mPacketLimits[CAST_SIZE(
75
        PacketType::PACKET_DROP)].lastTime = 0;
76
    mPacketLimits[CAST_SIZE(
77
        PacketType::PACKET_DROP)].cntLimit = 1;
78
    mPacketLimits[CAST_SIZE(
79
        PacketType::PACKET_DROP)].cnt = 0;
80
81
    // 100
82
    mPacketLimits[CAST_SIZE(
83
        PacketType::PACKET_NPC_NEXT)].timeLimit = 0;
84
    mPacketLimits[CAST_SIZE(
85
        PacketType::PACKET_NPC_NEXT)].lastTime = 0;
86
    mPacketLimits[CAST_SIZE(
87
        PacketType::PACKET_NPC_NEXT)].cntLimit = 1;
88
    mPacketLimits[CAST_SIZE(
89
        PacketType::PACKET_NPC_NEXT)].cnt = 0;
90
91
    mPacketLimits[CAST_SIZE(
92
        PacketType::PACKET_NPC_INPUT)].timeLimit = 100;
93
    mPacketLimits[CAST_SIZE(
94
        PacketType::PACKET_NPC_INPUT)].lastTime = 0;
95
    mPacketLimits[CAST_SIZE(
96
        PacketType::PACKET_NPC_INPUT)].cntLimit = 1;
97
    mPacketLimits[CAST_SIZE(
98
        PacketType::PACKET_NPC_INPUT)].cnt = 0;
99
100
    // 50
101
    mPacketLimits[CAST_SIZE(
102
        PacketType::PACKET_NPC_TALK)].timeLimit = 60;
103
    mPacketLimits[CAST_SIZE(
104
        PacketType::PACKET_NPC_TALK)].lastTime = 0;
105
    mPacketLimits[CAST_SIZE(
106
        PacketType::PACKET_NPC_TALK)].cntLimit = 1;
107
    mPacketLimits[CAST_SIZE(
108
        PacketType::PACKET_NPC_TALK)].cnt = 0;
109
110
    // 10
111
    mPacketLimits[CAST_SIZE(
112
        PacketType::PACKET_EMOTE)].timeLimit = 10 + 5;
113
    mPacketLimits[CAST_SIZE(
114
        PacketType::PACKET_EMOTE)].lastTime = 0;
115
    mPacketLimits[CAST_SIZE(
116
        PacketType::PACKET_EMOTE)].cntLimit = 1;
117
    mPacketLimits[CAST_SIZE(
118
        PacketType::PACKET_EMOTE)].cnt = 0;
119
120
    // 100
121
    mPacketLimits[CAST_SIZE(
122
        PacketType::PACKET_SIT)].timeLimit = 100;
123
    mPacketLimits[CAST_SIZE(
124
        PacketType::PACKET_SIT)].lastTime = 0;
125
    mPacketLimits[CAST_SIZE(
126
        PacketType::PACKET_SIT)].cntLimit = 1;
127
    mPacketLimits[CAST_SIZE(
128
        PacketType::PACKET_SIT)].cnt = 0;
129
130
    mPacketLimits[CAST_SIZE(
131
        PacketType::PACKET_DIRECTION)].timeLimit = 50;
132
    mPacketLimits[CAST_SIZE(
133
        PacketType::PACKET_DIRECTION)].lastTime = 0;
134
    mPacketLimits[CAST_SIZE(
135
        PacketType::PACKET_DIRECTION)].cntLimit = 1;
136
    mPacketLimits[CAST_SIZE(
137
        PacketType::PACKET_DIRECTION)].cnt = 0;
138
139
    // 2+
140
    mPacketLimits[CAST_SIZE(
141
        PacketType::PACKET_ATTACK)].timeLimit = 2 + 10;
142
    mPacketLimits[CAST_SIZE(
143
        PacketType::PACKET_ATTACK)].lastTime = 0;
144
    mPacketLimits[CAST_SIZE(
145
        PacketType::PACKET_ATTACK)].cntLimit = 1;
146
    mPacketLimits[CAST_SIZE(
147
        PacketType::PACKET_ATTACK)].cnt = 0;
148
149
    mPacketLimits[CAST_SIZE(
150
        PacketType::PACKET_STOPATTACK)].timeLimit = 2 + 10;
151
    mPacketLimits[CAST_SIZE(
152
        PacketType::PACKET_STOPATTACK)].lastTime = 0;
153
    mPacketLimits[CAST_SIZE(
154
        PacketType::PACKET_STOPATTACK)].cntLimit = 1;
155
    mPacketLimits[CAST_SIZE(
156
        PacketType::PACKET_STOPATTACK)].cnt = 0;
157
158
    mPacketLimits[CAST_SIZE(
159
        PacketType::PACKET_ONLINELIST)].timeLimit = 1800;
160
    mPacketLimits[CAST_SIZE(
161
        PacketType::PACKET_ONLINELIST)].lastTime = 0;
162
    mPacketLimits[CAST_SIZE(
163
        PacketType::PACKET_ONLINELIST)].cntLimit = 1;
164
    mPacketLimits[CAST_SIZE(
165
        PacketType::PACKET_ONLINELIST)].cnt = 0;
166
167
    // 300ms + 50 fix
168
    mPacketLimits[CAST_SIZE(
169
        PacketType::PACKET_WHISPER)].timeLimit = 30 + 5;
170
    mPacketLimits[CAST_SIZE(
171
        PacketType::PACKET_WHISPER)].lastTime = 0;
172
    mPacketLimits[CAST_SIZE(
173
        PacketType::PACKET_WHISPER)].cntLimit = 1;
174
    mPacketLimits[CAST_SIZE(
175
        PacketType::PACKET_WHISPER)].cnt = 0;
176
177
    if (!settings.serverConfigDir.empty())
178
    {
179
        const std::string packetLimitsName = settings.serverConfigDir
180
            + "/packetlimiter.txt";
181
182
        std::ifstream inPacketFile;
183
        struct stat statbuf;
184
185
        if ((stat(packetLimitsName.c_str(), &statbuf) != 0)
186
            || !S_ISREG(statbuf.st_mode))
187
        {
188
            // wtiting new file
189
            writePacketLimits(packetLimitsName);
190
        }
191
        else
192
        {   // reading existent file
193
            inPacketFile.open(packetLimitsName.c_str(), std::ios::in);
194
            char line[101];
195
196
            if (!inPacketFile.is_open() || !inPacketFile.getline(line, 100))
197
            {
198
                inPacketFile.close();
199
                return;
200
            }
201
202
            const int ver = atoi(line);
203
204
            for (int f = 0;
205
                 f < CAST_S32(PacketType::PACKET_SIZE);
206
                 f ++)
207
            {
208
                if (!inPacketFile.getline(line, 100))
209
                    break;
210
211
                if (!(ver == 1 &&
212
                    (static_cast<PacketTypeT>(f) == PacketType::PACKET_DROP ||
213
                    static_cast<PacketTypeT>(f)
214
                    == PacketType::PACKET_NPC_NEXT)))
215
                {
216
                    mPacketLimits[f].timeLimit = atoi(line);
217
                }
218
            }
219
            inPacketFile.close();
220
            if (ver < 5)
221
                writePacketLimits(packetLimitsName);
222
        }
223
    }
224
}
225
226
void PacketLimiter::writePacketLimits(const std::string &packetLimitsName)
227
{
228
    std::ofstream outPacketFile;
229
    outPacketFile.open(packetLimitsName.c_str(), std::ios::out);
230
    if (!outPacketFile.is_open())
231
    {
232
        reportAlways("Error opening file for writing: %s",
233
            packetLimitsName.c_str());
234
        outPacketFile.close();
235
        return;
236
    }
237
    outPacketFile << "4" << std::endl;
238
    for (int f = 0; f < CAST_S32(PacketType::PACKET_SIZE); f ++)
239
    {
240
        outPacketFile << toString(mPacketLimits[f].timeLimit)
241
                      << std::endl;
242
    }
243
244
    outPacketFile.close();
245
}
246
247
bool PacketLimiter::checkPackets(const PacketTypeT type)
248
{
249
    if (type > PacketType::PACKET_SIZE)
250
        return false;
251
252
    if (!serverConfig.getValueBool("enableBuggyServers", true))
253
        return true;
254
255
    const PacketLimit &limit = mPacketLimits[CAST_SIZE(type)];
256
    const int timeLimit = limit.timeLimit;
257
258
    if (timeLimit == 0)
259
        return true;
260
261
    const int time = tick_time;
262
    const int lastTime = limit.lastTime;
263
    const int cnt = limit.cnt;
264
    const int cntLimit = limit.cntLimit;
265
266
    if (lastTime > tick_time)
267
    {
268
//        instance()->mPacketLimits[type].lastTime = time;
269
//        instance()->mPacketLimits[type].cnt = 0;
270
271
        return true;
272
    }
273
    else if (lastTime + timeLimit > time)
274
    {
275
        if (cnt >= cntLimit)
276
        {
277
            return false;
278
        }
279
//        instance()->mPacketLimits[type].cnt ++;
280
        return true;
281
    }
282
//    instance()->mPacketLimits[type].lastTime = time;
283
//    instance()->mPacketLimits[type].cnt = 1;
284
    return true;
285
}
286
287
bool PacketLimiter::limitPackets(const PacketTypeT type)
288
{
289
    if (CAST_S32(type) < 0 || type > PacketType::PACKET_SIZE)
290
        return false;
291
292
    if (!serverConfig.getValueBool("enableBuggyServers", true))
293
        return true;
294
295
    PacketLimit &pack = mPacketLimits[CAST_SIZE(type)];
296
    const int timeLimit = pack.timeLimit;
297
298
    if (timeLimit == 0)
299
        return true;
300
301
    const int time = tick_time;
302
    const int lastTime = pack.lastTime;
303
    const int cnt = pack.cnt;
304
    const int cntLimit = pack.cntLimit;
305
306
    if (lastTime > tick_time)
307
    {
308
        pack.lastTime = time;
309
        pack.cnt = 0;
310
        return true;
311
    }
312
    else if (lastTime + timeLimit > time)
313
    {
314
        if (cnt >= cntLimit)
315
        {
316
            return false;
317
        }
318
        pack.cnt ++;
319
        return true;
320
    }
321
    pack.lastTime = time;
322
    pack.cnt = 1;
323
    return true;
324
}