Utils.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875
  1. /*
  2. * Copyright (c)2019 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: 2026-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_UTILS_HPP
  14. #define ZT_UTILS_HPP
  15. #include <algorithm>
  16. #include <map>
  17. #include <stdexcept>
  18. #include <stdint.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <string>
  23. #include <time.h>
  24. #include <vector>
  25. #if defined(__FreeBSD__)
  26. #include <sys/endian.h>
  27. #endif
  28. #include "Constants.hpp"
  29. #if __BYTE_ORDER == __LITTLE_ENDIAN
  30. #define ZT_CONST_TO_BE_UINT16(x) ((uint16_t)((uint16_t)((uint16_t)(x) << 8U) | (uint16_t)((uint16_t)(x) >> 8U)))
  31. #define ZT_CONST_TO_BE_UINT64(x) \
  32. ((((uint64_t)(x) & 0x00000000000000ffULL) << 56U) | (((uint64_t)(x) & 0x000000000000ff00ULL) << 40U) | (((uint64_t)(x) & 0x0000000000ff0000ULL) << 24U) | (((uint64_t)(x) & 0x00000000ff000000ULL) << 8U) \
  33. | (((uint64_t)(x) & 0x000000ff00000000ULL) >> 8U) | (((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24U) | (((uint64_t)(x) & 0x00ff000000000000ULL) >> 40U) | (((uint64_t)(x) & 0xff00000000000000ULL) >> 56U))
  34. #else
  35. #define ZT_CONST_TO_BE_UINT16(x) ((uint16_t)(x))
  36. #define ZT_CONST_TO_BE_UINT64(x) ((uint64_t)(x))
  37. #endif
  38. #define ZT_ROR64(x, r) (((x) >> (r)) | ((x) << (64 - (r))))
  39. #define ZT_ROL64(x, r) (((x) << (r)) | ((x) >> (64 - (r))))
  40. #define ZT_ROR32(x, r) (((x) >> (r)) | ((x) << (32 - (r))))
  41. #define ZT_ROL32(x, r) (((x) << (r)) | ((x) >> (32 - (r))))
  42. namespace ZeroTier {
  43. /**
  44. * Miscellaneous utility functions and global constants
  45. */
  46. class Utils {
  47. public:
  48. static const uint64_t ZERO256[4];
  49. #ifdef ZT_ARCH_ARM_HAS_NEON
  50. struct ARMCapabilities {
  51. ARMCapabilities() noexcept;
  52. bool aes;
  53. bool crc32;
  54. bool pmull;
  55. bool sha1;
  56. bool sha2;
  57. };
  58. static const ARMCapabilities ARMCAP;
  59. #endif
  60. #ifdef ZT_ARCH_X64
  61. struct CPUIDRegisters {
  62. CPUIDRegisters() noexcept;
  63. bool rdrand;
  64. bool aes;
  65. bool avx;
  66. bool vaes; // implies AVX
  67. bool vpclmulqdq; // implies AVX
  68. bool avx2;
  69. bool avx512f;
  70. bool sha;
  71. bool fsrm;
  72. };
  73. static const CPUIDRegisters CPUID;
  74. #endif
  75. /**
  76. * Compute the log2 (most significant bit set) of a 32-bit integer
  77. *
  78. * @param v Integer to compute
  79. * @return log2 or 0 if v is 0
  80. */
  81. static inline unsigned int log2(uint32_t v)
  82. {
  83. uint32_t r = (v > 0xffff) << 4;
  84. v >>= r;
  85. uint32_t shift = (v > 0xff) << 3;
  86. v >>= shift;
  87. r |= shift;
  88. shift = (v > 0xf) << 2;
  89. v >>= shift;
  90. r |= shift;
  91. shift = (v > 0x3) << 1;
  92. v >>= shift;
  93. r |= shift;
  94. r |= (v >> 1);
  95. return (unsigned int)r;
  96. }
  97. /**
  98. * Perform a time-invariant binary comparison
  99. *
  100. * @param a First binary string
  101. * @param b Second binary string
  102. * @param len Length of strings
  103. * @return True if strings are equal
  104. */
  105. static inline bool secureEq(const void* a, const void* b, unsigned int len)
  106. {
  107. uint8_t diff = 0;
  108. for (unsigned int i = 0; i < len; ++i) {
  109. diff |= ((reinterpret_cast<const uint8_t*>(a))[i] ^ (reinterpret_cast<const uint8_t*>(b))[i]);
  110. }
  111. return (diff == 0);
  112. }
  113. /**
  114. * Securely zero memory, avoiding compiler optimizations and such
  115. */
  116. static void burn(void* ptr, unsigned int len);
  117. /**
  118. * @param n Number to convert
  119. * @param s Buffer, at least 24 bytes in size
  120. * @return String containing 'n' in base 10 form
  121. */
  122. static char* decimal(unsigned long n, char s[24]);
  123. static inline char* hex(uint64_t i, char s[17])
  124. {
  125. s[0] = HEXCHARS[(i >> 60) & 0xf];
  126. s[1] = HEXCHARS[(i >> 56) & 0xf];
  127. s[2] = HEXCHARS[(i >> 52) & 0xf];
  128. s[3] = HEXCHARS[(i >> 48) & 0xf];
  129. s[4] = HEXCHARS[(i >> 44) & 0xf];
  130. s[5] = HEXCHARS[(i >> 40) & 0xf];
  131. s[6] = HEXCHARS[(i >> 36) & 0xf];
  132. s[7] = HEXCHARS[(i >> 32) & 0xf];
  133. s[8] = HEXCHARS[(i >> 28) & 0xf];
  134. s[9] = HEXCHARS[(i >> 24) & 0xf];
  135. s[10] = HEXCHARS[(i >> 20) & 0xf];
  136. s[11] = HEXCHARS[(i >> 16) & 0xf];
  137. s[12] = HEXCHARS[(i >> 12) & 0xf];
  138. s[13] = HEXCHARS[(i >> 8) & 0xf];
  139. s[14] = HEXCHARS[(i >> 4) & 0xf];
  140. s[15] = HEXCHARS[i & 0xf];
  141. s[16] = (char)0;
  142. return s;
  143. }
  144. static inline char* hex10(uint64_t i, char s[11])
  145. {
  146. s[0] = HEXCHARS[(i >> 36) & 0xf];
  147. s[1] = HEXCHARS[(i >> 32) & 0xf];
  148. s[2] = HEXCHARS[(i >> 28) & 0xf];
  149. s[3] = HEXCHARS[(i >> 24) & 0xf];
  150. s[4] = HEXCHARS[(i >> 20) & 0xf];
  151. s[5] = HEXCHARS[(i >> 16) & 0xf];
  152. s[6] = HEXCHARS[(i >> 12) & 0xf];
  153. s[7] = HEXCHARS[(i >> 8) & 0xf];
  154. s[8] = HEXCHARS[(i >> 4) & 0xf];
  155. s[9] = HEXCHARS[i & 0xf];
  156. s[10] = (char)0;
  157. return s;
  158. }
  159. static inline char* hex(uint32_t i, char s[9])
  160. {
  161. s[0] = HEXCHARS[(i >> 28) & 0xf];
  162. s[1] = HEXCHARS[(i >> 24) & 0xf];
  163. s[2] = HEXCHARS[(i >> 20) & 0xf];
  164. s[3] = HEXCHARS[(i >> 16) & 0xf];
  165. s[4] = HEXCHARS[(i >> 12) & 0xf];
  166. s[5] = HEXCHARS[(i >> 8) & 0xf];
  167. s[6] = HEXCHARS[(i >> 4) & 0xf];
  168. s[7] = HEXCHARS[i & 0xf];
  169. s[8] = (char)0;
  170. return s;
  171. }
  172. static inline char* hex(uint16_t i, char s[5])
  173. {
  174. s[0] = HEXCHARS[(i >> 12) & 0xf];
  175. s[1] = HEXCHARS[(i >> 8) & 0xf];
  176. s[2] = HEXCHARS[(i >> 4) & 0xf];
  177. s[3] = HEXCHARS[i & 0xf];
  178. s[4] = (char)0;
  179. return s;
  180. }
  181. static inline char* hex(uint8_t i, char s[3])
  182. {
  183. s[0] = HEXCHARS[(i >> 4) & 0xf];
  184. s[1] = HEXCHARS[i & 0xf];
  185. s[2] = (char)0;
  186. return s;
  187. }
  188. static inline char* hex(const void* d, unsigned int l, char* s)
  189. {
  190. char* const save = s;
  191. for (unsigned int i = 0; i < l; ++i) {
  192. const unsigned int b = reinterpret_cast<const uint8_t*>(d)[i];
  193. *(s++) = HEXCHARS[b >> 4];
  194. *(s++) = HEXCHARS[b & 0xf];
  195. }
  196. *s = (char)0;
  197. return save;
  198. }
  199. static inline unsigned int unhex(const char* h, void* buf, unsigned int buflen)
  200. {
  201. unsigned int l = 0;
  202. while (l < buflen) {
  203. uint8_t hc = *(reinterpret_cast<const uint8_t*>(h++));
  204. if (! hc) {
  205. break;
  206. }
  207. uint8_t c = 0;
  208. if ((hc >= 48) && (hc <= 57)) { // 0..9
  209. c = hc - 48;
  210. }
  211. else if ((hc >= 97) && (hc <= 102)) { // a..f
  212. c = hc - 87;
  213. }
  214. else if ((hc >= 65) && (hc <= 70)) { // A..F
  215. c = hc - 55;
  216. }
  217. hc = *(reinterpret_cast<const uint8_t*>(h++));
  218. if (! hc) {
  219. break;
  220. }
  221. c <<= 4;
  222. if ((hc >= 48) && (hc <= 57)) {
  223. c |= hc - 48;
  224. }
  225. else if ((hc >= 97) && (hc <= 102)) {
  226. c |= hc - 87;
  227. }
  228. else if ((hc >= 65) && (hc <= 70)) {
  229. c |= hc - 55;
  230. }
  231. reinterpret_cast<uint8_t*>(buf)[l++] = c;
  232. }
  233. return l;
  234. }
  235. static inline unsigned int unhex(const char* h, unsigned int hlen, void* buf, unsigned int buflen)
  236. {
  237. unsigned int l = 0;
  238. const char* hend = h + hlen;
  239. while (l < buflen) {
  240. if (h == hend) {
  241. break;
  242. }
  243. uint8_t hc = *(reinterpret_cast<const uint8_t*>(h++));
  244. if (! hc) {
  245. break;
  246. }
  247. uint8_t c = 0;
  248. if ((hc >= 48) && (hc <= 57)) {
  249. c = hc - 48;
  250. }
  251. else if ((hc >= 97) && (hc <= 102)) {
  252. c = hc - 87;
  253. }
  254. else if ((hc >= 65) && (hc <= 70)) {
  255. c = hc - 55;
  256. }
  257. if (h == hend) {
  258. break;
  259. }
  260. hc = *(reinterpret_cast<const uint8_t*>(h++));
  261. if (! hc) {
  262. break;
  263. }
  264. c <<= 4;
  265. if ((hc >= 48) && (hc <= 57)) {
  266. c |= hc - 48;
  267. }
  268. else if ((hc >= 97) && (hc <= 102)) {
  269. c |= hc - 87;
  270. }
  271. else if ((hc >= 65) && (hc <= 70)) {
  272. c |= hc - 55;
  273. }
  274. reinterpret_cast<uint8_t*>(buf)[l++] = c;
  275. }
  276. return l;
  277. }
  278. static inline float normalize(float value, float bigMin, float bigMax, float targetMin, float targetMax)
  279. {
  280. float bigSpan = bigMax - bigMin;
  281. float smallSpan = targetMax - targetMin;
  282. float valueScaled = (value - bigMin) / bigSpan;
  283. return targetMin + valueScaled * smallSpan;
  284. }
  285. /**
  286. * Generate secure random bytes
  287. *
  288. * This will try to use whatever OS sources of entropy are available. It's
  289. * guarded by an internal mutex so it's thread-safe.
  290. *
  291. * @param buf Buffer to fill
  292. * @param bytes Number of random bytes to generate
  293. */
  294. static void getSecureRandom(void* buf, unsigned int bytes);
  295. /**
  296. * Tokenize a string (alias for strtok_r or strtok_s depending on platform)
  297. *
  298. * @param str String to split
  299. * @param delim Delimiters
  300. * @param saveptr Pointer to a char * for temporary reentrant storage
  301. */
  302. static inline char* stok(char* str, const char* delim, char** saveptr)
  303. {
  304. #ifdef __WINDOWS__
  305. return strtok_s(str, delim, saveptr);
  306. #else
  307. return strtok_r(str, delim, saveptr);
  308. #endif
  309. }
  310. static inline unsigned int strToUInt(const char* s)
  311. {
  312. return (unsigned int)strtoul(s, (char**)0, 10);
  313. }
  314. static inline int strToInt(const char* s)
  315. {
  316. return (int)strtol(s, (char**)0, 10);
  317. }
  318. static inline unsigned long strToULong(const char* s)
  319. {
  320. return strtoul(s, (char**)0, 10);
  321. }
  322. static inline long strToLong(const char* s)
  323. {
  324. return strtol(s, (char**)0, 10);
  325. }
  326. static inline double strToDouble(const char* s)
  327. {
  328. return strtod(s, NULL);
  329. }
  330. static inline unsigned long long strToU64(const char* s)
  331. {
  332. #ifdef __WINDOWS__
  333. return (unsigned long long)_strtoui64(s, (char**)0, 10);
  334. #else
  335. return strtoull(s, (char**)0, 10);
  336. #endif
  337. }
  338. static inline long long strTo64(const char* s)
  339. {
  340. #ifdef __WINDOWS__
  341. return (long long)_strtoi64(s, (char**)0, 10);
  342. #else
  343. return strtoll(s, (char**)0, 10);
  344. #endif
  345. }
  346. static inline unsigned int hexStrToUInt(const char* s)
  347. {
  348. return (unsigned int)strtoul(s, (char**)0, 16);
  349. }
  350. static inline int hexStrToInt(const char* s)
  351. {
  352. return (int)strtol(s, (char**)0, 16);
  353. }
  354. static inline unsigned long hexStrToULong(const char* s)
  355. {
  356. return strtoul(s, (char**)0, 16);
  357. }
  358. static inline long hexStrToLong(const char* s)
  359. {
  360. return strtol(s, (char**)0, 16);
  361. }
  362. static inline unsigned long long hexStrToU64(const char* s)
  363. {
  364. #ifdef __WINDOWS__
  365. return (unsigned long long)_strtoui64(s, (char**)0, 16);
  366. #else
  367. return strtoull(s, (char**)0, 16);
  368. #endif
  369. }
  370. static inline long long hexStrTo64(const char* s)
  371. {
  372. #ifdef __WINDOWS__
  373. return (long long)_strtoi64(s, (char**)0, 16);
  374. #else
  375. return strtoll(s, (char**)0, 16);
  376. #endif
  377. }
  378. /**
  379. * Perform a safe C string copy, ALWAYS null-terminating the result
  380. *
  381. * This will never ever EVER result in dest[] not being null-terminated
  382. * regardless of any input parameter (other than len==0 which is invalid).
  383. *
  384. * @param dest Destination buffer (must not be NULL)
  385. * @param len Length of dest[] (if zero, false is returned and nothing happens)
  386. * @param src Source string (if NULL, dest will receive a zero-length string and true is returned)
  387. * @return True on success, false on overflow (buffer will still be 0-terminated)
  388. */
  389. static inline bool scopy(char* dest, unsigned int len, const char* src)
  390. {
  391. if (! len) {
  392. return false; // sanity check
  393. }
  394. if (! src) {
  395. *dest = (char)0;
  396. return true;
  397. }
  398. char* end = dest + len;
  399. while ((*dest++ = *src++)) {
  400. if (dest == end) {
  401. *(--dest) = (char)0;
  402. return false;
  403. }
  404. }
  405. return true;
  406. }
  407. /**
  408. * Count the number of bits set in an integer
  409. *
  410. * @param v 32-bit integer
  411. * @return Number of bits set in this integer (0-32)
  412. */
  413. static inline uint32_t countBits(uint32_t v)
  414. {
  415. v = v - ((v >> 1) & (uint32_t)0x55555555);
  416. v = (v & (uint32_t)0x33333333) + ((v >> 2) & (uint32_t)0x33333333);
  417. return ((((v + (v >> 4)) & (uint32_t)0xF0F0F0F) * (uint32_t)0x1010101) >> 24);
  418. }
  419. /**
  420. * Count the number of bits set in an integer
  421. *
  422. * @param v 64-bit integer
  423. * @return Number of bits set in this integer (0-64)
  424. */
  425. static inline uint64_t countBits(uint64_t v)
  426. {
  427. v = v - ((v >> 1) & (uint64_t)~(uint64_t)0 / 3);
  428. v = (v & (uint64_t)~(uint64_t)0 / 15 * 3) + ((v >> 2) & (uint64_t)~(uint64_t)0 / 15 * 3);
  429. v = (v + (v >> 4)) & (uint64_t)~(uint64_t)0 / 255 * 15;
  430. return (uint64_t)(v * ((uint64_t)~(uint64_t)0 / 255)) >> 56;
  431. }
  432. /**
  433. * Check if a memory buffer is all-zero
  434. *
  435. * @param p Memory to scan
  436. * @param len Length of memory
  437. * @return True if memory is all zero
  438. */
  439. static inline bool isZero(const void* p, unsigned int len)
  440. {
  441. for (unsigned int i = 0; i < len; ++i) {
  442. if (((const unsigned char*)p)[i]) {
  443. return false;
  444. }
  445. }
  446. return true;
  447. }
  448. /**
  449. * Unconditionally swap bytes regardless of host byte order
  450. *
  451. * @param n Integer to swap
  452. * @return Integer with bytes reversed
  453. */
  454. static ZT_INLINE uint64_t swapBytes(const uint64_t n) noexcept
  455. {
  456. #ifdef __GNUC__
  457. return __builtin_bswap64(n);
  458. #else
  459. #ifdef _MSC_VER
  460. return (uint64_t)_byteswap_uint64((unsigned __int64)n);
  461. #else
  462. return (
  463. ((n & 0x00000000000000ffULL) << 56) | ((n & 0x000000000000ff00ULL) << 40) | ((n & 0x0000000000ff0000ULL) << 24) | ((n & 0x00000000ff000000ULL) << 8) | ((n & 0x000000ff00000000ULL) >> 8) | ((n & 0x0000ff0000000000ULL) >> 24)
  464. | ((n & 0x00ff000000000000ULL) >> 40) | ((n & 0xff00000000000000ULL) >> 56));
  465. #endif
  466. #endif
  467. }
  468. /**
  469. * Unconditionally swap bytes regardless of host byte order
  470. *
  471. * @param n Integer to swap
  472. * @return Integer with bytes reversed
  473. */
  474. static ZT_INLINE uint32_t swapBytes(const uint32_t n) noexcept
  475. {
  476. #if defined(__GNUC__)
  477. return __builtin_bswap32(n);
  478. #else
  479. #ifdef _MSC_VER
  480. return (uint32_t)_byteswap_ulong((unsigned long)n);
  481. #else
  482. return htonl(n);
  483. #endif
  484. #endif
  485. }
  486. /**
  487. * Unconditionally swap bytes regardless of host byte order
  488. *
  489. * @param n Integer to swap
  490. * @return Integer with bytes reversed
  491. */
  492. static ZT_INLINE uint16_t swapBytes(const uint16_t n) noexcept
  493. {
  494. #if defined(__GNUC__)
  495. return __builtin_bswap16(n);
  496. #else
  497. #ifdef _MSC_VER
  498. return (uint16_t)_byteswap_ushort((unsigned short)n);
  499. #else
  500. return htons(n);
  501. #endif
  502. #endif
  503. }
  504. // These are helper adapters to load and swap integer types special cased by size
  505. // to work with all typedef'd variants, signed/unsigned, etc.
  506. template <typename I, unsigned int S> class _swap_bytes_bysize;
  507. template <typename I> class _swap_bytes_bysize<I, 1> {
  508. public:
  509. static ZT_INLINE I s(const I n) noexcept
  510. {
  511. return n;
  512. }
  513. };
  514. template <typename I> class _swap_bytes_bysize<I, 2> {
  515. public:
  516. static ZT_INLINE I s(const I n) noexcept
  517. {
  518. return (I)swapBytes((uint16_t)n);
  519. }
  520. };
  521. template <typename I> class _swap_bytes_bysize<I, 4> {
  522. public:
  523. static ZT_INLINE I s(const I n) noexcept
  524. {
  525. return (I)swapBytes((uint32_t)n);
  526. }
  527. };
  528. template <typename I> class _swap_bytes_bysize<I, 8> {
  529. public:
  530. static ZT_INLINE I s(const I n) noexcept
  531. {
  532. return (I)swapBytes((uint64_t)n);
  533. }
  534. };
  535. template <typename I, unsigned int S> class _load_be_bysize;
  536. template <typename I> class _load_be_bysize<I, 1> {
  537. public:
  538. static ZT_INLINE I l(const uint8_t* const p) noexcept
  539. {
  540. return p[0];
  541. }
  542. };
  543. template <typename I> class _load_be_bysize<I, 2> {
  544. public:
  545. static ZT_INLINE I l(const uint8_t* const p) noexcept
  546. {
  547. return (I)(((unsigned int)p[0] << 8U) | (unsigned int)p[1]);
  548. }
  549. };
  550. template <typename I> class _load_be_bysize<I, 4> {
  551. public:
  552. static ZT_INLINE I l(const uint8_t* const p) noexcept
  553. {
  554. return (I)(((uint32_t)p[0] << 24U) | ((uint32_t)p[1] << 16U) | ((uint32_t)p[2] << 8U) | (uint32_t)p[3]);
  555. }
  556. };
  557. template <typename I> class _load_be_bysize<I, 8> {
  558. public:
  559. static ZT_INLINE I l(const uint8_t* const p) noexcept
  560. {
  561. return (I)(((uint64_t)p[0] << 56U) | ((uint64_t)p[1] << 48U) | ((uint64_t)p[2] << 40U) | ((uint64_t)p[3] << 32U) | ((uint64_t)p[4] << 24U) | ((uint64_t)p[5] << 16U) | ((uint64_t)p[6] << 8U) | (uint64_t)p[7]);
  562. }
  563. };
  564. template <typename I, unsigned int S> class _load_le_bysize;
  565. template <typename I> class _load_le_bysize<I, 1> {
  566. public:
  567. static ZT_INLINE I l(const uint8_t* const p) noexcept
  568. {
  569. return p[0];
  570. }
  571. };
  572. template <typename I> class _load_le_bysize<I, 2> {
  573. public:
  574. static ZT_INLINE I l(const uint8_t* const p) noexcept
  575. {
  576. return (I)((unsigned int)p[0] | ((unsigned int)p[1] << 8U));
  577. }
  578. };
  579. template <typename I> class _load_le_bysize<I, 4> {
  580. public:
  581. static ZT_INLINE I l(const uint8_t* const p) noexcept
  582. {
  583. return (I)((uint32_t)p[0] | ((uint32_t)p[1] << 8U) | ((uint32_t)p[2] << 16U) | ((uint32_t)p[3] << 24U));
  584. }
  585. };
  586. template <typename I> class _load_le_bysize<I, 8> {
  587. public:
  588. static ZT_INLINE I l(const uint8_t* const p) noexcept
  589. {
  590. return (I)((uint64_t)p[0] | ((uint64_t)p[1] << 8U) | ((uint64_t)p[2] << 16U) | ((uint64_t)p[3] << 24U) | ((uint64_t)p[4] << 32U) | ((uint64_t)p[5] << 40U) | ((uint64_t)p[6] << 48U) | ((uint64_t)p[7]) << 56U);
  591. }
  592. };
  593. /**
  594. * Convert any signed or unsigned integer type to big-endian ("network") byte order
  595. *
  596. * @tparam I Integer type (usually inferred)
  597. * @param n Value to convert
  598. * @return Value in big-endian order
  599. */
  600. template <typename I> static ZT_INLINE I hton(const I n) noexcept
  601. {
  602. #if __BYTE_ORDER == __LITTLE_ENDIAN
  603. return _swap_bytes_bysize<I, sizeof(I)>::s(n);
  604. #else
  605. return n;
  606. #endif
  607. }
  608. /**
  609. * Convert any signed or unsigned integer type to host byte order from big-endian ("network") byte order
  610. *
  611. * @tparam I Integer type (usually inferred)
  612. * @param n Value to convert
  613. * @return Value in host byte order
  614. */
  615. template <typename I> static ZT_INLINE I ntoh(const I n) noexcept
  616. {
  617. #if __BYTE_ORDER == __LITTLE_ENDIAN
  618. return _swap_bytes_bysize<I, sizeof(I)>::s(n);
  619. #else
  620. return n;
  621. #endif
  622. }
  623. /**
  624. * Copy bits from memory into an integer type without modifying their order
  625. *
  626. * @tparam I Type to load
  627. * @param p Byte stream, must be at least sizeof(I) in size
  628. * @return Loaded raw integer
  629. */
  630. template <typename I> static ZT_INLINE I loadMachineEndian(const void* const p) noexcept
  631. {
  632. #ifdef ZT_NO_UNALIGNED_ACCESS
  633. I tmp;
  634. for (int i = 0; i < (int)sizeof(I); ++i) {
  635. reinterpret_cast<uint8_t*>(&tmp)[i] = reinterpret_cast<const uint8_t*>(p)[i];
  636. }
  637. return tmp;
  638. #else
  639. return *reinterpret_cast<const I*>(p);
  640. #endif
  641. }
  642. /**
  643. * Copy bits from memory into an integer type without modifying their order
  644. *
  645. * @tparam I Type to store
  646. * @param p Byte array (must be at least sizeof(I))
  647. * @param i Integer to store
  648. */
  649. template <typename I> static ZT_INLINE void storeMachineEndian(void* const p, const I i) noexcept
  650. {
  651. #ifdef ZT_NO_UNALIGNED_ACCESS
  652. for (unsigned int k = 0; k < sizeof(I); ++k) {
  653. reinterpret_cast<uint8_t*>(p)[k] = reinterpret_cast<const uint8_t*>(&i)[k];
  654. }
  655. #else
  656. *reinterpret_cast<I*>(p) = i;
  657. #endif
  658. }
  659. /**
  660. * Decode a big-endian value from a byte stream
  661. *
  662. * @tparam I Type to decode (should be unsigned e.g. uint32_t or uint64_t)
  663. * @param p Byte stream, must be at least sizeof(I) in size
  664. * @return Decoded integer
  665. */
  666. template <typename I> static ZT_INLINE I loadBigEndian(const void* const p) noexcept
  667. {
  668. #ifdef ZT_NO_UNALIGNED_ACCESS
  669. return _load_be_bysize<I, sizeof(I)>::l(reinterpret_cast<const uint8_t*>(p));
  670. #else
  671. return ntoh(*reinterpret_cast<const I*>(p));
  672. #endif
  673. }
  674. /**
  675. * Save an integer in big-endian format
  676. *
  677. * @tparam I Integer type to store (usually inferred)
  678. * @param p Byte stream to write (must be at least sizeof(I))
  679. * #param i Integer to write
  680. */
  681. template <typename I> static ZT_INLINE void storeBigEndian(void* const p, I i) noexcept
  682. {
  683. #ifdef ZT_NO_UNALIGNED_ACCESS
  684. storeMachineEndian(p, hton(i));
  685. #else
  686. *reinterpret_cast<I*>(p) = hton(i);
  687. #endif
  688. }
  689. /**
  690. * Decode a little-endian value from a byte stream
  691. *
  692. * @tparam I Type to decode
  693. * @param p Byte stream, must be at least sizeof(I) in size
  694. * @return Decoded integer
  695. */
  696. template <typename I> static ZT_INLINE I loadLittleEndian(const void* const p) noexcept
  697. {
  698. #if __BYTE_ORDER == __BIG_ENDIAN || defined(ZT_NO_UNALIGNED_ACCESS)
  699. return _load_le_bysize<I, sizeof(I)>::l(reinterpret_cast<const uint8_t*>(p));
  700. #else
  701. return *reinterpret_cast<const I*>(p);
  702. #endif
  703. }
  704. /**
  705. * Save an integer in little-endian format
  706. *
  707. * @tparam I Integer type to store (usually inferred)
  708. * @param p Byte stream to write (must be at least sizeof(I))
  709. * #param i Integer to write
  710. */
  711. template <typename I> static ZT_INLINE void storeLittleEndian(void* const p, const I i) noexcept
  712. {
  713. #if __BYTE_ORDER == __BIG_ENDIAN
  714. storeMachineEndian(p, _swap_bytes_bysize<I, sizeof(I)>::s(i));
  715. #else
  716. #ifdef ZT_NO_UNALIGNED_ACCESS
  717. storeMachineEndian(p, i);
  718. #else
  719. *reinterpret_cast<I*>(p) = i;
  720. #endif
  721. #endif
  722. }
  723. /**
  724. * Copy memory block whose size is known at compile time.
  725. *
  726. * @tparam L Size of memory
  727. * @param dest Destination memory
  728. * @param src Source memory
  729. */
  730. template <unsigned long L> static ZT_INLINE void copy(void* dest, const void* src) noexcept
  731. {
  732. #if defined(ZT_ARCH_X64) && defined(__GNUC__)
  733. uintptr_t l = L;
  734. __asm__ __volatile__("cld ; rep movsb" : "+c"(l), "+S"(src), "+D"(dest)::"memory");
  735. #else
  736. memcpy(dest, src, L);
  737. #endif
  738. }
  739. /**
  740. * Copy memory block whose size is known at run time
  741. *
  742. * @param dest Destination memory
  743. * @param src Source memory
  744. * @param len Bytes to copy
  745. */
  746. static ZT_INLINE void copy(void* dest, const void* src, unsigned long len) noexcept
  747. {
  748. #if defined(ZT_ARCH_X64) && defined(__GNUC__)
  749. __asm__ __volatile__("cld ; rep movsb" : "+c"(len), "+S"(src), "+D"(dest)::"memory");
  750. #else
  751. memcpy(dest, src, len);
  752. #endif
  753. }
  754. /**
  755. * Zero memory block whose size is known at compile time
  756. *
  757. * @tparam L Size in bytes
  758. * @param dest Memory to zero
  759. */
  760. template <unsigned long L> static ZT_INLINE void zero(void* dest) noexcept
  761. {
  762. #if defined(ZT_ARCH_X64) && defined(__GNUC__)
  763. uintptr_t l = L;
  764. __asm__ __volatile__("cld ; rep stosb" : "+c"(l), "+D"(dest) : "a"(0) : "memory");
  765. #else
  766. memset(dest, 0, L);
  767. #endif
  768. }
  769. /**
  770. * Zero memory block whose size is known at run time
  771. *
  772. * @param dest Memory to zero
  773. * @param len Size in bytes
  774. */
  775. static ZT_INLINE void zero(void* dest, unsigned long len) noexcept
  776. {
  777. #if defined(ZT_ARCH_X64) && defined(__GNUC__)
  778. __asm__ __volatile__("cld ; rep stosb" : "+c"(len), "+D"(dest) : "a"(0) : "memory");
  779. #else
  780. memset(dest, 0, len);
  781. #endif
  782. }
  783. /**
  784. * Hexadecimal characters 0-f
  785. */
  786. static const char HEXCHARS[16];
  787. /*
  788. * Remove `-` and `:` from a MAC address (in-place).
  789. *
  790. * @param mac The MAC address
  791. */
  792. static inline void cleanMac(std::string& mac)
  793. {
  794. auto start = mac.begin();
  795. auto end = mac.end();
  796. auto new_end = std::remove_if(start, end, [](char c) { return c == 45 || c == 58; });
  797. mac.erase(new_end, end);
  798. }
  799. };
  800. } // namespace ZeroTier
  801. #endif