]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/beast/http/impl/read.ipp
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / boost / beast / http / impl / read.ipp
CommitLineData
b32b8144
FG
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>
11fdf7f2 23#include <boost/asio/coroutine.hpp>
b32b8144 24#include <boost/asio/handler_continuation_hook.hpp>
11fdf7f2 25#include <boost/asio/handler_invoke_hook.hpp>
b32b8144
FG
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
32namespace boost {
33namespace beast {
34namespace http {
35
36namespace detail {
37
38//------------------------------------------------------------------------------
39
40template<class Stream, class DynamicBuffer,
41 bool isRequest, class Derived, class Handler>
42class read_some_op
11fdf7f2 43 : public boost::asio::coroutine
b32b8144 44{
b32b8144
FG
45 Stream& s_;
46 DynamicBuffer& b_;
47 basic_parser<isRequest, Derived>& p_;
b32b8144
FG
48 std::size_t bytes_transferred_ = 0;
49 Handler h_;
11fdf7f2 50 bool cont_ = false;
b32b8144
FG
51
52public:
53 read_some_op(read_some_op&&) = default;
11fdf7f2 54 read_some_op(read_some_op const&) = delete;
b32b8144
FG
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 {
11fdf7f2 72 return (boost::asio::get_associated_allocator)(h_);
b32b8144
FG
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 {
11fdf7f2 81 return (boost::asio::get_associated_executor)(
b32b8144
FG
82 h_, s_.get_executor());
83 }
84
85 void
86 operator()(
11fdf7f2
TL
87 error_code ec,
88 std::size_t bytes_transferred = 0,
89 bool cont = true);
b32b8144
FG
90
91 friend
92 bool asio_handler_is_continuation(read_some_op* op)
93 {
94 using boost::asio::asio_handler_is_continuation;
11fdf7f2 95 return op->cont_ ? true :
b32b8144
FG
96 asio_handler_is_continuation(
97 std::addressof(op->h_));
98 }
11fdf7f2
TL
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 }
b32b8144
FG
107};
108
109template<class Stream, class DynamicBuffer,
110 bool isRequest, class Derived, class Handler>
111void
112read_some_op<Stream, DynamicBuffer,
113 isRequest, Derived, Handler>::
114operator()(
115 error_code ec,
11fdf7f2
TL
116 std::size_t bytes_transferred,
117 bool cont)
b32b8144 118{
11fdf7f2
TL
119 cont_ = cont;
120 boost::optional<typename
121 DynamicBuffer::mutable_buffers_type> mb;
122 BOOST_ASIO_CORO_REENTER(*this)
b32b8144 123 {
b32b8144
FG
124 if(b_.size() == 0)
125 goto do_read;
11fdf7f2 126 for(;;)
b32b8144 127 {
11fdf7f2 128 // parse
b32b8144 129 {
11fdf7f2
TL
130 auto const used = p_.put(b_.data(), ec);
131 bytes_transferred_ += used;
132 b_.consume(used);
b32b8144 133 }
11fdf7f2
TL
134 if(ec != http::error::need_more)
135 break;
b32b8144 136
11fdf7f2
TL
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);
b32b8144 169 }
b32b8144 170
11fdf7f2
TL
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_);
b32b8144 178 }
b32b8144
FG
179}
180
181//------------------------------------------------------------------------------
182
183struct 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
194struct 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
205template<class Stream, class DynamicBuffer,
206 bool isRequest, class Derived, class Condition,
207 class Handler>
208class read_op
11fdf7f2 209 : public boost::asio::coroutine
b32b8144 210{
b32b8144
FG
211 Stream& s_;
212 DynamicBuffer& b_;
213 basic_parser<isRequest, Derived>& p_;
214 std::size_t bytes_transferred_ = 0;
215 Handler h_;
11fdf7f2 216 bool cont_ = false;
b32b8144
FG
217
218public:
219 read_op(read_op&&) = default;
11fdf7f2 220 read_op(read_op const&) = delete;
b32b8144
FG
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 {
11fdf7f2 239 return (boost::asio::get_associated_allocator)(h_);
b32b8144
FG
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 {
11fdf7f2 248 return (boost::asio::get_associated_executor)(
b32b8144
FG
249 h_, s_.get_executor());
250 }
251
252 void
253 operator()(
11fdf7f2
TL
254 error_code ec,
255 std::size_t bytes_transferred = 0,
256 bool cont = true);
b32b8144
FG
257
258 friend
259 bool asio_handler_is_continuation(read_op* op)
260 {
261 using boost::asio::asio_handler_is_continuation;
11fdf7f2 262 return op->cont_ ? true :
b32b8144
FG
263 asio_handler_is_continuation(
264 std::addressof(op->h_));
265 }
11fdf7f2
TL
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 }
b32b8144
FG
274};
275
276template<class Stream, class DynamicBuffer,
277 bool isRequest, class Derived, class Condition,
278 class Handler>
279void
280read_op<Stream, DynamicBuffer,
281 isRequest, Derived, Condition, Handler>::
282operator()(
283 error_code ec,
11fdf7f2
TL
284 std::size_t bytes_transferred,
285 bool cont)
b32b8144 286{
11fdf7f2
TL
287 cont_ = cont;
288 BOOST_ASIO_CORO_REENTER(*this)
b32b8144 289 {
b32b8144
FG
290 if(Condition{}(p_))
291 {
11fdf7f2
TL
292 BOOST_ASIO_CORO_YIELD
293 boost::asio::post(s_.get_executor(),
b32b8144 294 bind_handler(std::move(*this), ec));
b32b8144 295 goto upcall;
11fdf7f2
TL
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_);
b32b8144 310 }
b32b8144
FG
311}
312
313//------------------------------------------------------------------------------
314
315template<class Stream, class DynamicBuffer,
316 bool isRequest, class Body, class Allocator,
317 class Handler>
318class read_msg_op
11fdf7f2 319 : public boost::asio::coroutine
b32b8144
FG
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 {
b32b8144
FG
329 Stream& s;
330 DynamicBuffer& b;
331 message_type& m;
332 parser_type p;
333 std::size_t bytes_transferred = 0;
11fdf7f2 334 bool cont = false;
b32b8144 335
11fdf7f2 336 data(Handler const&, Stream& s_,
b32b8144
FG
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
349public:
350 read_msg_op(read_msg_op&&) = default;
11fdf7f2 351 read_msg_op(read_msg_op const&) = delete;
b32b8144
FG
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 {
11fdf7f2 366 return (boost::asio::get_associated_allocator)(d_.handler());
b32b8144
FG
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 {
11fdf7f2 375 return (boost::asio::get_associated_executor)(
b32b8144
FG
376 d_.handler(), d_->s.get_executor());
377 }
378
379 void
380 operator()(
11fdf7f2
TL
381 error_code ec,
382 std::size_t bytes_transferred = 0,
383 bool cont = true);
b32b8144
FG
384
385 friend
386 bool asio_handler_is_continuation(read_msg_op* op)
387 {
388 using boost::asio::asio_handler_is_continuation;
11fdf7f2 389 return op->d_->cont ? true :
b32b8144
FG
390 asio_handler_is_continuation(
391 std::addressof(op->d_.handler()));
392 }
11fdf7f2
TL
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 }
b32b8144
FG
401};
402
403template<class Stream, class DynamicBuffer,
404 bool isRequest, class Body, class Allocator,
405 class Handler>
406void
407read_msg_op<Stream, DynamicBuffer,
408 isRequest, Body, Allocator, Handler>::
409operator()(
410 error_code ec,
11fdf7f2
TL
411 std::size_t bytes_transferred,
412 bool cont)
b32b8144
FG
413{
414 auto& d = *d_;
11fdf7f2
TL
415 d.cont = cont;
416 BOOST_ASIO_CORO_REENTER(*this)
b32b8144 417 {
11fdf7f2 418 for(;;)
b32b8144 419 {
11fdf7f2
TL
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 }
b32b8144 432 }
11fdf7f2
TL
433 upcall:
434 bytes_transferred = d.bytes_transferred;
435 d_.invoke(ec, bytes_transferred);
b32b8144 436 }
b32b8144
FG
437}
438
439} // detail
440
441//------------------------------------------------------------------------------
442
443template<
444 class SyncReadStream,
445 class DynamicBuffer,
446 bool isRequest, class Derived>
447std::size_t
448read_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
467template<
468 class SyncReadStream,
469 class DynamicBuffer,
470 bool isRequest, class Derived>
471std::size_t
472read_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
535template<
536 class AsyncReadStream,
537 class DynamicBuffer,
538 bool isRequest, class Derived,
539 class ReadHandler>
540BOOST_ASIO_INITFN_RESULT_TYPE(
541 ReadHandler, void(error_code, std::size_t))
542async_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());
11fdf7f2
TL
554 BOOST_BEAST_HANDLER_INIT(
555 ReadHandler, void(error_code, std::size_t));
b32b8144
FG
556 detail::read_some_op<AsyncReadStream,
557 DynamicBuffer, isRequest, Derived, BOOST_ASIO_HANDLER_TYPE(
558 ReadHandler, void(error_code, std::size_t))>{
11fdf7f2
TL
559 std::move(init.completion_handler), stream, buffer, parser}(
560 {}, 0, false);
b32b8144
FG
561 return init.result.get();
562}
563
564//------------------------------------------------------------------------------
565
566template<
567 class SyncReadStream,
568 class DynamicBuffer,
569 bool isRequest, class Derived>
570std::size_t
571read_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
589template<
590 class SyncReadStream,
591 class DynamicBuffer,
592 bool isRequest, class Derived>
593std::size_t
594read_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
623template<
624 class AsyncReadStream,
625 class DynamicBuffer,
626 bool isRequest, class Derived,
627 class ReadHandler>
628BOOST_ASIO_INITFN_RESULT_TYPE(
629 ReadHandler, void(error_code, std::size_t))
630async_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);
11fdf7f2
TL
642 BOOST_BEAST_HANDLER_INIT(
643 ReadHandler, void(error_code, std::size_t));
b32b8144
FG
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))>{
11fdf7f2
TL
647 std::move(init.completion_handler), stream,
648 buffer, parser}({}, 0, false);
b32b8144
FG
649 return init.result.get();
650}
651
652//------------------------------------------------------------------------------
653
654template<
655 class SyncReadStream,
656 class DynamicBuffer,
657 bool isRequest, class Derived>
658std::size_t
659read(
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
677template<
678 class SyncReadStream,
679 class DynamicBuffer,
680 bool isRequest, class Derived>
681std::size_t
682read(
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
711template<
712 class AsyncReadStream,
713 class DynamicBuffer,
714 bool isRequest, class Derived,
715 class ReadHandler>
716BOOST_ASIO_INITFN_RESULT_TYPE(
717 ReadHandler, void(error_code, std::size_t))
718async_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);
11fdf7f2
TL
730 BOOST_BEAST_HANDLER_INIT(
731 ReadHandler, void(error_code, std::size_t));
b32b8144
FG
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))>{
11fdf7f2
TL
735 std::move(init.completion_handler), stream, buffer, parser}(
736 {}, 0, false);
b32b8144
FG
737 return init.result.get();
738}
739
740//------------------------------------------------------------------------------
741
742template<
743 class SyncReadStream,
744 class DynamicBuffer,
745 bool isRequest, class Body, class Allocator>
746std::size_t
747read(
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
769template<
770 class SyncReadStream,
771 class DynamicBuffer,
772 bool isRequest, class Body, class Allocator>
773std::size_t
774read(
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
799template<
800 class AsyncReadStream,
801 class DynamicBuffer,
802 bool isRequest, class Body, class Allocator,
803 class ReadHandler>
804BOOST_ASIO_INITFN_RESULT_TYPE(
805 ReadHandler, void(error_code, std::size_t))
806async_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");
11fdf7f2
TL
821 BOOST_BEAST_HANDLER_INIT(
822 ReadHandler, void(error_code, std::size_t));
b32b8144
FG
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))>{
11fdf7f2
TL
829 std::move(init.completion_handler), stream, buffer, msg}(
830 {}, 0, false);
b32b8144
FG
831 return init.result.get();
832}
833
834} // http
835} // beast
836} // boost
837
838#endif