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