GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/messagein.cpp Lines: 0 214 0.0 %
Date: 2018-09-20 Branches: 0 248 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-2018  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 readUInt16(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
uint8_t MessageIn::fromServerDirection(const uint8_t serverDir)
250
{
251
    // Translate from eAthena format
252
    switch (serverDir)
253
    {
254
        case 0:
255
            return 1;
256
        case 1:
257
            return 3;
258
        case 2:
259
            return 2;
260
        case 3:
261
            return 6;
262
        case 4:
263
            return 4;
264
        case 5:
265
            return 12;
266
        case 6:
267
            return 8;
268
        case 7:
269
            return 9;
270
        case 8:
271
            return 8;
272
        default:
273
            logger->log("incorrect direction: %d",
274
                CAST_S32(serverDir));
275
            return 0;
276
    }
277
}
278
279
void MessageIn::readCoordinates(uint16_t &restrict x,
280
                                uint16_t &restrict y,
281
                                uint8_t &restrict direction,
282
                                const char *const str)
283
{
284
    if (mPos + 3 <= mLength)
285
    {
286
        const char *const data = mData + CAST_SIZE(mPos);
287
        uint16_t temp = MAKEWORD(data[1] & 0x00c0, data[0] & 0x00ff);
288
        x = CAST_U16(temp >> 6);
289
        temp = MAKEWORD(data[2] & 0x00f0, data[1] & 0x003f);
290
        y = CAST_U16(temp >> 4);
291
292
        const uint8_t serverDir = CAST_U8(data[2] & 0x000f);
293
        direction = fromServerDirection(serverDir);
294
295
        DEBUGLOG2(std::string("readCoordinates: ").append(toString(
296
            CAST_S32(x))).append(",").append(toString(
297
            CAST_S32(y))).append(",").append(toString(
298
            CAST_S32(serverDir))), mPos, str);
299
    }
300
    else
301
    {
302
        x = 0;
303
        y = 0;
304
        direction = 0;
305
        logger->log("error: wrong readCoordinates packet");
306
    }
307
    mPos += 3;
308
    PacketCounters::incInBytes(3);
309
}
310
311
void MessageIn::readCoordinatePair(uint16_t &restrict srcX,
312
                                   uint16_t &restrict srcY,
313
                                   uint16_t &restrict dstX,
314
                                   uint16_t &restrict dstY,
315
                                   const char *const str)
316
{
317
    if (mPos + 5 <= mLength)
318
    {
319
        const char *const data = mData + CAST_SIZE(mPos);
320
        uint16_t temp = MAKEWORD(data[3], data[2] & 0x000f);
321
        dstX = CAST_U16(temp >> 2);
322
323
        dstY = MAKEWORD(data[4], data[3] & 0x0003);
324
325
        temp = MAKEWORD(data[1], data[0]);
326
        srcX = CAST_U16(temp >> 6);
327
328
        temp = MAKEWORD(data[2], data[1] & 0x003f);
329
        srcY = CAST_U16(temp >> 4);
330
331
        DEBUGLOG2(std::string("readCoordinatePair: ").append(toString(
332
            CAST_S32(srcX))).append(",").append(toString(
333
            CAST_S32(srcY))).append(" ").append(toString(
334
            CAST_S32(dstX))).append(",").append(toString(
335
            CAST_S32(dstY))), mPos, str);
336
    }
337
    else
338
    {
339
        srcX = 0;
340
        srcY = 0;
341
        dstX = 0;
342
        dstY = 0;
343
        logger->log("error: wrong readCoordinatePair packet");
344
    }
345
    mPos += 5;
346
    PacketCounters::incInBytes(5);
347
}
348
349
void MessageIn::skip(const unsigned int length, const char *const str)
350
{
351
    DEBUGLOG2("skip: " + toString(CAST_S32(length)), mPos, str);
352
    mPos += length;
353
    PacketCounters::incInBytes(length);
354
}
355
356
void MessageIn::skipToEnd(const char *const str)
357
{
358
    const int diff = CAST_S32(mLength - mPos);
359
    if (diff != 0)
360
    {
361
        DEBUGLOG2("skip: " + toString(diff), mPos, str);
362
        mPos = mLength;
363
        PacketCounters::incInBytes(diff);
364
    }
365
}
366
367
std::string MessageIn::readString(int length, const char *const dstr)
368
{
369
    // Get string length
370
    if (length < 0)
371
        length = readInt16("len");
372
373
    // Make sure the string isn't erroneous
374
    if (length < 0 || mPos + length > mLength)
375
    {
376
        DEBUGLOG2("readString error", mPos, dstr);
377
        mPos = mLength + 1;
378
        return "";
379
    }
380
381
    // Read the string
382
    const char *const stringBeg = mData + CAST_SIZE(mPos);
383
    const char *const stringEnd
384
        = static_cast<const char *>(memchr(stringBeg, '\0', length));
385
386
    const std::string str(stringBeg, stringEnd != nullptr
387
        ? stringEnd - stringBeg : CAST_SIZE(length));
388
    DEBUGLOG2("readString: " + str, mPos, dstr);
389
    mPos += length;
390
    PacketCounters::incInBytes(length);
391
    return str;
392
}
393
394
std::string MessageIn::readRawString(int length, const char *const dstr)
395
{
396
    // Get string length
397
    if (length < 0)
398
        length = readInt16("len");
399
400
    // Make sure the string isn't erroneous
401
    if (length < 0 || mPos + length > mLength)
402
    {
403
        mPos = mLength + 1;
404
        return "";
405
    }
406
407
    // Read the string
408
    const char *const stringBeg = mData + CAST_SIZE(mPos);
409
    const char *const stringEnd
410
        = static_cast<const char *>(memchr(stringBeg, '\0', length));
411
    std::string str(stringBeg, stringEnd != nullptr
412
        ? stringEnd - stringBeg : CAST_SIZE(length));
413
414
    DEBUGLOG2("readString: " + str, mPos, dstr);
415
416
    if (stringEnd != nullptr)
417
    {
418
        const size_t len2 = CAST_SIZE(length)
419
            - (stringEnd - stringBeg) - 1;
420
        const char *const stringBeg2 = stringEnd + 1;
421
        const char *const stringEnd2
422
            = static_cast<const char *>(memchr(stringBeg2, '\0', len2));
423
        const std::string hiddenPart = std::string(stringBeg2,
424
            stringEnd2 != nullptr ? stringEnd2 - stringBeg2 : len2);
425
        if (hiddenPart.length() > 0)
426
        {
427
            DEBUGLOG2("readString2: " + hiddenPart, mPos, dstr);
428
            return str.append("|").append(hiddenPart);
429
        }
430
    }
431
    mPos += length;
432
    PacketCounters::incInBytes(length);
433
434
    return str;
435
}
436
437
unsigned char *MessageIn::readBytes(int length, const char *const dstr)
438
{
439
    // Get string length
440
    if (length < 0)
441
        length = readInt16("len");
442
443
    // Make sure the string isn't erroneous
444
    if (length < 0 || mPos + length > mLength)
445
    {
446
        DEBUGLOG2("readBytesString error", mPos, dstr);
447
        mPos = mLength + 1;
448
        return nullptr;
449
    }
450
451
    unsigned char *const buf
452
        = new unsigned char[CAST_SIZE(length + 2)];
453
454
    memcpy(buf, mData + CAST_SIZE(mPos), length);
455
    buf[length] = 0;
456
    buf[length + 1] = 0;
457
    mPos += length;
458
459
#ifdef ENABLEDEBUGLOG
460
    std::string str;
461
    for (int f = 0; f < length; f ++)
462
        str.append(strprintf("%02x", CAST_U32(buf[f])));
463
    str += " ";
464
    for (int f = 0; f < length; f ++)
465
    {
466
        if (buf[f] != 0u)
467
            str.append(strprintf("%c", buf[f]));
468
        else
469
            str.append("_");
470
    }
471
    if (dstr != nullptr)
472
        logger->dlog(dstr);
473
    logger->dlog("ReadBytes: " + str);
474
#endif  // ENABLEDEBUGLOG
475
476
    PacketCounters::incInBytes(length);
477
    return buf;
478
}
479
480
int MessageIn::getVersionMain() const noexcept2
481
{
482
    if (packetVersionMain >= mVersion)
483
        return mVersion;
484
    return 0;
485
}
486
487
int MessageIn::getVersionRe() const noexcept2
488
{
489
    if (packetVersionRe >= mVersion)
490
        return mVersion;
491
    return 0;
492
}
493
494
int MessageIn::getVersionZero() const noexcept2
495
{
496
    if (packetVersionZero >= mVersion)
497
        return mVersion;
498
    return 0;
499
}
500
501
}  // namespace Net