write.hpp 27 KB

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