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