From 07271f9ae7a9d0f39c3b866d06d625e218315419 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Tue, 31 Oct 2023 13:49:01 -0700 Subject: [PATCH] RC refactor layout - Local and Remote RC's now implemented with discrete functionalities and uses --- CMakeLists.txt | 2 +- daemon/lokinet-bootstrap.cpp | 2 +- daemon/lokinet.cpp | 5 +- llarp/CMakeLists.txt | 2 + llarp/bootstrap.cpp | 2 +- llarp/config/config.cpp | 9 +- llarp/config/ini.cpp | 2 +- llarp/config/key_manager.cpp | 4 +- llarp/constants/version.cpp.in | 11 +- llarp/constants/version.hpp | 11 +- llarp/context.cpp | 3 +- llarp/crypto/crypto.cpp | 19 +- llarp/crypto/crypto.hpp | 14 +- llarp/crypto/types.cpp | 79 ++--- llarp/crypto/types.hpp | 75 +---- llarp/dht/kademlia.hpp | 2 +- llarp/dht/node.hpp | 6 +- llarp/handlers/exit.cpp | 34 +- llarp/link/contacts.cpp | 2 +- llarp/link/link_manager.cpp | 30 +- llarp/link/link_manager.hpp | 4 +- llarp/messages/path.hpp | 4 +- llarp/messages/relay.cpp | 4 +- llarp/nodedb.cpp | 38 +-- llarp/nodedb.hpp | 2 +- llarp/path/path.cpp | 16 +- llarp/path/pathbuilder.cpp | 24 +- llarp/profiling.cpp | 10 +- llarp/router/rc_gossiper.cpp | 6 +- llarp/router/rc_lookup_handler.cpp | 31 +- llarp/router/route_poker.cpp | 6 +- llarp/router/router.cpp | 96 +++--- llarp/router/router.hpp | 2 +- llarp/router_contact.cpp | 516 +++++++++++------------------ llarp/router_contact.hpp | 357 ++++++++++++++------ llarp/router_contact_local.cpp | 108 ++++++ llarp/router_contact_remote.cpp | 69 ++++ llarp/router_id.hpp | 8 +- llarp/rpc/lokid_rpc_client.cpp | 2 +- llarp/rpc/rpc_server.cpp | 2 +- llarp/service/endpoint.cpp | 6 +- llarp/service/identity.cpp | 8 +- llarp/service/protocol.cpp | 2 +- llarp/util/bencode.hpp | 2 +- llarp/util/file.cpp | 10 +- llarp/util/file.hpp | 8 +- 46 files changed, 884 insertions(+), 771 deletions(-) create mode 100644 llarp/router_contact_local.cpp create mode 100644 llarp/router_contact_remote.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b707a0f5..8c3b407d8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ if(APPLE) set(LOKINET_APPLE_BUILD 5) endif() -set(RELEASE_MOTTO "Our Lord And Savior" CACHE STRING "Release motto") +set(LOKINET_RELEASE_MOTTO "Anonymous, decentralized, IP-based overlay network" CACHE STRING "Release motto") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") diff --git a/daemon/lokinet-bootstrap.cpp b/daemon/lokinet-bootstrap.cpp index e1ad9cb4d..afdecec72 100644 --- a/daemon/lokinet-bootstrap.cpp +++ b/daemon/lokinet-bootstrap.cpp @@ -86,7 +86,7 @@ main(int argc, char* argv[]) #else cpr::Get( cpr::Url{bootstrap_url}, - cpr::Header{{"User-Agent", std::string{llarp::VERSION_FULL}}}, + cpr::Header{{"User-Agent", std::string{llarp::LOKINET_VERSION_FULL}}}, cpr::Ssl(cpr::ssl::CaPath{X509_get_default_cert_dir()})); #endif if (resp.status_code != 200) diff --git a/daemon/lokinet.cpp b/daemon/lokinet.cpp index b56227f40..67ac4a671 100644 --- a/daemon/lokinet.cpp +++ b/daemon/lokinet.cpp @@ -403,7 +403,7 @@ namespace { if (options.version) { - std::cout << llarp::VERSION_FULL << std::endl; + std::cout << llarp::LOKINET_VERSION_FULL << std::endl; return 0; } @@ -548,7 +548,8 @@ namespace static void run_main_context(std::optional confFile, const llarp::RuntimeOptions opts) { - llarp::LogInfo(fmt::format("starting up {} {}", llarp::VERSION_FULL, llarp::RELEASE_MOTTO)); + llarp::LogInfo(fmt::format( + "starting up {} {}", llarp::LOKINET_VERSION_FULL, llarp::LOKINET_RELEASE_MOTTO)); try { std::shared_ptr conf; diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index 06e4ac5b2..cce2e29b5 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -99,6 +99,8 @@ lokinet_add_library(lokinet-time-place net/net_int.cpp net/sock_addr.cpp router_contact.cpp + router_contact_local.cpp + router_contact_remote.cpp router_id.cpp router_version.cpp # to be deleted shortly service/address.cpp diff --git a/llarp/bootstrap.cpp b/llarp/bootstrap.cpp index 624757322..f5a795ea0 100644 --- a/llarp/bootstrap.cpp +++ b/llarp/bootstrap.cpp @@ -60,7 +60,7 @@ namespace llarp else { RouterContact rc; - if (not rc.Read(fpath)) + if (not rc.read(fpath)) { throw std::runtime_error{ fmt::format("failed to decode bootstrap RC, file='{}', rc={}", fpath, rc)}; diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index e28652d9d..64d473564 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -58,9 +58,10 @@ namespace llarp conf.defineOption( "router", "netid", - Default{llarp::DEFAULT_NETID}, + Default{llarp::LOKINET_DEFAULT_NETID}, Comment{ - "Network ID; this is '"s + llarp::DEFAULT_NETID + "' for mainnet, 'gamma' for testnet.", + "Network ID; this is '"s + llarp::LOKINET_DEFAULT_NETID + + "' for mainnet, 'gamma' for testnet.", }, [this](std::string arg) { if (arg.size() > NetID::size()) @@ -1329,7 +1330,7 @@ namespace llarp std::set seenRanges; for (const auto& hop : rcs) { - const auto network_addr = net::In6ToHUInt(hop.addr.in6().sin6_addr) & netmask; + const auto network_addr = net::In6ToHUInt(hop.addr6()->in6().sin6_addr) & netmask; if (auto [it, inserted] = seenRanges.emplace(network_addr, netmask); not inserted) { return false; @@ -1444,7 +1445,7 @@ namespace llarp { try { - ini = util::slurp_file(*fname); + ini = util::file_to_string(*fname); } catch (const std::exception&) { diff --git a/llarp/config/ini.cpp b/llarp/config/ini.cpp index 66b55dd4c..c74052819 100644 --- a/llarp/config/ini.cpp +++ b/llarp/config/ini.cpp @@ -15,7 +15,7 @@ namespace llarp { try { - m_Data = util::slurp_file(fname); + m_Data = util::file_to_string(fname); } catch (const std::exception& e) { diff --git a/llarp/config/key_manager.cpp b/llarp/config/key_manager.cpp index 3df661847..3df244dea 100644 --- a/llarp/config/key_manager.cpp +++ b/llarp/config/key_manager.cpp @@ -52,7 +52,7 @@ namespace llarp m_transportKeyPath = deriveFile(our_transport_key_filename, config.router.m_transportKeyFile); RouterContact rc; - bool exists = rc.Read(m_rcPath); + bool exists = rc.read(m_rcPath); if (not exists and not genIfAbsent) { LogError("Could not read RouterContact at path ", m_rcPath); @@ -61,7 +61,7 @@ namespace llarp // we need to back up keys if our self.signed doesn't appear to have a // valid signature - m_needBackup = (isSNode and not rc.VerifySignature()); + m_needBackup = (isSNode and not rc.verify_signature()); // 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 diff --git a/llarp/constants/version.cpp.in b/llarp/constants/version.cpp.in index e07223705..60d3af6ae 100644 --- a/llarp/constants/version.cpp.in +++ b/llarp/constants/version.cpp.in @@ -4,12 +4,11 @@ namespace llarp { // clang-format off - const std::array VERSION{{@lokinet_VERSION_MAJOR@, @lokinet_VERSION_MINOR@, @lokinet_VERSION_PATCH@}}; - const std::array ROUTER_VERSION{{llarp::constants::proto_version, @lokinet_VERSION_MAJOR@, @lokinet_VERSION_MINOR@, @lokinet_VERSION_PATCH@}}; - const char* const VERSION_TAG = "@VERSIONTAG@"; - const char* const VERSION_FULL = "lokinet-@lokinet_VERSION_MAJOR@.@lokinet_VERSION_MINOR@.@lokinet_VERSION_PATCH@-@VERSIONTAG@"; + const std::array 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 RELEASE_MOTTO = "@RELEASE_MOTTO@"; - const char* const DEFAULT_NETID = "lokinet"; + const char* const LOKINET_RELEASE_MOTTO = "@RELEASE_MOTTO@"; + const char* const LOKINET_DEFAULT_NETID = "lokinet"; // clang-format on } // namespace llarp diff --git a/llarp/constants/version.hpp b/llarp/constants/version.hpp index 1bfd68d31..f79b842e2 100644 --- a/llarp/constants/version.hpp +++ b/llarp/constants/version.hpp @@ -6,11 +6,10 @@ namespace llarp { // Given a full lokinet version of: lokinet-1.2.3-abc these are: - extern const std::array VERSION; // [1, 2, 3] - extern const std::array ROUTER_VERSION; // [proto, 1, 2, 3] - extern const char* const VERSION_TAG; // "abc" - extern const char* const VERSION_FULL; // "lokinet-1.2.3-abc" + extern const std::array LOKINET_VERSION; + extern const char* const LOKINET_VERSION_TAG; + extern const char* const LOKINET_VERSION_FULL; - extern const char* const RELEASE_MOTTO; - extern const char* const DEFAULT_NETID; + extern const char* const LOKINET_RELEASE_MOTTO; + extern const char* const LOKINET_DEFAULT_NETID; } // namespace llarp diff --git a/llarp/context.cpp b/llarp/context.cpp index be4f61d97..ab8ae70f9 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -59,7 +59,8 @@ namespace llarp throw std::runtime_error("Cannot call Setup() on context without a Config"); if (opts.showBanner) - llarp::LogInfo(fmt::format("{} {}", llarp::VERSION_FULL, llarp::RELEASE_MOTTO)); + llarp::LogInfo( + fmt::format("{} {}", llarp::LOKINET_VERSION_FULL, llarp::LOKINET_RELEASE_MOTTO)); if (!loop) { diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index f8a61535a..7b6aa046a 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -273,6 +273,14 @@ namespace llarp return true; } + bool + crypto::verify(const PubKey& pub, ustring_view data, ustring_view sig) + { + return (pub.size() == 32 && sig.size() == 64) + ? crypto_sign_verify_detached(sig.data(), data.data(), data.size(), pub.data()) != -1 + : false; + } + bool crypto::verify(const PubKey& pub, uint8_t* buf, size_t size, const Signature& sig) { @@ -428,11 +436,6 @@ namespace llarp return true; } - bool - crypto::seed_to_secretkey(llarp::SecretKey& secret, const llarp::IdentitySecret& seed) - { - return crypto_sign_ed25519_seed_keypair(secret.data() + 32, secret.data(), seed.data()) != -1; - } void crypto::randomize(uint8_t* buf, size_t len) { @@ -517,19 +520,19 @@ namespace llarp #endif const byte_t* - seckey_topublic(const SecretKey& sec) + seckey_to_pubkey(const SecretKey& sec) { return sec.data() + 32; } const byte_t* - pq_keypair_to_public(const PQKeyPair& k) + pq_keypair_to_pubkey(const PQKeyPair& k) { return k.data() + PQ_SECRETKEYSIZE; } const byte_t* - pq_keypair_to_secret(const PQKeyPair& k) + pq_keypair_to_seckey(const PQKeyPair& k) { return k.data(); } diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index 370b23e34..1b5c9a239 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -64,8 +64,11 @@ namespace llarp sign(Signature&, const PrivateKey&, uint8_t* buf, size_t size); /// ed25519 verify bool + verify(const PubKey&, ustring_view, ustring_view); + bool verify(const PubKey&, uint8_t*, size_t, const Signature&); - bool verify(ustring_view, ustring_view, ustring_view); + bool + verify(ustring_view, ustring_view, ustring_view); bool verify(uint8_t*, uint8_t*, size_t, uint8_t*); @@ -87,9 +90,6 @@ namespace llarp uint64_t key_n, const AlignedBuffer<32>* hash = nullptr); - /// seed to secretkey - bool - seed_to_secretkey(llarp::SecretKey&, const llarp::IdentitySecret&); /// randomize buffer void randomize(uint8_t* buf, size_t len); @@ -124,13 +124,13 @@ namespace llarp randint(); const byte_t* - seckey_topublic(const SecretKey& secret); + seckey_to_pubkey(const SecretKey& secret); const byte_t* - pq_keypair_to_public(const PQKeyPair& keypair); + pq_keypair_to_pubkey(const PQKeyPair& keypair); const byte_t* - pq_keypair_to_secret(const PQKeyPair& keypair); + pq_keypair_to_seckey(const PQKeyPair& keypair); /// rng type that uses llarp::randint(), which is cryptographically secure struct CSRNG diff --git a/llarp/crypto/types.cpp b/llarp/crypto/types.cpp index 30d4a3a9a..c7a141bbd 100644 --- a/llarp/crypto/types.cpp +++ b/llarp/crypto/types.cpp @@ -1,5 +1,6 @@ #include "types.hpp" +#include #include #include @@ -32,6 +33,36 @@ namespace llarp return oxenc::to_hex(begin(), end()); } + PubKey::operator RouterID() const + { + return {as_array()}; + } + + PubKey& + PubKey::operator=(const byte_t* ptr) + { + std::copy(ptr, ptr + SIZE, begin()); + return *this; + } + + bool + operator==(const PubKey& lhs, const PubKey& rhs) + { + return lhs.as_array() == rhs.as_array(); + } + + bool + operator==(const PubKey& lhs, const RouterID& rhs) + { + return lhs.as_array() == rhs.as_array(); + } + + bool + operator==(const RouterID& lhs, const PubKey& rhs) + { + return lhs.as_array() == rhs.as_array(); + } + bool SecretKey::LoadFromFile(const fs::path& fname) { @@ -39,7 +70,7 @@ namespace llarp std::array tmp; try { - sz = util::slurp_file(fname, tmp.data(), tmp.size()); + sz = util::file_to_buffer(fname, tmp.data(), tmp.size()); } catch (const std::exception&) { @@ -107,53 +138,7 @@ namespace llarp { return false; } - return true; - } - bool - IdentitySecret::LoadFromFile(const fs::path& fname) - { - std::array buf; - size_t sz; - try - { - sz = util::slurp_file(fname, buf.data(), buf.size()); - } - catch (const std::exception& e) - { - llarp::LogError("failed to load service node seed: ", e.what()); - return false; - } - if (sz != SIZE) - { - llarp::LogError("service node seed size invalid: ", sz, " != ", SIZE); - return false; - } - std::copy(buf.begin(), buf.end(), begin()); return true; } - - byte_t* - Signature::Lo() - { - return data(); - } - - const byte_t* - Signature::Lo() const - { - return data(); - } - - byte_t* - Signature::Hi() - { - return data() + 32; - } - - const byte_t* - Signature::Hi() const - { - return data() + 32; - } } // namespace llarp diff --git a/llarp/crypto/types.hpp b/llarp/crypto/types.hpp index e4188c35d..a91192770 100644 --- a/llarp/crypto/types.hpp +++ b/llarp/crypto/types.hpp @@ -2,7 +2,6 @@ #include "constants.hpp" -#include #include #include #include @@ -15,7 +14,9 @@ namespace llarp using SharedSecret = AlignedBuffer; using KeyExchangeNonce = AlignedBuffer<32>; - struct PubKey final : public AlignedBuffer + struct RouterID; + + struct PubKey : public AlignedBuffer { PubKey() = default; @@ -37,36 +38,20 @@ namespace llarp static PubKey from_string(const std::string& s); - operator RouterID() const - { - return {as_array()}; - } + operator RouterID() const; PubKey& - operator=(const byte_t* ptr) - { - std::copy(ptr, ptr + SIZE, begin()); - return *this; - } + operator=(const byte_t* ptr); }; - inline bool - operator==(const PubKey& lhs, const PubKey& rhs) - { - return lhs.as_array() == rhs.as_array(); - } + bool + operator==(const PubKey& lhs, const PubKey& rhs); - inline bool - operator==(const PubKey& lhs, const RouterID& rhs) - { - return lhs.as_array() == rhs.as_array(); - } + bool + operator==(const PubKey& lhs, const RouterID& rhs); - inline bool - operator==(const RouterID& lhs, const PubKey& rhs) - { - return lhs.as_array() == rhs.as_array(); - } + bool + operator==(const RouterID& lhs, const PubKey& rhs); struct PrivateKey; @@ -161,58 +146,24 @@ namespace llarp toPublic(PubKey& pubkey) const; }; - /// IdentitySecret is a secret key from a service node secret seed - struct IdentitySecret final : public AlignedBuffer<32> - { - IdentitySecret() : AlignedBuffer<32>() - {} - - /// no copy constructor - explicit IdentitySecret(const IdentitySecret&) = delete; - // no byte data constructor - explicit IdentitySecret(const byte_t*) = delete; - - /// load service node seed from file - bool - LoadFromFile(const fs::path& fname); - - std::string_view - ToString() const - { - return "[IdentitySecret]"; - } - }; - template <> constexpr inline bool IsToStringFormattable = true; template <> constexpr inline bool IsToStringFormattable = true; template <> constexpr inline bool IsToStringFormattable = true; - template <> - constexpr inline bool IsToStringFormattable = true; using ShortHash = AlignedBuffer; using LongHash = AlignedBuffer; struct Signature final : public AlignedBuffer { - byte_t* - Hi(); - - const byte_t* - Hi() const; - - byte_t* - Lo(); - - const byte_t* - Lo() const; + // }; using TunnelNonce = AlignedBuffer; using SymmNonce = AlignedBuffer; - using SymmKey = AlignedBuffer<32>; + using SymmKey = AlignedBuffer<32>; // not used using PQCipherBlock = AlignedBuffer; using PQPubKey = AlignedBuffer; diff --git a/llarp/dht/kademlia.hpp b/llarp/dht/kademlia.hpp index 776d8cb37..6508898b4 100644 --- a/llarp/dht/kademlia.hpp +++ b/llarp/dht/kademlia.hpp @@ -22,7 +22,7 @@ namespace llarp::dht bool operator()(const RouterContact& left, const RouterContact& right) const { - return (left.pubkey ^ us) < (right.pubkey ^ us); + return (left.router_id() ^ us) < (right.router_id() ^ us); } }; } // namespace llarp::dht diff --git a/llarp/dht/node.hpp b/llarp/dht/node.hpp index 0f2deecc2..36ac3e9d5 100644 --- a/llarp/dht/node.hpp +++ b/llarp/dht/node.hpp @@ -19,19 +19,19 @@ namespace llarp::dht ID.Zero(); } - RCNode(const RouterContact& other) : rc(other), ID(other.pubkey) + RCNode(const RouterContact& other) : rc(other), ID(other.router_id()) {} util::StatusObject ExtractStatus() const { - return rc.ExtractStatus(); + return rc.extract_status(); } bool operator<(const RCNode& other) const { - return rc.last_updated < other.rc.last_updated; + return rc.timestamp() < other.rc.timestamp(); } }; diff --git a/llarp/handlers/exit.cpp b/llarp/handlers/exit.cpp index 3702c3f2a..008e12b26 100644 --- a/llarp/handlers/exit.cpp +++ b/llarp/handlers/exit.cpp @@ -580,25 +580,29 @@ namespace llarp::handlers { router->modify_rc( [srvRecords = SRVRecords()](RouterContact rc) -> std::optional { + // TODO: update this RouterContact handling + // check if there are any new srv records - bool shouldUpdate = false; + // bool shouldUpdate = false; - for (const auto& rcSrv : rc.srvRecords) - { - if (srvRecords.count(rcSrv) == 0) - shouldUpdate = true; - } + // for (const auto& rcSrv : rc.srvRecords) + // { + // if (srvRecords.count(rcSrv) == 0) + // shouldUpdate = true; + // } + + // // no new records so don't modify + // if (not shouldUpdate) + // return std::nullopt; + + // // we got new entries so we clear the whole vector on the rc and recreate it + // rc.srvRecords.clear(); - // no new records so don't modify - if (not shouldUpdate) - return std::nullopt; + // for (auto& record : srvRecords) + // rc.srvRecords.emplace_back(record); - // we got new entries so we clear the whole vector on the rc and recreate it - rc.srvRecords.clear(); - for (auto& record : srvRecords) - rc.srvRecords.emplace_back(record); - // set the verssion to 1 because we have srv records - rc.version = 1; + // // set the verssion to 1 because we have srv records + // rc.version = 1; return rc; }); } diff --git a/llarp/link/contacts.cpp b/llarp/link/contacts.cpp index 82c7b7b44..de184ea52 100644 --- a/llarp/link/contacts.cpp +++ b/llarp/link/contacts.cpp @@ -39,7 +39,7 @@ namespace llarp while (itr != nodes.end()) { - if (itr->second.rc.IsExpired(now)) + if (itr->second.rc.is_expired(now)) itr = nodes.erase(itr); else ++itr; diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index f3f504795..e6515b7f4 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -20,7 +20,7 @@ namespace llarp std::shared_ptr Endpoint::get_conn(const RouterContact& rc) const { - if (auto itr = conns.find(rc.pubkey); itr != conns.end()) + if (auto itr = conns.find(rc.router_id()); itr != conns.end()) return itr->second; return nullptr; @@ -303,14 +303,14 @@ namespace llarp void LinkManager::connect_to(const RouterContact& rc) { - if (auto conn = ep.get_conn(rc.pubkey); conn) + if (auto conn = ep.get_conn(rc.router_id()); conn) { // TODO: should implement some connection failed logic, but not the same logic that // would be executed for another failure case return; } - auto& remote_addr = rc.addr; + const auto& remote_addr = rc.addr(); // TODO: confirm remote end is using the expected pubkey (RouterID). // TODO: ALPN for "client" vs "relay" (could just be set on endpoint creation) @@ -491,9 +491,9 @@ namespace llarp if (auto maybe_other = node_db->GetRandom(filter)) { - exclude.insert(maybe_other->pubkey); + exclude.insert(maybe_other->router_id()); - if (not rc_lookup->is_session_allowed(maybe_other->pubkey)) + if (not rc_lookup->is_session_allowed(maybe_other->router_id())) continue; connect_to(*maybe_other); @@ -609,23 +609,25 @@ namespace llarp target_rid.FromString(target_key); const auto target_addr = dht::Key_t{reinterpret_cast(target_key.data())}; - const auto& local_rid = _router.rc().pubkey; + const auto& local_rid = _router.rc().router_id(); const auto local_key = dht::Key_t{local_rid}; if (is_exploratory) { std::string neighbors{}; + const auto closest_rcs = _router.node_db()->find_many_closest_to(target_addr, RC_LOOKUP_STORAGE_REDUNDANCY); for (const auto& rc : closest_rcs) { - const auto& rid = rc.pubkey; + const auto& rid = rc.router_id(); if (_router.router_profiling().IsBadForConnect(rid) || target_rid == rid || local_rid == rid) continue; - neighbors += rid.bt_encode(); + neighbors += + rid.bt_encode(); // TODO: refactor to use reference to bt_dict_producer subdict } m.respond( @@ -635,12 +637,12 @@ namespace llarp else { const auto closest_rc = _router.node_db()->find_closest_to(target_addr); - const auto& closest_rid = closest_rc.pubkey; + const auto& closest_rid = closest_rc.router_id(); const auto closest_key = dht::Key_t{closest_rid}; if (target_addr == closest_key) { - if (closest_rc.ExpiresSoon(llarp::time_now_ms())) + if (closest_rc.expires_within_delta(llarp::time_now_ms())) { send_control_message( target_rid, @@ -837,7 +839,7 @@ namespace llarp const auto now = _router.now(); const auto addr = dht::Key_t{reinterpret_cast(derived_signing_key.data())}; - const auto local_key = _router.rc().pubkey; + const auto local_key = _router.rc().router_id(); if (not service::EncryptedIntroSet::verify(introset, derived_signing_key, sig)) { @@ -878,7 +880,7 @@ namespace llarp log::info(link_cat, "Relaying PublishIntroMessage for {}", addr); const auto& peer_rc = closest_rcs[relay_order]; - const auto& peer_key = peer_rc.pubkey; + const auto& peer_key = peer_rc.router_id(); if (peer_key == local_key) { @@ -908,7 +910,7 @@ namespace llarp for (const auto& rc : closest_rcs) { - if (rc.pubkey == local_key) + if (rc.router_id() == local_key) { rc_index = index; break; @@ -1024,7 +1026,7 @@ namespace llarp log::info(link_cat, "Relaying FindIntroMessage for {}", addr); const auto& peer_rc = closest_rcs[relay_order]; - const auto& peer_key = peer_rc.pubkey; + const auto& peer_key = peer_rc.router_id(); send_control_message( peer_key, diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 96e37de7f..66cde4bb7 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -372,8 +372,8 @@ namespace llarp endpoint->connect(remote, link_manager.tls_creds, std::forward(opts)...); // emplace immediately for connection open callback to find scid - connid_map.emplace(conn_interface->scid(), rc.pubkey); - auto [itr, b] = conns.emplace(rc.pubkey, nullptr); + connid_map.emplace(conn_interface->scid(), rc.router_id()); + auto [itr, b] = conns.emplace(rc.router_id(), nullptr); auto control_stream = conn_interface->template get_new_stream(); diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index e4885c620..17bd63ba3 100644 --- a/llarp/messages/path.hpp +++ b/llarp/messages/path.hpp @@ -22,7 +22,7 @@ namespace llarp hop.nonce.Randomize(); // do key exchange - if (!crypto::dh_client(hop.shared, hop.rc.pubkey, hop.commkey, hop.nonce)) + if (!crypto::dh_client(hop.shared, hop.rc._pubkey, hop.commkey, hop.nonce)) { auto err = fmt::format("Failed to generate shared key for path build!"); log::warning(path_cat, err); @@ -60,7 +60,7 @@ namespace llarp outer_nonce.Randomize(); // derive (outer) shared key - if (!crypto::dh_client(shared, hop.rc.pubkey, framekey, outer_nonce)) + if (!crypto::dh_client(shared, hop.rc._pubkey, framekey, outer_nonce)) { log::warning(path_cat, "DH client failed during hop info encryption!"); throw std::runtime_error{"DH failed during hop info encryption"}; diff --git a/llarp/messages/relay.cpp b/llarp/messages/relay.cpp index cabc2aa9d..7f816d61b 100644 --- a/llarp/messages/relay.cpp +++ b/llarp/messages/relay.cpp @@ -54,7 +54,7 @@ namespace llarp bool RelayUpstreamMessage::handle_message(Router* r) const { - auto path = r->path_context().GetByDownstream(conn->remote_rc.pubkey, pathid); + auto path = r->path_context().GetByDownstream(conn->remote_rc._pubkey, pathid); if (path) { return path->HandleUpstream(llarp_buffer_t(enc), nonce, r); @@ -110,7 +110,7 @@ namespace llarp bool RelayDownstreamMessage::handle_message(Router* r) const { - auto path = r->path_context().GetByUpstream(conn->remote_rc.pubkey, pathid); + auto path = r->path_context().GetByUpstream(conn->remote_rc._pubkey, pathid); if (path) { return path->HandleDownstream(llarp_buffer_t(enc), nonce, r); diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index cc6d2a28b..d3b7ee02c 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -14,8 +14,6 @@ static const std::string RC_FILE_EXT = ".signed"; namespace llarp { - static auto logcat = log::Cat("nodedb"); - NodeDB::Entry::Entry(RouterContact value) : rc(std::move(value)), insertedAt(llarp::time_now_ms()) {} @@ -79,7 +77,7 @@ namespace llarp // TODO: split this up? idk maybe some day... disk([this, data = std::move(copy)]() { for (const auto& rc : data) - rc.Write(get_path_by_pubkey(rc.pubkey)); + rc.write(get_path_by_pubkey(rc.router_id())); }); }); } @@ -123,20 +121,14 @@ namespace llarp RouterContact rc{}; - if (not rc.Read(f)) + if (not rc.read(f)) { // try loading it, purge it if it is junk purge.emplace(f); return true; } - if (not rc.FromOurNetwork()) - { - // skip entries that are not from our network - return true; - } - - if (rc.IsExpired(time_now_ms())) + if (rc.is_expired(time_now_ms())) { // rc expired dont load it and purge it later purge.emplace(f); @@ -145,8 +137,8 @@ namespace llarp // validate signature and purge entries with invalid signatures // load ones with valid signatures - if (rc.VerifySignature()) - entries.emplace(rc.pubkey, rc); + if (rc.verify_signature()) // TODO: fix this after RouterContact -> RemoteRC + entries.emplace(rc.router_id(), rc); else purge.emplace(f); @@ -172,7 +164,7 @@ namespace llarp router.loop()->call([this]() { for (const auto& item : entries) - item.second.rc.Write(get_path_by_pubkey(item.first)); + item.second.rc.write(get_path_by_pubkey(item.first)); }); } @@ -213,9 +205,9 @@ namespace llarp auto itr = entries.begin(); while (itr != entries.end()) { - if (itr->second.insertedAt < cutoff and keep.count(itr->second.rc.pubkey) == 0) + if (itr->second.insertedAt < cutoff and keep.count(itr->second.rc.router_id()) == 0) { - removed.insert(itr->second.rc.pubkey); + removed.insert(itr->second.rc.router_id()); itr = entries.erase(itr); } else @@ -230,8 +222,8 @@ namespace llarp NodeDB::put_rc(RouterContact rc) { router.loop()->call([this, rc]() { - entries.erase(rc.pubkey); - entries.emplace(rc.pubkey, rc); + entries.erase(rc.router_id()); + entries.emplace(rc.router_id(), rc); }); } @@ -245,14 +237,14 @@ namespace llarp NodeDB::put_rc_if_newer(RouterContact rc) { router.loop()->call([this, rc]() { - auto itr = entries.find(rc.pubkey); - if (itr == entries.end() or itr->second.rc.OtherIsNewer(rc)) + auto itr = entries.find(rc.router_id()); + if (itr == entries.end() or itr->second.rc.other_is_newer(rc)) { // delete if existing if (itr != entries.end()) entries.erase(itr); // add new entry - entries.emplace(rc.pubkey, rc); + entries.emplace(rc.router_id(), rc); } }); } @@ -282,14 +274,14 @@ namespace llarp llarp::RouterContact rc; const llarp::dht::XorMetric compare(location); VisitAll([&rc, compare](const auto& otherRC) { - if (rc.pubkey.IsZero()) + if (rc.router_id().IsZero()) { rc = otherRC; return; } if (compare( llarp::dht::Key_t{otherRC.pubkey.as_array()}, - llarp::dht::Key_t{rc.pubkey.as_array()})) + llarp::dht::Key_t{rc.router_id().as_array()})) rc = otherRC; }); return rc; diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index 7717b5ff5..17fe4ffbd 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -150,7 +150,7 @@ namespace llarp { if (visit(itr->second.rc)) { - removed.insert(itr->second.rc.pubkey); + removed.insert(itr->second.rc.router_id()); itr = entries.erase(itr); } else diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 75be48791..e5760c1a2 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -40,7 +40,7 @@ namespace llarp::path hops[idx].txID = hops[idx + 1].rxID; } // initialize parts of the introduction - intro.router = hops[hsz - 1].rc.pubkey; + intro.router = hops[hsz - 1].rc._router_id; intro.path_id = hops[hsz - 1].txID; if (auto parent = m_PathSet.lock()) EnterState(ePathBuilding, parent->Now()); @@ -152,13 +152,13 @@ namespace llarp::path RouterID Path::Endpoint() const { - return hops[hops.size() - 1].rc.pubkey; + return hops[hops.size() - 1].rc._router_id; } PubKey Path::EndpointPubKey() const { - return hops[hops.size() - 1].rc.pubkey; + return hops[hops.size() - 1].rc._router_id; } PathID_t @@ -184,13 +184,13 @@ namespace llarp::path bool Path::is_endpoint(const RouterID& r, const PathID_t& id) const { - return hops[hops.size() - 1].rc.pubkey == r && hops[hops.size() - 1].txID == id; + return hops[hops.size() - 1].rc._router_id == r && hops[hops.size() - 1].txID == id; } RouterID Path::upstream() const { - return hops[0].rc.pubkey; + return hops[0].rc._router_id; } const std::string& @@ -208,7 +208,7 @@ namespace llarp::path { if (!hops.empty()) hops_str += " -> "; - hops_str += RouterID(hop.rc.pubkey).ToString(); + hops_str += RouterID(hop.rc._router_id).ToString(); } return hops_str; } @@ -262,9 +262,9 @@ namespace llarp::path PathHopConfig::ExtractStatus() const { util::StatusObject obj{ - {"ip", rc.addr.to_string()}, + {"ip", rc._addr.to_string()}, {"lifetime", to_json(lifetime)}, - {"router", rc.pubkey.ToHex()}, + {"router", rc._router_id.ToHex()}, {"txid", txID.ToHex()}, {"rxid", rxID.ToHex()}}; return obj; diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index 7b78ead31..ec4d3fa3d 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -83,7 +83,7 @@ namespace llarp hop.nonce.Randomize(); // do key exchange - if (!crypto::dh_client(hop.shared, hop.rc.pubkey, hop.commkey, hop.nonce)) + if (!crypto::dh_client(hop.shared, hop.rc._pubkey, hop.commkey, hop.nonce)) { auto err = fmt::format("{} failed to generate shared key for path build!", Name()); log::error(path_cat, err); @@ -121,7 +121,7 @@ namespace llarp outer_nonce.Randomize(); // derive (outer) shared key - if (!crypto::dh_client(shared, hop.rc.pubkey, framekey, outer_nonce)) + if (!crypto::dh_client(shared, hop.rc._pubkey, framekey, outer_nonce)) { log::error(path_cat, "DH client failed during hop info encryption!"); throw std::runtime_error{"DH failed during hop info encryption"}; @@ -218,16 +218,16 @@ namespace llarp router->for_each_connection([&](link::Connection& conn) { const auto& rc = conn.remote_rc; #ifndef TESTNET - if (router->IsBootstrapNode(rc.pubkey)) + if (router->IsBootstrapNode(rc._pubkey)) return; #endif - if (exclude.count(rc.pubkey)) + if (exclude.count(rc._pubkey)) return; - if (BuildCooldownHit(rc.pubkey)) + if (BuildCooldownHit(rc._pubkey)) return; - if (router->router_profiling().IsBadForPath(rc.pubkey)) + if (router->router_profiling().IsBadForPath(rc._pubkey)) return; found = rc; @@ -243,7 +243,7 @@ namespace llarp }; if (const auto maybe = router->node_db()->GetRandom(filter)) { - return GetHopsAlignedToForBuild(maybe->pubkey); + return GetHopsAlignedToForBuild(maybe->_pubkey); } return std::nullopt; } @@ -353,7 +353,7 @@ namespace llarp return false; for (const auto& hop : hopsSet) { - if (hop.pubkey == rc.pubkey) + if (hop._pubkey == rc.pubkey) return false; } @@ -362,7 +362,7 @@ namespace llarp if (not pathConfig.Acceptable(hopsSet)) return false; #endif - return rc.pubkey != endpointRC.pubkey; + return rc.pubkey != endpointRC._pubkey; }; if (const auto maybe = router->node_db()->GetRandom(filter)) @@ -402,7 +402,7 @@ namespace llarp } lastBuild = llarp::time_now_ms(); - const RouterID edge{hops[0].pubkey}; + const RouterID edge{hops[0]._pubkey}; if (not router->pathbuild_limiter().Attempt(edge)) { @@ -429,7 +429,7 @@ namespace llarp { bool lastHop = (i == (n_hops - 1)); - const auto& nextHop = lastHop ? path_hops[i].rc.pubkey : path_hops[i + 1].rc.pubkey; + const auto& nextHop = lastHop ? path_hops[i].rc._pubkey : path_hops[i + 1].rc._pubkey; PathBuildMessage::setup_hop_keys(path_hops[i], nextHop); auto frame_str = PathBuildMessage::serialize(path_hops[i]); @@ -533,7 +533,7 @@ namespace llarp DoPathBuildBackoff(); for (const auto& hop : p->hops) { - const RouterID target{hop.rc.pubkey}; + const RouterID target{hop.rc._pubkey}; // look up router and see if it's still on the network log::info(path_cat, "Looking up RouterID {} due to path build timeout", target); diff --git a/llarp/profiling.cpp b/llarp/profiling.cpp index 3ae00f387..a8da6cec1 100644 --- a/llarp/profiling.cpp +++ b/llarp/profiling.cpp @@ -10,8 +10,6 @@ using oxenc::bt_dict_producer; namespace llarp { - static auto logcat = log::Cat("profiling"); - RouterProfile::RouterProfile(bt_dict_consumer dict) { BDecode(std::move(dict)); @@ -204,7 +202,7 @@ namespace llarp first = false; else { - auto& profile = m_Profiles[hop.rc.pubkey]; + auto& profile = m_Profiles[hop.rc.router_id()]; profile.pathFailCount += 1; profile.lastUpdated = llarp::time_now_ms(); } @@ -217,7 +215,7 @@ namespace llarp util::Lock lock{m_ProfilesMutex}; for (const auto& hop : p->hops) { - auto& profile = m_Profiles[hop.rc.pubkey]; + auto& profile = m_Profiles[hop.rc.router_id()]; profile.pathTimeoutCount += 1; profile.lastUpdated = llarp::time_now_ms(); } @@ -230,7 +228,7 @@ namespace llarp const auto sz = p->hops.size(); for (const auto& hop : p->hops) { - auto& profile = m_Profiles[hop.rc.pubkey]; + auto& profile = m_Profiles[hop.rc.router_id()]; // redeem previous fails by halfing the fail count and setting timeout to zero profile.pathFailCount /= 2; profile.pathTimeoutCount = 0; @@ -299,7 +297,7 @@ namespace llarp { try { - std::string data = util::slurp_file(fname); + std::string data = util::file_to_string(fname); util::Lock lock{m_ProfilesMutex}; BDecode(bt_dict_consumer{data}); } diff --git a/llarp/router/rc_gossiper.cpp b/llarp/router/rc_gossiper.cpp index 429a4b697..a380a54b1 100644 --- a/llarp/router/rc_gossiper.cpp +++ b/llarp/router/rc_gossiper.cpp @@ -30,7 +30,7 @@ namespace llarp bool RCGossiper::IsOurRC(const RouterContact& rc) const { - return rc.pubkey == rid; + return rc.router_id() == rid; } void @@ -67,11 +67,11 @@ namespace llarp RCGossiper::GossipRC(const RouterContact& rc) { // only distribute public routers - if (not rc.IsPublicRouter()) + if (not rc.is_public_router()) return false; if (link_manager == nullptr) return false; - const RouterID pubkey(rc.pubkey); + const RouterID pubkey(rc.router_id()); // filter check if (filter.Contains(pubkey)) return false; diff --git a/llarp/router/rc_lookup_handler.cpp b/llarp/router/rc_lookup_handler.cpp index 8cb96b10d..4c26d748b 100644 --- a/llarp/router/rc_lookup_handler.cpp +++ b/llarp/router/rc_lookup_handler.cpp @@ -101,6 +101,7 @@ namespace llarp throw; } + // TODO: replace this with construction of RemoteRC RouterContact result{std::move(payload)}; if (callback) @@ -204,22 +205,22 @@ namespace llarp bool RCLookupHandler::check_rc(const RouterContact& rc) const { - if (not is_session_allowed(rc.pubkey)) + if (not is_session_allowed(rc.router_id())) { - contacts->delete_rc_node_async(dht::Key_t{rc.pubkey}); + contacts->delete_rc_node_async(dht::Key_t{rc.router_id()}); return false; } - if (not rc.Verify(llarp::time_now_ms())) + if (not rc.verify(llarp::time_now_ms())) // TODO: fix this call after RouterContact -> RemoteRC { - LogWarn("RC for ", RouterID(rc.pubkey), " is invalid"); + LogWarn("RC for ", RouterID(rc.router_id()), " is invalid"); return false; } // update nodedb if required - if (rc.IsPublicRouter()) + if (rc.is_public_router()) { - LogDebug("Adding or updating RC for ", RouterID(rc.pubkey), " to nodedb and dht."); + LogDebug("Adding or updating RC for ", RouterID(rc.router_id()), " to nodedb and dht."); node_db->put_rc_if_newer(rc); contacts->put_rc_node_async(rc); } @@ -252,17 +253,17 @@ namespace llarp RCLookupHandler::check_renegotiate_valid(RouterContact newrc, RouterContact oldrc) { // mismatch of identity ? - if (newrc.pubkey != oldrc.pubkey) + if (newrc.router_id() != oldrc.router_id()) return false; - if (!is_session_allowed(newrc.pubkey)) + if (!is_session_allowed(newrc.router_id())) return false; auto func = [this, newrc] { check_rc(newrc); }; work_func(func); // update dht if required - if (contacts->rc_nodes()->HasNode(dht::Key_t{newrc.pubkey})) + if (contacts->rc_nodes()->HasNode(dht::Key_t{newrc.router_id()})) { contacts->rc_nodes()->PutNode(newrc); } @@ -278,15 +279,15 @@ namespace llarp std::unordered_set routersToLookUp; node_db->VisitInsertedBefore( - [&](const RouterContact& rc) { routersToLookUp.insert(rc.pubkey); }, - now - RouterContact::UpdateInterval); + [&](const RouterContact& rc) { routersToLookUp.insert(rc.router_id()); }, + now - RouterContact::REPUBLISH); for (const auto& router : routersToLookUp) { get_rc(router, nullptr, true); } - node_db->remove_stale_rcs(boostrap_rid_list, now - RouterContact::StaleInsertionAge); + node_db->remove_stale_rcs(boostrap_rid_list, now - RouterContact::STALE); } void @@ -301,7 +302,7 @@ namespace llarp { for (const auto& rc : bootstrap_rc_list) { - log::info(link_cat, "Doing explore via bootstrap node: {}", RouterID(rc.pubkey)); + log::info(link_cat, "Doing explore via bootstrap node: {}", RouterID(rc.router_id())); // TODO: replace this concept // dht->ExploreNetworkVia(dht::Key_t{rc.pubkey}); @@ -383,7 +384,7 @@ namespace llarp for (const auto& rc : bootstrap_rc_list) { - boostrap_rid_list.insert(rc.pubkey); + boostrap_rid_list.insert(rc.router_id()); } } @@ -392,7 +393,7 @@ namespace llarp { for (const auto& rc : bootstrap_rc_list) { - if (rc.pubkey == remote) + if (rc.router_id() == remote) { return true; } diff --git a/llarp/router/route_poker.cpp b/llarp/router/route_poker.cpp index 76c948d1c..b64ff9e9e 100644 --- a/llarp/router/route_poker.cpp +++ b/llarp/router/route_poker.cpp @@ -6,8 +6,6 @@ namespace llarp { - static auto logcat = log::Cat("route-poker"); - void RoutePoker::add_route(oxen::quic::Address ip) { @@ -221,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.remote_rc.addr()); }); add_route(router.link_manager().local()); // add default route @@ -240,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.remote_rc.addr()); }); if (is_enabled() and is_up) { vpn::AbstractRouteManager& route = router.vpn_platform()->RouteManager(); diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 1aa99d9a1..885e3fcf5 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -36,8 +36,6 @@ static constexpr std::chrono::milliseconds ROUTER_TICK_INTERVAL = 250ms; namespace llarp { - static auto logcat = log::Cat("router"); - Router::Router(EventLoop_ptr loop, std::shared_ptr vpnPlatform) : _route_poker{std::make_shared(*this)} , _lmq{std::make_shared()} @@ -178,7 +176,7 @@ namespace llarp util::StatusObject stats{ {"running", true}, - {"version", llarp::VERSION_FULL}, + {"version", llarp::LOKINET_VERSION_FULL}, {"uptime", to_json(Uptime())}, {"numPathsBuilt", pathsCount}, {"numPeersConnected", peers}, @@ -216,8 +214,9 @@ namespace llarp std::unordered_set peer_pubkeys; - for_each_connection( - [&peer_pubkeys](link::Connection& conn) { peer_pubkeys.emplace(conn.remote_rc.pubkey); }); + for_each_connection([&peer_pubkeys](link::Connection& conn) { + peer_pubkeys.emplace(conn.remote_rc.router_id()); + }); loop()->call([this, &peer_pubkeys]() { for (auto& pk : peer_pubkeys) @@ -253,7 +252,7 @@ namespace llarp if (auto maybe = node_db()->GetRandom([](const auto&) -> bool { return true; })) { - router = maybe->pubkey; + router = maybe->router_id(); return true; } return false; @@ -444,16 +443,16 @@ namespace llarp Router::HandleSaveRC() const { std::string fname = our_rc_file.string(); - router_contact.Write(fname.c_str()); + router_contact.write(fname.c_str()); } bool Router::SaveRC() { LogDebug("verify RC signature"); - if (!router_contact.Verify(now())) + if (!router_contact.verify(now())) // TODO: RouterContact -> RemoteRC { - Dump(rc()); + Dump(rc()); LogError("RC is invalid, not saving"); return false; } @@ -569,9 +568,7 @@ namespace llarp { SecretKey nextOnionKey; RouterContact nextRC = router_contact; - if (!nextRC.Sign(identity())) - return false; - if (!nextRC.Verify(time_now_ms(), false)) + if (!nextRC.sign(identity())) // TODO: RouterContact -> LocalRC return false; router_contact = std::move(nextRC); if (IsServiceNode()) @@ -585,20 +582,17 @@ namespace llarp // Set netid before anything else log::debug(logcat, "Network ID set to {}", conf.router.m_netId); if (!conf.router.m_netId.empty() - && strcmp(conf.router.m_netId.c_str(), llarp::DEFAULT_NETID) != 0) + && strcmp(conf.router.m_netId.c_str(), llarp::LOKINET_DEFAULT_NETID) != 0) { const auto& netid = conf.router.m_netId; llarp::LogWarn( "!!!! you have manually set netid to be '", netid, "' which does not equal '", - llarp::DEFAULT_NETID, + llarp::LOKINET_DEFAULT_NETID, "' you will run as a different network, good luck " "and don't forget: something something MUH traffic " "shape correlation !!!!"); - NetID::DefaultValue() = NetID(reinterpret_cast(netid.c_str())); - // reset netid in our rc - router_contact.netID = llarp::NetID(); } // Router config @@ -628,7 +622,7 @@ namespace llarp else log::debug(logcat, "No explicit public address given; will auto-detect during link setup"); - RouterContact::BlockBogons = conf.router.m_blockBogons; + RouterContact::BLOCK_BOGONS = conf.router.m_blockBogons; auto& networkConfig = conf.network; @@ -679,10 +673,10 @@ namespace llarp auto clearBadRCs = [this]() { for (auto it = bootstrap_rc_list.begin(); it != bootstrap_rc_list.end();) { - if (it->IsObsoleteBootstrap()) - log::warning(logcat, "ignoring obsolete boostrap RC: {}", RouterID{it->pubkey}); - else if (not it->Verify(now())) - log::warning(logcat, "ignoring invalid bootstrap RC: {}", RouterID{it->pubkey}); + if (it->is_obsolete_bootstrap()) + log::warning(logcat, "ignoring obsolete boostrap RC: {}", RouterID{it->router_id()}); + else if (not it->verify(now())) // TODO: RouterContact -> RemoteRC + log::warning(logcat, "ignoring invalid bootstrap RC: {}", RouterID{it->router_id()}); else { ++it; @@ -785,7 +779,7 @@ namespace llarp return std::count_if( bootstrap_rc_list.begin(), bootstrap_rc_list.end(), - [r](const RouterContact& rc) -> bool { return rc.pubkey == r; }) + [r](const RouterContact& rc) -> bool { return rc.router_id() == r; }) > 0; } @@ -806,8 +800,8 @@ namespace llarp if (IsServiceNode()) { LogInfo(NumberOfConnectedClients(), " client connections"); - LogInfo(ToString(router_contact.Age(now)), " since we last updated our RC"); - LogInfo(ToString(router_contact.TimeUntilExpires(now)), " until our RC expires"); + LogInfo(ToString(router_contact.age(now)), " since we last updated our RC"); + LogInfo(ToString(router_contact.time_to_expiry(now)), " until our RC expires"); } if (_last_stats_report > 0s) LogInfo(ToString(now - _last_stats_report), " last reported stats"); @@ -819,7 +813,7 @@ namespace llarp { std::string status; auto out = std::back_inserter(status); - fmt::format_to(out, "v{}", fmt::join(llarp::VERSION, ".")); + fmt::format_to(out, "v{}", fmt::join(llarp::LOKINET_VERSION, ".")); if (IsServiceNode()) { fmt::format_to( @@ -901,7 +895,8 @@ namespace llarp bool should_gossip = appears_funded(); if (is_snode - and (router_contact.ExpiresSoon(now, std::chrono::milliseconds(randint() % 10000)) or (now - router_contact.last_updated) > rc_regen_interval)) + and (router_contact.expires_within_delta(now, std::chrono::milliseconds(randint() % 10000)) + or (now - router_contact.timestamp().time_since_epoch()) > rc_regen_interval)) { LogInfo("regenerating RC"); if (update_rc()) @@ -923,22 +918,22 @@ namespace llarp // remove RCs for nodes that are no longer allowed by network policy node_db()->RemoveIf([&](const RouterContact& rc) -> bool { // don't purge bootstrap nodes from nodedb - if (IsBootstrapNode(rc.pubkey)) + if (IsBootstrapNode(rc.router_id())) { - log::trace(logcat, "Not removing {}: is bootstrap node", rc.pubkey); + 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.IsPublicRouter()) + if (not rc.is_public_router()) { - log::debug(logcat, "Removing {}: not a valid router", rc.pubkey); + log::debug(logcat, "Removing {}: not a valid router", rc.router_id()); return true; } /// clear out a fully expired RC - if (rc.IsExpired(now)) + if (rc.is_expired(now)) { - log::debug(logcat, "Removing {}: RC is expired", rc.pubkey); + log::debug(logcat, "Removing {}: RC is expired", rc.router_id()); return true; } // clients have no notion of a whilelist @@ -946,23 +941,23 @@ namespace llarp // routers that are not whitelisted for first hops if (not is_snode) { - log::trace(logcat, "Not removing {}: we are a client and it looks fine", rc.pubkey); + log::trace(logcat, "Not removing {}: we are a client and it looks fine", rc.router_id()); return false; } // if we don't have the whitelist yet don't remove the entry if (not has_whitelist) { - log::debug(logcat, "Skipping check on {}: don't have whitelist yet", rc.pubkey); + log::debug(logcat, "Skipping check on {}: don't have whitelist yet", rc.router_id()); return false; } // if we have no whitelist enabled or we have // the whitelist enabled and we got the whitelist // check against the whitelist and remove if it's not // in the whitelist OR if there is no whitelist don't remove - if (has_whitelist and not _rc_lookup_handler.is_session_allowed(rc.pubkey)) + if (has_whitelist and not _rc_lookup_handler.is_session_allowed(rc.router_id())) { - log::debug(logcat, "Removing {}: not a valid router", rc.pubkey); + log::debug(logcat, "Removing {}: not a valid router", rc.router_id()); return true; } return false; @@ -971,10 +966,10 @@ namespace llarp if (not is_snode or not has_whitelist) { // find all deregistered relays - std::unordered_set close_peers; + std::unordered_set close_peers; for_each_connection([this, &close_peers](link::Connection& conn) { - const auto& pk = conn.remote_rc.pubkey; + const auto& pk = conn.remote_rc.router_id(); if (conn.remote_is_relay and not _rc_lookup_handler.is_session_allowed(pk)) close_peers.insert(pk); @@ -1051,7 +1046,7 @@ namespace llarp std::set peer_keys; for_each_connection( - [&peer_keys](link::Connection& conn) { peer_keys.emplace(conn.remote_rc.pubkey); }); + [&peer_keys](link::Connection& conn) { peer_keys.emplace(conn.remote_rc.router_id()); }); _contacts->rc_nodes()->RemoveIf( [&peer_keys](const dht::Key_t& k) -> bool { return peer_keys.count(k) == 0; }); @@ -1112,15 +1107,18 @@ namespace llarp if (is_running || is_stopping) return false; - // set public signing key - router_contact.pubkey = seckey_topublic(identity()); + // TODO: replace all this logic with construction of LocalRC + + /* // set public signing key + router_contact._router_id = seckey_topublic(identity()); // set router version if service node if (IsServiceNode()) { - router_contact.routerVersion = RouterVersion(llarp::VERSION, llarp::constants::proto_version); + router_contact.routerVersion = + RouterVersion(llarp::LOKINET_VERSION, llarp::constants::proto_version); } - if (IsServiceNode() and not router_contact.IsPublicRouter()) + if (IsServiceNode() and not router_contact.is_public_router()) { LogError("we are configured as relay but have no reachable addresses"); return false; @@ -1130,7 +1128,7 @@ namespace llarp router_contact.enckey = seckey_topublic(encryption()); LogInfo("Signing rc..."); - if (!router_contact.Sign(identity())) + if (!router_contact.sign(identity())) { LogError("failed to sign rc"); return false; @@ -1166,14 +1164,14 @@ namespace llarp // regenerate keys and resign rc before everything else crypto::identity_keygen(_identity); crypto::encryption_keygen(_encryption); - router_contact.pubkey = seckey_topublic(identity()); + router_contact._router_id = seckey_topublic(identity()); router_contact.enckey = seckey_topublic(encryption()); - if (!router_contact.Sign(identity())) + if (!router_contact.sign(identity())) { LogError("failed to regenerate keys and sign RC"); return false; } - } + } */ LogInfo("starting hidden service context..."); if (!hidden_service_context().StartAll()) @@ -1193,7 +1191,7 @@ namespace llarp { node_db()->put_rc(rc); _contacts->rc_nodes()->PutNode(rc); - LogInfo("added bootstrap node ", RouterID{rc.pubkey}); + LogInfo("added bootstrap node ", RouterID{rc.router_id()}); } LogInfo("have ", _node_db->num_loaded(), " routers"); diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 6354b37c6..c20a3e57e 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -465,7 +465,7 @@ namespace llarp const byte_t* pubkey() const { - return seckey_topublic(_identity); + return seckey_to_pubkey(_identity); } /// send to remote router or queue for sending diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index d57866222..01a9d5f64 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -12,407 +12,276 @@ namespace llarp { - static auto logcat = log::Cat("RC"); - NetID& - NetID::DefaultValue() - { - static NetID defaultID(reinterpret_cast(llarp::DEFAULT_NETID)); - return defaultID; - } - - bool RouterContact::BlockBogons = true; + // RouterContact::RouterContact(std::string buf) + // { + // try + // { + // oxenc::bt_list_consumer btlc{buf}; - /// 1 day rc lifespan - constexpr auto rc_lifetime = 24h; - /// an RC inserted long enough ago (4 hrs) is considered stale and is removed - constexpr auto rc_stale_age = 4h; - /// window of time in which a router wil try to update their RC before it is marked stale - constexpr auto rc_update_window = 5min; - /// update RCs shortly before they are about to expire - constexpr auto rc_update_interval = rc_stale_age - rc_update_window; + // // signature.from_string(btlc.consume_string()); + // signed_bt_dict = btlc.consume_string(); - llarp_time_t RouterContact::Lifetime = rc_lifetime; - llarp_time_t RouterContact::StaleInsertionAge = rc_stale_age; - llarp_time_t RouterContact::UpdateInterval = rc_update_interval; + // // TODO: parse bt dict + // } + // catch (...) + // { + // log::warning(llarp_cat, "Error: RouterContact failed to populate bt encoded contents!"); + // } + // } - /// how many rc lifetime intervals should we wait until purging an rc - constexpr auto expiration_lifetime_generations = 10; - /// the max age of an rc before we want to expire it - constexpr auto rc_expire_age = rc_lifetime * expiration_lifetime_generations; - - NetID::NetID(const byte_t* val) + std::string + RouterContact::bt_encode() const { - const size_t len = strnlen(reinterpret_cast(val), size()); - std::copy(val, val + len, begin()); + oxenc::bt_dict_producer btdp; + bt_encode(btdp); + return std::move(btdp).str(); } - NetID::NetID() : NetID(DefaultValue().data()) - {} - - bool - NetID::operator==(const NetID& other) const + void + RouterContact::bt_load(oxenc::bt_dict_consumer& data) { - return ToString() == other.ToString(); - } + if (int rc_ver = data.require(""); rc_ver != RC_VERSION) + throw std::runtime_error{"Invalid RC: do not know how to parse v{} RCs"_format(rc_ver)}; - std::string - NetID::ToString() const - { - return {begin(), std::find(begin(), end(), '\0')}; - } + auto ipv4_port = data.require("4"); - bool - NetID::BDecode(llarp_buffer_t* buf) - { - Zero(); - llarp_buffer_t strbuf; - if (!bencode_read_string(buf, &strbuf)) - return false; + if (ipv4_port.size() != 6) + throw std::runtime_error{ + "Invalid RC address: expected 6-byte IPv4 IP/port, got {}"_format(ipv4_port.size())}; - if (strbuf.sz > size()) - return false; + sockaddr_in s4; + s4.sin_family = AF_INET; - std::copy(strbuf.base, strbuf.base + strbuf.sz, begin()); - return true; - } + std::memcpy(&s4.sin_addr.s_addr, ipv4_port.data(), 4); + std::memcpy(&s4.sin_port, ipv4_port.data() + 4, 2); - bool - NetID::BEncode(llarp_buffer_t* buf) const - { - auto term = std::find(begin(), end(), '\0'); - return bencode_write_bytestring(buf, data(), std::distance(begin(), term)); - } + _addr = oxen::quic::Address{&s4}; - RouterContact::RouterContact(std::string buf) - { - try + if (!_addr.is_public()) + throw std::runtime_error{"Invalid RC: IPv4 address is not a publicly routable IP"}; + + if (auto ipv6_port = data.maybe("6")) { - oxenc::bt_list_consumer btlc{buf}; + if (ipv6_port->size() != 18) + throw std::runtime_error{ + "Invalid RC address: expected 18-byte IPv6 IP/port, got {}"_format(ipv6_port->size())}; + + sockaddr_in6 s6{}; + s6.sin6_family = AF_INET6; - signature.from_string(btlc.consume_string()); - signed_bt_dict = btlc.consume_string(); + std::memcpy(&s6.sin6_addr.s6_addr, ipv6_port->data(), 16); + std::memcpy(&s6.sin6_port, ipv6_port->data() + 16, 2); - // TODO: parse bt dict + _addr6.emplace(&s6); + if (!_addr6->is_public()) + throw std::runtime_error{"Invalid RC: IPv6 address is not a publicly routable IP"}; } - catch (...) + else { - log::warning(llarp_cat, "Error: RouterContact failed to populate bt encoded contents!"); + _addr6.reset(); } - } - std::string - RouterContact::bt_encode() const - { - oxenc::bt_list_producer btlp; + auto netid = data.maybe("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)}; - try - { - btlp.append(signature.ToView()); - btlp.append(signed_bt_dict); - } - catch (...) - { - log::warning(llarp_cat, "Error: RouterContact failed to bt encode contents!"); - } + auto pk = data.require("p"); - return std::move(btlp).str(); - } + if (pk.size() != RouterID::SIZE) + throw std::runtime_error{"Invalid RC: router id has invalid size {}"_format(pk.size())}; - void - RouterContact::bt_encode_subdict(oxenc::bt_list_producer& btlp) const - { - btlp.append(signature.ToView()); - btlp.append(signed_bt_dict); - } + std::memcpy(_router_id.data(), pk.data(), RouterID::SIZE); - std::string - RouterContact::ToTXTRecord() const - { - std::string result; - auto out = std::back_inserter(result); - fmt::format_to(out, "addr={}; pk={}", addr.to_string(), pubkey); - fmt::format_to(out, "updated={}; onion_pk={}; ", last_updated.count(), enckey.ToHex()); - if (routerVersion.has_value()) - fmt::format_to(out, "router_version={}; ", *routerVersion); - return result; - } + _timestamp = rc_time{std::chrono::seconds{data.require("t")}}; - bool - RouterContact::FromOurNetwork() const - { - return netID == NetID::DefaultValue(); - } + auto ver = data.require("v"); - std::string - RouterContact::bencode_signed_section() const - { - oxenc::bt_dict_producer btdp; + if (ver.size() != 3) + throw std::runtime_error{ + "Invalid RC router version: received {} bytes (!= 3)"_format(ver.size())}; - btdp.append("a", addr.to_string()); - btdp.append("i", netID.ToView()); - btdp.append("k", pubkey.bt_encode()); - btdp.append("p", enckey.ToView()); - btdp.append("r", routerVersion->ToString()); + for (int i = 0; i < 3; i++) + _router_version[i] = ver[i]; + } - if (not srvRecords.empty()) - { - auto sublist = btdp.append_list("s"); + // std::string + // RouterContact::bencode_signed_section() const + // { + // oxenc::bt_dict_producer btdp; - for (auto& s : srvRecords) - sublist.append(s.bt_encode()); - } + // btdp.append("4", _addr.to_string()); - btdp.append("u", last_updated.count()); + // if (_addr6) + // btdp.append("6", _addr6->to_string()); - return std::move(btdp).str(); - } + // if (ACTIVE_NETID != llarp::LOKINET_DEFAULT_NETID) + // btdp.append("i", ACTIVE_NETID); - void - RouterContact::Clear() - { - signature.Zero(); - enckey.Zero(); - pubkey.Zero(); - routerVersion = std::optional{}; - last_updated = 0s; - srvRecords.clear(); - version = llarp::constants::proto_version; - } + // btdp.append("p", _router_id.bt_encode()); + // btdp.append("t", _timestamp.time_since_epoch().count()); + // btdp.append("v", _router_version.data()); + + // return std::move(btdp).str(); + // } util::StatusObject - RouterContact::ExtractStatus() const + RouterContact::extract_status() const { util::StatusObject obj{ - {"lastUpdated", last_updated.count()}, - {"publicRouter", IsPublicRouter()}, - {"identity", pubkey.ToString()}, - {"address", addr.to_string()}}; + {"lastUpdated", _timestamp.time_since_epoch().count()}, + {"publicRouter", is_public_router()}, + {"identity", _router_id.ToString()}, + {"address", _addr.to_string()}}; + + // if (routerVersion) + // { + // obj["routerVersion"] = routerVersion->ToString(); + // } + // std::vector srv; + // for (const auto& record : srvRecords) + // { + // srv.emplace_back(record.ExtractStatus()); + // } + // obj["srvRecords"] = srv; - if (routerVersion) - { - obj["routerVersion"] = routerVersion->ToString(); - } - std::vector srv; - for (const auto& record : srvRecords) - { - srv.emplace_back(record.ExtractStatus()); - } - obj["srvRecords"] = srv; return obj; } bool RouterContact::BDecode(llarp_buffer_t* buf) { - Clear(); - - if (*buf->cur == 'd') // old format - { - return DecodeVersion_0(buf); - } - else if (*buf->cur != 'l') // if not dict, should be new format and start with list - { - return false; - } - - try - { - std::string_view buf_view(reinterpret_cast(buf->cur), buf->size_left()); - oxenc::bt_list_consumer btlist(buf_view); - - uint64_t outer_version = btlist.consume_integer(); - - if (outer_version == 1) - { - bool decode_result = DecodeVersion_1(btlist); - - // advance the llarp_buffer_t since lokimq serialization is unaware of it. - // FIXME: this is broken (current_buffer got dropped), but the whole thing is getting - // replaced. - // buf->cur += btlist. - // current_buffer().data() - buf_view.data() + 1; - - return decode_result; - } - else - { - log::warning(logcat, "Received RouterContact with unkown version ({})", outer_version); - return false; - } - } - catch (const std::exception& e) - { - log::debug(logcat, "RouterContact::BDecode failed: {}", e.what()); - } - - return false; - } - - bool - RouterContact::DecodeVersion_0(llarp_buffer_t* buf) - { - return bencode_decode_dict(*this, buf); - } + // TODO: unfuck all of this - bool - RouterContact::DecodeVersion_1(oxenc::bt_list_consumer& btlist) - { - auto signature_string = btlist.consume_string_view(); - signed_bt_dict = btlist.consume_dict_data(); + (void)buf; - if (not btlist.is_finished()) - { - log::debug(logcat, "RouterContact serialized list too long for specified version."); - return false; - } + // clear(); - llarp_buffer_t sigbuf(signature_string.data(), signature_string.size()); - if (not signature.FromBytestring(&sigbuf)) - { - log::debug(logcat, "RouterContact serialized signature had invalid length."); - return false; - } + // if (*buf->cur == 'd') // old format + // { + // return DecodeVersion_0(buf); + // } + // else if (*buf->cur != 'l') // if not dict, should be new format and start with list + // { + // return false; + // } + + // try + // { + // std::string_view buf_view(reinterpret_cast(buf->cur), buf->size_left()); + // oxenc::bt_list_consumer btlist(buf_view); + + // uint64_t outer_version = btlist.consume_integer(); + + // if (outer_version == 1) + // { + // bool decode_result = DecodeVersion_1(btlist); + + // // advance the llarp_buffer_t since lokimq serialization is unaware of it. + // // FIXME: this is broken (current_buffer got dropped), but the whole thing is getting + // // replaced. + // // buf->cur += btlist. + // // current_buffer().data() - buf_view.data() + 1; + + // return decode_result; + // } + // else + // { + // log::warning(logcat, "Received RouterContact with unkown version ({})", outer_version); + // return false; + // } + // } + // catch (const std::exception& e) + // { + // log::debug(logcat, "RouterContact::BDecode failed: {}", e.what()); + // } - llarp_buffer_t data_dict_buf(signed_bt_dict.data(), signed_bt_dict.size()); - return bencode_decode_dict(*this, &data_dict_buf); + return false; } bool RouterContact::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) { bool read = false; + (void)key; // TOFIX: fuck everything about llarp_buffer_t + // if (!BEncodeMaybeReadDictEntry("a", addr, read, key, buf)) // return false; - if (!BEncodeMaybeReadDictEntry("i", netID, read, key, buf)) - return false; + // if (!BEncodeMaybeReadDictEntry("i", netID, read, key, buf)) + // return false; - if (!BEncodeMaybeReadDictEntry("k", pubkey, read, key, buf)) - return false; + // if (!BEncodeMaybeReadDictEntry("k", _router_id, read, key, buf)) + // return false; - if (key.startswith("r")) - { - RouterVersion r; - if (not r.BDecode(buf)) - return false; - routerVersion = r; - return true; - } + // if (key.startswith("r")) + // { + // RouterVersion r; + // if (not r.BDecode(buf)) + // return false; + // routerVersion = r; + // return true; + // } - if (not BEncodeMaybeReadDictList("s", srvRecords, read, key, buf)) - return false; + // if (not BEncodeMaybeReadDictList("s", srvRecords, read, key, buf)) + // return false; - if (!BEncodeMaybeReadDictEntry("p", enckey, read, key, buf)) - return false; + // if (!BEncodeMaybeReadDictEntry("p", enckey, read, key, buf)) + // return false; - if (!BEncodeMaybeReadDictInt("u", last_updated, read, key, buf)) - return false; + // if (!BEncodeMaybeReadDictInt("u", _timestamp, read, key, buf)) + // return false; - if (!BEncodeMaybeReadDictInt("v", version, read, key, buf)) - return false; + // if (!BEncodeMaybeReadDictInt("v", version, read, key, buf)) + // return false; - if (key.startswith("x") and serializeExit) - { - return bencode_discard(buf); - } + // if (key.startswith("x") and serializeExit) + // { + // return bencode_discard(buf); + // } - if (!BEncodeMaybeReadDictEntry("z", signature, read, key, buf)) - return false; + // if (!BEncodeMaybeReadDictEntry("z", signature, read, key, buf)) + // return false; return read or bencode_discard(buf); } bool - RouterContact::IsPublicRouter() const + RouterContact::is_public_router() const { - if (not routerVersion) + if (_router_version.empty()) return false; - return addr.is_addressable(); + return _addr.is_addressable(); } bool - RouterContact::IsExpired(llarp_time_t now) const + RouterContact::is_expired(llarp_time_t now) const { - return Age(now) >= rc_expire_age; + return age(now) >= _timestamp.time_since_epoch() + LIFETIME; } llarp_time_t - RouterContact::TimeUntilExpires(llarp_time_t now) const + RouterContact::time_to_expiry(llarp_time_t now) const { - const auto expiresAt = last_updated + Lifetime; - return now < expiresAt ? expiresAt - now : 0s; + const auto expiry = _timestamp.time_since_epoch() + LIFETIME; + return now < expiry ? expiry - now : 0s; } llarp_time_t - RouterContact::Age(llarp_time_t now) const - { - return now > last_updated ? now - last_updated : 0s; - } - - bool - RouterContact::ExpiresSoon(llarp_time_t now, llarp_time_t dlt) const - { - return TimeUntilExpires(now) <= dlt; - } - - bool - RouterContact::Sign(const SecretKey& secretkey) + RouterContact::age(llarp_time_t now) const { - pubkey = llarp::seckey_topublic(secretkey); - signature.Zero(); - last_updated = time_now_ms(); - - signed_bt_dict = bencode_signed_section(); - - return crypto::sign( - signature, - secretkey, - reinterpret_cast(signed_bt_dict.data()), - signed_bt_dict.size()); - } - - bool - RouterContact::Verify(llarp_time_t now, bool allowExpired) const - { - if (netID != NetID::DefaultValue()) - { - log::error( - logcat, "netid mismatch: '{}' (theirs) != '{}' (ours)", netID, NetID::DefaultValue()); - return false; - } - - if (IsExpired(now) and not allowExpired) - return false; - - // TODO: make net* overridable - const auto* net = net::Platform::Default_ptr(); - - if (net->IsBogon(addr.in4()) && BlockBogons) - { - log::error(logcat, "invalid address info: {}", addr); - return false; - } - - if (!VerifySignature()) - { - log::error(logcat, "invalid signature: {}", *this); - return false; - } - return true; + auto delta = now - _timestamp.time_since_epoch(); + return delta > 0s ? delta : 0s; } bool - RouterContact::VerifySignature() const + RouterContact::expires_within_delta(llarp_time_t now, llarp_time_t dlt) const { - RouterContact copy; - copy = *this; - copy.signature.Zero(); - - auto bte = copy.bt_encode(); - return crypto::verify(pubkey, reinterpret_cast(bte.data()), bte.size(), signature); + return time_to_expiry(now) <= dlt; } static constexpr std::array obsolete_bootstraps = { @@ -421,18 +290,18 @@ namespace llarp }; bool - RouterContact::IsObsoleteBootstrap() const + RouterContact::is_obsolete_bootstrap() const { for (const auto& k : obsolete_bootstraps) { - if (pubkey.ToHex() == k) + if (_router_id.ToHex() == k) return true; } return false; } bool - RouterContact::Write(const fs::path& fname) const + RouterContact::write(const fs::path& fname) const { std::array tmp; llarp_buffer_t buf(tmp); @@ -453,13 +322,13 @@ namespace llarp } bool - RouterContact::Read(const fs::path& fname) + RouterContact::read(const fs::path& fname) { std::array tmp; llarp_buffer_t buf(tmp); try { - util::slurp_file(fname, tmp.data(), tmp.size()); + util::file_to_buffer(fname, tmp.data(), tmp.size()); } catch (const std::exception& e) { @@ -468,19 +337,4 @@ namespace llarp } return BDecode(&buf); } - - std::string - RouterContact::ToString() const - { - return fmt::format( - "[RC k={} updated={} netid={} v={} ai={{{}}} e={} z={}]", - pubkey, - last_updated.count(), - netID, - version, - fmt::format("{}", addr), - enckey, - signature); - } - } // namespace llarp diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index 7e8e1fdce..d2a0f54a6 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -1,5 +1,6 @@ #pragma once +#include "router_id.hpp" #include "router_version.hpp" #include @@ -17,128 +18,169 @@ #include #include -#define MAX_RC_SIZE (1024) - namespace oxenc { class bt_list_consumer; } // namespace oxenc +/* + - figure out where we do bt_encoding of RC's + - maybe dump secret key from bt_encode + - it's weird to pass the secret key contextually + - suspicion we will need optional signature as an optional(?) string with serialized data + - resetting signature would be string::clear() instead + - ::sign() will cache serialized value + - do timestamp stuff + - bt_encode that takes bt_dict_producer requires reference to subdict + - presumably to be done in endpoints + - will be used for get_multi_rc endpoint +*/ + namespace llarp { - /// NetID - struct NetID final : public AlignedBuffer<8> + static auto logcat = log::Cat("RC"); + + using rc_time = std::chrono::time_point; + + /// RouterContact + struct RouterContact { - static NetID& - DefaultValue(); + static constexpr uint8_t RC_VERSION = 0; - NetID(); + /// Constructs an empty RC + RouterContact() = default; + RouterContact(std::string) + { + log::error(logcat, "ERROR: SUPPLANT THIS CONSTRUCTOR"); + } - explicit NetID(const byte_t* val); + // RouterContact(std::string buf); - NetID(const NetID& other) = default; - NetID& - operator=(const NetID& other) = default; + /// RC version that we support; we fail to load RCs that don't have the same version as that + /// means they are incompatible with us. + // static constexpr uint8_t VERSION = 0; - bool - operator==(const NetID& other) const; + /// Unit tests disable this to allow private IP ranges in RCs, which normally get rejected. + static inline bool BLOCK_BOGONS = true; - bool - operator!=(const NetID& other) const - { - return !(*this == other); - } + static inline std::string ACTIVE_NETID{LOKINET_DEFAULT_NETID}; - std::string - ToString() const; + static inline constexpr size_t MAX_RC_SIZE = 1024; - bool - BDecode(llarp_buffer_t* buf); + /// Timespans for RCs: - bool - BEncode(llarp_buffer_t* buf) const; - }; + /// How long (relative to its timestamp) before an RC becomes stale. Stale records are used + /// (e.g. for path building) only if there are no non-stale records available, such as might be + /// the case when a client has been turned off for a while. + static constexpr auto STALE = 12h; - /// RouterContact - struct RouterContact - { - /// for unit tests - static bool BlockBogons; + /// How long before an RC becomes invalid (and thus deleted). + static constexpr auto LIFETIME = 30 * 24h; + + /// How long before a relay updates and re-publish its RC to the network. (Relays can + /// re-publish more frequently than this if needed; this is meant to apply only if there are no + /// changes i.e. just to push out a new confirmation of the details). + static constexpr auto REPUBLISH = STALE / 2 - 5min; - static llarp_time_t Lifetime; - static llarp_time_t UpdateInterval; - static llarp_time_t StaleInsertionAge; + /// Getters for private attributes + const oxen::quic::Address& + addr() const + { + return _addr; + } - RouterContact() + const std::optional& + addr6() const { - Clear(); + return _addr6; } - RouterContact(std::string buf); + const RouterID& + router_id() const + { + return _router_id; + } + + const rc_time& + timestamp() const + { + return _timestamp; + } + protected: // advertised addresses - oxen::quic::Address addr; - // network identifier - NetID netID; - // public encryption public key - llarp::PubKey enckey; + oxen::quic::Address _addr; // refactor all 15 uses to use addr() method + std::optional _addr6; // optional ipv6 // public signing public key - llarp::PubKey pubkey; - // signature - llarp::Signature signature; + RouterID _router_id; // refactor all 103 uses to use router_id() method + + rc_time _timestamp{}; - llarp_time_t last_updated = 0s; - uint64_t version = llarp::constants::proto_version; - std::optional routerVersion; + // Lokinet version at the time the RC was produced + std::array _router_version; + + public: /// should we serialize the exit info? const static bool serializeExit = true; - std::string signed_bt_dict; - - std::vector srvRecords; + ustring _signed_payload; util::StatusObject - ExtractStatus() const; + extract_status() const; - RouterID - router_id() const + nlohmann::json + to_json() const { - return pubkey; + return extract_status(); } - nlohmann::json - ToJson() const + virtual std::string + to_string() const { - return ExtractStatus(); + return fmt::format( + "[RC k={} updated={} v={} addr={}]", + _router_id, + _timestamp, + RC_VERSION, + _addr.to_string()); } - std::string - ToString() const; - + /// On the wire we encode the data as a dict containing: + /// "" -- the RC format version, which must be == RouterContact::Version for us to attempt to + /// parse the reset of the fields. (Future versions might have backwards-compat support + /// for lower versions). + /// "4" -- 6 byte packed IPv4 address & port: 4 bytes of IPv4 address followed by 2 bytes of + /// port, both encoded in network (i.e. big-endian) order. + /// "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). + /// "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). + /// "v" -- lokinet version of the router; this is a three-byte packed value of + /// MAJOR, MINOR, PATCH, e.g. \x00\x0a\x03 for 0.10.3. + /// "~" -- signature of all of the previous serialized data, signed by "p" std::string bt_encode() const; - void - bt_encode_subdict(oxenc::bt_list_producer& btlp) const; - - std::string - bencode_signed_section() const; - - std::string - ToTXTRecord() const; + virtual void + bt_encode(oxenc::bt_dict_producer& btdp) const + { + (void)btdp; + } bool operator==(const RouterContact& other) const { - return addr == other.addr && enckey == other.enckey && pubkey == other.pubkey - && signature == other.signature && last_updated == other.last_updated - && netID == other.netID; + return _router_id == other._router_id and _addr == other._addr and _addr6 == other._addr6 + and _timestamp == other._timestamp and _router_version == other._router_version; } bool operator<(const RouterContact& other) const { - return pubkey < other.pubkey; + return _router_id < other._router_id; } bool @@ -147,14 +189,9 @@ namespace llarp return !(*this == other); } - void - Clear(); - - bool - IsExit() const - { - return false; - } + virtual void + clear() + {} bool BDecode(llarp_buffer_t* buf); @@ -163,64 +200,170 @@ namespace llarp decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf); bool - IsPublicRouter() const; - - bool - Verify(llarp_time_t now, bool allowExpired = true) const; - - bool - Sign(const llarp::SecretKey& secret); + is_public_router() const; /// does this RC expire soon? default delta is 1 minute bool - ExpiresSoon(llarp_time_t now, llarp_time_t dlt = 1min) const; + expires_within_delta(llarp_time_t now, llarp_time_t dlt = 1min) const; /// returns true if this RC is expired and should be removed bool - IsExpired(llarp_time_t now) const; + is_expired(llarp_time_t now) const; /// returns time in ms until we expire or 0 if we have expired llarp_time_t - TimeUntilExpires(llarp_time_t now) const; + time_to_expiry(llarp_time_t now) const; /// get the age of this RC in ms llarp_time_t - Age(llarp_time_t now) const; + age(llarp_time_t now) const; bool - OtherIsNewer(const RouterContact& other) const + other_is_newer(const RouterContact& other) const { - return last_updated < other.last_updated; + return _timestamp < other._timestamp; } bool - Read(const fs::path& fname); + read(const fs::path& fname); bool - Write(const fs::path& fname) const; + write(const fs::path& fname) const; bool - VerifySignature() const; + is_obsolete_bootstrap() const; - /// return true if the netid in this rc is for the network id we are using - bool - FromOurNetwork() const; + void + bt_load(oxenc::bt_dict_consumer& data); - bool - IsObsoleteBootstrap() const; + }; + + /// 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 + /// + /// Note: this class may be entirely superfluous, so it is used here as a placeholder until its + /// marginal utility is determined. It may end up as a free-floating method that reads in + /// parameters and outputs a bt-serialized string + struct LocalRC : public RouterContact + { private: - bool - DecodeVersion_0(llarp_buffer_t* buf); + ustring _signature; + + const SecretKey _secret_key; + + void + bt_sign(oxenc::bt_dict_consumer& btdc); + + void + resign(); + + public: + LocalRC(std::string payload, const SecretKey sk); + + void + bt_encode(oxenc::bt_dict_producer& btdp) const override; + + void + clear() override + { + _addr = {}; + _addr6.reset(); + _router_id.Zero(); + _timestamp = {}; + _router_version.fill(0); + _signature.clear(); + } bool - DecodeVersion_1(oxenc::bt_list_consumer& btlist); + operator==(const LocalRC& other) const + { + return _router_id == other._router_id and _addr == other._addr and _addr6 == other._addr6 + and _timestamp == other._timestamp and _router_version == other._router_version + and _signature == other._signature; + } + + /// Mutators for the private member attributes. Calling on the mutators + /// will clear the current signature and re-sign the RC + void + set_addr(oxen::quic::Address new_addr) + { + resign(); + _addr = std::move(new_addr); + } + + void + set_addr6(oxen::quic::Address new_addr) + { + resign(); + _addr6 = std::move(new_addr); + } + + void + set_router_id(RouterID rid) + { + resign(); + _router_id = std::move(rid); + } + + void + set_timestamp(llarp_time_t ts) + { + set_timestamp(rc_time{std::chrono::duration_cast(ts)}); + } + + void + set_timestamp(rc_time ts) + { + _timestamp = ts; + } + + /// Sets RC timestamp to current system clock time + void + set_systime_timestamp() + { + set_timestamp( + std::chrono::time_point_cast(std::chrono::system_clock::now())); + } + }; + + + /// Extension of RouterContact used in a "read-only" fashion. Parses the incoming RC to query + /// the data in the constructor, eliminating the need for a ::verify method/ + struct RemoteRC : public RouterContact + { + private: + // + + void + bt_verify(oxenc::bt_dict_consumer& data, bool reject_expired = false); + + public: + RemoteRC(std::string payload); + + // TODO: this method could use oxenc's append_encoded + void + bt_encode(oxenc::bt_dict_producer& btdp) const override; + + void + clear() override + { + _addr = {}; + _addr6.reset(); + _router_id.Zero(); + _timestamp = {}; + _router_version.fill(0); + } + }; - template <> - constexpr inline bool IsToStringFormattable = true; template <> constexpr inline bool IsToStringFormattable = true; + template <> + constexpr inline bool IsToStringFormattable = true; + template <> + constexpr inline bool IsToStringFormattable = true; using RouterLookupHandler = std::function&)>; } // namespace llarp @@ -233,7 +376,7 @@ namespace std size_t operator()(const llarp::RouterContact& r) const { - return std::hash{}(r.pubkey); + return std::hash{}(r.router_id()); } }; } // namespace std diff --git a/llarp/router_contact_local.cpp b/llarp/router_contact_local.cpp new file mode 100644 index 000000000..275b3c64e --- /dev/null +++ b/llarp/router_contact_local.cpp @@ -0,0 +1,108 @@ +#include "constants/version.hpp" +#include "crypto/crypto.hpp" +#include "net/net.hpp" +#include "router_contact.hpp" +#include "util/bencode.hpp" +#include "util/buffer.hpp" +#include "util/file.hpp" +#include "util/time.hpp" + +#include + +namespace llarp +{ + LocalRC::LocalRC(std::string payload, const SecretKey sk) : + _secret_key{std::move(sk)} + { + _router_id = llarp::seckey_to_pubkey(_secret_key); + + try + { + oxenc::bt_dict_consumer btdc{payload}; + bt_load(btdc); + bt_sign(btdc); + } + catch (const std::exception& e) + { + log::warning(logcat, "Failed to parse LocalRC: {}", e.what()); + throw; + } + } + + void + LocalRC::bt_sign(oxenc::bt_dict_consumer& btdc) + { + _signature.clear(); + + btdc.require_signature("~", [&](ustring_view msg, ustring_view s) { + if (!crypto::sign(const_cast(s.data()), _secret_key, msg)) + throw std::runtime_error{"Failed to sign RC"}; + + _signature = s; + _signed_payload = msg; + }); + } + + void + LocalRC::bt_encode(oxenc::bt_dict_producer& btdp) const + { + btdp.append("", RC_VERSION); + + std::array buf; + + { + if (not _addr.is_ipv4()) + throw std::runtime_error{"Unable to encode RC: addr is not IPv4"}; + + auto in4 = _addr.in4(); + + std::memcpy(buf.data(), &in4.sin_addr.s_addr, 4); + std::memcpy(buf.data() + 4, &in4.sin_port, 2); + + btdp.append("4", ustring_view{buf.data(), 6}); + } + + if (_addr6) + { + if (not _addr.is_ipv6()) + throw std::runtime_error{"Unable to encode RC: addr6 is set but is not IPv6"}; + + auto in6 = _addr.in6(); + + std::memcpy(buf.data(), &in6.sin6_addr.s6_addr, 16); + std::memcpy(buf.data() + 16, &in6.sin6_port, 2); + + btdp.append("6", ustring_view{buf.data(), 18}); + } + + if (ACTIVE_NETID != llarp::LOKINET_DEFAULT_NETID) + btdp.append("i", ACTIVE_NETID); + + btdp.append("p", _router_id.ToView()); + + btdp.append("t", _timestamp.time_since_epoch().count()); + + static_assert(llarp::LOKINET_VERSION.size() == 3); + btdp.append( + "v", std::string_view{reinterpret_cast(llarp::LOKINET_VERSION.data()), 3}); + + btdp.append_signature("~", [&](ustring_view to_sign) { + std::array sig; + + if (!crypto::sign(sig.data(), _secret_key, to_sign)) + throw std::runtime_error{"Failed to sign LocalRC"}; + + return sig; + }); + } + + void + LocalRC::resign() + { + oxenc::bt_dict_consumer btdc{_signed_payload}; + bt_sign(btdc); + + // DISCUSS: should we also update the timestamp when we re-sign? + // -> Is the timestamp referring to signing time or time the RC was originally created? + } +} // namespace llarp diff --git a/llarp/router_contact_remote.cpp b/llarp/router_contact_remote.cpp new file mode 100644 index 000000000..f17100310 --- /dev/null +++ b/llarp/router_contact_remote.cpp @@ -0,0 +1,69 @@ +#include "constants/version.hpp" +#include "crypto/crypto.hpp" +#include "net/net.hpp" +#include "router_contact.hpp" +#include "util/bencode.hpp" +#include "util/buffer.hpp" +#include "util/file.hpp" +#include "util/time.hpp" + +#include + +namespace llarp +{ + RemoteRC::RemoteRC(std::string payload) + { + try + { + oxenc::bt_dict_consumer btdc{payload}; + bt_load(btdc); + bt_verify(btdc); + } + catch (const std::exception& e) + { + log::warning(logcat, "Failed to parse RemoteRC: {}", e.what()); + throw; + } + } + + void + RemoteRC::bt_encode(oxenc::bt_dict_producer& btdp) const + { + (void)btdp; + + // TODO: implement append_encoded in oxenc so we can finish this implementation. + // It is almost identical to the implementation of LocalRC::bt_encode, except the + // call to append_signature is append_encoded. + // + // When that is done, we can take the common logic and move it into the base class + // ::bt_encode, and then have each derived class call into a different virtual method + // that calls append_signature in the LocalRC and append_encoded in the RemoteRC + } + + void + RemoteRC::bt_verify(oxenc::bt_dict_consumer& data, bool reject_expired) + { + data.require_signature("~", [this, reject_expired](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()) and reject_expired) + 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"}; + + _signed_payload = msg; + }); + } +} // namespace llarp diff --git a/llarp/router_id.hpp b/llarp/router_id.hpp index 273460f91..8a82f924d 100644 --- a/llarp/router_id.hpp +++ b/llarp/router_id.hpp @@ -3,9 +3,11 @@ #include "util/aligned.hpp" #include "util/status.hpp" +#include + namespace llarp { - struct RouterID : public AlignedBuffer<32> + struct RouterID : public PubKey { static constexpr size_t SIZE = 32; @@ -13,10 +15,10 @@ namespace llarp RouterID() = default; - RouterID(const byte_t* buf) : AlignedBuffer(buf) + RouterID(const byte_t* buf) : PubKey(buf) {} - RouterID(const Data& data) : AlignedBuffer(data) + RouterID(const Data& data) : PubKey(data) {} util::StatusObject diff --git a/llarp/rpc/lokid_rpc_client.cpp b/llarp/rpc/lokid_rpc_client.cpp index dfbcb253f..c9390b3b7 100644 --- a/llarp/rpc/lokid_rpc_client.cpp +++ b/llarp/rpc/lokid_rpc_client.cpp @@ -181,7 +181,7 @@ namespace llarp::rpc nlohmann::json payload = { {"pubkey_ed25519", oxenc::to_hex(pk.begin(), pk.end())}, - {"version", {VERSION[0], VERSION[1], VERSION[2]}}}; + {"version", {LOKINET_VERSION[0], LOKINET_VERSION[1], LOKINET_VERSION[2]}}}; if (auto err = r->OxendErrorState()) payload["error"] = *err; diff --git a/llarp/rpc/rpc_server.cpp b/llarp/rpc/rpc_server.cpp index 9e7581e50..92a7d71b3 100644 --- a/llarp/rpc/rpc_server.cpp +++ b/llarp/rpc/rpc_server.cpp @@ -154,7 +154,7 @@ namespace llarp::rpc RPCServer::invoke(Version& version) { util::StatusObject result{ - {"version", llarp::VERSION_FULL}, {"uptime", to_json(m_Router.Uptime())}}; + {"version", llarp::LOKINET_VERSION_FULL}, {"uptime", to_json(m_Router.Uptime())}}; SetJSONResponse(result, version.response); } diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 3b1a4dc44..7b5451612 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -223,10 +223,12 @@ namespace llarp::service // handles when we resolved a .snode auto handleResolvedSNodeName = [resultHandler, nodedb = router()->node_db()](auto router_id) { std::vector result{}; + if (auto maybe_rc = nodedb->get_rc(router_id)) { - result = maybe_rc->srvRecords; + result = maybe_rc->srvRecords; // TODO: RouterContact has no SRV records } + resultHandler(std::move(result)); }; @@ -766,7 +768,7 @@ namespace llarp::service }); if (not maybe.has_value()) return std::nullopt; - return GetHopsForBuildWithEndpoint(maybe->pubkey); + return GetHopsForBuildWithEndpoint(maybe->router_id()); } std::optional> diff --git a/llarp/service/identity.cpp b/llarp/service/identity.cpp index 3452146b5..b6333dcd7 100644 --- a/llarp/service/identity.cpp +++ b/llarp/service/identity.cpp @@ -44,7 +44,7 @@ namespace llarp::service { crypto::identity_keygen(signkey); crypto::encryption_keygen(enckey); - pub.Update(seckey_topublic(signkey), seckey_topublic(enckey)); + pub.Update(seckey_to_pubkey(signkey), seckey_to_pubkey(enckey)); crypto::pqe_keygen(pq); if (not crypto::derive_subkey_private(derivedSignKey, signkey, 1)) { @@ -114,7 +114,7 @@ namespace llarp::service // read file try { - util::slurp_file(fname, tmp.data(), tmp.size()); + util::file_to_buffer(fname, tmp.data(), tmp.size()); } catch (const std::length_error&) { @@ -139,7 +139,7 @@ namespace llarp::service if (!vanity.IsZero()) van = vanity; // update pubkeys - pub.Update(seckey_topublic(signkey), seckey_topublic(enckey), van); + pub.Update(seckey_to_pubkey(signkey), seckey_to_pubkey(enckey), van); if (not crypto::derive_subkey_private(derivedSignKey, signkey, 1)) { throw std::runtime_error("failed to derive subkey"); @@ -163,7 +163,7 @@ namespace llarp::service // set service info i.address_keys = pub; // set public encryption key - i.sntru_pubkey = pq_keypair_to_public(pq); + i.sntru_pubkey = pq_keypair_to_pubkey(pq); auto bte = i.bt_encode(); diff --git a/llarp/service/protocol.cpp b/llarp/service/protocol.cpp index bcc2960ef..6848e4698 100644 --- a/llarp/service/protocol.cpp +++ b/llarp/service/protocol.cpp @@ -256,7 +256,7 @@ namespace llarp::service // copy ProtocolFrameMessage frame(self->frame); if (!crypto::pqe_decrypt( - self->frame.cipher, K, pq_keypair_to_secret(self->m_LocalIdentity.pq))) + self->frame.cipher, K, pq_keypair_to_seckey(self->m_LocalIdentity.pq))) { LogError("pqke failed C=", self->frame.cipher); self->msg.reset(); diff --git a/llarp/util/bencode.hpp b/llarp/util/bencode.hpp index aae0fe3b1..fcde4efbc 100644 --- a/llarp/util/bencode.hpp +++ b/llarp/util/bencode.hpp @@ -365,7 +365,7 @@ namespace llarp std::string content; try { - content = util::slurp_file(fpath); + content = util::file_to_string(fpath); } catch (const std::exception&) { diff --git a/llarp/util/file.cpp b/llarp/util/file.cpp index ff929d016..26b21d987 100644 --- a/llarp/util/file.cpp +++ b/llarp/util/file.cpp @@ -19,7 +19,7 @@ namespace llarp::util { static std::streampos - slurp_file_open(const fs::path& filename, fs::ifstream& in) + file_reader_impl(const fs::path& filename, fs::ifstream& in) { in.exceptions(std::ifstream::failbit | std::ifstream::badbit); in.open(filename, std::ios::binary | std::ios::in); @@ -30,21 +30,21 @@ namespace llarp::util } std::string - slurp_file(const fs::path& filename) + file_to_string(const fs::path& filename) { fs::ifstream in; std::string contents; - auto size = slurp_file_open(filename, in); + auto size = file_reader_impl(filename, in); contents.resize(size); in.read(contents.data(), size); return contents; } size_t - slurp_file(const fs::path& filename, char* buffer, size_t buffer_size) + file_to_buffer(const fs::path& filename, char* buffer, size_t buffer_size) { fs::ifstream in; - auto size = slurp_file_open(filename, in); + auto size = file_reader_impl(filename, in); if (static_cast(size) > buffer_size) throw std::length_error{"file is too large for buffer"}; in.read(buffer, size); diff --git a/llarp/util/file.hpp b/llarp/util/file.hpp index a66b1555f..82ff2bfbc 100644 --- a/llarp/util/file.hpp +++ b/llarp/util/file.hpp @@ -14,21 +14,21 @@ namespace llarp::util { /// Reads a binary file from disk into a string. Throws on error. std::string - slurp_file(const fs::path& filename); + file_to_string(const fs::path& filename); /// Reads a binary file from disk directly into a buffer. Throws a std::length_error if the /// file is bigger than the buffer. Returns the bytes copied on success. size_t - slurp_file(const fs::path& filename, char* buffer, size_t buffer_size); + file_to_buffer(const fs::path& filename, char* buffer, size_t buffer_size); /// Same, but for some non-char but single-byte char type (e.g. byte_t, std::byte, unsigned char). template < typename Char, std::enable_if_t, int> = 1> inline size_t - slurp_file(const fs::path& filename, Char* buffer, size_t buffer_size) + file_to_buffer(const fs::path& filename, Char* buffer, size_t buffer_size) { - return slurp_file(filename, reinterpret_cast(buffer), buffer_size); + return file_to_buffer(filename, reinterpret_cast(buffer), buffer_size); } /// Dumps binary string contents to disk. The file is overwritten if it already exists. Throws