From 5fa3c2be87ac4978a82087c291ee3d2cafd6668a Mon Sep 17 00:00:00 2001 From: dr7ana Date: Tue, 28 Nov 2023 04:55:01 -0800 Subject: [PATCH] housekeeping and groundwork, initial commit --- llarp/link/link_manager.cpp | 31 ++++--- llarp/link/link_manager.hpp | 2 +- llarp/messages/dht.hpp | 1 + llarp/messages/rc.hpp | 3 +- llarp/nodedb.cpp | 147 ++++++++++++++++++++++++-------- llarp/nodedb.hpp | 68 +++++++++------ llarp/router/router.cpp | 92 ++++++++++++-------- llarp/router/router.hpp | 26 ++---- llarp/router_contact.cpp | 1 - llarp/router_contact.hpp | 6 +- llarp/router_contact_remote.cpp | 5 +- llarp/util/time.cpp | 6 ++ llarp/util/time.hpp | 5 ++ 13 files changed, 260 insertions(+), 133 deletions(-) diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 77f699740..926c1ceac 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -461,10 +461,9 @@ namespace llarp auto timestamp = rc_time{std::chrono::seconds{btdc.require("time"sv)}}; std::vector rcs; + while (not btlc.is_finished()) { - // TODO: maybe make RemoteRC constructor throw a bespoke exception type - // and catch it below so we know what about parsing failed? rcs.emplace_back(btlc.consume_dict_consumer()); } @@ -486,32 +485,35 @@ namespace llarp assert(_router.is_service_node()); const auto& rcs = node_db->get_rcs(); - const auto now = - std::chrono::time_point_cast(std::chrono::system_clock::now()); + const auto now = time_point_now(); + try { oxenc::bt_dict_consumer btdc{m.body()}; btdc.required("explicit_ids"); auto explicit_ids = btdc.consume_list>(); + auto since_time = rc_time{std::chrono::seconds{btdc.require("since")}}; if (explicit_ids.size() > (rcs.size() / 4)) { log::info( link_cat, "Remote requested too many relay IDs (greater than 1/4 of what we have)."); - m.respond(serialize_response({{messages::STATUS_KEY, RCFetchMessage::INVALID_REQUEST}})); + m.respond(RCFetchMessage::INVALID_REQUEST, true); return; } std::unordered_set explicit_relays; + for (auto& sv : explicit_ids) { if (sv.size() != RouterID::SIZE) { - m.respond(serialize_response({{messages::STATUS_KEY, RCFetchMessage::INVALID_REQUEST}})); + m.respond(RCFetchMessage::INVALID_REQUEST, true); return; } + explicit_relays.emplace(reinterpret_cast(sv.data())); } @@ -535,17 +537,17 @@ namespace llarp resp.append("time", now.time_since_epoch().count()); - m.respond(std::move(resp).str(), false); + m.respond(std::move(resp).str()); } catch (const std::exception& e) { log::info(link_cat, "Exception handling RC Fetch request: {}", e.what()); - m.respond(messages::ERROR_RESPONSE); + m.respond(messages::ERROR_RESPONSE, true); } } void - LinkManager::fetch_router_ids(const RouterID& source) + LinkManager::fetch_router_ids(const RouterID& source, std::function func) { if (ep.conns.empty()) { @@ -559,6 +561,7 @@ namespace llarp edge, "fetch_router_ids"s, RouterIDFetch::serialize(source), + (func) ? std::move(func) : [this, source = source, edge = std::move(edge)](oxen::quic::message m) { if (not m) { @@ -567,14 +570,17 @@ namespace llarp "Error fetching RouterIDs from source \"{}\" via edge \"{}\"", source, edge); - node_db->ingest_router_ids(edge, {}); // empty response == failure + node_db->ingest_router_ids(edge); // empty response == failure return; } + try { oxenc::bt_dict_consumer btdc{m.body()}; + btdc.required("routers"); auto router_id_strings = btdc.consume_list>(); + btdc.require_signature("signature", [&edge](ustring_view msg, ustring_view sig) { if (sig.size() != 64) throw std::runtime_error{"Invalid signature: not 64 bytes"}; @@ -582,7 +588,9 @@ namespace llarp throw std::runtime_error{ "Failed to verify signature for fetch RouterIDs response."}; }); + std::vector router_ids; + for (const auto& s : router_id_strings) { if (s.size() != RouterID::SIZE) @@ -592,6 +600,7 @@ namespace llarp } router_ids.emplace_back(s.data()); } + node_db->ingest_router_ids(edge, std::move(router_ids)); return; } @@ -599,7 +608,7 @@ namespace llarp { log::info(link_cat, "Error handling fetch RouterIDs response: {}", e.what()); } - node_db->ingest_router_ids(edge, {}); // empty response == failure + node_db->ingest_router_ids(edge); // empty response == failure }); } diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 899b25af4..cfa4b3c6d 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -233,7 +233,7 @@ namespace llarp handle_fetch_rcs(oxen::quic::message m); void - fetch_router_ids(const RouterID& source); + fetch_router_ids(const RouterID& source, std::function func = nullptr); void handle_fetch_router_ids(oxen::quic::message m); diff --git a/llarp/messages/dht.hpp b/llarp/messages/dht.hpp index 2a0e38805..2da262f3a 100644 --- a/llarp/messages/dht.hpp +++ b/llarp/messages/dht.hpp @@ -34,6 +34,7 @@ namespace llarp { inline auto NOT_FOUND = "NOT FOUND"sv; + // NOT USED inline static std::string serialize(dht::Key_t name_hash) { diff --git a/llarp/messages/rc.hpp b/llarp/messages/rc.hpp index d9eb2ab82..633b540d2 100644 --- a/llarp/messages/rc.hpp +++ b/llarp/messages/rc.hpp @@ -4,7 +4,8 @@ namespace llarp::RCFetchMessage { - inline constexpr auto INVALID_REQUEST = "Invalid relay ID requested."sv; + inline const auto INVALID_REQUEST = + messages::serialize_response({{messages::STATUS_KEY, "Invalid relay ID requested"}}); inline static std::string serialize(std::chrono::system_clock::time_point since, const std::vector& explicit_ids) diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index 7861b0041..15159f7d6 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -48,24 +48,24 @@ namespace llarp constexpr auto FlushInterval = 5min; NodeDB::NodeDB(fs::path root, std::function)> diskCaller, Router* r) - : router{*r} - , m_Root{std::move(root)} - , disk(std::move(diskCaller)) - , m_NextFlushAt{time_now_ms() + FlushInterval} + : _router{*r} + , _root{std::move(root)} + , _disk(std::move(diskCaller)) + , _next_flush_time{time_now_ms() + FlushInterval} { - EnsureSkiplist(m_Root); + EnsureSkiplist(_root); } void NodeDB::Tick(llarp_time_t now) { - if (m_NextFlushAt == 0s) + if (_next_flush_time == 0s) return; - if (now > m_NextFlushAt) + if (now > _next_flush_time) { - router.loop()->call([this]() { - m_NextFlushAt += FlushInterval; + _router.loop()->call([this]() { + _next_flush_time += FlushInterval; // make copy of all rcs std::vector copy; @@ -74,7 +74,7 @@ namespace llarp // flush them to disk in one big job // TODO: split this up? idk maybe some day... - disk([this, data = std::move(copy)]() { + _disk([this, data = std::move(copy)]() { for (const auto& rc : data) rc.write(get_path_by_pubkey(rc.router_id())); }); @@ -93,13 +93,13 @@ namespace llarp skiplistDir += hexString[0]; fname += RC_FILE_EXT; - return m_Root / skiplistDir / fname; + return _root / skiplistDir / fname; } bool NodeDB::want_rc(const RouterID& rid) const { - if (not router.is_service_node()) + if (not _router.is_service_node()) return true; return registered_routers.count(rid); } @@ -114,13 +114,31 @@ namespace llarp } } + bool + NodeDB::rotate_startup_rc_source() + { + if (client_known_routers.size() < 13) + { + // do something here + return false; + } + + RouterID temp = rc_fetch_source; + + while (temp == rc_fetch_source) + std::sample(client_known_routers.begin(), client_known_routers.end(), &temp, 1, csrng); + + rc_fetch_source = std::move(temp); + return true; + } + /// 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(); + 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) @@ -131,7 +149,7 @@ namespace llarp 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); + _router.link_manager().get_random_connected(new_source); if (conn_count == 1) { // if we only have one connection, it must be current rc fetch source @@ -149,8 +167,8 @@ namespace llarp } // 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); @@ -162,7 +180,7 @@ namespace llarp // 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); + _router.link_manager().get_random_connected(new_source); } rc_fetch_source = new_source.router_id(); } @@ -209,20 +227,72 @@ namespace llarp } } + void + NodeDB::fetch_initial() + { + int num_failures = 0; + + [[maybe_unused]] + bool use_bootstrap = false; + + RouterID fetch_src; + + // NodeDB::load_from_disk is called in Router::Run before any calls to Router::Tick are + // made, which trigger this function call. As a result, client_known_routers should be + // populated (if there was anything to populate it with) + auto num_known = client_known_routers.size(); + + if (num_known >= MIN_ACTIVE_RIDS) + { + std::sample(client_known_routers.begin(), client_known_routers.end(), &fetch_src, 1, csrng); + } + else + { + // DEFAULT TO BOOTSTRAP ROUTERS HERE + use_bootstrap = true; + log::debug( + logcat, + "Insufficient known active RID's to fetch ({}/{}); defaulting to bootstrap", + num_known, + MIN_ACTIVE_RIDS); + + assert(not bootstraps.empty()); + fetch_src = bootstraps.begin()->first; + } + + while (num_failures < MAX_FETCH_ATTEMPTS) + { + + + + } + + router_id_fetch_in_progress = true; + router_id_response_count = 0; + router_id_fetch_responses.clear(); + } + + bool + NodeDB::fetch_initial_rcs(const RouterID& src) + { + (void)src; + return true; + } + void NodeDB::fetch_rcs() { std::vector needed; - const auto now = - std::chrono::time_point_cast(std::chrono::system_clock::now()); + const auto now = time_point_now(); + for (const auto& [rid, rc] : known_rcs) { if (now - rc.timestamp() > RouterContact::OUTDATED_AGE) needed.push_back(rid); } - router.link_manager().fetch_rcs( + _router.link_manager().fetch_rcs( rc_fetch_source, last_rc_update_relay_timestamp, std::move(needed)); } @@ -231,6 +301,7 @@ namespace llarp { if (router_id_fetch_in_progress) return; + if (router_id_fetch_sources.empty()) select_router_id_sources(); @@ -244,8 +315,9 @@ namespace llarp router_id_fetch_in_progress = true; router_id_response_count = 0; router_id_fetch_responses.clear(); + for (const auto& rid : router_id_fetch_sources) - router.link_manager().fetch_router_ids(rid); + _router.link_manager().fetch_router_ids(rid); } void @@ -326,7 +398,7 @@ namespace llarp return false; } - if (not router.is_service_node()) + if (not _router.is_service_node()) return true; return router_whitelist.count(remote) or router_greylist.count(remote); @@ -343,7 +415,7 @@ namespace llarp void NodeDB::load_from_disk() { - if (m_Root.empty()) + if (_root.empty()) return; std::set purge; @@ -356,7 +428,7 @@ namespace llarp continue; std::string p; p += ch; - fs::path sub = m_Root / p; + fs::path sub = _root / p; llarp::util::IterDir(sub, [&](const fs::path& f) -> bool { // skip files that are not suffixed with .signed @@ -379,11 +451,13 @@ namespace llarp return true; } - known_rcs.emplace(rc.router_id(), rc); + const auto& rid = rc.router_id(); + + known_rcs.emplace(rid, rc); // TODO: the list of relays should be maintained and stored separately from // the RCs, as we keep older RCs around in case we go offline and need to // bootstrap, but they shouldn't be in the "good relays" list. - client_known_routers.insert(rc.router_id()); + client_known_routers.insert(rid); return true; }); @@ -401,10 +475,10 @@ namespace llarp void NodeDB::save_to_disk() const { - if (m_Root.empty()) + if (_root.empty()) return; - router.loop()->call([this]() { + _router.loop()->call([this]() { for (const auto& item : known_rcs) item.second.write(get_path_by_pubkey(item.first)); }); @@ -430,7 +504,7 @@ namespace llarp void NodeDB::remove_router(RouterID pk) { - router.loop()->call([this, pk]() { + _router.loop()->call([this, pk]() { known_rcs.erase(pk); remove_many_from_disk_async({pk}); }); @@ -439,9 +513,10 @@ namespace llarp void NodeDB::remove_stale_rcs() { - auto cutoff_time = - std::chrono::time_point_cast(std::chrono::system_clock::now()); - cutoff_time -= router.is_service_node() ? RouterContact::OUTDATED_AGE : RouterContact::LIFETIME; + auto cutoff_time = time_point_now(); + + cutoff_time -= + _router.is_service_node() ? RouterContact::OUTDATED_AGE : RouterContact::LIFETIME; for (auto itr = known_rcs.begin(); itr != known_rcs.end();) { if (cutoff_time > itr->second.timestamp()) @@ -469,7 +544,7 @@ namespace llarp size_t NodeDB::num_loaded() const { - return router.loop()->call_get([this]() { return known_rcs.size(); }); + return _router.loop()->call_get([this]() { return known_rcs.size(); }); } bool @@ -486,7 +561,7 @@ namespace llarp void NodeDB::remove_many_from_disk_async(std::unordered_set remove) const { - if (m_Root.empty()) + if (_root.empty()) return; // build file list std::set files; @@ -495,7 +570,7 @@ namespace llarp files.emplace(get_path_by_pubkey(std::move(id))); } // remove them from the disk via the diskio thread - disk([files]() { + _disk([files]() { for (auto fpath : files) fs::remove(fpath); }); @@ -504,7 +579,7 @@ namespace llarp RemoteRC NodeDB::find_closest_to(llarp::dht::Key_t location) const { - return router.loop()->call_get([this, location]() -> RemoteRC { + return _router.loop()->call_get([this, location]() -> RemoteRC { RemoteRC rc; const llarp::dht::XorMetric compare(location); @@ -524,7 +599,7 @@ namespace llarp std::vector NodeDB::find_many_closest_to(llarp::dht::Key_t location, uint32_t numRouters) const { - return router.loop()->call_get([this, location, numRouters]() -> std::vector { + return _router.loop()->call_get([this, location, numRouters]() -> std::vector { std::vector all; all.reserve(known_rcs.size()); diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index f4c3b629d..fc396f4ed 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -22,15 +22,18 @@ namespace llarp { struct Router; + inline constexpr size_t MIN_ACTIVE_RIDS{24}; + inline constexpr int MAX_FETCH_ATTEMPTS{10}; + class NodeDB { std::unordered_map known_rcs; - Router& router; - const fs::path m_Root; - const std::function)> disk; + Router& _router; + const fs::path _root; + const std::function)> _disk; - llarp_time_t m_NextFlushAt; + llarp_time_t _next_flush_time; /// asynchronously remove the files for a set of rcs on disk given their public ident key void @@ -53,7 +56,7 @@ namespace llarp std::unordered_set registered_routers; std::unordered_map last_rc_update_times; - // Router list for clients + // Client list of active RouterID's std::unordered_set client_known_routers; // only ever use to specific edges as path first-hops @@ -61,9 +64,13 @@ namespace llarp // rc update info RouterID rc_fetch_source; + rc_time last_rc_update_relay_timestamp; + static constexpr auto ROUTER_ID_SOURCE_COUNT = 12; + std::unordered_set router_id_fetch_sources; + std::unordered_map> router_id_fetch_responses; // process responses once all are received (or failed/timed out) size_t router_id_response_count{0}; @@ -106,22 +113,39 @@ namespace llarp return last_rc_update_times; } - // If we receive a bad set of RCs from our current RC source relay, we consider - // that relay to be a bad source of RCs and we randomly choose a new one. - // - // When using a new RC fetch relay, we first re-fetch the full RC list and, if - // that aligns with our RouterID list, we go back to periodic updates from that relay. - // - // This will respect edge-pinning and attempt to use a relay we already have - // a connection with. + /// If we receive a bad set of RCs from our current RC source relay, we consider + /// that relay to be a bad source of RCs and we randomly choose a new one. + /// + /// When using a new RC fetch relay, we first re-fetch the full RC list and, if + /// that aligns with our RouterID list, we go back to periodic updates from that relay. + /// + /// This will respect edge-pinning and attempt to use a relay we already have + /// a connection with. void rotate_rc_source(); + /// This function is called during startup and initial fetching. When a lokinet client + /// instance performs its initial RC/RID fetching, it may need to randomly select a + /// node from its list of stale RC's to relay its requests. If there is a failure in + /// mediating these request, the client will randomly select another RC source + /// + /// Returns: + /// true - a new startup RC source was selected + /// false - a new startup RC source was NOT selected + bool + rotate_startup_rc_source(); + void ingest_rcs(RouterID source, std::vector rcs, rc_time timestamp); void - ingest_router_ids(RouterID source, std::vector ids); + ingest_router_ids(RouterID source, std::vector ids = {}); + + void + fetch_initial(); + + bool + fetch_initial_rcs(const RouterID& src); void fetch_rcs(); @@ -216,7 +240,7 @@ namespace llarp std::optional GetRandom(Filter visit) const { - return router.loop()->call_get([visit]() -> std::optional { + return _router.loop()->call_get([visit]() -> std::optional { std::vector known_rcs; for (const auto& entry : known_rcs) known_rcs.push_back(entry); @@ -238,7 +262,7 @@ namespace llarp void VisitAll(Visit visit) const { - router.loop()->call([this, visit]() { + _router.loop()->call([this, visit]() { for (const auto& item : known_rcs) visit(item.second); }); @@ -253,7 +277,7 @@ namespace llarp void RemoveIf(Filter visit) { - router.loop()->call([this, visit]() { + _router.loop()->call([this, visit]() { std::unordered_set removed; auto itr = known_rcs.begin(); while (itr != known_rcs.end()) @@ -280,18 +304,12 @@ namespace llarp /// put (or replace) the RC if we consider it valid (want_rc). returns true if put. bool - put_rc( - RemoteRC rc, - rc_time now = - std::chrono::time_point_cast(std::chrono::system_clock::now())); + put_rc(RemoteRC rc, rc_time now = time_point_now()); /// if we consider it valid (want_rc), /// put this rc into the cache if it is not there or is newer than the one there already /// returns true if the rc was inserted bool - put_rc_if_newer( - RemoteRC rc, - rc_time now = - std::chrono::time_point_cast(std::chrono::system_clock::now())); + put_rc_if_newer(RemoteRC rc, rc_time now = time_point_now()); }; } // namespace llarp diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 7a23a3748..da98cf31b 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -352,12 +352,14 @@ namespace llarp // Backwards compat: before 0.9.10 we used `type=file` with `file=|-|stdout` for print mode auto log_type = conf.logging.type; + if (log_type == log::Type::File && (conf.logging.file == "stdout" || conf.logging.file == "-" || conf.logging.file.empty())) log_type = log::Type::Print; if (log::get_level_default() != log::Level::off) log::reset_level(conf.logging.level); + log::clear_sinks(); log::add_sink(log_type, log_type == log::Type::System ? "lokinet" : conf.logging.file); @@ -524,6 +526,7 @@ namespace llarp { // Set netid before anything else log::debug(logcat, "Network ID set to {}", conf.router.net_id); + if (!conf.router.net_id.empty() && strcmp(conf.router.net_id.c_str(), llarp::LOKINET_DEFAULT_NETID) != 0) { @@ -534,8 +537,8 @@ namespace llarp "' which does not equal '", llarp::LOKINET_DEFAULT_NETID, "' you will run as a different network, good luck " - "and don't forget: something something MUH traffic " - "shape correlation !!!!"); + "and don't forget: something something traffic shape " + "correlation!!"); } // Router config @@ -575,16 +578,20 @@ namespace llarp if (not networkConfig.strict_connect.empty()) { const auto& val = networkConfig.strict_connect; + if (is_service_node()) throw std::runtime_error("cannot use strict-connect option as service node"); + if (val.size() < 2) throw std::runtime_error( "Must specify more than one strict-connect router if using strict-connect"); + strictConnectPubkeys.insert(val.begin(), val.end()); log::debug(logcat, "{} strict-connect routers configured", val.size()); } std::vector configRouters = conf.connect.routers; + configRouters.insert( configRouters.end(), conf.bootstrap.files.begin(), conf.bootstrap.files.end()); @@ -595,9 +602,7 @@ namespace llarp if (configRouters.empty() and conf.bootstrap.routers.empty()) { if (fs::exists(defaultBootstrapFile)) - { configRouters.push_back(defaultBootstrapFile); - } } bootstrap_rc_list.clear(); @@ -624,6 +629,7 @@ namespace llarp "No bootstrap routers were loaded. The default bootstrap file {} does not exist, and " "loading fallback bootstrap RCs failed.", defaultBootstrapFile); + throw std::runtime_error("No bootstrap nodes available."); } } @@ -656,11 +662,11 @@ namespace llarp // Init components after relevant config settings loaded _link_manager.init(); - // FIXME: kludge for now, will be part of larger cleanup effort. + // TODO: RC refactor here if (_is_service_node) - InitInboundLinks(); + init_inbounds(); else - InitOutboundLinks(); + init_outbounds(); // profiling _profile_file = conf.router.data_dir / "profiles.dat"; @@ -819,36 +825,51 @@ namespace llarp // (relay-only) if we have fetched the relay list from oxend and // we are registered and funded, we want to gossip our RC periodically auto now_timepoint = std::chrono::system_clock::time_point(now); - if (is_snode and appears_funded() and (now_timepoint > next_rc_gossip)) - { - log::info(logcat, "regenerating and gossiping RC"); - router_contact.resign(); - save_rc(); - auto view = router_contact.view(); - _link_manager.gossip_rc( - pubkey(), std::string{reinterpret_cast(view.data()), view.size()}); - last_rc_gossip = now_timepoint; - // 1min to 5min before "stale time" is next gossip time - auto random_delta = - std::chrono::seconds{std::uniform_int_distribution{60, 300}(llarp::csrng)}; - next_rc_gossip = now_timepoint + RouterContact::STALE_AGE - random_delta; - } - - if (not is_snode) + if (is_snode) { - // (client-only) periodically fetch updated RCs - if (now_timepoint - last_rc_fetch > RC_UPDATE_INTERVAL) + if (appears_funded() and now_timepoint > next_rc_gossip) { - node_db()->fetch_rcs(); - last_rc_fetch = now_timepoint; + log::info(logcat, "regenerating and gossiping RC"); + + router_contact.resign(); + save_rc(); + + auto view = router_contact.view(); + + _link_manager.gossip_rc( + pubkey(), std::string{reinterpret_cast(view.data()), view.size()}); + + last_rc_gossip = now_timepoint; + + // 1min to 5min before "stale time" is next gossip time + auto random_delta = + std::chrono::seconds{std::uniform_int_distribution{60, 300}(llarp::csrng)}; + + next_rc_gossip = now_timepoint + RouterContact::STALE_AGE - random_delta; } - - // (client-only) periodically fetch updated RouterID list - if (now_timepoint - last_routerid_fetch > ROUTERID_UPDATE_INTERVAL) + } + else + { + if (needs_initial_fetch) { - node_db()->fetch_router_ids(); - last_routerid_fetch = now_timepoint; + node_db()->fetch_initial(); + } + else + { + // (client-only) periodically fetch updated RCs + if (now_timepoint - last_rc_fetch > RC_UPDATE_INTERVAL) + { + node_db()->fetch_rcs(); + last_rc_fetch = now_timepoint; + } + + // (client-only) periodically fetch updated RouterID list + if (now_timepoint - last_routerid_fetch > ROUTERID_UPDATE_INTERVAL) + { + node_db()->fetch_router_ids(); + last_routerid_fetch = now_timepoint; + } } } @@ -1074,8 +1095,11 @@ namespace llarp log::info(logcat, "Router populated NodeDB with {} routers", _node_db->num_loaded()); _loop->call_every(ROUTER_TICK_INTERVAL, weak_from_this(), [this] { Tick(); }); + _route_poker->start(); + is_running.store(true); + _started_at = now(); if (is_service_node()) @@ -1321,7 +1345,7 @@ namespace llarp } void - Router::InitInboundLinks() + Router::init_inbounds() { // auto addrs = _config->links.InboundListenAddrs; // if (is_service_node and addrs.empty()) @@ -1370,7 +1394,7 @@ namespace llarp } void - Router::InitOutboundLinks() + Router::init_outbounds() { // auto addrs = config()->links.OutboundLinks; // if (addrs.empty()) diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index cdd6da7ab..90a8a24b4 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -37,15 +37,6 @@ #include #include -/* - TONUKE: - - hidden_service_context - - TODO: - - router should hold DHT nodes container? in either a class or a map - - -*/ - namespace llarp { /// number of routers to publish to @@ -127,15 +118,14 @@ namespace llarp Profiling _router_profiling; fs::path _profile_file; LinkManager _link_manager{*this}; + + bool needs_initial_fetch{true}; + std::chrono::system_clock::time_point last_rc_gossip{ std::chrono::system_clock::time_point::min()}; - std::chrono::system_clock::time_point next_rc_gossip{ - std::chrono::system_clock::time_point::min()}; - - std::chrono::system_clock::time_point last_rc_fetch{ - std::chrono::system_clock::time_point::min()}; - std::chrono::system_clock::time_point last_routerid_fetch{ - std::chrono::system_clock::time_point::min()}; + std::chrono::system_clock::time_point next_rc_gossip{last_rc_gossip}; + std::chrono::system_clock::time_point last_rc_fetch{last_rc_gossip}; + std::chrono::system_clock::time_point last_routerid_fetch{last_rc_gossip}; // should we be sending padded messages every interval? bool send_padding = false; @@ -369,10 +359,10 @@ namespace llarp status_line(); void - InitInboundLinks(); + init_inbounds(); void - InitOutboundLinks(); + init_outbounds(); std::optional GetRandomGoodRouter(); diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index ab13328ca..0cd402802 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -6,7 +6,6 @@ #include "util/bencode.hpp" #include "util/buffer.hpp" #include "util/file.hpp" -#include "util/time.hpp" #include diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index b65aa2c76..c7a04cd89 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -21,8 +22,6 @@ namespace llarp { static auto logcat = log::Cat("RC"); - using rc_time = std::chrono::time_point; - static inline constexpr size_t NETID_SIZE{8}; /// On the wire we encode the data as a dict containing: @@ -298,8 +297,7 @@ namespace llarp void set_systime_timestamp() { - set_timestamp( - std::chrono::time_point_cast(std::chrono::system_clock::now())); + set_timestamp(time_point_now()); } }; diff --git a/llarp/router_contact_remote.cpp b/llarp/router_contact_remote.cpp index 0d7eeb05b..8e8188052 100644 --- a/llarp/router_contact_remote.cpp +++ b/llarp/router_contact_remote.cpp @@ -40,8 +40,9 @@ namespace llarp } catch (const std::exception& e) { - log::warning(logcat, "Failed to parse RemoteRC: {}", e.what()); - throw; + auto err = "Exception caught parsing RemoteRC: {}"_format(e.what()); + log::warning(logcat, err); + throw std::runtime_error{err}; } } diff --git a/llarp/util/time.cpp b/llarp/util/time.cpp index af36a55dd..39fc6e268 100644 --- a/llarp/util/time.cpp +++ b/llarp/util/time.cpp @@ -34,6 +34,12 @@ namespace llarp std::chrono::steady_clock::now() - started_at_steady); } + rc_time + time_point_now() + { + return std::chrono::time_point_cast(std::chrono::system_clock::now()); + } + Duration_t time_now_ms() { diff --git a/llarp/util/time.hpp b/llarp/util/time.hpp index 2a312090d..bba3cf636 100644 --- a/llarp/util/time.hpp +++ b/llarp/util/time.hpp @@ -12,6 +12,11 @@ using namespace std::chrono_literals; namespace llarp { + using rc_time = std::chrono::time_point; + + rc_time + time_point_now(); + /// get time right now as milliseconds, this is monotonic Duration_t time_now_ms();