Compare commits

...

15 Commits

Author SHA1 Message Date
dr7ana 1827ff63f1 kiiiiiick 2023-12-11 09:40:31 -08:00
dr7ana efe5fd3b5b try queueing 2023-12-11 09:17:29 -08:00
dr7ana 0bf3a3323a kick 2023-12-11 09:04:53 -08:00
dr7ana 22edd63284 libquic vbump 2023-12-11 08:35:20 -08:00
dr7ana 238cc3d0da kick 2023-12-11 08:16:13 -08:00
dr7ana 5f430a392b kick 2023-12-11 07:46:11 -08:00
dr7ana 63644d3d84 Bootstrap seed
- nodes now send their RC to the bootstrap seed on making a request
- allows the bootstrap seed to distribute RCs
2023-12-11 07:32:52 -08:00
dr7ana f2feea74ee Crit logging
- TODO: discuss authentication for nodes connecting to bootstrap seed
- crit log num connected/RC's, conn open/closed, etc
2023-12-11 03:45:23 -08:00
Jason Rhinelander 412ce44139 Update libquic 2023-12-11 03:13:39 -08:00
Jason Rhinelander daeff3ee7e Remove duplicate connection closing method
`deregister_peer` does the exact same thing as `close_connection` so
just remove it.

Also removes an unnecessary loop dispatch call (because we *have* to be
in the logic thread already to be able to touch the variables we are
touching before the dispatch).
2023-12-11 03:13:39 -08:00
Jason Rhinelander 0e6a2941bd Bump libquic 2023-12-11 03:13:39 -08:00
Jason Rhinelander b82b4c7fe6 Update libquic 2023-12-11 03:13:39 -08:00
Jason Rhinelander b3dc23e1bf Remove release motto
This doesn't really have a purpose.
2023-12-11 03:13:39 -08:00
Jason Rhinelander 30d58911fa Update logging in daemon.cpp
Some of these were wrong (trying to use formats that didn't work); this
updates them all to new-style logging.
2023-12-11 03:13:39 -08:00
dr7ana 9084d39e5a Squashed misc testnet fixes 2023-12-11 03:13:16 -08:00
20 changed files with 248 additions and 141 deletions

View File

@ -41,8 +41,6 @@ if(APPLE)
set(LOKINET_APPLE_BUILD 5) set(LOKINET_APPLE_BUILD 5)
endif() endif()
set(LOKINET_RELEASE_MOTTO "Anonymous, decentralized, IP-based overlay network" CACHE STRING "Release motto")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
set(DEFAULT_WITH_BOOTSTRAP ON) set(DEFAULT_WITH_BOOTSTRAP ON)

View File

@ -125,7 +125,7 @@ namespace
if (!GetModuleFileName(nullptr, szPath.data(), MAX_PATH)) if (!GetModuleFileName(nullptr, szPath.data(), MAX_PATH))
{ {
llarp::LogError("Cannot install service ", GetLastError()); llarp::log::error(logcat, "Cannot install service {}", GetLastError());
return; return;
} }
@ -137,7 +137,7 @@ namespace
if (nullptr == schSCManager) if (nullptr == schSCManager)
{ {
llarp::LogError("OpenSCManager failed ", GetLastError()); llarp::log::error(logcat, "OpenSCManager failed {}", GetLastError());
return; return;
} }
@ -159,12 +159,12 @@ namespace
if (schService == nullptr) if (schService == nullptr)
{ {
llarp::LogError("CreateService failed ", GetLastError()); llarp::log::error(logcat, "CreateService failed {}", GetLastError());
CloseServiceHandle(schSCManager); CloseServiceHandle(schSCManager);
return; return;
} }
else else
llarp::LogInfo("Service installed successfully"); llarp::log::info(logcat, "Service installed successfully");
CloseServiceHandle(schService); CloseServiceHandle(schService);
CloseServiceHandle(schSCManager); CloseServiceHandle(schSCManager);
@ -189,7 +189,7 @@ namespace
if (nullptr == schSCManager) if (nullptr == schSCManager)
{ {
llarp::LogError("OpenSCManager failed ", GetLastError()); llarp::log::error(logcat, "OpenSCManager failed {}", GetLastError());
return; return;
} }
@ -201,7 +201,7 @@ namespace
if (schService == nullptr) if (schService == nullptr)
{ {
llarp::LogError("OpenService failed ", GetLastError()); llarp::log::error(logcat, "OpenService failed {}", GetLastError());
CloseServiceHandle(schSCManager); CloseServiceHandle(schSCManager);
return; return;
} }
@ -214,10 +214,10 @@ namespace
SERVICE_CONFIG_DESCRIPTION, // change: description SERVICE_CONFIG_DESCRIPTION, // change: description
&sd)) // new description &sd)) // new description
{ {
llarp::LogError("ChangeServiceConfig2 failed"); llarp::log::error(logcat, "ChangeServiceConfig2 failed");
} }
else else
llarp::LogInfo("Service description updated successfully."); llarp::log::info(log_cat, "Service description updated successfully.");
CloseServiceHandle(schService); CloseServiceHandle(schService);
CloseServiceHandle(schSCManager); CloseServiceHandle(schSCManager);
@ -237,7 +237,7 @@ namespace
if (nullptr == schSCManager) if (nullptr == schSCManager)
{ {
llarp::LogError("OpenSCManager failed ", GetLastError()); llarp::log::error(logcat, "OpenSCManager failed {}", GetLastError());
return; return;
} }
@ -249,7 +249,7 @@ namespace
if (schService == nullptr) if (schService == nullptr)
{ {
llarp::LogError("OpenService failed ", GetLastError()); llarp::log::error(logcat, "OpenService failed {}", GetLastError());
CloseServiceHandle(schSCManager); CloseServiceHandle(schSCManager);
return; return;
} }
@ -257,10 +257,10 @@ namespace
// Delete the service. // Delete the service.
if (!DeleteService(schService)) if (!DeleteService(schService))
{ {
llarp::LogError("DeleteService failed ", GetLastError()); llarp::log::error(logcat, "DeleteService failed {}", GetLastError());
} }
else else
llarp::LogInfo("Service deleted successfully\n"); llarp::log::info(logcat, "Service deleted successfully");
CloseServiceHandle(schService); CloseServiceHandle(schService);
CloseServiceHandle(schSCManager); CloseServiceHandle(schSCManager);
@ -337,7 +337,7 @@ namespace
if (svc->handle == nullptr) if (svc->handle == nullptr)
{ {
llarp::LogError("failed to register daemon control handler"); llarp::log::error(logcat, "failed to register daemon control handler");
return; return;
} }
@ -454,7 +454,7 @@ namespace
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {
llarp::LogError("cannot generate config at ", *configFile, ": ", ex.what()); llarp::log::error(logcat, "cannot generate config at {}: {}", *configFile, ex.what());
return 1; return 1;
} }
} }
@ -464,13 +464,13 @@ namespace
{ {
if (!fs::exists(*configFile)) if (!fs::exists(*configFile))
{ {
llarp::LogError("Config file not found ", *configFile); llarp::log::error(logcat, "Config file not found {}", *configFile);
return 1; return 1;
} }
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {
llarp::LogError("cannot check if ", *configFile, " exists: ", ex.what()); llarp::log::error(logcat, "cannot check if ", *configFile, " exists: ", ex.what());
return 1; return 1;
} }
} }
@ -487,7 +487,7 @@ namespace
} }
catch (std::exception& ex) catch (std::exception& ex)
{ {
llarp::LogError("cannot ensure config: ", ex.what()); llarp::log::error(logcat, "cannot ensure config: {}", ex.what());
return 1; return 1;
} }
configFile = llarp::GetDefaultConfigPath(); configFile = llarp::GetDefaultConfigPath();
@ -548,14 +548,13 @@ namespace
static void static void
run_main_context(std::optional<fs::path> confFile, const llarp::RuntimeOptions opts) run_main_context(std::optional<fs::path> confFile, const llarp::RuntimeOptions opts)
{ {
llarp::LogInfo(fmt::format( llarp::log::info(logcat, "starting up {}", llarp::LOKINET_VERSION_FULL);
"starting up {} {}", llarp::LOKINET_VERSION_FULL, llarp::LOKINET_RELEASE_MOTTO));
try try
{ {
std::shared_ptr<llarp::Config> conf; std::shared_ptr<llarp::Config> conf;
if (confFile) if (confFile)
{ {
llarp::LogInfo("Using config file: ", *confFile); llarp::log::info(logcat, "Using config file: {}", *confFile);
conf = std::make_shared<llarp::Config>(confFile->parent_path()); conf = std::make_shared<llarp::Config>(confFile->parent_path());
} }
else else
@ -564,7 +563,7 @@ namespace
} }
if (not conf->load(confFile, opts.isSNode)) if (not conf->load(confFile, opts.isSNode))
{ {
llarp::LogError("failed to parse configuration"); llarp::log::error(logcat, "failed to parse configuration");
exit_code.set_value(1); exit_code.set_value(1);
return; return;
} }
@ -589,13 +588,13 @@ namespace
} }
catch (llarp::util::bind_socket_error& ex) catch (llarp::util::bind_socket_error& ex)
{ {
llarp::LogError(fmt::format("{}, is lokinet already running? 🤔", ex.what())); llarp::log::error(logcat, "{}; is lokinet already running?", ex.what());
exit_code.set_value(1); exit_code.set_value(1);
return; return;
} }
catch (const std::exception& ex) catch (const std::exception& ex)
{ {
llarp::LogError(fmt::format("failed to start up lokinet: {}", ex.what())); llarp::log::error(logcat, "failed to start up lokinet: {}", ex.what());
exit_code.set_value(1); exit_code.set_value(1);
return; return;
} }
@ -606,12 +605,12 @@ namespace
} }
catch (const std::exception& e) catch (const std::exception& e)
{ {
llarp::LogError("Fatal: caught exception while running: {}", e.what()); llarp::log::error(logcat, "Fatal: caught exception while running: {}", e.what());
exit_code.set_exception(std::current_exception()); exit_code.set_exception(std::current_exception());
} }
catch (...) catch (...)
{ {
llarp::LogError("Fatal: caught non-standard exception while running"); llarp::log::error(logcat, "Fatal: caught non-standard exception while running");
exit_code.set_exception(std::current_exception()); exit_code.set_exception(std::current_exception());
} }
} }

@ -1 +1 @@
Subproject commit a2d89aa79dd06cbd7ee864da285cf4d8ac1b09b9 Subproject commit ad8904debc55f9495667e8571ee5bb963156d54e

View File

@ -85,5 +85,7 @@ namespace llarp
} }
insert(rc); insert(rc);
} }
_curr = begin();
} }
} // namespace llarp } // namespace llarp

View File

@ -12,8 +12,13 @@ namespace llarp
{ {
struct BootstrapList final : public std::set<RemoteRC> struct BootstrapList final : public std::set<RemoteRC>
{ {
size_t index; std::set<RemoteRC>::iterator _curr;
std::set<RemoteRC>::iterator current;
const RemoteRC&
current()
{
return *_curr;
}
bool bool
bt_decode(std::string_view buf); bt_decode(std::string_view buf);
@ -32,12 +37,12 @@ namespace llarp
const RemoteRC& const RemoteRC&
next() next()
{ {
++current; ++_curr;
if (current == this->end()) if (_curr == this->end())
current = this->begin(); _curr = this->begin();
return *current; return *_curr;
} }
bool bool
@ -46,7 +51,8 @@ namespace llarp
void void
randomize() randomize()
{ {
current = std::next(begin(), std::uniform_int_distribution<size_t>{0, size() - 1}(csrng)); if (size() > 1)
_curr = std::next(begin(), std::uniform_int_distribution<size_t>{0, size() - 1}(csrng));
} }
void void

View File

@ -8,7 +8,6 @@ namespace llarp
const char* const LOKINET_VERSION_TAG = "@VERSIONTAG@"; const char* const LOKINET_VERSION_TAG = "@VERSIONTAG@";
const char* const LOKINET_VERSION_FULL = "lokinet-@lokinet_VERSION_MAJOR@.@lokinet_VERSION_MINOR@.@lokinet_VERSION_PATCH@-@LOKINET_VERSION_TAG@"; const char* const LOKINET_VERSION_FULL = "lokinet-@lokinet_VERSION_MAJOR@.@lokinet_VERSION_MINOR@.@lokinet_VERSION_PATCH@-@LOKINET_VERSION_TAG@";
const char* const LOKINET_RELEASE_MOTTO = "@RELEASE_MOTTO@";
const char* const LOKINET_DEFAULT_NETID = "lokinet"; const char* const LOKINET_DEFAULT_NETID = "lokinet";
const char* const LOKINET_TESTNET_NETID = "testnet"; const char* const LOKINET_TESTNET_NETID = "testnet";
// clang-format on // clang-format on

View File

@ -10,7 +10,6 @@ namespace llarp
extern const char* const LOKINET_VERSION_TAG; extern const char* const LOKINET_VERSION_TAG;
extern const char* const LOKINET_VERSION_FULL; extern const char* const LOKINET_VERSION_FULL;
extern const char* const LOKINET_RELEASE_MOTTO;
extern const char* const LOKINET_DEFAULT_NETID; extern const char* const LOKINET_DEFAULT_NETID;
extern const char* const LOKINET_TESTNET_NETID; extern const char* const LOKINET_TESTNET_NETID;
} // namespace llarp } // namespace llarp

View File

@ -57,8 +57,7 @@ namespace llarp
throw std::runtime_error("Cannot call Setup() on context without a Config"); throw std::runtime_error("Cannot call Setup() on context without a Config");
if (opts.showBanner) if (opts.showBanner)
llarp::LogInfo( llarp::LogInfo(fmt::format("{}", llarp::LOKINET_VERSION_FULL));
fmt::format("{} {}", llarp::LOKINET_VERSION_FULL, llarp::LOKINET_RELEASE_MOTTO));
if (!loop) if (!loop)
{ {

View File

@ -3,7 +3,7 @@
namespace llarp::link namespace llarp::link
{ {
Connection::Connection( Connection::Connection(
std::shared_ptr<oxen::quic::connection_interface>& c, const std::shared_ptr<oxen::quic::connection_interface>& c,
std::shared_ptr<oxen::quic::BTRequestStream>& s, std::shared_ptr<oxen::quic::BTRequestStream>& s,
const RemoteRC& rc) const RemoteRC& rc)
: conn{c}, control_stream{s}, remote_rc{std::move(rc)} : conn{c}, control_stream{s}, remote_rc{std::move(rc)}

View File

@ -18,7 +18,7 @@ namespace llarp::link
bool remote_is_relay{true}; bool remote_is_relay{true};
Connection( Connection(
std::shared_ptr<oxen::quic::connection_interface>& c, const std::shared_ptr<oxen::quic::connection_interface>& c,
std::shared_ptr<oxen::quic::BTRequestStream>& s, std::shared_ptr<oxen::quic::BTRequestStream>& s,
const RemoteRC& rc); const RemoteRC& rc);
}; };

View File

@ -51,27 +51,6 @@ namespace llarp
return false; return false;
} }
bool
Endpoint::deregister_peer(RouterID _rid)
{
if (auto itr = conns.find(_rid); itr != conns.end())
{
auto& c = itr->second;
auto& _scid = c->conn->scid();
link_manager._router.loop()->call([this, scid = _scid, rid = _rid]() {
endpoint->close_connection(scid);
conns.erase(rid);
connid_map.erase(scid);
});
return true;
}
return false;
}
size_t size_t
Endpoint::num_connected(bool clients_only) const Endpoint::num_connected(bool clients_only) const
{ {
@ -111,18 +90,15 @@ namespace llarp
void void
Endpoint::close_connection(RouterID _rid) Endpoint::close_connection(RouterID _rid)
{ {
if (auto itr = conns.find(_rid); itr != conns.end()) assert(link_manager._router.loop()->inEventLoop());
{ auto itr = conns.find(_rid);
auto& c = itr->second; if (itr != conns.end())
auto& _scid = c->conn->scid(); return;
link_manager._router.loop()->call([this, scid = _scid, rid = _rid]() { auto& conn = *itr->second->conn;
endpoint->close_connection(scid); conn.close_connection();
connid_map.erase(conn.scid());
conns.erase(rid); conns.erase(itr);
connid_map.erase(scid);
});
}
} }
} // namespace link } // namespace link
@ -159,6 +135,11 @@ namespace llarp
[this, msg = std::move(m)]() mutable { handle_gossip_rc(std::move(msg)); }); [this, msg = std::move(m)]() mutable { handle_gossip_rc(std::move(msg)); });
}); });
s->register_command("bfetch_rcs"s, [this, rid](oxen::quic::message m) {
_router.loop()->call(
[this, msg = std::move(m)]() mutable { handle_fetch_bootstrap_rcs(std::move(msg)); });
});
for (auto& method : direct_requests) for (auto& method : direct_requests)
{ {
s->register_command( s->register_command(
@ -193,26 +174,55 @@ namespace llarp
return on_conn_closed(ci, ec); return on_conn_closed(ci, ec);
}, },
[this](oxen::quic::dgram_interface& di, bstring dgram) { recv_data_message(di, dgram); }); [this](oxen::quic::dgram_interface& di, bstring dgram) { recv_data_message(di, dgram); });
ep->listen( tls_creds->set_key_verify_callback([this](const ustring_view& key, const ustring_view&) {
tls_creds, bool result = false;
[&](oxen::quic::Connection& c, RouterID other{key.data()};
oxen::quic::Endpoint& e,
std::optional<int64_t> id) -> std::shared_ptr<oxen::quic::Stream> { if (auto itr = rids_pending_verification.find(other); itr != rids_pending_verification.end())
if (id && id == 0) {
{ verified_rids[other] = itr->second;
auto s = std::make_shared<oxen::quic::BTRequestStream>( rids_pending_verification.erase(itr);
c, e, [](oxen::quic::Stream& s, uint64_t error_code) { result = true;
log::warning( }
logcat,
"BTRequestStream closed unexpectedly (ec:{}); closing connection...", if (_router.node_db()->has_rc(other))
error_code); result = true;
s.conn.close_connection(error_code);
}); // TODO: discuss pubkey verification for bootstraps connecting to seed node
register_commands(s); if (_router.is_bootstrap_seed())
return s; {
} log::warning(logcat, "Allowing connection -- we are bootstrap seed");
return std::make_shared<oxen::quic::Stream>(c, e); result = true;
}); }
log::critical(
logcat, "{}uccessfully verified connection to {}!", result ? "S" : "Uns", other);
return result;
});
if (_router.is_service_node())
{
ep->listen(
tls_creds,
[&](oxen::quic::Connection& c,
oxen::quic::Endpoint& e,
std::optional<int64_t> id) -> std::shared_ptr<oxen::quic::Stream> {
if (id && id == 0)
{
auto s = e.make_shared<oxen::quic::BTRequestStream>(
c, e, [](oxen::quic::Stream& s, uint64_t error_code) {
log::warning(
logcat,
"BTRequestStream closed unexpectedly (ec:{}); closing connection...",
error_code);
s.conn.close_connection(error_code);
});
register_commands(s);
return s;
}
return e.make_shared<oxen::quic::Stream>(c, e);
});
}
return ep; return ep;
} }
@ -346,6 +356,9 @@ namespace llarp
} }
const auto& remote_addr = rc.addr(); const auto& remote_addr = rc.addr();
const auto& rid = rc.router_id();
rids_pending_verification[rid] = rc;
// TODO: confirm remote end is using the expected pubkey (RouterID). // TODO: confirm remote end is using the expected pubkey (RouterID).
// TODO: ALPN for "client" vs "relay" (could just be set on endpoint creation) // TODO: ALPN for "client" vs "relay" (could just be set on endpoint creation)
@ -362,13 +375,39 @@ namespace llarp
log::warning(quic_cat, "Failed to begin establishing connection to {}", remote_addr); log::warning(quic_cat, "Failed to begin establishing connection to {}", remote_addr);
} }
void
LinkManager::on_inbound_conn(oxen::quic::connection_interface& ci)
{
const auto& scid = ci.scid();
RouterID rid{ci.remote_key()};
const auto& rc = verified_rids[rid];
ep.connid_map.emplace(scid, rid);
auto [itr, b] = ep.conns.emplace(rid, nullptr);
auto control_stream = ci.queue_stream<oxen::quic::BTRequestStream>([](oxen::quic::Stream& s,
uint64_t error_code) {
log::warning(
logcat, "BTRequestStream closed unexpectedly (ec:{}); closing connection...", error_code);
s.conn.close_connection(error_code);
});
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);
}
// TODO: should we add routes here now that Router::SessionOpen is gone? // TODO: should we add routes here now that Router::SessionOpen is gone?
void void
LinkManager::on_conn_open(oxen::quic::connection_interface& ci) LinkManager::on_conn_open(oxen::quic::connection_interface& ci)
{ {
_router.loop()->call([this, &conn_interface = ci]() { _router.loop()->call([this, &conn_interface = ci]() {
const auto& scid = conn_interface.scid(); const auto rid = RouterID{conn_interface.remote_key()};
const auto& rid = ep.connid_map[scid]; const auto& remote = conn_interface.remote();
if (conn_interface.is_inbound())
{
log::critical(logcat, "Inbound connection fom {} (remote:{})", rid, remote);
on_inbound_conn(conn_interface);
}
log::critical( log::critical(
logcat, logcat,
@ -380,6 +419,7 @@ namespace llarp
// messages to the remote // messages to the remote
if (auto itr = pending_conn_msg_queue.find(rid); itr != pending_conn_msg_queue.end()) if (auto itr = pending_conn_msg_queue.find(rid); itr != pending_conn_msg_queue.end())
{ {
log::critical(logcat, "Clearing pending queue for RID:{}", rid);
auto& que = itr->second; auto& que = itr->second;
while (not que.empty()) while (not que.empty())
@ -389,6 +429,7 @@ namespace llarp
if (m.is_control) if (m.is_control)
{ {
auto& msg = reinterpret_cast<PendingControlMessage&>(m); auto& msg = reinterpret_cast<PendingControlMessage&>(m);
log::critical(logcat, "Dispatching {} request!", msg.endpoint);
ep.conns[rid]->control_stream->command(msg.endpoint, msg.body, msg.func); ep.conns[rid]->control_stream->command(msg.endpoint, msg.body, msg.func);
} }
else else
@ -399,7 +440,9 @@ namespace llarp
que.pop_front(); que.pop_front();
} }
return;
} }
log::warning(logcat, "No pending queue to clear for RID:{}", rid);
}); });
}; };
@ -409,12 +452,16 @@ namespace llarp
_router.loop()->call([this, &conn_interface = ci, error_code = ec]() { _router.loop()->call([this, &conn_interface = ci, error_code = ec]() {
const auto& scid = conn_interface.scid(); const auto& scid = conn_interface.scid();
log::debug(quic_cat, "Purging quic connection CID:{} (ec: {})", scid, error_code); log::critical(quic_cat, "Purging quic connection CID:{} (ec: {})", scid, error_code);
if (const auto& c_itr = ep.connid_map.find(scid); c_itr != ep.connid_map.end()) if (const auto& c_itr = ep.connid_map.find(scid); c_itr != ep.connid_map.end())
{ {
const auto& rid = c_itr->second; const auto& rid = c_itr->second;
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()) if (auto p_itr = pending_conn_msg_queue.find(rid); p_itr != pending_conn_msg_queue.end())
pending_conn_msg_queue.erase(p_itr); pending_conn_msg_queue.erase(p_itr);
@ -423,7 +470,7 @@ namespace llarp
ep.connid_map.erase(c_itr); ep.connid_map.erase(c_itr);
log::debug(quic_cat, "Quic connection CID:{} purged successfully", scid); log::critical(quic_cat, "Quic connection CID:{} purged successfully", scid);
} }
}); });
} }
@ -440,18 +487,6 @@ namespace llarp
return ep.have_conn(remote, true); return ep.have_conn(remote, true);
} }
void
LinkManager::deregister_peer(RouterID remote)
{
if (auto rv = ep.deregister_peer(remote); rv)
{
persisting_conns.erase(remote);
log::info(logcat, "Peer {} successfully de-registered", remote);
}
else
log::warning(logcat, "Peer {} not found for de-registration!", remote);
}
void void
LinkManager::stop() LinkManager::stop()
{ {
@ -582,9 +617,25 @@ namespace llarp
void void
LinkManager::fetch_bootstrap_rcs( LinkManager::fetch_bootstrap_rcs(
const RouterID& source, std::string payload, std::function<void(oxen::quic::message m)> func) const RemoteRC& source, std::string payload, std::function<void(oxen::quic::message m)> func)
{ {
send_control_message(source, "bfetch_rcs", std::move(payload), std::move(func)); _router.loop()->call([this, source, payload, f = std::move(func)]() {
if (auto conn = ep.get_conn(source); conn)
{
log::critical(logcat, "Dispatched bootstrap fetch request!");
conn->control_stream->command("bfetch_rcs"s, std::move(payload), std::move(f));
return;
}
log::critical(logcat, "Queuing bootstrap fetch request");
auto pending = PendingControlMessage(std::move(payload), "bfetch_rcs"s, f);
auto [itr, b] = pending_conn_msg_queue.emplace(source.router_id(), MessageQueue());
itr->second.push_back(std::move(pending));
connect_to(source);
});
} }
void void
@ -594,11 +645,14 @@ namespace llarp
assert(_router.is_service_node()); assert(_router.is_service_node());
const auto& rcs = node_db->get_rcs(); const auto& rcs = node_db->get_rcs();
RemoteRC remote;
size_t quantity; size_t quantity;
try try
{ {
oxenc::bt_dict_consumer btdc{m.body()}; oxenc::bt_dict_consumer btdc{m.body()};
btdc.required("local");
remote = RemoteRC{btdc.consume_dict_consumer()};
quantity = btdc.require<size_t>("quantity"); quantity = btdc.require<size_t>("quantity");
} }
catch (const std::exception& e) catch (const std::exception& e)
@ -608,6 +662,8 @@ namespace llarp
return; return;
} }
node_db->put_rc(remote);
auto rc_size = rcs.size(); auto rc_size = rcs.size();
auto now = llarp::time_now_ms(); auto now = llarp::time_now_ms();
size_t i = 0; size_t i = 0;

View File

@ -61,9 +61,6 @@ namespace llarp
bool bool
have_conn(const RouterID& remote, bool client_only) const; have_conn(const RouterID& remote, bool client_only) const;
bool
deregister_peer(RouterID remote);
size_t size_t
num_connected(bool clients_only) const; num_connected(bool clients_only) const;
@ -181,6 +178,12 @@ namespace llarp
// holds any messages we attempt to send while connections are establishing // holds any messages we attempt to send while connections are establishing
std::unordered_map<RouterID, MessageQueue> pending_conn_msg_queue; std::unordered_map<RouterID, MessageQueue> pending_conn_msg_queue;
// 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
// object, we store the rid and rc here
std::map<RouterID, RemoteRC> verified_rids;
util::DecayingHashSet<RouterID> clients{path::DEFAULT_LIFETIME}; util::DecayingHashSet<RouterID> clients{path::DEFAULT_LIFETIME};
@ -203,6 +206,9 @@ namespace llarp
void void
recv_control_message(oxen::quic::message msg); recv_control_message(oxen::quic::message msg);
void
on_inbound_conn(oxen::quic::connection_interface& ci);
void void
on_conn_open(oxen::quic::connection_interface& ci); on_conn_open(oxen::quic::connection_interface& ci);
@ -252,7 +258,7 @@ namespace llarp
void void
fetch_bootstrap_rcs( fetch_bootstrap_rcs(
const RouterID& source, const RemoteRC& source,
std::string payload, std::string payload,
std::function<void(oxen::quic::message m)> func); std::function<void(oxen::quic::message m)> func);
@ -265,9 +271,6 @@ namespace llarp
bool bool
have_client_connection_to(const RouterID& remote) const; have_client_connection_to(const RouterID& remote) const;
void
deregister_peer(RouterID remote);
void void
test_reachability(const RouterID& rid, conn_open_hook, conn_closed_hook); test_reachability(const RouterID& rid, conn_open_hook, conn_closed_hook);
@ -417,6 +420,8 @@ namespace llarp
connid_map.emplace(conn_interface->scid(), rc.router_id()); connid_map.emplace(conn_interface->scid(), rc.router_id());
auto [itr, b] = conns.emplace(rc.router_id(), nullptr); auto [itr, b] = conns.emplace(rc.router_id(), nullptr);
log::critical(logcat, "Establishing connection to {}...", rc.router_id());
auto control_stream = conn_interface->template get_new_stream<oxen::quic::BTRequestStream>( auto control_stream = conn_interface->template get_new_stream<oxen::quic::BTRequestStream>(
[](oxen::quic::Stream& s, uint64_t error_code) { [](oxen::quic::Stream& s, uint64_t error_code) {
log::warning( log::warning(
@ -425,6 +430,7 @@ namespace llarp
error_code); error_code);
s.conn.close_connection(error_code); s.conn.close_connection(error_code);
}); });
itr->second = std::make_shared<link::Connection>(conn_interface, control_stream, rc); itr->second = std::make_shared<link::Connection>(conn_interface, control_stream, rc);
return true; return true;

View File

@ -37,10 +37,12 @@ namespace llarp
namespace BootstrapFetchMessage namespace BootstrapFetchMessage
{ {
// the LocalRC is converted to a RemoteRC type to send to the bootstrap seed
inline static std::string inline static std::string
serialize(size_t quantity) serialize(const RemoteRC& local_rc, size_t quantity)
{ {
oxenc::bt_dict_producer btdp; oxenc::bt_dict_producer btdp;
btdp.append_encoded("local", local_rc.view());
btdp.append("quantity", quantity); btdp.append("quantity", quantity);
return std::move(btdp).str(); return std::move(btdp).str();
} }

View File

@ -196,7 +196,8 @@ namespace llarp
{ {
// TODO: if this needs to be called more than once (ex: drastic failures), then // TODO: if this needs to be called more than once (ex: drastic failures), then
// change this assert to a bootstraps.clear() call // change this assert to a bootstraps.clear() call
assert(_bootstraps->empty()); if (_bootstraps)
assert(_bootstraps->empty());
_bootstraps = std::move(from_router); _bootstraps = std::move(from_router);
_bootstraps->randomize(); _bootstraps->randomize();
@ -343,8 +344,9 @@ namespace llarp
void void
NodeDB::fetch_initial() NodeDB::fetch_initial()
{ {
if (known_rids.empty()) if (known_rcs.empty())
{ {
log::critical(logcat, "No RC's held locally... BOOTSTRAP TIME");
fallback_to_bootstrap(); fallback_to_bootstrap();
} }
else else
@ -605,6 +607,14 @@ namespace llarp
{ {
_router.last_rc_fetch = llarp::time_point_now(); _router.last_rc_fetch = llarp::time_point_now();
if (_router.is_service_node())
{
_needs_rebootstrap = false;
fail_sources.clear();
fetch_failures = 0;
return;
}
if (initial) if (initial)
fetch_rids(initial); fetch_rids(initial);
} }
@ -619,7 +629,10 @@ namespace llarp
_needs_rebootstrap = false; _needs_rebootstrap = false;
if (initial) if (initial)
{
_needs_initial_fetch = false; _needs_initial_fetch = false;
_initial_completed = true;
}
} }
void void
@ -656,8 +669,9 @@ namespace llarp
_needs_rebootstrap = false; _needs_rebootstrap = false;
_router.link_manager().fetch_bootstrap_rcs( _router.link_manager().fetch_bootstrap_rcs(
fetch_source, _bootstraps->current(),
BootstrapFetchMessage::serialize(BOOTSTRAP_SOURCE_COUNT), BootstrapFetchMessage::serialize(
_router.router_contact.to_remote(), BOOTSTRAP_SOURCE_COUNT),
[this](oxen::quic::message m) mutable { [this](oxen::quic::message m) mutable {
if (not m) if (not m)
{ {
@ -755,9 +769,6 @@ namespace llarp
registered_routers.insert(greylist.begin(), greylist.end()); registered_routers.insert(greylist.begin(), greylist.end());
registered_routers.insert(greenlist.begin(), greenlist.end()); registered_routers.insert(greenlist.begin(), greenlist.end());
for (const auto& rid : whitelist)
known_rids.insert(rid);
router_whitelist.clear(); router_whitelist.clear();
router_whitelist.insert(whitelist.begin(), whitelist.end()); router_whitelist.insert(whitelist.begin(), whitelist.end());
router_greylist.clear(); router_greylist.clear();

View File

@ -135,9 +135,9 @@ namespace llarp
- gray: fully funded, but decommissioned routers - gray: fully funded, but decommissioned routers
- green: registered, but not fully-staked routers - green: registered, but not fully-staked routers
*/ */
std::unordered_set<RouterID> router_whitelist; std::set<RouterID> router_whitelist{};
std::unordered_set<RouterID> router_greylist; std::set<RouterID> router_greylist{};
std::unordered_set<RouterID> router_greenlist; std::set<RouterID> router_greenlist{};
// All registered relays (service nodes) // All registered relays (service nodes)
std::set<RouterID> registered_routers; std::set<RouterID> registered_routers;
@ -165,7 +165,7 @@ namespace llarp
std::atomic<int> fetch_failures{0}, bootstrap_failures{0}; std::atomic<int> fetch_failures{0}, bootstrap_failures{0};
std::atomic<bool> _using_bootstrap_fallback{false}, _needs_rebootstrap{false}, std::atomic<bool> _using_bootstrap_fallback{false}, _needs_rebootstrap{false},
_needs_initial_fetch{true}; _needs_initial_fetch{true}, _initial_completed{false};
bool bool
want_rc(const RouterID& rid) const; want_rc(const RouterID& rid) const;
@ -332,7 +332,7 @@ namespace llarp
return known_rids; return known_rids;
} }
const std::unordered_set<RouterID>& const std::set<RouterID>&
greylist() const greylist() const
{ {
return router_greylist; return router_greylist;

View File

@ -595,8 +595,6 @@ namespace llarp
? _listen_address ? _listen_address
: oxen::quic::Address{*paddr, pport ? *pport : DEFAULT_LISTEN_PORT}; : oxen::quic::Address{*paddr, pport ? *pport : DEFAULT_LISTEN_PORT};
log::critical(logcat, "listen_addr:{} \t public_addr:{}", _listen_address, _public_address);
RouterContact::BLOCK_BOGONS = conf.router.block_bogons; RouterContact::BLOCK_BOGONS = conf.router.block_bogons;
auto& networkConfig = conf.network; auto& networkConfig = conf.network;
@ -668,8 +666,15 @@ namespace llarp
clear_bad_rcs(); clear_bad_rcs();
if (_bootstrap_rc_list->empty() and not conf.bootstrap.seednode) _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)
{ {
log::warning(logcat, "Warning: bootstrap list is empty and we are not a seed node");
auto fallbacks = llarp::load_bootstrap_fallbacks(); auto fallbacks = llarp::load_bootstrap_fallbacks();
if (auto itr = fallbacks.find(RouterContact::ACTIVE_NETID); itr != fallbacks.end()) if (auto itr = fallbacks.find(RouterContact::ACTIVE_NETID); itr != fallbacks.end())
@ -692,11 +697,11 @@ namespace llarp
log::info( log::info(
logcat, "Loaded {} default fallback bootstrap routers!", _bootstrap_rc_list->size()); logcat, "Loaded {} default fallback bootstrap routers!", _bootstrap_rc_list->size());
clear_bad_rcs(); clear_bad_rcs();
node_db()->set_bootstrap_routers(std::move(_bootstrap_rc_list));
} }
if (conf.bootstrap.seednode) log::critical(logcat, "We have {} bootstrap routers!", _bootstrap_rc_list->size());
log::critical(logcat, "We are a bootstrap seed node!");
node_db()->set_bootstrap_routers(std::move(_bootstrap_rc_list));
// TODO: RC refactor here // TODO: RC refactor here
if (_is_service_node) if (_is_service_node)
@ -762,7 +767,8 @@ namespace llarp
Router::report_stats() Router::report_stats()
{ {
const auto now = llarp::time_now_ms(); const auto now = llarp::time_now_ms();
log::info(
log::critical(
logcat, logcat,
"{} RCs loaded with {} bootstrap peers and {} router connections!", "{} RCs loaded with {} bootstrap peers and {} router connections!",
_node_db->num_rcs(), _node_db->num_rcs(),
@ -771,15 +777,17 @@ namespace llarp
if (is_service_node()) if (is_service_node())
{ {
log::info( log::critical(
logcat, logcat,
"Local service node has {} client connections since last RC update ({} to expiry)", "Local service node has {} client connections since last RC update ({} to expiry)",
num_client_connections(), num_client_connections(),
router_contact.age(now), router_contact.age(now),
router_contact.time_to_expiry(now)); router_contact.time_to_expiry(now));
} }
if (_last_stats_report > 0s) if (_last_stats_report > 0s)
log::info(logcat, "Last reported stats time {}", now - _last_stats_report); log::info(logcat, "Last reported stats time {}", now - _last_stats_report);
_last_stats_report = now; _last_stats_report = now;
} }
@ -890,7 +898,8 @@ namespace llarp
if (needs_initial_fetch()) if (needs_initial_fetch())
{ {
node_db()->fetch_initial(); if (not _config->bootstrap.seednode)
node_db()->fetch_initial();
} }
else if (needs_rebootstrap() and next_bootstrap_attempt > now_timepoint) else if (needs_rebootstrap() and next_bootstrap_attempt > now_timepoint)
{ {
@ -975,7 +984,7 @@ namespace llarp
// mark peers as de-registered // mark peers as de-registered
for (auto& peer : close_peers) for (auto& peer : close_peers)
_link_manager.deregister_peer(peer); _link_manager.close_connection(peer);
} }
*/ */

View File

@ -88,6 +88,7 @@ namespace llarp
bool _testnet = false; bool _testnet = false;
bool _testing_disabled = false; bool _testing_disabled = false;
bool _bootstrap_seed = false;
consensus::reachability_testing router_testing; consensus::reachability_testing router_testing;
@ -157,6 +158,12 @@ namespace llarp
std::chrono::system_clock::time_point next_bootstrap_attempt{last_rc_gossip}; std::chrono::system_clock::time_point next_bootstrap_attempt{last_rc_gossip};
public: public:
bool
is_bootstrap_seed() const
{
return _bootstrap_seed;
}
int int
required_num_client_conns() const required_num_client_conns() const
{ {

View File

@ -207,6 +207,8 @@ namespace llarp
bt_load(oxenc::bt_dict_consumer& data); bt_load(oxenc::bt_dict_consumer& data);
}; };
struct RemoteRC;
/// Extension of RouterContact used to store a local "RC," and inserts a RouterContact by /// Extension of RouterContact used to store a local "RC," and inserts a RouterContact by
/// re-parsing and sending it out. This sub-class contains a pubkey and all the other attributes /// re-parsing and sending it out. This sub-class contains a pubkey and all the other attributes
/// required for signing and serialization /// required for signing and serialization
@ -236,6 +238,9 @@ namespace llarp
explicit LocalRC(std::string payload, const SecretKey sk); explicit LocalRC(std::string payload, const SecretKey sk);
~LocalRC() = default; ~LocalRC() = default;
RemoteRC
to_remote();
void void
resign(); resign();

View File

@ -27,6 +27,12 @@ namespace llarp
resign(); resign();
} }
RemoteRC
LocalRC::to_remote()
{
return RemoteRC{view()};
}
LocalRC::LocalRC(std::string payload, const SecretKey sk) : _secret_key{std::move(sk)} LocalRC::LocalRC(std::string payload, const SecretKey sk) : _secret_key{std::move(sk)}
{ {
_router_id = llarp::seckey_to_pubkey(_secret_key); _router_id = llarp::seckey_to_pubkey(_secret_key);

View File

@ -21,6 +21,9 @@ namespace llarp
RouterID(const Data& data) : PubKey(data) RouterID(const Data& data) : PubKey(data)
{} {}
RouterID(ustring_view data) : PubKey(data.data())
{}
util::StatusObject util::StatusObject
ExtractStatus() const; ExtractStatus() const;