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