2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 // Official repository: https://github.com/boostorg/beast
10 #ifndef BOOST_BEAST_CORE_FLAT_STREAM_HPP
11 #define BOOST_BEAST_CORE_FLAT_STREAM_HPP
13 #include <boost/beast/core/detail/config.hpp>
14 #include <boost/beast/core/error.hpp>
15 #include <boost/beast/core/flat_buffer.hpp>
16 #include <boost/beast/core/stream_traits.hpp>
17 #include <boost/beast/core/detail/flat_stream.hpp>
18 #include <boost/asio/async_result.hpp>
25 /** Stream wrapper to improve write performance.
27 This wrapper flattens writes for buffer sequences having length
28 greater than 1 and total size below a predefined amount, using
29 a dynamic memory allocation. It is primarily designed to overcome
30 a performance limitation of the current version of `net::ssl::stream`,
31 which does not use OpenSSL's scatter/gather interface for its
32 low-level read some and write some operations.
34 It is normally not necessary to use this class directly if you
35 are already using @ref ssl_stream. The following examples shows
36 how to use this class with the ssl stream that comes with
41 To use the @ref flat_stream template with SSL streams, declare
42 a variable of the correct type. Parameters passed to the constructor
43 will be forwarded to the next layer's constructor:
46 flat_stream<net::ssl::stream<ip::tcp::socket>> fs{ioc, ctx};
48 Alternatively you can write
50 ssl::stream<ip::tcp::socket> ss{ioc, ctx};
51 flat_stream<net::ssl::stream<ip::tcp::socket>&> fs{ss};
54 The resulting stream may be passed to any stream algorithms which
55 operate on synchronous or asynchronous read or write streams,
58 @li `net::read`, `net::async_read`
60 @li `net::write`, `net::async_write`
62 @li `net::read_until`, `net::async_read_until`
64 The stream may also be used as a template parameter in other
65 stream wrappers, such as for websocket:
67 websocket::stream<flat_stream<net::ssl::stream<ip::tcp::socket>>> ws{ioc, ctx};
70 @tparam NextLayer The type representing the next layer, to which
71 data will be read and written during operations. For synchronous
72 operations, the type must support the @b SyncStream concept. For
73 asynchronous operations, the type must support the @b AsyncStream
74 concept. This type will usually be some variation of
82 @li https://github.com/boostorg/asio/issues/100
83 @li https://github.com/boostorg/beast/issues/1108
84 @li https://stackoverflow.com/questions/38198638/openssl-ssl-write-from-multiple-buffers-ssl-writev
85 @li https://stackoverflow.com/questions/50026167/performance-drop-on-port-from-beast-1-0-0-b66-to-boost-1-67-0-beast
87 template<class NextLayer>
89 #if ! BOOST_BEAST_DOXYGEN
90 : private detail::flat_stream_base
96 BOOST_STATIC_ASSERT(has_get_executor<NextLayer>::value);
100 template<class ConstBufferSequence>
104 ConstBufferSequence const& buffers,
108 /// The type of the next layer.
109 using next_layer_type =
110 typename std::remove_reference<NextLayer>::type;
112 /// The type of the executor associated with the object.
113 using executor_type = beast::executor_type<next_layer_type>;
115 flat_stream(flat_stream&&) = default;
116 flat_stream(flat_stream const&) = default;
117 flat_stream& operator=(flat_stream&&) = default;
118 flat_stream& operator=(flat_stream const&) = default;
122 The treatment of pending operations will be the same as that
125 ~flat_stream() = default;
129 Arguments, if any, are forwarded to the next layer's constructor.
131 template<class... Args>
133 flat_stream(Args&&... args);
135 //--------------------------------------------------------------------------
137 /** Get the executor associated with the object.
139 This function may be used to obtain the executor object that the
140 stream uses to dispatch handlers for asynchronous operations.
142 @return A copy of the executor that stream will use to dispatch handlers.
145 get_executor() noexcept
147 return stream_.get_executor();
150 /** Get a reference to the next layer
152 This function returns a reference to the next layer
153 in a stack of stream layers.
155 @return A reference to the next layer in the stack of
159 next_layer() noexcept
164 /** Get a reference to the next layer
166 This function returns a reference to the next layer in a
167 stack of stream layers.
169 @return A reference to the next layer in the stack of
172 next_layer_type const&
173 next_layer() const noexcept
178 //--------------------------------------------------------------------------
180 /** Read some data from the stream.
182 This function is used to read data from the stream. The function call will
183 block until one or more bytes of data has been read successfully, or until
186 @param buffers The buffers into which the data will be read.
188 @returns The number of bytes read.
190 @throws boost::system::system_error Thrown on failure.
192 @note The `read_some` operation may not read all of the requested number of
193 bytes. Consider using the function `net::read` if you need to ensure
194 that the requested amount of data is read before the blocking operation
197 template<class MutableBufferSequence>
199 read_some(MutableBufferSequence const& buffers);
201 /** Read some data from the stream.
203 This function is used to read data from the stream. The function call will
204 block until one or more bytes of data has been read successfully, or until
207 @param buffers The buffers into which the data will be read.
209 @param ec Set to indicate what error occurred, if any.
211 @returns The number of bytes read.
213 @note The `read_some` operation may not read all of the requested number of
214 bytes. Consider using the function `net::read` if you need to ensure
215 that the requested amount of data is read before the blocking operation
218 template<class MutableBufferSequence>
221 MutableBufferSequence const& buffers,
224 /** Start an asynchronous read.
226 This function is used to asynchronously read one or more bytes of data from
227 the stream. The function call always returns immediately.
229 @param buffers The buffers into which the data will be read. Although the
230 buffers object may be copied as necessary, ownership of the underlying
231 buffers is retained by the caller, which must guarantee that they remain
232 valid until the handler is called.
234 @param handler The completion handler to invoke when the operation
235 completes. The implementation takes ownership of the handler by
236 performing a decay-copy. The equivalent function signature of
240 error_code const& error, // Result of operation.
241 std::size_t bytes_transferred // Number of bytes read.
244 Regardless of whether the asynchronous operation completes
245 immediately or not, the handler will not be invoked from within
246 this function. Invocation of the handler will be performed in a
247 manner equivalent to using `net::post`.
249 @note The `read_some` operation may not read all of the requested number of
250 bytes. Consider using the function `net::async_read` if you need
251 to ensure that the requested amount of data is read before the asynchronous
255 class MutableBufferSequence,
256 BOOST_BEAST_ASYNC_TPARAM2 ReadHandler =
257 net::default_completion_token_t<executor_type>>
258 BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
260 MutableBufferSequence const& buffers,
261 ReadHandler&& handler =
262 net::default_completion_token_t<executor_type>{});
264 /** Write some data to the stream.
266 This function is used to write data on the stream. The function call will
267 block until one or more bytes of data has been written successfully, or
268 until an error occurs.
270 @param buffers The data to be written.
272 @returns The number of bytes written.
274 @throws boost::system::system_error Thrown on failure.
276 @note The `write_some` operation may not transmit all of the data to the
277 peer. Consider using the function `net::write` if you need to
278 ensure that all data is written before the blocking operation completes.
280 template<class ConstBufferSequence>
282 write_some(ConstBufferSequence const& buffers);
284 /** Write some data to the stream.
286 This function is used to write data on the stream. The function call will
287 block until one or more bytes of data has been written successfully, or
288 until an error occurs.
290 @param buffers The data to be written.
292 @param ec Set to indicate what error occurred, if any.
294 @returns The number of bytes written.
296 @note The `write_some` operation may not transmit all of the data to the
297 peer. Consider using the function `net::write` if you need to
298 ensure that all data is written before the blocking operation completes.
300 template<class ConstBufferSequence>
303 ConstBufferSequence const& buffers,
306 /** Start an asynchronous write.
308 This function is used to asynchronously write one or more bytes of data to
309 the stream. The function call always returns immediately.
311 @param buffers The data to be written to the stream. Although the buffers
312 object may be copied as necessary, ownership of the underlying buffers is
313 retained by the caller, which must guarantee that they remain valid until
314 the handler is called.
316 @param handler The completion handler to invoke when the operation
317 completes. The implementation takes ownership of the handler by
318 performing a decay-copy. The equivalent function signature of
322 error_code const& ec, // Result of operation.
323 std::size_t bytes_transferred // Number of bytes written.
326 Regardless of whether the asynchronous operation completes
327 immediately or not, the handler will not be invoked from within
328 this function. Invocation of the handler will be performed in a
329 manner equivalent to using `net::post`.
331 @note The `async_write_some` operation may not transmit all of the data to
332 the peer. Consider using the function `net::async_write` if you need
333 to ensure that all data is written before the asynchronous operation completes.
336 class ConstBufferSequence,
337 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler =
338 net::default_completion_token_t<executor_type>>
339 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
341 ConstBufferSequence const& buffers,
342 WriteHandler&& handler =
343 net::default_completion_token_t<executor_type>{});
349 #include <boost/beast/core/impl/flat_stream.hpp>