Line data Source code
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/cppalliance/beast2
8 : //
9 :
10 : #ifndef BOOST_BEAST2_IMPL_WRITE_HPP
11 : #define BOOST_BEAST2_IMPL_WRITE_HPP
12 :
13 : #include <boost/asio/append.hpp>
14 : #include <boost/asio/buffer.hpp>
15 : #include <boost/asio/compose.hpp>
16 : #include <boost/asio/coroutine.hpp>
17 : #include <boost/asio/immediate.hpp>
18 : #include <boost/system/error_code.hpp>
19 : #include <boost/system/result.hpp>
20 : #include <boost/http_proto/serializer.hpp>
21 :
22 : namespace boost {
23 : namespace beast2 {
24 :
25 : namespace detail {
26 :
27 : template<class WriteStream>
28 : class write_some_op
29 : : public asio::coroutine
30 : {
31 : using buffers_type =
32 : http::serializer::const_buffers_type;
33 :
34 : WriteStream& dest_;
35 : http::serializer& sr_;
36 :
37 : public:
38 94 : write_some_op(
39 : WriteStream& dest,
40 : http::serializer& sr) noexcept
41 94 : : dest_(dest)
42 94 : , sr_(sr)
43 : {
44 94 : }
45 :
46 : template<class Self>
47 : void
48 188 : operator()(
49 : Self& self,
50 : system::error_code ec = {},
51 : std::size_t bytes_transferred = {})
52 : {
53 188 : system::result<buffers_type> rv;
54 :
55 376 : BOOST_ASIO_CORO_REENTER(*this)
56 : {
57 94 : self.reset_cancellation_state(
58 0 : asio::enable_total_cancellation());
59 :
60 94 : rv = sr_.prepare();
61 94 : if(! rv)
62 : {
63 0 : ec = rv.error();
64 0 : BOOST_ASIO_CORO_YIELD
65 : {
66 : BOOST_ASIO_HANDLER_LOCATION((
67 : __FILE__, __LINE__,
68 : "immediate"));
69 0 : auto io_ex = self.get_io_executor();
70 0 : asio::async_immediate(
71 : io_ex,
72 0 : asio::append(std::move(self), ec));
73 0 : }
74 0 : goto upcall;
75 : }
76 :
77 282 : BOOST_ASIO_CORO_YIELD
78 : {
79 : BOOST_ASIO_HANDLER_LOCATION((
80 : __FILE__, __LINE__,
81 : "beast2::write_some_op"));
82 94 : dest_.async_write_some(
83 94 : *rv,
84 94 : std::move(self));
85 : }
86 94 : sr_.consume(bytes_transferred);
87 :
88 94 : upcall:
89 94 : self.complete(
90 : ec, bytes_transferred );
91 : }
92 188 : }
93 : };
94 :
95 : //------------------------------------------------
96 :
97 : template<class WriteStream>
98 : class write_op
99 : : public asio::coroutine
100 : {
101 : WriteStream& dest_;
102 : http::serializer& sr_;
103 : std::size_t n_ = 0;
104 :
105 : public:
106 5 : write_op(
107 : WriteStream& dest,
108 : http::serializer& sr) noexcept
109 5 : : dest_(dest)
110 5 : , sr_(sr)
111 : {
112 5 : }
113 :
114 : template<class Self>
115 : void
116 52 : operator()(
117 : Self& self,
118 : system::error_code ec = {},
119 : std::size_t bytes_transferred = 0)
120 : {
121 104 : BOOST_ASIO_CORO_REENTER(*this)
122 : {
123 5 : self.reset_cancellation_state(asio::enable_total_cancellation());
124 :
125 : do
126 : {
127 50 : if(!!self.cancelled())
128 : {
129 3 : ec = asio::error::operation_aborted;
130 :
131 3 : break; // goto upcall
132 : }
133 :
134 141 : BOOST_ASIO_CORO_YIELD
135 : {
136 : BOOST_ASIO_HANDLER_LOCATION((
137 : __FILE__, __LINE__,
138 : "beast2::write_op"));
139 47 : async_write_some(
140 47 : dest_, sr_, std::move(self));
141 : }
142 47 : n_ += bytes_transferred;
143 :
144 47 : if(ec.failed())
145 1 : break; // goto upcall
146 : }
147 46 : while(! sr_.is_done());
148 :
149 : // upcall:
150 5 : self.complete(ec, n_ );
151 : }
152 52 : }
153 : };
154 :
155 : //------------------------------------------------
156 :
157 : #if 0
158 : template<
159 : class WriteStream,
160 : class ReadStream,
161 : class CompletionCondition>
162 : class relay_some_op
163 : : public asio::coroutine
164 : {
165 : WriteStream& dest_;
166 : ReadStream& src_;
167 : CompletionCondition cond_;
168 : http::serializer& sr_;
169 : std::size_t bytes_read_ = 0;
170 :
171 : public:
172 : relay_some_op(
173 : WriteStream& dest,
174 : ReadStream& src,
175 : CompletionCondition const& cond,
176 : http::serializer& sr) noexcept
177 : : dest_(dest)
178 : , src_(src)
179 : , cond_(cond)
180 : , sr_(sr)
181 : {
182 : }
183 :
184 : template<class Self>
185 : void
186 : operator()(
187 : Self& self,
188 : system::error_code ec = {},
189 : std::size_t bytes_transferred = 0)
190 : {
191 : urls::result<
192 : http::serializer::buffers> rv;
193 :
194 : BOOST_ASIO_CORO_REENTER(*this)
195 : {
196 : // Nothing to do
197 : BOOST_ASSERT(! sr_.is_complete());
198 :
199 : rv = sr_.prepare();
200 : if(! rv)
201 : {
202 : ec = rv.error();
203 : BOOST_ASIO_CORO_YIELD
204 : {
205 : BOOST_ASIO_HANDLER_LOCATION((
206 : __FILE__, __LINE__,
207 : "beast2::relay_some_op"));
208 : asio::post(std::move(self));
209 : }
210 : goto upcall;
211 : }
212 :
213 : BOOST_ASIO_CORO_YIELD
214 : {
215 : BOOST_ASIO_HANDLER_LOCATION((
216 : __FILE__, __LINE__,
217 : "beast2::relay_some_op"));
218 : dest_.async_write_some(
219 : write_buffers(*rv),
220 : std::move(self));
221 : }
222 : sr_.consume(bytes_transferred);
223 :
224 : upcall:
225 : self.complete(
226 : ec, bytes_transferred );
227 : }
228 : }
229 : };
230 : #endif
231 :
232 : } // detail
233 :
234 : //------------------------------------------------
235 :
236 : template<
237 : class AsyncWriteStream,
238 : BOOST_ASIO_COMPLETION_TOKEN_FOR(
239 : void(system::error_code, std::size_t)) CompletionToken>
240 : BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken,
241 : void (system::error_code, std::size_t))
242 94 : async_write_some(
243 : AsyncWriteStream& dest,
244 : http::serializer& sr,
245 : CompletionToken&& token)
246 : {
247 : return asio::async_compose<
248 : CompletionToken,
249 94 : void(system::error_code, std::size_t)>(
250 : detail::write_some_op<
251 : AsyncWriteStream>{dest, sr},
252 94 : token, dest);
253 : }
254 :
255 : template<
256 : class AsyncWriteStream,
257 : BOOST_ASIO_COMPLETION_TOKEN_FOR(
258 : void(system::error_code, std::size_t)) CompletionToken>
259 : BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken,
260 : void (system::error_code, std::size_t))
261 5 : async_write(
262 : AsyncWriteStream& dest,
263 : http::serializer& sr,
264 : CompletionToken&& token)
265 : {
266 : return asio::async_compose<
267 : CompletionToken,
268 5 : void(system::error_code, std::size_t)>(
269 : detail::write_op<
270 : AsyncWriteStream>{dest, sr},
271 : token,
272 5 : dest);
273 : }
274 :
275 : #if 0
276 : template<
277 : class AsyncWriteStream,
278 : class AsyncReadStream,
279 : class CompletionCondition,
280 : BOOST_ASIO_COMPLETION_TOKEN_FOR(
281 : void(system::error_code, std::size_t)) CompletionToken>
282 : BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken,
283 : void (system::error_code, std::size_t))
284 : async_relay_some(
285 : AsyncWriteStream& dest,
286 : AsyncReadStream& src,
287 : CompletionCondition const& cond,
288 : http::serializer& sr,
289 : CompletionToken&& token)
290 : {
291 : return asio::async_compose<
292 : CompletionToken,
293 : void(system::error_code, std::size_t)>(
294 : detail::relay_some_op<
295 : AsyncWriteStream,
296 : AsyncReadStream,
297 : CompletionCondition>{
298 : dest, src, cond, sr},
299 : token,
300 : dest,
301 : src);
302 : }
303 : #endif
304 :
305 : } // beast2
306 : } // boost
307 :
308 : #endif
|