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