diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b8fdd6c..5ea1d836 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,12 +55,21 @@ find_package(OpenSSL REQUIRED) enable_testing() include_directories(include) +#======================================================================= + +add_library(boost_redis_src STATIC examples/boost_redis.cpp) +target_compile_features(boost_redis_src PUBLIC cxx_std_20) +if (MSVC) + target_compile_options(boost_redis_src PRIVATE /bigobj) + target_compile_definitions(boost_redis_src PRIVATE _WIN32_WINNT=0x0601) +endif() + # Main function for the examples. #======================================================================= -add_library(test_common STATIC - tests/common.cpp -) +add_library(test_common STATIC) +target_sources(test_common PUBLIC tests/common.cpp) +target_link_libraries(test_common PUBLIC OpenSSL::Crypto OpenSSL::SSL boost_redis_src) target_compile_features(test_common PUBLIC cxx_std_17) if (MSVC) target_compile_options(test_common PRIVATE /bigobj) @@ -69,22 +78,19 @@ endif() #======================================================================= -add_library(common STATIC - examples/start.cpp - examples/main.cpp - examples/boost_redis.cpp -) -target_compile_features(common PUBLIC cxx_std_20) +add_library(examples_common STATIC examples/main.cpp) +target_compile_features(examples_common PUBLIC cxx_std_20) +target_link_libraries(examples_common PRIVATE boost_redis_src) if (MSVC) - target_compile_options(common PRIVATE /bigobj) - target_compile_definitions(common PRIVATE _WIN32_WINNT=0x0601) + target_compile_options(examples_common PRIVATE /bigobj) + target_compile_definitions(examples_common PRIVATE _WIN32_WINNT=0x0601) endif() # Executables #======================================================================= add_executable(cpp20_intro examples/cpp20_intro.cpp) -target_link_libraries(cpp20_intro common) +target_link_libraries(cpp20_intro PRIVATE OpenSSL::Crypto OpenSSL::SSL examples_common) target_compile_features(cpp20_intro PUBLIC cxx_std_20) add_test(cpp20_intro cpp20_intro) if (MSVC) @@ -93,7 +99,7 @@ if (MSVC) endif() add_executable(cpp20_streams examples/cpp20_streams.cpp) -target_link_libraries(cpp20_streams common) +target_link_libraries(cpp20_streams PRIVATE OpenSSL::Crypto OpenSSL::SSL examples_common) target_compile_features(cpp20_streams PUBLIC cxx_std_20) if (MSVC) target_compile_options(cpp20_streams PRIVATE /bigobj) @@ -101,6 +107,7 @@ if (MSVC) endif() add_executable(cpp17_intro examples/cpp17_intro.cpp) +target_link_libraries(cpp17_intro PRIVATE OpenSSL::Crypto OpenSSL::SSL) target_compile_features(cpp17_intro PUBLIC cxx_std_17) add_test(cpp17_intro cpp17_intro) if (MSVC) @@ -111,18 +118,19 @@ endif() if (NOT MSVC) add_executable(cpp17_intro_sync examples/cpp17_intro_sync.cpp) target_compile_features(cpp17_intro_sync PUBLIC cxx_std_17) +target_link_libraries(cpp17_intro_sync PRIVATE OpenSSL::Crypto OpenSSL::SSL) add_test(cpp17_intro_sync cpp17_intro_sync) endif() if (NOT MSVC) add_executable(cpp20_chat_room examples/cpp20_chat_room.cpp) target_compile_features(cpp20_chat_room PUBLIC cxx_std_20) -target_link_libraries(cpp20_chat_room common) +target_link_libraries(cpp20_chat_room PRIVATE OpenSSL::Crypto OpenSSL::SSL examples_common) endif() add_executable(cpp20_containers examples/cpp20_containers.cpp) target_compile_features(cpp20_containers PUBLIC cxx_std_20) -target_link_libraries(cpp20_containers common) +target_link_libraries(cpp20_containers PRIVATE OpenSSL::Crypto OpenSSL::SSL examples_common) add_test(cpp20_containers cpp20_containers) if (MSVC) target_compile_options(cpp20_containers PRIVATE /bigobj) @@ -132,12 +140,12 @@ endif() if (NOT MSVC) add_executable(cpp20_echo_server examples/cpp20_echo_server.cpp) target_compile_features(cpp20_echo_server PUBLIC cxx_std_20) -target_link_libraries(cpp20_echo_server common) +target_link_libraries(cpp20_echo_server PRIVATE OpenSSL::Crypto OpenSSL::SSL examples_common) endif() add_executable(cpp20_resolve_with_sentinel examples/cpp20_resolve_with_sentinel.cpp) target_compile_features(cpp20_resolve_with_sentinel PUBLIC cxx_std_20) -target_link_libraries(cpp20_resolve_with_sentinel common) +target_link_libraries(cpp20_resolve_with_sentinel PRIVATE OpenSSL::Crypto OpenSSL::SSL examples_common) #add_test(cpp20_resolve_with_sentinel cpp20_resolve_with_sentinel) if (MSVC) target_compile_options(cpp20_resolve_with_sentinel PRIVATE /bigobj) @@ -146,7 +154,7 @@ endif() add_executable(cpp20_json examples/cpp20_json.cpp) target_compile_features(cpp20_json PUBLIC cxx_std_20) -target_link_libraries(cpp20_json common) +target_link_libraries(cpp20_json PRIVATE OpenSSL::Crypto OpenSSL::SSL examples_common) add_test(cpp20_json cpp20_json) if (MSVC) target_compile_options(cpp20_json PRIVATE /bigobj) @@ -157,7 +165,7 @@ if (Protobuf_FOUND) protobuf_generate_cpp(PROTO_SRCS PROTO_HDRS examples/person.proto) add_executable(cpp20_protobuf examples/cpp20_protobuf.cpp ${PROTO_SRCS} ${PROTO_HDRS}) target_compile_features(cpp20_protobuf PUBLIC cxx_std_20) - target_link_libraries(cpp20_protobuf common ${Protobuf_LIBRARIES}) + target_link_libraries(cpp20_protobuf PRIVATE OpenSSL::Crypto OpenSSL::SSL examples_common ${Protobuf_LIBRARIES}) target_include_directories(cpp20_protobuf PUBLIC ${Protobuf_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}) add_test(cpp20_protobuf cpp20_protobuf) if (MSVC) @@ -168,7 +176,7 @@ endif() add_executable(cpp20_subscriber examples/cpp20_subscriber.cpp) target_compile_features(cpp20_subscriber PUBLIC cxx_std_20) -target_link_libraries(cpp20_subscriber common) +target_link_libraries(cpp20_subscriber PRIVATE OpenSSL::Crypto OpenSSL::SSL examples_common) if (MSVC) target_compile_options(cpp20_subscriber PRIVATE /bigobj) target_compile_definitions(cpp20_subscriber PRIVATE _WIN32_WINNT=0x0601) @@ -177,8 +185,7 @@ endif() add_executable(cpp20_intro_tls examples/cpp20_intro_tls.cpp) target_compile_features(cpp20_intro_tls PUBLIC cxx_std_20) add_test(cpp20_intro_tls cpp20_intro_tls) -target_link_libraries(cpp20_intro_tls OpenSSL::Crypto OpenSSL::SSL) -target_link_libraries(cpp20_intro_tls common) +target_link_libraries(cpp20_intro_tls PRIVATE OpenSSL::Crypto OpenSSL::SSL examples_common) if (MSVC) target_compile_options(cpp20_intro_tls PRIVATE /bigobj) target_compile_definitions(cpp20_intro_tls PRIVATE _WIN32_WINNT=0x0601) @@ -187,7 +194,7 @@ endif() add_executable(cpp20_low_level_async tests/cpp20_low_level_async.cpp) target_compile_features(cpp20_low_level_async PUBLIC cxx_std_20) add_test(cpp20_low_level_async cpp20_low_level_async) -target_link_libraries(cpp20_low_level_async common) +target_link_libraries(cpp20_low_level_async PRIVATE OpenSSL::Crypto OpenSSL::SSL examples_common boost_redis_src) if (MSVC) target_compile_options(cpp20_low_level_async PRIVATE /bigobj) target_compile_definitions(cpp20_low_level_async PRIVATE _WIN32_WINNT=0x0601) @@ -209,6 +216,7 @@ endif() add_executable(cpp17_low_level_sync tests/cpp17_low_level_sync.cpp) target_compile_features(cpp17_low_level_sync PUBLIC cxx_std_17) +target_link_libraries(cpp17_low_level_sync PRIVATE OpenSSL::Crypto OpenSSL::SSL examples_common boost_redis_src) add_test(cpp17_low_level_sync cpp17_low_level_sync) if (MSVC) target_compile_options(cpp17_low_level_sync PRIVATE /bigobj) @@ -217,7 +225,7 @@ endif() add_executable(test_conn_exec tests/conn_exec.cpp) target_compile_features(test_conn_exec PUBLIC cxx_std_20) -target_link_libraries(test_conn_exec test_common) +target_link_libraries(test_conn_exec PRIVATE OpenSSL::Crypto OpenSSL::SSL test_common) add_test(test_conn_exec test_conn_exec) if (MSVC) target_compile_options(test_conn_exec PRIVATE /bigobj) @@ -226,7 +234,7 @@ endif() add_executable(test_conn_exec_retry tests/conn_exec_retry.cpp) target_compile_features(test_conn_exec_retry PUBLIC cxx_std_20) -target_link_libraries(test_conn_exec_retry test_common) +target_link_libraries(test_conn_exec_retry PRIVATE OpenSSL::Crypto OpenSSL::SSL test_common) add_test(test_conn_exec_retry test_conn_exec_retry) if (MSVC) target_compile_options(test_conn_exec_retry PRIVATE /bigobj) @@ -235,7 +243,7 @@ endif() add_executable(test_conn_push tests/conn_push.cpp) target_compile_features(test_conn_push PUBLIC cxx_std_20) -target_link_libraries(test_conn_push test_common) +target_link_libraries(test_conn_push PRIVATE OpenSSL::Crypto OpenSSL::SSL test_common) add_test(test_conn_push test_conn_push) if (MSVC) target_compile_options(test_conn_push PRIVATE /bigobj) @@ -244,6 +252,7 @@ endif() add_executable(test_conn_quit tests/conn_quit.cpp) target_compile_features(test_conn_quit PUBLIC cxx_std_17) +target_link_libraries(test_conn_quit PRIVATE OpenSSL::Crypto OpenSSL::SSL test_common) add_test(test_conn_quit test_conn_quit) if (MSVC) target_compile_options(test_conn_quit PRIVATE /bigobj) @@ -252,7 +261,7 @@ endif() add_executable(test_conn_reconnect tests/conn_reconnect.cpp) target_compile_features(test_conn_reconnect PUBLIC cxx_std_20) -target_link_libraries(test_conn_reconnect common test_common) +target_link_libraries(test_conn_reconnect PRIVATE OpenSSL::Crypto OpenSSL::SSL test_common) add_test(test_conn_reconnect test_conn_reconnect) if (MSVC) target_compile_options(test_conn_reconnect PRIVATE /bigobj) @@ -262,7 +271,7 @@ endif() add_executable(test_conn_tls tests/conn_tls.cpp) add_test(test_conn_tls test_conn_tls) target_compile_features(test_conn_tls PUBLIC cxx_std_17) -target_link_libraries(test_conn_tls OpenSSL::Crypto OpenSSL::SSL) +target_link_libraries(test_conn_tls PRIVATE OpenSSL::Crypto OpenSSL::SSL boost_redis_src) if (MSVC) target_compile_options(test_conn_tls PRIVATE /bigobj) target_compile_definitions(test_conn_tls PRIVATE _WIN32_WINNT=0x0601) @@ -270,6 +279,7 @@ endif() add_executable(test_low_level tests/low_level.cpp) target_compile_features(test_low_level PUBLIC cxx_std_17) +target_link_libraries(test_low_level PRIVATE OpenSSL::Crypto OpenSSL::SSL boost_redis_src) add_test(test_low_level test_low_level) if (MSVC) target_compile_options(test_low_level PRIVATE /bigobj) @@ -279,6 +289,7 @@ endif() add_executable(test_conn_run_cancel tests/conn_run_cancel.cpp) target_compile_features(test_conn_run_cancel PUBLIC cxx_std_20) add_test(test_conn_run_cancel test_conn_run_cancel) +target_link_libraries(test_conn_run_cancel PRIVATE OpenSSL::Crypto OpenSSL::SSL boost_redis_src) if (MSVC) target_compile_options(test_conn_run_cancel PRIVATE /bigobj) target_compile_definitions(test_conn_run_cancel PRIVATE _WIN32_WINNT=0x0601) @@ -286,7 +297,7 @@ endif() add_executable(test_conn_exec_cancel tests/conn_exec_cancel.cpp) target_compile_features(test_conn_exec_cancel PUBLIC cxx_std_20) -target_link_libraries(test_conn_exec_cancel common test_common) +target_link_libraries(test_conn_exec_cancel PRIVATE OpenSSL::Crypto OpenSSL::SSL test_common boost_redis_src) add_test(test_conn_exec_cancel test_conn_exec_cancel) if (MSVC) target_compile_options(test_conn_exec_cancel PRIVATE /bigobj) @@ -295,7 +306,7 @@ endif() add_executable(test_conn_exec_cancel2 tests/conn_exec_cancel2.cpp) target_compile_features(test_conn_exec_cancel2 PUBLIC cxx_std_20) -target_link_libraries(test_conn_exec_cancel2 common test_common) +target_link_libraries(test_conn_exec_cancel2 PRIVATE OpenSSL::Crypto OpenSSL::SSL test_common boost_redis_src) add_test(test_conn_exec_cancel2 test_conn_exec_cancel2) if (MSVC) target_compile_options(test_conn_exec_cancel2 PRIVATE /bigobj) @@ -304,7 +315,7 @@ endif() add_executable(test_conn_exec_error tests/conn_exec_error.cpp) target_compile_features(test_conn_exec_error PUBLIC cxx_std_17) -target_link_libraries(test_conn_exec_error common test_common) +target_link_libraries(test_conn_exec_error PRIVATE OpenSSL::Crypto OpenSSL::SSL test_common boost_redis_src) add_test(test_conn_exec_error test_conn_exec_error) if (MSVC) target_compile_options(test_conn_exec_error PRIVATE /bigobj) @@ -313,7 +324,7 @@ endif() add_executable(test_conn_echo_stress tests/conn_echo_stress.cpp) target_compile_features(test_conn_echo_stress PUBLIC cxx_std_20) -target_link_libraries(test_conn_echo_stress common test_common) +target_link_libraries(test_conn_echo_stress PRIVATE OpenSSL::Crypto OpenSSL::SSL test_common boost_redis_src) add_test(test_conn_echo_stress test_conn_echo_stress) if (MSVC) target_compile_options(test_conn_echo_stress PRIVATE /bigobj) @@ -322,6 +333,7 @@ endif() add_executable(test_request tests/request.cpp) target_compile_features(test_request PUBLIC cxx_std_17) +target_link_libraries(test_request PRIVATE OpenSSL::Crypto OpenSSL::SSL test_common boost_redis_src) add_test(test_request test_request) if (MSVC) target_compile_options(test_request PRIVATE /bigobj) @@ -330,7 +342,7 @@ endif() add_executable(test_issue_50 tests/issue_50.cpp) target_compile_features(test_issue_50 PUBLIC cxx_std_20) -target_link_libraries(test_issue_50 common) +target_link_libraries(test_issue_50 PRIVATE OpenSSL::Crypto OpenSSL::SSL examples_common boost_redis_src) add_test(test_issue_50 test_issue_50) if (MSVC) target_compile_options(test_issue_50 PRIVATE /bigobj) @@ -339,7 +351,7 @@ endif() add_executable(test_conn_check_health tests/conn_check_health.cpp) target_compile_features(test_conn_check_health PUBLIC cxx_std_17) -target_link_libraries(test_conn_check_health common) +target_link_libraries(test_conn_check_health PRIVATE OpenSSL::Crypto OpenSSL::SSL examples_common boost_redis_src) add_test(test_conn_check_health test_conn_check_health) if (MSVC) target_compile_options(test_conn_check_health PRIVATE /bigobj) @@ -348,7 +360,7 @@ endif() add_executable(test_run tests/run.cpp) target_compile_features(test_run PUBLIC cxx_std_17) -target_link_libraries(test_run test_common) +target_link_libraries(test_run PRIVATE OpenSSL::Crypto OpenSSL::SSL test_common boost_redis_src) add_test(test_run test_run) if (MSVC) target_compile_options(test_run PRIVATE /bigobj) diff --git a/README.md b/README.md index 4184916a..7bc5da0f 100644 --- a/README.md +++ b/README.md @@ -678,7 +678,7 @@ Acknowledgement to people that helped shape Boost.Redis * Mohammad Nejati ([ashtum](https://github.com/ashtum)): For pointing out scenarios where calls to `async_exec` should fail when the connection is lost. * Klemens Morgenstern ([klemens-morgenstern](https://github.com/klemens-morgenstern)): For useful discussion about timeouts, cancellation, synchronous interfaces and general help with Asio. * Vinnie Falco ([vinniefalco](https://github.com/vinniefalco)): For general suggestions about how to improve the code and the documentation. -* Bram Veldhoen ([bveldhoen](https://github.com/bveldhoen)): For contributing a Redis streams example. +* Bram Veldhoen ([bveldhoen](https://github.com/bveldhoen)): For contributing a Redis-streams example. Also many thanks to all individuals that participated in the Boost review diff --git a/examples/cpp17_intro_sync.cpp b/examples/cpp17_intro_sync.cpp index 1969c3ce..bd106d29 100644 --- a/examples/cpp17_intro_sync.cpp +++ b/examples/cpp17_intro_sync.cpp @@ -12,6 +12,7 @@ // Include this in no more than one .cpp file. #include +namespace net = boost::asio; using boost::redis::sync_connection; using boost::redis::request; using boost::redis::response; diff --git a/examples/cpp20_chat_room.cpp b/examples/cpp20_chat_room.cpp index 7ef27c1e..489e5952 100644 --- a/examples/cpp20_chat_room.cpp +++ b/examples/cpp20_chat_room.cpp @@ -38,7 +38,7 @@ receiver(std::shared_ptr conn) -> net::awaitable request req; req.push("SUBSCRIBE", "channel"); - while (!conn->is_cancelled()) { + while (conn->will_reconnect()) { // Subscribe to channels. co_await conn->async_exec(req); diff --git a/examples/cpp20_intro_tls.cpp b/examples/cpp20_intro_tls.cpp index 33c36e0b..23b491e1 100644 --- a/examples/cpp20_intro_tls.cpp +++ b/examples/cpp20_intro_tls.cpp @@ -4,7 +4,7 @@ * accompanying file LICENSE.txt) */ -#include +#include #include #include #include @@ -18,7 +18,7 @@ using boost::redis::request; using boost::redis::response; using boost::redis::config; using boost::redis::logger; -using connection = net::deferred_t::as_default_on_t; +using connection = net::deferred_t::as_default_on_t; auto verify_certificate(bool, net::ssl::verify_context&) -> bool { @@ -28,13 +28,13 @@ auto verify_certificate(bool, net::ssl::verify_context&) -> bool auto co_main(config cfg) -> net::awaitable { + cfg.use_ssl = true; cfg.username = "aedis"; cfg.password = "aedis"; cfg.addr.host = "db.occase.de"; cfg.addr.port = "6380"; - net::ssl::context ctx{net::ssl::context::sslv23}; - auto conn = std::make_shared(co_await net::this_coro::executor, ctx); + auto conn = std::make_shared(co_await net::this_coro::executor); conn->async_run(cfg, {}, net::consign(net::detached, conn)); request req; diff --git a/examples/cpp20_subscriber.cpp b/examples/cpp20_subscriber.cpp index 5bc76a7d..1753095f 100644 --- a/examples/cpp20_subscriber.cpp +++ b/examples/cpp20_subscriber.cpp @@ -51,7 +51,7 @@ receiver(std::shared_ptr conn) -> net::awaitable request req; req.push("SUBSCRIBE", "channel"); - while (!conn->is_cancelled()) { + while (conn->will_reconnect()) { // Reconnect to channels. co_await conn->async_exec(req); diff --git a/examples/main.cpp b/examples/main.cpp index ffd67d9b..e8501954 100644 --- a/examples/main.cpp +++ b/examples/main.cpp @@ -4,34 +4,44 @@ * accompanying file LICENSE.txt) */ -#include "start.hpp" #include -#include -#include +#include +#include +#include #include -#if defined(BOOST_ASIO_HAS_CO_AWAIT) - +namespace net = boost::asio; using boost::redis::config; -extern boost::asio::awaitable co_main(config); +#if defined(BOOST_ASIO_HAS_CO_AWAIT) + +extern net::awaitable co_main(config); auto main(int argc, char * argv[]) -> int { - config cfg; - - if (argc == 3) { - cfg.addr.host = argv[1]; - cfg.addr.port = argv[2]; + try { + config cfg; + + if (argc == 3) { + cfg.addr.host = argv[1]; + cfg.addr.port = argv[2]; + } + + net::io_context ioc; + net::co_spawn(ioc, std::move(co_main(cfg)), [](std::exception_ptr p) { + if (p) + std::rethrow_exception(p); + }); + ioc.run(); + + } catch (std::exception const& e) { + std::cerr << "(main) " << e.what() << std::endl; + return 1; } - - return start(co_main(cfg)); } #else // defined(BOOST_ASIO_HAS_CO_AWAIT) -#include - auto main() -> int { std::cout << "Requires coroutine support." << std::endl; diff --git a/examples/start.cpp b/examples/start.cpp deleted file mode 100644 index fb6a9f01..00000000 --- a/examples/start.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright (c) 2018-2022 Marcelo Zimbres Silva (mzimbres@gmail.com) - * - * Distributed under the Boost Software License, Version 1.0. (See - * accompanying file LICENSE.txt) - */ - -#include -#include -#include -#include -#include "start.hpp" - -#if defined(BOOST_ASIO_HAS_CO_AWAIT) - -namespace net = boost::asio; - -auto start(net::awaitable op) -> int -{ - try { - net::io_context ioc; - net::co_spawn(ioc, std::move(op), [](std::exception_ptr p) { - if (p) - std::rethrow_exception(p); - }); - ioc.run(); - - return 0; - - } catch (std::exception const& e) { - std::cerr << "start> " << e.what() << std::endl; - } - - return 1; -} - -#endif // defined(BOOST_ASIO_HAS_CO_AWAIT) diff --git a/examples/start.hpp b/examples/start.hpp deleted file mode 100644 index a4ee0ef5..00000000 --- a/examples/start.hpp +++ /dev/null @@ -1,17 +0,0 @@ -/* Copyright (c) 2018-2022 Marcelo Zimbres Silva (mzimbres@gmail.com) - * - * Distributed under the Boost Software License, Version 1.0. (See - * accompanying file LICENSE.txt) - */ - -#ifndef BOOST_REDIS_EXAMPLES_START_HPP -#define BOOST_REDIS_EXAMPLES_START_HPP - -#include - -#if defined(BOOST_ASIO_HAS_CO_AWAIT) - -auto start(boost::asio::awaitable op) -> int; - -#endif // defined(BOOST_ASIO_HAS_CO_AWAIT) -#endif // BOOST_REDIS_EXAMPLES_START_HPP diff --git a/include/boost/redis/config.hpp b/include/boost/redis/config.hpp index 0abc4016..01e4caa6 100644 --- a/include/boost/redis/config.hpp +++ b/include/boost/redis/config.hpp @@ -27,6 +27,9 @@ struct address { * @ingroup high-level-api */ struct config { + /// Uses SSL instead of a plain connection. + bool use_ssl = false; + /// Address of the Redis server. address addr = address{"127.0.0.1", "6379"}; @@ -60,10 +63,16 @@ struct config { /// Time the SSL handshake operation is allowed to last. std::chrono::steady_clock::duration ssl_handshake_timeout = std::chrono::seconds{10}; - /// @brief Health checks interval. + /** Health checks interval. + * + * To disable health-checks pass zero as duration. + */ std::chrono::steady_clock::duration health_check_interval = std::chrono::seconds{2}; - /// Time waited before trying a reconnection. + /** @brief Time waited before trying a reconnection. + * + * To disable reconnection pass zero as duration. + */ std::chrono::steady_clock::duration reconnect_wait_interval = std::chrono::seconds{1}; }; diff --git a/include/boost/redis/connection.hpp b/include/boost/redis/connection.hpp index 931e4fbb..7360e848 100644 --- a/include/boost/redis/connection.hpp +++ b/include/boost/redis/connection.hpp @@ -9,101 +9,88 @@ #include #include +#include #include #include #include #include +#include #include +#include #include #include namespace boost::redis { -namespace detail -{ - -template -class dummy_handshaker { -public: - dummy_handshaker(Executor) {} - - template - auto async_handshake(Stream&, CompletionToken&& token) - { return asio::post(std::move(token)); } - - void set_config(config const&) {} - - std::size_t cancel(operation) { return 0;} - - constexpr bool is_dummy() const noexcept {return true;} -}; - -} - -/** @brief A connection to the Redis server. - * @ingroup high-level-api +/** \brief A SSL connection to the Redis server. + * \ingroup high-level-api * - * For more details, please see the documentation of each individual - * function. + * This class keeps a healthy connection to the Redis instance where + * commands can be sent at any time. For more details, please see the + * documentation of each individual function. * * @tparam Socket The socket type e.g. asio::ip::tcp::socket. + * */ -template -class basic_connection : - private detail::connection_base< - typename Socket::executor_type, - basic_connection> { +template +class basic_connection : private detail::connection_base> { public: - /// Executor type. - using executor_type = typename Socket::executor_type; - /// Type of the next layer - using next_layer_type = Socket; + using next_layer_type = asio::ssl::stream>; + + /// Executor type. + using executor_type = Executor; /// Rebinds the socket type to another executor. template struct rebind_executor { - /// The socket type when rebound to the specified executor. - using other = basic_connection::other>; + /// The connection type when rebound to the specified executor. + using other = basic_connection; }; - using base_type = detail::connection_base>; + using base_type = redis::detail::connection_base>; /// Contructs from an executor. explicit - basic_connection(executor_type ex) + basic_connection(executor_type ex, asio::ssl::context::method method = asio::ssl::context::tls_client) : base_type{ex} + , ctx_{method} , reconn_{ex} , runner_{ex, {}} - , stream_{ex} - {} + , stream_{std::make_unique(ex, ctx_)} + { } /// Contructs from a context. explicit - basic_connection(asio::io_context& ioc) - : basic_connection(ioc.get_executor()) + basic_connection(asio::io_context& ioc, asio::ssl::context::method method = asio::ssl::context::tls_client) + : basic_connection(ioc.get_executor(), method) { } /// Returns the associated executor. - auto get_executor() {return stream_.get_executor();} + auto get_executor() + {return stream_->get_executor();} - /// Resets the underlying stream. + /// Returns the ssl context. + auto const& get_ssl_context() const noexcept + { return ctx_;} + + /// Returns the ssl context. + auto& get_ssl_context() noexcept + { return ctx_;} + + /// Reset the underlying stream. void reset_stream() { - if (stream_.is_open()) { - system::error_code ec; - stream_.shutdown(asio::ip::tcp::socket::shutdown_both, ec); - stream_.close(ec); - } + stream_ = std::make_unique(stream_->get_executor(), ctx_); } /// Returns a reference to the next layer. - auto next_layer() noexcept -> auto& { return stream_; } + auto& next_layer() noexcept { return *stream_; } /// Returns a const reference to the next layer. - auto next_layer() const noexcept -> auto const& { return stream_; } + auto const& next_layer() const noexcept { return *stream_; } /** @brief Starts underlying connection operations. * @@ -153,7 +140,8 @@ class basic_connection : Logger l = Logger{}, CompletionToken token = CompletionToken{}) { - reconn_.set_wait_interval(cfg.reconnect_wait_interval); + use_ssl_ = cfg.use_ssl; + reconn_.set_config(cfg.reconnect_wait_interval); runner_.set_config(cfg); l.set_prefix(runner_.get_config().log_prefix); return reconn_.async_run(*this, l, std::move(token)); @@ -262,11 +250,11 @@ class basic_connection : { base_type::reserve(read, write); } /// Returns true if the connection was canceled. - bool is_cancelled() const noexcept - { return reconn_.is_cancelled();} + bool will_reconnect() const noexcept + { return reconn_.will_reconnect();} private: - using runner_type = detail::runner; + using runner_type = detail::runner; using reconnection_type = detail::basic_reconnection; using this_type = basic_connection; @@ -290,20 +278,27 @@ class basic_connection : { return base_type::async_run_impl(l, std::move(token)); } void close() - { reset_stream(); } + { + if (stream_->next_layer().is_open()) + stream_->next_layer().close(); + } + + auto is_open() const noexcept { return stream_->next_layer().is_open(); } + auto& lowest_layer() noexcept { return stream_->lowest_layer(); } - auto is_open() const noexcept { return stream_.is_open(); } - auto lowest_layer() noexcept -> auto& { return stream_.lowest_layer(); } + auto use_ssl() const noexcept { return use_ssl_;} + bool use_ssl_ = false; + asio::ssl::context ctx_; reconnection_type reconn_; runner_type runner_; - Socket stream_; + std::unique_ptr stream_; }; -/** \brief A connection that uses a asio::ip::tcp::socket. +/** \brief A connection that uses the asio::any_io_executor. * \ingroup high-level-api */ -using connection = basic_connection; +using connection = basic_connection; } // boost::redis diff --git a/include/boost/redis/detail/connection_base.hpp b/include/boost/redis/detail/connection_base.hpp index 7b51608d..de22bd5d 100644 --- a/include/boost/redis/detail/connection_base.hpp +++ b/include/boost/redis/detail/connection_base.hpp @@ -83,6 +83,11 @@ class read_next_op { , cmds_{info->get_number_of_commands()} {} + auto make_adapter() noexcept + { + return [i = index_, adpt = adapter_] (resp3::basic_node const& nd, system::error_code& ec) mutable { adpt(i, nd, ec); }; + } + template void operator()( Self& self @@ -103,11 +108,12 @@ class read_next_op { // to hand it to the push consumer. To do that we need // some data in the read bufer. if (conn_->read_buffer_.empty()) { - BOOST_ASIO_CORO_YIELD - asio::async_read_until( - conn_->next_layer(), - conn_->make_dynamic_buffer(), - "\r\n", std::move(self)); + + if (conn_->derived().use_ssl()) + BOOST_ASIO_CORO_YIELD asio::async_read_until(conn_->next_layer(), conn_->make_dynamic_buffer(), "\r\n", std::move(self)); + else + BOOST_ASIO_CORO_YIELD asio::async_read_until(conn_->next_layer().next_layer(), conn_->make_dynamic_buffer(), "\r\n", std::move(self)); + BOOST_REDIS_CHECK_OP1(conn_->cancel(operation::run);); if (info_->stop_requested()) { self.complete(asio::error::operation_aborted, 0); @@ -125,12 +131,10 @@ class read_next_op { } //----------------------------------- - BOOST_ASIO_CORO_YIELD - redis::detail::async_read( - conn_->next_layer(), - conn_->make_dynamic_buffer(), - [i = index_, adpt = adapter_] (resp3::basic_node const& nd, system::error_code& ec) mutable { adpt(i, nd, ec); }, - std::move(self)); + if (conn_->derived().use_ssl()) + BOOST_ASIO_CORO_YIELD redis::detail::async_read(conn_->next_layer(), conn_->make_dynamic_buffer(), make_adapter(), std::move(self)); + else + BOOST_ASIO_CORO_YIELD redis::detail::async_read(conn_->next_layer().next_layer(), conn_->make_dynamic_buffer(), make_adapter(), std::move(self)); ++index_; @@ -166,8 +170,11 @@ struct receive_op { conn->channel_.async_receive(std::move(self)); BOOST_REDIS_CHECK_OP1(;); - BOOST_ASIO_CORO_YIELD - redis::detail::async_read(conn->next_layer(), conn->make_dynamic_buffer(), adapter, std::move(self)); + if (conn->derived().use_ssl()) + BOOST_ASIO_CORO_YIELD redis::detail::async_read(conn->next_layer(), conn->make_dynamic_buffer(), adapter, std::move(self)); + else + BOOST_ASIO_CORO_YIELD redis::detail::async_read(conn->next_layer().next_layer(), conn->make_dynamic_buffer(), adapter, std::move(self)); + if (ec || is_cancelled(self)) { conn->cancel(operation::run); conn->cancel(operation::receive); @@ -342,8 +349,11 @@ struct writer_op { BOOST_ASIO_CORO_REENTER (coro) for (;;) { while (conn_->coalesce_requests()) { - BOOST_ASIO_CORO_YIELD - asio::async_write(conn_->next_layer(), asio::buffer(conn_->write_buffer_), std::move(self)); + if (conn_->derived().use_ssl()) + BOOST_ASIO_CORO_YIELD asio::async_write(conn_->next_layer(), asio::buffer(conn_->write_buffer_), std::move(self)); + else + BOOST_ASIO_CORO_YIELD asio::async_write(conn_->next_layer().next_layer(), asio::buffer(conn_->write_buffer_), std::move(self)); + logger_.on_write(ec, conn_->write_buffer_); BOOST_REDIS_CHECK_OP0(conn_->cancel(operation::run);); @@ -394,11 +404,10 @@ struct reader_op { BOOST_ASIO_CORO_REENTER (coro) for (;;) { - BOOST_ASIO_CORO_YIELD - asio::async_read_until( - conn->next_layer(), - conn->make_dynamic_buffer(), - "\r\n", std::move(self)); + if (conn->derived().use_ssl()) + BOOST_ASIO_CORO_YIELD asio::async_read_until(conn->next_layer(), conn->make_dynamic_buffer(), "\r\n", std::move(self)); + else + BOOST_ASIO_CORO_YIELD asio::async_read_until(conn->next_layer().next_layer(), conn->make_dynamic_buffer(), "\r\n", std::move(self)); if (ec == asio::error::eof) { conn->cancel(operation::run); diff --git a/include/boost/redis/ssl/detail/handshaker.hpp b/include/boost/redis/detail/handshaker.hpp similarity index 97% rename from include/boost/redis/ssl/detail/handshaker.hpp rename to include/boost/redis/detail/handshaker.hpp index 987c6ef3..6658aa9b 100644 --- a/include/boost/redis/ssl/detail/handshaker.hpp +++ b/include/boost/redis/detail/handshaker.hpp @@ -19,7 +19,7 @@ #include #include -namespace boost::redis::ssl::detail +namespace boost::redis::detail { template @@ -119,6 +119,6 @@ class handshaker { std::chrono::steady_clock::duration timeout_; }; -} // boost::redis::ssl::detail +} // boost::redis::detail #endif // BOOST_REDIS_SSL_CONNECTOR_HPP diff --git a/include/boost/redis/detail/health_checker.hpp b/include/boost/redis/detail/health_checker.hpp index 374f2b87..d6c2143c 100644 --- a/include/boost/redis/detail/health_checker.hpp +++ b/include/boost/redis/detail/health_checker.hpp @@ -107,7 +107,7 @@ class check_health_op { { BOOST_ASIO_CORO_REENTER (coro_) { - if (checker_->ping_interval_.count() == 0) { + if (checker_->ping_interval_ == std::chrono::seconds::zero()) { BOOST_ASIO_CORO_YIELD asio::post(std::move(self)); self.complete({}); diff --git a/include/boost/redis/detail/reconnection.hpp b/include/boost/redis/detail/reconnection.hpp index d021a3d9..88ee1817 100644 --- a/include/boost/redis/detail/reconnection.hpp +++ b/include/boost/redis/detail/reconnection.hpp @@ -30,10 +30,9 @@ struct reconnection_op { { BOOST_ASIO_CORO_YIELD conn_->async_run_one(logger_, std::move(self)); - conn_->reset_stream(); conn_->cancel(operation::receive); logger_.on_connection_lost(ec); - if (reconn_->is_cancelled() || is_cancelled(self)) { + if (!reconn_->will_reconnect() || is_cancelled(self)) { reconn_->cancel(operation::reconnection); self.complete(!!ec ? ec : asio::error::operation_aborted); return; @@ -43,10 +42,11 @@ struct reconnection_op { BOOST_ASIO_CORO_YIELD reconn_->timer_.async_wait(std::move(self)); BOOST_REDIS_CHECK_OP0(;) - if (reconn_->is_cancelled()) { + if (!reconn_->will_reconnect()) { self.complete(asio::error::operation_aborted); return; } + conn_->reset_stream(); } } }; @@ -56,19 +56,16 @@ struct reconnection_op { template class basic_reconnection { public: - /// Executor type. using executor_type = Executor; basic_reconnection(Executor ex) : timer_{ex} - , is_cancelled_{false} {} basic_reconnection(asio::io_context& ioc, std::chrono::steady_clock::duration wait_interval) : basic_reconnection{ioc.get_executor(), wait_interval} {} - /// Rebinds to a new executor type. template struct rebind_executor { @@ -92,7 +89,7 @@ class basic_reconnection { >(detail::reconnection_op{this, &conn, l}, token, conn); } - void set_wait_interval(std::chrono::steady_clock::duration wait_interval) + void set_config(std::chrono::steady_clock::duration wait_interval) { wait_interval_ = wait_interval; } @@ -102,7 +99,7 @@ class basic_reconnection { switch (op) { case operation::reconnection: case operation::all: - is_cancelled_ = true; + wait_interval_ = std::chrono::seconds::zero(); timer_.cancel(); break; default: /* ignore */; @@ -111,8 +108,8 @@ class basic_reconnection { return 0U; } - bool is_cancelled() const noexcept {return is_cancelled_;} - void reset() noexcept {is_cancelled_ = false;} + bool will_reconnect() const noexcept + { return wait_interval_ != std::chrono::seconds::zero();} private: using timer_type = @@ -125,11 +122,8 @@ class basic_reconnection { timer_type timer_; std::chrono::steady_clock::duration wait_interval_ = std::chrono::seconds{1}; - bool is_cancelled_; }; -using reconnection = basic_reconnection; - } // boost::redis #endif // BOOST_REDIS_RECONNECTION_HPP diff --git a/include/boost/redis/detail/runner.hpp b/include/boost/redis/detail/runner.hpp index b9329187..1fa4c0c7 100644 --- a/include/boost/redis/detail/runner.hpp +++ b/include/boost/redis/detail/runner.hpp @@ -136,7 +136,7 @@ struct run_all_op { logger_.on_connect(ec, runner_->ctor_.endpoint()); BOOST_REDIS_CHECK_OP0(conn_->cancel(operation::run);) - if (!runner_->hsher_.is_dummy()) { + if (conn_->use_ssl()) { BOOST_ASIO_CORO_YIELD runner_->hsher_.async_handshake(conn_->next_layer(), std::move(self)); logger_.on_ssl_handshake(ec); diff --git a/include/boost/redis/ssl/connection.hpp b/include/boost/redis/ssl/connection.hpp deleted file mode 100644 index 37da52a8..00000000 --- a/include/boost/redis/ssl/connection.hpp +++ /dev/null @@ -1,215 +0,0 @@ -/* Copyright (c) 2018-2022 Marcelo Zimbres Silva (mzimbres@gmail.com) - * - * Distributed under the Boost Software License, Version 1.0. (See - * accompanying file LICENSE.txt) - */ - -#ifndef BOOST_REDIS_SSL_CONNECTION_HPP -#define BOOST_REDIS_SSL_CONNECTION_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace boost::redis::ssl { - -template -class basic_connection; - -/** \brief A SSL connection to the Redis server. - * \ingroup high-level-api - * - * This class keeps a healthy connection to the Redis instance where - * commands can be sent at any time. For more details, please see the - * documentation of each individual function. - * - * @tparam Socket The socket type e.g. asio::ip::tcp::socket. - * - */ -template -class basic_connection> : - private redis::detail::connection_base< - typename asio::ssl::stream::executor_type, - basic_connection>> { -public: - /// Type of the next layer - using next_layer_type = asio::ssl::stream; - - /// Executor type. - using executor_type = typename next_layer_type::executor_type; - - /// Rebinds the socket type to another executor. - template - struct rebind_executor - { - /// The socket type when rebound to the specified executor. - using other = basic_connection::other>>; - }; - - using base_type = redis::detail::connection_base>>; - - /// Constructor - explicit - basic_connection(executor_type ex, asio::ssl::context& ctx) - : base_type{ex} - , ctx_{&ctx} - , reconn_{ex} - , runner_{ex, {}} - , stream_{std::make_unique(ex, ctx)} - { } - - /// Constructor - explicit - basic_connection(asio::io_context& ioc, asio::ssl::context& ctx) - : basic_connection(ioc.get_executor(), ctx) - { } - - /// Returns the associated executor. - auto get_executor() {return stream_->get_executor();} - - /// Reset the underlying stream. - void reset_stream() - { - if (stream_->next_layer().is_open()) { - stream_->next_layer().close(); - stream_ = std::make_unique(stream_->get_executor(), *ctx_); - } - } - - /// Returns a reference to the next layer. - auto& next_layer() noexcept { return *stream_; } - - /// Returns a const reference to the next layer. - auto const& next_layer() const noexcept { return *stream_; } - - /** @brief Establishes a connection with the Redis server asynchronously. - * - * See redis::connection::async_run for more information. - */ - template < - class Logger = logger, - class CompletionToken = asio::default_completion_token_t> - auto - async_run( - config const& cfg = {}, - Logger l = Logger{}, - CompletionToken token = CompletionToken{}) - { - reconn_.set_wait_interval(cfg.reconnect_wait_interval); - runner_.set_config(cfg); - l.set_prefix(runner_.get_config().log_prefix); - return reconn_.async_run(*this, l, std::move(token)); - } - - /** @brief Executes a command on the Redis server asynchronously. - * - * See redis::connection::async_exec for more information. - */ - template < - class Response = ignore_t, - class CompletionToken = asio::default_completion_token_t> - auto async_exec( - request const& req, - Response& response = ignore, - CompletionToken token = CompletionToken{}) - { - return base_type::async_exec(req, response, std::move(token)); - } - - /** @brief Receives server side pushes asynchronously. - * - * See redis::connection::async_receive for detailed information. - */ - template < - class Response = ignore_t, - class CompletionToken = asio::default_completion_token_t> - auto async_receive( - Response& response = ignore, - CompletionToken token = CompletionToken{}) - { - return base_type::async_receive(response, std::move(token)); - } - - /** @brief Cancel operations. - * - * See redis::connection::cancel for more information. - */ - auto cancel(operation op = operation::all) -> std::size_t - { - reconn_.cancel(op); - runner_.cancel(op); - return base_type::cancel(op); - } - - auto& lowest_layer() noexcept { return stream_->lowest_layer(); } - - /// Sets the maximum size of the read buffer. - void set_max_buffer_read_size(std::size_t max_read_size) noexcept - { base_type::set_max_buffer_read_size(max_read_size); } - - /** @brief Reserve memory on the read and write internal buffers. - * - * This function will call `std::string::reserve` on the - * underlying buffers. - * - * @param read The new capacity of the read buffer. - * @param write The new capacity of the write buffer. - */ - void reserve(std::size_t read, std::size_t write) - { base_type::reserve(read, write); } - - /// Returns true if the connection was canceled. - bool is_cancelled() const noexcept - { return reconn_.is_cancelled();} - -private: - using runner_type = redis::detail::runner; - using reconnection_type = redis::detail::basic_reconnection; - using this_type = basic_connection; - - template - auto async_run_one(Logger l, CompletionToken token) - { return runner_.async_run(*this, l, std::move(token)); } - - template - auto async_run_impl(Logger l, CompletionToken token) - { return base_type::async_run_impl(l, std::move(token)); } - - template friend class redis::detail::connection_base; - template friend class redis::detail::read_next_op; - template friend struct redis::detail::exec_op; - template friend struct redis::detail::receive_op; - template friend struct redis::detail::run_op; - template friend struct redis::detail::writer_op; - template friend struct redis::detail::reader_op; - template friend struct redis::detail::wait_receive_op; - template friend struct redis::detail::run_all_op; - template friend struct redis::detail::reconnection_op; - - auto is_open() const noexcept { return stream_->next_layer().is_open(); } - - void close() - { reset_stream(); } - - asio::ssl::context* ctx_; - reconnection_type reconn_; - runner_type runner_; - std::unique_ptr stream_; -}; - -/** \brief A connection that uses a boost::asio::ssl::stream. - * \ingroup high-level-api - */ -using connection = basic_connection>; - -} // boost::redis::ssl - -#endif // BOOST_REDIS_SSL_CONNECTION_HPP diff --git a/tests/common.cpp b/tests/common.cpp index 6583ffd5..366cd1d8 100644 --- a/tests/common.cpp +++ b/tests/common.cpp @@ -1,9 +1,12 @@ #include "common.hpp" #include #include +#include #include +namespace net = boost::asio; + struct run_callback { std::shared_ptr conn; boost::redis::operation op; @@ -27,3 +30,24 @@ run( conn->async_run(cfg, {}, run_callback{conn, op, ec}); } +#ifdef BOOST_ASIO_HAS_CO_AWAIT +auto start(net::awaitable op) -> int +{ + try { + net::io_context ioc; + net::co_spawn(ioc, std::move(op), [](std::exception_ptr p) { + if (p) + std::rethrow_exception(p); + }); + ioc.run(); + + return 0; + + } catch (std::exception const& e) { + std::cerr << "start> " << e.what() << std::endl; + } + + return 1; +} + +#endif // BOOST_ASIO_HAS_CO_AWAIT diff --git a/tests/common.hpp b/tests/common.hpp index 3f8909d2..4b917b54 100644 --- a/tests/common.hpp +++ b/tests/common.hpp @@ -2,18 +2,17 @@ #include #include +#include #include #include #include #include -namespace net = boost::asio; - #ifdef BOOST_ASIO_HAS_CO_AWAIT - inline auto redir(boost::system::error_code& ec) - { return net::redirect_error(boost::asio::use_awaitable, ec); } + { return boost::asio::redirect_error(boost::asio::use_awaitable, ec); } +auto start(boost::asio::awaitable op) -> int; #endif // BOOST_ASIO_HAS_CO_AWAIT void diff --git a/tests/conn_check_health.cpp b/tests/conn_check_health.cpp index 34a22496..494f22c7 100644 --- a/tests/conn_check_health.cpp +++ b/tests/conn_check_health.cpp @@ -10,7 +10,6 @@ #include #include #include "common.hpp" -#include namespace net = boost::asio; namespace redis = boost::redis; @@ -76,13 +75,13 @@ BOOST_AUTO_TEST_CASE(check_health) connection conn1{ioc}; - conn1.cancel(operation::reconnection); request req1; req1.push("CLIENT", "PAUSE", "10000", "ALL"); config cfg1; cfg1.health_check_id = "conn1"; + cfg1.reconnect_wait_interval = std::chrono::seconds::zero(); error_code res1; conn1.async_run(cfg1, {}, [&](auto ec) { std::cout << "async_run 1 completed: " << ec.message() << std::endl; diff --git a/tests/conn_echo_stress.cpp b/tests/conn_echo_stress.cpp index 3adb1a0f..bcb1f395 100644 --- a/tests/conn_echo_stress.cpp +++ b/tests/conn_echo_stress.cpp @@ -12,8 +12,6 @@ #include #include #include "common.hpp" -#include "../examples/start.hpp" -#include #ifdef BOOST_ASIO_HAS_CO_AWAIT diff --git a/tests/conn_exec.cpp b/tests/conn_exec.cpp index c9eaeac2..b5fe3a1e 100644 --- a/tests/conn_exec.cpp +++ b/tests/conn_exec.cpp @@ -10,7 +10,6 @@ #include #include #include "common.hpp" -#include // TODO: Test whether HELLO won't be inserted passt commands that have // been already writen. diff --git a/tests/conn_exec_cancel.cpp b/tests/conn_exec_cancel.cpp index 882698f4..1d257387 100644 --- a/tests/conn_exec_cancel.cpp +++ b/tests/conn_exec_cancel.cpp @@ -9,9 +9,7 @@ #define BOOST_TEST_MODULE conn-exec-cancel #include #include "common.hpp" -#include "../examples/start.hpp" #include -#include #ifdef BOOST_ASIO_HAS_CO_AWAIT #include diff --git a/tests/conn_exec_cancel2.cpp b/tests/conn_exec_cancel2.cpp index 83b383c4..37ee49fb 100644 --- a/tests/conn_exec_cancel2.cpp +++ b/tests/conn_exec_cancel2.cpp @@ -9,9 +9,7 @@ #define BOOST_TEST_MODULE conn-exec-cancel #include #include "common.hpp" -#include "../examples/start.hpp" #include -#include #ifdef BOOST_ASIO_HAS_CO_AWAIT #include diff --git a/tests/conn_exec_error.cpp b/tests/conn_exec_error.cpp index 45b9de2c..16f53631 100644 --- a/tests/conn_exec_error.cpp +++ b/tests/conn_exec_error.cpp @@ -10,7 +10,6 @@ #define BOOST_TEST_MODULE conn-exec-error #include #include "common.hpp" -#include #include namespace net = boost::asio; diff --git a/tests/conn_exec_retry.cpp b/tests/conn_exec_retry.cpp index 41ca94cb..7cc1f232 100644 --- a/tests/conn_exec_retry.cpp +++ b/tests/conn_exec_retry.cpp @@ -13,8 +13,6 @@ #include #include "common.hpp" -#include - namespace net = boost::asio; using error_code = boost::system::error_code; using connection = boost::redis::connection; diff --git a/tests/conn_push.cpp b/tests/conn_push.cpp index d2a9399b..c5770026 100644 --- a/tests/conn_push.cpp +++ b/tests/conn_push.cpp @@ -14,7 +14,6 @@ #include #include #include "common.hpp" -#include namespace net = boost::asio; namespace redis = boost::redis; diff --git a/tests/conn_quit.cpp b/tests/conn_quit.cpp index 0d5ba9a2..bf126ba1 100644 --- a/tests/conn_quit.cpp +++ b/tests/conn_quit.cpp @@ -9,9 +9,7 @@ #define BOOST_TEST_MODULE conn-quit #include #include - -// TODO: Move this to a lib. -#include +#include "common.hpp" namespace net = boost::asio; using boost::redis::connection; @@ -30,17 +28,14 @@ BOOST_AUTO_TEST_CASE(test_eof_no_error) req.push("QUIT"); net::io_context ioc; - connection conn{ioc}; + auto conn = std::make_shared(ioc); - conn.async_exec(req, ignore, [&](auto ec, auto) { + conn->async_exec(req, ignore, [&](auto ec, auto) { BOOST_TEST(!ec); - conn.cancel(operation::reconnection); - }); - - conn.async_run({}, {}, [](auto ec){ - BOOST_TEST(!!ec); + conn->cancel(operation::reconnection); }); + run(conn); ioc.run(); } @@ -49,8 +44,7 @@ BOOST_AUTO_TEST_CASE(test_async_run_exits) { net::io_context ioc; - connection conn{ioc}; - conn.cancel(operation::reconnection); + auto conn = std::make_shared(ioc); request req1; req1.get_config().cancel_on_connection_lost = false; @@ -75,25 +69,24 @@ BOOST_AUTO_TEST_CASE(test_async_run_exits) { std::clog << "c2: " << ec.message() << std::endl; BOOST_TEST(!ec); - conn.async_exec(req3, ignore, c3); + conn->async_exec(req3, ignore, c3); }; auto c1 = [&](auto ec, auto) { - std::cout << "c3: " << ec.message() << std::endl; + std::cout << "c1: " << ec.message() << std::endl; BOOST_TEST(!ec); - conn.async_exec(req2, ignore, c2); + conn->async_exec(req2, ignore, c2); }; - conn.async_exec(req1, ignore, c1); + conn->async_exec(req1, ignore, c1); // The healthy checker should not be the cause of async_run - // completing, so we set a long timeout. + // completing, so we disable. config cfg; - cfg.health_check_interval = 10000s; - conn.async_run({}, {}, [&](auto ec){ - BOOST_TEST(!!ec); - }); + cfg.health_check_interval = 0s; + cfg.reconnect_wait_interval = 0s; + run(conn, cfg); ioc.run(); } diff --git a/tests/conn_reconnect.cpp b/tests/conn_reconnect.cpp index ce948709..e1d37fe0 100644 --- a/tests/conn_reconnect.cpp +++ b/tests/conn_reconnect.cpp @@ -10,8 +10,6 @@ #include #include #include "common.hpp" -#include "../examples/start.hpp" -#include #ifdef BOOST_ASIO_HAS_CO_AWAIT #include @@ -57,9 +55,7 @@ net::awaitable test_reconnect_impl() // Test whether the client works after a reconnect. BOOST_AUTO_TEST_CASE(test_reconnect) { - net::io_context ioc; - net::co_spawn(ioc, test_reconnect_impl(), net::detached); - ioc.run(); + start(test_reconnect_impl()); } auto async_test_reconnect_timeout() -> net::awaitable diff --git a/tests/conn_run_cancel.cpp b/tests/conn_run_cancel.cpp index d9f383f1..09934c2b 100644 --- a/tests/conn_run_cancel.cpp +++ b/tests/conn_run_cancel.cpp @@ -12,7 +12,6 @@ #include #include #include "common.hpp" -#include #ifdef BOOST_ASIO_HAS_CO_AWAIT #include diff --git a/tests/conn_tls.cpp b/tests/conn_tls.cpp index 7a62b3b1..fef978ff 100644 --- a/tests/conn_tls.cpp +++ b/tests/conn_tls.cpp @@ -4,17 +4,15 @@ * accompanying file LICENSE.txt) */ -#include +#include #define BOOST_TEST_MODULE conn-tls #include #include #include "common.hpp" -#include - namespace net = boost::asio; -using connection = boost::redis::ssl::connection; +using connection = boost::redis::connection; using boost::redis::request; using boost::redis::response; using boost::redis::config; @@ -29,6 +27,7 @@ bool verify_certificate(bool, net::ssl::verify_context&) BOOST_AUTO_TEST_CASE(ping) { config cfg; + cfg.use_ssl = true; cfg.username = "aedis"; cfg.password = "aedis"; cfg.addr.host = "db.occase.de"; @@ -42,8 +41,7 @@ BOOST_AUTO_TEST_CASE(ping) response resp; net::io_context ioc; - net::ssl::context ctx{net::ssl::context::sslv23}; - connection conn{ioc, ctx}; + connection conn{ioc}; conn.next_layer().set_verify_mode(net::ssl::verify_peer); conn.next_layer().set_verify_callback(verify_certificate); diff --git a/tests/cpp17_low_level_sync.cpp b/tests/cpp17_low_level_sync.cpp index 81cd5949..78c753f8 100644 --- a/tests/cpp17_low_level_sync.cpp +++ b/tests/cpp17_low_level_sync.cpp @@ -11,7 +11,6 @@ #include #include #include -#include namespace net = boost::asio; namespace redis = boost::redis; diff --git a/tests/issue_50.cpp b/tests/issue_50.cpp index 4905cbed..38bc5f53 100644 --- a/tests/issue_50.cpp +++ b/tests/issue_50.cpp @@ -17,7 +17,6 @@ #include #include #include -#include "../examples/start.hpp" #if defined(BOOST_ASIO_HAS_CO_AWAIT) @@ -40,7 +39,7 @@ auto receiver(std::shared_ptr conn) -> net::awaitable { std::cout << "uuu" << std::endl; - while (!conn->is_cancelled()) { + while (conn->will_reconnect()) { std::cout << "dddd" << std::endl; // Loop reading Redis pushs messages. for (;;) { diff --git a/tests/low_level.cpp b/tests/low_level.cpp index 9902aedc..059d2e6f 100644 --- a/tests/low_level.cpp +++ b/tests/low_level.cpp @@ -22,8 +22,6 @@ #include #include -#include - // TODO: Test with empty strings. namespace std diff --git a/tests/request.cpp b/tests/request.cpp index 8b5a603b..6dd29f04 100644 --- a/tests/request.cpp +++ b/tests/request.cpp @@ -10,9 +10,6 @@ #include #include -#include -#include -#include using boost::redis::request; diff --git a/tests/run.cpp b/tests/run.cpp index 3e2740e9..b6837b17 100644 --- a/tests/run.cpp +++ b/tests/run.cpp @@ -8,7 +8,6 @@ #define BOOST_TEST_MODULE run #include #include -#include #include "common.hpp" namespace net = boost::asio; @@ -38,9 +37,9 @@ BOOST_AUTO_TEST_CASE(resolve_bad_host) cfg.resolve_timeout = 10h; cfg.connect_timeout = 10h; cfg.health_check_interval = 10h; + cfg.reconnect_wait_interval = 0s; connection conn{ioc}; - conn.cancel(operation::reconnection); conn.async_run(cfg, {}, [](auto ec){ BOOST_TEST(is_host_not_found(ec)); }); @@ -58,9 +57,9 @@ BOOST_AUTO_TEST_CASE(resolve_with_timeout) cfg.resolve_timeout = 1ms; cfg.connect_timeout = 1ms; cfg.health_check_interval = 10h; + cfg.reconnect_wait_interval = 0s; auto conn = std::make_shared(ioc); - conn->cancel(operation::reconnection); run(conn, cfg); ioc.run(); } @@ -75,9 +74,9 @@ BOOST_AUTO_TEST_CASE(connect_bad_port) cfg.resolve_timeout = 10h; cfg.connect_timeout = 10s; cfg.health_check_interval = 10h; + cfg.reconnect_wait_interval = 0s; auto conn = std::make_shared(ioc); - conn->cancel(operation::reconnection); run(conn, cfg, net::error::connection_refused); ioc.run(); }