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_DETAIL_IMPL_READ_HPP
11#define BOOST_BEAST_DETAIL_IMPL_READ_HPP
12
13#include <boost/beast/core/async_base.hpp>
14#include <boost/beast/core/flat_static_buffer.hpp>
15#include <boost/beast/core/read_size.hpp>
16#include <boost/asio/basic_stream_socket.hpp>
17#include <boost/asio/coroutine.hpp>
18#include <boost/throw_exception.hpp>
19
20namespace boost {
21namespace beast {
22namespace detail {
23
24// The number of bytes in the stack buffer when using non-blocking.
25static std::size_t constexpr default_max_stack_buffer = 16384;
26
27//------------------------------------------------------------------------------
28
29struct dynamic_read_ops
30{
31
32// read into a dynamic buffer until the
33// condition is met or an error occurs
34template<
35 class Stream,
36 class DynamicBuffer,
37 class Condition,
38 class Handler>
39class read_op
40 : public asio::coroutine
41 , public async_base<
42 Handler, beast::executor_type<Stream>>
43{
44 Stream& s_;
45 DynamicBuffer& b_;
46 Condition cond_;
47 error_code ec_;
48 std::size_t total_ = 0;
49
50public:
51 read_op(read_op&&) = default;
52
53 template<class Handler_, class Condition_>
54 read_op(
55 Handler_&& h,
56 Stream& s,
57 DynamicBuffer& b,
58 Condition_&& cond)
59 : async_base<Handler,
60 beast::executor_type<Stream>>(
61 std::forward<Handler_>(h),
62 s.get_executor())
63 , s_(s)
64 , b_(b)
65 , cond_(std::forward<Condition_>(cond))
66 {
67 (*this)({}, 0, false);
68 }
69
70 void
71 operator()(
72 error_code ec,
73 std::size_t bytes_transferred,
74 bool cont = true)
75 {
76 std::size_t max_prepare;
77 BOOST_ASIO_CORO_REENTER(*this)
78 {
79 for(;;)
80 {
81 max_prepare = beast::read_size(b_, cond_(ec, total_, b_));
82 if(max_prepare == 0)
83 break;
84 BOOST_ASIO_CORO_YIELD
85 s_.async_read_some(
86 b_.prepare(max_prepare), std::move(*this));
87 b_.commit(bytes_transferred);
88 total_ += bytes_transferred;
89 }
90 if(! cont)
91 {
92 // run this handler "as-if" using net::post
93 // to reduce template instantiations
94 ec_ = ec;
95 BOOST_ASIO_CORO_YIELD
96 s_.async_read_some(
97 b_.prepare(0), std::move(*this));
98 BOOST_BEAST_ASSIGN_EC(ec, ec_);
99 }
100 this->complete_now(ec, total_);
101 }
102 }
103};
104
105//------------------------------------------------------------------------------
106
107struct run_read_op
108{
109 template<
110 class AsyncReadStream,
111 class DynamicBuffer,
112 class Condition,
113 class ReadHandler>
114 void
115 operator()(
116 ReadHandler&& h,
117 AsyncReadStream* s,
118 DynamicBuffer* b,
119 Condition&& c)
120 {
121 // If you get an error on the following line it means
122 // that your handler does not meet the documented type
123 // requirements for the handler.
124
125 static_assert(
126 beast::detail::is_invocable<ReadHandler,
127 void(error_code, std::size_t)>::value,
128 "ReadHandler type requirements not met");
129
130 read_op<
131 AsyncReadStream,
132 DynamicBuffer,
133 typename std::decay<Condition>::type,
134 typename std::decay<ReadHandler>::type>(
135 std::forward<ReadHandler>(h),
136 *s,
137 *b,
138 std::forward<Condition>(c));
139 }
140
141};
142
143};
144
145//------------------------------------------------------------------------------
146
147template<
148 class SyncReadStream,
149 class DynamicBuffer,
150 class CompletionCondition,
151 class>
152std::size_t
153read(
154 SyncReadStream& stream,
155 DynamicBuffer& buffer,
156 CompletionCondition cond)
157{
158 static_assert(is_sync_read_stream<SyncReadStream>::value,
159 "SyncReadStream type requirements not met");
160 static_assert(
161 net::is_dynamic_buffer<DynamicBuffer>::value,
162 "DynamicBuffer type requirements not met");
163 static_assert(
164 detail::is_invocable<CompletionCondition,
165 void(error_code&, std::size_t, DynamicBuffer&)>::value,
166 "CompletionCondition type requirements not met");
167 error_code ec;
168 auto const bytes_transferred = detail::read(
169 stream, buffer, std::move(cond), ec);
170 if(ec)
171 BOOST_THROW_EXCEPTION(system_error{ec});
172 return bytes_transferred;
173}
174
175template<
176 class SyncReadStream,
177 class DynamicBuffer,
178 class CompletionCondition,
179 class>
180std::size_t
181read(
182 SyncReadStream& stream,
183 DynamicBuffer& buffer,
184 CompletionCondition cond,
185 error_code& ec)
186{
187 static_assert(is_sync_read_stream<SyncReadStream>::value,
188 "SyncReadStream type requirements not met");
189 static_assert(
190 net::is_dynamic_buffer<DynamicBuffer>::value,
191 "DynamicBuffer type requirements not met");
192 static_assert(
193 detail::is_invocable<CompletionCondition,
194 void(error_code&, std::size_t, DynamicBuffer&)>::value,
195 "CompletionCondition type requirements not met");
196 ec = {};
197 std::size_t total = 0;
198 std::size_t max_prepare;
199 for(;;)
200 {
201 max_prepare = beast::read_size(buffer, cond(ec, total, buffer));
202 if(max_prepare == 0)
203 break;
204 std::size_t const bytes_transferred =
205 stream.read_some(buffer.prepare(max_prepare), ec);
206 buffer.commit(bytes_transferred);
207 total += bytes_transferred;
208 }
209 return total;
210}
211
212template<
213 class AsyncReadStream,
214 class DynamicBuffer,
215 class CompletionCondition,
216 BOOST_BEAST_ASYNC_TPARAM2 ReadHandler,
217 class>
218BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
219async_read(
220 AsyncReadStream& stream,
221 DynamicBuffer& buffer,
222 CompletionCondition&& cond,
223 ReadHandler&& handler)
224{
225 static_assert(is_async_read_stream<AsyncReadStream>::value,
226 "AsyncReadStream type requirements not met");
227 static_assert(
228 net::is_dynamic_buffer<DynamicBuffer>::value,
229 "DynamicBuffer type requirements not met");
230 static_assert(
231 detail::is_invocable<CompletionCondition,
232 void(error_code&, std::size_t, DynamicBuffer&)>::value,
233 "CompletionCondition type requirements not met");
234 return net::async_initiate<
235 ReadHandler,
236 void(error_code, std::size_t)>(
237 typename dynamic_read_ops::run_read_op{},
238 handler,
239 &stream,
240 &buffer,
241 std::forward<CompletionCondition>(cond));
242}
243
244} // detail
245} // beast
246} // boost
247
248#endif
249

source code of boost/libs/beast/include/boost/beast/core/detail/impl/read.hpp