read.hpp 19 KB

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