]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/core/buffered_read_stream.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / 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