read.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  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/error.hpp>
  21. #include <boost/asio/compose.hpp>
  22. #include <boost/asio/coroutine.hpp>
  23. namespace boost {
  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. BOOST_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. BOOST_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. BOOST_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. BOOST_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. BOOST_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. BOOST_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. BOOST_ASSERT(p_.is_done());
  205. goto upcall;
  206. }
  207. BOOST_BEAST_ASSIGN_EC(ec, error::end_of_stream);
  208. break;
  209. }
  210. if(ec)
  211. break;
  212. }
  213. upcall:
  214. if(! cont_)
  215. {
  216. BOOST_ASIO_CORO_YIELD
  217. {
  218. BOOST_ASIO_HANDLER_LOCATION((
  219. __FILE__, __LINE__,
  220. "http::async_read_some"));
  221. net::post(
  222. s_.get_executor(),
  223. beast::bind_front_handler(std::move(self), ec));
  224. }
  225. }
  226. self.complete(ec, bytes_transferred_);
  227. }
  228. }
  229. };
  230. template<class Stream, class DynamicBuffer, bool isRequest, class Condition>
  231. class read_op
  232. : asio::coroutine
  233. {
  234. Stream& s_;
  235. DynamicBuffer& b_;
  236. basic_parser<isRequest>& p_;
  237. std::size_t bytes_transferred_;
  238. public:
  239. read_op(Stream& s, DynamicBuffer& b, basic_parser<isRequest>& p)
  240. : s_(s)
  241. , b_(b)
  242. , p_(p)
  243. , bytes_transferred_(0)
  244. {
  245. }
  246. template<class Self>
  247. void operator()(Self& self, error_code ec = {}, std::size_t bytes_transferred = 0)
  248. {
  249. BOOST_ASIO_CORO_REENTER(*this)
  250. {
  251. if (Condition{}(p_))
  252. {
  253. BOOST_ASIO_CORO_YIELD
  254. {
  255. BOOST_ASIO_HANDLER_LOCATION((
  256. __FILE__, __LINE__,
  257. "http::async_read"));
  258. net::post(s_.get_executor(), std::move(self));
  259. }
  260. }
  261. else
  262. {
  263. do
  264. {
  265. BOOST_ASIO_CORO_YIELD
  266. {
  267. BOOST_ASIO_HANDLER_LOCATION((
  268. __FILE__, __LINE__,
  269. "http::async_read"));
  270. async_read_some(
  271. s_, b_, p_, std::move(self));
  272. }
  273. bytes_transferred_ += bytes_transferred;
  274. } while (!ec &&
  275. !Condition{}(p_));
  276. }
  277. self.complete(ec, bytes_transferred_);
  278. }
  279. }
  280. };
  281. template<
  282. class SyncReadStream,
  283. class DynamicBuffer,
  284. bool isRequest>
  285. std::size_t
  286. read_some(SyncReadStream& s, DynamicBuffer& b, basic_parser<isRequest>& p, error_code& ec)
  287. {
  288. std::size_t total = 0;
  289. ec.clear();
  290. if(b.size() == 0)
  291. goto do_read;
  292. for(;;)
  293. {
  294. // parse
  295. {
  296. auto const used = p.put(b.data(), ec);
  297. total += used;
  298. b.consume(used);
  299. }
  300. if(ec != http::error::need_more)
  301. break;
  302. do_read:
  303. // VFALCO This was read_size_or_throw
  304. auto const size = read_size(b, 65536);
  305. if(size == 0)
  306. {
  307. BOOST_BEAST_ASSIGN_EC(ec, error::buffer_overflow);
  308. return total;
  309. }
  310. auto const mb =
  311. beast::detail::dynamic_buffer_prepare(
  312. b, size, ec, error::buffer_overflow);
  313. if(ec)
  314. return total;
  315. std::size_t
  316. bytes_transferred =
  317. s.read_some(*mb, ec);
  318. b.commit(bytes_transferred);
  319. if(ec == net::error::eof)
  320. {
  321. BOOST_ASSERT(bytes_transferred == 0);
  322. if(p.got_some())
  323. {
  324. // caller sees EOF on next read
  325. ec.assign(0, ec.category());
  326. p.put_eof(ec);
  327. if(ec)
  328. return total;
  329. BOOST_ASSERT(p.is_done());
  330. return total;
  331. }
  332. BOOST_BEAST_ASSIGN_EC(ec, error::end_of_stream);
  333. break;
  334. }
  335. if(ec)
  336. break;
  337. }
  338. return total;
  339. }
  340. template<class Condition, class Stream, class DynamicBuffer, bool isRequest>
  341. std::size_t sync_read_op(Stream& s, DynamicBuffer& b, basic_parser<isRequest>& p, error_code& ec)
  342. {
  343. std::size_t total = 0;
  344. ec.clear();
  345. if (!Condition{}(p))
  346. {
  347. do
  348. {
  349. total +=
  350. detail::read_some(s, b, p, ec);
  351. } while (!ec &&
  352. !Condition{}(p));
  353. }
  354. return total;
  355. }
  356. } // detail
  357. //------------------------------------------------------------------------------
  358. template<
  359. class SyncReadStream,
  360. class DynamicBuffer,
  361. bool isRequest>
  362. std::size_t
  363. read_some(
  364. SyncReadStream& stream,
  365. DynamicBuffer& buffer,
  366. basic_parser<isRequest>& parser)
  367. {
  368. static_assert(
  369. is_sync_read_stream<SyncReadStream>::value,
  370. "SyncReadStream type requirements not met");
  371. static_assert(
  372. net::is_dynamic_buffer<DynamicBuffer>::value,
  373. "DynamicBuffer type requirements not met");
  374. error_code ec;
  375. auto const bytes_transferred =
  376. http::read_some(stream, buffer, parser, ec);
  377. if(ec)
  378. BOOST_THROW_EXCEPTION(system_error{ec});
  379. return bytes_transferred;
  380. }
  381. template<
  382. class SyncReadStream,
  383. class DynamicBuffer,
  384. bool isRequest>
  385. std::size_t
  386. read_some(
  387. SyncReadStream& stream,
  388. DynamicBuffer& buffer,
  389. basic_parser<isRequest>& parser,
  390. error_code& ec)
  391. {
  392. static_assert(
  393. is_sync_read_stream<SyncReadStream>::value,
  394. "SyncReadStream type requirements not met");
  395. static_assert(
  396. net::is_dynamic_buffer<DynamicBuffer>::value,
  397. "DynamicBuffer type requirements not met");
  398. return detail::read_some(stream, buffer, parser, ec);
  399. }
  400. template<
  401. class AsyncReadStream,
  402. class DynamicBuffer,
  403. bool isRequest,
  404. BOOST_BEAST_ASYNC_TPARAM2 ReadHandler>
  405. BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
  406. async_read_some(
  407. AsyncReadStream& stream,
  408. DynamicBuffer& buffer,
  409. basic_parser<isRequest>& parser,
  410. ReadHandler&& handler)
  411. {
  412. return net::async_compose<ReadHandler,
  413. void(beast::error_code, std::size_t)>(
  414. detail::read_some_op<AsyncReadStream, DynamicBuffer, isRequest> {
  415. stream,
  416. buffer,
  417. parser
  418. },
  419. handler,
  420. stream);
  421. }
  422. //------------------------------------------------------------------------------
  423. template<
  424. class SyncReadStream,
  425. class DynamicBuffer,
  426. bool isRequest>
  427. std::size_t
  428. read_header(
  429. SyncReadStream& stream,
  430. DynamicBuffer& buffer,
  431. basic_parser<isRequest>& parser)
  432. {
  433. static_assert(
  434. is_sync_read_stream<SyncReadStream>::value,
  435. "SyncReadStream type requirements not met");
  436. static_assert(
  437. net::is_dynamic_buffer<DynamicBuffer>::value,
  438. "DynamicBuffer type requirements not met");
  439. error_code ec;
  440. auto const bytes_transferred =
  441. http::read_header(stream, buffer, parser, ec);
  442. if(ec)
  443. BOOST_THROW_EXCEPTION(system_error{ec});
  444. return bytes_transferred;
  445. }
  446. template<
  447. class SyncReadStream,
  448. class DynamicBuffer,
  449. bool isRequest>
  450. std::size_t
  451. read_header(
  452. SyncReadStream& stream,
  453. DynamicBuffer& buffer,
  454. basic_parser<isRequest>& parser,
  455. error_code& ec)
  456. {
  457. static_assert(
  458. is_sync_read_stream<SyncReadStream>::value,
  459. "SyncReadStream type requirements not met");
  460. static_assert(
  461. net::is_dynamic_buffer<DynamicBuffer>::value,
  462. "DynamicBuffer type requirements not met");
  463. parser.eager(false);
  464. return detail::sync_read_op<
  465. detail::parser_is_header_done>(
  466. stream, buffer, parser, ec);
  467. }
  468. template<
  469. class AsyncReadStream,
  470. class DynamicBuffer,
  471. bool isRequest,
  472. BOOST_BEAST_ASYNC_TPARAM2 ReadHandler>
  473. BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
  474. async_read_header(
  475. AsyncReadStream& stream,
  476. DynamicBuffer& buffer,
  477. basic_parser<isRequest>& parser,
  478. ReadHandler&& handler)
  479. {
  480. parser.eager(false);
  481. return net::async_compose<
  482. ReadHandler,
  483. void(error_code, std::size_t)>(
  484. detail::read_op<
  485. AsyncReadStream,
  486. DynamicBuffer,
  487. isRequest,
  488. detail::parser_is_header_done>(
  489. stream, buffer, parser),
  490. handler, stream);
  491. }
  492. //------------------------------------------------------------------------------
  493. template<
  494. class SyncReadStream,
  495. class DynamicBuffer,
  496. bool isRequest>
  497. std::size_t
  498. read(
  499. SyncReadStream& stream,
  500. DynamicBuffer& buffer,
  501. basic_parser<isRequest>& parser)
  502. {
  503. static_assert(
  504. is_sync_read_stream<SyncReadStream>::value,
  505. "SyncReadStream type requirements not met");
  506. static_assert(
  507. net::is_dynamic_buffer<DynamicBuffer>::value,
  508. "DynamicBuffer type requirements not met");
  509. error_code ec;
  510. auto const bytes_transferred =
  511. http::read(stream, buffer, parser, ec);
  512. if(ec)
  513. BOOST_THROW_EXCEPTION(system_error{ec});
  514. return bytes_transferred;
  515. }
  516. template<
  517. class SyncReadStream,
  518. class DynamicBuffer,
  519. bool isRequest>
  520. std::size_t
  521. read(
  522. SyncReadStream& stream,
  523. DynamicBuffer& buffer,
  524. basic_parser<isRequest>& parser,
  525. error_code& ec)
  526. {
  527. static_assert(
  528. is_sync_read_stream<SyncReadStream>::value,
  529. "SyncReadStream type requirements not met");
  530. static_assert(
  531. net::is_dynamic_buffer<DynamicBuffer>::value,
  532. "DynamicBuffer type requirements not met");
  533. parser.eager(true);
  534. return detail::sync_read_op<
  535. detail::parser_is_done>(
  536. stream, buffer, parser, ec);
  537. }
  538. template<
  539. class AsyncReadStream,
  540. class DynamicBuffer,
  541. bool isRequest,
  542. BOOST_BEAST_ASYNC_TPARAM2 ReadHandler>
  543. BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
  544. async_read(
  545. AsyncReadStream& stream,
  546. DynamicBuffer& buffer,
  547. basic_parser<isRequest>& parser,
  548. ReadHandler&& handler)
  549. {
  550. static_assert(
  551. is_async_read_stream<AsyncReadStream>::value,
  552. "AsyncReadStream type requirements not met");
  553. static_assert(
  554. net::is_dynamic_buffer<DynamicBuffer>::value,
  555. "DynamicBuffer type requirements not met");
  556. parser.eager(true);
  557. return net::async_compose<
  558. ReadHandler,
  559. void(error_code, std::size_t)>(
  560. detail::read_op<
  561. AsyncReadStream,
  562. DynamicBuffer,
  563. isRequest,
  564. detail::parser_is_done>(
  565. stream, buffer, parser),
  566. handler, stream);
  567. }
  568. //------------------------------------------------------------------------------
  569. template<
  570. class SyncReadStream,
  571. class DynamicBuffer,
  572. bool isRequest, class Body, class Allocator>
  573. std::size_t
  574. read(
  575. SyncReadStream& stream,
  576. DynamicBuffer& buffer,
  577. message<isRequest, Body, basic_fields<Allocator>>& msg)
  578. {
  579. static_assert(
  580. is_sync_read_stream<SyncReadStream>::value,
  581. "SyncReadStream type requirements not met");
  582. static_assert(
  583. net::is_dynamic_buffer<DynamicBuffer>::value,
  584. "DynamicBuffer type requirements not met");
  585. static_assert(is_body<Body>::value,
  586. "Body type requirements not met");
  587. static_assert(is_body_reader<Body>::value,
  588. "BodyReader type requirements not met");
  589. error_code ec;
  590. auto const bytes_transferred =
  591. http::read(stream, buffer, msg, ec);
  592. if(ec)
  593. BOOST_THROW_EXCEPTION(system_error{ec});
  594. return bytes_transferred;
  595. }
  596. template<
  597. class SyncReadStream,
  598. class DynamicBuffer,
  599. bool isRequest, class Body, class Allocator>
  600. std::size_t
  601. read(
  602. SyncReadStream& stream,
  603. DynamicBuffer& buffer,
  604. message<isRequest, Body, basic_fields<Allocator>>& msg,
  605. error_code& ec)
  606. {
  607. static_assert(
  608. is_sync_read_stream<SyncReadStream>::value,
  609. "SyncReadStream type requirements not met");
  610. static_assert(
  611. net::is_dynamic_buffer<DynamicBuffer>::value,
  612. "DynamicBuffer type requirements not met");
  613. static_assert(is_body<Body>::value,
  614. "Body type requirements not met");
  615. static_assert(is_body_reader<Body>::value,
  616. "BodyReader type requirements not met");
  617. parser<isRequest, Body, Allocator> p(std::move(msg));
  618. p.eager(true);
  619. auto const bytes_transferred =
  620. http::read(stream, buffer, p, ec);
  621. if(ec)
  622. return bytes_transferred;
  623. msg = p.release();
  624. return bytes_transferred;
  625. }
  626. template<
  627. class AsyncReadStream,
  628. class DynamicBuffer,
  629. bool isRequest, class Body, class Allocator,
  630. BOOST_BEAST_ASYNC_TPARAM2 ReadHandler>
  631. BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
  632. async_read(
  633. AsyncReadStream& stream,
  634. DynamicBuffer& buffer,
  635. message<isRequest, Body, basic_fields<Allocator>>& msg,
  636. ReadHandler&& handler)
  637. {
  638. static_assert(
  639. is_async_read_stream<AsyncReadStream>::value,
  640. "AsyncReadStream type requirements not met");
  641. static_assert(
  642. net::is_dynamic_buffer<DynamicBuffer>::value,
  643. "DynamicBuffer type requirements not met");
  644. static_assert(is_body<Body>::value,
  645. "Body type requirements not met");
  646. static_assert(is_body_reader<Body>::value,
  647. "BodyReader type requirements not met");
  648. return net::async_initiate<
  649. ReadHandler,
  650. void(error_code, std::size_t)>(
  651. detail::run_read_msg_op{},
  652. handler, &stream, &buffer, &msg);
  653. }
  654. } // http
  655. } // beast
  656. } // boost
  657. #endif