Project
Loading...
Searching...
No Matches
FairRunIdGenerator.cxx
Go to the documentation of this file.
1/********************************************************************************
2 * Copyright (C) 2014 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH *
3 * *
4 * This software is distributed under the terms of the *
5 * GNU Lesser General Public Licence (LGPL) version 3, *
6 * copied verbatim in the file "LICENSE" *
7 ********************************************************************************/
8/*
9 * gen_uuid.c --- generate a DCE-compatible uuid
10 *
11 * Copyright (C) 1996, 1997, 1998, 1999 Theodore Ts'o.
12 *
13 * %Begin-Header%
14 * This file may be redistributed under the terms of the GNU
15 * Library General Public License.
16 * %End-Header%
17 */
18
19/*
20 * Force inclusion of SVID stuff since we need it if we're compiling in
21 * gcc-wall wall mode
22 */
23#define _SVID_SOURCE
24#define _DEFAULT_SOURCE
25
26#include "FairRunIdGenerator.h"
27
28#include <stdlib.h> // for rand, srand
29#include <string.h> // for memcpy
30#include <sys/errno.h> // for errno, EAGAIN, EINTR
31#include <sys/fcntl.h> // for open, O_RDONLY, O_NONBLOCK
32#include <sys/time.h> // for gettimeofday
33#include <unistd.h> // for getpid, getuid, read
34
35#define srand(x) srandom(x)
36#define rand() random()
37
38// using namespace std;
39
40//#include "genid32.h" replaced by hrunidgenerator.h
41
42/*
43 * uuid.h -- private header file for uuids
44 *
45 * Copyright (C) 1996, 1997 Theodore Ts'o.
46 *
47 * %Begin-Header%
48 * This file may be redistributed under the terms of the GNU
49 * Library General Public License.
50 * %End-Header%
51 */
52
53/*
54 * Offset between 15-Oct-1582 and 1-Jan-70
55 */
56#define TIME_OFFSET_HIGH 0x01B21DD2
57#define TIME_OFFSET_LOW 0x13814000
58
59int FairRunIdGenerator::get_random_fd(void)
60{
61 struct timeval tv;
62 static int fd = -2;
63 int i;
64
65 if (fd == -2) {
66 gettimeofday(&tv, 0);
67 fd = open("/dev/urandom", O_RDONLY);
68 if (fd == -1) {
69 fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
70 }
71 srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
72 }
73 /* Crank the random number generator a few times */
74 gettimeofday(&tv, 0);
75 for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--) {
76 rand();
77 }
78 return fd;
79}
80
81/*
82 * Generate a series of random bytes. Use /dev/urandom if possible,
83 * and if not, use srandom/random.
84 */
85void FairRunIdGenerator::get_random_bytes(void* buf, int nbytes)
86{
87 int i, fd = get_random_fd();
88 int lose_counter = 0;
89 char* cp = static_cast<char*>(buf);
90
91 if (fd >= 0) {
92 while (nbytes > 0) {
93 i = read(fd, cp, nbytes);
94 if ((i < 0) && ((errno == EINTR) || (errno == EAGAIN))) {
95 continue;
96 }
97 if (i <= 0) {
98 if (lose_counter++ == 8) {
99 break;
100 }
101 continue;
102 }
103 nbytes -= i;
104 cp += i;
105 lose_counter = 0;
106 }
107 }
108 /* XXX put something better here if no /dev/random! */
109 for (i = 0; i < nbytes; i++) {
110 *cp++ = rand() & 0xFF;
111 }
112 return;
113}
114
115/*
116 * Get the ethernet hardware address, if we can find it...
117 */
118int FairRunIdGenerator::get_node_id(unsigned char* /*node_id*/)
119{
120#ifdef HAVE_NET_IF_H
121 int sd;
122 struct ifreq ifr, *ifrp;
123 struct ifconf ifc;
124 char buf[1024];
125 int n, i;
126 unsigned char* a;
127
128 /*
129 * BSD 4.4 defines the size of an ifreq to be
130 * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len
131 * However, under earlier systems, sa_len isn't present, so the size is
132 * just sizeof(struct ifreq)
133 */
134#ifdef HAVE_SA_LEN
135#ifndef max
136#define max(a, b) ((a) > (b) ? (a) : (b))
137#endif
138#define ifreq_size(i) max(sizeof(struct ifreq), sizeof((i).ifr_name) + (i).ifr_addr.sa_len)
139#else
140#define ifreq_size(i) sizeof(struct ifreq)
141#endif /* HAVE_SA_LEN*/
142
143 sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
144 if (sd < 0) {
145 return -1;
146 }
147 memset(buf, 0, sizeof(buf));
148 ifc.ifc_len = sizeof(buf);
149 ifc.ifc_buf = buf;
150 if (ioctl(sd, SIOCGIFCONF, (char*)&ifc) < 0) {
151 close(sd);
152 return -1;
153 }
154 n = ifc.ifc_len;
155 for (i = 0; i < n; i += ifreq_size(*ifr)) {
156 ifrp = (struct ifreq*)((char*)ifc.ifc_buf + i);
157 strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ);
158#ifdef SIOCGIFHWADDR
159 if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) {
160 continue;
161 }
162 a = (unsigned char*)&ifr.ifr_hwaddr.sa_data;
163#else
164#ifdef SIOCGENADDR
165 if (ioctl(sd, SIOCGENADDR, &ifr) < 0) {
166 continue;
167 }
168 a = (unsigned char*)ifr.ifr_enaddr;
169#else
170 /*
171 * XXX we don't have a way of getting the hardware
172 * address
173 */
174 close(sd);
175 return 0;
176#endif /* SIOCGENADDR */
177#endif /* SIOCGIFHWADDR */
178 if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) {
179 continue;
180 }
181 if (node_id) {
182 memcpy(node_id, a, 6);
183 close(sd);
184 return 1;
185 }
186 }
187 close(sd);
188#endif
189 return 0;
190}
191
192/* Assume that the gettimeofday() has microsecond granularity */
193#define MAX_ADJUSTMENT 10
194
195int FairRunIdGenerator::get_clock(uint32_t* clock_high, uint32_t* clock_low, uint16_t* ret_clock_seq)
196{
197 static int adjustment = 0;
198 static struct timeval last = {0, 0};
199 static uint16_t clock_seq;
200 struct timeval tv;
201 unsigned long long clock_reg;
202
203try_again:
204 gettimeofday(&tv, 0);
205 if ((last.tv_sec == 0) && (last.tv_usec == 0)) {
206 get_random_bytes(&clock_seq, sizeof(clock_seq));
207 clock_seq &= 0x1FFF;
208 last = tv;
209 last.tv_sec--;
210 }
211 if ((tv.tv_sec < last.tv_sec) || ((tv.tv_sec == last.tv_sec) && (tv.tv_usec < last.tv_usec))) {
212 clock_seq = (clock_seq + 1) & 0x1FFF;
213 adjustment = 0;
214 last = tv;
215 } else if ((tv.tv_sec == last.tv_sec) && (tv.tv_usec == last.tv_usec)) {
216 if (adjustment >= MAX_ADJUSTMENT) {
217 goto try_again;
218 }
219 adjustment++;
220 } else {
221 adjustment = 0;
222 last = tv;
223 }
224
225 clock_reg = tv.tv_usec * 10 + adjustment;
226 clock_reg += (static_cast<unsigned long long>(tv.tv_sec)) * 10000000;
227 clock_reg += ((static_cast<unsigned long long>(0x01B21DD2)) << 32) + 0x13814000;
228
229 *clock_high = clock_reg >> 32;
230 *clock_low = clock_reg;
231 *ret_clock_seq = clock_seq;
232
233 fTimeSpec.tv_sec = last.tv_sec;
234 // fTimeSpec.tv_nsec = last.tv_usec*1000.;
235 fTimeSpec.tv_nsec = 0.;
236
237 return 0;
238}
239
240void FairRunIdGenerator::uuid_generate_time(uuid_t out)
241{
242 static unsigned char node_id[6];
243 static int has_init = 0;
244 struct uuid uu;
245 uint32_t clock_mid;
246
247 if (!has_init) {
248 if (get_node_id(node_id) <= 0) {
249 get_random_bytes(node_id, 6);
250 /*
251 * Set multicast bit, to prevent conflicts
252 * with IEEE 802 addresses obtained from
253 * network cards
254 */
255 node_id[0] |= 0x80;
256 }
257 has_init = 1;
258 }
259 get_clock(&clock_mid, &uu.time_low, &uu.clock_seq);
260 uu.clock_seq |= 0x8000;
261 uu.time_mid = static_cast<uint16_t>(clock_mid);
262 uu.time_hi_and_version = (clock_mid >> 16) | 0x1000;
263 memcpy(uu.node, node_id, 6);
264 uuid_pack(&uu, out);
265}
266
267void FairRunIdGenerator::uuid_generate_random(uuid_t out)
268{
269 uuid_t buf;
270 struct uuid uu;
271
272 get_random_bytes(buf, sizeof(buf));
273 uuid_unpack(buf, &uu);
274
275 uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000;
276 uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000;
277 uuid_pack(&uu, out);
278}
279
280/*
281 * This is the generic front-end to uuid_generate_random and
282 * uuid_generate_time. It uses uuid_generate_random only if
283 * /dev/urandom is available, since otherwise we won't have
284 * high-quality randomness.
285 */
286void FairRunIdGenerator::uuid_generate(uuid_t out)
287{
288 /*
289 if (get_random_fd() >= 0) {
290 uuid_generate_random(out);
291 } else {
292 uuid_generate_time(out);
293 }
294 */
295 uuid_generate_time(out);
296}
297
298/*
299 * Internal routine for packing UUID's
300 *
301 * Copyright (C) 1996, 1997 Theodore Ts'o.
302 *
303 * %Begin-Header%
304 * This file may be redistributed under the terms of the GNU
305 * Library General Public License.
306 * %End-Header%
307 */
308
309void FairRunIdGenerator::uuid_pack(const struct uuid* uu, uuid_t ptr)
310{
311 uint32_t tmp;
312 unsigned char* out = ptr;
313
314 tmp = uu->time_low;
315 out[3] = static_cast<unsigned char>(tmp);
316 tmp >>= 8;
317 out[2] = static_cast<unsigned char>(tmp);
318 tmp >>= 8;
319 out[1] = static_cast<unsigned char>(tmp);
320 tmp >>= 8;
321 out[0] = static_cast<unsigned char>(tmp);
322
323 tmp = uu->time_mid;
324 out[5] = static_cast<unsigned char>(tmp);
325 tmp >>= 8;
326 out[4] = static_cast<unsigned char>(tmp);
327
328 tmp = uu->time_hi_and_version;
329 out[7] = static_cast<unsigned char>(tmp);
330 tmp >>= 8;
331 out[6] = static_cast<unsigned char>(tmp);
332
333 tmp = uu->clock_seq;
334 out[9] = static_cast<unsigned char>(tmp);
335 tmp >>= 8;
336 out[8] = static_cast<unsigned char>(tmp);
337
338 memcpy(out + 10, uu->node, 6);
339}
340
341/*
342 * Internal routine for unpacking UUID
343 *
344 * Copyright (C) 1996, 1997 Theodore Ts'o.
345 *
346 * %Begin-Header%
347 * This file may be redistributed under the terms of the GNU
348 * Library General Public License.
349 * %End-Header%
350 */
351
352void FairRunIdGenerator::uuid_unpack(const uuid_t in, struct uuid* uu)
353{
354 const uint8_t* ptr = in;
355 uint32_t tmp;
356
357 tmp = *ptr++;
358 tmp = (tmp << 8) | *ptr++;
359 tmp = (tmp << 8) | *ptr++;
360 tmp = (tmp << 8) | *ptr++;
361 uu->time_low = tmp;
362
363 tmp = *ptr++;
364 tmp = (tmp << 8) | *ptr++;
365 uu->time_mid = tmp;
366
367 tmp = *ptr++;
368 tmp = (tmp << 8) | *ptr++;
369 uu->time_hi_and_version = tmp;
370
371 tmp = *ptr++;
372 tmp = (tmp << 8) | *ptr++;
373 uu->clock_seq = tmp;
374
375 memcpy(uu->node, ptr, 6);
376}
377
379{
380 uuid_t uu;
381 // unsigned int v;
382 // struct timeval ret_tv;
383 uuid_generate(uu);
384
385 /*
386 v = ((uu[0] ^ uu[4] ^ uu[8] ^ uu[12]) << 0)
387 | ((uu[1] ^ uu[5] ^ uu[9] ^ uu[13]) << 8)
388 | ((uu[2] ^ uu[6] ^ uu[10] ^ uu[14]) << 16)
389 | ((uu[3] ^ uu[7] ^ uu[11] ^ uu[15]) << 24);
390*/
391
392 // return v & 0x7fffffff;
393 return getTID();
394}
395
396unsigned int FairRunIdGenerator::getTID() { return (fTimeSpec.tv_sec); }
397
398struct timespec FairRunIdGenerator::getTimeSpecFromTID(unsigned int ms)
399{
400 struct timespec ret_tv;
401 ret_tv.tv_sec = ms;
402 ret_tv.tv_nsec = 0.; // truncate the ns resolution
403 return ret_tv;
404}
#define srand(x)
#define MAX_ADJUSTMENT
#define rand()
unsigned int uint32_t
unsigned short int uint16_t
unsigned char uuid_t[16]
int32_t i
TBranch * ptr
unsigned int generateId(void)
GLdouble n
Definition glcorearb.h:1982
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glcorearb.h:2514
DeliveryType read(const std::string &str)
Polygon< T > close(Polygon< T > polygon)
Definition Polygon.h:126