tcps_client.hpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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_TCPS_CLIENT_HPP__
  12. #define __ASIO2_TCPS_CLIENT_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/tcp_client.hpp>
  18. #include <asio2/tcp/impl/ssl_stream_cp.hpp>
  19. #include <asio2/tcp/impl/ssl_context_cp.hpp>
  20. namespace asio2::detail
  21. {
  22. ASIO2_CLASS_FORWARD_DECLARE_BASE;
  23. ASIO2_CLASS_FORWARD_DECLARE_TCP_BASE;
  24. ASIO2_CLASS_FORWARD_DECLARE_TCP_CLIENT;
  25. template<class derived_t, class args_t = template_args_tcp_client>
  26. class tcps_client_impl_t
  27. : public ssl_context_cp <derived_t, args_t>
  28. , public tcp_client_impl_t <derived_t, args_t>
  29. , public ssl_stream_cp <derived_t, args_t>
  30. {
  31. ASIO2_CLASS_FRIEND_DECLARE_BASE;
  32. ASIO2_CLASS_FRIEND_DECLARE_TCP_BASE;
  33. ASIO2_CLASS_FRIEND_DECLARE_TCP_CLIENT;
  34. public:
  35. using super = tcp_client_impl_t <derived_t, args_t>;
  36. using self = tcps_client_impl_t<derived_t, args_t>;
  37. using args_type = args_t;
  38. using buffer_type = typename args_t::buffer_t;
  39. using ssl_context_comp = ssl_context_cp<derived_t, args_t>;
  40. using ssl_stream_comp = ssl_stream_cp <derived_t, args_t>;
  41. public:
  42. /**
  43. * @brief constructor
  44. */
  45. template<class... Args>
  46. explicit tcps_client_impl_t(
  47. asio::ssl::context::method method,
  48. Args&&... args
  49. )
  50. : ssl_context_comp(method)
  51. , super(std::forward<Args>(args)...)
  52. , ssl_stream_comp(*this, asio::ssl::stream_base::client)
  53. {
  54. }
  55. /**
  56. * @brief constructor
  57. */
  58. template<class... Args>
  59. explicit tcps_client_impl_t(Args&&... args)
  60. : ssl_context_comp(ASIO2_DEFAULT_SSL_METHOD)
  61. , super(std::forward<Args>(args)...)
  62. , ssl_stream_comp(*this, asio::ssl::stream_base::client)
  63. {
  64. }
  65. /**
  66. * @brief constructor
  67. */
  68. explicit tcps_client_impl_t()
  69. : ssl_context_comp(ASIO2_DEFAULT_SSL_METHOD)
  70. , super()
  71. , ssl_stream_comp(*this, asio::ssl::stream_base::client)
  72. {
  73. }
  74. /**
  75. * @brief destructor
  76. */
  77. ~tcps_client_impl_t()
  78. {
  79. this->stop();
  80. }
  81. /**
  82. * @brief destroy the content of all member variables, this is used for solve the memory leaks.
  83. * After this function is called, this class object cannot be used again.
  84. */
  85. inline void destroy()
  86. {
  87. derived_t& derive = this->derived();
  88. derive.ssl_stream_.reset();
  89. super::destroy();
  90. }
  91. /**
  92. * @brief get the stream object reference
  93. *
  94. */
  95. inline typename ssl_stream_comp::ssl_stream_type& stream() noexcept
  96. {
  97. return this->derived().ssl_stream();
  98. }
  99. /**
  100. * @brief get the stream object reference
  101. *
  102. */
  103. inline typename ssl_stream_comp::ssl_stream_type const& stream() const noexcept
  104. {
  105. return this->derived().ssl_stream();
  106. }
  107. public:
  108. /**
  109. * @brief bind ssl handshake listener
  110. * @param fun - a user defined callback function.
  111. * @param obj - a pointer or reference to a class object, this parameter can be none.
  112. * if fun is nonmember function, the obj param must be none, otherwise the obj must be the
  113. * the class object's pointer or reference.
  114. * Function signature : void()
  115. */
  116. template<class F, class ...C>
  117. inline derived_t & bind_handshake(F&& fun, C&&... obj)
  118. {
  119. this->listener_.bind(event_type::handshake,
  120. observer_t<>(std::forward<F>(fun), std::forward<C>(obj)...));
  121. return (this->derived());
  122. }
  123. protected:
  124. template<typename C>
  125. inline void _do_init(std::shared_ptr<ecs_t<C>>& ecs)
  126. {
  127. super::_do_init(ecs);
  128. this->derived()._ssl_init(ecs, this->derived().socket(), *this);
  129. }
  130. template<typename DeferEvent>
  131. inline void _post_shutdown(const error_code& ec, std::shared_ptr<derived_t> this_ptr, DeferEvent chain)
  132. {
  133. ASIO2_LOG_DEBUG("tcps_client::_post_shutdown: {} {}", ec.value(), ec.message());
  134. this->derived()._ssl_stop(this_ptr, defer_event
  135. {
  136. [this, ec, this_ptr, e = chain.move_event()] (event_queue_guard<derived_t> g) mutable
  137. {
  138. super::_post_shutdown(ec, std::move(this_ptr), defer_event(std::move(e), std::move(g)));
  139. }, chain.move_guard()
  140. });
  141. }
  142. template<typename C, typename DeferEvent>
  143. inline void _handle_connect(
  144. const error_code& ec,
  145. std::shared_ptr<derived_t> this_ptr, std::shared_ptr<ecs_t<C>> ecs, DeferEvent chain)
  146. {
  147. set_last_error(ec);
  148. derived_t& derive = this->derived();
  149. if (ec)
  150. {
  151. return derive._done_connect(ec, std::move(this_ptr), std::move(ecs), std::move(chain));
  152. }
  153. derive._ssl_start(this_ptr, ecs, derive.socket(), *this);
  154. derive._post_handshake(std::move(this_ptr), std::move(ecs), std::move(chain));
  155. }
  156. inline void _fire_handshake(std::shared_ptr<derived_t>& this_ptr)
  157. {
  158. // the _fire_handshake must be executed in the thread 0.
  159. ASIO2_ASSERT(this->derived().io_->running_in_this_thread());
  160. detail::ignore_unused(this_ptr);
  161. this->listener_.notify(event_type::handshake);
  162. }
  163. };
  164. }
  165. namespace asio2
  166. {
  167. using tcps_client_args = detail::template_args_tcp_client;
  168. template<class derived_t, class args_t>
  169. using tcps_client_impl_t = detail::tcps_client_impl_t<derived_t, args_t>;
  170. /**
  171. * @brief ssl tcp client
  172. * @throws constructor maybe throw exception "Too many open files" (exception code : 24)
  173. * asio::error::no_descriptors - Too many open files
  174. */
  175. template<class derived_t>
  176. class tcps_client_t : public detail::tcps_client_impl_t<derived_t, detail::template_args_tcp_client>
  177. {
  178. public:
  179. using detail::tcps_client_impl_t<derived_t, detail::template_args_tcp_client>::tcps_client_impl_t;
  180. };
  181. /**
  182. * @brief ssl tcp client
  183. * @throws constructor maybe throw exception "Too many open files" (exception code : 24)
  184. * asio::error::no_descriptors - Too many open files
  185. */
  186. class tcps_client : public tcps_client_t<tcps_client>
  187. {
  188. public:
  189. using tcps_client_t<tcps_client>::tcps_client_t;
  190. };
  191. }
  192. #if defined(ASIO2_INCLUDE_RATE_LIMIT)
  193. #include <asio2/tcp/tcp_stream.hpp>
  194. namespace asio2
  195. {
  196. struct tcps_rate_client_args : public tcps_client_args
  197. {
  198. using socket_t = asio2::tcp_stream<asio2::simple_rate_policy>;
  199. };
  200. template<class derived_t>
  201. class tcps_rate_client_t : public asio2::tcps_client_impl_t<derived_t, tcps_rate_client_args>
  202. {
  203. public:
  204. using asio2::tcps_client_impl_t<derived_t, tcps_rate_client_args>::tcps_client_impl_t;
  205. };
  206. class tcps_rate_client : public asio2::tcps_rate_client_t<tcps_rate_client>
  207. {
  208. public:
  209. using asio2::tcps_rate_client_t<tcps_rate_client>::tcps_rate_client_t;
  210. };
  211. }
  212. #endif
  213. #include <asio2/base/detail/pop_options.hpp>
  214. #endif // !__ASIO2_TCPS_CLIENT_HPP__
  215. #endif