GCC Code Coverage Report
Directory: src/ Exec Total Coverage
File: src/net/messageout.cpp Lines: 0 86 0.0 %
Date: 2018-11-12 Branches: 0 74 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/messageout.h"
24
25
#include "logger.h"
26
27
#include "net/net.h"
28
#include "net/packetcounters.h"
29
30
#include "utils/stringutils.h"
31
32
PRAGMA48(GCC diagnostic push)
33
PRAGMA48(GCC diagnostic ignored "-Wshadow")
34
#include <SDL_endian.h>
35
PRAGMA48(GCC diagnostic pop)
36
37
#include "debug.h"
38
39
#ifndef SDL_BIG_ENDIAN
40
#error missing SDL_endian.h
41
#endif  // SDL_BYTEORDER
42
43
extern int itemIdLen;
44
45
namespace Net
46
{
47
48
MessageOut::MessageOut(const int16_t id) :
49
    mData(nullptr),
50
    mDataSize(0),
51
    mPos(0),
52
    mId(id),
53
    mIgnore(false)
54
{
55
    PacketCounters::incOutPackets();
56
    IGNOREDEBUGLOG;
57
    DEBUGLOG2("Send packet", 0, "MessageOut");
58
}
59
60
void MessageOut::writeInt8(const int8_t value, const char *const str)
61
{
62
    expand(1);
63
    mData[mPos] = value;
64
    DEBUGLOG2("writeInt8:  " + toStringPrint(CAST_U32(
65
        CAST_U8(value))),
66
        mPos, str);
67
    mPos += 1;
68
}
69
70
void MessageOut::writeInt16(const int16_t value, const char *const str)
71
{
72
    expand(2);
73
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
74
    int16_t swap = SDL_Swap16(value);
75
    memcpy(mData + CAST_SIZE(mPos), &swap, sizeof(int16_t));
76
#else  // SDL_BYTEORDER == SDL_BIG_ENDIAN
77
78
    memcpy(mData + CAST_SIZE(mPos), &value, sizeof(int16_t));
79
#endif  // SDL_BYTEORDER == SDL_BIG_ENDIAN
80
81
    DEBUGLOG2("writeInt16: " + toStringPrint(CAST_U32(
82
        CAST_U16(value))),
83
        mPos, str);
84
    mPos += 2;
85
}
86
87
void MessageOut::writeInt32(const int32_t value, const char *const str)
88
{
89
    DEBUGLOG2("writeInt32: " + toStringPrint(CAST_U32(value)),
90
        mPos, str);
91
    expand(4);
92
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
93
    int32_t swap = SDL_Swap32(value);
94
    memcpy(mData + CAST_SIZE(mPos), &swap, sizeof(int32_t));
95
#else  // SDL_BYTEORDER == SDL_BIG_ENDIAN
96
97
    memcpy(mData + CAST_SIZE(mPos), &value, sizeof(int32_t));
98
#endif  // SDL_BYTEORDER == SDL_BIG_ENDIAN
99
100
    mPos += 4;
101
}
102
103
void MessageOut::writeItemId(const int32_t value,
104
                             const char *const str)
105
{
106
    if (itemIdLen == 2)
107
        writeInt16(CAST_S16(value), str);
108
    else
109
        writeInt32(value, str);
110
}
111
112
void MessageOut::writeInt64(const int64_t value, const char *const str)
113
{
114
    DEBUGLOG2("writeInt64: " + toStringPrint(CAST_U32(value)),
115
        mPos, str);
116
    expand(8);
117
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
118
    int32_t swap = SDL_Swap64(value);
119
    memcpy(mData + CAST_SIZE(mPos), &swap, sizeof(int64_t));
120
#else  // SDL_BYTEORDER == SDL_BIG_ENDIAN
121
122
    memcpy(mData + CAST_SIZE(mPos), &value, sizeof(int64_t));
123
#endif  // SDL_BYTEORDER == SDL_BIG_ENDIAN
124
125
    mPos += 8;
126
}
127
128
void MessageOut::writeBeingId(const BeingId value, const char *const str)
129
{
130
    writeInt32(toInt(value, int32_t), str);
131
}
132
133
#define LOBYTE(w) (CAST_U8(w))
134
#define HIBYTE(w) (CAST_U8((CAST_U16(w)) >> 8))
135
136
void MessageOut::writeCoordinates(const uint16_t x,
137
                                  const uint16_t y,
138
                                  unsigned char direction,
139
                                  const char *const str)
140
{
141
    DEBUGLOG2(strprintf("writeCoordinates: %u,%u %u",
142
        CAST_U32(x),
143
        CAST_U32(y),
144
        CAST_U32(direction)), mPos, str);
145
    unsigned char *const data = reinterpret_cast<unsigned char*>(mData)
146
        + CAST_SIZE(mPos);
147
    expand(3);
148
    mPos += 3;
149
150
    uint16_t temp = x;
151
    temp <<= 6;
152
    data[0] = 0;
153
    data[1] = 1;
154
    data[2] = 2;
155
    data[0] = HIBYTE(temp);
156
    data[1] = CAST_U8(temp);
157
    temp = y;
158
    temp <<= 4;
159
    data[1] |= HIBYTE(temp);
160
    data[2] = LOBYTE(temp);
161
    direction = toServerDirection(direction);
162
    data[2] |= direction;
163
}
164
165
void MessageOut::writeString(const std::string &string,
166
                             int length,
167
                             const char *const str)
168
{
169
    int stringLength = CAST_S32(string.length());
170
    if (length < 0)
171
    {
172
        // Write the length at the start if not fixed
173
        writeInt16(CAST_S16(stringLength), "len");
174
        length = stringLength;
175
    }
176
    else if (length < stringLength)
177
    {
178
        // Make sure the length of the string is no longer than specified
179
        stringLength = length;
180
    }
181
    expand(length);
182
183
    // Write the actual string
184
    memcpy(mData + CAST_SIZE(mPos), string.c_str(), stringLength);
185
186
    // Pad remaining space with zeros
187
    if (length > stringLength)
188
    {
189
        memset(mData + CAST_SIZE(mPos + stringLength),
190
            '\0',
191
            length - stringLength);
192
    }
193
194
    DEBUGLOG2("writeString: " + string, mPos, str);
195
    mPos += length;
196
}
197
198
void MessageOut::writeStringNoLog(const std::string &string,
199
                                  int length,
200
                                  const char *const str)
201
{
202
    int stringLength = CAST_S32(string.length());
203
    if (length < 0)
204
    {
205
        // Write the length at the start if not fixed
206
        writeInt16(CAST_S16(stringLength), "len");
207
        length = stringLength;
208
    }
209
    else if (length < stringLength)
210
    {
211
        // Make sure the length of the string is no longer than specified
212
        stringLength = length;
213
    }
214
    expand(length);
215
216
    // Write the actual string
217
    memcpy(mData + CAST_SIZE(mPos), string.c_str(), stringLength);
218
219
    // Pad remaining space with zeros
220
    if (length > stringLength)
221
    {
222
        memset(mData + CAST_SIZE(mPos + stringLength),
223
            '\0',
224
            length - stringLength);
225
    }
226
227
    DEBUGLOG2("writeString: ***", mPos, str);
228
    mPos += length;
229
}
230
231
const char *MessageOut::getData() const
232
{
233
    return mData;
234
}
235
236
unsigned int MessageOut::getDataSize() const
237
{
238
    return mDataSize;
239
}
240
241
unsigned char MessageOut::toServerDirection(unsigned char direction)
242
{
243
    // Translate direction to eAthena format
244
    switch (direction)
245
    {
246
        case 1:  // DOWN
247
            direction = 0;
248
            break;
249
        case 3:  // DOWN | LEFT
250
            direction = 1;
251
            break;
252
        case 2:  // LEFT
253
            direction = 2;
254
            break;
255
        case 6:  // LEFT | UP
256
            direction = 3;
257
            break;
258
        case 4:  // UP
259
            direction = 4;
260
            break;
261
        case 12:  // UP | RIGHT
262
            direction = 5;
263
            break;
264
        case 8:  // RIGHT
265
            direction = 6;
266
            break;
267
        case 9:  // RIGHT + DOWN
268
            direction = 7;
269
            break;
270
        default:
271
            // OOPSIE! Impossible or unknown
272
            direction = CAST_U8(-1);
273
            break;
274
    }
275
    return direction;
276
}
277
278
}  // namespace Net