SuperTuxKart
network_string.hpp
Go to the documentation of this file.
1 //
2 // SuperTuxKart - a fun racing game with go-kart
3 // Copyright (C) 2013-2015 SuperTuxKart-Team
4 //
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 3
8 // of the License, or (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 General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 
23 #ifndef NETWORK_STRING_HPP
24 #define NETWORK_STRING_HPP
25 
26 #include "network/protocol.hpp"
27 #include "utils/leak_check.hpp"
28 #include "utils/types.hpp"
29 #include "utils/vec3.hpp"
30 
31 #include "LinearMath/btQuaternion.h"
32 
33 #include "irrString.h"
34 
35 #include <assert.h>
36 #include <stdarg.h>
37 #include <stdexcept>
38 #include <string>
39 #include <string.h>
40 #include <vector>
41 
42 typedef unsigned char uchar;
43 
53 {
54 friend class Crypto;
55 private:
56  LEAK_CHECK();
57 
58 protected:
60  std::vector<uint8_t> m_buffer;
61 
68  mutable int m_current_offset;
69 
70  // ------------------------------------------------------------------------
76  std::string getString(int len) const
77  {
78  if (m_current_offset > (int)m_buffer.size() ||
79  m_current_offset + len > (int)m_buffer.size())
80  throw std::out_of_range("getString out of range.");
81 
82  std::string a(m_buffer.begin() + (m_current_offset ),
83  m_buffer.begin() + (m_current_offset + len));
84  m_current_offset += len;
85  return a;
86  } // getString
87  // ------------------------------------------------------------------------
89  BareNetworkString& addString(const std::string& value)
90  {
91  for (unsigned int i = 0; i < value.size(); i++)
92  m_buffer.push_back((uint8_t)(value[i]));
93  return *this;
94  } // addString
95 
96  // ------------------------------------------------------------------------
98  template<typename T, size_t n>
99  T get() const
100  {
101  int a = n;
102  T result = 0;
103  m_current_offset += n;
104  int offset = m_current_offset -1;
105  while (a--)
106  {
107  result <<= 8; // offset one byte
108  // add the data to result
109  result += m_buffer.at(offset - a);
110  }
111  return result;
112  } // get(int pos)
113  // ------------------------------------------------------------------------
115  template<typename T>
116  T get() const
117  {
118  return m_buffer.at(m_current_offset++);
119  } // get
120 
121 public:
122 
124  BareNetworkString(int capacity=16)
125  {
126  m_buffer.reserve(capacity);
127  m_current_offset = 0;
128  } // BareNetworkString
129 
130  // ------------------------------------------------------------------------
131  BareNetworkString(const std::string &s)
132  {
133  m_current_offset = 0;
134  encodeString(s);
135  } // BareNetworkString
136  // ------------------------------------------------------------------------
138  BareNetworkString(const char *data, int len)
139  {
140  m_current_offset = 0;
141  m_buffer.resize(len);
142  memcpy(m_buffer.data(), data, len);
143  } // BareNetworkString
144 
145  // ------------------------------------------------------------------------
147  void reset() { m_current_offset = 0; }
148  // ------------------------------------------------------------------------
149  BareNetworkString& encodeString16(const irr::core::stringw& value,
150  uint16_t max_len = 65535);
151  // ------------------------------------------------------------------------
152  int decodeString16(irr::core::stringw* out,
153  uint16_t max_len = 65535);
154  // ------------------------------------------------------------------------
155  BareNetworkString& encodeString(const std::string &value);
156  BareNetworkString& encodeString(const irr::core::stringw &value);
157  int decodeString(std::string *out) const;
158  int decodeStringW(irr::core::stringw *out) const;
159  std::string getLogMessage(const std::string &indent="") const;
160  // ------------------------------------------------------------------------
162  std::vector<uint8_t>& getBuffer() { return m_buffer; }
163 
164  // ------------------------------------------------------------------------
166  char* getData() { return (char*)(m_buffer.data()); };
167 
168  // ------------------------------------------------------------------------
170  const char* getData() const { return (char*)(m_buffer.data()); };
171 
172  // ------------------------------------------------------------------------
176  {
177  return (char*)(m_buffer.data()+m_current_offset);
178  } // getCurrentData
179 
180  // ------------------------------------------------------------------------
183  const char* getCurrentData() const
184  {
185  return (char*)(m_buffer.data()+m_current_offset);
186  } // getCurrentData
187  // ------------------------------------------------------------------------
188  int getCurrentOffset() const { return m_current_offset; }
189  // ------------------------------------------------------------------------
191  unsigned int size() const { return (int)m_buffer.size()-m_current_offset; }
192 
193  // ------------------------------------------------------------------------
195  void skip(int n)
196  {
197  m_current_offset += n;
198  assert(m_current_offset >=0 &&
199  m_current_offset <= (int)m_buffer.size());
200  } // skip
201  // ------------------------------------------------------------------------
206  unsigned int getTotalSize() const { return (unsigned int)m_buffer.size(); }
207  // ------------------------------------------------------------------------
208  // All functions related to adding data to a network string
210  BareNetworkString& addUInt8(const uint8_t value)
211  {
212  m_buffer.push_back(value);
213  return *this;
214  } // addUInt8
215 
216  // ------------------------------------------------------------------------
218  BareNetworkString& addChar(const char value)
219  {
220  m_buffer.push_back((uint8_t)(value));
221  return *this;
222  } // addChar
223  // ------------------------------------------------------------------------
225  BareNetworkString& addUInt16(const uint16_t value)
226  {
227  m_buffer.push_back((value >> 8) & 0xff);
228  m_buffer.push_back(value & 0xff);
229  return *this;
230  } // addUInt16
231 
232  // ------------------------------------------------------------------------
234  BareNetworkString& addInt24(const int value)
235  {
236  uint32_t combined = (uint32_t)value & 0xffffff;
237  m_buffer.push_back((combined >> 16) & 0xff);
238  m_buffer.push_back((combined >> 8) & 0xff);
239  m_buffer.push_back(combined & 0xff);
240  return *this;
241  } // addInt24
242 
243  // ------------------------------------------------------------------------
245  BareNetworkString& addUInt32(const uint32_t& value)
246  {
247  m_buffer.push_back((value >> 24) & 0xff);
248  m_buffer.push_back((value >> 16) & 0xff);
249  m_buffer.push_back((value >> 8) & 0xff);
250  m_buffer.push_back( value & 0xff);
251  return *this;
252  } // addUInt32
253 
254  // ------------------------------------------------------------------------
256  BareNetworkString& addUInt64(const uint64_t& value)
257  {
258  m_buffer.push_back((value >> 56) & 0xff);
259  m_buffer.push_back((value >> 48) & 0xff);
260  m_buffer.push_back((value >> 40) & 0xff);
261  m_buffer.push_back((value >> 32) & 0xff);
262  m_buffer.push_back((value >> 24) & 0xff);
263  m_buffer.push_back((value >> 16) & 0xff);
264  m_buffer.push_back((value >> 8) & 0xff);
265  m_buffer.push_back( value & 0xff);
266  return *this;
267  } // addUInt64
268 
269  // ------------------------------------------------------------------------
271  BareNetworkString& addFloat(const float value)
272  {
273  uint32_t *p = (uint32_t*)&value;
274  return addUInt32(*p);
275  } // addFloat
276 
277  // ------------------------------------------------------------------------
281  {
282  m_buffer.insert(m_buffer.end(),
283  value.m_buffer.begin()+value.m_current_offset,
284  value.m_buffer.end() );
285  return *this;
286  } // operator+=
287 
288  // ------------------------------------------------------------------------
291  {
292  return addFloat(f);
293  } // add
294  // ------------------------------------------------------------------------
297  {
298  return addFloat(xyz.getX()).addFloat(xyz.getY()).addFloat(xyz.getZ());
299  } // add
300 
301  // ------------------------------------------------------------------------
303  BareNetworkString& add(const btQuaternion &quat)
304  {
305  return addFloat(quat.getX()).addFloat(quat.getY())
306  .addFloat(quat.getZ()).addFloat(quat.getW());
307  } // add
308  // ------------------------------------------------------------------------
314  {
315  return addUInt32(ticks);
316  } // addTime
317 
318  // Functions related to getting data from a network string
319  // ------------------------------------------------------------------------
321  inline uint64_t getUInt64() const { return get<uint64_t, 8>(); }
322  // ------------------------------------------------------------------------
324  inline uint32_t getUInt32() const { return get<uint32_t, 4>(); }
325  // ------------------------------------------------------------------------
327  inline int getInt24() const
328  {
329  uint32_t combined = get<uint32_t, 3>();
330  if (combined & 0x800000)
331  return (0x1000000 - (int)combined) * -1;
332  else
333  return (int)combined;
334  }
335  // ------------------------------------------------------------------------
337  inline uint32_t getTime() const { return get<uint32_t, 4>(); }
338  // ------------------------------------------------------------------------
340  inline uint16_t getUInt16() const { return get<uint16_t, 2>(); }
341  // ------------------------------------------------------------------------
343  inline int16_t getInt16() const { return get<int16_t, 2>(); }
344  // ------------------------------------------------------------------------
346  inline uint8_t getUInt8() const
347  {
348  return m_buffer.at(m_current_offset++);
349  } // getUInt8
350  // ------------------------------------------------------------------------
352  inline int8_t getInt8() const
353  {
354  return m_buffer.at(m_current_offset++);
355  } // getInt8
356  // ------------------------------------------------------------------------
358  float getFloat() const
359  {
360  uint32_t u = getUInt32();
361  float f;
362  // Doig a "return *(float*)&u;" appears to be more efficient,
363  // but it can create incorrect code on higher optimisation: c++
364  // makes the assumption that pointer of different types never
365  // overlap. So the compiler can assume that the int pointer (&u)
366  // and float pointer do point to different aras, so there read
367  // (*(float*) can be done before the write to u (and then the
368  // write to u is basically a no-op and can be removed, too).
369  // Using a union of int and float is not valid either, there
370  // is no guarantee that writing to the int part of the union
371  // will affect the float part. So, an explicit memcpy is the
372  // more or less only portable guaranteed to be correct way of
373  // converting the int to a float.
374  memcpy(&f, &u, sizeof(float));
375  return f;
376  } // getFloat
377 
378  // ------------------------------------------------------------------------
380  Vec3 getVec3() const
381  {
382  Vec3 r;
383  r.setX(getFloat());
384  r.setY(getFloat());
385  r.setZ(getFloat());
386  return r;
387  } // getVec3
388 
389  // ------------------------------------------------------------------------
391  btQuaternion getQuat() const
392  {
393  btQuaternion q;
394  q.setX(getFloat());
395  q.setY(getFloat());
396  q.setZ(getFloat());
397  q.setW(getFloat());
398  return q;
399  } // getQuat
400  // ------------------------------------------------------------------------
401 
402 }; // class BareNetworkString
403 
404 
405 // ============================================================================
406 
422 {
423 public:
424  static void unitTesting();
425 
429  NetworkString(ProtocolType type, int capacity=16)
430  : BareNetworkString(capacity+1)
431  {
432  m_buffer.push_back(type);
433  } // NetworkString
434 
435  // ------------------------------------------------------------------------
439  NetworkString(const uint8_t *data, int len)
440  : BareNetworkString((char*)data, len)
441  {
442  m_current_offset = 1; // ignore type
443  } // NetworkString
444 
445  // ------------------------------------------------------------------------
447  void clear()
448  {
449  m_buffer.erase(m_buffer.begin() + 1, m_buffer.end());
450  m_current_offset = 1;
451  } // clear
452  // ------------------------------------------------------------------------
455  {
456  return (ProtocolType)(m_buffer.at(0) & ~PROTOCOL_SYNCHRONOUS);
457  } // getProtocolType
458 
459  // ------------------------------------------------------------------------
461  void setSynchronous(bool b)
462  {
463  if(b)
465  else
467  } // setSynchronous
468  // ------------------------------------------------------------------------
470  bool isSynchronous() const
471  {
473  } // isSynchronous
474 
475 }; // class NetworkString
476 
477 
478 #endif // NETWORK_STRING_HPP
BareNetworkString::getVec3
Vec3 getVec3() const
Gets a Vec3.
Definition: network_string.hpp:380
PROTOCOL_SYNCHRONOUS
@ PROTOCOL_SYNCHRONOUS
Flag, indicates synchronous delivery.
Definition: protocol.hpp:51
BareNetworkString::getUInt32
uint32_t getUInt32() const
Returns a unsigned 32 bit integer.
Definition: network_string.hpp:324
NetworkString::setSynchronous
void setSynchronous(bool b)
Sets if this message is to be sent synchronous or asynchronous.
Definition: network_string.hpp:461
BareNetworkString::getUInt64
uint64_t getUInt64() const
Returns a unsigned 64 bit integer.
Definition: network_string.hpp:321
BareNetworkString::BareNetworkString
BareNetworkString(int capacity=16)
Constructor, sets the protocol type of this message.
Definition: network_string.hpp:124
BareNetworkString::getCurrentData
char * getCurrentData()
Returns a byte pointer to the unread remaining content of the network string.
Definition: network_string.hpp:175
NetworkString::isSynchronous
bool isSynchronous() const
Returns if this message is synchronous or not.
Definition: network_string.hpp:470
BareNetworkString::addUInt8
BareNetworkString & addUInt8(const uint8_t value)
Add 8 bit unsigned int.
Definition: network_string.hpp:210
BareNetworkString::add
BareNetworkString & add(float f)
Adds a floating point number.
Definition: network_string.hpp:290
BareNetworkString::getInt16
int16_t getInt16() const
Returns an unsigned 16 bit integer.
Definition: network_string.hpp:343
BareNetworkString::getCurrentData
const char * getCurrentData() const
Returns a byte pointer to the unread remaining content of the network string.
Definition: network_string.hpp:183
BareNetworkString::addChar
BareNetworkString & addChar(const char value)
Adds a single character to the string.
Definition: network_string.hpp:218
NetworkString::NetworkString
NetworkString(ProtocolType type, int capacity=16)
Constructor for a message to be sent.
Definition: network_string.hpp:429
BareNetworkString::getData
char * getData()
Returns a byte pointer to the content of the network string.
Definition: network_string.hpp:166
BareNetworkString
Describes a chain of 8-bit unsigned integers.
Definition: network_string.hpp:53
types.hpp
Declares the general types that are used by the network.
BareNetworkString::getData
const char * getData() const
Returns a byte pointer to the content of the network string.
Definition: network_string.hpp:170
BareNetworkString::addString
BareNetworkString & addString(const std::string &value)
Adds a std::string.
Definition: network_string.hpp:89
BareNetworkString::getInt24
int getInt24() const
Returns a signed 24 bit integer.
Definition: network_string.hpp:327
BareNetworkString::addUInt64
BareNetworkString & addUInt64(const uint64_t &value)
Adds unsigned 64 bit integer.
Definition: network_string.hpp:256
NetworkString::clear
void clear()
Empties the string, but does not reset the pre-allocated size.
Definition: network_string.hpp:447
BareNetworkString::add
BareNetworkString & add(const btQuaternion &quat)
Adds the four components of a quaternion.
Definition: network_string.hpp:303
BareNetworkString::reset
void reset()
Allows one to read a buffer from the beginning again.
Definition: network_string.hpp:147
BareNetworkString::addInt24
BareNetworkString & addInt24(const int value)
Adds signed 24 bit integer.
Definition: network_string.hpp:234
BareNetworkString::decodeString
int decodeString(std::string *out) const
Returns a string at the given position.
Definition: network_string.cpp:104
NetworkString
A new implementation of NetworkString, which has a fixed format: Byte 0: The type of the message,...
Definition: network_string.hpp:422
BareNetworkString::size
unsigned int size() const
Returns the remaining length of the network string.
Definition: network_string.hpp:191
BareNetworkString::getQuat
btQuaternion getQuat() const
Gets a bullet quaternion.
Definition: network_string.hpp:391
BareNetworkString::encodeString16
BareNetworkString & encodeString16(const irr::core::stringw &value, uint16_t max_len=65535)
Encode string with max length of 16bit and utf32, used in motd or chat.
Definition: network_string.cpp:131
BareNetworkString::skip
void skip(int n)
Skips the specified number of bytes when reading.
Definition: network_string.hpp:195
BareNetworkString::m_buffer
std::vector< uint8_t > m_buffer
The actual buffer.
Definition: network_string.hpp:60
BareNetworkString::addTime
BareNetworkString & addTime(int ticks)
Adds a function to add a time ticks value.
Definition: network_string.hpp:313
BareNetworkString::BareNetworkString
BareNetworkString(const char *data, int len)
Initialises the string with a sequence of characters.
Definition: network_string.hpp:138
ProtocolType
ProtocolType
The types that protocols can have.
Definition: protocol.hpp:43
BareNetworkString::get
T get() const
Template to get n bytes from a buffer into a single data type.
Definition: network_string.hpp:99
Vec3
A wrapper around bullets btVector3 to include conventient conversion functions (e....
Definition: vec3.hpp:35
BareNetworkString::addFloat
BareNetworkString & addFloat(const float value)
Adds a 4 byte floating point value.
Definition: network_string.hpp:271
BareNetworkString::getBuffer
std::vector< uint8_t > & getBuffer()
Returns the internal buffer of the network string.
Definition: network_string.hpp:162
NetworkString::unitTesting
static void unitTesting()
Unit testing function.
Definition: network_string.cpp:30
BareNetworkString::encodeString
BareNetworkString & encodeString(const std::string &value)
Adds one byte for the length of the string, and then (up to 255 of) the characters of the given strin...
Definition: network_string.cpp:79
NetworkString::getProtocolType
ProtocolType getProtocolType() const
Returns the protocol type of this message.
Definition: network_string.hpp:454
NetworkString::NetworkString
NetworkString(const uint8_t *data, int len)
Constructor for a received message.
Definition: network_string.hpp:439
BareNetworkString::getFloat
float getFloat() const
Gets a 4 byte floating point value.
Definition: network_string.hpp:358
BareNetworkString::getTotalSize
unsigned int getTotalSize() const
Returns the send size, which is the full length of the buffer.
Definition: network_string.hpp:206
protocol.hpp
Generic protocols declarations.
BareNetworkString::decodeStringW
int decodeStringW(irr::core::stringw *out) const
Returns an irrlicht wide string from the utf8 encoded string at the given position.
Definition: network_string.cpp:120
BareNetworkString::get
T get() const
Another function for n == 1 to surpress warnings in clang.
Definition: network_string.hpp:116
BareNetworkString::getLogMessage
std::string getLogMessage(const std::string &indent="") const
Returns a string representing this message suitable to be printed to stdout or via the Log mechanism.
Definition: network_string.cpp:202
BareNetworkString::getUInt16
uint16_t getUInt16() const
Returns an unsigned 16 bit integer.
Definition: network_string.hpp:340
BareNetworkString::add
BareNetworkString & add(const Vec3 &xyz)
Adds the xyz components of a Vec3 to the string.
Definition: network_string.hpp:296
BareNetworkString::addUInt16
BareNetworkString & addUInt16(const uint16_t value)
Adds 16 bit unsigned int.
Definition: network_string.hpp:225
BareNetworkString::getTime
uint32_t getTime() const
Returns a unsigned 32 bit integer.
Definition: network_string.hpp:337
BareNetworkString::addUInt32
BareNetworkString & addUInt32(const uint32_t &value)
Adds unsigned 32 bit integer.
Definition: network_string.hpp:245
BareNetworkString::getString
std::string getString(int len) const
Returns a part of the network string as a std::string.
Definition: network_string.hpp:76
BareNetworkString::getInt8
int8_t getInt8() const
Returns an unsigned 8-bit integer.
Definition: network_string.hpp:352
BareNetworkString::getUInt8
uint8_t getUInt8() const
Returns an unsigned 8-bit integer.
Definition: network_string.hpp:346
BareNetworkString::m_current_offset
int m_current_offset
To avoid copying the buffer when bytes are deleted (which only happens at the front),...
Definition: network_string.hpp:68
BareNetworkString::operator+=
BareNetworkString & operator+=(BareNetworkString const &value)
Adds the content of another network string.
Definition: network_string.hpp:280