lluuid.cpp

Go to the documentation of this file.
00001 
00031 #include "linden_common.h"
00032 
00033 // We can't use WIN32_LEAN_AND_MEAN here, needs lots of includes.
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 NOT DONE YET!!!
00056 
00057 static char BASE85_TABLE[] = {
00058         '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
00059         'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
00060         'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
00061         'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
00062         'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
00063         'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
00064         'y', 'z', '!', '#', '$', '%', '&', '(', ')', '*',
00065         '+', '-', ';', '[', '=', '>', '?', '@', '^', '_',
00066         '`', '{', '|', '}', '~', '\0'
00067 };
00068 
00069 
00070 void encode( char * fiveChars, unsigned int word ) throw( )
00071 {
00072 for( int ix = 0; ix < 5; ++ix ) {
00073 fiveChars[4-ix] = encodeTable[ word % 85];
00074 word /= 85;
00075 }
00076 }
00077 
00078 To decode:
00079 unsigned int decode( char const * fiveChars ) throw( bad_input_data )
00080 {
00081 unsigned int ret = 0;
00082 for( int ix = 0; ix < 5; ++ix ) {
00083 char * s = strchr( encodeTable, fiveChars[ ix ] );
00084 if( s == 0 ) throw bad_input_data();
00085 ret = ret * 85 + (s-encodeTable);
00086 }
00087 return ret;
00088 }
00089 
00090 void LLUUID::toBase85(char* out)
00091 {
00092         U32* me = (U32*)&(mData[0]);
00093         for(S32 i = 0; i < 4; ++i)
00094         {
00095                 char* o = &out[i*i];
00096                 for(S32 j = 0; j < 5; ++j)
00097                 {
00098                         o[4-j] = BASE85_TABLE[ me[i] % 85];
00099                         word /= 85;
00100                 }
00101         }
00102 }
00103 
00104 unsigned int decode( char const * fiveChars ) throw( bad_input_data )
00105 {
00106         unsigned int ret = 0;
00107         for( S32 ix = 0; ix < 5; ++ix )
00108         {
00109                 char * s = strchr( encodeTable, fiveChars[ ix ] );
00110                 ret = ret * 85 + (s-encodeTable);
00111         }
00112         return ret;
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 // Common to all UUID implementations
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);         /* Flawfinder: ignore */
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];                /* Flawfinder: ignore */
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         // empty strings should make NULL uuid
00208         if (!in_string[0])
00209         {
00210                 setNull();
00211                 return TRUE;
00212         }
00213 
00214         if (strlen(in_string) != (UUID_STR_LENGTH - 1))         /* Flawfinder: ignore */
00215         {
00216                 // I'm a moron.  First implementation didn't have the right UUID format.
00217                 // Shouldn't see any of these any more
00218                 if (strlen(in_string) == (UUID_STR_LENGTH - 2)) /* Flawfinder: ignore */
00219                 {
00220                         if(emit)
00221                         {
00222                                 llinfos << "Warning! Using broken UUID string format" << llendl;
00223                         }
00224                         broken_format = TRUE;
00225                 }
00226                 else
00227                 {
00228                         // Bad UUID string.  Spam as INFO, as most cases we don't care.
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                                 // Missing - in the broken format
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))         /* Flawfinder: ignore */
00319         {
00320                 // I'm a moron.  First implementation didn't have the right UUID format.
00321                 if (strlen(in_string) == (UUID_STR_LENGTH - 2))         /* Flawfinder: ignore */
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                                 // Missing - in the broken format
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];         /* Flawfinder: ignore */
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         // *NOTE: If we are not using the janky generator ll_rand()
00441         // generates at least 3 good bytes of data since it is 0 to
00442         // RAND_MAX. This could be made more efficient by copying all the
00443         // bytes.
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 // static
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  //     printf( "The NCBENUM return code is: 0x%x \n", uRetCode );
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  //         printf( "The NCBRESET on LANA %d return code is: 0x%x \n",
00485  //                 lenum.lana[i], uRetCode );
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,  "*              " );               /* Flawfinder: ignore */
00492           Ncb.ncb_buffer = (unsigned char *)&Adapter;
00493           Ncb.ncb_length = sizeof(Adapter);
00494 
00495           uRetCode = Netbios( &Ncb );
00496 //          printf( "The NCBASTAT on LANA %d return code is: 0x%x \n",
00497 //                 lenum.lana[i], uRetCode );
00498           if ( uRetCode == 0 )
00499           {
00500 //            printf( "The Ethernet Number on LANA %d is: %02x%02x%02x%02x%02x%02x\n",
00501 //                                lenum.lana[i],
00502 //                  Adapter.adapt.adapter_address[0],
00503 //                  Adapter.adapt.adapter_address[1],
00504 //                  Adapter.adapt.adapter_address[2],
00505 //                  Adapter.adapt.adapter_address[3],
00506 //                  Adapter.adapt.adapter_address[4],
00507 //                  Adapter.adapt.adapter_address[5] );
00508                         memcpy(node_id,Adapter.adapt.adapter_address,6);                /* Flawfinder: ignore */
00509                         retval = 1;
00510 
00511           }
00512           }
00513         return retval;
00514 }
00515 
00516 #elif LL_DARWIN
00517 // Mac OS X version of the UUID generation code...
00518 /*
00519  * Get an ethernet hardware address, if we can find it...
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 // static
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 //              printf("Interface %s, address family %d, ", ifa->ifa_name, ifa->ifa_addr->sa_family);
00553                 for(i=0; i< ifa->ifa_addr->sa_len; i++)
00554                 {
00555 //                      printf("%02X ", (unsigned char)ifa->ifa_addr->sa_data[i]);
00556                 }
00557 //              printf("\n");
00558                 
00559                 if(ifa->ifa_addr->sa_family == AF_LINK)
00560                 {
00561                         // This is a link-level address
00562                         struct sockaddr_dl *lla = (struct sockaddr_dl *)ifa->ifa_addr;
00563                         
00564 //                      printf("\tLink level address, type %02X\n", lla->sdl_type);
00565 
00566                         if(lla->sdl_type == IFT_ETHER)
00567                         {
00568                                 // Use the first ethernet MAC in the list.
00569                                 // For some reason, the macro LLADDR() defined in net/if_dl.h doesn't expand correctly.  This is what it would do.
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                                 // We found one.
00585                                 break;
00586                         }
00587                 }
00588         }
00589         freeifaddrs(ifap);
00590 
00591         return result;
00592 }
00593 
00594 #else
00595 
00596 // Linux version of the UUID generation code...
00597 /*
00598  * Get the ethernet hardware address, if we can find it...
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 // static
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  * BSD 4.4 defines the size of an ifreq to be
00632  * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
00633  * However, under earlier systems, sa_len isn't present, so the size is 
00634  * just sizeof(struct ifreq)
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 /* HAVE_SA_LEN*/
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);                /* Flawfinder: ignore */
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                  * XXX we don't have a way of getting the hardware
00673                  * address
00674                  */
00675                 close(sd);
00676                 return 0;
00677 #endif /* SIOCGENADDR */
00678 #endif /* SIOCGIFHWADDR */
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);          /* Flawfinder: ignore */
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    // Compare two time values.
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    // Get system time with 100ns precision. Time is since Oct 15, 1582.
00707 #if LL_WINDOWS
00708    ULARGE_INTEGER time;
00709    GetSystemTimeAsFileTime((FILETIME *)&time);
00710    // NT keeps time in FILETIME format which is 100ns ticks since
00711    // Jan 1, 1601. UUIDs use time in 100ns ticks since Oct 15, 1582.
00712    // The difference is 17 Days in Oct + 30 (Nov) + 31 (Dec)
00713    // + 18 years and 5 leap days.
00714    time.QuadPart +=
00715             (unsigned __int64) (1000*1000*10)       // seconds
00716           * (unsigned __int64) (60 * 60 * 24)       // days
00717           * (unsigned __int64) (17+30+31+365*18+5); // # of days
00718 
00719    timestamp->high = time.HighPart;
00720    timestamp->low  = time.LowPart;
00721 #else
00722    struct timeval tp;
00723    gettimeofday(&tp, 0);
00724 
00725    // Offset between UUID formatted times and Unix formatted times.
00726    // UUID UTC base time is October 15, 1582.
00727    // Unix base time is January 1, 1970.
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    // Get current time as 60 bit 100ns ticks since whenever.
00738    // Compensate for the fact that real clock resolution is less
00739    // than 100ns.
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       // if clock reading changed since last UUID generated
00759       if (cmpTime(&time_last, &time_now))  {
00760          // reset count of uuid's generated with this clock reading
00761          uuids_this_tick = 0;
00762          break;
00763       }
00764       if (uuids_this_tick < uuids_per_tick) {
00765          uuids_this_tick++;
00766          break;
00767       }
00768       // going too fast for our clock; spin
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         // Create a UUID.
00789         uuid_time_t timestamp;
00790 
00791         static unsigned char node_id[6];        /* Flawfinder: ignore */
00792         static int has_init = 0;
00793    
00794         // Create a UUID.
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; // dummy seed.  reset it below
00799 #endif
00800         if (!has_init) 
00801         {
00802                 if (getNodeID(node_id) <= 0) 
00803                 {
00804                         get_random_bytes(node_id, 6);
00805                         /*
00806                          * Set multicast bit, to prevent conflicts
00807                          * with IEEE 802 addresses obtained from
00808                          * network cards
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         // get current time
00827         getCurrentTime(&timestamp);
00828 
00829         // if clock went backward change clockseq
00830         if (cmpTime(&timestamp, &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);           /* Flawfinder: ignore */
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];               /* Flawfinder: ignore */
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 }

Generated on Thu Jul 1 06:09:25 2010 for Second Life Viewer by  doxygen 1.4.7