update boost

This commit is contained in:
2023-11-24 12:56:13 -06:00
parent cfc99971af
commit 19d727037a
9260 changed files with 849256 additions and 299957 deletions

View File

@@ -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

View File

@@ -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 = {};
}

View File

@@ -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());

View File

@@ -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,

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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