1 ////////////////////////////////////////////////////////////
2 //
3 // SFML - Simple and Fast Multimedia Library
4 // Copyright (C) 2007-2018 Laurent Gomila (laurent@sfml-dev.org)
5 //
6 // This software is provided 'as-is', without any express or implied warranty.
7 // In no event will the authors be held liable for any damages arising from the use of this software.
8 //
9 // Permission is granted to anyone to use this software for any purpose,
10 // including commercial applications, and to alter it and redistribute it freely,
11 // subject to the following restrictions:
12 //
13 // 1. The origin of this software must not be misrepresented;
14 // you must not claim that you wrote the original software.
15 // If you use this software in a product, an acknowledgment
16 // in the product documentation would be appreciated but is not required.
17 //
18 // 2. Altered source versions must be plainly marked as such,
19 // and must not be misrepresented as being the original software.
20 //
21 // 3. This notice may not be removed or altered from any source distribution.
22 //
23 ////////////////////////////////////////////////////////////
24
25 ////////////////////////////////////////////////////////////
26 // Headers
27 ////////////////////////////////////////////////////////////
28 #include <SFML/Network/Packet.hpp>
29 #include <SFML/Network/SocketImpl.hpp>
30 #include <SFML/System/String.hpp>
31 #include <cstring>
32 #include <cwchar>
33
34
35 namespace sf
36 {
37 ////////////////////////////////////////////////////////////
Packet()38 Packet::Packet() :
39 m_readPos(0),
40 m_sendPos(0),
41 m_isValid(true)
42 {
43
44 }
45
46
47 ////////////////////////////////////////////////////////////
~Packet()48 Packet::~Packet()
49 {
50
51 }
52
53
54 ////////////////////////////////////////////////////////////
append(const void * data,std::size_t sizeInBytes)55 void Packet::append(const void* data, std::size_t sizeInBytes)
56 {
57 if (data && (sizeInBytes > 0))
58 {
59 std::size_t start = m_data.size();
60 m_data.resize(start + sizeInBytes);
61 std::memcpy(&m_data[start], data, sizeInBytes);
62 }
63 }
64
65
66 ////////////////////////////////////////////////////////////
clear()67 void Packet::clear()
68 {
69 m_data.clear();
70 m_readPos = 0;
71 m_isValid = true;
72 }
73
74
75 ////////////////////////////////////////////////////////////
getData() const76 const void* Packet::getData() const
77 {
78 return !m_data.empty() ? &m_data[0] : NULL;
79 }
80
81
82 ////////////////////////////////////////////////////////////
getDataSize() const83 std::size_t Packet::getDataSize() const
84 {
85 return m_data.size();
86 }
87
88
89 ////////////////////////////////////////////////////////////
endOfPacket() const90 bool Packet::endOfPacket() const
91 {
92 return m_readPos >= m_data.size();
93 }
94
95
96 ////////////////////////////////////////////////////////////
operator BoolType() const97 Packet::operator BoolType() const
98 {
99 return m_isValid ? &Packet::checkSize : NULL;
100 }
101
102
103 ////////////////////////////////////////////////////////////
operator >>(bool & data)104 Packet& Packet::operator >>(bool& data)
105 {
106 Uint8 value;
107 if (*this >> value)
108 data = (value != 0);
109
110 return *this;
111 }
112
113
114 ////////////////////////////////////////////////////////////
operator >>(Int8 & data)115 Packet& Packet::operator >>(Int8& data)
116 {
117 if (checkSize(sizeof(data)))
118 {
119 data = *reinterpret_cast<const Int8*>(&m_data[m_readPos]);
120 m_readPos += sizeof(data);
121 }
122
123 return *this;
124 }
125
126
127 ////////////////////////////////////////////////////////////
operator >>(Uint8 & data)128 Packet& Packet::operator >>(Uint8& data)
129 {
130 if (checkSize(sizeof(data)))
131 {
132 data = *reinterpret_cast<const Uint8*>(&m_data[m_readPos]);
133 m_readPos += sizeof(data);
134 }
135
136 return *this;
137 }
138
139
140 ////////////////////////////////////////////////////////////
operator >>(Int16 & data)141 Packet& Packet::operator >>(Int16& data)
142 {
143 if (checkSize(sizeof(data)))
144 {
145 data = ntohs(*reinterpret_cast<const Int16*>(&m_data[m_readPos]));
146 m_readPos += sizeof(data);
147 }
148
149 return *this;
150 }
151
152
153 ////////////////////////////////////////////////////////////
operator >>(Uint16 & data)154 Packet& Packet::operator >>(Uint16& data)
155 {
156 if (checkSize(sizeof(data)))
157 {
158 data = ntohs(*reinterpret_cast<const Uint16*>(&m_data[m_readPos]));
159 m_readPos += sizeof(data);
160 }
161
162 return *this;
163 }
164
165
166 ////////////////////////////////////////////////////////////
operator >>(Int32 & data)167 Packet& Packet::operator >>(Int32& data)
168 {
169 if (checkSize(sizeof(data)))
170 {
171 data = ntohl(*reinterpret_cast<const Int32*>(&m_data[m_readPos]));
172 m_readPos += sizeof(data);
173 }
174
175 return *this;
176 }
177
178
179 ////////////////////////////////////////////////////////////
operator >>(Uint32 & data)180 Packet& Packet::operator >>(Uint32& data)
181 {
182 if (checkSize(sizeof(data)))
183 {
184 data = ntohl(*reinterpret_cast<const Uint32*>(&m_data[m_readPos]));
185 m_readPos += sizeof(data);
186 }
187
188 return *this;
189 }
190
191
192 ////////////////////////////////////////////////////////////
operator >>(Int64 & data)193 Packet& Packet::operator >>(Int64& data)
194 {
195 if (checkSize(sizeof(data)))
196 {
197 // Since ntohll is not available everywhere, we have to convert
198 // to network byte order (big endian) manually
199 const Uint8* bytes = reinterpret_cast<const Uint8*>(&m_data[m_readPos]);
200 data = (static_cast<Int64>(bytes[0]) << 56) |
201 (static_cast<Int64>(bytes[1]) << 48) |
202 (static_cast<Int64>(bytes[2]) << 40) |
203 (static_cast<Int64>(bytes[3]) << 32) |
204 (static_cast<Int64>(bytes[4]) << 24) |
205 (static_cast<Int64>(bytes[5]) << 16) |
206 (static_cast<Int64>(bytes[6]) << 8) |
207 (static_cast<Int64>(bytes[7]) );
208 m_readPos += sizeof(data);
209 }
210
211 return *this;
212 }
213
214
215 ////////////////////////////////////////////////////////////
operator >>(Uint64 & data)216 Packet& Packet::operator >>(Uint64& data)
217 {
218 if (checkSize(sizeof(data)))
219 {
220 // Since ntohll is not available everywhere, we have to convert
221 // to network byte order (big endian) manually
222 const Uint8* bytes = reinterpret_cast<const Uint8*>(&m_data[m_readPos]);
223 data = (static_cast<Uint64>(bytes[0]) << 56) |
224 (static_cast<Uint64>(bytes[1]) << 48) |
225 (static_cast<Uint64>(bytes[2]) << 40) |
226 (static_cast<Uint64>(bytes[3]) << 32) |
227 (static_cast<Uint64>(bytes[4]) << 24) |
228 (static_cast<Uint64>(bytes[5]) << 16) |
229 (static_cast<Uint64>(bytes[6]) << 8) |
230 (static_cast<Uint64>(bytes[7]) );
231 m_readPos += sizeof(data);
232 }
233
234 return *this;
235 }
236
237
238 ////////////////////////////////////////////////////////////
operator >>(float & data)239 Packet& Packet::operator >>(float& data)
240 {
241 if (checkSize(sizeof(data)))
242 {
243 data = *reinterpret_cast<const float*>(&m_data[m_readPos]);
244 m_readPos += sizeof(data);
245 }
246
247 return *this;
248 }
249
250
251 ////////////////////////////////////////////////////////////
operator >>(double & data)252 Packet& Packet::operator >>(double& data)
253 {
254 if (checkSize(sizeof(data)))
255 {
256 data = *reinterpret_cast<const double*>(&m_data[m_readPos]);
257 m_readPos += sizeof(data);
258 }
259
260 return *this;
261 }
262
263
264 ////////////////////////////////////////////////////////////
operator >>(char * data)265 Packet& Packet::operator >>(char* data)
266 {
267 // First extract string length
268 Uint32 length = 0;
269 *this >> length;
270
271 if ((length > 0) && checkSize(length))
272 {
273 // Then extract characters
274 std::memcpy(data, &m_data[m_readPos], length);
275 data[length] = '\0';
276
277 // Update reading position
278 m_readPos += length;
279 }
280
281 return *this;
282 }
283
284
285 ////////////////////////////////////////////////////////////
operator >>(std::string & data)286 Packet& Packet::operator >>(std::string& data)
287 {
288 // First extract string length
289 Uint32 length = 0;
290 *this >> length;
291
292 data.clear();
293 if ((length > 0) && checkSize(length))
294 {
295 // Then extract characters
296 data.assign(&m_data[m_readPos], length);
297
298 // Update reading position
299 m_readPos += length;
300 }
301
302 return *this;
303 }
304
305
306 ////////////////////////////////////////////////////////////
operator >>(wchar_t * data)307 Packet& Packet::operator >>(wchar_t* data)
308 {
309 // First extract string length
310 Uint32 length = 0;
311 *this >> length;
312
313 if ((length > 0) && checkSize(length * sizeof(Uint32)))
314 {
315 // Then extract characters
316 for (Uint32 i = 0; i < length; ++i)
317 {
318 Uint32 character = 0;
319 *this >> character;
320 data[i] = static_cast<wchar_t>(character);
321 }
322 data[length] = L'\0';
323 }
324
325 return *this;
326 }
327
328
329 ////////////////////////////////////////////////////////////
operator >>(std::wstring & data)330 Packet& Packet::operator >>(std::wstring& data)
331 {
332 // First extract string length
333 Uint32 length = 0;
334 *this >> length;
335
336 data.clear();
337 if ((length > 0) && checkSize(length * sizeof(Uint32)))
338 {
339 // Then extract characters
340 for (Uint32 i = 0; i < length; ++i)
341 {
342 Uint32 character = 0;
343 *this >> character;
344 data += static_cast<wchar_t>(character);
345 }
346 }
347
348 return *this;
349 }
350
351
352 ////////////////////////////////////////////////////////////
operator >>(String & data)353 Packet& Packet::operator >>(String& data)
354 {
355 // First extract the string length
356 Uint32 length = 0;
357 *this >> length;
358
359 data.clear();
360 if ((length > 0) && checkSize(length * sizeof(Uint32)))
361 {
362 // Then extract characters
363 for (Uint32 i = 0; i < length; ++i)
364 {
365 Uint32 character = 0;
366 *this >> character;
367 data += character;
368 }
369 }
370
371 return *this;
372 }
373
374
375 ////////////////////////////////////////////////////////////
operator <<(bool data)376 Packet& Packet::operator <<(bool data)
377 {
378 *this << static_cast<Uint8>(data);
379 return *this;
380 }
381
382
383 ////////////////////////////////////////////////////////////
operator <<(Int8 data)384 Packet& Packet::operator <<(Int8 data)
385 {
386 append(&data, sizeof(data));
387 return *this;
388 }
389
390
391 ////////////////////////////////////////////////////////////
operator <<(Uint8 data)392 Packet& Packet::operator <<(Uint8 data)
393 {
394 append(&data, sizeof(data));
395 return *this;
396 }
397
398
399 ////////////////////////////////////////////////////////////
operator <<(Int16 data)400 Packet& Packet::operator <<(Int16 data)
401 {
402 Int16 toWrite = htons(data);
403 append(&toWrite, sizeof(toWrite));
404 return *this;
405 }
406
407
408 ////////////////////////////////////////////////////////////
operator <<(Uint16 data)409 Packet& Packet::operator <<(Uint16 data)
410 {
411 Uint16 toWrite = htons(data);
412 append(&toWrite, sizeof(toWrite));
413 return *this;
414 }
415
416
417 ////////////////////////////////////////////////////////////
operator <<(Int32 data)418 Packet& Packet::operator <<(Int32 data)
419 {
420 Int32 toWrite = htonl(data);
421 append(&toWrite, sizeof(toWrite));
422 return *this;
423 }
424
425
426 ////////////////////////////////////////////////////////////
operator <<(Uint32 data)427 Packet& Packet::operator <<(Uint32 data)
428 {
429 Uint32 toWrite = htonl(data);
430 append(&toWrite, sizeof(toWrite));
431 return *this;
432 }
433
434
435 ////////////////////////////////////////////////////////////
operator <<(Int64 data)436 Packet& Packet::operator <<(Int64 data)
437 {
438 // Since htonll is not available everywhere, we have to convert
439 // to network byte order (big endian) manually
440 Uint8 toWrite[] =
441 {
442 static_cast<Uint8>((data >> 56) & 0xFF),
443 static_cast<Uint8>((data >> 48) & 0xFF),
444 static_cast<Uint8>((data >> 40) & 0xFF),
445 static_cast<Uint8>((data >> 32) & 0xFF),
446 static_cast<Uint8>((data >> 24) & 0xFF),
447 static_cast<Uint8>((data >> 16) & 0xFF),
448 static_cast<Uint8>((data >> 8) & 0xFF),
449 static_cast<Uint8>((data ) & 0xFF)
450 };
451 append(&toWrite, sizeof(toWrite));
452 return *this;
453 }
454
455
456 ////////////////////////////////////////////////////////////
operator <<(Uint64 data)457 Packet& Packet::operator <<(Uint64 data)
458 {
459 // Since htonll is not available everywhere, we have to convert
460 // to network byte order (big endian) manually
461 Uint8 toWrite[] =
462 {
463 static_cast<Uint8>((data >> 56) & 0xFF),
464 static_cast<Uint8>((data >> 48) & 0xFF),
465 static_cast<Uint8>((data >> 40) & 0xFF),
466 static_cast<Uint8>((data >> 32) & 0xFF),
467 static_cast<Uint8>((data >> 24) & 0xFF),
468 static_cast<Uint8>((data >> 16) & 0xFF),
469 static_cast<Uint8>((data >> 8) & 0xFF),
470 static_cast<Uint8>((data ) & 0xFF)
471 };
472 append(&toWrite, sizeof(toWrite));
473 return *this;
474 }
475
476
477 ////////////////////////////////////////////////////////////
operator <<(float data)478 Packet& Packet::operator <<(float data)
479 {
480 append(&data, sizeof(data));
481 return *this;
482 }
483
484
485 ////////////////////////////////////////////////////////////
operator <<(double data)486 Packet& Packet::operator <<(double data)
487 {
488 append(&data, sizeof(data));
489 return *this;
490 }
491
492
493 ////////////////////////////////////////////////////////////
operator <<(const char * data)494 Packet& Packet::operator <<(const char* data)
495 {
496 // First insert string length
497 Uint32 length = static_cast<Uint32>(std::strlen(data));
498 *this << length;
499
500 // Then insert characters
501 append(data, length * sizeof(char));
502
503 return *this;
504 }
505
506
507 ////////////////////////////////////////////////////////////
operator <<(const std::string & data)508 Packet& Packet::operator <<(const std::string& data)
509 {
510 // First insert string length
511 Uint32 length = static_cast<Uint32>(data.size());
512 *this << length;
513
514 // Then insert characters
515 if (length > 0)
516 append(data.c_str(), length * sizeof(std::string::value_type));
517
518 return *this;
519 }
520
521
522 ////////////////////////////////////////////////////////////
operator <<(const wchar_t * data)523 Packet& Packet::operator <<(const wchar_t* data)
524 {
525 // First insert string length
526 Uint32 length = static_cast<Uint32>(std::wcslen(data));
527 *this << length;
528
529 // Then insert characters
530 for (const wchar_t* c = data; *c != L'\0'; ++c)
531 *this << static_cast<Uint32>(*c);
532
533 return *this;
534 }
535
536
537 ////////////////////////////////////////////////////////////
operator <<(const std::wstring & data)538 Packet& Packet::operator <<(const std::wstring& data)
539 {
540 // First insert string length
541 Uint32 length = static_cast<Uint32>(data.size());
542 *this << length;
543
544 // Then insert characters
545 if (length > 0)
546 {
547 for (std::wstring::const_iterator c = data.begin(); c != data.end(); ++c)
548 *this << static_cast<Uint32>(*c);
549 }
550
551 return *this;
552 }
553
554
555 ////////////////////////////////////////////////////////////
operator <<(const String & data)556 Packet& Packet::operator <<(const String& data)
557 {
558 // First insert the string length
559 Uint32 length = static_cast<Uint32>(data.getSize());
560 *this << length;
561
562 // Then insert characters
563 if (length > 0)
564 {
565 for (String::ConstIterator c = data.begin(); c != data.end(); ++c)
566 *this << *c;
567 }
568
569 return *this;
570 }
571
572
573 ////////////////////////////////////////////////////////////
checkSize(std::size_t size)574 bool Packet::checkSize(std::size_t size)
575 {
576 m_isValid = m_isValid && (m_readPos + size <= m_data.size());
577
578 return m_isValid;
579 }
580
581
582 ////////////////////////////////////////////////////////////
onSend(std::size_t & size)583 const void* Packet::onSend(std::size_t& size)
584 {
585 size = getDataSize();
586 return getData();
587 }
588
589
590 ////////////////////////////////////////////////////////////
onReceive(const void * data,std::size_t size)591 void Packet::onReceive(const void* data, std::size_t size)
592 {
593 append(data, size);
594 }
595
596 } // namespace sf
597