diff --git a/.gitignore b/.gitignore index a1d1593df..0b20f7ba5 100644 --- a/.gitignore +++ b/.gitignore @@ -43,7 +43,7 @@ testnet_tmp vsproject/ .vs -daemon.ini +*.ini .gradle/ diff --git a/llarp/bootstrap.cpp b/llarp/bootstrap.cpp index 65d53773c..b377ec715 100644 --- a/llarp/bootstrap.cpp +++ b/llarp/bootstrap.cpp @@ -77,6 +77,7 @@ namespace llarp else { RemoteRC rc; + if (not rc.read(fpath)) { throw std::runtime_error{ diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index 77e6d8206..a777a4795 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -19,14 +19,7 @@ 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; + constexpr int DEFAULT_PUBLIC_PORT = 1090; using namespace config; namespace @@ -72,38 +65,44 @@ namespace llarp net_id = std::move(arg); }); - int minConnections = - (params.is_relay ? DefaultMinConnectionsForRouter : DefaultMinConnectionsForClient); conf.define_option( "router", - "min-connections", - Default{minConnections}, + "relay-connections", + Default{CLIENT_ROUTER_CONNECTIONS}, + ClientOnly, Comment{ - "Minimum number of routers lokinet will attempt to maintain connections to.", + "Minimum number of routers lokinet client will attempt to maintain connections to.", }, [=](int arg) { - if (arg < minConnections) + if (arg < CLIENT_ROUTER_CONNECTIONS) throw std::invalid_argument{ - fmt::format("min-connections must be >= {}", minConnections)}; + fmt::format("Client relay connections must be >= {}", CLIENT_ROUTER_CONNECTIONS)}; - min_connected_routers = arg; + client_router_connections = arg; + }); + + conf.define_option( + "router", + "min-connections", + Deprecated, + Comment{ + "Minimum number of routers lokinet will attempt to maintain connections to.", + }, + [=](int) { + log::warning( + logcat, "Router min-connections is deprecated; use relay-connections for clients"); }); - int maxConnections = - (params.is_relay ? DefaultMaxConnectionsForRouter : DefaultMaxConnectionsForClient); conf.define_option( "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("router", "nickname", Deprecated); @@ -159,7 +158,7 @@ namespace llarp "router", "public-port", RelayOnly, - Default{DefaultPublicPort}, + Default{DEFAULT_PUBLIC_PORT}, Comment{ "When specifying public-ip=, this specifies the public UDP port at which this lokinet", "router is reachable. Required when public-ip is used.", @@ -1162,7 +1161,7 @@ namespace llarp conf.define_option( "lokid", "disable-testing", - Default{true}, + Default{false}, Hidden, RelayOnly, Comment{ diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index f47c92230..b294d9263 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -35,6 +35,7 @@ namespace llarp using ConfigMap = llarp::ConfigParser::ConfigMap; inline static constexpr uint16_t DEFAULT_LISTEN_PORT{1090}; + 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 +58,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; diff --git a/llarp/config/key_manager.cpp b/llarp/config/key_manager.cpp index d1da613c5..070a4ce86 100644 --- a/llarp/config/key_manager.cpp +++ b/llarp/config/key_manager.cpp @@ -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; } - } - } - if (not config.router.is_relay) - { - // 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::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; + } + } } // load encryption key - auto encryptionKeygen = [](llarp::SecretKey& key) { llarp::crypto::encryption_keygen(key); }; - if (not loadOrCreateKey(m_encKeyPath, encryptionKey, encryptionKeygen)) + auto enckey_gen = [](llarp::SecretKey& key) { llarp::crypto::encryption_keygen(key); }; + if (not keygen(enckey_path, encryption_key, enckey_gen)) + { + log::critical( + logcat, "KeyManager::keygen failed to generate encryption key line:{}", __LINE__); 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)) + + if (not keygen(transkey_path, transport_key, transkey_gen)) + { + log::critical( + logcat, "KeyManager::keygen failed to generate transport key line:{}", __LINE__); return false; + } - m_initialized = true; + 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 files = {m_rcPath, m_idKeyPath, m_encKeyPath, m_transportKeyPath}; + std::vector 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 keygen) { if (not fs::exists(path)) diff --git a/llarp/config/key_manager.hpp b/llarp/config/key_manager.hpp index 20a45d0c9..b0906f4d5 100644 --- a/llarp/config/key_manager.hpp +++ b/llarp/config/key_manager.hpp @@ -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 keygen); diff --git a/llarp/exit/context.cpp b/llarp/exit/context.cpp index aa3761cc9..ec03c38e4 100644 --- a/llarp/exit/context.cpp +++ b/llarp/exit/context.cpp @@ -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 - 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(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 diff --git a/llarp/exit/context.hpp b/llarp/exit/context.hpp index 31a9e766f..6e52da3bc 100644 --- a/llarp/exit/context.hpp +++ b/llarp/exit/context.hpp @@ -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>; void - CalculateExitTraffic(TrafficStats& stats); + calculate_exit_traffic(TrafficStats& stats); std::shared_ptr - GetExitEndpoint(std::string name) const; + get_exit_endpoint(std::string name) const; private: Router* router; - std::unordered_map> m_Exits; - std::list> m_Closed; + std::unordered_map> _exits; + std::list> _closed; }; } // namespace llarp::exit diff --git a/llarp/link/contacts.cpp b/llarp/link/contacts.cpp index a31a231db..ffb78ad10 100644 --- a/llarp/link/contacts.cpp +++ b/llarp/link/contacts.cpp @@ -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(0); - _router.loop()->call_every(1s, timer_keepalive, [this]() { on_clean_contacts(); }); - _rc_nodes = std::make_unique>(_local_key, llarp::randint); _introset_nodes = std::make_unique>(_local_key, llarp::randint); } std::optional Contacts::get_introset_by_location(const dht::Key_t& key) const { - return _router.loop()->call_get([this, key]() -> std::optional { - auto& introsets = _introset_nodes->nodes; + std::optional enc = std::nullopt; - if (auto itr = introsets.find(key); itr != introsets.end()) - return itr->second.introset; + auto& introsets = _introset_nodes->nodes; - return std::nullopt; - }); - } - - 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 (auto itr = introsets.find(key); itr != introsets.end()) + enc = itr->second.introset; - 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) - { - _router.loop()->call([this, val]() { _rc_nodes->PutNode(val); }); - } - - void - Contacts::delete_rc_node_async(const dht::Key_t& val) + Contacts::put_intro(service::EncryptedIntroSet enc) { - _router.loop()->call([this, val]() { _rc_nodes->DelNode(val); }); + _introset_nodes->PutNode(std::move(enc)); } } // namespace llarp diff --git a/llarp/link/contacts.hpp b/llarp/link/contacts.hpp index 8423a346f..37056cbbc 100644 --- a/llarp/link/contacts.hpp +++ b/llarp/link/contacts.hpp @@ -15,28 +15,14 @@ namespace llarp private: // TODO: why was this a shared ptr in the original implementation? revisit this std::shared_ptr timer_keepalive; - const dht::Key_t& _local_key; Router& _router; - std::atomic transit_allowed{false}; + const dht::Key_t _local_key; - // holds router contacts - std::unique_ptr> _rc_nodes; // holds introsets for remote services std::unique_ptr> _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 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* - rc_nodes() const - { - return _rc_nodes.get(); - } + put_intro(service::EncryptedIntroSet enc); dht::Bucket* services() const diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 2f61820b9..6db101b36 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -183,9 +183,11 @@ namespace llarp - connection close callback - stream constructor callback - will return a BTRequestStream on the first call to get_new_stream + - bt stream construction contains a stream close callback that shuts down the connection + if the btstream closes unexpectedly */ auto ep = quic->endpoint( - _router.local_addr(), + _router.listen_addr(), [this](oxen::quic::connection_interface& ci) { return on_conn_open(ci); }, [this](oxen::quic::connection_interface& ci, uint64_t ec) { return on_conn_closed(ci, ec); @@ -198,7 +200,14 @@ namespace llarp std::optional id) -> std::shared_ptr { if (id && id == 0) { - auto s = std::make_shared(c, e); + auto s = std::make_shared( + c, e, [](oxen::quic::Stream& s, uint64_t error_code) { + log::warning( + logcat, + "BTRequestStream closed unexpectedly (ec:{}); closing connection...", + error_code); + s.conn.close_connection(error_code); + }); register_commands(s); return s; } @@ -216,6 +225,13 @@ namespace llarp , ep{startup_endpoint(), *this} {} + std::unique_ptr + LinkManager::make(Router& r) + { + std::unique_ptr p{new LinkManager(r)}; + return p; + } + bool LinkManager::send_control_message( const RouterID& remote, @@ -496,6 +512,7 @@ namespace llarp { is_stopping = false; node_db = _router.node_db(); + client_router_connections = _router.required_num_client_conns(); } void @@ -898,7 +915,7 @@ namespace llarp "Received PublishIntroMessage in which we are peer index {}.. storing introset", relay_order); - _router.contacts()->services()->PutNode(dht::ISNode{std::move(enc)}); + _router.contacts().put_intro(std::move(enc)); respond(serialize_response({{messages::STATUS_KEY, ""}})); } else @@ -936,7 +953,7 @@ namespace llarp { log::info(link_cat, "Received PublishIntroMessage for {} (TXID: {}); we are candidate {}"); - _router.contacts()->services()->PutNode(dht::ISNode{std::move(enc)}); + _router.contacts().put_intro(std::move(enc)); respond(serialize_response({{messages::STATUS_KEY, ""}})); } else @@ -1064,7 +1081,7 @@ namespace llarp } else { - if (auto maybe_intro = _router.contacts()->get_introset_by_location(addr)) + if (auto maybe_intro = _router.contacts().get_introset_by_location(addr)) respond(serialize_response({{"INTROSET", maybe_intro->bt_encode()}})); else { @@ -1102,7 +1119,7 @@ namespace llarp if (m) { service::EncryptedIntroSet enc{payload}; - _router.contacts()->services()->PutNode(std::move(enc)); + _router.contacts().put_intro(std::move(enc)); } else { @@ -1114,7 +1131,7 @@ namespace llarp void LinkManager::handle_path_build(oxen::quic::message m, const RouterID& from) { - if (!_router.path_context().AllowingTransit()) + if (!_router.path_context().is_transit_allowed()) { log::warning(link_cat, "got path build request when not permitting transit"); m.respond(serialize_response({{messages::STATUS_KEY, PathBuildMessage::NO_TRANSIT}}), true); @@ -1200,7 +1217,7 @@ namespace llarp hop->info.upstream.from_string(upstream); - if (_router.path_context().HasTransitHop(hop->info)) + if (_router.path_context().has_transit_hop(hop->info)) { log::warning(link_cat, "Invalid PathID; PathIDs must be unique"); m.respond(serialize_response({{messages::STATUS_KEY, PathBuildMessage::BAD_PATHID}}), true); @@ -1237,7 +1254,7 @@ namespace llarp { hop->terminal_hop = true; // we are terminal hop and everything is okay - _router.path_context().PutTransitHop(hop); + _router.path_context().put_transit_hop(hop); m.respond(messages::OK_RESPONSE, false); return; } @@ -1270,7 +1287,7 @@ namespace llarp link_cat, "Upstream returned successful path build response; giving hop info to Router, " "then relaying response"); - _router.path_context().PutTransitHop(hop); + _router.path_context().put_transit_hop(hop); } if (m.timed_out) log::info(link_cat, "Upstream timed out on path build; relaying timeout"); @@ -1380,7 +1397,7 @@ namespace llarp auto success = (crypto::verify(pubkey, to_usv(dict_data), sig) - and _router.exitContext().ObtainNewExit(PubKey{pubkey.data()}, rx_id, flag != 0)); + and _router.exitContext().obtain_new_exit(PubKey{pubkey.data()}, rx_id, flag != 0)); m.respond( ObtainExitMessage::sign_and_serialize_response(_router.identity(), tx_id), not success); @@ -1417,7 +1434,7 @@ namespace llarp throw; } - auto path_ptr = _router.path_context().GetPath(PathID_t{to_usv(tx_id).data()}); + auto path_ptr = _router.path_context().get_path(PathID_t{to_usv(tx_id).data()}); if (crypto::verify(_router.pubkey(), to_usv(dict_data), sig)) path_ptr->enable_exit_traffic(); @@ -1449,7 +1466,8 @@ namespace llarp auto transit_hop = _router.path_context().GetTransitHop(_router.pubkey(), PathID_t{to_usv(tx_id).data()}); - if (auto exit_ep = _router.exitContext().FindEndpointForPath(PathID_t{to_usv(path_id).data()})) + if (auto exit_ep = + _router.exitContext().find_endpoint_for_path(PathID_t{to_usv(path_id).data()})) { if (crypto::verify(exit_ep->PubKey().data(), to_usv(dict_data), sig)) { @@ -1495,7 +1513,7 @@ namespace llarp return; } - auto path_ptr = _router.path_context().GetPath(PathID_t{to_usv(tx_id).data()}); + auto path_ptr = _router.path_context().get_path(PathID_t{to_usv(tx_id).data()}); if (crypto::verify(_router.pubkey(), to_usv(dict_data), sig)) { @@ -1536,7 +1554,7 @@ namespace llarp const auto rx_id = transit_hop->info.rxID; - if (auto exit_ep = router().exitContext().FindEndpointForPath(rx_id)) + if (auto exit_ep = router().exitContext().find_endpoint_for_path(rx_id)) { if (crypto::verify(exit_ep->PubKey().data(), to_usv(dict_data), sig)) { @@ -1580,7 +1598,7 @@ namespace llarp return; } - auto path_ptr = _router.path_context().GetPath(PathID_t{to_usv(tx_id).data()}); + auto path_ptr = _router.path_context().get_path(PathID_t{to_usv(tx_id).data()}); if (path_ptr->SupportsAnyRoles(path::ePathRoleExit | path::ePathRoleSVC) and crypto::verify(_router.pubkey(), to_usv(dict_data), sig)) diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 47e148054..e038db178 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -30,6 +30,8 @@ namespace llarp 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 { @@ -141,7 +143,8 @@ namespace llarp struct LinkManager { public: - explicit LinkManager(Router& r); + static std::unique_ptr + make(Router& r); bool send_control_message( @@ -160,6 +163,8 @@ namespace llarp } private: + explicit LinkManager(Router& r); + bool send_control_message_impl( const RouterID& remote, @@ -310,11 +315,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 diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index 6779d2a27..34adf4ced 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -766,8 +766,7 @@ namespace llarp router_greenlist.clear(); router_greenlist.insert(greenlist.begin(), greenlist.end()); - log::info( - logcat, "lokinet service node list now has ", known_rids.size(), " active router RIDs"); + log::info(logcat, "lokinet service node list now has {} active router RIDs", known_rids.size()); } std::optional @@ -843,7 +842,7 @@ namespace llarp const auto& rid = rc.router_id(); - auto [itr, b] = known_rcs.emplace(std::move(rc)); + auto [itr, b] = known_rcs.insert(std::move(rc)); rc_lookup.emplace(rid, *itr); known_rids.insert(rid); @@ -930,7 +929,7 @@ namespace llarp known_rcs.erase(rc); rc_lookup.erase(rid); - auto [itr, b] = known_rcs.emplace(std::move(rc)); + auto [itr, b] = known_rcs.insert(std::move(rc)); rc_lookup.emplace(rid, *itr); known_rids.insert(rid); @@ -939,9 +938,9 @@ namespace llarp } size_t - NodeDB::num_loaded() const + NodeDB::num_rcs() const { - return _router.loop()->call_get([this]() { return known_rcs.size(); }); + return known_rcs.size(); } bool diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index 6470cd8c5..2cd2fde01 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -178,7 +178,7 @@ namespace llarp fs::path get_path_by_pubkey(RouterID pk) const; - std::unique_ptr _bootstraps; + std::unique_ptr _bootstraps{}; public: explicit NodeDB( @@ -299,10 +299,28 @@ namespace llarp return _pinned_edges; } - std::unique_ptr& + size_t + num_bootstraps() const + { + return _bootstraps ? _bootstraps->size() : 0; + } + + bool + has_bootstraps() const + { + return _bootstraps ? _bootstraps->empty() : false; + } + + const BootstrapList& + bootstrap_list() const + { + return *_bootstraps; + } + + BootstrapList& bootstrap_list() { - return _bootstraps; + return *_bootstraps; } void @@ -354,7 +372,7 @@ namespace llarp /// the number of RCs that are loaded from disk size_t - num_loaded() const; + num_rcs() const; /// do periodic tasks like flush to disk and expiration void diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index a8e30a5a9..b8d9224f4 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -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 hop) + PathContext::put_transit_hop(std::shared_ptr hop) { TransitHopID downstream{hop->info.downstream, hop->info.rxID}; TransitHopID upstream{hop->info.upstream, hop->info.txID}; diff --git a/llarp/path/path_context.hpp b/llarp/path/path_context.hpp index 3f6b4485c..676831d21 100644 --- a/llarp/path/path_context.hpp +++ b/llarp/path/path_context.hpp @@ -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 hop); + put_transit_hop(std::shared_ptr 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); diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index 9ba1392c8..1151f64aa 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -224,7 +224,7 @@ namespace llarp const auto& rid = rc.router_id(); #ifndef TESTNET - if (router->IsBootstrapNode(rid)) + if (router->is_bootstrap_node(rid)) return; #endif if (exclude.count(rid)) diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index d3a8513fe..866e3ab03 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -45,7 +45,7 @@ namespace llarp , _disk_thread{_lmq->add_tagged_thread("disk")} , _rpc_server{nullptr} , _randomStartDelay{platform::is_simulation ? std::chrono::milliseconds{(llarp::randint() % 1250) + 2000} : 0s} - , _link_manager{*this} + // , _link_manager{*this} , _hidden_service_context{this} { _key_manager = std::make_shared(); @@ -59,9 +59,7 @@ namespace llarp } Router::~Router() - { - _contacts.reset(); - } + {} // TODO: investigate changes needed for libquic integration // still needed at all? @@ -86,11 +84,10 @@ namespace llarp return util::StatusObject{ {"running", true}, - {"numNodesKnown", _node_db->num_loaded()}, - {"contacts", _contacts->ExtractStatus()}, + {"numNodesKnown", _node_db->num_rcs()}, {"services", _hidden_service_context.ExtractStatus()}, {"exit", _exit_context.ExtractStatus()}, - {"links", _link_manager.extract_status()}}; + {"links", _link_manager->extract_status()}}; } // TODO: investigate changes needed for libquic integration @@ -102,7 +99,7 @@ namespace llarp auto services = _hidden_service_context.ExtractStatus(); - auto link_types = _link_manager.extract_status(); + auto link_types = _link_manager->extract_status(); uint64_t tx_rate = 0; uint64_t rx_rate = 0; @@ -175,7 +172,7 @@ namespace llarp {"uptime", to_json(Uptime())}, {"numPathsBuilt", pathsCount}, {"numPeersConnected", peers}, - {"numRoutersKnown", _node_db->num_loaded()}, + {"numRoutersKnown", _node_db->num_rcs()}, {"ratio", ratio}, {"txRate", tx_rate}, {"rxRate", rx_rate}, @@ -227,14 +224,14 @@ namespace llarp loop()->call([this, &peer_pubkeys]() { for (auto& pk : peer_pubkeys) - _link_manager.close_connection(pk); + _link_manager->close_connection(pk); }); } void Router::persist_connection_until(const RouterID& remote, llarp_time_t until) { - _link_manager.set_conn_persist(remote, until); + _link_manager->set_conn_persist(remote, until); } std::optional @@ -262,19 +259,19 @@ namespace llarp void Router::connect_to(const RouterID& rid) { - _link_manager.connect_to(rid); + _link_manager->connect_to(rid); } void Router::connect_to(const RemoteRC& rc) { - _link_manager.connect_to(rc); + _link_manager->connect_to(rc); } bool Router::send_data_message(const RouterID& remote, std::string payload) { - return _link_manager.send_data_message(remote, std::move(payload)); + return _link_manager->send_data_message(remote, std::move(payload)); } bool @@ -284,20 +281,20 @@ namespace llarp std::string body, std::function func) { - return _link_manager.send_control_message( + return _link_manager->send_control_message( remote, std::move(ep), std::move(body), std::move(func)); } void Router::for_each_connection(std::function func) { - return _link_manager.for_each_connection(func); + return _link_manager->for_each_connection(func); } bool Router::EnsureIdentity() { - _encryption = _key_manager->encryptionKey; + _encryption = _key_manager->encryption_key; if (is_service_node()) { @@ -340,13 +337,19 @@ namespace llarp } else { - _identity = _key_manager->identityKey; + _identity = _key_manager->identity_key; } if (_identity.IsZero()) + { + log::critical(logcat, "FUCK @ line:{}", __LINE__); return false; + } if (_encryption.IsZero()) + { + log::critical(logcat, "FUCK @ line:{}", __LINE__); return false; + } return true; } @@ -435,7 +438,7 @@ namespace llarp Router::insufficient_peers() const { constexpr int KnownPeerWarningThreshold = 5; - return node_db()->num_loaded() < KnownPeerWarningThreshold; + return node_db()->num_rcs() < KnownPeerWarningThreshold; } std::optional @@ -509,21 +512,22 @@ namespace llarp } size_t - Router::NumberOfConnectedRouters() const + Router::num_router_connections() const { - return _link_manager.get_num_connected(); + return _link_manager->get_num_connected(); } size_t - Router::NumberOfConnectedClients() const + Router::num_client_connections() const { - return _link_manager.get_num_connected_clients(); + return _link_manager->get_num_connected_clients(); } void Router::save_rc() { _node_db->put_rc(router_contact.view()); + log::info(logcat, "Saving RC file to {}", our_rc_file); queue_disk_io([&]() { router_contact.write(our_rc_file); }); } @@ -552,13 +556,14 @@ namespace llarp } // Router config - _link_manager.max_connected_routers = conf.router.max_connected_routers; - _link_manager.min_connected_routers = conf.router.min_connected_routers; + client_router_connections = conf.router.client_router_connections; - encryption_keyfile = _key_manager->m_encKeyPath; - our_rc_file = _key_manager->m_rcPath; - transport_keyfile = _key_manager->m_transportKeyPath; - identity_keyfile = _key_manager->m_idKeyPath; + encryption_keyfile = _key_manager->enckey_path; + our_rc_file = _key_manager->rc_path; + transport_keyfile = _key_manager->transkey_path; + identity_keyfile = _key_manager->idkey_path; + + std::optional _ourAddress; if (auto maybe_ip = conf.links.public_addr) _ourAddress = var::visit([](auto&& ip) { return SockAddr{ip}; }, *maybe_ip); @@ -574,11 +579,22 @@ namespace llarp else throw std::runtime_error{"public ip provided without public port"}; log::debug(logcat, "Using {} for our public address", *_ourAddress); + + _public_address = oxen::quic::Address{static_cast(*_ourAddress)}; + log::critical(logcat, "PUBLIC ADDR: {}", *_public_address); } else - log::debug(logcat, "No explicit public address given; will auto-detect during link setup"); + { + log::debug(logcat, "No explicit public address given; inferring now..."); - _local_addr = conf.links.addr; + if (auto maybe_addr = net().GetBestNetIF()) + { + _public_address = oxen::quic::Address{static_cast(*maybe_addr)}; + log::critical(logcat, "PUBLIC ADDR: {}", *_public_address); + } + } + + _listen_addr = conf.links.addr; RouterContact::BLOCK_BOGONS = conf.router.block_bogons; @@ -618,6 +634,26 @@ namespace llarp auto _bootstrap_rc_list = std::make_unique(); + auto clear_bad_rcs = [&]() mutable { + // in case someone has an old bootstrap file and is trying to use a bootstrap + // that no longer exists + for (auto it = _bootstrap_rc_list->begin(); it != _bootstrap_rc_list->end();) + { + if (it->is_obsolete_bootstrap()) + log::warning(logcat, "ignoring obsolete bootstrap RC: {}", it->router_id()); + else if (not it->verify()) + log::warning(logcat, "ignoring invalid bootstrap RC: {}", it->router_id()); + else + { + ++it; + continue; + } + + // we are in one of the above error cases that we warned about: + it = _bootstrap_rc_list->erase(it); + } + }; + for (const auto& router : configRouters) { log::debug(logcat, "Loading bootstrap router list from {}", defaultBootstrapFile); @@ -629,11 +665,18 @@ namespace llarp _bootstrap_rc_list->emplace(rc); } + clear_bad_rcs(); + if (_bootstrap_rc_list->empty() and not conf.bootstrap.seednode) { auto fallbacks = llarp::load_bootstrap_fallbacks(); - if (_bootstrap_rc_list->empty() and not conf.bootstrap.seednode) + if (auto itr = fallbacks.find(RouterContact::ACTIVE_NETID); itr != fallbacks.end()) + { + _bootstrap_rc_list->merge(itr->second); + } + + if (_bootstrap_rc_list->empty()) { // empty after trying fallback, if set log::error( @@ -644,35 +687,15 @@ namespace llarp throw std::runtime_error("No bootstrap nodes available."); } - } - - // in case someone has an old bootstrap file and is trying to use a bootstrap - // that no longer exists - for (auto it = _bootstrap_rc_list->begin(); it != _bootstrap_rc_list->end();) - { - if (it->is_obsolete_bootstrap()) - log::warning(logcat, "ignoring obsolete bootstrap RC: {}", it->router_id()); - else if (not it->verify()) - log::warning(logcat, "ignoring invalid bootstrap RC: {}", it->router_id()); - else - { - ++it; - continue; - } - // we are in one of the above error cases that we warned about: - it = _bootstrap_rc_list->erase(it); + log::info( + logcat, "Loaded {} default fallback bootstrap routers!", _bootstrap_rc_list->size()); + clear_bad_rcs(); + node_db()->set_bootstrap_routers(std::move(_bootstrap_rc_list)); } - node_db()->set_bootstrap_routers(std::move(_bootstrap_rc_list)); - if (conf.bootstrap.seednode) - LogInfo("we are a seed node"); - else - LogInfo("Loaded ", _bootstrap_rc_list->size(), " bootstrap routers"); - - // Init components after relevant config settings loaded - _link_manager.init(); + log::critical(logcat, "We are a bootstrap seed node!"); // TODO: RC refactor here if (_is_service_node) @@ -713,14 +736,18 @@ namespace llarp } bool - Router::IsBootstrapNode(const RouterID r) const + Router::is_bootstrap_node(const RouterID r) const { - const auto& b = _node_db->bootstrap_list(); - return std::count_if( - b->begin(), - b->end(), - [r](const RemoteRC& rc) -> bool { return rc.router_id() == r; }) - > 0; + if (_node_db->has_bootstraps()) + { + const auto& b = _node_db->bootstrap_list(); + return std::count_if( + b.begin(), + b.end(), + [r](const RemoteRC& rc) -> bool { return rc.router_id() == r; }) + > 0; + } + return false; } bool @@ -737,16 +764,16 @@ namespace llarp log::info( logcat, "{} RCs loaded with {} bootstrap peers and {} router connections!", - node_db()->num_loaded(), - _node_db->bootstrap_list()->size(), - NumberOfConnectedRouters()); + _node_db->num_rcs(), + _node_db->num_bootstraps(), + num_router_connections()); if (is_service_node()) { log::info( logcat, "Local service node has {} client connections since last RC update ({} to expiry)", - NumberOfConnectedClients(), + num_client_connections(), router_contact.age(now), router_contact.time_to_expiry(now)); } @@ -766,9 +793,9 @@ namespace llarp fmt::format_to( out, " snode | known/svc/clients: {}/{}/{}", - node_db()->num_loaded(), - NumberOfConnectedRouters(), - NumberOfConnectedClients()); + node_db()->num_rcs(), + num_router_connections(), + num_client_connections()); fmt::format_to( out, " | {} active paths | block {} ", @@ -784,10 +811,7 @@ namespace llarp else { fmt::format_to( - out, - " client | known/connected: {}/{}", - node_db()->num_loaded(), - NumberOfConnectedRouters()); + out, " client | known/connected: {}/{}", node_db()->num_rcs(), num_router_connections()); if (auto ep = hidden_service_context().GetDefault()) { @@ -850,7 +874,7 @@ namespace llarp auto view = router_contact.view(); - _link_manager.gossip_rc( + _link_manager->gossip_rc( pubkey(), std::string{reinterpret_cast(view.data()), view.size()}); last_rc_gossip = now_timepoint; @@ -891,14 +915,14 @@ namespace llarp // remove RCs for nodes that are no longer allowed by network policy node_db()->RemoveIf([&](const RemoteRC& rc) -> bool { // don't purge bootstrap nodes from nodedb - if (IsBootstrapNode(rc.router_id())) + if (is_bootstrap_node(rc.router_id())) { log::trace(logcat, "Not removing {}: is bootstrap node", rc.router_id()); return false; } // if for some reason we stored an RC that isn't a valid router // purge this entry - if (not rc.is_public_router()) + if (not rc.is_public_addressable()) { log::debug(logcat, "Removing {}: not a valid router", rc.router_id()); return true; @@ -956,11 +980,11 @@ namespace llarp } */ - _link_manager.check_persisting_conns(now); + _link_manager->check_persisting_conns(now); - size_t connected = NumberOfConnectedRouters(); + size_t connected = num_router_connections(); - size_t connectToNum = _link_manager.min_connected_routers; + size_t connectToNum = _link_manager->client_router_connections; const auto& pinned_edges = _node_db->pinned_edges(); const auto pinned_count = pinned_edges.size(); @@ -989,7 +1013,7 @@ namespace llarp log::error( logcat, "We appear to be an active service node, but have only {} known peers.", - node_db()->num_loaded()); + node_db()->num_rcs()); _next_decomm_warning = now + DecommissionWarnInterval; } } @@ -1000,7 +1024,7 @@ namespace llarp { size_t dlt = connectToNum - connected; LogDebug("connecting to ", dlt, " random routers to keep alive"); - _link_manager.connect_to_random(dlt); + _link_manager->connect_to_random(dlt); } _hidden_service_context.Tick(now); @@ -1023,7 +1047,7 @@ namespace llarp bool Router::GetRandomConnectedRouter(RemoteRC& result) const { - return _link_manager.get_random_connected(result); + return _link_manager->get_random_connected(result); } const std::set& @@ -1054,16 +1078,22 @@ namespace llarp bool Router::Run() { + log::critical(logcat, "{} called", __PRETTY_FUNCTION__); + if (is_running || is_stopping) return false; - // TODO: look at _ourAddress + router_contact = LocalRC::make( + identity(), _is_service_node and _public_address ? *_public_address : _listen_addr); - router_contact = LocalRC::make(identity(), local_addr()); + _link_manager = LinkManager::make(*this); - if (is_service_node() and not router_contact.is_public_router()) + // Init components after relevant config settings loaded + _link_manager->init(); + + if (is_service_node()) { - if (not router_contact.is_public_router()) + if (not router_contact.is_public_addressable()) { log::error(logcat, "Router is configured as relay but has no reachable addresses!"); return false; @@ -1101,16 +1131,19 @@ namespace llarp log::info(logcat, "Loading NodeDB from disk..."); _node_db->load_from_disk(); - _contacts = std::make_shared(llarp::dht::Key_t(pubkey()), *this); + log::info(logcat, "Creating Introset Contacts..."); + _contacts = std::make_unique(*this); - for (const auto& rc : *_node_db->bootstrap_list()) + if (_node_db->has_bootstraps()) { - node_db()->put_rc(rc); - _contacts->rc_nodes()->PutNode(rc); - log::info(logcat, "Added bootstrap node (rid: {})", rc.router_id()); - } + for (const auto& rc : _node_db->bootstrap_list()) + { + node_db()->put_rc(rc); + log::info(logcat, "Added bootstrap node (rid: {})", rc.router_id()); + } - log::info(logcat, "Router populated NodeDB with {} routers", _node_db->num_loaded()); + log::info(logcat, "Router populated NodeDB with {} routers", _node_db->num_rcs()); + } _loop->call_every(ROUTER_TICK_INTERVAL, weak_from_this(), [this] { Tick(); }); @@ -1155,7 +1188,7 @@ namespace llarp // try to make a session to this random router // this will do a dht lookup if needed - _link_manager.test_reachability( + _link_manager->test_reachability( router, [this, rid = router, previous = fails](oxen::quic::connection_interface& conn) { log::info( @@ -1224,7 +1257,7 @@ namespace llarp void Router::StopLinks() { - _link_manager.stop(); + _link_manager->stop(); } void @@ -1241,7 +1274,7 @@ namespace llarp LogWarn("stopping router hard"); llarp::sys::service_manager->stopping(); hidden_service_context().StopAll(); - _exit_context.Stop(); + _exit_context.stop(); StopLinks(); Close(); } @@ -1261,27 +1294,27 @@ namespace llarp } is_stopping.store(true); + if (auto level = log::get_level_default(); level > log::Level::info and level != log::Level::off) log::reset_level(log::Level::info); - log::info(logcat, "stopping"); + + log::info(logcat, "stopping service manager..."); llarp::sys::service_manager->stopping(); - log::debug(logcat, "stopping hidden service context"); + + log::debug(logcat, "stopping hidden service context..."); hidden_service_context().StopAll(); - llarp::sys::service_manager->stopping(); - log::debug(logcat, "stopping exit context"); - _exit_context.Stop(); - llarp::sys::service_manager->stopping(); - log::debug(logcat, "final upstream pump"); - llarp::sys::service_manager->stopping(); - log::debug(logcat, "final links pump"); + + log::debug(logcat, "stopping exit context..."); + _exit_context.stop(); + _loop->call_later(200ms, [this] { AfterStopIssued(); }); } bool Router::HasSessionTo(const RouterID& remote) const { - return _link_manager.have_connection_to(remote); + return _link_manager->have_connection_to(remote); } std::string @@ -1300,19 +1333,20 @@ namespace llarp Router::ConnectToRandomRouters(int _want) { const size_t want = _want; - auto connected = NumberOfConnectedRouters(); + auto connected = num_router_connections(); + if (connected >= want) return; - _link_manager.connect_to_random(want); + + _link_manager->connect_to_random(want); } bool Router::init_service_node() { - LogInfo("accepting transit traffic"); - paths.AllowTransit(); - _contacts->set_transit_allowed(true); - _exit_context.AddExitEndpoint("default", _config->network, _config->dns); + log::info(logcat, "Router accepting transit traffic..."); + paths.allow_transit(); + _exit_context.add_exit_endpoint("default", _config->network, _config->dns); return true; } @@ -1338,9 +1372,9 @@ namespace llarp } oxen::quic::Address - Router::local_addr() const + Router::listen_addr() const { - return _local_addr; + return _listen_addr; } void diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 3fe14c868..db73d753d 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -91,8 +91,8 @@ namespace llarp consensus::reachability_testing router_testing; - std::optional _ourAddress; - oxen::quic::Address _local_addr; + std::optional _public_address; // public addr for relays + oxen::quic::Address _listen_addr; EventLoop_ptr _loop; std::shared_ptr _vpn; @@ -122,7 +122,9 @@ namespace llarp oxenmq::address rpc_addr; Profiling _router_profiling; fs::path _profile_file; - LinkManager _link_manager{*this}; + + std::unique_ptr _link_manager; + int client_router_connections; // should we be sending padded messages every interval? bool send_padding = false; @@ -155,6 +157,12 @@ namespace llarp std::chrono::system_clock::time_point next_bootstrap_attempt{last_rc_gossip}; public: + int + required_num_client_conns() const + { + return client_router_connections; + } + RouterID local_rid() const { @@ -176,10 +184,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 @@ -212,10 +226,16 @@ namespace llarp LinkManager& link_manager() { - return _link_manager; + return *_link_manager; + } + + const LinkManager& + link_manager() const + { + return *_link_manager; } - inline int + int outbound_udp_socket() const { return _outbound_udp_socket; @@ -282,7 +302,7 @@ namespace llarp } oxen::quic::Address - local_addr() const; + listen_addr() const; util::StatusObject ExtractStatus() const; @@ -473,7 +493,7 @@ namespace llarp std::string body, std::function func = nullptr); - bool IsBootstrapNode(RouterID) const; + bool is_bootstrap_node(RouterID) const; /// call internal router ticker void @@ -490,11 +510,11 @@ namespace llarp /// 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; diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index 0cd402802..585e72f99 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -102,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()}}; @@ -221,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(); } diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index ce99d3822..0aee92c27 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -176,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 diff --git a/llarp/router_contact_local.cpp b/llarp/router_contact_local.cpp index 9b82551cc..47ed6009c 100644 --- a/llarp/router_contact_local.cpp +++ b/llarp/router_contact_local.cpp @@ -22,7 +22,8 @@ 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(); } @@ -123,8 +124,6 @@ namespace llarp static_assert(llarp::LOKINET_VERSION.size() == 3); btdp.append( "v", std::string_view{reinterpret_cast(llarp::LOKINET_VERSION.data()), 3}); - - bt_sign(btdp); } void diff --git a/llarp/router_contact_remote.cpp b/llarp/router_contact_remote.cpp index 8e8188052..f62849adf 100644 --- a/llarp/router_contact_remote.cpp +++ b/llarp/router_contact_remote.cpp @@ -89,7 +89,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; } diff --git a/llarp/rpc/rpc_server.cpp b/llarp/rpc/rpc_server.cpp index ea657fb81..c6873ff0f 100644 --- a/llarp/rpc/rpc_server.cpp +++ b/llarp/rpc/rpc_server.cpp @@ -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); @@ -329,7 +329,7 @@ namespace llarp::rpc } m_Router.loop()->call([&]() { - auto endpoint = m_Router.exitContext().GetExitEndpoint("default"); + auto endpoint = m_Router.exitContext().get_exit_endpoint("default"); if (endpoint == nullptr) { diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 6f7ea08a0..8c3264fe3 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -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 { @@ -1310,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; @@ -1335,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 /* diff --git a/llarp/service/identity.cpp b/llarp/service/identity.cpp index a79c6ae97..63ba3c5d6 100644 --- a/llarp/service/identity.cpp +++ b/llarp/service/identity.cpp @@ -97,7 +97,7 @@ namespace llarp::service if (exists and needBackup) { - KeyManager::backupFileByMoving(fname); + KeyManager::copy_backup_keyfile(fname); exists = false; }