123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- //
- // 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
|