GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/messagein.cpp Lines: 0 224 0.0 %
Date: 2021-03-17 Branches: 0 260 0.0 %

Line Branch Exec Source
1
/*
2
 *  The ManaPlus Client
3
 *  Copyright (C) 2004-2009  The Mana World Development Team
4
 *  Copyright (C) 2009-2010  The Mana Developers
5
 *  Copyright (C) 2011-2019  The ManaPlus Developers
6
 *  Copyright (C) 2019-2021  Andrei Karas
7
 *
8
 *  This file is part of The ManaPlus Client.
9
 *
10
 *  This program is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU General Public License as published by
12
 *  the Free Software Foundation; either version 2 of the License, or
13
 *  any later version.
14
 *
15
 *  This program is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU General Public License
21
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 */
23
24
#include "net/messagein.h"
25
26
#include "net/packetcounters.h"
27
28
#include "utils/cast.h"
29
#include "utils/stringutils.h"
30
31
#include "logger.h"
32
33
#include "debug.h"
34
35
PRAGMA48(GCC diagnostic push)
36
PRAGMA48(GCC diagnostic ignored "-Wshadow")
37
#ifndef SDL_BIG_ENDIAN
38
#include <SDL_endian.h>
39
#endif  // SDL_BYTEORDER
40
PRAGMA48(GCC diagnostic pop)
41
42
#define MAKEWORD(low, high) \
43
    (CAST_U16((CAST_U8(low)) | \
44
    (CAST_U16(CAST_U8(high))) << 8))
45
46
extern int itemIdLen;
47
extern int packetVersionMain;
48
extern int packetVersionRe;
49
extern int packetVersionZero;
50
51
namespace Net
52
{
53
54
MessageIn::MessageIn(const char *const data,
55
                     const unsigned int length) :
56
    mData(data),
57
    mLength(length),
58
    mPos(0),
59
    mVersion(0),
60
    mId(0),
61
    mIgnore(false)
62
{
63
    PacketCounters::incInPackets();
64
}
65
66
MessageIn::~MessageIn()
67
{
68
    if (mLength != 0U)
69
    {
70
        if (mPos != mLength && mPos != 2)
71
        {
72
            logger->log("Wrong actual or planned inbound packet size!");
73
            logger->log(" packet id: %u 0x%x",
74
                CAST_U32(mId),
75
                CAST_U32(mId));
76
            logger->log(" planned size: %u", mLength);
77
            logger->log(" read size: %u", mPos);
78
            WRONGPACKETSIZE;
79
        }
80
    }
81
    else
82
    {
83
        logger->log("Zero packet size: %d", CAST_S32(mId));
84
    }
85
}
86
87
uint16_t MessageIn::readId() const
88
{
89
    int16_t value = -1;
90
    if (mPos + 2 <= mLength)
91
    {
92
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
93
        int16_t swap;
94
        memcpy(&swap, mData + CAST_SIZE(mPos), sizeof(int16_t));
95
        value = SDL_Swap16(swap);
96
#else  // SDL_BYTEORDER == SDL_BIG_ENDIAN
97
98
        memcpy(&value, mData + CAST_SIZE(mPos), sizeof(int16_t));
99
#endif  // SDL_BYTEORDER == SDL_BIG_ENDIAN
100
    }
101
    return value;
102
}
103
104
unsigned char MessageIn::readUInt8(const char *const str)
105
{
106
    unsigned char value = CAST_U8(-1);
107
    if (mPos < mLength)
108
        value = CAST_U8(mData[mPos]);
109
110
    DEBUGLOG2("readUInt8:  " + toStringPrint(CAST_U32(value)),
111
        mPos, str);
112
    mPos += 1;
113
    PacketCounters::incInBytes(1);
114
    return value;
115
}
116
117
signed char MessageIn::readInt8(const char *const str)
118
{
119
    signed char value = CAST_S8(-1);
120
    if (mPos < mLength)
121
        value = CAST_S8(mData[mPos]);
122
123
    DEBUGLOG2("readInt8:   " + toStringPrint(CAST_U32(
124
        CAST_U8(value))),
125
        mPos, str);
126
    mPos += 1;
127
    PacketCounters::incInBytes(1);
128
    return value;
129
}
130
131
int16_t MessageIn::readInt16(const char *const str)
132
{
133
    int16_t value = -1;
134
    if (mPos + 2 <= mLength)
135
    {
136
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
137
        int16_t swap;
138
        memcpy(&swap, mData + CAST_SIZE(mPos), sizeof(int16_t));
139
        value = SDL_Swap16(swap);
140
#else  // SDL_BYTEORDER == SDL_BIG_ENDIAN
141
142
        memcpy(&value, mData + CAST_SIZE(mPos), sizeof(int16_t));
143
#endif  // SDL_BYTEORDER == SDL_BIG_ENDIAN
144
    }
145
    DEBUGLOG2("readInt16:  " + toStringPrint(CAST_U32(
146
        CAST_U16(value))),
147
        mPos, str);
148
    mPos += 2;
149
    PacketCounters::incInBytes(2);
150
    return value;
151
}
152
153
uint16_t MessageIn::readUInt16(const char *const str)
154
{
155
    uint16_t value = 0xffU;
156
    if (mPos + 2 <= mLength)
157
    {
158
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
159
        uint16_t swap;
160
        memcpy(&swap, mData + CAST_SIZE(mPos), sizeof(uint16_t));
161
        value = SDL_Swap16(swap);
162
#else  // SDL_BYTEORDER == SDL_BIG_ENDIAN
163
164
        memcpy(&value, mData + CAST_SIZE(mPos), sizeof(uint16_t));
165
#endif  // SDL_BYTEORDER == SDL_BIG_ENDIAN
166
    }
167
    DEBUGLOG2("readUInt16:  " + toStringPrint(CAST_U32(
168
        CAST_U16(value))),
169
        mPos, str);
170
    mPos += 2;
171
    PacketCounters::incInBytes(2);
172
    return value;
173
}
174
175
int32_t MessageIn::readInt32(const char *const str)
176
{
177
    int32_t value = -1;
178
    if (mPos + 4 <= mLength)
179
    {
180
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
181
        int32_t swap;
182
        memcpy(&swap, mData + CAST_SIZE(mPos), sizeof(int32_t));
183
        value = SDL_Swap32(swap);
184
#else  // SDL_BYTEORDER == SDL_BIG_ENDIAN
185
186
        memcpy(&value, mData + CAST_SIZE(mPos), sizeof(int32_t));
187
#endif  // SDL_BYTEORDER == SDL_BIG_ENDIAN
188
    }
189
    DEBUGLOG2("readInt32:  " + toStringPrint(CAST_S32(value)),
190
        mPos, str);
191
    mPos += 4;
192
    PacketCounters::incInBytes(4);
193
    return value;
194
}
195
196
uint32_t MessageIn::readUInt32(const char *const str)
197
{
198
    uint32_t value = 0;
199
    if (mPos + 4 <= mLength)
200
    {
201
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
202
        uint32_t swap;
203
        memcpy(&swap, mData + CAST_SIZE(mPos), sizeof(int32_t));
204
        value = SDL_Swap32(swap);
205
#else  // SDL_BYTEORDER == SDL_BIG_ENDIAN
206
207
        memcpy(&value, mData + CAST_SIZE(mPos), sizeof(int32_t));
208
#endif  // SDL_BYTEORDER == SDL_BIG_ENDIAN
209
    }
210
    DEBUGLOG2("readInt32:  " + toStringPrint(CAST_U32(value)),
211
        mPos, str);
212
    mPos += 4;
213
    PacketCounters::incInBytes(4);
214
    return value;
215
}
216
217
int MessageIn::readItemId(const char *const str)
218
{
219
    if (itemIdLen == 2)
220
        return readInt16(str);
221
    return readInt32(str);
222
}
223
224
BeingId MessageIn::readBeingId(const char *const str)
225
{
226
    return fromInt(readUInt32(str), BeingId);
227
}
228
229
int64_t MessageIn::readInt64(const char *const str)
230
{
231
    int64_t value = -1;
232
    if (mPos + 8 <= mLength)
233
    {
234
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
235
        int64_t swap;
236
        memcpy(&swap, mData + CAST_SIZE(mPos), sizeof(int64_t));
237
        value = SDL_Swap64(swap);
238
#else  // SDL_BYTEORDER == SDL_BIG_ENDIAN
239
240
        memcpy(&value, mData + CAST_SIZE(mPos), sizeof(int64_t));
241
#endif  // SDL_BYTEORDER == SDL_BIG_ENDIAN
242
    }
243
    DEBUGLOG2("readInt64:  " + toStringPrint(CAST_U32(value)),
244
        mPos, str);
245
    mPos += 8;
246
    PacketCounters::incInBytes(8);
247
    return value;
248
}
249
250
float MessageIn::readFloat(const char *const str)
251
{
252
    float value = 0;
253
    if (mPos + 4 <= mLength)
254
    {
255
        memcpy(&value, mData + CAST_SIZE(mPos), sizeof(float));
256
    }
257
#ifdef ENABLEDEBUGLOG
258
    std::string text = strprintf("readFloat: %f", value);
259
    DEBUGLOG2(str, mPos, text.c_str());
260
#endif
261
    mPos += 4;
262
    PacketCounters::incInBytes(4);
263
    return value;
264
}
265
266
uint8_t MessageIn::fromServerDirection(const uint8_t serverDir)
267
{
268
    // Translate from eAthena format
269
    switch (serverDir)
270
    {
271
        case 0:
272
            return 1;
273
        case 1:
274
            return 3;
275
        case 2:
276
            return 2;
277
        case 3:
278
            return 6;
279
        case 4:
280
            return 4;
281
        case 5:
282
            return 12;
283
        case 6:
284
            return 8;
285
        case 7:
286
            return 9;
287
        case 8:
288
            return 8;
289
        default:
290
            logger->log("incorrect direction: %d",
291
                CAST_S32(serverDir));
292
            return 0;
293
    }
294
}
295
296
void MessageIn::readCoordinates(uint16_t &restrict x,
297
                                uint16_t &restrict y,
298
                                uint8_t &restrict direction,
299
                                const char *const str)
300
{
301
    if (mPos + 3 <= mLength)
302
    {
303
        const char *const data = mData + CAST_SIZE(mPos);
304
        uint16_t temp = MAKEWORD(data[1] & 0x00c0, data[0] & 0x00ff);
305
        x = CAST_U16(temp >> 6);
306
        temp = MAKEWORD(data[2] & 0x00f0, data[1] & 0x003f);
307
        y = CAST_U16(temp >> 4);
308
309
        const uint8_t serverDir = CAST_U8(data[2] & 0x000f);
310
        direction = fromServerDirection(serverDir);
311
312
        DEBUGLOG2(std::string("readCoordinates: ").append(toString(
313
            CAST_S32(x))).append(",").append(toString(
314
            CAST_S32(y))).append(",").append(toString(
315
            CAST_S32(serverDir))), mPos, str);
316
    }
317
    else
318
    {
319
        x = 0;
320
        y = 0;
321
        direction = 0;
322
        logger->log("error: wrong readCoordinates packet");
323
    }
324
    mPos += 3;
325
    PacketCounters::incInBytes(3);
326
}
327
328
void MessageIn::readCoordinatePair(uint16_t &restrict srcX,
329
                                   uint16_t &restrict srcY,
330
                                   uint16_t &restrict dstX,
331
                                   uint16_t &restrict dstY,
332
                                   const char *const str)
333
{
334
    if (mPos + 5 <= mLength)
335
    {
336
        const char *const data = mData + CAST_SIZE(mPos);
337
        uint16_t temp = MAKEWORD(data[3], data[2] & 0x000f);
338
        dstX = CAST_U16(temp >> 2);
339
340
        dstY = MAKEWORD(data[4], data[3] & 0x0003);
341
342
        temp = MAKEWORD(data[1], data[0]);
343
        srcX = CAST_U16(temp >> 6);
344
345
        temp = MAKEWORD(data[2], data[1] & 0x003f);
346
        srcY = CAST_U16(temp >> 4);
347
348
        DEBUGLOG2(std::string("readCoordinatePair: ").append(toString(
349
            CAST_S32(srcX))).append(",").append(toString(
350
            CAST_S32(srcY))).append(" ").append(toString(
351
            CAST_S32(dstX))).append(",").append(toString(
352
            CAST_S32(dstY))), mPos, str);
353
    }
354
    else
355
    {
356
        srcX = 0;
357
        srcY = 0;
358
        dstX = 0;
359
        dstY = 0;
360
        logger->log("error: wrong readCoordinatePair packet");
361
    }
362
    mPos += 5;
363
    PacketCounters::incInBytes(5);
364
}
365
366
void MessageIn::skip(const unsigned int length, const char *const str)
367
{
368
    DEBUGLOG2("skip: " + toString(CAST_S32(length)), mPos, str);
369
    mPos += length;
370
    PacketCounters::incInBytes(length);
371
}
372
373
void MessageIn::skipToEnd(const char *const str)
374
{
375
    const int diff = CAST_S32(mLength - mPos);
376
    if (diff != 0)
377
    {
378
        DEBUGLOG2("skip: " + toString(diff), mPos, str);
379
        mPos = mLength;
380
        PacketCounters::incInBytes(diff);
381
    }
382
}
383
384
std::string MessageIn::readString(int length, const char *const dstr)
385
{
386
    // Get string length
387
    if (length < 0)
388
        length = readInt16("len");
389
390
    // Make sure the string isn't erroneous
391
    if (length < 0 || mPos + length > mLength)
392
    {
393
        DEBUGLOG2("readString error", mPos, dstr);
394
        mPos = mLength + 1;
395
        return "";
396
    }
397
398
    // Read the string
399
    const char *const stringBeg = mData + CAST_SIZE(mPos);
400
    const char *const stringEnd
401
        = static_cast<const char *>(memchr(stringBeg, '\0', length));
402
403
    const std::string str(stringBeg, stringEnd != nullptr
404
        ? stringEnd - stringBeg : CAST_SIZE(length));
405
    DEBUGLOG2("readString: " + str, mPos, dstr);
406
    mPos += length;
407
    PacketCounters::incInBytes(length);
408
    return str;
409
}
410
411
std::string MessageIn::readRawString(int length, const char *const dstr)
412
{
413
    // Get string length
414
    if (length < 0)
415
        length = readInt16("len");
416
417
    // Make sure the string isn't erroneous
418
    if (length < 0 || mPos + length > mLength)
419
    {
420
        mPos = mLength + 1;
421
        return "";
422
    }
423
424
    // Read the string
425
    const char *const stringBeg = mData + CAST_SIZE(mPos);
426
    const char *const stringEnd
427
        = static_cast<const char *>(memchr(stringBeg, '\0', length));
428
    std::string str(stringBeg, stringEnd != nullptr
429
        ? stringEnd - stringBeg : CAST_SIZE(length));
430
431
    DEBUGLOG2("readString: " + str, mPos, dstr);
432
433
    if (stringEnd != nullptr)
434
    {
435
        const size_t len2 = CAST_SIZE(length)
436
            - (stringEnd - stringBeg) - 1;
437
        const char *const stringBeg2 = stringEnd + 1;
438
        const char *const stringEnd2
439
            = static_cast<const char *>(memchr(stringBeg2, '\0', len2));
440
        const std::string hiddenPart = std::string(stringBeg2,
441
            stringEnd2 != nullptr ? stringEnd2 - stringBeg2 : len2);
442
        if (hiddenPart.length() > 0)
443
        {
444
            DEBUGLOG2("readString2: " + hiddenPart, mPos, dstr);
445
            return str.append("|").append(hiddenPart);
446
        }
447
    }
448
    mPos += length;
449
    PacketCounters::incInBytes(length);
450
451
    return str;
452
}
453
454
unsigned char *MessageIn::readBytes(int length, const char *const dstr)
455
{
456
    // Get string length
457
    if (length < 0)
458
        length = readInt16("len");
459
460
    // Make sure the string isn't erroneous
461
    if (length < 0 || mPos + length > mLength)
462
    {
463
        DEBUGLOG2("readBytesString error", mPos, dstr);
464
        mPos = mLength + 1;
465
        return nullptr;
466
    }
467
468
    unsigned char *const buf
469
        = new unsigned char[CAST_SIZE(length + 2)];
470
471
    memcpy(buf, mData + CAST_SIZE(mPos), length);
472
    buf[length] = 0;
473
    buf[length + 1] = 0;
474
    mPos += length;
475
476
#ifdef ENABLEDEBUGLOG
477
    if (!mIgnore)
478
    {
479
        std::string str;
480
        for (int f = 0; f < length; f ++)
481
            str.append(strprintf("%02x", CAST_U32(buf[f])));
482
        str += " ";
483
        for (int f = 0; f < length; f ++)
484
        {
485
            if (buf[f] != 0U)
486
                str.append(strprintf("%c", buf[f]));
487
            else
488
                str.append("_");
489
        }
490
        if (dstr != nullptr)
491
            logger->dlog(dstr);
492
        logger->dlog("ReadBytes: " + str);
493
    }
494
#endif  // ENABLEDEBUGLOG
495
496
    PacketCounters::incInBytes(length);
497
    return buf;
498
}
499
500
int MessageIn::getVersionMain() const noexcept2
501
{
502
    if (packetVersionMain >= mVersion)
503
        return mVersion;
504
    return 0;
505
}
506
507
int MessageIn::getVersionRe() const noexcept2
508
{
509
    if (packetVersionRe >= mVersion)
510
        return mVersion;
511
    return 0;
512
}
513
514
int MessageIn::getVersionZero() const noexcept2
515
{
516
    if (packetVersionZero >= mVersion)
517
        return mVersion;
518
    return 0;
519
}
520
521
}  // namespace Net