/* */ #include "SimpleRandomizer.h" #include #include #include #include #include #include "a2time.h" namespace aria2 { std::unique_ptr SimpleRandomizer::randomizer_; const std::unique_ptr& SimpleRandomizer::getInstance() { if(!randomizer_) { randomizer_.reset(new SimpleRandomizer()); } return randomizer_; } void SimpleRandomizer::init() { #ifndef __MINGW32__ // Just in case std::random_device() is fixed, add time and pid too. eng_.seed(std::random_device()()^time(nullptr)^getpid()); #endif // !__MINGW32__ } SimpleRandomizer::SimpleRandomizer() { #ifdef __MINGW32__ BOOL r = CryptAcquireContext(&cryProvider_, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT|CRYPT_SILENT); assert(r); #endif // __MINGW32__ } SimpleRandomizer::~SimpleRandomizer() { #ifdef __MINGW32__ CryptReleaseContext(cryProvider_, 0); #endif // __MINGW32__ } long int SimpleRandomizer::getRandomNumber() { #ifdef __MINGW32__ int32_t val; BOOL r = CryptGenRandom(cryProvider_, sizeof(val), reinterpret_cast(&val)); assert(r); if(val == INT32_MIN) { val = INT32_MAX; } else if(val < 0) { val = -val; } return val; #else // !__MINGW32__ return eng_(); #endif // !__MINGW32__ } long int SimpleRandomizer::getMaxRandomNumber() { #ifdef __MINGW32__ return INT32_MAX; #else // !__MINGW32__ return eng_.max(); #endif // !__MINGW32__ } long int SimpleRandomizer::getRandomNumber(long int to) { assert(to > 0); #ifdef __MINGW32__ return getRandomNumber() % to; #else // !__MINGW32__ return std::uniform_int_distribution(0, to - 1)(eng_); #endif // !__MINGW32__ } long int SimpleRandomizer::operator()(long int to) { return getRandomNumber(to); } void SimpleRandomizer::getRandomBytes(unsigned char *buf, size_t len) { #ifdef __MINGW32__ if (!CryptGenRandom(cryProvider_, len, (PBYTE)buf)) { throw std::bad_alloc(); } #else uint32_t val; size_t q = len / sizeof(val); size_t r = len % sizeof(val); auto gen = std::bind(std::uniform_int_distribution (0, std::numeric_limits::max()), eng_); for(; q > 0; --q) { val = gen(); memcpy(buf, &val, sizeof(val)); buf += sizeof(val); } val = gen(); memcpy(buf, &val, r); #endif } } // namespace aria2