lluuid.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. /**
  2. * @file lluuid.cpp
  3. *
  4. * $LicenseInfo:firstyear=2000&license=viewergpl$
  5. *
  6. * Copyright (c) 2000-2009, Linden Research, Inc.
  7. *
  8. * Second Life Viewer Source Code
  9. * The source code in this file ("Source Code") is provided by Linden Lab
  10. * to you under the terms of the GNU General Public License, version 2.0
  11. * ("GPL"), unless you have obtained a separate licensing agreement
  12. * ("Other License"), formally executed by you and Linden Lab. Terms of
  13. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  14. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  15. *
  16. * There are special exceptions to the terms and conditions of the GPL as
  17. * it is applied to this Source Code. View the full text of the exception
  18. * in the file doc/FLOSS-exception.txt in this software distribution, or
  19. * online at
  20. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  21. *
  22. * By copying, modifying or distributing this software, you acknowledge
  23. * that you have read and understood your obligations described above,
  24. * and agree to abide by those obligations.
  25. *
  26. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  27. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  28. * COMPLETENESS OR PERFORMANCE.
  29. * $/LicenseInfo$
  30. */
  31. #include "linden_common.h"
  32. #include "llmd5.h"
  33. #include "llmutex.h"
  34. #include "llrand.h"
  35. #include "llstring.h"
  36. #include "llsys.h" // For LLOSInfo::getNodeID()
  37. #include "lltimer.h"
  38. #include "hbxxh.h"
  39. const LLUUID LLUUID::null;
  40. const LLTransactionID LLTransactionID::tnull;
  41. static LLMutex sTimeMutex;
  42. #if LL_UUID_ALIGMENT_STATS
  43. static LLMutex sAlignmentMutex;
  44. //static
  45. U64 LLUUID::sAlignmentCounts[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  46. //static
  47. void LLUUID::incAlignment(intptr_t address)
  48. {
  49. sAlignmentMutex.lock();
  50. ++sAlignmentCounts[address & 7UL];
  51. sAlignmentMutex.unlock();
  52. }
  53. #endif
  54. LLUUID::LLUUID(const char* in_string) noexcept
  55. {
  56. #if LL_UUID_ALIGMENT_STATS
  57. incAlignment((intptr_t)mData);
  58. #endif
  59. if (!in_string || !*in_string)
  60. {
  61. setNull();
  62. return;
  63. }
  64. set(in_string);
  65. }
  66. LLUUID::LLUUID(const char* in_string, bool emit) noexcept
  67. {
  68. #if LL_UUID_ALIGMENT_STATS
  69. incAlignment((intptr_t)mData);
  70. #endif
  71. if (!in_string || !*in_string)
  72. {
  73. setNull();
  74. return;
  75. }
  76. set(in_string, emit);
  77. }
  78. LLUUID::LLUUID(const std::string& in_string) noexcept
  79. {
  80. #if LL_UUID_ALIGMENT_STATS
  81. incAlignment((intptr_t)mData);
  82. #endif
  83. if (in_string.empty())
  84. {
  85. setNull();
  86. return;
  87. }
  88. set(in_string);
  89. }
  90. LLUUID::LLUUID(const std::string& in_string, bool emit) noexcept
  91. {
  92. #if LL_UUID_ALIGMENT_STATS
  93. incAlignment((intptr_t)mData);
  94. #endif
  95. if (in_string.empty())
  96. {
  97. setNull();
  98. return;
  99. }
  100. set(in_string, emit);
  101. }
  102. static const char* sDigits = "0123456789abcdef";
  103. // I am using a lookup table to avoid branches during hexadecimal to digit
  104. // conversion, and unrolled manually the loop, with properly interleaved '-'
  105. // additions. HB
  106. // *TODO: consider SSE/AVX to convert (long ?) integers to string.
  107. std::string LLUUID::asString() const
  108. {
  109. std::string out;
  110. out.reserve(UUID_BYTES + 4);
  111. U8 byte = mData[0];
  112. out += sDigits[(byte >> 4) & 0x0F];
  113. out += sDigits[byte & 0x0F];
  114. byte = mData[1];
  115. out += sDigits[(byte >> 4) & 0x0F];
  116. out += sDigits[byte & 0x0F];
  117. byte = mData[2];
  118. out += sDigits[(byte >> 4) & 0x0F];
  119. out += sDigits[byte & 0x0F];
  120. byte = mData[3];
  121. out += sDigits[(byte >> 4) & 0x0F];
  122. out += sDigits[byte & 0x0F];
  123. out += '-';
  124. byte = mData[4];
  125. out += sDigits[(byte >> 4) & 0x0F];
  126. out += sDigits[byte & 0x0F];
  127. byte = mData[5];
  128. out += sDigits[(byte >> 4) & 0x0F];
  129. out += sDigits[byte & 0x0F];
  130. out += '-';
  131. byte = mData[6];
  132. out += sDigits[(byte >> 4) & 0x0F];
  133. out += sDigits[byte & 0x0F];
  134. byte = mData[7];
  135. out += sDigits[(byte >> 4) & 0x0F];
  136. out += sDigits[byte & 0x0F];
  137. out += '-';
  138. byte = mData[8];
  139. out += sDigits[(byte >> 4) & 0x0F];
  140. out += sDigits[byte & 0x0F];
  141. byte = mData[9];
  142. out += sDigits[(byte >> 4) & 0x0F];
  143. out += sDigits[byte & 0x0F];
  144. out += '-';
  145. byte = mData[10];
  146. out += sDigits[(byte >> 4) & 0x0F];
  147. out += sDigits[byte & 0x0F];
  148. byte = mData[11];
  149. out += sDigits[(byte >> 4) & 0x0F];
  150. out += sDigits[byte & 0x0F];
  151. byte = mData[12];
  152. out += sDigits[(byte >> 4) & 0x0F];
  153. out += sDigits[byte & 0x0F];
  154. byte = mData[13];
  155. out += sDigits[(byte >> 4) & 0x0F];
  156. out += sDigits[byte & 0x0F];
  157. byte = mData[14];
  158. out += sDigits[(byte >> 4) & 0x0F];
  159. out += sDigits[byte & 0x0F];
  160. byte = mData[15];
  161. out += sDigits[(byte >> 4) & 0x0F];
  162. out += sDigits[byte & 0x0F];
  163. return out;
  164. }
  165. // Private method to perform the string conversion on the stack (when 'out' is
  166. // allocated on the latter), which avoids memory allocations with some C++
  167. // libraries (where std::string is allocated on the heap when over 12 bytes
  168. // long or so). 'out' must point to a buffer with at least 37 bytes free. HB
  169. void LLUUID::toCString(char* out) const
  170. {
  171. U8 byte = mData[0];
  172. *out++ = sDigits[(byte >> 4) & 0x0F];
  173. *out++ = sDigits[byte & 0x0F];
  174. byte = mData[1];
  175. *out++ = sDigits[(byte >> 4) & 0x0F];
  176. *out++ = sDigits[byte & 0x0F];
  177. byte = mData[2];
  178. *out++ = sDigits[(byte >> 4) & 0x0F];
  179. *out++ = sDigits[byte & 0x0F];
  180. byte = mData[3];
  181. *out++ = sDigits[(byte >> 4) & 0x0F];
  182. *out++ = sDigits[byte & 0x0F];
  183. *out++ = '-';
  184. byte = mData[4];
  185. *out++ = sDigits[(byte >> 4) & 0x0F];
  186. *out++ = sDigits[byte & 0x0F];
  187. byte = mData[5];
  188. *out++ = sDigits[(byte >> 4) & 0x0F];
  189. *out++ = sDigits[byte & 0x0F];
  190. *out++ = '-';
  191. byte = mData[6];
  192. *out++ = sDigits[(byte >> 4) & 0x0F];
  193. *out++ = sDigits[byte & 0x0F];
  194. byte = mData[7];
  195. *out++ = sDigits[(byte >> 4) & 0x0F];
  196. *out++ = sDigits[byte & 0x0F];
  197. *out++ = '-';
  198. byte = mData[8];
  199. *out++ = sDigits[(byte >> 4) & 0x0F];
  200. *out++ = sDigits[byte & 0x0F];
  201. byte = mData[9];
  202. *out++ = sDigits[(byte >> 4) & 0x0F];
  203. *out++ = sDigits[byte & 0x0F];
  204. *out++ = '-';
  205. byte = mData[10];
  206. *out++ = sDigits[(byte >> 4) & 0x0F];
  207. *out++ = sDigits[byte & 0x0F];
  208. byte = mData[11];
  209. *out++ = sDigits[(byte >> 4) & 0x0F];
  210. *out++ = sDigits[byte & 0x0F];
  211. byte = mData[12];
  212. *out++ = sDigits[(byte >> 4) & 0x0F];
  213. *out++ = sDigits[byte & 0x0F];
  214. byte = mData[13];
  215. *out++ = sDigits[(byte >> 4) & 0x0F];
  216. *out++ = sDigits[byte & 0x0F];
  217. byte = mData[14];
  218. *out++ = sDigits[(byte >> 4) & 0x0F];
  219. *out++ = sDigits[byte & 0x0F];
  220. byte = mData[15];
  221. *out++ = sDigits[(byte >> 4) & 0x0F];
  222. *out++ = sDigits[byte & 0x0F];
  223. *out = '\0';
  224. }
  225. bool LLUUID::set(const char* in_string, bool emit)
  226. {
  227. return set(ll_safe_string(in_string), emit);
  228. }
  229. bool LLUUID::set(const std::string& in_string, bool emit)
  230. {
  231. bool broken_format = false;
  232. // Empty strings should make null UUID
  233. if (in_string.empty())
  234. {
  235. setNull();
  236. return true;
  237. }
  238. if (in_string.length() != UUID_STR_LENGTH - 1)
  239. {
  240. // First implementation did not have the right UUID format. Should not
  241. // see any of these any more.
  242. if (in_string.length() == UUID_STR_LENGTH - 2)
  243. {
  244. if (emit)
  245. {
  246. llwarns << "Warning ! Using broken UUID string format"
  247. << llendl;
  248. }
  249. broken_format = true;
  250. }
  251. else
  252. {
  253. if (emit)
  254. {
  255. llwarns << "Bad UUID string: " << in_string << llendl;
  256. }
  257. setNull();
  258. return false;
  259. }
  260. }
  261. constexpr char hexa = 10 - 'a';
  262. constexpr char HEXA = 10 - 'A';
  263. U8 cur_pos = 0;
  264. U8* ptr = mData;
  265. for (S32 i = 0; i < UUID_BYTES; ++i)
  266. {
  267. if (i == 4 || i == 6 || i == 8 || i == 10)
  268. {
  269. ++cur_pos;
  270. if (broken_format && i == 10)
  271. {
  272. // Missing '-' in the broken format
  273. --cur_pos;
  274. }
  275. }
  276. *ptr = 0;
  277. char c = in_string[cur_pos];
  278. if (c >= '0' && c <= '9')
  279. {
  280. *ptr += (U8)(c - '0');
  281. }
  282. else if (c >= 'a' && c <= 'f')
  283. {
  284. *ptr += (U8)(c + hexa);
  285. }
  286. else if (c >= 'A' && c <= 'F')
  287. {
  288. *ptr += (U8)(c + HEXA);
  289. }
  290. else
  291. {
  292. if (emit)
  293. {
  294. llwarns << "Invalid UUID string character" << llendl;
  295. }
  296. setNull();
  297. return false;
  298. }
  299. *ptr <<= 4;
  300. c = in_string[++cur_pos];
  301. if (c >= '0' && c <= '9')
  302. {
  303. *ptr += (U8)(c - '0');
  304. }
  305. else if (c >= 'a' && c <= 'f')
  306. {
  307. *ptr += (U8)(c + hexa);
  308. }
  309. else if (c >= 'A' && c <= 'F')
  310. {
  311. *ptr += (U8)(c + HEXA);
  312. }
  313. else
  314. {
  315. if (emit)
  316. {
  317. llwarns << "Invalid UUID string character" << llendl;
  318. }
  319. setNull();
  320. return false;
  321. }
  322. ++cur_pos;
  323. ++ptr;
  324. }
  325. return true;
  326. }
  327. // Helper function
  328. bool is_hex_digit(char c)
  329. {
  330. return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') ||
  331. (c >= 'A' && c <= 'F');
  332. }
  333. //static
  334. bool LLUUID::validate(const std::string& in_string)
  335. {
  336. bool broken_format = false;
  337. if (in_string.length() != UUID_STR_LENGTH - 1)
  338. {
  339. // First implementation did not have the right UUID format.
  340. if (in_string.length() == UUID_STR_LENGTH - 2)
  341. {
  342. broken_format = true;
  343. }
  344. else
  345. {
  346. return false;
  347. }
  348. }
  349. U8 cur_pos = 0;
  350. for (U32 i = 0; i < 16; ++i)
  351. {
  352. if (i == 4 || i == 6 || i == 8 || i == 10)
  353. {
  354. ++cur_pos;
  355. if (broken_format && i == 10)
  356. {
  357. // Missing '-' in the broken format
  358. --cur_pos;
  359. }
  360. }
  361. if (!is_hex_digit(in_string[cur_pos++]))
  362. {
  363. return false;
  364. }
  365. if (!is_hex_digit(in_string[cur_pos++]))
  366. {
  367. return false;
  368. }
  369. }
  370. return true;
  371. }
  372. const LLUUID& LLUUID::operator^=(const LLUUID& rhs)
  373. {
  374. U32* me = (U32*)&(mData[0]);
  375. const U32* other = (U32*)&(rhs.mData[0]);
  376. for (S32 i = 0; i < 4; ++i)
  377. {
  378. me[i] = me[i] ^ other[i];
  379. }
  380. return *this;
  381. }
  382. LLUUID LLUUID::operator^(const LLUUID& rhs) const
  383. {
  384. LLUUID id(*this);
  385. id ^= rhs;
  386. return id;
  387. }
  388. // WARNING: this algorithm SHALL NOT be changed. It is also used by the server
  389. // and plays a role in some assets validation (e.g. clothing items). Changing
  390. // it would cause invalid assets.
  391. void LLUUID::combine(const LLUUID& other, LLUUID& result) const
  392. {
  393. LLMD5 md5_uuid;
  394. md5_uuid.update((unsigned char*)mData, 16);
  395. md5_uuid.update((unsigned char*)other.mData, 16);
  396. md5_uuid.finalize();
  397. md5_uuid.raw_digest(result.mData);
  398. }
  399. LLUUID LLUUID::combine(const LLUUID& other) const
  400. {
  401. LLUUID combination;
  402. combine(other, combination);
  403. return combination;
  404. }
  405. std::ostream& operator<<(std::ostream& s, const LLUUID& uuid)
  406. {
  407. char uuid_str[UUID_STR_LENGTH];
  408. uuid.toCString(uuid_str);
  409. s << uuid_str;
  410. return s;
  411. }
  412. std::istream& operator>>(std::istream& s, LLUUID& uuid)
  413. {
  414. U32 i;
  415. char uuid_str[UUID_STR_LENGTH];
  416. for (i = 0; i < UUID_STR_LENGTH - 1; ++i)
  417. {
  418. s >> uuid_str[i];
  419. }
  420. uuid_str[i] = '\0';
  421. uuid.set(std::string(uuid_str));
  422. return s;
  423. }
  424. S32 LLUUID::cmpTime(uuid_time_t* t1, uuid_time_t* t2)
  425. {
  426. // Compare two time values.
  427. if (t1->high < t2->high) return -1;
  428. if (t1->high > t2->high) return 1;
  429. if (t1->low < t2->low) return -1;
  430. if (t1->low > t2->low) return 1;
  431. return 0;
  432. }
  433. void LLUUID::getSystemTime(uuid_time_t* timestamp)
  434. {
  435. // Get system time with 100ns precision. Time is since Oct 15, 1582.
  436. #if LL_WINDOWS
  437. ULARGE_INTEGER time;
  438. GetSystemTimeAsFileTime((FILETIME*)&time);
  439. // NT keeps time in FILETIME format which is 100ns ticks since
  440. // Jan 1, 1601. UUIDs use time in 100ns ticks since Oct 15, 1582.
  441. // The difference is 17 Days in Oct + 30 (Nov) + 31 (Dec)
  442. // + 18 years and 5 leap days.
  443. time.QuadPart += (unsigned __int64)(1000 * 1000 * 10) * // seconds
  444. (unsigned __int64)(60 * 60 * 24) * // days
  445. (unsigned __int64)(17 + 30 + 31 + 365 * 18 + 5); // # of days
  446. timestamp->high = time.HighPart;
  447. timestamp->low = time.LowPart;
  448. #else
  449. struct timeval tp;
  450. gettimeofday(&tp, 0);
  451. // Offset between UUID formatted times and Unix formatted times.
  452. // UUID UTC base time is October 15, 1582.
  453. // Unix base time is January 1, 1970.
  454. U64 uuid_time = ((U64)tp.tv_sec * 10000000) + (tp.tv_usec * 10) +
  455. U64L(0x01B21DD213814000);
  456. timestamp->high = (U32) (uuid_time >> 32);
  457. timestamp->low = (U32) (uuid_time & 0xFFFFFFFF);
  458. #endif
  459. }
  460. void LLUUID::getCurrentTime(uuid_time_t* timestamp)
  461. {
  462. // Get current time as 60 bit 100ns ticks since whenever. Compensate for
  463. // the fact that real clock resolution is less than 100ns.
  464. constexpr U32 uuids_per_tick = 1024;
  465. static uuid_time_t time_last;
  466. static U32 uuids_this_tick;
  467. static bool init = false;
  468. if (!init)
  469. {
  470. getSystemTime(&time_last);
  471. uuids_this_tick = uuids_per_tick;
  472. init = true;
  473. }
  474. uuid_time_t time_now = { 0, 0 };
  475. while (true)
  476. {
  477. getSystemTime(&time_now);
  478. // If clock reading changed since last UUID generated
  479. if (cmpTime(&time_last, &time_now))
  480. {
  481. // Reset count of uuid's generated with this clock reading
  482. uuids_this_tick = 0;
  483. break;
  484. }
  485. if (uuids_this_tick < uuids_per_tick)
  486. {
  487. ++uuids_this_tick;
  488. break;
  489. }
  490. // Going too fast for our clock; spin
  491. }
  492. time_last = time_now;
  493. if (uuids_this_tick != 0)
  494. {
  495. if (time_now.low & 0x80000000)
  496. {
  497. time_now.low += uuids_this_tick;
  498. if (!(time_now.low & 0x80000000))
  499. {
  500. ++time_now.high;
  501. }
  502. }
  503. else
  504. {
  505. time_now.low += uuids_this_tick;
  506. }
  507. }
  508. timestamp->high = time_now.high;
  509. timestamp->low = time_now.low;
  510. }
  511. void LLUUID::generate()
  512. {
  513. static unsigned char node_id[6];
  514. static uuid_time_t time_last = { 0, 0 };
  515. static U16 clock_seq = 0;
  516. static bool init_done = false;
  517. if (!init_done)
  518. {
  519. init_done = true;
  520. if (LLOSInfo::getNodeID(node_id) <= 0)
  521. {
  522. for (U32 i = 0; i < 6; ++i)
  523. {
  524. node_id[i] = ll_rand() & 0xFF;
  525. }
  526. // Set multicast bit, to prevent conflicts with IEEE 802 addresses
  527. // obtained from network cards
  528. node_id[0] |= 0x80;
  529. }
  530. getCurrentTime(&time_last);
  531. clock_seq = (U16)ll_rand(65536);
  532. }
  533. // Get current time
  534. uuid_time_t timestamp;
  535. getCurrentTime(&timestamp);
  536. U16 our_clock_seq = clock_seq;
  537. // If clock has not changed or went backward, change clockseq
  538. if (cmpTime(&timestamp, &time_last) != 1)
  539. {
  540. sTimeMutex.lock();
  541. clock_seq = (clock_seq + 1) & 0x3FFF;
  542. if (clock_seq == 0)
  543. {
  544. ++clock_seq;
  545. }
  546. // Ensure we are using a different clock_seq value from previous time
  547. our_clock_seq = clock_seq;
  548. sTimeMutex.unlock();
  549. }
  550. time_last = timestamp;
  551. memcpy(mData + 10, node_id, 6);
  552. U32 tmp;
  553. tmp = timestamp.low;
  554. mData[3] = (unsigned char)tmp;
  555. tmp >>= 8;
  556. mData[2] = (unsigned char)tmp;
  557. tmp >>= 8;
  558. mData[1] = (unsigned char)tmp;
  559. tmp >>= 8;
  560. mData[0] = (unsigned char)tmp;
  561. tmp = (U16) timestamp.high;
  562. mData[5] = (unsigned char)tmp;
  563. tmp >>= 8;
  564. mData[4] = (unsigned char)tmp;
  565. tmp = (timestamp.high >> 16) | 0x1000;
  566. mData[7] = (unsigned char)tmp;
  567. tmp >>= 8;
  568. mData[6] = (unsigned char)tmp;
  569. tmp = our_clock_seq;
  570. mData[9] = (unsigned char)tmp;
  571. tmp >>= 8;
  572. mData[8] = (unsigned char)tmp;
  573. HBXXH128::digest(*this, (const void*)mData, 16);
  574. }
  575. void LLUUID::generate(const std::string& hash_string)
  576. {
  577. HBXXH128::digest(*this, hash_string);
  578. }
  579. bool LLUUID::parseUUID(const std::string& buf, LLUUID* value)
  580. {
  581. if (buf.empty() || value == NULL)
  582. {
  583. return false;
  584. }
  585. std::string temp(buf);
  586. LLStringUtil::trim(temp);
  587. if (LLUUID::validate(temp))
  588. {
  589. value->set(temp);
  590. return true;
  591. }
  592. return false;
  593. }
  594. //static
  595. LLUUID LLUUID::generateNewID(std::string hash_string)
  596. {
  597. LLUUID new_id;
  598. if (hash_string.empty())
  599. {
  600. new_id.generate();
  601. }
  602. else
  603. {
  604. new_id.generate(hash_string);
  605. }
  606. return new_id;
  607. }
  608. LLAssetID LLTransactionID::makeAssetID(const LLUUID& session) const
  609. {
  610. LLAssetID result;
  611. if (isNull())
  612. {
  613. result.setNull();
  614. }
  615. else
  616. {
  617. combine(session, result);
  618. }
  619. return result;
  620. }