D:/Storage/CVS_Head/h323plus/src/guid.cxx

00001 /*
00002  * guid.cxx
00003  *
00004  * Globally Unique Identifier
00005  *
00006  * Open H323 Library
00007  *
00008  * Copyright (c) 1998-2001 Equivalence Pty. Ltd.
00009  *
00010  * The contents of this file are subject to the Mozilla Public License
00011  * Version 1.0 (the "License"); you may not use this file except in
00012  * compliance with the License. You may obtain a copy of the License at
00013  * http://www.mozilla.org/MPL/
00014  *
00015  * Software distributed under the License is distributed on an "AS IS"
00016  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
00017  * the License for the specific language governing rights and limitations
00018  * under the License.
00019  *
00020  * The Original Code is Open H323 Library.
00021  *
00022  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
00023  *
00024  * Contributor(s): ______________________________________.
00025  *
00026  * $Log: guid.cxx,v $
00027  * Revision 1.1  2007/08/06 20:51:05  shorne
00028  * First commit of h323plus
00029  *
00030  * Revision 1.15  2003/04/15 03:04:08  robertj
00031  * Fixed string constructor being able to build non null GUID.
00032  *
00033  * Revision 1.14  2002/10/10 05:33:18  robertj
00034  * VxWorks port, thanks Martijn Roest
00035  *
00036  * Revision 1.13  2002/08/05 10:03:47  robertj
00037  * Cosmetic changes to normalise the usage of pragma interface/implementation.
00038  *
00039  * Revision 1.12  2001/10/03 03:18:29  robertj
00040  * Changed to only get (or fake) MAC address once.
00041  *
00042  * Revision 1.11  2001/04/05 01:45:13  robertj
00043  * Fixed MSVC warning.
00044  *
00045  * Revision 1.10  2001/04/04 07:46:13  robertj
00046  * Fixed erros in rading GUID hex string.
00047  *
00048  * Revision 1.9  2001/04/04 06:46:39  robertj
00049  * Fixed errors in time calculation used in GUID.
00050  *
00051  * Revision 1.8  2001/03/19 05:52:24  robertj
00052  * Fixed problem with reading a GUID if there is leading white space.
00053  * If get error reading GUID then set the stream fail bit.
00054  *
00055  * Revision 1.7  2001/03/15 00:25:12  robertj
00056  * Fixed problem with hex output sign extending unsigned values.
00057  *
00058  * Revision 1.6  2001/03/14 05:03:37  robertj
00059  * Fixed printing of GUID to have bytes as hex instead of characters.
00060  *
00061  * Revision 1.5  2001/03/03 00:54:48  yurik
00062  * Proper fix for filetime routines used in guid calc done for WinCE
00063  *
00064  * Revision 1.4  2001/03/02 23:25:49  yurik
00065  * fixed typo
00066  *
00067  * Revision 1.3  2001/03/02 22:50:37  yurik
00068  * Used PTime for WinCE port instead of non-portable function
00069  *
00070  * Revision 1.2  2001/03/02 07:17:41  robertj
00071  * Compensated for stupid GNU compiler bug.
00072  *
00073  * Revision 1.1  2001/03/02 06:59:59  robertj
00074  * Enhanced the globally unique identifier class.
00075  *
00076  */
00077 
00078 #include <ptlib.h>
00079 
00080 #ifdef __GNUC__
00081 #pragma implementation "guid.h"
00082 #endif
00083 
00084 #include "guid.h"
00085 
00086 #include <ptlib/sockets.h>
00087 #include <ptclib/random.h>
00088 #include <ptclib/asner.h>
00089 
00090 
00091 #define GUID_SIZE 16
00092 
00093 
00095 
00096 OpalGloballyUniqueID::OpalGloballyUniqueID()
00097   : PBYTEArray(GUID_SIZE)
00098 {
00099   // Want time of UTC in 0.1 microseconds since 15 Oct 1582.
00100   PInt64 timestamp;
00101   static PInt64 deltaTime = PInt64(10000000)*24*60*60*
00102                             (  16            // Days from 15th October
00103                              + 31            // Days in December 1583
00104                              + 30            // Days in November 1583
00105 #ifdef _WIN32
00106                              + (1601-1583)*365   // Whole years
00107                              + (1601-1583)/4);   // Leap days
00108 
00109   // Get nanoseconds since 1601
00110 #ifndef _WIN32_WCE
00111   GetSystemTimeAsFileTime((LPFILETIME)&timestamp);
00112 #else
00113   SYSTEMTIME SystemTime;
00114   GetSystemTime(&SystemTime);
00115   SystemTimeToFileTime(&SystemTime, (LPFILETIME)&timestamp);
00116 #endif // _WIN32_WCE
00117 
00118   timestamp /= 100;
00119 #else // _WIN32
00120                              + (1970-1583)*365 // Days in years
00121                              + (1970-1583)/4   // Leap days
00122                              - 3);             // Allow for 1700, 1800, 1900 not leap years
00123 
00124 #ifdef P_VXWORKS
00125   struct timespec ts;
00126   clock_gettime(0,&ts);
00127   timestamp = (ts.tv_sec*(PInt64)1000000 + ts.tv_nsec*1000)*10;
00128 #else
00129   struct timeval tv;
00130   gettimeofday(&tv, NULL);
00131   timestamp = (tv.tv_sec*(PInt64)1000000 + tv.tv_usec)*10;
00132 #endif // P_VXWORKS
00133 #endif // _WIN32
00134 
00135   timestamp += deltaTime;
00136 
00137   theArray[0] = (BYTE)(timestamp&0xff);
00138   theArray[1] = (BYTE)((timestamp>>8)&0xff);
00139   theArray[2] = (BYTE)((timestamp>>16)&0xff);
00140   theArray[3] = (BYTE)((timestamp>>24)&0xff);
00141   theArray[4] = (BYTE)((timestamp>>32)&0xff);
00142   theArray[5] = (BYTE)((timestamp>>40)&0xff);
00143   theArray[6] = (BYTE)((timestamp>>48)&0xff);
00144   theArray[7] = (BYTE)(((timestamp>>56)&0x0f) + 0x10);  // Version number is 1
00145 
00146   static WORD clockSequence = (WORD)PRandom::Number();
00147   static PInt64 lastTimestamp = 0;
00148   if (lastTimestamp < timestamp)
00149     lastTimestamp = timestamp;
00150   else
00151     clockSequence++;
00152 
00153   theArray[8] = (BYTE)(((clockSequence>>8)&0x1f) | 0x80); // DCE compatible GUID
00154   theArray[9] = (BYTE)clockSequence;
00155 
00156   static PEthSocket::Address macAddress;
00157   static BOOL needMacAddress = TRUE;
00158   if (needMacAddress) {
00159     PIPSocket::InterfaceTable interfaces;
00160     if (PIPSocket::GetInterfaceTable(interfaces)) {
00161       for (PINDEX i = 0; i < interfaces.GetSize(); i++) {
00162         PString macAddrStr = interfaces[i].GetMACAddress();
00163         if (!macAddrStr && macAddrStr != "44-45-53-54-00-00") { /* not Win32 PPP device */
00164           macAddress = macAddrStr;
00165           if (macAddress != NULL) {
00166             needMacAddress = FALSE;
00167             break;
00168           }
00169         }
00170       }
00171     }
00172 
00173     if (needMacAddress) {
00174       PRandom rand;
00175       macAddress.ls.l = rand;
00176       macAddress.ls.s = (WORD)rand;
00177       macAddress.b[0] |= '\x80';
00178 
00179       needMacAddress = FALSE;
00180     }
00181   }
00182 
00183   memcpy(theArray+10, macAddress.b, 6);
00184 }
00185 
00186 
00187 OpalGloballyUniqueID::OpalGloballyUniqueID(const char * cstr)
00188   : PBYTEArray(GUID_SIZE)
00189 {
00190   if (cstr != NULL && *cstr != '\0') {
00191     PStringStream strm(cstr);
00192     ReadFrom(strm);
00193   }
00194 }
00195 
00196 
00197 OpalGloballyUniqueID::OpalGloballyUniqueID(const PString & str)
00198   : PBYTEArray(GUID_SIZE)
00199 {
00200   PStringStream strm(str);
00201   ReadFrom(strm);
00202 }
00203 
00204 
00205 OpalGloballyUniqueID::OpalGloballyUniqueID(const PASN_OctetString & newId)
00206   : PBYTEArray(newId)
00207 {
00208   PAssert(GetSize() == GUID_SIZE, PInvalidParameter);
00209   SetSize(GUID_SIZE);
00210 }
00211 
00212 
00213 PObject * OpalGloballyUniqueID::Clone() const
00214 {
00215   PAssert(GetSize() == GUID_SIZE, "OpalGloballyUniqueID is invalid size");
00216 
00217   return new OpalGloballyUniqueID(*this);
00218 }
00219 
00220 
00221 PINDEX OpalGloballyUniqueID::HashFunction() const
00222 {
00223   PAssert(GetSize() == GUID_SIZE, "OpalGloballyUniqueID is invalid size");
00224 
00225   DWORD * words = (DWORD *)theArray;
00226   DWORD sum = words[0] + words[1] + words[2] + words[3];
00227   return ((sum >> 25)+(sum >> 15)+sum)%23;
00228 }
00229 
00230 
00231 void OpalGloballyUniqueID::PrintOn(ostream & strm) const
00232 {
00233   PAssert(GetSize() == GUID_SIZE, "OpalGloballyUniqueID is invalid size");
00234 
00235   char fillchar = strm.fill();
00236   strm << hex << setfill('0')
00237        << setw(2) << (unsigned)(BYTE)theArray[0]
00238        << setw(2) << (unsigned)(BYTE)theArray[1]
00239        << setw(2) << (unsigned)(BYTE)theArray[2]
00240        << setw(2) << (unsigned)(BYTE)theArray[3] << '-'
00241        << setw(2) << (unsigned)(BYTE)theArray[4]
00242        << setw(2) << (unsigned)(BYTE)theArray[5] << '-'
00243        << setw(2) << (unsigned)(BYTE)theArray[6]
00244        << setw(2) << (unsigned)(BYTE)theArray[7] << '-'
00245        << setw(2) << (unsigned)(BYTE)theArray[8]
00246        << setw(2) << (unsigned)(BYTE)theArray[9] << '-'
00247        << setw(2) << (unsigned)(BYTE)theArray[10]
00248        << setw(2) << (unsigned)(BYTE)theArray[11]
00249        << setw(2) << (unsigned)(BYTE)theArray[12]
00250        << setw(2) << (unsigned)(BYTE)theArray[13]
00251        << setw(2) << (unsigned)(BYTE)theArray[14]
00252        << setw(2) << (unsigned)(BYTE)theArray[15]
00253        << dec << setfill(fillchar);
00254 }
00255 
00256 
00257 void OpalGloballyUniqueID::ReadFrom(istream & strm)
00258 {
00259   PAssert(GetSize() == GUID_SIZE, "OpalGloballyUniqueID is invalid size");
00260   SetSize(16);
00261 
00262   strm >> ws;
00263 
00264   PINDEX count = 0;
00265 
00266   while (count < 2*GUID_SIZE) {
00267     if (isxdigit(strm.peek())) {
00268       char digit = (char)(strm.get() - '0');
00269       if (digit >= 10) {
00270         digit -= 'A'-('9'+1);
00271         if (digit >= 16)
00272           digit -= 'a'-'A';
00273       }
00274       theArray[count/2] = (BYTE)((theArray[count/2] << 4) | digit);
00275       count++;
00276     }
00277     else if (strm.peek() == '-') {
00278       if (count != 8 && count != 12 && count != 16 && count != 20)
00279         break;
00280       strm.get(); // Ignore the dash if it was in the right place
00281     }
00282     else
00283       break;
00284   }
00285 
00286   if (count < 2*GUID_SIZE) {
00287     memset(theArray, 0, GUID_SIZE);
00288     strm.clear(ios::failbit);
00289   }
00290 }
00291 
00292 
00293 PString OpalGloballyUniqueID::AsString() const
00294 {
00295   PStringStream strm;
00296   PrintOn(strm);
00297   return strm;
00298 }
00299 
00300 
00301 BOOL OpalGloballyUniqueID::IsNULL() const
00302 {
00303   PAssert(GetSize() == GUID_SIZE, "OpalGloballyUniqueID is invalid size");
00304 
00305   return memcmp(theArray, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) == 0;
00306 }
00307 
00308 

Generated on Thu Oct 25 13:42:43 2007 for h323plus by  doxygen 1.5.2