]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/beast/_experimental/http/impl/icy_stream.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / beast / _experimental / http / impl / icy_stream.hpp
CommitLineData
92f5a8d4
TL
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_CORE_IMPL_ICY_STREAM_HPP
11#define BOOST_BEAST_CORE_IMPL_ICY_STREAM_HPP
12
13#include <boost/beast/core/async_base.hpp>
14#include <boost/beast/core/buffer_traits.hpp>
15#include <boost/beast/core/error.hpp>
16#include <boost/beast/core/stream_traits.hpp>
17#include <boost/beast/core/detail/is_invocable.hpp>
18#include <boost/asio/coroutine.hpp>
19#include <boost/assert.hpp>
20#include <boost/throw_exception.hpp>
21#include <cstring>
22#include <memory>
23#include <utility>
24
25namespace boost {
26namespace beast {
27namespace http {
28
29namespace detail {
30
31template<class ConstBufferSequence>
32boost::tribool
33is_icy(ConstBufferSequence const& buffers)
34{
35 char buf[3];
36 auto const n = net::buffer_copy(
37 net::mutable_buffer(buf, 3),
38 buffers);
39 if(n >= 1 && buf[0] != 'I')
40 return false;
41 if(n >= 2 && buf[1] != 'C')
42 return false;
43 if(n >= 3 && buf[2] != 'Y')
44 return false;
45 if(n < 3)
46 return boost::indeterminate;
47 return true;
48}
49
50} // detail
51
52template<class NextLayer>
53struct icy_stream<NextLayer>::ops
54{
55
56template<class Buffers, class Handler>
57class read_op
58 : public beast::async_base<Handler,
59 beast::executor_type<icy_stream>>
60 , public asio::coroutine
61{
62 icy_stream& s_;
63 Buffers b_;
64 std::size_t n_ = 0;
65 error_code ec_;
66 bool match_ = false;
67
68public:
69 template<class Handler_>
70 read_op(
71 Handler_&& h,
72 icy_stream& s,
73 Buffers const& b)
74 : async_base<Handler,
75 beast::executor_type<icy_stream>>(
76 std::forward<Handler_>(h), s.get_executor())
77 , s_(s)
78 , b_(b)
79 {
80 (*this)({}, 0, false);
81 }
82
83 void
84 operator()(
85 error_code ec,
86 std::size_t bytes_transferred,
87 bool cont = true)
88 {
89 BOOST_ASIO_CORO_REENTER(*this)
90 {
91 if(s_.detect_)
92 {
93 BOOST_ASSERT(s_.n_ == 0);
94 for(;;)
95 {
96 // Try to read the first three characters
97 BOOST_ASIO_CORO_YIELD
20effc67
TL
98 {
99 BOOST_ASIO_HANDLER_LOCATION((
100 __FILE__, __LINE__,
101 "http::icy_stream::async_read_some"));
102
103 s_.next_layer().async_read_some(
104 net::mutable_buffer(
105 s_.buf_ + s_.n_, 3 - s_.n_),
106 std::move(*this));
107 }
92f5a8d4
TL
108 s_.n_ += static_cast<char>(bytes_transferred);
109 if(ec)
110 goto upcall;
111 auto result = detail::is_icy(
112 net::const_buffer(s_.buf_, s_.n_));
113 if(boost::indeterminate(result))
114 continue;
115 if(result)
116 s_.n_ = static_cast<char>(net::buffer_copy(
117 net::buffer(s_.buf_, sizeof(s_.buf_)),
118 icy_stream::version()));
119 break;
120 }
121 s_.detect_ = false;
122 }
123 if(s_.n_ > 0)
124 {
125 bytes_transferred = net::buffer_copy(
126 b_, net::const_buffer(s_.buf_, s_.n_));
127 s_.n_ -= static_cast<char>(bytes_transferred);
128 std::memmove(
129 s_.buf_,
130 s_.buf_ + bytes_transferred,
131 sizeof(s_.buf_) - bytes_transferred);
132 }
133 else
134 {
135 BOOST_ASIO_CORO_YIELD
20effc67
TL
136 {
137 BOOST_ASIO_HANDLER_LOCATION((
138 __FILE__, __LINE__,
139 "http::icy_stream::async_read_some"));
140
141 s_.next_layer().async_read_some(
142 b_, std::move(*this));
143 }
92f5a8d4
TL
144 }
145 upcall:
146 if(! cont)
147 {
148 ec_ = ec;
149 n_ = bytes_transferred;
150 BOOST_ASIO_CORO_YIELD
20effc67
TL
151 {
152 BOOST_ASIO_HANDLER_LOCATION((
153 __FILE__, __LINE__,
154 "http::icy_stream::async_read_some"));
155
156 s_.next_layer().async_read_some(
157 net::mutable_buffer{},
158 std::move(*this));
159 }
92f5a8d4
TL
160 ec = ec_;
161 bytes_transferred = n_;
162 }
163 this->complete_now(ec, bytes_transferred);
164 }
165 }
166};
167
168struct run_read_op
169{
170 template<class ReadHandler, class Buffers>
171 void
172 operator()(
173 ReadHandler&& h,
174 icy_stream* s,
175 Buffers const& b)
176 {
177 // If you get an error on the following line it means
178 // that your handler does not meet the documented type
179 // requirements for the handler.
180
181 static_assert(
182 beast::detail::is_invocable<ReadHandler,
183 void(error_code, std::size_t)>::value,
184 "ReadHandler type requirements not met");
185
186 read_op<
187 Buffers,
188 typename std::decay<ReadHandler>::type>(
189 std::forward<ReadHandler>(h), *s, b);
190 }
191};
192
193};
194
195//------------------------------------------------------------------------------
196
197template<class NextLayer>
198template<class... Args>
199icy_stream<NextLayer>::
200icy_stream(Args&&... args)
201 : stream_(std::forward<Args>(args)...)
202{
203 std::memset(buf_, 0, sizeof(buf_));
204}
205
206template<class NextLayer>
207template<class MutableBufferSequence>
208std::size_t
209icy_stream<NextLayer>::
210read_some(MutableBufferSequence const& buffers)
211{
212 static_assert(is_sync_read_stream<next_layer_type>::value,
213 "SyncReadStream type requirements not met");
214 static_assert(net::is_mutable_buffer_sequence<
215 MutableBufferSequence>::value,
216 "MutableBufferSequence type requirements not met");
217 error_code ec;
218 auto n = read_some(buffers, ec);
219 if(ec)
220 BOOST_THROW_EXCEPTION(system_error{ec});
221 return n;
222}
223
224template<class NextLayer>
225template<class MutableBufferSequence>
226std::size_t
227icy_stream<NextLayer>::
228read_some(MutableBufferSequence const& buffers, error_code& ec)
229{
230 static_assert(is_sync_read_stream<next_layer_type>::value,
231 "SyncReadStream type requirements not met");
232 static_assert(net::is_mutable_buffer_sequence<
233 MutableBufferSequence>::value,
234 "MutableBufferSequence type requirements not met");
235 std::size_t bytes_transferred;
236 if(detect_)
237 {
238 BOOST_ASSERT(n_ == 0);
239 for(;;)
240 {
241 // Try to read the first three characters
242 bytes_transferred = next_layer().read_some(
243 net::mutable_buffer(buf_ + n_, 3 - n_), ec);
244 n_ += static_cast<char>(bytes_transferred);
245 if(ec)
246 return 0;
247 auto result = detail::is_icy(
248 net::const_buffer(buf_, n_));
249 if(boost::indeterminate(result))
250 continue;
251 if(result)
252 n_ = static_cast<char>(net::buffer_copy(
253 net::buffer(buf_, sizeof(buf_)),
254 icy_stream::version()));
255 break;
256 }
257 detect_ = false;
258 }
259 if(n_ > 0)
260 {
261 bytes_transferred = net::buffer_copy(
262 buffers, net::const_buffer(buf_, n_));
263 n_ -= static_cast<char>(bytes_transferred);
264 std::memmove(
265 buf_,
266 buf_ + bytes_transferred,
267 sizeof(buf_) - bytes_transferred);
268 }
269 else
270 {
271 bytes_transferred =
272 next_layer().read_some(buffers, ec);
273 }
274 return bytes_transferred;
275}
276
277template<class NextLayer>
278template<
279 class MutableBufferSequence,
20effc67 280 BOOST_BEAST_ASYNC_TPARAM2 ReadHandler>
92f5a8d4
TL
281BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
282icy_stream<NextLayer>::
283async_read_some(
284 MutableBufferSequence const& buffers,
285 ReadHandler&& handler)
286{
287 static_assert(is_async_read_stream<next_layer_type>::value,
288 "AsyncReadStream type requirements not met");
289 static_assert(net::is_mutable_buffer_sequence<
290 MutableBufferSequence >::value,
291 "MutableBufferSequence type requirements not met");
292 return net::async_initiate<
293 ReadHandler,
294 void(error_code, std::size_t)>(
295 typename ops::run_read_op{},
296 handler,
297 this,
298 buffers);
299}
300
301template<class NextLayer>
302template<class MutableBufferSequence>
303std::size_t
304icy_stream<NextLayer>::
305write_some(MutableBufferSequence const& buffers)
306{
307 static_assert(is_sync_write_stream<next_layer_type>::value,
308 "SyncWriteStream type requirements not met");
309 static_assert(net::is_const_buffer_sequence<
310 MutableBufferSequence>::value,
311 "MutableBufferSequence type requirements not met");
312 return stream_.write_some(buffers);
313}
314
315template<class NextLayer>
316template<class MutableBufferSequence>
317std::size_t
318icy_stream<NextLayer>::
319write_some(MutableBufferSequence const& buffers, error_code& ec)
320{
321 static_assert(is_sync_write_stream<next_layer_type>::value,
322 "SyncWriteStream type requirements not met");
323 static_assert(net::is_const_buffer_sequence<
324 MutableBufferSequence>::value,
325 "MutableBufferSequence type requirements not met");
326 return stream_.write_some(buffers, ec);
327}
328
329template<class NextLayer>
330template<
331 class MutableBufferSequence,
20effc67 332 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
92f5a8d4
TL
333BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
334icy_stream<NextLayer>::
335async_write_some(
336 MutableBufferSequence const& buffers,
337 WriteHandler&& handler)
338{
339 static_assert(is_async_write_stream<next_layer_type>::value,
340 "AsyncWriteStream type requirements not met");
341 static_assert(net::is_const_buffer_sequence<
342 MutableBufferSequence>::value,
343 "MutableBufferSequence type requirements not met");
344 return stream_.async_write_some(
345 buffers, std::forward<WriteHandler>(handler));
346}
347
348} // http
349} // beast
350} // boost
351
352#endif