Line data Source code
1 : //
2 : // Copyright (c) 2025 Mungo Gill
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_BODY_READ_STREAM_HPP
11 : #define BOOST_BEAST2_IMPL_BODY_READ_STREAM_HPP
12 :
13 : #include <boost/beast2/detail/config.hpp>
14 : #include <boost/beast2/read.hpp>
15 :
16 : #include <boost/asio/buffer.hpp>
17 : #include <boost/asio/buffers_iterator.hpp>
18 : #include <boost/asio/coroutine.hpp>
19 : #include <boost/core/ignore_unused.hpp>
20 :
21 : #include <iostream>
22 :
23 : namespace boost {
24 : namespace beast2 {
25 :
26 : namespace detail {
27 :
28 : template<class MutableBufferSequence, class AsyncReadStream>
29 : class body_read_stream_op : public asio::coroutine
30 : {
31 :
32 : AsyncReadStream& stream_;
33 : MutableBufferSequence mb_;
34 : http_proto::parser& pr_;
35 :
36 : public:
37 730 : body_read_stream_op(
38 : AsyncReadStream& s,
39 : MutableBufferSequence&& mb,
40 : http_proto::parser& pr) noexcept
41 730 : : stream_(s)
42 730 : , mb_(std::move(mb))
43 730 : , pr_(pr)
44 : {
45 730 : }
46 :
47 : template<class Self>
48 : void
49 1552 : operator()(
50 : Self& self,
51 : system::error_code ec = {},
52 : std::size_t bytes_transferred = 0)
53 : {
54 : boost::ignore_unused(bytes_transferred);
55 :
56 3104 : BOOST_ASIO_CORO_REENTER(*this)
57 : {
58 730 : self.reset_cancellation_state(asio::enable_total_cancellation());
59 :
60 730 : if(!pr_.got_header())
61 : {
62 429 : BOOST_ASIO_CORO_YIELD
63 : {
64 : BOOST_ASIO_HANDLER_LOCATION(
65 : (__FILE__, __LINE__, "async_read_header"));
66 143 : beast2::async_read_header<AsyncReadStream, Self>(
67 143 : stream_, pr_, std::move(self));
68 : }
69 143 : if(ec.failed())
70 : {
71 39 : goto upcall;
72 : }
73 : }
74 :
75 691 : if(!!self.cancelled())
76 : {
77 12 : ec = asio::error::operation_aborted;
78 12 : goto upcall;
79 : }
80 :
81 2037 : BOOST_ASIO_CORO_YIELD
82 : {
83 : BOOST_ASIO_HANDLER_LOCATION(
84 : (__FILE__, __LINE__, "async_read_some"));
85 679 : beast2::async_read_some(stream_, pr_, std::move(self));
86 : }
87 :
88 730 : upcall:
89 730 : std::size_t n = 0;
90 :
91 730 : if(!ec.failed())
92 : {
93 678 : auto source_buf = pr_.pull_body();
94 :
95 678 : n = boost::asio::buffer_copy(mb_, source_buf);
96 :
97 678 : pr_.consume_body(n);
98 :
99 678 : ec = (n != 0) ? system::error_code{} : asio::stream_errc::eof;
100 : }
101 :
102 730 : self.complete(ec, n);
103 : }
104 1552 : }
105 : };
106 :
107 : } // detail
108 :
109 : //------------------------------------------------
110 :
111 : // TODO: copy in Beast's stream traits to check if AsyncReadStream
112 : // is an AsyncReadStream, and also static_assert that body_read_stream is too.
113 :
114 : template<class AsyncReadStream>
115 105 : body_read_stream<AsyncReadStream>::body_read_stream(
116 : AsyncReadStream& und_stream,
117 : http_proto::parser& pr)
118 105 : : stream_(und_stream)
119 105 : , pr_(pr)
120 : {
121 105 : }
122 :
123 : template<class AsyncReadStream>
124 : template<
125 : class MutableBufferSequence,
126 : BOOST_ASIO_COMPLETION_TOKEN_FOR(void(system::error_code, std::size_t))
127 : CompletionToken>
128 : BOOST_ASIO_INITFN_AUTO_RESULT_TYPE(
129 : CompletionToken,
130 : void(system::error_code, std::size_t))
131 730 : body_read_stream<AsyncReadStream>::async_read_some(
132 : MutableBufferSequence mb,
133 : CompletionToken&& token)
134 : {
135 : return asio::
136 730 : async_compose<CompletionToken, void(system::error_code, std::size_t)>(
137 : detail::body_read_stream_op<MutableBufferSequence, AsyncReadStream>{
138 730 : stream_, std::move(mb), pr_ },
139 : token,
140 730 : stream_);
141 : }
142 :
143 : } // beast2
144 : } // boost
145 :
146 : #endif // BOOST_BEAST2_IMPL_BODY_READ_STREAM_HPP
|