1 // **********************************************************************
3 // Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
5 // This copy of Ice is licensed to you under the terms described in the
6 // ICE_LICENSE file included in this distribution.
8 // **********************************************************************
10 #include <IceUtil/UUID.h>
12 // On Windows, we use Windows's RPC UUID generator.
13 // On other platforms, we use a high quality random number generator
14 // (/dev/random) to generate "version 4" UUIDs, as described in
15 // http://www.ietf.org/internet-drafts/draft-mealling-uuid-urn-00.txt
20 # include <IceUtil/Random.h>
21 # include <sys/types.h>
36 namespace IceUtilInternal
40 // Initialize the pid.
49 myPid
[0] = (p
>> 8) & 0x7F;
54 PidInitializer pidInitializer
;
62 // Helper char to hex functions
64 inline void halfByteToHex(unsigned char hb
, char*& hexBuffer
)
68 *hexBuffer
++ = '0' + hb
;
72 *hexBuffer
++ = 'A' + (hb
- 10);
76 inline void bytesToHex(unsigned char* bytes
, size_t len
, char*& hexBuffer
)
78 for(size_t i
= 0; i
< len
; i
++)
80 halfByteToHex((bytes
[i
] & 0xF0) >> 4, hexBuffer
);
81 halfByteToHex((bytes
[i
] & 0x0F), hexBuffer
);
88 IceUtil::generateUUID()
97 UuidToString(&uuid
, &str
);
99 string result
= reinterpret_cast<char*>(str
);
107 unsigned char timeLow
[4];
108 unsigned char timeMid
[2];
109 unsigned char timeHighAndVersion
[2];
110 unsigned char clockSeqHiAndReserved
;
111 unsigned char clockSeqLow
;
112 unsigned char node
[6];
116 assert(sizeof(UUID
) == 16);
119 // Get a random sequence of bytes. Instead of using 122 random
120 // bits that could be duplicated (because of a bug with some Linux
121 // kernels and potentially other Unix platforms -- see comment in
122 // Random.cpp), we replace the last 15 bits of all "random"
123 // Randoms by the last 15 bits of the process id.
125 char* buffer
= reinterpret_cast<char*>(&uuid
);
126 IceUtilInternal::generateRandom(buffer
, static_cast<int>(sizeof(UUID
)));
129 // Adjust the bits that say "version 4" UUID
131 uuid
.timeHighAndVersion
[0] &= 0x0F;
132 uuid
.timeHighAndVersion
[0] |= (4 << 4);
133 uuid
.clockSeqHiAndReserved
&= 0x3F;
134 uuid
.clockSeqHiAndReserved
|= 0x80;
137 // Replace the end of the node by myPid (15 bits)
139 uuid
.node
[4] = (uuid
.node
[4] & 0x80) | myPid
[0];
140 uuid
.node
[5] = myPid
[1];
143 // Convert to a UUID string
145 char uuidString
[16 * 2 + 4 + 1]; // 16 bytes, 4 '-' and a final '\0'
146 char* uuidIndex
= uuidString
;
147 bytesToHex(uuid
.timeLow
, sizeof(uuid
.timeLow
), uuidIndex
);
149 bytesToHex(uuid
.timeMid
, sizeof(uuid
.timeMid
), uuidIndex
);
151 bytesToHex(uuid
.timeHighAndVersion
, sizeof(uuid
.timeHighAndVersion
), uuidIndex
);
153 bytesToHex(&uuid
.clockSeqHiAndReserved
, sizeof(uuid
.clockSeqHiAndReserved
), uuidIndex
);
154 bytesToHex(&uuid
.clockSeqLow
, sizeof(uuid
.clockSeqLow
), uuidIndex
);
156 bytesToHex(uuid
.node
, sizeof(uuid
.node
), uuidIndex
);