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