// // 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 #include #include #include #include #include #include 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 nonce{0}; return ++nonce; } inline beast::detail::pcg make_pcg() { auto const pv = prng_seed(); return beast::detail::pcg{ ((static_cast(pv[0])<<32)+pv[1]) ^ ((static_cast(pv[2])<<32)+pv[3]) ^ ((static_cast(pv[4])<<32)+pv[5]) ^ ((static_cast(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 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 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