GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/packetlimiter.cpp Lines: 0 118 0.0 %
Date: 2017-11-29 Branches: 0 86 0.0 %

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