]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/core/buffered_read_stream.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / beast / core / buffered_read_stream.hpp
1 //
2 // Copyright (c) 2016-2017 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/type_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 @b Stream with attached @b DynamicBuffer to buffer reads.
27
28 This wraps a @b Stream 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 @b DynamicBuffer which
31 is part of the object.
32
33 The use-case for this class is different than that of the
34 `boost::asio::buffered_readstream`. It is designed to facilitate
35 the use of `boost::asio::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 `boost::asio::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 `boost::asio::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 DynamicBuffer>
55 void process_http_message(
56 buffered_read_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 boost::asio::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 boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
96 "DynamicBuffer requirements not met");
97
98 template<class Buffers, class Handler>
99 class read_some_op;
100
101 DynamicBuffer buffer_;
102 std::size_t capacity_ = 0;
103 Stream next_layer_;
104
105 public:
106 /// The type of the internal buffer
107 using buffer_type = DynamicBuffer;
108
109 /// The type of the next layer.
110 using next_layer_type =
111 typename std::remove_reference<Stream>::type;
112
113 /// The type of the lowest layer.
114 using lowest_layer_type =
115 typename get_lowest_layer<next_layer_type>::type;
116
117 /** Move constructor.
118
119 @note The behavior of move assignment on or from streams
120 with active or pending operations is undefined.
121 */
122 buffered_read_stream(buffered_read_stream&&) = default;
123
124 /** Move assignment.
125
126 @note The behavior of move assignment on or from streams
127 with active or pending operations is undefined.
128 */
129 buffered_read_stream& operator=(buffered_read_stream&&) = default;
130
131 /** Construct the wrapping stream.
132
133 @param args Parameters forwarded to the `Stream` constructor.
134 */
135 template<class... Args>
136 explicit
137 buffered_read_stream(Args&&... args);
138
139 /// Get a reference to the next layer.
140 next_layer_type&
141 next_layer()
142 {
143 return next_layer_;
144 }
145
146 /// Get a const reference to the next layer.
147 next_layer_type const&
148 next_layer() const
149 {
150 return next_layer_;
151 }
152
153 /// Get a reference to the lowest layer.
154 lowest_layer_type&
155 lowest_layer()
156 {
157 return next_layer_.lowest_layer();
158 }
159
160 /// Get a const reference to the lowest layer.
161 lowest_layer_type const&
162 lowest_layer() const
163 {
164 return next_layer_.lowest_layer();
165 }
166
167 /** Get the executor associated with the object.
168
169 This function may be used to obtain the executor object that the stream
170 uses to dispatch handlers for asynchronous operations.
171
172 @return A copy of the executor that stream will use to dispatch handlers.
173
174 @note This function participates in overload resolution only if
175 `NextLayer` has a member function named `get_executor`.
176 */
177 #if BOOST_BEAST_DOXYGEN
178 implementation_defined
179 #else
180 template<
181 class T = next_layer_type,
182 class = typename std::enable_if<
183 has_get_executor<next_layer_type>::value>::type>
184 auto
185 #endif
186 get_executor() noexcept ->
187 decltype(std::declval<T&>().get_executor())
188 {
189 return next_layer_.get_executor();
190 }
191
192 /** Access the internal buffer.
193
194 The internal buffer is returned. It is possible for the
195 caller to break invariants with this function. For example,
196 by causing the internal buffer size to increase beyond
197 the caller defined maximum.
198 */
199 DynamicBuffer&
200 buffer()
201 {
202 return buffer_;
203 }
204
205 /// Access the internal buffer
206 DynamicBuffer const&
207 buffer() const
208 {
209 return buffer_;
210 }
211
212 /** Set the maximum buffer size.
213
214 This changes the maximum size of the internal buffer used
215 to hold read data. No bytes are discarded by this call. If
216 the buffer size is set to zero, no more data will be buffered.
217
218 Thread safety:
219 The caller is responsible for making sure the call is
220 made from the same implicit or explicit strand.
221
222 @param size The number of bytes in the read buffer.
223
224 @note This is a soft limit. If the new maximum size is smaller
225 than the amount of data in the buffer, no bytes are discarded.
226 */
227 void
228 capacity(std::size_t size)
229 {
230 capacity_ = size;
231 }
232
233 /** Read some data from the stream.
234
235 This function is used to read data from the stream.
236 The function call will block until one or more bytes of
237 data has been read successfully, or until an error occurs.
238
239 @param buffers One or more buffers into which the data will be read.
240
241 @return The number of bytes read.
242
243 @throws system_error Thrown on failure.
244 */
245 template<class MutableBufferSequence>
246 std::size_t
247 read_some(MutableBufferSequence const& buffers);
248
249 /** Read some data from the stream.
250
251 This function is used to read data from the stream.
252 The function call will block until one or more bytes of
253 data has been read successfully, or until an error occurs.
254
255 @param buffers One or more buffers into which the data will be read.
256
257 @param ec Set to the error, if any occurred.
258
259 @return The number of bytes read, or 0 on error.
260 */
261 template<class MutableBufferSequence>
262 std::size_t
263 read_some(MutableBufferSequence const& buffers,
264 error_code& ec);
265
266 /** Start an asynchronous read.
267
268 This function is used to asynchronously read data from
269 the stream. The function call always returns immediately.
270
271 @param buffers One or more buffers into which the data
272 will be read. Although the buffers object may be copied
273 as necessary, ownership of the underlying memory blocks
274 is retained by the caller, which must guarantee that they
275 remain valid until the handler is called.
276
277 @param handler The handler to be called when the operation
278 completes. Copies will be made of the handler as required.
279 The equivalent function signature of the handler must be:
280 @code void handler(
281 error_code const& error, // result of operation
282 std::size_t bytes_transferred // number of bytes transferred
283 ); @endcode
284 Regardless of whether the asynchronous operation completes
285 immediately or not, the handler will not be invoked from within
286 this function. Invocation of the handler will be performed in a
287 manner equivalent to using `boost::asio::io_context::post`.
288 */
289 template<class MutableBufferSequence, class ReadHandler>
290 BOOST_ASIO_INITFN_RESULT_TYPE(
291 ReadHandler, void(error_code, std::size_t))
292 async_read_some(MutableBufferSequence const& buffers,
293 ReadHandler&& handler);
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 @return The number of bytes written.
304
305 @throws system_error Thrown on failure.
306 */
307 template<class ConstBufferSequence>
308 std::size_t
309 write_some(ConstBufferSequence const& buffers)
310 {
311 static_assert(is_sync_write_stream<next_layer_type>::value,
312 "SyncWriteStream requirements not met");
313 return next_layer_.write_some(buffers);
314 }
315
316 /** Write some data to the stream.
317
318 This function is used to write data to the stream.
319 The function call will block until one or more bytes of the
320 data has been written successfully, or until an error occurs.
321
322 @param buffers One or more data buffers to be written to the stream.
323
324 @param ec Set to the error, if any occurred.
325
326 @return The number of bytes written.
327 */
328 template<class ConstBufferSequence>
329 std::size_t
330 write_some(ConstBufferSequence const& buffers,
331 error_code& ec)
332 {
333 static_assert(is_sync_write_stream<next_layer_type>::value,
334 "SyncWriteStream requirements not met");
335 return next_layer_.write_some(buffers, ec);
336 }
337
338 /** Start an asynchronous write.
339
340 This function is used to asynchronously write data from
341 the stream. The function call always returns immediately.
342
343 @param buffers One or more data buffers to be written to
344 the stream. Although the buffers object may be copied as
345 necessary, ownership of the underlying memory blocks is
346 retained by the caller, which must guarantee that they
347 remain valid until the handler is called.
348
349 @param handler The handler to be called when the operation
350 completes. Copies will be made of the handler as required.
351 The equivalent function signature of the handler must be:
352 @code void handler(
353 error_code const& error, // result of operation
354 std::size_t bytes_transferred // number of bytes transferred
355 ); @endcode
356 Regardless of whether the asynchronous operation completes
357 immediately or not, the handler will not be invoked from within
358 this function. Invocation of the handler will be performed in a
359 manner equivalent to using `boost::asio::io_context::post`.
360 */
361 template<class ConstBufferSequence, class WriteHandler>
362 BOOST_ASIO_INITFN_RESULT_TYPE(
363 WriteHandler, void(error_code, std::size_t))
364 async_write_some(ConstBufferSequence const& buffers,
365 WriteHandler&& handler);
366 };
367
368 } // beast
369 } // boost
370
371 #include <boost/beast/core/impl/buffered_read_stream.ipp>
372
373 #endif