Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / beast / core / buffered_read_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_BUFFERED_READ_STREAM_HPP
11 #define BOOST_BEAST_BUFFERED_READ_STREAM_HPP
12
13 #include <boost/beast/core/detail/config.hpp>
14 #include <boost/beast/core/error.hpp>
15 #include <boost/beast/core/multi_buffer.hpp>
16 #include <boost/beast/core/stream_traits.hpp>
17 #include <boost/asio/async_result.hpp>
18 #include <boost/asio/buffer.hpp>
19 #include <boost/asio/io_context.hpp>
20 #include <cstdint>
21 #include <utility>
22
23 namespace boost {
24 namespace beast {
25
26 /** A <em>Stream</em> with attached <em>DynamicBuffer</em> to buffer reads.
27
28     This wraps a <em>Stream</em> implementation so that calls to write are
29     passed through to the underlying stream, while calls to read will
30     first consume the input sequence stored in a <em>DynamicBuffer</em> which
31     is part of the object.
32
33     The use-case for this class is different than that of the
34     `net::buffered_read_stream`. It is designed to facilitate
35     the use of `net::read_until`, and to allow buffers
36     acquired during detection of handshakes to be made transparently
37     available to callers. A hypothetical implementation of the
38     buffered version of `net::ssl::stream::async_handshake`
39     could make use of this wrapper.
40
41     Uses:
42
43     @li Transparently leave untouched input acquired in calls
44       to `net::read_until` behind for subsequent callers.
45
46     @li "Preload" a stream with handshake input data acquired
47       from other sources.
48
49     Example:
50     @code
51     // Process the next HTTP header on the stream,
52     // leaving excess bytes behind for the next call.
53     //
54     template<class Stream, class DynamicBuffer>
55     void process_http_message(
56         buffered_read_stream<Stream, DynamicBuffer>& stream)
57     {
58         // Read up to and including the end of the HTTP
59         // header, leaving the sequence in the stream's
60         // buffer. read_until may read past the end of the
61         // headers; the return value will include only the
62         // part up to the end of the delimiter.
63         //
64         std::size_t bytes_transferred =
65             net::read_until(
66                 stream.next_layer(), stream.buffer(), "\r\n\r\n");
67
68         // Use buffers_prefix() to limit the input
69         // sequence to only the data up to and including
70         // the trailing "\r\n\r\n".
71         //
72         auto header_buffers = buffers_prefix(
73             bytes_transferred, stream.buffer().data());
74
75         ...
76
77         // Discard the portion of the input corresponding
78         // to the HTTP headers.
79         //
80         stream.buffer().consume(bytes_transferred);
81
82         // Everything we read from the stream
83         // is part of the content-body.
84     }
85     @endcode
86
87     @tparam Stream The type of stream to wrap.
88
89     @tparam DynamicBuffer The type of stream buffer to use.
90 */
91 template<class Stream, class DynamicBuffer>
92 class buffered_read_stream
93 {
94     static_assert(
95         net::is_dynamic_buffer<DynamicBuffer>::value,
96         "DynamicBuffer type requirements not met");
97
98     struct ops;
99
100     DynamicBuffer buffer_;
101     std::size_t capacity_ = 0;
102     Stream next_layer_;
103
104 public:
105     /// The type of the internal buffer
106     using buffer_type = DynamicBuffer;
107
108     /// The type of the next layer.
109     using next_layer_type =
110         typename std::remove_reference<Stream>::type;
111
112     /** Move constructor.
113
114         @note The behavior of move assignment on or from streams
115         with active or pending operations is undefined.
116     */
117     buffered_read_stream(buffered_read_stream&&) = default;
118
119     /** Move assignment.
120
121         @note The behavior of move assignment on or from streams
122         with active or pending operations is undefined.
123     */
124     buffered_read_stream& operator=(buffered_read_stream&&) = default;
125
126     /** Construct the wrapping stream.
127
128         @param args Parameters forwarded to the `Stream` constructor.
129     */
130     template<class... Args>
131     explicit
132     buffered_read_stream(Args&&... args);
133
134     /// Get a reference to the next layer.
135     next_layer_type&
136     next_layer() noexcept
137     {
138         return next_layer_;
139     }
140
141     /// Get a const reference to the next layer.
142     next_layer_type const&
143     next_layer() const noexcept
144     {
145         return next_layer_;
146     }
147     
148     using executor_type =
149         beast::executor_type<next_layer_type>;
150
151     /** Get the executor associated with the object.
152     
153         This function may be used to obtain the executor object that the stream
154         uses to dispatch handlers for asynchronous operations.
155
156         @return A copy of the executor that stream will use to dispatch handlers.
157     */
158     executor_type
159     get_executor() noexcept
160     {
161         return next_layer_.get_executor();
162     }
163
164     /** Access the internal buffer.
165
166         The internal buffer is returned. It is possible for the
167         caller to break invariants with this function. For example,
168         by causing the internal buffer size to increase beyond
169         the caller defined maximum.
170     */
171     DynamicBuffer&
172     buffer() noexcept
173     {
174         return buffer_;
175     }
176
177     /// Access the internal buffer
178     DynamicBuffer const&
179     buffer() const noexcept
180     {
181         return buffer_;
182     }
183
184     /** Set the maximum buffer size.
185
186         This changes the maximum size of the internal buffer used
187         to hold read data. No bytes are discarded by this call. If
188         the buffer size is set to zero, no more data will be buffered.
189
190         Thread safety:
191             The caller is responsible for making sure the call is
192             made from the same implicit or explicit strand.
193
194         @param size The number of bytes in the read buffer.
195
196         @note This is a soft limit. If the new maximum size is smaller
197         than the amount of data in the buffer, no bytes are discarded.
198     */
199     void
200     capacity(std::size_t size) noexcept
201     {
202         capacity_ = size;
203     }
204
205     /** Read some data from the stream.
206
207         This function is used to read data from the stream.
208         The function call will block until one or more bytes of
209         data has been read successfully, or until an error occurs.
210
211         @param buffers One or more buffers into which the data will be read.
212
213         @return The number of bytes read.
214
215         @throws system_error Thrown on failure.
216     */
217     template<class MutableBufferSequence>
218     std::size_t
219     read_some(MutableBufferSequence const& buffers);
220
221     /** Read some data from the stream.
222
223         This function is used to read data from the stream.
224         The function call will block until one or more bytes of
225         data has been read successfully, or until an error occurs.
226
227         @param buffers One or more buffers into which the data will be read.
228
229         @param ec Set to the error, if any occurred.
230
231         @return The number of bytes read, or 0 on error.
232     */
233     template<class MutableBufferSequence>
234     std::size_t
235     read_some(MutableBufferSequence const& buffers,
236         error_code& ec);
237
238     /** Start an asynchronous read.
239
240         This function is used to asynchronously read data from
241         the stream. The function call always returns immediately.
242
243         @param buffers One or more buffers into which the data
244         will be read. Although the buffers object may be copied
245         as necessary, ownership of the underlying memory blocks
246         is retained by the caller, which must guarantee that they
247         remain valid until the handler is called.
248
249         @param handler The completion handler to invoke when the operation
250         completes. The implementation takes ownership of the handler by
251         performing a decay-copy. The equivalent function signature of
252         the handler must be:
253         @code
254         void handler(
255             error_code const& error,      // result of operation
256             std::size_t bytes_transferred // number of bytes transferred
257         );
258         @endcode        
259         Regardless of whether the asynchronous operation completes
260         immediately or not, the handler will not be invoked from within
261         this function. Invocation of the handler will be performed in a
262         manner equivalent to using `net::post`.
263     */
264     template<
265         class MutableBufferSequence,
266         BOOST_BEAST_ASYNC_TPARAM2 ReadHandler =
267             net::default_completion_token_t<executor_type>>
268     BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
269     async_read_some(
270         MutableBufferSequence const& buffers,
271         ReadHandler&& handler =
272             net::default_completion_token_t<executor_type>{});
273
274     /** Write some data to the stream.
275
276         This function is used to write data to the stream.
277         The function call will block until one or more bytes of the
278         data has been written successfully, or until an error occurs.
279
280         @param buffers One or more data buffers to be written to the stream.
281
282         @return The number of bytes written.
283
284         @throws system_error Thrown on failure.
285     */
286     template<class ConstBufferSequence>
287     std::size_t
288     write_some(ConstBufferSequence const& buffers)
289     {
290         static_assert(is_sync_write_stream<next_layer_type>::value,
291             "SyncWriteStream type requirements not met");
292         return next_layer_.write_some(buffers);
293     }
294
295     /** Write some data to the stream.
296
297         This function is used to write data to the stream.
298         The function call will block until one or more bytes of the
299         data has been written successfully, or until an error occurs.
300
301         @param buffers One or more data buffers to be written to the stream.
302
303         @param ec Set to the error, if any occurred.
304
305         @return The number of bytes written.
306     */
307     template<class ConstBufferSequence>
308     std::size_t
309     write_some(ConstBufferSequence const& buffers,
310         error_code& ec)
311     {
312         static_assert(is_sync_write_stream<next_layer_type>::value,
313             "SyncWriteStream type requirements not met");
314         return next_layer_.write_some(buffers, ec);
315     }
316
317     /** Start an asynchronous write.
318
319         This function is used to asynchronously write data from
320         the stream. The function call always returns immediately.
321
322         @param buffers One or more data buffers to be written to
323         the stream. Although the buffers object may be copied as
324         necessary, ownership of the underlying memory blocks is
325         retained by the caller, which must guarantee that they
326         remain valid until the handler is called.
327
328         @param handler The completion handler to invoke when the operation
329         completes. The implementation takes ownership of the handler by
330         performing a decay-copy. The equivalent function signature of
331         the handler must be:
332         @code
333         void handler(
334             error_code const& error,      // result of operation
335             std::size_t bytes_transferred // number of bytes transferred
336         );
337         @endcode
338         Regardless of whether the asynchronous operation completes
339         immediately or not, the handler will not be invoked from within
340         this function. Invocation of the handler will be performed in a
341         manner equivalent to using `net::post`.
342     */
343     template<
344         class ConstBufferSequence,
345         BOOST_BEAST_ASYNC_TPARAM2 WriteHandler =
346             net::default_completion_token_t<executor_type>>
347     BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
348     async_write_some(
349         ConstBufferSequence const& buffers,
350         WriteHandler&& handler =
351             net::default_completion_token_t<executor_type>{});
352 };
353
354 } // beast
355 } // boost
356
357 #include <boost/beast/core/impl/buffered_read_stream.hpp>
358
359 #endif