Annotation of parser3/src/main/pa_random.C, revision 1.7
1.1 misha 1: /** @file
2: Parser: random related functions.
3:
1.6 moko 4: Copyright (c) 2001-2015 Art. Lebedev Studio (http://www.artlebedev.com)
1.1 misha 5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
6: */
7:
8: // includes
9:
10: #include "pa_random.h"
11: #include "pa_exception.h"
12: #include "pa_threads.h"
13:
1.7 ! moko 14: volatile const char * IDENT_PA_RANDOM_C="$Id: pa_random.C,v 1.6 2015/10/26 01:21:59 moko Exp $" IDENT_PA_RANDOM_H;
1.3 moko 15:
1.5 moko 16: #ifdef _MSC_VER
1.4 moko 17: #include <windows.h>
1.1 misha 18:
19: class Random_provider {
20: HCRYPTPROV fhProv;
21:
22: void acquire() {
23: SYNCHRONIZED;
24:
25: if(fhProv)
26: return;
27:
28: if(!CryptAcquireContext(&fhProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
1.7 ! moko 29: throw Exception(0, 0, "CryptAcquireContext failed");
1.1 misha 30: }
31: void release() {
32: if(fhProv)
33: CryptReleaseContext(fhProv, 0);
34: }
35:
36: public:
37: Random_provider(): fhProv(0) {}
38: ~Random_provider() { release(); }
39: void generate(void *buffer, size_t size) {
40: acquire();
41:
42: if(!CryptGenRandom(fhProv, size, (BYTE*)buffer))
1.7 ! moko 43: throw Exception(0, 0, "CryptGenRandom failed");
1.1 misha 44: }
45: }
46: random_provider;
47:
48: #else
49:
50: /// from gen_uuid.c
51: static int get_random_fd(void)
52: {
53: struct timeval tv;
54: static int fd = -2;
55: int i;
56:
57: if (fd == -2) {
58: gettimeofday(&tv, 0);
59: fd = open("/dev/urandom", O_RDONLY);
60: if (fd == -1)
61: fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
62: srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
63: }
64: /* Crank the random number generator a few times */
65: gettimeofday(&tv, 0);
66: for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
67: rand();
68: return fd;
69: }
70:
71:
72: /*
73: * Generate a series of random bytes. Use /dev/urandom if possible,
74: * and if not, use srandom/random.
75: */
76: static void get_random_bytes(void *buf, int nbytes)
77: {
78: int i, fd = get_random_fd();
79: int lose_counter = 0;
80: char *cp = (char *) buf;
81:
82: if (fd >= 0) {
83: while (nbytes > 0) {
84: i = read(fd, cp, nbytes);
85: if (i <= 0) {
86: if (lose_counter++ > 16)
87: break;
88: continue;
89: }
90: nbytes -= i;
91: cp += i;
92: lose_counter = 0;
93: }
94: }
95:
96: /* XXX put something better here if no /dev/random! */
97: for (i = 0; i < nbytes; i++)
98: *cp++ = rand() & 0xFF;
99: return;
100: }
101:
102:
103: #endif
104:
105: void random(void *buffer, size_t size) {
1.5 moko 106: #ifdef _MSC_VER
1.1 misha 107: random_provider.generate(buffer, size);
108: #else
109: get_random_bytes(buffer, size);
110: #endif
111: }
112:
1.7 ! moko 113: /// to hell with extra bytes on 64bit platforms
! 114: struct uuid {
! 115: unsigned int time_low;
! 116: unsigned short time_mid;
! 117: unsigned short time_hi_and_version;
! 118: unsigned short clock_seq;
! 119: unsigned char node[6];
! 120: };
! 121:
! 122: static uuid get_uuid() {
1.1 misha 123: // random
124: uuid uuid;
125: random(&uuid, sizeof(uuid));
126:
127: // http://www.opengroup.org/onlinepubs/9629399/apdxa.htm#tagtcjh_35
128: // ~
129: // version = DCE Security version, with embedded POSIX UIDs.
130: // variant = DCE
131: //
132: // DCE=Distributed Computing Environment
133: // http://www.opengroup.org/dce/
134: //
135: // they say this influences comparison&such,
136: // but could not figure out how, hence structure layout specified strictly
137: // anyhow, uuidgen on Win32 yield those values
138: //
139: // xxxxxxxx-xxxx-4xxx-{8,9,A,B}xxx-xxxxxxxxxxxx
140: uuid.clock_seq = (uuid.clock_seq & 0x3FFF) | 0x8000;
141: uuid.time_hi_and_version = (uuid.time_hi_and_version & 0x0FFF) | 0x4000;
142:
143: return uuid;
144: }
145:
1.7 ! moko 146: char *get_uuid_cstr() {
! 147: uuid uuid=get_uuid();
! 148:
! 149: const size_t bufsize=36+1/*zero-teminator*/+1/*for faulty snprintfs*/;
! 150: char* cstr=new(PointerFreeGC) char[bufsize];
! 151:
! 152: snprintf(cstr, bufsize,
! 153: "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
! 154: uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
! 155: uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
! 156: uuid.node[0], uuid.node[1], uuid.node[2],
! 157: uuid.node[3], uuid.node[4], uuid.node[5]);
! 158: return cstr;
! 159: }
! 160:
! 161: char *get_uuid_boundary() {
! 162: uuid uuid=get_uuid();
! 163:
! 164: const int boundary_bufsize=10+32+1/*for zero-teminator*/+1/*for faulty snprintfs*/;
! 165: char* boundary=new(PointerFreeGC) char[boundary_bufsize];
! 166:
! 167: snprintf(boundary, boundary_bufsize,
! 168: "----------%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X",
! 169: uuid.time_low, uuid.time_mid, uuid.time_hi_and_version,
! 170: uuid.clock_seq >> 8, uuid.clock_seq & 0xFF,
! 171: uuid.node[0], uuid.node[1], uuid.node[2],
! 172: uuid.node[3], uuid.node[4], uuid.node[5]);
! 173: return boundary;
! 174: }
E-mail: