mirror of
https://github.com/boostorg/beast.git
synced 2025-08-05 07:44:35 +02:00
Add detail/prng.hpp
This commit is contained in:
@@ -2,6 +2,7 @@ Version 205
|
|||||||
|
|
||||||
* Doc work
|
* Doc work
|
||||||
* Add detail/soft_mutex.hpp
|
* Add detail/soft_mutex.hpp
|
||||||
|
* Add detail/prng.hpp
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@@ -36,11 +36,11 @@ inline
|
|||||||
void
|
void
|
||||||
make_sec_ws_key(sec_ws_key_type& key)
|
make_sec_ws_key(sec_ws_key_type& key)
|
||||||
{
|
{
|
||||||
auto p = stream_prng::prng();
|
auto g = make_prng(true);
|
||||||
char a[16];
|
char a[16];
|
||||||
for(int i = 0; i < 16; i += 4)
|
for(int i = 0; i < 16; i += 4)
|
||||||
{
|
{
|
||||||
auto const v = p->secure();
|
auto const v = g();
|
||||||
a[i ] = v & 0xff;
|
a[i ] = v & 0xff;
|
||||||
a[i+1] = (v >> 8) & 0xff;
|
a[i+1] = (v >> 8) & 0xff;
|
||||||
a[i+2] = (v >> 16) & 0xff;
|
a[i+2] = (v >> 16) & 0xff;
|
||||||
|
315
include/boost/beast/websocket/detail/impl/prng.ipp
Normal file
315
include/boost/beast/websocket/detail/impl/prng.ipp
Normal file
@@ -0,0 +1,315 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2016-2017 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_IMPL_PRNG_IPP
|
||||||
|
#define BOOST_BEAST_WEBSOCKET_DETAIL_IMPL_PRNG_IPP
|
||||||
|
|
||||||
|
#include <boost/beast/core/detail/chacha.hpp>
|
||||||
|
#include <boost/align/aligned_alloc.hpp>
|
||||||
|
#include <boost/throw_exception.hpp>
|
||||||
|
#include <atomic>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <mutex>
|
||||||
|
#include <new>
|
||||||
|
#include <random>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
class prng_pool
|
||||||
|
{
|
||||||
|
std::mutex m_;
|
||||||
|
T* head_ = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static
|
||||||
|
prng_pool&
|
||||||
|
instance()
|
||||||
|
{
|
||||||
|
static prng_pool p;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
~prng_pool()
|
||||||
|
{
|
||||||
|
for(auto p = head_; p;)
|
||||||
|
{
|
||||||
|
auto next = p->next;
|
||||||
|
p->~T();
|
||||||
|
boost::alignment::aligned_free(p);
|
||||||
|
p = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prng::ref
|
||||||
|
acquire()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
std::lock_guard<
|
||||||
|
std::mutex> g(m_);
|
||||||
|
if(head_)
|
||||||
|
{
|
||||||
|
auto p = head_;
|
||||||
|
head_ = head_->next;
|
||||||
|
return prng::ref(*p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto p = boost::alignment::aligned_alloc(
|
||||||
|
16, sizeof(T));
|
||||||
|
if(! p)
|
||||||
|
BOOST_THROW_EXCEPTION(std::bad_alloc{});
|
||||||
|
return prng::ref(*(::new(p) T()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
release(T& t)
|
||||||
|
{
|
||||||
|
std::lock_guard<
|
||||||
|
std::mutex> g(m_);
|
||||||
|
t.next = head_;
|
||||||
|
head_ = &t;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
prng::ref
|
||||||
|
make_prng_no_tls(bool secure)
|
||||||
|
{
|
||||||
|
class fast_prng final : public prng
|
||||||
|
{
|
||||||
|
int refs_ = 0;
|
||||||
|
std::minstd_rand r_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
fast_prng* next;
|
||||||
|
|
||||||
|
fast_prng()
|
||||||
|
: r_([]
|
||||||
|
{
|
||||||
|
static std::atomic<
|
||||||
|
std::uint64_t> nonce{0};
|
||||||
|
auto const pv = prng_seed();
|
||||||
|
return static_cast<value_type>(
|
||||||
|
pv[0] + pv[1] + pv[2] + pv[3] +
|
||||||
|
pv[4] + pv[5] + pv[6] + pv[7] +
|
||||||
|
++nonce);
|
||||||
|
}())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
prng&
|
||||||
|
acquire() noexcept override
|
||||||
|
{
|
||||||
|
++refs_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
release() noexcept override
|
||||||
|
{
|
||||||
|
if(--refs_ == 0)
|
||||||
|
prng_pool<fast_prng>::instance().release(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type
|
||||||
|
operator()() noexcept override
|
||||||
|
{
|
||||||
|
return r_();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class secure_prng final : public prng
|
||||||
|
{
|
||||||
|
int refs_ = 0;
|
||||||
|
beast::detail::chacha<20> r_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
secure_prng* next;
|
||||||
|
|
||||||
|
secure_prng()
|
||||||
|
: r_(prng_seed(), []
|
||||||
|
{
|
||||||
|
static std::atomic<
|
||||||
|
std::uint64_t> nonce{0};
|
||||||
|
return ++nonce;
|
||||||
|
}())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
prng&
|
||||||
|
acquire() noexcept override
|
||||||
|
{
|
||||||
|
++refs_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
release() noexcept override
|
||||||
|
{
|
||||||
|
if(--refs_ == 0)
|
||||||
|
prng_pool<secure_prng>::instance().release(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type
|
||||||
|
operator()() noexcept override
|
||||||
|
{
|
||||||
|
return r_();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if(secure)
|
||||||
|
return prng_pool<secure_prng>::instance().acquire();
|
||||||
|
|
||||||
|
return prng_pool<fast_prng>::instance().acquire();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if ! BOOST_BEAST_NO_THREAD_LOCAL
|
||||||
|
prng::ref
|
||||||
|
make_prng_tls(bool secure)
|
||||||
|
{
|
||||||
|
class fast_prng final : public prng
|
||||||
|
{
|
||||||
|
std::minstd_rand r_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
fast_prng()
|
||||||
|
: r_([]
|
||||||
|
{
|
||||||
|
static std::atomic<
|
||||||
|
std::uint64_t> nonce{0};
|
||||||
|
auto const pv = prng_seed();
|
||||||
|
return static_cast<value_type>(
|
||||||
|
pv[0] + pv[1] + pv[2] + pv[3] +
|
||||||
|
pv[4] + pv[5] + pv[6] + pv[7] +
|
||||||
|
++nonce);
|
||||||
|
}())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
prng&
|
||||||
|
acquire() noexcept override
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
release() noexcept override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type
|
||||||
|
operator()() noexcept override
|
||||||
|
{
|
||||||
|
return r_();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class secure_prng final : public prng
|
||||||
|
{
|
||||||
|
beast::detail::chacha<20> r_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
secure_prng()
|
||||||
|
: r_(prng_seed(), []
|
||||||
|
{
|
||||||
|
static std::atomic<
|
||||||
|
std::uint64_t> nonce{0};
|
||||||
|
return ++nonce;
|
||||||
|
}())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
prng&
|
||||||
|
acquire() noexcept override
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
release() noexcept override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type
|
||||||
|
operator()() noexcept override
|
||||||
|
{
|
||||||
|
return r_();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if(secure)
|
||||||
|
{
|
||||||
|
thread_local secure_prng sp;
|
||||||
|
return prng::ref(sp);
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_local fast_prng fp;
|
||||||
|
return prng::ref(fp);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
prng::ref
|
||||||
|
make_prng(bool secure)
|
||||||
|
{
|
||||||
|
#if BOOST_BEAST_NO_THREAD_LOCAL
|
||||||
|
return make_prng_no_tls(secure);
|
||||||
|
#else
|
||||||
|
return make_prng_tls(secure);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // websocket
|
||||||
|
} // beast
|
||||||
|
} // boost
|
||||||
|
|
||||||
|
#endif
|
138
include/boost/beast/websocket/detail/prng.hpp
Normal file
138
include/boost/beast/websocket/detail/prng.hpp
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) 2016-2017 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_HPP
|
||||||
|
#define BOOST_BEAST_WEBSOCKET_DETAIL_PRNG_HPP
|
||||||
|
|
||||||
|
#include <boost/beast/core/detail/config.hpp>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <limits>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
namespace websocket {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
// Type-erased UniformRandomBitGenerator
|
||||||
|
// with 32-bit unsigned integer value_type
|
||||||
|
//
|
||||||
|
class prng
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
virtual ~prng() = default;
|
||||||
|
virtual prng& acquire() noexcept = 0;
|
||||||
|
virtual void release() noexcept = 0;
|
||||||
|
virtual std::uint32_t operator()() noexcept = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_type = std::uint32_t;
|
||||||
|
|
||||||
|
class ref
|
||||||
|
{
|
||||||
|
prng& p_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ref& operator=(ref const&) = delete;
|
||||||
|
|
||||||
|
~ref()
|
||||||
|
{
|
||||||
|
p_.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit
|
||||||
|
ref(prng& p) noexcept
|
||||||
|
: p_(p.acquire())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ref(ref const& other) noexcept
|
||||||
|
: p_(other.p_.acquire())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type
|
||||||
|
operator()() noexcept
|
||||||
|
{
|
||||||
|
return p_();
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
value_type constexpr
|
||||||
|
min() noexcept
|
||||||
|
{
|
||||||
|
return (std::numeric_limits<
|
||||||
|
value_type>::min)();
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
value_type constexpr
|
||||||
|
max() noexcept
|
||||||
|
{
|
||||||
|
return (std::numeric_limits<
|
||||||
|
value_type>::max)();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Manually seed the prngs, must be called
|
||||||
|
// before acquiring a prng for the first time.
|
||||||
|
//
|
||||||
|
BOOST_BEAST_DECL
|
||||||
|
std::uint32_t const*
|
||||||
|
prng_seed(std::seed_seq* ss = nullptr);
|
||||||
|
|
||||||
|
// Acquire a PRNG using the no-TLS implementation
|
||||||
|
//
|
||||||
|
BOOST_BEAST_DECL
|
||||||
|
prng::ref
|
||||||
|
make_prng_no_tls(bool secure);
|
||||||
|
|
||||||
|
// Acquire a PRNG using the TLS implementation
|
||||||
|
//
|
||||||
|
#if ! BOOST_BEAST_NO_THREAD_LOCAL
|
||||||
|
BOOST_BEAST_DECL
|
||||||
|
prng::ref
|
||||||
|
make_prng_tls(bool secure);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Acquire a PRNG using the TLS implementation if it
|
||||||
|
// is available, otherwise using the no-TLS implementation.
|
||||||
|
//
|
||||||
|
BOOST_BEAST_DECL
|
||||||
|
prng::ref
|
||||||
|
make_prng(bool secure);
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
struct stream_prng
|
||||||
|
{
|
||||||
|
bool secure_prng_ = true;
|
||||||
|
|
||||||
|
std::uint32_t
|
||||||
|
create_mask()
|
||||||
|
{
|
||||||
|
auto g = make_prng(secure_prng_);
|
||||||
|
for(;;)
|
||||||
|
if(auto key = g())
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // websocket
|
||||||
|
} // beast
|
||||||
|
} // boost
|
||||||
|
|
||||||
|
#include <boost/beast/websocket/detail/impl/prng.ipp>
|
||||||
|
|
||||||
|
#endif
|
@@ -15,210 +15,21 @@
|
|||||||
#include <boost/beast/http/string_body.hpp>
|
#include <boost/beast/http/string_body.hpp>
|
||||||
#include <boost/beast/websocket/option.hpp>
|
#include <boost/beast/websocket/option.hpp>
|
||||||
#include <boost/beast/websocket/detail/pmd_extension.hpp>
|
#include <boost/beast/websocket/detail/pmd_extension.hpp>
|
||||||
|
#include <boost/beast/websocket/detail/prng.hpp>
|
||||||
#include <boost/beast/zlib/deflate_stream.hpp>
|
#include <boost/beast/zlib/deflate_stream.hpp>
|
||||||
#include <boost/beast/zlib/inflate_stream.hpp>
|
#include <boost/beast/zlib/inflate_stream.hpp>
|
||||||
#include <boost/beast/core/buffers_suffix.hpp>
|
#include <boost/beast/core/buffers_suffix.hpp>
|
||||||
#include <boost/beast/core/error.hpp>
|
#include <boost/beast/core/error.hpp>
|
||||||
#include <boost/beast/core/detail/chacha.hpp>
|
|
||||||
#include <boost/beast/core/detail/clamp.hpp>
|
#include <boost/beast/core/detail/clamp.hpp>
|
||||||
#include <boost/align/aligned_alloc.hpp>
|
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/core/exchange.hpp>
|
|
||||||
#include <atomic>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <new>
|
|
||||||
#include <random>
|
|
||||||
|
|
||||||
// Turn this on to avoid using thread_local
|
|
||||||
//#define BOOST_BEAST_NO_THREAD_LOCAL 1
|
|
||||||
|
|
||||||
#ifdef BOOST_BEAST_NO_THREAD_LOCAL
|
|
||||||
#include <atomic>
|
|
||||||
#include <mutex>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
namespace websocket {
|
namespace websocket {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
struct stream_prng
|
|
||||||
{
|
|
||||||
bool secure_prng_ = true;
|
|
||||||
|
|
||||||
struct prng_type
|
|
||||||
{
|
|
||||||
std::minstd_rand fast;
|
|
||||||
beast::detail::chacha<20> secure;
|
|
||||||
|
|
||||||
#if BOOST_BEAST_NO_THREAD_LOCAL
|
|
||||||
prng_type* next = nullptr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
prng_type(std::uint32_t const* v, std::uint64_t stream)
|
|
||||||
: fast(static_cast<typename decltype(fast)::result_type>(
|
|
||||||
v[0] + v[1] + v[2] + v[3] + v[4] + v[5] + v[6] + v[7] + stream))
|
|
||||||
, secure(v, stream)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class prng_ref
|
|
||||||
{
|
|
||||||
prng_type* p_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
prng_ref& operator=(prng_ref&&) = delete;
|
|
||||||
|
|
||||||
explicit
|
|
||||||
prng_ref(prng_type& p)
|
|
||||||
: p_(&p)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
prng_ref(prng_ref&& other)
|
|
||||||
: p_(boost::exchange(other.p_, nullptr))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef BOOST_BEAST_NO_THREAD_LOCAL
|
|
||||||
~prng_ref()
|
|
||||||
{
|
|
||||||
if(p_)
|
|
||||||
pool::impl().release(*p_);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
prng_type*
|
|
||||||
operator->() const
|
|
||||||
{
|
|
||||||
return p_;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifndef BOOST_BEAST_NO_THREAD_LOCAL
|
|
||||||
static
|
|
||||||
prng_ref
|
|
||||||
prng()
|
|
||||||
{
|
|
||||||
static std::atomic<std::uint64_t> stream{0};
|
|
||||||
thread_local prng_type p{seed(), stream++};
|
|
||||||
return prng_ref(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
static
|
|
||||||
prng_ref
|
|
||||||
prng()
|
|
||||||
{
|
|
||||||
return prng_ref(pool::impl().acquire());
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static
|
|
||||||
std::uint32_t const*
|
|
||||||
seed(std::seed_seq* ss = nullptr)
|
|
||||||
{
|
|
||||||
static seed_data d(ss);
|
|
||||||
return d.v;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::uint32_t
|
|
||||||
create_mask()
|
|
||||||
{
|
|
||||||
auto p = prng();
|
|
||||||
if(secure_prng_)
|
|
||||||
for(;;)
|
|
||||||
if(auto key = p->secure())
|
|
||||||
return key;
|
|
||||||
for(;;)
|
|
||||||
if(auto key = p->fast())
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct seed_data
|
|
||||||
{
|
|
||||||
std::uint32_t v[8];
|
|
||||||
|
|
||||||
explicit
|
|
||||||
seed_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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef BOOST_BEAST_NO_THREAD_LOCAL
|
|
||||||
class pool
|
|
||||||
{
|
|
||||||
prng_type* head_ = nullptr;
|
|
||||||
std::atomic<std::uint64_t> n_{0};
|
|
||||||
std::mutex m_;
|
|
||||||
|
|
||||||
public:
|
|
||||||
~pool()
|
|
||||||
{
|
|
||||||
for(auto p = head_; p;)
|
|
||||||
{
|
|
||||||
auto next = p->next;
|
|
||||||
p->~prng_type();
|
|
||||||
boost::alignment::aligned_free(p);
|
|
||||||
p = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
prng_type&
|
|
||||||
acquire()
|
|
||||||
{
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(m_);
|
|
||||||
if(! head_)
|
|
||||||
break;
|
|
||||||
auto p = head_;
|
|
||||||
head_ = head_->next;
|
|
||||||
return *p;
|
|
||||||
}
|
|
||||||
auto p = boost::alignment::aligned_alloc(
|
|
||||||
16, sizeof(prng_type));
|
|
||||||
if(! p)
|
|
||||||
BOOST_THROW_EXCEPTION(std::bad_alloc{});
|
|
||||||
return *(::new(p) prng_type(seed(), n_++));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
release(prng_type& p)
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(m_);
|
|
||||||
p.next = head_;
|
|
||||||
head_ = &p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static
|
|
||||||
pool&
|
|
||||||
impl()
|
|
||||||
{
|
|
||||||
static pool instance;
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
template<bool deflateSupported>
|
template<bool deflateSupported>
|
||||||
struct stream_base : stream_prng
|
struct stream_base : stream_prng
|
||||||
{
|
{
|
||||||
|
@@ -3511,7 +3511,7 @@ inline
|
|||||||
void
|
void
|
||||||
seed_prng(std::seed_seq& ss)
|
seed_prng(std::seed_seq& ss)
|
||||||
{
|
{
|
||||||
detail::stream_prng::seed(&ss);
|
detail::prng_seed(&ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // websocket
|
} // websocket
|
||||||
|
@@ -17,6 +17,7 @@ add_executable (tests-beast-websocket
|
|||||||
${TEST_MAIN}
|
${TEST_MAIN}
|
||||||
Jamfile
|
Jamfile
|
||||||
test.hpp
|
test.hpp
|
||||||
|
_detail_prng.cpp
|
||||||
accept.cpp
|
accept.cpp
|
||||||
close.cpp
|
close.cpp
|
||||||
error.cpp
|
error.cpp
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
local SOURCES =
|
local SOURCES =
|
||||||
|
_detail_prng.cpp
|
||||||
accept.cpp
|
accept.cpp
|
||||||
close.cpp
|
close.cpp
|
||||||
error.cpp
|
error.cpp
|
||||||
|
69
test/beast/websocket/_detail_prng.cpp
Normal file
69
test/beast/websocket/_detail_prng.cpp
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
//
|
||||||
|
// Copyright (w) 2016-2017 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
|
||||||
|
//
|
||||||
|
|
||||||
|
// Test that header file is self-contained.
|
||||||
|
#include <boost/beast/websocket/detail/prng.hpp>
|
||||||
|
|
||||||
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
namespace websocket {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
class prng_test
|
||||||
|
: public beast::unit_test::suite
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
#if 0
|
||||||
|
char const* name() const noexcept //override
|
||||||
|
{
|
||||||
|
return "boost.beast.websocket.detail.prng";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <class F>
|
||||||
|
void
|
||||||
|
testPrng(F const& f)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
auto v = f()();
|
||||||
|
BEAST_EXPECT(
|
||||||
|
v >= (prng::ref::min)() &&
|
||||||
|
v <= (prng::ref::max)());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto v = f()();
|
||||||
|
BEAST_EXPECT(
|
||||||
|
v >= (prng::ref::min)() &&
|
||||||
|
v <= (prng::ref::max)());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
run() override
|
||||||
|
{
|
||||||
|
testPrng([]{ return make_prng(true); });
|
||||||
|
testPrng([]{ return make_prng(false); });
|
||||||
|
testPrng([]{ return make_prng_no_tls(true); });
|
||||||
|
testPrng([]{ return make_prng_no_tls(false); });
|
||||||
|
#if ! BOOST_BEAST_NO_THREAD_LOCAL
|
||||||
|
testPrng([]{ return make_prng_tls(true); });
|
||||||
|
testPrng([]{ return make_prng_tls(false); });
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//static prng_test t;
|
||||||
|
BEAST_DEFINE_TESTSUITE(beast,websocket,prng);
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // websocket
|
||||||
|
} // beast
|
||||||
|
} // boost
|
Reference in New Issue
Block a user