write.ipp 26 KB

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