| 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;}//------------------------------------------------------------------------------inlinestd::uint32_tmake_nonce(){    static std::atomic<std::uint32_t> nonce{0};    return ++nonce;}inlinebeast::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_LOCALinlinestd::uint32_tsecure_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();}inlinestd::uint32_tfast_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();}#elseinlinestd::uint32_tsecure_generate(){    thread_local static beast::detail::chacha<20> gen{prng_seed(), make_nonce()};    return gen();}inlinestd::uint32_tfast_generate(){    thread_local static beast::detail::pcg gen{make_pcg()};    return gen();}#endifgeneratormake_prng(bool secure){    if (secure)        return &secure_generate;    else        return &fast_generate;}} // detail} // websocket} // beast} // boost#endif
 |