https_client.hpp 6.6 KB

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