read.hpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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_DETAIL_IMPL_READ_HPP
  10. #define BOOST_BEAST_DETAIL_IMPL_READ_HPP
  11. #include <boost/beast/core/bind_handler.hpp>
  12. #include <boost/beast/core/async_base.hpp>
  13. #include <boost/beast/core/flat_static_buffer.hpp>
  14. #include <boost/beast/core/read_size.hpp>
  15. #include <boost/asio/basic_stream_socket.hpp>
  16. #include <boost/asio/coroutine.hpp>
  17. #include <boost/throw_exception.hpp>
  18. namespace boost {
  19. namespace beast {
  20. namespace detail {
  21. // The number of bytes in the stack buffer when using non-blocking.
  22. static std::size_t constexpr default_max_stack_buffer = 16384;
  23. //------------------------------------------------------------------------------
  24. struct dynamic_read_ops
  25. {
  26. // read into a dynamic buffer until the
  27. // condition is met or an error occurs
  28. template<
  29. class Stream,
  30. class DynamicBuffer,
  31. class Condition,
  32. class Handler>
  33. class read_op
  34. : public asio::coroutine
  35. , public async_base<
  36. Handler, beast::executor_type<Stream>>
  37. {
  38. Stream& s_;
  39. DynamicBuffer& b_;
  40. Condition cond_;
  41. error_code ec_;
  42. std::size_t total_ = 0;
  43. public:
  44. read_op(read_op&&) = default;
  45. template<class Handler_, class Condition_>
  46. read_op(
  47. Handler_&& h,
  48. Stream& s,
  49. DynamicBuffer& b,
  50. Condition_&& cond)
  51. : async_base<Handler,
  52. beast::executor_type<Stream>>(
  53. std::forward<Handler_>(h),
  54. s.get_executor())
  55. , s_(s)
  56. , b_(b)
  57. , cond_(std::forward<Condition_>(cond))
  58. {
  59. (*this)({}, 0, false);
  60. }
  61. void
  62. operator()(
  63. error_code ec,
  64. std::size_t bytes_transferred,
  65. bool cont = true)
  66. {
  67. std::size_t max_prepare;
  68. BOOST_ASIO_CORO_REENTER(*this)
  69. {
  70. for(;;)
  71. {
  72. max_prepare = beast::read_size(b_, cond_(ec, total_, b_));
  73. if(max_prepare == 0)
  74. break;
  75. BOOST_ASIO_CORO_YIELD
  76. s_.async_read_some(
  77. b_.prepare(max_prepare), std::move(*this));
  78. b_.commit(bytes_transferred);
  79. total_ += bytes_transferred;
  80. }
  81. if(! cont)
  82. {
  83. // run this handler "as-if" using net::post
  84. // to reduce template instantiations
  85. ec_ = ec;
  86. BOOST_ASIO_CORO_YIELD
  87. s_.async_read_some(
  88. b_.prepare(0), std::move(*this));
  89. ec = ec_;
  90. }
  91. this->complete_now(ec, total_);
  92. }
  93. }
  94. };
  95. //------------------------------------------------------------------------------
  96. struct run_read_op
  97. {
  98. template<
  99. class AsyncReadStream,
  100. class DynamicBuffer,
  101. class Condition,
  102. class ReadHandler>
  103. void
  104. operator()(
  105. ReadHandler&& h,
  106. AsyncReadStream* s,
  107. DynamicBuffer* b,
  108. Condition&& c)
  109. {
  110. // If you get an error on the following line it means
  111. // that your handler does not meet the documented type
  112. // requirements for the handler.
  113. static_assert(
  114. beast::detail::is_invocable<ReadHandler,
  115. void(error_code, std::size_t)>::value,
  116. "ReadHandler type requirements not met");
  117. read_op<
  118. AsyncReadStream,
  119. DynamicBuffer,
  120. typename std::decay<Condition>::type,
  121. typename std::decay<ReadHandler>::type>(
  122. std::forward<ReadHandler>(h),
  123. *s,
  124. *b,
  125. std::forward<Condition>(c));
  126. }
  127. };
  128. };
  129. //------------------------------------------------------------------------------
  130. template<
  131. class SyncReadStream,
  132. class DynamicBuffer,
  133. class CompletionCondition,
  134. class>
  135. std::size_t
  136. read(
  137. SyncReadStream& stream,
  138. DynamicBuffer& buffer,
  139. CompletionCondition cond)
  140. {
  141. static_assert(is_sync_read_stream<SyncReadStream>::value,
  142. "SyncReadStream type requirements not met");
  143. static_assert(
  144. net::is_dynamic_buffer<DynamicBuffer>::value,
  145. "DynamicBuffer type requirements not met");
  146. static_assert(
  147. detail::is_invocable<CompletionCondition,
  148. void(error_code&, std::size_t, DynamicBuffer&)>::value,
  149. "CompletionCondition type requirements not met");
  150. error_code ec;
  151. auto const bytes_transferred = detail::read(
  152. stream, buffer, std::move(cond), ec);
  153. if(ec)
  154. BOOST_THROW_EXCEPTION(system_error{ec});
  155. return bytes_transferred;
  156. }
  157. template<
  158. class SyncReadStream,
  159. class DynamicBuffer,
  160. class CompletionCondition,
  161. class>
  162. std::size_t
  163. read(
  164. SyncReadStream& stream,
  165. DynamicBuffer& buffer,
  166. CompletionCondition cond,
  167. error_code& ec)
  168. {
  169. static_assert(is_sync_read_stream<SyncReadStream>::value,
  170. "SyncReadStream type requirements not met");
  171. static_assert(
  172. net::is_dynamic_buffer<DynamicBuffer>::value,
  173. "DynamicBuffer type requirements not met");
  174. static_assert(
  175. detail::is_invocable<CompletionCondition,
  176. void(error_code&, std::size_t, DynamicBuffer&)>::value,
  177. "CompletionCondition type requirements not met");
  178. ec = {};
  179. std::size_t total = 0;
  180. std::size_t max_prepare;
  181. for(;;)
  182. {
  183. max_prepare = beast::read_size(buffer, cond(ec, total, buffer));
  184. if(max_prepare == 0)
  185. break;
  186. std::size_t const bytes_transferred =
  187. stream.read_some(buffer.prepare(max_prepare), ec);
  188. buffer.commit(bytes_transferred);
  189. total += bytes_transferred;
  190. }
  191. return total;
  192. }
  193. template<
  194. class AsyncReadStream,
  195. class DynamicBuffer,
  196. class CompletionCondition,
  197. class ReadHandler,
  198. class>
  199. BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
  200. async_read(
  201. AsyncReadStream& stream,
  202. DynamicBuffer& buffer,
  203. CompletionCondition&& cond,
  204. ReadHandler&& handler)
  205. {
  206. static_assert(is_async_read_stream<AsyncReadStream>::value,
  207. "AsyncReadStream type requirements not met");
  208. static_assert(
  209. net::is_dynamic_buffer<DynamicBuffer>::value,
  210. "DynamicBuffer type requirements not met");
  211. static_assert(
  212. detail::is_invocable<CompletionCondition,
  213. void(error_code&, std::size_t, DynamicBuffer&)>::value,
  214. "CompletionCondition type requirements not met");
  215. return net::async_initiate<
  216. ReadHandler,
  217. void(error_code, std::size_t)>(
  218. typename dynamic_read_ops::run_read_op{},
  219. handler,
  220. &stream,
  221. &buffer,
  222. std::forward<CompletionCondition>(cond));
  223. }
  224. } // detail
  225. } // beast
  226. } // boost
  227. #endif