diff options
Diffstat (limited to 'boost/beast')
86 files changed, 1380 insertions, 1695 deletions
diff --git a/boost/beast/_experimental/http/impl/icy_stream.hpp b/boost/beast/_experimental/http/impl/icy_stream.hpp index f7329180ee..9b6e66ab92 100644 --- a/boost/beast/_experimental/http/impl/icy_stream.hpp +++ b/boost/beast/_experimental/http/impl/icy_stream.hpp @@ -35,7 +35,7 @@ is_icy(ConstBufferSequence const& buffers) char buf[3]; auto const n = net::buffer_copy( net::mutable_buffer(buf, 3), - buffers); + buffers); if(n >= 1 && buf[0] != 'I') return false; if(n >= 2 && buf[1] != 'C') @@ -57,7 +57,7 @@ template<class Buffers, class Handler> class read_op : public beast::async_base<Handler, beast::executor_type<icy_stream>> - , public net::coroutine + , public asio::coroutine { icy_stream& s_; Buffers b_; diff --git a/boost/beast/_experimental/test/impl/stream.hpp b/boost/beast/_experimental/test/impl/stream.hpp index 53bd4db7c8..3925d7421f 100644 --- a/boost/beast/_experimental/test/impl/stream.hpp +++ b/boost/beast/_experimental/test/impl/stream.hpp @@ -12,9 +12,8 @@ #include <boost/beast/core/bind_handler.hpp> #include <boost/beast/core/buffer_traits.hpp> -#include <boost/beast/core/buffers_prefix.hpp> #include <boost/beast/core/detail/service_base.hpp> -#include <boost/beast/core/detail/type_traits.hpp> +#include <boost/beast/core/detail/is_invocable.hpp> #include <mutex> #include <stdexcept> #include <vector> @@ -108,6 +107,7 @@ class stream::read_op : public stream::read_op_base net::buffer_copy( b_, sp->b.data(), sp->read_max); sp->b.consume(bytes_transferred); + sp->nread_bytes += bytes_transferred; } else if (buffer_bytes(b_) > 0) { @@ -232,6 +232,7 @@ struct stream::run_write_op std::lock_guard<std::mutex> lock(out->m); n = net::buffer_copy(out->b.prepare(n), buffers); out->b.commit(n); + out->nwrite_bytes += n; out->notify_read(); } BOOST_ASSERT(! ec); @@ -295,6 +296,7 @@ read_some(MutableBufferSequence const& buffers, auto const n = net::buffer_copy( buffers, in_->b.data(), in_->read_max); in_->b.consume(n); + in_->nread_bytes += n; return n; } @@ -378,6 +380,7 @@ write_some( std::lock_guard<std::mutex> lock(out->m); n = net::buffer_copy(out->b.prepare(n), buffers); out->b.commit(n); + out->nwrite_bytes += n; out->notify_read(); } return n; diff --git a/boost/beast/_experimental/test/impl/stream.ipp b/boost/beast/_experimental/test/impl/stream.ipp index 38b8a8b2a4..1570ccaac0 100644 --- a/boost/beast/_experimental/test/impl/stream.ipp +++ b/boost/beast/_experimental/test/impl/stream.ipp @@ -13,7 +13,6 @@ #include <boost/beast/_experimental/test/stream.hpp> #include <boost/beast/core/bind_handler.hpp> #include <boost/beast/core/buffer_traits.hpp> -#include <boost/beast/core/buffers_prefix.hpp> #include <boost/make_shared.hpp> #include <stdexcept> #include <vector> @@ -262,6 +261,9 @@ connect(stream& remote) { BOOST_ASSERT(! out_.lock()); BOOST_ASSERT(! remote.out_.lock()); + std::lock(in_->m, remote.in_->m); + std::lock_guard<std::mutex> guard1{in_->m, std::adopt_lock}; + std::lock_guard<std::mutex> guard2{remote.in_->m, std::adopt_lock}; out_ = remote.in_; remote.out_ = in_; in_->code = status::ok; @@ -275,7 +277,7 @@ str() const auto const bs = in_->b.data(); if(buffer_bytes(bs) == 0) return {}; - auto const b = beast::buffers_front(bs); + net::const_buffer const b = *net::buffer_sequence_begin(bs); return {static_cast<char const*>(b.data()), b.size()}; } diff --git a/boost/beast/_experimental/test/stream.hpp b/boost/beast/_experimental/test/stream.hpp index 181acec9aa..eb12e8d840 100644 --- a/boost/beast/_experimental/test/stream.hpp +++ b/boost/beast/_experimental/test/stream.hpp @@ -141,7 +141,9 @@ class stream status code = status::ok; fail_count* fc = nullptr; std::size_t nread = 0; + std::size_t nread_bytes = 0; std::size_t nwrite = 0; + std::size_t nwrite_bytes = 0; std::size_t read_max = (std::numeric_limits<std::size_t>::max)(); std::size_t write_max = @@ -361,6 +363,13 @@ public: return in_->nread; } + /// Return the number of bytes read + std::size_t + nread_bytes() const noexcept + { + return in_->nread_bytes; + } + /// Return the number of writes std::size_t nwrite() const noexcept @@ -368,6 +377,13 @@ public: return in_->nwrite; } + /// Return the number of bytes written + std::size_t + nwrite_bytes() const noexcept + { + return in_->nwrite_bytes; + } + /** Close the stream. The other end of the connection will see diff --git a/boost/beast/_experimental/unit_test/thread.hpp b/boost/beast/_experimental/unit_test/thread.hpp deleted file mode 100644 index ed06cb3731..0000000000 --- a/boost/beast/_experimental/unit_test/thread.hpp +++ /dev/null @@ -1,128 +0,0 @@ -// -// 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_UNIT_TEST_THREAD_HPP -#define BOOST_BEAST_UNIT_TEST_THREAD_HPP - -#include <boost/beast/_experimental/unit_test/suite.hpp> -#include <functional> -#include <thread> -#include <utility> - -namespace boost { -namespace beast { -namespace unit_test { - -/** Replacement for std::thread that handles exceptions in unit tests. */ -class thread -{ -private: - suite* s_ = nullptr; - std::thread t_; - -public: - using id = std::thread::id; - using native_handle_type = std::thread::native_handle_type; - - thread() = default; - thread(thread const&) = delete; - thread& operator=(thread const&) = delete; - - thread(thread&& other) - : s_(other.s_) - , t_(std::move(other.t_)) - { - } - - thread& operator=(thread&& other) - { - s_ = other.s_; - t_ = std::move(other.t_); - return *this; - } - - template<class F, class... Args> - explicit - thread(suite& s, F&& f, Args&&... args) - : s_(&s) - { - std::function<void(void)> b = - std::bind(std::forward<F>(f), - std::forward<Args>(args)...); - t_ = std::thread(&thread::run, this, - std::move(b)); - } - - bool - joinable() const - { - return t_.joinable(); - } - - std::thread::id - get_id() const - { - return t_.get_id(); - } - - static - unsigned - hardware_concurrency() noexcept - { - return std::thread::hardware_concurrency(); - } - - void - join() - { - t_.join(); - s_->propagate_abort(); - } - - void - detach() - { - t_.detach(); - } - - void - swap(thread& other) - { - std::swap(s_, other.s_); - std::swap(t_, other.t_); - } - -private: - void - run(std::function <void(void)> f) - { - try - { - f(); - } - catch(suite::abort_exception const&) - { - } - catch(std::exception const& e) - { - s_->fail("unhandled exception: " + - std::string(e.what())); - } - catch(...) - { - s_->fail("unhandled exception"); - } - } -}; - -} // unit_test -} // beast -} // boost - -#endif diff --git a/boost/beast/core/basic_stream.hpp b/boost/beast/core/basic_stream.hpp index 057ab07ffd..25076059e2 100644 --- a/boost/beast/core/basic_stream.hpp +++ b/boost/beast/core/basic_stream.hpp @@ -73,7 +73,7 @@ namespace beast { be invoked by the executor associated with the stream upon construction. The type of executor used with this stream must meet the following requirements: - + @li Function objects submitted to the executor shall never run concurrently with each other. @@ -284,6 +284,7 @@ private: // but the implementation is still waiting on a timer. boost::shared_ptr<impl_type> impl_; + template<class Executor2> struct timeout_handler; struct ops; @@ -367,7 +368,7 @@ public: /** Move constructor - @param other The other object from which the move will occur. + @param other The other object from which the move will occur. @note Following the move, the moved-from object is in the same state as if newly constructed. @@ -490,7 +491,7 @@ public: //-------------------------------------------------------------------------- /** Get the executor associated with the object. - + This function may be used to obtain the executor object that the stream uses to dispatch completion handlers without an assocaited executor. @@ -498,7 +499,7 @@ public: @return A copy of the executor that stream will use to dispatch handlers. */ executor_type - get_executor() const noexcept + get_executor() noexcept { return impl_->ex(); } @@ -525,7 +526,7 @@ public: } /** Connect the stream to the specified endpoint. - + This function is used to connect the underlying socket to the specified remote endpoint. The function call will block until the connection is successfully made or an error occurs. @@ -534,7 +535,7 @@ public: closed state upon failure. @param ep The remote endpoint to connect to. - + @param ec Set to indicate what error occurred, if any. @see connect @@ -546,7 +547,7 @@ public: } /** Establishes a connection by trying each endpoint in a sequence. - + This function attempts to connect the stream to one of a sequence of endpoints by trying each endpoint until a connection is successfully established. @@ -556,11 +557,11 @@ public: The algorithm, known as a <em>composed operation</em>, is implemented in terms of calls to the underlying socket's `connect` function. - + @param endpoints A sequence of endpoints. - + @returns The successfully connected endpoint. - + @throws system_error Thrown on failure. If the sequence is empty, the associated error code is `net::error::not_found`. Otherwise, contains the error from the last connection attempt. @@ -579,7 +580,7 @@ public: } /** Establishes a connection by trying each endpoint in a sequence. - + This function attempts to connect the stream to one of a sequence of endpoints by trying each endpoint until a connection is successfully established. @@ -589,16 +590,16 @@ public: The algorithm, known as a <em>composed operation</em>, is implemented in terms of calls to the underlying socket's `connect` function. - + @param endpoints A sequence of endpoints. - + @param ec Set to indicate what error occurred, if any. If the sequence is empty, set to `net::error::not_found`. Otherwise, contains the error from the last connection attempt. - + @returns On success, the successfully connected endpoint. Otherwise, a default-constructed endpoint. - */ + */ template<class EndpointSequence #if ! BOOST_BEAST_DOXYGEN ,class = typename std::enable_if< @@ -616,27 +617,27 @@ public: } /** Establishes a connection by trying each endpoint in a sequence. - + This function attempts to connect the stream to one of a sequence of endpoints by trying each endpoint until a connection is successfully established. The underlying socket is automatically opened if needed. An automatically opened socket is not returned to the closed state upon failure. - + The algorithm, known as a <em>composed operation</em>, is implemented in terms of calls to the underlying socket's `connect` function. - + @param begin An iterator pointing to the start of a sequence of endpoints. - + @param end An iterator pointing to the end of a sequence of endpoints. - + @returns An iterator denoting the successfully connected endpoint. - + @throws system_error Thrown on failure. If the sequence is empty, the associated error code is `net::error::not_found`. Otherwise, contains the error from the last connection attempt. - */ + */ template<class Iterator> Iterator connect( @@ -646,25 +647,25 @@ public: } /** Establishes a connection by trying each endpoint in a sequence. - + This function attempts to connect the stream to one of a sequence of endpoints by trying each endpoint until a connection is successfully established. The underlying socket is automatically opened if needed. An automatically opened socket is not returned to the closed state upon failure. - + The algorithm, known as a <em>composed operation</em>, is implemented in terms of calls to the underlying socket's `connect` function. - + @param begin An iterator pointing to the start of a sequence of endpoints. - + @param end An iterator pointing to the end of a sequence of endpoints. - + @param ec Set to indicate what error occurred, if any. If the sequence is empty, set to boost::asio::error::not_found. Otherwise, contains the error from the last connection attempt. - + @returns On success, an iterator denoting the successfully connected endpoint. Otherwise, the end iterator. */ @@ -678,7 +679,7 @@ public: } /** Establishes a connection by trying each endpoint in a sequence. - + This function attempts to connect the stream to one of a sequence of endpoints by trying each endpoint until a connection is successfully established. @@ -688,9 +689,9 @@ public: The algorithm, known as a <em>composed operation</em>, is implemented in terms of calls to the underlying socket's `connect` function. - + @param endpoints A sequence of endpoints. - + @param connect_condition A function object that is called prior to each connection attempt. The signature of the function object must be: @code @@ -703,9 +704,9 @@ public: indicate success. The @c next parameter is the next endpoint to be tried. The function object should return true if the next endpoint should be tried, and false if it should be skipped. - + @returns The successfully connected endpoint. - + @throws boost::system::system_error Thrown on failure. If the sequence is empty, the associated error code is `net::error::not_found`. Otherwise, contains the error from the last connection attempt. @@ -779,7 +780,7 @@ public: } /** Establishes a connection by trying each endpoint in a sequence. - + This function attempts to connect the stream to one of a sequence of endpoints by trying each endpoint until a connection is successfully established. @@ -789,11 +790,11 @@ public: The algorithm, known as a <em>composed operation</em>, is implemented in terms of calls to the underlying socket's `connect` function. - + @param begin An iterator pointing to the start of a sequence of endpoints. - + @param end An iterator pointing to the end of a sequence of endpoints. - + @param connect_condition A function object that is called prior to each connection attempt. The signature of the function object must be: @code @@ -806,13 +807,13 @@ public: indicate success. The @c next parameter is the next endpoint to be tried. The function object should return true if the next endpoint should be tried, and false if it should be skipped. - + @returns An iterator denoting the successfully connected endpoint. - + @throws boost::system::system_error Thrown on failure. If the sequence is empty, the associated @c error_code is `net::error::not_found`. Otherwise, contains the error from the last connection attempt. - */ + */ template< class Iterator, class ConnectCondition> Iterator @@ -824,7 +825,7 @@ public: } /** Establishes a connection by trying each endpoint in a sequence. - + This function attempts to connect the stream to one of a sequence of endpoints by trying each endpoint until a connection is successfully established. @@ -834,11 +835,11 @@ public: The algorithm, known as a <em>composed operation</em>, is implemented in terms of calls to the underlying socket's `connect` function. - + @param begin An iterator pointing to the start of a sequence of endpoints. - + @param end An iterator pointing to the end of a sequence of endpoints. - + @param connect_condition A function object that is called prior to each connection attempt. The signature of the function object must be: @code @@ -851,11 +852,11 @@ public: indicate success. The @c next parameter is the next endpoint to be tried. The function object should return true if the next endpoint should be tried, and false if it should be skipped. - + @param ec Set to indicate what error occurred, if any. If the sequence is empty, set to `net::error::not_found`. Otherwise, contains the error from the last connection attempt. - + @returns On success, an iterator denoting the successfully connected endpoint. Otherwise, the end iterator. */ @@ -885,7 +886,7 @@ public: @param ep The remote endpoint to which the underlying socket will be connected. Copies will be made of the endpoint object as required. - + @param handler The completion handler to invoke when the operation completes. The implementation takes ownership of the handler by performing a decay-copy. The equivalent function signature of @@ -909,7 +910,7 @@ public: ConnectHandler&& handler); /** Establishes a connection by trying each endpoint in a sequence asynchronously. - + This function attempts to connect the stream to one of a sequence of endpoints by trying each endpoint until a connection is successfully established. @@ -924,10 +925,10 @@ public: If the timeout timer expires while the operation is outstanding, the current connection attempt will be canceled and the completion handler will be invoked with the error @ref error::timeout. - + @param endpoints A sequence of endpoints. This this object must meet the requirements of <em>EndpointSequence</em>. - + @param handler The completion handler to invoke when the operation completes. The implementation takes ownership of the handler by performing a decay-copy. The equivalent function signature of @@ -938,7 +939,7 @@ public: // net::error::not_found. Otherwise, contains the // error from the last connection attempt. error_code const& error, - + // On success, the successfully connected endpoint. // Otherwise, a default-constructed endpoint. typename Protocol::endpoint const& endpoint @@ -964,7 +965,7 @@ public: RangeConnectHandler&& handler); /** Establishes a connection by trying each endpoint in a sequence asynchronously. - + This function attempts to connect the stream to one of a sequence of endpoints by trying each endpoint until a connection is successfully established. @@ -982,7 +983,7 @@ public: @param endpoints A sequence of endpoints. This this object must meet the requirements of <em>EndpointSequence</em>. - + @param connect_condition A function object that is called prior to each connection attempt. The signature of the function object must be: @code @@ -1006,7 +1007,7 @@ public: // net::error::not_found. Otherwise, contains the // error from the last connection attempt. error_code const& error, - + // On success, the successfully connected endpoint. // Otherwise, a default-constructed endpoint. typename Protocol::endpoint const& endpoint @@ -1052,7 +1053,7 @@ public: RangeConnectHandler&& handler); /** Establishes a connection by trying each endpoint in a sequence asynchronously. - + This function attempts to connect the stream to one of a sequence of endpoints by trying each endpoint until a connection is successfully established. @@ -1067,9 +1068,9 @@ public: If the timeout timer expires while the operation is outstanding, the current connection attempt will be canceled and the completion handler will be invoked with the error @ref error::timeout. - + @param begin An iterator pointing to the start of a sequence of endpoints. - + @param end An iterator pointing to the end of a sequence of endpoints. @param handler The completion handler to invoke when the operation @@ -1082,7 +1083,7 @@ public: // net::error::not_found. Otherwise, contains the // error from the last connection attempt. error_code const& error, - + // On success, an iterator denoting the successfully // connected endpoint. Otherwise, the end iterator. Iterator iterator @@ -1102,7 +1103,7 @@ public: IteratorConnectHandler&& handler); /** Establishes a connection by trying each endpoint in a sequence asynchronously. - + This function attempts to connect the stream to one of a sequence of endpoints by trying each endpoint until a connection is successfully established. @@ -1113,11 +1114,11 @@ public: If the timeout timer expires while the operation is outstanding, the current connection attempt will be canceled and the completion handler will be invoked with the error @ref error::timeout. - + @param begin An iterator pointing to the start of a sequence of endpoints. @param end An iterator pointing to the end of a sequence of endpoints. - + @param connect_condition A function object that is called prior to each connection attempt. The signature of the function object must be: @code @@ -1136,7 +1137,7 @@ public: // net::error::not_found. Otherwise, contains the // error from the last connection attempt. error_code const& error, - + // On success, an iterator denoting the successfully // connected endpoint. Otherwise, the end iterator. Iterator iterator @@ -1162,7 +1163,7 @@ public: /** Read some data. This function is used to read some data from the stream. - + The call blocks until one of the following is true: @li One or more bytes are read from the stream. @@ -1172,11 +1173,11 @@ public: @param buffers The buffers into which the data will be read. If the size of the buffers is zero bytes, the call always returns immediately with no error. - + @returns The number of bytes read. - + @throws system_error Thrown on failure. - + @note The `read_some` operation may not receive all of the requested number of bytes. Consider using the function `net::read` if you need to ensure that the requested amount of data is read before the @@ -1202,11 +1203,11 @@ public: @param buffers The buffers into which the data will be read. If the size of the buffers is zero bytes, the call always returns immediately with no error. - + @param ec Set to indicate what error occurred, if any. @returns The number of bytes read. - + @note The `read_some` operation may not receive all of the requested number of bytes. Consider using the function `net::read` if you need to ensure that the requested amount of data is read before the @@ -1224,7 +1225,7 @@ public: /** Read some data asynchronously. This function is used to asynchronously read data from the stream. - + This call always returns immediately. The asynchronous operation will continue until one of the following conditions is true: @@ -1247,7 +1248,7 @@ public: Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called. - + @param handler The completion handler to invoke when the operation completes. The implementation takes ownership of the handler by performing a decay-copy. The equivalent function signature of @@ -1277,7 +1278,7 @@ public: /** Write some data. This function is used to write some data to the stream. - + The call blocks until one of the following is true: @li One or more bytes are written to the stream. @@ -1289,9 +1290,9 @@ public: with no error. @returns The number of bytes written. - + @throws system_error Thrown on failure. - + @note The `write_some` operation may not transmit all of the requested number of bytes. Consider using the function `net::write` if you need to ensure that the requested amount of data is written before the @@ -1307,7 +1308,7 @@ public: /** Write some data. This function is used to write some data to the stream. - + The call blocks until one of the following is true: @li One or more bytes are written to the stream. @@ -1321,9 +1322,9 @@ public: @param ec Set to indicate what error occurred, if any. @returns The number of bytes written. - + @throws system_error Thrown on failure. - + @note The `write_some` operation may not transmit all of the requested number of bytes. Consider using the function `net::write` if you need to ensure that the requested amount of data is written before the @@ -1341,7 +1342,7 @@ public: /** Write some data asynchronously. This function is used to asynchronously write data to the underlying socket. - + This call always returns immediately. The asynchronous operation will continue until one of the following conditions is true: @@ -1364,7 +1365,7 @@ public: Although the buffers object may be copied as necessary, ownership of the underlying memory blocks is retained by the caller, which must guarantee that they remain valid until the handler is called. - + @param handler The completion handler to invoke when the operation completes. The implementation takes ownership of the handler by performing a decay-copy. The equivalent function signature of diff --git a/boost/beast/core/buffers_cat.hpp b/boost/beast/core/buffers_cat.hpp index 532ea32eef..f13732916b 100644 --- a/boost/beast/core/buffers_cat.hpp +++ b/boost/beast/core/buffers_cat.hpp @@ -19,7 +19,6 @@ namespace boost { namespace beast { /** A buffer sequence representing a concatenation of buffer sequences. - @see buffers_cat */ template<class... Buffers> @@ -29,7 +28,6 @@ class buffers_cat_view public: /** The type of buffer returned when dereferencing an iterator. - If every buffer sequence in the view is a <em>MutableBufferSequence</em>, then `value_type` will be `net::mutable_buffer`. Otherwise, `value_type` will be `net::const_buffer`. @@ -50,7 +48,6 @@ public: buffers_cat_view& operator=(buffers_cat_view const&) = default; /** Constructor - @param buffers The list of buffer sequences to concatenate. Copies of the arguments will be maintained for the lifetime of the concatenated sequence; however, the ownership of the @@ -63,12 +60,12 @@ public: const_iterator begin() const; - /// Returns an iterator to one past the last buffer in the sequence + /// Returns an iterator to one past the last buffer in the sequence const_iterator end() const; }; -/** Concatenate 2 or more buffer sequences. +/** Concatenate 1 or more buffer sequences. This function returns a constant or mutable buffer sequence which, when iterated, efficiently concatenates the input buffer sequences. @@ -76,15 +73,12 @@ public: object does not take ownership of the underlying memory. The application is still responsible for managing the lifetime of the referenced memory. - @param buffers The list of buffer sequences to concatenate. - @return A new buffer sequence that represents the concatenation of the input buffer sequences. This buffer sequence will be a <em>MutableBufferSequence</em> if each of the passed buffer sequences is also a <em>MutableBufferSequence</em>; otherwise the returned buffer sequence will be a <em>ConstBufferSequence</em>. - @see buffers_cat_view */ #if BOOST_BEAST_DOXYGEN @@ -92,15 +86,15 @@ template<class... BufferSequence> buffers_cat_view<BufferSequence...> buffers_cat(BufferSequence const&... buffers) #else -template<class B1, class B2, class... Bn> -buffers_cat_view<B1, B2, Bn...> -buffers_cat(B1 const& b1, B2 const& b2, Bn const&... bn) +template<class B1, class... Bn> +buffers_cat_view<B1, Bn...> +buffers_cat(B1 const& b1, Bn const&... bn) #endif { static_assert( - is_const_buffer_sequence<B1, B2, Bn...>::value, + is_const_buffer_sequence<B1, Bn...>::value, "BufferSequence type requirements not met"); - return buffers_cat_view<B1, B2, Bn...>{b1, b2, bn...}; + return buffers_cat_view<B1, Bn...>{b1, bn...}; } } // beast diff --git a/boost/beast/core/detail/base64.hpp b/boost/beast/core/detail/base64.hpp index 7f91c04777..477fecf2a6 100644 --- a/boost/beast/core/detail/base64.hpp +++ b/boost/beast/core/detail/base64.hpp @@ -12,7 +12,6 @@ #include <boost/beast/core/string.hpp> #include <cctype> -#include <string> #include <utility> namespace boost { @@ -78,26 +77,6 @@ decode(void* dest, char const* src, std::size_t len); } // base64 -BOOST_BEAST_DECL -std::string -base64_encode(std::uint8_t const* data, std::size_t len); - -BOOST_BEAST_DECL -std::string -base64_encode(string_view s); - -template<class = void> -std::string -base64_decode(string_view data) -{ - std::string dest; - dest.resize(base64::decoded_size(data.size())); - auto const result = base64::decode( - &dest[0], data.data(), data.size()); - dest.resize(result.first); - return dest; -} - } // detail } // beast } // boost diff --git a/boost/beast/core/detail/base64.ipp b/boost/beast/core/detail/base64.ipp index 7e11d188b6..4fc3c6771f 100644 --- a/boost/beast/core/detail/base64.ipp +++ b/boost/beast/core/detail/base64.ipp @@ -195,24 +195,6 @@ decode(void* dest, char const* src, std::size_t len) } // base64 -std::string -base64_encode( - std::uint8_t const* data, - std::size_t len) -{ - std::string dest; - dest.resize(base64::encoded_size(len)); - dest.resize(base64::encode(&dest[0], data, len)); - return dest; -} - -std::string -base64_encode(string_view s) -{ - return base64_encode (reinterpret_cast < - std::uint8_t const*> (s.data()), s.size()); -} - } // detail } // beast } // boost diff --git a/boost/beast/core/detail/buffers_range_adaptor.hpp b/boost/beast/core/detail/buffers_range_adaptor.hpp index 2e04d14f6d..e8e5147433 100644 --- a/boost/beast/core/detail/buffers_range_adaptor.hpp +++ b/boost/beast/core/detail/buffers_range_adaptor.hpp @@ -38,13 +38,9 @@ public: buffers_iterator_type<BufferSequence>; iter_type it_{}; - buffers_range_adaptor const* b_ = nullptr; - const_iterator( - buffers_range_adaptor const& b, - iter_type const& it) + const_iterator(iter_type const& it) : it_(it) - , b_(&b) { } @@ -62,7 +58,7 @@ public: bool operator==(const_iterator const& other) const { - return b_ == other.b_ && it_ == other.it_; + return it_ == other.it_; } bool @@ -111,11 +107,6 @@ public: } }; - buffers_range_adaptor( - buffers_range_adaptor const&) = default; - buffers_range_adaptor& operator=( - buffers_range_adaptor const&) = default; - explicit buffers_range_adaptor(BufferSequence const& b) : b_(b) @@ -125,13 +116,13 @@ public: const_iterator begin() const noexcept { - return {*this, net::buffer_sequence_begin(b_)}; + return {net::buffer_sequence_begin(b_)}; } const_iterator end() const noexcept { - return {*this, net::buffer_sequence_end(b_)}; + return {net::buffer_sequence_end(b_)}; } }; diff --git a/boost/beast/core/detail/char_buffer.hpp b/boost/beast/core/detail/char_buffer.hpp new file mode 100644 index 0000000000..b1970ebc0a --- /dev/null +++ b/boost/beast/core/detail/char_buffer.hpp @@ -0,0 +1,78 @@ +// +// Copyright (c) 2019 Damian Jarek(damian.jarek93@gmail.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_CORE_DETAIL_CHAR_BUFFER_HPP +#define BOOST_BEAST_CORE_DETAIL_CHAR_BUFFER_HPP + +#include <boost/config.hpp> +#include <cstddef> +#include <cstring> +#include <cstdint> + +namespace boost { +namespace beast { +namespace detail { + +template <std::size_t N> +class char_buffer +{ +public: + bool try_push_back(char c) + { + if (size_ == N) + return false; + buf_[size_++] = c; + return true; + } + + bool try_append(char const* first, char const* last) + { + std::size_t const n = last - first; + if (n > N - size_) + return false; + std::memmove(&buf_[size_], first, n); + size_ += n; + return true; + } + + void clear() noexcept + { + size_ = 0; + } + + char* data() noexcept + { + return buf_; + } + + char const* data() const noexcept + { + return buf_; + } + + std::size_t size() const noexcept + { + return size_; + } + + bool empty() const noexcept + { + return size_ == 0; + } + +private: + std::size_t size_= 0; + char buf_[N]; +}; + +} // detail +} // beast +} // boost + +#endif diff --git a/boost/beast/core/detail/impl/read.hpp b/boost/beast/core/detail/impl/read.hpp index 137384aa40..3724979272 100644 --- a/boost/beast/core/detail/impl/read.hpp +++ b/boost/beast/core/detail/impl/read.hpp @@ -13,6 +13,7 @@ #include <boost/beast/core/bind_handler.hpp> #include <boost/beast/core/async_base.hpp> #include <boost/beast/core/flat_static_buffer.hpp> +#include <boost/beast/core/read_size.hpp> #include <boost/asio/basic_stream_socket.hpp> #include <boost/asio/coroutine.hpp> #include <boost/throw_exception.hpp> @@ -37,7 +38,7 @@ template< class Condition, class Handler> class read_op - : public net::coroutine + : public asio::coroutine , public async_base< Handler, beast::executor_type<Stream>> { @@ -73,18 +74,12 @@ public: std::size_t bytes_transferred, bool cont = true) { - std::size_t max_size; std::size_t max_prepare; BOOST_ASIO_CORO_REENTER(*this) { for(;;) { - max_size = cond_(ec, total_, b_); - max_prepare = std::min<std::size_t>( - std::max<std::size_t>( - 512, b_.capacity() - b_.size()), - std::min<std::size_t>( - max_size, b_.max_size() - b_.size())); + max_prepare = beast::read_size(b_, cond_(ec, total_, b_)); if(max_prepare == 0) break; BOOST_ASIO_CORO_YIELD @@ -201,16 +196,10 @@ read( "CompletionCondition type requirements not met"); ec = {}; std::size_t total = 0; - std::size_t max_size; std::size_t max_prepare; for(;;) { - max_size = cond(ec, total, buffer); - max_prepare = std::min<std::size_t>( - std::max<std::size_t>( - 512, buffer.capacity() - buffer.size()), - std::min<std::size_t>( - max_size, buffer.max_size() - buffer.size())); + max_prepare = beast::read_size(buffer, cond(ec, total, buffer)); if(max_prepare == 0) break; std::size_t const bytes_transferred = diff --git a/boost/beast/core/detail/impl/temporary_buffer.ipp b/boost/beast/core/detail/impl/temporary_buffer.ipp new file mode 100644 index 0000000000..932e847371 --- /dev/null +++ b/boost/beast/core/detail/impl/temporary_buffer.ipp @@ -0,0 +1,69 @@ +// +// Copyright (c) 2019 Damian Jarek(damian.jarek93@gmail.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_DETAIL_IMPL_TEMPORARY_BUFFER_IPP +#define BOOST_BEAST_DETAIL_IMPL_TEMPORARY_BUFFER_IPP + +#include <boost/beast/core/detail/temporary_buffer.hpp> +#include <boost/beast/core/detail/clamp.hpp> +#include <boost/core/exchange.hpp> +#include <boost/assert.hpp> +#include <memory> +#include <cstring> + +namespace boost { +namespace beast { +namespace detail { + +void +temporary_buffer:: +append(string_view s) +{ + grow(s.size()); + unchecked_append(s); +} + +void +temporary_buffer:: +append(string_view s1, string_view s2) +{ + grow(s1.size() + s2.size()); + unchecked_append(s1); + unchecked_append(s2); +} + +void +temporary_buffer:: +unchecked_append(string_view s) +{ + auto n = s.size(); + std::memcpy(&data_[size_], s.data(), n); + size_ += n; +} + +void +temporary_buffer:: +grow(std::size_t n) +{ + if (capacity_ - size_ >= n) + return; + + auto const capacity = (n + size_) * 2u; + BOOST_ASSERT(! detail::sum_exceeds( + n, size_, capacity)); + char* const p = new char[capacity]; + std::memcpy(p, data_, size_); + deallocate(boost::exchange(data_, p)); + capacity_ = capacity; +} +} // detail +} // beast +} // boost + +#endif diff --git a/boost/beast/core/detail/ostream.hpp b/boost/beast/core/detail/ostream.hpp index 65da560179..8785c2e6d8 100644 --- a/boost/beast/core/detail/ostream.hpp +++ b/boost/beast/core/detail/ostream.hpp @@ -12,7 +12,6 @@ #include <boost/beast/core/buffers_prefix.hpp> #include <boost/beast/core/buffers_range.hpp> -#include <boost/beast/core/detail/type_traits.hpp> #include <boost/throw_exception.hpp> #include <boost/asio/buffer.hpp> #include <memory> diff --git a/boost/beast/core/detail/remap_post_to_defer.hpp b/boost/beast/core/detail/remap_post_to_defer.hpp index 77f7d8ab20..850a833b52 100644 --- a/boost/beast/core/detail/remap_post_to_defer.hpp +++ b/boost/beast/core/detail/remap_post_to_defer.hpp @@ -10,7 +10,6 @@ #ifndef BOOST_BEAST_DETAIL_REMAP_POST_TO_DEFER_HPP #define BOOST_BEAST_DETAIL_REMAP_POST_TO_DEFER_HPP -#include <boost/asio/bind_executor.hpp> #include <boost/asio/is_executor.hpp> #include <boost/core/empty_value.hpp> #include <type_traits> diff --git a/boost/beast/core/detail/service_base.hpp b/boost/beast/core/detail/service_base.hpp index adec09bbf1..1efe121516 100644 --- a/boost/beast/core/detail/service_base.hpp +++ b/boost/beast/core/detail/service_base.hpp @@ -17,14 +17,9 @@ namespace beast { namespace detail { template<class T> -struct service_id : net::execution_context::id -{ -}; - -template<class T> struct service_base : net::execution_context::service { - static service_id<T> id; + static net::execution_context::id const id; explicit service_base(net::execution_context& ctx) @@ -34,7 +29,7 @@ struct service_base : net::execution_context::service }; template<class T> -service_id<T> service_base<T>::id; +net::execution_context::id const service_base<T>::id; } // detail } // beast diff --git a/boost/beast/core/detail/sha1.hpp b/boost/beast/core/detail/sha1.hpp index abcc307407..c4c8d5e3fd 100644 --- a/boost/beast/core/detail/sha1.hpp +++ b/boost/beast/core/detail/sha1.hpp @@ -11,10 +11,7 @@ #define BOOST_BEAST_DETAIL_SHA1_HPP #include <boost/beast/core/detail/config.hpp> - -#include <algorithm> #include <cstdint> -#include <cstring> // Based on https://github.com/vog/sha1 /* diff --git a/boost/beast/core/detail/string.hpp b/boost/beast/core/detail/string.hpp new file mode 100644 index 0000000000..b553c60439 --- /dev/null +++ b/boost/beast/core/detail/string.hpp @@ -0,0 +1,44 @@ +// +// 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_DETAIL_STRING_HPP +#define BOOST_BEAST_DETAIL_STRING_HPP + +#include <boost/beast/core/string_type.hpp> + +namespace boost { +namespace beast { + +namespace detail { + +// Pulling in the UDL directly breaks in some places on MSVC, +// so introduce a namespace for this purprose. +namespace string_literals { + +inline +string_view +operator"" _sv(char const* p, std::size_t n) +{ + return string_view{p, n}; +} + +} // string_literals + +inline +char +ascii_tolower(char c) +{ + return ((static_cast<unsigned>(c) - 65U) < 26) ? + c + 'a' - 'A' : c; +} +} // detail +} // beast +} // boost + +#endif diff --git a/boost/beast/core/detail/temporary_buffer.hpp b/boost/beast/core/detail/temporary_buffer.hpp new file mode 100644 index 0000000000..8285b8f7eb --- /dev/null +++ b/boost/beast/core/detail/temporary_buffer.hpp @@ -0,0 +1,83 @@ +// +// Copyright (c) 2019 Damian Jarek(damian.jarek93@gmail.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_DETAIL_TEMPORARY_BUFFER_HPP +#define BOOST_BEAST_DETAIL_TEMPORARY_BUFFER_HPP + +#include <boost/beast/core/detail/config.hpp> +#include <boost/beast/core/string.hpp> + +#include <memory> + +namespace boost { +namespace beast { +namespace detail { + +struct temporary_buffer +{ + temporary_buffer() = default; + temporary_buffer(temporary_buffer const&) = delete; + temporary_buffer& operator=(temporary_buffer const&) = delete; + + ~temporary_buffer() noexcept + { + deallocate(data_); + } + + BOOST_BEAST_DECL + void + append(string_view s); + + BOOST_BEAST_DECL + void + append(string_view s1, string_view s2); + + string_view + view() const noexcept + { + return {data_, size_}; + } + + bool + empty() const noexcept + { + return size_ == 0; + } + +private: + BOOST_BEAST_DECL + void + unchecked_append(string_view s); + + BOOST_BEAST_DECL + void + grow(std::size_t n); + + void + deallocate(char* data) noexcept + { + if (data != buffer_) + delete[] data; + } + + char buffer_[4096]; + char* data_ = buffer_; + std::size_t capacity_ = sizeof(buffer_); + std::size_t size_ = 0; +}; + +} // detail +} // beast +} // boost + +#ifdef BOOST_BEAST_HEADER_ONLY +#include <boost/beast/core/detail/impl/temporary_buffer.ipp> +#endif + +#endif diff --git a/boost/beast/core/detail/type_traits.hpp b/boost/beast/core/detail/type_traits.hpp index 3d895403b3..e94abbb179 100644 --- a/boost/beast/core/detail/type_traits.hpp +++ b/boost/beast/core/detail/type_traits.hpp @@ -10,36 +10,14 @@ #ifndef BOOST_BEAST_DETAIL_TYPE_TRAITS_HPP #define BOOST_BEAST_DETAIL_TYPE_TRAITS_HPP -#include <boost/beast/core/error.hpp> -#include <boost/beast/core/detail/is_invocable.hpp> -#include <boost/asio/buffer.hpp> -#include <boost/mp11/function.hpp> #include <boost/type_traits/make_void.hpp> -#include <iterator> -#include <tuple> #include <type_traits> -#include <string> -#include <utility> +#include <new> namespace boost { namespace beast { namespace detail { -// variadic min -template<class T> -T constexpr min(T t) -{ - return t; -} - -template<class T, class...Tn> -T constexpr min(T t0, T t1, Tn... tn) -{ - return (t0 < t1) ? - (detail::min)(t0, tn...) : - (detail::min)(t1, tn...); -} - template<class U> std::size_t constexpr max_sizeof() @@ -97,12 +75,6 @@ using aligned_union_t = //------------------------------------------------------------------------------ -template<class T> -void -accept_rv(T){} - -//------------------------------------------------------------------------------ - // for span template<class T, class E, class = void> struct is_contiguous_container: std::false_type {}; @@ -124,6 +96,18 @@ struct is_contiguous_container<T, E, void_t< >::type>>: std::true_type {}; +template <class T, class U> +T launder_cast(U* u) +{ +#if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606 + return std::launder(reinterpret_cast<T>(u)); +#elif defined(BOOST_GCC) && BOOST_GCC_VERSION > 80000 + return __builtin_launder(reinterpret_cast<T>(u)); +#else + return reinterpret_cast<T>(u); +#endif +} + } // detail } // beast } // boost diff --git a/boost/beast/core/detail/variant.hpp b/boost/beast/core/detail/variant.hpp index 94bd4c040c..f6f5b3c60b 100644 --- a/boost/beast/core/detail/variant.hpp +++ b/boost/beast/core/detail/variant.hpp @@ -45,7 +45,7 @@ class variant { using T = mp11::mp_at_c<variant, I::value - 1>; - reinterpret_cast<T&>(self.buf_).~T(); + detail::launder_cast<T*>(&self.buf_)->~T(); } }; @@ -64,7 +64,7 @@ class variant using T = mp11::mp_at_c<variant, I::value - 1>; ::new(&self.buf_) T( - reinterpret_cast<T const&>(other.buf_)); + *detail::launder_cast<T const*>(&other.buf_)); self.i_ = I::value; } }; @@ -83,9 +83,9 @@ class variant { using T = mp11::mp_at_c<variant, I::value - 1>; - ::new(&self.buf_) T( - reinterpret_cast<T&&>(other.buf_)); - reinterpret_cast<T&>(other.buf_).~T(); + ::new(&self.buf_) T(std::move( + *detail::launder_cast<T*>(&other.buf_))); + detail::launder_cast<T*>(&other.buf_)->~T(); self.i_ = I::value; } }; @@ -106,8 +106,8 @@ class variant using T = mp11::mp_at_c<variant, I::value - 1>; return - reinterpret_cast<T const&>(self.buf_) == - reinterpret_cast<T const&>(other.buf_); + *detail::launder_cast<T const*>(&self.buf_) == + *detail::launder_cast<T const*>(&other.buf_); } }; @@ -181,7 +181,7 @@ public: } return *this; } - + variant& operator=(variant const& other) { if(this != &other) @@ -208,7 +208,7 @@ public: get() { BOOST_ASSERT(i_ == I); - return *reinterpret_cast< + return *detail::launder_cast< mp11::mp_at_c<variant, I - 1>*>(&buf_); } @@ -217,7 +217,7 @@ public: get() const { BOOST_ASSERT(i_ == I); - return *reinterpret_cast< + return *detail::launder_cast< mp11::mp_at_c<variant, I - 1> const*>(&buf_); } diff --git a/boost/beast/core/detect_ssl.hpp b/boost/beast/core/detect_ssl.hpp index b7b0550175..9281156819 100644 --- a/boost/beast/core/detect_ssl.hpp +++ b/boost/beast/core/detect_ssl.hpp @@ -430,7 +430,6 @@ async_detect_ssl( // Non-const references need to be passed as pointers, // since we don't want a decay-copy. - return net::async_initiate< CompletionToken, void(error_code, bool)>( @@ -505,7 +504,7 @@ public: AsyncReadStream& stream, DynamicBuffer& buffer) : beast::async_base< - DetectHandler_, + DetectHandler, beast::executor_type<AsyncReadStream>>( std::forward<DetectHandler_>(handler), stream.get_executor()) diff --git a/boost/beast/core/impl/async_base.hpp b/boost/beast/core/impl/async_base.hpp index ec17b1cc1e..8dc8cb29a9 100644 --- a/boost/beast/core/impl/async_base.hpp +++ b/boost/beast/core/impl/async_base.hpp @@ -42,8 +42,9 @@ struct allocate_stable_state final allocate_stable_state>; A a(this->get()); - detail::allocator_traits<A>::destroy(a, this); - detail::allocator_traits<A>::deallocate(a, this, 1); + auto* p = this; + p->~allocate_stable_state(); + a.deallocate(p, 1); } }; @@ -118,33 +119,30 @@ allocate_stable( { using allocator_type = typename stable_async_base< Handler, Executor1, Allocator>::allocator_type; - + using state = detail::allocate_stable_state< + State, allocator_type>; using A = typename detail::allocator_traits< - allocator_type>::template rebind_alloc< - detail::allocate_stable_state< - State, allocator_type>>; + allocator_type>::template rebind_alloc<state>; struct deleter { allocator_type alloc; - detail::allocate_stable_state< - State, allocator_type>* ptr; + state* ptr; ~deleter() { if(ptr) { A a(alloc); - detail::allocator_traits<A>::deallocate(a, ptr, 1); + a.deallocate(ptr, 1); } } }; A a(base.get_allocator()); - deleter d{base.get_allocator(), nullptr}; - d.ptr = detail::allocator_traits<A>::allocate(a, 1); - detail::allocator_traits<A>::construct(a, d.ptr, - d.alloc, std::forward<Args>(args)...); + deleter d{base.get_allocator(), a.allocate(1)}; + ::new(static_cast<void*>(d.ptr)) + state(d.alloc, std::forward<Args>(args)...); d.ptr->next_ = base.list_; base.list_ = d.ptr; return boost::exchange(d.ptr, nullptr)->value; diff --git a/boost/beast/core/impl/basic_stream.hpp b/boost/beast/core/impl/basic_stream.hpp index c871944552..336c09f227 100644 --- a/boost/beast/core/impl/basic_stream.hpp +++ b/boost/beast/core/impl/basic_stream.hpp @@ -13,9 +13,7 @@ #include <boost/beast/core/async_base.hpp> #include <boost/beast/core/buffer_traits.hpp> #include <boost/beast/core/buffers_prefix.hpp> -#include <boost/beast/core/detail/type_traits.hpp> #include <boost/beast/websocket/teardown.hpp> -#include <boost/asio/bind_executor.hpp> #include <boost/asio/coroutine.hpp> #include <boost/assert.hpp> #include <boost/make_shared.hpp> @@ -161,12 +159,21 @@ close() //------------------------------------------------------------------------------ template<class Protocol, class Executor, class RatePolicy> +template<class Executor2> struct basic_stream<Protocol, Executor, RatePolicy>:: timeout_handler { + using executor_type = Executor2; + op_state& state; boost::weak_ptr<impl_type> wp; tick_type tick; + executor_type ex; + + executor_type get_executor() const noexcept + { + return ex; + } void operator()(error_code ec) @@ -212,62 +219,34 @@ class transfer_op using is_read = std::integral_constant<bool, isRead>; op_state& - state(std::true_type) - { - return impl_->read; - } - - op_state& - state(std::false_type) - { - return impl_->write; - } - - op_state& state() { - return state( - std::integral_constant<bool, isRead>{}); - } - - std::size_t - available_bytes(std::true_type) - { - return rate_policy_access:: - available_read_bytes(impl_->policy()); - } - - std::size_t - available_bytes(std::false_type) - { - return rate_policy_access:: - available_write_bytes(impl_->policy()); + if (isRead) + return impl_->read; + else + return impl_->write; } std::size_t available_bytes() { - return available_bytes(is_read{}); - } - - void - transfer_bytes(std::size_t n, std::true_type) - { - rate_policy_access:: - transfer_read_bytes(impl_->policy(), n); - } - - void - transfer_bytes(std::size_t n, std::false_type) - { - rate_policy_access:: - transfer_write_bytes(impl_->policy(), n); + if (isRead) + return rate_policy_access:: + available_read_bytes(impl_->policy()); + else + return rate_policy_access:: + available_write_bytes(impl_->policy()); } void transfer_bytes(std::size_t n) { - transfer_bytes(n, is_read{}); + if (isRead) + rate_policy_access:: + transfer_read_bytes(impl_->policy(), n); + else + rate_policy_access:: + transfer_write_bytes(impl_->policy(), n); } void @@ -329,13 +308,11 @@ public: // if a timeout is active, wait on the timer if(state().timer.expiry() != never()) state().timer.async_wait( - net::bind_executor( - this->get_executor(), - timeout_handler{ - state(), - impl_, - state().tick - })); + timeout_handler<decltype(this->get_executor())>{ + state(), + impl_, + state().tick, + this->get_executor()}); // check rate limit, maybe wait std::size_t amount; @@ -430,12 +407,11 @@ public: { if(state().timer.expiry() != stream_base::never()) impl_->write.timer.async_wait( - net::bind_executor( - this->get_executor(), - timeout_handler{ - state(), - impl_, - state().tick})); + timeout_handler<decltype(this->get_executor())>{ + state(), + impl_, + state().tick, + this->get_executor()}); impl_->socket.async_connect( ep, std::move(*this)); @@ -458,12 +434,11 @@ public: { if(state().timer.expiry() != stream_base::never()) impl_->write.timer.async_wait( - net::bind_executor( - this->get_executor(), - timeout_handler{ - state(), - impl_, - state().tick})); + timeout_handler<decltype(this->get_executor())>{ + state(), + impl_, + state().tick, + this->get_executor()}); net::async_connect(impl_->socket, eps, cond, std::move(*this)); @@ -486,12 +461,11 @@ public: { if(state().timer.expiry() != stream_base::never()) impl_->write.timer.async_wait( - net::bind_executor( - this->get_executor(), - timeout_handler{ - state(), - impl_, - state().tick})); + timeout_handler<decltype(this->get_executor())>{ + state(), + impl_, + state().tick, + this->get_executor()}); net::async_connect(impl_->socket, begin, end, cond, std::move(*this)); diff --git a/boost/beast/core/impl/buffered_read_stream.hpp b/boost/beast/core/impl/buffered_read_stream.hpp index 184881164f..cea0dcb9fa 100644 --- a/boost/beast/core/impl/buffered_read_stream.hpp +++ b/boost/beast/core/impl/buffered_read_stream.hpp @@ -15,7 +15,7 @@ #include <boost/beast/core/error.hpp> #include <boost/beast/core/read_size.hpp> #include <boost/beast/core/stream_traits.hpp> -#include <boost/beast/core/detail/type_traits.hpp> +#include <boost/beast/core/detail/is_invocable.hpp> #include <boost/asio/post.hpp> #include <boost/throw_exception.hpp> diff --git a/boost/beast/core/impl/buffers_adaptor.hpp b/boost/beast/core/impl/buffers_adaptor.hpp index 91caad5463..3eac32f6e0 100644 --- a/boost/beast/core/impl/buffers_adaptor.hpp +++ b/boost/beast/core/impl/buffers_adaptor.hpp @@ -11,7 +11,6 @@ #define BOOST_BEAST_IMPL_BUFFERS_ADAPTOR_HPP #include <boost/beast/core/buffer_traits.hpp> -#include <boost/beast/core/detail/type_traits.hpp> #include <boost/asio/buffer.hpp> #include <boost/config/workaround.hpp> #include <boost/throw_exception.hpp> diff --git a/boost/beast/core/impl/buffers_cat.hpp b/boost/beast/core/impl/buffers_cat.hpp index 255153f2bd..a0506a0b35 100644 --- a/boost/beast/core/impl/buffers_cat.hpp +++ b/boost/beast/core/impl/buffers_cat.hpp @@ -11,7 +11,6 @@ #define BOOST_BEAST_IMPL_BUFFERS_CAT_HPP #include <boost/beast/core/detail/tuple.hpp> -#include <boost/beast/core/detail/type_traits.hpp> #include <boost/beast/core/detail/variant.hpp> #include <boost/asio/buffer.hpp> #include <cstdint> @@ -23,6 +22,34 @@ namespace boost { namespace beast { +template<class Buffer> +class buffers_cat_view<Buffer> +{ + Buffer buffer_; +public: + using value_type = buffers_type<Buffer>; + + using const_iterator = buffers_iterator_type<Buffer>; + + explicit + buffers_cat_view(Buffer const& buffer) + : buffer_(buffer) + { + } + + const_iterator + begin() const + { + return net::buffer_sequence_begin(buffer_); + } + + const_iterator + end() const + { + return net::buffer_sequence_end(buffer_); + } +}; + #if defined(_MSC_VER) && ! defined(__clang__) # define BOOST_BEAST_UNREACHABLE() __assume(false) # define BOOST_BEAST_UNREACHABLE_RETURN(v) __assume(false) diff --git a/boost/beast/core/impl/flat_buffer.hpp b/boost/beast/core/impl/flat_buffer.hpp index f7fd51673d..83d3b4e74b 100644 --- a/boost/beast/core/impl/flat_buffer.hpp +++ b/boost/beast/core/impl/flat_buffer.hpp @@ -403,7 +403,7 @@ copy_from( if(begin_) { BOOST_ASSERT(other.begin_); - std::memcpy(begin_, other.begin_, n); + std::memcpy(begin_, other.in_, n); } } diff --git a/boost/beast/core/impl/flat_stream.hpp b/boost/beast/core/impl/flat_stream.hpp index 2972131198..f99ec02678 100644 --- a/boost/beast/core/impl/flat_stream.hpp +++ b/boost/beast/core/impl/flat_stream.hpp @@ -16,7 +16,6 @@ #include <boost/beast/core/stream_traits.hpp> #include <boost/beast/websocket/teardown.hpp> #include <boost/asio/buffer.hpp> -#include <boost/asio/coroutine.hpp> #include <memory> namespace boost { @@ -30,7 +29,6 @@ template<class Handler> class write_op : public async_base<Handler, beast::executor_type<flat_stream>> - , public net::coroutine { public: template< diff --git a/boost/beast/core/impl/multi_buffer.hpp b/boost/beast/core/impl/multi_buffer.hpp index 643f60ce2b..29a10fa17b 100644 --- a/boost/beast/core/impl/multi_buffer.hpp +++ b/boost/beast/core/impl/multi_buffer.hpp @@ -11,7 +11,6 @@ #define BOOST_BEAST_IMPL_MULTI_BUFFER_HPP #include <boost/beast/core/buffer_traits.hpp> -#include <boost/beast/core/detail/type_traits.hpp> #include <boost/config/workaround.hpp> #include <boost/core/exchange.hpp> #include <boost/assert.hpp> @@ -88,41 +87,6 @@ namespace beast { in_pos_ out_pos_ == 0 out_end_ == 0 */ -//------------------------------------------------------------------------------ - -template<class Allocator> -class basic_multi_buffer<Allocator>::element - : public boost::intrusive::list_base_hook< - boost::intrusive::link_mode< - boost::intrusive::normal_link>> -{ - using size_type = typename - detail::allocator_traits<Allocator>::size_type; - - size_type const size_; - -public: - element(element const&) = delete; - - explicit - element(size_type n) noexcept - : size_(n) - { - } - - size_type - size() const noexcept - { - return size_; - } - - char* - data() const noexcept - { - return const_cast<char*>( - reinterpret_cast<char const*>(this + 1)); - } -}; //------------------------------------------------------------------------------ @@ -487,7 +451,7 @@ template<class Allocator> basic_multi_buffer<Allocator>:: basic_multi_buffer( Allocator const& alloc) noexcept - : boost::empty_value<base_alloc_type>( + : boost::empty_value<Allocator>( boost::empty_init_t(), alloc) , max_(alloc_traits::max_size(this->get())) , out_(list_.end()) @@ -499,8 +463,8 @@ basic_multi_buffer<Allocator>:: basic_multi_buffer( std::size_t limit, Allocator const& alloc) noexcept - : boost::empty_value< - base_alloc_type>(boost::empty_init_t(), alloc) + : boost::empty_value<Allocator>( + boost::empty_init_t(), alloc) , max_(limit) , out_(list_.end()) { @@ -510,7 +474,7 @@ template<class Allocator> basic_multi_buffer<Allocator>:: basic_multi_buffer( basic_multi_buffer&& other) noexcept - : boost::empty_value<base_alloc_type>( + : boost::empty_value<Allocator>( boost::empty_init_t(), std::move(other.get())) , max_(other.max_) , in_size_(boost::exchange(other.in_size_, 0)) @@ -529,9 +493,9 @@ template<class Allocator> basic_multi_buffer<Allocator>:: basic_multi_buffer( basic_multi_buffer&& other, - Allocator const& alloc) - : boost::empty_value< - base_alloc_type>(boost::empty_init_t(), alloc) + Allocator const& alloc) + : boost::empty_value<Allocator>( + boost::empty_init_t(), alloc) , max_(other.max_) { if(this->get() != other.get()) @@ -562,7 +526,7 @@ template<class Allocator> basic_multi_buffer<Allocator>:: basic_multi_buffer( basic_multi_buffer const& other) - : boost::empty_value<base_alloc_type>( + : boost::empty_value<Allocator>( boost::empty_init_t(), alloc_traits:: select_on_container_copy_construction( other.get())) @@ -577,7 +541,7 @@ basic_multi_buffer<Allocator>:: basic_multi_buffer( basic_multi_buffer const& other, Allocator const& alloc) - : boost::empty_value<base_alloc_type>( + : boost::empty_value<Allocator>( boost::empty_init_t(), alloc) , max_(other.max_) , out_(list_.end()) @@ -601,8 +565,8 @@ basic_multi_buffer<Allocator>:: basic_multi_buffer( basic_multi_buffer<OtherAlloc> const& other, allocator_type const& alloc) - : boost::empty_value< - base_alloc_type>(boost::empty_init_t(), alloc) + : boost::empty_value<Allocator>( + boost::empty_init_t(), alloc) , max_(other.max_) , out_(list_.end()) { @@ -1012,10 +976,7 @@ consume(size_type n) noexcept in_pos_ = 0; auto& e = list_.front(); list_.erase(list_.iterator_to(e)); - auto const len = sizeof(e) + e.size(); - e.~element(); - alloc_traits::deallocate(this->get(), - reinterpret_cast<char*>(&e), len); + destroy(e); #if BOOST_BEAST_MULTI_BUFFER_DEBUG_CHECK debug_check(); #endif @@ -1216,10 +1177,14 @@ void basic_multi_buffer<Allocator>:: destroy(element& e) { - auto const len = sizeof(e) + e.size(); + auto a = rebind_type{this->get()}; + auto const n = + (sizeof(element) + e.size() + + sizeof(align_type) - 1) / + sizeof(align_type); e.~element(); - alloc_traits::deallocate(this->get(), - reinterpret_cast<char*>(&e), len); + alloc_traits::deallocate(a, + reinterpret_cast<align_type*>(&e), n); } template<class Allocator> @@ -1231,9 +1196,11 @@ alloc(std::size_t size) -> if(size > alloc_traits::max_size(this->get())) BOOST_THROW_EXCEPTION(std::length_error( "A basic_multi_buffer exceeded the allocator's maximum size")); - return *::new(alloc_traits::allocate( - this->get(), - sizeof(element) + size)) element(size); + auto a = rebind_type{this->get()}; + auto const p = alloc_traits::allocate(a, + (sizeof(element) + size + sizeof(align_type) - 1) / + sizeof(align_type)); + return *(::new(p) element(size)); } template<class Allocator> diff --git a/boost/beast/core/impl/read_size.hpp b/boost/beast/core/impl/read_size.hpp index 1896c014b8..babbcaac11 100644 --- a/boost/beast/core/impl/read_size.hpp +++ b/boost/beast/core/impl/read_size.hpp @@ -46,7 +46,6 @@ read_size(DynamicBuffer& buffer, static_assert( net::is_dynamic_buffer<DynamicBuffer>::value, "DynamicBuffer type requirements not met"); - BOOST_ASSERT(max_size >= 1); auto const size = buffer.size(); auto const limit = buffer.max_size() - size; BOOST_ASSERT(size <= buffer.max_size()); diff --git a/boost/beast/core/impl/static_buffer.hpp b/boost/beast/core/impl/static_buffer.hpp index dee13bfbe5..ae4f53c1b5 100644 --- a/boost/beast/core/impl/static_buffer.hpp +++ b/boost/beast/core/impl/static_buffer.hpp @@ -10,12 +10,7 @@ #ifndef BOOST_BEAST_IMPL_STATIC_BUFFER_HPP #define BOOST_BEAST_IMPL_STATIC_BUFFER_HPP -#include <boost/beast/core/detail/type_traits.hpp> #include <boost/asio/buffer.hpp> -#include <boost/throw_exception.hpp> -#include <algorithm> -#include <cstring> -#include <iterator> #include <stdexcept> namespace boost { diff --git a/boost/beast/core/impl/static_buffer.ipp b/boost/beast/core/impl/static_buffer.ipp index c26ff429b8..b87d704b65 100644 --- a/boost/beast/core/impl/static_buffer.ipp +++ b/boost/beast/core/impl/static_buffer.ipp @@ -11,12 +11,8 @@ #define BOOST_BEAST_IMPL_STATIC_BUFFER_IPP #include <boost/beast/core/static_buffer.hpp> -#include <boost/beast/core/detail/type_traits.hpp> #include <boost/asio/buffer.hpp> #include <boost/throw_exception.hpp> -#include <algorithm> -#include <cstring> -#include <iterator> #include <stdexcept> namespace boost { diff --git a/boost/beast/core/impl/static_string.hpp b/boost/beast/core/impl/static_string.hpp index c668b837fa..2e3e5617ab 100644 --- a/boost/beast/core/impl/static_string.hpp +++ b/boost/beast/core/impl/static_string.hpp @@ -11,7 +11,6 @@ #define BOOST_BEAST_IMPL_STATIC_STRING_HPP #include <boost/beast/core/detail/static_string.hpp> -#include <boost/beast/core/detail/type_traits.hpp> #include <boost/throw_exception.hpp> namespace boost { @@ -559,64 +558,6 @@ assign_char(CharT, std::false_type) -> "max_size() == 0"}); } -namespace detail { - -template<class Integer> -static_string<max_digits(sizeof(Integer))> -to_static_string(Integer x, std::true_type) -{ - if(x == 0) - return {'0'}; - static_string<detail::max_digits( - sizeof(Integer))> s; - if(x < 0) - { - x = -x; - char buf[max_digits(sizeof(x))]; - char* p = buf; - for(;x > 0; x /= 10) - *p++ = "0123456789"[x % 10]; - s.resize(1 + p - buf); - s[0] = '-'; - auto d = &s[1]; - while(p > buf) - *d++ = *--p; - } - else - { - char buf[max_digits(sizeof(x))]; - char* p = buf; - for(;x > 0; x /= 10) - *p++ = "0123456789"[x % 10]; - s.resize(p - buf); - auto d = &s[0]; - while(p > buf) - *d++ = *--p; - } - return s; -} - -template<class Integer> -static_string<max_digits(sizeof(Integer))> -to_static_string(Integer x, std::false_type) -{ - if(x == 0) - return {'0'}; - char buf[max_digits(sizeof(x))]; - char* p = buf; - for(;x > 0; x /= 10) - *p++ = "0123456789"[x % 10]; - static_string<detail::max_digits( - sizeof(Integer))> s; - s.resize(p - buf); - auto d = &s[0]; - while(p > buf) - *d++ = *--p; - return s; -} - -} // detail - template<class Integer, class> static_string<detail::max_digits(sizeof(Integer))> to_static_string(Integer x) diff --git a/boost/beast/core/impl/string.ipp b/boost/beast/core/impl/string.ipp new file mode 100644 index 0000000000..b64ce3f6aa --- /dev/null +++ b/boost/beast/core/impl/string.ipp @@ -0,0 +1,73 @@ +// +// 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_IMPL_STRING_IPP +#define BOOST_BEAST_IMPL_STRING_IPP + +#include <boost/beast/core/string.hpp> +#include <boost/beast/core/detail/string.hpp> + +#include <algorithm> + +namespace boost { +namespace beast { + +bool +iequals( + beast::string_view lhs, + beast::string_view rhs) +{ + auto n = lhs.size(); + if(rhs.size() != n) + return false; + auto p1 = lhs.data(); + auto p2 = rhs.data(); + char a, b; + // fast loop + while(n--) + { + a = *p1++; + b = *p2++; + if(a != b) + goto slow; + } + return true; +slow: + do + { + if( detail::ascii_tolower(a) != + detail::ascii_tolower(b)) + return false; + a = *p1++; + b = *p2++; + } + while(n--); + return true; +} + +bool +iless::operator()( + string_view lhs, + string_view rhs) const +{ + using std::begin; + using std::end; + return std::lexicographical_compare( + begin(lhs), end(lhs), begin(rhs), end(rhs), + [](char c1, char c2) + { + return detail::ascii_tolower(c1) < detail::ascii_tolower(c2); + } + ); +} + +} // beast +} // boost + +#endif diff --git a/boost/beast/core/multi_buffer.hpp b/boost/beast/core/multi_buffer.hpp index 2cf477a83b..837310c004 100644 --- a/boost/beast/core/multi_buffer.hpp +++ b/boost/beast/core/multi_buffer.hpp @@ -15,6 +15,7 @@ #include <boost/asio/buffer.hpp> #include <boost/core/empty_value.hpp> #include <boost/intrusive/list.hpp> +#include <boost/type_traits/type_with_alignment.hpp> #include <iterator> #include <limits> #include <memory> @@ -62,14 +63,13 @@ namespace beast { template<class Allocator> class basic_multi_buffer #if ! BOOST_BEAST_DOXYGEN - : private boost::empty_value< - typename detail::allocator_traits<Allocator>:: - template rebind_alloc<char>> + : private boost::empty_value<Allocator> #endif { - using base_alloc_type = typename - detail::allocator_traits<Allocator>:: - template rebind_alloc<char>; + // Fancy pointers are not supported + static_assert(std::is_pointer<typename + std::allocator_traits<Allocator>::pointer>::value, + "Allocator must use regular pointers"); static bool constexpr default_nothrow = std::is_nothrow_default_constructible<Allocator>::value; @@ -77,19 +77,61 @@ class basic_multi_buffer // Storage for the list of buffers representing the input // and output sequences. The allocation for each element // contains `element` followed by raw storage bytes. - class element; + class element + : public boost::intrusive::list_base_hook< + boost::intrusive::link_mode< + boost::intrusive::normal_link>> + { + using size_type = typename + detail::allocator_traits<Allocator>::size_type; + + size_type const size_; + + public: + element(element const&) = delete; + + explicit + element(size_type n) noexcept + : size_(n) + { + } + + size_type + size() const noexcept + { + return size_; + } + + char* + data() const noexcept + { + return const_cast<char*>( + reinterpret_cast<char const*>(this + 1)); + } + }; template<bool> class readable_bytes; + using size_type = typename + detail::allocator_traits<Allocator>::size_type; + + using align_type = typename + boost::type_with_alignment<alignof(element)>::type; + + using rebind_type = typename + beast::detail::allocator_traits<Allocator>:: + template rebind_alloc<align_type>; + using alloc_traits = - beast::detail::allocator_traits<base_alloc_type>; - using list_type = typename boost::intrusive::make_list<element, - boost::intrusive::constant_time_size<true>>::type; + beast::detail::allocator_traits<rebind_type>; + + using list_type = typename boost::intrusive::make_list< + element, boost::intrusive::constant_time_size<true>>::type; + using iter = typename list_type::iterator; - using const_iter = typename list_type::const_iterator; - using size_type = typename alloc_traits::size_type; + using const_iter = typename list_type::const_iterator; using pocma = typename alloc_traits::propagate_on_container_move_assignment; diff --git a/boost/beast/core/rate_policy.hpp b/boost/beast/core/rate_policy.hpp index 1f8abb9b6a..6375b11811 100644 --- a/boost/beast/core/rate_policy.hpp +++ b/boost/beast/core/rate_policy.hpp @@ -152,7 +152,7 @@ class simple_rate_policy friend class rate_policy_access; static std::size_t constexpr all = - std::numeric_limits<std::size_t>::max(); + (std::numeric_limits<std::size_t>::max)(); std::size_t rd_remain_ = all; std::size_t wr_remain_ = all; diff --git a/boost/beast/core/span.hpp b/boost/beast/core/span.hpp index e170729472..55a1454efd 100644 --- a/boost/beast/core/span.hpp +++ b/boost/beast/core/span.hpp @@ -186,21 +186,21 @@ public: { return data_; } - + /// Returns an iterator to the beginning of the span const_iterator cbegin() const { return data_; } - + /// Returns an iterator to one past the end of the span const_iterator end() const { return data_ + size_; } - + /// Returns an iterator to one past the end of the span const_iterator cend() const diff --git a/boost/beast/core/static_buffer.hpp b/boost/beast/core/static_buffer.hpp index 1e44237164..c4ff534f56 100644 --- a/boost/beast/core/static_buffer.hpp +++ b/boost/beast/core/static_buffer.hpp @@ -13,11 +13,7 @@ #include <boost/beast/core/detail/config.hpp> #include <boost/beast/core/detail/buffers_pair.hpp> #include <boost/asio/buffer.hpp> -#include <boost/assert.hpp> -#include <algorithm> -#include <array> #include <cstddef> -#include <cstring> namespace boost { namespace beast { @@ -134,7 +130,7 @@ public: BOOST_BEAST_DECL const_buffers_type data() const noexcept; - + /// Returns a constant buffer sequence representing the readable bytes const_buffers_type cdata() const noexcept @@ -148,7 +144,7 @@ public: data() noexcept; /** Returns a mutable buffer sequence representing writable bytes. - + Returns a mutable buffer sequence representing the writable bytes containing exactly `n` bytes of storage. Memory may be reallocated as needed. diff --git a/boost/beast/core/static_string.hpp b/boost/beast/core/static_string.hpp index fc60a72e7d..c1cea6c36e 100644 --- a/boost/beast/core/static_string.hpp +++ b/boost/beast/core/static_string.hpp @@ -16,8 +16,7 @@ #include <algorithm> #include <cstdint> #include <initializer_list> -#include <iterator> -#include <ostream> +#include <iosfwd> #include <stdexcept> #include <string> #include <type_traits> diff --git a/boost/beast/core/string.hpp b/boost/beast/core/string.hpp index 976bfca48a..06edca1969 100644 --- a/boost/beast/core/string.hpp +++ b/boost/beast/core/string.hpp @@ -11,82 +11,11 @@ #define BOOST_BEAST_STRING_HPP #include <boost/beast/core/detail/config.hpp> -#include <boost/version.hpp> - -#if defined(BOOST_BEAST_USE_STD_STRING_VIEW) -#include <string_view> -#else -#include <boost/utility/string_view.hpp> -#endif - -#include <algorithm> +#include <boost/beast/core/string_type.hpp> namespace boost { namespace beast { -#if defined(BOOST_BEAST_USE_STD_STRING_VIEW) - /// The type of string view used by the library - using string_view = std::string_view; - - /// The type of basic string view used by the library - template<class CharT, class Traits> - using basic_string_view = - std::basic_string_view<CharT, Traits>; -#else - /// The type of string view used by the library - using string_view = boost::string_view; - - /// The type of basic string view used by the library - template<class CharT, class Traits> - using basic_string_view = - boost::basic_string_view<CharT, Traits>; -#endif - -namespace detail { - -inline -char -ascii_tolower(char c) -{ - return ((static_cast<unsigned>(c) - 65U) < 26) ? - c + 'a' - 'A' : c; -} - -template<class = void> -bool -iequals( - beast::string_view lhs, - beast::string_view rhs) -{ - auto n = lhs.size(); - if(rhs.size() != n) - return false; - auto p1 = lhs.data(); - auto p2 = rhs.data(); - char a, b; - // fast loop - while(n--) - { - a = *p1++; - b = *p2++; - if(a != b) - goto slow; - } - return true; -slow: - do - { - if(ascii_tolower(a) != ascii_tolower(b)) - return false; - a = *p1++; - b = *p2++; - } - while(n--); - return true; -} - -} // detail - /** Returns `true` if two strings are equal, using a case-insensitive comparison. The case-comparison operation is defined only for low-ASCII characters. @@ -95,14 +24,11 @@ slow: @param rhs The string on the right side of the equality */ -inline +BOOST_BEAST_DECL bool iequals( beast::string_view lhs, - beast::string_view rhs) -{ - return detail::iequals(lhs, rhs); -} + beast::string_view rhs); /** A case-insensitive less predicate for strings. @@ -110,21 +36,11 @@ iequals( */ struct iless { + BOOST_BEAST_DECL bool operator()( string_view lhs, - string_view rhs) const - { - using std::begin; - using std::end; - return std::lexicographical_compare( - begin(lhs), end(lhs), begin(rhs), end(rhs), - [](char c1, char c2) - { - return detail::ascii_tolower(c1) < detail::ascii_tolower(c2); - } - ); - } + string_view rhs) const; }; /** A case-insensitive equality predicate for strings. @@ -145,4 +61,8 @@ struct iequal } // beast } // boost +#ifdef BOOST_BEAST_HEADER_ONLY +#include <boost/beast/core/impl/string.ipp> +#endif + #endif diff --git a/boost/beast/core/string_param.hpp b/boost/beast/core/string_param.hpp index 67ef69469c..cc55bfd170 100644 --- a/boost/beast/core/string_param.hpp +++ b/boost/beast/core/string_param.hpp @@ -14,7 +14,6 @@ #include <boost/beast/core/string.hpp> #include <boost/beast/core/static_string.hpp> #include <boost/beast/core/detail/static_ostream.hpp> -#include <boost/beast/core/detail/type_traits.hpp> #include <boost/optional.hpp> namespace boost { diff --git a/boost/beast/core/string_type.hpp b/boost/beast/core/string_type.hpp new file mode 100644 index 0000000000..b6b3f00534 --- /dev/null +++ b/boost/beast/core/string_type.hpp @@ -0,0 +1,45 @@ +// +// 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_STRING_TYPE_HPP +#define BOOST_BEAST_STRING_TYPE_HPP + +#include <boost/beast/core/detail/config.hpp> + +#if defined(BOOST_BEAST_USE_STD_STRING_VIEW) +#include <string_view> +#else +#include <boost/utility/string_view.hpp> +#endif + +namespace boost { +namespace beast { + +#if BOOST_BEAST_DOXYGEN || ! defined(BOOST_BEAST_USE_STD_STRING_VIEW) +/// The type of string view used by the library +using string_view = boost::string_view; + +/// The type of `basic_string_view` used by the library +template<class CharT, class Traits> +using basic_string_view = + boost::basic_string_view<CharT, Traits>; + +#else +using string_view = std::string_view; + +template<class CharT, class Traits> +using basic_string_view = + std::basic_string_view<CharT, Traits>; + +#endif + +} // beast +} // boost + +#endif diff --git a/boost/beast/http/basic_dynamic_body.hpp b/boost/beast/http/basic_dynamic_body.hpp index 3fea37379b..f49c50daf8 100644 --- a/boost/beast/http/basic_dynamic_body.hpp +++ b/boost/beast/http/basic_dynamic_body.hpp @@ -13,6 +13,7 @@ #include <boost/beast/core/detail/config.hpp> #include <boost/beast/core/buffer_traits.hpp> #include <boost/beast/core/detail/buffer.hpp> +#include <boost/beast/core/detail/clamp.hpp> #include <boost/beast/http/error.hpp> #include <boost/beast/http/message.hpp> #include <boost/optional.hpp> @@ -89,7 +90,7 @@ struct basic_dynamic_body error_code& ec) { auto const n = buffer_bytes(buffers); - if(body_.size() > body_.max_size() - n) + if(beast::detail::sum_exceeds(body_.size(), n, body_.max_size())) { ec = error::buffer_overflow; return 0; diff --git a/boost/beast/http/detail/basic_parser.hpp b/boost/beast/http/detail/basic_parser.hpp index f4e9083ffa..196d1c0a28 100644 --- a/boost/beast/http/detail/basic_parser.hpp +++ b/boost/beast/http/detail/basic_parser.hpp @@ -10,8 +10,8 @@ #ifndef BOOST_BEAST_HTTP_DETAIL_BASIC_PARSER_HPP #define BOOST_BEAST_HTTP_DETAIL_BASIC_PARSER_HPP -#include <boost/beast/core/static_string.hpp> #include <boost/beast/core/string.hpp> +#include <boost/beast/core/detail/char_buffer.hpp> #include <boost/beast/http/error.hpp> #include <boost/beast/http/detail/rfc7230.hpp> #include <boost/config.hpp> @@ -127,7 +127,7 @@ struct basic_parser_base BOOST_BEAST_DECL static bool - parse_dec(char const* it, char const* last, std::uint64_t& v); + parse_dec(string_view s, std::uint64_t& v); BOOST_BEAST_DECL static @@ -182,7 +182,7 @@ struct basic_parser_base char const* last, string_view& name, string_view& value, - static_string<max_obs_fold>& buf, + beast::detail::char_buffer<max_obs_fold>& buf, error_code& ec); BOOST_BEAST_DECL diff --git a/boost/beast/http/detail/basic_parser.ipp b/boost/beast/http/detail/basic_parser.ipp index 934d0dc505..5dd13d4ce1 100644 --- a/boost/beast/http/detail/basic_parser.ipp +++ b/boost/beast/http/detail/basic_parser.ipp @@ -154,8 +154,12 @@ find_eol( bool basic_parser_base:: -parse_dec(char const* it, char const* last, std::uint64_t& v) +parse_dec( + string_view s, + std::uint64_t& v) { + char const* it = s.data(); + char const* last = it + s.size(); if(it == last) return false; std::uint64_t tmp = 0; @@ -491,7 +495,7 @@ parse_field( char const* last, string_view& name, string_view& value, - static_string<max_obs_fold>& buf, + beast::detail::char_buffer<max_obs_fold>& buf, error_code& ec) { /* header-field = field-name ":" OWS field-value OWS @@ -607,63 +611,60 @@ parse_field( if(token_last != first) break; } - buf.resize(0); - buf.append(first, token_last); + buf.clear(); + if (!buf.try_append(first, token_last)) + { + ec = error::header_limit; + return; + } + BOOST_ASSERT(! buf.empty()); -#ifndef BOOST_NO_EXCEPTIONS - try -#endif + for(;;) { - for(;;) + // eat leading ' ' and '\t' + for(;;++p) { - // eat leading ' ' and '\t' - for(;;++p) - { - if(p + 1 > last) - { - ec = error::need_more; - return; - } - if(! (*p == ' ' || *p == '\t')) - break; - } - // parse to CRLF - first = p; - p = parse_token_to_eol(p, last, token_last, ec); - if(ec) - return; - if(! p) - { - ec = error::bad_value; - return; - } - // Look 1 char past the CRLF to handle obs-fold. if(p + 1 > last) { ec = error::need_more; return; } - token_last = trim_back(token_last, first); - if(first != token_last) - { - buf.push_back(' '); - buf.append(first, token_last); - } - if(*p != ' ' && *p != '\t') + if(! (*p == ' ' || *p == '\t')) + break; + } + // parse to CRLF + first = p; + p = parse_token_to_eol(p, last, token_last, ec); + if(ec) + return; + if(! p) + { + ec = error::bad_value; + return; + } + // Look 1 char past the CRLF to handle obs-fold. + if(p + 1 > last) + { + ec = error::need_more; + return; + } + token_last = trim_back(token_last, first); + if(first != token_last) + { + if (!buf.try_push_back(' ') || + !buf.try_append(first, token_last)) { - value = {buf.data(), buf.size()}; + ec = error::header_limit; return; } - ++p; } + if(*p != ' ' && *p != '\t') + { + value = {buf.data(), buf.size()}; + return; + } + ++p; } -#ifndef BOOST_NO_EXCEPTIONS - catch(std::length_error const&) - { - ec = error::header_limit; - return; - } -#endif } diff --git a/boost/beast/http/detail/rfc7230.hpp b/boost/beast/http/detail/rfc7230.hpp index 99f4af05e1..35bed0ab22 100644 --- a/boost/beast/http/detail/rfc7230.hpp +++ b/boost/beast/http/detail/rfc7230.hpp @@ -57,14 +57,6 @@ std::int8_t unhex(char c); BOOST_BEAST_DECL -void -skip_ows(char const*& it, char const* end); - -BOOST_BEAST_DECL -void -skip_token(char const*& it, char const* last); - -BOOST_BEAST_DECL string_view trim(string_view s); diff --git a/boost/beast/http/detail/rfc7230.ipp b/boost/beast/http/detail/rfc7230.ipp index 612eaf9a02..4d69e77241 100644 --- a/boost/beast/http/detail/rfc7230.ipp +++ b/boost/beast/http/detail/rfc7230.ipp @@ -219,8 +219,9 @@ unhex(char c) return tab[static_cast<unsigned char>(c)]; } +template <class ForwardIt> void -skip_ows(char const*& it, char const* end) +skip_ows(ForwardIt& it, ForwardIt end) { while(it != end) { @@ -230,8 +231,9 @@ skip_ows(char const*& it, char const* end) } } +template <class ForwardIt> void -skip_token(char const*& it, char const* last) +skip_token(ForwardIt& it, ForwardIt last) { while(it != last && is_token_char(*it)) ++it; diff --git a/boost/beast/http/fields.hpp b/boost/beast/http/fields.hpp index 927191d755..24b1a12203 100644 --- a/boost/beast/http/fields.hpp +++ b/boost/beast/http/fields.hpp @@ -62,8 +62,6 @@ class basic_fields friend class fields_test; // for `header` - static std::size_t constexpr max_static_buffer = 4096; - struct element; using off_t = std::uint16_t; @@ -72,7 +70,7 @@ public: /// The type of allocator used. using allocator_type = Allocator; - /// The type of element used to represent a field + /// The type of element used to represent a field class value_type { friend class basic_fields; @@ -198,7 +196,7 @@ private: using rebind_type = typename beast::detail::allocator_traits<Allocator>:: - template rebind_alloc<element>; + template rebind_alloc<align_type>; using alloc_traits = beast::detail::allocator_traits<rebind_type>; diff --git a/boost/beast/http/impl/basic_parser.ipp b/boost/beast/http/impl/basic_parser.ipp index 99947ae1f2..5cab22a884 100644 --- a/boost/beast/http/impl/basic_parser.ipp +++ b/boost/beast/http/impl/basic_parser.ipp @@ -14,9 +14,9 @@ #include <boost/beast/http/error.hpp> #include <boost/beast/http/rfc7230.hpp> #include <boost/beast/core/buffer_traits.hpp> -#include <boost/beast/core/static_string.hpp> #include <boost/beast/core/detail/clamp.hpp> #include <boost/beast/core/detail/config.hpp> +#include <boost/beast/core/detail/string.hpp> #include <boost/asio/buffer.hpp> #include <algorithm> #include <utility> @@ -405,7 +405,7 @@ parse_fields(char const*& in, string_view name; string_view value; // https://stackoverflow.com/questions/686217/maximum-on-http-header-values - static_string<max_obs_fold> buf; + beast::detail::char_buffer<max_obs_fold> buf; auto p = in; for(;;) { @@ -508,15 +508,16 @@ finish_header(error_code& ec, std::false_type) } else if(f_ & flagContentLength) { - if(len_ > body_limit_) - { - ec = error::body_limit; - return; - } if(len_ > 0) { f_ |= flagHasBody; state_ = state::body0; + + if(len_ > body_limit_) + { + ec = error::body_limit; + return; + } } else { @@ -746,6 +747,7 @@ basic_parser<isRequest>:: do_field(field f, string_view value, error_code& ec) { + using namespace beast::detail::string_literals; // Connection if(f == field::connection || f == field::proxy_connection) @@ -759,19 +761,19 @@ do_field(field f, } for(auto const& s : list) { - if(iequals({"close", 5}, s)) + if(beast::iequals("close"_sv, s)) { f_ |= flagConnectionClose; continue; } - if(iequals({"keep-alive", 10}, s)) + if(beast::iequals("keep-alive"_sv, s)) { f_ |= flagConnectionKeepAlive; continue; } - if(iequals({"upgrade", 7}, s)) + if(beast::iequals("upgrade"_sv, s)) { f_ |= flagConnectionUpgrade; continue; @@ -799,8 +801,7 @@ do_field(field f, } std::uint64_t v; - if(! parse_dec( - value.begin(), value.end(), v)) + if(! parse_dec(value, v)) { ec = error::bad_content_length; return; @@ -833,9 +834,9 @@ do_field(field f, ec = {}; auto const v = token_list{value}; auto const p = std::find_if(v.begin(), v.end(), - [&](typename token_list::value_type const& s) + [&](string_view const& s) { - return iequals({"chunked", 7}, s); + return beast::iequals("chunked"_sv, s); }); if(p == v.end()) return; diff --git a/boost/beast/http/impl/fields.hpp b/boost/beast/http/impl/fields.hpp index 9616af829c..2711df38b4 100644 --- a/boost/beast/http/impl/fields.hpp +++ b/boost/beast/http/impl/fields.hpp @@ -12,9 +12,9 @@ #include <boost/beast/core/buffers_cat.hpp> #include <boost/beast/core/string.hpp> -#include <boost/beast/core/static_string.hpp> #include <boost/beast/core/detail/buffers_ref.hpp> #include <boost/beast/core/detail/clamp.hpp> +#include <boost/beast/core/detail/temporary_buffer.hpp> #include <boost/beast/http/verb.hpp> #include <boost/beast/http/rfc7230.hpp> #include <boost/beast/http/status.hpp> @@ -24,13 +24,6 @@ #include <stdexcept> #include <string> -#if defined(BOOST_LIBSTDCXX_VERSION) && BOOST_LIBSTDCXX_VERSION < 60000 - // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437 -#ifndef BOOST_BEAST_HTTP_NO_FIELDS_BASIC_STRING_ALLOCATOR -#define BOOST_BEAST_HTTP_NO_FIELDS_BASIC_STRING_ALLOCATOR -#endif -#endif - namespace boost { namespace beast { namespace http { @@ -584,7 +577,7 @@ insert(field name, } auto const last = std::prev(before); // VFALCO is it worth comparing `field name` first? - if(! iequals(sname, last->name_string())) + if(! beast::iequals(sname, last->name_string())) { BOOST_ASSERT(count(sname) == 0); set_.insert_before(before, e); @@ -751,136 +744,31 @@ equal_range(string_view name) const -> namespace detail { -// Filter a token list -// -template<class String, class Pred> -void -filter_token_list( - String& s, - string_view value, - Pred&& pred) +struct iequals_predicate { - token_list te{value}; - auto it = te.begin(); - auto last = te.end(); - if(it == last) - return; - while(pred(*it)) - if(++it == last) - return; - s.append(it->data(), it->size()); - while(++it != last) + bool + operator()(string_view s) const { - if(! pred(*it)) - { - s.append(", "); - s.append(it->data(), it->size()); - } + return beast::iequals(s, sv1) || beast::iequals(s, sv2); } -} + + string_view sv1; + string_view sv2; +}; // Filter the last item in a token list -template<class String, class Pred> +BOOST_BEAST_DECL void filter_token_list_last( - String& s, + beast::detail::temporary_buffer& s, string_view value, - Pred&& pred) -{ - token_list te{value}; - if(te.begin() != te.end()) - { - auto it = te.begin(); - auto next = std::next(it); - if(next == te.end()) - { - if(! pred(*it)) - s.append(it->data(), it->size()); - return; - } - s.append(it->data(), it->size()); - for(;;) - { - it = next; - next = std::next(it); - if(next == te.end()) - { - if(! pred(*it)) - { - s.append(", "); - s.append(it->data(), it->size()); - } - return; - } - s.append(", "); - s.append(it->data(), it->size()); - } - } -} + iequals_predicate const& pred); -template<class String> +BOOST_BEAST_DECL void keep_alive_impl( - String& s, string_view value, - unsigned version, bool keep_alive) -{ - if(version < 11) - { - if(keep_alive) - { - // remove close - filter_token_list(s, value, - [](string_view s) - { - return iequals(s, "close"); - }); - // add keep-alive - if(s.empty()) - s.append("keep-alive"); - else if(! token_list{value}.exists("keep-alive")) - s.append(", keep-alive"); - } - else - { - // remove close and keep-alive - filter_token_list(s, value, - [](string_view s) - { - return - iequals(s, "close") || - iequals(s, "keep-alive"); - }); - } - } - else - { - if(keep_alive) - { - // remove close and keep-alive - filter_token_list(s, value, - [](string_view s) - { - return - iequals(s, "close") || - iequals(s, "keep-alive"); - }); - } - else - { - // remove keep-alive - filter_token_list(s, value, - [](string_view s) - { - return iequals(s, "keep-alive"); - }); - // add close - if(s.empty()) - s.append("close"); - else if(! token_list{value}.exists("close")) - s.append(", close"); - } - } -} + beast::detail::temporary_buffer& s, string_view value, + unsigned version, bool keep_alive); } // detail @@ -930,7 +818,7 @@ get_chunked_impl() const { auto const next = std::next(it); if(next == te.end()) - return iequals(*it, "chunked"); + return beast::iequals(*it, "chunked"); it = next; } return false; @@ -997,6 +885,7 @@ void basic_fields<Allocator>:: set_chunked_impl(bool value) { + beast::detail::temporary_buffer buf; auto it = find(field::transfer_encoding); if(value) { @@ -1012,84 +901,26 @@ set_chunked_impl(bool value) auto const next = std::next(itt); if(next == te.end()) { - if(iequals(*itt, "chunked")) + if(beast::iequals(*itt, "chunked")) return; // already set break; } itt = next; } - static_string<max_static_buffer> buf; - if(! beast::detail::sum_exceeds( - it->value().size(), 9u, buf.max_size())) - { - buf.append(it->value().data(), it->value().size()); - buf.append(", chunked", 9); - set(field::transfer_encoding, buf); - } - else - { - #ifdef BOOST_BEAST_HTTP_NO_FIELDS_BASIC_STRING_ALLOCATOR - // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437 - std::string s; - #else - using A = - typename beast::detail::allocator_traits< - Allocator>::template rebind_alloc<char>; - std::basic_string< - char, - std::char_traits<char>, - A> s{A{this->get()}}; - #endif - s.reserve(it->value().size() + 9); - s.append(it->value().data(), it->value().size()); - s.append(", chunked", 9); - set(field::transfer_encoding, s); - } + + buf.append(it->value(), ", chunked"); + set(field::transfer_encoding, buf.view()); return; } // filter "chunked" if(it == end()) return; -#ifndef BOOST_NO_EXCEPTIONS - try - { - static_string<max_static_buffer> buf; - detail::filter_token_list_last(buf, it->value(), - [](string_view s) - { - return iequals(s, "chunked"); - }); - if(! buf.empty()) - set(field::transfer_encoding, buf); - else - erase(field::transfer_encoding); - } - catch(std::length_error const&) -#endif - { - #ifdef BOOST_BEAST_HTTP_NO_FIELDS_BASIC_STRING_ALLOCATOR - // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437 - std::string s; - #else - using A = - typename beast::detail::allocator_traits< - Allocator>::template rebind_alloc<char>; - std::basic_string< - char, - std::char_traits<char>, - A> s{A{this->get()}}; - #endif - s.reserve(it->value().size()); - detail::filter_token_list_last(s, it->value(), - [](string_view s) - { - return iequals(s, "chunked"); - }); - if(! s.empty()) - set(field::transfer_encoding, s); - else - erase(field::transfer_encoding); - } + + detail::filter_token_list_last(buf, it->value(), {"chunked", {}}); + if(! buf.empty()) + set(field::transfer_encoding, buf.view()); + else + erase(field::transfer_encoding); } template<class Allocator> @@ -1112,40 +943,12 @@ set_keep_alive_impl( { // VFALCO What about Proxy-Connection ? auto const value = (*this)[field::connection]; -#ifndef BOOST_NO_EXCEPTIONS - try - { - static_string<max_static_buffer> buf; - detail::keep_alive_impl( - buf, value, version, keep_alive); - if(buf.empty()) - erase(field::connection); - else - set(field::connection, buf); - } - catch(std::length_error const&) -#endif - { - #ifdef BOOST_BEAST_HTTP_NO_FIELDS_BASIC_STRING_ALLOCATOR - // Workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56437 - std::string s; - #else - using A = - typename beast::detail::allocator_traits< - Allocator>::template rebind_alloc<char>; - std::basic_string< - char, - std::char_traits<char>, - A> s{A{this->get()}}; - #endif - s.reserve(value.size()); - detail::keep_alive_impl( - s, value, version, keep_alive); - if(s.empty()) - erase(field::connection); - else - set(field::connection, s); - } + beast::detail::temporary_buffer buf; + detail::keep_alive_impl(buf, value, version, keep_alive); + if(buf.empty()) + erase(field::connection); + else + set(field::connection, buf.view()); } //------------------------------------------------------------------------------ @@ -1187,8 +990,8 @@ delete_element(element& e) (sizeof(element) + e.off_ + e.len_ + 2 + sizeof(align_type) - 1) / sizeof(align_type); e.~element(); - alloc_traits::deallocate(a, &e, n); - //reinterpret_cast<align_type*>(&e), n); + alloc_traits::deallocate(a, + reinterpret_cast<align_type*>(&e), n); } template<class Allocator> @@ -1198,7 +1001,7 @@ set_element(element& e) { auto it = set_.lower_bound( e.name_string(), key_compare{}); - if(it == set_.end() || ! iequals( + if(it == set_.end() || ! beast::iequals( e.name_string(), it->name_string())) { set_.insert_before(it, e); @@ -1214,7 +1017,7 @@ set_element(element& e) delete_element(*it); it = next; if(it == set_.end() || - ! iequals(e.name_string(), it->name_string())) + ! beast::iequals(e.name_string(), it->name_string())) break; } set_.insert_before(it, e); @@ -1402,4 +1205,8 @@ swap(basic_fields& other, std::false_type) } // beast } // boost +#ifdef BOOST_BEAST_HEADER_ONLY +#include <boost/beast/http/impl/fields.ipp> +#endif + #endif diff --git a/boost/beast/http/impl/fields.ipp b/boost/beast/http/impl/fields.ipp new file mode 100644 index 0000000000..379d0a4d50 --- /dev/null +++ b/boost/beast/http/impl/fields.ipp @@ -0,0 +1,138 @@ +// +// 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_HTTP_IMPL_FIELDS_IPP +#define BOOST_BEAST_HTTP_IMPL_FIELDS_IPP + +#include <boost/beast/http/fields.hpp> + +namespace boost { +namespace beast { +namespace http { +namespace detail { + +// `basic_fields` assumes that `std::size_t` is larger than `uint16_t`, so we +// verify it explicitly here, so that users that use split compilation don't +// need to pay the (fairly small) price for this sanity check +BOOST_STATIC_ASSERT((std::numeric_limits<std::size_t>::max)() >= + (std::numeric_limits<std::uint32_t>::max)()); + +// Filter a token list +// +inline +void +filter_token_list( + beast::detail::temporary_buffer& s, + string_view value, + iequals_predicate const& pred) +{ + token_list te{value}; + auto it = te.begin(); + auto last = te.end(); + if(it == last) + return; + while(pred(*it)) + if(++it == last) + return; + s.append(*it); + while(++it != last) + { + if(! pred(*it)) + { + s.append(", ", *it); + } + } +} + +void +filter_token_list_last( + beast::detail::temporary_buffer& s, + string_view value, + iequals_predicate const& pred) +{ + token_list te{value}; + if(te.begin() != te.end()) + { + auto it = te.begin(); + auto next = std::next(it); + if(next == te.end()) + { + if(! pred(*it)) + s.append(*it); + return; + } + s.append(*it); + for(;;) + { + it = next; + next = std::next(it); + if(next == te.end()) + { + if(! pred(*it)) + { + s.append(", ", *it); + } + return; + } + s.append(", ", *it); + } + } +} + +void +keep_alive_impl( + beast::detail::temporary_buffer& s, string_view value, + unsigned version, bool keep_alive) +{ + if(version < 11) + { + if(keep_alive) + { + // remove close + filter_token_list(s, value, iequals_predicate{"close", {}}); + // add keep-alive + if(s.empty()) + s.append("keep-alive"); + else if(! token_list{value}.exists("keep-alive")) + s.append(", keep-alive"); + } + else + { + // remove close and keep-alive + filter_token_list(s, value, + iequals_predicate{"close", "keep-alive"}); + } + } + else + { + if(keep_alive) + { + // remove close and keep-alive + filter_token_list(s, value, + iequals_predicate{"close", "keep-alive"}); + } + else + { + // remove keep-alive + filter_token_list(s, value, iequals_predicate{"keep-alive", {}}); + // add close + if(s.empty()) + s.append("close"); + else if(! token_list{value}.exists("close")) + s.append(", close"); + } + } +} + +} // detail +} // http +} // beast +} // boost + +#endif // BOOST_BEAST_HTTP_IMPL_FIELDS_IPP diff --git a/boost/beast/http/impl/file_body_win32.hpp b/boost/beast/http/impl/file_body_win32.hpp index fc74c49772..cfeb5aaefd 100644 --- a/boost/beast/http/impl/file_body_win32.hpp +++ b/boost/beast/http/impl/file_body_win32.hpp @@ -16,6 +16,7 @@ #include <boost/beast/core/bind_handler.hpp> #include <boost/beast/core/buffers_range.hpp> #include <boost/beast/core/detail/clamp.hpp> +#include <boost/beast/core/detail/is_invocable.hpp> #include <boost/beast/http/serializer.hpp> #include <boost/asio/async_result.hpp> #include <boost/asio/basic_stream_socket.hpp> diff --git a/boost/beast/http/impl/message.hpp b/boost/beast/http/impl/message.hpp index 805d01f09a..4b101ad3b9 100644 --- a/boost/beast/http/impl/message.hpp +++ b/boost/beast/http/impl/message.hpp @@ -11,7 +11,6 @@ #define BOOST_BEAST_HTTP_IMPL_MESSAGE_HPP #include <boost/beast/core/error.hpp> -#include <boost/beast/core/detail/type_traits.hpp> #include <boost/assert.hpp> #include <boost/throw_exception.hpp> #include <stdexcept> diff --git a/boost/beast/http/impl/read.hpp b/boost/beast/http/impl/read.hpp index faea67eb25..ba265a57ed 100644 --- a/boost/beast/http/impl/read.hpp +++ b/boost/beast/http/impl/read.hpp @@ -62,8 +62,12 @@ parse_until( // caller to distinguish an SSL short read which // represents a safe connection closure, versus // a closure with data loss. - if(parser.got_some() && ! parser.is_done()) + if( ec != net::error::operation_aborted && + parser.got_some() && ! parser.is_done()) + { ec = error::partial_message; + } + return 0; } if(parser.is_done()) @@ -160,7 +164,7 @@ template< class read_msg_op : public beast::stable_async_base< Handler, beast::executor_type<Stream>> - , public net::coroutine + , public asio::coroutine { using parser_type = parser<isRequest, Body, Allocator>; diff --git a/boost/beast/http/impl/rfc7230.hpp b/boost/beast/http/impl/rfc7230.hpp index 11e424b4d1..40e2fff040 100644 --- a/boost/beast/http/impl/rfc7230.hpp +++ b/boost/beast/http/impl/rfc7230.hpp @@ -244,27 +244,6 @@ cend() const -> return const_iterator{s_.end(), s_.end()}; } -template<class T> -auto -ext_list:: -find(T const& s) -> - const_iterator -{ - return std::find_if(begin(), end(), - [&s](value_type const& v) - { - return iequals(s, v.first); - }); -} - -template<class T> -bool -ext_list:: -exists(T const& s) -{ - return find(s) != end(); -} - //------------------------------------------------------------------------------ @@ -378,19 +357,6 @@ cend() const -> return const_iterator{s_.end(), s_.end()}; } -template<class T> -bool -token_list:: -exists(T const& s) -{ - return std::find_if(begin(), end(), - [&s](value_type const& v) - { - return iequals(s, v); - } - ) != end(); -} - template<class Policy> bool validate_list(detail::basic_parsed_list< diff --git a/boost/beast/http/impl/rfc7230.ipp b/boost/beast/http/impl/rfc7230.ipp index cf60cefa36..6b46493ea3 100644 --- a/boost/beast/http/impl/rfc7230.ipp +++ b/boost/beast/http/impl/rfc7230.ipp @@ -11,6 +11,7 @@ #define BOOST_BEAST_HTTP_IMPL_RFC7230_IPP #include <boost/beast/http/rfc7230.hpp> +#include <algorithm> namespace boost { namespace beast { @@ -123,6 +124,24 @@ increment() } } +auto +ext_list:: +find(string_view const& s) -> const_iterator +{ + return std::find_if(begin(), end(), + [&s](value_type const& v) + { + return beast::iequals(s, v.first); + }); +} + +bool +ext_list:: +exists(string_view const& s) +{ + return find(s) != end(); +} + void token_list::const_iterator:: increment() @@ -169,6 +188,18 @@ increment() } } +bool +token_list:: +exists(string_view const& s) +{ + return std::find_if(begin(), end(), + [&s](value_type const& v) + { + return beast::iequals(s, v); + } + ) != end(); +} + } // http } // beast } // boost diff --git a/boost/beast/http/impl/verb.ipp b/boost/beast/http/impl/verb.ipp index 20ef47c551..988f1b9430 100644 --- a/boost/beast/http/impl/verb.ipp +++ b/boost/beast/http/impl/verb.ipp @@ -21,50 +21,51 @@ namespace http { string_view to_string(verb v) { + using namespace beast::detail::string_literals; switch(v) { - case verb::delete_: return "DELETE"; - case verb::get: return "GET"; - case verb::head: return "HEAD"; - case verb::post: return "POST"; - case verb::put: return "PUT"; - case verb::connect: return "CONNECT"; - case verb::options: return "OPTIONS"; - case verb::trace: return "TRACE"; - - case verb::copy: return "COPY"; - case verb::lock: return "LOCK"; - case verb::mkcol: return "MKCOL"; - case verb::move: return "MOVE"; - case verb::propfind: return "PROPFIND"; - case verb::proppatch: return "PROPPATCH"; - case verb::search: return "SEARCH"; - case verb::unlock: return "UNLOCK"; - case verb::bind: return "BIND"; - case verb::rebind: return "REBIND"; - case verb::unbind: return "UNBIND"; - case verb::acl: return "ACL"; - - case verb::report: return "REPORT"; - case verb::mkactivity: return "MKACTIVITY"; - case verb::checkout: return "CHECKOUT"; - case verb::merge: return "MERGE"; - - case verb::msearch: return "M-SEARCH"; - case verb::notify: return "NOTIFY"; - case verb::subscribe: return "SUBSCRIBE"; - case verb::unsubscribe: return "UNSUBSCRIBE"; - - case verb::patch: return "PATCH"; - case verb::purge: return "PURGE"; - - case verb::mkcalendar: return "MKCALENDAR"; - - case verb::link: return "LINK"; - case verb::unlink: return "UNLINK"; - + case verb::delete_: return "DELETE"_sv; + case verb::get: return "GET"_sv; + case verb::head: return "HEAD"_sv; + case verb::post: return "POST"_sv; + case verb::put: return "PUT"_sv; + case verb::connect: return "CONNECT"_sv; + case verb::options: return "OPTIONS"_sv; + case verb::trace: return "TRACE"_sv; + + case verb::copy: return "COPY"_sv; + case verb::lock: return "LOCK"_sv; + case verb::mkcol: return "MKCOL"_sv; + case verb::move: return "MOVE"_sv; + case verb::propfind: return "PROPFIND"_sv; + case verb::proppatch: return "PROPPATCH"_sv; + case verb::search: return "SEARCH"_sv; + case verb::unlock: return "UNLOCK"_sv; + case verb::bind: return "BIND"_sv; + case verb::rebind: return "REBIND"_sv; + case verb::unbind: return "UNBIND"_sv; + case verb::acl: return "ACL"_sv; + + case verb::report: return "REPORT"_sv; + case verb::mkactivity: return "MKACTIVITY"_sv; + case verb::checkout: return "CHECKOUT"_sv; + case verb::merge: return "MERGE"_sv; + + case verb::msearch: return "M-SEARCH"_sv; + case verb::notify: return "NOTIFY"_sv; + case verb::subscribe: return "SUBSCRIBE"_sv; + case verb::unsubscribe: return "UNSUBSCRIBE"_sv; + + case verb::patch: return "PATCH"_sv; + case verb::purge: return "PURGE"_sv; + + case verb::mkcalendar: return "MKCALENDAR"_sv; + + case verb::link: return "LINK"_sv; + case verb::unlink: return "UNLINK"_sv; + case verb::unknown: - return "<unknown>"; + return "<unknown>"_sv; } BOOST_THROW_EXCEPTION(std::invalid_argument{"unknown verb"}); @@ -108,34 +109,20 @@ string_to_verb(string_view v) UNLOCK UNSUBSCRIBE */ + using namespace beast::detail::string_literals; if(v.size() < 3) return verb::unknown; - // s must be null terminated - auto const eq = - [](string_view sv, char const* s) - { - auto p = sv.data(); - for(;;) - { - if(*s != *p) - return false; - ++s; - ++p; - if(! *s) - return p == (sv.data() + sv.size()); - } - }; auto c = v[0]; v.remove_prefix(1); switch(c) { case 'A': - if(v == "CL") + if(v == "CL"_sv) return verb::acl; break; case 'B': - if(v == "IND") + if(v == "IND"_sv) return verb::bind; break; @@ -145,14 +132,14 @@ string_to_verb(string_view v) switch(c) { case 'H': - if(eq(v, "ECKOUT")) + if(v == "ECKOUT"_sv) return verb::checkout; break; case 'O': - if(eq(v, "NNECT")) + if(v == "NNECT"_sv) return verb::connect; - if(eq(v, "PY")) + if(v == "PY"_sv) return verb::copy; BOOST_FALLTHROUGH; @@ -162,24 +149,24 @@ string_to_verb(string_view v) break; case 'D': - if(eq(v, "ELETE")) + if(v == "ELETE"_sv) return verb::delete_; break; case 'G': - if(eq(v, "ET")) + if(v == "ET"_sv) return verb::get; break; case 'H': - if(eq(v, "EAD")) + if(v == "EAD"_sv) return verb::head; break; case 'L': - if(eq(v, "INK")) + if(v == "INK"_sv) return verb::link; - if(eq(v, "OCK")) + if(v == "OCK"_sv) return verb::lock; break; @@ -189,31 +176,31 @@ string_to_verb(string_view v) switch(c) { case '-': - if(eq(v, "SEARCH")) + if(v == "SEARCH"_sv) return verb::msearch; break; case 'E': - if(eq(v, "RGE")) + if(v == "RGE"_sv) return verb::merge; break; case 'K': - if(eq(v, "ACTIVITY")) + if(v == "ACTIVITY"_sv) return verb::mkactivity; if(v[0] == 'C') { v.remove_prefix(1); - if(eq(v, "ALENDAR")) + if(v == "ALENDAR"_sv) return verb::mkcalendar; - if(eq(v, "OL")) + if(v == "OL"_sv) return verb::mkcol; break; } break; - + case 'O': - if(eq(v, "VE")) + if(v == "VE"_sv) return verb::move; BOOST_FALLTHROUGH; @@ -223,12 +210,12 @@ string_to_verb(string_view v) break; case 'N': - if(eq(v, "OTIFY")) + if(v == "OTIFY"_sv) return verb::notify; break; case 'O': - if(eq(v, "PTIONS")) + if(v == "PTIONS"_sv) return verb::options; break; @@ -238,26 +225,26 @@ string_to_verb(string_view v) switch(c) { case 'A': - if(eq(v, "TCH")) + if(v == "TCH"_sv) return verb::patch; break; case 'O': - if(eq(v, "ST")) + if(v == "ST"_sv) return verb::post; break; case 'R': - if(eq(v, "OPFIND")) + if(v == "OPFIND"_sv) return verb::propfind; - if(eq(v, "OPPATCH")) + if(v == "OPPATCH"_sv) return verb::proppatch; break; case 'U': - if(eq(v, "RGE")) + if(v == "RGE"_sv) return verb::purge; - if(eq(v, "T")) + if(v == "T"_sv) return verb::put; BOOST_FALLTHROUGH; @@ -270,21 +257,21 @@ string_to_verb(string_view v) if(v[0] != 'E') break; v.remove_prefix(1); - if(eq(v, "BIND")) + if(v == "BIND"_sv) return verb::rebind; - if(eq(v, "PORT")) + if(v == "PORT"_sv) return verb::report; break; case 'S': - if(eq(v, "EARCH")) + if(v == "EARCH"_sv) return verb::search; - if(eq(v, "UBSCRIBE")) + if(v == "UBSCRIBE"_sv) return verb::subscribe; break; case 'T': - if(eq(v, "RACE")) + if(v == "RACE"_sv) return verb::trace; break; @@ -292,13 +279,13 @@ string_to_verb(string_view v) if(v[0] != 'N') break; v.remove_prefix(1); - if(eq(v, "BIND")) + if(v == "BIND"_sv) return verb::unbind; - if(eq(v, "LINK")) + if(v == "LINK"_sv) return verb::unlink; - if(eq(v, "LOCK")) + if(v == "LOCK"_sv) return verb::unlock; - if(eq(v, "SUBSCRIBE")) + if(v == "SUBSCRIBE"_sv) return verb::unsubscribe; break; diff --git a/boost/beast/http/impl/write.hpp b/boost/beast/http/impl/write.hpp index 5636ce92f8..79b0c83d71 100644 --- a/boost/beast/http/impl/write.hpp +++ b/boost/beast/http/impl/write.hpp @@ -14,8 +14,9 @@ #include <boost/beast/core/async_base.hpp> #include <boost/beast/core/bind_handler.hpp> #include <boost/beast/core/buffers_range.hpp> -#include <boost/beast/core/ostream.hpp> +#include <boost/beast/core/make_printable.hpp> #include <boost/beast/core/stream_traits.hpp> +#include <boost/beast/core/detail/is_invocable.hpp> #include <boost/asio/coroutine.hpp> #include <boost/asio/post.hpp> #include <boost/asio/write.hpp> @@ -159,7 +160,7 @@ template< class write_op : public beast::async_base< Handler, beast::executor_type<Stream>> - , public net::coroutine + , public asio::coroutine { Stream& s_; serializer<isRequest, Body, Fields>& sr_; @@ -262,7 +263,7 @@ struct run_write_some_op { template< class WriteHandler, - class Stream, + class Stream, bool isRequest, class Body, class Fields> void operator()( @@ -903,7 +904,7 @@ operator<<(std::ostream& os, { typename Fields::writer fr{ h, h.version(), h.method()}; - return os << buffers(fr.get()); + return os << beast::make_printable(fr.get()); } template<class Fields> @@ -913,7 +914,7 @@ operator<<(std::ostream& os, { typename Fields::writer fr{ h, h.version(), h.result_int()}; - return os << buffers(fr.get()); + return os << beast::make_printable(fr.get()); } template<bool isRequest, class Body, class Fields> diff --git a/boost/beast/http/rfc7230.hpp b/boost/beast/http/rfc7230.hpp index bc2498db52..c83494e666 100644 --- a/boost/beast/http/rfc7230.hpp +++ b/boost/beast/http/rfc7230.hpp @@ -190,17 +190,17 @@ public: @return An iterator to the matching token, or `end()` if no token exists. */ - template<class T> + BOOST_BEAST_DECL const_iterator - find(T const& s); + find(string_view const& s); /** Return `true` if a token is present in the list. @param s The token to find. A case-insensitive comparison is used. */ - template<class T> + BOOST_BEAST_DECL bool - exists(T const& s); + exists(string_view const& s); }; //------------------------------------------------------------------------------ @@ -275,9 +275,9 @@ public: @param s The token to find. A case-insensitive comparison is used. */ - template<class T> + BOOST_BEAST_DECL bool - exists(T const& s); + exists(string_view const& s); }; /** A list of tokens in a comma separated HTTP field value. diff --git a/boost/beast/http/string_body.hpp b/boost/beast/http/string_body.hpp index 73a01a41fd..aeeefcc440 100644 --- a/boost/beast/http/string_body.hpp +++ b/boost/beast/http/string_body.hpp @@ -16,7 +16,6 @@ #include <boost/beast/http/message.hpp> #include <boost/beast/core/buffers_range.hpp> #include <boost/beast/core/detail/clamp.hpp> -#include <boost/beast/core/detail/type_traits.hpp> #include <boost/asio/buffer.hpp> #include <boost/optional.hpp> #include <cstdint> diff --git a/boost/beast/http/vector_body.hpp b/boost/beast/http/vector_body.hpp index b44ef0f625..c599e162b9 100644 --- a/boost/beast/http/vector_body.hpp +++ b/boost/beast/http/vector_body.hpp @@ -15,7 +15,6 @@ #include <boost/beast/http/error.hpp> #include <boost/beast/http/message.hpp> #include <boost/beast/core/detail/clamp.hpp> -#include <boost/beast/core/detail/type_traits.hpp> #include <boost/asio/buffer.hpp> #include <boost/optional.hpp> #include <cstdint> @@ -39,8 +38,7 @@ template<class T, class Allocator = std::allocator<T>> struct vector_body { private: - static_assert(sizeof(T) == 1 && - std::is_integral<T>::value, + static_assert(sizeof(T) == 1, "T requirements not met"); public: diff --git a/boost/beast/src.hpp b/boost/beast/src.hpp index 87b4ab305f..2376c3fcc2 100644 --- a/boost/beast/src.hpp +++ b/boost/beast/src.hpp @@ -31,6 +31,7 @@ the program, with the macro BOOST_BEAST_SEPARATE_COMPILATION defined. #include <boost/beast/core/detail/base64.ipp> #include <boost/beast/core/detail/sha1.ipp> +#include <boost/beast/core/detail/impl/temporary_buffer.ipp> #include <boost/beast/core/impl/error.ipp> #include <boost/beast/core/impl/file_posix.ipp> #include <boost/beast/core/impl/file_stdio.ipp> @@ -38,17 +39,20 @@ the program, with the macro BOOST_BEAST_SEPARATE_COMPILATION defined. #include <boost/beast/core/impl/flat_static_buffer.ipp> #include <boost/beast/core/impl/saved_handler.ipp> #include <boost/beast/core/impl/static_buffer.ipp> +#include <boost/beast/core/impl/string.ipp> #include <boost/beast/http/detail/basic_parser.ipp> #include <boost/beast/http/detail/rfc7230.ipp> #include <boost/beast/http/impl/basic_parser.ipp> #include <boost/beast/http/impl/error.ipp> #include <boost/beast/http/impl/field.ipp> +#include <boost/beast/http/impl/fields.ipp> #include <boost/beast/http/impl/rfc7230.ipp> #include <boost/beast/http/impl/status.ipp> #include <boost/beast/http/impl/verb.ipp> #include <boost/beast/websocket/detail/hybi13.ipp> +#include <boost/beast/websocket/detail/mask.ipp> #include <boost/beast/websocket/detail/pmd_extension.ipp> #include <boost/beast/websocket/detail/prng.ipp> #include <boost/beast/websocket/detail/service.ipp> diff --git a/boost/beast/ssl/ssl_stream.hpp b/boost/beast/ssl/ssl_stream.hpp index b96dbdda31..cab2463de2 100644 --- a/boost/beast/ssl/ssl_stream.hpp +++ b/boost/beast/ssl/ssl_stream.hpp @@ -655,12 +655,7 @@ public: teardown( boost::beast::role_type role, ssl_stream<SyncStream>& stream, - boost::system::error_code& ec) - { - // Just forward it to the underlying ssl::stream - using boost::beast::websocket::teardown; - teardown(role, *stream.p_, ec); - } + boost::system::error_code& ec); template<class AsyncStream, class TeardownHandler> friend @@ -668,16 +663,37 @@ public: async_teardown( boost::beast::role_type role, ssl_stream<AsyncStream>& stream, - TeardownHandler&& handler) - { - // Just forward it to the underlying ssl::stream - using boost::beast::websocket::async_teardown; - async_teardown(role, *stream.p_, - std::forward<TeardownHandler>(handler)); - } + TeardownHandler&& handler); #endif }; +#if ! BOOST_BEAST_DOXYGEN +template<class SyncStream> +void +teardown( + boost::beast::role_type role, + ssl_stream<SyncStream>& stream, + boost::system::error_code& ec) +{ + // Just forward it to the underlying ssl::stream + using boost::beast::websocket::teardown; + teardown(role, *stream.p_, ec); +} + +template<class AsyncStream, class TeardownHandler> +void +async_teardown( + boost::beast::role_type role, + ssl_stream<AsyncStream>& stream, + TeardownHandler&& handler) +{ + // Just forward it to the underlying ssl::stream + using boost::beast::websocket::async_teardown; + async_teardown(role, *stream.p_, + std::forward<TeardownHandler>(handler)); +} +#endif + } // beast } // boost diff --git a/boost/beast/version.hpp b/boost/beast/version.hpp index b689881bce..02144712eb 100644 --- a/boost/beast/version.hpp +++ b/boost/beast/version.hpp @@ -20,7 +20,7 @@ This is a simple integer that is incremented by one every time a set of code changes is merged to the develop branch. */ -#define BOOST_BEAST_VERSION 248 +#define BOOST_BEAST_VERSION 266 #define BOOST_BEAST_VERSION_STRING "Boost.Beast/" BOOST_STRINGIZE(BOOST_BEAST_VERSION) diff --git a/boost/beast/websocket/detail/decorator.hpp b/boost/beast/websocket/detail/decorator.hpp index cab7f9a298..03c1c8f637 100644 --- a/boost/beast/websocket/detail/decorator.hpp +++ b/boost/beast/websocket/detail/decorator.hpp @@ -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 diff --git a/boost/beast/websocket/detail/frame.hpp b/boost/beast/websocket/detail/frame.hpp index 1603bb556e..f217e04a52 100644 --- a/boost/beast/websocket/detail/frame.hpp +++ b/boost/beast/websocket/detail/frame.hpp @@ -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) { @@ -269,36 +212,29 @@ read_close( ec = error::bad_close_size; return; } - buffers_suffix<Buffers> cb(bs); - { - 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; - } - } - if(n > 0) + + 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)) { - 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; - } + // invalid close code + ec = error::bad_close_code; + return; } - else + + if(n > 2 && !check_utf8( + cr.reason.data(), cr.reason.size())) { - cr.reason = ""; + // not valid utf-8 + ec = error::bad_close_payload; + return; } ec = {}; } diff --git a/boost/beast/websocket/detail/hybi13.ipp b/boost/beast/websocket/detail/hybi13.ipp index b0ed57756b..0cbab15372 100644 --- a/boost/beast/websocket/detail/hybi13.ipp +++ b/boost/beast/websocket/detail/hybi13.ipp @@ -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 @@ -47,11 +41,12 @@ make_sec_ws_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"); + 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()); diff --git a/boost/beast/websocket/detail/mask.hpp b/boost/beast/websocket/detail/mask.hpp index ade89fdae5..58797372e5 100644 --- a/boost/beast/websocket/detail/mask.hpp +++ b/boost/beast/websocket/detail/mask.hpp @@ -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 diff --git a/boost/beast/websocket/detail/mask.ipp b/boost/beast/websocket/detail/mask.ipp new file mode 100644 index 0000000000..6c36d56bc1 --- /dev/null +++ b/boost/beast/websocket/detail/mask.ipp @@ -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 diff --git a/boost/beast/websocket/detail/pmd_extension.ipp b/boost/beast/websocket/detail/pmd_extension.ipp index 790998e8ff..005feec19d 100644 --- a/boost/beast/websocket/detail/pmd_extension.ipp +++ b/boost/beast/websocket/detail/pmd_extension.ipp @@ -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) diff --git a/boost/beast/websocket/detail/prng.hpp b/boost/beast/websocket/detail/prng.hpp index 35409b5837..6eb474f2f0 100644 --- a/boost/beast/websocket/detail/prng.hpp +++ b/boost/beast/websocket/detail/prng.hpp @@ -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 diff --git a/boost/beast/websocket/detail/prng.ipp b/boost/beast/websocket/detail/prng.ipp index 2807ca96e9..2d4e7f2771 100644 --- a/boost/beast/websocket/detail/prng.ipp +++ b/boost/beast/websocket/detail/prng.ipp @@ -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; - } - } + static std::atomic<std::uint32_t> nonce{0}; + return ++nonce; +} - 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())); - } +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()}; +} - void - release(T& t) - { - std::lock_guard< - std::mutex> g(m_); - t.next = head_; - head_ = &t; - } -}; +#ifdef BOOST_NO_CXX11_THREAD_LOCAL -prng::ref -make_prng_no_tls(bool secure) +inline +std::uint32_t +secure_generate() { - class fast_prng final : public prng + struct generator { - 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 + std::uint32_t operator()() { - ++refs_; - return *this; + std::lock_guard<std::mutex> guard{mtx}; + return gen(); } - void - release() noexcept override - { - if(--refs_ == 0) - prng_pool<fast_prng>::instance().release(*this); - } - - value_type - operator()() noexcept override - { - return r_(); - } + beast::detail::chacha<20> gen; + std::mutex mtx; }; - - 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 generator gen{beast::detail::chacha<20>{prng_seed(), make_nonce()}}; + return gen(); } -//------------------------------------------------------------------------------ - -#ifndef BOOST_NO_CXX11_THREAD_LOCAL - -prng::ref -make_prng_tls(bool secure) +inline +std::uint32_t +fast_generate() { - class fast_prng final : public prng + 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; - }()) - { - } - - protected: - prng& - acquire() noexcept override + std::uint32_t operator()() { - return *this; + std::lock_guard<std::mutex> guard{mtx}; + return gen(); } - 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(); +} - 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_(); - } - }; +#else - if(secure) - { - thread_local secure_prng sp; - return prng::ref(sp); - } +inline +std::uint32_t +secure_generate() +{ + thread_local static beast::detail::chacha<20> gen{prng_seed(), make_nonce()}; + return gen(); +} - thread_local fast_prng fp; - return prng::ref(fp); +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 diff --git a/boost/beast/websocket/impl/accept.hpp b/boost/beast/websocket/impl/accept.hpp index 4b989b56c7..1e33d8b40a 100644 --- a/boost/beast/websocket/impl/accept.hpp +++ b/boost/beast/websocket/impl/accept.hpp @@ -21,7 +21,6 @@ #include <boost/beast/core/buffer_traits.hpp> #include <boost/beast/core/stream_traits.hpp> #include <boost/beast/core/detail/buffer.hpp> -#include <boost/beast/core/detail/type_traits.hpp> #include <boost/beast/version.hpp> #include <boost/asio/coroutine.hpp> #include <boost/asio/post.hpp> @@ -80,13 +79,8 @@ build_response( decorator_opt(res); decorator(res); if(! res.count(http::field::server)) - { - // VFALCO this is weird.. - BOOST_STATIC_ASSERT(sizeof( - BOOST_BEAST_VERSION_STRING) < 20); - static_string<20> s(BOOST_BEAST_VERSION_STRING); - res.set(http::field::server, s); - } + res.set(http::field::server, + string_view(BOOST_BEAST_VERSION_STRING)); }; auto err = [&](error e) @@ -172,7 +166,7 @@ template<class Handler> class stream<NextLayer, deflateSupported>::response_op : public beast::stable_async_base< Handler, beast::executor_type<stream>> - , public net::coroutine + , public asio::coroutine { boost::weak_ptr<impl_type> wp_; error_code result_; // must come before res_ @@ -247,7 +241,7 @@ template<class Handler, class Decorator> class stream<NextLayer, deflateSupported>::accept_op : public beast::stable_async_base< Handler, beast::executor_type<stream>> - , public net::coroutine + , public asio::coroutine { boost::weak_ptr<impl_type> wp_; http::request_parser<http::empty_body>& p_; diff --git a/boost/beast/websocket/impl/close.hpp b/boost/beast/websocket/impl/close.hpp index 03078d9232..d59374ccd3 100644 --- a/boost/beast/websocket/impl/close.hpp +++ b/boost/beast/websocket/impl/close.hpp @@ -38,7 +38,7 @@ template<class Handler> class stream<NextLayer, deflateSupported>::close_op : public beast::stable_async_base< Handler, beast::executor_type<stream>> - , public net::coroutine + , public asio::coroutine { boost::weak_ptr<impl_type> wp_; error_code ev_; diff --git a/boost/beast/websocket/impl/handshake.hpp b/boost/beast/websocket/impl/handshake.hpp index 21fba99738..645b1a3a30 100644 --- a/boost/beast/websocket/impl/handshake.hpp +++ b/boost/beast/websocket/impl/handshake.hpp @@ -37,7 +37,7 @@ template<class Handler> class stream<NextLayer, deflateSupported>::handshake_op : public beast::stable_async_base<Handler, beast::executor_type<stream>> - , public net::coroutine + , public asio::coroutine { struct data { diff --git a/boost/beast/websocket/impl/ping.hpp b/boost/beast/websocket/impl/ping.hpp index 350505c081..6f92d7c725 100644 --- a/boost/beast/websocket/impl/ping.hpp +++ b/boost/beast/websocket/impl/ping.hpp @@ -35,7 +35,7 @@ template<class Handler> class stream<NextLayer, deflateSupported>::ping_op : public beast::stable_async_base< Handler, beast::executor_type<stream>> - , public net::coroutine + , public asio::coroutine { boost::weak_ptr<impl_type> wp_; detail::frame_buffer& fb_; @@ -115,7 +115,7 @@ public: template<class NextLayer, bool deflateSupported> template<class Executor> class stream<NextLayer, deflateSupported>::idle_ping_op - : public net::coroutine + : public asio::coroutine , public boost::empty_value<Executor> { boost::weak_ptr<impl_type> wp_; @@ -176,7 +176,8 @@ public: impl.op_idle_ping.emplace(std::move(*this)); impl.wr_block.lock(this); BOOST_ASIO_CORO_YIELD - net::post(this->get(), std::move(*this)); + net::post( + this->get_executor(), std::move(*this)); BOOST_ASSERT(impl.wr_block.is_locked(this)); } if(impl.check_stop_now(ec)) diff --git a/boost/beast/websocket/impl/read.hpp b/boost/beast/websocket/impl/read.hpp index 8be18e5975..86c8940fc7 100644 --- a/boost/beast/websocket/impl/read.hpp +++ b/boost/beast/websocket/impl/read.hpp @@ -48,7 +48,7 @@ template<class Handler, class MutableBufferSequence> class stream<NextLayer, deflateSupported>::read_some_op : public beast::async_base< Handler, beast::executor_type<stream>> - , public net::coroutine + , public asio::coroutine { boost::weak_ptr<impl_type> wp_; MutableBufferSequence bs_; @@ -619,7 +619,7 @@ template<class Handler, class DynamicBuffer> class stream<NextLayer, deflateSupported>::read_op : public beast::async_base< Handler, beast::executor_type<stream>> - , public net::coroutine + , public asio::coroutine { boost::weak_ptr<impl_type> wp_; DynamicBuffer& b_; @@ -664,21 +664,22 @@ public: auto& impl = *sp; using mutable_buffers_type = typename DynamicBuffer::mutable_buffers_type; - boost::optional<mutable_buffers_type> mb; BOOST_ASIO_CORO_REENTER(*this) { do { - mb = beast::detail::dynamic_buffer_prepare(b_, - clamp(impl.read_size_hint_db(b_), limit_), - ec, error::buffer_overflow); - if(impl.check_stop_now(ec)) - goto upcall; - // VFALCO TODO use boost::beast::bind_continuation BOOST_ASIO_CORO_YIELD - read_some_op<read_op, mutable_buffers_type>( - std::move(*this), sp, *mb); + { + auto mb = beast::detail::dynamic_buffer_prepare(b_, + clamp(impl.read_size_hint_db(b_), limit_), + ec, error::buffer_overflow); + if(impl.check_stop_now(ec)) + goto upcall; + read_some_op<read_op, mutable_buffers_type>( + std::move(*this), sp, *mb); + } + b_.commit(bytes_transferred); bytes_written_ += bytes_transferred; if(ec) diff --git a/boost/beast/websocket/impl/stream.hpp b/boost/beast/websocket/impl/stream.hpp index 150748c453..539e255192 100644 --- a/boost/beast/websocket/impl/stream.hpp +++ b/boost/beast/websocket/impl/stream.hpp @@ -25,11 +25,8 @@ #include <boost/beast/core/buffers_suffix.hpp> #include <boost/beast/core/flat_static_buffer.hpp> #include <boost/beast/core/detail/clamp.hpp> -#include <boost/beast/core/detail/type_traits.hpp> -#include <boost/asio/bind_executor.hpp> #include <boost/asio/steady_timer.hpp> #include <boost/assert.hpp> -#include <boost/endian/buffers.hpp> #include <boost/make_shared.hpp> #include <boost/throw_exception.hpp> #include <algorithm> @@ -64,7 +61,7 @@ stream(Args&&... args) template<class NextLayer, bool deflateSupported> auto stream<NextLayer, deflateSupported>:: -get_executor() const noexcept -> +get_executor() noexcept -> executor_type { return impl_->stream().get_executor(); @@ -140,12 +137,7 @@ read_size_hint(DynamicBuffer& buffer) const static_assert( net::is_dynamic_buffer<DynamicBuffer>::value, "DynamicBuffer type requirements not met"); - auto const initial_size = (std::min)( - +tcp_frame_size, - buffer.max_size() - buffer.size()); - if(initial_size == 0) - return 1; // buffer is full - return read_size_hint(initial_size); + return impl_->read_size_hint_db(buffer); } //------------------------------------------------------------------------------ diff --git a/boost/beast/websocket/impl/stream_impl.hpp b/boost/beast/websocket/impl/stream_impl.hpp index ec5557c361..5bcd9c78ab 100644 --- a/boost/beast/websocket/impl/stream_impl.hpp +++ b/boost/beast/websocket/impl/stream_impl.hpp @@ -30,9 +30,7 @@ #include <boost/beast/core/static_buffer.hpp> #include <boost/beast/core/stream_traits.hpp> #include <boost/beast/core/detail/clamp.hpp> -#include <boost/beast/core/detail/type_traits.hpp> #include <boost/beast/version.hpp> -#include <boost/asio/bind_executor.hpp> #include <boost/asio/steady_timer.hpp> #include <boost/core/empty_value.hpp> #include <boost/enable_shared_from_this.hpp> @@ -99,7 +97,8 @@ struct stream<NextLayer, deflateSupported>::impl_type bool wr_cont /* next write is a continuation */ = false; bool wr_frag /* autofrag the current message */ = false; bool wr_frag_opt /* autofrag option setting */ = true; - bool wr_compress /* compress current message */ = false; + bool wr_compress; /* compress current message */ + bool wr_compress_opt /* compress message setting */ = true; detail::opcode wr_opcode /* message type */ = detail::opcode::text; std::unique_ptr< std::uint8_t[]> wr_buf; // write buffer @@ -211,11 +210,14 @@ struct stream<NextLayer, deflateSupported>::impl_type timer.cancel(); } - // Called before each write frame + // Called just before sending + // the first frame of each message void begin_msg() { wr_frag = wr_frag_opt; + wr_compress = + this->pmd_enabled() && wr_compress_opt; // Maintain the write buffer if( this->pmd_enabled() || @@ -234,6 +236,8 @@ struct stream<NextLayer, deflateSupported>::impl_type wr_buf_size = wr_buf_opt; wr_buf.reset(); } + + // } //-------------------------------------------------------------------------- @@ -275,13 +279,6 @@ struct stream<NextLayer, deflateSupported>::impl_type return key; } - std::size_t - read_size_hint(std::size_t initial_size) const - { - return this->read_size_hint_pmd( - initial_size, rd_done, rd_remain, rd_fh); - } - template<class DynamicBuffer> std::size_t read_size_hint_db(DynamicBuffer& buffer) const @@ -291,7 +288,8 @@ struct stream<NextLayer, deflateSupported>::impl_type buffer.max_size() - buffer.size()); if(initial_size == 0) return 1; // buffer is full - return this->read_size_hint(initial_size); + return this->read_size_hint_pmd( + initial_size, rd_done, rd_remain, rd_fh); } template<class DynamicBuffer> @@ -771,10 +769,12 @@ parse_fh( { case 126: { - std::uint8_t tmp[2]; - BOOST_ASSERT(buffer_bytes(cb) >= sizeof(tmp)); - cb.consume(net::buffer_copy(net::buffer(tmp), cb)); - fh.len = detail::big_uint16_to_native(&tmp[0]); + + std::uint16_t len_be; + BOOST_ASSERT(buffer_bytes(cb) >= sizeof(len_be)); + cb.consume(net::buffer_copy( + net::mutable_buffer(&len_be, sizeof(len_be)), cb)); + fh.len = endian::big_to_native(len_be); if(fh.len < 126) { // length not canonical @@ -785,10 +785,11 @@ parse_fh( } case 127: { - std::uint8_t tmp[8]; - BOOST_ASSERT(buffer_bytes(cb) >= sizeof(tmp)); - cb.consume(net::buffer_copy(net::buffer(tmp), cb)); - fh.len = detail::big_uint64_to_native(&tmp[0]); + std::uint64_t len_be; + BOOST_ASSERT(buffer_bytes(cb) >= sizeof(len_be)); + cb.consume(net::buffer_copy( + net::mutable_buffer(&len_be, sizeof(len_be)), cb)); + fh.len = endian::big_to_native(len_be); if(fh.len < 65536) { // length not canonical @@ -800,10 +801,11 @@ parse_fh( } if(fh.mask) { - std::uint8_t tmp[4]; - BOOST_ASSERT(buffer_bytes(cb) >= sizeof(tmp)); - cb.consume(net::buffer_copy(net::buffer(tmp), cb)); - fh.key = detail::little_uint32_to_native(&tmp[0]); + std::uint32_t key_le; + BOOST_ASSERT(buffer_bytes(cb) >= sizeof(key_le)); + cb.consume(net::buffer_copy( + net::mutable_buffer(&key_le, sizeof(key_le)), cb)); + fh.key = endian::little_to_native(key_le); detail::prepare_key(rd_key, fh.key); } else @@ -909,12 +911,10 @@ write_close(DynamicBuffer& db, close_reason const& cr) if(fh.mask) detail::prepare_key(key, fh.key); { - std::uint8_t tmp[2]; - ::new(&tmp[0]) big_uint16_buf_t{ - (std::uint16_t)cr.code}; + auto code_be = endian::native_to_big<std::uint16_t>(cr.code); auto mb = db.prepare(2); net::buffer_copy(mb, - net::buffer(tmp)); + net::const_buffer(&code_be, sizeof(code_be))); if(fh.mask) detail::mask_inplace(mb, key); db.commit(2); diff --git a/boost/beast/websocket/impl/teardown.hpp b/boost/beast/websocket/impl/teardown.hpp index 8e0913762c..2e2f0ad7e3 100644 --- a/boost/beast/websocket/impl/teardown.hpp +++ b/boost/beast/websocket/impl/teardown.hpp @@ -14,7 +14,7 @@ #include <boost/beast/core/bind_handler.hpp> #include <boost/beast/core/stream_traits.hpp> #include <boost/beast/core/detail/bind_continuation.hpp> -#include <boost/beast/core/detail/type_traits.hpp> +#include <boost/beast/core/detail/is_invocable.hpp> #include <boost/asio/coroutine.hpp> #include <boost/asio/post.hpp> #include <memory> @@ -33,7 +33,7 @@ class teardown_tcp_op Handler, beast::executor_type< net::basic_stream_socket< Protocol, Executor>>> - , public net::coroutine + , public asio::coroutine { using socket_type = net::basic_stream_socket<Protocol, Executor>; diff --git a/boost/beast/websocket/impl/write.hpp b/boost/beast/websocket/impl/write.hpp index 318693f512..2a82b677b3 100644 --- a/boost/beast/websocket/impl/write.hpp +++ b/boost/beast/websocket/impl/write.hpp @@ -41,7 +41,7 @@ template<class Handler, class Buffers> class stream<NextLayer, deflateSupported>::write_some_op : public beast::async_base< Handler, beast::executor_type<stream>> - , public net::coroutine + , public asio::coroutine { enum { diff --git a/boost/beast/websocket/option.hpp b/boost/beast/websocket/option.hpp index 62ebfa4a2b..1133c4e1fa 100644 --- a/boost/beast/websocket/option.hpp +++ b/boost/beast/websocket/option.hpp @@ -11,15 +11,6 @@ #define BOOST_BEAST_WEBSOCKET_OPTION_HPP #include <boost/beast/core/detail/config.hpp> -#include <boost/beast/websocket/rfc6455.hpp> -#include <boost/beast/core/detail/type_traits.hpp> -#include <boost/throw_exception.hpp> -#include <algorithm> -#include <cstdint> -#include <functional> -#include <stdexcept> -#include <type_traits> -#include <utility> namespace boost { namespace beast { diff --git a/boost/beast/websocket/stream.hpp b/boost/beast/websocket/stream.hpp index a9d79d2de4..367a54537c 100644 --- a/boost/beast/websocket/stream.hpp +++ b/boost/beast/websocket/stream.hpp @@ -23,7 +23,6 @@ #include <boost/beast/core/role.hpp> #include <boost/beast/core/stream_traits.hpp> #include <boost/beast/core/string.hpp> -#include <boost/beast/core/detail/type_traits.hpp> #include <boost/beast/http/detail/type_traits.hpp> #include <boost/asio/async_result.hpp> #include <boost/asio/error.hpp> @@ -220,7 +219,7 @@ public: @return A copy of the executor that stream will use to dispatch handlers. */ executor_type - get_executor() const noexcept; + get_executor() noexcept; /** Get a reference to the next layer diff --git a/boost/beast/zlib/detail/deflate_stream.hpp b/boost/beast/zlib/detail/deflate_stream.hpp index 74ce6e5a9a..1460dd42dd 100644 --- a/boost/beast/zlib/detail/deflate_stream.hpp +++ b/boost/beast/zlib/detail/deflate_stream.hpp @@ -40,7 +40,6 @@ #include <boost/beast/zlib/error.hpp> #include <boost/beast/zlib/zlib.hpp> #include <boost/beast/zlib/detail/ranges.hpp> -#include <boost/beast/core/detail/type_traits.hpp> #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/optional.hpp> diff --git a/boost/beast/zlib/detail/deflate_stream.ipp b/boost/beast/zlib/detail/deflate_stream.ipp index 4641697c36..5169843362 100644 --- a/boost/beast/zlib/detail/deflate_stream.ipp +++ b/boost/beast/zlib/detail/deflate_stream.ipp @@ -39,7 +39,6 @@ #include <boost/beast/zlib/detail/deflate_stream.hpp> #include <boost/beast/zlib/detail/ranges.hpp> -#include <boost/beast/core/detail/type_traits.hpp> #include <boost/assert.hpp> #include <boost/config.hpp> #include <boost/make_unique.hpp> @@ -623,6 +622,7 @@ init() window_ = reinterpret_cast<Byte*>(buf_.get()); prev_ = reinterpret_cast<std::uint16_t*>(buf_.get() + nwindow); + std::memset(prev_, 0, nprev); head_ = reinterpret_cast<std::uint16_t*>(buf_.get() + nwindow + nprev); /* We overlay pending_buf_ and d_buf_ + l_buf_. This works |