diff options
Diffstat (limited to 'indra/llcommon/lluuid.cpp')
-rwxr-xr-x[-rw-r--r--] | indra/llcommon/lluuid.cpp | 348 |
1 files changed, 260 insertions, 88 deletions
diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index bcbae06ec5..e3671047b4 100644..100755 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -1,31 +1,25 @@ /** * @file lluuid.cpp * - * $LicenseInfo:firstyear=2000&license=viewergpl$ - * - * Copyright (c) 2000-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2000&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ @@ -33,9 +27,10 @@ // We can't use WIN32_LEAN_AND_MEAN here, needs lots of includes. #if LL_WINDOWS -# undef WIN32_LEAN_AND_MEAN -# include <winsock2.h> -# include <windows.h> +#include "llwin32headers.h" +// ugh, this is ugly. We need to straighten out our linking for this library +#pragma comment(lib, "IPHLPAPI.lib") +#include <iphlpapi.h> #endif #include "lldefs.h" @@ -47,10 +42,16 @@ #include "llmd5.h" #include "llstring.h" #include "lltimer.h" +#include "llthread.h" const LLUUID LLUUID::null; const LLTransactionID LLTransactionID::tnull; +// static +LLMutex * LLUUID::mMutex = NULL; + + + /* NOT DONE YET!!! @@ -231,7 +232,7 @@ BOOL LLUUID::set(const std::string& in_string, BOOL emit) { if(emit) { - llwarns << "Warning! Using broken UUID string format" << llendl; + LL_WARNS() << "Warning! Using broken UUID string format" << LL_ENDL; } broken_format = TRUE; } @@ -241,7 +242,7 @@ BOOL LLUUID::set(const std::string& in_string, BOOL emit) if(emit) { //don't spam the logs because a resident can't spell. - llwarns << "Bad UUID string: " << in_string << llendl; + LL_WARNS() << "Bad UUID string: " << in_string << LL_ENDL; } setNull(); return FALSE; @@ -280,7 +281,7 @@ BOOL LLUUID::set(const std::string& in_string, BOOL emit) { if(emit) { - llwarns << "Invalid UUID string character" << llendl; + LL_WARNS() << "Invalid UUID string character" << LL_ENDL; } setNull(); return FALSE; @@ -305,7 +306,7 @@ BOOL LLUUID::set(const std::string& in_string, BOOL emit) { if(emit) { - llwarns << "Invalid UUID string character" << llendl; + LL_WARNS() << "Invalid UUID string character" << LL_ENDL; } setNull(); return FALSE; @@ -452,7 +453,8 @@ static void get_random_bytes(void *buf, int nbytes) return; } -#if LL_WINDOWS +#if LL_WINDOWS + typedef struct _ASTAT_ { ADAPTER_STATUS adapt; @@ -460,58 +462,44 @@ typedef struct _ASTAT_ }ASTAT, * PASTAT; // static -S32 LLUUID::getNodeID(unsigned char * node_id) -{ - ASTAT Adapter; - NCB Ncb; - UCHAR uRetCode; - LANA_ENUM lenum; - int i; - int retval = 0; - - memset( &Ncb, 0, sizeof(Ncb) ); - Ncb.ncb_command = NCBENUM; - Ncb.ncb_buffer = (UCHAR *)&lenum; - Ncb.ncb_length = sizeof(lenum); - uRetCode = Netbios( &Ncb ); - // printf( "The NCBENUM return code is: 0x%x \n", uRetCode ); - - for(i=0; i < lenum.length ;i++) - { - memset( &Ncb, 0, sizeof(Ncb) ); - Ncb.ncb_command = NCBRESET; - Ncb.ncb_lana_num = lenum.lana[i]; - - uRetCode = Netbios( &Ncb ); - // printf( "The NCBRESET on LANA %d return code is: 0x%x \n", - // lenum.lana[i], uRetCode ); - - memset( &Ncb, 0, sizeof (Ncb) ); - Ncb.ncb_command = NCBASTAT; - Ncb.ncb_lana_num = lenum.lana[i]; - - strcpy( (char *)Ncb.ncb_callname, "* " ); /* Flawfinder: ignore */ - Ncb.ncb_buffer = (unsigned char *)&Adapter; - Ncb.ncb_length = sizeof(Adapter); - - uRetCode = Netbios( &Ncb ); -// printf( "The NCBASTAT on LANA %d return code is: 0x%x \n", -// lenum.lana[i], uRetCode ); - if ( uRetCode == 0 ) - { -// printf( "The Ethernet Number on LANA %d is: %02x%02x%02x%02x%02x%02x\n", -// lenum.lana[i], -// Adapter.adapt.adapter_address[0], -// Adapter.adapt.adapter_address[1], -// Adapter.adapt.adapter_address[2], -// Adapter.adapt.adapter_address[3], -// Adapter.adapt.adapter_address[4], -// Adapter.adapt.adapter_address[5] ); +S32 LLUUID::getNodeID(unsigned char *node_id) +{ + ASTAT Adapter; + NCB Ncb; + UCHAR uRetCode; + LANA_ENUM lenum; + int i; + int retval = 0; + + memset( &Ncb, 0, sizeof(Ncb) ); + Ncb.ncb_command = NCBENUM; + Ncb.ncb_buffer = (UCHAR *)&lenum; + Ncb.ncb_length = sizeof(lenum); + uRetCode = Netbios( &Ncb ); + + for(i=0; i < lenum.length ;i++) + { + memset( &Ncb, 0, sizeof(Ncb) ); + Ncb.ncb_command = NCBRESET; + Ncb.ncb_lana_num = lenum.lana[i]; + + uRetCode = Netbios( &Ncb ); + + memset( &Ncb, 0, sizeof (Ncb) ); + Ncb.ncb_command = NCBASTAT; + Ncb.ncb_lana_num = lenum.lana[i]; + + strcpy( (char *)Ncb.ncb_callname, "* " ); /* Flawfinder: ignore */ + Ncb.ncb_buffer = (unsigned char *)&Adapter; + Ncb.ncb_length = sizeof(Adapter); + + uRetCode = Netbios( &Ncb ); + if ( uRetCode == 0 ) + { memcpy(node_id,Adapter.adapt.adapter_address,6); /* Flawfinder: ignore */ retval = 1; - - } - } + } + } return retval; } @@ -750,6 +738,7 @@ void LLUUID::getCurrentTime(uuid_time_t *timestamp) getSystemTime(&time_last); uuids_this_tick = uuids_per_tick; init = TRUE; + mMutex = new LLMutex(NULL); } uuid_time_t time_now = {0,0}; @@ -801,6 +790,7 @@ void LLUUID::generate() #endif if (!has_init) { + has_init = 1; if (getNodeID(node_id) <= 0) { get_random_bytes(node_id, 6); @@ -822,18 +812,24 @@ void LLUUID::generate() #else clock_seq = (U16)ll_rand(65536); #endif - has_init = 1; } // get current time getCurrentTime(×tamp); + U16 our_clock_seq = clock_seq; - // if clock went backward change clockseq - if (cmpTime(×tamp, &time_last) == -1) { + // if clock hasn't changed or went backward, change clockseq + if (cmpTime(×tamp, &time_last) != 1) + { + LLMutexLock lock(mMutex); clock_seq = (clock_seq + 1) & 0x3FFF; - if (clock_seq == 0) clock_seq++; + if (clock_seq == 0) + clock_seq++; + our_clock_seq = clock_seq; // Ensure we're using a different clock_seq value from previous time } + time_last = timestamp; + memcpy(mData+10, node_id, 6); /* Flawfinder: ignore */ U32 tmp; tmp = timestamp.low; @@ -855,7 +851,8 @@ void LLUUID::generate() tmp >>= 8; mData[6] = (unsigned char) tmp; - tmp = clock_seq; + tmp = our_clock_seq; + mData[9] = (unsigned char) tmp; tmp >>= 8; mData[8] = (unsigned char) tmp; @@ -865,8 +862,6 @@ void LLUUID::generate() md5_uuid.update(mData,16); md5_uuid.finalize(); md5_uuid.raw_digest(mData); - - time_last = timestamp; } void LLUUID::generate(const std::string& hash_string) @@ -880,8 +875,14 @@ U32 LLUUID::getRandomSeed() static unsigned char seed[16]; /* Flawfinder: ignore */ getNodeID(&seed[0]); - seed[6]='\0'; - seed[7]='\0'; + + // Incorporate the pid into the seed to prevent + // processes that start on the same host at the same + // time from generating the same seed. + pid_t pid = LLApp::getPid(); + + seed[6]=(unsigned char)(pid >> 8); + seed[7]=(unsigned char)(pid); getSystemTime((uuid_time_t *)(&seed[8])); LLMD5 md5_seed; @@ -938,3 +939,174 @@ LLAssetID LLTransactionID::makeAssetID(const LLUUID& session) const } return result; } + +// Construct +LLUUID::LLUUID() +{ + setNull(); +} + + +// Faster than copying from memory + void LLUUID::setNull() +{ + U32 *word = (U32 *)mData; + word[0] = 0; + word[1] = 0; + word[2] = 0; + word[3] = 0; +} + + +// Compare + bool LLUUID::operator==(const LLUUID& rhs) const +{ + U32 *tmp = (U32 *)mData; + U32 *rhstmp = (U32 *)rhs.mData; + // Note: binary & to avoid branching + return + (tmp[0] == rhstmp[0]) & + (tmp[1] == rhstmp[1]) & + (tmp[2] == rhstmp[2]) & + (tmp[3] == rhstmp[3]); +} + + + bool LLUUID::operator!=(const LLUUID& rhs) const +{ + U32 *tmp = (U32 *)mData; + U32 *rhstmp = (U32 *)rhs.mData; + // Note: binary | to avoid branching + return + (tmp[0] != rhstmp[0]) | + (tmp[1] != rhstmp[1]) | + (tmp[2] != rhstmp[2]) | + (tmp[3] != rhstmp[3]); +} + +/* +// JC: This is dangerous. It allows UUIDs to be cast automatically +// to integers, among other things. Use isNull() or notNull(). + LLUUID::operator bool() const +{ + U32 *word = (U32 *)mData; + return (word[0] | word[1] | word[2] | word[3]) > 0; +} +*/ + + BOOL LLUUID::notNull() const +{ + U32 *word = (U32 *)mData; + return (word[0] | word[1] | word[2] | word[3]) > 0; +} + +// Faster than == LLUUID::null because doesn't require +// as much memory access. + BOOL LLUUID::isNull() const +{ + U32 *word = (U32 *)mData; + // If all bits are zero, return !0 == TRUE + return !(word[0] | word[1] | word[2] | word[3]); +} + +// Copy constructor + LLUUID::LLUUID(const LLUUID& rhs) +{ + U32 *tmp = (U32 *)mData; + U32 *rhstmp = (U32 *)rhs.mData; + tmp[0] = rhstmp[0]; + tmp[1] = rhstmp[1]; + tmp[2] = rhstmp[2]; + tmp[3] = rhstmp[3]; +} + + LLUUID::~LLUUID() +{ +} + +// Assignment + LLUUID& LLUUID::operator=(const LLUUID& rhs) +{ + // No need to check the case where this==&rhs. The branch is slower than the write. + U32 *tmp = (U32 *)mData; + U32 *rhstmp = (U32 *)rhs.mData; + tmp[0] = rhstmp[0]; + tmp[1] = rhstmp[1]; + tmp[2] = rhstmp[2]; + tmp[3] = rhstmp[3]; + + return *this; +} + + + LLUUID::LLUUID(const char *in_string) +{ + if (!in_string || in_string[0] == 0) + { + setNull(); + return; + } + + set(in_string); +} + + LLUUID::LLUUID(const std::string& in_string) +{ + if (in_string.empty()) + { + setNull(); + return; + } + + set(in_string); +} + +// IW: DON'T "optimize" these w/ U32s or you'll scoogie the sort order +// IW: this will make me very sad + bool LLUUID::operator<(const LLUUID &rhs) const +{ + U32 i; + for( i = 0; i < (UUID_BYTES - 1); i++ ) + { + if( mData[i] != rhs.mData[i] ) + { + return (mData[i] < rhs.mData[i]); + } + } + return (mData[UUID_BYTES - 1] < rhs.mData[UUID_BYTES - 1]); +} + + bool LLUUID::operator>(const LLUUID &rhs) const +{ + U32 i; + for( i = 0; i < (UUID_BYTES - 1); i++ ) + { + if( mData[i] != rhs.mData[i] ) + { + return (mData[i] > rhs.mData[i]); + } + } + return (mData[UUID_BYTES - 1] > rhs.mData[UUID_BYTES - 1]); +} + + U16 LLUUID::getCRC16() const +{ + // A UUID is 16 bytes, or 8 shorts. + U16 *short_data = (U16*)mData; + U16 out = 0; + out += short_data[0]; + out += short_data[1]; + out += short_data[2]; + out += short_data[3]; + out += short_data[4]; + out += short_data[5]; + out += short_data[6]; + out += short_data[7]; + return out; +} + + U32 LLUUID::getCRC32() const +{ + U32 *tmp = (U32*)mData; + return tmp[0] + tmp[1] + tmp[2] + tmp[3]; +} |