]> git.lizzy.rs Git - minetest.git/blob - src/network/networkpacket.cpp
Stop NetworkPacket methods from producing bloated packets
[minetest.git] / src / network / networkpacket.cpp
1 /*
2 Minetest
3 Copyright (C) 2015 nerzhul, Loic Blot <loic.blot@unix-experience.fr>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "networkpacket.h"
21 #include "debug.h"
22 #include "exceptions.h"
23 #include "util/serialize.h"
24
25 NetworkPacket::NetworkPacket(u16 command, u32 datasize, u16 peer_id):
26 m_datasize(datasize), m_read_offset(0), m_command(command), m_peer_id(peer_id)
27 {
28         m_data.resize(m_datasize);
29 }
30
31 NetworkPacket::NetworkPacket(u16 command, u32 datasize):
32 m_datasize(datasize), m_read_offset(0), m_command(command), m_peer_id(0)
33 {
34         m_data.resize(m_datasize);
35 }
36
37 NetworkPacket::~NetworkPacket()
38 {
39         m_data.clear();
40 }
41
42 void NetworkPacket::checkReadOffset(u32 from_offset)
43 {
44         if (from_offset >= m_datasize) {
45                 std::stringstream ss;
46                 ss << "Reading outside packet (offset: " <<
47                                 from_offset << ", packet size: " << getSize() << ")";
48                 throw PacketError(ss.str());
49         }
50 }
51
52 void NetworkPacket::putRawPacket(u8 *data, u32 datasize, u16 peer_id)
53 {
54         // If a m_command is already set, we are rewriting on same packet
55         // This is not permitted
56         assert(m_command == 0);
57
58         m_datasize = datasize - 2;
59         m_peer_id = peer_id;
60
61         // split command and datas
62         m_command = readU16(&data[0]);
63         m_data = std::vector<u8>(&data[2], &data[2 + m_datasize]);
64 }
65
66 char* NetworkPacket::getString(u32 from_offset)
67 {
68         checkReadOffset(from_offset);
69
70         return (char*)&m_data[from_offset];
71 }
72
73 void NetworkPacket::putRawString(const char* src, u32 len)
74 {
75         if (m_read_offset + len > m_datasize) {
76                 m_datasize = m_read_offset + len;
77                 m_data.resize(m_datasize);
78         }
79
80         memcpy(&m_data[m_read_offset], src, len);
81         m_read_offset += len;
82 }
83
84 NetworkPacket& NetworkPacket::operator>>(std::string& dst)
85 {
86         u16 strLen = readU16(&m_data[m_read_offset]);
87         m_read_offset += sizeof(u16);
88
89         dst.clear();
90
91         if (strLen == 0) {
92                 return *this;
93         }
94
95         dst.reserve(strLen);
96         dst.append((char*)&m_data[m_read_offset], strLen);
97
98         m_read_offset += strLen;
99         return *this;
100 }
101
102 NetworkPacket& NetworkPacket::operator<<(std::string src)
103 {
104         u16 msgsize = src.size();
105         if (msgsize > 0xFFFF) {
106                 msgsize = 0xFFFF;
107         }
108
109         *this << msgsize;
110
111         putRawString(src.c_str(), (u32)msgsize);
112
113         return *this;
114 }
115
116 void NetworkPacket::putLongString(std::string src)
117 {
118         u32 msgsize = src.size();
119         if (msgsize > 0xFFFFFFFF) {
120                 msgsize = 0xFFFFFFFF;
121         }
122
123         *this << msgsize;
124
125         putRawString(src.c_str(), msgsize);
126 }
127
128 NetworkPacket& NetworkPacket::operator>>(std::wstring& dst)
129 {
130         u16 strLen = readU16(&m_data[m_read_offset]);
131         m_read_offset += sizeof(u16);
132
133         dst.clear();
134
135         if (strLen == 0) {
136                 return *this;
137         }
138
139         dst.reserve(strLen);
140         for(u16 i=0; i<strLen; i++) {
141                 wchar_t c16 = readU16(&m_data[m_read_offset]);
142                 dst.append(&c16, 1);
143                 m_read_offset += sizeof(u16);
144         }
145
146         return *this;
147 }
148
149 NetworkPacket& NetworkPacket::operator<<(std::wstring src)
150 {
151         u16 msgsize = src.size();
152         if (msgsize > 0xFFFF) {
153                 msgsize = 0xFFFF;
154         }
155
156         *this << msgsize;
157
158         // Write string
159         for (u16 i=0; i<msgsize; i++) {
160                 *this << (u16) src[i];
161         }
162
163         return *this;
164 }
165
166 std::string NetworkPacket::readLongString()
167 {
168         u32 strLen = readU32(&m_data[m_read_offset]);
169         m_read_offset += sizeof(u32);
170
171         if (strLen == 0) {
172                 return "";
173         }
174
175         std::string dst;
176
177         dst.reserve(strLen);
178         dst.append((char*)&m_data[m_read_offset], strLen);
179
180         m_read_offset += strLen;
181
182         return dst;
183 }
184
185 NetworkPacket& NetworkPacket::operator>>(char& dst)
186 {
187         checkReadOffset(m_read_offset);
188
189         dst = readU8(&m_data[m_read_offset]);
190
191         incrOffset<char>();
192         return *this;
193 }
194
195 char NetworkPacket::getChar(u32 offset)
196 {
197         checkReadOffset(offset);
198
199         return readU8(&m_data[offset]);
200 }
201
202 NetworkPacket& NetworkPacket::operator<<(char src)
203 {
204         checkDataSize<u8>();
205
206         writeU8(&m_data[m_read_offset], src);
207
208         incrOffset<char>();
209         return *this;
210 }
211
212 NetworkPacket& NetworkPacket::operator<<(u8 src)
213 {
214         checkDataSize<u8>();
215
216         writeU8(&m_data[m_read_offset], src);
217
218         incrOffset<u8>();
219         return *this;
220 }
221
222 NetworkPacket& NetworkPacket::operator<<(bool src)
223 {
224         checkDataSize<u8>();
225
226         writeU8(&m_data[m_read_offset], src);
227
228         incrOffset<u8>();
229         return *this;
230 }
231
232 NetworkPacket& NetworkPacket::operator<<(u16 src)
233 {
234         checkDataSize<u16>();
235
236         writeU16(&m_data[m_read_offset], src);
237
238         incrOffset<u16>();
239         return *this;
240 }
241
242 NetworkPacket& NetworkPacket::operator<<(u32 src)
243 {
244         checkDataSize<u32>();
245
246         writeU32(&m_data[m_read_offset], src);
247
248         incrOffset<u32>();
249         return *this;
250 }
251
252 NetworkPacket& NetworkPacket::operator<<(u64 src)
253 {
254         checkDataSize<u64>();
255
256         writeU64(&m_data[m_read_offset], src);
257
258         incrOffset<u64>();
259         return *this;
260 }
261
262 NetworkPacket& NetworkPacket::operator<<(float src)
263 {
264         checkDataSize<float>();
265
266         writeF1000(&m_data[m_read_offset], src);
267
268         incrOffset<float>();
269         return *this;
270 }
271
272 NetworkPacket& NetworkPacket::operator>>(bool& dst)
273 {
274         checkReadOffset(m_read_offset);
275
276         dst = readU8(&m_data[m_read_offset]);
277
278         incrOffset<u8>();
279         return *this;
280 }
281
282 NetworkPacket& NetworkPacket::operator>>(u8& dst)
283 {
284         checkReadOffset(m_read_offset);
285
286         dst = readU8(&m_data[m_read_offset]);
287
288         incrOffset<u8>();
289         return *this;
290 }
291
292 u8 NetworkPacket::getU8(u32 offset)
293 {
294         checkReadOffset(offset);
295
296         return readU8(&m_data[offset]);
297 }
298
299 u8* NetworkPacket::getU8Ptr(u32 from_offset)
300 {
301         if (m_datasize == 0) {
302                 return NULL;
303         }
304
305         checkReadOffset(from_offset);
306
307         return (u8*)&m_data[from_offset];
308 }
309
310 NetworkPacket& NetworkPacket::operator>>(u16& dst)
311 {
312         checkReadOffset(m_read_offset);
313
314         dst = readU16(&m_data[m_read_offset]);
315
316         incrOffset<u16>();
317         return *this;
318 }
319
320 u16 NetworkPacket::getU16(u32 from_offset)
321 {
322         checkReadOffset(from_offset);
323
324         return readU16(&m_data[from_offset]);
325 }
326
327 NetworkPacket& NetworkPacket::operator>>(u32& dst)
328 {
329         checkReadOffset(m_read_offset);
330
331         dst = readU32(&m_data[m_read_offset]);
332
333         incrOffset<u32>();
334         return *this;
335 }
336
337 NetworkPacket& NetworkPacket::operator>>(u64& dst)
338 {
339         checkReadOffset(m_read_offset);
340
341         dst = readU64(&m_data[m_read_offset]);
342
343         incrOffset<u64>();
344         return *this;
345 }
346
347 NetworkPacket& NetworkPacket::operator>>(float& dst)
348 {
349         checkReadOffset(m_read_offset);
350
351         dst = readF1000(&m_data[m_read_offset]);
352
353         incrOffset<float>();
354         return *this;
355 }
356
357 NetworkPacket& NetworkPacket::operator>>(v2f& dst)
358 {
359         checkReadOffset(m_read_offset);
360
361         dst = readV2F1000(&m_data[m_read_offset]);
362
363         incrOffset<v2f>();
364         return *this;
365 }
366
367 NetworkPacket& NetworkPacket::operator>>(v3f& dst)
368 {
369         checkReadOffset(m_read_offset);
370
371         dst = readV3F1000(&m_data[m_read_offset]);
372
373         incrOffset<v3f>();
374         return *this;
375 }
376
377 NetworkPacket& NetworkPacket::operator>>(s16& dst)
378 {
379         checkReadOffset(m_read_offset);
380
381         dst = readS16(&m_data[m_read_offset]);
382
383         incrOffset<s16>();
384         return *this;
385 }
386
387 NetworkPacket& NetworkPacket::operator<<(s16 src)
388 {
389         *this << (u16) src;
390         return *this;
391 }
392
393 NetworkPacket& NetworkPacket::operator>>(s32& dst)
394 {
395         checkReadOffset(m_read_offset);
396
397         dst = readS32(&m_data[m_read_offset]);
398
399         incrOffset<s32>();
400         return *this;
401 }
402
403 NetworkPacket& NetworkPacket::operator<<(s32 src)
404 {
405         *this << (u32) src;
406         return *this;
407 }
408
409 NetworkPacket& NetworkPacket::operator>>(v3s16& dst)
410 {
411         checkReadOffset(m_read_offset);
412
413         dst = readV3S16(&m_data[m_read_offset]);
414
415         incrOffset<v3s16>();
416         return *this;
417 }
418
419 NetworkPacket& NetworkPacket::operator>>(v2s32& dst)
420 {
421         dst = readV2S32(&m_data[m_read_offset]);
422
423         incrOffset<v2s32>();
424         return *this;
425 }
426
427 NetworkPacket& NetworkPacket::operator>>(v3s32& dst)
428 {
429         checkReadOffset(m_read_offset);
430
431         dst = readV3S32(&m_data[m_read_offset]);
432
433         incrOffset<v3s32>();
434         return *this;
435 }
436
437 NetworkPacket& NetworkPacket::operator<<(v2f src)
438 {
439         *this << (float) src.X;
440         *this << (float) src.Y;
441         return *this;
442 }
443
444 NetworkPacket& NetworkPacket::operator<<(v3f src)
445 {
446         *this << (float) src.X;
447         *this << (float) src.Y;
448         *this << (float) src.Z;
449         return *this;
450 }
451
452 NetworkPacket& NetworkPacket::operator<<(v3s16 src)
453 {
454         *this << (s16) src.X;
455         *this << (s16) src.Y;
456         *this << (s16) src.Z;
457         return *this;
458 }
459
460 NetworkPacket& NetworkPacket::operator<<(v2s32 src)
461 {
462         *this << (s32) src.X;
463         *this << (s32) src.Y;
464         return *this;
465 }
466
467 NetworkPacket& NetworkPacket::operator<<(v3s32 src)
468 {
469         *this << (s32) src.X;
470         *this << (s32) src.Y;
471         *this << (s32) src.Z;
472         return *this;
473 }
474
475 NetworkPacket& NetworkPacket::operator>>(video::SColor& dst)
476 {
477         checkReadOffset(m_read_offset);
478
479         dst = readARGB8(&m_data[m_read_offset]);
480
481         incrOffset<u32>();
482         return *this;
483 }
484
485 NetworkPacket& NetworkPacket::operator<<(video::SColor src)
486 {
487         checkDataSize<u32>();
488
489         writeU32(&m_data[m_read_offset], src.color);
490
491         incrOffset<u32>();
492         return *this;
493 }
494
495 Buffer<u8> NetworkPacket::oldForgePacket()
496 {
497         Buffer<u8> sb(m_datasize + 2);
498         writeU16(&sb[0], m_command);
499
500         u8* datas = getU8Ptr(0);
501
502         if (datas != NULL)
503                 memcpy(&sb[2], datas, m_datasize);
504         return sb;
505 }