From 2b2d8c51a139d7001912dc59d5ae03a6e30f8bde Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Mon, 27 Nov 2023 19:07:29 -0500 Subject: [PATCH] rework rotate_rc_source function, just for 'normal operation' now --- llarp/nodedb.cpp | 41 +++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index f5e7018fc..7861b0041 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -114,23 +114,52 @@ namespace llarp } } + /// Called in normal operation when the relay we fetched RCs from gives either a "bad" + /// response or a timeout. Attempts to switch to a new relay as our RC source, using + /// existing connections if possible, and respecting pinned edges. void NodeDB::rotate_rc_source() { auto conn_count = router.link_manager().get_num_connected(); + + // This function makes no sense to be called if we have no connections... if (conn_count == 0) - { - // not connected to any nodes yet, so no sensible source - return; - } + throw std::runtime_error{"Called rotate_rc_source with no connections, does not make sense!"}; + + // We should not be in this function if client_known_routers isn't populated + if (client_known_routers.size() <= 1) + throw std::runtime_error{"Cannot rotate RC source without RC source(s) to rotate to!"}; + RemoteRC new_source{}; router.link_manager().get_random_connected(new_source); if (conn_count == 1) { - // only one connection, use it - rc_fetch_source = new_source.router_id(); + // if we only have one connection, it must be current rc fetch source + assert(new_source.router_id() == rc_fetch_source); + + if (pinned_edges.size() == 1) + { + // only one pinned edge set, use it even though it gave unsatisfactory RCs + assert(rc_fetch_source == *(pinned_edges.begin())); + log::warning( + logcat, + "Single pinned edge {} gave bad RC response; still using it despite this.", + rc_fetch_source); + return; + } + + // only one connection, choose a new relay to connect to for rc fetching + + RouterID r = rc_fetch_source; + while (r == rc_fetch_source) + { + std::sample(client_known_routers.begin(), client_known_routers.end(), &r, 1, csrng); + } + rc_fetch_source = std::move(r); + return; } + // choose one of our other existing connections to use as the RC fetch source while (new_source.router_id() == rc_fetch_source) { router.link_manager().get_random_connected(new_source);