write.hpp 26 KB

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