]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/beast/http/impl/write.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / beast / http / impl / write.hpp
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_HTTP_IMPL_WRITE_HPP
11 #define BOOST_BEAST_HTTP_IMPL_WRITE_HPP
12
13 #include <boost/beast/http/type_traits.hpp>
14 #include <boost/beast/core/async_base.hpp>
15 #include <boost/beast/core/bind_handler.hpp>
16 #include <boost/beast/core/buffers_range.hpp>
17 #include <boost/beast/core/make_printable.hpp>
18 #include <boost/beast/core/stream_traits.hpp>
19 #include <boost/beast/core/detail/is_invocable.hpp>
20 #include <boost/asio/coroutine.hpp>
21 #include <boost/asio/post.hpp>
22 #include <boost/asio/write.hpp>
23 #include <boost/optional.hpp>
24 #include <boost/throw_exception.hpp>
25 #include <ostream>
26 #include <sstream>
27
28 namespace boost {
29 namespace beast {
30 namespace http {
31 namespace detail {
32
33 template<
34 class Handler,
35 class Stream,
36 bool isRequest, class Body, class Fields>
37 class write_some_op
38 : public beast::async_base<
39 Handler, beast::executor_type<Stream>>
40 {
41 Stream& s_;
42 serializer<isRequest,Body, Fields>& sr_;
43
44 class lambda
45 {
46 write_some_op& op_;
47
48 public:
49 bool invoked = false;
50
51 explicit
52 lambda(write_some_op& op)
53 : op_(op)
54 {
55 }
56
57 template<class ConstBufferSequence>
58 void
59 operator()(
60 error_code& ec,
61 ConstBufferSequence const& buffers)
62 {
63 BOOST_ASIO_HANDLER_LOCATION((
64 __FILE__, __LINE__,
65 "http::async_write_some"));
66
67 invoked = true;
68 ec = {};
69 op_.s_.async_write_some(
70 buffers, std::move(op_));
71 }
72 };
73
74 public:
75 template<class Handler_>
76 write_some_op(
77 Handler_&& h,
78 Stream& s,
79 serializer<isRequest, Body, Fields>& sr)
80 : async_base<
81 Handler, beast::executor_type<Stream>>(
82 std::forward<Handler_>(h), s.get_executor())
83 , s_(s)
84 , sr_(sr)
85 {
86 (*this)();
87 }
88
89 void
90 operator()()
91 {
92 error_code ec;
93 if(! sr_.is_done())
94 {
95 lambda f{*this};
96 sr_.next(ec, f);
97 if(ec)
98 {
99 BOOST_ASSERT(! f.invoked);
100
101 BOOST_ASIO_HANDLER_LOCATION((
102 __FILE__, __LINE__,
103 "http::async_write_some"));
104
105 return net::post(
106 s_.get_executor(),
107 beast::bind_front_handler(
108 std::move(*this), ec, 0));
109 }
110 if(f.invoked)
111 {
112 // *this is now moved-from,
113 return;
114 }
115 // What else could it be?
116 BOOST_ASSERT(sr_.is_done());
117 }
118
119 BOOST_ASIO_HANDLER_LOCATION((
120 __FILE__, __LINE__,
121 "http::async_write_some"));
122
123 return net::post(
124 s_.get_executor(),
125 beast::bind_front_handler(
126 std::move(*this), ec, 0));
127 }
128
129 void
130 operator()(
131 error_code ec,
132 std::size_t bytes_transferred)
133 {
134 if(! ec)
135 sr_.consume(bytes_transferred);
136 this->complete_now(ec, bytes_transferred);
137 }
138 };
139
140 //------------------------------------------------------------------------------
141
142 struct serializer_is_header_done
143 {
144 template<
145 bool isRequest, class Body, class Fields>
146 bool
147 operator()(
148 serializer<isRequest, Body, Fields>& sr) const
149 {
150 return sr.is_header_done();
151 }
152 };
153
154 struct serializer_is_done
155 {
156 template<
157 bool isRequest, class Body, class Fields>
158 bool
159 operator()(
160 serializer<isRequest, Body, Fields>& sr) const
161 {
162 return sr.is_done();
163 }
164 };
165
166 //------------------------------------------------------------------------------
167
168 template<
169 class Handler,
170 class Stream,
171 class Predicate,
172 bool isRequest, class Body, class Fields>
173 class write_op
174 : public beast::async_base<
175 Handler, beast::executor_type<Stream>>
176 , public asio::coroutine
177 {
178 Stream& s_;
179 serializer<isRequest, Body, Fields>& sr_;
180 std::size_t bytes_transferred_ = 0;
181
182 public:
183 template<class Handler_>
184 write_op(
185 Handler_&& h,
186 Stream& s,
187 serializer<isRequest, Body, Fields>& sr)
188 : async_base<
189 Handler, beast::executor_type<Stream>>(
190 std::forward<Handler_>(h), s.get_executor())
191 , s_(s)
192 , sr_(sr)
193 {
194 (*this)();
195 }
196
197 void
198 operator()(
199 error_code ec = {},
200 std::size_t bytes_transferred = 0)
201 {
202 BOOST_ASIO_CORO_REENTER(*this)
203 {
204 if(Predicate{}(sr_))
205 {
206 BOOST_ASIO_CORO_YIELD
207 {
208 BOOST_ASIO_HANDLER_LOCATION((
209 __FILE__, __LINE__,
210 "http::async_write"));
211
212 net::post(
213 s_.get_executor(),
214 std::move(*this));
215 }
216 goto upcall;
217 }
218 for(;;)
219 {
220 BOOST_ASIO_CORO_YIELD
221 {
222 BOOST_ASIO_HANDLER_LOCATION((
223 __FILE__, __LINE__,
224 "http::async_write"));
225
226 beast::http::async_write_some(
227 s_, sr_, std::move(*this));
228 }
229 bytes_transferred_ += bytes_transferred;
230 if(ec)
231 goto upcall;
232 if(Predicate{}(sr_))
233 break;
234 }
235 upcall:
236 this->complete_now(ec, bytes_transferred_);
237 }
238 }
239 };
240
241 //------------------------------------------------------------------------------
242
243 template<
244 class Handler,
245 class Stream,
246 bool isRequest, class Body, class Fields>
247 class write_msg_op
248 : public beast::stable_async_base<
249 Handler, beast::executor_type<Stream>>
250 {
251 Stream& s_;
252 serializer<isRequest, Body, Fields>& sr_;
253
254 public:
255 template<
256 class Handler_,
257 class... Args>
258 write_msg_op(
259 Handler_&& h,
260 Stream& s,
261 Args&&... args)
262 : stable_async_base<
263 Handler, beast::executor_type<Stream>>(
264 std::forward<Handler_>(h), s.get_executor())
265 , s_(s)
266 , sr_(beast::allocate_stable<
267 serializer<isRequest, Body, Fields>>(
268 *this, std::forward<Args>(args)...))
269 {
270 (*this)();
271 }
272
273 void
274 operator()()
275 {
276 BOOST_ASIO_HANDLER_LOCATION((
277 __FILE__, __LINE__,
278 "http::async_write(msg)"));
279
280 async_write(s_, sr_, std::move(*this));
281 }
282
283 void
284 operator()(
285 error_code ec, std::size_t bytes_transferred)
286 {
287 this->complete_now(ec, bytes_transferred);
288 }
289 };
290
291 struct run_write_some_op
292 {
293 template<
294 class WriteHandler,
295 class Stream,
296 bool isRequest, class Body, class Fields>
297 void
298 operator()(
299 WriteHandler&& h,
300 Stream* s,
301 serializer<isRequest, Body, Fields>* sr)
302 {
303 // If you get an error on the following line it means
304 // that your handler does not meet the documented type
305 // requirements for the handler.
306
307 static_assert(
308 beast::detail::is_invocable<WriteHandler,
309 void(error_code, std::size_t)>::value,
310 "WriteHandler type requirements not met");
311
312 write_some_op<
313 typename std::decay<WriteHandler>::type,
314 Stream,
315 isRequest, Body, Fields>(
316 std::forward<WriteHandler>(h), *s, *sr);
317 }
318 };
319
320 struct run_write_op
321 {
322 template<
323 class WriteHandler,
324 class Stream,
325 class Predicate,
326 bool isRequest, class Body, class Fields>
327 void
328 operator()(
329 WriteHandler&& h,
330 Stream* s,
331 Predicate const&,
332 serializer<isRequest, Body, Fields>* sr)
333 {
334 // If you get an error on the following line it means
335 // that your handler does not meet the documented type
336 // requirements for the handler.
337
338 static_assert(
339 beast::detail::is_invocable<WriteHandler,
340 void(error_code, std::size_t)>::value,
341 "WriteHandler type requirements not met");
342
343 write_op<
344 typename std::decay<WriteHandler>::type,
345 Stream,
346 Predicate,
347 isRequest, Body, Fields>(
348 std::forward<WriteHandler>(h), *s, *sr);
349 }
350 };
351
352 struct run_write_msg_op
353 {
354 template<
355 class WriteHandler,
356 class Stream,
357 bool isRequest, class Body, class Fields,
358 class... Args>
359 void
360 operator()(
361 WriteHandler&& h,
362 Stream* s,
363 message<isRequest, Body, Fields>* m,
364 std::false_type,
365 Args&&... args)
366 {
367 // If you get an error on the following line it means
368 // that your handler does not meet the documented type
369 // requirements for the handler.
370
371 static_assert(
372 beast::detail::is_invocable<WriteHandler,
373 void(error_code, std::size_t)>::value,
374 "WriteHandler type requirements not met");
375
376 write_msg_op<
377 typename std::decay<WriteHandler>::type,
378 Stream,
379 isRequest, Body, Fields>(
380 std::forward<WriteHandler>(h), *s, *m,
381 std::forward<Args>(args)...);
382 }
383
384 template<
385 class WriteHandler,
386 class Stream,
387 bool isRequest, class Body, class Fields,
388 class... Args>
389 void
390 operator()(
391 WriteHandler&& h,
392 Stream* s,
393 message<isRequest, Body, Fields> const* m,
394 std::true_type,
395 Args&&... args)
396 {
397 // If you get an error on the following line it means
398 // that your handler does not meet the documented type
399 // requirements for the handler.
400
401 static_assert(
402 beast::detail::is_invocable<WriteHandler,
403 void(error_code, std::size_t)>::value,
404 "WriteHandler type requirements not met");
405
406 write_msg_op<
407 typename std::decay<WriteHandler>::type,
408 Stream,
409 isRequest, Body, Fields>(
410 std::forward<WriteHandler>(h), *s, *m,
411 std::forward<Args>(args)...);
412 }
413 };
414
415 //------------------------------------------------------------------------------
416
417 template<class Stream>
418 class write_some_lambda
419 {
420 Stream& stream_;
421
422 public:
423 bool invoked = false;
424 std::size_t bytes_transferred = 0;
425
426 explicit
427 write_some_lambda(Stream& stream)
428 : stream_(stream)
429 {
430 }
431
432 template<class ConstBufferSequence>
433 void
434 operator()(error_code& ec,
435 ConstBufferSequence const& buffers)
436 {
437 invoked = true;
438 bytes_transferred =
439 stream_.write_some(buffers, ec);
440 }
441 };
442
443 template<class Stream>
444 class write_lambda
445 {
446 Stream& stream_;
447
448 public:
449 bool invoked = false;
450 std::size_t bytes_transferred = 0;
451
452 explicit
453 write_lambda(Stream& stream)
454 : stream_(stream)
455 {
456 }
457
458 template<class ConstBufferSequence>
459 void
460 operator()(error_code& ec,
461 ConstBufferSequence const& buffers)
462 {
463 invoked = true;
464 bytes_transferred = net::write(
465 stream_, buffers, ec);
466 }
467 };
468
469 template<
470 class SyncWriteStream,
471 bool isRequest, class Body, class Fields>
472 std::size_t
473 write_some_impl(
474 SyncWriteStream& stream,
475 serializer<isRequest, Body, Fields>& sr,
476 error_code& ec)
477 {
478 if(! sr.is_done())
479 {
480 write_some_lambda<SyncWriteStream> f{stream};
481 sr.next(ec, f);
482 if(ec)
483 return f.bytes_transferred;
484 if(f.invoked)
485 sr.consume(f.bytes_transferred);
486 return f.bytes_transferred;
487 }
488 ec = {};
489 return 0;
490 }
491
492 template<
493 class AsyncWriteStream,
494 bool isRequest, class Body, class Fields,
495 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
496 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
497 async_write_some_impl(
498 AsyncWriteStream& stream,
499 serializer<isRequest, Body, Fields>& sr,
500 WriteHandler&& handler)
501 {
502 return net::async_initiate<
503 WriteHandler,
504 void(error_code, std::size_t)>(
505 run_write_some_op{},
506 handler,
507 &stream,
508 &sr);
509 }
510
511 } // detail
512
513 //------------------------------------------------------------------------------
514
515 template<
516 class SyncWriteStream,
517 bool isRequest, class Body, class Fields>
518 std::size_t
519 write_some(
520 SyncWriteStream& stream,
521 serializer<isRequest, Body, Fields>& sr)
522 {
523 static_assert(is_sync_write_stream<SyncWriteStream>::value,
524 "SyncWriteStream type requirements not met");
525 static_assert(is_body<Body>::value,
526 "Body type requirements not met");
527 static_assert(is_body_writer<Body>::value,
528 "BodyWriter type requirements not met");
529 error_code ec;
530 auto const bytes_transferred =
531 write_some(stream, sr, ec);
532 if(ec)
533 BOOST_THROW_EXCEPTION(system_error{ec});
534 return bytes_transferred;
535 }
536
537 template<
538 class SyncWriteStream,
539 bool isRequest, class Body, class Fields>
540 std::size_t
541 write_some(
542 SyncWriteStream& stream,
543 serializer<isRequest, Body, Fields>& sr,
544 error_code& ec)
545 {
546 static_assert(is_sync_write_stream<SyncWriteStream>::value,
547 "SyncWriteStream type requirements not met");
548 static_assert(is_body<Body>::value,
549 "Body type requirements not met");
550 static_assert(is_body_writer<Body>::value,
551 "BodyWriter type requirements not met");
552 return detail::write_some_impl(stream, sr, ec);
553 }
554
555 template<
556 class AsyncWriteStream,
557 bool isRequest, class Body, class Fields,
558 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
559 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
560 async_write_some(
561 AsyncWriteStream& stream,
562 serializer<isRequest, Body, Fields>& sr,
563 WriteHandler&& handler)
564 {
565 static_assert(is_async_write_stream<
566 AsyncWriteStream>::value,
567 "AsyncWriteStream type requirements not met");
568 static_assert(is_body<Body>::value,
569 "Body type requirements not met");
570 static_assert(is_body_writer<Body>::value,
571 "BodyWriter type requirements not met");
572 return detail::async_write_some_impl(stream, sr,
573 std::forward<WriteHandler>(handler));
574 }
575
576 //------------------------------------------------------------------------------
577
578 template<
579 class SyncWriteStream,
580 bool isRequest, class Body, class Fields>
581 std::size_t
582 write_header(SyncWriteStream& stream,
583 serializer<isRequest, Body, Fields>& sr)
584 {
585 static_assert(is_sync_write_stream<SyncWriteStream>::value,
586 "SyncWriteStream type requirements not met");
587 static_assert(is_body<Body>::value,
588 "Body type requirements not met");
589 static_assert(is_body_writer<Body>::value,
590 "BodyWriter type requirements not met");
591 error_code ec;
592 auto const bytes_transferred =
593 write_header(stream, sr, ec);
594 if(ec)
595 BOOST_THROW_EXCEPTION(system_error{ec});
596 return bytes_transferred;
597 }
598
599 template<
600 class SyncWriteStream,
601 bool isRequest, class Body, class Fields>
602 std::size_t
603 write_header(
604 SyncWriteStream& stream,
605 serializer<isRequest, Body, Fields>& sr,
606 error_code& ec)
607 {
608 static_assert(is_sync_write_stream<SyncWriteStream>::value,
609 "SyncWriteStream type requirements not met");
610 static_assert(is_body<Body>::value,
611 "Body type requirements not met");
612 static_assert(is_body_writer<Body>::value,
613 "BodyWriter type requirements not met");
614 sr.split(true);
615 std::size_t bytes_transferred = 0;
616 if(! sr.is_header_done())
617 {
618 detail::write_lambda<SyncWriteStream> f{stream};
619 do
620 {
621 sr.next(ec, f);
622 bytes_transferred += f.bytes_transferred;
623 if(ec)
624 return bytes_transferred;
625 BOOST_ASSERT(f.invoked);
626 sr.consume(f.bytes_transferred);
627 }
628 while(! sr.is_header_done());
629 }
630 else
631 {
632 ec = {};
633 }
634 return bytes_transferred;
635 }
636
637 template<
638 class AsyncWriteStream,
639 bool isRequest, class Body, class Fields,
640 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
641 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
642 async_write_header(
643 AsyncWriteStream& stream,
644 serializer<isRequest, Body, Fields>& sr,
645 WriteHandler&& handler)
646 {
647 static_assert(is_async_write_stream<
648 AsyncWriteStream>::value,
649 "AsyncWriteStream type requirements not met");
650 static_assert(is_body<Body>::value,
651 "Body type requirements not met");
652 static_assert(is_body_writer<Body>::value,
653 "BodyWriter type requirements not met");
654 sr.split(true);
655 return net::async_initiate<
656 WriteHandler,
657 void(error_code, std::size_t)>(
658 detail::run_write_op{},
659 handler,
660 &stream,
661 detail::serializer_is_header_done{},
662 &sr);
663 }
664
665 //------------------------------------------------------------------------------
666
667 template<
668 class SyncWriteStream,
669 bool isRequest, class Body, class Fields>
670 std::size_t
671 write(
672 SyncWriteStream& stream,
673 serializer<isRequest, Body, Fields>& sr)
674 {
675 static_assert(is_sync_write_stream<SyncWriteStream>::value,
676 "SyncWriteStream type requirements not met");
677 error_code ec;
678 auto const bytes_transferred =
679 write(stream, sr, ec);
680 if(ec)
681 BOOST_THROW_EXCEPTION(system_error{ec});
682 return bytes_transferred;
683 }
684
685 template<
686 class SyncWriteStream,
687 bool isRequest, class Body, class Fields>
688 std::size_t
689 write(
690 SyncWriteStream& stream,
691 serializer<isRequest, Body, Fields>& sr,
692 error_code& ec)
693 {
694 static_assert(is_sync_write_stream<SyncWriteStream>::value,
695 "SyncWriteStream type requirements not met");
696 std::size_t bytes_transferred = 0;
697 sr.split(false);
698 for(;;)
699 {
700 bytes_transferred +=
701 write_some(stream, sr, ec);
702 if(ec)
703 return bytes_transferred;
704 if(sr.is_done())
705 break;
706 }
707 return bytes_transferred;
708 }
709
710 template<
711 class AsyncWriteStream,
712 bool isRequest, class Body, class Fields,
713 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
714 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
715 async_write(
716 AsyncWriteStream& stream,
717 serializer<isRequest, Body, Fields>& sr,
718 WriteHandler&& handler)
719 {
720 static_assert(is_async_write_stream<
721 AsyncWriteStream>::value,
722 "AsyncWriteStream type requirements not met");
723 static_assert(is_body<Body>::value,
724 "Body type requirements not met");
725 static_assert(is_body_writer<Body>::value,
726 "BodyWriter type requirements not met");
727 sr.split(false);
728 return net::async_initiate<
729 WriteHandler,
730 void(error_code, std::size_t)>(
731 detail::run_write_op{},
732 handler,
733 &stream,
734 detail::serializer_is_done{},
735 &sr);
736 }
737
738 //------------------------------------------------------------------------------
739
740 template<
741 class SyncWriteStream,
742 bool isRequest, class Body, class Fields>
743 typename std::enable_if<
744 is_mutable_body_writer<Body>::value,
745 std::size_t>::type
746 write(
747 SyncWriteStream& stream,
748 message<isRequest, Body, Fields>& msg)
749 {
750 static_assert(is_sync_write_stream<SyncWriteStream>::value,
751 "SyncWriteStream type requirements not met");
752 static_assert(is_body<Body>::value,
753 "Body type requirements not met");
754 static_assert(is_body_writer<Body>::value,
755 "BodyWriter type requirements not met");
756 error_code ec;
757 auto const bytes_transferred =
758 write(stream, msg, ec);
759 if(ec)
760 BOOST_THROW_EXCEPTION(system_error{ec});
761 return bytes_transferred;
762 }
763
764 template<
765 class SyncWriteStream,
766 bool isRequest, class Body, class Fields>
767 typename std::enable_if<
768 ! is_mutable_body_writer<Body>::value,
769 std::size_t>::type
770 write(
771 SyncWriteStream& stream,
772 message<isRequest, Body, Fields> const& msg)
773 {
774 static_assert(is_sync_write_stream<SyncWriteStream>::value,
775 "SyncWriteStream type requirements not met");
776 static_assert(is_body<Body>::value,
777 "Body type requirements not met");
778 static_assert(is_body_writer<Body>::value,
779 "BodyWriter type requirements not met");
780 error_code ec;
781 auto const bytes_transferred =
782 write(stream, msg, ec);
783 if(ec)
784 BOOST_THROW_EXCEPTION(system_error{ec});
785 return bytes_transferred;
786 }
787
788 template<
789 class SyncWriteStream,
790 bool isRequest, class Body, class Fields>
791 typename std::enable_if<
792 is_mutable_body_writer<Body>::value,
793 std::size_t>::type
794 write(
795 SyncWriteStream& stream,
796 message<isRequest, Body, Fields>& msg,
797 error_code& ec)
798 {
799 static_assert(is_sync_write_stream<SyncWriteStream>::value,
800 "SyncWriteStream type requirements not met");
801 static_assert(is_body<Body>::value,
802 "Body type requirements not met");
803 static_assert(is_body_writer<Body>::value,
804 "BodyWriter type requirements not met");
805 serializer<isRequest, Body, Fields> sr{msg};
806 return write(stream, sr, ec);
807 }
808
809 template<
810 class SyncWriteStream,
811 bool isRequest, class Body, class Fields>
812 typename std::enable_if<
813 ! is_mutable_body_writer<Body>::value,
814 std::size_t>::type
815 write(
816 SyncWriteStream& stream,
817 message<isRequest, Body, Fields> const& msg,
818 error_code& ec)
819 {
820 static_assert(is_sync_write_stream<SyncWriteStream>::value,
821 "SyncWriteStream type requirements not met");
822 static_assert(is_body<Body>::value,
823 "Body type requirements not met");
824 static_assert(is_body_writer<Body>::value,
825 "BodyWriter type requirements not met");
826 serializer<isRequest, Body, Fields> sr{msg};
827 return write(stream, sr, ec);
828 }
829
830 template<
831 class AsyncWriteStream,
832 bool isRequest, class Body, class Fields,
833 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
834 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
835 async_write(
836 AsyncWriteStream& stream,
837 message<isRequest, Body, Fields>& msg,
838 WriteHandler&& handler,
839 typename std::enable_if<
840 is_mutable_body_writer<Body>::value>::type*)
841 {
842 static_assert(
843 is_async_write_stream<AsyncWriteStream>::value,
844 "AsyncWriteStream type requirements not met");
845 static_assert(is_body<Body>::value,
846 "Body type requirements not met");
847 static_assert(is_body_writer<Body>::value,
848 "BodyWriter type requirements not met");
849 return net::async_initiate<
850 WriteHandler,
851 void(error_code, std::size_t)>(
852 detail::run_write_msg_op{},
853 handler,
854 &stream,
855 &msg,
856 std::false_type{});
857 }
858
859 template<
860 class AsyncWriteStream,
861 bool isRequest, class Body, class Fields,
862 BOOST_BEAST_ASYNC_TPARAM2 WriteHandler>
863 BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
864 async_write(
865 AsyncWriteStream& stream,
866 message<isRequest, Body, Fields> const& msg,
867 WriteHandler&& handler,
868 typename std::enable_if<
869 ! is_mutable_body_writer<Body>::value>::type*)
870 {
871 static_assert(
872 is_async_write_stream<AsyncWriteStream>::value,
873 "AsyncWriteStream type requirements not met");
874 static_assert(is_body<Body>::value,
875 "Body type requirements not met");
876 static_assert(is_body_writer<Body>::value,
877 "BodyWriter type requirements not met");
878 return net::async_initiate<
879 WriteHandler,
880 void(error_code, std::size_t)>(
881 detail::run_write_msg_op{},
882 handler,
883 &stream,
884 &msg,
885 std::true_type{});
886 }
887
888 //------------------------------------------------------------------------------
889
890 namespace detail {
891
892 template<class Serializer>
893 class write_ostream_lambda
894 {
895 std::ostream& os_;
896 Serializer& sr_;
897
898 public:
899 write_ostream_lambda(std::ostream& os,
900 Serializer& sr)
901 : os_(os)
902 , sr_(sr)
903 {
904 }
905
906 template<class ConstBufferSequence>
907 void
908 operator()(error_code& ec,
909 ConstBufferSequence const& buffers) const
910 {
911 ec = {};
912 if(os_.fail())
913 return;
914 std::size_t bytes_transferred = 0;
915 for(auto b : beast::buffers_range_ref(buffers))
916 {
917 os_.write(static_cast<char const*>(
918 b.data()), b.size());
919 if(os_.fail())
920 return;
921 bytes_transferred += b.size();
922 }
923 sr_.consume(bytes_transferred);
924 }
925 };
926
927 } // detail
928
929 template<class Fields>
930 std::ostream&
931 operator<<(std::ostream& os,
932 header<true, Fields> const& h)
933 {
934 typename Fields::writer fr{
935 h, h.version(), h.method()};
936 return os << beast::make_printable(fr.get());
937 }
938
939 template<class Fields>
940 std::ostream&
941 operator<<(std::ostream& os,
942 header<false, Fields> const& h)
943 {
944 typename Fields::writer fr{
945 h, h.version(), h.result_int()};
946 return os << beast::make_printable(fr.get());
947 }
948
949 template<bool isRequest, class Body, class Fields>
950 std::ostream&
951 operator<<(std::ostream& os,
952 message<isRequest, Body, Fields> const& msg)
953 {
954 static_assert(is_body<Body>::value,
955 "Body type requirements not met");
956 static_assert(is_body_writer<Body>::value,
957 "BodyWriter type requirements not met");
958 serializer<isRequest, Body, Fields> sr{msg};
959 error_code ec;
960 detail::write_ostream_lambda<decltype(sr)> f{os, sr};
961 do
962 {
963 sr.next(ec, f);
964 if(os.fail())
965 break;
966 if(ec)
967 {
968 os.setstate(std::ios::failbit);
969 break;
970 }
971 }
972 while(! sr.is_done());
973 return os;
974 }
975
976 } // http
977 } // beast
978 } // boost
979
980 #endif