152 lines
3.0 KiB
Plaintext
152 lines
3.0 KiB
Plaintext
|
//
|
||
|
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
|
||
|
//
|
||
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||
|
//
|
||
|
// Official repository: https://github.com/boostorg/beast
|
||
|
//
|
||
|
|
||
|
#ifndef BOOST_BEAST_WEBSOCKET_DETAIL_PRNG_IPP
|
||
|
#define BOOST_BEAST_WEBSOCKET_DETAIL_PRNG_IPP
|
||
|
|
||
|
#include <boost/beast/websocket/detail/prng.hpp>
|
||
|
#include <boost/beast/core/detail/chacha.hpp>
|
||
|
#include <boost/beast/core/detail/pcg.hpp>
|
||
|
#include <atomic>
|
||
|
#include <cstdlib>
|
||
|
#include <mutex>
|
||
|
#include <random>
|
||
|
|
||
|
namespace boost {
|
||
|
namespace beast {
|
||
|
namespace websocket {
|
||
|
namespace detail {
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
|
||
|
std::uint32_t const*
|
||
|
prng_seed(std::seed_seq* ss)
|
||
|
{
|
||
|
struct data
|
||
|
{
|
||
|
std::uint32_t v[8];
|
||
|
|
||
|
explicit
|
||
|
data(std::seed_seq* pss)
|
||
|
{
|
||
|
if(! pss)
|
||
|
{
|
||
|
std::random_device g;
|
||
|
std::seed_seq ss{
|
||
|
g(), g(), g(), g(),
|
||
|
g(), g(), g(), g()};
|
||
|
ss.generate(v, v+8);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pss->generate(v, v+8);
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
static data const d(ss);
|
||
|
return d.v;
|
||
|
}
|
||
|
|
||
|
//------------------------------------------------------------------------------
|
||
|
|
||
|
inline
|
||
|
std::uint32_t
|
||
|
make_nonce()
|
||
|
{
|
||
|
static std::atomic<std::uint32_t> nonce{0};
|
||
|
return ++nonce;
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
beast::detail::pcg make_pcg()
|
||
|
{
|
||
|
auto const pv = prng_seed();
|
||
|
return beast::detail::pcg{
|
||
|
((static_cast<std::uint64_t>(pv[0])<<32)+pv[1]) ^
|
||
|
((static_cast<std::uint64_t>(pv[2])<<32)+pv[3]) ^
|
||
|
((static_cast<std::uint64_t>(pv[4])<<32)+pv[5]) ^
|
||
|
((static_cast<std::uint64_t>(pv[6])<<32)+pv[7]), make_nonce()};
|
||
|
}
|
||
|
|
||
|
#ifdef BOOST_NO_CXX11_THREAD_LOCAL
|
||
|
|
||
|
inline
|
||
|
std::uint32_t
|
||
|
secure_generate()
|
||
|
{
|
||
|
struct generator
|
||
|
{
|
||
|
std::uint32_t operator()()
|
||
|
{
|
||
|
std::lock_guard<std::mutex> guard{mtx};
|
||
|
return gen();
|
||
|
}
|
||
|
|
||
|
beast::detail::chacha<20> gen;
|
||
|
std::mutex mtx;
|
||
|
};
|
||
|
static generator gen{beast::detail::chacha<20>{prng_seed(), make_nonce()}};
|
||
|
return gen();
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
std::uint32_t
|
||
|
fast_generate()
|
||
|
{
|
||
|
struct generator
|
||
|
{
|
||
|
std::uint32_t operator()()
|
||
|
{
|
||
|
std::lock_guard<std::mutex> guard{mtx};
|
||
|
return gen();
|
||
|
}
|
||
|
|
||
|
beast::detail::pcg gen;
|
||
|
std::mutex mtx;
|
||
|
};
|
||
|
static generator gen{make_pcg()};
|
||
|
return gen();
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
|
||
|
inline
|
||
|
std::uint32_t
|
||
|
secure_generate()
|
||
|
{
|
||
|
thread_local static beast::detail::chacha<20> gen{prng_seed(), make_nonce()};
|
||
|
return gen();
|
||
|
}
|
||
|
|
||
|
inline
|
||
|
std::uint32_t
|
||
|
fast_generate()
|
||
|
{
|
||
|
thread_local static beast::detail::pcg gen{make_pcg()};
|
||
|
return gen();
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
generator
|
||
|
make_prng(bool secure)
|
||
|
{
|
||
|
if (secure)
|
||
|
return &secure_generate;
|
||
|
else
|
||
|
return &fast_generate;
|
||
|
}
|
||
|
|
||
|
} // detail
|
||
|
} // websocket
|
||
|
} // beast
|
||
|
} // boost
|
||
|
|
||
|
#endif
|