update boost
This commit is contained in:
@@ -11,7 +11,6 @@
|
||||
#define BOOST_BEAST_WEBSOCKET_DETAIL_DECORATOR_HPP
|
||||
|
||||
#include <boost/beast/websocket/rfc6455.hpp>
|
||||
#include <boost/beast/core/detail/type_traits.hpp>
|
||||
#include <boost/core/exchange.hpp>
|
||||
#include <boost/type_traits/make_void.hpp>
|
||||
#include <algorithm>
|
||||
@@ -213,7 +212,7 @@ struct decorator::vtable_impl<F, true>
|
||||
void
|
||||
move(storage& dst, storage& src) noexcept
|
||||
{
|
||||
auto& f = *reinterpret_cast<F*>(&src.buf_);
|
||||
auto& f = *beast::detail::launder_cast<F*>(&src.buf_);
|
||||
::new (&dst.buf_) F(std::move(f));
|
||||
}
|
||||
|
||||
@@ -221,7 +220,7 @@ struct decorator::vtable_impl<F, true>
|
||||
void
|
||||
destroy(storage& dst) noexcept
|
||||
{
|
||||
reinterpret_cast<F*>(&dst.buf_)->~F();
|
||||
beast::detail::launder_cast<F*>(&dst.buf_)->~F();
|
||||
}
|
||||
|
||||
static
|
||||
@@ -229,7 +228,7 @@ struct decorator::vtable_impl<F, true>
|
||||
invoke_req(storage& dst, request_type& req)
|
||||
{
|
||||
maybe_invoke<F, request_type>{}(
|
||||
*reinterpret_cast<F*>(&dst.buf_), req);
|
||||
*beast::detail::launder_cast<F*>(&dst.buf_), req);
|
||||
}
|
||||
|
||||
static
|
||||
@@ -237,7 +236,7 @@ struct decorator::vtable_impl<F, true>
|
||||
invoke_res(storage& dst, response_type& res)
|
||||
{
|
||||
maybe_invoke<F, response_type>{}(
|
||||
*reinterpret_cast<F*>(&dst.buf_), res);
|
||||
*beast::detail::launder_cast<F*>(&dst.buf_), res);
|
||||
}
|
||||
|
||||
static
|
||||
|
||||
@@ -14,20 +14,10 @@
|
||||
#include <boost/beast/websocket/error.hpp>
|
||||
#include <boost/beast/websocket/rfc6455.hpp>
|
||||
#include <boost/beast/websocket/detail/utf8_checker.hpp>
|
||||
#include <boost/beast/core/buffers_suffix.hpp>
|
||||
#include <boost/beast/core/flat_static_buffer.hpp>
|
||||
#include <boost/beast/core/static_string.hpp>
|
||||
#include <boost/asio/buffer.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
// This is for <boost/endian/buffers.hpp>
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, > 0)
|
||||
# pragma warning (push)
|
||||
# pragma warning (disable: 4127) // conditional expression is constant
|
||||
#endif
|
||||
#include <boost/endian/buffers.hpp>
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, > 0)
|
||||
# pragma warning (pop)
|
||||
#endif
|
||||
#include <boost/endian/conversion.hpp>
|
||||
#include <cstdint>
|
||||
|
||||
namespace boost {
|
||||
@@ -35,56 +25,6 @@ namespace beast {
|
||||
namespace websocket {
|
||||
namespace detail {
|
||||
|
||||
inline
|
||||
std::uint16_t
|
||||
big_uint16_to_native(void const* buf)
|
||||
{
|
||||
auto const p = static_cast<
|
||||
std::uint8_t const*>(buf);
|
||||
return (p[0]<<8) + p[1];
|
||||
}
|
||||
|
||||
inline
|
||||
std::uint64_t
|
||||
big_uint64_to_native(void const* buf)
|
||||
{
|
||||
auto const p = static_cast<
|
||||
std::uint8_t const*>(buf);
|
||||
return
|
||||
(static_cast<std::uint64_t>(p[0])<<56) +
|
||||
(static_cast<std::uint64_t>(p[1])<<48) +
|
||||
(static_cast<std::uint64_t>(p[2])<<40) +
|
||||
(static_cast<std::uint64_t>(p[3])<<32) +
|
||||
(static_cast<std::uint64_t>(p[4])<<24) +
|
||||
(static_cast<std::uint64_t>(p[5])<<16) +
|
||||
(static_cast<std::uint64_t>(p[6])<< 8) +
|
||||
p[7];
|
||||
}
|
||||
|
||||
inline
|
||||
std::uint32_t
|
||||
little_uint32_to_native(void const* buf)
|
||||
{
|
||||
auto const p = static_cast<
|
||||
std::uint8_t const*>(buf);
|
||||
return
|
||||
p[0] +
|
||||
(static_cast<std::uint32_t>(p[1])<< 8) +
|
||||
(static_cast<std::uint32_t>(p[2])<<16) +
|
||||
(static_cast<std::uint32_t>(p[3])<<24);
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
native_to_little_uint32(std::uint32_t v, void* buf)
|
||||
{
|
||||
auto p = static_cast<std::uint8_t*>(buf);
|
||||
p[0] = v & 0xff;
|
||||
p[1] = (v >> 8) & 0xff;
|
||||
p[2] = (v >> 16) & 0xff;
|
||||
p[3] = (v >> 24) & 0xff;
|
||||
}
|
||||
|
||||
// frame header opcodes
|
||||
enum class opcode : std::uint8_t
|
||||
{
|
||||
@@ -193,7 +133,6 @@ template<class DynamicBuffer>
|
||||
void
|
||||
write(DynamicBuffer& db, frame_header const& fh)
|
||||
{
|
||||
using namespace boost::endian;
|
||||
std::size_t n;
|
||||
std::uint8_t b[14];
|
||||
b[0] = (fh.fin ? 0x80 : 0x00) | static_cast<std::uint8_t>(fh.op);
|
||||
@@ -212,19 +151,24 @@ write(DynamicBuffer& db, frame_header const& fh)
|
||||
else if(fh.len <= 65535)
|
||||
{
|
||||
b[1] |= 126;
|
||||
::new(&b[2]) big_uint16_buf_t{
|
||||
(std::uint16_t)fh.len};
|
||||
auto len_be = endian::native_to_big(
|
||||
static_cast<std::uint16_t>(fh.len));
|
||||
std::memcpy(&b[2], &len_be, sizeof(len_be));
|
||||
n = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
b[1] |= 127;
|
||||
::new(&b[2]) big_uint64_buf_t{fh.len};
|
||||
auto len_be = endian::native_to_big(
|
||||
static_cast<std::uint64_t>(fh.len));
|
||||
std::memcpy(&b[2], &len_be, sizeof(len_be));
|
||||
n = 10;
|
||||
}
|
||||
if(fh.mask)
|
||||
{
|
||||
native_to_little_uint32(fh.key, &b[n]);
|
||||
auto key_le = endian::native_to_little(
|
||||
static_cast<std::uint32_t>(fh.key));
|
||||
std::memcpy(&b[n], &key_le, sizeof(key_le));
|
||||
n += 4;
|
||||
}
|
||||
db.commit(net::buffer_copy(
|
||||
@@ -254,8 +198,7 @@ read_close(
|
||||
Buffers const& bs,
|
||||
error_code& ec)
|
||||
{
|
||||
using namespace boost::endian;
|
||||
auto n = buffer_bytes(bs);
|
||||
auto const n = buffer_bytes(bs);
|
||||
BOOST_ASSERT(n <= 125);
|
||||
if(n == 0)
|
||||
{
|
||||
@@ -266,39 +209,32 @@ read_close(
|
||||
if(n == 1)
|
||||
{
|
||||
// invalid payload size == 1
|
||||
ec = error::bad_close_size;
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_close_size);
|
||||
return;
|
||||
}
|
||||
buffers_suffix<Buffers> cb(bs);
|
||||
|
||||
std::uint16_t code_be;
|
||||
cr.reason.resize(n - 2);
|
||||
std::array<net::mutable_buffer, 2> out_bufs{{
|
||||
net::mutable_buffer(&code_be, sizeof(code_be)),
|
||||
net::mutable_buffer(&cr.reason[0], n - 2)}};
|
||||
|
||||
net::buffer_copy(out_bufs, bs);
|
||||
|
||||
cr.code = endian::big_to_native(code_be);
|
||||
if(! is_valid_close_code(cr.code))
|
||||
{
|
||||
std::uint8_t b[2];
|
||||
net::buffer_copy(net::buffer(b), cb);
|
||||
cr.code = big_uint16_to_native(&b[0]);
|
||||
cb.consume(2);
|
||||
n -= 2;
|
||||
if(! is_valid_close_code(cr.code))
|
||||
{
|
||||
// invalid close code
|
||||
ec = error::bad_close_code;
|
||||
return;
|
||||
}
|
||||
// invalid close code
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_close_code);
|
||||
return;
|
||||
}
|
||||
if(n > 0)
|
||||
|
||||
if(n > 2 && !check_utf8(
|
||||
cr.reason.data(), cr.reason.size()))
|
||||
{
|
||||
cr.reason.resize(n);
|
||||
net::buffer_copy(
|
||||
net::buffer(&cr.reason[0], n), cb);
|
||||
if(! check_utf8(
|
||||
cr.reason.data(), cr.reason.size()))
|
||||
{
|
||||
// not valid utf-8
|
||||
ec = error::bad_close_payload;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cr.reason = "";
|
||||
// not valid utf-8
|
||||
BOOST_BEAST_ASSIGN_EC(ec, error::bad_close_payload);
|
||||
return;
|
||||
}
|
||||
ec = {};
|
||||
}
|
||||
|
||||
@@ -27,18 +27,12 @@ void
|
||||
make_sec_ws_key(sec_ws_key_type& key)
|
||||
{
|
||||
auto g = make_prng(true);
|
||||
char a[16];
|
||||
for(int i = 0; i < 16; i += 4)
|
||||
{
|
||||
auto const v = g();
|
||||
a[i ] = v & 0xff;
|
||||
a[i+1] = (v >> 8) & 0xff;
|
||||
a[i+2] = (v >> 16) & 0xff;
|
||||
a[i+3] = (v >> 24) & 0xff;
|
||||
}
|
||||
std::uint32_t a[4];
|
||||
for (auto& v : a)
|
||||
v = g();
|
||||
key.resize(key.max_size());
|
||||
key.resize(beast::detail::base64::encode(
|
||||
key.data(), &a[0], 16));
|
||||
key.data(), &a[0], sizeof(a)));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -46,12 +40,13 @@ make_sec_ws_accept(
|
||||
sec_ws_accept_type& accept,
|
||||
string_view key)
|
||||
{
|
||||
BOOST_ASSERT(key.size() <= sec_ws_key_type::max_size_n);
|
||||
static_string<sec_ws_key_type::max_size_n + 36> m(key);
|
||||
m.append("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
|
||||
BOOST_ASSERT(key.size() <= sec_ws_key_type::static_capacity);
|
||||
using namespace beast::detail::string_literals;
|
||||
auto const guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"_sv;
|
||||
beast::detail::sha1_context ctx;
|
||||
beast::detail::init(ctx);
|
||||
beast::detail::update(ctx, m.data(), m.size());
|
||||
beast::detail::update(ctx, key.data(), key.size());
|
||||
beast::detail::update(ctx, guid.data(), guid.size());
|
||||
char digest[beast::detail::sha1_context::digest_size];
|
||||
beast::detail::finish(ctx, &digest[0]);
|
||||
accept.resize(accept.max_size());
|
||||
|
||||
@@ -137,7 +137,7 @@ struct impl_base<true>
|
||||
return false;
|
||||
if(zs.avail_out >= 6)
|
||||
{
|
||||
zo.write(zs, zlib::Flush::full, ec);
|
||||
zo.write(zs, zlib::Flush::sync, ec);
|
||||
BOOST_ASSERT(! ec);
|
||||
// remove flush marker
|
||||
zs.total_out -= 4;
|
||||
@@ -302,6 +302,11 @@ struct impl_base<true>
|
||||
return pmd_ != nullptr;
|
||||
}
|
||||
|
||||
bool should_compress(std::size_t n_bytes) const
|
||||
{
|
||||
return n_bytes >= pmd_opts_.msg_size_threshold;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
read_size_hint_pmd(
|
||||
std::size_t initial_size,
|
||||
@@ -447,6 +452,11 @@ struct impl_base<false>
|
||||
return false;
|
||||
}
|
||||
|
||||
bool should_compress(std::size_t) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::size_t
|
||||
read_size_hint_pmd(
|
||||
std::size_t initial_size,
|
||||
|
||||
@@ -26,62 +26,27 @@ namespace detail {
|
||||
|
||||
using prepared_key = std::array<unsigned char, 4>;
|
||||
|
||||
inline
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
prepare_key(prepared_key& prepared, std::uint32_t key)
|
||||
{
|
||||
prepared[0] = (key >> 0) & 0xff;
|
||||
prepared[1] = (key >> 8) & 0xff;
|
||||
prepared[2] = (key >> 16) & 0xff;
|
||||
prepared[3] = (key >> 24) & 0xff;
|
||||
}
|
||||
|
||||
template<std::size_t N>
|
||||
void
|
||||
rol(std::array<unsigned char, N>& v, std::size_t n)
|
||||
{
|
||||
auto v0 = v;
|
||||
for(std::size_t i = 0; i < v.size(); ++i )
|
||||
v[i] = v0[(i + n) % v.size()];
|
||||
}
|
||||
prepare_key(prepared_key& prepared, std::uint32_t key);
|
||||
|
||||
// Apply mask in place
|
||||
//
|
||||
inline
|
||||
BOOST_BEAST_DECL
|
||||
void
|
||||
mask_inplace(net::mutable_buffer& b, prepared_key& key)
|
||||
{
|
||||
auto n = b.size();
|
||||
auto mask = key; // avoid aliasing
|
||||
auto p = static_cast<unsigned char*>(b.data());
|
||||
while(n >= 4)
|
||||
{
|
||||
for(int i = 0; i < 4; ++i)
|
||||
p[i] ^= mask[i];
|
||||
p += 4;
|
||||
n -= 4;
|
||||
}
|
||||
if(n > 0)
|
||||
{
|
||||
for(std::size_t i = 0; i < n; ++i)
|
||||
p[i] ^= mask[i];
|
||||
rol(key, n);
|
||||
}
|
||||
}
|
||||
mask_inplace(net::mutable_buffer const& b, prepared_key& key);
|
||||
|
||||
// Apply mask in place
|
||||
//
|
||||
template<
|
||||
class MutableBufferSequence,
|
||||
class KeyType>
|
||||
template<class MutableBufferSequence>
|
||||
void
|
||||
mask_inplace(
|
||||
MutableBufferSequence const& buffers,
|
||||
KeyType& key)
|
||||
prepared_key& key)
|
||||
{
|
||||
for(net::mutable_buffer b :
|
||||
beast::buffers_range_ref(buffers))
|
||||
mask_inplace(b, key);
|
||||
detail::mask_inplace(b, key);
|
||||
}
|
||||
|
||||
} // detail
|
||||
@@ -89,4 +54,10 @@ mask_inplace(
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
|
||||
#if BOOST_BEAST_HEADER_ONLY
|
||||
#include <boost/beast/websocket/detail/mask.ipp>
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
66
linx64/include/boost/beast/websocket/detail/mask.ipp
Normal file
66
linx64/include/boost/beast/websocket/detail/mask.ipp
Normal file
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// 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_MASK_IPP
|
||||
#define BOOST_BEAST_WEBSOCKET_DETAIL_MASK_IPP
|
||||
|
||||
#include <boost/beast/websocket/detail/mask.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace beast {
|
||||
namespace websocket {
|
||||
namespace detail {
|
||||
|
||||
void
|
||||
prepare_key(prepared_key& prepared, std::uint32_t key)
|
||||
{
|
||||
prepared[0] = (key >> 0) & 0xff;
|
||||
prepared[1] = (key >> 8) & 0xff;
|
||||
prepared[2] = (key >> 16) & 0xff;
|
||||
prepared[3] = (key >> 24) & 0xff;
|
||||
}
|
||||
|
||||
inline
|
||||
void
|
||||
rol(prepared_key& v, std::size_t n)
|
||||
{
|
||||
auto v0 = v;
|
||||
for(std::size_t i = 0; i < v.size(); ++i )
|
||||
v[i] = v0[(i + n) % v.size()];
|
||||
}
|
||||
|
||||
// Apply mask in place
|
||||
//
|
||||
void
|
||||
mask_inplace(net::mutable_buffer const& b, prepared_key& key)
|
||||
{
|
||||
auto n = b.size();
|
||||
auto const mask = key; // avoid aliasing
|
||||
auto p = static_cast<unsigned char*>(b.data());
|
||||
while(n >= 4)
|
||||
{
|
||||
for(int i = 0; i < 4; ++i)
|
||||
p[i] ^= mask[i];
|
||||
p += 4;
|
||||
n -= 4;
|
||||
}
|
||||
if(n > 0)
|
||||
{
|
||||
for(std::size_t i = 0; i < n; ++i)
|
||||
p[i] ^= mask[i];
|
||||
rol(key, n);
|
||||
}
|
||||
}
|
||||
|
||||
} // detail
|
||||
} // websocket
|
||||
} // beast
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
@@ -82,7 +82,7 @@ pmd_write(http::basic_fields<Allocator>& fields,
|
||||
pmd_offer const& offer)
|
||||
{
|
||||
auto s = detail::pmd_write_impl(offer);
|
||||
fields.set(http::field::sec_websocket_extensions, s);
|
||||
fields.set(http::field::sec_websocket_extensions, to_string_view(s));
|
||||
}
|
||||
|
||||
// Negotiate a permessage-deflate client offer
|
||||
@@ -104,7 +104,7 @@ pmd_negotiate(
|
||||
|
||||
auto s = detail::pmd_negotiate_impl(config, offer, o);
|
||||
if(config.accept)
|
||||
fields.set(http::field::sec_websocket_extensions, s);
|
||||
fields.set(http::field::sec_websocket_extensions, to_string_view(s));
|
||||
}
|
||||
|
||||
// Normalize the server's response
|
||||
|
||||
@@ -52,11 +52,11 @@ pmd_read_impl(pmd_offer& offer, http::ext_list const& list)
|
||||
|
||||
for(auto const& ext : list)
|
||||
{
|
||||
if(iequals(ext.first, "permessage-deflate"))
|
||||
if(beast::iequals(ext.first, "permessage-deflate"))
|
||||
{
|
||||
for(auto const& param : ext.second)
|
||||
{
|
||||
if(iequals(param.first,
|
||||
if(beast::iequals(param.first,
|
||||
"server_max_window_bits"))
|
||||
{
|
||||
if(offer.server_max_window_bits != 0)
|
||||
@@ -84,7 +84,7 @@ pmd_read_impl(pmd_offer& offer, http::ext_list const& list)
|
||||
return; // MUST decline
|
||||
}
|
||||
}
|
||||
else if(iequals(param.first,
|
||||
else if(beast::iequals(param.first,
|
||||
"client_max_window_bits"))
|
||||
{
|
||||
if(offer.client_max_window_bits != 0)
|
||||
@@ -112,7 +112,7 @@ pmd_read_impl(pmd_offer& offer, http::ext_list const& list)
|
||||
offer.client_max_window_bits = -1;
|
||||
}
|
||||
}
|
||||
else if(iequals(param.first,
|
||||
else if(beast::iequals(param.first,
|
||||
"server_no_context_takeover"))
|
||||
{
|
||||
if(offer.server_no_context_takeover)
|
||||
@@ -131,7 +131,7 @@ pmd_read_impl(pmd_offer& offer, http::ext_list const& list)
|
||||
}
|
||||
offer.server_no_context_takeover = true;
|
||||
}
|
||||
else if(iequals(param.first,
|
||||
else if(beast::iequals(param.first,
|
||||
"client_no_context_takeover"))
|
||||
{
|
||||
if(offer.client_no_context_takeover)
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
#define BOOST_BEAST_WEBSOCKET_DETAIL_PRNG_HPP
|
||||
|
||||
#include <boost/beast/core/detail/config.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <random>
|
||||
|
||||
namespace boost {
|
||||
@@ -20,66 +20,7 @@ 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)();
|
||||
}
|
||||
};
|
||||
};
|
||||
using generator = std::uint32_t(*)();
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -90,25 +31,11 @@ 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
|
||||
//
|
||||
#ifndef BOOST_NO_CXX11_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
|
||||
generator
|
||||
make_prng(bool secure);
|
||||
|
||||
} // detail
|
||||
|
||||
@@ -13,14 +13,10 @@
|
||||
#include <boost/beast/websocket/detail/prng.hpp>
|
||||
#include <boost/beast/core/detail/chacha.hpp>
|
||||
#include <boost/beast/core/detail/pcg.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 {
|
||||
@@ -59,264 +55,92 @@ prng_seed(std::seed_seq* ss)
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
template<class T>
|
||||
class prng_pool
|
||||
inline
|
||||
std::uint32_t
|
||||
make_nonce()
|
||||
{
|
||||
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;
|
||||
beast::detail::pcg r_;
|
||||
|
||||
public:
|
||||
fast_prng* next = nullptr;
|
||||
|
||||
fast_prng()
|
||||
: r_(
|
||||
[]{
|
||||
auto const pv = prng_seed();
|
||||
return
|
||||
((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]);
|
||||
}(),
|
||||
[]{
|
||||
static std::atomic<
|
||||
std::uint32_t> nonce{0};
|
||||
return ++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 = nullptr;
|
||||
|
||||
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();
|
||||
static std::atomic<std::uint32_t> nonce{0};
|
||||
return ++nonce;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#ifndef BOOST_NO_CXX11_THREAD_LOCAL
|
||||
|
||||
prng::ref
|
||||
make_prng_tls(bool secure)
|
||||
inline
|
||||
beast::detail::pcg make_pcg()
|
||||
{
|
||||
class fast_prng final : public prng
|
||||
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
|
||||
{
|
||||
beast::detail::pcg r_;
|
||||
|
||||
public:
|
||||
fast_prng()
|
||||
: r_(
|
||||
[]{
|
||||
auto const pv = prng_seed();
|
||||
return
|
||||
((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]);
|
||||
}(),
|
||||
[]{
|
||||
static std::atomic<
|
||||
std::uint32_t> nonce{0};
|
||||
return ++nonce;
|
||||
}())
|
||||
std::uint32_t operator()()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard{mtx};
|
||||
return gen();
|
||||
}
|
||||
|
||||
protected:
|
||||
prng&
|
||||
acquire() noexcept override
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
release() noexcept override
|
||||
{
|
||||
}
|
||||
|
||||
value_type
|
||||
operator()() noexcept override
|
||||
{
|
||||
return r_();
|
||||
}
|
||||
beast::detail::chacha<20> gen;
|
||||
std::mutex mtx;
|
||||
};
|
||||
static generator gen{beast::detail::chacha<20>{prng_seed(), make_nonce()}};
|
||||
return gen();
|
||||
}
|
||||
|
||||
class secure_prng final : public prng
|
||||
inline
|
||||
std::uint32_t
|
||||
fast_generate()
|
||||
{
|
||||
struct generator
|
||||
{
|
||||
beast::detail::chacha<20> r_;
|
||||
|
||||
public:
|
||||
secure_prng()
|
||||
: r_(prng_seed(), []
|
||||
{
|
||||
static std::atomic<
|
||||
std::uint64_t> nonce{0};
|
||||
return ++nonce;
|
||||
}())
|
||||
std::uint32_t operator()()
|
||||
{
|
||||
std::lock_guard<std::mutex> guard{mtx};
|
||||
return gen();
|
||||
}
|
||||
|
||||
protected:
|
||||
prng&
|
||||
acquire() noexcept override
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
void
|
||||
release() noexcept override
|
||||
{
|
||||
}
|
||||
|
||||
value_type
|
||||
operator()() noexcept override
|
||||
{
|
||||
return r_();
|
||||
}
|
||||
beast::detail::pcg gen;
|
||||
std::mutex mtx;
|
||||
};
|
||||
static generator gen{make_pcg()};
|
||||
return gen();
|
||||
}
|
||||
|
||||
if(secure)
|
||||
{
|
||||
thread_local secure_prng sp;
|
||||
return prng::ref(sp);
|
||||
}
|
||||
#else
|
||||
|
||||
thread_local fast_prng fp;
|
||||
return prng::ref(fp);
|
||||
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
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
prng::ref
|
||||
generator
|
||||
make_prng(bool secure)
|
||||
{
|
||||
#ifdef BOOST_NO_CXX11_THREAD_LOCAL
|
||||
return make_prng_no_tls(secure);
|
||||
#else
|
||||
return make_prng_tls(secure);
|
||||
#endif
|
||||
if (secure)
|
||||
return &secure_generate;
|
||||
else
|
||||
return &fast_generate;
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
Reference in New Issue
Block a user