flat_stream.hpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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_FLAT_STREAM_HPP
  10. #define BOOST_BEAST_CORE_IMPL_FLAT_STREAM_HPP
  11. #include <boost/beast/core/async_base.hpp>
  12. #include <boost/beast/core/buffers_prefix.hpp>
  13. #include <boost/beast/core/static_buffer.hpp>
  14. #include <boost/beast/core/stream_traits.hpp>
  15. #include <boost/beast/websocket/teardown.hpp>
  16. #include <boost/asio/buffer.hpp>
  17. #include <memory>
  18. namespace boost {
  19. namespace beast {
  20. template<class NextLayer>
  21. struct flat_stream<NextLayer>::ops
  22. {
  23. template<class Handler>
  24. class write_op
  25. : public async_base<Handler,
  26. beast::executor_type<flat_stream>>
  27. {
  28. public:
  29. template<
  30. class ConstBufferSequence,
  31. class Handler_>
  32. write_op(
  33. Handler_&& h,
  34. flat_stream<NextLayer>& s,
  35. ConstBufferSequence const& b)
  36. : async_base<Handler,
  37. beast::executor_type<flat_stream>>(
  38. std::forward<Handler_>(h),
  39. s.get_executor())
  40. {
  41. auto const result =
  42. flatten(b, max_size);
  43. if(result.flatten)
  44. {
  45. s.buffer_.clear();
  46. s.buffer_.commit(net::buffer_copy(
  47. s.buffer_.prepare(result.size),
  48. b, result.size));
  49. s.stream_.async_write_some(
  50. s.buffer_.data(), std::move(*this));
  51. }
  52. else
  53. {
  54. s.buffer_.clear();
  55. s.buffer_.shrink_to_fit();
  56. s.stream_.async_write_some(
  57. beast::buffers_prefix(
  58. result.size, b), std::move(*this));
  59. }
  60. }
  61. void
  62. operator()(
  63. boost::system::error_code ec,
  64. std::size_t bytes_transferred)
  65. {
  66. this->complete_now(ec, bytes_transferred);
  67. }
  68. };
  69. struct run_write_op
  70. {
  71. template<class WriteHandler, class Buffers>
  72. void
  73. operator()(
  74. WriteHandler&& h,
  75. flat_stream* s,
  76. Buffers const& b)
  77. {
  78. // If you get an error on the following line it means
  79. // that your handler does not meet the documented type
  80. // requirements for the handler.
  81. static_assert(
  82. beast::detail::is_invocable<WriteHandler,
  83. void(error_code, std::size_t)>::value,
  84. "WriteHandler type requirements not met");
  85. write_op<
  86. typename std::decay<WriteHandler>::type>(
  87. std::forward<WriteHandler>(h), *s, b);
  88. }
  89. };
  90. };
  91. //------------------------------------------------------------------------------
  92. template<class NextLayer>
  93. template<class... Args>
  94. flat_stream<NextLayer>::
  95. flat_stream(Args&&... args)
  96. : stream_(std::forward<Args>(args)...)
  97. {
  98. }
  99. template<class NextLayer>
  100. template<class MutableBufferSequence>
  101. std::size_t
  102. flat_stream<NextLayer>::
  103. read_some(MutableBufferSequence const& buffers)
  104. {
  105. static_assert(boost::beast::is_sync_read_stream<next_layer_type>::value,
  106. "SyncReadStream type requirements not met");
  107. static_assert(net::is_mutable_buffer_sequence<
  108. MutableBufferSequence>::value,
  109. "MutableBufferSequence type requirements not met");
  110. error_code ec;
  111. auto n = read_some(buffers, ec);
  112. if(ec)
  113. BOOST_THROW_EXCEPTION(boost::system::system_error{ec});
  114. return n;
  115. }
  116. template<class NextLayer>
  117. template<class MutableBufferSequence>
  118. std::size_t
  119. flat_stream<NextLayer>::
  120. read_some(MutableBufferSequence const& buffers, error_code& ec)
  121. {
  122. static_assert(boost::beast::is_sync_read_stream<next_layer_type>::value,
  123. "SyncReadStream type requirements not met");
  124. static_assert(net::is_mutable_buffer_sequence<
  125. MutableBufferSequence>::value,
  126. "MutableBufferSequence type requirements not met");
  127. return stream_.read_some(buffers, ec);
  128. }
  129. template<class NextLayer>
  130. template<
  131. class MutableBufferSequence,
  132. class ReadHandler>
  133. BOOST_BEAST_ASYNC_RESULT2(ReadHandler)
  134. flat_stream<NextLayer>::
  135. async_read_some(
  136. MutableBufferSequence const& buffers,
  137. ReadHandler&& handler)
  138. {
  139. static_assert(boost::beast::is_async_read_stream<next_layer_type>::value,
  140. "AsyncReadStream type requirements not met");
  141. static_assert(net::is_mutable_buffer_sequence<
  142. MutableBufferSequence >::value,
  143. "MutableBufferSequence type requirements not met");
  144. return stream_.async_read_some(
  145. buffers, std::forward<ReadHandler>(handler));
  146. }
  147. template<class NextLayer>
  148. template<class ConstBufferSequence>
  149. std::size_t
  150. flat_stream<NextLayer>::
  151. write_some(ConstBufferSequence const& buffers)
  152. {
  153. static_assert(boost::beast::is_sync_write_stream<next_layer_type>::value,
  154. "SyncWriteStream type requirements not met");
  155. static_assert(net::is_const_buffer_sequence<
  156. ConstBufferSequence>::value,
  157. "ConstBufferSequence type requirements not met");
  158. error_code ec;
  159. auto n = write_some(buffers, ec);
  160. if(ec)
  161. BOOST_THROW_EXCEPTION(boost::system::system_error{ec});
  162. return n;
  163. }
  164. template<class NextLayer>
  165. template<class ConstBufferSequence>
  166. std::size_t
  167. flat_stream<NextLayer>::
  168. stack_write_some(
  169. std::size_t size,
  170. ConstBufferSequence const& buffers,
  171. error_code& ec)
  172. {
  173. static_buffer<max_stack> b;
  174. b.commit(net::buffer_copy(
  175. b.prepare(size), buffers));
  176. return stream_.write_some(b.data(), ec);
  177. }
  178. template<class NextLayer>
  179. template<class ConstBufferSequence>
  180. std::size_t
  181. flat_stream<NextLayer>::
  182. write_some(ConstBufferSequence const& buffers, error_code& ec)
  183. {
  184. static_assert(boost::beast::is_sync_write_stream<next_layer_type>::value,
  185. "SyncWriteStream type requirements not met");
  186. static_assert(net::is_const_buffer_sequence<
  187. ConstBufferSequence>::value,
  188. "ConstBufferSequence type requirements not met");
  189. auto const result = flatten(buffers, max_size);
  190. if(result.flatten)
  191. {
  192. if(result.size <= max_stack)
  193. return stack_write_some(result.size, buffers, ec);
  194. buffer_.clear();
  195. buffer_.commit(net::buffer_copy(
  196. buffer_.prepare(result.size),
  197. buffers));
  198. return stream_.write_some(buffer_.data(), ec);
  199. }
  200. buffer_.clear();
  201. buffer_.shrink_to_fit();
  202. return stream_.write_some(
  203. boost::beast::buffers_prefix(result.size, buffers), ec);
  204. }
  205. template<class NextLayer>
  206. template<
  207. class ConstBufferSequence,
  208. class WriteHandler>
  209. BOOST_BEAST_ASYNC_RESULT2(WriteHandler)
  210. flat_stream<NextLayer>::
  211. async_write_some(
  212. ConstBufferSequence const& buffers,
  213. WriteHandler&& handler)
  214. {
  215. static_assert(boost::beast::is_async_write_stream<next_layer_type>::value,
  216. "AsyncWriteStream type requirements not met");
  217. static_assert(net::is_const_buffer_sequence<
  218. ConstBufferSequence>::value,
  219. "ConstBufferSequence type requirements not met");
  220. return net::async_initiate<
  221. WriteHandler,
  222. void(error_code, std::size_t)>(
  223. typename ops::run_write_op{},
  224. handler,
  225. this,
  226. buffers);
  227. }
  228. template<class NextLayer>
  229. void
  230. teardown(
  231. boost::beast::role_type role,
  232. flat_stream<NextLayer>& s,
  233. error_code& ec)
  234. {
  235. using boost::beast::websocket::teardown;
  236. teardown(role, s.next_layer(), ec);
  237. }
  238. template<class NextLayer, class TeardownHandler>
  239. void
  240. async_teardown(
  241. boost::beast::role_type role,
  242. flat_stream<NextLayer>& s,
  243. TeardownHandler&& handler)
  244. {
  245. using boost::beast::websocket::async_teardown;
  246. async_teardown(role, s.next_layer(), std::move(handler));
  247. }
  248. } // beast
  249. } // boost
  250. #endif