1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
// **********************************************************************
//
// Copyright (c) 2003-2006 ZeroC, Inc. All rights reserved.
//
// This copy of Ice is licensed to you under the terms described in the
// ICE_LICENSE file included in this distribution.
//
// **********************************************************************
#include <IceUtil/UUID.h>
// On Windows, we use Windows's RPC UUID generator.
// On other platforms, we use a high quality random number generator
// (/dev/random) to generate "version 4" UUIDs, as described in
// http://www.ietf.org/internet-drafts/draft-mealling-uuid-urn-00.txt
#ifdef _WIN32
# include <rpc.h>
#else
# include <IceUtil/Random.h>
#endif
using namespace std;
// Helper char to hex functions
//
inline void halfByteToHex(unsigned char hb, char*& hexBuffer)
{
if(hb < 10)
{
*hexBuffer++ = '0' + hb;
}
else
{
*hexBuffer++ = 'A' + (hb - 10);
}
}
inline void bytesToHex(unsigned char* bytes, size_t len, char*& hexBuffer)
{
for(size_t i = 0; i < len; i++)
{
halfByteToHex((bytes[i] & 0xF0) >> 4, hexBuffer);
halfByteToHex((bytes[i] & 0x0F), hexBuffer);
}
}
string
IceUtil::generateUUID()
{
#ifdef _WIN32
UUID uuid;
UuidCreate(&uuid);
unsigned char* str;
UuidToString(&uuid, &str);
string result = reinterpret_cast<char*>(str);
RpcStringFree(&str);
return result;
#else
struct UUID
{
unsigned char timeLow[4];
unsigned char timeMid[2];
unsigned char timeHighAndVersion[2];
unsigned char clockSeqHiAndReserved;
unsigned char clockSeqLow;
unsigned char node[6];
};
UUID uuid;
assert(sizeof(UUID) == 16);
//
// Get a random sequence of bytes and the pid of the current
// process. Instead of using 122 random bits that could be
// duplicated (because of a bug with some Linux kernels and
// potentially other Unix platforms -- see comment in Random.cpp),
// we replace the last 15 bits of all "random" Randoms by the last
// 15 bits of the process id.
//
char* buffer = reinterpret_cast<char*>(&uuid);
char pid[2];
generateRandomAndGetPid(buffer, sizeof(UUID), pid);
//
// Adjust the bits that say "version 4" UUID
//
uuid.timeHighAndVersion[0] &= 0x0F;
uuid.timeHighAndVersion[0] |= (4 << 4);
uuid.clockSeqHiAndReserved &= 0x3F;
uuid.clockSeqHiAndReserved |= 0x80;
//
// Replace the end of the node by myPid (15 bits)
//
uuid.node[4] = (uuid.node[4] & 0x80) | pid[0];
uuid.node[5] = pid[1];
//
// Convert to a UUID string
//
char uuidString[16 * 2 + 4 + 1]; // 16 bytes, 4 '-' and a final '\0'
char* uuidIndex = uuidString;
bytesToHex(uuid.timeLow, sizeof(uuid.timeLow), uuidIndex);
*uuidIndex++ = '-';
bytesToHex(uuid.timeMid, sizeof(uuid.timeMid), uuidIndex);
*uuidIndex++ = '-';
bytesToHex(uuid.timeHighAndVersion, sizeof(uuid.timeHighAndVersion), uuidIndex);
*uuidIndex++ = '-';
bytesToHex(&uuid.clockSeqHiAndReserved, sizeof(uuid.clockSeqHiAndReserved), uuidIndex);
bytesToHex(&uuid.clockSeqLow, sizeof(uuid.clockSeqLow), uuidIndex);
*uuidIndex++ = '-';
bytesToHex(uuid.node, sizeof(uuid.node), uuidIndex);
*uuidIndex = '\0';
return uuidString;
#endif
}
|