Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:58:20

0001 //
0002 // Copyright (c) 2019-2025 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 
0008 #ifndef BOOST_MYSQL_DETAIL_ENGINE_STREAM_ADAPTOR_HPP
0009 #define BOOST_MYSQL_DETAIL_ENGINE_STREAM_ADAPTOR_HPP
0010 
0011 #include <boost/mysql/error_code.hpp>
0012 
0013 #include <boost/mysql/detail/config.hpp>
0014 #include <boost/mysql/detail/engine_impl.hpp>
0015 #include <boost/mysql/detail/socket_stream.hpp>
0016 #include <boost/mysql/detail/void_t.hpp>
0017 
0018 #include <boost/asio/any_io_executor.hpp>
0019 #include <boost/asio/ip/tcp.hpp>
0020 #include <boost/asio/ssl/stream.hpp>
0021 #include <boost/config.hpp>
0022 #include <boost/core/ignore_unused.hpp>
0023 
0024 #include <type_traits>
0025 
0026 // Adapts a regular Asio Stream to meet the EngineStream requirements
0027 // We only use callbacks with the async functions in this file, so no need to support arbitrary return types
0028 
0029 namespace boost {
0030 namespace mysql {
0031 namespace detail {
0032 
0033 // Connect and close helpers
0034 // LCOV_EXCL_START
0035 template <class Stream>
0036 void do_connect_impl(Stream&, const void*, error_code&, std::false_type)
0037 {
0038     BOOST_ASSERT(false);
0039 }
0040 // LCOV_EXCL_STOP
0041 
0042 template <class Stream>
0043 void do_connect_impl(Stream& stream, const void* ep, error_code& ec, std::true_type)
0044 {
0045     stream.lowest_layer().connect(
0046         *static_cast<const typename Stream::lowest_layer_type::endpoint_type*>(ep),
0047         ec
0048     );
0049 }
0050 
0051 template <class Stream>
0052 void do_connect(Stream& stream, const void* ep, error_code& ec)
0053 {
0054     do_connect_impl(stream, ep, ec, is_socket_stream<Stream>{});
0055 }
0056 
0057 // LCOV_EXCL_START
0058 template <class Stream, class CompletionToken>
0059 void do_async_connect_impl(Stream&, const void*, CompletionToken&&, std::false_type)
0060 {
0061     BOOST_ASSERT(false);
0062 }
0063 // LCOV_EXCL_STOP
0064 
0065 template <class Stream, class CompletionToken>
0066 void do_async_connect_impl(Stream& stream, const void* ep, CompletionToken&& token, std::true_type)
0067 {
0068     stream.lowest_layer().async_connect(
0069         *static_cast<const typename Stream::lowest_layer_type::endpoint_type*>(ep),
0070         std::forward<CompletionToken>(token)
0071     );
0072 }
0073 
0074 template <class Stream, class CompletionToken>
0075 void do_async_connect(Stream& stream, const void* ep, CompletionToken&& token)
0076 {
0077     do_async_connect_impl(stream, ep, std::forward<CompletionToken>(token), is_socket_stream<Stream>{});
0078 }
0079 
0080 // LCOV_EXCL_START
0081 template <class Stream>
0082 void do_close_impl(Stream&, error_code&, std::false_type)
0083 {
0084     BOOST_ASSERT(false);
0085 }
0086 // LCOV_EXCL_STOP
0087 
0088 template <class Stream>
0089 void do_close_impl(Stream& stream, error_code& ec, std::true_type)
0090 {
0091     stream.lowest_layer().shutdown(asio::socket_base::shutdown_both, ec);
0092     stream.lowest_layer().close(ec);
0093 }
0094 
0095 template <class Stream>
0096 void do_close(Stream& stream, error_code& ec)
0097 {
0098     do_close_impl(stream, ec, is_socket_stream<Stream>{});
0099 }
0100 
0101 template <class Stream>
0102 class engine_stream_adaptor
0103 {
0104     Stream stream_;
0105 
0106 public:
0107     template <class... Args>
0108     engine_stream_adaptor(Args&&... args) : stream_(std::forward<Args>(args)...)
0109     {
0110     }
0111 
0112     Stream& stream() { return stream_; }
0113     const Stream& stream() const { return stream_; }
0114 
0115     bool supports_ssl() const { return false; }
0116 
0117     using executor_type = asio::any_io_executor;
0118     executor_type get_executor() { return stream_.get_executor(); }
0119 
0120     // SSL
0121     // LCOV_EXCL_START
0122     void ssl_handshake(error_code&) { BOOST_ASSERT(false); }
0123 
0124     template <class CompletinToken>
0125     void async_ssl_handshake(CompletinToken&&)
0126     {
0127         BOOST_ASSERT(false);
0128     }
0129 
0130     void ssl_shutdown(error_code&) { BOOST_ASSERT(false); }
0131 
0132     template <class CompletionToken>
0133     void async_ssl_shutdown(CompletionToken&&)
0134     {
0135         BOOST_ASSERT(false);
0136     }
0137     // LCOV_EXCL_STOP
0138 
0139     // Reading
0140     std::size_t read_some(boost::asio::mutable_buffer buff, bool use_ssl, error_code& ec)
0141     {
0142         BOOST_ASSERT(!use_ssl);
0143         boost::ignore_unused(use_ssl);
0144         return stream_.read_some(buff, ec);
0145     }
0146 
0147     template <class CompletionToken>
0148     void async_read_some(boost::asio::mutable_buffer buff, bool use_ssl, CompletionToken&& token)
0149     {
0150         BOOST_ASSERT(!use_ssl);
0151         boost::ignore_unused(use_ssl);
0152         stream_.async_read_some(buff, std::forward<CompletionToken>(token));
0153     }
0154 
0155     // Writing
0156     std::size_t write_some(boost::asio::const_buffer buff, bool use_ssl, error_code& ec)
0157     {
0158         BOOST_ASSERT(!use_ssl);
0159         boost::ignore_unused(use_ssl);
0160         return stream_.write_some(buff, ec);
0161     }
0162 
0163     template <class CompletionToken>
0164     void async_write_some(boost::asio::const_buffer buff, bool use_ssl, CompletionToken&& token)
0165     {
0166         BOOST_ASSERT(!use_ssl);
0167         boost::ignore_unused(use_ssl);
0168         stream_.async_write_some(buff, std::forward<CompletionToken>(token));
0169     }
0170 
0171     // Connect and close
0172     void connect(const void* endpoint, error_code& ec) { do_connect(stream_, endpoint, ec); }
0173 
0174     template <class CompletionToken>
0175     void async_connect(const void* endpoint, CompletionToken&& token)
0176     {
0177         do_async_connect(stream_, endpoint, std::forward<CompletionToken>(token));
0178     }
0179 
0180     void close(error_code& ec) { do_close(stream_, ec); }
0181 };
0182 
0183 template <class Stream>
0184 class engine_stream_adaptor<asio::ssl::stream<Stream>>
0185 {
0186     asio::ssl::stream<Stream> stream_;
0187 
0188 public:
0189     template <class... Args>
0190     engine_stream_adaptor(Args&&... args) : stream_(std::forward<Args>(args)...)
0191     {
0192     }
0193 
0194     asio::ssl::stream<Stream>& stream() { return stream_; }
0195     const asio::ssl::stream<Stream>& stream() const { return stream_; }
0196 
0197     bool supports_ssl() const { return true; }
0198 
0199     using executor_type = asio::any_io_executor;
0200     executor_type get_executor() { return stream_.get_executor(); }
0201 
0202     // SSL
0203     void ssl_handshake(error_code& ec) { stream_.handshake(asio::ssl::stream_base::client, ec); }
0204 
0205     template <class CompletionToken>
0206     void async_ssl_handshake(CompletionToken&& token)
0207     {
0208         stream_.async_handshake(asio::ssl::stream_base::client, std::forward<CompletionToken>(token));
0209     }
0210 
0211     void ssl_shutdown(error_code& ec) { stream_.shutdown(ec); }
0212 
0213     template <class CompletionToken>
0214     void async_ssl_shutdown(CompletionToken&& token)
0215     {
0216         stream_.async_shutdown(std::forward<CompletionToken>(token));
0217     }
0218 
0219     // Reading
0220     std::size_t read_some(boost::asio::mutable_buffer buff, bool use_ssl, error_code& ec)
0221     {
0222         if (use_ssl)
0223         {
0224             return stream_.read_some(buff, ec);
0225         }
0226         else
0227         {
0228             return stream_.next_layer().read_some(buff, ec);
0229         }
0230     }
0231 
0232     template <class CompletionToken>
0233     void async_read_some(boost::asio::mutable_buffer buff, bool use_ssl, CompletionToken&& token)
0234     {
0235         if (use_ssl)
0236         {
0237             stream_.async_read_some(buff, std::forward<CompletionToken>(token));
0238         }
0239         else
0240         {
0241             stream_.next_layer().async_read_some(buff, std::forward<CompletionToken>(token));
0242         }
0243     }
0244 
0245     // Writing
0246     std::size_t write_some(boost::asio::const_buffer buff, bool use_ssl, error_code& ec)
0247     {
0248         if (use_ssl)
0249         {
0250             return stream_.write_some(buff, ec);
0251         }
0252         else
0253         {
0254             return stream_.next_layer().write_some(buff, ec);
0255         }
0256     }
0257 
0258     template <class CompletionToken>
0259     void async_write_some(boost::asio::const_buffer buff, bool use_ssl, CompletionToken&& token)
0260     {
0261         if (use_ssl)
0262         {
0263             stream_.async_write_some(buff, std::forward<CompletionToken>(token));
0264         }
0265         else
0266         {
0267             stream_.next_layer().async_write_some(buff, std::forward<CompletionToken>(token));
0268         }
0269     }
0270 
0271     // Connect and close
0272     void connect(const void* endpoint, error_code& ec) { do_connect(stream_, endpoint, ec); }
0273 
0274     template <class CompletionToken>
0275     void async_connect(const void* endpoint, CompletionToken&& token)
0276     {
0277         do_async_connect(stream_, endpoint, std::forward<CompletionToken>(token));
0278     }
0279 
0280     void close(error_code& ec) { do_close(stream_, ec); }
0281 };
0282 
0283 #ifdef BOOST_MYSQL_SEPARATE_COMPILATION
0284 extern template class engine_impl<engine_stream_adaptor<asio::ssl::stream<asio::ip::tcp::socket>>>;
0285 extern template class engine_impl<engine_stream_adaptor<asio::ip::tcp::socket>>;
0286 #endif
0287 
0288 template <class Stream, class... Args>
0289 std::unique_ptr<engine> make_engine(Args&&... args)
0290 {
0291     return std::unique_ptr<engine>(new engine_impl<engine_stream_adaptor<Stream>>(std::forward<Args>(args)...)
0292     );
0293 }
0294 
0295 // Use these only for engines created using make_engine
0296 template <class Stream>
0297 Stream& stream_from_engine(engine& eng)
0298 {
0299     using derived_t = engine_impl<engine_stream_adaptor<Stream>>;
0300     return static_cast<derived_t&>(eng).stream().stream();
0301 }
0302 
0303 template <class Stream>
0304 const Stream& stream_from_engine(const engine& eng)
0305 {
0306     using derived_t = engine_impl<engine_stream_adaptor<Stream>>;
0307     return static_cast<const derived_t&>(eng).stream().stream();
0308 }
0309 
0310 }  // namespace detail
0311 }  // namespace mysql
0312 }  // namespace boost
0313 
0314 #endif