File indexing completed on 2025-01-18 09:42:39
0001
0002
0003
0004
0005
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
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
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
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
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
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
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
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
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
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 }
0302 }
0303 }
0304
0305
0306
0307 #endif