/src/server/shared/Packets/ByteBuffer.h

https://gitlab.com/tkrokli/TrinityCore_434 · C Header · 776 lines · 610 code · 125 blank · 41 comment · 60 complexity · d683a825be72e51caf34d861770ee8bb MD5 · raw file

  1. /*
  2. * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
  3. * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the
  7. * Free Software Foundation; either version 2 of the License, or (at your
  8. * option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #ifndef _BYTEBUFFER_H
  19. #define _BYTEBUFFER_H
  20. #include "Define.h"
  21. #include "Errors.h"
  22. #include "ByteConverter.h"
  23. #include "Util.h"
  24. #include <exception>
  25. #include <list>
  26. #include <map>
  27. #include <string>
  28. #include <vector>
  29. #include <cstring>
  30. #include <time.h>
  31. #include <cmath>
  32. #include <type_traits>
  33. #include <boost/asio/buffer.hpp>
  34. class MessageBuffer;
  35. // Root of ByteBuffer exception hierarchy
  36. class ByteBufferException : public std::exception
  37. {
  38. public:
  39. ~ByteBufferException() throw() { }
  40. char const* what() const throw() override { return msg_.c_str(); }
  41. protected:
  42. std::string & message() throw() { return msg_; }
  43. private:
  44. std::string msg_;
  45. };
  46. class ByteBufferPositionException : public ByteBufferException
  47. {
  48. public:
  49. ByteBufferPositionException(bool add, size_t pos, size_t size, size_t valueSize);
  50. ~ByteBufferPositionException() throw() { }
  51. };
  52. class ByteBufferSourceException : public ByteBufferException
  53. {
  54. public:
  55. ByteBufferSourceException(size_t pos, size_t size, size_t valueSize);
  56. ~ByteBufferSourceException() throw() { }
  57. };
  58. class ByteBuffer
  59. {
  60. public:
  61. static size_t const DEFAULT_SIZE = 0x1000;
  62. static uint8 const InitialBitPos = 8;
  63. // constructor
  64. ByteBuffer() : _rpos(0), _wpos(0), _bitpos(InitialBitPos), _curbitval(0)
  65. {
  66. _storage.reserve(DEFAULT_SIZE);
  67. }
  68. ByteBuffer(size_t reserve) : _rpos(0), _wpos(0), _bitpos(InitialBitPos), _curbitval(0)
  69. {
  70. _storage.reserve(reserve);
  71. }
  72. ByteBuffer(ByteBuffer&& buf) : _rpos(buf._rpos), _wpos(buf._wpos),
  73. _bitpos(buf._bitpos), _curbitval(buf._curbitval), _storage(std::move(buf._storage)) { }
  74. ByteBuffer(ByteBuffer const& right) : _rpos(right._rpos), _wpos(right._wpos),
  75. _bitpos(right._bitpos), _curbitval(right._curbitval), _storage(right._storage) { }
  76. ByteBuffer(MessageBuffer&& buffer);
  77. ByteBuffer& operator=(ByteBuffer const& right)
  78. {
  79. if (this != &right)
  80. {
  81. _rpos = right._rpos;
  82. _wpos = right._wpos;
  83. _bitpos = right._bitpos;
  84. _curbitval = right._curbitval;
  85. _storage = right._storage;
  86. }
  87. return *this;
  88. }
  89. virtual ~ByteBuffer() { }
  90. void clear()
  91. {
  92. _storage.clear();
  93. _rpos = _wpos = 0;
  94. }
  95. template <typename T> void append(T value)
  96. {
  97. static_assert(std::is_fundamental<T>::value, "append(compound)");
  98. EndianConvert(value);
  99. append((uint8 *)&value, sizeof(value));
  100. }
  101. void FlushBits()
  102. {
  103. if (_bitpos == 8)
  104. return;
  105. _bitpos = 8;
  106. append((uint8 *)&_curbitval, sizeof(uint8));
  107. _curbitval = 0;
  108. }
  109. bool WriteBit(uint32 bit)
  110. {
  111. --_bitpos;
  112. if (bit)
  113. _curbitval |= (1 << (_bitpos));
  114. if (_bitpos == 0)
  115. {
  116. _bitpos = 8;
  117. append((uint8 *)&_curbitval, sizeof(_curbitval));
  118. _curbitval = 0;
  119. }
  120. return (bit != 0);
  121. }
  122. bool ReadBit()
  123. {
  124. ++_bitpos;
  125. if (_bitpos > 7)
  126. {
  127. _bitpos = 0;
  128. _curbitval = read<uint8>();
  129. }
  130. return ((_curbitval >> (7-_bitpos)) & 1) != 0;
  131. }
  132. template <typename T> void WriteBits(T value, size_t bits)
  133. {
  134. for (int32 i = bits-1; i >= 0; --i)
  135. WriteBit((value >> i) & 1);
  136. }
  137. uint32 ReadBits(size_t bits)
  138. {
  139. uint32 value = 0;
  140. for (int32 i = bits-1; i >= 0; --i)
  141. if (ReadBit())
  142. value |= (1 << (i));
  143. return value;
  144. }
  145. // Reads a byte (if needed) in-place
  146. void ReadByteSeq(uint8& b)
  147. {
  148. if (b != 0)
  149. b ^= read<uint8>();
  150. }
  151. void WriteByteSeq(uint8 b)
  152. {
  153. if (b != 0)
  154. append<uint8>(b ^ 1);
  155. }
  156. template <typename T> void put(size_t pos, T value)
  157. {
  158. static_assert(std::is_fundamental<T>::value, "append(compound)");
  159. EndianConvert(value);
  160. put(pos, (uint8 *)&value, sizeof(value));
  161. }
  162. /**
  163. * @name PutBits
  164. * @brief Places specified amount of bits of value at specified position in packet.
  165. * To ensure all bits are correctly written, only call this method after
  166. * bit flush has been performed
  167. * @param pos Position to place the value at, in bits. The entire value must fit in the packet
  168. * It is advised to obtain the position using bitwpos() function.
  169. * @param value Data to write.
  170. * @param bitCount Number of bits to store the value on.
  171. */
  172. template <typename T> void PutBits(size_t pos, T value, uint32 bitCount)
  173. {
  174. if (!bitCount)
  175. throw ByteBufferSourceException((pos + bitCount) / 8, size(), 0);
  176. if (pos + bitCount > size() * 8)
  177. throw ByteBufferPositionException(false, (pos + bitCount) / 8, size(), (bitCount - 1) / 8 + 1);
  178. for (uint32 i = 0; i < bitCount; ++i)
  179. {
  180. size_t wp = (pos + i) / 8;
  181. size_t bit = (pos + i) % 8;
  182. if ((value >> (bitCount - i - 1)) & 1)
  183. _storage[wp] |= 1 << (7 - bit);
  184. else
  185. _storage[wp] &= ~(1 << (7 - bit));
  186. }
  187. }
  188. ByteBuffer &operator<<(uint8 value)
  189. {
  190. append<uint8>(value);
  191. return *this;
  192. }
  193. ByteBuffer &operator<<(uint16 value)
  194. {
  195. append<uint16>(value);
  196. return *this;
  197. }
  198. ByteBuffer &operator<<(uint32 value)
  199. {
  200. append<uint32>(value);
  201. return *this;
  202. }
  203. ByteBuffer &operator<<(uint64 value)
  204. {
  205. append<uint64>(value);
  206. return *this;
  207. }
  208. // signed as in 2e complement
  209. ByteBuffer &operator<<(int8 value)
  210. {
  211. append<int8>(value);
  212. return *this;
  213. }
  214. ByteBuffer &operator<<(int16 value)
  215. {
  216. append<int16>(value);
  217. return *this;
  218. }
  219. ByteBuffer &operator<<(int32 value)
  220. {
  221. append<int32>(value);
  222. return *this;
  223. }
  224. ByteBuffer &operator<<(int64 value)
  225. {
  226. append<int64>(value);
  227. return *this;
  228. }
  229. // floating points
  230. ByteBuffer &operator<<(float value)
  231. {
  232. append<float>(value);
  233. return *this;
  234. }
  235. ByteBuffer &operator<<(double value)
  236. {
  237. append<double>(value);
  238. return *this;
  239. }
  240. ByteBuffer &operator<<(const std::string &value)
  241. {
  242. if (size_t len = value.length())
  243. append((uint8 const*)value.c_str(), len);
  244. append((uint8)0);
  245. return *this;
  246. }
  247. ByteBuffer &operator<<(const char *str)
  248. {
  249. if (size_t len = (str ? strlen(str) : 0))
  250. append((uint8 const*)str, len);
  251. append((uint8)0);
  252. return *this;
  253. }
  254. ByteBuffer &operator>>(bool &value)
  255. {
  256. value = read<char>() > 0 ? true : false;
  257. return *this;
  258. }
  259. ByteBuffer &operator>>(uint8 &value)
  260. {
  261. value = read<uint8>();
  262. return *this;
  263. }
  264. ByteBuffer &operator>>(uint16 &value)
  265. {
  266. value = read<uint16>();
  267. return *this;
  268. }
  269. ByteBuffer &operator>>(uint32 &value)
  270. {
  271. value = read<uint32>();
  272. return *this;
  273. }
  274. ByteBuffer &operator>>(uint64 &value)
  275. {
  276. value = read<uint64>();
  277. return *this;
  278. }
  279. //signed as in 2e complement
  280. ByteBuffer &operator>>(int8 &value)
  281. {
  282. value = read<int8>();
  283. return *this;
  284. }
  285. ByteBuffer &operator>>(int16 &value)
  286. {
  287. value = read<int16>();
  288. return *this;
  289. }
  290. ByteBuffer &operator>>(int32 &value)
  291. {
  292. value = read<int32>();
  293. return *this;
  294. }
  295. ByteBuffer &operator>>(int64 &value)
  296. {
  297. value = read<int64>();
  298. return *this;
  299. }
  300. ByteBuffer &operator>>(float &value)
  301. {
  302. value = read<float>();
  303. if (!std::isfinite(value))
  304. throw ByteBufferException();
  305. return *this;
  306. }
  307. ByteBuffer &operator>>(double &value)
  308. {
  309. value = read<double>();
  310. if (!std::isfinite(value))
  311. throw ByteBufferException();
  312. return *this;
  313. }
  314. ByteBuffer &operator>>(std::string& value)
  315. {
  316. value.clear();
  317. while (rpos() < size()) // prevent crash at wrong string format in packet
  318. {
  319. char c = read<char>();
  320. if (c == 0)
  321. break;
  322. value += c;
  323. }
  324. return *this;
  325. }
  326. uint8& operator[](size_t const pos)
  327. {
  328. if (pos >= size())
  329. throw ByteBufferPositionException(false, pos, 1, size());
  330. return _storage[pos];
  331. }
  332. uint8 const& operator[](size_t const pos) const
  333. {
  334. if (pos >= size())
  335. throw ByteBufferPositionException(false, pos, 1, size());
  336. return _storage[pos];
  337. }
  338. size_t rpos() const { return _rpos; }
  339. size_t rpos(size_t rpos_)
  340. {
  341. _rpos = rpos_;
  342. return _rpos;
  343. }
  344. void rfinish()
  345. {
  346. _rpos = wpos();
  347. }
  348. size_t wpos() const { return _wpos; }
  349. size_t wpos(size_t wpos_)
  350. {
  351. _wpos = wpos_;
  352. return _wpos;
  353. }
  354. /// Returns position of last written bit
  355. size_t bitwpos() const { return _wpos * 8 + 8 - _bitpos; }
  356. size_t bitwpos(size_t newPos)
  357. {
  358. _wpos = newPos / 8;
  359. _bitpos = 8 - (newPos % 8);
  360. return _wpos * 8 + 8 - _bitpos;
  361. }
  362. template<typename T>
  363. void read_skip() { read_skip(sizeof(T)); }
  364. void read_skip(size_t skip)
  365. {
  366. if (_rpos + skip > size())
  367. throw ByteBufferPositionException(false, _rpos, skip, size());
  368. _rpos += skip;
  369. }
  370. template <typename T> T read()
  371. {
  372. T r = read<T>(_rpos);
  373. _rpos += sizeof(T);
  374. return r;
  375. }
  376. template <typename T> T read(size_t pos) const
  377. {
  378. if (pos + sizeof(T) > size())
  379. throw ByteBufferPositionException(false, pos, sizeof(T), size());
  380. T val = *((T const*)&_storage[pos]);
  381. EndianConvert(val);
  382. return val;
  383. }
  384. void read(uint8 *dest, size_t len)
  385. {
  386. if (_rpos + len > size())
  387. throw ByteBufferPositionException(false, _rpos, len, size());
  388. std::memcpy(dest, &_storage[_rpos], len);
  389. _rpos += len;
  390. }
  391. void readPackGUID(uint64& guid)
  392. {
  393. if (rpos() + 1 > size())
  394. throw ByteBufferPositionException(false, _rpos, 1, size());
  395. guid = 0;
  396. uint8 guidmark = 0;
  397. (*this) >> guidmark;
  398. for (int i = 0; i < 8; ++i)
  399. {
  400. if (guidmark & (uint8(1) << i))
  401. {
  402. if (rpos() + 1 > size())
  403. throw ByteBufferPositionException(false, _rpos, 1, size());
  404. uint8 bit;
  405. (*this) >> bit;
  406. guid |= (uint64(bit) << (i * 8));
  407. }
  408. }
  409. }
  410. std::string ReadString(uint32 length)
  411. {
  412. if (!length)
  413. return std::string();
  414. char* buffer = new char[length + 1]();
  415. read((uint8*)buffer, length);
  416. std::string retval = buffer;
  417. delete[] buffer;
  418. return retval;
  419. }
  420. //! Method for writing strings that have their length sent separately in packet
  421. //! without null-terminating the string
  422. void WriteString(std::string const& str)
  423. {
  424. if (size_t len = str.length())
  425. append(str.c_str(), len);
  426. }
  427. uint32 ReadPackedTime()
  428. {
  429. uint32 packedDate = read<uint32>();
  430. tm lt = tm();
  431. lt.tm_min = packedDate & 0x3F;
  432. lt.tm_hour = (packedDate >> 6) & 0x1F;
  433. //lt.tm_wday = (packedDate >> 11) & 7;
  434. lt.tm_mday = ((packedDate >> 14) & 0x3F) + 1;
  435. lt.tm_mon = (packedDate >> 20) & 0xF;
  436. lt.tm_year = ((packedDate >> 24) & 0x1F) + 100;
  437. return uint32(mktime(&lt));
  438. }
  439. ByteBuffer& ReadPackedTime(uint32& time)
  440. {
  441. time = ReadPackedTime();
  442. return *this;
  443. }
  444. uint8* contents()
  445. {
  446. if (_storage.empty())
  447. throw ByteBufferException();
  448. return _storage.data();
  449. }
  450. uint8 const* contents() const
  451. {
  452. if (_storage.empty())
  453. throw ByteBufferException();
  454. return _storage.data();
  455. }
  456. size_t size() const { return _storage.size(); }
  457. bool empty() const { return _storage.empty(); }
  458. void resize(size_t newsize)
  459. {
  460. _storage.resize(newsize, 0);
  461. _rpos = 0;
  462. _wpos = size();
  463. }
  464. void reserve(size_t ressize)
  465. {
  466. if (ressize > size())
  467. _storage.reserve(ressize);
  468. }
  469. void append(const char *src, size_t cnt)
  470. {
  471. return append((const uint8 *)src, cnt);
  472. }
  473. template<class T> void append(const T *src, size_t cnt)
  474. {
  475. return append((const uint8 *)src, cnt * sizeof(T));
  476. }
  477. void append(const uint8 *src, size_t cnt)
  478. {
  479. if (!cnt)
  480. throw ByteBufferSourceException(_wpos, size(), cnt);
  481. if (!src)
  482. throw ByteBufferSourceException(_wpos, size(), cnt);
  483. ASSERT(size() < 10000000);
  484. FlushBits();
  485. if (_storage.size() < _wpos + cnt)
  486. _storage.resize(_wpos + cnt);
  487. std::memcpy(&_storage[_wpos], src, cnt);
  488. _wpos += cnt;
  489. }
  490. void append(const ByteBuffer& buffer)
  491. {
  492. if (buffer.wpos())
  493. append(buffer.contents(), buffer.wpos());
  494. }
  495. // can be used in SMSG_MONSTER_MOVE opcode
  496. void appendPackXYZ(float x, float y, float z)
  497. {
  498. uint32 packed = 0;
  499. packed |= ((int)(x / 0.25f) & 0x7FF);
  500. packed |= ((int)(y / 0.25f) & 0x7FF) << 11;
  501. packed |= ((int)(z / 0.25f) & 0x3FF) << 22;
  502. *this << packed;
  503. }
  504. void appendPackGUID(uint64 guid)
  505. {
  506. uint8 packGUID[8+1];
  507. packGUID[0] = 0;
  508. size_t size = 1;
  509. for (uint8 i = 0;guid != 0;++i)
  510. {
  511. if (guid & 0xFF)
  512. {
  513. packGUID[0] |= uint8(1 << i);
  514. packGUID[size] = uint8(guid & 0xFF);
  515. ++size;
  516. }
  517. guid >>= 8;
  518. }
  519. append(packGUID, size);
  520. }
  521. void AppendPackedTime(time_t time)
  522. {
  523. tm lt;
  524. localtime_r(&time, &lt);
  525. append<uint32>((lt.tm_year - 100) << 24 | lt.tm_mon << 20 | (lt.tm_mday - 1) << 14 | lt.tm_wday << 11 | lt.tm_hour << 6 | lt.tm_min);
  526. }
  527. void put(size_t pos, const uint8 *src, size_t cnt)
  528. {
  529. if (pos + cnt > size())
  530. throw ByteBufferPositionException(true, pos, cnt, size());
  531. if (!src)
  532. throw ByteBufferSourceException(_wpos, size(), cnt);
  533. std::memcpy(&_storage[pos], src, cnt);
  534. }
  535. void print_storage() const;
  536. void textlike() const;
  537. void hexlike() const;
  538. protected:
  539. size_t _rpos, _wpos, _bitpos;
  540. uint8 _curbitval;
  541. std::vector<uint8> _storage;
  542. };
  543. template <typename T>
  544. inline ByteBuffer &operator<<(ByteBuffer &b, std::vector<T> v)
  545. {
  546. b << (uint32)v.size();
  547. for (typename std::vector<T>::iterator i = v.begin(); i != v.end(); ++i)
  548. {
  549. b << *i;
  550. }
  551. return b;
  552. }
  553. template <typename T>
  554. inline ByteBuffer &operator>>(ByteBuffer &b, std::vector<T> &v)
  555. {
  556. uint32 vsize;
  557. b >> vsize;
  558. v.clear();
  559. while (vsize--)
  560. {
  561. T t;
  562. b >> t;
  563. v.push_back(t);
  564. }
  565. return b;
  566. }
  567. template <typename T>
  568. inline ByteBuffer &operator<<(ByteBuffer &b, std::list<T> v)
  569. {
  570. b << (uint32)v.size();
  571. for (typename std::list<T>::iterator i = v.begin(); i != v.end(); ++i)
  572. {
  573. b << *i;
  574. }
  575. return b;
  576. }
  577. template <typename T>
  578. inline ByteBuffer &operator>>(ByteBuffer &b, std::list<T> &v)
  579. {
  580. uint32 vsize;
  581. b >> vsize;
  582. v.clear();
  583. while (vsize--)
  584. {
  585. T t;
  586. b >> t;
  587. v.push_back(t);
  588. }
  589. return b;
  590. }
  591. template <typename K, typename V>
  592. inline ByteBuffer &operator<<(ByteBuffer &b, std::map<K, V> &m)
  593. {
  594. b << (uint32)m.size();
  595. for (typename std::map<K, V>::iterator i = m.begin(); i != m.end(); ++i)
  596. {
  597. b << i->first << i->second;
  598. }
  599. return b;
  600. }
  601. template <typename K, typename V>
  602. inline ByteBuffer &operator>>(ByteBuffer &b, std::map<K, V> &m)
  603. {
  604. uint32 msize;
  605. b >> msize;
  606. m.clear();
  607. while (msize--)
  608. {
  609. K k;
  610. V v;
  611. b >> k >> v;
  612. m.insert(make_pair(k, v));
  613. }
  614. return b;
  615. }
  616. /// @todo Make a ByteBuffer.cpp and move all this inlining to it.
  617. template<> inline std::string ByteBuffer::read<std::string>()
  618. {
  619. std::string tmp;
  620. *this >> tmp;
  621. return tmp;
  622. }
  623. template<>
  624. inline void ByteBuffer::read_skip<char*>()
  625. {
  626. std::string temp;
  627. *this >> temp;
  628. }
  629. template<>
  630. inline void ByteBuffer::read_skip<char const*>()
  631. {
  632. read_skip<char*>();
  633. }
  634. template<>
  635. inline void ByteBuffer::read_skip<std::string>()
  636. {
  637. read_skip<char*>();
  638. }
  639. namespace boost
  640. {
  641. namespace asio
  642. {
  643. inline const_buffers_1 buffer(ByteBuffer const& packet)
  644. {
  645. return buffer(packet.contents(), packet.size());
  646. }
  647. }
  648. }
  649. #endif