File indexing completed on 2026-08-17 09:00:18
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/redis/adapter/any_adapter.hpp>
0010 #include <boost/redis/config.hpp>
0011 #include <boost/redis/detail/connection_state.hpp>
0012 #include <boost/redis/detail/coroutine.hpp>
0013 #include <boost/redis/detail/multiplexer.hpp>
0014 #include <boost/redis/detail/run_fsm.hpp>
0015 #include <boost/redis/impl/is_terminal_cancel.hpp>
0016 #include <boost/redis/impl/log_utils.hpp>
0017 #include <boost/redis/impl/setup_request_utils.hpp>
0018
0019 #include <boost/asio/cancellation_type.hpp>
0020 #include <boost/asio/error.hpp>
0021 #include <boost/asio/local/basic_endpoint.hpp> // for BOOST_ASIO_HAS_LOCAL_SOCKETS
0022 #include <boost/system/error_code.hpp>
0023
0024 namespace boost::redis::detail {
0025
0026 inline system::error_code check_config(const config& cfg)
0027 {
0028 if (!cfg.unix_socket.empty()) {
0029 if (cfg.use_ssl)
0030 return error::unix_sockets_ssl_unsupported;
0031 #ifndef BOOST_ASIO_HAS_LOCAL_SOCKETS
0032 return error::unix_sockets_unsupported;
0033 #endif
0034 }
0035 return system::error_code{};
0036 }
0037
0038 inline void compose_ping_request(const config& cfg, request& to)
0039 {
0040 to.clear();
0041 to.push("PING", cfg.health_check_id);
0042 }
0043
0044 inline void process_setup_node(
0045 connection_state& st,
0046 resp3::basic_node<std::string_view> const& nd,
0047 system::error_code& ec)
0048 {
0049 switch (nd.data_type) {
0050 case resp3::type::simple_error:
0051 case resp3::type::blob_error:
0052 case resp3::type::null:
0053 ec = redis::error::resp3_hello;
0054 st.setup_diagnostic = nd.value;
0055 break;
0056 default:;
0057 }
0058 }
0059
0060 inline any_adapter make_setup_adapter(connection_state& st)
0061 {
0062 return any_adapter{
0063 [&st](any_adapter::parse_event evt, resp3::node_view const& nd, system::error_code& ec) {
0064 if (evt == any_adapter::parse_event::node)
0065 process_setup_node(st, nd, ec);
0066 }};
0067 }
0068
0069 inline void on_setup_done(const multiplexer::elem& elm, connection_state& st)
0070 {
0071 const auto ec = elm.get_error();
0072 if (ec) {
0073 if (st.setup_diagnostic.empty()) {
0074 log_info(st.logger, "Setup request execution: ", ec);
0075 } else {
0076 log_info(st.logger, "Setup request execution: ", ec, " (", st.setup_diagnostic, ")");
0077 }
0078 } else {
0079 log_info(st.logger, "Setup request execution: success");
0080 }
0081 }
0082
0083 run_action run_fsm::resume(
0084 connection_state& st,
0085 system::error_code ec,
0086 asio::cancellation_type_t cancel_state)
0087 {
0088 switch (resume_point_) {
0089 BOOST_REDIS_CORO_INITIAL
0090
0091
0092 ec = check_config(st.cfg);
0093 if (ec) {
0094 log_err(st.logger, "Invalid configuration: ", ec);
0095 stored_ec_ = ec;
0096 BOOST_REDIS_YIELD(resume_point_, 1, run_action_type::immediate)
0097 return stored_ec_;
0098 }
0099
0100
0101 compose_setup_request(st.cfg);
0102
0103
0104 compose_ping_request(st.cfg, st.ping_req);
0105
0106 for (;;) {
0107
0108 BOOST_REDIS_YIELD(resume_point_, 2, run_action_type::connect)
0109
0110
0111 if (is_terminal_cancel(cancel_state)) {
0112 log_debug(st.logger, "Run: cancelled (1)");
0113 return system::error_code(asio::error::operation_aborted);
0114 }
0115
0116
0117 if (!ec) {
0118
0119 st.mpx.reset();
0120 st.setup_diagnostic.clear();
0121
0122
0123 if (st.cfg.setup.get_commands() != 0u) {
0124 auto elm = make_elem(st.cfg.setup, make_setup_adapter(st));
0125 elm->set_done_callback([&elem_ref = *elm, &st] {
0126 on_setup_done(elem_ref, st);
0127 });
0128 st.mpx.add(elm);
0129 }
0130
0131
0132 BOOST_REDIS_YIELD(resume_point_, 3, run_action_type::parallel_group)
0133
0134
0135 stored_ec_ = ec;
0136
0137
0138
0139 st.mpx.cancel_on_conn_lost();
0140
0141
0142
0143
0144 BOOST_REDIS_YIELD(resume_point_, 4, run_action_type::cancel_receive)
0145
0146
0147 ec = stored_ec_;
0148 }
0149
0150
0151 if (is_terminal_cancel(cancel_state)) {
0152 log_debug(st.logger, "Run: cancelled (2)");
0153 return system::error_code(asio::error::operation_aborted);
0154 }
0155
0156
0157 if (st.cfg.reconnect_wait_interval.count() == 0) {
0158 return ec;
0159 }
0160
0161
0162 BOOST_REDIS_YIELD(resume_point_, 5, run_action_type::wait_for_reconnection)
0163
0164
0165 if (is_terminal_cancel(cancel_state)) {
0166 log_debug(st.logger, "Run: cancelled (3)");
0167 return system::error_code(asio::error::operation_aborted);
0168 }
0169 }
0170 }
0171
0172
0173 BOOST_ASSERT(false);
0174 return system::error_code();
0175 }
0176
0177 }