icy_stream.hpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  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_CORE_IMPL_ICY_STREAM_HPP
  10. #define BOOST_BEAST_CORE_IMPL_ICY_STREAM_HPP
  11. #include <boost/beast/core/async_base.hpp>
  12. #include <boost/beast/core/buffer_traits.hpp>
  13. #include <boost/beast/core/error.hpp>
  14. #include <boost/beast/core/stream_traits.hpp>
  15. #include <boost/beast/core/detail/is_invocable.hpp>
  16. #include <boost/asio/coroutine.hpp>
  17. #include <boost/assert.hpp>
  18. #include <boost/throw_exception.hpp>
  19. #include <cstring>
  20. #include <memory>
  21. #include <utility>
  22. namespace boost {
  23. namespace beast {
  24. namespace http {
  25. namespace detail {
  26. template<class ConstBufferSequence>
  27. boost::tribool
  28. is_icy(ConstBufferSequence const& buffers)
  29. {
  30. char buf[3];
  31. auto const n = net::buffer_copy(
  32. net::mutable_buffer(buf, 3),
  33. buffers);
  34. if(n >= 1 && buf[0] != 'I')
  35. return false;
  36. if(n >= 2 && buf[1] != 'C')
  37. return false;
  38. if(n >= 3 && buf[2] != 'Y')
  39. return false;
  40. if(n < 3)
  41. return boost::indeterminate;
  42. return true;
  43. }
  44. } // detail
  45. template<class NextLayer>
  46. struct icy_stream<NextLayer>::ops
  47. {
  48. template<class Buffers, class Handler>
  49. class read_op
  50. : public beast::async_base<Handler,
  51. beast::executor_type<icy_stream>>
  52. , public asio::coroutine
  53. {
  54. icy_stream& s_;
  55. Buffers b_;
  56. std::size_t n_ = 0;
  57. error_code ec_;
  58. bool match_ = false;
  59. public:
  60. template<class Handler_>
  61. read_op(
  62. Handler_&& h,
  63. icy_stream& s,
  64. Buffers const& b)
  65. : async_base<Handler,
  66. beast::executor_type<icy_stream>>(
  67. std::forward<Handler_>(h), s.get_executor())
  68. , s_(s)
  69. , b_(b)
  70. {
  71. (*this)({}, 0, false);
  72. }
  73. void
  74. operator()(
  75. error_code ec,
  76. std::size_t bytes_transferred,
  77. bool cont = true)
  78. {
  79. BOOST_ASIO_CORO_REENTER(*this)
  80. {
  81. if(s_.detect_)
  82. {
  83. BOOST_ASSERT(s_.n_ == 0);
  84. for(;;)
  85. {
  86. // Try to read the first three characters
  87. BOOST_ASIO_CORO_YIELD
  88. s_.next_layer().async_read_some(
  89. net::mutable_buffer(
  90. s_.buf_ + s_.n_, 3 - s_.n_),
  91. std::move(*this));
  92. s_.n_ += static_cast<char>(bytes_transferred);
  93. if(ec)
  94. goto upcall;
  95. auto result = detail::is_icy(
  96. net::const_buffer(s_.buf_, s_.n_));
  97. if(boost::indeterminate(result))
  98. continue;
  99. if(result)
  100. s_.n_ = static_cast<char>(net::buffer_copy(
  101. net::buffer(s_.buf_, sizeof(s_.buf_)),
  102. icy_stream::version()));
  103. break;
  104. }
  105. s_.detect_ = false;
  106. }
  107. if(s_.n_ > 0)
  108. {
  109. bytes_transferred = net::buffer_copy(
  110. b_, net::const_buffer(s_.buf_, s_.n_));
  111. s_.n_ -= static_cast<char>(bytes_transferred);
  112. std::memmove(
  113. s_.buf_,
  114. s_.buf_ + bytes_transferred,
  115. sizeof(s_.buf_) - bytes_transferred);
  116. }
  117. else
  118. {
  119. BOOST_ASIO_CORO_YIELD
  120. s_.next_layer().async_read_some(
  121. b_, std::move(*this));
  122. }
  123. upcall:
  124. if(! cont)
  125. {
  126. ec_ = ec;
  127. n_ = bytes_transferred;
  128. BOOST_ASIO_CORO_YIELD
  129. s_.next_layer().async_read_some(
  130. net::mutable_buffer{},
  131. std::move(*this));
  132. ec = ec_;
  133. bytes_transferred = n_;
  134. }
  135. this->complete_now(ec, bytes_transferred);
  136. }
  137. }
  138. };
  139. struct run_read_op
  140. {
  141. template<class ReadHandler, class Buffers>
  142. void
  143. operator()(
  144. ReadHandler&& h,
  145. icy_stream* s,
  146. Buffers const& b)
  147. {
  148. // If you get an error on the following line it means
  149. // that your handler does not meet the documented type
  150. // requirements for the handler.
  151. static_assert(
  152. beast::detail::is_invocable<ReadHandler,
  153. void(error_code, std::size_t)>::value,
  154. "ReadHandler type requirements not met");
  155. read_op<
  156. Buffers,
  157. typename std::decay<ReadHandler>::type>(
  158. std::forward<ReadHandler>(h), *s, b);
  159. }
  160. };
  161. };
  162. //------------------------------------------------------------------------------
  163. template<class NextLayer>
  164. template<class... Args>
  165. icy_stream<NextLayer>::
  166. icy_stream(Args&&... args)
  167. : stream_(std::forward<Args>(args)...)
  168. {
  169. std::memset(buf_, 0, sizeof(buf_));
  170. }
  171. template<class NextLayer>
  172. template<class MutableBufferSequence>
  173. std::size_t
  174. icy_stream<NextLayer>::
  175. read_some(MutableBufferSequence const& buffers)
  176. {
  177. static_assert(is_sync_read_stream<next_layer_type>::value,
  178. "SyncReadStream type requirements not met");
  179. static_assert(net::is_mutable_buffer_sequence<
  180. MutableBufferSequence>::value,
  181. "MutableBufferSequence type requirements not met");
  182. error_code ec;
  183. auto n = read_some(buffers, ec);
  184. if(ec)
  185. BOOST_THROW_EXCEPTION(system_error{ec});
  186. return n;
  187. }
  188. template<class NextLayer>
  189. template<class MutableBufferSequence>
  190. std::size_t
  191. icy_stream<NextLayer>::
  192. read_some(MutableBufferSequence const& buffers, error_code& ec)
  193. {
  194. static_assert(is_sync_read_stream<next_layer_type>::value,
  195. "SyncReadStream type requirements not met");
  196. static_assert(net::is_mutable_buffer_sequence<
  197. MutableBufferSequence>::value,
  198. "MutableBufferSequence type requirements not met");
  199. std::size_t bytes_transferred;
  200. if(detect_)
  201. {
  202. BOOST_ASSERT(n_ == 0);
  203. for(;;)
  204. {
  205. // Try to read the first three characters
  206. bytes_transferred = next_layer().read_some(
  207. net::mutable_buffer(buf_ + n_, 3 - n_), ec);
  208. n_ += static_cast<char>(bytes_transferred);
  209. if(ec)
  210. return 0;
  211. auto result = detail::is_icy(
  212. net::const_buffer(buf_, n_));
  213. if(boost::indeterminate(result))
  214. continue;
  215. if(result)
  216. n_ = static_cast<char>(net::buffer_copy(
  217. net::buffer(buf_, sizeof(buf_)),
  218. icy_stream::version()));
  219. break;
  220. }
  221. detect_ = false;
  222. }
  223. if(n_ > 0)
  224. {
  225. bytes_transferred = net::buffer_copy(
  226. buffers, net::const_buffer(buf_, n_));
  227. n_ -= static_cast<char>(bytes_transferred);
  228. std::memmove(
  229. buf_,
  230. buf_ + bytes_transferred,
  231. sizeof(buf_) - bytes_transferred);
  232. }
  233. else
  234. {
  235. bytes_transferred =
  236. next_layer().read_some(buffers, ec);
  237. }
  238. return bytes_transferred;
  239. }
  240. template<class NextLayer>
  241. template<
  242. class MutableBufferSequence,
  243. class ReadHandler>
  244. BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
  245. icy_stream<NextLayer>::
  246. async_read_some(
  247. MutableBufferSequence const& buffers,
  248. ReadHandler&& handler)
  249. {
  250. static_assert(is_async_read_stream<next_layer_type>::value,
  251. "AsyncReadStream type requirements not met");
  252. static_assert(net::is_mutable_buffer_sequence<
  253. MutableBufferSequence >::value,
  254. "MutableBufferSequence type requirements not met");
  255. return net::async_initiate<
  256. ReadHandler,
  257. void(error_code, std::size_t)>(
  258. typename ops::run_read_op{},
  259. handler,
  260. this,
  261. buffers);
  262. }
  263. template<class NextLayer>
  264. template<class MutableBufferSequence>
  265. std::size_t
  266. icy_stream<NextLayer>::
  267. write_some(MutableBufferSequence const& buffers)
  268. {
  269. static_assert(is_sync_write_stream<next_layer_type>::value,
  270. "SyncWriteStream type requirements not met");
  271. static_assert(net::is_const_buffer_sequence<
  272. MutableBufferSequence>::value,
  273. "MutableBufferSequence type requirements not met");
  274. return stream_.write_some(buffers);
  275. }
  276. template<class NextLayer>
  277. template<class MutableBufferSequence>
  278. std::size_t
  279. icy_stream<NextLayer>::
  280. write_some(MutableBufferSequence const& buffers, error_code& ec)
  281. {
  282. static_assert(is_sync_write_stream<next_layer_type>::value,
  283. "SyncWriteStream type requirements not met");
  284. static_assert(net::is_const_buffer_sequence<
  285. MutableBufferSequence>::value,
  286. "MutableBufferSequence type requirements not met");
  287. return stream_.write_some(buffers, ec);
  288. }
  289. template<class NextLayer>
  290. template<
  291. class MutableBufferSequence,
  292. class WriteHandler>
  293. BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
  294. icy_stream<NextLayer>::
  295. async_write_some(
  296. MutableBufferSequence const& buffers,
  297. WriteHandler&& handler)
  298. {
  299. static_assert(is_async_write_stream<next_layer_type>::value,
  300. "AsyncWriteStream type requirements not met");
  301. static_assert(net::is_const_buffer_sequence<
  302. MutableBufferSequence>::value,
  303. "MutableBufferSequence type requirements not met");
  304. return stream_.async_write_some(
  305. buffers, std::forward<WriteHandler>(handler));
  306. }
  307. } // http
  308. } // beast
  309. } // boost
  310. #endif