read.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. //
  2. // Copyright (c) 2016-2019 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_READ_HPP
  10. #define BOOST_BEAST_HTTP_IMPL_READ_HPP
  11. #include <boost/beast/http/type_traits.hpp>
  12. #include <boost/beast/http/error.hpp>
  13. #include <boost/beast/http/parser.hpp>
  14. #include <boost/beast/http/read.hpp>
  15. #include <boost/beast/core/async_base.hpp>
  16. #include <boost/beast/core/stream_traits.hpp>
  17. #include <boost/beast/core/detail/read.hpp>
  18. #include <boost/asio/error.hpp>
  19. namespace boost {
  20. namespace beast {
  21. namespace http {
  22. namespace detail {
  23. // The default maximum number of bytes to transfer in a single operation.
  24. std::size_t constexpr default_max_transfer_size = 65536;
  25. template<
  26. class DynamicBuffer,
  27. bool isRequest,
  28. class Condition>
  29. std::size_t
  30. parse_until(
  31. DynamicBuffer& buffer,
  32. basic_parser<isRequest>& parser,
  33. error_code& ec,
  34. Condition cond)
  35. {
  36. if(ec == net::error::eof)
  37. {
  38. if(parser.got_some())
  39. {
  40. // Caller sees EOF on next read
  41. ec = {};
  42. parser.put_eof(ec);
  43. BOOST_ASSERT(ec || parser.is_done());
  44. }
  45. else
  46. {
  47. ec = error::end_of_stream;
  48. }
  49. return 0;
  50. }
  51. if(ec)
  52. {
  53. // Upgrade the error if we have a partial message.
  54. // This causes SSL short reads (and every other error)
  55. // to be converted into something else, allowing the
  56. // caller to distinguish an SSL short read which
  57. // represents a safe connection closure, versus
  58. // a closure with data loss.
  59. if( ec != net::error::operation_aborted &&
  60. parser.got_some() && ! parser.is_done())
  61. {
  62. ec = error::partial_message;
  63. }
  64. return 0;
  65. }
  66. if(parser.is_done())
  67. return 0;
  68. if(buffer.size() > 0)
  69. {
  70. auto const bytes_used =
  71. parser.put(buffer.data(), ec);
  72. // total = total + bytes_used; // VFALCO Can't do this in a condition
  73. buffer.consume(bytes_used);
  74. if(ec == http::error::need_more)
  75. {
  76. if(buffer.size() >= buffer.max_size())
  77. {
  78. ec = http::error::buffer_overflow;
  79. return 0;
  80. }
  81. ec = {};
  82. }
  83. else if(ec || cond())
  84. {
  85. return 0;
  86. }
  87. }
  88. return default_max_transfer_size;
  89. }
  90. // predicate is true on any forward parser progress
  91. template<bool isRequest>
  92. struct read_some_condition
  93. {
  94. basic_parser<isRequest>& parser;
  95. template<class DynamicBuffer>
  96. std::size_t
  97. operator()(error_code& ec, std::size_t,
  98. DynamicBuffer& buffer)
  99. {
  100. return detail::parse_until(
  101. buffer, parser, ec,
  102. []
  103. {
  104. return true;
  105. });
  106. }
  107. };
  108. // predicate is true when parser header is complete
  109. template<bool isRequest>
  110. struct read_header_condition
  111. {
  112. basic_parser<isRequest>& parser;
  113. template<class DynamicBuffer>
  114. std::size_t
  115. operator()(error_code& ec, std::size_t,
  116. DynamicBuffer& buffer)
  117. {
  118. return detail::parse_until(
  119. buffer, parser, ec,
  120. [this]
  121. {
  122. return parser.is_header_done();
  123. });
  124. }
  125. };
  126. // predicate is true when parser message is complete
  127. template<bool isRequest>
  128. struct read_all_condition
  129. {
  130. basic_parser<isRequest>& parser;
  131. template<class DynamicBuffer>
  132. std::size_t
  133. operator()(error_code& ec, std::size_t,
  134. DynamicBuffer& buffer)
  135. {
  136. return detail::parse_until(
  137. buffer, parser, ec,
  138. [this]
  139. {
  140. return parser.is_done();
  141. });
  142. }
  143. };
  144. //------------------------------------------------------------------------------
  145. template<
  146. class Stream, class DynamicBuffer,
  147. bool isRequest, class Body, class Allocator,
  148. class Handler>
  149. class read_msg_op
  150. : public beast::stable_async_base<
  151. Handler, beast::executor_type<Stream>>
  152. , public asio::coroutine
  153. {
  154. using parser_type =
  155. parser<isRequest, Body, Allocator>;
  156. using message_type =
  157. typename parser_type::value_type;
  158. struct data
  159. {
  160. Stream& s;
  161. message_type& m;
  162. parser_type p;
  163. data(
  164. Stream& s_,
  165. message_type& m_)
  166. : s(s_)
  167. , m(m_)
  168. , p(std::move(m))
  169. {
  170. }
  171. };
  172. data& d_;
  173. public:
  174. template<class Handler_>
  175. read_msg_op(
  176. Handler_&& h,
  177. Stream& s,
  178. DynamicBuffer& b,
  179. message_type& m)
  180. : stable_async_base<
  181. Handler, beast::executor_type<Stream>>(
  182. std::forward<Handler_>(h), s.get_executor())
  183. , d_(beast::allocate_stable<data>(
  184. *this, s, m))
  185. {
  186. http::async_read(d_.s, b, d_.p, std::move(*this));
  187. }
  188. void
  189. operator()(
  190. error_code ec,
  191. std::size_t bytes_transferred)
  192. {
  193. if(! ec)
  194. d_.m = d_.p.release();
  195. this->complete_now(ec, bytes_transferred);
  196. }
  197. };
  198. struct run_read_msg_op
  199. {
  200. template<
  201. class ReadHandler,
  202. class AsyncReadStream,
  203. class DynamicBuffer,
  204. bool isRequest, class Body, class Allocator>
  205. void
  206. operator()(
  207. ReadHandler&& h,
  208. AsyncReadStream* s,
  209. DynamicBuffer* b,
  210. message<isRequest, Body,
  211. basic_fields<Allocator>>* m)
  212. {
  213. // If you get an error on the following line it means
  214. // that your handler does not meet the documented type
  215. // requirements for the handler.
  216. static_assert(
  217. beast::detail::is_invocable<ReadHandler,
  218. void(error_code, std::size_t)>::value,
  219. "ReadHandler type requirements not met");
  220. read_msg_op<
  221. AsyncReadStream,
  222. DynamicBuffer,
  223. isRequest, Body, Allocator,
  224. typename std::decay<ReadHandler>::type>(
  225. std::forward<ReadHandler>(h), *s, *b, *m);
  226. }
  227. };
  228. } // detail
  229. //------------------------------------------------------------------------------
  230. template<
  231. class SyncReadStream,
  232. class DynamicBuffer,
  233. bool isRequest>
  234. std::size_t
  235. read_some(
  236. SyncReadStream& stream,
  237. DynamicBuffer& buffer,
  238. basic_parser<isRequest>& parser)
  239. {
  240. static_assert(
  241. is_sync_read_stream<SyncReadStream>::value,
  242. "SyncReadStream type requirements not met");
  243. static_assert(
  244. net::is_dynamic_buffer<DynamicBuffer>::value,
  245. "DynamicBuffer type requirements not met");
  246. error_code ec;
  247. auto const bytes_transferred =
  248. http::read_some(stream, buffer, parser, ec);
  249. if(ec)
  250. BOOST_THROW_EXCEPTION(system_error{ec});
  251. return bytes_transferred;
  252. }
  253. template<
  254. class SyncReadStream,
  255. class DynamicBuffer,
  256. bool isRequest>
  257. std::size_t
  258. read_some(
  259. SyncReadStream& stream,
  260. DynamicBuffer& buffer,
  261. basic_parser<isRequest>& parser,
  262. error_code& ec)
  263. {
  264. static_assert(
  265. is_sync_read_stream<SyncReadStream>::value,
  266. "SyncReadStream type requirements not met");
  267. static_assert(
  268. net::is_dynamic_buffer<DynamicBuffer>::value,
  269. "DynamicBuffer type requirements not met");
  270. return beast::detail::read(stream, buffer,
  271. detail::read_some_condition<
  272. isRequest>{parser}, ec);
  273. }
  274. template<
  275. class AsyncReadStream,
  276. class DynamicBuffer,
  277. bool isRequest,
  278. class ReadHandler>
  279. BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
  280. async_read_some(
  281. AsyncReadStream& stream,
  282. DynamicBuffer& buffer,
  283. basic_parser<isRequest>& parser,
  284. ReadHandler&& handler)
  285. {
  286. return beast::detail::async_read(
  287. stream,
  288. buffer,
  289. detail::read_some_condition<
  290. isRequest>{parser},
  291. std::forward<ReadHandler>(handler));
  292. }
  293. //------------------------------------------------------------------------------
  294. template<
  295. class SyncReadStream,
  296. class DynamicBuffer,
  297. bool isRequest>
  298. std::size_t
  299. read_header(
  300. SyncReadStream& stream,
  301. DynamicBuffer& buffer,
  302. basic_parser<isRequest>& parser)
  303. {
  304. static_assert(
  305. is_sync_read_stream<SyncReadStream>::value,
  306. "SyncReadStream type requirements not met");
  307. static_assert(
  308. net::is_dynamic_buffer<DynamicBuffer>::value,
  309. "DynamicBuffer type requirements not met");
  310. error_code ec;
  311. auto const bytes_transferred =
  312. http::read_header(stream, buffer, parser, ec);
  313. if(ec)
  314. BOOST_THROW_EXCEPTION(system_error{ec});
  315. return bytes_transferred;
  316. }
  317. template<
  318. class SyncReadStream,
  319. class DynamicBuffer,
  320. bool isRequest>
  321. std::size_t
  322. read_header(
  323. SyncReadStream& stream,
  324. DynamicBuffer& buffer,
  325. basic_parser<isRequest>& parser,
  326. error_code& ec)
  327. {
  328. static_assert(
  329. is_sync_read_stream<SyncReadStream>::value,
  330. "SyncReadStream type requirements not met");
  331. static_assert(
  332. net::is_dynamic_buffer<DynamicBuffer>::value,
  333. "DynamicBuffer type requirements not met");
  334. parser.eager(false);
  335. return beast::detail::read(stream, buffer,
  336. detail::read_header_condition<
  337. isRequest>{parser}, ec);
  338. }
  339. template<
  340. class AsyncReadStream,
  341. class DynamicBuffer,
  342. bool isRequest,
  343. class ReadHandler>
  344. BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
  345. async_read_header(
  346. AsyncReadStream& stream,
  347. DynamicBuffer& buffer,
  348. basic_parser<isRequest>& parser,
  349. ReadHandler&& handler)
  350. {
  351. parser.eager(false);
  352. return beast::detail::async_read(
  353. stream,
  354. buffer,
  355. detail::read_header_condition<
  356. isRequest>{parser},
  357. std::forward<ReadHandler>(handler));
  358. }
  359. //------------------------------------------------------------------------------
  360. template<
  361. class SyncReadStream,
  362. class DynamicBuffer,
  363. bool isRequest>
  364. std::size_t
  365. read(
  366. SyncReadStream& stream,
  367. DynamicBuffer& buffer,
  368. basic_parser<isRequest>& parser)
  369. {
  370. static_assert(
  371. is_sync_read_stream<SyncReadStream>::value,
  372. "SyncReadStream type requirements not met");
  373. static_assert(
  374. net::is_dynamic_buffer<DynamicBuffer>::value,
  375. "DynamicBuffer type requirements not met");
  376. error_code ec;
  377. auto const bytes_transferred =
  378. http::read(stream, buffer, parser, ec);
  379. if(ec)
  380. BOOST_THROW_EXCEPTION(system_error{ec});
  381. return bytes_transferred;
  382. }
  383. template<
  384. class SyncReadStream,
  385. class DynamicBuffer,
  386. bool isRequest>
  387. std::size_t
  388. read(
  389. SyncReadStream& stream,
  390. DynamicBuffer& buffer,
  391. basic_parser<isRequest>& parser,
  392. error_code& ec)
  393. {
  394. static_assert(
  395. is_sync_read_stream<SyncReadStream>::value,
  396. "SyncReadStream type requirements not met");
  397. static_assert(
  398. net::is_dynamic_buffer<DynamicBuffer>::value,
  399. "DynamicBuffer type requirements not met");
  400. parser.eager(true);
  401. return beast::detail::read(stream, buffer,
  402. detail::read_all_condition<
  403. isRequest>{parser}, ec);
  404. }
  405. template<
  406. class AsyncReadStream,
  407. class DynamicBuffer,
  408. bool isRequest,
  409. class ReadHandler>
  410. BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
  411. async_read(
  412. AsyncReadStream& stream,
  413. DynamicBuffer& buffer,
  414. basic_parser<isRequest>& parser,
  415. ReadHandler&& handler)
  416. {
  417. static_assert(
  418. is_async_read_stream<AsyncReadStream>::value,
  419. "AsyncReadStream type requirements not met");
  420. static_assert(
  421. net::is_dynamic_buffer<DynamicBuffer>::value,
  422. "DynamicBuffer type requirements not met");
  423. parser.eager(true);
  424. return beast::detail::async_read(
  425. stream,
  426. buffer,
  427. detail::read_all_condition<
  428. isRequest>{parser},
  429. std::forward<ReadHandler>(handler));
  430. }
  431. //------------------------------------------------------------------------------
  432. template<
  433. class SyncReadStream,
  434. class DynamicBuffer,
  435. bool isRequest, class Body, class Allocator>
  436. std::size_t
  437. read(
  438. SyncReadStream& stream,
  439. DynamicBuffer& buffer,
  440. message<isRequest, Body, basic_fields<Allocator>>& msg)
  441. {
  442. static_assert(
  443. is_sync_read_stream<SyncReadStream>::value,
  444. "SyncReadStream type requirements not met");
  445. static_assert(
  446. net::is_dynamic_buffer<DynamicBuffer>::value,
  447. "DynamicBuffer type requirements not met");
  448. static_assert(is_body<Body>::value,
  449. "Body type requirements not met");
  450. static_assert(is_body_reader<Body>::value,
  451. "BodyReader type requirements not met");
  452. error_code ec;
  453. auto const bytes_transferred =
  454. http::read(stream, buffer, msg, ec);
  455. if(ec)
  456. BOOST_THROW_EXCEPTION(system_error{ec});
  457. return bytes_transferred;
  458. }
  459. template<
  460. class SyncReadStream,
  461. class DynamicBuffer,
  462. bool isRequest, class Body, class Allocator>
  463. std::size_t
  464. read(
  465. SyncReadStream& stream,
  466. DynamicBuffer& buffer,
  467. message<isRequest, Body, basic_fields<Allocator>>& msg,
  468. error_code& ec)
  469. {
  470. static_assert(
  471. is_sync_read_stream<SyncReadStream>::value,
  472. "SyncReadStream type requirements not met");
  473. static_assert(
  474. net::is_dynamic_buffer<DynamicBuffer>::value,
  475. "DynamicBuffer type requirements not met");
  476. static_assert(is_body<Body>::value,
  477. "Body type requirements not met");
  478. static_assert(is_body_reader<Body>::value,
  479. "BodyReader type requirements not met");
  480. parser<isRequest, Body, Allocator> p(std::move(msg));
  481. p.eager(true);
  482. auto const bytes_transferred =
  483. http::read(stream, buffer, p, ec);
  484. if(ec)
  485. return bytes_transferred;
  486. msg = p.release();
  487. return bytes_transferred;
  488. }
  489. template<
  490. class AsyncReadStream,
  491. class DynamicBuffer,
  492. bool isRequest, class Body, class Allocator,
  493. class ReadHandler>
  494. BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
  495. async_read(
  496. AsyncReadStream& stream,
  497. DynamicBuffer& buffer,
  498. message<isRequest, Body, basic_fields<Allocator>>& msg,
  499. ReadHandler&& handler)
  500. {
  501. static_assert(
  502. is_async_read_stream<AsyncReadStream>::value,
  503. "AsyncReadStream type requirements not met");
  504. static_assert(
  505. net::is_dynamic_buffer<DynamicBuffer>::value,
  506. "DynamicBuffer type requirements not met");
  507. static_assert(is_body<Body>::value,
  508. "Body type requirements not met");
  509. static_assert(is_body_reader<Body>::value,
  510. "BodyReader type requirements not met");
  511. return net::async_initiate<
  512. ReadHandler,
  513. void(error_code, std::size_t)>(
  514. detail::run_read_msg_op{},
  515. handler, &stream, &buffer, &msg);
  516. }
  517. } // http
  518. } // beast
  519. } // boost
  520. #endif