mirror of
https://github.com/oxen-io/lokinet.git
synced 2024-11-15 12:13:24 +00:00
housekeeping and groundwork, initial commit
This commit is contained in:
parent
5ac4a9a61b
commit
07fc0246ed
@ -461,10 +461,9 @@ namespace llarp
|
||||
auto timestamp = rc_time{std::chrono::seconds{btdc.require<int64_t>("time"sv)}};
|
||||
|
||||
std::vector<RemoteRC> 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::seconds>(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<std::vector<std::string>>();
|
||||
|
||||
auto since_time = rc_time{std::chrono::seconds{btdc.require<int64_t>("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<RouterID> 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<const byte_t*>(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<void(oxen::quic::message m)> 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<std::vector<ustring>>();
|
||||
|
||||
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<RouterID> 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
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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<void(oxen::quic::message m)> func = nullptr);
|
||||
|
||||
void
|
||||
handle_fetch_router_ids(oxen::quic::message m);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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<RouterID>& explicit_ids)
|
||||
|
147
llarp/nodedb.cpp
147
llarp/nodedb.cpp
@ -48,24 +48,24 @@ namespace llarp
|
||||
constexpr auto FlushInterval = 5min;
|
||||
|
||||
NodeDB::NodeDB(fs::path root, std::function<void(std::function<void()>)> 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<RemoteRC> 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<RouterID> needed;
|
||||
|
||||
const auto now =
|
||||
std::chrono::time_point_cast<std::chrono::seconds>(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<fs::path> 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::seconds>(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<RouterID> remove) const
|
||||
{
|
||||
if (m_Root.empty())
|
||||
if (_root.empty())
|
||||
return;
|
||||
// build file list
|
||||
std::set<fs::path> 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<RemoteRC>
|
||||
NodeDB::find_many_closest_to(llarp::dht::Key_t location, uint32_t numRouters) const
|
||||
{
|
||||
return router.loop()->call_get([this, location, numRouters]() -> std::vector<RemoteRC> {
|
||||
return _router.loop()->call_get([this, location, numRouters]() -> std::vector<RemoteRC> {
|
||||
std::vector<const RemoteRC*> all;
|
||||
|
||||
all.reserve(known_rcs.size());
|
||||
|
@ -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<RouterID, RemoteRC> known_rcs;
|
||||
|
||||
Router& router;
|
||||
const fs::path m_Root;
|
||||
const std::function<void(std::function<void()>)> disk;
|
||||
Router& _router;
|
||||
const fs::path _root;
|
||||
const std::function<void(std::function<void()>)> _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<RouterID> registered_routers;
|
||||
std::unordered_map<RouterID, rc_time> last_rc_update_times;
|
||||
|
||||
// Router list for clients
|
||||
// Client list of active RouterID's
|
||||
std::unordered_set<RouterID> 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<RouterID> router_id_fetch_sources;
|
||||
|
||||
std::unordered_map<RouterID, std::vector<RouterID>> 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<RemoteRC> rcs, rc_time timestamp);
|
||||
|
||||
void
|
||||
ingest_router_ids(RouterID source, std::vector<RouterID> ids);
|
||||
ingest_router_ids(RouterID source, std::vector<RouterID> ids = {});
|
||||
|
||||
void
|
||||
fetch_initial();
|
||||
|
||||
bool
|
||||
fetch_initial_rcs(const RouterID& src);
|
||||
|
||||
void
|
||||
fetch_rcs();
|
||||
@ -216,7 +240,7 @@ namespace llarp
|
||||
std::optional<RemoteRC>
|
||||
GetRandom(Filter visit) const
|
||||
{
|
||||
return router.loop()->call_get([visit]() -> std::optional<RemoteRC> {
|
||||
return _router.loop()->call_get([visit]() -> std::optional<RemoteRC> {
|
||||
std::vector<const decltype(known_rcs)::value_type*> 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<RouterID> 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::seconds>(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::seconds>(std::chrono::system_clock::now()));
|
||||
put_rc_if_newer(RemoteRC rc, rc_time now = time_point_now());
|
||||
};
|
||||
} // namespace llarp
|
||||
|
@ -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<fs::path> 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<const char*>(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<size_t>{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<const char*>(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<size_t>{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())
|
||||
|
@ -37,15 +37,6 @@
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
/*
|
||||
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<RouterID>
|
||||
GetRandomGoodRouter();
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include "util/bencode.hpp"
|
||||
#include "util/buffer.hpp"
|
||||
#include "util/file.hpp"
|
||||
#include "util/time.hpp"
|
||||
|
||||
#include <oxenc/bt_serialize.h>
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <llarp/util/aligned.hpp>
|
||||
#include <llarp/util/bencode.hpp>
|
||||
#include <llarp/util/status.hpp>
|
||||
#include <llarp/util/time.hpp>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <oxenc/bt_producer.h>
|
||||
@ -21,8 +22,6 @@ namespace llarp
|
||||
{
|
||||
static auto logcat = log::Cat("RC");
|
||||
|
||||
using rc_time = std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>;
|
||||
|
||||
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::seconds>(std::chrono::system_clock::now()));
|
||||
set_timestamp(time_point_now());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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::seconds>(std::chrono::system_clock::now());
|
||||
}
|
||||
|
||||
Duration_t
|
||||
time_now_ms()
|
||||
{
|
||||
|
@ -12,6 +12,11 @@ using namespace std::chrono_literals;
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
using rc_time = std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>;
|
||||
|
||||
rc_time
|
||||
time_point_now();
|
||||
|
||||
/// get time right now as milliseconds, this is monotonic
|
||||
Duration_t
|
||||
time_now_ms();
|
||||
|
Loading…
Reference in New Issue
Block a user