wss_session.hpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. /*
  2. * Copyright (c) 2017-2023 zhllxt
  3. *
  4. * author : zhllxt
  5. * email : 37792738@qq.com
  6. *
  7. * Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. */
  10. #if defined(ASIO2_ENABLE_SSL) || defined(ASIO2_USE_SSL)
  11. #ifndef __ASIO2_WSS_SESSION_HPP__
  12. #define __ASIO2_WSS_SESSION_HPP__
  13. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  14. #pragma once
  15. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  16. #include <asio2/base/detail/push_options.hpp>
  17. #include <asio2/tcp/tcps_session.hpp>
  18. #include <asio2/http/ws_session.hpp>
  19. namespace asio2::detail
  20. {
  21. struct template_args_wss_session : public template_args_ws_session
  22. {
  23. using stream_t = websocket::stream<asio::ssl::stream<typename template_args_ws_session::socket_t&>&>;
  24. };
  25. ASIO2_CLASS_FORWARD_DECLARE_BASE;
  26. ASIO2_CLASS_FORWARD_DECLARE_TCP_BASE;
  27. ASIO2_CLASS_FORWARD_DECLARE_TCP_SERVER;
  28. ASIO2_CLASS_FORWARD_DECLARE_TCP_SESSION;
  29. template<class derived_t, class args_t = template_args_wss_session>
  30. class wss_session_impl_t
  31. : public tcps_session_impl_t<derived_t, args_t>
  32. , public ws_stream_cp <derived_t, args_t>
  33. , public ws_send_op <derived_t, args_t>
  34. {
  35. ASIO2_CLASS_FRIEND_DECLARE_BASE;
  36. ASIO2_CLASS_FRIEND_DECLARE_TCP_BASE;
  37. ASIO2_CLASS_FRIEND_DECLARE_TCP_SERVER;
  38. ASIO2_CLASS_FRIEND_DECLARE_TCP_SESSION;
  39. public:
  40. using super = tcps_session_impl_t<derived_t, args_t>;
  41. using self = wss_session_impl_t <derived_t, args_t>;
  42. using args_type = args_t;
  43. using key_type = std::size_t;
  44. using body_type = typename args_t::body_t;
  45. using buffer_type = typename args_t::buffer_t;
  46. using ws_stream_comp = ws_stream_cp<derived_t, args_t>;
  47. using super::send;
  48. using super::async_send;
  49. public:
  50. /**
  51. * @brief constructor
  52. */
  53. explicit wss_session_impl_t(
  54. asio::ssl::context & ctx,
  55. session_mgr_t<derived_t> & sessions,
  56. listener_t & listener,
  57. std::shared_ptr<io_t> rwio,
  58. std::size_t init_buf_size,
  59. std::size_t max_buf_size
  60. )
  61. : super(ctx, sessions, listener, std::move(rwio), init_buf_size, max_buf_size)
  62. , ws_stream_cp<derived_t, args_t>()
  63. , ws_send_op <derived_t, args_t>()
  64. {
  65. }
  66. /**
  67. * @brief destructor
  68. */
  69. ~wss_session_impl_t()
  70. {
  71. }
  72. /**
  73. * @brief destroy the content of all member variables, this is used for solve the memory leaks.
  74. * After this function is called, this class object cannot be used again.
  75. */
  76. inline void destroy()
  77. {
  78. derived_t& derive = this->derived();
  79. derive.ws_stream_.reset();
  80. super::destroy();
  81. }
  82. /**
  83. * @brief return the websocket stream object reference
  84. */
  85. inline typename args_t::stream_t& stream() noexcept
  86. {
  87. return this->derived().ws_stream();
  88. }
  89. /**
  90. * @brief return the websocket stream object reference
  91. */
  92. inline typename args_t::stream_t const& stream() const noexcept
  93. {
  94. return this->derived().ws_stream();
  95. }
  96. public:
  97. /**
  98. * @brief get this object hash key,used for session map
  99. */
  100. inline key_type hash_key() const noexcept
  101. {
  102. return reinterpret_cast<key_type>(this);
  103. }
  104. /**
  105. * @brief get the websocket upgraged request object
  106. */
  107. inline websocket::request_type& get_upgrade_request() noexcept { return this->upgrade_req_; }
  108. /**
  109. * @brief get the websocket upgraged request object
  110. */
  111. inline const websocket::request_type& get_upgrade_request() const noexcept { return this->upgrade_req_; }
  112. protected:
  113. inline typename super::ssl_stream_type& upgrade_stream() noexcept
  114. {
  115. return this->ssl_stream();
  116. }
  117. inline typename super::ssl_stream_type const& upgrade_stream() const noexcept
  118. {
  119. return this->ssl_stream();
  120. }
  121. template<typename C>
  122. inline void _do_init(std::shared_ptr<derived_t>& this_ptr, std::shared_ptr<ecs_t<C>>& ecs)
  123. {
  124. super::_do_init(this_ptr, ecs);
  125. this->derived()._ws_init(ecs, this->derived().ssl_stream());
  126. }
  127. template<typename DeferEvent>
  128. inline void _post_shutdown(const error_code& ec, std::shared_ptr<derived_t> this_ptr, DeferEvent chain)
  129. {
  130. ASIO2_LOG_DEBUG("wss_session::_post_shutdown: {} {}", ec.value(), ec.message());
  131. this->derived()._ws_stop(this_ptr, defer_event
  132. {
  133. [this, ec, this_ptr, e = chain.move_event()](event_queue_guard<derived_t> g) mutable
  134. {
  135. super::_post_shutdown(ec, std::move(this_ptr), defer_event(std::move(e), std::move(g)));
  136. }, chain.move_guard()
  137. });
  138. }
  139. template<typename C, typename DeferEvent>
  140. inline void _handle_connect(
  141. const error_code& ec,
  142. std::shared_ptr<derived_t> this_ptr, std::shared_ptr<ecs_t<C>> ecs, DeferEvent chain)
  143. {
  144. detail::ignore_unused(ec);
  145. derived_t& derive = this->derived();
  146. ASIO2_ASSERT(!ec);
  147. ASIO2_ASSERT(derive.sessions_.io_->running_in_this_thread());
  148. asio::dispatch(derive.io_->context(), make_allocator(derive.wallocator(),
  149. [&derive, this_ptr = std::move(this_ptr), ecs = std::move(ecs), chain = std::move(chain)]
  150. () mutable
  151. {
  152. derive._ssl_start(this_ptr, ecs, derive.socket(), derive.ctx_);
  153. derive._ws_start(this_ptr, ecs, derive.ssl_stream());
  154. derive._post_handshake(std::move(this_ptr), std::move(ecs), std::move(chain));
  155. }));
  156. }
  157. template<typename C, typename DeferEvent>
  158. inline void _handle_handshake(
  159. const error_code& ec,
  160. std::shared_ptr<derived_t> this_ptr, std::shared_ptr<ecs_t<C>> ecs, DeferEvent chain)
  161. {
  162. ASIO2_ASSERT(this->derived().io_->running_in_this_thread());
  163. // Use "sessions_.dispatch" to ensure that the _fire_accept function and the _fire_handshake
  164. // function are fired in the same thread
  165. this->sessions_.dispatch(
  166. [this, ec, this_ptr = std::move(this_ptr), ecs = std::move(ecs), chain = std::move(chain)]
  167. () mutable
  168. {
  169. ASIO2_ASSERT(this->derived().sessions_.io_->running_in_this_thread());
  170. set_last_error(ec);
  171. this->derived()._fire_handshake(this_ptr);
  172. if (ec)
  173. {
  174. this->derived()._do_disconnect(ec, std::move(this_ptr), std::move(chain));
  175. return;
  176. }
  177. asio::dispatch(this->io_->context(), make_allocator(this->wallocator_,
  178. [this, this_ptr = std::move(this_ptr), ecs = std::move(ecs), chain = std::move(chain)]
  179. () mutable
  180. {
  181. ASIO2_ASSERT(this->derived().io_->running_in_this_thread());
  182. this->derived()._post_read_upgrade_request(
  183. std::move(this_ptr), std::move(ecs), std::move(chain));
  184. }));
  185. });
  186. }
  187. template<class Data, class Callback>
  188. inline bool _do_send(Data& data, Callback&& callback)
  189. {
  190. return this->derived()._ws_send(data, std::forward<Callback>(callback));
  191. }
  192. protected:
  193. template<typename C>
  194. inline void _post_recv(std::shared_ptr<derived_t> this_ptr, std::shared_ptr<ecs_t<C>> ecs)
  195. {
  196. this->derived()._ws_post_recv(std::move(this_ptr), std::move(ecs));
  197. }
  198. template<typename C>
  199. inline void _handle_recv(
  200. const error_code& ec, std::size_t bytes_recvd,
  201. std::shared_ptr<derived_t> this_ptr, std::shared_ptr<ecs_t<C>> ecs)
  202. {
  203. this->derived()._ws_handle_recv(ec, bytes_recvd, std::move(this_ptr), std::move(ecs));
  204. }
  205. inline void _fire_upgrade(std::shared_ptr<derived_t>& this_ptr)
  206. {
  207. // the _fire_upgrade must be executed in the thread 0.
  208. ASIO2_ASSERT(this->sessions_.io_->running_in_this_thread());
  209. this->listener_.notify(event_type::upgrade, this_ptr);
  210. }
  211. protected:
  212. websocket::request_type upgrade_req_;
  213. };
  214. }
  215. namespace asio2
  216. {
  217. using wss_session_args = detail::template_args_wss_session;
  218. template<class derived_t, class args_t>
  219. using wss_session_impl_t = detail::wss_session_impl_t<derived_t, args_t>;
  220. template<class derived_t>
  221. class wss_session_t : public detail::wss_session_impl_t<derived_t, detail::template_args_wss_session>
  222. {
  223. public:
  224. using detail::wss_session_impl_t<derived_t, detail::template_args_wss_session>::wss_session_impl_t;
  225. };
  226. class wss_session : public wss_session_t<wss_session>
  227. {
  228. public:
  229. using wss_session_t<wss_session>::wss_session_t;
  230. };
  231. }
  232. #include <asio2/base/detail/pop_options.hpp>
  233. #if defined(ASIO2_INCLUDE_RATE_LIMIT)
  234. #include <asio2/tcp/tcp_stream.hpp>
  235. namespace asio2
  236. {
  237. struct wss_rate_session_args : public wss_session_args
  238. {
  239. using socket_t = asio2::tcp_stream<asio2::simple_rate_policy>;
  240. using stream_t = websocket::stream<asio::ssl::stream<socket_t&>&>;
  241. };
  242. template<class derived_t>
  243. class wss_rate_session_t : public asio2::wss_session_impl_t<derived_t, wss_rate_session_args>
  244. {
  245. public:
  246. using asio2::wss_session_impl_t<derived_t, wss_rate_session_args>::wss_session_impl_t;
  247. };
  248. class wss_rate_session : public asio2::wss_rate_session_t<wss_rate_session>
  249. {
  250. public:
  251. using asio2::wss_rate_session_t<wss_rate_session>::wss_rate_session_t;
  252. };
  253. }
  254. #endif
  255. #endif // !__ASIO2_WSS_SESSION_HPP__
  256. #endif