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