read.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  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(parser.got_some() && ! parser.is_done())
  60. ec = error::partial_message;
  61. return 0;
  62. }
  63. if(parser.is_done())
  64. return 0;
  65. if(buffer.size() > 0)
  66. {
  67. auto const bytes_used =
  68. parser.put(buffer.data(), ec);
  69. // total = total + bytes_used; // VFALCO Can't do this in a condition
  70. buffer.consume(bytes_used);
  71. if(ec == http::error::need_more)
  72. {
  73. if(buffer.size() >= buffer.max_size())
  74. {
  75. ec = http::error::buffer_overflow;
  76. return 0;
  77. }
  78. ec = {};
  79. }
  80. else if(ec || cond())
  81. {
  82. return 0;
  83. }
  84. }
  85. return default_max_transfer_size;
  86. }
  87. // predicate is true on any forward parser progress
  88. template<bool isRequest>
  89. struct read_some_condition
  90. {
  91. basic_parser<isRequest>& parser;
  92. template<class DynamicBuffer>
  93. std::size_t
  94. operator()(error_code& ec, std::size_t,
  95. DynamicBuffer& buffer)
  96. {
  97. return detail::parse_until(
  98. buffer, parser, ec,
  99. []
  100. {
  101. return true;
  102. });
  103. }
  104. };
  105. // predicate is true when parser header is complete
  106. template<bool isRequest>
  107. struct read_header_condition
  108. {
  109. basic_parser<isRequest>& parser;
  110. template<class DynamicBuffer>
  111. std::size_t
  112. operator()(error_code& ec, std::size_t,
  113. DynamicBuffer& buffer)
  114. {
  115. return detail::parse_until(
  116. buffer, parser, ec,
  117. [this]
  118. {
  119. return parser.is_header_done();
  120. });
  121. }
  122. };
  123. // predicate is true when parser message is complete
  124. template<bool isRequest>
  125. struct read_all_condition
  126. {
  127. basic_parser<isRequest>& parser;
  128. template<class DynamicBuffer>
  129. std::size_t
  130. operator()(error_code& ec, std::size_t,
  131. DynamicBuffer& buffer)
  132. {
  133. return detail::parse_until(
  134. buffer, parser, ec,
  135. [this]
  136. {
  137. return parser.is_done();
  138. });
  139. }
  140. };
  141. //------------------------------------------------------------------------------
  142. template<
  143. class Stream, class DynamicBuffer,
  144. bool isRequest, class Body, class Allocator,
  145. class Handler>
  146. class read_msg_op
  147. : public beast::stable_async_base<
  148. Handler, beast::executor_type<Stream>>
  149. , public net::coroutine
  150. {
  151. using parser_type =
  152. parser<isRequest, Body, Allocator>;
  153. using message_type =
  154. typename parser_type::value_type;
  155. struct data
  156. {
  157. Stream& s;
  158. message_type& m;
  159. parser_type p;
  160. data(
  161. Stream& s_,
  162. message_type& m_)
  163. : s(s_)
  164. , m(m_)
  165. , p(std::move(m))
  166. {
  167. }
  168. };
  169. data& d_;
  170. public:
  171. template<class Handler_>
  172. read_msg_op(
  173. Handler_&& h,
  174. Stream& s,
  175. DynamicBuffer& b,
  176. message_type& m)
  177. : stable_async_base<
  178. Handler, beast::executor_type<Stream>>(
  179. std::forward<Handler_>(h), s.get_executor())
  180. , d_(beast::allocate_stable<data>(
  181. *this, s, m))
  182. {
  183. http::async_read(d_.s, b, d_.p, std::move(*this));
  184. }
  185. void
  186. operator()(
  187. error_code ec,
  188. std::size_t bytes_transferred)
  189. {
  190. if(! ec)
  191. d_.m = d_.p.release();
  192. this->complete_now(ec, bytes_transferred);
  193. }
  194. };
  195. struct run_read_msg_op
  196. {
  197. template<
  198. class ReadHandler,
  199. class AsyncReadStream,
  200. class DynamicBuffer,
  201. bool isRequest, class Body, class Allocator>
  202. void
  203. operator()(
  204. ReadHandler&& h,
  205. AsyncReadStream* s,
  206. DynamicBuffer* b,
  207. message<isRequest, Body,
  208. basic_fields<Allocator>>* m)
  209. {
  210. // If you get an error on the following line it means
  211. // that your handler does not meet the documented type
  212. // requirements for the handler.
  213. static_assert(
  214. beast::detail::is_invocable<ReadHandler,
  215. void(error_code, std::size_t)>::value,
  216. "ReadHandler type requirements not met");
  217. read_msg_op<
  218. AsyncReadStream,
  219. DynamicBuffer,
  220. isRequest, Body, Allocator,
  221. typename std::decay<ReadHandler>::type>(
  222. std::forward<ReadHandler>(h), *s, *b, *m);
  223. }
  224. };
  225. } // detail
  226. //------------------------------------------------------------------------------
  227. template<
  228. class SyncReadStream,
  229. class DynamicBuffer,
  230. bool isRequest>
  231. std::size_t
  232. read_some(
  233. SyncReadStream& stream,
  234. DynamicBuffer& buffer,
  235. basic_parser<isRequest>& parser)
  236. {
  237. static_assert(
  238. is_sync_read_stream<SyncReadStream>::value,
  239. "SyncReadStream type requirements not met");
  240. static_assert(
  241. net::is_dynamic_buffer<DynamicBuffer>::value,
  242. "DynamicBuffer type requirements not met");
  243. error_code ec;
  244. auto const bytes_transferred =
  245. http::read_some(stream, buffer, parser, ec);
  246. if(ec)
  247. BOOST_THROW_EXCEPTION(system_error{ec});
  248. return bytes_transferred;
  249. }
  250. template<
  251. class SyncReadStream,
  252. class DynamicBuffer,
  253. bool isRequest>
  254. std::size_t
  255. read_some(
  256. SyncReadStream& stream,
  257. DynamicBuffer& buffer,
  258. basic_parser<isRequest>& parser,
  259. error_code& ec)
  260. {
  261. static_assert(
  262. is_sync_read_stream<SyncReadStream>::value,
  263. "SyncReadStream type requirements not met");
  264. static_assert(
  265. net::is_dynamic_buffer<DynamicBuffer>::value,
  266. "DynamicBuffer type requirements not met");
  267. return beast::detail::read(stream, buffer,
  268. detail::read_some_condition<
  269. isRequest>{parser}, ec);
  270. }
  271. template<
  272. class AsyncReadStream,
  273. class DynamicBuffer,
  274. bool isRequest,
  275. class ReadHandler>
  276. BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
  277. async_read_some(
  278. AsyncReadStream& stream,
  279. DynamicBuffer& buffer,
  280. basic_parser<isRequest>& parser,
  281. ReadHandler&& handler)
  282. {
  283. return beast::detail::async_read(
  284. stream,
  285. buffer,
  286. detail::read_some_condition<
  287. isRequest>{parser},
  288. std::forward<ReadHandler>(handler));
  289. }
  290. //------------------------------------------------------------------------------
  291. template<
  292. class SyncReadStream,
  293. class DynamicBuffer,
  294. bool isRequest>
  295. std::size_t
  296. read_header(
  297. SyncReadStream& stream,
  298. DynamicBuffer& buffer,
  299. basic_parser<isRequest>& parser)
  300. {
  301. static_assert(
  302. is_sync_read_stream<SyncReadStream>::value,
  303. "SyncReadStream type requirements not met");
  304. static_assert(
  305. net::is_dynamic_buffer<DynamicBuffer>::value,
  306. "DynamicBuffer type requirements not met");
  307. error_code ec;
  308. auto const bytes_transferred =
  309. http::read_header(stream, buffer, parser, ec);
  310. if(ec)
  311. BOOST_THROW_EXCEPTION(system_error{ec});
  312. return bytes_transferred;
  313. }
  314. template<
  315. class SyncReadStream,
  316. class DynamicBuffer,
  317. bool isRequest>
  318. std::size_t
  319. read_header(
  320. SyncReadStream& stream,
  321. DynamicBuffer& buffer,
  322. basic_parser<isRequest>& parser,
  323. error_code& ec)
  324. {
  325. static_assert(
  326. is_sync_read_stream<SyncReadStream>::value,
  327. "SyncReadStream type requirements not met");
  328. static_assert(
  329. net::is_dynamic_buffer<DynamicBuffer>::value,
  330. "DynamicBuffer type requirements not met");
  331. parser.eager(false);
  332. return beast::detail::read(stream, buffer,
  333. detail::read_header_condition<
  334. isRequest>{parser}, ec);
  335. }
  336. template<
  337. class AsyncReadStream,
  338. class DynamicBuffer,
  339. bool isRequest,
  340. class ReadHandler>
  341. BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
  342. async_read_header(
  343. AsyncReadStream& stream,
  344. DynamicBuffer& buffer,
  345. basic_parser<isRequest>& parser,
  346. ReadHandler&& handler)
  347. {
  348. parser.eager(false);
  349. return beast::detail::async_read(
  350. stream,
  351. buffer,
  352. detail::read_header_condition<
  353. isRequest>{parser},
  354. std::forward<ReadHandler>(handler));
  355. }
  356. //------------------------------------------------------------------------------
  357. template<
  358. class SyncReadStream,
  359. class DynamicBuffer,
  360. bool isRequest>
  361. std::size_t
  362. read(
  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(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(
  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. parser.eager(true);
  398. return beast::detail::read(stream, buffer,
  399. detail::read_all_condition<
  400. isRequest>{parser}, ec);
  401. }
  402. template<
  403. class AsyncReadStream,
  404. class DynamicBuffer,
  405. bool isRequest,
  406. class ReadHandler>
  407. BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
  408. async_read(
  409. AsyncReadStream& stream,
  410. DynamicBuffer& buffer,
  411. basic_parser<isRequest>& parser,
  412. ReadHandler&& handler)
  413. {
  414. static_assert(
  415. is_async_read_stream<AsyncReadStream>::value,
  416. "AsyncReadStream type requirements not met");
  417. static_assert(
  418. net::is_dynamic_buffer<DynamicBuffer>::value,
  419. "DynamicBuffer type requirements not met");
  420. parser.eager(true);
  421. return beast::detail::async_read(
  422. stream,
  423. buffer,
  424. detail::read_all_condition<
  425. isRequest>{parser},
  426. std::forward<ReadHandler>(handler));
  427. }
  428. //------------------------------------------------------------------------------
  429. template<
  430. class SyncReadStream,
  431. class DynamicBuffer,
  432. bool isRequest, class Body, class Allocator>
  433. std::size_t
  434. read(
  435. SyncReadStream& stream,
  436. DynamicBuffer& buffer,
  437. message<isRequest, Body, basic_fields<Allocator>>& msg)
  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. static_assert(is_body<Body>::value,
  446. "Body type requirements not met");
  447. static_assert(is_body_reader<Body>::value,
  448. "BodyReader type requirements not met");
  449. error_code ec;
  450. auto const bytes_transferred =
  451. http::read(stream, buffer, msg, ec);
  452. if(ec)
  453. BOOST_THROW_EXCEPTION(system_error{ec});
  454. return bytes_transferred;
  455. }
  456. template<
  457. class SyncReadStream,
  458. class DynamicBuffer,
  459. bool isRequest, class Body, class Allocator>
  460. std::size_t
  461. read(
  462. SyncReadStream& stream,
  463. DynamicBuffer& buffer,
  464. message<isRequest, Body, basic_fields<Allocator>>& msg,
  465. error_code& ec)
  466. {
  467. static_assert(
  468. is_sync_read_stream<SyncReadStream>::value,
  469. "SyncReadStream type requirements not met");
  470. static_assert(
  471. net::is_dynamic_buffer<DynamicBuffer>::value,
  472. "DynamicBuffer type requirements not met");
  473. static_assert(is_body<Body>::value,
  474. "Body type requirements not met");
  475. static_assert(is_body_reader<Body>::value,
  476. "BodyReader type requirements not met");
  477. parser<isRequest, Body, Allocator> p(std::move(msg));
  478. p.eager(true);
  479. auto const bytes_transferred =
  480. http::read(stream, buffer, p, ec);
  481. if(ec)
  482. return bytes_transferred;
  483. msg = p.release();
  484. return bytes_transferred;
  485. }
  486. template<
  487. class AsyncReadStream,
  488. class DynamicBuffer,
  489. bool isRequest, class Body, class Allocator,
  490. class ReadHandler>
  491. BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
  492. async_read(
  493. AsyncReadStream& stream,
  494. DynamicBuffer& buffer,
  495. message<isRequest, Body, basic_fields<Allocator>>& msg,
  496. ReadHandler&& handler)
  497. {
  498. static_assert(
  499. is_async_read_stream<AsyncReadStream>::value,
  500. "AsyncReadStream type requirements not met");
  501. static_assert(
  502. net::is_dynamic_buffer<DynamicBuffer>::value,
  503. "DynamicBuffer type requirements not met");
  504. static_assert(is_body<Body>::value,
  505. "Body type requirements not met");
  506. static_assert(is_body_reader<Body>::value,
  507. "BodyReader type requirements not met");
  508. return net::async_initiate<
  509. ReadHandler,
  510. void(error_code, std::size_t)>(
  511. detail::run_read_msg_op{},
  512. handler, &stream, &buffer, &msg);
  513. }
  514. } // http
  515. } // beast
  516. } // boost
  517. #endif