mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
fix: Replaces random endpoint resolution with sequential (#5365)
This change addresses an issue where `rippled` attempts to connect to an IPv6 address, even when the local network lacks IPv6 support, resulting in a "Network is unreachable" error. The fix replaces the custom endpoint selection logic with `boost::async_connect`, which sequentially attempts to connect to available endpoints until one succeeds or all fail.
This commit is contained in:
@@ -102,7 +102,7 @@ ValidatorSite::ValidatorSite(
|
|||||||
ValidatorSite::~ValidatorSite()
|
ValidatorSite::~ValidatorSite()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock{state_mutex_};
|
std::unique_lock<std::mutex> lock{state_mutex_};
|
||||||
if (timer_.expires_at() > clock_type::time_point{})
|
if (timer_.expiry() > clock_type::time_point{})
|
||||||
{
|
{
|
||||||
if (!stopping_)
|
if (!stopping_)
|
||||||
{
|
{
|
||||||
@@ -168,7 +168,7 @@ ValidatorSite::start()
|
|||||||
{
|
{
|
||||||
std::lock_guard l0{sites_mutex_};
|
std::lock_guard l0{sites_mutex_};
|
||||||
std::lock_guard l1{state_mutex_};
|
std::lock_guard l1{state_mutex_};
|
||||||
if (timer_.expires_at() == clock_type::time_point{})
|
if (timer_.expiry() == clock_type::time_point{})
|
||||||
setTimer(l0, l1);
|
setTimer(l0, l1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,6 +96,9 @@ public:
|
|||||||
void
|
void
|
||||||
onResolve(error_code const& ec, results_type results);
|
onResolve(error_code const& ec, results_type results);
|
||||||
|
|
||||||
|
void
|
||||||
|
onConnect(error_code const& ec, endpoint_type const& endpoint);
|
||||||
|
|
||||||
void
|
void
|
||||||
onStart();
|
onStart();
|
||||||
|
|
||||||
@@ -195,46 +198,26 @@ WorkBase<Impl>::onResolve(error_code const& ec, results_type results)
|
|||||||
if (ec)
|
if (ec)
|
||||||
return fail(ec);
|
return fail(ec);
|
||||||
|
|
||||||
// Use last endpoint if it is successfully connected
|
boost::asio::async_connect(
|
||||||
// and is in the list, otherwise pick a random endpoint
|
socket_,
|
||||||
// from the list (excluding last endpoint). If there is
|
results,
|
||||||
// only one endpoint and it is the last endpoint then
|
|
||||||
// use the last endpoint.
|
|
||||||
lastEndpoint_ = [&]() -> endpoint_type {
|
|
||||||
int foundIndex = 0;
|
|
||||||
auto const foundIt = std::find_if(
|
|
||||||
results.begin(), results.end(), [&](endpoint_type const& e) {
|
|
||||||
if (e == lastEndpoint_)
|
|
||||||
return true;
|
|
||||||
foundIndex++;
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
if (foundIt != results.end() && lastStatus_)
|
|
||||||
return lastEndpoint_;
|
|
||||||
else if (results.size() == 1)
|
|
||||||
return *results.begin();
|
|
||||||
else if (foundIt == results.end())
|
|
||||||
return *std::next(results.begin(), rand_int(results.size() - 1));
|
|
||||||
|
|
||||||
// lastEndpoint_ is part of the collection
|
|
||||||
// Pick a random number from the n-1 valid choices, if we use
|
|
||||||
// this as an index, note the last element will never be chosen
|
|
||||||
// and the `lastEndpoint_` index may be chosen. So when the
|
|
||||||
// `lastEndpoint_` index is chosen, that is treated as if the
|
|
||||||
// last element was chosen.
|
|
||||||
auto randIndex =
|
|
||||||
(results.size() > 2) ? rand_int(results.size() - 2) : 0;
|
|
||||||
if (randIndex == foundIndex)
|
|
||||||
randIndex = results.size() - 1;
|
|
||||||
return *std::next(results.begin(), randIndex);
|
|
||||||
}();
|
|
||||||
|
|
||||||
socket_.async_connect(
|
|
||||||
lastEndpoint_,
|
|
||||||
strand_.wrap(std::bind(
|
strand_.wrap(std::bind(
|
||||||
&Impl::onConnect,
|
&WorkBase::onConnect,
|
||||||
impl().shared_from_this(),
|
impl().shared_from_this(),
|
||||||
std::placeholders::_1)));
|
std::placeholders::_1,
|
||||||
|
std::placeholders::_2)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Impl>
|
||||||
|
void
|
||||||
|
WorkBase<Impl>::onConnect(error_code const& ec, endpoint_type const& endpoint)
|
||||||
|
{
|
||||||
|
lastEndpoint_ = endpoint;
|
||||||
|
|
||||||
|
if (ec)
|
||||||
|
return fail(ec);
|
||||||
|
|
||||||
|
impl().onConnect(ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
|
|||||||
Reference in New Issue
Block a user