mirror of https://github.com/oxen-io/lokinet
Merge d6e5aca572
into c693569c00
This commit is contained in:
commit
3d639b436d
|
@ -43,7 +43,7 @@ testnet_tmp
|
|||
vsproject/
|
||||
.vs
|
||||
|
||||
daemon.ini
|
||||
*.ini
|
||||
|
||||
|
||||
.gradle/
|
||||
|
|
|
@ -41,8 +41,6 @@ if(APPLE)
|
|||
set(LOKINET_APPLE_BUILD 5)
|
||||
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")
|
||||
|
||||
set(DEFAULT_WITH_BOOTSTRAP ON)
|
||||
|
|
|
@ -46,10 +46,8 @@ int
|
|||
main(int argc, char* argv[])
|
||||
{
|
||||
const std::unordered_map<std::string, std::string> bootstrap_urls = {
|
||||
{"mainnet", "https://seed.lokinet.org/lokinet.signed"},
|
||||
{"lokinet", "https://seed.lokinet.org/lokinet.signed"},
|
||||
{"testnet", "https://seed.lokinet.org/testnet.signed"},
|
||||
{"gamma", "https://seed.lokinet.org/testnet.signed"}};
|
||||
{"testnet", "https://seed.lokinet.org/testnet.signed"}};
|
||||
|
||||
std::string bootstrap_url = bootstrap_urls.at("lokinet");
|
||||
fs::path outputfile{llarp::GetDefaultBootstrap()};
|
||||
|
|
|
@ -125,7 +125,7 @@ namespace
|
|||
|
||||
if (!GetModuleFileName(nullptr, szPath.data(), MAX_PATH))
|
||||
{
|
||||
llarp::LogError("Cannot install service ", GetLastError());
|
||||
llarp::log::error(logcat, "Cannot install service {}", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -137,7 +137,7 @@ namespace
|
|||
|
||||
if (nullptr == schSCManager)
|
||||
{
|
||||
llarp::LogError("OpenSCManager failed ", GetLastError());
|
||||
llarp::log::error(logcat, "OpenSCManager failed {}", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -159,12 +159,12 @@ namespace
|
|||
|
||||
if (schService == nullptr)
|
||||
{
|
||||
llarp::LogError("CreateService failed ", GetLastError());
|
||||
llarp::log::error(logcat, "CreateService failed {}", GetLastError());
|
||||
CloseServiceHandle(schSCManager);
|
||||
return;
|
||||
}
|
||||
else
|
||||
llarp::LogInfo("Service installed successfully");
|
||||
llarp::log::info(logcat, "Service installed successfully");
|
||||
|
||||
CloseServiceHandle(schService);
|
||||
CloseServiceHandle(schSCManager);
|
||||
|
@ -189,7 +189,7 @@ namespace
|
|||
|
||||
if (nullptr == schSCManager)
|
||||
{
|
||||
llarp::LogError("OpenSCManager failed ", GetLastError());
|
||||
llarp::log::error(logcat, "OpenSCManager failed {}", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,7 @@ namespace
|
|||
|
||||
if (schService == nullptr)
|
||||
{
|
||||
llarp::LogError("OpenService failed ", GetLastError());
|
||||
llarp::log::error(logcat, "OpenService failed {}", GetLastError());
|
||||
CloseServiceHandle(schSCManager);
|
||||
return;
|
||||
}
|
||||
|
@ -214,10 +214,10 @@ namespace
|
|||
SERVICE_CONFIG_DESCRIPTION, // change: description
|
||||
&sd)) // new description
|
||||
{
|
||||
llarp::LogError("ChangeServiceConfig2 failed");
|
||||
llarp::log::error(logcat, "ChangeServiceConfig2 failed");
|
||||
}
|
||||
else
|
||||
llarp::LogInfo("Service description updated successfully.");
|
||||
llarp::log::info(log_cat, "Service description updated successfully.");
|
||||
|
||||
CloseServiceHandle(schService);
|
||||
CloseServiceHandle(schSCManager);
|
||||
|
@ -237,7 +237,7 @@ namespace
|
|||
|
||||
if (nullptr == schSCManager)
|
||||
{
|
||||
llarp::LogError("OpenSCManager failed ", GetLastError());
|
||||
llarp::log::error(logcat, "OpenSCManager failed {}", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -249,7 +249,7 @@ namespace
|
|||
|
||||
if (schService == nullptr)
|
||||
{
|
||||
llarp::LogError("OpenService failed ", GetLastError());
|
||||
llarp::log::error(logcat, "OpenService failed {}", GetLastError());
|
||||
CloseServiceHandle(schSCManager);
|
||||
return;
|
||||
}
|
||||
|
@ -257,10 +257,10 @@ namespace
|
|||
// Delete the service.
|
||||
if (!DeleteService(schService))
|
||||
{
|
||||
llarp::LogError("DeleteService failed ", GetLastError());
|
||||
llarp::log::error(logcat, "DeleteService failed {}", GetLastError());
|
||||
}
|
||||
else
|
||||
llarp::LogInfo("Service deleted successfully\n");
|
||||
llarp::log::info(logcat, "Service deleted successfully");
|
||||
|
||||
CloseServiceHandle(schService);
|
||||
CloseServiceHandle(schSCManager);
|
||||
|
@ -337,7 +337,7 @@ namespace
|
|||
|
||||
if (svc->handle == nullptr)
|
||||
{
|
||||
llarp::LogError("failed to register daemon control handler");
|
||||
llarp::log::error(logcat, "failed to register daemon control handler");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -454,7 +454,7 @@ namespace
|
|||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -464,13 +464,13 @@ namespace
|
|||
{
|
||||
if (!fs::exists(*configFile))
|
||||
{
|
||||
llarp::LogError("Config file not found ", *configFile);
|
||||
llarp::log::error(logcat, "Config file not found {}", *configFile);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -487,7 +487,7 @@ namespace
|
|||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
llarp::LogError("cannot ensure config: ", ex.what());
|
||||
llarp::log::error(logcat, "cannot ensure config: {}", ex.what());
|
||||
return 1;
|
||||
}
|
||||
configFile = llarp::GetDefaultConfigPath();
|
||||
|
@ -548,14 +548,13 @@ namespace
|
|||
static void
|
||||
run_main_context(std::optional<fs::path> confFile, const llarp::RuntimeOptions opts)
|
||||
{
|
||||
llarp::LogInfo(fmt::format(
|
||||
"starting up {} {}", llarp::LOKINET_VERSION_FULL, llarp::LOKINET_RELEASE_MOTTO));
|
||||
llarp::log::info(logcat, "starting up {}", llarp::LOKINET_VERSION_FULL);
|
||||
try
|
||||
{
|
||||
std::shared_ptr<llarp::Config> conf;
|
||||
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());
|
||||
}
|
||||
else
|
||||
|
@ -564,7 +563,7 @@ namespace
|
|||
}
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
@ -589,13 +588,13 @@ namespace
|
|||
}
|
||||
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);
|
||||
return;
|
||||
}
|
||||
catch (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);
|
||||
return;
|
||||
}
|
||||
|
@ -604,14 +603,14 @@ namespace
|
|||
auto result = ctx->Run(opts);
|
||||
exit_code.set_value(result);
|
||||
}
|
||||
catch (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());
|
||||
}
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 3ced484e8cc543b90c5fc554ccc0ea2e54ec8d37
|
||||
Subproject commit 0e431b912eb4bf76a9219861afc06cd8ceafa781
|
|
@ -178,10 +178,10 @@ lokinet_add_library(lokinet-nodedb
|
|||
set(BOOTSTRAP_FALLBACKS)
|
||||
foreach(bs IN ITEMS MAINNET TESTNET)
|
||||
if(BOOTSTRAP_FALLBACK_${bs})
|
||||
message(STATUS "Building with ${bs} fallback boostrap path \"${BOOTSTRAP_FALLBACK_${bs}}\"")
|
||||
message(STATUS "Building with ${bs} fallback bootstrap path \"${BOOTSTRAP_FALLBACK_${bs}}\"")
|
||||
file(READ "${BOOTSTRAP_FALLBACK_${bs}}" bs_data HEX)
|
||||
if(bs STREQUAL TESTNET)
|
||||
set(network "gamma")
|
||||
set(network "testnet")
|
||||
elseif(bs STREQUAL MAINNET)
|
||||
set(network "lokinet")
|
||||
else()
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace llarp
|
|||
oxenc::bt_list_consumer btlc{buf};
|
||||
|
||||
while (not btlc.is_finished())
|
||||
emplace(btlc.consume_dict_consumer());
|
||||
emplace(btlc.consume_dict_data());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
|
@ -25,6 +25,24 @@ namespace llarp
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BootstrapList::contains(const RouterID& rid) const
|
||||
{
|
||||
for (const auto& it : *this)
|
||||
{
|
||||
if (it.router_id() == rid)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
BootstrapList::contains(const RemoteRC& rc) const
|
||||
{
|
||||
return count(rc);
|
||||
}
|
||||
|
||||
std::string_view
|
||||
BootstrapList::bt_encode() const
|
||||
{
|
||||
|
@ -59,6 +77,7 @@ namespace llarp
|
|||
else
|
||||
{
|
||||
RemoteRC rc;
|
||||
|
||||
if (not rc.read(fpath))
|
||||
{
|
||||
throw std::runtime_error{
|
||||
|
@ -66,5 +85,7 @@ namespace llarp
|
|||
}
|
||||
insert(rc);
|
||||
}
|
||||
|
||||
_curr = begin();
|
||||
}
|
||||
} // namespace llarp
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "router_contact.hpp"
|
||||
|
||||
#include <llarp/crypto/crypto.hpp>
|
||||
#include <llarp/util/fs.hpp>
|
||||
|
||||
#include <set>
|
||||
|
@ -11,6 +12,14 @@ namespace llarp
|
|||
{
|
||||
struct BootstrapList final : public std::set<RemoteRC>
|
||||
{
|
||||
std::set<RemoteRC>::iterator _curr = begin();
|
||||
|
||||
const RemoteRC&
|
||||
current()
|
||||
{
|
||||
return *_curr;
|
||||
}
|
||||
|
||||
bool
|
||||
bt_decode(std::string_view buf);
|
||||
|
||||
|
@ -20,6 +29,35 @@ namespace llarp
|
|||
void
|
||||
read_from_file(const fs::path& fpath);
|
||||
|
||||
bool
|
||||
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
|
||||
const RemoteRC&
|
||||
next()
|
||||
{
|
||||
if (size() < 2)
|
||||
return *_curr;
|
||||
|
||||
++_curr;
|
||||
|
||||
if (_curr == this->end())
|
||||
_curr = this->begin();
|
||||
|
||||
return *_curr;
|
||||
}
|
||||
|
||||
bool
|
||||
contains(const RemoteRC& rc) const;
|
||||
|
||||
void
|
||||
randomize()
|
||||
{
|
||||
if (size() > 1)
|
||||
_curr = std::next(begin(), std::uniform_int_distribution<size_t>{0, size() - 1}(csrng));
|
||||
}
|
||||
|
||||
void
|
||||
clear_list()
|
||||
{
|
||||
|
|
|
@ -19,15 +19,6 @@
|
|||
|
||||
namespace llarp
|
||||
{
|
||||
// constants for config file default values
|
||||
constexpr int DefaultMinConnectionsForRouter = 6;
|
||||
constexpr int DefaultMaxConnectionsForRouter = 60;
|
||||
|
||||
constexpr int DefaultMinConnectionsForClient = 4;
|
||||
constexpr int DefaultMaxConnectionsForClient = 6;
|
||||
|
||||
constexpr int DefaultPublicPort = 1090;
|
||||
|
||||
using namespace config;
|
||||
namespace
|
||||
{
|
||||
|
@ -61,8 +52,8 @@ namespace llarp
|
|||
"netid",
|
||||
Default{llarp::LOKINET_DEFAULT_NETID},
|
||||
Comment{
|
||||
"Network ID; this is '"s + llarp::LOKINET_DEFAULT_NETID
|
||||
+ "' for mainnet, 'gamma' for testnet.",
|
||||
"Network ID; this is '"s + llarp::LOKINET_DEFAULT_NETID + "' for mainnet, '"s
|
||||
+ llarp::LOKINET_TESTNET_NETID + "' for testnet."s,
|
||||
},
|
||||
[this](std::string arg) {
|
||||
if (arg.size() > NETID_SIZE)
|
||||
|
@ -72,38 +63,44 @@ namespace llarp
|
|||
net_id = std::move(arg);
|
||||
});
|
||||
|
||||
int minConnections =
|
||||
(params.is_relay ? DefaultMinConnectionsForRouter : DefaultMinConnectionsForClient);
|
||||
conf.define_option<int>(
|
||||
"router",
|
||||
"relay-connections",
|
||||
Default{CLIENT_ROUTER_CONNECTIONS},
|
||||
ClientOnly,
|
||||
Comment{
|
||||
"Minimum number of routers lokinet client will attempt to maintain connections to.",
|
||||
},
|
||||
[=](int arg) {
|
||||
if (arg < CLIENT_ROUTER_CONNECTIONS)
|
||||
throw std::invalid_argument{
|
||||
fmt::format("Client relay connections must be >= {}", CLIENT_ROUTER_CONNECTIONS)};
|
||||
|
||||
client_router_connections = arg;
|
||||
});
|
||||
|
||||
conf.define_option<int>(
|
||||
"router",
|
||||
"min-connections",
|
||||
Default{minConnections},
|
||||
Deprecated,
|
||||
Comment{
|
||||
"Minimum number of routers lokinet will attempt to maintain connections to.",
|
||||
},
|
||||
[=](int arg) {
|
||||
if (arg < minConnections)
|
||||
throw std::invalid_argument{
|
||||
fmt::format("min-connections must be >= {}", minConnections)};
|
||||
|
||||
min_connected_routers = arg;
|
||||
[=](int) {
|
||||
log::warning(
|
||||
logcat, "Router min-connections is deprecated; use relay-connections for clients");
|
||||
});
|
||||
|
||||
int maxConnections =
|
||||
(params.is_relay ? DefaultMaxConnectionsForRouter : DefaultMaxConnectionsForClient);
|
||||
conf.define_option<int>(
|
||||
"router",
|
||||
"max-connections",
|
||||
Default{maxConnections},
|
||||
Deprecated,
|
||||
Comment{
|
||||
"Maximum number (hard limit) of routers lokinet will be connected to at any time.",
|
||||
},
|
||||
[=](int arg) {
|
||||
if (arg < maxConnections)
|
||||
throw std::invalid_argument{
|
||||
fmt::format("max-connections must be >= {}", maxConnections)};
|
||||
|
||||
max_connected_routers = arg;
|
||||
[=](int) {
|
||||
log::warning(
|
||||
logcat, "Router max-connections is deprecated; use relay-connections for clients");
|
||||
});
|
||||
|
||||
conf.define_option<std::string>("router", "nickname", Deprecated);
|
||||
|
@ -135,19 +132,7 @@ namespace llarp
|
|||
"this setting specifies the public IP at which this router is reachable. When",
|
||||
"provided the public-port option must also be specified.",
|
||||
},
|
||||
[this, net = params.Net_ptr()](std::string arg) {
|
||||
if (arg.empty())
|
||||
return;
|
||||
nuint32_t addr{};
|
||||
if (not addr.FromString(arg))
|
||||
throw std::invalid_argument{fmt::format("{} is not a valid IPv4 address", arg)};
|
||||
|
||||
if (net->IsBogonIP(addr))
|
||||
throw std::invalid_argument{
|
||||
fmt::format("{} is not a publicly routable ip address", addr)};
|
||||
|
||||
public_ip = addr;
|
||||
});
|
||||
[this](std::string arg) { public_ip = std::move(arg); });
|
||||
|
||||
conf.define_option<std::string>("router", "public-address", Hidden, [](std::string) {
|
||||
throw std::invalid_argument{
|
||||
|
@ -155,19 +140,18 @@ namespace llarp
|
|||
"[router]:public-port instead"};
|
||||
});
|
||||
|
||||
conf.define_option<int>(
|
||||
conf.define_option<uint16_t>(
|
||||
"router",
|
||||
"public-port",
|
||||
RelayOnly,
|
||||
Default{DefaultPublicPort},
|
||||
Comment{
|
||||
"When specifying public-ip=, this specifies the public UDP port at which this lokinet",
|
||||
"router is reachable. Required when public-ip is used.",
|
||||
},
|
||||
[this](int arg) {
|
||||
[this](uint16_t arg) {
|
||||
if (arg <= 0 || arg > std::numeric_limits<uint16_t>::max())
|
||||
throw std::invalid_argument("public-port must be >= 0 and <= 65536");
|
||||
public_port = ToNet(huint16_t{static_cast<uint16_t>(arg)});
|
||||
public_port = arg;
|
||||
});
|
||||
|
||||
conf.define_option<int>(
|
||||
|
@ -290,7 +274,7 @@ namespace llarp
|
|||
MultiValue,
|
||||
[this](std::string value) {
|
||||
RouterID router;
|
||||
if (not router.FromString(value))
|
||||
if (not router.from_string(value))
|
||||
throw std::invalid_argument{"bad snode value: " + value};
|
||||
if (not strict_connect.insert(router).second)
|
||||
throw std::invalid_argument{"duplicate strict connect snode: " + value};
|
||||
|
@ -710,7 +694,7 @@ namespace llarp
|
|||
},
|
||||
[this](std::string arg) {
|
||||
RouterID id;
|
||||
if (not id.FromString(arg))
|
||||
if (not id.from_string(arg))
|
||||
throw std::invalid_argument{fmt::format("Invalid RouterID: {}", arg)};
|
||||
|
||||
auto itr = snode_blacklist.emplace(std::move(id));
|
||||
|
@ -913,26 +897,38 @@ namespace llarp
|
|||
conf.define_option<std::string>(
|
||||
"bind",
|
||||
"public-ip",
|
||||
Hidden,
|
||||
RelayOnly,
|
||||
Comment{
|
||||
"The IP address to advertise to the network instead of the incoming= or auto-detected",
|
||||
"IP. This is typically required only when incoming= is used to listen on an internal",
|
||||
"private range IP address that received traffic forwarded from the public IP.",
|
||||
},
|
||||
[this](std::string_view arg) {
|
||||
SockAddr pubaddr{arg};
|
||||
public_addr = pubaddr.getIP();
|
||||
[this](std::string arg) {
|
||||
public_addr = std::move(arg);
|
||||
log::warning(
|
||||
logcat,
|
||||
"Using deprecated option; pass this value to [Router]:public-ip instead PLEASE");
|
||||
});
|
||||
|
||||
conf.define_option<uint16_t>(
|
||||
"bind",
|
||||
"public-port",
|
||||
Hidden,
|
||||
RelayOnly,
|
||||
Comment{
|
||||
"The port to advertise to the network instead of the incoming= (or default) port.",
|
||||
"This is typically required only when incoming= is used to listen on an internal",
|
||||
"private range IP address/port that received traffic forwarded from the public IP.",
|
||||
},
|
||||
[this](uint16_t arg) { public_port = net::port_t::from_host(arg); });
|
||||
[this](uint16_t arg) {
|
||||
if (arg <= 0 || arg > std::numeric_limits<uint16_t>::max())
|
||||
throw std::invalid_argument("public-port must be >= 0 and <= 65536");
|
||||
public_port = arg;
|
||||
log::warning(
|
||||
logcat,
|
||||
"Using deprecated option; pass this value to [Router]:public-port instead PLEASE");
|
||||
});
|
||||
|
||||
auto parse_addr_for_link = [net_ptr](const std::string& arg) {
|
||||
std::optional<oxen::quic::Address> maybe = std::nullopt;
|
||||
|
@ -965,14 +961,10 @@ namespace llarp
|
|||
throw std::invalid_argument{fmt::format("{} is a loopback address", arg)};
|
||||
}
|
||||
if (not maybe)
|
||||
{
|
||||
// infer public address
|
||||
if (auto maybe_ifname = net_ptr->GetBestNetIF())
|
||||
maybe = oxen::quic::Address{*maybe_ifname};
|
||||
}
|
||||
|
||||
if (maybe && maybe->port() == 0)
|
||||
maybe = oxen::quic::Address{maybe->host(), DEFAULT_LISTEN_PORT};
|
||||
maybe = net_ptr->get_best_public_address(true, DEFAULT_LISTEN_PORT);
|
||||
else if (maybe && maybe->port() == 0)
|
||||
maybe->set_port(DEFAULT_LISTEN_PORT);
|
||||
|
||||
return maybe;
|
||||
};
|
||||
|
@ -980,10 +972,7 @@ namespace llarp
|
|||
conf.define_option<std::string>(
|
||||
"bind",
|
||||
"listen",
|
||||
Required,
|
||||
Comment{
|
||||
"********** NEW API OPTION (see note) **********",
|
||||
"",
|
||||
"IP and/or port for lokinet to bind to for inbound/outbound connections.",
|
||||
"",
|
||||
"If IP is omitted then lokinet will search for a local network interface with a",
|
||||
|
@ -1007,11 +996,13 @@ namespace llarp
|
|||
},
|
||||
[this, parse_addr_for_link](const std::string& arg) {
|
||||
if (auto a = parse_addr_for_link(arg); a and a->is_addressable())
|
||||
addr = a;
|
||||
{
|
||||
listen_addr = *a;
|
||||
using_user_value = true;
|
||||
using_new_api = true;
|
||||
}
|
||||
else
|
||||
addr = oxen::quic::Address{""s, DEFAULT_LISTEN_PORT};
|
||||
|
||||
using_new_api = true;
|
||||
throw std::invalid_argument{"Could not parse listen address!"};
|
||||
});
|
||||
|
||||
conf.define_option<std::string>(
|
||||
|
@ -1020,86 +1011,22 @@ namespace llarp
|
|||
RelayOnly,
|
||||
MultiValue,
|
||||
Hidden,
|
||||
Comment{
|
||||
"********** DEPRECATED **********",
|
||||
"Note: the new API dictates the lokinet bind address through the 'listen' config",
|
||||
"parameter. Only ONE address will be read (no more lists of inbounds). Any address",
|
||||
"passed to `listen` will supersede the",
|
||||
"",
|
||||
"IP and/or port to listen on for incoming connections.",
|
||||
"",
|
||||
"If IP is omitted then lokinet will search for a local network interface with a",
|
||||
"public IP address and use that IP (and will exit with an error if no such IP is found",
|
||||
"on the system). If port is omitted then lokinet defaults to 1090.",
|
||||
"",
|
||||
"Examples:",
|
||||
" inbound=15.5.29.5:443",
|
||||
" inbound=10.0.2.2",
|
||||
" inbound=:1234",
|
||||
"",
|
||||
"Using a private range IP address (like the second example entry) will require using",
|
||||
"the public-ip= and public-port= to specify the public IP address at which this",
|
||||
"router can be reached.",
|
||||
},
|
||||
[this, parse_addr_for_link](const std::string& arg) {
|
||||
if (using_new_api)
|
||||
throw std::runtime_error{"USE THE NEW API -- SPECIFY LOCAL ADDRESS UNDER [LISTEN]"};
|
||||
|
||||
if (auto a = parse_addr_for_link(arg); a and a->is_addressable())
|
||||
addr = a;
|
||||
else
|
||||
addr = oxen::quic::Address{""s, DEFAULT_LISTEN_PORT};
|
||||
{
|
||||
log::warning(
|
||||
logcat,
|
||||
"Loaded address from deprecated [inbound] options; update your config to use "
|
||||
"[bind]:listen instead PLEASE");
|
||||
listen_addr = *a;
|
||||
using_user_value = true;
|
||||
}
|
||||
});
|
||||
|
||||
conf.define_option<std::string>(
|
||||
"bind",
|
||||
"outbound",
|
||||
MultiValue,
|
||||
params.is_relay ? Comment{
|
||||
"********** THIS PARAMETER IS DEPRECATED -- USE 'LISTEN' INSTEAD **********",
|
||||
"",
|
||||
"IP and/or port to use for outbound socket connections to other lokinet routers.",
|
||||
"",
|
||||
"If no outbound bind IP is configured, or the 0.0.0.0 wildcard IP is given, then",
|
||||
"lokinet will bind to the same IP being used for inbound connections (either an",
|
||||
"explicit inbound= provided IP, or the default). If no port is given, or port is",
|
||||
"given as 0, then a random high port will be used.",
|
||||
"",
|
||||
"If using multiple inbound= addresses then you *must* provide an explicit oubound= IP.",
|
||||
"",
|
||||
"Examples:",
|
||||
" outbound=1.2.3.4:5678",
|
||||
" outbound=:9000",
|
||||
" outbound=8.9.10.11",
|
||||
"",
|
||||
"The second example binds on the default incoming IP using port 9000; the third",
|
||||
"example binds on the given IP address using a random high port.",
|
||||
} : Comment{
|
||||
"********** DEPRECATED **********",
|
||||
"",
|
||||
"IP and/or port to use for outbound socket connections to lokinet routers.",
|
||||
"",
|
||||
"If no outbound bind IP is configured then lokinet will use a wildcard IP address",
|
||||
"(equivalent to specifying 0.0.0.0). If no port is given then a random high port",
|
||||
"will be used.",
|
||||
"",
|
||||
"Examples:",
|
||||
" outbound=1.2.3.4:5678",
|
||||
" outbound=:9000",
|
||||
" outbound=8.9.10.11",
|
||||
"",
|
||||
"The second example binds on the wildcard address using port 9000; the third example",
|
||||
"binds on the given IP address using a random high port.",
|
||||
},
|
||||
[this, parse_addr_for_link](const std::string& arg) {
|
||||
if (using_new_api)
|
||||
throw std::runtime_error{"USE THE NEW API -- SPECIFY LOCAL ADDRESS UNDER [LISTEN]"};
|
||||
|
||||
if (auto a = parse_addr_for_link(arg); a and a->is_addressable())
|
||||
addr = a;
|
||||
else
|
||||
addr = oxen::quic::Address{""s, DEFAULT_LISTEN_PORT};
|
||||
});
|
||||
conf.define_option<std::string>("bind", "outbound", MultiValue, Deprecated, Hidden);
|
||||
|
||||
conf.add_undeclared_handler(
|
||||
"bind", [this](std::string_view, std::string_view key, std::string_view val) {
|
||||
|
@ -1118,7 +1045,11 @@ namespace llarp
|
|||
// special case: wildcard for outbound
|
||||
if (key == "*")
|
||||
{
|
||||
addr = oxen::quic::Address{port};
|
||||
log::warning(
|
||||
logcat,
|
||||
"Wildcat address referencing port {} is referencing deprecated outbound config "
|
||||
"options; use [bind]:listen instead",
|
||||
port);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1137,16 +1068,17 @@ namespace llarp
|
|||
e.what())};
|
||||
}
|
||||
|
||||
if (temp.is_addressable())
|
||||
if (not temp.is_addressable())
|
||||
{
|
||||
addr = std::move(temp);
|
||||
return;
|
||||
throw std::runtime_error{fmt::format(
|
||||
"Invalid address: {}; stop using this deprecated handler, update your config to "
|
||||
"use "
|
||||
"[bind]:listen instead PLEASE",
|
||||
temp)};
|
||||
}
|
||||
|
||||
throw std::runtime_error{fmt::format(
|
||||
"Invalid address: {}; stop using this deprecated handler, update your config to use "
|
||||
"[bind]:listen instead PLEASE",
|
||||
temp)};
|
||||
listen_addr = std::move(temp);
|
||||
using_user_value = true;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1221,17 +1153,16 @@ namespace llarp
|
|||
LokidConfig::define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params)
|
||||
{
|
||||
(void)params;
|
||||
|
||||
conf.define_option<bool>("lokid", "enabled", RelayOnly, Deprecated);
|
||||
|
||||
conf.define_option<std::string>("lokid", "jsonrpc", RelayOnly, [](std::string arg) {
|
||||
if (arg.empty())
|
||||
return;
|
||||
throw std::invalid_argument(
|
||||
"the [lokid]:jsonrpc option is no longer supported; please use the [lokid]:rpc config "
|
||||
"option instead with oxend's lmq-local-control address -- typically a value such as "
|
||||
"rpc=ipc:///var/lib/oxen/oxend.sock or rpc=ipc:///home/snode/.oxen/oxend.sock");
|
||||
});
|
||||
conf.define_option<bool>(
|
||||
"lokid",
|
||||
"disable-testing",
|
||||
Default{false},
|
||||
Hidden,
|
||||
RelayOnly,
|
||||
Comment{
|
||||
"Development option: set to true to disable reachability testing when using ",
|
||||
"testnet"},
|
||||
assignment_acceptor(disable_testing));
|
||||
|
||||
conf.define_option<std::string>(
|
||||
"lokid",
|
||||
|
@ -1250,6 +1181,15 @@ namespace llarp
|
|||
[this](std::string arg) { rpc_addr = oxenmq::address(arg); });
|
||||
|
||||
// Deprecated options:
|
||||
conf.define_option<std::string>("lokid", "jsonrpc", RelayOnly, Hidden, [](std::string arg) {
|
||||
if (arg.empty())
|
||||
return;
|
||||
throw std::invalid_argument(
|
||||
"the [lokid]:jsonrpc option is no longer supported; please use the [lokid]:rpc config "
|
||||
"option instead with oxend's lmq-local-control address -- typically a value such as "
|
||||
"rpc=ipc:///var/lib/oxen/oxend.sock or rpc=ipc:///home/snode/.oxen/oxend.sock");
|
||||
});
|
||||
conf.define_option<bool>("lokid", "enabled", RelayOnly, Deprecated);
|
||||
conf.define_option<std::string>("lokid", "username", Deprecated);
|
||||
conf.define_option<std::string>("lokid", "password", Deprecated);
|
||||
conf.define_option<std::string>("lokid", "service-node-seed", Deprecated);
|
||||
|
|
|
@ -34,7 +34,9 @@ namespace llarp
|
|||
using SectionValues = llarp::ConfigParser::SectionValues;
|
||||
using ConfigMap = llarp::ConfigParser::ConfigMap;
|
||||
|
||||
inline static constexpr uint16_t DEFAULT_LISTEN_PORT{1090};
|
||||
inline const std::string QUAD_ZERO{"0.0.0.0"};
|
||||
inline constexpr uint16_t DEFAULT_LISTEN_PORT{1090};
|
||||
inline constexpr int CLIENT_ROUTER_CONNECTIONS = 4;
|
||||
|
||||
// TODO: don't use these maps. they're sloppy and difficult to follow
|
||||
/// Small struct to gather all parameters needed for config generation to reduce the number of
|
||||
|
@ -57,8 +59,7 @@ namespace llarp
|
|||
|
||||
struct RouterConfig
|
||||
{
|
||||
size_t min_connected_routers = 0;
|
||||
size_t max_connected_routers = 0;
|
||||
int client_router_connections{CLIENT_ROUTER_CONNECTIONS};
|
||||
|
||||
std::string net_id;
|
||||
|
||||
|
@ -77,10 +78,9 @@ namespace llarp
|
|||
std::string transkey_file;
|
||||
|
||||
bool is_relay = false;
|
||||
/// deprecated
|
||||
std::optional<net::ipaddr_t> public_ip;
|
||||
/// deprecated
|
||||
std::optional<net::port_t> public_port;
|
||||
|
||||
std::optional<std::string> public_ip;
|
||||
std::optional<uint16_t> public_port;
|
||||
|
||||
void
|
||||
define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params);
|
||||
|
@ -170,10 +170,14 @@ namespace llarp
|
|||
|
||||
struct LinksConfig
|
||||
{
|
||||
std::optional<net::ipaddr_t> public_addr;
|
||||
std::optional<net::port_t> public_port;
|
||||
// DEPRECATED -- use [Router]:public_addr
|
||||
std::optional<std::string> public_addr;
|
||||
// DEPRECATED -- use [Router]:public_port
|
||||
std::optional<uint16_t> public_port;
|
||||
|
||||
std::optional<oxen::quic::Address> addr;
|
||||
std::optional<oxen::quic::Address> listen_addr;
|
||||
|
||||
bool using_user_value = false;
|
||||
bool using_new_api = false;
|
||||
|
||||
void
|
||||
|
@ -202,6 +206,7 @@ namespace llarp
|
|||
{
|
||||
fs::path id_keyfile;
|
||||
oxenmq::address rpc_addr;
|
||||
bool disable_testing = true;
|
||||
|
||||
void
|
||||
define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params);
|
||||
|
|
|
@ -10,20 +10,20 @@
|
|||
|
||||
namespace llarp
|
||||
{
|
||||
KeyManager::KeyManager() : m_initialized(false), m_needBackup(false)
|
||||
KeyManager::KeyManager() : is_initialized(false), backup_keys(false)
|
||||
{}
|
||||
|
||||
bool
|
||||
KeyManager::initialize(const llarp::Config& config, bool genIfAbsent, bool isSNode)
|
||||
KeyManager::initialize(const llarp::Config& config, bool gen_if_absent, bool is_snode)
|
||||
{
|
||||
if (m_initialized)
|
||||
if (is_initialized)
|
||||
return false;
|
||||
|
||||
if (not isSNode)
|
||||
if (not is_snode)
|
||||
{
|
||||
crypto::identity_keygen(identityKey);
|
||||
crypto::encryption_keygen(encryptionKey);
|
||||
crypto::encryption_keygen(transportKey);
|
||||
crypto::identity_keygen(identity_key);
|
||||
crypto::encryption_keygen(encryption_key);
|
||||
crypto::encryption_keygen(transport_key);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -46,80 +46,87 @@ namespace llarp
|
|||
}
|
||||
};
|
||||
|
||||
m_rcPath = deriveFile(our_rc_filename, config.router.rc_file);
|
||||
m_idKeyPath = deriveFile(our_identity_filename, config.router.idkey_file);
|
||||
m_encKeyPath = deriveFile(our_enc_key_filename, config.router.enckey_file);
|
||||
m_transportKeyPath = deriveFile(our_transport_key_filename, config.router.transkey_file);
|
||||
rc_path = deriveFile(our_rc_filename, config.router.rc_file);
|
||||
idkey_path = deriveFile(our_identity_filename, config.router.idkey_file);
|
||||
enckey_path = deriveFile(our_enc_key_filename, config.router.enckey_file);
|
||||
transkey_path = deriveFile(our_transport_key_filename, config.router.transkey_file);
|
||||
|
||||
RemoteRC rc;
|
||||
bool exists = rc.read(m_rcPath);
|
||||
if (not exists and not genIfAbsent)
|
||||
{
|
||||
LogError("Could not read RouterContact at path ", m_rcPath);
|
||||
return false;
|
||||
}
|
||||
|
||||
// we need to back up keys if our self.signed doesn't appear to have a
|
||||
// valid signature
|
||||
m_needBackup = (isSNode and not rc.verify());
|
||||
|
||||
// if our RC file can't be verified, assume it is out of date (e.g. uses
|
||||
// older encryption) and needs to be regenerated. before doing so, backup
|
||||
// files that will be overwritten
|
||||
if (exists and m_needBackup)
|
||||
if (auto exists = rc.read(rc_path); not exists)
|
||||
{
|
||||
if (!genIfAbsent)
|
||||
if (not gen_if_absent)
|
||||
{
|
||||
LogError("Our RouterContact ", m_rcPath, " is invalid or out of date");
|
||||
log::error(logcat, "Could not read RC at path {}", rc_path);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
if (backup_keys = (is_snode and not rc.verify()); backup_keys)
|
||||
{
|
||||
LogWarn(
|
||||
"Our RouterContact ",
|
||||
m_rcPath,
|
||||
" seems out of date, backing up and regenerating private keys");
|
||||
auto err = "RC (path:{}) is invalid or out of date"_format(rc_path);
|
||||
|
||||
if (!backupKeyFilesByMoving())
|
||||
if (not gen_if_absent)
|
||||
{
|
||||
LogError(
|
||||
"Could not mv some key files, please ensure key files"
|
||||
" are backed up if needed and remove");
|
||||
log::error(logcat, err);
|
||||
return false;
|
||||
}
|
||||
|
||||
log::warning(logcat, "{}; backing up and regenerating private keys...", err);
|
||||
|
||||
if (not copy_backup_keyfiles())
|
||||
{
|
||||
log::error(logcat, "Failed to copy-backup key files");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (not config.router.is_relay)
|
||||
// load encryption key
|
||||
auto enckey_gen = [](llarp::SecretKey& key) { llarp::crypto::encryption_keygen(key); };
|
||||
if (not keygen(enckey_path, encryption_key, enckey_gen))
|
||||
{
|
||||
// load identity key or create if needed
|
||||
auto identityKeygen = [](llarp::SecretKey& key) {
|
||||
// TODO: handle generating from service node seed
|
||||
llarp::crypto::identity_keygen(key);
|
||||
};
|
||||
if (not loadOrCreateKey(m_idKeyPath, identityKey, identityKeygen))
|
||||
return false;
|
||||
log::critical(
|
||||
logcat, "KeyManager::keygen failed to generate encryption key line:{}", __LINE__);
|
||||
return false;
|
||||
}
|
||||
|
||||
// load encryption key
|
||||
auto encryptionKeygen = [](llarp::SecretKey& key) { llarp::crypto::encryption_keygen(key); };
|
||||
if (not loadOrCreateKey(m_encKeyPath, encryptionKey, encryptionKeygen))
|
||||
return false;
|
||||
|
||||
// TODO: transport key (currently done in LinkLayer)
|
||||
auto transportKeygen = [](llarp::SecretKey& key) {
|
||||
auto transkey_gen = [](llarp::SecretKey& key) {
|
||||
key.Zero();
|
||||
crypto::encryption_keygen(key);
|
||||
};
|
||||
if (not loadOrCreateKey(m_transportKeyPath, transportKey, transportKeygen))
|
||||
return false;
|
||||
|
||||
m_initialized = true;
|
||||
if (not keygen(transkey_path, transport_key, transkey_gen))
|
||||
{
|
||||
log::critical(
|
||||
logcat, "KeyManager::keygen failed to generate transport key line:{}", __LINE__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (not config.router.is_relay)
|
||||
{
|
||||
// load identity key or create if needed
|
||||
auto idkey_gen = [](llarp::SecretKey& key) {
|
||||
// TODO: handle generating from service node seed
|
||||
llarp::crypto::identity_keygen(key);
|
||||
};
|
||||
|
||||
if (not keygen(idkey_path, identity_key, idkey_gen))
|
||||
{
|
||||
log::critical(
|
||||
logcat, "KeyManager::keygen failed to generate identity key line:{}", __LINE__);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
is_initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
KeyManager::backupFileByMoving(const fs::path& filepath)
|
||||
KeyManager::copy_backup_keyfile(const fs::path& filepath)
|
||||
{
|
||||
auto findFreeBackupFilename = [](const fs::path& filepath) {
|
||||
for (int i = 0; i < 9; i++)
|
||||
|
@ -136,6 +143,7 @@ namespace llarp
|
|||
|
||||
std::error_code ec;
|
||||
bool exists = fs::exists(filepath, ec);
|
||||
|
||||
if (ec)
|
||||
{
|
||||
LogError("Could not determine status of file ", filepath, ": ", ec.message());
|
||||
|
@ -168,13 +176,13 @@ namespace llarp
|
|||
}
|
||||
|
||||
bool
|
||||
KeyManager::backupKeyFilesByMoving() const
|
||||
KeyManager::copy_backup_keyfiles() const
|
||||
{
|
||||
std::vector<fs::path> files = {m_rcPath, m_idKeyPath, m_encKeyPath, m_transportKeyPath};
|
||||
std::vector<fs::path> files = {rc_path, idkey_path, enckey_path, transkey_path};
|
||||
|
||||
for (auto& filepath : files)
|
||||
{
|
||||
if (not backupFileByMoving(filepath))
|
||||
if (not copy_backup_keyfile(filepath))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -182,7 +190,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
bool
|
||||
KeyManager::loadOrCreateKey(
|
||||
KeyManager::keygen(
|
||||
fs::path path, llarp::SecretKey& key, std::function<void(llarp::SecretKey& key)> keygen)
|
||||
{
|
||||
if (not fs::exists(path))
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace llarp
|
|||
/// @param filepath is the name of the original file to backup.
|
||||
/// @return true if the file could be moved or didn't exist, false otherwise
|
||||
static bool
|
||||
backupFileByMoving(const fs::path& filepath);
|
||||
copy_backup_keyfile(const fs::path& filepath);
|
||||
|
||||
/// Constructor
|
||||
KeyManager();
|
||||
|
@ -52,37 +52,37 @@ namespace llarp
|
|||
/// @param rc (out) will be modified to contian the RouterContact
|
||||
/// @return true on success, false otherwise
|
||||
bool
|
||||
getRouterContact(llarp::RouterContact& rc) const;
|
||||
gen_rc(llarp::RouterContact& rc) const;
|
||||
|
||||
/// Return whether or not we need to backup keys as we load them
|
||||
bool
|
||||
needBackup() const
|
||||
needs_backup() const
|
||||
{
|
||||
return m_needBackup;
|
||||
return backup_keys;
|
||||
}
|
||||
|
||||
llarp::SecretKey identityKey;
|
||||
llarp::SecretKey encryptionKey;
|
||||
llarp::SecretKey transportKey;
|
||||
llarp::SecretKey identity_key;
|
||||
llarp::SecretKey encryption_key;
|
||||
llarp::SecretKey transport_key;
|
||||
|
||||
fs::path m_rcPath;
|
||||
fs::path m_idKeyPath;
|
||||
fs::path m_encKeyPath;
|
||||
fs::path m_transportKeyPath;
|
||||
fs::path rc_path;
|
||||
fs::path idkey_path;
|
||||
fs::path enckey_path;
|
||||
fs::path transkey_path;
|
||||
|
||||
private:
|
||||
std::atomic_bool m_initialized;
|
||||
std::atomic_bool m_needBackup;
|
||||
std::atomic_bool is_initialized;
|
||||
std::atomic_bool backup_keys;
|
||||
|
||||
/// Backup each key file (by copying, e.g. foo -> foo.bak)
|
||||
bool
|
||||
backupKeyFilesByMoving() const;
|
||||
copy_backup_keyfiles() const;
|
||||
|
||||
/// Load the key at a given filepath or create it
|
||||
///
|
||||
/// @param keygen is a function that will generate the key if needed
|
||||
static bool
|
||||
loadOrCreateKey(
|
||||
keygen(
|
||||
fs::path filepath,
|
||||
llarp::SecretKey& key,
|
||||
std::function<void(llarp::SecretKey& key)> keygen);
|
||||
|
|
|
@ -82,29 +82,34 @@ namespace llarp::consensus
|
|||
|
||||
// Pull the next element off the queue, but skip ourself, any that are no longer registered, and
|
||||
// any that are currently known to be failing (those are queued for testing separately).
|
||||
RouterID my_pk{router->pubkey()};
|
||||
auto local_pk = router->local_rid();
|
||||
|
||||
while (!testing_queue.empty())
|
||||
{
|
||||
auto& pk = testing_queue.back();
|
||||
std::optional<RouterID> sn;
|
||||
if (pk != my_pk && !failing.count(pk))
|
||||
|
||||
if (pk != local_pk && !failing.count(pk))
|
||||
sn = pk;
|
||||
|
||||
testing_queue.pop_back();
|
||||
|
||||
if (sn)
|
||||
return sn;
|
||||
}
|
||||
|
||||
if (!requeue)
|
||||
return std::nullopt;
|
||||
|
||||
// FIXME: when a *new* node comes online we need to inject it into a random position in the SN
|
||||
// list with probability (L/N) [L = current list size, N = potential list size]
|
||||
//
|
||||
// (FIXME: put this FIXME in a better place ;-) )
|
||||
|
||||
// We exhausted the queue so repopulate it and try again
|
||||
|
||||
testing_queue.clear();
|
||||
const auto all = router->get_whitelist();
|
||||
const auto& all = router->get_whitelist();
|
||||
|
||||
testing_queue.insert(testing_queue.begin(), all.begin(), all.end());
|
||||
|
||||
std::shuffle(testing_queue.begin(), testing_queue.end(), llarp::csrng);
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
namespace llarp
|
||||
{
|
||||
// clang-format off
|
||||
const std::array<uint16_t, 3> LOKINET_VERSION{{@lokinet_VERSION_MAJOR@, @lokinet_VERSION_MINOR@, @lokinet_VERSION_PATCH@}};
|
||||
const std::array<uint8_t, 3> LOKINET_VERSION{{@lokinet_VERSION_MAJOR@, @lokinet_VERSION_MINOR@, @lokinet_VERSION_PATCH@}};
|
||||
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_RELEASE_MOTTO = "@RELEASE_MOTTO@";
|
||||
const char* const LOKINET_DEFAULT_NETID = "lokinet";
|
||||
const char* const LOKINET_TESTNET_NETID = "testnet";
|
||||
// clang-format on
|
||||
} // namespace llarp
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
namespace llarp
|
||||
{
|
||||
// Given a full lokinet version of: lokinet-1.2.3-abc these are:
|
||||
extern const std::array<uint16_t, 3> LOKINET_VERSION;
|
||||
extern const std::array<uint8_t, 3> LOKINET_VERSION;
|
||||
extern const char* const LOKINET_VERSION_TAG;
|
||||
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_TESTNET_NETID;
|
||||
} // namespace llarp
|
||||
|
|
|
@ -57,8 +57,7 @@ namespace llarp
|
|||
throw std::runtime_error("Cannot call Setup() on context without a Config");
|
||||
|
||||
if (opts.showBanner)
|
||||
llarp::LogInfo(
|
||||
fmt::format("{} {}", llarp::LOKINET_VERSION_FULL, llarp::LOKINET_RELEASE_MOTTO));
|
||||
llarp::LogInfo(fmt::format("{}", llarp::LOKINET_VERSION_FULL));
|
||||
|
||||
if (!loop)
|
||||
{
|
||||
|
|
|
@ -32,9 +32,11 @@ namespace llarp
|
|||
std::string
|
||||
ToString() const;
|
||||
|
||||
// FIXME: this is deceptively named: it should be "from_hex" since that's what it does.
|
||||
bool
|
||||
FromString(const std::string& str);
|
||||
|
||||
// FIXME: this is deceptively named: it should be "from_hex" since that's what it does.
|
||||
static PubKey
|
||||
from_string(const std::string& s);
|
||||
|
||||
|
|
|
@ -13,19 +13,19 @@ namespace llarp::exit
|
|||
Context::Tick(llarp_time_t now)
|
||||
{
|
||||
{
|
||||
auto itr = m_Exits.begin();
|
||||
while (itr != m_Exits.end())
|
||||
auto itr = _exits.begin();
|
||||
while (itr != _exits.end())
|
||||
{
|
||||
itr->second->Tick(now);
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
{
|
||||
auto itr = m_Closed.begin();
|
||||
while (itr != m_Closed.end())
|
||||
auto itr = _closed.begin();
|
||||
while (itr != _closed.end())
|
||||
{
|
||||
if ((*itr)->ShouldRemove())
|
||||
itr = m_Closed.erase(itr);
|
||||
itr = _closed.erase(itr);
|
||||
else
|
||||
++itr;
|
||||
}
|
||||
|
@ -33,14 +33,14 @@ namespace llarp::exit
|
|||
}
|
||||
|
||||
void
|
||||
Context::Stop()
|
||||
Context::stop()
|
||||
{
|
||||
auto itr = m_Exits.begin();
|
||||
while (itr != m_Exits.end())
|
||||
auto itr = _exits.begin();
|
||||
while (itr != _exits.end())
|
||||
{
|
||||
itr->second->Stop();
|
||||
m_Closed.emplace_back(std::move(itr->second));
|
||||
itr = m_Exits.erase(itr);
|
||||
_closed.emplace_back(std::move(itr->second));
|
||||
itr = _exits.erase(itr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,8 +48,8 @@ namespace llarp::exit
|
|||
Context::ExtractStatus() const
|
||||
{
|
||||
util::StatusObject obj{};
|
||||
auto itr = m_Exits.begin();
|
||||
while (itr != m_Exits.end())
|
||||
auto itr = _exits.begin();
|
||||
while (itr != _exits.end())
|
||||
{
|
||||
obj[itr->first] = itr->second->ExtractStatus();
|
||||
++itr;
|
||||
|
@ -58,10 +58,10 @@ namespace llarp::exit
|
|||
}
|
||||
|
||||
void
|
||||
Context::CalculateExitTraffic(TrafficStats& stats)
|
||||
Context::calculate_exit_traffic(TrafficStats& stats)
|
||||
{
|
||||
auto itr = m_Exits.begin();
|
||||
while (itr != m_Exits.end())
|
||||
auto itr = _exits.begin();
|
||||
while (itr != _exits.end())
|
||||
{
|
||||
itr->second->CalculateTrafficStats(stats);
|
||||
++itr;
|
||||
|
@ -69,10 +69,10 @@ namespace llarp::exit
|
|||
}
|
||||
|
||||
exit::Endpoint*
|
||||
Context::FindEndpointForPath(const PathID_t& path) const
|
||||
Context::find_endpoint_for_path(const PathID_t& path) const
|
||||
{
|
||||
auto itr = m_Exits.begin();
|
||||
while (itr != m_Exits.end())
|
||||
auto itr = _exits.begin();
|
||||
while (itr != _exits.end())
|
||||
{
|
||||
auto ep = itr->second->FindEndpointByPath(path);
|
||||
if (ep)
|
||||
|
@ -83,10 +83,10 @@ namespace llarp::exit
|
|||
}
|
||||
|
||||
bool
|
||||
Context::ObtainNewExit(const PubKey& pk, const PathID_t& path, bool permitInternet)
|
||||
Context::obtain_new_exit(const PubKey& pk, const PathID_t& path, bool permitInternet)
|
||||
{
|
||||
auto itr = m_Exits.begin();
|
||||
while (itr != m_Exits.end())
|
||||
auto itr = _exits.begin();
|
||||
while (itr != _exits.end())
|
||||
{
|
||||
if (itr->second->AllocateNewExit(pk, path, permitInternet))
|
||||
return true;
|
||||
|
@ -96,9 +96,9 @@ namespace llarp::exit
|
|||
}
|
||||
|
||||
std::shared_ptr<handlers::ExitEndpoint>
|
||||
Context::GetExitEndpoint(std::string name) const
|
||||
Context::get_exit_endpoint(std::string name) const
|
||||
{
|
||||
if (auto itr = m_Exits.find(name); itr != m_Exits.end())
|
||||
if (auto itr = _exits.find(name); itr != _exits.end())
|
||||
{
|
||||
return itr->second;
|
||||
}
|
||||
|
@ -106,10 +106,10 @@ namespace llarp::exit
|
|||
}
|
||||
|
||||
void
|
||||
Context::AddExitEndpoint(
|
||||
Context::add_exit_endpoint(
|
||||
const std::string& name, const NetworkConfig& networkConfig, const DnsConfig& dnsConfig)
|
||||
{
|
||||
if (m_Exits.find(name) != m_Exits.end())
|
||||
if (_exits.find(name) != _exits.end())
|
||||
throw std::invalid_argument{fmt::format("An exit with name {} already exists", name)};
|
||||
|
||||
auto endpoint = std::make_unique<handlers::ExitEndpoint>(name, router);
|
||||
|
@ -119,7 +119,7 @@ namespace llarp::exit
|
|||
if (!endpoint->Start())
|
||||
throw std::runtime_error{fmt::format("Failed to start endpoint {}", name)};
|
||||
|
||||
m_Exits.emplace(name, std::move(endpoint));
|
||||
_exits.emplace(name, std::move(endpoint));
|
||||
}
|
||||
|
||||
} // namespace llarp::exit
|
||||
|
|
|
@ -18,37 +18,37 @@ namespace llarp::exit
|
|||
Tick(llarp_time_t now);
|
||||
|
||||
void
|
||||
ClearAllEndpoints();
|
||||
clear_all_endpoints();
|
||||
|
||||
util::StatusObject
|
||||
ExtractStatus() const;
|
||||
|
||||
/// send close to all exit sessions and remove all sessions
|
||||
void
|
||||
Stop();
|
||||
stop();
|
||||
|
||||
void
|
||||
AddExitEndpoint(
|
||||
add_exit_endpoint(
|
||||
const std::string& name, const NetworkConfig& networkConfig, const DnsConfig& dnsConfig);
|
||||
|
||||
bool
|
||||
ObtainNewExit(const PubKey& remote, const PathID_t& path, bool permitInternet);
|
||||
obtain_new_exit(const PubKey& remote, const PathID_t& path, bool permitInternet);
|
||||
|
||||
exit::Endpoint*
|
||||
FindEndpointForPath(const PathID_t& path) const;
|
||||
find_endpoint_for_path(const PathID_t& path) const;
|
||||
|
||||
/// calculate (pk, tx, rx) for all exit traffic
|
||||
using TrafficStats = std::unordered_map<PubKey, std::pair<uint64_t, uint64_t>>;
|
||||
|
||||
void
|
||||
CalculateExitTraffic(TrafficStats& stats);
|
||||
calculate_exit_traffic(TrafficStats& stats);
|
||||
|
||||
std::shared_ptr<handlers::ExitEndpoint>
|
||||
GetExitEndpoint(std::string name) const;
|
||||
get_exit_endpoint(std::string name) const;
|
||||
|
||||
private:
|
||||
Router* router;
|
||||
std::unordered_map<std::string, std::shared_ptr<handlers::ExitEndpoint>> m_Exits;
|
||||
std::list<std::shared_ptr<handlers::ExitEndpoint>> m_Closed;
|
||||
std::unordered_map<std::string, std::shared_ptr<handlers::ExitEndpoint>> _exits;
|
||||
std::list<std::shared_ptr<handlers::ExitEndpoint>> _closed;
|
||||
};
|
||||
} // namespace llarp::exit
|
||||
|
|
|
@ -281,7 +281,7 @@ namespace llarp::handlers
|
|||
}
|
||||
// forward dns for snode
|
||||
RouterID r;
|
||||
if (r.FromString(msg.questions[0].Name()))
|
||||
if (r.from_string(msg.questions[0].Name()))
|
||||
{
|
||||
huint128_t ip;
|
||||
PubKey pubKey(r);
|
||||
|
|
|
@ -535,7 +535,7 @@ namespace llarp::handlers
|
|||
if (auto saddr = service::Address(); saddr.FromString(name))
|
||||
ReplyToLokiDNSWhenReady(saddr, msg, isV6);
|
||||
|
||||
if (auto rid = RouterID(); rid.FromString(name))
|
||||
if (auto rid = RouterID(); rid.from_string(name))
|
||||
ReplyToSNodeDNSWhenReady(rid, msg, isV6);
|
||||
};
|
||||
|
||||
|
@ -568,7 +568,7 @@ namespace llarp::handlers
|
|||
if (not qname)
|
||||
return false;
|
||||
RouterID addr;
|
||||
if (not addr.FromString(*qname))
|
||||
if (not addr.from_string(*qname))
|
||||
return false;
|
||||
auto replyMsg = std::make_shared<dns::Message>(clear_dns_message(msg));
|
||||
return ReplyToSNodeDNSWhenReady(addr, std::move(replyMsg), false);
|
||||
|
@ -604,7 +604,7 @@ namespace llarp::handlers
|
|||
if (msg.questions[0].qtype == dns::qTypeTXT)
|
||||
{
|
||||
RouterID snode;
|
||||
if (snode.FromString(qname))
|
||||
if (snode.from_string(qname))
|
||||
{
|
||||
if (auto rc = router()->node_db()->get_rc(snode))
|
||||
msg.AddTXTReply(std::string{rc->view()});
|
||||
|
|
|
@ -3,10 +3,9 @@
|
|||
namespace llarp::link
|
||||
{
|
||||
Connection::Connection(
|
||||
std::shared_ptr<oxen::quic::connection_interface>& c,
|
||||
std::shared_ptr<oxen::quic::BTRequestStream>& s,
|
||||
const RemoteRC& rc)
|
||||
: conn{c}, control_stream{s}, remote_rc{std::move(rc)}
|
||||
const std::shared_ptr<oxen::quic::connection_interface>& c,
|
||||
std::shared_ptr<oxen::quic::BTRequestStream>& s)
|
||||
: conn{c}, control_stream{s} /* , remote_rc{std::move(rc)} */
|
||||
{}
|
||||
|
||||
} // namespace llarp::link
|
||||
|
|
|
@ -11,16 +11,14 @@ namespace llarp::link
|
|||
{
|
||||
std::shared_ptr<oxen::quic::connection_interface> conn;
|
||||
std::shared_ptr<oxen::quic::BTRequestStream> control_stream;
|
||||
RemoteRC remote_rc;
|
||||
|
||||
// one side of a connection will be responsible for some things, e.g. heartbeat
|
||||
bool inbound{false};
|
||||
bool remote_is_relay{true};
|
||||
|
||||
Connection(
|
||||
std::shared_ptr<oxen::quic::connection_interface>& c,
|
||||
std::shared_ptr<oxen::quic::BTRequestStream>& s,
|
||||
const RemoteRC& rc);
|
||||
const std::shared_ptr<oxen::quic::connection_interface>& c,
|
||||
std::shared_ptr<oxen::quic::BTRequestStream>& s);
|
||||
};
|
||||
} // namespace llarp::link
|
||||
|
||||
|
|
|
@ -5,82 +5,38 @@
|
|||
|
||||
namespace llarp
|
||||
{
|
||||
Contacts::Contacts(const dht::Key_t& k, Router& r) : _local_key{k}, _router{r}
|
||||
Contacts::Contacts(Router& r) : _router{r}, _local_key{r.pubkey()}
|
||||
{
|
||||
timer_keepalive = std::make_shared<int>(0);
|
||||
_router.loop()->call_every(1s, timer_keepalive, [this]() { on_clean_contacts(); });
|
||||
|
||||
_rc_nodes = std::make_unique<dht::Bucket<dht::RCNode>>(_local_key, llarp::randint);
|
||||
_introset_nodes = std::make_unique<dht::Bucket<dht::ISNode>>(_local_key, llarp::randint);
|
||||
}
|
||||
|
||||
std::optional<service::EncryptedIntroSet>
|
||||
Contacts::get_introset_by_location(const dht::Key_t& key) const
|
||||
{
|
||||
return _router.loop()->call_get([this, key]() -> std::optional<service::EncryptedIntroSet> {
|
||||
auto& introsets = _introset_nodes->nodes;
|
||||
std::optional<service::EncryptedIntroSet> enc = std::nullopt;
|
||||
|
||||
if (auto itr = introsets.find(key); itr != introsets.end())
|
||||
return itr->second.introset;
|
||||
auto& introsets = _introset_nodes->nodes;
|
||||
|
||||
return std::nullopt;
|
||||
});
|
||||
}
|
||||
if (auto itr = introsets.find(key); itr != introsets.end())
|
||||
enc = itr->second.introset;
|
||||
|
||||
void
|
||||
Contacts::on_clean_contacts()
|
||||
{
|
||||
const auto now = llarp::time_now_ms();
|
||||
|
||||
if (_rc_nodes)
|
||||
{
|
||||
auto& nodes = _rc_nodes->nodes;
|
||||
auto itr = nodes.begin();
|
||||
|
||||
while (itr != nodes.end())
|
||||
{
|
||||
if (itr->second.rc.is_expired(now))
|
||||
itr = nodes.erase(itr);
|
||||
else
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
|
||||
if (_introset_nodes)
|
||||
{
|
||||
auto& svcs = _introset_nodes->nodes;
|
||||
auto itr = svcs.begin();
|
||||
|
||||
while (itr != svcs.end())
|
||||
{
|
||||
if (itr->second.introset.IsExpired(now))
|
||||
itr = svcs.erase(itr);
|
||||
else
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
return enc;
|
||||
}
|
||||
|
||||
util::StatusObject
|
||||
Contacts::ExtractStatus() const
|
||||
{
|
||||
util::StatusObject obj{
|
||||
{"nodes", _rc_nodes->ExtractStatus()},
|
||||
{"services", _introset_nodes->ExtractStatus()},
|
||||
{"local_key", _local_key.ToHex()}};
|
||||
{"services", _introset_nodes->ExtractStatus()}, {"local_key", _local_key.ToHex()}};
|
||||
return obj;
|
||||
}
|
||||
|
||||
void
|
||||
Contacts::put_rc_node_async(const dht::RCNode& val)
|
||||
Contacts::put_intro(service::EncryptedIntroSet enc)
|
||||
{
|
||||
_router.loop()->call([this, val]() { _rc_nodes->PutNode(val); });
|
||||
}
|
||||
|
||||
void
|
||||
Contacts::delete_rc_node_async(const dht::Key_t& val)
|
||||
{
|
||||
_router.loop()->call([this, val]() { _rc_nodes->DelNode(val); });
|
||||
_introset_nodes->PutNode(std::move(enc));
|
||||
}
|
||||
|
||||
} // namespace llarp
|
||||
|
|
|
@ -15,28 +15,14 @@ namespace llarp
|
|||
private:
|
||||
// TODO: why was this a shared ptr in the original implementation? revisit this
|
||||
std::shared_ptr<int> timer_keepalive;
|
||||
const dht::Key_t& _local_key;
|
||||
Router& _router;
|
||||
std::atomic<bool> transit_allowed{false};
|
||||
const dht::Key_t _local_key;
|
||||
|
||||
// holds router contacts
|
||||
std::unique_ptr<dht::Bucket<dht::RCNode>> _rc_nodes;
|
||||
// holds introsets for remote services
|
||||
std::unique_ptr<dht::Bucket<dht::ISNode>> _introset_nodes;
|
||||
|
||||
public:
|
||||
Contacts(const dht::Key_t& local, Router& r);
|
||||
|
||||
/// Sets the value of transit_allowed to the value of `b`. Returns false if the
|
||||
/// value was already b, true otherwise
|
||||
bool
|
||||
set_transit_allowed(bool b)
|
||||
{
|
||||
return not transit_allowed.exchange(b) == b;
|
||||
}
|
||||
|
||||
void
|
||||
on_clean_contacts();
|
||||
Contacts(Router& r);
|
||||
|
||||
std::optional<service::EncryptedIntroSet>
|
||||
get_introset_by_location(const dht::Key_t& key) const;
|
||||
|
@ -46,16 +32,7 @@ namespace llarp
|
|||
ExtractStatus() const;
|
||||
|
||||
void
|
||||
put_rc_node_async(const dht::RCNode& val);
|
||||
|
||||
void
|
||||
delete_rc_node_async(const dht::Key_t& val);
|
||||
|
||||
dht::Bucket<dht::RCNode>*
|
||||
rc_nodes() const
|
||||
{
|
||||
return _rc_nodes.get();
|
||||
}
|
||||
put_intro(service::EncryptedIntroSet enc);
|
||||
|
||||
dht::Bucket<dht::ISNode>*
|
||||
services() const
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -28,6 +28,11 @@ namespace llarp
|
|||
struct LinkManager;
|
||||
class NodeDB;
|
||||
|
||||
using conn_open_hook = oxen::quic::connection_established_callback;
|
||||
using conn_closed_hook = oxen::quic::connection_closed_callback;
|
||||
using stream_open_hook = oxen::quic::stream_open_callback;
|
||||
using stream_closed_hook = oxen::quic::stream_close_callback;
|
||||
|
||||
namespace link
|
||||
{
|
||||
struct Connection;
|
||||
|
@ -43,9 +48,12 @@ namespace llarp
|
|||
|
||||
// for outgoing packets, we route via RouterID; map RouterID->Connection
|
||||
// for incoming packets, we get a ConnectionID; map ConnectionID->RouterID
|
||||
std::unordered_map<RouterID, std::shared_ptr<link::Connection>> conns;
|
||||
std::unordered_map<RouterID, std::shared_ptr<link::Connection>> active_conns;
|
||||
std::unordered_map<oxen::quic::ConnectionID, RouterID> connid_map;
|
||||
|
||||
// for pending connections, cleared in LinkManager::on_conn_open
|
||||
std::unordered_map<RouterID, std::shared_ptr<link::Connection>> pending_conns;
|
||||
|
||||
// TODO: see which of these is actually useful and delete the other
|
||||
std::shared_ptr<link::Connection>
|
||||
get_conn(const RemoteRC&) const;
|
||||
|
@ -56,9 +64,6 @@ namespace llarp
|
|||
bool
|
||||
have_conn(const RouterID& remote, bool client_only) const;
|
||||
|
||||
bool
|
||||
deregister_peer(RouterID remote);
|
||||
|
||||
size_t
|
||||
num_connected(bool clients_only) const;
|
||||
|
||||
|
@ -107,27 +112,18 @@ namespace llarp
|
|||
struct PendingMessage
|
||||
{
|
||||
std::string body;
|
||||
std::optional<std::string> endpoint = std::nullopt;
|
||||
std::function<void(oxen::quic::message)> func = nullptr;
|
||||
|
||||
RouterID rid;
|
||||
bool is_control{false};
|
||||
bool is_control = false;
|
||||
|
||||
PendingMessage(std::string b, bool control = false) : body{std::move(b)}, is_control{control}
|
||||
PendingMessage(std::string b) : body{std::move(b)}
|
||||
{}
|
||||
};
|
||||
|
||||
struct PendingDataMessage : PendingMessage
|
||||
{
|
||||
PendingDataMessage(std::string b) : PendingMessage(b)
|
||||
{}
|
||||
};
|
||||
|
||||
struct PendingControlMessage : PendingMessage
|
||||
{
|
||||
std::string endpoint;
|
||||
std::function<void(oxen::quic::message)> func;
|
||||
|
||||
PendingControlMessage(
|
||||
std::string b, std::string e, std::function<void(oxen::quic::message)> f = nullptr)
|
||||
: PendingMessage(b, true), endpoint{std::move(e)}, func{std::move(f)}
|
||||
PendingMessage(
|
||||
std::string b, std::string ep, std::function<void(oxen::quic::message)> f = nullptr)
|
||||
: body{std::move(b)}, endpoint{std::move(ep)}, func{std::move(f)}, is_control{true}
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -138,7 +134,8 @@ namespace llarp
|
|||
struct LinkManager
|
||||
{
|
||||
public:
|
||||
explicit LinkManager(Router& r);
|
||||
static std::unique_ptr<LinkManager>
|
||||
make(Router& r);
|
||||
|
||||
bool
|
||||
send_control_message(
|
||||
|
@ -157,6 +154,8 @@ namespace llarp
|
|||
}
|
||||
|
||||
private:
|
||||
explicit LinkManager(Router& r);
|
||||
|
||||
bool
|
||||
send_control_message_impl(
|
||||
const RouterID& remote,
|
||||
|
@ -173,6 +172,12 @@ namespace llarp
|
|||
|
||||
// holds any messages we attempt to send while connections are establishing
|
||||
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 outbound 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};
|
||||
|
||||
|
@ -195,6 +200,9 @@ namespace llarp
|
|||
void
|
||||
recv_control_message(oxen::quic::message msg);
|
||||
|
||||
void
|
||||
on_inbound_conn(oxen::quic::connection_interface& ci);
|
||||
|
||||
void
|
||||
on_conn_open(oxen::quic::connection_interface& ci);
|
||||
|
||||
|
@ -227,17 +235,30 @@ namespace llarp
|
|||
handle_gossip_rc(oxen::quic::message m);
|
||||
|
||||
void
|
||||
fetch_rcs(const RouterID& source, rc_time since, const std::vector<RouterID>& explicit_ids);
|
||||
fetch_rcs(
|
||||
const RouterID& source,
|
||||
std::string payload,
|
||||
std::function<void(oxen::quic::message m)> func);
|
||||
|
||||
void
|
||||
handle_fetch_rcs(oxen::quic::message m);
|
||||
|
||||
void
|
||||
fetch_router_ids(const RouterID& source);
|
||||
fetch_router_ids(
|
||||
const RouterID& via, std::string payload, std::function<void(oxen::quic::message m)> func);
|
||||
|
||||
void
|
||||
handle_fetch_router_ids(oxen::quic::message m);
|
||||
|
||||
void
|
||||
fetch_bootstrap_rcs(
|
||||
const RemoteRC& source,
|
||||
std::string payload,
|
||||
std::function<void(oxen::quic::message m)> func);
|
||||
|
||||
void
|
||||
handle_fetch_bootstrap_rcs(oxen::quic::message m);
|
||||
|
||||
bool
|
||||
have_connection_to(const RouterID& remote, bool client_only = false) const;
|
||||
|
||||
|
@ -245,13 +266,13 @@ namespace llarp
|
|||
have_client_connection_to(const RouterID& remote) const;
|
||||
|
||||
void
|
||||
deregister_peer(RouterID remote);
|
||||
test_reachability(const RouterID& rid, conn_open_hook, conn_closed_hook);
|
||||
|
||||
void
|
||||
connect_to(const RouterID& router);
|
||||
connect_to(const RouterID& router, conn_open_hook = nullptr);
|
||||
|
||||
void
|
||||
connect_to(const RemoteRC& rc);
|
||||
connect_to(const RemoteRC& rc, conn_open_hook = nullptr, conn_closed_hook = nullptr);
|
||||
|
||||
void
|
||||
close_connection(RouterID rid);
|
||||
|
@ -291,11 +312,8 @@ namespace llarp
|
|||
void
|
||||
connect_to_random(int num_conns);
|
||||
|
||||
// TODO: tune these (maybe even remove max?) now that we're switching to quic
|
||||
/// always maintain this many connections to other routers
|
||||
size_t min_connected_routers = 4;
|
||||
/// hard upperbound limit on the number of router to router connections
|
||||
size_t max_connected_routers = 6;
|
||||
/// always maintain this many client connections to other routers
|
||||
int client_router_connections = 4;
|
||||
|
||||
private:
|
||||
// DHT messages
|
||||
|
@ -330,18 +348,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)>
|
||||
|
@ -389,17 +398,28 @@ namespace llarp
|
|||
{
|
||||
try
|
||||
{
|
||||
const auto& rid = rc.router_id();
|
||||
log::critical(logcat, "Establishing connection to RID:{}", rid);
|
||||
|
||||
auto conn_interface =
|
||||
endpoint->connect(remote, link_manager.tls_creds, std::forward<Opt>(opts)...);
|
||||
|
||||
// emplace immediately for connection open callback to find scid
|
||||
connid_map.emplace(conn_interface->scid(), rc.router_id());
|
||||
auto [itr, b] = conns.emplace(rc.router_id(), nullptr);
|
||||
// add to pending conns
|
||||
auto [itr, b] = pending_conns.emplace(rid, nullptr);
|
||||
|
||||
auto control_stream =
|
||||
conn_interface->template get_new_stream<oxen::quic::BTRequestStream>();
|
||||
itr->second = std::make_shared<link::Connection>(conn_interface, control_stream, rc);
|
||||
auto control_stream = conn_interface->template get_new_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);
|
||||
});
|
||||
|
||||
link_manager.register_commands(control_stream);
|
||||
itr->second = std::make_shared<link::Connection>(conn_interface, control_stream);
|
||||
|
||||
log::critical(logcat, "Connection to RID:{} added to pending connections...", rid);
|
||||
return true;
|
||||
}
|
||||
catch (...)
|
||||
|
|
|
@ -20,7 +20,6 @@ namespace llarp
|
|||
{
|
||||
namespace messages
|
||||
{
|
||||
|
||||
inline std::string
|
||||
serialize_response(oxenc::bt_dict supplement = {})
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
#pragma once
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#include <llarp/util/logging/buffer.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace FetchRCMessage
|
||||
{
|
||||
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)
|
||||
{
|
||||
oxenc::bt_dict_producer btdp;
|
||||
|
||||
try
|
||||
{
|
||||
{
|
||||
auto sublist = btdp.append_list("explicit_ids");
|
||||
|
||||
for (const auto& rid : explicit_ids)
|
||||
sublist.append(rid.ToView());
|
||||
}
|
||||
|
||||
btdp.append("since", since.time_since_epoch() / 1s);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log::error(link_cat, "Error: RCFetchMessage failed to bt encode contents!");
|
||||
}
|
||||
|
||||
return std::move(btdp).str();
|
||||
}
|
||||
} // namespace FetchRCMessage
|
||||
|
||||
namespace BootstrapFetchMessage
|
||||
{
|
||||
// the LocalRC is converted to a RemoteRC type to send to the bootstrap seed
|
||||
inline static std::string
|
||||
serialize(const LocalRC& local_rc, size_t quantity)
|
||||
{
|
||||
oxenc::bt_dict_producer btdp;
|
||||
btdp.append_encoded("local", oxen::quic::to_sv(local_rc.view()));
|
||||
log::critical(logcat, "Serializing localRC: {}", oxenc::to_hex(local_rc.view()));
|
||||
btdp.append("quantity", quantity);
|
||||
return std::move(btdp).str();
|
||||
}
|
||||
|
||||
inline static std::string
|
||||
serialize_response(const std::vector<RouterID>& explicit_ids)
|
||||
{
|
||||
oxenc::bt_dict_producer btdp;
|
||||
|
||||
try
|
||||
{
|
||||
auto sublist = btdp.append_list("explicit_ids");
|
||||
|
||||
for (const auto& rid : explicit_ids)
|
||||
sublist.append(rid.ToView());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log::error(link_cat, "Error: BootstrapFetchMessage failed to bt encode contents!");
|
||||
}
|
||||
|
||||
return std::move(btdp).str();
|
||||
}
|
||||
} // namespace BootstrapFetchMessage
|
||||
|
||||
namespace FetchRIDMessage
|
||||
{
|
||||
inline constexpr auto INVALID_REQUEST = "Invalid relay ID requested to relay response from."sv;
|
||||
|
||||
inline static std::string
|
||||
serialize(const RouterID& source)
|
||||
{
|
||||
// serialize_response is a bit weird here, and perhaps could have a sister function
|
||||
// with the same purpose but as a request, but...it works.
|
||||
return messages::serialize_response({{"source", source.ToView()}});
|
||||
}
|
||||
} // namespace FetchRIDMessage
|
||||
|
||||
} // namespace llarp
|
|
@ -1,30 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
namespace llarp::RCFetchMessage
|
||||
{
|
||||
inline constexpr auto INVALID_REQUEST = "Invalid relay ID requested."sv;
|
||||
|
||||
inline static std::string
|
||||
serialize(std::chrono::system_clock::time_point since, const std::vector<RouterID>& explicit_ids)
|
||||
{
|
||||
oxenc::bt_dict_producer btdp;
|
||||
|
||||
try
|
||||
{
|
||||
btdp.append("since", since.time_since_epoch() / 1s);
|
||||
{
|
||||
auto id_list = btdp.append_list("explicit_ids");
|
||||
for (const auto& rid : explicit_ids)
|
||||
id_list.append(rid.ToView());
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log::error(link_cat, "Error: RCFetchMessage failed to bt encode contents!");
|
||||
}
|
||||
|
||||
return std::move(btdp).str();
|
||||
}
|
||||
} // namespace llarp::RCFetchMessage
|
|
@ -1,17 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
namespace llarp::RouterIDFetch
|
||||
{
|
||||
inline constexpr auto INVALID_REQUEST = "Invalid relay ID requested to relay response from."sv;
|
||||
|
||||
inline static std::string
|
||||
serialize(const RouterID& source)
|
||||
{
|
||||
// serialize_response is a bit weird here, and perhaps could have a sister function
|
||||
// with the same purpose but as a request, but...it works.
|
||||
return messages::serialize_response({{"source", source.ToView()}});
|
||||
}
|
||||
|
||||
} // namespace llarp::RouterIDFetch
|
|
@ -10,6 +10,8 @@
|
|||
#include <llarp/util/bits.hpp>
|
||||
#include <llarp/util/mem.hpp>
|
||||
|
||||
#include <quic/address.hpp>
|
||||
|
||||
#include <cstdlib> // for itoa
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
@ -121,8 +123,10 @@ namespace llarp
|
|||
return var::visit([](auto&& ip) { return not ip.n; }, ip);
|
||||
}
|
||||
|
||||
virtual std::optional<sockaddr*>
|
||||
GetBestNetIF(int af = AF_INET) const = 0;
|
||||
// Attempts to guess a good default public network address from the system's public IP
|
||||
// addresses; the returned Address (if set) will have its port set to the given value.
|
||||
virtual std::optional<oxen::quic::Address>
|
||||
get_best_public_address(bool ipv4, uint16_t port) const = 0;
|
||||
|
||||
virtual std::optional<IPRange>
|
||||
FindFreeRange() const = 0;
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include <ifaddrs.h>
|
||||
#endif
|
||||
|
||||
#include <quic/address.hpp>
|
||||
|
||||
#include <list>
|
||||
|
||||
namespace llarp::net
|
||||
|
@ -50,19 +52,21 @@ namespace llarp::net
|
|||
return ifname;
|
||||
}
|
||||
|
||||
std::optional<sockaddr*>
|
||||
GetBestNetIF(int af) const override
|
||||
std::optional<oxen::quic::Address>
|
||||
get_best_public_address(bool ipv4, uint16_t port) const override
|
||||
{
|
||||
std::optional<sockaddr*> found;
|
||||
std::optional<oxen::quic::Address> found;
|
||||
|
||||
iter_all([this, &found, af](auto i) {
|
||||
iter_all([&found, ipv4, port](ifaddrs* i) {
|
||||
if (found)
|
||||
return;
|
||||
if (i and i->ifa_addr and i->ifa_addr->sa_family == af)
|
||||
if (i and i->ifa_addr and i->ifa_addr->sa_family == (ipv4 ? AF_INET : AF_INET6))
|
||||
{
|
||||
if (not IsBogon(*i->ifa_addr))
|
||||
oxen::quic::Address a{i->ifa_addr};
|
||||
if (a.is_public_ip())
|
||||
{
|
||||
found = i->ifa_addr;
|
||||
a.set_port(port);
|
||||
found = std::move(a);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -129,8 +129,8 @@ namespace llarp::net
|
|||
return "lokitun0";
|
||||
}
|
||||
|
||||
std::optional<sockaddr*>
|
||||
GetBestNetIF(int) const override
|
||||
std::optional<oxen::quic::Address>
|
||||
get_best_public_address(bool, uint16_t) const override
|
||||
{
|
||||
// TODO: implement me ?
|
||||
return std::nullopt;
|
||||
|
|
919
llarp/nodedb.cpp
919
llarp/nodedb.cpp
File diff suppressed because it is too large
Load Diff
519
llarp/nodedb.hpp
519
llarp/nodedb.hpp
|
@ -12,9 +12,9 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
|
||||
|
@ -22,15 +22,160 @@ namespace llarp
|
|||
{
|
||||
struct Router;
|
||||
|
||||
/* RC Fetch Constants */
|
||||
// max number of attempts we make in non-bootstrap fetch requests
|
||||
inline constexpr int MAX_FETCH_ATTEMPTS{10};
|
||||
// the total number of returned rcs that are held locally should be at least this
|
||||
inline constexpr size_t MIN_GOOD_RC_FETCH_TOTAL{};
|
||||
// the ratio of returned rcs found locally to to total returned should be above this ratio
|
||||
inline constexpr double MIN_GOOD_RC_FETCH_THRESHOLD{};
|
||||
|
||||
/* RID Fetch Constants */
|
||||
inline constexpr size_t MIN_ACTIVE_RIDS{24};
|
||||
// the number of rid sources that we make rid fetch requests to
|
||||
inline constexpr size_t RID_SOURCE_COUNT{12};
|
||||
// upper limit on how many rid fetch requests to rid sources can fail
|
||||
inline constexpr size_t MAX_RID_ERRORS{4};
|
||||
// each returned rid must appear this number of times across all responses
|
||||
inline constexpr int MIN_RID_FETCH_FREQ{RID_SOURCE_COUNT - MAX_RID_ERRORS - 1};
|
||||
// the total number of accepted returned rids should be above this number
|
||||
inline constexpr size_t MIN_GOOD_RID_FETCH_TOTAL{};
|
||||
// the ratio of accepted:rejected rids must be above this ratio
|
||||
inline constexpr double GOOD_RID_FETCH_THRESHOLD{};
|
||||
/* Bootstrap Constants */
|
||||
// the number of rc's we query the bootstrap for
|
||||
inline constexpr size_t BOOTSTRAP_SOURCE_COUNT{10};
|
||||
// the maximum number of fetch requests we make across all bootstraps
|
||||
inline constexpr int MAX_BOOTSTRAP_FETCH_ATTEMPTS{5};
|
||||
// if all bootstraps fail, router will trigger re-bootstrapping after this cooldown
|
||||
inline constexpr auto BOOTSTRAP_COOLDOWN{1min};
|
||||
|
||||
/* Other Constants */
|
||||
// the maximum number of RC/RID fetches that can pass w/o an unconfirmed rc/rid appearing
|
||||
inline constexpr int MAX_CONFIRMATION_ATTEMPTS{5};
|
||||
// threshold amount of verifications to promote an unconfirmed rc/rid
|
||||
inline constexpr int CONFIRMATION_THRESHOLD{3};
|
||||
|
||||
inline constexpr auto FLUSH_INTERVAL{5min};
|
||||
|
||||
template <
|
||||
typename ID_t,
|
||||
std::enable_if_t<std::is_same_v<ID_t, RouterID> || std::is_same_v<ID_t, RemoteRC>, int> = 0>
|
||||
struct Unconfirmed
|
||||
{
|
||||
const ID_t id;
|
||||
int attempts = 0;
|
||||
int verifications = 0;
|
||||
|
||||
Unconfirmed() = delete;
|
||||
Unconfirmed(const ID_t& obj) : id{obj}
|
||||
{}
|
||||
Unconfirmed(ID_t&& obj) : id{std::move(obj)}
|
||||
{}
|
||||
|
||||
int
|
||||
strikes() const
|
||||
{
|
||||
return attempts;
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return verifications == CONFIRMATION_THRESHOLD;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(const Unconfirmed& other) const
|
||||
{
|
||||
return id == other.id;
|
||||
}
|
||||
|
||||
bool
|
||||
operator<(const Unconfirmed& other) const
|
||||
{
|
||||
return id < other.id;
|
||||
}
|
||||
};
|
||||
|
||||
class NodeDB
|
||||
{
|
||||
std::unordered_map<RouterID, RemoteRC> known_rcs;
|
||||
Router& _router;
|
||||
const fs::path _root;
|
||||
const std::function<void(std::function<void()>)> _disk;
|
||||
|
||||
Router& router;
|
||||
const fs::path m_Root;
|
||||
const std::function<void(std::function<void()>)> disk;
|
||||
llarp_time_t _next_flush_time;
|
||||
|
||||
llarp_time_t m_NextFlushAt;
|
||||
/******** RouterID/RouterContacts ********/
|
||||
|
||||
/** RouterID mappings
|
||||
Both the following are populated in NodeDB startup with RouterID's stored on disk.
|
||||
- known_rids: meant to persist between lokinet sessions, and is only
|
||||
populated during startup and RouterID fetching. This is meant to represent the
|
||||
client instance's most recent perspective of the network, and record which RouterID's
|
||||
were recently "active" and connected to
|
||||
- unconfirmed_rids: holds new rids returned in fetch requests to be verified by subsequent
|
||||
fetch requests
|
||||
- known_rcs: populated during startup and when RC's are updated both during gossip
|
||||
and periodic RC fetching
|
||||
- unconfirmed_rcs: holds new rcs to be verified by subsequent fetch requests, similar to
|
||||
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;
|
||||
|
||||
std::set<RemoteRC> known_rcs;
|
||||
std::set<Unconfirmed<RemoteRC>> unconfirmed_rcs;
|
||||
|
||||
std::map<RouterID, const RemoteRC&> rc_lookup;
|
||||
|
||||
std::set<RemoteRC> _bootstrap_seeds;
|
||||
std::set<RouterID> _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
|
||||
- green: registered, but not fully-staked routers
|
||||
*/
|
||||
std::set<RouterID> router_whitelist{};
|
||||
std::set<RouterID> router_greylist{};
|
||||
std::set<RouterID> router_greenlist{};
|
||||
|
||||
// All registered relays (service nodes)
|
||||
std::set<RouterID> registered_routers;
|
||||
// timing (note: Router holds the variables for last rc and rid request times)
|
||||
std::unordered_map<RouterID, rc_time> last_rc_update_times;
|
||||
// if populated from a config file, lists specific exclusively used as path first-hops
|
||||
std::set<RouterID> _pinned_edges;
|
||||
// source of "truth" for RC updating. This relay will also mediate requests to the
|
||||
// 12 selected active RID's for RID fetching
|
||||
RouterID fetch_source;
|
||||
// set of 12 randomly selected RID's from the client's set of routers
|
||||
std::set<RouterID> rid_sources{};
|
||||
// logs the RID's that resulted in an error during RID fetching
|
||||
std::set<RouterID> fail_sources{};
|
||||
// tracks the number of times each rid appears in the above responses
|
||||
std::unordered_map<RouterID, int> fetch_counters{};
|
||||
|
||||
/** Failure counters:
|
||||
- fetch_failures: tracks errors fetching RC's from the RC node and requesting RID's
|
||||
from the 12 RID sources. Errors in the individual RID sets are NOT counted towards
|
||||
this, their performance as a group is evaluated wholistically
|
||||
- bootstrap_failures: tracks errors fetching both RC's from bootstrasps and RID requests
|
||||
they mediate. This is a different counter as we only bootstrap in problematic cases
|
||||
*/
|
||||
std::atomic<int> fetch_failures{0}, bootstrap_attempts{0};
|
||||
|
||||
std::atomic<bool> _using_bootstrap_fallback{false}, _needs_rebootstrap{false},
|
||||
_needs_initial_fetch{true}, _initial_completed{false};
|
||||
|
||||
bool
|
||||
want_rc(const RouterID& rid) const;
|
||||
|
||||
/// asynchronously remove the files for a set of rcs on disk given their public ident key
|
||||
void
|
||||
|
@ -40,97 +185,91 @@ namespace llarp
|
|||
fs::path
|
||||
get_path_by_pubkey(RouterID pk) const;
|
||||
|
||||
std::unordered_map<RouterID, RemoteRC> bootstraps;
|
||||
|
||||
// Router lists for snodes
|
||||
// whitelist = active routers
|
||||
std::unordered_set<RouterID> router_whitelist;
|
||||
// greylist = fully funded, but decommissioned routers
|
||||
std::unordered_set<RouterID> router_greylist;
|
||||
// greenlist = registered but not fully-staked routers
|
||||
std::unordered_set<RouterID> router_greenlist;
|
||||
// all registered relays (snodes)
|
||||
std::unordered_set<RouterID> registered_routers;
|
||||
std::unordered_map<RouterID, rc_time> last_rc_update_times;
|
||||
|
||||
// Router list for clients
|
||||
std::unordered_set<RouterID> client_known_routers;
|
||||
|
||||
// only ever use to specific edges as path first-hops
|
||||
std::unordered_set<RouterID> pinned_edges;
|
||||
|
||||
// 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};
|
||||
bool router_id_fetch_in_progress{false};
|
||||
|
||||
bool
|
||||
want_rc(const RouterID& rid) const;
|
||||
|
||||
public:
|
||||
void
|
||||
set_bootstrap_routers(const std::set<RemoteRC>& rcs);
|
||||
explicit NodeDB(
|
||||
fs::path rootdir, std::function<void(std::function<void()>)> diskCaller, Router* r);
|
||||
|
||||
const std::unordered_set<RouterID>&
|
||||
whitelist() const
|
||||
/// in memory nodedb
|
||||
NodeDB();
|
||||
|
||||
std::set<RouterID>&
|
||||
seeds()
|
||||
{
|
||||
return router_whitelist;
|
||||
return _seeds;
|
||||
}
|
||||
|
||||
const std::unordered_set<RouterID>&
|
||||
greylist() const
|
||||
const std::set<RouterID>&
|
||||
get_known_rids() const
|
||||
{
|
||||
return router_greylist;
|
||||
return known_rids;
|
||||
}
|
||||
|
||||
const std::unordered_set<RouterID>&
|
||||
get_registered_routers() const
|
||||
{
|
||||
return registered_routers;
|
||||
}
|
||||
|
||||
const std::unordered_map<RouterID, RemoteRC>&
|
||||
get_rcs() const
|
||||
const std::set<RemoteRC>&
|
||||
get_known_rcs() const
|
||||
{
|
||||
return known_rcs;
|
||||
}
|
||||
|
||||
const std::unordered_map<RouterID, rc_time>&
|
||||
get_last_rc_update_times() const
|
||||
std::optional<RemoteRC>
|
||||
get_rc_by_rid(const RouterID& rid);
|
||||
|
||||
bool
|
||||
needs_initial_fetch() const
|
||||
{
|
||||
return last_rc_update_times;
|
||||
return _needs_initial_fetch;
|
||||
}
|
||||
|
||||
// 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();
|
||||
bool
|
||||
needs_rebootstrap() const
|
||||
{
|
||||
return _needs_rebootstrap;
|
||||
}
|
||||
|
||||
void
|
||||
ingest_rcs(RouterID source, std::vector<RemoteRC> rcs, rc_time timestamp);
|
||||
ingest_bootstrap_seed();
|
||||
|
||||
bool
|
||||
ingest_fetched_rcs(std::set<RemoteRC> rcs, rc_time timestamp);
|
||||
|
||||
bool
|
||||
process_fetched_rcs(std::set<RemoteRC>& rcs);
|
||||
|
||||
void
|
||||
ingest_router_ids(RouterID source, std::vector<RouterID> ids);
|
||||
ingest_rid_fetch_responses(const RouterID& source, std::set<RouterID> ids = {});
|
||||
|
||||
bool
|
||||
process_fetched_rids();
|
||||
|
||||
void
|
||||
fetch_rcs();
|
||||
fetch_initial();
|
||||
|
||||
// RouterContact fetching
|
||||
void
|
||||
fetch_router_ids();
|
||||
fetch_rcs(bool initial = false);
|
||||
void
|
||||
post_fetch_rcs(bool initial = false);
|
||||
void
|
||||
fetch_rcs_result(bool initial = false, bool error = false);
|
||||
|
||||
// RouterID fetching
|
||||
void
|
||||
select_router_id_sources(std::unordered_set<RouterID> excluded = {});
|
||||
fetch_rids(bool initial = false);
|
||||
void
|
||||
post_fetch_rids(bool initial = false);
|
||||
void
|
||||
fetch_rids_result(bool initial = false);
|
||||
|
||||
// Bootstrap fallback fetching
|
||||
void
|
||||
fallback_to_bootstrap();
|
||||
void
|
||||
bootstrap_cooldown();
|
||||
|
||||
// Populate rid_sources with random sample from known_rids. A set of rids is passed
|
||||
// if only specific RID's need to be re-selected; to re-select all, pass the member
|
||||
// variable ::known_rids
|
||||
void
|
||||
reselect_router_id_sources(std::set<RouterID> specific);
|
||||
|
||||
void
|
||||
set_router_whitelist(
|
||||
|
@ -160,7 +299,7 @@ namespace llarp
|
|||
bool
|
||||
is_path_allowed(const RouterID& remote) const
|
||||
{
|
||||
return router_whitelist.count(remote);
|
||||
return known_rids.count(remote);
|
||||
}
|
||||
|
||||
// if pinned edges were specified, the remote must be in that set, else any remote
|
||||
|
@ -168,17 +307,89 @@ namespace llarp
|
|||
bool
|
||||
is_first_hop_allowed(const RouterID& remote) const;
|
||||
|
||||
const std::unordered_set<RouterID>&
|
||||
get_pinned_edges() const
|
||||
std::set<RouterID>&
|
||||
pinned_edges()
|
||||
{
|
||||
return pinned_edges;
|
||||
return _pinned_edges;
|
||||
}
|
||||
|
||||
explicit NodeDB(
|
||||
fs::path rootdir, std::function<void(std::function<void()>)> diskCaller, Router* r);
|
||||
void
|
||||
store_bootstraps();
|
||||
|
||||
/// in memory nodedb
|
||||
NodeDB();
|
||||
size_t
|
||||
num_bootstraps() const
|
||||
{
|
||||
return _bootstraps.size();
|
||||
}
|
||||
|
||||
bool
|
||||
has_bootstraps() const
|
||||
{
|
||||
return _bootstraps.empty();
|
||||
}
|
||||
|
||||
const BootstrapList&
|
||||
bootstrap_list() const
|
||||
{
|
||||
return _bootstraps;
|
||||
}
|
||||
|
||||
BootstrapList&
|
||||
bootstrap_list()
|
||||
{
|
||||
return _bootstraps;
|
||||
}
|
||||
|
||||
const std::set<RemoteRC>&
|
||||
bootstrap_seeds() const
|
||||
{
|
||||
return _bootstrap_seeds;
|
||||
}
|
||||
|
||||
std::set<RemoteRC>&
|
||||
bootstrap_seeds()
|
||||
{
|
||||
return _bootstrap_seeds;
|
||||
}
|
||||
|
||||
void
|
||||
set_bootstrap_routers(BootstrapList& from_router);
|
||||
|
||||
const std::set<RouterID>&
|
||||
whitelist() const
|
||||
{
|
||||
return known_rids;
|
||||
}
|
||||
|
||||
const std::set<RouterID>&
|
||||
greylist() const
|
||||
{
|
||||
return router_greylist;
|
||||
}
|
||||
|
||||
const std::set<RouterID>&
|
||||
get_registered_routers() const
|
||||
{
|
||||
return registered_routers;
|
||||
}
|
||||
|
||||
const std::set<RemoteRC>&
|
||||
get_rcs() const
|
||||
{
|
||||
return known_rcs;
|
||||
}
|
||||
|
||||
// const std::unordered_map<RouterID, RemoteRC>&
|
||||
// get_rcs() const
|
||||
// {
|
||||
// return known_rcs;
|
||||
// }
|
||||
|
||||
const std::unordered_map<RouterID, rc_time>&
|
||||
get_last_rc_update_times() const
|
||||
{
|
||||
return last_rc_update_times;
|
||||
}
|
||||
|
||||
/// load all known_rcs from disk syncrhonously
|
||||
void
|
||||
|
@ -190,7 +401,10 @@ namespace llarp
|
|||
|
||||
/// the number of RCs that are loaded from disk
|
||||
size_t
|
||||
num_loaded() const;
|
||||
num_rcs() const;
|
||||
|
||||
size_t
|
||||
num_rids() const;
|
||||
|
||||
/// do periodic tasks like flush to disk and expiration
|
||||
void
|
||||
|
@ -212,25 +426,55 @@ namespace llarp
|
|||
std::optional<RemoteRC>
|
||||
get_rc(RouterID pk) const;
|
||||
|
||||
template <typename Filter>
|
||||
std::optional<RemoteRC>
|
||||
GetRandom(Filter visit) const
|
||||
get_random_rc() const;
|
||||
|
||||
std::optional<std::vector<RemoteRC>>
|
||||
get_n_random_rcs(size_t n) const;
|
||||
|
||||
/** The following random conditional functions utilize a simple implementation of reservoir
|
||||
sampling to return either 1 or n random RC's using only one pass through the set of RC's.
|
||||
|
||||
Pseudocode:
|
||||
- begin iterating through the set
|
||||
- load the first n (or 1) that pass hook(n) into a list Selected[]
|
||||
- for all that pass the hook, increment i, tracking the number seen thus far
|
||||
- generate a random integer x from 0 to i
|
||||
- x < n ? Selected[x] = current : continue;
|
||||
*/
|
||||
|
||||
std::optional<RemoteRC>
|
||||
get_random_rc_conditional(std::function<bool(RemoteRC)> hook) const;
|
||||
|
||||
std::optional<std::vector<RemoteRC>>
|
||||
get_n_random_rcs_conditional(size_t n, std::function<bool(RemoteRC)> hook) const;
|
||||
|
||||
// Updates `current` to not contain any of the elements of `replace` and resamples (up to
|
||||
// `target_size`) from population to refill it.
|
||||
template <typename T, typename RNG>
|
||||
void
|
||||
replace_subset(
|
||||
std::set<T>& current,
|
||||
const std::set<T>& replace,
|
||||
std::set<T> population,
|
||||
size_t target_size,
|
||||
RNG&& rng)
|
||||
{
|
||||
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);
|
||||
// Remove the ones we are replacing from current:
|
||||
current.erase(replace.begin(), replace.end());
|
||||
|
||||
std::shuffle(known_rcs.begin(), known_rcs.end(), llarp::csrng);
|
||||
// Remove ones we are replacing, and ones we already have, from the population so that we
|
||||
// won't reselect them:
|
||||
population.erase(replace.begin(), replace.end());
|
||||
population.erase(current.begin(), current.end());
|
||||
|
||||
for (const auto entry : known_rcs)
|
||||
{
|
||||
if (visit(entry->second))
|
||||
return entry->second;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
});
|
||||
if (current.size() < target_size)
|
||||
std::sample(
|
||||
population.begin(),
|
||||
population.end(),
|
||||
std::inserter(current, current.end()),
|
||||
target_size - current.size(),
|
||||
rng);
|
||||
}
|
||||
|
||||
/// visit all known_rcs
|
||||
|
@ -238,9 +482,9 @@ 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);
|
||||
visit(item);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -253,24 +497,72 @@ 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())
|
||||
|
||||
for (auto itr = rc_lookup.begin(); itr != rc_lookup.end();)
|
||||
{
|
||||
if (visit(itr->second))
|
||||
{
|
||||
removed.insert(itr->second.router_id());
|
||||
itr = known_rcs.erase(itr);
|
||||
removed.insert(itr->first);
|
||||
known_rcs.erase(itr->second);
|
||||
itr = rc_lookup.erase(itr);
|
||||
}
|
||||
else
|
||||
++itr;
|
||||
}
|
||||
|
||||
if (not removed.empty())
|
||||
remove_many_from_disk_async(std::move(removed));
|
||||
});
|
||||
}
|
||||
|
||||
template <
|
||||
typename ID_t,
|
||||
std::enable_if_t<std::is_same_v<ID_t, RouterID> || std::is_same_v<ID_t, RemoteRC>, int> = 0>
|
||||
void
|
||||
process_results(
|
||||
std::set<ID_t> unconfirmed, std::set<Unconfirmed<ID_t>>& container, std::set<ID_t>& known)
|
||||
{
|
||||
// before we add the unconfirmed set, we check to see if our local set of unconfirmed
|
||||
// rcs/rids appeared in the latest unconfirmed set; if so, we will increment their number
|
||||
// of verifications and reset the attempts counter. Once appearing in 3 different requests,
|
||||
// the rc/rid will be "verified" and promoted to the known_{rcs,rids} container
|
||||
for (auto itr = container.begin(); itr != container.end();)
|
||||
{
|
||||
auto& id = itr->id;
|
||||
auto& count = const_cast<int&>(itr->attempts);
|
||||
auto& verifications = const_cast<int&>(itr->verifications);
|
||||
|
||||
if (auto found = unconfirmed.find(id); found != unconfirmed.end())
|
||||
{
|
||||
if (++verifications >= CONFIRMATION_THRESHOLD)
|
||||
{
|
||||
if constexpr (std::is_same_v<ID_t, RemoteRC>)
|
||||
put_rc_if_newer(id);
|
||||
else
|
||||
known.emplace(id);
|
||||
itr = container.erase(itr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// reset attempt counter and continue
|
||||
count = 0;
|
||||
++itr;
|
||||
}
|
||||
|
||||
unconfirmed.erase(found);
|
||||
}
|
||||
|
||||
itr = (++count >= MAX_CONFIRMATION_ATTEMPTS) ? container.erase(itr) : ++itr;
|
||||
}
|
||||
|
||||
for (auto& id : unconfirmed)
|
||||
{
|
||||
container.emplace(std::move(id));
|
||||
}
|
||||
}
|
||||
|
||||
/// remove rcs that are older than we want to keep. For relays, this is when
|
||||
/// they become "outdated" (i.e. 12hrs). Clients will hang on to them until
|
||||
/// they are fully "expired" (i.e. 30 days), as the client may go offline for
|
||||
|
@ -280,18 +572,23 @@ 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
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<llarp::Unconfirmed<llarp::RemoteRC>> : public hash<llarp::RemoteRC>
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct hash<llarp::Unconfirmed<llarp::RouterID>> : hash<llarp::RouterID>
|
||||
{};
|
||||
} // namespace std
|
||||
|
|
|
@ -118,7 +118,7 @@ namespace llarp::path
|
|||
if ((not self) or (not response_cb))
|
||||
return;
|
||||
|
||||
if (m.timed_out)
|
||||
if (not m)
|
||||
{
|
||||
response_cb(messages::TIMEOUT_RESPONSE);
|
||||
return;
|
||||
|
|
|
@ -13,19 +13,19 @@ namespace llarp::path
|
|||
{}
|
||||
|
||||
void
|
||||
PathContext::AllowTransit()
|
||||
PathContext::allow_transit()
|
||||
{
|
||||
m_AllowTransit = true;
|
||||
}
|
||||
|
||||
bool
|
||||
PathContext::AllowingTransit() const
|
||||
PathContext::is_transit_allowed() const
|
||||
{
|
||||
return m_AllowTransit;
|
||||
}
|
||||
|
||||
bool
|
||||
PathContext::CheckPathLimitHitByIP(const IpAddress& ip)
|
||||
PathContext::check_path_limit_hit_by_ip(const IpAddress& ip)
|
||||
{
|
||||
#ifdef TESTNET
|
||||
return false;
|
||||
|
@ -39,21 +39,6 @@ namespace llarp::path
|
|||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
PathContext::CheckPathLimitHitByIP(const std::string& ip)
|
||||
{
|
||||
#ifdef TESTNET
|
||||
return false;
|
||||
#else
|
||||
IpAddress remote{ip};
|
||||
// null out the port -- we don't care about it for path limiting purposes
|
||||
remote.setPort(0);
|
||||
// try inserting remote address by ip into decaying hash set
|
||||
// if it cannot insert it has hit a limit
|
||||
return not path_limits.Insert(remote);
|
||||
#endif
|
||||
}
|
||||
|
||||
const EventLoop_ptr&
|
||||
PathContext::loop()
|
||||
{
|
||||
|
@ -102,7 +87,7 @@ namespace llarp::path
|
|||
}
|
||||
|
||||
bool
|
||||
PathContext::HasTransitHop(const TransitHopInfo& info)
|
||||
PathContext::has_transit_hop(const TransitHopInfo& info)
|
||||
{
|
||||
TransitHopID downstream{info.downstream, info.rxID};
|
||||
if (transit_hops.count(downstream))
|
||||
|
@ -125,7 +110,7 @@ namespace llarp::path
|
|||
}
|
||||
|
||||
Path_ptr
|
||||
PathContext::GetPath(const PathID_t& path_id)
|
||||
PathContext::get_path(const PathID_t& path_id)
|
||||
{
|
||||
if (auto itr = own_paths.find(path_id); itr != own_paths.end())
|
||||
return itr->second;
|
||||
|
@ -186,7 +171,7 @@ namespace llarp::path
|
|||
}
|
||||
|
||||
void
|
||||
PathContext::PutTransitHop(std::shared_ptr<TransitHop> hop)
|
||||
PathContext::put_transit_hop(std::shared_ptr<TransitHop> hop)
|
||||
{
|
||||
TransitHopID downstream{hop->info.downstream, hop->info.rxID};
|
||||
TransitHopID upstream{hop->info.upstream, hop->info.txID};
|
||||
|
|
|
@ -62,28 +62,25 @@ namespace llarp::path
|
|||
ExpirePaths(llarp_time_t now);
|
||||
|
||||
void
|
||||
AllowTransit();
|
||||
allow_transit();
|
||||
|
||||
void
|
||||
RejectTransit();
|
||||
reject_transit();
|
||||
|
||||
bool
|
||||
CheckPathLimitHitByIP(const IpAddress& ip);
|
||||
check_path_limit_hit_by_ip(const IpAddress& ip);
|
||||
|
||||
bool
|
||||
CheckPathLimitHitByIP(const std::string& ip);
|
||||
is_transit_allowed() const;
|
||||
|
||||
bool
|
||||
AllowingTransit() const;
|
||||
|
||||
bool
|
||||
HasTransitHop(const TransitHopInfo& info);
|
||||
has_transit_hop(const TransitHopInfo& info);
|
||||
|
||||
void
|
||||
PutTransitHop(std::shared_ptr<TransitHop> hop);
|
||||
put_transit_hop(std::shared_ptr<TransitHop> hop);
|
||||
|
||||
Path_ptr
|
||||
GetPath(const PathID_t& path_id);
|
||||
get_path(const PathID_t& path_id);
|
||||
|
||||
bool
|
||||
TransitHopPreviousIsRouter(const PathID_t& path, const RouterID& r);
|
||||
|
|
|
@ -220,11 +220,10 @@ namespace llarp
|
|||
{
|
||||
std::optional<RemoteRC> found = std::nullopt;
|
||||
router->for_each_connection([&](link::Connection& conn) {
|
||||
const auto& rc = conn.remote_rc;
|
||||
const auto& rid = rc.router_id();
|
||||
RouterID rid{conn.conn->remote_key()};
|
||||
|
||||
#ifndef TESTNET
|
||||
if (router->IsBootstrapNode(rid))
|
||||
if (router->is_bootstrap_node(rid))
|
||||
return;
|
||||
#endif
|
||||
if (exclude.count(rid))
|
||||
|
@ -236,7 +235,7 @@ namespace llarp
|
|||
if (router->router_profiling().IsBadForPath(rid))
|
||||
return;
|
||||
|
||||
found = rc;
|
||||
found = router->node_db()->get_rc(rid);
|
||||
});
|
||||
return found;
|
||||
}
|
||||
|
@ -244,13 +243,13 @@ namespace llarp
|
|||
std::optional<std::vector<RemoteRC>>
|
||||
Builder::GetHopsForBuild()
|
||||
{
|
||||
auto filter = [r = router](const auto& rc) -> bool {
|
||||
auto filter = [r = router](const RemoteRC& rc) -> bool {
|
||||
return not r->router_profiling().IsBadForPath(rc.router_id(), 1);
|
||||
};
|
||||
if (const auto maybe = router->node_db()->GetRandom(filter))
|
||||
{
|
||||
|
||||
if (auto maybe = router->node_db()->get_random_rc_conditional(filter))
|
||||
return GetHopsAlignedToForBuild(maybe->router_id());
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
@ -359,6 +358,7 @@ namespace llarp
|
|||
|
||||
if (r->router_profiling().IsBadForPath(rid, 1))
|
||||
return false;
|
||||
|
||||
for (const auto& hop : hopsSet)
|
||||
{
|
||||
if (hop.router_id() == rid)
|
||||
|
@ -373,7 +373,7 @@ namespace llarp
|
|||
return rc.router_id() != endpointRC.router_id();
|
||||
};
|
||||
|
||||
if (const auto maybe = router->node_db()->GetRandom(filter))
|
||||
if (auto maybe = router->node_db()->get_random_rc_conditional(filter))
|
||||
hops.emplace_back(*maybe);
|
||||
else
|
||||
return std::nullopt;
|
||||
|
@ -513,9 +513,9 @@ namespace llarp
|
|||
path->EnterState(path::ePathEstablished);
|
||||
return;
|
||||
}
|
||||
if (m.timed_out)
|
||||
if (not m)
|
||||
{
|
||||
log::warning(path_cat, "Path build timed out");
|
||||
log::warning(path_cat, "Path build request failed!");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -219,7 +219,7 @@ namespace llarp
|
|||
|
||||
// explicit route pokes for first hops
|
||||
router.for_each_connection(
|
||||
[this](link::Connection conn) { add_route(conn.remote_rc.addr()); });
|
||||
[this](link::Connection conn) { add_route(conn.conn->remote()); });
|
||||
|
||||
add_route(router.link_manager().local());
|
||||
// add default route
|
||||
|
@ -238,7 +238,7 @@ namespace llarp
|
|||
{
|
||||
// unpoke routes for first hops
|
||||
router.for_each_connection(
|
||||
[this](link::Connection conn) { delete_route(conn.remote_rc.addr()); });
|
||||
[this](link::Connection conn) { delete_route(conn.conn->remote()); });
|
||||
if (is_enabled() and is_up)
|
||||
{
|
||||
vpn::AbstractRouteManager& route = router.vpn_platform()->RouteManager();
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
@ -64,14 +55,14 @@ namespace llarp
|
|||
|
||||
struct Router : std::enable_shared_from_this<Router>
|
||||
{
|
||||
friend class NodeDB;
|
||||
|
||||
explicit Router(EventLoop_ptr loop, std::shared_ptr<vpn::Platform> vpnPlatform);
|
||||
|
||||
~Router();
|
||||
|
||||
private:
|
||||
std::shared_ptr<RoutePoker> _route_poker;
|
||||
/// bootstrap RCs
|
||||
BootstrapList bootstrap_rc_list;
|
||||
std::chrono::steady_clock::time_point _next_explore_at;
|
||||
llarp_time_t last_pump = 0s;
|
||||
// transient iwp encryption key
|
||||
|
@ -95,8 +86,14 @@ namespace llarp
|
|||
int _outbound_udp_socket = -1;
|
||||
bool _is_service_node = false;
|
||||
|
||||
std::optional<SockAddr> _ourAddress;
|
||||
oxen::quic::Address _local_addr;
|
||||
bool _testnet = false;
|
||||
bool _testing_disabled = false;
|
||||
bool _bootstrap_seed = false;
|
||||
|
||||
consensus::reachability_testing router_testing;
|
||||
|
||||
std::optional<oxen::quic::Address> _public_address; // public addr for relays
|
||||
oxen::quic::Address _listen_address;
|
||||
|
||||
EventLoop_ptr _loop;
|
||||
std::shared_ptr<vpn::Platform> _vpn;
|
||||
|
@ -108,7 +105,7 @@ namespace llarp
|
|||
std::shared_ptr<NodeDB> _node_db;
|
||||
llarp_time_t _started_at;
|
||||
const oxenmq::TaggedThreadID _disk_thread;
|
||||
oxen::quic::Network _net;
|
||||
// oxen::quic::Network _net; // DISCUSS: we don't use this anywhere..?
|
||||
|
||||
llarp_time_t _last_stats_report = 0s;
|
||||
llarp_time_t _next_decomm_warning = time_now_ms() + 15s;
|
||||
|
@ -126,24 +123,15 @@ namespace llarp
|
|||
oxenmq::address rpc_addr;
|
||||
Profiling _router_profiling;
|
||||
fs::path _profile_file;
|
||||
LinkManager _link_manager{*this};
|
||||
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::unique_ptr<LinkManager> _link_manager;
|
||||
int client_router_connections;
|
||||
|
||||
// should we be sending padded messages every interval?
|
||||
bool send_padding = false;
|
||||
|
||||
service::Context _hidden_service_context;
|
||||
|
||||
consensus::reachability_testing router_testing;
|
||||
|
||||
bool
|
||||
should_report_stats(llarp_time_t now) const;
|
||||
|
||||
|
@ -159,7 +147,41 @@ namespace llarp
|
|||
bool
|
||||
insufficient_peers() const;
|
||||
|
||||
protected:
|
||||
// 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{last_rc_gossip};
|
||||
std::chrono::system_clock::time_point last_rc_fetch{last_rc_gossip};
|
||||
std::chrono::system_clock::time_point last_rid_fetch{last_rc_gossip};
|
||||
std::chrono::system_clock::time_point next_bootstrap_attempt{last_rc_gossip};
|
||||
|
||||
public:
|
||||
bool
|
||||
is_bootstrap_seed() const
|
||||
{
|
||||
return _bootstrap_seed;
|
||||
}
|
||||
|
||||
int
|
||||
required_num_client_conns() const
|
||||
{
|
||||
return client_router_connections;
|
||||
}
|
||||
|
||||
RouterID
|
||||
local_rid() const
|
||||
{
|
||||
return RouterID{pubkey()};
|
||||
}
|
||||
|
||||
bool
|
||||
needs_initial_fetch() const;
|
||||
|
||||
bool
|
||||
needs_rebootstrap() const;
|
||||
|
||||
void
|
||||
for_each_connection(std::function<void(link::Connection&)> func);
|
||||
|
||||
|
@ -169,10 +191,16 @@ namespace llarp
|
|||
void
|
||||
connect_to(const RemoteRC& rc);
|
||||
|
||||
Contacts*
|
||||
const Contacts&
|
||||
contacts() const
|
||||
{
|
||||
return _contacts.get();
|
||||
return *_contacts;
|
||||
}
|
||||
|
||||
Contacts&
|
||||
contacts()
|
||||
{
|
||||
return *_contacts;
|
||||
}
|
||||
|
||||
std::shared_ptr<Config>
|
||||
|
@ -205,10 +233,16 @@ namespace llarp
|
|||
LinkManager&
|
||||
link_manager()
|
||||
{
|
||||
return _link_manager;
|
||||
return *_link_manager;
|
||||
}
|
||||
|
||||
inline int
|
||||
const LinkManager&
|
||||
link_manager() const
|
||||
{
|
||||
return *_link_manager;
|
||||
}
|
||||
|
||||
int
|
||||
outbound_udp_socket() const
|
||||
{
|
||||
return _outbound_udp_socket;
|
||||
|
@ -275,7 +309,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
oxen::quic::Address
|
||||
public_ip() const;
|
||||
listen_addr() const;
|
||||
|
||||
util::StatusObject
|
||||
ExtractStatus() const;
|
||||
|
@ -283,7 +317,7 @@ namespace llarp
|
|||
util::StatusObject
|
||||
ExtractSummaryStatus() const;
|
||||
|
||||
const std::unordered_set<RouterID>&
|
||||
const std::set<RouterID>&
|
||||
get_whitelist() const;
|
||||
|
||||
void
|
||||
|
@ -369,10 +403,10 @@ namespace llarp
|
|||
status_line();
|
||||
|
||||
void
|
||||
InitInboundLinks();
|
||||
init_inbounds();
|
||||
|
||||
void
|
||||
InitOutboundLinks();
|
||||
init_outbounds();
|
||||
|
||||
std::optional<RouterID>
|
||||
GetRandomGoodRouter();
|
||||
|
@ -466,7 +500,7 @@ namespace llarp
|
|||
std::string body,
|
||||
std::function<void(oxen::quic::message m)> func = nullptr);
|
||||
|
||||
bool IsBootstrapNode(RouterID) const;
|
||||
bool is_bootstrap_node(RouterID) const;
|
||||
|
||||
/// call internal router ticker
|
||||
void
|
||||
|
@ -478,23 +512,16 @@ namespace llarp
|
|||
return llarp::time_now_ms();
|
||||
}
|
||||
|
||||
/// parse a routing message in a buffer and handle it with a handler if
|
||||
/// successful parsing return true on parse and handle success otherwise
|
||||
/// return false
|
||||
bool
|
||||
ParseRoutingMessageBuffer(
|
||||
const llarp_buffer_t& buf, path::AbstractHopHandler& p, const PathID_t& rxid);
|
||||
|
||||
void
|
||||
ConnectToRandomRouters(int N);
|
||||
|
||||
/// count the number of unique service nodes connected via pubkey
|
||||
size_t
|
||||
NumberOfConnectedRouters() const;
|
||||
num_router_connections() const;
|
||||
|
||||
/// count the number of unique clients connected by pubkey
|
||||
size_t
|
||||
NumberOfConnectedClients() const;
|
||||
num_client_connections() const;
|
||||
|
||||
bool
|
||||
GetRandomConnectedRouter(RemoteRC& result) const;
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
@ -57,19 +56,19 @@ namespace llarp
|
|||
}
|
||||
|
||||
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(
|
||||
ACTIVE_NETID, netid)};
|
||||
|
||||
auto pk = data.require<std::string_view>("p");
|
||||
auto pubkey = data.require<std::string_view>("p");
|
||||
if (pubkey.size() != 32)
|
||||
throw std::runtime_error{
|
||||
"Invalid RC pubkey: expected 32 bytes, got {}"_format(pubkey.size())};
|
||||
std::memcpy(_router_id.data(), pubkey.data(), 32);
|
||||
|
||||
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");
|
||||
|
||||
|
@ -103,7 +102,7 @@ namespace llarp
|
|||
{
|
||||
util::StatusObject obj{
|
||||
{"lastUpdated", _timestamp.time_since_epoch().count()},
|
||||
{"publicRouter", is_public_router()},
|
||||
{"publicRouter", is_public_addressable()},
|
||||
{"identity", _router_id.ToString()},
|
||||
{"address", _addr.to_string()}};
|
||||
|
||||
|
@ -222,10 +221,11 @@ namespace llarp
|
|||
}
|
||||
|
||||
bool
|
||||
RouterContact::is_public_router() const
|
||||
RouterContact::is_public_addressable() const
|
||||
{
|
||||
if (_router_version.empty())
|
||||
return false;
|
||||
|
||||
return _addr.is_addressable();
|
||||
}
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
@ -34,7 +33,7 @@ namespace llarp
|
|||
/// "6" -- optional 18 byte IPv6 address & port: 16 byte raw IPv6 address followed by 2 bytes
|
||||
/// of port in network order.
|
||||
/// "i" -- optional network ID string of up to 8 bytes; this is omitted for the default network
|
||||
/// ID ("lokinet") but included for others (such as "gamma" for testnet).
|
||||
/// ID ("lokinet") but included for others (such as "testnet" for testnet).
|
||||
/// "p" -- 32-byte router pubkey
|
||||
/// "t" -- timestamp when this RC record was created (which also implicitly determines when it
|
||||
/// goes stale and when it expires).
|
||||
|
@ -177,7 +176,7 @@ namespace llarp
|
|||
decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf);
|
||||
|
||||
bool
|
||||
is_public_router() const;
|
||||
is_public_addressable() const;
|
||||
|
||||
/// does this RC expire soon? default delta is 1 minute
|
||||
bool
|
||||
|
@ -208,6 +207,8 @@ namespace llarp
|
|||
bt_load(oxenc::bt_dict_consumer& data);
|
||||
};
|
||||
|
||||
struct RemoteRC;
|
||||
|
||||
/// 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
|
||||
/// required for signing and serialization
|
||||
|
@ -237,6 +238,9 @@ namespace llarp
|
|||
explicit LocalRC(std::string payload, const SecretKey sk);
|
||||
~LocalRC() = default;
|
||||
|
||||
RemoteRC
|
||||
to_remote();
|
||||
|
||||
void
|
||||
resign();
|
||||
|
||||
|
@ -298,8 +302,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());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -311,15 +314,18 @@ namespace llarp
|
|||
void
|
||||
bt_verify(oxenc::bt_dict_consumer& data, bool reject_expired = false) const;
|
||||
|
||||
explicit RemoteRC(oxenc::bt_dict_consumer btdc);
|
||||
|
||||
public:
|
||||
RemoteRC() = default;
|
||||
RemoteRC(std::string_view data) : RemoteRC{oxenc::bt_dict_consumer{data}}
|
||||
{}
|
||||
RemoteRC(ustring_view data) : RemoteRC{oxenc::bt_dict_consumer{data}}
|
||||
explicit RemoteRC(std::string_view data) : RemoteRC{oxenc::bt_dict_consumer{data}}
|
||||
{
|
||||
_payload = {reinterpret_cast<const unsigned char*>(data.data()), data.size()};
|
||||
}
|
||||
explicit RemoteRC(ustring_view data) : RemoteRC{oxenc::bt_dict_consumer{data}}
|
||||
{
|
||||
_payload = data;
|
||||
}
|
||||
explicit RemoteRC(oxenc::bt_dict_consumer btdc);
|
||||
~RemoteRC() = default;
|
||||
|
||||
std::string_view
|
||||
|
@ -360,10 +366,18 @@ namespace std
|
|||
template <>
|
||||
struct hash<llarp::RouterContact>
|
||||
{
|
||||
size_t
|
||||
virtual size_t
|
||||
operator()(const llarp::RouterContact& r) const
|
||||
{
|
||||
return std::hash<llarp::PubKey>{}(r.router_id());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct hash<llarp::RemoteRC> : public hash<llarp::RouterContact>
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct hash<llarp::LocalRC> final : public hash<llarp::RouterContact>
|
||||
{};
|
||||
} // namespace std
|
||||
|
|
|
@ -22,10 +22,18 @@ namespace llarp
|
|||
{
|
||||
_router_id = llarp::seckey_to_pubkey(_secret_key);
|
||||
_addr = std::move(local);
|
||||
_addr6.emplace(&_addr.in6());
|
||||
if (_addr.is_ipv6())
|
||||
_addr6.emplace(&_addr.in6());
|
||||
resign();
|
||||
}
|
||||
|
||||
RemoteRC
|
||||
LocalRC::to_remote()
|
||||
{
|
||||
resign();
|
||||
return RemoteRC{view()};
|
||||
}
|
||||
|
||||
LocalRC::LocalRC(std::string payload, const SecretKey sk) : _secret_key{std::move(sk)}
|
||||
{
|
||||
_router_id = llarp::seckey_to_pubkey(_secret_key);
|
||||
|
@ -47,13 +55,13 @@ namespace llarp
|
|||
|
||||
if (net->IsBogon(addr().in4()) and BLOCK_BOGONS)
|
||||
{
|
||||
auto err = "Unable to verify expired RemoteRC!";
|
||||
auto err = "Unable to verify expired LocalRC!";
|
||||
log::info(logcat, err);
|
||||
throw std::runtime_error{err};
|
||||
}
|
||||
|
||||
if (not crypto::verify(router_id(), msg, sig))
|
||||
throw std::runtime_error{"Failed to verify RemoteRC"};
|
||||
throw std::runtime_error{"Failed to verify LocalRC"};
|
||||
});
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
|
@ -78,7 +86,7 @@ namespace llarp
|
|||
return sig;
|
||||
});
|
||||
|
||||
_payload = btdp.view<unsigned char>();
|
||||
_payload = ustring{btdp.view<unsigned char>()};
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -123,8 +131,6 @@ namespace llarp
|
|||
static_assert(llarp::LOKINET_VERSION.size() == 3);
|
||||
btdp.append(
|
||||
"v", std::string_view{reinterpret_cast<const char*>(llarp::LOKINET_VERSION.data()), 3});
|
||||
|
||||
bt_sign(btdp);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -16,32 +16,13 @@ namespace llarp
|
|||
try
|
||||
{
|
||||
bt_load(btdc);
|
||||
|
||||
btdc.require_signature("~", [this](ustring_view msg, ustring_view sig) {
|
||||
if (sig.size() != 64)
|
||||
throw std::runtime_error{"Invalid signature: not 64 bytes"};
|
||||
|
||||
if (is_expired(time_now_ms()))
|
||||
throw std::runtime_error{"Unable to verify expired RemoteRC!"};
|
||||
|
||||
// TODO: revisit if this is needed; detail from previous implementation
|
||||
const auto* net = net::Platform::Default_ptr();
|
||||
|
||||
if (net->IsBogon(addr().in4()) and BLOCK_BOGONS)
|
||||
{
|
||||
auto err = "Unable to verify expired RemoteRC!";
|
||||
log::info(logcat, err);
|
||||
throw std::runtime_error{err};
|
||||
}
|
||||
|
||||
if (not crypto::verify(router_id(), msg, sig))
|
||||
throw std::runtime_error{"Failed to verify RemoteRC"};
|
||||
});
|
||||
bt_verify(btdc, /*reject_expired=*/true);
|
||||
}
|
||||
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};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,13 +41,20 @@ namespace llarp
|
|||
|
||||
if (net->IsBogon(addr().in4()) and BLOCK_BOGONS)
|
||||
{
|
||||
auto err = "Unable to verify expired RemoteRC!";
|
||||
auto err = "Unable to verify expired RemoteRC address!";
|
||||
log::info(logcat, err);
|
||||
throw std::runtime_error{err};
|
||||
}
|
||||
|
||||
log::error(
|
||||
log::Cat("FIXME"),
|
||||
"ABOUT TO VERIFY THIS: {}, WITH SIG {}, SIGNED BY {}",
|
||||
oxenc::to_hex(msg),
|
||||
oxenc::to_hex(sig),
|
||||
router_id().ToHex());
|
||||
|
||||
if (not crypto::verify(router_id(), msg, sig))
|
||||
throw std::runtime_error{"Failed to verify RemoteRC"};
|
||||
throw std::runtime_error{"Failed to verify RemoteRC signature"};
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -74,11 +62,11 @@ namespace llarp
|
|||
RemoteRC::read(const fs::path& fname)
|
||||
{
|
||||
ustring buf;
|
||||
buf.reserve(MAX_RC_SIZE);
|
||||
buf.resize(MAX_RC_SIZE);
|
||||
|
||||
try
|
||||
{
|
||||
util::file_to_buffer(fname, buf.data(), MAX_RC_SIZE);
|
||||
util::file_to_buffer(fname, buf.data(), buf.size());
|
||||
|
||||
oxenc::bt_dict_consumer btdc{buf};
|
||||
bt_load(btdc);
|
||||
|
@ -88,7 +76,7 @@ namespace llarp
|
|||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
log::error(logcat, "Failed to read or validate RC from {}: {}", fname, e.what());
|
||||
log::warning(logcat, "Failed to read or validate RC from {}: {}", fname, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
bool
|
||||
RouterID::FromString(std::string_view str)
|
||||
RouterID::from_string(std::string_view str)
|
||||
{
|
||||
auto pos = str.find(SNODE_TLD);
|
||||
if (pos != str.size() - SNODE_TLD.size())
|
||||
|
|
|
@ -21,6 +21,9 @@ namespace llarp
|
|||
RouterID(const Data& data) : PubKey(data)
|
||||
{}
|
||||
|
||||
RouterID(ustring_view data) : PubKey(data.data())
|
||||
{}
|
||||
|
||||
util::StatusObject
|
||||
ExtractStatus() const;
|
||||
|
||||
|
@ -30,8 +33,11 @@ namespace llarp
|
|||
std::string
|
||||
ShortString() const;
|
||||
|
||||
// FIXME: this is deceptively named: it parses something base32z formatted with .snode on the
|
||||
// end, so should probably be called "from_snode_address" or "from_base32z" or something that
|
||||
// doesn't sound exactly like the other (different) from_strings of its base classes.
|
||||
bool
|
||||
FromString(std::string_view str);
|
||||
from_string(std::string_view str);
|
||||
|
||||
RouterID&
|
||||
operator=(const byte_t* ptr)
|
||||
|
@ -49,7 +55,6 @@ namespace llarp
|
|||
|
||||
template <>
|
||||
constexpr inline bool IsToStringFormattable<RouterID> = true;
|
||||
|
||||
} // namespace llarp
|
||||
|
||||
namespace std
|
||||
|
|
|
@ -97,7 +97,7 @@ namespace llarp::rpc
|
|||
return; // bail
|
||||
}
|
||||
|
||||
LogDebug("new block at height ", m_BlockHeight);
|
||||
log::trace(logcat, "new block at height {}", m_BlockHeight);
|
||||
// don't upadate on block notification if an update is pending
|
||||
if (not m_UpdatingList)
|
||||
UpdateServiceNodeList();
|
||||
|
@ -138,7 +138,7 @@ namespace llarp::rpc
|
|||
throw std::runtime_error{"get_service_nodes did not return 'OK' status"};
|
||||
if (auto it = json.find("unchanged");
|
||||
it != json.end() and it->is_boolean() and it->get<bool>())
|
||||
LogDebug("service node list unchanged");
|
||||
log::trace(logcat, "service node list unchanged");
|
||||
else
|
||||
{
|
||||
self->HandleNewServiceNodeList(json.at("service_node_states"));
|
||||
|
@ -269,6 +269,7 @@ namespace llarp::rpc
|
|||
keymap = std::move(keymap),
|
||||
router = std::move(router)]() mutable {
|
||||
m_KeyMap = std::move(keymap);
|
||||
|
||||
router->set_router_whitelist(active, decomm, unfunded);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ namespace llarp::rpc
|
|||
{
|
||||
if (r.is_service_node())
|
||||
{
|
||||
return r.exitContext().GetExitEndpoint(name);
|
||||
return r.exitContext().get_exit_endpoint(name);
|
||||
}
|
||||
|
||||
return r.hidden_service_context().GetEndpointByName(name);
|
||||
|
@ -322,14 +322,14 @@ namespace llarp::rpc
|
|||
return;
|
||||
}
|
||||
|
||||
if (not routerID.FromString(lookupsnode.request.routerID))
|
||||
if (not routerID.from_string(lookupsnode.request.routerID))
|
||||
{
|
||||
SetJSONError("Invalid remote: " + lookupsnode.request.routerID, lookupsnode.response);
|
||||
return;
|
||||
}
|
||||
|
||||
m_Router.loop()->call([&]() {
|
||||
auto endpoint = m_Router.exitContext().GetExitEndpoint("default");
|
||||
auto endpoint = m_Router.exitContext().get_exit_endpoint("default");
|
||||
|
||||
if (endpoint == nullptr)
|
||||
{
|
||||
|
|
|
@ -79,7 +79,7 @@ namespace llarp::service
|
|||
{
|
||||
RouterID router{};
|
||||
service::Address addr{};
|
||||
if (router.FromString(lokinet_addr))
|
||||
if (router.from_string(lokinet_addr))
|
||||
return router;
|
||||
if (addr.FromString(lokinet_addr))
|
||||
return addr;
|
||||
|
|
|
@ -516,7 +516,7 @@ namespace llarp::service
|
|||
const auto& keyfile = _state->key_file;
|
||||
if (!keyfile.empty())
|
||||
{
|
||||
_identity.EnsureKeys(keyfile, router()->key_manager()->needBackup());
|
||||
_identity.EnsureKeys(keyfile, router()->key_manager()->needs_backup());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -697,14 +697,16 @@ namespace llarp::service
|
|||
{
|
||||
std::unordered_set<RouterID> exclude;
|
||||
ForEachPath([&exclude](auto path) { exclude.insert(path->Endpoint()); });
|
||||
const auto maybe =
|
||||
router()->node_db()->GetRandom([exclude, r = router()](const RemoteRC& rc) -> bool {
|
||||
const auto& rid = rc.router_id();
|
||||
return exclude.count(rid) == 0 and not r->router_profiling().IsBadForPath(rid);
|
||||
});
|
||||
if (not maybe.has_value())
|
||||
return std::nullopt;
|
||||
return GetHopsForBuildWithEndpoint(maybe->router_id());
|
||||
|
||||
auto hook = [exclude, r = router()](const RemoteRC& rc) -> bool {
|
||||
const auto& rid = rc.router_id();
|
||||
return not(exclude.count(rid) || r->router_profiling().IsBadForPath(rid));
|
||||
};
|
||||
|
||||
if (auto maybe = router()->node_db()->get_random_rc_conditional(hook))
|
||||
return GetHopsForBuildWithEndpoint(maybe->router_id());
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::vector<RemoteRC>>
|
||||
|
@ -1308,7 +1310,7 @@ namespace llarp::service
|
|||
// TODO: if all requests fail, call callback with failure?
|
||||
for (const auto& path : paths)
|
||||
{
|
||||
path->find_intro(location, false, 0, [this, hook, got_it](std::string resp) mutable {
|
||||
path->find_intro(location, false, 0, [hook, got_it, this](std::string resp) mutable {
|
||||
// asking many, use only first successful
|
||||
if (*got_it)
|
||||
return;
|
||||
|
@ -1333,7 +1335,7 @@ namespace llarp::service
|
|||
}
|
||||
|
||||
service::EncryptedIntroSet enc{introset};
|
||||
router()->contacts()->services()->PutNode(std::move(enc));
|
||||
router()->contacts().put_intro(std::move(enc));
|
||||
|
||||
// TODO: finish this
|
||||
/*
|
||||
|
@ -1396,7 +1398,7 @@ namespace llarp::service
|
|||
|
||||
while (not _inbound_queue.empty())
|
||||
{
|
||||
// succ it out
|
||||
// suck it out
|
||||
queue.emplace(std::move(*_inbound_queue.popFront()));
|
||||
}
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ namespace llarp::service
|
|||
|
||||
if (exists and needBackup)
|
||||
{
|
||||
KeyManager::backupFileByMoving(fname);
|
||||
KeyManager::copy_backup_keyfile(fname);
|
||||
exists = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace llarp::service
|
|||
{
|
||||
oxenc::bt_dict_consumer btdc{std::move(buf)};
|
||||
|
||||
router.FromString(btdc.require<std::string>("k"));
|
||||
router.from_string(btdc.require<std::string>("k"));
|
||||
latency = std::chrono::milliseconds{btdc.require<uint64_t>("l")};
|
||||
path_id.from_string(btdc.require<std::string>("p"));
|
||||
expiry = std::chrono::milliseconds{btdc.require<uint64_t>("x")};
|
||||
|
|
|
@ -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