Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / beast / core / flat_stream.hpp
1 //
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
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)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9
10 #ifndef BOOST_BEAST_CORE_FLAT_STREAM_HPP
11 #define BOOST_BEAST_CORE_FLAT_STREAM_HPP
12
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>
19 #include <cstdlib>
20 #include <utility>
21
22 namespace boost {
23 namespace beast {
24
25 /** Stream wrapper to improve write performance.
26
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.
33
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
37     networking:
38
39     @par Example
40
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:
44
45     @code
46         flat_stream<net::ssl::stream<ip::tcp::socket>> fs{ioc, ctx};
47     @endcode
48     Alternatively you can write
49     @code
50         ssl::stream<ip::tcp::socket> ss{ioc, ctx};
51         flat_stream<net::ssl::stream<ip::tcp::socket>&> fs{ss};
52     @endcode
53
54     The resulting stream may be passed to any stream algorithms which
55     operate on synchronous or asynchronous read or write streams,
56     examples include:
57     
58     @li `net::read`, `net::async_read`
59
60     @li `net::write`, `net::async_write`
61
62     @li `net::read_until`, `net::async_read_until`
63
64     The stream may also be used as a template parameter in other
65     stream wrappers, such as for websocket:
66     @code
67         websocket::stream<flat_stream<net::ssl::stream<ip::tcp::socket>>> ws{ioc, ctx};
68     @endcode
69
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
75     `net::ssl::stream`.
76
77     @par Concepts
78         @li SyncStream
79         @li AsyncStream
80
81     @see
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
86 */
87 template<class NextLayer>
88 class flat_stream
89 #if ! BOOST_BEAST_DOXYGEN
90     : private detail::flat_stream_base
91 #endif
92 {
93     NextLayer stream_;
94     flat_buffer buffer_;
95
96     BOOST_STATIC_ASSERT(has_get_executor<NextLayer>::value);
97
98     struct ops;
99
100     template<class ConstBufferSequence>
101     std::size_t
102     stack_write_some(
103         std::size_t size,
104         ConstBufferSequence const& buffers,
105         error_code& ec);
106
107 public:
108     /// The type of the next layer.
109     using next_layer_type =
110         typename std::remove_reference<NextLayer>::type;
111
112     /// The type of the executor associated with the object.
113     using executor_type = beast::executor_type<next_layer_type>;
114
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;
119
120     /** Destructor
121
122         The treatment of pending operations will be the same as that
123         of the next layer.
124     */
125     ~flat_stream() = default;
126
127     /** Constructor
128
129         Arguments, if any, are forwarded to the next layer's constructor.
130     */
131     template<class... Args>
132     explicit
133     flat_stream(Args&&... args);
134
135     //--------------------------------------------------------------------------
136
137     /** Get the executor associated with the object.
138     
139         This function may be used to obtain the executor object that the
140         stream uses to dispatch handlers for asynchronous operations.
141
142         @return A copy of the executor that stream will use to dispatch handlers.
143     */
144     executor_type
145     get_executor() noexcept
146     {
147         return stream_.get_executor();
148     }
149
150     /** Get a reference to the next layer
151
152         This function returns a reference to the next layer
153         in a stack of stream layers.
154
155         @return A reference to the next layer in the stack of
156         stream layers.
157     */
158     next_layer_type&
159     next_layer() noexcept
160     {
161         return stream_;
162     }
163
164     /** Get a reference to the next layer
165
166         This function returns a reference to the next layer in a
167         stack of stream layers.
168
169         @return A reference to the next layer in the stack of
170         stream layers.
171     */
172     next_layer_type const&
173     next_layer() const noexcept
174     {
175         return stream_;
176     }
177
178     //--------------------------------------------------------------------------
179
180     /** Read some data from the stream.
181
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
184         an error occurs.
185         
186         @param buffers The buffers into which the data will be read.
187         
188         @returns The number of bytes read.
189         
190         @throws boost::system::system_error Thrown on failure.
191         
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
195         completes.
196     */
197     template<class MutableBufferSequence>
198     std::size_t
199     read_some(MutableBufferSequence const& buffers);
200
201     /** Read some data from the stream.
202
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
205         an error occurs.
206         
207         @param buffers The buffers into which the data will be read.
208         
209         @param ec Set to indicate what error occurred, if any.
210
211         @returns The number of bytes read.
212                 
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
216         completes.
217     */
218     template<class MutableBufferSequence>
219     std::size_t
220     read_some(
221         MutableBufferSequence const& buffers,
222         error_code& ec);
223
224     /** Start an asynchronous read.
225     
226         This function is used to asynchronously read one or more bytes of data from
227         the stream. The function call always returns immediately.
228         
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.
233         
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
237         the handler must be:
238         @code
239         void handler(
240             error_code const& error,        // Result of operation.
241             std::size_t bytes_transferred   // Number of bytes read.
242         );
243         @endcode
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`.
248         
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
252         operation completes.
253     */
254     template<
255         class MutableBufferSequence,
256         BOOST_BEAST_ASYNC_TPARAM2 ReadHandler =
257             net::default_completion_token_t<executor_type>>
258     BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
259     async_read_some(
260         MutableBufferSequence const& buffers,
261         ReadHandler&& handler =
262             net::default_completion_token_t<executor_type>{});
263
264     /** Write some data to the stream.
265     
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.
269         
270         @param buffers The data to be written.
271         
272         @returns The number of bytes written.
273         
274         @throws boost::system::system_error Thrown on failure.
275         
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.
279     */
280     template<class ConstBufferSequence>
281     std::size_t
282     write_some(ConstBufferSequence const& buffers);
283
284     /** Write some data to the stream.
285     
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.
289         
290         @param buffers The data to be written.
291         
292         @param ec Set to indicate what error occurred, if any.
293
294         @returns The number of bytes written.
295                 
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.
299     */
300     template<class ConstBufferSequence>
301     std::size_t
302     write_some(
303         ConstBufferSequence const& buffers,
304         error_code& ec);
305
306     /** Start an asynchronous write.
307         
308         This function is used to asynchronously write one or more bytes of data to
309         the stream. The function call always returns immediately.
310         
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.
315         
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
319         the handler must be:
320         @code
321         void handler(
322             error_code const& ec,           // Result of operation.
323             std::size_t bytes_transferred   // Number of bytes written.
324         );
325         @endcode     
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`.
330         
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.
334     */
335     template<
336         class ConstBufferSequence,
337         BOOST_BEAST_ASYNC_TPARAM2 WriteHandler =
338             net::default_completion_token_t<executor_type>>
339     BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
340     async_write_some(
341         ConstBufferSequence const& buffers,
342         WriteHandler&& handler =
343             net::default_completion_token_t<executor_type>{});
344 };
345
346 } // beast
347 } // boost
348
349 #include <boost/beast/core/impl/flat_stream.hpp>
350
351 #endif