1
1
Fork 0
mirror of https://github.com/oxen-io/lokinet synced 2023-12-14 06:53:00 +01:00

come on already work already

This commit is contained in:
dr7ana 2023-12-12 07:45:38 -08:00
parent 94f307283f
commit b69f754599
9 changed files with 146 additions and 117 deletions

View file

@ -26,7 +26,7 @@ namespace llarp
}
bool
BootstrapList::contains(const RouterID& rid)
BootstrapList::contains(const RouterID& rid) const
{
for (const auto& it : *this)
{
@ -38,7 +38,7 @@ namespace llarp
}
bool
BootstrapList::contains(const RemoteRC& rc)
BootstrapList::contains(const RemoteRC& rc) const
{
return count(rc);
}

View file

@ -12,7 +12,7 @@ namespace llarp
{
struct BootstrapList final : public std::set<RemoteRC>
{
std::set<RemoteRC>::iterator _curr;
std::set<RemoteRC>::iterator _curr = begin();
const RemoteRC&
current()
@ -30,7 +30,7 @@ namespace llarp
read_from_file(const fs::path& fpath);
bool
contains(const RouterID& rid);
contains(const RouterID& rid) const;
// returns a reference to the next index and a boolean that equals true if
// this is the front of the set
@ -46,7 +46,7 @@ namespace llarp
}
bool
contains(const RemoteRC& rc);
contains(const RemoteRC& rc) const;
void
randomize()

View file

@ -178,12 +178,13 @@ namespace llarp
bool result = false;
RouterID other{key.data()};
if (auto itr = rids_pending_verification.find(other); itr != rids_pending_verification.end())
{
verified_rids[other] = itr->second;
rids_pending_verification.erase(itr);
result = true;
}
// if (auto itr = rids_pending_verification.find(other); itr !=
// rids_pending_verification.end())
// {
// verified_rids[other] = itr->second;
// rids_pending_verification.erase(itr);
// result = true;
// }
if (_router.node_db()->has_rc(other))
result = true;
@ -254,7 +255,8 @@ namespace llarp
if (func)
{
func = [this, f = std::move(func)](oxen::quic::message m) mutable {
_router.loop()->call([func = std::move(f), msg = std::move(m)]() mutable { func(std::move(msg)); });
_router.loop()->call(
[func = std::move(f), msg = std::move(m)]() mutable { func(std::move(msg)); });
};
}
@ -358,12 +360,12 @@ namespace llarp
const auto& remote_addr = rc.addr();
const auto& rid = rc.router_id();
rids_pending_verification[rid] = rc;
// rids_pending_verification[rid] = rc;
// TODO: confirm remote end is using the expected pubkey (RouterID).
// TODO: ALPN for "client" vs "relay" (could just be set on endpoint creation)
if (auto rv = ep.establish_connection(
oxen::quic::RemoteAddress{rc.router_id().ToView(), remote_addr},
oxen::quic::RemoteAddress{rid.ToView(), remote_addr},
rc,
std::move(on_open),
std::move(on_close));
@ -391,6 +393,7 @@ namespace llarp
logcat, "BTRequestStream closed unexpectedly (ec:{}); closing connection...", error_code);
s.conn.close_connection(error_code);
});
register_commands(control_stream);
itr->second = std::make_shared<link::Connection>(ci.shared_from_this(), control_stream, rc);
log::critical(logcat, "Successfully configured inbound connection fom {}; storing RC...", rid);
@ -460,9 +463,10 @@ namespace llarp
{
const auto& rid = c_itr->second;
if (auto maybe = rids_pending_verification.find(rid);
maybe != rids_pending_verification.end())
rids_pending_verification.erase(maybe);
// if (auto maybe = rids_pending_verification.find(rid);
// maybe != rids_pending_verification.end())
// rids_pending_verification.erase(maybe);
// in case this didn't clear earlier, do it now
if (auto p_itr = pending_conn_msg_queue.find(rid); p_itr != pending_conn_msg_queue.end())
pending_conn_msg_queue.erase(p_itr);
@ -665,14 +669,14 @@ namespace llarp
return;
}
node_db->put_rc(remote);
auto is_seed = _router.is_bootstrap_seed();
auto& bootstraps = node_db->bootstrap_list();
auto count = bootstraps.size();
auto& src = is_seed ? node_db->bootstrap_seeds() : node_db->get_known_rcs();
auto count = src.size();
if (count == 0)
{
log::error(logcat, "No bootstraps locally to send!");
log::error(logcat, "No {} locally to send!", is_seed ? "bootstrap seeds" : "known RCs");
m.respond(messages::ERROR_RESPONSE, true);
return;
}
@ -685,18 +689,21 @@ namespace llarp
{
auto sublist = btdp.append_list("rcs");
while (i < quantity)
for (const auto& rc : src)
{
auto& next_rc = bootstraps.next();
if (not rc.is_expired(now))
sublist.append_encoded(rc.view());
if (next_rc.is_expired(now))
continue;
sublist.append_encoded(next_rc.view());
++i;
if (++i >= quantity)
break;
}
}
if (is_seed)
node_db->bootstrap_seeds().insert(remote);
else
node_db->put_rc(remote);
m.respond(std::move(btdp).str());
}

View file

@ -181,7 +181,7 @@ namespace llarp
// when establishing a connection, the rid of the remote is placed here to be cross-
// checked by the tls verification callback
std::map<RouterID, RemoteRC> rids_pending_verification;
// in the interim of verifying an inbound connection and the creation of its link::Connection
// in the interim of verifying an outbound connection and the creation of its link::Connection
// object, we store the rid and rc here
std::map<RouterID, RemoteRC> verified_rids;
@ -354,18 +354,9 @@ namespace llarp
{"find_name"sv, &LinkManager::handle_find_name},
{"publish_intro"sv, &LinkManager::handle_publish_intro},
{"find_intro"sv, &LinkManager::handle_find_intro}};
/*
{"path_confirm", &LinkManager::handle_path_confirm},
{"path_latency", &LinkManager::handle_path_latency},
{"update_exit", &LinkManager::handle_update_exit},
{"obtain_exit", &LinkManager::handle_obtain_exit},
{"close_exit", &LinkManager::handle_close_exit},
{"convo_intro", &LinkManager::handle_convo_intro}};
*/
// these requests are direct, i.e. not over a path;
// the rest are relay->relay
// TODO: new RC fetch endpoint (which will be both client->relay and relay->relay)
std::unordered_map<
std::string_view,
void (LinkManager::*)(std::string_view body, std::function<void(std::string)> respond)>
@ -431,6 +422,7 @@ namespace llarp
s.conn.close_connection(error_code);
});
link_manager.register_commands(control_stream);
itr->second = std::make_shared<link::Connection>(conn_interface, control_stream, rc);
return true;

View file

@ -192,15 +192,10 @@ namespace llarp
}
void
NodeDB::set_bootstrap_routers(std::unique_ptr<BootstrapList> from_router)
NodeDB::set_bootstrap_routers(BootstrapList from_router)
{
// TODO: if this needs to be called more than once (ex: drastic failures), then
// change this assert to a bootstraps.clear() call
if (_bootstraps)
assert(_bootstraps->empty());
_bootstraps = std::move(from_router);
_bootstraps->randomize();
_bootstraps.merge(from_router);
_bootstraps.randomize();
}
bool
@ -610,6 +605,8 @@ namespace llarp
if (_router.is_service_node())
{
_needs_rebootstrap = false;
_needs_initial_fetch = false;
_using_bootstrap_fallback = false;
fail_sources.clear();
fetch_failures = 0;
return;
@ -627,6 +624,7 @@ namespace llarp
_router.last_rid_fetch = llarp::time_point_now();
fetch_counters.clear();
_needs_rebootstrap = false;
_using_bootstrap_fallback = false;
if (initial)
{
@ -638,6 +636,7 @@ namespace llarp
void
NodeDB::fallback_to_bootstrap()
{
log::critical(logcat, "{} called", __PRETTY_FUNCTION__);
auto at_max_failures = bootstrap_attempts >= MAX_BOOTSTRAP_FETCH_ATTEMPTS;
// base case: we have failed to query all bootstraps, or we received a sample of
@ -660,7 +659,7 @@ namespace llarp
return;
}
auto rc = _bootstraps->next();
auto rc = (_using_bootstrap_fallback) ? _bootstraps.next() : _bootstraps.current();
fetch_source = rc.router_id();
}
@ -669,8 +668,10 @@ namespace llarp
_needs_rebootstrap = false;
++bootstrap_attempts;
log::critical(logcat, "Dispatching BootstrapRC fetch request to {}", _bootstraps.current().view());
_router.link_manager().fetch_bootstrap_rcs(
_bootstraps->current(),
_bootstraps.current(),
BootstrapFetchMessage::serialize(_router.router_contact, BOOTSTRAP_SOURCE_COUNT),
[this](oxen::quic::message m) mutable {
if (not m)
@ -723,7 +724,7 @@ namespace llarp
if (rids.size() == BOOTSTRAP_SOURCE_COUNT)
{
known_rids.swap(rids);
known_rids.merge(rids);
fetch_initial();
}
else
@ -745,6 +746,7 @@ namespace llarp
NodeDB::bootstrap_cooldown()
{
_needs_rebootstrap = true;
_using_bootstrap_fallback = false;
_router.next_bootstrap_attempt = llarp::time_point_now() + BOOTSTRAP_COOLDOWN;
}
@ -792,7 +794,7 @@ namespace llarp
NodeDB::is_connection_allowed(const RouterID& remote) const
{
if (_pinned_edges.size() && _pinned_edges.count(remote) == 0
&& not _bootstraps->contains(remote))
&& not _bootstraps.contains(remote))
return false;
if (not _router.is_service_node())
@ -810,6 +812,20 @@ namespace llarp
return true;
}
void
NodeDB::store_bootstraps()
{
if (_bootstraps.empty())
return;
for (const auto& rc : _bootstraps)
{
put_rc(rc);
}
log::critical(logcat, "NodeDB populated with {} routers", num_rcs());
}
void
NodeDB::load_from_disk()
{

View file

@ -121,6 +121,9 @@ namespace llarp
the unknown_rids container
- rc_lookup: holds all the same rc's as known_rcs, but can be used to look them up by
their rid
- bootstrap_seeds: if we are the seed node, we insert the rc's of bootstrap fetch requests
senders into this container to "introduce" them to each other
- _bootstraps: the standard container for bootstrap RemoteRCs
*/
std::set<RouterID> known_rids;
std::set<Unconfirmed<RouterID>> unconfirmed_rids;
@ -130,6 +133,9 @@ namespace llarp
std::map<RouterID, const RemoteRC&> rc_lookup;
std::set<RemoteRC> _bootstrap_seeds;
BootstrapList _bootstraps{};
/** RouterID lists // TODO: get rid of all these, replace with better decom/not staked sets
- white: active routers
- gray: fully funded, but decommissioned routers
@ -178,8 +184,6 @@ namespace llarp
fs::path
get_path_by_pubkey(RouterID pk) const;
std::unique_ptr<BootstrapList> _bootstraps{};
public:
explicit NodeDB(
fs::path rootdir, std::function<void(std::function<void()>)> diskCaller, Router* r);
@ -214,6 +218,9 @@ namespace llarp
return _needs_rebootstrap;
}
void
ingest_bootstrap_seed();
bool
ingest_fetched_rcs(std::set<RemoteRC> rcs, rc_time timestamp);
@ -299,32 +306,47 @@ namespace llarp
return _pinned_edges;
}
void
store_bootstraps();
size_t
num_bootstraps() const
{
return _bootstraps ? _bootstraps->size() : 0;
return _bootstraps.size();
}
bool
has_bootstraps() const
{
return _bootstraps ? _bootstraps->empty() : false;
return _bootstraps.empty();
}
const BootstrapList&
bootstrap_list() const
{
return *_bootstraps;
return _bootstraps;
}
BootstrapList&
bootstrap_list()
{
return *_bootstraps;
return _bootstraps;
}
const std::set<RemoteRC>&
bootstrap_seeds() const
{
return _bootstrap_seeds;
}
std::set<RemoteRC>&
bootstrap_seeds()
{
return _bootstrap_seeds;
}
void
set_bootstrap_routers(std::unique_ptr<BootstrapList> from_router);
set_bootstrap_routers(BootstrapList from_router);
const std::set<RouterID>&
whitelist() const

View file

@ -631,17 +631,18 @@ namespace llarp
configRouters.push_back(defaultBootstrapFile);
}
auto _bootstrap_rc_list = std::make_unique<BootstrapList>();
BootstrapList _bootstrap_rc_list;
auto clear_bad_rcs = [&]() mutable {
log::critical(logcat, "Clearing bad RCs...");
// in case someone has an old bootstrap file and is trying to use a bootstrap
// that no longer exists
for (auto it = _bootstrap_rc_list->begin(); it != _bootstrap_rc_list->end();)
for (auto it = _bootstrap_rc_list.begin(); it != _bootstrap_rc_list.end();)
{
if (it->is_obsolete_bootstrap())
log::warning(logcat, "ignoring obsolete bootstrap RC: {}", it->router_id());
log::critical(logcat, "ignoring obsolete bootstrap RC: {}", it->router_id());
else if (not it->verify())
log::warning(logcat, "ignoring invalid bootstrap RC: {}", it->router_id());
log::critical(logcat, "ignoring invalid bootstrap RC: {}", it->router_id());
else
{
++it;
@ -649,29 +650,27 @@ namespace llarp
}
// we are in one of the above error cases that we warned about:
it = _bootstrap_rc_list->erase(it);
it = _bootstrap_rc_list.erase(it);
}
};
for (const auto& router : configRouters)
{
log::debug(logcat, "Loading bootstrap router list from {}", defaultBootstrapFile);
_bootstrap_rc_list->read_from_file(router);
_bootstrap_rc_list.read_from_file(router);
}
for (const auto& rc : conf.bootstrap.routers)
{
_bootstrap_rc_list->emplace(rc);
_bootstrap_rc_list.emplace(rc);
}
clear_bad_rcs();
_bootstrap_seed = conf.bootstrap.seednode;
if (_bootstrap_seed)
log::critical(logcat, "We are a bootstrap seed node!");
if (_bootstrap_rc_list->empty() and not _bootstrap_seed)
if (_bootstrap_rc_list.empty() and not _bootstrap_seed)
{
log::warning(logcat, "Warning: bootstrap list is empty and we are not a seed node");
@ -679,10 +678,10 @@ namespace llarp
if (auto itr = fallbacks.find(RouterContact::ACTIVE_NETID); itr != fallbacks.end())
{
_bootstrap_rc_list->merge(itr->second);
_bootstrap_rc_list.merge(itr->second);
}
if (_bootstrap_rc_list->empty())
if (_bootstrap_rc_list.empty())
{
// empty after trying fallback, if set
log::error(
@ -694,12 +693,12 @@ namespace llarp
throw std::runtime_error("No bootstrap nodes available.");
}
log::info(
logcat, "Loaded {} default fallback bootstrap routers!", _bootstrap_rc_list->size());
clear_bad_rcs();
log::critical(
logcat, "Loaded {} default fallback bootstrap routers!", _bootstrap_rc_list.size());
}
log::critical(logcat, "We have {} bootstrap routers!", _bootstrap_rc_list->size());
clear_bad_rcs();
log::critical(logcat, "We have {} bootstrap routers!", _bootstrap_rc_list.size());
node_db()->set_bootstrap_routers(std::move(_bootstrap_rc_list));
@ -1140,21 +1139,11 @@ namespace llarp
log::info(logcat, "Loading NodeDB from disk...");
_node_db->load_from_disk();
_node_db->store_bootstraps();
log::info(logcat, "Creating Introset Contacts...");
_contacts = std::make_unique<Contacts>(*this);
if (_node_db->has_bootstraps())
{
for (const auto& rc : _node_db->bootstrap_list())
{
node_db()->put_rc(rc);
log::info(logcat, "Added bootstrap node (rid: {})", rc.router_id());
}
log::info(logcat, "Router populated NodeDB with {} routers", _node_db->num_rcs());
}
_loop->call_every(ROUTER_TICK_INTERVAL, weak_from_this(), [this] { Tick(); });
_route_poker->start();
@ -1163,7 +1152,7 @@ namespace llarp
_started_at = now();
if (is_service_node())
if (is_service_node() and not _testing_disabled)
{
// do service node testing if we are in service node whitelist mode
_loop->call_every(consensus::REACHABILITY_TESTING_TIMER_INTERVAL, weak_from_this(), [this] {
@ -1225,6 +1214,7 @@ namespace llarp
}
});
}
llarp::sys::service_manager->ready();
return is_running;
}

View file

@ -17,45 +17,55 @@ namespace llarp
if (int rc_ver = data.require<uint8_t>(""); rc_ver != RC_VERSION)
throw std::runtime_error{"Invalid RC: do not know how to parse v{} RCs"_format(rc_ver)};
auto ipv4_port = data.require<std::string_view>("4");
auto addr_key = data.key();
bool addr_set = false;
if (ipv4_port.size() != 6)
throw std::runtime_error{
"Invalid RC address: expected 6-byte IPv4 IP/port, got {}"_format(ipv4_port.size())};
sockaddr_in s4;
s4.sin_family = AF_INET;
std::memcpy(&s4.sin_addr.s_addr, ipv4_port.data(), 4);
std::memcpy(&s4.sin_port, ipv4_port.data() + 4, 2);
_addr = oxen::quic::Address{&s4};
if (!_addr.is_public())
throw std::runtime_error{"Invalid RC: IPv4 address is not a publicly routable IP"};
if (auto ipv6_port = data.maybe<std::string_view>("6"))
if (addr_key == "4")
{
if (ipv6_port->size() != 18)
auto ipv4_port = data.consume<std::string_view>();
if (ipv4_port.size() != 6)
throw std::runtime_error{
"Invalid RC address: expected 18-byte IPv6 IP/port, got {}"_format(ipv6_port->size())};
"Invalid RC address: expected 6-byte IPv4 IP/port, got {}"_format(ipv4_port.size())};
sockaddr_in s4;
s4.sin_family = AF_INET;
std::memcpy(&s4.sin_addr.s_addr, ipv4_port.data(), 4);
std::memcpy(&s4.sin_port, ipv4_port.data() + 4, 2);
_addr = oxen::quic::Address{&s4};
// advance in case ipv4 and ipv6 are included
addr_key = data.key();
addr_set = true;
}
if (addr_key == "6")
{
auto ipv6_port = data.consume<std::string_view>();
if (ipv6_port.size() != 18)
throw std::runtime_error{
"Invalid RC address: expected 18-byte IPv6 IP/port, got {}"_format(ipv6_port.size())};
sockaddr_in6 s6{};
s6.sin6_family = AF_INET6;
std::memcpy(&s6.sin6_addr.s6_addr, ipv6_port->data(), 16);
std::memcpy(&s6.sin6_port, ipv6_port->data() + 16, 2);
std::memcpy(&s6.sin6_addr.s6_addr, ipv6_port.data(), 16);
std::memcpy(&s6.sin6_port, ipv6_port.data() + 16, 2);
_addr6.emplace(&s6);
if (!_addr6->is_public())
throw std::runtime_error{"Invalid RC: IPv6 address is not a publicly routable IP"};
}
else
{
_addr6.reset();
}
if (not addr_set)
throw std::runtime_error{"Invalid RC: could not discern ipv4 vs ipv6 in payload"};
auto netid = data.maybe<std::string_view>("i").value_or(llarp::LOKINET_DEFAULT_NETID);
if (netid != ACTIVE_NETID)
throw std::runtime_error{
"Invalid RC netid: expected {}, got {}; this is an RC for a different network!"_format(
@ -67,14 +77,7 @@ namespace llarp
"Invalid RC pubkey: expected 32 bytes, got {}"_format(pubkey.size())};
std::memcpy(_router_id.data(), pubkey.data(), 32);
// auto pk = data.require<std::string_view>("p");
// if (pk.size() != RouterID::SIZE)
// throw std::runtime_error{"Invalid RC: router id has invalid size {}"_format(pk.size())};
// std::memcpy(_router_id.data(), pk.data(), RouterID::SIZE);
_timestamp = rc_time{std::chrono::seconds{data.require<int64_t>("t")}};
_timestamp = rc_time{std::chrono::seconds{data.require<uint64_t>("t")}};
auto ver = data.require<ustring_view>("v");

View file

@ -16,7 +16,6 @@ namespace llarp
try
{
bt_load(btdc);
bt_verify(btdc, /*reject_expired=*/true);
}
catch (const std::exception& e)