00001
00031 #include "linden_common.h"
00032
00033
00034 #if LL_WINDOWS
00035 # undef WIN32_LEAN_AND_MEAN
00036 # include <winsock2.h>
00037 # include <windows.h>
00038 #endif
00039
00040 #include "lldefs.h"
00041 #include "llerror.h"
00042
00043 #include "lluuid.h"
00044 #include "llerror.h"
00045 #include "llrand.h"
00046 #include "llmd5.h"
00047 #include "llstring.h"
00048 #include "lltimer.h"
00049
00050 const LLUUID LLUUID::null;
00051 const LLTransactionID LLTransactionID::tnull;
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116 #define LL_USE_JANKY_RANDOM_NUMBER_GENERATOR 0
00117 #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR
00118
00121 static U64 sJankyRandomSeed(LLUUID::getRandomSeed());
00122
00126 U32 janky_fast_random_bytes()
00127 {
00128 sJankyRandomSeed = U64L(1664525) * sJankyRandomSeed + U64L(1013904223);
00129 return (U32)sJankyRandomSeed;
00130 }
00131
00135 U32 janky_fast_random_byes_range(U32 val)
00136 {
00137 sJankyRandomSeed = U64L(1664525) * sJankyRandomSeed + U64L(1013904223);
00138 return (U32)(sJankyRandomSeed) % val;
00139 }
00140
00144 U32 janky_fast_random_seeded_bytes(U32 seed, U32 val)
00145 {
00146 seed = U64L(1664525) * (U64)(seed) + U64L(1013904223);
00147 return (U32)(seed) % val;
00148 }
00149 #endif
00150
00151
00152 void LLUUID::toString(char *out) const
00153 {
00154 sprintf(out,
00155 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
00156 (U8)(mData[0]),
00157 (U8)(mData[1]),
00158 (U8)(mData[2]),
00159 (U8)(mData[3]),
00160 (U8)(mData[4]),
00161 (U8)(mData[5]),
00162 (U8)(mData[6]),
00163 (U8)(mData[7]),
00164 (U8)(mData[8]),
00165 (U8)(mData[9]),
00166 (U8)(mData[10]),
00167 (U8)(mData[11]),
00168 (U8)(mData[12]),
00169 (U8)(mData[13]),
00170 (U8)(mData[14]),
00171 (U8)(mData[15]));
00172 }
00173
00174 void LLUUID::toCompressedString(char *out) const
00175 {
00176 memcpy(out, mData, UUID_BYTES);
00177 out[UUID_BYTES] = '\0';
00178 }
00179
00180 std::string LLUUID::getString() const
00181 {
00182 return asString();
00183 }
00184
00185 std::string LLUUID::asString() const
00186 {
00187 char str[UUID_STR_SIZE];
00188 toString(str);
00189 return std::string(str);
00190 }
00191
00192 BOOL LLUUID::set(const std::string& in_string, BOOL emit)
00193 {
00194 return set(in_string.c_str(), emit);
00195 }
00196
00197 BOOL LLUUID::set(const char *in_string, BOOL emit)
00198 {
00199 BOOL broken_format = FALSE;
00200 if (!in_string)
00201 {
00202 llerrs << "No string pointer in LLUUID::set!" << llendl;
00203 setNull();
00204 return FALSE;
00205 }
00206
00207
00208 if (!in_string[0])
00209 {
00210 setNull();
00211 return TRUE;
00212 }
00213
00214 if (strlen(in_string) != (UUID_STR_LENGTH - 1))
00215 {
00216
00217
00218 if (strlen(in_string) == (UUID_STR_LENGTH - 2))
00219 {
00220 if(emit)
00221 {
00222 llinfos << "Warning! Using broken UUID string format" << llendl;
00223 }
00224 broken_format = TRUE;
00225 }
00226 else
00227 {
00228
00229 if(emit)
00230 {
00231 llinfos << "Bad UUID string: " << in_string << llendl;
00232 }
00233 setNull();
00234 return FALSE;
00235 }
00236 }
00237
00238 U8 cur_pos = 0;
00239 S32 i;
00240 for (i = 0; i < UUID_BYTES; i++)
00241 {
00242 if ((i == 4) || (i == 6) || (i == 8) || (i == 10))
00243 {
00244 cur_pos++;
00245 if (broken_format && (i==10))
00246 {
00247
00248 cur_pos--;
00249 }
00250 }
00251
00252 mData[i] = 0;
00253
00254 if ((*(in_string + cur_pos) >= '0') && (*(in_string+cur_pos) <= '9'))
00255 {
00256 mData[i] += (U8)(*(in_string + cur_pos) - '0');
00257 }
00258 else if ((*(in_string + cur_pos) >= 'a') && (*(in_string+cur_pos) <='f'))
00259 {
00260 mData[i] += (U8)(10 + *(in_string + cur_pos) - 'a');
00261 }
00262 else if ((*(in_string + cur_pos) >= 'A') && (*(in_string+cur_pos) <='F'))
00263 {
00264 mData[i] += (U8)(10 + *(in_string + cur_pos) - 'A');
00265 }
00266 else
00267 {
00268 if(emit)
00269 {
00270 llwarns << "Invalid UUID string character" << llendl;
00271 }
00272 setNull();
00273 return FALSE;
00274 }
00275
00276 mData[i] = mData[i] << 4;
00277 cur_pos++;
00278
00279 if ((*(in_string + cur_pos) >= '0') && (*(in_string+cur_pos) <= '9'))
00280 {
00281 mData[i] += (U8)(*(in_string + cur_pos) - '0');
00282 }
00283 else if ((*(in_string + cur_pos) >= 'a') && (*(in_string+cur_pos) <='f'))
00284 {
00285 mData[i] += (U8)(10 + *(in_string + cur_pos) - 'a');
00286 }
00287 else if ((*(in_string + cur_pos) >= 'A') && (*(in_string+cur_pos) <='F'))
00288 {
00289 mData[i] += (U8)(10 + *(in_string + cur_pos) - 'A');
00290 }
00291 else
00292 {
00293 if(emit)
00294 {
00295 llwarns << "Invalid UUID string character" << llendl;
00296 }
00297 setNull();
00298 return FALSE;
00299 }
00300 cur_pos++;
00301 }
00302
00303 return TRUE;
00304 }
00305
00306 BOOL LLUUID::validate(const std::string& in_string)
00307 {
00308 return validate(in_string.c_str());
00309 }
00310
00311 BOOL LLUUID::validate(const char *in_string)
00312 {
00313 BOOL broken_format = FALSE;
00314 if (!in_string)
00315 {
00316 return FALSE;
00317 }
00318 if (strlen(in_string) != (UUID_STR_LENGTH - 1))
00319 {
00320
00321 if (strlen(in_string) == (UUID_STR_LENGTH - 2))
00322 {
00323 broken_format = TRUE;
00324 }
00325 else
00326 {
00327 return FALSE;
00328 }
00329 }
00330
00331 U8 cur_pos = 0;
00332 U32 i;
00333 for (i = 0; i < 16; i++)
00334 {
00335 if ((i == 4) || (i == 6) || (i == 8) || (i == 10))
00336 {
00337 cur_pos++;
00338 if (broken_format && (i==10))
00339 {
00340
00341 cur_pos--;
00342 }
00343 }
00344
00345 if ((*(in_string + cur_pos) >= '0') && (*(in_string+cur_pos) <= '9'))
00346 {
00347 }
00348 else if ((*(in_string + cur_pos) >= 'a') && (*(in_string+cur_pos) <='f'))
00349 {
00350 }
00351 else if ((*(in_string + cur_pos) >= 'A') && (*(in_string+cur_pos) <='F'))
00352 {
00353 }
00354 else
00355 {
00356 return FALSE;
00357 }
00358
00359 cur_pos++;
00360
00361 if ((*(in_string + cur_pos) >= '0') && (*(in_string+cur_pos) <= '9'))
00362 {
00363 }
00364 else if ((*(in_string + cur_pos) >= 'a') && (*(in_string+cur_pos) <='f'))
00365 {
00366 }
00367 else if ((*(in_string + cur_pos) >= 'A') && (*(in_string+cur_pos) <='F'))
00368 {
00369 }
00370 else
00371 {
00372 return FALSE;
00373 }
00374 cur_pos++;
00375 }
00376 return TRUE;
00377 }
00378
00379 const LLUUID& LLUUID::operator^=(const LLUUID& rhs)
00380 {
00381 U32* me = (U32*)&(mData[0]);
00382 const U32* other = (U32*)&(rhs.mData[0]);
00383 for(S32 i = 0; i < 4; ++i)
00384 {
00385 me[i] = me[i] ^ other[i];
00386 }
00387 return *this;
00388 }
00389
00390 LLUUID LLUUID::operator^(const LLUUID& rhs) const
00391 {
00392 LLUUID id(*this);
00393 id ^= rhs;
00394 return id;
00395 }
00396
00397 void LLUUID::combine(const LLUUID& other, LLUUID& result) const
00398 {
00399 LLMD5 md5_uuid;
00400 md5_uuid.update((unsigned char*)mData, 16);
00401 md5_uuid.update((unsigned char*)other.mData, 16);
00402 md5_uuid.finalize();
00403 md5_uuid.raw_digest(result.mData);
00404 }
00405
00406 LLUUID LLUUID::combine(const LLUUID &other) const
00407 {
00408 LLUUID combination;
00409 combine(other, combination);
00410 return combination;
00411 }
00412
00413 std::ostream& operator<<(std::ostream& s, const LLUUID &uuid)
00414 {
00415 char uuid_str[UUID_STR_LENGTH];
00416
00417 uuid.toString(uuid_str);
00418 s << uuid_str;
00419 return s;
00420 }
00421
00422 std::istream& operator>>(std::istream &s, LLUUID &uuid)
00423 {
00424 U32 i;
00425 char uuid_str[UUID_STR_LENGTH];
00426 for (i = 0; i < UUID_STR_LENGTH-1; i++)
00427 {
00428 s >> uuid_str[i];
00429 }
00430 uuid_str[i] = '\0';
00431 uuid.set(uuid_str);
00432 return s;
00433 }
00434
00435 static void get_random_bytes(void *buf, int nbytes)
00436 {
00437 int i;
00438 char *cp = (char *) buf;
00439
00440
00441
00442
00443
00444 for (i=0; i < nbytes; i++)
00445 #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR
00446 *cp++ = janky_fast_random_bytes() & 0xFF;
00447 #else
00448 *cp++ = ll_rand() & 0xFF;
00449 #endif
00450 return;
00451 }
00452
00453 #if LL_WINDOWS
00454 typedef struct _ASTAT_
00455 {
00456 ADAPTER_STATUS adapt;
00457 NAME_BUFFER NameBuff [30];
00458 }ASTAT, * PASTAT;
00459
00460
00461 S32 LLUUID::getNodeID(unsigned char * node_id)
00462 {
00463 ASTAT Adapter;
00464 NCB Ncb;
00465 UCHAR uRetCode;
00466 LANA_ENUM lenum;
00467 int i;
00468 int retval = 0;
00469
00470 memset( &Ncb, 0, sizeof(Ncb) );
00471 Ncb.ncb_command = NCBENUM;
00472 Ncb.ncb_buffer = (UCHAR *)&lenum;
00473 Ncb.ncb_length = sizeof(lenum);
00474 uRetCode = Netbios( &Ncb );
00475
00476
00477 for(i=0; i < lenum.length ;i++)
00478 {
00479 memset( &Ncb, 0, sizeof(Ncb) );
00480 Ncb.ncb_command = NCBRESET;
00481 Ncb.ncb_lana_num = lenum.lana[i];
00482
00483 uRetCode = Netbios( &Ncb );
00484
00485
00486
00487 memset( &Ncb, 0, sizeof (Ncb) );
00488 Ncb.ncb_command = NCBASTAT;
00489 Ncb.ncb_lana_num = lenum.lana[i];
00490
00491 strcpy( (char *)Ncb.ncb_callname, "* " );
00492 Ncb.ncb_buffer = (unsigned char *)&Adapter;
00493 Ncb.ncb_length = sizeof(Adapter);
00494
00495 uRetCode = Netbios( &Ncb );
00496
00497
00498 if ( uRetCode == 0 )
00499 {
00500
00501
00502
00503
00504
00505
00506
00507
00508 memcpy(node_id,Adapter.adapt.adapter_address,6);
00509 retval = 1;
00510
00511 }
00512 }
00513 return retval;
00514 }
00515
00516 #elif LL_DARWIN
00517
00518
00519
00520
00521 #include <unistd.h>
00522 #include <sys/types.h>
00523 #include <sys/time.h>
00524 #include <sys/socket.h>
00525 #include <sys/ioctl.h>
00526 #include <net/if.h>
00527 #include <net/if_types.h>
00528 #include <net/if_dl.h>
00529 #include <net/route.h>
00530 #include <ifaddrs.h>
00531
00532
00533 S32 LLUUID::getNodeID(unsigned char *node_id)
00534 {
00535 int i;
00536 unsigned char *a = NULL;
00537 struct ifaddrs *ifap, *ifa;
00538 int rv;
00539 S32 result = 0;
00540
00541 if ((rv=getifaddrs(&ifap))==-1)
00542 {
00543 return -1;
00544 }
00545 if (ifap == NULL)
00546 {
00547 return -1;
00548 }
00549
00550 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
00551 {
00552
00553 for(i=0; i< ifa->ifa_addr->sa_len; i++)
00554 {
00555
00556 }
00557
00558
00559 if(ifa->ifa_addr->sa_family == AF_LINK)
00560 {
00561
00562 struct sockaddr_dl *lla = (struct sockaddr_dl *)ifa->ifa_addr;
00563
00564
00565
00566 if(lla->sdl_type == IFT_ETHER)
00567 {
00568
00569
00570 a = (unsigned char *)&((lla)->sdl_data);
00571 a += (lla)->sdl_nlen;
00572
00573 if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
00574 {
00575 continue;
00576 }
00577
00578 if (node_id)
00579 {
00580 memcpy(node_id, a, 6);
00581 result = 1;
00582 }
00583
00584
00585 break;
00586 }
00587 }
00588 }
00589 freeifaddrs(ifap);
00590
00591 return result;
00592 }
00593
00594 #else
00595
00596
00597
00598
00599
00600 #include <unistd.h>
00601 #include <fcntl.h>
00602 #include <errno.h>
00603 #include <sys/types.h>
00604 #include <sys/time.h>
00605 #include <sys/stat.h>
00606 #include <sys/file.h>
00607 #include <sys/ioctl.h>
00608 #include <sys/socket.h>
00609 #include <net/if.h>
00610 #define HAVE_NETINET_IN_H
00611 #ifdef HAVE_NETINET_IN_H
00612 #include <netinet/in.h>
00613 #if LL_SOLARIS
00614 #include <sys/sockio.h>
00615 #elif !LL_DARWIN
00616 #include <linux/sockios.h>
00617 #endif
00618 #endif
00619
00620
00621 S32 LLUUID::getNodeID(unsigned char *node_id)
00622 {
00623 int sd;
00624 struct ifreq ifr, *ifrp;
00625 struct ifconf ifc;
00626 char buf[1024];
00627 int n, i;
00628 unsigned char *a;
00629
00630
00631
00632
00633
00634
00635
00636 #ifdef HAVE_SA_LEN
00637 #ifndef max
00638 #define max(a,b) ((a) > (b) ? (a) : (b))
00639 #endif
00640 #define ifreq_size(i) max(sizeof(struct ifreq),\
00641 sizeof((i).ifr_name)+(i).ifr_addr.sa_len)
00642 #else
00643 #define ifreq_size(i) sizeof(struct ifreq)
00644 #endif
00645
00646 sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
00647 if (sd < 0) {
00648 return -1;
00649 }
00650 memset(buf, 0, sizeof(buf));
00651 ifc.ifc_len = sizeof(buf);
00652 ifc.ifc_buf = buf;
00653 if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) {
00654 close(sd);
00655 return -1;
00656 }
00657 n = ifc.ifc_len;
00658 for (i = 0; i < n; i+= ifreq_size(*ifr) ) {
00659 ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i);
00660 strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
00661 #ifdef SIOCGIFHWADDR
00662 if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
00663 continue;
00664 a = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
00665 #else
00666 #ifdef SIOCGENADDR
00667 if (ioctl(sd, SIOCGENADDR, &ifr) < 0)
00668 continue;
00669 a = (unsigned char *) ifr.ifr_enaddr;
00670 #else
00671
00672
00673
00674
00675 close(sd);
00676 return 0;
00677 #endif
00678 #endif
00679 if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5])
00680 continue;
00681 if (node_id) {
00682 memcpy(node_id, a, 6);
00683 close(sd);
00684 return 1;
00685 }
00686 }
00687 close(sd);
00688 return 0;
00689 }
00690
00691 #endif
00692
00693 S32 LLUUID::cmpTime(uuid_time_t *t1, uuid_time_t *t2)
00694 {
00695
00696
00697 if (t1->high < t2->high) return -1;
00698 if (t1->high > t2->high) return 1;
00699 if (t1->low < t2->low) return -1;
00700 if (t1->low > t2->low) return 1;
00701 return 0;
00702 }
00703
00704 void LLUUID::getSystemTime(uuid_time_t *timestamp)
00705 {
00706
00707 #if LL_WINDOWS
00708 ULARGE_INTEGER time;
00709 GetSystemTimeAsFileTime((FILETIME *)&time);
00710
00711
00712
00713
00714 time.QuadPart +=
00715 (unsigned __int64) (1000*1000*10)
00716 * (unsigned __int64) (60 * 60 * 24)
00717 * (unsigned __int64) (17+30+31+365*18+5);
00718
00719 timestamp->high = time.HighPart;
00720 timestamp->low = time.LowPart;
00721 #else
00722 struct timeval tp;
00723 gettimeofday(&tp, 0);
00724
00725
00726
00727
00728 U64 uuid_time = ((U64)tp.tv_sec * 10000000) + (tp.tv_usec * 10) +
00729 U64L(0x01B21DD213814000);
00730 timestamp->high = (U32) (uuid_time >> 32);
00731 timestamp->low = (U32) (uuid_time & 0xFFFFFFFF);
00732 #endif
00733 }
00734
00735 void LLUUID::getCurrentTime(uuid_time_t *timestamp)
00736 {
00737
00738
00739
00740
00741 const U32 uuids_per_tick = 1024;
00742
00743 static uuid_time_t time_last;
00744 static U32 uuids_this_tick;
00745 static BOOL init = FALSE;
00746
00747 if (!init) {
00748 getSystemTime(&time_last);
00749 uuids_this_tick = uuids_per_tick;
00750 init = TRUE;
00751 }
00752
00753 uuid_time_t time_now = {0,0};
00754
00755 while (1) {
00756 getSystemTime(&time_now);
00757
00758
00759 if (cmpTime(&time_last, &time_now)) {
00760
00761 uuids_this_tick = 0;
00762 break;
00763 }
00764 if (uuids_this_tick < uuids_per_tick) {
00765 uuids_this_tick++;
00766 break;
00767 }
00768
00769 }
00770
00771 time_last = time_now;
00772
00773 if (uuids_this_tick != 0) {
00774 if (time_now.low & 0x80000000) {
00775 time_now.low += uuids_this_tick;
00776 if (!(time_now.low & 0x80000000))
00777 time_now.high++;
00778 } else
00779 time_now.low += uuids_this_tick;
00780 }
00781
00782 timestamp->high = time_now.high;
00783 timestamp->low = time_now.low;
00784 }
00785
00786 void LLUUID::generate()
00787 {
00788
00789 uuid_time_t timestamp;
00790
00791 static unsigned char node_id[6];
00792 static int has_init = 0;
00793
00794
00795 static uuid_time_t time_last = {0,0};
00796 static U16 clock_seq = 0;
00797 #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR
00798 static U32 seed = 0L;
00799 #endif
00800 if (!has_init)
00801 {
00802 if (getNodeID(node_id) <= 0)
00803 {
00804 get_random_bytes(node_id, 6);
00805
00806
00807
00808
00809
00810 node_id[0] |= 0x80;
00811 }
00812
00813 getCurrentTime(&time_last);
00814 #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR
00815 seed = time_last.low;
00816 #endif
00817
00818 #if LL_USE_JANKY_RANDOM_NUMBER_GENERATOR
00819 clock_seq = (U16)janky_fast_random_seeded_bytes(seed, 65536);
00820 #else
00821 clock_seq = (U16)ll_rand(65536);
00822 #endif
00823 has_init = 1;
00824 }
00825
00826
00827 getCurrentTime(×tamp);
00828
00829
00830 if (cmpTime(×tamp, &time_last) == -1) {
00831 clock_seq = (clock_seq + 1) & 0x3FFF;
00832 if (clock_seq == 0) clock_seq++;
00833 }
00834
00835 memcpy(mData+10, node_id, 6);
00836 U32 tmp;
00837 tmp = timestamp.low;
00838 mData[3] = (unsigned char) tmp;
00839 tmp >>= 8;
00840 mData[2] = (unsigned char) tmp;
00841 tmp >>= 8;
00842 mData[1] = (unsigned char) tmp;
00843 tmp >>= 8;
00844 mData[0] = (unsigned char) tmp;
00845
00846 tmp = (U16) timestamp.high;
00847 mData[5] = (unsigned char) tmp;
00848 tmp >>= 8;
00849 mData[4] = (unsigned char) tmp;
00850
00851 tmp = (timestamp.high >> 16) | 0x1000;
00852 mData[7] = (unsigned char) tmp;
00853 tmp >>= 8;
00854 mData[6] = (unsigned char) tmp;
00855
00856 tmp = clock_seq;
00857 mData[9] = (unsigned char) tmp;
00858 tmp >>= 8;
00859 mData[8] = (unsigned char) tmp;
00860
00861 LLMD5 md5_uuid;
00862
00863 md5_uuid.update(mData,16);
00864 md5_uuid.finalize();
00865 md5_uuid.raw_digest(mData);
00866
00867 time_last = timestamp;
00868 }
00869
00870
00871 U32 LLUUID::getRandomSeed()
00872 {
00873 static unsigned char seed[16];
00874
00875 getNodeID(&seed[0]);
00876 seed[6]='\0';
00877 seed[7]='\0';
00878 getSystemTime((uuid_time_t *)(&seed[8]));
00879
00880 LLMD5 md5_seed;
00881
00882 md5_seed.update(seed,16);
00883 md5_seed.finalize();
00884 md5_seed.raw_digest(seed);
00885
00886 return(*(U32 *)seed);
00887 }
00888
00889 BOOL LLUUID::parseUUID(const char* buf, LLUUID* value)
00890 {
00891 if( buf == NULL || buf[0] == '\0' || value == NULL)
00892 {
00893 return FALSE;
00894 }
00895
00896 LLString temp( buf );
00897 LLString::trim(temp);
00898 if( LLUUID::validate( temp ) )
00899 {
00900 value->set( temp );
00901 return TRUE;
00902 }
00903 return FALSE;
00904 }
00905
00906 LLAssetID LLTransactionID::makeAssetID(const LLUUID& session) const
00907 {
00908 LLAssetID result;
00909 if (isNull())
00910 {
00911 result.setNull();
00912 }
00913 else
00914 {
00915 combine(session, result);
00916 }
00917 return result;
00918 }