read.hpp 19 KB

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