stream.hpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  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 BHO_BEAST_WEBSOCKET_IMPL_STREAM_HPP
  10. #define BHO_BEAST_WEBSOCKET_IMPL_STREAM_HPP
  11. #include <asio2/bho/beast/core/buffer_traits.hpp>
  12. #include <asio2/bho/beast/websocket/rfc6455.hpp>
  13. #include <asio2/bho/beast/websocket/teardown.hpp>
  14. #include <asio2/bho/beast/websocket/detail/hybi13.hpp>
  15. #include <asio2/bho/beast/websocket/detail/mask.hpp>
  16. #include <asio2/bho/beast/websocket/impl/stream_impl.hpp>
  17. #include <asio2/bho/beast/version.hpp>
  18. #include <asio2/bho/beast/http/read.hpp>
  19. #include <asio2/bho/beast/http/write.hpp>
  20. #include <asio2/bho/beast/http/rfc7230.hpp>
  21. #include <asio2/bho/beast/core/buffers_cat.hpp>
  22. #include <asio2/bho/beast/core/buffers_prefix.hpp>
  23. #include <asio2/bho/beast/core/buffers_suffix.hpp>
  24. #include <asio2/bho/beast/core/flat_static_buffer.hpp>
  25. #include <asio2/bho/beast/core/detail/clamp.hpp>
  26. #include <asio/steady_timer.hpp>
  27. #include <asio2/bho/assert.hpp>
  28. #include <asio2/bho/throw_exception.hpp>
  29. #include <algorithm>
  30. #include <chrono>
  31. #include <memory>
  32. #include <stdexcept>
  33. #include <utility>
  34. namespace bho {
  35. namespace beast {
  36. namespace websocket {
  37. template<class NextLayer, bool deflateSupported>
  38. stream<NextLayer, deflateSupported>::
  39. ~stream()
  40. {
  41. if(impl_)
  42. impl_->remove();
  43. }
  44. template<class NextLayer, bool deflateSupported>
  45. template<class... Args>
  46. stream<NextLayer, deflateSupported>::
  47. stream(Args&&... args)
  48. : impl_(std::make_shared<impl_type>(
  49. std::forward<Args>(args)...))
  50. {
  51. BHO_ASSERT(impl_->rd_buf.max_size() >=
  52. max_control_frame_size);
  53. }
  54. template<class NextLayer, bool deflateSupported>
  55. template<class Other>
  56. stream<NextLayer, deflateSupported>::
  57. stream(stream<Other> && other)
  58. : impl_(std::make_shared<impl_type>(std::move(other.next_layer())))
  59. {
  60. }
  61. template<class NextLayer, bool deflateSupported>
  62. auto
  63. stream<NextLayer, deflateSupported>::
  64. get_executor() noexcept ->
  65. executor_type
  66. {
  67. return impl_->stream().get_executor();
  68. }
  69. template<class NextLayer, bool deflateSupported>
  70. auto
  71. stream<NextLayer, deflateSupported>::
  72. next_layer() noexcept ->
  73. next_layer_type&
  74. {
  75. return impl_->stream();
  76. }
  77. template<class NextLayer, bool deflateSupported>
  78. auto
  79. stream<NextLayer, deflateSupported>::
  80. next_layer() const noexcept ->
  81. next_layer_type const&
  82. {
  83. return impl_->stream();
  84. }
  85. template<class NextLayer, bool deflateSupported>
  86. bool
  87. stream<NextLayer, deflateSupported>::
  88. is_open() const noexcept
  89. {
  90. return impl_->status_ == status::open;
  91. }
  92. template<class NextLayer, bool deflateSupported>
  93. bool
  94. stream<NextLayer, deflateSupported>::
  95. got_binary() const noexcept
  96. {
  97. return impl_->rd_op == detail::opcode::binary;
  98. }
  99. template<class NextLayer, bool deflateSupported>
  100. bool
  101. stream<NextLayer, deflateSupported>::
  102. is_message_done() const noexcept
  103. {
  104. return impl_->rd_done;
  105. }
  106. template<class NextLayer, bool deflateSupported>
  107. close_reason const&
  108. stream<NextLayer, deflateSupported>::
  109. reason() const noexcept
  110. {
  111. return impl_->cr;
  112. }
  113. template<class NextLayer, bool deflateSupported>
  114. std::size_t
  115. stream<NextLayer, deflateSupported>::
  116. read_size_hint(
  117. std::size_t initial_size) const
  118. {
  119. return impl_->read_size_hint_pmd(
  120. initial_size, impl_->rd_done,
  121. impl_->rd_remain, impl_->rd_fh);
  122. }
  123. template<class NextLayer, bool deflateSupported>
  124. template<class DynamicBuffer, class>
  125. std::size_t
  126. stream<NextLayer, deflateSupported>::
  127. read_size_hint(DynamicBuffer& buffer) const
  128. {
  129. static_assert(
  130. net::is_dynamic_buffer<DynamicBuffer>::value,
  131. "DynamicBuffer type requirements not met");
  132. return impl_->read_size_hint_db(buffer);
  133. }
  134. //------------------------------------------------------------------------------
  135. //
  136. // Settings
  137. //
  138. //------------------------------------------------------------------------------
  139. // decorator
  140. template<class NextLayer, bool deflateSupported>
  141. void
  142. stream<NextLayer, deflateSupported>::
  143. set_option(decorator opt)
  144. {
  145. impl_->decorator_opt = std::move(opt.d_);
  146. }
  147. // timeout
  148. template<class NextLayer, bool deflateSupported>
  149. void
  150. stream<NextLayer, deflateSupported>::
  151. get_option(timeout& opt)
  152. {
  153. opt = impl_->timeout_opt;
  154. }
  155. template<class NextLayer, bool deflateSupported>
  156. void
  157. stream<NextLayer, deflateSupported>::
  158. set_option(timeout const& opt)
  159. {
  160. impl_->set_option(opt);
  161. }
  162. //
  163. template<class NextLayer, bool deflateSupported>
  164. void
  165. stream<NextLayer, deflateSupported>::
  166. set_option(permessage_deflate const& o)
  167. {
  168. impl_->set_option_pmd(o);
  169. }
  170. template<class NextLayer, bool deflateSupported>
  171. void
  172. stream<NextLayer, deflateSupported>::
  173. get_option(permessage_deflate& o)
  174. {
  175. impl_->get_option_pmd(o);
  176. }
  177. template<class NextLayer, bool deflateSupported>
  178. void
  179. stream<NextLayer, deflateSupported>::
  180. auto_fragment(bool value)
  181. {
  182. impl_->wr_frag_opt = value;
  183. }
  184. template<class NextLayer, bool deflateSupported>
  185. bool
  186. stream<NextLayer, deflateSupported>::
  187. auto_fragment() const
  188. {
  189. return impl_->wr_frag_opt;
  190. }
  191. template<class NextLayer, bool deflateSupported>
  192. void
  193. stream<NextLayer, deflateSupported>::
  194. binary(bool value)
  195. {
  196. impl_->wr_opcode = value ?
  197. detail::opcode::binary :
  198. detail::opcode::text;
  199. }
  200. template<class NextLayer, bool deflateSupported>
  201. bool
  202. stream<NextLayer, deflateSupported>::
  203. binary() const
  204. {
  205. return impl_->wr_opcode == detail::opcode::binary;
  206. }
  207. template<class NextLayer, bool deflateSupported>
  208. void
  209. stream<NextLayer, deflateSupported>::
  210. control_callback(std::function<
  211. void(frame_type, string_view)> cb)
  212. {
  213. impl_->ctrl_cb = std::move(cb);
  214. }
  215. template<class NextLayer, bool deflateSupported>
  216. void
  217. stream<NextLayer, deflateSupported>::
  218. control_callback()
  219. {
  220. impl_->ctrl_cb = {};
  221. }
  222. template<class NextLayer, bool deflateSupported>
  223. void
  224. stream<NextLayer, deflateSupported>::
  225. read_message_max(std::size_t amount)
  226. {
  227. impl_->rd_msg_max = amount;
  228. }
  229. template<class NextLayer, bool deflateSupported>
  230. std::size_t
  231. stream<NextLayer, deflateSupported>::
  232. read_message_max() const
  233. {
  234. return impl_->rd_msg_max;
  235. }
  236. template<class NextLayer, bool deflateSupported>
  237. void
  238. stream<NextLayer, deflateSupported>::
  239. secure_prng(bool value)
  240. {
  241. this->impl_->secure_prng_ = value;
  242. }
  243. template<class NextLayer, bool deflateSupported>
  244. void
  245. stream<NextLayer, deflateSupported>::
  246. write_buffer_bytes(std::size_t amount)
  247. {
  248. if(amount < 8)
  249. BHO_THROW_EXCEPTION(std::invalid_argument{
  250. "write buffer size underflow"});
  251. impl_->wr_buf_opt = amount;
  252. }
  253. template<class NextLayer, bool deflateSupported>
  254. std::size_t
  255. stream<NextLayer, deflateSupported>::
  256. write_buffer_bytes() const
  257. {
  258. return impl_->wr_buf_opt;
  259. }
  260. template<class NextLayer, bool deflateSupported>
  261. void
  262. stream<NextLayer, deflateSupported>::
  263. text(bool value)
  264. {
  265. impl_->wr_opcode = value ?
  266. detail::opcode::text :
  267. detail::opcode::binary;
  268. }
  269. template<class NextLayer, bool deflateSupported>
  270. bool
  271. stream<NextLayer, deflateSupported>::
  272. text() const
  273. {
  274. return impl_->wr_opcode == detail::opcode::text;
  275. }
  276. template<class NextLayer, bool deflateSupported>
  277. void
  278. stream<NextLayer, deflateSupported>::
  279. compress(bool value)
  280. {
  281. impl_->wr_compress_opt = value;
  282. }
  283. template<class NextLayer, bool deflateSupported>
  284. bool
  285. stream<NextLayer, deflateSupported>::
  286. compress() const
  287. {
  288. return impl_->wr_compress_opt;
  289. }
  290. //------------------------------------------------------------------------------
  291. // _Fail the WebSocket Connection_
  292. template<class NextLayer, bool deflateSupported>
  293. void
  294. stream<NextLayer, deflateSupported>::
  295. do_fail(
  296. std::uint16_t code, // if set, send a close frame first
  297. error_code ev, // error code to use upon success
  298. error_code& ec) // set to the error, else set to ev
  299. {
  300. BHO_ASSERT(ev);
  301. impl_->change_status(status::closing);
  302. if(code != close_code::none && ! impl_->wr_close)
  303. {
  304. impl_->wr_close = true;
  305. detail::frame_buffer fb;
  306. impl_->template write_close<
  307. flat_static_buffer_base>(fb, code);
  308. net::write(impl_->stream(), fb.data(), ec);
  309. if(impl_->check_stop_now(ec))
  310. return;
  311. }
  312. using beast::websocket::teardown;
  313. teardown(impl_->role, impl_->stream(), ec);
  314. if(ec == net::error::eof)
  315. {
  316. // Rationale:
  317. // http://stackoverflow.com/questions/25587403/boost-asio-ssl-async-shutdown-always-finishes-with-an-error
  318. ec = {};
  319. }
  320. if(! ec)
  321. {
  322. BHO_BEAST_ASSIGN_EC(ec, ev);
  323. }
  324. if(ec && ec != error::closed)
  325. impl_->change_status(status::failed);
  326. else
  327. impl_->change_status(status::closed);
  328. impl_->close();
  329. }
  330. } // websocket
  331. } // beast
  332. } // bho
  333. #endif