Annotation of parser3/src/main/pa_random.C, revision 1.1

1.1     ! misha       1: /** @file
        !             2:        Parser: random related functions.
        !             3: 
        !             4:        Copyright (c) 2001-2008 ArtLebedev Group (http://www.artlebedev.com)
        !             5:        Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
        !             6: */
        !             7: 
        !             8: static const char * const IDENT_RANDOM_C="$Date: 2009-01-12 07:42:44 $";
        !             9: 
        !            10: // includes
        !            11: 
        !            12: #include "pa_random.h"
        !            13: #include "pa_exception.h"
        !            14: #include "pa_threads.h"
        !            15: 
        !            16: #ifdef WIN32
        !            17: #      include <windows.h>
        !            18: #endif
        !            19: 
        !            20: #ifdef WIN32
        !            21: class Random_provider {
        !            22:        HCRYPTPROV fhProv;
        !            23:        
        !            24:        void acquire() {
        !            25:                SYNCHRONIZED;
        !            26: 
        !            27:                if(fhProv)
        !            28:                        return;
        !            29: 
        !            30:                if(!CryptAcquireContext(&fhProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
        !            31:                        throw Exception(0,
        !            32:                                0,
        !            33:                                "CryptAcquireContext failed");
        !            34:        }
        !            35:        void release() {
        !            36:                if(fhProv)
        !            37:                        CryptReleaseContext(fhProv, 0);
        !            38:        }
        !            39:        
        !            40: public:
        !            41:        Random_provider(): fhProv(0) {}
        !            42:        ~Random_provider() { release(); }
        !            43:        void generate(void *buffer, size_t size) {
        !            44:                acquire();
        !            45: 
        !            46:                if(!CryptGenRandom(fhProv, size, (BYTE*)buffer))
        !            47:                        throw Exception(0,
        !            48:                                0,
        !            49:                                "CryptGenRandom failed");
        !            50:        }
        !            51: }
        !            52:        random_provider;
        !            53: 
        !            54: #else
        !            55: 
        !            56: /// from gen_uuid.c
        !            57: static int get_random_fd(void)
        !            58: {
        !            59:         struct timeval  tv;
        !            60:         static int      fd = -2;
        !            61:         int             i;
        !            62: 
        !            63:         if (fd == -2) {
        !            64:                 gettimeofday(&tv, 0);
        !            65:                 fd = open("/dev/urandom", O_RDONLY);
        !            66:                 if (fd == -1)
        !            67:                         fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
        !            68:                 srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
        !            69:         }
        !            70:         /* Crank the random number generator a few times */
        !            71:         gettimeofday(&tv, 0);
        !            72:         for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
        !            73:                 rand();
        !            74:         return fd;
        !            75: }
        !            76: 
        !            77: 
        !            78: /*
        !            79:  * Generate a series of random bytes.  Use /dev/urandom if possible,
        !            80:  * and if not, use srandom/random.
        !            81:  */
        !            82: static void get_random_bytes(void *buf, int nbytes)
        !            83: {
        !            84:         int i, fd = get_random_fd();
        !            85:         int lose_counter = 0;
        !            86:         char *cp = (char *) buf;
        !            87: 
        !            88:         if (fd >= 0) {
        !            89:                 while (nbytes > 0) {
        !            90:                         i = read(fd, cp, nbytes);
        !            91:                         if (i <= 0) {
        !            92:                                 if (lose_counter++ > 16)
        !            93:                                         break;
        !            94:                                 continue;
        !            95:                         }
        !            96:                         nbytes -= i;
        !            97:                         cp += i;
        !            98:                         lose_counter = 0;
        !            99:                 }
        !           100:         }
        !           101: 
        !           102:         /* XXX put something better here if no /dev/random! */
        !           103:         for (i = 0; i < nbytes; i++)
        !           104:                 *cp++ = rand() & 0xFF;
        !           105:         return;
        !           106: }
        !           107: 
        !           108: 
        !           109: #endif
        !           110: 
        !           111: void random(void *buffer, size_t size) {
        !           112: #ifdef WIN32
        !           113:        random_provider.generate(buffer, size);
        !           114: #else
        !           115:        get_random_bytes(buffer, size);
        !           116: #endif
        !           117: }
        !           118: 
        !           119: uuid get_uuid() {
        !           120:        // random
        !           121:        uuid uuid;
        !           122:        random(&uuid, sizeof(uuid));
        !           123: 
        !           124:        // http://www.opengroup.org/onlinepubs/9629399/apdxa.htm#tagtcjh_35
        !           125:        // ~
        !           126:        // version = DCE Security version, with embedded POSIX UIDs.  
        !           127:        // variant = DCE
        !           128:        //
        !           129:        // DCE=Distributed Computing Environment
        !           130:        // http://www.opengroup.org/dce/
        !           131:        //
        !           132:        // they say this influences comparison&such,
        !           133:        // but could not figure out how, hence structure layout specified strictly
        !           134:        // anyhow, uuidgen on Win32 yield those values
        !           135:        // 
        !           136:        // xxxxxxxx-xxxx-4xxx-{8,9,A,B}xxx-xxxxxxxxxxxx
        !           137:        uuid.clock_seq = (uuid.clock_seq & 0x3FFF) | 0x8000;
        !           138:         uuid.time_hi_and_version = (uuid.time_hi_and_version & 0x0FFF) | 0x4000;
        !           139: 
        !           140:        return uuid;
        !           141: }
        !           142: 

E-mail: