]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | // |
92f5a8d4 | 2 | // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) |
7c673cae FG |
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 | // | |
b32b8144 FG |
7 | // Official repository: https://github.com/boostorg/beast |
8 | // | |
7c673cae | 9 | |
b32b8144 FG |
10 | #ifndef BOOST_BEAST_BUFFERED_READ_STREAM_HPP |
11 | #define BOOST_BEAST_BUFFERED_READ_STREAM_HPP | |
7c673cae | 12 | |
b32b8144 FG |
13 | #include <boost/beast/core/detail/config.hpp> |
14 | #include <boost/beast/core/error.hpp> | |
15 | #include <boost/beast/core/multi_buffer.hpp> | |
92f5a8d4 | 16 | #include <boost/beast/core/stream_traits.hpp> |
b32b8144 | 17 | #include <boost/asio/async_result.hpp> |
7c673cae | 18 | #include <boost/asio/buffer.hpp> |
b32b8144 | 19 | #include <boost/asio/io_context.hpp> |
7c673cae FG |
20 | #include <cstdint> |
21 | #include <utility> | |
22 | ||
b32b8144 | 23 | namespace boost { |
7c673cae FG |
24 | namespace beast { |
25 | ||
92f5a8d4 | 26 | /** A <em>Stream</em> with attached <em>DynamicBuffer</em> to buffer reads. |
7c673cae | 27 | |
92f5a8d4 | 28 | This wraps a <em>Stream</em> implementation so that calls to write are |
7c673cae | 29 | passed through to the underlying stream, while calls to read will |
92f5a8d4 | 30 | first consume the input sequence stored in a <em>DynamicBuffer</em> which |
7c673cae FG |
31 | is part of the object. |
32 | ||
33 | The use-case for this class is different than that of the | |
92f5a8d4 TL |
34 | `net::buffered_read_stream`. It is designed to facilitate |
35 | the use of `net::read_until`, and to allow buffers | |
7c673cae FG |
36 | acquired during detection of handshakes to be made transparently |
37 | available to callers. A hypothetical implementation of the | |
92f5a8d4 | 38 | buffered version of `net::ssl::stream::async_handshake` |
7c673cae FG |
39 | could make use of this wrapper. |
40 | ||
41 | Uses: | |
42 | ||
43 | @li Transparently leave untouched input acquired in calls | |
92f5a8d4 | 44 | to `net::read_until` behind for subsequent callers. |
7c673cae FG |
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 | // | |
92f5a8d4 | 54 | template<class Stream, class DynamicBuffer> |
7c673cae | 55 | void process_http_message( |
92f5a8d4 | 56 | buffered_read_stream<Stream, DynamicBuffer>& stream) |
7c673cae FG |
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 = | |
92f5a8d4 | 65 | net::read_until( |
7c673cae FG |
66 | stream.next_layer(), stream.buffer(), "\r\n\r\n"); |
67 | ||
b32b8144 | 68 | // Use buffers_prefix() to limit the input |
7c673cae FG |
69 | // sequence to only the data up to and including |
70 | // the trailing "\r\n\r\n". | |
71 | // | |
b32b8144 | 72 | auto header_buffers = buffers_prefix( |
7c673cae FG |
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> | |
b32b8144 | 92 | class buffered_read_stream |
7c673cae | 93 | { |
b32b8144 | 94 | static_assert( |
92f5a8d4 TL |
95 | net::is_dynamic_buffer<DynamicBuffer>::value, |
96 | "DynamicBuffer type requirements not met"); | |
7c673cae | 97 | |
92f5a8d4 | 98 | struct ops; |
7c673cae | 99 | |
b32b8144 | 100 | DynamicBuffer buffer_; |
7c673cae FG |
101 | std::size_t capacity_ = 0; |
102 | Stream next_layer_; | |
103 | ||
104 | public: | |
105 | /// The type of the internal buffer | |
b32b8144 | 106 | using buffer_type = DynamicBuffer; |
7c673cae FG |
107 | |
108 | /// The type of the next layer. | |
109 | using next_layer_type = | |
110 | typename std::remove_reference<Stream>::type; | |
111 | ||
7c673cae FG |
112 | /** Move constructor. |
113 | ||
114 | @note The behavior of move assignment on or from streams | |
115 | with active or pending operations is undefined. | |
116 | */ | |
b32b8144 | 117 | buffered_read_stream(buffered_read_stream&&) = default; |
7c673cae FG |
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 | */ | |
b32b8144 | 124 | buffered_read_stream& operator=(buffered_read_stream&&) = default; |
7c673cae FG |
125 | |
126 | /** Construct the wrapping stream. | |
127 | ||
128 | @param args Parameters forwarded to the `Stream` constructor. | |
129 | */ | |
130 | template<class... Args> | |
131 | explicit | |
b32b8144 | 132 | buffered_read_stream(Args&&... args); |
7c673cae FG |
133 | |
134 | /// Get a reference to the next layer. | |
135 | next_layer_type& | |
92f5a8d4 | 136 | next_layer() noexcept |
7c673cae FG |
137 | { |
138 | return next_layer_; | |
139 | } | |
140 | ||
141 | /// Get a const reference to the next layer. | |
142 | next_layer_type const& | |
92f5a8d4 | 143 | next_layer() const noexcept |
7c673cae FG |
144 | { |
145 | return next_layer_; | |
146 | } | |
147 | ||
92f5a8d4 TL |
148 | using executor_type = |
149 | beast::executor_type<next_layer_type>; | |
7c673cae | 150 | |
b32b8144 FG |
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. | |
b32b8144 | 157 | */ |
92f5a8d4 TL |
158 | executor_type |
159 | get_executor() noexcept | |
7c673cae | 160 | { |
b32b8144 | 161 | return next_layer_.get_executor(); |
7c673cae FG |
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& | |
92f5a8d4 | 172 | buffer() noexcept |
7c673cae | 173 | { |
b32b8144 | 174 | return buffer_; |
7c673cae FG |
175 | } |
176 | ||
177 | /// Access the internal buffer | |
178 | DynamicBuffer const& | |
92f5a8d4 | 179 | buffer() const noexcept |
7c673cae | 180 | { |
b32b8144 | 181 | return buffer_; |
7c673cae FG |
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 | |
92f5a8d4 | 200 | capacity(std::size_t size) noexcept |
7c673cae FG |
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 | ||
92f5a8d4 TL |
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( | |
7c673cae FG |
255 | error_code const& error, // result of operation |
256 | std::size_t bytes_transferred // number of bytes transferred | |
92f5a8d4 TL |
257 | ); |
258 | @endcode | |
7c673cae FG |
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 | |
92f5a8d4 | 262 | manner equivalent to using `net::post`. |
7c673cae | 263 | */ |
92f5a8d4 TL |
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>{}); | |
7c673cae FG |
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 | { | |
b32b8144 | 290 | static_assert(is_sync_write_stream<next_layer_type>::value, |
92f5a8d4 | 291 | "SyncWriteStream type requirements not met"); |
7c673cae FG |
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 | { | |
b32b8144 | 312 | static_assert(is_sync_write_stream<next_layer_type>::value, |
92f5a8d4 | 313 | "SyncWriteStream type requirements not met"); |
7c673cae FG |
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 | ||
92f5a8d4 TL |
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( | |
7c673cae FG |
334 | error_code const& error, // result of operation |
335 | std::size_t bytes_transferred // number of bytes transferred | |
92f5a8d4 TL |
336 | ); |
337 | @endcode | |
7c673cae FG |
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 | |
92f5a8d4 | 341 | manner equivalent to using `net::post`. |
7c673cae | 342 | */ |
92f5a8d4 TL |
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>{}); | |
7c673cae FG |
352 | }; |
353 | ||
354 | } // beast | |
b32b8144 | 355 | } // boost |
7c673cae | 356 | |
92f5a8d4 | 357 | #include <boost/beast/core/impl/buffered_read_stream.hpp> |
7c673cae FG |
358 | |
359 | #endif |