Buf.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. /*
  2. * Copyright (c)2013-2020 ZeroTier, Inc.
  3. *
  4. * Use of this software is governed by the Business Source License included
  5. * in the LICENSE.TXT file in the project's root directory.
  6. *
  7. * Change Date: 2024-01-01
  8. *
  9. * On the date above, in accordance with the Business Source License, use
  10. * of this software will be governed by version 2.0 of the Apache License.
  11. */
  12. /****/
  13. #ifndef ZT_BUF_HPP
  14. #define ZT_BUF_HPP
  15. #include "Constants.hpp"
  16. #include "AtomicCounter.hpp"
  17. #include "Utils.hpp"
  18. #include "SharedPtr.hpp"
  19. #include "Mutex.hpp"
  20. #include <cstdint>
  21. #include <cstring>
  22. #include <cstdlib>
  23. // Buffers are 16384 bytes in size because this is the smallest size that can hold any packet
  24. // and is a power of two. It needs to be a power of two because masking is significantly faster
  25. // than integer division modulus.
  26. #define ZT_BUF_MEM_SIZE 0x00004000
  27. #define ZT_BUF_MEM_MASK 0x00003fffU
  28. namespace ZeroTier {
  29. /**
  30. * Buffer and methods for branch-free bounds-checked data assembly and parsing
  31. *
  32. * This implements an extremely fast buffer for packet assembly and parsing that avoids
  33. * branching whenever possible. To be safe it must be used correctly!
  34. *
  35. * The read methods are prefixed by 'r', and write methods with 'w'. All methods take
  36. * an iterator, which is just an int that should be initialized to 0 (or whatever starting
  37. * position is desired). All read methods will advance the iterator regardless of outcome.
  38. *
  39. * Read and write methods fail silently in the event of overflow. They do not corrupt or
  40. * access memory outside the bounds of Buf, but will otherwise produce undefined results.
  41. *
  42. * IT IS THE RESPONSIBILITY OF THE USER of this class to use the readOverflow() and
  43. * writeOverflow() static methods to check the iterator for overflow after each series
  44. * of reads and writes and BEFORE ANY PARSING or other decisions are made on the basis
  45. * of the data obtained from a buffer. Failure to do so can result in bugs due
  46. * to parsing and branching on undefined or corrupt data.
  47. *
  48. * ^^ THIS IS VERY IMPORTANT ^^
  49. *
  50. * A typical packet assembly consists of repeated calls to the write methods followed by
  51. * a check to writeOverflow() before final packet armoring and transport. A typical packet
  52. * disassembly and parsing consists of a series of read calls to obtain the packet's
  53. * fields followed by a call to readOverflow() to check that these fields are valid. The
  54. * packet is discarded if readOverflow() returns true. Some packet parsers may make
  55. * additional reads and in this case readOverflow() must be checked after each set of
  56. * reads to ensure that overflow did not occur.
  57. *
  58. * Buf uses a lock-free pool for extremely fast allocation and deallocation.
  59. */
  60. class Buf
  61. {
  62. friend class SharedPtr<Buf>;
  63. private:
  64. // Direct construction isn't allowed; use get().
  65. ZT_ALWAYS_INLINE Buf()
  66. {}
  67. ZT_ALWAYS_INLINE Buf(const Buf &b)
  68. {}
  69. public:
  70. static void operator delete(void *ptr,std::size_t sz);
  71. /**
  72. * Get obtains a buffer from the pool or allocates a new buffer if the pool is empty
  73. *
  74. * @return Buffer
  75. */
  76. static SharedPtr<Buf> get();
  77. /**
  78. * Free buffers in the pool
  79. *
  80. * New buffers will be created and the pool repopulated if get() is called
  81. * and outstanding buffers will still be returned to the pool. This just
  82. * frees buffers currently held in reserve.
  83. */
  84. static void freePool();
  85. /**
  86. * Check for overflow beyond the size of the buffer
  87. *
  88. * This is used to check for overflow when writing. It returns true if the iterator
  89. * has passed beyond the capacity of the buffer.
  90. *
  91. * @param ii Iterator to check
  92. * @return True if iterator has read past the size of the buffer
  93. */
  94. static ZT_ALWAYS_INLINE bool writeOverflow(const int &ii)
  95. { return ((ii - ZT_BUF_MEM_SIZE) > 0); }
  96. /**
  97. * Check for overflow beyond the size of the data that should be in the buffer
  98. *
  99. * This is used to check for overflow when reading, with the second argument being the
  100. * size of the meaningful data actually present in the buffer.
  101. *
  102. * @param ii Iterator to check
  103. * @param size Size of data that should be in buffer
  104. * @return True if iterator has read past the size of the data
  105. */
  106. static ZT_ALWAYS_INLINE bool readOverflow(const int &ii,const unsigned int size)
  107. { return ((ii - (int)size) > 0); }
  108. ////////////////////////////////////////////////////////////////////////////
  109. // Read methods
  110. ////////////////////////////////////////////////////////////////////////////
  111. /**
  112. * Read a byte
  113. *
  114. * @param ii Iterator
  115. * @return Byte (undefined on overflow)
  116. */
  117. ZT_ALWAYS_INLINE uint8_t rI8(int &ii) const
  118. {
  119. const unsigned int s = (unsigned int)ii++;
  120. return data[s & ZT_BUF_MEM_MASK];
  121. }
  122. /**
  123. * Read a 16-bit integer
  124. *
  125. * @param ii Integer
  126. * @return Integer (undefined on overflow)
  127. */
  128. ZT_ALWAYS_INLINE uint16_t rI16(int &ii) const
  129. {
  130. const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
  131. ii += 2;
  132. #ifdef ZT_NO_UNALIGNED_ACCESS
  133. return (
  134. ((uint16_t)data[s] << 8U) |
  135. (uint16_t)data[s + 1]);
  136. #else
  137. return Utils::ntoh(*reinterpret_cast<const uint16_t *>(data + s));
  138. #endif
  139. }
  140. /**
  141. * Read a 32-bit integer
  142. *
  143. * @param ii Integer
  144. * @return Integer (undefined on overflow)
  145. */
  146. ZT_ALWAYS_INLINE uint32_t rI32(int &ii) const
  147. {
  148. const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
  149. ii += 4;
  150. #ifdef ZT_NO_UNALIGNED_ACCESS
  151. return (
  152. ((uint32_t)data[s] << 24U) |
  153. ((uint32_t)data[s + 1] << 16U) |
  154. ((uint32_t)data[s + 2] << 8U) |
  155. (uint32_t)data[s + 3]);
  156. #else
  157. return Utils::ntoh(*reinterpret_cast<const uint32_t *>(data + s));
  158. #endif
  159. }
  160. /**
  161. * Read a 64-bit integer
  162. *
  163. * @param ii Integer
  164. * @return Integer (undefined on overflow)
  165. */
  166. ZT_ALWAYS_INLINE uint64_t rI64(int &ii) const
  167. {
  168. const unsigned int s = (unsigned int)ii & ZT_BUF_MEM_MASK;
  169. ii += 8;
  170. #ifdef ZT_NO_UNALIGNED_ACCESS
  171. return (
  172. ((uint64_t)data[s] << 56U) |
  173. ((uint64_t)data[s + 1] << 48U) |
  174. ((uint64_t)data[s + 2] << 40U) |
  175. ((uint64_t)data[s + 3] << 32U) |
  176. ((uint64_t)data[s + 4] << 24U) |
  177. ((uint64_t)data[s + 5] << 16U) |
  178. ((uint64_t)data[s + 6] << 8U) |
  179. (uint64_t)data[s + 7]);
  180. #else
  181. return Utils::ntoh(*reinterpret_cast<const uint64_t *>(data + s));
  182. #endif
  183. }
  184. /**
  185. * Read an object supporting the marshal/unmarshal interface
  186. *
  187. * If the return value is negative the object's state is undefined. A return value of
  188. * zero typically also indicates a problem, though this may depend on the object type.
  189. *
  190. * Since objects may be invalid even if there is no overflow, it's important to check
  191. * the return value of this function in all cases and discard invalid packets as it
  192. * indicates.
  193. *
  194. * @tparam T Object type
  195. * @param ii Iterator
  196. * @param obj Object to read
  197. * @return Bytes read or a negative value on unmarshal error (passed from object) or overflow
  198. */
  199. template<typename T>
  200. ZT_ALWAYS_INLINE int rO(int &ii,T &obj) const
  201. {
  202. if (ii < ZT_BUF_MEM_SIZE) {
  203. int ms = obj.unmarshal(data + ii,ZT_BUF_MEM_SIZE - ii);
  204. if (ms > 0)
  205. ii += ms;
  206. return ms;
  207. }
  208. return -1;
  209. }
  210. /**
  211. * Read a C-style string from the buffer, making a copy and advancing the iterator
  212. *
  213. * Use this if the buffer's memory may get changed between reading and processing
  214. * what is read.
  215. *
  216. * @param ii Iterator
  217. * @param buf Buffer to receive string
  218. * @param bufSize Capacity of buffer in bytes
  219. * @return Pointer to buf or NULL on overflow or error
  220. */
  221. ZT_ALWAYS_INLINE char *rS(int &ii,char *const buf,const unsigned int bufSize) const
  222. {
  223. const char *const s = (const char *)(data + ii);
  224. const int sii = ii;
  225. while (ii < ZT_BUF_MEM_SIZE) {
  226. if (data[ii++] == 0) {
  227. memcpy(buf,s,ii - sii);
  228. return buf;
  229. }
  230. }
  231. return nullptr;
  232. }
  233. /**
  234. * Obtain a pointer to a C-style string in the buffer without copying and advance the iterator
  235. *
  236. * The iterator is advanced even if this fails and returns NULL so that readOverflow()
  237. * will indicate that an overflow occurred. As with other reads the string's contents are
  238. * undefined if readOverflow() returns true.
  239. *
  240. * This version avoids a copy and so is faster if the buffer won't be modified between
  241. * reading and processing.
  242. *
  243. * @param ii Iterator
  244. * @return Pointer to null-terminated C-style string or NULL on overflow or error
  245. */
  246. ZT_ALWAYS_INLINE const char *rSnc(int &ii) const
  247. {
  248. const char *const s = (const char *)(data + ii);
  249. while (ii < ZT_BUF_MEM_SIZE) {
  250. if (data[ii++] == 0)
  251. return s;
  252. }
  253. return nullptr;
  254. }
  255. /**
  256. * Read a byte array from the buffer, making a copy and advancing the iterator
  257. *
  258. * Use this if the buffer's memory may get changed between reading and processing
  259. * what is read.
  260. *
  261. * @param ii Iterator
  262. * @param bytes Buffer to contain data to read
  263. * @param len Length of buffer
  264. * @return Pointer to data or NULL on overflow or error
  265. */
  266. ZT_ALWAYS_INLINE void *rB(int &ii,void *bytes,unsigned int len) const
  267. {
  268. const void *const b = (const void *)(data + ii);
  269. if ((ii += (int)len) <= ZT_BUF_MEM_SIZE) {
  270. memcpy(bytes,b,len);
  271. return bytes;
  272. }
  273. return nullptr;
  274. }
  275. /**
  276. * Obtain a pointer to a field in the buffer without copying and advance the iterator
  277. *
  278. * The iterator is advanced even if this fails and returns NULL so that readOverflow()
  279. * will indicate that an overflow occurred.
  280. *
  281. * This version avoids a copy and so is faster if the buffer won't be modified between
  282. * reading and processing.
  283. *
  284. * @param ii Iterator
  285. * @param len Length of data field to obtain a pointer to
  286. * @return Pointer to field or NULL on overflow
  287. */
  288. ZT_ALWAYS_INLINE const void *rBnc(int &ii,unsigned int len) const
  289. {
  290. const void *const b = (const void *)(data + ii);
  291. return ((ii += (int)len) <= ZT_BUF_MEM_SIZE) ? b : nullptr;
  292. }
  293. ////////////////////////////////////////////////////////////////////////////
  294. // Write methods
  295. ////////////////////////////////////////////////////////////////////////////
  296. /**
  297. * Write a byte
  298. *
  299. * @param ii Iterator
  300. * @param n Byte
  301. */
  302. ZT_ALWAYS_INLINE void wI(int &ii,uint8_t n)
  303. {
  304. const unsigned int s = (unsigned int)ii++;
  305. data[s & ZT_BUF_MEM_MASK] = n;
  306. }
  307. /**
  308. * Write a 16-bit integer in big-endian byte order
  309. *
  310. * @param ii Iterator
  311. * @param n Integer
  312. */
  313. ZT_ALWAYS_INLINE void wI(int &ii,uint16_t n)
  314. {
  315. const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK;
  316. ii += 2;
  317. #ifdef ZT_NO_UNALIGNED_ACCESS
  318. data[s] = (uint8_t)(n >> 8U);
  319. data[s + 1] = (uint8_t)n;
  320. #else
  321. *reinterpret_cast<uint16_t *>(data + s) = Utils::hton(n);
  322. #endif
  323. }
  324. /**
  325. * Write a 32-bit integer in big-endian byte order
  326. *
  327. * @param ii Iterator
  328. * @param n Integer
  329. */
  330. ZT_ALWAYS_INLINE void wI(int &ii,uint32_t n)
  331. {
  332. const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK;
  333. ii += 4;
  334. #ifdef ZT_NO_UNALIGNED_ACCESS
  335. data[s] = (uint8_t)(n >> 24U);
  336. data[s + 1] = (uint8_t)(n >> 16U);
  337. data[s + 2] = (uint8_t)(n >> 8U);
  338. data[s + 3] = (uint8_t)n;
  339. #else
  340. *reinterpret_cast<uint32_t *>(data + s) = Utils::hton(n);
  341. #endif
  342. }
  343. /**
  344. * Write a 64-bit integer in big-endian byte order
  345. *
  346. * @param ii Iterator
  347. * @param n Integer
  348. */
  349. ZT_ALWAYS_INLINE void wI(int &ii,uint64_t n)
  350. {
  351. const unsigned int s = ((unsigned int)ii) & ZT_BUF_MEM_MASK;
  352. ii += 8;
  353. #ifdef ZT_NO_UNALIGNED_ACCESS
  354. data[s] = (uint8_t)(n >> 56U);
  355. data[s + 1] = (uint8_t)(n >> 48U);
  356. data[s + 2] = (uint8_t)(n >> 40U);
  357. data[s + 3] = (uint8_t)(n >> 32U);
  358. data[s + 4] = (uint8_t)(n >> 24U);
  359. data[s + 5] = (uint8_t)(n >> 16U);
  360. data[s + 6] = (uint8_t)(n >> 8U);
  361. data[s + 7] = (uint8_t)n;
  362. #else
  363. *reinterpret_cast<uint64_t *>(data + s) = Utils::hton(n);
  364. #endif
  365. }
  366. /**
  367. * Write an object implementing the marshal interface
  368. *
  369. * @tparam T Object type
  370. * @param ii Iterator
  371. * @param t Object to write
  372. */
  373. template<typename T>
  374. ZT_ALWAYS_INLINE void wO(int &ii,T &t)
  375. {
  376. const unsigned int s = (unsigned int)ii;
  377. if ((s + T::marshalSizeMax()) <= ZT_BUF_MEM_SIZE) {
  378. int ms = t.marshal(data + s);
  379. if (ms > 0)
  380. ii += ms;
  381. } else {
  382. ii += T::marshalSizeMax(); // mark as overflowed even if we didn't do anything
  383. }
  384. }
  385. /**
  386. * Write a C-style null-terminated string (including the trailing zero)
  387. *
  388. * @param ii Iterator
  389. * @param s String to write (writes an empty string if this is NULL)
  390. */
  391. ZT_ALWAYS_INLINE void wS(int &ii,const char *s)
  392. {
  393. if (s) {
  394. char c;
  395. do {
  396. c = *(s++);
  397. wI(ii,(uint8_t)c);
  398. } while (c);
  399. } else {
  400. wI(ii,(uint8_t)0);
  401. }
  402. }
  403. /**
  404. * Write a byte array
  405. *
  406. * @param ii Iterator
  407. * @param bytes Bytes to write
  408. * @param len Size of data in bytes
  409. */
  410. ZT_ALWAYS_INLINE void wB(int &ii,const void *const bytes,const unsigned int len)
  411. {
  412. unsigned int s = (unsigned int)ii;
  413. if ((ii += (int)len) <= ZT_BUF_MEM_SIZE)
  414. memcpy(data + s,bytes,len);
  415. }
  416. ////////////////////////////////////////////////////////////////////////////
  417. ZT_ALWAYS_INLINE Buf &operator=(const Buf &b)
  418. {
  419. if (&b != this)
  420. memcpy(data,b.data,ZT_BUF_MEM_SIZE);
  421. return *this;
  422. }
  423. /**
  424. * Raw buffer
  425. *
  426. * The extra eight bytes permit silent overflow of integer types without reading or writing
  427. * beyond Buf's memory and without branching or extra masks. They can be ignored otherwise.
  428. */
  429. uint8_t data[ZT_BUF_MEM_SIZE + 8];
  430. private:
  431. volatile uintptr_t __nextInPool;
  432. AtomicCounter __refCount;
  433. };
  434. } // namespace ZeroTier
  435. #endif