]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/http/impl/read.ipp
Add patch for failing prerm scripts
[ceph.git] / ceph / src / boost / boost / beast / http / impl / read.ipp
1 //
2 // Copyright (c) 2016-2017 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_HTTP_IMPL_READ_IPP_HPP
11 #define BOOST_BEAST_HTTP_IMPL_READ_IPP_HPP
12
13 #include <boost/beast/http/type_traits.hpp>
14 #include <boost/beast/http/error.hpp>
15 #include <boost/beast/http/parser.hpp>
16 #include <boost/beast/http/read.hpp>
17 #include <boost/beast/core/bind_handler.hpp>
18 #include <boost/beast/core/handler_ptr.hpp>
19 #include <boost/beast/core/read_size.hpp>
20 #include <boost/beast/core/type_traits.hpp>
21 #include <boost/asio/associated_allocator.hpp>
22 #include <boost/asio/associated_executor.hpp>
23 #include <boost/asio/coroutine.hpp>
24 #include <boost/asio/handler_continuation_hook.hpp>
25 #include <boost/asio/handler_invoke_hook.hpp>
26 #include <boost/asio/post.hpp>
27 #include <boost/assert.hpp>
28 #include <boost/config.hpp>
29 #include <boost/optional.hpp>
30 #include <boost/throw_exception.hpp>
31
32 namespace boost {
33 namespace beast {
34 namespace http {
35
36 namespace detail {
37
38 //------------------------------------------------------------------------------
39
40 template<class Stream, class DynamicBuffer,
41 bool isRequest, class Derived, class Handler>
42 class read_some_op
43 : public boost::asio::coroutine
44 {
45 Stream& s_;
46 DynamicBuffer& b_;
47 basic_parser<isRequest, Derived>& p_;
48 std::size_t bytes_transferred_ = 0;
49 Handler h_;
50 bool cont_ = false;
51
52 public:
53 read_some_op(read_some_op&&) = default;
54 read_some_op(read_some_op const&) = delete;
55
56 template<class DeducedHandler>
57 read_some_op(DeducedHandler&& h, Stream& s,
58 DynamicBuffer& b, basic_parser<isRequest, Derived>& p)
59 : s_(s)
60 , b_(b)
61 , p_(p)
62 , h_(std::forward<DeducedHandler>(h))
63 {
64 }
65
66 using allocator_type =
67 boost::asio::associated_allocator_t<Handler>;
68
69 allocator_type
70 get_allocator() const noexcept
71 {
72 return (boost::asio::get_associated_allocator)(h_);
73 }
74
75 using executor_type = boost::asio::associated_executor_t<
76 Handler, decltype(std::declval<Stream&>().get_executor())>;
77
78 executor_type
79 get_executor() const noexcept
80 {
81 return (boost::asio::get_associated_executor)(
82 h_, s_.get_executor());
83 }
84
85 void
86 operator()(
87 error_code ec,
88 std::size_t bytes_transferred = 0,
89 bool cont = true);
90
91 friend
92 bool asio_handler_is_continuation(read_some_op* op)
93 {
94 using boost::asio::asio_handler_is_continuation;
95 return op->cont_ ? true :
96 asio_handler_is_continuation(
97 std::addressof(op->h_));
98 }
99
100 template<class Function>
101 friend
102 void asio_handler_invoke(Function&& f, read_some_op* op)
103 {
104 using boost::asio::asio_handler_invoke;
105 asio_handler_invoke(f, std::addressof(op->h_));
106 }
107 };
108
109 template<class Stream, class DynamicBuffer,
110 bool isRequest, class Derived, class Handler>
111 void
112 read_some_op<Stream, DynamicBuffer,
113 isRequest, Derived, Handler>::
114 operator()(
115 error_code ec,
116 std::size_t bytes_transferred,
117 bool cont)
118 {
119 cont_ = cont;
120 boost::optional<typename
121 DynamicBuffer::mutable_buffers_type> mb;
122 BOOST_ASIO_CORO_REENTER(*this)
123 {
124 if(b_.size() == 0)
125 goto do_read;
126 for(;;)
127 {
128 // parse
129 {
130 auto const used = p_.put(b_.data(), ec);
131 bytes_transferred_ += used;
132 b_.consume(used);
133 }
134 if(ec != http::error::need_more)
135 break;
136
137 do_read:
138 try
139 {
140 mb.emplace(b_.prepare(
141 read_size_or_throw(b_, 65536)));
142 }
143 catch(std::length_error const&)
144 {
145 ec = error::buffer_overflow;
146 break;
147 }
148 BOOST_ASIO_CORO_YIELD
149 s_.async_read_some(*mb, std::move(*this));
150 if(ec == boost::asio::error::eof)
151 {
152 BOOST_ASSERT(bytes_transferred == 0);
153 if(p_.got_some())
154 {
155 // caller sees EOF on next read
156 ec.assign(0, ec.category());
157 p_.put_eof(ec);
158 if(ec)
159 goto upcall;
160 BOOST_ASSERT(p_.is_done());
161 goto upcall;
162 }
163 ec = error::end_of_stream;
164 break;
165 }
166 if(ec)
167 break;
168 b_.commit(bytes_transferred);
169 }
170
171 upcall:
172 if(! cont_)
173 return boost::asio::post(
174 s_.get_executor(),
175 bind_handler(std::move(h_),
176 ec, bytes_transferred_));
177 h_(ec, bytes_transferred_);
178 }
179 }
180
181 //------------------------------------------------------------------------------
182
183 struct parser_is_done
184 {
185 template<bool isRequest, class Derived>
186 bool
187 operator()(basic_parser<
188 isRequest, Derived> const& p) const
189 {
190 return p.is_done();
191 }
192 };
193
194 struct parser_is_header_done
195 {
196 template<bool isRequest, class Derived>
197 bool
198 operator()(basic_parser<
199 isRequest, Derived> const& p) const
200 {
201 return p.is_header_done();
202 }
203 };
204
205 template<class Stream, class DynamicBuffer,
206 bool isRequest, class Derived, class Condition,
207 class Handler>
208 class read_op
209 : public boost::asio::coroutine
210 {
211 Stream& s_;
212 DynamicBuffer& b_;
213 basic_parser<isRequest, Derived>& p_;
214 std::size_t bytes_transferred_ = 0;
215 Handler h_;
216 bool cont_ = false;
217
218 public:
219 read_op(read_op&&) = default;
220 read_op(read_op const&) = delete;
221
222 template<class DeducedHandler>
223 read_op(DeducedHandler&& h, Stream& s,
224 DynamicBuffer& b, basic_parser<isRequest,
225 Derived>& p)
226 : s_(s)
227 , b_(b)
228 , p_(p)
229 , h_(std::forward<DeducedHandler>(h))
230 {
231 }
232
233 using allocator_type =
234 boost::asio::associated_allocator_t<Handler>;
235
236 allocator_type
237 get_allocator() const noexcept
238 {
239 return (boost::asio::get_associated_allocator)(h_);
240 }
241
242 using executor_type = boost::asio::associated_executor_t<
243 Handler, decltype(std::declval<Stream&>().get_executor())>;
244
245 executor_type
246 get_executor() const noexcept
247 {
248 return (boost::asio::get_associated_executor)(
249 h_, s_.get_executor());
250 }
251
252 void
253 operator()(
254 error_code ec,
255 std::size_t bytes_transferred = 0,
256 bool cont = true);
257
258 friend
259 bool asio_handler_is_continuation(read_op* op)
260 {
261 using boost::asio::asio_handler_is_continuation;
262 return op->cont_ ? true :
263 asio_handler_is_continuation(
264 std::addressof(op->h_));
265 }
266
267 template<class Function>
268 friend
269 void asio_handler_invoke(Function&& f, read_op* op)
270 {
271 using boost::asio::asio_handler_invoke;
272 asio_handler_invoke(f, std::addressof(op->h_));
273 }
274 };
275
276 template<class Stream, class DynamicBuffer,
277 bool isRequest, class Derived, class Condition,
278 class Handler>
279 void
280 read_op<Stream, DynamicBuffer,
281 isRequest, Derived, Condition, Handler>::
282 operator()(
283 error_code ec,
284 std::size_t bytes_transferred,
285 bool cont)
286 {
287 cont_ = cont;
288 BOOST_ASIO_CORO_REENTER(*this)
289 {
290 if(Condition{}(p_))
291 {
292 BOOST_ASIO_CORO_YIELD
293 boost::asio::post(s_.get_executor(),
294 bind_handler(std::move(*this), ec));
295 goto upcall;
296 }
297 for(;;)
298 {
299 BOOST_ASIO_CORO_YIELD
300 async_read_some(
301 s_, b_, p_, std::move(*this));
302 if(ec)
303 goto upcall;
304 bytes_transferred_ += bytes_transferred;
305 if(Condition{}(p_))
306 goto upcall;
307 }
308 upcall:
309 h_(ec, bytes_transferred_);
310 }
311 }
312
313 //------------------------------------------------------------------------------
314
315 template<class Stream, class DynamicBuffer,
316 bool isRequest, class Body, class Allocator,
317 class Handler>
318 class read_msg_op
319 : public boost::asio::coroutine
320 {
321 using parser_type =
322 parser<isRequest, Body, Allocator>;
323
324 using message_type =
325 typename parser_type::value_type;
326
327 struct data
328 {
329 Stream& s;
330 DynamicBuffer& b;
331 message_type& m;
332 parser_type p;
333 std::size_t bytes_transferred = 0;
334 bool cont = false;
335
336 data(Handler const&, Stream& s_,
337 DynamicBuffer& b_, message_type& m_)
338 : s(s_)
339 , b(b_)
340 , m(m_)
341 , p(std::move(m))
342 {
343 p.eager(true);
344 }
345 };
346
347 handler_ptr<data, Handler> d_;
348
349 public:
350 read_msg_op(read_msg_op&&) = default;
351 read_msg_op(read_msg_op const&) = delete;
352
353 template<class DeducedHandler, class... Args>
354 read_msg_op(DeducedHandler&& h, Stream& s, Args&&... args)
355 : d_(std::forward<DeducedHandler>(h),
356 s, std::forward<Args>(args)...)
357 {
358 }
359
360 using allocator_type =
361 boost::asio::associated_allocator_t<Handler>;
362
363 allocator_type
364 get_allocator() const noexcept
365 {
366 return (boost::asio::get_associated_allocator)(d_.handler());
367 }
368
369 using executor_type = boost::asio::associated_executor_t<
370 Handler, decltype(std::declval<Stream&>().get_executor())>;
371
372 executor_type
373 get_executor() const noexcept
374 {
375 return (boost::asio::get_associated_executor)(
376 d_.handler(), d_->s.get_executor());
377 }
378
379 void
380 operator()(
381 error_code ec,
382 std::size_t bytes_transferred = 0,
383 bool cont = true);
384
385 friend
386 bool asio_handler_is_continuation(read_msg_op* op)
387 {
388 using boost::asio::asio_handler_is_continuation;
389 return op->d_->cont ? true :
390 asio_handler_is_continuation(
391 std::addressof(op->d_.handler()));
392 }
393
394 template<class Function>
395 friend
396 void asio_handler_invoke(Function&& f, read_msg_op* op)
397 {
398 using boost::asio::asio_handler_invoke;
399 asio_handler_invoke(f, std::addressof(op->d_.handler()));
400 }
401 };
402
403 template<class Stream, class DynamicBuffer,
404 bool isRequest, class Body, class Allocator,
405 class Handler>
406 void
407 read_msg_op<Stream, DynamicBuffer,
408 isRequest, Body, Allocator, Handler>::
409 operator()(
410 error_code ec,
411 std::size_t bytes_transferred,
412 bool cont)
413 {
414 auto& d = *d_;
415 d.cont = cont;
416 BOOST_ASIO_CORO_REENTER(*this)
417 {
418 for(;;)
419 {
420 BOOST_ASIO_CORO_YIELD
421 async_read_some(
422 d.s, d.b, d.p, std::move(*this));
423 if(ec)
424 goto upcall;
425 d.bytes_transferred +=
426 bytes_transferred;
427 if(d.p.is_done())
428 {
429 d.m = d.p.release();
430 goto upcall;
431 }
432 }
433 upcall:
434 bytes_transferred = d.bytes_transferred;
435 d_.invoke(ec, bytes_transferred);
436 }
437 }
438
439 } // detail
440
441 //------------------------------------------------------------------------------
442
443 template<
444 class SyncReadStream,
445 class DynamicBuffer,
446 bool isRequest, class Derived>
447 std::size_t
448 read_some(
449 SyncReadStream& stream,
450 DynamicBuffer& buffer,
451 basic_parser<isRequest, Derived>& parser)
452 {
453 static_assert(is_sync_read_stream<SyncReadStream>::value,
454 "SyncReadStream requirements not met");
455 static_assert(
456 boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
457 "DynamicBuffer requirements not met");
458 BOOST_ASSERT(! parser.is_done());
459 error_code ec;
460 auto const bytes_transferred =
461 read_some(stream, buffer, parser, ec);
462 if(ec)
463 BOOST_THROW_EXCEPTION(system_error{ec});
464 return bytes_transferred;
465 }
466
467 template<
468 class SyncReadStream,
469 class DynamicBuffer,
470 bool isRequest, class Derived>
471 std::size_t
472 read_some(
473 SyncReadStream& stream,
474 DynamicBuffer& buffer,
475 basic_parser<isRequest, Derived>& parser,
476 error_code& ec)
477 {
478 static_assert(is_sync_read_stream<SyncReadStream>::value,
479 "SyncReadStream requirements not met");
480 static_assert(
481 boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
482 "DynamicBuffer requirements not met");
483 BOOST_ASSERT(! parser.is_done());
484 std::size_t bytes_transferred = 0;
485 if(buffer.size() == 0)
486 goto do_read;
487 for(;;)
488 {
489 // invoke parser
490 {
491 auto const n = parser.put(buffer.data(), ec);
492 bytes_transferred += n;
493 buffer.consume(n);
494 if(! ec)
495 break;
496 if(ec != http::error::need_more)
497 break;
498 }
499 do_read:
500 boost::optional<typename
501 DynamicBuffer::mutable_buffers_type> b;
502 try
503 {
504 b.emplace(buffer.prepare(
505 read_size_or_throw(buffer, 65536)));
506 }
507 catch(std::length_error const&)
508 {
509 ec = error::buffer_overflow;
510 return bytes_transferred;
511 }
512 auto const n = stream.read_some(*b, ec);
513 if(ec == boost::asio::error::eof)
514 {
515 BOOST_ASSERT(n == 0);
516 if(parser.got_some())
517 {
518 // caller sees EOF on next read
519 parser.put_eof(ec);
520 if(ec)
521 break;
522 BOOST_ASSERT(parser.is_done());
523 break;
524 }
525 ec = error::end_of_stream;
526 break;
527 }
528 if(ec)
529 break;
530 buffer.commit(n);
531 }
532 return bytes_transferred;
533 }
534
535 template<
536 class AsyncReadStream,
537 class DynamicBuffer,
538 bool isRequest, class Derived,
539 class ReadHandler>
540 BOOST_ASIO_INITFN_RESULT_TYPE(
541 ReadHandler, void(error_code, std::size_t))
542 async_read_some(
543 AsyncReadStream& stream,
544 DynamicBuffer& buffer,
545 basic_parser<isRequest, Derived>& parser,
546 ReadHandler&& handler)
547 {
548 static_assert(is_async_read_stream<AsyncReadStream>::value,
549 "AsyncReadStream requirements not met");
550 static_assert(
551 boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
552 "DynamicBuffer requirements not met");
553 BOOST_ASSERT(! parser.is_done());
554 BOOST_BEAST_HANDLER_INIT(
555 ReadHandler, void(error_code, std::size_t));
556 detail::read_some_op<AsyncReadStream,
557 DynamicBuffer, isRequest, Derived, BOOST_ASIO_HANDLER_TYPE(
558 ReadHandler, void(error_code, std::size_t))>{
559 std::move(init.completion_handler), stream, buffer, parser}(
560 {}, 0, false);
561 return init.result.get();
562 }
563
564 //------------------------------------------------------------------------------
565
566 template<
567 class SyncReadStream,
568 class DynamicBuffer,
569 bool isRequest, class Derived>
570 std::size_t
571 read_header(
572 SyncReadStream& stream,
573 DynamicBuffer& buffer,
574 basic_parser<isRequest, Derived>& parser)
575 {
576 static_assert(is_sync_read_stream<SyncReadStream>::value,
577 "SyncReadStream requirements not met");
578 static_assert(
579 boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
580 "DynamicBuffer requirements not met");
581 error_code ec;
582 auto const bytes_transferred =
583 read_header(stream, buffer, parser, ec);
584 if(ec)
585 BOOST_THROW_EXCEPTION(system_error{ec});
586 return bytes_transferred;
587 }
588
589 template<
590 class SyncReadStream,
591 class DynamicBuffer,
592 bool isRequest, class Derived>
593 std::size_t
594 read_header(
595 SyncReadStream& stream,
596 DynamicBuffer& buffer,
597 basic_parser<isRequest, Derived>& parser,
598 error_code& ec)
599 {
600 static_assert(is_sync_read_stream<SyncReadStream>::value,
601 "SyncReadStream requirements not met");
602 static_assert(
603 boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
604 "DynamicBuffer requirements not met");
605 parser.eager(false);
606 if(parser.is_header_done())
607 {
608 ec.assign(0, ec.category());
609 return 0;
610 }
611 std::size_t bytes_transferred = 0;
612 do
613 {
614 bytes_transferred += read_some(
615 stream, buffer, parser, ec);
616 if(ec)
617 return bytes_transferred;
618 }
619 while(! parser.is_header_done());
620 return bytes_transferred;
621 }
622
623 template<
624 class AsyncReadStream,
625 class DynamicBuffer,
626 bool isRequest, class Derived,
627 class ReadHandler>
628 BOOST_ASIO_INITFN_RESULT_TYPE(
629 ReadHandler, void(error_code, std::size_t))
630 async_read_header(
631 AsyncReadStream& stream,
632 DynamicBuffer& buffer,
633 basic_parser<isRequest, Derived>& parser,
634 ReadHandler&& handler)
635 {
636 static_assert(is_async_read_stream<AsyncReadStream>::value,
637 "AsyncReadStream requirements not met");
638 static_assert(
639 boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
640 "DynamicBuffer requirements not met");
641 parser.eager(false);
642 BOOST_BEAST_HANDLER_INIT(
643 ReadHandler, void(error_code, std::size_t));
644 detail::read_op<AsyncReadStream, DynamicBuffer,
645 isRequest, Derived, detail::parser_is_header_done,
646 BOOST_ASIO_HANDLER_TYPE(ReadHandler, void(error_code, std::size_t))>{
647 std::move(init.completion_handler), stream,
648 buffer, parser}({}, 0, false);
649 return init.result.get();
650 }
651
652 //------------------------------------------------------------------------------
653
654 template<
655 class SyncReadStream,
656 class DynamicBuffer,
657 bool isRequest, class Derived>
658 std::size_t
659 read(
660 SyncReadStream& stream,
661 DynamicBuffer& buffer,
662 basic_parser<isRequest, Derived>& parser)
663 {
664 static_assert(is_sync_read_stream<SyncReadStream>::value,
665 "SyncReadStream requirements not met");
666 static_assert(
667 boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
668 "DynamicBuffer requirements not met");
669 error_code ec;
670 auto const bytes_transferred =
671 read(stream, buffer, parser, ec);
672 if(ec)
673 BOOST_THROW_EXCEPTION(system_error{ec});
674 return bytes_transferred;
675 }
676
677 template<
678 class SyncReadStream,
679 class DynamicBuffer,
680 bool isRequest, class Derived>
681 std::size_t
682 read(
683 SyncReadStream& stream,
684 DynamicBuffer& buffer,
685 basic_parser<isRequest, Derived>& parser,
686 error_code& ec)
687 {
688 static_assert(is_sync_read_stream<SyncReadStream>::value,
689 "SyncReadStream requirements not met");
690 static_assert(
691 boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
692 "DynamicBuffer requirements not met");
693 parser.eager(true);
694 if(parser.is_done())
695 {
696 ec.assign(0, ec.category());
697 return 0;
698 }
699 std::size_t bytes_transferred = 0;
700 do
701 {
702 bytes_transferred += read_some(
703 stream, buffer, parser, ec);
704 if(ec)
705 return bytes_transferred;
706 }
707 while(! parser.is_done());
708 return bytes_transferred;
709 }
710
711 template<
712 class AsyncReadStream,
713 class DynamicBuffer,
714 bool isRequest, class Derived,
715 class ReadHandler>
716 BOOST_ASIO_INITFN_RESULT_TYPE(
717 ReadHandler, void(error_code, std::size_t))
718 async_read(
719 AsyncReadStream& stream,
720 DynamicBuffer& buffer,
721 basic_parser<isRequest, Derived>& parser,
722 ReadHandler&& handler)
723 {
724 static_assert(is_async_read_stream<AsyncReadStream>::value,
725 "AsyncReadStream requirements not met");
726 static_assert(
727 boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
728 "DynamicBuffer requirements not met");
729 parser.eager(true);
730 BOOST_BEAST_HANDLER_INIT(
731 ReadHandler, void(error_code, std::size_t));
732 detail::read_op<AsyncReadStream, DynamicBuffer,
733 isRequest, Derived, detail::parser_is_done,
734 BOOST_ASIO_HANDLER_TYPE(ReadHandler, void(error_code, std::size_t))>{
735 std::move(init.completion_handler), stream, buffer, parser}(
736 {}, 0, false);
737 return init.result.get();
738 }
739
740 //------------------------------------------------------------------------------
741
742 template<
743 class SyncReadStream,
744 class DynamicBuffer,
745 bool isRequest, class Body, class Allocator>
746 std::size_t
747 read(
748 SyncReadStream& stream,
749 DynamicBuffer& buffer,
750 message<isRequest, Body, basic_fields<Allocator>>& msg)
751 {
752 static_assert(is_sync_read_stream<SyncReadStream>::value,
753 "SyncReadStream requirements not met");
754 static_assert(
755 boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
756 "DynamicBuffer requirements not met");
757 static_assert(is_body<Body>::value,
758 "Body requirements not met");
759 static_assert(is_body_reader<Body>::value,
760 "BodyReader requirements not met");
761 error_code ec;
762 auto const bytes_transferred =
763 read(stream, buffer, msg, ec);
764 if(ec)
765 BOOST_THROW_EXCEPTION(system_error{ec});
766 return bytes_transferred;
767 }
768
769 template<
770 class SyncReadStream,
771 class DynamicBuffer,
772 bool isRequest, class Body, class Allocator>
773 std::size_t
774 read(
775 SyncReadStream& stream,
776 DynamicBuffer& buffer,
777 message<isRequest, Body, basic_fields<Allocator>>& msg,
778 error_code& ec)
779 {
780 static_assert(is_sync_read_stream<SyncReadStream>::value,
781 "SyncReadStream requirements not met");
782 static_assert(
783 boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
784 "DynamicBuffer requirements not met");
785 static_assert(is_body<Body>::value,
786 "Body requirements not met");
787 static_assert(is_body_reader<Body>::value,
788 "BodyReader requirements not met");
789 parser<isRequest, Body, Allocator> p{std::move(msg)};
790 p.eager(true);
791 auto const bytes_transferred =
792 read(stream, buffer, p.base(), ec);
793 if(ec)
794 return bytes_transferred;
795 msg = p.release();
796 return bytes_transferred;
797 }
798
799 template<
800 class AsyncReadStream,
801 class DynamicBuffer,
802 bool isRequest, class Body, class Allocator,
803 class ReadHandler>
804 BOOST_ASIO_INITFN_RESULT_TYPE(
805 ReadHandler, void(error_code, std::size_t))
806 async_read(
807 AsyncReadStream& stream,
808 DynamicBuffer& buffer,
809 message<isRequest, Body, basic_fields<Allocator>>& msg,
810 ReadHandler&& handler)
811 {
812 static_assert(is_async_read_stream<AsyncReadStream>::value,
813 "AsyncReadStream requirements not met");
814 static_assert(
815 boost::asio::is_dynamic_buffer<DynamicBuffer>::value,
816 "DynamicBuffer requirements not met");
817 static_assert(is_body<Body>::value,
818 "Body requirements not met");
819 static_assert(is_body_reader<Body>::value,
820 "BodyReader requirements not met");
821 BOOST_BEAST_HANDLER_INIT(
822 ReadHandler, void(error_code, std::size_t));
823 detail::read_msg_op<
824 AsyncReadStream,
825 DynamicBuffer,
826 isRequest, Body, Allocator,
827 BOOST_ASIO_HANDLER_TYPE(
828 ReadHandler, void(error_code, std::size_t))>{
829 std::move(init.completion_handler), stream, buffer, msg}(
830 {}, 0, false);
831 return init.result.get();
832 }
833
834 } // http
835 } // beast
836 } // boost
837
838 #endif