Fixed compilation issues
[distributed.git] / src / libs / net / uuid.cxx
blobc929ec552e12bbb0a5a8ed075366721679ac63c4
1 //
2 // Copyright (C) 2008 Francesco Salvestrini
3 // Gino Carrozzo
4 //
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License along
16 // with this program; if not, write to the Free Software Foundation, Inc.,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "config.h"
22 #include <cstdlib>
23 #include <stdexcept>
24 #include <sstream>
25 #include <iomanip>
26 #include <cstring>
27 #include <string>
28 #include <iostream>
30 #include <stdlib.h> // XXX-FIXME to remove with rand/srand wraps in gnulib
31 #include <sys/time.h> // XXX-FIXME to remove with rand/srand wraps in gnulib
33 #include "libs/net/uuid.h"
36 using namespace Net;
38 static uint32_t myrand(uint32_t min, uint32_t max)
40 struct timeval tv;
42 float fmax;
43 float fmin;
45 if (gettimeofday(&tv, NULL) == -1) {
46 return 0;
48 srand(tv.tv_usec);
50 fmax = (max != 0xFFFFFFFF) ? (float) max : (float)RAND_MAX;
51 fmin = min ? (float) min : 0.0;
53 return (min + (uint32_t) (fmax * (rand() / (RAND_MAX + 1.0))));
56 UUID::UUID(void)
58 format_uuid_random();
59 check_uuid();
62 UUID::~UUID(void)
66 UUID::UUID(version_t version)
68 memset(&uuid_, 0, sizeof(uuid_));
70 switch (version) {
71 case IETF_RFC4122_TIMEBASED: {
72 format_uuid_tb();
74 break;
75 case DCE_SECURITY_POSIX_UID: {
77 break;
78 case IETF_RFC4122_NAMEBASED_MD5: {
79 format_uuid_nb();
80 scramble_md5();
82 break;
83 case IETF_RFC4122_NAMEBASED_SHA1: {
84 format_uuid_nb();
85 scramble_sha1();
87 break;
88 case IETF_RFC4122_RANDOM: {
89 format_uuid_random();
91 break;
92 default: {
93 throw invalid_version(version,
94 "not supported in IETF RFC4122");
96 break;
99 check_uuid();
103 // NOTE (excerpt from wikipedia):
105 // In its canonical form, a UUID consists of 32 hexadecimal digits, displayed
106 // in 5 groups separated by hyphens, in the form 8-4-4-4-12 for a total of
107 // 36 characters. For example:
109 // 550e8400-e29b-41d4-a716-446655440000
112 bool UUID::grab_8hex(const std::string & u,
113 std::string::size_type s,
114 std::string::size_type e,
115 uint32_t & v)
117 if ((e - s) != 8) {
118 return false;
121 std::string tmp;
122 tmp = u.substr(s, e);
124 const char * t;
125 t = tmp.c_str();
127 v = strtoul(t, 0, 16);
129 return true;
132 bool UUID::grab_4hex(const std::string & u,
133 std::string::size_type s,
134 std::string::size_type e,
135 uint16_t & v)
137 if ((e - s) != 4) {
138 return false;
141 std::string tmp;
142 tmp = u.substr(s, e);
144 const char * t;
145 t = tmp.c_str();
147 v = strtoul(t, 0, 16);
149 return true;
152 bool UUID::grab_12hex(const std::string & u,
153 std::string::size_type s,
154 std::string::size_type e,
155 uint8_t * v)
157 if ((e - s) != 12) {
158 return false;
161 std::string tmp;
162 tmp = u.substr(s, e);
164 int i;
165 char buf[3];
167 buf[2] = 0;
168 for (i = 0; i < 6; i++) {
169 buf[0] = tmp[i * 2];
170 buf[1] = tmp[i * 2 + 1];
171 v[i] = strtoul(buf, 0, 16);
174 return true;
177 UUID::UUID(const std::string & u)
179 std::string::size_type s, e;
181 s = 0;
183 // Grab the time-low part
184 e = u.find_first_of('-', s);
185 if (!grab_8hex(u, s, e, uuid_.time_low)) {
186 throw invalid_hexfield(1, "Wrong field-1");
188 s = e + 1;
190 // Grab the time-mid part
191 e = u.find_first_of('-', s);
192 if (!grab_4hex(u, s, e, uuid_.time_mid)) {
193 throw invalid_hexfield(2, "Wrong field-2");
195 s = e + 1;
197 // Grab the time-high-and-version part
198 e = u.find_first_of('-', s);
199 if (!grab_4hex(u, s, e, uuid_.time_hi_and_version)) {
200 throw invalid_hexfield(3, "Wrong field-3");
202 s = e + 1;
204 // Grab clock-seq-and-reserverd clock-seq-low part
205 e = u.find('-', s);
206 if (!grab_4hex(u, s, e, uuid_.clock_seq)) {
207 throw invalid_hexfield(4, "Wrong field-4");
209 s = e + 1;
211 // Grab the node part
212 e = u.size();
213 if (!grab_12hex(u, s, e, uuid_.node)) {
214 throw invalid_hexfield(5, "Wrong field-5");
217 check_uuid();
220 void UUID::clear(void)
222 memset(&uuid_, 0, sizeof(struct uuid));
225 Net::UUID & UUID::operator =(const UUID & rhs)
227 memcpy(&uuid_, &rhs.uuid_, sizeof(struct uuid));
229 return *this;
232 bool UUID::operator ==(const UUID & rhs)
234 if (!memcmp(&uuid_, &rhs.uuid_, sizeof(struct uuid))) {
235 return true;
238 return false;
241 UUID::operator std::string(void)
243 std::stringstream s;
245 s << std::hex << std::setw(8) << std::setfill('0')
246 << uuid_.time_low;
247 s << "-";
248 s << std::hex << std::setw(4) << std::setfill('0')
249 << uuid_.time_mid;
250 s << "-";
251 s << std::hex << std::setw(4) << std::setfill('0')
252 << uuid_.time_hi_and_version;
253 s << "-";
254 s << std::hex << std::setw(4) << std::setfill('0')
255 << uuid_.clock_seq;
256 s << "-";
258 int i;
259 for (i = 0; i < 6; i++) {
260 s << std::hex << std::setw(2) << std::setfill('0')
261 << static_cast<int>(uuid_.node[i]);
264 return s.str();
267 std::ostream & operator <<(std::ostream & stream,
268 UUID obj)
270 return stream;
273 std::istream & operator >>(std::istream & stream,
274 UUID & obj)
276 return stream;
279 void UUID::format_uuid_tb(void)
281 throw generic_problem("XXX TO BE IMPLEMENTED");
284 void UUID::format_uuid_nb(void)
286 throw generic_problem("XXX TO BE IMPLEMENTED");
289 void UUID::format_uuid_random(void)
291 uuid_.time_low = myrand(0, 0xFFFFFFFF);
292 uuid_.time_mid = (uint16_t) myrand(0, 0xFFFF);
293 uuid_.time_hi_and_version = (uint16_t) myrand(0, 0xFFFF);
294 uuid_.time_hi_and_version &= 0x0FFF;
295 uuid_.time_hi_and_version |= (IETF_RFC4122_RANDOM << 12);
296 uuid_.clock_seq = (uint16_t) myrand(0, 0xFFFF);
297 uuid_.clock_seq &= 0x3FFF;
298 uuid_.clock_seq |= (0x2 << 14); // variant
300 size_t i;
301 for (i = 0; i < 6; i++) {
302 uuid_.node[i] = (uint8_t) myrand(0, 0xFF);
307 // From RFC4122
308 // This bit is the unicast/multicast bit, which will never be set in
309 // IEEE 802 addresses obtained from network cards. Hence, there can
310 // never be a conflict between UUIDs generated by machines with and
311 // without network cards.
312 uuid_.node[0] |= (0x1 << 7);
315 void UUID::scramble_sha1(void)
317 throw generic_problem("XXX TO BE IMPLEMENTED");
320 void UUID::scramble_md5(void)
322 throw generic_problem("XXX TO BE IMPLEMENTED");
326 void UUID::check_uuid(void)
328 version_t ver;
329 uint8_t variant;
331 ver = (version_t) (uuid_.time_hi_and_version >> 12);
332 variant = (uuid_.clock_seq & 0xC000) >> 14;
334 if (variant != 2) {
335 throw formatting_problem(ver,
336 variant,
337 "UUID has a fake variant");
340 switch (ver) {
341 case IETF_RFC4122_TIMEBASED: {
342 // XXX-FIXME
344 break;
345 case DCE_SECURITY_POSIX_UID: {
346 // XXX-FIXME
348 break;
349 case IETF_RFC4122_NAMEBASED_MD5: {
350 // XXX-FIXME
352 break;
353 case IETF_RFC4122_NAMEBASED_SHA1: {
354 // XXX-FIXME
356 break;
357 case IETF_RFC4122_RANDOM: {
358 if (!(uuid_.node[0] >> 7)) {
359 throw formatting_problem(ver,
361 "UUID has a "
362 "non-multicast "
363 "node-id");
366 break;
367 default: {
368 throw formatting_problem(ver,
370 "UUID has a fake version");
372 break;