any_stream_impl.hpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. //
  2. // Copyright (c) 2019-2023 Ruben Perez Hidalgo (rubenperez038 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. #ifndef BHO_MYSQL_DETAIL_ANY_STREAM_IMPL_HPP
  8. #define BHO_MYSQL_DETAIL_ANY_STREAM_IMPL_HPP
  9. #include <asio2/bho/mysql/error_code.hpp>
  10. #include <asio2/bho/mysql/detail/any_stream.hpp>
  11. #include <asio2/bho/mysql/detail/config.hpp>
  12. #include <asio2/bho/mysql/detail/socket_stream.hpp>
  13. #include <asio/ip/tcp.hpp>
  14. #include <asio/ssl/stream.hpp>
  15. #include <asio2/bho/config.hpp>
  16. #include <type_traits>
  17. namespace bho {
  18. namespace mysql {
  19. namespace detail {
  20. // Connect and close helpers
  21. template <class Stream>
  22. const typename Stream::lowest_layer_type::endpoint_type cast_endpoint(const void* input) noexcept
  23. {
  24. return *static_cast<const typename Stream::lowest_layer_type::endpoint_type*>(input);
  25. }
  26. template <class Stream>
  27. void do_connect_impl(Stream&, const void*, error_code&, std::false_type)
  28. {
  29. BHO_ASSERT(false);
  30. }
  31. template <class Stream>
  32. void do_connect_impl(Stream& stream, const void* endpoint, error_code& ec, std::true_type)
  33. {
  34. stream.lowest_layer().connect(cast_endpoint<Stream>(endpoint), ec);
  35. }
  36. template <class Stream>
  37. void do_connect(Stream& stream, const void* endpoint, error_code& ec)
  38. {
  39. do_connect_impl(stream, endpoint, ec, is_socket_stream<Stream>{});
  40. }
  41. template <class Stream>
  42. void do_async_connect_impl(
  43. Stream&,
  44. const void*,
  45. asio::any_completion_handler<void(error_code)>&&,
  46. std::false_type
  47. )
  48. {
  49. BHO_ASSERT(false);
  50. }
  51. template <class Stream>
  52. void do_async_connect_impl(
  53. Stream& stream,
  54. const void* endpoint,
  55. asio::any_completion_handler<void(error_code)>&& handler,
  56. std::true_type
  57. )
  58. {
  59. stream.lowest_layer().async_connect(cast_endpoint<Stream>(endpoint), std::move(handler));
  60. }
  61. template <class Stream>
  62. void do_async_connect(
  63. Stream& stream,
  64. const void* endpoint,
  65. asio::any_completion_handler<void(error_code)>&& handler
  66. )
  67. {
  68. do_async_connect_impl(stream, endpoint, std::move(handler), is_socket_stream<Stream>{});
  69. }
  70. template <class Stream>
  71. void do_close_impl(Stream&, error_code&, std::false_type)
  72. {
  73. BHO_ASSERT(false);
  74. }
  75. template <class Stream>
  76. void do_close_impl(Stream& stream, error_code& ec, std::true_type)
  77. {
  78. stream.lowest_layer().shutdown(asio::socket_base::shutdown_both, ec);
  79. stream.lowest_layer().close(ec);
  80. }
  81. template <class Stream>
  82. void do_close(Stream& stream, error_code& ec)
  83. {
  84. do_close_impl(stream, ec, is_socket_stream<Stream>{});
  85. }
  86. template <class Stream>
  87. bool do_is_open_impl(const Stream&, std::false_type) noexcept
  88. {
  89. return false;
  90. }
  91. template <class Stream>
  92. bool do_is_open_impl(const Stream& stream, std::true_type) noexcept
  93. {
  94. return stream.lowest_layer().is_open();
  95. }
  96. template <class Stream>
  97. bool do_is_open(const Stream& stream) noexcept
  98. {
  99. return do_is_open_impl(stream, is_socket_stream<Stream>{});
  100. }
  101. template <class Stream>
  102. class any_stream_impl final : public any_stream
  103. {
  104. Stream stream_;
  105. public:
  106. template <class... Args>
  107. any_stream_impl(Args&&... args) : any_stream(false), stream_(std::forward<Args>(args)...)
  108. {
  109. }
  110. Stream& stream() noexcept { return stream_; }
  111. const Stream& stream() const noexcept { return stream_; }
  112. executor_type get_executor() override final { return stream_.get_executor(); }
  113. // SSL
  114. void handshake(error_code&) final override { BHO_ASSERT(false); }
  115. void async_handshake(asio::any_completion_handler<void(error_code)>) final override
  116. {
  117. BHO_ASSERT(false);
  118. }
  119. void shutdown(error_code&) final override { BHO_ASSERT(false); }
  120. void async_shutdown(asio::any_completion_handler<void(error_code)>) final override
  121. {
  122. BHO_ASSERT(false);
  123. }
  124. // Reading
  125. std::size_t read_some(asio::mutable_buffer buff, error_code& ec) final override
  126. {
  127. return stream_.read_some(buff, ec);
  128. }
  129. void async_read_some(
  130. asio::mutable_buffer buff,
  131. asio::any_completion_handler<void(error_code, std::size_t)> handler
  132. ) final override
  133. {
  134. return stream_.async_read_some(buff, std::move(handler));
  135. }
  136. // Writing
  137. std::size_t write_some(asio::const_buffer buff, error_code& ec) final override
  138. {
  139. return stream_.write_some(buff, ec);
  140. }
  141. void async_write_some(
  142. asio::const_buffer buff,
  143. asio::any_completion_handler<void(error_code, std::size_t)> handler
  144. ) final override
  145. {
  146. return stream_.async_write_some(buff, std::move(handler));
  147. }
  148. // Connect and close
  149. void connect(const void* endpoint, error_code& ec) override final { do_connect(stream_, endpoint, ec); }
  150. void async_connect(const void* endpoint, asio::any_completion_handler<void(error_code)> handler)
  151. override final
  152. {
  153. do_async_connect(stream_, endpoint, std::move(handler));
  154. }
  155. void close(error_code& ec) override final { do_close(stream_, ec); }
  156. bool is_open() const noexcept override { return do_is_open(stream_); }
  157. };
  158. template <class Stream>
  159. class any_stream_impl<asio::ssl::stream<Stream>> final : public any_stream
  160. {
  161. asio::ssl::stream<Stream> stream_;
  162. public:
  163. template <class... Args>
  164. any_stream_impl(Args&&... args) : any_stream(true), stream_(std::forward<Args>(args)...)
  165. {
  166. }
  167. asio::ssl::stream<Stream>& stream() noexcept { return stream_; }
  168. const asio::ssl::stream<Stream>& stream() const noexcept { return stream_; }
  169. executor_type get_executor() override final { return stream_.get_executor(); }
  170. // SSL
  171. void handshake(error_code& ec) override final
  172. {
  173. set_ssl_active();
  174. stream_.handshake(asio::ssl::stream_base::client, ec);
  175. }
  176. void async_handshake(asio::any_completion_handler<void(error_code)> handler) override final
  177. {
  178. set_ssl_active();
  179. stream_.async_handshake(asio::ssl::stream_base::client, std::move(handler));
  180. }
  181. void shutdown(error_code& ec) override final { stream_.shutdown(ec); }
  182. void async_shutdown(asio::any_completion_handler<void(error_code)> handler) override final
  183. {
  184. return stream_.async_shutdown(std::move(handler));
  185. }
  186. // Reading
  187. std::size_t read_some(asio::mutable_buffer buff, error_code& ec) override final
  188. {
  189. if (ssl_active())
  190. {
  191. return stream_.read_some(buff, ec);
  192. }
  193. else
  194. {
  195. return stream_.next_layer().read_some(buff, ec);
  196. }
  197. }
  198. void async_read_some(
  199. asio::mutable_buffer buff,
  200. asio::any_completion_handler<void(error_code, std::size_t)> handler
  201. ) override final
  202. {
  203. if (ssl_active())
  204. {
  205. return stream_.async_read_some(buff, std::move(handler));
  206. }
  207. else
  208. {
  209. return stream_.next_layer().async_read_some(buff, std::move(handler));
  210. }
  211. }
  212. // Writing
  213. std::size_t write_some(asio::const_buffer buff, error_code& ec) override final
  214. {
  215. if (ssl_active())
  216. {
  217. return stream_.write_some(buff, ec);
  218. }
  219. else
  220. {
  221. return stream_.next_layer().write_some(buff, ec);
  222. }
  223. }
  224. void async_write_some(
  225. asio::const_buffer buff,
  226. asio::any_completion_handler<void(error_code, std::size_t)> handler
  227. ) override final
  228. {
  229. if (ssl_active())
  230. {
  231. stream_.async_write_some(buff, std::move(handler));
  232. }
  233. else
  234. {
  235. return stream_.next_layer().async_write_some(buff, std::move(handler));
  236. }
  237. }
  238. // Connect and close
  239. void connect(const void* endpoint, error_code& ec) override final { do_connect(stream_, endpoint, ec); }
  240. void async_connect(const void* endpoint, asio::any_completion_handler<void(error_code)> handler)
  241. override final
  242. {
  243. do_async_connect(stream_, endpoint, std::move(handler));
  244. }
  245. void close(error_code& ec) override final { do_close(stream_, ec); }
  246. bool is_open() const noexcept override { return do_is_open(stream_); }
  247. };
  248. template <class Stream>
  249. const Stream& cast(const any_stream& obj) noexcept
  250. {
  251. return static_cast<const any_stream_impl<Stream>&>(obj).stream();
  252. }
  253. template <class Stream>
  254. Stream& cast(any_stream& obj) noexcept
  255. {
  256. return static_cast<any_stream_impl<Stream>&>(obj).stream();
  257. }
  258. #ifdef BHO_MYSQL_SEPARATE_COMPILATION
  259. extern template class any_stream_impl<asio::ssl::stream<asio::ip::tcp::socket>>;
  260. extern template class any_stream_impl<asio::ip::tcp::socket>;
  261. #endif
  262. } // namespace detail
  263. } // namespace mysql
  264. } // namespace bho
  265. // any_stream_impl.ipp explicitly instantiates any_stream_impl, so not included here
  266. #endif