blocxx
|
00001 /******************************************************************************* 00002 * Copyright (C) 2005, Vintela, Inc. All rights reserved. 00003 * Copyright (C) 2006, Novell, Inc. All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * * Redistributions of source code must retain the above copyright notice, 00009 * this list of conditions and the following disclaimer. 00010 * * Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * * Neither the name of 00014 * Vintela, Inc., 00015 * nor Novell, Inc., 00016 * nor the names of its contributors or employees may be used to 00017 * endorse or promote products derived from this software without 00018 * specific prior written permission. 00019 * 00020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00021 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00022 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00023 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 00024 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00025 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00026 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00027 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00028 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00029 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00030 * POSSIBILITY OF SUCH DAMAGE. 00031 *******************************************************************************/ 00032 00033 00039 #include "blocxx/BLOCXX_config.h" 00040 #include "blocxx/RandomNumber.hpp" 00041 #include "blocxx/Assertion.hpp" 00042 #include "blocxx/ThreadOnce.hpp" 00043 #include "blocxx/Mutex.hpp" 00044 #include "blocxx/MutexLock.hpp" 00045 #include "blocxx/GlobalMutex.hpp" 00046 #include <fstream> 00047 #include <sys/types.h> 00048 00049 #ifdef BLOCXX_HAVE_UNISTD_H 00050 #include <unistd.h> 00051 #endif 00052 00053 #ifdef BLOCXX_HAVE_SYS_TIME_H 00054 #include <sys/time.h> 00055 #endif 00056 00057 #include <stdlib.h> 00058 #include <time.h> 00059 00060 namespace BLOCXX_NAMESPACE 00061 { 00062 00064 namespace 00065 { 00066 OnceFlag guard = BLOCXX_ONCE_INIT; 00067 unsigned int seed = 0; 00068 } 00069 00071 RandomNumber::RandomNumber(Int32 lowVal, Int32 highVal) 00072 : m_lowVal(lowVal), m_highVal(highVal) 00073 { 00074 if (lowVal > highVal) 00075 { 00076 m_lowVal = highVal; 00077 m_highVal = lowVal; 00078 } 00079 callOnce(guard, &initRandomness); 00080 } 00081 00083 void 00084 RandomNumber::initRandomness() 00085 { 00086 #ifdef BLOCXX_WIN32 00087 time_t timeval = ::time(NULL); 00088 seed = timeval; 00089 #else 00090 // use the time as part of the seed 00091 struct timeval tv; 00092 gettimeofday(&tv, 0); 00093 // try to get something from the kernel 00094 std::ifstream infile("/dev/urandom", std::ios::in); 00095 if (!infile) 00096 { 00097 infile.open("/dev/random", std::ios::in); 00098 } 00099 // don't initialize this, we may get random stack 00100 // junk in case infile isn't usable. 00101 unsigned int dev_rand_input; 00102 if (infile) 00103 { 00104 infile.read(reinterpret_cast<char*>(&dev_rand_input), sizeof(dev_rand_input)); 00105 infile.close(); 00106 } 00107 // Build the seed. Take into account our pid and uid. 00108 seed = dev_rand_input ^ (getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec; 00109 #endif 00110 #ifdef BLOCXX_HAVE_SRANDOM 00111 srandom(seed); 00112 #else 00113 srand(seed); 00114 #endif 00115 } 00116 00118 void 00119 RandomNumber::saveRandomState() 00120 { 00121 // Do nothing. This function is so that RandomNumber has the same interface as CryptographicRandomNumber 00122 } 00123 00124 namespace 00125 { 00126 GlobalMutex g_guard = BLOCXX_GLOBAL_MUTEX_INIT(); 00127 } 00129 Int32 00130 RandomNumber::getNextNumber() 00131 { 00132 MutexLock lock(g_guard); 00133 #ifdef BLOCXX_HAVE_RANDOM 00134 return m_lowVal + (random() % (m_highVal - m_lowVal + 1)); 00135 #else 00136 return m_lowVal + (rand() % (m_highVal - m_lowVal + 1)); 00137 #endif 00138 } 00139 00140 } // end namespace BLOCXX_NAMESPACE 00141