read.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722
  1. //
  2. // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
  3. // Copyright (c) 2020 Richard Hodges (hodges.r@gmail.com)
  4. //
  5. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // Official repository: https://github.com/boostorg/beast
  9. //
  10. #ifndef BHO_BEAST_HTTP_IMPL_READ_HPP
  11. #define BHO_BEAST_HTTP_IMPL_READ_HPP
  12. #include <asio2/bho/beast/http/type_traits.hpp>
  13. #include <asio2/bho/beast/http/error.hpp>
  14. #include <asio2/bho/beast/http/parser.hpp>
  15. #include <asio2/bho/beast/http/read.hpp>
  16. #include <asio2/bho/beast/core/async_base.hpp>
  17. #include <asio2/bho/beast/core/stream_traits.hpp>
  18. #include <asio2/bho/beast/core/detail/buffer.hpp>
  19. #include <asio2/bho/beast/core/detail/read.hpp>
  20. #include <asio/error.hpp>
  21. #include <asio/compose.hpp>
  22. #include <asio/coroutine.hpp>
  23. namespace bho {
  24. namespace beast {
  25. namespace http {
  26. namespace detail {
  27. struct parser_is_done
  28. {
  29. template<bool isRequest>
  30. bool
  31. operator()(basic_parser<isRequest> const& p) const
  32. {
  33. return p.is_done();
  34. }
  35. };
  36. struct parser_is_header_done
  37. {
  38. template<bool isRequest>
  39. bool
  40. operator()(basic_parser<isRequest> const& p) const
  41. {
  42. return p.is_header_done();
  43. }
  44. };
  45. //------------------------------------------------------------------------------
  46. template<
  47. class Stream, class DynamicBuffer,
  48. bool isRequest, class Body, class Allocator,
  49. class Handler>
  50. class read_msg_op
  51. : public beast::stable_async_base<
  52. Handler, beast::executor_type<Stream>>
  53. , public asio::coroutine
  54. {
  55. using parser_type =
  56. parser<isRequest, Body, Allocator>;
  57. using message_type =
  58. typename parser_type::value_type;
  59. struct data
  60. {
  61. Stream& s;
  62. message_type& m;
  63. parser_type p;
  64. data(
  65. Stream& s_,
  66. message_type& m_)
  67. : s(s_)
  68. , m(m_)
  69. , p(std::move(m))
  70. {
  71. }
  72. };
  73. data& d_;
  74. public:
  75. template<class Handler_>
  76. read_msg_op(
  77. Handler_&& h,
  78. Stream& s,
  79. DynamicBuffer& b,
  80. message_type& m)
  81. : stable_async_base<
  82. Handler, beast::executor_type<Stream>>(
  83. std::forward<Handler_>(h), s.get_executor())
  84. , d_(beast::allocate_stable<data>(
  85. *this, s, m))
  86. {
  87. ASIO_HANDLER_LOCATION((
  88. __FILE__, __LINE__,
  89. "http::async_read(msg)"));
  90. http::async_read(d_.s, b, d_.p, std::move(*this));
  91. }
  92. void
  93. operator()(
  94. error_code ec,
  95. std::size_t bytes_transferred)
  96. {
  97. if(! ec)
  98. d_.m = d_.p.release();
  99. this->complete_now(ec, bytes_transferred);
  100. }
  101. };
  102. struct run_read_msg_op
  103. {
  104. template<
  105. class ReadHandler,
  106. class AsyncReadStream,
  107. class DynamicBuffer,
  108. bool isRequest, class Body, class Allocator>
  109. void
  110. operator()(
  111. ReadHandler&& h,
  112. AsyncReadStream* s,
  113. DynamicBuffer* b,
  114. message<isRequest, Body,
  115. basic_fields<Allocator>>* m)
  116. {
  117. // If you get an error on the following line it means
  118. // that your handler does not meet the documented type
  119. // requirements for the handler.
  120. static_assert(
  121. beast::detail::is_invocable<ReadHandler,
  122. void(error_code, std::size_t)>::value,
  123. "ReadHandler type requirements not met");
  124. read_msg_op<
  125. AsyncReadStream,
  126. DynamicBuffer,
  127. isRequest, Body, Allocator,
  128. typename std::decay<ReadHandler>::type>(
  129. std::forward<ReadHandler>(h), *s, *b, *m);
  130. }
  131. };
  132. template<class AsyncReadStream, class DynamicBuffer, bool isRequest>
  133. class read_some_op : asio::coroutine
  134. {
  135. AsyncReadStream& s_;
  136. DynamicBuffer& b_;
  137. basic_parser<isRequest>& p_;
  138. std::size_t bytes_transferred_;
  139. bool cont_;
  140. public:
  141. read_some_op(
  142. AsyncReadStream& s,
  143. DynamicBuffer& b,
  144. basic_parser<isRequest>& p)
  145. : s_(s)
  146. , b_(b)
  147. , p_(p)
  148. , bytes_transferred_(0)
  149. , cont_(false)
  150. {
  151. }
  152. template<class Self>
  153. void operator()(
  154. Self& self,
  155. error_code ec = {},
  156. std::size_t bytes_transferred = 0)
  157. {
  158. ASIO_CORO_REENTER(*this)
  159. {
  160. if(b_.size() == 0)
  161. goto do_read;
  162. for(;;)
  163. {
  164. // parse
  165. {
  166. auto const used = p_.put(b_.data(), ec);
  167. bytes_transferred_ += used;
  168. b_.consume(used);
  169. }
  170. if(ec != http::error::need_more)
  171. break;
  172. do_read:
  173. ASIO_CORO_YIELD
  174. {
  175. cont_ = true;
  176. // VFALCO This was read_size_or_throw
  177. auto const size = read_size(b_, 65536);
  178. if(size == 0)
  179. {
  180. BHO_BEAST_ASSIGN_EC(ec, error::buffer_overflow);
  181. goto upcall;
  182. }
  183. auto const mb =
  184. beast::detail::dynamic_buffer_prepare(
  185. b_, size, ec, error::buffer_overflow);
  186. if(ec)
  187. goto upcall;
  188. ASIO_HANDLER_LOCATION((
  189. __FILE__, __LINE__,
  190. "http::async_read_some"));
  191. s_.async_read_some(*mb, std::move(self));
  192. }
  193. b_.commit(bytes_transferred);
  194. if(ec == net::error::eof)
  195. {
  196. BHO_ASSERT(bytes_transferred == 0);
  197. if(p_.got_some())
  198. {
  199. // caller sees EOF on next read
  200. ec.assign(0, ec.category());
  201. p_.put_eof(ec);
  202. if(ec)
  203. goto upcall;
  204. BHO_ASSERT(p_.is_done());
  205. goto upcall;
  206. }
  207. BHO_BEAST_ASSIGN_EC(ec, error::end_of_stream);
  208. break;
  209. }
  210. if(ec)
  211. break;
  212. }
  213. upcall:
  214. if(! cont_)
  215. {
  216. ASIO_CORO_YIELD
  217. {
  218. ASIO_HANDLER_LOCATION((
  219. __FILE__, __LINE__,
  220. "http::async_read_some"));
  221. const auto ex =
  222. asio::get_associated_immediate_executor(
  223. self, s_.get_executor());
  224. net::dispatch(
  225. ex,
  226. beast::bind_front_handler(std::move(self), ec));
  227. }
  228. }
  229. self.complete(ec, bytes_transferred_);
  230. }
  231. }
  232. };
  233. template<class Stream, class DynamicBuffer, bool isRequest, class Condition>
  234. class read_op
  235. : asio::coroutine
  236. {
  237. Stream& s_;
  238. DynamicBuffer& b_;
  239. basic_parser<isRequest>& p_;
  240. std::size_t bytes_transferred_;
  241. public:
  242. read_op(Stream& s, DynamicBuffer& b, basic_parser<isRequest>& p)
  243. : s_(s)
  244. , b_(b)
  245. , p_(p)
  246. , bytes_transferred_(0)
  247. {
  248. }
  249. template<class Self>
  250. void operator()(Self& self, error_code ec = {}, std::size_t bytes_transferred = 0)
  251. {
  252. ASIO_CORO_REENTER(*this)
  253. {
  254. if (Condition{}(p_))
  255. {
  256. ASIO_CORO_YIELD
  257. {
  258. ASIO_HANDLER_LOCATION((
  259. __FILE__, __LINE__,
  260. "http::async_read"));
  261. const auto ex =
  262. asio::get_associated_immediate_executor(
  263. self, s_.get_executor());
  264. net::dispatch(ex, std::move(self));
  265. }
  266. }
  267. else
  268. {
  269. do
  270. {
  271. ASIO_CORO_YIELD
  272. {
  273. ASIO_HANDLER_LOCATION((
  274. __FILE__, __LINE__,
  275. "http::async_read"));
  276. async_read_some(
  277. s_, b_, p_, std::move(self));
  278. }
  279. bytes_transferred_ += bytes_transferred;
  280. } while (!ec &&
  281. !Condition{}(p_));
  282. }
  283. self.complete(ec, bytes_transferred_);
  284. }
  285. }
  286. };
  287. template<
  288. class SyncReadStream,
  289. class DynamicBuffer,
  290. bool isRequest>
  291. std::size_t
  292. read_some(SyncReadStream& s, DynamicBuffer& b, basic_parser<isRequest>& p, error_code& ec)
  293. {
  294. std::size_t total = 0;
  295. ec.clear();
  296. if(b.size() == 0)
  297. goto do_read;
  298. for(;;)
  299. {
  300. // parse
  301. {
  302. auto const used = p.put(b.data(), ec);
  303. total += used;
  304. b.consume(used);
  305. }
  306. if(ec != http::error::need_more)
  307. break;
  308. do_read:
  309. // VFALCO This was read_size_or_throw
  310. auto const size = read_size(b, 65536);
  311. if(size == 0)
  312. {
  313. BHO_BEAST_ASSIGN_EC(ec, error::buffer_overflow);
  314. return total;
  315. }
  316. auto const mb =
  317. beast::detail::dynamic_buffer_prepare(
  318. b, size, ec, error::buffer_overflow);
  319. if(ec)
  320. return total;
  321. std::size_t
  322. bytes_transferred =
  323. s.read_some(*mb, ec);
  324. b.commit(bytes_transferred);
  325. if(ec == net::error::eof)
  326. {
  327. BHO_ASSERT(bytes_transferred == 0);
  328. if(p.got_some())
  329. {
  330. // caller sees EOF on next read
  331. ec.assign(0, ec.category());
  332. p.put_eof(ec);
  333. if(ec)
  334. return total;
  335. BHO_ASSERT(p.is_done());
  336. return total;
  337. }
  338. BHO_BEAST_ASSIGN_EC(ec, error::end_of_stream);
  339. break;
  340. }
  341. if(ec)
  342. break;
  343. }
  344. return total;
  345. }
  346. template<class Condition, class Stream, class DynamicBuffer, bool isRequest>
  347. std::size_t sync_read_op(Stream& s, DynamicBuffer& b, basic_parser<isRequest>& p, error_code& ec)
  348. {
  349. std::size_t total = 0;
  350. ec.clear();
  351. if (!Condition{}(p))
  352. {
  353. do
  354. {
  355. total +=
  356. detail::read_some(s, b, p, ec);
  357. } while (!ec &&
  358. !Condition{}(p));
  359. }
  360. return total;
  361. }
  362. } // detail
  363. //------------------------------------------------------------------------------
  364. template<
  365. class SyncReadStream,
  366. class DynamicBuffer,
  367. bool isRequest>
  368. std::size_t
  369. read_some(
  370. SyncReadStream& stream,
  371. DynamicBuffer& buffer,
  372. basic_parser<isRequest>& parser)
  373. {
  374. static_assert(
  375. is_sync_read_stream<SyncReadStream>::value,
  376. "SyncReadStream type requirements not met");
  377. static_assert(
  378. net::is_dynamic_buffer<DynamicBuffer>::value,
  379. "DynamicBuffer type requirements not met");
  380. error_code ec;
  381. auto const bytes_transferred =
  382. http::read_some(stream, buffer, parser, ec);
  383. if(ec)
  384. BHO_THROW_EXCEPTION(system_error{ec});
  385. return bytes_transferred;
  386. }
  387. template<
  388. class SyncReadStream,
  389. class DynamicBuffer,
  390. bool isRequest>
  391. std::size_t
  392. read_some(
  393. SyncReadStream& stream,
  394. DynamicBuffer& buffer,
  395. basic_parser<isRequest>& parser,
  396. error_code& ec)
  397. {
  398. static_assert(
  399. is_sync_read_stream<SyncReadStream>::value,
  400. "SyncReadStream type requirements not met");
  401. static_assert(
  402. net::is_dynamic_buffer<DynamicBuffer>::value,
  403. "DynamicBuffer type requirements not met");
  404. return detail::read_some(stream, buffer, parser, ec);
  405. }
  406. template<
  407. class AsyncReadStream,
  408. class DynamicBuffer,
  409. bool isRequest,
  410. BHO_BEAST_ASYNC_TPARAM2 ReadHandler>
  411. BHO_BEAST_ASYNC_RESULT2(ReadHandler)
  412. async_read_some(
  413. AsyncReadStream& stream,
  414. DynamicBuffer& buffer,
  415. basic_parser<isRequest>& parser,
  416. ReadHandler&& handler)
  417. {
  418. return net::async_compose<ReadHandler,
  419. void(beast::error_code, std::size_t)>(
  420. detail::read_some_op<AsyncReadStream, DynamicBuffer, isRequest> {
  421. stream,
  422. buffer,
  423. parser
  424. },
  425. handler,
  426. stream);
  427. }
  428. //------------------------------------------------------------------------------
  429. template<
  430. class SyncReadStream,
  431. class DynamicBuffer,
  432. bool isRequest>
  433. std::size_t
  434. read_header(
  435. SyncReadStream& stream,
  436. DynamicBuffer& buffer,
  437. basic_parser<isRequest>& parser)
  438. {
  439. static_assert(
  440. is_sync_read_stream<SyncReadStream>::value,
  441. "SyncReadStream type requirements not met");
  442. static_assert(
  443. net::is_dynamic_buffer<DynamicBuffer>::value,
  444. "DynamicBuffer type requirements not met");
  445. error_code ec;
  446. auto const bytes_transferred =
  447. http::read_header(stream, buffer, parser, ec);
  448. if(ec)
  449. BHO_THROW_EXCEPTION(system_error{ec});
  450. return bytes_transferred;
  451. }
  452. template<
  453. class SyncReadStream,
  454. class DynamicBuffer,
  455. bool isRequest>
  456. std::size_t
  457. read_header(
  458. SyncReadStream& stream,
  459. DynamicBuffer& buffer,
  460. basic_parser<isRequest>& parser,
  461. error_code& ec)
  462. {
  463. static_assert(
  464. is_sync_read_stream<SyncReadStream>::value,
  465. "SyncReadStream type requirements not met");
  466. static_assert(
  467. net::is_dynamic_buffer<DynamicBuffer>::value,
  468. "DynamicBuffer type requirements not met");
  469. parser.eager(false);
  470. return detail::sync_read_op<
  471. detail::parser_is_header_done>(
  472. stream, buffer, parser, ec);
  473. }
  474. template<
  475. class AsyncReadStream,
  476. class DynamicBuffer,
  477. bool isRequest,
  478. BHO_BEAST_ASYNC_TPARAM2 ReadHandler>
  479. BHO_BEAST_ASYNC_RESULT2(ReadHandler)
  480. async_read_header(
  481. AsyncReadStream& stream,
  482. DynamicBuffer& buffer,
  483. basic_parser<isRequest>& parser,
  484. ReadHandler&& handler)
  485. {
  486. parser.eager(false);
  487. return net::async_compose<
  488. ReadHandler,
  489. void(error_code, std::size_t)>(
  490. detail::read_op<
  491. AsyncReadStream,
  492. DynamicBuffer,
  493. isRequest,
  494. detail::parser_is_header_done>(
  495. stream, buffer, parser),
  496. handler, stream);
  497. }
  498. //------------------------------------------------------------------------------
  499. template<
  500. class SyncReadStream,
  501. class DynamicBuffer,
  502. bool isRequest>
  503. std::size_t
  504. read(
  505. SyncReadStream& stream,
  506. DynamicBuffer& buffer,
  507. basic_parser<isRequest>& parser)
  508. {
  509. static_assert(
  510. is_sync_read_stream<SyncReadStream>::value,
  511. "SyncReadStream type requirements not met");
  512. static_assert(
  513. net::is_dynamic_buffer<DynamicBuffer>::value,
  514. "DynamicBuffer type requirements not met");
  515. error_code ec;
  516. auto const bytes_transferred =
  517. http::read(stream, buffer, parser, ec);
  518. if(ec)
  519. BHO_THROW_EXCEPTION(system_error{ec});
  520. return bytes_transferred;
  521. }
  522. template<
  523. class SyncReadStream,
  524. class DynamicBuffer,
  525. bool isRequest>
  526. std::size_t
  527. read(
  528. SyncReadStream& stream,
  529. DynamicBuffer& buffer,
  530. basic_parser<isRequest>& parser,
  531. error_code& ec)
  532. {
  533. static_assert(
  534. is_sync_read_stream<SyncReadStream>::value,
  535. "SyncReadStream type requirements not met");
  536. static_assert(
  537. net::is_dynamic_buffer<DynamicBuffer>::value,
  538. "DynamicBuffer type requirements not met");
  539. parser.eager(true);
  540. return detail::sync_read_op<
  541. detail::parser_is_done>(
  542. stream, buffer, parser, ec);
  543. }
  544. template<
  545. class AsyncReadStream,
  546. class DynamicBuffer,
  547. bool isRequest,
  548. BHO_BEAST_ASYNC_TPARAM2 ReadHandler>
  549. BHO_BEAST_ASYNC_RESULT2(ReadHandler)
  550. async_read(
  551. AsyncReadStream& stream,
  552. DynamicBuffer& buffer,
  553. basic_parser<isRequest>& parser,
  554. ReadHandler&& handler)
  555. {
  556. static_assert(
  557. is_async_read_stream<AsyncReadStream>::value,
  558. "AsyncReadStream type requirements not met");
  559. static_assert(
  560. net::is_dynamic_buffer<DynamicBuffer>::value,
  561. "DynamicBuffer type requirements not met");
  562. parser.eager(true);
  563. return net::async_compose<
  564. ReadHandler,
  565. void(error_code, std::size_t)>(
  566. detail::read_op<
  567. AsyncReadStream,
  568. DynamicBuffer,
  569. isRequest,
  570. detail::parser_is_done>(
  571. stream, buffer, parser),
  572. handler, stream);
  573. }
  574. //------------------------------------------------------------------------------
  575. template<
  576. class SyncReadStream,
  577. class DynamicBuffer,
  578. bool isRequest, class Body, class Allocator>
  579. std::size_t
  580. read(
  581. SyncReadStream& stream,
  582. DynamicBuffer& buffer,
  583. message<isRequest, Body, basic_fields<Allocator>>& msg)
  584. {
  585. static_assert(
  586. is_sync_read_stream<SyncReadStream>::value,
  587. "SyncReadStream type requirements not met");
  588. static_assert(
  589. net::is_dynamic_buffer<DynamicBuffer>::value,
  590. "DynamicBuffer type requirements not met");
  591. static_assert(is_body<Body>::value,
  592. "Body type requirements not met");
  593. static_assert(is_body_reader<Body>::value,
  594. "BodyReader type requirements not met");
  595. error_code ec;
  596. auto const bytes_transferred =
  597. http::read(stream, buffer, msg, ec);
  598. if(ec)
  599. BHO_THROW_EXCEPTION(system_error{ec});
  600. return bytes_transferred;
  601. }
  602. template<
  603. class SyncReadStream,
  604. class DynamicBuffer,
  605. bool isRequest, class Body, class Allocator>
  606. std::size_t
  607. read(
  608. SyncReadStream& stream,
  609. DynamicBuffer& buffer,
  610. message<isRequest, Body, basic_fields<Allocator>>& msg,
  611. error_code& ec)
  612. {
  613. static_assert(
  614. is_sync_read_stream<SyncReadStream>::value,
  615. "SyncReadStream type requirements not met");
  616. static_assert(
  617. net::is_dynamic_buffer<DynamicBuffer>::value,
  618. "DynamicBuffer type requirements not met");
  619. static_assert(is_body<Body>::value,
  620. "Body type requirements not met");
  621. static_assert(is_body_reader<Body>::value,
  622. "BodyReader type requirements not met");
  623. parser<isRequest, Body, Allocator> p(std::move(msg));
  624. p.eager(true);
  625. auto const bytes_transferred =
  626. http::read(stream, buffer, p, ec);
  627. if(ec)
  628. return bytes_transferred;
  629. msg = p.release();
  630. return bytes_transferred;
  631. }
  632. template<
  633. class AsyncReadStream,
  634. class DynamicBuffer,
  635. bool isRequest, class Body, class Allocator,
  636. BHO_BEAST_ASYNC_TPARAM2 ReadHandler>
  637. BHO_BEAST_ASYNC_RESULT2(ReadHandler)
  638. async_read(
  639. AsyncReadStream& stream,
  640. DynamicBuffer& buffer,
  641. message<isRequest, Body, basic_fields<Allocator>>& msg,
  642. ReadHandler&& handler)
  643. {
  644. static_assert(
  645. is_async_read_stream<AsyncReadStream>::value,
  646. "AsyncReadStream type requirements not met");
  647. static_assert(
  648. net::is_dynamic_buffer<DynamicBuffer>::value,
  649. "DynamicBuffer type requirements not met");
  650. static_assert(is_body<Body>::value,
  651. "Body type requirements not met");
  652. static_assert(is_body_reader<Body>::value,
  653. "BodyReader type requirements not met");
  654. return net::async_initiate<
  655. ReadHandler,
  656. void(error_code, std::size_t)>(
  657. detail::run_read_msg_op{},
  658. handler, &stream, &buffer, &msg);
  659. }
  660. } // http
  661. } // beast
  662. } // bho
  663. #endif