Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:42:39

0001 //
0002 // Copyright (c) 2019-2023 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_ANY_STREAM_IMPL_HPP
0009 #define BOOST_MYSQL_DETAIL_ANY_STREAM_IMPL_HPP
0010 
0011 #include <boost/mysql/error_code.hpp>
0012 
0013 #include <boost/mysql/detail/any_stream.hpp>
0014 #include <boost/mysql/detail/config.hpp>
0015 #include <boost/mysql/detail/socket_stream.hpp>
0016 
0017 #include <boost/asio/ip/tcp.hpp>
0018 #include <boost/asio/ssl/stream.hpp>
0019 #include <boost/config.hpp>
0020 
0021 #include <type_traits>
0022 
0023 namespace boost {
0024 namespace mysql {
0025 namespace detail {
0026 
0027 // Connect and close helpers
0028 template <class Stream>
0029 const typename Stream::lowest_layer_type::endpoint_type cast_endpoint(const void* input) noexcept
0030 {
0031     return *static_cast<const typename Stream::lowest_layer_type::endpoint_type*>(input);
0032 }
0033 
0034 template <class Stream>
0035 void do_connect_impl(Stream&, const void*, error_code&, std::false_type)
0036 {
0037     BOOST_ASSERT(false);
0038 }
0039 
0040 template <class Stream>
0041 void do_connect_impl(Stream& stream, const void* endpoint, error_code& ec, std::true_type)
0042 {
0043     stream.lowest_layer().connect(cast_endpoint<Stream>(endpoint), ec);
0044 }
0045 
0046 template <class Stream>
0047 void do_connect(Stream& stream, const void* endpoint, error_code& ec)
0048 {
0049     do_connect_impl(stream, endpoint, ec, is_socket_stream<Stream>{});
0050 }
0051 
0052 template <class Stream>
0053 void do_async_connect_impl(
0054     Stream&,
0055     const void*,
0056     asio::any_completion_handler<void(error_code)>&&,
0057     std::false_type
0058 )
0059 {
0060     BOOST_ASSERT(false);
0061 }
0062 
0063 template <class Stream>
0064 void do_async_connect_impl(
0065     Stream& stream,
0066     const void* endpoint,
0067     asio::any_completion_handler<void(error_code)>&& handler,
0068     std::true_type
0069 )
0070 {
0071     stream.lowest_layer().async_connect(cast_endpoint<Stream>(endpoint), std::move(handler));
0072 }
0073 
0074 template <class Stream>
0075 void do_async_connect(
0076     Stream& stream,
0077     const void* endpoint,
0078     asio::any_completion_handler<void(error_code)>&& handler
0079 )
0080 {
0081     do_async_connect_impl(stream, endpoint, std::move(handler), is_socket_stream<Stream>{});
0082 }
0083 
0084 template <class Stream>
0085 void do_close_impl(Stream&, error_code&, std::false_type)
0086 {
0087     BOOST_ASSERT(false);
0088 }
0089 
0090 template <class Stream>
0091 void do_close_impl(Stream& stream, error_code& ec, std::true_type)
0092 {
0093     stream.lowest_layer().shutdown(asio::socket_base::shutdown_both, ec);
0094     stream.lowest_layer().close(ec);
0095 }
0096 
0097 template <class Stream>
0098 void do_close(Stream& stream, error_code& ec)
0099 {
0100     do_close_impl(stream, ec, is_socket_stream<Stream>{});
0101 }
0102 
0103 template <class Stream>
0104 bool do_is_open_impl(const Stream&, std::false_type) noexcept
0105 {
0106     return false;
0107 }
0108 
0109 template <class Stream>
0110 bool do_is_open_impl(const Stream& stream, std::true_type) noexcept
0111 {
0112     return stream.lowest_layer().is_open();
0113 }
0114 
0115 template <class Stream>
0116 bool do_is_open(const Stream& stream) noexcept
0117 {
0118     return do_is_open_impl(stream, is_socket_stream<Stream>{});
0119 }
0120 
0121 template <class Stream>
0122 class any_stream_impl final : public any_stream
0123 {
0124     Stream stream_;
0125 
0126 public:
0127     template <class... Args>
0128     any_stream_impl(Args&&... args) : any_stream(false), stream_(std::forward<Args>(args)...)
0129     {
0130     }
0131 
0132     Stream& stream() noexcept { return stream_; }
0133     const Stream& stream() const noexcept { return stream_; }
0134 
0135     executor_type get_executor() override final { return stream_.get_executor(); }
0136 
0137     // SSL
0138     void handshake(error_code&) final override { BOOST_ASSERT(false); }
0139     void async_handshake(asio::any_completion_handler<void(error_code)>) final override
0140     {
0141         BOOST_ASSERT(false);
0142     }
0143     void shutdown(error_code&) final override { BOOST_ASSERT(false); }
0144     void async_shutdown(asio::any_completion_handler<void(error_code)>) final override
0145     {
0146         BOOST_ASSERT(false);
0147     }
0148 
0149     // Reading
0150     std::size_t read_some(boost::asio::mutable_buffer buff, error_code& ec) final override
0151     {
0152         return stream_.read_some(buff, ec);
0153     }
0154     void async_read_some(
0155         boost::asio::mutable_buffer buff,
0156         asio::any_completion_handler<void(error_code, std::size_t)> handler
0157     ) final override
0158     {
0159         return stream_.async_read_some(buff, std::move(handler));
0160     }
0161 
0162     // Writing
0163     std::size_t write_some(boost::asio::const_buffer buff, error_code& ec) final override
0164     {
0165         return stream_.write_some(buff, ec);
0166     }
0167     void async_write_some(
0168         boost::asio::const_buffer buff,
0169         asio::any_completion_handler<void(error_code, std::size_t)> handler
0170     ) final override
0171     {
0172         return stream_.async_write_some(buff, std::move(handler));
0173     }
0174 
0175     // Connect and close
0176     void connect(const void* endpoint, error_code& ec) override final { do_connect(stream_, endpoint, ec); }
0177     void async_connect(const void* endpoint, asio::any_completion_handler<void(error_code)> handler)
0178         override final
0179     {
0180         do_async_connect(stream_, endpoint, std::move(handler));
0181     }
0182     void close(error_code& ec) override final { do_close(stream_, ec); }
0183     bool is_open() const noexcept override { return do_is_open(stream_); }
0184 };
0185 
0186 template <class Stream>
0187 class any_stream_impl<asio::ssl::stream<Stream>> final : public any_stream
0188 {
0189     asio::ssl::stream<Stream> stream_;
0190 
0191 public:
0192     template <class... Args>
0193     any_stream_impl(Args&&... args) : any_stream(true), stream_(std::forward<Args>(args)...)
0194     {
0195     }
0196 
0197     asio::ssl::stream<Stream>& stream() noexcept { return stream_; }
0198     const asio::ssl::stream<Stream>& stream() const noexcept { return stream_; }
0199 
0200     executor_type get_executor() override final { return stream_.get_executor(); }
0201 
0202     // SSL
0203     void handshake(error_code& ec) override final
0204     {
0205         set_ssl_active();
0206         stream_.handshake(boost::asio::ssl::stream_base::client, ec);
0207     }
0208     void async_handshake(asio::any_completion_handler<void(error_code)> handler) override final
0209     {
0210         set_ssl_active();
0211         stream_.async_handshake(boost::asio::ssl::stream_base::client, std::move(handler));
0212     }
0213     void shutdown(error_code& ec) override final { stream_.shutdown(ec); }
0214     void async_shutdown(asio::any_completion_handler<void(error_code)> handler) override final
0215     {
0216         return stream_.async_shutdown(std::move(handler));
0217     }
0218 
0219     // Reading
0220     std::size_t read_some(boost::asio::mutable_buffer buff, error_code& ec) override final
0221     {
0222         if (ssl_active())
0223         {
0224             return stream_.read_some(buff, ec);
0225         }
0226         else
0227         {
0228             return stream_.next_layer().read_some(buff, ec);
0229         }
0230     }
0231     void async_read_some(
0232         boost::asio::mutable_buffer buff,
0233         asio::any_completion_handler<void(error_code, std::size_t)> handler
0234     ) override final
0235     {
0236         if (ssl_active())
0237         {
0238             return stream_.async_read_some(buff, std::move(handler));
0239         }
0240         else
0241         {
0242             return stream_.next_layer().async_read_some(buff, std::move(handler));
0243         }
0244     }
0245 
0246     // Writing
0247     std::size_t write_some(boost::asio::const_buffer buff, error_code& ec) override final
0248     {
0249         if (ssl_active())
0250         {
0251             return stream_.write_some(buff, ec);
0252         }
0253         else
0254         {
0255             return stream_.next_layer().write_some(buff, ec);
0256         }
0257     }
0258     void async_write_some(
0259         boost::asio::const_buffer buff,
0260         asio::any_completion_handler<void(error_code, std::size_t)> handler
0261     ) override final
0262     {
0263         if (ssl_active())
0264         {
0265             stream_.async_write_some(buff, std::move(handler));
0266         }
0267         else
0268         {
0269             return stream_.next_layer().async_write_some(buff, std::move(handler));
0270         }
0271     }
0272 
0273     // Connect and close
0274     void connect(const void* endpoint, error_code& ec) override final { do_connect(stream_, endpoint, ec); }
0275     void async_connect(const void* endpoint, asio::any_completion_handler<void(error_code)> handler)
0276         override final
0277     {
0278         do_async_connect(stream_, endpoint, std::move(handler));
0279     }
0280     void close(error_code& ec) override final { do_close(stream_, ec); }
0281     bool is_open() const noexcept override { return do_is_open(stream_); }
0282 };
0283 
0284 template <class Stream>
0285 const Stream& cast(const any_stream& obj) noexcept
0286 {
0287     return static_cast<const any_stream_impl<Stream>&>(obj).stream();
0288 }
0289 
0290 template <class Stream>
0291 Stream& cast(any_stream& obj) noexcept
0292 {
0293     return static_cast<any_stream_impl<Stream>&>(obj).stream();
0294 }
0295 
0296 #ifdef BOOST_MYSQL_SEPARATE_COMPILATION
0297 extern template class any_stream_impl<asio::ssl::stream<asio::ip::tcp::socket>>;
0298 extern template class any_stream_impl<asio::ip::tcp::socket>;
0299 #endif
0300 
0301 }  // namespace detail
0302 }  // namespace mysql
0303 }  // namespace boost
0304 
0305 // any_stream_impl.ipp explicitly instantiates any_stream_impl, so not included here
0306 
0307 #endif