Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:28

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