GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/messagein.cpp Lines: 0 201 0.0 %
Date: 2018-07-14 Branches: 0 240 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
namespace Net
46
{
47
48
MessageIn::MessageIn(const char *const data,
49
                     const unsigned int length) :
50
    mData(data),
51
    mLength(length),
52
    mPos(0),
53
    mVersion(0),
54
    mId(0),
55
    mIgnore(false)
56
{
57
    PacketCounters::incInPackets();
58
}
59
60
MessageIn::~MessageIn()
61
{
62
    if (mLength != 0u)
63
    {
64
        if (mPos != mLength && mPos != 2)
65
        {
66
            logger->log("Wrong actual or planned inbound packet size!");
67
            logger->log(" packet id: %u 0x%x",
68
                CAST_U32(mId),
69
                CAST_U32(mId));
70
            logger->log(" planned size: %u", mLength);
71
            logger->log(" read size: %u", mPos);
72
            WRONGPACKETSIZE;
73
        }
74
    }
75
    else
76
    {
77
        logger->log("Zero packet size: %d", CAST_S32(mId));
78
    }
79
}
80
81
uint16_t MessageIn::readId() const
82
{
83
    int16_t value = -1;
84
    if (mPos + 2 <= mLength)
85
    {
86
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
87
        int16_t swap;
88
        memcpy(&swap, mData + CAST_SIZE(mPos), sizeof(int16_t));
89
        value = SDL_Swap16(swap);
90
#else  // SDL_BYTEORDER == SDL_BIG_ENDIAN
91
92
        memcpy(&value, mData + CAST_SIZE(mPos), sizeof(int16_t));
93
#endif  // SDL_BYTEORDER == SDL_BIG_ENDIAN
94
    }
95
    return value;
96
}
97
98
unsigned char MessageIn::readUInt8(const char *const str)
99
{
100
    unsigned char value = CAST_U8(-1);
101
    if (mPos < mLength)
102
        value = CAST_U8(mData[mPos]);
103
104
    DEBUGLOG2("readUInt8:  " + toStringPrint(CAST_U32(value)),
105
        mPos, str);
106
    mPos += 1;
107
    PacketCounters::incInBytes(1);
108
    return value;
109
}
110
111
signed char MessageIn::readInt8(const char *const str)
112
{
113
    signed char value = CAST_S8(-1);
114
    if (mPos < mLength)
115
        value = CAST_S8(mData[mPos]);
116
117
    DEBUGLOG2("readInt8:   " + toStringPrint(CAST_U32(
118
        CAST_U8(value))),
119
        mPos, str);
120
    mPos += 1;
121
    PacketCounters::incInBytes(1);
122
    return value;
123
}
124
125
int16_t MessageIn::readInt16(const char *const str)
126
{
127
    int16_t value = -1;
128
    if (mPos + 2 <= mLength)
129
    {
130
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
131
        int16_t swap;
132
        memcpy(&swap, mData + CAST_SIZE(mPos), sizeof(int16_t));
133
        value = SDL_Swap16(swap);
134
#else  // SDL_BYTEORDER == SDL_BIG_ENDIAN
135
136
        memcpy(&value, mData + CAST_SIZE(mPos), sizeof(int16_t));
137
#endif  // SDL_BYTEORDER == SDL_BIG_ENDIAN
138
    }
139
    DEBUGLOG2("readInt16:  " + toStringPrint(CAST_U32(
140
        CAST_U16(value))),
141
        mPos, str);
142
    mPos += 2;
143
    PacketCounters::incInBytes(2);
144
    return value;
145
}
146
147
uint16_t MessageIn::readUInt16(const char *const str)
148
{
149
    uint16_t value = 0xffU;
150
    if (mPos + 2 <= mLength)
151
    {
152
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
153
        uint16_t swap;
154
        memcpy(&swap, mData + CAST_SIZE(mPos), sizeof(uint16_t));
155
        value = SDL_Swap16(swap);
156
#else  // SDL_BYTEORDER == SDL_BIG_ENDIAN
157
158
        memcpy(&value, mData + CAST_SIZE(mPos), sizeof(uint16_t));
159
#endif  // SDL_BYTEORDER == SDL_BIG_ENDIAN
160
    }
161
    DEBUGLOG2("readUInt16:  " + toStringPrint(CAST_U32(
162
        CAST_U16(value))),
163
        mPos, str);
164
    mPos += 2;
165
    PacketCounters::incInBytes(2);
166
    return value;
167
}
168
169
int32_t MessageIn::readInt32(const char *const str)
170
{
171
    int32_t value = -1;
172
    if (mPos + 4 <= mLength)
173
    {
174
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
175
        int32_t swap;
176
        memcpy(&swap, mData + CAST_SIZE(mPos), sizeof(int32_t));
177
        value = SDL_Swap32(swap);
178
#else  // SDL_BYTEORDER == SDL_BIG_ENDIAN
179
180
        memcpy(&value, mData + CAST_SIZE(mPos), sizeof(int32_t));
181
#endif  // SDL_BYTEORDER == SDL_BIG_ENDIAN
182
    }
183
    DEBUGLOG2("readInt32:  " + toStringPrint(CAST_S32(value)),
184
        mPos, str);
185
    mPos += 4;
186
    PacketCounters::incInBytes(4);
187
    return value;
188
}
189
190
uint32_t MessageIn::readUInt32(const char *const str)
191
{
192
    uint32_t value = 0;
193
    if (mPos + 4 <= mLength)
194
    {
195
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
196
        uint32_t swap;
197
        memcpy(&swap, mData + CAST_SIZE(mPos), sizeof(int32_t));
198
        value = SDL_Swap32(swap);
199
#else  // SDL_BYTEORDER == SDL_BIG_ENDIAN
200
201
        memcpy(&value, mData + CAST_SIZE(mPos), sizeof(int32_t));
202
#endif  // SDL_BYTEORDER == SDL_BIG_ENDIAN
203
    }
204
    DEBUGLOG2("readInt32:  " + toStringPrint(CAST_U32(value)),
205
        mPos, str);
206
    mPos += 4;
207
    PacketCounters::incInBytes(4);
208
    return value;
209
}
210
211
BeingId MessageIn::readBeingId(const char *const str)
212
{
213
    return fromInt(readUInt32(str), BeingId);
214
}
215
216
int64_t MessageIn::readInt64(const char *const str)
217
{
218
    int64_t value = -1;
219
    if (mPos + 8 <= mLength)
220
    {
221
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
222
        int64_t swap;
223
        memcpy(&swap, mData + CAST_SIZE(mPos), sizeof(int64_t));
224
        value = SDL_Swap64(swap);
225
#else  // SDL_BYTEORDER == SDL_BIG_ENDIAN
226
227
        memcpy(&value, mData + CAST_SIZE(mPos), sizeof(int64_t));
228
#endif  // SDL_BYTEORDER == SDL_BIG_ENDIAN
229
    }
230
    DEBUGLOG2("readInt64:  " + toStringPrint(CAST_U32(value)),
231
        mPos, str);
232
    mPos += 8;
233
    PacketCounters::incInBytes(8);
234
    return value;
235
}
236
237
uint8_t MessageIn::fromServerDirection(const uint8_t serverDir)
238
{
239
    // Translate from eAthena format
240
    switch (serverDir)
241
    {
242
        case 0:
243
            return 1;
244
        case 1:
245
            return 3;
246
        case 2:
247
            return 2;
248
        case 3:
249
            return 6;
250
        case 4:
251
            return 4;
252
        case 5:
253
            return 12;
254
        case 6:
255
            return 8;
256
        case 7:
257
            return 9;
258
        case 8:
259
            return 8;
260
        default:
261
            logger->log("incorrect direction: %d",
262
                CAST_S32(serverDir));
263
            return 0;
264
    }
265
}
266
267
void MessageIn::readCoordinates(uint16_t &restrict x,
268
                                uint16_t &restrict y,
269
                                uint8_t &restrict direction,
270
                                const char *const str)
271
{
272
    if (mPos + 3 <= mLength)
273
    {
274
        const char *const data = mData + CAST_SIZE(mPos);
275
        uint16_t temp = MAKEWORD(data[1] & 0x00c0, data[0] & 0x00ff);
276
        x = CAST_U16(temp >> 6);
277
        temp = MAKEWORD(data[2] & 0x00f0, data[1] & 0x003f);
278
        y = CAST_U16(temp >> 4);
279
280
        const uint8_t serverDir = CAST_U8(data[2] & 0x000f);
281
        direction = fromServerDirection(serverDir);
282
283
        DEBUGLOG2(std::string("readCoordinates: ").append(toString(
284
            CAST_S32(x))).append(",").append(toString(
285
            CAST_S32(y))).append(",").append(toString(
286
            CAST_S32(serverDir))), mPos, str);
287
    }
288
    else
289
    {
290
        x = 0;
291
        y = 0;
292
        direction = 0;
293
        logger->log("error: wrong readCoordinates packet");
294
    }
295
    mPos += 3;
296
    PacketCounters::incInBytes(3);
297
}
298
299
void MessageIn::readCoordinatePair(uint16_t &restrict srcX,
300
                                   uint16_t &restrict srcY,
301
                                   uint16_t &restrict dstX,
302
                                   uint16_t &restrict dstY,
303
                                   const char *const str)
304
{
305
    if (mPos + 5 <= mLength)
306
    {
307
        const char *const data = mData + CAST_SIZE(mPos);
308
        uint16_t temp = MAKEWORD(data[3], data[2] & 0x000f);
309
        dstX = CAST_U16(temp >> 2);
310
311
        dstY = MAKEWORD(data[4], data[3] & 0x0003);
312
313
        temp = MAKEWORD(data[1], data[0]);
314
        srcX = CAST_U16(temp >> 6);
315
316
        temp = MAKEWORD(data[2], data[1] & 0x003f);
317
        srcY = CAST_U16(temp >> 4);
318
319
        DEBUGLOG2(std::string("readCoordinatePair: ").append(toString(
320
            CAST_S32(srcX))).append(",").append(toString(
321
            CAST_S32(srcY))).append(" ").append(toString(
322
            CAST_S32(dstX))).append(",").append(toString(
323
            CAST_S32(dstY))), mPos, str);
324
    }
325
    else
326
    {
327
        srcX = 0;
328
        srcY = 0;
329
        dstX = 0;
330
        dstY = 0;
331
        logger->log("error: wrong readCoordinatePair packet");
332
    }
333
    mPos += 5;
334
    PacketCounters::incInBytes(5);
335
}
336
337
void MessageIn::skip(const unsigned int length, const char *const str)
338
{
339
    DEBUGLOG2("skip: " + toString(CAST_S32(length)), mPos, str);
340
    mPos += length;
341
    PacketCounters::incInBytes(length);
342
}
343
344
void MessageIn::skipToEnd(const char *const str)
345
{
346
    const int diff = CAST_S32(mLength - mPos);
347
    if (diff != 0)
348
    {
349
        DEBUGLOG2("skip: " + toString(diff), mPos, str);
350
        mPos = mLength;
351
        PacketCounters::incInBytes(diff);
352
    }
353
}
354
355
std::string MessageIn::readString(int length, const char *const dstr)
356
{
357
    // Get string length
358
    if (length < 0)
359
        length = readInt16("len");
360
361
    // Make sure the string isn't erroneous
362
    if (length < 0 || mPos + length > mLength)
363
    {
364
        DEBUGLOG2("readString error", mPos, dstr);
365
        mPos = mLength + 1;
366
        return "";
367
    }
368
369
    // Read the string
370
    const char *const stringBeg = mData + CAST_SIZE(mPos);
371
    const char *const stringEnd
372
        = static_cast<const char *>(memchr(stringBeg, '\0', length));
373
374
    const std::string str(stringBeg, stringEnd != nullptr
375
        ? stringEnd - stringBeg : CAST_SIZE(length));
376
    DEBUGLOG2("readString: " + str, mPos, dstr);
377
    mPos += length;
378
    PacketCounters::incInBytes(length);
379
    return str;
380
}
381
382
std::string MessageIn::readRawString(int length, const char *const dstr)
383
{
384
    // Get string length
385
    if (length < 0)
386
        length = readInt16("len");
387
388
    // Make sure the string isn't erroneous
389
    if (length < 0 || mPos + length > mLength)
390
    {
391
        mPos = mLength + 1;
392
        return "";
393
    }
394
395
    // Read the string
396
    const char *const stringBeg = mData + CAST_SIZE(mPos);
397
    const char *const stringEnd
398
        = static_cast<const char *>(memchr(stringBeg, '\0', length));
399
    std::string str(stringBeg, stringEnd != nullptr
400
        ? stringEnd - stringBeg : CAST_SIZE(length));
401
402
    DEBUGLOG2("readString: " + str, mPos, dstr);
403
404
    if (stringEnd != nullptr)
405
    {
406
        const size_t len2 = CAST_SIZE(length)
407
            - (stringEnd - stringBeg) - 1;
408
        const char *const stringBeg2 = stringEnd + 1;
409
        const char *const stringEnd2
410
            = static_cast<const char *>(memchr(stringBeg2, '\0', len2));
411
        const std::string hiddenPart = std::string(stringBeg2,
412
            stringEnd2 != nullptr ? stringEnd2 - stringBeg2 : len2);
413
        if (hiddenPart.length() > 0)
414
        {
415
            DEBUGLOG2("readString2: " + hiddenPart, mPos, dstr);
416
            return str.append("|").append(hiddenPart);
417
        }
418
    }
419
    mPos += length;
420
    PacketCounters::incInBytes(length);
421
422
    return str;
423
}
424
425
unsigned char *MessageIn::readBytes(int length, const char *const dstr)
426
{
427
    // Get string length
428
    if (length < 0)
429
        length = readInt16("len");
430
431
    // Make sure the string isn't erroneous
432
    if (length < 0 || mPos + length > mLength)
433
    {
434
        DEBUGLOG2("readBytesString error", mPos, dstr);
435
        mPos = mLength + 1;
436
        return nullptr;
437
    }
438
439
    unsigned char *const buf
440
        = new unsigned char[CAST_SIZE(length + 2)];
441
442
    memcpy(buf, mData + CAST_SIZE(mPos), length);
443
    buf[length] = 0;
444
    buf[length + 1] = 0;
445
    mPos += length;
446
447
#ifdef ENABLEDEBUGLOG
448
    std::string str;
449
    for (int f = 0; f < length; f ++)
450
        str.append(strprintf("%02x", CAST_U32(buf[f])));
451
    str += " ";
452
    for (int f = 0; f < length; f ++)
453
    {
454
        if (buf[f] != 0u)
455
            str.append(strprintf("%c", buf[f]));
456
        else
457
            str.append("_");
458
    }
459
    if (dstr != nullptr)
460
        logger->dlog(dstr);
461
    logger->dlog("ReadBytes: " + str);
462
#endif  // ENABLEDEBUGLOG
463
464
    PacketCounters::incInBytes(length);
465
    return buf;
466
}
467
468
}  // namespace Net