PageRenderTime 46ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llcommon/lluuid.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 924 lines | 651 code | 104 blank | 169 comment | 126 complexity | 026675afc5272f70873b23a53744e453 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file lluuid.cpp
  3. *
  4. * $LicenseInfo:firstyear=2000&license=viewerlgpl$
  5. * Second Life Viewer Source Code
  6. * Copyright (C) 2010, Linden Research, Inc.
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation;
  11. * version 2.1 of the License only.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. *
  22. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  23. * $/LicenseInfo$
  24. */
  25. #include "linden_common.h"
  26. // We can't use WIN32_LEAN_AND_MEAN here, needs lots of includes.
  27. #if LL_WINDOWS
  28. #undef WIN32_LEAN_AND_MEAN
  29. #include <winsock2.h>
  30. #include <windows.h>
  31. // ugh, this is ugly. We need to straighten out our linking for this library
  32. #pragma comment(lib, "IPHLPAPI.lib")
  33. #include <iphlpapi.h>
  34. #endif
  35. #include "lldefs.h"
  36. #include "llerror.h"
  37. #include "lluuid.h"
  38. #include "llerror.h"
  39. #include "llrand.h"
  40. #include "llmd5.h"
  41. #include "llstring.h"
  42. #include "lltimer.h"
  43. const LLUUID LLUUID::null;
  44. const LLTransactionID LLTransactionID::tnull;
  45. /*
  46. NOT DONE YET!!!
  47. static char BASE85_TABLE[] = {
  48. '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
  49. 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
  50. 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
  51. 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
  52. 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
  53. 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
  54. 'y', 'z', '!', '#', '$', '%', '&', '(', ')', '*',
  55. '+', '-', ';', '[', '=', '>', '?', '@', '^', '_',
  56. '`', '{', '|', '}', '~', '\0'
  57. };
  58. void encode( char * fiveChars, unsigned int word ) throw( )
  59. {
  60. for( int ix = 0; ix < 5; ++ix ) {
  61. fiveChars[4-ix] = encodeTable[ word % 85];
  62. word /= 85;
  63. }
  64. }
  65. To decode:
  66. unsigned int decode( char const * fiveChars ) throw( bad_input_data )
  67. {
  68. unsigned int ret = 0;
  69. for( int ix = 0; ix < 5; ++ix ) {
  70. char * s = strchr( encodeTable, fiveChars[ ix ] );
  71. if( s == 0 ) throw bad_input_data();
  72. ret = ret * 85 + (s-encodeTable);
  73. }
  74. return ret;
  75. }
  76. void LLUUID::toBase85(char* out)
  77. {
  78. U32* me = (U32*)&(mData[0]);
  79. for(S32 i = 0; i < 4; ++i)
  80. {
  81. char* o = &out[i*i];
  82. for(S32 j = 0; j < 5; ++j)
  83. {
  84. o[4-j] = BASE85_TABLE[ me[i] % 85];
  85. word /= 85;
  86. }
  87. }
  88. }
  89. unsigned int decode( char const * fiveChars ) throw( bad_input_data )
  90. {
  91. unsigned int ret = 0;
  92. for( S32 ix = 0; ix < 5; ++ix )
  93. {
  94. char * s = strchr( encodeTable, fiveChars[ ix ] );
  95. ret = ret * 85 + (s-encodeTable);
  96. }
  97. return ret;
  98. }
  99. */
  100. #define LL_USE_JANKY_RANDOM_NUMBER_GENERATOR 0
  101. #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR
  102. /**
  103. * @brief a global for
  104. */
  105. static U64 sJankyRandomSeed(LLUUID::getRandomSeed());
  106. /**
  107. * @brief generate a random U32.
  108. */
  109. U32 janky_fast_random_bytes()
  110. {
  111. sJankyRandomSeed = U64L(1664525) * sJankyRandomSeed + U64L(1013904223);
  112. return (U32)sJankyRandomSeed;
  113. }
  114. /**
  115. * @brief generate a random U32 from [0, val)
  116. */
  117. U32 janky_fast_random_byes_range(U32 val)
  118. {
  119. sJankyRandomSeed = U64L(1664525) * sJankyRandomSeed + U64L(1013904223);
  120. return (U32)(sJankyRandomSeed) % val;
  121. }
  122. /**
  123. * @brief generate a random U32 from [0, val)
  124. */
  125. U32 janky_fast_random_seeded_bytes(U32 seed, U32 val)
  126. {
  127. seed = U64L(1664525) * (U64)(seed) + U64L(1013904223);
  128. return (U32)(seed) % val;
  129. }
  130. #endif
  131. // Common to all UUID implementations
  132. void LLUUID::toString(std::string& out) const
  133. {
  134. out = llformat(
  135. "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
  136. (U8)(mData[0]),
  137. (U8)(mData[1]),
  138. (U8)(mData[2]),
  139. (U8)(mData[3]),
  140. (U8)(mData[4]),
  141. (U8)(mData[5]),
  142. (U8)(mData[6]),
  143. (U8)(mData[7]),
  144. (U8)(mData[8]),
  145. (U8)(mData[9]),
  146. (U8)(mData[10]),
  147. (U8)(mData[11]),
  148. (U8)(mData[12]),
  149. (U8)(mData[13]),
  150. (U8)(mData[14]),
  151. (U8)(mData[15]));
  152. }
  153. // *TODO: deprecate
  154. void LLUUID::toString(char *out) const
  155. {
  156. std::string buffer;
  157. toString(buffer);
  158. strcpy(out,buffer.c_str()); /* Flawfinder: ignore */
  159. }
  160. void LLUUID::toCompressedString(std::string& out) const
  161. {
  162. char bytes[UUID_BYTES+1];
  163. memcpy(bytes, mData, UUID_BYTES); /* Flawfinder: ignore */
  164. bytes[UUID_BYTES] = '\0';
  165. out.assign(bytes, UUID_BYTES);
  166. }
  167. // *TODO: deprecate
  168. void LLUUID::toCompressedString(char *out) const
  169. {
  170. memcpy(out, mData, UUID_BYTES); /* Flawfinder: ignore */
  171. out[UUID_BYTES] = '\0';
  172. }
  173. std::string LLUUID::getString() const
  174. {
  175. return asString();
  176. }
  177. std::string LLUUID::asString() const
  178. {
  179. std::string str;
  180. toString(str);
  181. return str;
  182. }
  183. BOOL LLUUID::set(const char* in_string, BOOL emit)
  184. {
  185. return set(ll_safe_string(in_string),emit);
  186. }
  187. BOOL LLUUID::set(const std::string& in_string, BOOL emit)
  188. {
  189. BOOL broken_format = FALSE;
  190. // empty strings should make NULL uuid
  191. if (in_string.empty())
  192. {
  193. setNull();
  194. return TRUE;
  195. }
  196. if (in_string.length() != (UUID_STR_LENGTH - 1)) /* Flawfinder: ignore */
  197. {
  198. // I'm a moron. First implementation didn't have the right UUID format.
  199. // Shouldn't see any of these any more
  200. if (in_string.length() == (UUID_STR_LENGTH - 2)) /* Flawfinder: ignore */
  201. {
  202. if(emit)
  203. {
  204. llwarns << "Warning! Using broken UUID string format" << llendl;
  205. }
  206. broken_format = TRUE;
  207. }
  208. else
  209. {
  210. // Bad UUID string. Spam as INFO, as most cases we don't care.
  211. if(emit)
  212. {
  213. //don't spam the logs because a resident can't spell.
  214. llwarns << "Bad UUID string: " << in_string << llendl;
  215. }
  216. setNull();
  217. return FALSE;
  218. }
  219. }
  220. U8 cur_pos = 0;
  221. S32 i;
  222. for (i = 0; i < UUID_BYTES; i++)
  223. {
  224. if ((i == 4) || (i == 6) || (i == 8) || (i == 10))
  225. {
  226. cur_pos++;
  227. if (broken_format && (i==10))
  228. {
  229. // Missing - in the broken format
  230. cur_pos--;
  231. }
  232. }
  233. mData[i] = 0;
  234. if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9'))
  235. {
  236. mData[i] += (U8)(in_string[cur_pos] - '0');
  237. }
  238. else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <='f'))
  239. {
  240. mData[i] += (U8)(10 + in_string[cur_pos] - 'a');
  241. }
  242. else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <='F'))
  243. {
  244. mData[i] += (U8)(10 + in_string[cur_pos] - 'A');
  245. }
  246. else
  247. {
  248. if(emit)
  249. {
  250. llwarns << "Invalid UUID string character" << llendl;
  251. }
  252. setNull();
  253. return FALSE;
  254. }
  255. mData[i] = mData[i] << 4;
  256. cur_pos++;
  257. if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9'))
  258. {
  259. mData[i] += (U8)(in_string[cur_pos] - '0');
  260. }
  261. else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <='f'))
  262. {
  263. mData[i] += (U8)(10 + in_string[cur_pos] - 'a');
  264. }
  265. else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <='F'))
  266. {
  267. mData[i] += (U8)(10 + in_string[cur_pos] - 'A');
  268. }
  269. else
  270. {
  271. if(emit)
  272. {
  273. llwarns << "Invalid UUID string character" << llendl;
  274. }
  275. setNull();
  276. return FALSE;
  277. }
  278. cur_pos++;
  279. }
  280. return TRUE;
  281. }
  282. BOOL LLUUID::validate(const std::string& in_string)
  283. {
  284. BOOL broken_format = FALSE;
  285. if (in_string.length() != (UUID_STR_LENGTH - 1)) /* Flawfinder: ignore */
  286. {
  287. // I'm a moron. First implementation didn't have the right UUID format.
  288. if (in_string.length() == (UUID_STR_LENGTH - 2)) /* Flawfinder: ignore */
  289. {
  290. broken_format = TRUE;
  291. }
  292. else
  293. {
  294. return FALSE;
  295. }
  296. }
  297. U8 cur_pos = 0;
  298. for (U32 i = 0; i < 16; i++)
  299. {
  300. if ((i == 4) || (i == 6) || (i == 8) || (i == 10))
  301. {
  302. cur_pos++;
  303. if (broken_format && (i==10))
  304. {
  305. // Missing - in the broken format
  306. cur_pos--;
  307. }
  308. }
  309. if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9'))
  310. {
  311. }
  312. else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <='f'))
  313. {
  314. }
  315. else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <='F'))
  316. {
  317. }
  318. else
  319. {
  320. return FALSE;
  321. }
  322. cur_pos++;
  323. if ((in_string[cur_pos] >= '0') && (in_string[cur_pos] <= '9'))
  324. {
  325. }
  326. else if ((in_string[cur_pos] >= 'a') && (in_string[cur_pos] <='f'))
  327. {
  328. }
  329. else if ((in_string[cur_pos] >= 'A') && (in_string[cur_pos] <='F'))
  330. {
  331. }
  332. else
  333. {
  334. return FALSE;
  335. }
  336. cur_pos++;
  337. }
  338. return TRUE;
  339. }
  340. const LLUUID& LLUUID::operator^=(const LLUUID& rhs)
  341. {
  342. U32* me = (U32*)&(mData[0]);
  343. const U32* other = (U32*)&(rhs.mData[0]);
  344. for(S32 i = 0; i < 4; ++i)
  345. {
  346. me[i] = me[i] ^ other[i];
  347. }
  348. return *this;
  349. }
  350. LLUUID LLUUID::operator^(const LLUUID& rhs) const
  351. {
  352. LLUUID id(*this);
  353. id ^= rhs;
  354. return id;
  355. }
  356. void LLUUID::combine(const LLUUID& other, LLUUID& result) const
  357. {
  358. LLMD5 md5_uuid;
  359. md5_uuid.update((unsigned char*)mData, 16);
  360. md5_uuid.update((unsigned char*)other.mData, 16);
  361. md5_uuid.finalize();
  362. md5_uuid.raw_digest(result.mData);
  363. }
  364. LLUUID LLUUID::combine(const LLUUID &other) const
  365. {
  366. LLUUID combination;
  367. combine(other, combination);
  368. return combination;
  369. }
  370. std::ostream& operator<<(std::ostream& s, const LLUUID &uuid)
  371. {
  372. std::string uuid_str;
  373. uuid.toString(uuid_str);
  374. s << uuid_str;
  375. return s;
  376. }
  377. std::istream& operator>>(std::istream &s, LLUUID &uuid)
  378. {
  379. U32 i;
  380. char uuid_str[UUID_STR_LENGTH]; /* Flawfinder: ignore */
  381. for (i = 0; i < UUID_STR_LENGTH-1; i++)
  382. {
  383. s >> uuid_str[i];
  384. }
  385. uuid_str[i] = '\0';
  386. uuid.set(std::string(uuid_str));
  387. return s;
  388. }
  389. static void get_random_bytes(void *buf, int nbytes)
  390. {
  391. int i;
  392. char *cp = (char *) buf;
  393. // *NOTE: If we are not using the janky generator ll_rand()
  394. // generates at least 3 good bytes of data since it is 0 to
  395. // RAND_MAX. This could be made more efficient by copying all the
  396. // bytes.
  397. for (i=0; i < nbytes; i++)
  398. #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR
  399. *cp++ = janky_fast_random_bytes() & 0xFF;
  400. #else
  401. *cp++ = ll_rand() & 0xFF;
  402. #endif
  403. return;
  404. }
  405. #if LL_WINDOWS
  406. typedef struct _ASTAT_
  407. {
  408. ADAPTER_STATUS adapt;
  409. NAME_BUFFER NameBuff [30];
  410. }ASTAT, * PASTAT;
  411. // static
  412. S32 LLUUID::getNodeID(unsigned char *node_id)
  413. {
  414. ASTAT Adapter;
  415. NCB Ncb;
  416. UCHAR uRetCode;
  417. LANA_ENUM lenum;
  418. int i;
  419. int retval = 0;
  420. memset( &Ncb, 0, sizeof(Ncb) );
  421. Ncb.ncb_command = NCBENUM;
  422. Ncb.ncb_buffer = (UCHAR *)&lenum;
  423. Ncb.ncb_length = sizeof(lenum);
  424. uRetCode = Netbios( &Ncb );
  425. for(i=0; i < lenum.length ;i++)
  426. {
  427. memset( &Ncb, 0, sizeof(Ncb) );
  428. Ncb.ncb_command = NCBRESET;
  429. Ncb.ncb_lana_num = lenum.lana[i];
  430. uRetCode = Netbios( &Ncb );
  431. memset( &Ncb, 0, sizeof (Ncb) );
  432. Ncb.ncb_command = NCBASTAT;
  433. Ncb.ncb_lana_num = lenum.lana[i];
  434. strcpy( (char *)Ncb.ncb_callname, "* " ); /* Flawfinder: ignore */
  435. Ncb.ncb_buffer = (unsigned char *)&Adapter;
  436. Ncb.ncb_length = sizeof(Adapter);
  437. uRetCode = Netbios( &Ncb );
  438. if ( uRetCode == 0 )
  439. {
  440. memcpy(node_id,Adapter.adapt.adapter_address,6); /* Flawfinder: ignore */
  441. retval = 1;
  442. }
  443. }
  444. return retval;
  445. }
  446. #elif LL_DARWIN
  447. // Mac OS X version of the UUID generation code...
  448. /*
  449. * Get an ethernet hardware address, if we can find it...
  450. */
  451. #include <unistd.h>
  452. #include <sys/types.h>
  453. #include <sys/time.h>
  454. #include <sys/socket.h>
  455. #include <sys/ioctl.h>
  456. #include <net/if.h>
  457. #include <net/if_types.h>
  458. #include <net/if_dl.h>
  459. #include <net/route.h>
  460. #include <ifaddrs.h>
  461. // static
  462. S32 LLUUID::getNodeID(unsigned char *node_id)
  463. {
  464. int i;
  465. unsigned char *a = NULL;
  466. struct ifaddrs *ifap, *ifa;
  467. int rv;
  468. S32 result = 0;
  469. if ((rv=getifaddrs(&ifap))==-1)
  470. {
  471. return -1;
  472. }
  473. if (ifap == NULL)
  474. {
  475. return -1;
  476. }
  477. for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
  478. {
  479. // printf("Interface %s, address family %d, ", ifa->ifa_name, ifa->ifa_addr->sa_family);
  480. for(i=0; i< ifa->ifa_addr->sa_len; i++)
  481. {
  482. // printf("%02X ", (unsigned char)ifa->ifa_addr->sa_data[i]);
  483. }
  484. // printf("\n");
  485. if(ifa->ifa_addr->sa_family == AF_LINK)
  486. {
  487. // This is a link-level address
  488. struct sockaddr_dl *lla = (struct sockaddr_dl *)ifa->ifa_addr;
  489. // printf("\tLink level address, type %02X\n", lla->sdl_type);
  490. if(lla->sdl_type == IFT_ETHER)
  491. {
  492. // Use the first ethernet MAC in the list.
  493. // For some reason, the macro LLADDR() defined in net/if_dl.h doesn't expand correctly. This is what it would do.
  494. a = (unsigned char *)&((lla)->sdl_data);
  495. a += (lla)->sdl_nlen;
  496. if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
  497. {
  498. continue;
  499. }
  500. if (node_id)
  501. {
  502. memcpy(node_id, a, 6);
  503. result = 1;
  504. }
  505. // We found one.
  506. break;
  507. }
  508. }
  509. }
  510. freeifaddrs(ifap);
  511. return result;
  512. }
  513. #else
  514. // Linux version of the UUID generation code...
  515. /*
  516. * Get the ethernet hardware address, if we can find it...
  517. */
  518. #include <unistd.h>
  519. #include <fcntl.h>
  520. #include <errno.h>
  521. #include <sys/types.h>
  522. #include <sys/time.h>
  523. #include <sys/stat.h>
  524. #include <sys/file.h>
  525. #include <sys/ioctl.h>
  526. #include <sys/socket.h>
  527. #include <net/if.h>
  528. #define HAVE_NETINET_IN_H
  529. #ifdef HAVE_NETINET_IN_H
  530. #include <netinet/in.h>
  531. #if LL_SOLARIS
  532. #include <sys/sockio.h>
  533. #elif !LL_DARWIN
  534. #include <linux/sockios.h>
  535. #endif
  536. #endif
  537. // static
  538. S32 LLUUID::getNodeID(unsigned char *node_id)
  539. {
  540. int sd;
  541. struct ifreq ifr, *ifrp;
  542. struct ifconf ifc;
  543. char buf[1024];
  544. int n, i;
  545. unsigned char *a;
  546. /*
  547. * BSD 4.4 defines the size of an ifreq to be
  548. * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
  549. * However, under earlier systems, sa_len isn't present, so the size is
  550. * just sizeof(struct ifreq)
  551. */
  552. #ifdef HAVE_SA_LEN
  553. #ifndef max
  554. #define max(a,b) ((a) > (b) ? (a) : (b))
  555. #endif
  556. #define ifreq_size(i) max(sizeof(struct ifreq),\
  557. sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
  558. #else
  559. #define ifreq_size(i) sizeof(struct ifreq)
  560. #endif /* HAVE_SA_LEN*/
  561. sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
  562. if (sd < 0) {
  563. return -1;
  564. }
  565. memset(buf, 0, sizeof(buf));
  566. ifc.ifc_len = sizeof(buf);
  567. ifc.ifc_buf = buf;
  568. if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) {
  569. close(sd);
  570. return -1;
  571. }
  572. n = ifc.ifc_len;
  573. for (i = 0; i < n; i+= ifreq_size(*ifr) ) {
  574. ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
  575. strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); /* Flawfinder: ignore */
  576. #ifdef SIOCGIFHWADDR
  577. if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
  578. continue;
  579. a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
  580. #else
  581. #ifdef SIOCGENADDR
  582. if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
  583. continue;
  584. a = (unsigned char *) ifr.ifr_enaddr;
  585. #else
  586. /*
  587. * XXX we don't have a way of getting the hardware
  588. * address
  589. */
  590. close(sd);
  591. return 0;
  592. #endif /* SIOCGENADDR */
  593. #endif /* SIOCGIFHWADDR */
  594. if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
  595. continue;
  596. if (node_id) {
  597. memcpy(node_id, a, 6); /* Flawfinder: ignore */
  598. close(sd);
  599. return 1;
  600. }
  601. }
  602. close(sd);
  603. return 0;
  604. }
  605. #endif
  606. S32 LLUUID::cmpTime(uuid_time_t *t1, uuid_time_t *t2)
  607. {
  608. // Compare two time values.
  609. if (t1->high < t2->high) return -1;
  610. if (t1->high > t2->high) return 1;
  611. if (t1->low < t2->low) return -1;
  612. if (t1->low > t2->low) return 1;
  613. return 0;
  614. }
  615. void LLUUID::getSystemTime(uuid_time_t *timestamp)
  616. {
  617. // Get system time with 100ns precision. Time is since Oct 15, 1582.
  618. #if LL_WINDOWS
  619. ULARGE_INTEGER time;
  620. GetSystemTimeAsFileTime((FILETIME *)&time);
  621. // NT keeps time in FILETIME format which is 100ns ticks since
  622. // Jan 1, 1601. UUIDs use time in 100ns ticks since Oct 15, 1582.
  623. // The difference is 17 Days in Oct + 30 (Nov) + 31 (Dec)
  624. // + 18 years and 5 leap days.
  625. time.QuadPart +=
  626. (unsigned __int64) (1000*1000*10) // seconds
  627. * (unsigned __int64) (60 * 60 * 24) // days
  628. * (unsigned __int64) (17+30+31+365*18+5); // # of days
  629. timestamp->high = time.HighPart;
  630. timestamp->low = time.LowPart;
  631. #else
  632. struct timeval tp;
  633. gettimeofday(&tp, 0);
  634. // Offset between UUID formatted times and Unix formatted times.
  635. // UUID UTC base time is October 15, 1582.
  636. // Unix base time is January 1, 1970.
  637. U64 uuid_time = ((U64)tp.tv_sec * 10000000) + (tp.tv_usec * 10) +
  638. U64L(0x01B21DD213814000);
  639. timestamp->high = (U32) (uuid_time >> 32);
  640. timestamp->low = (U32) (uuid_time & 0xFFFFFFFF);
  641. #endif
  642. }
  643. void LLUUID::getCurrentTime(uuid_time_t *timestamp)
  644. {
  645. // Get current time as 60 bit 100ns ticks since whenever.
  646. // Compensate for the fact that real clock resolution is less
  647. // than 100ns.
  648. const U32 uuids_per_tick = 1024;
  649. static uuid_time_t time_last;
  650. static U32 uuids_this_tick;
  651. static BOOL init = FALSE;
  652. if (!init) {
  653. getSystemTime(&time_last);
  654. uuids_this_tick = uuids_per_tick;
  655. init = TRUE;
  656. }
  657. uuid_time_t time_now = {0,0};
  658. while (1) {
  659. getSystemTime(&time_now);
  660. // if clock reading changed since last UUID generated
  661. if (cmpTime(&time_last, &time_now)) {
  662. // reset count of uuid's generated with this clock reading
  663. uuids_this_tick = 0;
  664. break;
  665. }
  666. if (uuids_this_tick < uuids_per_tick) {
  667. uuids_this_tick++;
  668. break;
  669. }
  670. // going too fast for our clock; spin
  671. }
  672. time_last = time_now;
  673. if (uuids_this_tick != 0) {
  674. if (time_now.low & 0x80000000) {
  675. time_now.low += uuids_this_tick;
  676. if (!(time_now.low & 0x80000000))
  677. time_now.high++;
  678. } else
  679. time_now.low += uuids_this_tick;
  680. }
  681. timestamp->high = time_now.high;
  682. timestamp->low = time_now.low;
  683. }
  684. void LLUUID::generate()
  685. {
  686. // Create a UUID.
  687. uuid_time_t timestamp;
  688. static unsigned char node_id[6]; /* Flawfinder: ignore */
  689. static int has_init = 0;
  690. // Create a UUID.
  691. static uuid_time_t time_last = {0,0};
  692. static U16 clock_seq = 0;
  693. #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR
  694. static U32 seed = 0L; // dummy seed. reset it below
  695. #endif
  696. if (!has_init)
  697. {
  698. if (getNodeID(node_id) <= 0)
  699. {
  700. get_random_bytes(node_id, 6);
  701. /*
  702. * Set multicast bit, to prevent conflicts
  703. * with IEEE 802 addresses obtained from
  704. * network cards
  705. */
  706. node_id[0] |= 0x80;
  707. }
  708. getCurrentTime(&time_last);
  709. #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR
  710. seed = time_last.low;
  711. #endif
  712. #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR
  713. clock_seq = (U16)janky_fast_random_seeded_bytes(seed, 65536);
  714. #else
  715. clock_seq = (U16)ll_rand(65536);
  716. #endif
  717. has_init = 1;
  718. }
  719. // get current time
  720. getCurrentTime(&timestamp);
  721. // if clock went backward change clockseq
  722. if (cmpTime(&timestamp, &time_last) == -1) {
  723. clock_seq = (clock_seq + 1) & 0x3FFF;
  724. if (clock_seq == 0) clock_seq++;
  725. }
  726. memcpy(mData+10, node_id, 6); /* Flawfinder: ignore */
  727. U32 tmp;
  728. tmp = timestamp.low;
  729. mData[3] = (unsigned char) tmp;
  730. tmp >>= 8;
  731. mData[2] = (unsigned char) tmp;
  732. tmp >>= 8;
  733. mData[1] = (unsigned char) tmp;
  734. tmp >>= 8;
  735. mData[0] = (unsigned char) tmp;
  736. tmp = (U16) timestamp.high;
  737. mData[5] = (unsigned char) tmp;
  738. tmp >>= 8;
  739. mData[4] = (unsigned char) tmp;
  740. tmp = (timestamp.high >> 16) | 0x1000;
  741. mData[7] = (unsigned char) tmp;
  742. tmp >>= 8;
  743. mData[6] = (unsigned char) tmp;
  744. tmp = clock_seq;
  745. mData[9] = (unsigned char) tmp;
  746. tmp >>= 8;
  747. mData[8] = (unsigned char) tmp;
  748. LLMD5 md5_uuid;
  749. md5_uuid.update(mData,16);
  750. md5_uuid.finalize();
  751. md5_uuid.raw_digest(mData);
  752. time_last = timestamp;
  753. }
  754. void LLUUID::generate(const std::string& hash_string)
  755. {
  756. LLMD5 md5_uuid((U8*)hash_string.c_str());
  757. md5_uuid.raw_digest(mData);
  758. }
  759. U32 LLUUID::getRandomSeed()
  760. {
  761. static unsigned char seed[16]; /* Flawfinder: ignore */
  762. getNodeID(&seed[0]);
  763. seed[6]='\0';
  764. seed[7]='\0';
  765. getSystemTime((uuid_time_t *)(&seed[8]));
  766. LLMD5 md5_seed;
  767. md5_seed.update(seed,16);
  768. md5_seed.finalize();
  769. md5_seed.raw_digest(seed);
  770. return(*(U32 *)seed);
  771. }
  772. BOOL LLUUID::parseUUID(const std::string& buf, LLUUID* value)
  773. {
  774. if( buf.empty() || value == NULL)
  775. {
  776. return FALSE;
  777. }
  778. std::string temp( buf );
  779. LLStringUtil::trim(temp);
  780. if( LLUUID::validate( temp ) )
  781. {
  782. value->set( temp );
  783. return TRUE;
  784. }
  785. return FALSE;
  786. }
  787. //static
  788. LLUUID LLUUID::generateNewID(std::string hash_string)
  789. {
  790. LLUUID new_id;
  791. if (hash_string.empty())
  792. {
  793. new_id.generate();
  794. }
  795. else
  796. {
  797. new_id.generate(hash_string);
  798. }
  799. return new_id;
  800. }
  801. LLAssetID LLTransactionID::makeAssetID(const LLUUID& session) const
  802. {
  803. LLAssetID result;
  804. if (isNull())
  805. {
  806. result.setNull();
  807. }
  808. else
  809. {
  810. combine(session, result);
  811. }
  812. return result;
  813. }