From c2d54ade6707d4a2eeb5cf1fa6e141010b338826 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Tue, 1 Oct 2024 08:02:49 -0500 Subject: [PATCH 1/6] GH-525 Remove dead code --- plugins/net_plugin/net_plugin.cpp | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/plugins/net_plugin/net_plugin.cpp b/plugins/net_plugin/net_plugin.cpp index 5e19a16f85..f7a90a7a34 100644 --- a/plugins/net_plugin/net_plugin.cpp +++ b/plugins/net_plugin/net_plugin.cpp @@ -351,7 +351,6 @@ namespace eosio { struct connection_detail { std::string host; connection_ptr c; - tcp::endpoint active_ip; tcp::resolver::results_type ips; }; @@ -421,7 +420,6 @@ namespace eosio { void add(connection_ptr c); string connect(const string& host, const string& p2p_address); string resolve_and_connect(const string& host, const string& p2p_address); - void update_connection_endpoint(connection_ptr c, const tcp::endpoint& endpoint); void connect(const connection_ptr& c); string disconnect(const string& host); void close_all(); @@ -2844,7 +2842,6 @@ namespace eosio { boost::asio::bind_executor( strand, [c = shared_from_this(), socket=socket]( const boost::system::error_code& err, const tcp::endpoint& endpoint ) { if( !err && socket->is_open() && socket == c->socket ) { - my_impl->connections.update_connection_endpoint(c, endpoint); c->update_endpoints(endpoint); if( c->start_session() ) { c->send_handshake(); @@ -4647,12 +4644,9 @@ namespace eosio { void connections_manager::add( connection_ptr c ) { std::lock_guard g( connections_mtx ); - boost::system::error_code ec; - auto endpoint = c->socket->remote_endpoint(ec); connections.insert( connection_detail{ .host = c->peer_address(), - .c = std::move(c), - .active_ip = endpoint} ); + .c = std::move(c)} ); } // called by API @@ -4701,18 +4695,6 @@ namespace eosio { return "added connection"; } - void connections_manager::update_connection_endpoint(connection_ptr c, - const tcp::endpoint& endpoint) { - std::unique_lock g( connections_mtx ); - auto& index = connections.get(); - const auto& it = index.find(c); - if( it != index.end() ) { - index.modify(it, [endpoint](connection_detail& cd) { - cd.active_ip = endpoint; - }); - } - } - void connections_manager::connect(const connection_ptr& c) { std::lock_guard g( connections_mtx ); const auto& index = connections.get(); From f336eafb19fb52086a73f21b7c09f207af2bf504 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Tue, 1 Oct 2024 09:04:24 -0500 Subject: [PATCH 2/6] GH-525 Minimum code changes to resolve on reconnect --- plugins/net_plugin/net_plugin.cpp | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/plugins/net_plugin/net_plugin.cpp b/plugins/net_plugin/net_plugin.cpp index f7a90a7a34..ab3295eed7 100644 --- a/plugins/net_plugin/net_plugin.cpp +++ b/plugins/net_plugin/net_plugin.cpp @@ -419,8 +419,9 @@ namespace eosio { void add(connection_ptr c); string connect(const string& host, const string& p2p_address); - string resolve_and_connect(const string& host, const string& p2p_address); + string resolve_and_connect(const string& host, const string& p2p_address, uint16_t consecutive_immediate_connection_close = 0); void connect(const connection_ptr& c); + void remove(const connection_ptr& c); string disconnect(const string& host); void close_all(); @@ -835,7 +836,7 @@ namespace eosio { public: enum class connection_state { connecting, connected, closing, closed }; - explicit connection( const string& endpoint, const string& listen_address ); + explicit connection( const string& endpoint, const string& listen_address, uint16_t consecutive_immediate_connection_close ); /// @brief ctor /// @param socket created by boost::asio in fc::listener /// @param address identifier of listen socket which accepted this new connection @@ -1264,13 +1265,14 @@ namespace eosio { //--------------------------------------------------------------------------- - connection::connection( const string& endpoint, const string& listen_address ) + connection::connection( const string& endpoint, const string& listen_address, uint16_t consecutive_immediate_connection_close ) : peer_addr( endpoint ), strand( my_impl->thread_pool.get_executor() ), socket( new tcp::socket( my_impl->thread_pool.get_executor() ) ), listen_address( listen_address ), log_p2p_address( endpoint ), connection_id( ++my_impl->current_connection_id ), + consecutive_immediate_connection_close( consecutive_immediate_connection_close ), sync_response_expected_timer( my_impl->thread_pool.get_executor() ), last_handshake_recv(), last_handshake_sent(), @@ -2826,10 +2828,10 @@ namespace eosio { return true; // true so doesn't remove from valid connections } } + connection_ptr c = shared_from_this(); - strand.post([c]() { - my_impl->connections.connect(c); - }); + my_impl->connections.remove(c); + my_impl->connections.resolve_and_connect(c->peer_address(), c->listen_address, c->consecutive_immediate_connection_close.load()); return true; } @@ -4657,7 +4659,7 @@ namespace eosio { return resolve_and_connect( host, p2p_address ); } - string connections_manager::resolve_and_connect( const string& peer_address, const string& listen_address ) { + string connections_manager::resolve_and_connect( const string& peer_address, const string& listen_address, uint16_t consecutive_immediate_connection_close ) { string::size_type colon = peer_address.find(':'); if (colon == std::string::npos || colon == 0) { fc_elog( logger, "Invalid peer address. must be \"host:port[:|]\": ${p}", ("p", peer_address) ); @@ -4673,8 +4675,9 @@ namespace eosio { auto resolver = std::make_shared( my_impl->thread_pool.get_executor() ); resolver->async_resolve(host, port, - [resolver, host = host, port = port, peer_address = peer_address, listen_address = listen_address, this]( const boost::system::error_code& err, const tcp::resolver::results_type& results ) { - connection_ptr c = std::make_shared( peer_address, listen_address ); + [resolver, host, port, peer_address, listen_address, consecutive_immediate_connection_close, this] + ( const boost::system::error_code& err, const tcp::resolver::results_type& results ) { + connection_ptr c = std::make_shared( peer_address, listen_address, consecutive_immediate_connection_close ); c->set_heartbeat_timeout( heartbeat_timeout ); std::lock_guard g( connections_mtx ); auto [it, inserted] = connections.emplace( connection_detail{ @@ -4688,7 +4691,7 @@ namespace eosio { fc_wlog( logger, "Unable to resolve ${host}:${port} ${error}", ("host", host)("port", port)( "error", err.message() ) ); it->c->set_state(connection::connection_state::closed); - ++(it->c->consecutive_immediate_connection_close); + ++it->c->consecutive_immediate_connection_close; } } ); @@ -4704,7 +4707,13 @@ namespace eosio { } } - // called by API + void connections_manager::remove(const connection_ptr& c) { + std::lock_guard g( connections_mtx ); + auto& index = connections.get(); + index.erase(c); + } + +// called by API string connections_manager::disconnect( const string& host ) { std::lock_guard g( connections_mtx ); auto& index = connections.get(); From 6e8767ff482074d89f4515e50a91b3ba975441c8 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Tue, 1 Oct 2024 13:44:09 -0500 Subject: [PATCH 3/6] GH-525 Refactor resolve_and_connect so that connection object is reused. --- plugins/net_plugin/net_plugin.cpp | 148 +++++++++++++++--------------- 1 file changed, 73 insertions(+), 75 deletions(-) diff --git a/plugins/net_plugin/net_plugin.cpp b/plugins/net_plugin/net_plugin.cpp index ab3295eed7..326d3f55a3 100644 --- a/plugins/net_plugin/net_plugin.cpp +++ b/plugins/net_plugin/net_plugin.cpp @@ -351,7 +351,6 @@ namespace eosio { struct connection_detail { std::string host; connection_ptr c; - tcp::resolver::results_type ips; }; using connection_details_index = multi_index_container< @@ -403,6 +402,8 @@ namespace eosio { boost::asio::steady_timer::duration conn_period, uint32_t maximum_client_count); + std::chrono::milliseconds get_heartbeat_timeout() const { return heartbeat_timeout; } + uint32_t get_max_client_count() const { return max_client_count; } fc::microseconds get_connector_period() const; @@ -419,9 +420,7 @@ namespace eosio { void add(connection_ptr c); string connect(const string& host, const string& p2p_address); - string resolve_and_connect(const string& host, const string& p2p_address, uint16_t consecutive_immediate_connection_close = 0); - void connect(const connection_ptr& c); - void remove(const connection_ptr& c); + string resolve_and_connect(const string& host, const string& p2p_address); string disconnect(const string& host); void close_all(); @@ -836,7 +835,7 @@ namespace eosio { public: enum class connection_state { connecting, connected, closing, closed }; - explicit connection( const string& endpoint, const string& listen_address, uint16_t consecutive_immediate_connection_close ); + explicit connection( const string& endpoint, const string& listen_address ); /// @brief ctor /// @param socket created by boost::asio in fc::listener /// @param address identifier of listen socket which accepted this new connection @@ -1014,7 +1013,7 @@ namespace eosio { bool populate_handshake( handshake_message& hello ) const; - bool reconnect(); + bool resolve_and_connect(); void connect( const tcp::resolver::results_type& endpoints ); void start_read_message(); @@ -1265,21 +1264,20 @@ namespace eosio { //--------------------------------------------------------------------------- - connection::connection( const string& endpoint, const string& listen_address, uint16_t consecutive_immediate_connection_close ) + connection::connection( const string& endpoint, const string& listen_address ) : peer_addr( endpoint ), strand( my_impl->thread_pool.get_executor() ), socket( new tcp::socket( my_impl->thread_pool.get_executor() ) ), listen_address( listen_address ), log_p2p_address( endpoint ), connection_id( ++my_impl->current_connection_id ), - consecutive_immediate_connection_close( consecutive_immediate_connection_close ), sync_response_expected_timer( my_impl->thread_pool.get_executor() ), last_handshake_recv(), last_handshake_sent(), p2p_address( endpoint ) { + set_connection_type( peer_address() ); my_impl->mark_bp_connection(this); - update_endpoints(); fc_ilog( logger, "created connection - ${c} to ${n}", ("c", connection_id)("n", endpoint) ); } @@ -1294,7 +1292,6 @@ namespace eosio { last_handshake_recv(), last_handshake_sent() { - update_endpoints(); fc_dlog( logger, "new connection - ${c} object created for peer ${address}:${port} from listener ${addr}", ("c", connection_id)("address", log_remote_endpoint_ip)("port", log_remote_endpoint_port)("addr", listen_address) ); } @@ -1388,6 +1385,7 @@ namespace eosio { bool connection::start_session() { verify_strand_in_this_thread( strand, __func__, __LINE__ ); + update_endpoints(); boost::asio::ip::tcp::no_delay nodelay( true ); boost::system::error_code ec; socket->set_option( nodelay, ec ); @@ -2810,31 +2808,6 @@ namespace eosio { //------------------------------------------------------------------------ - bool connection::reconnect() { - switch ( no_retry ) { - case no_reason: - case wrong_version: - case benign_other: - case duplicate: // attempt reconnect in case connection has been dropped, should quickly disconnect if duplicate - break; - default: - fc_dlog( logger, "Skipping connect due to go_away reason ${r}",("r", reason_str( no_retry ))); - return false; - } - if( consecutive_immediate_connection_close > def_max_consecutive_immediate_connection_close || no_retry == benign_other ) { - fc::microseconds connector_period = my_impl->connections.get_connector_period(); - fc::lock_guard g( conn_mtx ); - if( last_close == fc::time_point() || last_close > fc::time_point::now() - connector_period ) { - return true; // true so doesn't remove from valid connections - } - } - - connection_ptr c = shared_from_this(); - my_impl->connections.remove(c); - my_impl->connections.resolve_and_connect(c->peer_address(), c->listen_address, c->consecutive_immediate_connection_close.load()); - return true; - } - // called from connection strand void connection::connect( const tcp::resolver::results_type& endpoints ) { set_state(connection_state::connecting); @@ -4635,6 +4608,7 @@ namespace eosio { update_p2p_connection_metrics = std::move(fun); } + // can be called from any thread void connections_manager::connect_supplied_peers(const string& p2p_address) { std::unique_lock g(connections_mtx); chain::flat_set peers = supplied_peers; @@ -4659,61 +4633,85 @@ namespace eosio { return resolve_and_connect( host, p2p_address ); } - string connections_manager::resolve_and_connect( const string& peer_address, const string& listen_address, uint16_t consecutive_immediate_connection_close ) { + string connections_manager::resolve_and_connect( const string& peer_address, const string& listen_address ) { string::size_type colon = peer_address.find(':'); if (colon == std::string::npos || colon == 0) { fc_elog( logger, "Invalid peer address. must be \"host:port[:|]\": ${p}", ("p", peer_address) ); return "invalid peer address"; } - std::lock_guard g( connections_mtx ); - if( find_connection_i( peer_address ) ) - return "already connected"; + { + std::lock_guard g( connections_mtx ); + if( find_connection_i( peer_address ) ) + return "already connected"; + } auto [host, port, type] = split_host_port_type(peer_address); - auto resolver = std::make_shared( my_impl->thread_pool.get_executor() ); - - resolver->async_resolve(host, port, - [resolver, host, port, peer_address, listen_address, consecutive_immediate_connection_close, this] - ( const boost::system::error_code& err, const tcp::resolver::results_type& results ) { - connection_ptr c = std::make_shared( peer_address, listen_address, consecutive_immediate_connection_close ); - c->set_heartbeat_timeout( heartbeat_timeout ); - std::lock_guard g( connections_mtx ); - auto [it, inserted] = connections.emplace( connection_detail{ - .host = peer_address, - .c = std::move(c), - .ips = results - }); - if( !err ) { - it->c->connect( results ); - } else { - fc_wlog( logger, "Unable to resolve ${host}:${port} ${error}", - ("host", host)("port", port)( "error", err.message() ) ); - it->c->set_state(connection::connection_state::closed); - ++it->c->consecutive_immediate_connection_close; - } - } ); + connection_ptr c = std::make_shared( peer_address, listen_address ); + if (c->resolve_and_connect()) { + add(c); + + return "added connection"; + } - return "added connection"; + return "connection failed"; } - void connections_manager::connect(const connection_ptr& c) { - std::lock_guard g( connections_mtx ); - const auto& index = connections.get(); - const auto& it = index.find(c); - if( it != index.end() ) { - it->c->connect( it->ips ); + // called from any thread + bool connection::resolve_and_connect() { + switch ( no_retry ) { + case no_reason: + case wrong_version: + case benign_other: + case duplicate: // attempt reconnect in case connection has been dropped, should quickly disconnect if duplicate + break; + default: + fc_dlog( logger, "Skipping connect due to go_away reason ${r}",("r", reason_str( no_retry ))); + return false; } - } - void connections_manager::remove(const connection_ptr& c) { - std::lock_guard g( connections_mtx ); - auto& index = connections.get(); - index.erase(c); + string::size_type colon = peer_address().find(':'); + if (colon == std::string::npos || colon == 0) { + fc_elog( logger, "Invalid peer address. must be \"host:port[:|]\": ${p}", ("p", peer_address()) ); + return false; + } + + connection_ptr c = shared_from_this(); + + if( consecutive_immediate_connection_close > def_max_consecutive_immediate_connection_close || no_retry == benign_other ) { + fc::microseconds connector_period = my_impl->connections.get_connector_period(); + fc::lock_guard g( conn_mtx ); + if( last_close == fc::time_point() || last_close > fc::time_point::now() - connector_period ) { + return true; // true so doesn't remove from valid connections + } + } + + auto [host, port, type] = split_host_port_type(c->peer_address()); + if (host.empty()) + return false; + + strand.post([c, host, port]() { + auto resolver = std::make_shared( my_impl->thread_pool.get_executor() ); + resolver->async_resolve(host, port, + [resolver, c, host, port] + ( const boost::system::error_code& err, const tcp::resolver::results_type& results ) { + c->set_heartbeat_timeout( my_impl->connections.get_heartbeat_timeout() ); + if( !err ) { + c->connect( results ); + } else { + fc_wlog( logger, "Unable to resolve ${host}:${port} ${error}", + ("host", host)("port", port)( "error", err.message() ) ); + c->set_state(connection::connection_state::closed); + ++c->consecutive_immediate_connection_close; + } + } ); + } ); + + return true; } -// called by API + // called by API string connections_manager::disconnect( const string& host ) { std::lock_guard g( connections_mtx ); auto& index = connections.get(); @@ -4815,7 +4813,7 @@ namespace eosio { auto cleanup = [&num_peers, &num_rm, this](vector&& reconnecting, vector&& removing) { for( auto& c : reconnecting ) { - if (!c->reconnect()) { + if (!c->resolve_and_connect()) { --num_peers; ++num_rm; removing.push_back(c); From 709f7c0e8f7ffef8ac5e849d9bff101a7409c317 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Tue, 1 Oct 2024 15:36:34 -0500 Subject: [PATCH 4/6] GH-525 Used shared_lock for shared_mutex --- plugins/net_plugin/net_plugin.cpp | 32 ++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/plugins/net_plugin/net_plugin.cpp b/plugins/net_plugin/net_plugin.cpp index 326d3f55a3..7bff463995 100644 --- a/plugins/net_plugin/net_plugin.cpp +++ b/plugins/net_plugin/net_plugin.cpp @@ -4579,7 +4579,7 @@ namespace eosio { //---------------------------------------------------------------------------- size_t connections_manager::number_connections() const { - std::lock_guard g(connections_mtx); + std::shared_lock g(connections_mtx); return connections.size(); } @@ -4610,7 +4610,7 @@ namespace eosio { // can be called from any thread void connections_manager::connect_supplied_peers(const string& p2p_address) { - std::unique_lock g(connections_mtx); + std::shared_lock g(connections_mtx); chain::flat_set peers = supplied_peers; g.unlock(); for (const auto& peer : peers) { @@ -4641,7 +4641,7 @@ namespace eosio { } { - std::lock_guard g( connections_mtx ); + std::shared_lock g( connections_mtx ); if( find_connection_i( peer_address ) ) return "already connected"; } @@ -4737,8 +4737,11 @@ namespace eosio { } std::optional connections_manager::status( const string& host )const { - std::shared_lock g( connections_mtx ); - auto con = find_connection_i( host ); + connection_ptr con; + { + std::shared_lock g( connections_mtx ); + con = find_connection_i( host ); + } if( con ) { return con->get_status(); } @@ -4746,12 +4749,19 @@ namespace eosio { } vector connections_manager::connection_statuses()const { + vector conns; vector result; - std::shared_lock g( connections_mtx ); - auto& index = connections.get(); - result.reserve( index.size() ); - for( const connection_detail& cd : index ) { - result.emplace_back( cd.c->get_status() ); + { + std::shared_lock g( connections_mtx ); + auto& index = connections.get(); + result.reserve( index.size() ); + conns.reserve( index.size() ); + for( const connection_detail& cd : index ) { + conns.emplace_back( cd.c ); + } + } + for (const auto& c : conns) { + result.push_back( c->get_status() ); } return result; } @@ -4879,7 +4889,7 @@ namespace eosio { assert(update_p2p_connection_metrics); auto from = from_connection.lock(); std::shared_lock g(connections_mtx); - auto& index = connections.get(); + const auto& index = connections.get(); size_t num_clients = 0, num_peers = 0, num_bp_peers = 0; net_plugin::p2p_per_connection_metrics per_connection(index.size()); for (auto it = index.begin(); it != index.end(); ++it) { From 3c6363058ac114fad9a257d682332b3ac49ce7f6 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Tue, 1 Oct 2024 15:37:24 -0500 Subject: [PATCH 5/6] GH-525 Used std::move --- plugins/net_plugin/net_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/net_plugin/net_plugin.cpp b/plugins/net_plugin/net_plugin.cpp index 7bff463995..e966eb3d7d 100644 --- a/plugins/net_plugin/net_plugin.cpp +++ b/plugins/net_plugin/net_plugin.cpp @@ -4650,7 +4650,7 @@ namespace eosio { connection_ptr c = std::make_shared( peer_address, listen_address ); if (c->resolve_and_connect()) { - add(c); + add(std::move(c)); return "added connection"; } From 6c6b22fd36513a8c4639bde40481811deff17712 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Tue, 1 Oct 2024 18:42:37 -0500 Subject: [PATCH 6/6] GH-525 Remove duplicate code --- plugins/net_plugin/net_plugin.cpp | 38 ++++++++++++++----------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/plugins/net_plugin/net_plugin.cpp b/plugins/net_plugin/net_plugin.cpp index e966eb3d7d..f5d93f64dc 100644 --- a/plugins/net_plugin/net_plugin.cpp +++ b/plugins/net_plugin/net_plugin.cpp @@ -1190,16 +1190,21 @@ namespace eosio { }; - std::tuple split_host_port_type(const std::string& peer_add) { + std::tuple split_host_port_type(const std::string& peer_add, bool incoming) { // host:port:[|] if (peer_add.empty()) return {}; string::size_type p = peer_add[0] == '[' ? peer_add.find(']') : 0; - if (p == string::npos) { - fc_wlog( logger, "Invalid peer address: ${peer}", ("peer", peer_add) ); + string::size_type colon = p != string::npos ? peer_add.find(':', p) : string::npos; + if (colon == std::string::npos || colon == 0) { + // if incoming then not an error this peer can do anything about + if (incoming) { + fc_dlog( logger, "Invalid peer address. must be \"host:port[:|]\": ${p}", ("p", peer_add) ); + } else { + fc_elog( logger, "Invalid peer address. must be \"host:port[:|]\": ${p}", ("p", peer_add) ); + } return {}; } - string::size_type colon = peer_add.find(':', p); string::size_type colon2 = peer_add.find(':', colon + 1); string::size_type end = colon2 == string::npos ? string::npos : peer_add.find_first_of( " :+=.,<>!$%^&(*)|-#@\t", colon2 + 1 ); // future proof by including most symbols without using regex @@ -1324,7 +1329,7 @@ namespace eosio { // called from connection strand void connection::set_connection_type( const std::string& peer_add ) { - auto [host, port, type] = split_host_port_type(peer_add); + auto [host, port, type] = split_host_port_type(peer_add, false); if( type.empty() ) { fc_dlog( logger, "Setting connection - ${c} type for: ${peer} to both transactions and blocks", ("c", connection_id)("peer", peer_add) ); connection_type = both; @@ -2866,7 +2871,7 @@ namespace eosio { fc_ilog(logger, "Accepted new connection: " + paddr_str); connections.any_of_supplied_peers([&listen_address, &paddr_str, &paddr_desc, &limit](const string& peer_addr) { - auto [host, port, type] = split_host_port_type(peer_addr); + auto [host, port, type] = split_host_port_type(peer_addr, false); if (host == paddr_str) { if (limit > 0) { fc_dlog(logger, "Connection inbound to ${la} from ${a} is a configured p2p-peer-address and will not be throttled", ("la", listen_address)("a", paddr_desc)); @@ -3362,9 +3367,9 @@ namespace eosio { } if( incoming() ) { - auto [host, port, type] = split_host_port_type(msg.p2p_address); + auto [host, port, type] = split_host_port_type(msg.p2p_address, true); if (host.size()) - set_connection_type( msg.p2p_address ); + set_connection_type( msg.p2p_address); peer_dlog( this, "checking for duplicate" ); auto is_duplicate = [&](const connection_ptr& check) { @@ -4634,9 +4639,8 @@ namespace eosio { } string connections_manager::resolve_and_connect( const string& peer_address, const string& listen_address ) { - string::size_type colon = peer_address.find(':'); - if (colon == std::string::npos || colon == 0) { - fc_elog( logger, "Invalid peer address. must be \"host:port[:|]\": ${p}", ("p", peer_address) ); + auto [host, port, type] = split_host_port_type(peer_address, false); + if (host.empty()) { return "invalid peer address"; } @@ -4646,8 +4650,6 @@ namespace eosio { return "already connected"; } - auto [host, port, type] = split_host_port_type(peer_address); - connection_ptr c = std::make_shared( peer_address, listen_address ); if (c->resolve_and_connect()) { add(std::move(c)); @@ -4671,11 +4673,9 @@ namespace eosio { return false; } - string::size_type colon = peer_address().find(':'); - if (colon == std::string::npos || colon == 0) { - fc_elog( logger, "Invalid peer address. must be \"host:port[:|]\": ${p}", ("p", peer_address()) ); + auto [host, port, type] = split_host_port_type(peer_address(), false); + if (host.empty()) return false; - } connection_ptr c = shared_from_this(); @@ -4687,10 +4687,6 @@ namespace eosio { } } - auto [host, port, type] = split_host_port_type(c->peer_address()); - if (host.empty()) - return false; - strand.post([c, host, port]() { auto resolver = std::make_shared( my_impl->thread_pool.get_executor() ); resolver->async_resolve(host, port,