Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-01 08:09:32

0001 //
0002 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/beast
0008 //
0009 
0010 #ifndef BOOST_BEAST_CORE_FLAT_STREAM_HPP
0011 #define BOOST_BEAST_CORE_FLAT_STREAM_HPP
0012 
0013 #include <boost/beast/core/detail/config.hpp>
0014 #include <boost/beast/core/error.hpp>
0015 #include <boost/beast/core/flat_buffer.hpp>
0016 #include <boost/beast/core/stream_traits.hpp>
0017 #include <boost/beast/core/detail/flat_stream.hpp>
0018 #include <boost/asio/async_result.hpp>
0019 #include <cstdlib>
0020 #include <utility>
0021 
0022 namespace boost {
0023 namespace beast {
0024 
0025 /** (Deprecated: This wrapper is no longer needed; Asio linearizes
0026     scatter/gather I/O in ssl::stream.) Stream wrapper to improve write
0027     performance.
0028 
0029     This wrapper flattens writes for buffer sequences having length
0030     greater than 1 and total size below a predefined amount, using
0031     a dynamic memory allocation. It is primarily designed to overcome
0032     a performance limitation of the current version of `net::ssl::stream`,
0033     which does not use OpenSSL's scatter/gather interface for its
0034     low-level read some and write some operations.
0035 
0036     It is normally not necessary to use this class directly if you
0037     are already using @ref ssl_stream. The following examples shows
0038     how to use this class with the ssl stream that comes with
0039     networking:
0040 
0041     @par Example
0042 
0043     To use the @ref flat_stream template with SSL streams, declare
0044     a variable of the correct type. Parameters passed to the constructor
0045     will be forwarded to the next layer's constructor:
0046 
0047     @code
0048         flat_stream<net::ssl::stream<ip::tcp::socket>> fs{ioc, ctx};
0049     @endcode
0050     Alternatively you can write
0051     @code
0052         ssl::stream<ip::tcp::socket> ss{ioc, ctx};
0053         flat_stream<net::ssl::stream<ip::tcp::socket>&> fs{ss};
0054     @endcode
0055 
0056     The resulting stream may be passed to any stream algorithms which
0057     operate on synchronous or asynchronous read or write streams,
0058     examples include:
0059     
0060     @li `net::read`, `net::async_read`
0061 
0062     @li `net::write`, `net::async_write`
0063 
0064     @li `net::read_until`, `net::async_read_until`
0065 
0066     The stream may also be used as a template parameter in other
0067     stream wrappers, such as for websocket:
0068     @code
0069         websocket::stream<flat_stream<net::ssl::stream<ip::tcp::socket>>> ws{ioc, ctx};
0070     @endcode
0071 
0072     @tparam NextLayer The type representing the next layer, to which
0073     data will be read and written during operations. For synchronous
0074     operations, the type must support the @b SyncStream concept. For
0075     asynchronous operations, the type must support the @b AsyncStream
0076     concept. This type will usually be some variation of
0077     `net::ssl::stream`.
0078 
0079     @par Concepts
0080         @li SyncStream
0081         @li AsyncStream
0082 
0083     @see
0084         @li https://github.com/boostorg/asio/issues/100
0085         @li https://github.com/boostorg/beast/issues/1108
0086         @li https://stackoverflow.com/questions/38198638/openssl-ssl-write-from-multiple-buffers-ssl-writev
0087         @li https://stackoverflow.com/questions/50026167/performance-drop-on-port-from-beast-1-0-0-b66-to-boost-1-67-0-beast
0088 */
0089 template<class NextLayer>
0090 class flat_stream
0091 #if ! BOOST_BEAST_DOXYGEN
0092     : private detail::flat_stream_base
0093 #endif
0094 {
0095     NextLayer stream_;
0096     flat_buffer buffer_;
0097 
0098     BOOST_STATIC_ASSERT(has_get_executor<NextLayer>::value);
0099 
0100     struct ops;
0101 
0102     template<class ConstBufferSequence>
0103     std::size_t
0104     stack_write_some(
0105         std::size_t size,
0106         ConstBufferSequence const& buffers,
0107         error_code& ec);
0108 
0109 public:
0110     /// The type of the next layer.
0111     using next_layer_type =
0112         typename std::remove_reference<NextLayer>::type;
0113 
0114     /// The type of the executor associated with the object.
0115     using executor_type = beast::executor_type<next_layer_type>;
0116 
0117     flat_stream(flat_stream&&) = default;
0118     flat_stream(flat_stream const&) = default;
0119     flat_stream& operator=(flat_stream&&) = default;
0120     flat_stream& operator=(flat_stream const&) = default;
0121 
0122     /** Destructor
0123 
0124         The treatment of pending operations will be the same as that
0125         of the next layer.
0126     */
0127     ~flat_stream() = default;
0128 
0129     /** Constructor
0130 
0131         Arguments, if any, are forwarded to the next layer's constructor.
0132     */
0133     template<class... Args>
0134     explicit
0135     flat_stream(Args&&... args);
0136 
0137     //--------------------------------------------------------------------------
0138 
0139     /** Get the executor associated with the object.
0140     
0141         This function may be used to obtain the executor object that the
0142         stream uses to dispatch handlers for asynchronous operations.
0143 
0144         @return A copy of the executor that stream will use to dispatch handlers.
0145     */
0146     executor_type
0147     get_executor() noexcept
0148     {
0149         return stream_.get_executor();
0150     }
0151 
0152     /** Get a reference to the next layer
0153 
0154         This function returns a reference to the next layer
0155         in a stack of stream layers.
0156 
0157         @return A reference to the next layer in the stack of
0158         stream layers.
0159     */
0160     next_layer_type&
0161     next_layer() noexcept
0162     {
0163         return stream_;
0164     }
0165 
0166     /** Get a reference to the next layer
0167 
0168         This function returns a reference to the next layer in a
0169         stack of stream layers.
0170 
0171         @return A reference to the next layer in the stack of
0172         stream layers.
0173     */
0174     next_layer_type const&
0175     next_layer() const noexcept
0176     {
0177         return stream_;
0178     }
0179 
0180     //--------------------------------------------------------------------------
0181 
0182     /** Read some data from the stream.
0183 
0184         This function is used to read data from the stream. The function call will
0185         block until one or more bytes of data has been read successfully, or until
0186         an error occurs.
0187         
0188         @param buffers The buffers into which the data will be read.
0189         
0190         @returns The number of bytes read.
0191         
0192         @throws boost::system::system_error Thrown on failure.
0193         
0194         @note The `read_some` operation may not read all of the requested number of
0195         bytes. Consider using the function `net::read` if you need to ensure
0196         that the requested amount of data is read before the blocking operation
0197         completes.
0198     */
0199     template<class MutableBufferSequence>
0200     std::size_t
0201     read_some(MutableBufferSequence const& buffers);
0202 
0203     /** Read some data from the stream.
0204 
0205         This function is used to read data from the stream. The function call will
0206         block until one or more bytes of data has been read successfully, or until
0207         an error occurs.
0208         
0209         @param buffers The buffers into which the data will be read.
0210         
0211         @param ec Set to indicate what error occurred, if any.
0212 
0213         @returns The number of bytes read.
0214                 
0215         @note The `read_some` operation may not read all of the requested number of
0216         bytes. Consider using the function `net::read` if you need to ensure
0217         that the requested amount of data is read before the blocking operation
0218         completes.
0219     */
0220     template<class MutableBufferSequence>
0221     std::size_t
0222     read_some(
0223         MutableBufferSequence const& buffers,
0224         error_code& ec);
0225 
0226     /** Start an asynchronous read.
0227     
0228         This function is used to asynchronously read one or more bytes of data from
0229         the stream. The function call always returns immediately.
0230         
0231         @param buffers The buffers into which the data will be read. Although the
0232         buffers object may be copied as necessary, ownership of the underlying
0233         buffers is retained by the caller, which must guarantee that they remain
0234         valid until the handler is called.
0235         
0236         @param handler The completion handler to invoke when the operation
0237         completes. The implementation takes ownership of the handler by
0238         performing a decay-copy. The equivalent function signature of
0239         the handler must be:
0240         @code
0241         void handler(
0242             error_code const& error,        // Result of operation.
0243             std::size_t bytes_transferred   // Number of bytes read.
0244         );
0245         @endcode
0246         If the handler has an associated immediate executor,
0247         an immediate completion will be dispatched to it.
0248         Otherwise, the handler will not be invoked from within
0249         this function. Invocation of the handler will be performed
0250         by dispatching to the immediate executor. If no
0251         immediate executor is specified, this is equivalent
0252         to using `net::post`.
0253         @note The `read_some` operation may not read all of the requested number of
0254         bytes. Consider using the function `net::async_read` if you need
0255         to ensure that the requested amount of data is read before the asynchronous
0256         operation completes.
0257     */
0258     template<
0259         class MutableBufferSequence,
0260         BOOST_BEAST_ASYNC_TPARAM2 ReadHandler =
0261             net::default_completion_token_t<executor_type>>
0262     BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
0263     async_read_some(
0264         MutableBufferSequence const& buffers,
0265         ReadHandler&& handler =
0266             net::default_completion_token_t<executor_type>{});
0267 
0268     /** Write some data to the stream.
0269     
0270         This function is used to write data on the stream. The function call will
0271         block until one or more bytes of data has been written successfully, or
0272         until an error occurs.
0273         
0274         @param buffers The data to be written.
0275         
0276         @returns The number of bytes written.
0277         
0278         @throws boost::system::system_error Thrown on failure.
0279         
0280         @note The `write_some` operation may not transmit all of the data to the
0281         peer. Consider using the function `net::write` if you need to
0282         ensure that all data is written before the blocking operation completes.
0283     */
0284     template<class ConstBufferSequence>
0285     std::size_t
0286     write_some(ConstBufferSequence const& buffers);
0287 
0288     /** Write some data to the stream.
0289     
0290         This function is used to write data on the stream. The function call will
0291         block until one or more bytes of data has been written successfully, or
0292         until an error occurs.
0293         
0294         @param buffers The data to be written.
0295         
0296         @param ec Set to indicate what error occurred, if any.
0297 
0298         @returns The number of bytes written.
0299                 
0300         @note The `write_some` operation may not transmit all of the data to the
0301         peer. Consider using the function `net::write` if you need to
0302         ensure that all data is written before the blocking operation completes.
0303     */
0304     template<class ConstBufferSequence>
0305     std::size_t
0306     write_some(
0307         ConstBufferSequence const& buffers,
0308         error_code& ec);
0309 
0310     /** Start an asynchronous write.
0311         
0312         This function is used to asynchronously write one or more bytes of data to
0313         the stream. The function call always returns immediately.
0314         
0315         @param buffers The data to be written to the stream. Although the buffers
0316         object may be copied as necessary, ownership of the underlying buffers is
0317         retained by the caller, which must guarantee that they remain valid until
0318         the handler is called.
0319         
0320         @param handler The completion handler to invoke when the operation
0321         completes. The implementation takes ownership of the handler by
0322         performing a decay-copy. The equivalent function signature of
0323         the handler must be:
0324         @code
0325         void handler(
0326             error_code const& ec,           // Result of operation.
0327             std::size_t bytes_transferred   // Number of bytes written.
0328         );
0329         @endcode     
0330         If the handler has an associated immediate executor,
0331         an immediate completion will be dispatched to it.
0332         Otherwise, the handler will not be invoked from within
0333         this function. Invocation of the handler will be performed
0334         by dispatching to the immediate executor. If no
0335         immediate executor is specified, this is equivalent
0336         to using `net::post`.
0337         @note The `async_write_some` operation may not transmit all of the data to
0338         the peer. Consider using the function `net::async_write` if you need
0339         to ensure that all data is written before the asynchronous operation completes.
0340     */
0341     template<
0342         class ConstBufferSequence,
0343         BOOST_BEAST_ASYNC_TPARAM2 WriteHandler =
0344             net::default_completion_token_t<executor_type>>
0345     BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
0346     async_write_some(
0347         ConstBufferSequence const& buffers,
0348         WriteHandler&& handler =
0349             net::default_completion_token_t<executor_type>{});
0350 };
0351 
0352 } // beast
0353 } // boost
0354 
0355 #include <boost/beast/core/impl/flat_stream.hpp>
0356 
0357 #endif