From 3c46b07bfe326c35019fb65d5445a75ec98a3887 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Mon, 31 Jul 2023 08:38:41 -0400 Subject: [PATCH 001/312] Add oxen-libquic submodule TODO: correctly plug it into CMake and remove ngtcp2 submodule from lokinet as it will now come from oxen-libquic, if even used directly by lokinet at all. --- .gitmodules | 3 +++ external/CMakeLists.txt | 6 +++--- external/oxen-libquic | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) create mode 160000 external/oxen-libquic diff --git a/.gitmodules b/.gitmodules index 837e3a6575..1a28d576d8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -39,3 +39,6 @@ [submodule "external/CLI11"] path = external/CLI11 url = https://github.com/CLIUtils/CLI11.git +[submodule "external/oxen-libquic"] + path = external/oxen-libquic + url = https://github.com/oxen-io/oxen-libquic.git diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index c2226bd773..70ae346196 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -33,7 +33,7 @@ if(SUBMODULE_CHECK) check_submodule(oxen-encoding) check_submodule(uvw) check_submodule(cpr) - check_submodule(ngtcp2) + check_submodule(oxen-libquic) check_submodule(CLI11) endif() endif() @@ -95,8 +95,8 @@ target_include_directories(uvw INTERFACE uvw/src) target_link_libraries(uvw INTERFACE libuv) # ngtcp2 needs some massaging to build nicely: -include(ngtcp2_lib) -add_ngtcp2_lib() +#include(ngtcp2_lib) +#add_ngtcp2_lib() # cpr configuration. Ideally we'd just do this via add_subdirectory, but cpr's cmake requires # 3.15+, and we target lower than that (and this is fairly simple to build). diff --git a/external/oxen-libquic b/external/oxen-libquic new file mode 160000 index 0000000000..d431c2feca --- /dev/null +++ b/external/oxen-libquic @@ -0,0 +1 @@ +Subproject commit d431c2fecad97a7e37612ffdba1cd3f9db89a364 From 9b42a21ca2484677b0ecb919b150a18d51528c5e Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Mon, 31 Jul 2023 08:42:03 -0400 Subject: [PATCH 002/312] initial quic wire proto Connection skeleton --- llarp/link/connection.hpp | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 llarp/link/connection.hpp diff --git a/llarp/link/connection.hpp b/llarp/link/connection.hpp new file mode 100644 index 0000000000..8b0f749fd0 --- /dev/null +++ b/llarp/link/connection.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include +#include + +#include + +namespace llarp::link +{ + + class Connection + { + std::shared_ptr conn; + + RouterID remote_id; + RouterContact remote_rc; + AddressInfo remote_addr_info; // RC may have many, this is the one in use for this connection + + bool inbound; // one side of a connection will be responsible for some things, e.g. heartbeat + bool remote_is_relay; + + public: + + const RouterContact& RemoteRC() { return remote_rc; } + const RouterID& RemoteID() { return remote_id; } + + bool RemoteIsRelay() { return remote_is_relay; } + + }; +} // namespace llarp::link From 22ac3cd26e0ce69f57b8e5caddbff5309a1bfd61 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Mon, 31 Jul 2023 10:27:33 -0400 Subject: [PATCH 003/312] initial quic wire proto Endpoint skeleton --- llarp/link/endpoint.hpp | 54 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 llarp/link/endpoint.hpp diff --git a/llarp/link/endpoint.hpp b/llarp/link/endpoint.hpp new file mode 100644 index 0000000000..1686052dc0 --- /dev/null +++ b/llarp/link/endpoint.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include + +#include + +namespace llarp::link +{ + +#ifndef NDEBUG + struct debug_hooks + { + oxen::quic::dgram_data_callback incoming_datagram; + oxen::quic::stream_data_callback incoming_stream_packet; + }; +#endif + + class Endpoint + { + std::shared_ptr endpoint; + + // for outgoing packets, we route via RouterID; map RouterID->Connection + // for incoming packets, we get a ConnectionID; map ConnectionID->RouterID + std::unordered_map> connections; + std::unordered_map connid_map; + + AbstractRouter* router; + oxen::quic::Address bind_addr; + + public: + +#ifndef NDEBUG + debug_hooks debug; + // could obviously set directly because public, but setter doesn't hurt + void SetDebugHooks(debug_hooks hooks) { debug = std::move(hooks); } +#endif + + Endpoint(AbstractRouter* router, oxen::quic::Address bind_addr); + + // Establish a connection to the remote `rc`. + // + // If already connected (or pending), returns existing connection. + // If connection not possible (e.g. no suitable remote address), returns nullptr. + // Otherwise, creates and returns Connection, usable right away. + std::shared_ptr Connect(RouterContact rc); + + // Return the Connection to `remote` if we have one, else nullptr. + std::shared_ptr GetConnection(RouterID remote); + + void HandleIncomingDataMessage(oxen::quic::dgram_interface& dgi, bstring dgram); + void HandleIncomingControlMessage(oxen::quic::Stream& stream, bstring_view packet); + }; + +} // namespace llarp::link From ad5055b85fffa5d925631ee58155abca3cefc976 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Mon, 31 Jul 2023 08:49:06 -0700 Subject: [PATCH 004/312] cmake tweaks for redundant dependencies (WIP) --- .clang-tidy | 8 +++- .gitmodules | 6 --- CMakeLists.txt | 2 +- external/CMakeLists.txt | 18 ++++----- external/oxen-encoding | 1 - external/oxen-logging | 1 - llarp/CMakeLists.txt | 5 ++- llarp/link/connection.hpp | 2 +- llarp/link/endpoint.hpp | 5 ++- llarp/net/ip_address.hpp | 2 +- llarp/net/net_int.hpp | 12 +++--- llarp/quic/connection.cpp | 77 +++++++++++++++++++-------------------- llarp/quic/connection.hpp | 4 +- llarp/quic/endpoint.cpp | 2 +- llarp/router/router.hpp | 3 ++ llarp/util/buffer.hpp | 2 +- 16 files changed, 76 insertions(+), 74 deletions(-) delete mode 160000 external/oxen-encoding delete mode 160000 external/oxen-logging diff --git a/.clang-tidy b/.clang-tidy index b9b50e74bf..dbcf69f4bc 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,2 +1,8 @@ HeaderFilterRegex: 'llarp/.*' -Checks: 'readability-else-after-return,clang-analyzer-core-*,modernize-*,-modernize-use-trailing-return-type,-modernize-use-nodiscard,bugprone-*,-bugprone-easily-swappable-parameters' +Checks: +'readability-else-after-return, +clang-analyzer-core-*,modernize-*, +-modernize-use-trailing-return-type, +-modernize-use-nodiscard, +bugprone-*, +-bugprone-easily-swappable-parameters' diff --git a/.gitmodules b/.gitmodules index 1a28d576d8..38524f3db1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -27,12 +27,6 @@ path = external/ngtcp2 url = https://github.com/ngtcp2/ngtcp2.git branch = v0.1.0 -[submodule "external/oxen-encoding"] - path = external/oxen-encoding - url = https://github.com/oxen-io/oxen-encoding.git -[submodule "external/oxen-logging"] - path = external/oxen-logging - url = https://github.com/oxen-io/oxen-logging.git [submodule "gui"] path = gui url = https://github.com/oxen-io/lokinet-gui.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 039262a2bc..c775c1626a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,7 +130,7 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON) include(cmake/unix.cmake) include(cmake/check_for_std_optional.cmake) -include(cmake/check_for_std_filesystem.cmake) +#include(cmake/check_for_std_filesystem.cmake) if(NOT WIN32) if(IOS OR ANDROID) diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 70ae346196..364a4d0f7b 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -25,12 +25,11 @@ if(SUBMODULE_CHECK) message(STATUS "Checking submodules") check_submodule(nlohmann) - check_submodule(ghc-filesystem) - check_submodule(oxen-logging fmt spdlog) +# check_submodule(ghc-filesystem) +# check_submodule(oxen-logging fmt spdlog) check_submodule(pybind11) check_submodule(sqlite_orm) check_submodule(oxen-mq) - check_submodule(oxen-encoding) check_submodule(uvw) check_submodule(cpr) check_submodule(oxen-libquic) @@ -60,18 +59,17 @@ macro(system_or_submodule BIGNAME smallname pkgconf subdir) endif() endmacro() -system_or_submodule(OXENC oxenc liboxenc>=1.0.4 oxen-encoding) system_or_submodule(OXENMQ oxenmq liboxenmq>=1.2.14 oxen-mq) set(JSON_BuildTests OFF CACHE INTERNAL "") set(JSON_Install OFF CACHE INTERNAL "") system_or_submodule(NLOHMANN nlohmann_json nlohmann_json>=3.7.0 nlohmann) -if (STATIC OR FORCE_SPDLOG_SUBMODULE OR FORCE_FMT_SUBMODULE) - set(OXEN_LOGGING_FORCE_SUBMODULES ON CACHE INTERNAL "") -endif() -set(OXEN_LOGGING_SOURCE_ROOT "${PROJECT_SOURCE_DIR}" CACHE INTERNAL "") -add_subdirectory(oxen-logging) +#if (STATIC OR FORCE_SPDLOG_SUBMODULE OR FORCE_FMT_SUBMODULE) +# set(OXEN_LOGGING_FORCE_SUBMODULES ON CACHE INTERNAL "") +#endif() +#set(OXEN_LOGGING_SOURCE_ROOT "${PROJECT_SOURCE_DIR}" CACHE INTERNAL "") +#add_subdirectory(oxen-logging) if(WITH_HIVE) add_subdirectory(pybind11 EXCLUDE_FROM_ALL) @@ -98,6 +96,8 @@ target_link_libraries(uvw INTERFACE libuv) #include(ngtcp2_lib) #add_ngtcp2_lib() +add_subdirectory(oxen-libquic) + # cpr configuration. Ideally we'd just do this via add_subdirectory, but cpr's cmake requires # 3.15+, and we target lower than that (and this is fairly simple to build). if(WITH_BOOTSTRAP) diff --git a/external/oxen-encoding b/external/oxen-encoding deleted file mode 160000 index a869ae2b01..0000000000 --- a/external/oxen-encoding +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a869ae2b0152ad70855e3774a425c39a25ae1ca6 diff --git a/external/oxen-logging b/external/oxen-logging deleted file mode 160000 index b6e70ad3aa..0000000000 --- a/external/oxen-logging +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b6e70ad3aa3b2d718f8607599864cd50a951166a diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index 6653a5f08c..a6e2e59f17 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -509,12 +509,13 @@ target_link_libraries(lokinet-platform PUBLIC target_link_libraries(lokinet-util PUBLIC nlohmann_json::nlohmann_json - filesystem +# filesystem oxenc::oxenc ) target_link_libraries(lokinet-plainquic PUBLIC - ngtcp2_static + ngtcp2_crypto + libquic uvw ) diff --git a/llarp/link/connection.hpp b/llarp/link/connection.hpp index 8b0f749fd0..9d1759f19a 100644 --- a/llarp/link/connection.hpp +++ b/llarp/link/connection.hpp @@ -3,7 +3,7 @@ #include #include -#include +#include namespace llarp::link { diff --git a/llarp/link/endpoint.hpp b/llarp/link/endpoint.hpp index 1686052dc0..6240a17886 100644 --- a/llarp/link/endpoint.hpp +++ b/llarp/link/endpoint.hpp @@ -1,8 +1,11 @@ #pragma once +#include "connection.hpp" + +#include #include -#include +#include namespace llarp::link { diff --git a/llarp/net/ip_address.hpp b/llarp/net/ip_address.hpp index 5be44071e7..51fbb050c9 100644 --- a/llarp/net/ip_address.hpp +++ b/llarp/net/ip_address.hpp @@ -19,7 +19,7 @@ namespace llarp /// As a convenience, it can produce a SockAddr for dealing with network libraries which depend /// sockaddr structs. However, it does not keep this as a member variable and isn't responsible /// for its lifetime/memory/etc. - struct [[deprecated("use llarp::SockAddr instead")]] IpAddress + struct /* [[deprecated("use llarp::SockAddr instead")]] */ IpAddress { /// Empty constructor. IpAddress() = default; diff --git a/llarp/net/net_int.hpp b/llarp/net/net_int.hpp index e34f9b23ba..173a764bd1 100644 --- a/llarp/net/net_int.hpp +++ b/llarp/net/net_int.hpp @@ -256,25 +256,25 @@ namespace llarp template <> inline constexpr bool IsToStringFormattable = true; - using nuint16_t [[deprecated("use llarp::net::port_t instead")]] = llarp::net::port_t; - using nuint32_t [[deprecated("use llarp::net::ipv4addr_t instead")]] = llarp::net::ipv4addr_t; - using nuint128_t [[deprecated("use llarp::net::ipv6addr_t instead")]] = llarp::net::ipv6addr_t; + using nuint16_t /* [[deprecated("use llarp::net::port_t instead")]] */ = llarp::net::port_t; + using nuint32_t /* [[deprecated("use llarp::net::ipv4addr_t instead")]] */ = llarp::net::ipv4addr_t; + using nuint128_t /* [[deprecated("use llarp::net::ipv6addr_t instead")]] */ = llarp::net::ipv6addr_t; template - [[deprecated("use llarp::net::ToNet instead")]] inline llarp::nuint_t +/* [[deprecated("use llarp::net::ToNet instead")]] */ inline llarp::nuint_t ToNet(llarp::huint_t x) { return llarp::net::ToNet(x); } template - [[deprecated("use llarp::net::ToHost instead")]] inline llarp::huint_t +/* [[deprecated("use llarp::net::ToHost instead")]] */ inline llarp::huint_t ToHost(llarp::nuint_t x) { return llarp::net::ToHost(x); } - [[deprecated("use llarp::net::ToHost instead")]] inline net::ipv4addr_t +/* [[deprecated("use llarp::net::ToHost instead")]] */ inline net::ipv4addr_t xhtonl(huint32_t x) { return ToNet(x); diff --git a/llarp/quic/connection.cpp b/llarp/quic/connection.cpp index 389828c78e..741f932d92 100644 --- a/llarp/quic/connection.cpp +++ b/llarp/quic/connection.cpp @@ -83,7 +83,7 @@ namespace llarp::quic int recv_crypto_data( ngtcp2_conn* conn_, - ngtcp2_crypto_level crypto_level, + ngtcp2_encryption_level crypto_level, uint64_t offset, const uint8_t* rawdata, size_t rawdatalen, @@ -95,12 +95,12 @@ namespace llarp::quic auto& conn = *static_cast(user_data); switch (crypto_level) { - case NGTCP2_CRYPTO_LEVEL_EARLY: - // We don't currently use or support 0rtt - LogWarn("Invalid EARLY crypto level"); - return FAIL; + // case NGTCP2_CRYPTO_LEVEL_EARLY: + // // We don't currently use or support 0rtt + // LogWarn("Invalid EARLY crypto level"); + // return FAIL; - case NGTCP2_CRYPTO_LEVEL_INITIAL: + case NGTCP2_ENCRYPTION_LEVEL_INITIAL: log::trace(log_cat, "Receiving initial crypto..."); // "Initial" level means we are still handshaking; if we are server then we receive // the client's transport params (sent in client_initial, above) and blast ours @@ -112,15 +112,15 @@ namespace llarp::quic if (ngtcp2_conn_is_server(conn)) { - if (auto rv = conn.send_magic(NGTCP2_CRYPTO_LEVEL_INITIAL); rv != 0) + if (auto rv = conn.send_magic(NGTCP2_ENCRYPTION_LEVEL_INITIAL); rv != 0) return rv; - if (auto rv = conn.send_transport_params(NGTCP2_CRYPTO_LEVEL_HANDSHAKE); rv != 0) + if (auto rv = conn.send_transport_params(NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE); rv != 0) return rv; } break; - case NGTCP2_CRYPTO_LEVEL_HANDSHAKE: + case NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE: log::trace(log_cat, "Receiving handshake crypto..."); if (!ngtcp2_conn_is_server(conn)) { @@ -130,7 +130,7 @@ namespace llarp::quic // the server can install our rx key; we have to send *something* back to invoke // the server's HANDSHAKE callback (so that it knows handshake is complete) so // send the magic again. - if (auto rv = conn.send_magic(NGTCP2_CRYPTO_LEVEL_HANDSHAKE); rv != 0) + if (auto rv = conn.send_magic(NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE); rv != 0) return rv; } else @@ -398,7 +398,7 @@ namespace llarp::quic settings.initial_ts = get_timestamp(); // FIXME: IPv6 - settings.max_udp_payload_size = Endpoint::max_pkt_size_v4; + settings.max_tx_udp_payload_size = Endpoint::max_pkt_size_v4; settings.cc_algo = NGTCP2_CC_ALGO_CUBIC; // settings.initial_rtt = ???; # NGTCP2's default is 333ms @@ -719,9 +719,6 @@ namespace llarp::quic if (nwrite == 0) { LogTrace("Nothing else to write for non-stream data for now (or we are congested)"); - ngtcp2_conn_stat cstat; - ngtcp2_conn_get_conn_stat(*this, &cstat); - LogTrace("Current unacked bytes in flight: ", cstat.bytes_in_flight); break; } @@ -773,7 +770,7 @@ namespace llarp::quic if (!good) { LogDebug("stream_open_callback returned failure, dropping stream ", id); - ngtcp2_conn_shutdown_stream(*this, id.id, 1); + ngtcp2_conn_shutdown_stream(*this, 0, id.id, 1); io_ready(); return NGTCP2_ERR_CALLBACK_FAILURE; } @@ -944,9 +941,9 @@ namespace llarp::quic { endpoint.null_crypto.client_initial(*this); - if (int rv = send_magic(NGTCP2_CRYPTO_LEVEL_INITIAL); rv != 0) + if (int rv = send_magic(NGTCP2_ENCRYPTION_LEVEL_INITIAL); rv != 0) return rv; - if (int rv = send_transport_params(NGTCP2_CRYPTO_LEVEL_INITIAL); rv != 0) + if (int rv = send_transport_params(NGTCP2_ENCRYPTION_LEVEL_INITIAL); rv != 0) return rv; io_ready(); @@ -997,7 +994,7 @@ namespace llarp::quic endpoint.null_crypto.install_rx_key(*this); if (!ngtcp2_conn_is_server(*this)) endpoint.null_crypto.install_tx_key(*this); - ngtcp2_conn_handshake_completed(*this); + ngtcp2_conn_tls_handshake_completed(*this); if (on_handshake_complete) { @@ -1125,21 +1122,22 @@ namespace llarp::quic } } - ngtcp2_transport_params params; + // ngtcp2_transport_params params; - auto exttype = is_server ? NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO - : NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS; + // auto exttype = is_server ? NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO + // : NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS; - auto rv = ngtcp2_decode_transport_params(¶ms, exttype, data.data(), data.size()); - LogDebug("Decode transport params ", rv == 0 ? "success" : "fail: "s + ngtcp2_strerror(rv)); - LogTrace("params orig dcid = ", ConnectionID(params.original_dcid)); - LogTrace("params init scid = ", ConnectionID(params.initial_scid)); - if (rv == 0) - { - rv = ngtcp2_conn_set_remote_transport_params(*this, ¶ms); - LogDebug( - "Set remote transport params ", rv == 0 ? "success" : "fail: "s + ngtcp2_strerror(rv)); - } + auto rv = ngtcp2_conn_decode_and_set_remote_transport_params(*this, data.data(), data.size()); + // auto rv = ngtcp2_decode_transport_params(¶ms, exttype, data.data(), data.size()); + // LogDebug("Decode transport params ", rv == 0 ? "success" : "fail: "s + ngtcp2_strerror(rv)); + // LogTrace("params orig dcid = ", ConnectionID(params.original_dcid)); + // LogTrace("params init scid = ", ConnectionID(params.initial_scid)); + // if (rv == 0) + // { + // rv = ngtcp2_conn_set_remote_transport_params(*this, ¶ms); + // LogDebug( + // "Set remote transport params ", rv == 0 ? "success" : "fail: "s + ngtcp2_strerror(rv)); + // } if (rv != 0) { @@ -1153,7 +1151,7 @@ namespace llarp::quic // Sends our magic string at the given level. This fixed magic string is taking the place of TLS // parameters in full QUIC. int - Connection::send_magic(ngtcp2_crypto_level level) + Connection::send_magic(ngtcp2_encryption_level level) { return ngtcp2_conn_submit_crypto_data( *this, level, handshake_magic.data(), handshake_magic.size()); @@ -1171,10 +1169,9 @@ namespace llarp::quic // Sends transport parameters. `level` is expected to be INITIAL for clients (which send the // transport parameters in the initial packet), or HANDSHAKE for servers. int - Connection::send_transport_params(ngtcp2_crypto_level level) + Connection::send_transport_params(ngtcp2_encryption_level level) { - ngtcp2_transport_params tparams; - ngtcp2_conn_get_local_transport_params(*this, &tparams); + ngtcp2_transport_params tparams = *ngtcp2_conn_get_local_transport_params(*this); assert(conn_buffer.empty()); conn_buffer.resize(Endpoint::max_pkt_size_v4); @@ -1196,12 +1193,11 @@ namespace llarp::quic assert(buf < bufend); } - const bool is_server = ngtcp2_conn_is_server(*this); - auto exttype = is_server ? NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS - : NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO; + // const bool is_server = ngtcp2_conn_is_server(*this); + // auto exttype = is_server ? NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS + // : NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO; - if (ngtcp2_ssize nwrite = ngtcp2_encode_transport_params(buf, bufend - buf, exttype, &tparams); - nwrite >= 0) + if (ngtcp2_ssize nwrite = ngtcp2_conn_encode_local_transport_params(*this, buf, bufend-buf); nwrite >= 0) { assert(nwrite > 0); conn_buffer.resize(buf - u8data(conn_buffer) + nwrite); @@ -1211,6 +1207,7 @@ namespace llarp::quic conn_buffer.clear(); return nwrite; } + LogDebug("encoded transport params: ", buffer_printer{conn_buffer}); return ngtcp2_conn_submit_crypto_data(*this, level, u8data(conn_buffer), conn_buffer.size()); } diff --git a/llarp/quic/connection.hpp b/llarp/quic/connection.hpp index b3e19989fd..d483ee8195 100644 --- a/llarp/quic/connection.hpp +++ b/llarp/quic/connection.hpp @@ -324,9 +324,9 @@ namespace llarp::quic int recv_transport_params(std::basic_string_view data); int - send_magic(ngtcp2_crypto_level level); + send_magic(ngtcp2_encryption_level level); int - send_transport_params(ngtcp2_crypto_level level); + send_transport_params(ngtcp2_encryption_level level); void complete_handshake(); }; diff --git a/llarp/quic/endpoint.cpp b/llarp/quic/endpoint.cpp index 55fc9262c5..a8459b5ec1 100644 --- a/llarp/quic/endpoint.cpp +++ b/llarp/quic/endpoint.cpp @@ -130,7 +130,7 @@ namespace llarp::quic void Endpoint::handle_conn_packet(Connection& conn, const Packet& p) { - if (ngtcp2_conn_is_in_closing_period(conn)) + if (ngtcp2_conn_in_closing_period(conn)) { LogDebug("Connection is in closing period, dropping"); close_connection(conn); diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 16efb1fccc..007ff9c7bb 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -47,6 +47,8 @@ #include +#include + namespace llarp { struct Router : public AbstractRouter @@ -233,6 +235,7 @@ namespace llarp std::shared_ptr _nodedb; llarp_time_t _startedAt; const oxenmq::TaggedThreadID m_DiskThread; + oxen::quic::Network _net; llarp_time_t Uptime() const override; diff --git a/llarp/util/buffer.hpp b/llarp/util/buffer.hpp index abb0cffa06..c77df8a311 100644 --- a/llarp/util/buffer.hpp +++ b/llarp/util/buffer.hpp @@ -27,7 +27,7 @@ struct ManagedBuffer; /// TODO: replace usage of these with std::span (via a backport until we move to C++20). That's a /// fairly big job, though, as llarp_buffer_t is currently used a bit differently (i.e. maintains /// both start and current position, plus has some value reading/writing methods). -struct [[deprecated("this type is stupid, use something else")]] llarp_buffer_t +struct /* [[deprecated("this type is stupid, use something else")]] */ llarp_buffer_t { /// starting memory address byte_t* base{nullptr}; From ab863184047cbec847c5202942e3bf6a2e785ffb Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Mon, 28 Aug 2023 10:56:44 -0400 Subject: [PATCH 005/312] Partial implementation of libquic as wire protocol TODO: - set up all the callbacks for libquic - define control message requests, responses, commands - plug new control messages into lokinet (path creation, network state, etc) - plug connection state changes (established, failed, closed, etc.) into lokinet - lots of cleanup and miscellanea --- llarp/link/connection.hpp | 13 +- llarp/link/endpoint.hpp | 38 +- llarp/link/i_link_manager.hpp | 33 +- llarp/link/link_manager.cpp | 413 ++++++++-------------- llarp/link/link_manager.hpp | 86 +++-- llarp/net/address_info.cpp | 8 + llarp/net/address_info.hpp | 3 + llarp/router/abstractrouter.hpp | 4 - llarp/router/outbound_message_handler.cpp | 6 +- llarp/router/outbound_session_maker.cpp | 107 ++---- llarp/router/outbound_session_maker.hpp | 12 +- llarp/router/router.cpp | 198 ++++------- llarp/router/router.hpp | 12 +- 13 files changed, 337 insertions(+), 596 deletions(-) diff --git a/llarp/link/connection.hpp b/llarp/link/connection.hpp index 9d1759f19a..d137ef4a41 100644 --- a/llarp/link/connection.hpp +++ b/llarp/link/connection.hpp @@ -8,23 +8,14 @@ namespace llarp::link { - class Connection + struct Connection { std::shared_ptr conn; + std::shared_ptr control_stream; - RouterID remote_id; RouterContact remote_rc; - AddressInfo remote_addr_info; // RC may have many, this is the one in use for this connection bool inbound; // one side of a connection will be responsible for some things, e.g. heartbeat bool remote_is_relay; - - public: - - const RouterContact& RemoteRC() { return remote_rc; } - const RouterID& RemoteID() { return remote_id; } - - bool RemoteIsRelay() { return remote_is_relay; } - }; } // namespace llarp::link diff --git a/llarp/link/endpoint.hpp b/llarp/link/endpoint.hpp index 6240a17886..5c1f506204 100644 --- a/llarp/link/endpoint.hpp +++ b/llarp/link/endpoint.hpp @@ -10,48 +10,16 @@ namespace llarp::link { -#ifndef NDEBUG - struct debug_hooks - { - oxen::quic::dgram_data_callback incoming_datagram; - oxen::quic::stream_data_callback incoming_stream_packet; - }; -#endif - - class Endpoint + struct Endpoint { std::shared_ptr endpoint; + bool inbound {false}; // for outgoing packets, we route via RouterID; map RouterID->Connection // for incoming packets, we get a ConnectionID; map ConnectionID->RouterID - std::unordered_map> connections; + std::unordered_map connections; std::unordered_map connid_map; - AbstractRouter* router; - oxen::quic::Address bind_addr; - - public: - -#ifndef NDEBUG - debug_hooks debug; - // could obviously set directly because public, but setter doesn't hurt - void SetDebugHooks(debug_hooks hooks) { debug = std::move(hooks); } -#endif - - Endpoint(AbstractRouter* router, oxen::quic::Address bind_addr); - - // Establish a connection to the remote `rc`. - // - // If already connected (or pending), returns existing connection. - // If connection not possible (e.g. no suitable remote address), returns nullptr. - // Otherwise, creates and returns Connection, usable right away. - std::shared_ptr Connect(RouterContact rc); - - // Return the Connection to `remote` if we have one, else nullptr. - std::shared_ptr GetConnection(RouterID remote); - - void HandleIncomingDataMessage(oxen::quic::dgram_interface& dgi, bstring dgram); - void HandleIncomingControlMessage(oxen::quic::Stream& stream, bstring_view packet); }; } // namespace llarp::link diff --git a/llarp/link/i_link_manager.hpp b/llarp/link/i_link_manager.hpp index 48ffd3d94f..3e9d07456c 100644 --- a/llarp/link/i_link_manager.hpp +++ b/llarp/link/i_link_manager.hpp @@ -20,7 +20,7 @@ namespace llarp { virtual ~ILinkManager() = default; - virtual LinkLayer_ptr + virtual llarp::link::Endpoint* GetCompatibleLink(const RouterContact& rc) const = 0; virtual IOutboundSessionMaker* @@ -34,28 +34,12 @@ namespace llarp uint16_t priority = 0) = 0; virtual bool - HasSessionTo(const RouterID& remote) const = 0; + HaveConnection(const RouterID& remote) const = 0; - // it is fine to have both an inbound and outbound session with - // another relay, and is useful for network testing. This test - // is more specific for use with "should we connect outbound?" - virtual bool - HasOutboundSessionTo(const RouterID& remote) const = 0; - - /// return true if the session with this pubkey is a client - /// return false if the session with this pubkey is a router - /// return std::nullopt we have no session with this pubkey - virtual std::optional - SessionIsClient(RouterID remote) const = 0; - - virtual void - PumpLinks() = 0; - - virtual void - AddLink(LinkLayer_ptr link, bool inbound = false) = 0; - - virtual bool - StartLinks() = 0; + /// return true if we have a connection to the remote and it is not a relay, + /// else return false + bool + HaveClientConnection(const RouterID& remote) const = 0; virtual void Stop() = 0; @@ -82,14 +66,11 @@ namespace llarp DeregisterPeer(RouterID remote) = 0; virtual size_t - NumberOfConnectedRouters() const = 0; + NumberOfConnectedRouters(bool clients_only = false) const = 0; virtual size_t NumberOfConnectedClients() const = 0; - virtual size_t - NumberOfPendingConnections() const = 0; - virtual bool GetRandomConnectedRouter(RouterContact& router) const = 0; diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 116bfb3929..1977907728 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -8,32 +8,25 @@ namespace llarp { - LinkLayer_ptr + llarp::link::Endpoint* LinkManager::GetCompatibleLink(const RouterContact& rc) const { if (stopping) return nullptr; - for (auto& link : outboundLinks) + for (const auto& ep : endpoints) { - // TODO: may want to add some memory of session failures for a given - // router on a given link and not return that link here for a - // duration - if (not link->IsCompatable(rc)) - continue; - - return link; + //TODO: need some notion of "is this link compatible with that address". + // iwp just checks that the link dialect ("iwp") matches the address info dialect, + // but that feels insufficient. For now, just return the first endpoint we have; + // we should probably only have 1 for now anyway until we make ipv6 work. + return &ep; } return nullptr; } - IOutboundSessionMaker* - LinkManager::GetSessionMaker() const - { - return _sessionMaker; - } - + //TODO: replace with control/data message sending with libquic bool LinkManager::SendTo( const RouterID& remote, @@ -58,108 +51,48 @@ namespace llarp } bool - LinkManager::HasSessionTo(const RouterID& remote) const - { - return GetLinkWithSessionTo(remote) != nullptr; - } - - bool - LinkManager::HasOutboundSessionTo(const RouterID& remote) const + LinkManager::HaveClientConnection(const RouterID& remote) const { - for (const auto& link : outboundLinks) + for (const auto& ep : endpoints) { - if (link->HasSessionTo(remote)) + if (auto itr = ep.connections.find(remote); itr != ep.connections.end()) + { + if (itr->second.remote_is_relay) + return false; return true; + } } return false; } - std::optional - LinkManager::SessionIsClient(RouterID remote) const - { - for (const auto& link : inboundLinks) - { - const auto session = link->FindSessionByPubkey(remote); - if (session) - return not session->IsRelay(); - } - if (HasOutboundSessionTo(remote)) - return false; - return std::nullopt; - } - void LinkManager::DeregisterPeer(RouterID remote) { m_PersistingSessions.erase(remote); - for (const auto& link : inboundLinks) + for (const auto& ep : endpoints) { - link->CloseSessionTo(remote); + if (auto itr = ep.connections.find(remote); itr != ep.connections.end()) + itr->second.conn->close(); //TODO: libquic needs some function for this } - for (const auto& link : outboundLinks) - { - link->CloseSessionTo(remote); - } - LogInfo(remote, " has been de-registered"); - } - void - LinkManager::PumpLinks() - { - for (const auto& link : inboundLinks) - { - link->Pump(); - } - for (const auto& link : outboundLinks) - { - link->Pump(); - } + LogInfo(remote, " has been de-registered"); } void - LinkManager::AddLink(LinkLayer_ptr link, bool inbound) + AddLink(oxen::quic::Address bind, bool inbound = false) { - util::Lock l(_mutex); - + //TODO: libquic callbacks: new_conn_alpn_notify, new_conn_pubkey_ok, new_conn_established/ready + auto ep = quic->endpoint(bind); + endpoints.emplace_back(); + auto& endp = endpoints.back(); + endp.endpoint = std::move(ep); if (inbound) { - inboundLinks.emplace(link); - } - else - { - outboundLinks.emplace(link); - } - } - - bool - LinkManager::StartLinks() - { - LogInfo("starting ", outboundLinks.size(), " outbound links"); - for (const auto& link : outboundLinks) - { - if (!link->Start()) - { - LogWarn("outbound link '", link->Name(), "' failed to start"); - return false; - } - LogDebug("Outbound Link ", link->Name(), " started"); - } - - if (inboundLinks.size()) - { - LogInfo("starting ", inboundLinks.size(), " inbound links"); - for (const auto& link : inboundLinks) - { - if (!link->Start()) - { - LogWarn("Link ", link->Name(), " failed to start"); - return false; - } - LogDebug("Inbound Link ", link->Name(), " started"); - } + oxen::quic::dgram_data_callback dgram_cb = [this](oxen::quic::dgram_interface& dgi, bstring dgram){ HandleIncomingDataMessage(dgi, dgram); }; + oxen::quic::stream_data_callback stream_cb = [this](oxen::quic::Stream& stream, bstring_view packet){ HandleIncomingControlMessage(stream, packet); }; + endp.endpoint->listen(tls_creds, dgram_cb, stream_cb); + endp.inbound = true; } - - return true; } void @@ -175,10 +108,7 @@ namespace llarp LogInfo("stopping links"); stopping = true; - for (const auto& link : outboundLinks) - link->Stop(); - for (const auto& link : inboundLinks) - link->Stop(); + quic.reset(); } void @@ -190,13 +120,10 @@ namespace llarp util::Lock l(_mutex); m_PersistingSessions[remote] = std::max(until, m_PersistingSessions[remote]); - if (auto maybe = SessionIsClient(remote)) + if (HaveClientConnection(remote)) { - if (*maybe) - { - // mark this as a client so we don't try to back connect - m_Clients.Upsert(remote); - } + // mark this as a client so we don't try to back connect + m_Clients.Upsert(remote); } } @@ -252,64 +179,28 @@ namespace llarp } size_t - LinkManager::NumberOfConnectedRouters() const + LinkManager::NumberOfConnectedRouters(bool clients_only) const { - std::set connectedRouters; - - auto fn = [&connectedRouters](const ILinkSession* session, bool) { - if (session->IsEstablished()) + size_t count{0}; + for (const auto& ep : endpoints) + { + for (const auto& conn : ep.connections) { - const RouterContact rc(session->GetRemoteRC()); - if (rc.IsPublicRouter()) - { - connectedRouters.insert(rc.pubkey); - } + if (not (conn.remote_is_relay and clients_only)) + count++; } - }; - - ForEachPeer(fn); + } - return connectedRouters.size(); + return count; } size_t LinkManager::NumberOfConnectedClients() const { - std::set connectedClients; - - auto fn = [&connectedClients](const ILinkSession* session, bool) { - if (session->IsEstablished()) - { - const RouterContact rc(session->GetRemoteRC()); - if (!rc.IsPublicRouter()) - { - connectedClients.insert(rc.pubkey); - } - } - }; - - ForEachPeer(fn); - - return connectedClients.size(); - } - - size_t - LinkManager::NumberOfPendingConnections() const - { - size_t pending = 0; - for (const auto& link : inboundLinks) - { - pending += link->NumberOfPendingSessions(); - } - - for (const auto& link : outboundLinks) - { - pending += link->NumberOfPendingSessions(); - } - - return pending; + return NumberOfConnectedRouters(true); } + //TODO: libquic bool LinkManager::GetRandomConnectedRouter(RouterContact& router) const { @@ -339,148 +230,142 @@ namespace llarp return false; } + //TODO: this? perhaps no longer necessary in the same way? void LinkManager::CheckPersistingSessions(llarp_time_t now) { if (stopping) return; - - std::vector sessionsNeeded; - std::vector sessionsClosed; - - { - util::Lock l(_mutex); - for (auto [remote, until] : m_PersistingSessions) - { - if (now < until) - { - auto link = GetLinkWithSessionTo(remote); - if (link) - { - link->KeepAliveSessionTo(remote); - } - else if (not m_Clients.Contains(remote)) - { - sessionsNeeded.push_back(remote); - } - } - else if (not m_Clients.Contains(remote)) - { - sessionsClosed.push_back(remote); - } - } - } - - for (const auto& router : sessionsNeeded) - { - LogDebug("ensuring session to ", router, " for previously made commitment"); - _sessionMaker->CreateSessionTo(router, nullptr); - } - - for (const auto& router : sessionsClosed) - { - m_PersistingSessions.erase(router); - ForEachOutboundLink([router](auto link) { link->CloseSessionTo(router); }); - } } + //TODO: do we still need this concept? void LinkManager::updatePeerDb(std::shared_ptr peerDb) { - std::vector> statsToUpdate; - - int64_t diffTotalTX = 0; - - ForEachPeer([&](ILinkSession* session) { - // derive RouterID - RouterID id = RouterID(session->GetRemoteRC().pubkey); - - SessionStats sessionStats = session->GetSessionStats(); - SessionStats diff; - SessionStats& lastStats = m_lastRouterStats[id]; - - // TODO: operator overloads / member func for diff - diff.currentRateRX = std::max(sessionStats.currentRateRX, lastStats.currentRateRX); - diff.currentRateTX = std::max(sessionStats.currentRateTX, lastStats.currentRateTX); - diff.totalPacketsRX = sessionStats.totalPacketsRX - lastStats.totalPacketsRX; - diff.totalAckedTX = sessionStats.totalAckedTX - lastStats.totalAckedTX; - diff.totalDroppedTX = sessionStats.totalDroppedTX - lastStats.totalDroppedTX; - - diffTotalTX = diff.totalAckedTX + diff.totalDroppedTX + diff.totalInFlightTX; - - lastStats = sessionStats; - - // TODO: if we have both inbound and outbound session, this will overwrite - statsToUpdate.push_back({id, diff}); - }); - - for (auto& routerStats : statsToUpdate) - { - peerDb->modifyPeerStats(routerStats.first, [&](PeerStats& stats) { - // TODO: store separate stats for up vs down - const auto& diff = routerStats.second; - - // note that 'currentRateRX' and 'currentRateTX' are per-second - stats.peakBandwidthBytesPerSec = std::max( - stats.peakBandwidthBytesPerSec, - (double)std::max(diff.currentRateRX, diff.currentRateTX)); - stats.numPacketsDropped += diff.totalDroppedTX; - stats.numPacketsSent = diff.totalAckedTX; - stats.numPacketsAttempted = diffTotalTX; - - // TODO: others -- we have slight mismatch on what we store - }); - } } + //TODO: this util::StatusObject LinkManager::ExtractStatus() const { - std::vector ob_links, ib_links; - std::transform( - inboundLinks.begin(), - inboundLinks.end(), - std::back_inserter(ib_links), - [](const auto& link) -> util::StatusObject { return link->ExtractStatus(); }); - std::transform( - outboundLinks.begin(), - outboundLinks.end(), - std::back_inserter(ob_links), - [](const auto& link) -> util::StatusObject { return link->ExtractStatus(); }); - - util::StatusObject obj{{"outbound", ob_links}, {"inbound", ib_links}}; - - return obj; + return {}; } void - LinkManager::Init(IOutboundSessionMaker* sessionMaker) + LinkManager::Init(I_RCLookupHandler* rcLookup) { stopping = false; - _sessionMaker = sessionMaker; + _rcLookup = rcLookup; + _nodedb = router->nodedb(); } - LinkLayer_ptr - LinkManager::GetLinkWithSessionTo(const RouterID& remote) const + void + LinkManager::Connect(RouterID router) { - if (stopping) - return nullptr; + auto fn = [this](const RouterID& r, const RouterContact* const rc, const RCRequestResult res){ + if (res == RCRequestResult::Success) + Connect(*rc); + /* TODO: + else + RC lookup failure callback here + */ + }; - for (const auto& link : outboundLinks) + _rcLookup->GetRC(router, fn); + } + + // This function assumes the RC has already had its signature verified and connection is allowed. + void + LinkManager::Connect(RouterContact rc) + { + //TODO: connection failed callback + if (HaveConnection(rc.pubkey)) + return; + + // RC shouldn't be valid if this is the case, but may as well sanity check... + //TODO: connection failed callback + if (rc.addrs.empty()) + return; + + //TODO: connection failed callback + auto* ep = GetCompatibleLink(rc); + if (ep == nullptr) + return; + + //TODO: connection established/failed callbacks + oxen::quic::dgram_data_callback dgram_cb = [this](oxen::quic::dgram_interface& dgi, bstring dgram){ HandleIncomingDataMessage(dgi, dgram); }; + oxen::quic::stream_data_callback stream_cb = [this](oxen::quic::Stream& stream, bstring_view packet){ HandleIncomingControlMessage(stream, packet); }; + + //TODO: once "compatible link" cares about address, actually choose addr to connect to + // based on which one is compatible with the link we chose. For now, just use + // the first one. + auto& selected = rc.addrs[0]; + llarp::quic::opt::remote_addr remote{selected.IPString(), selected.port}; + //TODO: confirm remote end is using the expected pubkey (RouterID). + //TODO: ALPN for "client" vs "relay" (could just be set on endpoint creation) + auto conn_interface = ep->connect(remote, dgram_cb, stream_cb, tls_creds); + + std::shared_ptr stream = conn_interface->get_new_stream(); + + llarp::link::Connection conn; + conn.conn = conn_interface; + conn.control_stream = stream; + conn.remote_rc = rc; + conn.inbound = false; + conn.remote_is_relay = true; + + ep->connections[rc.pubkey] = std::move(conn); + ep->connid_map[conn_interface->scid()] = rc.pubkey; + } + + void + LinkManager::ConnectToRandomRouters(int numDesired) + { + std::set exclude; + do { - if (link->HasSessionTo(remote)) + auto filter = [exclude](const auto& rc) -> bool { return exclude.count(rc.pubkey) == 0; }; + + RouterContact other; + if (const auto maybe = _nodedb->GetRandom(filter)) { - return link; + other = *maybe; } - } - for (const auto& link : inboundLinks) + else + break; + + exclude.insert(other.pubkey); + if (not _rcLookup->SessionIsAllowed(other.pubkey)) + continue; + + Connect(other); + --remainingDesired; + } while (remainingDesired > 0); + } + + bool + LinkManager::HaveConnection(const RouterID& remote) + { + for (const auto& ep : endpoints) { - if (link->HasSessionTo(remote)) + if (ep.connections.contains(remote)) { - return link; + return true; } } - return nullptr; + return false; + } + + void + LinkManager::HandleIncomingDataMessage(oxen::quic::dgram_interface& dgi, bstring dgram) + { + //TODO: this + } + + void + LinkManager::HandleIncomingControlMessage(oxen::quic::Stream& stream, bstring_view packet) + { + //TODO: this } } // namespace llarp diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 77179b7131..939cab70e9 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -4,6 +4,9 @@ #include #include "server.hpp" +#include "endpoint.hpp" + +#include #include #include @@ -16,9 +19,11 @@ namespace llarp struct LinkManager final : public ILinkManager { public: + LinkManager(AbstractRouter* r) : router(r) {} + ~LinkManager() override = default; - LinkLayer_ptr + llarp::link::Endpoint* GetCompatibleLink(const RouterContact& rc) const override; IOutboundSessionMaker* @@ -32,25 +37,16 @@ namespace llarp uint16_t priority) override; bool - HasSessionTo(const RouterID& remote) const override; + HaveConnection(const RouterID& remote) const override; bool - HasOutboundSessionTo(const RouterID& remote) const override; - - std::optional - SessionIsClient(RouterID remote) const override; + HaveClientConnection(const RouterID& remote) const void DeregisterPeer(RouterID remote) override; void - PumpLinks() override; - - void - AddLink(LinkLayer_ptr link, bool inbound = false) override; - - bool - StartLinks() override; + AddLink(oxen::quic::Address bind, bool inbound = false); void Stop() override; @@ -58,28 +54,29 @@ namespace llarp void PersistSessionUntil(const RouterID& remote, llarp_time_t until) override; + //TODO: change for libquic Connections void ForEachPeer(std::function visit, bool randomize = false) const override; + //TODO: change for libquic Connections void ForEachPeer(std::function visit) override; + //TODO: change for libquic Endpoints void ForEachInboundLink(std::function visit) const override; + //TODO: change for libquic Endpoints void ForEachOutboundLink(std::function visit) const override; size_t - NumberOfConnectedRouters() const override; + NumberOfConnectedRouters(bool clients_only = false) const override; size_t NumberOfConnectedClients() const override; - size_t - NumberOfPendingConnections() const override; - bool GetRandomConnectedRouter(RouterContact& router) const override; @@ -93,20 +90,40 @@ namespace llarp ExtractStatus() const override; void - Init(IOutboundSessionMaker* sessionMaker); + Init(I_RCLookupHandler* rcLookup); + + // Do an RC lookup for the given RouterID; the result will trigger + // Connect(RouterContact) on success (or if we already have it), and will + // trigger connection failure callback on lookup failure. + void + Connect(RouterID router); + + // Establish a connection to the remote `rc`. + // + // Connection established/failed callbacks should be invoked when either happens, + // but this function should do nothing if already connected. + void + Connect(RouterContact rc); + + // Attempts to connect to a number of random routers. + // + // This will try to connect to *up to* numDesired routers, but will not + // check if we already have a connection to any of the random set, as making + // that thread safe would be slow...I think. + void + ConnectToRandomRouters(int numDesired); + + //TODO: tune these (maybe even remove max?) now that we're switching to quic + /// always maintain this many connections to other routers + size_t minConnectedRouters = 4; + /// hard upperbound limit on the number of router to router connections + size_t maxConnectedRouters = 6; private: - LinkLayer_ptr - GetLinkWithSessionTo(const RouterID& remote) const; std::atomic stopping; mutable util::Mutex _mutex; // protects m_PersistingSessions - using LinkSet = std::set>; - - LinkSet outboundLinks; - LinkSet inboundLinks; - // sessions to persist -> timestamp to end persist at std::unordered_map m_PersistingSessions GUARDED_BY(_mutex); @@ -114,7 +131,24 @@ namespace llarp util::DecayingHashSet m_Clients{path::default_lifetime}; - IOutboundSessionMaker* _sessionMaker; + I_RCLookupHandler* _rcLookup; + std::shared_ptr _nodedb; + + AbstractRouter* router; + + // FIXME: Lokinet currently expects to be able to kill all network functionality before + // finishing other shutdown things, including destroying this class, and that is all in + // Network's destructor, so we need to be able to destroy it before this class. + std::unique_ptr quic { std::make_unique() }; + + std::vector endpoints; + + //TODO: initialize creds + std::shared_ptr tls_creds; + + void HandleIncomingDataMessage(oxen::quic::dgram_interface& dgi, bstring dgram); + void HandleIncomingControlMessage(oxen::quic::Stream& stream, bstring_view packet); + }; } // namespace llarp diff --git a/llarp/net/address_info.cpp b/llarp/net/address_info.cpp index f39b1d4c94..d9b11543c2 100644 --- a/llarp/net/address_info.cpp +++ b/llarp/net/address_info.cpp @@ -178,6 +178,14 @@ namespace llarp return fmt::format("[{}]:{}", tmp, port); } + std::string + AddressInfo::IPString() const + { + char tmp[INET6_ADDRSTRLEN] = {0}; + inet_ntop(AF_INET6, (void*)&ip, tmp, sizeof(tmp)); + return std::string{sizeof(tmp), tmp}; + } + void to_json(nlohmann::json& j, const AddressInfo& a) { diff --git a/llarp/net/address_info.hpp b/llarp/net/address_info.hpp index 73d41939eb..5b87c33170 100644 --- a/llarp/net/address_info.hpp +++ b/llarp/net/address_info.hpp @@ -65,6 +65,9 @@ namespace llarp std::string ToString() const; + + std::string + IPString() const; }; void diff --git a/llarp/router/abstractrouter.hpp b/llarp/router/abstractrouter.hpp index 162b506167..8f5eeb9ebb 100644 --- a/llarp/router/abstractrouter.hpp +++ b/llarp/router/abstractrouter.hpp @@ -40,7 +40,6 @@ namespace llarp struct SecretKey; struct Signature; struct IOutboundMessageHandler; - struct IOutboundSessionMaker; struct ILinkManager; struct I_RCLookupHandler; struct RoutePoker; @@ -175,9 +174,6 @@ namespace llarp virtual IOutboundMessageHandler& outboundMessageHandler() = 0; - virtual IOutboundSessionMaker& - outboundSessionMaker() = 0; - virtual ILinkManager& linkManager() = 0; diff --git a/llarp/router/outbound_message_handler.cpp b/llarp/router/outbound_message_handler.cpp index 0a793b2ff1..93d1c47c26 100644 --- a/llarp/router/outbound_message_handler.cpp +++ b/llarp/router/outbound_message_handler.cpp @@ -24,7 +24,7 @@ namespace llarp const RouterID& remote, const ILinkMessage& msg, SendStatusHandler callback) { // if the destination is invalid, callback with failure and return - if (not _router->linkManager().SessionIsClient(remote) + if (not _router->linkManager().HaveClientConnection(remote) and not _router->rcLookupHandler().SessionIsAllowed(remote)) { DoCallback(callback, SendStatus::InvalidRouter); @@ -49,7 +49,7 @@ namespace llarp std::copy_n(buf.base, buf.sz, ent.message.data()); // if we have a session to the destination, queue the message and return - if (_router->linkManager().HasSessionTo(remote)) + if (_router->linkManager().HaveConnection(remote)) { QueueOutboundMessage(std::move(ent)); return true; @@ -213,7 +213,7 @@ namespace llarp bool OutboundMessageHandler::SendIfSession(const MessageQueueEntry& ent) { - if (_router->linkManager().HasSessionTo(ent.router)) + if (_router->linkManager().HaveConnection(ent.router)) { return Send(ent); } diff --git a/llarp/router/outbound_session_maker.cpp b/llarp/router/outbound_session_maker.cpp index 4eb264487f..7150f6b43a 100644 --- a/llarp/router/outbound_session_maker.cpp +++ b/llarp/router/outbound_session_maker.cpp @@ -6,7 +6,7 @@ #include #include #include "i_rc_lookup_handler.hpp" -#include +#include #include #include #include @@ -17,19 +17,6 @@ namespace llarp { - struct PendingSession - { - // TODO: add session establish status metadata, e.g. num retries - - const RouterContact rc; - LinkLayer_ptr link; - - size_t attemptCount = 0; - - PendingSession(RouterContact _rc, LinkLayer_ptr _link) - : rc(std::move(_rc)), link(std::move(_link)) - {} - }; bool OutboundSessionMaker::OnSessionEstablished(ILinkSession* session) @@ -67,12 +54,12 @@ namespace llarp void OutboundSessionMaker::CreateSessionTo(const RouterID& router, RouterCallback on_result) { - if (on_result) { util::Lock l(_mutex); auto itr_pair = pendingCallbacks.emplace(router, CallbacksQueue{}); - itr_pair.first->second.push_back(on_result); + if (on_result) + itr_pair.first->second.push_back(on_result); } if (HavePendingSessionTo(router)) @@ -85,7 +72,7 @@ namespace llarp // short-circuit to success callback if we already have an outbound session // to the remote - if (_linkManager->HasOutboundSessionTo(router)) + if (_linkManager->HasConnection(router)) { FinalizeRequest(router, SessionResult::Establish); return; @@ -103,12 +90,12 @@ namespace llarp { const RouterID router{rc.pubkey}; - if (on_result) { util::Lock l(_mutex); auto itr_pair = pendingCallbacks.emplace(router, CallbacksQueue{}); - itr_pair.first->second.push_back(on_result); + if (on_result) + itr_pair.first->second.push_back(on_result); } if (not HavePendingSessionTo(router)) @@ -117,14 +104,6 @@ namespace llarp CreatePendingSession(router); } - // short-circuit to success callback if we already have an outbound session - // to the remote - if (_linkManager->HasOutboundSessionTo(router)) - { - FinalizeRequest(router, SessionResult::Establish); - return; - } - GotRouterContact(router, rc); } @@ -132,7 +111,7 @@ namespace llarp OutboundSessionMaker::HavePendingSessionTo(const RouterID& router) const { util::Lock l(_mutex); - return pendingSessions.find(router) != pendingSessions.end(); + return pendingCallbacks.find(router) != pendingCallbacks.end(); } void @@ -195,60 +174,25 @@ namespace llarp } void - OutboundSessionMaker::DoEstablish(const RouterID& router) + OutboundSessionMaker::GotRouterContact(const RouterID& router, const RouterContact& rc) { - std::unique_lock l{_mutex}; - - auto itr = pendingSessions.find(router); - - if (itr == pendingSessions.end()) + if (not _rcLookup->CheckRC(rc)) { + FinalizeRequest(rc.pubkey, SessionResult::InvalidRouter); return; } - const auto& job = itr->second; - if (not job->link->TryEstablishTo(job->rc)) + if (not ShouldConnectTo(router)) { - l.unlock(); - FinalizeRequest(router, SessionResult::EstablishFail); + FinalizeRequest(router, SessionResult::NoLink); + return; } - } - - void - OutboundSessionMaker::GotRouterContact(const RouterID& router, const RouterContact& rc) - { - { - std::unique_lock l{_mutex}; - // in case other request found RC for this router after this request was - // made - auto itr = pendingSessions.find(router); - if (itr == pendingSessions.end()) - { - return; - } - - LinkLayer_ptr link = _linkManager->GetCompatibleLink(rc); - - if (not link) - { - l.unlock(); - FinalizeRequest(router, SessionResult::NoLink); - return; - } - - auto session = std::make_shared(rc, link); - - itr->second = session; - } - if (ShouldConnectTo(router)) - { - _loop->call([this, router] { DoEstablish(router); }); - } + auto result = _linkManager->Connect(rc); + if (result) + FinalizeRequest(router, SessionResult::Establish); else - { - FinalizeRequest(router, SessionResult::NoLink); - } + FinalizeRequest(router, SessionResult::EstablishFail); } bool @@ -256,16 +200,14 @@ namespace llarp { if (router == us or not _rcLookup->SessionIsAllowed(router)) return false; - if (_linkManager->HasOutboundSessionTo(router)) - return false; if (_router->IsServiceNode()) return true; size_t numPending = 0; { util::Lock lock(_mutex); - if (pendingSessions.find(router) == pendingSessions.end()) - numPending += pendingSessions.size(); + if (pendingCallbacks.find(router) == pendingCallbacks.end()) + numPending += pendingCallbacks.size(); } return _linkManager->NumberOfConnectedRouters() + numPending < maxConnectedRouters; @@ -330,14 +272,10 @@ namespace llarp FinalizeRequest(rc.pubkey, SessionResult::Establish); } + //TODO: rename this, if we even want to keep it void OutboundSessionMaker::CreatePendingSession(const RouterID& router) { - { - util::Lock l(_mutex); - pendingSessions.emplace(router, nullptr); - } - auto peerDb = _router->peerDb(); if (peerDb) { @@ -377,11 +315,6 @@ namespace llarp { _loop->call([callback, router, type] { return callback(router, type); }); } - - { - util::Lock l(_mutex); - pendingSessions.erase(router); - } } } // namespace llarp diff --git a/llarp/router/outbound_session_maker.hpp b/llarp/router/outbound_session_maker.hpp index 1906868ee2..f658ae30fe 100644 --- a/llarp/router/outbound_session_maker.hpp +++ b/llarp/router/outbound_session_maker.hpp @@ -15,7 +15,7 @@ namespace llarp { struct PendingSession; - struct ILinkManager; + struct LinkManager; struct I_RCLookupHandler; struct OutboundSessionMaker final : public IOutboundSessionMaker @@ -73,9 +73,6 @@ namespace llarp size_t maxConnectedRouters = 6; private: - void - DoEstablish(const RouterID& router) EXCLUDES(_mutex); - void GotRouterContact(const RouterID& router, const RouterContact& rc) EXCLUDES(_mutex); @@ -98,15 +95,12 @@ namespace llarp void FinalizeRequest(const RouterID& router, const SessionResult type) EXCLUDES(_mutex); - mutable util::Mutex _mutex; // protects pendingSessions, pendingCallbacks - - std::unordered_map> pendingSessions - GUARDED_BY(_mutex); + mutable util::Mutex _mutex; // protects pendingCallbacks std::unordered_map pendingCallbacks GUARDED_BY(_mutex); AbstractRouter* _router = nullptr; - ILinkManager* _linkManager = nullptr; + LinkManager* _linkManager = nullptr; I_RCLookupHandler* _rcLookup = nullptr; Profiling* _profiler = nullptr; std::shared_ptr _nodedb; diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 6a4db8c5ae..1d9dc51e6e 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -79,6 +79,8 @@ namespace llarp llarp_dht_context_free(_dht); } + //TODO: investigate changes needed for libquic integration + // still needed at all? void Router::PumpLL() { @@ -109,6 +111,7 @@ namespace llarp {"outboundMessages", _outboundMessageHandler.ExtractStatus()}}; } + //TODO: investigate changes needed for libquic integration util::StatusObject Router::ExtractSummaryStatus() const { @@ -206,6 +209,7 @@ namespace llarp return stats; } + //TODO: libquic change bool Router::HandleRecvLinkMessageBuffer(ILinkSession* session, const llarp_buffer_t& buf) { @@ -219,6 +223,8 @@ namespace llarp } return inbound_link_msg_parser.ProcessFrom(session, buf); } + + //TODO: investigate changes needed for libquic integration void Router::Freeze() { @@ -230,6 +236,7 @@ namespace llarp }); } + //TODO: investigate changes needed for libquic integration void Router::Thaw() { @@ -305,12 +312,14 @@ namespace llarp return _outboundMessageHandler.QueueMessage(remote, msg, handler); } + //TODO: if still needed/useful, replace this in line with libquic impl void Router::ForEachPeer(std::function visit, bool randomize) const { _linkManager.ForEachPeer(visit, randomize); } + //TODO: if still needed/useful, replace this in line with libquic impl void Router::ForEachPeer(std::function visit) { @@ -329,7 +338,7 @@ namespace llarp if (remote.Verify(Now())) { LogDebug("verified signature"); - _outboundSessionMaker.CreateSessionTo(remote, nullptr); + _linkManager->Connect(remote); } else LogError(rcfile, " contains invalid RC"); @@ -614,6 +623,7 @@ namespace llarp _rc = std::move(nextRC); if (rotateKeys) { + //TODO: libquic change // propagate RC by renegotiating sessions ForEachPeer([](ILinkSession* s) { if (s->RenegotiateSession()) @@ -650,8 +660,8 @@ namespace llarp // Router config _rc.SetNick(conf.router.m_nickname); - _outboundSessionMaker.maxConnectedRouters = conf.router.m_maxConnectedRouters; - _outboundSessionMaker.minConnectedRouters = conf.router.m_minConnectedRouters; + _linkManager.maxConnectedRouters = conf.router.m_maxConnectedRouters; + _linkManager.minConnectedRouters = conf.router.m_minConnectedRouters; encryption_keyfile = m_keyManager->m_encKeyPath; our_rc_file = m_keyManager->m_rcPath; @@ -771,14 +781,7 @@ namespace llarp // Init components after relevant config settings loaded _outboundMessageHandler.Init(this); - _outboundSessionMaker.Init( - this, - &_linkManager, - &_rcLookupHandler, - &_routerProfiling, - _loop, - util::memFn(&AbstractRouter::QueueWork, this)); - _linkManager.Init(&_outboundSessionMaker); + _linkManager.Init(&_rcLookupHandler); _rcLookupHandler.Init( _dht, _nodedb, @@ -791,10 +794,11 @@ namespace llarp whitelistRouters, m_isServiceNode); - // inbound links - InitInboundLinks(); - // outbound links - InitOutboundLinks(); + //FIXME: kludge for now, will be part of larger cleanup effort. + if (m_isServiceNode) + InitInboundLinks(); + else + InitOutboundLinks(); // profiling _profilesFile = conf.router.m_dataDir / "profiles.dat"; @@ -1047,10 +1051,6 @@ namespace llarp _linkManager.CheckPersistingSessions(now); size_t connected = NumberOfConnectedRouters(); - if (not isSvcNode) - { - connected += _linkManager.NumberOfPendingConnections(); - } const int interval = isSvcNode ? 5 : 2; const auto timepoint_now = Clock_t::now(); @@ -1059,7 +1059,7 @@ namespace llarp _rcLookupHandler.ExploreNetwork(); m_NextExploreAt = timepoint_now + std::chrono::seconds(interval); } - size_t connectToNum = _outboundSessionMaker.minConnectedRouters; + size_t connectToNum = _linkManager.minConnectedRouters; const auto strictConnect = _rcLookupHandler.NumberOfStrictConnectRouters(); if (strictConnect > 0 && connectToNum > strictConnect) { @@ -1097,7 +1097,7 @@ namespace llarp { size_t dlt = connectToNum - connected; LogDebug("connecting to ", dlt, " random routers to keep alive"); - _outboundSessionMaker.ConnectToRandomRouters(dlt); + _linkManager.ConnectToRandomRouters(dlt); } _hiddenServiceContext.Tick(now); @@ -1134,6 +1134,7 @@ namespace llarp } } + //TODO: libquic change // get connected peers std::set peersWeHave; _linkManager.ForEachPeer([&peersWeHave](ILinkSession* s) { @@ -1156,6 +1157,7 @@ namespace llarp return CryptoManager::instance()->sign(sig, identity(), buf); } + //TODO: replace this in line with libquic impl void Router::SessionClosed(RouterID remote) { @@ -1172,6 +1174,7 @@ namespace llarp } } + //TODO: replace this in line with libquic impl void Router::ConnectionTimedOut(ILinkSession* session) { @@ -1195,6 +1198,7 @@ namespace llarp } } + //TODO: replace this in line with libquic impl bool Router::ConnectionEstablished(ILinkSession* session, bool inbound) { @@ -1275,39 +1279,6 @@ namespace llarp _rc.routerVersion = RouterVersion(llarp::VERSION, llarp::constants::proto_version); } - _linkManager.ForEachInboundLink([&](LinkLayer_ptr link) { - AddressInfo ai; - if (link->GetOurAddressInfo(ai)) - { - // override ip and port as needed - if (_ourAddress) - { - const auto ai_ip = ai.IP(); - const auto override_ip = _ourAddress->getIP(); - - auto ai_ip_str = var::visit([](auto&& ip) { return ip.ToString(); }, ai_ip); - auto override_ip_str = var::visit([](auto&& ip) { return ip.ToString(); }, override_ip); - - if ((not Net().IsBogonIP(ai_ip)) and (not Net().IsBogonIP(override_ip)) - and ai_ip != override_ip) - throw std::runtime_error{ - "Lokinet is bound to public IP '{}', but public-ip is set to '{}'. Either fix the " - "[router]:public-ip setting or set a bind address in the [bind] section of the " - "config."_format(ai_ip_str, override_ip_str)}; - ai.fromSockAddr(*_ourAddress); - } - if (RouterContact::BlockBogons && Net().IsBogon(ai.ip)) - throw std::runtime_error{var::visit( - [](auto&& ip) { - return "cannot use " + ip.ToString() - + " as a public ip as it is in a non routable ip range"; - }, - ai.IP())}; - LogInfo("adding address: ", ai); - _rc.addrs.push_back(ai); - } - }); - if (IsServiceNode() and not _rc.IsPublicRouter()) { LogError("we are configured as relay but have no reachable addresses"); @@ -1332,12 +1303,6 @@ namespace llarp return false; } } - _outboundSessionMaker.SetOurRouter(pubkey()); - if (!_linkManager.StartLinks()) - { - LogWarn("One or more links failed to start."); - return false; - } if (IsServiceNode()) { @@ -1426,6 +1391,11 @@ namespace llarp LogDebug("Establishing session to ", router, " for SN testing"); // try to make a session to this random router // this will do a dht lookup if needed + _linkManager->Connect(router); + + /* + * TODO: container of pending snode test routers to be queried on + * connection success/failure, then do this stuff there. _outboundSessionMaker.CreateSessionTo( router, [previous_fails = fails, this](const auto& router, const auto result) { auto rpc = RpcClient(); @@ -1465,6 +1435,7 @@ namespace llarp rpc->InformConnection(router, result == SessionResult::Establish); } }); + */ } }); } @@ -1569,7 +1540,7 @@ namespace llarp bool Router::HasSessionTo(const RouterID& remote) const { - return _linkManager.HasSessionTo(remote); + return _linkManager.HaveConnection(remote); } std::string @@ -1589,13 +1560,9 @@ namespace llarp { const size_t want = _want; auto connected = NumberOfConnectedRouters(); - if (not IsServiceNode()) - { - connected += _linkManager.NumberOfPendingConnections(); - } if (connected >= want) return; - _outboundSessionMaker.ConnectToRandomRouters(want); + _linkManager.ConnectToRandomRouters(want); } bool @@ -1623,7 +1590,7 @@ namespace llarp return false; } - _outboundSessionMaker.CreateSessionTo(rc, nullptr); + _linkManager->Connect(rc); return true; } @@ -1649,6 +1616,8 @@ namespace llarp return ep and ep->HasExit(); } + //TODO: change to use new LinkManager foreach semantics, or make function for this + // on LinkManager itself std::optional> Router::OurPublicIP() const { @@ -1665,6 +1634,37 @@ namespace llarp return found; } + void + AddAddressToRC(AddressInfo& ai) + { + // override ip and port as needed + if (_ourAddress) + { + const auto ai_ip = ai.IP(); + const auto override_ip = _ourAddress->getIP(); + + auto ai_ip_str = var::visit([](auto&& ip) { return ip.ToString(); }, ai_ip); + auto override_ip_str = var::visit([](auto&& ip) { return ip.ToString(); }, override_ip); + + if ((not Net().IsBogonIP(ai_ip)) and (not Net().IsBogonIP(override_ip)) + and ai_ip != override_ip) + throw std::runtime_error{ + "Lokinet is bound to public IP '{}', but public-ip is set to '{}'. Either fix the " + "[router]:public-ip setting or set a bind address in the [bind] section of the " + "config."_format(ai_ip_str, override_ip_str)}; + ai.fromSockAddr(*_ourAddress); + } + if (RouterContact::BlockBogons && Net().IsBogon(ai.ip)) + throw std::runtime_error{var::visit( + [](auto&& ip) { + return "cannot use " + ip.ToString() + + " as a public ip as it is in a non routable ip range"; + }, + ai.IP())}; + LogInfo("adding address: ", ai); + _rc.addrs.push_back(ai); + } + void Router::InitInboundLinks() { @@ -1702,22 +1702,14 @@ namespace llarp throw std::runtime_error{"no public ip provided for inbound socket"}; } - auto server = iwp::NewInboundLink( - m_keyManager, - loop(), - util::memFn(&AbstractRouter::rc, this), - util::memFn(&AbstractRouter::HandleRecvLinkMessageBuffer, this), - util::memFn(&AbstractRouter::Sign, this), - nullptr, - util::memFn(&Router::ConnectionEstablished, this), - util::memFn(&AbstractRouter::CheckRenegotiateValid, this), - util::memFn(&Router::ConnectionTimedOut, this), - util::memFn(&AbstractRouter::SessionClosed, this), - util::memFn(&AbstractRouter::TriggerPump, this), - util::memFn(&AbstractRouter::QueueWork, this)); + _linkManager.AddLink(bind_addr.ToString(), true); - server->Bind(this, bind_addr); - _linkManager.AddLink(std::move(server), true); + AddressInfo ai; + ai.fromSockAddr(bind_addr); + ai.pubkey = llarp::seckey_topublic(_identity); + ai.dialect = "quicinet"; // FIXME: constant, also better name? + ai.rank = 2; // FIXME: hardcoded from the beginning...keep? + AddAddressToRC(ai); } } @@ -1730,47 +1722,7 @@ namespace llarp for (auto& bind_addr : addrs) { - auto link = iwp::NewOutboundLink( - m_keyManager, - loop(), - util::memFn(&AbstractRouter::rc, this), - util::memFn(&AbstractRouter::HandleRecvLinkMessageBuffer, this), - util::memFn(&AbstractRouter::Sign, this), - [this](llarp::RouterContact rc) { - if (IsServiceNode()) - return; - for (const auto& addr : rc.addrs) - m_RoutePoker->AddRoute(addr.IPv4()); - }, - util::memFn(&Router::ConnectionEstablished, this), - util::memFn(&AbstractRouter::CheckRenegotiateValid, this), - util::memFn(&Router::ConnectionTimedOut, this), - util::memFn(&AbstractRouter::SessionClosed, this), - util::memFn(&AbstractRouter::TriggerPump, this), - util::memFn(&AbstractRouter::QueueWork, this)); - - const auto& net = Net(); - - // If outbound is set to wildcard and we have just one inbound, then bind to the inbound IP; - // if you have more than one inbound you have to be explicit about your outbound. - if (net.IsWildcardAddress(bind_addr.getIP())) - { - bool multiple = false; - _linkManager.ForEachInboundLink([&bind_addr, &multiple](const auto& link) { - if (multiple) - throw std::runtime_error{ - "outbound= IP address must be specified when using multiple inbound= addresses"}; - multiple = true; - bind_addr.setIP(link->LocalSocketAddr().getIP()); - }); - } - - link->Bind(this, bind_addr); - - if constexpr (llarp::platform::is_android) - m_OutboundUDPSocket = link->GetUDPFD().value_or(-1); - - _linkManager.AddLink(std::move(link), false); + _linkManager.AddLink(bind_addr.ToString(), false); } } diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 007ff9c7bb..139941f5c1 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -311,8 +311,7 @@ namespace llarp Profiling _routerProfiling; fs::path _profilesFile; OutboundMessageHandler _outboundMessageHandler; - OutboundSessionMaker _outboundSessionMaker; - LinkManager _linkManager; + LinkManager _linkManager { this }; RCLookupHandler _rcLookupHandler; RCGossiper _rcGossiper; @@ -330,12 +329,6 @@ namespace llarp return _outboundMessageHandler; } - IOutboundSessionMaker& - outboundSessionMaker() override - { - return _outboundSessionMaker; - } - ILinkManager& linkManager() override { @@ -595,6 +588,9 @@ namespace llarp bool TooFewPeers() const; + void + AddAddressToRC(AddressInfo& ai); + protected: virtual void HandleRouterEvent(tooling::RouterEventPtr event) const override; From 1346ce53266922c9a6fbe748162f9511f79cbac6 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Mon, 28 Aug 2023 09:03:49 -0700 Subject: [PATCH 006/312] oxen-libquic bump for cmake fix --- external/oxen-libquic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/oxen-libquic b/external/oxen-libquic index d431c2feca..15821c53fc 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit d431c2fecad97a7e37612ffdba1cd3f9db89a364 +Subproject commit 15821c53fc0f261537bca89387268eea84e1f1c5 From c997ca2b60e50b54e53b5910aaa1f3121cec1fb7 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Mon, 28 Aug 2023 13:13:35 -0300 Subject: [PATCH 007/312] Don't rely on cmake search path for StaticBuild Resolves a conflict with libquic's StaticBuild. --- CMakeLists.txt | 2 +- external/oxen-libquic | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c775c1626a..bd67b5ac10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,7 +77,7 @@ if(BUILD_STATIC_DEPS AND NOT STATIC_LINK) endif() if(BUILD_STATIC_DEPS) set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE) - include(StaticBuild) + include(cmake/StaticBuild.cmake) endif() if(NOT CMAKE_BUILD_TYPE) diff --git a/external/oxen-libquic b/external/oxen-libquic index 15821c53fc..0fdbb2c8ad 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit 15821c53fc0f261537bca89387268eea84e1f1c5 +Subproject commit 0fdbb2c8ad20a729979465cf3c4f625c9c88fe04 From 4992b9b02c26fff0aa3f0e6ea4eb3496c8961807 Mon Sep 17 00:00:00 2001 From: dan Date: Thu, 26 Jan 2023 12:31:25 -0800 Subject: [PATCH 008/312] Added path-build to documentation - re-structure docs - add diagrams --- docs/architecture.md | 46 ++++++++++++++++++++++++++++ docs/high-level-overview.md | 19 ------------ docs/ideal-ux.md | 4 +-- docs/install.md | 2 +- docs/lokinet_pathbuild_no_steps.png | Bin 0 -> 106676 bytes docs/net-comparisons.md | 1 - docs/project-structure.md | 12 ++++---- docs/readme.md | 38 +++++++++-------------- 8 files changed, 70 insertions(+), 52 deletions(-) create mode 100644 docs/architecture.md delete mode 100644 docs/high-level-overview.md create mode 100644 docs/lokinet_pathbuild_no_steps.png diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000000..8fd7d51ece --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,46 @@ +# High-Level Architecture + +## Path Building + +

+ +

+ +Starting from the top, here's a high-level overview of how the lokinet client builds a path to a terminating node + +1. Client semi-randomly selects SN's for hops 2 and 3 using Introset Hash Ring (IHR) + - First hop is sticky: upon initialization of lokinet, 4-5 first hops are selected + +2. Message sent to hop 1 + - Message consists of eight records in a linked list. Four hops are typically used, leaving the last 4 links as dummy records + - Each record contains a TX (upstream) path ID and RX (downstream) path ID + - Each record has a pointer to the next record, except for the final hops' record; the pointer here is recursive, signalling the end of the path-build + +3. Hop 2 pops top record, appends metadata, and pushes record to the back of linked list + - Hop adds metadata to the record, such as optional lifetime, pubkey to derive shared secret, etc + +4. Steps 2-3 are repeated for the remaining hops until destination is reached + - Final hop reads the recursive pointer signalling the end of the path-build process + +5. Upon completion, plain-text reply is propagated backwards, where the client can then decrypt all records + +6. Client measures latency + - A) Routing message is sequentially encrypted using hop 4's key through hop 1's key + - At each iteration, the nonce is permuted by XOR'ing the previous nonce with the hash of the secret key of each hop + - B) Routing message is sent s.t. each hop can decrypt, with final hop receiving plain-text + - Each hop appends latency and expiration time data, with the final hop interpreting the plain-text as a routing message and sending it back to the client + +7. Introset is published to IHR upon successful completion; introset contains: + - Path ID's of routers + - Latency and expiration time for each hop + - DNS SRV records + - etc + +### Failure Cases + +1. Next hop is an invalid SN +2. Cannot connect to SN + +In either case, the path-build status is sent backwards with an error flag. Once received by the client, metadata related to the prospective path is wiped and the path forgotten + + diff --git a/docs/high-level-overview.md b/docs/high-level-overview.md deleted file mode 100644 index 1d2baea84c..0000000000 --- a/docs/high-level-overview.md +++ /dev/null @@ -1,19 +0,0 @@ -## onion routing overview - - - - - - - -## endpoint zmq api - - - -## DNS - - - - - - diff --git a/docs/ideal-ux.md b/docs/ideal-ux.md index 7cda8e29a5..9b78c763a2 100644 --- a/docs/ideal-ux.md +++ b/docs/ideal-ux.md @@ -8,7 +8,7 @@ The `.snode` gtld refers to a router on the network by its public ed25519 key. The `.loki` gtld refers to clients that publish the existence anonymously to the network by their ed25519 public key. (`.loki` also has the ability to use short names resolved via external consensus method, like a blockchain). -# How Do I use Lokinet? +# How do I use Lokinet? set system dns resolver to use the dns resolver provided by lokinet, make sure the upstream dns provider that lokinet uses for non lokinet gtlds is set as desired (see lokinet.ini `[dns]` section) @@ -16,7 +16,7 @@ configure exit traffic provider if you want to tunnel ip traffic via lokinet, by note: per flow (ip+proto/port) isolation is trivial on a technical level but currently not implemented at this time. -# Can I run lokinet on a soho router +# Can I run lokinet on a soho router? Yes and that is the best way to run it in practice. diff --git a/docs/install.md b/docs/install.md index 17cf9da086..21d69dd5b3 100644 --- a/docs/install.md +++ b/docs/install.md @@ -30,7 +30,7 @@ You can get the latest stable release for lokinet on windows or macos from https You do not have to build from source if you do not wish to, we provide [apt](#deb-install) and [rpm](#rpm-install) repos. -#### APT repository +#### APT Repository You can install debian packages from `deb.oxen.io` by adding the apt repo to your system. diff --git a/docs/lokinet_pathbuild_no_steps.png b/docs/lokinet_pathbuild_no_steps.png new file mode 100644 index 0000000000000000000000000000000000000000..7967150e34cbe06231782b7210ca784e2f328bbd GIT binary patch literal 106676 zcmZ_02SAf)(=JR01r!vqV4;Yjf`)`N6(Jo+A&`)Qii9*mLOMwZiWC(P3s}M4D=K0E zL@5Fa_O1v@u`dYNK%{u?xbN=!edqlD?izUtcbR+Unwe`Rn?t9O97j(XZDwZX7#f0) zG&8euGc&X3wX*?to;k0oGBb1jq$O~)i3X8GCN%Sg;r{-~8w!b6Xtdriyf+leQ!3{R zBs{U2m#CR97iz&R@H|l=kccEg!QbydAyAkf#NQ8!VEUuIVVD3U_<;G(M+G3G|9+n* z7RvuKAbdUq4B$iM@g;JtLK8pd?>B^6p7`(4&`KDO6%hfUAo)^}CITYDQ{w-AM<-Nk zBntUIlg>xY_xJz%i8fg&{QI^*sFU!8rn@i#*wKHM4rY}6XR&BpGFcQMjWmX_5|fkg z0SS5p?C(M3yu|+uLI>;h`!h6*fMmg<`AOsel01N?N)l6|v;hVgL>9_~31|WcN|ne< zWQH?^aw3k7fuN!#abYwJ-5W}TM#fQfT&WlrEezG-qm(Q$JCXuLCxb@_Vlo8CmdN3O zIfx7h2H_3GvS74Ox-f!BON0gxz;y^)!c!?VB=Ck*Ko&^lVFrSjLR1itjAWe_XFv)# zMvRt4qc9SfNq8=gD2WflaFT>tiGoW*g&38QiU>Uc!%=8iN=nWujWgj5`kf)VbyA>1Uv*w#7bb8sIW*>Vxqr}8zmG+M@eLA)9+xD&>ArojSG*)O2Ml< z(}zfhlnY=csbj$vRtEm2!dNII_&0$S36X=Fae7P~JRC&k7B!&xQj4%U9 zfgvQym?$BPqm0yH4MvtendZ+?x z%*+pwaU&UGIUFyP2%@MWE(3*=O8oU=4K-AqKqK;^Q~^w3C@TR&7O3ONLak6A1x8>; z@si+FP8=)=&BLmcBo0N6K}M-C3W7=q7et4^bh1dWORO|p6(5zL4wGsHVTlQm0*X0nf%t$Xd3D5tfu3niL?44>1VP3`m3`5uU(7t7I4h zlgnV@iBbtER2fPIM-c`IkCN%ZY7#=FGD5rp?H>)N2*M*};gke2PfaJ&qcI5xBM(Y7 zCTL_y^k^Z9183`vVjKjn4+tS6;R)f)Xp~%yii8>>DGF$mf)*)*g8_xg1RNoh%i!y< zL<1&?&qLAGCUwJrKLODqozZ{_muVn+35zQY0Qb}wyi|_|Do$kbBf%#N?2bfb3K@t< zjD(10vJ>cdED;?i^pDme4610Hh^b{Hq9YON(8xFvFASfkQ>dvJ2A3nDn&zj|qWB7W z0$mMdhN{I0LZ&*~9AtB+BYIKwWu8RxN`x|s57&Q!qQ0fvfS}Ih^H7H>e zsFaD}z$u<0f%N(_kR8~kxhL@TQu;%pL{X5?M1sPoU`vv;46FvhfhPKMqVck5nZSrgLJ$n_TghaOI7AfbPvS@F zz@o4cAm;zb6T&PDT5HQIEk`y82W7IekE`nb-KuMu28DAxlAj95!Ar6TskH0zpJFi0Qm&7>=k8hv-;|Fcc;{jxRCB8;E+5maI-pjv~WMz9)bV z4u+uD@{&}BXqH~#A0m}gv{W>g$`3;_#3UA3qzKn4*kl+4!-en!Sh-llRzzzQEJ2ta z%Ow*LXfTSHOdzWf;&=_!NM%PN6$%VbPoa@%>_nu$9H-X~ zzyTs?9FYLri;57SSg;7BNkySr7Mh4Lh9=2HC<6p7B$F{3O1RR1z=lARi7awFIuU~N zCopMxRXh#6kCKWMOk5ZBy3EC57{SOkqN4izwX zDg&?%qLeI?%A<`m6&G#*o5O1K^k`a?Uaz5QSqgtO91U!HiKThCYcQr6+_!RnY>4m}3;fg#Hu~2Prg#n297)9EoL9>0EF{4OK!_JTx^x zfhCFs;y5as1}8(gI&4%Vk!Ga$Gq73;LrfOXLf{M{Intz9B$yEii#HjZEIvwwKqcVd zCQdSV&D| zi<->S%1L}0L%<^-jA0~%3XRvHlO-@YPpc9qis%xUzn;P6ha^$71PBJEA_x-`AcoGVrQccIw@c!y}5(bS>BAHxln90%M=^-k7 z5}O$T$G{;xL^7X>#u?*Sri?&EW^u4#0rYr{Iz%5Y25(~{paf1NB0M|k`N6#SZ=^II);b)-kwPnL(zO zM?^xj8eB+d1c?*EMu@PXp~?s~ICmZ_S;fNxTf-VylmwVKJc-WL#z(W2kvz6PJ`TrY zQ)yZP5jf*etu9fGG+@YjhBPWdpJYlrSW!X(@*}8;KnlEQCLxr_z;gn`ApFB7VIsu{16?Bnt^yk!t~Etdm;ix- z#6*+iN_4cpgu*l?qo~jjr71s&gmI7`2a2#F{#uo7j zqNo5ZRfI<{aiR#Uh(n18BZHk{1tPQoBv}TCNwvX$Q3@oF5RV8C)v9!~aI%I(i4T?O zBgu+n9s+~qFtj40FccOqmL=*?JQfP4h{ICJN|6ZWPfcV}gtBm<3S+(9j19mu@GPc0M4Ox_<+B+P{OAB2N=_ira101YHRH6=sxY`n$%zYN$P>fjL#W}X zP=6v`tWQ)Sgen4z6U_=w6yd{3NjP<)0xVlAjbkCC&?r7JIReR+NaS(h3CRo$N5q30 z6ZD+uNJ;{m%nv{b=%o5{K0yNLah!e&k@DL3FWl&4P0w^3YEgTk~L=_|f zpCZvDVfgw)9>__Q#%P`()JVVu7-^9lY&4EWG9tNHe-ueVi;omSxbj4}$!$a$X`wuw zUIYjaaP<%8@rM8b*Z*O4Ui289 zUyEB?-)NRB|Il@9U2Am8xgSH%U_&2TH+Ia#2HV-0d$?PzNpo_t_#YPyP8PqNoANwn zMs4`t5B_;8)-GH20RPX`|1|(~eOkl14cAXz|G$U*&-?j~yDb05WdCE7V4|~AQ(gor zs^I^7TK5u+=KpWWJ{F#C(9y?7kGH_O?{sz_-@Bk{sAF!_skhA=3AwK2uXN3RJ1b6J zw*O!IO)v6tFY)MfI&A@@pterGIb(GTb??Hbj#E(&{FYyN@+$emUir(5lCu$qiQPpP z?y2DkPm~j53%!Tj&S%M0&rdRLuKMwm z-CbilL(5*KBDAzIR{!r4sGemywl#kQF2kGUW|qD--rhJFcEgWbQWsUkdFaO}u8ump ztZDe${h+fe2foUy)6CBe6v|E-oNUyw6$_oWJ!CP#7zN;*DbG7dalWD`;}fyIl+H)B=ni+m$K{p%`02Omo$~8 zQf>a#RQKt20rHj?eUrCr*=UwhrGK3~+r7SsN@G&b>sP}ggFW(!&zCi;2K$m2 z$0+_^Ew)%7*L!VV{OEJpn@!y>rRU&VEF;a;v31$b-FK0#+S1n4iro-iMn(HNx0YRS z>77enP5rH_`u9p79m#P+$O`gDaTpGhp>@jw<7)?ds(Ot5-JkcRbfb|8PkfLoe=7A~ z>L(693*Y@;GYszb>fQf)=%(}Lu*ec;JI(ZLnNO1@{MtkdY};=qR7bYg2CHhdM+Ck1 zeqjGH{m=HS3U*9#ed_hm9boxL_IiP!7IuFzfBh2I(LTSoZCphBJuroz{Wz=r^oWRv#k8}3e>%SZEZXB={HQZahitzyse0n> z`D@T)@rXLnl#^b-)Q@DEE$Dc@V)d)NhK?MT!~9VkNU&Lp>gKd#U5ZOjS$)lAsy8hI zANDJD*ry6CRnv<%RmbtpUF%a^yRel@v*z2{w3cZ;JUXlXy;?MHhZVo0t4**eP=t)naU?3FMRar~W#b^6BW#Wwq-ZH_F^oagUEt{p1-Wrb@NIN7oMg`QSxf*0DwKBS+E3G}j6Qme1EubmhJ zsed)zcUlQng{4eNk@JU;kje1kKT*HM=vdT3Uj zzTHCQaU#=Y7XY=b!rBAN8!JC746%z_sGNpLyOPu?lDm9Q*Ey{m*O75?Z{Ex^(U-oS z2|8c(sqJLSzqppJbOtMQDE)9M&^aCQA-%!oF2N+_YNC~0Lw2*}7gzVm_fT&(+*Q_m zO)ne689Q~=_lIXSAMROiajcW2&E#B`73SOIIeyrq*|Z%KSVk~poWAkn`3l9ujLnO> z%NFO_{^c2eq_tmh^$Rg(sRsnuo9Gj~YUnFD_i?b>jmr`k4|7fHT4%W9@dFD^IKa7jmwBme1_JBwb5zYF726$WE%ASxA9b3= zT_vdL?U+lSe%?LxXS;1~dGY7V&F`by`-cI@y}G{E{_d7^YvHFyN6%u{j(&gT;Q@># zX~Vk6qhW=EHvm>iYGyiD{d)XqYc~L+|G29|>A?kIq5voQykPe`$tFKWH@V*4)pp;z znjUYT$G-RF-2N8eZN|Kto|}H+ws7b2_mv~Rq`5&~+OuXvcV#cA{CR!5-%`Y1RQBM1 zHy2=%I_1KrD}kAIe=JU*bdTBwoM-vQ>c5_zzWXlidwwd`{l*TzrSI2VA8A%p6(-d_ zImx(tDxKq8w>R&<-v0~9o#G7}`S_kTwsw!Lr<+>5@5Ir6R{!4#x0w`?ax#5R%tcUGE3c@5w={SL5*P)R zH5YDgoAYL5xPL{idD8V!vpIcdGvbyCE$cHHY)X>-Vy?b$oCI-qi#onsv`}FA_E!DG z6|$4}D|DZyl=)#kVA@8Hm%B9OjdF=v2ljp*+XlRD>Gy5N_orT|_;hS{i^+#fPkx(E z{gqulojddT7Hxx#>$!)ANfjUVuYP^)XGbnC3G-w0ztZF4-A`=!l7iw7xt{u0w2BX*OUhzunVZOXyVu}x5LbV_1(s_wDIy#DL$7nVO_7!mJX#1DEQVsxD;a5N4 zSK1Pnl04Akw_y_AgU z3~|vuia-2uMat((-9RCsggxKey23-eHyt&vIob64K<^CW$AjIbC=7UYnD^9oyRJE= zc=X|sEy~O}ZCyD^;pZ3U4|8{nD?LEkJe{RaElCe(H+doEYr)Iw+YfOsh*-#!-S!Kv zK1llbpyp-6zM`0G#_m(6&z4lJSUsFn`g>%sBCzj8ZC_kjR`F&xl=6Tn{N!qSn>Qj~ z$FHj2mDz`LDn<&bNP|9^*Cx$4>z#-mzTs&OHHB?N1QYnPC0*}cRAH*~9__L8gZ$`R zz)|ieajXiPfuiSK`P%CBU-Qc}n>|v{dH#W?ug{*53lF?U+fT5k4EB9~1pt9B`vKxv zS!I&%0bc}p=lrDbz#rTEjum(2x%yr<1>-lTrxf|6`9gd*LE4Wz{=W2T2!EijS<#$v zch2?Nu|YE5K-WpB_9JUXjUTz7R1c(@cd{y zh-#6Q?P+I4wu^h6y?|2;k5u`oD7 z2oT=M%?dJD8!!g8xQ>60>pSkAhIm+#Cielbq&z8$q$V@ua=Ys;H3ms#A&ojUBg^49$LFLCDe zdmg~1ZMf@x$`tJV?NfqZ?r`*Z&?R}HSGLtu+8&*#NiA~wYCkxt&);W=V>fejw@X)M zch&FI!CkAy4$f*AHHK7taV4<*E@a2lV3%0)v=)8qDp6D6e%Yje_`LE3%C<~p_SaYX z*2KsKg;R^&gWV_3qU|XlZ7~RHON6)Y>^0}DUUzAZt5fMK-EQt|5Y^5gMz%d_&v(qT z$s1?4#%9NiyStIdTt-Xc`knP2yaNcC{FaXoGQ zmuo(}&v$HeU2v=ag(AdO;V+2bWBQl&dMq3bP$C5F*z4NwTYb{=zfn`3$#eXwm$@U% z2dA_+E0e1?J|^F`ZoH#z=uO}x(m|l=?6g;91Sy_4SuFfh;!p@qx#gXHF zQT}S-0w2%$Hcl1;jW%(l*e{>BhzDo+o6t8}COfq(jQ9F{Y#M2*YR#pI^O(MK7MFND z#Aeod*;$U^qqe0x)Tk%0*>RvSZE4HcXT6q$(EjzLu_ZyZC|!_N)E<1R6M5E+Lv~-5 zxz=v})Vgy%C#o*44V)zi{a3@d2!RD*I|%=SWlkuNh;EeJygFvi2AO-T^DGVI`%lLb zpY3y_ZZ+80S#Ms60$}=CU{-~ve2?w$7!}*5YV7rO1B$iG{&r6}@4@^#Bg)U!3mzzH zZdRQ?P;U<-AZ*H3h5TcscIgHW5Da|xas!qr9CVAL^U#f$(cJ}8k2x`&-xUr!+=9(N zG;&L0x7`LmdQSr78x&CQ+t8Drap^(I&cSezwDCqd33Vllz9%!BtzZz|eREaDwbz7+%LPI#J{S?4UA)4p;OImzi`x#jYDU+ctNMOs zS-G0H%!>MXvUa+lLjpLCf1Erf&5UG~N!id8+~!r}JkEMQc4#2Gu)62x%((aK)>_Uq z%k_Vs;mi8zef?r>OYNrd{PcS3t%0twEnXZ7Cl5#uGO%Z6+rk=)J6P-dH1u>)POAM9 zmW#FDvpr_Tp=q)C|0BY~{v8fD*$VP|*Px=Tw1O3xk^3j%%&gsx?rnQwMf%C=VI-J^}R3Ol*h$- z*X-Lci7Oaa`_2+`^22mr)cJAs8R^$1?f|Ceg1-S&3iK$ zpK&kKJ?UK)Nr0P0XHEtdT4!VK8sQ4}bv2;JciGyn6VDW(_styhSm*S263pl;ABg6mHIDW4Z>$mJ|1b5IJ<)%TR3SKFJAZSnO9*)JPT{Mo-L!i8p;5~}ycgIgXE{$x}h zuO2=g{@4Bd!?&epdzjKcf1fa|=Fc=?-=8o({0qSUiIuZK@;|pwRR?1ay1ZWu%=7dG z;%8Tr6Zo(BfQz4|RPrPyXUyMJ!NWq^gq;6}sC4%-Q3|3XmUCxKwuY@{r|qV z@DKH1Ykg_vpM>yR`2U^^%b4#xYwxorQPcNxJC_6_AKHuto_F{X}J0-h4ZT`K)h`DzolPdmQ1bvwu z^IXiU;ojP@^-+8O%JH#ydMZlu?fqT*qe-4_*!1PwK^l=a%8Hc=tM=Rbvi5VC*sXNc z(KoMHLfxyMP3ZB2(;GJ04P6rzF0B&f4D!G1mcP4td|CbBZvCR}*3cLK6&pG&xM226 zv{`tLB<>G&ky9x8>x2`~x!hJoPuR{=ZF8B6U@_Bjl?v9q)i=&G7vG913i7#rhWYp( zEwVE=C7n;~@V0-Lg>@hASY86!o9^PA7VmS3z%70Jdg2j7*8JNp7Pl)`zZf3g?|3${ z)}wH4c;Nqy`=BJ*X8ETh& zxZL`9dr6BMNw~tpW zm&)&Ka33`x-Mh6?BM^8?FI`4SJiizRM?VD5PzTI)c_}?KW{~03x{~e+=DB@w%>EC6K zmJ(x+6|K1NwW z&YWAe!|~mtqvTiTsz$CfelT&dU5n1PPY=lgEK~C}zzM1w=iBQ>-(8nTia9hSfcnp2x^P?A71%n%EKNY}RDJ zeHmGoXJVwBrkm8W{YNzX1L<$F>{|pd)IFGBL1x3cJ%vRH@#j5?b)TdAO#}*Yt_)Df z-3Kzq+!~x}XiM+wf3{SyT$VU*&V*r84zTb}fq(6i*R7m9LtSkIY1+HKCh-jY+kDa$ z;HP)G#6Jo5aGGnH@Stwlc11?838XS-9R^T|&P;2t$#+D4yU(n?2@0= zBlSnqx9T@@dPA&Rrq68m?Cq)g{oZ+OnHbO=i@E^=c>br8DeQJ0`?^Y{qK=xVdOF_< zK>)VT;5$#V`eXWsU}K+*16DEm&#r6&XL^q{r`;UiXiaCQp9oqDyB$N$=Y$c_-~AR-Op`1L$c@)uZfZ&&|PZ zdk+}8GEl;Ko(Kvll}FV*pghnGv81wNQa;0<7ja=(g>i>2%9;-zc(T)bI>(1E zZojv%v*^KB#pB~ZeE0XJbeHeG_#1d8z18(aAgjo2IY(&;o)SQdjV_h%&FNqg&A|R< z+EUFuEh)zeUVR0Hg>pbsFMPJvL|Fua0)hPcno;uS%k`I%I;wsTpW6+W?vOq|yLZl) zh-L@s9@N8YLtk%qAKe*Ka>r(mGG&K-SjD6Zjl1IX?l%f10)~0raK*|2wbwNF89(D= zj@TWUKkuQPRTMO|dFk0@XxmYoW0c9Yc^qG>G;fqIJ~pCWF~iY$Q#ano^WCH7R}Hp%=(sADGhj-EaG-7gv)txh;FnZkQ4DdawG{oXOs9tRhZ3V2NgvS4|+A z&5ntEJG2j}*mq6&+Suv0=x&?!_ZR%l@(pHn1_~y~I6g~NQgUx%uSm`#pA$1d1tUP~udBx>U zfJi6kU(fb8SdXmbq!nlR&VF|UZ}*lI`|uDU`K_guRf@~~ztV?yn%weT6S0Lw_=1|^ zD`V%G?sabR;*3!vR{*DEJIigT@1dt#pK{f&@8^FMIxLyEOqmXfir0?LOnqM{ZaIL- zY%wKQ(?NBhnz8ufV!LI$>l;1YEDn6kcU(NRS$2UMGiu`$c*%*|fIzuGow2(dumsOv zoB>GLJWbu;aYN_5#Szp4kGlmLFV=Rg>p8yxV1g~BT%`6`vFgWm>cWCy0RA55Dz7)J zGgWC}_fWO8i>P6V)f4Dx{DnvtmMvMRjzBA6E$Jjd}ny;=q`Q+bT zfJw>mGgkIu?6GiAHoWaktBRlJ;MuDBW&0X``+fWSgMgI#>WJX3^^a#W z0NplAVA=CNYewpeRlkS()R=nROm7QrXy!!nS`4tuU zYFp{%)RBP?-==)dckH^he^np1RCIUB&D7RK9KoxykzbvOJ@;SU*f%{_-S?%g7sGaU zTre8FCWXhE*!X?_NyhPCe_5ygvKiDw&OJOaf6AoOy-Vfg-r@Q=AqzsL`un<#Yg{*f z`IWMHXUjZ$#=X{DZGLoq$Zp|S=oeXz%r5N^331>e^dWu9D7E&bf4(WG_$JUii2p z)hq`y+0u4Q0HY3g+!n+UC##^L-po!w*bX#wd?UZ&-`Jp0zQ<6bqKy;x`T)>EFxL67bc9-+TjQc+$_O+rOlWt7e zQSb}B(JFV$w1qFG9^8B9IH)eds(m+p@bh#7g z>#TAU@%;MI)upO-a-W=f&U!@ut$R)IyS=v-6((i%d-sIrI5o_)FvUgFSO7a7Mtk8`fBnX}%A*^%;5 z+W37&UstNp{0bhrD)Vyi^)6uaqU~uhwY%&G%n_+S-_E#jy}?Eq+`1ApTWq9{^87EM zZMMEK4ncPa^9oz+JF)UYnFaGS>u$@`0;SJZpQhdGq6%`K z5OHI@g}qIK_1Arw6BbPQ>r2D9nAq=Yd#*vxQx2@+jJpGZ;VXqQ9HsE;f%qWTDL!3` zyBe~cz3%KvANkrArykXmS=9u39Yj{6higAL=(g<~y}`%VcLAoiO=$US#_FN-?PL3{ zqE2jGVvxIBeOtZpa>kqm;geW)KGWli+=|r)9XF^-RO^nU$zsQkNr!@N2HU2Ne9Bda z^EZ0$Jhz}ceeue(1S7z8%}TOaXqA8G#{AX3?yqNGWxH=k{vCIIUGJti%f=giOEbKu zvf`c2=1t>#Xz!foY*C+XW;-Wu%t{V9up_;EfwP78DDxoi@zbnNTbiokmlZUZ&9dPA z?a00dUD810XkW!}-?f(9$U7r$!|PTd1;ISI%k(+j<;=sg14n+oAucH{C0#9ZE-S%N z9*phlwX@Ya&0N+q+tfM{Ih=L**C*?)`mLYbrlw)@4)hoCXmaJsbXrH<=uebUS!K!z)#I2*Q%9=_RYf>%Nw!7ty8)Kh^y-VD7*L|#C z7dN%U+%toEs6TC1=fwV2U321%zYbROYtmZJkPy9*y(>2w+G8cvmbE8?++u&-%C)*M zr~AvIRea0zqZU>CS=PD&sYjmqo)%0r-S*j3C)>QmGK9Nh@i;TR%SvC5t9J+9Hf~*> zY2(-xbKhlsXa7s-0{gHg0EpC>Ed#H3#qnv}y9>ULeZEuhrYqlZI?ue4gX+DGE5O~E z_&)RPYEwVf%2^E?4+(-i%F@2fzbSxK6_4szo@KqS)chMQr})sVBfXWGd){k6qt33Q zh5f1b1c7tOb}rWDh>z31q`mWy&ifsI=r#&=@h-inu4IRIWyOj5V6ACM;q$r z3(Regqpt|MQb_#!Oa^En|ljVZJ z3vf{~HjFh*eIFk3z&Z*SovC^O3bfWFF)=+?r8DAypn^EHJ*JHGn%S1>knBkva_tu%s#Z9>on`P&wfEl z?>1&7U;Uz-ieo zH>I`L#i5NA*S*M~8nNeP?89JC?hGy?J27*U(xl31e8!qjGCFT#`h#kj3o@{1l6#9c z)_tN=n|7Py;w%>q1iR1*9)54_$f=Fq6HVnz&n7eDRAb2|cK}w0RK>ewt>j|;vuR^E z4_6c~3I5>zKCN^!Z6@-o_;AQfx1Vm))~1}_7JR(MqToRO;?j@iPEH@^bqyr%Q(X&j zc~)_re{w(2Bvx_SatSCBPl$+=H(I2?Q*}AVw5z4&vuPqua zD>>nh5{F}07&+K2d##v!4x$`Vj2YgQK zn=|9BRVz4DVQkuowCoUVW<%>TT62Wa{|u)1NSYz|(~W6qqc+5CD!HR56IR!Kacaw| zhp*hMzME-ZQ&YQPVEh-`7aNR~tZkb+_7$!0=_nHy*AQacl-t|zj%ycH0nav};JMMk z+tnHL7}5648TUzNc<4QP_{g#asL`&jiyH);!St`^Ej*rCy|o&~wto;-H@dkgiza;J zV+5J~*dIlahGdNP0m<{4CeHSJ$Hv3YiOXUa!xp?W%dgFCQtU~NxDdLap~RdKU?JV% zl3p;+XKi7_y0H*NEk=Gx$i|YDdnu~woVeF_+D&8dTMoz=b*af`FUOSq21yMouk5S zv90aMM;)`)e-Ldv3UhS^;m$K^P{~2}RhEH{s~l^lx$UjX&3}7*;@kb~9D${L6NizK zu`kWOZ0GX1ANM$b+VZoVhW(~qijNGN*&zjE+NEnQ1w%auUSYl>B*ki5(l*}8ji`b5 zr9%$OOVkD@dhvO6FCq_wKehF_>Gd%Gjh;z|KR&uVR1>Cr*ekuTqAFWoEt$9~{nBAt zky}aO73Uk{Hw4bxCXATV{VM~%tE>4;F*{=d+O&D zXb8BsX%l9(UOn$INRVIpq3no`I)<@En|&mX3j;B(?TtpSWw`MQVS+r-rQF)c2)MJ+*Re` z$#XZChx?aU2W^v{fL^Iku$f`c{U->q2K~=qAkwV4pXJJEfkMusE6C_(wE^)baJyH zSz!5V%aPc>DIibOq9&(tDe24J<|N1GzGO}c<``*#=z*Q!{a`cushl{gprFm#v^53a zI1=`Sf#Yj+Z?-I{?V3E7Qo?g~+G)({`^1^FQvUwum9wJ3)%MqD6J5qy94V}ux^6mD zT3t-_`U0~}v7oLN2fPUnqT747%R>UaBgxcJwEr+ zh||uj4Z(Hpo_8Vgv~eEvN6yvWqxzS$G$7{A~V z8sn_`l4qAL^JoJF{K!fYRNM19@Z7?BS;(fVzHTLOuQw~^^rY`4j_F}TInR4TIe zN;^Gc#~8tt>yOeK2FH0g5lqt@&L)K>GX9Whp?i};e+9~3K=h5?J2?SSLoR_HduM*} zavJ&o1iIADDXQQiUe+-#)aKk0lj@Yf`@^Ek^OEx%02u+>f@$&&d+9)54NEsWf4*4j zF4TRvw|6;64Pg;Qx11~{<4g*}-%H0xy#7=V^7?w~kDE2D8yOy4n#xu;8_jDP7A?}e zr}P8r^h3Vmp5XCzo3*GAQ3cei&o z2Oe403_3HHZ=N1FwR>ur>gUt&6z?y@KWwz&es5Rbm~mxGOXX)l3ss+dJ0P(0xK_t# zd;eOP^p_yTt*6-g0{ldP2R*=a)Va?hm+z(iZK);b5;O}Ts0Fmq-7s_eOt8wrxck=| z`)BV_X5>5iExjCIVG(ChBmQD)(i=aUrUlgKaZ@vviOd9Lg|*IBoLMsm_tj6zFz?97 zGSkFB$0+Xue(ED}^YqWk_F%wibv9fzYieT$ecoQ@W^U4$j=%W*4)^f1!v4{fi?q`ncmFQcJXmuFSMBB2@H7Unp#7jX zx59S1q59C48Jau(XF*m^L<>%c2+nz%8HLly>rSp?KdX zz@rA`wgNB${M#7%;g+L|Yu@qIen9=@DhQ_920Y`1y483tpBafWPTafxv%%$K=n` zoxirG^aQ4C{+jxy95-a=8-1~%XsU^+T@+k%m+5J>-rls;?qvJuf%qh1hSuKr_Tb-zgzGb52{iE$vvaa^T%g(NVLe zU~b;%#>%WB)Yk^DR~gp!GUr)aV4sleGtuv24DHqzRO0fwx#vg+fco6h3f-CVrI4J!_CfG%8E(-!{FlKI&{?Yn zt!&C>dBquFRh#9>>bRC-9&X<5Sn@u&wa}Hhx{dbfMg#bY5Lm+7*^&^)x7TuxPMUoz zOg#CK`-y0eJWmVGx^cDXX3eIUa=rc&)Pt`5W9F};U*-G#$IRiU<|6&9-rwCV?jCRI z(6nA(cdNZ}u=|2+!j>($e^kg@-#6GlmAuZ>vC_UIq5}L6A!dSJh)wRw?(z>W4>~?O zIL;%_(KPafhcmWMcKBO;V)@4^)|;CjI&<Ft>^KpRR==GhY%d%I!UnXdlX0HbfddKYjSwya9}}2Ez7NhNE5sQ*#Ii z?+>cY!Xi#Vtb<{1PR2E6B54!Y&cnwXyfcn1?kG0SG2ik5u122fPUy&2{p!FuBNC}e ziHmxxNxs8mcaqw<^40=g(+H|Z*Jbk0c`S0uKFrKrWcMGvuZ35 z+~+rb&)jnYebj;eV*Q*TR>z>vG0D!qzZ<^|CY#?HeGKX}Vgck}-8?%C665mi_MXt+ zCu}@#BoyZMWCWQ7jwiJOuhd(Czp8n=`0fVQ z1f_DmU*-eMD@0L9@SIt>b$RsM2Sg8775sB*9)w5%pohB*Q=p4(0m4Z#`mMl8{s#Q? z@1x-x-i&f@R$)x^YVTWb7+)aLt>nYzKyWu6y^uR;7_R8PzBJjdje3vB<@#NITRpxK z@bG##BGs9Xm&hF`66{j@a`iyZ$YOq+VC|=Bg6e;9)BifvMNqg{El(APY&->$pK-XR%CN4Adj=;)K@S`NXB+s~gtFX-1eO-TwnPsP|cgbW% z(l#;`bpmY<|9Q^rRMoi%(2>d7YDz3ge&*PFxccA<1|vD#C`dl%vxD8wLJd~(r~%Y= zh|DNpet3}cQr8A7=LiT2F8DBDxL}m#4~3433KNN$j=qzHMA4Z9^01rKDDOz}S*Y~b z1fkC80y>4WKBc$u)emDv%D(#nr=%pdw$`_C3}X>_MHtM2WPd*S1LXV>!H`*(ejHg8 zDf5tmCF)VDNaQD+5zg_-%ItR*)iH`^l@WiogH_o$#-lmR<@c2)$~AYcTp^3w*>V~H z(XXKI^X0q$V(h~zCg>`2nnk%f#&^b^Ws;M?d8NMwaoX8~#&?k;HNZB;$rUpR(uKOe zPQ+u3xd1r!AAJ;jMk&hX?uqxDpY%;KyzJ`EBvBs_FQJ&sYt<7B{ag2Tfcgq>*5}{q zu?Ao`bFm#z#X7qoSyT27yBNB36JdB1zRFpF`SoA2kkZqGv?M1b7s$+H`aY^biW)!o zoR2TH+iAsswg>U*eh?E`AU?A9&5h|Mi=Y-RePx7-e8#D>W$XbYnn|vB+vfCiYRRraTP_R2*8aW%J_kmhdnbm42mX5+<{w!cEUWfxFaO$=)&sk?d2EhWVmZ zUk&d9+91nL1S-yeoT)EEgn}gBq1WYF2}%qqZQ{awD}X1**}9jS-%_?J5XRbl)F|dl zjDNG@iL|DlD^P-^1|xu zU1V9q6?ymEK9Sl=mV9&X(UR#&E+E9KFrw3ghdC@)9?Q_9E%e{*UHgJ4uZ~b&rW|J{ z>%`Y~j+4(0l8u#@=SMy&YWWVOynO(j#Z7}Z0Uw+^GTHm$b>~y*1P8}DEQ~X}S_Pth zTi1KFW_-yyo$Pn-$?u9(0W$UJ7s*O0%M2?{6 z%DV|&ZQN(*vksdoi=8RN3|bCc{qO^V325CgcFX+rV8I2rS zWv;)u;W+Zn>C^h3tzVHDSsyRoJ-ME-5wM7@TJmFX%>14@5gpAT9BPm7yXc6UbiUFj zfd23Tfl4@|@ozci5be=0mt_U0SKLGyea%|yQwA6%x7)q<yeXtjD1c_haOism@}A z@TMFiNS$+Z3mJS4vy#+XmF)1q%x+Z1L=p3nPF|&w!8CFg3obs7Pj-khmVc6UI@jp`qml4*sPVE zJ`Jtmo7C=!mZ>J=PEuX$;5u%n%pk*$yQGnW1J2mD^&P@1Cl3nS|Ij|gXT~$f@lnDP zkN4H{e>!7(u`grOd`9H`H$P(!SZ&t%P5e3PSSYk{WuUcY(fDezz=rvqDA*!sLken^ z1FM^+=3}UU)3X@kI4=sOVLnnkp28$WV=Tn{yD*Jv{A#T_Iq4~fG5QJgOplXt7NYwy zBsb#S#Uo$uA%##8Icr82qgB}?zcq@!m8cR`H*;NyD_{~_w5V=u{MGM}c+sKvJSeQs zN~vo$F#Hfn@mhm+bmT(I)){>h*FEOL(!T2X7L7H&%>B%cM|sT+ye~EX%q#mPe)66d z=l8r)M7Am!2;|nEc^j*%>s7k-bqROp72i)^xbJEAwad$CXxgzZ&?)|bkKN+4Yd(nr ztA6VJ&6NYsar0a?gRP;Q5jH!#Uz{y^AztFH;FDpf&V`6xQrUuoWbIDZs;d`_~?}@`h2*uRhJxQ zQcm&5rbix#kq*|)mEj0^R|jnwv=Ad=L zPP+%9)id#_r%1;Yf)<<^rxH4Jv(oMclTB|!3lN!Bg|PlE(#dQuSRcQV=Gbp!%>P*buw|WNe zskPYkrNoHSy64@Iz=ukMS?qNM`)to#zl!>~Ar#R(*Rb))#?Vd`uZ+1zX|gF>m|<8X z-|JBI=X~mh|KdlV4#R?c>nNRzw>rlL?t6dizvcUsp8M8`9frCw4<%|eRhV#gm0g%( zhY(BrzX-7yG%-S@k?Rwa@A>QIes{Q^AVlj1AX;0K(-ow+6?SN??APSr~By@36i{SB{Z339}y;}Xbijy1Rjz?%g^k6FQ_#E0HFTM z9B5CeWtXkhf!O88f%DsXrbOXtmWHK6XVYd+!wBK9aQQ`~UD8BB>ilU~`}x#|Qj6OI ztF{6?f~cYf5ogZw8L{uet#zIL-|5+2zd1A`Vm-1LBHFY%Gk=A>)5nq0vaforEp_h~ z_+e~;m@EK$%xV>wRR(omJm2r#S;t6AH@y5b)s1=Jm|ogpsSVZ^&-4~2ZfUE%30eO3`Ou|r zV*{!jj`vJ6qytYFoguq@u%ZuNL}+3gfY~?#nLbJNX##47`eH)_a88eTw1jUt!XVz! z#qAkXb9MBCc!AL4P?g>Jihuzt?1TLK=zG4@gyTkrkTy_a05Ox8ycGfHt0U0KW=8>F z6YYfYoMizhp0JbAIgts!h-I^k6bkW3xP>}*I#To-t`XlXb-JMY4d?>iozn>S3t-vMn%wSz<#$ZcC#Q8T1pPw<__i9C*2G5Tks>yZ^ zi%UHj5R%k}b!dIp0RZ zR-IHlUh_Z9)neh5Z-thp+X-6lW8AAImHqKawL)zxq zFwuBrl+Kh+$rZ6$;iJYC{1BB~Q^2}rfYq=6P*AUlggyRl$&s69?k1<%$-7Y{1Qy(f zCQ624VSlVw*@^lJ`+b`r1}$mVL+8B}1<`aB0#Vr00%_)I>Zbs(Nl=UtC@28lhYxfj zJ_FS*^H9^(EEo4t>JaeKR&rXeL0E`%XFzv_750aAtRUh5r(sqa;Z-*BT}X2%2o z4YdP8jcFKOjBpkY0k3Da*+?+BeI#skBydSKUIk^>B)`A9 zKQ&zj9VwYzZl}D!5;+jzONrSg10+&o1XdEWajN?S`X0Sxs5~ag zpd`n+Rw^p_JHFHl;HIk+XrWauI=b;gv-kfp4_@`xUF|j7Kbgub`8)i>=VXF|ZaB4o zHDw}EpC=pP+ap{`Qha1*teX#K#GkE(ROaD0E|emYSz??17D@8OgCbKu<%I#N96$$A zy6@*oZ=I17LO-53)X6z4%TE0WXDqg8L{Y$WKJ%!BrqcE;Th^Z#x&pTn;CNM0$HymL z7yG>%8Z-VqG+OUDt=-P|1DD_n5X{^`r?g;n8cbp;scVVLUUMHCF5fwRFAxFx;3VCU z8l%HbAuc=PLP43#7zX$?UB2K)(gZSWhsvlJMxJIc`DvT)sCNbQVv1d-e@~_8-oshW zew>luS3$&WQ~6*T&ta%@mG$;mmKrI`*j3}+xKe@+o;tl-zcwGV>}QCdn~uEg??~iv z_#-Y(Md?T&trP20irjDzSq~e6D+iAVFhlH&Qj<{KQjSt$?~HJr8l5)xKrqB$l7W;2 zvv4*s8^W*8($arJjDcn*R13>|PS{y>(#-2qeu9}q5`}B%fQBATp6|~#nYA=Cxy8rH zSxmzziWZ@9ckVqI;tU^Gbe7d&ii4rRfU9^;@Km-BvpfV*!% za$setS)a;;DT<>nJGJf#0_cBGF!8}*ATd;U0F)F{)P>X#D?mCXZDBm_M`ev`|Li${ zXxBT>Hc8L^VZ*78LwT?A(lC_-x_LA)ngYM~$PG8F8;K_Rhaa(Z53x15T^lbf@vG=l zfaJR5G@ZS$?9OWhE=%;vmFq64lPwXp9ir4Nl! ztXcyojA=m(MS_YCJ)(Y192u)8bDSC$!U-`nvs`DgegXiT&&^BoKwA$$@<4|Tj^I`j z z2mfqRI^H+L4@!wR%@_Gcf5zZn;}#$p-i%k*q22A;Bt?9o&CmXoO!rPQ*?elKD9mH3 zx@R(NSA!HhRW_#vYC6`C*TiBPMk2offnyHfpqtu{cFGluE!uZ+$@;EgeUj(#D|BZ+ zWebM;HL33i(&Xxlw>s(3PeTX%Q8*=Qx(QWOQKsm41bA9pd?exd1cHp85uq=powx0- zA-e_o{*S9)8@cO`?>xAHfUMJgbT1g9#Azm-nK=gW*BVba7`L^tdKm)#35Me{X{w@# z?xN8taL~Q3HO1=t0ZK`F(`;>dcb&P9)hAadOewnipp)TIot%DN+(cqCj{RrEuQc+sR+Us-DLJu_RdA#t_WMvSex zpX!{s3TmUGD-Wv@(jHq@+aPR-~0PGST{a&{n`k}j%cf8y-3i2mnbi^Lieno zgr1mVM6e-AItv`S)VcnI(}VW4)`r*7li*->(M;g`OVI1g%s*Z|Y4+au%5z8dUhiI^ zq42+ssHmAI3n6|W&6drV&LIIJuK(_(&RB)h&l|xN+B=-5a-2QBqXQ79L!S#io!zpUt@i4>(v2#G!fEVQ1LX_d}I zdqFcTGz|6U7i0CN_s1Nv%eAD$O@!igldTgktRtonZL`L|j6L5WK>F|G^;JYv03+5Z zP-{;L0(ZSm4hAk@D|Q(X9c+L(%T-+SeDlmOR629O>lWG&G-yUdKv*exsIIJ>x8kYf zy@w9&>z-kBqnf({K2OS62^lPaexWzjF`RbH2-?{HVt(Y|L!^W>yf#?pp>Cdw;PMAz zex3gVLseufHVl?mm6b@She6-zsn^7hdN2_e;1-2Q->{tHk>eL@uPg)3EL{;Wy1e`P zA02@*i`^OL;9AJ)Lw4kOj#^^+O*9^m>I=;KOu(cIQ7VVJv6ziV5ms(3@^xRj!oH&$ zeck!}q_Cwvav%~1Y@FmEh$qmEJxm^NgyC2*XcT{92s^by2u#RdJw@`wRQTH>6ON7_LTaD7?TGB{!*EM$f@Olxf{O14^(L2K{aKL#6Y)J0O!_f^E@)t0s z@`pzI!OY0RhE#@SHftKjtB6S&9e?lrtoxrU3ArbbNcGJ%q;wQ*WGfZ-b|mgNu-eJw?=qJEQ%&+}(-pQ8VHD$)>P+(^V zP)CtLYC|^ICXaanVCMlu0A-6y+bU6zCg?1r6l0Fo$Y;}F{`XS5Mrb!F%Bz} zb2USn*MEM!S!`HrnlTK8trK)Q0&T+kY|5Ouxr_t?((gDlRN3pjO@_+oLzMsw!(E>7 zF3)}Z(6#X+;?Ma%;2-n{=3EA=fJAeJjRhFFv9%V&DY&1++4YdSuCI%|)P(Ta^H`zV zFmcDBsaByt`Y57Fo_bcLgCyBHI^W-~OnzMDJD}*`OE3LO6njJE!u(oZ-={G|jnrLupO&pa ze-2!rzRoWR7M?14%%0&y&I!ZMBXPYcBG-*e@XBvlJ1L`;4}+*`Safs9LJfh-UE-Xn zmjH<5Ew@A%8DNYe%8u#e{@nz#zC*q}`z3E;1jcl3li|g_8J5?mrL>N%#M*@$k4I7b zMDyf8`E`SfP0j>F5Z2bm^VXIRJ<)vkV-94a9K2ce5z)NG zQ7~Xjwk2+d)>hM#2*56W^6H$r#Omf_uR+Dc+b}O5CW2?8{U*v4i*ws*9isR^e|UR! z;56&eXsh{kY^2EGsvRHVzjAD^=?Z9yJp34NSY%M)|E#s1!o{mbgBL9Q;5cPSF4Hnn z4|9@11>lM!XGi{~f4d5`cr)VvBAjFL-%)n)N zSbmN9s&678{oK&~@(%9-AmPty(Q%V_NC#_)m^YMd#gTr%6{|FBG~c^QDG?EU;Tacc zfEja9<1*P6G3JSOs4Q7W65ABbf1lW9*>JpKUHql5(#GgOmG6gI*!tSHU63fJ=zfbA zO$M*Evg7x1I|5saZgL#wbaS+m|Fzc#HBW0N71X6!q+9zV{uKTyD*d9X7hZDgWVPpe z=?!cQ!+CmRnsFnf`!S#2nl_@e;QXyK8`qx2+^&;%D!vxPBX*DINzCCMS~`KwpDE}m z1_??X;K}8)D4MJ`#akzXtBN|ck)86glctkWMhxd)of!n8pR2~WGgS6cz8S3-Bi9&v zJcf;01@X~R@#?&GSQ9Y+$kH1E@fniS&c|s6!*wkp2 zdtt{;F)_$%l_7-=#nAn9`H+WzENW;~<`=V%1Luaa_uWTlw#RFVp-Pt|N6@kQ_AlCn zYKcb!U6nCXw|{gN5b|US(Wj{iF{n0CKYCm;l@Hp@(Rf9ZK@t5FVJhVKj5OOnpq@6! zjw>3oxn8UK>#JTc_50hZUT%$fx9nsVo|LlMNs4h)iThJiVud+KKYhW9??!Fh;Gus0 zzC?2H7nlGwcnO5hy%-nP9+VH5wh=v#)2?n`hrYb>0_K3-5&Qz7@cLj>b9FAxhh}Pd z>?tp9`Oe{N#bbim(ye>OBYU_YS`q>n{nRo0lNlmT8$`P&iLGMZJ~^=ZTm~!4g5>ee z=cJ0m!edcT$~~kp09?8UN3cIcTziBgWJ}o=bH-A1y@rT+!88c!Qst%`JW0}sOcg)A zswvTsvwQ(Go0-p3S--1TLkMi)k=oga$vGdyA`;8Y`Buc2<^?Jn^G6m4_?Ke;#I4!>Y1l^${G*Lf?W!9L@ zm>kWK4m>U+R!opiKH}w+ZY+0Yh=%Z4DJf6k3bCdbNT*FoCkH*fcS`LChPIOoL@~PP z_3HC@fWSJLP^JOdeEfyS80@91nx^*D1>#2Bz)oxg8KTcK8?ad$j%N~z4J{WtW6PdX z5sjN5BQ3d}MbDMaC+YTMsWl1Bo@2^!%&k}$~HkGl5sjzKJorby$$EFng_wWds_`nhN@JTxU-~@K3Y`AM> z+oX%5M=G#A7$}2#^(c;pq+6!T?!e4>MPPQ+2f4|9g>Cmw1D_{uQG^in8|w0u*n~Vl z)XR7!#B_BhI2Ik$Z#JfLqd|T_&oaK4jySAC;FvzlaOM|aBmU6Lc^W2&FR2ew7f5@a zx+3}$>TCTgq467dhMuy7q3ffa7@73eWV#=+DU!Hk`bD0CrLZfH`$l4fF_%8YZ)EZC zXC5+sXEw!WT)L@nis8K8-f#&~mTV&38M7;&t7Dv>pkImGDG)ot7nl4hPHH@Wh>M|x5~c66+}gnFth2b zy3P*!8@)N7uxg>24{)I)=hcHF*kta5yDN7?RHYK&a2MNC=|xo)Da}ldGsRCy&6Y1~ zV?U5bXjet7#W`AeYKd2k5vA!gw6{J|(ZcJb5j}1k3pdozlPAO1-Mg2MLUKb4NKZTv z85MW496yD^dFa9H`tW@N#G;0&iK!=OsV)=++5{X{LWZ z%hFEsq;q^PaE?^Y^%lMAYQ3!7GiE2r1sI4+W|=d&J4fT&qf0MSPjY@P))fpwcEcbv zdL2p`qvc`cc@q&w`W86y|vn=FcN8pxEA!#bPG$Ubxx1cphCEfvUC}kxMnl#6}Lz;lew?vhs{nV!Uva zlFo-Jr@1}WM~}u{&%6vUR@H@1PkfL@O8gs;C2D)r+n)=+UqE!S&p5xQnWP*Jqw{`t zMYsi%61ReQP^GrTXkE*XQ&rC;8wRf}e2!&~%#C_N#d4qaDUqTb$T<%_HSw6yvPK<# z^AHpU9CH9+(sSy`Ma88W#KdiPil$rwhDbwv52GvaMxW;vOUwJ{kHjX$)$AWcM4~Ec=tu=9qYm=DTqCzm&kE0PeeN8y1fL;R*|R~UmgS$Jz_Ks z&}u!lAmf>~F=e>uEyaM;(F_j{uz59f6#FYq^1?)CD#FwZc6$a#>Oy7$CX~NYcMl#n zCi0m+0Kt=1TK+1v_$2lhTNoiLFJh34tgbhRf|1pICW@7xIrlb?SWk29l;EMgN+oLg z=3j*op|xh`%K>9!20?z_Zh(bH7RSUMCeyMnA%q8i#4K|1Pps22uhw+5tk~CefI80y zoPOW>0)}B~haX5T$zR*R)=6dQbrpyH*1;;2berydK&pKK#_Sc1;>T1U} z9uCGtn+=YogSNjAj>yi-tV3QVjNMqp|2!e5 zEB%sNbQAdPHCZTGs){u@$3Zc-$G-i$Mr7oxZBE8>E8l0=<851sB2QiRcBz}LkcIVT z$?0kg-_d++xmW?p4`>-C9MixD4i#6J2-IAa%*9eiQ%u&qc)|4zicEii7nH&%KTvaS z!}uV(z+$~GQ3=J(L}o--A9@~^*TnLk~CVOHzc7TA%4;N{5^=mat{1ogr2XSJD z?-luZG7?K4tq=4K8D7Ty^2XQQW+gs}GwjzIVm|*Hz-}y&$j9xomn@W}zG%I)kJbOK z+pNs~HgHFNGx_4lQW}j})~S=hU^IMRAMg)Vk*Tc(Do5P9E8RabOcDCd2_`;OJN zZELmo;<~o@lM6oKIencIY-5d--yYjfLml>91QmwvrLrc3=d%V!x*yRg+SaHgPL#Kh%}scJSShA>eq`_vVwT4Ai{i5~YWZhEfu)!{OI zj}B*n+;mhgi7!P68~;A)tD)6hZCcTPxBzbh5CB7AO7bxsgLZ;ef?9(1lno;FosFUT zXomsG&CRTpn7DLW&RQ3+a-aIx-p$a@agmC816Ui%wUmlPo;~~J-gtQSm048*v=A&t z*|o)H#P6bj+Z?c{RAUG9oS?c)kBVxRjA{-#r=vW!{rR|Hzc`$>lfL1VcZD_*Ch54j z5NW#-+ibAQ;-B)B(yY?r3Jz30@Uh2ln0|f##Kv-|W$*MFoVg332JnW2HaJ#}S!I;b z<|Rq{7>;km|Qf1UcDo@wF8R;>$p|jwlqY5 zs7oEo7C8o@n3@gC`Cv6XX|3iqq~`B?3&HIm>rjpJv%n?SwhK%e!dP6uX4kU{5kB>9 z#)E^aSx47v?qvloiY%et2Q@C}9Fo;q{kDz)Mw7CJJ;NKKXb4|H+< zjVJQ%*Zt^dzM-l5A?S*kVl7cmrSi_ZbE-ClESH$gw}hp9pXGVSAByqtBRVMQ$kr@R zStg&aDZ!umET3_eoBxn*RbJoe$Bs6&!~qVwLzYIaJ+YgVB5LVwpUfW%`cY=%WoWxv zJyAT23wp@#HdDsl)y-I0?3+fXz5~ocP#xrMW9~ZP8WVW8oF}xE*#qB-VgX7oVb4q* zprzY(!0=0MJ<5618viI=o*6+3;kKyi^)=wpzY<41?-gYO>RE{2I*gsNJC;QFHsa6O z6+mxX#oQR}oKJb6D>0pCpBq&_P57jO9Bgcn&wDonxd&3hCS%a$4#d1H3%zCOgC ziE|axG5DI@jqQPKY?!49nr>e<%eG)0Ec+r+EBtsd30C$4AImq@*`H`LJ{IA3Kz@t# zi+9$3{aHxiU9}^@4X?WJtRs@@&=8)9dbpy7e?b&$*`wz8%$0|cuFF8m9U;&M_Dh&8>MKyKHwk^jVs~4Nx(kt(>n-5jB2g1)`Rb?qclSbFl%fm zbZA;y%{Q1AOXv+-4nMT>o-n-qJQ!;d$Tv}eigX&1eXC71ohm1`_DzP}@NV*We@sI9ZlSC~)0z~Kfnmqg}L2{ry#w?#kW{#IB z`e4X;xy6f9{@R+`XJw*uFmVzcnRcYbSSP-os`5NYK`|ojSqrDNf3iA&L{~4-ovP%- z+SPYws@r;7?>#ydzAi4M&R9;qTHo>JRZ3Wl9WGL?M!|QawIGr;HR$M^g@T2dtpr+k zw+VQC2busFUTdar{zz`Ftz0QqSz^HKj%TK44$F=ASLh|hH@%O{Tl*3P4Wg&8p1*1Y2UZe9XhM@L`hHq zjNf2j`B$}-$}G+WL1=K#`mnSLJe^Pe`k%Yvcg5op$SmI(`p3|j z+bI1Kq>^Bn(VTbBPh?DP8cnI5qHK)!>ijiWxUzeR4BmPt#`3Y(@8?Rtc>OR0gVD7F zwR-(PpC_3GqIL)es*fPaX@>>Pi5*+2UmRDL#4-MO8g z@V_&Ro9RJ%&GLQ|*;9pv%yDLRpcQdMdd@#!5^wh*Uys&kVF?VGUmXFrc*O5Z$$O}; zk^^ybs`D9u=|vCqIEV^rYHx2u)k%^1S1zT9=jCK_76E@qVA1<{Fg1EA%MB2s@p zz+PZ>Jw5Wbi6*{%r+=c}gY0&s&`#@&O-leJxK~oBPX^ZQ7SRhA0ItWxh>%~?li-H$ zHPLoDMRN*nPx=D>#NN zyw46De-av;_=%#8oRw5imdT9xwv%hl;3y^w3=)wk<(VqpG-rfV(&mY*_^=JajzLx& zbb4_9^8R)H{=X|OA5rayXVF}??3S+qdPx&@er)&YOEenk8XABCxaBVx}~5!sp!Fh25F z=RYo+cl`f3Axv&m$IvRHL4^*@m&)&)sGr_@Ya50Xjxh{eJy(cK9HAO_qTtq%8!=I0 zCwAF1a5c)`M8p5hc7HC4HFl7Sr`;t`fpYtA0u{njdQQh|MR!M#Ec@T7^Srx%=TpYu?u);PN&n+!hduH?#CONt$iVvHIlp_w$>q_q$=%=wlGF44xSm%g(zg<>Y#`=u9{^OdX=d+If{P)F zhpy8sS-r5J6#0vHn0I8)uT{6JdC8Y{JzPaJmHJd6X2CC~1A|zoTD*__t7_RP2%8m! zeyt$g&vwV;d|8Xcmq`D<4K^gnVSWwfuk2oT0(XKT1^c<`e*(cIvNXtD-y9i|IPOIk-;+Vddj@VpFg4f1XT~{+XR{S$6M0Q_Pw92g*BtcKK`4 z2^dQw{>an-c#q%cYW>eM_D_`kAO8$Q=gPEChjWU0%gY)p6tLEydlLShKM~PTYvsl` zh-CL4FNbvxTz1$6w;%pAl!XhdkR+4JY=4u=#mC(GyG`FmsFpLV;GH7{^gak;sNZF_s9)&2xVyA~@YSnfrl!O)%ncrgiR^soPL2|GSnDVr{$H)?f3-o7 zJmZiIilq4D-yw=}sz#56cD~Z;wt(mD-NTR8-PuYs|5jvWD&7{X-Q5V-PmRL@zXJCD z@BZ{Z^4I^kvj6=H`6uWZhTVGkzgU}uL2{R50+R`XZ)HHd?3{vfD8gcj`$p5ppif!7+XVZR&{*# z_iFBvclJm-fn7JUkD9u!II4E8lfKAFn_a6So$ls=*GRGfy4O%+i0)jN8=7jTb*@@(@4ckL*otRYw z$p)f}+hZs2U)#H9@4v1SK_U?UP6Q(SD*`RGs84s*BC`$HXjj(Y80O6|x#?g2(F| z%W0m$R;FD|74pq|C><614(h0(>w>+oQ8NE&x?xFnSX19Z*lY6<86!xn-b9UGJ@C4^ zW7gvozCJmR z;D}1+`!6A^C*(Q<^gR3*@4GhjWuT>A-qfB$ib1Ei3|%1XCQ%?G=L{>5?q8lRFKvdw zB!s7UhPvx@ah#c#pwaML#i3uvZq41j z08R+N6+uLB)*v_o1*&<_DWv#Fm$o&9mo0(V+J!<{nx^XK`hB>mu9h#d3+zaXeLp{~ zV3~$;<>>bI#)WgkjWq~n&aNFEYTxLaU(3o5Tq`l?nA}xwk{pq{vc7{EBBa$LiXN|J zU=i=br3*2s%=zP9{Iv9B3VJf(A>G=B(Xl+qcUqdgfnSYkbS{KTDSuo1;>~$wQ@8j* zON)fCGUC+f`6c(wWgKK zkf%wOpeuPe@7`_?Q6fl!H zlv8@-=CMP8vyvF?>d!4#epSFNRE9{YbPfu~*-tH}=$SCunQ~4QL%a&E(cq`5571Q8 zLiqfrmi>O??N%tNc199YwSs-E+Y+c^UnX$v1B^>6wfp-1?w8jjGDg5AAsxoA6&_HL z6%Tda)^172X|-Y_(PKpWtDN?M)1RN19MGYzL7|`rUJ?5){}{D3vYzh0YgQv{laurX zN68NVe0eA%{&X^MiVu|<4b5*#Dt~*mzk^0I{85r_%BixxiQ9OgA)5ega>eo1(eluK7ppPudA?8!c`1RQUDPl<7b1mMS+0MjW$mB6fJnkHtF zZubu69!Bjnl`eEVP|P2FqoYpZdK067KqjvH?Jw6)p;3u5)c2KoYa%`iN`5gpxESU-$T6ihkj|uZyE_MVjrTvh<__IJ*a6dx<;=p7bt|v8H%}!n zUqKdOkuhUPVJo-2bXrw}5NRC}vc-b2Z_j}&C8eyPoAYV+UE(NdG1VJq(pSFAiah*TIFP5(!iim8TU2Jy49~Y# zFZpy0f(1utetQyjHFbukuzL`b8m|rOO92>hezJIb0+*Qqi`bDHHr`#p784kKWaNd< zje(t8@gt<2X5vWeBIAS&zKs{ottiCJqhHF7mL}uR>K%-h&~3XpKp@fU8wDkY=4gf} zJK7QL2%8KTe&2L-uz)3SF;%!UDLxX_I>Pq=i z=$&A6Jk0zmz|e$S+NLb;H^l*c5}ttX?JRR7cd`eI14~b;k)3l+SZ!~|fBvM+Ezy0J zR0&;8pQf}Qt;N4kD%OY{2?FMQ++;HZ{QB&p65nAIL1rw7sAo?+}1t?vXnd# zT1*(BJq3dj$;@hx1$KAEt1!rOPg7*a&LX#2zE5H!;qkg=Vm{HDAcsGy>~b{aw&%>n{si@5h6co`Q9{W$0}ByxV&9ObzpYg!j6vd-jjn-Vjp*RVKo=g z`H5o^Aur5OvSah=zn!ZfY>Z%wWx4m{4-Tcq;WFpceFW14VX7?=%Sf%oM32qP!LE%q@wC=Gf| zqvRs}P?kV`wTt?_r4|=Dxi5TC{O!N*15pJlsT?HQe)}3E2?~1EG`#$&Dnr6MEzxv1 z=2i(!$|^svxXryzp%?izrDEgxaZ8g!I%iHR*|~};fjRJ$!2Oin-MAms7TUB&A!~&% zU%y5tg}sBOVX1Jy`F)Q%m}s|nIdkZIRR+S3}q}8a&31v4~Y(E$7z`cT~PGDg)i`!AFmLLuh@*@Z%=8#(x}o z`~9z@*IlFdI0tEV^YR=W`sbu4nr7~RZoF%hU~$&@k70F(HLY`E3=x@*Y*;k*JU!;Xu;)-bnh%RtE2Rt;9X zve5LVA$LJY5Jj3FY&p>y&V>&9b7Fh)I+c+qLO^>N;j;E07nMJIo6Qu$A-o9RecF3T z_dTa>y|2>#!RM9hSC6Q=k(wm6Jr*Wq^wA`cGn>}9b`*uI&Rak5vZr=m7;95>d5Uh6 z*dom$lX#m78xx>37i--*1()X)!JwCatUaFNJ=Zmih;NPy+)JQ%u2+mtE40zECEN+| z$VdDzeh(s{AF^ZZ`44iz0JjxK{MnXHpkU(x70Y#CkC^6a1lx=#x_5Q1%zexl5jRb@ zOyz?c2-D&2p-wPR?|Yw7&A4Ki_5HW63TmFX`1Q3cQhrsi zsskvu4E{Fw8_aPR)KpRMc6lnm)x~%1= zTAtL3A3B+}-=b}RmWda~r|5>Mu7K~mza?QzZk;Ju_7Dj2?i-`x#4<&WpWfZ+uSJlZ z&Sri84V^e_EI3<@8A2U2cg~F3&;95?j zikeh8Hcdd)ZR?5$1Pze`T0<)N_4w!4H`*e~&WE9Bw%vja?x?l3d{lfdQo)*PeCxk^ zb7-N^g2Y_?6{H}R#Bi7$ykWn9YI%7bGmk_{!>?n z$adQ7}Ld<$Jf7aO0{a85wC za7Qcy!$dw!X~aryp$uk&OKk4^e*TU@gI0&)=6sRKwTiPSuPM<4W{ffU1?3B2OY$tc zns5OJ*0=pBhpg{dD`h|tm5G2b3%)aG=5B)x7Le}xg!xvsRFW%IG`Gc8Ryz%U11Xs& z`GUR-ti*&DsVd^?2Zu!n66gQ=_C`vXSG?ovZY1V6*onk>{}G8t4PAC}XvFA&TxO)V zfRg4IJx}UeHWVsZ7?(ns`z#_gk>Vv+&F2@XRE~=zQY27g?mS{KzQJ3gpX5boRRBvN zd+>ZqNXC!SifKnTrb68xP=s1%BsWl?Xn#iwkU|LXhsrM zXTt*c_mq7tgaWaSQW?J%1c%)nF0b+IA*~UNiQj1X|H9kofiqqDEyMO$=&P*YsuF?G zW0xMa9(2`-rWrDNdSva=rL8ZqjQ{&{orUYI$i95+;r1hs>Qp0DZ6AW9Wgek94Ar28 z*cDj=`>?HqkNT$La4X@6O0wG6^owf}7Sj0?4Hhzvjh4Arrls26#X_a3d2y?_)QO)N zucK(9uj@QlF!q3Pc!-cgkKwNVz7i_baBQrEj*fy775v)C`GV zFr?>reKbR|EQFIw>1w!eGflsFw<-6TI;H zG(M}Xe#rnww0G_sXV4orrV!CpIW2ZRfZ~Sy_iB?-oy1=*abp zN~i=Vo;ZIV2>cpnQQ*sb)5#24!E?8tPYm3GT#@vWIlp3iJGXs~mb8a7UqZ#tMj#QG zl`kreF=D?#4lLtmA-NfY#8WImb(-)aWZ%H%7ZT;r(1s z;926!)L08vXcchbn`1k_V%Zi zh*Jjcc>ZAidn9jRYpQo5s?y^ZfbB#jdU|Pvse|T1^qN1?FyknV*y*Oa-_ywtc|=1M zsA;P3;lak4?3M4YG%ghG*70F)#$xG)!wD0K#)rRUjY_o)jXgbQ}83%NFI-`mqR7v>M- znUQ~)>{dA@J7)|3A7?9p`Pi#Rbwl+VA8l<) zf`easvcSi$f%a{eQQMVNpF-lF&~(t$8P^KzF1iET&Z5)($D_JN{gWHU9#9XblO-$! zrEJQ`h#U&x-QK31XT$n>?`>xo9wY3Nhn7~>d+5HEh#|ltVLsQnLM6uD99nqHlfZmN z;k5d0A;W^(DP%PMqma2!Sp9dkm<_u5Zm3n?XJk^*Fp-(~6g#2nD~3unvW#|kfDDlb zY!59EaEXDg0O$Mu2V{jw(D+>gig)=B(OODZJ#b>ONpJUmqbUKiD$e0Rv#UTlzMw}QUATS24$r?q}~`GU?Ry*Ig@KzTf%h`{(`r)^f?x z=eg&c_nc#nagA$S<3F8CaA(6*oyIF}MazlQJlM*D@^Cr8li6X><3XZD9o(r!VDjj> z@tZdky35QyXq#^fhPihEGahMmF%Y;a=Xe5-B#Qt4u(Yhss zZd-Z51PPIxCaW|7Q|1Cg5eF6N1gz&aeF8D@5@JZ>$KB>Th*T4}W08Oj9JU4CJmR;b z86Fm+g8!u}@-J)3EGCC3C$GZpMGxJY$tm2> zG%^h%FUpKrVv#?f|Lybl5&oyM{cmPlpD$!wr_qS3aq`8{q)O4@qx*f~Rm_=Es64n- z&g#?ZDg6$$+5h#+{yd$YeuENEU*G-5fTldG3l=HqG}>2cJ0MhZ>0!7yi-0z0|1tRZ zJ5tectrvDr_$QA@h^40!q^z0{XarsHKl$zdFQ3(Q`or8#&j=4>t(Z7Ien-qLCUJlI z*=@;oZ2dd6#TUbgic{T{2_=xg-v2LG-kOPG$)v}2EHzGK6tM`CQbzg$g# z3H`pU|6e})kNEua$>n+8=L3~uzqk6`vB>-+eJ4Sx+_iJB#%F8K-*5AOj5u$h|7r{& zt@58;3w=I_X?e89M3u^#J@kKsqT?Xw59z;d$v^#s|FFOR%g_GLcK!ol{O@eZ|DU&W zHIR48phmHk3Gni)bDnF25)eQG;`d7Sh=%WzN~pmpJo_c#|f9`ktdwzI8nK>DF8yHt}vjr2WNi0wMe|F>e&i+M#$__wNI+*1KiQN98!Wo^;dw*jpc1)@=5xZnG*JOiH zHhnu6hhAP)b{Hxz(>T5z=X22^8wdf>gbx}UzfV_cmoIhkOdok9FNaebtXWPa&)c5v z{Bl1Ub#@ppeEEK2k*JwzBh-v$XkS>;^Wa%RzR``^{dIm|4<(P$HSlvqWh7AFe$UL- zL3DrkIqc-T75B(8SRPH$zwAS>ciwB!l@O=(u>jIf9~I@=-fz{a?opur(W#wXeUEp@ z+JfYl!<=4K-jr&#lL!poHLj|Vl4#QcoA_bp~+?V># zyFLk{STiV!KR@Hcr7p&wr0B3nOAB zY9oTWmMwXBmh!Dcw8GABeZ+rAr3mdw(OzD6?B3UqQ7$?kP89W=e~hNLzx>O!_`kdf zc;ElF^@6R0EPr60*L__xg*$mnJ*X>xw#bzGyxwbES*5LOJ-OLB!MAK@m(OHt&0pGH z6KL#7Ejcz6WBQVfiAy=Wb~(GcEs9G0%cEDR8qb8y!V`E|m5CW*bM>S-)X(x>|47kW z&9ARZtW3g`cy4ekVWiHW`v=3r2N5k>>22uaVQAvL-WC6i!~60X??kDQkZphVl91nL z459n&CaTFY>ugr7EusV*4~w0I)+UWDKjP}!&OOJP`-!?yWM@f6aJ`k4+AP-0)sLOP zj$cP!ahlU3TRoaz$f?OKMa=Ru+uGvM^`DD2Mk1JZ#U#EYN}$n^&Dt5e3Uz5m1DNrD zH4Ne1+NsHE!5Xyh!-+y4bR`L=I!%;b{Ve`aU5wsDpsa`pKl|JY`Ytf2A8_6dGXfcSFd|TJKSM-BYzzp zfGGcNOBt!?mQIAkzn=}C3VcO2DejuQcr!^gF-xF}q>*1wTsu=ERl*eek)RGkqFiyv zY3q?{{p;O@5&}Qf`P-Tc-&ZPDZ@p`Ash|=4rLOv1I^XB>t-A*=<)7Vpq)$ z*Wyf$*RpJS;#9x3M^m2))4!>?d!+TCMb+GiaH#@rD%A|%PDSLVs{HF_hXMU%q2792 zc)0gH7Rp|`A+iQ&mviW~Cf#{}#n@BNi;a8ZJG;`iV^3Y5sVBDWcLfnigPP~e=Nc)T%Bn?Jw=jc z&;|XRa8m(Xms-qV-0&)F0wbXpL2<-6QMDhCf>Mn?J;L(^?b6>M2=qbs zV2I3AL49R}x(8-BOdZb9P$DjmTt03XaP?|EfhEqa7{HLWNwq+9%dZ?o zkB7Phq~n7|{nr}j5&gSx7r8KMf%JvJ40FghalRV$o5e3fk6?t_`OvGU{!TlSt`kmfDlI=<04y0;N!=SOuxwO+M**^tz zxk38QV}SbB6}Ho{cr@->7ElRQL-LjfJM?e`%Jb zSUp~$nPC3QES?a;z7k96frd9dz#B^_o&EJ0s65Q)(9NOXHW9G1^LLsvo@gOx7QD9} z0NGk!(XtXxyTlSHwFkQ@Jz{&hbj&vgaRD@`gBw)s`->I2cU$>{axSH6K zh2>oU_~2a8{m&s`*s}Ru0jP!(^ZZXW18i^5QukRop61=UZ2R+YCi{B5LHYOUjK!gL z^}q(%jLmm_hn`6^k<3fR&zSb?-uXvy zHmWu%87z8ry3P*6?_3qi3Csp(j(;9(t|)rY-nRMT4#vb+KtZC&%5yaL=F7{YS6O z*&vxmrl3R;o4k6>PtnQWZEJl$J~53==F~(hLz>SuBE}XSH z3!wav%}qNBh{42ktCl0dlpraXH@IL$!+9q;(8)KEXu~g$Ht)${>^S-E8N!QqMb?-|;IkT*{M#*R# zddCs29HksGVut=Wsa0PEHtl$+O{-ORf@u6D@2$R1K{h|a-^FqH{ZJ{rEJ+H)zOH=# z?8xO-aziER3Ad#MTH1qOXd@jp0-e1-oaGrtunX%mQvh^u2`zt3z1fj`LB#t$HD9_tdy^R zgBj1(;+_R7)XX~g2*QXgHn?fCJpyhrGV>tla~L6j_(|~o@dohOo(%nH53_2Wjm8dP zP#@>W2)atg%!MAMyU>+pYUXgFX4KYteRt(#k59_x+W1AB-l2g_W<9XZ6-fVT+z) zq4mn;9D~*ykC68$Zg%{@eP>fQf6GVn*Ls(o2hr=4AgjkIA`?jyNEEJ_u2!{O3-TQ5amT(p=Os9)s_4mC7CLK9@A1R}fkF>m<#&g=DasM|L2&jC;I$jVdxx5PH z5mS6CKB3=jV`{Xmrl>JX6Ep$ym{6QZPeJCP8t+Vtj2V|h#u^J=je(ABDmX!>$aQ|^ z-37~E=*+x*FC_I(s)1Ue2bFBQi5IPvm~NEMyz-==8wk3Je~riFSDB%?)z7KjUB7rv znM77EBdy2oJacSOS0jk(yykMR%BqGZoM*o?)K<)FpZ_NpK*&N7Rr-qDE9n? zYnt}XW}dt|fn(ddS(7ZJC7t%t-pnf|iSj$kdkh}Ci*Z=$*PcA7ej~ti%XRnjNaBYw zmyt`qtcFxRQ8Tw=e~K-?LV*YDNX`{uGM-d#Ui2xY00Bz&hfB_sCV~O1{xF(US_(z% zaET)pbbz^Gh0I2AinE{8_zSRmeg`HvCEtx}c!cS)77CVO6PiwfJv#tFtiBG-6_zPl znjbPxW_Q@m<|)UlHkhir59FR+r?-;&84BqknvE_7hOROP%K^t8a{~E#3s@6g?jevp zl+rUVt<-9--Tt|hfvJmYkT7;zG~QtSMu7>r9g^dtuzhGpj+-+xV&`so6W-NJb$=^` zZv%YFN*G$K0G|X;96~R?geL!E0^k}NnAcp8y7pAR9b0M;hg^P?-&`60EI)V9)5{lr zwiFliC5q?nFny7|QE}(#)fO&_F1oZCL0_XuG1p|vGr`>nSTi?R<8++_eS5|;!!RG5 zr1}Yx^@nJy#D1Vr#x(X}b2~ZoXr^|_u-b}j`iD>b4<}oKiRQqr>?B=DBr?S?Z_@S2 z+fcxW@L( zRup~U-2lE|p>cy!!HAIgaEoZldHvjL)ow<*++s#o5}o7Z-0)^=?Qlg8T5_}D8sf$P zSDb30zR3^>GG|8kke3IZs$h!$T6-|$^SA@h&7l`a_IqfWwc6_p2V&B0YHCZ*Nidn~ zCL6jGf|!LEyX6u=CRuWWUKB4z?i-mKax`4 z5Z(jx_~B(|ExUy_{QO-~z@;?Y>M@;NiZwXeZfDTPLW!X9Ts-(6YCzmUYWDz_q!RBd znY#$XjtD1F0wnEBG8WzwM%bh;#dEc2At#mFN4fsnQBPJDn|-DT$<-W4jUrV7K(%8U zQxt*M;b!~|=9{Sy?V;L~4nL3IHJh@aYR4Au6Y5j}IukYq3*CeusF!mH{pO8}0Ndar z(a)8An)6}@kx^8wh+!9E4*0;<^hQA8_r%S7R}xaP(qMD4&z5&#n+)!Pyb$*tbXEl* ztkqx>BI}Dr&J-4lEE(}1>8wA04G6`Q=PaKC<)xuwQ>k}ubAb``l6q4<6;EW<0br9I zHtIxXI)?EV?>0uRD~u@A0?|LL?I{PH%@>xkFs{ur=iWSlySJ(RH<1+?&>#Ph3R$&6 zuJ5{8FhWuUAy|oub1--NChO}_27&*>uHRF}>AoB?Avw686x43Y%AC67>52^#KpKEFPB44WvmSL_rUmEGYB& zqTI%H42Gjwz^QOY7TJuH;PLjcx}i>e!x*HhjQh(N$OR+OMwg)E>1Bh_AJOG|iqgvQ z(p!U!=Wo2tbDFNbzP&uS;Va_P;tJnztkfB9iEJ&}7=JI!0)rwR2z8$hTL2Yx0aB<* zP!)49LMEpA4<3cIJK@Lh(_^7+zeFgqK>9c(LWI2{(pszgn=cLlI`!!^5ERtm0NH-X zyrKuur@=+wax=LJ2#cu)wukaVPgY{_SG@TtX#TNzYSwNKn3=j?@$sGuIk z{pXUVY7BG0;H#gZL`VA@$|<$?SVaAmoH z9}o|;knS(_4>^EbJ9@A1BM)X3gyCi&p@lPoKe`22#c%dz;4nyCm3*w-xDF?3AVL&Y zcuKP=$qJ$ICk{nX#j-Qpg+N?W7{a7(Y(tyJ-LkYKku>K;q8^yu|(c z_(cTX(0DGQ8cf3U2f}OiP!q21oG3<<_YZV^$s>qv47`xcfsk(-%DdiZo@1p0s=@L4 z#`a?G5Qy#mf*L5SkJO|pr02Ilh*2G~zzGcbdO3Pls?ef$5!4A|!SJYpc=iI+cInG@ z-sy(jgw*onAV^J#xhyCMgxK^Xs9uEf{$Su_=*j$ApvVUoNbof~`{7O~5ebt_ga~6F zPL?u@v_-vzf+_U3+a-)D`AU%L?URLq#uPnI@F*~K$(Ve1VnMZ47YfO!^RMN{9m=p0 zMM&=hX|fymYb;P2r+4!GbESHbzTys)dx%WQgc2R3k}}D8^}u;!w`_T`4dmGK4+qjO zzZoU*!Tcx)!L32;IisHl=>=q%Zxk^VN-8Q^5Pfy+gF?M7sF=D=*M);kMnXnFI$z2k zd!Z1>(L*4KVBGkqJ{+U@oHJ;Pc@xL7LfO)_kJZ3Cjzt)y%n4MglG>gr6bg1gA#^P;JaX28gk*E0;m^!&nV#S<4cY&}H|A7>m)fusLU{)H^ zHG|*X0}_DT)vhy1K)J<+1GO9H=q!BG+g5 zBY!l^GPKl(g;K|asm`JDq>m${;b^$$L)%)DdhhE+ShyOpsN=iry67hlS?QQ1GJzqb z8AfQdMtT7z%?iBm7@O|6{3)~0;P%fUxWSd7xS=2u{RR~xkV!mx4GKaMW_3y}u5gIS z*&wBJP`s4>9%STh`+mh1IhJjcj<|n(u%&jbsWv1u*q$u{YyHZL2S7Yzs8_O=MhxFG z%_ak@Gp9{WOq@Ci#u$jJWZ@NZ!xgS*XC=vW3-V2;2U(x}H7R6%b>B4#0p5& z9lqGTFmevP44YPBAJ!(;f7)lATGCQA%((>HCT2Z|sOnIIS-{|JKc+WSEY<4!7kn!PYhj~7)#scjF`{?CM_9$ zs8drg_Qx}11TqXA9V8hItT)gsS8DjrS0A!@1!{s#Gj~Yo-d_&cMYBYw zyN7$tUU>DAd|i4Mw)Wc#>B>6+{ErmYVV+(26{QTu_Hp7xOHs5^4XLISj0s)-q1TZ>9gV2{(b^Yze$6 zrPJe|+5?&~h&3laAYDnaQV7*x53wY`__*lQWJi!OWK|Kw9SEj4#Lwy}>75rhLoEEY z?~@HhmEL=j#I}w0G4Km3UDlG5;1H7{NhtlnJz6r@sM0za+}870cPs!d-tH3~eB!FK zl`q-S&!%L=%!4sse}5yLoHmL{wzvbWj0HM4#fdr^B!*Z)Im~KksB(5`yP{-Y=r^cp z!!9!xJGfRw)R465kE+|rzkr%0b zLDYp4_=`T-@G4~?nIZ!-EoXxuKV<|H@KqJ1y{MsFi^9lUqTq4mICM=- zl*LdMW7c>uDxQ9|jZ{$*mwZ#|SXPF&m1c7T?A#@%>mN*zJG(SV?n68F@tr_zap{cP zMp7nKj1=JAn9yBH%*EfPcaZz>7@vygAc1*E#ZO{1VAK7DX(v~|%CnG)bzFx|JK|2(%@qMLXI%46 zJ94~ZgsAo*WVtjSe49#gRnk-9GITnLP%3*0XXYVv&xzgVN_8dH(QuZvbxV`nUZ7`8 zSt}6T!PmtYZ<@Cs02bHC>q(xn=DWP;cb~EehjNDA05FWGCuWu(w3fbb#c1y)yJ$$8NzC#)Za#%3$v{$3x@?!QNS( zmBg+iZ3@PT#T{>YfG@T=K5X&$iMBfn=YwtD*%L|d@OSh12IA-SZ-{eT?ufHpy*7f;Iwy_nB>IPE*WJn#AaRnyG0XslDQ^ z#}-R8-ZyUq2#+*>Ir^a2Hn+u>izu?_DMg!e@#Fs77z>(m>_p^OScjVQb&$H17$|ai zBZ?b<4?5FlwndonF|6AzDFmS8*!^{I%;kji3k@j?73kBNE_DpfJyuB%v!*nP4&7|p zXBn3J{&?`87j{5qIMD-I=C)6FwGt>Oq``X)?3AJOemzc#U(t0@A`DGzUBcbpkuBDO zEMvzTUo2E2DTY(?T;;pY*9551^U-T089MVFgidH|p950aVyrQir!T*wvnoeV?T0Kt zUcX73SWE~8aI^>0O`WZb3%UG7gI?j+I(CHS92}82;^<0T!ipszT|nA%c(k!vUHL+e ziviX2L?|)$$Fp8O0;{!=w>zQwcjTgZ;T2q4G6EmckCJ^OnZgeX)iKyfdoT%~5Z|VTCcYhiaKHZ<3jY30EhZ$fRr;PtCC2(dPZ(?yJj_`1 zNd@xK8wd(f?Z7ATEEs+9Fc9VQd{YVdX&f>7WA8T z`s?lW#k~_toid{e7#Tr>x&1R;s@Qe1xsnYP7 zAANRs(&%nX(2ck!KR{!VY?+XZm-p}UhXGq)qnB84SPlv1eQeMt$x+KGRVn!p>`s#LJ;a<4^3?tlJox9~1~4UIi;ra7*LQw}xyp*o}J zQVpIglF*6q4&9w7w~eQ|V32o{&nQqG?JLH%$OHT+?Y3wpb2oKdg1-djfA|W|t~AAr z`w1zH}>I_^Z#Z$a2L#C)d z4v^Qsz!J#sA5CiLH_oS96Lr*IFW?R z9cY$Ad(jHB3?~*XS{sv0rVjGlf8B7@(+>a0LtN`n& zOX2Mr8hmxJutMG6znb|io)M?mFgVvY-rBQ3yoKi+D8?`i+5t9z#R%P9(n!6bQt|gs z`D4l_`rBHyLNhpy8e(Cu?S+>;1Ecd_xA1OilSKYe7x};E8xX^35%wE9LG(_(f2o(s zo}2J+la{d@OL=Mf_tQR0jFA*d1hH-$-y#-vz~PHi*yS0IZ7l^~c>jQ1q9pp!?fvg&#{WHK^%`8Kt=)&6fm4 zGY{5ZkO1qildEs8%i!M^vX8~0cDxkYu{4jtH}{vt6g}YZpQ5QbdG+Yz&@5x|%-`1s zv4*1PpW1`xT0?pv18W2IjRungd#x}e%w+U`8@>ND?lXR|_W;Jl@m%Nef{se-Vxut? zA)Q?EE^3m@f1dy@9>(jZL~wHAq2{3*RH)CA`+t|lWy~o3`Tc{~-~YCo05TGQx4NLw zB{R6lo&qEGN~Z{r0vhuifJl6FN7PoJ238i)l2MpKBo@GvNv0LHqw!8B`A?@P6B)3G z%ajo|lrck90^u-?(+o*5I&^x^Lljq#3fAwJ0aHe*s=yY$!o;2W8h|o~Vx+MP3JU87 zZS{_w3oRYR?x<0(cV3U`ZGWZ+dN_n73KnIb7nQe?P5D^SXfcy)~Gg7|W)N&q{;TYs@@4DuO=f8l+n>A`W`HPEgsl0G)ec;e5&_ znQ}8^_dExk!EUuwP1D`nQlO4|A-l+=*?1315(@PT# zzIEA}siQ?2Y>`JG^AN{tEM#2oT}jDrVx*NJ!v_`UiGW~0tuu20x;#dD7#Q2P$MP`a z?hHru9^MjcMf**(df(mq?;co1Nt@adkNuU}fmkemEM$kqacT2IjrDapr?at8(1n+E z8H&8g&YQOackDW)LR(ib0DI?S?LZ3;Qh6_xH?Pzn#kxJ~q&$m*LALDrWwGc?0~x7O zYOgZ&veMQGZkrjoSmf_qzNS0Is9(Ah+q+@t%UY?PcZzE3|_s>8r%c5c- z7FLJE2;;>|2~pY)u)9;?H|T9jlHC?7Xu9ow3D&ePfD*;<;XHowbm@K%bBz0dJ->?L#fSu(jB25q^uj% zC<&FtfFz}acmu#qBXX6bjMhG274wmH4}5XiPgjZff#D;Q(>KHRU#@<6^z*t`u?6EV z`!0J2y}IXwK8^Knz3MWg;{|f>J*v+itL*H;E(twA!>b9DYr||vN1x}m005aC=w)j5 zau=UBjZuA&P$4hHLq9Chcr{+S3Cf0%9Ahf^MLWB*WpO z>6!3)sRN(nzCjKK6ENqpV@ zkM6wax(h#*HD7R?1V_i;t$UPInOdd(xN3TFXOH6|=Qts?B#=ajKWWn;^ph;k&7g~r zhfjte7O6|JgTxV)!xaWXDK7M6WD%WOB&T9n!9XiLgXzeGihxH3i5}se*+VJVB zyU_o-zUVl9{~L)ac~UZq!lB=oVMP>EcUs+j+tFv*3sXT)1V)n7ip+w_f*G~$W zI(5ZyJgtT1GfRDYj9zF(jvx${tr9DLxW9oKHv<6+KB%&dhjOU=W%*wRPjt)XmPhCk zGyS`QLKjyn*S0+~=7b&{Vi;FjyiefY+gN8nshVGV?I)`9{K=yG1Cy8Iq;fbGhU^yl z7`hY(aJF@kveumi~#=zRo8W6()3pkO#*kmH-f4UZ^dOAa@NlkZ7 z^ftT1<9L9R_H}lIh5&X|0dWFbqyk@;Q1=Z2cgE1W1N0kr$>a9!ypD`aKxhNC5daj;Z?8za4@-GJ_(>zaKp01da{kF7%r^@ zaE+9tf&mZDlYQSzg5@{M4^$4*$16L5n2rZ+q^e_^4lIh;^a6;+mWH?QC+qg$vYGyP zvjU^3`aih<8BxU1PU8gwsij2y#EaIc)@1_eZT=IYBZ_`ZH_#>F%e#;nC-4FY11--&s9?UQ_r{*`&5$~J5 z-wx9sF@%_CA&A-xNYJsYSF<5y7WhrFLJf?-w38Jv zaOy;R&sHg57=Yy*@+&ejbP^T>gRnExR4C&3@S>@c{dnn13S1l(EH;gWHF^j zbD=qZriH?(W8C%GxZvrm6f}Nq%+uB>b3k$)*&yt@s(sz)xJr z&3H7lH}j1AK&jd|j6c9tuwzh0m6;X&aN`wT%}V1AS?=#Ql2&fu@m<8!>DyRI27VC8 z&y+-&78k80%u`4RW8d5gTDugB_7iDwWgbmIouySMUWPtcjhdxUjg`*d@hh3O9=p0R z*wIzFCT?StQC(l05sJsUrFvcw$H!6{fP1~Mh_AhUG0r7QTY#F7qE{S?%Pq-N(V3!l z#REzhI<)AfRAE6;KebRExg-)^!^nw=A1jfqO63 zo(Wz7vC7OW>dhdjl@mTtV-Q|Gjr%H49aDedmRej}Sk^jzwf;iMxKR~<8f(73%;Lz4 z&S|9pMNhb$^_At^80+C094fa}?~Nbv5`9h*S47 z$)S8HiBFRG=P7@mWc|^C2~W8BXL;g5@}+>(@azok`0fEF`7k27Je0J@vHGE(UR z5ItJVYTqfhB@d%m}tgK_PQe}y`%D>o7#{cT0$3WalbEyKoR#9hr&Ktr@P z(!X5_y^cOZE}bZpu%>ngS_YG-xVIgNYjv$GMsj$hYmv*UYHgH?Aa3<(6E!%|PGKiD zJIX>4o_BzZ!*Qw5w9a6<36b$peJ+y!aTUZXG&o2JQKBAb=q?ebbQZJUf0V()8~8{M zOI+U{ysboj*vdg2cJ!`j-((dV20$Rq832&ipMDv+G%`eK&nC0GJ5dUlnS>EGOmSLb zGvg93i{DFxLG|_%(Dm61eHJ5s&0mBWJj@Z|NI;}3g@{1{l&BGx_1IRwEBF-)sS}DQ zNcANuxP|x9UBVsn6R%gORbd-~Q}9|2JNc~m4ohSd>Z&0w{?O>>huGeG-##?|m?wd5 zVQ`bW34{{3HvD=WZg26CYxY+TqEa8gR2t)d9mc*CpM!cnn82r`?SJZc+LQVFhatZ+ zmDt}J16Uaj9znDU8B`8%;1faG6Z?@O@oE|97$7P{`G5_{6)Amv4$%ri15W57{iYJ^ zPb{XA2AL@h@4fHm4;Jw*h6Dj20$i1+Hht?K{EBXUA7%X3I65eOGUnakvL0~ic+&R? z{x|(MMtBw?&@}SKFnPugb@{{m9Sy%`37LQk58PfM_s+FpV00SOxAukwe`)Z&X-XAN z$Ey^1jsqf>dtU|ZD>UK2oRK1f`(>MW_X|uQ&GOI{QkLGX@V^EGPsB^#7yalbFGE*i z)BOVB?z0@(=d^?!TX<8?OX0$yg-%yF)#^s|7HQ+Brzc0YkPt@53%{d!uO~s6K427f zgOc724*B&ju5^rkYiv&SICO<1f!g5C%xpjViTH!>{of~q%Fr{u?){ifrJJ<3yAadK zWjC14hiFhDqJG*FkXk_N3`Z~$a8M+p4KQ8L(T@n9jLCeuimDtmk!UABEb+AqKXuG_ z=N8VfV}8^}34eHZE}A1Lj7TLa8C(>qs=;j(=4 zo@_|E5yQP4gO1;xyV5w2cKxtKcxgbd>?K6ItNNZM72lTJf$@W|T!5)KNKQDO z`8D`4a5{{KWax+p1K=6mK#7-(4rq2xHT%|Bm4eTw@U8L20sYOC)3x#Zr#2EN;v!2Q z$8yw6v z)+?fi`xB>)tW5>N1MjDg;g`GTK81d3d?`M*GxH%;|FGoYQUbi(cU9M%g(ZNr1H>X5T#;lqiiMi&Fqot}PaI+x&&cOOjX;Y-# z?1w2Jha1o!Re0|&2ttw`av;)6DgdTtYiGzH7}WqAGLHe16(cp&$je(ZwXpvOB2!?m z_Gdd}R6#JFLU4iaCF+Li*nSlsH5~+uTs7NdFXvn?fJ>iKtu@VN&U%^v1zXdyc^poGoOS{2KJLV4uo+cW6^ef7y8?Rbv3|Mpy z0sG?*Q$X_G=QMrws<`_TsX3zL){*OoW-5vLP%04u zXF>9=ZDP)j`J1jAGyI4}_1pl9x=$NEA#+#)Mw_>HrO_^Sr!mbxln9EbKo+Y<1>&re z>ftM*{n9eJP}0#(6eeb@g4THp3F-izW+TJ_@9>gE9ELsXiMW5M<~J}!7;U7t15eiq zyR%W392*L&l1?2(=blZHgaSvtn;cS-oPXo8**o{EkYsta zEqpCc=gJ#C17bc5q`5eP;>&>2;D>WYxRJr9bn@{I+dAJGInPvPN*MW&NHn7H^bH-B2#n407#V~_4y z89s&YPNjt*FSQk){RnrEFgmEGMPL{n0M5u=%Jw#|8et@YPs|SZb^(rXlr|xwv{6hK zW&s@m9t}$=aO!BKJPUy>{;6x;2eNEC<^*%W_MhMx8oa-aKczad_0NOlUTQg?1oxb{ zK0HG(8`xewuq+%`0x<*VUS7QnIz;l*#HHT5x8DJEK^l~Z-1mQ&Ha=YYT>0kGZKP}W z!8G=T+W00g@5NccZq{MBP`-2(vQDhPOLON+K#P8k_&F@Y3@73T@v11IQ+kOJ47lZP zMV-TQl< z7&$^QY+S7%$3t{z!l?xiVQPIr9>Zc@1PVgR{{Sw<>-uBrwb>5vL{1oq^xn%MVYpX? zVI+)4Ix8vQFKA$2b2578o&!~h3Jke!?g%Fsj`~$-o+t z^&OPH_AncT{m2e1!Y#&v%Min+P5497N)5q~5V!(xR!3z!%Qb}NRejY$KN(P5udiWT z3*Zt3PIC7o@i|IZngg2=5&V4rd8p-``^`^=C1%&X6y0oAz;>zm$UUQZ`U~;IggqWU zg{3V*J9M2js>|Vm|JcC-NQ}Cygq=E0Yv7nT9c;FejBGuI60;lPJWp??i#jI#reX7F zYazIwo{93lYO{J~#~d_P8ZLtOl#GVBO$znmhb6nh^lnf<6wAiLGrKw0 zIvPEY#TfGn-3pJDmidLW&w&o&ivf91Y?v+U5)!3FS%H^Hi-}Lo&kJhaI*#P#>4Dj= zkSZqt^=Ben#+7Iwut*M=fa%*&M83QHA7_4o%)BYa&32(F;LJ$u8LqSJwNJ={*<)Sn zcawS!UEead`9h26I53~Dt{>3j(XhHf&ddXA4UWdOES15JjEp&gPX<3I?3gP&JBaxM zlKfeQe=??Q;WH%&Sf%B)N3trYT{?yf-f;O;dWK;HqBtwBLYeClQFNq?%YmEOotT{0Dypi0s8QP|LmzH=#qQ+?|;ABL!w{?WUK%Sj6Z zaR#S{GZMntTI@mY*$GoAah>DZz%;~Sy$VS>&B~z2SbuShQ1?wvk*S)Ro5g91^yYDY~g{3k_wrM}VPM&j~U;8yTECF_uEQtgH6LhUK zqMHYQ|DgRl_{~rc8F7+p3Pl~(qAHt9-)eL{=g-$ZGQanlPs~Z`o>`KsBuklfds5#@ zM%=ypIF*)zJB!_zcPg>xpY({kOefx~-so8&FkBp8QQw};@XJ;!i_nwE-Ll8wiij5r z<_~ytOROvB6+w&3wJ?sbj2@mX3R%88UpW)T?@$E&$V7>kAKfqMt*;Yb936>wKiSsx z+MEr@?lMp&&)rR*6|iWMr2rJ<@nbb-aSEkm zcIL}oBNRf_cR0uNaJct=%8z#+xys`9_4`b@=Oo$6bb-V~j6WY9z1f7;&|)E{HfO)R z`ca_6aAae2?}V&@>fScnV+ZUb&Hx&iiM1L1j`^ji>EDy`G=KG0zz$;y)zQcK`lQ6% zN}=QqUCxaa={Qa-S)xe1U$DqFi%T;(+H2%H#^j|`=*KUA-uscvapmj1s`6f~j;Z(V zdIR*vXE`N&9Jng%3Gi@F#*SFw(BEp~3IykUEluiVOo~m0j2<51z05d$I(DnfQhxkn zSRw5vm0*$gaK&#^+~V&ItDw$lfBLTea!*FQoE)-hCULL3c(ggK6(5Vwj}B?_zL_<|~fkPwdCoq-+m`N9Jm3tTspWT6e1hmrxhE6skMAadVb5TY7svWjTRKl7CRPRD8-J0Dv@ z1lhd40TK>tC7rHG36GWrgKKoZc*lGur7Tz!vj(-B=GgZ88M&XTx(RZ&1!=QM`eH@q zllwy!(l~>B^V*eFn|v@jNAD-+-mRxhA{5$jeJ=R)%k-q-V&9x?+`HjUJJD`Wl_mi= z5Hn>T{d{kAoEt?lLIa6^K5@UX;cmU>yw>>Xe&%P?xwCX`(ciLmJ99kSpKWCAPgC9> zeunDh&%Y`5W}&a?71xhvca9>rJKCq+xAq<4&ikD?qP=zZY1BpvN4~pw@)PaF>UTLJ z0@vWhpJW&xmY}{HeWHhlqa=s?PHuHRUm}I=?HBda@O#`P%OmqvtJVmrkQNy-P42-3 z8$C($vJL46m%fKLPY#vpX_>#-_97PyYMQ8@QF$+cid|Ttv7Eo~K|Qy+XWGw7^|Oz& zPf^dZY7>HWp)UUU0GQoi?CF}U)Tl@Z+J58d-Kjg9*I;&0cgifk^{wj_=!mH%zF-+| zu#)v#dG7StL*t9fabd~zU($Hb!?qpiT zDQZLs?Bc05_Q{x^XQ2Zz>Kc;@~8?Dz5T_Be@iRyS(}G*Dq;n?oMOZx{V$F z91iSlS*8EuDvG;&Ni>#q73LQsOns+t+rXj$+b>qY1KEcAW=1xxa{CywU60lLPv3-OoWALduH1!tbobyR{99JVi2eiq%V$#ATQmOQ z&H>NLj+${jqp8Wmg}0U4SI6-AIh$VM#5bLCL~?BW+`#&Tsk~p08q?-*-A##NJQH~z zFt?H~Q-6NfVF{;fgWoP%dDU6?-pWn9y~bb)Me-^cC(y|uG@kUsIJWNe^UUk+4`-Ae z9c7b4jVyG+@8w2E!4Dp3>D(`2lo=gmZ#pSqltZL-d=W^hN%B z9tbayFgZFx^-U&D45B-daa-SM6OWonECmfU{_%_&=;t#zuECML4HEkBcPcAk?J74x z(4w{T^K*ovik^*V9_4?|Lt-ij~05nwd#XNydSf z<$gDyf7;4ik$(G{k@~i)p`q}h)%4+(`53ki1l69q2E+;NCDL-x%xJ)1HoA0bn z(KDF&U@h_(2v@qAr-A4p{T7M{>QF;VC5PECA5^@$uM4G(^PQvKm^6Rxct<{rh(C9H zB`5lu_Tc!==q&dzdZ6y>bNNOXf8vDv388N;NyBrAvl$xckvBZ(9EQT)Nwx<+qfIe* zZ1vcIdqNitzMcZ@t%@cbqb+O4%kZU|h@cl*dF5I3j*_!TbBKfS8}a@OZNYW-H>_GZ zTQA=I%s$oNL9k0#-EzUTAp{Z#nac$Ix<4m^)31|K3~S8LOOTJG7th}vy^xHGxXAXU zc~PButHXbel1`+AXi^lk{iKqgBwl$x@$s%WVmX|^a%}y>a#W47HXV$#{I(o79m#Q% z#y>Rl_Np8i9pXBQ7vBuBRzB6eKxgMGOxudn5G8XGG8^U-^da}*O;7+M=KFll;0-H2 z^@YfW4Z_aniM`B|0%G4~BB3JZvf$6Vx3pimj94A4*0ujH_TD=l%m4i!j${KHFMTLFpE5PE`$FfvcE9t^#G` zKxlSoKMnRNEUs7p2Sd&As^Lp?;PfFiUy};MN2zDjs5;sizXzqN!iWhUtb&H#|gS8!?}iz~6Yeg9g>!E}s3MnUlm6t7E9=!~bf z`CLtb$EycE0#7On^`HBEO*g2Vk0+uWJn=kVpq;1Xw{qxxE7`j|o9I%l_3^jw9@S3n zDS33SZCjcsCB|}Y7slofbrz~zJy@vf8FAkH=$RqrdY+uuRss4bInEJA0~Z}e z5N}&}!B5u`>RS#R{;JA&3u5>>97b3X&uv_I}kjoXDrY ziSty?U5eq9nE1>vCtYSf`BZB2ozlILN=voiojayW5%uf7{-8;bCH*LP&+`+f@@|jh z_^8=<&n%kEJGX771wScjHwu2G?B4DAS@aEU{#C5|}W2p=0 zwijc$Pm+3Vr?DNToO`M7O9Rx3Z_xiBhJ_##nu@b#EM1l}!)LNXIyOO)?{IjPBd z-;abO4w|PXN6U<#j|Qrn_-vc@U2U~yJ8JEQa|KM+e$~JKlKT9gUH~NwP37GrR9DW_8quk?b=mwO!T|qlVjEEsOzy5`6h2k zo;vN~+H@O6S1fW`4D=?k|B^a=Fu@j01;lNd1s=P0arNS^2MnT>9;ALpZ{-YGap;(R zw{t`v%QlAwDyZgjeNSSz9(uRrr`+O?5~Y=|rKFUten0CwYuK>6DAePpjhn}76)ODy`qQBlF3{YQgd9+ZCH^Nwwr;iG%MdZ^#n8{lz_K4?wu zZJS#7L`k!g$CWNIiBryCeKeZVuKygnKD~~t;Ool@{$ZG!k4()Jo3c@g{Xs6c%yunp zO9FtWwYTO4F?8$qn^Fpg`f{(E^1m|0dv^V4p$)ISol}4Dt?vnjF;BQJ6b{{KDk&7o zkz094Lg_Idb`DKUylAO){X5@cf~5O(s<8^}$Gk6tex|Y-xp^OcaIib^mQXut54)tc zS-#D^cR2oLUL*PSC~0-?Ni2{6%v4WSXIXr@e3f)-*Q%A8itTlu-)X4NdM}8=7gu zUR%tr7xtC4@TnH%Z}nG%(@NF9_zcvQ@SMixZ1UWz_1fc)8yEz%^0@nu<&7<3wJ}@s$XFUKc@dx_!q_t7IR*8rB*Euy=Mq7%~AG(9Y4r0 zta#u=uOHie`s4!4BJlKD*LCCaYb=LMlKsl_w?<6;Xl0MJub29);gYae-3erk#4{&k zs>;lzoYCJ6>}u-y^rX7X`nRdadQeA=%e?3y$1@8N_tuj6a1m*Kj8%HUJ>EVxLB|oV z3D-mg7o&r|2NrT+3zaDb8@s=Aj)*8t9LF>n-;r(g$q(G^iDpUTzsulj@J=NH&$Rbe zX!)gAGs^>PSEoCcSjM<>C9AcDx8CJykrH4Jeo_x9S4a>yObjPqmGbD`=1`_$6ihA{ z#ILkZZt-$z$UT&f(o1Y&=HRO1+A;zDjb%i(b0L z_e;yUeT#Fu>MiNbY|CVxI^_B7JZ2t{cIs;2kBiW`;a8nGjB0an9IwIO);~0LQRXp8 zRP1~dws1%ExA6#SF@)yZ$*;59$v$ij?o>J!O<&yn=)8Kwm)GNL!=q?ZofKQI8G>_o zIA5AMi;b~jvp9{Bkl-rF&})3|D-*tAkf<(6!+gWtMxCAa)9pW=B@a9Ae&)?p$<#ht z8)>c6>`0RSQ7lRAUB1wX*>)?C-yjGKt-c;}{Wo_K$;_YBp%3+hReoR=(%!%jqt)Z* zloT9bntHUi6BsXiJefH8`MCmZk?~wdC~ZqB`smcLA6B#}(1|~j#vV3w#I}e_u5=H_ijR}c4LX33UN8#mVMYi~PQ19FqQQaPm)Z@07J z5K=yJ8jdO&ae39C<%qp&-MYCd-H0zFHn4nOAqi99bDbJr$XrE->&EPfp2Zfk6IA;usc9Jt)OazQv8`gq@owIbZU1uaxLZ zm(VJfyWC+<`g;u5#gdKYAI|d{>x=xZuY-@~*B+kXiNF(b`qmgjc|xzydE>P$p=Y4W zXW1DB6-#3+bGWgC9f$l|WzSVdh0T@>DhFg@HhR6jPZ@JweHG$C3U!W5#5*pHtsMUF_w*DB?1kbP;QIDM5~mXSd7$K>0)wQjK@n~;-XuX;`G1FQJEbd zaJ?R^HyfQ*QXKpCz#_=tcU#qUk7BPetSW_CDf>Xxy`}2}``hWaSkLAO$;?6M+E<~Y zQ)ILqm0l|RE2*O*p4IK+vwbRwlsr*#R=;GBL-|40|+xgT}Hk+5g zI9bt0^}ypbVtryqAS*t)6CFbZVF&bozPs^8C*y z)qZM>;Z%a9VTR$^YhglSG9S8SvQbl^dzmYq!U;OIG@P?aI||i3*E#;PS2cZXk!m7$ zBiokct&2_TO5Ld9+k?;DQGuHdOxJhkxdN7&L$9w4O=S+fH=iyUb3Xn?p3Id&uCvJA zGP{3%rhWQsnvfTT&9%(u_>y-0;>%v6OOA<_tftH38aNnA;(1!%-g$nlaFKe}@Ktk1 zpWQH=?ySj9#=)Kt=dIc)&%ucx3&t+Y{#5ZKHHx4zV%z7MeTiDT<{&;-lrnGVG8)XT z)-f}3Y-XjA_eSKw&r;|(mZVb(Bx6ArBU3ZIDoD18xniKuxcr1V=Yg8wN>Es=*P~l4 za)a#Obu(xr9;im(U5-19R7)+PzcreyoP0H_k26R+?w@A^QTls+vW7oVsQ;50{n*kv z?|q7`xt>>8Epda_J zd-u7;K;GufldKxI-=w2L#V_RJAuY>Nixb+|Z)+MTh<0(3{ILDI`*xD^??H}!r*G#= zYWJVMQ;NHr(c6mKQs3Zi*`N0{d+x4L*@vG%J58#ulc{yAJ@pwnmH#iud8j5Ve4Z+t+nw>q3ZQ&#BptXk`h z2e~)@>YX{C?B_%mU#cII=`cT(kN$pPpc8W)KfrMEnx5tEcPR{wIksTQr_`9`L^%$< z^;)q>D05l%{o6DL_1_4e>}Dur2;cK2f57E?g=l`duZ!AE@%`*GXf9|E7^S8Fh4 zjQ*g0gvb5m;Lp~uOAa;V`j&tZvCPp?9`)r26tsvqzDxukw$H(}Lf9W${}9N^J}P`%w! zWD{h+_3Lu^Vt3A{hlWviCNr(%j-ykW=yyxwZESja^!6-l*iS7I*&XfobT)6S9lR=m zMAW0oxW9S#Y--BzlmpcWtIP2>!%BL~zE@K5zc&v_DBry1C#C?I0W|ve*lCbeqATW6 zY?&+kE9;$Y0{rqXD$v$zD&g%28<+Jo5p+zUXC1K^Tzv~$*W|}H^lFKHBFUp=FaAOu zLhDXl#b5f9dV06&@1xm@i;(f!e#-LgO=DrJa=eLU_#wXU3Xw8r@RFV&`(){5Ly5O| zSEBHMVLEs&anE=2;T+cuT)u{<;UU{LaNlok-#A;jETFi8KYqjXYr_Fm*X7=}8m%O#F}e^MF@F4~Z>GFTz zNf!XJt|Wzl26@$)w$YvR=hp9E3%l>~cV6oJ*=SHsJ>%JHAHXVLUwG2s{hj{d1N-wT z6f7^C%f9ScZLtF(GF~~lMPHx@>!R!y2@8*7w^j1hTQoVL^~LIu@pB1YzgD%GwQ;Eg zd-AYR=yI?6Z}+{D(RCxqBQY%Io=zh4aGJBtKe$iL@BJ!y`DEPunS3~2`MYeLC|f!s zx!MQU4;Pde)HC=y?`>VWnyn{YwC@&ivyxDEx)ZawtGA&Q5QEv4(FG#7MH&ssqW^%& zybb#PoGLPC;i@SIq#N)mP*2Gm&GC3{EqX-7hVj|8WkW;4x9yv$ z<@U16*4-I9Xz#Prjk*qWKX1O!AJEDqp^P>`BOL_&Svunf)K}0ZR-41Gj-LO6<5$uE zf_IAJkKBv`jOG-_N6wFE*))(U*=d#VPI%Y~t4bJZxiZ)aOx8{ddGGm3T|3zvvJ1g^ z?TDRi3L!nAVA#W8WFvE)|6lMP0!Sfl(Mr~6Fov-kz6@MY?y;}GeMFJ##V*%;n@r14 z129eB7sCYd!&E@c)-eQ#S5iQ^SOfNkc?*|uT>Z&Eh6;J4fJjbTI$TGG*f)LreLdio zsCQ`=as=kCSAqY_6hsuRVRrsFq;Cwn)ZmO%3|a=6h|La{(dHLR{vdcjEq2Pl?pyhC zcWoIbp9vQiVZ0r0GRr(@opp8Qi(`R^CwUqzKednl@K85cS7!ZI$QAz}~zZovQZb3ssA#Ih{v zJ4E97PFq+*4aeqhE#`kfRR2|rX}Afsm3()Jy&c02r1^!XMdI`vd6~ zL8dhZBUb1D;GULn{s(~aUnQK9K{!YsTRNGDk%Of9zw9JLRs)4#!~eE+|BEU8|IpGM zFbYPezrD0mc&U$)C)$W>Z|7p|XsrPm@l?N@%GAdCQ9_+rj%NDQQrXFfz{Qcy`t>D| z&mN0Ju*3Ib|K;0v_8`97D}&u7d9u9uWZm;P#%)q3`uFMsvlIef$^58eV4MM#Yjf1iXK|NhvH=1!dt`A?Mh4n_a!5jUyHF zei(a)lzS=8YX=2$jO0PO(`ia@>O^Agxz7 zSlDmA0nE$#V-(1)`m6Lx{Gx)E!5|pavVWI!(7KLv z7d`7~&{v=7PS|PRoio$Hv^-1?Wn75>1Tntg3uRYxAdKulNo}o6?|GFcb_M&o1S&b_* zA$?ab?PT=WuNiuuJ zzq1V#{oCtxMy)NO5+}xuft6u>&u>mQD&c*7w5_))ouev}z^tZv2OY>51;=!oV2bhp01lIetvXKB+9AmLxSUqc*v5x1S2>)5sjh+$Z zU-DuM>bIoF&|6CcKbEfgZ&KEbkv9ZXSgN@~;CObC%g-c6 zT~7~&X51?8&@#EQW>CXCBgNki_d;RwHlYH}0i@x;nd~JS-$ORSK^8t)% zkDf#0x2kgd7N}ucz;h)NuqOc~*-&VEzWTu&sLhwxVgCPPG&$dA;QrKUwPo&Mblz_k zHI{rwX1F!r`hy|Ralfx&;flhbsPdz%XqGE{zSlpHJ<8?08>Lk~%gI=bi4X98Pe>p&Ap! zWcgyH@FiI!Lo5Pi=)3a~&G@Yc5qZ>4{yXxmCAY6Om0xKsxmV5S8&hHNX^Oz?kYcfj zvf;2upeJ1*hHz@TghyR_WqQ%Hp#}51)kZR2zP9K^-WO`--gDfAoqUoA)9+|GxYn1TnT ze2YZFrLQjY&bs;-we8g1?JaSF$spLSx$av=qpLbEGl+Yja?w(7+)&_HV>lWv8YJY_2pHet0U#=bN*8VRq>05PR`~ z6jV=FW>bH4Mhh2WZ|n=%mutc0vBTw=a*W1w4XtNeY-U`e_&!b7f%4l9$7LaElX-6& zy;un#^m(A83qwD59;NnZso~Be*C6YzW}s-y(&ML+ct`^Lb01q{C{upHg~z~u6T;l+ z4Y#=^wT@1^j_SSYXAL zNG5O~lGsU`4l^w+ui2R!_bLT_Jxd(-8L0-(ZtVY(`PKIGu#gchdF)r_hw|%6_h`%F zC3Nh22P5Z{Gq@!anbfBaE^IFEJgM=WC5?SnA1&9`OINiRaQt1{P?JGp)NZlf>(^aI zPIi-8vWBBwN+20P%CF`>m-?2V`8OJ79#;?%%&EFx6H)nWZAOvLQS?F8wZDJ7kH^Z2 zlRUWEDrrb3j$F2if_u@tM+OEZKcI~-!x2Vd|(*3>1?&lSWU|(aTPVA%bOq6~| zJR}_3efpt~Z^(IJ#x3{yQ*0~^mLm5^aVMr(99b(R_!zk^bPj-EIKcPYgsx~h!i_vo=EfMHFDt8ywH*K`&jV+hGOF9 z;-NFR)iO@PCf8{29$^41qB-zk5S9Q};CXsU1>M)rCPTWIhh`V%gKFH4NM@MT!&WZu zz71~=(osni<+^Jk7PF_qi!$f!?JUC8pue|_uGN#exiYHu;SsUrq2fAeYY7LJ5yj34 z4!7?bVMDFHjWVWePY`3M6di2g&aS}H!U zQt~bIJ}apjF2zs;$3Z4k#S53+&bK@EDkr`I z)w?Yfk1X&WZNP|Nw$o&N{E=1pJ37O1D-URzMyXZI%j2jVU*+=DB;g5w#(O4Igp|;o z(OeTy4r%Uw%!l|iw@)6XrFGS53ZqC2kh>a%Vg=I~?sAi#GMzZ~8F^Yc)^TT2gmt?(RU= zu)9eB8P0DDnBcNsKZHT*NRXblfH@phUy3@l~hTtj=vX@HP|?h3(fi4A|q&LG4pF_Co)hIs)@ok z)EUhC;Or0BE)CMaNB?4<9XgggpAr&1shJ=o$vHbDTD~zaBNR}^M zqCZK#gzb`1P|MH|$gr0@8AGaq!Ac)eqEgv4QOEB>a8Sx^Z0k+R1I#jKuTaOcHUliC`hJcDj%0}+UOLG5L6INHayFw*?re)muiQqbAU z&JO#E?@b$g?F(vk738r?Hc+1Q^8N8AVqUvNL?Ux|M!pYCx7NYM&_RHv_joSdcmC7H zQeO@smx^cw476b1lS%Yj=tx>jNM%3+?c=%^R4_vm1mU?QLN=K{0A9cnMkF4^lHbkb z^UYkl_kTVmG4wk9e|iButfm?Rvbfs@EO}wWoBYRy z-y)bDGC3}NF97GkGknv5%WwD-MI;{Gu5$6s%Fi%;+YjTV&5sTzH@1oo!LatPKnz6K z;B}HouW-J|s9Jp z@0)s(B*Z7u%JVLD?kd5+PoM+qtGD_F`qtto_V!0-332Ef7@Pv#J_?Yj{$M)1m*hJ67L243G!?_QC?Ko$SQ#o5$NheP{_dZyVS_QclT z=J3N9Qx2#-8l3xbu_aVG|M53Pn%sFbsRygWOurm`+_$ELEBu6uOiSVW z@Nl_a>8k!~Dj;5qftj?>&frq2RPcHNvmb2_(`EWjB*_{eLM};HGUE3A^nA&WHrf>8 zPkp@EAzYi|pE4k`ag%f)#gZEfk0Lj=+KMhf8XK2Z(ztjDIN%LXpGFje05dvE^Mn<0 zsL!{s;Y*o&S3A6TCT>!S?%pMTyy;NK3>E&~;m_E}K$mEFso%+QC^FvTfwMYNfwf+{ zjh`ePx{+vh7)nsz6lQZ6IuQVG@Vl{ql-pNsU8L1%$!F>Yq?8{vsais(oCWzK+5Kq6 z9}S|V{c z#m|Pk71`gnn&Ss*2|5@Sw#b)cOOS?GPqV~C0yv%$xn-}xTUcNTJA1U2_++&1RmO2; zSm4YKNj`;>-ga5NEO?VrTmwqJG!AlCfGh)DE)@3zm>RqR+ZP**+_%3l01Y9b%Qwa- z2}qRIrm>g}KI~OKO9f-P9dU~T-lUf=+VuB6OoH+F2Ca~TWXt>=JANiMo?wf7O~8IS%2Dus-$mWl`4ArtdvwU=X}vcPHi+yX7I~Br&+H z-fy47L6o8u{6HK`+K|8MRh?EqK~`l@_fP;CO*A2PZ+9ebz`u7RyxZz96ub6=Ie7!7 zOvr5kIC<3YQPqC3cc^ED_Gmyp$a^7FsXJYO4GBJh2#f4)Q{)fk&yZGtCzVCDwGAK+-CgqX<{-cJ(VuZh|&U?1M^`OSXD*&+H;{2z}tSEv?w zd^2YY%?vyD@JPQawE^Lb=x(T@3AlC`s0@MmX5?;vFro^LVe%>n*wEg&CvrX^pB=Ks zA4tQ8y=oGk&g(0OF%jCt>w9M@ne3Xyp=htIo?$l>lZ(oHSp>;uNxs|!uJ0E3<9?P) z?9(dH=<@`$)6W5)4dK%>RN@YQZZ;8a7B=p4%2p@r=VOk_ttFqRX2L{}dg9wR5Ka7y z1r+lkEm`?<7+K5LE2bE&bg+d@_BKiy%=9MAm}W@_p#MlWNb3&Wq-2VXwMdUPwf+5U zbH(xG`_10H0YXhIjEDgIea%%J@J^wcYMXNwZzM(Yp=4z2^u7a zg!*n)0q12qQP%$UqS$>*elb?`8i5e{dXSWzhiIV@5Fxu7JhstPX&7?kF>5?S!lK<=ulR-cE0~7sa<>tz ztjbyLbF|qZCZ3xnro|!Vxr#fO=7*!LmtK;61XL)8F%!hBFdUr4z%ocdt7RZi^__D! zi?v}50M;aFZ=h^*)A?;}yUPU0OtoM1&9*%O)y`Wx@N_qrXNRbLf4Y-KoBBnJR7gTD z>brRpgf1qIc^t<9P76m;Z;*Tl9V^ZD!3N?_0&3Cw(m|MbtCl1jI235DPM*I!j-0)o!4xLV66N!4zP}J}`f-x?{xeG(m-MP##ZF^;N;{taAHwHWbXv zzsy!+D_l?Or?q0ThMo=X*&%Y@t(z)k9}JIq9gA0GlAOAs>-jFME@qtnULG()+5w!k zfjO@ni=>s+g#p zG;Owo*l+OiuJbCw!bX;{(WZDFq=MFmH?fBlZt?l9eZL0&?8rh0KH$N2yWcMOnD41+ zMcKmy#B^aNKEO#);J$X#+kDZ_5yRf-r>v!Q`1Bw{Qk4Pv&32QlnL zlt`xG`|p9*MjHfM$Ddv7#xF`85+E5WfLm0eXWi2{+P0NvdO-8yt)*;+f+pR-}dM<*?`Diwa0u7_!uJqc|_7C{EBbX3&@Cf z8vkt~$g^f*aqf}I!12Ok{hqE?E zZ;g~-7fx10Pfqbw+slJ6S3>3O2FN-Csn+=H`>%qB>wl^DuBiy-rsaCjCaRriK>%bv zR^=Wk9dd;lSvUTTn7Xd0;65|^j=LYY?_H}_?|p$1sh%@{`_~T61ZZ= z89@pSJ>ll4%NL*d>^_bua;ax=;g4J8@dAR)Oeyl7Mr8jE)`V_4;OXxkpdeWi(8rh^ zqIkUumMPi+;u+k|541r*RsDF(z8P{EDqvkW2RbTtZ0|GdqS?y|jo`4eeCi^leVmKXKA8vv~v$S)_@!r6=|?nc%l znt4`;`>vxkCm1XlUmfg=7CUR6mu#m=Wj()Ss z@phT*umnys67TU{al!-0Q?G~|$^xdd8RQMEhGjO+u)kwmZ4N1H=R?y$@n=dQX%U$n z4p$umj|3`H<8u?^eVGiuh}0*2eo+ID=K``xUZWcKVn$*Bp(HO;w1fAsT=;(>mB2Y#1!hmKe%k38LUVq~X*JocR6hQ`!SGgc~F+fI*?jIv4#( zY{jzrm~dB_iiWC&i>NUjyBEFzqq1+xPrDF_!35&VW&`Pnf9#V@X*a7 z!@!!a1+%a{G~cuX1pm~+l@Xy;5P>0-I{HZrf)-IgVn+^uHv*;b-2EmDkk0}ko7nv& zf0&rZ2LT>^za-qUY}uD;sp=8@c4F)0QhtZPii%G@caygecAYck{MFZVX4b|OAk@IB4nHH!CAj`v#W~+&urZX17u|5T zw^N@r+zr2yDT2s^*;Z6ReA)&dunFMGED#MT0JlsT#LoyxlOaNk{Txau_6kj2>veg0 zA_$^$RXZ1(q3n8=Y{(6X5nei+iwedbHOgDc`!=9)G^qrR;f`XXu`3e42~BzvgT9O+ zP;YjxWz>b>1(-Fz&`N`q%Qc9@I0jS!?^8-+@8oA^_u2dh5$3+f?>3ibGNKV#ui!+v z<#1u7$>UrT%=pK1nMxuwXw)4Bkd3BnXa%3sGE}$*rv6g8kW(!1LY@J@?gMze8#Gw^ zOvq%u>YEK+Q0%!N@>;RVHhk$bsDOnL@Y=k@=Hca<<_7U%(8wDzkQ<~&qs0ikl&Uxl zHGo752_k=@@u1DO_Q?>hU1b@(5^#b&%o0l8P|Mnc$c$a~tOJgSrNLs#(Q2nSq+$Yq z;Z@D&XMhzj5Q4BmV|;p6MA<6>4`^Mq-(o?^o7Ef+dS4eb#5aQvn3NL7+VvurBCWHOC0TFf@@aaE>?Gugi>L$u9OE(+jvQzhkox$YkvU8U#a5= zulL?`7(t5>Mj|+DLrG37Yz_1W;c7W>Bo$T4OlrU$r?1@hJx=dRs%yE{$imazJDKLw zLD2)!Yabr_Zr`pfvI7_)qjSW0Wsn0XD<~o5XqoyDgusmXv+TXV-(O|WE_i-K9m*Ck z-$up3c*3PnMVKM!Ljjt-*lDp0S;^lBfOS+$HZ&X`Y?d6@w6i~S^0JEd;)@x!uB)c= z-@fq_$J|VaPTn@w(E%*EXX1C_r+dfy`i}y zPm+J5fCyYNc|7$+p+q5dLTcd8&RkGoM7x;e;fh)4AekRaTf;8JbL|2c6%e(34?|oK`=O6~; zQSai;)><8j;WWzYBSI&gD5J;;_D#pl`bo%~WBiOnoI#?3DrH3%@CNobMg3y5RQuA2 zXrR@C>|05507B1Oi;&eg_h97a|7DVHZw=k($kVqLz@`Tz;4>PR}Uw1%gK zlR~EUYYblyg~o;>%)uE`4#gzKmWS%#gW%C5m6(p=yJ@WEdRbnPoLwv-R4uZ^0vV9i zsdL14YJ890iAKn}2w-SiMTIyD#mgrkdJGE$X2$7F33c((SK;#IWHK!iLFkUGX`#$Y zgJFsb*8Z5t(&yjV!4V4h06Tc{Q|JCG4GIP`R`|o0Ggh|$#)p0SEliBy{X4_{AHw}K zRcOK~5FR1_cfRRAzukgq@?UYLOQXL;WCdB(A1MA8Z18Zp0*3yL&HwaU{{on6PK!*+ z{4bcw&mgxZ@Go_Q|NM{tdu#u`IRAIm{(ay5|7b(*UP0VdhPWpY0%<{|ZOzs!&4`3e zj~(dlNy&Mwq=5>jDFZX_RC8pC6ztKr8I_)(zXCJ#gu*@t{P; z5Pe4iG!zgs5>^3jkBc<>uu(!}f@%025nrzyuz)Z}Rr4w+EsO>x05R4L;D9SO9Ez0&+VZaZT4dGHdFkd;eU_MU6#?z44A>p;@UJ7JO(>WCyapr^1yt~V}cxv9K zZlb%CHv_}soN|^-hJ_Vn3%G1e;EW7kLloq06bb{EXI6741b9kCk!fP?uZd`Y`D?|# zOooYhj1|bO{XxI(-R{8xurnfekpZ$&LEAp<kVhGxZJ{$g8-ocE^O{fhvoh zC%F}6NHQeJ7LXm~L+=a`Wx9aFOPU&M>n5nn>6!#VC*OM$$9SC1L1K}PD_f)_Z6>(< z8K+Mv1sqMym*NbPKbF(q2uB&c9YB+U6f|{CpeODaDs^8s5&ykf!73G0WJ0hhqi#!3 zCZnE;1m>!-Z-FsXDYh@VyA4l-l4jQ(@EgqrU!Te^P?JBsgH=VigK=?LuhVapVelD< zNRcK1s^0eSVbne)=(L7~U!tNHZr=?6AdR(*4)RIX$GLOJQNo5IPsi1_AY6YYk@lmC zk}1W#^11x@+&}RF;<3$ykRW1#a8&NEq0=IWC%&u)TUyV1Zm%oqG8a9-_DJ6%5oxV# z2tz`$B{$=3i&~G(kCAF~9g+U@h2nq3c9k2|;b9DSP`>%+;6Mr`Pa3K7JQB8p2-@lOV$H1o+4TfxsfDlJsZ3<}CWuW}467hEl9A#h$IKD|= z`DY32(UDF-030I1F|rv^N`a81r6m9TX(K7}5I*AZ2mbx@Y$lY^)j2X{u~g7?wSc21 zc|Cdl$R$y}v8s7!>(~G83MZ~k9L|3_1{3{X z+=q;iMTcSF5asXEHzVg5#9%ovcz26z%8#o zMv0(50E0h=8&P#c3fRC57!Af@2J%gLNIFmv1b`VhR4&V4oF)8YvN57SFq&;sR*yAY zn$AcQOd>W(Vueg|DC|*Iqq&n884_Nk;P)iJ0tdi{{C-mbv-nlN0>})Y7Yky7Zo;ZB z%BPp>4qE0@cTZd%oTdc$%&5tqU0pvIU)~|17gSDEGhE=Bhq9Lb7>mnXdlt=xb&KpA z{Y+pu9ugH~2at?#(y7oQTHNdPzttno(Q}3m6Nu=4fRaec2GR@s%%TYvWnl0;p-k?# zdLK%im)Eq6IIO%vxWvF<*tuW6`WuR)1t$M!(h=B$jgwtNi~UC%4aT>VhMm_&1yU^O z%7-;;J?$qNQBr1uCw~ zj6EMt&66>bg{e_@-9Al>YJ&W~He;IhEBNpIUT>iF3{NFyoO4Rp)>h6|Qo(0I55c~W zXemRa`Y>wFUD$a_y15FcWEk}^FdQRMQ@ct-c}9h$d|750dJQoUY(h%sg=z>Q={#=} zf8fHNhkX(Hfwou#J=X4jywq}sM16zk4ifJKY@mR8NBpqc@HF%gPWIPn#=KQqJ}MoX zmHd@0o2~r3jQlx~5ZOq5N4v4AVo@zw_44q`ToY$+fkM?;9AYN#Tq9`kv5ee91qM-` zZ^0DuNO1iVQ@A5o5WbWP>FMUixi9oPU%F%P>&fq3d&M+fXNa*O-;dp&OTic+8JmQ z!qk`lsgpZQu$y`Y4e=)acVLxEW7zDl|N0tnc;07A&if&YA4a-zdb3sgMN_ZZlsc}{IlH%a17`K!=Iz_1l!qw!B!>%4@MLdZDol} zI@K_+`7X3z^4%`yI{jN}_~`pfWgLGm&){0)wKADl_iG>-@bK+?zEaet(dZG_HB_6E zNrNx-)_d|0iy(565v)Id06e6Sd&?yF{B^JX3K-o4l=243!1GT;zFK~L2KFf#^q+uM z_d(-#A}~a3P(cYFGW8oL$p#wL4-j-ZZ_TM7jqNZ25H2kEH5u*Nl6){GA(gzx=S$S^ z_EQ88Wd4{+v-7YUl>|6 zDbf1mRj7JN@eBleH;tgqHvFmZO&H?BKf|o#t$T`g*_6F`%?cbq{x(fjAlQFQEPR5g?)d{->S` z3uQgQ~gp9un@J71JCHl!jJ7$GOStSYz_pe>>sIt`_?oK3i|5_!`3b~x=n_xaxgVKcJoCS^|U`xPNND2`X$P_Cx_6NHum6^ zNf{k9eqPK7zX!tHDYe?op-|SiqVZJRULYtLU}8MboNb1(IV5S2#?Zr>FK2l}|39c^ z64Lk`-h1W>5rEJ_Pv!+eGX{;|@u)fHc#ccQr2iSPDnw2i&=>q;Ux~3X=mo>uQ5Hd& zQPA}Wv6dp#-!%cx7q~=-i!`@@m;y^#7LcD47Sda_1Y%zla2WJ98!dN}l@EnZTVl}E zQ34NyfaPL25vA9gF$t*;Sx(7}PIs3c0!A_3`l}-=jh>Eic!`pMZVqWX{*7gS#i9wA zV*0CaMil9+p|xzd(%~}H4_-Hi(nvf+K{#P=jg&gVpy*K`AD<94_dwWdm;Gk--5984 zIy}5m^GV^Vh|j?r(=isP^A0Id#r%1=D8zkvxczgSVsQ4@1eK42+C>OfMFp(hu3(lXnm3BG$$M-ksJ^1jw z8B`o^|GW=_jsdPVe^M3_&C>*c=L6n z$83yHKTjHj$_Nwh(b_1_&QZrW0PQ??Ut}TcH1!akm+`uVdi?3$?7%oAqy)i+?Zys# z^{4LltGrr5p)HIaY6N#PZJKNEPSh5}e&p8%o`kGs(bJXwfH)|!WDyXP|C2L-oM-+p zYI4sOl9@)WjDb}Mg<7Ecp#{Nda}4E>VJnv18uU-%GDd5khFo@R=&~&mDjk8J*b; zN98nbI_*4l>UILh*)!0`ccSM`VBRFHw$`%}XW2pWzLauEk%1`L1T1cekNR&;qSG*o0zpY2DCw zLI+KAvDdOap$#bfigeCdVDMNx{fczUZ+0*sF z-|u)I3v!wksPmU#Bm#nC-jg9xbN_oH(OKZoFFrorY@?k8ruAm%kP3xuM&-gP2NK3N zPCz8F#eLEz3?e9VV3@ypBcA}_$v)l%;rZu~Adv~(%@7sTX@%jlv-L;2MglLx0a{sY z1nW=N!Nh0X84Qho1t)PmJ(?y=5Im|pvpn^r&=+YThw2}Om1)$)fQlfZ+dB>2@yl*N zKBxbQD=jI3m~ig?8Kk^Mi&S&~5yUT_5^--7gwQ>0$smDo7GUifJBk?~`{y zZ%zRYIEX*YwhzOjMk-&(z|tYqN>#&=#>}mSPf>{C#2pg%^@$d+&RXCstee2Y-jECi zgE$Qg@>{nTD|#gl#U7RUMJ8f23dISR8<-OMdhW?dL;~5uiIx z@j915MljlZi*uPtJVUn7BZ zR%eXC3Q122FUmVE0ki+j0h9ufrs|iro0ay6T(2s74Y2*xG2k*x46p+H=Plz{4?%5YtEDK@x`y%5g(0T#CH*a=Re*z8@i_ ziT9>L<(h1yV*-zG_u5fUWGfS|e;0XP?VtVd~oGMF7r z&f`ZZxb-wMfC852T>`~zUB;jcA*ZLKynTT3C^cgmu5nwn6I7;87vw#a1+3r-;9_+s z5uk@@2G`UdiEUVi8snIAS2td2U6oa697Dv;rH17h7Fxhq#lFn2Rp;-Vse4IEi?sYDsi=ZL+=&J(9>e~~w zB4FoE05|hXJ;VnYhR9*T>02YHj~~JL>&kY30$xFLk~X3#?ji@mHF%KB6sQug3{60E zTI|B7?Bf}+5zl9<4&+2b>XtMWFG;Jl44P8v{s#6+;5nf*%?B5Shpjv#WJv$XLIXXq z>BD>ZiKnEY6RdgRc<*xO4AeRb5}|@=_dZbj`N*JG1=_P`iA!X!j=z2}Y`c(<@#* z85qVIX0Q`j3&o@AaN31N%AKCJ2*D3e?h$ToKwFCp0;Ir15VpbANuhp;BDA0p3f(mx zGEoGlyK+-K8rjjtYVaT&ZgoW@NP7@Zy~4EJe^yADy$fxGwzs5d=VpufOW_c^^^$*Ne5!!Xy$9u*^*IOvB}X1 zwm-n|d={TNPRxusLLC}P{6R*tiNSmxa1gx8hyo&@d&S;dKXqgeu0SYqmnKVM8FLK+ zgyjr3QU~nzpkOOU_rj${4w6A*A-!L$UYk(Xx7*>4U6BI51wd2#z0Mw)O<2h+CiT*1{!7%9>;SW&vAEm z&wS_lUe|S==Vv+3D8X)-hu*=ELnFSitvlWfNi%jY2>#)q=N8cQH7_^!f@uqE8<78h z*fyR=#|1(cW@OZr*Of8?TLcY<*8}>zKl%ezEw{~{_IVnmog-&T$khLkC0os%>U zMwbigPzM={6B$7awZleh_6{=E9Ke-&xsNOl0$p0}av)Bj2g?F!d0l`!hD893INIa( zuo09}!m2CBHZ(8I*|nr=_DN^De*-NoYTucbpjQeoaf1`GcD89h-n=1L=cM<+Y5x*5 zkk3Tm>L<+1x#BNmK7H4LTm1u)>Gj$n#88gp4-SA0)$UMug#cs3vyaMdA%zGGs@^~I z4(KT-7&4M~;(7WoAwl+Qsfv2un3qwCd|JoX(&uh&6jAG))(%o{um1qik){1NU}j27 zzDpC9{BI>g{_O_vxQ)@X7|Yxv8E{_#WP@h|kxn}|MMvv|$EUnth?K*CD%T;|MPDJ< zw7C=2t}ycqYcHrSS;EKY#rSPum^0dNZiHT8CJ5HAuhq+PUj-30#Jn(*P6?G%h>s0V zju${NriMsqU`ElUr1bdF7Ge^@{G2l8N!eo)0!a@a{FEKd?<;55cYQkCCo{8$z&J`L zTReDhWlHSOLoFdOgIKej_Wtq^7G()xCtdb)?(lgM`sxyV;GeIr;Zp1c0n&qa*FKb8 zICZSR>hRN$cw}-5)XUR!WXQ;*dP_ZH5DIMXAcSZc??4EX@qb>K@w^@O`aNS)L-dbE zXDskGZB=HdBzQ5}Zz*YK8OI__RZK5kd=t@s}*Q|$3be1Nl{v0XwaMc4^M)&g9FuIFX1kud^M?a2PSxat2|O z!lCp7HY_}VS+Xp5;R@mas&%BXN24RmDflh?2M zKz`HVr8|eijdj05y9$f(==ofcb4Z(cG79EM{m?~yQf8I|OZKmT*4$MWe* zWc0$U<~qmQ-SO2Lqpgn^!Zkv3^WC(Ztyu%-f$U=Ve5w|R$ zYZFV#LO__4Xvu>)&HjYIgBvg^D2awh%CZmLvsgcDrHW`F?H8+~3(anKX>nq~=l@g2 zgz-V-m?ws#&Is!AFwSpVR~#)0>LrapF*Z+%`l(RduW0lF`nh;SQX*VpE|cg0a3(NFaKgmQ9XDV|vw&W8FxPOsEaB((!NJMS0T}8C zfUysk++a%ysmJ2!op??XrA{son~HNZqc#{W^>C}WWY}iPqBA(E^`W#hVET9wpO67g@OW16-QRv0V_7k9#t(BDh zK=i_Rx7vQRBR2P>yi`E-(rHy30(QyDoeOJ zU&oA$jT1|}7x)JgvyBs`HvaNVz4}dZ@M6?qkhr2NX_$8{KQ~sCD_4&2VK0gliQh{n zVHfUzZ5apd29IB{drZsDWzdHD_MM4AXB=UhPRrqdJh&W2OYQ>ant9)=vDem#y3yO9 zigGL}t9JVaMLk`n325buCDWzZQP?*eD7Y2@6|4(|B9ko{Ijw z+8xc&!i$Ar>v^Sz!Yhe>Y^1T{S_@BW#$F_Np0fZ<3kkT=uF30bVImgR+ChlxX zxhwg7@=L0E@sq<}CdHm#M=3MEeGYRwTlrfdj}XIKZISv#yC7d7_!^bpb7lsxL&0c7 z@oft3y|2DqJU;i(vF8rZSUvHjRvNk9>9A_F{M zp)JHOgpp>UdXHC^(4$72a0t{NIQD+;Wi_5GsBU(?EL&NDT2J{j4&rly8)ST!Yfh?# z^f>8(&{*&COjb?d*nSq9r_fj3)h~4H)sJZZ;**E0LXE#LahPZBUeH!pzDPV&YMU_Y zUrev?Soc2_1%l)cAh+-X!}^wVM>2W?pM2r&n1R)KlkvyDfrt8PU{##OY#}alkMw+A z()sp=OAjedP>oGUHc7EJ!YS0;;&b=DQM&h+Wm|=U`=qZf?zbg*>7^R-Vs+D| zEL2!yud_p^C5hJG{}3mn(4tY*zA!MxesSTj^+J^oixQ1`)Z9Yjqy~NljmI!FGDV{e zM)j;@jEarabgiros8;Z=3ue=XTogX~BN-jYQn|79AHSF0E9rQ!r;mTeM-O1+zPj_5 zYcpw%YbQtFF^v|cT7R6H#5FQWT}~k&m|CC?`Nbu?|AV3u+^~05dmn!s zd&l&QR5YD)Hs8kJATzj7zcTr6q2P`PHNvayn(~H)|MlCwU&PLR1>WV6-Yri*K=Qmw zX}GukTst!LkvwWnV&u{)ASF6)o*gf^<6#R84*d3pr*Y~F{QUuCt37}98b&xO z!hF)`hP7UGJSg;<H?QaM)?+?fWwDu-I3}Z}nIU#itO2q8A zt2}i&NBAK-!Lo8oJ4&lPZ!6z;sl1|Q1UB3!g{E74!Io$;T(Pun>aZ2R7%TKoCouA; zFkd0V7hEEvzc>erq_@I5?lL}*So;fTBg5*e%b&b!^DT1f0X9@5(G-7K#;ql11tBmI z^smVTPx%tGv@rvZl^yUQfO{Rcf3H*r^4IFiXyF6=kcx!Hisk?U^W-{+cSO|`5LiaZ z`OVO5*`U?0anxb8uK|E1eEpe$WQsRczL;%_q@`IgKJ94N0aMKfw})GMqJ080ZpO%Cdk z+)~x%cKAmbx{;@4Uv%LvM`QvoK^6dW6YIcV^NdKpd~n*77z1M3Ovq}bt&4CV=h<#^ zS_x#rdrnmg;;%x;We_urI~Edx;zYRNF{5FC8S_8x@%UUA1*M3d)~&Hg0G+P&!nn=J zZO><>9_&Kiws`B*xD+qn=J7pRc$x|R=OeXlMcqBu}4 zrc@A{C%faEg2_CfUa)d%0A>hbOrUR|2@i{XsHiHM|Ox(KWs*dyr&@`>AIpj2oC&@lOtB4kx$IgA47?@P(Gz?OLmcBnpvA;rKcX zNtG7WwK@)Np?A4y#p?CZPCtENDiF`l9;vN3gXop4jZ>~Q8P&r6j}@YX$RKoGNJ1JE z%1)uHjYuWtTpL6O{Z+x7e4>Eg#gqsf(Q$`JBu}tI;|ZWiV^;GSGxG%2F3-xi`A$Sv z!HI${&O~333m_(i13Qb0Gl1kU@e25wpL;bLX$8~>HVcTsB6-&(P7p!CROCNP{CW*-q zGCcqh#DPjbrOQ9vOD^jqs%h;Z1e96WRr#Yqu80uee4+%H(XBHcYF+HYf*7fi%Z4dU z!j`u3V}Ia>7?QH$iMK5-!Gy|qPhrU68UR?F@7O%|-G1ol{m+}5qPx3J81Y3OGdZ6t zR)&u@!j~nb;&Wq6z3tS$5~VASy?Z_8uba@HScUP9&x@0fJI3v8mj59ow11=K&*FOf z`pGLLpBdDpqR>F&AK$$jaQyHo~T=p(2R7OOuy)}w<^pU7ykTo3>xtPPo`aRsDGdxggYtvB?>9qd%8L+&l19Oe2h& z0E&O0vWBt5LAg`Of`(el2&kv^*pcC1>%zwb^tpd_Jw~32tewOtP9Pee@XQq-T1`wY z78Sy)IiZ&@=wxoOJ>Q{o9 z``*v6Yo-9ae{J*PrCt)_2!o7Zh2r3MohWn#zmUBpBT<`?h{MuzVv93!eP2i-U-m2f zQxG3~nZw6n}mG_ql_p zOs&DGob%V-zB?;rIyJ(HHE}OmoVSu7aHrFX#_!lxLP@Q@@f5Oj9=F(cV8L^#IuY-{ zfnA>m(4Y!LVYJeepQ5|_oMPlilQE}mtao`I-at28tzniRgz4CNB8wA*IwlFvmuzg? z-5VS9-Sp0fOtHafBgPOd`l;>dz*1bhqnmo99wohhb{rinFAxwSoRSqm%=F_DE{X4rY)16oM^Q*>syt9cB1=IkbLOyyuId@w4Iyi6n<_|xw@2h+4)KIA&0no%fw z!p=LqVS4@BsZD|7e^{T{zhRSC{Q!vZYiDd7T++!^J12m&{4&LUaBV*J`*VIOlU2E4 zEdMa-Y0YAr#%yFo+>{rnpn7v-wF-N_yiO=^Ea9`b!Uymi7qOs`$?O_K zK@9zn(I0j}*i$;D49g(){k&z6zj} zL@oaKptn;k_0sP<;LRL(F(-v4$`LNk_I7FhpmNPYk1=1kHc&b3Q3A$>B*(_zfb#qF zd6uOqhg-fLjnk-vb9AtHgXd%ecpsl>j3-&zfkSv^S(`L8Xst&Y>hXZFs&C3p9CFgz z69)L&MGU)mENfKak4&oiw+3G*;t$rA8+(-qta4|J*Z5$XV47MA299%Fe?|lqCNMWmj)beF?PI`&oFR z^MI5-0|0|vl+HV}IUE8><-yJ6_6PQ|3A7+Cp>u`JV*86S1tXI0(`xOsU1*+V1A9yu zV|cJ$0{n}BtoOXR8`zm|DfK{a4c#;j32tdJ32%-u!&q89cbN71z~G$f?S-)whL%Fu zKah!@e7QrHe=%f=uh->#`lT;{R^(e1;atCAU()>I)W1qU&>-zw>M#_!*U(-QDSSE4 z{z8hqKjrxG35LZNAW@zR*&*+BWv;^Q%|~ZI@OantM5I}##0Vd{zdfsJle4e;H1H0N7MkQe0k*lKUB9+O4ccC?}$BTA4vgfLi3oMJh%}a&^ zOVmz?%BF$X3T|xXp@&0@Yzey^NJEP$6`Z9sZEmg((wg9_Y z=yExw;+rEC3qMhrI_ddM-$Z)jBqXdzxF?Jm!TYhD=e(@uD!<7;PykT1?B>1^de5Ox zPZ%YTBIg^SFtt$YFA-S^ApLP||Jyp((Kbq8Vxa)JWm%6Tt< zhNfqaT;zr(d=}w`5;X!wo0BFA>!O>PCYInvBKf`o+u3=b#CbItrB;sE0t}(Vo9%>~ zs}ot|!D0l;b4i)f^#Kl?B?*Vz$p`NQhR26%a}YIVU=OoYC7V(*K*RYAn9PKs1r97` z^sX&=C-Jf4ajw1TdAd7Kz1Y$O8D+mftStado)9U$s;VqS^_u%Zyk0c3n?pK=gt-}Gv z)Ckb|e>$9|-nFp-uIygZc>uL%YFPH=TC9RJ$o&Y+7m)STc)7HnHC2I%cDQQeXAoc8 z5ex54bjEA6sFBITl~HC-KlTVu+;8Bo&t;lAhMip{^`v+RGu~*5T86H>d+4`29|C{6 z&D=!~0)Sa7Q&|(#(YvEBNB1Ne=v<^TmsVZTN!roIwoXlGvI!gx=R0)QDb@R3o?Flm z^{S)(!6I!^ZH0>jpJ7xllVD_!H)OCW`nrm@tOIjykkM=CTvol7+Jwk%eLnj!RJ#;? zNM@MoV#~oyh4kwyXPfM#JR*(QQul4}(m?VyyB44~k5`uZe78v~&MA*A)9R`NUXso7fv)T_Q7{@lG5K^T}X7jcfU`Ap2RfJ~~Qp zb6&vvWLnS?aktH}s-uif42xCJ&cwCsruMIgn`=#4x1tzz?Q~Pe_l5p^Y!&;I1UvBpT>;szhQRyvMm z6*!Fxoc5z~8yAay0Nsu)C17(79FY=y|v97 zN~3w>+406Z$87~?;qS@zhMA9&xmMyBgilev7?Nt0z7(C->okfz)<3c-TuK}ImVM~1 zVqNNL5t~%R{H9o(YG&bEC>rnd8H-wx9CIG>e0(I&gRe(1GMT#M4xR%Ll3bzES3mDSKE(GkWs*Kq#xhj4N6R>4175|4z0 zwrVD4(zZQ^u(h#k6IuOQYx8c&-8-lei2R=mdrzu`naUKVg}1&N$-kK1Zo{aYp7H22 zdz+@YGK94kEEj`+T$$i65e=El-AiS9*6y~i{rc{${3bekLw+m2xq#$1edHwT8<5{v zoE{F3OEHP)3z$;CCbvoJv3n>T8ks6?o} zfOXWHDTV|to&EaiP7HDGT93^cbzPnWnyzr+8GNOTvOwr^y8fe&1c7MtJQ(}SIO~xl zx}82`ufec`)(OmLKm^%=Rm+s@KeR7lQd|-579bqOJ7Oc68TnEO9~Kaoxqq+{{r55h z-*t)H-}ivo4q3Cg+3^Qo7~ws0yOjI&zSlAvTGyydOY=SNUXXvZ z;2$Rxhtg`-bk|0gbMEf`#c$-x8oOVG^$3#zl}qO6Re!_Rub)0w9a`0#>J!eCI=J_5 z+<*&48P>W&IGD4h8j@M-yCaQE^=*Mljk}zAu%kK2$@@xO^^TESHyhRP+ws!R40UuI zu6uL7&CS(}{Scr#arQPhU8=kXy_dWOGu4pbC0uo!DiF@-ZDG>|34MfGdax*KQDU4P z->Gk+SgV{pgxZ^FLSCH=l;MV*2luf|9QZy80h~G{+>v4Hm+(kXtjt!InY_ z8{%A8S~a&fYe&$z)7c+!!bK+^93tUZ@zRHOr8Y#X%a#yXhWeQ!^mtS~?zNz)eEb+= z?UQT?2MTGDy(@{*=u}S&X(NTxu7b=DjF{5t+D_}=R}753EYUBkEDh;X#GyHfufBP5 z@p*R`+cohF&b&mW?8W{&#k3%^pxP@evVj{*-wbwQ~q zPo>VpvoOJ_!7h7Bcu^Ufb%Bgky-2B;&+i@UF~}BG#u=T4!YwEDrARt+rh(JbyHuv~ z?dEJ(nQ(hC6Azd{r(C?8om&Jt;i zGW-Bcm7wVH!5GHHw^zkDps2srXX&D+)k^O{(-CR)eXOTkPr0R59JO}*AuG1fl zMLDE@Hb=xOl0L^$BU;}kY7t)xejRlY3({9U!->rlFDTXjTNbh+Wufk_eEe)KHDV3! zP4u#|u=&q3kc&U)3TPfvC()VOqw2d~Jl(-zcM4dNgm_x~TejA9wdw>E+MZ10H4Y>_+bJ#a zm%aC%5%zj7R~A<4=UzH$nDGj{PPXQa)?({JrG4jpXB-lqdbfjcrp#V!lb)&K64bZSI@Y}vEje=qPNHRRcO{`2hD0Umt@FQ7C{#P%1(a}ZH%^K|r- z-g-*gz4ysOONsR`t|QIko&nI}1*-G$o`s}YN$>lkmwe|#fK^akBwc!&8daj$$mIWd zs{8rFE1;zI>`n^6s$b0OLfs{J-d}$WeL0_jC#duV{ia1ski8Z3fjVE08lC}dU2(ks zbqr6N<{!H=rRzIaN~I{G zZhFsl#QX)As2uUMM=}YP$a$`qalsLWq=${R6Z~haxnPvg!wWS62d}@HeW^YE6HH6x zryC+FKu*?S)t3M0`p3g66%FhfdxpJj&sVt0U!ctN=HLlPwncGjH@Uu-Lf5nmv~;Q5 zAt<6e*wv5EZvy&L1uYD_Al2H0VG&M!ok?81^NyOQrM>Sc zx8Lq-KQQ|ENScQ^JxHhs!NVe(OOaJj?vuWm3NF)7Fg!TeZ2|#I+yQ`D5ue$aS-YLj zZV1DUX;z&0CSNt<)WJfg1JuKW|6aqLB$D6T*P@bM&%rR9>yg71M9`J%hvT?{z1b6f8&x76WEXj~UJ402^o;Y%}=rWHTQkt`D(QtkBX zm9GUtAq-~~qo_=b+lh=+d>Fl;dtB45H^y#-97*K!%NwiT4@+yi3jpqfl(K#0-dQY6 zs?#sq?<9azfRcPYRRnKOqXc~tSkXNQHg5MC=)XMbS&g%1Ate(_O~m@dBGp_4?;!fI=Pqc-t(x~ZykKGtEvFh%+^$#n!CLkt+MjwHJ*qg zz~c%NCY91f!;+xC5pK9b$CeYzd2lE^(clL(9vto`F#Cq<%)<_3<>)>yIhS&7-C$?^(S1d-Pd4n8=EF4n3Ho;Och>_A(+S?DELk$G5CqN-y-mT z17FEWzpHGysa+qTYA!bv4y4A3j%?!yEhS&A^Xg}is?OZcis#B3*Y2%{E#aDvA{vT+ zYnOfg%IR9|@(sYN_Xvaxa@f~>S5-)G*M1nlOD+ezN{cL`T1~u0#nxmE!2WKdMnKW- z>CdLi)^htE+(|C1he_IxOkH*!m=CfAE9xp(dxZMJIMejTTG%ya9Cf*W=`N+Tw?Qkl za!{Dttn89Gn*9UUtR%&;Sp;BnIn3{PfNAz^OdYqW$GlZdpIn5L-UnPGWuq&f(8B?l zt+X~j;N2vpi_?@AZx5dMbo60+#}NO2vw-Q?#5kV6JDQvb;Xr!&$!rpm#99!N#_3eG z$;|u}GvIcYKc{q$RvWXs;3FA*Y+Nca7;{EoXazWd3bf{G&5^n4WFtXtzxg4-GvMib6+; zjOub>p{oAvqoPZ!6O9yf;!w`MEs8Pw7@CBiK+$h|SaCpuh!$NC)t)EeRTaCL*!Ue~ zbh5tzi`jqO(6+@g?%;ea!&7aUc3h2fn;2ef|GeD~!A@qXOJ=9hl}xkUBSXegX)e>} zTP(FUqufnC9c8?EvE_u|{JQW@&!bLy>RH*&TYEoK96%70N)HVQy1|sfB(!Vbw!r1F zG-qJQ%6O(~6Qj^%7S$8bZSdh!0j|gIO%)2-*KVdv|F4TqCyGhNaC@z=d`GbP_bi8q zxuB}JHXJ%_N7)6HVH_BSzsaO%!@Ui-a$xv4bm z%M2q17&@JojnKHVmF0;M$+3(Xzsso6vC$uT6A=aze?@MH1r3?O1on>Tdp`DTks`U# z5H(ty@xIpH28?wT4aV7NApYvz{AdM{;oXt(Wzi=L26p?*TbTq8tQ?AFYPZJUro}HQ z$?vBOAHA_+S%K9t8tQQtR@y*0@|$nZek59p01wdHxt^$m7kLblC*A=J_ef5WY`cK( z?N9qA#GM)eq4acO_@(Xja(R!T_0WONz>xi{7X5iWwRS{RJ@SxX?Bv~JVt60gFA4L5 zQDmd0tN(N9WbZRkx7s2fOyKU$%q}RkM5rE<9ctS986xMr$rS>-rT+`Kn$lC*KS!wiv81H$D@Z7LbV zEnKDdTsEjDNx?=|o*a}ZF}!~9M!dXEHrkwpsP~}^=a#M&ztZr|r%+Vj!-a{9n5f{} zM#BetpMXKW_1mMk?er|y9C`T7nK(jEa>1nsiqqb8@9&gf(oWA6C>g5M2$!?mWHj-T zD7~ZVcd{*+>40U+3v0a=vEpF0b~gos4$BFd1T7S6>So`CntL?ur#uttZ|t&~cW+8^ zVgrtFFaZB>x@oZmPn-|bt~{1`eL*NbZux(rqLEwD#lrt9@t1+xXvl6|0-x`+IH%rR}yx?@U#0i#jOppBsa^kX!#)g0LncEa)C48ZBL1 zS<`pE>YiTfJLx#iU+jv4SSo$A{CQeYoqfP?ID77WU+JXCkB3!NN`#~tqm(9%-B2C^ zigRHxqf0|ql`ddVP9K#<%Bo!qQG)WR4_(%WPoi84x9vN@Awe&ul75o=M_*~8q;49s zRXRiNO#!j6dm_FqN)uBYQNb9UF$2f2vX5?=my3viTw!N%Pl`CxAZ-x8eqe`OaRyZQ zd7_=%0Qx!R@O zk>`Xp>oNGR+g&^NNY6!YFTrD&mS0_DGN1U57U0MyXxYbe{o2$mgp-5+fk+DSQ*Jd0 zGn7-P0?vO|t=hP2%1E$kVc}5m{g&N(bs0A8JG`sAqraA0aAGZ##Pyk&@AWbRzaV!> zb@c7h-p@Z|=vwFm{W|#*ceP>K*t&5iLzX%DIrw7r)RR|l|6&(8csZNAb|jYb_86ZT@M6vD%x1OsZ5B@r56k6xt z$G|gJKMHS^djk6Z-`DqakQs2YsO`=U`*l5zVtTYs8ajU3g>%xf6oK#K1T9zNiqR>o|o9qEW0?Q^(nz>M)sjs ztzBE)KP>zdw~B>!NZm=IKPUq!G_y4)1`af7`Tm7Bcis?H!_NM<+N~GVFOk>+I{$ZC z`t1H%LdqDMQGNP_gyQF*bVSND_uHFJ24VY8B54Zy$BKsq~jkuzgLs zc@Bub&!x#Od@*@56_e?{pb^YjFZxDw#fUQUHdnnlf+@%j`#l!Dq+eY9)?>%#TNE#u|(eD3p`Q*cjh2E^mUKdM^FS zocD$5<;TZ6{`lR!ZGRi%xx4p;=cy!fZh);F4RWrPo@&HkX-xAFVUC7NyhILI*E7g3 zpF#UA2Ty3^ah?)PjwmWM{&nB%tT54qfrI_@z5f=!MFwWGTZOxeDToeA8U3zXA&Fmc zrO|yUF#@zI>CpW7K@Y)*i+7LzaAM$D2b-klYSoM6UNCwL9MPB^6Al=nE4%#5!&bsg zWm|9Mug|t}hRdNlwY)&Roxk3fp~uX%k9H-!>m~F*=_~Of_MA(X>-RaG!`&0Kc!SDe zSY9<(`F!L7HT-9tGjL#@Xc7lRQOLzcgm=jmGq z7RX||GeK0x>$wQaTLmHV{!*h_tWBXP0hfu}I|FdTdGL4sp0uV61DopKZGS1Pq+xBN zZ*b#GAG$ahXNxHw$Mu~-GRMEk?Xr=B#w_%0Y3-c@BV`XEGD@}99rR%S8%Wpgg5G?% zmYj4qSGsEi59Y__$v$kB9h~ehdwp!3b>qmDAB$ao`roO_&wLj{lJUywSz}UOY)|I7 zt#`77iKh+e88;CPYX3;c7PE`H^9MVE>}Y~CO#A{Go^gO3TEIg0y-jPC)K`cY^J3cb(Xq#A|diie?;Q=tq)HS3RPFTgLm*DVmZYr=Ub zJe8Ur%B{#(PT^ysYfl@R!91}TwWT$A_e-Ft{rnq|^xSj;&HF_8!^>au?__#IQ)P{~ zVVj{-Zyw6YMxwE2%Gv^38lX2)-R!X!nemiUrEam(86-FWgr66;C!q_44wmIb#d4=) z8*|^+NfpC@aj%xM2QgSobSceg$BxyeWi%Tl_$NarPLVMiilgLj0&N;`YT+CO#|zG| zn}O0+i2XQHe*gz24wBascRV<_Z&5Sqy`v#tS6l*>i<}T$Q#zT6tx2Q~QB#huU}OnH z2fWu`w5h+Bb9hCYkoyznUcb(4@Qx{8v&ETuTRX_+rF%k-FD@2mG+!3bRD@@Ld5fkS zw!MRU>vm||Lr@$vwiR=VmA(%G;4kS)VJcdtO|iR1kr_F7hrME~QSB3OqpEgs7tDW$ z_)?#Hd#iRNI_`sbvtP!?WSdkBU*o&|f-3birP2ej3Tu3_1f=*)Rm@}uC4=&njK*mM zQ;~ZqxWhwnh|IarX1Z^h+Zso}JOicZr5N|2%S0=)i;uAQgMz}l#yd| ztdycFW412!A6)w#3Q!KlA4S<;qC%dMGNsMv1#1P;Kpcl|73!pu#MGB!Xk%4 zd6|o#d+2_S-k;u#5|Ewi0;cB3M}B0*y7&O4Fd-5`!Vz%&ds8?(Z2{?`2f63$A-2&! z2RfF##fmn6*&zhY8YliAre%5aq$QJWC=yk|(3p!m4(U820sJ35YiL7_FGk&R4ZT*U-T@zp<@k*Ey zjAD#dOU!D&!NpShZdbt@Ks-w|#98UxZgR7+F>^^JWCp(UovWC7Q3l2EBPQhBY`Id<`PgGxX{3AcZ^*-_PShDqlz!In2Ik37-E zonh>D78d2j9iS|jeBF-UuFFu*Wv+laO79?)TL?!AMZrD#%$5 zG)EV7#sCShJ=LkO(p17h#8lA_i$W3eay$KY4Qnsq1pb!3XjR7UaE^SLtrMJs>A_r? zyvlUSw^iAymWM+DgAK6i`4wJ4otyy7_jEm9yLBNg$U4R=Ml?HNF6@z^2LH6vfpb4# z$-20n{2#l`P#eeRhpjJ1rviB|^MUVSbVA`Zhgg=frl?qD{&=V0ER%$4J8R0Pb3tjh zXtmyj_k9K_PDj;eq6Bb>;TIo3o2e^mpD430qGMj%TEb{Vl9zPC#C~dgF`m3k_We;J z&^fKrgy+P$d(B?7a8qTbFnI4SauFm~4{d~aYFqv?N0OEt9HEGd)i-T2$W5jQ(0F$d zJTL9~omrbGCKGYOyo~_&DgABYmzn8q(HHP5<3oPtTaQ51shP1-wI!oPWg9|HdHL1F zi$unNKykMdcd+!YhE~V+Pd>gheX8pOsW!tcWjm`Rlk&dKn)_`=#BEJCkL`$dz#mz< z3ltg;*6AF9Y5^=J{yceJG&=U!ev5AMS7UL4*^6LL7lgCZjGFaO@<_%U=Dxs*y_#+z zB=)yZz|n8Ov0Zx6nZUv6=z4eLa&bTA5x+#06nD%r+!_k{ljQwTgY+fV)?;6_XbU_X z2_p&Bk`!PP4+LwI%BM18`gNFvTpC4|UpeuKc77zMW)yjl1oWX?U%?}9e7ElZ`5VI+ zS(Vf9y5h;57nO33GS(U$#U-7zvSu_w%RELsD4OE)71-V=)N@4H#)V<~2^mQ6*Z))@ zT2NAM5~BNq-lx44Gi;U#H0{=Sa9QLCvPYq1IHtG#qr8n`AQ^e-H9eHaV&p}>@3s6p z#@u~~y=Hj=TLwM*-i7BExE>CA>gap?h4{BNLz=cy40_rLx(~L49t@wuZ9gtms3t}c z9q9P*;~$`4ri1_rqJf4%Nvx^*U0&q#?#(t6+h5^t`cmlhk1v$XG-J}dTXJgxgfdWU|0k6BBB4xnA$?olS5Z~WbnTs> zwVIY&+ic$+&$noN@?2~`^+MKEx5;T?=G%yL%1)x2O7c zME_AX3d5s!TFvG(#*9^e!5c;os`*+w>5Y4RKE74>nnc3VcJ4YikdI0dq>Cn6Z0g+^ zWXu!M^)|9`qR){g8~`%pJn)Tg0~}m@s;Nwx!T(keBM&P$ym0Is{Bs~tI~>30uDE+D zI#Xb`aIOV67Ib9O&&o$wyFo)AE9oscX-aBFl^o&RB9DTzVddO?AlK(s4u)K#3bLD5 zdEY7V7vj{>pU%ZgNSS#!H58q0=!dZSO@Kg}f|N(=(kFAn3h0+o0qVdWQ4|bKeDB=? zI=Ft&hE5=zu)4vysRHJPGUyo7{VLE`#b>P9XL7YgAquUPbTRhd*<1pIV5r^15F7;D z(!pQ|X?Y4bqV|H}kq9Y}Bo zz;LLVrFZg8>W6YG_~@X1aouuj+ay>g+uB_|DwWwh#q+7toMQ# zBVjfPV9izb{yh>k>dCpUWt1twr^$yy5&B7J(G@BPg6^L$SDs_{or%>;x(iA5Iq2=D zuOxWwX9rRpQ=F3wytUKY&iI-B{f0+L0KQ1)bbNjttsTXMtEB7DxnoODW>dYj_aJ?a z{9g*|JV;l^9X(&P63&Br_06OsA;KzfPY@d%bFhRa6a)?N00tP2@7Ai4I54QL|QB>tbAU*@=h=XjG}5a z8n(5s3r?0iDX`3q6T5Kz+tV`nA&s~8-KORwZ6npmR9`!2zVVcQEbErm*Yq13fm}RG znju}_FGuodx3kR^IpD(CRWY28vlapY^&#u9Q~qS<+?o+w$p2XrDu+l z%tl5*nD&M0u(;zq%)FW<{um0~*{hU&bf&0*owr93+RDMp{9XaRvZS={Ro5Oyyl56YiOZQWZlaQe7cQQtPUzK-=iyn}bUw6;7L zTLqxB5L`(nZiRliTc5Pu2%d19?LPd);lhHgB0UMQZRG6xTxt3Dq7J4PH{0W+2iM<|&Qk2xUH&~@{5kj*A5Hqo>VIeRnD!%U zDwDr-J_y;r#Qg%eX#fTf3!K~p#0mT}q9^pW{>wlEc${=Jx$-|@kHQ$OPZ~-mlW_H- zgR!$0p#0_cCLLb zL*Ixw*yB4&OgXW-jrni>Em1ry5xwAkKbx(yb`dpZLdt_ON?e&211*?nm%lyr)glAw zoRwvzN7H3cF{mOQ%HEq}{@;|EdpA5lxVq2RvaJU&#x#Q{mEQ~s^Jadofq2t8x{Tnw zh&&R!^|*7{d!x|#sOj%pzc(D&AQ^F~D_ep)GfqYj@L_^Kz=c=V$ZMO#2(|YDY~D-I z%kW3^T?B*-{10|`6yEmONB2C1e~XSW#GPKhU%}@RFrdsLF03>8-DDM81L+lwbAlEA(+&o(|6{ zlY1g`ogi17SB^qgXJ1U+TC)tmd(GU%9&c>fzmm9viy9-42IQ}Eayn(!9^0u;bLqsS zE)H&PsElvNNWivZ7W4`lHI)4OeK`6GNyyE+#U6e8Pnolwv7Q%8JMROW?a>E;I1Ben z(XAbn)v)L8m>a*rl`{KUAI|E_+^0vjp!sG55LOF&Zu*}O*i8@MyRBzQGW7Rxc=BFy zO+$tUMx^*71mx73(}5@fGzi}>!ojsPC^NhkdFuMI#CSzC$tcQ*dFvdFA?!vV0rxfT z?~e>ZQ8`hzq(`37TIVaq@9YYFW}X!>8YvxRQ35o6$2!1wzi;P@?p@-&4Q3x1*R-uu z9WRTVC4GnPt&0^yx0Bu+I4>!)NKsq8BHX*+8wD`$&PYnyO6=Mg>~LRbC0ZbMKlsLr z66hS02C4b~|+&oqUtSJMNp<`}`-{^-ApvJ;01rv+)7m7O2he>p=h3s>95gW}VY zq|`+w#{EN$q~H-2&hG!j2fIKv$-vr2a{El)RGY^rp^qe%h&S8Mn2Es#HSDv3DN7aU zxT~Md1v|STUrp@v-r4}mh;OetHf%+d9`DEq74|oT_PzvyhH@lL0P{^BA{IFh(5N>| zDY#TMTWV`z0Sz;J!5Qiect}JR%Hb6v6M|-Q{^QpNKsJ4;o<*u0qLJ2U(E_}b3eZVc zf;*`SF_ENQUzt7+H&#Zh^zfYOu49#xH4I3=t@_z%Iso0*`vLFbdsp(w=sM>-50)n9 z1YfvV&63WMiG5iWrc!LS^QRo!F1w$Qk^JbzTiTwAP(S3c6+Ur@FQYgp*AfDLy+jcI zhngEVkPu*V{vym)n5E~lznJhq-S0`%PPpMNhx2IywmSgrRGcS4Mu}mz?vSWSJ?EVU zmjBB4@>P4Xu$K`i82q^d(LA!G9L|nWh%jw=PnT}fQ-*;SR#p-#f~KmKFg>seIK$TU zU(au#$4`2QA7ojIMz>5urI+o;wYhk3Gt21FOLDlcB0c_>Kqm!ky#byHG89pvC;vM= z3{T#P|4?%7#HFzWL&TXhn7QkS`m}h#r#Am9g^ze9m+lFQ2$0g6Is;&;FA(U{C7c=SCM+n8?+B9PV`IHvqAy#93u z;P7w#(ALj0w-u}>8*lt>fib7dXWRtRDU}!kzp_UXVo9q4u>)dh71UCL zz(3tr8j6_65l7o$?dh(96kBMUQ1#;tRxU*BGX}e{)O4`-JBMJ=Ev=PiiOGl) z3cMCNj)5S*5Y%N%*a^45L!tH?gCHR(-5q_`7e-$7dH6#&pkJRXKl2f9L!!|;cLf}! zrQAGo=(#JiB`N11+$&9_%T``Ld0U(Lf12!F`wlxIM14jFHYTmdKOzR7ij_PC|_`)(h&XoT=OlWl2ojUzj6 zEQRWed9jUb3!E%m8iYML2PTlxpWy&#cgWe5e@LCP24y{B5uq|U^uu2e()d0cDdKNm zd6BaJ=E3#pqrBtuBQXklp&*rDaj8TQ+c0*<~E4!-Wcw-tjCrXdb*cG|l+0I>!t%2OBhuY%&h3;{0)i zn7X>xN(4k>x~dB1mqS;L{MRqmuW05PzZII0CE##BuDUpJ3hvFgv!MpMw%3|X_xMAE zIZpjARjIZs5+H1{{e&Q&WM#ov#WpO$Lfmg?|Ef_i1+4)KbJXJHgHZFZe)lco#BPSJ zA`TELQzq8yol@#EaDFxan(7dPNza2EVL|W`x-(_U9fm&n3SPtO(&ef_jrx@c1u?0W zX+`gW&R6C*4H-cqx7Xp_9gr8chB3@ZfL;p(CUdR*n23L z`6Q!0h#U_YX?s<`fXP-hHP~B+gK#0vZxba-S8mQHPW>S!V1#s%SY-3b5=48iHDHL& zaqu9{4N+vk%K&gS=QbbCtPrm>7mERK=9MhuPpiWR?^W{9QXD+qAj)-_=V8OXx09?L z`uAwagb>6}>i6XTRgXO4guFM8vAHq~+{zyGpF|u>L^^^G_~UG)0$|JCTv+R<+=zOpe_%v#?XXmFFn27pgs~A|7-7`sZ@P(flVJ}= zXvWUH0L0(&fsde9?a7BFmL`9$Eq{nh3^78b8pU46(4PW;}5Sjeb zaG7;d+wnceuf^y=X&d47=E&2nfb4PL3-jAbPYSngj@`n6G zSqLm)&oXCg4WUM-e9mKff-GY(ImTm6vk1G$Q4P`#>6&7b`Xkels1)JM{GnnnvilWIXZvOx7uF& zo4;n}pYQqkJkRrf-tYHg%^#>TK(S<<6V6KW^)*1LhA=nj7u^?5%WS^c*l8iSob~qo z`7Q$1Ltp*?>2H}v7evVQbFg-2~j6d1Ov#N_tGL0 zX*2epr+{;!vxb1>i2P%rEqO*GF_lJPOi}ARp@f|TI%tF+FW3U0Ny_$ja~Jf9a}*1D z0#%D?72hJ8NOH(ZHH|WdJM-Ss`V`>Nz0n~qwnlL7UV8;B(?e3RyLcXbOg=T+MOluK zr-&NQ(3*;tZCX#bc%tp<*!Dk^n@}nV%Jl7y$I!*UOz)l9rP2*E2v43$#;V4gNdIYL zqS^WHshS9>ot!hc<&ZToEegRsZ3HV-v_M{q9~U1qthgs`hA}Y6e8wFT*&1damf~si zRKooSOLiJB7$&n}7LD?wlPQiW& zswH!`l@~N_bMudP?s7ipxkZo0yTivhV___om&vb<--f><`fG%(^u1nG7 zXcUchMltF^^WTEP7ZNndtW{n63u`1koswnAB}=EoWNMx{q@f;-9xUX|DnZR^!JYj>_0<%KRg zI_QaHLGdg6g?grjcW8dL7I@IqC#V@?8@#cc-?!>4Igc^h)cs^`RKajWr{p zhzgbYhcRuBbZFA-*UQ(d^>1ORVK^ED)+!$u=}A3QuQ=s^rp}Hm@o!8^mN8$7vPYr5xU!UPobXDJWOL z-#_j1x~Ax5$Zl@%=nku=8j+>J`_2`d`KA<1j)yl#LvYO+B2^kL)3VWWr%hzt9|49s z#Gc`;0~65htF>9k7nZ@J$J=VTLO=*DL*zg%bx+oLGWL}=u~PEX*4sXsiq zr=Fn)kY$pKs>8(Ds`E!K7r4f1U+p6}$6=*L^y(X0{<$C)=Ek_#68d0ycVNrZ%z-JS zpf2n}u&Qdgr-+TmSyjY45nA#OdiPZt`h};upG$LI)ps!aT4wod)8-X#g%$2i=sum7 zz*TQGUkLk?fP?X~>q|A|*Sn@plkZqrCA-+|UriibQnyyWsJZ#&mIHuD^$`#Lxc2`P z70lO|9_cC&AB?1thM2$!M<}&7A#cumBXeJU$!YT@r;51Y^hA5rd<9M;>efvOmu+fj zvhk~R6t6%Bx(;3HvlGB-U8Wu@SH>((vD4zKK%;O(*LuwP`#Xfqh3Co)zP1&ftJ(i& z&#WayQxC9xhwy5D;rSmh%z!O(S4#OrJ0B13&##vmPMd@bDo2f}7@T{)X8y(TBN32k z79?b(D;Yfl)1vEfW4Q2Vg^LvPO>+7@d{U7Y?2MCTRex260Kdz3H0#K|FTl3nzoNHs zd>-Znvr7xfxe6e!E^(k*I)`?c*ZBBlC>gP3+JUE9z|lS`V$_1T=uLeY2bcM{ZC;r8 z%rB6xCnWy0?`>XXZ%yg!C#-N{)6159bu6ot^2Y79tFqhhKXyJDs9Kk_iQ~v}DIvLU zc@H$A?tNAY%fp9}scBym{FXue zz^COpN#1b52vQ4Uw}OLyYnVS;%;h`>x(yNq9q)jf!`{B^qu^-{=LAO4E|-j>%f@)T zEXzy2MXp-;As)Jqcme8K$L&Z<#KzFxv~*J4s!TKH+l)` zq<-+-?$@mCA6}t($ouK7iJHECP=mPJNIO|)cWw&y-dt$)$RDOimy^(w3+_+vu? zV(YGXUu^fKkMHdK$#d(sOD27SqO4lp9SjVV(81i>ff#9e0x-6ET>vMY1Zh5pJbDjC z`q-)KV$7uOT+!@Q3c5KYNis-|Y(!jyB0vd#p{McDE0}Kmc&Nywb3?KKTVvtfeYPu= zn(hh6DNOK-%Cj`3Czc6unKq^(eEo_R%L`(c5~~3#pO7*Cl}(6wSdACxN8Z{P zy|b(LCG-lRuB?Rz^z0ZA%1C>>(O*2f91C^DJ$C^brZChwhf)pj1VY3lP=dq2R9867 zrc2T`Fz#cUPf;b*2=;u@wVI7djnHv?j?}EP_VxuBjk!HHNG#S5vF2_B5DB*HS_hj! z3yvA#0T6aLOt9T_uqsX?5f;If{&x{zuMsk~r#2tJ0GxD}D|KQB3|T6Fk~Zs;LvL=F zv)wqn0PKstR8>zjAMxsX1LLlz!2AF3gG`Go29PrfHAEm=_i=Kyol7^S=`!)z@0U5B zPCkXyx6&W2e=+O@By9#!V#z0|HP8r@G1Y1Xw5i(Bn{_571cy5@4JGYb=X^@cxo59K zU#_VeI&wFHoFl#&OfZ=UNY}-=S_SvqgGgP&)t5#rXol0u$m-hT>VqFuF-*U>_jrU1 z8zn>L;(0OBJF-3FW;5KmIkAAW%g&)B!^RVXs&Fkd_s5%7a=N5+|IGle^{R0 zW71>TL7qc-J;l>Dwe(uF7YfwE$BL5lJLx^oNJAn3fjEe=%JBw0AKz^sgv+EQEH?Ab z=1QXIw#HV3RX_5OHst-79TOaZbIl@B(Q#ea@r~XA#SCHe+Mkh$9xEO;29e_`#ywRU$dqTSvRQoN(jh{t7T)$$PVgFYZsgVa00cxhT#tOlhQQs?9HecW)R>NvUDT zIL^qqQ|$O|`A(I?>fFP7wlZi1Kk)1+ny9k#lsVLE#A=MimxBgFIbkolPhwA9Brx?c-LqkM<0+foCsLW=OU zZ-zx0p+d$rq_~Y&n+DM577)Vn$1+n`hlxcnrOfZbf zbGx|z$iI8dE?5!Tm@7}d|Ng4P{PCSgTKpo0ig@*T(wCbn2A@6VHuQ2c_xS$-lc}aZ literal 0 HcmV?d00001 diff --git a/docs/net-comparisons.md b/docs/net-comparisons.md index 65264cd376..4dc1ffc0eb 100644 --- a/docs/net-comparisons.md +++ b/docs/net-comparisons.md @@ -1,6 +1,5 @@ # How is lokinet different than ... - ## Tor Browser Tor browser is a hardened Firefox Web Browser meant exclusively to surf http(s) sites via Tor. It is meant to be a complete self contained browser you open and run to surf the Web (not the internet) anonymously. diff --git a/docs/project-structure.md b/docs/project-structure.md index 7c06c70f85..61c63c2914 100644 --- a/docs/project-structure.md +++ b/docs/project-structure.md @@ -1,8 +1,8 @@ -# Lokinet project structure +# Lokinet Project Structure this codebase is a bit large. this is a high level map of the current code structure. -## lokinet executable main functions `(/daemon)` +## Lokinet executable main functions `(/daemon)` * `lokinet.cpp`: lokinet daemon executable * `lokinet.swift`: macos sysex/appex executable @@ -10,14 +10,14 @@ this codebase is a bit large. this is a high level map of the current code struc * `lokinet-bootstrap.cpp`: legacy util for windows, downloads a bootstrap file via https -## lokinet public headers `(/include)` +## Lokinet public headers `(/include)` `lokinet.h and lokinet/*.h`: C headers for embedded lokinet `llarp.hpp`: semi-internal C++ header for lokinet executables -## lokinet core library `(/llarp)` +## Lokinet core library `(/llarp)` * `/llarp`: contains a few straggling compilation units * `/llarp/android`: android platform compat shims @@ -49,7 +49,7 @@ this codebase is a bit large. this is a high level map of the current code struc * `/llarp/win32`: windows specific code -## component relations +## Component relations ### `/llarp/service` / `/llarp/handlers` / `/llarp/exit` @@ -82,7 +82,7 @@ node to node traffic logic and wire protocol dialects * `//TODO: separte implementation details from interfaces` -## platform contrib code `(/contrib)` +## Platform contrib code `(/contrib)` grab bag directory for non core related platform specific non source code diff --git a/docs/readme.md b/docs/readme.md index 534a19497e..25e4b21ade 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -2,33 +2,25 @@ This is where Lokinet documentation lives. -[How Do I install Lokinet?](install.md) +## Contents: -[How Do I use Lokinet?](ideal-ux.md) +### Local Environment Set-Up + - [Installing Lokinet](install.md) + - [Using Lokinet](ideal-ux.md) -## High level -[How is Lokinet different to \[insert network technology name here\] ?](net-comparisons.md) +### High Level Overview + - [Lokinet versus \[insert network technology name here\]](net-comparisons.md) + - [Lokinet architecture](architecture.md) + - [Lokinet and DNS](dns-overview.md) + - [Limitations of Lokinet](we-cannot-make-sandwiches.md) - - -[Lokinet and DNS](dns-overview.md) - -[What Lokinet can't do](we-cannot-make-sandwiches.md) - -## Lokinet Internals - -[High level layout of the git repo](project-structure.md) - - -[Build Doxygen Docs for internals](doxygen.md) - -## Lokinet (SN)Application Developer Portal - - -[What are "SNApps" and how to develop them.](snapps-dev-guide.md) - -[How do I embed lokinet into my application?](liblokinet-dev-guide.md) +### Lokinet Internals + - [Git repo layout and project structure](project-structure.md) + - [Building Doxygen Docs for internals](doxygen.md) +### Lokinet (SN)Application Developer Portal + - [SNapps development overview](snapps-dev-guide.md) + - [Embedded Lokinet](liblokinet-dev-guide.md) From 620f916e65ba8a99af4a06f9aafd3abe33209ee0 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Mon, 28 Aug 2023 10:17:31 -0700 Subject: [PATCH 009/312] Bump oxen-libquic to latest PR's --- external/oxen-libquic | 2 +- llarp/CMakeLists.txt | 2 +- llarp/link/i_link_manager.hpp | 6 ++++-- llarp/link/link_manager.hpp | 6 +++--- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/external/oxen-libquic b/external/oxen-libquic index 0fdbb2c8ad..7a24ed3d08 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit 0fdbb2c8ad20a729979465cf3c4f625c9c88fe04 +Subproject commit 7a24ed3d085202f0b2381f149670b602bb3515fc diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index a6e2e59f17..cc96712d21 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -333,7 +333,7 @@ add_library(lokinet-base INTERFACE) target_include_directories(lokinet-base INTERFACE ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/include ) -target_link_libraries(lokinet-base INTERFACE oxen::logging lokinet-cryptography) +target_link_libraries(lokinet-base INTERFACE quic lokinet-cryptography) if(WITH_PEERSTATS) target_compile_definitions(lokinet-base INTERFACE -DLOKINET_PEERSTATS_BACKEND) diff --git a/llarp/link/i_link_manager.hpp b/llarp/link/i_link_manager.hpp index 3e9d07456c..7ee5462901 100644 --- a/llarp/link/i_link_manager.hpp +++ b/llarp/link/i_link_manager.hpp @@ -1,6 +1,8 @@ #pragma once +#include "endpoint.hpp" #include "server.hpp" + #include #include @@ -20,7 +22,7 @@ namespace llarp { virtual ~ILinkManager() = default; - virtual llarp::link::Endpoint* + virtual link::Endpoint* GetCompatibleLink(const RouterContact& rc) const = 0; virtual IOutboundSessionMaker* @@ -38,7 +40,7 @@ namespace llarp /// return true if we have a connection to the remote and it is not a relay, /// else return false - bool + virtual bool HaveClientConnection(const RouterID& remote) const = 0; virtual void diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 939cab70e9..5334f3fde3 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -23,7 +23,7 @@ namespace llarp ~LinkManager() override = default; - llarp::link::Endpoint* + link::Endpoint* GetCompatibleLink(const RouterContact& rc) const override; IOutboundSessionMaker* @@ -40,7 +40,7 @@ namespace llarp HaveConnection(const RouterID& remote) const override; bool - HaveClientConnection(const RouterID& remote) const + HaveClientConnection(const RouterID& remote) const override; void DeregisterPeer(RouterID remote) override; @@ -141,7 +141,7 @@ namespace llarp // Network's destructor, so we need to be able to destroy it before this class. std::unique_ptr quic { std::make_unique() }; - std::vector endpoints; + std::vector endpoints; //TODO: initialize creds std::shared_ptr tls_creds; From 0260da6bd99f307a804b43d41a95c2a0d4732c78 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Mon, 28 Aug 2023 10:39:40 -0700 Subject: [PATCH 010/312] cleaning up after tom --- llarp/link/endpoint.hpp | 3 +-- llarp/link/i_link_manager.hpp | 3 +++ llarp/link/link_manager.cpp | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/llarp/link/endpoint.hpp b/llarp/link/endpoint.hpp index 5c1f506204..88abe0f2de 100644 --- a/llarp/link/endpoint.hpp +++ b/llarp/link/endpoint.hpp @@ -9,7 +9,6 @@ namespace llarp::link { - struct Endpoint { std::shared_ptr endpoint; @@ -17,7 +16,7 @@ namespace llarp::link // for outgoing packets, we route via RouterID; map RouterID->Connection // for incoming packets, we get a ConnectionID; map ConnectionID->RouterID - std::unordered_map connections; + std::unordered_map connections; std::unordered_map connid_map; }; diff --git a/llarp/link/i_link_manager.hpp b/llarp/link/i_link_manager.hpp index 7ee5462901..4ec86e80d5 100644 --- a/llarp/link/i_link_manager.hpp +++ b/llarp/link/i_link_manager.hpp @@ -18,6 +18,9 @@ namespace llarp struct IOutboundSessionMaker; struct RouterID; + using bstring = std::basic_string; + using bstring_view = std::basic_string_view; + struct ILinkManager { virtual ~ILinkManager() = default; diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 1977907728..18a401e9d0 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -72,7 +72,9 @@ namespace llarp for (const auto& ep : endpoints) { if (auto itr = ep.connections.find(remote); itr != ep.connections.end()) + { itr->second.conn->close(); //TODO: libquic needs some function for this + } } LogInfo(remote, " has been de-registered"); @@ -186,7 +188,7 @@ namespace llarp { for (const auto& conn : ep.connections) { - if (not (conn.remote_is_relay and clients_only)) + if (not (conn.second.remote_is_relay and clients_only)) count++; } } From cd7498cb5a1e648ace4cd86fd50cc7b23ccf7538 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Mon, 28 Aug 2023 14:59:06 -0300 Subject: [PATCH 011/312] Bump libquic for oxen-logging fix --- external/oxen-libquic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/oxen-libquic b/external/oxen-libquic index 7a24ed3d08..1df9b9d8f6 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit 7a24ed3d085202f0b2381f149670b602bb3515fc +Subproject commit 1df9b9d8f691524a67369703aa530e6f8544e873 From 68e8abc234a5e7499981f0ee11ec7970437fb51e Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Mon, 28 Aug 2023 15:01:31 -0400 Subject: [PATCH 012/312] bump libquic version --- external/oxen-libquic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/oxen-libquic b/external/oxen-libquic index 1df9b9d8f6..0f2504f7a2 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit 1df9b9d8f691524a67369703aa530e6f8544e873 +Subproject commit 0f2504f7a2bfe4803e62cf7a9161806b0718ee5b From 450121734ad5bf4a1423092a5bd6f7d0ce415c47 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Mon, 28 Aug 2023 15:07:39 -0400 Subject: [PATCH 013/312] liblokinet compilation issues from implicit ngtcp2 version bump Note: this is compilation-fixing only. Behavior fixing will come later with combining the earlier efforts on liblokinet with the new wire protocol changes. --- llarp/quic/endpoint.cpp | 34 ++++++++++++++-------------------- llarp/quic/endpoint.hpp | 2 +- llarp/quic/server.cpp | 4 ++-- llarp/quic/stream.cpp | 2 +- 4 files changed, 18 insertions(+), 24 deletions(-) diff --git a/llarp/quic/endpoint.cpp b/llarp/quic/endpoint.cpp index a8459b5ec1..39d31e9b13 100644 --- a/llarp/quic/endpoint.cpp +++ b/llarp/quic/endpoint.cpp @@ -98,19 +98,15 @@ namespace llarp::quic std::optional Endpoint::handle_packet_init(const Packet& p) { - version_info vi; + ngtcp2_version_cid vid; auto rv = ngtcp2_pkt_decode_version_cid( - &vi.version, - &vi.dcid, - &vi.dcid_len, - &vi.scid, - &vi.scid_len, + &vid, u8data(p.data), p.data.size(), NGTCP2_MAX_CIDLEN); if (rv == 1) { // 1 means Version Negotiation should be sent and otherwise the packet should be ignored - send_version_negotiation(vi, p.path.remote); + send_version_negotiation(vid, p.path.remote); return std::nullopt; } if (rv != 0) @@ -119,14 +115,15 @@ namespace llarp::quic return std::nullopt; } - if (vi.dcid_len > ConnectionID::max_size()) + if (vid.dcidlen > ConnectionID::max_size()) { LogWarn("Internal error: destination ID is longer than should be allowed"); return std::nullopt; } - return std::make_optional(vi.dcid, vi.dcid_len); + return std::make_optional(vid.dcid, vid.dcidlen); } + void Endpoint::handle_conn_packet(Connection& conn, const Packet& p) { @@ -198,7 +195,7 @@ namespace llarp::quic } void - Endpoint::send_version_negotiation(const version_info& vi, const Address& source) + Endpoint::send_version_negotiation(const ngtcp2_version_cid& vi, const Address& source) { std::array buf; std::array versions; @@ -212,9 +209,9 @@ namespace llarp::quic buf.size(), std::uniform_int_distribution{0, 255}(rng), vi.dcid, - vi.dcid_len, + vi.dcidlen, vi.scid, - vi.scid_len, + vi.scidlen, versions.data(), versions.size()); if (nwrote < 0) @@ -236,19 +233,16 @@ namespace llarp::quic Path path; ngtcp2_pkt_info pi; - auto write_close_func = application ? ngtcp2_conn_write_application_close_versioned - : ngtcp2_conn_write_connection_close_versioned; + ngtcp2_ccerr err; + ngtcp2_ccerr_set_liberr(&err, code, reinterpret_cast(const_cast(close_reason.data())), close_reason.size()); - auto written = write_close_func( + auto written = ngtcp2_conn_write_connection_close( conn, path, - NGTCP2_PKT_INFO_VERSION, &pi, u8data(conn.conn_buffer), conn.conn_buffer.size(), - code, - reinterpret_cast(close_reason.data()), - close_reason.size(), + &err, get_timestamp()); if (written <= 0) { @@ -318,7 +312,7 @@ namespace llarp::quic if (auto* conn_ptr = std::get_if(&it->second)) { Connection& conn = **conn_ptr; - auto exp = ngtcp2_conn_get_idle_expiry(conn); + auto exp = ngtcp2_conn_get_expiry(conn); if (exp >= now_ts || conn.draining) continue; start_draining(conn); diff --git a/llarp/quic/endpoint.hpp b/llarp/quic/endpoint.hpp index f49460593a..010e15c415 100644 --- a/llarp/quic/endpoint.hpp +++ b/llarp/quic/endpoint.hpp @@ -185,7 +185,7 @@ namespace llarp::quic } void - send_version_negotiation(const version_info& vi, const Address& source); + send_version_negotiation(const ngtcp2_version_cid& vi, const Address& source); // Looks up a connection. Returns a shared_ptr (either copied for a primary connection, or // locked from an alias's weak pointer) if the connection was found or nullptr if not; and a diff --git a/llarp/quic/server.cpp b/llarp/quic/server.cpp index ebda2bd400..03aa2f9c79 100644 --- a/llarp/quic/server.cpp +++ b/llarp/quic/server.cpp @@ -31,7 +31,7 @@ namespace llarp::quic { // Invalid/unexpected version, send a version negotiation LogDebug("Invalid/unsupported version; sending version negotiation"); send_version_negotiation( - version_info{hd.version, hd.dcid.data, hd.dcid.datalen, hd.scid.data, hd.scid.datalen}, + ngtcp2_version_cid{hd.version, hd.dcid.data, hd.dcid.datalen, hd.scid.data, hd.scid.datalen}, p.path.remote); return nullptr; } @@ -42,7 +42,7 @@ namespace llarp::quic return nullptr; } - if (hd.type == NGTCP2_PKT_INITIAL && hd.token.len) + if (hd.type == NGTCP2_PKT_INITIAL && hd.tokenlen) { // This is a normal QUIC thing, but we don't do it: LogWarn("Unexpected token in initial packet"); diff --git a/llarp/quic/stream.cpp b/llarp/quic/stream.cpp index 93f297068b..0ddaf73721 100644 --- a/llarp/quic/stream.cpp +++ b/llarp/quic/stream.cpp @@ -326,7 +326,7 @@ namespace llarp::quic else if (error_code) { is_closing = is_shutdown = true; - ngtcp2_conn_shutdown_stream(conn, stream_id.id, *error_code); + ngtcp2_conn_shutdown_stream(conn, 0, stream_id.id, *error_code); } else if (is_closing) LogDebug("Stream is already closing"); From 99be31b72fdf238f2b7215284007626eb9532eb4 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Mon, 28 Aug 2023 16:50:06 -0400 Subject: [PATCH 014/312] compiles, but does not link --- llarp/CMakeLists.txt | 3 +- llarp/link/i_link_manager.hpp | 58 +++++++---- llarp/link/link_manager.cpp | 117 ++++++---------------- llarp/link/link_manager.hpp | 34 +------ llarp/net/address_info.cpp | 2 +- llarp/router/outbound_message_handler.cpp | 4 +- llarp/router/rc_gossiper.cpp | 7 ++ llarp/router/rc_lookup_handler.cpp | 6 ++ llarp/router/router.cpp | 60 +++++++---- llarp/router/router.hpp | 1 - 10 files changed, 137 insertions(+), 155 deletions(-) diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index cc96712d21..969be3894c 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -236,7 +236,6 @@ add_library(lokinet-context context.cpp link/link_manager.cpp router/outbound_message_handler.cpp - router/outbound_session_maker.cpp router/rc_lookup_handler.cpp router/rc_gossiper.cpp router/router.cpp @@ -515,7 +514,7 @@ target_link_libraries(lokinet-util PUBLIC target_link_libraries(lokinet-plainquic PUBLIC ngtcp2_crypto - libquic + quic uvw ) diff --git a/llarp/link/i_link_manager.hpp b/llarp/link/i_link_manager.hpp index 4ec86e80d5..41dc83ce71 100644 --- a/llarp/link/i_link_manager.hpp +++ b/llarp/link/i_link_manager.hpp @@ -13,6 +13,33 @@ struct llarp_buffer_t; namespace llarp { + + //TODO: do we still want this? + enum class SessionResult + { + Establish, + Timeout, + RouterNotFound, + InvalidRouter, + NoLink, + EstablishFail + }; + + constexpr std::string_view + ToString(SessionResult sr) + { + return sr == llarp::SessionResult::Establish ? "success"sv + : sr == llarp::SessionResult::Timeout ? "timeout"sv + : sr == llarp::SessionResult::NoLink ? "no link"sv + : sr == llarp::SessionResult::InvalidRouter ? "invalid router"sv + : sr == llarp::SessionResult::RouterNotFound ? "not found"sv + : sr == llarp::SessionResult::EstablishFail ? "establish failed"sv + : "???"sv; + } + template <> + constexpr inline bool IsToStringFormattable = true; + + struct RouterContact; struct ILinkSession; struct IOutboundSessionMaker; @@ -25,9 +52,6 @@ namespace llarp { virtual ~ILinkManager() = default; - virtual link::Endpoint* - GetCompatibleLink(const RouterContact& rc) const = 0; - virtual IOutboundSessionMaker* GetSessionMaker() const = 0; @@ -39,7 +63,7 @@ namespace llarp uint16_t priority = 0) = 0; virtual bool - HaveConnection(const RouterID& remote) const = 0; + HaveConnection(const RouterID& remote, bool client_only = false) const = 0; /// return true if we have a connection to the remote and it is not a relay, /// else return false @@ -52,19 +76,6 @@ namespace llarp virtual void PersistSessionUntil(const RouterID& remote, llarp_time_t until) = 0; - virtual void - ForEachPeer( - std::function visit, bool randomize = false) const = 0; - - virtual void - ForEachPeer(std::function visit) = 0; - - virtual void - ForEachInboundLink(std::function visit) const = 0; - - virtual void - ForEachOutboundLink(std::function visit) const = 0; - /// close all connections to this peer /// remove all link layer commits virtual void @@ -87,6 +98,19 @@ namespace llarp virtual util::StatusObject ExtractStatus() const = 0; + + // Do an RC lookup for the given RouterID; the result will trigger + // Connect(RouterContact) on success (or if we already have it), and will + // trigger connection failure callback on lookup failure. + virtual void + Connect(RouterID router) = 0; + + // Establish a connection to the remote `rc`. + // + // Connection established/failed callbacks should be invoked when either happens, + // but this function should do nothing if already connected. + virtual void + Connect(RouterContact rc) = 0; }; } // namespace llarp diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 18a401e9d0..da8a9689bb 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1,6 +1,7 @@ #include "link_manager.hpp" -#include +#include +#include #include #include @@ -8,13 +9,13 @@ namespace llarp { - llarp::link::Endpoint* - LinkManager::GetCompatibleLink(const RouterContact& rc) const + link::Endpoint* + LinkManager::GetCompatibleLink(const RouterContact& rc) { if (stopping) return nullptr; - for (const auto& ep : endpoints) + for (auto& ep : endpoints) { //TODO: need some notion of "is this link compatible with that address". // iwp just checks that the link dialect ("iwp") matches the address info dialect, @@ -37,8 +38,7 @@ namespace llarp if (stopping) return false; - auto link = GetLinkWithSessionTo(remote); - if (link == nullptr) + if (not HaveConnection(remote)) { if (completed) { @@ -47,24 +47,32 @@ namespace llarp return false; } - return link->SendTo(remote, buf, completed, priority); + //TODO: send the message + //TODO: if we keep bool return type, change this accordingly + return false; } bool - LinkManager::HaveClientConnection(const RouterID& remote) const + LinkManager::HaveConnection(const RouterID& remote, bool client_only) const { for (const auto& ep : endpoints) { if (auto itr = ep.connections.find(remote); itr != ep.connections.end()) { - if (itr->second.remote_is_relay) - return false; - return true; + if (not (itr->second.remote_is_relay and client_only)) + return true; + return false; } } return false; } + bool + LinkManager::HaveClientConnection(const RouterID& remote) const + { + return HaveConnection(remote, true); + } + void LinkManager::DeregisterPeer(RouterID remote) { @@ -73,7 +81,9 @@ namespace llarp { if (auto itr = ep.connections.find(remote); itr != ep.connections.end()) { + /* itr->second.conn->close(); //TODO: libquic needs some function for this + */ } } @@ -81,7 +91,7 @@ namespace llarp } void - AddLink(oxen::quic::Address bind, bool inbound = false) + LinkManager::AddLink(const oxen::quic::opt::local_addr& bind, bool inbound) { //TODO: libquic callbacks: new_conn_alpn_notify, new_conn_pubkey_ok, new_conn_established/ready auto ep = quic->endpoint(bind); @@ -129,57 +139,6 @@ namespace llarp } } - void - LinkManager::ForEachPeer( - std::function visit, bool randomize) const - { - if (stopping) - return; - - for (const auto& link : outboundLinks) - { - link->ForEachSession([visit](const ILinkSession* peer) { visit(peer, true); }, randomize); - } - for (const auto& link : inboundLinks) - { - link->ForEachSession([visit](const ILinkSession* peer) { visit(peer, false); }, randomize); - } - } - - void - LinkManager::ForEachPeer(std::function visit) - { - if (stopping) - return; - - for (const auto& link : outboundLinks) - { - link->ForEachSession([visit](ILinkSession* peer) { visit(peer); }); - } - for (const auto& link : inboundLinks) - { - link->ForEachSession([visit](ILinkSession* peer) { visit(peer); }); - } - } - - void - LinkManager::ForEachInboundLink(std::function visit) const - { - for (const auto& link : inboundLinks) - { - visit(link); - } - } - - void - LinkManager::ForEachOutboundLink(std::function visit) const - { - for (const auto& link : outboundLinks) - { - visit(link); - } - } - size_t LinkManager::NumberOfConnectedRouters(bool clients_only) const { @@ -202,18 +161,18 @@ namespace llarp return NumberOfConnectedRouters(true); } - //TODO: libquic bool LinkManager::GetRandomConnectedRouter(RouterContact& router) const { std::unordered_map connectedRouters; - ForEachPeer( - [&connectedRouters](const ILinkSession* peer, bool unused) { - (void)unused; - connectedRouters[peer->GetPubKey()] = peer->GetRemoteRC(); - }, - false); + for (const auto& ep : endpoints) + { + for (const auto& [router_id, conn] : ep.connections) + { + connectedRouters.emplace(router_id, conn.remote_rc); + } + } const auto sz = connectedRouters.size(); if (sz) @@ -302,10 +261,10 @@ namespace llarp // based on which one is compatible with the link we chose. For now, just use // the first one. auto& selected = rc.addrs[0]; - llarp::quic::opt::remote_addr remote{selected.IPString(), selected.port}; + oxen::quic::opt::remote_addr remote{selected.IPString(), selected.port}; //TODO: confirm remote end is using the expected pubkey (RouterID). //TODO: ALPN for "client" vs "relay" (could just be set on endpoint creation) - auto conn_interface = ep->connect(remote, dgram_cb, stream_cb, tls_creds); + auto conn_interface = ep->endpoint->connect(remote, dgram_cb, stream_cb, tls_creds); std::shared_ptr stream = conn_interface->get_new_stream(); @@ -324,6 +283,7 @@ namespace llarp LinkManager::ConnectToRandomRouters(int numDesired) { std::set exclude; + auto remainingDesired = numDesired; do { auto filter = [exclude](const auto& rc) -> bool { return exclude.count(rc.pubkey) == 0; }; @@ -345,19 +305,6 @@ namespace llarp } while (remainingDesired > 0); } - bool - LinkManager::HaveConnection(const RouterID& remote) - { - for (const auto& ep : endpoints) - { - if (ep.connections.contains(remote)) - { - return true; - } - } - return false; - } - void LinkManager::HandleIncomingDataMessage(oxen::quic::dgram_interface& dgi, bstring dgram) { diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 5334f3fde3..bb88deea38 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -23,9 +23,6 @@ namespace llarp ~LinkManager() override = default; - link::Endpoint* - GetCompatibleLink(const RouterContact& rc) const override; - IOutboundSessionMaker* GetSessionMaker() const override; @@ -37,7 +34,7 @@ namespace llarp uint16_t priority) override; bool - HaveConnection(const RouterID& remote) const override; + HaveConnection(const RouterID& remote, bool client_only = false) const override; bool HaveClientConnection(const RouterID& remote) const override; @@ -46,7 +43,7 @@ namespace llarp DeregisterPeer(RouterID remote) override; void - AddLink(oxen::quic::Address bind, bool inbound = false); + AddLink(const oxen::quic::opt::local_addr& bind, bool inbound = false); void Stop() override; @@ -54,23 +51,6 @@ namespace llarp void PersistSessionUntil(const RouterID& remote, llarp_time_t until) override; - //TODO: change for libquic Connections - void - ForEachPeer(std::function visit, bool randomize = false) - const override; - - //TODO: change for libquic Connections - void - ForEachPeer(std::function visit) override; - - //TODO: change for libquic Endpoints - void - ForEachInboundLink(std::function visit) const override; - - //TODO: change for libquic Endpoints - void - ForEachOutboundLink(std::function visit) const override; - size_t NumberOfConnectedRouters(bool clients_only = false) const override; @@ -92,16 +72,9 @@ namespace llarp void Init(I_RCLookupHandler* rcLookup); - // Do an RC lookup for the given RouterID; the result will trigger - // Connect(RouterContact) on success (or if we already have it), and will - // trigger connection failure callback on lookup failure. void Connect(RouterID router); - // Establish a connection to the remote `rc`. - // - // Connection established/failed callbacks should be invoked when either happens, - // but this function should do nothing if already connected. void Connect(RouterContact rc); @@ -121,6 +94,9 @@ namespace llarp private: + link::Endpoint* + GetCompatibleLink(const RouterContact& rc); + std::atomic stopping; mutable util::Mutex _mutex; // protects m_PersistingSessions diff --git a/llarp/net/address_info.cpp b/llarp/net/address_info.cpp index d9b11543c2..d25b23645a 100644 --- a/llarp/net/address_info.cpp +++ b/llarp/net/address_info.cpp @@ -183,7 +183,7 @@ namespace llarp { char tmp[INET6_ADDRSTRLEN] = {0}; inet_ntop(AF_INET6, (void*)&ip, tmp, sizeof(tmp)); - return std::string{sizeof(tmp), tmp}; + return std::string{tmp}; } void diff --git a/llarp/router/outbound_message_handler.cpp b/llarp/router/outbound_message_handler.cpp index 93d1c47c26..a92b90cba7 100644 --- a/llarp/router/outbound_message_handler.cpp +++ b/llarp/router/outbound_message_handler.cpp @@ -168,11 +168,11 @@ namespace llarp _router->loop()->call([f = std::move(callback), status] { f(status); }); } + //TODO: still necessary/desired? void OutboundMessageHandler::QueueSessionCreation(const RouterID& remote) { - auto fn = util::memFn(&OutboundMessageHandler::OnSessionResult, this); - _router->linkManager().GetSessionMaker()->CreateSessionTo(remote, fn); + _router->linkManager().Connect(remote); } bool diff --git a/llarp/router/rc_gossiper.cpp b/llarp/router/rc_gossiper.cpp index bd9e99b7b2..c1bafb2fda 100644 --- a/llarp/router/rc_gossiper.cpp +++ b/llarp/router/rc_gossiper.cpp @@ -100,6 +100,9 @@ namespace llarp std::vector gossipTo; + /* + * TODO: gossip RC via libquic + * // select peers to gossip to m_LinkManager->ForEachPeer( [&](const ILinkSession* peerSession, bool) { @@ -140,6 +143,10 @@ namespace llarp // send message peerSession->SendMessageBuffer(std::move(msg), nullptr, gossip.Priority()); }); + * + * + */ + return true; } diff --git a/llarp/router/rc_lookup_handler.cpp b/llarp/router/rc_lookup_handler.cpp index ca9169e650..3693dc8f34 100644 --- a/llarp/router/rc_lookup_handler.cpp +++ b/llarp/router/rc_lookup_handler.cpp @@ -337,6 +337,9 @@ namespace llarp return; // explore via every connected peer + /* + * TODO: DHT explore via libquic + * _linkManager->ForEachPeer([&](ILinkSession* s) { if (!s->IsEstablished()) return; @@ -347,6 +350,9 @@ namespace llarp _dht->impl->ExploreNetworkVia(dht::Key_t{rc.pubkey}); } }); + * + * + */ } void diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 1d9dc51e6e..c02d0c3c0b 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -91,7 +91,6 @@ namespace llarp paths.PumpUpstream(); _hiddenServiceContext.Pump(); _outboundMessageHandler.Pump(); - _linkManager.PumpLinks(); llarp::LogTrace("Router::PumpLL() end"); } @@ -224,24 +223,30 @@ namespace llarp return inbound_link_msg_parser.ProcessFrom(session, buf); } - //TODO: investigate changes needed for libquic integration void Router::Freeze() { if (IsServiceNode()) return; + /* + *TODO: investigate changes needed for libquic integration + * linkManager().ForEachPeer([](auto peer) { if (peer) peer->Close(); }); + * + */ } - //TODO: investigate changes needed for libquic integration void Router::Thaw() { if (IsServiceNode()) return; + /* + *TODO: investigate changes needed for libquic integration + * // get pubkeys we are connected to std::unordered_set peerPubkeys; linkManager().ForEachPeer([&peerPubkeys](auto peer) { @@ -261,6 +266,8 @@ namespace llarp return true; }); LogInfo("We are ready to go bruh... probably"); + * + */ } void @@ -316,14 +323,14 @@ namespace llarp void Router::ForEachPeer(std::function visit, bool randomize) const { - _linkManager.ForEachPeer(visit, randomize); + //_linkManager.ForEachPeer(visit, randomize); } //TODO: if still needed/useful, replace this in line with libquic impl void Router::ForEachPeer(std::function visit) { - _linkManager.ForEachPeer(visit); + //_linkManager.ForEachPeer(visit); } void @@ -338,7 +345,7 @@ namespace llarp if (remote.Verify(Now())) { LogDebug("verified signature"); - _linkManager->Connect(remote); + _linkManager.Connect(remote); } else LogError(rcfile, " contains invalid RC"); @@ -625,12 +632,14 @@ namespace llarp { //TODO: libquic change // propagate RC by renegotiating sessions + /* ForEachPeer([](ILinkSession* s) { if (s->RenegotiateSession()) LogInfo("renegotiated session"); else LogWarn("failed to renegotiate session"); }); + */ } if (IsServiceNode()) return SaveRC(); @@ -1032,6 +1041,9 @@ namespace llarp // find all deregistered relays std::unordered_set closePeers; + /* + * TODO: change for libquic + * _linkManager.ForEachPeer([&](auto session) { if (whitelistRouters and not gotWhitelist) return; @@ -1043,6 +1055,9 @@ namespace llarp closePeers.emplace(pk); } }); + * + * + */ // mark peers as de-registered for (auto& peer : closePeers) @@ -1134,7 +1149,9 @@ namespace llarp } } - //TODO: libquic change + /* + *TODO: libquic change + * // get connected peers std::set peersWeHave; _linkManager.ForEachPeer([&peersWeHave](ILinkSession* s) { @@ -1147,6 +1164,8 @@ namespace llarp [&peersWeHave](const dht::Key_t& k) -> bool { return peersWeHave.count(k) == 0; }); // expire paths paths.ExpirePaths(now); + * + */ // update tick timestamp _lastTick = llarp::time_now_ms(); } @@ -1184,7 +1203,6 @@ namespace llarp // TODO: make sure this is a public router (on whitelist)? m_peerDb->modifyPeerStats(id, [&](PeerStats& stats) { stats.numConnectionTimeouts++; }); } - _outboundSessionMaker.OnConnectTimeout(session); } void @@ -1209,7 +1227,6 @@ namespace llarp m_peerDb->modifyPeerStats(id, [&](PeerStats& stats) { stats.numConnectionSuccesses++; }); } NotifyRouterEvent(pubkey(), id, inbound); - return _outboundSessionMaker.OnSessionEstablished(session); } bool @@ -1391,7 +1408,7 @@ namespace llarp LogDebug("Establishing session to ", router, " for SN testing"); // try to make a session to this random router // this will do a dht lookup if needed - _linkManager->Connect(router); + _linkManager.Connect(router); /* * TODO: container of pending snode test routers to be queried on @@ -1533,7 +1550,6 @@ namespace llarp paths.PumpUpstream(); llarp::sys::service_manager->stopping(); log::debug(logcat, "final links pump"); - _linkManager.PumpLinks(); _loop->call_later(200ms, [this] { AfterStopIssued(); }); } @@ -1590,7 +1606,7 @@ namespace llarp return false; } - _linkManager->Connect(rc); + _linkManager.Connect(rc); return true; } @@ -1616,14 +1632,16 @@ namespace llarp return ep and ep->HasExit(); } - //TODO: change to use new LinkManager foreach semantics, or make function for this - // on LinkManager itself std::optional> Router::OurPublicIP() const { if (_ourAddress) return _ourAddress->getIP(); std::optional> found; + /* + *TODO: change to use new LinkManager foreach semantics, or make function for this + * on LinkManager itself + * _linkManager.ForEachInboundLink([&found](const auto& link) { if (found) return; @@ -1631,11 +1649,14 @@ namespace llarp if (link->GetOurAddressInfo(ai)) found = ai.IP(); }); + * + * + */ return found; } void - AddAddressToRC(AddressInfo& ai) + Router::AddAddressToRC(AddressInfo& ai) { // override ip and port as needed if (_ourAddress) @@ -1702,10 +1723,11 @@ namespace llarp throw std::runtime_error{"no public ip provided for inbound socket"}; } - _linkManager.AddLink(bind_addr.ToString(), true); - AddressInfo ai; ai.fromSockAddr(bind_addr); + + _linkManager.AddLink({ai.IPString(), ai.port}, true); + ai.pubkey = llarp::seckey_topublic(_identity); ai.dialect = "quicinet"; // FIXME: constant, also better name? ai.rank = 2; // FIXME: hardcoded from the beginning...keep? @@ -1722,7 +1744,9 @@ namespace llarp for (auto& bind_addr : addrs) { - _linkManager.AddLink(bind_addr.ToString(), false); + AddressInfo ai; + ai.fromSockAddr(bind_addr); + _linkManager.AddLink({ai.IPString(), ai.port}, false); } } diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 139941f5c1..155fd23088 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -19,7 +19,6 @@ #include #include #include "outbound_message_handler.hpp" -#include "outbound_session_maker.hpp" #include "rc_gossiper.hpp" #include "rc_lookup_handler.hpp" #include "route_poker.hpp" From 78f866347b5d9cd5c6e3a8bac7abca8f71ae48bd Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Mon, 28 Aug 2023 18:05:34 -0300 Subject: [PATCH 015/312] Remove unnecessary static_pointer_cast --- llarp/context.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llarp/context.cpp b/llarp/context.cpp index e38a1adcd4..487a240661 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -96,8 +96,7 @@ namespace llarp std::shared_ptr Context::makeRouter(const EventLoop_ptr& loop) { - return std::static_pointer_cast( - std::make_shared(loop, makeVPNPlatform())); + return std::make_shared(loop, makeVPNPlatform()); } std::shared_ptr From c92facc15e403fea7e10b20bdc7ec281b1811ace Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Mon, 28 Aug 2023 18:09:23 -0300 Subject: [PATCH 016/312] Minor cleanups --- llarp/link/link_manager.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index bb88deea38..39623b5838 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -21,8 +21,6 @@ namespace llarp public: LinkManager(AbstractRouter* r) : router(r) {} - ~LinkManager() override = default; - IOutboundSessionMaker* GetSessionMaker() const override; @@ -73,10 +71,10 @@ namespace llarp Init(I_RCLookupHandler* rcLookup); void - Connect(RouterID router); + Connect(RouterID router) override; void - Connect(RouterContact rc); + Connect(RouterContact rc) override; // Attempts to connect to a number of random routers. // From a44fdab4601b0facc7814fe9c642fb93eda577e6 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Mon, 28 Aug 2023 17:21:03 -0400 Subject: [PATCH 017/312] LinkManager linker issues / explicit constructor --- llarp/link/i_link_manager.hpp | 3 --- llarp/link/link_manager.hpp | 4 +--- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/llarp/link/i_link_manager.hpp b/llarp/link/i_link_manager.hpp index 41dc83ce71..8eb5fcac7d 100644 --- a/llarp/link/i_link_manager.hpp +++ b/llarp/link/i_link_manager.hpp @@ -52,9 +52,6 @@ namespace llarp { virtual ~ILinkManager() = default; - virtual IOutboundSessionMaker* - GetSessionMaker() const = 0; - virtual bool SendTo( const RouterID& remote, diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 39623b5838..aa622cc220 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -19,10 +19,8 @@ namespace llarp struct LinkManager final : public ILinkManager { public: - LinkManager(AbstractRouter* r) : router(r) {} + explicit LinkManager(AbstractRouter* r) : router{r} {} - IOutboundSessionMaker* - GetSessionMaker() const override; bool SendTo( From bc585d93d27ecabc061291a40a90007b91d6f0e4 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Mon, 28 Aug 2023 18:30:30 -0300 Subject: [PATCH 018/312] Remove external/ngtcp2 (use the one from libquic instead) --- .gitmodules | 4 ---- external/ngtcp2 | 1 - 2 files changed, 5 deletions(-) delete mode 160000 external/ngtcp2 diff --git a/.gitmodules b/.gitmodules index 38524f3db1..5790be24db 100644 --- a/.gitmodules +++ b/.gitmodules @@ -23,10 +23,6 @@ [submodule "external/cpr"] path = external/cpr url = https://github.com/whoshuu/cpr -[submodule "external/ngtcp2"] - path = external/ngtcp2 - url = https://github.com/ngtcp2/ngtcp2.git - branch = v0.1.0 [submodule "gui"] path = gui url = https://github.com/oxen-io/lokinet-gui.git diff --git a/external/ngtcp2 b/external/ngtcp2 deleted file mode 160000 index 026b8434eb..0000000000 --- a/external/ngtcp2 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 026b8434ebcbeec48939d1c7671a0a4d5c75202b From d92d95177d15a4571fe5977e5a4e745d6193f0e6 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Mon, 28 Aug 2023 19:23:46 -0300 Subject: [PATCH 019/312] ngtcp2 build fix -std=c99 breaks ngtcp2's build -- it appears to depend on GNU extensions when compiling on linux, so don't force compiler C extensions off. --- CMakeLists.txt | 3 +-- llarp/CMakeLists.txt | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bd67b5ac10..8fdb02246b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,9 +102,8 @@ include(CheckLibraryExists) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) -set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) -set(CMAKE_C_EXTENSIONS OFF) include(cmake/target_link_libraries_system.cmake) include(cmake/add_import_library.cmake) diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index 969be3894c..c8b7e18164 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -513,7 +513,6 @@ target_link_libraries(lokinet-util PUBLIC ) target_link_libraries(lokinet-plainquic PUBLIC - ngtcp2_crypto quic uvw ) From e2e7ed34905afa2e2547a36851f0fcbec661d0b7 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Mon, 28 Aug 2023 19:20:57 -0400 Subject: [PATCH 020/312] pass datagram data cb to endpoint ctor, not listen/connect Still ngtcp2 link errors, but everything else seems to build. Have not checked tests; not likely they will build or be correct if broken. --- llarp/link/link_manager.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index da8a9689bb..9be7f46048 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -94,15 +94,15 @@ namespace llarp LinkManager::AddLink(const oxen::quic::opt::local_addr& bind, bool inbound) { //TODO: libquic callbacks: new_conn_alpn_notify, new_conn_pubkey_ok, new_conn_established/ready - auto ep = quic->endpoint(bind); + // stream_opened, stream_data, stream_closed, conn_closed + oxen::quic::dgram_data_callback dgram_cb = [this](oxen::quic::dgram_interface& dgi, bstring dgram){ HandleIncomingDataMessage(dgi, dgram); }; + auto ep = quic->endpoint(bind, std::move(dgram_cb), oxen::quic::opt::enable_datagrams{oxen::quic::Splitting::ACTIVE}); endpoints.emplace_back(); auto& endp = endpoints.back(); endp.endpoint = std::move(ep); if (inbound) { - oxen::quic::dgram_data_callback dgram_cb = [this](oxen::quic::dgram_interface& dgi, bstring dgram){ HandleIncomingDataMessage(dgi, dgram); }; - oxen::quic::stream_data_callback stream_cb = [this](oxen::quic::Stream& stream, bstring_view packet){ HandleIncomingControlMessage(stream, packet); }; - endp.endpoint->listen(tls_creds, dgram_cb, stream_cb); + endp.endpoint->listen(tls_creds); endp.inbound = true; } } @@ -254,7 +254,6 @@ namespace llarp return; //TODO: connection established/failed callbacks - oxen::quic::dgram_data_callback dgram_cb = [this](oxen::quic::dgram_interface& dgi, bstring dgram){ HandleIncomingDataMessage(dgi, dgram); }; oxen::quic::stream_data_callback stream_cb = [this](oxen::quic::Stream& stream, bstring_view packet){ HandleIncomingControlMessage(stream, packet); }; //TODO: once "compatible link" cares about address, actually choose addr to connect to @@ -264,7 +263,8 @@ namespace llarp oxen::quic::opt::remote_addr remote{selected.IPString(), selected.port}; //TODO: confirm remote end is using the expected pubkey (RouterID). //TODO: ALPN for "client" vs "relay" (could just be set on endpoint creation) - auto conn_interface = ep->endpoint->connect(remote, dgram_cb, stream_cb, tls_creds); + //TODO: does connect() inherit the endpoint's datagram data callback, and do we want it to if so? + auto conn_interface = ep->endpoint->connect(remote, stream_cb, tls_creds); std::shared_ptr stream = conn_interface->get_new_stream(); From db01c7c4cec80510dc0cadb0683f3a091979603f Mon Sep 17 00:00:00 2001 From: dr7ana Date: Tue, 29 Aug 2023 05:21:32 -0700 Subject: [PATCH 021/312] oxen-mq commit bump --- external/oxen-mq | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/oxen-mq b/external/oxen-mq index 4f6dc35ea1..e1b66ced48 160000 --- a/external/oxen-mq +++ b/external/oxen-mq @@ -1 +1 @@ -Subproject commit 4f6dc35ea13722a5f9dcd0c3d65b6b7ac3d0f0c5 +Subproject commit e1b66ced4803e1b0cb05ed554cb5fc82b14c13c0 From edd353442516c8da85fc7ace89889d7e3c5b0159 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Tue, 29 Aug 2023 13:17:55 -0400 Subject: [PATCH 022/312] Default cmake BUILD_SHARED_LIBS to OFF By not having BUILD_SHARED_LIBS as a defaulted option, if it was not set in the invocation of cmake then any submodule could come along and set it instead by declaring it as an option. If/when this happens in the middle of the cmake process, some modules will have the flag unset and others will have it as the default that the submodule set, leading to inconsistent compilation parameters at best, but likely linking failure. --- CMakeLists.txt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fdb02246b..395364f98b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,11 +70,17 @@ include(cmake/enable_lto.cmake) option(CROSS_PLATFORM "cross compiler platform" "Linux") option(CROSS_PREFIX "toolchain cross compiler prefix" "") +option(BUILD_SHARED_LIBS "Build shared library" OFF) option(BUILD_STATIC_DEPS "Download, build, and statically link against core dependencies" OFF) option(STATIC_LINK "link statically against dependencies" ${BUILD_STATIC_DEPS}) if(BUILD_STATIC_DEPS AND NOT STATIC_LINK) message(FATAL_ERROR "Option BUILD_STATIC_DEPS requires STATIC_LINK to be enabled as well") endif() + +if(BUILD_STATIC_DEPS AND BUILD_SHARED_LIBS) + message(FATAL_ERROR "Incompatible options: BUILD_STATIC_DEPS cannot be used with BUILD_SHARED_LIBS") +endif() + if(BUILD_STATIC_DEPS) set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE) include(cmake/StaticBuild.cmake) @@ -92,11 +98,6 @@ endif() option(WARN_DEPRECATED "show deprecation warnings" ${debug}) -if(BUILD_STATIC_DEPS AND STATIC_LINK) - message(STATUS "we are building static deps so we won't build shared libs") - set(BUILD_SHARED_LIBS OFF CACHE BOOL "") -endif() - include(CheckCXXSourceCompiles) include(CheckLibraryExists) set(CMAKE_CXX_STANDARD 17) From a921575c55c4ac8921083a4fd933075e860c4f07 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Tue, 29 Aug 2023 07:26:59 -0700 Subject: [PATCH 023/312] mein gott --- CMakeLists.txt | 2 +- llarp/dht/context.cpp | 22 +- llarp/dht/context.hpp | 8 +- llarp/dht/message.cpp | 207 ++- llarp/dht/message.hpp | 78 +- llarp/dht/messages/consensus.hpp | 39 +- llarp/dht/messages/findintro.cpp | 183 +-- llarp/dht/messages/findintro.hpp | 74 +- llarp/dht/messages/findname.cpp | 25 +- llarp/dht/messages/findname.hpp | 10 +- llarp/dht/messages/findrouter.cpp | 248 ++- llarp/dht/messages/findrouter.hpp | 101 +- llarp/dht/messages/gotintro.cpp | 183 +-- llarp/dht/messages/gotintro.hpp | 85 +- llarp/dht/messages/gotname.cpp | 25 +- llarp/dht/messages/gotname.hpp | 11 +- llarp/dht/messages/gotrouter.cpp | 199 ++- llarp/dht/messages/gotrouter.hpp | 94 +- llarp/dht/messages/pubintro.cpp | 300 ++-- llarp/dht/messages/pubintro.hpp | 61 +- llarp/exit/exit_messages.cpp | 13 +- llarp/exit/exit_messages.hpp | 26 +- llarp/iwp/linklayer.cpp | 6 +- llarp/iwp/linklayer.hpp | 6 +- llarp/iwp/message_buffer.cpp | 17 +- llarp/iwp/message_buffer.hpp | 18 +- llarp/iwp/session.cpp | 40 +- llarp/iwp/session.hpp | 12 +- llarp/link/connection.hpp | 2 +- llarp/link/endpoint.hpp | 3 +- llarp/link/i_link_manager.hpp | 10 +- llarp/link/link_manager.cpp | 89 +- llarp/link/link_manager.hpp | 20 +- llarp/link/server.cpp | 32 +- llarp/link/server.hpp | 30 +- llarp/link/session.cpp | 2 +- llarp/link/session.hpp | 6 +- llarp/messages/common.hpp | 21 + llarp/messages/dht_immediate.cpp | 68 +- llarp/messages/dht_immediate.hpp | 16 +- llarp/messages/discard.hpp | 75 +- llarp/messages/link_intro.cpp | 111 +- llarp/messages/link_intro.hpp | 32 +- llarp/messages/link_message.hpp | 64 +- llarp/messages/link_message_parser.cpp | 8 +- llarp/messages/link_message_parser.hpp | 10 +- llarp/messages/relay.cpp | 96 +- llarp/messages/relay.hpp | 42 +- llarp/messages/relay_commit.cpp | 41 +- llarp/messages/relay_commit.hpp | 20 +- llarp/messages/relay_status.cpp | 54 +- llarp/messages/relay_status.hpp | 20 +- llarp/net/ip_address.hpp | 56 +- llarp/net/net_int.hpp | 12 +- llarp/path/ihophandler.hpp | 4 +- llarp/path/path.cpp | 1440 ++++++++--------- llarp/path/path.hpp | 6 +- llarp/path/pathbuilder.cpp | 2 +- llarp/path/pathset.hpp | 2 +- llarp/path/transit_hop.cpp | 704 ++++---- llarp/path/transit_hop.hpp | 8 +- llarp/quic/address.hpp | 5 +- llarp/quic/connection.cpp | 11 +- llarp/quic/endpoint.cpp | 12 +- llarp/quic/server.cpp | 3 +- llarp/router/abstractrouter.hpp | 19 +- llarp/router/i_outbound_message_handler.hpp | 5 +- llarp/router/i_outbound_session_maker.hpp | 6 +- llarp/router/outbound_message_handler.cpp | 36 +- llarp/router/outbound_message_handler.hpp | 4 +- llarp/router/outbound_session_maker.cpp | 6 +- llarp/router/outbound_session_maker.hpp | 4 +- llarp/router/rc_gossiper.cpp | 6 +- llarp/router/router.cpp | 50 +- llarp/router/router.hpp | 18 +- llarp/router_contact.cpp | 9 + llarp/router_contact.hpp | 7 +- llarp/routing/dht_message.cpp | 4 +- llarp/routing/dht_message.hpp | 41 +- llarp/routing/handler.hpp | 8 +- llarp/routing/message.hpp | 45 +- llarp/routing/message_parser.cpp | 236 +-- llarp/routing/message_parser.hpp | 8 +- llarp/routing/path_confirm_message.cpp | 2 +- llarp/routing/path_confirm_message.hpp | 47 +- llarp/routing/path_latency_message.cpp | 2 +- llarp/routing/path_latency_message.hpp | 4 +- llarp/routing/path_transfer_message.cpp | 2 +- llarp/routing/path_transfer_message.hpp | 4 +- llarp/routing/transfer_traffic_message.cpp | 2 +- llarp/routing/transfer_traffic_message.hpp | 4 +- llarp/service/endpoint.cpp | 4 +- .../service/hidden_service_address_lookup.cpp | 2 +- .../service/hidden_service_address_lookup.hpp | 2 +- llarp/service/lookup.hpp | 2 +- llarp/service/protocol.cpp | 3 +- llarp/service/protocol.hpp | 8 +- llarp/tooling/dht_event.hpp | 2 +- llarp/util/buffer.hpp | 161 +- 99 files changed, 3087 insertions(+), 2906 deletions(-) create mode 100644 llarp/messages/common.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 395364f98b..246613fa83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,7 +96,7 @@ if(CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]") add_definitions(-DLOKINET_DEBUG) endif() -option(WARN_DEPRECATED "show deprecation warnings" ${debug}) +option(WARN_DEPRECATED "show deprecation warnings" OFF) include(CheckCXXSourceCompiles) include(CheckLibraryExists) diff --git a/llarp/dht/context.cpp b/llarp/dht/context.cpp index 06c67953d4..77097158bd 100644 --- a/llarp/dht/context.cpp +++ b/llarp/dht/context.cpp @@ -110,7 +110,7 @@ namespace llarp /// send a dht message to peer, if keepalive is true then keep the session /// with that peer alive for 10 seconds void - DHTSendTo(const RouterID& peer, IMessage* msg, bool keepalive = true) override; + DHTSendTo(const RouterID& peer, AbstractDHTMessage* msg, bool keepalive = true) override; /// get routers closest to target excluding requester bool @@ -118,7 +118,7 @@ namespace llarp const Key_t& requester, uint64_t txid, const RouterID& target, - std::vector>& reply) override; + std::vector>& reply) override; /// handle rc lookup from requester for target void @@ -127,11 +127,11 @@ namespace llarp uint64_t txid, const Key_t& target, bool recursive, - std::vector>& replies) override; + std::vector>& replies) override; /// relay a dht message from a local path to the main network bool - RelayRequestForPath(const llarp::PathID_t& localPath, const IMessage& msg) override; + RelayRequestForPath(const llarp::PathID_t& localPath, const AbstractDHTMessage& msg) override; /// send introset to peer as R/S void @@ -374,7 +374,7 @@ namespace llarp uint64_t txid, const Key_t& target, bool recursive, - std::vector>& replies) + std::vector>& replies) { if (target == ourKey) { @@ -475,9 +475,9 @@ namespace llarp } void - Context::DHTSendTo(const RouterID& peer, IMessage* msg, bool) + Context::DHTSendTo(const RouterID& peer, AbstractDHTMessage* msg, bool) { - llarp::DHTImmediateMessage m; + DHTImmediateMessage m; m.msgs.emplace_back(msg); router->SendToOrQueue(peer, m); auto now = Now(); @@ -489,10 +489,10 @@ namespace llarp // namespace. by the time this is called, we are inside // llarp::routing::DHTMessage::HandleMessage() bool - Context::RelayRequestForPath(const llarp::PathID_t& id, const IMessage& msg) + Context::RelayRequestForPath(const llarp::PathID_t& id, const AbstractDHTMessage& msg) { - llarp::routing::DHTMessage reply; - if (!msg.HandleMessage(router->dht(), reply.M)) + routing::DHTMessage reply; + if (!msg.handle_message(router->dht(), reply.M)) return false; if (not reply.M.empty()) { @@ -584,7 +584,7 @@ namespace llarp const Key_t& requester, uint64_t txid, const RouterID& target, - std::vector>& reply) + std::vector>& reply) { std::vector closer; const Key_t t(target.as_array()); diff --git a/llarp/dht/context.hpp b/llarp/dht/context.hpp index 1b184555fd..ba6a9173c1 100644 --- a/llarp/dht/context.hpp +++ b/llarp/dht/context.hpp @@ -89,7 +89,7 @@ namespace llarp uint64_t relayOrder) = 0; virtual void - DHTSendTo(const RouterID& peer, IMessage* msg, bool keepalive = true) = 0; + DHTSendTo(const RouterID& peer, AbstractDHTMessage* msg, bool keepalive = true) = 0; /// get routers closest to target excluding requester virtual bool @@ -97,7 +97,7 @@ namespace llarp const Key_t& requester, uint64_t txid, const RouterID& target, - std::vector>& reply) = 0; + std::vector>& reply) = 0; /// handle rc lookup from requester for target virtual void @@ -106,10 +106,10 @@ namespace llarp uint64_t txid, const Key_t& target, bool recursive, - std::vector>& replies) = 0; + std::vector>& replies) = 0; virtual bool - RelayRequestForPath(const PathID_t& localPath, const IMessage& msg) = 0; + RelayRequestForPath(const PathID_t& localPath, const AbstractDHTMessage& msg) = 0; /// send introset to peer from source with S counter and excluding peers virtual void diff --git a/llarp/dht/message.cpp b/llarp/dht/message.cpp index dfaabfea3f..b4ad730668 100644 --- a/llarp/dht/message.cpp +++ b/llarp/dht/message.cpp @@ -1,4 +1,5 @@ #include "context.hpp" +#include "oxenc/bt_serialize.h" #include #include @@ -10,128 +11,124 @@ #include #include -namespace llarp +namespace llarp::dht { - namespace dht + struct MessageDecoder { - struct MessageDecoder - { - const Key_t& From; - IMessage::Ptr_t msg; - bool firstKey = true; - bool relayed = false; + const Key_t& From; + AbstractDHTMessage::Ptr_t msg; + bool firstKey = true; + bool relayed = false; - MessageDecoder(const Key_t& from, bool wasRelayed) : From(from), relayed(wasRelayed) - {} + MessageDecoder(const Key_t& from, bool wasRelayed) : From(from), relayed(wasRelayed) + {} - bool - operator()(llarp_buffer_t* buffer, llarp_buffer_t* key) + bool + operator()(llarp_buffer_t* buffer, llarp_buffer_t* key) + { + llarp_buffer_t strbuf; + // check for empty dict + if (!key) + return !firstKey; + // first key + if (firstKey) { - llarp_buffer_t strbuf; - // check for empty dict - if (!key) - return !firstKey; - - // first key - if (firstKey) + if (!(key->startswith("A"))) + return false; + if (!bencode_read_string(buffer, &strbuf)) + return false; + // bad msg size? + if (strbuf.sz != 1) + return false; + llarp::LogDebug("Handle DHT message ", *strbuf.base, " relayed=", relayed); + switch (*strbuf.base) { - if (!(key->startswith("A"))) - return false; - if (!bencode_read_string(buffer, &strbuf)) - return false; - // bad msg size? - if (strbuf.sz != 1) - return false; - llarp::LogDebug("Handle DHT message ", *strbuf.base, " relayed=", relayed); - switch (*strbuf.base) - { - case 'N': - msg = std::make_unique(From, Key_t{}, 0); + case 'N': + msg = std::make_unique(From, Key_t{}, 0); + break; + case 'M': + msg = std::make_unique(From, 0, service::EncryptedName{}); + break; + case 'F': + msg = std::make_unique(From, relayed, 0); + break; + case 'R': + if (relayed) + msg = std::make_unique(From); + else + msg = std::make_unique(From); + break; + case 'S': + msg = std::make_unique(From, relayed); + break; + case 'I': + msg = std::make_unique(From, relayed); + break; + case 'G': + if (relayed) + { + msg = std::make_unique(); break; - case 'M': - msg = std::make_unique(From, 0, service::EncryptedName{}); + } + else + { + msg = std::make_unique(From); break; - case 'F': - msg = std::make_unique(From, relayed, 0); - break; - case 'R': - if (relayed) - msg = std::make_unique(From); - else - msg = std::make_unique(From); - break; - case 'S': - msg = std::make_unique(From, relayed); - break; - case 'I': - msg = std::make_unique(From, relayed); - break; - case 'G': - if (relayed) - { - msg = std::make_unique(); - break; - } - else - { - msg = std::make_unique(From); - break; - } - default: - llarp::LogWarn("unknown dht message type: ", (char)*strbuf.base); - // bad msg type - return false; - } - firstKey = false; - return msg != nullptr; + } + default: + llarp::LogWarn("unknown dht message type: ", (char)*strbuf.base); + // bad msg type + return false; } - - return msg->DecodeKey(*key, buffer); + firstKey = false; + return msg != nullptr; } - }; - IMessage::Ptr_t - DecodeMesssage(const Key_t& from, llarp_buffer_t* buf, bool relayed) - { - MessageDecoder dec(from, relayed); - if (!bencode_read_dict(dec, buf)) - return nullptr; - - return std::move(dec.msg); + return msg->decode_key(*key, buffer); } + }; - struct ListDecoder - { - ListDecoder(bool hasRelayed, const Key_t& from, std::vector& list) - : relayed(hasRelayed), From(from), l(list) - {} + AbstractDHTMessage::Ptr_t + DecodeMessage(const Key_t& from, llarp_buffer_t* buf, bool relayed) + { + MessageDecoder dec(from, relayed); + if (!bencode_read_dict(dec, buf)) + return nullptr; - bool relayed; - const Key_t& From; - std::vector& l; + return std::move(dec.msg); + } - bool - operator()(llarp_buffer_t* buffer, bool has) - { - if (!has) - return true; - auto msg = DecodeMesssage(From, buffer, relayed); - if (msg) - { - l.emplace_back(std::move(msg)); - return true; - } + struct ListDecoder + { + ListDecoder(bool hasRelayed, const Key_t& from, std::vector& list) + : relayed(hasRelayed), From(from), l(list) + {} - return false; - } - }; + bool relayed; + const Key_t& From; + std::vector& l; bool - DecodeMesssageList( - Key_t from, llarp_buffer_t* buf, std::vector& list, bool relayed) + operator()(llarp_buffer_t* buffer, bool has) { - ListDecoder dec(relayed, from, list); - return bencode_read_list(dec, buf); + if (!has) + return true; + auto msg = DecodeMessage(From, buffer, relayed); + if (msg) + { + l.emplace_back(std::move(msg)); + return true; + } + + return false; } - } // namespace dht -} // namespace llarp + }; + + bool + DecodeMessageList( + Key_t from, llarp_buffer_t* buf, std::vector& list, bool relayed) + { + ListDecoder dec(relayed, from, list); + return bencode_read_list(dec, buf); + } +} // namespace llarp::dht diff --git a/llarp/dht/message.hpp b/llarp/dht/message.hpp index 13fdd92290..1017203c0a 100644 --- a/llarp/dht/message.hpp +++ b/llarp/dht/message.hpp @@ -2,46 +2,70 @@ #include "dht.h" #include "key.hpp" +#include #include #include #include -namespace llarp +namespace { - namespace dht + static auto dht_cat = llarp::log::Cat("lokinet.dht"); +} // namespace + +namespace llarp::dht +{ + constexpr size_t MAX_MSG_SIZE = 2048; + + struct AbstractDHTMessage : private AbstractSerializable { - constexpr size_t MAX_MSG_SIZE = 2048; + virtual ~AbstractDHTMessage() = default; - struct IMessage - { - virtual ~IMessage() = default; + /// construct + AbstractDHTMessage(const Key_t& from) : From(from) + {} - /// construct - IMessage(const Key_t& from) : From(from) - {} + using Ptr_t = std::unique_ptr; - using Ptr_t = std::unique_ptr; + virtual bool + handle_message(struct llarp_dht_context* dht, std::vector& replies) const = 0; - virtual bool - HandleMessage(struct llarp_dht_context* dht, std::vector& replies) const = 0; + void + bt_encode(oxenc::bt_dict_producer& btdp) const override = 0; - virtual bool - BEncode(llarp_buffer_t* buf) const = 0; + virtual bool + decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) = 0; + + // methods we do not want to inherit onwards from AbstractSerializable + void + bt_encode(oxenc::bt_list_producer&) const final + { + throw std::runtime_error{"Error: DHT messages should encode directly to a bt dict producer!"}; + } + void + bt_encode(llarp_buffer&) const final + { + throw std::runtime_error{"Error: DHT messages should encode directly to a bt dict producer!"}; + } + std::string + bt_encode() const final + { + throw std::runtime_error{"Error: DHT messages should encode directly to a bt dict producer!"}; + } - virtual bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) = 0; + Key_t From; + PathID_t pathID; + uint64_t version = llarp::constants::proto_version; + }; - Key_t From; - PathID_t pathID; - uint64_t version = llarp::constants::proto_version; - }; + AbstractDHTMessage::Ptr_t + DecodeMessage(const Key_t& from, llarp_buffer_t* buf, bool relayed = false); - IMessage::Ptr_t - DecodeMessage(const Key_t& from, llarp_buffer_t* buf, bool relayed = false); + bool + DecodeMessageList( + Key_t from, + llarp_buffer_t* buf, + std::vector& list, + bool relayed = false); - bool - DecodeMesssageList( - Key_t from, llarp_buffer_t* buf, std::vector& dst, bool relayed = false); - } // namespace dht -} // namespace llarp +} // namespace llarp::dht diff --git a/llarp/dht/messages/consensus.hpp b/llarp/dht/messages/consensus.hpp index f5a4312048..986823c2fc 100644 --- a/llarp/dht/messages/consensus.hpp +++ b/llarp/dht/messages/consensus.hpp @@ -2,26 +2,23 @@ #include #include -namespace llarp +namespace llarp::dht { - namespace dht + struct ConsensusMessage { - struct ConsensusMessage - { - /// H - ShortHash m_Hash; - /// K - std::vector m_Keys; - /// N - uint64_t m_NumberOfEntries; - /// O - uint64_t m_EntryOffset; - /// T - uint64_t m_TxID; - /// U - llarp_time_t m_NextUpdateRequired; - /// V - RouterVersion m_RotuerVersion; - }; - } // namespace dht -} // namespace llarp + /// H + ShortHash m_Hash; + /// K + std::vector m_Keys; + /// N + uint64_t m_NumberOfEntries; + /// O + uint64_t m_EntryOffset; + /// T + uint64_t m_TxID; + /// U + llarp_time_t m_NextUpdateRequired; + /// V + RouterVersion m_RotuerVersion; + }; +} // namespace llarp::dht diff --git a/llarp/dht/messages/findintro.cpp b/llarp/dht/messages/findintro.cpp index a898b78c1e..5eb628a3f7 100644 --- a/llarp/dht/messages/findintro.cpp +++ b/llarp/dht/messages/findintro.cpp @@ -5,135 +5,120 @@ #include #include -namespace llarp +namespace llarp::dht { - namespace dht - { - FindIntroMessage::~FindIntroMessage() = default; + FindIntroMessage::~FindIntroMessage() = default; - bool - FindIntroMessage::DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* val) - { - bool read = false; + bool + FindIntroMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* val) + { + bool read = false; - if (!BEncodeMaybeReadDictEntry("N", tagName, read, k, val)) - return false; + if (!BEncodeMaybeReadDictEntry("N", tagName, read, k, val)) + return false; - if (!BEncodeMaybeReadDictInt("O", relayOrder, read, k, val)) - return false; + if (!BEncodeMaybeReadDictInt("O", relayOrder, read, k, val)) + return false; - if (!BEncodeMaybeReadDictEntry("S", location, read, k, val)) - return false; + if (!BEncodeMaybeReadDictEntry("S", location, read, k, val)) + return false; - if (!BEncodeMaybeReadDictInt("T", txID, read, k, val)) - return false; + if (!BEncodeMaybeReadDictInt("T", txID, read, k, val)) + return false; - if (!BEncodeMaybeVerifyVersion("V", version, llarp::constants::proto_version, read, k, val)) - return false; + if (!BEncodeMaybeVerifyVersion("V", version, llarp::constants::proto_version, read, k, val)) + return false; - return read; - } + return read; + } - bool - FindIntroMessage::BEncode(llarp_buffer_t* buf) const + void + FindIntroMessage::bt_encode(oxenc::bt_dict_producer& btdp) const + { + try { - if (!bencode_start_dict(buf)) - return false; - - // message id - if (!BEncodeWriteDictMsgType(buf, "A", "F")) - return false; + btdp.append("A", "F"); if (tagName.Empty()) { - // relay order - if (!BEncodeWriteDictInt("O", relayOrder, buf)) - return false; - - // service address - if (!BEncodeWriteDictEntry("S", location, buf)) - return false; + btdp.append("O", relayOrder); + btdp.append("S", location.ToView()); } else { - if (!BEncodeWriteDictEntry("N", tagName, buf)) - return false; - - // relay order - if (!BEncodeWriteDictInt("O", relayOrder, buf)) - return false; + btdp.append("N", tagName.ToView()); + btdp.append("O", relayOrder); } - // txid - if (!BEncodeWriteDictInt("T", txID, buf)) - return false; - // protocol version - if (!BEncodeWriteDictInt("V", llarp::constants::proto_version, buf)) - return false; - - return bencode_end(buf); + + btdp.append("T", txID); + btdp.append("V", llarp::constants::proto_version); + } + catch (...) + { + log::critical(dht_cat, "FindIntroMessage failed to bt encode contents!"); } + } - bool - FindIntroMessage::HandleMessage( - llarp_dht_context* ctx, std::vector& replies) const + bool + FindIntroMessage::handle_message( + llarp_dht_context* ctx, std::vector& replies) const + { + auto& dht = *ctx->impl; + if (dht.pendingIntrosetLookups().HasPendingLookupFrom(TXOwner{From, txID})) { - auto& dht = *ctx->impl; - if (dht.pendingIntrosetLookups().HasPendingLookupFrom(TXOwner{From, txID})) - { - llarp::LogWarn("duplicate FIM from ", From, " txid=", txID); - return false; - } + llarp::LogWarn("duplicate FIM from ", From, " txid=", txID); + return false; + } - if (not tagName.Empty()) + if (not tagName.Empty()) + { + return false; + } + // bad request (request for zero-key) + if (location.IsZero()) + { + // we dont got it + replies.emplace_back(new GotIntroMessage({}, txID)); + return true; + } + + // we are relaying this message for e.g. a client + if (relayed) + { + if (relayOrder >= IntroSetStorageRedundancy) { - return false; + llarp::LogWarn("Invalid relayOrder received: ", relayOrder); + replies.emplace_back(new GotIntroMessage({}, txID)); + return true; } - // bad request (request for zero-key) - if (location.IsZero()) + + auto closestRCs = + dht.GetRouter()->nodedb()->FindManyClosestTo(location, IntroSetStorageRedundancy); + + if (closestRCs.size() <= relayOrder) { - // we dont got it + llarp::LogWarn("Can't fulfill FindIntro for relayOrder: ", relayOrder); replies.emplace_back(new GotIntroMessage({}, txID)); return true; } - // we are relaying this message for e.g. a client - if (relayed) + const auto& entry = closestRCs[relayOrder]; + Key_t peer = Key_t(entry.pubkey); + dht.LookupIntroSetForPath(location, txID, pathID, peer, 0); + } + else + { + // we should have this value if introset was propagated properly + const auto maybe = dht.GetIntroSetByLocation(location); + if (maybe) { - if (relayOrder >= IntroSetStorageRedundancy) - { - llarp::LogWarn("Invalid relayOrder received: ", relayOrder); - replies.emplace_back(new GotIntroMessage({}, txID)); - return true; - } - - auto closestRCs = - dht.GetRouter()->nodedb()->FindManyClosestTo(location, IntroSetStorageRedundancy); - - if (closestRCs.size() <= relayOrder) - { - llarp::LogWarn("Can't fulfill FindIntro for relayOrder: ", relayOrder); - replies.emplace_back(new GotIntroMessage({}, txID)); - return true; - } - - const auto& entry = closestRCs[relayOrder]; - Key_t peer = Key_t(entry.pubkey); - dht.LookupIntroSetForPath(location, txID, pathID, peer, 0); + replies.emplace_back(new GotIntroMessage({*maybe}, txID)); } else { - // we should have this value if introset was propagated properly - const auto maybe = dht.GetIntroSetByLocation(location); - if (maybe) - { - replies.emplace_back(new GotIntroMessage({*maybe}, txID)); - } - else - { - LogWarn("Got FIM with relayed == false and we don't have entry"); - replies.emplace_back(new GotIntroMessage({}, txID)); - } + LogWarn("Got FIM with relayed == false and we don't have entry"); + replies.emplace_back(new GotIntroMessage({}, txID)); } - return true; } - } // namespace dht -} // namespace llarp + return true; + } +} // namespace llarp::dht diff --git a/llarp/dht/messages/findintro.hpp b/llarp/dht/messages/findintro.hpp index b3571168e1..bfa0fac21a 100644 --- a/llarp/dht/messages/findintro.hpp +++ b/llarp/dht/messages/findintro.hpp @@ -5,44 +5,42 @@ #include #include -namespace llarp +namespace llarp::dht { - namespace dht + struct FindIntroMessage final : public AbstractDHTMessage { - struct FindIntroMessage final : public IMessage + Key_t location; + llarp::service::Tag tagName; + uint64_t txID = 0; + bool relayed = false; + uint64_t relayOrder = 0; + + FindIntroMessage(const Key_t& from, bool relay, uint64_t order) : AbstractDHTMessage(from) + { + relayed = relay; + relayOrder = order; + } + + FindIntroMessage(const llarp::service::Tag& tag, uint64_t txid) + : AbstractDHTMessage({}), tagName(tag), txID(txid) + {} + + explicit FindIntroMessage(uint64_t txid, const Key_t& addr, uint64_t order) + : AbstractDHTMessage({}), location(addr), txID(txid), relayOrder(order) { - Key_t location; - llarp::service::Tag tagName; - uint64_t txID = 0; - bool relayed = false; - uint64_t relayOrder = 0; - - FindIntroMessage(const Key_t& from, bool relay, uint64_t order) : IMessage(from) - { - relayed = relay; - relayOrder = order; - } - - FindIntroMessage(const llarp::service::Tag& tag, uint64_t txid) - : IMessage({}), tagName(tag), txID(txid) - {} - - explicit FindIntroMessage(uint64_t txid, const Key_t& addr, uint64_t order) - : IMessage({}), location(addr), txID(txid), relayOrder(order) - { - tagName.Zero(); - } - - ~FindIntroMessage() override; - - bool - BEncode(llarp_buffer_t* buf) const override; - - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) override; - - bool - HandleMessage(llarp_dht_context* ctx, std::vector& replies) const override; - }; - } // namespace dht -} // namespace llarp + tagName.Zero(); + } + + ~FindIntroMessage() override; + + void + bt_encode(oxenc::bt_dict_producer& btdp) const override; + + bool + decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; + + bool + handle_message( + llarp_dht_context* ctx, std::vector& replies) const override; + }; +} // namespace llarp::dht diff --git a/llarp/dht/messages/findname.cpp b/llarp/dht/messages/findname.cpp index 975ee2a09d..4986af2bd4 100644 --- a/llarp/dht/messages/findname.cpp +++ b/llarp/dht/messages/findname.cpp @@ -10,21 +10,26 @@ namespace llarp::dht { FindNameMessage::FindNameMessage(const Key_t& from, Key_t namehash, uint64_t txid) - : IMessage(from), NameHash(std::move(namehash)), TxID(txid) + : AbstractDHTMessage(from), NameHash(std::move(namehash)), TxID(txid) {} - bool - FindNameMessage::BEncode(llarp_buffer_t* buf) const + void + FindNameMessage::bt_encode(oxenc::bt_dict_producer& btdp) const { - const auto data = oxenc::bt_serialize(oxenc::bt_dict{ - {"A", "N"sv}, - {"H", std::string_view{(char*)NameHash.data(), NameHash.size()}}, - {"T", TxID}}); - return buf->write(data.begin(), data.end()); + try + { + btdp.append("A", "N"); + btdp.append("H", NameHash.ToView()); + btdp.append("T", TxID); + } + catch (...) + { + log::error(dht_cat, "Error: FindNameMessage failed to bt encode contents!"); + } } bool - FindNameMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) + FindNameMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) { if (key.startswith("H")) { @@ -38,7 +43,7 @@ namespace llarp::dht } bool - FindNameMessage::HandleMessage(struct llarp_dht_context* dht, std::vector& replies) const + FindNameMessage::handle_message(struct llarp_dht_context* dht, std::vector& replies) const { (void)replies; auto r = dht->impl->GetRouter(); diff --git a/llarp/dht/messages/findname.hpp b/llarp/dht/messages/findname.hpp index de02300ee4..ee29365cc0 100644 --- a/llarp/dht/messages/findname.hpp +++ b/llarp/dht/messages/findname.hpp @@ -4,18 +4,18 @@ namespace llarp::dht { - struct FindNameMessage : public IMessage + struct FindNameMessage : public AbstractDHTMessage { explicit FindNameMessage(const Key_t& from, Key_t namehash, uint64_t txid); - bool - BEncode(llarp_buffer_t* buf) const override; + void + bt_encode(oxenc::bt_dict_producer& btdp) const override; bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) override; + decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; bool - HandleMessage(struct llarp_dht_context* dht, std::vector& replies) const override; + handle_message(struct llarp_dht_context* dht, std::vector& replies) const override; Key_t NameHash; uint64_t TxID; diff --git a/llarp/dht/messages/findrouter.cpp b/llarp/dht/messages/findrouter.cpp index 35978122d7..80fed57319 100644 --- a/llarp/dht/messages/findrouter.cpp +++ b/llarp/dht/messages/findrouter.cpp @@ -9,172 +9,142 @@ #include -namespace llarp +namespace llarp::dht { - namespace dht + bool + RelayedFindRouterMessage::handle_message( + llarp_dht_context* ctx, std::vector>& replies) const { - bool - RelayedFindRouterMessage::HandleMessage( - llarp_dht_context* ctx, std::vector>& replies) const + auto& dht = *ctx->impl; + /// lookup for us, send an immeidate reply + const Key_t us = dht.OurKey(); + const Key_t k{targetKey}; + if (k == us) { - auto& dht = *ctx->impl; - /// lookup for us, send an immeidate reply - const Key_t us = dht.OurKey(); - const Key_t k{targetKey}; - if (k == us) + auto path = dht.GetRouter()->pathContext().GetByUpstream(targetKey, pathID); + if (path) { - auto path = dht.GetRouter()->pathContext().GetByUpstream(targetKey, pathID); - if (path) - { - replies.emplace_back(new GotRouterMessage(k, txid, {dht.GetRouter()->rc()}, false)); - return true; - } - return false; - } - - Key_t peer; - // check if we know this in our nodedb first - if (not dht.GetRouter()->SessionToRouterAllowed(targetKey)) - { - // explicitly disallowed by network - replies.emplace_back(new GotRouterMessage(k, txid, {}, false)); - return true; - } - // check netdb - const auto rc = dht.GetRouter()->nodedb()->FindClosestTo(k); - if (rc.pubkey == targetKey) - { - replies.emplace_back(new GotRouterMessage(k, txid, {rc}, false)); + replies.emplace_back(new GotRouterMessage(k, txid, {dht.GetRouter()->rc()}, false)); return true; } - peer = Key_t(rc.pubkey); - // lookup if we don't have it in our nodedb - dht.LookupRouterForPath(targetKey, txid, pathID, peer); + return false; + } + + Key_t peer; + // check if we know this in our nodedb first + if (not dht.GetRouter()->SessionToRouterAllowed(targetKey)) + { + // explicitly disallowed by network + replies.emplace_back(new GotRouterMessage(k, txid, {}, false)); return true; } + // check netdb + const auto rc = dht.GetRouter()->nodedb()->FindClosestTo(k); + if (rc.pubkey == targetKey) + { + replies.emplace_back(new GotRouterMessage(k, txid, {rc}, false)); + return true; + } + peer = Key_t(rc.pubkey); + // lookup if we don't have it in our nodedb + dht.LookupRouterForPath(targetKey, txid, pathID, peer); + return true; + } - FindRouterMessage::~FindRouterMessage() = default; + FindRouterMessage::~FindRouterMessage() = default; - bool - FindRouterMessage::BEncode(llarp_buffer_t* buf) const + void + FindRouterMessage::bt_encode(oxenc::bt_dict_producer& btdp) const + { + try { - if (!bencode_start_dict(buf)) - return false; - - // message type - if (!bencode_write_bytestring(buf, "A", 1)) - return false; - if (!bencode_write_bytestring(buf, "R", 1)) - return false; + btdp.append("A", "R"); + btdp.append("T", exploratory ? 1 : 0); + btdp.append("I", iterative ? 1 : 0); + btdp.append("K", targetKey.ToView()); + btdp.append("T", txid); + btdp.append("V", version); + } + catch (...) + { + log::error(dht_cat, "Error: FindRouterMessage failed to bt encode contents!"); + } + } - // exploritory or not? - if (!bencode_write_bytestring(buf, "E", 1)) - return false; - if (!bencode_write_uint64(buf, exploritory ? 1 : 0)) - return false; + bool + FindRouterMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) + { + llarp_buffer_t strbuf; - // iterative or not? - if (!bencode_write_bytestring(buf, "I", 1)) - return false; - if (!bencode_write_uint64(buf, iterative ? 1 : 0)) + if (key.startswith("E")) + { + uint64_t result; + if (!bencode_read_integer(val, &result)) return false; - // key - if (!bencode_write_bytestring(buf, "K", 1)) - return false; - if (!bencode_write_bytestring(buf, targetKey.data(), targetKey.size())) - return false; + exploratory = result != 0; + return true; + } - // txid - if (!bencode_write_bytestring(buf, "T", 1)) - return false; - if (!bencode_write_uint64(buf, txid)) + if (key.startswith("I")) + { + uint64_t result; + if (!bencode_read_integer(val, &result)) return false; - // version - if (!bencode_write_bytestring(buf, "V", 1)) + iterative = result != 0; + return true; + } + if (key.startswith("K")) + { + if (!bencode_read_string(val, &strbuf)) return false; - if (!bencode_write_uint64(buf, version)) + if (strbuf.sz != targetKey.size()) return false; - return bencode_end(buf); + std::copy(strbuf.base, strbuf.base + targetKey.SIZE, targetKey.begin()); + return true; } - - bool - FindRouterMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) + if (key.startswith("T")) { - llarp_buffer_t strbuf; - - if (key.startswith("E")) - { - uint64_t result; - if (!bencode_read_integer(val, &result)) - return false; + return bencode_read_integer(val, &txid); + } + if (key.startswith("V")) + { + return bencode_read_integer(val, &version); + } + return false; + } - exploritory = result != 0; - return true; - } + bool + FindRouterMessage::handle_message( + llarp_dht_context* ctx, std::vector>& replies) const + { + auto& dht = *ctx->impl; - if (key.startswith("I")) - { - uint64_t result; - if (!bencode_read_integer(val, &result)) - return false; + auto router = dht.GetRouter(); + router->NotifyRouterEvent(router->pubkey(), *this); - iterative = result != 0; - return true; - } - if (key.startswith("K")) - { - if (!bencode_read_string(val, &strbuf)) - return false; - if (strbuf.sz != targetKey.size()) - return false; - - std::copy(strbuf.base, strbuf.base + targetKey.SIZE, targetKey.begin()); - return true; - } - if (key.startswith("T")) - { - return bencode_read_integer(val, &txid); - } - if (key.startswith("V")) - { - return bencode_read_integer(val, &version); - } + if (!dht.AllowTransit()) + { + llarp::LogWarn("Got DHT lookup from ", From, " when we are not allowing dht transit"); return false; } - - bool - FindRouterMessage::HandleMessage( - llarp_dht_context* ctx, std::vector>& replies) const + if (dht.pendingRouterLookups().HasPendingLookupFrom({From, txid})) { - auto& dht = *ctx->impl; - - auto router = dht.GetRouter(); - router->NotifyRouterEvent(router->pubkey(), *this); - - if (!dht.AllowTransit()) - { - llarp::LogWarn("Got DHT lookup from ", From, " when we are not allowing dht transit"); - return false; - } - if (dht.pendingRouterLookups().HasPendingLookupFrom({From, txid})) - { - llarp::LogWarn("Duplicate FRM from ", From, " txid=", txid); - return false; - } - RouterContact found; - if (targetKey.IsZero()) - { - llarp::LogError("invalid FRM from ", From, " key is zero"); - return false; - } - const Key_t k(targetKey); - if (exploritory) - return dht.HandleExploritoryRouterLookup(From, txid, targetKey, replies); - dht.LookupRouterRelayed(From, txid, k, !iterative, replies); - return true; + llarp::LogWarn("Duplicate FRM from ", From, " txid=", txid); + return false; + } + RouterContact found; + if (targetKey.IsZero()) + { + llarp::LogError("invalid FRM from ", From, " key is zero"); + return false; } - } // namespace dht -} // namespace llarp + const Key_t k(targetKey); + if (exploratory) + return dht.HandleExploritoryRouterLookup(From, txid, targetKey, replies); + dht.LookupRouterRelayed(From, txid, k, !iterative, replies); + return true; + } +} // namespace llarp::dht diff --git a/llarp/dht/messages/findrouter.hpp b/llarp/dht/messages/findrouter.hpp index 9ff4b09a52..9a34c018c9 100644 --- a/llarp/dht/messages/findrouter.hpp +++ b/llarp/dht/messages/findrouter.hpp @@ -1,57 +1,56 @@ #pragma once #include -namespace llarp +namespace llarp::dht { - namespace dht + struct FindRouterMessage : public AbstractDHTMessage { - struct FindRouterMessage : public IMessage - { - // inbound parsing - FindRouterMessage(const Key_t& from) : IMessage(from) - {} - - // find by routerid - FindRouterMessage(uint64_t id, const RouterID& target) - : IMessage({}), targetKey(target), txid(id) - {} - - // exploritory - FindRouterMessage(uint64_t id) : IMessage({}), exploritory(true), txid(id) - { - targetKey.Randomize(); - } - - ~FindRouterMessage() override; - - bool - BEncode(llarp_buffer_t* buf) const override; - - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) override; - - bool - HandleMessage( - llarp_dht_context* ctx, std::vector>& replies) const override; - - RouterID targetKey; - bool iterative = false; - bool exploritory = false; - uint64_t txid = 0; - uint64_t version = 0; - }; - - /// variant of FindRouterMessage relayed via path - struct RelayedFindRouterMessage final : public FindRouterMessage + // inbound parsing + FindRouterMessage(const Key_t& from) : AbstractDHTMessage(from) + {} + + // find by routerid + FindRouterMessage(uint64_t id, const RouterID& target) + : AbstractDHTMessage({}), targetKey(target), txid(id) + {} + + // exploritory + FindRouterMessage(uint64_t id) : AbstractDHTMessage({}), exploratory(true), txid(id) { - RelayedFindRouterMessage(const Key_t& from) : FindRouterMessage(from) - {} - - /// handle a relayed FindRouterMessage, do a lookup on the dht and inform - /// the path of the result - /// TODO: smart path expiration logic needs to be implemented - bool - HandleMessage(llarp_dht_context* ctx, std::vector& replies) const override; - }; - } // namespace dht -} // namespace llarp + targetKey.Randomize(); + } + + ~FindRouterMessage() override; + + void + bt_encode(oxenc::bt_dict_producer& btdp) const override; + + bool + decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; + + bool + handle_message( + llarp_dht_context* ctx, + std::vector>& replies) const override; + + RouterID targetKey; + bool iterative = false; + bool exploratory = false; + uint64_t txid = 0; + uint64_t version = 0; + }; + + /// variant of FindRouterMessage relayed via path + struct RelayedFindRouterMessage final : public FindRouterMessage + { + RelayedFindRouterMessage(const Key_t& from) : FindRouterMessage(from) + {} + + /// handle a relayed FindRouterMessage, do a lookup on the dht and inform + /// the path of the result + /// TODO: smart path expiration logic needs to be implemented + bool + handle_message( + llarp_dht_context* ctx, std::vector& replies) const override; + }; +} // namespace llarp::dht diff --git a/llarp/dht/messages/gotintro.cpp b/llarp/dht/messages/gotintro.cpp index f96a9cd4bb..628fa2924c 100644 --- a/llarp/dht/messages/gotintro.cpp +++ b/llarp/dht/messages/gotintro.cpp @@ -9,117 +9,118 @@ #include #include -namespace llarp +namespace llarp::dht { - namespace dht - { - GotIntroMessage::GotIntroMessage(std::vector results, uint64_t tx) - : IMessage({}), found(std::move(results)), txid(tx) - {} + GotIntroMessage::GotIntroMessage(std::vector results, uint64_t tx) + : AbstractDHTMessage({}), found(std::move(results)), txid(tx) + {} - bool - GotIntroMessage::HandleMessage( - llarp_dht_context* ctx, std::vector>& /*replies*/) const - { - auto& dht = *ctx->impl; - auto* router = dht.GetRouter(); + bool + GotIntroMessage::handle_message( + llarp_dht_context* ctx, std::vector>& /*replies*/) const + { + auto& dht = *ctx->impl; + auto* router = dht.GetRouter(); - router->NotifyRouterEvent( - router->pubkey(), - Key_t(From.data()), - (found.size() > 0 ? found[0] : llarp::service::EncryptedIntroSet{}), - txid); + router->NotifyRouterEvent( + router->pubkey(), + Key_t(From.data()), + (found.size() > 0 ? found[0] : llarp::service::EncryptedIntroSet{}), + txid); - for (const auto& introset : found) + for (const auto& introset : found) + { + if (!introset.Verify(dht.Now())) { - if (!introset.Verify(dht.Now())) - { - LogWarn( - "Invalid introset while handling direct GotIntro " - "from ", - From); - return false; - } + LogWarn( + "Invalid introset while handling direct GotIntro " + "from ", + From); + return false; } - TXOwner owner(From, txid); + } + TXOwner owner(From, txid); - auto serviceLookup = dht.pendingIntrosetLookups().GetPendingLookupFrom(owner); - if (serviceLookup) + auto serviceLookup = dht.pendingIntrosetLookups().GetPendingLookupFrom(owner); + if (serviceLookup) + { + if (not found.empty()) { - if (not found.empty()) - { - dht.pendingIntrosetLookups().Found(owner, serviceLookup->target, found); - } - else - { - dht.pendingIntrosetLookups().NotFound(owner, nullptr); - } - return true; + dht.pendingIntrosetLookups().Found(owner, serviceLookup->target, found); } - LogError("no pending TX for GIM from ", From, " txid=", txid); - return false; + else + { + dht.pendingIntrosetLookups().NotFound(owner, nullptr); + } + return true; } + LogError("no pending TX for GIM from ", From, " txid=", txid); + return false; + } - bool - RelayedGotIntroMessage::HandleMessage( - llarp_dht_context* ctx, - [[maybe_unused]] std::vector>& replies) const + bool + RelayedGotIntroMessage::handle_message( + llarp_dht_context* ctx, + [[maybe_unused]] std::vector>& replies) const + { + // TODO: implement me better? + auto pathset = ctx->impl->GetRouter()->pathContext().GetLocalPathSet(pathID); + if (pathset) { - // TODO: implement me better? - auto pathset = ctx->impl->GetRouter()->pathContext().GetLocalPathSet(pathID); - if (pathset) - { - auto copy = std::make_shared(*this); - return pathset->HandleGotIntroMessage(copy); - } - LogWarn("No path for got intro message pathid=", pathID); - return false; + auto copy = std::make_shared(*this); + return pathset->HandleGotIntroMessage(copy); } + LogWarn("No path for got intro message pathid=", pathID); + return false; + } - bool - GotIntroMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) + bool + GotIntroMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) + { + if (key.startswith("I")) { - if (key.startswith("I")) - { - return BEncodeReadList(found, buf); - } - if (key.startswith("K")) - { - if (closer) // duplicate key? - return false; - dht::Key_t K; - if (not K.BDecode(buf)) - return false; - closer = K; - return true; - } - bool read = false; - if (!BEncodeMaybeReadDictInt("T", txid, read, key, buf)) + return BEncodeReadList(found, buf); + } + if (key.startswith("K")) + { + if (closer) // duplicate key? return false; - if (!BEncodeMaybeReadDictInt("V", version, read, key, buf)) + dht::Key_t K; + if (not K.BDecode(buf)) return false; - return read; + closer = K; + return true; } + bool read = false; + if (!BEncodeMaybeReadDictInt("T", txid, read, key, buf)) + return false; + if (!BEncodeMaybeReadDictInt("V", version, read, key, buf)) + return false; + return read; + } - bool - GotIntroMessage::BEncode(llarp_buffer_t* buf) const + void + GotIntroMessage::bt_encode(oxenc::bt_dict_producer& btdp) const + { + try { - if (!bencode_start_dict(buf)) - return false; - if (!BEncodeWriteDictMsgType(buf, "A", "G")) - return false; - if (!BEncodeWriteDictList("I", found, buf)) - return false; - if (closer) + btdp.append("A", "G"); + { - if (!BEncodeWriteDictEntry("K", *closer, buf)) - return false; + auto sublist = btdp.append_list("I"); + for (auto f : found) + sublist.append(f.ToString()); } - if (!BEncodeWriteDictInt("T", txid, buf)) - return false; - if (!BEncodeWriteDictInt("V", version, buf)) - return false; - return bencode_end(buf); + + if (closer) + btdp.append("K", closer->ToView()); + + btdp.append("T", txid); + btdp.append("V", version); + } + catch (...) + { + log::error(dht_cat, "Error: GotIntroMessage failed to bt encode contents!"); } - } // namespace dht -} // namespace llarp + } +} // namespace llarp::dht diff --git a/llarp/dht/messages/gotintro.hpp b/llarp/dht/messages/gotintro.hpp index 3e9fda6b01..e5c288cfa4 100644 --- a/llarp/dht/messages/gotintro.hpp +++ b/llarp/dht/messages/gotintro.hpp @@ -7,58 +7,57 @@ #include #include -namespace llarp +namespace llarp::dht { - namespace dht + /// acknowledgement to PublishIntroMessage or reply to FindIntroMessage + struct GotIntroMessage : public AbstractDHTMessage { - /// acknowledgement to PublishIntroMessage or reply to FindIntroMessage - struct GotIntroMessage : public IMessage + /// the found introsets + std::vector found; + /// txid + uint64_t txid = 0; + /// the key of a router closer in keyspace if iterative lookup + std::optional closer; + + GotIntroMessage(const Key_t& from) : AbstractDHTMessage(from) + {} + + GotIntroMessage(const GotIntroMessage& other) + : AbstractDHTMessage(other.From), found(other.found), txid(other.txid), closer(other.closer) { - /// the found introsets - std::vector found; - /// txid - uint64_t txid = 0; - /// the key of a router closer in keyspace if iterative lookup - std::optional closer; + version = other.version; + } - GotIntroMessage(const Key_t& from) : IMessage(from) - {} + /// for iterative reply + GotIntroMessage(const Key_t& from, const Key_t& _closer, uint64_t _txid) + : AbstractDHTMessage(from), txid(_txid), closer(_closer) + {} - GotIntroMessage(const GotIntroMessage& other) - : IMessage(other.From), found(other.found), txid(other.txid), closer(other.closer) - { - version = other.version; - } + /// for recursive reply + GotIntroMessage(std::vector results, uint64_t txid); - /// for iterative reply - GotIntroMessage(const Key_t& from, const Key_t& _closer, uint64_t _txid) - : IMessage(from), txid(_txid), closer(_closer) - {} + ~GotIntroMessage() override = default; - /// for recursive reply - GotIntroMessage(std::vector results, uint64_t txid); + void + bt_encode(oxenc::bt_dict_producer& btdp) const override; - ~GotIntroMessage() override = default; + bool + decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; - bool - BEncode(llarp_buffer_t* buf) const override; + bool + handle_message( + llarp_dht_context* ctx, std::vector& replies) const override; + }; - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) override; - - bool - HandleMessage(llarp_dht_context* ctx, std::vector& replies) const override; - }; - - struct RelayedGotIntroMessage final : public GotIntroMessage - { - RelayedGotIntroMessage() : GotIntroMessage({}) - {} + struct RelayedGotIntroMessage final : public GotIntroMessage + { + RelayedGotIntroMessage() : GotIntroMessage({}) + {} - bool - HandleMessage(llarp_dht_context* ctx, std::vector& replies) const override; - }; + bool + handle_message( + llarp_dht_context* ctx, std::vector& replies) const override; + }; - using GotIntroMessage_constptr = std::shared_ptr; - } // namespace dht -} // namespace llarp + using GotIntroMessage_constptr = std::shared_ptr; +} // namespace llarp::dht diff --git a/llarp/dht/messages/gotname.cpp b/llarp/dht/messages/gotname.cpp index 78c0f2e74b..20dc274fd9 100644 --- a/llarp/dht/messages/gotname.cpp +++ b/llarp/dht/messages/gotname.cpp @@ -9,23 +9,30 @@ namespace llarp::dht constexpr size_t NameSizeLimit = 128; GotNameMessage::GotNameMessage(const Key_t& from, uint64_t txid, service::EncryptedName data) - : IMessage(from), result(std::move(data)), TxID(txid) + : AbstractDHTMessage(from), result(std::move(data)), TxID(txid) { if (result.ciphertext.size() > NameSizeLimit) throw std::invalid_argument("name data too big"); } - bool - GotNameMessage::BEncode(llarp_buffer_t* buf) const + void + GotNameMessage::bt_encode(oxenc::bt_dict_producer& btdp) const { - const std::string nonce((const char*)result.nonce.data(), result.nonce.size()); - const auto data = oxenc::bt_serialize( - oxenc::bt_dict{{"A", "M"sv}, {"D", result.ciphertext}, {"N", nonce}, {"T", TxID}}); - return buf->write(data.begin(), data.end()); + try + { + btdp.append("A", "M"); + btdp.append("D", result.ciphertext); + btdp.append("N", result.nonce.ToView()); + btdp.append("T", TxID); + } + catch (...) + { + log::error(dht_cat, "Error: GotNameMessage failed to bt encode contents!"); + } } bool - GotNameMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) + GotNameMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) { if (key.startswith("D")) { @@ -50,7 +57,7 @@ namespace llarp::dht } bool - GotNameMessage::HandleMessage(struct llarp_dht_context* ctx, std::vector&) const + GotNameMessage::handle_message(struct llarp_dht_context* ctx, std::vector&) const { auto pathset = ctx->impl->GetRouter()->pathContext().GetLocalPathSet(pathID); if (pathset == nullptr) diff --git a/llarp/dht/messages/gotname.hpp b/llarp/dht/messages/gotname.hpp index 6575e21f55..d6400cf52e 100644 --- a/llarp/dht/messages/gotname.hpp +++ b/llarp/dht/messages/gotname.hpp @@ -5,21 +5,20 @@ namespace llarp::dht { - struct GotNameMessage : public IMessage + struct GotNameMessage : public AbstractDHTMessage { explicit GotNameMessage(const Key_t& from, uint64_t txid, service::EncryptedName data); - bool - BEncode(llarp_buffer_t* buf) const override; + void + bt_encode(oxenc::bt_dict_producer& btdp) const override; bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) override; + decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; bool - HandleMessage(struct llarp_dht_context* dht, std::vector& replies) const override; + handle_message(struct llarp_dht_context* dht, std::vector& replies) const override; service::EncryptedName result; uint64_t TxID; }; - } // namespace llarp::dht diff --git a/llarp/dht/messages/gotrouter.cpp b/llarp/dht/messages/gotrouter.cpp index 46bb89303f..33b4920582 100644 --- a/llarp/dht/messages/gotrouter.cpp +++ b/llarp/dht/messages/gotrouter.cpp @@ -7,133 +7,126 @@ #include #include -namespace llarp +namespace llarp::dht { - namespace dht - { - GotRouterMessage::~GotRouterMessage() = default; + GotRouterMessage::~GotRouterMessage() = default; - bool - GotRouterMessage::BEncode(llarp_buffer_t* buf) const + void + GotRouterMessage::bt_encode(oxenc::bt_dict_producer& btdp) const + { + try { - if (not bencode_start_dict(buf)) - return false; - - // message type - if (not BEncodeWriteDictMsgType(buf, "A", "S")) - return false; + btdp.append("A", "S"); if (closerTarget) + btdp.append("K", closerTarget->ToView()); + { - if (not BEncodeWriteDictEntry("K", *closerTarget, buf)) - return false; + auto sublist = btdp.append_list("N"); + + for (auto& k : nearKeys) + sublist.append(k.ToView()); } - // near - if (not nearKeys.empty()) { - if (not BEncodeWriteDictList("N", nearKeys, buf)) - return false; + auto sublist = btdp.append_list("R"); + + for (auto& r : foundRCs) + sublist.append(r.ToString()); } - if (not BEncodeWriteDictList("R", foundRCs, buf)) - return false; + btdp.append("T", txid); + btdp.append("V", version); + } + catch (...) + { + log::error(dht_cat, "Error: GotRouterMessage failed to bt encode contents!"); + } + } - // txid - if (not BEncodeWriteDictInt("T", txid, buf)) + bool + GotRouterMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) + { + if (key.startswith("K")) + { + if (closerTarget) // duplicate key? return false; + closerTarget = std::make_unique(); + return closerTarget->BDecode(val); + } + if (key.startswith("N")) + { + return BEncodeReadList(nearKeys, val); + } + if (key.startswith("R")) + { + return BEncodeReadList(foundRCs, val); + } + if (key.startswith("T")) + { + return bencode_read_integer(val, &txid); + } + bool read = false; + if (!BEncodeMaybeVerifyVersion("V", version, llarp::constants::proto_version, read, key, val)) + return false; - // version - if (not BEncodeWriteDictInt("V", version, buf)) - return false; + return read; + } - return bencode_end(buf); + bool + GotRouterMessage::handle_message( + llarp_dht_context* ctx, + [[maybe_unused]] std::vector>& replies) const + { + auto& dht = *ctx->impl; + if (relayed) + { + auto pathset = ctx->impl->GetRouter()->pathContext().GetLocalPathSet(pathID); + auto copy = std::make_shared(*this); + return pathset && pathset->HandleGotRouterMessage(copy); } + // not relayed + const TXOwner owner(From, txid); - bool - GotRouterMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) + if (dht.pendingExploreLookups().HasPendingLookupFrom(owner)) { - if (key.startswith("K")) - { - if (closerTarget) // duplicate key? - return false; - closerTarget = std::make_unique(); - return closerTarget->BDecode(val); - } - if (key.startswith("N")) + LogDebug("got ", nearKeys.size(), " results in GRM for explore"); + if (nearKeys.empty()) + dht.pendingExploreLookups().NotFound(owner, closerTarget); + else { - return BEncodeReadList(nearKeys, val); + dht.pendingExploreLookups().Found(owner, From.as_array(), nearKeys); } - if (key.startswith("R")) - { - return BEncodeReadList(foundRCs, val); - } - if (key.startswith("T")) - { - return bencode_read_integer(val, &txid); - } - bool read = false; - if (!BEncodeMaybeVerifyVersion("V", version, llarp::constants::proto_version, read, key, val)) + return true; + } + // not explore lookup + if (dht.pendingRouterLookups().HasPendingLookupFrom(owner)) + { + LogDebug("got ", foundRCs.size(), " results in GRM for lookup"); + if (foundRCs.empty()) + dht.pendingRouterLookups().NotFound(owner, closerTarget); + else if (foundRCs[0].pubkey.IsZero()) return false; - - return read; + else + dht.pendingRouterLookups().Found(owner, foundRCs[0].pubkey, foundRCs); + return true; } - - bool - GotRouterMessage::HandleMessage( - llarp_dht_context* ctx, - [[maybe_unused]] std::vector>& replies) const + // store if valid + for (const auto& rc : foundRCs) { - auto& dht = *ctx->impl; - if (relayed) - { - auto pathset = ctx->impl->GetRouter()->pathContext().GetLocalPathSet(pathID); - auto copy = std::make_shared(*this); - return pathset && pathset->HandleGotRouterMessage(copy); - } - // not relayed - const TXOwner owner(From, txid); - - if (dht.pendingExploreLookups().HasPendingLookupFrom(owner)) - { - LogDebug("got ", nearKeys.size(), " results in GRM for explore"); - if (nearKeys.empty()) - dht.pendingExploreLookups().NotFound(owner, closerTarget); - else - { - dht.pendingExploreLookups().Found(owner, From.as_array(), nearKeys); - } - return true; - } - // not explore lookup - if (dht.pendingRouterLookups().HasPendingLookupFrom(owner)) - { - LogDebug("got ", foundRCs.size(), " results in GRM for lookup"); - if (foundRCs.empty()) - dht.pendingRouterLookups().NotFound(owner, closerTarget); - else if (foundRCs[0].pubkey.IsZero()) - return false; - else - dht.pendingRouterLookups().Found(owner, foundRCs[0].pubkey, foundRCs); - return true; - } - // store if valid - for (const auto& rc : foundRCs) + if (not dht.GetRouter()->rcLookupHandler().CheckRC(rc)) + return false; + if (txid == 0) // txid == 0 on gossip { - if (not dht.GetRouter()->rcLookupHandler().CheckRC(rc)) - return false; - if (txid == 0) // txid == 0 on gossip - { - auto* router = dht.GetRouter(); - router->NotifyRouterEvent(router->pubkey(), rc); - router->GossipRCIfNeeded(rc); + auto* router = dht.GetRouter(); + router->NotifyRouterEvent(router->pubkey(), rc); + router->GossipRCIfNeeded(rc); - auto peerDb = router->peerDb(); - if (peerDb) - peerDb->handleGossipedRC(rc); - } + auto peerDb = router->peerDb(); + if (peerDb) + peerDb->handleGossipedRC(rc); } - return true; } - } // namespace dht -} // namespace llarp + return true; + } +} // namespace llarp::dht diff --git a/llarp/dht/messages/gotrouter.hpp b/llarp/dht/messages/gotrouter.hpp index 55a74f98e2..2e7294a15b 100644 --- a/llarp/dht/messages/gotrouter.hpp +++ b/llarp/dht/messages/gotrouter.hpp @@ -6,63 +6,61 @@ #include #include -namespace llarp +namespace llarp::dht { - namespace dht + struct GotRouterMessage final : public AbstractDHTMessage { - struct GotRouterMessage final : public IMessage - { - GotRouterMessage(const Key_t& from, bool tunneled) : IMessage(from), relayed(tunneled) - {} - GotRouterMessage( - const Key_t& from, uint64_t id, const std::vector& results, bool tunneled) - : IMessage(from), foundRCs(results), txid(id), relayed(tunneled) - {} + GotRouterMessage(const Key_t& from, bool tunneled) : AbstractDHTMessage(from), relayed(tunneled) + {} + GotRouterMessage( + const Key_t& from, uint64_t id, const std::vector& results, bool tunneled) + : AbstractDHTMessage(from), foundRCs(results), txid(id), relayed(tunneled) + {} - GotRouterMessage(const Key_t& from, const Key_t& closer, uint64_t id, bool tunneled) - : IMessage(from), closerTarget(new Key_t(closer)), txid(id), relayed(tunneled) - {} + GotRouterMessage(const Key_t& from, const Key_t& closer, uint64_t id, bool tunneled) + : AbstractDHTMessage(from), closerTarget(new Key_t(closer)), txid(id), relayed(tunneled) + {} - GotRouterMessage(uint64_t id, std::vector _near, bool tunneled) - : IMessage({}), nearKeys(std::move(_near)), txid(id), relayed(tunneled) - {} + GotRouterMessage(uint64_t id, std::vector _near, bool tunneled) + : AbstractDHTMessage({}), nearKeys(std::move(_near)), txid(id), relayed(tunneled) + {} - /// gossip message - GotRouterMessage(const RouterContact rc) : IMessage({}), foundRCs({rc}), txid(0) - { - version = llarp::constants::proto_version; - } + /// gossip message + GotRouterMessage(const RouterContact rc) : AbstractDHTMessage({}), foundRCs({rc}), txid(0) + { + version = llarp::constants::proto_version; + } - GotRouterMessage(const GotRouterMessage& other) - : IMessage(other.From) - , foundRCs(other.foundRCs) - , nearKeys(other.nearKeys) - , closerTarget(copy_or_nullptr(other.closerTarget)) - , txid(other.txid) - , relayed(other.relayed) - { - version = other.version; - } + GotRouterMessage(const GotRouterMessage& other) + : AbstractDHTMessage(other.From) + , foundRCs(other.foundRCs) + , nearKeys(other.nearKeys) + , closerTarget(copy_or_nullptr(other.closerTarget)) + , txid(other.txid) + , relayed(other.relayed) + { + version = other.version; + } - ~GotRouterMessage() override; + ~GotRouterMessage() override; - bool - BEncode(llarp_buffer_t* buf) const override; + void + bt_encode(oxenc::bt_dict_producer& btdp) const override; - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) override; + bool + decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; - bool - HandleMessage( - llarp_dht_context* ctx, std::vector>& replies) const override; + bool + handle_message( + llarp_dht_context* ctx, + std::vector>& replies) const override; - std::vector foundRCs; - std::vector nearKeys; - std::unique_ptr closerTarget; - uint64_t txid = 0; - bool relayed = false; - }; + std::vector foundRCs; + std::vector nearKeys; + std::unique_ptr closerTarget; + uint64_t txid = 0; + bool relayed = false; + }; - using GotRouterMessage_constptr = std::shared_ptr; - } // namespace dht -} // namespace llarp + using GotRouterMessage_constptr = std::shared_ptr; +} // namespace llarp::dht diff --git a/llarp/dht/messages/pubintro.cpp b/llarp/dht/messages/pubintro.cpp index b80424fc76..dc54c9f157 100644 --- a/llarp/dht/messages/pubintro.cpp +++ b/llarp/dht/messages/pubintro.cpp @@ -9,194 +9,184 @@ #include -namespace llarp +namespace llarp::dht { - namespace dht + const uint64_t PublishIntroMessage::MaxPropagationDepth = 5; + PublishIntroMessage::~PublishIntroMessage() = default; + + bool + PublishIntroMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) { - const uint64_t PublishIntroMessage::MaxPropagationDepth = 5; - PublishIntroMessage::~PublishIntroMessage() = default; + bool read = false; + if (!BEncodeMaybeReadDictEntry("I", introset, read, key, val)) + return false; + if (read) + return true; + + if (!BEncodeMaybeReadDictInt("O", relayOrder, read, key, val)) + return false; + if (read) + return true; - bool - PublishIntroMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) + uint64_t relayedInt = (relayed ? 1 : 0); + if (!BEncodeMaybeReadDictInt("R", relayedInt, read, key, val)) + return false; + if (read) { - bool read = false; - if (!BEncodeMaybeReadDictEntry("I", introset, read, key, val)) - return false; - if (read) - return true; + relayed = relayedInt; + return true; + } - if (!BEncodeMaybeReadDictInt("O", relayOrder, read, key, val)) - return false; - if (read) - return true; + if (!BEncodeMaybeReadDictInt("T", txID, read, key, val)) + return false; + if (read) + return true; - uint64_t relayedInt = (relayed ? 1 : 0); - if (!BEncodeMaybeReadDictInt("R", relayedInt, read, key, val)) - return false; - if (read) - { - relayed = relayedInt; - return true; - } + if (!BEncodeMaybeReadDictInt("V", version, read, key, val)) + return false; + if (read) + return true; - if (!BEncodeMaybeReadDictInt("T", txID, read, key, val)) - return false; - if (read) - return true; + return false; + } - if (!BEncodeMaybeReadDictInt("V", version, read, key, val)) - return false; - if (read) - return true; + bool + PublishIntroMessage::handle_message( + llarp_dht_context* ctx, std::vector>& replies) const + { + const auto now = ctx->impl->Now(); + const llarp::dht::Key_t addr{introset.derivedSigningKey.data()}; - return false; + auto router = ctx->impl->GetRouter(); + router->NotifyRouterEvent( + router->pubkey(), Key_t(relayed ? router->pubkey() : From.data()), addr, txID, relayOrder); + + auto& dht = *ctx->impl; + if (!introset.Verify(now)) + { + llarp::LogWarn("Received PublishIntroMessage with invalid introset: ", introset); + // don't propogate or store + replies.emplace_back(new GotIntroMessage({}, txID)); + return true; } - bool - PublishIntroMessage::HandleMessage( - llarp_dht_context* ctx, std::vector>& replies) const + if (introset.IsExpired(now + llarp::service::MAX_INTROSET_TIME_DELTA)) { - const auto now = ctx->impl->Now(); - const llarp::dht::Key_t addr{introset.derivedSigningKey.data()}; - - auto router = ctx->impl->GetRouter(); - router->NotifyRouterEvent( - router->pubkey(), - Key_t(relayed ? router->pubkey() : From.data()), - addr, - txID, - relayOrder); - - auto& dht = *ctx->impl; - if (!introset.Verify(now)) - { - llarp::LogWarn("Received PublishIntroMessage with invalid introset: ", introset); - // don't propogate or store - replies.emplace_back(new GotIntroMessage({}, txID)); - return true; - } + // don't propogate or store + llarp::LogWarn("Received PublishIntroMessage with expired Introset: ", introset); + replies.emplace_back(new GotIntroMessage({}, txID)); + return true; + } - if (introset.IsExpired(now + llarp::service::MAX_INTROSET_TIME_DELTA)) - { - // don't propogate or store - llarp::LogWarn("Received PublishIntroMessage with expired Introset: ", introset); - replies.emplace_back(new GotIntroMessage({}, txID)); - return true; - } + // identify closest 4 routers + auto closestRCs = dht.GetRouter()->nodedb()->FindManyClosestTo(addr, IntroSetStorageRedundancy); + if (closestRCs.size() != IntroSetStorageRedundancy) + { + llarp::LogWarn("Received PublishIntroMessage but only know ", closestRCs.size(), " nodes"); + replies.emplace_back(new GotIntroMessage({}, txID)); + return true; + } - // identify closest 4 routers - auto closestRCs = - dht.GetRouter()->nodedb()->FindManyClosestTo(addr, IntroSetStorageRedundancy); - if (closestRCs.size() != IntroSetStorageRedundancy) - { - llarp::LogWarn("Received PublishIntroMessage but only know ", closestRCs.size(), " nodes"); - replies.emplace_back(new GotIntroMessage({}, txID)); - return true; - } + const auto& us = dht.OurKey(); - const auto& us = dht.OurKey(); + // function to identify the closest 4 routers we know of for this introset + auto propagateIfNotUs = [&](size_t index) { + assert(index < IntroSetStorageRedundancy); - // function to identify the closest 4 routers we know of for this introset - auto propagateIfNotUs = [&](size_t index) { - assert(index < IntroSetStorageRedundancy); + const auto& rc = closestRCs[index]; + const Key_t peer{rc.pubkey}; - const auto& rc = closestRCs[index]; - const Key_t peer{rc.pubkey}; + if (peer == us) + { + llarp::LogInfo("we are peer ", index, " so storing instead of propagating"); - if (peer == us) + dht.services()->PutNode(introset); + replies.emplace_back(new GotIntroMessage({introset}, txID)); + } + else + { + llarp::LogInfo("propagating to peer ", index); + if (relayed) { - llarp::LogInfo("we are peer ", index, " so storing instead of propagating"); - - dht.services()->PutNode(introset); - replies.emplace_back(new GotIntroMessage({introset}, txID)); + dht.PropagateLocalIntroSet(pathID, txID, introset, peer, 0); } else { - llarp::LogInfo("propagating to peer ", index); - if (relayed) - { - dht.PropagateLocalIntroSet(pathID, txID, introset, peer, 0); - } - else - { - dht.PropagateIntroSetTo(From, txID, introset, peer, 0); - } + dht.PropagateIntroSetTo(From, txID, introset, peer, 0); } - }; + } + }; - if (relayed) + if (relayed) + { + if (relayOrder >= IntroSetStorageRedundancy) { - if (relayOrder >= IntroSetStorageRedundancy) - { - llarp::LogWarn("Received PublishIntroMessage with invalid relayOrder: ", relayOrder); - replies.emplace_back(new GotIntroMessage({}, txID)); - return true; - } + llarp::LogWarn("Received PublishIntroMessage with invalid relayOrder: ", relayOrder); + replies.emplace_back(new GotIntroMessage({}, txID)); + return true; + } - llarp::LogInfo("Relaying PublishIntroMessage for ", addr, ", txid=", txID); + llarp::LogInfo("Relaying PublishIntroMessage for ", addr, ", txid=", txID); - propagateIfNotUs(relayOrder); - } - else + propagateIfNotUs(relayOrder); + } + else + { + int candidateNumber = -1; + int index = 0; + for (const auto& rc : closestRCs) { - int candidateNumber = -1; - int index = 0; - for (const auto& rc : closestRCs) - { - if (rc.pubkey == dht.OurKey()) - { - candidateNumber = index; - break; - } - ++index; - } - - if (candidateNumber >= 0) + if (rc.pubkey == dht.OurKey()) { - LogInfo( - "Received PubIntro for ", - addr, - ", txid=", - txID, - " and we are candidate ", - candidateNumber); - dht.services()->PutNode(introset); - replies.emplace_back(new GotIntroMessage({introset}, txID)); - } - else - { - LogWarn( - "!!! Received PubIntro with relayed==false but we aren't" - " candidate, intro derived key: ", - addr, - ", txid=", - txID, - ", message from: ", - From); + candidateNumber = index; + break; } + ++index; } - return true; + if (candidateNumber >= 0) + { + LogInfo( + "Received PubIntro for ", + addr, + ", txid=", + txID, + " and we are candidate ", + candidateNumber); + dht.services()->PutNode(introset); + replies.emplace_back(new GotIntroMessage({introset}, txID)); + } + else + { + LogWarn( + "!!! Received PubIntro with relayed==false but we aren't" + " candidate, intro derived key: ", + addr, + ", txid=", + txID, + ", message from: ", + From); + } } - bool - PublishIntroMessage::BEncode(llarp_buffer_t* buf) const + return true; + } + + void + PublishIntroMessage::bt_encode(oxenc::bt_dict_producer& btdp) const + { + try + { + btdp.append("A", "I"); + btdp.append("T", introset.ToString()); + btdp.append("O", relayOrder); + btdp.append("R", relayed ? 1 : 0); + btdp.append("T", txID); + btdp.append("V", llarp::constants::proto_version); + } + catch (...) { - if (!bencode_start_dict(buf)) - return false; - if (!BEncodeWriteDictMsgType(buf, "A", "I")) - return false; - if (!BEncodeWriteDictEntry("I", introset, buf)) - return false; - if (!BEncodeWriteDictInt("O", relayOrder, buf)) - return false; - if (!BEncodeWriteDictInt("R", relayed, buf)) - return false; - if (!BEncodeWriteDictInt("T", txID, buf)) - return false; - if (!BEncodeWriteDictInt("V", llarp::constants::proto_version, buf)) - return false; - return bencode_end(buf); + log::error(dht_cat, "Error: PublishIntroMessage failed to bt encode contents!"); } - } // namespace dht -} // namespace llarp + } +} // namespace llarp::dht diff --git a/llarp/dht/messages/pubintro.hpp b/llarp/dht/messages/pubintro.hpp index 0f12021f1c..8b210274f4 100644 --- a/llarp/dht/messages/pubintro.hpp +++ b/llarp/dht/messages/pubintro.hpp @@ -5,39 +5,42 @@ #include #include -namespace llarp +namespace llarp::dht { - namespace dht + struct PublishIntroMessage final : public AbstractDHTMessage { - struct PublishIntroMessage final : public IMessage - { - static const uint64_t MaxPropagationDepth; - llarp::service::EncryptedIntroSet introset; - bool relayed = false; - uint64_t relayOrder = 0; - uint64_t txID = 0; - PublishIntroMessage(const Key_t& from, bool relayed_) : IMessage(from), relayed(relayed_) - {} + static const uint64_t MaxPropagationDepth; + llarp::service::EncryptedIntroSet introset; + bool relayed = false; + uint64_t relayOrder = 0; + uint64_t txID = 0; + PublishIntroMessage(const Key_t& from, bool relayed_) + : AbstractDHTMessage(from), relayed(relayed_) + {} - PublishIntroMessage( - const llarp::service::EncryptedIntroSet& introset_, - uint64_t tx, - bool relayed_, - uint64_t relayOrder_) - : IMessage({}), introset(introset_), relayed(relayed_), relayOrder(relayOrder_), txID(tx) - {} + PublishIntroMessage( + const llarp::service::EncryptedIntroSet& introset_, + uint64_t tx, + bool relayed_, + uint64_t relayOrder_) + : AbstractDHTMessage({}) + , introset(introset_) + , relayed(relayed_) + , relayOrder(relayOrder_) + , txID(tx) + {} - ~PublishIntroMessage() override; + ~PublishIntroMessage() override; - bool - BEncode(llarp_buffer_t* buf) const override; + void + bt_encode(oxenc::bt_dict_producer& btdp) const override; - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) override; + bool + decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; - bool - HandleMessage( - llarp_dht_context* ctx, std::vector>& replies) const override; - }; - } // namespace dht -} // namespace llarp + bool + handle_message( + llarp_dht_context* ctx, + std::vector>& replies) const override; + }; +} // namespace llarp::dht diff --git a/llarp/exit/exit_messages.cpp b/llarp/exit/exit_messages.cpp index c3b6fd6741..9f72cc2daf 100644 --- a/llarp/exit/exit_messages.cpp +++ b/llarp/exit/exit_messages.cpp @@ -93,7 +93,7 @@ namespace llarp } bool - ObtainExitMessage::HandleMessage(IMessageHandler* h, AbstractRouter* r) const + ObtainExitMessage::HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const { return h->HandleObtainExitMessage(*this, r); } @@ -163,7 +163,7 @@ namespace llarp } bool - GrantExitMessage::HandleMessage(IMessageHandler* h, AbstractRouter* r) const + GrantExitMessage::HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const { return h->HandleGrantExitMessage(*this, r); } @@ -241,7 +241,7 @@ namespace llarp } bool - RejectExitMessage::HandleMessage(IMessageHandler* h, AbstractRouter* r) const + RejectExitMessage::HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const { return h->HandleRejectExitMessage(*this, r); } @@ -311,7 +311,7 @@ namespace llarp } bool - UpdateExitMessage::HandleMessage(IMessageHandler* h, AbstractRouter* r) const + UpdateExitMessage::HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const { return h->HandleUpdateExitMessage(*this, r); } @@ -346,7 +346,8 @@ namespace llarp } bool - UpdateExitVerifyMessage::HandleMessage(IMessageHandler* h, AbstractRouter* r) const + UpdateExitVerifyMessage::HandleMessage( + AbstractRoutingMessageHandler* h, AbstractRouter* r) const { return h->HandleUpdateExitVerifyMessage(*this, r); } @@ -412,7 +413,7 @@ namespace llarp } bool - CloseExitMessage::HandleMessage(IMessageHandler* h, AbstractRouter* r) const + CloseExitMessage::HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const { return h->HandleCloseExitMessage(*this, r); } diff --git a/llarp/exit/exit_messages.hpp b/llarp/exit/exit_messages.hpp index 5c0710fb88..1887f2fab5 100644 --- a/llarp/exit/exit_messages.hpp +++ b/llarp/exit/exit_messages.hpp @@ -10,7 +10,7 @@ namespace llarp { namespace routing { - struct ObtainExitMessage final : public IMessage + struct ObtainExitMessage final : public AbstractRoutingMessage { std::vector B; uint64_t E{0}; @@ -20,7 +20,7 @@ namespace llarp uint64_t X{0}; llarp::Signature Z; - ObtainExitMessage() : IMessage() + ObtainExitMessage() : AbstractRoutingMessage() {} ~ObtainExitMessage() override = default; @@ -51,10 +51,10 @@ namespace llarp DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) override; bool - HandleMessage(IMessageHandler* h, AbstractRouter* r) const override; + HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; }; - struct GrantExitMessage final : public IMessage + struct GrantExitMessage final : public AbstractRoutingMessage { using Nonce_t = llarp::AlignedBuffer<16>; @@ -75,7 +75,7 @@ namespace llarp DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) override; bool - HandleMessage(IMessageHandler* h, AbstractRouter* r) const override; + HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; void Clear() override @@ -86,7 +86,7 @@ namespace llarp } }; - struct RejectExitMessage final : public IMessage + struct RejectExitMessage final : public AbstractRoutingMessage { using Nonce_t = llarp::AlignedBuffer<16>; uint64_t B; @@ -118,10 +118,10 @@ namespace llarp DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) override; bool - HandleMessage(IMessageHandler* h, AbstractRouter* r) const override; + HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; }; - struct UpdateExitVerifyMessage final : public IMessage + struct UpdateExitVerifyMessage final : public AbstractRoutingMessage { using Nonce_t = llarp::AlignedBuffer<16>; uint64_t T; @@ -145,10 +145,10 @@ namespace llarp DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) override; bool - HandleMessage(IMessageHandler* h, AbstractRouter* r) const override; + HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; }; - struct UpdateExitMessage final : public IMessage + struct UpdateExitMessage final : public AbstractRoutingMessage { using Nonce_t = llarp::AlignedBuffer<16>; llarp::PathID_t P; @@ -169,7 +169,7 @@ namespace llarp DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) override; bool - HandleMessage(IMessageHandler* h, AbstractRouter* r) const override; + HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; void Clear() override @@ -181,7 +181,7 @@ namespace llarp } }; - struct CloseExitMessage final : public IMessage + struct CloseExitMessage final : public AbstractRoutingMessage { using Nonce_t = llarp::AlignedBuffer<16>; @@ -195,7 +195,7 @@ namespace llarp DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) override; bool - HandleMessage(IMessageHandler* h, AbstractRouter* r) const override; + HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; bool Sign(const llarp::SecretKey& sk); diff --git a/llarp/iwp/linklayer.cpp b/llarp/iwp/linklayer.cpp index 6fb807058d..a0637ccc04 100644 --- a/llarp/iwp/linklayer.cpp +++ b/llarp/iwp/linklayer.cpp @@ -48,9 +48,9 @@ namespace llarp::iwp } void - LinkLayer::RecvFrom(const SockAddr& from, ILinkSession::Packet_t pkt) + LinkLayer::RecvFrom(const SockAddr& from, AbstractLinkSession::Packet_t pkt) { - std::shared_ptr session; + std::shared_ptr session; auto itr = m_AuthedAddrs.find(from); bool isNewSession = false; if (itr == m_AuthedAddrs.end()) @@ -83,7 +83,7 @@ namespace llarp::iwp } } - std::shared_ptr + std::shared_ptr LinkLayer::NewOutboundSession(const RouterContact& rc, const AddressInfo& ai) { if (m_Inbound) diff --git a/llarp/iwp/linklayer.hpp b/llarp/iwp/linklayer.hpp index 82504edc78..8399f26c2d 100644 --- a/llarp/iwp/linklayer.hpp +++ b/llarp/iwp/linklayer.hpp @@ -32,7 +32,7 @@ namespace llarp::iwp WorkerFunc_t dowork, bool permitInbound); - std::shared_ptr + std::shared_ptr NewOutboundSession(const RouterContact& rc, const AddressInfo& ai) override; std::string_view @@ -42,7 +42,7 @@ namespace llarp::iwp Rank() const override; void - RecvFrom(const SockAddr& from, ILinkSession::Packet_t pkt) override; + RecvFrom(const SockAddr& from, AbstractLinkSession::Packet_t pkt) override; void WakeupPlaintext(); @@ -55,7 +55,7 @@ namespace llarp::iwp HandleWakeupPlaintext(); const std::shared_ptr m_Wakeup; - std::vector m_WakingUp; + std::vector m_WakingUp; const bool m_Inbound; }; diff --git a/llarp/iwp/message_buffer.cpp b/llarp/iwp/message_buffer.cpp index 000f80a6af..e384b2cf85 100644 --- a/llarp/iwp/message_buffer.cpp +++ b/llarp/iwp/message_buffer.cpp @@ -8,9 +8,9 @@ namespace llarp { OutboundMessage::OutboundMessage( uint64_t msgid, - ILinkSession::Message_t msg, + AbstractLinkSession::Message_t msg, llarp_time_t now, - ILinkSession::CompletionHandler handler, + AbstractLinkSession::CompletionHandler handler, uint16_t priority) : m_Data{std::move(msg)} , m_MsgID{msgid} @@ -24,7 +24,7 @@ namespace llarp m_Acks.set(0); } - ILinkSession::Packet_t + AbstractLinkSession::Packet_t OutboundMessage::XMIT() const { size_t extra = std::min(m_Data.size(), FragmentSize); @@ -43,7 +43,7 @@ namespace llarp { if (m_Completed) { - m_Completed(ILinkSession::DeliveryStatus::eDeliverySuccess); + m_Completed(AbstractLinkSession::DeliveryStatus::eDeliverySuccess); } m_Completed = nullptr; } @@ -62,7 +62,7 @@ namespace llarp void OutboundMessage::FlushUnAcked( - std::function sendpkt, llarp_time_t now) + std::function sendpkt, llarp_time_t now) { /// overhead for a data packet in plaintext static constexpr size_t Overhead = 10; @@ -111,7 +111,7 @@ namespace llarp { if (m_Completed) { - m_Completed(ILinkSession::DeliveryStatus::eDeliveryDropped); + m_Completed(AbstractLinkSession::DeliveryStatus::eDeliveryDropped); } m_Completed = nullptr; } @@ -135,7 +135,7 @@ namespace llarp m_LastActiveAt = now; } - ILinkSession::Packet_t + AbstractLinkSession::Packet_t InboundMessage::ACKS() const { auto acks = CreatePacket(Command::eACKS, 9); @@ -175,7 +175,8 @@ namespace llarp } void - InboundMessage::SendACKS(std::function sendpkt, llarp_time_t now) + InboundMessage::SendACKS( + std::function sendpkt, llarp_time_t now) { sendpkt(ACKS()); m_LastACKSent = now; diff --git a/llarp/iwp/message_buffer.hpp b/llarp/iwp/message_buffer.hpp index f0dae604c4..207a3b2eef 100644 --- a/llarp/iwp/message_buffer.hpp +++ b/llarp/iwp/message_buffer.hpp @@ -38,15 +38,15 @@ namespace llarp OutboundMessage() = default; OutboundMessage( uint64_t msgid, - ILinkSession::Message_t data, + AbstractLinkSession::Message_t data, llarp_time_t now, - ILinkSession::CompletionHandler handler, + AbstractLinkSession::CompletionHandler handler, uint16_t priority); - ILinkSession::Message_t m_Data; + AbstractLinkSession::Message_t m_Data; uint64_t m_MsgID = 0; std::bitset m_Acks; - ILinkSession::CompletionHandler m_Completed; + AbstractLinkSession::CompletionHandler m_Completed; llarp_time_t m_LastFlush = 0s; ShortHash m_Digest; llarp_time_t m_StartedAt = 0s; @@ -61,14 +61,14 @@ namespace llarp return std::tie(prioA, m_MsgID) < std::tie(prioB, other.m_MsgID); } - ILinkSession::Packet_t + AbstractLinkSession::Packet_t XMIT() const; void Ack(byte_t bitmask); void - FlushUnAcked(std::function sendpkt, llarp_time_t now); + FlushUnAcked(std::function sendpkt, llarp_time_t now); bool ShouldFlush(llarp_time_t now) const; @@ -91,7 +91,7 @@ namespace llarp InboundMessage() = default; InboundMessage(uint64_t msgid, uint16_t sz, ShortHash h, llarp_time_t now); - ILinkSession::Message_t m_Data; + AbstractLinkSession::Message_t m_Data; ShortHash m_Digset; uint64_t m_MsgID = 0; llarp_time_t m_LastACKSent = 0s; @@ -117,9 +117,9 @@ namespace llarp ShouldSendACKS(llarp_time_t now) const; void - SendACKS(std::function sendpkt, llarp_time_t now); + SendACKS(std::function sendpkt, llarp_time_t now); - ILinkSession::Packet_t + AbstractLinkSession::Packet_t ACKS() const; }; diff --git a/llarp/iwp/session.cpp b/llarp/iwp/session.cpp index b2109c479c..93f4f1a45e 100644 --- a/llarp/iwp/session.cpp +++ b/llarp/iwp/session.cpp @@ -11,11 +11,11 @@ namespace llarp { namespace iwp { - ILinkSession::Packet_t + AbstractLinkSession::Packet_t CreatePacket(Command cmd, size_t plainsize, size_t minpad, size_t variance) { const size_t pad = minpad > 0 ? minpad + (variance > 0 ? randint() % variance : 0) : 0; - ILinkSession::Packet_t pkt(PacketOverhead + plainsize + pad + CommandOverhead); + AbstractLinkSession::Packet_t pkt(PacketOverhead + plainsize + pad + CommandOverhead); // randomize pad if (pad) { @@ -100,8 +100,8 @@ namespace llarp m_RemoteRC = msg->rc; GotLIM = util::memFn(&Session::GotRenegLIM, this); assert(shared_from_this().use_count() > 1); - SendOurLIM([self = shared_from_this()](ILinkSession::DeliveryStatus st) { - if (st == ILinkSession::DeliveryStatus::eDeliverySuccess) + SendOurLIM([self = shared_from_this()](AbstractLinkSession::DeliveryStatus st) { + if (st == AbstractLinkSession::DeliveryStatus::eDeliverySuccess) { self->m_State = State::Ready; self->m_Parent->MapAddr(self->m_RemoteRC.pubkey, self.get()); @@ -112,24 +112,30 @@ namespace llarp } void - Session::SendOurLIM(ILinkSession::CompletionHandler h) + Session::SendOurLIM(AbstractLinkSession::CompletionHandler h) { LinkIntroMessage msg; msg.rc = m_Parent->GetOurRC(); - msg.N.Randomize(); - msg.P = 60000; - if (not msg.Sign(m_Parent->Sign)) + msg.nonce.Randomize(); + msg.session_period = 60000; + if (not msg.sign(m_Parent->Sign)) { LogError("failed to sign our RC for ", m_RemoteAddr); return; } - ILinkSession::Message_t data(LinkIntroMessage::MaxSize + PacketOverhead); + + AbstractLinkSession::Message_t data(LinkIntroMessage::MAX_MSG_SIZE + PacketOverhead); llarp_buffer_t buf(data); - if (not msg.BEncode(&buf)) + if (auto str = msg.bt_encode(); not str.empty()) { - LogError("failed to encode LIM for ", m_RemoteAddr); + buf.write(str.begin(), str.end()); + } + else + { + log::critical(link_cat, "Error: Failed to encode LIM for {}", m_RemoteAddr); return; } + if (not SendMessageBuffer(std::move(data), h)) { LogError("failed to send LIM to ", m_RemoteAddr); @@ -139,7 +145,7 @@ namespace llarp } void - Session::EncryptAndSend(ILinkSession::Packet_t data) + Session::EncryptAndSend(AbstractLinkSession::Packet_t data) { m_EncryptNext.emplace_back(std::move(data)); TriggerPump(); @@ -186,12 +192,14 @@ namespace llarp bool Session::SendMessageBuffer( - ILinkSession::Message_t buf, ILinkSession::CompletionHandler completed, uint16_t priority) + AbstractLinkSession::Message_t buf, + AbstractLinkSession::CompletionHandler completed, + uint16_t priority) { if (m_TXMsgs.size() >= MaxSendQueueSize) { if (completed) - completed(ILinkSession::DeliveryStatus::eDeliveryDropped); + completed(AbstractLinkSession::DeliveryStatus::eDeliveryDropped); return false; } const auto now = m_Parent->Now(); @@ -441,7 +449,7 @@ namespace llarp TunnelNonce N; N.Randomize(); { - ILinkSession::Packet_t req(Introduction::SIZE + PacketOverhead); + AbstractLinkSession::Packet_t req(Introduction::SIZE + PacketOverhead); const auto pk = m_Parent->GetOurRC().pubkey; const auto e_pk = m_Parent->RouterEncryptionSecret().toPublic(); auto itr = req.data() + PacketOverhead; @@ -955,7 +963,7 @@ namespace llarp } bool - Session::Recv_LL(ILinkSession::Packet_t data) + Session::Recv_LL(AbstractLinkSession::Packet_t data) { m_RXRate += data.size(); diff --git a/llarp/iwp/session.hpp b/llarp/iwp/session.hpp index 210a37a1ec..eef78ada15 100644 --- a/llarp/iwp/session.hpp +++ b/llarp/iwp/session.hpp @@ -19,7 +19,7 @@ namespace llarp /// packet crypto overhead size static constexpr size_t PacketOverhead = HMACSIZE + TUNNONCESIZE; /// creates a packet with plaintext size + wire overhead + random pad - ILinkSession::Packet_t + AbstractLinkSession::Packet_t CreatePacket(Command cmd, size_t plainsize, size_t min_pad = 16, size_t pad_variance = 16); /// Time how long we try delivery for static constexpr std::chrono::milliseconds DeliveryTimeout = 500ms; @@ -36,7 +36,7 @@ namespace llarp /// How long we wait for a session to die with no tx from them static constexpr auto SessionAliveTimeout = PingInterval * 5; - struct Session : public ILinkSession, public std::enable_shared_from_this + struct Session : public AbstractLinkSession, public std::enable_shared_from_this { using Time_t = std::chrono::milliseconds; @@ -61,14 +61,14 @@ namespace llarp bool SendMessageBuffer( - ILinkSession::Message_t msg, + AbstractLinkSession::Message_t msg, CompletionHandler resultHandler, uint16_t priority = 0) override; void Send_LL(const byte_t* buf, size_t sz); - void EncryptAndSend(ILinkSession::Packet_t); + void EncryptAndSend(AbstractLinkSession::Packet_t); void Start() override; @@ -76,7 +76,7 @@ namespace llarp void Close() override; - bool Recv_LL(ILinkSession::Packet_t) override; + bool Recv_LL(AbstractLinkSession::Packet_t) override; bool SendKeepAlive() override; @@ -251,7 +251,7 @@ namespace llarp GotRenegLIM(const LinkIntroMessage* msg); void - SendOurLIM(ILinkSession::CompletionHandler h = nullptr); + SendOurLIM(AbstractLinkSession::CompletionHandler h = nullptr); void HandleXMIT(Packet_t msg); diff --git a/llarp/link/connection.hpp b/llarp/link/connection.hpp index d137ef4a41..171f91c8b1 100644 --- a/llarp/link/connection.hpp +++ b/llarp/link/connection.hpp @@ -15,7 +15,7 @@ namespace llarp::link RouterContact remote_rc; - bool inbound; // one side of a connection will be responsible for some things, e.g. heartbeat + bool inbound; // one side of a connection will be responsible for some things, e.g. heartbeat bool remote_is_relay; }; } // namespace llarp::link diff --git a/llarp/link/endpoint.hpp b/llarp/link/endpoint.hpp index 88abe0f2de..6ac3bb95d9 100644 --- a/llarp/link/endpoint.hpp +++ b/llarp/link/endpoint.hpp @@ -12,13 +12,12 @@ namespace llarp::link struct Endpoint { std::shared_ptr endpoint; - bool inbound {false}; + bool inbound{false}; // for outgoing packets, we route via RouterID; map RouterID->Connection // for incoming packets, we get a ConnectionID; map ConnectionID->RouterID std::unordered_map connections; std::unordered_map connid_map; - }; } // namespace llarp::link diff --git a/llarp/link/i_link_manager.hpp b/llarp/link/i_link_manager.hpp index 8eb5fcac7d..27f77e3771 100644 --- a/llarp/link/i_link_manager.hpp +++ b/llarp/link/i_link_manager.hpp @@ -14,7 +14,7 @@ struct llarp_buffer_t; namespace llarp { - //TODO: do we still want this? + // TODO: do we still want this? enum class SessionResult { Establish, @@ -39,15 +39,11 @@ namespace llarp template <> constexpr inline bool IsToStringFormattable = true; - struct RouterContact; - struct ILinkSession; + struct AbstractLinkSession; struct IOutboundSessionMaker; struct RouterID; - using bstring = std::basic_string; - using bstring_view = std::basic_string_view; - struct ILinkManager { virtual ~ILinkManager() = default; @@ -56,7 +52,7 @@ namespace llarp SendTo( const RouterID& remote, const llarp_buffer_t& buf, - ILinkSession::CompletionHandler completed, + AbstractLinkSession::CompletionHandler completed, uint16_t priority = 0) = 0; virtual bool diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 9be7f46048..e4dd2d3252 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -17,22 +17,22 @@ namespace llarp for (auto& ep : endpoints) { - //TODO: need some notion of "is this link compatible with that address". - // iwp just checks that the link dialect ("iwp") matches the address info dialect, - // but that feels insufficient. For now, just return the first endpoint we have; - // we should probably only have 1 for now anyway until we make ipv6 work. + // TODO: need some notion of "is this link compatible with that address". + // iwp just checks that the link dialect ("iwp") matches the address info dialect, + // but that feels insufficient. For now, just return the first endpoint we have; + // we should probably only have 1 for now anyway until we make ipv6 work. return &ep; } return nullptr; } - //TODO: replace with control/data message sending with libquic + // TODO: replace with control/data message sending with libquic bool LinkManager::SendTo( const RouterID& remote, const llarp_buffer_t& buf, - ILinkSession::CompletionHandler completed, + AbstractLinkSession::CompletionHandler completed, uint16_t priority) { if (stopping) @@ -42,13 +42,13 @@ namespace llarp { if (completed) { - completed(ILinkSession::DeliveryStatus::eDeliveryDropped); + completed(AbstractLinkSession::DeliveryStatus::eDeliveryDropped); } return false; } - //TODO: send the message - //TODO: if we keep bool return type, change this accordingly + // TODO: send the message + // TODO: if we keep bool return type, change this accordingly return false; } @@ -59,7 +59,7 @@ namespace llarp { if (auto itr = ep.connections.find(remote); itr != ep.connections.end()) { - if (not (itr->second.remote_is_relay and client_only)) + if (not(itr->second.remote_is_relay and client_only)) return true; return false; } @@ -93,10 +93,16 @@ namespace llarp void LinkManager::AddLink(const oxen::quic::opt::local_addr& bind, bool inbound) { - //TODO: libquic callbacks: new_conn_alpn_notify, new_conn_pubkey_ok, new_conn_established/ready - // stream_opened, stream_data, stream_closed, conn_closed - oxen::quic::dgram_data_callback dgram_cb = [this](oxen::quic::dgram_interface& dgi, bstring dgram){ HandleIncomingDataMessage(dgi, dgram); }; - auto ep = quic->endpoint(bind, std::move(dgram_cb), oxen::quic::opt::enable_datagrams{oxen::quic::Splitting::ACTIVE}); + // TODO: libquic callbacks: new_conn_alpn_notify, new_conn_pubkey_ok, new_conn_established/ready + // stream_opened, stream_data, stream_closed, conn_closed + oxen::quic::dgram_data_callback dgram_cb = + [this](oxen::quic::dgram_interface& dgi, bstring dgram) { + HandleIncomingDataMessage(dgi, dgram); + }; + auto ep = quic->endpoint( + bind, + std::move(dgram_cb), + oxen::quic::opt::enable_datagrams{oxen::quic::Splitting::ACTIVE}); endpoints.emplace_back(); auto& endp = endpoints.back(); endp.endpoint = std::move(ep); @@ -147,7 +153,7 @@ namespace llarp { for (const auto& conn : ep.connections) { - if (not (conn.second.remote_is_relay and clients_only)) + if (not(conn.second.remote_is_relay and clients_only)) count++; } } @@ -191,7 +197,7 @@ namespace llarp return false; } - //TODO: this? perhaps no longer necessary in the same way? + // TODO: this? perhaps no longer necessary in the same way? void LinkManager::CheckPersistingSessions(llarp_time_t now) { @@ -199,13 +205,12 @@ namespace llarp return; } - //TODO: do we still need this concept? + // TODO: do we still need this concept? void LinkManager::updatePeerDb(std::shared_ptr peerDb) - { - } + {} - //TODO: this + // TODO: this util::StatusObject LinkManager::ExtractStatus() const { @@ -223,13 +228,13 @@ namespace llarp void LinkManager::Connect(RouterID router) { - auto fn = [this](const RouterID& r, const RouterContact* const rc, const RCRequestResult res){ - if (res == RCRequestResult::Success) - Connect(*rc); - /* TODO: - else - RC lookup failure callback here - */ + auto fn = [this](const RouterID& r, const RouterContact* const rc, const RCRequestResult res) { + if (res == RCRequestResult::Success) + Connect(*rc); + /* TODO: + else + RC lookup failure callback here + */ }; _rcLookup->GetRC(router, fn); @@ -239,31 +244,35 @@ namespace llarp void LinkManager::Connect(RouterContact rc) { - //TODO: connection failed callback + // TODO: connection failed callback if (HaveConnection(rc.pubkey)) return; // RC shouldn't be valid if this is the case, but may as well sanity check... - //TODO: connection failed callback + // TODO: connection failed callback if (rc.addrs.empty()) return; - //TODO: connection failed callback + // TODO: connection failed callback auto* ep = GetCompatibleLink(rc); if (ep == nullptr) return; - //TODO: connection established/failed callbacks - oxen::quic::stream_data_callback stream_cb = [this](oxen::quic::Stream& stream, bstring_view packet){ HandleIncomingControlMessage(stream, packet); }; + // TODO: connection established/failed callbacks + oxen::quic::stream_data_callback stream_cb = + [this](oxen::quic::Stream& stream, bstring_view packet) { + HandleIncomingControlMessage(stream, packet); + }; - //TODO: once "compatible link" cares about address, actually choose addr to connect to - // based on which one is compatible with the link we chose. For now, just use - // the first one. + // TODO: once "compatible link" cares about address, actually choose addr to connect to + // based on which one is compatible with the link we chose. For now, just use + // the first one. auto& selected = rc.addrs[0]; oxen::quic::opt::remote_addr remote{selected.IPString(), selected.port}; - //TODO: confirm remote end is using the expected pubkey (RouterID). - //TODO: ALPN for "client" vs "relay" (could just be set on endpoint creation) - //TODO: does connect() inherit the endpoint's datagram data callback, and do we want it to if so? + // TODO: confirm remote end is using the expected pubkey (RouterID). + // TODO: ALPN for "client" vs "relay" (could just be set on endpoint creation) + // TODO: does connect() inherit the endpoint's datagram data callback, and do we want it to if + // so? auto conn_interface = ep->endpoint->connect(remote, stream_cb, tls_creds); std::shared_ptr stream = conn_interface->get_new_stream(); @@ -308,13 +317,13 @@ namespace llarp void LinkManager::HandleIncomingDataMessage(oxen::quic::dgram_interface& dgi, bstring dgram) { - //TODO: this + // TODO: this } void LinkManager::HandleIncomingControlMessage(oxen::quic::Stream& stream, bstring_view packet) { - //TODO: this + // TODO: this } } // namespace llarp diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index aa622cc220..6aafa593dc 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -19,14 +19,14 @@ namespace llarp struct LinkManager final : public ILinkManager { public: - explicit LinkManager(AbstractRouter* r) : router{r} {} - + explicit LinkManager(AbstractRouter* r) : router{r} + {} bool SendTo( const RouterID& remote, const llarp_buffer_t& buf, - ILinkSession::CompletionHandler completed, + AbstractLinkSession::CompletionHandler completed, uint16_t priority) override; bool @@ -82,14 +82,13 @@ namespace llarp void ConnectToRandomRouters(int numDesired); - //TODO: tune these (maybe even remove max?) now that we're switching to quic + // TODO: tune these (maybe even remove max?) now that we're switching to quic /// always maintain this many connections to other routers size_t minConnectedRouters = 4; /// hard upperbound limit on the number of router to router connections size_t maxConnectedRouters = 6; private: - link::Endpoint* GetCompatibleLink(const RouterContact& rc); @@ -111,16 +110,17 @@ namespace llarp // FIXME: Lokinet currently expects to be able to kill all network functionality before // finishing other shutdown things, including destroying this class, and that is all in // Network's destructor, so we need to be able to destroy it before this class. - std::unique_ptr quic { std::make_unique() }; + std::unique_ptr quic{std::make_unique()}; std::vector endpoints; - //TODO: initialize creds + // TODO: initialize creds std::shared_ptr tls_creds; - void HandleIncomingDataMessage(oxen::quic::dgram_interface& dgi, bstring dgram); - void HandleIncomingControlMessage(oxen::quic::Stream& stream, bstring_view packet); - + void + HandleIncomingDataMessage(oxen::quic::dgram_interface& dgi, bstring dgram); + void + HandleIncomingControlMessage(oxen::quic::Stream& stream, bstring_view packet); }; } // namespace llarp diff --git a/llarp/link/server.cpp b/llarp/link/server.cpp index 72eaa7ff9d..12d56155a0 100644 --- a/llarp/link/server.cpp +++ b/llarp/link/server.cpp @@ -53,7 +53,7 @@ namespace llarp return m_AuthedLinks.find(id) != m_AuthedLinks.end(); } - std::shared_ptr + std::shared_ptr ILinkLayer::FindSessionByPubkey(RouterID id) { Lock_t l(m_AuthedLinksMutex); @@ -64,9 +64,10 @@ namespace llarp } void - ILinkLayer::ForEachSession(std::function visit, bool randomize) const + ILinkLayer::ForEachSession( + std::function visit, bool randomize) const { - std::vector> sessions; + std::vector> sessions; { Lock_t l(m_AuthedLinksMutex); if (m_AuthedLinks.size() == 0) @@ -99,9 +100,10 @@ namespace llarp } bool - ILinkLayer::VisitSessionByPubkey(const RouterID& pk, std::function visit) + ILinkLayer::VisitSessionByPubkey( + const RouterID& pk, std::function visit) { - std::shared_ptr session; + std::shared_ptr session; { Lock_t l(m_AuthedLinksMutex); auto itr = m_AuthedLinks.find(pk); @@ -113,9 +115,9 @@ namespace llarp } void - ILinkLayer::ForEachSession(std::function visit) + ILinkLayer::ForEachSession(std::function visit) { - std::vector> sessions; + std::vector> sessions; { Lock_t l(m_AuthedLinksMutex); auto itr = m_AuthedLinks.begin(); @@ -138,7 +140,7 @@ namespace llarp m_Router = router; m_udp = m_Router->loop()->make_udp( [this]([[maybe_unused]] UDPHandle& udp, const SockAddr& from, llarp_buffer_t buf) { - ILinkSession::Packet_t pkt; + AbstractLinkSession::Packet_t pkt; pkt.resize(buf.sz); std::copy_n(buf.base, buf.sz, pkt.data()); RecvFrom(from, std::move(pkt)); @@ -155,7 +157,7 @@ namespace llarp ILinkLayer::Pump() { std::unordered_set closedSessions; - std::vector> closedPending; + std::vector> closedPending; auto _now = Now(); { Lock_t l(m_AuthedLinksMutex); @@ -223,7 +225,7 @@ namespace llarp } bool - ILinkLayer::MapAddr(const RouterID& pk, ILinkSession* s) + ILinkLayer::MapAddr(const RouterID& pk, AbstractLinkSession* s) { Lock_t l_authed(m_AuthedLinksMutex); Lock_t l_pending(m_PendingMutex); @@ -321,7 +323,7 @@ namespace llarp return false; } } - std::shared_ptr s = NewOutboundSession(rc, to); + std::shared_ptr s = NewOutboundSession(rc, to); if (BeforeConnect) { BeforeConnect(std::move(rc)); @@ -432,10 +434,10 @@ namespace llarp ILinkLayer::SendTo( const RouterID& remote, const llarp_buffer_t& buf, - ILinkSession::CompletionHandler completed, + AbstractLinkSession::CompletionHandler completed, uint16_t priority) { - std::shared_ptr s; + std::shared_ptr s; { Lock_t l(m_AuthedLinksMutex); // pick lowest backlog session @@ -450,7 +452,7 @@ namespace llarp } } } - ILinkSession::Message_t pkt(buf.sz); + AbstractLinkSession::Message_t pkt(buf.sz); std::copy_n(buf.base, buf.sz, pkt.begin()); return s && s->SendMessageBuffer(std::move(pkt), completed, priority); } @@ -478,7 +480,7 @@ namespace llarp } bool - ILinkLayer::PutSession(const std::shared_ptr& s) + ILinkLayer::PutSession(const std::shared_ptr& s) { Lock_t lock(m_PendingMutex); const auto address = s->GetRemoteEndpoint(); diff --git a/llarp/link/server.hpp b/llarp/link/server.hpp index f9aca894b0..1f2de21b7c 100644 --- a/llarp/link/server.hpp +++ b/llarp/link/server.hpp @@ -18,7 +18,7 @@ namespace llarp /// handle a link layer message. this allows for the message to be handled by "upper layers" /// /// currently called from iwp::Session when messages are sent or received. - using LinkMessageHandler = std::function; + using LinkMessageHandler = std::function; /// sign a buffer with identity key. this function should take the given `llarp_buffer_t` and /// sign it, prividing the signature in the out variable `Signature&`. @@ -29,7 +29,7 @@ namespace llarp /// handle connection timeout /// /// currently called from ILinkLayer::Pump() when an unestablished session times out - using TimeoutHandler = std::function; + using TimeoutHandler = std::function; /// get our RC /// @@ -41,7 +41,7 @@ namespace llarp /// return true to accept /// /// currently called in iwp::Session when a valid LIM is received. - using SessionEstablishedHandler = std::function; + using SessionEstablishedHandler = std::function; /// f(new, old) /// handler of session renegotiation @@ -95,11 +95,11 @@ namespace llarp HasSessionTo(const RouterID& pk); void - ForEachSession(std::function visit, bool randomize = false) const - EXCLUDES(m_AuthedLinksMutex); + ForEachSession(std::function visit, bool randomize = false) + const EXCLUDES(m_AuthedLinksMutex); void - ForEachSession(std::function visit) EXCLUDES(m_AuthedLinksMutex); + ForEachSession(std::function visit) EXCLUDES(m_AuthedLinksMutex); void UnmapAddr(const SockAddr& addr); @@ -110,18 +110,18 @@ namespace llarp void Bind(AbstractRouter* router, SockAddr addr); - virtual std::shared_ptr + virtual std::shared_ptr NewOutboundSession(const RouterContact& rc, const AddressInfo& ai) = 0; /// fetch a session by the identity pubkey it claims - std::shared_ptr + std::shared_ptr FindSessionByPubkey(RouterID pk); virtual void Pump(); virtual void - RecvFrom(const SockAddr& from, ILinkSession::Packet_t pkt) = 0; + RecvFrom(const SockAddr& from, AbstractLinkSession::Packet_t pkt) = 0; bool PickAddress(const RouterContact& rc, AddressInfo& picked) const; @@ -151,14 +151,14 @@ namespace llarp SendTo( const RouterID& remote, const llarp_buffer_t& buf, - ILinkSession::CompletionHandler completed, + AbstractLinkSession::CompletionHandler completed, uint16_t priority); virtual bool GetOurAddressInfo(AddressInfo& addr) const; bool - VisitSessionByPubkey(const RouterID& pk, std::function visit) + VisitSessionByPubkey(const RouterID& pk, std::function visit) EXCLUDES(m_AuthedLinksMutex); virtual uint16_t @@ -187,7 +187,7 @@ namespace llarp } bool - MapAddr(const RouterID& pk, ILinkSession* s); + MapAddr(const RouterID& pk, AbstractLinkSession* s); void Tick(llarp_time_t now); @@ -254,15 +254,15 @@ namespace llarp using Mutex_t = util::NullMutex; #endif bool - PutSession(const std::shared_ptr& s); + PutSession(const std::shared_ptr& s); AbstractRouter* m_Router; SockAddr m_ourAddr; std::shared_ptr m_udp; SecretKey m_SecretKey; - using AuthedLinks = std::unordered_multimap>; - using Pending = std::unordered_map>; + using AuthedLinks = std::unordered_multimap>; + using Pending = std::unordered_map>; mutable DECLARE_LOCK(Mutex_t, m_AuthedLinksMutex, ACQUIRED_BEFORE(m_PendingMutex)); AuthedLinks m_AuthedLinks GUARDED_BY(m_AuthedLinksMutex); mutable DECLARE_LOCK(Mutex_t, m_PendingMutex, ACQUIRED_AFTER(m_AuthedLinksMutex)); diff --git a/llarp/link/session.cpp b/llarp/link/session.cpp index 016b1fcff5..a7894780c7 100644 --- a/llarp/link/session.cpp +++ b/llarp/link/session.cpp @@ -3,7 +3,7 @@ namespace llarp { bool - ILinkSession::IsRelay() const + AbstractLinkSession::IsRelay() const { return GetRemoteRC().IsPublicRouter(); } diff --git a/llarp/link/session.hpp b/llarp/link/session.hpp index 0c54756fa7..8c5b96d943 100644 --- a/llarp/link/session.hpp +++ b/llarp/link/session.hpp @@ -11,7 +11,7 @@ namespace llarp { struct LinkIntroMessage; - struct ILinkMessage; + struct AbstractLinkMessage; struct ILinkLayer; struct SessionStats @@ -27,9 +27,9 @@ namespace llarp uint64_t totalInFlightTX = 0; }; - struct ILinkSession + struct AbstractLinkSession { - virtual ~ILinkSession() = default; + virtual ~AbstractLinkSession() = default; /// delivery status of a message enum class DeliveryStatus diff --git a/llarp/messages/common.hpp b/llarp/messages/common.hpp new file mode 100644 index 0000000000..d1599bd238 --- /dev/null +++ b/llarp/messages/common.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include + +#include + +namespace llarp +{ + /// abstract base class for serialized messages + struct AbstractSerializable + { + virtual std::string + bt_encode() const = 0; + virtual void + bt_encode(llarp_buffer& b) const = 0; + virtual void + bt_encode(oxenc::bt_dict_producer& btdp) const = 0; + virtual void + bt_encode(oxenc::bt_list_producer& btlp) const = 0; + }; +} // namespace llarp diff --git a/llarp/messages/dht_immediate.cpp b/llarp/messages/dht_immediate.cpp index 4799329790..81e34d7bc9 100644 --- a/llarp/messages/dht_immediate.cpp +++ b/llarp/messages/dht_immediate.cpp @@ -5,17 +5,41 @@ namespace llarp { void - DHTImmediateMessage::Clear() + DHTImmediateMessage::clear() { msgs.clear(); version = 0; } + std::string + DHTImmediateMessage::bt_encode() const + { + oxenc::bt_dict_producer btdp; + + try + { + btdp.append("a", ""); + { + auto subdict = btdp.append_dict("m"); + for (auto& m : msgs) + m->bt_encode(subdict); + } + + btdp.append("v", llarp::constants::proto_version); + } + catch (...) + { + log::critical(link_cat, "Error: DHTImmediateMessage failed to bt encode contents!"); + } + + return std::move(btdp).str(); + } + bool - DHTImmediateMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) + DHTImmediateMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) { if (key.startswith("m")) - return llarp::dht::DecodeMesssageList(dht::Key_t(session->GetPubKey()), buf, msgs); + return llarp::dht::DecodeMessageList(dht::Key_t(session->GetPubKey()), buf, msgs); if (key.startswith("v")) { if (!bencode_read_integer(buf, &version)) @@ -27,48 +51,14 @@ namespace llarp } bool - DHTImmediateMessage::BEncode(llarp_buffer_t* buf) const - { - if (!bencode_start_dict(buf)) - return false; - - // message type - if (!bencode_write_bytestring(buf, "a", 1)) - return false; - if (!bencode_write_bytestring(buf, "m", 1)) - return false; - - // dht messages - if (!bencode_write_bytestring(buf, "m", 1)) - return false; - // begin list - if (!bencode_start_list(buf)) - return false; - for (const auto& msg : msgs) - { - if (!msg->BEncode(buf)) - return false; - } - // end list - if (!bencode_end(buf)) - return false; - - // protocol version - if (!bencode_write_uint64_entry(buf, "v", 1, llarp::constants::proto_version)) - return false; - - return bencode_end(buf); - } - - bool - DHTImmediateMessage::HandleMessage(AbstractRouter* router) const + DHTImmediateMessage::handle_message(AbstractRouter* router) const { DHTImmediateMessage reply; reply.session = session; bool result = true; for (auto& msg : msgs) { - result &= msg->HandleMessage(router->dht(), reply.msgs); + result &= msg->handle_message(router->dht(), reply.msgs); } if (reply.msgs.size()) { diff --git a/llarp/messages/dht_immediate.hpp b/llarp/messages/dht_immediate.hpp index fca01d581a..25c6f62883 100644 --- a/llarp/messages/dht_immediate.hpp +++ b/llarp/messages/dht_immediate.hpp @@ -7,27 +7,27 @@ namespace llarp { - struct DHTImmediateMessage final : public ILinkMessage + struct DHTImmediateMessage final : public AbstractLinkMessage { DHTImmediateMessage() = default; ~DHTImmediateMessage() override = default; - std::vector> msgs; + std::vector> msgs; - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) override; + std::string + bt_encode() const override; bool - BEncode(llarp_buffer_t* buf) const override; + decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; bool - HandleMessage(AbstractRouter* router) const override; + handle_message(AbstractRouter* router) const override; void - Clear() override; + clear() override; const char* - Name() const override + name() const override { return "DHTImmediate"; } diff --git a/llarp/messages/discard.hpp b/llarp/messages/discard.hpp index 5a3458a59e..c495e90920 100644 --- a/llarp/messages/discard.hpp +++ b/llarp/messages/discard.hpp @@ -7,37 +7,42 @@ namespace llarp { - struct DiscardMessage final : public ILinkMessage + struct DiscardMessage final : public AbstractLinkMessage { - DiscardMessage() : ILinkMessage() + DiscardMessage() : AbstractLinkMessage() {} - bool - BEncode(llarp_buffer_t* buf) const override + std::string + bt_encode() const override { - if (!bencode_start_dict(buf)) - return false; - if (!bencode_write_bytestring(buf, "a", 1)) - return false; - if (!bencode_write_bytestring(buf, "x", 1)) - return false; - return bencode_end(buf); + oxenc::bt_dict_producer btdp; + + try + { + btdp.append("a", "x"); + } + catch (...) + { + log::critical(link_cat, "Error: RelayDownstreamMessage failed to bt encode contents!"); + } + + return std::move(btdp).str(); } void - Clear() override + clear() override { version = 0; } const char* - Name() const override + name() const override { return "Discard"; } bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) override + decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override { if (key.startswith("a")) { @@ -52,7 +57,7 @@ namespace llarp } bool - HandleMessage(AbstractRouter* /*router*/) const override + handle_message(AbstractRouter* /*router*/) const override { return true; } @@ -60,7 +65,7 @@ namespace llarp namespace routing { - struct DataDiscardMessage final : public IMessage + struct DataDiscardMessage final : public AbstractRoutingMessage { PathID_t P; @@ -73,19 +78,19 @@ namespace llarp } void - Clear() override + clear() override { version = 0; } bool - HandleMessage(IMessageHandler* h, AbstractRouter* r) const override + handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override { return h->HandleDataDiscardMessage(*this, r); } bool - DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* buf) override + decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) override { bool read = false; if (!BEncodeMaybeReadDictEntry("P", P, read, k, buf)) @@ -97,22 +102,24 @@ namespace llarp return read; } - bool - BEncode(llarp_buffer_t* buf) const override + std::string + bt_encode() const override { - if (!bencode_start_dict(buf)) - return false; - - if (!BEncodeWriteDictMsgType(buf, "A", "D")) - return false; - if (!BEncodeWriteDictEntry("P", P, buf)) - return false; - if (!BEncodeWriteDictInt("S", S, buf)) - return false; - if (!BEncodeWriteDictInt("V", version, buf)) - return false; - - return bencode_end(buf); + oxenc::bt_dict_producer btdp; + + try + { + btdp.append("A", "D"); + btdp.append("P", P.ToView()); + btdp.append("S", S); + btdp.append("V", version); + } + catch (...) + { + log::critical(route_cat, "Error: DataDiscardMessage failed to bt encode contents!"); + } + + return std::move(btdp).str(); } }; } // namespace routing diff --git a/llarp/messages/link_intro.cpp b/llarp/messages/link_intro.cpp index 2ffab6f3c5..70b4b6df6c 100644 --- a/llarp/messages/link_intro.cpp +++ b/llarp/messages/link_intro.cpp @@ -6,10 +6,12 @@ #include #include +#include + namespace llarp { bool - LinkIntroMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) + LinkIntroMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) { if (key.startswith("a")) { @@ -22,14 +24,14 @@ namespace llarp } if (key.startswith("n")) { - if (N.BDecode(buf)) + if (nonce.BDecode(buf)) return true; llarp::LogWarn("failed to decode nonce in LIM"); return false; } if (key.startswith("p")) { - return bencode_read_integer(buf, &P); + return bencode_read_integer(buf, &session_period); } if (key.startswith("r")) { @@ -54,103 +56,104 @@ namespace llarp } if (key.startswith("z")) { - return Z.BDecode(buf); + return sig.BDecode(buf); } llarp::LogWarn("invalid LIM key: ", *key.cur); return false; } - bool - LinkIntroMessage::BEncode(llarp_buffer_t* buf) const + std::string + LinkIntroMessage::bt_encode() const { - if (!bencode_start_dict(buf)) - return false; - - if (!bencode_write_bytestring(buf, "a", 1)) - return false; - if (!bencode_write_bytestring(buf, "i", 1)) - return false; - - if (!bencode_write_bytestring(buf, "n", 1)) - return false; - if (!N.BEncode(buf)) - return false; - - if (!bencode_write_bytestring(buf, "p", 1)) - return false; - if (!bencode_write_uint64(buf, P)) - return false; + oxenc::bt_dict_producer btdp; - if (!bencode_write_bytestring(buf, "r", 1)) - return false; - if (!rc.BEncode(buf)) - return false; + try + { + btdp.append("a", "i"); + btdp.append("n", nonce.ToView()); + btdp.append("p", session_period); - if (!bencode_write_uint64_entry(buf, "v", 1, llarp::constants::proto_version)) - return false; + { + auto subdict = btdp.append_list("r"); + rc.bt_encode_subdict(subdict); + } - if (!bencode_write_bytestring(buf, "z", 1)) - return false; - if (!Z.BEncode(buf)) - return false; + btdp.append("v", llarp::constants::proto_version); + btdp.append("z", sig.ToView()); + } + catch (...) + { + log::critical(link_cat, "Error: LinkIntroMessage failed to bt encode contents!"); + } - return bencode_end(buf); + return std::move(btdp).str(); } bool - LinkIntroMessage::HandleMessage(AbstractRouter* /*router*/) const + LinkIntroMessage::handle_message(AbstractRouter* /*router*/) const { - if (!Verify()) + if (!verify()) return false; return session->GotLIM(this); } void - LinkIntroMessage::Clear() + LinkIntroMessage::clear() { - P = 0; - N.Zero(); + session_period = 0; + nonce.Zero(); rc.Clear(); - Z.Zero(); + sig.Zero(); version = 0; } bool - LinkIntroMessage::Sign(std::function signer) + LinkIntroMessage::sign(std::function signer) { - Z.Zero(); - std::array tmp; + sig.Zero(); + // need to keep this as a llarp_buffer_t for now, as all the crypto code expects + // byte_t types -- fix this later + std::array tmp; llarp_buffer_t buf(tmp); - if (!BEncode(&buf)) - return false; + + auto bte = bt_encode(); + buf.write(bte.begin(), bte.end()); + buf.sz = buf.cur - buf.base; buf.cur = buf.base; - return signer(Z, buf); + + return signer(sig, buf); } bool - LinkIntroMessage::Verify() const + LinkIntroMessage::verify() const { LinkIntroMessage copy; copy = *this; - copy.Z.Zero(); - std::array tmp; + copy.sig.Zero(); + + // need to keep this as a llarp_buffer_t for now, as all the crypto code expects + // byte_t types -- fix this later + std::array tmp; llarp_buffer_t buf(tmp); - if (!copy.BEncode(&buf)) - return false; + + auto bte = copy.bt_encode(); + buf.write(bte.begin(), bte.end()); + buf.sz = buf.cur - buf.base; buf.cur = buf.base; + // outer signature - if (!CryptoManager::instance()->verify(rc.pubkey, buf, Z)) + if (!CryptoManager::instance()->verify(rc.pubkey, buf, sig)) { - llarp::LogError("outer signature failure"); + log::error(link_cat, "Error: outer signature failed!"); return false; } // verify RC if (!rc.Verify(llarp::time_now_ms())) { - llarp::LogError("invalid RC in link intro"); + log::error(link_cat, "Error: invalid RC in link intro!"); return false; } return true; diff --git a/llarp/messages/link_intro.hpp b/llarp/messages/link_intro.hpp index 7cdc3190e0..c76b4ac81d 100644 --- a/llarp/messages/link_intro.hpp +++ b/llarp/messages/link_intro.hpp @@ -6,47 +6,47 @@ namespace llarp { - struct ILinkSession; + struct AbstractLinkSession; - struct LinkIntroMessage : public ILinkMessage + struct LinkIntroMessage final : public AbstractLinkMessage { - static constexpr size_t MaxSize = MAX_RC_SIZE + 256; + static constexpr size_t MAX_MSG_SIZE = MAX_RC_SIZE + 256; - LinkIntroMessage() : ILinkMessage() + LinkIntroMessage() : AbstractLinkMessage() {} RouterContact rc; - KeyExchangeNonce N; - Signature Z; - uint64_t P; + KeyExchangeNonce nonce; + Signature sig; + uint64_t session_period; - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) override; + std::string + bt_encode() const override; bool - BEncode(llarp_buffer_t* buf) const override; + handle_message(AbstractRouter* router) const override; bool - HandleMessage(AbstractRouter* router) const override; + decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; bool - Sign(std::function signer); + sign(std::function signer); bool - Verify() const; + verify() const; void - Clear() override; + clear() override; const char* - Name() const override + name() const override { return "LinkIntro"; } // always first uint16_t - Priority() const override + priority() const override { return std::numeric_limits::max(); } diff --git a/llarp/messages/link_message.hpp b/llarp/messages/link_message.hpp index af5af6413e..d96f183be9 100644 --- a/llarp/messages/link_message.hpp +++ b/llarp/messages/link_message.hpp @@ -1,5 +1,7 @@ #pragma once +#include "common.hpp" + #include #include #include @@ -7,60 +9,70 @@ #include +namespace +{ + static auto link_cat = llarp::log::Cat("lokinet.link"); +} // namespace + namespace llarp { - struct ILinkSession; + struct AbstractLinkSession; struct AbstractRouter; /// parsed link layer message - struct ILinkMessage + struct AbstractLinkMessage : private AbstractSerializable { /// who did this message come from or is going to - ILinkSession* session = nullptr; + AbstractLinkSession* session = nullptr; uint64_t version = llarp::constants::proto_version; PathID_t pathid; - ILinkMessage() = default; + AbstractLinkMessage() = default; - virtual ~ILinkMessage() = default; + virtual ~AbstractLinkMessage() = default; - virtual bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) = 0; - - bool - BDecode(llarp_buffer_t* buf) - { - // default version if not specified is 0 - uint64_t v = 0; - // seek for version and set it if we got it - if (BEncodeSeekDictVersion(v, buf, 'v')) - { - version = v; - } - // when we hit the code path version is set and we can tell how to decode - return bencode_decode_dict(*this, buf); - } + std::string + bt_encode() const override = 0; virtual bool - BEncode(llarp_buffer_t* buf) const = 0; + handle_message(AbstractRouter* router) const = 0; virtual bool - HandleMessage(AbstractRouter* router) const = 0; + decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) = 0; virtual void - Clear() = 0; + clear() = 0; // the name of this kind of message virtual const char* - Name() const = 0; + name() const = 0; /// get message prority, higher value means more important virtual uint16_t - Priority() const + priority() const { return 1; } + + // methods we do not want to inherit onwards from AbstractSerializable + void + bt_encode(llarp_buffer&) const final + { + throw std::runtime_error{"Error: Link messages should not encode directly to a buffer!"}; + } + void + bt_encode(oxenc::bt_dict_producer&) const final + { + throw std::runtime_error{ + "Error: Link messages should not encode directly to a bt list producer!"}; + } + void + bt_encode(oxenc::bt_list_producer&) const final + { + throw std::runtime_error{ + "Error: Link messages should not encode directly to a bt list producer!"}; + } }; } // namespace llarp diff --git a/llarp/messages/link_message_parser.cpp b/llarp/messages/link_message_parser.cpp index 814b7d0d6e..af2b5c75fe 100644 --- a/llarp/messages/link_message_parser.cpp +++ b/llarp/messages/link_message_parser.cpp @@ -99,7 +99,7 @@ namespace llarp if (!key) return MessageDone(); - return msg->DecodeKey(*key, buffer); + return msg->decode_key(*key, buffer); } bool @@ -108,14 +108,14 @@ namespace llarp bool result = false; if (msg) { - result = msg->HandleMessage(router); + result = msg->handle_message(router); } Reset(); return result; } bool - LinkMessageParser::ProcessFrom(ILinkSession* src, const llarp_buffer_t& buf) + LinkMessageParser::ProcessFrom(AbstractLinkSession* src, const llarp_buffer_t& buf) { if (!src) { @@ -133,7 +133,7 @@ namespace llarp LinkMessageParser::Reset() { if (msg) - msg->Clear(); + msg->clear(); msg = nullptr; } } // namespace llarp diff --git a/llarp/messages/link_message_parser.hpp b/llarp/messages/link_message_parser.hpp index f20e5dc652..584142418a 100644 --- a/llarp/messages/link_message_parser.hpp +++ b/llarp/messages/link_message_parser.hpp @@ -8,8 +8,8 @@ namespace llarp { struct AbstractRouter; - struct ILinkMessage; - struct ILinkSession; + struct AbstractLinkMessage; + struct AbstractLinkSession; struct LinkMessageParser { @@ -21,7 +21,7 @@ namespace llarp /// start processig message from a link session bool - ProcessFrom(ILinkSession* from, const llarp_buffer_t& buf); + ProcessFrom(AbstractLinkSession* from, const llarp_buffer_t& buf); /// called when the message is fully read /// return true when the message was accepted otherwise returns false @@ -39,8 +39,8 @@ namespace llarp private: bool firstkey; AbstractRouter* router; - ILinkSession* from; - ILinkMessage* msg; + AbstractLinkSession* from; + AbstractLinkMessage* msg; struct msg_holder_t; diff --git a/llarp/messages/relay.cpp b/llarp/messages/relay.cpp index ace3d7df2a..02a0e0b54d 100644 --- a/llarp/messages/relay.cpp +++ b/llarp/messages/relay.cpp @@ -7,109 +7,113 @@ namespace llarp { void - RelayUpstreamMessage::Clear() + RelayUpstreamMessage::clear() { pathid.Zero(); - X.Clear(); - Y.Zero(); + enc.Clear(); + nonce.Zero(); version = 0; } - bool - RelayUpstreamMessage::BEncode(llarp_buffer_t* buf) const + std::string + RelayUpstreamMessage::bt_encode() const { - if (!bencode_start_dict(buf)) - return false; - if (!BEncodeWriteDictMsgType(buf, "a", "u")) - return false; + oxenc::bt_dict_producer btdp; - if (!BEncodeWriteDictEntry("p", pathid, buf)) - return false; - if (!BEncodeWriteDictInt("v", llarp::constants::proto_version, buf)) - return false; - if (!BEncodeWriteDictEntry("x", X, buf)) - return false; - if (!BEncodeWriteDictEntry("y", Y, buf)) - return false; - return bencode_end(buf); + try + { + btdp.append("a", "u"); + btdp.append("p", pathid.ToView()); + btdp.append("v", llarp::constants::proto_version); + btdp.append("x", std::string_view{reinterpret_cast(enc.data()), enc.size()}); + btdp.append("y", std::string_view{reinterpret_cast(nonce.data()), nonce.size()}); + } + catch (...) + { + log::critical(link_cat, "Error: RelayUpstreamMessage failed to bt encode contents!"); + } + + return std::move(btdp).str(); } bool - RelayUpstreamMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) + RelayUpstreamMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) { bool read = false; if (!BEncodeMaybeReadDictEntry("p", pathid, read, key, buf)) return false; if (!BEncodeMaybeVerifyVersion("v", version, llarp::constants::proto_version, read, key, buf)) return false; - if (!BEncodeMaybeReadDictEntry("x", X, read, key, buf)) + if (!BEncodeMaybeReadDictEntry("x", enc, read, key, buf)) return false; - if (!BEncodeMaybeReadDictEntry("y", Y, read, key, buf)) + if (!BEncodeMaybeReadDictEntry("y", nonce, read, key, buf)) return false; return read; } bool - RelayUpstreamMessage::HandleMessage(AbstractRouter* r) const + RelayUpstreamMessage::handle_message(AbstractRouter* r) const { auto path = r->pathContext().GetByDownstream(session->GetPubKey(), pathid); if (path) { - return path->HandleUpstream(llarp_buffer_t(X), Y, r); + return path->HandleUpstream(llarp_buffer_t(enc), nonce, r); } return false; } void - RelayDownstreamMessage::Clear() + RelayDownstreamMessage::clear() { pathid.Zero(); - X.Clear(); - Y.Zero(); + enc.Clear(); + nonce.Zero(); version = 0; } - bool - RelayDownstreamMessage::BEncode(llarp_buffer_t* buf) const + std::string + RelayDownstreamMessage::bt_encode() const { - if (!bencode_start_dict(buf)) - return false; - if (!BEncodeWriteDictMsgType(buf, "a", "d")) - return false; + oxenc::bt_dict_producer btdp; - if (!BEncodeWriteDictEntry("p", pathid, buf)) - return false; - if (!BEncodeWriteDictInt("v", llarp::constants::proto_version, buf)) - return false; - if (!BEncodeWriteDictEntry("x", X, buf)) - return false; - if (!BEncodeWriteDictEntry("y", Y, buf)) - return false; - return bencode_end(buf); + try + { + btdp.append("a", "d"); + btdp.append("p", pathid.ToView()); + btdp.append("v", llarp::constants::proto_version); + btdp.append("x", std::string_view{reinterpret_cast(enc.data()), enc.size()}); + btdp.append("y", std::string_view{reinterpret_cast(nonce.data()), nonce.size()}); + } + catch (...) + { + log::critical(link_cat, "Error: RelayDownstreamMessage failed to bt encode contents!"); + } + + return std::move(btdp).str(); } bool - RelayDownstreamMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) + RelayDownstreamMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) { bool read = false; if (!BEncodeMaybeReadDictEntry("p", pathid, read, key, buf)) return false; if (!BEncodeMaybeVerifyVersion("v", version, llarp::constants::proto_version, read, key, buf)) return false; - if (!BEncodeMaybeReadDictEntry("x", X, read, key, buf)) + if (!BEncodeMaybeReadDictEntry("x", enc, read, key, buf)) return false; - if (!BEncodeMaybeReadDictEntry("y", Y, read, key, buf)) + if (!BEncodeMaybeReadDictEntry("y", nonce, read, key, buf)) return false; return read; } bool - RelayDownstreamMessage::HandleMessage(AbstractRouter* r) const + RelayDownstreamMessage::handle_message(AbstractRouter* r) const { auto path = r->pathContext().GetByUpstream(session->GetPubKey(), pathid); if (path) { - return path->HandleDownstream(llarp_buffer_t(X), Y, r); + return path->HandleDownstream(llarp_buffer_t(enc), nonce, r); } llarp::LogWarn("no path for downstream message id=", pathid); return false; diff --git a/llarp/messages/relay.hpp b/llarp/messages/relay.hpp index a7d07c8de7..d7b6c26ceb 100644 --- a/llarp/messages/relay.hpp +++ b/llarp/messages/relay.hpp @@ -9,60 +9,60 @@ namespace llarp { - struct RelayUpstreamMessage : public ILinkMessage + struct RelayUpstreamMessage final : public AbstractLinkMessage { - Encrypted X; - TunnelNonce Y; + Encrypted enc; + TunnelNonce nonce; bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) override; + decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; - bool - BEncode(llarp_buffer_t* buf) const override; + std::string + bt_encode() const override; bool - HandleMessage(AbstractRouter* router) const override; + handle_message(AbstractRouter* router) const override; void - Clear() override; - const char* + clear() override; - Name() const override + const char* + name() const override { return "RelayUpstream"; } uint16_t - Priority() const override + priority() const override { return 0; } }; - struct RelayDownstreamMessage : public ILinkMessage + struct RelayDownstreamMessage final : public AbstractLinkMessage { - Encrypted X; - TunnelNonce Y; + Encrypted enc; + TunnelNonce nonce; bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) override; + decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; - bool - BEncode(llarp_buffer_t* buf) const override; + std::string + bt_encode() const override; bool - HandleMessage(AbstractRouter* router) const override; + handle_message(AbstractRouter* router) const override; void - Clear() override; + clear() override; const char* - Name() const override + name() const override { return "RelayDownstream"; } uint16_t - Priority() const override + priority() const override { return 0; } diff --git a/llarp/messages/relay_commit.cpp b/llarp/messages/relay_commit.cpp index 887fc680e8..f8810fdac0 100644 --- a/llarp/messages/relay_commit.cpp +++ b/llarp/messages/relay_commit.cpp @@ -20,7 +20,7 @@ namespace llarp { bool - LR_CommitMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) + LR_CommitMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) { if (key.startswith("c")) { @@ -36,32 +36,39 @@ namespace llarp } void - LR_CommitMessage::Clear() + LR_CommitMessage::clear() { std::for_each(frames.begin(), frames.end(), [](auto& f) { f.Clear(); }); version = 0; } - bool - LR_CommitMessage::BEncode(llarp_buffer_t* buf) const + std::string + LR_CommitMessage::bt_encode() const { - if (!bencode_start_dict(buf)) - return false; - // msg type - if (!BEncodeWriteDictMsgType(buf, "a", "c")) - return false; - // frames - if (!BEncodeWriteDictArray("c", frames, buf)) - return false; - // version - if (!bencode_write_uint64_entry(buf, "v", 1, llarp::constants::proto_version)) - return false; + oxenc::bt_dict_producer btdp; - return bencode_end(buf); + try + { + btdp.append("a", "c"); + { + auto sublist = btdp.append_list("c"); + + for (auto& f : frames) + sublist.append({reinterpret_cast(f.data()), f.size()}); + } + + btdp.append("v", llarp::constants::proto_version); + } + catch (...) + { + log::critical(link_cat, "Error: LR_CommitMessage failed to bt encode contents!"); + } + + return std::move(btdp).str(); } bool - LR_CommitMessage::HandleMessage(AbstractRouter* router) const + LR_CommitMessage::handle_message(AbstractRouter* router) const { if (frames.size() != path::max_len) { diff --git a/llarp/messages/relay_commit.hpp b/llarp/messages/relay_commit.hpp index 1649339170..f6c1c371fd 100644 --- a/llarp/messages/relay_commit.hpp +++ b/llarp/messages/relay_commit.hpp @@ -45,12 +45,12 @@ namespace llarp OnKey(llarp_buffer_t* buffer, llarp_buffer_t* key); }; - struct LR_CommitMessage : public ILinkMessage + struct LR_CommitMessage final : public AbstractLinkMessage { std::array frames; LR_CommitMessage(std::array _frames) - : ILinkMessage(), frames(std::move(_frames)) + : AbstractLinkMessage(), frames(std::move(_frames)) {} LR_CommitMessage() = default; @@ -58,28 +58,28 @@ namespace llarp ~LR_CommitMessage() override = default; void - Clear() override; + clear() override; bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) override; + decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; - bool - BEncode(llarp_buffer_t* buf) const override; + std::string + bt_encode() const override; bool - HandleMessage(AbstractRouter* router) const override; + handle_message(AbstractRouter* router) const override; bool AsyncDecrypt(llarp::path::PathContext* context) const; const char* - Name() const override + name() const override { return "RelayCommit"; } - virtual uint16_t - Priority() const override + uint16_t + priority() const override { return 5; } diff --git a/llarp/messages/relay_status.cpp b/llarp/messages/relay_status.cpp index 0f5fdc6070..44a02f3dea 100644 --- a/llarp/messages/relay_status.cpp +++ b/llarp/messages/relay_status.cpp @@ -57,7 +57,7 @@ namespace llarp }; bool - LR_StatusMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) + LR_StatusMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) { bool read = false; if (key.startswith("c")) @@ -90,39 +90,43 @@ namespace llarp } void - LR_StatusMessage::Clear() + LR_StatusMessage::clear() { std::for_each(frames.begin(), frames.end(), [](auto& f) { f.Clear(); }); version = 0; status = 0; } - bool - LR_StatusMessage::BEncode(llarp_buffer_t* buf) const + std::string + LR_StatusMessage::bt_encode() const { - if (!bencode_start_dict(buf)) - return false; - // msg type - if (!BEncodeWriteDictMsgType(buf, "a", "s")) - return false; - // frames - if (!BEncodeWriteDictArray("c", frames, buf)) - return false; - // path id - if (!BEncodeWriteDictEntry("p", pathid, buf)) - return false; - // status (for now, only success bit is relevant) - if (!BEncodeWriteDictInt("s", status, buf)) - return false; - // version - if (!bencode_write_uint64_entry(buf, "v", 1, llarp::constants::proto_version)) - return false; + oxenc::bt_dict_producer btdp; + + try + { + btdp.append("a", "s"); + + { + auto sublist = btdp.append_list("c"); + + for (auto& f : frames) + sublist.append({reinterpret_cast(f.data()), f.size()}); + } + + btdp.append("p", pathid.ToView()); + btdp.append("s", status); + btdp.append("v", llarp::constants::proto_version); + } + catch (...) + { + log::critical(link_cat, "Error: LR_StatusMessage failed to bt encode contents!"); + } - return bencode_end(buf); + return std::move(btdp).str(); } bool - LR_StatusMessage::HandleMessage(AbstractRouter* router) const + LR_StatusMessage::handle_message(AbstractRouter* router) const { llarp::LogDebug("Received LR_Status message from (", session->GetPubKey(), ")"); if (frames.size() != path::max_len) @@ -198,14 +202,14 @@ namespace llarp if (!record.BEncode(&buf)) { // failed to encode? - LogError(Name(), " Failed to generate Status Record"); + LogError(name(), " Failed to generate Status Record"); DumpBuffer(buf); return false; } // use ephemeral keypair for frame if (!frame.DoEncrypt(pathKey, true)) { - LogError(Name(), " Failed to encrypt LRSR"); + LogError(name(), " Failed to encrypt LRSR"); DumpBuffer(buf); return false; } diff --git a/llarp/messages/relay_status.hpp b/llarp/messages/relay_status.hpp index 265ce6a085..e30d6479fc 100644 --- a/llarp/messages/relay_status.hpp +++ b/llarp/messages/relay_status.hpp @@ -53,7 +53,7 @@ namespace llarp std::string LRStatusCodeToString(uint64_t status); - struct LR_StatusMessage : public ILinkMessage + struct LR_StatusMessage final : public AbstractLinkMessage { std::array frames; @@ -62,7 +62,7 @@ namespace llarp uint64_t status = 0; LR_StatusMessage(std::array _frames) - : ILinkMessage(), frames(std::move(_frames)) + : AbstractLinkMessage(), frames(std::move(_frames)) {} LR_StatusMessage() = default; @@ -70,16 +70,16 @@ namespace llarp ~LR_StatusMessage() override = default; void - Clear() override; + clear() override; bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) override; + decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; - bool - BEncode(llarp_buffer_t* buf) const override; + std::string + bt_encode() const override; bool - HandleMessage(AbstractRouter* router) const override; + handle_message(AbstractRouter* router) const override; void SetDummyFrames(); @@ -111,12 +111,12 @@ namespace llarp std::shared_ptr hop); const char* - Name() const override + name() const override { return "RelayStatus"; } - virtual uint16_t - Priority() const override + uint16_t + priority() const override { return 6; } diff --git a/llarp/net/ip_address.hpp b/llarp/net/ip_address.hpp index 51fbb050c9..e0a8f477f8 100644 --- a/llarp/net/ip_address.hpp +++ b/llarp/net/ip_address.hpp @@ -24,7 +24,7 @@ namespace llarp /// Empty constructor. IpAddress() = default; /// move construtor - IpAddress(IpAddress &&) = default; + IpAddress(IpAddress&&) = default; /// copy construct IpAddress(const IpAddress&); @@ -54,64 +54,80 @@ namespace llarp /// @param addr is an SockAddr to initialize from. IpAddress(const SockAddr& addr); - IpAddress& operator=(const sockaddr& other); + IpAddress& + operator=(const sockaddr& other); /// move assignment - IpAddress& operator=(IpAddress&& other); + IpAddress& + operator=(IpAddress&& other); /// copy assignment - IpAddress& operator=(const IpAddress& other); + IpAddress& + operator=(const IpAddress& other); /// Return the port. Returns -1 if no port has been provided. /// /// @return the port, if present - std::optional getPort() const; + std::optional + getPort() const; /// Return true if we have a port set otherwise return false - bool hasPort() const; + bool + hasPort() const; /// Set the port. /// /// @param port - void setPort(std::optional port); + void + setPort(std::optional port); /// Set the IP address. Follows the same logic as the constructor with the same signature, but /// doesn't overwrite the port if the port isn't present in the string. - void setAddress(std::string_view str); - void setAddress(std::string_view str, std::optional port); + void + setAddress(std::string_view str); + void + setAddress(std::string_view str, std::optional port); /// Returns true if this is an IPv4 address (or an IPv6 address representing an IPv4 address) /// /// TODO: could return an int (e.g. 4 or 6) or an enum /// /// @return true if this is an IPv4 address, false otherwise - bool isIPv4(); + bool + isIPv4(); /// Returns true if this represents a valid IpAddress, false otherwise. /// /// @return whether or not this IpAddress is empty - bool isEmpty() const; + bool + isEmpty() const; /// Creates an instance of SockAddr representing this IpAddress. /// /// @return an instance of a SockAddr created from this IpAddress - SockAddr createSockAddr() const; + SockAddr + createSockAddr() const; /// Returns true if this IpAddress is a bogon, false otherwise /// /// @return whether or not this IpAddress is a bogon - bool isBogon() const; + bool + isBogon() const; /// Returns a string representing this IpAddress /// /// @return string representation of this IpAddress - std::string ToString() const; + std::string + ToString() const; - std::string toHost() const; + std::string + toHost() const; - huint32_t toIP() const; + huint32_t + toIP() const; - huint128_t toIP6() const; + huint128_t + toIP6() const; // TODO: other utility functions left over from Addr which may be useful // IsBogon() const; @@ -119,9 +135,11 @@ namespace llarp // std::hash // to string / stream / etc - bool operator<(const IpAddress& other) const; + bool + operator<(const IpAddress& other) const; - bool operator==(const IpAddress& other) const; + bool + operator==(const IpAddress& other) const; private: bool m_empty = true; diff --git a/llarp/net/net_int.hpp b/llarp/net/net_int.hpp index 173a764bd1..9bb545107d 100644 --- a/llarp/net/net_int.hpp +++ b/llarp/net/net_int.hpp @@ -257,24 +257,26 @@ namespace llarp inline constexpr bool IsToStringFormattable = true; using nuint16_t /* [[deprecated("use llarp::net::port_t instead")]] */ = llarp::net::port_t; - using nuint32_t /* [[deprecated("use llarp::net::ipv4addr_t instead")]] */ = llarp::net::ipv4addr_t; - using nuint128_t /* [[deprecated("use llarp::net::ipv6addr_t instead")]] */ = llarp::net::ipv6addr_t; + using nuint32_t /* [[deprecated("use llarp::net::ipv4addr_t instead")]] */ = + llarp::net::ipv4addr_t; + using nuint128_t /* [[deprecated("use llarp::net::ipv6addr_t instead")]] */ = + llarp::net::ipv6addr_t; template -/* [[deprecated("use llarp::net::ToNet instead")]] */ inline llarp::nuint_t + /* [[deprecated("use llarp::net::ToNet instead")]] */ inline llarp::nuint_t ToNet(llarp::huint_t x) { return llarp::net::ToNet(x); } template -/* [[deprecated("use llarp::net::ToHost instead")]] */ inline llarp::huint_t + /* [[deprecated("use llarp::net::ToHost instead")]] */ inline llarp::huint_t ToHost(llarp::nuint_t x) { return llarp::net::ToHost(x); } -/* [[deprecated("use llarp::net::ToHost instead")]] */ inline net::ipv4addr_t + /* [[deprecated("use llarp::net::ToHost instead")]] */ inline net::ipv4addr_t xhtonl(huint32_t x) { return ToNet(x); diff --git a/llarp/path/ihophandler.hpp b/llarp/path/ihophandler.hpp index 0465ca9fb8..e9bc981f35 100644 --- a/llarp/path/ihophandler.hpp +++ b/llarp/path/ihophandler.hpp @@ -17,7 +17,7 @@ namespace llarp namespace routing { - struct IMessage; + struct AbstractRoutingMessage; } namespace path @@ -43,7 +43,7 @@ namespace llarp /// send routing message and increment sequence number virtual bool - SendRoutingMessage(const routing::IMessage& msg, AbstractRouter* r) = 0; + SendRoutingMessage(const routing::AbstractRoutingMessage& msg, AbstractRouter* r) = 0; // handle data in upstream direction virtual bool diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index f777611e78..b9cccbe4b4 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -21,893 +21,889 @@ #include #include -namespace llarp +namespace llarp::path { - namespace path - { - Path::Path( - const std::vector& h, - std::weak_ptr pathset, - PathRole startingRoles, - std::string shortName) - : m_PathSet{std::move(pathset)}, _role{startingRoles}, m_shortName{std::move(shortName)} + Path::Path( + const std::vector& h, + std::weak_ptr pathset, + PathRole startingRoles, + std::string shortName) + : m_PathSet{std::move(pathset)}, _role{startingRoles}, m_shortName{std::move(shortName)} + { + hops.resize(h.size()); + size_t hsz = h.size(); + for (size_t idx = 0; idx < hsz; ++idx) { - hops.resize(h.size()); - size_t hsz = h.size(); - for (size_t idx = 0; idx < hsz; ++idx) + hops[idx].rc = h[idx]; + do { - hops[idx].rc = h[idx]; - do - { - hops[idx].txID.Randomize(); - } while (hops[idx].txID.IsZero()); - - do - { - hops[idx].rxID.Randomize(); - } while (hops[idx].rxID.IsZero()); - } + hops[idx].txID.Randomize(); + } while (hops[idx].txID.IsZero()); - for (size_t idx = 0; idx < hsz - 1; ++idx) + do { - hops[idx].txID = hops[idx + 1].rxID; - } - // initialize parts of the introduction - intro.router = hops[hsz - 1].rc.pubkey; - intro.pathID = hops[hsz - 1].txID; - if (auto parent = m_PathSet.lock()) - EnterState(ePathBuilding, parent->Now()); + hops[idx].rxID.Randomize(); + } while (hops[idx].rxID.IsZero()); } - void - Path::SetBuildResultHook(BuildResultHookFunc func) + for (size_t idx = 0; idx < hsz - 1; ++idx) { - m_BuiltHook = func; + hops[idx].txID = hops[idx + 1].rxID; } + // initialize parts of the introduction + intro.router = hops[hsz - 1].rc.pubkey; + intro.pathID = hops[hsz - 1].txID; + if (auto parent = m_PathSet.lock()) + EnterState(ePathBuilding, parent->Now()); + } - bool - Path::HandleUpstream(const llarp_buffer_t& X, const TunnelNonce& Y, AbstractRouter* r) - { - if (not m_UpstreamReplayFilter.Insert(Y)) - return false; - return IHopHandler::HandleUpstream(X, Y, r); - } + void + Path::SetBuildResultHook(BuildResultHookFunc func) + { + m_BuiltHook = func; + } - bool - Path::HandleDownstream(const llarp_buffer_t& X, const TunnelNonce& Y, AbstractRouter* r) - { - if (not m_DownstreamReplayFilter.Insert(Y)) - return false; - return IHopHandler::HandleDownstream(X, Y, r); - } + bool + Path::HandleUpstream(const llarp_buffer_t& X, const TunnelNonce& Y, AbstractRouter* r) + { + if (not m_UpstreamReplayFilter.Insert(Y)) + return false; + return IHopHandler::HandleUpstream(X, Y, r); + } - RouterID - Path::Endpoint() const - { - return hops[hops.size() - 1].rc.pubkey; - } + bool + Path::HandleDownstream(const llarp_buffer_t& X, const TunnelNonce& Y, AbstractRouter* r) + { + if (not m_DownstreamReplayFilter.Insert(Y)) + return false; + return IHopHandler::HandleDownstream(X, Y, r); + } - PubKey - Path::EndpointPubKey() const - { - return hops[hops.size() - 1].rc.pubkey; - } + RouterID + Path::Endpoint() const + { + return hops[hops.size() - 1].rc.pubkey; + } - PathID_t - Path::TXID() const - { - return hops[0].txID; - } + PubKey + Path::EndpointPubKey() const + { + return hops[hops.size() - 1].rc.pubkey; + } - PathID_t - Path::RXID() const - { - return hops[0].rxID; - } + PathID_t + Path::TXID() const + { + return hops[0].txID; + } - bool - Path::IsReady() const - { - if (Expired(llarp::time_now_ms())) - return false; - return intro.latency > 0s && _status == ePathEstablished; - } + PathID_t + Path::RXID() const + { + return hops[0].rxID; + } - bool - Path::IsEndpoint(const RouterID& r, const PathID_t& id) const - { - return hops[hops.size() - 1].rc.pubkey == r && hops[hops.size() - 1].txID == id; - } + bool + Path::IsReady() const + { + if (Expired(llarp::time_now_ms())) + return false; + return intro.latency > 0s && _status == ePathEstablished; + } - RouterID - Path::Upstream() const - { - return hops[0].rc.pubkey; - } + bool + Path::IsEndpoint(const RouterID& r, const PathID_t& id) const + { + return hops[hops.size() - 1].rc.pubkey == r && hops[hops.size() - 1].txID == id; + } + + RouterID + Path::Upstream() const + { + return hops[0].rc.pubkey; + } - const std::string& - Path::ShortName() const + const std::string& + Path::ShortName() const + { + return m_shortName; + } + + std::string + Path::HopsString() const + { + std::string hops_str; + hops_str.reserve(hops.size() * 62); // 52 for the pkey, 6 for .snode, 4 for the ' -> ' joiner + for (const auto& hop : hops) { - return m_shortName; + if (!hops.empty()) + hops_str += " -> "; + hops_str += RouterID(hop.rc.pubkey).ToString(); } + return hops_str; + } + + bool + Path::HandleLRSM(uint64_t status, std::array& frames, AbstractRouter* r) + { + uint64_t currentStatus = status; - std::string - Path::HopsString() const + size_t index = 0; + std::optional failedAt; + while (index < hops.size()) { - std::string hops_str; - hops_str.reserve(hops.size() * 62); // 52 for the pkey, 6 for .snode, 4 for the ' -> ' joiner - for (const auto& hop : hops) + if (!frames[index].DoDecrypt(hops[index].shared)) { - if (!hops.empty()) - hops_str += " -> "; - hops_str += RouterID(hop.rc.pubkey).ToString(); + currentStatus = LR_StatusRecord::FAIL_DECRYPT_ERROR; + failedAt = hops[index].rc.pubkey; + break; } - return hops_str; - } + llarp::LogDebug("decrypted LRSM frame from ", hops[index].rc.pubkey); - bool - Path::HandleLRSM(uint64_t status, std::array& frames, AbstractRouter* r) - { - uint64_t currentStatus = status; + llarp_buffer_t* buf = frames[index].Buffer(); + buf->cur = buf->base + EncryptedFrameOverheadSize; - size_t index = 0; - std::optional failedAt; - while (index < hops.size()) + LR_StatusRecord record; + // successful decrypt + if (!record.BDecode(buf)) { - if (!frames[index].DoDecrypt(hops[index].shared)) - { - currentStatus = LR_StatusRecord::FAIL_DECRYPT_ERROR; - failedAt = hops[index].rc.pubkey; - break; - } - llarp::LogDebug("decrypted LRSM frame from ", hops[index].rc.pubkey); - - llarp_buffer_t* buf = frames[index].Buffer(); - buf->cur = buf->base + EncryptedFrameOverheadSize; + llarp::LogWarn("malformed frame inside LRCM from ", hops[index].rc.pubkey); + currentStatus = LR_StatusRecord::FAIL_MALFORMED_RECORD; + failedAt = hops[index].rc.pubkey; + break; + } + llarp::LogDebug("Decoded LR Status Record from ", hops[index].rc.pubkey); - LR_StatusRecord record; - // successful decrypt - if (!record.BDecode(buf)) + currentStatus = record.status; + if ((record.status & LR_StatusRecord::SUCCESS) != LR_StatusRecord::SUCCESS) + { + if (record.status & LR_StatusRecord::FAIL_CONGESTION and index == 0) { - llarp::LogWarn("malformed frame inside LRCM from ", hops[index].rc.pubkey); - currentStatus = LR_StatusRecord::FAIL_MALFORMED_RECORD; + // first hop building too fast failedAt = hops[index].rc.pubkey; break; } - llarp::LogDebug("Decoded LR Status Record from ", hops[index].rc.pubkey); - - currentStatus = record.status; - if ((record.status & LR_StatusRecord::SUCCESS) != LR_StatusRecord::SUCCESS) + // failed at next hop + if (index + 1 < hops.size()) { - if (record.status & LR_StatusRecord::FAIL_CONGESTION and index == 0) - { - // first hop building too fast - failedAt = hops[index].rc.pubkey; - break; - } - // failed at next hop - if (index + 1 < hops.size()) - { - failedAt = hops[index + 1].rc.pubkey; - } - break; + failedAt = hops[index + 1].rc.pubkey; } - ++index; + break; } + ++index; + } - if ((currentStatus & LR_StatusRecord::SUCCESS) == LR_StatusRecord::SUCCESS) + if ((currentStatus & LR_StatusRecord::SUCCESS) == LR_StatusRecord::SUCCESS) + { + llarp::LogDebug("LR_Status message processed, path build successful"); + r->loop()->call([r, self = shared_from_this()] { self->HandlePathConfirmMessage(r); }); + } + else + { + if (failedAt) { - llarp::LogDebug("LR_Status message processed, path build successful"); - r->loop()->call([r, self = shared_from_this()] { self->HandlePathConfirmMessage(r); }); + r->NotifyRouterEvent(Endpoint(), RXID(), *failedAt); + LogWarn( + Name(), + " build failed at ", + *failedAt, + " status=", + LRStatusCodeToString(currentStatus), + " hops=", + HopsString()); + r->routerProfiling().MarkHopFail(*failedAt); } else - { - if (failedAt) - { - r->NotifyRouterEvent(Endpoint(), RXID(), *failedAt); - LogWarn( - Name(), - " build failed at ", - *failedAt, - " status=", - LRStatusCodeToString(currentStatus), - " hops=", - HopsString()); - r->routerProfiling().MarkHopFail(*failedAt); - } - else - r->routerProfiling().MarkPathFail(this); - llarp::LogDebug("LR_Status message processed, path build failed"); - - if (currentStatus & LR_StatusRecord::FAIL_TIMEOUT) - { - llarp::LogDebug("Path build failed due to timeout"); - } - else if (currentStatus & LR_StatusRecord::FAIL_CONGESTION) - { - llarp::LogDebug("Path build failed due to congestion"); - } - else if (currentStatus & LR_StatusRecord::FAIL_DEST_UNKNOWN) - { - llarp::LogDebug( - "Path build failed due to one or more nodes giving destination " - "unknown"); - } - else if (currentStatus & LR_StatusRecord::FAIL_DEST_INVALID) - { - llarp::LogDebug( - "Path build failed due to one or more nodes considered an " - "invalid destination"); - if (failedAt) - { - r->loop()->call([nodedb = r->nodedb(), router = *failedAt]() { - LogInfo("router ", router, " is deregistered so we remove it"); - nodedb->Remove(router); - }); - } - } - else if (currentStatus & LR_StatusRecord::FAIL_CANNOT_CONNECT) - { - llarp::LogDebug( - "Path build failed due to a node being unable to connect to the " - "next hop"); - } - else if (currentStatus & LR_StatusRecord::FAIL_MALFORMED_RECORD) - { - llarp::LogDebug( - "Path build failed due to a malformed record in the build status " - "message"); - } - else if (currentStatus & LR_StatusRecord::FAIL_DECRYPT_ERROR) - { - llarp::LogDebug( - "Path build failed due to a decrypt error in the build status " - "message"); - } - else - { - llarp::LogDebug("Path build failed for an unspecified reason"); - } - RouterID edge{}; - if (failedAt) - edge = *failedAt; - r->loop()->call([r, self = shared_from_this(), edge]() { - self->EnterState(ePathFailed, r->Now()); - if (auto parent = self->m_PathSet.lock()) - { - parent->HandlePathBuildFailedAt(self, edge); - } - }); - } - - // TODO: meaningful return value? - return true; - } // namespace path + r->routerProfiling().MarkPathFail(this); + llarp::LogDebug("LR_Status message processed, path build failed"); - void - Path::EnterState(PathStatus st, llarp_time_t now) - { - if (st == ePathFailed) - { - _status = st; - return; - } - if (st == ePathExpired && _status == ePathBuilding) + if (currentStatus & LR_StatusRecord::FAIL_TIMEOUT) { - _status = st; - if (auto parent = m_PathSet.lock()) - { - parent->HandlePathBuildTimeout(shared_from_this()); - } + llarp::LogDebug("Path build failed due to timeout"); } - else if (st == ePathBuilding) + else if (currentStatus & LR_StatusRecord::FAIL_CONGESTION) { - LogInfo("path ", Name(), " is building"); - buildStarted = now; + llarp::LogDebug("Path build failed due to congestion"); } - else if (st == ePathEstablished && _status == ePathBuilding) + else if (currentStatus & LR_StatusRecord::FAIL_DEST_UNKNOWN) { - LogInfo("path ", Name(), " is built, took ", ToString(now - buildStarted)); + llarp::LogDebug( + "Path build failed due to one or more nodes giving destination " + "unknown"); } - else if (st == ePathTimeout && _status == ePathEstablished) + else if (currentStatus & LR_StatusRecord::FAIL_DEST_INVALID) { - LogInfo("path ", Name(), " died"); - _status = st; - if (auto parent = m_PathSet.lock()) + llarp::LogDebug( + "Path build failed due to one or more nodes considered an " + "invalid destination"); + if (failedAt) { - parent->HandlePathDied(shared_from_this()); + r->loop()->call([nodedb = r->nodedb(), router = *failedAt]() { + LogInfo("router ", router, " is deregistered so we remove it"); + nodedb->Remove(router); + }); } } - else if (st == ePathEstablished && _status == ePathTimeout) + else if (currentStatus & LR_StatusRecord::FAIL_CANNOT_CONNECT) { - LogInfo("path ", Name(), " reanimated"); + llarp::LogDebug( + "Path build failed due to a node being unable to connect to the " + "next hop"); } - else if (st == ePathIgnore) + else if (currentStatus & LR_StatusRecord::FAIL_MALFORMED_RECORD) { - LogInfo("path ", Name(), " ignored"); + llarp::LogDebug( + "Path build failed due to a malformed record in the build status " + "message"); } - _status = st; - } - - util::StatusObject - PathHopConfig::ExtractStatus() const - { - const auto ip = net::In6ToHUInt(rc.addrs[0].ip); - util::StatusObject obj{ - {"ip", ip.ToString()}, - {"lifetime", to_json(lifetime)}, - {"router", rc.pubkey.ToHex()}, - {"txid", txID.ToHex()}, - {"rxid", rxID.ToHex()}}; - return obj; - } - - util::StatusObject - Path::ExtractStatus() const - { - auto now = llarp::time_now_ms(); - - util::StatusObject obj{ - {"intro", intro.ExtractStatus()}, - {"lastRecvMsg", to_json(m_LastRecvMessage)}, - {"lastLatencyTest", to_json(m_LastLatencyTestTime)}, - {"buildStarted", to_json(buildStarted)}, - {"expired", Expired(now)}, - {"expiresSoon", ExpiresSoon(now)}, - {"expiresAt", to_json(ExpireTime())}, - {"ready", IsReady()}, - {"txRateCurrent", m_LastTXRate}, - {"rxRateCurrent", m_LastRXRate}, - {"replayTX", m_UpstreamReplayFilter.Size()}, - {"replayRX", m_DownstreamReplayFilter.Size()}, - {"hasExit", SupportsAnyRoles(ePathRoleExit)}}; - - std::vector hopsObj; - std::transform( - hops.begin(), - hops.end(), - std::back_inserter(hopsObj), - [](const auto& hop) -> util::StatusObject { return hop.ExtractStatus(); }); - obj["hops"] = hopsObj; - - switch (_status) + else if (currentStatus & LR_StatusRecord::FAIL_DECRYPT_ERROR) { - case ePathBuilding: - obj["status"] = "building"; - break; - case ePathEstablished: - obj["status"] = "established"; - break; - case ePathTimeout: - obj["status"] = "timeout"; - break; - case ePathExpired: - obj["status"] = "expired"; - break; - case ePathFailed: - obj["status"] = "failed"; - break; - case ePathIgnore: - obj["status"] = "ignored"; - break; - default: - obj["status"] = "unknown"; - break; + llarp::LogDebug( + "Path build failed due to a decrypt error in the build status " + "message"); } - return obj; - } - - void - Path::Rebuild() - { - if (auto parent = m_PathSet.lock()) + else { - std::vector newHops; - for (const auto& hop : hops) - newHops.emplace_back(hop.rc); - LogInfo(Name(), " rebuilding on ", ShortName()); - parent->Build(newHops); + llarp::LogDebug("Path build failed for an unspecified reason"); } + RouterID edge{}; + if (failedAt) + edge = *failedAt; + r->loop()->call([r, self = shared_from_this(), edge]() { + self->EnterState(ePathFailed, r->Now()); + if (auto parent = self->m_PathSet.lock()) + { + parent->HandlePathBuildFailedAt(self, edge); + } + }); } - bool - Path::SendLatencyMessage(AbstractRouter* r) + // TODO: meaningful return value? + return true; + } // namespace path + + void + Path::EnterState(PathStatus st, llarp_time_t now) + { + if (st == ePathFailed) { - const auto now = r->Now(); - // send path latency test - routing::PathLatencyMessage latency{}; - latency.T = randint(); - latency.S = NextSeqNo(); - m_LastLatencyTestID = latency.T; - m_LastLatencyTestTime = now; - LogDebug(Name(), " send latency test id=", latency.T); - if (not SendRoutingMessage(latency, r)) - return false; - FlushUpstream(r); - return true; + _status = st; + return; } - - void - Path::Tick(llarp_time_t now, AbstractRouter* r) + if (st == ePathExpired && _status == ePathBuilding) { - if (Expired(now)) - return; - - m_LastRXRate = m_RXRate; - m_LastTXRate = m_TXRate; - - m_RXRate = 0; - m_TXRate = 0; - - if (_status == ePathBuilding) - { - if (buildStarted == 0s) - return; - if (now >= buildStarted) - { - const auto dlt = now - buildStarted; - if (dlt >= path::build_timeout) - { - LogWarn(Name(), " waited for ", ToString(dlt), " and no path was built"); - r->routerProfiling().MarkPathFail(this); - EnterState(ePathExpired, now); - return; - } - } - } - // check to see if this path is dead - if (_status == ePathEstablished) - { - auto dlt = now - m_LastLatencyTestTime; - if (dlt > path::latency_interval && m_LastLatencyTestID == 0) - { - SendLatencyMessage(r); - // latency test FEC - r->loop()->call_later(2s, [self = shared_from_this(), r]() { - if (self->m_LastLatencyTestID) - self->SendLatencyMessage(r); - }); - return; - } - dlt = now - m_LastRecvMessage; - if (dlt >= path::alive_timeout) - { - LogWarn(Name(), " waited for ", ToString(dlt), " and path looks dead"); - r->routerProfiling().MarkPathFail(this); - EnterState(ePathTimeout, now); - } - } - if (_status == ePathIgnore and now - m_LastRecvMessage >= path::alive_timeout) + _status = st; + if (auto parent = m_PathSet.lock()) { - // clean up this path as we dont use it anymore - EnterState(ePathExpired, now); + parent->HandlePathBuildTimeout(shared_from_this()); } } - - void - Path::HandleAllUpstream(std::vector msgs, AbstractRouter* r) + else if (st == ePathBuilding) { - for (const auto& msg : msgs) - { - if (r->SendToOrQueue(Upstream(), msg)) - { - m_TXRate += msg.X.size(); - } - else - { - LogDebug("failed to send upstream to ", Upstream()); - } - } - r->TriggerPump(); + LogInfo("path ", Name(), " is building"); + buildStarted = now; } - - void - Path::UpstreamWork(TrafficQueue_t msgs, AbstractRouter* r) + else if (st == ePathEstablished && _status == ePathBuilding) { - std::vector sendmsgs(msgs.size()); - size_t idx = 0; - for (auto& ev : msgs) - { - const llarp_buffer_t buf(ev.first); - TunnelNonce n = ev.second; - for (const auto& hop : hops) - { - CryptoManager::instance()->xchacha20(buf, hop.shared, n); - n ^= hop.nonceXOR; - } - auto& msg = sendmsgs[idx]; - msg.X = buf; - msg.Y = ev.second; - msg.pathid = TXID(); - ++idx; - } - r->loop()->call([self = shared_from_this(), data = std::move(sendmsgs), r]() mutable { - self->HandleAllUpstream(std::move(data), r); - }); + LogInfo("path ", Name(), " is built, took ", ToString(now - buildStarted)); } - - void - Path::FlushUpstream(AbstractRouter* r) + else if (st == ePathTimeout && _status == ePathEstablished) { - if (not m_UpstreamQueue.empty()) + LogInfo("path ", Name(), " died"); + _status = st; + if (auto parent = m_PathSet.lock()) { - r->QueueWork([self = shared_from_this(), - data = std::exchange(m_UpstreamQueue, {}), - r]() mutable { self->UpstreamWork(std::move(data), r); }); + parent->HandlePathDied(shared_from_this()); } } - - void - Path::FlushDownstream(AbstractRouter* r) + else if (st == ePathEstablished && _status == ePathTimeout) { - if (not m_DownstreamQueue.empty()) - { - r->QueueWork([self = shared_from_this(), - data = std::exchange(m_DownstreamQueue, {}), - r]() mutable { self->DownstreamWork(std::move(data), r); }); - } + LogInfo("path ", Name(), " reanimated"); } - - /// how long we wait for a path to become active again after it times out - constexpr auto PathReanimationTimeout = 45s; - - bool - Path::Expired(llarp_time_t now) const + else if (st == ePathIgnore) { - if (_status == ePathFailed) - return true; - if (_status == ePathBuilding) - return false; - if (_status == ePathTimeout) - { - return now >= m_LastRecvMessage + PathReanimationTimeout; - } - if (_status == ePathEstablished or _status == ePathIgnore) - { - return now >= ExpireTime(); - } - return true; + LogInfo("path ", Name(), " ignored"); } + _status = st; + } - std::string - Path::Name() const + util::StatusObject + PathHopConfig::ExtractStatus() const + { + const auto ip = net::In6ToHUInt(rc.addrs[0].ip); + util::StatusObject obj{ + {"ip", ip.ToString()}, + {"lifetime", to_json(lifetime)}, + {"router", rc.pubkey.ToHex()}, + {"txid", txID.ToHex()}, + {"rxid", rxID.ToHex()}}; + return obj; + } + + util::StatusObject + Path::ExtractStatus() const + { + auto now = llarp::time_now_ms(); + + util::StatusObject obj{ + {"intro", intro.ExtractStatus()}, + {"lastRecvMsg", to_json(m_LastRecvMessage)}, + {"lastLatencyTest", to_json(m_LastLatencyTestTime)}, + {"buildStarted", to_json(buildStarted)}, + {"expired", Expired(now)}, + {"expiresSoon", ExpiresSoon(now)}, + {"expiresAt", to_json(ExpireTime())}, + {"ready", IsReady()}, + {"txRateCurrent", m_LastTXRate}, + {"rxRateCurrent", m_LastRXRate}, + {"replayTX", m_UpstreamReplayFilter.Size()}, + {"replayRX", m_DownstreamReplayFilter.Size()}, + {"hasExit", SupportsAnyRoles(ePathRoleExit)}}; + + std::vector hopsObj; + std::transform( + hops.begin(), + hops.end(), + std::back_inserter(hopsObj), + [](const auto& hop) -> util::StatusObject { return hop.ExtractStatus(); }); + obj["hops"] = hopsObj; + + switch (_status) + { + case ePathBuilding: + obj["status"] = "building"; + break; + case ePathEstablished: + obj["status"] = "established"; + break; + case ePathTimeout: + obj["status"] = "timeout"; + break; + case ePathExpired: + obj["status"] = "expired"; + break; + case ePathFailed: + obj["status"] = "failed"; + break; + case ePathIgnore: + obj["status"] = "ignored"; + break; + default: + obj["status"] = "unknown"; + break; + } + return obj; + } + + void + Path::Rebuild() + { + if (auto parent = m_PathSet.lock()) { - return fmt::format("TX={} RX={}", TXID(), RXID()); + std::vector newHops; + for (const auto& hop : hops) + newHops.emplace_back(hop.rc); + LogInfo(Name(), " rebuilding on ", ShortName()); + parent->Build(newHops); } + } + + bool + Path::SendLatencyMessage(AbstractRouter* r) + { + const auto now = r->Now(); + // send path latency test + routing::PathLatencyMessage latency{}; + latency.T = randint(); + latency.S = NextSeqNo(); + m_LastLatencyTestID = latency.T; + m_LastLatencyTestTime = now; + LogDebug(Name(), " send latency test id=", latency.T); + if (not SendRoutingMessage(latency, r)) + return false; + FlushUpstream(r); + return true; + } + + void + Path::Tick(llarp_time_t now, AbstractRouter* r) + { + if (Expired(now)) + return; - void - Path::DownstreamWork(TrafficQueue_t msgs, AbstractRouter* r) + m_LastRXRate = m_RXRate; + m_LastTXRate = m_TXRate; + + m_RXRate = 0; + m_TXRate = 0; + + if (_status == ePathBuilding) { - std::vector sendMsgs(msgs.size()); - size_t idx = 0; - for (auto& ev : msgs) + if (buildStarted == 0s) + return; + if (now >= buildStarted) { - const llarp_buffer_t buf(ev.first); - sendMsgs[idx].Y = ev.second; - for (const auto& hop : hops) + const auto dlt = now - buildStarted; + if (dlt >= path::build_timeout) { - sendMsgs[idx].Y ^= hop.nonceXOR; - CryptoManager::instance()->xchacha20(buf, hop.shared, sendMsgs[idx].Y); + LogWarn(Name(), " waited for ", ToString(dlt), " and no path was built"); + r->routerProfiling().MarkPathFail(this); + EnterState(ePathExpired, now); + return; } - sendMsgs[idx].X = buf; - ++idx; } - r->loop()->call([self = shared_from_this(), msgs = std::move(sendMsgs), r]() mutable { - self->HandleAllDownstream(std::move(msgs), r); - }); } - - void - Path::HandleAllDownstream(std::vector msgs, AbstractRouter* r) + // check to see if this path is dead + if (_status == ePathEstablished) { - for (const auto& msg : msgs) + auto dlt = now - m_LastLatencyTestTime; + if (dlt > path::latency_interval && m_LastLatencyTestID == 0) { - const llarp_buffer_t buf{msg.X}; - m_RXRate += buf.sz; - if (HandleRoutingMessage(buf, r)) - { - r->TriggerPump(); - m_LastRecvMessage = r->Now(); - } + SendLatencyMessage(r); + // latency test FEC + r->loop()->call_later(2s, [self = shared_from_this(), r]() { + if (self->m_LastLatencyTestID) + self->SendLatencyMessage(r); + }); + return; } - } - - bool - Path::HandleRoutingMessage(const llarp_buffer_t& buf, AbstractRouter* r) - { - if (!r->ParseRoutingMessageBuffer(buf, this, RXID())) + dlt = now - m_LastRecvMessage; + if (dlt >= path::alive_timeout) { - LogWarn("Failed to parse inbound routing message"); - return false; + LogWarn(Name(), " waited for ", ToString(dlt), " and path looks dead"); + r->routerProfiling().MarkPathFail(this); + EnterState(ePathTimeout, now); } - return true; } + if (_status == ePathIgnore and now - m_LastRecvMessage >= path::alive_timeout) + { + // clean up this path as we dont use it anymore + EnterState(ePathExpired, now); + } + } - bool - Path::HandleUpdateExitVerifyMessage( - const routing::UpdateExitVerifyMessage& msg, AbstractRouter* r) + void + Path::HandleAllUpstream(std::vector msgs, AbstractRouter* r) + { + for (const auto& msg : msgs) { - (void)r; - if (m_UpdateExitTX && msg.T == m_UpdateExitTX) + if (r->SendToOrQueue(Upstream(), msg)) { - if (m_ExitUpdated) - return m_ExitUpdated(shared_from_this()); + m_TXRate += msg.enc.size(); } - if (m_CloseExitTX && msg.T == m_CloseExitTX) + else { - if (m_ExitClosed) - return m_ExitClosed(shared_from_this()); + LogDebug("failed to send upstream to ", Upstream()); } - return false; } + r->TriggerPump(); + } - bool - Path::SendRoutingMessage(const routing::IMessage& msg, AbstractRouter* r) + void + Path::UpstreamWork(TrafficQueue_t msgs, AbstractRouter* r) + { + std::vector sendmsgs(msgs.size()); + size_t idx = 0; + for (auto& ev : msgs) { - std::array tmp; - llarp_buffer_t buf(tmp); - // should help prevent bad paths with uninitialized members - // FIXME: Why would we get uninitialized IMessages? - if (msg.version != llarp::constants::proto_version) - return false; - if (!msg.BEncode(&buf)) - { - LogError("Bencode failed"); - DumpBuffer(buf); - return false; - } - // make nonce - TunnelNonce N; - N.Randomize(); - buf.sz = buf.cur - buf.base; - // pad smaller messages - if (buf.sz < pad_size) + const llarp_buffer_t buf(ev.first); + TunnelNonce n = ev.second; + for (const auto& hop : hops) { - // randomize padding - CryptoManager::instance()->randbytes(buf.cur, pad_size - buf.sz); - buf.sz = pad_size; + CryptoManager::instance()->xchacha20(buf, hop.shared, n); + n ^= hop.nonceXOR; } - buf.cur = buf.base; - LogDebug("send routing message ", msg.S, " with ", buf.sz, " bytes to endpoint ", Endpoint()); - return HandleUpstream(buf, N, r); + auto& msg = sendmsgs[idx]; + msg.enc = buf; + msg.nonce = ev.second; + msg.pathid = TXID(); + ++idx; } + r->loop()->call([self = shared_from_this(), data = std::move(sendmsgs), r]() mutable { + self->HandleAllUpstream(std::move(data), r); + }); + } - bool - Path::HandlePathTransferMessage( - const routing::PathTransferMessage& /*msg*/, AbstractRouter* /*r*/) + void + Path::FlushUpstream(AbstractRouter* r) + { + if (not m_UpstreamQueue.empty()) { - LogWarn("unwarranted path transfer message on tx=", TXID(), " rx=", RXID()); - return false; + r->QueueWork([self = shared_from_this(), + data = std::exchange(m_UpstreamQueue, {}), + r]() mutable { self->UpstreamWork(std::move(data), r); }); } + } - bool - Path::HandleDataDiscardMessage(const routing::DataDiscardMessage& msg, AbstractRouter* r) + void + Path::FlushDownstream(AbstractRouter* r) + { + if (not m_DownstreamQueue.empty()) { - MarkActive(r->Now()); - if (m_DropHandler) - return m_DropHandler(shared_from_this(), msg.P, msg.S); - return true; + r->QueueWork([self = shared_from_this(), + data = std::exchange(m_DownstreamQueue, {}), + r]() mutable { self->DownstreamWork(std::move(data), r); }); } + } - bool - Path::HandlePathConfirmMessage(AbstractRouter* r) - { - LogDebug("Path Build Confirm, path: ", ShortName()); - const auto now = llarp::time_now_ms(); - if (_status == ePathBuilding) - { - // finish initializing introduction - intro.expiresAt = buildStarted + hops[0].lifetime; - - r->routerProfiling().MarkPathSuccess(this); + /// how long we wait for a path to become active again after it times out + constexpr auto PathReanimationTimeout = 45s; - // persist session with upstream router until the path is done - r->PersistSessionUntil(Upstream(), intro.expiresAt); - MarkActive(now); - return SendLatencyMessage(r); - } - LogWarn("got unwarranted path confirm message on tx=", RXID(), " rx=", RXID()); + bool + Path::Expired(llarp_time_t now) const + { + if (_status == ePathFailed) + return true; + if (_status == ePathBuilding) return false; + if (_status == ePathTimeout) + { + return now >= m_LastRecvMessage + PathReanimationTimeout; } - - bool - Path::HandlePathConfirmMessage(const routing::PathConfirmMessage& /*msg*/, AbstractRouter* r) + if (_status == ePathEstablished or _status == ePathIgnore) { - return HandlePathConfirmMessage(r); + return now >= ExpireTime(); } + return true; + } - bool - Path::HandleHiddenServiceFrame(const service::ProtocolFrame& frame) + std::string + Path::Name() const + { + return fmt::format("TX={} RX={}", TXID(), RXID()); + } + + void + Path::DownstreamWork(TrafficQueue_t msgs, AbstractRouter* r) + { + std::vector sendMsgs(msgs.size()); + size_t idx = 0; + for (auto& ev : msgs) { - if (auto parent = m_PathSet.lock()) + const llarp_buffer_t buf(ev.first); + sendMsgs[idx].nonce = ev.second; + for (const auto& hop : hops) { - MarkActive(parent->Now()); - return m_DataHandler && m_DataHandler(shared_from_this(), frame); + sendMsgs[idx].nonce ^= hop.nonceXOR; + CryptoManager::instance()->xchacha20(buf, hop.shared, sendMsgs[idx].nonce); } - return false; - } - - template - static llarp_time_t - computeLatency(const Samples_t& samps) - { - llarp_time_t mean = 0s; - if (samps.empty()) - return mean; - for (const auto& samp : samps) - mean += samp; - return mean / samps.size(); + sendMsgs[idx].enc = buf; + ++idx; } + r->loop()->call([self = shared_from_this(), msgs = std::move(sendMsgs), r]() mutable { + self->HandleAllDownstream(std::move(msgs), r); + }); + } - constexpr auto MaxLatencySamples = 8; - - bool - Path::HandlePathLatencyMessage(const routing::PathLatencyMessage&, AbstractRouter* r) + void + Path::HandleAllDownstream(std::vector msgs, AbstractRouter* r) + { + for (const auto& msg : msgs) { - const auto now = r->Now(); - MarkActive(now); - if (m_LastLatencyTestID) + const llarp_buffer_t buf{msg.enc}; + m_RXRate += buf.sz; + if (HandleRoutingMessage(buf, r)) { - m_LatencySamples.emplace_back(now - m_LastLatencyTestTime); - - while (m_LatencySamples.size() > MaxLatencySamples) - m_LatencySamples.pop_front(); - - intro.latency = computeLatency(m_LatencySamples); - m_LastLatencyTestID = 0; - EnterState(ePathEstablished, now); - if (m_BuiltHook) - m_BuiltHook(shared_from_this()); - m_BuiltHook = nullptr; + r->TriggerPump(); + m_LastRecvMessage = r->Now(); } - return true; } + } - /// this is the Client's side of handling a DHT message. it's handled - /// in-place. - bool - Path::HandleDHTMessage(const dht::IMessage& msg, AbstractRouter* r) + bool + Path::HandleRoutingMessage(const llarp_buffer_t& buf, AbstractRouter* r) + { + if (!r->ParseRoutingMessageBuffer(buf, this, RXID())) { - MarkActive(r->Now()); - routing::DHTMessage reply; - if (!msg.HandleMessage(r->dht(), reply.M)) - return false; - if (reply.M.size()) - return SendRoutingMessage(reply, r); - return true; + LogWarn("Failed to parse inbound routing message"); + return false; } + return true; + } - bool - Path::HandleCloseExitMessage(const routing::CloseExitMessage& msg, AbstractRouter* /*r*/) + bool + Path::HandleUpdateExitVerifyMessage( + const routing::UpdateExitVerifyMessage& msg, AbstractRouter* r) + { + (void)r; + if (m_UpdateExitTX && msg.T == m_UpdateExitTX) { - /// allows exits to close from their end - if (SupportsAnyRoles(ePathRoleExit | ePathRoleSVC)) - { - if (msg.Verify(EndpointPubKey())) - { - LogInfo(Name(), " had its exit closed"); - _role &= ~ePathRoleExit; - return true; - } + if (m_ExitUpdated) + return m_ExitUpdated(shared_from_this()); + } + if (m_CloseExitTX && msg.T == m_CloseExitTX) + { + if (m_ExitClosed) + return m_ExitClosed(shared_from_this()); + } + return false; + } - LogError(Name(), " CXM from exit with bad signature"); - } - else - LogError(Name(), " unwarranted CXM"); + bool + Path::SendRoutingMessage(const routing::AbstractRoutingMessage& msg, AbstractRouter* r) + { + std::array tmp; + llarp_buffer_t buf(tmp); + // should help prevent bad paths with uninitialized members + // FIXME: Why would we get uninitialized IMessages? + if (msg.version != llarp::constants::proto_version) + return false; + if (!msg.BEncode(&buf)) + { + LogError("Bencode failed"); + DumpBuffer(buf); return false; } + // make nonce + TunnelNonce N; + N.Randomize(); + buf.sz = buf.cur - buf.base; + // pad smaller messages + if (buf.sz < pad_size) + { + // randomize padding + CryptoManager::instance()->randbytes(buf.cur, pad_size - buf.sz); + buf.sz = pad_size; + } + buf.cur = buf.base; + LogDebug("send routing message ", msg.S, " with ", buf.sz, " bytes to endpoint ", Endpoint()); + return HandleUpstream(buf, N, r); + } + + bool + Path::HandlePathTransferMessage( + const routing::PathTransferMessage& /*msg*/, AbstractRouter* /*r*/) + { + LogWarn("unwarranted path transfer message on tx=", TXID(), " rx=", RXID()); + return false; + } - bool - Path::SendExitRequest(const routing::ObtainExitMessage& msg, AbstractRouter* r) + bool + Path::HandleDataDiscardMessage(const routing::DataDiscardMessage& msg, AbstractRouter* r) + { + MarkActive(r->Now()); + if (m_DropHandler) + return m_DropHandler(shared_from_this(), msg.P, msg.S); + return true; + } + + bool + Path::HandlePathConfirmMessage(AbstractRouter* r) + { + LogDebug("Path Build Confirm, path: ", ShortName()); + const auto now = llarp::time_now_ms(); + if (_status == ePathBuilding) { - LogInfo(Name(), " sending exit request to ", Endpoint()); - m_ExitObtainTX = msg.T; - return SendRoutingMessage(msg, r); + // finish initializing introduction + intro.expiresAt = buildStarted + hops[0].lifetime; + + r->routerProfiling().MarkPathSuccess(this); + + // persist session with upstream router until the path is done + r->PersistSessionUntil(Upstream(), intro.expiresAt); + MarkActive(now); + return SendLatencyMessage(r); } + LogWarn("got unwarranted path confirm message on tx=", RXID(), " rx=", RXID()); + return false; + } - bool - Path::SendExitClose(const routing::CloseExitMessage& msg, AbstractRouter* r) + bool + Path::HandlePathConfirmMessage(const routing::PathConfirmMessage& /*msg*/, AbstractRouter* r) + { + return HandlePathConfirmMessage(r); + } + + bool + Path::HandleHiddenServiceFrame(const service::ProtocolFrame& frame) + { + if (auto parent = m_PathSet.lock()) { - LogInfo(Name(), " closing exit to ", Endpoint()); - // mark as not exit anymore - _role &= ~ePathRoleExit; - return SendRoutingMessage(msg, r); + MarkActive(parent->Now()); + return m_DataHandler && m_DataHandler(shared_from_this(), frame); } + return false; + } - bool - Path::HandleObtainExitMessage(const routing::ObtainExitMessage& msg, AbstractRouter* r) + template + static llarp_time_t + computeLatency(const Samples_t& samps) + { + llarp_time_t mean = 0s; + if (samps.empty()) + return mean; + for (const auto& samp : samps) + mean += samp; + return mean / samps.size(); + } + + constexpr auto MaxLatencySamples = 8; + + bool + Path::HandlePathLatencyMessage(const routing::PathLatencyMessage&, AbstractRouter* r) + { + const auto now = r->Now(); + MarkActive(now); + if (m_LastLatencyTestID) { - (void)msg; - (void)r; - LogError(Name(), " got unwarranted OXM"); - return false; + m_LatencySamples.emplace_back(now - m_LastLatencyTestTime); + + while (m_LatencySamples.size() > MaxLatencySamples) + m_LatencySamples.pop_front(); + + intro.latency = computeLatency(m_LatencySamples); + m_LastLatencyTestID = 0; + EnterState(ePathEstablished, now); + if (m_BuiltHook) + m_BuiltHook(shared_from_this()); + m_BuiltHook = nullptr; } + return true; + } - bool - Path::HandleUpdateExitMessage(const routing::UpdateExitMessage& msg, AbstractRouter* r) - { - (void)msg; - (void)r; - LogError(Name(), " got unwarranted UXM"); + /// this is the Client's side of handling a DHT message. it's handled + /// in-place. + bool + Path::HandleDHTMessage(const dht::AbstractDHTMessage& msg, AbstractRouter* r) + { + MarkActive(r->Now()); + routing::DHTMessage reply; + if (!msg.handle_message(r->dht(), reply.M)) return false; - } + if (reply.M.size()) + return SendRoutingMessage(reply, r); + return true; + } - bool - Path::HandleRejectExitMessage(const routing::RejectExitMessage& msg, AbstractRouter* r) + bool + Path::HandleCloseExitMessage(const routing::CloseExitMessage& msg, AbstractRouter* /*r*/) + { + /// allows exits to close from their end + if (SupportsAnyRoles(ePathRoleExit | ePathRoleSVC)) { - if (m_ExitObtainTX && msg.T == m_ExitObtainTX) + if (msg.Verify(EndpointPubKey())) { - if (!msg.Verify(EndpointPubKey())) - { - LogError(Name(), "RXM invalid signature"); - return false; - } - LogInfo(Name(), " ", Endpoint(), " Rejected exit"); - MarkActive(r->Now()); - return InformExitResult(llarp_time_t(msg.B)); + LogInfo(Name(), " had its exit closed"); + _role &= ~ePathRoleExit; + return true; } - LogError(Name(), " got unwarranted RXM"); - return false; + + LogError(Name(), " CXM from exit with bad signature"); } + else + LogError(Name(), " unwarranted CXM"); + return false; + } + + bool + Path::SendExitRequest(const routing::ObtainExitMessage& msg, AbstractRouter* r) + { + LogInfo(Name(), " sending exit request to ", Endpoint()); + m_ExitObtainTX = msg.T; + return SendRoutingMessage(msg, r); + } - bool - Path::HandleGrantExitMessage(const routing::GrantExitMessage& msg, AbstractRouter* r) + bool + Path::SendExitClose(const routing::CloseExitMessage& msg, AbstractRouter* r) + { + LogInfo(Name(), " closing exit to ", Endpoint()); + // mark as not exit anymore + _role &= ~ePathRoleExit; + return SendRoutingMessage(msg, r); + } + + bool + Path::HandleObtainExitMessage(const routing::ObtainExitMessage& msg, AbstractRouter* r) + { + (void)msg; + (void)r; + LogError(Name(), " got unwarranted OXM"); + return false; + } + + bool + Path::HandleUpdateExitMessage(const routing::UpdateExitMessage& msg, AbstractRouter* r) + { + (void)msg; + (void)r; + LogError(Name(), " got unwarranted UXM"); + return false; + } + + bool + Path::HandleRejectExitMessage(const routing::RejectExitMessage& msg, AbstractRouter* r) + { + if (m_ExitObtainTX && msg.T == m_ExitObtainTX) { - if (m_ExitObtainTX && msg.T == m_ExitObtainTX) + if (!msg.Verify(EndpointPubKey())) { - if (!msg.Verify(EndpointPubKey())) - { - LogError(Name(), " GXM signature failed"); - return false; - } - // we now can send exit traffic - _role |= ePathRoleExit; - LogInfo(Name(), " ", Endpoint(), " Granted exit"); - MarkActive(r->Now()); - return InformExitResult(0s); + LogError(Name(), "RXM invalid signature"); + return false; } - LogError(Name(), " got unwarranted GXM"); - return false; + LogInfo(Name(), " ", Endpoint(), " Rejected exit"); + MarkActive(r->Now()); + return InformExitResult(llarp_time_t(msg.B)); } + LogError(Name(), " got unwarranted RXM"); + return false; + } - bool - Path::InformExitResult(llarp_time_t B) + bool + Path::HandleGrantExitMessage(const routing::GrantExitMessage& msg, AbstractRouter* r) + { + if (m_ExitObtainTX && msg.T == m_ExitObtainTX) { - auto self = shared_from_this(); - bool result = true; - for (const auto& hook : m_ObtainedExitHooks) - result = hook(self, B) and result; - m_ObtainedExitHooks.clear(); - return result; + if (!msg.Verify(EndpointPubKey())) + { + LogError(Name(), " GXM signature failed"); + return false; + } + // we now can send exit traffic + _role |= ePathRoleExit; + LogInfo(Name(), " ", Endpoint(), " Granted exit"); + MarkActive(r->Now()); + return InformExitResult(0s); } + LogError(Name(), " got unwarranted GXM"); + return false; + } - bool - Path::HandleTransferTrafficMessage( - const routing::TransferTrafficMessage& msg, AbstractRouter* r) + bool + Path::InformExitResult(llarp_time_t B) + { + auto self = shared_from_this(); + bool result = true; + for (const auto& hook : m_ObtainedExitHooks) + result = hook(self, B) and result; + m_ObtainedExitHooks.clear(); + return result; + } + + bool + Path::HandleTransferTrafficMessage(const routing::TransferTrafficMessage& msg, AbstractRouter* r) + { + // check if we can handle exit data + if (!SupportsAnyRoles(ePathRoleExit | ePathRoleSVC)) + return false; + // handle traffic if we have a handler + if (!m_ExitTrafficHandler) + return false; + bool sent = msg.X.size() > 0; + auto self = shared_from_this(); + for (const auto& pkt : msg.X) { - // check if we can handle exit data - if (!SupportsAnyRoles(ePathRoleExit | ePathRoleSVC)) - return false; - // handle traffic if we have a handler - if (!m_ExitTrafficHandler) - return false; - bool sent = msg.X.size() > 0; - auto self = shared_from_this(); - for (const auto& pkt : msg.X) + if (pkt.size() <= 8) + continue; + auto counter = oxenc::load_big_to_host(pkt.data()); + if (m_ExitTrafficHandler( + self, llarp_buffer_t(pkt.data() + 8, pkt.size() - 8), counter, msg.protocol)) { - if (pkt.size() <= 8) - continue; - auto counter = oxenc::load_big_to_host(pkt.data()); - if (m_ExitTrafficHandler( - self, llarp_buffer_t(pkt.data() + 8, pkt.size() - 8), counter, msg.protocol)) - { - MarkActive(r->Now()); - EnterState(ePathEstablished, r->Now()); - } + MarkActive(r->Now()); + EnterState(ePathEstablished, r->Now()); } - return sent; } + return sent; + } - } // namespace path -} // namespace llarp +} // namespace llarp::path diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index d1396b8f2c..c2a5407aa4 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -70,7 +70,7 @@ namespace llarp /// A path we made struct Path final : public IHopHandler, - public routing::IMessageHandler, + public routing::AbstractRoutingMessageHandler, public std::enable_shared_from_this { using BuildResultHookFunc = std::function; @@ -291,7 +291,7 @@ namespace llarp Tick(llarp_time_t now, AbstractRouter* r); bool - SendRoutingMessage(const routing::IMessage& msg, AbstractRouter* r) override; + SendRoutingMessage(const routing::AbstractRoutingMessage& msg, AbstractRouter* r) override; bool HandleObtainExitMessage(const routing::ObtainExitMessage& msg, AbstractRouter* r) override; @@ -337,7 +337,7 @@ namespace llarp HandleGotIntroMessage(const dht::GotIntroMessage& msg); bool - HandleDHTMessage(const dht::IMessage& msg, AbstractRouter* r) override; + HandleDHTMessage(const dht::AbstractDHTMessage& msg, AbstractRouter* r) override; bool HandleRoutingMessage(const llarp_buffer_t& buf, AbstractRouter* r); diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index 1710b9d335..63fe3f87b4 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -238,7 +238,7 @@ namespace llarp { std::optional found = std::nullopt; m_router->ForEachPeer( - [&](const ILinkSession* s, bool isOutbound) { + [&](const AbstractLinkSession* s, bool isOutbound) { if (s && s->IsEstablished() && isOutbound && not found.has_value()) { const RouterContact rc = s->GetRemoteRC(); diff --git a/llarp/path/pathset.hpp b/llarp/path/pathset.hpp index f7fe5690ea..cbaeb52f21 100644 --- a/llarp/path/pathset.hpp +++ b/llarp/path/pathset.hpp @@ -230,7 +230,7 @@ namespace llarp return false; } - virtual routing::IMessageHandler* + virtual routing::AbstractRoutingMessageHandler* GetDHTHandler() { return nullptr; diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index ff912aae09..b1164f8776 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -17,444 +17,434 @@ #include -namespace llarp +namespace llarp::path { - namespace path + std::string + TransitHopInfo::ToString() const { - std::string - TransitHopInfo::ToString() const - { - return fmt::format( - "[TransitHopInfo tx={} rx={} upstream={} downstream={}]", - txID, - rxID, - upstream, - downstream); - } - - TransitHop::TransitHop() - : IHopHandler{} - , m_UpstreamGather{transit_hop_queue_size} - , m_DownstreamGather{transit_hop_queue_size} - { - m_UpstreamGather.enable(); - m_DownstreamGather.enable(); - m_UpstreamWorkCounter = 0; - m_DownstreamWorkCounter = 0; - } + return fmt::format( + "[TransitHopInfo tx={} rx={} upstream={} downstream={}]", txID, rxID, upstream, downstream); + } + + TransitHop::TransitHop() + : IHopHandler{} + , m_UpstreamGather{transit_hop_queue_size} + , m_DownstreamGather{transit_hop_queue_size} + { + m_UpstreamGather.enable(); + m_DownstreamGather.enable(); + m_UpstreamWorkCounter = 0; + m_DownstreamWorkCounter = 0; + } + + bool + TransitHop::Expired(llarp_time_t now) const + { + return destroy || (now >= ExpireTime()); + } - bool - TransitHop::Expired(llarp_time_t now) const - { - return destroy || (now >= ExpireTime()); - } + llarp_time_t + TransitHop::ExpireTime() const + { + return started + lifetime; + } - llarp_time_t - TransitHop::ExpireTime() const - { - return started + lifetime; - } + bool + TransitHop::HandleLRSM(uint64_t status, std::array& frames, AbstractRouter* r) + { + auto msg = std::make_shared(frames); + msg->status = status; + msg->pathid = info.rxID; - bool - TransitHop::HandleLRSM( - uint64_t status, std::array& frames, AbstractRouter* r) - { - auto msg = std::make_shared(frames); - msg->status = status; - msg->pathid = info.rxID; + // TODO: add to IHopHandler some notion of "path status" - // TODO: add to IHopHandler some notion of "path status" + const uint64_t ourStatus = LR_StatusRecord::SUCCESS; - const uint64_t ourStatus = LR_StatusRecord::SUCCESS; + msg->AddFrame(pathKey, ourStatus); + LR_StatusMessage::QueueSendMessage(r, info.downstream, msg, shared_from_this()); + return true; + } - msg->AddFrame(pathKey, ourStatus); - LR_StatusMessage::QueueSendMessage(r, info.downstream, msg, shared_from_this()); - return true; - } + TransitHopInfo::TransitHopInfo(const RouterID& down, const LR_CommitRecord& record) + : txID(record.txid), rxID(record.rxid), upstream(record.nextHop), downstream(down) + {} - TransitHopInfo::TransitHopInfo(const RouterID& down, const LR_CommitRecord& record) - : txID(record.txid), rxID(record.rxid), upstream(record.nextHop), downstream(down) - {} + bool + TransitHop::SendRoutingMessage(const routing::AbstractRoutingMessage& msg, AbstractRouter* r) + { + if (!IsEndpoint(r->pubkey())) + return false; - bool - TransitHop::SendRoutingMessage(const routing::IMessage& msg, AbstractRouter* r) + std::array tmp; + llarp_buffer_t buf(tmp); + if (!msg.BEncode(&buf)) { - if (!IsEndpoint(r->pubkey())) - return false; + llarp::LogError("failed to encode routing message"); + return false; + } + TunnelNonce N; + N.Randomize(); + buf.sz = buf.cur - buf.base; + // pad to nearest MESSAGE_PAD_SIZE bytes + auto dlt = buf.sz % pad_size; + if (dlt) + { + dlt = pad_size - dlt; + // randomize padding + CryptoManager::instance()->randbytes(buf.cur, dlt); + buf.sz += dlt; + } + buf.cur = buf.base; + return HandleDownstream(buf, N, r); + } - std::array tmp; - llarp_buffer_t buf(tmp); - if (!msg.BEncode(&buf)) + void + TransitHop::DownstreamWork(TrafficQueue_t msgs, AbstractRouter* r) + { + auto flushIt = [self = shared_from_this(), r]() { + std::vector msgs; + while (auto maybe = self->m_DownstreamGather.tryPopFront()) { - llarp::LogError("failed to encode routing message"); - return false; + msgs.push_back(*maybe); } - TunnelNonce N; - N.Randomize(); - buf.sz = buf.cur - buf.base; - // pad to nearest MESSAGE_PAD_SIZE bytes - auto dlt = buf.sz % pad_size; - if (dlt) + self->HandleAllDownstream(std::move(msgs), r); + }; + for (auto& ev : msgs) + { + RelayDownstreamMessage msg; + const llarp_buffer_t buf(ev.first); + msg.pathid = info.rxID; + msg.nonce = ev.second ^ nonceXOR; + CryptoManager::instance()->xchacha20(buf, pathKey, ev.second); + msg.enc = buf; + llarp::LogDebug( + "relay ", + msg.enc.size(), + " bytes downstream from ", + info.upstream, + " to ", + info.downstream); + if (m_DownstreamGather.full()) { - dlt = pad_size - dlt; - // randomize padding - CryptoManager::instance()->randbytes(buf.cur, dlt); - buf.sz += dlt; + r->loop()->call(flushIt); } - buf.cur = buf.base; - return HandleDownstream(buf, N, r); + if (m_DownstreamGather.enabled()) + m_DownstreamGather.pushBack(msg); } + r->loop()->call(flushIt); + } - void - TransitHop::DownstreamWork(TrafficQueue_t msgs, AbstractRouter* r) + void + TransitHop::UpstreamWork(TrafficQueue_t msgs, AbstractRouter* r) + { + for (auto& ev : msgs) { - auto flushIt = [self = shared_from_this(), r]() { - std::vector msgs; - while (auto maybe = self->m_DownstreamGather.tryPopFront()) - { - msgs.push_back(*maybe); - } - self->HandleAllDownstream(std::move(msgs), r); - }; - for (auto& ev : msgs) - { - RelayDownstreamMessage msg; - const llarp_buffer_t buf(ev.first); - msg.pathid = info.rxID; - msg.Y = ev.second ^ nonceXOR; - CryptoManager::instance()->xchacha20(buf, pathKey, ev.second); - msg.X = buf; - llarp::LogDebug( - "relay ", - msg.X.size(), - " bytes downstream from ", - info.upstream, - " to ", - info.downstream); - if (m_DownstreamGather.full()) - { - r->loop()->call(flushIt); - } - if (m_DownstreamGather.enabled()) - m_DownstreamGather.pushBack(msg); - } - r->loop()->call(flushIt); + const llarp_buffer_t buf(ev.first); + RelayUpstreamMessage msg; + CryptoManager::instance()->xchacha20(buf, pathKey, ev.second); + msg.pathid = info.txID; + msg.nonce = ev.second ^ nonceXOR; + msg.enc = buf; + if (m_UpstreamGather.tryPushBack(msg) != thread::QueueReturn::Success) + break; } - void - TransitHop::UpstreamWork(TrafficQueue_t msgs, AbstractRouter* r) - { - for (auto& ev : msgs) + // Flush it: + r->loop()->call([self = shared_from_this(), r] { + std::vector msgs; + while (auto maybe = self->m_UpstreamGather.tryPopFront()) { - const llarp_buffer_t buf(ev.first); - RelayUpstreamMessage msg; - CryptoManager::instance()->xchacha20(buf, pathKey, ev.second); - msg.pathid = info.txID; - msg.Y = ev.second ^ nonceXOR; - msg.X = buf; - if (m_UpstreamGather.tryPushBack(msg) != thread::QueueReturn::Success) - break; + msgs.push_back(*maybe); } + self->HandleAllUpstream(std::move(msgs), r); + }); + } - // Flush it: - r->loop()->call([self = shared_from_this(), r] { - std::vector msgs; - while (auto maybe = self->m_UpstreamGather.tryPopFront()) - { - msgs.push_back(*maybe); - } - self->HandleAllUpstream(std::move(msgs), r); - }); - } - - void - TransitHop::HandleAllUpstream(std::vector msgs, AbstractRouter* r) + void + TransitHop::HandleAllUpstream(std::vector msgs, AbstractRouter* r) + { + if (IsEndpoint(r->pubkey())) { - if (IsEndpoint(r->pubkey())) + for (const auto& msg : msgs) { - for (const auto& msg : msgs) - { - const llarp_buffer_t buf(msg.X); - if (!r->ParseRoutingMessageBuffer(buf, this, info.rxID)) - { - LogWarn("invalid upstream data on endpoint ", info); - } - m_LastActivity = r->Now(); - } - FlushDownstream(r); - for (const auto& other : m_FlushOthers) + const llarp_buffer_t buf(msg.enc); + if (!r->ParseRoutingMessageBuffer(buf, this, info.rxID)) { - other->FlushDownstream(r); + LogWarn("invalid upstream data on endpoint ", info); } - m_FlushOthers.clear(); + m_LastActivity = r->Now(); } - else + FlushDownstream(r); + for (const auto& other : m_FlushOthers) { - for (const auto& msg : msgs) - { - llarp::LogDebug( - "relay ", - msg.X.size(), - " bytes upstream from ", - info.downstream, - " to ", - info.upstream); - r->SendToOrQueue(info.upstream, msg); - } + other->FlushDownstream(r); } - r->TriggerPump(); + m_FlushOthers.clear(); } - - void - TransitHop::HandleAllDownstream(std::vector msgs, AbstractRouter* r) + else { for (const auto& msg : msgs) { llarp::LogDebug( "relay ", - msg.X.size(), - " bytes downstream from ", - info.upstream, + msg.enc.size(), + " bytes upstream from ", + info.downstream, " to ", - info.downstream); - r->SendToOrQueue(info.downstream, msg); - } - r->TriggerPump(); - } - - void - TransitHop::FlushUpstream(AbstractRouter* r) - { - if (not m_UpstreamQueue.empty()) - { - r->QueueWork([self = shared_from_this(), - data = std::exchange(m_UpstreamQueue, {}), - r]() mutable { self->UpstreamWork(std::move(data), r); }); + info.upstream); + r->SendToOrQueue(info.upstream, msg); } } + r->TriggerPump(); + } - void - TransitHop::FlushDownstream(AbstractRouter* r) + void + TransitHop::HandleAllDownstream(std::vector msgs, AbstractRouter* r) + { + for (const auto& msg : msgs) { - if (not m_DownstreamQueue.empty()) - { - r->QueueWork([self = shared_from_this(), - data = std::exchange(m_DownstreamQueue, {}), - r]() mutable { self->DownstreamWork(std::move(data), r); }); - } + llarp::LogDebug( + "relay ", + msg.enc.size(), + " bytes downstream from ", + info.upstream, + " to ", + info.downstream); + r->SendToOrQueue(info.downstream, msg); } + r->TriggerPump(); + } - /// this is where a DHT message is handled at the end of a path, that is, - /// where a SNode receives a DHT message from a client along a path. - bool - TransitHop::HandleDHTMessage(const llarp::dht::IMessage& msg, AbstractRouter* r) + void + TransitHop::FlushUpstream(AbstractRouter* r) + { + if (not m_UpstreamQueue.empty()) { - return r->dht()->impl->RelayRequestForPath(info.rxID, msg); + r->QueueWork([self = shared_from_this(), + data = std::exchange(m_UpstreamQueue, {}), + r]() mutable { self->UpstreamWork(std::move(data), r); }); } + } - bool - TransitHop::HandlePathLatencyMessage( - const llarp::routing::PathLatencyMessage& msg, AbstractRouter* r) + void + TransitHop::FlushDownstream(AbstractRouter* r) + { + if (not m_DownstreamQueue.empty()) { - llarp::routing::PathLatencyMessage reply; - reply.L = msg.T; - reply.S = msg.S; - return SendRoutingMessage(reply, r); + r->QueueWork([self = shared_from_this(), + data = std::exchange(m_DownstreamQueue, {}), + r]() mutable { self->DownstreamWork(std::move(data), r); }); } + } - bool - TransitHop::HandlePathConfirmMessage( - [[maybe_unused]] const llarp::routing::PathConfirmMessage& msg, - [[maybe_unused]] AbstractRouter* r) - { - llarp::LogWarn("unwarranted path confirm message on ", info); - return false; - } + /// this is where a DHT message is handled at the end of a path, that is, + /// where a SNode receives a DHT message from a client along a path. + bool + TransitHop::HandleDHTMessage(const llarp::dht::AbstractDHTMessage& msg, AbstractRouter* r) + { + return r->dht()->impl->RelayRequestForPath(info.rxID, msg); + } - bool - TransitHop::HandleDataDiscardMessage( - [[maybe_unused]] const llarp::routing::DataDiscardMessage& msg, - [[maybe_unused]] AbstractRouter* r) - { - llarp::LogWarn("unwarranted path data discard message on ", info); - return false; - } + bool + TransitHop::HandlePathLatencyMessage( + const llarp::routing::PathLatencyMessage& msg, AbstractRouter* r) + { + llarp::routing::PathLatencyMessage reply; + reply.L = msg.T; + reply.S = msg.S; + return SendRoutingMessage(reply, r); + } + + bool + TransitHop::HandlePathConfirmMessage( + [[maybe_unused]] const llarp::routing::PathConfirmMessage& msg, + [[maybe_unused]] AbstractRouter* r) + { + llarp::LogWarn("unwarranted path confirm message on ", info); + return false; + } + + bool + TransitHop::HandleDataDiscardMessage( + [[maybe_unused]] const llarp::routing::DataDiscardMessage& msg, + [[maybe_unused]] AbstractRouter* r) + { + llarp::LogWarn("unwarranted path data discard message on ", info); + return false; + } - bool - TransitHop::HandleObtainExitMessage( - const llarp::routing::ObtainExitMessage& msg, AbstractRouter* r) + bool + TransitHop::HandleObtainExitMessage( + const llarp::routing::ObtainExitMessage& msg, AbstractRouter* r) + { + if (msg.Verify() && r->exitContext().ObtainNewExit(msg.I, info.rxID, msg.E != 0)) { - if (msg.Verify() && r->exitContext().ObtainNewExit(msg.I, info.rxID, msg.E != 0)) + llarp::routing::GrantExitMessage grant; + grant.S = NextSeqNo(); + grant.T = msg.T; + if (!grant.Sign(r->identity())) { - llarp::routing::GrantExitMessage grant; - grant.S = NextSeqNo(); - grant.T = msg.T; - if (!grant.Sign(r->identity())) - { - llarp::LogError("Failed to sign grant exit message"); - return false; - } - return SendRoutingMessage(grant, r); - } - // TODO: exponential backoff - // TODO: rejected policies - llarp::routing::RejectExitMessage reject; - reject.S = NextSeqNo(); - reject.T = msg.T; - if (!reject.Sign(r->identity())) - { - llarp::LogError("Failed to sign reject exit message"); + llarp::LogError("Failed to sign grant exit message"); return false; } - return SendRoutingMessage(reject, r); - } - - bool - TransitHop::HandleCloseExitMessage( - const llarp::routing::CloseExitMessage& msg, AbstractRouter* r) - { - const llarp::routing::DataDiscardMessage discard(info.rxID, msg.S); - auto ep = r->exitContext().FindEndpointForPath(info.rxID); - if (ep && msg.Verify(ep->PubKey())) - { - llarp::routing::CloseExitMessage reply; - reply.Y = msg.Y; - reply.S = NextSeqNo(); - if (reply.Sign(r->identity())) - { - if (SendRoutingMessage(reply, r)) - { - ep->Close(); - return true; - } - } - } - return SendRoutingMessage(discard, r); + return SendRoutingMessage(grant, r); } - - bool - TransitHop::HandleUpdateExitVerifyMessage( - const llarp::routing::UpdateExitVerifyMessage& msg, AbstractRouter* r) + // TODO: exponential backoff + // TODO: rejected policies + llarp::routing::RejectExitMessage reject; + reject.S = NextSeqNo(); + reject.T = msg.T; + if (!reject.Sign(r->identity())) { - (void)msg; - (void)r; - llarp::LogError("unwarranted exit verify on ", info); + llarp::LogError("Failed to sign reject exit message"); return false; } + return SendRoutingMessage(reject, r); + } - bool - TransitHop::HandleUpdateExitMessage( - const llarp::routing::UpdateExitMessage& msg, AbstractRouter* r) + bool + TransitHop::HandleCloseExitMessage(const llarp::routing::CloseExitMessage& msg, AbstractRouter* r) + { + const llarp::routing::DataDiscardMessage discard(info.rxID, msg.S); + auto ep = r->exitContext().FindEndpointForPath(info.rxID); + if (ep && msg.Verify(ep->PubKey())) { - auto ep = r->exitContext().FindEndpointForPath(msg.P); - if (ep) + llarp::routing::CloseExitMessage reply; + reply.Y = msg.Y; + reply.S = NextSeqNo(); + if (reply.Sign(r->identity())) { - if (!msg.Verify(ep->PubKey())) - return false; - - if (ep->UpdateLocalPath(info.rxID)) + if (SendRoutingMessage(reply, r)) { - llarp::routing::UpdateExitVerifyMessage reply; - reply.T = msg.T; - reply.S = NextSeqNo(); - return SendRoutingMessage(reply, r); + ep->Close(); + return true; } } - // on fail tell message was discarded - llarp::routing::DataDiscardMessage discard(info.rxID, msg.S); - return SendRoutingMessage(discard, r); } + return SendRoutingMessage(discard, r); + } - bool - TransitHop::HandleRejectExitMessage( - const llarp::routing::RejectExitMessage& msg, AbstractRouter* r) - { - (void)msg; - (void)r; - llarp::LogError(info, " got unwarranted RXM"); - return false; - } - - bool - TransitHop::HandleGrantExitMessage( - const llarp::routing::GrantExitMessage& msg, AbstractRouter* r) + bool + TransitHop::HandleUpdateExitVerifyMessage( + const llarp::routing::UpdateExitVerifyMessage& msg, AbstractRouter* r) + { + (void)msg; + (void)r; + llarp::LogError("unwarranted exit verify on ", info); + return false; + } + + bool + TransitHop::HandleUpdateExitMessage( + const llarp::routing::UpdateExitMessage& msg, AbstractRouter* r) + { + auto ep = r->exitContext().FindEndpointForPath(msg.P); + if (ep) { - (void)msg; - (void)r; - llarp::LogError(info, " got unwarranted GXM"); - return false; - } + if (!msg.Verify(ep->PubKey())) + return false; - bool - TransitHop::HandleTransferTrafficMessage( - const llarp::routing::TransferTrafficMessage& msg, AbstractRouter* r) - { - auto endpoint = r->exitContext().FindEndpointForPath(info.rxID); - if (endpoint) + if (ep->UpdateLocalPath(info.rxID)) { - bool sent = true; - for (const auto& pkt : msg.X) - { - // check short packet buffer - if (pkt.size() <= 8) - continue; - auto counter = oxenc::load_big_to_host(pkt.data()); - llarp_buffer_t buf{pkt.data() + 8, pkt.size() - 8}; - sent = - endpoint->QueueOutboundTraffic(info.rxID, buf.copy(), counter, msg.protocol) and sent; - } - return sent; + llarp::routing::UpdateExitVerifyMessage reply; + reply.T = msg.T; + reply.S = NextSeqNo(); + return SendRoutingMessage(reply, r); } - - llarp::LogError("No exit endpoint on ", info); - // discarded - llarp::routing::DataDiscardMessage discard(info.rxID, msg.S); - return SendRoutingMessage(discard, r); } - - bool - TransitHop::HandlePathTransferMessage( - const llarp::routing::PathTransferMessage& msg, AbstractRouter* r) + // on fail tell message was discarded + llarp::routing::DataDiscardMessage discard(info.rxID, msg.S); + return SendRoutingMessage(discard, r); + } + + bool + TransitHop::HandleRejectExitMessage( + const llarp::routing::RejectExitMessage& msg, AbstractRouter* r) + { + (void)msg; + (void)r; + llarp::LogError(info, " got unwarranted RXM"); + return false; + } + + bool + TransitHop::HandleGrantExitMessage(const llarp::routing::GrantExitMessage& msg, AbstractRouter* r) + { + (void)msg; + (void)r; + llarp::LogError(info, " got unwarranted GXM"); + return false; + } + + bool + TransitHop::HandleTransferTrafficMessage( + const llarp::routing::TransferTrafficMessage& msg, AbstractRouter* r) + { + auto endpoint = r->exitContext().FindEndpointForPath(info.rxID); + if (endpoint) { - auto path = r->pathContext().GetPathForTransfer(msg.P); - llarp::routing::DataDiscardMessage discarded{msg.P, msg.S}; - if (path == nullptr || msg.T.F != info.txID) + bool sent = true; + for (const auto& pkt : msg.X) { - return SendRoutingMessage(discarded, r); + // check short packet buffer + if (pkt.size() <= 8) + continue; + auto counter = oxenc::load_big_to_host(pkt.data()); + llarp_buffer_t buf{pkt.data() + 8, pkt.size() - 8}; + sent = + endpoint->QueueOutboundTraffic(info.rxID, buf.copy(), counter, msg.protocol) and sent; } - // send routing message - if (path->SendRoutingMessage(msg.T, r)) - { - m_FlushOthers.emplace(path); - return true; - } - return SendRoutingMessage(discarded, r); + return sent; } - std::string - TransitHop::ToString() const - { - return fmt::format( - "[TransitHop {} started={} lifetime={}", info, started.count(), lifetime.count()); - } + llarp::LogError("No exit endpoint on ", info); + // discarded + llarp::routing::DataDiscardMessage discard(info.rxID, msg.S); + return SendRoutingMessage(discard, r); + } - void - TransitHop::Stop() + bool + TransitHop::HandlePathTransferMessage( + const llarp::routing::PathTransferMessage& msg, AbstractRouter* r) + { + auto path = r->pathContext().GetPathForTransfer(msg.P); + llarp::routing::DataDiscardMessage discarded{msg.P, msg.S}; + if (path == nullptr || msg.T.F != info.txID) { - m_UpstreamGather.disable(); - m_DownstreamGather.disable(); + return SendRoutingMessage(discarded, r); } - - void - TransitHop::SetSelfDestruct() + // send routing message + if (path->SendRoutingMessage(msg.T, r)) { - destroy = true; + m_FlushOthers.emplace(path); + return true; } + return SendRoutingMessage(discarded, r); + } - void - TransitHop::QueueDestroySelf(AbstractRouter* r) - { - r->loop()->call([self = shared_from_this()] { self->SetSelfDestruct(); }); - } - } // namespace path -} // namespace llarp + std::string + TransitHop::ToString() const + { + return fmt::format( + "[TransitHop {} started={} lifetime={}", info, started.count(), lifetime.count()); + } + + void + TransitHop::Stop() + { + m_UpstreamGather.disable(); + m_DownstreamGather.disable(); + } + + void + TransitHop::SetSelfDestruct() + { + destroy = true; + } + + void + TransitHop::QueueDestroySelf(AbstractRouter* r) + { + r->loop()->call([self = shared_from_this()] { self->SetSelfDestruct(); }); + } +} // namespace llarp::path diff --git a/llarp/path/transit_hop.hpp b/llarp/path/transit_hop.hpp index fb628929ff..a6a8fc1efd 100644 --- a/llarp/path/transit_hop.hpp +++ b/llarp/path/transit_hop.hpp @@ -53,7 +53,7 @@ namespace llarp } struct TransitHop : public IHopHandler, - public routing::IMessageHandler, + public routing::AbstractRoutingMessageHandler, std::enable_shared_from_this { TransitHop(); @@ -117,11 +117,11 @@ namespace llarp // send routing message when end of path bool - SendRoutingMessage(const routing::IMessage& msg, AbstractRouter* r) override; + SendRoutingMessage(const routing::AbstractRoutingMessage& msg, AbstractRouter* r) override; // handle routing message when end of path bool - HandleRoutingMessage(const routing::IMessage& msg, AbstractRouter* r); + HandleRoutingMessage(const routing::AbstractRoutingMessage& msg, AbstractRouter* r); bool HandleDataDiscardMessage(const routing::DataDiscardMessage& msg, AbstractRouter* r) override; @@ -171,7 +171,7 @@ namespace llarp HandleGotIntroMessage(const dht::GotIntroMessage& msg); bool - HandleDHTMessage(const dht::IMessage& msg, AbstractRouter* r) override; + HandleDHTMessage(const dht::AbstractDHTMessage& msg, AbstractRouter* r) override; void FlushUpstream(AbstractRouter* r) override; diff --git a/llarp/quic/address.hpp b/llarp/quic/address.hpp index 793713e628..847a58caec 100644 --- a/llarp/quic/address.hpp +++ b/llarp/quic/address.hpp @@ -105,7 +105,10 @@ namespace llarp::quic Address local_, remote_; public: - ngtcp2_path path{{local_, local_.sockaddr_size()}, {remote_, remote_.sockaddr_size()}, nullptr}; + ngtcp2_path path{ + {local_, static_cast(local_.sockaddr_size())}, + {remote_, static_cast(remote_.sockaddr_size())}, + nullptr}; // Public accessors are const: const Address& local = local_; diff --git a/llarp/quic/connection.cpp b/llarp/quic/connection.cpp index 741f932d92..6fef72a73a 100644 --- a/llarp/quic/connection.cpp +++ b/llarp/quic/connection.cpp @@ -95,10 +95,10 @@ namespace llarp::quic auto& conn = *static_cast(user_data); switch (crypto_level) { - // case NGTCP2_CRYPTO_LEVEL_EARLY: - // // We don't currently use or support 0rtt - // LogWarn("Invalid EARLY crypto level"); - // return FAIL; + // case NGTCP2_CRYPTO_LEVEL_EARLY: + // // We don't currently use or support 0rtt + // LogWarn("Invalid EARLY crypto level"); + // return FAIL; case NGTCP2_ENCRYPTION_LEVEL_INITIAL: log::trace(log_cat, "Receiving initial crypto..."); @@ -1197,7 +1197,8 @@ namespace llarp::quic // auto exttype = is_server ? NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS // : NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO; - if (ngtcp2_ssize nwrite = ngtcp2_conn_encode_local_transport_params(*this, buf, bufend-buf); nwrite >= 0) + if (ngtcp2_ssize nwrite = ngtcp2_conn_encode_local_transport_params(*this, buf, bufend - buf); + nwrite >= 0) { assert(nwrite > 0); conn_buffer.resize(buf - u8data(conn_buffer) + nwrite); diff --git a/llarp/quic/endpoint.cpp b/llarp/quic/endpoint.cpp index 39d31e9b13..5a3da5b061 100644 --- a/llarp/quic/endpoint.cpp +++ b/llarp/quic/endpoint.cpp @@ -99,11 +99,7 @@ namespace llarp::quic Endpoint::handle_packet_init(const Packet& p) { ngtcp2_version_cid vid; - auto rv = ngtcp2_pkt_decode_version_cid( - &vid, - u8data(p.data), - p.data.size(), - NGTCP2_MAX_CIDLEN); + auto rv = ngtcp2_pkt_decode_version_cid(&vid, u8data(p.data), p.data.size(), NGTCP2_MAX_CIDLEN); if (rv == 1) { // 1 means Version Negotiation should be sent and otherwise the packet should be ignored send_version_negotiation(vid, p.path.remote); @@ -234,7 +230,11 @@ namespace llarp::quic ngtcp2_pkt_info pi; ngtcp2_ccerr err; - ngtcp2_ccerr_set_liberr(&err, code, reinterpret_cast(const_cast(close_reason.data())), close_reason.size()); + ngtcp2_ccerr_set_liberr( + &err, + code, + reinterpret_cast(const_cast(close_reason.data())), + close_reason.size()); auto written = ngtcp2_conn_write_connection_close( conn, diff --git a/llarp/quic/server.cpp b/llarp/quic/server.cpp index 03aa2f9c79..f996f9d1b6 100644 --- a/llarp/quic/server.cpp +++ b/llarp/quic/server.cpp @@ -31,7 +31,8 @@ namespace llarp::quic { // Invalid/unexpected version, send a version negotiation LogDebug("Invalid/unsupported version; sending version negotiation"); send_version_negotiation( - ngtcp2_version_cid{hd.version, hd.dcid.data, hd.dcid.datalen, hd.scid.data, hd.scid.datalen}, + ngtcp2_version_cid{ + hd.version, hd.dcid.data, hd.dcid.datalen, hd.scid.data, hd.scid.datalen}, p.path.remote); return nullptr; } diff --git a/llarp/router/abstractrouter.hpp b/llarp/router/abstractrouter.hpp index 8f5eeb9ebb..ce48ebc8a4 100644 --- a/llarp/router/abstractrouter.hpp +++ b/llarp/router/abstractrouter.hpp @@ -33,8 +33,8 @@ namespace llarp class NodeDB; struct Config; struct RouterID; - struct ILinkMessage; - struct ILinkSession; + struct AbstractLinkMessage; + struct AbstractLinkSession; struct PathID_t; struct Profiling; struct SecretKey; @@ -71,7 +71,7 @@ namespace llarp namespace routing { - struct IMessageHandler; + struct AbstractRoutingMessageHandler; } namespace service @@ -100,7 +100,7 @@ namespace llarp virtual ~AbstractRouter() = default; virtual bool - HandleRecvLinkMessageBuffer(ILinkSession* from, const llarp_buffer_t& msg) = 0; + HandleRecvLinkMessageBuffer(AbstractLinkSession* from, const llarp_buffer_t& msg) = 0; virtual const net::Platform& Net() const = 0; @@ -268,14 +268,18 @@ namespace llarp virtual bool SendToOrQueue( - const RouterID& remote, const ILinkMessage& msg, SendStatusHandler handler = nullptr) = 0; + const RouterID& remote, + const AbstractLinkMessage& msg, + SendStatusHandler handler = nullptr) = 0; virtual void PersistSessionUntil(const RouterID& remote, llarp_time_t until) = 0; virtual bool ParseRoutingMessageBuffer( - const llarp_buffer_t& buf, routing::IMessageHandler* h, const PathID_t& rxid) = 0; + const llarp_buffer_t& buf, + routing::AbstractRoutingMessageHandler* h, + const PathID_t& rxid) = 0; /// count the number of service nodes we are connected to virtual size_t @@ -318,7 +322,8 @@ namespace llarp /// visit each connected link session virtual void - ForEachPeer(std::function visit, bool randomize) const = 0; + ForEachPeer( + std::function visit, bool randomize) const = 0; virtual bool SessionToRouterAllowed(const RouterID& router) const = 0; diff --git a/llarp/router/i_outbound_message_handler.hpp b/llarp/router/i_outbound_message_handler.hpp index ed9e542a5b..3782493222 100644 --- a/llarp/router/i_outbound_message_handler.hpp +++ b/llarp/router/i_outbound_message_handler.hpp @@ -17,7 +17,7 @@ namespace llarp Congestion }; - struct ILinkMessage; + struct AbstractLinkMessage; struct RouterID; struct PathID_t; @@ -32,7 +32,8 @@ namespace llarp virtual ~IOutboundMessageHandler() = default; virtual bool - QueueMessage(const RouterID& remote, const ILinkMessage& msg, SendStatusHandler callback) = 0; + QueueMessage( + const RouterID& remote, const AbstractLinkMessage& msg, SendStatusHandler callback) = 0; virtual void Pump() = 0; diff --git a/llarp/router/i_outbound_session_maker.hpp b/llarp/router/i_outbound_session_maker.hpp index 97dd0aed9e..6c77fa0f22 100644 --- a/llarp/router/i_outbound_session_maker.hpp +++ b/llarp/router/i_outbound_session_maker.hpp @@ -10,7 +10,7 @@ namespace llarp { - struct ILinkSession; + struct AbstractLinkSession; struct RouterID; struct RouterContact; @@ -45,10 +45,10 @@ namespace llarp virtual ~IOutboundSessionMaker() = default; virtual bool - OnSessionEstablished(ILinkSession* session) = 0; + OnSessionEstablished(AbstractLinkSession* session) = 0; virtual void - OnConnectTimeout(ILinkSession* session) = 0; + OnConnectTimeout(AbstractLinkSession* session) = 0; virtual void CreateSessionTo(const RouterID& router, RouterCallback on_result) = 0; diff --git a/llarp/router/outbound_message_handler.cpp b/llarp/router/outbound_message_handler.cpp index a92b90cba7..ee019f195f 100644 --- a/llarp/router/outbound_message_handler.cpp +++ b/llarp/router/outbound_message_handler.cpp @@ -21,7 +21,7 @@ namespace llarp bool OutboundMessageHandler::QueueMessage( - const RouterID& remote, const ILinkMessage& msg, SendStatusHandler callback) + const RouterID& remote, const AbstractLinkMessage& msg, SendStatusHandler callback) { // if the destination is invalid, callback with failure and return if (not _router->linkManager().HaveClientConnection(remote) @@ -34,19 +34,21 @@ namespace llarp ent.router = remote; ent.inform = std::move(callback); ent.pathid = msg.pathid; - ent.priority = msg.Priority(); + ent.priority = msg.priority(); - std::array linkmsg_buffer; - llarp_buffer_t buf{linkmsg_buffer}; + // std::array linkmsg_buffer; + // llarp_buffer_t buf{linkmsg_buffer}; - if (!EncodeBuffer(msg, buf)) + llarp_buffer _buf{MAX_LINK_MSG_SIZE}; + + if (!EncodeBuffer(msg, _buf)) { return false; } - ent.message.resize(buf.sz); + ent.message.resize(_buf.size()); - std::copy_n(buf.base, buf.sz, ent.message.data()); + std::copy_n(_buf.data(), _buf.size(), ent.message.data()); // if we have a session to the destination, queue the message and return if (_router->linkManager().HaveConnection(remote)) @@ -168,7 +170,7 @@ namespace llarp _router->loop()->call([f = std::move(callback), status] { f(status); }); } - //TODO: still necessary/desired? + // TODO: still necessary/desired? void OutboundMessageHandler::QueueSessionCreation(const RouterID& remote) { @@ -176,18 +178,16 @@ namespace llarp } bool - OutboundMessageHandler::EncodeBuffer(const ILinkMessage& msg, llarp_buffer_t& buf) + OutboundMessageHandler::EncodeBuffer(const AbstractLinkMessage& msg, llarp_buffer& buf) { - if (!msg.BEncode(&buf)) + if (auto str = msg.bt_encode(); not str.empty()) { - LogWarn("failed to encode outbound message, buffer size left: ", buf.size_left()); - return false; + buf = llarp_buffer{std::move(str)}; + return true; } - // set size of message - buf.sz = buf.cur - buf.base; - buf.cur = buf.base; - return true; + log::error(link_cat, "Error: OutboundMessageHandler failed to encode outbound message!"); + return false; } bool @@ -199,8 +199,8 @@ namespace llarp return _router->linkManager().SendTo( ent.router, buf, - [this, callback](ILinkSession::DeliveryStatus status) { - if (status == ILinkSession::DeliveryStatus::eDeliverySuccess) + [this, callback](AbstractLinkSession::DeliveryStatus status) { + if (status == AbstractLinkSession::DeliveryStatus::eDeliverySuccess) DoCallback(callback, SendStatus::Success); else { diff --git a/llarp/router/outbound_message_handler.hpp b/llarp/router/outbound_message_handler.hpp index 232568f646..cb4c7d0199 100644 --- a/llarp/router/outbound_message_handler.hpp +++ b/llarp/router/outbound_message_handler.hpp @@ -44,7 +44,7 @@ namespace llarp * so for example an invalid destination still yields a true return. */ bool - QueueMessage(const RouterID& remote, const ILinkMessage& msg, SendStatusHandler callback) + QueueMessage(const RouterID& remote, const AbstractLinkMessage& msg, SendStatusHandler callback) override EXCLUDES(_mutex); /* Called when pumping output queues, typically scheduled via a call to Router::TriggerPump(). @@ -123,7 +123,7 @@ namespace llarp QueueSessionCreation(const RouterID& remote); bool - EncodeBuffer(const ILinkMessage& msg, llarp_buffer_t& buf); + EncodeBuffer(const AbstractLinkMessage& msg, llarp_buffer& buf); /* sends the message along to the link layer, and hopefully out to the network * diff --git a/llarp/router/outbound_session_maker.cpp b/llarp/router/outbound_session_maker.cpp index 7150f6b43a..a4eb9a21a6 100644 --- a/llarp/router/outbound_session_maker.cpp +++ b/llarp/router/outbound_session_maker.cpp @@ -19,7 +19,7 @@ namespace llarp { bool - OutboundSessionMaker::OnSessionEstablished(ILinkSession* session) + OutboundSessionMaker::OnSessionEstablished(AbstractLinkSession* session) { // TODO: do we want to keep it const RouterContact rc = session->GetRemoteRC(); @@ -44,7 +44,7 @@ namespace llarp } void - OutboundSessionMaker::OnConnectTimeout(ILinkSession* session) + OutboundSessionMaker::OnConnectTimeout(AbstractLinkSession* session) { const auto router = RouterID(session->GetPubKey()); LogWarn("Session establish attempt to ", router, " timed out.", session->GetRemoteEndpoint()); @@ -272,7 +272,7 @@ namespace llarp FinalizeRequest(rc.pubkey, SessionResult::Establish); } - //TODO: rename this, if we even want to keep it + // TODO: rename this, if we even want to keep it void OutboundSessionMaker::CreatePendingSession(const RouterID& router) { diff --git a/llarp/router/outbound_session_maker.hpp b/llarp/router/outbound_session_maker.hpp index f658ae30fe..b1823dabe3 100644 --- a/llarp/router/outbound_session_maker.hpp +++ b/llarp/router/outbound_session_maker.hpp @@ -29,10 +29,10 @@ namespace llarp ~OutboundSessionMaker() override = default; bool - OnSessionEstablished(ILinkSession* session) override; + OnSessionEstablished(AbstractLinkSession* session) override; void - OnConnectTimeout(ILinkSession* session) override; + OnConnectTimeout(AbstractLinkSession* session) override; void CreateSessionTo(const RouterID& router, RouterCallback on_result) override EXCLUDES(_mutex); diff --git a/llarp/router/rc_gossiper.cpp b/llarp/router/rc_gossiper.cpp index c1bafb2fda..1e5c8705a8 100644 --- a/llarp/router/rc_gossiper.cpp +++ b/llarp/router/rc_gossiper.cpp @@ -105,7 +105,7 @@ namespace llarp * // select peers to gossip to m_LinkManager->ForEachPeer( - [&](const ILinkSession* peerSession, bool) { + [&](const AbstractLinkSession* peerSession, bool) { // ensure connected session if (not(peerSession && peerSession->IsEstablished())) return; @@ -122,7 +122,7 @@ namespace llarp std::sample( gossipTo.begin(), gossipTo.end(), std::inserter(keys, keys.end()), MaxGossipPeers, CSRNG{}); - m_LinkManager->ForEachPeer([&](ILinkSession* peerSession) { + m_LinkManager->ForEachPeer([&](AbstractLinkSession* peerSession) { if (not(peerSession && peerSession->IsEstablished())) return; @@ -131,7 +131,7 @@ namespace llarp return; // encode message - ILinkSession::Message_t msg{}; + AbstractLinkSession::Message_t msg{}; msg.resize(MAX_LINK_MSG_SIZE / 2); llarp_buffer_t buf(msg); if (not gossip.BEncode(&buf)) diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index c02d0c3c0b..e8f78ee7f7 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -79,8 +79,8 @@ namespace llarp llarp_dht_context_free(_dht); } - //TODO: investigate changes needed for libquic integration - // still needed at all? + // TODO: investigate changes needed for libquic integration + // still needed at all? void Router::PumpLL() { @@ -110,7 +110,7 @@ namespace llarp {"outboundMessages", _outboundMessageHandler.ExtractStatus()}}; } - //TODO: investigate changes needed for libquic integration + // TODO: investigate changes needed for libquic integration util::StatusObject Router::ExtractSummaryStatus() const { @@ -208,9 +208,9 @@ namespace llarp return stats; } - //TODO: libquic change + // TODO: libquic change bool - Router::HandleRecvLinkMessageBuffer(ILinkSession* session, const llarp_buffer_t& buf) + Router::HandleRecvLinkMessageBuffer(AbstractLinkSession* session, const llarp_buffer_t& buf) { if (_stopping) return true; @@ -314,21 +314,23 @@ namespace llarp } bool - Router::SendToOrQueue(const RouterID& remote, const ILinkMessage& msg, SendStatusHandler handler) + Router::SendToOrQueue( + const RouterID& remote, const AbstractLinkMessage& msg, SendStatusHandler handler) { return _outboundMessageHandler.QueueMessage(remote, msg, handler); } - //TODO: if still needed/useful, replace this in line with libquic impl + // TODO: if still needed/useful, replace this in line with libquic impl void - Router::ForEachPeer(std::function visit, bool randomize) const + Router::ForEachPeer( + std::function visit, bool randomize) const { //_linkManager.ForEachPeer(visit, randomize); } - //TODO: if still needed/useful, replace this in line with libquic impl + // TODO: if still needed/useful, replace this in line with libquic impl void - Router::ForEachPeer(std::function visit) + Router::ForEachPeer(std::function visit) { //_linkManager.ForEachPeer(visit); } @@ -540,7 +542,7 @@ namespace llarp bool Router::ParseRoutingMessageBuffer( - const llarp_buffer_t& buf, routing::IMessageHandler* h, const PathID_t& rxid) + const llarp_buffer_t& buf, routing::AbstractRoutingMessageHandler* h, const PathID_t& rxid) { return inbound_routing_msg_parser.ParseMessageBuffer(buf, h, rxid, this); } @@ -630,8 +632,8 @@ namespace llarp _rc = std::move(nextRC); if (rotateKeys) { - //TODO: libquic change - // propagate RC by renegotiating sessions + // TODO: libquic change + // propagate RC by renegotiating sessions /* ForEachPeer([](ILinkSession* s) { if (s->RenegotiateSession()) @@ -803,7 +805,7 @@ namespace llarp whitelistRouters, m_isServiceNode); - //FIXME: kludge for now, will be part of larger cleanup effort. + // FIXME: kludge for now, will be part of larger cleanup effort. if (m_isServiceNode) InitInboundLinks(); else @@ -1176,7 +1178,7 @@ namespace llarp return CryptoManager::instance()->sign(sig, identity(), buf); } - //TODO: replace this in line with libquic impl + // TODO: replace this in line with libquic impl void Router::SessionClosed(RouterID remote) { @@ -1193,9 +1195,9 @@ namespace llarp } } - //TODO: replace this in line with libquic impl + // TODO: replace this in line with libquic impl void - Router::ConnectionTimedOut(ILinkSession* session) + Router::ConnectionTimedOut(AbstractLinkSession* session) { if (m_peerDb) { @@ -1216,9 +1218,9 @@ namespace llarp } } - //TODO: replace this in line with libquic impl + // TODO: replace this in line with libquic impl bool - Router::ConnectionEstablished(ILinkSession* session, bool inbound) + Router::ConnectionEstablished(AbstractLinkSession* session, bool inbound) { RouterID id{session->GetPubKey()}; if (m_peerDb) @@ -1670,7 +1672,7 @@ namespace llarp if ((not Net().IsBogonIP(ai_ip)) and (not Net().IsBogonIP(override_ip)) and ai_ip != override_ip) throw std::runtime_error{ - "Lokinet is bound to public IP '{}', but public-ip is set to '{}'. Either fix the " + "Lokinet is bound to public IP '{}', but public-ip is set to '{}'. Either fix the " "[router]:public-ip setting or set a bind address in the [bind] section of the " "config."_format(ai_ip_str, override_ip_str)}; ai.fromSockAddr(*_ourAddress); @@ -1678,8 +1680,8 @@ namespace llarp if (RouterContact::BlockBogons && Net().IsBogon(ai.ip)) throw std::runtime_error{var::visit( [](auto&& ip) { - return "cannot use " + ip.ToString() - + " as a public ip as it is in a non routable ip range"; + return "cannot use " + ip.ToString() + + " as a public ip as it is in a non routable ip range"; }, ai.IP())}; LogInfo("adding address: ", ai); @@ -1729,8 +1731,8 @@ namespace llarp _linkManager.AddLink({ai.IPString(), ai.port}, true); ai.pubkey = llarp::seckey_topublic(_identity); - ai.dialect = "quicinet"; // FIXME: constant, also better name? - ai.rank = 2; // FIXME: hardcoded from the beginning...keep? + ai.dialect = "quicinet"; // FIXME: constant, also better name? + ai.rank = 2; // FIXME: hardcoded from the beginning...keep? AddAddressToRC(ai); } } diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 155fd23088..d47ae7aafc 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -310,7 +310,7 @@ namespace llarp Profiling _routerProfiling; fs::path _profilesFile; OutboundMessageHandler _outboundMessageHandler; - LinkManager _linkManager { this }; + LinkManager _linkManager{this}; RCLookupHandler _rcLookupHandler; RCGossiper _rcGossiper; @@ -360,7 +360,7 @@ namespace llarp ~Router() override; bool - HandleRecvLinkMessageBuffer(ILinkSession* from, const llarp_buffer_t& msg) override; + HandleRecvLinkMessageBuffer(AbstractLinkSession* from, const llarp_buffer_t& msg) override; void InitInboundLinks(); @@ -459,14 +459,14 @@ namespace llarp /// MUST be called in the logic thread bool SendToOrQueue( - const RouterID& remote, const ILinkMessage& msg, SendStatusHandler handler) override; + const RouterID& remote, const AbstractLinkMessage& msg, SendStatusHandler handler) override; void - ForEachPeer(std::function visit, bool randomize = false) + ForEachPeer(std::function visit, bool randomize = false) const override; void - ForEachPeer(std::function visit); + ForEachPeer(std::function visit); bool IsBootstrapNode(RouterID) const override; @@ -483,11 +483,11 @@ namespace llarp /// called by link when an unestablished connection times out void - ConnectionTimedOut(ILinkSession* session); + ConnectionTimedOut(AbstractLinkSession* session); /// called by link when session is fully established bool - ConnectionEstablished(ILinkSession* session, bool inbound); + ConnectionEstablished(AbstractLinkSession* session, bool inbound); /// call internal router ticker void @@ -504,7 +504,9 @@ namespace llarp /// return false bool ParseRoutingMessageBuffer( - const llarp_buffer_t& buf, routing::IMessageHandler* h, const PathID_t& rxid) override; + const llarp_buffer_t& buf, + routing::AbstractRoutingMessageHandler* h, + const PathID_t& rxid) override; void ConnectToRandomRouters(int N) override; diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index 194a59b0b8..cd5731fc5d 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -110,6 +110,14 @@ namespace llarp return false; } + void + RouterContact::bt_encode_subdict(oxenc::bt_list_producer& btlp) const + { + btlp.append("1"); + btlp.append(signature.ToView()); + btlp.append(signed_bt_dict); + } + std::string RouterContact::ToTXTRecord() const { @@ -196,6 +204,7 @@ namespace llarp if (!bencode_write_uint64_entry(buf, "v", 1, version)) return false; + // D We can delete this? if (serializeExit) { /* write xi if they exist */ diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index 340bab5970..fe7605b862 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -11,8 +11,9 @@ #include "llarp/dns/srv_data.hpp" -#include +#include #include +#include #include #define MAX_RC_SIZE (1024) @@ -111,6 +112,10 @@ namespace llarp bool BEncode(llarp_buffer_t* buf) const; + // tofix: drop version 0 case, change parameter to take btlp reference + void + bt_encode_subdict(oxenc::bt_list_producer& btlp) const; + bool BEncodeSignedSection(llarp_buffer_t* buf) const; diff --git a/llarp/routing/dht_message.cpp b/llarp/routing/dht_message.cpp index 72ffe6bb4f..bdffb0a66c 100644 --- a/llarp/routing/dht_message.cpp +++ b/llarp/routing/dht_message.cpp @@ -14,7 +14,7 @@ namespace llarp { llarp::dht::Key_t fromKey; fromKey.Zero(); - return llarp::dht::DecodeMesssageList(fromKey, val, M, true); + return llarp::dht::DecodeMessageList(fromKey, val, M, true); } if (key.startswith("S")) { @@ -51,7 +51,7 @@ namespace llarp /// (e.g. dht::IMessage::HandleMessage()) in-place and is the case where a /// client receives a DHT message bool - DHTMessage::HandleMessage(IMessageHandler* h, AbstractRouter* r) const + DHTMessage::HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const { // set source as us const llarp::dht::Key_t us(r->pubkey()); diff --git a/llarp/routing/dht_message.hpp b/llarp/routing/dht_message.hpp index f1d13f6b02..72ebab2d10 100644 --- a/llarp/routing/dht_message.hpp +++ b/llarp/routing/dht_message.hpp @@ -5,32 +5,29 @@ #include -namespace llarp +namespace llarp::routing { - namespace routing + struct DHTMessage final : public AbstractRoutingMessage { - struct DHTMessage final : public IMessage - { - std::vector M; - uint64_t V = 0; + std::vector M; + uint64_t V = 0; - ~DHTMessage() override = default; + ~DHTMessage() override = default; - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) override; + bool + DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) override; - bool - BEncode(llarp_buffer_t* buf) const override; + bool + BEncode(llarp_buffer_t* buf) const override; - bool - HandleMessage(IMessageHandler* h, AbstractRouter* r) const override; + bool + HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; - void - Clear() override - { - M.clear(); - V = 0; - } - }; - } // namespace routing -} // namespace llarp + void + Clear() override + { + M.clear(); + V = 0; + } + }; +} // namespace llarp::routing diff --git a/llarp/routing/handler.hpp b/llarp/routing/handler.hpp index fb68aabae7..9e1de588f7 100644 --- a/llarp/routing/handler.hpp +++ b/llarp/routing/handler.hpp @@ -8,7 +8,7 @@ namespace llarp namespace dht { - struct IMessage; + struct AbstractDHTMessage; } namespace service @@ -31,7 +31,7 @@ namespace llarp struct PathLatencyMessage; // handles messages on the routing level - struct IMessageHandler + struct AbstractRoutingMessageHandler { virtual bool HandleObtainExitMessage(const ObtainExitMessage& msg, AbstractRouter* r) = 0; @@ -69,10 +69,10 @@ namespace llarp virtual bool HandlePathLatencyMessage(const PathLatencyMessage& msg, AbstractRouter* r) = 0; virtual bool - HandleDHTMessage(const dht::IMessage& msg, AbstractRouter* r) = 0; + HandleDHTMessage(const dht::AbstractDHTMessage& msg, AbstractRouter* r) = 0; }; - using MessageHandler_ptr = std::shared_ptr; + using MessageHandler_ptr = std::shared_ptr; } // namespace routing } // namespace llarp diff --git a/llarp/routing/message.hpp b/llarp/routing/message.hpp index 6544792d5b..4acfd0e65f 100644 --- a/llarp/routing/message.hpp +++ b/llarp/routing/message.hpp @@ -1,41 +1,66 @@ #pragma once +#include #include #include #include #include +namespace +{ + static auto route_cat = llarp::log::Cat("lokinet.routing"); +} // namespace + namespace llarp { struct AbstractRouter; namespace routing { - struct IMessageHandler; + struct AbstractRoutingMessageHandler; - struct IMessage + struct AbstractRoutingMessage : private AbstractSerializable { PathID_t from; uint64_t S{0}; uint64_t version = llarp::constants::proto_version; - IMessage() = default; + AbstractRoutingMessage() = default; - virtual ~IMessage() = default; + virtual ~AbstractRoutingMessage() = default; virtual bool - BEncode(llarp_buffer_t* buf) const = 0; + decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) = 0; - virtual bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) = 0; + std::string + bt_encode() const override = 0; virtual bool - HandleMessage(IMessageHandler* h, AbstractRouter* r) const = 0; + handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const = 0; virtual void - Clear() = 0; + clear() = 0; + + // methods we do not want to inherit onwards from AbstractSerializable + void + bt_encode(oxenc::bt_list_producer&) const final + { + throw std::runtime_error{ + "Error: Routing messages should not encode directly to a bt list producer!"}; + } + void + bt_encode(llarp_buffer&) const final + { + throw std::runtime_error{"Error: Routing messages should not encode directly to a buffer!"}; + } + void + bt_encode(oxenc::bt_dict_producer&) const final + { + throw std::runtime_error{ + "Error: Routing messages should not encode directly to a bt dict producer!"}; + } bool - operator<(const IMessage& other) const + operator<(const AbstractRoutingMessage& other) const { return other.S < S; } diff --git a/llarp/routing/message_parser.cpp b/llarp/routing/message_parser.cpp index 16f77ae872..09db93c874 100644 --- a/llarp/routing/message_parser.cpp +++ b/llarp/routing/message_parser.cpp @@ -10,136 +10,136 @@ #include "transfer_traffic_message.hpp" #include -namespace llarp +namespace llarp::routing { - namespace routing + struct InboundMessageParser::MessageHolder { - struct InboundMessageParser::MessageHolder - { - DataDiscardMessage D; - PathLatencyMessage L; - DHTMessage M; - PathConfirmMessage P; - PathTransferMessage T; - service::ProtocolFrame H; - TransferTrafficMessage I; - GrantExitMessage G; - RejectExitMessage J; - ObtainExitMessage O; - UpdateExitMessage U; - CloseExitMessage C; - }; + DataDiscardMessage D; + PathLatencyMessage L; + DHTMessage M; + PathConfirmMessage P; + PathTransferMessage T; + service::ProtocolFrame H; + TransferTrafficMessage I; + GrantExitMessage G; + RejectExitMessage J; + ObtainExitMessage O; + UpdateExitMessage U; + CloseExitMessage C; + }; - InboundMessageParser::InboundMessageParser() : m_Holder(std::make_unique()) - {} + InboundMessageParser::InboundMessageParser() : m_Holder(std::make_unique()) + {} - InboundMessageParser::~InboundMessageParser() = default; + InboundMessageParser::~InboundMessageParser() = default; - bool - InboundMessageParser::operator()(llarp_buffer_t* buffer, llarp_buffer_t* key) + bool + InboundMessageParser::operator()(llarp_buffer_t* buffer, llarp_buffer_t* key) + { + if (key == nullptr && firstKey) { - if (key == nullptr && firstKey) - { - // empty dict + // empty dict + return false; + } + if (!key) + return true; + if (firstKey) + { + llarp_buffer_t strbuf; + if (!(key->startswith("A"))) return false; - } - if (!key) - return true; - if (firstKey) + if (!bencode_read_string(buffer, &strbuf)) + return false; + if (strbuf.sz != 1) + return false; + ourKey = *strbuf.cur; + LogDebug("routing message '", std::string{ourKey, 1}, "'"); + switch (ourKey) { - llarp_buffer_t strbuf; - if (!(key->startswith("A"))) - return false; - if (!bencode_read_string(buffer, &strbuf)) - return false; - if (strbuf.sz != 1) - return false; - ourKey = *strbuf.cur; - LogDebug("routing message '", std::string{ourKey, 1}, "'"); - switch (ourKey) - { - case 'D': - msg = &m_Holder->D; - break; - case 'L': - msg = &m_Holder->L; - break; - case 'M': - msg = &m_Holder->M; - break; - case 'P': - msg = &m_Holder->P; - break; - case 'T': - msg = &m_Holder->T; - break; - case 'H': - msg = &m_Holder->H; - break; - case 'I': - msg = &m_Holder->I; - break; - case 'G': - msg = &m_Holder->G; - break; - case 'J': - msg = &m_Holder->J; - break; - case 'O': - msg = &m_Holder->O; - break; - case 'U': - msg = &m_Holder->U; - break; - case 'C': - msg = &m_Holder->C; - break; - default: - llarp::LogError("invalid routing message id: ", *strbuf.cur); - } - if (msg) - msg->version = version; - firstKey = false; - return msg != nullptr; + case 'D': + msg = &m_Holder->D; + break; + case 'L': + msg = &m_Holder->L; + break; + case 'M': + msg = &m_Holder->M; + break; + case 'P': + msg = &m_Holder->P; + break; + case 'T': + msg = &m_Holder->T; + break; + case 'H': + msg = &m_Holder->H; + break; + case 'I': + msg = &m_Holder->I; + break; + case 'G': + msg = &m_Holder->G; + break; + case 'J': + msg = &m_Holder->J; + break; + case 'O': + msg = &m_Holder->O; + break; + case 'U': + msg = &m_Holder->U; + break; + case 'C': + msg = &m_Holder->C; + break; + default: + llarp::LogError("invalid routing message id: ", *strbuf.cur); } - - return msg->DecodeKey(*key, buffer); + if (msg) + msg->version = version; + firstKey = false; + return msg != nullptr; } - bool - InboundMessageParser::ParseMessageBuffer( - const llarp_buffer_t& buf, IMessageHandler* h, const PathID_t& from, AbstractRouter* r) + return msg->DecodeKey(*key, buffer); + } + + bool + InboundMessageParser::ParseMessageBuffer( + const llarp_buffer_t& buf, + AbstractRoutingMessageHandler* h, + const PathID_t& from, + AbstractRouter* r) + { + bool result = false; + msg = nullptr; + firstKey = true; + ManagedBuffer copiedBuf(buf); + auto& copy = copiedBuf.underlying; + uint64_t v = 0; + if (BEncodeSeekDictVersion(v, ©, 'V')) { - bool result = false; - msg = nullptr; - firstKey = true; - ManagedBuffer copiedBuf(buf); - auto& copy = copiedBuf.underlying; - uint64_t v = 0; - if (BEncodeSeekDictVersion(v, ©, 'V')) - { - version = v; - } - if (bencode_read_dict(*this, ©)) - { - msg->from = from; - LogDebug("handle routing message ", msg->S, " from ", from); - result = msg->HandleMessage(h, r); - if (!result) - { - llarp::LogWarn("Failed to handle inbound routing message ", ourKey); - } - } - else + version = v; + } + if (bencode_read_dict(*this, ©)) + { + msg->from = from; + LogDebug("handle routing message ", msg->S, " from ", from); + result = msg->HandleMessage(h, r); + if (!result) { - llarp::LogError("read dict failed in routing layer"); - llarp::DumpBuffer(buf); + llarp::LogWarn("Failed to handle inbound routing message ", ourKey); } - if (msg) - msg->Clear(); - msg = nullptr; - version = 0; - return result; } - } // namespace routing -} // namespace llarp + else + { + llarp::LogError("read dict failed in routing layer"); + llarp::DumpBuffer(buf); + } + if (msg) + msg->Clear(); + msg = nullptr; + version = 0; + return result; + } +} // namespace llarp::routing diff --git a/llarp/routing/message_parser.hpp b/llarp/routing/message_parser.hpp index ed841875ac..968260224d 100644 --- a/llarp/routing/message_parser.hpp +++ b/llarp/routing/message_parser.hpp @@ -12,8 +12,8 @@ namespace llarp namespace routing { - struct IMessage; - struct IMessageHandler; + struct AbstractRoutingMessage; + struct AbstractRoutingMessageHandler; struct InboundMessageParser { @@ -23,7 +23,7 @@ namespace llarp bool ParseMessageBuffer( const llarp_buffer_t& buf, - IMessageHandler* handler, + AbstractRoutingMessageHandler* handler, const PathID_t& from, AbstractRouter* r); @@ -36,7 +36,7 @@ namespace llarp char ourKey{'\0'}; struct MessageHolder; - IMessage* msg{nullptr}; + AbstractRoutingMessage* msg{nullptr}; std::unique_ptr m_Holder; }; } // namespace routing diff --git a/llarp/routing/path_confirm_message.cpp b/llarp/routing/path_confirm_message.cpp index 98d2df8762..00b739d67b 100644 --- a/llarp/routing/path_confirm_message.cpp +++ b/llarp/routing/path_confirm_message.cpp @@ -46,7 +46,7 @@ namespace llarp } bool - PathConfirmMessage::HandleMessage(IMessageHandler* h, AbstractRouter* r) const + PathConfirmMessage::HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const { return h && h->HandlePathConfirmMessage(*this, r); } diff --git a/llarp/routing/path_confirm_message.hpp b/llarp/routing/path_confirm_message.hpp index 9394b56873..c9a76bc2aa 100644 --- a/llarp/routing/path_confirm_message.hpp +++ b/llarp/routing/path_confirm_message.hpp @@ -2,35 +2,32 @@ #include "message.hpp" -namespace llarp +namespace llarp::routing { - namespace routing + struct PathConfirmMessage final : public AbstractRoutingMessage { - struct PathConfirmMessage final : public IMessage - { - llarp_time_t pathLifetime = 0s; - llarp_time_t pathCreated = 0s; + llarp_time_t pathLifetime = 0s; + llarp_time_t pathCreated = 0s; - PathConfirmMessage() = default; - PathConfirmMessage(llarp_time_t lifetime); - ~PathConfirmMessage() override = default; + PathConfirmMessage() = default; + PathConfirmMessage(llarp_time_t lifetime); + ~PathConfirmMessage() override = default; - bool - BEncode(llarp_buffer_t* buf) const override; + bool + BEncode(llarp_buffer_t* buf) const override; - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) override; + bool + DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) override; - bool - HandleMessage(IMessageHandler* h, AbstractRouter* r) const override; + bool + HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; - void - Clear() override - { - pathLifetime = 0s; - pathCreated = 0s; - version = 0; - } - }; - } // namespace routing -} // namespace llarp + void + Clear() override + { + pathLifetime = 0s; + pathCreated = 0s; + version = 0; + } + }; +} // namespace llarp::routing diff --git a/llarp/routing/path_latency_message.cpp b/llarp/routing/path_latency_message.cpp index 66099067ab..ad97e32489 100644 --- a/llarp/routing/path_latency_message.cpp +++ b/llarp/routing/path_latency_message.cpp @@ -45,7 +45,7 @@ namespace llarp } bool - PathLatencyMessage::HandleMessage(IMessageHandler* h, AbstractRouter* r) const + PathLatencyMessage::HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const { return h && h->HandlePathLatencyMessage(*this, r); } diff --git a/llarp/routing/path_latency_message.hpp b/llarp/routing/path_latency_message.hpp index 16346b9699..006bb77b98 100644 --- a/llarp/routing/path_latency_message.hpp +++ b/llarp/routing/path_latency_message.hpp @@ -6,7 +6,7 @@ namespace llarp { namespace routing { - struct PathLatencyMessage final : public IMessage + struct PathLatencyMessage final : public AbstractRoutingMessage { uint64_t T = 0; uint64_t L = 0; @@ -27,7 +27,7 @@ namespace llarp } bool - HandleMessage(IMessageHandler* h, AbstractRouter* r) const override; + HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; }; } // namespace routing } // namespace llarp diff --git a/llarp/routing/path_transfer_message.cpp b/llarp/routing/path_transfer_message.cpp index ddb5ac82d9..8984d0b987 100644 --- a/llarp/routing/path_transfer_message.cpp +++ b/llarp/routing/path_transfer_message.cpp @@ -49,7 +49,7 @@ namespace llarp } bool - PathTransferMessage::HandleMessage(IMessageHandler* h, AbstractRouter* r) const + PathTransferMessage::HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const { return h->HandlePathTransferMessage(*this, r); } diff --git a/llarp/routing/path_transfer_message.hpp b/llarp/routing/path_transfer_message.hpp index 1b31865068..ffb6f80d6d 100644 --- a/llarp/routing/path_transfer_message.hpp +++ b/llarp/routing/path_transfer_message.hpp @@ -9,7 +9,7 @@ namespace llarp { namespace routing { - struct PathTransferMessage final : public IMessage + struct PathTransferMessage final : public AbstractRoutingMessage { PathID_t P; service::ProtocolFrame T; @@ -29,7 +29,7 @@ namespace llarp BEncode(llarp_buffer_t* buf) const override; bool - HandleMessage(IMessageHandler*, AbstractRouter* r) const override; + HandleMessage(AbstractRoutingMessageHandler*, AbstractRouter* r) const override; void Clear() override diff --git a/llarp/routing/transfer_traffic_message.cpp b/llarp/routing/transfer_traffic_message.cpp index b1a7beeba0..a95e80ad51 100644 --- a/llarp/routing/transfer_traffic_message.cpp +++ b/llarp/routing/transfer_traffic_message.cpp @@ -58,7 +58,7 @@ namespace llarp } bool - TransferTrafficMessage::HandleMessage(IMessageHandler* h, AbstractRouter* r) const + TransferTrafficMessage::HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const { return h->HandleTransferTrafficMessage(*this, r); } diff --git a/llarp/routing/transfer_traffic_message.hpp b/llarp/routing/transfer_traffic_message.hpp index 82c0b29246..b1ef654ba2 100644 --- a/llarp/routing/transfer_traffic_message.hpp +++ b/llarp/routing/transfer_traffic_message.hpp @@ -13,7 +13,7 @@ namespace llarp constexpr size_t ExitPadSize = 512 - 48; constexpr size_t MaxExitMTU = 1500; constexpr size_t ExitOverhead = sizeof(uint64_t); - struct TransferTrafficMessage final : public IMessage + struct TransferTrafficMessage final : public AbstractRoutingMessage { std::vector> X; service::ProtocolType protocol; @@ -45,7 +45,7 @@ namespace llarp DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* val) override; bool - HandleMessage(IMessageHandler* h, AbstractRouter* r) const override; + HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; }; } // namespace routing } // namespace llarp diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 89c24bc6bc..fe18ebecce 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -769,7 +769,7 @@ namespace llarp , m_relayOrder(relayOrder) {} - std::shared_ptr + std::shared_ptr BuildRequestMessage() override { auto msg = std::make_shared(); @@ -988,7 +988,7 @@ namespace llarp namehash, llarp_buffer_t(lnsName.c_str(), lnsName.size())); } - std::shared_ptr + std::shared_ptr BuildRequestMessage() override { auto msg = std::make_shared(); diff --git a/llarp/service/hidden_service_address_lookup.cpp b/llarp/service/hidden_service_address_lookup.cpp index 7b8d71e29f..5c386101a0 100644 --- a/llarp/service/hidden_service_address_lookup.cpp +++ b/llarp/service/hidden_service_address_lookup.cpp @@ -49,7 +49,7 @@ namespace llarp return handle(remote, found, endpoint, TimeLeft(time_now_ms()), relayOrder); } - std::shared_ptr + std::shared_ptr HiddenServiceAddressLookup::BuildRequestMessage() { auto msg = std::make_shared(); diff --git a/llarp/service/hidden_service_address_lookup.hpp b/llarp/service/hidden_service_address_lookup.hpp index 164b365d28..b90260a4a8 100644 --- a/llarp/service/hidden_service_address_lookup.hpp +++ b/llarp/service/hidden_service_address_lookup.hpp @@ -46,7 +46,7 @@ namespace llarp bool HandleIntrosetResponse(const std::set& results) override; - std::shared_ptr + std::shared_ptr BuildRequestMessage() override; }; } // namespace service diff --git a/llarp/service/lookup.hpp b/llarp/service/lookup.hpp index 9f20cc1271..4a485c1de6 100644 --- a/llarp/service/lookup.hpp +++ b/llarp/service/lookup.hpp @@ -64,7 +64,7 @@ namespace llarp } /// build request message for service lookup - virtual std::shared_ptr + virtual std::shared_ptr BuildRequestMessage() = 0; /// build a new request message and send it via a path diff --git a/llarp/service/protocol.cpp b/llarp/service/protocol.cpp index b838c44cd3..96bfd9b122 100644 --- a/llarp/service/protocol.cpp +++ b/llarp/service/protocol.cpp @@ -523,7 +523,8 @@ namespace llarp } bool - ProtocolFrame::HandleMessage(routing::IMessageHandler* h, AbstractRouter* /*r*/) const + ProtocolFrame::HandleMessage( + routing::AbstractRoutingMessageHandler* h, AbstractRouter* /*r*/) const { return h->HandleHiddenServiceFrame(*this); } diff --git a/llarp/service/protocol.hpp b/llarp/service/protocol.hpp index 4286ce221d..a13f3cf2e4 100644 --- a/llarp/service/protocol.hpp +++ b/llarp/service/protocol.hpp @@ -71,7 +71,7 @@ namespace llarp }; /// outer message - struct ProtocolFrame final : public routing::IMessage + struct ProtocolFrame final : public routing::AbstractRoutingMessage { using Encrypted_t = Encrypted<2048>; PQCipherBlock C; @@ -83,7 +83,7 @@ namespace llarp service::ConvoTag T; ProtocolFrame(const ProtocolFrame& other) - : routing::IMessage() + : routing::AbstractRoutingMessage() , C(other.C) , D(other.D) , R(other.R) @@ -96,7 +96,7 @@ namespace llarp version = other.version; } - ProtocolFrame() : routing::IMessage{} + ProtocolFrame() : routing::AbstractRoutingMessage{} { Clear(); } @@ -162,7 +162,7 @@ namespace llarp Verify(const ServiceInfo& from) const; bool - HandleMessage(routing::IMessageHandler* h, AbstractRouter* r) const override; + HandleMessage(routing::AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; }; } // namespace service } // namespace llarp diff --git a/llarp/tooling/dht_event.hpp b/llarp/tooling/dht_event.hpp index 5c7f856116..f0f0e7850f 100644 --- a/llarp/tooling/dht_event.hpp +++ b/llarp/tooling/dht_event.hpp @@ -102,7 +102,7 @@ namespace tooling , from(msg.From) , targetKey(msg.targetKey) , iterative(msg.iterative) - , exploritory(msg.exploritory) + , exploritory(msg.exploratory) , txid(msg.txid) , version(msg.version) {} diff --git a/llarp/util/buffer.hpp b/llarp/util/buffer.hpp index c77df8a311..01ba5ea1b8 100644 --- a/llarp/util/buffer.hpp +++ b/llarp/util/buffer.hpp @@ -20,7 +20,84 @@ namespace llarp { using byte_view_t = std::basic_string_view; -} + using bstring = std::basic_string; + using bstring_view = std::basic_string_view; + + struct llarp_buffer + { + private: + std::string _buf; + std::string_view _bview; + size_t _size; + + public: + llarp_buffer() = default; + llarp_buffer(size_t s) : _size{s} + { + _buf.reserve(_size); + _bview = {_buf}; + } + llarp_buffer(std::string& b) : _buf{std::move(b)}, _bview{_buf}, _size{_buf.size()} + {} + llarp_buffer(std::string_view bv) : _buf{bv}, _bview{_buf}, _size{_buf.size()} + {} + + template < + typename CharT, + std::enable_if_t< + std::is_convertible_v || std::is_constructible_v, + int> = 0> + llarp_buffer(CharT* c) : _buf{c}, _bview{_buf}, _size{_buf.size()} + {} + + std::string_view + view() const + { + return _bview; + } + + size_t + size() const + { + return _size; + } + + bool + is_empty() const + { + return _buf.empty(); + } + + char* + data() + { + return _buf.data(); + } + char* + data_at(size_t pos) + { + return _buf.data() + pos; + } + + const char* + vdata() + { + return _bview.data(); + } + const char* + vdata_at(size_t pos) + { + return _bview.data() + pos; + } + + char + operator[](size_t pos) + { + return *(data() + pos); + } + }; + +} // namespace llarp struct ManagedBuffer; @@ -36,18 +113,19 @@ struct /* [[deprecated("this type is stupid, use something else")]] */ llarp_buf /// max size of buffer size_t sz{0}; - byte_t operator[](size_t x) + byte_t + operator[](size_t x) { return *(this->base + x); } llarp_buffer_t() = default; - llarp_buffer_t(byte_t * b, byte_t * c, size_t s) : base(b), cur(c), sz(s) + llarp_buffer_t(byte_t* b, byte_t* c, size_t s) : base(b), cur(c), sz(s) {} llarp_buffer_t(const ManagedBuffer&) = delete; - llarp_buffer_t(ManagedBuffer &&) = delete; + llarp_buffer_t(ManagedBuffer&&) = delete; template static constexpr bool is_basic_byte = sizeof(Byte) == 1 and std::is_trivially_copyable_v; @@ -57,21 +135,21 @@ struct /* [[deprecated("this type is stupid, use something else")]] */ llarp_buf template < typename Byte, typename = std::enable_if_t && is_basic_byte>> - llarp_buffer_t(Byte * buf, size_t sz) : base{reinterpret_cast(buf)}, cur{base}, sz{sz} + llarp_buffer_t(Byte* buf, size_t sz) : base{reinterpret_cast(buf)}, cur{base}, sz{sz} {} /// initialize llarp_buffer_t from vector or array of byte-like values template < typename Byte, typename = std::enable_if_t && is_basic_byte>> - llarp_buffer_t(std::vector & b) : llarp_buffer_t{b.data(), b.size()} + llarp_buffer_t(std::vector& b) : llarp_buffer_t{b.data(), b.size()} {} template < typename Byte, size_t N, typename = std::enable_if_t && is_basic_byte>> - llarp_buffer_t(std::array & b) : llarp_buffer_t{b.data(), b.size()} + llarp_buffer_t(std::array& b) : llarp_buffer_t{b.data(), b.size()} {} // These overloads, const_casting away the const, are not just gross but downright dangerous: @@ -97,27 +175,32 @@ struct /* [[deprecated("this type is stupid, use something else")]] */ llarp_buf template < typename T, typename = std::void_t().data() + std::declval().size())>> - explicit llarp_buffer_t(T && t) : llarp_buffer_t{t.data(), t.size()} + explicit llarp_buffer_t(T&& t) : llarp_buffer_t{t.data(), t.size()} {} - byte_t* begin() + byte_t* + begin() { return base; } - const byte_t* begin() const + const byte_t* + begin() const { return base; } - byte_t* end() + byte_t* + end() { return base + sz; } - const byte_t* end() const + const byte_t* + end() const { return base + sz; } - size_t size_left() const + size_t + size_left() const { size_t diff = cur - base; assert(diff <= sz); @@ -127,50 +210,66 @@ struct /* [[deprecated("this type is stupid, use something else")]] */ llarp_buf } template - bool read_into(OutputIt begin, OutputIt end); + bool + read_into(OutputIt begin, OutputIt end); template - bool write(InputIt begin, InputIt end); + bool + write(InputIt begin, InputIt end); #ifndef _WIN32 - bool writef(const char* fmt, ...) __attribute__((format(printf, 2, 3))); + bool + writef(const char* fmt, ...) __attribute__((format(printf, 2, 3))); #elif defined(__MINGW64__) || defined(__MINGW32__) - bool writef(const char* fmt, ...) __attribute__((__format__(__MINGW_PRINTF_FORMAT, 2, 3))); + bool + writef(const char* fmt, ...) __attribute__((__format__(__MINGW_PRINTF_FORMAT, 2, 3))); #else - bool writef(const char* fmt, ...); + bool + writef(const char* fmt, ...); #endif - bool put_uint16(uint16_t i); - bool put_uint32(uint32_t i); + bool + put_uint16(uint16_t i); + bool + put_uint32(uint32_t i); - bool put_uint64(uint64_t i); + bool + put_uint64(uint64_t i); - bool read_uint16(uint16_t & i); - bool read_uint32(uint32_t & i); + bool + read_uint16(uint16_t& i); + bool + read_uint32(uint32_t& i); - bool read_uint64(uint64_t & i); + bool + read_uint64(uint64_t& i); - size_t read_until(char delim, byte_t* result, size_t resultlen); + size_t + read_until(char delim, byte_t* result, size_t resultlen); /// make a copy of this buffer - std::vector copy() const; + std::vector + copy() const; /// get a read-only view over the entire region - llarp::byte_view_t view_all() const + llarp::byte_view_t + view_all() const { return {base, sz}; } /// get a read-only view over the remaining/unused region - llarp::byte_view_t view_remaining() const + llarp::byte_view_t + view_remaining() const { return {cur, size_left()}; } /// Part of the curse. Returns true if the remaining buffer space starts with the given string /// view. - bool startswith(std::string_view prefix_str) const + bool + startswith(std::string_view prefix_str) const { llarp::byte_view_t prefix{ reinterpret_cast(prefix_str.data()), prefix_str.size()}; @@ -180,7 +279,7 @@ struct /* [[deprecated("this type is stupid, use something else")]] */ llarp_buf private: friend struct ManagedBuffer; llarp_buffer_t(const llarp_buffer_t&) = default; - llarp_buffer_t(llarp_buffer_t &&) = default; + llarp_buffer_t(llarp_buffer_t&&) = default; }; template @@ -233,8 +332,6 @@ struct [[deprecated("deprecated along with llarp_buffer_t")]] ManagedBuffer namespace llarp { - using byte_view_t = std::basic_string_view; - // Wrapper around a std::unique_ptr that owns its own memory and is also implicitly // convertible to a llarp_buffer_t. struct OwnedBuffer From 11e54f65522459612170a738c0533d95ae4b8b7a Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 31 Aug 2023 09:28:02 -0700 Subject: [PATCH 024/312] More message refactoring - routing messages and surrounding code - shim code in place for iteration and optimization after deciding what to do with buffer, string handling, and subsequent function calls --- CMakeLists.txt | 6 +- llarp/CMakeLists.txt | 2 +- llarp/crypto/types.cpp | 2 +- llarp/dht/context.cpp | 1076 ++++++++-------- llarp/dht/localrouterlookup.cpp | 87 +- llarp/dht/localrouterlookup.hpp | 21 +- llarp/dht/localserviceaddresslookup.cpp | 91 +- llarp/dht/localserviceaddresslookup.hpp | 31 +- llarp/dht/localtaglookup.cpp | 59 +- llarp/dht/localtaglookup.hpp | 21 +- llarp/dht/message.cpp | 14 +- llarp/dht/message.hpp | 10 +- llarp/dht/messages/findintro.cpp | 2 +- llarp/dht/messages/findintro.hpp | 3 +- llarp/dht/messages/findname.cpp | 12 +- llarp/dht/messages/findname.hpp | 4 +- llarp/dht/messages/findrouter.cpp | 2 +- llarp/dht/messages/findrouter.hpp | 3 +- llarp/dht/messages/gotintro.cpp | 2 +- llarp/dht/messages/gotintro.hpp | 6 +- llarp/dht/messages/gotname.cpp | 3 +- llarp/dht/messages/gotname.hpp | 4 +- llarp/dht/messages/pubintro.cpp | 2 +- llarp/dht/publishservicejob.cpp | 127 +- llarp/dht/publishservicejob.hpp | 77 +- llarp/dns/srv_data.cpp | 7 +- llarp/dns/srv_data.hpp | 4 +- llarp/exit/endpoint.cpp | 386 +++--- llarp/exit/exit_messages.cpp | 770 +++++------ llarp/exit/exit_messages.hpp | 354 +++-- llarp/exit/policy.cpp | 57 +- llarp/exit/policy.hpp | 43 +- llarp/exit/session.cpp | 623 +++++---- llarp/exit/session.hpp | 8 +- llarp/link/link_manager.cpp | 16 +- llarp/messages/dht_immediate.cpp | 10 + llarp/messages/discard.hpp | 18 +- llarp/messages/link_message_parser.cpp | 2 +- llarp/net/address_info.cpp | 65 +- llarp/net/address_info.hpp | 6 +- llarp/net/exit_info.cpp | 4 +- llarp/net/exit_info.hpp | 4 +- llarp/net/ip_packet.hpp | 12 +- llarp/net/ip_range.cpp | 14 +- llarp/net/ip_range.hpp | 12 +- llarp/net/traffic_policy.cpp | 72 +- llarp/net/traffic_policy.hpp | 10 +- llarp/path/path.cpp | 75 +- llarp/path/path.hpp | 4 +- llarp/path/pathset.cpp | 711 +++++----- llarp/path/transit_hop.cpp | 64 +- llarp/path/transit_hop.hpp | 2 +- llarp/pow.cpp | 18 +- llarp/pow.hpp | 6 +- llarp/router/outbound_message_handler.cpp | 7 + llarp/router/router.cpp | 9 +- llarp/router_contact.cpp | 59 +- llarp/router_contact.hpp | 6 +- llarp/router_version.cpp | 28 +- llarp/router_version.hpp | 9 +- llarp/routing/dht_message.cpp | 68 - llarp/routing/dht_message.hpp | 33 - llarp/routing/handler.hpp | 4 +- llarp/routing/message.hpp | 4 +- llarp/routing/message_parser.cpp | 14 +- llarp/routing/path_confirm_message.cpp | 80 +- llarp/routing/path_confirm_message.hpp | 18 +- llarp/routing/path_dht_message.cpp | 74 ++ llarp/routing/path_dht_message.hpp | 31 + llarp/routing/path_latency_message.cpp | 77 +- llarp/routing/path_latency_message.hpp | 43 +- llarp/routing/path_transfer_message.cpp | 84 +- llarp/routing/path_transfer_message.hpp | 68 +- llarp/routing/transfer_traffic_message.cpp | 108 +- llarp/routing/transfer_traffic_message.hpp | 78 +- llarp/service/async_key_exchange.cpp | 135 +- llarp/service/async_key_exchange.hpp | 61 +- llarp/service/endpoint.cpp | 116 +- llarp/service/endpoint.hpp | 2 +- llarp/service/endpoint_util.hpp | 111 +- .../service/hidden_service_address_lookup.cpp | 89 +- .../service/hidden_service_address_lookup.hpp | 79 +- llarp/service/identity.cpp | 313 +++-- llarp/service/identity.hpp | 87 +- llarp/service/info.cpp | 145 +-- llarp/service/info.hpp | 156 +-- llarp/service/intro.cpp | 128 +- llarp/service/intro.hpp | 150 +-- llarp/service/intro_set.cpp | 151 +-- llarp/service/intro_set.hpp | 292 +++-- llarp/service/outbound_context.cpp | 1138 ++++++++--------- llarp/service/outbound_context.hpp | 2 +- llarp/service/protocol.cpp | 887 +++++++------ llarp/service/protocol.hpp | 92 +- llarp/service/sendcontext.cpp | 274 ++-- llarp/service/sendcontext.hpp | 2 +- llarp/util/aligned.hpp | 8 +- llarp/util/bencode.hpp | 73 +- llarp/util/buffer.hpp | 15 +- 99 files changed, 5223 insertions(+), 5229 deletions(-) delete mode 100644 llarp/routing/dht_message.cpp delete mode 100644 llarp/routing/dht_message.hpp create mode 100644 llarp/routing/path_dht_message.cpp create mode 100644 llarp/routing/path_dht_message.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 246613fa83..eff2b914fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -187,11 +187,7 @@ set(warning_flags -Wall -Wextra -Wno-unknown-pragmas -Wno-unused-function -Werro if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") list(APPEND warning_flags -Wno-unknown-warning-option) endif() -if(WARN_DEPRECATED) - list(APPEND warning_flags -Wdeprecated-declarations) -else() - list(APPEND warning_flags -Wno-deprecated-declarations) -endif() +list(APPEND warning_flags -Wno-deprecated-declarations) # If we blindly add these directly as compile_options then they get passed to swiftc on Apple and # break, so we use a generate expression to set them only for C++/C/ObjC diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index c8b7e18164..aa17e6b928 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -264,7 +264,7 @@ add_library(lokinet-peerstats # routing layer is anonymized over the onion layer add_library(lokinet-layer-routing STATIC - routing/dht_message.cpp + routing/path_dht_message.cpp routing/message_parser.cpp routing/path_confirm_message.cpp routing/path_latency_message.cpp diff --git a/llarp/crypto/types.cpp b/llarp/crypto/types.cpp index 5ed89c79c8..95dea93bb0 100644 --- a/llarp/crypto/types.cpp +++ b/llarp/crypto/types.cpp @@ -91,7 +91,7 @@ namespace llarp { std::string tmp(128, 0); llarp_buffer_t buf(tmp); - if (!BEncode(&buf)) + if (!bt_encode(&buf)) return false; tmp.resize(buf.cur - buf.base); diff --git a/llarp/dht/context.cpp b/llarp/dht/context.cpp index 77097158bd..0f552c8549 100644 --- a/llarp/dht/context.cpp +++ b/llarp/dht/context.cpp @@ -16,651 +16,645 @@ #include #include #include -#include +#include #include #include #include #include #include -namespace llarp +namespace llarp::dht { - namespace dht - { - AbstractContext::~AbstractContext() = default; - - struct Context final : public AbstractContext - { - Context(); - - ~Context() override = default; - - util::StatusObject - ExtractStatus() const override; + AbstractContext::~AbstractContext() = default; - void - StoreRC(const RouterContact rc) const override - { - GetRouter()->rcLookupHandler().CheckRC(rc); - } - - void - LookupIntroSetRelayed( - const Key_t& target, - const Key_t& whoasked, - uint64_t whoaskedTX, - const Key_t& askpeer, - uint64_t relayOrder, - service::EncryptedIntroSetLookupHandler result = nullptr) override; - - void - LookupIntroSetDirect( - const Key_t& target, - const Key_t& whoasked, - uint64_t whoaskedTX, - const Key_t& askpeer, - service::EncryptedIntroSetLookupHandler result = nullptr) override; - - /// on behalf of whoasked request router with public key target from dht - /// router with key askpeer - void - LookupRouterRecursive( - const RouterID& target, - const Key_t& whoasked, - uint64_t whoaskedTX, - const Key_t& askpeer, - RouterLookupHandler result = nullptr) override; - - bool - LookupRouter(const RouterID& target, RouterLookupHandler result) override - { - Key_t askpeer; - if (!_nodes->FindClosest(Key_t(target), askpeer)) - { - return false; - } - LookupRouterRecursive(target, OurKey(), 0, askpeer, result); - return true; - } + struct Context final : public AbstractContext + { + Context(); - bool - HasRouterLookup(const RouterID& target) const override - { - return pendingRouterLookups().HasLookupFor(target); - } + ~Context() override = default; - /// issue dht lookup for router via askpeer and send reply to local path - void - LookupRouterForPath( - const RouterID& target, - uint64_t txid, - const PathID_t& path, - const Key_t& askpeer) override; - - /// issue dht lookup for introset for addr via askpeer and send reply to - /// local path - void - LookupIntroSetForPath( - const Key_t& addr, - uint64_t txid, - const llarp::PathID_t& path, - const Key_t& askpeer, - uint64_t relayOrder) override; - - /// send a dht message to peer, if keepalive is true then keep the session - /// with that peer alive for 10 seconds - void - DHTSendTo(const RouterID& peer, AbstractDHTMessage* msg, bool keepalive = true) override; - - /// get routers closest to target excluding requester - bool - HandleExploritoryRouterLookup( - const Key_t& requester, - uint64_t txid, - const RouterID& target, - std::vector>& reply) override; - - /// handle rc lookup from requester for target - void - LookupRouterRelayed( - const Key_t& requester, - uint64_t txid, - const Key_t& target, - bool recursive, - std::vector>& replies) override; - - /// relay a dht message from a local path to the main network - bool - RelayRequestForPath(const llarp::PathID_t& localPath, const AbstractDHTMessage& msg) override; - - /// send introset to peer as R/S - void - PropagateLocalIntroSet( - const PathID_t& from, - uint64_t txid, - const service::EncryptedIntroSet& introset, - const Key_t& tellpeer, - uint64_t relayOrder) override; - - /// send introset to peer from source with S counter and excluding peers - void - PropagateIntroSetTo( - const Key_t& from, - uint64_t txid, - const service::EncryptedIntroSet& introset, - const Key_t& tellpeer, - uint64_t relayOrder) override; - - /// initialize dht context and explore every exploreInterval milliseconds - void - Init(const Key_t& us, AbstractRouter* router) override; - - /// get localally stored introset by service address - std::optional - GetIntroSetByLocation(const Key_t& location) const override; - - void - handle_cleaner_timer(); - - /// explore dht for new routers - void - Explore(size_t N = 3); - - llarp::AbstractRouter* router{nullptr}; - // for router contacts - std::unique_ptr> _nodes; - - // for introduction sets - std::unique_ptr> _services; - - Bucket* - services() override - { - return _services.get(); - } + util::StatusObject + ExtractStatus() const override; - bool allowTransit{false}; + void + StoreRC(const RouterContact rc) const override + { + GetRouter()->rcLookupHandler().CheckRC(rc); + } - bool& - AllowTransit() override - { - return allowTransit; - } - const bool& - AllowTransit() const override - { - return allowTransit; - } + void + LookupIntroSetRelayed( + const Key_t& target, + const Key_t& whoasked, + uint64_t whoaskedTX, + const Key_t& askpeer, + uint64_t relayOrder, + service::EncryptedIntroSetLookupHandler result = nullptr) override; - Bucket* - Nodes() const override - { - return _nodes.get(); - } + void + LookupIntroSetDirect( + const Key_t& target, + const Key_t& whoasked, + uint64_t whoaskedTX, + const Key_t& askpeer, + service::EncryptedIntroSetLookupHandler result = nullptr) override; - void - PutRCNodeAsync(const RCNode& val) override - { - router->loop()->call([nodes = Nodes(), val] { nodes->PutNode(val); }); - } + /// on behalf of whoasked request router with public key target from dht + /// router with key askpeer + void + LookupRouterRecursive( + const RouterID& target, + const Key_t& whoasked, + uint64_t whoaskedTX, + const Key_t& askpeer, + RouterLookupHandler result = nullptr) override; - void - DelRCNodeAsync(const Key_t& val) override + bool + LookupRouter(const RouterID& target, RouterLookupHandler result) override + { + Key_t askpeer; + if (!_nodes->FindClosest(Key_t(target), askpeer)) { - router->loop()->call([nodes = Nodes(), val] { nodes->DelNode(val); }); + return false; } + LookupRouterRecursive(target, OurKey(), 0, askpeer, result); + return true; + } - const Key_t& - OurKey() const override - { - return ourKey; - } + bool + HasRouterLookup(const RouterID& target) const override + { + return pendingRouterLookups().HasLookupFor(target); + } - llarp::AbstractRouter* - GetRouter() const override - { - return router; - } + /// issue dht lookup for router via askpeer and send reply to local path + void + LookupRouterForPath( + const RouterID& target, uint64_t txid, const PathID_t& path, const Key_t& askpeer) override; - bool - GetRCFromNodeDB(const Key_t& k, llarp::RouterContact& rc) const override - { - if (const auto maybe = router->nodedb()->Get(k.as_array()); maybe.has_value()) - { - rc = *maybe; - return true; - } - return false; - } + /// issue dht lookup for introset for addr via askpeer and send reply to + /// local path + void + LookupIntroSetForPath( + const Key_t& addr, + uint64_t txid, + const llarp::PathID_t& path, + const Key_t& askpeer, + uint64_t relayOrder) override; - PendingIntrosetLookups _pendingIntrosetLookups; - PendingRouterLookups _pendingRouterLookups; - PendingExploreLookups _pendingExploreLookups; + /// send a dht message to peer, if keepalive is true then keep the session + /// with that peer alive for 10 seconds + void + DHTSendTo(const RouterID& peer, AbstractDHTMessage* msg, bool keepalive = true) override; - PendingIntrosetLookups& - pendingIntrosetLookups() override - { - return _pendingIntrosetLookups; - } + /// get routers closest to target excluding requester + bool + HandleExploritoryRouterLookup( + const Key_t& requester, + uint64_t txid, + const RouterID& target, + std::vector>& reply) override; - const PendingIntrosetLookups& - pendingIntrosetLookups() const override - { - return _pendingIntrosetLookups; - } + /// handle rc lookup from requester for target + void + LookupRouterRelayed( + const Key_t& requester, + uint64_t txid, + const Key_t& target, + bool recursive, + std::vector>& replies) override; - PendingRouterLookups& - pendingRouterLookups() override - { - return _pendingRouterLookups; - } + /// relay a dht message from a local path to the main network + bool + RelayRequestForPath(const llarp::PathID_t& localPath, const AbstractDHTMessage& msg) override; - const PendingRouterLookups& - pendingRouterLookups() const override - { - return _pendingRouterLookups; - } + /// send introset to peer as R/S + void + PropagateLocalIntroSet( + const PathID_t& from, + uint64_t txid, + const service::EncryptedIntroSet& introset, + const Key_t& tellpeer, + uint64_t relayOrder) override; - PendingExploreLookups& - pendingExploreLookups() override - { - return _pendingExploreLookups; - } + /// send introset to peer from source with S counter and excluding peers + void + PropagateIntroSetTo( + const Key_t& from, + uint64_t txid, + const service::EncryptedIntroSet& introset, + const Key_t& tellpeer, + uint64_t relayOrder) override; - const PendingExploreLookups& - pendingExploreLookups() const override - { - return _pendingExploreLookups; - } + /// initialize dht context and explore every exploreInterval milliseconds + void + Init(const Key_t& us, AbstractRouter* router) override; - uint64_t - NextID() - { - return ++ids; - } + /// get localally stored introset by service address + std::optional + GetIntroSetByLocation(const Key_t& location) const override; - llarp_time_t - Now() const override; + void + handle_cleaner_timer(); - void - ExploreNetworkVia(const Key_t& peer) override; + /// explore dht for new routers + void + Explore(size_t N = 3); - private: - std::shared_ptr _timer_keepalive; + llarp::AbstractRouter* router{nullptr}; + // for router contacts + std::unique_ptr> _nodes; - void - CleanupTX(); + // for introduction sets + std::unique_ptr> _services; - uint64_t ids; + Bucket* + services() override + { + return _services.get(); + } - Key_t ourKey; - }; + bool allowTransit{false}; - Context::Context() + bool& + AllowTransit() override { - randombytes((byte_t*)&ids, sizeof(uint64_t)); + return allowTransit; } - - void - Context::Explore(size_t N) + const bool& + AllowTransit() const override { - // ask N random peers for new routers - llarp::LogDebug("Exploring network via ", N, " peers"); - std::set peers; + return allowTransit; + } - if (_nodes->GetManyRandom(peers, N)) - { - for (const auto& peer : peers) - ExploreNetworkVia(peer); - } - else - llarp::LogError("failed to select ", N, " random nodes for exploration"); + Bucket* + Nodes() const override + { + return _nodes.get(); } void - Context::ExploreNetworkVia(const Key_t& askpeer) + PutRCNodeAsync(const RCNode& val) override { - uint64_t txid = ++ids; - const TXOwner peer(askpeer, txid); - const TXOwner whoasked(OurKey(), txid); - const RouterID K(askpeer.as_array()); - pendingExploreLookups().NewTX( - peer, whoasked, K, new ExploreNetworkJob(askpeer.as_array(), this)); + router->loop()->call([nodes = Nodes(), val] { nodes->PutNode(val); }); } void - Context::handle_cleaner_timer() + DelRCNodeAsync(const Key_t& val) override { - // clean up transactions - CleanupTX(); - const llarp_time_t now = Now(); + router->loop()->call([nodes = Nodes(), val] { nodes->DelNode(val); }); + } - if (_nodes) - { - // expire router contacts in memory - auto& nodes = _nodes->nodes; - auto itr = nodes.begin(); - while (itr != nodes.end()) - { - if (itr->second.rc.IsExpired(now)) - { - itr = nodes.erase(itr); - } - else - ++itr; - } - } + const Key_t& + OurKey() const override + { + return ourKey; + } - if (_services) - { - // expire intro sets - auto& nodes = _services->nodes; - auto itr = nodes.begin(); - while (itr != nodes.end()) - { - if (itr->second.introset.IsExpired(now)) - { - itr = nodes.erase(itr); - } - else - ++itr; - } - } + llarp::AbstractRouter* + GetRouter() const override + { + return router; } - void - Context::LookupRouterRelayed( - const Key_t& requester, - uint64_t txid, - const Key_t& target, - bool recursive, - std::vector>& replies) + bool + GetRCFromNodeDB(const Key_t& k, llarp::RouterContact& rc) const override { - if (target == ourKey) - { - // we are the target, give them our RC - replies.emplace_back(new GotRouterMessage(requester, txid, {router->rc()}, false)); - return; - } - if (not GetRouter()->SessionToRouterAllowed(target.as_array())) - { - // explicitly not allowed - replies.emplace_back(new GotRouterMessage(requester, txid, {}, false)); - return; - } - const auto rc = GetRouter()->nodedb()->FindClosestTo(target); - const Key_t next(rc.pubkey); + if (const auto maybe = router->nodedb()->Get(k.as_array()); maybe.has_value()) { - if (next == target) - { - // we know the target - if (rc.ExpiresSoon(llarp::time_now_ms())) - { - // ask target for their rc to keep it updated - LookupRouterRecursive(target.as_array(), requester, txid, next); - } - else - { - // send reply with rc we know of - replies.emplace_back(new GotRouterMessage(requester, txid, {rc}, false)); - } - } - else if (recursive) // are we doing a recursive lookup? - { - // is the next peer we ask closer to the target than us? - if ((next ^ target) < (ourKey ^ target)) - { - // yes it is closer, ask neighbour recursively - LookupRouterRecursive(target.as_array(), requester, txid, next); - } - else - { - // no we are closer to the target so tell requester it's not there - // so they switch to iterative lookup - replies.emplace_back(new GotRouterMessage(requester, txid, {}, false)); - } - } - else - { - // iterative lookup and we don't have it tell them who is closer - replies.emplace_back(new GotRouterMessage(requester, next, txid, false)); - } + rc = *maybe; + return true; } + return false; } - std::optional - Context::GetIntroSetByLocation(const Key_t& key) const + PendingIntrosetLookups _pendingIntrosetLookups; + PendingRouterLookups _pendingRouterLookups; + PendingExploreLookups _pendingExploreLookups; + + PendingIntrosetLookups& + pendingIntrosetLookups() override { - auto itr = _services->nodes.find(key); - if (itr == _services->nodes.end()) - return {}; - return itr->second.introset; + return _pendingIntrosetLookups; } - void - Context::CleanupTX() + const PendingIntrosetLookups& + pendingIntrosetLookups() const override { - auto now = Now(); - llarp::LogTrace("DHT tick"); - - pendingRouterLookups().Expire(now); - _pendingIntrosetLookups.Expire(now); - pendingExploreLookups().Expire(now); + return _pendingIntrosetLookups; } - util::StatusObject - Context::ExtractStatus() const + PendingRouterLookups& + pendingRouterLookups() override { - util::StatusObject obj{ - {"pendingRouterLookups", pendingRouterLookups().ExtractStatus()}, - {"pendingIntrosetLookups", _pendingIntrosetLookups.ExtractStatus()}, - {"pendingExploreLookups", pendingExploreLookups().ExtractStatus()}, - {"nodes", _nodes->ExtractStatus()}, - {"services", _services->ExtractStatus()}, - {"ourKey", ourKey.ToHex()}}; - return obj; + return _pendingRouterLookups; } - void - Context::Init(const Key_t& us, AbstractRouter* r) + const PendingRouterLookups& + pendingRouterLookups() const override { - router = r; - ourKey = us; - _nodes = std::make_unique>(ourKey, llarp::randint); - _services = std::make_unique>(ourKey, llarp::randint); - llarp::LogDebug("initialize dht with key ", ourKey); - // start cleanup timer - _timer_keepalive = std::make_shared(0); - router->loop()->call_every(1s, _timer_keepalive, [this] { handle_cleaner_timer(); }); + return _pendingRouterLookups; } - void - Context::DHTSendTo(const RouterID& peer, AbstractDHTMessage* msg, bool) + PendingExploreLookups& + pendingExploreLookups() override { - DHTImmediateMessage m; - m.msgs.emplace_back(msg); - router->SendToOrQueue(peer, m); - auto now = Now(); - router->PersistSessionUntil(peer, now + 1min); + return _pendingExploreLookups; } - // this function handles incoming DHT messages sent down a path by a client - // note that IMessage here is different than that found in the routing - // namespace. by the time this is called, we are inside - // llarp::routing::DHTMessage::HandleMessage() - bool - Context::RelayRequestForPath(const llarp::PathID_t& id, const AbstractDHTMessage& msg) + const PendingExploreLookups& + pendingExploreLookups() const override { - routing::DHTMessage reply; - if (!msg.handle_message(router->dht(), reply.M)) - return false; - if (not reply.M.empty()) - { - auto path = router->pathContext().GetByUpstream(router->pubkey(), id); - return path && path->SendRoutingMessage(reply, router); - } - return true; + return _pendingExploreLookups; } - void - Context::LookupIntroSetForPath( - const Key_t& addr, - uint64_t txid, - const llarp::PathID_t& path, - const Key_t& askpeer, - uint64_t relayOrder) + uint64_t + NextID() { - const TXOwner asker(OurKey(), txid); - const TXOwner peer(askpeer, ++ids); - _pendingIntrosetLookups.NewTX( - peer, - asker, - asker, - new LocalServiceAddressLookup(path, txid, relayOrder, addr, this, askpeer)); + return ++ids; } + llarp_time_t + Now() const override; + void - Context::PropagateIntroSetTo( - const Key_t& from, - uint64_t txid, - const service::EncryptedIntroSet& introset, - const Key_t& tellpeer, - uint64_t relayOrder) - { - const TXOwner asker(from, txid); - const TXOwner peer(tellpeer, ++ids); - _pendingIntrosetLookups.NewTX( - peer, asker, asker, new PublishServiceJob(asker, introset, this, relayOrder)); - } + ExploreNetworkVia(const Key_t& peer) override; + + private: + std::shared_ptr _timer_keepalive; void - Context::PropagateLocalIntroSet( - const PathID_t& from, - uint64_t txid, - const service::EncryptedIntroSet& introset, - const Key_t& tellpeer, - uint64_t relayOrder) + CleanupTX(); + + uint64_t ids; + + Key_t ourKey; + }; + + Context::Context() + { + randombytes((byte_t*)&ids, sizeof(uint64_t)); + } + + void + Context::Explore(size_t N) + { + // ask N random peers for new routers + llarp::LogDebug("Exploring network via ", N, " peers"); + std::set peers; + + if (_nodes->GetManyRandom(peers, N)) { - const TXOwner asker(OurKey(), txid); - const TXOwner peer(tellpeer, ++ids); - _pendingIntrosetLookups.NewTX( - peer, - asker, - peer, - new LocalPublishServiceJob(peer, from, txid, introset, this, relayOrder)); + for (const auto& peer : peers) + ExploreNetworkVia(peer); } + else + llarp::LogError("failed to select ", N, " random nodes for exploration"); + } - void - Context::LookupIntroSetRelayed( - const Key_t& addr, - const Key_t& whoasked, - uint64_t txid, - const Key_t& askpeer, - uint64_t relayOrder, - service::EncryptedIntroSetLookupHandler handler) + void + Context::ExploreNetworkVia(const Key_t& askpeer) + { + uint64_t txid = ++ids; + const TXOwner peer(askpeer, txid); + const TXOwner whoasked(OurKey(), txid); + const RouterID K(askpeer.as_array()); + pendingExploreLookups().NewTX( + peer, whoasked, K, new ExploreNetworkJob(askpeer.as_array(), this)); + } + + void + Context::handle_cleaner_timer() + { + // clean up transactions + CleanupTX(); + const llarp_time_t now = Now(); + + if (_nodes) { - const TXOwner asker(whoasked, txid); - const TXOwner peer(askpeer, ++ids); - _pendingIntrosetLookups.NewTX( - peer, asker, asker, new ServiceAddressLookup(asker, addr, this, relayOrder, handler)); + // expire router contacts in memory + auto& nodes = _nodes->nodes; + auto itr = nodes.begin(); + while (itr != nodes.end()) + { + if (itr->second.rc.IsExpired(now)) + { + itr = nodes.erase(itr); + } + else + ++itr; + } } - void - Context::LookupIntroSetDirect( - const Key_t& addr, - const Key_t& whoasked, - uint64_t txid, - const Key_t& askpeer, - service::EncryptedIntroSetLookupHandler handler) + if (_services) { - const TXOwner asker(whoasked, txid); - const TXOwner peer(askpeer, ++ids); - _pendingIntrosetLookups.NewTX( - peer, asker, asker, new ServiceAddressLookup(asker, addr, this, 0, handler), 1s); + // expire intro sets + auto& nodes = _services->nodes; + auto itr = nodes.begin(); + while (itr != nodes.end()) + { + if (itr->second.introset.IsExpired(now)) + { + itr = nodes.erase(itr); + } + else + ++itr; + } } - - bool - Context::HandleExploritoryRouterLookup( - const Key_t& requester, - uint64_t txid, - const RouterID& target, - std::vector>& reply) + } + + void + Context::LookupRouterRelayed( + const Key_t& requester, + uint64_t txid, + const Key_t& target, + bool recursive, + std::vector>& replies) + { + if (target == ourKey) { - std::vector closer; - const Key_t t(target.as_array()); - std::set foundRouters; - if (!_nodes) - return false; - - const size_t nodeCount = _nodes->size(); - if (nodeCount == 0) + // we are the target, give them our RC + replies.emplace_back(new GotRouterMessage(requester, txid, {router->rc()}, false)); + return; + } + if (not GetRouter()->SessionToRouterAllowed(target.as_array())) + { + // explicitly not allowed + replies.emplace_back(new GotRouterMessage(requester, txid, {}, false)); + return; + } + const auto rc = GetRouter()->nodedb()->FindClosestTo(target); + const Key_t next(rc.pubkey); + { + if (next == target) { - llarp::LogError("cannot handle exploritory router lookup, no dht peers"); - return false; + // we know the target + if (rc.ExpiresSoon(llarp::time_now_ms())) + { + // ask target for their rc to keep it updated + LookupRouterRecursive(target.as_array(), requester, txid, next); + } + else + { + // send reply with rc we know of + replies.emplace_back(new GotRouterMessage(requester, txid, {rc}, false)); + } } - llarp::LogDebug("We have ", _nodes->size(), " connected nodes into the DHT"); - // ourKey should never be in the connected list - // requester is likely in the connected list - // 4 or connection nodes (minus a potential requestor), whatever is less - if (!_nodes->GetManyNearExcluding( - t, foundRouters, std::min(nodeCount, size_t{4}), std::set{ourKey, requester})) + else if (recursive) // are we doing a recursive lookup? { - llarp::LogError( - "not enough dht nodes to handle exploritory router lookup, " - "have ", - nodeCount, - " dht peers"); - return false; + // is the next peer we ask closer to the target than us? + if ((next ^ target) < (ourKey ^ target)) + { + // yes it is closer, ask neighbour recursively + LookupRouterRecursive(target.as_array(), requester, txid, next); + } + else + { + // no we are closer to the target so tell requester it's not there + // so they switch to iterative lookup + replies.emplace_back(new GotRouterMessage(requester, txid, {}, false)); + } } - for (const auto& f : foundRouters) + else { - const RouterID id = f.as_array(); - // discard shit routers - if (router->routerProfiling().IsBadForConnect(id)) - continue; - closer.emplace_back(id); + // iterative lookup and we don't have it tell them who is closer + replies.emplace_back(new GotRouterMessage(requester, next, txid, false)); } - llarp::LogDebug("Gave ", closer.size(), " routers for exploration"); - reply.emplace_back(new GotRouterMessage(txid, closer, false)); - return true; } + } - void - Context::LookupRouterForPath( - const RouterID& target, uint64_t txid, const llarp::PathID_t& path, const Key_t& askpeer) + std::optional + Context::GetIntroSetByLocation(const Key_t& key) const + { + auto itr = _services->nodes.find(key); + if (itr == _services->nodes.end()) + return {}; + return itr->second.introset; + } + + void + Context::CleanupTX() + { + auto now = Now(); + llarp::LogTrace("DHT tick"); + + pendingRouterLookups().Expire(now); + _pendingIntrosetLookups.Expire(now); + pendingExploreLookups().Expire(now); + } + util::StatusObject + Context::ExtractStatus() const + { + util::StatusObject obj{ + {"pendingRouterLookups", pendingRouterLookups().ExtractStatus()}, + {"pendingIntrosetLookups", _pendingIntrosetLookups.ExtractStatus()}, + {"pendingExploreLookups", pendingExploreLookups().ExtractStatus()}, + {"nodes", _nodes->ExtractStatus()}, + {"services", _services->ExtractStatus()}, + {"ourKey", ourKey.ToHex()}}; + return obj; + } + + void + Context::Init(const Key_t& us, AbstractRouter* r) + { + router = r; + ourKey = us; + _nodes = std::make_unique>(ourKey, llarp::randint); + _services = std::make_unique>(ourKey, llarp::randint); + llarp::LogDebug("initialize dht with key ", ourKey); + // start cleanup timer + _timer_keepalive = std::make_shared(0); + router->loop()->call_every(1s, _timer_keepalive, [this] { handle_cleaner_timer(); }); + } + + void + Context::DHTSendTo(const RouterID& peer, AbstractDHTMessage* msg, bool) + { + DHTImmediateMessage m; + m.msgs.emplace_back(msg); + router->SendToOrQueue(peer, m); + auto now = Now(); + router->PersistSessionUntil(peer, now + 1min); + } + + // this function handles incoming DHT messages sent down a path by a client + // note that IMessage here is different than that found in the routing + // namespace. by the time this is called, we are inside + // llarp::routing::DHTMessage::HandleMessage() + bool + Context::RelayRequestForPath(const llarp::PathID_t& id, const AbstractDHTMessage& msg) + { + routing::PathDHTMessage reply; + if (!msg.handle_message(router->dht(), reply.dht_msgs)) + return false; + if (not reply.dht_msgs.empty()) { - const TXOwner peer(askpeer, ++ids); - const TXOwner whoasked(OurKey(), txid); - _pendingRouterLookups.NewTX( - peer, whoasked, target, new LocalRouterLookup(path, txid, target, this)); + auto path = router->pathContext().GetByUpstream(router->pubkey(), id); + return path && path->SendRoutingMessage(reply, router); } - - void - Context::LookupRouterRecursive( - const RouterID& target, - const Key_t& whoasked, - uint64_t txid, - const Key_t& askpeer, - RouterLookupHandler handler) + return true; + } + + void + Context::LookupIntroSetForPath( + const Key_t& addr, + uint64_t txid, + const llarp::PathID_t& path, + const Key_t& askpeer, + uint64_t relayOrder) + { + const TXOwner asker(OurKey(), txid); + const TXOwner peer(askpeer, ++ids); + _pendingIntrosetLookups.NewTX( + peer, + asker, + asker, + new LocalServiceAddressLookup(path, txid, relayOrder, addr, this, askpeer)); + } + + void + Context::PropagateIntroSetTo( + const Key_t& from, + uint64_t txid, + const service::EncryptedIntroSet& introset, + const Key_t& tellpeer, + uint64_t relayOrder) + { + const TXOwner asker(from, txid); + const TXOwner peer(tellpeer, ++ids); + _pendingIntrosetLookups.NewTX( + peer, asker, asker, new PublishServiceJob(asker, introset, this, relayOrder)); + } + + void + Context::PropagateLocalIntroSet( + const PathID_t& from, + uint64_t txid, + const service::EncryptedIntroSet& introset, + const Key_t& tellpeer, + uint64_t relayOrder) + { + const TXOwner asker(OurKey(), txid); + const TXOwner peer(tellpeer, ++ids); + _pendingIntrosetLookups.NewTX( + peer, + asker, + peer, + new LocalPublishServiceJob(peer, from, txid, introset, this, relayOrder)); + } + + void + Context::LookupIntroSetRelayed( + const Key_t& addr, + const Key_t& whoasked, + uint64_t txid, + const Key_t& askpeer, + uint64_t relayOrder, + service::EncryptedIntroSetLookupHandler handler) + { + const TXOwner asker(whoasked, txid); + const TXOwner peer(askpeer, ++ids); + _pendingIntrosetLookups.NewTX( + peer, asker, asker, new ServiceAddressLookup(asker, addr, this, relayOrder, handler)); + } + + void + Context::LookupIntroSetDirect( + const Key_t& addr, + const Key_t& whoasked, + uint64_t txid, + const Key_t& askpeer, + service::EncryptedIntroSetLookupHandler handler) + { + const TXOwner asker(whoasked, txid); + const TXOwner peer(askpeer, ++ids); + _pendingIntrosetLookups.NewTX( + peer, asker, asker, new ServiceAddressLookup(asker, addr, this, 0, handler), 1s); + } + + bool + Context::HandleExploritoryRouterLookup( + const Key_t& requester, + uint64_t txid, + const RouterID& target, + std::vector>& reply) + { + std::vector closer; + const Key_t t(target.as_array()); + std::set foundRouters; + if (!_nodes) + return false; + + const size_t nodeCount = _nodes->size(); + if (nodeCount == 0) { - const TXOwner asker(whoasked, txid); - const TXOwner peer(askpeer, ++ids); - _pendingRouterLookups.NewTX( - peer, asker, target, new RecursiveRouterLookup(asker, target, this, handler)); + llarp::LogError("cannot handle exploritory router lookup, no dht peers"); + return false; } - - llarp_time_t - Context::Now() const + llarp::LogDebug("We have ", _nodes->size(), " connected nodes into the DHT"); + // ourKey should never be in the connected list + // requester is likely in the connected list + // 4 or connection nodes (minus a potential requestor), whatever is less + if (!_nodes->GetManyNearExcluding( + t, foundRouters, std::min(nodeCount, size_t{4}), std::set{ourKey, requester})) { - return router->Now(); + llarp::LogError( + "not enough dht nodes to handle exploritory router lookup, " + "have ", + nodeCount, + " dht peers"); + return false; } - - std::unique_ptr - makeContext() + for (const auto& f : foundRouters) { - return std::make_unique(); + const RouterID id = f.as_array(); + // discard shit routers + if (router->routerProfiling().IsBadForConnect(id)) + continue; + closer.emplace_back(id); } + llarp::LogDebug("Gave ", closer.size(), " routers for exploration"); + reply.emplace_back(new GotRouterMessage(txid, closer, false)); + return true; + } + + void + Context::LookupRouterForPath( + const RouterID& target, uint64_t txid, const llarp::PathID_t& path, const Key_t& askpeer) + + { + const TXOwner peer(askpeer, ++ids); + const TXOwner whoasked(OurKey(), txid); + _pendingRouterLookups.NewTX( + peer, whoasked, target, new LocalRouterLookup(path, txid, target, this)); + } + + void + Context::LookupRouterRecursive( + const RouterID& target, + const Key_t& whoasked, + uint64_t txid, + const Key_t& askpeer, + RouterLookupHandler handler) + { + const TXOwner asker(whoasked, txid); + const TXOwner peer(askpeer, ++ids); + _pendingRouterLookups.NewTX( + peer, asker, target, new RecursiveRouterLookup(asker, target, this, handler)); + } + + llarp_time_t + Context::Now() const + { + return router->Now(); + } + + std::unique_ptr + makeContext() + { + return std::make_unique(); + } - } // namespace dht -} // namespace llarp +} // namespace llarp::dht diff --git a/llarp/dht/localrouterlookup.cpp b/llarp/dht/localrouterlookup.cpp index a70edd9238..0e82b24627 100644 --- a/llarp/dht/localrouterlookup.cpp +++ b/llarp/dht/localrouterlookup.cpp @@ -5,60 +5,57 @@ #include #include -#include +#include #include -namespace llarp +namespace llarp::dht { - namespace dht - { - LocalRouterLookup::LocalRouterLookup( - const PathID_t& path, uint64_t txid, const RouterID& _target, AbstractContext* ctx) - : RecursiveRouterLookup(TXOwner{ctx->OurKey(), txid}, _target, ctx, nullptr) - , localPath(path) - {} + LocalRouterLookup::LocalRouterLookup( + const PathID_t& path, uint64_t txid, const RouterID& _target, AbstractContext* ctx) + : RecursiveRouterLookup(TXOwner{ctx->OurKey(), txid}, _target, ctx, nullptr), localPath(path) + {} - void - LocalRouterLookup::SendReply() + void + LocalRouterLookup::SendReply() + { + auto path = + parent->GetRouter()->pathContext().GetByUpstream(parent->OurKey().as_array(), localPath); + if (!path) + { + llarp::LogWarn( + "did not send reply for relayed dht request, no such local path " + "for pathid=", + localPath); + return; + } + if (valuesFound.size()) { - auto path = - parent->GetRouter()->pathContext().GetByUpstream(parent->OurKey().as_array(), localPath); - if (!path) + RouterContact found; + for (const auto& rc : valuesFound) { - llarp::LogWarn( - "did not send reply for relayed dht request, no such local path " - "for pathid=", - localPath); - return; + if (rc.OtherIsNewer(found)) + found = rc; } - if (valuesFound.size()) + valuesFound.clear(); + if (not found.pubkey.IsZero()) { - RouterContact found; - for (const auto& rc : valuesFound) - { - if (rc.OtherIsNewer(found)) - found = rc; - } - valuesFound.clear(); - if (not found.pubkey.IsZero()) - { - valuesFound.resize(1); - valuesFound[0] = found; - } - else - { - llarp::LogWarn("We found a null RC for dht request, dropping it"); - } + valuesFound.resize(1); + valuesFound[0] = found; } - routing::DHTMessage msg; - msg.M.emplace_back(new GotRouterMessage(parent->OurKey(), whoasked.txid, valuesFound, true)); - if (!path->SendRoutingMessage(msg, parent->GetRouter())) + else { - llarp::LogWarn( - "failed to send routing message when informing result of dht " - "request, pathid=", - localPath); + llarp::LogWarn("We found a null RC for dht request, dropping it"); } } - } // namespace dht -} // namespace llarp + routing::PathDHTMessage msg; + msg.dht_msgs.emplace_back( + new GotRouterMessage(parent->OurKey(), whoasked.txid, valuesFound, true)); + if (!path->SendRoutingMessage(msg, parent->GetRouter())) + { + llarp::LogWarn( + "failed to send routing message when informing result of dht " + "request, pathid=", + localPath); + } + } +} // namespace llarp::dht diff --git a/llarp/dht/localrouterlookup.hpp b/llarp/dht/localrouterlookup.hpp index f2532b2013..282e954d81 100644 --- a/llarp/dht/localrouterlookup.hpp +++ b/llarp/dht/localrouterlookup.hpp @@ -7,21 +7,18 @@ #include #include -namespace llarp +namespace llarp::dht { - namespace dht + struct LocalRouterLookup : public RecursiveRouterLookup { - struct LocalRouterLookup : public RecursiveRouterLookup - { - PathID_t localPath; + PathID_t localPath; - LocalRouterLookup( - const PathID_t& path, uint64_t txid, const RouterID& target, AbstractContext* ctx); + LocalRouterLookup( + const PathID_t& path, uint64_t txid, const RouterID& target, AbstractContext* ctx); - void - SendReply() override; - }; - } // namespace dht -} // namespace llarp + void + SendReply() override; + }; +} // namespace llarp::dht #endif diff --git a/llarp/dht/localserviceaddresslookup.cpp b/llarp/dht/localserviceaddresslookup.cpp index 177294cf48..eda075a524 100644 --- a/llarp/dht/localserviceaddresslookup.cpp +++ b/llarp/dht/localserviceaddresslookup.cpp @@ -4,58 +4,55 @@ #include #include #include -#include +#include #include -namespace llarp +namespace llarp::dht { - namespace dht - { - LocalServiceAddressLookup::LocalServiceAddressLookup( - const PathID_t& pathid, - uint64_t txid, - uint64_t relayOrder, - const Key_t& addr, - AbstractContext* ctx, - [[maybe_unused]] const Key_t& askpeer) - : ServiceAddressLookup(TXOwner{ctx->OurKey(), txid}, addr, ctx, relayOrder, nullptr) - , localPath(pathid) - {} + LocalServiceAddressLookup::LocalServiceAddressLookup( + const PathID_t& pathid, + uint64_t txid, + uint64_t relayOrder, + const Key_t& addr, + AbstractContext* ctx, + [[maybe_unused]] const Key_t& askpeer) + : ServiceAddressLookup(TXOwner{ctx->OurKey(), txid}, addr, ctx, relayOrder, nullptr) + , localPath(pathid) + {} - void - LocalServiceAddressLookup::SendReply() + void + LocalServiceAddressLookup::SendReply() + { + auto path = + parent->GetRouter()->pathContext().GetByUpstream(parent->OurKey().as_array(), localPath); + if (!path) { - auto path = - parent->GetRouter()->pathContext().GetByUpstream(parent->OurKey().as_array(), localPath); - if (!path) - { - llarp::LogWarn( - "did not send reply for relayed dht request, no such local path " - "for pathid=", - localPath); - return; - } - // pick newest if we have more than 1 result - if (valuesFound.size()) - { - service::EncryptedIntroSet found; - for (const auto& introset : valuesFound) - { - if (found.OtherIsNewer(introset)) - found = introset; - } - valuesFound.clear(); - valuesFound.emplace_back(found); - } - routing::DHTMessage msg; - msg.M.emplace_back(new GotIntroMessage(valuesFound, whoasked.txid)); - if (!path->SendRoutingMessage(msg, parent->GetRouter())) + llarp::LogWarn( + "did not send reply for relayed dht request, no such local path " + "for pathid=", + localPath); + return; + } + // pick newest if we have more than 1 result + if (valuesFound.size()) + { + service::EncryptedIntroSet found; + for (const auto& introset : valuesFound) { - llarp::LogWarn( - "failed to send routing message when informing result of dht " - "request, pathid=", - localPath); + if (found.OtherIsNewer(introset)) + found = introset; } + valuesFound.clear(); + valuesFound.emplace_back(found); + } + routing::PathDHTMessage msg; + msg.dht_msgs.emplace_back(new GotIntroMessage(valuesFound, whoasked.txid)); + if (!path->SendRoutingMessage(msg, parent->GetRouter())) + { + llarp::LogWarn( + "failed to send routing message when informing result of dht " + "request, pathid=", + localPath); } - } // namespace dht -} // namespace llarp + } +} // namespace llarp::dht diff --git a/llarp/dht/localserviceaddresslookup.hpp b/llarp/dht/localserviceaddresslookup.hpp index c25755566e..272a22ae24 100644 --- a/llarp/dht/localserviceaddresslookup.hpp +++ b/llarp/dht/localserviceaddresslookup.hpp @@ -5,27 +5,24 @@ #include -namespace llarp +namespace llarp::dht { - namespace dht + struct LocalServiceAddressLookup : public ServiceAddressLookup { - struct LocalServiceAddressLookup : public ServiceAddressLookup - { - PathID_t localPath; + PathID_t localPath; - LocalServiceAddressLookup( - const PathID_t& pathid, - uint64_t txid, - uint64_t relayOrder, - const Key_t& addr, - AbstractContext* ctx, - [[maybe_unused]] const Key_t& askpeer); + LocalServiceAddressLookup( + const PathID_t& pathid, + uint64_t txid, + uint64_t relayOrder, + const Key_t& addr, + AbstractContext* ctx, + [[maybe_unused]] const Key_t& askpeer); - void - SendReply() override; - }; + void + SendReply() override; + }; - } // namespace dht -} // namespace llarp +} // namespace llarp::dht #endif diff --git a/llarp/dht/localtaglookup.cpp b/llarp/dht/localtaglookup.cpp index a4bc88b68b..ca7cbe843a 100644 --- a/llarp/dht/localtaglookup.cpp +++ b/llarp/dht/localtaglookup.cpp @@ -4,39 +4,36 @@ #include #include #include -#include +#include -namespace llarp +namespace llarp::dht { - namespace dht - { - LocalTagLookup::LocalTagLookup( - const PathID_t& path, uint64_t txid, const service::Tag& _target, AbstractContext* ctx) - : TagLookup(TXOwner{ctx->OurKey(), txid}, _target, ctx, 0), localPath(path) - {} + LocalTagLookup::LocalTagLookup( + const PathID_t& path, uint64_t txid, const service::Tag& _target, AbstractContext* ctx) + : TagLookup(TXOwner{ctx->OurKey(), txid}, _target, ctx, 0), localPath(path) + {} - void - LocalTagLookup::SendReply() + void + LocalTagLookup::SendReply() + { + auto path = + parent->GetRouter()->pathContext().GetByUpstream(parent->OurKey().as_array(), localPath); + if (!path) + { + llarp::LogWarn( + "did not send reply for relayed dht request, no such local path " + "for pathid=", + localPath); + return; + } + routing::PathDHTMessage msg; + msg.dht_msgs.emplace_back(new GotIntroMessage(valuesFound, whoasked.txid)); + if (!path->SendRoutingMessage(msg, parent->GetRouter())) { - auto path = - parent->GetRouter()->pathContext().GetByUpstream(parent->OurKey().as_array(), localPath); - if (!path) - { - llarp::LogWarn( - "did not send reply for relayed dht request, no such local path " - "for pathid=", - localPath); - return; - } - routing::DHTMessage msg; - msg.M.emplace_back(new GotIntroMessage(valuesFound, whoasked.txid)); - if (!path->SendRoutingMessage(msg, parent->GetRouter())) - { - llarp::LogWarn( - "failed to send routing message when informing result of dht " - "request, pathid=", - localPath); - } + llarp::LogWarn( + "failed to send routing message when informing result of dht " + "request, pathid=", + localPath); } - } // namespace dht -} // namespace llarp + } +} // namespace llarp::dht diff --git a/llarp/dht/localtaglookup.hpp b/llarp/dht/localtaglookup.hpp index 728487477d..cb96c9f256 100644 --- a/llarp/dht/localtaglookup.hpp +++ b/llarp/dht/localtaglookup.hpp @@ -3,21 +3,18 @@ #include "taglookup.hpp" -namespace llarp +namespace llarp::dht { - namespace dht + struct LocalTagLookup : public TagLookup { - struct LocalTagLookup : public TagLookup - { - PathID_t localPath; + PathID_t localPath; - LocalTagLookup( - const PathID_t& path, uint64_t txid, const service::Tag& target, AbstractContext* ctx); + LocalTagLookup( + const PathID_t& path, uint64_t txid, const service::Tag& target, AbstractContext* ctx); - void - SendReply() override; - }; - } // namespace dht -} // namespace llarp + void + SendReply() override; + }; +} // namespace llarp::dht #endif diff --git a/llarp/dht/message.cpp b/llarp/dht/message.cpp index b4ad730668..b11ee145c3 100644 --- a/llarp/dht/message.cpp +++ b/llarp/dht/message.cpp @@ -16,7 +16,7 @@ namespace llarp::dht struct MessageDecoder { const Key_t& From; - AbstractDHTMessage::Ptr_t msg; + std::unique_ptr msg; bool firstKey = true; bool relayed = false; @@ -88,7 +88,7 @@ namespace llarp::dht } }; - AbstractDHTMessage::Ptr_t + std::unique_ptr DecodeMessage(const Key_t& from, llarp_buffer_t* buf, bool relayed) { MessageDecoder dec(from, relayed); @@ -100,13 +100,14 @@ namespace llarp::dht struct ListDecoder { - ListDecoder(bool hasRelayed, const Key_t& from, std::vector& list) + ListDecoder( + bool hasRelayed, const Key_t& from, std::vector>& list) : relayed(hasRelayed), From(from), l(list) {} bool relayed; const Key_t& From; - std::vector& l; + std::vector>& l; bool operator()(llarp_buffer_t* buffer, bool has) @@ -126,7 +127,10 @@ namespace llarp::dht bool DecodeMessageList( - Key_t from, llarp_buffer_t* buf, std::vector& list, bool relayed) + Key_t from, + llarp_buffer_t* buf, + std::vector>& list, + bool relayed) { ListDecoder dec(relayed, from, list); return bencode_read_list(dec, buf); diff --git a/llarp/dht/message.hpp b/llarp/dht/message.hpp index 1017203c0a..1c06bc7201 100644 --- a/llarp/dht/message.hpp +++ b/llarp/dht/message.hpp @@ -25,10 +25,10 @@ namespace llarp::dht AbstractDHTMessage(const Key_t& from) : From(from) {} - using Ptr_t = std::unique_ptr; - virtual bool - handle_message(struct llarp_dht_context* dht, std::vector& replies) const = 0; + handle_message( + struct llarp_dht_context* dht, + std::vector>& replies) const = 0; void bt_encode(oxenc::bt_dict_producer& btdp) const override = 0; @@ -58,14 +58,14 @@ namespace llarp::dht uint64_t version = llarp::constants::proto_version; }; - AbstractDHTMessage::Ptr_t + std::unique_ptr DecodeMessage(const Key_t& from, llarp_buffer_t* buf, bool relayed = false); bool DecodeMessageList( Key_t from, llarp_buffer_t* buf, - std::vector& list, + std::vector>& list, bool relayed = false); } // namespace llarp::dht diff --git a/llarp/dht/messages/findintro.cpp b/llarp/dht/messages/findintro.cpp index 5eb628a3f7..be5673f67f 100644 --- a/llarp/dht/messages/findintro.cpp +++ b/llarp/dht/messages/findintro.cpp @@ -60,7 +60,7 @@ namespace llarp::dht bool FindIntroMessage::handle_message( - llarp_dht_context* ctx, std::vector& replies) const + llarp_dht_context* ctx, std::vector>& replies) const { auto& dht = *ctx->impl; if (dht.pendingIntrosetLookups().HasPendingLookupFrom(TXOwner{From, txID})) diff --git a/llarp/dht/messages/findintro.hpp b/llarp/dht/messages/findintro.hpp index bfa0fac21a..116e2d188d 100644 --- a/llarp/dht/messages/findintro.hpp +++ b/llarp/dht/messages/findintro.hpp @@ -41,6 +41,7 @@ namespace llarp::dht bool handle_message( - llarp_dht_context* ctx, std::vector& replies) const override; + llarp_dht_context* ctx, + std::vector>& replies) const override; }; } // namespace llarp::dht diff --git a/llarp/dht/messages/findname.cpp b/llarp/dht/messages/findname.cpp index 4986af2bd4..f6681abaeb 100644 --- a/llarp/dht/messages/findname.cpp +++ b/llarp/dht/messages/findname.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include namespace llarp::dht { @@ -43,7 +43,9 @@ namespace llarp::dht } bool - FindNameMessage::handle_message(struct llarp_dht_context* dht, std::vector& replies) const + FindNameMessage::handle_message( + struct llarp_dht_context* dht, + std::vector>& replies) const { (void)replies; auto r = dht->impl->GetRouter(); @@ -53,14 +55,14 @@ namespace llarp::dht auto path = r->pathContext().GetPathForTransfer(pathID); if (path == nullptr) return; - routing::DHTMessage msg; + routing::PathDHTMessage msg; if (maybe.has_value()) { - msg.M.emplace_back(new GotNameMessage(dht::Key_t{}, TxID, *maybe)); + msg.dht_msgs.emplace_back(new GotNameMessage(dht::Key_t{}, TxID, *maybe)); } else { - msg.M.emplace_back(new GotNameMessage(dht::Key_t{}, TxID, service::EncryptedName{})); + msg.dht_msgs.emplace_back(new GotNameMessage(dht::Key_t{}, TxID, service::EncryptedName{})); } path->SendRoutingMessage(msg, r); }); diff --git a/llarp/dht/messages/findname.hpp b/llarp/dht/messages/findname.hpp index ee29365cc0..05c8e49b8a 100644 --- a/llarp/dht/messages/findname.hpp +++ b/llarp/dht/messages/findname.hpp @@ -15,7 +15,9 @@ namespace llarp::dht decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; bool - handle_message(struct llarp_dht_context* dht, std::vector& replies) const override; + handle_message( + struct llarp_dht_context* dht, + std::vector>& replies) const override; Key_t NameHash; uint64_t TxID; diff --git a/llarp/dht/messages/findrouter.cpp b/llarp/dht/messages/findrouter.cpp index 80fed57319..25f64452c1 100644 --- a/llarp/dht/messages/findrouter.cpp +++ b/llarp/dht/messages/findrouter.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include diff --git a/llarp/dht/messages/findrouter.hpp b/llarp/dht/messages/findrouter.hpp index 9a34c018c9..9c57ae2814 100644 --- a/llarp/dht/messages/findrouter.hpp +++ b/llarp/dht/messages/findrouter.hpp @@ -51,6 +51,7 @@ namespace llarp::dht /// TODO: smart path expiration logic needs to be implemented bool handle_message( - llarp_dht_context* ctx, std::vector& replies) const override; + llarp_dht_context* ctx, + std::vector>& replies) const override; }; } // namespace llarp::dht diff --git a/llarp/dht/messages/gotintro.cpp b/llarp/dht/messages/gotintro.cpp index 628fa2924c..b9aa1f0b18 100644 --- a/llarp/dht/messages/gotintro.cpp +++ b/llarp/dht/messages/gotintro.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include diff --git a/llarp/dht/messages/gotintro.hpp b/llarp/dht/messages/gotintro.hpp index e5c288cfa4..58378b6214 100644 --- a/llarp/dht/messages/gotintro.hpp +++ b/llarp/dht/messages/gotintro.hpp @@ -46,7 +46,8 @@ namespace llarp::dht bool handle_message( - llarp_dht_context* ctx, std::vector& replies) const override; + llarp_dht_context* ctx, + std::vector>& replies) const override; }; struct RelayedGotIntroMessage final : public GotIntroMessage @@ -56,7 +57,8 @@ namespace llarp::dht bool handle_message( - llarp_dht_context* ctx, std::vector& replies) const override; + llarp_dht_context* ctx, + std::vector>& replies) const override; }; using GotIntroMessage_constptr = std::shared_ptr; diff --git a/llarp/dht/messages/gotname.cpp b/llarp/dht/messages/gotname.cpp index 20dc274fd9..16e4778b1c 100644 --- a/llarp/dht/messages/gotname.cpp +++ b/llarp/dht/messages/gotname.cpp @@ -57,7 +57,8 @@ namespace llarp::dht } bool - GotNameMessage::handle_message(struct llarp_dht_context* ctx, std::vector&) const + GotNameMessage::handle_message( + struct llarp_dht_context* ctx, std::vector>&) const { auto pathset = ctx->impl->GetRouter()->pathContext().GetLocalPathSet(pathID); if (pathset == nullptr) diff --git a/llarp/dht/messages/gotname.hpp b/llarp/dht/messages/gotname.hpp index d6400cf52e..001913313a 100644 --- a/llarp/dht/messages/gotname.hpp +++ b/llarp/dht/messages/gotname.hpp @@ -16,7 +16,9 @@ namespace llarp::dht decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; bool - handle_message(struct llarp_dht_context* dht, std::vector& replies) const override; + handle_message( + struct llarp_dht_context* dht, + std::vector>& replies) const override; service::EncryptedName result; uint64_t TxID; diff --git a/llarp/dht/messages/pubintro.cpp b/llarp/dht/messages/pubintro.cpp index dc54c9f157..34f7c3cb0a 100644 --- a/llarp/dht/messages/pubintro.cpp +++ b/llarp/dht/messages/pubintro.cpp @@ -4,7 +4,7 @@ #include "gotintro.hpp" #include #include -#include +#include #include #include diff --git a/llarp/dht/publishservicejob.cpp b/llarp/dht/publishservicejob.cpp index 6d138b62ce..bdec431257 100644 --- a/llarp/dht/publishservicejob.cpp +++ b/llarp/dht/publishservicejob.cpp @@ -4,81 +4,78 @@ #include #include #include -#include +#include #include #include -namespace llarp +namespace llarp::dht { - namespace dht - { - PublishServiceJob::PublishServiceJob( - const TXOwner& asker, - const service::EncryptedIntroSet& introset_, - AbstractContext* ctx, - uint64_t relayOrder_) - : TX(asker, asker, ctx) - , relayOrder(relayOrder_) - , introset(introset_) - {} + PublishServiceJob::PublishServiceJob( + const TXOwner& asker, + const service::EncryptedIntroSet& introset_, + AbstractContext* ctx, + uint64_t relayOrder_) + : TX(asker, asker, ctx) + , relayOrder(relayOrder_) + , introset(introset_) + {} - bool - PublishServiceJob::Validate(const service::EncryptedIntroSet& value) const + bool + PublishServiceJob::Validate(const service::EncryptedIntroSet& value) const + { + if (value.derivedSigningKey != introset.derivedSigningKey) { - if (value.derivedSigningKey != introset.derivedSigningKey) - { - llarp::LogWarn("publish introset acknowledgement acked a different service"); - return false; - } - const llarp_time_t now = llarp::time_now_ms(); - return value.Verify(now); + llarp::LogWarn("publish introset acknowledgement acked a different service"); + return false; } + const llarp_time_t now = llarp::time_now_ms(); + return value.Verify(now); + } - void - PublishServiceJob::Start(const TXOwner& peer) - { - parent->DHTSendTo( - peer.node.as_array(), new PublishIntroMessage(introset, peer.txid, false, relayOrder)); - } + void + PublishServiceJob::Start(const TXOwner& peer) + { + parent->DHTSendTo( + peer.node.as_array(), new PublishIntroMessage(introset, peer.txid, false, relayOrder)); + } - void - PublishServiceJob::SendReply() - { - parent->DHTSendTo(whoasked.node.as_array(), new GotIntroMessage({introset}, whoasked.txid)); - } + void + PublishServiceJob::SendReply() + { + parent->DHTSendTo(whoasked.node.as_array(), new GotIntroMessage({introset}, whoasked.txid)); + } - LocalPublishServiceJob::LocalPublishServiceJob( - const TXOwner& peer, - const PathID_t& fromID, - uint64_t _txid, - const service::EncryptedIntroSet& introset, - AbstractContext* ctx, - uint64_t relayOrder) - : PublishServiceJob(peer, introset, ctx, relayOrder), localPath(fromID), txid(_txid) - {} + LocalPublishServiceJob::LocalPublishServiceJob( + const TXOwner& peer, + const PathID_t& fromID, + uint64_t _txid, + const service::EncryptedIntroSet& introset, + AbstractContext* ctx, + uint64_t relayOrder) + : PublishServiceJob(peer, introset, ctx, relayOrder), localPath(fromID), txid(_txid) + {} - void - LocalPublishServiceJob::SendReply() + void + LocalPublishServiceJob::SendReply() + { + auto path = + parent->GetRouter()->pathContext().GetByUpstream(parent->OurKey().as_array(), localPath); + if (!path) + { + llarp::LogWarn( + "did not send reply for relayed dht request, no such local path " + "for pathid=", + localPath); + return; + } + routing::PathDHTMessage msg; + msg.dht_msgs.emplace_back(new GotIntroMessage({introset}, txid)); + if (!path->SendRoutingMessage(msg, parent->GetRouter())) { - auto path = - parent->GetRouter()->pathContext().GetByUpstream(parent->OurKey().as_array(), localPath); - if (!path) - { - llarp::LogWarn( - "did not send reply for relayed dht request, no such local path " - "for pathid=", - localPath); - return; - } - routing::DHTMessage msg; - msg.M.emplace_back(new GotIntroMessage({introset}, txid)); - if (!path->SendRoutingMessage(msg, parent->GetRouter())) - { - llarp::LogWarn( - "failed to send routing message when informing result of dht " - "request, pathid=", - localPath); - } + llarp::LogWarn( + "failed to send routing message when informing result of dht " + "request, pathid=", + localPath); } - } // namespace dht -} // namespace llarp + } +} // namespace llarp::dht diff --git a/llarp/dht/publishservicejob.hpp b/llarp/dht/publishservicejob.hpp index 7be563e308..b8de827c5e 100644 --- a/llarp/dht/publishservicejob.hpp +++ b/llarp/dht/publishservicejob.hpp @@ -8,47 +8,44 @@ #include -namespace llarp +namespace llarp::dht { - namespace dht + struct PublishServiceJob : public TX { - struct PublishServiceJob : public TX - { - uint64_t relayOrder; - service::EncryptedIntroSet introset; - - PublishServiceJob( - const TXOwner& asker, - const service::EncryptedIntroSet& introset, - AbstractContext* ctx, - uint64_t relayOrder); - - bool - Validate(const service::EncryptedIntroSet& introset) const override; - - void - Start(const TXOwner& peer) override; - - virtual void - SendReply() override; - }; - - struct LocalPublishServiceJob : public PublishServiceJob - { - PathID_t localPath; - uint64_t txid; - LocalPublishServiceJob( - const TXOwner& peer, - const PathID_t& fromID, - uint64_t txid, - const service::EncryptedIntroSet& introset, - AbstractContext* ctx, - uint64_t relayOrder); - - void - SendReply() override; - }; - } // namespace dht -} // namespace llarp + uint64_t relayOrder; + service::EncryptedIntroSet introset; + + PublishServiceJob( + const TXOwner& asker, + const service::EncryptedIntroSet& introset, + AbstractContext* ctx, + uint64_t relayOrder); + + bool + Validate(const service::EncryptedIntroSet& introset) const override; + + void + Start(const TXOwner& peer) override; + + void + SendReply() override; + }; + + struct LocalPublishServiceJob : public PublishServiceJob + { + PathID_t localPath; + uint64_t txid; + LocalPublishServiceJob( + const TXOwner& peer, + const PathID_t& fromID, + uint64_t txid, + const service::EncryptedIntroSet& introset, + AbstractContext* ctx, + uint64_t relayOrder); + + void + SendReply() override; + }; +} // namespace llarp::dht #endif diff --git a/llarp/dns/srv_data.cpp b/llarp/dns/srv_data.cpp index 24f7bab290..42f84479af 100644 --- a/llarp/dns/srv_data.cpp +++ b/llarp/dns/srv_data.cpp @@ -105,11 +105,10 @@ namespace llarp::dns return IsValid(); } - bool - SRVData::BEncode(llarp_buffer_t* buf) const + std::string + SRVData::bt_encode() const { - const std::string data = oxenc::bt_serialize(toTuple()); - return buf->write(data.begin(), data.end()); + return oxenc::bt_serialize(toTuple()); } bool diff --git a/llarp/dns/srv_data.hpp b/llarp/dns/srv_data.hpp index 58281ab8d5..bcba9b672c 100644 --- a/llarp/dns/srv_data.hpp +++ b/llarp/dns/srv_data.hpp @@ -57,8 +57,8 @@ namespace llarp::dns return toTupleRef() == other.toTupleRef(); } - bool - BEncode(llarp_buffer_t*) const; + std::string + bt_encode() const; bool BDecode(llarp_buffer_t*); diff --git a/llarp/exit/endpoint.cpp b/llarp/exit/endpoint.cpp index 4bbad541ce..2b29129dc6 100644 --- a/llarp/exit/endpoint.cpp +++ b/llarp/exit/endpoint.cpp @@ -5,237 +5,233 @@ #include #include -namespace llarp +namespace llarp::exit { - namespace exit + Endpoint::Endpoint( + const llarp::PubKey& remoteIdent, + const llarp::path::HopHandler_ptr& beginPath, + bool rewriteIP, + huint128_t ip, + llarp::handlers::ExitEndpoint* parent) + : createdAt{parent->Now()} + , m_Parent{parent} + , m_remoteSignKey{remoteIdent} + , m_CurrentPath{beginPath} + , m_IP{ip} + , m_RewriteSource{rewriteIP} { - Endpoint::Endpoint( - const llarp::PubKey& remoteIdent, - const llarp::path::HopHandler_ptr& beginPath, - bool rewriteIP, - huint128_t ip, - llarp::handlers::ExitEndpoint* parent) - : createdAt{parent->Now()} - , m_Parent{parent} - , m_remoteSignKey{remoteIdent} - , m_CurrentPath{beginPath} - , m_IP{ip} - , m_RewriteSource{rewriteIP} - { - m_LastActive = parent->Now(); - } + m_LastActive = parent->Now(); + } - Endpoint::~Endpoint() - { - if (m_CurrentPath) - m_Parent->DelEndpointInfo(m_CurrentPath->RXID()); - } + Endpoint::~Endpoint() + { + if (m_CurrentPath) + m_Parent->DelEndpointInfo(m_CurrentPath->RXID()); + } - void - Endpoint::Close() - { - m_Parent->RemoveExit(this); - } + void + Endpoint::Close() + { + m_Parent->RemoveExit(this); + } - util::StatusObject - Endpoint::ExtractStatus() const + util::StatusObject + Endpoint::ExtractStatus() const + { + auto now = m_Parent->Now(); + util::StatusObject obj{ + {"identity", m_remoteSignKey.ToString()}, + {"ip", m_IP.ToString()}, + {"txRate", m_TxRate}, + {"rxRate", m_RxRate}, + {"createdAt", to_json(createdAt)}, + {"exiting", !m_RewriteSource}, + {"looksDead", LooksDead(now)}, + {"expiresSoon", ExpiresSoon(now)}, + {"expired", IsExpired(now)}}; + return obj; + } + + bool + Endpoint::UpdateLocalPath(const llarp::PathID_t& nextPath) + { + if (!m_Parent->UpdateEndpointPath(m_remoteSignKey, nextPath)) + return false; + const RouterID us{m_Parent->GetRouter()->pubkey()}; + m_CurrentPath = m_Parent->GetRouter()->pathContext().GetByUpstream(us, nextPath); + return true; + } + + void + Endpoint::Tick(llarp_time_t now) + { + (void)now; + m_RxRate = 0; + m_TxRate = 0; + } + + bool + Endpoint::IsExpired(llarp_time_t now) const + { + auto path = GetCurrentPath(); + if (path) { - auto now = m_Parent->Now(); - util::StatusObject obj{ - {"identity", m_remoteSignKey.ToString()}, - {"ip", m_IP.ToString()}, - {"txRate", m_TxRate}, - {"rxRate", m_RxRate}, - {"createdAt", to_json(createdAt)}, - {"exiting", !m_RewriteSource}, - {"looksDead", LooksDead(now)}, - {"expiresSoon", ExpiresSoon(now)}, - {"expired", IsExpired(now)}}; - return obj; + return path->Expired(now); } + // if we don't have an underlying path we are considered expired + return true; + } + + bool + Endpoint::ExpiresSoon(llarp_time_t now, llarp_time_t dlt) const + { + if (m_CurrentPath) + return m_CurrentPath->ExpiresSoon(now, dlt); + return true; + } - bool - Endpoint::UpdateLocalPath(const llarp::PathID_t& nextPath) + bool + Endpoint::LooksDead(llarp_time_t now, llarp_time_t timeout) const + { + if (ExpiresSoon(now, timeout)) + return true; + auto path = GetCurrentPath(); + if (not path) + return true; + auto lastPing = path->LastRemoteActivityAt(); + if (lastPing == 0s || (now > lastPing && now - lastPing > timeout)) + return now > m_LastActive && now - m_LastActive > timeout; + else if (lastPing > 0s) // NOLINT + return now > lastPing && now - lastPing > timeout; + return lastPing > 0s; + } + + bool + Endpoint::QueueOutboundTraffic( + PathID_t path, std::vector buf, uint64_t counter, service::ProtocolType t) + { + const service::ConvoTag tag{path.as_array()}; + if (t == service::ProtocolType::QUIC) { - if (!m_Parent->UpdateEndpointPath(m_remoteSignKey, nextPath)) + auto quic = m_Parent->GetQUICTunnel(); + if (not quic) return false; - const RouterID us{m_Parent->GetRouter()->pubkey()}; - m_CurrentPath = m_Parent->GetRouter()->pathContext().GetByUpstream(us, nextPath); + m_TxRate += buf.size(); + quic->receive_packet(tag, std::move(buf)); + m_LastActive = m_Parent->Now(); return true; } + // queue overflow + if (m_UpstreamQueue.size() > MaxUpstreamQueueSize) + return false; - void - Endpoint::Tick(llarp_time_t now) - { - (void)now; - m_RxRate = 0; - m_TxRate = 0; - } + llarp::net::IPPacket pkt{std::move(buf)}; + if (pkt.empty()) + return false; - bool - Endpoint::IsExpired(llarp_time_t now) const + if (pkt.IsV6() && m_Parent->SupportsV6()) { - auto path = GetCurrentPath(); - if (path) - { - return path->Expired(now); - } - // if we don't have an underlying path we are considered expired - return true; + huint128_t dst; + if (m_RewriteSource) + dst = m_Parent->GetIfAddr(); + else + dst = pkt.dstv6(); + pkt.UpdateIPv6Address(m_IP, dst); } - - bool - Endpoint::ExpiresSoon(llarp_time_t now, llarp_time_t dlt) const + else if (pkt.IsV4() && !m_Parent->SupportsV6()) { - if (m_CurrentPath) - return m_CurrentPath->ExpiresSoon(now, dlt); - return true; + huint32_t dst; + if (m_RewriteSource) + dst = net::TruncateV6(m_Parent->GetIfAddr()); + else + dst = pkt.dstv4(); + pkt.UpdateIPv4Address(xhtonl(net::TruncateV6(m_IP)), xhtonl(dst)); } - - bool - Endpoint::LooksDead(llarp_time_t now, llarp_time_t timeout) const + else { - if (ExpiresSoon(now, timeout)) - return true; - auto path = GetCurrentPath(); - if (not path) - return true; - auto lastPing = path->LastRemoteActivityAt(); - if (lastPing == 0s || (now > lastPing && now - lastPing > timeout)) - return now > m_LastActive && now - m_LastActive > timeout; - else if (lastPing > 0s) // NOLINT - return now > lastPing && now - lastPing > timeout; - return lastPing > 0s; + return false; } - - bool - Endpoint::QueueOutboundTraffic( - PathID_t path, std::vector buf, uint64_t counter, service::ProtocolType t) + m_TxRate += pkt.size(); + m_UpstreamQueue.emplace(std::move(pkt), counter); + m_LastActive = m_Parent->Now(); + return true; + } + + bool + Endpoint::QueueInboundTraffic(std::vector buf, service::ProtocolType type) + { + if (type != service::ProtocolType::QUIC) { - const service::ConvoTag tag{path.as_array()}; - if (t == service::ProtocolType::QUIC) - { - auto quic = m_Parent->GetQUICTunnel(); - if (not quic) - return false; - m_TxRate += buf.size(); - quic->receive_packet(tag, std::move(buf)); - m_LastActive = m_Parent->Now(); - return true; - } - // queue overflow - if (m_UpstreamQueue.size() > MaxUpstreamQueueSize) - return false; - llarp::net::IPPacket pkt{std::move(buf)}; if (pkt.empty()) return false; - if (pkt.IsV6() && m_Parent->SupportsV6()) - { - huint128_t dst; - if (m_RewriteSource) - dst = m_Parent->GetIfAddr(); - else - dst = pkt.dstv6(); - pkt.UpdateIPv6Address(m_IP, dst); - } - else if (pkt.IsV4() && !m_Parent->SupportsV6()) - { - huint32_t dst; - if (m_RewriteSource) - dst = net::TruncateV6(m_Parent->GetIfAddr()); - else - dst = pkt.dstv4(); - pkt.UpdateIPv4Address(xhtonl(net::TruncateV6(m_IP)), xhtonl(dst)); - } + huint128_t src; + if (m_RewriteSource) + src = m_Parent->GetIfAddr(); else - { - return false; - } - m_TxRate += pkt.size(); - m_UpstreamQueue.emplace(std::move(pkt), counter); - m_LastActive = m_Parent->Now(); - return true; + src = pkt.srcv6(); + if (pkt.IsV6()) + pkt.UpdateIPv6Address(src, m_IP); + else + pkt.UpdateIPv4Address(xhtonl(net::TruncateV6(src)), xhtonl(net::TruncateV6(m_IP))); + + buf = pkt.steal(); } - bool - Endpoint::QueueInboundTraffic(std::vector buf, service::ProtocolType type) + const uint8_t queue_idx = buf.size() / llarp::routing::EXIT_PAD_SIZE; + if (m_DownstreamQueues.find(queue_idx) == m_DownstreamQueues.end()) + m_DownstreamQueues.emplace(queue_idx, InboundTrafficQueue_t{}); + auto& queue = m_DownstreamQueues.at(queue_idx); + if (queue.size() == 0) { - if (type != service::ProtocolType::QUIC) - { - llarp::net::IPPacket pkt{std::move(buf)}; - if (pkt.empty()) - return false; - - huint128_t src; - if (m_RewriteSource) - src = m_Parent->GetIfAddr(); - else - src = pkt.srcv6(); - if (pkt.IsV6()) - pkt.UpdateIPv6Address(src, m_IP); - else - pkt.UpdateIPv4Address(xhtonl(net::TruncateV6(src)), xhtonl(net::TruncateV6(m_IP))); - - buf = pkt.steal(); - } - - const uint8_t queue_idx = buf.size() / llarp::routing::ExitPadSize; - if (m_DownstreamQueues.find(queue_idx) == m_DownstreamQueues.end()) - m_DownstreamQueues.emplace(queue_idx, InboundTrafficQueue_t{}); - auto& queue = m_DownstreamQueues.at(queue_idx); - if (queue.size() == 0) - { - queue.emplace_back(); - queue.back().protocol = type; - return queue.back().PutBuffer(std::move(buf), m_Counter++); - } - auto& msg = queue.back(); - if (msg.Size() + buf.size() > llarp::routing::ExitPadSize) - { - queue.emplace_back(); - queue.back().protocol = type; - return queue.back().PutBuffer(std::move(buf), m_Counter++); - } - msg.protocol = type; - return msg.PutBuffer(std::move(buf), m_Counter++); + queue.emplace_back(); + queue.back().protocol = type; + return queue.back().PutBuffer(std::move(buf), m_Counter++); + } + auto& msg = queue.back(); + if (msg.Size() + buf.size() > llarp::routing::EXIT_PAD_SIZE) + { + queue.emplace_back(); + queue.back().protocol = type; + return queue.back().PutBuffer(std::move(buf), m_Counter++); } + msg.protocol = type; + return msg.PutBuffer(std::move(buf), m_Counter++); + } - bool - Endpoint::Flush() + bool + Endpoint::Flush() + { + // flush upstream queue + while (m_UpstreamQueue.size()) { - // flush upstream queue - while (m_UpstreamQueue.size()) - { - m_Parent->QueueOutboundTraffic( - const_cast(m_UpstreamQueue.top().pkt).steal()); - m_UpstreamQueue.pop(); - } - // flush downstream queue - auto path = GetCurrentPath(); - bool sent = path != nullptr; - if (path) + m_Parent->QueueOutboundTraffic(const_cast(m_UpstreamQueue.top().pkt).steal()); + m_UpstreamQueue.pop(); + } + // flush downstream queue + auto path = GetCurrentPath(); + bool sent = path != nullptr; + if (path) + { + for (auto& item : m_DownstreamQueues) { - for (auto& item : m_DownstreamQueues) + auto& queue = item.second; + while (queue.size()) { - auto& queue = item.second; - while (queue.size()) + auto& msg = queue.front(); + msg.sequence_number = path->NextSeqNo(); + if (path->SendRoutingMessage(msg, m_Parent->GetRouter())) { - auto& msg = queue.front(); - msg.S = path->NextSeqNo(); - if (path->SendRoutingMessage(msg, m_Parent->GetRouter())) - { - m_RxRate += msg.Size(); - sent = true; - } - queue.pop_front(); + m_RxRate += msg.Size(); + sent = true; } + queue.pop_front(); } } - for (auto& item : m_DownstreamQueues) - item.second.clear(); - return sent; } - } // namespace exit -} // namespace llarp + for (auto& item : m_DownstreamQueues) + item.second.clear(); + return sent; + } +} // namespace llarp::exit diff --git a/llarp/exit/exit_messages.cpp b/llarp/exit/exit_messages.cpp index 9f72cc2daf..d850c61920 100644 --- a/llarp/exit/exit_messages.cpp +++ b/llarp/exit/exit_messages.cpp @@ -3,419 +3,461 @@ #include #include -namespace llarp +namespace llarp::routing { - namespace routing + bool + ObtainExitMessage::Sign(const llarp::SecretKey& sk) { - bool - ObtainExitMessage::Sign(const llarp::SecretKey& sk) + std::array tmp; + llarp_buffer_t buf(tmp); + pubkey = seckey_topublic(sk); + sig.Zero(); + + auto bte = bt_encode(); + buf.write(bte.begin(), bte.end()); + + buf.sz = buf.cur - buf.base; + return CryptoManager::instance()->sign(sig, sk, buf); + } + + bool + ObtainExitMessage::Verify() const + { + std::array tmp; + llarp_buffer_t buf(tmp); + ObtainExitMessage copy; + copy = *this; + copy.sig.Zero(); + + auto bte = copy.bt_encode(); + buf.write(bte.begin(), bte.end()); + + // rewind buffer + buf.sz = buf.cur - buf.base; + return CryptoManager::instance()->verify(pubkey, buf, sig); + } + + std::string + ObtainExitMessage::bt_encode() const + { + oxenc::bt_dict_producer btdp; + + try { - std::array tmp; - llarp_buffer_t buf(tmp); - I = seckey_topublic(sk); - Z.Zero(); - if (!BEncode(&buf)) + btdp.append("A", "O"); + { - return false; + auto subdict = btdp.append_dict("B"); + + for (auto& b : blacklist_policy) + b.bt_encode(subdict); } - buf.sz = buf.cur - buf.base; - return CryptoManager::instance()->sign(Z, sk, buf); - } - bool - ObtainExitMessage::Verify() const - { - std::array tmp; - llarp_buffer_t buf(tmp); - ObtainExitMessage copy; - copy = *this; - copy.Z.Zero(); - if (!copy.BEncode(&buf)) + btdp.append("E", flag); + btdp.append("I", pubkey.ToView()); + btdp.append("S", sequence_number); + btdp.append("T", tx_id); + btdp.append("V", version); + { - return false; + auto subdict = btdp.append_dict("B"); + + for (auto& w : whitelist_policy) + w.bt_encode(subdict); } - // rewind buffer - buf.sz = buf.cur - buf.base; - return CryptoManager::instance()->verify(I, buf, Z); - } - bool - ObtainExitMessage::BEncode(llarp_buffer_t* buf) const - { - if (!bencode_start_dict(buf)) - return false; - if (!BEncodeWriteDictMsgType(buf, "A", "O")) - return false; - if (!BEncodeWriteDictArray("B", B, buf)) - return false; - if (!BEncodeWriteDictInt("E", E, buf)) - return false; - if (!BEncodeWriteDictEntry("I", I, buf)) - return false; - if (!BEncodeWriteDictInt("S", S, buf)) - return false; - if (!BEncodeWriteDictInt("T", T, buf)) - return false; - if (!BEncodeWriteDictInt("V", version, buf)) - return false; - if (!BEncodeWriteDictArray("W", W, buf)) - return false; - if (!BEncodeWriteDictInt("X", X, buf)) - return false; - if (!BEncodeWriteDictEntry("Z", Z, buf)) - return false; - return bencode_end(buf); + btdp.append("X", address_lifetime); + btdp.append("Z", sig.ToView()); } - - bool - ObtainExitMessage::DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* buf) + catch (...) { - bool read = false; - if (!BEncodeMaybeReadDictList("B", B, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("E", E, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("I", I, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("S", S, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("T", T, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictList("W", W, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("X", X, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("Z", Z, read, k, buf)) - return false; - return read; + log::critical(route_cat, "Error: ObtainExitMessage failed to bt encode contents!"); } - bool - ObtainExitMessage::HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const - { - return h->HandleObtainExitMessage(*this, r); - } + return std::move(btdp).str(); + } - bool - GrantExitMessage::BEncode(llarp_buffer_t* buf) const - { - if (!bencode_start_dict(buf)) - return false; - if (!BEncodeWriteDictMsgType(buf, "A", "G")) - return false; - if (!BEncodeWriteDictInt("S", S, buf)) - return false; - if (!BEncodeWriteDictInt("T", T, buf)) - return false; - if (!BEncodeWriteDictInt("V", version, buf)) - return false; - if (!BEncodeWriteDictEntry("Y", Y, buf)) - return false; - if (!BEncodeWriteDictEntry("Z", Z, buf)) - return false; - return bencode_end(buf); - } + bool + ObtainExitMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) + { + bool read = false; + if (!BEncodeMaybeReadDictList("B", blacklist_policy, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictInt("E", flag, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictEntry("I", pubkey, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictList("W", whitelist_policy, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictInt("X", address_lifetime, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf)) + return false; + return read; + } - bool - GrantExitMessage::DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* buf) - { - bool read = false; - if (!BEncodeMaybeReadDictInt("S", S, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("T", T, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("Y", Y, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("Z", Z, read, k, buf)) - return false; - return read; - } + bool + ObtainExitMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + { + return h->HandleObtainExitMessage(*this, r); + } - bool - GrantExitMessage::Verify(const llarp::PubKey& pk) const - { - std::array tmp; - llarp_buffer_t buf(tmp); - GrantExitMessage copy; - copy = *this; - copy.Z.Zero(); - if (!copy.BEncode(&buf)) - return false; - buf.sz = buf.cur - buf.base; - return CryptoManager::instance()->verify(pk, buf, Z); - } + std::string + GrantExitMessage::bt_encode() const + { + oxenc::bt_dict_producer btdp; - bool - GrantExitMessage::Sign(const llarp::SecretKey& sk) + try { - std::array tmp; - llarp_buffer_t buf(tmp); - Z.Zero(); - Y.Randomize(); - if (!BEncode(&buf)) - return false; - buf.sz = buf.cur - buf.base; - return CryptoManager::instance()->sign(Z, sk, buf); + btdp.append("A", "G"); + btdp.append("S", sequence_number); + btdp.append("T", tx_id); + btdp.append("V", version); + btdp.append("Y", nonce.ToView()); + btdp.append("Z", sig.ToView()); } - - bool - GrantExitMessage::HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + catch (...) { - return h->HandleGrantExitMessage(*this, r); + log::critical(route_cat, "Error: GrantExitMessage failed to bt encode contents!"); } - bool - RejectExitMessage::BEncode(llarp_buffer_t* buf) const - { - if (!bencode_start_dict(buf)) - return false; - if (!BEncodeWriteDictMsgType(buf, "A", "J")) - return false; - if (!BEncodeWriteDictInt("B", B, buf)) - return false; - if (!BEncodeWriteDictList("R", R, buf)) - return false; - if (!BEncodeWriteDictInt("S", S, buf)) - return false; - if (!BEncodeWriteDictInt("T", T, buf)) - return false; - if (!BEncodeWriteDictInt("V", version, buf)) - return false; - if (!BEncodeWriteDictEntry("Y", Y, buf)) - return false; - if (!BEncodeWriteDictEntry("Z", Z, buf)) - return false; - return bencode_end(buf); - } + return std::move(btdp).str(); + } - bool - RejectExitMessage::DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* buf) - { - bool read = false; - if (!BEncodeMaybeReadDictInt("B", B, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictList("R", R, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("S", S, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("T", T, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("Y", Y, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("Z", Z, read, k, buf)) - return false; - return read; - } + bool + GrantExitMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) + { + bool read = false; + if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictEntry("Y", nonce, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf)) + return false; + return read; + } - bool - RejectExitMessage::Sign(const llarp::SecretKey& sk) - { - std::array tmp; - llarp_buffer_t buf(tmp); - Z.Zero(); - Y.Randomize(); - if (!BEncode(&buf)) - return false; - buf.sz = buf.cur - buf.base; - return CryptoManager::instance()->sign(Z, sk, buf); - } + bool + GrantExitMessage::Verify(const llarp::PubKey& pk) const + { + std::array tmp; + llarp_buffer_t buf(tmp); + GrantExitMessage copy; + copy = *this; + copy.sig.Zero(); - bool - RejectExitMessage::Verify(const llarp::PubKey& pk) const - { - std::array tmp; - llarp_buffer_t buf(tmp); - RejectExitMessage copy; - copy = *this; - copy.Z.Zero(); - if (!copy.BEncode(&buf)) - return false; - buf.sz = buf.cur - buf.base; - return CryptoManager::instance()->verify(pk, buf, Z); - } + auto bte = copy.bt_encode(); + buf.write(bte.begin(), bte.end()); - bool - RejectExitMessage::HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const - { - return h->HandleRejectExitMessage(*this, r); - } + buf.sz = buf.cur - buf.base; + return CryptoManager::instance()->verify(pk, buf, sig); + } - bool - UpdateExitMessage::BEncode(llarp_buffer_t* buf) const - { - if (!bencode_start_dict(buf)) - return false; - if (!BEncodeWriteDictMsgType(buf, "A", "V")) - return false; - if (!BEncodeWriteDictEntry("P", P, buf)) - return false; - if (!BEncodeWriteDictInt("S", S, buf)) - return false; - if (!BEncodeWriteDictInt("T", T, buf)) - return false; - if (!BEncodeWriteDictInt("V", version, buf)) - return false; - if (!BEncodeWriteDictEntry("Z", Z, buf)) - return false; - return bencode_end(buf); - } + bool + GrantExitMessage::Sign(const llarp::SecretKey& sk) + { + std::array tmp; + llarp_buffer_t buf(tmp); + sig.Zero(); + nonce.Randomize(); - bool - UpdateExitMessage::DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* buf) - { - bool read = false; - if (!BEncodeMaybeReadDictInt("S", S, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("T", T, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("P", P, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("Z", Z, read, k, buf)) - return false; - return read; - } + auto bte = bt_encode(); + buf.write(bte.begin(), bte.end()); - bool - UpdateExitMessage::Verify(const llarp::PubKey& pk) const + buf.sz = buf.cur - buf.base; + return CryptoManager::instance()->sign(sig, sk, buf); + } - { - std::array tmp; - llarp_buffer_t buf(tmp); - UpdateExitMessage copy; - copy = *this; - copy.Z.Zero(); - if (!copy.BEncode(&buf)) - return false; - buf.sz = buf.cur - buf.base; - return CryptoManager::instance()->verify(pk, buf, Z); - } + bool + GrantExitMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + { + return h->HandleGrantExitMessage(*this, r); + } - bool - UpdateExitMessage::Sign(const llarp::SecretKey& sk) - { - std::array tmp; - llarp_buffer_t buf(tmp); - Y.Randomize(); - if (!BEncode(&buf)) - return false; - buf.sz = buf.cur - buf.base; - return CryptoManager::instance()->sign(Z, sk, buf); - } + std::string + RejectExitMessage::bt_encode() const + { + oxenc::bt_dict_producer btdp; - bool - UpdateExitMessage::HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + try { - return h->HandleUpdateExitMessage(*this, r); - } + btdp.append("A", "J"); + btdp.append("B", backoff_time); - bool - UpdateExitVerifyMessage::BEncode(llarp_buffer_t* buf) const - { - if (!bencode_start_dict(buf)) - return false; - if (!BEncodeWriteDictMsgType(buf, "A", "V")) - return false; - if (!BEncodeWriteDictInt("S", S, buf)) - return false; - if (!BEncodeWriteDictInt("T", T, buf)) - return false; - if (!BEncodeWriteDictInt("V", version, buf)) - return false; - return bencode_end(buf); - } + { + auto subdict = btdp.append_dict("R"); - bool - UpdateExitVerifyMessage::DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* buf) + for (auto& b : blacklist_policy) + b.bt_encode(subdict); + } + + btdp.append("S", sequence_number); + btdp.append("T", tx_id); + btdp.append("V", version); + btdp.append("Y", nonce.ToView()); + btdp.append("Z", sig.ToView()); + } + catch (...) { - bool read = false; - if (!BEncodeMaybeReadDictInt("S", S, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("T", T, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) - return false; - return read; + log::critical(route_cat, "Error: RejectExitMessage failed to bt encode contents!"); } - bool - UpdateExitVerifyMessage::HandleMessage( - AbstractRoutingMessageHandler* h, AbstractRouter* r) const + return std::move(btdp).str(); + } + + bool + RejectExitMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) + { + bool read = false; + if (!BEncodeMaybeReadDictInt("B", backoff_time, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictList("R", blacklist_policy, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictEntry("Y", nonce, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf)) + return false; + return read; + } + + bool + RejectExitMessage::Sign(const llarp::SecretKey& sk) + { + std::array tmp; + llarp_buffer_t buf(tmp); + sig.Zero(); + nonce.Randomize(); + + auto bte = bt_encode(); + buf.write(bte.begin(), bte.end()); + + buf.sz = buf.cur - buf.base; + return CryptoManager::instance()->sign(sig, sk, buf); + } + + bool + RejectExitMessage::Verify(const llarp::PubKey& pk) const + { + std::array tmp; + llarp_buffer_t buf(tmp); + RejectExitMessage copy; + copy = *this; + copy.sig.Zero(); + + auto bte = copy.bt_encode(); + buf.write(bte.begin(), bte.end()); + + buf.sz = buf.cur - buf.base; + return CryptoManager::instance()->verify(pk, buf, sig); + } + + bool + RejectExitMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + { + return h->HandleRejectExitMessage(*this, r); + } + + std::string + UpdateExitMessage::bt_encode() const + { + oxenc::bt_dict_producer btdp; + + try { - return h->HandleUpdateExitVerifyMessage(*this, r); + btdp.append("A", "V"); + btdp.append("P", path_id.ToView()); + btdp.append("S", sequence_number); + btdp.append("T", tx_id); + btdp.append("V", version); + btdp.append("Z", sig.ToView()); } - - bool - CloseExitMessage::BEncode(llarp_buffer_t* buf) const + catch (...) { - if (!bencode_start_dict(buf)) - return false; - if (!BEncodeWriteDictMsgType(buf, "A", "C")) - return false; - if (!BEncodeWriteDictInt("S", S, buf)) - return false; - if (!BEncodeWriteDictInt("V", version, buf)) - return false; - if (!BEncodeWriteDictEntry("Y", Y, buf)) - return false; - if (!BEncodeWriteDictEntry("Z", Z, buf)) - return false; - return bencode_end(buf); + log::critical(route_cat, "Error: UpdateExitMessage failed to bt encode contents!"); } - bool - CloseExitMessage::DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* buf) + return std::move(btdp).str(); + } + + bool + UpdateExitMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) + { + bool read = false; + if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictEntry("P", path_id, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf)) + return false; + return read; + } + + bool + UpdateExitMessage::Verify(const llarp::PubKey& pk) const + + { + std::array tmp; + llarp_buffer_t buf(tmp); + UpdateExitMessage copy; + copy = *this; + copy.sig.Zero(); + + auto bte = copy.bt_encode(); + buf.write(bte.begin(), bte.end()); + + buf.sz = buf.cur - buf.base; + return CryptoManager::instance()->verify(pk, buf, sig); + } + + bool + UpdateExitMessage::Sign(const llarp::SecretKey& sk) + { + std::array tmp; + llarp_buffer_t buf(tmp); + nonce.Randomize(); + + auto bte = bt_encode(); + buf.write(bte.begin(), bte.end()); + + buf.sz = buf.cur - buf.base; + return CryptoManager::instance()->sign(sig, sk, buf); + } + + bool + UpdateExitMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + { + return h->HandleUpdateExitMessage(*this, r); + } + + std::string + UpdateExitVerifyMessage::bt_encode() const + { + oxenc::bt_dict_producer btdp; + + try { - bool read = false; - if (!BEncodeMaybeReadDictInt("S", S, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("Y", Y, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("Z", Z, read, k, buf)) - return false; - return read; + btdp.append("A", "V"); + btdp.append("S", sequence_number); + btdp.append("T", tx_id); + btdp.append("V", version); } - - bool - CloseExitMessage::Verify(const llarp::PubKey& pk) const + catch (...) { - std::array tmp; - llarp_buffer_t buf(tmp); - CloseExitMessage copy; - copy = *this; - copy.Z.Zero(); - if (!copy.BEncode(&buf)) - return false; - buf.sz = buf.cur - buf.base; - return CryptoManager::instance()->verify(pk, buf, Z); + log::critical(route_cat, "Error: UpdateExitVerifyMessage failed to bt encode contents!"); } - bool - CloseExitMessage::Sign(const llarp::SecretKey& sk) + return std::move(btdp).str(); + } + + bool + UpdateExitVerifyMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) + { + bool read = false; + if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) + return false; + return read; + } + + bool + UpdateExitVerifyMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + { + return h->HandleUpdateExitVerifyMessage(*this, r); + } + + std::string + CloseExitMessage::bt_encode() const + { + oxenc::bt_dict_producer btdp; + + try { - std::array tmp; - llarp_buffer_t buf(tmp); - Z.Zero(); - Y.Randomize(); - if (!BEncode(&buf)) - return false; - buf.sz = buf.cur - buf.base; - return CryptoManager::instance()->sign(Z, sk, buf); + btdp.append("A", "C"); + btdp.append("S", sequence_number); + btdp.append("V", version); + btdp.append("Y", nonce.ToView()); + btdp.append("Z", sig.ToView()); } - - bool - CloseExitMessage::HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + catch (...) { - return h->HandleCloseExitMessage(*this, r); + log::critical(route_cat, "Error: CloseExitMessage failed to bt encode contents!"); } - } // namespace routing -} // namespace llarp + + return std::move(btdp).str(); + } + + bool + CloseExitMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) + { + bool read = false; + if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictEntry("Y", nonce, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf)) + return false; + return read; + } + + bool + CloseExitMessage::Verify(const llarp::PubKey& pk) const + { + std::array tmp; + llarp_buffer_t buf(tmp); + CloseExitMessage copy; + copy = *this; + copy.sig.Zero(); + + auto bte = copy.bt_encode(); + buf.write(bte.begin(), bte.end()); + + buf.sz = buf.cur - buf.base; + return CryptoManager::instance()->verify(pk, buf, sig); + } + + bool + CloseExitMessage::Sign(const llarp::SecretKey& sk) + { + std::array tmp; + llarp_buffer_t buf(tmp); + sig.Zero(); + nonce.Randomize(); + + auto bte = bt_encode(); + buf.write(bte.begin(), bte.end()); + + buf.sz = buf.cur - buf.base; + return CryptoManager::instance()->sign(sig, sk, buf); + } + + bool + CloseExitMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + { + return h->HandleCloseExitMessage(*this, r); + } +} // namespace llarp::routing diff --git a/llarp/exit/exit_messages.hpp b/llarp/exit/exit_messages.hpp index 1887f2fab5..7dbe8975e7 100644 --- a/llarp/exit/exit_messages.hpp +++ b/llarp/exit/exit_messages.hpp @@ -6,210 +6,206 @@ #include -namespace llarp +namespace llarp::routing { - namespace routing + struct ObtainExitMessage final : public AbstractRoutingMessage { - struct ObtainExitMessage final : public AbstractRoutingMessage - { - std::vector B; - uint64_t E{0}; - llarp::PubKey I; - uint64_t T{0}; - std::vector W; - uint64_t X{0}; - llarp::Signature Z; - - ObtainExitMessage() : AbstractRoutingMessage() - {} - - ~ObtainExitMessage() override = default; - - void - Clear() override - { - B.clear(); - E = 0; - I.Zero(); - T = 0; - W.clear(); - X = 0; - Z.Zero(); - } - - /// populates I and signs - bool - Sign(const llarp::SecretKey& sk); - - bool - Verify() const; - - bool - BEncode(llarp_buffer_t* buf) const override; - - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) override; - - bool - HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; - }; - - struct GrantExitMessage final : public AbstractRoutingMessage + std::vector blacklist_policy; + uint64_t flag{0}; // 0 for snode, 1 for internet access + llarp::PubKey pubkey; + uint64_t tx_id{0}; + std::vector whitelist_policy; + uint64_t address_lifetime{0}; + llarp::Signature sig; + + ObtainExitMessage() : AbstractRoutingMessage() + {} + + ~ObtainExitMessage() override = default; + + void + clear() override { - using Nonce_t = llarp::AlignedBuffer<16>; + blacklist_policy.clear(); + flag = 0; + pubkey.Zero(); + tx_id = 0; + whitelist_policy.clear(); + address_lifetime = 0; + sig.Zero(); + } - uint64_t T; - Nonce_t Y; - llarp::Signature Z; + /// populates I and signs + bool + Sign(const llarp::SecretKey& sk); - bool - BEncode(llarp_buffer_t* buf) const override; + bool + Verify() const; - bool - Sign(const llarp::SecretKey& sk); + std::string + bt_encode() const override; + + bool + decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; + + bool + handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + }; + + struct GrantExitMessage final : public AbstractRoutingMessage + { + using Nonce_t = llarp::AlignedBuffer<16>; - bool - Verify(const llarp::PubKey& pk) const; + uint64_t tx_id; + Nonce_t nonce; + llarp::Signature sig; - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) override; + std::string + bt_encode() const override; - bool - HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + bool + Sign(const llarp::SecretKey& sk); - void - Clear() override - { - T = 0; - Y.Zero(); - Z.Zero(); - } - }; + bool + Verify(const llarp::PubKey& pk) const; - struct RejectExitMessage final : public AbstractRoutingMessage + bool + decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; + + bool + handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + + void + clear() override { - using Nonce_t = llarp::AlignedBuffer<16>; - uint64_t B; - std::vector R; - uint64_t T; - Nonce_t Y; - llarp::Signature Z; - - void - Clear() override - { - B = 0; - R.clear(); - T = 0; - Y.Zero(); - Z.Zero(); - } - - bool - Sign(const llarp::SecretKey& sk); - - bool - Verify(const llarp::PubKey& pk) const; - - bool - BEncode(llarp_buffer_t* buf) const override; - - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) override; - - bool - HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; - }; - - struct UpdateExitVerifyMessage final : public AbstractRoutingMessage + tx_id = 0; + nonce.Zero(); + sig.Zero(); + } + }; + + struct RejectExitMessage final : public AbstractRoutingMessage + { + using Nonce_t = llarp::AlignedBuffer<16>; + uint64_t backoff_time; + std::vector blacklist_policy; + uint64_t tx_id; + Nonce_t nonce; + llarp::Signature sig; + + void + clear() override { - using Nonce_t = llarp::AlignedBuffer<16>; - uint64_t T; - Nonce_t Y; - llarp::Signature Z; + backoff_time = 0; + blacklist_policy.clear(); + tx_id = 0; + nonce.Zero(); + sig.Zero(); + } - ~UpdateExitVerifyMessage() override = default; + bool + Sign(const llarp::SecretKey& sk); - void - Clear() override - { - T = 0; - Y.Zero(); - Z.Zero(); - } + bool + Verify(const llarp::PubKey& pk) const; - bool - BEncode(llarp_buffer_t* buf) const override; + std::string + bt_encode() const override; - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) override; + bool + decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; - bool - HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; - }; + bool + handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + }; - struct UpdateExitMessage final : public AbstractRoutingMessage - { - using Nonce_t = llarp::AlignedBuffer<16>; - llarp::PathID_t P; - uint64_t T; - Nonce_t Y; - llarp::Signature Z; - - bool - Sign(const llarp::SecretKey& sk); - - bool - Verify(const llarp::PubKey& pk) const; - - bool - BEncode(llarp_buffer_t* buf) const override; - - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) override; - - bool - HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; - - void - Clear() override - { - P.Zero(); - T = 0; - Y.Zero(); - Z.Zero(); - } - }; - - struct CloseExitMessage final : public AbstractRoutingMessage + struct UpdateExitVerifyMessage final : public AbstractRoutingMessage + { + using Nonce_t = llarp::AlignedBuffer<16>; + uint64_t tx_id; + Nonce_t nonce; + llarp::Signature sig; + + ~UpdateExitVerifyMessage() override = default; + + void + clear() override { - using Nonce_t = llarp::AlignedBuffer<16>; + tx_id = 0; + nonce.Zero(); + sig.Zero(); + } + + std::string + bt_encode() const override; + + bool + decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; + + bool + handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + }; + + struct UpdateExitMessage final : public AbstractRoutingMessage + { + using Nonce_t = llarp::AlignedBuffer<16>; + llarp::PathID_t path_id; + uint64_t tx_id; + Nonce_t nonce; + llarp::Signature sig; + + bool + Sign(const llarp::SecretKey& sk); - Nonce_t Y; - llarp::Signature Z; + bool + Verify(const llarp::PubKey& pk) const; - bool - BEncode(llarp_buffer_t* buf) const override; + std::string + bt_encode() const override; - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) override; + bool + decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; - bool - HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + bool + handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; - bool - Sign(const llarp::SecretKey& sk); + void + clear() override + { + path_id.Zero(); + tx_id = 0; + nonce.Zero(); + sig.Zero(); + } + }; + + struct CloseExitMessage final : public AbstractRoutingMessage + { + using Nonce_t = llarp::AlignedBuffer<16>; + + Nonce_t nonce; + llarp::Signature sig; + + std::string + bt_encode() const override; - bool - Verify(const llarp::PubKey& pk) const; + bool + decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; - void - Clear() override - { - Y.Zero(); - Z.Zero(); - } - }; + bool + handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; - } // namespace routing -} // namespace llarp + bool + Sign(const llarp::SecretKey& sk); + + bool + Verify(const llarp::PubKey& pk) const; + + void + clear() override + { + nonce.Zero(); + sig.Zero(); + } + }; +} // namespace llarp::routing diff --git a/llarp/exit/policy.cpp b/llarp/exit/policy.cpp index d9b230f51f..9fe49243b3 100644 --- a/llarp/exit/policy.cpp +++ b/llarp/exit/policy.cpp @@ -1,39 +1,36 @@ #include "policy.hpp" -namespace llarp +namespace llarp::exit { - namespace exit + void + Policy::bt_encode(oxenc::bt_dict_producer& btdp) const { - bool - Policy::BEncode(llarp_buffer_t* buf) const + try { - if (!bencode_start_dict(buf)) - return false; - if (!BEncodeWriteDictInt("a", proto, buf)) - return false; - if (!BEncodeWriteDictInt("b", port, buf)) - return false; - if (!BEncodeWriteDictInt("d", drop, buf)) - return false; - if (!BEncodeWriteDictInt("v", version, buf)) - return false; - return bencode_end(buf); + btdp.append("a", proto); + btdp.append("b", port); + btdp.append("d", drop); + btdp.append("v", version); } - - bool - Policy::DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* buf) + catch (...) { - bool read = false; - if (!BEncodeMaybeReadDictInt("a", proto, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("b", port, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("d", drop, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("v", version, read, k, buf)) - return false; - return read; + log::critical(policy_cat, "Error: exit Policy failed to bt encode contents!"); } + } + + bool + Policy::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) + { + bool read = false; + if (!BEncodeMaybeReadDictInt("a", proto, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictInt("b", port, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictInt("d", drop, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictInt("v", version, read, k, buf)) + return false; + return read; + } - } // namespace exit -} // namespace llarp +} // namespace llarp::exit diff --git a/llarp/exit/policy.hpp b/llarp/exit/policy.hpp index de41e1ebcd..60b20d95ac 100644 --- a/llarp/exit/policy.hpp +++ b/llarp/exit/policy.hpp @@ -1,29 +1,32 @@ #pragma once +#include #include -namespace llarp +namespace { - namespace exit + static auto policy_cat = llarp::log::Cat("lokinet.policy"); +} // namespace + +namespace llarp::exit +{ + struct Policy { - struct Policy - { - uint64_t proto = 0; - uint64_t port = 0; - uint64_t drop = 0; - uint64_t version = llarp::constants::proto_version; + uint64_t proto = 0; + uint64_t port = 0; + uint64_t drop = 0; + uint64_t version = llarp::constants::proto_version; - bool - BDecode(llarp_buffer_t* buf) - { - return bencode_decode_dict(*this, buf); - } + bool + BDecode(llarp_buffer_t* buf) + { + return bencode_decode_dict(*this, buf); + } - bool - DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* val); + bool + decode_key(const llarp_buffer_t& k, llarp_buffer_t* val); - bool - BEncode(llarp_buffer_t* buf) const; - }; - } // namespace exit -} // namespace llarp + void + bt_encode(oxenc::bt_dict_producer& btdp) const; + }; +} // namespace llarp::exit diff --git a/llarp/exit/session.cpp b/llarp/exit/session.cpp index 8c8553922e..6d6ea988f9 100644 --- a/llarp/exit/session.cpp +++ b/llarp/exit/session.cpp @@ -9,380 +9,377 @@ #include #include -namespace llarp +namespace llarp::exit { - namespace exit + BaseSession::BaseSession( + const llarp::RouterID& routerId, + std::function writepkt, + AbstractRouter* r, + size_t numpaths, + size_t hoplen, + EndpointBase* parent) + : llarp::path::Builder{r, numpaths, hoplen} + , m_ExitRouter{routerId} + , m_WritePacket{std::move(writepkt)} + , m_Counter{0} + , m_LastUse{r->Now()} + , m_BundleRC{false} + , m_Parent{parent} { - BaseSession::BaseSession( - const llarp::RouterID& routerId, - std::function writepkt, - AbstractRouter* r, - size_t numpaths, - size_t hoplen, - EndpointBase* parent) - : llarp::path::Builder{r, numpaths, hoplen} - , m_ExitRouter{routerId} - , m_WritePacket{std::move(writepkt)} - , m_Counter{0} - , m_LastUse{r->Now()} - , m_BundleRC{false} - , m_Parent{parent} - { - CryptoManager::instance()->identity_keygen(m_ExitIdentity); - } + CryptoManager::instance()->identity_keygen(m_ExitIdentity); + } - BaseSession::~BaseSession() = default; + BaseSession::~BaseSession() = default; - void - BaseSession::HandlePathDied(path::Path_ptr p) - { - p->Rebuild(); - } + void + BaseSession::HandlePathDied(path::Path_ptr p) + { + p->Rebuild(); + } - util::StatusObject - BaseSession::ExtractStatus() const - { - auto obj = path::Builder::ExtractStatus(); - obj["lastExitUse"] = to_json(m_LastUse); - auto pub = m_ExitIdentity.toPublic(); - obj["exitIdentity"] = pub.ToString(); - obj["endpoint"] = m_ExitRouter.ToString(); - return obj; - } + util::StatusObject + BaseSession::ExtractStatus() const + { + auto obj = path::Builder::ExtractStatus(); + obj["lastExitUse"] = to_json(m_LastUse); + auto pub = m_ExitIdentity.toPublic(); + obj["exitIdentity"] = pub.ToString(); + obj["endpoint"] = m_ExitRouter.ToString(); + return obj; + } + + bool + BaseSession::LoadIdentityFromFile(const char* fname) + { + return m_ExitIdentity.LoadFromFile(fname); + } - bool - BaseSession::LoadIdentityFromFile(const char* fname) - { - return m_ExitIdentity.LoadFromFile(fname); - } + bool + BaseSession::ShouldBuildMore(llarp_time_t now) const + { + if (BuildCooldownHit(now)) + return false; + const size_t expect = (1 + (numDesiredPaths / 2)); + // check 30 seconds into the future and see if we need more paths + const llarp_time_t future = now + 30s + buildIntervalLimit; + return NumPathsExistingAt(future) < expect; + } + + void + BaseSession::BlacklistSNode(const RouterID snode) + { + m_SnodeBlacklist.insert(std::move(snode)); + } - bool - BaseSession::ShouldBuildMore(llarp_time_t now) const + std::optional> + BaseSession::GetHopsForBuild() + { + if (numHops == 1) { - if (BuildCooldownHit(now)) - return false; - const size_t expect = (1 + (numDesiredPaths / 2)); - // check 30 seconds into the future and see if we need more paths - const llarp_time_t future = now + 30s + buildIntervalLimit; - return NumPathsExistingAt(future) < expect; + if (auto maybe = m_router->nodedb()->Get(m_ExitRouter)) + return std::vector{*maybe}; + return std::nullopt; } + else + return GetHopsAlignedToForBuild(m_ExitRouter); + } - void - BaseSession::BlacklistSNode(const RouterID snode) - { - m_SnodeBlacklist.insert(std::move(snode)); - } + bool + BaseSession::CheckPathDead(path::Path_ptr, llarp_time_t dlt) + { + return dlt >= path::alive_timeout; + } - std::optional> - BaseSession::GetHopsForBuild() + void + BaseSession::HandlePathBuilt(llarp::path::Path_ptr p) + { + path::Builder::HandlePathBuilt(p); + p->SetDropHandler(util::memFn(&BaseSession::HandleTrafficDrop, this)); + p->SetDeadChecker(util::memFn(&BaseSession::CheckPathDead, this)); + p->SetExitTrafficHandler(util::memFn(&BaseSession::HandleTraffic, this)); + p->AddObtainExitHandler(util::memFn(&BaseSession::HandleGotExit, this)); + + routing::ObtainExitMessage obtain; + obtain.sequence_number = p->NextSeqNo(); + obtain.tx_id = llarp::randint(); + PopulateRequest(obtain); + if (!obtain.Sign(m_ExitIdentity)) { - if (numHops == 1) - { - if (auto maybe = m_router->nodedb()->Get(m_ExitRouter)) - return std::vector{*maybe}; - return std::nullopt; - } - else - return GetHopsAlignedToForBuild(m_ExitRouter); + llarp::LogError("Failed to sign exit request"); + return; } + if (p->SendExitRequest(obtain, m_router)) + llarp::LogInfo("asking ", m_ExitRouter, " for exit"); + else + llarp::LogError("failed to send exit request"); + } + + void + BaseSession::AddReadyHook(SessionReadyFunc func) + { + m_PendingCallbacks.emplace_back(func); + } - bool - BaseSession::CheckPathDead(path::Path_ptr, llarp_time_t dlt) + bool + BaseSession::HandleGotExit(llarp::path::Path_ptr p, llarp_time_t b) + { + if (b == 0s) { - return dlt >= path::alive_timeout; + llarp::LogInfo("obtained an exit via ", p->Endpoint()); + m_CurrentPath = p->RXID(); + CallPendingCallbacks(true); } + return true; + } - void - BaseSession::HandlePathBuilt(llarp::path::Path_ptr p) - { - path::Builder::HandlePathBuilt(p); - p->SetDropHandler(util::memFn(&BaseSession::HandleTrafficDrop, this)); - p->SetDeadChecker(util::memFn(&BaseSession::CheckPathDead, this)); - p->SetExitTrafficHandler(util::memFn(&BaseSession::HandleTraffic, this)); - p->AddObtainExitHandler(util::memFn(&BaseSession::HandleGotExit, this)); - - routing::ObtainExitMessage obtain; - obtain.S = p->NextSeqNo(); - obtain.T = llarp::randint(); - PopulateRequest(obtain); - if (!obtain.Sign(m_ExitIdentity)) - { - llarp::LogError("Failed to sign exit request"); - return; - } - if (p->SendExitRequest(obtain, m_router)) - llarp::LogInfo("asking ", m_ExitRouter, " for exit"); - else - llarp::LogError("failed to send exit request"); - } + void + BaseSession::CallPendingCallbacks(bool success) + { + if (m_PendingCallbacks.empty()) + return; - void - BaseSession::AddReadyHook(SessionReadyFunc func) + if (success) { - m_PendingCallbacks.emplace_back(func); + auto self = shared_from_this(); + for (auto& f : m_PendingCallbacks) + f(self); } - - bool - BaseSession::HandleGotExit(llarp::path::Path_ptr p, llarp_time_t b) + else { - if (b == 0s) - { - llarp::LogInfo("obtained an exit via ", p->Endpoint()); - m_CurrentPath = p->RXID(); - CallPendingCallbacks(true); - } - return true; + for (auto& f : m_PendingCallbacks) + f(nullptr); } + m_PendingCallbacks.clear(); + } - void - BaseSession::CallPendingCallbacks(bool success) - { - if (m_PendingCallbacks.empty()) - return; - - if (success) - { - auto self = shared_from_this(); - for (auto& f : m_PendingCallbacks) - f(self); - } - else + void + BaseSession::ResetInternalState() + { + auto sendExitClose = [&](const llarp::path::Path_ptr p) { + const static auto roles = llarp::path::ePathRoleExit | llarp::path::ePathRoleSVC; + if (p->SupportsAnyRoles(roles)) { - for (auto& f : m_PendingCallbacks) - f(nullptr); - } - m_PendingCallbacks.clear(); - } - - void - BaseSession::ResetInternalState() - { - auto sendExitClose = [&](const llarp::path::Path_ptr p) { - const static auto roles = llarp::path::ePathRoleExit | llarp::path::ePathRoleSVC; - if (p->SupportsAnyRoles(roles)) + llarp::LogInfo(p->Name(), " closing exit path"); + routing::CloseExitMessage msg; + if (msg.Sign(m_ExitIdentity) && p->SendExitClose(msg, m_router)) { - llarp::LogInfo(p->Name(), " closing exit path"); - routing::CloseExitMessage msg; - if (msg.Sign(m_ExitIdentity) && p->SendExitClose(msg, m_router)) - { - p->ClearRoles(roles); - } - else - llarp::LogWarn(p->Name(), " failed to send exit close message"); + p->ClearRoles(roles); } - }; - ForEachPath(sendExitClose); - path::Builder::ResetInternalState(); - } - - bool - BaseSession::Stop() - { - CallPendingCallbacks(false); - auto sendExitClose = [&](const path::Path_ptr p) { - if (p->SupportsAnyRoles(path::ePathRoleExit)) - { - LogInfo(p->Name(), " closing exit path"); - routing::CloseExitMessage msg; - if (!(msg.Sign(m_ExitIdentity) && p->SendExitClose(msg, m_router))) - LogWarn(p->Name(), " failed to send exit close message"); - } - }; - ForEachPath(sendExitClose); - m_router->pathContext().RemovePathSet(shared_from_this()); - return path::Builder::Stop(); - } - - bool - BaseSession::HandleTraffic( - llarp::path::Path_ptr path, - const llarp_buffer_t& buf, - uint64_t counter, - service::ProtocolType t) - { - const service::ConvoTag tag{path->RXID().as_array()}; - - if (t == service::ProtocolType::QUIC) - { - auto quic = m_Parent->GetQUICTunnel(); - if (not quic) - return false; - quic->receive_packet(tag, buf); - return true; + else + llarp::LogWarn(p->Name(), " failed to send exit close message"); } + }; + ForEachPath(sendExitClose); + path::Builder::ResetInternalState(); + } - if (m_WritePacket) + bool + BaseSession::Stop() + { + CallPendingCallbacks(false); + auto sendExitClose = [&](const path::Path_ptr p) { + if (p->SupportsAnyRoles(path::ePathRoleExit)) { - llarp::net::IPPacket pkt{buf.view_all()}; - if (pkt.empty()) - return false; - m_LastUse = m_router->Now(); - m_Downstream.emplace(counter, pkt); - return true; + LogInfo(p->Name(), " closing exit path"); + routing::CloseExitMessage msg; + if (!(msg.Sign(m_ExitIdentity) && p->SendExitClose(msg, m_router))) + LogWarn(p->Name(), " failed to send exit close message"); } - return false; - } + }; + ForEachPath(sendExitClose); + m_router->pathContext().RemovePathSet(shared_from_this()); + return path::Builder::Stop(); + } + + bool + BaseSession::HandleTraffic( + llarp::path::Path_ptr path, + const llarp_buffer_t& buf, + uint64_t counter, + service::ProtocolType t) + { + const service::ConvoTag tag{path->RXID().as_array()}; - bool - BaseSession::HandleTrafficDrop(llarp::path::Path_ptr p, const PathID_t& path, uint64_t s) + if (t == service::ProtocolType::QUIC) { - llarp::LogError("dropped traffic on exit ", m_ExitRouter, " S=", s, " P=", path); - p->EnterState(path::ePathIgnore, m_router->Now()); + auto quic = m_Parent->GetQUICTunnel(); + if (not quic) + return false; + quic->receive_packet(tag, buf); return true; } - bool - BaseSession::QueueUpstreamTraffic( - llarp::net::IPPacket pkt, const size_t N, service::ProtocolType t) + if (m_WritePacket) { - auto& queue = m_Upstream[pkt.size() / N]; - // queue overflow - if (queue.size() >= MaxUpstreamQueueLength) + llarp::net::IPPacket pkt{buf.view_all()}; + if (pkt.empty()) return false; - if (queue.size() == 0) - { - queue.emplace_back(); - queue.back().protocol = t; - return queue.back().PutBuffer(llarp_buffer_t{pkt}, m_Counter++); - } - auto& back = queue.back(); - // pack to nearest N - if (back.Size() + pkt.size() > N) - { - queue.emplace_back(); - queue.back().protocol = t; - return queue.back().PutBuffer(llarp_buffer_t{pkt}, m_Counter++); - } - back.protocol = t; - return back.PutBuffer(llarp_buffer_t{pkt}, m_Counter++); + m_LastUse = m_router->Now(); + m_Downstream.emplace(counter, pkt); + return true; } + return false; + } - bool - BaseSession::IsReady() const + bool + BaseSession::HandleTrafficDrop(llarp::path::Path_ptr p, const PathID_t& path, uint64_t s) + { + llarp::LogError("dropped traffic on exit ", m_ExitRouter, " S=", s, " P=", path); + p->EnterState(path::ePathIgnore, m_router->Now()); + return true; + } + + bool + BaseSession::QueueUpstreamTraffic( + llarp::net::IPPacket pkt, const size_t N, service::ProtocolType t) + { + auto& queue = m_Upstream[pkt.size() / N]; + // queue overflow + if (queue.size() >= MaxUpstreamQueueLength) + return false; + if (queue.size() == 0) { - if (m_CurrentPath.IsZero()) - return false; - const size_t expect = (1 + (numDesiredPaths / 2)); - return AvailablePaths(llarp::path::ePathRoleExit) >= expect; + queue.emplace_back(); + queue.back().protocol = t; + return queue.back().PutBuffer(llarp_buffer_t{pkt}, m_Counter++); } - - bool - BaseSession::IsExpired(llarp_time_t now) const + auto& back = queue.back(); + // pack to nearest N + if (back.Size() + pkt.size() > N) { - return now > m_LastUse && now - m_LastUse > LifeSpan; + queue.emplace_back(); + queue.back().protocol = t; + return queue.back().PutBuffer(llarp_buffer_t{pkt}, m_Counter++); } + back.protocol = t; + return back.PutBuffer(llarp_buffer_t{pkt}, m_Counter++); + } - bool - BaseSession::UrgentBuild(llarp_time_t now) const - { - if (BuildCooldownHit(now)) - return false; - if (IsReady() and NumInStatus(path::ePathBuilding) < numDesiredPaths) - return path::Builder::UrgentBuild(now); + bool + BaseSession::IsReady() const + { + if (m_CurrentPath.IsZero()) return false; - } + const size_t expect = (1 + (numDesiredPaths / 2)); + return AvailablePaths(llarp::path::ePathRoleExit) >= expect; + } - bool - BaseSession::FlushUpstream() + bool + BaseSession::IsExpired(llarp_time_t now) const + { + return now > m_LastUse && now - m_LastUse > LifeSpan; + } + + bool + BaseSession::UrgentBuild(llarp_time_t now) const + { + if (BuildCooldownHit(now)) + return false; + if (IsReady() and NumInStatus(path::ePathBuilding) < numDesiredPaths) + return path::Builder::UrgentBuild(now); + return false; + } + + bool + BaseSession::FlushUpstream() + { + auto now = m_router->Now(); + auto path = PickEstablishedPath(llarp::path::ePathRoleExit); + if (path) { - auto now = m_router->Now(); - auto path = PickEstablishedPath(llarp::path::ePathRoleExit); - if (path) + for (auto& [i, queue] : m_Upstream) { - for (auto& [i, queue] : m_Upstream) + while (queue.size()) { - while (queue.size()) - { - auto& msg = queue.front(); - msg.S = path->NextSeqNo(); - path->SendRoutingMessage(msg, m_router); - queue.pop_front(); - } + auto& msg = queue.front(); + msg.sequence_number = path->NextSeqNo(); + path->SendRoutingMessage(msg, m_router); + queue.pop_front(); } } - else - { - if (m_Upstream.size()) - llarp::LogWarn("no path for exit session"); - // discard upstream - for (auto& [i, queue] : m_Upstream) - queue.clear(); - m_Upstream.clear(); - if (numHops == 1) - { - auto r = m_router; - if (const auto maybe = r->nodedb()->Get(m_ExitRouter); maybe.has_value()) - r->TryConnectAsync(*maybe, 5); - else - r->LookupRouter(m_ExitRouter, [r](const std::vector& results) { - if (results.size()) - r->TryConnectAsync(results[0], 5); - }); - } - else if (UrgentBuild(now)) - BuildOneAlignedTo(m_ExitRouter); - } - return true; } - - void - BaseSession::FlushDownstream() + else { - while (m_Downstream.size()) - { - if (m_WritePacket) - m_WritePacket(const_cast(m_Downstream.top().second).steal()); - m_Downstream.pop(); - } - } - - SNodeSession::SNodeSession( - const llarp::RouterID& snodeRouter, - std::function writepkt, - AbstractRouter* r, - size_t numpaths, - size_t hoplen, - bool useRouterSNodeKey, - EndpointBase* parent) - : BaseSession{snodeRouter, writepkt, r, numpaths, hoplen, parent} - { - if (useRouterSNodeKey) + if (m_Upstream.size()) + llarp::LogWarn("no path for exit session"); + // discard upstream + for (auto& [i, queue] : m_Upstream) + queue.clear(); + m_Upstream.clear(); + if (numHops == 1) { - m_ExitIdentity = r->identity(); + auto r = m_router; + if (const auto maybe = r->nodedb()->Get(m_ExitRouter); maybe.has_value()) + r->TryConnectAsync(*maybe, 5); + else + r->LookupRouter(m_ExitRouter, [r](const std::vector& results) { + if (results.size()) + r->TryConnectAsync(results[0], 5); + }); } + else if (UrgentBuild(now)) + BuildOneAlignedTo(m_ExitRouter); } + return true; + } - std::string - SNodeSession::Name() const + void + BaseSession::FlushDownstream() + { + while (m_Downstream.size()) { - return "SNode::" + m_ExitRouter.ToString(); + if (m_WritePacket) + m_WritePacket(const_cast(m_Downstream.top().second).steal()); + m_Downstream.pop(); } - - std::string - ExitSession::Name() const + } + + SNodeSession::SNodeSession( + const llarp::RouterID& snodeRouter, + std::function writepkt, + AbstractRouter* r, + size_t numpaths, + size_t hoplen, + bool useRouterSNodeKey, + EndpointBase* parent) + : BaseSession{snodeRouter, writepkt, r, numpaths, hoplen, parent} + { + if (useRouterSNodeKey) { - return "Exit::" + m_ExitRouter.ToString(); + m_ExitIdentity = r->identity(); } + } - void - SNodeSession::SendPacketToRemote(const llarp_buffer_t& buf, service::ProtocolType t) - { - net::IPPacket pkt{buf.view_all()}; - if (pkt.empty()) - return; - pkt.ZeroAddresses(); - QueueUpstreamTraffic(std::move(pkt), llarp::routing::ExitPadSize, t); - } + std::string + SNodeSession::Name() const + { + return "SNode::" + m_ExitRouter.ToString(); + } - void - ExitSession::SendPacketToRemote(const llarp_buffer_t& buf, service::ProtocolType t) - { - net::IPPacket pkt{buf.view_all()}; - if (pkt.empty()) - return; + std::string + ExitSession::Name() const + { + return "Exit::" + m_ExitRouter.ToString(); + } - pkt.ZeroSourceAddress(); - QueueUpstreamTraffic(std::move(pkt), llarp::routing::ExitPadSize, t); - } - } // namespace exit -} // namespace llarp + void + SNodeSession::SendPacketToRemote(const llarp_buffer_t& buf, service::ProtocolType t) + { + net::IPPacket pkt{buf.view_all()}; + if (pkt.empty()) + return; + pkt.ZeroAddresses(); + QueueUpstreamTraffic(std::move(pkt), llarp::routing::EXIT_PAD_SIZE, t); + } + + void + ExitSession::SendPacketToRemote(const llarp_buffer_t& buf, service::ProtocolType t) + { + net::IPPacket pkt{buf.view_all()}; + if (pkt.empty()) + return; + + pkt.ZeroSourceAddress(); + QueueUpstreamTraffic(std::move(pkt), llarp::routing::EXIT_PAD_SIZE, t); + } +} // namespace llarp::exit diff --git a/llarp/exit/session.hpp b/llarp/exit/session.hpp index 7191cc104b..6d90a9b94f 100644 --- a/llarp/exit/session.hpp +++ b/llarp/exit/session.hpp @@ -218,8 +218,8 @@ namespace llarp PopulateRequest(llarp::routing::ObtainExitMessage& msg) const override { // TODO: set expiration time - msg.X = 0; - msg.E = 1; + msg.address_lifetime = 0; + msg.flag = 1; } }; @@ -247,8 +247,8 @@ namespace llarp PopulateRequest(llarp::routing::ObtainExitMessage& msg) const override { // TODO: set expiration time - msg.X = 0; - msg.E = 0; + msg.address_lifetime = 0; + msg.flag = 0; } }; diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index e4dd2d3252..0f3906eda7 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -10,7 +10,7 @@ namespace llarp { link::Endpoint* - LinkManager::GetCompatibleLink(const RouterContact& rc) + LinkManager::GetCompatibleLink(const RouterContact&) { if (stopping) return nullptr; @@ -31,9 +31,9 @@ namespace llarp bool LinkManager::SendTo( const RouterID& remote, - const llarp_buffer_t& buf, + const llarp_buffer_t&, AbstractLinkSession::CompletionHandler completed, - uint16_t priority) + uint16_t) { if (stopping) return false; @@ -199,7 +199,7 @@ namespace llarp // TODO: this? perhaps no longer necessary in the same way? void - LinkManager::CheckPersistingSessions(llarp_time_t now) + LinkManager::CheckPersistingSessions(llarp_time_t) { if (stopping) return; @@ -207,7 +207,7 @@ namespace llarp // TODO: do we still need this concept? void - LinkManager::updatePeerDb(std::shared_ptr peerDb) + LinkManager::updatePeerDb(std::shared_ptr) {} // TODO: this @@ -228,7 +228,7 @@ namespace llarp void LinkManager::Connect(RouterID router) { - auto fn = [this](const RouterID& r, const RouterContact* const rc, const RCRequestResult res) { + auto fn = [this](const RouterID&, const RouterContact* const rc, const RCRequestResult res) { if (res == RCRequestResult::Success) Connect(*rc); /* TODO: @@ -315,13 +315,13 @@ namespace llarp } void - LinkManager::HandleIncomingDataMessage(oxen::quic::dgram_interface& dgi, bstring dgram) + LinkManager::HandleIncomingDataMessage(oxen::quic::dgram_interface&, bstring) { // TODO: this } void - LinkManager::HandleIncomingControlMessage(oxen::quic::Stream& stream, bstring_view packet) + LinkManager::HandleIncomingControlMessage(oxen::quic::Stream&, bstring_view) { // TODO: this } diff --git a/llarp/messages/dht_immediate.cpp b/llarp/messages/dht_immediate.cpp index 81e34d7bc9..871a812238 100644 --- a/llarp/messages/dht_immediate.cpp +++ b/llarp/messages/dht_immediate.cpp @@ -11,6 +11,16 @@ namespace llarp version = 0; } + /** Note: this is where AbstractDHTMessage::bt_encode() is called. Contextually, this is a + bit confusing as it is within the ::bt_encode() method of DHTImmediateMessage, which is + not an AbstractDHTMessage, but an AbstractLinkMessage. To see why AbstractLinkMessage + overrides the ::bt_encode() that returns an std::string, see the comment in llarp/router/ + outbound_message_handler.cpp above OutboundMessageHandler::EncodeBuffer(...). + + In this context, there is already a bt_dict_producer being used by DHTImmediateMessage's + bt_encode() method. This allows us to easily choose the override of bt_encode() that returns + nothing, but takes a bt_dict_producer as a reference. + */ std::string DHTImmediateMessage::bt_encode() const { diff --git a/llarp/messages/discard.hpp b/llarp/messages/discard.hpp index c495e90920..cebc5782d3 100644 --- a/llarp/messages/discard.hpp +++ b/llarp/messages/discard.hpp @@ -7,9 +7,9 @@ namespace llarp { - struct DiscardMessage final : public AbstractLinkMessage + struct LinkDiscardMessage final : public AbstractLinkMessage { - DiscardMessage() : AbstractLinkMessage() + LinkDiscardMessage() : AbstractLinkMessage() {} std::string @@ -67,13 +67,13 @@ namespace llarp { struct DataDiscardMessage final : public AbstractRoutingMessage { - PathID_t P; + PathID_t path_id; DataDiscardMessage() = default; - DataDiscardMessage(const PathID_t& dst, uint64_t s) : P(dst) + DataDiscardMessage(const PathID_t& dst, uint64_t s) : path_id(dst) { - S = s; + sequence_number = s; version = llarp::constants::proto_version; } @@ -93,9 +93,9 @@ namespace llarp decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) override { bool read = false; - if (!BEncodeMaybeReadDictEntry("P", P, read, k, buf)) + if (!BEncodeMaybeReadDictEntry("P", path_id, read, k, buf)) return false; - if (!BEncodeMaybeReadDictInt("S", S, read, k, buf)) + if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf)) return false; if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) return false; @@ -110,8 +110,8 @@ namespace llarp try { btdp.append("A", "D"); - btdp.append("P", P.ToView()); - btdp.append("S", S); + btdp.append("P", path_id.ToView()); + btdp.append("S", sequence_number); btdp.append("V", version); } catch (...) diff --git a/llarp/messages/link_message_parser.cpp b/llarp/messages/link_message_parser.cpp index af2b5c75fe..ae4cf7e581 100644 --- a/llarp/messages/link_message_parser.cpp +++ b/llarp/messages/link_message_parser.cpp @@ -23,7 +23,7 @@ namespace llarp DHTImmediateMessage m; LR_CommitMessage c; LR_StatusMessage s; - DiscardMessage x; + LinkDiscardMessage x; msg_holder_t() = default; }; diff --git a/llarp/net/address_info.cpp b/llarp/net/address_info.cpp index d25b23645a..a0f972570d 100644 --- a/llarp/net/address_info.cpp +++ b/llarp/net/address_info.cpp @@ -33,7 +33,7 @@ namespace llarp } bool - AddressInfo::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) + AddressInfo::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) { uint64_t i; char tmp[128] = {0}; @@ -111,47 +111,30 @@ namespace llarp return false; } - bool - AddressInfo::BEncode(llarp_buffer_t* buff) const + std::string + AddressInfo::bt_encode() const { char ipbuff[128] = {0}; - const char* ipstr; - if (!bencode_start_dict(buff)) - return false; - /* rank */ - if (!bencode_write_bytestring(buff, "c", 1)) - return false; - if (!bencode_write_uint64(buff, rank)) - return false; - /* dialect */ - if (!bencode_write_bytestring(buff, "d", 1)) - return false; - if (!bencode_write_bytestring(buff, dialect.c_str(), dialect.size())) - return false; - /* encryption key */ - if (!bencode_write_bytestring(buff, "e", 1)) - return false; - if (!bencode_write_bytestring(buff, pubkey.data(), PUBKEYSIZE)) - return false; - /** ip */ - ipstr = inet_ntop(AF_INET6, (void*)&ip, ipbuff, sizeof(ipbuff)); - if (!ipstr) - return false; - if (!bencode_write_bytestring(buff, "i", 1)) - return false; - if (!bencode_write_bytestring(buff, ipstr, strnlen(ipstr, sizeof(ipbuff)))) - return false; - /** port */ - if (!bencode_write_bytestring(buff, "p", 1)) - return false; - if (!bencode_write_uint64(buff, port)) - return false; - - /** version */ - if (!bencode_write_uint64_entry(buff, "v", 1, llarp::constants::proto_version)) - return false; - /** end */ - return bencode_end(buff); + oxenc::bt_dict_producer btdp; + + try + { + btdp.append("c", rank); + btdp.append("d", dialect); + btdp.append("e", pubkey.ToView()); + + const char* ipstr = inet_ntop(AF_INET6, (void*)&ip, ipbuff, sizeof(ipbuff)); + + btdp.append("i", std::string_view{ipstr, strnlen(ipstr, sizeof(ipbuff))}); + btdp.append("p", port); + btdp.append("v", version); + } + catch (...) + { + log::critical(net_cat, "Error: AddressInfo failed to bt encode contents!"); + } + + return std::move(btdp).str(); } IpAddress @@ -159,7 +142,7 @@ namespace llarp { SockAddr addr(ip); addr.setPort(port); - return IpAddress(addr); + return {addr}; } void diff --git a/llarp/net/address_info.hpp b/llarp/net/address_info.hpp index 5b87c33170..a1971cbca8 100644 --- a/llarp/net/address_info.hpp +++ b/llarp/net/address_info.hpp @@ -35,11 +35,11 @@ namespace llarp return bencode_decode_dict(*this, buf); } - bool - BEncode(llarp_buffer_t* buf) const; + std::string + bt_encode() const; bool - DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* buf); + decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf); /// Return an IpAddress representing the address portion of this AddressInfo IpAddress diff --git a/llarp/net/exit_info.cpp b/llarp/net/exit_info.cpp index ef91471d3b..4d28de57e5 100644 --- a/llarp/net/exit_info.cpp +++ b/llarp/net/exit_info.cpp @@ -14,7 +14,7 @@ namespace llarp { bool - ExitInfo::BEncode(llarp_buffer_t* buf) const + ExitInfo::bt_encode(llarp_buffer_t* buf) const { SockAddr exitaddr = ipAddress.createSockAddr(); const auto* exitaddr6 = static_cast(exitaddr); @@ -62,7 +62,7 @@ namespace llarp } bool - ExitInfo::DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* buf) + ExitInfo::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) { bool read = false; if (!BEncodeMaybeReadDictEntry("k", pubkey, read, k, buf)) diff --git a/llarp/net/exit_info.hpp b/llarp/net/exit_info.hpp index 1db07aef38..b190ec9e01 100644 --- a/llarp/net/exit_info.hpp +++ b/llarp/net/exit_info.hpp @@ -29,7 +29,7 @@ namespace llarp {} bool - BEncode(llarp_buffer_t* buf) const; + bt_encode(llarp_buffer_t* buf) const; bool BDecode(llarp_buffer_t* buf) @@ -38,7 +38,7 @@ namespace llarp } bool - DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* buf); + decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf); std::string ToString() const; diff --git a/llarp/net/ip_packet.hpp b/llarp/net/ip_packet.hpp index 3a1ed2d74d..50565e4aa3 100644 --- a/llarp/net/ip_packet.hpp +++ b/llarp/net/ip_packet.hpp @@ -157,13 +157,12 @@ namespace llarp::net { if (auto* vec = std::get_if>(&udp_body)) return make_udp(src.getIP(), src.port(), dst.getIP(), dst.port(), std::move(*vec)); - else if (auto* buf = std::get_if(&udp_body)) + if (auto* buf = std::get_if(&udp_body)) return make_udp(src, dst, buf->copy()); - else - return net::IPPacket{size_t{}}; + return net::IPPacket{size_t{}}; } - [[deprecated("deprecated because of llarp_buffer_t")]] inline bool + inline bool Load(const llarp_buffer_t& buf) { _buf = buf.copy(); @@ -173,7 +172,7 @@ namespace llarp::net return false; } - [[deprecated("deprecated because of llarp_buffer_t")]] inline llarp_buffer_t + inline llarp_buffer_t ConstBuffer() const { return llarp_buffer_t{_buf}; @@ -275,8 +274,7 @@ namespace llarp::net { if (IsV4()) return Header()->protocol; - else - return HeaderV6()->protocol; + return HeaderV6()->protocol; } inline bool diff --git a/llarp/net/ip_range.cpp b/llarp/net/ip_range.cpp index eaee05fd48..23fe8b1c06 100644 --- a/llarp/net/ip_range.cpp +++ b/llarp/net/ip_range.cpp @@ -6,11 +6,17 @@ namespace llarp { - bool - IPRange::BEncode(llarp_buffer_t* buf) const + void + IPRange::bt_encode(oxenc::bt_list_producer& btlp) const { - const auto str = oxenc::bt_serialize(ToString()); - return buf->write(str.begin(), str.end()); + try + { + btlp.append(ToString()); + } + catch (...) + { + log::critical(net_cat, "Error: IPRange failed to bt encode contents"); + } } bool diff --git a/llarp/net/ip_range.hpp b/llarp/net/ip_range.hpp index f085048b28..20e5e87cf0 100644 --- a/llarp/net/ip_range.hpp +++ b/llarp/net/ip_range.hpp @@ -2,15 +2,23 @@ #include "ip.hpp" #include "net_bits.hpp" +#include #include #include #include +#include +#include #include #include #include #include +namespace +{ + static auto net_cat = llarp::log::Cat("lokinet.net"); +} // namespace + namespace llarp { struct IPRange @@ -150,8 +158,8 @@ namespace llarp bool FromString(std::string str); - bool - BEncode(llarp_buffer_t* buf) const; + void + bt_encode(oxenc::bt_list_producer& btlc) const; bool BDecode(llarp_buffer_t* buf); diff --git a/llarp/net/traffic_policy.cpp b/llarp/net/traffic_policy.cpp index e94cb94a71..794ac33830 100644 --- a/llarp/net/traffic_policy.cpp +++ b/llarp/net/traffic_policy.cpp @@ -105,59 +105,45 @@ namespace llarp::net return true; } - bool - ProtocolInfo::BEncode(llarp_buffer_t* buf) const + void + ProtocolInfo::bt_encode(oxenc::bt_list_producer& btlp) const { - if (not bencode_start_list(buf)) - return false; - if (not bencode_write_uint64(buf, static_cast>(protocol))) - return false; - if (port) + try { - const auto hostint = ToHost(*port); - if (not bencode_write_uint64(buf, hostint.h)) - return false; + { + auto sublist = btlp.append_list(); + sublist.append(static_cast(protocol)); + } + + btlp.append(ToHost(*port).h); + } + catch (...) + { + log::critical(net_cat, "Error: ProtocolInfo failed to bt encode contents!"); } - return bencode_end(buf); } - bool - TrafficPolicy::BEncode(llarp_buffer_t* buf) const + void + TrafficPolicy::bt_encode(oxenc::bt_dict_producer& btdp) const { - if (not bencode_start_dict(buf)) - return false; - - if (not bencode_write_bytestring(buf, "p", 1)) - return false; - - if (not bencode_start_list(buf)) - return false; - - for (const auto& item : protocols) + try { - if (not item.BEncode(buf)) - return false; - } - - if (not bencode_end(buf)) - return false; - - if (not bencode_write_bytestring(buf, "r", 1)) - return false; - - if (not bencode_start_list(buf)) - return false; + { + auto sublist = btdp.append_list("p"); + for (auto& p : protocols) + p.bt_encode(sublist); + } - for (const auto& item : ranges) + { + auto sublist = btdp.append_list("r"); + for (auto& r : ranges) + r.bt_encode(sublist); + } + } + catch (...) { - if (not item.BEncode(buf)) - return false; + log::critical(net_cat, "Error: TrafficPolicy failed to bt encode contents!"); } - - if (not bencode_end(buf)) - return false; - - return bencode_end(buf); } bool diff --git a/llarp/net/traffic_policy.hpp b/llarp/net/traffic_policy.hpp index a34456535e..6175b54e85 100644 --- a/llarp/net/traffic_policy.hpp +++ b/llarp/net/traffic_policy.hpp @@ -4,6 +4,8 @@ #include "ip_packet.hpp" #include "llarp/util/status.hpp" +#include + #include namespace llarp::net @@ -16,8 +18,8 @@ namespace llarp::net /// the layer 3 port if applicable std::optional port; - bool - BEncode(llarp_buffer_t* buf) const; + void + bt_encode(oxenc::bt_list_producer& btlp) const; bool BDecode(llarp_buffer_t* buf); @@ -50,8 +52,8 @@ namespace llarp::net /// protocols that are explicity allowed std::set protocols; - bool - BEncode(llarp_buffer_t* buf) const; + void + bt_encode(oxenc::bt_dict_producer& btdp) const; bool BDecode(llarp_buffer_t* buf); diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index b9cccbe4b4..211f276c91 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include @@ -53,7 +53,7 @@ namespace llarp::path } // initialize parts of the introduction intro.router = hops[hsz - 1].rc.pubkey; - intro.pathID = hops[hsz - 1].txID; + intro.path_id = hops[hsz - 1].txID; if (auto parent = m_PathSet.lock()) EnterState(ePathBuilding, parent->Now()); } @@ -415,11 +415,11 @@ namespace llarp::path const auto now = r->Now(); // send path latency test routing::PathLatencyMessage latency{}; - latency.T = randint(); - latency.S = NextSeqNo(); - m_LastLatencyTestID = latency.T; + latency.sent_time = randint(); + latency.sequence_number = NextSeqNo(); + m_LastLatencyTestID = latency.sent_time; m_LastLatencyTestTime = now; - LogDebug(Name(), " send latency test id=", latency.T); + LogDebug(Name(), " send latency test id=", latency.sent_time); if (not SendRoutingMessage(latency, r)) return false; FlushUpstream(r); @@ -627,12 +627,12 @@ namespace llarp::path const routing::UpdateExitVerifyMessage& msg, AbstractRouter* r) { (void)r; - if (m_UpdateExitTX && msg.T == m_UpdateExitTX) + if (m_UpdateExitTX && msg.tx_id == m_UpdateExitTX) { if (m_ExitUpdated) return m_ExitUpdated(shared_from_this()); } - if (m_CloseExitTX && msg.T == m_CloseExitTX) + if (m_CloseExitTX && msg.tx_id == m_CloseExitTX) { if (m_ExitClosed) return m_ExitClosed(shared_from_this()); @@ -640,6 +640,21 @@ namespace llarp::path return false; } + /** Note: this is one of two places where AbstractRoutingMessage::bt_encode() is called, the + other of which is llarp/path/transit_hop.cpp in TransitHop::SendRoutingMessage(). For now, + we will default to the override of ::bt_encode() that returns an std::string. The role that + llarp_buffer_t plays here is likely superfluous, and can be replaced with either a leaner + llarp_buffer, or just handled using strings. + + One important consideration is the frequency at which routing messages are sent, making + superfluous copies important to optimize out here. We have to instantiate at least one + std::string whether we pass a bt_dict_producer as a reference or create one within the + ::bt_encode() call. + + If we decide to stay with std::strings, the function Path::HandleUpstream (along with the + functions it calls and so on) will need to be modified to take an std::string that we can + std::move around. + */ bool Path::SendRoutingMessage(const routing::AbstractRoutingMessage& msg, AbstractRouter* r) { @@ -649,12 +664,10 @@ namespace llarp::path // FIXME: Why would we get uninitialized IMessages? if (msg.version != llarp::constants::proto_version) return false; - if (!msg.BEncode(&buf)) - { - LogError("Bencode failed"); - DumpBuffer(buf); - return false; - } + + auto bte = msg.bt_encode(); + buf.write(bte.begin(), bte.end()); + // make nonce TunnelNonce N; N.Randomize(); @@ -667,7 +680,13 @@ namespace llarp::path buf.sz = pad_size; } buf.cur = buf.base; - LogDebug("send routing message ", msg.S, " with ", buf.sz, " bytes to endpoint ", Endpoint()); + LogDebug( + "send routing message ", + msg.sequence_number, + " with ", + buf.sz, + " bytes to endpoint ", + Endpoint()); return HandleUpstream(buf, N, r); } @@ -684,7 +703,7 @@ namespace llarp::path { MarkActive(r->Now()); if (m_DropHandler) - return m_DropHandler(shared_from_this(), msg.P, msg.S); + return m_DropHandler(shared_from_this(), msg.path_id, msg.sequence_number); return true; } @@ -696,12 +715,12 @@ namespace llarp::path if (_status == ePathBuilding) { // finish initializing introduction - intro.expiresAt = buildStarted + hops[0].lifetime; + intro.expiry = buildStarted + hops[0].lifetime; r->routerProfiling().MarkPathSuccess(this); // persist session with upstream router until the path is done - r->PersistSessionUntil(Upstream(), intro.expiresAt); + r->PersistSessionUntil(Upstream(), intro.expiry); MarkActive(now); return SendLatencyMessage(r); } @@ -716,7 +735,7 @@ namespace llarp::path } bool - Path::HandleHiddenServiceFrame(const service::ProtocolFrame& frame) + Path::HandleHiddenServiceFrame(const service::ProtocolFrameMessage& frame) { if (auto parent = m_PathSet.lock()) { @@ -768,10 +787,10 @@ namespace llarp::path Path::HandleDHTMessage(const dht::AbstractDHTMessage& msg, AbstractRouter* r) { MarkActive(r->Now()); - routing::DHTMessage reply; - if (!msg.handle_message(r->dht(), reply.M)) + routing::PathDHTMessage reply; + if (!msg.handle_message(r->dht(), reply.dht_msgs)) return false; - if (reply.M.size()) + if (reply.dht_msgs.size()) return SendRoutingMessage(reply, r); return true; } @@ -800,7 +819,7 @@ namespace llarp::path Path::SendExitRequest(const routing::ObtainExitMessage& msg, AbstractRouter* r) { LogInfo(Name(), " sending exit request to ", Endpoint()); - m_ExitObtainTX = msg.T; + m_ExitObtainTX = msg.tx_id; return SendRoutingMessage(msg, r); } @@ -834,7 +853,7 @@ namespace llarp::path bool Path::HandleRejectExitMessage(const routing::RejectExitMessage& msg, AbstractRouter* r) { - if (m_ExitObtainTX && msg.T == m_ExitObtainTX) + if (m_ExitObtainTX && msg.tx_id == m_ExitObtainTX) { if (!msg.Verify(EndpointPubKey())) { @@ -843,7 +862,7 @@ namespace llarp::path } LogInfo(Name(), " ", Endpoint(), " Rejected exit"); MarkActive(r->Now()); - return InformExitResult(llarp_time_t(msg.B)); + return InformExitResult(llarp_time_t(msg.backoff_time)); } LogError(Name(), " got unwarranted RXM"); return false; @@ -852,7 +871,7 @@ namespace llarp::path bool Path::HandleGrantExitMessage(const routing::GrantExitMessage& msg, AbstractRouter* r) { - if (m_ExitObtainTX && msg.T == m_ExitObtainTX) + if (m_ExitObtainTX && msg.tx_id == m_ExitObtainTX) { if (!msg.Verify(EndpointPubKey())) { @@ -889,9 +908,9 @@ namespace llarp::path // handle traffic if we have a handler if (!m_ExitTrafficHandler) return false; - bool sent = msg.X.size() > 0; + bool sent = msg.enc_buf.size() > 0; auto self = shared_from_this(); - for (const auto& pkt : msg.X) + for (const auto& pkt : msg.enc_buf) { if (pkt.size() <= 8) continue; diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index c2a5407aa4..82e2fafcb2 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -77,7 +77,7 @@ namespace llarp using CheckForDeadFunc = std::function; using DropHandlerFunc = std::function; using HopList = std::vector; - using DataHandlerFunc = std::function; + using DataHandlerFunc = std::function; using ExitUpdatedFunc = std::function; using ExitClosedFunc = std::function; using ExitTrafficHandlerFunc = @@ -331,7 +331,7 @@ namespace llarp const routing::PathTransferMessage& msg, AbstractRouter* r) override; bool - HandleHiddenServiceFrame(const service::ProtocolFrame& frame) override; + HandleHiddenServiceFrame(const service::ProtocolFrameMessage& frame) override; bool HandleGotIntroMessage(const dht::GotIntroMessage& msg); diff --git a/llarp/path/pathset.cpp b/llarp/path/pathset.cpp index 0474544d2a..e47a762004 100644 --- a/llarp/path/pathset.cpp +++ b/llarp/path/pathset.cpp @@ -2,463 +2,464 @@ #include #include "path.hpp" -#include +#include #include #include -namespace llarp +namespace llarp::path { - namespace path - { - PathSet::PathSet(size_t num) : numDesiredPaths(num) - {} - - bool - PathSet::ShouldBuildMore(llarp_time_t now) const - { - (void)now; - const auto building = NumInStatus(ePathBuilding); - if (building >= numDesiredPaths) - return false; - const auto established = NumInStatus(ePathEstablished); - return established < numDesiredPaths; - } + PathSet::PathSet(size_t num) : numDesiredPaths(num) + {} - bool - PathSet::ShouldBuildMoreForRoles(llarp_time_t now, PathRole roles) const + bool + PathSet::ShouldBuildMore(llarp_time_t now) const + { + (void)now; + const auto building = NumInStatus(ePathBuilding); + if (building >= numDesiredPaths) + return false; + const auto established = NumInStatus(ePathEstablished); + return established < numDesiredPaths; + } + + bool + PathSet::ShouldBuildMoreForRoles(llarp_time_t now, PathRole roles) const + { + Lock_t l(m_PathsMutex); + const size_t required = MinRequiredForRoles(roles); + size_t has = 0; + for (const auto& item : m_Paths) { - Lock_t l(m_PathsMutex); - const size_t required = MinRequiredForRoles(roles); - size_t has = 0; - for (const auto& item : m_Paths) + if (item.second->SupportsAnyRoles(roles)) { - if (item.second->SupportsAnyRoles(roles)) - { - if (!item.second->ExpiresSoon(now)) - ++has; - } + if (!item.second->ExpiresSoon(now)) + ++has; } - return has < required; } + return has < required; + } - size_t - PathSet::MinRequiredForRoles(PathRole roles) const + size_t + PathSet::MinRequiredForRoles(PathRole roles) const + { + (void)roles; + return 0; + } + + size_t + PathSet::NumPathsExistingAt(llarp_time_t futureTime) const + { + size_t num = 0; + Lock_t l(m_PathsMutex); + for (const auto& item : m_Paths) { - (void)roles; - return 0; + if (item.second->IsReady() && !item.second->Expired(futureTime)) + ++num; } + return num; + } - size_t - PathSet::NumPathsExistingAt(llarp_time_t futureTime) const + void + PathSet::TickPaths(AbstractRouter* r) + { + const auto now = llarp::time_now_ms(); + Lock_t l{m_PathsMutex}; + for (auto& item : m_Paths) { - size_t num = 0; - Lock_t l(m_PathsMutex); - for (const auto& item : m_Paths) - { - if (item.second->IsReady() && !item.second->Expired(futureTime)) - ++num; - } - return num; + item.second->Tick(now, r); } + } - void - PathSet::TickPaths(AbstractRouter* r) + void + PathSet::Tick(llarp_time_t) + { + std::unordered_set endpoints; + for (auto& item : m_Paths) { - const auto now = llarp::time_now_ms(); - Lock_t l{m_PathsMutex}; - for (auto& item : m_Paths) - { - item.second->Tick(now, r); - } + endpoints.emplace(item.second->Endpoint()); } - void - PathSet::Tick(llarp_time_t) + m_PathCache.clear(); + for (const auto& ep : endpoints) { - std::unordered_set endpoints; - for (auto& item : m_Paths) - { - endpoints.emplace(item.second->Endpoint()); - } - - m_PathCache.clear(); - for (const auto& ep : endpoints) + if (auto path = GetPathByRouter(ep)) { - if (auto path = GetPathByRouter(ep)) - { - m_PathCache[ep] = path->weak_from_this(); - } + m_PathCache[ep] = path->weak_from_this(); } } + } - void - PathSet::ExpirePaths(llarp_time_t now, AbstractRouter* router) + void + PathSet::ExpirePaths(llarp_time_t now, AbstractRouter* router) + { + Lock_t l(m_PathsMutex); + if (m_Paths.size() == 0) + return; + auto itr = m_Paths.begin(); + while (itr != m_Paths.end()) { - Lock_t l(m_PathsMutex); - if (m_Paths.size() == 0) - return; - auto itr = m_Paths.begin(); - while (itr != m_Paths.end()) + if (itr->second->Expired(now)) { - if (itr->second->Expired(now)) - { - PathID_t txid = itr->second->TXID(); - router->outboundMessageHandler().RemovePath(std::move(txid)); - PathID_t rxid = itr->second->RXID(); - router->outboundMessageHandler().RemovePath(std::move(rxid)); - itr = m_Paths.erase(itr); - } - else - ++itr; + PathID_t txid = itr->second->TXID(); + router->outboundMessageHandler().RemovePath(std::move(txid)); + PathID_t rxid = itr->second->RXID(); + router->outboundMessageHandler().RemovePath(std::move(rxid)); + itr = m_Paths.erase(itr); } + else + ++itr; } + } - Path_ptr - PathSet::GetEstablishedPathClosestTo( - RouterID id, std::unordered_set excluding, PathRole roles) const + Path_ptr + PathSet::GetEstablishedPathClosestTo( + RouterID id, std::unordered_set excluding, PathRole roles) const + { + Lock_t l{m_PathsMutex}; + Path_ptr path = nullptr; + AlignedBuffer<32> dist; + AlignedBuffer<32> to = id; + dist.Fill(0xff); + for (const auto& item : m_Paths) { - Lock_t l{m_PathsMutex}; - Path_ptr path = nullptr; - AlignedBuffer<32> dist; - AlignedBuffer<32> to = id; - dist.Fill(0xff); - for (const auto& item : m_Paths) + if (!item.second->IsReady()) + continue; + if (!item.second->SupportsAnyRoles(roles)) + continue; + if (excluding.count(item.second->Endpoint())) + continue; + AlignedBuffer<32> localDist = item.second->Endpoint() ^ to; + if (localDist < dist) { - if (!item.second->IsReady()) - continue; - if (!item.second->SupportsAnyRoles(roles)) - continue; - if (excluding.count(item.second->Endpoint())) - continue; - AlignedBuffer<32> localDist = item.second->Endpoint() ^ to; - if (localDist < dist) - { - dist = localDist; - path = item.second; - } + dist = localDist; + path = item.second; } - return path; } + return path; + } - Path_ptr - PathSet::GetNewestPathByRouter(RouterID id, PathRole roles) const + Path_ptr + PathSet::GetNewestPathByRouter(RouterID id, PathRole roles) const + { + Lock_t l(m_PathsMutex); + Path_ptr chosen = nullptr; + auto itr = m_Paths.begin(); + while (itr != m_Paths.end()) { - Lock_t l(m_PathsMutex); - Path_ptr chosen = nullptr; - auto itr = m_Paths.begin(); - while (itr != m_Paths.end()) + if (itr->second->IsReady() && itr->second->SupportsAnyRoles(roles)) { - if (itr->second->IsReady() && itr->second->SupportsAnyRoles(roles)) + if (itr->second->Endpoint() == id) { - if (itr->second->Endpoint() == id) - { - if (chosen == nullptr) - chosen = itr->second; - else if (chosen->intro.expiresAt < itr->second->intro.expiresAt) - chosen = itr->second; - } + // Note: revisit these, are they supposed to be redundant? + // if (chosen == nullptr) + // chosen = itr->second; + // else if (chosen->intro.expiry < itr->second->intro.expiry) + // chosen = itr->second; + chosen = itr->second; } - ++itr; } - return chosen; + ++itr; } + return chosen; + } - Path_ptr - PathSet::GetPathByRouter(RouterID id, PathRole roles) const + Path_ptr + PathSet::GetPathByRouter(RouterID id, PathRole roles) const + { + Lock_t l(m_PathsMutex); + Path_ptr chosen = nullptr; + if (roles == ePathRoleAny) { - Lock_t l(m_PathsMutex); - Path_ptr chosen = nullptr; - if (roles == ePathRoleAny) + if (auto itr = m_PathCache.find(id); itr != m_PathCache.end()) { - if (auto itr = m_PathCache.find(id); itr != m_PathCache.end()) - { - return itr->second.lock(); - } + return itr->second.lock(); } - auto itr = m_Paths.begin(); - while (itr != m_Paths.end()) - { - if (itr->second->IsReady() && itr->second->SupportsAnyRoles(roles)) - { - if (itr->second->Endpoint() == id) - { - if (chosen == nullptr) - chosen = itr->second; - else if ( - chosen->intro.latency != 0s and chosen->intro.latency > itr->second->intro.latency) - chosen = itr->second; - } - } - ++itr; - } - return chosen; } - - Path_ptr - PathSet::GetRandomPathByRouter(RouterID id, PathRole roles) const + auto itr = m_Paths.begin(); + while (itr != m_Paths.end()) { - Lock_t l(m_PathsMutex); - std::vector chosen; - auto itr = m_Paths.begin(); - while (itr != m_Paths.end()) + if (itr->second->IsReady() && itr->second->SupportsAnyRoles(roles)) { - if (itr->second->IsReady() && itr->second->SupportsAnyRoles(roles)) + if (itr->second->Endpoint() == id) { - if (itr->second->Endpoint() == id) - { - chosen.emplace_back(itr->second); - } + // Note: revisit these as well + // if (chosen == nullptr) + // chosen = itr->second; + // else if ( + // chosen->intro.latency != 0s and chosen->intro.latency > itr->second->intro.latency) + // chosen = itr->second; + chosen = itr->second; } - ++itr; } - if (chosen.empty()) - return nullptr; - size_t idx = 0; - if (chosen.size() >= 2) - { - idx = rand() % chosen.size(); - } - return chosen[idx]; + ++itr; } + return chosen; + } - Path_ptr - PathSet::GetByEndpointWithID(RouterID ep, PathID_t id) const + Path_ptr + PathSet::GetRandomPathByRouter(RouterID id, PathRole roles) const + { + Lock_t l(m_PathsMutex); + std::vector chosen; + auto itr = m_Paths.begin(); + while (itr != m_Paths.end()) { - Lock_t l(m_PathsMutex); - auto itr = m_Paths.begin(); - while (itr != m_Paths.end()) + if (itr->second->IsReady() && itr->second->SupportsAnyRoles(roles)) { - if (itr->second->IsEndpoint(ep, id)) + if (itr->second->Endpoint() == id) { - return itr->second; + chosen.emplace_back(itr->second); } - ++itr; } + ++itr; + } + if (chosen.empty()) return nullptr; + size_t idx = 0; + if (chosen.size() >= 2) + { + idx = rand() % chosen.size(); } + return chosen[idx]; + } - Path_ptr - PathSet::GetPathByID(PathID_t id) const + Path_ptr + PathSet::GetByEndpointWithID(RouterID ep, PathID_t id) const + { + Lock_t l(m_PathsMutex); + auto itr = m_Paths.begin(); + while (itr != m_Paths.end()) { - Lock_t l(m_PathsMutex); - auto itr = m_Paths.begin(); - while (itr != m_Paths.end()) + if (itr->second->IsEndpoint(ep, id)) { - if (itr->second->RXID() == id) - return itr->second; - ++itr; + return itr->second; } - return nullptr; + ++itr; } + return nullptr; + } - size_t - PathSet::AvailablePaths(PathRole roles) const + Path_ptr + PathSet::GetPathByID(PathID_t id) const + { + Lock_t l(m_PathsMutex); + auto itr = m_Paths.begin(); + while (itr != m_Paths.end()) { - Lock_t l(m_PathsMutex); - size_t count = 0; - auto itr = m_Paths.begin(); - while (itr != m_Paths.end()) - { - if (itr->second->Status() == ePathEstablished && itr->second->SupportsAnyRoles(roles)) - ++count; - ++itr; - } - return count; + if (itr->second->RXID() == id) + return itr->second; + ++itr; } + return nullptr; + } - size_t - PathSet::NumInStatus(PathStatus st) const + size_t + PathSet::AvailablePaths(PathRole roles) const + { + Lock_t l(m_PathsMutex); + size_t count = 0; + auto itr = m_Paths.begin(); + while (itr != m_Paths.end()) { - Lock_t l(m_PathsMutex); - size_t count = 0; - auto itr = m_Paths.begin(); - while (itr != m_Paths.end()) - { - if (itr->second->Status() == st) - ++count; - ++itr; - } - return count; + if (itr->second->Status() == ePathEstablished && itr->second->SupportsAnyRoles(roles)) + ++count; + ++itr; } + return count; + } - void - PathSet::AddPath(Path_ptr path) + size_t + PathSet::NumInStatus(PathStatus st) const + { + Lock_t l(m_PathsMutex); + size_t count = 0; + auto itr = m_Paths.begin(); + while (itr != m_Paths.end()) { - Lock_t l(m_PathsMutex); - const auto upstream = path->Upstream(); // RouterID - const auto RXID = path->RXID(); // PathID - if (not m_Paths.emplace(std::make_pair(upstream, RXID), path).second) - { - LogError( - Name(), - " failed to add own path, duplicate info wtf? upstream=", - upstream, - " rxid=", - RXID); - } + if (itr->second->Status() == st) + ++count; + ++itr; } + return count; + } - Path_ptr - PathSet::GetByUpstream(RouterID remote, PathID_t rxid) const + void + PathSet::AddPath(Path_ptr path) + { + Lock_t l(m_PathsMutex); + const auto upstream = path->Upstream(); // RouterID + const auto RXID = path->RXID(); // PathID + if (not m_Paths.emplace(std::make_pair(upstream, RXID), path).second) { - Lock_t l(m_PathsMutex); - auto itr = m_Paths.find({remote, rxid}); - if (itr == m_Paths.end()) - return nullptr; - return itr->second; + LogError( + Name(), + " failed to add own path, duplicate info wtf? upstream=", + upstream, + " rxid=", + RXID); } + } + + Path_ptr + PathSet::GetByUpstream(RouterID remote, PathID_t rxid) const + { + Lock_t l(m_PathsMutex); + auto itr = m_Paths.find({remote, rxid}); + if (itr == m_Paths.end()) + return nullptr; + return itr->second; + } - std::optional> - PathSet::GetCurrentIntroductionsWithFilter( - std::function filter) const + std::optional> + PathSet::GetCurrentIntroductionsWithFilter( + std::function filter) const + { + std::set intros; + Lock_t l{m_PathsMutex}; + auto itr = m_Paths.begin(); + while (itr != m_Paths.end()) { - std::set intros; - Lock_t l{m_PathsMutex}; - auto itr = m_Paths.begin(); - while (itr != m_Paths.end()) + if (itr->second->IsReady() and filter(itr->second->intro)) { - if (itr->second->IsReady() and filter(itr->second->intro)) - { - intros.insert(itr->second->intro); - } - ++itr; + intros.insert(itr->second->intro); } - if (intros.empty()) - return std::nullopt; - return intros; + ++itr; } + if (intros.empty()) + return std::nullopt; + return intros; + } - void - PathSet::HandlePathBuildTimeout(Path_ptr p) - { - LogWarn(Name(), " path build ", p->ShortName(), " timed out"); - m_BuildStats.timeouts++; - } + void + PathSet::HandlePathBuildTimeout(Path_ptr p) + { + LogWarn(Name(), " path build ", p->ShortName(), " timed out"); + m_BuildStats.timeouts++; + } - void - PathSet::HandlePathBuildFailedAt(Path_ptr p, RouterID hop) - { - LogWarn(Name(), " path build ", p->ShortName(), " failed at ", hop); - m_BuildStats.fails++; - } + void + PathSet::HandlePathBuildFailedAt(Path_ptr p, RouterID hop) + { + LogWarn(Name(), " path build ", p->ShortName(), " failed at ", hop); + m_BuildStats.fails++; + } - void - PathSet::HandlePathDied(Path_ptr p) - { - LogWarn(Name(), " path ", p->ShortName(), " died"); - } + void + PathSet::HandlePathDied(Path_ptr p) + { + LogWarn(Name(), " path ", p->ShortName(), " died"); + } - void - PathSet::PathBuildStarted(Path_ptr p) - { - LogInfo(Name(), " path build ", p->ShortName(), " started"); - m_BuildStats.attempts++; - } + void + PathSet::PathBuildStarted(Path_ptr p) + { + LogInfo(Name(), " path build ", p->ShortName(), " started"); + m_BuildStats.attempts++; + } - util::StatusObject - BuildStats::ExtractStatus() const - { - return util::StatusObject{ - {"success", success}, {"attempts", attempts}, {"timeouts", timeouts}, {"fails", fails}}; - } + util::StatusObject + BuildStats::ExtractStatus() const + { + return util::StatusObject{ + {"success", success}, {"attempts", attempts}, {"timeouts", timeouts}, {"fails", fails}}; + } - std::string - BuildStats::ToString() const + std::string + BuildStats::ToString() const + { + return fmt::format( + "{:.2f} percent success (success={} attempts={} timeouts={} fails={})", + SuccessRatio() * 100.0, + success, + attempts, + timeouts, + fails); + } + + double + BuildStats::SuccessRatio() const + { + if (attempts) + return double(success) / double(attempts); + return 0.0; + } + + bool + PathSet::GetNewestIntro(service::Introduction& intro) const + { + intro.Clear(); + bool found = false; + Lock_t l(m_PathsMutex); + auto itr = m_Paths.begin(); + while (itr != m_Paths.end()) { - return fmt::format( - "{:.2f} percent success (success={} attempts={} timeouts={} fails={})", - SuccessRatio() * 100.0, - success, - attempts, - timeouts, - fails); + if (itr->second->IsReady() && itr->second->intro.expiry > intro.expiry) + { + intro = itr->second->intro; + found = true; + } + ++itr; } + return found; + } - double - BuildStats::SuccessRatio() const + Path_ptr + PathSet::PickRandomEstablishedPath(PathRole roles) const + { + std::vector established; + Lock_t l(m_PathsMutex); + auto itr = m_Paths.begin(); + while (itr != m_Paths.end()) { - if (attempts) - return double(success) / double(attempts); - return 0.0; + if (itr->second->IsReady() && itr->second->SupportsAnyRoles(roles)) + established.push_back(itr->second); + ++itr; } - - bool - PathSet::GetNewestIntro(service::Introduction& intro) const + auto sz = established.size(); + if (sz) { - intro.Clear(); - bool found = false; - Lock_t l(m_PathsMutex); - auto itr = m_Paths.begin(); - while (itr != m_Paths.end()) - { - if (itr->second->IsReady() && itr->second->intro.expiresAt > intro.expiresAt) - { - intro = itr->second->intro; - found = true; - } - ++itr; - } - return found; + return established[randint() % sz]; } - Path_ptr - PathSet::PickRandomEstablishedPath(PathRole roles) const - { - std::vector established; - Lock_t l(m_PathsMutex); - auto itr = m_Paths.begin(); - while (itr != m_Paths.end()) - { - if (itr->second->IsReady() && itr->second->SupportsAnyRoles(roles)) - established.push_back(itr->second); - ++itr; - } - auto sz = established.size(); - if (sz) - { - return established[randint() % sz]; - } + return nullptr; + } - return nullptr; + Path_ptr + PathSet::PickEstablishedPath(PathRole roles) const + { + std::vector established; + Lock_t l(m_PathsMutex); + auto itr = m_Paths.begin(); + while (itr != m_Paths.end()) + { + if (itr->second->IsReady() && itr->second->SupportsAnyRoles(roles)) + established.push_back(itr->second); + ++itr; } - - Path_ptr - PathSet::PickEstablishedPath(PathRole roles) const + Path_ptr chosen = nullptr; + llarp_time_t minLatency = 30s; + for (const auto& path : established) { - std::vector established; - Lock_t l(m_PathsMutex); - auto itr = m_Paths.begin(); - while (itr != m_Paths.end()) + if (path->intro.latency < minLatency and path->intro.latency != 0s) { - if (itr->second->IsReady() && itr->second->SupportsAnyRoles(roles)) - established.push_back(itr->second); - ++itr; - } - Path_ptr chosen = nullptr; - llarp_time_t minLatency = 30s; - for (const auto& path : established) - { - if (path->intro.latency < minLatency and path->intro.latency != 0s) - { - minLatency = path->intro.latency; - chosen = path; - } + minLatency = path->intro.latency; + chosen = path; } - return chosen; } + return chosen; + } - void - PathSet::UpstreamFlush(AbstractRouter* r) - { - ForEachPath([r](const Path_ptr& p) { p->FlushUpstream(r); }); - } + void + PathSet::UpstreamFlush(AbstractRouter* r) + { + ForEachPath([r](const Path_ptr& p) { p->FlushUpstream(r); }); + } - void - PathSet::DownstreamFlush(AbstractRouter* r) - { - ForEachPath([r](const Path_ptr& p) { p->FlushDownstream(r); }); - } + void + PathSet::DownstreamFlush(AbstractRouter* r) + { + ForEachPath([r](const Path_ptr& p) { p->FlushDownstream(r); }); + } - } // namespace path -} // namespace llarp +} // namespace llarp::path diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index b1164f8776..dba3e6287b 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -69,6 +69,21 @@ namespace llarp::path : txID(record.txid), rxID(record.rxid), upstream(record.nextHop), downstream(down) {} + /** Note: this is one of two places where AbstractRoutingMessage::bt_encode() is called, the + other of which is llarp/path/path.cpp in Path::SendRoutingMessage(). For now, + we will default to the override of ::bt_encode() that returns an std::string. The role that + llarp_buffer_t plays here is likely superfluous, and can be replaced with either a leaner + llarp_buffer, or just handled using strings. + + One important consideration is the frequency at which routing messages are sent, making + superfluous copies important to optimize out here. We have to instantiate at least one + std::string whether we pass a bt_dict_producer as a reference or create one within the + ::bt_encode() call. + + If we decide to stay with std::strings, the function Path::HandleUpstream (along with the + functions it calls and so on) will need to be modified to take an std::string that we can + std::move around. + */ bool TransitHop::SendRoutingMessage(const routing::AbstractRoutingMessage& msg, AbstractRouter* r) { @@ -77,11 +92,10 @@ namespace llarp::path std::array tmp; llarp_buffer_t buf(tmp); - if (!msg.BEncode(&buf)) - { - llarp::LogError("failed to encode routing message"); - return false; - } + + auto bte = msg.bt_encode(); + buf.write(bte.begin(), bte.end()); + TunnelNonce N; N.Randomize(); buf.sz = buf.cur - buf.base; @@ -250,8 +264,8 @@ namespace llarp::path const llarp::routing::PathLatencyMessage& msg, AbstractRouter* r) { llarp::routing::PathLatencyMessage reply; - reply.L = msg.T; - reply.S = msg.S; + reply.latency = msg.sent_time; + reply.sequence_number = msg.sequence_number; return SendRoutingMessage(reply, r); } @@ -277,11 +291,11 @@ namespace llarp::path TransitHop::HandleObtainExitMessage( const llarp::routing::ObtainExitMessage& msg, AbstractRouter* r) { - if (msg.Verify() && r->exitContext().ObtainNewExit(msg.I, info.rxID, msg.E != 0)) + if (msg.Verify() && r->exitContext().ObtainNewExit(msg.pubkey, info.rxID, msg.flag != 0)) { llarp::routing::GrantExitMessage grant; - grant.S = NextSeqNo(); - grant.T = msg.T; + grant.sequence_number = NextSeqNo(); + grant.tx_id = msg.tx_id; if (!grant.Sign(r->identity())) { llarp::LogError("Failed to sign grant exit message"); @@ -292,8 +306,8 @@ namespace llarp::path // TODO: exponential backoff // TODO: rejected policies llarp::routing::RejectExitMessage reject; - reject.S = NextSeqNo(); - reject.T = msg.T; + reject.sequence_number = NextSeqNo(); + reject.tx_id = msg.tx_id; if (!reject.Sign(r->identity())) { llarp::LogError("Failed to sign reject exit message"); @@ -305,13 +319,13 @@ namespace llarp::path bool TransitHop::HandleCloseExitMessage(const llarp::routing::CloseExitMessage& msg, AbstractRouter* r) { - const llarp::routing::DataDiscardMessage discard(info.rxID, msg.S); + const llarp::routing::DataDiscardMessage discard(info.rxID, msg.sequence_number); auto ep = r->exitContext().FindEndpointForPath(info.rxID); if (ep && msg.Verify(ep->PubKey())) { llarp::routing::CloseExitMessage reply; - reply.Y = msg.Y; - reply.S = NextSeqNo(); + reply.nonce = msg.nonce; + reply.sequence_number = NextSeqNo(); if (reply.Sign(r->identity())) { if (SendRoutingMessage(reply, r)) @@ -338,7 +352,7 @@ namespace llarp::path TransitHop::HandleUpdateExitMessage( const llarp::routing::UpdateExitMessage& msg, AbstractRouter* r) { - auto ep = r->exitContext().FindEndpointForPath(msg.P); + auto ep = r->exitContext().FindEndpointForPath(msg.path_id); if (ep) { if (!msg.Verify(ep->PubKey())) @@ -347,13 +361,13 @@ namespace llarp::path if (ep->UpdateLocalPath(info.rxID)) { llarp::routing::UpdateExitVerifyMessage reply; - reply.T = msg.T; - reply.S = NextSeqNo(); + reply.tx_id = msg.tx_id; + reply.sequence_number = NextSeqNo(); return SendRoutingMessage(reply, r); } } // on fail tell message was discarded - llarp::routing::DataDiscardMessage discard(info.rxID, msg.S); + llarp::routing::DataDiscardMessage discard(info.rxID, msg.sequence_number); return SendRoutingMessage(discard, r); } @@ -384,7 +398,7 @@ namespace llarp::path if (endpoint) { bool sent = true; - for (const auto& pkt : msg.X) + for (const auto& pkt : msg.enc_buf) { // check short packet buffer if (pkt.size() <= 8) @@ -399,7 +413,7 @@ namespace llarp::path llarp::LogError("No exit endpoint on ", info); // discarded - llarp::routing::DataDiscardMessage discard(info.rxID, msg.S); + llarp::routing::DataDiscardMessage discard(info.rxID, msg.sequence_number); return SendRoutingMessage(discard, r); } @@ -407,14 +421,14 @@ namespace llarp::path TransitHop::HandlePathTransferMessage( const llarp::routing::PathTransferMessage& msg, AbstractRouter* r) { - auto path = r->pathContext().GetPathForTransfer(msg.P); - llarp::routing::DataDiscardMessage discarded{msg.P, msg.S}; - if (path == nullptr || msg.T.F != info.txID) + auto path = r->pathContext().GetPathForTransfer(msg.path_id); + llarp::routing::DataDiscardMessage discarded{msg.path_id, msg.sequence_number}; + if (path == nullptr || msg.protocol_frame_msg.path_id != info.txID) { return SendRoutingMessage(discarded, r); } // send routing message - if (path->SendRoutingMessage(msg.T, r)) + if (path->SendRoutingMessage(msg.protocol_frame_msg, r)) { m_FlushOthers.emplace(path); return true; diff --git a/llarp/path/transit_hop.hpp b/llarp/path/transit_hop.hpp index a6a8fc1efd..a52374734a 100644 --- a/llarp/path/transit_hop.hpp +++ b/llarp/path/transit_hop.hpp @@ -160,7 +160,7 @@ namespace llarp HandleCloseExitMessage(const routing::CloseExitMessage& msg, AbstractRouter* r) override; bool - HandleHiddenServiceFrame(const service::ProtocolFrame& /*frame*/) override + HandleHiddenServiceFrame(const service::ProtocolFrameMessage& /*frame*/) override { /// TODO: implement me LogWarn("Got hidden service data on transit hop"); diff --git a/llarp/pow.cpp b/llarp/pow.cpp index 3de7071112..9143ca0416 100644 --- a/llarp/pow.cpp +++ b/llarp/pow.cpp @@ -10,19 +10,16 @@ namespace llarp PoW::~PoW() = default; bool - PoW::DecodeKey(const llarp_buffer_t& /*k*/, llarp_buffer_t* /*val*/) + PoW::decode_key(const llarp_buffer_t& /*k*/, llarp_buffer_t* /*val*/) { // TODO: implement me return false; } - bool - PoW::BEncode(llarp_buffer_t* buf) const + std::string + PoW::bt_encode() const { - // TODO: implement me - if (!bencode_start_dict(buf)) - return false; - return bencode_end(buf); + return ""s; } bool @@ -34,9 +31,12 @@ namespace llarp ShortHash digest; std::array tmp; llarp_buffer_t buf(tmp); - // encode - if (!BEncode(&buf)) + + auto bte = bt_encode(); + + if (auto b = buf.write(bte.begin(), bte.end()); not b) return false; + // rewind buf.sz = buf.cur - buf.base; buf.cur = buf.base; diff --git a/llarp/pow.hpp b/llarp/pow.hpp index 79ff75e8b3..b41fb003ad 100644 --- a/llarp/pow.hpp +++ b/llarp/pow.hpp @@ -20,10 +20,10 @@ namespace llarp IsValid(llarp_time_t now) const; bool - DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* val); + decode_key(const llarp_buffer_t& k, llarp_buffer_t* val); - bool - BEncode(llarp_buffer_t* buf) const; + std::string + bt_encode() const; bool operator==(const PoW& other) const diff --git a/llarp/router/outbound_message_handler.cpp b/llarp/router/outbound_message_handler.cpp index ee019f195f..2202c1ec8d 100644 --- a/llarp/router/outbound_message_handler.cpp +++ b/llarp/router/outbound_message_handler.cpp @@ -177,6 +177,13 @@ namespace llarp _router->linkManager().Connect(remote); } + /** Note: This is where AbstractLinkMessage::bt_encode() is called. Contextually, this is + different than how the other Abstract message types invoke ::bt_encode(), namely that + there is no bt_dict_producer already being appended to. As a result, this use case + likely requires a span backport and/or re-designed llarp_buffer. Until then, the + ::bt_encode() override that returns an std::string upon destruction of its bt_dict_producer + will be used + */ bool OutboundMessageHandler::EncodeBuffer(const AbstractLinkMessage& msg, llarp_buffer& buf) { diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index e8f78ee7f7..76e9e694eb 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -322,15 +322,14 @@ namespace llarp // TODO: if still needed/useful, replace this in line with libquic impl void - Router::ForEachPeer( - std::function visit, bool randomize) const + Router::ForEachPeer(std::function, bool) const { //_linkManager.ForEachPeer(visit, randomize); } // TODO: if still needed/useful, replace this in line with libquic impl void - Router::ForEachPeer(std::function visit) + Router::ForEachPeer(std::function) { //_linkManager.ForEachPeer(visit); } @@ -653,7 +652,8 @@ 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)) + if (!conf.router.m_netId.empty() + && strcmp(conf.router.m_netId.c_str(), llarp::DEFAULT_NETID) != 0) { const auto& netid = conf.router.m_netId; llarp::LogWarn( @@ -1229,6 +1229,7 @@ namespace llarp m_peerDb->modifyPeerStats(id, [&](PeerStats& stats) { stats.numConnectionSuccesses++; }); } NotifyRouterEvent(pubkey(), id, inbound); + return true; } bool diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index cd5731fc5d..b65733a2bc 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -87,27 +87,27 @@ namespace llarp return bencode_write_bytestring(buf, data(), std::distance(begin(), term)); } - bool - RouterContact::BEncode(llarp_buffer_t* buf) const + std::string + RouterContact::bt_encode() const { - if (version == 0) - return BEncodeSignedSection(buf); - else if (version == 1) - { - // TODO: heapless serialization for this in lokimq's bt serialization. - if (not buf->writef("li1e%zu:", signature.size())) - return false; - if (not buf->write(signature.begin(), signature.end())) - return false; - if (not buf->write(signed_bt_dict.begin(), signed_bt_dict.end())) - return false; - if (not buf->writef("e")) - return false; + oxenc::bt_list_producer btlp; - return true; + try + { + btlp.append(1); + btlp.append(signature.ToView()); + btlp.append(signed_bt_dict); + } + catch (...) + { + log::critical(llarp_cat, "Error: RouterContact failed to bt encode contents!"); } - return false; + return std::move(btlp).str(); + + // NOTE: Confirm that we are cutting checks for version == 0 + // if (version == 0) + // return BEncodeSignedSection(buf); } void @@ -158,7 +158,7 @@ namespace llarp /* write signing pubkey */ if (!bencode_write_bytestring(buf, "k", 1)) return false; - if (!pubkey.BEncode(buf)) + if (!pubkey.bt_encode(buf)) return false; std::string nick = Nick(); @@ -178,7 +178,7 @@ namespace llarp /* write encryption pubkey */ if (!bencode_write_bytestring(buf, "p", 1)) return false; - if (!enckey.BEncode(buf)) + if (!enckey.bt_encode(buf)) return false; // write router version if present @@ -221,7 +221,7 @@ namespace llarp /* write signature */ if (!bencode_write_bytestring(buf, "z", 1)) return false; - if (!signature.BEncode(buf)) + if (!signature.bt_encode(buf)) return false; } @@ -342,7 +342,7 @@ namespace llarp } bool - RouterContact::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) + RouterContact::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) { bool read = false; if (!BEncodeMaybeReadDictList("a", addrs, read, key, buf)) @@ -523,11 +523,10 @@ namespace llarp copy.signature.Zero(); std::array tmp; llarp_buffer_t buf(tmp); - if (!copy.BEncode(&buf)) - { - log::error(logcat, "bencode failed"); - return false; - } + + auto bte = copy.bt_encode(); + buf.write(bte.begin(), bte.end()); + buf.sz = buf.cur - buf.base; buf.cur = buf.base; return CryptoManager::instance()->verify(pubkey, buf, signature); @@ -563,10 +562,10 @@ namespace llarp { std::array tmp; llarp_buffer_t buf(tmp); - if (!BEncode(&buf)) - { - return false; - } + + auto bte = bt_encode(); + buf.write(bte.begin(), bte.end()); + try { util::dump_file(fname, tmp.data(), buf.cur - buf.base); diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index fe7605b862..0acb531e69 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -109,8 +109,8 @@ namespace llarp std::string ToString() const; - bool - BEncode(llarp_buffer_t* buf) const; + std::string + bt_encode() const; // tofix: drop version 0 case, change parameter to take btlp reference void @@ -155,7 +155,7 @@ namespace llarp BDecode(llarp_buffer_t* buf); bool - DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* buf); + decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf); bool HasNick() const; diff --git a/llarp/router_version.cpp b/llarp/router_version.cpp index c15a7c2a99..84c57f9dae 100644 --- a/llarp/router_version.cpp +++ b/llarp/router_version.cpp @@ -17,22 +17,24 @@ namespace llarp return m_ProtoVersion == other.m_ProtoVersion; } - bool - RouterVersion::BEncode(llarp_buffer_t* buf) const + std::string + RouterVersion::bt_encode() const { - if (not bencode_start_list(buf)) - return false; - if (not IsEmpty()) + oxenc::bt_list_producer btlp; + + try { - if (not bencode_write_uint64(buf, m_ProtoVersion)) - return false; - for (const auto& i : m_Version) - { - if (not bencode_write_uint64(buf, i)) - return false; - } + btlp.append(m_ProtoVersion); + + for (auto& v : m_Version) + btlp.append(v); + } + catch (...) + { + log::critical(llarp_cat, "Error: RouterVersion failed to bt encode contents!"); } - return bencode_end(buf); + + return std::move(btlp).str(); } void diff --git a/llarp/router_version.hpp b/llarp/router_version.hpp index a03cc02fc5..ace16fd017 100644 --- a/llarp/router_version.hpp +++ b/llarp/router_version.hpp @@ -6,6 +6,11 @@ #include "constants/proto.hpp" #include "util/formattable.hpp" +namespace +{ + static auto llarp_cat = llarp::log::Cat("lokinet.llarp"); +} // namespace + namespace llarp { struct RouterVersion @@ -16,8 +21,8 @@ namespace llarp explicit RouterVersion(const Version_t& routerVersion, uint64_t protoVersion); - bool - BEncode(llarp_buffer_t* buf) const; + std::string + bt_encode() const; bool BDecode(llarp_buffer_t* buf); diff --git a/llarp/routing/dht_message.cpp b/llarp/routing/dht_message.cpp deleted file mode 100644 index bdffb0a66c..0000000000 --- a/llarp/routing/dht_message.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "dht_message.hpp" - -#include -#include "handler.hpp" - -namespace llarp -{ - namespace routing - { - bool - DHTMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) - { - if (key.startswith("M")) - { - llarp::dht::Key_t fromKey; - fromKey.Zero(); - return llarp::dht::DecodeMessageList(fromKey, val, M, true); - } - if (key.startswith("S")) - { - return bencode_read_integer(val, &S); - } - if (key.startswith("V")) - { - return bencode_read_integer(val, &V); - } - return false; - } - - bool - DHTMessage::BEncode(llarp_buffer_t* buf) const - { - if (!bencode_start_dict(buf)) - return false; - - if (!BEncodeWriteDictMsgType(buf, "A", "M")) - return false; - if (!BEncodeWriteDictBEncodeList("M", M, buf)) - return false; - if (!BEncodeWriteDictInt("S", S, buf)) - return false; - if (!BEncodeWriteDictInt("V", llarp::constants::proto_version, buf)) - return false; - - return bencode_end(buf); - } - - /// 'h' here is either TransitHop or Path. - /// TransitHop chains to dht::Context::RelayRequestForPath and is where the - /// end of a path handles a client's DHT message Path handles the message - /// (e.g. dht::IMessage::HandleMessage()) in-place and is the case where a - /// client receives a DHT message - bool - DHTMessage::HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const - { - // set source as us - const llarp::dht::Key_t us(r->pubkey()); - for (const auto& msg : M) - { - msg->From = us; - msg->pathID = from; - if (!h->HandleDHTMessage(*msg, r)) - return false; - } - return true; - } - } // namespace routing -} // namespace llarp diff --git a/llarp/routing/dht_message.hpp b/llarp/routing/dht_message.hpp deleted file mode 100644 index 72ebab2d10..0000000000 --- a/llarp/routing/dht_message.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include -#include "message.hpp" - -#include - -namespace llarp::routing -{ - struct DHTMessage final : public AbstractRoutingMessage - { - std::vector M; - uint64_t V = 0; - - ~DHTMessage() override = default; - - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) override; - - bool - BEncode(llarp_buffer_t* buf) const override; - - bool - HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; - - void - Clear() override - { - M.clear(); - V = 0; - } - }; -} // namespace llarp::routing diff --git a/llarp/routing/handler.hpp b/llarp/routing/handler.hpp index 9e1de588f7..adca3cdd68 100644 --- a/llarp/routing/handler.hpp +++ b/llarp/routing/handler.hpp @@ -13,7 +13,7 @@ namespace llarp namespace service { - struct ProtocolFrame; + struct ProtocolFrameMessage; } namespace routing @@ -61,7 +61,7 @@ namespace llarp HandlePathTransferMessage(const PathTransferMessage& msg, AbstractRouter* r) = 0; virtual bool - HandleHiddenServiceFrame(const service::ProtocolFrame& msg) = 0; + HandleHiddenServiceFrame(const service::ProtocolFrameMessage& msg) = 0; virtual bool HandlePathConfirmMessage(const PathConfirmMessage& msg, AbstractRouter* r) = 0; diff --git a/llarp/routing/message.hpp b/llarp/routing/message.hpp index 4acfd0e65f..5a4700bb7a 100644 --- a/llarp/routing/message.hpp +++ b/llarp/routing/message.hpp @@ -21,7 +21,7 @@ namespace llarp struct AbstractRoutingMessage : private AbstractSerializable { PathID_t from; - uint64_t S{0}; + uint64_t sequence_number{0}; uint64_t version = llarp::constants::proto_version; AbstractRoutingMessage() = default; @@ -62,7 +62,7 @@ namespace llarp bool operator<(const AbstractRoutingMessage& other) const { - return other.S < S; + return other.sequence_number < sequence_number; } }; diff --git a/llarp/routing/message_parser.cpp b/llarp/routing/message_parser.cpp index 09db93c874..5f7e5b5376 100644 --- a/llarp/routing/message_parser.cpp +++ b/llarp/routing/message_parser.cpp @@ -3,7 +3,7 @@ #include #include #include -#include "dht_message.hpp" +#include "path_dht_message.hpp" #include "path_confirm_message.hpp" #include "path_latency_message.hpp" #include "path_transfer_message.hpp" @@ -16,10 +16,10 @@ namespace llarp::routing { DataDiscardMessage D; PathLatencyMessage L; - DHTMessage M; + PathDHTMessage M; PathConfirmMessage P; PathTransferMessage T; - service::ProtocolFrame H; + service::ProtocolFrameMessage H; TransferTrafficMessage I; GrantExitMessage G; RejectExitMessage J; @@ -101,7 +101,7 @@ namespace llarp::routing return msg != nullptr; } - return msg->DecodeKey(*key, buffer); + return msg->decode_key(*key, buffer); } bool @@ -124,8 +124,8 @@ namespace llarp::routing if (bencode_read_dict(*this, ©)) { msg->from = from; - LogDebug("handle routing message ", msg->S, " from ", from); - result = msg->HandleMessage(h, r); + LogDebug("handle routing message ", msg->sequence_number, " from ", from); + result = msg->handle_message(h, r); if (!result) { llarp::LogWarn("Failed to handle inbound routing message ", ourKey); @@ -137,7 +137,7 @@ namespace llarp::routing llarp::DumpBuffer(buf); } if (msg) - msg->Clear(); + msg->clear(); msg = nullptr; version = 0; return result; diff --git a/llarp/routing/path_confirm_message.cpp b/llarp/routing/path_confirm_message.cpp index 00b739d67b..3b41386e79 100644 --- a/llarp/routing/path_confirm_message.cpp +++ b/llarp/routing/path_confirm_message.cpp @@ -4,52 +4,52 @@ #include #include -namespace llarp +namespace llarp::routing { - namespace routing + PathConfirmMessage::PathConfirmMessage(llarp_time_t lifetime) + : path_lifetime(lifetime), path_created_time(time_now_ms()) + {} + + bool + PathConfirmMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) { - PathConfirmMessage::PathConfirmMessage(llarp_time_t lifetime) - : pathLifetime(lifetime), pathCreated(time_now_ms()) - {} + bool read = false; + if (!BEncodeMaybeReadDictInt("L", path_lifetime, read, key, val)) + return false; + if (!BEncodeMaybeReadDictInt("S", sequence_number, read, key, val)) + return false; + if (!BEncodeMaybeReadDictInt("T", path_created_time, read, key, val)) + return false; + if (!BEncodeMaybeReadDictInt("V", version, read, key, val)) + return false; + return read; + } - bool - PathConfirmMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) - { - bool read = false; - if (!BEncodeMaybeReadDictInt("L", pathLifetime, read, key, val)) - return false; - if (!BEncodeMaybeReadDictInt("S", S, read, key, val)) - return false; - if (!BEncodeMaybeReadDictInt("T", pathCreated, read, key, val)) - return false; - if (!BEncodeMaybeReadDictInt("V", version, read, key, val)) - return false; - return read; - } + std::string + PathConfirmMessage::bt_encode() const + { + oxenc::bt_dict_producer btdp; - bool - PathConfirmMessage::BEncode(llarp_buffer_t* buf) const + try { - if (!bencode_start_dict(buf)) - return false; - if (!BEncodeWriteDictMsgType(buf, "A", "P")) - return false; - if (!BEncodeWriteDictInt("L", pathLifetime.count(), buf)) - return false; - if (!BEncodeWriteDictInt("S", S, buf)) - return false; - if (!BEncodeWriteDictInt("T", pathCreated.count(), buf)) - return false; - if (!BEncodeWriteDictInt("V", version, buf)) - return false; - return bencode_end(buf); + btdp.append("A", "P"); + btdp.append("L", path_lifetime.count()); + btdp.append("S", sequence_number); + btdp.append("T", path_created_time.count()); + btdp.append("V", version); } - - bool - PathConfirmMessage::HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + catch (...) { - return h && h->HandlePathConfirmMessage(*this, r); + log::critical(route_cat, "Error: PathConfirmMessage failed to bt encode contents!"); } - } // namespace routing -} // namespace llarp + return std::move(btdp).str(); + } + + bool + PathConfirmMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + { + return h && h->HandlePathConfirmMessage(*this, r); + } + +} // namespace llarp::routing diff --git a/llarp/routing/path_confirm_message.hpp b/llarp/routing/path_confirm_message.hpp index c9a76bc2aa..986f0f9675 100644 --- a/llarp/routing/path_confirm_message.hpp +++ b/llarp/routing/path_confirm_message.hpp @@ -6,27 +6,27 @@ namespace llarp::routing { struct PathConfirmMessage final : public AbstractRoutingMessage { - llarp_time_t pathLifetime = 0s; - llarp_time_t pathCreated = 0s; + llarp_time_t path_lifetime = 0s; + llarp_time_t path_created_time = 0s; PathConfirmMessage() = default; PathConfirmMessage(llarp_time_t lifetime); ~PathConfirmMessage() override = default; - bool - BEncode(llarp_buffer_t* buf) const override; + std::string + bt_encode() const override; bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) override; + decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; bool - HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; void - Clear() override + clear() override { - pathLifetime = 0s; - pathCreated = 0s; + path_lifetime = 0s; + path_created_time = 0s; version = 0; } }; diff --git a/llarp/routing/path_dht_message.cpp b/llarp/routing/path_dht_message.cpp new file mode 100644 index 0000000000..3f5bddb96c --- /dev/null +++ b/llarp/routing/path_dht_message.cpp @@ -0,0 +1,74 @@ +#include "path_dht_message.hpp" + +#include +#include "handler.hpp" + +namespace llarp::routing +{ + bool + PathDHTMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) + { + if (key.startswith("M")) + { + llarp::dht::Key_t fromKey; + fromKey.Zero(); + return llarp::dht::DecodeMessageList(fromKey, val, dht_msgs, true); + } + if (key.startswith("S")) + { + return bencode_read_integer(val, &sequence_number); + } + if (key.startswith("V")) + { + return bencode_read_integer(val, &version); + } + return false; + } + + std::string + PathDHTMessage::bt_encode() const + { + oxenc::bt_dict_producer btdp; + + try + { + btdp.append("A", "M"); + + { + auto subdict = btdp.append_dict("M"); + + for (auto& m : dht_msgs) + m->bt_encode(subdict); + } + + btdp.append("S", sequence_number); + btdp.append("V", version); + } + catch (...) + { + log::critical(route_cat, "Error: DHTMessage failed to bt encode contents!"); + } + + return std::move(btdp).str(); + } + + /// 'h' here is either TransitHop or Path. + /// TransitHop chains to dht::Context::RelayRequestForPath and is where the + /// end of a path handles a client's DHT message Path handles the message + /// (e.g. dht::IMessage::HandleMessage()) in-place and is the case where a + /// client receives a DHT message + bool + PathDHTMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + { + // set source as us + const llarp::dht::Key_t us(r->pubkey()); + for (const auto& msg : dht_msgs) + { + msg->From = us; + msg->pathID = from; + if (!h->HandleDHTMessage(*msg, r)) + return false; + } + return true; + } +} // namespace llarp::routing diff --git a/llarp/routing/path_dht_message.hpp b/llarp/routing/path_dht_message.hpp new file mode 100644 index 0000000000..af8b473aac --- /dev/null +++ b/llarp/routing/path_dht_message.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include +#include "message.hpp" + +#include + +namespace llarp::routing +{ + struct PathDHTMessage final : public AbstractRoutingMessage + { + std::vector> dht_msgs; + + ~PathDHTMessage() override = default; + + bool + decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; + + std::string + bt_encode() const override; + + bool + handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + + void + clear() override + { + dht_msgs.clear(); + } + }; +} // namespace llarp::routing diff --git a/llarp/routing/path_latency_message.cpp b/llarp/routing/path_latency_message.cpp index ad97e32489..4715311eed 100644 --- a/llarp/routing/path_latency_message.cpp +++ b/llarp/routing/path_latency_message.cpp @@ -3,52 +3,49 @@ #include "handler.hpp" #include -namespace llarp +namespace llarp::routing { - namespace routing + PathLatencyMessage::PathLatencyMessage() = default; + + bool + PathLatencyMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) { - PathLatencyMessage::PathLatencyMessage() = default; + bool read = false; + if (!BEncodeMaybeReadDictInt("L", latency, read, key, val)) + return false; + if (!BEncodeMaybeReadDictInt("S", sequence_number, read, key, val)) + return false; + if (!BEncodeMaybeReadDictInt("T", sent_time, read, key, val)) + return false; + return read; + } - bool - PathLatencyMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) - { - bool read = false; - if (!BEncodeMaybeReadDictInt("L", L, read, key, val)) - return false; - if (!BEncodeMaybeReadDictInt("S", S, read, key, val)) - return false; - if (!BEncodeMaybeReadDictInt("T", T, read, key, val)) - return false; - return read; - } + std::string + PathLatencyMessage::bt_encode() const + { + oxenc::bt_dict_producer btdp; - bool - PathLatencyMessage::BEncode(llarp_buffer_t* buf) const + try { - if (!bencode_start_dict(buf)) - return false; - if (!BEncodeWriteDictMsgType(buf, "A", "L")) - return false; - if (L) - { - if (!BEncodeWriteDictInt("L", L, buf)) - return false; - } - if (T) - { - if (!BEncodeWriteDictInt("T", T, buf)) - return false; - } - if (!BEncodeWriteDictInt("S", S, buf)) - return false; - return bencode_end(buf); + btdp.append("A", "L"); + if (latency) + btdp.append("L", latency); + if (sent_time) + btdp.append("T", sent_time); + btdp.append("S", sequence_number); } - - bool - PathLatencyMessage::HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + catch (...) { - return h && h->HandlePathLatencyMessage(*this, r); + log::critical(route_cat, "Error: PathLatencyMessage failed to bt encode contents!"); } - } // namespace routing -} // namespace llarp + return std::move(btdp).str(); + } + + bool + PathLatencyMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + { + return h && h->HandlePathLatencyMessage(*this, r); + } + +} // namespace llarp::routing diff --git a/llarp/routing/path_latency_message.hpp b/llarp/routing/path_latency_message.hpp index 006bb77b98..3a5ec34730 100644 --- a/llarp/routing/path_latency_message.hpp +++ b/llarp/routing/path_latency_message.hpp @@ -2,32 +2,29 @@ #include "message.hpp" -namespace llarp +namespace llarp::routing { - namespace routing + struct PathLatencyMessage final : public AbstractRoutingMessage { - struct PathLatencyMessage final : public AbstractRoutingMessage - { - uint64_t T = 0; - uint64_t L = 0; - PathLatencyMessage(); + uint64_t sent_time = 0; + uint64_t latency = 0; + PathLatencyMessage(); - bool - BEncode(llarp_buffer_t* buf) const override; + std::string + bt_encode() const override; - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) override; + bool + decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; - void - Clear() override - { - T = 0; - L = 0; - version = 0; - } + void + clear() override + { + sent_time = 0; + latency = 0; + version = 0; + } - bool - HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; - }; - } // namespace routing -} // namespace llarp + bool + handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + }; +} // namespace llarp::routing diff --git a/llarp/routing/path_transfer_message.cpp b/llarp/routing/path_transfer_message.cpp index 8984d0b987..f210b0eb05 100644 --- a/llarp/routing/path_transfer_message.cpp +++ b/llarp/routing/path_transfer_message.cpp @@ -3,56 +3,50 @@ #include "handler.hpp" #include -namespace llarp +namespace llarp::routing { - namespace routing + bool + PathTransferMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) { - bool - PathTransferMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) - { - bool read = false; - if (!BEncodeMaybeReadDictEntry("P", P, read, key, val)) - return false; - if (!BEncodeMaybeReadDictInt("S", S, read, key, val)) - return false; - if (!BEncodeMaybeReadDictEntry("T", T, read, key, val)) - return false; - if (!BEncodeMaybeReadDictInt("V", version, read, key, val)) - return false; - if (!BEncodeMaybeReadDictEntry("Y", Y, read, key, val)) - return false; - return read; - } + bool read = false; + if (!BEncodeMaybeReadDictEntry("P", path_id, read, key, val)) + return false; + if (!BEncodeMaybeReadDictInt("S", sequence_number, read, key, val)) + return false; + if (!BEncodeMaybeReadDictEntry("T", protocol_frame_msg, read, key, val)) + return false; + if (!BEncodeMaybeReadDictInt("V", version, read, key, val)) + return false; + if (!BEncodeMaybeReadDictEntry("Y", nonce, read, key, val)) + return false; + return read; + } + + std::string + PathTransferMessage::bt_encode() const + { + oxenc::bt_dict_producer btdp; - bool - PathTransferMessage::BEncode(llarp_buffer_t* buf) const + try { - if (!bencode_start_dict(buf)) - return false; - if (!BEncodeWriteDictMsgType(buf, "A", "T")) - return false; - if (!BEncodeWriteDictEntry("P", P, buf)) - return false; - - if (!BEncodeWriteDictInt("S", S, buf)) - return false; - - if (!BEncodeWriteDictEntry("T", T, buf)) - return false; - - if (!BEncodeWriteDictInt("V", llarp::constants::proto_version, buf)) - return false; - if (!BEncodeWriteDictEntry("Y", Y, buf)) - return false; - - return bencode_end(buf); + btdp.append("A", "T"); + btdp.append("P", path_id.ToView()); + btdp.append("T", protocol_frame_msg.bt_encode()); + btdp.append("V", version); + btdp.append("Y", nonce.ToView()); } - - bool - PathTransferMessage::HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + catch (...) { - return h->HandlePathTransferMessage(*this, r); + log::critical(route_cat, "Error: PathTransferMessage failed to bt encode contents!"); } - } // namespace routing -} // namespace llarp + return std::move(btdp).str(); + } + + bool + PathTransferMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + { + return h->HandlePathTransferMessage(*this, r); + } + +} // namespace llarp::routing diff --git a/llarp/routing/path_transfer_message.hpp b/llarp/routing/path_transfer_message.hpp index ffb6f80d6d..2ede435605 100644 --- a/llarp/routing/path_transfer_message.hpp +++ b/llarp/routing/path_transfer_message.hpp @@ -5,41 +5,39 @@ #include "message.hpp" #include -namespace llarp +namespace llarp::routing { - namespace routing + struct PathTransferMessage final : public AbstractRoutingMessage { - struct PathTransferMessage final : public AbstractRoutingMessage + PathID_t path_id; + service::ProtocolFrameMessage protocol_frame_msg; + TunnelNonce nonce; + + PathTransferMessage() = default; + PathTransferMessage(const service::ProtocolFrameMessage& f, const PathID_t& p) + : path_id(p), protocol_frame_msg(f) + { + nonce.Randomize(); + } + ~PathTransferMessage() override = default; + + bool + decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; + + std::string + bt_encode() const override; + + bool + handle_message(AbstractRoutingMessageHandler*, AbstractRouter* r) const override; + + void + clear() override { - PathID_t P; - service::ProtocolFrame T; - TunnelNonce Y; - - PathTransferMessage() = default; - PathTransferMessage(const service::ProtocolFrame& f, const PathID_t& p) : P(p), T(f) - { - Y.Randomize(); - } - ~PathTransferMessage() override = default; - - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) override; - - bool - BEncode(llarp_buffer_t* buf) const override; - - bool - HandleMessage(AbstractRoutingMessageHandler*, AbstractRouter* r) const override; - - void - Clear() override - { - P.Zero(); - T.Clear(); - Y.Zero(); - version = 0; - } - }; - - } // namespace routing -} // namespace llarp + path_id.Zero(); + protocol_frame_msg.clear(); + nonce.Zero(); + version = 0; + } + }; + +} // namespace llarp::routing diff --git a/llarp/routing/transfer_traffic_message.cpp b/llarp/routing/transfer_traffic_message.cpp index a95e80ad51..c46d3acb09 100644 --- a/llarp/routing/transfer_traffic_message.cpp +++ b/llarp/routing/transfer_traffic_message.cpp @@ -5,63 +5,69 @@ #include -namespace llarp +namespace llarp::routing { - namespace routing + bool + TransferTrafficMessage::PutBuffer(const llarp_buffer_t& buf, uint64_t counter) { - bool - TransferTrafficMessage::PutBuffer(const llarp_buffer_t& buf, uint64_t counter) - { - if (buf.sz > MaxExitMTU) - return false; - X.emplace_back(buf.sz + 8); - byte_t* ptr = X.back().data(); - oxenc::write_host_as_big(counter, ptr); - ptr += 8; - memcpy(ptr, buf.base, buf.sz); - // 8 bytes encoding overhead and 8 bytes counter - _size += buf.sz + 16; - return true; - } + if (buf.sz > MAX_EXIT_MTU) + return false; + enc_buf.emplace_back(buf.sz + 8); + byte_t* ptr = enc_buf.back().data(); + oxenc::write_host_as_big(counter, ptr); + ptr += 8; + memcpy(ptr, buf.base, buf.sz); + // 8 bytes encoding overhead and 8 bytes counter + _size += buf.sz + 16; + return true; + } - bool - TransferTrafficMessage::BEncode(llarp_buffer_t* buf) const - { - if (!bencode_start_dict(buf)) - return false; - if (!BEncodeWriteDictMsgType(buf, "A", "I")) - return false; - if (!BEncodeWriteDictInt("P", protocol, buf)) - return false; - if (!BEncodeWriteDictInt("S", S, buf)) - return false; - if (!BEncodeWriteDictInt("V", version, buf)) - return false; - if (!BEncodeWriteDictList("X", X, buf)) - return false; - return bencode_end(buf); - } + std::string + TransferTrafficMessage::bt_encode() const + { + oxenc::bt_dict_producer btdp; - bool - TransferTrafficMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) + try { - bool read = false; - if (!BEncodeMaybeReadDictInt("S", S, read, key, buf)) - return false; - if (!BEncodeMaybeReadDictInt("P", protocol, read, key, buf)) - return false; - if (!BEncodeMaybeReadDictInt("V", version, read, key, buf)) - return false; - if (!BEncodeMaybeReadDictList("X", X, read, key, buf)) - return false; - return read or bencode_discard(buf); - } + btdp.append("A", "I"); + btdp.append("P", static_cast(protocol)); + btdp.append("S", sequence_number); + btdp.append("V", version); + + { + auto sublist = btdp.append_list("X"); - bool - TransferTrafficMessage::HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + for (auto& b : enc_buf) + sublist.append(std::string_view{reinterpret_cast(b.data()), b.size()}); + } + } + catch (...) { - return h->HandleTransferTrafficMessage(*this, r); + log::critical(route_cat, "Error: PathLatencyMessage failed to bt encode contents!"); } - } // namespace routing -} // namespace llarp + return std::move(btdp).str(); + } + + bool + TransferTrafficMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) + { + bool read = false; + if (!BEncodeMaybeReadDictInt("S", sequence_number, read, key, buf)) + return false; + if (!BEncodeMaybeReadDictInt("P", protocol, read, key, buf)) + return false; + if (!BEncodeMaybeReadDictInt("V", version, read, key, buf)) + return false; + if (!BEncodeMaybeReadDictList("X", enc_buf, read, key, buf)) + return false; + return read or bencode_discard(buf); + } + + bool + TransferTrafficMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + { + return h->HandleTransferTrafficMessage(*this, r); + } + +} // namespace llarp::routing diff --git a/llarp/routing/transfer_traffic_message.hpp b/llarp/routing/transfer_traffic_message.hpp index b1ef654ba2..14f24ef500 100644 --- a/llarp/routing/transfer_traffic_message.hpp +++ b/llarp/routing/transfer_traffic_message.hpp @@ -6,46 +6,44 @@ #include -namespace llarp +namespace llarp::routing { - namespace routing + constexpr size_t EXIT_PAD_SIZE = 512 - 48; + constexpr size_t MAX_EXIT_MTU = 1500; + constexpr size_t EXIT_OVERHEAD = sizeof(uint64_t); + + struct TransferTrafficMessage final : public AbstractRoutingMessage { - constexpr size_t ExitPadSize = 512 - 48; - constexpr size_t MaxExitMTU = 1500; - constexpr size_t ExitOverhead = sizeof(uint64_t); - struct TransferTrafficMessage final : public AbstractRoutingMessage + std::vector> enc_buf; + service::ProtocolType protocol; + size_t _size = 0; + + void + clear() override { - std::vector> X; - service::ProtocolType protocol; - size_t _size = 0; - - void - Clear() override - { - X.clear(); - _size = 0; - version = 0; - protocol = service::ProtocolType::TrafficV4; - } - - size_t - Size() const - { - return _size; - } - - /// append buffer to X - bool - PutBuffer(const llarp_buffer_t& buf, uint64_t counter); - - bool - BEncode(llarp_buffer_t* buf) const override; - - bool - DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* val) override; - - bool - HandleMessage(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; - }; - } // namespace routing -} // namespace llarp + enc_buf.clear(); + _size = 0; + version = 0; + protocol = service::ProtocolType::TrafficV4; + } + + size_t + Size() const + { + return _size; + } + + /// append buffer to X + bool + PutBuffer(const llarp_buffer_t& buf, uint64_t counter); + + std::string + bt_encode() const override; + + bool + decode_key(const llarp_buffer_t& k, llarp_buffer_t* val) override; + + bool + handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + }; +} // namespace llarp::routing diff --git a/llarp/service/async_key_exchange.cpp b/llarp/service/async_key_exchange.cpp index bf814daac9..9723fe2927 100644 --- a/llarp/service/async_key_exchange.cpp +++ b/llarp/service/async_key_exchange.cpp @@ -5,79 +5,76 @@ #include #include -namespace llarp +namespace llarp::service { - namespace service + AsyncKeyExchange::AsyncKeyExchange( + EventLoop_ptr l, + ServiceInfo r, + const Identity& localident, + const PQPubKey& introsetPubKey, + const Introduction& remote, + IDataHandler* h, + const ConvoTag& t, + ProtocolType proto) + : loop(std::move(l)) + , m_remote(std::move(r)) + , m_LocalIdentity(localident) + , introPubKey(introsetPubKey) + , remoteIntro(remote) + , handler(h) + , tag(t) { - AsyncKeyExchange::AsyncKeyExchange( - EventLoop_ptr l, - ServiceInfo r, - const Identity& localident, - const PQPubKey& introsetPubKey, - const Introduction& remote, - IDataHandler* h, - const ConvoTag& t, - ProtocolType proto) - : loop(std::move(l)) - , m_remote(std::move(r)) - , m_LocalIdentity(localident) - , introPubKey(introsetPubKey) - , remoteIntro(remote) - , handler(h) - , tag(t) - { - msg.proto = proto; - } + msg.proto = proto; + } + + void + AsyncKeyExchange::Result( + std::shared_ptr self, std::shared_ptr frame) + { + // put values + self->handler->PutSenderFor(self->msg.tag, self->m_remote, false); + self->handler->PutCachedSessionKeyFor(self->msg.tag, self->sharedKey); + self->handler->PutIntroFor(self->msg.tag, self->remoteIntro); + self->handler->PutReplyIntroFor(self->msg.tag, self->msg.introReply); + self->hook(frame); + } - void - AsyncKeyExchange::Result( - std::shared_ptr self, std::shared_ptr frame) + void + AsyncKeyExchange::Encrypt( + std::shared_ptr self, std::shared_ptr frame) + { + // derive ntru session key component + SharedSecret K; + auto crypto = CryptoManager::instance(); + crypto->pqe_encrypt(frame->cipher, K, self->introPubKey); + // randomize Nonce + frame->nonce.Randomize(); + // compure post handshake session key + // PKE (A, B, N) + SharedSecret sharedSecret; + path_dh_func dh_client = util::memFn(&Crypto::dh_client, crypto); + if (!self->m_LocalIdentity.KeyExchange(dh_client, sharedSecret, self->m_remote, frame->nonce)) { - // put values - self->handler->PutSenderFor(self->msg.tag, self->m_remote, false); - self->handler->PutCachedSessionKeyFor(self->msg.tag, self->sharedKey); - self->handler->PutIntroFor(self->msg.tag, self->remoteIntro); - self->handler->PutReplyIntroFor(self->msg.tag, self->msg.introReply); - self->hook(frame); + LogError("failed to derive x25519 shared key component"); } - - void - AsyncKeyExchange::Encrypt( - std::shared_ptr self, std::shared_ptr frame) + std::array tmp = {{0}}; + // K + std::copy(K.begin(), K.end(), tmp.begin()); + // H (K + PKE(A, B, N)) + std::copy(sharedSecret.begin(), sharedSecret.end(), tmp.begin() + 32); + crypto->shorthash(self->sharedKey, llarp_buffer_t(tmp)); + // set tag + self->msg.tag = self->tag; + // set sender + self->msg.sender = self->m_LocalIdentity.pub; + // set version + self->msg.version = llarp::constants::proto_version; + // encrypt and sign + if (frame->EncryptAndSign(self->msg, K, self->m_LocalIdentity)) + self->loop->call([self, frame] { AsyncKeyExchange::Result(self, frame); }); + else { - // derive ntru session key component - SharedSecret K; - auto crypto = CryptoManager::instance(); - crypto->pqe_encrypt(frame->C, K, self->introPubKey); - // randomize Nonce - frame->N.Randomize(); - // compure post handshake session key - // PKE (A, B, N) - SharedSecret sharedSecret; - path_dh_func dh_client = util::memFn(&Crypto::dh_client, crypto); - if (!self->m_LocalIdentity.KeyExchange(dh_client, sharedSecret, self->m_remote, frame->N)) - { - LogError("failed to derive x25519 shared key component"); - } - std::array tmp = {{0}}; - // K - std::copy(K.begin(), K.end(), tmp.begin()); - // H (K + PKE(A, B, N)) - std::copy(sharedSecret.begin(), sharedSecret.end(), tmp.begin() + 32); - crypto->shorthash(self->sharedKey, llarp_buffer_t(tmp)); - // set tag - self->msg.tag = self->tag; - // set sender - self->msg.sender = self->m_LocalIdentity.pub; - // set version - self->msg.version = llarp::constants::proto_version; - // encrypt and sign - if (frame->EncryptAndSign(self->msg, K, self->m_LocalIdentity)) - self->loop->call([self, frame] { AsyncKeyExchange::Result(self, frame); }); - else - { - LogError("failed to encrypt and sign"); - } + LogError("failed to encrypt and sign"); } - } // namespace service -} // namespace llarp + } +} // namespace llarp::service diff --git a/llarp/service/async_key_exchange.hpp b/llarp/service/async_key_exchange.hpp index 1bc4e68cac..be260c7f4b 100644 --- a/llarp/service/async_key_exchange.hpp +++ b/llarp/service/async_key_exchange.hpp @@ -4,41 +4,38 @@ #include "identity.hpp" #include "protocol.hpp" -namespace llarp +namespace llarp::service { - namespace service + struct AsyncKeyExchange : public std::enable_shared_from_this { - struct AsyncKeyExchange : public std::enable_shared_from_this - { - EventLoop_ptr loop; - SharedSecret sharedKey; - ServiceInfo m_remote; - const Identity& m_LocalIdentity; - ProtocolMessage msg; - Introduction intro; - const PQPubKey introPubKey; - Introduction remoteIntro; - std::function)> hook; - IDataHandler* handler; - ConvoTag tag; + EventLoop_ptr loop; + SharedSecret sharedKey; + ServiceInfo m_remote; + const Identity& m_LocalIdentity; + ProtocolMessage msg; + Introduction intro; + const PQPubKey introPubKey; + Introduction remoteIntro; + std::function)> hook; + IDataHandler* handler; + ConvoTag tag; - AsyncKeyExchange( - EventLoop_ptr l, - ServiceInfo r, - const Identity& localident, - const PQPubKey& introsetPubKey, - const Introduction& remote, - IDataHandler* h, - const ConvoTag& t, - ProtocolType proto); + AsyncKeyExchange( + EventLoop_ptr l, + ServiceInfo r, + const Identity& localident, + const PQPubKey& introsetPubKey, + const Introduction& remote, + IDataHandler* h, + const ConvoTag& t, + ProtocolType proto); - static void - Result(std::shared_ptr user, std::shared_ptr frame); + static void + Result(std::shared_ptr user, std::shared_ptr frame); - /// given protocol message make protocol frame - static void - Encrypt(std::shared_ptr user, std::shared_ptr frame); - }; + /// given protocol message make protocol frame + static void + Encrypt(std::shared_ptr user, std::shared_ptr frame); + }; - } // namespace service -} // namespace llarp +} // namespace llarp::service diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index fe18ebecce..8751718004 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include @@ -122,33 +122,33 @@ namespace llarp return; } - introSet().supportedProtocols.clear(); + introSet().supported_protocols.clear(); // add supported ethertypes if (HasIfAddr()) { if (IPRange::V4MappedRange().Contains(GetIfAddr())) { - introSet().supportedProtocols.push_back(ProtocolType::TrafficV4); + introSet().supported_protocols.push_back(ProtocolType::TrafficV4); } else { - introSet().supportedProtocols.push_back(ProtocolType::TrafficV6); + introSet().supported_protocols.push_back(ProtocolType::TrafficV6); } // exit related stuffo if (m_state->m_ExitEnabled) { - introSet().supportedProtocols.push_back(ProtocolType::Exit); - introSet().exitTrafficPolicy = GetExitPolicy(); - introSet().ownedRanges = GetOwnedRanges(); + introSet().supported_protocols.push_back(ProtocolType::Exit); + introSet().exit_policy = GetExitPolicy(); + introSet().owned_ranges = GetOwnedRanges(); } } // add quic ethertype if we have listeners set up if (auto* quic = GetQUICTunnel()) { if (quic->hasListeners()) - introSet().supportedProtocols.push_back(ProtocolType::QUIC); + introSet().supported_protocols.push_back(ProtocolType::QUIC); } introSet().intros.clear(); @@ -772,8 +772,8 @@ namespace llarp std::shared_ptr BuildRequestMessage() override { - auto msg = std::make_shared(); - msg->M.emplace_back( + auto msg = std::make_shared(); + msg->dht_msgs.emplace_back( std::make_unique(m_IntroSet, txid, true, m_relayOrder)); return msg; } @@ -991,8 +991,8 @@ namespace llarp std::shared_ptr BuildRequestMessage() override { - auto msg = std::make_shared(); - msg->M.emplace_back(std::make_unique( + auto msg = std::make_shared(); + msg->dht_msgs.emplace_back(std::make_unique( dht::Key_t{}, dht::Key_t{namehash.as_array()}, txid)); return msg; } @@ -1153,11 +1153,11 @@ namespace llarp if (routers.find(router) == routers.end()) { auto path = GetEstablishedPathClosestTo(router); - routing::DHTMessage msg; + routing::PathDHTMessage msg; auto txid = GenTXID(); - msg.M.emplace_back(std::make_unique(txid, router)); + msg.dht_msgs.emplace_back(std::make_unique(txid, router)); if (path) - msg.S = path->NextSeqNo(); + msg.sequence_number = path->NextSeqNo(); if (path && path->SendRoutingMessage(msg, Router())) { RouterLookupJob job{this, [handler, router, nodedb = m_router->nodedb()](auto results) { @@ -1170,8 +1170,8 @@ namespace llarp handler(results); }}; - assert(msg.M.size() == 1); - auto dhtMsg = dynamic_cast(msg.M[0].get()); + assert(msg.dht_msgs.size() == 1); + auto dhtMsg = dynamic_cast(msg.dht_msgs[0].get()); assert(dhtMsg != nullptr); m_router->NotifyRouterEvent(m_router->pubkey(), *dhtMsg); @@ -1230,7 +1230,7 @@ namespace llarp Introduction intro = msg->introReply; if (HasInboundConvo(msg->sender.Addr())) { - intro.pathID = from; + intro.path_id = from; intro.router = p->Endpoint(); } PutReplyIntroFor(msg->tag, intro); @@ -1328,11 +1328,11 @@ namespace llarp // not applicable because we are not an exit or don't have an endpoint auth policy if ((not m_state->m_ExitEnabled) or m_AuthPolicy == nullptr) return; - ProtocolFrame f{}; - f.R = AuthResultCodeAsInt(result.code); - f.T = tag; - f.F = path->intro.pathID; - f.N.Randomize(); + ProtocolFrameMessage f{}; + f.flag = AuthResultCodeAsInt(result.code); + f.convo_tag = tag; + f.path_id = path->intro.path_id; + f.nonce.Randomize(); if (result.code == AuthResultCode::eAuthAccepted) { ProtocolMessage msg; @@ -1386,10 +1386,10 @@ namespace llarp Endpoint::ResetConvoTag(ConvoTag tag, path::Path_ptr p, PathID_t from) { // send reset convo tag message - ProtocolFrame f{}; - f.R = 1; - f.T = tag; - f.F = p->intro.pathID; + ProtocolFrameMessage f{}; + f.flag = 1; + f.convo_tag = tag; + f.path_id = p->intro.path_id; f.Sign(m_Identity); { LogWarn("invalidating convotag T=", tag); @@ -1400,25 +1400,25 @@ namespace llarp } bool - Endpoint::HandleHiddenServiceFrame(path::Path_ptr p, const ProtocolFrame& frame) + Endpoint::HandleHiddenServiceFrame(path::Path_ptr p, const ProtocolFrameMessage& frame) { - if (frame.R) + if (frame.flag) { // handle discard ServiceInfo si; - if (!GetSenderFor(frame.T, si)) + if (!GetSenderFor(frame.convo_tag, si)) return false; // verify source if (!frame.Verify(si)) return false; // remove convotag it doesn't exist - LogWarn("remove convotag T=", frame.T, " R=", frame.R, " from ", si.Addr()); - RemoveConvoTag(frame.T); + LogWarn("remove convotag T=", frame.convo_tag, " R=", frame.flag, " from ", si.Addr()); + RemoveConvoTag(frame.convo_tag); return true; } if (not frame.AsyncDecryptAndVerify(Router()->loop(), p, m_Identity, this)) { - ResetConvoTag(frame.T, p, frame.F); + ResetConvoTag(frame.convo_tag, p, frame.path_id); } return true; } @@ -1797,9 +1797,9 @@ namespace llarp while (not m_SendQueue.empty()) { SendEvent_t item = m_SendQueue.popFront(); - item.first->S = item.second->NextSeqNo(); + item.first->sequence_number = item.second->NextSeqNo(); if (item.second->SendRoutingMessage(*item.first, router)) - ConvoTagTX(item.first->T.T); + ConvoTagTX(item.first->protocol_frame_msg.convo_tag); } UpstreamFlush(router); @@ -1949,8 +1949,8 @@ namespace llarp // inbound conversation LogTrace("Have inbound convo"); auto transfer = std::make_shared(); - ProtocolFrame& f = transfer->T; - f.R = 0; + ProtocolFrameMessage& f = transfer->protocol_frame_msg; + f.flag = 0; std::shared_ptr p; if (const auto maybe = GetBestConvoTagFor(remote)) { @@ -1983,33 +1983,35 @@ namespace llarp return false; } - f.T = tag; + f.convo_tag = tag; // TODO: check expiration of our end - auto m = std::make_shared(f.T); + auto m = std::make_shared(f.convo_tag); m->PutBuffer(data); - f.N.Randomize(); - f.C.Zero(); - f.R = 0; - transfer->Y.Randomize(); + f.nonce.Randomize(); + f.cipher.Zero(); + f.flag = 0; + transfer->nonce.Randomize(); m->proto = t; m->introReply = p->intro; m->sender = m_Identity.pub; - if (auto maybe = GetSeqNoForConvo(f.T)) + if (auto maybe = GetSeqNoForConvo(f.convo_tag)) { m->seqno = *maybe; } else { - LogWarn(Name(), " could not set sequence number, no session T=", f.T); + LogWarn(Name(), " could not set sequence number, no session T=", f.convo_tag); return false; } - f.S = m->seqno; - f.F = p->intro.pathID; - transfer->P = replyIntro.pathID; + f.sequence_number = m->seqno; + f.path_id = p->intro.path_id; + transfer->path_id = replyIntro.path_id; Router()->QueueWork([transfer, p, m, K, this]() { - if (not transfer->T.EncryptAndSign(*m, K, m_Identity)) + if (not transfer->protocol_frame_msg.EncryptAndSign(*m, K, m_Identity)) { - LogError("failed to encrypt and sign for sessionn T=", transfer->T.T); + LogError( + "failed to encrypt and sign for sessionn T=", + transfer->protocol_frame_msg.convo_tag); return; } m_SendQueue.tryPushBack(SendEvent_t{transfer, p}); @@ -2017,14 +2019,12 @@ namespace llarp }); return true; } - else - { - LogWarn( - Name(), - " SendToOrQueue on inbound convo from ", - remote, - " but get-best returned none; bug?"); - } + + LogWarn( + Name(), + " SendToOrQueue on inbound convo from ", + remote, + " but get-best returned none; bug?"); } if (not WantsOutboundSession(remote)) { diff --git a/llarp/service/endpoint.hpp b/llarp/service/endpoint.hpp index 46fd42e7b3..4c24b43926 100644 --- a/llarp/service/endpoint.hpp +++ b/llarp/service/endpoint.hpp @@ -205,7 +205,7 @@ namespace llarp HandleGotNameMessage(std::shared_ptr msg) override; bool - HandleHiddenServiceFrame(path::Path_ptr p, const service::ProtocolFrame& msg); + HandleHiddenServiceFrame(path::Path_ptr p, const service::ProtocolFrameMessage& msg); void SetEndpointAuth(std::shared_ptr policy); diff --git a/llarp/service/endpoint_util.hpp b/llarp/service/endpoint_util.hpp index 9b2c469652..62792f7827 100644 --- a/llarp/service/endpoint_util.hpp +++ b/llarp/service/endpoint_util.hpp @@ -2,75 +2,70 @@ #include "endpoint_types.hpp" -namespace llarp +namespace llarp::service { - namespace service + struct EndpointUtil { - struct EndpointUtil - { - static void - ExpireSNodeSessions(llarp_time_t now, SNodeSessions& sessions); + static void + ExpireSNodeSessions(llarp_time_t now, SNodeSessions& sessions); - static void - ExpirePendingTx(llarp_time_t now, PendingLookups& lookups); + static void + ExpirePendingTx(llarp_time_t now, PendingLookups& lookups); - static void - ExpirePendingRouterLookups(llarp_time_t now, PendingRouters& routers); + static void + ExpirePendingRouterLookups(llarp_time_t now, PendingRouters& routers); - static void - DeregisterDeadSessions(llarp_time_t now, Sessions& sessions); + static void + DeregisterDeadSessions(llarp_time_t now, Sessions& sessions); - static void - TickRemoteSessions( - llarp_time_t now, Sessions& remoteSessions, Sessions& deadSessions, ConvoMap& sessions); + static void + TickRemoteSessions( + llarp_time_t now, Sessions& remoteSessions, Sessions& deadSessions, ConvoMap& sessions); - static void - ExpireConvoSessions(llarp_time_t now, ConvoMap& sessions); + static void + ExpireConvoSessions(llarp_time_t now, ConvoMap& sessions); - static void - StopRemoteSessions(Sessions& remoteSessions); + static void + StopRemoteSessions(Sessions& remoteSessions); - static void - StopSnodeSessions(SNodeSessions& sessions); + static void + StopSnodeSessions(SNodeSessions& sessions); - static bool - HasPathToService(const Address& addr, const Sessions& remoteSessions); + static bool + HasPathToService(const Address& addr, const Sessions& remoteSessions); - static bool - GetConvoTagsForService( - const ConvoMap& sessions, const Address& addr, std::set& tags); - }; + static bool + GetConvoTagsForService(const ConvoMap& sessions, const Address& addr, std::set& tags); + }; - template - static path::Path::UniqueEndpointSet_t - GetManyPathsWithUniqueEndpoints( - Endpoint_t* ep, - size_t N, - std::optional maybeLocation = std::nullopt, - size_t tries = 10) + template + static path::Path::UniqueEndpointSet_t + GetManyPathsWithUniqueEndpoints( + Endpoint_t* ep, + size_t N, + std::optional maybeLocation = std::nullopt, + size_t tries = 10) + { + std::unordered_set exclude; + path::Path::UniqueEndpointSet_t paths; + do { - std::unordered_set exclude; - path::Path::UniqueEndpointSet_t paths; - do + --tries; + path::Path_ptr path; + if (maybeLocation) { - --tries; - path::Path_ptr path; - if (maybeLocation) - { - path = ep->GetEstablishedPathClosestTo(RouterID{maybeLocation->as_array()}, exclude); - } - else - { - path = ep->PickRandomEstablishedPath(); - } - if (path and path->IsReady()) - { - paths.emplace(path); - exclude.insert(path->Endpoint()); - } - } while (tries > 0 and paths.size() < N); - return paths; - } - } // namespace service - -} // namespace llarp + path = ep->GetEstablishedPathClosestTo(RouterID{maybeLocation->as_array()}, exclude); + } + else + { + path = ep->PickRandomEstablishedPath(); + } + if (path and path->IsReady()) + { + paths.emplace(path); + exclude.insert(path->Endpoint()); + } + } while (tries > 0 and paths.size() < N); + return paths; + } +} // namespace llarp::service diff --git a/llarp/service/hidden_service_address_lookup.cpp b/llarp/service/hidden_service_address_lookup.cpp index 5c386101a0..64d0f5fed9 100644 --- a/llarp/service/hidden_service_address_lookup.cpp +++ b/llarp/service/hidden_service_address_lookup.cpp @@ -4,58 +4,55 @@ #include "endpoint.hpp" #include -namespace llarp +namespace llarp::service { - namespace service + HiddenServiceAddressLookup::HiddenServiceAddressLookup( + Endpoint* p, + HandlerFunc h, + const dht::Key_t& l, + const PubKey& k, + const RouterID& ep, + uint64_t order, + uint64_t tx, + llarp_time_t timeout) + : IServiceLookup(p, tx, "HSLookup", timeout) + , rootkey(k) + , relayOrder(order) + , location(l) + , handle(std::move(h)) { - HiddenServiceAddressLookup::HiddenServiceAddressLookup( - Endpoint* p, - HandlerFunc h, - const dht::Key_t& l, - const PubKey& k, - const RouterID& ep, - uint64_t order, - uint64_t tx, - llarp_time_t timeout) - : IServiceLookup(p, tx, "HSLookup", timeout) - , rootkey(k) - , relayOrder(order) - , location(l) - , handle(std::move(h)) - { - endpoint = ep; - } + endpoint = ep; + } - bool - HiddenServiceAddressLookup::HandleIntrosetResponse(const std::set& results) + bool + HiddenServiceAddressLookup::HandleIntrosetResponse(const std::set& results) + { + std::optional found; + const Address remote{rootkey}; + if (results.size() > 0) { - std::optional found; - const Address remote{rootkey}; - if (results.size() > 0) + EncryptedIntroSet selected; + for (const auto& introset : results) + { + if (selected.OtherIsNewer(introset)) + selected = introset; + } + const auto maybe = selected.MaybeDecrypt(rootkey); + if (maybe) { - EncryptedIntroSet selected; - for (const auto& introset : results) - { - if (selected.OtherIsNewer(introset)) - selected = introset; - } - const auto maybe = selected.MaybeDecrypt(rootkey); - if (maybe) - { - LogInfo("found result for ", remote.ToString()); - found = *maybe; - } + LogInfo("found result for ", remote.ToString()); + found = *maybe; } - return handle(remote, found, endpoint, TimeLeft(time_now_ms()), relayOrder); } + return handle(remote, found, endpoint, TimeLeft(time_now_ms()), relayOrder); + } - std::shared_ptr - HiddenServiceAddressLookup::BuildRequestMessage() - { - auto msg = std::make_shared(); - msg->M.emplace_back(std::make_unique(txid, location, relayOrder)); - return msg; - } + std::shared_ptr + HiddenServiceAddressLookup::BuildRequestMessage() + { + auto msg = std::make_shared(); + msg->dht_msgs.emplace_back(std::make_unique(txid, location, relayOrder)); + return msg; + } - } // namespace service -} // namespace llarp +} // namespace llarp::service diff --git a/llarp/service/hidden_service_address_lookup.hpp b/llarp/service/hidden_service_address_lookup.hpp index b90260a4a8..f81b9b1556 100644 --- a/llarp/service/hidden_service_address_lookup.hpp +++ b/llarp/service/hidden_service_address_lookup.hpp @@ -1,53 +1,50 @@ #pragma once -#include +#include #include "intro_set.hpp" #include "lookup.hpp" -namespace llarp +namespace llarp::service { - namespace service - { - /// interval for which we will add to lookup timeout interval - constexpr auto IntrosetLookupGraceInterval = 20s; + /// interval for which we will add to lookup timeout interval + constexpr auto IntrosetLookupGraceInterval = 20s; - struct Endpoint; - struct HiddenServiceAddressLookup : public IServiceLookup + struct Endpoint; + struct HiddenServiceAddressLookup : public IServiceLookup + { + const PubKey rootkey; + uint64_t relayOrder; + const dht::Key_t location; + using HandlerFunc = std::function, const RouterID&, llarp_time_t, uint64_t)>; + HandlerFunc handle; + + HiddenServiceAddressLookup( + Endpoint* p, + HandlerFunc h, + const dht::Key_t& location, + const PubKey& rootkey, + const RouterID& routerAsked, + uint64_t relayOrder, + uint64_t tx, + llarp_time_t timeout); + + ~HiddenServiceAddressLookup() override = default; + + bool + IsFor(EndpointBase::AddressVariant_t addr) const override { - const PubKey rootkey; - uint64_t relayOrder; - const dht::Key_t location; - using HandlerFunc = std::function, const RouterID&, llarp_time_t, uint64_t)>; - HandlerFunc handle; - - HiddenServiceAddressLookup( - Endpoint* p, - HandlerFunc h, - const dht::Key_t& location, - const PubKey& rootkey, - const RouterID& routerAsked, - uint64_t relayOrder, - uint64_t tx, - llarp_time_t timeout); - - ~HiddenServiceAddressLookup() override = default; - - virtual bool - IsFor(EndpointBase::AddressVariant_t addr) const override + if (const auto* ptr = std::get_if
(&addr)) { - if (const auto* ptr = std::get_if
(&addr)) - { - return Address{rootkey} == *ptr; - } - return false; + return Address{rootkey} == *ptr; } + return false; + } - bool - HandleIntrosetResponse(const std::set& results) override; + bool + HandleIntrosetResponse(const std::set& results) override; - std::shared_ptr - BuildRequestMessage() override; - }; - } // namespace service -} // namespace llarp + std::shared_ptr + BuildRequestMessage() override; + }; +} // namespace llarp::service diff --git a/llarp/service/identity.cpp b/llarp/service/identity.cpp index a28bb22044..1329ef739c 100644 --- a/llarp/service/identity.cpp +++ b/llarp/service/identity.cpp @@ -4,185 +4,184 @@ #include #include -namespace llarp +namespace llarp::service { - namespace service + bool + Identity::BEncode(llarp_buffer_t* buf) const { - bool - Identity::BEncode(llarp_buffer_t* buf) const + if (!bencode_start_dict(buf)) + return false; + if (!BEncodeWriteDictEntry("s", signkey, buf)) + return false; + if (!BEncodeWriteDictInt("v", version, buf)) + return false; + return bencode_end(buf); + } + + bool + Identity::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) + { + bool read = false; + if (!BEncodeMaybeReadDictEntry("s", signkey, read, key, buf)) + return false; + if (!BEncodeMaybeReadDictInt("v", version, read, key, buf)) + return false; + if (not read) + return bencode_discard(buf); + return true; + } + + void + Identity::Clear() + { + signkey.Zero(); + enckey.Zero(); + pq.Zero(); + derivedSignKey.Zero(); + vanity.Zero(); + } + + void + Identity::RegenerateKeys() + { + auto crypto = CryptoManager::instance(); + crypto->identity_keygen(signkey); + crypto->encryption_keygen(enckey); + pub.Update(seckey_topublic(signkey), seckey_topublic(enckey)); + crypto->pqe_keygen(pq); + if (not crypto->derive_subkey_private(derivedSignKey, signkey, 1)) { - if (!bencode_start_dict(buf)) - return false; - if (!BEncodeWriteDictEntry("s", signkey, buf)) - return false; - if (!BEncodeWriteDictInt("v", version, buf)) - return false; - return bencode_end(buf); + throw std::runtime_error("failed to derive subkey"); } + } + + bool + Identity::KeyExchange( + path_dh_func dh, + SharedSecret& result, + const ServiceInfo& other, + const KeyExchangeNonce& N) const + { + return dh(result, other.EncryptionPublicKey(), enckey, N); + } - bool - Identity::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) - { - bool read = false; - if (!BEncodeMaybeReadDictEntry("s", signkey, read, key, buf)) - return false; - if (!BEncodeMaybeReadDictInt("v", version, read, key, buf)) - return false; - if (not read) - return bencode_discard(buf); - return true; - } + bool + Identity::Sign(Signature& sig, const llarp_buffer_t& buf) const + { + return CryptoManager::instance()->sign(sig, signkey, buf); + } + + void + Identity::EnsureKeys(fs::path fname, bool needBackup) + { + // make sure we are empty + Clear(); - void - Identity::Clear() + std::array tmp; + + // this can throw + bool exists = fs::exists(fname); + + if (exists and needBackup) { - signkey.Zero(); - enckey.Zero(); - pq.Zero(); - derivedSignKey.Zero(); - vanity.Zero(); + KeyManager::backupFileByMoving(fname); + exists = false; } - void - Identity::RegenerateKeys() + // check for file + if (!exists) { - auto crypto = CryptoManager::instance(); - crypto->identity_keygen(signkey); - crypto->encryption_keygen(enckey); - pub.Update(seckey_topublic(signkey), seckey_topublic(enckey)); - crypto->pqe_keygen(pq); - if (not crypto->derive_subkey_private(derivedSignKey, signkey, 1)) + llarp_buffer_t buf{tmp}; + // regen and encode + RegenerateKeys(); + if (!BEncode(&buf)) + throw std::length_error("failed to encode new identity"); + const auto sz = buf.cur - buf.base; + // write + try { - throw std::runtime_error("failed to derive subkey"); + util::dump_file(fname, tmp.data(), sz); } + catch (const std::exception& e) + { + throw std::runtime_error{fmt::format("failed to write {}: {}", fname, e.what())}; + } + return; } - bool - Identity::KeyExchange( - path_dh_func dh, - SharedSecret& result, - const ServiceInfo& other, - const KeyExchangeNonce& N) const + if (not fs::is_regular_file(fname)) { - return dh(result, other.EncryptionPublicKey(), enckey, N); + throw std::invalid_argument{fmt::format("{} is not a regular file", fname)}; } - bool - Identity::Sign(Signature& sig, const llarp_buffer_t& buf) const + // read file + try { - return CryptoManager::instance()->sign(sig, signkey, buf); + util::slurp_file(fname, tmp.data(), tmp.size()); } - - void - Identity::EnsureKeys(fs::path fname, bool needBackup) + catch (const std::length_error&) { - // make sure we are empty - Clear(); - - std::array tmp; - - // this can throw - bool exists = fs::exists(fname); - - if (exists and needBackup) - { - KeyManager::backupFileByMoving(fname); - exists = false; - } - - // check for file - if (!exists) - { - llarp_buffer_t buf{tmp}; - // regen and encode - RegenerateKeys(); - if (!BEncode(&buf)) - throw std::length_error("failed to encode new identity"); - const auto sz = buf.cur - buf.base; - // write - try - { - util::dump_file(fname, tmp.data(), sz); - } - catch (const std::exception& e) - { - throw std::runtime_error{fmt::format("failed to write {}: {}", fname, e.what())}; - } - return; - } + throw std::length_error{"service identity too big"}; + } + // (don't catch io error exceptions) + { + llarp_buffer_t buf{tmp}; + if (!bencode_decode_dict(*this, &buf)) + throw std::length_error{"could not decode service identity"}; + } + auto crypto = CryptoManager::instance(); - if (not fs::is_regular_file(fname)) - { - throw std::invalid_argument{fmt::format("{} is not a regular file", fname)}; - } + // ensure that the encryption key is set + if (enckey.IsZero()) + crypto->encryption_keygen(enckey); - // read file - try - { - util::slurp_file(fname, tmp.data(), tmp.size()); - } - catch (const std::length_error&) - { - throw std::length_error{"service identity too big"}; - } - // (don't catch io error exceptions) - { - llarp_buffer_t buf{tmp}; - if (!bencode_decode_dict(*this, &buf)) - throw std::length_error{"could not decode service identity"}; - } - auto crypto = CryptoManager::instance(); - - // ensure that the encryption key is set - if (enckey.IsZero()) - crypto->encryption_keygen(enckey); - - // also ensure the ntru key is set - if (pq.IsZero()) - crypto->pqe_keygen(pq); - - std::optional van; - if (!vanity.IsZero()) - van = vanity; - // update pubkeys - pub.Update(seckey_topublic(signkey), seckey_topublic(enckey), van); - if (not crypto->derive_subkey_private(derivedSignKey, signkey, 1)) - { - throw std::runtime_error("failed to derive subkey"); - } - } + // also ensure the ntru key is set + if (pq.IsZero()) + crypto->pqe_keygen(pq); - std::optional - Identity::EncryptAndSignIntroSet(const IntroSet& other_i, llarp_time_t now) const + std::optional van; + if (!vanity.IsZero()) + van = vanity; + // update pubkeys + pub.Update(seckey_topublic(signkey), seckey_topublic(enckey), van); + if (not crypto->derive_subkey_private(derivedSignKey, signkey, 1)) { - EncryptedIntroSet encrypted; - - if (other_i.intros.empty()) - return std::nullopt; - IntroSet i{other_i}; - encrypted.nounce.Randomize(); - // set timestamp - // TODO: round to nearest 1000 ms - i.timestampSignedAt = now; - encrypted.signedAt = now; - // set service info - i.addressKeys = pub; - // set public encryption key - i.sntrupKey = pq_keypair_to_public(pq); - std::array tmp; - llarp_buffer_t buf{tmp}; - if (not i.BEncode(&buf)) - return std::nullopt; - // rewind and resize buffer - buf.sz = buf.cur - buf.base; - buf.cur = buf.base; - const SharedSecret k{i.addressKeys.Addr()}; - CryptoManager::instance()->xchacha20(buf, k, encrypted.nounce); - encrypted.introsetPayload = buf.copy(); - - if (not encrypted.Sign(derivedSignKey)) - return std::nullopt; - return encrypted; + throw std::runtime_error("failed to derive subkey"); } - } // namespace service -} // namespace llarp + } + + std::optional + Identity::EncryptAndSignIntroSet(const IntroSet& other_i, llarp_time_t now) const + { + EncryptedIntroSet encrypted; + + if (other_i.intros.empty()) + return std::nullopt; + IntroSet i{other_i}; + encrypted.nounce.Randomize(); + // set timestamp + // TODO: round to nearest 1000 ms + i.time_signed = now; + encrypted.signedAt = now; + // set service info + i.addressKeys = pub; + // set public encryption key + i.sntru_pubkey = pq_keypair_to_public(pq); + std::array tmp; + llarp_buffer_t buf{tmp}; + + auto bte = i.bt_encode(); + buf.write(bte.begin(), bte.end()); + + // rewind and resize buffer + buf.sz = buf.cur - buf.base; + buf.cur = buf.base; + const SharedSecret k{i.addressKeys.Addr()}; + CryptoManager::instance()->xchacha20(buf, k, encrypted.nounce); + encrypted.introsetPayload = buf.copy(); + + if (not encrypted.Sign(derivedSignKey)) + return std::nullopt; + return encrypted; + } +} // namespace llarp::service diff --git a/llarp/service/identity.hpp b/llarp/service/identity.hpp index 5278f1af6a..dfbf8ed253 100644 --- a/llarp/service/identity.hpp +++ b/llarp/service/identity.hpp @@ -11,60 +11,57 @@ #include -namespace llarp +namespace llarp::service { - namespace service + // private keys + struct Identity { - // private keys - struct Identity - { - SecretKey enckey; - SecretKey signkey; - PrivateKey derivedSignKey; - PQKeyPair pq; - uint64_t version = llarp::constants::proto_version; - VanityNonce vanity; + SecretKey enckey; + SecretKey signkey; + PrivateKey derivedSignKey; + PQKeyPair pq; + uint64_t version = llarp::constants::proto_version; + VanityNonce vanity; - // public service info - ServiceInfo pub; + // public service info + ServiceInfo pub; - // regenerate secret keys - void - RegenerateKeys(); + // regenerate secret keys + void + RegenerateKeys(); - bool - BEncode(llarp_buffer_t* buf) const; + bool + BEncode(llarp_buffer_t* buf) const; - /// @param needBackup determines whether existing keys will be cycled - void - EnsureKeys(fs::path fpath, bool needBackup); + /// @param needBackup determines whether existing keys will be cycled + void + EnsureKeys(fs::path fpath, bool needBackup); - bool - KeyExchange( - path_dh_func dh, - SharedSecret& sharedkey, - const ServiceInfo& other, - const KeyExchangeNonce& N) const; + bool + KeyExchange( + path_dh_func dh, + SharedSecret& sharedkey, + const ServiceInfo& other, + const KeyExchangeNonce& N) const; - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf); + bool + decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf); - std::optional - EncryptAndSignIntroSet(const IntroSet& i, llarp_time_t now) const; + std::optional + EncryptAndSignIntroSet(const IntroSet& i, llarp_time_t now) const; - bool - Sign(Signature& sig, const llarp_buffer_t& buf) const; + bool + Sign(Signature& sig, const llarp_buffer_t& buf) const; - /// zero out all secret key members - void - Clear(); - }; + /// zero out all secret key members + void + Clear(); + }; - inline bool - operator==(const Identity& lhs, const Identity& rhs) - { - return std::tie(lhs.enckey, lhs.signkey, lhs.pq, lhs.version, lhs.vanity) - == std::tie(rhs.enckey, rhs.signkey, rhs.pq, rhs.version, rhs.vanity); - } - } // namespace service -} // namespace llarp + inline bool + operator==(const Identity& lhs, const Identity& rhs) + { + return std::tie(lhs.enckey, lhs.signkey, lhs.pq, lhs.version, lhs.vanity) + == std::tie(rhs.enckey, rhs.signkey, rhs.pq, rhs.version, rhs.vanity); + } +} // namespace llarp::service diff --git a/llarp/service/info.cpp b/llarp/service/info.cpp index b9f5ee6180..6ab6101a62 100644 --- a/llarp/service/info.cpp +++ b/llarp/service/info.cpp @@ -9,97 +9,86 @@ #include #include -namespace llarp +namespace llarp::service { - namespace service + bool + ServiceInfo::Verify(const llarp_buffer_t& payload, const Signature& sig) const { - bool - ServiceInfo::Verify(const llarp_buffer_t& payload, const Signature& sig) const - { - return CryptoManager::instance()->verify(signkey, payload, sig); - } + return CryptoManager::instance()->verify(signkey, payload, sig); + } - bool - ServiceInfo::Update( - const byte_t* sign, const byte_t* enc, const std::optional& nonce) + bool + ServiceInfo::Update( + const byte_t* sign, const byte_t* enc, const std::optional& nonce) + { + signkey = sign; + enckey = enc; + if (nonce) { - signkey = sign; - enckey = enc; - if (nonce) - { - vanity = *nonce; - } - return UpdateAddr(); + vanity = *nonce; } + return UpdateAddr(); + } - bool - ServiceInfo::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) - { - bool read = false; - if (!BEncodeMaybeReadDictEntry("e", enckey, read, key, val)) - return false; - if (!BEncodeMaybeReadDictEntry("s", signkey, read, key, val)) - return false; - if (!BEncodeMaybeReadDictInt("v", version, read, key, val)) - return false; - if (!BEncodeMaybeReadDictEntry("x", vanity, read, key, val)) - return false; - return read; - } + bool + ServiceInfo::decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) + { + bool read = false; + if (!BEncodeMaybeReadDictEntry("e", enckey, read, key, val)) + return false; + if (!BEncodeMaybeReadDictEntry("s", signkey, read, key, val)) + return false; + if (!BEncodeMaybeReadDictInt("v", version, read, key, val)) + return false; + if (!BEncodeMaybeReadDictEntry("x", vanity, read, key, val)) + return false; + return read; + } - bool - ServiceInfo::BEncode(llarp_buffer_t* buf) const - { - if (!bencode_start_dict(buf)) - return false; - if (!BEncodeWriteDictEntry("e", enckey, buf)) - return false; - if (!BEncodeWriteDictEntry("s", signkey, buf)) - return false; - if (!BEncodeWriteDictInt("v", llarp::constants::proto_version, buf)) - return false; - if (!vanity.IsZero()) - { - if (!BEncodeWriteDictEntry("x", vanity, buf)) - return false; - } - return bencode_end(buf); - } + void + ServiceInfo::bt_encode(oxenc::bt_dict_producer& btdp) const + { + btdp.append("e", enckey.ToView()); + btdp.append("s", signkey.ToView()); + btdp.append("v", version); - std::string - ServiceInfo::Name() const - { - if (m_CachedAddr.IsZero()) - { - Address addr; - CalculateAddress(addr.as_array()); - return addr.ToString(); - } - return m_CachedAddr.ToString(); - } + if (not vanity.IsZero()) + btdp.append("x", vanity.ToView()); + } - bool - ServiceInfo::CalculateAddress(std::array& data) const + std::string + ServiceInfo::Name() const + { + if (m_CachedAddr.IsZero()) { - data = signkey.as_array(); - return true; + Address addr; + CalculateAddress(addr.as_array()); + return addr.ToString(); } + return m_CachedAddr.ToString(); + } - bool - ServiceInfo::UpdateAddr() - { - if (m_CachedAddr.IsZero()) - { - return CalculateAddress(m_CachedAddr.as_array()); - } - return true; - } + bool + ServiceInfo::CalculateAddress(std::array& data) const + { + data = signkey.as_array(); + return true; + } - std::string - ServiceInfo::ToString() const + bool + ServiceInfo::UpdateAddr() + { + if (m_CachedAddr.IsZero()) { - return fmt::format("[ServiceInfo e={} s={} v={} x={}]", enckey, signkey, version, vanity); + return CalculateAddress(m_CachedAddr.as_array()); } + return true; + } + + std::string + ServiceInfo::ToString() const + { + return fmt::format("[ServiceInfo e={} s={} v={} x={}]", enckey, signkey, version, vanity); + } - } // namespace service -} // namespace llarp +} // namespace llarp::service diff --git a/llarp/service/info.hpp b/llarp/service/info.hpp index 8244f6db95..8d9a43e45b 100644 --- a/llarp/service/info.hpp +++ b/llarp/service/info.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include #include "address.hpp" #include "vanity.hpp" @@ -7,102 +9,104 @@ #include -namespace llarp +namespace +{ + static auto info_cat = llarp::log::Cat("lokinet.info"); +} // namespace + +namespace llarp::service { - namespace service + struct ServiceInfo { - struct ServiceInfo - { - private: - PubKey enckey; - PubKey signkey; - mutable Address m_CachedAddr; + private: + PubKey enckey; + PubKey signkey; + mutable Address m_CachedAddr; - public: - VanityNonce vanity; - uint64_t version = llarp::constants::proto_version; + public: + VanityNonce vanity; + uint64_t version = llarp::constants::proto_version; - void - RandomizeVanity() - { - vanity.Randomize(); - } + void + RandomizeVanity() + { + vanity.Randomize(); + } - bool - Verify(const llarp_buffer_t& payload, const Signature& sig) const; + bool + Verify(const llarp_buffer_t& payload, const Signature& sig) const; - const PubKey& - EncryptionPublicKey() const + const PubKey& + EncryptionPublicKey() const + { + if (m_CachedAddr.IsZero()) { - if (m_CachedAddr.IsZero()) - { - CalculateAddress(m_CachedAddr.as_array()); - } - return enckey; + CalculateAddress(m_CachedAddr.as_array()); } + return enckey; + } - bool - Update(const byte_t* sign, const byte_t* enc, const std::optional& nonce = {}); - - bool - operator==(const ServiceInfo& other) const - { - return enckey == other.enckey && signkey == other.signkey && version == other.version - && vanity == other.vanity; - } + bool + Update(const byte_t* sign, const byte_t* enc, const std::optional& nonce = {}); - bool - operator!=(const ServiceInfo& other) const - { - return !(*this == other); - } - - bool - operator<(const ServiceInfo& other) const - { - return Addr() < other.Addr(); - } + bool + operator==(const ServiceInfo& other) const + { + return enckey == other.enckey && signkey == other.signkey && version == other.version + && vanity == other.vanity; + } - std::string - ToString() const; + bool + operator!=(const ServiceInfo& other) const + { + return !(*this == other); + } - /// .loki address - std::string - Name() const; + bool + operator<(const ServiceInfo& other) const + { + return Addr() < other.Addr(); + } - bool - UpdateAddr(); + std::string + ToString() const; - const Address& - Addr() const - { - if (m_CachedAddr.IsZero()) - { - CalculateAddress(m_CachedAddr.as_array()); - } - return m_CachedAddr; - } + /// .loki address + std::string + Name() const; - /// calculate our address - bool - CalculateAddress(std::array& data) const; + bool + UpdateAddr(); - bool - BDecode(llarp_buffer_t* buf) + const Address& + Addr() const + { + if (m_CachedAddr.IsZero()) { - if (not bencode_decode_dict(*this, buf)) - return false; - return UpdateAddr(); + CalculateAddress(m_CachedAddr.as_array()); } + return m_CachedAddr; + } - bool - BEncode(llarp_buffer_t* buf) const; + /// calculate our address + bool + CalculateAddress(std::array& data) const; - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf); - }; - } // namespace service -} // namespace llarp + bool + BDecode(llarp_buffer_t* buf) + { + if (not bencode_decode_dict(*this, buf)) + return false; + return UpdateAddr(); + } + + void + bt_encode(oxenc::bt_dict_producer& btdp) const; + + bool + decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf); + }; +} // namespace llarp::service template <> constexpr inline bool llarp::IsToStringFormattable = true; diff --git a/llarp/service/intro.cpp b/llarp/service/intro.cpp index 026d49dee6..bcb1eac99d 100644 --- a/llarp/service/intro.cpp +++ b/llarp/service/intro.cpp @@ -1,81 +1,73 @@ #include "intro.hpp" #include -namespace llarp +namespace llarp::service { - namespace service + util::StatusObject + Introduction::ExtractStatus() const { - util::StatusObject - Introduction::ExtractStatus() const - { - util::StatusObject obj{ - {"router", router.ToHex()}, - {"path", pathID.ToHex()}, - {"expiresAt", to_json(expiresAt)}, - {"latency", to_json(latency)}, - {"version", uint64_t(version)}}; - return obj; - } + util::StatusObject obj{ + {"router", router.ToHex()}, + {"path", path_id.ToHex()}, + {"expiresAt", to_json(expiry)}, + {"latency", to_json(latency)}, + {"version", uint64_t(version)}}; + return obj; + } - bool - Introduction::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) - { - bool read = false; - if (!BEncodeMaybeReadDictEntry("k", router, read, key, buf)) - return false; - if (!BEncodeMaybeReadDictInt("l", latency, read, key, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("p", pathID, read, key, buf)) - return false; - if (!BEncodeMaybeReadDictInt("v", version, read, key, buf)) - return false; - if (!BEncodeMaybeReadDictInt("x", expiresAt, read, key, buf)) - return false; - return read; - } + bool + Introduction::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) + { + bool read = false; + if (!BEncodeMaybeReadDictEntry("k", router, read, key, buf)) + return false; + if (!BEncodeMaybeReadDictInt("l", latency, read, key, buf)) + return false; + if (!BEncodeMaybeReadDictEntry("p", path_id, read, key, buf)) + return false; + if (!BEncodeMaybeReadDictInt("v", version, read, key, buf)) + return false; + if (!BEncodeMaybeReadDictInt("x", expiry, read, key, buf)) + return false; + return read; + } - bool - Introduction::BEncode(llarp_buffer_t* buf) const + void + Introduction::bt_encode(oxenc::bt_dict_producer& btdp) const + { + try { - if (!bencode_start_dict(buf)) - return false; - - if (!BEncodeWriteDictEntry("k", router, buf)) - return false; - if (latency > 0s) - { - if (!BEncodeWriteDictInt("l", latency.count(), buf)) - return false; - } - if (!BEncodeWriteDictEntry("p", pathID, buf)) - return false; - if (!BEncodeWriteDictInt("v", version, buf)) - return false; - if (!BEncodeWriteDictInt("x", expiresAt.count(), buf)) - return false; - return bencode_end(buf); + btdp.append("k", router.ToView()); + btdp.append("l", latency.count()); + btdp.append("p", path_id.ToView()); + btdp.append("v", version); + btdp.append("x", expiry.count()); } - - void - Introduction::Clear() + catch (...) { - router.Zero(); - pathID.Zero(); - latency = 0s; - expiresAt = 0s; + log::critical(intro_cat, "Error: Introduction failed to bt encode contents!"); } + } - std::string - Introduction::ToString() const - { - return fmt::format( - "[Intro k={} l={} p={} v={} x={}]", - RouterID{router}, - latency.count(), - pathID, - version, - expiresAt.count()); - } + void + Introduction::Clear() + { + router.Zero(); + path_id.Zero(); + latency = 0s; + expiry = 0s; + } + + std::string + Introduction::ToString() const + { + return fmt::format( + "[Intro k={} l={} p={} v={} x={}]", + RouterID{router}, + latency.count(), + path_id, + version, + expiry.count()); + } - } // namespace service -} // namespace llarp +} // namespace llarp::service diff --git a/llarp/service/intro.hpp b/llarp/service/intro.hpp index bb659a4d4f..ebfcf03660 100644 --- a/llarp/service/intro.hpp +++ b/llarp/service/intro.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include #include #include @@ -7,82 +9,84 @@ #include -namespace llarp +namespace +{ + static auto intro_cat = llarp::log::Cat("lokinet.intro"); +} // namespace + +namespace llarp::service { - namespace service + struct Introduction { - struct Introduction + RouterID router; + PathID_t path_id; + llarp_time_t latency = 0s; + llarp_time_t expiry = 0s; + uint64_t version = llarp::constants::proto_version; + + util::StatusObject + ExtractStatus() const; + + bool + IsExpired(llarp_time_t now) const + { + return now >= expiry; + } + + bool + ExpiresSoon(llarp_time_t now, llarp_time_t dlt = 30s) const + { + return IsExpired(now + dlt); + } + + std::string + ToString() const; + + void + bt_encode(oxenc::bt_dict_producer& btdp) const; + + bool + BDecode(llarp_buffer_t* buf) + { + return bencode_decode_dict(*this, buf); + } + + bool + decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf); + + void + Clear(); + + bool + operator<(const Introduction& other) const + { + return std::tie(expiry, path_id, router, version, latency) + < std::tie(other.expiry, other.path_id, other.router, other.version, other.latency); + } + + bool + operator==(const Introduction& other) const { - RouterID router; - PathID_t pathID; - llarp_time_t latency = 0s; - llarp_time_t expiresAt = 0s; - uint64_t version = llarp::constants::proto_version; - - util::StatusObject - ExtractStatus() const; - - bool - IsExpired(llarp_time_t now) const - { - return now >= expiresAt; - } - - bool - ExpiresSoon(llarp_time_t now, llarp_time_t dlt = 30s) const - { - return IsExpired(now + dlt); - } - - std::string - ToString() const; - - bool - BEncode(llarp_buffer_t* buf) const; - - bool - BDecode(llarp_buffer_t* buf) - { - return bencode_decode_dict(*this, buf); - } - - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf); - - void - Clear(); - - bool - operator<(const Introduction& other) const - { - return std::tie(expiresAt, pathID, router, version, latency) - < std::tie(other.expiresAt, other.pathID, other.router, other.version, other.latency); - } - - bool - operator==(const Introduction& other) const - { - return pathID == other.pathID && router == other.router; - } - - bool - operator!=(const Introduction& other) const - { - return pathID != other.pathID || router != other.router; - } - }; - - /// comparator for introset timestamp - struct CompareIntroTimestamp + return path_id == other.path_id && router == other.router; + } + + bool + operator!=(const Introduction& other) const { - bool - operator()(const Introduction& left, const Introduction& right) const - { - return left.expiresAt > right.expiresAt; - } - }; - } // namespace service -} // namespace llarp + return path_id != other.path_id || router != other.router; + } + }; + + /// comparator for introset timestamp + struct CompareIntroTimestamp + { + bool + operator()(const Introduction& left, const Introduction& right) const + { + return left.expiry > right.expiry; + } + }; +} // namespace llarp::service template <> constexpr inline bool llarp::IsToStringFormattable = true; @@ -95,7 +99,7 @@ namespace std size_t operator()(const llarp::service::Introduction& i) const { - return std::hash{}(i.router) ^ std::hash{}(i.pathID); + return std::hash{}(i.router) ^ std::hash{}(i.path_id); } }; } // namespace std diff --git a/llarp/service/intro_set.cpp b/llarp/service/intro_set.cpp index 07c39497f0..006741c1d8 100644 --- a/llarp/service/intro_set.cpp +++ b/llarp/service/intro_set.cpp @@ -35,7 +35,7 @@ namespace llarp::service } bool - EncryptedIntroSet::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) + EncryptedIntroSet::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) { bool read = false; if (key.startswith("x")) @@ -139,7 +139,7 @@ namespace llarp::service util::StatusObject IntroSet::ExtractStatus() const { - util::StatusObject obj{{"published", to_json(timestampSignedAt)}}; + util::StatusObject obj{{"published", to_json(time_signed)}}; std::vector introsObjs; std::transform( intros.begin(), @@ -152,27 +152,27 @@ namespace llarp::service std::vector protocols; std::transform( - supportedProtocols.begin(), - supportedProtocols.end(), + supported_protocols.begin(), + supported_protocols.end(), std::back_inserter(protocols), [](const auto& proto) -> util::StatusObject { return service::ToString(proto); }); obj["protos"] = protocols; std::vector ranges; std::transform( - ownedRanges.begin(), - ownedRanges.end(), + owned_ranges.begin(), + owned_ranges.end(), std::back_inserter(ranges), [](const auto& range) -> util::StatusObject { return range.ToString(); }); obj["advertisedRanges"] = ranges; - if (exitTrafficPolicy) - obj["exitPolicy"] = exitTrafficPolicy->ExtractStatus(); + if (exit_policy) + obj["exitPolicy"] = exit_policy->ExtractStatus(); return obj; } bool - IntroSet::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) + IntroSet::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) { bool read = false; if (!BEncodeMaybeReadDictEntry("a", addressKeys, read, key, buf)) @@ -183,7 +183,7 @@ namespace llarp::service net::TrafficPolicy policy; if (not policy.BDecode(buf)) return false; - exitTrafficPolicy = policy; + exit_policy = policy; return true; } @@ -191,7 +191,7 @@ namespace llarp::service { return BEncodeReadList(intros, buf); } - if (!BEncodeMaybeReadDictEntry("k", sntrupKey, read, key, buf)) + if (!BEncodeMaybeReadDictEntry("k", sntru_pubkey, read, key, buf)) return false; if (!BEncodeMaybeReadDictEntry("n", topic, read, key, buf)) @@ -206,7 +206,7 @@ namespace llarp::service uint64_t protoval; if (not bencode_read_integer(buf, &protoval)) return false; - supportedProtocols.emplace_back(static_cast(protoval)); + supported_protocols.emplace_back(static_cast(protoval)); } return true; }, @@ -215,7 +215,7 @@ namespace llarp::service if (key.startswith("r")) { - return BEncodeReadSet(ownedRanges, buf); + return BEncodeReadSet(owned_ranges, buf); } if (key.startswith("s")) @@ -241,7 +241,7 @@ namespace llarp::service read = true; } - if (!BEncodeMaybeReadDictInt("t", timestampSignedAt, read, key, buf)) + if (!BEncodeMaybeReadDictInt("t", time_signed, read, key, buf)) return false; if (!BEncodeMaybeReadDictInt("v", version, read, key, buf)) @@ -253,96 +253,67 @@ namespace llarp::service return read or bencode_discard(buf); } - bool - IntroSet::BEncode(llarp_buffer_t* buf) const + std::string + IntroSet::bt_encode() const { - if (not bencode_start_dict(buf)) - return false; - if (not BEncodeWriteDictEntry("a", addressKeys, buf)) - return false; + oxenc::bt_dict_producer btdp; - // exit policy if applicable - if (exitTrafficPolicy) + try { - if (not BEncodeWriteDictEntry("e", *exitTrafficPolicy, buf)) - return false; - } - // start introduction list - if (not bencode_write_bytestring(buf, "i", 1)) - return false; - if (not BEncodeWriteList(intros.begin(), intros.end(), buf)) - return false; - // end introduction list - - // pq pubkey - if (not BEncodeWriteDictEntry("k", sntrupKey, buf)) - return false; + { + auto subdict = btdp.append_dict("a"); + addressKeys.bt_encode(subdict); + } - // topic tag - if (not topic.ToString().empty()) - { - if (not BEncodeWriteDictEntry("n", topic, buf)) - return false; - } + if (exit_policy) + { + auto subdict = btdp.append_dict("e"); + exit_policy->bt_encode(subdict); + } - // supported ethertypes - if (not supportedProtocols.empty()) - { - if (not bencode_write_bytestring(buf, "p", 1)) - return false; + { + auto subdict = btdp.append_dict("i"); + for (auto& i : intros) + i.bt_encode(subdict); + } - if (not bencode_start_list(buf)) - return false; + btdp.append("k", sntru_pubkey.ToView()); + btdp.append("n", topic.ToView()); - for (const auto& proto : supportedProtocols) + if (not supported_protocols.empty()) { - if (not bencode_write_uint64(buf, static_cast(proto))) - return false; + auto sublist = btdp.append_list("p"); + for (auto& p : supported_protocols) + sublist.append(static_cast(p)); } - if (not bencode_end(buf)) - return false; - } + if (not owned_ranges.empty()) + { + auto sublist = btdp.append_list("s"); + for (auto& r : owned_ranges) + r.bt_encode(sublist); + } - // owned ranges - if (not ownedRanges.empty()) - { - if (not bencode_write_bytestring(buf, "r", 1)) - return false; + if (not SRVs.empty()) + btdp.append("s", oxenc::bt_serialize(SRVs)); - if (not BEncodeWriteSet(ownedRanges, buf)) - return false; + btdp.append("t", time_signed.count()); + btdp.append("v", version); + btdp.append("z", signature.ToView()); } - - // srv records - if (not SRVs.empty()) + catch (...) { - std::string serial = oxenc::bt_serialize(SRVs); - if (!bencode_write_bytestring(buf, "s", 1)) - return false; - if (!buf->write(serial.begin(), serial.end())) - return false; + log::critical(net_cat, "Error: IntroSet failed to bt encode contents!"); } - // timestamp - if (!BEncodeWriteDictInt("t", timestampSignedAt.count(), buf)) - return false; - - // write version - if (!BEncodeWriteDictInt("v", version, buf)) - return false; - - if (!BEncodeWriteDictEntry("z", signature, buf)) - return false; - - return bencode_end(buf); + return std::move(btdp).str(); } bool IntroSet::HasExpiredIntros(llarp_time_t now) const { for (const auto& intro : intros) - if (now >= intro.expiresAt) + if (now >= intro.expiry) return true; return false; } @@ -386,10 +357,10 @@ namespace llarp::service IntroSet copy; copy = *this; copy.signature.Zero(); - if (!copy.BEncode(&buf)) - { - return false; - } + + auto bte = copy.bt_encode(); + buf.write(bte.begin(), bte.end()); + // rewind and resize buffer buf.sz = buf.cur - buf.base; buf.cur = buf.base; @@ -402,7 +373,7 @@ namespace llarp::service now += MAX_INTROSET_TIME_DELTA; for (const auto& intro : intros) { - if (intro.expiresAt > now && intro.expiresAt - now > path::default_lifetime) + if (intro.expiry > now && intro.expiry - now > path::default_lifetime) { return false; } @@ -415,7 +386,7 @@ namespace llarp::service { llarp_time_t maxTime = 0s; for (const auto& intro : intros) - maxTime = std::max(intro.expiresAt, maxTime); + maxTime = std::max(intro.expiry, maxTime); return maxTime; } @@ -426,9 +397,9 @@ namespace llarp::service "[IntroSet addressKeys={} intros={{{}}} sntrupKey={} topic={} signedAt={} v={} sig={}]", addressKeys, fmt::format("{}", fmt::join(intros, ",")), - sntrupKey, + sntru_pubkey, topic, - timestampSignedAt.count(), + time_signed.count(), version, signature); } diff --git a/llarp/service/intro_set.hpp b/llarp/service/intro_set.hpp index fdeec01264..7556286dd3 100644 --- a/llarp/service/intro_set.hpp +++ b/llarp/service/intro_set.hpp @@ -20,189 +20,185 @@ #include #include -namespace llarp +namespace llarp::service { - namespace service - { - constexpr std::size_t MAX_INTROSET_SIZE = 4096; - // 10 seconds clock skew permitted for introset expiration - constexpr llarp_time_t MAX_INTROSET_TIME_DELTA = 10s; + constexpr std::size_t MAX_INTROSET_SIZE = 4096; + // 10 seconds clock skew permitted for introset expiration + constexpr llarp_time_t MAX_INTROSET_TIME_DELTA = 10s; - struct IntroSet + struct IntroSet + { + ServiceInfo addressKeys; + std::vector intros; + PQPubKey sntru_pubkey; + Tag topic; + std::vector SRVs; + llarp_time_t time_signed = 0s; + + /// ethertypes we advertise that we speak + std::vector supported_protocols; + /// aonnuce that these ranges are reachable via our endpoint + /// only set when we support exit traffic ethertype is supported + std::set owned_ranges; + + /// policies about traffic that we are willing to carry + /// a protocol/range whitelist or blacklist + /// only set when we support exit traffic ethertype + std::optional exit_policy; + + Signature signature; + uint64_t version = llarp::constants::proto_version; + + bool + OtherIsNewer(const IntroSet& other) const { - ServiceInfo addressKeys; - std::vector intros; - PQPubKey sntrupKey; - Tag topic; - std::vector SRVs; - llarp_time_t timestampSignedAt = 0s; + return time_signed < other.time_signed; + } - /// ethertypes we advertise that we speak - std::vector supportedProtocols; - /// aonnuce that these ranges are reachable via our endpoint - /// only set when we support exit traffic ethertype is supported - std::set ownedRanges; + std::string + ToString() const; - /// policies about traffic that we are willing to carry - /// a protocol/range whitelist or blacklist - /// only set when we support exit traffic ethertype - std::optional exitTrafficPolicy; + llarp_time_t + GetNewestIntroExpiration() const; - Signature signature; - uint64_t version = llarp::constants::proto_version; + bool + GetNewestIntro(Introduction& intro) const; - bool - OtherIsNewer(const IntroSet& other) const - { - return timestampSignedAt < other.timestampSignedAt; - } + bool + HasExpiredIntros(llarp_time_t now) const; - std::string - ToString() const; + /// return true if any of our intros expires soon given a delta + bool + HasStaleIntros(llarp_time_t now, llarp_time_t delta) const; - llarp_time_t - GetNewestIntroExpiration() const; + bool + IsExpired(llarp_time_t now) const; - bool - GetNewestIntro(Introduction& intro) const; + std::vector + GetMatchingSRVRecords(std::string_view service_proto) const; - bool - HasExpiredIntros(llarp_time_t now) const; + std::string + bt_encode() const; - /// return true if any of our intros expires soon given a delta - bool - HasStaleIntros(llarp_time_t now, llarp_time_t delta) const; + bool + BDecode(llarp_buffer_t* buf) + { + return bencode_decode_dict(*this, buf); + } - bool - IsExpired(llarp_time_t now) const; + bool + decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf); - std::vector - GetMatchingSRVRecords(std::string_view service_proto) const; + bool + Verify(llarp_time_t now) const; - bool - BEncode(llarp_buffer_t* buf) const; + util::StatusObject + ExtractStatus() const; + }; - bool - BDecode(llarp_buffer_t* buf) - { - return bencode_decode_dict(*this, buf); - } + inline bool + operator<(const IntroSet& lhs, const IntroSet& rhs) + { + return lhs.addressKeys < rhs.addressKeys; + } - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf); + inline bool + operator==(const IntroSet& lhs, const IntroSet& rhs) + { + return std::tie( + lhs.addressKeys, + lhs.intros, + lhs.sntru_pubkey, + lhs.time_signed, + lhs.version, + lhs.topic, + lhs.signature) + == std::tie( + rhs.addressKeys, + rhs.intros, + rhs.sntru_pubkey, + rhs.time_signed, + rhs.version, + rhs.topic, + rhs.signature); + } + + inline bool + operator!=(const IntroSet& lhs, const IntroSet& rhs) + { + return !(lhs == rhs); + } - bool - Verify(llarp_time_t now) const; + /// public version of the introset that is encrypted + struct EncryptedIntroSet + { + using Payload_t = std::vector; - util::StatusObject - ExtractStatus() const; - }; + PubKey derivedSigningKey; + llarp_time_t signedAt = 0s; + Payload_t introsetPayload; + TunnelNonce nounce; + std::optional topic; + Signature sig; - inline bool - operator<(const IntroSet& lhs, const IntroSet& rhs) - { - return lhs.addressKeys < rhs.addressKeys; - } + bool + Sign(const PrivateKey& k); - inline bool - operator==(const IntroSet& lhs, const IntroSet& rhs) - { - return std::tie( - lhs.addressKeys, - lhs.intros, - lhs.sntrupKey, - lhs.timestampSignedAt, - lhs.version, - lhs.topic, - lhs.signature) - == std::tie( - rhs.addressKeys, - rhs.intros, - rhs.sntrupKey, - rhs.timestampSignedAt, - rhs.version, - rhs.topic, - rhs.signature); - } + bool + IsExpired(llarp_time_t now) const; - inline bool - operator!=(const IntroSet& lhs, const IntroSet& rhs) - { - return !(lhs == rhs); - } + bool + BEncode(llarp_buffer_t* buf) const; - /// public version of the introset that is encrypted - struct EncryptedIntroSet + bool + BDecode(llarp_buffer_t* buf) { - using Payload_t = std::vector; - - PubKey derivedSigningKey; - llarp_time_t signedAt = 0s; - Payload_t introsetPayload; - TunnelNonce nounce; - std::optional topic; - Signature sig; - - bool - Sign(const PrivateKey& k); - - bool - IsExpired(llarp_time_t now) const; - - bool - BEncode(llarp_buffer_t* buf) const; - - bool - BDecode(llarp_buffer_t* buf) - { - return bencode_decode_dict(*this, buf); - } + return bencode_decode_dict(*this, buf); + } - bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf); + bool + decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf); - bool - OtherIsNewer(const EncryptedIntroSet& other) const; + bool + OtherIsNewer(const EncryptedIntroSet& other) const; - /// verify signature and timestamp - bool - Verify(llarp_time_t now) const; + /// verify signature and timestamp + bool + Verify(llarp_time_t now) const; - std::string - ToString() const; + std::string + ToString() const; - util::StatusObject - ExtractStatus() const; + util::StatusObject + ExtractStatus() const; - std::optional - MaybeDecrypt(const PubKey& rootKey) const; - }; + std::optional + MaybeDecrypt(const PubKey& rootKey) const; + }; - inline bool - operator<(const EncryptedIntroSet& lhs, const EncryptedIntroSet& rhs) - { - return lhs.derivedSigningKey < rhs.derivedSigningKey; - } + inline bool + operator<(const EncryptedIntroSet& lhs, const EncryptedIntroSet& rhs) + { + return lhs.derivedSigningKey < rhs.derivedSigningKey; + } - inline bool - operator==(const EncryptedIntroSet& lhs, const EncryptedIntroSet& rhs) - { - return std::tie(lhs.signedAt, lhs.derivedSigningKey, lhs.nounce, lhs.sig) - == std::tie(rhs.signedAt, rhs.derivedSigningKey, rhs.nounce, rhs.sig); - } + inline bool + operator==(const EncryptedIntroSet& lhs, const EncryptedIntroSet& rhs) + { + return std::tie(lhs.signedAt, lhs.derivedSigningKey, lhs.nounce, lhs.sig) + == std::tie(rhs.signedAt, rhs.derivedSigningKey, rhs.nounce, rhs.sig); + } - inline bool - operator!=(const EncryptedIntroSet& lhs, const EncryptedIntroSet& rhs) - { - return !(lhs == rhs); - } + inline bool + operator!=(const EncryptedIntroSet& lhs, const EncryptedIntroSet& rhs) + { + return !(lhs == rhs); + } - using EncryptedIntroSetLookupHandler = - std::function&)>; - using IntroSetLookupHandler = std::function&)>; + using EncryptedIntroSetLookupHandler = std::function&)>; + using IntroSetLookupHandler = std::function&)>; - } // namespace service -} // namespace llarp +} // namespace llarp::service template <> constexpr inline bool llarp::IsToStringFormattable = true; diff --git a/llarp/service/outbound_context.cpp b/llarp/service/outbound_context.cpp index 28b4a37af5..a461b88ebd 100644 --- a/llarp/service/outbound_context.cpp +++ b/llarp/service/outbound_context.cpp @@ -13,707 +13,703 @@ #include #include -namespace llarp +namespace llarp::service { - namespace service + bool + OutboundContext::Stop() { - bool - OutboundContext::Stop() - { - markedBad = true; - return path::Builder::Stop(); - } + markedBad = true; + return path::Builder::Stop(); + } - bool - OutboundContext::IsDone(llarp_time_t now) const - { - (void)now; - return AvailablePaths(path::ePathRoleAny) == 0 && ShouldRemove(); - } + bool + OutboundContext::IsDone(llarp_time_t now) const + { + (void)now; + return AvailablePaths(path::ePathRoleAny) == 0 && ShouldRemove(); + } - bool - OutboundContext::ShouldBundleRC() const - { - return m_Endpoint->ShouldBundleRC(); - } + bool + OutboundContext::ShouldBundleRC() const + { + return m_Endpoint->ShouldBundleRC(); + } - bool - OutboundContext::HandleDataDrop(path::Path_ptr p, const PathID_t& dst, uint64_t seq) + bool + OutboundContext::HandleDataDrop(path::Path_ptr p, const PathID_t& dst, uint64_t seq) + { + // pick another intro + if (dst == remoteIntro.path_id && remoteIntro.router == p->Endpoint()) { - // pick another intro - if (dst == remoteIntro.pathID && remoteIntro.router == p->Endpoint()) - { - LogWarn(Name(), " message ", seq, " dropped by endpoint ", p->Endpoint(), " via ", dst); - markedBad = remoteIntro.IsExpired(Now()); - MarkCurrentIntroBad(Now()); - ShiftIntroRouter(p->Endpoint()); - UpdateIntroSet(); - } - return true; + LogWarn(Name(), " message ", seq, " dropped by endpoint ", p->Endpoint(), " via ", dst); + markedBad = remoteIntro.IsExpired(Now()); + MarkCurrentIntroBad(Now()); + ShiftIntroRouter(p->Endpoint()); + UpdateIntroSet(); } + return true; + } - constexpr auto OutboundContextNumPaths = 4; + constexpr auto OutboundContextNumPaths = 4; - OutboundContext::OutboundContext(const IntroSet& introset, Endpoint* parent) - : path::Builder{parent->Router(), OutboundContextNumPaths, parent->numHops} - , SendContext{introset.addressKeys, {}, this, parent} - , location{introset.addressKeys.Addr().ToKey()} - , addr{introset.addressKeys.Addr()} - , currentIntroSet{introset} + OutboundContext::OutboundContext(const IntroSet& introset, Endpoint* parent) + : path::Builder{parent->Router(), OutboundContextNumPaths, parent->numHops} + , SendContext{introset.addressKeys, {}, this, parent} + , location{introset.addressKeys.Addr().ToKey()} + , addr{introset.addressKeys.Addr()} + , currentIntroSet{introset} - { - assert(not introset.intros.empty()); - updatingIntroSet = false; + { + assert(not introset.intros.empty()); + updatingIntroSet = false; - // pick random first intro - auto it = introset.intros.begin(); - if (introset.intros.size() > 1) - { - CSRNG rng{}; - it += std::uniform_int_distribution{0, introset.intros.size() - 1}(rng); - } - m_NextIntro = *it; - currentConvoTag.Randomize(); - lastShift = Now(); - // add send and connect timeouts to the parent endpoints path alignment timeout - // this will make it so that there is less of a chance for timing races - sendTimeout += parent->PathAlignmentTimeout(); - connectTimeout += parent->PathAlignmentTimeout(); + // pick random first intro + auto it = introset.intros.begin(); + if (introset.intros.size() > 1) + { + CSRNG rng{}; + it += std::uniform_int_distribution{0, introset.intros.size() - 1}(rng); } - - OutboundContext::~OutboundContext() = default; - - /// actually swap intros - void - OutboundContext::SwapIntros() + m_NextIntro = *it; + currentConvoTag.Randomize(); + lastShift = Now(); + // add send and connect timeouts to the parent endpoints path alignment timeout + // this will make it so that there is less of a chance for timing races + sendTimeout += parent->PathAlignmentTimeout(); + connectTimeout += parent->PathAlignmentTimeout(); + } + + OutboundContext::~OutboundContext() = default; + + /// actually swap intros + void + OutboundContext::SwapIntros() + { + if (remoteIntro != m_NextIntro) { - if (remoteIntro != m_NextIntro) + remoteIntro = m_NextIntro; + m_DataHandler->PutSenderFor(currentConvoTag, currentIntroSet.addressKeys, false); + m_DataHandler->PutIntroFor(currentConvoTag, remoteIntro); + ShiftIntroRouter(m_NextIntro.router); + // if we have not made a handshake to the remote endpoint do so + if (not IntroGenerated()) { - remoteIntro = m_NextIntro; - m_DataHandler->PutSenderFor(currentConvoTag, currentIntroSet.addressKeys, false); - m_DataHandler->PutIntroFor(currentConvoTag, remoteIntro); - ShiftIntroRouter(m_NextIntro.router); - // if we have not made a handshake to the remote endpoint do so - if (not IntroGenerated()) - { - KeepAlive(); - } + KeepAlive(); } } + } - Address - OutboundContext::Addr() const - { - return addr; - } - - bool - OutboundContext::OnIntroSetUpdate( - const Address&, - std::optional foundIntro, - const RouterID& endpoint, - llarp_time_t, - uint64_t relayOrder) + Address + OutboundContext::Addr() const + { + return addr; + } + + bool + OutboundContext::OnIntroSetUpdate( + const Address&, + std::optional foundIntro, + const RouterID& endpoint, + llarp_time_t, + uint64_t relayOrder) + { + if (markedBad) + return true; + updatingIntroSet = false; + if (foundIntro) { - if (markedBad) + if (foundIntro->time_signed == 0s) + { + LogWarn(Name(), " got introset with zero timestamp: ", *foundIntro); return true; - updatingIntroSet = false; - if (foundIntro) + } + if (currentIntroSet.time_signed > foundIntro->time_signed) { - if (foundIntro->timestampSignedAt == 0s) - { - LogWarn(Name(), " got introset with zero timestamp: ", *foundIntro); - return true; - } - if (currentIntroSet.timestampSignedAt > foundIntro->timestampSignedAt) - { - LogInfo("introset is old, dropping"); - return true; - } - - const llarp_time_t now = Now(); - if (foundIntro->IsExpired(now)) - { - LogError("got expired introset from lookup from ", endpoint); - return true; - } - currentIntroSet = *foundIntro; - ShiftIntroRouter(RouterID{}); + LogInfo("introset is old, dropping"); + return true; } - else if (relayOrder > 0) + + const llarp_time_t now = Now(); + if (foundIntro->IsExpired(now)) { - ++m_LookupFails; - LogWarn(Name(), " failed to look up introset, fails=", m_LookupFails); + LogError("got expired introset from lookup from ", endpoint); + return true; } - return true; + currentIntroSet = *foundIntro; + ShiftIntroRouter(RouterID{}); } - - bool - OutboundContext::ReadyToSend() const + else if (relayOrder > 0) { - if (markedBad) - return false; - if (remoteIntro.router.IsZero()) - return false; - return IntroSent() and GetPathByRouter(remoteIntro.router); + ++m_LookupFails; + LogWarn(Name(), " failed to look up introset, fails=", m_LookupFails); } + return true; + } + + bool + OutboundContext::ReadyToSend() const + { + if (markedBad) + return false; + if (remoteIntro.router.IsZero()) + return false; + return IntroSent() and GetPathByRouter(remoteIntro.router); + } - void - OutboundContext::ShiftIntroRouter(const RouterID r) + void + OutboundContext::ShiftIntroRouter(const RouterID r) + { + const auto now = Now(); + Introduction selectedIntro{}; + for (const auto& intro : currentIntroSet.intros) { - const auto now = Now(); - Introduction selectedIntro{}; - for (const auto& intro : currentIntroSet.intros) + if (intro.expiry > selectedIntro.expiry and intro.router != r) { - if (intro.expiresAt > selectedIntro.expiresAt and intro.router != r) - { - selectedIntro = intro; - } + selectedIntro = intro; } - if (selectedIntro.router.IsZero() || selectedIntro.ExpiresSoon(now)) - return; - m_NextIntro = selectedIntro; - lastShift = now; } + if (selectedIntro.router.IsZero() || selectedIntro.ExpiresSoon(now)) + return; + m_NextIntro = selectedIntro; + lastShift = now; + } + + void + OutboundContext::HandlePathBuildTimeout(path::Path_ptr p) + { + ShiftIntroRouter(p->Endpoint()); + path::Builder::HandlePathBuildTimeout(p); + } - void - OutboundContext::HandlePathBuildTimeout(path::Path_ptr p) + void + OutboundContext::HandlePathBuildFailedAt(path::Path_ptr p, RouterID hop) + { + if (p->Endpoint() == hop) { + // shift intro when we fail at the pivot ShiftIntroRouter(p->Endpoint()); - path::Builder::HandlePathBuildTimeout(p); } + path::Builder::HandlePathBuildFailedAt(p, hop); + } - void - OutboundContext::HandlePathBuildFailedAt(path::Path_ptr p, RouterID hop) + void + OutboundContext::HandlePathBuilt(path::Path_ptr p) + { + path::Builder::HandlePathBuilt(p); + p->SetDataHandler([self = weak_from_this()](auto path, auto frame) { + if (auto ptr = self.lock()) + return ptr->HandleHiddenServiceFrame(path, frame); + return false; + }); + p->SetDropHandler([self = weak_from_this()](auto path, auto id, auto seqno) { + if (auto ptr = self.lock()) + return ptr->HandleDataDrop(path, id, seqno); + return false; + }); + if (markedBad) { - if (p->Endpoint() == hop) - { - // shift intro when we fail at the pivot - ShiftIntroRouter(p->Endpoint()); - } - path::Builder::HandlePathBuildFailedAt(p, hop); + // ignore new path if we are marked dead + LogInfo(Name(), " marked bad, ignoring new path"); + p->EnterState(path::ePathIgnore, Now()); } - - void - OutboundContext::HandlePathBuilt(path::Path_ptr p) + else if (p->Endpoint() == m_NextIntro.router) { - path::Builder::HandlePathBuilt(p); - p->SetDataHandler([self = weak_from_this()](auto path, auto frame) { - if (auto ptr = self.lock()) - return ptr->HandleHiddenServiceFrame(path, frame); - return false; - }); - p->SetDropHandler([self = weak_from_this()](auto path, auto id, auto seqno) { - if (auto ptr = self.lock()) - return ptr->HandleDataDrop(path, id, seqno); - return false; - }); - if (markedBad) - { - // ignore new path if we are marked dead - LogInfo(Name(), " marked bad, ignoring new path"); - p->EnterState(path::ePathIgnore, Now()); - } - else if (p->Endpoint() == m_NextIntro.router) - { - // we now have a path to the next intro, swap intros - SwapIntros(); - } + // we now have a path to the next intro, swap intros + SwapIntros(); } + } - void - OutboundContext::AsyncGenIntro(const llarp_buffer_t& payload, ProtocolType t) + void + OutboundContext::AsyncGenIntro(const llarp_buffer_t& payload, ProtocolType t) + { + if (generatedIntro) { - if (generatedIntro) - { - LogWarn(Name(), " dropping packet as we are not fully handshaked right now"); - return; - } - if (remoteIntro.router.IsZero()) - { - LogWarn(Name(), " dropping intro frame we have no intro ready yet"); - return; - } + LogWarn(Name(), " dropping packet as we are not fully handshaked right now"); + return; + } + if (remoteIntro.router.IsZero()) + { + LogWarn(Name(), " dropping intro frame we have no intro ready yet"); + return; + } - auto path = GetPathByRouter(remoteIntro.router); - if (path == nullptr) - { - LogError(Name(), " has no path to ", remoteIntro.router, " when we should have had one"); + auto path = GetPathByRouter(remoteIntro.router); + if (path == nullptr) + { + LogError(Name(), " has no path to ", remoteIntro.router, " when we should have had one"); + return; + } + auto frame = std::make_shared(); + frame->clear(); + auto ex = std::make_shared( + m_Endpoint->Loop(), + remoteIdent, + m_Endpoint->GetIdentity(), + currentIntroSet.sntru_pubkey, + remoteIntro, + m_DataHandler, + currentConvoTag, + t); + + ex->hook = [self = shared_from_this(), path](auto frame) { + if (not self->Send(std::move(frame), path)) return; - } - auto frame = std::make_shared(); - frame->Clear(); - auto ex = std::make_shared( - m_Endpoint->Loop(), - remoteIdent, - m_Endpoint->GetIdentity(), - currentIntroSet.sntrupKey, - remoteIntro, - m_DataHandler, - currentConvoTag, - t); - - ex->hook = [self = shared_from_this(), path](auto frame) { - if (not self->Send(std::move(frame), path)) - return; - self->m_Endpoint->Loop()->call_later( - self->remoteIntro.latency, [self]() { self->sentIntro = true; }); - }; - - ex->msg.PutBuffer(payload); - ex->msg.introReply = path->intro; - frame->F = ex->msg.introReply.pathID; - frame->R = 0; - generatedIntro = true; - // ensure we have a sender put for this convo tag - m_DataHandler->PutSenderFor(currentConvoTag, currentIntroSet.addressKeys, false); - // encrypt frame async - m_Endpoint->Router()->QueueWork([ex, frame] { return AsyncKeyExchange::Encrypt(ex, frame); }); + self->m_Endpoint->Loop()->call_later( + self->remoteIntro.latency, [self]() { self->sentIntro = true; }); + }; + + ex->msg.PutBuffer(payload); + ex->msg.introReply = path->intro; + frame->path_id = ex->msg.introReply.path_id; + frame->flag = 0; + generatedIntro = true; + // ensure we have a sender put for this convo tag + m_DataHandler->PutSenderFor(currentConvoTag, currentIntroSet.addressKeys, false); + // encrypt frame async + m_Endpoint->Router()->QueueWork([ex, frame] { return AsyncKeyExchange::Encrypt(ex, frame); }); + + LogInfo(Name(), " send intro frame T=", currentConvoTag); + } + + std::string + OutboundContext::Name() const + { + return "OBContext:" + currentIntroSet.addressKeys.Addr().ToString(); + } - LogInfo(Name(), " send intro frame T=", currentConvoTag); + void + OutboundContext::UpdateIntroSet() + { + constexpr auto IntrosetUpdateInterval = 10s; + const auto now = Now(); + if (updatingIntroSet or markedBad or now < m_LastIntrosetUpdateAt + IntrosetUpdateInterval) + return; + LogInfo(Name(), " updating introset"); + m_LastIntrosetUpdateAt = now; + // we want to use the parent endpoint's paths because outbound context + // does not implement path::PathSet::HandleGotIntroMessage + const auto paths = GetManyPathsWithUniqueEndpoints(m_Endpoint, 2, location); + uint64_t relayOrder = 0; + for (const auto& path : paths) + { + HiddenServiceAddressLookup* job = new HiddenServiceAddressLookup( + m_Endpoint, + util::memFn(&OutboundContext::OnIntroSetUpdate, shared_from_this()), + location, + PubKey{addr.as_array()}, + path->Endpoint(), + relayOrder, + m_Endpoint->GenTXID(), + (IntrosetUpdateInterval / 2) + (2 * path->intro.latency) + IntrosetLookupGraceInterval); + relayOrder++; + if (job->SendRequestViaPath(path, m_Endpoint->Router())) + updatingIntroSet = true; } + } - std::string - OutboundContext::Name() const + util::StatusObject + OutboundContext::ExtractStatus() const + { + auto obj = path::Builder::ExtractStatus(); + obj["estimatedRTT"] = to_json(estimatedRTT); + obj["currentConvoTag"] = currentConvoTag.ToHex(); + obj["remoteIntro"] = remoteIntro.ExtractStatus(); + obj["sessionCreatedAt"] = to_json(createdAt); + obj["lastGoodSend"] = to_json(lastGoodSend); + obj["lastRecv"] = to_json(m_LastInboundTraffic); + obj["lastIntrosetUpdate"] = to_json(m_LastIntrosetUpdateAt); + obj["seqno"] = sequenceNo; + obj["markedBad"] = markedBad; + obj["lastShift"] = to_json(lastShift); + obj["remoteIdentity"] = addr.ToString(); + obj["currentRemoteIntroset"] = currentIntroSet.ExtractStatus(); + obj["nextIntro"] = m_NextIntro.ExtractStatus(); + obj["readyToSend"] = ReadyToSend(); + return obj; + } + + void + OutboundContext::KeepAlive() + { + std::array tmp; + llarp_buffer_t buf{tmp}; + CryptoManager::instance()->randomize(buf); + SendPacketToRemote(buf, ProtocolType::Control); + m_LastKeepAliveAt = Now(); + } + + bool + OutboundContext::Pump(llarp_time_t now) + { + if (ReadyToSend() and remoteIntro.router.IsZero()) { - return "OBContext:" + currentIntroSet.addressKeys.Addr().ToString(); + SwapIntros(); } - - void - OutboundContext::UpdateIntroSet() + if (ReadyToSend()) { - constexpr auto IntrosetUpdateInterval = 10s; - const auto now = Now(); - if (updatingIntroSet or markedBad or now < m_LastIntrosetUpdateAt + IntrosetUpdateInterval) - return; - LogInfo(Name(), " updating introset"); - m_LastIntrosetUpdateAt = now; - // we want to use the parent endpoint's paths because outbound context - // does not implement path::PathSet::HandleGotIntroMessage - const auto paths = GetManyPathsWithUniqueEndpoints(m_Endpoint, 2, location); - uint64_t relayOrder = 0; - for (const auto& path : paths) + // if we dont have a cached session key after sending intro we are in a fugged state so + // expunge + SharedSecret discardme; + if (not m_DataHandler->GetCachedSessionKeyFor(currentConvoTag, discardme)) { - HiddenServiceAddressLookup* job = new HiddenServiceAddressLookup( - m_Endpoint, - util::memFn(&OutboundContext::OnIntroSetUpdate, shared_from_this()), - location, - PubKey{addr.as_array()}, - path->Endpoint(), - relayOrder, - m_Endpoint->GenTXID(), - (IntrosetUpdateInterval / 2) + (2 * path->intro.latency) + IntrosetLookupGraceInterval); - relayOrder++; - if (job->SendRequestViaPath(path, m_Endpoint->Router())) - updatingIntroSet = true; + LogError(Name(), " no cached key after sending intro, we are in a fugged state, oh no"); + return true; } } - util::StatusObject - OutboundContext::ExtractStatus() const + if (m_GotInboundTraffic and m_LastInboundTraffic + sendTimeout <= now) { - auto obj = path::Builder::ExtractStatus(); - obj["estimatedRTT"] = to_json(estimatedRTT); - obj["currentConvoTag"] = currentConvoTag.ToHex(); - obj["remoteIntro"] = remoteIntro.ExtractStatus(); - obj["sessionCreatedAt"] = to_json(createdAt); - obj["lastGoodSend"] = to_json(lastGoodSend); - obj["lastRecv"] = to_json(m_LastInboundTraffic); - obj["lastIntrosetUpdate"] = to_json(m_LastIntrosetUpdateAt); - obj["seqno"] = sequenceNo; - obj["markedBad"] = markedBad; - obj["lastShift"] = to_json(lastShift); - obj["remoteIdentity"] = addr.ToString(); - obj["currentRemoteIntroset"] = currentIntroSet.ExtractStatus(); - obj["nextIntro"] = m_NextIntro.ExtractStatus(); - obj["readyToSend"] = ReadyToSend(); - return obj; + // timeout on other side + UpdateIntroSet(); + MarkCurrentIntroBad(now); + ShiftIntroRouter(remoteIntro.router); } - - void - OutboundContext::KeepAlive() + // check for stale intros + // update the introset if we think we need to + if (currentIntroSet.HasStaleIntros(now, path::intro_path_spread) + or remoteIntro.ExpiresSoon(now, path::intro_path_spread)) { - std::array tmp; - llarp_buffer_t buf{tmp}; - CryptoManager::instance()->randomize(buf); - SendPacketToRemote(buf, ProtocolType::Control); - m_LastKeepAliveAt = Now(); + UpdateIntroSet(); + ShiftIntroduction(false); } - bool - OutboundContext::Pump(llarp_time_t now) + if (ReadyToSend()) { - if (ReadyToSend() and remoteIntro.router.IsZero()) + if (not remoteIntro.router.IsZero() and not GetPathByRouter(remoteIntro.router)) { - SwapIntros(); - } - if (ReadyToSend()) - { - // if we dont have a cached session key after sending intro we are in a fugged state so - // expunge - SharedSecret discardme; - if (not m_DataHandler->GetCachedSessionKeyFor(currentConvoTag, discardme)) - { - LogError(Name(), " no cached key after sending intro, we are in a fugged state, oh no"); - return true; - } - } - - if (m_GotInboundTraffic and m_LastInboundTraffic + sendTimeout <= now) - { - // timeout on other side - UpdateIntroSet(); - MarkCurrentIntroBad(now); - ShiftIntroRouter(remoteIntro.router); - } - // check for stale intros - // update the introset if we think we need to - if (currentIntroSet.HasStaleIntros(now, path::intro_path_spread) - or remoteIntro.ExpiresSoon(now, path::intro_path_spread)) - { - UpdateIntroSet(); - ShiftIntroduction(false); - } - - if (ReadyToSend()) - { - if (not remoteIntro.router.IsZero() and not GetPathByRouter(remoteIntro.router)) - { - // pick another good intro if we have no path on our current intro - std::vector otherIntros; - ForEachPath([now, router = remoteIntro.router, &otherIntros](auto path) { - if (path and path->IsReady() and path->Endpoint() != router - and not path->ExpiresSoon(now, path::intro_path_spread)) - { - otherIntros.emplace_back(path->intro); - } - }); - if (not otherIntros.empty()) + // pick another good intro if we have no path on our current intro + std::vector otherIntros; + ForEachPath([now, router = remoteIntro.router, &otherIntros](auto path) { + if (path and path->IsReady() and path->Endpoint() != router + and not path->ExpiresSoon(now, path::intro_path_spread)) { - std::shuffle(otherIntros.begin(), otherIntros.end(), CSRNG{}); - remoteIntro = otherIntros[0]; + otherIntros.emplace_back(path->intro); } - } - } - // lookup router in intro if set and unknown - if (not m_NextIntro.router.IsZero()) - m_Endpoint->EnsureRouterIsKnown(m_NextIntro.router); - - if (ReadyToSend() and not m_ReadyHooks.empty()) - { - const auto path = GetPathByRouter(remoteIntro.router); - if (not path) - { - LogWarn(Name(), " ready but no path to ", remoteIntro.router, " ???"); - return true; - } - for (const auto& hook : m_ReadyHooks) - hook(this); - m_ReadyHooks.clear(); - } - - const auto timeout = std::max(lastGoodSend, m_LastInboundTraffic); - if (lastGoodSend > 0s and now >= timeout + (sendTimeout / 2)) - { - // send a keep alive to keep this session alive - KeepAlive(); - if (markedBad) + }); + if (not otherIntros.empty()) { - LogWarn(Name(), " keepalive timeout hit"); - return true; + std::shuffle(otherIntros.begin(), otherIntros.end(), CSRNG{}); + remoteIntro = otherIntros[0]; } } + } + // lookup router in intro if set and unknown + if (not m_NextIntro.router.IsZero()) + m_Endpoint->EnsureRouterIsKnown(m_NextIntro.router); - // check for half open state where we can send but we get nothing back - if (m_LastInboundTraffic == 0s and now - createdAt > connectTimeout) - { - LogWarn(Name(), " half open state, we can send but we got nothing back"); - return true; - } - // if we are dead return true so we are removed - const bool removeIt = timeout > 0s ? (now >= timeout && now - timeout > sendTimeout) - : (now >= createdAt && now - createdAt > connectTimeout); - if (removeIt) + if (ReadyToSend() and not m_ReadyHooks.empty()) + { + const auto path = GetPathByRouter(remoteIntro.router); + if (not path) { - LogInfo(Name(), " session is stale"); + LogWarn(Name(), " ready but no path to ", remoteIntro.router, " ???"); return true; } - return false; + for (const auto& hook : m_ReadyHooks) + hook(this); + m_ReadyHooks.clear(); } - void - OutboundContext::AddReadyHook(std::function hook, llarp_time_t timeout) + const auto timeout = std::max(lastGoodSend, m_LastInboundTraffic); + if (lastGoodSend > 0s and now >= timeout + (sendTimeout / 2)) { - if (ReadyToSend()) - { - hook(this); - return; - } - if (m_ReadyHooks.empty()) + // send a keep alive to keep this session alive + KeepAlive(); + if (markedBad) { - m_router->loop()->call_later(timeout, [this]() { - LogWarn(Name(), " did not obtain session in time"); - for (const auto& hook : m_ReadyHooks) - hook(nullptr); - m_ReadyHooks.clear(); - }); + LogWarn(Name(), " keepalive timeout hit"); + return true; } - m_ReadyHooks.push_back(hook); } - std::optional> - OutboundContext::GetHopsForBuild() + // check for half open state where we can send but we get nothing back + if (m_LastInboundTraffic == 0s and now - createdAt > connectTimeout) { - if (m_NextIntro.router.IsZero()) - { - ShiftIntroduction(false); - } - if (m_NextIntro.router.IsZero()) - return std::nullopt; - return GetHopsAlignedToForBuild(m_NextIntro.router, m_Endpoint->SnodeBlacklist()); + LogWarn(Name(), " half open state, we can send but we got nothing back"); + return true; } - - bool - OutboundContext::ShouldBuildMore(llarp_time_t now) const + // if we are dead return true so we are removed + const bool removeIt = timeout > 0s ? (now >= timeout && now - timeout > sendTimeout) + : (now >= createdAt && now - createdAt > connectTimeout); + if (removeIt) { - if (markedBad or path::Builder::BuildCooldownHit(now)) - return false; - - if (NumInStatus(path::ePathBuilding) >= std::max(numDesiredPaths / size_t{2}, size_t{1})) - return false; + LogInfo(Name(), " session is stale"); + return true; + } + return false; + } - size_t numValidPaths = 0; - bool havePathToNextIntro = false; - ForEachPath([now, this, &havePathToNextIntro, &numValidPaths](path::Path_ptr path) { - if (not path->IsReady()) - return; - if (not path->intro.ExpiresSoon(now, path::default_lifetime - path::intro_path_spread)) - { - numValidPaths++; - if (path->intro.router == m_NextIntro.router) - havePathToNextIntro = true; - } + void + OutboundContext::AddReadyHook(std::function hook, llarp_time_t timeout) + { + if (ReadyToSend()) + { + hook(this); + return; + } + if (m_ReadyHooks.empty()) + { + m_router->loop()->call_later(timeout, [this]() { + LogWarn(Name(), " did not obtain session in time"); + for (const auto& hook : m_ReadyHooks) + hook(nullptr); + m_ReadyHooks.clear(); }); - return numValidPaths < numDesiredPaths or not havePathToNextIntro; } + m_ReadyHooks.push_back(hook); + } - void - OutboundContext::MarkCurrentIntroBad(llarp_time_t now) + std::optional> + OutboundContext::GetHopsForBuild() + { + if (m_NextIntro.router.IsZero()) { - MarkIntroBad(remoteIntro, now); + ShiftIntroduction(false); } + if (m_NextIntro.router.IsZero()) + return std::nullopt; + return GetHopsAlignedToForBuild(m_NextIntro.router, m_Endpoint->SnodeBlacklist()); + } + + bool + OutboundContext::ShouldBuildMore(llarp_time_t now) const + { + if (markedBad or path::Builder::BuildCooldownHit(now)) + return false; - void - OutboundContext::MarkIntroBad(const Introduction&, llarp_time_t) - {} + if (NumInStatus(path::ePathBuilding) >= std::max(numDesiredPaths / size_t{2}, size_t{1})) + return false; - bool - OutboundContext::IntroSent() const - { - return sentIntro; - } + size_t numValidPaths = 0; + bool havePathToNextIntro = false; + ForEachPath([now, this, &havePathToNextIntro, &numValidPaths](path::Path_ptr path) { + if (not path->IsReady()) + return; + if (not path->intro.ExpiresSoon(now, path::default_lifetime - path::intro_path_spread)) + { + numValidPaths++; + if (path->intro.router == m_NextIntro.router) + havePathToNextIntro = true; + } + }); + return numValidPaths < numDesiredPaths or not havePathToNextIntro; + } - bool - OutboundContext::IntroGenerated() const + void + OutboundContext::MarkCurrentIntroBad(llarp_time_t now) + { + MarkIntroBad(remoteIntro, now); + } + + void + OutboundContext::MarkIntroBad(const Introduction&, llarp_time_t) + {} + + bool + OutboundContext::IntroSent() const + { + return sentIntro; + } + + bool + OutboundContext::IntroGenerated() const + { + return generatedIntro; + } + + bool + OutboundContext::ShiftIntroduction(bool rebuild) + { + bool success = false; + const auto now = Now(); + if (abs(now - lastShift) < shiftTimeout) + return false; + bool shifted = false; + std::vector intros = currentIntroSet.intros; + if (intros.size() > 1) { - return generatedIntro; + std::shuffle(intros.begin(), intros.end(), CSRNG{}); } - bool - OutboundContext::ShiftIntroduction(bool rebuild) + // to find a intro on the same router as before that is newer + for (const auto& intro : intros) { - bool success = false; - const auto now = Now(); - if (abs(now - lastShift) < shiftTimeout) - return false; - bool shifted = false; - std::vector intros = currentIntroSet.intros; - if (intros.size() > 1) + if (intro.ExpiresSoon(now)) + continue; + if (m_Endpoint->SnodeBlacklist().count(intro.router)) + continue; + if (remoteIntro.router == intro.router) { - std::shuffle(intros.begin(), intros.end(), CSRNG{}); + if (intro.expiry > m_NextIntro.expiry) + { + success = true; + m_NextIntro = intro; + } } - - // to find a intro on the same router as before that is newer + } + if (!success) + { + /// pick newer intro not on same router for (const auto& intro : intros) { - if (intro.ExpiresSoon(now)) - continue; if (m_Endpoint->SnodeBlacklist().count(intro.router)) continue; - if (remoteIntro.router == intro.router) + m_Endpoint->EnsureRouterIsKnown(intro.router); + if (intro.ExpiresSoon(now)) + continue; + if (m_NextIntro != intro) { - if (intro.expiresAt > m_NextIntro.expiresAt) + if (intro.expiry > m_NextIntro.expiry) { - success = true; + shifted = intro.router != m_NextIntro.router; m_NextIntro = intro; + success = true; } } } - if (!success) - { - /// pick newer intro not on same router - for (const auto& intro : intros) - { - if (m_Endpoint->SnodeBlacklist().count(intro.router)) - continue; - m_Endpoint->EnsureRouterIsKnown(intro.router); - if (intro.ExpiresSoon(now)) - continue; - if (m_NextIntro != intro) - { - if (intro.expiresAt > m_NextIntro.expiresAt) - { - shifted = intro.router != m_NextIntro.router; - m_NextIntro = intro; - success = true; - } - } - } - } - if (m_NextIntro.router.IsZero()) - return false; - if (shifted) - lastShift = now; - if (rebuild && !BuildCooldownHit(Now())) - BuildOneAlignedTo(m_NextIntro.router); - return success; } + if (m_NextIntro.router.IsZero()) + return false; + if (shifted) + lastShift = now; + if (rebuild && !BuildCooldownHit(Now())) + BuildOneAlignedTo(m_NextIntro.router); + return success; + } - void - OutboundContext::HandlePathDied(path::Path_ptr path) + void + OutboundContext::HandlePathDied(path::Path_ptr path) + { + // unconditionally update introset + UpdateIntroSet(); + const RouterID endpoint{path->Endpoint()}; + // if a path to our current intro died... + if (endpoint == remoteIntro.router) { - // unconditionally update introset - UpdateIntroSet(); - const RouterID endpoint{path->Endpoint()}; - // if a path to our current intro died... - if (endpoint == remoteIntro.router) + // figure out how many paths to this router we have + size_t num = 0; + ForEachPath([&](const path::Path_ptr& p) { + if (p->Endpoint() == endpoint && p->IsReady()) + ++num; + }); + if (num == 0) { - // figure out how many paths to this router we have - size_t num = 0; - ForEachPath([&](const path::Path_ptr& p) { - if (p->Endpoint() == endpoint && p->IsReady()) - ++num; - }); - if (num == 0) - { - // we have no more paths to this endpoint so we want to pivot off of it - MarkCurrentIntroBad(Now()); - ShiftIntroRouter(endpoint); - if (m_NextIntro.router != endpoint) - BuildOneAlignedTo(m_NextIntro.router); - } + // we have no more paths to this endpoint so we want to pivot off of it + MarkCurrentIntroBad(Now()); + ShiftIntroRouter(endpoint); + if (m_NextIntro.router != endpoint) + BuildOneAlignedTo(m_NextIntro.router); } } + } - bool - OutboundContext::ShouldKeepAlive(llarp_time_t now) const + bool + OutboundContext::ShouldKeepAlive(llarp_time_t now) const + { + const auto SendKeepAliveInterval = sendTimeout / 2; + if (not m_GotInboundTraffic) + return false; + if (m_LastInboundTraffic == 0s) + return false; + return (now - m_LastKeepAliveAt) >= SendKeepAliveInterval; + } + + void + OutboundContext::Tick(llarp_time_t now) + { + path::Builder::Tick(now); + if (ShouldKeepAlive(now)) + KeepAlive(); + } + + bool + OutboundContext::HandleHiddenServiceFrame(path::Path_ptr p, const ProtocolFrameMessage& frame) + { + m_LastInboundTraffic = m_Endpoint->Now(); + m_GotInboundTraffic = true; + if (frame.flag) { - const auto SendKeepAliveInterval = sendTimeout / 2; - if (not m_GotInboundTraffic) + // handle discard + ServiceInfo si; + if (!m_Endpoint->GetSenderFor(frame.convo_tag, si)) + { + LogWarn("no sender for T=", frame.convo_tag); return false; - if (m_LastInboundTraffic == 0s) + } + // verify source + if (!frame.Verify(si)) + { + LogWarn("signature verification failed, T=", frame.convo_tag); return false; - return (now - m_LastKeepAliveAt) >= SendKeepAliveInterval; - } - - void - OutboundContext::Tick(llarp_time_t now) - { - path::Builder::Tick(now); - if (ShouldKeepAlive(now)) - KeepAlive(); - } + } + // remove convotag it doesn't exist + LogWarn("remove convotag T=", frame.convo_tag, " R=", frame.flag); - bool - OutboundContext::HandleHiddenServiceFrame(path::Path_ptr p, const ProtocolFrame& frame) - { - m_LastInboundTraffic = m_Endpoint->Now(); - m_GotInboundTraffic = true; - if (frame.R) + AuthResult result{AuthResultCode::eAuthFailed, "unknown reason"}; + if (const auto maybe = AuthResultCodeFromInt(frame.flag)) + result.code = *maybe; + SharedSecret sessionKey{}; + if (m_DataHandler->GetCachedSessionKeyFor(frame.convo_tag, sessionKey)) { - // handle discard - ServiceInfo si; - if (!m_Endpoint->GetSenderFor(frame.T, si)) + ProtocolMessage msg{}; + if (frame.DecryptPayloadInto(sessionKey, msg)) { - LogWarn("no sender for T=", frame.T); - return false; - } - // verify source - if (!frame.Verify(si)) - { - LogWarn("signature verification failed, T=", frame.T); - return false; - } - // remove convotag it doesn't exist - LogWarn("remove convotag T=", frame.T, " R=", frame.R); - - AuthResult result{AuthResultCode::eAuthFailed, "unknown reason"}; - if (const auto maybe = AuthResultCodeFromInt(frame.R)) - result.code = *maybe; - SharedSecret sessionKey{}; - if (m_DataHandler->GetCachedSessionKeyFor(frame.T, sessionKey)) - { - ProtocolMessage msg{}; - if (frame.DecryptPayloadInto(sessionKey, msg)) + if (msg.proto == ProtocolType::Auth and not msg.payload.empty()) { - if (msg.proto == ProtocolType::Auth and not msg.payload.empty()) - { - result.reason = std::string{ - reinterpret_cast(msg.payload.data()), msg.payload.size()}; - } + result.reason = + std::string{reinterpret_cast(msg.payload.data()), msg.payload.size()}; } } - - m_Endpoint->RemoveConvoTag(frame.T); - if (authResultListener) - { - authResultListener(result); - authResultListener = nullptr; - } - return true; } - std::function)> hook = nullptr; + + m_Endpoint->RemoveConvoTag(frame.convo_tag); if (authResultListener) { - std::function handler = authResultListener; + authResultListener(result); authResultListener = nullptr; - hook = [handler](std::shared_ptr msg) { - AuthResult result{AuthResultCode::eAuthAccepted, "OK"}; - if (msg->proto == ProtocolType::Auth and not msg->payload.empty()) - { - result.reason = std::string{ - reinterpret_cast(msg->payload.data()), msg->payload.size()}; - } - handler(result); - }; } - const auto& ident = m_Endpoint->GetIdentity(); - if (not frame.AsyncDecryptAndVerify(m_Endpoint->Loop(), p, ident, m_Endpoint, hook)) - { - // send reset convo tag message - LogError("failed to decrypt and verify frame"); - ProtocolFrame f; - f.R = 1; - f.T = frame.T; - f.F = p->intro.pathID; - - f.Sign(ident); + return true; + } + std::function)> hook = nullptr; + if (authResultListener) + { + std::function handler = authResultListener; + authResultListener = nullptr; + hook = [handler](std::shared_ptr msg) { + AuthResult result{AuthResultCode::eAuthAccepted, "OK"}; + if (msg->proto == ProtocolType::Auth and not msg->payload.empty()) { - LogWarn("invalidating convotag T=", frame.T); - m_Endpoint->RemoveConvoTag(frame.T); - m_Endpoint->m_SendQueue.tryPushBack( - SendEvent_t{std::make_shared(f, frame.F), p}); + result.reason = + std::string{reinterpret_cast(msg->payload.data()), msg->payload.size()}; } - } - return true; + handler(result); + }; } - - void - OutboundContext::SendPacketToRemote(const llarp_buffer_t& buf, service::ProtocolType t) + const auto& ident = m_Endpoint->GetIdentity(); + if (not frame.AsyncDecryptAndVerify(m_Endpoint->Loop(), p, ident, m_Endpoint, hook)) { - AsyncEncryptAndSendTo(buf, t); + // send reset convo tag message + LogError("failed to decrypt and verify frame"); + ProtocolFrameMessage f; + f.flag = 1; + f.convo_tag = frame.convo_tag; + f.path_id = p->intro.path_id; + + f.Sign(ident); + { + LogWarn("invalidating convotag T=", frame.convo_tag); + m_Endpoint->RemoveConvoTag(frame.convo_tag); + m_Endpoint->m_SendQueue.tryPushBack( + SendEvent_t{std::make_shared(f, frame.path_id), p}); + } } + return true; + } - } // namespace service + void + OutboundContext::SendPacketToRemote(const llarp_buffer_t& buf, service::ProtocolType t) + { + AsyncEncryptAndSendTo(buf, t); + } -} // namespace llarp +} // namespace llarp::service diff --git a/llarp/service/outbound_context.hpp b/llarp/service/outbound_context.hpp index b005bcd19a..8073487823 100644 --- a/llarp/service/outbound_context.hpp +++ b/llarp/service/outbound_context.hpp @@ -124,7 +124,7 @@ namespace llarp GetHopsForBuild() override; bool - HandleHiddenServiceFrame(path::Path_ptr p, const ProtocolFrame& frame); + HandleHiddenServiceFrame(path::Path_ptr p, const ProtocolFrameMessage& frame); std::string Name() const override; diff --git a/llarp/service/protocol.cpp b/llarp/service/protocol.cpp index 96bfd9b122..d9abccc851 100644 --- a/llarp/service/protocol.cpp +++ b/llarp/service/protocol.cpp @@ -8,526 +8,509 @@ #include #include -namespace llarp +namespace llarp::service { - namespace service + ProtocolMessage::ProtocolMessage() { - ProtocolMessage::ProtocolMessage() - { - tag.Zero(); - } + tag.Zero(); + } - ProtocolMessage::ProtocolMessage(const ConvoTag& t) : tag(t) - {} + ProtocolMessage::ProtocolMessage(const ConvoTag& t) : tag(t) + {} - ProtocolMessage::~ProtocolMessage() = default; + ProtocolMessage::~ProtocolMessage() = default; - void - ProtocolMessage::PutBuffer(const llarp_buffer_t& buf) - { - payload.resize(buf.sz); - memcpy(payload.data(), buf.base, buf.sz); - } + void + ProtocolMessage::PutBuffer(const llarp_buffer_t& buf) + { + payload.resize(buf.sz); + memcpy(payload.data(), buf.base, buf.sz); + } - void - ProtocolMessage::ProcessAsync( - path::Path_ptr path, PathID_t from, std::shared_ptr self) - { - if (!self->handler->HandleDataMessage(path, from, self)) - LogWarn("failed to handle data message from ", path->Name()); - } + void + ProtocolMessage::ProcessAsync( + path::Path_ptr path, PathID_t from, std::shared_ptr self) + { + if (!self->handler->HandleDataMessage(path, from, self)) + LogWarn("failed to handle data message from ", path->Name()); + } - bool - ProtocolMessage::DecodeKey(const llarp_buffer_t& k, llarp_buffer_t* buf) + bool + ProtocolMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) + { + bool read = false; + if (!BEncodeMaybeReadDictInt("a", proto, read, k, buf)) + return false; + if (k.startswith("d")) { - bool read = false; - if (!BEncodeMaybeReadDictInt("a", proto, read, k, buf)) - return false; - if (k.startswith("d")) - { - llarp_buffer_t strbuf; - if (!bencode_read_string(buf, &strbuf)) - return false; - PutBuffer(strbuf); - return true; - } - if (!BEncodeMaybeReadDictEntry("i", introReply, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("n", seqno, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("s", sender, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("t", tag, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("v", version, read, k, buf)) + llarp_buffer_t strbuf; + if (!bencode_read_string(buf, &strbuf)) return false; - return read; + PutBuffer(strbuf); + return true; } + if (!BEncodeMaybeReadDictEntry("i", introReply, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictInt("n", seqno, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictEntry("s", sender, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictEntry("t", tag, read, k, buf)) + return false; + if (!BEncodeMaybeReadDictInt("v", version, read, k, buf)) + return false; + return read; + } + + std::string + ProtocolMessage::bt_encode() const + { + oxenc::bt_dict_producer btdp; - bool - ProtocolMessage::BEncode(llarp_buffer_t* buf) const + try { - if (!bencode_start_dict(buf)) - return false; - if (!BEncodeWriteDictInt("a", proto, buf)) - return false; + btdp.append("a", static_cast(proto)); + if (not payload.empty()) + btdp.append( + "d", std::string_view{reinterpret_cast(payload.data()), payload.size()}); + { - if (!bencode_write_bytestring(buf, "d", 1)) - return false; - if (!bencode_write_bytestring(buf, payload.data(), payload.size())) - return false; + auto subdict = btdp.append_dict("i"); + introReply.bt_encode(subdict); } - if (!BEncodeWriteDictEntry("i", introReply, buf)) - return false; - if (!BEncodeWriteDictInt("n", seqno, buf)) - return false; - if (!BEncodeWriteDictEntry("s", sender, buf)) - return false; - if (!tag.IsZero()) + + btdp.append("n", seqno); + { - if (!BEncodeWriteDictEntry("t", tag, buf)) - return false; + auto subdict = btdp.append_dict("s"); + sender.bt_encode(subdict); } - if (!BEncodeWriteDictInt("v", version, buf)) - return false; - return bencode_end(buf); - } - std::vector - ProtocolMessage::EncodeAuthInfo() const + btdp.append("t", tag.ToView()); + btdp.append("v", version); + } + catch (...) { - std::array info; - llarp_buffer_t buf{info}; - if (not bencode_start_dict(&buf)) - throw std::runtime_error("impossibly small buffer"); - if (not BEncodeWriteDictInt("a", proto, &buf)) - throw std::runtime_error("impossibly small buffer"); - if (not BEncodeWriteDictEntry("i", introReply, &buf)) - throw std::runtime_error("impossibly small buffer"); - if (not BEncodeWriteDictEntry("s", sender, &buf)) - throw std::runtime_error("impossibly small buffer"); - if (not BEncodeWriteDictEntry("t", tag, &buf)) - throw std::runtime_error("impossibly small buffer"); - if (not BEncodeWriteDictInt("v", version, &buf)) - throw std::runtime_error("impossibly small buffer"); - if (not bencode_end(&buf)) - throw std::runtime_error("impossibly small buffer"); - const std::size_t encodedSize = buf.cur - buf.base; - std::vector data; - data.resize(encodedSize); - std::copy_n(buf.base, encodedSize, data.data()); - return data; + log::critical(route_cat, "Error: ProtocolMessage failed to bt encode contents!"); } - ProtocolFrame::~ProtocolFrame() = default; + return std::move(btdp).str(); + } + + std::vector + ProtocolMessage::EncodeAuthInfo() const + { + oxenc::bt_dict_producer btdp; - bool - ProtocolFrame::BEncode(llarp_buffer_t* buf) const + try { - if (!bencode_start_dict(buf)) - return false; + btdp.append("a", static_cast(proto)); - if (!BEncodeWriteDictMsgType(buf, "A", "H")) - return false; - if (!C.IsZero()) - { - if (!BEncodeWriteDictEntry("C", C, buf)) - return false; - } - if (D.size() > 0) { - if (!BEncodeWriteDictEntry("D", D, buf)) - return false; + auto subdict = btdp.append_dict("s"); + sender.bt_encode(subdict); } - if (!BEncodeWriteDictEntry("F", F, buf)) - return false; - if (!N.IsZero()) - { - if (!BEncodeWriteDictEntry("N", N, buf)) - return false; - } - if (R) - { - if (!BEncodeWriteDictInt("R", R, buf)) - return false; - } - if (!T.IsZero()) - { - if (!BEncodeWriteDictEntry("T", T, buf)) - return false; - } - if (!BEncodeWriteDictInt("V", version, buf)) - return false; - if (!BEncodeWriteDictEntry("Z", Z, buf)) - return false; - return bencode_end(buf); - } - bool - ProtocolFrame::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) + btdp.append("t", tag.ToView()); + btdp.append("v", version); + } + catch (...) { - bool read = false; - if (key.startswith("A")) - { - llarp_buffer_t strbuf; - if (!bencode_read_string(val, &strbuf)) - return false; - if (strbuf.sz != 1) - return false; - return *strbuf.cur == 'H'; - } - if (!BEncodeMaybeReadDictEntry("D", D, read, key, val)) - return false; - if (!BEncodeMaybeReadDictEntry("F", F, read, key, val)) - return false; - if (!BEncodeMaybeReadDictEntry("C", C, read, key, val)) - return false; - if (!BEncodeMaybeReadDictEntry("N", N, read, key, val)) - return false; - if (!BEncodeMaybeReadDictInt("S", S, read, key, val)) - return false; - if (!BEncodeMaybeReadDictInt("R", R, read, key, val)) - return false; - if (!BEncodeMaybeReadDictEntry("T", T, read, key, val)) - return false; - if (!BEncodeMaybeVerifyVersion("V", version, llarp::constants::proto_version, read, key, val)) - return false; - if (!BEncodeMaybeReadDictEntry("Z", Z, read, key, val)) - return false; - return read; + log::critical(route_cat, "Error: ProtocolMessage failed to bt encode auth info"); } - bool - ProtocolFrame::DecryptPayloadInto(const SharedSecret& sharedkey, ProtocolMessage& msg) const + auto view = btdp.view(); + std::vector data; + data.resize(view.size()); + + std::copy_n(view.data(), view.size(), data.data()); + return data; + } + + ProtocolFrameMessage::~ProtocolFrameMessage() = default; + + std::string + ProtocolFrameMessage::bt_encode() const + { + oxenc::bt_dict_producer btdp; + + try { - Encrypted_t tmp = D; - auto buf = tmp.Buffer(); - CryptoManager::instance()->xchacha20(*buf, sharedkey, N); - return bencode_decode_dict(msg, buf); + btdp.append("A", "H"); + btdp.append("C", cipher.ToView()); + btdp.append("D", std::string_view{reinterpret_cast(enc.data()), enc.size()}); + btdp.append("F", path_id.ToView()); + btdp.append("N", nonce.ToView()); + btdp.append("R", flag); + btdp.append("T", convo_tag.ToView()); + btdp.append("V", version); + btdp.append("Z", sig.ToView()); } - - bool - ProtocolFrame::Sign(const Identity& localIdent) + catch (...) { - Z.Zero(); - std::array tmp; - llarp_buffer_t buf(tmp); - // encode - if (!BEncode(&buf)) - { - LogError("message too big to encode"); - return false; - } - // rewind - buf.sz = buf.cur - buf.base; - buf.cur = buf.base; - // sign - return localIdent.Sign(Z, buf); + log::critical(route_cat, "Error: ProtocolFrameMessage failed to bt encode contents!"); } - bool - ProtocolFrame::EncryptAndSign( - const ProtocolMessage& msg, const SharedSecret& sessionKey, const Identity& localIdent) + return std::move(btdp).str(); + } + + bool + ProtocolFrameMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) + { + bool read = false; + if (key.startswith("A")) { - std::array tmp; - llarp_buffer_t buf(tmp); - // encode message - if (!msg.BEncode(&buf)) - { - LogError("message too big to encode"); + llarp_buffer_t strbuf; + if (!bencode_read_string(val, &strbuf)) return false; - } - // rewind - buf.sz = buf.cur - buf.base; - buf.cur = buf.base; - // encrypt - CryptoManager::instance()->xchacha20(buf, sessionKey, N); - // put encrypted buffer - D = buf; - // zero out signature - Z.Zero(); - llarp_buffer_t buf2(tmp); - // encode frame - if (!BEncode(&buf2)) - { - LogError("frame too big to encode"); - DumpBuffer(buf2); - return false; - } - // rewind - buf2.sz = buf2.cur - buf2.base; - buf2.cur = buf2.base; - // sign - if (!localIdent.Sign(Z, buf2)) - { - LogError("failed to sign? wtf?!"); + if (strbuf.sz != 1) return false; - } - return true; + return *strbuf.cur == 'H'; } - - struct AsyncFrameDecrypt - { - path::Path_ptr path; - EventLoop_ptr loop; - std::shared_ptr msg; - const Identity& m_LocalIdentity; - Endpoint* handler; - const ProtocolFrame frame; - const Introduction fromIntro; - - AsyncFrameDecrypt( - EventLoop_ptr l, - const Identity& localIdent, - Endpoint* h, - std::shared_ptr m, - const ProtocolFrame& f, - const Introduction& recvIntro) - : loop(std::move(l)) - , msg(std::move(m)) - , m_LocalIdentity(localIdent) - , handler(h) - , frame(f) - , fromIntro(recvIntro) - {} - - static void - Work(std::shared_ptr self) - { - auto crypto = CryptoManager::instance(); - SharedSecret K; - SharedSecret sharedKey; - // copy - ProtocolFrame frame(self->frame); - if (!crypto->pqe_decrypt(self->frame.C, K, pq_keypair_to_secret(self->m_LocalIdentity.pq))) - { - LogError("pqke failed C=", self->frame.C); - self->msg.reset(); - return; - } - // decrypt - auto buf = frame.D.Buffer(); - crypto->xchacha20(*buf, K, self->frame.N); - if (!bencode_decode_dict(*self->msg, buf)) - { - LogError("failed to decode inner protocol message"); - DumpBuffer(*buf); - self->msg.reset(); - return; - } - // verify signature of outer message after we parsed the inner message - if (!self->frame.Verify(self->msg->sender)) - { - LogError( - "intro frame has invalid signature Z=", - self->frame.Z, - " from ", - self->msg->sender.Addr()); - Dump(self->frame); - Dump(*self->msg); - self->msg.reset(); - return; - } - - if (self->handler->HasConvoTag(self->msg->tag)) - { - LogError("dropping duplicate convo tag T=", self->msg->tag); - // TODO: send convotag reset - self->msg.reset(); - return; - } - - // PKE (A, B, N) - SharedSecret sharedSecret; - path_dh_func dh_server = util::memFn(&Crypto::dh_server, CryptoManager::instance()); - - if (!self->m_LocalIdentity.KeyExchange( - dh_server, sharedSecret, self->msg->sender, self->frame.N)) - { - LogError("x25519 key exchange failed"); - Dump(self->frame); - self->msg.reset(); - return; - } - std::array tmp; - // K - std::copy(K.begin(), K.end(), tmp.begin()); - // S = HS( K + PKE( A, B, N)) - std::copy(sharedSecret.begin(), sharedSecret.end(), tmp.begin() + 32); - crypto->shorthash(sharedKey, llarp_buffer_t(tmp)); - - std::shared_ptr msg = std::move(self->msg); - path::Path_ptr path = std::move(self->path); - const PathID_t from = self->frame.F; - msg->handler = self->handler; - self->handler->AsyncProcessAuthMessage( - msg, - [path, msg, from, handler = self->handler, fromIntro = self->fromIntro, sharedKey]( - AuthResult result) { - if (result.code == AuthResultCode::eAuthAccepted) - { - if (handler->WantsOutboundSession(msg->sender.Addr())) - { - handler->PutSenderFor(msg->tag, msg->sender, false); - } - else - { - handler->PutSenderFor(msg->tag, msg->sender, true); - } - handler->PutReplyIntroFor(msg->tag, msg->introReply); - handler->PutCachedSessionKeyFor(msg->tag, sharedKey); - handler->SendAuthResult(path, from, msg->tag, result); - LogInfo("auth okay for T=", msg->tag, " from ", msg->sender.Addr()); - ProtocolMessage::ProcessAsync(path, from, msg); - } - else - { - LogWarn("auth not okay for T=", msg->tag, ": ", result.reason); - } - handler->Pump(time_now_ms()); - }); - } - }; - - ProtocolFrame& - ProtocolFrame::operator=(const ProtocolFrame& other) + if (!BEncodeMaybeReadDictEntry("D", enc, read, key, val)) + return false; + if (!BEncodeMaybeReadDictEntry("F", path_id, read, key, val)) + return false; + if (!BEncodeMaybeReadDictEntry("C", cipher, read, key, val)) + return false; + if (!BEncodeMaybeReadDictEntry("N", nonce, read, key, val)) + return false; + if (!BEncodeMaybeReadDictInt("S", sequence_number, read, key, val)) + return false; + if (!BEncodeMaybeReadDictInt("R", flag, read, key, val)) + return false; + if (!BEncodeMaybeReadDictEntry("T", convo_tag, read, key, val)) + return false; + if (!BEncodeMaybeVerifyVersion("V", version, llarp::constants::proto_version, read, key, val)) + return false; + if (!BEncodeMaybeReadDictEntry("Z", sig, read, key, val)) + return false; + return read; + } + + bool + ProtocolFrameMessage::DecryptPayloadInto( + const SharedSecret& sharedkey, ProtocolMessage& msg) const + { + Encrypted_t tmp = enc; + auto buf = tmp.Buffer(); + CryptoManager::instance()->xchacha20(*buf, sharedkey, nonce); + return bencode_decode_dict(msg, buf); + } + + bool + ProtocolFrameMessage::Sign(const Identity& localIdent) + { + sig.Zero(); + std::array tmp; + llarp_buffer_t buf(tmp); + // encode + auto bte = bt_encode(); + buf.write(bte.begin(), bte.end()); + + // rewind + buf.sz = buf.cur - buf.base; + buf.cur = buf.base; + // sign + return localIdent.Sign(sig, buf); + } + + bool + ProtocolFrameMessage::EncryptAndSign( + const ProtocolMessage& msg, const SharedSecret& sessionKey, const Identity& localIdent) + { + std::array tmp; + llarp_buffer_t buf1(tmp); + // encode message + auto bte1 = msg.bt_encode(); + buf1.write(bte1.begin(), bte1.end()); + // rewind + buf1.sz = buf1.cur - buf1.base; + buf1.cur = buf1.base; + // encrypt + CryptoManager::instance()->xchacha20(buf1, sessionKey, nonce); + // put encrypted buffer + enc = buf1; + // zero out signature + sig.Zero(); + + llarp_buffer_t buf2(tmp); + auto bte2 = bt_encode(); + buf2.write(bte2.begin(), bte2.end()); + // rewind + buf2.sz = buf2.cur - buf2.base; + buf2.cur = buf2.base; + // sign + if (!localIdent.Sign(sig, buf2)) { - C = other.C; - D = other.D; - F = other.F; - N = other.N; - Z = other.Z; - T = other.T; - R = other.R; - S = other.S; - version = other.version; - return *this; + LogError("failed to sign? wtf?!"); + return false; } + return true; + } - struct AsyncDecrypt - { - ServiceInfo si; - SharedSecret shared; - ProtocolFrame frame; - }; - - bool - ProtocolFrame::AsyncDecryptAndVerify( - EventLoop_ptr loop, - path::Path_ptr recvPath, + struct AsyncFrameDecrypt + { + path::Path_ptr path; + EventLoop_ptr loop; + std::shared_ptr msg; + const Identity& m_LocalIdentity; + Endpoint* handler; + const ProtocolFrameMessage frame; + const Introduction fromIntro; + + AsyncFrameDecrypt( + EventLoop_ptr l, const Identity& localIdent, - Endpoint* handler, - std::function)> hook) const + Endpoint* h, + std::shared_ptr m, + const ProtocolFrameMessage& f, + const Introduction& recvIntro) + : loop(std::move(l)) + , msg(std::move(m)) + , m_LocalIdentity(localIdent) + , handler(h) + , frame(f) + , fromIntro(recvIntro) + {} + + static void + Work(std::shared_ptr self) { - auto msg = std::make_shared(); - msg->handler = handler; - if (T.IsZero()) + auto crypto = CryptoManager::instance(); + SharedSecret K; + SharedSecret sharedKey; + // copy + ProtocolFrameMessage frame(self->frame); + if (!crypto->pqe_decrypt( + self->frame.cipher, K, pq_keypair_to_secret(self->m_LocalIdentity.pq))) { - // we need to dh - auto dh = std::make_shared( - loop, localIdent, handler, msg, *this, recvPath->intro); - dh->path = recvPath; - handler->Router()->QueueWork([dh = std::move(dh)] { return AsyncFrameDecrypt::Work(dh); }); - return true; + LogError("pqke failed C=", self->frame.cipher); + self->msg.reset(); + return; } - - auto v = std::make_shared(); - - if (!handler->GetCachedSessionKeyFor(T, v->shared)) + // decrypt + auto buf = frame.enc.Buffer(); + crypto->xchacha20(*buf, K, self->frame.nonce); + if (!bencode_decode_dict(*self->msg, buf)) { - LogError("No cached session for T=", T); - return false; + LogError("failed to decode inner protocol message"); + DumpBuffer(*buf); + self->msg.reset(); + return; } - if (v->shared.IsZero()) + // verify signature of outer message after we parsed the inner message + if (!self->frame.Verify(self->msg->sender)) { - LogError("bad cached session key for T=", T); - return false; + LogError( + "intro frame has invalid signature Z=", + self->frame.sig, + " from ", + self->msg->sender.Addr()); + Dump(self->frame); + Dump(*self->msg); + self->msg.reset(); + return; } - if (!handler->GetSenderFor(T, v->si)) + if (self->handler->HasConvoTag(self->msg->tag)) { - LogError("No sender for T=", T); - return false; + LogError("dropping duplicate convo tag T=", self->msg->tag); + // TODO: send convotag reset + self->msg.reset(); + return; } - if (v->si.Addr().IsZero()) + + // PKE (A, B, N) + SharedSecret sharedSecret; + path_dh_func dh_server = util::memFn(&Crypto::dh_server, CryptoManager::instance()); + + if (!self->m_LocalIdentity.KeyExchange( + dh_server, sharedSecret, self->msg->sender, self->frame.nonce)) { - LogError("Bad sender for T=", T); - return false; + LogError("x25519 key exchange failed"); + Dump(self->frame); + self->msg.reset(); + return; } - - v->frame = *this; - auto callback = [loop, hook](std::shared_ptr msg) { - if (hook) - { - loop->call([msg, hook]() { hook(msg); }); - } - }; - handler->Router()->QueueWork( - [v, msg = std::move(msg), recvPath = std::move(recvPath), callback, handler]() { - auto resetTag = [handler, tag = v->frame.T, from = v->frame.F, path = recvPath]() { - handler->ResetConvoTag(tag, path, from); - }; - - if (not v->frame.Verify(v->si)) + std::array tmp; + // K + std::copy(K.begin(), K.end(), tmp.begin()); + // S = HS( K + PKE( A, B, N)) + std::copy(sharedSecret.begin(), sharedSecret.end(), tmp.begin() + 32); + crypto->shorthash(sharedKey, llarp_buffer_t(tmp)); + + std::shared_ptr msg = std::move(self->msg); + path::Path_ptr path = std::move(self->path); + const PathID_t from = self->frame.path_id; + msg->handler = self->handler; + self->handler->AsyncProcessAuthMessage( + msg, + [path, msg, from, handler = self->handler, fromIntro = self->fromIntro, sharedKey]( + AuthResult result) { + if (result.code == AuthResultCode::eAuthAccepted) { - LogError("Signature failure from ", v->si.Addr()); - handler->Loop()->call_soon(resetTag); - return; + if (handler->WantsOutboundSession(msg->sender.Addr())) + { + handler->PutSenderFor(msg->tag, msg->sender, false); + } + else + { + handler->PutSenderFor(msg->tag, msg->sender, true); + } + handler->PutReplyIntroFor(msg->tag, msg->introReply); + handler->PutCachedSessionKeyFor(msg->tag, sharedKey); + handler->SendAuthResult(path, from, msg->tag, result); + LogInfo("auth okay for T=", msg->tag, " from ", msg->sender.Addr()); + ProtocolMessage::ProcessAsync(path, from, msg); } - if (not v->frame.DecryptPayloadInto(v->shared, *msg)) + else { - LogError("failed to decrypt message from ", v->si.Addr()); - handler->Loop()->call_soon(resetTag); - return; + LogWarn("auth not okay for T=", msg->tag, ": ", result.reason); } - callback(msg); - RecvDataEvent ev; - ev.fromPath = std::move(recvPath); - ev.pathid = v->frame.F; - auto* handler = msg->handler; - ev.msg = std::move(msg); - handler->QueueRecvData(std::move(ev)); + handler->Pump(time_now_ms()); }); - return true; } + }; - bool - ProtocolFrame::operator==(const ProtocolFrame& other) const + ProtocolFrameMessage& + ProtocolFrameMessage::operator=(const ProtocolFrameMessage& other) + { + cipher = other.cipher; + enc = other.enc; + path_id = other.path_id; + nonce = other.nonce; + sig = other.sig; + convo_tag = other.convo_tag; + flag = other.flag; + sequence_number = other.sequence_number; + version = other.version; + return *this; + } + + struct AsyncDecrypt + { + ServiceInfo si; + SharedSecret shared; + ProtocolFrameMessage frame; + }; + + bool + ProtocolFrameMessage::AsyncDecryptAndVerify( + EventLoop_ptr loop, + path::Path_ptr recvPath, + const Identity& localIdent, + Endpoint* handler, + std::function)> hook) const + { + auto msg = std::make_shared(); + msg->handler = handler; + if (convo_tag.IsZero()) { - return C == other.C && D == other.D && N == other.N && Z == other.Z && T == other.T - && S == other.S && version == other.version; + // we need to dh + auto dh = std::make_shared( + loop, localIdent, handler, msg, *this, recvPath->intro); + dh->path = recvPath; + handler->Router()->QueueWork([dh = std::move(dh)] { return AsyncFrameDecrypt::Work(dh); }); + return true; } - bool - ProtocolFrame::Verify(const ServiceInfo& svc) const - { - ProtocolFrame copy(*this); - // save signature - // zero out signature for verify - copy.Z.Zero(); - // serialize - std::array tmp; - llarp_buffer_t buf(tmp); - if (!copy.BEncode(&buf)) - { - LogError("bencode fail"); - return false; - } + auto v = std::make_shared(); - // rewind buffer - buf.sz = buf.cur - buf.base; - buf.cur = buf.base; - // verify - return svc.Verify(buf, Z); + if (!handler->GetCachedSessionKeyFor(convo_tag, v->shared)) + { + LogError("No cached session for T=", convo_tag); + return false; + } + if (v->shared.IsZero()) + { + LogError("bad cached session key for T=", convo_tag); + return false; } - bool - ProtocolFrame::HandleMessage( - routing::AbstractRoutingMessageHandler* h, AbstractRouter* /*r*/) const + if (!handler->GetSenderFor(convo_tag, v->si)) + { + LogError("No sender for T=", convo_tag); + return false; + } + if (v->si.Addr().IsZero()) { - return h->HandleHiddenServiceFrame(*this); + LogError("Bad sender for T=", convo_tag); + return false; } - } // namespace service -} // namespace llarp + v->frame = *this; + auto callback = [loop, hook](std::shared_ptr msg) { + if (hook) + { + loop->call([msg, hook]() { hook(msg); }); + } + }; + handler->Router()->QueueWork( + [v, msg = std::move(msg), recvPath = std::move(recvPath), callback, handler]() { + auto resetTag = + [handler, tag = v->frame.convo_tag, from = v->frame.path_id, path = recvPath]() { + handler->ResetConvoTag(tag, path, from); + }; + + if (not v->frame.Verify(v->si)) + { + LogError("Signature failure from ", v->si.Addr()); + handler->Loop()->call_soon(resetTag); + return; + } + if (not v->frame.DecryptPayloadInto(v->shared, *msg)) + { + LogError("failed to decrypt message from ", v->si.Addr()); + handler->Loop()->call_soon(resetTag); + return; + } + callback(msg); + RecvDataEvent ev; + ev.fromPath = std::move(recvPath); + ev.pathid = v->frame.path_id; + auto* handler = msg->handler; + ev.msg = std::move(msg); + handler->QueueRecvData(std::move(ev)); + }); + return true; + } + + bool + ProtocolFrameMessage::operator==(const ProtocolFrameMessage& other) const + { + return cipher == other.cipher && enc == other.enc && nonce == other.nonce && sig == other.sig + && convo_tag == other.convo_tag && sequence_number == other.sequence_number + && version == other.version; + } + + bool + ProtocolFrameMessage::Verify(const ServiceInfo& svc) const + { + ProtocolFrameMessage copy(*this); + // save signature + // zero out signature for verify + copy.sig.Zero(); + // serialize + std::array tmp; + llarp_buffer_t buf(tmp); + + auto bte = copy.bt_encode(); + buf.write(bte.begin(), bte.end()); + + // rewind buffer + buf.sz = buf.cur - buf.base; + buf.cur = buf.base; + // verify + return svc.Verify(buf, sig); + } + + bool + ProtocolFrameMessage::handle_message( + routing::AbstractRoutingMessageHandler* h, AbstractRouter* /*r*/) const + { + return h->HandleHiddenServiceFrame(*this); + } + +} // namespace llarp::service diff --git a/llarp/service/protocol.hpp b/llarp/service/protocol.hpp index a13f3cf2e4..adb8daeaa6 100644 --- a/llarp/service/protocol.hpp +++ b/llarp/service/protocol.hpp @@ -31,6 +31,11 @@ namespace llarp constexpr std::size_t MAX_PROTOCOL_MESSAGE_SIZE = 2048 * 2; + /* Note: Talk to Tom and Jason about switching the names of ProtocolFrameMessage (carrier + object) and ProtocolMessage (inner object) to something like ProtocolMessageCarrier and + ProtocolMessage? + */ + /// inner message struct ProtocolMessage { @@ -52,10 +57,10 @@ namespace llarp EncodeAuthInfo() const; bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val); + decode_key(const llarp_buffer_t& key, llarp_buffer_t* val); - bool - BEncode(llarp_buffer_t* buf) const; + std::string + bt_encode() const; void PutBuffer(const llarp_buffer_t& payload); @@ -71,49 +76,49 @@ namespace llarp }; /// outer message - struct ProtocolFrame final : public routing::AbstractRoutingMessage + struct ProtocolFrameMessage final : public routing::AbstractRoutingMessage { using Encrypted_t = Encrypted<2048>; - PQCipherBlock C; - Encrypted_t D; - uint64_t R; - KeyExchangeNonce N; - Signature Z; - PathID_t F; - service::ConvoTag T; - - ProtocolFrame(const ProtocolFrame& other) - : routing::AbstractRoutingMessage() - , C(other.C) - , D(other.D) - , R(other.R) - , N(other.N) - , Z(other.Z) - , F(other.F) - , T(other.T) + PQCipherBlock cipher; + Encrypted_t enc; + uint64_t flag; // set to indicate in plaintext a nack, aka "dont try again" + KeyExchangeNonce nonce; + Signature sig; + PathID_t path_id; + service::ConvoTag convo_tag; + + ProtocolFrameMessage(const ProtocolFrameMessage& other) + : routing::AbstractRoutingMessage(other) + , cipher(other.cipher) + , enc(other.enc) + , flag(other.flag) + , nonce(other.nonce) + , sig(other.sig) + , path_id(other.path_id) + , convo_tag(other.convo_tag) { - S = other.S; + sequence_number = other.sequence_number; version = other.version; } - ProtocolFrame() : routing::AbstractRoutingMessage{} + ProtocolFrameMessage() : routing::AbstractRoutingMessage{} { - Clear(); + clear(); } - ~ProtocolFrame() override; + ~ProtocolFrameMessage() override; bool - operator==(const ProtocolFrame& other) const; + operator==(const ProtocolFrameMessage& other) const; bool - operator!=(const ProtocolFrame& other) const + operator!=(const ProtocolFrameMessage& other) const { return !(*this == other); } - ProtocolFrame& - operator=(const ProtocolFrame& other); + ProtocolFrameMessage& + operator=(const ProtocolFrameMessage& other); bool EncryptAndSign( @@ -134,10 +139,15 @@ namespace llarp DecryptPayloadInto(const SharedSecret& sharedkey, ProtocolMessage& into) const; bool - DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* val) override; + decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; - bool - BEncode(llarp_buffer_t* buf) const override; + /** Note: this method needs to be re-examined where it is called in the other class methods, + like ::Sign(), ::EncryptAndSign(), and ::Verify(). In all 3 of these cases, the subsequent + methods that the llarp_buffer_t is passed to must be refactored to take either a string, a + redesigned llarp_buffer, or some span backport. + */ + std::string + bt_encode() const override; bool BDecode(llarp_buffer_t* buf) @@ -146,15 +156,15 @@ namespace llarp } void - Clear() override + clear() override { - C.Zero(); - D.Clear(); - F.Zero(); - T.Zero(); - N.Zero(); - Z.Zero(); - R = 0; + cipher.Zero(); + enc.Clear(); + path_id.Zero(); + convo_tag.Zero(); + nonce.Zero(); + sig.Zero(); + flag = 0; version = llarp::constants::proto_version; } @@ -162,7 +172,7 @@ namespace llarp Verify(const ServiceInfo& from) const; bool - HandleMessage(routing::AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + handle_message(routing::AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; }; } // namespace service } // namespace llarp diff --git a/llarp/service/sendcontext.cpp b/llarp/service/sendcontext.cpp index 0629ba3d00..4572b0c985 100644 --- a/llarp/service/sendcontext.cpp +++ b/llarp/service/sendcontext.cpp @@ -7,165 +7,163 @@ #include #include -namespace llarp +namespace llarp::service { - namespace service - { - static constexpr size_t SendContextQueueSize = 512; + static constexpr size_t SendContextQueueSize = 512; - SendContext::SendContext( - ServiceInfo ident, const Introduction& intro, path::PathSet* send, Endpoint* ep) - : remoteIdent(std::move(ident)) - , remoteIntro(intro) - , m_PathSet(send) - , m_DataHandler(ep) - , m_Endpoint(ep) - , createdAt(ep->Now()) - , m_SendQueue(SendContextQueueSize) - {} + SendContext::SendContext( + ServiceInfo ident, const Introduction& intro, path::PathSet* send, Endpoint* ep) + : remoteIdent(std::move(ident)) + , remoteIntro(intro) + , m_PathSet(send) + , m_DataHandler(ep) + , m_Endpoint(ep) + , createdAt(ep->Now()) + , m_SendQueue(SendContextQueueSize) + {} - bool - SendContext::Send(std::shared_ptr msg, path::Path_ptr path) + bool + SendContext::Send(std::shared_ptr msg, path::Path_ptr path) + { + if (path->IsReady() + and m_SendQueue.tryPushBack(std::make_pair( + std::make_shared(*msg, remoteIntro.path_id), path)) + == thread::QueueReturn::Success) { - if (path->IsReady() - and m_SendQueue.tryPushBack(std::make_pair( - std::make_shared(*msg, remoteIntro.pathID), path)) - == thread::QueueReturn::Success) - { - m_Endpoint->Router()->TriggerPump(); - return true; - } - return false; + m_Endpoint->Router()->TriggerPump(); + return true; } + return false; + } - void - SendContext::FlushUpstream() + void + SendContext::FlushUpstream() + { + auto r = m_Endpoint->Router(); + std::unordered_set flushpaths; + auto rttRMS = 0ms; + while (auto maybe = m_SendQueue.tryPopFront()) { - auto r = m_Endpoint->Router(); - std::unordered_set flushpaths; - auto rttRMS = 0ms; - while (auto maybe = m_SendQueue.tryPopFront()) - { - auto& [msg, path] = *maybe; - msg->S = path->NextSeqNo(); - if (path->SendRoutingMessage(*msg, r)) - { - lastGoodSend = r->Now(); - flushpaths.emplace(path); - m_Endpoint->ConvoTagTX(msg->T.T); - const auto rtt = (path->intro.latency + remoteIntro.latency) * 2; - rttRMS += rtt * rtt.count(); - } - } - // flush the select path's upstream - for (const auto& path : flushpaths) + auto& [msg, path] = *maybe; + msg->sequence_number = path->NextSeqNo(); + if (path->SendRoutingMessage(*msg, r)) { - path->FlushUpstream(r); + lastGoodSend = r->Now(); + flushpaths.emplace(path); + m_Endpoint->ConvoTagTX(msg->protocol_frame_msg.convo_tag); + const auto rtt = (path->intro.latency + remoteIntro.latency) * 2; + rttRMS += rtt * rtt.count(); } - if (flushpaths.empty()) - return; - estimatedRTT = std::chrono::milliseconds{ - static_cast(std::sqrt(rttRMS.count() / flushpaths.size()))}; } - - /// send on an established convo tag - void - SendContext::EncryptAndSendTo(const llarp_buffer_t& payload, ProtocolType t) + // flush the select path's upstream + for (const auto& path : flushpaths) { - SharedSecret shared; - auto f = std::make_shared(); - f->R = 0; - f->N.Randomize(); - f->T = currentConvoTag; - f->S = ++sequenceNo; - - auto path = m_PathSet->GetPathByRouter(remoteIntro.router); - if (!path) - { - ShiftIntroRouter(remoteIntro.router); - LogWarn(m_PathSet->Name(), " cannot encrypt and send: no path for intro ", remoteIntro); - return; - } + path->FlushUpstream(r); + } + if (flushpaths.empty()) + return; + estimatedRTT = std::chrono::milliseconds{ + static_cast(std::sqrt(rttRMS.count() / flushpaths.size()))}; + } - if (!m_DataHandler->GetCachedSessionKeyFor(f->T, shared)) - { - LogWarn( - m_PathSet->Name(), " could not send, has no cached session key on session T=", f->T); - return; - } + /// send on an established convo tag + void + SendContext::EncryptAndSendTo(const llarp_buffer_t& payload, ProtocolType t) + { + SharedSecret shared; + auto f = std::make_shared(); + f->flag = 0; + f->nonce.Randomize(); + f->convo_tag = currentConvoTag; + f->sequence_number = ++sequenceNo; - auto m = std::make_shared(); - m_DataHandler->PutIntroFor(f->T, remoteIntro); - m_DataHandler->PutReplyIntroFor(f->T, path->intro); - m->proto = t; - if (auto maybe = m_Endpoint->GetSeqNoForConvo(f->T)) - { - m->seqno = *maybe; - } - else - { - LogWarn(m_PathSet->Name(), " could not get sequence number for session T=", f->T); - return; - } - m->introReply = path->intro; - f->F = m->introReply.pathID; - m->sender = m_Endpoint->GetIdentity().pub; - m->tag = f->T; - m->PutBuffer(payload); - m_Endpoint->Router()->QueueWork([f, m, shared, path, this] { - if (not f->EncryptAndSign(*m, shared, m_Endpoint->GetIdentity())) - { - LogError(m_PathSet->Name(), " failed to sign message"); - return; - } - Send(f, path); - }); + auto path = m_PathSet->GetPathByRouter(remoteIntro.router); + if (!path) + { + ShiftIntroRouter(remoteIntro.router); + LogWarn(m_PathSet->Name(), " cannot encrypt and send: no path for intro ", remoteIntro); + return; } - void - SendContext::AsyncSendAuth(std::function resultHandler) + if (!m_DataHandler->GetCachedSessionKeyFor(f->convo_tag, shared)) { - if (const auto maybe = m_Endpoint->MaybeGetAuthInfoForEndpoint(remoteIdent.Addr())) - { - // send auth message - const llarp_buffer_t authdata{maybe->token}; - AsyncGenIntro(authdata, ProtocolType::Auth); - authResultListener = resultHandler; - } - else - resultHandler({AuthResultCode::eAuthAccepted, "no auth needed"}); + LogWarn( + m_PathSet->Name(), + " could not send, has no cached session key on session T=", + f->convo_tag); + return; } - void - SendContext::AsyncEncryptAndSendTo(const llarp_buffer_t& data, ProtocolType protocol) + auto m = std::make_shared(); + m_DataHandler->PutIntroFor(f->convo_tag, remoteIntro); + m_DataHandler->PutReplyIntroFor(f->convo_tag, path->intro); + m->proto = t; + if (auto maybe = m_Endpoint->GetSeqNoForConvo(f->convo_tag)) { - if (IntroSent()) - { - EncryptAndSendTo(data, protocol); - return; - } - // have we generated the initial intro but not sent it yet? bail here so we don't cause - // bullshittery - if (IntroGenerated() and not IntroSent()) + m->seqno = *maybe; + } + else + { + LogWarn(m_PathSet->Name(), " could not get sequence number for session T=", f->convo_tag); + return; + } + m->introReply = path->intro; + f->path_id = m->introReply.path_id; + m->sender = m_Endpoint->GetIdentity().pub; + m->tag = f->convo_tag; + m->PutBuffer(payload); + m_Endpoint->Router()->QueueWork([f, m, shared, path, this] { + if (not f->EncryptAndSign(*m, shared, m_Endpoint->GetIdentity())) { - LogWarn( - m_PathSet->Name(), - " we have generated an intial handshake but have not sent it yet so we drop a packet " - "to prevent bullshittery"); + LogError(m_PathSet->Name(), " failed to sign message"); return; } - const auto maybe = m_Endpoint->MaybeGetAuthInfoForEndpoint(remoteIdent.Addr()); - if (maybe.has_value()) - { - // send auth message - const llarp_buffer_t authdata(maybe->token); - AsyncGenIntro(authdata, ProtocolType::Auth); - } - else - { - AsyncGenIntro(data, protocol); - } + Send(f, path); + }); + } + + void + SendContext::AsyncSendAuth(std::function resultHandler) + { + if (const auto maybe = m_Endpoint->MaybeGetAuthInfoForEndpoint(remoteIdent.Addr())) + { + // send auth message + const llarp_buffer_t authdata{maybe->token}; + AsyncGenIntro(authdata, ProtocolType::Auth); + authResultListener = resultHandler; } - } // namespace service + else + resultHandler({AuthResultCode::eAuthAccepted, "no auth needed"}); + } -} // namespace llarp + void + SendContext::AsyncEncryptAndSendTo(const llarp_buffer_t& data, ProtocolType protocol) + { + if (IntroSent()) + { + EncryptAndSendTo(data, protocol); + return; + } + // have we generated the initial intro but not sent it yet? bail here so we don't cause + // bullshittery + if (IntroGenerated() and not IntroSent()) + { + LogWarn( + m_PathSet->Name(), + " we have generated an intial handshake but have not sent it yet so we drop a packet " + "to prevent bullshittery"); + return; + } + const auto maybe = m_Endpoint->MaybeGetAuthInfoForEndpoint(remoteIdent.Addr()); + if (maybe.has_value()) + { + // send auth message + const llarp_buffer_t authdata(maybe->token); + AsyncGenIntro(authdata, ProtocolType::Auth); + } + else + { + AsyncGenIntro(data, protocol); + } + } +} // namespace llarp::service diff --git a/llarp/service/sendcontext.hpp b/llarp/service/sendcontext.hpp index 0728d7fc5d..ffddff0b4a 100644 --- a/llarp/service/sendcontext.hpp +++ b/llarp/service/sendcontext.hpp @@ -28,7 +28,7 @@ namespace llarp /// queue send a fully encrypted hidden service frame /// via a path bool - Send(std::shared_ptr f, path::Path_ptr path); + Send(std::shared_ptr f, path::Path_ptr path); /// flush upstream traffic when in router thread void diff --git a/llarp/util/aligned.hpp b/llarp/util/aligned.hpp index fb756d5628..46768b318e 100644 --- a/llarp/util/aligned.hpp +++ b/llarp/util/aligned.hpp @@ -244,11 +244,17 @@ namespace llarp } bool - BEncode(llarp_buffer_t* buf) const + bt_encode(llarp_buffer_t* buf) const { return bencode_write_bytestring(buf, data(), sz); } + std::string + bt_encode() const + { + return {reinterpret_cast(data()), sz}; + } + bool BDecode(llarp_buffer_t* buf) { diff --git a/llarp/util/bencode.hpp b/llarp/util/bencode.hpp index f0344b2d80..09a26bbabf 100644 --- a/llarp/util/bencode.hpp +++ b/llarp/util/bencode.hpp @@ -4,6 +4,7 @@ #include "bencode.h" #include "file.hpp" #include +#include #include "mem.hpp" #include @@ -12,6 +13,8 @@ namespace llarp { + static auto ben_cat = log::Cat("stupid.bencode"); + template bool BEncodeReadList(List_t& result, llarp_buffer_t* buf); @@ -34,7 +37,11 @@ namespace llarp bool BEncodeWriteDictEntry(const char* k, const Obj_t& o, llarp_buffer_t* buf) { - return bencode_write_bytestring(buf, k, 1) && o.BEncode(buf); + if (auto b = bencode_write_bytestring(buf, k, 1); not b) + return false; + auto bte = o.bt_encode(); + buf->write(bte.begin(), bte.end()); + return true; } template @@ -128,15 +135,21 @@ namespace llarp bool BEncodeWriteDictBEncodeList(const char* k, const List_t& l, llarp_buffer_t* buf) { - if (!bencode_write_bytestring(buf, k, 1)) - return false; - if (!bencode_start_list(buf)) - return false; + oxenc::bt_dict_producer btdp; - for (const auto& item : l) - if (!item->BEncode(buf)) - return false; - return bencode_end(buf); + { + auto sublist = btdp.append_list(k); + + for (const auto& item : l) + { + sublist.append(l.bt_encode()); + } + } + + auto view = btdp.view(); + buf->write(view.begin(), view.end()); + + return true; } template @@ -149,7 +162,7 @@ namespace llarp return false; for (size_t idx = 0; idx < array.size(); ++idx) - if (!array[idx].BEncode(buf)) + if (!array[idx].bt_encode(buf)) return false; return bencode_end(buf); } @@ -158,14 +171,23 @@ namespace llarp bool BEncodeWriteList(Iter itr, Iter end, llarp_buffer_t* buf) { - if (!bencode_start_list(buf)) + oxenc::bt_list_producer btlp; + + try + { + while (itr != end) + btlp.append(itr->bt_encode()); + } + catch (...) + { + log::critical(ben_cat, "Stupid bencode.hpp shim code failed."); + } + + auto view = btlp.view(); + if (auto b = buf->write(view.begin(), view.end()); not b) return false; - while (itr != end) - if (!itr->BEncode(buf)) - return false; - else - ++itr; - return bencode_end(buf); + + return true; } template @@ -207,7 +229,7 @@ namespace llarp [&](llarp_buffer_t* buffer, llarp_buffer_t* key) { if (key == nullptr) return true; - if (sink.DecodeKey(*key, buffer)) + if (sink.decode_key(*key, buffer)) return true; llarp::LogWarn("undefined key '", *key->cur, "' for entry in dict"); @@ -306,7 +328,7 @@ namespace llarp for (const auto& item : set) { - if (not item.BEncode(buffer)) + if (not item.bt_encode(buffer)) return false; } @@ -326,10 +348,11 @@ namespace llarp { std::array tmp; llarp_buffer_t buf(tmp); - if (val.BEncode(&buf)) - { + + auto bte = val.bt_encode(); + + if (auto b = buf.write(bte.begin(), bte.end()); b) llarp::DumpBuffer(buf); - } } /// read entire file and decode its contents into t @@ -357,8 +380,10 @@ namespace llarp { std::string tmp(bufsz, 0); llarp_buffer_t buf(tmp); - if (!t.BEncode(&buf)) - return false; + + auto bte = t.bt_encode(); + buf.write(bte.begin(), bte.end()); + tmp.resize(buf.cur - buf.base); try { diff --git a/llarp/util/buffer.hpp b/llarp/util/buffer.hpp index 01ba5ea1b8..3ba3140568 100644 --- a/llarp/util/buffer.hpp +++ b/llarp/util/buffer.hpp @@ -154,20 +154,15 @@ struct /* [[deprecated("this type is stupid, use something else")]] */ llarp_buf // These overloads, const_casting away the const, are not just gross but downright dangerous: template >> - [[deprecated("dangerous constructor that casts away constness, be very careful")]] llarp_buffer_t( - const Byte* buf, size_t sz) - : llarp_buffer_t{const_cast(buf), sz} + llarp_buffer_t(const Byte* buf, size_t sz) : llarp_buffer_t{const_cast(buf), sz} {} template >> - [[deprecated("dangerous constructor that casts away constness, be very careful")]] llarp_buffer_t( - const std::vector& b) - : llarp_buffer_t{const_cast(b.data()), b.size()} + llarp_buffer_t(const std::vector& b) : llarp_buffer_t{const_cast(b.data()), b.size()} {} template >> - [[deprecated("dangerous constructor that casts away constness, be very careful")]] llarp_buffer_t( - const std::array& b) + llarp_buffer_t(const std::array& b) : llarp_buffer_t{const_cast(b.data()), b.size()} {} @@ -312,7 +307,7 @@ llarp_buffer_t::write(InputIt begin, InputIt end) /** Provide a copyable/moveable wrapper around `llarp_buffer_t`. */ -struct [[deprecated("deprecated along with llarp_buffer_t")]] ManagedBuffer +struct ManagedBuffer { llarp_buffer_t underlying; @@ -321,7 +316,7 @@ struct [[deprecated("deprecated along with llarp_buffer_t")]] ManagedBuffer explicit ManagedBuffer(const llarp_buffer_t& b) : underlying(b) {} - ManagedBuffer(ManagedBuffer &&) = default; + ManagedBuffer(ManagedBuffer&&) = default; ManagedBuffer(const ManagedBuffer&) = default; operator const llarp_buffer_t&() const From 511c20cdb6a90e705f42b573f327036c17247ed0 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Wed, 13 Sep 2023 08:57:29 -0700 Subject: [PATCH 025/312] Message handling methods - `::handle_message` is transposed; Rather than the message calling the method and taking a reference to the router, the router should have a handle_message method and take a reference to the message - `::EndcodeBuffer` takes a string reference, to which the result of `::bt_encode()` is assigned --- llarp/dht/context.cpp | 67 +++++++++++++---------- llarp/dht/context.hpp | 14 +++-- llarp/dht/dht.cpp | 2 +- llarp/dht/explorenetworkjob.hpp | 2 +- llarp/dht/localrouterlookup.cpp | 2 +- llarp/dht/localrouterlookup.hpp | 5 +- llarp/dht/localserviceaddresslookup.cpp | 2 +- llarp/dht/localserviceaddresslookup.hpp | 2 +- llarp/dht/localtaglookup.cpp | 5 +- llarp/dht/localtaglookup.hpp | 5 +- llarp/dht/message.hpp | 4 +- llarp/dht/messages/findintro.cpp | 4 +- llarp/dht/messages/findintro.hpp | 2 +- llarp/dht/messages/findname.cpp | 38 +++++++------ llarp/dht/messages/findname.hpp | 2 +- llarp/dht/messages/findrouter.cpp | 9 ++- llarp/dht/messages/findrouter.hpp | 4 +- llarp/dht/messages/gotintro.cpp | 8 +-- llarp/dht/messages/gotintro.hpp | 4 +- llarp/dht/messages/gotname.cpp | 4 +- llarp/dht/messages/gotname.hpp | 2 +- llarp/dht/messages/gotrouter.cpp | 5 +- llarp/dht/messages/gotrouter.hpp | 2 +- llarp/dht/messages/pubintro.cpp | 8 +-- llarp/dht/messages/pubintro.hpp | 2 +- llarp/dht/publishservicejob.cpp | 4 +- llarp/dht/publishservicejob.hpp | 4 +- llarp/dht/recursiverouterlookup.cpp | 2 +- llarp/dht/recursiverouterlookup.hpp | 2 +- llarp/dht/serviceaddresslookup.cpp | 2 +- llarp/dht/serviceaddresslookup.hpp | 2 +- llarp/dht/taglookup.hpp | 5 +- llarp/dht/tx.hpp | 6 +- llarp/messages/common.hpp | 6 ++ llarp/messages/dht_immediate.cpp | 6 +- llarp/path/path.cpp | 3 +- llarp/path/transit_hop.cpp | 2 +- llarp/router/abstractrouter.hpp | 7 ++- llarp/router/outbound_message_handler.cpp | 15 ++--- llarp/router/outbound_message_handler.hpp | 2 +- llarp/router/outbound_session_maker.cpp | 2 +- llarp/router/outbound_session_maker.hpp | 2 +- llarp/router/rc_lookup_handler.cpp | 18 +++--- llarp/router/rc_lookup_handler.hpp | 9 ++- llarp/router/router.cpp | 14 ++--- llarp/router/router.hpp | 7 ++- 46 files changed, 183 insertions(+), 141 deletions(-) diff --git a/llarp/dht/context.cpp b/llarp/dht/context.cpp index 0f552c8549..91931a8041 100644 --- a/llarp/dht/context.cpp +++ b/llarp/dht/context.cpp @@ -25,13 +25,13 @@ namespace llarp::dht { - AbstractContext::~AbstractContext() = default; + AbstractDHTMessageHandler::~AbstractDHTMessageHandler() = default; - struct Context final : public AbstractContext + struct DHTMessageHandler final : public AbstractDHTMessageHandler { - Context(); + DHTMessageHandler(); - ~Context() override = default; + ~DHTMessageHandler() override = default; util::StatusObject ExtractStatus() const override; @@ -280,6 +280,10 @@ namespace llarp::dht void ExploreNetworkVia(const Key_t& peer) override; + bool + handle_message( + const AbstractDHTMessage&, std::vector>&) override; + private: std::shared_ptr _timer_keepalive; @@ -291,13 +295,13 @@ namespace llarp::dht Key_t ourKey; }; - Context::Context() + DHTMessageHandler::DHTMessageHandler() { randombytes((byte_t*)&ids, sizeof(uint64_t)); } void - Context::Explore(size_t N) + DHTMessageHandler::Explore(size_t N) { // ask N random peers for new routers llarp::LogDebug("Exploring network via ", N, " peers"); @@ -313,7 +317,7 @@ namespace llarp::dht } void - Context::ExploreNetworkVia(const Key_t& askpeer) + DHTMessageHandler::ExploreNetworkVia(const Key_t& askpeer) { uint64_t txid = ++ids; const TXOwner peer(askpeer, txid); @@ -324,7 +328,7 @@ namespace llarp::dht } void - Context::handle_cleaner_timer() + DHTMessageHandler::handle_cleaner_timer() { // clean up transactions CleanupTX(); @@ -364,7 +368,7 @@ namespace llarp::dht } void - Context::LookupRouterRelayed( + DHTMessageHandler::LookupRouterRelayed( const Key_t& requester, uint64_t txid, const Key_t& target, @@ -424,7 +428,7 @@ namespace llarp::dht } std::optional - Context::GetIntroSetByLocation(const Key_t& key) const + DHTMessageHandler::GetIntroSetByLocation(const Key_t& key) const { auto itr = _services->nodes.find(key); if (itr == _services->nodes.end()) @@ -433,7 +437,7 @@ namespace llarp::dht } void - Context::CleanupTX() + DHTMessageHandler::CleanupTX() { auto now = Now(); llarp::LogTrace("DHT tick"); @@ -444,7 +448,7 @@ namespace llarp::dht } util::StatusObject - Context::ExtractStatus() const + DHTMessageHandler::ExtractStatus() const { util::StatusObject obj{ {"pendingRouterLookups", pendingRouterLookups().ExtractStatus()}, @@ -456,8 +460,15 @@ namespace llarp::dht return obj; } + bool + DHTMessageHandler::handle_message( + const AbstractDHTMessage& msg, std::vector>& replies) + { + return msg.handle_message(*this, replies); + } + void - Context::Init(const Key_t& us, AbstractRouter* r) + DHTMessageHandler::Init(const Key_t& us, AbstractRouter* r) { router = r; ourKey = us; @@ -470,7 +481,7 @@ namespace llarp::dht } void - Context::DHTSendTo(const RouterID& peer, AbstractDHTMessage* msg, bool) + DHTMessageHandler::DHTSendTo(const RouterID& peer, AbstractDHTMessage* msg, bool) { DHTImmediateMessage m; m.msgs.emplace_back(msg); @@ -484,10 +495,10 @@ namespace llarp::dht // namespace. by the time this is called, we are inside // llarp::routing::DHTMessage::HandleMessage() bool - Context::RelayRequestForPath(const llarp::PathID_t& id, const AbstractDHTMessage& msg) + DHTMessageHandler::RelayRequestForPath(const llarp::PathID_t& id, const AbstractDHTMessage& msg) { routing::PathDHTMessage reply; - if (!msg.handle_message(router->dht(), reply.dht_msgs)) + if (not handle_message(msg, reply.dht_msgs)) return false; if (not reply.dht_msgs.empty()) { @@ -498,7 +509,7 @@ namespace llarp::dht } void - Context::LookupIntroSetForPath( + DHTMessageHandler::LookupIntroSetForPath( const Key_t& addr, uint64_t txid, const llarp::PathID_t& path, @@ -515,7 +526,7 @@ namespace llarp::dht } void - Context::PropagateIntroSetTo( + DHTMessageHandler::PropagateIntroSetTo( const Key_t& from, uint64_t txid, const service::EncryptedIntroSet& introset, @@ -529,7 +540,7 @@ namespace llarp::dht } void - Context::PropagateLocalIntroSet( + DHTMessageHandler::PropagateLocalIntroSet( const PathID_t& from, uint64_t txid, const service::EncryptedIntroSet& introset, @@ -546,7 +557,7 @@ namespace llarp::dht } void - Context::LookupIntroSetRelayed( + DHTMessageHandler::LookupIntroSetRelayed( const Key_t& addr, const Key_t& whoasked, uint64_t txid, @@ -561,7 +572,7 @@ namespace llarp::dht } void - Context::LookupIntroSetDirect( + DHTMessageHandler::LookupIntroSetDirect( const Key_t& addr, const Key_t& whoasked, uint64_t txid, @@ -575,7 +586,7 @@ namespace llarp::dht } bool - Context::HandleExploritoryRouterLookup( + DHTMessageHandler::HandleExploritoryRouterLookup( const Key_t& requester, uint64_t txid, const RouterID& target, @@ -621,7 +632,7 @@ namespace llarp::dht } void - Context::LookupRouterForPath( + DHTMessageHandler::LookupRouterForPath( const RouterID& target, uint64_t txid, const llarp::PathID_t& path, const Key_t& askpeer) { @@ -632,7 +643,7 @@ namespace llarp::dht } void - Context::LookupRouterRecursive( + DHTMessageHandler::LookupRouterRecursive( const RouterID& target, const Key_t& whoasked, uint64_t txid, @@ -646,15 +657,15 @@ namespace llarp::dht } llarp_time_t - Context::Now() const + DHTMessageHandler::Now() const { return router->Now(); } - std::unique_ptr - makeContext() + std::unique_ptr + make_handler() { - return std::make_unique(); + return std::make_unique(); } } // namespace llarp::dht diff --git a/llarp/dht/context.hpp b/llarp/dht/context.hpp index ba6a9173c1..5fc17ec819 100644 --- a/llarp/dht/context.hpp +++ b/llarp/dht/context.hpp @@ -32,13 +32,13 @@ namespace llarp static constexpr size_t IntroSetStorageRedundancy = (IntroSetRelayRedundancy * IntroSetRequestsPerRelay); - struct AbstractContext + struct AbstractDHTMessageHandler /* : public AbstractMessageHandler */ { using PendingIntrosetLookups = TXHolder; using PendingRouterLookups = TXHolder; using PendingExploreLookups = TXHolder; - virtual ~AbstractContext() = 0; + virtual ~AbstractDHTMessageHandler() = 0; virtual bool LookupRouter(const RouterID& target, RouterLookupHandler result) = 0; @@ -190,16 +190,20 @@ namespace llarp virtual void StoreRC(const RouterContact rc) const = 0; + + virtual bool + handle_message( + const AbstractDHTMessage&, std::vector>&) = 0; }; - std::unique_ptr - makeContext(); + std::unique_ptr + make_handler(); } // namespace dht } // namespace llarp struct llarp_dht_context { - std::unique_ptr impl; + std::unique_ptr impl; llarp::AbstractRouter* parent; llarp_dht_context(llarp::AbstractRouter* router); }; diff --git a/llarp/dht/dht.cpp b/llarp/dht/dht.cpp index f124113436..8dbecfc8c1 100644 --- a/llarp/dht/dht.cpp +++ b/llarp/dht/dht.cpp @@ -5,7 +5,7 @@ llarp_dht_context::llarp_dht_context(llarp::AbstractRouter* router) { parent = router; - impl = llarp::dht::makeContext(); + impl = llarp::dht::make_handler(); } struct llarp_dht_context* diff --git a/llarp/dht/explorenetworkjob.hpp b/llarp/dht/explorenetworkjob.hpp index 990c619f8f..ac97ed778c 100644 --- a/llarp/dht/explorenetworkjob.hpp +++ b/llarp/dht/explorenetworkjob.hpp @@ -10,7 +10,7 @@ namespace llarp { struct ExploreNetworkJob : public TX { - ExploreNetworkJob(const RouterID& peer, AbstractContext* ctx) + ExploreNetworkJob(const RouterID& peer, AbstractDHTMessageHandler* ctx) : TX(TXOwner{}, peer, ctx) {} diff --git a/llarp/dht/localrouterlookup.cpp b/llarp/dht/localrouterlookup.cpp index 0e82b24627..2482e37ce4 100644 --- a/llarp/dht/localrouterlookup.cpp +++ b/llarp/dht/localrouterlookup.cpp @@ -11,7 +11,7 @@ namespace llarp::dht { LocalRouterLookup::LocalRouterLookup( - const PathID_t& path, uint64_t txid, const RouterID& _target, AbstractContext* ctx) + const PathID_t& path, uint64_t txid, const RouterID& _target, AbstractDHTMessageHandler* ctx) : RecursiveRouterLookup(TXOwner{ctx->OurKey(), txid}, _target, ctx, nullptr), localPath(path) {} diff --git a/llarp/dht/localrouterlookup.hpp b/llarp/dht/localrouterlookup.hpp index 282e954d81..fc7b4b0299 100644 --- a/llarp/dht/localrouterlookup.hpp +++ b/llarp/dht/localrouterlookup.hpp @@ -14,7 +14,10 @@ namespace llarp::dht PathID_t localPath; LocalRouterLookup( - const PathID_t& path, uint64_t txid, const RouterID& target, AbstractContext* ctx); + const PathID_t& path, + uint64_t txid, + const RouterID& target, + AbstractDHTMessageHandler* ctx); void SendReply() override; diff --git a/llarp/dht/localserviceaddresslookup.cpp b/llarp/dht/localserviceaddresslookup.cpp index eda075a524..4644831a22 100644 --- a/llarp/dht/localserviceaddresslookup.cpp +++ b/llarp/dht/localserviceaddresslookup.cpp @@ -14,7 +14,7 @@ namespace llarp::dht uint64_t txid, uint64_t relayOrder, const Key_t& addr, - AbstractContext* ctx, + AbstractDHTMessageHandler* ctx, [[maybe_unused]] const Key_t& askpeer) : ServiceAddressLookup(TXOwner{ctx->OurKey(), txid}, addr, ctx, relayOrder, nullptr) , localPath(pathid) diff --git a/llarp/dht/localserviceaddresslookup.hpp b/llarp/dht/localserviceaddresslookup.hpp index 272a22ae24..8263cab6ee 100644 --- a/llarp/dht/localserviceaddresslookup.hpp +++ b/llarp/dht/localserviceaddresslookup.hpp @@ -16,7 +16,7 @@ namespace llarp::dht uint64_t txid, uint64_t relayOrder, const Key_t& addr, - AbstractContext* ctx, + AbstractDHTMessageHandler* ctx, [[maybe_unused]] const Key_t& askpeer); void diff --git a/llarp/dht/localtaglookup.cpp b/llarp/dht/localtaglookup.cpp index ca7cbe843a..2e6e7f65cb 100644 --- a/llarp/dht/localtaglookup.cpp +++ b/llarp/dht/localtaglookup.cpp @@ -9,7 +9,10 @@ namespace llarp::dht { LocalTagLookup::LocalTagLookup( - const PathID_t& path, uint64_t txid, const service::Tag& _target, AbstractContext* ctx) + const PathID_t& path, + uint64_t txid, + const service::Tag& _target, + AbstractDHTMessageHandler* ctx) : TagLookup(TXOwner{ctx->OurKey(), txid}, _target, ctx, 0), localPath(path) {} diff --git a/llarp/dht/localtaglookup.hpp b/llarp/dht/localtaglookup.hpp index cb96c9f256..d9e3d7de3b 100644 --- a/llarp/dht/localtaglookup.hpp +++ b/llarp/dht/localtaglookup.hpp @@ -10,7 +10,10 @@ namespace llarp::dht PathID_t localPath; LocalTagLookup( - const PathID_t& path, uint64_t txid, const service::Tag& target, AbstractContext* ctx); + const PathID_t& path, + uint64_t txid, + const service::Tag& target, + AbstractDHTMessageHandler* ctx); void SendReply() override; diff --git a/llarp/dht/message.hpp b/llarp/dht/message.hpp index 1c06bc7201..a340f63b28 100644 --- a/llarp/dht/message.hpp +++ b/llarp/dht/message.hpp @@ -17,6 +17,8 @@ namespace llarp::dht { constexpr size_t MAX_MSG_SIZE = 2048; + struct AbstractDHTMessageHandler; + struct AbstractDHTMessage : private AbstractSerializable { virtual ~AbstractDHTMessage() = default; @@ -27,7 +29,7 @@ namespace llarp::dht virtual bool handle_message( - struct llarp_dht_context* dht, + AbstractDHTMessageHandler& dht, std::vector>& replies) const = 0; void diff --git a/llarp/dht/messages/findintro.cpp b/llarp/dht/messages/findintro.cpp index be5673f67f..93c1609656 100644 --- a/llarp/dht/messages/findintro.cpp +++ b/llarp/dht/messages/findintro.cpp @@ -60,9 +60,9 @@ namespace llarp::dht bool FindIntroMessage::handle_message( - llarp_dht_context* ctx, std::vector>& replies) const + AbstractDHTMessageHandler& dht, + std::vector>& replies) const { - auto& dht = *ctx->impl; if (dht.pendingIntrosetLookups().HasPendingLookupFrom(TXOwner{From, txID})) { llarp::LogWarn("duplicate FIM from ", From, " txid=", txID); diff --git a/llarp/dht/messages/findintro.hpp b/llarp/dht/messages/findintro.hpp index 116e2d188d..2390a77e09 100644 --- a/llarp/dht/messages/findintro.hpp +++ b/llarp/dht/messages/findintro.hpp @@ -41,7 +41,7 @@ namespace llarp::dht bool handle_message( - llarp_dht_context* ctx, + AbstractDHTMessageHandler& dht, std::vector>& replies) const override; }; } // namespace llarp::dht diff --git a/llarp/dht/messages/findname.cpp b/llarp/dht/messages/findname.cpp index f6681abaeb..2559313983 100644 --- a/llarp/dht/messages/findname.cpp +++ b/llarp/dht/messages/findname.cpp @@ -44,28 +44,30 @@ namespace llarp::dht bool FindNameMessage::handle_message( - struct llarp_dht_context* dht, + AbstractDHTMessageHandler& dht, std::vector>& replies) const { (void)replies; - auto r = dht->impl->GetRouter(); - if (pathID.IsZero() or not r->IsServiceNode()) + auto router = dht.GetRouter(); + if (pathID.IsZero() or not router->IsServiceNode()) return false; - r->RpcClient()->LookupLNSNameHash(NameHash, [r, pathID = pathID, TxID = TxID](auto maybe) { - auto path = r->pathContext().GetPathForTransfer(pathID); - if (path == nullptr) - return; - routing::PathDHTMessage msg; - if (maybe.has_value()) - { - msg.dht_msgs.emplace_back(new GotNameMessage(dht::Key_t{}, TxID, *maybe)); - } - else - { - msg.dht_msgs.emplace_back(new GotNameMessage(dht::Key_t{}, TxID, service::EncryptedName{})); - } - path->SendRoutingMessage(msg, r); - }); + router->RpcClient()->LookupLNSNameHash( + NameHash, [router, pathID = pathID, TxID = TxID](auto maybe) { + auto path = router->pathContext().GetPathForTransfer(pathID); + if (path == nullptr) + return; + routing::PathDHTMessage msg; + if (maybe.has_value()) + { + msg.dht_msgs.emplace_back(new GotNameMessage(dht::Key_t{}, TxID, *maybe)); + } + else + { + msg.dht_msgs.emplace_back( + new GotNameMessage(dht::Key_t{}, TxID, service::EncryptedName{})); + } + path->SendRoutingMessage(msg, router); + }); return true; } diff --git a/llarp/dht/messages/findname.hpp b/llarp/dht/messages/findname.hpp index 05c8e49b8a..49f8f73f5f 100644 --- a/llarp/dht/messages/findname.hpp +++ b/llarp/dht/messages/findname.hpp @@ -16,7 +16,7 @@ namespace llarp::dht bool handle_message( - struct llarp_dht_context* dht, + AbstractDHTMessageHandler& dht, std::vector>& replies) const override; Key_t NameHash; diff --git a/llarp/dht/messages/findrouter.cpp b/llarp/dht/messages/findrouter.cpp index 25f64452c1..e902b7d7a2 100644 --- a/llarp/dht/messages/findrouter.cpp +++ b/llarp/dht/messages/findrouter.cpp @@ -13,9 +13,9 @@ namespace llarp::dht { bool RelayedFindRouterMessage::handle_message( - llarp_dht_context* ctx, std::vector>& replies) const + AbstractDHTMessageHandler& dht, + std::vector>& replies) const { - auto& dht = *ctx->impl; /// lookup for us, send an immeidate reply const Key_t us = dht.OurKey(); const Key_t k{targetKey}; @@ -118,10 +118,9 @@ namespace llarp::dht bool FindRouterMessage::handle_message( - llarp_dht_context* ctx, std::vector>& replies) const + AbstractDHTMessageHandler& dht, + std::vector>& replies) const { - auto& dht = *ctx->impl; - auto router = dht.GetRouter(); router->NotifyRouterEvent(router->pubkey(), *this); diff --git a/llarp/dht/messages/findrouter.hpp b/llarp/dht/messages/findrouter.hpp index 9c57ae2814..7dd0b78fbe 100644 --- a/llarp/dht/messages/findrouter.hpp +++ b/llarp/dht/messages/findrouter.hpp @@ -30,7 +30,7 @@ namespace llarp::dht bool handle_message( - llarp_dht_context* ctx, + AbstractDHTMessageHandler& dht, std::vector>& replies) const override; RouterID targetKey; @@ -51,7 +51,7 @@ namespace llarp::dht /// TODO: smart path expiration logic needs to be implemented bool handle_message( - llarp_dht_context* ctx, + AbstractDHTMessageHandler& dht, std::vector>& replies) const override; }; } // namespace llarp::dht diff --git a/llarp/dht/messages/gotintro.cpp b/llarp/dht/messages/gotintro.cpp index b9aa1f0b18..43d1355752 100644 --- a/llarp/dht/messages/gotintro.cpp +++ b/llarp/dht/messages/gotintro.cpp @@ -17,9 +17,9 @@ namespace llarp::dht bool GotIntroMessage::handle_message( - llarp_dht_context* ctx, std::vector>& /*replies*/) const + AbstractDHTMessageHandler& dht, + std::vector>& /*replies*/) const { - auto& dht = *ctx->impl; auto* router = dht.GetRouter(); router->NotifyRouterEvent( @@ -60,11 +60,11 @@ namespace llarp::dht bool RelayedGotIntroMessage::handle_message( - llarp_dht_context* ctx, + AbstractDHTMessageHandler& dht, [[maybe_unused]] std::vector>& replies) const { // TODO: implement me better? - auto pathset = ctx->impl->GetRouter()->pathContext().GetLocalPathSet(pathID); + auto pathset = dht.GetRouter()->pathContext().GetLocalPathSet(pathID); if (pathset) { auto copy = std::make_shared(*this); diff --git a/llarp/dht/messages/gotintro.hpp b/llarp/dht/messages/gotintro.hpp index 58378b6214..7fd61b10e5 100644 --- a/llarp/dht/messages/gotintro.hpp +++ b/llarp/dht/messages/gotintro.hpp @@ -46,7 +46,7 @@ namespace llarp::dht bool handle_message( - llarp_dht_context* ctx, + AbstractDHTMessageHandler& dht, std::vector>& replies) const override; }; @@ -57,7 +57,7 @@ namespace llarp::dht bool handle_message( - llarp_dht_context* ctx, + AbstractDHTMessageHandler& dht, std::vector>& replies) const override; }; diff --git a/llarp/dht/messages/gotname.cpp b/llarp/dht/messages/gotname.cpp index 16e4778b1c..720786d2d3 100644 --- a/llarp/dht/messages/gotname.cpp +++ b/llarp/dht/messages/gotname.cpp @@ -58,9 +58,9 @@ namespace llarp::dht bool GotNameMessage::handle_message( - struct llarp_dht_context* ctx, std::vector>&) const + AbstractDHTMessageHandler& dht, std::vector>&) const { - auto pathset = ctx->impl->GetRouter()->pathContext().GetLocalPathSet(pathID); + auto pathset = dht.GetRouter()->pathContext().GetLocalPathSet(pathID); if (pathset == nullptr) return false; auto copy = std::make_shared(*this); diff --git a/llarp/dht/messages/gotname.hpp b/llarp/dht/messages/gotname.hpp index 001913313a..63db881e76 100644 --- a/llarp/dht/messages/gotname.hpp +++ b/llarp/dht/messages/gotname.hpp @@ -17,7 +17,7 @@ namespace llarp::dht bool handle_message( - struct llarp_dht_context* dht, + AbstractDHTMessageHandler& dht, std::vector>& replies) const override; service::EncryptedName result; diff --git a/llarp/dht/messages/gotrouter.cpp b/llarp/dht/messages/gotrouter.cpp index 33b4920582..b42e9a51a7 100644 --- a/llarp/dht/messages/gotrouter.cpp +++ b/llarp/dht/messages/gotrouter.cpp @@ -75,13 +75,12 @@ namespace llarp::dht bool GotRouterMessage::handle_message( - llarp_dht_context* ctx, + AbstractDHTMessageHandler& dht, [[maybe_unused]] std::vector>& replies) const { - auto& dht = *ctx->impl; if (relayed) { - auto pathset = ctx->impl->GetRouter()->pathContext().GetLocalPathSet(pathID); + auto pathset = dht.GetRouter()->pathContext().GetLocalPathSet(pathID); auto copy = std::make_shared(*this); return pathset && pathset->HandleGotRouterMessage(copy); } diff --git a/llarp/dht/messages/gotrouter.hpp b/llarp/dht/messages/gotrouter.hpp index 2e7294a15b..cca17f2d5e 100644 --- a/llarp/dht/messages/gotrouter.hpp +++ b/llarp/dht/messages/gotrouter.hpp @@ -52,7 +52,7 @@ namespace llarp::dht bool handle_message( - llarp_dht_context* ctx, + AbstractDHTMessageHandler& dht, std::vector>& replies) const override; std::vector foundRCs; diff --git a/llarp/dht/messages/pubintro.cpp b/llarp/dht/messages/pubintro.cpp index 34f7c3cb0a..a5c6cfee79 100644 --- a/llarp/dht/messages/pubintro.cpp +++ b/llarp/dht/messages/pubintro.cpp @@ -52,16 +52,16 @@ namespace llarp::dht bool PublishIntroMessage::handle_message( - llarp_dht_context* ctx, std::vector>& replies) const + AbstractDHTMessageHandler& dht, + std::vector>& replies) const { - const auto now = ctx->impl->Now(); + const auto now = dht.Now(); const llarp::dht::Key_t addr{introset.derivedSigningKey.data()}; - auto router = ctx->impl->GetRouter(); + auto router = dht.GetRouter(); router->NotifyRouterEvent( router->pubkey(), Key_t(relayed ? router->pubkey() : From.data()), addr, txID, relayOrder); - auto& dht = *ctx->impl; if (!introset.Verify(now)) { llarp::LogWarn("Received PublishIntroMessage with invalid introset: ", introset); diff --git a/llarp/dht/messages/pubintro.hpp b/llarp/dht/messages/pubintro.hpp index 8b210274f4..da877f079b 100644 --- a/llarp/dht/messages/pubintro.hpp +++ b/llarp/dht/messages/pubintro.hpp @@ -40,7 +40,7 @@ namespace llarp::dht bool handle_message( - llarp_dht_context* ctx, + AbstractDHTMessageHandler& dht, std::vector>& replies) const override; }; } // namespace llarp::dht diff --git a/llarp/dht/publishservicejob.cpp b/llarp/dht/publishservicejob.cpp index bdec431257..7c00ffeac8 100644 --- a/llarp/dht/publishservicejob.cpp +++ b/llarp/dht/publishservicejob.cpp @@ -13,7 +13,7 @@ namespace llarp::dht PublishServiceJob::PublishServiceJob( const TXOwner& asker, const service::EncryptedIntroSet& introset_, - AbstractContext* ctx, + AbstractDHTMessageHandler* ctx, uint64_t relayOrder_) : TX(asker, asker, ctx) , relayOrder(relayOrder_) @@ -50,7 +50,7 @@ namespace llarp::dht const PathID_t& fromID, uint64_t _txid, const service::EncryptedIntroSet& introset, - AbstractContext* ctx, + AbstractDHTMessageHandler* ctx, uint64_t relayOrder) : PublishServiceJob(peer, introset, ctx, relayOrder), localPath(fromID), txid(_txid) {} diff --git a/llarp/dht/publishservicejob.hpp b/llarp/dht/publishservicejob.hpp index b8de827c5e..c0badfe8fd 100644 --- a/llarp/dht/publishservicejob.hpp +++ b/llarp/dht/publishservicejob.hpp @@ -18,7 +18,7 @@ namespace llarp::dht PublishServiceJob( const TXOwner& asker, const service::EncryptedIntroSet& introset, - AbstractContext* ctx, + AbstractDHTMessageHandler* ctx, uint64_t relayOrder); bool @@ -40,7 +40,7 @@ namespace llarp::dht const PathID_t& fromID, uint64_t txid, const service::EncryptedIntroSet& introset, - AbstractContext* ctx, + AbstractDHTMessageHandler* ctx, uint64_t relayOrder); void diff --git a/llarp/dht/recursiverouterlookup.cpp b/llarp/dht/recursiverouterlookup.cpp index f4d881622f..e0828b1511 100644 --- a/llarp/dht/recursiverouterlookup.cpp +++ b/llarp/dht/recursiverouterlookup.cpp @@ -16,7 +16,7 @@ namespace llarp RecursiveRouterLookup::RecursiveRouterLookup( const TXOwner& _whoasked, const RouterID& _target, - AbstractContext* ctx, + AbstractDHTMessageHandler* ctx, RouterLookupHandler result) : TX(_whoasked, _target, ctx), resultHandler(std::move(result)) diff --git a/llarp/dht/recursiverouterlookup.hpp b/llarp/dht/recursiverouterlookup.hpp index 69344c4f83..8e592547e1 100644 --- a/llarp/dht/recursiverouterlookup.hpp +++ b/llarp/dht/recursiverouterlookup.hpp @@ -16,7 +16,7 @@ namespace llarp RecursiveRouterLookup( const TXOwner& whoasked, const RouterID& target, - AbstractContext* ctx, + AbstractDHTMessageHandler* ctx, RouterLookupHandler result); bool diff --git a/llarp/dht/serviceaddresslookup.cpp b/llarp/dht/serviceaddresslookup.cpp index bdbee13fd8..028465b86b 100644 --- a/llarp/dht/serviceaddresslookup.cpp +++ b/llarp/dht/serviceaddresslookup.cpp @@ -12,7 +12,7 @@ namespace llarp ServiceAddressLookup::ServiceAddressLookup( const TXOwner& asker, const Key_t& addr, - AbstractContext* ctx, + AbstractDHTMessageHandler* ctx, uint32_t order, service::EncryptedIntroSetLookupHandler handler) : TX(asker, asker, ctx) diff --git a/llarp/dht/serviceaddresslookup.hpp b/llarp/dht/serviceaddresslookup.hpp index fbdf5e4ae3..ad642727f9 100644 --- a/llarp/dht/serviceaddresslookup.hpp +++ b/llarp/dht/serviceaddresslookup.hpp @@ -21,7 +21,7 @@ namespace llarp ServiceAddressLookup( const TXOwner& asker, const Key_t& addr, - AbstractContext* ctx, + AbstractDHTMessageHandler* ctx, uint32_t relayOrder, service::EncryptedIntroSetLookupHandler handler); diff --git a/llarp/dht/taglookup.hpp b/llarp/dht/taglookup.hpp index b40c352dcb..8a96c14bcd 100644 --- a/llarp/dht/taglookup.hpp +++ b/llarp/dht/taglookup.hpp @@ -13,7 +13,10 @@ namespace llarp { uint64_t recursionDepth; TagLookup( - const TXOwner& asker, const service::Tag& tag, AbstractContext* ctx, uint64_t recursion) + const TXOwner& asker, + const service::Tag& tag, + AbstractDHTMessageHandler* ctx, + uint64_t recursion) : TX(asker, tag, ctx), recursionDepth(recursion) {} diff --git a/llarp/dht/tx.hpp b/llarp/dht/tx.hpp index 43ac5c0770..02e5ec7ef8 100644 --- a/llarp/dht/tx.hpp +++ b/llarp/dht/tx.hpp @@ -13,18 +13,18 @@ namespace llarp { namespace dht { - struct AbstractContext; + struct AbstractDHTMessageHandler; template struct TX { K target; - AbstractContext* parent; + AbstractDHTMessageHandler* parent; std::set peersAsked; std::vector valuesFound; TXOwner whoasked; - TX(const TXOwner& asker, const K& k, AbstractContext* p) + TX(const TXOwner& asker, const K& k, AbstractDHTMessageHandler* p) : target(k), parent(p), whoasked(asker) {} diff --git a/llarp/messages/common.hpp b/llarp/messages/common.hpp index d1599bd238..2faac9863c 100644 --- a/llarp/messages/common.hpp +++ b/llarp/messages/common.hpp @@ -18,4 +18,10 @@ namespace llarp virtual void bt_encode(oxenc::bt_list_producer& btlp) const = 0; }; + + struct AbstractMessageHandler + { + virtual bool + handle_message(AbstractSerializable&) = 0; + }; } // namespace llarp diff --git a/llarp/messages/dht_immediate.cpp b/llarp/messages/dht_immediate.cpp index 871a812238..86b8420db7 100644 --- a/llarp/messages/dht_immediate.cpp +++ b/llarp/messages/dht_immediate.cpp @@ -1,6 +1,7 @@ #include "dht_immediate.hpp" #include +#include namespace llarp { @@ -66,9 +67,10 @@ namespace llarp DHTImmediateMessage reply; reply.session = session; bool result = true; - for (auto& msg : msgs) + auto dht = router->dht(); + for (const auto& msg : msgs) { - result &= msg->handle_message(router->dht(), reply.msgs); + result &= dht->handle_message(*msg, reply.msgs); } if (reply.msgs.size()) { diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 211f276c91..3103c2bf6f 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -1,5 +1,6 @@ #include "path.hpp" +#include #include #include #include @@ -788,7 +789,7 @@ namespace llarp::path { MarkActive(r->Now()); routing::PathDHTMessage reply; - if (!msg.handle_message(r->dht(), reply.dht_msgs)) + if (not r->dht()->handle_message(msg, reply.dht_msgs)) return false; if (reply.dht_msgs.size()) return SendRoutingMessage(reply, r); diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index dba3e6287b..23cc483ef5 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -256,7 +256,7 @@ namespace llarp::path bool TransitHop::HandleDHTMessage(const llarp::dht::AbstractDHTMessage& msg, AbstractRouter* r) { - return r->dht()->impl->RelayRequestForPath(info.rxID, msg); + return r->dht()->RelayRequestForPath(info.rxID, msg); } bool diff --git a/llarp/router/abstractrouter.hpp b/llarp/router/abstractrouter.hpp index ce48ebc8a4..0e907e8b3e 100644 --- a/llarp/router/abstractrouter.hpp +++ b/llarp/router/abstractrouter.hpp @@ -44,6 +44,11 @@ namespace llarp struct I_RCLookupHandler; struct RoutePoker; + namespace dht + { + struct AbstractDHTMessageHandler; + } + namespace dns { class I_SystemSettings; @@ -114,7 +119,7 @@ namespace llarp virtual const std::shared_ptr& RpcClient() const = 0; - virtual llarp_dht_context* + virtual std::shared_ptr dht() const = 0; virtual const std::shared_ptr& diff --git a/llarp/router/outbound_message_handler.cpp b/llarp/router/outbound_message_handler.cpp index 2202c1ec8d..914ad4c0ea 100644 --- a/llarp/router/outbound_message_handler.cpp +++ b/llarp/router/outbound_message_handler.cpp @@ -36,15 +36,11 @@ namespace llarp ent.pathid = msg.pathid; ent.priority = msg.priority(); - // std::array linkmsg_buffer; - // llarp_buffer_t buf{linkmsg_buffer}; - - llarp_buffer _buf{MAX_LINK_MSG_SIZE}; + std::string _buf; + _buf.reserve(MAX_LINK_MSG_SIZE); if (!EncodeBuffer(msg, _buf)) - { return false; - } ent.message.resize(_buf.size()); @@ -185,13 +181,10 @@ namespace llarp will be used */ bool - OutboundMessageHandler::EncodeBuffer(const AbstractLinkMessage& msg, llarp_buffer& buf) + OutboundMessageHandler::EncodeBuffer(const AbstractLinkMessage& msg, std::string& buf) { - if (auto str = msg.bt_encode(); not str.empty()) - { - buf = llarp_buffer{std::move(str)}; + if (buf = msg.bt_encode(); not buf.empty()) return true; - } log::error(link_cat, "Error: OutboundMessageHandler failed to encode outbound message!"); return false; diff --git a/llarp/router/outbound_message_handler.hpp b/llarp/router/outbound_message_handler.hpp index cb4c7d0199..0634b33fbb 100644 --- a/llarp/router/outbound_message_handler.hpp +++ b/llarp/router/outbound_message_handler.hpp @@ -123,7 +123,7 @@ namespace llarp QueueSessionCreation(const RouterID& remote); bool - EncodeBuffer(const AbstractLinkMessage& msg, llarp_buffer& buf); + EncodeBuffer(const AbstractLinkMessage& msg, std::string& buf); /* sends the message along to the link layer, and hopefully out to the network * diff --git a/llarp/router/outbound_session_maker.cpp b/llarp/router/outbound_session_maker.cpp index a4eb9a21a6..e6cbc32c02 100644 --- a/llarp/router/outbound_session_maker.cpp +++ b/llarp/router/outbound_session_maker.cpp @@ -158,7 +158,7 @@ namespace llarp void OutboundSessionMaker::Init( AbstractRouter* router, - ILinkManager* linkManager, + LinkManager* linkManager, I_RCLookupHandler* rcLookup, Profiling* profiler, EventLoop_ptr loop, diff --git a/llarp/router/outbound_session_maker.hpp b/llarp/router/outbound_session_maker.hpp index b1823dabe3..131d29e47e 100644 --- a/llarp/router/outbound_session_maker.hpp +++ b/llarp/router/outbound_session_maker.hpp @@ -55,7 +55,7 @@ namespace llarp void Init( AbstractRouter* router, - ILinkManager* linkManager, + LinkManager* linkManager, I_RCLookupHandler* rcLookup, Profiling* profiler, EventLoop_ptr loop, diff --git a/llarp/router/rc_lookup_handler.cpp b/llarp/router/rc_lookup_handler.cpp index 3693dc8f34..4755a8383a 100644 --- a/llarp/router/rc_lookup_handler.cpp +++ b/llarp/router/rc_lookup_handler.cpp @@ -114,7 +114,7 @@ namespace llarp LogWarn("cannot lookup ", router, " anonymously"); } - if (!_dht->impl->LookupRouter(router, fn)) + if (!_dht->LookupRouter(router, fn)) { FinalizeRequest(router, nullptr, RCRequestResult::RouterNotFound); } @@ -196,11 +196,11 @@ namespace llarp { if (not SessionIsAllowed(rc.pubkey)) { - _dht->impl->DelRCNodeAsync(dht::Key_t{rc.pubkey}); + _dht->DelRCNodeAsync(dht::Key_t{rc.pubkey}); return false; } - if (not rc.Verify(_dht->impl->Now())) + if (not rc.Verify(_dht->Now())) { LogWarn("RC for ", RouterID(rc.pubkey), " is invalid"); return false; @@ -211,7 +211,7 @@ namespace llarp { LogDebug("Adding or updating RC for ", RouterID(rc.pubkey), " to nodedb and dht."); _loop->call([rc, n = _nodedb] { n->PutIfNewer(rc); }); - _dht->impl->PutRCNodeAsync(rc); + _dht->PutRCNodeAsync(rc); } return true; @@ -252,9 +252,9 @@ namespace llarp _work(func); // update dht if required - if (_dht->impl->Nodes()->HasNode(dht::Key_t{newrc.pubkey})) + if (_dht->Nodes()->HasNode(dht::Key_t{newrc.pubkey})) { - _dht->impl->Nodes()->PutNode(newrc); + _dht->Nodes()->PutNode(newrc); } // TODO: check for other places that need updating the RC @@ -296,7 +296,7 @@ namespace llarp for (const auto& rc : _bootstrapRCList) { LogInfo("Doing explore via bootstrap node: ", RouterID(rc.pubkey)); - _dht->impl->ExploreNetworkVia(dht::Key_t{rc.pubkey}); + _dht->ExploreNetworkVia(dht::Key_t{rc.pubkey}); } } @@ -333,7 +333,7 @@ namespace llarp return; } // service nodes gossip, not explore - if (_dht->impl->GetRouter()->IsServiceNode()) + if (_dht->GetRouter()->IsServiceNode()) return; // explore via every connected peer @@ -357,7 +357,7 @@ namespace llarp void RCLookupHandler::Init( - llarp_dht_context* dht, + std::shared_ptr dht, std::shared_ptr nodedb, EventLoop_ptr loop, WorkerFunc_t dowork, diff --git a/llarp/router/rc_lookup_handler.hpp b/llarp/router/rc_lookup_handler.hpp index 184b8d1022..eed6a835dd 100644 --- a/llarp/router/rc_lookup_handler.hpp +++ b/llarp/router/rc_lookup_handler.hpp @@ -17,6 +17,11 @@ namespace llarp class NodeDB; class EventLoop; + namespace dht + { + struct AbstractDHTMessageHandler; + } // namespace dht + namespace service { struct Context; @@ -94,7 +99,7 @@ namespace llarp void Init( - llarp_dht_context* dht, + std::shared_ptr dht, std::shared_ptr nodedb, std::shared_ptr loop, WorkerFunc_t dowork, @@ -128,7 +133,7 @@ namespace llarp mutable util::Mutex _mutex; // protects pendingCallbacks, whitelistRouters - llarp_dht_context* _dht = nullptr; + std::shared_ptr _dht = nullptr; std::shared_ptr _nodedb; std::shared_ptr _loop; WorkerFunc_t _work = nullptr; diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 76e9e694eb..2a39fec874 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -54,7 +54,7 @@ namespace llarp , _vpnPlatform{std::move(vpnPlatform)} , paths{this} , _exitContext{this} - , _dht{llarp_dht_context_new(this)} + , _dht{dht::make_handler()} , m_DiskThread{m_lmq->add_tagged_thread("disk")} , inbound_link_msg_parser{this} , _hiddenServiceContext{this} @@ -76,7 +76,7 @@ namespace llarp Router::~Router() { - llarp_dht_context_free(_dht); + _dht.reset(); } // TODO: investigate changes needed for libquic integration @@ -103,7 +103,7 @@ namespace llarp return util::StatusObject{ {"running", true}, {"numNodesKnown", _nodedb->NumLoaded()}, - {"dht", _dht->impl->ExtractStatus()}, + {"dht", _dht->ExtractStatus()}, {"services", _hiddenServiceContext.ExtractStatus()}, {"exit", _exitContext.ExtractStatus()}, {"links", _linkManager.ExtractStatus()}, @@ -1183,7 +1183,7 @@ namespace llarp Router::SessionClosed(RouterID remote) { dht::Key_t k(remote); - dht()->impl->Nodes()->DelNode(k); + dht()->Nodes()->DelNode(k); LogInfo("Session to ", remote, " fully closed"); if (IsServiceNode()) @@ -1366,12 +1366,12 @@ namespace llarp _nodedb->LoadFromDisk(); } - llarp_dht_context_start(dht(), pubkey()); + _dht->Init(llarp::dht::Key_t(pubkey()), this); for (const auto& rc : bootstrapRCList) { nodedb()->Put(rc); - _dht->impl->Nodes()->PutNode(rc); + _dht->Nodes()->PutNode(rc); LogInfo("added bootstrap node ", RouterID{rc.pubkey}); } @@ -1589,7 +1589,7 @@ namespace llarp { LogInfo("accepting transit traffic"); paths.AllowTransit(); - llarp_dht_allow_transit(dht()); + _dht->AllowTransit() = true; _exitContext.AddExitEndpoint("default", m_Config->network, m_Config->dns); return true; } diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index d47ae7aafc..ff74551dd0 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -101,7 +102,7 @@ namespace llarp return m_lokidRpcClient; } - llarp_dht_context* + std::shared_ptr dht() const override { return _dht; @@ -230,7 +231,7 @@ namespace llarp exit::Context _exitContext; SecretKey _identity; SecretKey _encryption; - llarp_dht_context* _dht = nullptr; + std::shared_ptr _dht; std::shared_ptr _nodedb; llarp_time_t _startedAt; const oxenmq::TaggedThreadID m_DiskThread; @@ -593,7 +594,7 @@ namespace llarp AddAddressToRC(AddressInfo& ai); protected: - virtual void + void HandleRouterEvent(tooling::RouterEventPtr event) const override; virtual bool From 0b6506a00b6a435af97f610d447b9d59e619dc96 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Wed, 13 Sep 2023 09:08:24 -0700 Subject: [PATCH 026/312] oxen-libquic version bump - added CI fixes for gnutls build --- .drone.jsonnet | 26 ++++++++++++++++++++++++-- external/oxen-libquic | 2 +- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/.drone.jsonnet b/.drone.jsonnet index 793ee75855..4dece3571b 100644 --- a/.drone.jsonnet +++ b/.drone.jsonnet @@ -9,6 +9,7 @@ local default_deps_base = [ 'libsqlite3-dev', 'libcurl4-openssl-dev', 'libzmq3-dev', + 'libgnutls28-dev', 'make', ]; local default_deps_nocxx = ['libsodium-dev'] + default_deps_base; // libsodium-dev needs to be >= 1.0.18 @@ -35,6 +36,7 @@ local debian_pipeline(name, image, arch='amd64', deps=default_deps, + extra_setup=[], build_type='Release', lto=false, werror=true, @@ -70,7 +72,8 @@ local debian_pipeline(name, 'echo deb http://deb.oxen.io $$(lsb_release -sc) main >/etc/apt/sources.list.d/oxen.list', 'eatmydata ' + apt_get_quiet + ' update', ] else [] - ) + [ + ) + extra_setup + + [ 'eatmydata ' + apt_get_quiet + ' dist-upgrade -y', 'eatmydata ' + apt_get_quiet + ' install --no-install-recommends -y gdb cmake git pkg-config ccache ' + std.join(' ', deps), 'mkdir build', @@ -90,6 +93,24 @@ local debian_pipeline(name, }, ], }; +local local_gnutls(jobs=6, prefix='/usr/local') = [ + apt_get_quiet + ' install -y curl ca-certificates', + 'curl -sSL https://ftp.gnu.org/gnu/nettle/nettle-3.9.1.tar.gz | tar xfz -', + 'curl -sSL https://www.gnupg.org/ftp/gcrypt/gnutls/v3.8/gnutls-3.8.0.tar.xz | tar xfJ -', + 'export CC="ccache gcc"', + 'export PKG_CONFIG_PATH=' + prefix + '/lib/pkgconfig:' + prefix + '/lib64/pkgconfig', + 'export LD_LIBRARY_PATH=' + prefix + '/lib:' + prefix + '/lib64', + 'cd nettle-3.9.1', + './configure --prefix=' + prefix, + 'make -j' + jobs, + 'make install', + 'cd ..', + 'cd gnutls-3.8.0', + './configure --prefix=' + prefix + ' --with-included-libtasn1 --with-included-unistring --without-p11-kit --disable-libdane --disable-cxx --without-tpm --without-tpm2', + 'make -j' + jobs, + 'make install', + 'cd ..', +]; local apk_builder(name, image, extra_cmds=[], allow_fail=false, jobs=6) = { kind: 'pipeline', type: 'docker', @@ -367,12 +388,13 @@ local docs_pipeline(name, image, extra_cmds=[], allow_fail=false) = { clang(13), full_llvm(13), debian_pipeline('Debian stable (i386)', docker_base + 'debian-stable/i386'), - debian_pipeline('Debian buster (amd64)', docker_base + 'debian-buster', cmake_extra='-DDOWNLOAD_SODIUM=ON'), + debian_pipeline('Debian buster (amd64)', docker_base + 'debian-buster', extra_setup=local_gnutls(), cmake_extra='-DDOWNLOAD_SODIUM=ON'), debian_pipeline('Ubuntu latest (amd64)', docker_base + 'ubuntu-rolling'), debian_pipeline('Ubuntu LTS (amd64)', docker_base + 'ubuntu-lts'), debian_pipeline('Ubuntu bionic (amd64)', docker_base + 'ubuntu-bionic', deps=['g++-8'] + default_deps_nocxx, + extra_setup=local_gnutls(), cmake_extra='-DCMAKE_C_COMPILER=gcc-8 -DCMAKE_CXX_COMPILER=g++-8', oxen_repo=true), diff --git a/external/oxen-libquic b/external/oxen-libquic index 0f2504f7a2..1ec1addaa7 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit 0f2504f7a2bfe4803e62cf7a9161806b0718ee5b +Subproject commit 1ec1addaa7a402c94c7b2690e79635a364337d35 From 81aa044baadbb38b08d132c367b31fc8516a2e76 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Wed, 13 Sep 2023 10:07:17 -0700 Subject: [PATCH 027/312] kitware CI deps - stupid warn deprecated stupid --- .drone.jsonnet | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/.drone.jsonnet b/.drone.jsonnet index 4dece3571b..71ca9109d7 100644 --- a/.drone.jsonnet +++ b/.drone.jsonnet @@ -31,6 +31,13 @@ local ci_dep_mirror(want_mirror) = (if want_mirror then ' -DLOCAL_MIRROR=https:/ local apt_get_quiet = 'apt-get -o=Dpkg::Use-Pty=0 -q'; +local kitware_repo(distro) = [ + 'eatmydata ' + apt_get_quiet + ' install -y curl ca-certificates', + 'curl -sSL https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - >/usr/share/keyrings/kitware-archive-keyring.gpg', + 'echo "deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ ' + distro + ' main" >/etc/apt/sources.list.d/kitware.list', + 'eatmydata ' + apt_get_quiet + ' update', +]; + // Regular build on a debian-like system: local debian_pipeline(name, image, @@ -72,14 +79,14 @@ local debian_pipeline(name, 'echo deb http://deb.oxen.io $$(lsb_release -sc) main >/etc/apt/sources.list.d/oxen.list', 'eatmydata ' + apt_get_quiet + ' update', ] else [] - ) + extra_setup + ) + extra_setup + [ 'eatmydata ' + apt_get_quiet + ' dist-upgrade -y', 'eatmydata ' + apt_get_quiet + ' install --no-install-recommends -y gdb cmake git pkg-config ccache ' + std.join(' ', deps), 'mkdir build', 'cd build', 'cmake .. -DWITH_SETCAP=OFF -DCMAKE_CXX_FLAGS=-fdiagnostics-color=always -DCMAKE_BUILD_TYPE=' + build_type + ' ' + - (if build_type == 'Debug' then ' -DWARN_DEPRECATED=OFF ' else '') + + '-DWARN_DEPRECATED=OFF ' + (if werror then '-DWARNINGS_AS_ERRORS=ON ' else '') + '-DWITH_LTO=' + (if lto then 'ON ' else 'OFF ') + '-DWITH_TESTS=' + (if tests then 'ON ' else 'OFF ') + @@ -322,7 +329,7 @@ local mac_builder(name, 'ulimit -n 1024', // because macos sets ulimit to 256 for some reason yeah idk './contrib/mac-configure.sh ' + ci_dep_mirror(local_mirror) + - (if build_type == 'Debug' then ' -DWARN_DEPRECATED=OFF ' else '') + + '-DWARN_DEPRECATED=OFF ' + codesign, 'cd build-mac', // We can't use the 'package' target here because making a .dmg requires an active logged in @@ -372,29 +379,29 @@ local docs_pipeline(name, image, extra_cmds=[], allow_fail=false) = { 'echo "Building on ${DRONE_STAGE_MACHINE}"', apt_get_quiet + ' update', apt_get_quiet + ' install -y eatmydata', - 'eatmydata ' + apt_get_quiet + ' install --no-install-recommends -y git clang-format-14 jsonnet', + 'eatmydata ' + apt_get_quiet + ' install --no-install-recommends -y git clang-format-15 jsonnet', './contrib/ci/drone-format-verify.sh', ], }], }, // documentation builder - docs_pipeline('Documentation', - docker_base + 'docbuilder', - extra_cmds=['UPLOAD_OS=docs ./contrib/ci/drone-static-upload.sh']), + //docs_pipeline('Documentation', + // docker_base + 'docbuilder', + // extra_cmds=['UPLOAD_OS=docs ./contrib/ci/drone-static-upload.sh']), // Various debian builds debian_pipeline('Debian sid (amd64)', docker_base + 'debian-sid'), debian_pipeline('Debian sid/Debug (amd64)', docker_base + 'debian-sid', build_type='Debug'), - clang(13), - full_llvm(13), + clang(16), + full_llvm(16), debian_pipeline('Debian stable (i386)', docker_base + 'debian-stable/i386'), - debian_pipeline('Debian buster (amd64)', docker_base + 'debian-buster', extra_setup=local_gnutls(), cmake_extra='-DDOWNLOAD_SODIUM=ON'), + debian_pipeline('Debian buster (amd64)', docker_base + 'debian-buster', extra_setup=kitware_repo('bionic') + local_gnutls(), cmake_extra='-DDOWNLOAD_SODIUM=ON'), debian_pipeline('Ubuntu latest (amd64)', docker_base + 'ubuntu-rolling'), debian_pipeline('Ubuntu LTS (amd64)', docker_base + 'ubuntu-lts'), debian_pipeline('Ubuntu bionic (amd64)', docker_base + 'ubuntu-bionic', deps=['g++-8'] + default_deps_nocxx, - extra_setup=local_gnutls(), + extra_setup=kitware_repo('bionic') + local_gnutls(), cmake_extra='-DCMAKE_C_COMPILER=gcc-8 -DCMAKE_CXX_COMPILER=g++-8', oxen_repo=true), @@ -425,6 +432,7 @@ local docs_pipeline(name, image, extra_cmds=[], allow_fail=false) = { debian_pipeline('Static (bionic amd64)', docker_base + 'ubuntu-bionic', deps=['g++-8', 'python3-dev', 'automake', 'libtool'], + extra_setup=kitware_repo('bionic'), lto=true, tests=false, oxen_repo=true, @@ -442,6 +450,7 @@ local docs_pipeline(name, image, extra_cmds=[], allow_fail=false) = { docker_base + 'debian-buster/arm32v7', arch='arm64', deps=['g++', 'python3-dev', 'automake', 'libtool'], + extra_setup=kitware_repo('bionic'), cmake_extra='-DBUILD_STATIC_DEPS=ON -DBUILD_SHARED_LIBS=OFF -DSTATIC_LINK=ON ' + '-DCMAKE_CXX_FLAGS="-march=armv7-a+fp -Wno-psabi" -DCMAKE_C_FLAGS="-march=armv7-a+fp" ' + '-DNATIVE_BUILD=OFF -DWITH_SYSTEMD=OFF -DWITH_BOOTSTRAP=OFF', From 7ce517bd2d344d0ed4eed2b0e690fac8a89f5a56 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Wed, 13 Sep 2023 10:39:11 -0700 Subject: [PATCH 028/312] oxen-libquic update; no leak warn deprecated --- external/oxen-libquic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/oxen-libquic b/external/oxen-libquic index 1ec1addaa7..ef8d9c3130 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit 1ec1addaa7a402c94c7b2690e79635a364337d35 +Subproject commit ef8d9c31303c139577b642eab85e67213cf1b2d3 From 821cbeaacf0c8f226adb1e7236de65f7237c374e Mon Sep 17 00:00:00 2001 From: dr7ana Date: Wed, 13 Sep 2023 12:29:30 -0700 Subject: [PATCH 029/312] warnings_as_errors fixes --- llarp/quic/connection.cpp | 3 ++- llarp/quic/endpoint.cpp | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/llarp/quic/connection.cpp b/llarp/quic/connection.cpp index 6fef72a73a..27de0511f6 100644 --- a/llarp/quic/connection.cpp +++ b/llarp/quic/connection.cpp @@ -1171,7 +1171,8 @@ namespace llarp::quic int Connection::send_transport_params(ngtcp2_encryption_level level) { - ngtcp2_transport_params tparams = *ngtcp2_conn_get_local_transport_params(*this); + [[maybe_unused]] ngtcp2_transport_params tparams = + *ngtcp2_conn_get_local_transport_params(*this); assert(conn_buffer.empty()); conn_buffer.resize(Endpoint::max_pkt_size_v4); diff --git a/llarp/quic/endpoint.cpp b/llarp/quic/endpoint.cpp index 5a3da5b061..b96694e08c 100644 --- a/llarp/quic/endpoint.cpp +++ b/llarp/quic/endpoint.cpp @@ -220,7 +220,10 @@ namespace llarp::quic void Endpoint::close_connection( - Connection& conn, uint64_t code, bool application, std::string_view close_reason) + Connection& conn, + uint64_t code, + [[maybe_unused]] bool application, + std::string_view close_reason) { LogDebug("Closing connection ", conn.base_cid); if (!conn.closing) From 7f8207d5d375a0aa1019a6f4de7c322a0e39c8ee Mon Sep 17 00:00:00 2001 From: dr7ana Date: Wed, 13 Sep 2023 12:57:18 -0700 Subject: [PATCH 030/312] Nuked superfluous interface classes RIP: - i_link_manager - i_outbound_message_handler - i_gossiper - i_outbound_session_maker - i_rc_lookup_handler --- llarp/dht/context.cpp | 2 +- llarp/dht/messages/gotrouter.cpp | 2 +- llarp/dht/node.hpp | 93 ++- llarp/dht/recursiverouterlookup.cpp | 2 +- llarp/handlers/exit.cpp | 2 +- llarp/link/i_link_manager.hpp | 109 --- llarp/link/link_manager.cpp | 4 +- llarp/link/link_manager.hpp | 60 +- llarp/messages/relay_commit.cpp | 2 +- llarp/path/path.cpp | 2 +- llarp/path/path_context.cpp | 694 ++++++++++---------- llarp/path/path_context.hpp | 2 +- llarp/path/pathbuilder.cpp | 2 +- llarp/path/pathset.cpp | 3 +- llarp/path/transit_hop.cpp | 2 +- llarp/router/abstractrouter.hpp | 14 +- llarp/router/i_gossiper.hpp | 45 -- llarp/router/i_outbound_message_handler.hpp | 48 -- llarp/router/i_outbound_session_maker.hpp | 72 -- llarp/router/i_rc_lookup_handler.hpp | 81 --- llarp/router/outbound_message_handler.hpp | 33 +- llarp/router/outbound_session_maker.hpp | 52 +- llarp/router/rc_gossiper.cpp | 4 +- llarp/router/rc_gossiper.hpp | 32 +- llarp/router/rc_lookup_handler.cpp | 4 +- llarp/router/rc_lookup_handler.hpp | 58 +- llarp/router/router.hpp | 6 +- 27 files changed, 575 insertions(+), 855 deletions(-) delete mode 100644 llarp/link/i_link_manager.hpp delete mode 100644 llarp/router/i_gossiper.hpp delete mode 100644 llarp/router/i_outbound_message_handler.hpp delete mode 100644 llarp/router/i_outbound_session_maker.hpp delete mode 100644 llarp/router/i_rc_lookup_handler.hpp diff --git a/llarp/dht/context.cpp b/llarp/dht/context.cpp index 91931a8041..5bd9f7ad19 100644 --- a/llarp/dht/context.cpp +++ b/llarp/dht/context.cpp @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include diff --git a/llarp/dht/messages/gotrouter.cpp b/llarp/dht/messages/gotrouter.cpp index b42e9a51a7..040570bfb3 100644 --- a/llarp/dht/messages/gotrouter.cpp +++ b/llarp/dht/messages/gotrouter.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include namespace llarp::dht diff --git a/llarp/dht/node.hpp b/llarp/dht/node.hpp index ce4e124f13..0012298707 100644 --- a/llarp/dht/node.hpp +++ b/llarp/dht/node.hpp @@ -5,63 +5,60 @@ #include #include -namespace llarp +namespace llarp::dht { - namespace dht + struct RCNode { - struct RCNode - { - RouterContact rc; - Key_t ID; - - RCNode() - { - ID.Zero(); - } + RouterContact rc; + Key_t ID; - RCNode(const RouterContact& other) : rc(other), ID(other.pubkey) - {} + RCNode() + { + ID.Zero(); + } - util::StatusObject - ExtractStatus() const - { - return rc.ExtractStatus(); - } + RCNode(const RouterContact& other) : rc(other), ID(other.pubkey) + {} - bool - operator<(const RCNode& other) const - { - return rc.last_updated < other.rc.last_updated; - } - }; + util::StatusObject + ExtractStatus() const + { + return rc.ExtractStatus(); + } - struct ISNode + bool + operator<(const RCNode& other) const { - service::EncryptedIntroSet introset; + return rc.last_updated < other.rc.last_updated; + } + }; + + struct ISNode + { + service::EncryptedIntroSet introset; - Key_t ID; + Key_t ID; - ISNode() - { - ID.Zero(); - } + ISNode() + { + ID.Zero(); + } - ISNode(service::EncryptedIntroSet other) : introset(std::move(other)) - { - ID = Key_t(introset.derivedSigningKey.as_array()); - } + ISNode(service::EncryptedIntroSet other) : introset(std::move(other)) + { + ID = Key_t(introset.derivedSigningKey.as_array()); + } - util::StatusObject - ExtractStatus() const - { - return introset.ExtractStatus(); - } + util::StatusObject + ExtractStatus() const + { + return introset.ExtractStatus(); + } - bool - operator<(const ISNode& other) const - { - return introset.signedAt < other.introset.signedAt; - } - }; - } // namespace dht -} // namespace llarp + bool + operator<(const ISNode& other) const + { + return introset.signedAt < other.introset.signedAt; + } + }; +} // namespace llarp::dht diff --git a/llarp/dht/recursiverouterlookup.cpp b/llarp/dht/recursiverouterlookup.cpp index e0828b1511..d1812e7b44 100644 --- a/llarp/dht/recursiverouterlookup.cpp +++ b/llarp/dht/recursiverouterlookup.cpp @@ -5,7 +5,7 @@ #include #include -#include +#include #include diff --git a/llarp/handlers/exit.cpp b/llarp/handlers/exit.cpp index a7840c0904..02f898b112 100644 --- a/llarp/handlers/exit.cpp +++ b/llarp/handlers/exit.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include diff --git a/llarp/link/i_link_manager.hpp b/llarp/link/i_link_manager.hpp deleted file mode 100644 index 27f77e3771..0000000000 --- a/llarp/link/i_link_manager.hpp +++ /dev/null @@ -1,109 +0,0 @@ -#pragma once - -#include "endpoint.hpp" -#include "server.hpp" - -#include -#include - -#include -#include - -struct llarp_buffer_t; - -namespace llarp -{ - - // TODO: do we still want this? - enum class SessionResult - { - Establish, - Timeout, - RouterNotFound, - InvalidRouter, - NoLink, - EstablishFail - }; - - constexpr std::string_view - ToString(SessionResult sr) - { - return sr == llarp::SessionResult::Establish ? "success"sv - : sr == llarp::SessionResult::Timeout ? "timeout"sv - : sr == llarp::SessionResult::NoLink ? "no link"sv - : sr == llarp::SessionResult::InvalidRouter ? "invalid router"sv - : sr == llarp::SessionResult::RouterNotFound ? "not found"sv - : sr == llarp::SessionResult::EstablishFail ? "establish failed"sv - : "???"sv; - } - template <> - constexpr inline bool IsToStringFormattable = true; - - struct RouterContact; - struct AbstractLinkSession; - struct IOutboundSessionMaker; - struct RouterID; - - struct ILinkManager - { - virtual ~ILinkManager() = default; - - virtual bool - SendTo( - const RouterID& remote, - const llarp_buffer_t& buf, - AbstractLinkSession::CompletionHandler completed, - uint16_t priority = 0) = 0; - - virtual bool - HaveConnection(const RouterID& remote, bool client_only = false) const = 0; - - /// return true if we have a connection to the remote and it is not a relay, - /// else return false - virtual bool - HaveClientConnection(const RouterID& remote) const = 0; - - virtual void - Stop() = 0; - - virtual void - PersistSessionUntil(const RouterID& remote, llarp_time_t until) = 0; - - /// close all connections to this peer - /// remove all link layer commits - virtual void - DeregisterPeer(RouterID remote) = 0; - - virtual size_t - NumberOfConnectedRouters(bool clients_only = false) const = 0; - - virtual size_t - NumberOfConnectedClients() const = 0; - - virtual bool - GetRandomConnectedRouter(RouterContact& router) const = 0; - - virtual void - CheckPersistingSessions(llarp_time_t now) = 0; - - virtual void - updatePeerDb(std::shared_ptr peerDb) = 0; - - virtual util::StatusObject - ExtractStatus() const = 0; - - // Do an RC lookup for the given RouterID; the result will trigger - // Connect(RouterContact) on success (or if we already have it), and will - // trigger connection failure callback on lookup failure. - virtual void - Connect(RouterID router) = 0; - - // Establish a connection to the remote `rc`. - // - // Connection established/failed callbacks should be invoked when either happens, - // but this function should do nothing if already connected. - virtual void - Connect(RouterContact rc) = 0; - }; - -} // namespace llarp diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 0f3906eda7..1add168b35 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1,6 +1,6 @@ #include "link_manager.hpp" -#include +#include #include #include @@ -218,7 +218,7 @@ namespace llarp } void - LinkManager::Init(I_RCLookupHandler* rcLookup) + LinkManager::Init(RCLookupHandler* rcLookup) { stopping = false; _rcLookup = rcLookup; diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 6aafa593dc..980193ae7d 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -1,7 +1,5 @@ #pragma once -#include "i_link_manager.hpp" - #include #include "server.hpp" #include "endpoint.hpp" @@ -14,9 +12,31 @@ namespace llarp { - struct IRouterContactManager; + enum class SessionResult + { + Establish, + Timeout, + RouterNotFound, + InvalidRouter, + NoLink, + EstablishFail + }; - struct LinkManager final : public ILinkManager + constexpr std::string_view + ToString(SessionResult sr) + { + return sr == llarp::SessionResult::Establish ? "success"sv + : sr == llarp::SessionResult::Timeout ? "timeout"sv + : sr == llarp::SessionResult::NoLink ? "no link"sv + : sr == llarp::SessionResult::InvalidRouter ? "invalid router"sv + : sr == llarp::SessionResult::RouterNotFound ? "not found"sv + : sr == llarp::SessionResult::EstablishFail ? "establish failed"sv + : "???"sv; + } + template <> + constexpr inline bool IsToStringFormattable = true; + + struct LinkManager { public: explicit LinkManager(AbstractRouter* r) : router{r} @@ -27,52 +47,52 @@ namespace llarp const RouterID& remote, const llarp_buffer_t& buf, AbstractLinkSession::CompletionHandler completed, - uint16_t priority) override; + uint16_t priority); bool - HaveConnection(const RouterID& remote, bool client_only = false) const override; + HaveConnection(const RouterID& remote, bool client_only = false) const; bool - HaveClientConnection(const RouterID& remote) const override; + HaveClientConnection(const RouterID& remote) const; void - DeregisterPeer(RouterID remote) override; + DeregisterPeer(RouterID remote); void AddLink(const oxen::quic::opt::local_addr& bind, bool inbound = false); void - Stop() override; + Stop(); void - PersistSessionUntil(const RouterID& remote, llarp_time_t until) override; + PersistSessionUntil(const RouterID& remote, llarp_time_t until); size_t - NumberOfConnectedRouters(bool clients_only = false) const override; + NumberOfConnectedRouters(bool clients_only = false) const; size_t - NumberOfConnectedClients() const override; + NumberOfConnectedClients() const; bool - GetRandomConnectedRouter(RouterContact& router) const override; + GetRandomConnectedRouter(RouterContact& router) const; void - CheckPersistingSessions(llarp_time_t now) override; + CheckPersistingSessions(llarp_time_t now); void - updatePeerDb(std::shared_ptr peerDb) override; + updatePeerDb(std::shared_ptr peerDb); util::StatusObject - ExtractStatus() const override; + ExtractStatus() const; void - Init(I_RCLookupHandler* rcLookup); + Init(RCLookupHandler* rcLookup); void - Connect(RouterID router) override; + Connect(RouterID router); void - Connect(RouterContact rc) override; + Connect(RouterContact rc); // Attempts to connect to a number of random routers. // @@ -102,7 +122,7 @@ namespace llarp util::DecayingHashSet m_Clients{path::default_lifetime}; - I_RCLookupHandler* _rcLookup; + RCLookupHandler* _rcLookup; std::shared_ptr _nodedb; AbstractRouter* router; diff --git a/llarp/messages/relay_commit.cpp b/llarp/messages/relay_commit.cpp index f8810fdac0..e93475d205 100644 --- a/llarp/messages/relay_commit.cpp +++ b/llarp/messages/relay_commit.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 3103c2bf6f..c0d188ccb2 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include #include diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index 7bb5223b0a..82bb0e63dc 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -1,419 +1,417 @@ +#include "path.hpp" #include "path_context.hpp" +#include #include -#include "path.hpp" #include -#include +#include -namespace llarp +namespace llarp::path { - namespace path - { - static constexpr auto DefaultPathBuildLimit = 500ms; + static constexpr auto DefaultPathBuildLimit = 500ms; - PathContext::PathContext(AbstractRouter* router) - : m_Router(router), m_AllowTransit(false), m_PathLimits(DefaultPathBuildLimit) - {} + PathContext::PathContext(AbstractRouter* router) + : m_Router(router), m_AllowTransit(false), m_PathLimits(DefaultPathBuildLimit) + {} - void - PathContext::AllowTransit() - { - m_AllowTransit = true; - } + void + PathContext::AllowTransit() + { + m_AllowTransit = true; + } - bool - PathContext::AllowingTransit() const - { - return m_AllowTransit; - } + bool + PathContext::AllowingTransit() const + { + return m_AllowTransit; + } - bool - PathContext::CheckPathLimitHitByIP(const IpAddress& ip) - { + bool + PathContext::CheckPathLimitHitByIP(const IpAddress& ip) + { #ifdef TESTNET - return false; + 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 m_PathLimits.Insert(remote); + 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 m_PathLimits.Insert(remote); #endif - } - - const EventLoop_ptr& - PathContext::loop() - { - return m_Router->loop(); - } + } - const SecretKey& - PathContext::EncryptionSecretKey() - { - return m_Router->encryption(); - } + const EventLoop_ptr& + PathContext::loop() + { + return m_Router->loop(); + } - bool - PathContext::HopIsUs(const RouterID& k) const - { - return std::equal(m_Router->pubkey(), m_Router->pubkey() + PUBKEYSIZE, k.begin()); - } + const SecretKey& + PathContext::EncryptionSecretKey() + { + return m_Router->encryption(); + } - PathContext::EndpointPathPtrSet - PathContext::FindOwnedPathsWithEndpoint(const RouterID& r) - { - EndpointPathPtrSet found; - m_OurPaths.ForEach([&](const Path_ptr& p) { - if (p->Endpoint() == r && p->IsReady()) - found.insert(p); - }); - return found; - } + bool + PathContext::HopIsUs(const RouterID& k) const + { + return std::equal(m_Router->pubkey(), m_Router->pubkey() + PUBKEYSIZE, k.begin()); + } - bool - PathContext::ForwardLRCM( - const RouterID& nextHop, - const std::array& frames, - SendStatusHandler handler) + PathContext::EndpointPathPtrSet + PathContext::FindOwnedPathsWithEndpoint(const RouterID& r) + { + EndpointPathPtrSet found; + m_OurPaths.ForEach([&](const Path_ptr& p) { + if (p->Endpoint() == r && p->IsReady()) + found.insert(p); + }); + return found; + } + + bool + PathContext::ForwardLRCM( + const RouterID& nextHop, + const std::array& frames, + SendStatusHandler handler) + { + if (handler == nullptr) { - if (handler == nullptr) - { - LogError("Calling ForwardLRCM without passing result handler"); - return false; - } - - const LR_CommitMessage msg{frames}; - - LogDebug("forwarding LRCM to ", nextHop); - - return m_Router->SendToOrQueue(nextHop, msg, handler); + LogError("Calling ForwardLRCM without passing result handler"); + return false; } - template < - typename Lock_t, - typename Map_t, - typename Key_t, - typename CheckValue_t, - typename GetFunc_t, - typename Return_ptr = HopHandler_ptr> - Return_ptr - MapGet(Map_t& map, const Key_t& k, CheckValue_t check, GetFunc_t get) - { - Lock_t lock(map.first); - auto range = map.second.equal_range(k); - for (auto i = range.first; i != range.second; ++i) - { - if (check(i->second)) - return get(i->second); - } - return nullptr; - } + const LR_CommitMessage msg{frames}; - template - bool - MapHas(Map_t& map, const Key_t& k, CheckValue_t check) - { - Lock_t lock(map.first); - auto range = map.second.equal_range(k); - for (auto i = range.first; i != range.second; ++i) - { - if (check(i->second)) - return true; - } - return false; - } + LogDebug("forwarding LRCM to ", nextHop); - template - void - MapPut(Map_t& map, const Key_t& k, const Value_t& v) - { - Lock_t lock(map.first); - map.second.emplace(k, v); - } + return m_Router->SendToOrQueue(nextHop, msg, handler); + } - template - void - MapIter(Map_t& map, Visit_t v) + template < + typename Lock_t, + typename Map_t, + typename Key_t, + typename CheckValue_t, + typename GetFunc_t, + typename Return_ptr = HopHandler_ptr> + Return_ptr + MapGet(Map_t& map, const Key_t& k, CheckValue_t check, GetFunc_t get) + { + Lock_t lock(map.first); + auto range = map.second.equal_range(k); + for (auto i = range.first; i != range.second; ++i) { - Lock_t lock(map.first); - for (const auto& item : map.second) - v(item); + if (check(i->second)) + return get(i->second); } + return nullptr; + } - template - void - MapDel(Map_t& map, const Key_t& k, Check_t check) + template + bool + MapHas(Map_t& map, const Key_t& k, CheckValue_t check) + { + Lock_t lock(map.first); + auto range = map.second.equal_range(k); + for (auto i = range.first; i != range.second; ++i) { - Lock_t lock(map.first); - auto range = map.second.equal_range(k); - for (auto i = range.first; i != range.second;) - { - if (check(i->second)) - i = map.second.erase(i); - else - ++i; - } + if (check(i->second)) + return true; } + return false; + } - void - PathContext::AddOwnPath(PathSet_ptr set, Path_ptr path) - { - set->AddPath(path); - MapPut(m_OurPaths, path->TXID(), path); - MapPut(m_OurPaths, path->RXID(), path); - } + template + void + MapPut(Map_t& map, const Key_t& k, const Value_t& v) + { + Lock_t lock(map.first); + map.second.emplace(k, v); + } - bool - PathContext::HasTransitHop(const TransitHopInfo& info) + template + void + MapIter(Map_t& map, Visit_t v) + { + Lock_t lock(map.first); + for (const auto& item : map.second) + v(item); + } + + template + void + MapDel(Map_t& map, const Key_t& k, Check_t check) + { + Lock_t lock(map.first); + auto range = map.second.equal_range(k); + for (auto i = range.first; i != range.second;) { - return MapHas( - m_TransitPaths, info.txID, [info](const std::shared_ptr& hop) -> bool { - return info == hop->info; - }); + if (check(i->second)) + i = map.second.erase(i); + else + ++i; } + } - std::optional> - PathContext::TransitHopByInfo(const TransitHopInfo& info) - { - // this is ugly as sin - auto own = MapGet< - SyncTransitMap_t::Lock_t, - decltype(m_TransitPaths), - PathID_t, - std::function&)>, - std::function&)>, - TransitHop*>( - m_TransitPaths, - info.txID, - [info](const auto& hop) -> bool { return hop->info == info; }, - [](const auto& hop) -> TransitHop* { return hop.get(); }); - if (own) - return own->weak_from_this(); - return std::nullopt; - } + void + PathContext::AddOwnPath(PathSet_ptr set, Path_ptr path) + { + set->AddPath(path); + MapPut(m_OurPaths, path->TXID(), path); + MapPut(m_OurPaths, path->RXID(), path); + } - std::optional> - PathContext::TransitHopByUpstream(const RouterID& upstream, const PathID_t& id) - { - // this is ugly as sin as well - auto own = MapGet< - SyncTransitMap_t::Lock_t, - decltype(m_TransitPaths), - PathID_t, - std::function&)>, - std::function&)>, - TransitHop*>( - m_TransitPaths, - id, - [upstream](const auto& hop) -> bool { return hop->info.upstream == upstream; }, - [](const auto& hop) -> TransitHop* { return hop.get(); }); - if (own) - return own->weak_from_this(); - return std::nullopt; - } + bool + PathContext::HasTransitHop(const TransitHopInfo& info) + { + return MapHas( + m_TransitPaths, info.txID, [info](const std::shared_ptr& hop) -> bool { + return info == hop->info; + }); + } + + std::optional> + PathContext::TransitHopByInfo(const TransitHopInfo& info) + { + // this is ugly as sin + auto own = MapGet< + SyncTransitMap_t::Lock_t, + decltype(m_TransitPaths), + PathID_t, + std::function&)>, + std::function&)>, + TransitHop*>( + m_TransitPaths, + info.txID, + [info](const auto& hop) -> bool { return hop->info == info; }, + [](const auto& hop) -> TransitHop* { return hop.get(); }); + if (own) + return own->weak_from_this(); + return std::nullopt; + } + + std::optional> + PathContext::TransitHopByUpstream(const RouterID& upstream, const PathID_t& id) + { + // this is ugly as sin as well + auto own = MapGet< + SyncTransitMap_t::Lock_t, + decltype(m_TransitPaths), + PathID_t, + std::function&)>, + std::function&)>, + TransitHop*>( + m_TransitPaths, + id, + [upstream](const auto& hop) -> bool { return hop->info.upstream == upstream; }, + [](const auto& hop) -> TransitHop* { return hop.get(); }); + if (own) + return own->weak_from_this(); + return std::nullopt; + } + + HopHandler_ptr + PathContext::GetByUpstream(const RouterID& remote, const PathID_t& id) + { + auto own = MapGet( + m_OurPaths, + id, + [](const Path_ptr) -> bool { + // TODO: is this right? + return true; + }, + [](Path_ptr p) -> HopHandler_ptr { return p; }); + if (own) + return own; + + return MapGet( + m_TransitPaths, + id, + [remote](const std::shared_ptr& hop) -> bool { + return hop->info.upstream == remote; + }, + [](const std::shared_ptr& h) -> HopHandler_ptr { return h; }); + } + + bool + PathContext::TransitHopPreviousIsRouter(const PathID_t& path, const RouterID& otherRouter) + { + SyncTransitMap_t::Lock_t lock(m_TransitPaths.first); + auto itr = m_TransitPaths.second.find(path); + if (itr == m_TransitPaths.second.end()) + return false; + return itr->second->info.downstream == otherRouter; + } - HopHandler_ptr - PathContext::GetByUpstream(const RouterID& remote, const PathID_t& id) + HopHandler_ptr + PathContext::GetByDownstream(const RouterID& remote, const PathID_t& id) + { + return MapGet( + m_TransitPaths, + id, + [remote](const std::shared_ptr& hop) -> bool { + return hop->info.downstream == remote; + }, + [](const std::shared_ptr& h) -> HopHandler_ptr { return h; }); + } + + PathSet_ptr + PathContext::GetLocalPathSet(const PathID_t& id) + { + auto& map = m_OurPaths; + util::Lock lock(map.first); + auto itr = map.second.find(id); + if (itr != map.second.end()) { - auto own = MapGet( - m_OurPaths, - id, - [](const Path_ptr) -> bool { - // TODO: is this right? - return true; - }, - [](Path_ptr p) -> HopHandler_ptr { return p; }); - if (own) - return own; - - return MapGet( - m_TransitPaths, - id, - [remote](const std::shared_ptr& hop) -> bool { - return hop->info.upstream == remote; - }, - [](const std::shared_ptr& h) -> HopHandler_ptr { return h; }); + if (auto parent = itr->second->m_PathSet.lock()) + return parent; } + return nullptr; + } - bool - PathContext::TransitHopPreviousIsRouter(const PathID_t& path, const RouterID& otherRouter) - { - SyncTransitMap_t::Lock_t lock(m_TransitPaths.first); - auto itr = m_TransitPaths.second.find(path); - if (itr == m_TransitPaths.second.end()) - return false; - return itr->second->info.downstream == otherRouter; - } + const byte_t* + PathContext::OurRouterID() const + { + return m_Router->pubkey(); + } - HopHandler_ptr - PathContext::GetByDownstream(const RouterID& remote, const PathID_t& id) - { - return MapGet( - m_TransitPaths, - id, - [remote](const std::shared_ptr& hop) -> bool { - return hop->info.downstream == remote; - }, - [](const std::shared_ptr& h) -> HopHandler_ptr { return h; }); - } + AbstractRouter* + PathContext::Router() + { + return m_Router; + } - PathSet_ptr - PathContext::GetLocalPathSet(const PathID_t& id) + TransitHop_ptr + PathContext::GetPathForTransfer(const PathID_t& id) + { + const RouterID us(OurRouterID()); + auto& map = m_TransitPaths; { - auto& map = m_OurPaths; - util::Lock lock(map.first); - auto itr = map.second.find(id); - if (itr != map.second.end()) + SyncTransitMap_t::Lock_t lock(map.first); + auto range = map.second.equal_range(id); + for (auto i = range.first; i != range.second; ++i) { - if (auto parent = itr->second->m_PathSet.lock()) - return parent; + if (i->second->info.upstream == us) + return i->second; } - return nullptr; } + return nullptr; + } - const byte_t* - PathContext::OurRouterID() const - { - return m_Router->pubkey(); - } + void + PathContext::PumpUpstream() + { + m_TransitPaths.ForEach([&](auto& ptr) { ptr->FlushUpstream(m_Router); }); + m_OurPaths.ForEach([&](auto& ptr) { ptr->FlushUpstream(m_Router); }); + } - AbstractRouter* - PathContext::Router() - { - return m_Router; - } + void + PathContext::PumpDownstream() + { + m_TransitPaths.ForEach([&](auto& ptr) { ptr->FlushDownstream(m_Router); }); + m_OurPaths.ForEach([&](auto& ptr) { ptr->FlushDownstream(m_Router); }); + } - TransitHop_ptr - PathContext::GetPathForTransfer(const PathID_t& id) - { - const RouterID us(OurRouterID()); - auto& map = m_TransitPaths; - { - SyncTransitMap_t::Lock_t lock(map.first); - auto range = map.second.equal_range(id); - for (auto i = range.first; i != range.second; ++i) - { - if (i->second->info.upstream == us) - return i->second; - } - } - return nullptr; - } + uint64_t + PathContext::CurrentTransitPaths() + { + SyncTransitMap_t::Lock_t lock(m_TransitPaths.first); + const auto& map = m_TransitPaths.second; + return map.size() / 2; + } - void - PathContext::PumpUpstream() + uint64_t + PathContext::CurrentOwnedPaths(path::PathStatus st) + { + uint64_t num{}; + util::Lock lock{m_OurPaths.first}; + auto& map = m_OurPaths.second; + for (auto itr = map.begin(); itr != map.end(); ++itr) { - m_TransitPaths.ForEach([&](auto& ptr) { ptr->FlushUpstream(m_Router); }); - m_OurPaths.ForEach([&](auto& ptr) { ptr->FlushUpstream(m_Router); }); + if (itr->second->Status() == st) + num++; } + return num / 2; + } - void - PathContext::PumpDownstream() - { - m_TransitPaths.ForEach([&](auto& ptr) { ptr->FlushDownstream(m_Router); }); - m_OurPaths.ForEach([&](auto& ptr) { ptr->FlushDownstream(m_Router); }); - } + void + PathContext::PutTransitHop(std::shared_ptr hop) + { + MapPut(m_TransitPaths, hop->info.txID, hop); + MapPut(m_TransitPaths, hop->info.rxID, hop); + } - uint64_t - PathContext::CurrentTransitPaths() - { - SyncTransitMap_t::Lock_t lock(m_TransitPaths.first); - const auto& map = m_TransitPaths.second; - return map.size() / 2; - } + void + PathContext::ExpirePaths(llarp_time_t now) + { + // decay limits + m_PathLimits.Decay(now); - uint64_t - PathContext::CurrentOwnedPaths(path::PathStatus st) { - uint64_t num{}; - util::Lock lock{m_OurPaths.first}; - auto& map = m_OurPaths.second; - for (auto itr = map.begin(); itr != map.end(); ++itr) + SyncTransitMap_t::Lock_t lock(m_TransitPaths.first); + auto& map = m_TransitPaths.second; + auto itr = map.begin(); + while (itr != map.end()) { - if (itr->second->Status() == st) - num++; + if (itr->second->Expired(now)) + { + m_Router->outboundMessageHandler().RemovePath(itr->first); + itr = map.erase(itr); + } + else + { + itr->second->DecayFilters(now); + ++itr; + } } - return num / 2; } - - void - PathContext::PutTransitHop(std::shared_ptr hop) { - MapPut(m_TransitPaths, hop->info.txID, hop); - MapPut(m_TransitPaths, hop->info.rxID, hop); - } - - void - PathContext::ExpirePaths(llarp_time_t now) - { - // decay limits - m_PathLimits.Decay(now); - + util::Lock lock(m_OurPaths.first); + auto& map = m_OurPaths.second; + auto itr = map.begin(); + while (itr != map.end()) { - SyncTransitMap_t::Lock_t lock(m_TransitPaths.first); - auto& map = m_TransitPaths.second; - auto itr = map.begin(); - while (itr != map.end()) + if (itr->second->Expired(now)) { - if (itr->second->Expired(now)) - { - m_Router->outboundMessageHandler().RemovePath(itr->first); - itr = map.erase(itr); - } - else - { - itr->second->DecayFilters(now); - ++itr; - } + itr = map.erase(itr); } - } - { - util::Lock lock(m_OurPaths.first); - auto& map = m_OurPaths.second; - auto itr = map.begin(); - while (itr != map.end()) + else { - if (itr->second->Expired(now)) - { - itr = map.erase(itr); - } - else - { - itr->second->DecayFilters(now); - ++itr; - } + itr->second->DecayFilters(now); + ++itr; } } } + } - routing::MessageHandler_ptr - PathContext::GetHandler(const PathID_t& id) + routing::MessageHandler_ptr + PathContext::GetHandler(const PathID_t& id) + { + routing::MessageHandler_ptr h = nullptr; + auto pathset = GetLocalPathSet(id); + if (pathset) { - routing::MessageHandler_ptr h = nullptr; - auto pathset = GetLocalPathSet(id); - if (pathset) - { - h = pathset->GetPathByID(id); - } - if (h) - return h; - const RouterID us(OurRouterID()); - auto& map = m_TransitPaths; + h = pathset->GetPathByID(id); + } + if (h) + return h; + const RouterID us(OurRouterID()); + auto& map = m_TransitPaths; + { + SyncTransitMap_t::Lock_t lock(map.first); + auto range = map.second.equal_range(id); + for (auto i = range.first; i != range.second; ++i) { - SyncTransitMap_t::Lock_t lock(map.first); - auto range = map.second.equal_range(id); - for (auto i = range.first; i != range.second; ++i) - { - if (i->second->info.upstream == us) - return i->second; - } + if (i->second->info.upstream == us) + return i->second; } - return nullptr; } + return nullptr; + } - void - PathContext::RemovePathSet(PathSet_ptr) - {} - } // namespace path -} // namespace llarp + void + PathContext::RemovePathSet(PathSet_ptr) + {} +} // namespace llarp::path diff --git a/llarp/path/path_context.hpp b/llarp/path/path_context.hpp index af5b9e175c..621e4629e5 100644 --- a/llarp/path/path_context.hpp +++ b/llarp/path/path_context.hpp @@ -7,7 +7,7 @@ #include "pathset.hpp" #include "transit_hop.hpp" #include -#include +#include #include #include #include diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index 63fe3f87b4..d3c565a68b 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/llarp/path/pathset.cpp b/llarp/path/pathset.cpp index e47a762004..1f15c3fd79 100644 --- a/llarp/path/pathset.cpp +++ b/llarp/path/pathset.cpp @@ -1,7 +1,8 @@ +#include "path.hpp" #include "pathset.hpp" +#include #include -#include "path.hpp" #include #include diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index 23cc483ef5..c990200238 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/llarp/router/abstractrouter.hpp b/llarp/router/abstractrouter.hpp index 0e907e8b3e..109e265fe3 100644 --- a/llarp/router/abstractrouter.hpp +++ b/llarp/router/abstractrouter.hpp @@ -5,7 +5,7 @@ #include #include #include -#include "i_outbound_message_handler.hpp" +#include "outbound_message_handler.hpp" #include #include #include @@ -39,9 +39,9 @@ namespace llarp struct Profiling; struct SecretKey; struct Signature; - struct IOutboundMessageHandler; - struct ILinkManager; - struct I_RCLookupHandler; + struct OutboundMessageHandler; + struct LinkManager; + struct RCLookupHandler; struct RoutePoker; namespace dht @@ -176,16 +176,16 @@ namespace llarp virtual const service::Context& hiddenServiceContext() const = 0; - virtual IOutboundMessageHandler& + virtual OutboundMessageHandler& outboundMessageHandler() = 0; - virtual ILinkManager& + virtual LinkManager& linkManager() = 0; virtual const std::shared_ptr& routePoker() const = 0; - virtual I_RCLookupHandler& + virtual RCLookupHandler& rcLookupHandler() = 0; virtual std::shared_ptr diff --git a/llarp/router/i_gossiper.hpp b/llarp/router/i_gossiper.hpp deleted file mode 100644 index c0d6fd51fe..0000000000 --- a/llarp/router/i_gossiper.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once -#include -#include -#include - -namespace llarp -{ - /// The maximum number of peers we will flood a gossiped RC to when propagating an RC - constexpr size_t MaxGossipPeers = 20; - - struct I_RCGossiper - { - virtual ~I_RCGossiper() = default; - /// try goissping RC - /// return false if we hit a cooldown for this rc - /// return true if we gossiped this rc to at least 1 peer - virtual bool - GossipRC(const RouterContact& rc) = 0; - - using Time_t = Duration_t; - - virtual void - Decay(Time_t now) = 0; - - /// return true if we should gossip our RC now - virtual bool - ShouldGossipOurRC(Time_t now) const = 0; - - /// return true if that rc is owned by us - virtual bool - IsOurRC(const RouterContact& rc) const = 0; - - /// forget the replay filter entry given pubkey - virtual void - Forget(const RouterID& router) = 0; - - /// returns the time point when we will send our next gossip at - virtual TimePoint_t - NextGossipAt() const = 0; - - /// returns the time point when we sent our last gossip at or nullopt if we never did - virtual std::optional - LastGossipAt() const = 0; - }; -} // namespace llarp diff --git a/llarp/router/i_outbound_message_handler.hpp b/llarp/router/i_outbound_message_handler.hpp deleted file mode 100644 index 3782493222..0000000000 --- a/llarp/router/i_outbound_message_handler.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include - -#include -#include - -namespace llarp -{ - enum class SendStatus - { - Success, - Timeout, - NoLink, - InvalidRouter, - RouterNotFound, - Congestion - }; - - struct AbstractLinkMessage; - struct RouterID; - struct PathID_t; - - using SendStatusHandler = std::function; - - static const size_t MAX_PATH_QUEUE_SIZE = 100; - static const size_t MAX_OUTBOUND_QUEUE_SIZE = 1000; - static const size_t MAX_OUTBOUND_MESSAGES_PER_TICK = 500; - - struct IOutboundMessageHandler - { - virtual ~IOutboundMessageHandler() = default; - - virtual bool - QueueMessage( - const RouterID& remote, const AbstractLinkMessage& msg, SendStatusHandler callback) = 0; - - virtual void - Pump() = 0; - - virtual void - RemovePath(const PathID_t& pathid) = 0; - - virtual util::StatusObject - ExtractStatus() const = 0; - }; - -} // namespace llarp diff --git a/llarp/router/i_outbound_session_maker.hpp b/llarp/router/i_outbound_session_maker.hpp deleted file mode 100644 index 6c77fa0f22..0000000000 --- a/llarp/router/i_outbound_session_maker.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#pragma once - -#include -#include -#include - -#include - -#include - -namespace llarp -{ - struct AbstractLinkSession; - struct RouterID; - struct RouterContact; - - enum class SessionResult - { - Establish, - Timeout, - RouterNotFound, - InvalidRouter, - NoLink, - EstablishFail - }; - - constexpr std::string_view - ToString(SessionResult sr) - { - return sr == llarp::SessionResult::Establish ? "success"sv - : sr == llarp::SessionResult::Timeout ? "timeout"sv - : sr == llarp::SessionResult::NoLink ? "no link"sv - : sr == llarp::SessionResult::InvalidRouter ? "invalid router"sv - : sr == llarp::SessionResult::RouterNotFound ? "not found"sv - : sr == llarp::SessionResult::EstablishFail ? "establish failed"sv - : "???"sv; - } - template <> - constexpr inline bool IsToStringFormattable = true; - - using RouterCallback = std::function; - - struct IOutboundSessionMaker - { - virtual ~IOutboundSessionMaker() = default; - - virtual bool - OnSessionEstablished(AbstractLinkSession* session) = 0; - - virtual void - OnConnectTimeout(AbstractLinkSession* session) = 0; - - virtual void - CreateSessionTo(const RouterID& router, RouterCallback on_result) = 0; - - virtual void - CreateSessionTo(const RouterContact& rc, RouterCallback on_result) = 0; - - virtual bool - HavePendingSessionTo(const RouterID& router) const = 0; - - virtual void - ConnectToRandomRouters(int numDesired) = 0; - - virtual util::StatusObject - ExtractStatus() const = 0; - - virtual bool - ShouldConnectTo(const RouterID& router) const = 0; - }; - -} // namespace llarp diff --git a/llarp/router/i_rc_lookup_handler.hpp b/llarp/router/i_rc_lookup_handler.hpp deleted file mode 100644 index 4efee04c69..0000000000 --- a/llarp/router/i_rc_lookup_handler.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once - -#include -#include - -#include -#include -#include - -namespace llarp -{ - struct RouterContact; - - enum class RCRequestResult - { - Success, - InvalidRouter, - RouterNotFound, - BadRC - }; - - using RCRequestCallback = - std::function; - - struct I_RCLookupHandler - { - virtual ~I_RCLookupHandler() = default; - - virtual void - AddValidRouter(const RouterID& router) = 0; - - virtual void - RemoveValidRouter(const RouterID& router) = 0; - - virtual void - SetRouterWhitelist( - const std::vector& whitelist, - const std::vector& greylist, - const std::vector& greenlist) = 0; - - virtual void - GetRC(const RouterID& router, RCRequestCallback callback, bool forceLookup = false) = 0; - - virtual bool - PathIsAllowed(const RouterID& remote) const = 0; - - virtual bool - SessionIsAllowed(const RouterID& remote) const = 0; - - virtual bool - IsGreylisted(const RouterID& remote) const = 0; - - virtual bool - IsGreenlisted(const RouterID& remote) const = 0; - - virtual bool - IsRegistered(const RouterID& remote) const = 0; - - virtual bool - CheckRC(const RouterContact& rc) const = 0; - - virtual bool - GetRandomWhitelistRouter(RouterID& router) const = 0; - - virtual bool - CheckRenegotiateValid(RouterContact newrc, RouterContact oldrc) = 0; - - virtual void - PeriodicUpdate(llarp_time_t now) = 0; - - virtual void - ExploreNetwork() = 0; - - virtual size_t - NumberOfStrictConnectRouters() const = 0; - - virtual bool - HaveReceivedWhitelist() const = 0; - }; - -} // namespace llarp diff --git a/llarp/router/outbound_message_handler.hpp b/llarp/router/outbound_message_handler.hpp index 0634b33fbb..a71c6849f3 100644 --- a/llarp/router/outbound_message_handler.hpp +++ b/llarp/router/outbound_message_handler.hpp @@ -1,7 +1,5 @@ #pragma once -#include "i_outbound_message_handler.hpp" - #include #include #include @@ -17,13 +15,32 @@ struct llarp_buffer_t; namespace llarp { + enum class SendStatus + { + Success, + Timeout, + NoLink, + InvalidRouter, + RouterNotFound, + Congestion + }; + struct AbstractRouter; enum class SessionResult; + struct AbstractLinkMessage; + struct RouterID; + struct PathID_t; + + static const size_t MAX_PATH_QUEUE_SIZE = 100; + static const size_t MAX_OUTBOUND_QUEUE_SIZE = 1000; + static const size_t MAX_OUTBOUND_MESSAGES_PER_TICK = 500; + + using SendStatusHandler = std::function; - struct OutboundMessageHandler final : public IOutboundMessageHandler + struct OutboundMessageHandler final { public: - ~OutboundMessageHandler() override = default; + ~OutboundMessageHandler() = default; OutboundMessageHandler(size_t maxQueueSize = MAX_OUTBOUND_QUEUE_SIZE); @@ -45,7 +62,7 @@ namespace llarp */ bool QueueMessage(const RouterID& remote, const AbstractLinkMessage& msg, SendStatusHandler callback) - override EXCLUDES(_mutex); + EXCLUDES(_mutex); /* Called when pumping output queues, typically scheduled via a call to Router::TriggerPump(). * @@ -59,16 +76,16 @@ namespace llarp * Sends messages from path queues until all are empty or a set cap has been reached. */ void - Pump() override; + Pump(); /* Called from outside this class to inform it that a path has died / expired * and its queue should be discarded. */ void - RemovePath(const PathID_t& pathid) override; + RemovePath(const PathID_t& pathid); util::StatusObject - ExtractStatus() const override; + ExtractStatus() const; void Init(AbstractRouter* router); diff --git a/llarp/router/outbound_session_maker.hpp b/llarp/router/outbound_session_maker.hpp index 131d29e47e..5e978dfe19 100644 --- a/llarp/router/outbound_session_maker.hpp +++ b/llarp/router/outbound_session_maker.hpp @@ -1,10 +1,10 @@ #pragma once -#include "i_outbound_session_maker.hpp" +#include "rc_lookup_handler.hpp" -#include "i_rc_lookup_handler.hpp" #include - +#include +#include #include #include @@ -18,7 +18,33 @@ namespace llarp struct LinkManager; struct I_RCLookupHandler; - struct OutboundSessionMaker final : public IOutboundSessionMaker + enum class SessionResult + { + Establish, + Timeout, + RouterNotFound, + InvalidRouter, + NoLink, + EstablishFail + }; + + constexpr std::string_view + ToString(SessionResult sr) + { + return sr == llarp::SessionResult::Establish ? "success"sv + : sr == llarp::SessionResult::Timeout ? "timeout"sv + : sr == llarp::SessionResult::NoLink ? "no link"sv + : sr == llarp::SessionResult::InvalidRouter ? "invalid router"sv + : sr == llarp::SessionResult::RouterNotFound ? "not found"sv + : sr == llarp::SessionResult::EstablishFail ? "establish failed"sv + : "???"sv; + } + template <> + constexpr inline bool IsToStringFormattable = true; + + using RouterCallback = std::function; + + struct OutboundSessionMaker { using Work_t = std::function; using WorkerFunc_t = std::function; @@ -26,31 +52,31 @@ namespace llarp using CallbacksQueue = std::list; public: - ~OutboundSessionMaker() override = default; + ~OutboundSessionMaker() = default; bool - OnSessionEstablished(AbstractLinkSession* session) override; + OnSessionEstablished(AbstractLinkSession* session); void - OnConnectTimeout(AbstractLinkSession* session) override; + OnConnectTimeout(AbstractLinkSession* session); void - CreateSessionTo(const RouterID& router, RouterCallback on_result) override EXCLUDES(_mutex); + CreateSessionTo(const RouterID& router, RouterCallback on_result) EXCLUDES(_mutex); void - CreateSessionTo(const RouterContact& rc, RouterCallback on_result) override EXCLUDES(_mutex); + CreateSessionTo(const RouterContact& rc, RouterCallback on_result) EXCLUDES(_mutex); bool - HavePendingSessionTo(const RouterID& router) const override EXCLUDES(_mutex); + HavePendingSessionTo(const RouterID& router) const EXCLUDES(_mutex); void - ConnectToRandomRouters(int numDesired) override; + ConnectToRandomRouters(int numDesired); util::StatusObject - ExtractStatus() const override; + ExtractStatus() const; bool - ShouldConnectTo(const RouterID& router) const override EXCLUDES(_mutex); + ShouldConnectTo(const RouterID& router) const EXCLUDES(_mutex); void Init( diff --git a/llarp/router/rc_gossiper.cpp b/llarp/router/rc_gossiper.cpp index 1e5c8705a8..986e25f4a9 100644 --- a/llarp/router/rc_gossiper.cpp +++ b/llarp/router/rc_gossiper.cpp @@ -13,11 +13,11 @@ namespace llarp static constexpr auto GossipOurRCInterval = (RCGossipFilterDecayInterval * 2) - (5min); RCGossiper::RCGossiper() - : I_RCGossiper(), m_Filter(std::chrono::duration_cast(RCGossipFilterDecayInterval)) + : m_Filter(std::chrono::duration_cast(RCGossipFilterDecayInterval)) {} void - RCGossiper::Init(ILinkManager* l, const RouterID& ourID, AbstractRouter* router) + RCGossiper::Init(LinkManager* l, const RouterID& ourID, AbstractRouter* router) { m_OurRouterID = ourID; m_LinkManager = l; diff --git a/llarp/router/rc_gossiper.hpp b/llarp/router/rc_gossiper.hpp index 948abad32c..a82840e77c 100644 --- a/llarp/router/rc_gossiper.hpp +++ b/llarp/router/rc_gossiper.hpp @@ -1,47 +1,51 @@ #pragma once #include -#include "i_gossiper.hpp" -#include "i_outbound_message_handler.hpp" -#include +#include "outbound_message_handler.hpp" +#include #include "abstractrouter.hpp" namespace llarp { - struct RCGossiper : public I_RCGossiper + /// The maximum number of peers we will flood a gossiped RC to when propagating an RC + constexpr size_t MaxGossipPeers = 20; + + struct RCGossiper { + using Time_t = Duration_t; + RCGossiper(); - ~RCGossiper() override = default; + ~RCGossiper() = default; bool - GossipRC(const RouterContact& rc) override; + GossipRC(const RouterContact& rc); void - Decay(Time_t now) override; + Decay(Time_t now); bool - ShouldGossipOurRC(Time_t now) const override; + ShouldGossipOurRC(Time_t now) const; bool - IsOurRC(const RouterContact& rc) const override; + IsOurRC(const RouterContact& rc) const; void - Init(ILinkManager*, const RouterID&, AbstractRouter*); + Init(LinkManager*, const RouterID&, AbstractRouter*); void - Forget(const RouterID& router) override; + Forget(const RouterID& router); TimePoint_t - NextGossipAt() const override; + NextGossipAt() const; std::optional - LastGossipAt() const override; + LastGossipAt() const; private: RouterID m_OurRouterID; Time_t m_LastGossipedOurRC = 0s; - ILinkManager* m_LinkManager = nullptr; + LinkManager* m_LinkManager = nullptr; util::DecayingHashSet m_Filter; AbstractRouter* m_router; diff --git a/llarp/router/rc_lookup_handler.cpp b/llarp/router/rc_lookup_handler.cpp index 4755a8383a..f55d50e826 100644 --- a/llarp/router/rc_lookup_handler.cpp +++ b/llarp/router/rc_lookup_handler.cpp @@ -1,7 +1,7 @@ #include #include "rc_lookup_handler.hpp" -#include +#include #include #include #include @@ -361,7 +361,7 @@ namespace llarp std::shared_ptr nodedb, EventLoop_ptr loop, WorkerFunc_t dowork, - ILinkManager* linkManager, + LinkManager* linkManager, service::Context* hiddenServiceContext, const std::unordered_set& strictConnectPubkeys, const std::set& bootstrapRCList, diff --git a/llarp/router/rc_lookup_handler.hpp b/llarp/router/rc_lookup_handler.hpp index eed6a835dd..4758f2dac4 100644 --- a/llarp/router/rc_lookup_handler.hpp +++ b/llarp/router/rc_lookup_handler.hpp @@ -1,10 +1,10 @@ #pragma once -#include -#include "i_rc_lookup_handler.hpp" +#include #include +#include #include #include #include @@ -28,22 +28,34 @@ namespace llarp } // namespace service - struct ILinkManager; + struct LinkManager; + struct RouterContact; + + enum class RCRequestResult + { + Success, + InvalidRouter, + RouterNotFound, + BadRC + }; + + using RCRequestCallback = + std::function; - struct RCLookupHandler final : public I_RCLookupHandler + struct RCLookupHandler { public: using Work_t = std::function; using WorkerFunc_t = std::function; using CallbacksQueue = std::list; - ~RCLookupHandler() override = default; + ~RCLookupHandler() = default; void - AddValidRouter(const RouterID& router) override EXCLUDES(_mutex); + AddValidRouter(const RouterID& router) EXCLUDES(_mutex); void - RemoveValidRouter(const RouterID& router) override EXCLUDES(_mutex); + RemoveValidRouter(const RouterID& router) EXCLUDES(_mutex); void SetRouterWhitelist( @@ -51,51 +63,51 @@ namespace llarp const std::vector& greylist, const std::vector& greenlist - ) override EXCLUDES(_mutex); + ) EXCLUDES(_mutex); bool - HaveReceivedWhitelist() const override; + HaveReceivedWhitelist() const; void - GetRC(const RouterID& router, RCRequestCallback callback, bool forceLookup = false) override + GetRC(const RouterID& router, RCRequestCallback callback, bool forceLookup = false) EXCLUDES(_mutex); bool - PathIsAllowed(const RouterID& remote) const override EXCLUDES(_mutex); + PathIsAllowed(const RouterID& remote) const EXCLUDES(_mutex); bool - SessionIsAllowed(const RouterID& remote) const override EXCLUDES(_mutex); + SessionIsAllowed(const RouterID& remote) const EXCLUDES(_mutex); bool - IsGreylisted(const RouterID& remote) const override EXCLUDES(_mutex); + IsGreylisted(const RouterID& remote) const EXCLUDES(_mutex); // "greenlist" = new routers (i.e. "green") that aren't fully funded yet bool - IsGreenlisted(const RouterID& remote) const override EXCLUDES(_mutex); + IsGreenlisted(const RouterID& remote) const EXCLUDES(_mutex); // registered just means that there is at least an operator stake, but doesn't require the node // be fully funded, active, or not decommed. (In other words: it is any of the white, grey, or // green list). bool - IsRegistered(const RouterID& remote) const override EXCLUDES(_mutex); + IsRegistered(const RouterID& remote) const EXCLUDES(_mutex); bool - CheckRC(const RouterContact& rc) const override; + CheckRC(const RouterContact& rc) const; bool - GetRandomWhitelistRouter(RouterID& router) const override EXCLUDES(_mutex); + GetRandomWhitelistRouter(RouterID& router) const EXCLUDES(_mutex); bool - CheckRenegotiateValid(RouterContact newrc, RouterContact oldrc) override; + CheckRenegotiateValid(RouterContact newrc, RouterContact oldrc); void - PeriodicUpdate(llarp_time_t now) override; + PeriodicUpdate(llarp_time_t now); void - ExploreNetwork() override; + ExploreNetwork(); size_t - NumberOfStrictConnectRouters() const override; + NumberOfStrictConnectRouters() const; void Init( @@ -103,7 +115,7 @@ namespace llarp std::shared_ptr nodedb, std::shared_ptr loop, WorkerFunc_t dowork, - ILinkManager* linkManager, + LinkManager* linkManager, service::Context* hiddenServiceContext, const std::unordered_set& strictConnectPubkeys, const std::set& bootstrapRCList, @@ -138,7 +150,7 @@ namespace llarp std::shared_ptr _loop; WorkerFunc_t _work = nullptr; service::Context* _hiddenServiceContext = nullptr; - ILinkManager* _linkManager = nullptr; + LinkManager* _linkManager = nullptr; /// explicit whitelist of routers we will connect to directly (not for /// service nodes) diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index ff74551dd0..2cf96cd87a 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -323,19 +323,19 @@ namespace llarp TimePoint_t m_NextExploreAt; - IOutboundMessageHandler& + OutboundMessageHandler& outboundMessageHandler() override { return _outboundMessageHandler; } - ILinkManager& + LinkManager& linkManager() override { return _linkManager; } - I_RCLookupHandler& + RCLookupHandler& rcLookupHandler() override { return _rcLookupHandler; From a4272c4503e0133b3ea7c66d87576eadc29d6fb0 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 14 Sep 2023 05:08:10 -0700 Subject: [PATCH 031/312] Added span backport --- .gitmodules | 3 +++ external/span-lite | 1 + llarp/router/outbound_session_maker.cpp | 4 ++-- llarp/router/outbound_session_maker.hpp | 4 ++-- llarp/router/rc_lookup_handler.hpp | 1 - 5 files changed, 8 insertions(+), 5 deletions(-) create mode 160000 external/span-lite diff --git a/.gitmodules b/.gitmodules index 5790be24db..73f0a79358 100644 --- a/.gitmodules +++ b/.gitmodules @@ -32,3 +32,6 @@ [submodule "external/oxen-libquic"] path = external/oxen-libquic url = https://github.com/oxen-io/oxen-libquic.git +[submodule "external/span-lite"] + path = external/span-lite + url = https://github.com/martinmoene/span-lite.git diff --git a/external/span-lite b/external/span-lite new file mode 160000 index 0000000000..bc08bf8725 --- /dev/null +++ b/external/span-lite @@ -0,0 +1 @@ +Subproject commit bc08bf87258d881aaa83b50c54dea67ea33d0e8e diff --git a/llarp/router/outbound_session_maker.cpp b/llarp/router/outbound_session_maker.cpp index e6cbc32c02..f9297cc0b5 100644 --- a/llarp/router/outbound_session_maker.cpp +++ b/llarp/router/outbound_session_maker.cpp @@ -5,7 +5,7 @@ #include #include #include -#include "i_rc_lookup_handler.hpp" +#include "rc_lookup_handler.hpp" #include #include #include @@ -159,7 +159,7 @@ namespace llarp OutboundSessionMaker::Init( AbstractRouter* router, LinkManager* linkManager, - I_RCLookupHandler* rcLookup, + RCLookupHandler* rcLookup, Profiling* profiler, EventLoop_ptr loop, WorkerFunc_t dowork) diff --git a/llarp/router/outbound_session_maker.hpp b/llarp/router/outbound_session_maker.hpp index 5e978dfe19..7749268da7 100644 --- a/llarp/router/outbound_session_maker.hpp +++ b/llarp/router/outbound_session_maker.hpp @@ -82,7 +82,7 @@ namespace llarp Init( AbstractRouter* router, LinkManager* linkManager, - I_RCLookupHandler* rcLookup, + RCLookupHandler* rcLookup, Profiling* profiler, EventLoop_ptr loop, WorkerFunc_t work); @@ -127,7 +127,7 @@ namespace llarp AbstractRouter* _router = nullptr; LinkManager* _linkManager = nullptr; - I_RCLookupHandler* _rcLookup = nullptr; + RCLookupHandler* _rcLookup = nullptr; Profiling* _profiler = nullptr; std::shared_ptr _nodedb; EventLoop_ptr _loop; diff --git a/llarp/router/rc_lookup_handler.hpp b/llarp/router/rc_lookup_handler.hpp index 4758f2dac4..45bb0291c1 100644 --- a/llarp/router/rc_lookup_handler.hpp +++ b/llarp/router/rc_lookup_handler.hpp @@ -1,6 +1,5 @@ #pragma once - #include #include From d1b7eee7c823cbe6a4f894d725b1e2416642f1ae Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 14 Sep 2023 05:20:13 -0700 Subject: [PATCH 032/312] Zlib version bump 1.2.13 -> 1.3 --- cmake/StaticBuild.cmake | 4 ++-- external/CMakeLists.txt | 23 +++++++---------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/cmake/StaticBuild.cmake b/cmake/StaticBuild.cmake index 5663fa66da..d6663ed9fe 100644 --- a/cmake/StaticBuild.cmake +++ b/cmake/StaticBuild.cmake @@ -55,11 +55,11 @@ set(LIBUV_SOURCE libuv-v${LIBUV_VERSION}.tar.gz) set(LIBUV_HASH SHA512=91197ff9303112567bbb915bbb88058050e2ad1c048815a3b57c054635d5dc7df458b956089d785475290132236cb0edcfae830f5d749de29a9a3213eeaf0b20 CACHE STRING "libuv source hash") -set(ZLIB_VERSION 1.2.13 CACHE STRING "zlib version") +set(ZLIB_VERSION 1.3 CACHE STRING "zlib version") set(ZLIB_MIRROR ${LOCAL_MIRROR} https://zlib.net CACHE STRING "zlib mirror(s)") set(ZLIB_SOURCE zlib-${ZLIB_VERSION}.tar.xz) -set(ZLIB_HASH SHA256=d14c38e313afc35a9a8760dadf26042f51ea0f5d154b0630a31da0540107fb98 +set(ZLIB_HASH SHA256=8a9ba2898e1d0d774eca6ba5b4627a11e5588ba85c8851336eb38de4683050a7 CACHE STRING "zlib source hash") set(CURL_VERSION 7.86.0 CACHE STRING "curl version") diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 364a4d0f7b..5fb082101d 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -24,16 +24,15 @@ if(SUBMODULE_CHECK) endfunction () message(STATUS "Checking submodules") + check_submodule(CLI11) + check_submodule(cpr) check_submodule(nlohmann) -# check_submodule(ghc-filesystem) -# check_submodule(oxen-logging fmt spdlog) + check_submodule(oxen-libquic) + check_submodule(oxen-mq) check_submodule(pybind11) + check_submodule(span-lite) check_submodule(sqlite_orm) - check_submodule(oxen-mq) check_submodule(uvw) - check_submodule(cpr) - check_submodule(oxen-libquic) - check_submodule(CLI11) endif() endif() @@ -65,12 +64,6 @@ set(JSON_BuildTests OFF CACHE INTERNAL "") set(JSON_Install OFF CACHE INTERNAL "") system_or_submodule(NLOHMANN nlohmann_json nlohmann_json>=3.7.0 nlohmann) -#if (STATIC OR FORCE_SPDLOG_SUBMODULE OR FORCE_FMT_SUBMODULE) -# set(OXEN_LOGGING_FORCE_SUBMODULES ON CACHE INTERNAL "") -#endif() -#set(OXEN_LOGGING_SOURCE_ROOT "${PROJECT_SOURCE_DIR}" CACHE INTERNAL "") -#add_subdirectory(oxen-logging) - if(WITH_HIVE) add_subdirectory(pybind11 EXCLUDE_FROM_ALL) endif() @@ -92,12 +85,10 @@ add_library(uvw INTERFACE) target_include_directories(uvw INTERFACE uvw/src) target_link_libraries(uvw INTERFACE libuv) -# ngtcp2 needs some massaging to build nicely: -#include(ngtcp2_lib) -#add_ngtcp2_lib() - add_subdirectory(oxen-libquic) +add_subdirectory(span-lite) + # cpr configuration. Ideally we'd just do this via add_subdirectory, but cpr's cmake requires # 3.15+, and we target lower than that (and this is fairly simple to build). if(WITH_BOOTSTRAP) From fd527d612f162b2031914b4951bd4257e6ea7f7a Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 14 Sep 2023 07:54:51 -0700 Subject: [PATCH 033/312] Carving through llarp/link --- llarp/CMakeLists.txt | 2 + llarp/iwp/session.hpp | 441 +++++++++++----------- llarp/link/connection.cpp | 10 + llarp/link/connection.hpp | 5 +- llarp/link/endpoint.cpp | 72 ++++ llarp/link/endpoint.hpp | 25 +- llarp/link/link_manager.cpp | 132 +++---- llarp/link/link_manager.hpp | 82 ++-- llarp/messages/common.hpp | 8 +- llarp/messages/link_message.hpp | 5 - llarp/path/pathbuilder.cpp | 2 +- llarp/router/outbound_message_handler.cpp | 8 +- llarp/router/outbound_session_maker.cpp | 2 +- llarp/router/router.cpp | 34 +- llarp/router/router.hpp | 18 +- llarp/router_contact.hpp | 1 - 16 files changed, 475 insertions(+), 372 deletions(-) create mode 100644 llarp/link/connection.cpp create mode 100644 llarp/link/endpoint.cpp diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index aa17e6b928..4dfdc98a93 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -208,6 +208,8 @@ add_library(lokinet-layer-wire # a series of layer 1 symbols which are then transmitted between lokinet instances add_library(lokinet-layer-link STATIC + link/connection.cpp + link/endpoint.cpp link/link_manager.cpp link/session.cpp link/server.cpp diff --git a/llarp/iwp/session.hpp b/llarp/iwp/session.hpp index eef78ada15..6d6e8faa29 100644 --- a/llarp/iwp/session.hpp +++ b/llarp/iwp/session.hpp @@ -12,267 +12,264 @@ #include #include -namespace llarp +namespace llarp::iwp { - namespace iwp + /// packet crypto overhead size + static constexpr size_t PacketOverhead = HMACSIZE + TUNNONCESIZE; + /// creates a packet with plaintext size + wire overhead + random pad + AbstractLinkSession::Packet_t + CreatePacket(Command cmd, size_t plainsize, size_t min_pad = 16, size_t pad_variance = 16); + /// Time how long we try delivery for + static constexpr std::chrono::milliseconds DeliveryTimeout = 500ms; + /// Time how long we wait to recieve a message + static constexpr auto ReceivalTimeout = (DeliveryTimeout * 8) / 5; + /// How long to keep a replay window for + static constexpr auto ReplayWindow = (ReceivalTimeout * 3) / 2; + /// How often to acks RX messages + static constexpr auto ACKResendInterval = DeliveryTimeout / 2; + /// How often to retransmit TX fragments + static constexpr auto TXFlushInterval = (DeliveryTimeout / 5) * 4; + /// How often we send a keepalive + static constexpr std::chrono::milliseconds PingInterval = 5s; + /// How long we wait for a session to die with no tx from them + static constexpr auto SessionAliveTimeout = PingInterval * 5; + + struct Session : public AbstractLinkSession, public std::enable_shared_from_this { - /// packet crypto overhead size - static constexpr size_t PacketOverhead = HMACSIZE + TUNNONCESIZE; - /// creates a packet with plaintext size + wire overhead + random pad - AbstractLinkSession::Packet_t - CreatePacket(Command cmd, size_t plainsize, size_t min_pad = 16, size_t pad_variance = 16); - /// Time how long we try delivery for - static constexpr std::chrono::milliseconds DeliveryTimeout = 500ms; - /// Time how long we wait to recieve a message - static constexpr auto ReceivalTimeout = (DeliveryTimeout * 8) / 5; - /// How long to keep a replay window for - static constexpr auto ReplayWindow = (ReceivalTimeout * 3) / 2; - /// How often to acks RX messages - static constexpr auto ACKResendInterval = DeliveryTimeout / 2; - /// How often to retransmit TX fragments - static constexpr auto TXFlushInterval = (DeliveryTimeout / 5) * 4; - /// How often we send a keepalive - static constexpr std::chrono::milliseconds PingInterval = 5s; - /// How long we wait for a session to die with no tx from them - static constexpr auto SessionAliveTimeout = PingInterval * 5; - - struct Session : public AbstractLinkSession, public std::enable_shared_from_this + using Time_t = std::chrono::milliseconds; + + /// maximum number of messages we can ack in a multiack + static constexpr std::size_t MaxACKSInMACK = 1024 / sizeof(uint64_t); + + /// outbound session + Session(LinkLayer* parent, const RouterContact& rc, const AddressInfo& ai); + /// inbound session + Session(LinkLayer* parent, const SockAddr& from); + + // Signal the event loop that a pump is needed (idempotent) + void + TriggerPump(); + + // Does the actual pump + void + Pump() override; + + void + Tick(llarp_time_t now) override; + + bool + SendMessageBuffer( + AbstractLinkSession::Message_t msg, + CompletionHandler resultHandler, + uint16_t priority = 0) override; + + void + Send_LL(const byte_t* buf, size_t sz); + + void EncryptAndSend(AbstractLinkSession::Packet_t); + + void + Start() override; + + void + Close() override; + + bool Recv_LL(AbstractLinkSession::Packet_t) override; + + bool + SendKeepAlive() override; + + bool + IsEstablished() const override; + + bool + TimedOut(llarp_time_t now) const override; + + PubKey + GetPubKey() const override { - using Time_t = std::chrono::milliseconds; + return m_RemoteRC.pubkey; + } - /// maximum number of messages we can ack in a multiack - static constexpr std::size_t MaxACKSInMACK = 1024 / sizeof(uint64_t); - - /// outbound session - Session(LinkLayer* parent, const RouterContact& rc, const AddressInfo& ai); - /// inbound session - Session(LinkLayer* parent, const SockAddr& from); - - // Signal the event loop that a pump is needed (idempotent) - void - TriggerPump(); - - // Does the actual pump - void - Pump() override; - - void - Tick(llarp_time_t now) override; - - bool - SendMessageBuffer( - AbstractLinkSession::Message_t msg, - CompletionHandler resultHandler, - uint16_t priority = 0) override; - - void - Send_LL(const byte_t* buf, size_t sz); - - void EncryptAndSend(AbstractLinkSession::Packet_t); - - void - Start() override; - - void - Close() override; - - bool Recv_LL(AbstractLinkSession::Packet_t) override; - - bool - SendKeepAlive() override; - - bool - IsEstablished() const override; - - bool - TimedOut(llarp_time_t now) const override; - - PubKey - GetPubKey() const override - { - return m_RemoteRC.pubkey; - } - - const SockAddr& - GetRemoteEndpoint() const override - { - return m_RemoteAddr; - } - - RouterContact - GetRemoteRC() const override - { - return m_RemoteRC; - } - - size_t - SendQueueBacklog() const override - { - return m_TXMsgs.size(); - } - - ILinkLayer* - GetLinkLayer() const override - { - return m_Parent; - } - - bool - RenegotiateSession() override; - - bool - ShouldPing() const override; - - SessionStats - GetSessionStats() const override; - - util::StatusObject - ExtractStatus() const override; + const SockAddr& + GetRemoteEndpoint() const override + { + return m_RemoteAddr; + } - bool - IsInbound() const override - { - return m_Inbound; - } - void - HandlePlaintext() override; + RouterContact + GetRemoteRC() const override + { + return m_RemoteRC; + } - private: - enum class State - { - /// we have no data recv'd - Initial, - /// we are in introduction phase - Introduction, - /// we sent our LIM - LinkIntro, - /// handshake done and LIM has been obtained - Ready, - /// we are closed now - Closed - }; - static std::string - StateToString(State state); - State m_State; - SessionStats m_Stats; + size_t + SendQueueBacklog() const override + { + return m_TXMsgs.size(); + } - /// are we inbound session ? - const bool m_Inbound; - /// parent link layer - LinkLayer* const m_Parent; - const llarp_time_t m_CreatedAt; - const SockAddr m_RemoteAddr; + ILinkLayer* + GetLinkLayer() const override + { + return m_Parent; + } - AddressInfo m_ChosenAI; - /// remote rc - RouterContact m_RemoteRC; - /// session key - SharedSecret m_SessionKey; - /// session token - AlignedBuffer<24> token; + bool + RenegotiateSession() override; - PubKey m_ExpectedIdent; - PubKey m_RemoteOnionKey; + bool + ShouldPing() const override; - llarp_time_t m_LastTX = 0s; - llarp_time_t m_LastRX = 0s; + SessionStats + GetSessionStats() const override; - // accumulate for periodic rate calculation - uint64_t m_TXRate = 0; - uint64_t m_RXRate = 0; + util::StatusObject + ExtractStatus() const override; - llarp_time_t m_ResetRatesAt = 0s; + bool + IsInbound() const override + { + return m_Inbound; + } + void + HandlePlaintext() override; - uint64_t m_TXID = 0; + private: + enum class State + { + /// we have no data recv'd + Initial, + /// we are in introduction phase + Introduction, + /// we sent our LIM + LinkIntro, + /// handshake done and LIM has been obtained + Ready, + /// we are closed now + Closed + }; + static std::string + StateToString(State state); + State m_State; + SessionStats m_Stats; - bool - ShouldResetRates(llarp_time_t now) const; + /// are we inbound session ? + const bool m_Inbound; + /// parent link layer + LinkLayer* const m_Parent; + const llarp_time_t m_CreatedAt; + const SockAddr m_RemoteAddr; - void - ResetRates(); + AddressInfo m_ChosenAI; + /// remote rc + RouterContact m_RemoteRC; + /// session key + SharedSecret m_SessionKey; + /// session token + AlignedBuffer<24> token; - std::map m_RXMsgs; - std::map m_TXMsgs; + PubKey m_ExpectedIdent; + PubKey m_RemoteOnionKey; - /// maps rxid to time recieved - std::unordered_map m_ReplayFilter; - /// rx messages to send in next round of multiacks - util::ascending_priority_queue m_SendMACKs; + llarp_time_t m_LastTX = 0s; + llarp_time_t m_LastRX = 0s; - using CryptoQueue_t = std::vector; + // accumulate for periodic rate calculation + uint64_t m_TXRate = 0; + uint64_t m_RXRate = 0; - CryptoQueue_t m_EncryptNext; - CryptoQueue_t m_DecryptNext; + llarp_time_t m_ResetRatesAt = 0s; - std::atomic_flag m_PlaintextEmpty; - llarp::thread::Queue m_PlaintextRecv; - std::atomic_flag m_SentClosed; + uint64_t m_TXID = 0; - void - EncryptWorker(CryptoQueue_t msgs); + bool + ShouldResetRates(llarp_time_t now) const; - void - DecryptWorker(CryptoQueue_t msgs); + void + ResetRates(); - void - HandleGotIntro(Packet_t pkt); + std::map m_RXMsgs; + std::map m_TXMsgs; - void - HandleGotIntroAck(Packet_t pkt); + /// maps rxid to time recieved + std::unordered_map m_ReplayFilter; + /// rx messages to send in next round of multiacks + util::ascending_priority_queue m_SendMACKs; - void - HandleCreateSessionRequest(Packet_t pkt); + using CryptoQueue_t = std::vector; - void - HandleAckSession(Packet_t pkt); + CryptoQueue_t m_EncryptNext; + CryptoQueue_t m_DecryptNext; - void - HandleSessionData(Packet_t pkt); + std::atomic_flag m_PlaintextEmpty; + llarp::thread::Queue m_PlaintextRecv; + std::atomic_flag m_SentClosed; - bool - DecryptMessageInPlace(Packet_t& pkt); + void + EncryptWorker(CryptoQueue_t msgs); - void - SendMACK(); + void + DecryptWorker(CryptoQueue_t msgs); - void - HandleRecvMsgCompleted(const InboundMessage& msg); + void + HandleGotIntro(Packet_t pkt); - void - GenerateAndSendIntro(); + void + HandleGotIntroAck(Packet_t pkt); - bool - GotInboundLIM(const LinkIntroMessage* msg); + void + HandleCreateSessionRequest(Packet_t pkt); - bool - GotOutboundLIM(const LinkIntroMessage* msg); + void + HandleAckSession(Packet_t pkt); - bool - GotRenegLIM(const LinkIntroMessage* msg); + void + HandleSessionData(Packet_t pkt); - void - SendOurLIM(AbstractLinkSession::CompletionHandler h = nullptr); + bool + DecryptMessageInPlace(Packet_t& pkt); - void - HandleXMIT(Packet_t msg); + void + SendMACK(); - void - HandleDATA(Packet_t msg); + void + HandleRecvMsgCompleted(const InboundMessage& msg); - void - HandleACKS(Packet_t msg); + void + GenerateAndSendIntro(); - void - HandleNACK(Packet_t msg); + bool + GotInboundLIM(const LinkIntroMessage* msg); - void - HandlePING(Packet_t msg); + bool + GotOutboundLIM(const LinkIntroMessage* msg); - void - HandleCLOS(Packet_t msg); + bool + GotRenegLIM(const LinkIntroMessage* msg); - void - HandleMACK(Packet_t msg); - }; - } // namespace iwp -} // namespace llarp + void + SendOurLIM(AbstractLinkSession::CompletionHandler h = nullptr); + + void + HandleXMIT(Packet_t msg); + + void + HandleDATA(Packet_t msg); + + void + HandleACKS(Packet_t msg); + + void + HandleNACK(Packet_t msg); + + void + HandlePING(Packet_t msg); + + void + HandleCLOS(Packet_t msg); + + void + HandleMACK(Packet_t msg); + }; +} // namespace llarp::iwp diff --git a/llarp/link/connection.cpp b/llarp/link/connection.cpp new file mode 100644 index 0000000000..025eae8e68 --- /dev/null +++ b/llarp/link/connection.cpp @@ -0,0 +1,10 @@ +#include "connection.hpp" + +namespace llarp::link +{ + Connection::Connection( + std::shared_ptr& c, std::shared_ptr& s) + : conn{c}, control_stream{s} + {} + +} // namespace llarp::link diff --git a/llarp/link/connection.hpp b/llarp/link/connection.hpp index 171f91c8b1..b0c7e08154 100644 --- a/llarp/link/connection.hpp +++ b/llarp/link/connection.hpp @@ -7,9 +7,12 @@ namespace llarp::link { - struct Connection { + Connection( + std::shared_ptr& c, + std::shared_ptr& s); + std::shared_ptr conn; std::shared_ptr control_stream; diff --git a/llarp/link/endpoint.cpp b/llarp/link/endpoint.cpp new file mode 100644 index 0000000000..95376029cc --- /dev/null +++ b/llarp/link/endpoint.cpp @@ -0,0 +1,72 @@ +#include "endpoint.hpp" +#include "link_manager.hpp" + +namespace llarp::link +{ + std::shared_ptr + Endpoint::get_conn(const RouterContact& rc) const + { + for (const auto& [rid, conn] : conns) + { + if (conn->remote_rc == rc) + return conn; + } + + return nullptr; + } + + bool + Endpoint::have_conn(const RouterID& remote, bool client_only) const + { + if (auto itr = conns.find(remote); itr != conns.end()) + { + if (not(itr->second->remote_is_relay and client_only)) + return true; + } + + return false; + } + + // TOFIX: use the new close methods after bumping libquic + bool + Endpoint::deregister_peer(RouterID remote) + { + if (auto itr = conns.find(remote); itr != conns.end()) + { + endpoint->close_connection(*dynamic_cast(itr->second->conn.get())); + conns.erase(itr); + return true; + } + + return false; + } + + bool + Endpoint::establish_connection(const oxen::quic::opt::local_addr& remote) + { + try + { + oxen::quic::dgram_data_callback dgram_cb = + [this](oxen::quic::dgram_interface& dgi, bstring dgram) { + link_manager.recv_data_message(dgi, dgram); + }; + + auto conn_interface = endpoint->connect(remote, link_manager.tls_creds, dgram_cb); + auto control_stream = conn_interface->get_new_stream(); + + // TOFIX: get a real RouterID after refactoring it + RouterID rid; + auto [itr, b] = conns.emplace(rid); + itr->second = std::make_shared(conn_interface, control_stream); + connid_map.emplace(conn_interface->scid(), rid); + + return true; + } + catch (...) + { + log::error(quic_cat, "Error: failed to establish connection to {}", remote); + return false; + } + } + +} // namespace llarp::link diff --git a/llarp/link/endpoint.hpp b/llarp/link/endpoint.hpp index 6ac3bb95d9..e4fca1449f 100644 --- a/llarp/link/endpoint.hpp +++ b/llarp/link/endpoint.hpp @@ -11,13 +11,34 @@ namespace llarp::link { struct Endpoint { + Endpoint(std::shared_ptr ep, LinkManager& lm) + : endpoint{std::move(ep)}, link_manager{lm} + {} + std::shared_ptr endpoint; - bool inbound{false}; + LinkManager& link_manager; // for outgoing packets, we route via RouterID; map RouterID->Connection // for incoming packets, we get a ConnectionID; map ConnectionID->RouterID - std::unordered_map connections; + std::unordered_map> conns; std::unordered_map connid_map; + + std::shared_ptr + get_conn(const RouterContact&) const; + + bool + have_conn(const RouterID& remote, bool client_only) const; + + bool + deregister_peer(RouterID remote); + + bool + establish_connection(const oxen::quic::opt::local_addr& remote); }; } // namespace llarp::link + +/* +- Refactor RouterID to use gnutls info and maybe ConnectionID + +*/ diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 1add168b35..e226b96ffd 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1,5 +1,6 @@ #include "link_manager.hpp" +#include #include #include #include @@ -9,27 +10,31 @@ namespace llarp { - link::Endpoint* - LinkManager::GetCompatibleLink(const RouterContact&) + + LinkManager::LinkManager(Router& r) + : router{r} + , quic{std::make_unique()} + , tls_creds{oxen::quic::GNUTLSCreds::make_from_ed_keys( + {reinterpret_cast(router.encryption().data()), router.encryption().size()}, + {reinterpret_cast(router.encryption().toPublic().data()), size_t{32}})} + , ep{quic->endpoint(router.local), *this} + {} + + std::shared_ptr + LinkManager::get_compatible_link(const RouterContact& rc) { if (stopping) return nullptr; - for (auto& ep : endpoints) - { - // TODO: need some notion of "is this link compatible with that address". - // iwp just checks that the link dialect ("iwp") matches the address info dialect, - // but that feels insufficient. For now, just return the first endpoint we have; - // we should probably only have 1 for now anyway until we make ipv6 work. - return &ep; - } + if (auto c = ep.get_conn(rc); c) + return c; return nullptr; } // TODO: replace with control/data message sending with libquic bool - LinkManager::SendTo( + LinkManager::send_to( const RouterID& remote, const llarp_buffer_t&, AbstractLinkSession::CompletionHandler completed, @@ -38,7 +43,7 @@ namespace llarp if (stopping) return false; - if (not HaveConnection(remote)) + if (not have_connection_to(remote)) { if (completed) { @@ -53,68 +58,40 @@ namespace llarp } bool - LinkManager::HaveConnection(const RouterID& remote, bool client_only) const + LinkManager::have_connection_to(const RouterID& remote, bool client_only) const { - for (const auto& ep : endpoints) - { - if (auto itr = ep.connections.find(remote); itr != ep.connections.end()) - { - if (not(itr->second.remote_is_relay and client_only)) - return true; - return false; - } - } - return false; + return ep.have_conn(remote, client_only); } bool - LinkManager::HaveClientConnection(const RouterID& remote) const + LinkManager::have_client_connection_to(const RouterID& remote) const { - return HaveConnection(remote, true); + return ep.have_conn(remote, true); } void - LinkManager::DeregisterPeer(RouterID remote) + LinkManager::deregister_peer(RouterID remote) { - m_PersistingSessions.erase(remote); - for (const auto& ep : endpoints) + if (auto rv = ep.deregister_peer(remote); rv) { - if (auto itr = ep.connections.find(remote); itr != ep.connections.end()) - { - /* - itr->second.conn->close(); //TODO: libquic needs some function for this - */ - } + persisting_conns.erase(remote); + log::info(logcat, "Peer {} successfully de-registered"); } - - LogInfo(remote, " has been de-registered"); + else + log::warning(logcat, "Peer {} not found for de-registeration!"); } void - LinkManager::AddLink(const oxen::quic::opt::local_addr& bind, bool inbound) + LinkManager::connect_to(const oxen::quic::opt::local_addr& remote) { - // TODO: libquic callbacks: new_conn_alpn_notify, new_conn_pubkey_ok, new_conn_established/ready - // stream_opened, stream_data, stream_closed, conn_closed - oxen::quic::dgram_data_callback dgram_cb = - [this](oxen::quic::dgram_interface& dgi, bstring dgram) { - HandleIncomingDataMessage(dgi, dgram); - }; - auto ep = quic->endpoint( - bind, - std::move(dgram_cb), - oxen::quic::opt::enable_datagrams{oxen::quic::Splitting::ACTIVE}); - endpoints.emplace_back(); - auto& endp = endpoints.back(); - endp.endpoint = std::move(ep); - if (inbound) - { - endp.endpoint->listen(tls_creds); - endp.inbound = true; - } + if (auto rv = ep.establish_connection(remote); rv) + log::info(quic_cat, "Connection to {} successfully established!", remote); + else + log::info(quic_cat, "Connection to {} unsuccessfully established", remote); } void - LinkManager::Stop() + LinkManager::stop() { if (stopping) { @@ -130,23 +107,23 @@ namespace llarp } void - LinkManager::PersistSessionUntil(const RouterID& remote, llarp_time_t until) + LinkManager::set_conn_persist(const RouterID& remote, llarp_time_t until) { if (stopping) return; util::Lock l(_mutex); - m_PersistingSessions[remote] = std::max(until, m_PersistingSessions[remote]); - if (HaveClientConnection(remote)) + persisting_conns[remote] = std::max(until, persisting_conns[remote]); + if (have_client_connection_to(remote)) { // mark this as a client so we don't try to back connect - m_Clients.Upsert(remote); + clients.Upsert(remote); } } size_t - LinkManager::NumberOfConnectedRouters(bool clients_only) const + LinkManager::get_num_connected(bool clients_only) const { size_t count{0}; for (const auto& ep : endpoints) @@ -162,13 +139,13 @@ namespace llarp } size_t - LinkManager::NumberOfConnectedClients() const + LinkManager::get_num_connected_clients() const { - return NumberOfConnectedRouters(true); + return get_num_connected(true); } bool - LinkManager::GetRandomConnectedRouter(RouterContact& router) const + LinkManager::get_random_connected(RouterContact& router) const { std::unordered_map connectedRouters; @@ -199,7 +176,7 @@ namespace llarp // TODO: this? perhaps no longer necessary in the same way? void - LinkManager::CheckPersistingSessions(llarp_time_t) + LinkManager::check_persisting_conns(llarp_time_t) { if (stopping) return; @@ -207,7 +184,7 @@ namespace llarp // TODO: do we still need this concept? void - LinkManager::updatePeerDb(std::shared_ptr) + LinkManager::update_peer_db(std::shared_ptr) {} // TODO: this @@ -218,7 +195,7 @@ namespace llarp } void - LinkManager::Init(RCLookupHandler* rcLookup) + LinkManager::init(RCLookupHandler* rcLookup) { stopping = false; _rcLookup = rcLookup; @@ -226,11 +203,12 @@ namespace llarp } void - LinkManager::Connect(RouterID router) + LinkManager::connect_to(RouterID router) { - auto fn = [this](const RouterID&, const RouterContact* const rc, const RCRequestResult res) { + auto fn = [this]( + const RouterID& rid, const RouterContact* const rc, const RCRequestResult res) { if (res == RCRequestResult::Success) - Connect(*rc); + connect_to(*rc); /* TODO: else RC lookup failure callback here @@ -242,10 +220,10 @@ namespace llarp // This function assumes the RC has already had its signature verified and connection is allowed. void - LinkManager::Connect(RouterContact rc) + LinkManager::connect_to(RouterContact rc) { // TODO: connection failed callback - if (HaveConnection(rc.pubkey)) + if (have_connection_to(rc.pubkey)) return; // RC shouldn't be valid if this is the case, but may as well sanity check... @@ -254,14 +232,14 @@ namespace llarp return; // TODO: connection failed callback - auto* ep = GetCompatibleLink(rc); + auto* ep = get_compatible_link(rc); if (ep == nullptr) return; // TODO: connection established/failed callbacks oxen::quic::stream_data_callback stream_cb = [this](oxen::quic::Stream& stream, bstring_view packet) { - HandleIncomingControlMessage(stream, packet); + recv_control_message(stream, packet); }; // TODO: once "compatible link" cares about address, actually choose addr to connect to @@ -289,7 +267,7 @@ namespace llarp } void - LinkManager::ConnectToRandomRouters(int numDesired) + LinkManager::connect_to_random(int numDesired) { std::set exclude; auto remainingDesired = numDesired; @@ -315,13 +293,13 @@ namespace llarp } void - LinkManager::HandleIncomingDataMessage(oxen::quic::dgram_interface&, bstring) + LinkManager::recv_data_message(oxen::quic::dgram_interface&, bstring) { // TODO: this } void - LinkManager::HandleIncomingControlMessage(oxen::quic::Stream&, bstring_view) + LinkManager::recv_control_message(oxen::quic::Stream&, bstring_view) { // TODO: this } diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 980193ae7d..92fbbe1a5a 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -1,6 +1,7 @@ #pragma once #include + #include "server.hpp" #include "endpoint.hpp" @@ -10,6 +11,13 @@ #include #include +#include + +namespace +{ + static auto quic_cat = llarp::log::Cat("lokinet.quic"); +} // namespace + namespace llarp { enum class SessionResult @@ -36,63 +44,64 @@ namespace llarp template <> constexpr inline bool IsToStringFormattable = true; + struct Router; + struct LinkManager { public: - explicit LinkManager(AbstractRouter* r) : router{r} - {} + explicit LinkManager(Router& r); bool - SendTo( + send_to( const RouterID& remote, const llarp_buffer_t& buf, AbstractLinkSession::CompletionHandler completed, uint16_t priority); bool - HaveConnection(const RouterID& remote, bool client_only = false) const; + have_connection_to(const RouterID& remote, bool client_only = false) const; bool - HaveClientConnection(const RouterID& remote) const; + have_client_connection_to(const RouterID& remote) const; + + void + deregister_peer(RouterID remote); + + void + connect_to(const oxen::quic::opt::local_addr& remote); void - DeregisterPeer(RouterID remote); + connect_to(RouterID router); void - AddLink(const oxen::quic::opt::local_addr& bind, bool inbound = false); + connect_to(RouterContact rc); void - Stop(); + stop(); void - PersistSessionUntil(const RouterID& remote, llarp_time_t until); + set_conn_persist(const RouterID& remote, llarp_time_t until); size_t - NumberOfConnectedRouters(bool clients_only = false) const; + get_num_connected(bool clients_only = false) const; size_t - NumberOfConnectedClients() const; + get_num_connected_clients() const; bool - GetRandomConnectedRouter(RouterContact& router) const; + get_random_connected(RouterContact& router) const; void - CheckPersistingSessions(llarp_time_t now); + check_persisting_conns(llarp_time_t now); void - updatePeerDb(std::shared_ptr peerDb); + update_peer_db(std::shared_ptr peerDb); util::StatusObject ExtractStatus() const; void - Init(RCLookupHandler* rcLookup); - - void - Connect(RouterID router); - - void - Connect(RouterContact rc); + init(RCLookupHandler* rcLookup); // Attempts to connect to a number of random routers. // @@ -100,47 +109,46 @@ namespace llarp // check if we already have a connection to any of the random set, as making // that thread safe would be slow...I think. void - ConnectToRandomRouters(int numDesired); + connect_to_random(int numDesired); // TODO: tune these (maybe even remove max?) now that we're switching to quic /// always maintain this many connections to other routers - size_t minConnectedRouters = 4; + size_t min_connected_routers = 4; /// hard upperbound limit on the number of router to router connections - size_t maxConnectedRouters = 6; + size_t max_connected_routers = 6; private: - link::Endpoint* - GetCompatibleLink(const RouterContact& rc); + friend struct link::Endpoint; + + std::shared_ptr + get_compatible_link(const RouterContact& rc); std::atomic stopping; mutable util::Mutex _mutex; // protects m_PersistingSessions // sessions to persist -> timestamp to end persist at - std::unordered_map m_PersistingSessions GUARDED_BY(_mutex); + std::unordered_map persisting_conns GUARDED_BY(_mutex); - std::unordered_map m_lastRouterStats; + std::unordered_map last_router_stats; - util::DecayingHashSet m_Clients{path::default_lifetime}; + util::DecayingHashSet clients{path::default_lifetime}; RCLookupHandler* _rcLookup; std::shared_ptr _nodedb; - AbstractRouter* router; + Router& router; // FIXME: Lokinet currently expects to be able to kill all network functionality before // finishing other shutdown things, including destroying this class, and that is all in // Network's destructor, so we need to be able to destroy it before this class. - std::unique_ptr quic{std::make_unique()}; - - std::vector endpoints; - - // TODO: initialize creds + std::unique_ptr quic; std::shared_ptr tls_creds; + link::Endpoint ep; void - HandleIncomingDataMessage(oxen::quic::dgram_interface& dgi, bstring dgram); + recv_data_message(oxen::quic::dgram_interface& dgi, bstring dgram); void - HandleIncomingControlMessage(oxen::quic::Stream& stream, bstring_view packet); + recv_control_message(oxen::quic::Stream& stream, bstring_view packet); }; } // namespace llarp diff --git a/llarp/messages/common.hpp b/llarp/messages/common.hpp index 2faac9863c..7b6618b446 100644 --- a/llarp/messages/common.hpp +++ b/llarp/messages/common.hpp @@ -1,9 +1,15 @@ #pragma once #include - #include +#include + +namespace +{ + static auto link_cat = llarp::log::Cat("lokinet.link"); +} // namespace + namespace llarp { /// abstract base class for serialized messages diff --git a/llarp/messages/link_message.hpp b/llarp/messages/link_message.hpp index d96f183be9..91602a1746 100644 --- a/llarp/messages/link_message.hpp +++ b/llarp/messages/link_message.hpp @@ -9,11 +9,6 @@ #include -namespace -{ - static auto link_cat = llarp::log::Cat("lokinet.link"); -} // namespace - namespace llarp { struct AbstractLinkSession; diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index d3c565a68b..72c5000bad 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -505,7 +505,7 @@ namespace llarp { // remove all connections to this router as it's probably not registered anymore LogWarn("removing router ", router, " because of path build timeout"); - r->linkManager().DeregisterPeer(router); + r->linkManager().deregister_peer(router); r->nodedb()->Remove(router); } }, diff --git a/llarp/router/outbound_message_handler.cpp b/llarp/router/outbound_message_handler.cpp index 914ad4c0ea..37a8c214a4 100644 --- a/llarp/router/outbound_message_handler.cpp +++ b/llarp/router/outbound_message_handler.cpp @@ -24,7 +24,7 @@ namespace llarp const RouterID& remote, const AbstractLinkMessage& msg, SendStatusHandler callback) { // if the destination is invalid, callback with failure and return - if (not _router->linkManager().HaveClientConnection(remote) + if (not _router->linkManager().have_client_connection_to(remote) and not _router->rcLookupHandler().SessionIsAllowed(remote)) { DoCallback(callback, SendStatus::InvalidRouter); @@ -47,7 +47,7 @@ namespace llarp std::copy_n(_buf.data(), _buf.size(), ent.message.data()); // if we have a session to the destination, queue the message and return - if (_router->linkManager().HaveConnection(remote)) + if (_router->linkManager().have_connection_to(remote)) { QueueOutboundMessage(std::move(ent)); return true; @@ -196,7 +196,7 @@ namespace llarp const llarp_buffer_t buf{ent.message}; m_queueStats.sent++; SendStatusHandler callback = ent.inform; - return _router->linkManager().SendTo( + return _router->linkManager().send_to( ent.router, buf, [this, callback](AbstractLinkSession::DeliveryStatus status) { @@ -213,7 +213,7 @@ namespace llarp bool OutboundMessageHandler::SendIfSession(const MessageQueueEntry& ent) { - if (_router->linkManager().HaveConnection(ent.router)) + if (_router->linkManager().have_connection_to(ent.router)) { return Send(ent); } diff --git a/llarp/router/outbound_session_maker.cpp b/llarp/router/outbound_session_maker.cpp index f9297cc0b5..387ecb0cf9 100644 --- a/llarp/router/outbound_session_maker.cpp +++ b/llarp/router/outbound_session_maker.cpp @@ -210,7 +210,7 @@ namespace llarp numPending += pendingCallbacks.size(); } - return _linkManager->NumberOfConnectedRouters() + numPending < maxConnectedRouters; + return _linkManager->get_num_connected() + numPending < maxConnectedRouters; } void diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 2a39fec874..9303f8b7da 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -273,7 +273,7 @@ namespace llarp void Router::PersistSessionUntil(const RouterID& remote, llarp_time_t until) { - _linkManager.PersistSessionUntil(remote, until); + _linkManager.set_conn_persist(remote, until); } void @@ -599,13 +599,13 @@ namespace llarp size_t Router::NumberOfConnectedRouters() const { - return _linkManager.NumberOfConnectedRouters(); + return _linkManager.get_num_connected(); } size_t Router::NumberOfConnectedClients() const { - return _linkManager.NumberOfConnectedClients(); + return _linkManager.get_num_connected_clients(); } bool @@ -671,8 +671,8 @@ namespace llarp // Router config _rc.SetNick(conf.router.m_nickname); - _linkManager.maxConnectedRouters = conf.router.m_maxConnectedRouters; - _linkManager.minConnectedRouters = conf.router.m_minConnectedRouters; + _linkManager.max_connected_routers = conf.router.m_maxConnectedRouters; + _linkManager.min_connected_routers = conf.router.m_minConnectedRouters; encryption_keyfile = m_keyManager->m_encKeyPath; our_rc_file = m_keyManager->m_rcPath; @@ -792,7 +792,7 @@ namespace llarp // Init components after relevant config settings loaded _outboundMessageHandler.Init(this); - _linkManager.Init(&_rcLookupHandler); + _linkManager.init(&_rcLookupHandler); _rcLookupHandler.Init( _dht, _nodedb, @@ -1063,9 +1063,9 @@ namespace llarp // mark peers as de-registered for (auto& peer : closePeers) - _linkManager.DeregisterPeer(std::move(peer)); + _linkManager.deregister_peer(std::move(peer)); - _linkManager.CheckPersistingSessions(now); + _linkManager.check_persisting_conns(now); size_t connected = NumberOfConnectedRouters(); @@ -1076,7 +1076,7 @@ namespace llarp _rcLookupHandler.ExploreNetwork(); m_NextExploreAt = timepoint_now + std::chrono::seconds(interval); } - size_t connectToNum = _linkManager.minConnectedRouters; + size_t connectToNum = _linkManager.min_connected_routers; const auto strictConnect = _rcLookupHandler.NumberOfStrictConnectRouters(); if (strictConnect > 0 && connectToNum > strictConnect) { @@ -1114,7 +1114,7 @@ namespace llarp { size_t dlt = connectToNum - connected; LogDebug("connecting to ", dlt, " random routers to keep alive"); - _linkManager.ConnectToRandomRouters(dlt); + _linkManager.connect_to_random(dlt); } _hiddenServiceContext.Tick(now); @@ -1133,7 +1133,7 @@ namespace llarp // TODO: throttle this? // TODO: need to capture session stats when session terminates / is removed from link // manager - _linkManager.updatePeerDb(m_peerDb); + _linkManager.update_peer_db(m_peerDb); if (m_peerDb->shouldFlush(now)) { @@ -1235,7 +1235,7 @@ namespace llarp bool Router::GetRandomConnectedRouter(RouterContact& result) const { - return _linkManager.GetRandomConnectedRouter(result); + return _linkManager.get_random_connected(result); } void @@ -1501,7 +1501,7 @@ namespace llarp void Router::StopLinks() { - _linkManager.Stop(); + _linkManager.stop(); } void @@ -1559,7 +1559,7 @@ namespace llarp bool Router::HasSessionTo(const RouterID& remote) const { - return _linkManager.HaveConnection(remote); + return _linkManager.have_connection_to(remote); } std::string @@ -1581,7 +1581,7 @@ namespace llarp auto connected = NumberOfConnectedRouters(); if (connected >= want) return; - _linkManager.ConnectToRandomRouters(want); + _linkManager.connect_to_random(want); } bool @@ -1729,7 +1729,7 @@ namespace llarp AddressInfo ai; ai.fromSockAddr(bind_addr); - _linkManager.AddLink({ai.IPString(), ai.port}, true); + _linkManager.connect_to({ai.IPString(), ai.port}, true); ai.pubkey = llarp::seckey_topublic(_identity); ai.dialect = "quicinet"; // FIXME: constant, also better name? @@ -1749,7 +1749,7 @@ namespace llarp { AddressInfo ai; ai.fromSockAddr(bind_addr); - _linkManager.AddLink({ai.IPString(), ai.port}, false); + _linkManager.connect_to({ai.IPString(), ai.port}, false); } } diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 2cf96cd87a..7090462cca 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -47,11 +47,22 @@ #include -#include +namespace libquic = oxen::quic; namespace llarp { - struct Router : public AbstractRouter + + class RouteManager final /* : public AbstractRouter */ + { + public: + std::shared_ptr + get_or_connect(); + + private: + std::shared_ptr ep; + }; + + struct Router final : public AbstractRouter { llarp_time_t _lastPump = 0s; bool ready; @@ -224,6 +235,7 @@ namespace llarp ShouldTestOtherRouters() const; std::optional _ourAddress; + oxen::quic::Address local; EventLoop_ptr _loop; std::shared_ptr _vpnPlatform; @@ -311,7 +323,7 @@ namespace llarp Profiling _routerProfiling; fs::path _profilesFile; OutboundMessageHandler _outboundMessageHandler; - LinkManager _linkManager{this}; + LinkManager _linkManager{*this}; RCLookupHandler _rcLookupHandler; RCGossiper _rcGossiper; diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index 0acb531e69..ed6a8dcd8c 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -112,7 +112,6 @@ namespace llarp std::string bt_encode() const; - // tofix: drop version 0 case, change parameter to take btlp reference void bt_encode_subdict(oxenc::bt_list_producer& btlp) const; From ffb90e87dc66d1243251c3e3c687b8d0f004cfca Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 14 Sep 2023 12:16:13 -0700 Subject: [PATCH 034/312] libquic bump --- external/oxen-libquic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/oxen-libquic b/external/oxen-libquic index ef8d9c3130..329a6ba6ff 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit ef8d9c31303c139577b642eab85e67213cf1b2d3 +Subproject commit 329a6ba6ff79f7a94762f0e55d8366190cbfb318 From aaf688cf8190714ae635c6ed7255ff8714d5f0d8 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Fri, 15 Sep 2023 07:55:32 -0700 Subject: [PATCH 035/312] Deleted a lot - RIP llarp/iwp/* and most of llarp/link --- include/llarp.hpp | 6 +- jni/lokinet_daemon.cpp | 4 +- llarp/CMakeLists.txt | 13 - llarp/apple/route_manager.hpp | 2 +- llarp/apple/vpn_interface.cpp | 4 +- llarp/apple/vpn_interface.hpp | 4 +- llarp/apple/vpn_platform.cpp | 2 +- llarp/apple/vpn_platform.hpp | 2 +- llarp/consensus/reachability_testing.cpp | 6 +- llarp/consensus/reachability_testing.hpp | 5 +- llarp/context.cpp | 4 +- llarp/dht/context.cpp | 20 +- llarp/dht/context.hpp | 10 +- llarp/dht/dht.cpp | 4 +- llarp/dht/dht.h | 4 +- llarp/dht/explorenetworkjob.cpp | 4 +- llarp/dht/localrouterlookup.cpp | 4 +- llarp/dht/localserviceaddresslookup.cpp | 4 +- llarp/dht/localtaglookup.cpp | 4 +- llarp/dht/messages/findintro.cpp | 4 +- llarp/dht/messages/findname.cpp | 6 +- llarp/dht/messages/findrouter.cpp | 8 +- llarp/dht/messages/gotintro.cpp | 6 +- llarp/dht/messages/gotname.cpp | 4 +- llarp/dht/messages/gotrouter.cpp | 10 +- llarp/dht/messages/pubintro.cpp | 5 +- llarp/dht/publishservicejob.cpp | 4 +- llarp/dht/recursiverouterlookup.cpp | 4 +- llarp/exit/context.cpp | 181 ++- llarp/exit/context.hpp | 69 +- llarp/exit/endpoint.cpp | 4 +- llarp/exit/exit_messages.cpp | 12 +- llarp/exit/exit_messages.hpp | 12 +- llarp/exit/session.cpp | 12 +- llarp/exit/session.hpp | 6 +- llarp/handlers/exit.cpp | 1411 ++++++++++---------- llarp/handlers/exit.hpp | 62 +- llarp/handlers/null.hpp | 4 +- llarp/handlers/tun.cpp | 41 +- llarp/handlers/tun.hpp | 2 +- llarp/iwp/iwp.cpp | 72 - llarp/iwp/iwp.hpp | 40 - llarp/iwp/linklayer.cpp | 115 -- llarp/iwp/linklayer.hpp | 63 - llarp/iwp/message_buffer.cpp | 194 --- llarp/iwp/message_buffer.hpp | 127 -- llarp/iwp/session.cpp | 1031 -------------- llarp/iwp/session.hpp | 275 ---- llarp/link/connection.cpp | 6 +- llarp/link/connection.hpp | 15 +- llarp/link/endpoint.cpp | 72 - llarp/link/endpoint.hpp | 38 +- llarp/link/factory.cpp | 43 - llarp/link/factory.hpp | 48 - llarp/link/link_manager.cpp | 222 ++- llarp/link/link_manager.hpp | 135 +- llarp/link/server.cpp | 20 +- llarp/link/server.hpp | 278 ---- llarp/link/session.cpp | 11 - llarp/link/session.hpp | 138 -- llarp/lokinet_shared.cpp | 2 +- llarp/messages/dht_immediate.cpp | 4 +- llarp/messages/dht_immediate.hpp | 2 +- llarp/messages/discard.hpp | 4 +- llarp/messages/link_intro.cpp | 4 +- llarp/messages/link_intro.hpp | 2 +- llarp/messages/link_message.hpp | 5 +- llarp/messages/link_message_parser.cpp | 2 +- llarp/messages/link_message_parser.hpp | 6 +- llarp/messages/relay.cpp | 10 +- llarp/messages/relay.hpp | 4 +- llarp/messages/relay_commit.cpp | 42 +- llarp/messages/relay_commit.hpp | 4 +- llarp/messages/relay_status.cpp | 21 +- llarp/messages/relay_status.hpp | 10 +- llarp/net/address_info.cpp | 185 --- llarp/net/address_info.hpp | 98 -- llarp/net/net.hpp | 1 - llarp/path/ihophandler.cpp | 6 +- llarp/path/ihophandler.hpp | 22 +- llarp/path/path.cpp | 86 +- llarp/path/path.hpp | 61 +- llarp/path/path_context.cpp | 33 +- llarp/path/path_context.hpp | 9 +- llarp/path/pathbuilder.cpp | 44 +- llarp/path/pathbuilder.hpp | 4 +- llarp/path/pathset.cpp | 10 +- llarp/path/pathset.hpp | 10 +- llarp/path/transit_hop.cpp | 65 +- llarp/path/transit_hop.hpp | 49 +- llarp/router/abstractrouter.hpp | 397 ------ llarp/router/outbound_message_handler.cpp | 14 +- llarp/router/outbound_message_handler.hpp | 6 +- llarp/router/outbound_session_maker.cpp | 4 +- llarp/router/outbound_session_maker.hpp | 12 +- llarp/router/rc_gossiper.cpp | 35 +- llarp/router/rc_gossiper.hpp | 13 +- llarp/router/rc_lookup_handler.cpp | 202 +-- llarp/router/rc_lookup_handler.hpp | 81 +- llarp/router/route_poker.cpp | 22 +- llarp/router/route_poker.hpp | 6 +- llarp/router/router.cpp | 474 +++---- llarp/router/router.hpp | 456 +++---- llarp/router_contact.hpp | 7 +- llarp/routing/handler.hpp | 26 +- llarp/routing/message.hpp | 4 +- llarp/routing/message_parser.cpp | 5 +- llarp/routing/message_parser.hpp | 4 +- llarp/routing/path_confirm_message.cpp | 2 +- llarp/routing/path_confirm_message.hpp | 2 +- llarp/routing/path_dht_message.cpp | 4 +- llarp/routing/path_dht_message.hpp | 2 +- llarp/routing/path_latency_message.cpp | 2 +- llarp/routing/path_latency_message.hpp | 2 +- llarp/routing/path_transfer_message.cpp | 2 +- llarp/routing/path_transfer_message.hpp | 2 +- llarp/routing/transfer_traffic_message.cpp | 2 +- llarp/routing/transfer_traffic_message.hpp | 2 +- llarp/rpc/lokid_rpc_client.cpp | 764 ++++++----- llarp/rpc/lokid_rpc_client.hpp | 10 +- llarp/rpc/rpc_request.hpp | 2 +- llarp/rpc/rpc_request_definitions.hpp | 1 - llarp/rpc/rpc_server.cpp | 8 +- llarp/rpc/rpc_server.hpp | 6 +- llarp/service/auth.cpp | 10 +- llarp/service/auth.hpp | 2 +- llarp/service/context.cpp | 15 +- llarp/service/context.hpp | 4 +- llarp/service/endpoint.cpp | 97 +- llarp/service/endpoint.hpp | 12 +- llarp/service/endpoint_state.hpp | 2 +- llarp/service/lookup.cpp | 6 +- llarp/service/lookup.hpp | 2 +- llarp/service/outbound_context.cpp | 8 +- llarp/service/protocol.cpp | 8 +- llarp/service/protocol.hpp | 2 +- llarp/service/sendcontext.cpp | 8 +- llarp/tooling/hive_context.cpp | 2 +- llarp/tooling/hive_context.hpp | 2 +- llarp/tooling/router_hive.cpp | 2 +- llarp/vpn/android.hpp | 2 +- llarp/vpn/linux.hpp | 4 +- llarp/vpn/platform.hpp | 6 +- llarp/vpn/win32.cpp | 2 +- llarp/vpn/win32.hpp | 4 +- llarp/win32/wintun.cpp | 8 +- llarp/win32/wintun.hpp | 4 +- pybind/common.hpp | 2 +- pybind/llarp/handlers/pyhandler.hpp | 2 +- pybind/llarp/router.cpp | 14 +- pybind/llarp/tooling/router_hive.cpp | 2 +- pybind/module.cpp | 2 +- test/mocks/mock_context.hpp | 4 +- test/mocks/mock_vpn.hpp | 2 +- 154 files changed, 2639 insertions(+), 5903 deletions(-) delete mode 100644 llarp/iwp/iwp.cpp delete mode 100644 llarp/iwp/iwp.hpp delete mode 100644 llarp/iwp/linklayer.cpp delete mode 100644 llarp/iwp/linklayer.hpp delete mode 100644 llarp/iwp/message_buffer.cpp delete mode 100644 llarp/iwp/message_buffer.hpp delete mode 100644 llarp/iwp/session.cpp delete mode 100644 llarp/iwp/session.hpp delete mode 100644 llarp/link/endpoint.cpp delete mode 100644 llarp/link/factory.cpp delete mode 100644 llarp/link/factory.hpp delete mode 100644 llarp/link/server.hpp delete mode 100644 llarp/link/session.cpp delete mode 100644 llarp/link/session.hpp delete mode 100644 llarp/net/address_info.cpp delete mode 100644 llarp/net/address_info.hpp delete mode 100644 llarp/router/abstractrouter.hpp diff --git a/include/llarp.hpp b/include/llarp.hpp index 2d00bdeba4..50955b868a 100644 --- a/include/llarp.hpp +++ b/include/llarp.hpp @@ -21,7 +21,7 @@ namespace llarp struct Config; struct Crypto; struct CryptoManager; - struct AbstractRouter; + struct Router; class NodeDB; namespace thread @@ -40,7 +40,7 @@ namespace llarp { std::shared_ptr crypto = nullptr; std::shared_ptr cryptoManager = nullptr; - std::shared_ptr router = nullptr; + std::shared_ptr router = nullptr; std::shared_ptr loop = nullptr; std::shared_ptr nodedb = nullptr; @@ -89,7 +89,7 @@ namespace llarp /// Creates a router. Can be overridden to allow a different class of router /// to be created instead. Defaults to llarp::Router. - virtual std::shared_ptr + virtual std::shared_ptr makeRouter(const std::shared_ptr& loop); /// create the nodedb given our current configs diff --git a/jni/lokinet_daemon.cpp b/jni/lokinet_daemon.cpp index 8bd90f5106..98b6e8b5a2 100644 --- a/jni/lokinet_daemon.cpp +++ b/jni/lokinet_daemon.cpp @@ -2,7 +2,7 @@ #include "lokinet_jni_common.hpp" #include #include -#include +#include extern "C" { @@ -85,7 +85,7 @@ extern "C" Java_network_loki_lokinet_LokinetDaemon_GetUDPSocket(JNIEnv* env, jobject self) { if (auto ptr = GetImpl(env, self); ptr and ptr->router) - return ptr->router->OutboundUDPSocket(); + return ptr->router->outbound_socket(); return -1; } diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index 4dfdc98a93..cf8a86fb94 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -194,25 +194,14 @@ add_library(lokinet-layer-onion messages/relay_status.cpp ) -# lokinet-layer-wire is a layer 1 analog which splits up -# layer 2 frames into layer 1 symbols which in the case of iwp are encrypted udp/ip packets -add_library(lokinet-layer-wire - STATIC - iwp/iwp.cpp - iwp/linklayer.cpp - iwp/message_buffer.cpp - iwp/session.cpp -) # lokinet-layer-link is for our layer 2 analog which splits up layer 2 frames into # a series of layer 1 symbols which are then transmitted between lokinet instances add_library(lokinet-layer-link STATIC link/connection.cpp - link/endpoint.cpp link/link_manager.cpp link/session.cpp - link/server.cpp messages/dht_immediate.cpp messages/link_intro.cpp messages/link_message_parser.cpp @@ -454,7 +443,6 @@ link_lokinet_layers( lokinet-layer-routing lokinet-layer-onion lokinet-layer-link - lokinet-layer-wire ) # set me to OFF to disable old codepath @@ -481,7 +469,6 @@ target_link_libraries(lokinet-layers INTERFACE lokinet-layer-routing lokinet-layer-onion lokinet-layer-link - lokinet-layer-wire ) diff --git a/llarp/apple/route_manager.hpp b/llarp/apple/route_manager.hpp index 69403c04d5..7dfc37e78e 100644 --- a/llarp/apple/route_manager.hpp +++ b/llarp/apple/route_manager.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include "context_wrapper.h" diff --git a/llarp/apple/vpn_interface.cpp b/llarp/apple/vpn_interface.cpp index f0b3a6c32d..3f128ad17b 100644 --- a/llarp/apple/vpn_interface.cpp +++ b/llarp/apple/vpn_interface.cpp @@ -1,7 +1,7 @@ #include "vpn_interface.hpp" #include "context.hpp" -#include +#include namespace llarp::apple { @@ -9,7 +9,7 @@ namespace llarp::apple Context& ctx, packet_write_callback packet_writer, on_readable_callback on_readable, - AbstractRouter* router) + Router* router) : vpn::NetworkInterface{{}} , m_PacketWriter{std::move(packet_writer)} , m_OnReadable{std::move(on_readable)} diff --git a/llarp/apple/vpn_interface.hpp b/llarp/apple/vpn_interface.hpp index b030afd9a9..787eb4ebbe 100644 --- a/llarp/apple/vpn_interface.hpp +++ b/llarp/apple/vpn_interface.hpp @@ -20,7 +20,7 @@ namespace llarp::apple Context& ctx, packet_write_callback packet_writer, on_readable_callback on_readable, - AbstractRouter* router); + Router* router); // Method to call when a packet has arrived to deliver the packet to lokinet bool @@ -50,7 +50,7 @@ namespace llarp::apple thread::Queue m_ReadQueue{PacketQueueSize}; - AbstractRouter* const _router; + Router* const _router; }; } // namespace llarp::apple diff --git a/llarp/apple/vpn_platform.cpp b/llarp/apple/vpn_platform.cpp index 1d1eafb8e4..bc34f6d5ca 100644 --- a/llarp/apple/vpn_platform.cpp +++ b/llarp/apple/vpn_platform.cpp @@ -16,7 +16,7 @@ namespace llarp::apple {} std::shared_ptr - VPNPlatform::ObtainInterface(vpn::InterfaceInfo, AbstractRouter* router) + VPNPlatform::ObtainInterface(vpn::InterfaceInfo, Router* router) { return std::make_shared(m_Context, m_PacketWriter, m_OnReadable, router); } diff --git a/llarp/apple/vpn_platform.hpp b/llarp/apple/vpn_platform.hpp index 3e9023ee67..b5b4361684 100644 --- a/llarp/apple/vpn_platform.hpp +++ b/llarp/apple/vpn_platform.hpp @@ -17,7 +17,7 @@ namespace llarp::apple void* callback_context); std::shared_ptr - ObtainInterface(vpn::InterfaceInfo, AbstractRouter*) override; + ObtainInterface(vpn::InterfaceInfo, Router*) override; vpn::IRouteManager& RouteManager() override diff --git a/llarp/consensus/reachability_testing.cpp b/llarp/consensus/reachability_testing.cpp index f238907d01..511f49a43d 100644 --- a/llarp/consensus/reachability_testing.cpp +++ b/llarp/consensus/reachability_testing.cpp @@ -1,7 +1,7 @@ #include "reachability_testing.hpp" #include -#include +#include #include #include @@ -72,7 +72,7 @@ namespace llarp::consensus } std::optional - reachability_testing::next_random(AbstractRouter* router, const time_point_t& now, bool requeue) + reachability_testing::next_random(Router* router, const time_point_t& now, bool requeue) { if (next_general_test > now) return std::nullopt; @@ -104,7 +104,7 @@ namespace llarp::consensus // We exhausted the queue so repopulate it and try again testing_queue.clear(); - const auto all = router->GetRouterWhitelist(); + const auto all = router->router_whitelist(); testing_queue.insert(testing_queue.begin(), all.begin(), all.end()); std::shuffle(testing_queue.begin(), testing_queue.end(), rng); diff --git a/llarp/consensus/reachability_testing.hpp b/llarp/consensus/reachability_testing.hpp index ecea880393..9792c3ceec 100644 --- a/llarp/consensus/reachability_testing.hpp +++ b/llarp/consensus/reachability_testing.hpp @@ -12,7 +12,7 @@ namespace llarp { - struct AbstractRouter; + struct Router; } namespace llarp::consensus @@ -117,8 +117,7 @@ namespace llarp::consensus // `requeue` is mainly for internal use: if false it avoids rebuilding the queue if we run // out (and instead just return nullopt). std::optional - next_random( - AbstractRouter* router, const time_point_t& now = clock_t::now(), bool requeue = true); + next_random(Router* router, const time_point_t& now = clock_t::now(), bool requeue = true); // Removes and returns up to MAX_RETESTS_PER_TICK nodes that are due to be tested (i.e. // next-testing-time <= now). Returns [snrecord, #previous-failures] for each. diff --git a/llarp/context.cpp b/llarp/context.cpp index 487a240661..621c99cf11 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -90,10 +90,10 @@ namespace llarp Context::makeNodeDB() { return std::make_shared( - nodedb_dirname, [r = router.get()](auto call) { r->QueueDiskIO(std::move(call)); }); + nodedb_dirname, [r = router.get()](auto call) { r->queue_disk_io(std::move(call)); }); } - std::shared_ptr + std::shared_ptr Context::makeRouter(const EventLoop_ptr& loop) { return std::make_shared(loop, makeVPNPlatform()); diff --git a/llarp/dht/context.cpp b/llarp/dht/context.cpp index 5bd9f7ad19..c9231df166 100644 --- a/llarp/dht/context.cpp +++ b/llarp/dht/context.cpp @@ -15,7 +15,7 @@ #include "taglookup.hpp" #include #include -#include +#include #include #include #include @@ -39,7 +39,7 @@ namespace llarp::dht void StoreRC(const RouterContact rc) const override { - GetRouter()->rcLookupHandler().CheckRC(rc); + GetRouter()->rc_lookup_handler().check_rc(rc); } void @@ -148,7 +148,7 @@ namespace llarp::dht /// initialize dht context and explore every exploreInterval milliseconds void - Init(const Key_t& us, AbstractRouter* router) override; + Init(const Key_t& us, Router* router) override; /// get localally stored introset by service address std::optional @@ -161,7 +161,7 @@ namespace llarp::dht void Explore(size_t N = 3); - llarp::AbstractRouter* router{nullptr}; + llarp::Router* router{nullptr}; // for router contacts std::unique_ptr> _nodes; @@ -211,7 +211,7 @@ namespace llarp::dht return ourKey; } - llarp::AbstractRouter* + llarp::Router* GetRouter() const override { return router; @@ -220,7 +220,7 @@ namespace llarp::dht bool GetRCFromNodeDB(const Key_t& k, llarp::RouterContact& rc) const override { - if (const auto maybe = router->nodedb()->Get(k.as_array()); maybe.has_value()) + if (const auto maybe = router->node_db()->Get(k.as_array()); maybe.has_value()) { rc = *maybe; return true; @@ -387,7 +387,7 @@ namespace llarp::dht replies.emplace_back(new GotRouterMessage(requester, txid, {}, false)); return; } - const auto rc = GetRouter()->nodedb()->FindClosestTo(target); + const auto rc = GetRouter()->node_db()->FindClosestTo(target); const Key_t next(rc.pubkey); { if (next == target) @@ -468,7 +468,7 @@ namespace llarp::dht } void - DHTMessageHandler::Init(const Key_t& us, AbstractRouter* r) + DHTMessageHandler::Init(const Key_t& us, Router* r) { router = r; ourKey = us; @@ -502,7 +502,7 @@ namespace llarp::dht return false; if (not reply.dht_msgs.empty()) { - auto path = router->pathContext().GetByUpstream(router->pubkey(), id); + auto path = router->path_context().GetByUpstream(router->pubkey(), id); return path && path->SendRoutingMessage(reply, router); } return true; @@ -622,7 +622,7 @@ namespace llarp::dht { const RouterID id = f.as_array(); // discard shit routers - if (router->routerProfiling().IsBadForConnect(id)) + if (router->router_profiling().IsBadForConnect(id)) continue; closer.emplace_back(id); } diff --git a/llarp/dht/context.hpp b/llarp/dht/context.hpp index 5fc17ec819..292ae862fb 100644 --- a/llarp/dht/context.hpp +++ b/llarp/dht/context.hpp @@ -19,7 +19,7 @@ namespace llarp { - struct AbstractRouter; + struct Router; namespace dht { @@ -130,7 +130,7 @@ namespace llarp uint64_t relayOrder) = 0; virtual void - Init(const Key_t& us, AbstractRouter* router) = 0; + Init(const Key_t& us, Router* router) = 0; virtual std::optional GetIntroSetByLocation(const Key_t& location) const = 0; @@ -141,7 +141,7 @@ namespace llarp virtual void ExploreNetworkVia(const Key_t& peer) = 0; - virtual llarp::AbstractRouter* + virtual llarp::Router* GetRouter() const = 0; virtual bool @@ -204,8 +204,8 @@ namespace llarp struct llarp_dht_context { std::unique_ptr impl; - llarp::AbstractRouter* parent; - llarp_dht_context(llarp::AbstractRouter* router); + llarp::Router* parent; + llarp_dht_context(llarp::Router* router); }; #endif diff --git a/llarp/dht/dht.cpp b/llarp/dht/dht.cpp index 8dbecfc8c1..8b1b1b4fcc 100644 --- a/llarp/dht/dht.cpp +++ b/llarp/dht/dht.cpp @@ -2,14 +2,14 @@ #include "dht.h" #include -llarp_dht_context::llarp_dht_context(llarp::AbstractRouter* router) +llarp_dht_context::llarp_dht_context(llarp::Router* router) { parent = router; impl = llarp::dht::make_handler(); } struct llarp_dht_context* -llarp_dht_context_new(llarp::AbstractRouter* router) +llarp_dht_context_new(llarp::Router* router) { return new llarp_dht_context(router); } diff --git a/llarp/dht/dht.h b/llarp/dht/dht.h index 20ce470c7e..618b113509 100644 --- a/llarp/dht/dht.h +++ b/llarp/dht/dht.h @@ -14,12 +14,12 @@ struct llarp_dht_context; namespace llarp { - struct AbstractRouter; + struct Router; } /// allocator struct llarp_dht_context* -llarp_dht_context_new(llarp::AbstractRouter* parent); +llarp_dht_context_new(llarp::Router* parent); /// deallocator void diff --git a/llarp/dht/explorenetworkjob.cpp b/llarp/dht/explorenetworkjob.cpp index 55c35a33c5..e0c7ebc02e 100644 --- a/llarp/dht/explorenetworkjob.cpp +++ b/llarp/dht/explorenetworkjob.cpp @@ -2,7 +2,7 @@ #include "context.hpp" #include -#include +#include #include @@ -33,7 +33,7 @@ namespace llarp for (const auto& pk : valuesFound) { // lookup router - if (router and router->nodedb()->Has(pk)) + if (router and router->node_db()->Has(pk)) continue; parent->LookupRouter( pk, [router, pk](const auto& res) { router->HandleDHTLookupForExplore(pk, res); }); diff --git a/llarp/dht/localrouterlookup.cpp b/llarp/dht/localrouterlookup.cpp index 2482e37ce4..aeb8fafa95 100644 --- a/llarp/dht/localrouterlookup.cpp +++ b/llarp/dht/localrouterlookup.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include @@ -19,7 +19,7 @@ namespace llarp::dht LocalRouterLookup::SendReply() { auto path = - parent->GetRouter()->pathContext().GetByUpstream(parent->OurKey().as_array(), localPath); + parent->GetRouter()->path_context().GetByUpstream(parent->OurKey().as_array(), localPath); if (!path) { llarp::LogWarn( diff --git a/llarp/dht/localserviceaddresslookup.cpp b/llarp/dht/localserviceaddresslookup.cpp index 4644831a22..45333d61fe 100644 --- a/llarp/dht/localserviceaddresslookup.cpp +++ b/llarp/dht/localserviceaddresslookup.cpp @@ -3,7 +3,7 @@ #include "context.hpp" #include #include -#include +#include #include #include @@ -24,7 +24,7 @@ namespace llarp::dht LocalServiceAddressLookup::SendReply() { auto path = - parent->GetRouter()->pathContext().GetByUpstream(parent->OurKey().as_array(), localPath); + parent->GetRouter()->path_context().GetByUpstream(parent->OurKey().as_array(), localPath); if (!path) { llarp::LogWarn( diff --git a/llarp/dht/localtaglookup.cpp b/llarp/dht/localtaglookup.cpp index 2e6e7f65cb..435d770a7a 100644 --- a/llarp/dht/localtaglookup.cpp +++ b/llarp/dht/localtaglookup.cpp @@ -3,7 +3,7 @@ #include "context.hpp" #include #include -#include +#include #include namespace llarp::dht @@ -20,7 +20,7 @@ namespace llarp::dht LocalTagLookup::SendReply() { auto path = - parent->GetRouter()->pathContext().GetByUpstream(parent->OurKey().as_array(), localPath); + parent->GetRouter()->path_context().GetByUpstream(parent->OurKey().as_array(), localPath); if (!path) { llarp::LogWarn( diff --git a/llarp/dht/messages/findintro.cpp b/llarp/dht/messages/findintro.cpp index 93c1609656..7a3706cfc7 100644 --- a/llarp/dht/messages/findintro.cpp +++ b/llarp/dht/messages/findintro.cpp @@ -2,7 +2,7 @@ #include "findintro.hpp" #include "gotintro.hpp" #include -#include +#include #include namespace llarp::dht @@ -92,7 +92,7 @@ namespace llarp::dht } auto closestRCs = - dht.GetRouter()->nodedb()->FindManyClosestTo(location, IntroSetStorageRedundancy); + dht.GetRouter()->node_db()->FindManyClosestTo(location, IntroSetStorageRedundancy); if (closestRCs.size() <= relayOrder) { diff --git a/llarp/dht/messages/findname.cpp b/llarp/dht/messages/findname.cpp index 2559313983..aefa638630 100644 --- a/llarp/dht/messages/findname.cpp +++ b/llarp/dht/messages/findname.cpp @@ -2,7 +2,7 @@ #include #include #include "gotname.hpp" -#include +#include #include #include #include @@ -51,9 +51,9 @@ namespace llarp::dht auto router = dht.GetRouter(); if (pathID.IsZero() or not router->IsServiceNode()) return false; - router->RpcClient()->LookupLNSNameHash( + router->rpc_client()->LookupLNSNameHash( NameHash, [router, pathID = pathID, TxID = TxID](auto maybe) { - auto path = router->pathContext().GetPathForTransfer(pathID); + auto path = router->path_context().GetPathForTransfer(pathID); if (path == nullptr) return; routing::PathDHTMessage msg; diff --git a/llarp/dht/messages/findrouter.cpp b/llarp/dht/messages/findrouter.cpp index e902b7d7a2..a226723046 100644 --- a/llarp/dht/messages/findrouter.cpp +++ b/llarp/dht/messages/findrouter.cpp @@ -4,7 +4,7 @@ #include "gotrouter.hpp" #include #include -#include +#include #include #include @@ -21,7 +21,7 @@ namespace llarp::dht const Key_t k{targetKey}; if (k == us) { - auto path = dht.GetRouter()->pathContext().GetByUpstream(targetKey, pathID); + auto path = dht.GetRouter()->path_context().GetByUpstream(targetKey, pathID); if (path) { replies.emplace_back(new GotRouterMessage(k, txid, {dht.GetRouter()->rc()}, false)); @@ -39,7 +39,7 @@ namespace llarp::dht return true; } // check netdb - const auto rc = dht.GetRouter()->nodedb()->FindClosestTo(k); + const auto rc = dht.GetRouter()->node_db()->FindClosestTo(k); if (rc.pubkey == targetKey) { replies.emplace_back(new GotRouterMessage(k, txid, {rc}, false)); @@ -122,7 +122,7 @@ namespace llarp::dht std::vector>& replies) const { auto router = dht.GetRouter(); - router->NotifyRouterEvent(router->pubkey(), *this); + router->notify_router_event(router->pubkey(), *this); if (!dht.AllowTransit()) { diff --git a/llarp/dht/messages/gotintro.cpp b/llarp/dht/messages/gotintro.cpp index 43d1355752..9be5a0e5f8 100644 --- a/llarp/dht/messages/gotintro.cpp +++ b/llarp/dht/messages/gotintro.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include @@ -22,7 +22,7 @@ namespace llarp::dht { auto* router = dht.GetRouter(); - router->NotifyRouterEvent( + router->notify_router_event( router->pubkey(), Key_t(From.data()), (found.size() > 0 ? found[0] : llarp::service::EncryptedIntroSet{}), @@ -64,7 +64,7 @@ namespace llarp::dht [[maybe_unused]] std::vector>& replies) const { // TODO: implement me better? - auto pathset = dht.GetRouter()->pathContext().GetLocalPathSet(pathID); + auto pathset = dht.GetRouter()->path_context().GetLocalPathSet(pathID); if (pathset) { auto copy = std::make_shared(*this); diff --git a/llarp/dht/messages/gotname.cpp b/llarp/dht/messages/gotname.cpp index 720786d2d3..1f927e31b2 100644 --- a/llarp/dht/messages/gotname.cpp +++ b/llarp/dht/messages/gotname.cpp @@ -1,7 +1,7 @@ #include "gotname.hpp" #include #include -#include +#include #include namespace llarp::dht @@ -60,7 +60,7 @@ namespace llarp::dht GotNameMessage::handle_message( AbstractDHTMessageHandler& dht, std::vector>&) const { - auto pathset = dht.GetRouter()->pathContext().GetLocalPathSet(pathID); + auto pathset = dht.GetRouter()->path_context().GetLocalPathSet(pathID); if (pathset == nullptr) return false; auto copy = std::make_shared(*this); diff --git a/llarp/dht/messages/gotrouter.cpp b/llarp/dht/messages/gotrouter.cpp index 040570bfb3..4113c0b3b2 100644 --- a/llarp/dht/messages/gotrouter.cpp +++ b/llarp/dht/messages/gotrouter.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include @@ -80,7 +80,7 @@ namespace llarp::dht { if (relayed) { - auto pathset = dht.GetRouter()->pathContext().GetLocalPathSet(pathID); + auto pathset = dht.GetRouter()->path_context().GetLocalPathSet(pathID); auto copy = std::make_shared(*this); return pathset && pathset->HandleGotRouterMessage(copy); } @@ -113,15 +113,15 @@ namespace llarp::dht // store if valid for (const auto& rc : foundRCs) { - if (not dht.GetRouter()->rcLookupHandler().CheckRC(rc)) + if (not dht.GetRouter()->rc_lookup_handler().check_rc(rc)) return false; if (txid == 0) // txid == 0 on gossip { auto* router = dht.GetRouter(); - router->NotifyRouterEvent(router->pubkey(), rc); + router->notify_router_event(router->pubkey(), rc); router->GossipRCIfNeeded(rc); - auto peerDb = router->peerDb(); + auto peerDb = router->peer_db(); if (peerDb) peerDb->handleGossipedRC(rc); } diff --git a/llarp/dht/messages/pubintro.cpp b/llarp/dht/messages/pubintro.cpp index a5c6cfee79..13bb0b6197 100644 --- a/llarp/dht/messages/pubintro.cpp +++ b/llarp/dht/messages/pubintro.cpp @@ -3,7 +3,7 @@ #include #include "gotintro.hpp" #include -#include +#include #include #include @@ -79,7 +79,8 @@ namespace llarp::dht } // identify closest 4 routers - auto closestRCs = dht.GetRouter()->nodedb()->FindManyClosestTo(addr, IntroSetStorageRedundancy); + auto closestRCs = + dht.GetRouter()->node_db()->FindManyClosestTo(addr, IntroSetStorageRedundancy); if (closestRCs.size() != IntroSetStorageRedundancy) { llarp::LogWarn("Received PublishIntroMessage but only know ", closestRCs.size(), " nodes"); diff --git a/llarp/dht/publishservicejob.cpp b/llarp/dht/publishservicejob.cpp index 7c00ffeac8..0420688c3c 100644 --- a/llarp/dht/publishservicejob.cpp +++ b/llarp/dht/publishservicejob.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include namespace llarp::dht @@ -59,7 +59,7 @@ namespace llarp::dht LocalPublishServiceJob::SendReply() { auto path = - parent->GetRouter()->pathContext().GetByUpstream(parent->OurKey().as_array(), localPath); + parent->GetRouter()->path_context().GetByUpstream(parent->OurKey().as_array(), localPath); if (!path) { llarp::LogWarn( diff --git a/llarp/dht/recursiverouterlookup.cpp b/llarp/dht/recursiverouterlookup.cpp index d1812e7b44..6ae5096a1a 100644 --- a/llarp/dht/recursiverouterlookup.cpp +++ b/llarp/dht/recursiverouterlookup.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include @@ -49,7 +49,7 @@ namespace llarp RouterContact found; for (const auto& rc : valuesFound) { - if (found.OtherIsNewer(rc) && parent->GetRouter()->rcLookupHandler().CheckRC(rc)) + if (found.OtherIsNewer(rc) && parent->GetRouter()->rc_lookup_handler().check_rc(rc)) found = rc; } valuesFound.clear(); diff --git a/llarp/exit/context.cpp b/llarp/exit/context.cpp index e229262ba2..fdf0a3118e 100644 --- a/llarp/exit/context.cpp +++ b/llarp/exit/context.cpp @@ -2,126 +2,123 @@ #include #include -namespace llarp +namespace llarp::exit { - namespace exit - { - Context::Context(AbstractRouter* r) : m_Router(r) - {} - Context::~Context() = default; + Context::Context(Router* r) : router(r) + {} + Context::~Context() = default; - void - Context::Tick(llarp_time_t now) + void + Context::Tick(llarp_time_t now) + { { + auto itr = m_Exits.begin(); + while (itr != m_Exits.end()) { - auto itr = m_Exits.begin(); - while (itr != m_Exits.end()) - { - itr->second->Tick(now); - ++itr; - } - } - { - auto itr = m_Closed.begin(); - while (itr != m_Closed.end()) - { - if ((*itr)->ShouldRemove()) - itr = m_Closed.erase(itr); - else - ++itr; - } + itr->second->Tick(now); + ++itr; } } - - void - Context::Stop() { - auto itr = m_Exits.begin(); - while (itr != m_Exits.end()) + auto itr = m_Closed.begin(); + while (itr != m_Closed.end()) { - itr->second->Stop(); - m_Closed.emplace_back(std::move(itr->second)); - itr = m_Exits.erase(itr); + if ((*itr)->ShouldRemove()) + itr = m_Closed.erase(itr); + else + ++itr; } } + } - util::StatusObject - Context::ExtractStatus() const + void + Context::Stop() + { + auto itr = m_Exits.begin(); + while (itr != m_Exits.end()) { - util::StatusObject obj{}; - auto itr = m_Exits.begin(); - while (itr != m_Exits.end()) - { - obj[itr->first] = itr->second->ExtractStatus(); - ++itr; - } - return obj; + itr->second->Stop(); + m_Closed.emplace_back(std::move(itr->second)); + itr = m_Exits.erase(itr); } + } - void - Context::CalculateExitTraffic(TrafficStats& stats) + util::StatusObject + Context::ExtractStatus() const + { + util::StatusObject obj{}; + auto itr = m_Exits.begin(); + while (itr != m_Exits.end()) { - auto itr = m_Exits.begin(); - while (itr != m_Exits.end()) - { - itr->second->CalculateTrafficStats(stats); - ++itr; - } + obj[itr->first] = itr->second->ExtractStatus(); + ++itr; } + return obj; + } - exit::Endpoint* - Context::FindEndpointForPath(const PathID_t& path) const + void + Context::CalculateExitTraffic(TrafficStats& stats) + { + auto itr = m_Exits.begin(); + while (itr != m_Exits.end()) { - auto itr = m_Exits.begin(); - while (itr != m_Exits.end()) - { - auto ep = itr->second->FindEndpointByPath(path); - if (ep) - return ep; - ++itr; - } - return nullptr; + itr->second->CalculateTrafficStats(stats); + ++itr; } + } - bool - Context::ObtainNewExit(const PubKey& pk, const PathID_t& path, bool permitInternet) + exit::Endpoint* + Context::FindEndpointForPath(const PathID_t& path) const + { + auto itr = m_Exits.begin(); + while (itr != m_Exits.end()) { - auto itr = m_Exits.begin(); - while (itr != m_Exits.end()) - { - if (itr->second->AllocateNewExit(pk, path, permitInternet)) - return true; - ++itr; - } - return false; + auto ep = itr->second->FindEndpointByPath(path); + if (ep) + return ep; + ++itr; } + return nullptr; + } - std::shared_ptr - Context::GetExitEndpoint(std::string name) const + bool + Context::ObtainNewExit(const PubKey& pk, const PathID_t& path, bool permitInternet) + { + auto itr = m_Exits.begin(); + while (itr != m_Exits.end()) { - if (auto itr = m_Exits.find(name); itr != m_Exits.end()) - { - return itr->second; - } - return nullptr; + if (itr->second->AllocateNewExit(pk, path, permitInternet)) + return true; + ++itr; } + return false; + } - void - Context::AddExitEndpoint( - const std::string& name, const NetworkConfig& networkConfig, const DnsConfig& dnsConfig) + std::shared_ptr + Context::GetExitEndpoint(std::string name) const + { + if (auto itr = m_Exits.find(name); itr != m_Exits.end()) { - if (m_Exits.find(name) != m_Exits.end()) - throw std::invalid_argument{fmt::format("An exit with name {} already exists", name)}; + return itr->second; + } + return nullptr; + } - auto endpoint = std::make_unique(name, m_Router); - endpoint->Configure(networkConfig, dnsConfig); + void + Context::AddExitEndpoint( + const std::string& name, const NetworkConfig& networkConfig, const DnsConfig& dnsConfig) + { + if (m_Exits.find(name) != m_Exits.end()) + throw std::invalid_argument{fmt::format("An exit with name {} already exists", name)}; - // add endpoint - if (!endpoint->Start()) - throw std::runtime_error{fmt::format("Failed to start endpoint {}", name)}; + auto endpoint = std::make_unique(name, router); + endpoint->Configure(networkConfig, dnsConfig); - m_Exits.emplace(name, std::move(endpoint)); - } + // add endpoint + if (!endpoint->Start()) + throw std::runtime_error{fmt::format("Failed to start endpoint {}", name)}; + + m_Exits.emplace(name, std::move(endpoint)); + } - } // namespace exit -} // namespace llarp +} // namespace llarp::exit diff --git a/llarp/exit/context.hpp b/llarp/exit/context.hpp index beb371aee9..7c12f60533 100644 --- a/llarp/exit/context.hpp +++ b/llarp/exit/context.hpp @@ -5,52 +5,49 @@ #include #include -namespace llarp +namespace llarp::exit { - namespace exit + /// owner of all the exit endpoints + struct Context { - /// owner of all the exit endpoints - struct Context - { - Context(AbstractRouter* r); - ~Context(); + Context(Router* r); + ~Context(); - void - Tick(llarp_time_t now); + void + Tick(llarp_time_t now); - void - ClearAllEndpoints(); + void + ClearAllEndpoints(); - util::StatusObject - ExtractStatus() const; + util::StatusObject + ExtractStatus() const; - /// send close to all exit sessions and remove all sessions - void - Stop(); + /// send close to all exit sessions and remove all sessions + void + Stop(); - void - AddExitEndpoint( - const std::string& name, const NetworkConfig& networkConfig, const DnsConfig& dnsConfig); + void + AddExitEndpoint( + const std::string& name, const NetworkConfig& networkConfig, const DnsConfig& dnsConfig); - bool - ObtainNewExit(const PubKey& remote, const PathID_t& path, bool permitInternet); + bool + ObtainNewExit(const PubKey& remote, const PathID_t& path, bool permitInternet); - exit::Endpoint* - FindEndpointForPath(const PathID_t& path) const; + exit::Endpoint* + FindEndpointForPath(const PathID_t& path) const; - /// calculate (pk, tx, rx) for all exit traffic - using TrafficStats = std::unordered_map>; + /// calculate (pk, tx, rx) for all exit traffic + using TrafficStats = std::unordered_map>; - void - CalculateExitTraffic(TrafficStats& stats); + void + CalculateExitTraffic(TrafficStats& stats); - std::shared_ptr - GetExitEndpoint(std::string name) const; + std::shared_ptr + GetExitEndpoint(std::string name) const; - private: - AbstractRouter* m_Router; - std::unordered_map> m_Exits; - std::list> m_Closed; - }; - } // namespace exit -} // namespace llarp + private: + Router* router; + std::unordered_map> m_Exits; + std::list> m_Closed; + }; +} // namespace llarp::exit diff --git a/llarp/exit/endpoint.cpp b/llarp/exit/endpoint.cpp index 2b29129dc6..7a0c418d19 100644 --- a/llarp/exit/endpoint.cpp +++ b/llarp/exit/endpoint.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include namespace llarp::exit @@ -58,7 +58,7 @@ namespace llarp::exit if (!m_Parent->UpdateEndpointPath(m_remoteSignKey, nextPath)) return false; const RouterID us{m_Parent->GetRouter()->pubkey()}; - m_CurrentPath = m_Parent->GetRouter()->pathContext().GetByUpstream(us, nextPath); + m_CurrentPath = m_Parent->GetRouter()->path_context().GetByUpstream(us, nextPath); return true; } diff --git a/llarp/exit/exit_messages.cpp b/llarp/exit/exit_messages.cpp index d850c61920..0385834f37 100644 --- a/llarp/exit/exit_messages.cpp +++ b/llarp/exit/exit_messages.cpp @@ -103,7 +103,7 @@ namespace llarp::routing } bool - ObtainExitMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + ObtainExitMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const { return h->HandleObtainExitMessage(*this, r); } @@ -179,7 +179,7 @@ namespace llarp::routing } bool - GrantExitMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + GrantExitMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const { return h->HandleGrantExitMessage(*this, r); } @@ -268,7 +268,7 @@ namespace llarp::routing } bool - RejectExitMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + RejectExitMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const { return h->HandleRejectExitMessage(*this, r); } @@ -344,7 +344,7 @@ namespace llarp::routing } bool - UpdateExitMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + UpdateExitMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const { return h->HandleUpdateExitMessage(*this, r); } @@ -383,7 +383,7 @@ namespace llarp::routing } bool - UpdateExitVerifyMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + UpdateExitVerifyMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const { return h->HandleUpdateExitVerifyMessage(*this, r); } @@ -456,7 +456,7 @@ namespace llarp::routing } bool - CloseExitMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + CloseExitMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const { return h->HandleCloseExitMessage(*this, r); } diff --git a/llarp/exit/exit_messages.hpp b/llarp/exit/exit_messages.hpp index 7dbe8975e7..18e04187ed 100644 --- a/llarp/exit/exit_messages.hpp +++ b/llarp/exit/exit_messages.hpp @@ -49,7 +49,7 @@ namespace llarp::routing decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; bool - handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + handle_message(AbstractRoutingMessageHandler* h, Router* r) const override; }; struct GrantExitMessage final : public AbstractRoutingMessage @@ -73,7 +73,7 @@ namespace llarp::routing decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; bool - handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + handle_message(AbstractRoutingMessageHandler* h, Router* r) const override; void clear() override @@ -116,7 +116,7 @@ namespace llarp::routing decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; bool - handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + handle_message(AbstractRoutingMessageHandler* h, Router* r) const override; }; struct UpdateExitVerifyMessage final : public AbstractRoutingMessage @@ -143,7 +143,7 @@ namespace llarp::routing decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; bool - handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + handle_message(AbstractRoutingMessageHandler* h, Router* r) const override; }; struct UpdateExitMessage final : public AbstractRoutingMessage @@ -167,7 +167,7 @@ namespace llarp::routing decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; bool - handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + handle_message(AbstractRoutingMessageHandler* h, Router* r) const override; void clear() override @@ -193,7 +193,7 @@ namespace llarp::routing decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; bool - handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + handle_message(AbstractRoutingMessageHandler* h, Router* r) const override; bool Sign(const llarp::SecretKey& sk); diff --git a/llarp/exit/session.cpp b/llarp/exit/session.cpp index 6d6ea988f9..a56b50d38b 100644 --- a/llarp/exit/session.cpp +++ b/llarp/exit/session.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include @@ -14,7 +14,7 @@ namespace llarp::exit BaseSession::BaseSession( const llarp::RouterID& routerId, std::function writepkt, - AbstractRouter* r, + Router* r, size_t numpaths, size_t hoplen, EndpointBase* parent) @@ -76,7 +76,7 @@ namespace llarp::exit { if (numHops == 1) { - if (auto maybe = m_router->nodedb()->Get(m_ExitRouter)) + if (auto maybe = m_router->node_db()->Get(m_ExitRouter)) return std::vector{*maybe}; return std::nullopt; } @@ -187,7 +187,7 @@ namespace llarp::exit } }; ForEachPath(sendExitClose); - m_router->pathContext().RemovePathSet(shared_from_this()); + m_router->path_context().RemovePathSet(shared_from_this()); return path::Builder::Stop(); } @@ -309,7 +309,7 @@ namespace llarp::exit if (numHops == 1) { auto r = m_router; - if (const auto maybe = r->nodedb()->Get(m_ExitRouter); maybe.has_value()) + if (const auto maybe = r->node_db()->Get(m_ExitRouter); maybe.has_value()) r->TryConnectAsync(*maybe, 5); else r->LookupRouter(m_ExitRouter, [r](const std::vector& results) { @@ -337,7 +337,7 @@ namespace llarp::exit SNodeSession::SNodeSession( const llarp::RouterID& snodeRouter, std::function writepkt, - AbstractRouter* r, + Router* r, size_t numpaths, size_t hoplen, bool useRouterSNodeKey, diff --git a/llarp/exit/session.hpp b/llarp/exit/session.hpp index 6d90a9b94f..6a34be8411 100644 --- a/llarp/exit/session.hpp +++ b/llarp/exit/session.hpp @@ -38,7 +38,7 @@ namespace llarp BaseSession( const llarp::RouterID& exitRouter, std::function writepkt, - AbstractRouter* r, + Router* r, size_t numpaths, size_t hoplen, EndpointBase* parent); @@ -198,7 +198,7 @@ namespace llarp ExitSession( const llarp::RouterID& snodeRouter, std::function writepkt, - AbstractRouter* r, + Router* r, size_t numpaths, size_t hoplen, EndpointBase* parent) @@ -228,7 +228,7 @@ namespace llarp SNodeSession( const llarp::RouterID& snodeRouter, std::function writepkt, - AbstractRouter* r, + Router* r, size_t numpaths, size_t hoplen, bool useRouterSNodeKey, diff --git a/llarp/handlers/exit.cpp b/llarp/handlers/exit.cpp index 02f898b112..018e1d2ec7 100644 --- a/llarp/handlers/exit.cpp +++ b/llarp/handlers/exit.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include @@ -13,886 +13,883 @@ #include #include -namespace llarp +namespace llarp::handlers { - namespace handlers + ExitEndpoint::ExitEndpoint(std::string name, Router* r) + : router(r) + , name(std::move(name)) + , tunnel_manager{std::make_shared(*this)} { - ExitEndpoint::ExitEndpoint(std::string name, AbstractRouter* r) - : m_Router(r), m_Name(std::move(name)), m_QUIC{std::make_shared(*this)} - { - m_ShouldInitTun = true; - m_QUIC = std::make_shared(*this); - } + should_init_tun = true; + tunnel_manager = std::make_shared(*this); + } - ExitEndpoint::~ExitEndpoint() = default; + ExitEndpoint::~ExitEndpoint() = default; - void - ExitEndpoint::LookupNameAsync( - std::string, std::function)> resultHandler) - { - // TODO: implement me - resultHandler(std::nullopt); - } + void + ExitEndpoint::LookupNameAsync( + std::string, std::function)> resultHandler) + { + // TODO: implement me + resultHandler(std::nullopt); + } - void - ExitEndpoint::LookupServiceAsync( - std::string, std::string, std::function)> resultHandler) + void + ExitEndpoint::LookupServiceAsync( + std::string, std::string, std::function)> resultHandler) + { + // TODO: implement me + resultHandler({}); + } + + std::optional + ExitEndpoint::GetEndpointWithConvoTag(service::ConvoTag tag) const + { + for (const auto& [pathID, pk] : paths) { - // TODO: implement me - resultHandler({}); + if (pathID.as_array() == tag.as_array()) + return RouterID{pk.as_array()}; } - - std::optional - ExitEndpoint::GetEndpointWithConvoTag(service::ConvoTag tag) const + for (const auto& [rid, session] : snode_sessions) { - for (const auto& [pathID, pk] : m_Paths) - { - if (pathID.as_array() == tag.as_array()) - return RouterID{pk.as_array()}; - } - for (const auto& [rid, session] : m_SNodeSessions) - { - PathID_t pathID{tag.as_array()}; - if (session->GetPathByID(pathID)) - return rid; - } - return std::nullopt; + PathID_t pathID{tag.as_array()}; + if (session->GetPathByID(pathID)) + return rid; } + return std::nullopt; + } - std::optional - ExitEndpoint::GetBestConvoTagFor(AddressVariant_t addr) const + std::optional + ExitEndpoint::GetBestConvoTagFor(AddressVariant_t addr) const + { + if (auto* rid = std::get_if(&addr)) { - if (auto* rid = std::get_if(&addr)) - { - service::ConvoTag tag{}; - auto visit = [&tag](exit::Endpoint* const ep) -> bool { - if (not ep) - return false; - if (auto path = ep->GetCurrentPath()) - tag = service::ConvoTag{path->RXID().as_array()}; - return true; - }; - if (VisitEndpointsFor(PubKey{*rid}, visit) and not tag.IsZero()) - return tag; - auto itr = m_SNodeSessions.find(*rid); - if (itr == m_SNodeSessions.end()) - { - return std::nullopt; - } - if (auto path = itr->second->GetPathByRouter(*rid)) - { + service::ConvoTag tag{}; + auto visit = [&tag](exit::Endpoint* const ep) -> bool { + if (not ep) + return false; + if (auto path = ep->GetCurrentPath()) tag = service::ConvoTag{path->RXID().as_array()}; - return tag; - } + return true; + }; + if (VisitEndpointsFor(PubKey{*rid}, visit) and not tag.IsZero()) + return tag; + auto itr = snode_sessions.find(*rid); + if (itr == snode_sessions.end()) + { return std::nullopt; } + if (auto path = itr->second->GetPathByRouter(*rid)) + { + tag = service::ConvoTag{path->RXID().as_array()}; + return tag; + } return std::nullopt; } + return std::nullopt; + } - const EventLoop_ptr& - ExitEndpoint::Loop() - { - return m_Router->loop(); - } + const EventLoop_ptr& + ExitEndpoint::Loop() + { + return router->loop(); + } - bool - ExitEndpoint::SendToOrQueue( - service::ConvoTag tag, const llarp_buffer_t& payload, service::ProtocolType type) + bool + ExitEndpoint::SendToOrQueue( + service::ConvoTag tag, const llarp_buffer_t& payload, service::ProtocolType type) + { + if (auto maybeAddr = GetEndpointWithConvoTag(tag)) { - if (auto maybeAddr = GetEndpointWithConvoTag(tag)) + if (std::holds_alternative(*maybeAddr)) + return false; + if (auto* rid = std::get_if(&*maybeAddr)) { - if (std::holds_alternative(*maybeAddr)) - return false; - if (auto* rid = std::get_if(&*maybeAddr)) + for (auto [itr, end] = active_exits.equal_range(PubKey{*rid}); itr != end; ++itr) { - for (auto [itr, end] = m_ActiveExits.equal_range(PubKey{*rid}); itr != end; ++itr) + if (not itr->second->LooksDead(Now())) { - if (not itr->second->LooksDead(Now())) - { - if (itr->second->QueueInboundTraffic(payload.copy(), type)) - return true; - } + if (itr->second->QueueInboundTraffic(payload.copy(), type)) + return true; } + } - if (not m_Router->PathToRouterAllowed(*rid)) - return false; + if (not router->PathToRouterAllowed(*rid)) + return false; - ObtainSNodeSession(*rid, [pkt = payload.copy(), type](auto session) mutable { - if (session and session->IsReady()) - { - session->SendPacketToRemote(std::move(pkt), type); - } - }); - } - return true; + ObtainSNodeSession(*rid, [pkt = payload.copy(), type](auto session) mutable { + if (session and session->IsReady()) + { + session->SendPacketToRemote(std::move(pkt), type); + } + }); } - return false; + return true; } + return false; + } - bool - ExitEndpoint::EnsurePathTo( - AddressVariant_t addr, - std::function)> hook, - llarp_time_t) + bool + ExitEndpoint::EnsurePathTo( + AddressVariant_t addr, + std::function)> hook, + llarp_time_t) + { + if (std::holds_alternative(addr)) + return false; + if (auto* rid = std::get_if(&addr)) { - if (std::holds_alternative(addr)) - return false; - if (auto* rid = std::get_if(&addr)) + if (snode_keys.count(PubKey{*rid}) or router->PathToRouterAllowed(*rid)) { - if (m_SNodeKeys.count(PubKey{*rid}) or m_Router->PathToRouterAllowed(*rid)) - { - ObtainSNodeSession( - *rid, [hook, routerID = *rid](std::shared_ptr session) { - if (session and session->IsReady()) + ObtainSNodeSession( + *rid, [hook, routerID = *rid](std::shared_ptr session) { + if (session and session->IsReady()) + { + if (auto path = session->GetPathByRouter(routerID)) { - if (auto path = session->GetPathByRouter(routerID)) - { - hook(service::ConvoTag{path->RXID().as_array()}); - } - else - hook(std::nullopt); + hook(service::ConvoTag{path->RXID().as_array()}); } else hook(std::nullopt); - }); - } - else - { - // probably a client - hook(GetBestConvoTagFor(addr)); - } + } + else + hook(std::nullopt); + }); } - return true; - } - - util::StatusObject - ExitEndpoint::ExtractStatus() const - { - util::StatusObject obj{{"permitExit", m_PermitExit}, {"ip", m_IfAddr.ToString()}}; - util::StatusObject exitsObj{}; - for (const auto& item : m_ActiveExits) + else { - exitsObj[item.first.ToString()] = item.second->ExtractStatus(); + // probably a client + hook(GetBestConvoTagFor(addr)); } - obj["exits"] = exitsObj; - return obj; } + return true; + } - bool - ExitEndpoint::SupportsV6() const + util::StatusObject + ExitEndpoint::ExtractStatus() const + { + util::StatusObject obj{{"permitExit", permit_exit}, {"ip", if_addr.ToString()}}; + util::StatusObject exitsObj{}; + for (const auto& item : active_exits) { - return m_UseV6; + exitsObj[item.first.ToString()] = item.second->ExtractStatus(); } + obj["exits"] = exitsObj; + return obj; + } - bool - ExitEndpoint::ShouldHookDNSMessage(const dns::Message& msg) const + bool + ExitEndpoint::SupportsV6() const + { + return use_ipv6; + } + + bool + ExitEndpoint::ShouldHookDNSMessage(const dns::Message& msg) const + { + if (msg.questions.size() == 0) + return false; + // always hook ptr for ranges we own + if (msg.questions[0].qtype == dns::qTypePTR) { - if (msg.questions.size() == 0) - return false; - // always hook ptr for ranges we own - if (msg.questions[0].qtype == dns::qTypePTR) - { - if (auto ip = dns::DecodePTR(msg.questions[0].qname)) - return m_OurRange.Contains(*ip); - return false; - } - if (msg.questions[0].qtype == dns::qTypeA || msg.questions[0].qtype == dns::qTypeCNAME - || msg.questions[0].qtype == dns::qTypeAAAA) - { - if (msg.questions[0].IsName("localhost.loki")) - return true; - if (msg.questions[0].HasTLD(".snode")) - return true; - } + if (auto ip = dns::DecodePTR(msg.questions[0].qname)) + return ip_range.Contains(*ip); return false; } - - bool - ExitEndpoint::MaybeHookDNS( - std::shared_ptr source, - const dns::Message& query, - const SockAddr& to, - const SockAddr& from) + if (msg.questions[0].qtype == dns::qTypeA || msg.questions[0].qtype == dns::qTypeCNAME + || msg.questions[0].qtype == dns::qTypeAAAA) { - if (not ShouldHookDNSMessage(query)) - return false; - - auto job = std::make_shared(source, query, to, from); - if (not HandleHookedDNSMessage(query, [job](auto msg) { job->SendReply(msg.ToBuffer()); })) - job->Cancel(); - return true; + if (msg.questions[0].IsName("localhost.loki")) + return true; + if (msg.questions[0].HasTLD(".snode")) + return true; } + return false; + } - bool - ExitEndpoint::HandleHookedDNSMessage(dns::Message msg, std::function reply) + bool + ExitEndpoint::MaybeHookDNS( + std::shared_ptr source, + const dns::Message& query, + const SockAddr& to, + const SockAddr& from) + { + if (not ShouldHookDNSMessage(query)) + return false; + + auto job = std::make_shared(source, query, to, from); + if (not HandleHookedDNSMessage(query, [job](auto msg) { job->SendReply(msg.ToBuffer()); })) + job->Cancel(); + return true; + } + + bool + ExitEndpoint::HandleHookedDNSMessage(dns::Message msg, std::function reply) + { + if (msg.questions[0].qtype == dns::qTypePTR) { - if (msg.questions[0].qtype == dns::qTypePTR) + auto ip = dns::DecodePTR(msg.questions[0].qname); + if (not ip) + return false; + if (ip == if_addr) { - auto ip = dns::DecodePTR(msg.questions[0].qname); - if (not ip) - return false; - if (ip == m_IfAddr) + RouterID us = GetRouter()->pubkey(); + msg.AddAReply(us.ToString(), 300); + } + else + { + auto itr = ip_to_key.find(*ip); + if (itr != ip_to_key.end() && snode_keys.find(itr->second) != snode_keys.end()) { - RouterID us = GetRouter()->pubkey(); - msg.AddAReply(us.ToString(), 300); + RouterID them = itr->second; + msg.AddAReply(them.ToString()); } else - { - auto itr = m_IPToKey.find(*ip); - if (itr != m_IPToKey.end() && m_SNodeKeys.find(itr->second) != m_SNodeKeys.end()) - { - RouterID them = itr->second; - msg.AddAReply(them.ToString()); - } - else - msg.AddNXReply(); - } + msg.AddNXReply(); } - else if (msg.questions[0].qtype == dns::qTypeCNAME) + } + else if (msg.questions[0].qtype == dns::qTypeCNAME) + { + if (msg.questions[0].IsName("random.snode")) { - if (msg.questions[0].IsName("random.snode")) - { - RouterID random; - if (GetRouter()->GetRandomGoodRouter(random)) - msg.AddCNAMEReply(random.ToString(), 1); - else - msg.AddNXReply(); - } - else if (msg.questions[0].IsName("localhost.loki")) + RouterID random; + if (GetRouter()->GetRandomGoodRouter(random)) + msg.AddCNAMEReply(random.ToString(), 1); + else + msg.AddNXReply(); + } + else if (msg.questions[0].IsName("localhost.loki")) + { + RouterID us = router->pubkey(); + msg.AddAReply(us.ToString(), 1); + } + else + msg.AddNXReply(); + } + else if (msg.questions[0].qtype == dns::qTypeA || msg.questions[0].qtype == dns::qTypeAAAA) + { + const bool isV6 = msg.questions[0].qtype == dns::qTypeAAAA; + const bool isV4 = msg.questions[0].qtype == dns::qTypeA; + if (msg.questions[0].IsName("random.snode")) + { + RouterID random; + if (GetRouter()->GetRandomGoodRouter(random)) { - RouterID us = m_Router->pubkey(); - msg.AddAReply(us.ToString(), 1); + msg.AddCNAMEReply(random.ToString(), 1); + auto ip = ObtainServiceNodeIP(random); + msg.AddINReply(ip, false); } else msg.AddNXReply(); + reply(msg); + return true; } - else if (msg.questions[0].qtype == dns::qTypeA || msg.questions[0].qtype == dns::qTypeAAAA) + if (msg.questions[0].IsName("localhost.loki")) { - const bool isV6 = msg.questions[0].qtype == dns::qTypeAAAA; - const bool isV4 = msg.questions[0].qtype == dns::qTypeA; - if (msg.questions[0].IsName("random.snode")) + msg.AddINReply(GetIfAddr(), isV6); + reply(msg); + return true; + } + // forward dns for snode + RouterID r; + if (r.FromString(msg.questions[0].Name())) + { + huint128_t ip; + PubKey pubKey(r); + if (isV4 && SupportsV6()) { - RouterID random; - if (GetRouter()->GetRandomGoodRouter(random)) - { - msg.AddCNAMEReply(random.ToString(), 1); - auto ip = ObtainServiceNodeIP(random); - msg.AddINReply(ip, false); - } - else - msg.AddNXReply(); - reply(msg); - return true; + msg.hdr_fields |= dns::flags_QR | dns::flags_AA | dns::flags_RA; } - if (msg.questions[0].IsName("localhost.loki")) + else if (snode_keys.find(pubKey) == snode_keys.end()) { - msg.AddINReply(GetIfAddr(), isV6); - reply(msg); + // we do not have it mapped, async obtain it + ObtainSNodeSession( + r, + [&, msg = std::make_shared(msg), reply]( + std::shared_ptr session) { + if (session && session->IsReady()) + { + msg->AddINReply(key_to_IP[pubKey], isV6); + } + else + { + msg->AddNXReply(); + } + reply(*msg); + }); return true; } - // forward dns for snode - RouterID r; - if (r.FromString(msg.questions[0].Name())) + else { - huint128_t ip; - PubKey pubKey(r); - if (isV4 && SupportsV6()) - { - msg.hdr_fields |= dns::flags_QR | dns::flags_AA | dns::flags_RA; - } - else if (m_SNodeKeys.find(pubKey) == m_SNodeKeys.end()) - { - // we do not have it mapped, async obtain it - ObtainSNodeSession( - r, - [&, msg = std::make_shared(msg), reply]( - std::shared_ptr session) { - if (session && session->IsReady()) - { - msg->AddINReply(m_KeyToIP[pubKey], isV6); - } - else - { - msg->AddNXReply(); - } - reply(*msg); - }); - return true; - } - else + // we have it mapped already as a service node + auto itr = key_to_IP.find(pubKey); + if (itr != key_to_IP.end()) { - // we have it mapped already as a service node - auto itr = m_KeyToIP.find(pubKey); - if (itr != m_KeyToIP.end()) - { - ip = itr->second; - msg.AddINReply(ip, isV6); - } - else // fallback case that should never happen (probably) - msg.AddNXReply(); + ip = itr->second; + msg.AddINReply(ip, isV6); } + else // fallback case that should never happen (probably) + msg.AddNXReply(); } - else - msg.AddNXReply(); } - reply(msg); - return true; + else + msg.AddNXReply(); } + reply(msg); + return true; + } - void - ExitEndpoint::ObtainSNodeSession(const RouterID& router, exit::SessionReadyFunc obtainCb) + void + ExitEndpoint::ObtainSNodeSession(const RouterID& rid, exit::SessionReadyFunc obtain_cb) + { + if (not router->rc_lookup_handler().is_session_allowed(rid)) { - if (not m_Router->rcLookupHandler().SessionIsAllowed(router)) - { - obtainCb(nullptr); - return; - } - ObtainServiceNodeIP(router); - m_SNodeSessions[router]->AddReadyHook(obtainCb); + obtain_cb(nullptr); + return; } + ObtainServiceNodeIP(rid); + snode_sessions[rid]->AddReadyHook(obtain_cb); + } - llarp_time_t - ExitEndpoint::Now() const - { - return m_Router->Now(); - } + llarp_time_t + ExitEndpoint::Now() const + { + return router->Now(); + } - bool - ExitEndpoint::VisitEndpointsFor( - const PubKey& pk, std::function visit) const + bool + ExitEndpoint::VisitEndpointsFor( + const PubKey& pk, std::function visit) const + { + for (auto [itr, end] = active_exits.equal_range(pk); itr != end; ++itr) { - for (auto [itr, end] = m_ActiveExits.equal_range(pk); itr != end; ++itr) - { - if (not visit(itr->second.get())) - return true; - } - return false; + if (not visit(itr->second.get())) + return true; } + return false; + } - void - ExitEndpoint::Flush() + void + ExitEndpoint::Flush() + { + while (not inet_to_network.empty()) { - while (not m_InetToNetwork.empty()) - { - auto& top = m_InetToNetwork.top(); + auto& top = inet_to_network.top(); - // get a session by public key - std::optional maybe_pk; - { - auto itr = m_IPToKey.find(top.dstv6()); - if (itr != m_IPToKey.end()) - maybe_pk = itr->second; - } + // get a session by public key + std::optional maybe_pk; + { + auto itr = ip_to_key.find(top.dstv6()); + if (itr != ip_to_key.end()) + maybe_pk = itr->second; + } - auto buf = const_cast(top).steal(); - m_InetToNetwork.pop(); - // we have no session for public key so drop - if (not maybe_pk) - continue; // we are in a while loop + auto buf = const_cast(top).steal(); + inet_to_network.pop(); + // we have no session for public key so drop + if (not maybe_pk) + continue; // we are in a while loop - const auto& pk = *maybe_pk; + const auto& pk = *maybe_pk; - // check if this key is a service node - if (m_SNodeKeys.count(pk)) + // check if this key is a service node + if (snode_keys.count(pk)) + { + // check if it's a service node session we made and queue it via our + // snode session that we made otherwise use an inbound session that + // was made by the other service node + auto itr = snode_sessions.find(pk); + if (itr != snode_sessions.end()) { - // check if it's a service node session we made and queue it via our - // snode session that we made otherwise use an inbound session that - // was made by the other service node - auto itr = m_SNodeSessions.find(pk); - if (itr != m_SNodeSessions.end()) - { - itr->second->SendPacketToRemote(std::move(buf), service::ProtocolType::TrafficV4); - // we are in a while loop - continue; - } + itr->second->SendPacketToRemote(std::move(buf), service::ProtocolType::TrafficV4); + // we are in a while loop + continue; } - auto tryFlushingTraffic = - [this, buf = std::move(buf), pk](exit::Endpoint* const ep) -> bool { - if (!ep->QueueInboundTraffic(buf, service::ProtocolType::TrafficV4)) - { - LogWarn( - Name(), - " dropped inbound traffic for session ", - pk, - " as we are overloaded (probably)"); - // continue iteration - return true; - } - // break iteration - return false; - }; - if (!VisitEndpointsFor(pk, tryFlushingTraffic)) + } + auto tryFlushingTraffic = [this, buf = std::move(buf), pk](exit::Endpoint* const ep) -> bool { + if (!ep->QueueInboundTraffic(buf, service::ProtocolType::TrafficV4)) { - // we may have all dead sessions, wtf now? LogWarn( Name(), " dropped inbound traffic for session ", pk, - " as we have no working endpoints"); + " as we are overloaded (probably)"); + // continue iteration + return true; } - } - - for (auto& [pubkey, endpoint] : m_ActiveExits) + // break iteration + return false; + }; + if (!VisitEndpointsFor(pk, tryFlushingTraffic)) { - if (!endpoint->Flush()) - { - LogWarn("exit session with ", pubkey, " dropped packets"); - } + // we may have all dead sessions, wtf now? + LogWarn( + Name(), + " dropped inbound traffic for session ", + pk, + " as we have no working endpoints"); } - for (auto& [id, session] : m_SNodeSessions) + } + + for (auto& [pubkey, endpoint] : active_exits) + { + if (!endpoint->Flush()) { - session->FlushUpstream(); - session->FlushDownstream(); + LogWarn("exit session with ", pubkey, " dropped packets"); } } + for (auto& [id, session] : snode_sessions) + { + session->FlushUpstream(); + session->FlushDownstream(); + } + } - bool - ExitEndpoint::Start() + bool + ExitEndpoint::Start() + { + // map our address + const PubKey us(router->pubkey()); + const huint128_t ip = GetIfAddr(); + key_to_IP[us] = ip; + ip_to_key[ip] = us; + ip_activity[ip] = std::numeric_limits::max(); + snode_keys.insert(us); + + if (should_init_tun) { - // map our address - const PubKey us(m_Router->pubkey()); - const huint128_t ip = GetIfAddr(); - m_KeyToIP[us] = ip; - m_IPToKey[ip] = us; - m_IPActivity[ip] = std::numeric_limits::max(); - m_SNodeKeys.insert(us); + vpn::InterfaceInfo info; + info.ifname = if_name; + info.addrs.emplace_back(ip_range); - if (m_ShouldInitTun) + if_net = GetRouter()->vpn_platform()->CreateInterface(std::move(info), router); + if (not if_net) { - vpn::InterfaceInfo info; - info.ifname = m_ifname; - info.addrs.emplace_back(m_OurRange); - - m_NetIf = GetRouter()->GetVPNPlatform()->CreateInterface(std::move(info), m_Router); - if (not m_NetIf) - { - llarp::LogError("Could not create interface"); - return false; - } - if (not GetRouter()->loop()->add_network_interface( - m_NetIf, [this](net::IPPacket pkt) { OnInetPacket(std::move(pkt)); })) - { - llarp::LogWarn("Could not create tunnel for exit endpoint"); - return false; - } + llarp::LogError("Could not create interface"); + return false; + } + if (not GetRouter()->loop()->add_network_interface( + if_net, [this](net::IPPacket pkt) { OnInetPacket(std::move(pkt)); })) + { + llarp::LogWarn("Could not create tunnel for exit endpoint"); + return false; + } - GetRouter()->loop()->add_ticker([this] { Flush(); }); + GetRouter()->loop()->add_ticker([this] { Flush(); }); #ifndef _WIN32 - m_Resolver = std::make_shared( - m_Router->loop(), m_DNSConf, if_nametoindex(m_ifname.c_str())); - m_Resolver->Start(); + resolver = + std::make_shared(router->loop(), dns_conf, if_nametoindex(if_name.c_str())); + resolver->Start(); #endif - } - return true; } + return true; + } - AbstractRouter* - ExitEndpoint::GetRouter() - { - return m_Router; - } + Router* + ExitEndpoint::GetRouter() + { + return router; + } - huint128_t - ExitEndpoint::GetIfAddr() const - { - return m_IfAddr; - } + huint128_t + ExitEndpoint::GetIfAddr() const + { + return if_addr; + } - bool - ExitEndpoint::Stop() - { - for (auto& item : m_SNodeSessions) - item.second->Stop(); - return true; - } + bool + ExitEndpoint::Stop() + { + for (auto& item : snode_sessions) + item.second->Stop(); + return true; + } - bool - ExitEndpoint::ShouldRemove() const - { - for (auto& item : m_SNodeSessions) - if (!item.second->ShouldRemove()) - return false; - return true; - } + bool + ExitEndpoint::ShouldRemove() const + { + for (auto& item : snode_sessions) + if (!item.second->ShouldRemove()) + return false; + return true; + } - bool - ExitEndpoint::HasLocalMappedAddrFor(const PubKey& pk) const - { - return m_KeyToIP.find(pk) != m_KeyToIP.end(); - } + bool + ExitEndpoint::HasLocalMappedAddrFor(const PubKey& pk) const + { + return key_to_IP.find(pk) != key_to_IP.end(); + } - huint128_t - ExitEndpoint::GetIPForIdent(const PubKey pk) + huint128_t + ExitEndpoint::GetIPForIdent(const PubKey pk) + { + huint128_t found{}; + if (!HasLocalMappedAddrFor(pk)) { - huint128_t found{}; - if (!HasLocalMappedAddrFor(pk)) + // allocate and map + found = AllocateNewAddress(); + if (!key_to_IP.emplace(pk, found).second) { - // allocate and map - found = AllocateNewAddress(); - if (!m_KeyToIP.emplace(pk, found).second) - { - LogError(Name(), "failed to map ", pk, " to ", found); - return found; - } - if (!m_IPToKey.emplace(found, pk).second) - { - LogError(Name(), "failed to map ", found, " to ", pk); - return found; - } - if (HasLocalMappedAddrFor(pk)) - LogInfo(Name(), " mapping ", pk, " to ", found); - else - LogError(Name(), "failed to map ", pk, " to ", found); + LogError(Name(), "failed to map ", pk, " to ", found); + return found; + } + if (!ip_to_key.emplace(found, pk).second) + { + LogError(Name(), "failed to map ", found, " to ", pk); + return found; } + if (HasLocalMappedAddrFor(pk)) + LogInfo(Name(), " mapping ", pk, " to ", found); else - found = m_KeyToIP[pk]; - - MarkIPActive(found); - m_KeyToIP.rehash(0); - assert(HasLocalMappedAddrFor(pk)); - return found; + LogError(Name(), "failed to map ", pk, " to ", found); } + else + found = key_to_IP[pk]; - huint128_t - ExitEndpoint::AllocateNewAddress() - { - if (m_NextAddr < m_HigestAddr) - return ++m_NextAddr; + MarkIPActive(found); + key_to_IP.rehash(0); + assert(HasLocalMappedAddrFor(pk)); + return found; + } - // find oldest activity ip address - huint128_t found = {0}; - llarp_time_t min = std::numeric_limits::max(); - for (const auto& [addr, time] : m_IPActivity) + huint128_t + ExitEndpoint::AllocateNewAddress() + { + if (next_addr < highest_addr) + return ++next_addr; + + // find oldest activity ip address + huint128_t found = {0}; + llarp_time_t min = std::numeric_limits::max(); + for (const auto& [addr, time] : ip_activity) + { + if (time < min) { - if (time < min) - { - found.h = addr.h; - min = time; - } + found.h = addr.h; + min = time; } - // kick old ident off exit - // TODO: DoS - PubKey pk = m_IPToKey[found]; - KickIdentOffExit(pk); - - return found; } + // kick old ident off exit + // TODO: DoS + PubKey pk = ip_to_key[found]; + KickIdentOffExit(pk); - EndpointBase::AddressVariant_t - ExitEndpoint::LocalAddress() const - { - return RouterID{m_Router->pubkey()}; - } + return found; + } - void - ExitEndpoint::SRVRecordsChanged() - { - m_Router->ModifyOurRC( - [srvRecords = SRVRecords()](RouterContact rc) -> std::optional { - // check if there are any new srv records - bool shouldUpdate = false; + EndpointBase::AddressVariant_t + ExitEndpoint::LocalAddress() const + { + return RouterID{router->pubkey()}; + } - for (const auto& rcSrv : rc.srvRecords) - { - if (srvRecords.count(rcSrv) == 0) - shouldUpdate = true; - } + void + ExitEndpoint::SRVRecordsChanged() + { + router->modify_rc( + [srvRecords = SRVRecords()](RouterContact rc) -> std::optional { + // check if there are any new srv records + bool shouldUpdate = false; - // no new records so don't modify - if (not shouldUpdate) - return std::nullopt; + for (const auto& rcSrv : rc.srvRecords) + { + if (srvRecords.count(rcSrv) == 0) + shouldUpdate = true; + } - // 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; - return rc; - }); - } + // 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(); + for (auto& record : srvRecords) + rc.srvRecords.emplace_back(record); + // set the verssion to 1 because we have srv records + rc.version = 1; + return rc; + }); + } - std::optional - ExitEndpoint::GetStatFor(AddressVariant_t) const - { - /// TODO: implement me - return std::nullopt; - } + std::optional + ExitEndpoint::GetStatFor(AddressVariant_t) const + { + /// TODO: implement me + return std::nullopt; + } - std::unordered_set - ExitEndpoint::AllRemoteEndpoints() const + std::unordered_set + ExitEndpoint::AllRemoteEndpoints() const + { + std::unordered_set remote; + for (const auto& [path, pubkey] : paths) { - std::unordered_set remote; - for (const auto& [path, pubkey] : m_Paths) - { - remote.insert(RouterID{pubkey}); - } - return remote; + remote.insert(RouterID{pubkey}); } + return remote; + } - bool - ExitEndpoint::QueueOutboundTraffic(net::IPPacket pkt) - { - return m_NetIf && m_NetIf->WritePacket(std::move(pkt)); - } + bool + ExitEndpoint::QueueOutboundTraffic(net::IPPacket pkt) + { + return if_net && if_net->WritePacket(std::move(pkt)); + } - void - ExitEndpoint::KickIdentOffExit(const PubKey& pk) - { - LogInfo(Name(), " kicking ", pk, " off exit"); - huint128_t ip = m_KeyToIP[pk]; - m_KeyToIP.erase(pk); - m_IPToKey.erase(ip); - for (auto [exit_itr, end] = m_ActiveExits.equal_range(pk); exit_itr != end;) - exit_itr = m_ActiveExits.erase(exit_itr); - } + void + ExitEndpoint::KickIdentOffExit(const PubKey& pk) + { + LogInfo(Name(), " kicking ", pk, " off exit"); + huint128_t ip = key_to_IP[pk]; + key_to_IP.erase(pk); + ip_to_key.erase(ip); + for (auto [exit_itr, end] = active_exits.equal_range(pk); exit_itr != end;) + exit_itr = active_exits.erase(exit_itr); + } + + void + ExitEndpoint::MarkIPActive(huint128_t ip) + { + ip_activity[ip] = GetRouter()->Now(); + } - void - ExitEndpoint::MarkIPActive(huint128_t ip) - { - m_IPActivity[ip] = GetRouter()->Now(); - } + void + ExitEndpoint::OnInetPacket(net::IPPacket pkt) + { + inet_to_network.emplace(std::move(pkt)); + } - void - ExitEndpoint::OnInetPacket(net::IPPacket pkt) - { - m_InetToNetwork.emplace(std::move(pkt)); - } + bool + ExitEndpoint::QueueSNodePacket(const llarp_buffer_t& buf, huint128_t from) + { + net::IPPacket pkt{buf.view_all()}; + if (pkt.empty()) + return false; + // rewrite ip + if (use_ipv6) + pkt.UpdateIPv6Address(from, if_addr); + else + pkt.UpdateIPv4Address(xhtonl(net::TruncateV6(from)), xhtonl(net::TruncateV6(if_addr))); + return if_net and if_net->WritePacket(std::move(pkt)); + } + + exit::Endpoint* + ExitEndpoint::FindEndpointByPath(const PathID_t& path) + { + exit::Endpoint* endpoint = nullptr; + PubKey pk; + if (auto itr = paths.find(path); itr != paths.end()) + pk = itr->second; + else + return nullptr; + if (auto itr = active_exits.find(pk); itr != active_exits.end()) + { + if (itr->second->PubKey() == pk) + endpoint = itr->second.get(); + } + return endpoint; + } + + bool + ExitEndpoint::UpdateEndpointPath(const PubKey& remote, const PathID_t& next) + { + // check if already mapped + if (auto itr = paths.find(next); itr != paths.end()) + return false; + paths.emplace(next, remote); + return true; + } - bool - ExitEndpoint::QueueSNodePacket(const llarp_buffer_t& buf, huint128_t from) + void + ExitEndpoint::Configure(const NetworkConfig& networkConfig, const DnsConfig& dnsConfig) + { + /* + * TODO: pre-config refactor, this was checking a couple things that were extremely vague + * these could have appeared on either [dns] or [network], but they weren't documented + * anywhere + * + if (k == "type" && v == "null") + { + m_ShouldInitTun = false; + return true; + } + if (k == "exit") { - net::IPPacket pkt{buf.view_all()}; - if (pkt.empty()) - return false; - // rewrite ip - if (m_UseV6) - pkt.UpdateIPv6Address(from, m_IfAddr); - else - pkt.UpdateIPv4Address(xhtonl(net::TruncateV6(from)), xhtonl(net::TruncateV6(m_IfAddr))); - return m_NetIf and m_NetIf->WritePacket(std::move(pkt)); + m_PermitExit = IsTrueValue(v.c_str()); + return true; } + */ + + dns_conf = dnsConfig; - exit::Endpoint* - ExitEndpoint::FindEndpointByPath(const PathID_t& path) + if (networkConfig.m_endpointType == "null") { - exit::Endpoint* endpoint = nullptr; - PubKey pk; - if (auto itr = m_Paths.find(path); itr != m_Paths.end()) - pk = itr->second; - else - return nullptr; - if (auto itr = m_ActiveExits.find(pk); itr != m_ActiveExits.end()) - { - if (itr->second->PubKey() == pk) - endpoint = itr->second.get(); - } - return endpoint; + should_init_tun = false; } - bool - ExitEndpoint::UpdateEndpointPath(const PubKey& remote, const PathID_t& next) + ip_range = networkConfig.m_ifaddr; + if (!ip_range.addr.h) { - // check if already mapped - if (auto itr = m_Paths.find(next); itr != m_Paths.end()) - return false; - m_Paths.emplace(next, remote); - return true; + const auto maybe = router->net().FindFreeRange(); + if (not maybe.has_value()) + throw std::runtime_error("cannot find free interface range"); + ip_range = *maybe; } + const auto host_str = ip_range.BaseAddressString(); + // string, or just a plain char array? + if_addr = ip_range.addr; + next_addr = if_addr; + highest_addr = ip_range.HighestAddr(); + use_ipv6 = not ip_range.IsV4(); - void - ExitEndpoint::Configure(const NetworkConfig& networkConfig, const DnsConfig& dnsConfig) + if_name = networkConfig.m_ifname; + if (if_name.empty()) { - /* - * TODO: pre-config refactor, this was checking a couple things that were extremely vague - * these could have appeared on either [dns] or [network], but they weren't documented - * anywhere - * - if (k == "type" && v == "null") - { - m_ShouldInitTun = false; - return true; - } - if (k == "exit") - { - m_PermitExit = IsTrueValue(v.c_str()); - return true; - } - */ - - m_DNSConf = dnsConfig; - - if (networkConfig.m_endpointType == "null") - { - m_ShouldInitTun = false; - } - - m_OurRange = networkConfig.m_ifaddr; - if (!m_OurRange.addr.h) - { - const auto maybe = m_Router->Net().FindFreeRange(); - if (not maybe.has_value()) - throw std::runtime_error("cannot find free interface range"); - m_OurRange = *maybe; - } - const auto host_str = m_OurRange.BaseAddressString(); - // string, or just a plain char array? - m_IfAddr = m_OurRange.addr; - m_NextAddr = m_IfAddr; - m_HigestAddr = m_OurRange.HighestAddr(); - m_UseV6 = not m_OurRange.IsV4(); - - m_ifname = networkConfig.m_ifname; - if (m_ifname.empty()) - { - const auto maybe = m_Router->Net().FindFreeTun(); - if (not maybe.has_value()) - throw std::runtime_error("cannot find free interface name"); - m_ifname = *maybe; - } - LogInfo(Name(), " set ifname to ", m_ifname); - if (auto* quic = GetQUICTunnel()) - { - quic->listen([ifaddr = net::TruncateV6(m_IfAddr)](std::string_view, uint16_t port) { - return llarp::SockAddr{ifaddr, huint16_t{port}}; - }); - } + const auto maybe = router->net().FindFreeTun(); + if (not maybe.has_value()) + throw std::runtime_error("cannot find free interface name"); + if_name = *maybe; } - - huint128_t - ExitEndpoint::ObtainServiceNodeIP(const RouterID& other) + LogInfo(Name(), " set ifname to ", if_name); + if (auto* quic = GetQUICTunnel()) { - const PubKey pubKey{other}; - const PubKey us{m_Router->pubkey()}; - // just in case - if (pubKey == us) - return m_IfAddr; - - huint128_t ip = GetIPForIdent(pubKey); - if (m_SNodeKeys.emplace(pubKey).second) - { - auto session = std::make_shared( - other, - [this, ip](const auto& buf) { return QueueSNodePacket(buf, ip); }, - GetRouter(), - 2, - 1, - true, - this); - // this is a new service node make an outbound session to them - m_SNodeSessions[other] = session; - } - return ip; + quic->listen([ifaddr = net::TruncateV6(if_addr)](std::string_view, uint16_t port) { + return llarp::SockAddr{ifaddr, huint16_t{port}}; + }); } + } - quic::TunnelManager* - ExitEndpoint::GetQUICTunnel() + huint128_t + ExitEndpoint::ObtainServiceNodeIP(const RouterID& other) + { + const PubKey pubKey{other}; + const PubKey us{router->pubkey()}; + // just in case + if (pubKey == us) + return if_addr; + + huint128_t ip = GetIPForIdent(pubKey); + if (snode_keys.emplace(pubKey).second) + { + auto session = std::make_shared( + other, + [this, ip](const auto& buf) { return QueueSNodePacket(buf, ip); }, + GetRouter(), + 2, + 1, + true, + this); + // this is a new service node make an outbound session to them + snode_sessions[other] = session; + } + return ip; + } + + quic::TunnelManager* + ExitEndpoint::GetQUICTunnel() + { + return tunnel_manager.get(); + } + + bool + ExitEndpoint::AllocateNewExit(const PubKey pk, const PathID_t& path, bool wantInternet) + { + if (wantInternet && !permit_exit) + return false; + path::HopHandler_ptr handler = router->path_context().GetByUpstream(router->pubkey(), path); + if (handler == nullptr) + return false; + auto ip = GetIPForIdent(pk); + if (GetRouter()->path_context().TransitHopPreviousIsRouter(path, pk.as_array())) { - return m_QUIC.get(); + // we think this path belongs to a service node + // mark it as such so we don't make an outbound session to them + snode_keys.emplace(pk.as_array()); } + active_exits.emplace( + pk, std::make_unique(pk, handler, !wantInternet, ip, this)); - bool - ExitEndpoint::AllocateNewExit(const PubKey pk, const PathID_t& path, bool wantInternet) - { - if (wantInternet && !m_PermitExit) - return false; - path::HopHandler_ptr handler = - m_Router->pathContext().GetByUpstream(m_Router->pubkey(), path); - if (handler == nullptr) - return false; - auto ip = GetIPForIdent(pk); - if (GetRouter()->pathContext().TransitHopPreviousIsRouter(path, pk.as_array())) - { - // we think this path belongs to a service node - // mark it as such so we don't make an outbound session to them - m_SNodeKeys.emplace(pk.as_array()); - } - m_ActiveExits.emplace( - pk, std::make_unique(pk, handler, !wantInternet, ip, this)); + paths[path] = pk; - m_Paths[path] = pk; + return HasLocalMappedAddrFor(pk); + } - return HasLocalMappedAddrFor(pk); - } + std::string + ExitEndpoint::Name() const + { + return name; + } - std::string - ExitEndpoint::Name() const - { - return m_Name; - } + void + ExitEndpoint::DelEndpointInfo(const PathID_t& path) + { + paths.erase(path); + } - void - ExitEndpoint::DelEndpointInfo(const PathID_t& path) + void + ExitEndpoint::RemoveExit(const exit::Endpoint* ep) + { + for (auto [itr, end] = active_exits.equal_range(ep->PubKey()); itr != end; ++itr) { - m_Paths.erase(path); + if (itr->second->GetCurrentPath() == ep->GetCurrentPath()) + { + active_exits.erase(itr); + // now ep is gone af + return; + } } + } - void - ExitEndpoint::RemoveExit(const exit::Endpoint* ep) + void + ExitEndpoint::Tick(llarp_time_t now) + { { - for (auto [itr, end] = m_ActiveExits.equal_range(ep->PubKey()); itr != end; ++itr) + auto itr = snode_sessions.begin(); + while (itr != snode_sessions.end()) { - if (itr->second->GetCurrentPath() == ep->GetCurrentPath()) + if (itr->second->IsExpired(now)) + itr = snode_sessions.erase(itr); + else { - m_ActiveExits.erase(itr); - // now ep is gone af - return; + itr->second->Tick(now); + ++itr; } } } - - void - ExitEndpoint::Tick(llarp_time_t now) { + // expire + auto itr = active_exits.begin(); + while (itr != active_exits.end()) { - auto itr = m_SNodeSessions.begin(); - while (itr != m_SNodeSessions.end()) - { - if (itr->second->IsExpired(now)) - itr = m_SNodeSessions.erase(itr); - else - { - itr->second->Tick(now); - ++itr; - } - } + if (itr->second->IsExpired(now)) + itr = active_exits.erase(itr); + else + ++itr; } + // pick chosen exits and tick + chosen_exits.clear(); + itr = active_exits.begin(); + while (itr != active_exits.end()) { - // expire - auto itr = m_ActiveExits.begin(); - while (itr != m_ActiveExits.end()) - { - if (itr->second->IsExpired(now)) - itr = m_ActiveExits.erase(itr); - else - ++itr; - } - // pick chosen exits and tick - m_ChosenExits.clear(); - itr = m_ActiveExits.begin(); - while (itr != m_ActiveExits.end()) + // do we have an exit set for this key? + if (chosen_exits.find(itr->first) != chosen_exits.end()) { - // do we have an exit set for this key? - if (m_ChosenExits.find(itr->first) != m_ChosenExits.end()) + // yes + if (chosen_exits[itr->first]->createdAt < itr->second->createdAt) { - // yes - if (m_ChosenExits[itr->first]->createdAt < itr->second->createdAt) - { - // if the iterators's exit is newer use it for the chosen exit for - // key - if (!itr->second->LooksDead(now)) - m_ChosenExits[itr->first] = itr->second.get(); - } + // if the iterators's exit is newer use it for the chosen exit for + // key + if (!itr->second->LooksDead(now)) + chosen_exits[itr->first] = itr->second.get(); } - else if (!itr->second->LooksDead(now)) // set chosen exit if not dead for key that - // doesn't have one yet - m_ChosenExits[itr->first] = itr->second.get(); - // tick which clears the tx rx counters - itr->second->Tick(now); - ++itr; } + else if (!itr->second->LooksDead(now)) // set chosen exit if not dead for key that + // doesn't have one yet + chosen_exits[itr->first] = itr->second.get(); + // tick which clears the tx rx counters + itr->second->Tick(now); + ++itr; } } - } // namespace handlers -} // namespace llarp + } +} // namespace llarp::handlers diff --git a/llarp/handlers/exit.hpp b/llarp/handlers/exit.hpp index 79fc2be47f..7899141fa6 100644 --- a/llarp/handlers/exit.hpp +++ b/llarp/handlers/exit.hpp @@ -7,7 +7,7 @@ namespace llarp { - struct AbstractRouter; + struct Router; namespace handlers { struct ExitEndpoint : public dns::Resolver_Base, public EndpointBase @@ -31,7 +31,7 @@ namespace llarp const SockAddr& to, const SockAddr& from) override; - ExitEndpoint(std::string name, AbstractRouter* r); + ExitEndpoint(std::string name, Router* r); ~ExitEndpoint() override; std::optional @@ -112,7 +112,7 @@ namespace llarp void OnInetPacket(net::IPPacket buf); - AbstractRouter* + Router* GetRouter(); llarp_time_t @@ -122,7 +122,7 @@ namespace llarp void CalculateTrafficStats(Stats& stats) { - for (auto& [pubkey, endpoint] : m_ActiveExits) + for (auto& [pubkey, endpoint] : active_exits) { stats[pubkey].first += endpoint->TxRate(); stats[pubkey].second += endpoint->RxRate(); @@ -172,7 +172,7 @@ namespace llarp GetIPForIdent(const PubKey pk); /// async obtain snode session and call callback when it's ready to send void - ObtainSNodeSession(const RouterID& router, exit::SessionReadyFunc obtainCb); + ObtainSNodeSession(const RouterID& rid, exit::SessionReadyFunc obtain_cb); private: huint128_t @@ -192,54 +192,52 @@ namespace llarp void KickIdentOffExit(const PubKey& pk); - AbstractRouter* m_Router; - std::shared_ptr m_Resolver; - bool m_ShouldInitTun; - std::string m_Name; - bool m_PermitExit; - std::unordered_map m_Paths; + Router* router; + std::shared_ptr resolver; + bool should_init_tun; + std::string name; + bool permit_exit; + std::unordered_map paths; - std::unordered_map m_ChosenExits; + std::unordered_map chosen_exits; - std::unordered_multimap> m_ActiveExits; + std::unordered_multimap> active_exits; - using KeyMap_t = std::unordered_map; - - KeyMap_t m_KeyToIP; + std::unordered_map key_to_IP; using SNodes_t = std::set; /// set of pubkeys we treat as snodes - SNodes_t m_SNodeKeys; + SNodes_t snode_keys; using SNodeSessions_t = std::unordered_map>; /// snode sessions we are talking to directly - SNodeSessions_t m_SNodeSessions; + SNodeSessions_t snode_sessions; - std::unordered_map m_IPToKey; + std::unordered_map ip_to_key; - huint128_t m_IfAddr; - huint128_t m_HigestAddr; + huint128_t if_addr; + huint128_t highest_addr; - huint128_t m_NextAddr; - IPRange m_OurRange; - std::string m_ifname; + huint128_t next_addr; + IPRange ip_range; + std::string if_name; - std::unordered_map m_IPActivity; + std::unordered_map ip_activity; - std::shared_ptr m_NetIf; + std::shared_ptr if_net; - SockAddr m_LocalResolverAddr; - std::vector m_UpstreamResolvers; + SockAddr resolver_addr; + std::vector upstream_resolvers; - std::shared_ptr m_QUIC; + std::shared_ptr tunnel_manager; using PacketQueue_t = std:: priority_queue, net::IPPacket::CompareOrder>; /// internet to llarp packet queue - PacketQueue_t m_InetToNetwork; - bool m_UseV6; - DnsConfig m_DNSConf; + PacketQueue_t inet_to_network; + bool use_ipv6; + DnsConfig dns_conf; }; } // namespace handlers } // namespace llarp diff --git a/llarp/handlers/null.hpp b/llarp/handlers/null.hpp index bfa0525e86..4d5202fe02 100644 --- a/llarp/handlers/null.hpp +++ b/llarp/handlers/null.hpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include @@ -12,7 +12,7 @@ namespace llarp::handlers struct NullEndpoint final : public llarp::service::Endpoint, public std::enable_shared_from_this { - NullEndpoint(AbstractRouter* r, llarp::service::Context* parent) + NullEndpoint(Router* r, llarp::service::Context* parent) : llarp::service::Endpoint{r, parent} , m_PacketRouter{new vpn::EgresPacketRouter{[](auto from, auto pkt) { var::visit( diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index e04e44ea72..a9ea3010bf 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include @@ -49,7 +49,7 @@ namespace llarp auto job = std::make_shared(source, query, to, from); if (HandleHookedDNSMessage(query, [job](auto msg) { job->SendReply(msg.ToBuffer()); })) - Router()->TriggerPump(); + router()->TriggerPump(); else job->Cancel(); return true; @@ -125,7 +125,7 @@ namespace llarp virtual ~TunDNS() = default; explicit TunDNS(TunEndpoint* ep, const llarp::DnsConfig& conf) - : dns::Server{ep->Router()->loop(), conf, 0} + : dns::Server{ep->router()->loop(), conf, 0} , m_QueryBind{conf.m_QueryBind} , m_OurIP{ToNet(ep->GetIfAddr())} , m_Endpoint{ep} @@ -145,8 +145,7 @@ namespace llarp } }; - TunEndpoint::TunEndpoint(AbstractRouter* r, service::Context* parent) - : service::Endpoint{r, parent} + TunEndpoint::TunEndpoint(Router* r, service::Context* parent) : service::Endpoint{r, parent} { m_PacketRouter = std::make_shared( [this](net::IPPacket pkt) { HandleGotUserPacket(std::move(pkt)); }); @@ -180,7 +179,7 @@ namespace llarp if (m_DnsConfig.m_raw_dns) { - if (auto vpn = Router()->GetVPNPlatform()) + if (auto vpn = router()->vpn_platform()) { // get the first local address we know of std::optional localaddr; @@ -196,7 +195,7 @@ namespace llarp if (platform::is_windows) { auto dns_io = vpn->create_packet_io(0, localaddr); - Router()->loop()->add_ticker([r = Router(), dns_io, handler = m_PacketRouter]() { + router()->loop()->add_ticker([r = router(), dns_io, handler = m_PacketRouter]() { net::IPPacket pkt = dns_io->ReadNextPacket(); while (not pkt.empty()) { @@ -306,7 +305,7 @@ namespace llarp method, conf.m_AuthWhitelist, conf.m_AuthStaticTokens, - Router()->lmq(), + router()->lmq(), shared_from_this()); auth->Start(); m_AuthPolicy = std::move(auth); @@ -334,7 +333,7 @@ namespace llarp m_IfName = conf.m_ifname; if (m_IfName.empty()) { - const auto maybe = m_router->Net().FindFreeTun(); + const auto maybe = m_router->net().FindFreeTun(); if (not maybe.has_value()) throw std::runtime_error("cannot find free interface name"); m_IfName = *maybe; @@ -343,7 +342,7 @@ namespace llarp m_OurRange = conf.m_ifaddr; if (!m_OurRange.addr.h) { - const auto maybe = m_router->Net().FindFreeRange(); + const auto maybe = m_router->net().FindFreeRange(); if (not maybe.has_value()) { throw std::runtime_error("cannot find free address range"); @@ -716,7 +715,7 @@ namespace llarp if (is_random_snode(msg)) { RouterID random; - if (Router()->GetRandomGoodRouter(random)) + if (router()->GetRandomGoodRouter(random)) { msg.AddCNAMEReply(random.ToString(), 1); } @@ -766,7 +765,7 @@ namespace llarp else if (is_random_snode(msg)) { RouterID random; - if (Router()->GetRandomGoodRouter(random)) + if (router()->GetRandomGoodRouter(random)) { msg.AddCNAMEReply(random.ToString(), 1); return ReplyToSNodeDNSWhenReady(random, std::make_shared(msg), isV6); @@ -1024,7 +1023,7 @@ namespace llarp try { - m_NetIf = Router()->GetVPNPlatform()->CreateInterface(std::move(info), Router()); + m_NetIf = router()->vpn_platform()->CreateInterface(std::move(info), router()); } catch (std::exception& ex) { @@ -1040,7 +1039,7 @@ namespace llarp pkt_router->HandleIPPacket(std::move(pkt)); }; - if (not Router()->loop()->add_network_interface(m_NetIf, std::move(handle_packet))) + if (not router()->loop()->add_network_interface(m_NetIf, std::move(handle_packet))) { LogError(Name(), " failed to add network interface"); return false; @@ -1051,7 +1050,7 @@ namespace llarp if constexpr (not llarp::platform::is_apple) { - if (auto maybe = m_router->Net().GetInterfaceIPv6Address(m_IfName)) + if (auto maybe = m_router->net().GetInterfaceIPv6Address(m_IfName)) { m_OurIPv6 = *maybe; LogInfo(Name(), " has ipv6 address ", m_OurIPv6); @@ -1134,7 +1133,7 @@ namespace llarp if (auto itr = m_ExitIPToExitAddress.find(ip); itr != m_ExitIPToExitAddress.end()) return itr->second; - const auto& net = m_router->Net(); + const auto& net = m_router->net(); const bool is_bogon = net.IsBogonIP(ip); // build up our candidates to choose @@ -1209,7 +1208,7 @@ namespace llarp std::function extra_cb; if (not HasFlowToService(addr)) { - extra_cb = [poker = Router()->routePoker()]() { poker->Up(); }; + extra_cb = [poker = router()->routePoker()]() { poker->Up(); }; } pkt.ZeroSourceAddress(); MarkAddressOutbound(addr); @@ -1221,7 +1220,7 @@ namespace llarp if (extra_cb) extra_cb(); ctx->SendPacketToRemote(pkt.ConstBuffer(), service::ProtocolType::Exit); - Router()->TriggerPump(); + router()->TriggerPump(); return; } LogWarn("cannot ensure path to exit ", addr, " so we drop some packets"); @@ -1260,7 +1259,7 @@ namespace llarp if (SendToOrQueue(*maybe, pkt.ConstBuffer(), type)) { MarkIPActive(dst); - Router()->TriggerPump(); + router()->TriggerPump(); return; } } @@ -1280,7 +1279,7 @@ namespace llarp if (SendToOrQueue(*maybe, pkt.ConstBuffer(), type)) { MarkIPActive(dst); - Router()->TriggerPump(); + router()->TriggerPump(); } else { @@ -1436,7 +1435,7 @@ namespace llarp } m_NetworkToUserPktQueue.push(std::move(write)); // wake up so we ensure that all packets are written to user - Router()->TriggerPump(); + router()->TriggerPump(); return true; } diff --git a/llarp/handlers/tun.hpp b/llarp/handlers/tun.hpp index be7db46419..f9b41b74c1 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -24,7 +24,7 @@ namespace llarp public dns::Resolver_Base, public std::enable_shared_from_this { - TunEndpoint(AbstractRouter* r, llarp::service::Context* parent); + TunEndpoint(Router* r, llarp::service::Context* parent); ~TunEndpoint() override; vpn::NetworkInterface* diff --git a/llarp/iwp/iwp.cpp b/llarp/iwp/iwp.cpp deleted file mode 100644 index 2ed7e21103..0000000000 --- a/llarp/iwp/iwp.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "iwp.hpp" -#include "linklayer.hpp" -#include -#include - -namespace llarp -{ - namespace iwp - { - LinkLayer_ptr - NewInboundLink( - std::shared_ptr keyManager, - std::shared_ptr loop, - GetRCFunc getrc, - LinkMessageHandler h, - SignBufferFunc sign, - BeforeConnectFunc_t before, - SessionEstablishedHandler est, - SessionRenegotiateHandler reneg, - TimeoutHandler timeout, - SessionClosedHandler closed, - PumpDoneHandler pumpDone, - WorkerFunc_t work) - { - return std::make_shared( - keyManager, - loop, - getrc, - h, - sign, - before, - est, - reneg, - timeout, - closed, - pumpDone, - work, - true); - } - - LinkLayer_ptr - NewOutboundLink( - std::shared_ptr keyManager, - std::shared_ptr loop, - GetRCFunc getrc, - LinkMessageHandler h, - SignBufferFunc sign, - BeforeConnectFunc_t before, - SessionEstablishedHandler est, - SessionRenegotiateHandler reneg, - TimeoutHandler timeout, - SessionClosedHandler closed, - PumpDoneHandler pumpDone, - WorkerFunc_t work) - { - return std::make_shared( - keyManager, - loop, - getrc, - h, - sign, - before, - est, - reneg, - timeout, - closed, - pumpDone, - work, - false); - } - } // namespace iwp -} // namespace llarp diff --git a/llarp/iwp/iwp.hpp b/llarp/iwp/iwp.hpp deleted file mode 100644 index 54a353d371..0000000000 --- a/llarp/iwp/iwp.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include -#include "linklayer.hpp" -#include -#include - -namespace llarp::iwp -{ - LinkLayer_ptr - NewInboundLink( - std::shared_ptr keyManager, - std::shared_ptr loop, - GetRCFunc getrc, - LinkMessageHandler h, - SignBufferFunc sign, - BeforeConnectFunc_t before, - SessionEstablishedHandler est, - SessionRenegotiateHandler reneg, - TimeoutHandler timeout, - SessionClosedHandler closed, - PumpDoneHandler pumpDone, - WorkerFunc_t work); - - LinkLayer_ptr - NewOutboundLink( - std::shared_ptr keyManager, - std::shared_ptr loop, - GetRCFunc getrc, - LinkMessageHandler h, - SignBufferFunc sign, - BeforeConnectFunc_t before, - SessionEstablishedHandler est, - SessionRenegotiateHandler reneg, - TimeoutHandler timeout, - SessionClosedHandler closed, - PumpDoneHandler pumpDone, - WorkerFunc_t work); - -} // namespace llarp::iwp diff --git a/llarp/iwp/linklayer.cpp b/llarp/iwp/linklayer.cpp deleted file mode 100644 index a0637ccc04..0000000000 --- a/llarp/iwp/linklayer.cpp +++ /dev/null @@ -1,115 +0,0 @@ -#include "linklayer.hpp" -#include "session.hpp" -#include -#include -#include - -namespace llarp::iwp -{ - LinkLayer::LinkLayer( - std::shared_ptr keyManager, - std::shared_ptr ev, - GetRCFunc getrc, - LinkMessageHandler h, - SignBufferFunc sign, - BeforeConnectFunc_t before, - SessionEstablishedHandler est, - SessionRenegotiateHandler reneg, - TimeoutHandler timeout, - SessionClosedHandler closed, - PumpDoneHandler pumpDone, - WorkerFunc_t worker, - bool allowInbound) - : ILinkLayer( - keyManager, getrc, h, sign, before, est, reneg, timeout, closed, pumpDone, worker) - , m_Wakeup{ev->make_waker([this]() { HandleWakeupPlaintext(); })} - , m_Inbound{allowInbound} - {} - - std::string_view - LinkLayer::Name() const - { - return "iwp"; - } - - std::string - LinkLayer::PrintableName() const - { - if (m_Inbound) - return "inbound iwp link"; - else - return "outbound iwp link"; - } - - uint16_t - LinkLayer::Rank() const - { - return 2; - } - - void - LinkLayer::RecvFrom(const SockAddr& from, AbstractLinkSession::Packet_t pkt) - { - std::shared_ptr session; - auto itr = m_AuthedAddrs.find(from); - bool isNewSession = false; - if (itr == m_AuthedAddrs.end()) - { - Lock_t lock{m_PendingMutex}; - auto it = m_Pending.find(from); - if (it == m_Pending.end()) - { - if (not m_Inbound) - return; - isNewSession = true; - it = m_Pending.emplace(from, std::make_shared(this, from)).first; - } - session = it->second; - } - else - { - if (auto s_itr = m_AuthedLinks.find(itr->second); s_itr != m_AuthedLinks.end()) - session = s_itr->second; - } - if (session) - { - bool success = session->Recv_LL(std::move(pkt)); - if (not success and isNewSession) - { - LogDebug("Brand new session failed; removing from pending sessions list"); - m_Pending.erase(from); - } - WakeupPlaintext(); - } - } - - std::shared_ptr - LinkLayer::NewOutboundSession(const RouterContact& rc, const AddressInfo& ai) - { - if (m_Inbound) - throw std::logic_error{"inbound link cannot make outbound sessions"}; - return std::make_shared(this, rc, ai); - } - - void - LinkLayer::WakeupPlaintext() - { - m_Wakeup->Trigger(); - } - - void - LinkLayer::HandleWakeupPlaintext() - { - // Copy bare pointers out first because HandlePlaintext can end up removing themselves from the - // structures. - m_WakingUp.clear(); // Reused to minimize allocations. - for (const auto& [router_id, session] : m_AuthedLinks) - m_WakingUp.push_back(session.get()); - for (const auto& [addr, session] : m_Pending) - m_WakingUp.push_back(session.get()); - for (auto* session : m_WakingUp) - session->HandlePlaintext(); - PumpDone(); - } - -} // namespace llarp::iwp diff --git a/llarp/iwp/linklayer.hpp b/llarp/iwp/linklayer.hpp deleted file mode 100644 index 8399f26c2d..0000000000 --- a/llarp/iwp/linklayer.hpp +++ /dev/null @@ -1,63 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace llarp::iwp -{ - struct Session; - - struct LinkLayer final : public ILinkLayer - { - LinkLayer( - std::shared_ptr keyManager, - std::shared_ptr ev, - GetRCFunc getrc, - LinkMessageHandler h, - SignBufferFunc sign, - BeforeConnectFunc_t before, - SessionEstablishedHandler est, - SessionRenegotiateHandler reneg, - TimeoutHandler timeout, - SessionClosedHandler closed, - PumpDoneHandler pumpDone, - WorkerFunc_t dowork, - bool permitInbound); - - std::shared_ptr - NewOutboundSession(const RouterContact& rc, const AddressInfo& ai) override; - - std::string_view - Name() const override; - - uint16_t - Rank() const override; - - void - RecvFrom(const SockAddr& from, AbstractLinkSession::Packet_t pkt) override; - - void - WakeupPlaintext(); - - std::string - PrintableName() const; - - private: - void - HandleWakeupPlaintext(); - - const std::shared_ptr m_Wakeup; - std::vector m_WakingUp; - const bool m_Inbound; - }; - - using LinkLayer_ptr = std::shared_ptr; -} // namespace llarp::iwp diff --git a/llarp/iwp/message_buffer.cpp b/llarp/iwp/message_buffer.cpp deleted file mode 100644 index e384b2cf85..0000000000 --- a/llarp/iwp/message_buffer.cpp +++ /dev/null @@ -1,194 +0,0 @@ -#include "message_buffer.hpp" -#include "session.hpp" -#include - -namespace llarp -{ - namespace iwp - { - OutboundMessage::OutboundMessage( - uint64_t msgid, - AbstractLinkSession::Message_t msg, - llarp_time_t now, - AbstractLinkSession::CompletionHandler handler, - uint16_t priority) - : m_Data{std::move(msg)} - , m_MsgID{msgid} - , m_Completed{handler} - , m_LastFlush{now} - , m_StartedAt{now} - , m_ResendPriority{priority} - { - const llarp_buffer_t buf(m_Data); - CryptoManager::instance()->shorthash(m_Digest, buf); - m_Acks.set(0); - } - - AbstractLinkSession::Packet_t - OutboundMessage::XMIT() const - { - size_t extra = std::min(m_Data.size(), FragmentSize); - auto xmit = CreatePacket(Command::eXMIT, 10 + 32 + extra, 0, 0); - oxenc::write_host_as_big( - static_cast(m_Data.size()), xmit.data() + CommandOverhead + PacketOverhead); - oxenc::write_host_as_big(m_MsgID, xmit.data() + 2 + CommandOverhead + PacketOverhead); - std::copy_n( - m_Digest.begin(), m_Digest.size(), xmit.data() + 10 + CommandOverhead + PacketOverhead); - std::copy_n(m_Data.data(), extra, xmit.data() + 10 + CommandOverhead + PacketOverhead + 32); - return xmit; - } - - void - OutboundMessage::Completed() - { - if (m_Completed) - { - m_Completed(AbstractLinkSession::DeliveryStatus::eDeliverySuccess); - } - m_Completed = nullptr; - } - - bool - OutboundMessage::ShouldFlush(llarp_time_t now) const - { - return now - m_LastFlush >= TXFlushInterval; - } - - void - OutboundMessage::Ack(byte_t bitmask) - { - m_Acks = std::bitset<8>(bitmask); - } - - void - OutboundMessage::FlushUnAcked( - std::function sendpkt, llarp_time_t now) - { - /// overhead for a data packet in plaintext - static constexpr size_t Overhead = 10; - uint16_t idx = 0; - const auto datasz = m_Data.size(); - while (idx < datasz) - { - if (not m_Acks[idx / FragmentSize]) - { - const size_t fragsz = idx + FragmentSize < datasz ? FragmentSize : datasz - idx; - auto frag = CreatePacket(Command::eDATA, fragsz + Overhead, 0, 0); - oxenc::write_host_as_big(idx, frag.data() + 2 + PacketOverhead); - oxenc::write_host_as_big(m_MsgID, frag.data() + 4 + PacketOverhead); - std::copy( - m_Data.begin() + idx, - m_Data.begin() + idx + fragsz, - frag.data() + PacketOverhead + Overhead + 2); - sendpkt(std::move(frag)); - } - idx += FragmentSize; - } - m_LastFlush = now; - } - - bool - OutboundMessage::IsTransmitted() const - { - const auto sz = m_Data.size(); - for (uint16_t idx = 0; idx < sz; idx += FragmentSize) - { - if (not m_Acks.test(idx / FragmentSize)) - return false; - } - return true; - } - - bool - OutboundMessage::IsTimedOut(const llarp_time_t now) const - { - // TODO: make configurable by outbound message deliverer - return now > m_StartedAt && now - m_StartedAt > DeliveryTimeout; - } - - void - OutboundMessage::InformTimeout() - { - if (m_Completed) - { - m_Completed(AbstractLinkSession::DeliveryStatus::eDeliveryDropped); - } - m_Completed = nullptr; - } - - InboundMessage::InboundMessage(uint64_t msgid, uint16_t sz, ShortHash h, llarp_time_t now) - : m_Data(size_t{sz}), m_Digset{std::move(h)}, m_MsgID(msgid), m_LastActiveAt{now} - {} - - void - InboundMessage::HandleData(uint16_t idx, const llarp_buffer_t& buf, llarp_time_t now) - { - if (idx + buf.sz > m_Data.size()) - { - LogWarn("invalid fragment offset ", idx); - return; - } - byte_t* dst = m_Data.data() + idx; - std::copy_n(buf.base, buf.sz, dst); - m_Acks.set(idx / FragmentSize); - LogTrace("got fragment ", idx / FragmentSize); - m_LastActiveAt = now; - } - - AbstractLinkSession::Packet_t - InboundMessage::ACKS() const - { - auto acks = CreatePacket(Command::eACKS, 9); - oxenc::write_host_as_big(m_MsgID, acks.data() + CommandOverhead + PacketOverhead); - acks[PacketOverhead + 10] = AcksBitmask(); - return acks; - } - - byte_t - InboundMessage::AcksBitmask() const - { - return byte_t{(byte_t)m_Acks.to_ulong()}; - } - - bool - InboundMessage::IsCompleted() const - { - const auto sz = m_Data.size(); - for (size_t idx = 0; idx < sz; idx += FragmentSize) - { - if (not m_Acks.test(idx / FragmentSize)) - return false; - } - return true; - } - - bool - InboundMessage::ShouldSendACKS(llarp_time_t now) const - { - return now > m_LastACKSent + ACKResendInterval; - } - - bool - InboundMessage::IsTimedOut(const llarp_time_t now) const - { - return now > m_LastActiveAt && now - m_LastActiveAt > DeliveryTimeout; - } - - void - InboundMessage::SendACKS( - std::function sendpkt, llarp_time_t now) - { - sendpkt(ACKS()); - m_LastACKSent = now; - } - - bool - InboundMessage::Verify() const - { - ShortHash gotten; - const llarp_buffer_t buf(m_Data); - CryptoManager::instance()->shorthash(gotten, buf); - return gotten == m_Digset; - } - } // namespace iwp -} // namespace llarp diff --git a/llarp/iwp/message_buffer.hpp b/llarp/iwp/message_buffer.hpp deleted file mode 100644 index 207a3b2eef..0000000000 --- a/llarp/iwp/message_buffer.hpp +++ /dev/null @@ -1,127 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include - -namespace llarp -{ - namespace iwp - { - enum Command - { - /// keep alive message - ePING = 0, - /// begin transission - eXMIT = 1, - /// fragment data - eDATA = 2, - /// acknolege fragments - eACKS = 3, - /// negative ack - eNACK = 4, - /// multiack - eMACK = 5, - /// close session - eCLOS = 0xff, - }; - - /// max size of data fragments - static constexpr size_t FragmentSize = 1024; - /// plaintext header overhead size - static constexpr size_t CommandOverhead = 2; - - struct OutboundMessage - { - OutboundMessage() = default; - OutboundMessage( - uint64_t msgid, - AbstractLinkSession::Message_t data, - llarp_time_t now, - AbstractLinkSession::CompletionHandler handler, - uint16_t priority); - - AbstractLinkSession::Message_t m_Data; - uint64_t m_MsgID = 0; - std::bitset m_Acks; - AbstractLinkSession::CompletionHandler m_Completed; - llarp_time_t m_LastFlush = 0s; - ShortHash m_Digest; - llarp_time_t m_StartedAt = 0s; - uint16_t m_ResendPriority; - - bool - operator<(const OutboundMessage& other) const - { - // yes, the first order is reversed as higher means more important - // second part is for queue order - int prioA = -m_ResendPriority, prioB = -other.m_ResendPriority; - return std::tie(prioA, m_MsgID) < std::tie(prioB, other.m_MsgID); - } - - AbstractLinkSession::Packet_t - XMIT() const; - - void - Ack(byte_t bitmask); - - void - FlushUnAcked(std::function sendpkt, llarp_time_t now); - - bool - ShouldFlush(llarp_time_t now) const; - - void - Completed(); - - bool - IsTransmitted() const; - - bool - IsTimedOut(llarp_time_t now) const; - - void - InformTimeout(); - }; - - struct InboundMessage - { - InboundMessage() = default; - InboundMessage(uint64_t msgid, uint16_t sz, ShortHash h, llarp_time_t now); - - AbstractLinkSession::Message_t m_Data; - ShortHash m_Digset; - uint64_t m_MsgID = 0; - llarp_time_t m_LastACKSent = 0s; - llarp_time_t m_LastActiveAt = 0s; - std::bitset m_Acks; - - void - HandleData(uint16_t idx, const llarp_buffer_t& buf, llarp_time_t now); - - bool - IsCompleted() const; - - bool - IsTimedOut(llarp_time_t now) const; - - bool - Verify() const; - - byte_t - AcksBitmask() const; - - bool - ShouldSendACKS(llarp_time_t now) const; - - void - SendACKS(std::function sendpkt, llarp_time_t now); - - AbstractLinkSession::Packet_t - ACKS() const; - }; - - } // namespace iwp -} // namespace llarp diff --git a/llarp/iwp/session.cpp b/llarp/iwp/session.cpp deleted file mode 100644 index 93f4f1a45e..0000000000 --- a/llarp/iwp/session.cpp +++ /dev/null @@ -1,1031 +0,0 @@ -#include "session.hpp" - -#include -#include -#include -#include - -#include - -namespace llarp -{ - namespace iwp - { - AbstractLinkSession::Packet_t - CreatePacket(Command cmd, size_t plainsize, size_t minpad, size_t variance) - { - const size_t pad = minpad > 0 ? minpad + (variance > 0 ? randint() % variance : 0) : 0; - AbstractLinkSession::Packet_t pkt(PacketOverhead + plainsize + pad + CommandOverhead); - // randomize pad - if (pad) - { - CryptoManager::instance()->randbytes( - pkt.data() + PacketOverhead + CommandOverhead + plainsize, pad); - } - // randomize nounce - CryptoManager::instance()->randbytes(pkt.data() + HMACSIZE, TUNNONCESIZE); - pkt[PacketOverhead] = llarp::constants::proto_version; - pkt[PacketOverhead + 1] = cmd; - return pkt; - } - - constexpr size_t PlaintextQueueSize = 512; - - Session::Session(LinkLayer* p, const RouterContact& rc, const AddressInfo& ai) - : m_State{State::Initial} - , m_Inbound{false} - , m_Parent(p) - , m_CreatedAt{p->Now()} - , m_RemoteAddr{ai} - , m_ChosenAI(ai) - , m_RemoteRC(rc) - , m_PlaintextRecv{PlaintextQueueSize} - { - token.Zero(); - m_PlaintextEmpty.test_and_set(); - GotLIM = util::memFn(&Session::GotOutboundLIM, this); - CryptoManager::instance()->shorthash(m_SessionKey, llarp_buffer_t(rc.pubkey)); - } - - Session::Session(LinkLayer* p, const SockAddr& from) - : m_State{State::Initial} - , m_Inbound{true} - , m_Parent(p) - , m_CreatedAt{p->Now()} - , m_RemoteAddr{from} - , m_PlaintextRecv{PlaintextQueueSize} - { - token.Randomize(); - m_PlaintextEmpty.test_and_set(); - GotLIM = util::memFn(&Session::GotInboundLIM, this); - const PubKey pk = m_Parent->GetOurRC().pubkey; - CryptoManager::instance()->shorthash(m_SessionKey, llarp_buffer_t(pk)); - } - - void - Session::Send_LL(const byte_t* buf, size_t sz) - { - LogTrace("send ", sz, " to ", m_RemoteAddr); - const llarp_buffer_t pkt(buf, sz); - m_Parent->SendTo_LL(m_RemoteAddr, pkt); - m_LastTX = time_now_ms(); - m_TXRate += sz; - } - - bool - Session::GotInboundLIM(const LinkIntroMessage* msg) - { - if (msg->rc.pubkey != m_ExpectedIdent) - { - LogError( - "ident key mismatch from ", m_RemoteAddr, " ", msg->rc.pubkey, " != ", m_ExpectedIdent); - return false; - } - m_State = State::Ready; - GotLIM = util::memFn(&Session::GotRenegLIM, this); - m_RemoteRC = msg->rc; - m_Parent->MapAddr(m_RemoteRC.pubkey, this); - return m_Parent->SessionEstablished(this, true); - } - - bool - Session::GotOutboundLIM(const LinkIntroMessage* msg) - { - if (msg->rc.pubkey != m_RemoteRC.pubkey) - { - LogError("ident key mismatch"); - return false; - } - - m_RemoteRC = msg->rc; - GotLIM = util::memFn(&Session::GotRenegLIM, this); - assert(shared_from_this().use_count() > 1); - SendOurLIM([self = shared_from_this()](AbstractLinkSession::DeliveryStatus st) { - if (st == AbstractLinkSession::DeliveryStatus::eDeliverySuccess) - { - self->m_State = State::Ready; - self->m_Parent->MapAddr(self->m_RemoteRC.pubkey, self.get()); - self->m_Parent->SessionEstablished(self.get(), false); - } - }); - return true; - } - - void - Session::SendOurLIM(AbstractLinkSession::CompletionHandler h) - { - LinkIntroMessage msg; - msg.rc = m_Parent->GetOurRC(); - msg.nonce.Randomize(); - msg.session_period = 60000; - if (not msg.sign(m_Parent->Sign)) - { - LogError("failed to sign our RC for ", m_RemoteAddr); - return; - } - - AbstractLinkSession::Message_t data(LinkIntroMessage::MAX_MSG_SIZE + PacketOverhead); - llarp_buffer_t buf(data); - if (auto str = msg.bt_encode(); not str.empty()) - { - buf.write(str.begin(), str.end()); - } - else - { - log::critical(link_cat, "Error: Failed to encode LIM for {}", m_RemoteAddr); - return; - } - - if (not SendMessageBuffer(std::move(data), h)) - { - LogError("failed to send LIM to ", m_RemoteAddr); - return; - } - LogTrace("sent LIM to ", m_RemoteAddr); - } - - void - Session::EncryptAndSend(AbstractLinkSession::Packet_t data) - { - m_EncryptNext.emplace_back(std::move(data)); - TriggerPump(); - if (!IsEstablished()) - { - EncryptWorker(std::move(m_EncryptNext)); - m_EncryptNext = CryptoQueue_t{}; - } - } - - void - Session::EncryptWorker(CryptoQueue_t msgs) - { - LogTrace("encrypt worker ", msgs.size(), " messages"); - for (auto& pkt : msgs) - { - llarp_buffer_t pktbuf{pkt}; - const TunnelNonce nonce_ptr{pkt.data() + HMACSIZE}; - pktbuf.base += PacketOverhead; - pktbuf.cur = pktbuf.base; - pktbuf.sz -= PacketOverhead; - CryptoManager::instance()->xchacha20(pktbuf, m_SessionKey, nonce_ptr); - pktbuf.base = pkt.data() + HMACSIZE; - pktbuf.sz = pkt.size() - HMACSIZE; - CryptoManager::instance()->hmac(pkt.data(), pktbuf, m_SessionKey); - Send_LL(pkt.data(), pkt.size()); - } - } - - void - Session::Close() - { - if (m_State == State::Closed) - return; - auto close_msg = CreatePacket(Command::eCLOS, 0, 16, 16); - m_Parent->UnmapAddr(m_RemoteAddr); - m_State = State::Closed; - if (m_SentClosed.test_and_set()) - return; - EncryptAndSend(std::move(close_msg)); - - LogInfo(m_Parent->PrintableName(), " closing connection to ", m_RemoteAddr); - } - - bool - Session::SendMessageBuffer( - AbstractLinkSession::Message_t buf, - AbstractLinkSession::CompletionHandler completed, - uint16_t priority) - { - if (m_TXMsgs.size() >= MaxSendQueueSize) - { - if (completed) - completed(AbstractLinkSession::DeliveryStatus::eDeliveryDropped); - return false; - } - const auto now = m_Parent->Now(); - const auto msgid = m_TXID++; - const auto bufsz = buf.size(); - auto& msg = - m_TXMsgs.emplace(msgid, OutboundMessage{msgid, std::move(buf), now, completed, priority}) - .first->second; - TriggerPump(); - EncryptAndSend(msg.XMIT()); - if (bufsz > FragmentSize) - { - msg.FlushUnAcked(util::memFn(&Session::EncryptAndSend, this), now); - } - m_Stats.totalInFlightTX++; - LogDebug("send message ", msgid, " to ", m_RemoteAddr); - return true; - } - - void - Session::SendMACK() - { - // send multi acks - while (not m_SendMACKs.empty()) - { - const auto sz = m_SendMACKs.size(); - const auto max = Session::MaxACKSInMACK; - auto numAcks = std::min(sz, max); - auto mack = CreatePacket(Command::eMACK, 1 + (numAcks * sizeof(uint64_t))); - mack[PacketOverhead + CommandOverhead] = byte_t{static_cast(numAcks)}; - byte_t* ptr = mack.data() + 3 + PacketOverhead; - LogTrace("send ", numAcks, " macks to ", m_RemoteAddr); - const auto& itr = m_SendMACKs.top(); - while (numAcks > 0) - { - oxenc::write_host_as_big(itr, ptr); - m_SendMACKs.pop(); - numAcks--; - ptr += sizeof(uint64_t); - } - EncryptAndSend(std::move(mack)); - } - } - - void - Session::TriggerPump() - { - m_Parent->Router()->TriggerPump(); - } - - void - Session::Pump() - { - const auto now = m_Parent->Now(); - if (m_State == State::Ready || m_State == State::LinkIntro) - { - if (ShouldPing()) - SendKeepAlive(); - for (auto& [id, msg] : m_RXMsgs) - { - if (msg.ShouldSendACKS(now)) - { - msg.SendACKS(util::memFn(&Session::EncryptAndSend, this), now); - } - } - std::priority_queue< - OutboundMessage*, - std::vector, - ComparePtr> - to_resend; - for (auto& [id, msg] : m_TXMsgs) - { - if (msg.ShouldFlush(now)) - to_resend.push(&msg); - } - if (not to_resend.empty()) - { - for (auto& msg = to_resend.top(); not to_resend.empty(); to_resend.pop()) - msg->FlushUnAcked(util::memFn(&Session::EncryptAndSend, this), now); - } - } - if (not m_EncryptNext.empty()) - { - m_Parent->QueueWork( - [self = shared_from_this(), data = m_EncryptNext] { self->EncryptWorker(data); }); - m_EncryptNext.clear(); - } - - if (not m_DecryptNext.empty()) - { - m_Parent->QueueWork( - [self = shared_from_this(), data = m_DecryptNext] { self->DecryptWorker(data); }); - m_DecryptNext.clear(); - } - } - - bool - Session::GotRenegLIM(const LinkIntroMessage* lim) - { - LogDebug("renegotiate session on ", m_RemoteAddr); - return m_Parent->SessionRenegotiate(lim->rc, m_RemoteRC); - } - - bool - Session::RenegotiateSession() - { - SendOurLIM(); - return true; - } - - bool - Session::ShouldPing() const - { - if (m_State == State::Ready) - { - const auto now = m_Parent->Now(); - return now - m_LastTX > PingInterval; - } - return false; - } - - SessionStats - Session::GetSessionStats() const - { - // TODO: thread safety - return m_Stats; - } - - util::StatusObject - Session::ExtractStatus() const - { - const auto now = m_Parent->Now(); - - return { - {"txRateCurrent", m_Stats.currentRateTX}, - {"rxRateCurrent", m_Stats.currentRateRX}, - {"rxPktsRcvd", m_Stats.totalPacketsRX}, - - // leave 'tx' and 'rx' as duplicates of 'xRateCurrent' for compat - {"tx", m_Stats.currentRateTX}, - {"rx", m_Stats.currentRateRX}, - - {"txPktsAcked", m_Stats.totalAckedTX}, - {"txPktsDropped", m_Stats.totalDroppedTX}, - {"txPktsInFlight", m_Stats.totalInFlightTX}, - - {"state", StateToString(m_State)}, - {"inbound", m_Inbound}, - {"replayFilter", m_ReplayFilter.size()}, - {"txMsgQueueSize", m_TXMsgs.size()}, - {"rxMsgQueueSize", m_RXMsgs.size()}, - {"remoteAddr", m_RemoteAddr.ToString()}, - {"remoteRC", m_RemoteRC.ExtractStatus()}, - {"created", to_json(m_CreatedAt)}, - {"uptime", to_json(now - m_CreatedAt)}}; - } - - bool - Session::TimedOut(llarp_time_t now) const - { - if (m_State == State::Ready) - { - return now > m_LastRX - && now - m_LastRX - > (m_Inbound and not m_RemoteRC.IsPublicRouter() ? DefaultLinkSessionLifetime - : SessionAliveTimeout); - } - return now - m_CreatedAt >= LinkLayerConnectTimeout; - } - - bool - Session::ShouldResetRates(llarp_time_t now) const - { - return now >= m_ResetRatesAt; - } - - void - Session::ResetRates() - { - m_Stats.currentRateTX = m_TXRate; - m_Stats.currentRateRX = m_RXRate; - m_RXRate = 0; - m_TXRate = 0; - } - - void - Session::Tick(llarp_time_t now) - { - if (ShouldResetRates(now)) - { - ResetRates(); - m_ResetRatesAt = now + 1s; - } - // remove pending outbound messsages that timed out - // inform waiters - { - auto itr = m_TXMsgs.begin(); - while (itr != m_TXMsgs.end()) - { - if (itr->second.IsTimedOut(now)) - { - m_Stats.totalDroppedTX++; - m_Stats.totalInFlightTX--; - LogTrace("Dropped unacked packet to ", m_RemoteAddr); - itr->second.InformTimeout(); - itr = m_TXMsgs.erase(itr); - } - else - ++itr; - } - } - { - // remove pending inbound messages that timed out - auto itr = m_RXMsgs.begin(); - while (itr != m_RXMsgs.end()) - { - if (itr->second.IsTimedOut(now)) - { - m_ReplayFilter.emplace(itr->first, now); - itr = m_RXMsgs.erase(itr); - } - else - ++itr; - } - } - { - // decay replay window - auto itr = m_ReplayFilter.begin(); - while (itr != m_ReplayFilter.end()) - { - if (itr->second + ReplayWindow <= now) - { - itr = m_ReplayFilter.erase(itr); - } - else - ++itr; - } - } - } - - using Introduction = - AlignedBuffer; - - void - Session::GenerateAndSendIntro() - { - TunnelNonce N; - N.Randomize(); - { - AbstractLinkSession::Packet_t req(Introduction::SIZE + PacketOverhead); - const auto pk = m_Parent->GetOurRC().pubkey; - const auto e_pk = m_Parent->RouterEncryptionSecret().toPublic(); - auto itr = req.data() + PacketOverhead; - std::copy_n(pk.data(), pk.size(), itr); - itr += pk.size(); - std::copy_n(e_pk.data(), e_pk.size(), itr); - itr += e_pk.size(); - std::copy_n(N.data(), N.size(), itr); - Signature Z; - llarp_buffer_t signbuf(req.data() + PacketOverhead, Introduction::SIZE - Signature::SIZE); - m_Parent->Sign(Z, signbuf); - std::copy_n( - Z.data(), - Z.size(), - req.data() + PacketOverhead + (Introduction::SIZE - Signature::SIZE)); - CryptoManager::instance()->randbytes(req.data() + HMACSIZE, TUNNONCESIZE); - EncryptAndSend(std::move(req)); - } - m_State = State::Introduction; - if (not CryptoManager::instance()->transport_dh_client( - m_SessionKey, m_ChosenAI.pubkey, m_Parent->RouterEncryptionSecret(), N)) - { - LogError("failed to transport_dh_client on outbound session to ", m_RemoteAddr); - return; - } - LogTrace("sent intro to ", m_RemoteAddr); - } - - void - Session::HandleCreateSessionRequest(Packet_t pkt) - { - if (not DecryptMessageInPlace(pkt)) - { - LogError( - m_Parent->PrintableName(), " failed to decrypt session request from ", m_RemoteAddr); - return; - } - if (pkt.size() < token.size() + PacketOverhead) - { - LogError( - m_Parent->PrintableName(), - " bad session request size, ", - pkt.size(), - " < ", - token.size() + PacketOverhead, - " from ", - m_RemoteAddr); - return; - } - const auto begin = pkt.data() + PacketOverhead; - if (not std::equal(begin, begin + token.size(), token.data())) - { - LogError(m_Parent->PrintableName(), " token mismatch from ", m_RemoteAddr); - return; - } - m_LastRX = m_Parent->Now(); - m_State = State::LinkIntro; - SendOurLIM(); - } - - void - Session::HandleGotIntro(Packet_t pkt) - { - if (pkt.size() < (Introduction::SIZE + PacketOverhead)) - { - LogWarn(m_Parent->PrintableName(), " intro too small from ", m_RemoteAddr); - return; - } - byte_t* ptr = pkt.data() + PacketOverhead; - TunnelNonce N; - std::copy_n(ptr, PubKey::SIZE, m_ExpectedIdent.data()); - ptr += PubKey::SIZE; - std::copy_n(ptr, PubKey::SIZE, m_RemoteOnionKey.data()); - ptr += PubKey::SIZE; - std::copy_n(ptr, TunnelNonce::SIZE, N.data()); - ptr += TunnelNonce::SIZE; - Signature Z; - std::copy_n(ptr, Z.size(), Z.data()); - const llarp_buffer_t verifybuf( - pkt.data() + PacketOverhead, Introduction::SIZE - Signature::SIZE); - if (!CryptoManager::instance()->verify(m_ExpectedIdent, verifybuf, Z)) - { - LogError(m_Parent->PrintableName(), " intro verify failed from ", m_RemoteAddr); - return; - } - const PubKey pk = m_Parent->TransportSecretKey().toPublic(); - LogDebug( - "got intro: remote-pk=", - m_RemoteOnionKey.ToHex(), - " N=", - N.ToHex(), - " local-pk=", - pk.ToHex()); - if (not CryptoManager::instance()->transport_dh_server( - m_SessionKey, m_RemoteOnionKey, m_Parent->TransportSecretKey(), N)) - { - LogError("failed to transport_dh_server on inbound intro from ", m_RemoteAddr); - return; - } - Packet_t reply(token.size() + PacketOverhead); - // random nonce - CryptoManager::instance()->randbytes(reply.data() + HMACSIZE, TUNNONCESIZE); - // set token - std::copy_n(token.data(), token.size(), reply.data() + PacketOverhead); - m_LastRX = m_Parent->Now(); - EncryptAndSend(std::move(reply)); - LogDebug("sent intro ack to ", m_RemoteAddr); - m_State = State::Introduction; - } - - void - Session::HandleGotIntroAck(Packet_t pkt) - { - if (pkt.size() < (token.size() + PacketOverhead)) - { - LogError( - m_Parent->PrintableName(), - " bad intro ack size ", - pkt.size(), - " < ", - token.size() + PacketOverhead, - " from ", - m_RemoteAddr); - return; - } - Packet_t reply(token.size() + PacketOverhead); - if (not DecryptMessageInPlace(pkt)) - { - LogError(m_Parent->PrintableName(), " intro ack decrypt failed from ", m_RemoteAddr); - return; - } - m_LastRX = m_Parent->Now(); - std::copy_n(pkt.data() + PacketOverhead, token.size(), token.data()); - std::copy_n(token.data(), token.size(), reply.data() + PacketOverhead); - // random nounce - CryptoManager::instance()->randbytes(reply.data() + HMACSIZE, TUNNONCESIZE); - EncryptAndSend(std::move(reply)); - LogDebug("sent session request to ", m_RemoteAddr); - m_State = State::LinkIntro; - } - - bool - Session::DecryptMessageInPlace(Packet_t& pkt) - { - if (pkt.size() <= PacketOverhead) - { - LogError("packet too small from ", m_RemoteAddr); - return false; - } - const llarp_buffer_t buf(pkt); - ShortHash H; - llarp_buffer_t curbuf(buf.base, buf.sz); - curbuf.base += ShortHash::SIZE; - curbuf.sz -= ShortHash::SIZE; - if (not CryptoManager::instance()->hmac(H.data(), curbuf, m_SessionKey)) - { - LogError("failed to caclulate keyed hash for ", m_RemoteAddr); - return false; - } - const ShortHash expected{buf.base}; - if (H != expected) - { - LogDebug( - m_Parent->PrintableName(), - " keyed hash mismatch ", - H, - " != ", - expected, - " from ", - m_RemoteAddr, - " state=", - int(m_State), - " size=", - buf.sz); - return false; - } - const TunnelNonce N{curbuf.base}; - curbuf.base += 32; - curbuf.sz -= 32; - LogTrace("decrypt: ", curbuf.sz, " bytes from ", m_RemoteAddr); - return CryptoManager::instance()->xchacha20(curbuf, m_SessionKey, N); - } - - void - Session::Start() - { - if (m_Inbound) - return; - GenerateAndSendIntro(); - } - - void - Session::HandleSessionData(Packet_t pkt) - { - m_DecryptNext.emplace_back(std::move(pkt)); - TriggerPump(); - } - - void - Session::DecryptWorker(CryptoQueue_t msgs) - { - auto itr = msgs.begin(); - while (itr != msgs.end()) - { - auto& pkt = *itr; - if (not DecryptMessageInPlace(pkt)) - { - itr = msgs.erase(itr); - LogError("failed to decrypt session data from ", m_RemoteAddr); - continue; - } - if (pkt[PacketOverhead] != llarp::constants::proto_version) - { - LogError( - "protocol version mismatch ", - int(pkt[PacketOverhead]), - " != ", - llarp::constants::proto_version); - itr = msgs.erase(itr); - continue; - } - ++itr; - } - m_PlaintextRecv.tryPushBack(std::move(msgs)); - m_PlaintextEmpty.clear(); - m_Parent->WakeupPlaintext(); - } - - void - Session::HandlePlaintext() - { - if (m_PlaintextEmpty.test_and_set()) - return; - while (auto maybe_queue = m_PlaintextRecv.tryPopFront()) - { - for (auto& result : *maybe_queue) - { - LogTrace("Command ", int(result[PacketOverhead + 1]), " from ", m_RemoteAddr); - switch (result[PacketOverhead + 1]) - { - case Command::eXMIT: - HandleXMIT(std::move(result)); - break; - case Command::eDATA: - HandleDATA(std::move(result)); - break; - case Command::eACKS: - HandleACKS(std::move(result)); - break; - case Command::ePING: - HandlePING(std::move(result)); - break; - case Command::eNACK: - HandleNACK(std::move(result)); - break; - case Command::eCLOS: - HandleCLOS(std::move(result)); - break; - case Command::eMACK: - HandleMACK(std::move(result)); - break; - default: - LogError("invalid command ", int(result[PacketOverhead + 1]), " from ", m_RemoteAddr); - } - } - } - SendMACK(); - m_Parent->WakeupPlaintext(); - } - - void - Session::HandleMACK(Packet_t data) - { - if (data.size() < (3 + PacketOverhead)) - { - LogError("impossibly short mack from ", m_RemoteAddr); - return; - } - byte_t numAcks = data[CommandOverhead + PacketOverhead]; - if (data.size() < 1 + CommandOverhead + PacketOverhead + (numAcks * sizeof(uint64_t))) - { - LogError("short mack from ", m_RemoteAddr); - return; - } - LogTrace("got ", int(numAcks), " mack from ", m_RemoteAddr); - byte_t* ptr = data.data() + CommandOverhead + PacketOverhead + 1; - while (numAcks > 0) - { - auto acked = oxenc::load_big_to_host(ptr); - LogTrace("mack containing txid=", acked, " from ", m_RemoteAddr); - auto itr = m_TXMsgs.find(acked); - if (itr != m_TXMsgs.end()) - { - m_Stats.totalAckedTX++; - m_Stats.totalInFlightTX--; - itr->second.Completed(); - m_TXMsgs.erase(itr); - } - else - { - LogTrace("ignored mack for txid=", acked, " from ", m_RemoteAddr); - } - ptr += sizeof(uint64_t); - numAcks--; - } - } - - void - Session::HandleNACK(Packet_t data) - { - if (data.size() < (CommandOverhead + sizeof(uint64_t) + PacketOverhead)) - { - LogError("short nack from ", m_RemoteAddr); - return; - } - auto txid = oxenc::load_big_to_host(data.data() + CommandOverhead + PacketOverhead); - LogTrace("got nack on ", txid, " from ", m_RemoteAddr); - auto itr = m_TXMsgs.find(txid); - if (itr != m_TXMsgs.end()) - { - EncryptAndSend(itr->second.XMIT()); - } - m_LastRX = m_Parent->Now(); - } - - void - Session::HandleXMIT(Packet_t data) - { - static constexpr size_t XMITOverhead = - (CommandOverhead + PacketOverhead + sizeof(uint16_t) + sizeof(uint64_t) - + ShortHash::SIZE); - if (data.size() < XMITOverhead) - { - LogError("short XMIT from ", m_RemoteAddr); - return; - } - auto* pos = data.data() + CommandOverhead + PacketOverhead; - auto sz = oxenc::load_big_to_host(pos); - pos += sizeof(sz); - auto rxid = oxenc::load_big_to_host(pos); - pos += sizeof(rxid); - auto p2 = pos + ShortHash::SIZE; - assert(p2 == data.data() + XMITOverhead); - LogTrace("rxid=", rxid, " sz=", sz, " h=", oxenc::to_hex(pos, p2), " from ", m_RemoteAddr); - m_LastRX = m_Parent->Now(); - { - // check for replay - auto itr = m_ReplayFilter.find(rxid); - if (itr != m_ReplayFilter.end()) - { - m_SendMACKs.emplace(rxid); - LogTrace("duplicate rxid=", rxid, " from ", m_RemoteAddr); - return; - } - } - { - const auto now = m_Parent->Now(); - auto itr = m_RXMsgs.find(rxid); - if (itr == m_RXMsgs.end()) - { - itr = m_RXMsgs.emplace(rxid, InboundMessage{rxid, sz, ShortHash{pos}, m_Parent->Now()}) - .first; - TriggerPump(); - - sz = std::min(sz, uint16_t{FragmentSize}); - if ((data.size() - XMITOverhead) == sz) - { - { - const llarp_buffer_t buf(data.data() + (data.size() - sz), sz); - itr->second.HandleData(0, buf, now); - if (not itr->second.IsCompleted()) - { - return; - } - - if (not itr->second.Verify()) - { - LogError("bad short xmit hash from ", m_RemoteAddr); - return; - } - } - HandleRecvMsgCompleted(itr->second); - } - } - else - LogTrace("got duplicate xmit on ", rxid, " from ", m_RemoteAddr); - } - } - - void - Session::HandleDATA(Packet_t data) - { - if (data.size() < (CommandOverhead + sizeof(uint16_t) + sizeof(uint64_t) + PacketOverhead)) - { - LogError("short DATA from ", m_RemoteAddr, " ", data.size()); - return; - } - m_LastRX = m_Parent->Now(); - auto sz = oxenc::load_big_to_host(data.data() + CommandOverhead + PacketOverhead); - auto rxid = oxenc::load_big_to_host( - data.data() + CommandOverhead + sizeof(uint16_t) + PacketOverhead); - auto itr = m_RXMsgs.find(rxid); - if (itr == m_RXMsgs.end()) - { - if (m_ReplayFilter.find(rxid) == m_ReplayFilter.end()) - { - LogTrace("no rxid=", rxid, " for ", m_RemoteAddr); - auto nack = CreatePacket(Command::eNACK, 8); - oxenc::write_host_as_big(rxid, nack.data() + PacketOverhead + CommandOverhead); - EncryptAndSend(std::move(nack)); - } - else - { - LogTrace("replay hit for rxid=", rxid, " for ", m_RemoteAddr); - m_SendMACKs.emplace(rxid); - } - return; - } - - { - const llarp_buffer_t buf( - data.data() + PacketOverhead + 12, data.size() - (PacketOverhead + 12)); - itr->second.HandleData(sz, buf, m_Parent->Now()); - } - - if (itr->second.IsCompleted()) - { - if (itr->second.Verify()) - { - HandleRecvMsgCompleted(itr->second); - } - else - { - LogError("hash mismatch for message ", itr->first); - } - } - } - - void - Session::HandleRecvMsgCompleted(const InboundMessage& msg) - { - const auto rxid = msg.m_MsgID; - if (m_ReplayFilter.emplace(rxid, m_Parent->Now()).second) - { - m_Parent->HandleMessage(this, msg.m_Data); - EncryptAndSend(msg.ACKS()); - LogDebug("recv'd message ", rxid, " from ", m_RemoteAddr); - } - m_RXMsgs.erase(rxid); - } - - void - Session::HandleACKS(Packet_t data) - { - if (data.size() < (11 + PacketOverhead)) - { - LogError("short ACKS from ", m_RemoteAddr); - return; - } - const auto now = m_Parent->Now(); - m_LastRX = now; - auto txid = oxenc::load_big_to_host(data.data() + 2 + PacketOverhead); - auto itr = m_TXMsgs.find(txid); - if (itr == m_TXMsgs.end()) - { - LogTrace("no txid=", txid, " for ", m_RemoteAddr); - return; - } - itr->second.Ack(data[10 + PacketOverhead]); - - if (itr->second.IsTransmitted()) - { - LogDebug("sent message ", itr->first, " to ", m_RemoteAddr); - itr->second.Completed(); - itr = m_TXMsgs.erase(itr); - } - else - { - itr->second.FlushUnAcked(util::memFn(&Session::EncryptAndSend, this), now); - } - } - - void - Session::HandleCLOS(Packet_t) - { - LogInfo("remote closed by ", m_RemoteAddr); - Close(); - } - - void - Session::HandlePING(Packet_t) - { - m_LastRX = m_Parent->Now(); - } - - bool - Session::SendKeepAlive() - { - if (m_State == State::Ready) - { - EncryptAndSend(CreatePacket(Command::ePING, 0)); - return true; - } - return false; - } - - bool - Session::IsEstablished() const - { - return m_State == State::Ready; - } - - bool - Session::Recv_LL(AbstractLinkSession::Packet_t data) - { - m_RXRate += data.size(); - - // TODO: differentiate between good and bad RX packets here - m_Stats.totalPacketsRX++; - switch (m_State) - { - case State::Initial: - if (m_Inbound) - { - // initial data - // enter introduction phase - if (DecryptMessageInPlace(data)) - { - HandleGotIntro(std::move(data)); - } - else - { - LogDebug("bad intro from ", m_RemoteAddr); - return false; - } - } - break; - case State::Introduction: - if (m_Inbound) - { - // we are replying to an intro ack - HandleCreateSessionRequest(std::move(data)); - } - else - { - // we got an intro ack - // send a session request - HandleGotIntroAck(std::move(data)); - } - break; - case State::LinkIntro: - default: - HandleSessionData(std::move(data)); - break; - } - return true; - } - - std::string - Session::StateToString(State state) - { - switch (state) - { - case State::Initial: - return "Initial"; - case State::Introduction: - return "Introduction"; - case State::LinkIntro: - return "LinkIntro"; - case State::Ready: - return "Ready"; - case State::Closed: - return "Close"; - default: - return "Invalid"; - } - } - } // namespace iwp -} // namespace llarp diff --git a/llarp/iwp/session.hpp b/llarp/iwp/session.hpp deleted file mode 100644 index 6d6e8faa29..0000000000 --- a/llarp/iwp/session.hpp +++ /dev/null @@ -1,275 +0,0 @@ -#pragma once - -#include -#include "linklayer.hpp" -#include "message_buffer.hpp" -#include - -#include -#include -#include - -#include -#include - -namespace llarp::iwp -{ - /// packet crypto overhead size - static constexpr size_t PacketOverhead = HMACSIZE + TUNNONCESIZE; - /// creates a packet with plaintext size + wire overhead + random pad - AbstractLinkSession::Packet_t - CreatePacket(Command cmd, size_t plainsize, size_t min_pad = 16, size_t pad_variance = 16); - /// Time how long we try delivery for - static constexpr std::chrono::milliseconds DeliveryTimeout = 500ms; - /// Time how long we wait to recieve a message - static constexpr auto ReceivalTimeout = (DeliveryTimeout * 8) / 5; - /// How long to keep a replay window for - static constexpr auto ReplayWindow = (ReceivalTimeout * 3) / 2; - /// How often to acks RX messages - static constexpr auto ACKResendInterval = DeliveryTimeout / 2; - /// How often to retransmit TX fragments - static constexpr auto TXFlushInterval = (DeliveryTimeout / 5) * 4; - /// How often we send a keepalive - static constexpr std::chrono::milliseconds PingInterval = 5s; - /// How long we wait for a session to die with no tx from them - static constexpr auto SessionAliveTimeout = PingInterval * 5; - - struct Session : public AbstractLinkSession, public std::enable_shared_from_this - { - using Time_t = std::chrono::milliseconds; - - /// maximum number of messages we can ack in a multiack - static constexpr std::size_t MaxACKSInMACK = 1024 / sizeof(uint64_t); - - /// outbound session - Session(LinkLayer* parent, const RouterContact& rc, const AddressInfo& ai); - /// inbound session - Session(LinkLayer* parent, const SockAddr& from); - - // Signal the event loop that a pump is needed (idempotent) - void - TriggerPump(); - - // Does the actual pump - void - Pump() override; - - void - Tick(llarp_time_t now) override; - - bool - SendMessageBuffer( - AbstractLinkSession::Message_t msg, - CompletionHandler resultHandler, - uint16_t priority = 0) override; - - void - Send_LL(const byte_t* buf, size_t sz); - - void EncryptAndSend(AbstractLinkSession::Packet_t); - - void - Start() override; - - void - Close() override; - - bool Recv_LL(AbstractLinkSession::Packet_t) override; - - bool - SendKeepAlive() override; - - bool - IsEstablished() const override; - - bool - TimedOut(llarp_time_t now) const override; - - PubKey - GetPubKey() const override - { - return m_RemoteRC.pubkey; - } - - const SockAddr& - GetRemoteEndpoint() const override - { - return m_RemoteAddr; - } - - RouterContact - GetRemoteRC() const override - { - return m_RemoteRC; - } - - size_t - SendQueueBacklog() const override - { - return m_TXMsgs.size(); - } - - ILinkLayer* - GetLinkLayer() const override - { - return m_Parent; - } - - bool - RenegotiateSession() override; - - bool - ShouldPing() const override; - - SessionStats - GetSessionStats() const override; - - util::StatusObject - ExtractStatus() const override; - - bool - IsInbound() const override - { - return m_Inbound; - } - void - HandlePlaintext() override; - - private: - enum class State - { - /// we have no data recv'd - Initial, - /// we are in introduction phase - Introduction, - /// we sent our LIM - LinkIntro, - /// handshake done and LIM has been obtained - Ready, - /// we are closed now - Closed - }; - static std::string - StateToString(State state); - State m_State; - SessionStats m_Stats; - - /// are we inbound session ? - const bool m_Inbound; - /// parent link layer - LinkLayer* const m_Parent; - const llarp_time_t m_CreatedAt; - const SockAddr m_RemoteAddr; - - AddressInfo m_ChosenAI; - /// remote rc - RouterContact m_RemoteRC; - /// session key - SharedSecret m_SessionKey; - /// session token - AlignedBuffer<24> token; - - PubKey m_ExpectedIdent; - PubKey m_RemoteOnionKey; - - llarp_time_t m_LastTX = 0s; - llarp_time_t m_LastRX = 0s; - - // accumulate for periodic rate calculation - uint64_t m_TXRate = 0; - uint64_t m_RXRate = 0; - - llarp_time_t m_ResetRatesAt = 0s; - - uint64_t m_TXID = 0; - - bool - ShouldResetRates(llarp_time_t now) const; - - void - ResetRates(); - - std::map m_RXMsgs; - std::map m_TXMsgs; - - /// maps rxid to time recieved - std::unordered_map m_ReplayFilter; - /// rx messages to send in next round of multiacks - util::ascending_priority_queue m_SendMACKs; - - using CryptoQueue_t = std::vector; - - CryptoQueue_t m_EncryptNext; - CryptoQueue_t m_DecryptNext; - - std::atomic_flag m_PlaintextEmpty; - llarp::thread::Queue m_PlaintextRecv; - std::atomic_flag m_SentClosed; - - void - EncryptWorker(CryptoQueue_t msgs); - - void - DecryptWorker(CryptoQueue_t msgs); - - void - HandleGotIntro(Packet_t pkt); - - void - HandleGotIntroAck(Packet_t pkt); - - void - HandleCreateSessionRequest(Packet_t pkt); - - void - HandleAckSession(Packet_t pkt); - - void - HandleSessionData(Packet_t pkt); - - bool - DecryptMessageInPlace(Packet_t& pkt); - - void - SendMACK(); - - void - HandleRecvMsgCompleted(const InboundMessage& msg); - - void - GenerateAndSendIntro(); - - bool - GotInboundLIM(const LinkIntroMessage* msg); - - bool - GotOutboundLIM(const LinkIntroMessage* msg); - - bool - GotRenegLIM(const LinkIntroMessage* msg); - - void - SendOurLIM(AbstractLinkSession::CompletionHandler h = nullptr); - - void - HandleXMIT(Packet_t msg); - - void - HandleDATA(Packet_t msg); - - void - HandleACKS(Packet_t msg); - - void - HandleNACK(Packet_t msg); - - void - HandlePING(Packet_t msg); - - void - HandleCLOS(Packet_t msg); - - void - HandleMACK(Packet_t msg); - }; -} // namespace llarp::iwp diff --git a/llarp/link/connection.cpp b/llarp/link/connection.cpp index 025eae8e68..8fcb21cffa 100644 --- a/llarp/link/connection.cpp +++ b/llarp/link/connection.cpp @@ -3,8 +3,10 @@ namespace llarp::link { Connection::Connection( - std::shared_ptr& c, std::shared_ptr& s) - : conn{c}, control_stream{s} + std::shared_ptr& c, + std::shared_ptr& s, + RouterContact& rc) + : conn{c}, control_stream{s}, remote_rc{std::move(rc)} {} } // namespace llarp::link diff --git a/llarp/link/connection.hpp b/llarp/link/connection.hpp index b0c7e08154..9168036748 100644 --- a/llarp/link/connection.hpp +++ b/llarp/link/connection.hpp @@ -9,16 +9,17 @@ namespace llarp::link { struct Connection { - Connection( - std::shared_ptr& c, - std::shared_ptr& s); - std::shared_ptr conn; std::shared_ptr control_stream; - RouterContact remote_rc; - bool inbound; // one side of a connection will be responsible for some things, e.g. heartbeat - bool remote_is_relay; + // one side of a connection will be responsible for some things, e.g. heartbeat + bool inbound{false}; + bool remote_is_relay{true}; + + Connection( + std::shared_ptr& c, + std::shared_ptr& s, + RouterContact& rc); }; } // namespace llarp::link diff --git a/llarp/link/endpoint.cpp b/llarp/link/endpoint.cpp deleted file mode 100644 index 95376029cc..0000000000 --- a/llarp/link/endpoint.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "endpoint.hpp" -#include "link_manager.hpp" - -namespace llarp::link -{ - std::shared_ptr - Endpoint::get_conn(const RouterContact& rc) const - { - for (const auto& [rid, conn] : conns) - { - if (conn->remote_rc == rc) - return conn; - } - - return nullptr; - } - - bool - Endpoint::have_conn(const RouterID& remote, bool client_only) const - { - if (auto itr = conns.find(remote); itr != conns.end()) - { - if (not(itr->second->remote_is_relay and client_only)) - return true; - } - - return false; - } - - // TOFIX: use the new close methods after bumping libquic - bool - Endpoint::deregister_peer(RouterID remote) - { - if (auto itr = conns.find(remote); itr != conns.end()) - { - endpoint->close_connection(*dynamic_cast(itr->second->conn.get())); - conns.erase(itr); - return true; - } - - return false; - } - - bool - Endpoint::establish_connection(const oxen::quic::opt::local_addr& remote) - { - try - { - oxen::quic::dgram_data_callback dgram_cb = - [this](oxen::quic::dgram_interface& dgi, bstring dgram) { - link_manager.recv_data_message(dgi, dgram); - }; - - auto conn_interface = endpoint->connect(remote, link_manager.tls_creds, dgram_cb); - auto control_stream = conn_interface->get_new_stream(); - - // TOFIX: get a real RouterID after refactoring it - RouterID rid; - auto [itr, b] = conns.emplace(rid); - itr->second = std::make_shared(conn_interface, control_stream); - connid_map.emplace(conn_interface->scid(), rid); - - return true; - } - catch (...) - { - log::error(quic_cat, "Error: failed to establish connection to {}", remote); - return false; - } - } - -} // namespace llarp::link diff --git a/llarp/link/endpoint.hpp b/llarp/link/endpoint.hpp index e4fca1449f..b5090c56a8 100644 --- a/llarp/link/endpoint.hpp +++ b/llarp/link/endpoint.hpp @@ -1,44 +1,12 @@ #pragma once #include "connection.hpp" +#include "link_manager.hpp" -#include +#include #include #include namespace llarp::link -{ - struct Endpoint - { - Endpoint(std::shared_ptr ep, LinkManager& lm) - : endpoint{std::move(ep)}, link_manager{lm} - {} - - std::shared_ptr endpoint; - LinkManager& link_manager; - - // for outgoing packets, we route via RouterID; map RouterID->Connection - // for incoming packets, we get a ConnectionID; map ConnectionID->RouterID - std::unordered_map> conns; - std::unordered_map connid_map; - - std::shared_ptr - get_conn(const RouterContact&) const; - - bool - have_conn(const RouterID& remote, bool client_only) const; - - bool - deregister_peer(RouterID remote); - - bool - establish_connection(const oxen::quic::opt::local_addr& remote); - }; - -} // namespace llarp::link - -/* -- Refactor RouterID to use gnutls info and maybe ConnectionID - -*/ +{} // namespace llarp::link diff --git a/llarp/link/factory.cpp b/llarp/link/factory.cpp deleted file mode 100644 index f94e010538..0000000000 --- a/llarp/link/factory.cpp +++ /dev/null @@ -1,43 +0,0 @@ -#include "factory.hpp" -#include - -namespace llarp -{ - LinkFactory::LinkType - LinkFactory::TypeFromName(std::string_view str) - { - if (str == "iwp") - return LinkType::eLinkIWP; - if (str == "mempipe") - return LinkType::eLinkMempipe; - return LinkType::eLinkUnknown; - } - - std::string - LinkFactory::NameFromType(LinkFactory::LinkType tp) - { - switch (tp) - { - case LinkType::eLinkIWP: - return "iwp"; - case LinkType::eLinkMempipe: - return "mempipe"; - default: - return "unspec"; - } - } - - LinkFactory::Factory - LinkFactory::Obtain(LinkFactory::LinkType tp, bool permitInbound) - { - switch (tp) - { - case LinkType::eLinkIWP: - if (permitInbound) - return llarp::iwp::NewInboundLink; - return llarp::iwp::NewOutboundLink; - default: - return nullptr; - } - } -} // namespace llarp diff --git a/llarp/link/factory.hpp b/llarp/link/factory.hpp deleted file mode 100644 index e87f314647..0000000000 --- a/llarp/link/factory.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once -#include -#include -#include -#include - -#include "server.hpp" - -namespace llarp -{ - /// LinkFactory is responsible for returning std::functions that create the - /// link layer types - struct LinkFactory - { - enum class LinkType - { - eLinkUTP, - eLinkIWP, - eLinkMempipe, - eLinkUnknown - }; - - using Factory = std::function, - GetRCFunc, - LinkMessageHandler, - SignBufferFunc, - SessionEstablishedHandler, - SessionRenegotiateHandler, - TimeoutHandler, - SessionClosedHandler, - PumpDoneHandler)>; - - /// get link type by name string - /// if invalid returns eLinkUnspec - static LinkType - TypeFromName(std::string_view name); - - /// turns a link type into a string representation - static std::string - NameFromType(LinkType t); - - /// obtain a link factory of a certain type - static Factory - Obtain(LinkType t, bool permitInbound); - }; - -} // namespace llarp diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index e226b96ffd..3bff19ebcb 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1,54 +1,103 @@ #include "link_manager.hpp" +#include "connection.hpp" #include #include #include -#include #include #include namespace llarp { + namespace link + { + std::shared_ptr + Endpoint::get_conn(const RouterContact& rc) const + { + for (const auto& [rid, conn] : conns) + { + if (conn->remote_rc == rc) + return conn; + } + + return nullptr; + } + + bool + Endpoint::have_conn(const RouterID& remote, bool client_only) const + { + if (auto itr = conns.find(remote); itr != conns.end()) + { + if (not(itr->second->remote_is_relay and client_only)) + return true; + } + + return false; + } + + bool + Endpoint::deregister_peer(RouterID remote) + { + if (auto itr = conns.find(remote); itr != conns.end()) + { + itr->second->conn->close_connection(); + conns.erase(itr); + return true; + } + + return false; + } + + size_t + Endpoint::num_connected(bool clients_only) const + { + size_t count = 0; + + for (const auto& c : conns) + { + if (not(c.second->remote_is_relay and clients_only)) + count += 1; + } + + return count; + } + + bool + Endpoint::get_random_connection(RouterContact& router) const + { + if (const auto size = conns.size(); size) + { + auto itr = conns.begin(); + std::advance(itr, randint() % size); + router = itr->second->remote_rc; + return true; + } + + log::warning(quic_cat, "Error: failed to fetch random connection"); + return false; + } + } // namespace link LinkManager::LinkManager(Router& r) : router{r} , quic{std::make_unique()} , tls_creds{oxen::quic::GNUTLSCreds::make_from_ed_keys( - {reinterpret_cast(router.encryption().data()), router.encryption().size()}, - {reinterpret_cast(router.encryption().toPublic().data()), size_t{32}})} + {reinterpret_cast(router.identity().data()), size_t{32}}, + {reinterpret_cast(router.identity().toPublic().data()), size_t{32}})} , ep{quic->endpoint(router.local), *this} {} - std::shared_ptr - LinkManager::get_compatible_link(const RouterContact& rc) - { - if (stopping) - return nullptr; - - if (auto c = ep.get_conn(rc); c) - return c; - - return nullptr; - } - // TODO: replace with control/data message sending with libquic bool - LinkManager::send_to( - const RouterID& remote, - const llarp_buffer_t&, - AbstractLinkSession::CompletionHandler completed, - uint16_t) + LinkManager::send_to(const RouterID& remote, const llarp_buffer_t&, uint16_t) { if (stopping) return false; if (not have_connection_to(remote)) { - if (completed) - { - completed(AbstractLinkSession::DeliveryStatus::eDeliveryDropped); - } + // TODO: some error callback to report message send failure return false; } @@ -81,15 +130,6 @@ namespace llarp log::warning(logcat, "Peer {} not found for de-registeration!"); } - void - LinkManager::connect_to(const oxen::quic::opt::local_addr& remote) - { - if (auto rv = ep.establish_connection(remote); rv) - log::info(quic_cat, "Connection to {} successfully established!", remote); - else - log::info(quic_cat, "Connection to {} unsuccessfully established", remote); - } - void LinkManager::stop() { @@ -98,7 +138,7 @@ namespace llarp return; } - util::Lock l(_mutex); + util::Lock l(m); LogInfo("stopping links"); stopping = true; @@ -112,7 +152,7 @@ namespace llarp if (stopping) return; - util::Lock l(_mutex); + util::Lock l(m); persisting_conns[remote] = std::max(until, persisting_conns[remote]); if (have_client_connection_to(remote)) @@ -125,17 +165,7 @@ namespace llarp size_t LinkManager::get_num_connected(bool clients_only) const { - size_t count{0}; - for (const auto& ep : endpoints) - { - for (const auto& conn : ep.connections) - { - if (not(conn.second.remote_is_relay and clients_only)) - count++; - } - } - - return count; + return ep.num_connected(clients_only); } size_t @@ -147,31 +177,7 @@ namespace llarp bool LinkManager::get_random_connected(RouterContact& router) const { - std::unordered_map connectedRouters; - - for (const auto& ep : endpoints) - { - for (const auto& [router_id, conn] : ep.connections) - { - connectedRouters.emplace(router_id, conn.remote_rc); - } - } - - const auto sz = connectedRouters.size(); - if (sz) - { - auto itr = connectedRouters.begin(); - if (sz > 1) - { - std::advance(itr, randint() % sz); - } - - router = itr->second; - - return true; - } - - return false; + return ep.get_random_connection(router); } // TODO: this? perhaps no longer necessary in the same way? @@ -189,7 +195,7 @@ namespace llarp // TODO: this util::StatusObject - LinkManager::ExtractStatus() const + LinkManager::extract_status() const { return {}; } @@ -198,15 +204,17 @@ namespace llarp LinkManager::init(RCLookupHandler* rcLookup) { stopping = false; - _rcLookup = rcLookup; - _nodedb = router->nodedb(); + rc_lookup = rcLookup; + node_db = router.node_db(); } void LinkManager::connect_to(RouterID router) { auto fn = [this]( - const RouterID& rid, const RouterContact* const rc, const RCRequestResult res) { + [[maybe_unused]] const RouterID& rid, + const RouterContact* const rc, + const RCRequestResult res) { if (res == RCRequestResult::Success) connect_to(*rc); /* TODO: @@ -215,26 +223,18 @@ namespace llarp */ }; - _rcLookup->GetRC(router, fn); + rc_lookup->get_rc(router, fn); } // This function assumes the RC has already had its signature verified and connection is allowed. void LinkManager::connect_to(RouterContact rc) { - // TODO: connection failed callback if (have_connection_to(rc.pubkey)) + { + // TODO: connection failed callback return; - - // RC shouldn't be valid if this is the case, but may as well sanity check... - // TODO: connection failed callback - if (rc.addrs.empty()) - return; - - // TODO: connection failed callback - auto* ep = get_compatible_link(rc); - if (ep == nullptr) - return; + } // TODO: connection established/failed callbacks oxen::quic::stream_data_callback stream_cb = @@ -245,51 +245,41 @@ namespace llarp // TODO: once "compatible link" cares about address, actually choose addr to connect to // based on which one is compatible with the link we chose. For now, just use // the first one. - auto& selected = rc.addrs[0]; - oxen::quic::opt::remote_addr remote{selected.IPString(), selected.port}; + 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) // TODO: does connect() inherit the endpoint's datagram data callback, and do we want it to if // so? - auto conn_interface = ep->endpoint->connect(remote, stream_cb, tls_creds); - - std::shared_ptr stream = conn_interface->get_new_stream(); - - llarp::link::Connection conn; - conn.conn = conn_interface; - conn.control_stream = stream; - conn.remote_rc = rc; - conn.inbound = false; - conn.remote_is_relay = true; - - ep->connections[rc.pubkey] = std::move(conn); - ep->connid_map[conn_interface->scid()] = rc.pubkey; + if (auto rv = ep.establish_connection(remote_addr, rc, stream_cb, tls_creds); rv) + { + log::info(quic_cat, "Connection to {} successfully established!", remote_addr); + return; + } + log::warning(quic_cat, "Connection to {} successfully established!", remote_addr); } void - LinkManager::connect_to_random(int numDesired) + LinkManager::connect_to_random(int num_conns) { std::set exclude; - auto remainingDesired = numDesired; + auto remainder = num_conns; + do { auto filter = [exclude](const auto& rc) -> bool { return exclude.count(rc.pubkey) == 0; }; - RouterContact other; - if (const auto maybe = _nodedb->GetRandom(filter)) + if (auto maybe_other = node_db->GetRandom(filter)) { - other = *maybe; - } - else - break; + exclude.insert(maybe_other->pubkey); - exclude.insert(other.pubkey); - if (not _rcLookup->SessionIsAllowed(other.pubkey)) - continue; + if (not rc_lookup->is_session_allowed(maybe_other->pubkey)) + continue; - Connect(other); - --remainingDesired; - } while (remainingDesired > 0); + connect_to(*maybe_other); + --remainder; + } + } while (remainder > 0); } void diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 92fbbe1a5a..edad06f05f 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -1,10 +1,11 @@ #pragma once +#include +#include +#include +#include #include -#include "server.hpp" -#include "endpoint.hpp" - #include #include @@ -20,6 +21,52 @@ namespace namespace llarp { + struct LinkManager; + + namespace link + { + struct Connection; + + struct Endpoint + { + Endpoint(std::shared_ptr ep, LinkManager& lm) + : endpoint{std::move(ep)}, link_manager{lm} + {} + + std::shared_ptr endpoint; + LinkManager& link_manager; + + // for outgoing packets, we route via RouterID; map RouterID->Connection + // for incoming packets, we get a ConnectionID; map ConnectionID->RouterID + std::unordered_map> conns; + std::unordered_map connid_map; + + std::shared_ptr + get_conn(const RouterContact&) const; + + bool + have_conn(const RouterID& remote, bool client_only) const; + + bool + deregister_peer(RouterID remote); + + size_t + num_connected(bool clients_only) const; + + bool + get_random_connection(RouterContact& router) const; + // DISCUSS: added template to forward callbacks/etc to endpoint->connect(...). + // This would be useful after combining link_manager with the redundant classes + // listed below. As a result, link_manager would be holding all the relevant + // callbacks, tls_creds, and other context required for endpoint management + template + bool + establish_connection(const oxen::quic::Address& remote, RouterContact& rc, Opt&&... opts); + + private: + }; + } // namespace link + enum class SessionResult { Establish, @@ -52,11 +99,7 @@ namespace llarp explicit LinkManager(Router& r); bool - send_to( - const RouterID& remote, - const llarp_buffer_t& buf, - AbstractLinkSession::CompletionHandler completed, - uint16_t priority); + send_to(const RouterID& remote, const llarp_buffer_t& buf, uint16_t priority); bool have_connection_to(const RouterID& remote, bool client_only = false) const; @@ -67,9 +110,6 @@ namespace llarp void deregister_peer(RouterID remote); - void - connect_to(const oxen::quic::opt::local_addr& remote); - void connect_to(RouterID router); @@ -98,18 +138,18 @@ namespace llarp update_peer_db(std::shared_ptr peerDb); util::StatusObject - ExtractStatus() const; + extract_status() const; void init(RCLookupHandler* rcLookup); // Attempts to connect to a number of random routers. // - // This will try to connect to *up to* numDesired routers, but will not + // This will try to connect to *up to* num_conns routers, but will not // check if we already have a connection to any of the random set, as making // that thread safe would be slow...I think. void - connect_to_random(int numDesired); + 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 @@ -120,21 +160,19 @@ namespace llarp private: friend struct link::Endpoint; - std::shared_ptr - get_compatible_link(const RouterContact& rc); - std::atomic stopping; - mutable util::Mutex _mutex; // protects m_PersistingSessions + // DISCUSS: is this necessary? can we reduce the amount of locking and nuke this + mutable util::Mutex m; // protects persisting_conns // sessions to persist -> timestamp to end persist at std::unordered_map persisting_conns GUARDED_BY(_mutex); - std::unordered_map last_router_stats; - util::DecayingHashSet clients{path::default_lifetime}; - RCLookupHandler* _rcLookup; - std::shared_ptr _nodedb; + RCLookupHandler* rc_lookup; + std::shared_ptr node_db; + + oxen::quic::Address addr; Router& router; @@ -151,4 +189,57 @@ namespace llarp recv_control_message(oxen::quic::Stream& stream, bstring_view packet); }; + namespace link + { + template + bool + Endpoint::establish_connection( + const oxen::quic::Address& remote, RouterContact& rc, Opt&&... opts) + { + try + { + oxen::quic::dgram_data_callback dgram_cb = + [this](oxen::quic::dgram_interface& dgi, bstring dgram) { + link_manager.recv_data_message(dgi, dgram); + }; + + auto conn_interface = + endpoint->connect(remote, link_manager.tls_creds, dgram_cb, std::forward(opts)...); + auto control_stream = conn_interface->get_new_stream(); + + // TOFIX: get a real RouterID after refactoring RouterID + RouterID rid; + auto [itr, b] = conns.emplace(rid); + itr->second = std::make_shared(conn_interface, rc, control_stream); + connid_map.emplace(conn_interface->scid(), rid); + + return true; + } + catch (...) + { + log::error(quic_cat, "Error: failed to establish connection to {}", remote); + return false; + } + } + } // namespace link + } // namespace llarp + +/* +- Refactor RouterID to use gnutls info and maybe ConnectionID +- Combine routerID and connectionID to simplify mapping in llarp/link/endpoint.hpp +- Combine llarp/link/session.hpp into llarp/link/connection.hpp::Connection + +- Combine llarp/link/server.hpp::ILinkLayer into llarp/link/endpoint.hpp::Endpoint + - must maintain metadata storage, callbacks, etc +- If: one endpoint for ipv4 and ipv6 + - Then: can potentially combine: + - llarp/link/endpoint.hpp + - llarp/link/link_manager.hpp + - llarp/link/outbound_message_handler.hpp + - llarp/link/outbound_session_maker.hpp + + -> Yields mega-combo endpoint managing object? + - Can avoid "kitchen sink" by greatly reducing complexity of implementation + +*/ diff --git a/llarp/link/server.cpp b/llarp/link/server.cpp index 12d56155a0..5c9aef4140 100644 --- a/llarp/link/server.cpp +++ b/llarp/link/server.cpp @@ -1,4 +1,3 @@ -#include "server.hpp" #include #include #include @@ -7,7 +6,7 @@ #include #include #include -#include +#include #include static constexpr auto LINK_LAYER_TICK_INTERVAL = 100ms; @@ -132,7 +131,7 @@ namespace llarp } void - ILinkLayer::Bind(AbstractRouter* router, SockAddr bind_addr) + ILinkLayer::Bind(Router* router, SockAddr bind_addr) { if (router->Net().IsLoopbackAddress(bind_addr.getIP())) throw std::runtime_error{"cannot udp bind socket on loopback"}; @@ -248,21 +247,6 @@ namespace llarp return false; } - bool - ILinkLayer::PickAddress(const RouterContact& rc, llarp::AddressInfo& picked) const - { - auto OurDialect = Name(); - for (const auto& addr : rc.addrs) - { - if (addr.dialect == OurDialect) - { - picked = addr; - return true; - } - } - return false; - } - util::StatusObject ILinkLayer::ExtractStatus() const { diff --git a/llarp/link/server.hpp b/llarp/link/server.hpp deleted file mode 100644 index 1f2de21b7c..0000000000 --- a/llarp/link/server.hpp +++ /dev/null @@ -1,278 +0,0 @@ -#pragma once - -#include -#include -#include "session.hpp" -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace llarp -{ - /// handle a link layer message. this allows for the message to be handled by "upper layers" - /// - /// currently called from iwp::Session when messages are sent or received. - using LinkMessageHandler = std::function; - - /// sign a buffer with identity key. this function should take the given `llarp_buffer_t` and - /// sign it, prividing the signature in the out variable `Signature&`. - /// - /// currently called from iwp::Session for signing LIMs (link introduction messages) - using SignBufferFunc = std::function; - - /// handle connection timeout - /// - /// currently called from ILinkLayer::Pump() when an unestablished session times out - using TimeoutHandler = std::function; - - /// get our RC - /// - /// currently called by iwp::Session to include as part of a LIM (link introduction message) - using GetRCFunc = std::function; - - /// handler of session established - /// return false to reject - /// return true to accept - /// - /// currently called in iwp::Session when a valid LIM is received. - using SessionEstablishedHandler = std::function; - - /// f(new, old) - /// handler of session renegotiation - /// returns true if the new rc is valid - /// returns false otherwise and the session is terminated - /// - /// currently called from iwp::Session when we receive a renegotiation LIM - using SessionRenegotiateHandler = std::function; - - /// handles close of all sessions with pubkey - /// - /// Note that this handler is called while m_AuthedLinksMutex is held - /// - /// currently called from iwp::ILinkSession when a previously established session times out - using SessionClosedHandler = std::function; - - /// notifies router that a link session has ended its pump and we should flush - /// messages to upper layers - /// - /// currently called at the end of every iwp::Session::Pump() call - using PumpDoneHandler = std::function; - - using Work_t = std::function; - /// queue work to worker thread - using WorkerFunc_t = std::function; - - /// before connection hook, called before we try connecting via outbound link - using BeforeConnectFunc_t = std::function; - - struct ILinkLayer - { - ILinkLayer( - std::shared_ptr keyManager, - GetRCFunc getrc, - LinkMessageHandler handler, - SignBufferFunc signFunc, - BeforeConnectFunc_t before, - SessionEstablishedHandler sessionEstablish, - SessionRenegotiateHandler renegotiate, - TimeoutHandler timeout, - SessionClosedHandler closed, - PumpDoneHandler pumpDone, - WorkerFunc_t doWork); - virtual ~ILinkLayer() = default; - - /// get current time via event loop - llarp_time_t - Now() const; - - bool - HasSessionTo(const RouterID& pk); - - void - ForEachSession(std::function visit, bool randomize = false) - const EXCLUDES(m_AuthedLinksMutex); - - void - ForEachSession(std::function visit) EXCLUDES(m_AuthedLinksMutex); - - void - UnmapAddr(const SockAddr& addr); - - void - SendTo_LL(const SockAddr& to, const llarp_buffer_t& pkt); - - void - Bind(AbstractRouter* router, SockAddr addr); - - virtual std::shared_ptr - NewOutboundSession(const RouterContact& rc, const AddressInfo& ai) = 0; - - /// fetch a session by the identity pubkey it claims - std::shared_ptr - FindSessionByPubkey(RouterID pk); - - virtual void - Pump(); - - virtual void - RecvFrom(const SockAddr& from, AbstractLinkSession::Packet_t pkt) = 0; - - bool - PickAddress(const RouterContact& rc, AddressInfo& picked) const; - - bool - TryEstablishTo(RouterContact rc); - - bool - Start(); - - virtual void - Stop(); - - virtual std::string_view - Name() const = 0; - - util::StatusObject - ExtractStatus() const EXCLUDES(m_AuthedLinksMutex); - - void - CloseSessionTo(const RouterID& remote); - - void - KeepAliveSessionTo(const RouterID& remote); - - virtual bool - SendTo( - const RouterID& remote, - const llarp_buffer_t& buf, - AbstractLinkSession::CompletionHandler completed, - uint16_t priority); - - virtual bool - GetOurAddressInfo(AddressInfo& addr) const; - - bool - VisitSessionByPubkey(const RouterID& pk, std::function visit) - EXCLUDES(m_AuthedLinksMutex); - - virtual uint16_t - Rank() const = 0; - - const byte_t* - TransportPubKey() const; - - const SecretKey& - RouterEncryptionSecret() const - { - return m_RouterEncSecret; - } - - const SecretKey& - TransportSecretKey() const; - - bool - IsCompatable(const llarp::RouterContact& other) const - { - const auto us = Name(); - for (const auto& ai : other.addrs) - if (ai.dialect == us) - return true; - return false; - } - - bool - MapAddr(const RouterID& pk, AbstractLinkSession* s); - - void - Tick(llarp_time_t now); - - LinkMessageHandler HandleMessage; - TimeoutHandler HandleTimeout; - SignBufferFunc Sign; - GetRCFunc GetOurRC; - BeforeConnectFunc_t BeforeConnect; - SessionEstablishedHandler SessionEstablished; - SessionClosedHandler SessionClosed; - SessionRenegotiateHandler SessionRenegotiate; - PumpDoneHandler PumpDone; - std::shared_ptr keyManager; - WorkerFunc_t QueueWork; - - bool - operator<(const ILinkLayer& other) const - { - auto rankA = Rank(), rankB = other.Rank(); - auto nameA = Name(), nameB = other.Name(); - return std::tie(rankA, nameA, m_ourAddr) < std::tie(rankB, nameB, other.m_ourAddr); - } - - /// called by link session to remove a pending session who is timed out - // void - // RemovePending(ILinkSession* s) EXCLUDES(m_PendingMutex); - - /// count the number of sessions that are yet to be fully connected - size_t - NumberOfPendingSessions() const - { - Lock_t lock(m_PendingMutex); - return m_Pending.size(); - } - - // Returns the file description of the UDP server, if available. - std::optional - GetUDPFD() const; - - // Gets a pointer to the router owning us. - AbstractRouter* - Router() const - { - return m_Router; - } - - /// Get the local sock addr we are bound on - const SockAddr& - LocalSocketAddr() const - { - return m_ourAddr; - } - - private: - const SecretKey& m_RouterEncSecret; - - protected: -#ifdef TRACY_ENABLE - using Lock_t = std::lock_guard; - using Mutex_t = std::mutex; -#else - using Lock_t = util::NullLock; - using Mutex_t = util::NullMutex; -#endif - bool - PutSession(const std::shared_ptr& s); - - AbstractRouter* m_Router; - SockAddr m_ourAddr; - std::shared_ptr m_udp; - SecretKey m_SecretKey; - - using AuthedLinks = std::unordered_multimap>; - using Pending = std::unordered_map>; - mutable DECLARE_LOCK(Mutex_t, m_AuthedLinksMutex, ACQUIRED_BEFORE(m_PendingMutex)); - AuthedLinks m_AuthedLinks GUARDED_BY(m_AuthedLinksMutex); - mutable DECLARE_LOCK(Mutex_t, m_PendingMutex, ACQUIRED_AFTER(m_AuthedLinksMutex)); - Pending m_Pending GUARDED_BY(m_PendingMutex); - std::unordered_map m_AuthedAddrs; - std::unordered_map m_RecentlyClosed; - - private: - std::shared_ptr m_repeater_keepalive; - }; - - using LinkLayer_ptr = std::shared_ptr; -} // namespace llarp diff --git a/llarp/link/session.cpp b/llarp/link/session.cpp deleted file mode 100644 index a7894780c7..0000000000 --- a/llarp/link/session.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "session.hpp" - -namespace llarp -{ - bool - AbstractLinkSession::IsRelay() const - { - return GetRemoteRC().IsPublicRouter(); - } - -} // namespace llarp diff --git a/llarp/link/session.hpp b/llarp/link/session.hpp deleted file mode 100644 index 8c5b96d943..0000000000 --- a/llarp/link/session.hpp +++ /dev/null @@ -1,138 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include - -namespace llarp -{ - struct LinkIntroMessage; - struct AbstractLinkMessage; - struct ILinkLayer; - - struct SessionStats - { - // rate - uint64_t currentRateRX = 0; - uint64_t currentRateTX = 0; - - uint64_t totalPacketsRX = 0; - - uint64_t totalAckedTX = 0; - uint64_t totalDroppedTX = 0; - uint64_t totalInFlightTX = 0; - }; - - struct AbstractLinkSession - { - virtual ~AbstractLinkSession() = default; - - /// delivery status of a message - enum class DeliveryStatus - { - eDeliverySuccess = 0, - eDeliveryDropped = 1 - }; - - /// hook for utp for when we have established a connection - virtual void - OnLinkEstablished(ILinkLayer*){}; - - /// called during pumping - virtual void - Pump() = 0; - - /// called every timer tick - virtual void Tick(llarp_time_t) = 0; - - /// message delivery result hook function - using CompletionHandler = std::function; - - using Packet_t = std::vector; - using Message_t = std::vector; - - /// send a message buffer to the remote endpoint - virtual bool - SendMessageBuffer(Message_t, CompletionHandler handler, uint16_t priority) = 0; - - /// start the connection - virtual void - Start() = 0; - - virtual void - Close() = 0; - - /// recv packet on low layer - /// not used by utp - virtual bool - Recv_LL(Packet_t) - { - return true; - } - - /// send a keepalive to the remote endpoint - virtual bool - SendKeepAlive() = 0; - - /// return true if we are established - virtual bool - IsEstablished() const = 0; - - /// return true if this session has timed out - virtual bool - TimedOut(llarp_time_t now) const = 0; - - /// get remote public identity key - virtual PubKey - GetPubKey() const = 0; - - /// is an inbound session or not - virtual bool - IsInbound() const = 0; - - /// get remote address - virtual const SockAddr& - GetRemoteEndpoint() const = 0; - - // get remote rc - virtual RouterContact - GetRemoteRC() const = 0; - - /// is this session a session to a relay? - bool - IsRelay() const; - - /// handle a valid LIM - std::function GotLIM; - - /// send queue current blacklog - virtual size_t - SendQueueBacklog() const = 0; - - /// get parent link layer - virtual ILinkLayer* - GetLinkLayer() const = 0; - - /// renegotiate session when we have a new RC locally - virtual bool - RenegotiateSession() = 0; - - /// return true if we should send an explicit keepalive message - virtual bool - ShouldPing() const = 0; - - /// return the current stats for this session - virtual SessionStats - GetSessionStats() const = 0; - - virtual util::StatusObject - ExtractStatus() const = 0; - - virtual void - HandlePlaintext() = 0; - }; -} // namespace llarp diff --git a/llarp/lokinet_shared.cpp b/llarp/lokinet_shared.cpp index 7d4a0f085d..33488edb29 100644 --- a/llarp/lokinet_shared.cpp +++ b/llarp/lokinet_shared.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include #include diff --git a/llarp/messages/dht_immediate.cpp b/llarp/messages/dht_immediate.cpp index 86b8420db7..2b1585084b 100644 --- a/llarp/messages/dht_immediate.cpp +++ b/llarp/messages/dht_immediate.cpp @@ -1,6 +1,6 @@ #include "dht_immediate.hpp" -#include +#include #include namespace llarp @@ -62,7 +62,7 @@ namespace llarp } bool - DHTImmediateMessage::handle_message(AbstractRouter* router) const + DHTImmediateMessage::handle_message(Router* router) const { DHTImmediateMessage reply; reply.session = session; diff --git a/llarp/messages/dht_immediate.hpp b/llarp/messages/dht_immediate.hpp index 25c6f62883..905fed8c47 100644 --- a/llarp/messages/dht_immediate.hpp +++ b/llarp/messages/dht_immediate.hpp @@ -21,7 +21,7 @@ namespace llarp decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; bool - handle_message(AbstractRouter* router) const override; + handle_message(Router* router) const override; void clear() override; diff --git a/llarp/messages/discard.hpp b/llarp/messages/discard.hpp index cebc5782d3..44535e7344 100644 --- a/llarp/messages/discard.hpp +++ b/llarp/messages/discard.hpp @@ -57,7 +57,7 @@ namespace llarp } bool - handle_message(AbstractRouter* /*router*/) const override + handle_message(Router* /*router*/) const override { return true; } @@ -84,7 +84,7 @@ namespace llarp } bool - handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override + handle_message(AbstractRoutingMessageHandler* h, Router* r) const override { return h->HandleDataDiscardMessage(*this, r); } diff --git a/llarp/messages/link_intro.cpp b/llarp/messages/link_intro.cpp index 70b4b6df6c..05377caa06 100644 --- a/llarp/messages/link_intro.cpp +++ b/llarp/messages/link_intro.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include @@ -91,7 +91,7 @@ namespace llarp } bool - LinkIntroMessage::handle_message(AbstractRouter* /*router*/) const + LinkIntroMessage::handle_message(Router* /*router*/) const { if (!verify()) return false; diff --git a/llarp/messages/link_intro.hpp b/llarp/messages/link_intro.hpp index c76b4ac81d..51b5276e03 100644 --- a/llarp/messages/link_intro.hpp +++ b/llarp/messages/link_intro.hpp @@ -24,7 +24,7 @@ namespace llarp bt_encode() const override; bool - handle_message(AbstractRouter* router) const override; + handle_message(Router* router) const override; bool decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; diff --git a/llarp/messages/link_message.hpp b/llarp/messages/link_message.hpp index 91602a1746..237fda914b 100644 --- a/llarp/messages/link_message.hpp +++ b/llarp/messages/link_message.hpp @@ -2,7 +2,6 @@ #include "common.hpp" -#include #include #include #include @@ -12,7 +11,7 @@ namespace llarp { struct AbstractLinkSession; - struct AbstractRouter; + struct Router; /// parsed link layer message struct AbstractLinkMessage : private AbstractSerializable @@ -31,7 +30,7 @@ namespace llarp bt_encode() const override = 0; virtual bool - handle_message(AbstractRouter* router) const = 0; + handle_message(Router* router) const = 0; virtual bool decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) = 0; diff --git a/llarp/messages/link_message_parser.cpp b/llarp/messages/link_message_parser.cpp index ae4cf7e581..5651fc9dfe 100644 --- a/llarp/messages/link_message_parser.cpp +++ b/llarp/messages/link_message_parser.cpp @@ -28,7 +28,7 @@ namespace llarp msg_holder_t() = default; }; - LinkMessageParser::LinkMessageParser(AbstractRouter* _router) + LinkMessageParser::LinkMessageParser(Router* _router) : router(_router), from(nullptr), msg(nullptr), holder(std::make_unique()) {} diff --git a/llarp/messages/link_message_parser.hpp b/llarp/messages/link_message_parser.hpp index 584142418a..dffe4f75bb 100644 --- a/llarp/messages/link_message_parser.hpp +++ b/llarp/messages/link_message_parser.hpp @@ -7,13 +7,13 @@ namespace llarp { - struct AbstractRouter; + struct Router; struct AbstractLinkMessage; struct AbstractLinkSession; struct LinkMessageParser { - LinkMessageParser(AbstractRouter* router); + LinkMessageParser(Router* router); ~LinkMessageParser(); bool @@ -38,7 +38,7 @@ namespace llarp private: bool firstkey; - AbstractRouter* router; + Router* router; AbstractLinkSession* from; AbstractLinkMessage* msg; diff --git a/llarp/messages/relay.cpp b/llarp/messages/relay.cpp index 02a0e0b54d..5eeaf8b6cb 100644 --- a/llarp/messages/relay.cpp +++ b/llarp/messages/relay.cpp @@ -1,7 +1,7 @@ #include "relay.hpp" #include -#include +#include #include namespace llarp @@ -52,9 +52,9 @@ namespace llarp } bool - RelayUpstreamMessage::handle_message(AbstractRouter* r) const + RelayUpstreamMessage::handle_message(Router* r) const { - auto path = r->pathContext().GetByDownstream(session->GetPubKey(), pathid); + auto path = r->path_context().GetByDownstream(session->GetPubKey(), pathid); if (path) { return path->HandleUpstream(llarp_buffer_t(enc), nonce, r); @@ -108,9 +108,9 @@ namespace llarp } bool - RelayDownstreamMessage::handle_message(AbstractRouter* r) const + RelayDownstreamMessage::handle_message(Router* r) const { - auto path = r->pathContext().GetByUpstream(session->GetPubKey(), pathid); + auto path = r->path_context().GetByUpstream(session->GetPubKey(), pathid); if (path) { return path->HandleDownstream(llarp_buffer_t(enc), nonce, r); diff --git a/llarp/messages/relay.hpp b/llarp/messages/relay.hpp index d7b6c26ceb..266a01aef3 100644 --- a/llarp/messages/relay.hpp +++ b/llarp/messages/relay.hpp @@ -21,7 +21,7 @@ namespace llarp bt_encode() const override; bool - handle_message(AbstractRouter* router) const override; + handle_message(Router* router) const override; void clear() override; @@ -50,7 +50,7 @@ namespace llarp bt_encode() const override; bool - handle_message(AbstractRouter* router) const override; + handle_message(Router* router) const override; void clear() override; diff --git a/llarp/messages/relay_commit.cpp b/llarp/messages/relay_commit.cpp index e93475d205..c62cee90d0 100644 --- a/llarp/messages/relay_commit.cpp +++ b/llarp/messages/relay_commit.cpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include #include @@ -68,19 +68,19 @@ namespace llarp } bool - LR_CommitMessage::handle_message(AbstractRouter* router) const + LR_CommitMessage::handle_message(Router* router) const { if (frames.size() != path::max_len) { llarp::LogError("LRCM invalid number of records, ", frames.size(), "!=", path::max_len); return false; } - if (!router->pathContext().AllowingTransit()) + if (!router->path_context().AllowingTransit()) { llarp::LogError("got LRCM when not permitting transit"); return false; } - return AsyncDecrypt(&router->pathContext()); + return AsyncDecrypt(&router->path_context()); } bool @@ -212,7 +212,7 @@ namespace llarp static void OnForwardLRCMResult( - AbstractRouter* router, + Router* router, std::shared_ptr path, const PathID_t pathid, const RouterID nextHop, @@ -246,7 +246,7 @@ namespace llarp std::abort(); break; } - router->QueueWork([router, path, pathid, nextHop, pathKey, status] { + router->queue_work([router, path, pathid, nextHop, pathKey, status] { LR_StatusMessage::CreateAndSend(router, path, pathid, nextHop, pathKey, status); }); } @@ -259,7 +259,7 @@ namespace llarp { llarp::LogError("duplicate transit hop ", self->hop->info); LR_StatusMessage::CreateAndSend( - self->context->Router(), + self->context->router(), self->hop, self->hop->info.rxID, self->hop->info.downstream, @@ -278,7 +278,7 @@ namespace llarp // we hit a limit so tell it to slow tf down llarp::LogError("client path build hit limit ", *self->fromAddr); OnForwardLRCMResult( - self->context->Router(), + self->context->router(), self->hop, self->hop->info.rxID, self->hop->info.downstream, @@ -290,7 +290,7 @@ namespace llarp #endif } - if (not self->context->Router()->PathToRouterAllowed(self->hop->info.upstream)) + if (not self->context->router()->PathToRouterAllowed(self->hop->info.upstream)) { // we are not allowed to forward it ... now what? llarp::LogError( @@ -298,7 +298,7 @@ namespace llarp self->hop->info.upstream, "not allowed, dropping build request on the floor"); OnForwardLRCMResult( - self->context->Router(), + self->context->router(), self->hop, self->hop->info.rxID, self->hop->info.downstream, @@ -309,9 +309,9 @@ namespace llarp } // persist sessions to upstream and downstream routers until the commit // ends - self->context->Router()->PersistSessionUntil( + self->context->router()->PersistSessionUntil( self->hop->info.downstream, self->hop->ExpireTime() + 10s); - self->context->Router()->PersistSessionUntil( + self->context->router()->PersistSessionUntil( self->hop->info.upstream, self->hop->ExpireTime() + 10s); // put hop self->context->PutTransitHop(self->hop); @@ -319,7 +319,7 @@ namespace llarp using std::placeholders::_1; auto func = [self](auto status) { OnForwardLRCMResult( - self->context->Router(), + self->context->router(), self->hop, self->hop->info.rxID, self->hop->info.downstream, @@ -329,7 +329,7 @@ namespace llarp }; self->context->ForwardLRCM(self->hop->info.upstream, self->frames, func); // trigger idempotent pump to ensure that the build messages propagate - self->context->Router()->TriggerPump(); + self->context->router()->TriggerPump(); } // this is called from the logic thread @@ -346,14 +346,14 @@ namespace llarp else { // persist session to downstream until path expiration - self->context->Router()->PersistSessionUntil( + self->context->router()->PersistSessionUntil( self->hop->info.downstream, self->hop->ExpireTime() + 10s); // put hop self->context->PutTransitHop(self->hop); } if (!LR_StatusMessage::CreateAndSend( - self->context->Router(), + self->context->router(), self->hop, self->hop->info.rxID, self->hop->info.downstream, @@ -371,7 +371,7 @@ namespace llarp static void HandleDecrypted(llarp_buffer_t* buf, std::shared_ptr self) { - auto now = self->context->Router()->Now(); + auto now = self->context->router()->Now(); auto& info = self->hop->info; if (!buf) { @@ -434,8 +434,8 @@ namespace llarp // TODO: check if we really want to accept it self->hop->started = now; - self->context->Router()->NotifyRouterEvent( - self->context->Router()->pubkey(), self->hop); + self->context->router()->NotifyRouterEvent( + self->context->router()->pubkey(), self->hop); size_t sz = self->frames[0].size(); // shift @@ -472,7 +472,7 @@ namespace llarp }); } // trigger idempotent pump to ensure that the build messages propagate - self->context->Router()->TriggerPump(); + self->context->router()->TriggerPump(); } }; @@ -486,7 +486,7 @@ namespace llarp // decrypt frames async frameDecrypt->decrypter->AsyncDecrypt( - frameDecrypt->frames[0], frameDecrypt, [r = context->Router()](auto func) { + frameDecrypt->frames[0], frameDecrypt, [r = context->router()](auto func) { r->QueueWork(std::move(func)); }); return true; diff --git a/llarp/messages/relay_commit.hpp b/llarp/messages/relay_commit.hpp index f6c1c371fd..b7c27c5e6b 100644 --- a/llarp/messages/relay_commit.hpp +++ b/llarp/messages/relay_commit.hpp @@ -13,7 +13,7 @@ namespace llarp { // forward declare - struct AbstractRouter; + struct Router; namespace path { struct PathContext; @@ -67,7 +67,7 @@ namespace llarp bt_encode() const override; bool - handle_message(AbstractRouter* router) const override; + handle_message(Router* router) const override; bool AsyncDecrypt(llarp::path::PathContext* context) const; diff --git a/llarp/messages/relay_status.cpp b/llarp/messages/relay_status.cpp index 44a02f3dea..d831df8d2a 100644 --- a/llarp/messages/relay_status.cpp +++ b/llarp/messages/relay_status.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include #include @@ -23,14 +23,14 @@ namespace llarp std::array frames; uint64_t status = 0; HopHandler_ptr hop; - AbstractRouter* router; + Router* router; PathID_t pathid; LRSM_AsyncHandler( std::array _frames, uint64_t _status, HopHandler_ptr _hop, - AbstractRouter* _router, + Router* _router, PathID_t pathid) : frames{std::move(_frames)} , status{_status} @@ -44,7 +44,8 @@ namespace llarp void handle() { - router->NotifyRouterEvent(router->pubkey(), pathid, status); + router->notify_router_event( + router->pubkey(), pathid, status); hop->HandleLRSM(status, frames, router); } @@ -52,7 +53,7 @@ namespace llarp queue_handle() { auto func = [self = shared_from_this()] { self->handle(); }; - router->QueueWork(func); + router->queue_work(func); } }; @@ -126,7 +127,7 @@ namespace llarp } bool - LR_StatusMessage::handle_message(AbstractRouter* router) const + LR_StatusMessage::handle_message(Router* router) const { llarp::LogDebug("Received LR_Status message from (", session->GetPubKey(), ")"); if (frames.size() != path::max_len) @@ -135,7 +136,7 @@ namespace llarp return false; } - auto path = router->pathContext().GetByUpstream(session->GetPubKey(), pathid); + auto path = router->path_context().GetByUpstream(session->GetPubKey(), pathid); if (not path) { llarp::LogWarn("unhandled LR_Status message: no associated path found pathid=", pathid); @@ -156,7 +157,7 @@ namespace llarp // call this from a worker thread bool LR_StatusMessage::CreateAndSend( - AbstractRouter* router, + Router* router, std::shared_ptr hop, const PathID_t pathid, const RouterID nextHop, @@ -219,7 +220,7 @@ namespace llarp void LR_StatusMessage::QueueSendMessage( - AbstractRouter* router, + Router* router, const RouterID nextHop, std::shared_ptr msg, std::shared_ptr hop) @@ -231,7 +232,7 @@ namespace llarp void LR_StatusMessage::SendMessage( - AbstractRouter* router, + Router* router, const RouterID nextHop, std::shared_ptr msg, std::shared_ptr hop) diff --git a/llarp/messages/relay_status.hpp b/llarp/messages/relay_status.hpp index e30d6479fc..f0ce9bdd22 100644 --- a/llarp/messages/relay_status.hpp +++ b/llarp/messages/relay_status.hpp @@ -13,7 +13,7 @@ namespace llarp { // forward declare - struct AbstractRouter; + struct Router; namespace path { struct PathContext; @@ -79,14 +79,14 @@ namespace llarp bt_encode() const override; bool - handle_message(AbstractRouter* router) const override; + handle_message(Router* router) const override; void SetDummyFrames(); static bool CreateAndSend( - AbstractRouter* router, + Router* router, std::shared_ptr hop, const PathID_t pathid, const RouterID nextHop, @@ -98,14 +98,14 @@ namespace llarp static void QueueSendMessage( - AbstractRouter* router, + Router* router, const RouterID nextHop, std::shared_ptr msg, std::shared_ptr hop); static void SendMessage( - AbstractRouter* router, + Router* router, const RouterID nextHop, std::shared_ptr msg, std::shared_ptr hop); diff --git a/llarp/net/address_info.cpp b/llarp/net/address_info.cpp deleted file mode 100644 index a0f972570d..0000000000 --- a/llarp/net/address_info.cpp +++ /dev/null @@ -1,185 +0,0 @@ -#include "address_info.hpp" -#include - -#ifndef _WIN32 -#include -#endif -#include "net.hpp" -#include -#include - -#include - -namespace llarp -{ - bool - operator==(const AddressInfo& lhs, const AddressInfo& rhs) - { - // we don't care about rank - return lhs.pubkey == rhs.pubkey && lhs.port == rhs.port && lhs.dialect == rhs.dialect - && lhs.ip == rhs.ip; - } - - bool - operator<(const AddressInfo& lhs, const AddressInfo& rhs) - { - return std::tie(lhs.rank, lhs.ip, lhs.port) < std::tie(rhs.rank, rhs.ip, rhs.port); - } - - std::variant - AddressInfo::IP() const - { - return SockAddr{ip}.getIP(); - } - - bool - AddressInfo::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) - { - uint64_t i; - char tmp[128] = {0}; - - llarp_buffer_t strbuf; - - // rank - if (key.startswith("c")) - { - if (!bencode_read_integer(buf, &i)) - return false; - - if (i > 65536 || i <= 0) - return false; - - rank = i; - return true; - } - - // dialect - if (key.startswith("d")) - { - if (!bencode_read_string(buf, &strbuf)) - return false; - if (strbuf.sz > sizeof(tmp)) - return false; - memcpy(tmp, strbuf.base, strbuf.sz); - tmp[strbuf.sz] = 0; - dialect = std::string(tmp); - return true; - } - - // encryption public key - if (key.startswith("e")) - { - return pubkey.BDecode(buf); - } - - // ip address - if (key.startswith("i")) - { - if (!bencode_read_string(buf, &strbuf)) - return false; - - if (strbuf.sz >= sizeof(tmp)) - return false; - - memcpy(tmp, strbuf.base, strbuf.sz); - tmp[strbuf.sz] = 0; - return inet_pton(AF_INET6, tmp, &ip.s6_addr[0]) == 1; - } - - // port - if (key.startswith("p")) - { - if (!bencode_read_integer(buf, &i)) - return false; - - if (i > 65536 || i <= 0) - return false; - - port = i; - return true; - } - - // version - if (key.startswith("v")) - { - if (!bencode_read_integer(buf, &i)) - return false; - return i == llarp::constants::proto_version; - } - - // bad key - return false; - } - - std::string - AddressInfo::bt_encode() const - { - char ipbuff[128] = {0}; - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("c", rank); - btdp.append("d", dialect); - btdp.append("e", pubkey.ToView()); - - const char* ipstr = inet_ntop(AF_INET6, (void*)&ip, ipbuff, sizeof(ipbuff)); - - btdp.append("i", std::string_view{ipstr, strnlen(ipstr, sizeof(ipbuff))}); - btdp.append("p", port); - btdp.append("v", version); - } - catch (...) - { - log::critical(net_cat, "Error: AddressInfo failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - - IpAddress - AddressInfo::toIpAddress() const - { - SockAddr addr(ip); - addr.setPort(port); - return {addr}; - } - - void - AddressInfo::fromSockAddr(const SockAddr& addr) - { - const auto* addr6 = static_cast(addr); - memcpy(ip.s6_addr, addr6->sin6_addr.s6_addr, sizeof(ip.s6_addr)); - port = addr.getPort(); - } - - std::string - AddressInfo::ToString() const - { - char tmp[INET6_ADDRSTRLEN] = {0}; - inet_ntop(AF_INET6, (void*)&ip, tmp, sizeof(tmp)); - return fmt::format("[{}]:{}", tmp, port); - } - - std::string - AddressInfo::IPString() const - { - char tmp[INET6_ADDRSTRLEN] = {0}; - inet_ntop(AF_INET6, (void*)&ip, tmp, sizeof(tmp)); - return std::string{tmp}; - } - - void - to_json(nlohmann::json& j, const AddressInfo& a) - { - char tmp[128] = {0}; - inet_ntop(AF_INET6, (void*)&a.ip, tmp, sizeof(tmp)); - - j = nlohmann::json{ - {"rank", a.rank}, - {"dialect", a.dialect}, - {"pubkey", a.pubkey.ToString()}, - {"in6_addr", tmp}, - {"port", a.port}}; - } -} // namespace llarp diff --git a/llarp/net/address_info.hpp b/llarp/net/address_info.hpp deleted file mode 100644 index a1971cbca8..0000000000 --- a/llarp/net/address_info.hpp +++ /dev/null @@ -1,98 +0,0 @@ -#pragma once - -#include -#include "ip_address.hpp" -#include "net.h" -#include -#include - -#include -#include - -#include - -/** - * address_info.hpp - * - * utilities for handling addresses on the llarp network - */ - -/// address information model -namespace llarp -{ - struct AddressInfo - { - uint16_t rank; - std::string dialect; - llarp::PubKey pubkey; - in6_addr ip = {}; - uint16_t port; - uint64_t version = llarp::constants::proto_version; - - bool - BDecode(llarp_buffer_t* buf) - { - return bencode_decode_dict(*this, buf); - } - - std::string - bt_encode() const; - - bool - decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf); - - /// Return an IpAddress representing the address portion of this AddressInfo - IpAddress - toIpAddress() const; - - /// Updates our ip and port to reflect that of the given SockAddr - void - fromSockAddr(const SockAddr& address); - - /// get this as an explicit v4 or explicit v6 - net::ipaddr_t - IP() const; - - /// get this as an v4 or throw if it is not one - inline net::ipv4addr_t - IPv4() const - { - auto ip = IP(); - if (auto* ptr = std::get_if(&ip)) - return *ptr; - throw std::runtime_error{"no ipv4 address found in address info"}; - } - - std::string - ToString() const; - - std::string - IPString() const; - }; - - void - to_json(nlohmann::json& j, const AddressInfo& a); - - bool - operator==(const AddressInfo& lhs, const AddressInfo& rhs); - - bool - operator<(const AddressInfo& lhs, const AddressInfo& rhs); - - template <> - constexpr inline bool IsToStringFormattable = true; - -} // namespace llarp - -namespace std -{ - template <> - struct hash - { - size_t - operator()(const llarp::AddressInfo& addr) const - { - return std::hash{}(addr.pubkey); - } - }; -} // namespace std diff --git a/llarp/net/net.hpp b/llarp/net/net.hpp index b3a7af8e49..f215310296 100644 --- a/llarp/net/net.hpp +++ b/llarp/net/net.hpp @@ -1,7 +1,6 @@ #pragma once #include "uint128.hpp" -#include "address_info.hpp" #include "ip_address.hpp" #include "net_int.hpp" #include "net.h" diff --git a/llarp/path/ihophandler.cpp b/llarp/path/ihophandler.cpp index 3b7055cb92..9927765efd 100644 --- a/llarp/path/ihophandler.cpp +++ b/llarp/path/ihophandler.cpp @@ -1,5 +1,5 @@ #include "ihophandler.hpp" -#include +#include namespace llarp { @@ -7,7 +7,7 @@ namespace llarp { // handle data in upstream direction bool - IHopHandler::HandleUpstream(const llarp_buffer_t& X, const TunnelNonce& Y, AbstractRouter* r) + IHopHandler::HandleUpstream(const llarp_buffer_t& X, const TunnelNonce& Y, Router* r) { auto& pkt = m_UpstreamQueue.emplace_back(); pkt.first.resize(X.sz); @@ -19,7 +19,7 @@ namespace llarp // handle data in downstream direction bool - IHopHandler::HandleDownstream(const llarp_buffer_t& X, const TunnelNonce& Y, AbstractRouter* r) + IHopHandler::HandleDownstream(const llarp_buffer_t& X, const TunnelNonce& Y, Router* r) { auto& pkt = m_DownstreamQueue.emplace_back(); pkt.first.resize(X.sz); diff --git a/llarp/path/ihophandler.hpp b/llarp/path/ihophandler.hpp index e9bc981f35..68312a6272 100644 --- a/llarp/path/ihophandler.hpp +++ b/llarp/path/ihophandler.hpp @@ -13,7 +13,7 @@ struct llarp_buffer_t; namespace llarp { - struct AbstractRouter; + struct Router; namespace routing { @@ -43,21 +43,21 @@ namespace llarp /// send routing message and increment sequence number virtual bool - SendRoutingMessage(const routing::AbstractRoutingMessage& msg, AbstractRouter* r) = 0; + SendRoutingMessage(const routing::AbstractRoutingMessage& msg, Router* r) = 0; // handle data in upstream direction virtual bool - HandleUpstream(const llarp_buffer_t& X, const TunnelNonce& Y, AbstractRouter*); + HandleUpstream(const llarp_buffer_t& X, const TunnelNonce& Y, Router*); // handle data in downstream direction virtual bool - HandleDownstream(const llarp_buffer_t& X, const TunnelNonce& Y, AbstractRouter*); + HandleDownstream(const llarp_buffer_t& X, const TunnelNonce& Y, Router*); /// return timestamp last remote activity happened at virtual llarp_time_t LastRemoteActivityAt() const = 0; virtual bool - HandleLRSM(uint64_t status, std::array& frames, AbstractRouter* r) = 0; + HandleLRSM(uint64_t status, std::array& frames, Router* r) = 0; uint64_t NextSeqNo() @@ -66,10 +66,10 @@ namespace llarp } virtual void - FlushUpstream(AbstractRouter* r) = 0; + FlushUpstream(Router* r) = 0; virtual void - FlushDownstream(AbstractRouter* r) = 0; + FlushDownstream(Router* r) = 0; protected: uint64_t m_SequenceNum = 0; @@ -79,15 +79,15 @@ namespace llarp util::DecayingHashSet m_DownstreamReplayFilter; virtual void - UpstreamWork(TrafficQueue_t queue, AbstractRouter* r) = 0; + UpstreamWork(TrafficQueue_t queue, Router* r) = 0; virtual void - DownstreamWork(TrafficQueue_t queue, AbstractRouter* r) = 0; + DownstreamWork(TrafficQueue_t queue, Router* r) = 0; virtual void - HandleAllUpstream(std::vector msgs, AbstractRouter* r) = 0; + HandleAllUpstream(std::vector msgs, Router* r) = 0; virtual void - HandleAllDownstream(std::vector msgs, AbstractRouter* r) = 0; + HandleAllDownstream(std::vector msgs, Router* r) = 0; }; using HopHandler_ptr = std::shared_ptr; diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index c0d188ccb2..c8204a33b7 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -10,7 +10,7 @@ #include "transit_hop.hpp" #include #include -#include +#include #include #include #include @@ -66,7 +66,7 @@ namespace llarp::path } bool - Path::HandleUpstream(const llarp_buffer_t& X, const TunnelNonce& Y, AbstractRouter* r) + Path::HandleUpstream(const llarp_buffer_t& X, const TunnelNonce& Y, Router* r) { if (not m_UpstreamReplayFilter.Insert(Y)) return false; @@ -74,7 +74,7 @@ namespace llarp::path } bool - Path::HandleDownstream(const llarp_buffer_t& X, const TunnelNonce& Y, AbstractRouter* r) + Path::HandleDownstream(const llarp_buffer_t& X, const TunnelNonce& Y, Router* r) { if (not m_DownstreamReplayFilter.Insert(Y)) return false; @@ -146,7 +146,7 @@ namespace llarp::path } bool - Path::HandleLRSM(uint64_t status, std::array& frames, AbstractRouter* r) + Path::HandleLRSM(uint64_t status, std::array& frames, Router* r) { uint64_t currentStatus = status; @@ -204,7 +204,7 @@ namespace llarp::path { if (failedAt) { - r->NotifyRouterEvent(Endpoint(), RXID(), *failedAt); + r->notify_router_event(Endpoint(), RXID(), *failedAt); LogWarn( Name(), " build failed at ", @@ -213,10 +213,10 @@ namespace llarp::path LRStatusCodeToString(currentStatus), " hops=", HopsString()); - r->routerProfiling().MarkHopFail(*failedAt); + r->router_profiling().MarkHopFail(*failedAt); } else - r->routerProfiling().MarkPathFail(this); + r->router_profiling().MarkPathFail(this); llarp::LogDebug("LR_Status message processed, path build failed"); if (currentStatus & LR_StatusRecord::FAIL_TIMEOUT) @@ -240,7 +240,7 @@ namespace llarp::path "invalid destination"); if (failedAt) { - r->loop()->call([nodedb = r->nodedb(), router = *failedAt]() { + r->loop()->call([nodedb = r->node_db(), router = *failedAt]() { LogInfo("router ", router, " is deregistered so we remove it"); nodedb->Remove(router); }); @@ -411,7 +411,7 @@ namespace llarp::path } bool - Path::SendLatencyMessage(AbstractRouter* r) + Path::SendLatencyMessage(Router* r) { const auto now = r->Now(); // send path latency test @@ -428,7 +428,7 @@ namespace llarp::path } void - Path::Tick(llarp_time_t now, AbstractRouter* r) + Path::Tick(llarp_time_t now, Router* r) { if (Expired(now)) return; @@ -449,7 +449,7 @@ namespace llarp::path if (dlt >= path::build_timeout) { LogWarn(Name(), " waited for ", ToString(dlt), " and no path was built"); - r->routerProfiling().MarkPathFail(this); + r->router_profiling().MarkPathFail(this); EnterState(ePathExpired, now); return; } @@ -473,7 +473,7 @@ namespace llarp::path if (dlt >= path::alive_timeout) { LogWarn(Name(), " waited for ", ToString(dlt), " and path looks dead"); - r->routerProfiling().MarkPathFail(this); + r->router_profiling().MarkPathFail(this); EnterState(ePathTimeout, now); } } @@ -485,7 +485,7 @@ namespace llarp::path } void - Path::HandleAllUpstream(std::vector msgs, AbstractRouter* r) + Path::HandleAllUpstream(std::vector msgs, Router* r) { for (const auto& msg : msgs) { @@ -502,7 +502,7 @@ namespace llarp::path } void - Path::UpstreamWork(TrafficQueue_t msgs, AbstractRouter* r) + Path::UpstreamWork(TrafficQueue_t msgs, Router* r) { std::vector sendmsgs(msgs.size()); size_t idx = 0; @@ -527,24 +527,24 @@ namespace llarp::path } void - Path::FlushUpstream(AbstractRouter* r) + Path::FlushUpstream(Router* r) { if (not m_UpstreamQueue.empty()) { - r->QueueWork([self = shared_from_this(), - data = std::exchange(m_UpstreamQueue, {}), - r]() mutable { self->UpstreamWork(std::move(data), r); }); + r->queue_work([self = shared_from_this(), + data = std::exchange(m_UpstreamQueue, {}), + r]() mutable { self->UpstreamWork(std::move(data), r); }); } } void - Path::FlushDownstream(AbstractRouter* r) + Path::FlushDownstream(Router* r) { if (not m_DownstreamQueue.empty()) { - r->QueueWork([self = shared_from_this(), - data = std::exchange(m_DownstreamQueue, {}), - r]() mutable { self->DownstreamWork(std::move(data), r); }); + r->queue_work([self = shared_from_this(), + data = std::exchange(m_DownstreamQueue, {}), + r]() mutable { self->DownstreamWork(std::move(data), r); }); } } @@ -576,7 +576,7 @@ namespace llarp::path } void - Path::DownstreamWork(TrafficQueue_t msgs, AbstractRouter* r) + Path::DownstreamWork(TrafficQueue_t msgs, Router* r) { std::vector sendMsgs(msgs.size()); size_t idx = 0; @@ -598,7 +598,7 @@ namespace llarp::path } void - Path::HandleAllDownstream(std::vector msgs, AbstractRouter* r) + Path::HandleAllDownstream(std::vector msgs, Router* r) { for (const auto& msg : msgs) { @@ -613,7 +613,7 @@ namespace llarp::path } bool - Path::HandleRoutingMessage(const llarp_buffer_t& buf, AbstractRouter* r) + Path::HandleRoutingMessage(const llarp_buffer_t& buf, Router* r) { if (!r->ParseRoutingMessageBuffer(buf, this, RXID())) { @@ -624,8 +624,7 @@ namespace llarp::path } bool - Path::HandleUpdateExitVerifyMessage( - const routing::UpdateExitVerifyMessage& msg, AbstractRouter* r) + Path::HandleUpdateExitVerifyMessage(const routing::UpdateExitVerifyMessage& msg, Router* r) { (void)r; if (m_UpdateExitTX && msg.tx_id == m_UpdateExitTX) @@ -657,7 +656,7 @@ namespace llarp::path std::move around. */ bool - Path::SendRoutingMessage(const routing::AbstractRoutingMessage& msg, AbstractRouter* r) + Path::SendRoutingMessage(const routing::AbstractRoutingMessage& msg, Router* r) { std::array tmp; llarp_buffer_t buf(tmp); @@ -692,15 +691,14 @@ namespace llarp::path } bool - Path::HandlePathTransferMessage( - const routing::PathTransferMessage& /*msg*/, AbstractRouter* /*r*/) + Path::HandlePathTransferMessage(const routing::PathTransferMessage& /*msg*/, Router* /*r*/) { LogWarn("unwarranted path transfer message on tx=", TXID(), " rx=", RXID()); return false; } bool - Path::HandleDataDiscardMessage(const routing::DataDiscardMessage& msg, AbstractRouter* r) + Path::HandleDataDiscardMessage(const routing::DataDiscardMessage& msg, Router* r) { MarkActive(r->Now()); if (m_DropHandler) @@ -709,7 +707,7 @@ namespace llarp::path } bool - Path::HandlePathConfirmMessage(AbstractRouter* r) + Path::HandlePathConfirmMessage(Router* r) { LogDebug("Path Build Confirm, path: ", ShortName()); const auto now = llarp::time_now_ms(); @@ -718,7 +716,7 @@ namespace llarp::path // finish initializing introduction intro.expiry = buildStarted + hops[0].lifetime; - r->routerProfiling().MarkPathSuccess(this); + r->router_profiling().MarkPathSuccess(this); // persist session with upstream router until the path is done r->PersistSessionUntil(Upstream(), intro.expiry); @@ -730,7 +728,7 @@ namespace llarp::path } bool - Path::HandlePathConfirmMessage(const routing::PathConfirmMessage& /*msg*/, AbstractRouter* r) + Path::HandlePathConfirmMessage(const routing::PathConfirmMessage& /*msg*/, Router* r) { return HandlePathConfirmMessage(r); } @@ -761,7 +759,7 @@ namespace llarp::path constexpr auto MaxLatencySamples = 8; bool - Path::HandlePathLatencyMessage(const routing::PathLatencyMessage&, AbstractRouter* r) + Path::HandlePathLatencyMessage(const routing::PathLatencyMessage&, Router* r) { const auto now = r->Now(); MarkActive(now); @@ -785,7 +783,7 @@ namespace llarp::path /// this is the Client's side of handling a DHT message. it's handled /// in-place. bool - Path::HandleDHTMessage(const dht::AbstractDHTMessage& msg, AbstractRouter* r) + Path::HandleDHTMessage(const dht::AbstractDHTMessage& msg, Router* r) { MarkActive(r->Now()); routing::PathDHTMessage reply; @@ -797,7 +795,7 @@ namespace llarp::path } bool - Path::HandleCloseExitMessage(const routing::CloseExitMessage& msg, AbstractRouter* /*r*/) + Path::HandleCloseExitMessage(const routing::CloseExitMessage& msg, Router* /*r*/) { /// allows exits to close from their end if (SupportsAnyRoles(ePathRoleExit | ePathRoleSVC)) @@ -817,7 +815,7 @@ namespace llarp::path } bool - Path::SendExitRequest(const routing::ObtainExitMessage& msg, AbstractRouter* r) + Path::SendExitRequest(const routing::ObtainExitMessage& msg, Router* r) { LogInfo(Name(), " sending exit request to ", Endpoint()); m_ExitObtainTX = msg.tx_id; @@ -825,7 +823,7 @@ namespace llarp::path } bool - Path::SendExitClose(const routing::CloseExitMessage& msg, AbstractRouter* r) + Path::SendExitClose(const routing::CloseExitMessage& msg, Router* r) { LogInfo(Name(), " closing exit to ", Endpoint()); // mark as not exit anymore @@ -834,7 +832,7 @@ namespace llarp::path } bool - Path::HandleObtainExitMessage(const routing::ObtainExitMessage& msg, AbstractRouter* r) + Path::HandleObtainExitMessage(const routing::ObtainExitMessage& msg, Router* r) { (void)msg; (void)r; @@ -843,7 +841,7 @@ namespace llarp::path } bool - Path::HandleUpdateExitMessage(const routing::UpdateExitMessage& msg, AbstractRouter* r) + Path::HandleUpdateExitMessage(const routing::UpdateExitMessage& msg, Router* r) { (void)msg; (void)r; @@ -852,7 +850,7 @@ namespace llarp::path } bool - Path::HandleRejectExitMessage(const routing::RejectExitMessage& msg, AbstractRouter* r) + Path::HandleRejectExitMessage(const routing::RejectExitMessage& msg, Router* r) { if (m_ExitObtainTX && msg.tx_id == m_ExitObtainTX) { @@ -870,7 +868,7 @@ namespace llarp::path } bool - Path::HandleGrantExitMessage(const routing::GrantExitMessage& msg, AbstractRouter* r) + Path::HandleGrantExitMessage(const routing::GrantExitMessage& msg, Router* r) { if (m_ExitObtainTX && msg.tx_id == m_ExitObtainTX) { @@ -901,7 +899,7 @@ namespace llarp::path } bool - Path::HandleTransferTrafficMessage(const routing::TransferTrafficMessage& msg, AbstractRouter* r) + Path::HandleTransferTrafficMessage(const routing::TransferTrafficMessage& msg, Router* r) { // check if we can handle exit data if (!SupportsAnyRoles(ePathRoleExit | ePathRoleSVC)) diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 82e2fafcb2..91998f74a2 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -27,7 +27,7 @@ namespace llarp { - struct AbstractRouter; + struct Router; struct LR_CommitMessage; namespace path @@ -203,11 +203,11 @@ namespace llarp // handle data in upstream direction bool - HandleUpstream(const llarp_buffer_t& X, const TunnelNonce& Y, AbstractRouter*) override; + HandleUpstream(const llarp_buffer_t& X, const TunnelNonce& Y, Router*) override; // handle data in downstream direction bool - HandleDownstream(const llarp_buffer_t& X, const TunnelNonce& Y, AbstractRouter*) override; + HandleDownstream(const llarp_buffer_t& X, const TunnelNonce& Y, Router*) override; const std::string& ShortName() const; @@ -222,8 +222,7 @@ namespace llarp } bool - HandleLRSM( - uint64_t status, std::array& frames, AbstractRouter* r) override; + HandleLRSM(uint64_t status, std::array& frames, Router* r) override; void SetBuildResultHook(BuildResultHookFunc func); @@ -288,47 +287,45 @@ namespace llarp Rebuild(); void - Tick(llarp_time_t now, AbstractRouter* r); + Tick(llarp_time_t now, Router* r); bool - SendRoutingMessage(const routing::AbstractRoutingMessage& msg, AbstractRouter* r) override; + SendRoutingMessage(const routing::AbstractRoutingMessage& msg, Router* r) override; bool - HandleObtainExitMessage(const routing::ObtainExitMessage& msg, AbstractRouter* r) override; + HandleObtainExitMessage(const routing::ObtainExitMessage& msg, Router* r) override; bool HandleUpdateExitVerifyMessage( - const routing::UpdateExitVerifyMessage& msg, AbstractRouter* r) override; + const routing::UpdateExitVerifyMessage& msg, Router* r) override; bool - HandleTransferTrafficMessage( - const routing::TransferTrafficMessage& msg, AbstractRouter* r) override; + HandleTransferTrafficMessage(const routing::TransferTrafficMessage& msg, Router* r) override; bool - HandleUpdateExitMessage(const routing::UpdateExitMessage& msg, AbstractRouter* r) override; + HandleUpdateExitMessage(const routing::UpdateExitMessage& msg, Router* r) override; bool - HandleCloseExitMessage(const routing::CloseExitMessage& msg, AbstractRouter* r) override; + HandleCloseExitMessage(const routing::CloseExitMessage& msg, Router* r) override; bool - HandleGrantExitMessage(const routing::GrantExitMessage& msg, AbstractRouter* r) override; + HandleGrantExitMessage(const routing::GrantExitMessage& msg, Router* r) override; bool - HandleRejectExitMessage(const routing::RejectExitMessage& msg, AbstractRouter* r) override; + HandleRejectExitMessage(const routing::RejectExitMessage& msg, Router* r) override; bool - HandleDataDiscardMessage(const routing::DataDiscardMessage& msg, AbstractRouter* r) override; + HandleDataDiscardMessage(const routing::DataDiscardMessage& msg, Router* r) override; bool - HandlePathConfirmMessage(AbstractRouter* r); + HandlePathConfirmMessage(Router* r); bool - HandlePathConfirmMessage(const routing::PathConfirmMessage& msg, AbstractRouter* r) override; + HandlePathConfirmMessage(const routing::PathConfirmMessage& msg, Router* r) override; bool - HandlePathLatencyMessage(const routing::PathLatencyMessage& msg, AbstractRouter* r) override; + HandlePathLatencyMessage(const routing::PathLatencyMessage& msg, Router* r) override; bool - HandlePathTransferMessage( - const routing::PathTransferMessage& msg, AbstractRouter* r) override; + HandlePathTransferMessage(const routing::PathTransferMessage& msg, Router* r) override; bool HandleHiddenServiceFrame(const service::ProtocolFrameMessage& frame) override; @@ -337,10 +334,10 @@ namespace llarp HandleGotIntroMessage(const dht::GotIntroMessage& msg); bool - HandleDHTMessage(const dht::AbstractDHTMessage& msg, AbstractRouter* r) override; + HandleDHTMessage(const dht::AbstractDHTMessage& msg, Router* r) override; bool - HandleRoutingMessage(const llarp_buffer_t& buf, AbstractRouter* r); + HandleRoutingMessage(const llarp_buffer_t& buf, Router* r); bool IsReady() const; @@ -375,33 +372,33 @@ namespace llarp } bool - SendExitRequest(const routing::ObtainExitMessage& msg, AbstractRouter* r); + SendExitRequest(const routing::ObtainExitMessage& msg, Router* r); bool - SendExitClose(const routing::CloseExitMessage& msg, AbstractRouter* r); + SendExitClose(const routing::CloseExitMessage& msg, Router* r); void - FlushUpstream(AbstractRouter* r) override; + FlushUpstream(Router* r) override; void - FlushDownstream(AbstractRouter* r) override; + FlushDownstream(Router* r) override; protected: void - UpstreamWork(TrafficQueue_t queue, AbstractRouter* r) override; + UpstreamWork(TrafficQueue_t queue, Router* r) override; void - DownstreamWork(TrafficQueue_t queue, AbstractRouter* r) override; + DownstreamWork(TrafficQueue_t queue, Router* r) override; void - HandleAllUpstream(std::vector msgs, AbstractRouter* r) override; + HandleAllUpstream(std::vector msgs, Router* r) override; void - HandleAllDownstream(std::vector msgs, AbstractRouter* r) override; + HandleAllDownstream(std::vector msgs, Router* r) override; private: bool - SendLatencyMessage(AbstractRouter* r); + SendLatencyMessage(Router* r); /// call obtained exit hooks bool diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index 82bb0e63dc..92ccace926 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -1,17 +1,16 @@ #include "path.hpp" #include "path_context.hpp" -#include #include -#include +#include #include namespace llarp::path { static constexpr auto DefaultPathBuildLimit = 500ms; - PathContext::PathContext(AbstractRouter* router) - : m_Router(router), m_AllowTransit(false), m_PathLimits(DefaultPathBuildLimit) + PathContext::PathContext(Router* router) + : router(router), m_AllowTransit(false), m_PathLimits(DefaultPathBuildLimit) {} void @@ -44,19 +43,19 @@ namespace llarp::path const EventLoop_ptr& PathContext::loop() { - return m_Router->loop(); + return router->loop(); } const SecretKey& PathContext::EncryptionSecretKey() { - return m_Router->encryption(); + return router->encryption(); } bool PathContext::HopIsUs(const RouterID& k) const { - return std::equal(m_Router->pubkey(), m_Router->pubkey() + PUBKEYSIZE, k.begin()); + return std::equal(router->pubkey(), router->pubkey() + PUBKEYSIZE, k.begin()); } PathContext::EndpointPathPtrSet @@ -86,7 +85,7 @@ namespace llarp::path LogDebug("forwarding LRCM to ", nextHop); - return m_Router->SendToOrQueue(nextHop, msg, handler); + return router->SendToOrQueue(nextHop, msg, handler); } template < @@ -274,13 +273,7 @@ namespace llarp::path const byte_t* PathContext::OurRouterID() const { - return m_Router->pubkey(); - } - - AbstractRouter* - PathContext::Router() - { - return m_Router; + return router->pubkey(); } TransitHop_ptr @@ -303,15 +296,15 @@ namespace llarp::path void PathContext::PumpUpstream() { - m_TransitPaths.ForEach([&](auto& ptr) { ptr->FlushUpstream(m_Router); }); - m_OurPaths.ForEach([&](auto& ptr) { ptr->FlushUpstream(m_Router); }); + m_TransitPaths.ForEach([&](auto& ptr) { ptr->FlushUpstream(router); }); + m_OurPaths.ForEach([&](auto& ptr) { ptr->FlushUpstream(router); }); } void PathContext::PumpDownstream() { - m_TransitPaths.ForEach([&](auto& ptr) { ptr->FlushDownstream(m_Router); }); - m_OurPaths.ForEach([&](auto& ptr) { ptr->FlushDownstream(m_Router); }); + m_TransitPaths.ForEach([&](auto& ptr) { ptr->FlushDownstream(router); }); + m_OurPaths.ForEach([&](auto& ptr) { ptr->FlushDownstream(router); }); } uint64_t @@ -357,7 +350,7 @@ namespace llarp::path { if (itr->second->Expired(now)) { - m_Router->outboundMessageHandler().RemovePath(itr->first); + router->outboundMessageHandler().RemovePath(itr->first); itr = map.erase(itr); } else diff --git a/llarp/path/path_context.hpp b/llarp/path/path_context.hpp index 621e4629e5..359ebddc1b 100644 --- a/llarp/path/path_context.hpp +++ b/llarp/path/path_context.hpp @@ -17,7 +17,7 @@ namespace llarp { - struct AbstractRouter; + struct Router; struct LR_CommitMessage; struct RelayDownstreamMessage; struct RelayUpstreamMessage; @@ -32,7 +32,7 @@ namespace llarp struct PathContext { - explicit PathContext(AbstractRouter* router); + explicit PathContext(Router* router); /// called from router tick function void @@ -160,9 +160,6 @@ namespace llarp const EventLoop_ptr& loop(); - AbstractRouter* - Router(); - const SecretKey& EncryptionSecretKey(); @@ -178,7 +175,7 @@ namespace llarp CurrentOwnedPaths(path::PathStatus status = path::PathStatus::ePathEstablished); private: - AbstractRouter* m_Router; + Router* router; SyncTransitMap_t m_TransitPaths; SyncOwnedPathsMap_t m_OurPaths; bool m_AllowTransit; diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index 72c5000bad..eb58efc166 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include @@ -33,7 +33,7 @@ namespace llarp Handler result; size_t idx = 0; - AbstractRouter* router = nullptr; + Router* router = nullptr; WorkerFunc_t work; EventLoop_ptr loop; LR_CommitMessage LRCM; @@ -139,9 +139,9 @@ namespace llarp if (ctx->pathset->IsStopped()) return; - ctx->router->NotifyRouterEvent(ctx->router->pubkey(), ctx->path); + ctx->router->notify_router_event(ctx->router->pubkey(), ctx->path); - ctx->router->pathContext().AddOwnPath(ctx->pathset, ctx->path); + ctx->router->path_context().AddOwnPath(ctx->pathset, ctx->path); ctx->pathset->PathBuildStarted(ctx->path); const RouterID remote = ctx->path->Upstream(); @@ -184,7 +184,7 @@ namespace llarp return m_EdgeLimiter.Contains(router); } - Builder::Builder(AbstractRouter* p_router, size_t pathNum, size_t hops) + Builder::Builder(Router* p_router, size_t pathNum, size_t hops) : path::PathSet{pathNum}, _run{true}, m_router{p_router}, numHops{hops} { CryptoManager::instance()->encryption_keygen(enckey); @@ -202,7 +202,7 @@ namespace llarp { PathSet::Tick(now); now = llarp::time_now_ms(); - m_router->pathBuildLimiter().Decay(now); + m_router->pathbuild_limiter().Decay(now); ExpirePaths(now, m_router); if (ShouldBuildMore(now)) @@ -252,7 +252,7 @@ namespace llarp if (BuildCooldownHit(rc.pubkey)) return; - if (m_router->routerProfiling().IsBadForPath(rc.pubkey)) + if (m_router->router_profiling().IsBadForPath(rc.pubkey)) return; found = rc; @@ -266,9 +266,9 @@ namespace llarp Builder::GetHopsForBuild() { auto filter = [r = m_router](const auto& rc) -> bool { - return not r->routerProfiling().IsBadForPath(rc.pubkey, 1); + return not r->router_profiling().IsBadForPath(rc.pubkey, 1); }; - if (const auto maybe = m_router->nodedb()->GetRandom(filter)) + if (const auto maybe = m_router->node_db()->GetRandom(filter)) { return GetHopsAlignedToForBuild(maybe->pubkey); } @@ -309,7 +309,7 @@ namespace llarp bool Builder::BuildCooldownHit(RouterID edge) const { - return m_router->pathBuildLimiter().Limited(edge); + return m_router->pathbuild_limiter().Limited(edge); } bool @@ -344,7 +344,7 @@ namespace llarp std::optional> Builder::GetHopsAlignedToForBuild(RouterID endpoint, const std::set& exclude) { - const auto pathConfig = m_router->GetConfig()->paths; + const auto pathConfig = m_router->config()->paths; std::vector hops; { @@ -358,7 +358,7 @@ namespace llarp }; RouterContact endpointRC; - if (const auto maybe = m_router->nodedb()->Get(endpoint)) + if (const auto maybe = m_router->node_db()->Get(endpoint)) { endpointRC = *maybe; } @@ -382,7 +382,7 @@ namespace llarp hopsSet.insert(endpointRC); hopsSet.insert(hops.begin(), hops.end()); - if (r->routerProfiling().IsBadForPath(rc.pubkey, 1)) + if (r->router_profiling().IsBadForPath(rc.pubkey, 1)) return false; for (const auto& hop : hopsSet) { @@ -398,7 +398,7 @@ namespace llarp return rc.pubkey != endpointRC.pubkey; }; - if (const auto maybe = m_router->nodedb()->GetRandom(filter)) + if (const auto maybe = m_router->node_db()->GetRandom(filter)) hops.emplace_back(*maybe); else return std::nullopt; @@ -432,7 +432,7 @@ namespace llarp return; lastBuild = Now(); const RouterID edge{hops[0].pubkey}; - if (not m_router->pathBuildLimiter().Attempt(edge)) + if (not m_router->pathbuild_limiter().Attempt(edge)) { LogWarn(Name(), " building too fast to edge router ", edge); return; @@ -451,7 +451,7 @@ namespace llarp ctx->AsyncGenerateKeys( path, m_router->loop(), - [r = m_router](auto func) { r->QueueWork(std::move(func)); }, + [r = m_router](auto func) { r->queue_work(std::move(func)); }, &PathBuilderKeysGenerated); } @@ -459,7 +459,7 @@ namespace llarp Builder::HandlePathBuilt(Path_ptr p) { buildIntervalLimit = PATH_BUILD_RATE; - m_router->routerProfiling().MarkPathSuccess(p.get()); + m_router->router_profiling().MarkPathSuccess(p.get()); LogInfo(p->Name(), " built latency=", ToString(p->intro.latency)); m_BuildStats.success++; @@ -484,7 +484,7 @@ namespace llarp void Builder::HandlePathBuildTimeout(Path_ptr p) { - m_router->routerProfiling().MarkPathTimeout(p.get()); + m_router->router_profiling().MarkPathTimeout(p.get()); PathSet::HandlePathBuildTimeout(p); DoPathBuildBackoff(); for (const auto& hop : p->hops) @@ -493,20 +493,20 @@ namespace llarp // look up router and see if it's still on the network m_router->loop()->call_soon([router, r = m_router]() { LogInfo("looking up ", router, " because of path build timeout"); - r->rcLookupHandler().GetRC( + r->rc_lookup_handler().get_rc( router, [r](const auto& router, const auto* rc, auto result) { if (result == RCRequestResult::Success && rc != nullptr) { LogInfo("refreshed rc for ", router); - r->nodedb()->PutIfNewer(*rc); + r->node_db()->PutIfNewer(*rc); } else { // remove all connections to this router as it's probably not registered anymore LogWarn("removing router ", router, " because of path build timeout"); - r->linkManager().deregister_peer(router); - r->nodedb()->Remove(router); + r->link_manager().deregister_peer(router); + r->node_db()->Remove(router); } }, true); diff --git a/llarp/path/pathbuilder.hpp b/llarp/path/pathbuilder.hpp index a011989740..f9cf2e3d2a 100644 --- a/llarp/path/pathbuilder.hpp +++ b/llarp/path/pathbuilder.hpp @@ -57,14 +57,14 @@ namespace llarp DoPathBuildBackoff(); public: - AbstractRouter* const m_router; + Router* const m_router; SecretKey enckey; size_t numHops; llarp_time_t lastBuild = 0s; llarp_time_t buildIntervalLimit = MIN_PATH_BUILD_INTERVAL; /// construct - Builder(AbstractRouter* p_router, size_t numDesiredPaths, size_t numHops); + Builder(Router* p_router, size_t numDesiredPaths, size_t numHops); virtual ~Builder() = default; diff --git a/llarp/path/pathset.cpp b/llarp/path/pathset.cpp index 1f15c3fd79..f05a372f7f 100644 --- a/llarp/path/pathset.cpp +++ b/llarp/path/pathset.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include @@ -62,7 +62,7 @@ namespace llarp::path } void - PathSet::TickPaths(AbstractRouter* r) + PathSet::TickPaths(Router* r) { const auto now = llarp::time_now_ms(); Lock_t l{m_PathsMutex}; @@ -92,7 +92,7 @@ namespace llarp::path } void - PathSet::ExpirePaths(llarp_time_t now, AbstractRouter* router) + PathSet::ExpirePaths(llarp_time_t now, Router* router) { Lock_t l(m_PathsMutex); if (m_Paths.size() == 0) @@ -452,13 +452,13 @@ namespace llarp::path } void - PathSet::UpstreamFlush(AbstractRouter* r) + PathSet::UpstreamFlush(Router* r) { ForEachPath([r](const Path_ptr& p) { p->FlushUpstream(r); }); } void - PathSet::DownstreamFlush(AbstractRouter* r) + PathSet::DownstreamFlush(Router* r) { ForEachPath([r](const Path_ptr& p) { p->FlushDownstream(r); }); } diff --git a/llarp/path/pathset.hpp b/llarp/path/pathset.hpp index cbaeb52f21..581c38dfa1 100644 --- a/llarp/path/pathset.hpp +++ b/llarp/path/pathset.hpp @@ -156,7 +156,7 @@ namespace llarp GetByUpstream(RouterID remote, PathID_t rxid) const; void - ExpirePaths(llarp_time_t now, AbstractRouter* router); + ExpirePaths(llarp_time_t now, Router* router); /// get the number of paths in this status size_t @@ -268,7 +268,7 @@ namespace llarp std::function filter) const; virtual bool - PublishIntroSet(const service::EncryptedIntroSet&, AbstractRouter*) + PublishIntroSet(const service::EncryptedIntroSet&, Router*) { return false; } @@ -299,10 +299,10 @@ namespace llarp } void - UpstreamFlush(AbstractRouter* r); + UpstreamFlush(Router* r); void - DownstreamFlush(AbstractRouter* r); + DownstreamFlush(Router* r); size_t numDesiredPaths; @@ -310,7 +310,7 @@ namespace llarp BuildStats m_BuildStats; void - TickPaths(AbstractRouter* r); + TickPaths(Router* r); using Mtx_t = util::NullMutex; using Lock_t = util::NullLock; diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index c990200238..8b81cc9c62 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -9,7 +9,7 @@ #include #include "path_context.hpp" #include "transit_hop.hpp" -#include +#include #include #include #include @@ -50,7 +50,7 @@ namespace llarp::path } bool - TransitHop::HandleLRSM(uint64_t status, std::array& frames, AbstractRouter* r) + TransitHop::HandleLRSM(uint64_t status, std::array& frames, Router* r) { auto msg = std::make_shared(frames); msg->status = status; @@ -85,7 +85,7 @@ namespace llarp::path std::move around. */ bool - TransitHop::SendRoutingMessage(const routing::AbstractRoutingMessage& msg, AbstractRouter* r) + TransitHop::SendRoutingMessage(const routing::AbstractRoutingMessage& msg, Router* r) { if (!IsEndpoint(r->pubkey())) return false; @@ -113,7 +113,7 @@ namespace llarp::path } void - TransitHop::DownstreamWork(TrafficQueue_t msgs, AbstractRouter* r) + TransitHop::DownstreamWork(TrafficQueue_t msgs, Router* r) { auto flushIt = [self = shared_from_this(), r]() { std::vector msgs; @@ -149,7 +149,7 @@ namespace llarp::path } void - TransitHop::UpstreamWork(TrafficQueue_t msgs, AbstractRouter* r) + TransitHop::UpstreamWork(TrafficQueue_t msgs, Router* r) { for (auto& ev : msgs) { @@ -175,7 +175,7 @@ namespace llarp::path } void - TransitHop::HandleAllUpstream(std::vector msgs, AbstractRouter* r) + TransitHop::HandleAllUpstream(std::vector msgs, Router* r) { if (IsEndpoint(r->pubkey())) { @@ -213,7 +213,7 @@ namespace llarp::path } void - TransitHop::HandleAllDownstream(std::vector msgs, AbstractRouter* r) + TransitHop::HandleAllDownstream(std::vector msgs, Router* r) { for (const auto& msg : msgs) { @@ -230,38 +230,37 @@ namespace llarp::path } void - TransitHop::FlushUpstream(AbstractRouter* r) + TransitHop::FlushUpstream(Router* r) { if (not m_UpstreamQueue.empty()) { - r->QueueWork([self = shared_from_this(), - data = std::exchange(m_UpstreamQueue, {}), - r]() mutable { self->UpstreamWork(std::move(data), r); }); + r->queue_work([self = shared_from_this(), + data = std::exchange(m_UpstreamQueue, {}), + r]() mutable { self->UpstreamWork(std::move(data), r); }); } } void - TransitHop::FlushDownstream(AbstractRouter* r) + TransitHop::FlushDownstream(Router* r) { if (not m_DownstreamQueue.empty()) { - r->QueueWork([self = shared_from_this(), - data = std::exchange(m_DownstreamQueue, {}), - r]() mutable { self->DownstreamWork(std::move(data), r); }); + r->queue_work([self = shared_from_this(), + data = std::exchange(m_DownstreamQueue, {}), + r]() mutable { self->DownstreamWork(std::move(data), r); }); } } /// this is where a DHT message is handled at the end of a path, that is, /// where a SNode receives a DHT message from a client along a path. bool - TransitHop::HandleDHTMessage(const llarp::dht::AbstractDHTMessage& msg, AbstractRouter* r) + TransitHop::HandleDHTMessage(const llarp::dht::AbstractDHTMessage& msg, Router* r) { return r->dht()->RelayRequestForPath(info.rxID, msg); } bool - TransitHop::HandlePathLatencyMessage( - const llarp::routing::PathLatencyMessage& msg, AbstractRouter* r) + TransitHop::HandlePathLatencyMessage(const llarp::routing::PathLatencyMessage& msg, Router* r) { llarp::routing::PathLatencyMessage reply; reply.latency = msg.sent_time; @@ -271,8 +270,7 @@ namespace llarp::path bool TransitHop::HandlePathConfirmMessage( - [[maybe_unused]] const llarp::routing::PathConfirmMessage& msg, - [[maybe_unused]] AbstractRouter* r) + [[maybe_unused]] const llarp::routing::PathConfirmMessage& msg, [[maybe_unused]] Router* r) { llarp::LogWarn("unwarranted path confirm message on ", info); return false; @@ -280,16 +278,14 @@ namespace llarp::path bool TransitHop::HandleDataDiscardMessage( - [[maybe_unused]] const llarp::routing::DataDiscardMessage& msg, - [[maybe_unused]] AbstractRouter* r) + [[maybe_unused]] const llarp::routing::DataDiscardMessage& msg, [[maybe_unused]] Router* r) { llarp::LogWarn("unwarranted path data discard message on ", info); return false; } bool - TransitHop::HandleObtainExitMessage( - const llarp::routing::ObtainExitMessage& msg, AbstractRouter* r) + TransitHop::HandleObtainExitMessage(const llarp::routing::ObtainExitMessage& msg, Router* r) { if (msg.Verify() && r->exitContext().ObtainNewExit(msg.pubkey, info.rxID, msg.flag != 0)) { @@ -317,7 +313,7 @@ namespace llarp::path } bool - TransitHop::HandleCloseExitMessage(const llarp::routing::CloseExitMessage& msg, AbstractRouter* r) + TransitHop::HandleCloseExitMessage(const llarp::routing::CloseExitMessage& msg, Router* r) { const llarp::routing::DataDiscardMessage discard(info.rxID, msg.sequence_number); auto ep = r->exitContext().FindEndpointForPath(info.rxID); @@ -340,7 +336,7 @@ namespace llarp::path bool TransitHop::HandleUpdateExitVerifyMessage( - const llarp::routing::UpdateExitVerifyMessage& msg, AbstractRouter* r) + const llarp::routing::UpdateExitVerifyMessage& msg, Router* r) { (void)msg; (void)r; @@ -349,8 +345,7 @@ namespace llarp::path } bool - TransitHop::HandleUpdateExitMessage( - const llarp::routing::UpdateExitMessage& msg, AbstractRouter* r) + TransitHop::HandleUpdateExitMessage(const llarp::routing::UpdateExitMessage& msg, Router* r) { auto ep = r->exitContext().FindEndpointForPath(msg.path_id); if (ep) @@ -372,8 +367,7 @@ namespace llarp::path } bool - TransitHop::HandleRejectExitMessage( - const llarp::routing::RejectExitMessage& msg, AbstractRouter* r) + TransitHop::HandleRejectExitMessage(const llarp::routing::RejectExitMessage& msg, Router* r) { (void)msg; (void)r; @@ -382,7 +376,7 @@ namespace llarp::path } bool - TransitHop::HandleGrantExitMessage(const llarp::routing::GrantExitMessage& msg, AbstractRouter* r) + TransitHop::HandleGrantExitMessage(const llarp::routing::GrantExitMessage& msg, Router* r) { (void)msg; (void)r; @@ -392,7 +386,7 @@ namespace llarp::path bool TransitHop::HandleTransferTrafficMessage( - const llarp::routing::TransferTrafficMessage& msg, AbstractRouter* r) + const llarp::routing::TransferTrafficMessage& msg, Router* r) { auto endpoint = r->exitContext().FindEndpointForPath(info.rxID); if (endpoint) @@ -418,10 +412,9 @@ namespace llarp::path } bool - TransitHop::HandlePathTransferMessage( - const llarp::routing::PathTransferMessage& msg, AbstractRouter* r) + TransitHop::HandlePathTransferMessage(const llarp::routing::PathTransferMessage& msg, Router* r) { - auto path = r->pathContext().GetPathForTransfer(msg.path_id); + auto path = r->path_context().GetPathForTransfer(msg.path_id); llarp::routing::DataDiscardMessage discarded{msg.path_id, msg.sequence_number}; if (path == nullptr || msg.protocol_frame_msg.path_id != info.txID) { @@ -457,7 +450,7 @@ namespace llarp::path } void - TransitHop::QueueDestroySelf(AbstractRouter* r) + TransitHop::QueueDestroySelf(Router* r) { r->loop()->call([self = shared_from_this()] { self->SetSelfDestruct(); }); } diff --git a/llarp/path/transit_hop.hpp b/llarp/path/transit_hop.hpp index a52374734a..4752eca762 100644 --- a/llarp/path/transit_hop.hpp +++ b/llarp/path/transit_hop.hpp @@ -100,8 +100,7 @@ namespace llarp } bool - HandleLRSM( - uint64_t status, std::array& frames, AbstractRouter* r) override; + HandleLRSM(uint64_t status, std::array& frames, Router* r) override; std::string ToString() const; @@ -117,47 +116,45 @@ namespace llarp // send routing message when end of path bool - SendRoutingMessage(const routing::AbstractRoutingMessage& msg, AbstractRouter* r) override; + SendRoutingMessage(const routing::AbstractRoutingMessage& msg, Router* r) override; // handle routing message when end of path bool - HandleRoutingMessage(const routing::AbstractRoutingMessage& msg, AbstractRouter* r); + HandleRoutingMessage(const routing::AbstractRoutingMessage& msg, Router* r); bool - HandleDataDiscardMessage(const routing::DataDiscardMessage& msg, AbstractRouter* r) override; + HandleDataDiscardMessage(const routing::DataDiscardMessage& msg, Router* r) override; bool - HandlePathConfirmMessage(AbstractRouter* r); + HandlePathConfirmMessage(Router* r); bool - HandlePathConfirmMessage(const routing::PathConfirmMessage& msg, AbstractRouter* r) override; + HandlePathConfirmMessage(const routing::PathConfirmMessage& msg, Router* r) override; bool - HandlePathTransferMessage( - const routing::PathTransferMessage& msg, AbstractRouter* r) override; + HandlePathTransferMessage(const routing::PathTransferMessage& msg, Router* r) override; bool - HandlePathLatencyMessage(const routing::PathLatencyMessage& msg, AbstractRouter* r) override; + HandlePathLatencyMessage(const routing::PathLatencyMessage& msg, Router* r) override; bool - HandleObtainExitMessage(const routing::ObtainExitMessage& msg, AbstractRouter* r) override; + HandleObtainExitMessage(const routing::ObtainExitMessage& msg, Router* r) override; bool HandleUpdateExitVerifyMessage( - const routing::UpdateExitVerifyMessage& msg, AbstractRouter* r) override; + const routing::UpdateExitVerifyMessage& msg, Router* r) override; bool - HandleTransferTrafficMessage( - const routing::TransferTrafficMessage& msg, AbstractRouter* r) override; + HandleTransferTrafficMessage(const routing::TransferTrafficMessage& msg, Router* r) override; bool - HandleUpdateExitMessage(const routing::UpdateExitMessage& msg, AbstractRouter* r) override; + HandleUpdateExitMessage(const routing::UpdateExitMessage& msg, Router* r) override; bool - HandleGrantExitMessage(const routing::GrantExitMessage& msg, AbstractRouter* r) override; + HandleGrantExitMessage(const routing::GrantExitMessage& msg, Router* r) override; bool - HandleRejectExitMessage(const routing::RejectExitMessage& msg, AbstractRouter* r) override; + HandleRejectExitMessage(const routing::RejectExitMessage& msg, Router* r) override; bool - HandleCloseExitMessage(const routing::CloseExitMessage& msg, AbstractRouter* r) override; + HandleCloseExitMessage(const routing::CloseExitMessage& msg, Router* r) override; bool HandleHiddenServiceFrame(const service::ProtocolFrameMessage& /*frame*/) override @@ -171,29 +168,29 @@ namespace llarp HandleGotIntroMessage(const dht::GotIntroMessage& msg); bool - HandleDHTMessage(const dht::AbstractDHTMessage& msg, AbstractRouter* r) override; + HandleDHTMessage(const dht::AbstractDHTMessage& msg, Router* r) override; void - FlushUpstream(AbstractRouter* r) override; + FlushUpstream(Router* r) override; void - FlushDownstream(AbstractRouter* r) override; + FlushDownstream(Router* r) override; void - QueueDestroySelf(AbstractRouter* r); + QueueDestroySelf(Router* r); protected: void - UpstreamWork(TrafficQueue_t queue, AbstractRouter* r) override; + UpstreamWork(TrafficQueue_t queue, Router* r) override; void - DownstreamWork(TrafficQueue_t queue, AbstractRouter* r) override; + DownstreamWork(TrafficQueue_t queue, Router* r) override; void - HandleAllUpstream(std::vector msgs, AbstractRouter* r) override; + HandleAllUpstream(std::vector msgs, Router* r) override; void - HandleAllDownstream(std::vector msgs, AbstractRouter* r) override; + HandleAllDownstream(std::vector msgs, Router* r) override; private: void diff --git a/llarp/router/abstractrouter.hpp b/llarp/router/abstractrouter.hpp deleted file mode 100644 index 109e265fe3..0000000000 --- a/llarp/router/abstractrouter.hpp +++ /dev/null @@ -1,397 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include "outbound_message_handler.hpp" -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef LOKINET_HIVE -#include -#endif - -struct llarp_buffer_t; -struct llarp_dht_context; - -namespace oxenmq -{ - class OxenMQ; -} - -namespace llarp -{ - class NodeDB; - struct Config; - struct RouterID; - struct AbstractLinkMessage; - struct AbstractLinkSession; - struct PathID_t; - struct Profiling; - struct SecretKey; - struct Signature; - struct OutboundMessageHandler; - struct LinkManager; - struct RCLookupHandler; - struct RoutePoker; - - namespace dht - { - struct AbstractDHTMessageHandler; - } - - namespace dns - { - class I_SystemSettings; - } - - namespace net - { - class Platform; - } - - namespace exit - { - struct Context; - } - - namespace rpc - { - struct LokidRpcClient; - } - - namespace path - { - struct PathContext; - } - - namespace routing - { - struct AbstractRoutingMessageHandler; - } - - namespace service - { - struct Context; - } - - namespace thread - { - class ThreadPool; - } - - namespace vpn - { - class Platform; - } - - using LMQ_ptr = std::shared_ptr; - - struct AbstractRouter : public std::enable_shared_from_this - { -#ifdef LOKINET_HIVE - tooling::RouterHive* hive = nullptr; -#endif - - virtual ~AbstractRouter() = default; - - virtual bool - HandleRecvLinkMessageBuffer(AbstractLinkSession* from, const llarp_buffer_t& msg) = 0; - - virtual const net::Platform& - Net() const = 0; - - virtual const LMQ_ptr& - lmq() const = 0; - - virtual vpn::Platform* - GetVPNPlatform() const = 0; - - virtual const std::shared_ptr& - RpcClient() const = 0; - - virtual std::shared_ptr - dht() const = 0; - - virtual const std::shared_ptr& - nodedb() const = 0; - - virtual const path::PathContext& - pathContext() const = 0; - - virtual path::PathContext& - pathContext() = 0; - - virtual const RouterContact& - rc() const = 0; - - /// modify our rc - /// modify returns nullopt if unmodified otherwise it returns the new rc to be sigend and - /// published out - virtual void - ModifyOurRC(std::function(RouterContact)> modify) = 0; - - virtual exit::Context& - exitContext() = 0; - - virtual const std::shared_ptr& - keyManager() const = 0; - - virtual const SecretKey& - identity() const = 0; - - virtual const SecretKey& - encryption() const = 0; - - virtual Profiling& - routerProfiling() = 0; - - virtual const EventLoop_ptr& - loop() const = 0; - - /// call function in crypto worker - virtual void QueueWork(std::function) = 0; - - /// call function in disk io thread - virtual void QueueDiskIO(std::function) = 0; - - virtual std::shared_ptr - GetConfig() const - { - return nullptr; - } - - virtual service::Context& - hiddenServiceContext() = 0; - - virtual const service::Context& - hiddenServiceContext() const = 0; - - virtual OutboundMessageHandler& - outboundMessageHandler() = 0; - - virtual LinkManager& - linkManager() = 0; - - virtual const std::shared_ptr& - routePoker() const = 0; - - virtual RCLookupHandler& - rcLookupHandler() = 0; - - virtual std::shared_ptr - peerDb() = 0; - - virtual bool - Sign(Signature& sig, const llarp_buffer_t& buf) const = 0; - - virtual bool - Configure(std::shared_ptr conf, bool isSNode, std::shared_ptr nodedb) = 0; - - virtual bool - IsServiceNode() const = 0; - - /// Called to determine if we're in a bad state (which gets reported to our oxend) that should - /// prevent uptime proofs from going out to the network (so that the error state gets noticed). - /// Currently this means we require a decent number of peers whenever we are fully staked - /// (active or decommed). - virtual std::optional - OxendErrorState() const = 0; - - virtual bool - StartRpcServer() = 0; - - virtual bool - Run() = 0; - - virtual bool - IsRunning() const = 0; - - virtual bool - LooksAlive() const = 0; - - /// stop running the router logic gracefully - virtual void - Stop() = 0; - - /// indicate we are about to sleep for a while - virtual void - Freeze() = 0; - - /// thaw from long sleep or network changed event - virtual void - Thaw() = 0; - - /// non gracefully stop the router - virtual void - Die() = 0; - - /// Trigger a pump of low level links. Idempotent. - virtual void - TriggerPump() = 0; - - virtual bool - IsBootstrapNode(RouterID r) const = 0; - - virtual const byte_t* - pubkey() const = 0; - - /// get what our real public ip is if we can know it - virtual std::optional> - OurPublicIP() const = 0; - - /// connect to N random routers - virtual void - ConnectToRandomRouters(int N) = 0; - - virtual bool - TryConnectAsync(RouterContact rc, uint16_t tries) = 0; - - /// called by link when a remote session has no more sessions open - virtual void - SessionClosed(RouterID remote) = 0; - - /// returns system clock milliseconds since epoch - virtual llarp_time_t - Now() const = 0; - - /// returns milliseconds since started - virtual llarp_time_t - Uptime() const = 0; - - virtual bool - GetRandomGoodRouter(RouterID& r) = 0; - - virtual bool - SendToOrQueue( - const RouterID& remote, - const AbstractLinkMessage& msg, - SendStatusHandler handler = nullptr) = 0; - - virtual void - PersistSessionUntil(const RouterID& remote, llarp_time_t until) = 0; - - virtual bool - ParseRoutingMessageBuffer( - const llarp_buffer_t& buf, - routing::AbstractRoutingMessageHandler* h, - const PathID_t& rxid) = 0; - - /// count the number of service nodes we are connected to - virtual size_t - NumberOfConnectedRouters() const = 0; - - /// count the number of clients that are connected to us - virtual size_t - NumberOfConnectedClients() const = 0; - - virtual bool - GetRandomConnectedRouter(RouterContact& result) const = 0; - - virtual void - HandleDHTLookupForExplore(RouterID remote, const std::vector& results) = 0; - - virtual void SetDownHook(std::function){}; - - /// lookup router by pubkey - /// if we are a service node this is done direct otherwise it's done via - /// path - virtual void - LookupRouter(RouterID remote, RouterLookupHandler resultHandler) = 0; - - /// check if newRc matches oldRC and update local rc for this remote contact - /// if valid - /// returns true on valid and updated - /// returns false otherwise - virtual bool - CheckRenegotiateValid(RouterContact newRc, RouterContact oldRC) = 0; - - /// set router's service node whitelist - virtual void - SetRouterWhitelist( - const std::vector& whitelist, - const std::vector& greylist, - const std::vector& unfundedlist) = 0; - - virtual std::unordered_set - GetRouterWhitelist() const = 0; - - /// visit each connected link session - virtual void - ForEachPeer( - std::function visit, bool randomize) const = 0; - - virtual bool - SessionToRouterAllowed(const RouterID& router) const = 0; - - virtual bool - PathToRouterAllowed(const RouterID& router) const = 0; - - /// return true if we have an exit as a client - virtual bool - HasClientExit() const - { - return false; - }; - - virtual path::BuildLimiter& - pathBuildLimiter() = 0; - - /// return true if we have at least 1 session to this router in either - /// direction - virtual bool - HasSessionTo(const RouterID& router) const = 0; - - virtual uint32_t - NextPathBuildNumber() = 0; - - virtual std::string - ShortName() const = 0; - - virtual util::StatusObject - ExtractStatus() const = 0; - - virtual util::StatusObject - ExtractSummaryStatus() const = 0; - - /// gossip an rc if required - virtual void - GossipRCIfNeeded(const RouterContact rc) = 0; - - virtual std::string - status_line() = 0; - - /// Templated convenience function to generate a RouterHive event and - /// delegate to non-templated (and overridable) function for handling. - template - void - NotifyRouterEvent([[maybe_unused]] Params&&... args) const - { - // TODO: no-op when appropriate - auto event = std::make_unique(args...); - HandleRouterEvent(std::move(event)); - } - - virtual int - OutboundUDPSocket() const - { - return -1; - } - - protected: - /// Virtual function to handle RouterEvent. HiveRouter overrides this in - /// order to inject the event. The default implementation in Router simply - /// logs it. - virtual void - HandleRouterEvent(tooling::RouterEventPtr event) const = 0; - }; -} // namespace llarp diff --git a/llarp/router/outbound_message_handler.cpp b/llarp/router/outbound_message_handler.cpp index 37a8c214a4..5743f9dbc1 100644 --- a/llarp/router/outbound_message_handler.cpp +++ b/llarp/router/outbound_message_handler.cpp @@ -24,8 +24,8 @@ namespace llarp const RouterID& remote, const AbstractLinkMessage& msg, SendStatusHandler callback) { // if the destination is invalid, callback with failure and return - if (not _router->linkManager().have_client_connection_to(remote) - and not _router->rcLookupHandler().SessionIsAllowed(remote)) + if (not _router->link_manager().have_client_connection_to(remote) + and not _router->rc_lookup_handler().is_session_allowed(remote)) { DoCallback(callback, SendStatus::InvalidRouter); return true; @@ -47,7 +47,7 @@ namespace llarp std::copy_n(_buf.data(), _buf.size(), ent.message.data()); // if we have a session to the destination, queue the message and return - if (_router->linkManager().have_connection_to(remote)) + if (_router->link_manager().have_connection_to(remote)) { QueueOutboundMessage(std::move(ent)); return true; @@ -126,7 +126,7 @@ namespace llarp } void - OutboundMessageHandler::Init(AbstractRouter* router) + OutboundMessageHandler::Init(Router* router) { _router = router; outboundMessageQueues.emplace(zeroID, MessageQueue()); @@ -170,7 +170,7 @@ namespace llarp void OutboundMessageHandler::QueueSessionCreation(const RouterID& remote) { - _router->linkManager().Connect(remote); + _router->link_manager().Connect(remote); } /** Note: This is where AbstractLinkMessage::bt_encode() is called. Contextually, this is @@ -196,7 +196,7 @@ namespace llarp const llarp_buffer_t buf{ent.message}; m_queueStats.sent++; SendStatusHandler callback = ent.inform; - return _router->linkManager().send_to( + return _router->link_manager().send_to( ent.router, buf, [this, callback](AbstractLinkSession::DeliveryStatus status) { @@ -213,7 +213,7 @@ namespace llarp bool OutboundMessageHandler::SendIfSession(const MessageQueueEntry& ent) { - if (_router->linkManager().have_connection_to(ent.router)) + if (_router->link_manager().have_connection_to(ent.router)) { return Send(ent); } diff --git a/llarp/router/outbound_message_handler.hpp b/llarp/router/outbound_message_handler.hpp index a71c6849f3..da688b75a7 100644 --- a/llarp/router/outbound_message_handler.hpp +++ b/llarp/router/outbound_message_handler.hpp @@ -25,7 +25,7 @@ namespace llarp Congestion }; - struct AbstractRouter; + struct Router; enum class SessionResult; struct AbstractLinkMessage; struct RouterID; @@ -88,7 +88,7 @@ namespace llarp ExtractStatus() const; void - Init(AbstractRouter* router); + Init(Router* router); private: /* A message that has been queued for sending, but not yet @@ -210,7 +210,7 @@ namespace llarp std::queue roundRobinOrder; - AbstractRouter* _router; + Router* _router; util::ContentionKiller m_Killer; diff --git a/llarp/router/outbound_session_maker.cpp b/llarp/router/outbound_session_maker.cpp index 387ecb0cf9..b6812fa35a 100644 --- a/llarp/router/outbound_session_maker.cpp +++ b/llarp/router/outbound_session_maker.cpp @@ -1,6 +1,6 @@ #include "outbound_session_maker.hpp" -#include "abstractrouter.hpp" +#include "Router.hpp" #include #include #include @@ -157,7 +157,7 @@ namespace llarp void OutboundSessionMaker::Init( - AbstractRouter* router, + Router* router, LinkManager* linkManager, RCLookupHandler* rcLookup, Profiling* profiler, diff --git a/llarp/router/outbound_session_maker.hpp b/llarp/router/outbound_session_maker.hpp index 7749268da7..6f2a871250 100644 --- a/llarp/router/outbound_session_maker.hpp +++ b/llarp/router/outbound_session_maker.hpp @@ -1,5 +1,13 @@ #pragma once +/* + Note: + - this class is marked for destruction + - functionality to be absorbed into llarp/link/link_manager.hpp + - can be subdivided into multiple objects + +*/ + #include "rc_lookup_handler.hpp" #include @@ -80,7 +88,7 @@ namespace llarp void Init( - AbstractRouter* router, + Router* router, LinkManager* linkManager, RCLookupHandler* rcLookup, Profiling* profiler, @@ -125,7 +133,7 @@ namespace llarp std::unordered_map pendingCallbacks GUARDED_BY(_mutex); - AbstractRouter* _router = nullptr; + Router* _router = nullptr; LinkManager* _linkManager = nullptr; RCLookupHandler* _rcLookup = nullptr; Profiling* _profiler = nullptr; diff --git a/llarp/router/rc_gossiper.cpp b/llarp/router/rc_gossiper.cpp index 986e25f4a9..7012556029 100644 --- a/llarp/router/rc_gossiper.cpp +++ b/llarp/router/rc_gossiper.cpp @@ -12,42 +12,41 @@ namespace llarp // (30 minutes * 2) - 5 minutes static constexpr auto GossipOurRCInterval = (RCGossipFilterDecayInterval * 2) - (5min); - RCGossiper::RCGossiper() - : m_Filter(std::chrono::duration_cast(RCGossipFilterDecayInterval)) + RCGossiper::RCGossiper() : filter(std::chrono::duration_cast(RCGossipFilterDecayInterval)) {} void - RCGossiper::Init(LinkManager* l, const RouterID& ourID, AbstractRouter* router) + RCGossiper::Init(LinkManager* l, const RouterID& ourID, Router* router) { - m_OurRouterID = ourID; - m_LinkManager = l; - m_router = router; + rid = ourID; + link_manager = l; + router = router; } bool RCGossiper::ShouldGossipOurRC(Time_t now) const { - return now >= (m_LastGossipedOurRC + GossipOurRCInterval); + return now >= (last_rc_gossip + GossipOurRCInterval); } bool RCGossiper::IsOurRC(const RouterContact& rc) const { - return rc.pubkey == m_OurRouterID; + return rc.pubkey == rid; } void RCGossiper::Decay(Time_t now) { - m_Filter.Decay(now); + filter.Decay(now); } void RCGossiper::Forget(const RouterID& pk) { - m_Filter.Remove(pk); - if (m_OurRouterID == pk) - m_LastGossipedOurRC = 0s; + filter.Remove(pk); + if (rid == pk) + last_rc_gossip = 0s; } TimePoint_t @@ -61,9 +60,9 @@ namespace llarp std::optional RCGossiper::LastGossipAt() const { - if (m_LastGossipedOurRC == 0s) + if (last_rc_gossip == 0s) return std::nullopt; - return DateClock_t::time_point{m_LastGossipedOurRC}; + return DateClock_t::time_point{last_rc_gossip}; } bool @@ -72,13 +71,13 @@ namespace llarp // only distribute public routers if (not rc.IsPublicRouter()) return false; - if (m_LinkManager == nullptr) + if (link_manager == nullptr) return false; const RouterID pubkey(rc.pubkey); // filter check - if (m_Filter.Contains(pubkey)) + if (filter.Contains(pubkey)) return false; - m_Filter.Insert(pubkey); + filter.Insert(pubkey); const auto now = time_now_ms(); // is this our rc? @@ -91,7 +90,7 @@ namespace llarp return false; } // ya pop it - m_LastGossipedOurRC = now; + last_rc_gossip = now; } // send a GRCM as gossip method diff --git a/llarp/router/rc_gossiper.hpp b/llarp/router/rc_gossiper.hpp index a82840e77c..b753bb8385 100644 --- a/llarp/router/rc_gossiper.hpp +++ b/llarp/router/rc_gossiper.hpp @@ -3,7 +3,6 @@ #include #include "outbound_message_handler.hpp" #include -#include "abstractrouter.hpp" namespace llarp { @@ -31,7 +30,7 @@ namespace llarp IsOurRC(const RouterContact& rc) const; void - Init(LinkManager*, const RouterID&, AbstractRouter*); + Init(LinkManager*, const RouterID&, Router*); void Forget(const RouterID& router); @@ -43,11 +42,11 @@ namespace llarp LastGossipAt() const; private: - RouterID m_OurRouterID; - Time_t m_LastGossipedOurRC = 0s; - LinkManager* m_LinkManager = nullptr; - util::DecayingHashSet m_Filter; + RouterID rid; + Time_t last_rc_gossip = 0s; + LinkManager* link_manager = nullptr; + util::DecayingHashSet filter; - AbstractRouter* m_router; + Router* router; }; } // namespace llarp diff --git a/llarp/router/rc_lookup_handler.cpp b/llarp/router/rc_lookup_handler.cpp index f55d50e826..86305248f7 100644 --- a/llarp/router/rc_lookup_handler.cpp +++ b/llarp/router/rc_lookup_handler.cpp @@ -2,7 +2,6 @@ #include "rc_lookup_handler.hpp" #include -#include #include #include #include @@ -10,7 +9,7 @@ #include #include #include -#include "abstractrouter.hpp" +#include "router.hpp" #include #include @@ -19,17 +18,17 @@ namespace llarp { void - RCLookupHandler::AddValidRouter(const RouterID& router) + RCLookupHandler::add_valid_router(const RouterID& router) { util::Lock l(_mutex); - whitelistRouters.insert(router); + router_whitelist.insert(router); } void - RCLookupHandler::RemoveValidRouter(const RouterID& router) + RCLookupHandler::remove_valid_router(const RouterID& router) { util::Lock l(_mutex); - whitelistRouters.erase(router); + router_whitelist.erase(router); } static void @@ -40,7 +39,7 @@ namespace llarp } void - RCLookupHandler::SetRouterWhitelist( + RCLookupHandler::set_router_whitelist( const std::vector& whitelist, const std::vector& greylist, const std::vector& greenlist) @@ -49,34 +48,34 @@ namespace llarp return; util::Lock l(_mutex); - loadColourList(whitelistRouters, whitelist); - loadColourList(greylistRouters, greylist); - loadColourList(greenlistRouters, greenlist); + loadColourList(router_whitelist, whitelist); + loadColourList(router_greylist, greylist); + loadColourList(router_greenlist, greenlist); - LogInfo("lokinet service node list now has ", whitelistRouters.size(), " active routers"); + LogInfo("lokinet service node list now has ", router_whitelist.size(), " active routers"); } bool - RCLookupHandler::HaveReceivedWhitelist() const + RCLookupHandler::has_received_whitelist() const { util::Lock l(_mutex); - return not whitelistRouters.empty(); + return not router_whitelist.empty(); } void - RCLookupHandler::GetRC(const RouterID& router, RCRequestCallback callback, bool forceLookup) + RCLookupHandler::get_rc(const RouterID& router, RCRequestCallback callback, bool forceLookup) { RouterContact remoteRC; if (not forceLookup) { - if (const auto maybe = _nodedb->Get(router); maybe.has_value()) + if (const auto maybe = node_db->Get(router); maybe.has_value()) { remoteRC = *maybe; if (callback) { callback(router, &remoteRC, RCRequestResult::Success); } - FinalizeRequest(router, &remoteRC, RCRequestResult::Success); + finalize_request(router, &remoteRC, RCRequestResult::Success); return; } } @@ -85,7 +84,7 @@ namespace llarp { util::Lock l(_mutex); - auto itr_pair = pendingCallbacks.emplace(router, CallbacksQueue{}); + auto itr_pair = pending_callbacks.emplace(router, callback_que{}); if (callback) { @@ -96,14 +95,14 @@ namespace llarp if (shouldDoLookup) { - auto fn = [this, router](const auto& res) { HandleDHTLookupResult(router, res); }; + auto fn = [this, router](const auto& res) { handle_dht_lookup_result(router, res); }; // if we are a client try using the hidden service endpoints if (!isServiceNode) { bool sent = false; LogInfo("Lookup ", router, " anonymously"); - _hiddenServiceContext->ForEachService( + hidden_service_context->ForEachService( [&](const std::string&, const std::shared_ptr& ep) -> bool { const bool success = ep->LookupRouterAnon(router, fn); sent = sent || success; @@ -114,22 +113,22 @@ namespace llarp LogWarn("cannot lookup ", router, " anonymously"); } - if (!_dht->LookupRouter(router, fn)) + if (!dht->LookupRouter(router, fn)) { - FinalizeRequest(router, nullptr, RCRequestResult::RouterNotFound); + finalize_request(router, nullptr, RCRequestResult::RouterNotFound); } else { - _routerLookupTimes[router] = std::chrono::steady_clock::now(); + router_lookup_times[router] = std::chrono::steady_clock::now(); } } } bool - RCLookupHandler::IsGreylisted(const RouterID& remote) const + RCLookupHandler::is_grey_listed(const RouterID& remote) const { - if (_strictConnectPubkeys.size() && _strictConnectPubkeys.count(remote) == 0 - && !RemoteInBootstrap(remote)) + if (strict_connect_pubkeys.size() && strict_connect_pubkeys.count(remote) == 0 + && !is_remote_in_bootstrap(remote)) { return false; } @@ -139,29 +138,29 @@ namespace llarp util::Lock lock{_mutex}; - return greylistRouters.count(remote); + return router_greylist.count(remote); } bool - RCLookupHandler::IsGreenlisted(const RouterID& remote) const + RCLookupHandler::is_green_listed(const RouterID& remote) const { util::Lock lock{_mutex}; - return greenlistRouters.count(remote); + return router_greenlist.count(remote); } bool - RCLookupHandler::IsRegistered(const RouterID& remote) const + RCLookupHandler::is_registered(const RouterID& remote) const { util::Lock lock{_mutex}; - return whitelistRouters.count(remote) || greylistRouters.count(remote) - || greenlistRouters.count(remote); + return router_whitelist.count(remote) || router_greylist.count(remote) + || router_greenlist.count(remote); } bool - RCLookupHandler::PathIsAllowed(const RouterID& remote) const + RCLookupHandler::is_path_allowed(const RouterID& remote) const { - if (_strictConnectPubkeys.size() && _strictConnectPubkeys.count(remote) == 0 - && !RemoteInBootstrap(remote)) + if (strict_connect_pubkeys.size() && strict_connect_pubkeys.count(remote) == 0 + && !is_remote_in_bootstrap(remote)) { return false; } @@ -171,14 +170,14 @@ namespace llarp util::Lock lock{_mutex}; - return whitelistRouters.count(remote); + return router_whitelist.count(remote); } bool - RCLookupHandler::SessionIsAllowed(const RouterID& remote) const + RCLookupHandler::is_session_allowed(const RouterID& remote) const { - if (_strictConnectPubkeys.size() && _strictConnectPubkeys.count(remote) == 0 - && !RemoteInBootstrap(remote)) + if (strict_connect_pubkeys.size() && strict_connect_pubkeys.count(remote) == 0 + && !is_remote_in_bootstrap(remote)) { return false; } @@ -188,19 +187,19 @@ namespace llarp util::Lock lock{_mutex}; - return whitelistRouters.count(remote) or greylistRouters.count(remote); + return router_whitelist.count(remote) or router_greylist.count(remote); } bool - RCLookupHandler::CheckRC(const RouterContact& rc) const + RCLookupHandler::check_rc(const RouterContact& rc) const { - if (not SessionIsAllowed(rc.pubkey)) + if (not is_session_allowed(rc.pubkey)) { - _dht->DelRCNodeAsync(dht::Key_t{rc.pubkey}); + dht->DelRCNodeAsync(dht::Key_t{rc.pubkey}); return false; } - if (not rc.Verify(_dht->Now())) + if (not rc.Verify(dht->Now())) { LogWarn("RC for ", RouterID(rc.pubkey), " is invalid"); return false; @@ -210,26 +209,26 @@ namespace llarp if (rc.IsPublicRouter()) { LogDebug("Adding or updating RC for ", RouterID(rc.pubkey), " to nodedb and dht."); - _loop->call([rc, n = _nodedb] { n->PutIfNewer(rc); }); - _dht->PutRCNodeAsync(rc); + loop->call([rc, n = node_db] { n->PutIfNewer(rc); }); + dht->PutRCNodeAsync(rc); } return true; } size_t - RCLookupHandler::NumberOfStrictConnectRouters() const + RCLookupHandler::num_strict_connect_routers() const { - return _strictConnectPubkeys.size(); + return strict_connect_pubkeys.size(); } bool - RCLookupHandler::GetRandomWhitelistRouter(RouterID& router) const + RCLookupHandler::get_random_whitelist_router(RouterID& router) const { util::Lock l(_mutex); - const auto sz = whitelistRouters.size(); - auto itr = whitelistRouters.begin(); + const auto sz = router_whitelist.size(); + auto itr = router_whitelist.begin(); if (sz == 0) return false; if (sz > 1) @@ -239,22 +238,22 @@ namespace llarp } bool - RCLookupHandler::CheckRenegotiateValid(RouterContact newrc, RouterContact oldrc) + RCLookupHandler::check_renegotiate_valid(RouterContact newrc, RouterContact oldrc) { // mismatch of identity ? if (newrc.pubkey != oldrc.pubkey) return false; - if (!SessionIsAllowed(newrc.pubkey)) + if (!is_session_allowed(newrc.pubkey)) return false; - auto func = [this, newrc] { CheckRC(newrc); }; - _work(func); + auto func = [this, newrc] { check_rc(newrc); }; + work_func(func); // update dht if required - if (_dht->Nodes()->HasNode(dht::Key_t{newrc.pubkey})) + if (dht->Nodes()->HasNode(dht::Key_t{newrc.pubkey})) { - _dht->Nodes()->PutNode(newrc); + dht->Nodes()->PutNode(newrc); } // TODO: check for other places that need updating the RC @@ -262,14 +261,14 @@ namespace llarp } void - RCLookupHandler::PeriodicUpdate(llarp_time_t now) + RCLookupHandler::periodic_update(llarp_time_t now) { // try looking up stale routers std::unordered_set routersToLookUp; - _nodedb->VisitInsertedBefore( + node_db->VisitInsertedBefore( [&](const RouterContact& rc) { - if (HavePendingLookup(rc.pubkey)) + if (has_pending_lookup(rc.pubkey)) return; routersToLookUp.insert(rc.pubkey); }, @@ -277,26 +276,26 @@ namespace llarp for (const auto& router : routersToLookUp) { - GetRC(router, nullptr, true); + get_rc(router, nullptr, true); } - _nodedb->RemoveStaleRCs(_bootstrapRouterIDList, now - RouterContact::StaleInsertionAge); + node_db->RemoveStaleRCs(boostrap_rid_list, now - RouterContact::StaleInsertionAge); } void - RCLookupHandler::ExploreNetwork() + RCLookupHandler::explore_network() { - const size_t known = _nodedb->NumLoaded(); - if (_bootstrapRCList.empty() && known == 0) + const size_t known = node_db->NumLoaded(); + if (bootstrap_rc_list.empty() && known == 0) { LogError("we have no bootstrap nodes specified"); } - else if (known <= _bootstrapRCList.size()) + else if (known <= bootstrap_rc_list.size()) { - for (const auto& rc : _bootstrapRCList) + for (const auto& rc : bootstrap_rc_list) { LogInfo("Doing explore via bootstrap node: ", RouterID(rc.pubkey)); - _dht->ExploreNetworkVia(dht::Key_t{rc.pubkey}); + dht->ExploreNetworkVia(dht::Key_t{rc.pubkey}); } } @@ -313,9 +312,9 @@ namespace llarp { // if we are using a whitelist look up a few routers we don't have util::Lock l(_mutex); - for (const auto& r : whitelistRouters) + for (const auto& r : router_whitelist) { - if (now > _routerLookupTimes[r] + RerequestInterval and not _nodedb->Has(r)) + if (now > router_lookup_times[r] + RerequestInterval and not node_db->Has(r)) { lookupRouters.emplace_back(r); } @@ -329,11 +328,11 @@ namespace llarp } for (const auto& r : lookupRouters) - GetRC(r, nullptr, true); + get_rc(r, nullptr, true); return; } // service nodes gossip, not explore - if (_dht->GetRouter()->IsServiceNode()) + if (dht->GetRouter()->IsServiceNode()) return; // explore via every connected peer @@ -356,11 +355,11 @@ namespace llarp } void - RCLookupHandler::Init( - std::shared_ptr dht, + RCLookupHandler::init( + std::shared_ptr d, std::shared_ptr nodedb, - EventLoop_ptr loop, - WorkerFunc_t dowork, + EventLoop_ptr l, + worker_func dowork, LinkManager* linkManager, service::Context* hiddenServiceContext, const std::unordered_set& strictConnectPubkeys, @@ -368,58 +367,59 @@ namespace llarp bool useWhitelist_arg, bool isServiceNode_arg) { - _dht = dht; - _nodedb = std::move(nodedb); - _loop = std::move(loop); - _work = std::move(dowork); - _hiddenServiceContext = hiddenServiceContext; - _strictConnectPubkeys = strictConnectPubkeys; - _bootstrapRCList = bootstrapRCList; - _linkManager = linkManager; + dht = d; + node_db = std::move(nodedb); + loop = std::move(l); + work_func = std::move(dowork); + hidden_service_context = hiddenServiceContext; + strict_connect_pubkeys = strictConnectPubkeys; + bootstrap_rc_list = bootstrapRCList; + link_manager = linkManager; useWhitelist = useWhitelist_arg; isServiceNode = isServiceNode_arg; - for (const auto& rc : _bootstrapRCList) + for (const auto& rc : bootstrap_rc_list) { - _bootstrapRouterIDList.insert(rc.pubkey); + boostrap_rid_list.insert(rc.pubkey); } } void - RCLookupHandler::HandleDHTLookupResult(RouterID remote, const std::vector& results) + RCLookupHandler::handle_dht_lookup_result( + RouterID remote, const std::vector& results) { if (not results.size()) { - FinalizeRequest(remote, nullptr, RCRequestResult::RouterNotFound); + finalize_request(remote, nullptr, RCRequestResult::RouterNotFound); return; } - if (not SessionIsAllowed(remote)) + if (not is_session_allowed(remote)) { - FinalizeRequest(remote, &results[0], RCRequestResult::InvalidRouter); + finalize_request(remote, &results[0], RCRequestResult::InvalidRouter); return; } - if (not CheckRC(results[0])) + if (not check_rc(results[0])) { - FinalizeRequest(remote, &results[0], RCRequestResult::BadRC); + finalize_request(remote, &results[0], RCRequestResult::BadRC); return; } - FinalizeRequest(remote, &results[0], RCRequestResult::Success); + finalize_request(remote, &results[0], RCRequestResult::Success); } bool - RCLookupHandler::HavePendingLookup(RouterID remote) const + RCLookupHandler::has_pending_lookup(RouterID remote) const { util::Lock l(_mutex); - return pendingCallbacks.find(remote) != pendingCallbacks.end(); + return pending_callbacks.find(remote) != pending_callbacks.end(); } bool - RCLookupHandler::RemoteInBootstrap(const RouterID& remote) const + RCLookupHandler::is_remote_in_bootstrap(const RouterID& remote) const { - for (const auto& rc : _bootstrapRCList) + for (const auto& rc : bootstrap_rc_list) { if (rc.pubkey == remote) { @@ -430,19 +430,19 @@ namespace llarp } void - RCLookupHandler::FinalizeRequest( + RCLookupHandler::finalize_request( const RouterID& router, const RouterContact* const rc, RCRequestResult result) { - CallbacksQueue movedCallbacks; + callback_que movedCallbacks; { util::Lock l(_mutex); - auto itr = pendingCallbacks.find(router); + auto itr = pending_callbacks.find(router); - if (itr != pendingCallbacks.end()) + if (itr != pending_callbacks.end()) { movedCallbacks.splice(movedCallbacks.begin(), itr->second); - pendingCallbacks.erase(itr); + pending_callbacks.erase(itr); } } // lock diff --git a/llarp/router/rc_lookup_handler.hpp b/llarp/router/rc_lookup_handler.hpp index 45bb0291c1..7220d4f154 100644 --- a/llarp/router/rc_lookup_handler.hpp +++ b/llarp/router/rc_lookup_handler.hpp @@ -44,20 +44,19 @@ namespace llarp struct RCLookupHandler { public: - using Work_t = std::function; - using WorkerFunc_t = std::function; - using CallbacksQueue = std::list; + using worker_func = std::function)>; + using callback_que = std::list; ~RCLookupHandler() = default; void - AddValidRouter(const RouterID& router) EXCLUDES(_mutex); + add_valid_router(const RouterID& router) EXCLUDES(_mutex); void - RemoveValidRouter(const RouterID& router) EXCLUDES(_mutex); + remove_valid_router(const RouterID& router) EXCLUDES(_mutex); void - SetRouterWhitelist( + set_router_whitelist( const std::vector& whitelist, const std::vector& greylist, const std::vector& greenlist @@ -65,55 +64,55 @@ namespace llarp ) EXCLUDES(_mutex); bool - HaveReceivedWhitelist() const; + has_received_whitelist() const; void - GetRC(const RouterID& router, RCRequestCallback callback, bool forceLookup = false) + get_rc(const RouterID& router, RCRequestCallback callback, bool forceLookup = false) EXCLUDES(_mutex); bool - PathIsAllowed(const RouterID& remote) const EXCLUDES(_mutex); + is_path_allowed(const RouterID& remote) const EXCLUDES(_mutex); bool - SessionIsAllowed(const RouterID& remote) const EXCLUDES(_mutex); + is_session_allowed(const RouterID& remote) const EXCLUDES(_mutex); bool - IsGreylisted(const RouterID& remote) const EXCLUDES(_mutex); + is_grey_listed(const RouterID& remote) const EXCLUDES(_mutex); // "greenlist" = new routers (i.e. "green") that aren't fully funded yet bool - IsGreenlisted(const RouterID& remote) const EXCLUDES(_mutex); + is_green_listed(const RouterID& remote) const EXCLUDES(_mutex); // registered just means that there is at least an operator stake, but doesn't require the node // be fully funded, active, or not decommed. (In other words: it is any of the white, grey, or // green list). bool - IsRegistered(const RouterID& remote) const EXCLUDES(_mutex); + is_registered(const RouterID& remote) const EXCLUDES(_mutex); bool - CheckRC(const RouterContact& rc) const; + check_rc(const RouterContact& rc) const; bool - GetRandomWhitelistRouter(RouterID& router) const EXCLUDES(_mutex); + get_random_whitelist_router(RouterID& router) const EXCLUDES(_mutex); bool - CheckRenegotiateValid(RouterContact newrc, RouterContact oldrc); + check_renegotiate_valid(RouterContact newrc, RouterContact oldrc); void - PeriodicUpdate(llarp_time_t now); + periodic_update(llarp_time_t now); void - ExploreNetwork(); + explore_network(); size_t - NumberOfStrictConnectRouters() const; + num_strict_connect_routers() const; void - Init( + init( std::shared_ptr dht, std::shared_ptr nodedb, std::shared_ptr loop, - WorkerFunc_t dowork, + worker_func dowork, LinkManager* linkManager, service::Context* hiddenServiceContext, const std::unordered_set& strictConnectPubkeys, @@ -122,56 +121,56 @@ namespace llarp bool isServiceNode_arg); std::unordered_set - Whitelist() const + whitelist() const { util::Lock lock{_mutex}; - return whitelistRouters; + return router_whitelist; } private: void - HandleDHTLookupResult(RouterID remote, const std::vector& results); + handle_dht_lookup_result(RouterID remote, const std::vector& results); bool - HavePendingLookup(RouterID remote) const EXCLUDES(_mutex); + has_pending_lookup(RouterID remote) const EXCLUDES(_mutex); bool - RemoteInBootstrap(const RouterID& remote) const; + is_remote_in_bootstrap(const RouterID& remote) const; void - FinalizeRequest(const RouterID& router, const RouterContact* const rc, RCRequestResult result) + finalize_request(const RouterID& router, const RouterContact* const rc, RCRequestResult result) EXCLUDES(_mutex); mutable util::Mutex _mutex; // protects pendingCallbacks, whitelistRouters - std::shared_ptr _dht = nullptr; - std::shared_ptr _nodedb; - std::shared_ptr _loop; - WorkerFunc_t _work = nullptr; - service::Context* _hiddenServiceContext = nullptr; - LinkManager* _linkManager = nullptr; + std::shared_ptr dht = nullptr; + std::shared_ptr node_db; + std::shared_ptr loop; + worker_func work_func = nullptr; + service::Context* hidden_service_context = nullptr; + LinkManager* link_manager = nullptr; /// explicit whitelist of routers we will connect to directly (not for /// service nodes) - std::unordered_set _strictConnectPubkeys; + std::unordered_set strict_connect_pubkeys; - std::set _bootstrapRCList; - std::unordered_set _bootstrapRouterIDList; + std::set bootstrap_rc_list; + std::unordered_set boostrap_rid_list; - std::unordered_map pendingCallbacks GUARDED_BY(_mutex); + std::unordered_map pending_callbacks GUARDED_BY(_mutex); bool useWhitelist = false; bool isServiceNode = false; // whitelist = active routers - std::unordered_set whitelistRouters GUARDED_BY(_mutex); + std::unordered_set router_whitelist GUARDED_BY(_mutex); // greylist = fully funded, but decommissioned routers - std::unordered_set greylistRouters GUARDED_BY(_mutex); + std::unordered_set router_greylist GUARDED_BY(_mutex); // greenlist = registered but not fully-staked routers - std::unordered_set greenlistRouters GUARDED_BY(_mutex); + std::unordered_set router_greenlist GUARDED_BY(_mutex); using TimePoint = std::chrono::steady_clock::time_point; - std::unordered_map _routerLookupTimes; + std::unordered_map router_lookup_times; }; } // namespace llarp diff --git a/llarp/router/route_poker.cpp b/llarp/router/route_poker.cpp index 1471ac911c..cd9434bdd7 100644 --- a/llarp/router/route_poker.cpp +++ b/llarp/router/route_poker.cpp @@ -1,5 +1,5 @@ #include "route_poker.hpp" -#include +#include "router.hpp" #include #include #include @@ -36,7 +36,7 @@ namespace llarp { if (ip.n and gateway.n and IsEnabled()) { - vpn::IRouteManager& route = m_Router->GetVPNPlatform()->RouteManager(); + vpn::IRouteManager& route = m_Router->vpn_platform()->RouteManager(); route.DelRoute(ip, gateway); } } @@ -46,7 +46,7 @@ namespace llarp { if (ip.n and gateway.n and IsEnabled()) { - vpn::IRouteManager& route = m_Router->GetVPNPlatform()->RouteManager(); + vpn::IRouteManager& route = m_Router->vpn_platform()->RouteManager(); route.AddRoute(ip, gateway); } } @@ -63,7 +63,7 @@ namespace llarp } void - RoutePoker::Start(AbstractRouter* router) + RoutePoker::Start(Router* router) { m_Router = router; if (not IsEnabled()) @@ -101,10 +101,10 @@ namespace llarp RoutePoker::~RoutePoker() { - if (not m_Router or not m_Router->GetVPNPlatform()) + if (not m_Router or not m_Router->vpn_platform()) return; - auto& route = m_Router->GetVPNPlatform()->RouteManager(); + auto& route = m_Router->vpn_platform()->RouteManager(); for (const auto& [ip, gateway] : m_PokedRoutes) { if (gateway.n and ip.n) @@ -120,7 +120,7 @@ namespace llarp throw std::runtime_error{"Attempting to use RoutePoker before calling Init"}; if (m_Router->IsServiceNode()) return false; - if (const auto& conf = m_Router->GetConfig()) + if (const auto& conf = m_Router->config()) return conf->network.m_EnableRoutePoker; throw std::runtime_error{"Attempting to use RoutePoker with router with no config set"}; @@ -137,7 +137,7 @@ namespace llarp if (ep == nullptr) return; // ensure we have a vpn platform - auto* platform = m_Router->GetVPNPlatform(); + auto* platform = m_Router->vpn_platform(); if (platform == nullptr) return; // ensure we have a vpn interface @@ -214,10 +214,10 @@ namespace llarp { log::info(logcat, "RoutePoker coming up; poking routes"); - vpn::IRouteManager& route = m_Router->GetVPNPlatform()->RouteManager(); + vpn::IRouteManager& route = m_Router->vpn_platform()->RouteManager(); // black hole all routes if enabled - if (m_Router->GetConfig()->network.m_BlackholeRoutes) + if (m_Router->config()->network.m_BlackholeRoutes) route.AddBlackhole(); // explicit route pokes for first hops @@ -246,7 +246,7 @@ namespace llarp if (IsEnabled() and m_up) { - vpn::IRouteManager& route = m_Router->GetVPNPlatform()->RouteManager(); + vpn::IRouteManager& route = m_Router->vpn_platform()->RouteManager(); const auto ep = m_Router->hiddenServiceContext().GetDefault(); if (auto* vpn = ep->GetVPNInterface()) route.DelDefaultRouteViaInterface(*vpn); diff --git a/llarp/router/route_poker.hpp b/llarp/router/route_poker.hpp index 9a0feb65c9..a5399cecc7 100644 --- a/llarp/router/route_poker.hpp +++ b/llarp/router/route_poker.hpp @@ -8,7 +8,7 @@ namespace llarp { - struct AbstractRouter; + struct Router; struct RoutePoker : public std::enable_shared_from_this { @@ -19,7 +19,7 @@ namespace llarp DelRoute(net::ipv4addr_t ip); void - Start(AbstractRouter* router); + Start(Router* router); ~RoutePoker(); @@ -62,7 +62,7 @@ namespace llarp std::optional m_CurrentGateway; - AbstractRouter* m_Router = nullptr; + Router* m_Router = nullptr; bool m_up{false}; }; } // namespace llarp diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 9303f8b7da..8b7eee69b6 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -9,8 +9,6 @@ #include #include #include -#include -#include #include #include #include @@ -48,14 +46,13 @@ namespace llarp static auto logcat = log::Cat("router"); Router::Router(EventLoop_ptr loop, std::shared_ptr vpnPlatform) - : ready{false} - , m_lmq{std::make_shared()} + : _lmq{std::make_shared()} , _loop{std::move(loop)} - , _vpnPlatform{std::move(vpnPlatform)} + , _vpn{std::move(vpnPlatform)} , paths{this} , _exitContext{this} , _dht{dht::make_handler()} - , m_DiskThread{m_lmq->add_tagged_thread("disk")} + , _disk_thread{_lmq->add_tagged_thread("disk")} , inbound_link_msg_parser{this} , _hiddenServiceContext{this} , m_RoutePoker{std::make_shared()} @@ -64,14 +61,14 @@ namespace llarp platform::is_simulation ? std::chrono::milliseconds{(llarp::randint() % 1250) + 2000} : 0s} { - m_keyManager = std::make_shared(); + _key_manager = std::make_shared(); // for lokid, so we don't close the connection when syncing the whitelist - m_lmq->MAX_MSG_SIZE = -1; - _stopping.store(false); - _running.store(false); + _lmq->MAX_MSG_SIZE = -1; + is_stopping.store(false); + is_running.store(false); _lastTick = llarp::time_now_ms(); - m_NextExploreAt = Clock_t::now(); - m_Pump = _loop->make_waker([this]() { PumpLL(); }); + m_NextExploreAt = std::chrono::steady_clock::now(); + loop_wakeup = _loop->make_waker([this]() { PumpLL(); }); } Router::~Router() @@ -85,7 +82,7 @@ namespace llarp Router::PumpLL() { llarp::LogTrace("Router::PumpLL() start"); - if (_stopping.load()) + if (is_stopping.load()) return; paths.PumpDownstream(); paths.PumpUpstream(); @@ -97,16 +94,16 @@ namespace llarp util::StatusObject Router::ExtractStatus() const { - if (not _running) + if (not is_running) util::StatusObject{{"running", false}}; return util::StatusObject{ {"running", true}, - {"numNodesKnown", _nodedb->NumLoaded()}, + {"numNodesKnown", _node_db->NumLoaded()}, {"dht", _dht->ExtractStatus()}, {"services", _hiddenServiceContext.ExtractStatus()}, {"exit", _exitContext.ExtractStatus()}, - {"links", _linkManager.ExtractStatus()}, + {"links", _link_manager.extract_status()}, {"outboundMessages", _outboundMessageHandler.ExtractStatus()}}; } @@ -114,12 +111,12 @@ namespace llarp util::StatusObject Router::ExtractSummaryStatus() const { - if (!_running) + if (!is_running) return util::StatusObject{{"running", false}}; auto services = _hiddenServiceContext.ExtractStatus(); - auto link_types = _linkManager.ExtractStatus(); + auto link_types = _link_manager.extract_status(); uint64_t tx_rate = 0; uint64_t rx_rate = 0; @@ -192,7 +189,7 @@ namespace llarp {"uptime", to_json(Uptime())}, {"numPathsBuilt", pathsCount}, {"numPeersConnected", peers}, - {"numRoutersKnown", _nodedb->NumLoaded()}, + {"numRoutersKnown", _node_db->NumLoaded()}, {"ratio", ratio}, {"txRate", tx_rate}, {"rxRate", rx_rate}, @@ -212,7 +209,7 @@ namespace llarp bool Router::HandleRecvLinkMessageBuffer(AbstractLinkSession* session, const llarp_buffer_t& buf) { - if (_stopping) + if (is_stopping) return true; if (!session) @@ -273,7 +270,7 @@ namespace llarp void Router::PersistSessionUntil(const RouterID& remote, llarp_time_t until) { - _linkManager.set_conn_persist(remote, until); + _link_manager.set_conn_persist(remote, until); } void @@ -294,12 +291,12 @@ namespace llarp bool Router::GetRandomGoodRouter(RouterID& router) { - if (whitelistRouters) + if (follow_whitelist) { - return _rcLookupHandler.GetRandomWhitelistRouter(router); + return _rc_lookup_handler.get_random_whitelist_router(router); } - if (const auto maybe = nodedb()->GetRandom([](const auto&) -> bool { return true; })) + if (const auto maybe = node_db()->GetRandom([](const auto&) -> bool { return true; })) { router = maybe->pubkey; return true; @@ -310,7 +307,7 @@ namespace llarp void Router::TriggerPump() { - m_Pump->Trigger(); + loop_wakeup->Trigger(); } bool @@ -346,7 +343,7 @@ namespace llarp if (remote.Verify(Now())) { LogDebug("verified signature"); - _linkManager.Connect(remote); + _link_manager.connect_to(remote); } else LogError(rcfile, " contains invalid RC"); @@ -355,9 +352,9 @@ namespace llarp bool Router::EnsureIdentity() { - _encryption = m_keyManager->encryptionKey; + _encryption = _key_manager->encryptionKey; - if (whitelistRouters) + if (follow_whitelist) { #if defined(ANDROID) || defined(IOS) LogError("running a service node on mobile device is not possible."); @@ -375,10 +372,10 @@ namespace llarp numTries++; try { - _identity = RpcClient()->ObtainIdentityKey(); + _identity = rpc_client()->ObtainIdentityKey(); const RouterID pk{pubkey()}; LogWarn("Obtained lokid identity key: ", pk); - RpcClient()->StartPings(); + rpc_client()->StartPings(); break; } catch (const std::exception& e) @@ -398,7 +395,7 @@ namespace llarp } else { - _identity = m_keyManager->identityKey; + _identity = _key_manager->identityKey; } if (_identity.IsZero()) @@ -414,8 +411,8 @@ namespace llarp { llarp::sys::service_manager->starting(); - m_Config = std::move(c); - auto& conf = *m_Config; + config = std::move(c); + auto& conf = *config; // Do logging config as early as possible to get the configured log level applied @@ -432,18 +429,18 @@ namespace llarp log::add_sink(log_type, log_type == log::Type::System ? "lokinet" : conf.logging.m_logFile); // re-add rpc log sink if rpc enabled, else free it - if (m_Config->api.m_enableRPCServer and llarp::logRingBuffer) + if (config->api.m_enableRPCServer and llarp::logRingBuffer) log::add_sink(llarp::logRingBuffer, llarp::log::DEFAULT_PATTERN_MONO); else llarp::logRingBuffer = nullptr; log::debug(logcat, "Configuring router"); - whitelistRouters = conf.lokid.whitelistRouters; - if (whitelistRouters) + follow_whitelist = conf.lokid.whitelistRouters; + if (follow_whitelist) { lokidRPCAddr = oxenmq::address(conf.lokid.lokidRPCAddr); - m_lokidRpcClient = std::make_shared(m_lmq, weak_from_this()); + _rpc_client = std::make_shared(_lmq, weak_from_this()); } log::debug(logcat, "Starting RPC server"); @@ -451,28 +448,28 @@ namespace llarp throw std::runtime_error("Failed to start rpc server"); if (conf.router.m_workerThreads > 0) - m_lmq->set_general_threads(conf.router.m_workerThreads); + _lmq->set_general_threads(conf.router.m_workerThreads); log::debug(logcat, "Starting OMQ server"); - m_lmq->start(); + _lmq->start(); - _nodedb = std::move(nodedb); + _node_db = std::move(nodedb); - m_isServiceNode = conf.router.m_isRelay; + is_service_node = conf.router.m_isRelay; log::debug( - logcat, m_isServiceNode ? "Running as a relay (service node)" : "Running as a client"); + logcat, is_service_node ? "Running as a relay (service node)" : "Running as a client"); - if (whitelistRouters) + if (follow_whitelist) { - m_lokidRpcClient->ConnectAsync(lokidRPCAddr); + _rpc_client->ConnectAsync(lokidRPCAddr); } log::debug(logcat, "Initializing key manager"); - if (not m_keyManager->initialize(conf, true, isSNode)) + if (not _key_manager->initialize(conf, true, isSNode)) throw std::runtime_error("KeyManager failed to initialize"); log::debug(logcat, "Initializing from configuration"); - if (!FromConfig(conf)) + if (!from_config(conf)) throw std::runtime_error("FromConfig() failed"); log::debug(logcat, "Initializing identity"); @@ -486,36 +483,36 @@ namespace llarp Router::HandleSaveRC() const { std::string fname = our_rc_file.string(); - _rc.Write(fname.c_str()); + router_contact.Write(fname.c_str()); } bool Router::SaveRC() { LogDebug("verify RC signature"); - if (!_rc.Verify(Now())) + if (!router_contact.Verify(Now())) { Dump(rc()); LogError("RC is invalid, not saving"); return false; } - if (m_isServiceNode) - _nodedb->Put(_rc); - QueueDiskIO([&]() { HandleSaveRC(); }); + if (is_service_node) + _node_db->Put(router_contact); + queue_disk_io([&]() { HandleSaveRC(); }); return true; } bool Router::IsServiceNode() const { - return m_isServiceNode; + return is_service_node; } bool - Router::TooFewPeers() const + Router::insufficient_peers() const { constexpr int KnownPeerWarningThreshold = 5; - return nodedb()->NumLoaded() < KnownPeerWarningThreshold; + return node_db()->NumLoaded() < KnownPeerWarningThreshold; } std::optional @@ -523,7 +520,7 @@ namespace llarp { // If we're in the white or gray list then we *should* be establishing connections to other // routers, so if we have almost no peers then something is almost certainly wrong. - if (LooksFunded() and TooFewPeers()) + if (appear_funder() and insufficient_peers()) return "too few peer connections; lokinet is not adequately connected to the network"; return std::nullopt; } @@ -536,7 +533,7 @@ namespace llarp _onDown(); log::debug(logcat, "stopping mainloop"); _loop->stop(); - _running.store(false); + is_running.store(false); } bool @@ -547,72 +544,72 @@ namespace llarp } bool - Router::LooksDecommissioned() const + Router::appear_decommed() const { - return IsServiceNode() and whitelistRouters and _rcLookupHandler.HaveReceivedWhitelist() - and _rcLookupHandler.IsGreylisted(pubkey()); + return IsServiceNode() and follow_whitelist and _rc_lookup_handler.has_received_whitelist() + and _rc_lookup_handler.is_grey_listed(pubkey()); } bool - Router::LooksFunded() const + Router::appear_funder() const { - return IsServiceNode() and whitelistRouters and _rcLookupHandler.HaveReceivedWhitelist() - and _rcLookupHandler.SessionIsAllowed(pubkey()); + return IsServiceNode() and follow_whitelist and _rc_lookup_handler.has_received_whitelist() + and _rc_lookup_handler.is_session_allowed(pubkey()); } bool - Router::LooksRegistered() const + Router::appear_registered() const { - return IsServiceNode() and whitelistRouters and _rcLookupHandler.HaveReceivedWhitelist() - and _rcLookupHandler.IsRegistered(pubkey()); + return IsServiceNode() and follow_whitelist and _rc_lookup_handler.has_received_whitelist() + and _rc_lookup_handler.is_registered(pubkey()); } bool - Router::ShouldTestOtherRouters() const + Router::can_test_routers() const { if (not IsServiceNode()) return false; - if (not whitelistRouters) + if (not follow_whitelist) return true; - if (not _rcLookupHandler.HaveReceivedWhitelist()) + if (not _rc_lookup_handler.has_received_whitelist()) return false; - return _rcLookupHandler.SessionIsAllowed(pubkey()); + return _rc_lookup_handler.is_session_allowed(pubkey()); } bool Router::SessionToRouterAllowed(const RouterID& router) const { - return _rcLookupHandler.SessionIsAllowed(router); + return _rc_lookup_handler.is_session_allowed(router); } bool Router::PathToRouterAllowed(const RouterID& router) const { - if (LooksDecommissioned()) + if (appear_decommed()) { // we are decom'd don't allow any paths outbound at all return false; } - return _rcLookupHandler.PathIsAllowed(router); + return _rc_lookup_handler.is_path_allowed(router); } size_t Router::NumberOfConnectedRouters() const { - return _linkManager.get_num_connected(); + return _link_manager.get_num_connected(); } size_t Router::NumberOfConnectedClients() const { - return _linkManager.get_num_connected_clients(); + return _link_manager.get_num_connected_clients(); } bool - Router::UpdateOurRC(bool rotateKeys) + Router::update_rc(bool rotateKeys) { SecretKey nextOnionKey; - RouterContact nextRC = _rc; + RouterContact nextRC = router_contact; if (rotateKeys) { CryptoManager::instance()->encryption_keygen(nextOnionKey); @@ -628,7 +625,7 @@ namespace llarp return false; if (!nextRC.Verify(time_now_ms(), false)) return false; - _rc = std::move(nextRC); + router_contact = std::move(nextRC); if (rotateKeys) { // TODO: libquic change @@ -648,7 +645,7 @@ namespace llarp } bool - Router::FromConfig(const Config& conf) + Router::from_config(const Config& conf) { // Set netid before anything else log::debug(logcat, "Network ID set to {}", conf.router.m_netId); @@ -666,18 +663,18 @@ namespace llarp "shape correlation !!!!"); NetID::DefaultValue() = NetID(reinterpret_cast(netid.c_str())); // reset netid in our rc - _rc.netID = llarp::NetID(); + router_contact.netID = llarp::NetID(); } // Router config - _rc.SetNick(conf.router.m_nickname); - _linkManager.max_connected_routers = conf.router.m_maxConnectedRouters; - _linkManager.min_connected_routers = conf.router.m_minConnectedRouters; + router_contact.SetNick(conf.router.m_nickname); + _link_manager.max_connected_routers = conf.router.m_maxConnectedRouters; + _link_manager.min_connected_routers = conf.router.m_minConnectedRouters; - encryption_keyfile = m_keyManager->m_encKeyPath; - our_rc_file = m_keyManager->m_rcPath; - transport_keyfile = m_keyManager->m_transportKeyPath; - ident_keyfile = m_keyManager->m_idKeyPath; + 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; if (auto maybe_ip = conf.links.PublicAddress) _ourAddress = var::visit([](auto&& ip) { return SockAddr{ip}; }, *maybe_ip); @@ -767,7 +764,7 @@ namespace llarp if (bootstrapRCList.empty() and not conf.bootstrap.seednode) { auto fallbacks = llarp::load_bootstrap_fallbacks(); - if (auto itr = fallbacks.find(_rc.netID.ToString()); itr != fallbacks.end()) + if (auto itr = fallbacks.find(router_contact.netID.ToString()); itr != fallbacks.end()) { bootstrapRCList = itr->second; log::debug(logcat, "loaded {} default fallback bootstrap routers", bootstrapRCList.size()); @@ -792,21 +789,21 @@ namespace llarp // Init components after relevant config settings loaded _outboundMessageHandler.Init(this); - _linkManager.init(&_rcLookupHandler); - _rcLookupHandler.Init( + _link_manager.init(&_rc_lookup_handler); + _rc_lookup_handler.init( _dht, - _nodedb, + _node_db, _loop, - util::memFn(&AbstractRouter::QueueWork, this), - &_linkManager, + util::memFn(&Router::queue_work, this), + &_link_manager, &_hiddenServiceContext, strictConnectPubkeys, bootstrapRCList, - whitelistRouters, - m_isServiceNode); + follow_whitelist, + is_service_node); // FIXME: kludge for now, will be part of larger cleanup effort. - if (m_isServiceNode) + if (is_service_node) InitInboundLinks(); else InitOutboundLinks(); @@ -825,12 +822,12 @@ namespace llarp else { LogInfo("loading router profiles from ", _profilesFile); - routerProfiling().Load(_profilesFile); + router_profiling().Load(_profilesFile); } } else { - routerProfiling().Disable(); + router_profiling().Disable(); LogInfo("router profiling disabled"); } @@ -846,7 +843,7 @@ namespace llarp bool Router::CheckRenegotiateValid(RouterContact newrc, RouterContact oldrc) { - return _rcLookupHandler.CheckRenegotiateValid(newrc, oldrc); + return _rc_lookup_handler.check_renegotiate_valid(newrc, oldrc); } bool @@ -860,28 +857,28 @@ namespace llarp } bool - Router::ShouldReportStats(llarp_time_t now) const + Router::should_report_stats(llarp_time_t now) const { static constexpr auto ReportStatsInterval = 1h; - return now - m_LastStatsReport > ReportStatsInterval; + return now - _last_stats_report > ReportStatsInterval; } void - Router::ReportStats() + Router::report_stats() { const auto now = Now(); - LogInfo(nodedb()->NumLoaded(), " RCs loaded"); + LogInfo(node_db()->NumLoaded(), " RCs loaded"); LogInfo(bootstrapRCList.size(), " bootstrap peers"); LogInfo(NumberOfConnectedRouters(), " router connections"); if (IsServiceNode()) { LogInfo(NumberOfConnectedClients(), " client connections"); - LogInfo(ToString(_rc.Age(now)), " since we last updated our RC"); - LogInfo(ToString(_rc.TimeUntilExpires(now)), " until our RC expires"); + LogInfo(ToString(router_contact.Age(now)), " since we last updated our RC"); + LogInfo(ToString(router_contact.TimeUntilExpires(now)), " until our RC expires"); } - if (m_LastStatsReport > 0s) - LogInfo(ToString(now - m_LastStatsReport), " last reported stats"); - m_LastStatsReport = now; + if (_last_stats_report > 0s) + LogInfo(ToString(now - _last_stats_report), " last reported stats"); + _last_stats_report = now; } std::string @@ -895,14 +892,14 @@ namespace llarp fmt::format_to( out, " snode | known/svc/clients: {}/{}/{}", - nodedb()->NumLoaded(), + node_db()->NumLoaded(), NumberOfConnectedRouters(), NumberOfConnectedClients()); fmt::format_to( out, " | {} active paths | block {} ", - pathContext().CurrentTransitPaths(), - (m_lokidRpcClient ? m_lokidRpcClient->BlockHeight() : 0)); + path_context().CurrentTransitPaths(), + (_rpc_client ? _rpc_client->BlockHeight() : 0)); auto maybe_last = _rcGossiper.LastGossipAt(); fmt::format_to( out, @@ -915,7 +912,7 @@ namespace llarp fmt::format_to( out, " client | known/connected: {}/{}", - nodedb()->NumLoaded(), + node_db()->NumLoaded(), NumberOfConnectedRouters()); if (auto ep = hiddenServiceContext().GetDefault()) @@ -923,7 +920,7 @@ namespace llarp fmt::format_to( out, " | paths/endpoints {}/{}", - pathContext().CurrentOwnedPaths(), + path_context().CurrentOwnedPaths(), ep->UniqueEndpoints()); if (auto success_rate = ep->CurrentBuildStats().SuccessRatio(); success_rate < 0.5) @@ -939,7 +936,7 @@ namespace llarp void Router::Tick() { - if (_stopping) + if (is_stopping) return; // LogDebug("tick router"); const auto now = Now(); @@ -952,30 +949,30 @@ namespace llarp llarp::sys::service_manager->report_periodic_stats(); - m_PathBuildLimiter.Decay(now); + _pathbuild_limiter.Decay(now); - routerProfiling().Tick(); + router_profiling().Tick(); - if (ShouldReportStats(now)) + if (should_report_stats(now)) { - ReportStats(); + report_stats(); } _rcGossiper.Decay(now); - _rcLookupHandler.PeriodicUpdate(now); + _rc_lookup_handler.periodic_update(now); - const bool gotWhitelist = _rcLookupHandler.HaveReceivedWhitelist(); + const bool gotWhitelist = _rc_lookup_handler.has_received_whitelist(); const bool isSvcNode = IsServiceNode(); - const bool decom = LooksDecommissioned(); - bool shouldGossip = isSvcNode and whitelistRouters and gotWhitelist - and _rcLookupHandler.SessionIsAllowed(pubkey()); + const bool decom = appear_decommed(); + bool shouldGossip = isSvcNode and follow_whitelist and gotWhitelist + and _rc_lookup_handler.is_session_allowed(pubkey()); if (isSvcNode - and (_rc.ExpiresSoon(now, std::chrono::milliseconds(randint() % 10000)) or (now - _rc.last_updated) > rcRegenInterval)) + and (router_contact.ExpiresSoon(now, std::chrono::milliseconds(randint() % 10000)) or (now - router_contact.last_updated) > rcRegenInterval)) { LogInfo("regenerating RC"); - if (UpdateOurRC()) + if (update_rc()) { // our rc changed so we should gossip it shouldGossip = true; @@ -989,10 +986,10 @@ namespace llarp { // if we have the whitelist enabled, we have fetched the list and we are in either // the white or grey list, we want to gossip our RC - GossipRCIfNeeded(_rc); + GossipRCIfNeeded(router_contact); } // remove RCs for nodes that are no longer allowed by network policy - nodedb()->RemoveIf([&](const RouterContact& rc) -> bool { + node_db()->RemoveIf([&](const RouterContact& rc) -> bool { // don't purge bootstrap nodes from nodedb if (IsBootstrapNode(rc.pubkey)) { @@ -1023,7 +1020,7 @@ namespace llarp // if we have a whitelist enabled and we don't // have the whitelist yet don't remove the entry - if (whitelistRouters and not gotWhitelist) + if (follow_whitelist and not gotWhitelist) { log::debug(logcat, "Skipping check on {}: don't have whitelist yet", rc.pubkey); return false; @@ -1032,7 +1029,7 @@ namespace llarp // 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 (gotWhitelist and not _rcLookupHandler.SessionIsAllowed(rc.pubkey)) + if (gotWhitelist and not _rc_lookup_handler.is_session_allowed(rc.pubkey)) { log::debug(logcat, "Removing {}: not a valid router", rc.pubkey); return true; @@ -1063,30 +1060,30 @@ namespace llarp // mark peers as de-registered for (auto& peer : closePeers) - _linkManager.deregister_peer(std::move(peer)); + _link_manager.deregister_peer(std::move(peer)); - _linkManager.check_persisting_conns(now); + _link_manager.check_persisting_conns(now); size_t connected = NumberOfConnectedRouters(); const int interval = isSvcNode ? 5 : 2; - const auto timepoint_now = Clock_t::now(); + const auto timepoint_now = std::chrono::steady_clock::now(); if (timepoint_now >= m_NextExploreAt and not decom) { - _rcLookupHandler.ExploreNetwork(); + _rc_lookup_handler.explore_network(); m_NextExploreAt = timepoint_now + std::chrono::seconds(interval); } - size_t connectToNum = _linkManager.min_connected_routers; - const auto strictConnect = _rcLookupHandler.NumberOfStrictConnectRouters(); + size_t connectToNum = _link_manager.min_connected_routers; + const auto strictConnect = _rc_lookup_handler.num_strict_connect_routers(); if (strictConnect > 0 && connectToNum > strictConnect) { connectToNum = strictConnect; } - if (isSvcNode and now >= m_NextDecommissionWarn) + if (isSvcNode and now >= next_decomm_warning) { constexpr auto DecommissionWarnInterval = 5min; - if (auto registered = LooksRegistered(), funded = LooksFunded(); + if (auto registered = appear_registered(), funded = appear_funder(); not(registered and funded and not decom)) { // complain about being deregistered/decommed/unfunded @@ -1096,52 +1093,52 @@ namespace llarp not registered ? "deregistered" : decom ? "decommissioned" : "not fully staked"); - m_NextDecommissionWarn = now + DecommissionWarnInterval; + next_decomm_warning = now + DecommissionWarnInterval; } - else if (TooFewPeers()) + else if (insufficient_peers()) { log::error( logcat, "We appear to be an active service node, but have only {} known peers.", - nodedb()->NumLoaded()); - m_NextDecommissionWarn = now + DecommissionWarnInterval; + node_db()->NumLoaded()); + next_decomm_warning = now + DecommissionWarnInterval; } } // if we need more sessions to routers and we are not a service node kicked from the network or // we are a client we shall connect out to others - if (connected < connectToNum and (LooksFunded() or not isSvcNode)) + if (connected < connectToNum and (appear_funder() or not isSvcNode)) { size_t dlt = connectToNum - connected; LogDebug("connecting to ", dlt, " random routers to keep alive"); - _linkManager.connect_to_random(dlt); + _link_manager.connect_to_random(dlt); } _hiddenServiceContext.Tick(now); _exitContext.Tick(now); // save profiles - if (routerProfiling().ShouldSave(now) and m_Config->network.m_saveProfiles) + if (router_profiling().ShouldSave(now) and config->network.m_saveProfiles) { - QueueDiskIO([&]() { routerProfiling().Save(_profilesFile); }); + queue_disk_io([&]() { router_profiling().Save(_profilesFile); }); } - _nodedb->Tick(now); + _node_db->Tick(now); - if (m_peerDb) + if (_peer_db) { // TODO: throttle this? // TODO: need to capture session stats when session terminates / is removed from link // manager - _linkManager.update_peer_db(m_peerDb); + _link_manager.update_peer_db(_peer_db); - if (m_peerDb->shouldFlush(now)) + if (_peer_db->shouldFlush(now)) { LogDebug("Queing database flush..."); - QueueDiskIO([this]() { + queue_disk_io([this]() { try { - m_peerDb->flushDatabase(); + _peer_db->flushDatabase(); } catch (std::exception& ex) { @@ -1188,7 +1185,7 @@ namespace llarp LogInfo("Session to ", remote, " fully closed"); if (IsServiceNode()) return; - if (const auto maybe = nodedb()->Get(remote); maybe.has_value()) + if (const auto maybe = node_db()->Get(remote); maybe.has_value()) { for (const auto& addr : maybe->addrs) m_RoutePoker->DelRoute(addr.IPv4()); @@ -1199,21 +1196,21 @@ namespace llarp void Router::ConnectionTimedOut(AbstractLinkSession* session) { - if (m_peerDb) + if (_peer_db) { RouterID id{session->GetPubKey()}; // TODO: make sure this is a public router (on whitelist)? - m_peerDb->modifyPeerStats(id, [&](PeerStats& stats) { stats.numConnectionTimeouts++; }); + _peer_db->modifyPeerStats(id, [&](PeerStats& stats) { stats.numConnectionTimeouts++; }); } } void - Router::ModifyOurRC(std::function(RouterContact)> modify) + Router::modify_rc(std::function(RouterContact)> modify) { if (auto maybe = modify(rc())) { - _rc = *maybe; - UpdateOurRC(); + router_contact = *maybe; + update_rc(); _rcGossiper.GossipRC(rc()); } } @@ -1223,19 +1220,19 @@ namespace llarp Router::ConnectionEstablished(AbstractLinkSession* session, bool inbound) { RouterID id{session->GetPubKey()}; - if (m_peerDb) + if (_peer_db) { // TODO: make sure this is a public router (on whitelist)? - m_peerDb->modifyPeerStats(id, [&](PeerStats& stats) { stats.numConnectionSuccesses++; }); + _peer_db->modifyPeerStats(id, [&](PeerStats& stats) { stats.numConnectionSuccesses++; }); } - NotifyRouterEvent(pubkey(), id, inbound); + notify_router_event(pubkey(), id, inbound); return true; } bool Router::GetRandomConnectedRouter(RouterContact& result) const { - return _linkManager.get_random_connected(result); + return _link_manager.get_random_connected(result); } void @@ -1243,7 +1240,7 @@ namespace llarp { for (const auto& rc : results) { - _rcLookupHandler.CheckRC(rc); + _rc_lookup_handler.check_rc(rc); } } @@ -1251,7 +1248,7 @@ namespace llarp void Router::LookupRouter(RouterID remote, RouterLookupHandler resultHandler) { - _rcLookupHandler.GetRC( + _rc_lookup_handler.get_rc( remote, [=](const RouterID& id, const RouterContact* const rc, const RCRequestResult result) { (void)id; @@ -1268,19 +1265,19 @@ namespace llarp } void - Router::SetRouterWhitelist( + Router::set_router_whitelist( const std::vector& whitelist, const std::vector& greylist, const std::vector& unfundedlist) { - _rcLookupHandler.SetRouterWhitelist(whitelist, greylist, unfundedlist); + _rc_lookup_handler.set_router_whitelist(whitelist, greylist, unfundedlist); } bool Router::StartRpcServer() { - if (m_Config->api.m_enableRPCServer) - m_RPCServer = std::make_unique(m_lmq, *this); + if (config->api.m_enableRPCServer) + m_RPCServer = std::make_unique(_lmq, *this); return true; } @@ -1288,28 +1285,28 @@ namespace llarp bool Router::Run() { - if (_running || _stopping) + if (is_running || is_stopping) return false; // set public signing key - _rc.pubkey = seckey_topublic(identity()); + router_contact.pubkey = seckey_topublic(identity()); // set router version if service node if (IsServiceNode()) { - _rc.routerVersion = RouterVersion(llarp::VERSION, llarp::constants::proto_version); + router_contact.routerVersion = RouterVersion(llarp::VERSION, llarp::constants::proto_version); } - if (IsServiceNode() and not _rc.IsPublicRouter()) + if (IsServiceNode() and not router_contact.IsPublicRouter()) { LogError("we are configured as relay but have no reachable addresses"); return false; } // set public encryption key - _rc.enckey = seckey_topublic(encryption()); + router_contact.enckey = seckey_topublic(encryption()); LogInfo("Signing rc..."); - if (!_rc.Sign(identity())) + if (!router_contact.Sign(identity())) { LogError("failed to sign rc"); return false; @@ -1335,9 +1332,9 @@ namespace llarp const RouterID us = pubkey(); LogInfo("initalized service node: ", us); // init gossiper here - _rcGossiper.Init(&_linkManager, us, this); + _rcGossiper.Init(&_link_manager, us, this); // relays do not use profiling - routerProfiling().Disable(); + router_profiling().Disable(); } else { @@ -1345,9 +1342,9 @@ namespace llarp // regenerate keys and resign rc before everything else CryptoManager::instance()->identity_keygen(_identity); CryptoManager::instance()->encryption_keygen(_encryption); - _rc.pubkey = seckey_topublic(identity()); - _rc.enckey = seckey_topublic(encryption()); - if (!_rc.Sign(identity())) + router_contact.pubkey = seckey_topublic(identity()); + router_contact.enckey = seckey_topublic(encryption()); + if (!router_contact.Sign(identity())) { LogError("failed to regenerate keys and sign RC"); return false; @@ -1363,38 +1360,38 @@ namespace llarp { LogInfo("Loading nodedb from disk..."); - _nodedb->LoadFromDisk(); + _node_db->LoadFromDisk(); } _dht->Init(llarp::dht::Key_t(pubkey()), this); for (const auto& rc : bootstrapRCList) { - nodedb()->Put(rc); + node_db()->Put(rc); _dht->Nodes()->PutNode(rc); LogInfo("added bootstrap node ", RouterID{rc.pubkey}); } - LogInfo("have ", _nodedb->NumLoaded(), " routers"); + LogInfo("have ", _node_db->NumLoaded(), " routers"); _loop->call_every(ROUTER_TICK_INTERVAL, weak_from_this(), [this] { Tick(); }); m_RoutePoker->Start(this); - _running.store(true); + is_running.store(true); _startedAt = Now(); - if (whitelistRouters) + if (follow_whitelist) { // do service node testing if we are in service node whitelist mode _loop->call_every(consensus::REACHABILITY_TESTING_TIMER_INTERVAL, weak_from_this(), [this] { // dont run tests if we are not running or we are stopping - if (not _running) + if (not is_running) return; // dont run tests if we think we should not test other routers // this occurs when we are deregistered or do not have the service node list // yet when we expect to have one. - if (not ShouldTestOtherRouters()) + if (not can_test_routers()) return; - auto tests = m_routerTesting.get_failing(); - if (auto maybe = m_routerTesting.next_random(this)) + auto tests = router_testing.get_failing(); + if (auto maybe = router_testing.next_random(this)) { tests.emplace_back(*maybe, 0); } @@ -1405,13 +1402,13 @@ namespace llarp LogDebug( router, " is no longer a registered service node so we remove it from the testing list"); - m_routerTesting.remove_node_from_failing(router); + router_testing.remove_node_from_failing(router); continue; } LogDebug("Establishing session to ", router, " for SN testing"); // try to make a session to this random router // this will do a dht lookup if needed - _linkManager.Connect(router); + _link_manager.connect_to(router); /* * TODO: container of pending snode test routers to be queried on @@ -1460,13 +1457,13 @@ namespace llarp }); } llarp::sys::service_manager->ready(); - return _running; + return is_running; } bool Router::IsRunning() const { - return _running; + return is_running; } llarp_time_t @@ -1484,7 +1481,7 @@ namespace llarp llarp::sys::service_manager->stopping(); Close(); log::debug(logcat, "stopping oxenmq"); - m_lmq.reset(); + _lmq.reset(); } void @@ -1494,25 +1491,25 @@ namespace llarp log::debug(logcat, "stopping links"); StopLinks(); log::debug(logcat, "saving nodedb to disk"); - nodedb()->SaveToDisk(); + node_db()->SaveToDisk(); _loop->call_later(200ms, [this] { AfterStopLinks(); }); } void Router::StopLinks() { - _linkManager.stop(); + _link_manager.stop(); } void Router::Die() { - if (!_running) + if (!is_running) return; - if (_stopping) + if (is_stopping) return; - _stopping.store(true); + is_stopping.store(true); if (log::get_level_default() != log::Level::off) log::reset_level(log::Level::info); LogWarn("stopping router hard"); @@ -1526,18 +1523,18 @@ namespace llarp void Router::Stop() { - if (!_running) + if (!is_running) { log::debug(logcat, "Stop called, but not running"); return; } - if (_stopping) + if (is_stopping) { log::debug(logcat, "Stop called, but already stopping"); return; } - _stopping.store(true); + 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); @@ -1559,7 +1556,7 @@ namespace llarp bool Router::HasSessionTo(const RouterID& remote) const { - return _linkManager.have_connection_to(remote); + return _link_manager.have_connection_to(remote); } std::string @@ -1571,7 +1568,7 @@ namespace llarp uint32_t Router::NextPathBuildNumber() { - return path_build_count++; + return _path_build_count++; } void @@ -1581,7 +1578,7 @@ namespace llarp auto connected = NumberOfConnectedRouters(); if (connected >= want) return; - _linkManager.connect_to_random(want); + _link_manager.connect_to_random(want); } bool @@ -1590,7 +1587,7 @@ namespace llarp LogInfo("accepting transit traffic"); paths.AllowTransit(); _dht->AllowTransit() = true; - _exitContext.AddExitEndpoint("default", m_Config->network, m_Config->dns); + _exitContext.AddExitEndpoint("default", config->network, config->dns); return true; } @@ -1604,26 +1601,26 @@ namespace llarp return false; } - if (not _rcLookupHandler.SessionIsAllowed(rc.pubkey)) + if (not _rc_lookup_handler.is_session_allowed(rc.pubkey)) { return false; } - _linkManager.Connect(rc); + _link_manager.connect_to(rc); return true; } void - Router::QueueWork(std::function func) + Router::queue_work(std::function func) { - m_lmq->job(std::move(func)); + _lmq->job(std::move(func)); } void - Router::QueueDiskIO(std::function func) + Router::queue_disk_io(std::function func) { - m_lmq->job(std::move(func), m_DiskThread); + _lmq->job(std::move(func), _disk_thread); } bool @@ -1636,7 +1633,7 @@ namespace llarp } std::optional> - Router::OurPublicIP() const + Router::public_ip() const { if (_ourAddress) return _ourAddress->getIP(); @@ -1658,58 +1655,27 @@ namespace llarp return found; } - void - Router::AddAddressToRC(AddressInfo& ai) - { - // override ip and port as needed - if (_ourAddress) - { - const auto ai_ip = ai.IP(); - const auto override_ip = _ourAddress->getIP(); - - auto ai_ip_str = var::visit([](auto&& ip) { return ip.ToString(); }, ai_ip); - auto override_ip_str = var::visit([](auto&& ip) { return ip.ToString(); }, override_ip); - - if ((not Net().IsBogonIP(ai_ip)) and (not Net().IsBogonIP(override_ip)) - and ai_ip != override_ip) - throw std::runtime_error{ - "Lokinet is bound to public IP '{}', but public-ip is set to '{}'. Either fix the " - "[router]:public-ip setting or set a bind address in the [bind] section of the " - "config."_format(ai_ip_str, override_ip_str)}; - ai.fromSockAddr(*_ourAddress); - } - if (RouterContact::BlockBogons && Net().IsBogon(ai.ip)) - throw std::runtime_error{var::visit( - [](auto&& ip) { - return "cannot use " + ip.ToString() - + " as a public ip as it is in a non routable ip range"; - }, - ai.IP())}; - LogInfo("adding address: ", ai); - _rc.addrs.push_back(ai); - } - void Router::InitInboundLinks() { - auto addrs = m_Config->links.InboundListenAddrs; - if (m_isServiceNode and addrs.empty()) + auto addrs = config->links.InboundListenAddrs; + if (is_service_node and addrs.empty()) { LogInfo("Inferring Public Address"); - auto maybe_port = m_Config->links.PublicPort; - if (m_Config->router.PublicPort and not maybe_port) - maybe_port = m_Config->router.PublicPort; + auto maybe_port = config->links.PublicPort; + if (config->router.PublicPort and not maybe_port) + maybe_port = config->router.PublicPort; if (not maybe_port) maybe_port = net::port_t::from_host(constants::DefaultInboundIWPPort); - if (auto maybe_addr = Net().MaybeInferPublicAddr(*maybe_port)) + if (auto maybe_addr = net().MaybeInferPublicAddr(*maybe_port)) { LogInfo("Public Address looks to be ", *maybe_addr); addrs.emplace_back(std::move(*maybe_addr)); } } - if (m_isServiceNode and addrs.empty()) + if (is_service_node and addrs.empty()) throw std::runtime_error{"we are a service node and we have no inbound links configured"}; // create inbound links, if we are a service node @@ -1718,7 +1684,7 @@ namespace llarp if (bind_addr.getPort() == 0) throw std::invalid_argument{"inbound link cannot use port 0"}; - if (Net().IsWildcardAddress(bind_addr.getIP())) + if (net().IsWildcardAddress(bind_addr.getIP())) { if (auto maybe_ip = OurPublicIP()) bind_addr.setIP(*maybe_ip); @@ -1741,9 +1707,9 @@ namespace llarp void Router::InitOutboundLinks() { - auto addrs = m_Config->links.OutboundLinks; + auto addrs = config->links.OutboundLinks; if (addrs.empty()) - addrs.emplace_back(Net().Wildcard()); + addrs.emplace_back(net().Wildcard()); for (auto& bind_addr : addrs) { @@ -1754,13 +1720,13 @@ namespace llarp } const llarp::net::Platform& - Router::Net() const + Router::net() const { return *llarp::net::Platform::Default_ptr(); } void - Router::MessageSent(const RouterID& remote, SendStatus status) + Router::message_sent(const RouterID& remote, SendStatus status) { if (status == SendStatus::Success) { @@ -1773,7 +1739,7 @@ namespace llarp } void - Router::HandleRouterEvent(tooling::RouterEventPtr event) const + Router::handle_router_event(tooling::RouterEventPtr event) const { LogDebug(event->ToString()); } diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 7090462cca..09aa4885d7 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -1,7 +1,5 @@ #pragma once -#include "abstractrouter.hpp" - #include #include #include @@ -12,13 +10,14 @@ #include #include #include -#include #include #include #include #include #include #include +#include +#include #include "outbound_message_handler.hpp" #include "rc_gossiper.hpp" #include "rc_lookup_handler.hpp" @@ -52,7 +51,7 @@ namespace libquic = oxen::quic; namespace llarp { - class RouteManager final /* : public AbstractRouter */ + class RouteManager final /* : public Router */ { public: std::shared_ptr @@ -62,198 +61,273 @@ namespace llarp std::shared_ptr ep; }; - struct Router final : public AbstractRouter + struct Router : std::enable_shared_from_this { - llarp_time_t _lastPump = 0s; - bool ready; + private: + llarp_time_t last_pump = 0s; // transient iwp encryption key fs::path transport_keyfile; - // long term identity key - fs::path ident_keyfile; - + fs::path identity_keyfile; fs::path encryption_keyfile; - // path to write our self signed rc to fs::path our_rc_file; - // use file based logging? - bool m_UseFileLogging = false; - + bool use_file_logging = false; // our router contact - RouterContact _rc; - + RouterContact router_contact; /// should we obey the service node whitelist? - bool whitelistRouters = false; + bool follow_whitelist = false; + std::shared_ptr _lmq; + path::BuildLimiter _pathbuild_limiter; + std::shared_ptr loop_wakeup; + + std::atomic is_stopping; + std::atomic is_running; + + int _outbound_udp_socket = -1; + bool is_service_node = false; + + std::optional _ourAddress; + oxen::quic::Address local; + + EventLoop_ptr _loop; + std::shared_ptr _vpn; + path::PathContext paths; + exit::Context _exitContext; + SecretKey _identity; + SecretKey _encryption; + std::shared_ptr _dht; + std::shared_ptr _node_db; + llarp_time_t _startedAt; + const oxenmq::TaggedThreadID _disk_thread; + oxen::quic::Network _net; - LMQ_ptr m_lmq; + llarp_time_t _last_stats_report = 0s; + llarp_time_t next_decomm_warning = time_now_ms() + 15s; + std::shared_ptr _key_manager; + std::shared_ptr _peer_db; + std::shared_ptr _config; + uint32_t _path_build_count = 0; - path::BuildLimiter m_PathBuildLimiter; + consensus::reachability_testing router_testing; - std::shared_ptr m_Pump; + bool + should_report_stats(llarp_time_t now) const; + + void + report_stats(); + + bool + update_rc(bool rotateKeys = false); + + bool + from_config(const Config& conf); + + void + message_sent(const RouterID& remote, SendStatus status); + + bool + insufficient_peers() const; + + protected: + void + handle_router_event(tooling::RouterEventPtr event) const; + + virtual bool + disableGossipingRC_TestingOnly() + { + return false; + }; + + public: + std::shared_ptr + config() const + { + return _config; + } path::BuildLimiter& - pathBuildLimiter() override + pathbuild_limiter() { - return m_PathBuildLimiter; + return _pathbuild_limiter; } const llarp::net::Platform& - Net() const override; + net() const; - const LMQ_ptr& - lmq() const override + const std::shared_ptr& + lmq() const { - return m_lmq; + return _lmq; } const std::shared_ptr& - RpcClient() const override + rpc_client() const { - return m_lokidRpcClient; + return _rpc_client; } std::shared_ptr - dht() const override + dht() const { return _dht; } - std::optional> - OurPublicIP() const override; - - util::StatusObject - ExtractStatus() const override; - - util::StatusObject - ExtractSummaryStatus() const override; - - const std::shared_ptr& - nodedb() const override + // TOFIX: THIS + OutboundMessageHandler& + outboundMessageHandler() { - return _nodedb; + return _outboundMessageHandler; } - const path::PathContext& - pathContext() const override + LinkManager& + link_manager() { - return paths; + return _link_manager; } - path::PathContext& - pathContext() override + RCLookupHandler& + rc_lookup_handler() { - return paths; + return _rc_lookup_handler; } - const RouterContact& - rc() const override + std::shared_ptr + peer_db() { - return _rc; + return _peer_db; } - void - ModifyOurRC(std::function(RouterContact)> modify) override; - - void - SetRouterWhitelist( - const std::vector& whitelist, - const std::vector& greylist, - const std::vector& unfunded) override; - - std::unordered_set - GetRouterWhitelist() const override + inline int + outbound_udp_socket() const { - return _rcLookupHandler.Whitelist(); + return _outbound_udp_socket; } exit::Context& - exitContext() override + exitContext() { return _exitContext; } const std::shared_ptr& - keyManager() const override + key_manager() const { - return m_keyManager; + return _key_manager; } const SecretKey& - identity() const override + identity() const { return _identity; } const SecretKey& - encryption() const override + encryption() const { return _encryption; } Profiling& - routerProfiling() override + router_profiling() { - return _routerProfiling; + return _router_profiling; } const EventLoop_ptr& - loop() const override + loop() const { return _loop; } vpn::Platform* - GetVPNPlatform() const override + vpn_platform() const + { + return _vpn.get(); + } + + const std::shared_ptr& + node_db() const + { + return _node_db; + } + + path::PathContext& + path_context() { - return _vpnPlatform.get(); + return paths; + } + + const RouterContact& + rc() const + { + return router_contact; + } + + std::optional> + public_ip() const; + + util::StatusObject + ExtractStatus() const; + + util::StatusObject + ExtractSummaryStatus() const; + + std::unordered_set + router_whitelist() const + { + return _rc_lookup_handler.whitelist(); + } + + void + modify_rc(std::function(RouterContact)> modify); + + void + set_router_whitelist( + const std::vector& whitelist, + const std::vector& greylist, + const std::vector& unfunded); + + template + void + notify_router_event([[maybe_unused]] Params&&... args) const + { + // TODO: no-op when appropriate + auto event = std::make_unique(args...); + handle_router_event(std::move(event)); } void - QueueWork(std::function func) override; + queue_work(std::function func); void - QueueDiskIO(std::function func) override; + queue_disk_io(std::function func); /// return true if we look like we are a decommissioned service node bool - LooksDecommissioned() const; + appear_decommed() const; /// return true if we look like we are a registered, fully-staked service node (either active or /// decommissioned). This condition determines when we are allowed to (and attempt to) connect /// to other peers when running as a service node. bool - LooksFunded() const; + appear_funded() const; /// return true if we a registered service node; not that this only requires a partial stake, /// and does not imply that this service node is *active* or fully funded. bool - LooksRegistered() const; + appear_registered() const; /// return true if we look like we are allowed and able to test other routers bool - ShouldTestOtherRouters() const; - - std::optional _ourAddress; - oxen::quic::Address local; - - EventLoop_ptr _loop; - std::shared_ptr _vpnPlatform; - path::PathContext paths; - exit::Context _exitContext; - SecretKey _identity; - SecretKey _encryption; - std::shared_ptr _dht; - std::shared_ptr _nodedb; - llarp_time_t _startedAt; - const oxenmq::TaggedThreadID m_DiskThread; - oxen::quic::Network _net; + can_test_routers() const; llarp_time_t - Uptime() const override; + Uptime() const; bool - Sign(Signature& sig, const llarp_buffer_t& buf) const override; + Sign(Signature& sig, const llarp_buffer_t& buf) const; /// how often do we resign our RC? milliseconds. // TODO: make configurable @@ -268,13 +342,13 @@ namespace llarp service::Context _hiddenServiceContext; service::Context& - hiddenServiceContext() override + hiddenServiceContext() { return _hiddenServiceContext; } const service::Context& - hiddenServiceContext() const override + hiddenServiceContext() const { return _hiddenServiceContext; } @@ -284,13 +358,13 @@ namespace llarp std::function _onDown; void - SetDownHook(std::function hook) override + SetDownHook(std::function hook) { _onDown = hook; } bool - LooksAlive() const override + LooksAlive() const { const llarp_time_t now = Now(); return now <= _lastTick || (now - _lastTick) <= llarp_time_t{30000}; @@ -300,7 +374,7 @@ namespace llarp BootstrapList bootstrapRCList; const std::shared_ptr& - routePoker() const override + routePoker() const { return m_RoutePoker; } @@ -308,7 +382,7 @@ namespace llarp std::shared_ptr m_RoutePoker; void - TriggerPump() override; + TriggerPump(); void PumpLL(); @@ -317,63 +391,32 @@ namespace llarp const llarp_time_t _randomStartDelay; - std::shared_ptr m_lokidRpcClient; + std::shared_ptr _rpc_client; oxenmq::address lokidRPCAddr; - Profiling _routerProfiling; + Profiling _router_profiling; fs::path _profilesFile; OutboundMessageHandler _outboundMessageHandler; - LinkManager _linkManager{*this}; - RCLookupHandler _rcLookupHandler; + LinkManager _link_manager{*this}; + RCLookupHandler _rc_lookup_handler; RCGossiper _rcGossiper; std::string - status_line() override; + status_line(); - using Clock_t = std::chrono::steady_clock; - using TimePoint_t = Clock_t::time_point; + using TimePoint_t = std::chrono::steady_clock::time_point; TimePoint_t m_NextExploreAt; - OutboundMessageHandler& - outboundMessageHandler() override - { - return _outboundMessageHandler; - } - - LinkManager& - linkManager() override - { - return _linkManager; - } - - RCLookupHandler& - rcLookupHandler() override - { - return _rcLookupHandler; - } - - std::shared_ptr - peerDb() override - { - return m_peerDb; - } - - inline int - OutboundUDPSocket() const override - { - return m_OutboundUDPSocket; - } - void - GossipRCIfNeeded(const RouterContact rc) override; + GossipRCIfNeeded(const RouterContact rc); explicit Router(EventLoop_ptr loop, std::shared_ptr vpnPlatform); - ~Router() override; + ~Router(); bool - HandleRecvLinkMessageBuffer(AbstractLinkSession* from, const llarp_buffer_t& msg) override; + HandleRecvLinkMessageBuffer(AbstractLinkSession* from, const llarp_buffer_t& msg); void InitInboundLinks(); @@ -382,7 +425,7 @@ namespace llarp InitOutboundLinks(); bool - GetRandomGoodRouter(RouterID& r) override; + GetRandomGoodRouter(RouterID& r); /// initialize us as a service node /// return true on success @@ -390,47 +433,47 @@ namespace llarp InitServiceNode(); bool - IsRunning() const override; + IsRunning() const; /// return true if we are running in service node mode bool - IsServiceNode() const override; + IsServiceNode() const; std::optional - OxendErrorState() const override; + OxendErrorState() const; void Close(); bool - Configure(std::shared_ptr conf, bool isSNode, std::shared_ptr nodedb) override; + Configure(std::shared_ptr conf, bool isSNode, std::shared_ptr nodedb); bool - StartRpcServer() override; + StartRpcServer(); void - Freeze() override; + Freeze(); void - Thaw() override; + Thaw(); bool - Run() override; + Run(); /// stop running the router logic gracefully void - Stop() override; + Stop(); /// non graceful stop router void - Die() override; + Die(); /// close all sessions and shutdown all links void StopLinks(); void - PersistSessionUntil(const RouterID& remote, llarp_time_t until) override; + PersistSessionUntil(const RouterID& remote, llarp_time_t until); bool EnsureIdentity(); @@ -439,9 +482,10 @@ namespace llarp EnsureEncryptionKey(); bool - SessionToRouterAllowed(const RouterID& router) const override; + SessionToRouterAllowed(const RouterID& router) const; + bool - PathToRouterAllowed(const RouterID& router) const override; + PathToRouterAllowed(const RouterID& router) const; void HandleSaveRC() const; @@ -451,10 +495,10 @@ namespace llarp /// return true if we are a client with an exit configured bool - HasClientExit() const override; + HasClientExit() const; const byte_t* - pubkey() const override + pubkey() const { return seckey_topublic(_identity); } @@ -463,7 +507,7 @@ namespace llarp try_connect(fs::path rcfile); bool - TryConnectAsync(RouterContact rc, uint16_t tries) override; + TryConnectAsync(RouterContact rc, uint16_t tries); /// send to remote router or queue for sending /// returns false on overflow @@ -472,27 +516,27 @@ namespace llarp /// MUST be called in the logic thread bool SendToOrQueue( - const RouterID& remote, const AbstractLinkMessage& msg, SendStatusHandler handler) override; + const RouterID& remote, const AbstractLinkMessage& msg, SendStatusHandler handler); void - ForEachPeer(std::function visit, bool randomize = false) - const override; + ForEachPeer( + std::function visit, bool randomize = false) const; void ForEachPeer(std::function visit); - bool IsBootstrapNode(RouterID) const override; + bool IsBootstrapNode(RouterID) const; /// check if newRc matches oldRC and update local rc for this remote contact /// if valid /// returns true on valid and updated /// returns false otherwise bool - CheckRenegotiateValid(RouterContact newRc, RouterContact oldRC) override; + CheckRenegotiateValid(RouterContact newRc, RouterContact oldRC); /// called by link when a remote session has no more sessions open void - SessionClosed(RouterID remote) override; + SessionClosed(RouterID remote); /// called by link when an unestablished connection times out void @@ -507,7 +551,7 @@ namespace llarp Tick(); llarp_time_t - Now() const override + Now() const { return llarp::time_now_ms(); } @@ -517,103 +561,41 @@ namespace llarp /// return false bool ParseRoutingMessageBuffer( - const llarp_buffer_t& buf, - routing::AbstractRoutingMessageHandler* h, - const PathID_t& rxid) override; + const llarp_buffer_t& buf, routing::AbstractRoutingMessageHandler* h, const PathID_t& rxid); void - ConnectToRandomRouters(int N) override; + ConnectToRandomRouters(int N); /// count the number of unique service nodes connected via pubkey size_t - NumberOfConnectedRouters() const override; + NumberOfConnectedRouters() const; /// count the number of unique clients connected by pubkey size_t - NumberOfConnectedClients() const override; + NumberOfConnectedClients() const; bool - GetRandomConnectedRouter(RouterContact& result) const override; + GetRandomConnectedRouter(RouterContact& result) const; void - HandleDHTLookupForExplore(RouterID remote, const std::vector& results) override; + HandleDHTLookupForExplore(RouterID remote, const std::vector& results); void - LookupRouter(RouterID remote, RouterLookupHandler resultHandler) override; + LookupRouter(RouterID remote, RouterLookupHandler resultHandler); bool - HasSessionTo(const RouterID& remote) const override; + HasSessionTo(const RouterID& remote) const; std::string - ShortName() const override; + ShortName() const; uint32_t - NextPathBuildNumber() override; + NextPathBuildNumber(); void AfterStopLinks(); void AfterStopIssued(); - - std::shared_ptr m_Config; - - std::shared_ptr - GetConfig() const override - { - return m_Config; - } - - int m_OutboundUDPSocket = -1; - - private: - std::atomic _stopping; - std::atomic _running; - - bool m_isServiceNode = false; - - // Delay warning about being decommed/dereged until we've had enough time to sync up with oxend - static constexpr auto DECOMM_WARNING_STARTUP_DELAY = 15s; - - llarp_time_t m_LastStatsReport = 0s; - llarp_time_t m_NextDecommissionWarn = time_now_ms() + DECOMM_WARNING_STARTUP_DELAY; - std::shared_ptr m_keyManager; - std::shared_ptr m_peerDb; - - uint32_t path_build_count = 0; - - consensus::reachability_testing m_routerTesting; - - bool - ShouldReportStats(llarp_time_t now) const; - - void - ReportStats(); - - bool - UpdateOurRC(bool rotateKeys = false); - - bool - FromConfig(const Config& conf); - - void - MessageSent(const RouterID& remote, SendStatus status); - - bool - TooFewPeers() const; - - void - AddAddressToRC(AddressInfo& ai); - - protected: - void - HandleRouterEvent(tooling::RouterEventPtr event) const override; - - virtual bool - disableGossipingRC_TestingOnly() - { - return false; - }; }; - } // namespace llarp diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index ed6a8dcd8c..6fcd021aeb 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -2,7 +2,6 @@ #include "llarp/constants/version.hpp" #include "llarp/crypto/types.hpp" -#include "llarp/net/address_info.hpp" #include "llarp/net/exit_info.hpp" #include "llarp/util/aligned.hpp" #include "llarp/util/bencode.hpp" @@ -11,6 +10,8 @@ #include "llarp/dns/srv_data.hpp" +#include + #include #include #include @@ -75,7 +76,7 @@ namespace llarp } // advertised addresses - std::vector addrs; + oxen::quic::Address addr; // network identifier NetID netID; // public encryption public key @@ -124,7 +125,7 @@ namespace llarp bool operator==(const RouterContact& other) const { - return addrs == other.addrs && enckey == other.enckey && pubkey == other.pubkey + return addr == other.addr && enckey == other.enckey && pubkey == other.pubkey && signature == other.signature && nickname == other.nickname && last_updated == other.last_updated && netID == other.netID; } diff --git a/llarp/routing/handler.hpp b/llarp/routing/handler.hpp index adca3cdd68..e28a1f4c00 100644 --- a/llarp/routing/handler.hpp +++ b/llarp/routing/handler.hpp @@ -4,7 +4,7 @@ namespace llarp { - struct AbstractRouter; + struct Router; namespace dht { @@ -34,42 +34,42 @@ namespace llarp struct AbstractRoutingMessageHandler { virtual bool - HandleObtainExitMessage(const ObtainExitMessage& msg, AbstractRouter* r) = 0; + HandleObtainExitMessage(const ObtainExitMessage& msg, Router* r) = 0; virtual bool - HandleGrantExitMessage(const GrantExitMessage& msg, AbstractRouter* r) = 0; + HandleGrantExitMessage(const GrantExitMessage& msg, Router* r) = 0; virtual bool - HandleRejectExitMessage(const RejectExitMessage& msg, AbstractRouter* r) = 0; + HandleRejectExitMessage(const RejectExitMessage& msg, Router* r) = 0; virtual bool - HandleTransferTrafficMessage(const TransferTrafficMessage& msg, AbstractRouter* r) = 0; + HandleTransferTrafficMessage(const TransferTrafficMessage& msg, Router* r) = 0; virtual bool - HandleUpdateExitMessage(const UpdateExitMessage& msg, AbstractRouter* r) = 0; + HandleUpdateExitMessage(const UpdateExitMessage& msg, Router* r) = 0; virtual bool - HandleUpdateExitVerifyMessage(const UpdateExitVerifyMessage& msg, AbstractRouter* r) = 0; + HandleUpdateExitVerifyMessage(const UpdateExitVerifyMessage& msg, Router* r) = 0; virtual bool - HandleCloseExitMessage(const CloseExitMessage& msg, AbstractRouter* r) = 0; + HandleCloseExitMessage(const CloseExitMessage& msg, Router* r) = 0; virtual bool - HandleDataDiscardMessage(const DataDiscardMessage& msg, AbstractRouter* r) = 0; + HandleDataDiscardMessage(const DataDiscardMessage& msg, Router* r) = 0; virtual bool - HandlePathTransferMessage(const PathTransferMessage& msg, AbstractRouter* r) = 0; + HandlePathTransferMessage(const PathTransferMessage& msg, Router* r) = 0; virtual bool HandleHiddenServiceFrame(const service::ProtocolFrameMessage& msg) = 0; virtual bool - HandlePathConfirmMessage(const PathConfirmMessage& msg, AbstractRouter* r) = 0; + HandlePathConfirmMessage(const PathConfirmMessage& msg, Router* r) = 0; virtual bool - HandlePathLatencyMessage(const PathLatencyMessage& msg, AbstractRouter* r) = 0; + HandlePathLatencyMessage(const PathLatencyMessage& msg, Router* r) = 0; virtual bool - HandleDHTMessage(const dht::AbstractDHTMessage& msg, AbstractRouter* r) = 0; + HandleDHTMessage(const dht::AbstractDHTMessage& msg, Router* r) = 0; }; using MessageHandler_ptr = std::shared_ptr; diff --git a/llarp/routing/message.hpp b/llarp/routing/message.hpp index 5a4700bb7a..ac04d30b36 100644 --- a/llarp/routing/message.hpp +++ b/llarp/routing/message.hpp @@ -13,7 +13,7 @@ namespace namespace llarp { - struct AbstractRouter; + struct Router; namespace routing { struct AbstractRoutingMessageHandler; @@ -35,7 +35,7 @@ namespace llarp bt_encode() const override = 0; virtual bool - handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const = 0; + handle_message(AbstractRoutingMessageHandler* h, Router* r) const = 0; virtual void clear() = 0; diff --git a/llarp/routing/message_parser.cpp b/llarp/routing/message_parser.cpp index 5f7e5b5376..64b214d138 100644 --- a/llarp/routing/message_parser.cpp +++ b/llarp/routing/message_parser.cpp @@ -106,10 +106,7 @@ namespace llarp::routing bool InboundMessageParser::ParseMessageBuffer( - const llarp_buffer_t& buf, - AbstractRoutingMessageHandler* h, - const PathID_t& from, - AbstractRouter* r) + const llarp_buffer_t& buf, AbstractRoutingMessageHandler* h, const PathID_t& from, Router* r) { bool result = false; msg = nullptr; diff --git a/llarp/routing/message_parser.hpp b/llarp/routing/message_parser.hpp index 968260224d..0ee7a5ceef 100644 --- a/llarp/routing/message_parser.hpp +++ b/llarp/routing/message_parser.hpp @@ -7,7 +7,7 @@ namespace llarp { - struct AbstractRouter; + struct Router; struct PathID_t; namespace routing @@ -25,7 +25,7 @@ namespace llarp const llarp_buffer_t& buf, AbstractRoutingMessageHandler* handler, const PathID_t& from, - AbstractRouter* r); + Router* r); bool operator()(llarp_buffer_t* buffer, llarp_buffer_t* key); diff --git a/llarp/routing/path_confirm_message.cpp b/llarp/routing/path_confirm_message.cpp index 3b41386e79..268e2e4b83 100644 --- a/llarp/routing/path_confirm_message.cpp +++ b/llarp/routing/path_confirm_message.cpp @@ -47,7 +47,7 @@ namespace llarp::routing } bool - PathConfirmMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + PathConfirmMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const { return h && h->HandlePathConfirmMessage(*this, r); } diff --git a/llarp/routing/path_confirm_message.hpp b/llarp/routing/path_confirm_message.hpp index 986f0f9675..d7f4f1624c 100644 --- a/llarp/routing/path_confirm_message.hpp +++ b/llarp/routing/path_confirm_message.hpp @@ -20,7 +20,7 @@ namespace llarp::routing decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; bool - handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + handle_message(AbstractRoutingMessageHandler* h, Router* r) const override; void clear() override diff --git a/llarp/routing/path_dht_message.cpp b/llarp/routing/path_dht_message.cpp index 3f5bddb96c..bca3ad5e9e 100644 --- a/llarp/routing/path_dht_message.cpp +++ b/llarp/routing/path_dht_message.cpp @@ -1,6 +1,6 @@ #include "path_dht_message.hpp" -#include +#include #include "handler.hpp" namespace llarp::routing @@ -58,7 +58,7 @@ namespace llarp::routing /// (e.g. dht::IMessage::HandleMessage()) in-place and is the case where a /// client receives a DHT message bool - PathDHTMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + PathDHTMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const { // set source as us const llarp::dht::Key_t us(r->pubkey()); diff --git a/llarp/routing/path_dht_message.hpp b/llarp/routing/path_dht_message.hpp index af8b473aac..365a2e8376 100644 --- a/llarp/routing/path_dht_message.hpp +++ b/llarp/routing/path_dht_message.hpp @@ -20,7 +20,7 @@ namespace llarp::routing bt_encode() const override; bool - handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + handle_message(AbstractRoutingMessageHandler* h, Router* r) const override; void clear() override diff --git a/llarp/routing/path_latency_message.cpp b/llarp/routing/path_latency_message.cpp index 4715311eed..b70b7041ca 100644 --- a/llarp/routing/path_latency_message.cpp +++ b/llarp/routing/path_latency_message.cpp @@ -43,7 +43,7 @@ namespace llarp::routing } bool - PathLatencyMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + PathLatencyMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const { return h && h->HandlePathLatencyMessage(*this, r); } diff --git a/llarp/routing/path_latency_message.hpp b/llarp/routing/path_latency_message.hpp index 3a5ec34730..fdbfc42ed7 100644 --- a/llarp/routing/path_latency_message.hpp +++ b/llarp/routing/path_latency_message.hpp @@ -25,6 +25,6 @@ namespace llarp::routing } bool - handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + handle_message(AbstractRoutingMessageHandler* h, Router* r) const override; }; } // namespace llarp::routing diff --git a/llarp/routing/path_transfer_message.cpp b/llarp/routing/path_transfer_message.cpp index f210b0eb05..fd840997dc 100644 --- a/llarp/routing/path_transfer_message.cpp +++ b/llarp/routing/path_transfer_message.cpp @@ -44,7 +44,7 @@ namespace llarp::routing } bool - PathTransferMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + PathTransferMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const { return h->HandlePathTransferMessage(*this, r); } diff --git a/llarp/routing/path_transfer_message.hpp b/llarp/routing/path_transfer_message.hpp index 2ede435605..d156ef2ff7 100644 --- a/llarp/routing/path_transfer_message.hpp +++ b/llarp/routing/path_transfer_message.hpp @@ -28,7 +28,7 @@ namespace llarp::routing bt_encode() const override; bool - handle_message(AbstractRoutingMessageHandler*, AbstractRouter* r) const override; + handle_message(AbstractRoutingMessageHandler*, Router* r) const override; void clear() override diff --git a/llarp/routing/transfer_traffic_message.cpp b/llarp/routing/transfer_traffic_message.cpp index c46d3acb09..3e27377104 100644 --- a/llarp/routing/transfer_traffic_message.cpp +++ b/llarp/routing/transfer_traffic_message.cpp @@ -65,7 +65,7 @@ namespace llarp::routing } bool - TransferTrafficMessage::handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const + TransferTrafficMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const { return h->HandleTransferTrafficMessage(*this, r); } diff --git a/llarp/routing/transfer_traffic_message.hpp b/llarp/routing/transfer_traffic_message.hpp index 14f24ef500..890c178f45 100644 --- a/llarp/routing/transfer_traffic_message.hpp +++ b/llarp/routing/transfer_traffic_message.hpp @@ -44,6 +44,6 @@ namespace llarp::routing decode_key(const llarp_buffer_t& k, llarp_buffer_t* val) override; bool - handle_message(AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + handle_message(AbstractRoutingMessageHandler* h, Router* r) const override; }; } // namespace llarp::routing diff --git a/llarp/rpc/lokid_rpc_client.cpp b/llarp/rpc/lokid_rpc_client.cpp index 6f409f88e0..0db01fd662 100644 --- a/llarp/rpc/lokid_rpc_client.cpp +++ b/llarp/rpc/lokid_rpc_client.cpp @@ -3,467 +3,461 @@ #include #include -#include +#include #include #include #include #include -namespace llarp +namespace llarp::rpc { - namespace rpc + static constexpr oxenmq::LogLevel + toLokiMQLogLevel(log::Level level) { - static constexpr oxenmq::LogLevel - toLokiMQLogLevel(log::Level level) + switch (level) { - switch (level) - { - case log::Level::critical: - return oxenmq::LogLevel::fatal; - case log::Level::err: - return oxenmq::LogLevel::error; - case log::Level::warn: - return oxenmq::LogLevel::warn; - case log::Level::info: - return oxenmq::LogLevel::info; - case log::Level::debug: - return oxenmq::LogLevel::debug; - case log::Level::trace: - case log::Level::off: - default: - return oxenmq::LogLevel::trace; - } + case log::Level::critical: + return oxenmq::LogLevel::fatal; + case log::Level::err: + return oxenmq::LogLevel::error; + case log::Level::warn: + return oxenmq::LogLevel::warn; + case log::Level::info: + return oxenmq::LogLevel::info; + case log::Level::debug: + return oxenmq::LogLevel::debug; + case log::Level::trace: + case log::Level::off: + default: + return oxenmq::LogLevel::trace; } + } - LokidRpcClient::LokidRpcClient(LMQ_ptr lmq, std::weak_ptr r) - : m_lokiMQ{std::move(lmq)}, m_Router{std::move(r)} - { - // m_lokiMQ->log_level(toLokiMQLogLevel(LogLevel::Instance().curLevel)); + LokidRpcClient::LokidRpcClient(std::shared_ptr lmq, std::weak_ptr r) + : m_lokiMQ{std::move(lmq)}, m_Router{std::move(r)} + { + // m_lokiMQ->log_level(toLokiMQLogLevel(LogLevel::Instance().curLevel)); - // new block handler - m_lokiMQ->add_category("notify", oxenmq::Access{oxenmq::AuthLevel::none}) - .add_command("block", [this](oxenmq::Message& m) { HandleNewBlock(m); }); + // new block handler + m_lokiMQ->add_category("notify", oxenmq::Access{oxenmq::AuthLevel::none}) + .add_command("block", [this](oxenmq::Message& m) { HandleNewBlock(m); }); - // TODO: proper auth here - auto lokidCategory = m_lokiMQ->add_category("lokid", oxenmq::Access{oxenmq::AuthLevel::none}); - lokidCategory.add_request_command( - "get_peer_stats", [this](oxenmq::Message& m) { HandleGetPeerStats(m); }); - m_UpdatingList = false; - } + // TODO: proper auth here + auto lokidCategory = m_lokiMQ->add_category("lokid", oxenmq::Access{oxenmq::AuthLevel::none}); + lokidCategory.add_request_command( + "get_peer_stats", [this](oxenmq::Message& m) { HandleGetPeerStats(m); }); + m_UpdatingList = false; + } - void - LokidRpcClient::ConnectAsync(oxenmq::address url) + void + LokidRpcClient::ConnectAsync(oxenmq::address url) + { + if (auto router = m_Router.lock()) { - if (auto router = m_Router.lock()) + if (not router->IsServiceNode()) { - if (not router->IsServiceNode()) - { - throw std::runtime_error("we cannot talk to lokid while not a service node"); - } - LogInfo("connecting to lokid via LMQ at ", url.full_address()); - m_Connection = m_lokiMQ->connect_remote( - url, - [](oxenmq::ConnectionID) {}, - [self = shared_from_this(), url](oxenmq::ConnectionID, std::string_view f) { - llarp::LogWarn("Failed to connect to lokid: ", f); - if (auto router = self->m_Router.lock()) - { - router->loop()->call([self, url]() { self->ConnectAsync(url); }); - } - }); + throw std::runtime_error("we cannot talk to lokid while not a service node"); } + LogInfo("connecting to lokid via LMQ at ", url.full_address()); + m_Connection = m_lokiMQ->connect_remote( + url, + [](oxenmq::ConnectionID) {}, + [self = shared_from_this(), url](oxenmq::ConnectionID, std::string_view f) { + llarp::LogWarn("Failed to connect to lokid: ", f); + if (auto router = self->m_Router.lock()) + { + router->loop()->call([self, url]() { self->ConnectAsync(url); }); + } + }); } + } - void - LokidRpcClient::Command(std::string_view cmd) + void + LokidRpcClient::Command(std::string_view cmd) + { + LogDebug("lokid command: ", cmd); + m_lokiMQ->send(*m_Connection, std::move(cmd)); + } + + void + LokidRpcClient::HandleNewBlock(oxenmq::Message& msg) + { + if (msg.data.size() != 2) { - LogDebug("lokid command: ", cmd); - m_lokiMQ->send(*m_Connection, std::move(cmd)); + LogError( + "we got an invalid new block notification with ", + msg.data.size(), + " parts instead of 2 parts so we will not update the list of service nodes"); + return; // bail } - - void - LokidRpcClient::HandleNewBlock(oxenmq::Message& msg) + try { - if (msg.data.size() != 2) - { - LogError( - "we got an invalid new block notification with ", - msg.data.size(), - " parts instead of 2 parts so we will not update the list of service nodes"); - return; // bail - } - try - { - m_BlockHeight = std::stoll(std::string{msg.data[0]}); - } - catch (std::exception& ex) - { - LogError("bad block height: ", ex.what()); - return; // bail - } - - LogDebug("new block at height ", m_BlockHeight); - // don't upadate on block notification if an update is pending - if (not m_UpdatingList) - UpdateServiceNodeList(); + m_BlockHeight = std::stoll(std::string{msg.data[0]}); } - - void - LokidRpcClient::UpdateServiceNodeList() + catch (std::exception& ex) { - if (m_UpdatingList.exchange(true)) - return; // update already in progress - - nlohmann::json request{ - {"fields", - { - {"pubkey_ed25519", true}, - {"service_node_pubkey", true}, - {"funded", true}, - {"active", true}, - {"block_hash", true}, - }}, - }; - if (!m_LastUpdateHash.empty()) - request["poll_block_hash"] = m_LastUpdateHash; - - Request( - "rpc.get_service_nodes", - [self = shared_from_this()](bool success, std::vector data) { - if (not success) - LogWarn("failed to update service node list"); - else if (data.size() < 2) - LogWarn("oxend gave empty reply for service node list"); - else + LogError("bad block height: ", ex.what()); + return; // bail + } + + LogDebug("new block at height ", m_BlockHeight); + // don't upadate on block notification if an update is pending + if (not m_UpdatingList) + UpdateServiceNodeList(); + } + + void + LokidRpcClient::UpdateServiceNodeList() + { + if (m_UpdatingList.exchange(true)) + return; // update already in progress + + nlohmann::json request{ + {"fields", + { + {"pubkey_ed25519", true}, + {"service_node_pubkey", true}, + {"funded", true}, + {"active", true}, + {"block_hash", true}, + }}, + }; + if (!m_LastUpdateHash.empty()) + request["poll_block_hash"] = m_LastUpdateHash; + + Request( + "rpc.get_service_nodes", + [self = shared_from_this()](bool success, std::vector data) { + if (not success) + LogWarn("failed to update service node list"); + else if (data.size() < 2) + LogWarn("oxend gave empty reply for service node list"); + else + { + try { - try + auto json = nlohmann::json::parse(std::move(data[1])); + if (json.at("status") != "OK") + throw std::runtime_error{"get_service_nodes did not return 'OK' status"}; + if (auto it = json.find("unchanged"); + it != json.end() and it->is_boolean() and it->get()) + LogDebug("service node list unchanged"); + else { - auto json = nlohmann::json::parse(std::move(data[1])); - if (json.at("status") != "OK") - throw std::runtime_error{"get_service_nodes did not return 'OK' status"}; - if (auto it = json.find("unchanged"); - it != json.end() and it->is_boolean() and it->get()) - LogDebug("service node list unchanged"); + self->HandleNewServiceNodeList(json.at("service_node_states")); + if (auto it = json.find("block_hash"); it != json.end() and it->is_string()) + self->m_LastUpdateHash = it->get(); else - { - self->HandleNewServiceNodeList(json.at("service_node_states")); - if (auto it = json.find("block_hash"); it != json.end() and it->is_string()) - self->m_LastUpdateHash = it->get(); - else - self->m_LastUpdateHash.clear(); - } - } - catch (const std::exception& ex) - { - LogError("failed to process service node list: ", ex.what()); + self->m_LastUpdateHash.clear(); } } + catch (const std::exception& ex) + { + LogError("failed to process service node list: ", ex.what()); + } + } - // set down here so that the 1) we don't start updating until we're completely finished - // with the previous update; and 2) so that m_UpdatingList also guards m_LastUpdateHash - self->m_UpdatingList = false; - }, - request.dump()); - } + // set down here so that the 1) we don't start updating until we're completely finished + // with the previous update; and 2) so that m_UpdatingList also guards m_LastUpdateHash + self->m_UpdatingList = false; + }, + request.dump()); + } - void - LokidRpcClient::StartPings() - { - constexpr auto PingInterval = 30s; + void + LokidRpcClient::StartPings() + { + constexpr auto PingInterval = 30s; - auto router = m_Router.lock(); - if (not router) - return; + auto router = m_Router.lock(); + if (not router) + return; - auto makePingRequest = router->loop()->make_caller([self = shared_from_this()]() { - // send a ping - PubKey pk{}; - auto r = self->m_Router.lock(); - if (not r) - return; // router has gone away, maybe shutting down? - - pk = r->pubkey(); - - nlohmann::json payload = { - {"pubkey_ed25519", oxenc::to_hex(pk.begin(), pk.end())}, - {"version", {VERSION[0], VERSION[1], VERSION[2]}}}; - - if (auto err = r->OxendErrorState()) - payload["error"] = *err; - - self->Request( - "admin.lokinet_ping", - [](bool success, std::vector data) { - (void)data; - LogDebug("Received response for ping. Successful: ", success); - }, - payload.dump()); - - // subscribe to block updates - self->Request("sub.block", [](bool success, std::vector data) { - if (data.empty() or not success) - { - LogError("failed to subscribe to new blocks"); - return; - } - LogDebug("subscribed to new blocks: ", data[0]); - }); - // Trigger an update on a regular timer as well in case we missed a block notify for some - // reason (e.g. oxend restarts and loses the subscription); we poll using the last known - // hash so that the poll is very cheap (basically empty) if the block hasn't advanced. - self->UpdateServiceNodeList(); - }); + auto makePingRequest = router->loop()->make_caller([self = shared_from_this()]() { + // send a ping + PubKey pk{}; + auto r = self->m_Router.lock(); + if (not r) + return; // router has gone away, maybe shutting down? - // Fire one ping off right away to get things going. - makePingRequest(); - m_lokiMQ->add_timer(std::move(makePingRequest), PingInterval); - } + pk = r->pubkey(); - void - LokidRpcClient::HandleNewServiceNodeList(const nlohmann::json& j) - { - std::unordered_map keymap; - std::vector activeNodeList, decommNodeList, unfundedNodeList; - if (not j.is_array()) - throw std::runtime_error{ - "Invalid service node list: expected array of service node states"}; + nlohmann::json payload = { + {"pubkey_ed25519", oxenc::to_hex(pk.begin(), pk.end())}, + {"version", {VERSION[0], VERSION[1], VERSION[2]}}}; - for (auto& snode : j) - { - const auto ed_itr = snode.find("pubkey_ed25519"); - if (ed_itr == snode.end() or not ed_itr->is_string()) - continue; - const auto svc_itr = snode.find("service_node_pubkey"); - if (svc_itr == snode.end() or not svc_itr->is_string()) - continue; - const auto active_itr = snode.find("active"); - if (active_itr == snode.end() or not active_itr->is_boolean()) - continue; - const bool active = active_itr->get(); - const auto funded_itr = snode.find("funded"); - if (funded_itr == snode.end() or not funded_itr->is_boolean()) - continue; - const bool funded = funded_itr->get(); - - RouterID rid; - PubKey pk; - if (not rid.FromHex(ed_itr->get()) - or not pk.FromHex(svc_itr->get())) - continue; - - keymap[rid] = pk; - (active ? activeNodeList - : funded ? decommNodeList - : unfundedNodeList) - .push_back(std::move(rid)); - } + if (auto err = r->OxendErrorState()) + payload["error"] = *err; - if (activeNodeList.empty()) - { - LogWarn("got empty service node list, ignoring."); - return; - } + self->Request( + "admin.lokinet_ping", + [](bool success, std::vector data) { + (void)data; + LogDebug("Received response for ping. Successful: ", success); + }, + payload.dump()); - // inform router about the new list - if (auto router = m_Router.lock()) - { - auto& loop = router->loop(); - loop->call([this, - active = std::move(activeNodeList), - decomm = std::move(decommNodeList), - unfunded = std::move(unfundedNodeList), - keymap = std::move(keymap), - router = std::move(router)]() mutable { - m_KeyMap = std::move(keymap); - router->SetRouterWhitelist(active, decomm, unfunded); - }); - } - else - LogWarn("Cannot update whitelist: router object has gone away"); + // subscribe to block updates + self->Request("sub.block", [](bool success, std::vector data) { + if (data.empty() or not success) + { + LogError("failed to subscribe to new blocks"); + return; + } + LogDebug("subscribed to new blocks: ", data[0]); + }); + // Trigger an update on a regular timer as well in case we missed a block notify for some + // reason (e.g. oxend restarts and loses the subscription); we poll using the last known + // hash so that the poll is very cheap (basically empty) if the block hasn't advanced. + self->UpdateServiceNodeList(); + }); + + // Fire one ping off right away to get things going. + makePingRequest(); + m_lokiMQ->add_timer(std::move(makePingRequest), PingInterval); + } + + void + LokidRpcClient::HandleNewServiceNodeList(const nlohmann::json& j) + { + std::unordered_map keymap; + std::vector activeNodeList, decommNodeList, unfundedNodeList; + if (not j.is_array()) + throw std::runtime_error{"Invalid service node list: expected array of service node states"}; + + for (auto& snode : j) + { + const auto ed_itr = snode.find("pubkey_ed25519"); + if (ed_itr == snode.end() or not ed_itr->is_string()) + continue; + const auto svc_itr = snode.find("service_node_pubkey"); + if (svc_itr == snode.end() or not svc_itr->is_string()) + continue; + const auto active_itr = snode.find("active"); + if (active_itr == snode.end() or not active_itr->is_boolean()) + continue; + const bool active = active_itr->get(); + const auto funded_itr = snode.find("funded"); + if (funded_itr == snode.end() or not funded_itr->is_boolean()) + continue; + const bool funded = funded_itr->get(); + + RouterID rid; + PubKey pk; + if (not rid.FromHex(ed_itr->get()) + or not pk.FromHex(svc_itr->get())) + continue; + + keymap[rid] = pk; + (active ? activeNodeList + : funded ? decommNodeList + : unfundedNodeList) + .push_back(std::move(rid)); } - void - LokidRpcClient::InformConnection(RouterID router, bool success) + if (activeNodeList.empty()) { - if (auto r = m_Router.lock()) - { - r->loop()->call([router, success, this]() { - if (auto itr = m_KeyMap.find(router); itr != m_KeyMap.end()) - { - const nlohmann::json request = { - {"passed", success}, {"pubkey", itr->second.ToHex()}, {"type", "lokinet"}}; - Request( - "admin.report_peer_status", - [self = shared_from_this()](bool success, std::vector) { - if (not success) - { - LogError("Failed to report connection status to oxend"); - return; - } - LogDebug("reported connection status to core"); - }, - request.dump()); - } - }); - } + LogWarn("got empty service node list, ignoring."); + return; } - SecretKey - LokidRpcClient::ObtainIdentityKey() + // inform router about the new list + if (auto router = m_Router.lock()) { - std::promise promise; - Request( - "admin.get_service_privkeys", - [self = shared_from_this(), &promise](bool success, std::vector data) { - try + auto& loop = router->loop(); + loop->call([this, + active = std::move(activeNodeList), + decomm = std::move(decommNodeList), + unfunded = std::move(unfundedNodeList), + keymap = std::move(keymap), + router = std::move(router)]() mutable { + m_KeyMap = std::move(keymap); + router->set_router_whitelist(active, decomm, unfunded); + }); + } + else + LogWarn("Cannot update whitelist: router object has gone away"); + } + + void + LokidRpcClient::InformConnection(RouterID router, bool success) + { + if (auto r = m_Router.lock()) + { + r->loop()->call([router, success, this]() { + if (auto itr = m_KeyMap.find(router); itr != m_KeyMap.end()) + { + const nlohmann::json request = { + {"passed", success}, {"pubkey", itr->second.ToHex()}, {"type", "lokinet"}}; + Request( + "admin.report_peer_status", + [self = shared_from_this()](bool success, std::vector) { + if (not success) + { + LogError("Failed to report connection status to oxend"); + return; + } + LogDebug("reported connection status to core"); + }, + request.dump()); + } + }); + } + } + + SecretKey + LokidRpcClient::ObtainIdentityKey() + { + std::promise promise; + Request( + "admin.get_service_privkeys", + [self = shared_from_this(), &promise](bool success, std::vector data) { + try + { + if (not success) { - if (not success) - { - throw std::runtime_error( - "failed to get private key request " - "failed"); - } - if (data.empty() or data.size() < 2) - { - throw std::runtime_error( - "failed to get private key request " - "data empty"); - } - const auto j = nlohmann::json::parse(data[1]); - SecretKey k; - if (not k.FromHex(j.at("service_node_ed25519_privkey").get())) - { - throw std::runtime_error("failed to parse private key"); - } - promise.set_value(k); + throw std::runtime_error( + "failed to get private key request " + "failed"); } - catch (const std::exception& e) + if (data.empty() or data.size() < 2) { - LogWarn("Caught exception while trying to request admin keys: ", e.what()); - promise.set_exception(std::current_exception()); + throw std::runtime_error( + "failed to get private key request " + "data empty"); } - catch (...) + const auto j = nlohmann::json::parse(data[1]); + SecretKey k; + if (not k.FromHex(j.at("service_node_ed25519_privkey").get())) { - LogWarn("Caught non-standard exception while trying to request admin keys"); - promise.set_exception(std::current_exception()); + throw std::runtime_error("failed to parse private key"); } - }); - auto ftr = promise.get_future(); - return ftr.get(); - } + promise.set_value(k); + } + catch (const std::exception& e) + { + LogWarn("Caught exception while trying to request admin keys: ", e.what()); + promise.set_exception(std::current_exception()); + } + catch (...) + { + LogWarn("Caught non-standard exception while trying to request admin keys"); + promise.set_exception(std::current_exception()); + } + }); + auto ftr = promise.get_future(); + return ftr.get(); + } - void - LokidRpcClient::LookupLNSNameHash( - dht::Key_t namehash, - std::function)> resultHandler) - { - LogDebug("Looking Up LNS NameHash ", namehash); - const nlohmann::json req{{"type", 2}, {"name_hash", namehash.ToHex()}}; - Request( - "rpc.lns_resolve", - [this, resultHandler](bool success, std::vector data) { - std::optional maybe = std::nullopt; - if (success) + void + LokidRpcClient::LookupLNSNameHash( + dht::Key_t namehash, std::function)> resultHandler) + { + LogDebug("Looking Up LNS NameHash ", namehash); + const nlohmann::json req{{"type", 2}, {"name_hash", namehash.ToHex()}}; + Request( + "rpc.lns_resolve", + [this, resultHandler](bool success, std::vector data) { + std::optional maybe = std::nullopt; + if (success) + { + try { - try - { - service::EncryptedName result; - const auto j = nlohmann::json::parse(data[1]); - result.ciphertext = oxenc::from_hex(j["encrypted_value"].get()); - const auto nonce = oxenc::from_hex(j["nonce"].get()); - if (nonce.size() != result.nonce.size()) - { - throw std::invalid_argument{fmt::format( - "nonce size mismatch: {} != {}", nonce.size(), result.nonce.size())}; - } - - std::copy_n(nonce.data(), nonce.size(), result.nonce.data()); - maybe = result; - } - catch (std::exception& ex) + service::EncryptedName result; + const auto j = nlohmann::json::parse(data[1]); + result.ciphertext = oxenc::from_hex(j["encrypted_value"].get()); + const auto nonce = oxenc::from_hex(j["nonce"].get()); + if (nonce.size() != result.nonce.size()) { - LogError("failed to parse response from lns lookup: ", ex.what()); + throw std::invalid_argument{fmt::format( + "nonce size mismatch: {} != {}", nonce.size(), result.nonce.size())}; } + + std::copy_n(nonce.data(), nonce.size(), result.nonce.data()); + maybe = result; } - if (auto r = m_Router.lock()) + catch (std::exception& ex) { - r->loop()->call( - [resultHandler, maybe = std::move(maybe)]() { resultHandler(std::move(maybe)); }); + LogError("failed to parse response from lns lookup: ", ex.what()); } - }, - req.dump()); + } + if (auto r = m_Router.lock()) + { + r->loop()->call( + [resultHandler, maybe = std::move(maybe)]() { resultHandler(std::move(maybe)); }); + } + }, + req.dump()); + } + + void + LokidRpcClient::HandleGetPeerStats(oxenmq::Message& msg) + { + LogInfo("Got request for peer stats (size: ", msg.data.size(), ")"); + for (auto str : msg.data) + { + LogInfo(" :", str); } - void - LokidRpcClient::HandleGetPeerStats(oxenmq::Message& msg) + if (auto router = m_Router.lock()) { - LogInfo("Got request for peer stats (size: ", msg.data.size(), ")"); - for (auto str : msg.data) + if (not router->peer_db()) { - LogInfo(" :", str); + LogWarn("HandleGetPeerStats called when router has no peerDb set up."); + + // TODO: this can sometimes occur if lokid hits our API before we're done configuring + // (mostly an issue in a loopback testnet) + msg.send_reply("EAGAIN"); + return; } - if (auto router = m_Router.lock()) + try { - if (not router->peerDb()) + // msg.data[0] is expected to contain a bt list of router ids (in our preferred string + // format) + if (msg.data.empty()) { - LogWarn("HandleGetPeerStats called when router has no peerDb set up."); - - // TODO: this can sometimes occur if lokid hits our API before we're done configuring - // (mostly an issue in a loopback testnet) - msg.send_reply("EAGAIN"); + LogWarn("lokid requested peer stats with no request body"); + msg.send_reply("peer stats request requires list of router IDs"); return; } - try + std::vector routerIdStrings; + oxenc::bt_deserialize(msg.data[0], routerIdStrings); + + std::vector routerIds; + routerIds.reserve(routerIdStrings.size()); + + for (const auto& routerIdString : routerIdStrings) { - // msg.data[0] is expected to contain a bt list of router ids (in our preferred string - // format) - if (msg.data.empty()) + RouterID id; + if (not id.FromString(routerIdString)) { - LogWarn("lokid requested peer stats with no request body"); - msg.send_reply("peer stats request requires list of router IDs"); + LogWarn("lokid sent us an invalid router id: ", routerIdString); + msg.send_reply("Invalid router id"); return; } - std::vector routerIdStrings; - oxenc::bt_deserialize(msg.data[0], routerIdStrings); - - std::vector routerIds; - routerIds.reserve(routerIdStrings.size()); - - for (const auto& routerIdString : routerIdStrings) - { - RouterID id; - if (not id.FromString(routerIdString)) - { - LogWarn("lokid sent us an invalid router id: ", routerIdString); - msg.send_reply("Invalid router id"); - return; - } - - routerIds.push_back(std::move(id)); - } + routerIds.push_back(std::move(id)); + } - auto statsList = router->peerDb()->listPeerStats(routerIds); + auto statsList = router->peer_db()->listPeerStats(routerIds); - int32_t bufSize = - 256 + (statsList.size() * 1024); // TODO: tune this or allow to grow dynamically - auto buf = std::unique_ptr(new uint8_t[bufSize]); - llarp_buffer_t llarpBuf(buf.get(), bufSize); + int32_t bufSize = + 256 + (statsList.size() * 1024); // TODO: tune this or allow to grow dynamically + auto buf = std::unique_ptr(new uint8_t[bufSize]); + llarp_buffer_t llarpBuf(buf.get(), bufSize); - PeerStats::BEncodeList(statsList, &llarpBuf); + PeerStats::BEncodeList(statsList, &llarpBuf); - msg.send_reply( - std::string_view((const char*)llarpBuf.base, llarpBuf.cur - llarpBuf.base)); - } - catch (const std::exception& e) - { - LogError("Failed to handle get_peer_stats request: ", e.what()); - msg.send_reply("server error"); - } + msg.send_reply(std::string_view((const char*)llarpBuf.base, llarpBuf.cur - llarpBuf.base)); + } + catch (const std::exception& e) + { + LogError("Failed to handle get_peer_stats request: ", e.what()); + msg.send_reply("server error"); } } - } // namespace rpc -} // namespace llarp + } +} // namespace llarp::rpc diff --git a/llarp/rpc/lokid_rpc_client.hpp b/llarp/rpc/lokid_rpc_client.hpp index cbd9b459fa..becca7e29c 100644 --- a/llarp/rpc/lokid_rpc_client.hpp +++ b/llarp/rpc/lokid_rpc_client.hpp @@ -10,16 +10,14 @@ namespace llarp { - struct AbstractRouter; + struct Router; namespace rpc { - using LMQ_ptr = std::shared_ptr; - /// The LokidRpcClient uses loki-mq to talk to make API requests to lokid. struct LokidRpcClient : public std::enable_shared_from_this { - explicit LokidRpcClient(LMQ_ptr lmq, std::weak_ptr r); + explicit LokidRpcClient(std::shared_ptr lmq, std::weak_ptr r); /// Connect to lokid async void @@ -87,9 +85,9 @@ namespace llarp HandleNewBlock(oxenmq::Message& msg); std::optional m_Connection; - LMQ_ptr m_lokiMQ; + std::shared_ptr m_lokiMQ; - std::weak_ptr m_Router; + std::weak_ptr m_Router; std::atomic m_UpdatingList; std::string m_LastUpdateHash; diff --git a/llarp/rpc/rpc_request.hpp b/llarp/rpc/rpc_request.hpp index caf50d9f37..8801298c8c 100644 --- a/llarp/rpc/rpc_request.hpp +++ b/llarp/rpc/rpc_request.hpp @@ -7,7 +7,7 @@ #include "json_bt.hpp" #include #include -#include +#include #include #include #include diff --git a/llarp/rpc/rpc_request_definitions.hpp b/llarp/rpc/rpc_request_definitions.hpp index 565f34572e..340eb6c411 100644 --- a/llarp/rpc/rpc_request_definitions.hpp +++ b/llarp/rpc/rpc_request_definitions.hpp @@ -2,7 +2,6 @@ #include "rpc_request_decorators.hpp" #include "llarp/net/ip_range.hpp" -#include "llarp/router/abstractrouter.hpp" #include "llarp/router/route_poker.hpp" #include "llarp/service/address.hpp" #include "llarp/service/endpoint.hpp" diff --git a/llarp/rpc/rpc_server.cpp b/llarp/rpc/rpc_server.cpp index 746557f63e..ae7ac5f583 100644 --- a/llarp/rpc/rpc_server.cpp +++ b/llarp/rpc/rpc_server.cpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include #include @@ -77,7 +77,7 @@ namespace llarp::rpc } std::shared_ptr - GetEndpointByName(AbstractRouter& r, std::string name) + GetEndpointByName(Router& r, std::string name) { if (r.IsServiceNode()) { @@ -99,11 +99,11 @@ namespace llarp::rpc regs.emplace(RPC::name, std::move(cback)); } - RPCServer::RPCServer(LMQ_ptr lmq, AbstractRouter& r) + RPCServer::RPCServer(LMQ_ptr lmq, Router& r) : m_LMQ{std::move(lmq)}, m_Router(r), log_subs{*m_LMQ, llarp::logRingBuffer} { // copied logic loop as placeholder - for (const auto& addr : r.GetConfig()->api.m_rpcBindAddresses) + for (const auto& addr : r.get_config()->api.m_rpcBindAddresses) { m_LMQ->listen_plain(addr.zmq_address()); LogInfo("Bound RPC server to ", addr.full_address()); diff --git a/llarp/rpc/rpc_server.hpp b/llarp/rpc/rpc_server.hpp index bda5d6888a..56bb1f11e0 100644 --- a/llarp/rpc/rpc_server.hpp +++ b/llarp/rpc/rpc_server.hpp @@ -13,7 +13,7 @@ namespace llarp { - struct AbstractRouter; + struct Router; } // namespace llarp namespace @@ -81,7 +81,7 @@ namespace llarp::rpc class RPCServer { public: - explicit RPCServer(LMQ_ptr, AbstractRouter&); + explicit RPCServer(LMQ_ptr, Router&); ~RPCServer() = default; void @@ -118,7 +118,7 @@ namespace llarp::rpc invoke(Config& config); LMQ_ptr m_LMQ; - AbstractRouter& m_Router; + Router& m_Router; oxen::log::PubsubLogger log_subs; }; diff --git a/llarp/service/auth.cpp b/llarp/service/auth.cpp index 1c6ce91fb9..90faef6f3f 100644 --- a/llarp/service/auth.cpp +++ b/llarp/service/auth.cpp @@ -1,7 +1,7 @@ #include "auth.hpp" #include -#include +#include #include "protocol.hpp" #include #include @@ -87,7 +87,7 @@ namespace llarp::service { const std::set m_Files; const AuthFileType m_Type; - AbstractRouter* const m_Router; + Router* const m_Router; mutable util::Mutex m_Access; std::unordered_set m_Pending; /// returns an auth result for a auth info challange, opens every file until it finds a token @@ -131,7 +131,7 @@ namespace llarp::service } public: - FileAuthPolicy(AbstractRouter* r, std::set files, AuthFileType filetype) + FileAuthPolicy(Router* r, std::set files, AuthFileType filetype) : m_Files{std::move(files)}, m_Type{filetype}, m_Router{r} {} @@ -153,7 +153,7 @@ namespace llarp::service } if (msg->proto == ProtocolType::Auth) { - m_Router->QueueDiskIO( + m_Router->queue_disk_io( [self = shared_from_this(), auth = AuthInfo{std::string{ reinterpret_cast(msg->payload.data()), msg->payload.size()}}, @@ -180,7 +180,7 @@ namespace llarp::service }; std::shared_ptr - MakeFileAuthPolicy(AbstractRouter* r, std::set files, AuthFileType filetype) + MakeFileAuthPolicy(Router* r, std::set files, AuthFileType filetype) { return std::make_shared(r, std::move(files), filetype); } diff --git a/llarp/service/auth.hpp b/llarp/service/auth.hpp index b87f9eab7e..f357ca86b8 100644 --- a/llarp/service/auth.hpp +++ b/llarp/service/auth.hpp @@ -95,6 +95,6 @@ namespace llarp::service /// make an IAuthPolicy that reads out of a static file std::shared_ptr - MakeFileAuthPolicy(AbstractRouter*, std::set files, AuthFileType fileType); + MakeFileAuthPolicy(Router*, std::set files, AuthFileType fileType); } // namespace llarp::service diff --git a/llarp/service/context.cpp b/llarp/service/context.cpp index 4b7c00bb44..68b62c0144 100644 --- a/llarp/service/context.cpp +++ b/llarp/service/context.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include "endpoint.hpp" #include @@ -14,29 +14,28 @@ namespace llarp static auto logcat = log::Cat("service"); namespace { - using EndpointConstructor = - std::function; + using EndpointConstructor = std::function; using EndpointConstructors = std::map; static EndpointConstructors endpointConstructors = { {"tun", - [](AbstractRouter* r, service::Context* c) { + [](Router* r, service::Context* c) { return std::make_shared(r, c); }}, {"android", - [](AbstractRouter* r, service::Context* c) { + [](Router* r, service::Context* c) { return std::make_shared(r, c); }}, {"ios", - [](AbstractRouter* r, service::Context* c) { + [](Router* r, service::Context* c) { return std::make_shared(r, c); }}, - {"null", [](AbstractRouter* r, service::Context* c) { + {"null", [](Router* r, service::Context* c) { return std::make_shared(r, c); }}}; } // namespace - Context::Context(AbstractRouter* r) : m_Router(r) + Context::Context(Router* r) : m_Router(r) {} Context::~Context() = default; diff --git a/llarp/service/context.hpp b/llarp/service/context.hpp index 3694d9772b..ce5ff8e8ae 100644 --- a/llarp/service/context.hpp +++ b/llarp/service/context.hpp @@ -16,7 +16,7 @@ namespace llarp /// only supports one endpoint per instance struct Context { - explicit Context(AbstractRouter* r); + explicit Context(Router* r); ~Context(); void @@ -66,7 +66,7 @@ namespace llarp StartAll(); private: - AbstractRouter* const m_Router; + Router* const m_Router; std::unordered_map> m_Endpoints; std::list> m_Stopped; }; diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 8751718004..6cd921fb0f 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -48,7 +48,7 @@ namespace llarp { static auto logcat = log::Cat("endpoint"); - Endpoint::Endpoint(AbstractRouter* r, Context* parent) + Endpoint::Endpoint(Router* r, Context* parent) : path::Builder{r, 3, path::default_len} , context{parent} , m_InboundTrafficQueue{512} @@ -170,7 +170,7 @@ namespace llarp LogWarn("failed to generate introset for endpoint ", Name()); return; } - if (PublishIntroSet(*maybe, Router())) + if (PublishIntroSet(*maybe, router())) { LogInfo("(re)publishing introset for endpoint ", Name()); } @@ -181,7 +181,7 @@ namespace llarp } bool - Endpoint::IsReady() const + Endpoint::is_ready() const { const auto now = Now(); if (introSet().intros.empty()) @@ -308,7 +308,7 @@ namespace llarp }; // handles when we resolved a .snode - auto handleResolvedSNodeName = [resultHandler, nodedb = Router()->nodedb()](auto router_id) { + auto handleResolvedSNodeName = [resultHandler, nodedb = router()->node_db()](auto router_id) { std::vector result{}; if (auto maybe_rc = nodedb->Get(router_id)) { @@ -674,7 +674,7 @@ namespace llarp const auto& keyfile = m_state->m_Keyfile; if (!keyfile.empty()) { - m_Identity.EnsureKeys(keyfile, Router()->keyManager()->needBackup()); + m_Identity.EnsureKeys(keyfile, router()->key_manager()->needBackup()); } else { @@ -710,7 +710,7 @@ namespace llarp Endpoint::~Endpoint() = default; bool - Endpoint::PublishIntroSet(const EncryptedIntroSet& introset, AbstractRouter* r) + Endpoint::PublishIntroSet(const EncryptedIntroSet& introset, Router* r) { const auto paths = GetManyPathsWithUniqueEndpoints( this, @@ -734,7 +734,7 @@ namespace llarp { for (size_t i = 0; i < llarp::dht::IntroSetRequestsPerRelay; ++i) { - r->NotifyRouterEvent( + r->notify_router_event( r->pubkey(), llarp::dht::Key_t{introset.derivedSigningKey.as_array()}, RouterID(path->hops[path->hops.size() - 1].rc.pubkey), @@ -815,10 +815,7 @@ namespace llarp bool Endpoint::PublishIntroSetVia( - const EncryptedIntroSet& introset, - AbstractRouter* r, - path::Path_ptr path, - uint64_t relayOrder) + const EncryptedIntroSet& introset, Router* r, path::Path_ptr path, uint64_t relayOrder) { auto job = new PublishIntroSetJob(this, GenTXID(), introset, relayOrder, PublishIntrosetTimeout); @@ -879,9 +876,9 @@ namespace llarp std::unordered_set exclude; ForEachPath([&exclude](auto path) { exclude.insert(path->Endpoint()); }); const auto maybe = - m_router->nodedb()->GetRandom([exclude, r = m_router](const auto& rc) -> bool { + m_router->node_db()->GetRandom([exclude, r = m_router](const auto& rc) -> bool { return exclude.count(rc.pubkey) == 0 - and not r->routerProfiling().IsBadForPath(rc.pubkey); + and not r->router_profiling().IsBadForPath(rc.pubkey); }); if (not maybe.has_value()) return std::nullopt; @@ -945,10 +942,10 @@ namespace llarp { for (auto& rc : msg->foundRCs) { - Router()->QueueWork([this, rc, msg]() mutable { + router()->queue_work([this, rc, msg]() mutable { bool valid = rc.Verify(llarp::time_now_ms()); - Router()->loop()->call([this, valid, rc = std::move(rc), msg] { - Router()->nodedb()->PutIfNewer(rc); + router()->loop()->call([this, valid, rc = std::move(rc), msg] { + router()->node_db()->PutIfNewer(rc); HandleVerifyGotRouter(msg, rc.pubkey, valid); }); }); @@ -1037,7 +1034,7 @@ namespace llarp bool Endpoint::ReadyForNetwork() const { - return IsReady() and ReadyToDoLookup(GetUniqueEndpointsForLookup().size()); + return is_ready() and ReadyToDoLookup(GetUniqueEndpointsForLookup().size()); } bool @@ -1134,37 +1131,37 @@ namespace llarp } void - Endpoint::EnsureRouterIsKnown(const RouterID& router) + Endpoint::EnsureRouterIsKnown(const RouterID& rid) { - if (router.IsZero()) + if (rid.IsZero()) return; - if (!Router()->nodedb()->Has(router)) + if (!router()->node_db()->Has(rid)) { - LookupRouterAnon(router, nullptr); + LookupRouterAnon(rid, nullptr); } } bool - Endpoint::LookupRouterAnon(RouterID router, RouterLookupHandler handler) + Endpoint::LookupRouterAnon(RouterID rid, RouterLookupHandler handler) { using llarp::dht::FindRouterMessage; auto& routers = m_state->m_PendingRouters; - if (routers.find(router) == routers.end()) + if (routers.find(rid) == routers.end()) { - auto path = GetEstablishedPathClosestTo(router); + auto path = GetEstablishedPathClosestTo(rid); routing::PathDHTMessage msg; auto txid = GenTXID(); - msg.dht_msgs.emplace_back(std::make_unique(txid, router)); + msg.dht_msgs.emplace_back(std::make_unique(txid, rid)); if (path) msg.sequence_number = path->NextSeqNo(); - if (path && path->SendRoutingMessage(msg, Router())) + if (path && path->SendRoutingMessage(msg, router())) { - RouterLookupJob job{this, [handler, router, nodedb = m_router->nodedb()](auto results) { + RouterLookupJob job{this, [handler, rid, nodedb = m_router->node_db()](auto results) { if (results.empty()) { - LogInfo("could not find ", router, ", remove it from nodedb"); - nodedb->Remove(router); + LogInfo("could not find ", rid, ", remove it from nodedb"); + nodedb->Remove(rid); } if (handler) handler(results); @@ -1174,9 +1171,9 @@ namespace llarp auto dhtMsg = dynamic_cast(msg.dht_msgs[0].get()); assert(dhtMsg != nullptr); - m_router->NotifyRouterEvent(m_router->pubkey(), *dhtMsg); + m_router->notify_router_event(router()->pubkey(), *dhtMsg); - routers.emplace(router, std::move(job)); + routers.emplace(rid, std::move(job)); return true; } } @@ -1219,7 +1216,7 @@ namespace llarp Endpoint::QueueRecvData(RecvDataEvent ev) { m_RecvQueue.tryPushBack(std::move(ev)); - Router()->TriggerPump(); + router()->TriggerPump(); } bool @@ -1291,7 +1288,7 @@ namespace llarp || (msg->proto == ProtocolType::QUIC and m_quic)) { m_InboundTrafficQueue.tryPushBack(std::move(msg)); - Router()->TriggerPump(); + router()->TriggerPump(); return true; } if (msg->proto == ProtocolType::Control) @@ -1317,7 +1314,7 @@ namespace llarp } else { - Router()->loop()->call([h = std::move(hook)] { h({AuthResultCode::eAuthAccepted, "OK"}); }); + router()->loop()->call([h = std::move(hook)] { h({AuthResultCode::eAuthAccepted, "OK"}); }); } } @@ -1416,7 +1413,7 @@ namespace llarp RemoveConvoTag(frame.convo_tag); return true; } - if (not frame.AsyncDecryptAndVerify(Router()->loop(), p, m_Identity, this)) + if (not frame.AsyncDecryptAndVerify(router()->loop(), p, m_Identity, this)) { ResetConvoTag(frame.convo_tag, p, frame.path_id); } @@ -1426,7 +1423,7 @@ namespace llarp void Endpoint::HandlePathDied(path::Path_ptr p) { - m_router->routerProfiling().MarkPathTimeout(p.get()); + m_router->router_profiling().MarkPathTimeout(p.get()); ManualRebuild(1); path::Builder::HandlePathDied(p); RegenAndPublishIntroSet(); @@ -1448,7 +1445,7 @@ namespace llarp { // tell all our existing remote sessions about this introset update - const auto now = Router()->Now(); + const auto now = router()->Now(); auto& lookups = m_state->m_PendingServiceLookups; if (introset) { @@ -1613,7 +1610,7 @@ namespace llarp " order=", order); order++; - if (job->SendRequestViaPath(path, Router())) + if (job->SendRequestViaPath(path, router())) { hookAdded = true; } @@ -1662,7 +1659,7 @@ namespace llarp ConvoTag{maybe->as_array()}, pkt.ConstBuffer(), ProtocolType::TrafficV4, 0); return false; }, - Router(), + router(), 1, numHops, false, @@ -1739,7 +1736,7 @@ namespace llarp if (s) { s->SendPacketToRemote(pkt->ConstBuffer(), t); - Router()->TriggerPump(); + router()->TriggerPump(); } }); return true; @@ -1782,7 +1779,7 @@ namespace llarp queue.pop(); } - auto router = Router(); + auto r = router(); // TODO: locking on this container for (const auto& [addr, outctx] : m_state->m_RemoteSessions) { @@ -1790,7 +1787,7 @@ namespace llarp outctx->Pump(now); } // TODO: locking on this container - for (const auto& [router, session] : m_state->m_SNodeSessions) + for (const auto& [r, session] : m_state->m_SNodeSessions) session->FlushUpstream(); // send queue flush @@ -1798,11 +1795,11 @@ namespace llarp { SendEvent_t item = m_SendQueue.popFront(); item.first->sequence_number = item.second->NextSeqNo(); - if (item.second->SendRoutingMessage(*item.first, router)) + if (item.second->SendRoutingMessage(*item.first, r)) ConvoTagTX(item.first->protocol_frame_msg.convo_tag); } - UpstreamFlush(router); + UpstreamFlush(r); } std::optional @@ -2006,7 +2003,7 @@ namespace llarp f.sequence_number = m->seqno; f.path_id = p->intro.path_id; transfer->path_id = replyIntro.path_id; - Router()->QueueWork([transfer, p, m, K, this]() { + router()->queue_work([transfer, p, m, K, this]() { if (not transfer->protocol_frame_msg.EncryptAndSign(*m, K, m_Identity)) { LogError( @@ -2015,7 +2012,7 @@ namespace llarp return; } m_SendQueue.tryPushBack(SendEvent_t{transfer, p}); - Router()->TriggerPump(); + router()->TriggerPump(); }); return true; } @@ -2107,8 +2104,8 @@ namespace llarp < requiredPaths; } - AbstractRouter* - Endpoint::Router() + Router* + Endpoint::router() { return m_state->m_Router; } @@ -2116,7 +2113,7 @@ namespace llarp const EventLoop_ptr& Endpoint::Loop() { - return Router()->loop(); + return router()->loop(); } void diff --git a/llarp/service/endpoint.hpp b/llarp/service/endpoint.hpp index 4c24b43926..422d11c1e0 100644 --- a/llarp/service/endpoint.hpp +++ b/llarp/service/endpoint.hpp @@ -67,14 +67,14 @@ namespace llarp public IDataHandler, public EndpointBase { - Endpoint(AbstractRouter* r, Context* parent); + Endpoint(Router* r, Context* parent); ~Endpoint() override; /// return true if we are ready to recv packets from the void. /// really should be ReadyForInboundTraffic() but the diff is HUGE and we need to rewrite this /// component anyways. bool - IsReady() const; + is_ready() const; void QueueRecvData(RecvDataEvent ev) override; @@ -146,8 +146,8 @@ namespace llarp const EventLoop_ptr& Loop() override; - AbstractRouter* - Router(); + Router* + router(); virtual bool LoadKeyFile(); @@ -189,11 +189,11 @@ namespace llarp } bool - PublishIntroSet(const EncryptedIntroSet& i, AbstractRouter* r) override; + PublishIntroSet(const EncryptedIntroSet& i, Router* r) override; bool PublishIntroSetVia( - const EncryptedIntroSet& i, AbstractRouter* r, path::Path_ptr p, uint64_t relayOrder); + const EncryptedIntroSet& i, Router* r, path::Path_ptr p, uint64_t relayOrder); bool HandleGotIntroMessage(std::shared_ptr msg) override; diff --git a/llarp/service/endpoint_state.hpp b/llarp/service/endpoint_state.hpp index 7cbae08945..4764effbbb 100644 --- a/llarp/service/endpoint_state.hpp +++ b/llarp/service/endpoint_state.hpp @@ -26,7 +26,7 @@ namespace llarp { std::set m_SnodeBlacklist; - AbstractRouter* m_Router; + Router* m_Router; std::string m_Keyfile; std::string m_Name; std::string m_NetNS; diff --git a/llarp/service/lookup.cpp b/llarp/service/lookup.cpp index e1895b0516..ff6266a858 100644 --- a/llarp/service/lookup.cpp +++ b/llarp/service/lookup.cpp @@ -2,12 +2,12 @@ #include #include -#include +#include #include namespace llarp { - struct AbstractRouter; + struct Router; namespace service { @@ -19,7 +19,7 @@ namespace llarp } bool - IServiceLookup::SendRequestViaPath(path::Path_ptr path, AbstractRouter* r) + IServiceLookup::SendRequestViaPath(path::Path_ptr path, Router* r) { auto msg = BuildRequestMessage(); if (!msg) diff --git a/llarp/service/lookup.hpp b/llarp/service/lookup.hpp index 4a485c1de6..8a15a48b0e 100644 --- a/llarp/service/lookup.hpp +++ b/llarp/service/lookup.hpp @@ -69,7 +69,7 @@ namespace llarp /// build a new request message and send it via a path virtual bool - SendRequestViaPath(path::Path_ptr p, AbstractRouter* r); + SendRequestViaPath(path::Path_ptr p, Router* r); ILookupHolder* m_parent; uint64_t txid; diff --git a/llarp/service/outbound_context.cpp b/llarp/service/outbound_context.cpp index a461b88ebd..672f00cf9c 100644 --- a/llarp/service/outbound_context.cpp +++ b/llarp/service/outbound_context.cpp @@ -5,7 +5,7 @@ #include "endpoint_util.hpp" #include "protocol_type.hpp" -#include +#include #include #include #include @@ -53,7 +53,7 @@ namespace llarp::service constexpr auto OutboundContextNumPaths = 4; OutboundContext::OutboundContext(const IntroSet& introset, Endpoint* parent) - : path::Builder{parent->Router(), OutboundContextNumPaths, parent->numHops} + : path::Builder{parent->router(), OutboundContextNumPaths, parent->numHops} , SendContext{introset.addressKeys, {}, this, parent} , location{introset.addressKeys.Addr().ToKey()} , addr{introset.addressKeys.Addr()} @@ -266,7 +266,7 @@ namespace llarp::service // ensure we have a sender put for this convo tag m_DataHandler->PutSenderFor(currentConvoTag, currentIntroSet.addressKeys, false); // encrypt frame async - m_Endpoint->Router()->QueueWork([ex, frame] { return AsyncKeyExchange::Encrypt(ex, frame); }); + m_Endpoint->router()->queue_work([ex, frame] { return AsyncKeyExchange::Encrypt(ex, frame); }); LogInfo(Name(), " send intro frame T=", currentConvoTag); } @@ -302,7 +302,7 @@ namespace llarp::service m_Endpoint->GenTXID(), (IntrosetUpdateInterval / 2) + (2 * path->intro.latency) + IntrosetLookupGraceInterval); relayOrder++; - if (job->SendRequestViaPath(path, m_Endpoint->Router())) + if (job->SendRequestViaPath(path, m_Endpoint->router())) updatingIntroSet = true; } } diff --git a/llarp/service/protocol.cpp b/llarp/service/protocol.cpp index d9abccc851..d3d4d63e72 100644 --- a/llarp/service/protocol.cpp +++ b/llarp/service/protocol.cpp @@ -5,7 +5,7 @@ #include #include #include "endpoint.hpp" -#include +#include #include namespace llarp::service @@ -412,7 +412,7 @@ namespace llarp::service auto dh = std::make_shared( loop, localIdent, handler, msg, *this, recvPath->intro); dh->path = recvPath; - handler->Router()->QueueWork([dh = std::move(dh)] { return AsyncFrameDecrypt::Work(dh); }); + handler->router()->queue_work([dh = std::move(dh)] { return AsyncFrameDecrypt::Work(dh); }); return true; } @@ -447,7 +447,7 @@ namespace llarp::service loop->call([msg, hook]() { hook(msg); }); } }; - handler->Router()->QueueWork( + handler->router()->queue_work( [v, msg = std::move(msg), recvPath = std::move(recvPath), callback, handler]() { auto resetTag = [handler, tag = v->frame.convo_tag, from = v->frame.path_id, path = recvPath]() { @@ -508,7 +508,7 @@ namespace llarp::service bool ProtocolFrameMessage::handle_message( - routing::AbstractRoutingMessageHandler* h, AbstractRouter* /*r*/) const + routing::AbstractRoutingMessageHandler* h, Router* /*r*/) const { return h->HandleHiddenServiceFrame(*this); } diff --git a/llarp/service/protocol.hpp b/llarp/service/protocol.hpp index adb8daeaa6..ef9757a99c 100644 --- a/llarp/service/protocol.hpp +++ b/llarp/service/protocol.hpp @@ -172,7 +172,7 @@ namespace llarp Verify(const ServiceInfo& from) const; bool - handle_message(routing::AbstractRoutingMessageHandler* h, AbstractRouter* r) const override; + handle_message(routing::AbstractRoutingMessageHandler* h, Router* r) const override; }; } // namespace service } // namespace llarp diff --git a/llarp/service/sendcontext.cpp b/llarp/service/sendcontext.cpp index 4572b0c985..d0ca164643 100644 --- a/llarp/service/sendcontext.cpp +++ b/llarp/service/sendcontext.cpp @@ -1,6 +1,6 @@ #include "sendcontext.hpp" -#include +#include #include #include "endpoint.hpp" #include @@ -30,7 +30,7 @@ namespace llarp::service std::make_shared(*msg, remoteIntro.path_id), path)) == thread::QueueReturn::Success) { - m_Endpoint->Router()->TriggerPump(); + m_Endpoint->router()->TriggerPump(); return true; } return false; @@ -39,7 +39,7 @@ namespace llarp::service void SendContext::FlushUpstream() { - auto r = m_Endpoint->Router(); + auto r = m_Endpoint->router(); std::unordered_set flushpaths; auto rttRMS = 0ms; while (auto maybe = m_SendQueue.tryPopFront()) @@ -112,7 +112,7 @@ namespace llarp::service m->sender = m_Endpoint->GetIdentity().pub; m->tag = f->convo_tag; m->PutBuffer(payload); - m_Endpoint->Router()->QueueWork([f, m, shared, path, this] { + m_Endpoint->router()->queue_work([f, m, shared, path, this] { if (not f->EncryptAndSign(*m, shared, m_Endpoint->GetIdentity())) { LogError(m_PathSet->Name(), " failed to sign message"); diff --git a/llarp/tooling/hive_context.cpp b/llarp/tooling/hive_context.cpp index c029d7ecb3..130fe28e0f 100644 --- a/llarp/tooling/hive_context.cpp +++ b/llarp/tooling/hive_context.cpp @@ -7,7 +7,7 @@ namespace tooling HiveContext::HiveContext(RouterHive* hive) : m_hive(hive) {} - std::shared_ptr + std::shared_ptr HiveContext::makeRouter(const llarp::EventLoop_ptr& loop) { return std::make_shared(loop, makeVPNPlatform(), m_hive); diff --git a/llarp/tooling/hive_context.hpp b/llarp/tooling/hive_context.hpp index 99963a90c3..c9fd3a80a4 100644 --- a/llarp/tooling/hive_context.hpp +++ b/llarp/tooling/hive_context.hpp @@ -11,7 +11,7 @@ namespace tooling { HiveContext(RouterHive* hive); - std::shared_ptr + std::shared_ptr makeRouter(const llarp::EventLoop_ptr& loop) override; /// Get this context's router as a HiveRouter. diff --git a/llarp/tooling/router_hive.cpp b/llarp/tooling/router_hive.cpp index d58a0608ad..ea77071e28 100644 --- a/llarp/tooling/router_hive.cpp +++ b/llarp/tooling/router_hive.cpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include diff --git a/llarp/vpn/android.hpp b/llarp/vpn/android.hpp index 3364e75fa2..3cbe25e180 100644 --- a/llarp/vpn/android.hpp +++ b/llarp/vpn/android.hpp @@ -88,7 +88,7 @@ namespace llarp::vpn {} std::shared_ptr - ObtainInterface(InterfaceInfo info, AbstractRouter*) override + ObtainInterface(InterfaceInfo info, Router*) override { return std::make_shared(std::move(info), fd); } diff --git a/llarp/vpn/linux.hpp b/llarp/vpn/linux.hpp index cfc99cdc80..d39e11a7b5 100644 --- a/llarp/vpn/linux.hpp +++ b/llarp/vpn/linux.hpp @@ -18,7 +18,7 @@ #include -#include +#include #include #include @@ -442,7 +442,7 @@ namespace llarp::vpn public: std::shared_ptr - ObtainInterface(InterfaceInfo info, AbstractRouter*) override + ObtainInterface(InterfaceInfo info, Router*) override { return std::make_shared(std::move(info)); }; diff --git a/llarp/vpn/platform.hpp b/llarp/vpn/platform.hpp index 9ae880bb9a..0885518e49 100644 --- a/llarp/vpn/platform.hpp +++ b/llarp/vpn/platform.hpp @@ -11,7 +11,7 @@ namespace llarp { struct Context; - struct AbstractRouter; + struct Router; } // namespace llarp namespace llarp::vpn @@ -123,7 +123,7 @@ namespace llarp::vpn /// get a new network interface fully configured given the interface info /// blocks until ready, throws on error virtual std::shared_ptr - ObtainInterface(InterfaceInfo info, AbstractRouter* router) = 0; + ObtainInterface(InterfaceInfo info, Router* router) = 0; public: Platform() = default; @@ -133,7 +133,7 @@ namespace llarp::vpn /// create and start a network interface inline std::shared_ptr - CreateInterface(InterfaceInfo info, AbstractRouter* router) + CreateInterface(InterfaceInfo info, Router* router) { if (auto netif = ObtainInterface(std::move(info), router)) { diff --git a/llarp/vpn/win32.cpp b/llarp/vpn/win32.cpp index f6f4a452e6..2027076ba8 100644 --- a/llarp/vpn/win32.cpp +++ b/llarp/vpn/win32.cpp @@ -111,7 +111,7 @@ namespace llarp::win32 } std::shared_ptr - VPNPlatform::ObtainInterface(InterfaceInfo info, AbstractRouter* router) + VPNPlatform::ObtainInterface(InterfaceInfo info, Router* router) { return wintun::make_interface(std::move(info), router); } diff --git a/llarp/vpn/win32.hpp b/llarp/vpn/win32.hpp index 40ea98e33e..ac52489352 100644 --- a/llarp/vpn/win32.hpp +++ b/llarp/vpn/win32.hpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include @@ -63,7 +63,7 @@ namespace llarp::win32 DelDefaultRouteViaInterface(NetworkInterface& vpn) override; std::shared_ptr - ObtainInterface(InterfaceInfo info, AbstractRouter* router) override; + ObtainInterface(InterfaceInfo info, Router* router) override; std::shared_ptr create_packet_io( diff --git a/llarp/win32/wintun.cpp b/llarp/win32/wintun.cpp index ca77c61fa4..10569a69e6 100644 --- a/llarp/win32/wintun.cpp +++ b/llarp/win32/wintun.cpp @@ -10,7 +10,7 @@ extern "C" #include "guid.hpp" #include #include -#include +#include #include #include #include @@ -273,7 +273,7 @@ namespace llarp::win32 class WintunInterface : public vpn::NetworkInterface { - AbstractRouter* const _router; + Router* const _router; std::shared_ptr _adapter; std::shared_ptr _session; thread::Queue _recv_queue; @@ -284,7 +284,7 @@ namespace llarp::win32 static inline constexpr size_t packet_queue_length = 1024; public: - WintunInterface(vpn::InterfaceInfo info, AbstractRouter* router) + WintunInterface(vpn::InterfaceInfo info, Router* router) : vpn::NetworkInterface{std::move(info)} , _router{router} , _adapter{std::make_shared(m_Info.ifname)} @@ -385,7 +385,7 @@ namespace llarp::win32 namespace wintun { std::shared_ptr - make_interface(const llarp::vpn::InterfaceInfo& info, llarp::AbstractRouter* r) + make_interface(const llarp::vpn::InterfaceInfo& info, llarp::Router* r) { WintunInitialize(); return std::static_pointer_cast( diff --git a/llarp/win32/wintun.hpp b/llarp/win32/wintun.hpp index 1d2e7a7dc7..9ae7834f3c 100644 --- a/llarp/win32/wintun.hpp +++ b/llarp/win32/wintun.hpp @@ -4,7 +4,7 @@ namespace llarp { - struct AbstractRouter; + struct Router; } namespace llarp::vpn @@ -17,6 +17,6 @@ namespace llarp::win32::wintun { /// makes a new vpn interface with a wintun context given info and a router pointer std::shared_ptr - make_interface(const vpn::InterfaceInfo& info, AbstractRouter* router); + make_interface(const vpn::InterfaceInfo& info, Router* router); } // namespace llarp::win32::wintun diff --git a/pybind/common.hpp b/pybind/common.hpp index 83769d2c7f..655dccf06c 100644 --- a/pybind/common.hpp +++ b/pybind/common.hpp @@ -21,7 +21,7 @@ namespace llarp CryptoTypes_Init(py::module& mod); void - AbstractRouter_Init(py::module& mod); + Router_Init(py::module& mod); void RouterID_Init(py::module& mod); diff --git a/pybind/llarp/handlers/pyhandler.hpp b/pybind/llarp/handlers/pyhandler.hpp index 3f712dcc68..db90076aff 100644 --- a/pybind/llarp/handlers/pyhandler.hpp +++ b/pybind/llarp/handlers/pyhandler.hpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include namespace llarp { diff --git a/pybind/llarp/router.cpp b/pybind/llarp/router.cpp index 04fe8b0bc6..c32d51e9fd 100644 --- a/pybind/llarp/router.cpp +++ b/pybind/llarp/router.cpp @@ -1,17 +1,17 @@ #include -#include +#include #include namespace llarp { void - AbstractRouter_Init(py::module& mod) + Router_Init(py::module& mod) { - py::class_>(mod, "AbstractRouter") - .def("rc", &AbstractRouter::rc) - .def("Stop", &AbstractRouter::Stop) - .def("peerDb", &AbstractRouter::peerDb); + py::class_>(mod, "Router") + .def("rc", &Router::rc) + .def("Stop", &Router::Stop) + .def("peerDb", &Router::peerDb); } } // namespace llarp @@ -21,7 +21,7 @@ namespace tooling void HiveRouter_Init(py::module& mod) { - py::class_>(mod, "HiveRouter") + py::class_>(mod, "HiveRouter") .def("disableGossiping", &HiveRouter::disableGossiping) .def("enableGossiping", &HiveRouter::enableGossiping); } diff --git a/pybind/llarp/tooling/router_hive.cpp b/pybind/llarp/tooling/router_hive.cpp index cae413113d..0eabc7e334 100644 --- a/pybind/llarp/tooling/router_hive.cpp +++ b/pybind/llarp/tooling/router_hive.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include namespace tooling diff --git a/pybind/module.cpp b/pybind/module.cpp index d122c19b5d..dc75ace23b 100644 --- a/pybind/module.cpp +++ b/pybind/module.cpp @@ -5,7 +5,7 @@ PYBIND11_MODULE(pyllarp, m) { tooling::RouterHive_Init(m); tooling::RouterEvent_Init(m); - llarp::AbstractRouter_Init(m); + llarp::Router_Init(m); tooling::HiveRouter_Init(m); llarp::PeerDb_Init(m); llarp::PeerStats_Init(m); diff --git a/test/mocks/mock_context.hpp b/test/mocks/mock_context.hpp index b24e929a34..e25e0ef26b 100644 --- a/test/mocks/mock_context.hpp +++ b/test/mocks/mock_context.hpp @@ -17,10 +17,10 @@ namespace mocks loop = std::shared_ptr{const_cast(&_net), [](Network*) {}}; } - std::shared_ptr + std::shared_ptr makeRouter(const std::shared_ptr&) override { - return std::static_pointer_cast( + return std::static_pointer_cast( std::make_shared(_net, makeVPNPlatform())); } diff --git a/test/mocks/mock_vpn.hpp b/test/mocks/mock_vpn.hpp index 9e7a3f374c..22cc4bcdbd 100644 --- a/test/mocks/mock_vpn.hpp +++ b/test/mocks/mock_vpn.hpp @@ -47,7 +47,7 @@ namespace mocks {} virtual std::shared_ptr - ObtainInterface(llarp::vpn::InterfaceInfo info, llarp::AbstractRouter*) override + ObtainInterface(llarp::vpn::InterfaceInfo info, llarp::Router*) override { return std::make_shared(info); }; From bfa96297799bf2329cd59804f4a8cca3bcf8b7eb Mon Sep 17 00:00:00 2001 From: dr7ana Date: Mon, 18 Sep 2023 14:50:07 -0700 Subject: [PATCH 036/312] More carving + libquic bump - bumped libquic to begin implementing dependent features on connection open/close signals - more gutting of interface classes --- external/oxen-libquic | 2 +- llarp/CMakeLists.txt | 2 +- llarp/exit/endpoint.hpp | 2 +- llarp/link/endpoint.hpp | 12 - llarp/link/link_manager.cpp | 164 +++--- llarp/link/link_manager.hpp | 105 ++-- llarp/link/server.cpp | 483 ------------------ llarp/messages/relay_status.cpp | 2 +- llarp/messages/relay_status.hpp | 2 +- llarp/path/abstracthophandler.cpp | 36 ++ ...ihophandler.hpp => abstracthophandler.hpp} | 6 +- llarp/path/ihophandler.cpp | 39 -- llarp/path/path.cpp | 7 +- llarp/path/path.hpp | 4 +- llarp/path/path_context.hpp | 2 +- llarp/path/pathset.hpp | 1 + llarp/path/transit_hop.cpp | 2 +- llarp/path/transit_hop.hpp | 4 +- llarp/router/outbound_session_maker.cpp | 3 +- llarp/router/rc_gossiper.cpp | 5 +- llarp/router/rc_gossiper.hpp | 3 +- llarp/router/router.cpp | 167 +++--- llarp/router/router.hpp | 97 ++-- llarp/router_contact.cpp | 3 +- llarp/util/priority_queue.hpp | 1 - 25 files changed, 354 insertions(+), 800 deletions(-) delete mode 100644 llarp/link/endpoint.hpp delete mode 100644 llarp/link/server.cpp create mode 100644 llarp/path/abstracthophandler.cpp rename llarp/path/{ihophandler.hpp => abstracthophandler.hpp} (94%) delete mode 100644 llarp/path/ihophandler.cpp diff --git a/external/oxen-libquic b/external/oxen-libquic index 329a6ba6ff..2c6b8774c5 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit 329a6ba6ff79f7a94762f0e55d8366190cbfb318 +Subproject commit 2c6b8774c53426b4c99ca6a84c71149789cd77e4 diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index cf8a86fb94..d4c01334b9 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -183,7 +183,7 @@ add_library(lokinet-layer-flow # with onion paths. onion paths anonymize routing layer pdu. add_library(lokinet-layer-onion STATIC - path/ihophandler.cpp + path/abstracthophandler.cpp path/path_context.cpp path/path.cpp path/pathbuilder.cpp diff --git a/llarp/exit/endpoint.hpp b/llarp/exit/endpoint.hpp index b6fc4b13e9..9f0943f8de 100644 --- a/llarp/exit/endpoint.hpp +++ b/llarp/exit/endpoint.hpp @@ -2,7 +2,7 @@ #include #include -#include +#include #include #include #include diff --git a/llarp/link/endpoint.hpp b/llarp/link/endpoint.hpp deleted file mode 100644 index b5090c56a8..0000000000 --- a/llarp/link/endpoint.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include "connection.hpp" -#include "link_manager.hpp" - -#include -#include - -#include - -namespace llarp::link -{} // namespace llarp::link diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 3bff19ebcb..962fa43279 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -15,11 +15,8 @@ namespace llarp std::shared_ptr Endpoint::get_conn(const RouterContact& rc) const { - for (const auto& [rid, conn] : conns) - { - if (conn->remote_rc == rc) - return conn; - } + if (auto itr = conns.find(rc.pubkey); itr != conns.end()) + return itr->second; return nullptr; } @@ -79,33 +76,131 @@ namespace llarp } } // namespace link + // TODO: pass connection open callback to endpoint constructor! LinkManager::LinkManager(Router& r) : router{r} , quic{std::make_unique()} , tls_creds{oxen::quic::GNUTLSCreds::make_from_ed_keys( {reinterpret_cast(router.identity().data()), size_t{32}}, {reinterpret_cast(router.identity().toPublic().data()), size_t{32}})} - , ep{quic->endpoint(router.local), *this} + , ep{quic->endpoint( + router.public_ip(), + [this](oxen::quic::connection_interface& ci) { return on_conn_open(ci); }), + *this} {} // TODO: replace with control/data message sending with libquic bool - LinkManager::send_to(const RouterID& remote, const llarp_buffer_t&, uint16_t) + LinkManager::send_to(const RouterID& remote, bstring data, uint16_t priority) { if (stopping) return false; if (not have_connection_to(remote)) { + auto pending = PendingMessage(data, priority); + + auto [itr, b] = pending_conn_msg_queue.emplace(remote, MessageQueue()); + itr->second.push(std::move(pending)); + + rc_lookup->get_rc( + remote, + [this]( + [[maybe_unused]] const RouterID& rid, + const RouterContact* const rc, + const RCRequestResult res) { + if (res == RCRequestResult::Success) + connect_to(*rc); + else + log::warning(quic_cat, "Do something intelligent here for error handling"); + }); + // TODO: some error callback to report message send failure + // or, should we connect and pass a send-msg callback as the connection successful cb? return false; } // TODO: send the message // TODO: if we keep bool return type, change this accordingly + return false; } + void + LinkManager::connect_to(RouterID router) + { + rc_lookup->get_rc( + router, + [this]( + [[maybe_unused]] const RouterID& rid, + const RouterContact* const rc, + const RCRequestResult res) { + if (res == RCRequestResult::Success) + connect_to(*rc); + /* TODO: + else + RC lookup failure callback here + */ + }); + } + + // This function assumes the RC has already had its signature verified and connection is allowed. + void + LinkManager::connect_to(RouterContact rc) + { + if (have_connection_to(rc.pubkey)) + { + // TODO: connection failed callback + return; + } + + // TODO: connection established/failed callbacks + oxen::quic::stream_data_callback stream_cb = + [this](oxen::quic::Stream& stream, bstring_view packet) { + recv_control_message(stream, packet); + }; + + // TODO: once "compatible link" cares about address, actually choose addr to connect to + // based on which one is compatible with the link we chose. For now, just use + // the first one. + 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) + // TODO: does connect() inherit the endpoint's datagram data callback, and do we want it to if + // so? + if (auto rv = ep.establish_connection(remote_addr, rc, stream_cb, tls_creds); rv) + { + log::info(quic_cat, "Connection to {} successfully established!", remote_addr); + return; + } + log::warning(quic_cat, "Connection to {} successfully established!", remote_addr); + } + + void + LinkManager::on_conn_open(oxen::quic::connection_interface& ci) + { + router.loop()->call([]() {}); + + const auto& scid = ci.scid(); + const auto& rid = ep.connid_map[scid]; + + if (auto itr = pending_conn_msg_queue.find(rid); itr != pending_conn_msg_queue.end()) + { + auto& que = itr->second; + + while (not que.empty()) + { + auto& m = que.top(); + + (m.is_control) ? ep.conns[rid]->control_stream->send(std::move(m.buf)) + : ci.send_datagram(std::move(m.buf)); + + que.pop(); + } + } + }; + bool LinkManager::have_connection_to(const RouterID& remote, bool client_only) const { @@ -124,10 +219,10 @@ namespace llarp if (auto rv = ep.deregister_peer(remote); rv) { persisting_conns.erase(remote); - log::info(logcat, "Peer {} successfully de-registered"); + log::info(logcat, "Peer {} successfully de-registered", remote); } else - log::warning(logcat, "Peer {} not found for de-registeration!"); + log::warning(logcat, "Peer {} not found for de-registration!", remote); } void @@ -208,57 +303,6 @@ namespace llarp node_db = router.node_db(); } - void - LinkManager::connect_to(RouterID router) - { - auto fn = [this]( - [[maybe_unused]] const RouterID& rid, - const RouterContact* const rc, - const RCRequestResult res) { - if (res == RCRequestResult::Success) - connect_to(*rc); - /* TODO: - else - RC lookup failure callback here - */ - }; - - rc_lookup->get_rc(router, fn); - } - - // This function assumes the RC has already had its signature verified and connection is allowed. - void - LinkManager::connect_to(RouterContact rc) - { - if (have_connection_to(rc.pubkey)) - { - // TODO: connection failed callback - return; - } - - // TODO: connection established/failed callbacks - oxen::quic::stream_data_callback stream_cb = - [this](oxen::quic::Stream& stream, bstring_view packet) { - recv_control_message(stream, packet); - }; - - // TODO: once "compatible link" cares about address, actually choose addr to connect to - // based on which one is compatible with the link we chose. For now, just use - // the first one. - 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) - // TODO: does connect() inherit the endpoint's datagram data callback, and do we want it to if - // so? - if (auto rv = ep.establish_connection(remote_addr, rc, stream_cb, tls_creds); rv) - { - log::info(quic_cat, "Connection to {} successfully established!", remote_addr); - return; - } - log::warning(quic_cat, "Connection to {} successfully established!", remote_addr); - } - void LinkManager::connect_to_random(int num_conns) { diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index edad06f05f..b53f29bcfe 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -1,5 +1,7 @@ #pragma once +#include "connection.hpp" + #include #include #include @@ -13,6 +15,7 @@ #include #include +#include namespace { @@ -91,15 +94,65 @@ namespace llarp template <> constexpr inline bool IsToStringFormattable = true; + struct PendingMessage + { + bstring buf; + uint16_t priority; + bool is_control{false}; + + PendingMessage(bstring b, uint16_t p, bool c = false) + : buf{std::move(b)}, priority{p}, is_control{c} + {} + }; + + using MessageQueue = util::ascending_priority_queue; + struct Router; struct LinkManager { + private: + friend struct link::Endpoint; + + std::atomic stopping; + // DISCUSS: is this necessary? can we reduce the amount of locking and nuke this + mutable util::Mutex m; // protects persisting_conns + + // sessions to persist -> timestamp to end persist at + std::unordered_map persisting_conns GUARDED_BY(_mutex); + + // holds any messages we attempt to send while connections are establishing + std::unordered_map pending_conn_msg_queue; + + util::DecayingHashSet clients{path::default_lifetime}; + + RCLookupHandler* rc_lookup; + std::shared_ptr node_db; + + oxen::quic::Address addr; + + Router& router; + + // FIXME: Lokinet currently expects to be able to kill all network functionality before + // finishing other shutdown things, including destroying this class, and that is all in + // Network's destructor, so we need to be able to destroy it before this class. + std::unique_ptr quic; + std::shared_ptr tls_creds; + link::Endpoint ep; + + void + recv_data_message(oxen::quic::dgram_interface& dgi, bstring dgram); + void + recv_control_message(oxen::quic::Stream& stream, bstring_view packet); + + void + on_conn_open(oxen::quic::connection_interface& ci); + public: explicit LinkManager(Router& r); bool - send_to(const RouterID& remote, const llarp_buffer_t& buf, uint16_t priority); + send_to(const RouterID& remote, bstring data, uint16_t priority); bool have_connection_to(const RouterID& remote, bool client_only = false) const; @@ -156,37 +209,6 @@ namespace llarp size_t min_connected_routers = 4; /// hard upperbound limit on the number of router to router connections size_t max_connected_routers = 6; - - private: - friend struct link::Endpoint; - - std::atomic stopping; - // DISCUSS: is this necessary? can we reduce the amount of locking and nuke this - mutable util::Mutex m; // protects persisting_conns - - // sessions to persist -> timestamp to end persist at - std::unordered_map persisting_conns GUARDED_BY(_mutex); - - util::DecayingHashSet clients{path::default_lifetime}; - - RCLookupHandler* rc_lookup; - std::shared_ptr node_db; - - oxen::quic::Address addr; - - Router& router; - - // FIXME: Lokinet currently expects to be able to kill all network functionality before - // finishing other shutdown things, including destroying this class, and that is all in - // Network's destructor, so we need to be able to destroy it before this class. - std::unique_ptr quic; - std::shared_ptr tls_creds; - link::Endpoint ep; - - void - recv_data_message(oxen::quic::dgram_interface& dgi, bstring dgram); - void - recv_control_message(oxen::quic::Stream& stream, bstring_view packet); }; namespace link @@ -205,13 +227,13 @@ namespace llarp auto conn_interface = endpoint->connect(remote, link_manager.tls_creds, dgram_cb, std::forward(opts)...); - auto control_stream = conn_interface->get_new_stream(); - // TOFIX: get a real RouterID after refactoring RouterID - RouterID rid; - auto [itr, b] = conns.emplace(rid); + // emplace immediately for connection open callback to find scid + connid_map.emplace(conn_interface->scid(), rc.pubkey); + auto [itr, b] = conns.emplace(rc.pubkey); + + auto control_stream = conn_interface->get_new_stream(); itr->second = std::make_shared(conn_interface, rc, control_stream); - connid_map.emplace(conn_interface->scid(), rid); return true; } @@ -232,6 +254,7 @@ namespace llarp - Combine llarp/link/server.hpp::ILinkLayer into llarp/link/endpoint.hpp::Endpoint - must maintain metadata storage, callbacks, etc + - If: one endpoint for ipv4 and ipv6 - Then: can potentially combine: - llarp/link/endpoint.hpp @@ -242,4 +265,12 @@ namespace llarp -> Yields mega-combo endpoint managing object? - Can avoid "kitchen sink" by greatly reducing complexity of implementation + + llarp/router/outbound_message_handler.hpp + - pendingsessionmessagequeue + - establish queue of messages to be sent on a connection we are creating + - upon creation, send these messages in the connection established callback + - if connection times out, flush queue + - TOCHECK: is priority used at all?? + */ diff --git a/llarp/link/server.cpp b/llarp/link/server.cpp deleted file mode 100644 index 5c9aef4140..0000000000 --- a/llarp/link/server.cpp +++ /dev/null @@ -1,483 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static constexpr auto LINK_LAYER_TICK_INTERVAL = 100ms; - -namespace llarp -{ - ILinkLayer::ILinkLayer( - std::shared_ptr keyManager, - GetRCFunc getrc, - LinkMessageHandler handler, - SignBufferFunc signbuf, - BeforeConnectFunc_t before, - SessionEstablishedHandler establishedSession, - SessionRenegotiateHandler reneg, - TimeoutHandler timeout, - SessionClosedHandler closed, - PumpDoneHandler pumpDone, - WorkerFunc_t work) - : HandleMessage(std::move(handler)) - , HandleTimeout(std::move(timeout)) - , Sign(std::move(signbuf)) - , GetOurRC(std::move(getrc)) - , BeforeConnect(std::move(before)) - , SessionEstablished(std::move(establishedSession)) - , SessionClosed(std::move(closed)) - , SessionRenegotiate(std::move(reneg)) - , PumpDone(std::move(pumpDone)) - , QueueWork(std::move(work)) - , m_RouterEncSecret(keyManager->encryptionKey) - , m_SecretKey(keyManager->transportKey) - {} - - llarp_time_t - ILinkLayer::Now() const - { - return m_Router->loop()->time_now(); - } - - bool - ILinkLayer::HasSessionTo(const RouterID& id) - { - Lock_t l(m_AuthedLinksMutex); - return m_AuthedLinks.find(id) != m_AuthedLinks.end(); - } - - std::shared_ptr - ILinkLayer::FindSessionByPubkey(RouterID id) - { - Lock_t l(m_AuthedLinksMutex); - auto itr = m_AuthedLinks.find(id); - if (itr == m_AuthedLinks.end()) - return nullptr; - return itr->second; - } - - void - ILinkLayer::ForEachSession( - std::function visit, bool randomize) const - { - std::vector> sessions; - { - Lock_t l(m_AuthedLinksMutex); - if (m_AuthedLinks.size() == 0) - return; - const size_t sz = randint() % m_AuthedLinks.size(); - auto itr = m_AuthedLinks.begin(); - auto begin = itr; - if (randomize) - { - std::advance(itr, sz); - begin = itr; - } - while (itr != m_AuthedLinks.end()) - { - sessions.emplace_back(itr->second); - ++itr; - } - if (randomize) - { - itr = m_AuthedLinks.begin(); - while (itr != begin) - { - sessions.emplace_back(itr->second); - ++itr; - } - } - } - for (const auto& session : sessions) - visit(session.get()); - } - - bool - ILinkLayer::VisitSessionByPubkey( - const RouterID& pk, std::function visit) - { - std::shared_ptr session; - { - Lock_t l(m_AuthedLinksMutex); - auto itr = m_AuthedLinks.find(pk); - if (itr == m_AuthedLinks.end()) - return false; - session = itr->second; - } - return visit(session.get()); - } - - void - ILinkLayer::ForEachSession(std::function visit) - { - std::vector> sessions; - { - Lock_t l(m_AuthedLinksMutex); - auto itr = m_AuthedLinks.begin(); - while (itr != m_AuthedLinks.end()) - { - sessions.emplace_back(itr->second); - ++itr; - } - } - for (const auto& s : sessions) - visit(s.get()); - } - - void - ILinkLayer::Bind(Router* router, SockAddr bind_addr) - { - if (router->Net().IsLoopbackAddress(bind_addr.getIP())) - throw std::runtime_error{"cannot udp bind socket on loopback"}; - m_ourAddr = bind_addr; - m_Router = router; - m_udp = m_Router->loop()->make_udp( - [this]([[maybe_unused]] UDPHandle& udp, const SockAddr& from, llarp_buffer_t buf) { - AbstractLinkSession::Packet_t pkt; - pkt.resize(buf.sz); - std::copy_n(buf.base, buf.sz, pkt.data()); - RecvFrom(from, std::move(pkt)); - }); - - if (m_udp->listen(m_ourAddr)) - return; - - throw std::runtime_error{ - fmt::format("failed to listen {} udp socket on {}", Name(), m_ourAddr)}; - } - - void - ILinkLayer::Pump() - { - std::unordered_set closedSessions; - std::vector> closedPending; - auto _now = Now(); - { - Lock_t l(m_AuthedLinksMutex); - auto itr = m_AuthedLinks.begin(); - while (itr != m_AuthedLinks.end()) - { - if (not itr->second->TimedOut(_now)) - { - itr->second->Pump(); - ++itr; - } - else - { - llarp::LogInfo("session to ", RouterID(itr->second->GetPubKey()), " timed out"); - itr->second->Close(); - closedSessions.emplace(itr->first); - UnmapAddr(itr->second->GetRemoteEndpoint()); - itr = m_AuthedLinks.erase(itr); - } - } - } - { - Lock_t l(m_PendingMutex); - - auto itr = m_Pending.begin(); - while (itr != m_Pending.end()) - { - if (not itr->second->TimedOut(_now)) - { - itr->second->Pump(); - ++itr; - } - else - { - LogInfo("pending session at ", itr->first, " timed out"); - UnmapAddr(itr->second->GetRemoteEndpoint()); - // defer call so we can acquire mutexes later - closedPending.emplace_back(std::move(itr->second)); - itr = m_Pending.erase(itr); - } - } - } - { - Lock_t l(m_AuthedLinksMutex); - for (const auto& r : closedSessions) - { - if (m_AuthedLinks.count(r) == 0) - { - SessionClosed(r); - } - } - } - for (const auto& pending : closedPending) - { - if (pending->IsInbound()) - continue; - HandleTimeout(pending.get()); - } - } - - void - ILinkLayer::UnmapAddr(const SockAddr& addr) - { - m_AuthedAddrs.erase(addr); - } - - bool - ILinkLayer::MapAddr(const RouterID& pk, AbstractLinkSession* s) - { - Lock_t l_authed(m_AuthedLinksMutex); - Lock_t l_pending(m_PendingMutex); - const auto addr = s->GetRemoteEndpoint(); - auto itr = m_Pending.find(addr); - if (itr != m_Pending.end()) - { - if (m_AuthedLinks.count(pk)) - { - LogWarn("too many session for ", pk); - s->Close(); - return false; - } - m_AuthedAddrs.emplace(addr, pk); - m_AuthedLinks.emplace(pk, itr->second); - itr = m_Pending.erase(itr); - m_Router->TriggerPump(); - return true; - } - return false; - } - - util::StatusObject - ILinkLayer::ExtractStatus() const - { - std::vector pending, established; - - { - Lock_t l(m_PendingMutex); - std::transform( - m_Pending.cbegin(), - m_Pending.cend(), - std::back_inserter(pending), - [](const auto& item) -> util::StatusObject { return item.second->ExtractStatus(); }); - } - { - Lock_t l(m_AuthedLinksMutex); - std::transform( - m_AuthedLinks.cbegin(), - m_AuthedLinks.cend(), - std::back_inserter(established), - [](const auto& item) -> util::StatusObject { return item.second->ExtractStatus(); }); - } - - return { - {"name", Name()}, - {"rank", uint64_t(Rank())}, - {"addr", m_ourAddr.ToString()}, - {"sessions", util::StatusObject{{"pending", pending}, {"established", established}}}}; - } - - bool - ILinkLayer::TryEstablishTo(RouterContact rc) - { - { - Lock_t l(m_AuthedLinksMutex); - if (m_AuthedLinks.count(rc.pubkey)) - { - LogWarn("Too many links to ", RouterID{rc.pubkey}, ", not establishing another one"); - return false; - } - } - llarp::AddressInfo to; - if (not PickAddress(rc, to)) - { - LogWarn("router ", RouterID{rc.pubkey}, " has no acceptable inbound addresses"); - return false; - } - const SockAddr address{to}; - { - Lock_t l(m_PendingMutex); - if (m_Pending.count(address)) - { - LogWarn( - "Too many pending connections to ", - address, - " while establishing to ", - RouterID{rc.pubkey}, - ", not establishing another"); - return false; - } - } - std::shared_ptr s = NewOutboundSession(rc, to); - if (BeforeConnect) - { - BeforeConnect(std::move(rc)); - } - if (not PutSession(s)) - { - return false; - } - s->Start(); - return true; - } - - bool - ILinkLayer::Start() - { - // Tie the lifetime of this repeater to this arbitrary shared_ptr: - m_repeater_keepalive = std::make_shared(0); - m_Router->loop()->call_every( - LINK_LAYER_TICK_INTERVAL, m_repeater_keepalive, [this] { Tick(Now()); }); - return true; - } - - void - ILinkLayer::Tick(const llarp_time_t now) - { - { - Lock_t l(m_AuthedLinksMutex); - for (const auto& [routerid, link] : m_AuthedLinks) - link->Tick(now); - } - - { - Lock_t l(m_PendingMutex); - for (const auto& [addr, link] : m_Pending) - link->Tick(now); - } - - { - // decay recently closed list - auto itr = m_RecentlyClosed.begin(); - while (itr != m_RecentlyClosed.end()) - { - if (itr->second >= now) - itr = m_RecentlyClosed.erase(itr); - else - ++itr; - } - } - } - - void - ILinkLayer::Stop() - { - m_repeater_keepalive.reset(); // make the repeater kill itself - { - Lock_t l(m_AuthedLinksMutex); - for (const auto& [router, link] : m_AuthedLinks) - link->Close(); - } - { - Lock_t l(m_PendingMutex); - for (const auto& [addr, link] : m_Pending) - link->Close(); - } - } - - void - ILinkLayer::CloseSessionTo(const RouterID& remote) - { - static constexpr auto CloseGraceWindow = 500ms; - const auto now = Now(); - { - Lock_t l(m_AuthedLinksMutex); - RouterID r = remote; - llarp::LogInfo("Closing all to ", r); - for (auto [itr, end] = m_AuthedLinks.equal_range(r); itr != end;) - { - itr->second->Close(); - m_RecentlyClosed.emplace(itr->second->GetRemoteEndpoint(), now + CloseGraceWindow); - itr = m_AuthedLinks.erase(itr); - } - } - SessionClosed(remote); - } - - void - ILinkLayer::KeepAliveSessionTo(const RouterID& remote) - { - Lock_t l(m_AuthedLinksMutex); - for (auto [itr, end] = m_AuthedLinks.equal_range(remote); itr != end; ++itr) - { - if (itr->second->ShouldPing()) - { - LogDebug("keepalive to ", remote); - itr->second->SendKeepAlive(); - } - } - } - - void - ILinkLayer::SendTo_LL(const SockAddr& to, const llarp_buffer_t& pkt) - { - if (not m_udp->send(to, pkt)) - LogError("could not send udp packet to ", to); - } - - bool - ILinkLayer::SendTo( - const RouterID& remote, - const llarp_buffer_t& buf, - AbstractLinkSession::CompletionHandler completed, - uint16_t priority) - { - std::shared_ptr s; - { - Lock_t l(m_AuthedLinksMutex); - // pick lowest backlog session - size_t min = std::numeric_limits::max(); - - for (auto [itr, end] = m_AuthedLinks.equal_range(remote); itr != end; ++itr) - { - if (const auto backlog = itr->second->SendQueueBacklog(); backlog < min) - { - s = itr->second; - min = backlog; - } - } - } - AbstractLinkSession::Message_t pkt(buf.sz); - std::copy_n(buf.base, buf.sz, pkt.begin()); - return s && s->SendMessageBuffer(std::move(pkt), completed, priority); - } - - bool - ILinkLayer::GetOurAddressInfo(llarp::AddressInfo& addr) const - { - addr.fromSockAddr(m_ourAddr); - addr.dialect = Name(); - addr.pubkey = TransportPubKey(); - addr.rank = Rank(); - return true; - } - - const byte_t* - ILinkLayer::TransportPubKey() const - { - return llarp::seckey_topublic(TransportSecretKey()); - } - - const SecretKey& - ILinkLayer::TransportSecretKey() const - { - return m_SecretKey; - } - - bool - ILinkLayer::PutSession(const std::shared_ptr& s) - { - Lock_t lock(m_PendingMutex); - const auto address = s->GetRemoteEndpoint(); - if (m_Pending.count(address)) - return false; - m_Pending.emplace(address, s); - return true; - } - - std::optional - ILinkLayer::GetUDPFD() const - { - return m_udp->file_descriptor(); - } - -} // namespace llarp diff --git a/llarp/messages/relay_status.cpp b/llarp/messages/relay_status.cpp index d831df8d2a..6d881d6aed 100644 --- a/llarp/messages/relay_status.cpp +++ b/llarp/messages/relay_status.cpp @@ -18,7 +18,7 @@ namespace llarp { struct LRSM_AsyncHandler : public std::enable_shared_from_this { - using HopHandler_ptr = std::shared_ptr; + using HopHandler_ptr = std::shared_ptr; std::array frames; uint64_t status = 0; diff --git a/llarp/messages/relay_status.hpp b/llarp/messages/relay_status.hpp index f0ce9bdd22..941f7b4619 100644 --- a/llarp/messages/relay_status.hpp +++ b/llarp/messages/relay_status.hpp @@ -17,7 +17,7 @@ namespace llarp namespace path { struct PathContext; - struct IHopHandler; + struct AbstractHopHandler; struct TransitHop; } // namespace path diff --git a/llarp/path/abstracthophandler.cpp b/llarp/path/abstracthophandler.cpp new file mode 100644 index 0000000000..b4d88bccb5 --- /dev/null +++ b/llarp/path/abstracthophandler.cpp @@ -0,0 +1,36 @@ +#include "abstracthophandler.hpp" +#include + +namespace llarp::path +{ + // handle data in upstream direction + bool + AbstractHopHandler::HandleUpstream(const llarp_buffer_t& X, const TunnelNonce& Y, Router* r) + { + auto& pkt = m_UpstreamQueue.emplace_back(); + pkt.first.resize(X.sz); + std::copy_n(X.base, X.sz, pkt.first.begin()); + pkt.second = Y; + r->TriggerPump(); + return true; + } + + // handle data in downstream direction + bool + AbstractHopHandler::HandleDownstream(const llarp_buffer_t& X, const TunnelNonce& Y, Router* r) + { + auto& pkt = m_DownstreamQueue.emplace_back(); + pkt.first.resize(X.sz); + std::copy_n(X.base, X.sz, pkt.first.begin()); + pkt.second = Y; + r->TriggerPump(); + return true; + } + + void + AbstractHopHandler::DecayFilters(llarp_time_t now) + { + m_UpstreamReplayFilter.Decay(now); + m_DownstreamReplayFilter.Decay(now); + } +} // namespace llarp::path diff --git a/llarp/path/ihophandler.hpp b/llarp/path/abstracthophandler.hpp similarity index 94% rename from llarp/path/ihophandler.hpp rename to llarp/path/abstracthophandler.hpp index 68312a6272..593db5d519 100644 --- a/llarp/path/ihophandler.hpp +++ b/llarp/path/abstracthophandler.hpp @@ -22,12 +22,12 @@ namespace llarp namespace path { - struct IHopHandler + struct AbstractHopHandler { using TrafficEvent_t = std::pair, TunnelNonce>; using TrafficQueue_t = std::list; - virtual ~IHopHandler() = default; + virtual ~AbstractHopHandler() = default; virtual PathID_t RXID() const = 0; @@ -90,6 +90,6 @@ namespace llarp HandleAllDownstream(std::vector msgs, Router* r) = 0; }; - using HopHandler_ptr = std::shared_ptr; + using HopHandler_ptr = std::shared_ptr; } // namespace path } // namespace llarp diff --git a/llarp/path/ihophandler.cpp b/llarp/path/ihophandler.cpp deleted file mode 100644 index 9927765efd..0000000000 --- a/llarp/path/ihophandler.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "ihophandler.hpp" -#include - -namespace llarp -{ - namespace path - { - // handle data in upstream direction - bool - IHopHandler::HandleUpstream(const llarp_buffer_t& X, const TunnelNonce& Y, Router* r) - { - auto& pkt = m_UpstreamQueue.emplace_back(); - pkt.first.resize(X.sz); - std::copy_n(X.base, X.sz, pkt.first.begin()); - pkt.second = Y; - r->TriggerPump(); - return true; - } - - // handle data in downstream direction - bool - IHopHandler::HandleDownstream(const llarp_buffer_t& X, const TunnelNonce& Y, Router* r) - { - auto& pkt = m_DownstreamQueue.emplace_back(); - pkt.first.resize(X.sz); - std::copy_n(X.base, X.sz, pkt.first.begin()); - pkt.second = Y; - r->TriggerPump(); - return true; - } - - void - IHopHandler::DecayFilters(llarp_time_t now) - { - m_UpstreamReplayFilter.Decay(now); - m_DownstreamReplayFilter.Decay(now); - } - } // namespace path -} // namespace llarp diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index c8204a33b7..d0561c42c2 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -70,7 +70,7 @@ namespace llarp::path { if (not m_UpstreamReplayFilter.Insert(Y)) return false; - return IHopHandler::HandleUpstream(X, Y, r); + return AbstractHopHandler::HandleUpstream(X, Y, r); } bool @@ -78,7 +78,7 @@ namespace llarp::path { if (not m_DownstreamReplayFilter.Insert(Y)) return false; - return IHopHandler::HandleDownstream(X, Y, r); + return AbstractHopHandler::HandleDownstream(X, Y, r); } RouterID @@ -332,9 +332,8 @@ namespace llarp::path util::StatusObject PathHopConfig::ExtractStatus() const { - const auto ip = net::In6ToHUInt(rc.addrs[0].ip); util::StatusObject obj{ - {"ip", ip.ToString()}, + {"ip", rc.addr.to_string()}, {"lifetime", to_json(lifetime)}, {"router", rc.pubkey.ToHex()}, {"txid", txID.ToHex()}, diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 91998f74a2..155ce748e5 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -4,7 +4,7 @@ #include #include #include -#include "ihophandler.hpp" +#include "abstracthophandler.hpp" #include "path_types.hpp" #include "pathbuilder.hpp" #include "pathset.hpp" @@ -69,7 +69,7 @@ namespace llarp } /// A path we made - struct Path final : public IHopHandler, + struct Path final : public AbstractHopHandler, public routing::AbstractRoutingMessageHandler, public std::enable_shared_from_this { diff --git a/llarp/path/path_context.hpp b/llarp/path/path_context.hpp index 359ebddc1b..b46ee56ee9 100644 --- a/llarp/path/path_context.hpp +++ b/llarp/path/path_context.hpp @@ -2,7 +2,7 @@ #include #include -#include "ihophandler.hpp" +#include "abstracthophandler.hpp" #include "path_types.hpp" #include "pathset.hpp" #include "transit_hop.hpp" diff --git a/llarp/path/pathset.hpp b/llarp/path/pathset.hpp index 581c38dfa1..7bd70048bd 100644 --- a/llarp/path/pathset.hpp +++ b/llarp/path/pathset.hpp @@ -1,6 +1,7 @@ #pragma once #include "path_types.hpp" +#include #include #include #include diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index 8b81cc9c62..a134a8567b 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -27,7 +27,7 @@ namespace llarp::path } TransitHop::TransitHop() - : IHopHandler{} + : AbstractHopHandler{} , m_UpstreamGather{transit_hop_queue_size} , m_DownstreamGather{transit_hop_queue_size} { diff --git a/llarp/path/transit_hop.hpp b/llarp/path/transit_hop.hpp index 4752eca762..d4cac25ea2 100644 --- a/llarp/path/transit_hop.hpp +++ b/llarp/path/transit_hop.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include #include @@ -52,7 +52,7 @@ namespace llarp < std::tie(rhs.txID, rhs.rxID, rhs.upstream, rhs.downstream); } - struct TransitHop : public IHopHandler, + struct TransitHop : public AbstractHopHandler, public routing::AbstractRoutingMessageHandler, std::enable_shared_from_this { diff --git a/llarp/router/outbound_session_maker.cpp b/llarp/router/outbound_session_maker.cpp index b6812fa35a..be7ead52e3 100644 --- a/llarp/router/outbound_session_maker.cpp +++ b/llarp/router/outbound_session_maker.cpp @@ -1,8 +1,7 @@ #include "outbound_session_maker.hpp" -#include "Router.hpp" +#include "router.hpp" #include -#include #include #include #include "rc_lookup_handler.hpp" diff --git a/llarp/router/rc_gossiper.cpp b/llarp/router/rc_gossiper.cpp index 7012556029..b394962c29 100644 --- a/llarp/router/rc_gossiper.cpp +++ b/llarp/router/rc_gossiper.cpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace llarp { @@ -16,11 +17,11 @@ namespace llarp {} void - RCGossiper::Init(LinkManager* l, const RouterID& ourID, Router* router) + RCGossiper::Init(LinkManager* l, const RouterID& ourID, Router* r) { rid = ourID; link_manager = l; - router = router; + router = r; } bool diff --git a/llarp/router/rc_gossiper.hpp b/llarp/router/rc_gossiper.hpp index b753bb8385..d6cc4dab3e 100644 --- a/llarp/router/rc_gossiper.hpp +++ b/llarp/router/rc_gossiper.hpp @@ -2,12 +2,13 @@ #include #include "outbound_message_handler.hpp" -#include namespace llarp { /// The maximum number of peers we will flood a gossiped RC to when propagating an RC constexpr size_t MaxGossipPeers = 20; + struct LinkManager; + struct RouterContact; struct RCGossiper { diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 8b7eee69b6..e2dd076478 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -46,20 +46,18 @@ namespace llarp static auto logcat = log::Cat("router"); Router::Router(EventLoop_ptr loop, std::shared_ptr vpnPlatform) - : _lmq{std::make_shared()} + : _route_poker{std::make_shared()} + , _lmq{std::make_shared()} , _loop{std::move(loop)} , _vpn{std::move(vpnPlatform)} , paths{this} - , _exitContext{this} + , _exit_context{this} , _dht{dht::make_handler()} , _disk_thread{_lmq->add_tagged_thread("disk")} - , inbound_link_msg_parser{this} - , _hiddenServiceContext{this} - , m_RoutePoker{std::make_shared()} , m_RPCServer{nullptr} - , _randomStartDelay{ - platform::is_simulation ? std::chrono::milliseconds{(llarp::randint() % 1250) + 2000} - : 0s} + , _randomStartDelay{platform::is_simulation ? std::chrono::milliseconds{(llarp::randint() % 1250) + 2000} : 0s} + , inbound_link_msg_parser{this} + , _hidden_service_context{this} { _key_manager = std::make_shared(); // for lokid, so we don't close the connection when syncing the whitelist @@ -67,7 +65,7 @@ namespace llarp is_stopping.store(false); is_running.store(false); _lastTick = llarp::time_now_ms(); - m_NextExploreAt = std::chrono::steady_clock::now(); + _next_explore_at = std::chrono::steady_clock::now(); loop_wakeup = _loop->make_waker([this]() { PumpLL(); }); } @@ -86,11 +84,12 @@ namespace llarp return; paths.PumpDownstream(); paths.PumpUpstream(); - _hiddenServiceContext.Pump(); - _outboundMessageHandler.Pump(); + _hidden_service_context.Pump(); + // _outboundMessageHandler.Pump(); llarp::LogTrace("Router::PumpLL() end"); } + // TOFIX: this util::StatusObject Router::ExtractStatus() const { @@ -101,10 +100,10 @@ namespace llarp {"running", true}, {"numNodesKnown", _node_db->NumLoaded()}, {"dht", _dht->ExtractStatus()}, - {"services", _hiddenServiceContext.ExtractStatus()}, - {"exit", _exitContext.ExtractStatus()}, + {"services", _hidden_service_context.ExtractStatus()}, + {"exit", _exit_context.ExtractStatus()}, {"links", _link_manager.extract_status()}, - {"outboundMessages", _outboundMessageHandler.ExtractStatus()}}; + /* {"outboundMessages", _outboundMessageHandler.ExtractStatus()} */}; } // TODO: investigate changes needed for libquic integration @@ -114,7 +113,7 @@ namespace llarp if (!is_running) return util::StatusObject{{"running", false}}; - auto services = _hiddenServiceContext.ExtractStatus(); + auto services = _hidden_service_context.ExtractStatus(); auto link_types = _link_manager.extract_status(); @@ -411,8 +410,8 @@ namespace llarp { llarp::sys::service_manager->starting(); - config = std::move(c); - auto& conf = *config; + _config = std::move(c); + auto& conf = *_config; // Do logging config as early as possible to get the configured log level applied @@ -429,7 +428,7 @@ namespace llarp log::add_sink(log_type, log_type == log::Type::System ? "lokinet" : conf.logging.m_logFile); // re-add rpc log sink if rpc enabled, else free it - if (config->api.m_enableRPCServer and llarp::logRingBuffer) + if (_config->api.m_enableRPCServer and llarp::logRingBuffer) log::add_sink(llarp::logRingBuffer, llarp::log::DEFAULT_PATTERN_MONO); else llarp::logRingBuffer = nullptr; @@ -439,7 +438,7 @@ namespace llarp follow_whitelist = conf.lokid.whitelistRouters; if (follow_whitelist) { - lokidRPCAddr = oxenmq::address(conf.lokid.lokidRPCAddr); + rpc_addr = oxenmq::address(conf.lokid.lokidRPCAddr); _rpc_client = std::make_shared(_lmq, weak_from_this()); } @@ -461,7 +460,7 @@ namespace llarp if (follow_whitelist) { - _rpc_client->ConnectAsync(lokidRPCAddr); + _rpc_client->ConnectAsync(rpc_addr); } log::debug(logcat, "Initializing key manager"); @@ -520,7 +519,7 @@ namespace llarp { // If we're in the white or gray list then we *should* be establishing connections to other // routers, so if we have almost no peers then something is almost certainly wrong. - if (appear_funder() and insufficient_peers()) + if (appears_funded() and insufficient_peers()) return "too few peer connections; lokinet is not adequately connected to the network"; return std::nullopt; } @@ -544,21 +543,21 @@ namespace llarp } bool - Router::appear_decommed() const + Router::appears_decommed() const { return IsServiceNode() and follow_whitelist and _rc_lookup_handler.has_received_whitelist() and _rc_lookup_handler.is_grey_listed(pubkey()); } bool - Router::appear_funder() const + Router::appears_funded() const { return IsServiceNode() and follow_whitelist and _rc_lookup_handler.has_received_whitelist() and _rc_lookup_handler.is_session_allowed(pubkey()); } bool - Router::appear_registered() const + Router::appears_registered() const { return IsServiceNode() and follow_whitelist and _rc_lookup_handler.has_received_whitelist() and _rc_lookup_handler.is_registered(pubkey()); @@ -585,7 +584,7 @@ namespace llarp bool Router::PathToRouterAllowed(const RouterID& router) const { - if (appear_decommed()) + if (appears_decommed()) { // we are decom'd don't allow any paths outbound at all return false; @@ -728,22 +727,22 @@ namespace llarp } } - bootstrapRCList.clear(); + bootstrap_rc_list.clear(); for (const auto& router : configRouters) { log::debug(logcat, "Loading bootstrap router list from {}", defaultBootstrapFile); - bootstrapRCList.AddFromFile(router); + bootstrap_rc_list.AddFromFile(router); } for (const auto& rc : conf.bootstrap.routers) { - bootstrapRCList.emplace(rc); + bootstrap_rc_list.emplace(rc); } // in case someone has an old bootstrap file and is trying to use a bootstrap // that no longer exists auto clearBadRCs = [this]() { - for (auto it = bootstrapRCList.begin(); it != bootstrapRCList.end();) + 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}); @@ -755,22 +754,23 @@ namespace llarp continue; } // we are in one of the above error cases that we warned about: - it = bootstrapRCList.erase(it); + it = bootstrap_rc_list.erase(it); } }; clearBadRCs(); - if (bootstrapRCList.empty() and not conf.bootstrap.seednode) + if (bootstrap_rc_list.empty() and not conf.bootstrap.seednode) { auto fallbacks = llarp::load_bootstrap_fallbacks(); if (auto itr = fallbacks.find(router_contact.netID.ToString()); itr != fallbacks.end()) { - bootstrapRCList = itr->second; - log::debug(logcat, "loaded {} default fallback bootstrap routers", bootstrapRCList.size()); + bootstrap_rc_list = itr->second; + log::debug( + logcat, "loaded {} default fallback bootstrap routers", bootstrap_rc_list.size()); clearBadRCs(); } - if (bootstrapRCList.empty() and not conf.bootstrap.seednode) + if (bootstrap_rc_list.empty() and not conf.bootstrap.seednode) { // empty after trying fallback, if set log::error( @@ -785,7 +785,7 @@ namespace llarp if (conf.bootstrap.seednode) LogInfo("we are a seed node"); else - LogInfo("Loaded ", bootstrapRCList.size(), " bootstrap routers"); + LogInfo("Loaded ", bootstrap_rc_list.size(), " bootstrap routers"); // Init components after relevant config settings loaded _outboundMessageHandler.Init(this); @@ -796,9 +796,9 @@ namespace llarp _loop, util::memFn(&Router::queue_work, this), &_link_manager, - &_hiddenServiceContext, + &_hidden_service_context, strictConnectPubkeys, - bootstrapRCList, + bootstrap_rc_list, follow_whitelist, is_service_node); @@ -809,20 +809,20 @@ namespace llarp InitOutboundLinks(); // profiling - _profilesFile = conf.router.m_dataDir / "profiles.dat"; + _profile_file = conf.router.m_dataDir / "profiles.dat"; // Network config if (conf.network.m_enableProfiling.value_or(false)) { LogInfo("router profiling enabled"); - if (not fs::exists(_profilesFile)) + if (not fs::exists(_profile_file)) { - LogInfo("no profiles file at ", _profilesFile, " skipping"); + LogInfo("no profiles file at ", _profile_file, " skipping"); } else { - LogInfo("loading router profiles from ", _profilesFile); - router_profiling().Load(_profilesFile); + LogInfo("loading router profiles from ", _profile_file); + router_profiling().Load(_profile_file); } } else @@ -850,8 +850,8 @@ namespace llarp Router::IsBootstrapNode(const RouterID r) const { return std::count_if( - bootstrapRCList.begin(), - bootstrapRCList.end(), + bootstrap_rc_list.begin(), + bootstrap_rc_list.end(), [r](const RouterContact& rc) -> bool { return rc.pubkey == r; }) > 0; } @@ -868,7 +868,7 @@ namespace llarp { const auto now = Now(); LogInfo(node_db()->NumLoaded(), " RCs loaded"); - LogInfo(bootstrapRCList.size(), " bootstrap peers"); + LogInfo(bootstrap_rc_list.size(), " bootstrap peers"); LogInfo(NumberOfConnectedRouters(), " router connections"); if (IsServiceNode()) { @@ -964,12 +964,12 @@ namespace llarp const bool gotWhitelist = _rc_lookup_handler.has_received_whitelist(); const bool isSvcNode = IsServiceNode(); - const bool decom = appear_decommed(); + const bool decom = appears_decommed(); bool shouldGossip = isSvcNode and follow_whitelist and gotWhitelist and _rc_lookup_handler.is_session_allowed(pubkey()); if (isSvcNode - and (router_contact.ExpiresSoon(now, std::chrono::milliseconds(randint() % 10000)) or (now - router_contact.last_updated) > rcRegenInterval)) + and (router_contact.ExpiresSoon(now, std::chrono::milliseconds(randint() % 10000)) or (now - router_contact.last_updated) > rc_regen_interval)) { LogInfo("regenerating RC"); if (update_rc()) @@ -1068,10 +1068,10 @@ namespace llarp const int interval = isSvcNode ? 5 : 2; const auto timepoint_now = std::chrono::steady_clock::now(); - if (timepoint_now >= m_NextExploreAt and not decom) + if (timepoint_now >= _next_explore_at and not decom) { _rc_lookup_handler.explore_network(); - m_NextExploreAt = timepoint_now + std::chrono::seconds(interval); + _next_explore_at = timepoint_now + std::chrono::seconds(interval); } size_t connectToNum = _link_manager.min_connected_routers; const auto strictConnect = _rc_lookup_handler.num_strict_connect_routers(); @@ -1080,10 +1080,10 @@ namespace llarp connectToNum = strictConnect; } - if (isSvcNode and now >= next_decomm_warning) + if (isSvcNode and now >= _next_decomm_warning) { constexpr auto DecommissionWarnInterval = 5min; - if (auto registered = appear_registered(), funded = appear_funder(); + if (auto registered = appears_registered(), funded = appears_funded(); not(registered and funded and not decom)) { // complain about being deregistered/decommed/unfunded @@ -1093,7 +1093,7 @@ namespace llarp not registered ? "deregistered" : decom ? "decommissioned" : "not fully staked"); - next_decomm_warning = now + DecommissionWarnInterval; + _next_decomm_warning = now + DecommissionWarnInterval; } else if (insufficient_peers()) { @@ -1101,26 +1101,26 @@ namespace llarp logcat, "We appear to be an active service node, but have only {} known peers.", node_db()->NumLoaded()); - next_decomm_warning = now + DecommissionWarnInterval; + _next_decomm_warning = now + DecommissionWarnInterval; } } // if we need more sessions to routers and we are not a service node kicked from the network or // we are a client we shall connect out to others - if (connected < connectToNum and (appear_funder() or not isSvcNode)) + if (connected < connectToNum and (appears_funded() or not isSvcNode)) { size_t dlt = connectToNum - connected; LogDebug("connecting to ", dlt, " random routers to keep alive"); _link_manager.connect_to_random(dlt); } - _hiddenServiceContext.Tick(now); - _exitContext.Tick(now); + _hidden_service_context.Tick(now); + _exit_context.Tick(now); // save profiles - if (router_profiling().ShouldSave(now) and config->network.m_saveProfiles) + if (router_profiling().ShouldSave(now) and _config->network.m_saveProfiles) { - queue_disk_io([&]() { router_profiling().Save(_profilesFile); }); + queue_disk_io([&]() { router_profiling().Save(_profile_file); }); } _node_db->Tick(now); @@ -1276,7 +1276,7 @@ namespace llarp bool Router::StartRpcServer() { - if (config->api.m_enableRPCServer) + if (_config->api.m_enableRPCServer) m_RPCServer = std::make_unique(_lmq, *this); return true; @@ -1365,7 +1365,7 @@ namespace llarp _dht->Init(llarp::dht::Key_t(pubkey()), this); - for (const auto& rc : bootstrapRCList) + for (const auto& rc : bootstrap_rc_list) { node_db()->Put(rc); _dht->Nodes()->PutNode(rc); @@ -1375,9 +1375,9 @@ namespace llarp LogInfo("have ", _node_db->NumLoaded(), " routers"); _loop->call_every(ROUTER_TICK_INTERVAL, weak_from_this(), [this] { Tick(); }); - m_RoutePoker->Start(this); + _route_poker->Start(this); is_running.store(true); - _startedAt = Now(); + _started_at = Now(); if (follow_whitelist) { // do service node testing if we are in service node whitelist mode @@ -1470,8 +1470,8 @@ namespace llarp Router::Uptime() const { const llarp_time_t _now = Now(); - if (_startedAt > 0s && _now > _startedAt) - return _now - _startedAt; + if (_started_at > 0s && _now > _started_at) + return _now - _started_at; return 0s; } @@ -1515,7 +1515,7 @@ namespace llarp LogWarn("stopping router hard"); llarp::sys::service_manager->stopping(); hiddenServiceContext().StopAll(); - _exitContext.Stop(); + _exit_context.Stop(); StopLinks(); Close(); } @@ -1544,7 +1544,7 @@ namespace llarp hiddenServiceContext().StopAll(); llarp::sys::service_manager->stopping(); log::debug(logcat, "stopping exit context"); - _exitContext.Stop(); + _exit_context.Stop(); llarp::sys::service_manager->stopping(); log::debug(logcat, "final upstream pump"); paths.PumpUpstream(); @@ -1587,7 +1587,7 @@ namespace llarp LogInfo("accepting transit traffic"); paths.AllowTransit(); _dht->AllowTransit() = true; - _exitContext.AddExitEndpoint("default", config->network, config->dns); + _exit_context.AddExitEndpoint("default", _config->network, _config->dns); return true; } @@ -1632,40 +1632,23 @@ namespace llarp return ep and ep->HasExit(); } - std::optional> + oxen::quic::Address Router::public_ip() const { - if (_ourAddress) - return _ourAddress->getIP(); - std::optional> found; - /* - *TODO: change to use new LinkManager foreach semantics, or make function for this - * on LinkManager itself - * - _linkManager.ForEachInboundLink([&found](const auto& link) { - if (found) - return; - AddressInfo ai; - if (link->GetOurAddressInfo(ai)) - found = ai.IP(); - }); - * - * - */ - return found; + return _local_addr; } void Router::InitInboundLinks() { - auto addrs = config->links.InboundListenAddrs; + auto addrs = _config->links.InboundListenAddrs; if (is_service_node and addrs.empty()) { LogInfo("Inferring Public Address"); - auto maybe_port = config->links.PublicPort; - if (config->router.PublicPort and not maybe_port) - maybe_port = config->router.PublicPort; + auto maybe_port = _config->links.PublicPort; + if (_config->router.PublicPort and not maybe_port) + maybe_port = _config->router.PublicPort; if (not maybe_port) maybe_port = net::port_t::from_host(constants::DefaultInboundIWPPort); @@ -1686,7 +1669,7 @@ namespace llarp if (net().IsWildcardAddress(bind_addr.getIP())) { - if (auto maybe_ip = OurPublicIP()) + if (auto maybe_ip = public_ip()) bind_addr.setIP(*maybe_ip); else throw std::runtime_error{"no public ip provided for inbound socket"}; @@ -1695,7 +1678,7 @@ namespace llarp AddressInfo ai; ai.fromSockAddr(bind_addr); - _linkManager.connect_to({ai.IPString(), ai.port}, true); + _link_manager.connect_to({ai.IPString(), ai.port}, true); ai.pubkey = llarp::seckey_topublic(_identity); ai.dialect = "quicinet"; // FIXME: constant, also better name? diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 09aa4885d7..42fc6a846e 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -63,7 +63,15 @@ namespace llarp struct Router : std::enable_shared_from_this { + explicit Router(EventLoop_ptr loop, std::shared_ptr vpnPlatform); + + ~Router(); + private: + std::shared_ptr _route_poker; + /// bootstrap RCs + BootstrapList bootstrap_rc_list; + std::chrono::steady_clock::time_point _next_explore_at; llarp_time_t last_pump = 0s; // transient iwp encryption key fs::path transport_keyfile; @@ -89,27 +97,53 @@ namespace llarp bool is_service_node = false; std::optional _ourAddress; - oxen::quic::Address local; + oxen::quic::Address _local_addr; EventLoop_ptr _loop; std::shared_ptr _vpn; path::PathContext paths; - exit::Context _exitContext; + exit::Context _exit_context; SecretKey _identity; SecretKey _encryption; std::shared_ptr _dht; std::shared_ptr _node_db; - llarp_time_t _startedAt; + llarp_time_t _started_at; const oxenmq::TaggedThreadID _disk_thread; oxen::quic::Network _net; llarp_time_t _last_stats_report = 0s; - llarp_time_t next_decomm_warning = time_now_ms() + 15s; + llarp_time_t _next_decomm_warning = time_now_ms() + 15s; std::shared_ptr _key_manager; std::shared_ptr _peer_db; std::shared_ptr _config; uint32_t _path_build_count = 0; + std::unique_ptr m_RPCServer; + + const llarp_time_t _randomStartDelay; + + std::shared_ptr _rpc_client; + + oxenmq::address rpc_addr; + Profiling _router_profiling; + fs::path _profile_file; + OutboundMessageHandler _outboundMessageHandler; + LinkManager _link_manager{*this}; + RCLookupHandler _rc_lookup_handler; + RCGossiper _rcGossiper; + + /// how often do we resign our RC? milliseconds. + // TODO: make configurable + llarp_time_t rc_regen_interval = 1h; + + // should we be sending padded messages every interval? + bool send_padding = false; + + LinkMessageParser inbound_link_msg_parser; + routing::InboundMessageParser inbound_routing_msg_parser; + + service::Context _hidden_service_context; + consensus::reachability_testing router_testing; bool @@ -208,7 +242,7 @@ namespace llarp exit::Context& exitContext() { - return _exitContext; + return _exit_context; } const std::shared_ptr& @@ -265,7 +299,7 @@ namespace llarp return router_contact; } - std::optional> + oxen::quic::Address public_ip() const; util::StatusObject @@ -306,18 +340,18 @@ namespace llarp /// return true if we look like we are a decommissioned service node bool - appear_decommed() const; + appears_decommed() const; /// return true if we look like we are a registered, fully-staked service node (either active or /// decommissioned). This condition determines when we are allowed to (and attempt to) connect /// to other peers when running as a service node. bool - appear_funded() const; + appears_funded() const; /// return true if we a registered service node; not that this only requires a partial stake, /// and does not imply that this service node is *active* or fully funded. bool - appear_registered() const; + appears_registered() const; /// return true if we look like we are allowed and able to test other routers bool @@ -329,28 +363,16 @@ namespace llarp bool Sign(Signature& sig, const llarp_buffer_t& buf) const; - /// how often do we resign our RC? milliseconds. - // TODO: make configurable - llarp_time_t rcRegenInterval = 1h; - - // should we be sending padded messages every interval? - bool sendPadding = false; - - LinkMessageParser inbound_link_msg_parser; - routing::InboundMessageParser inbound_routing_msg_parser; - - service::Context _hiddenServiceContext; - service::Context& hiddenServiceContext() { - return _hiddenServiceContext; + return _hidden_service_context; } const service::Context& hiddenServiceContext() const { - return _hiddenServiceContext; + return _hidden_service_context; } llarp_time_t _lastTick = 0s; @@ -370,51 +392,24 @@ namespace llarp return now <= _lastTick || (now - _lastTick) <= llarp_time_t{30000}; } - /// bootstrap RCs - BootstrapList bootstrapRCList; - const std::shared_ptr& routePoker() const { - return m_RoutePoker; + return _route_poker; } - std::shared_ptr m_RoutePoker; - void TriggerPump(); void PumpLL(); - std::unique_ptr m_RPCServer; - - const llarp_time_t _randomStartDelay; - - std::shared_ptr _rpc_client; - - oxenmq::address lokidRPCAddr; - Profiling _router_profiling; - fs::path _profilesFile; - OutboundMessageHandler _outboundMessageHandler; - LinkManager _link_manager{*this}; - RCLookupHandler _rc_lookup_handler; - RCGossiper _rcGossiper; - std::string status_line(); - using TimePoint_t = std::chrono::steady_clock::time_point; - - TimePoint_t m_NextExploreAt; - void GossipRCIfNeeded(const RouterContact rc); - explicit Router(EventLoop_ptr loop, std::shared_ptr vpnPlatform); - - ~Router(); - bool HandleRecvLinkMessageBuffer(AbstractLinkSession* from, const llarp_buffer_t& msg); diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index b65733a2bc..936bb1cf98 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -123,8 +123,7 @@ namespace llarp { std::string result; auto out = std::back_inserter(result); - for (const auto& addr : addrs) - fmt::format_to(out, "ai_addr={}; ai_pk={}; ", addr.toIpAddress(), addr.pubkey); + 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); diff --git a/llarp/util/priority_queue.hpp b/llarp/util/priority_queue.hpp index 19ef98f554..25204cb08f 100644 --- a/llarp/util/priority_queue.hpp +++ b/llarp/util/priority_queue.hpp @@ -9,5 +9,4 @@ namespace llarp::util template > using ascending_priority_queue = std::priority_queue>; - } // namespace llarp::util From a3e6cec7e7ae97d3f7effc10b46d9e517b45a257 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Tue, 19 Sep 2023 13:09:18 -0700 Subject: [PATCH 037/312] Address type migration + libquic bump - llarp/router/router.hpp, route_poker, and platform code moved to libquic Address types - implementing required methods in link_manager for connection establishment - coming along nicely --- external/oxen-libquic | 2 +- llarp/CMakeLists.txt | 4 - llarp/apple/route_manager.cpp | 12 +- llarp/apple/route_manager.hpp | 22 ++- llarp/apple/vpn_platform.cpp | 10 +- llarp/apple/vpn_platform.hpp | 12 +- llarp/link/link_manager.cpp | 129 +++++++++++--- llarp/link/link_manager.hpp | 30 +++- llarp/messages/link_message.hpp | 13 +- llarp/messages/link_message_parser.cpp | 139 --------------- llarp/messages/link_message_parser.hpp | 49 ------ llarp/router/route_poker.cpp | 206 +++++++++++----------- llarp/router/route_poker.hpp | 38 ++-- llarp/router/router.cpp | 231 ++++++++----------------- llarp/router/router.hpp | 64 +++---- llarp/rpc/rpc_server.cpp | 10 +- llarp/service/context.hpp | 126 +++++++------- llarp/util/meta/memfn.hpp | 117 ++++++------- llarp/vpn/android.hpp | 26 +-- llarp/vpn/linux.hpp | 88 +++++----- llarp/vpn/platform.cpp | 2 +- llarp/vpn/platform.hpp | 33 ++-- llarp/vpn/win32.cpp | 47 ++--- llarp/vpn/win32.hpp | 34 ++-- 24 files changed, 635 insertions(+), 809 deletions(-) delete mode 100644 llarp/messages/link_message_parser.cpp delete mode 100644 llarp/messages/link_message_parser.hpp diff --git a/external/oxen-libquic b/external/oxen-libquic index 2c6b8774c5..009d61e251 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit 2c6b8774c53426b4c99ca6a84c71149789cd77e4 +Subproject commit 009d61e251cf4cfaa70f224b13c4bb7e905d734b diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index d4c01334b9..494f7417a5 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -103,7 +103,6 @@ endif() add_library(lokinet-nodedb STATIC bootstrap.cpp - net/address_info.cpp net/exit_info.cpp net/traffic_policy.cpp nodedb.cpp @@ -201,10 +200,8 @@ add_library(lokinet-layer-link STATIC link/connection.cpp link/link_manager.cpp - link/session.cpp messages/dht_immediate.cpp messages/link_intro.cpp - messages/link_message_parser.cpp ) # lokinet-plainquic is for holding the tunneled plainquic code, not quic wire protocol code @@ -334,7 +331,6 @@ endif() add_library(lokinet-layers INTERFACE) add_library(lokinet-amalgum INTERFACE) - # helper function to link a library to lokinet-base, enable lto, add to lokinet-amalgum and then link to other libs function(lokinet_link_lib libname) message(DEBUG "created target: ${libname}") diff --git a/llarp/apple/route_manager.cpp b/llarp/apple/route_manager.cpp index 021095eaf7..5cfc2c0a4e 100644 --- a/llarp/apple/route_manager.cpp +++ b/llarp/apple/route_manager.cpp @@ -19,7 +19,7 @@ namespace llarp::apple } std::shared_ptr tun; - router->hiddenServiceContext().ForEachService([&tun](const auto& /*name*/, const auto ep) { + router->hidden_service_context().ForEachService([&tun](const auto& /*name*/, const auto ep) { tun = std::dynamic_pointer_cast(ep); return !tun; }); @@ -33,13 +33,13 @@ namespace llarp::apple if (enable) tun->ReconfigureDNS({SockAddr{127, 0, 0, 1, {dns_trampoline_port}}}); else - tun->ReconfigureDNS(router->GetConfig()->dns.m_upstreamDNS); + tun->ReconfigureDNS(router->config()->dns.m_upstreamDNS); trampoline_active = enable; } void - RouteManager::AddDefaultRouteViaInterface(vpn::NetworkInterface&) + RouteManager::add_default_route_via_interface(vpn::NetworkInterface&) { check_trampoline(true); if (callback_context and route_callbacks.add_default_route) @@ -47,7 +47,7 @@ namespace llarp::apple } void - RouteManager::DelDefaultRouteViaInterface(vpn::NetworkInterface&) + RouteManager::delete_default_route_via_interface(vpn::NetworkInterface&) { check_trampoline(false); if (callback_context and route_callbacks.del_default_route) @@ -55,7 +55,7 @@ namespace llarp::apple } void - RouteManager::AddRouteViaInterface(vpn::NetworkInterface&, IPRange range) + RouteManager::add_route_via_interface(vpn::NetworkInterface&, IPRange range) { check_trampoline(true); if (callback_context) @@ -78,7 +78,7 @@ namespace llarp::apple } void - RouteManager::DelRouteViaInterface(vpn::NetworkInterface&, IPRange range) + RouteManager::delete_route_via_interface(vpn::NetworkInterface&, IPRange range) { check_trampoline(false); if (callback_context) diff --git a/llarp/apple/route_manager.hpp b/llarp/apple/route_manager.hpp index 7dfc37e78e..e247b47554 100644 --- a/llarp/apple/route_manager.hpp +++ b/llarp/apple/route_manager.hpp @@ -6,7 +6,7 @@ namespace llarp::apple { - class RouteManager final : public llarp::vpn::IRouteManager + class RouteManager final : public llarp::vpn::AbstractRouteManager { public: RouteManager(llarp::Context& ctx, llarp_route_callbacks rcs, void* callback_context) @@ -16,33 +16,31 @@ namespace llarp::apple /// These are called for poking route holes, but we don't have to do that at all on macos /// because the appex isn't subject to its own rules. void - AddRoute(net::ipaddr_t /*ip*/, net::ipaddr_t /*gateway*/) override + add_route(oxen::quic::Address /*ip*/, oxen::quic::Address /*gateway*/) override {} void - DelRoute(net::ipaddr_t /*ip*/, net::ipaddr_t /*gateway*/) override + delete_route(oxen::quic::Address /*ip*/, oxen::quic::Address /*gateway*/) override {} void - AddDefaultRouteViaInterface(vpn::NetworkInterface& vpn) override; + add_default_route_via_interface(vpn::NetworkInterface& vpn) override; void - DelDefaultRouteViaInterface(vpn::NetworkInterface& vpn) override; + delete_default_route_via_interface(vpn::NetworkInterface& vpn) override; void - AddRouteViaInterface(vpn::NetworkInterface& vpn, IPRange range) override; + add_route_via_interface(vpn::NetworkInterface& vpn, IPRange range) override; void - DelRouteViaInterface(vpn::NetworkInterface& vpn, IPRange range) override; + delete_route_via_interface(vpn::NetworkInterface& vpn, IPRange range) override; - std::vector - GetGatewaysNotOnInterface(vpn::NetworkInterface& /*vpn*/) override + std::vector + get_non_interface_gateways(vpn::NetworkInterface& /*vpn*/) override { // We can't get this on mac from our sandbox, but we don't actually need it because we // ignore the gateway for AddRoute/DelRoute anyway, so just return a zero IP. - std::vector ret; - ret.emplace_back(net::ipv4addr_t{}); - return ret; + return std::vector{}; } private: diff --git a/llarp/apple/vpn_platform.cpp b/llarp/apple/vpn_platform.cpp index bc34f6d5ca..1f94e6e6d0 100644 --- a/llarp/apple/vpn_platform.cpp +++ b/llarp/apple/vpn_platform.cpp @@ -9,15 +9,15 @@ namespace llarp::apple VPNInterface::on_readable_callback on_readable, llarp_route_callbacks route_callbacks, void* callback_context) - : m_Context{ctx} - , m_RouteManager{ctx, std::move(route_callbacks), callback_context} - , m_PacketWriter{std::move(packet_writer)} - , m_OnReadable{std::move(on_readable)} + : _context{ctx} + , _route_manager{ctx, std::move(route_callbacks), callback_context} + , _packet_writer{std::move(packet_writer)} + , _read_cb{std::move(on_readable)} {} std::shared_ptr VPNPlatform::ObtainInterface(vpn::InterfaceInfo, Router* router) { - return std::make_shared(m_Context, m_PacketWriter, m_OnReadable, router); + return std::make_shared(_context, _packet_writer, _read_cb, router); } } // namespace llarp::apple diff --git a/llarp/apple/vpn_platform.hpp b/llarp/apple/vpn_platform.hpp index b5b4361684..5cbe2858f3 100644 --- a/llarp/apple/vpn_platform.hpp +++ b/llarp/apple/vpn_platform.hpp @@ -19,17 +19,17 @@ namespace llarp::apple std::shared_ptr ObtainInterface(vpn::InterfaceInfo, Router*) override; - vpn::IRouteManager& + vpn::AbstractRouteManager& RouteManager() override { - return m_RouteManager; + return _route_manager; } private: - Context& m_Context; - apple::RouteManager m_RouteManager; - VPNInterface::packet_write_callback m_PacketWriter; - VPNInterface::on_readable_callback m_OnReadable; + Context& _context; + apple::RouteManager _route_manager; + VPNInterface::packet_write_callback _packet_writer; + VPNInterface::on_readable_callback _read_cb; }; } // namespace llarp::apple diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 962fa43279..ce2c8dfd7f 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -34,12 +34,20 @@ namespace llarp } bool - Endpoint::deregister_peer(RouterID remote) + Endpoint::deregister_peer(RouterID _rid) { - if (auto itr = conns.find(remote); itr != conns.end()) + if (auto itr = conns.find(_rid); itr != conns.end()) { - itr->second->conn->close_connection(); - conns.erase(itr); + auto& c = itr->second; + auto& _scid = c->conn->scid(); + + link_manager.router.loop()->call([this, scid = _scid, rid = _rid]() { + endpoint->close_connection(scid); + + conns.erase(rid); + connid_map.erase(scid); + }); + return true; } @@ -74,8 +82,42 @@ namespace llarp log::warning(quic_cat, "Error: failed to fetch random connection"); return false; } + + void + Endpoint::for_each_connection(std::function func) + { + for (const auto& [rid, conn] : conns) + func(*conn); + } + + void + Endpoint::close_connection(RouterID _rid) + { + if (auto itr = conns.find(_rid); itr != conns.end()) + { + auto& c = itr->second; + auto& _scid = c->conn->scid(); + + link_manager.router.loop()->call([this, scid = _scid, rid = _rid]() { + endpoint->close_connection(scid); + + conns.erase(rid); + connid_map.erase(scid); + }); + } + } + } // namespace link + void + LinkManager::for_each_connection(std::function func) + { + if (is_stopping) + return; + + return ep.for_each_connection(func); + } + // TODO: pass connection open callback to endpoint constructor! LinkManager::LinkManager(Router& r) : router{r} @@ -85,7 +127,10 @@ namespace llarp {reinterpret_cast(router.identity().toPublic().data()), size_t{32}})} , ep{quic->endpoint( router.public_ip(), - [this](oxen::quic::connection_interface& ci) { return on_conn_open(ci); }), + [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); + }), *this} {} @@ -93,7 +138,7 @@ namespace llarp bool LinkManager::send_to(const RouterID& remote, bstring data, uint16_t priority) { - if (stopping) + if (is_stopping) return false; if (not have_connection_to(remote)) @@ -127,10 +172,16 @@ namespace llarp } void - LinkManager::connect_to(RouterID router) + LinkManager::close_connection(RouterID rid) + { + return ep.close_connection(rid); + } + + void + LinkManager::connect_to(RouterID rid) { rc_lookup->get_rc( - router, + rid, [this]( [[maybe_unused]] const RouterID& rid, const RouterContact* const rc, @@ -177,29 +228,55 @@ namespace llarp log::warning(quic_cat, "Connection to {} successfully established!", remote_addr); } + // TODO: should we add routes here now that Router::SessionOpen is gone? void LinkManager::on_conn_open(oxen::quic::connection_interface& ci) { - router.loop()->call([]() {}); + router.loop()->call([this, &conn_interface = ci]() { + const auto& scid = conn_interface.scid(); + const auto& rid = ep.connid_map[scid]; - const auto& scid = ci.scid(); - const auto& rid = ep.connid_map[scid]; + if (auto itr = pending_conn_msg_queue.find(rid); itr != pending_conn_msg_queue.end()) + { + auto& que = itr->second; - if (auto itr = pending_conn_msg_queue.find(rid); itr != pending_conn_msg_queue.end()) - { - auto& que = itr->second; + while (not que.empty()) + { + auto& m = que.top(); + + (m.is_control) ? ep.conns[rid]->control_stream->send(std::move(m.buf)) + : conn_interface.send_datagram(std::move(m.buf)); - while (not que.empty()) + que.pop(); + } + } + }); + }; + + void + LinkManager::on_conn_closed(oxen::quic::connection_interface& ci, uint64_t ec) + { + router.loop()->call([this, &conn_interface = ci, error_code = ec]() { + const auto& scid = conn_interface.scid(); + + log::debug(quic_cat, "Purging quic connection CID:{} (ec: {})", scid, error_code); + + if (const auto& c_itr = ep.connid_map.find(scid); c_itr != ep.connid_map.end()) { - auto& m = que.top(); + const auto& rid = c_itr->second; - (m.is_control) ? ep.conns[rid]->control_stream->send(std::move(m.buf)) - : ci.send_datagram(std::move(m.buf)); + if (auto p_itr = pending_conn_msg_queue.find(rid); p_itr != pending_conn_msg_queue.end()) + pending_conn_msg_queue.erase(p_itr); - que.pop(); + if (auto m_itr = ep.conns.find(rid); m_itr != ep.conns.end()) + ep.conns.erase(m_itr); + + ep.connid_map.erase(c_itr); + + log::debug(quic_cat, "Quic connection CID:{} purged successfully", scid); } - } - }; + }); + } bool LinkManager::have_connection_to(const RouterID& remote, bool client_only) const @@ -228,7 +305,7 @@ namespace llarp void LinkManager::stop() { - if (stopping) + if (is_stopping) { return; } @@ -236,7 +313,7 @@ namespace llarp util::Lock l(m); LogInfo("stopping links"); - stopping = true; + is_stopping = true; quic.reset(); } @@ -244,7 +321,7 @@ namespace llarp void LinkManager::set_conn_persist(const RouterID& remote, llarp_time_t until) { - if (stopping) + if (is_stopping) return; util::Lock l(m); @@ -279,7 +356,7 @@ namespace llarp void LinkManager::check_persisting_conns(llarp_time_t) { - if (stopping) + if (is_stopping) return; } @@ -298,7 +375,7 @@ namespace llarp void LinkManager::init(RCLookupHandler* rcLookup) { - stopping = false; + is_stopping = false; rc_lookup = rcLookup; node_db = router.node_db(); } diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index b53f29bcfe..063f9120a5 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -66,6 +67,12 @@ namespace llarp bool establish_connection(const oxen::quic::Address& remote, RouterContact& rc, Opt&&... opts); + void + for_each_connection(std::function func); + + void + close_connection(RouterID rid); + private: }; } // namespace link @@ -114,7 +121,7 @@ namespace llarp private: friend struct link::Endpoint; - std::atomic stopping; + std::atomic is_stopping; // DISCUSS: is this necessary? can we reduce the amount of locking and nuke this mutable util::Mutex m; // protects persisting_conns @@ -148,9 +155,24 @@ namespace llarp void on_conn_open(oxen::quic::connection_interface& ci); + void + on_conn_closed(oxen::quic::connection_interface& ci, uint64_t ec); + public: explicit LinkManager(Router& r); + const link::Endpoint& + endpoint() + { + return ep; + } + + const oxen::quic::Address& + local() + { + return addr; + } + bool send_to(const RouterID& remote, bstring data, uint16_t priority); @@ -169,6 +191,9 @@ namespace llarp void connect_to(RouterContact rc); + void + close_connection(RouterID rid); + void stop(); @@ -196,6 +221,9 @@ namespace llarp void init(RCLookupHandler* rcLookup); + void + for_each_connection(std::function func); + // Attempts to connect to a number of random routers. // // This will try to connect to *up to* num_conns routers, but will not diff --git a/llarp/messages/link_message.hpp b/llarp/messages/link_message.hpp index 237fda914b..6793886fa7 100644 --- a/llarp/messages/link_message.hpp +++ b/llarp/messages/link_message.hpp @@ -10,18 +10,21 @@ namespace llarp { - struct AbstractLinkSession; + namespace link + { + struct Connection; + } + struct Router; /// parsed link layer message struct AbstractLinkMessage : private AbstractSerializable { - /// who did this message come from or is going to - AbstractLinkSession* session = nullptr; - uint64_t version = llarp::constants::proto_version; - + std::shared_ptr conn; PathID_t pathid; + uint64_t version = llarp::constants::proto_version; + AbstractLinkMessage() = default; virtual ~AbstractLinkMessage() = default; diff --git a/llarp/messages/link_message_parser.cpp b/llarp/messages/link_message_parser.cpp deleted file mode 100644 index 5651fc9dfe..0000000000 --- a/llarp/messages/link_message_parser.cpp +++ /dev/null @@ -1,139 +0,0 @@ -#include "link_message_parser.hpp" - -#include "dht_immediate.hpp" -#include "discard.hpp" -#include "link_intro.hpp" -#include "link_message.hpp" -#include "relay_commit.hpp" -#include "relay_status.hpp" -#include "relay.hpp" -#include -#include -#include - -#include - -namespace llarp -{ - struct LinkMessageParser::msg_holder_t - { - LinkIntroMessage i; - RelayDownstreamMessage d; - RelayUpstreamMessage u; - DHTImmediateMessage m; - LR_CommitMessage c; - LR_StatusMessage s; - LinkDiscardMessage x; - - msg_holder_t() = default; - }; - - LinkMessageParser::LinkMessageParser(Router* _router) - : router(_router), from(nullptr), msg(nullptr), holder(std::make_unique()) - {} - - LinkMessageParser::~LinkMessageParser() = default; - - bool - LinkMessageParser::operator()(llarp_buffer_t* buffer, llarp_buffer_t* key) - { - // we are reading the first key - if (firstkey) - { - llarp_buffer_t strbuf; - // check for empty dict - if (!key) - return false; - // we are expecting the first key to be 'a' - if (!key->startswith("a")) - { - llarp::LogWarn("message has no message type"); - return false; - } - - if (!bencode_read_string(buffer, &strbuf)) - { - llarp::LogWarn("could not read value of message type"); - return false; - } - // bad key size - if (strbuf.sz != 1) - { - llarp::LogWarn("bad mesage type size: ", strbuf.sz); - return false; - } - // create the message to parse based off message type - llarp::LogDebug("inbound message ", *strbuf.cur); - switch (*strbuf.cur) - { - case 'i': - msg = &holder->i; - break; - case 'd': - msg = &holder->d; - break; - case 'u': - msg = &holder->u; - break; - case 'm': - msg = &holder->m; - break; - case 'c': - msg = &holder->c; - break; - case 's': - msg = &holder->s; - break; - case 'x': - msg = &holder->x; - break; - default: - return false; - } - - msg->session = from; - firstkey = false; - return true; - } - // check for last element - if (!key) - return MessageDone(); - - return msg->decode_key(*key, buffer); - } - - bool - LinkMessageParser::MessageDone() - { - bool result = false; - if (msg) - { - result = msg->handle_message(router); - } - Reset(); - return result; - } - - bool - LinkMessageParser::ProcessFrom(AbstractLinkSession* src, const llarp_buffer_t& buf) - { - if (!src) - { - llarp::LogWarn("no link session"); - return false; - } - - from = src; - firstkey = true; - ManagedBuffer copy(buf); - return bencode_read_dict(*this, ©.underlying); - } - - void - LinkMessageParser::Reset() - { - if (msg) - msg->clear(); - msg = nullptr; - } -} // namespace llarp diff --git a/llarp/messages/link_message_parser.hpp b/llarp/messages/link_message_parser.hpp deleted file mode 100644 index dffe4f75bb..0000000000 --- a/llarp/messages/link_message_parser.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include -#include - -#include - -namespace llarp -{ - struct Router; - struct AbstractLinkMessage; - struct AbstractLinkSession; - - struct LinkMessageParser - { - LinkMessageParser(Router* router); - ~LinkMessageParser(); - - bool - operator()(llarp_buffer_t* buffer, llarp_buffer_t* key); - - /// start processig message from a link session - bool - ProcessFrom(AbstractLinkSession* from, const llarp_buffer_t& buf); - - /// called when the message is fully read - /// return true when the message was accepted otherwise returns false - bool - MessageDone(); - - /// resets internal state - void - Reset(); - - private: - RouterID - GetCurrentFrom(); - - private: - bool firstkey; - Router* router; - AbstractLinkSession* from; - AbstractLinkMessage* msg; - - struct msg_holder_t; - - std::unique_ptr holder; - }; -} // namespace llarp diff --git a/llarp/router/route_poker.cpp b/llarp/router/route_poker.cpp index cd9434bdd7..14783454f9 100644 --- a/llarp/router/route_poker.cpp +++ b/llarp/router/route_poker.cpp @@ -10,134 +10,133 @@ namespace llarp static auto logcat = log::Cat("route-poker"); void - RoutePoker::AddRoute(net::ipv4addr_t ip) + RoutePoker::add_route(oxen::quic::Address ip) { - if (not m_up) + if (not is_up) return; - bool has_existing = m_PokedRoutes.count(ip); + + bool has_existing = poked_routes.count(ip); + // set up route and apply as needed - auto& gw = m_PokedRoutes[ip]; - if (m_CurrentGateway) + auto& gw = poked_routes[ip]; + + if (current_gateway) { // remove existing mapping as needed if (has_existing) - DisableRoute(ip, gw); + disable_route(ip, gw); // update and add new mapping - gw = *m_CurrentGateway; - log::info(logcat, "add route {} via {}", ip, gw); - EnableRoute(ip, gw); + gw = *current_gateway; + + log::info(logcat, "Added route to {} via {}", ip, gw); + + enable_route(ip, gw); } else - gw = net::ipv4addr_t{}; + gw = oxen::quic::Address{}; } void - RoutePoker::DisableRoute(net::ipv4addr_t ip, net::ipv4addr_t gateway) + RoutePoker::disable_route(oxen::quic::Address ip, oxen::quic::Address gateway) { - if (ip.n and gateway.n and IsEnabled()) + if (ip.is_set() and gateway.is_set() and is_enabled()) { - vpn::IRouteManager& route = m_Router->vpn_platform()->RouteManager(); - route.DelRoute(ip, gateway); + vpn::AbstractRouteManager& route = router.vpn_platform()->RouteManager(); + route.delete_route(ip, gateway); } } void - RoutePoker::EnableRoute(net::ipv4addr_t ip, net::ipv4addr_t gateway) + RoutePoker::enable_route(oxen::quic::Address ip, oxen::quic::Address gateway) { - if (ip.n and gateway.n and IsEnabled()) + if (ip.is_set() and gateway.is_set() and is_enabled()) { - vpn::IRouteManager& route = m_Router->vpn_platform()->RouteManager(); - route.AddRoute(ip, gateway); + vpn::AbstractRouteManager& route = router.vpn_platform()->RouteManager(); + route.add_route(ip, gateway); } } void - RoutePoker::DelRoute(net::ipv4addr_t ip) + RoutePoker::delete_route(oxen::quic::Address ip) { - const auto itr = m_PokedRoutes.find(ip); - if (itr == m_PokedRoutes.end()) - return; - log::info(logcat, "del route {} via {}", itr->first, itr->second); - DisableRoute(itr->first, itr->second); - m_PokedRoutes.erase(itr); + if (const auto itr = poked_routes.find(ip); itr != poked_routes.end()) + { + log::info(logcat, "Deleting route to {} via {}", itr->first, itr->second); + disable_route(itr->first, itr->second); + poked_routes.erase(itr); + } } void - RoutePoker::Start(Router* router) + RoutePoker::start() { - m_Router = router; - if (not IsEnabled()) + if (not is_enabled()) return; - m_Router->loop()->call_every(100ms, weak_from_this(), [self = weak_from_this()]() { + router.loop()->call_every(100ms, weak_from_this(), [self = weak_from_this()]() { if (auto ptr = self.lock()) - ptr->Update(); + ptr->update(); }); } void - RoutePoker::DeleteAllRoutes() + RoutePoker::delete_all_routes() { // DelRoute will check enabled, so no need here - for (const auto& item : m_PokedRoutes) - DelRoute(item.first); + for (const auto& item : poked_routes) + delete_route(item.first); } void - RoutePoker::DisableAllRoutes() + RoutePoker::disable_all_routes() { - for (const auto& [ip, gateway] : m_PokedRoutes) + for (const auto& [ip, gateway] : poked_routes) { - DisableRoute(ip, gateway); + disable_route(ip, gateway); } } void - RoutePoker::RefreshAllRoutes() + RoutePoker::refresh_all_routes() { - for (const auto& item : m_PokedRoutes) - AddRoute(item.first); + for (const auto& item : poked_routes) + add_route(item.first); } RoutePoker::~RoutePoker() { - if (not m_Router or not m_Router->vpn_platform()) + if (not router.vpn_platform()) return; - auto& route = m_Router->vpn_platform()->RouteManager(); - for (const auto& [ip, gateway] : m_PokedRoutes) + auto& route = router.vpn_platform()->RouteManager(); + for (const auto& [ip, gateway] : poked_routes) { - if (gateway.n and ip.n) - route.DelRoute(ip, gateway); + if (gateway.is_set() and ip.is_set()) + route.delete_route(ip, gateway); } - route.DelBlackhole(); + route.delete_blackhole(); } bool - RoutePoker::IsEnabled() const + RoutePoker::is_enabled() const { - if (not m_Router) - throw std::runtime_error{"Attempting to use RoutePoker before calling Init"}; - if (m_Router->IsServiceNode()) + if (router.IsServiceNode()) return false; - if (const auto& conf = m_Router->config()) + if (const auto& conf = router.config()) return conf->network.m_EnableRoutePoker; throw std::runtime_error{"Attempting to use RoutePoker with router with no config set"}; } void - RoutePoker::Update() + RoutePoker::update() { - if (not m_Router) - throw std::runtime_error{"Attempting to use RoutePoker before calling Init"}; - // ensure we have an endpoint - auto ep = m_Router->hiddenServiceContext().GetDefault(); + auto ep = router.hidden_service_context().GetDefault(); if (ep == nullptr) return; // ensure we have a vpn platform - auto* platform = m_Router->vpn_platform(); + auto* platform = router.vpn_platform(); if (platform == nullptr) return; // ensure we have a vpn interface @@ -148,47 +147,48 @@ namespace llarp auto& route = platform->RouteManager(); // get current gateways, assume sorted by lowest metric first - auto gateways = route.GetGatewaysNotOnInterface(*vpn); - std::optional next_gw; - for (auto& gateway : gateways) + auto gateways = route.get_non_interface_gateways(*vpn); + std::optional next_gw; + + for (auto& g : gateways) { - if (auto* gw_ptr = std::get_if(&gateway)) + if (g.is_ipv4()) { - next_gw = *gw_ptr; + next_gw = g; break; } } // update current gateway and apply state changes as needed - if (m_CurrentGateway != next_gw) + if (!(current_gateway == next_gw)) { - if (next_gw and m_CurrentGateway) + if (next_gw and current_gateway) { - log::info(logcat, "default gateway changed from {} to {}", *m_CurrentGateway, *next_gw); - m_CurrentGateway = next_gw; - m_Router->Thaw(); - RefreshAllRoutes(); + log::info(logcat, "default gateway changed from {} to {}", *current_gateway, *next_gw); + current_gateway = next_gw; + router.Thaw(); + refresh_all_routes(); } - else if (m_CurrentGateway) + else if (current_gateway) { - log::warning(logcat, "default gateway {} has gone away", *m_CurrentGateway); - m_CurrentGateway = next_gw; - m_Router->Freeze(); + log::warning(logcat, "default gateway {} has gone away", *current_gateway); + current_gateway = next_gw; + router.Freeze(); } else // next_gw and not m_CurrentGateway { log::info(logcat, "default gateway found at {}", *next_gw); - m_CurrentGateway = next_gw; + current_gateway = next_gw; } } - else if (m_Router->HasClientExit()) - Up(); + else if (router.HasClientExit()) + put_up(); } void - RoutePoker::SetDNSMode(bool exit_mode_on) const + RoutePoker::set_dns_mode(bool exit_mode_on) const { - auto ep = m_Router->hiddenServiceContext().GetDefault(); + auto ep = router.hidden_service_context().GetDefault(); if (not ep) return; if (auto dns_server = ep->DNS()) @@ -196,17 +196,17 @@ namespace llarp } void - RoutePoker::Up() + RoutePoker::put_up() { - bool was_up = m_up; - m_up = true; + bool was_up = is_up; + is_up = true; if (not was_up) { - if (not IsEnabled()) + if (not is_enabled()) { log::warning(logcat, "RoutePoker coming up, but route poking is disabled by config"); } - else if (not m_CurrentGateway) + else if (not current_gateway) { log::warning(logcat, "RokerPoker came up, but we don't know of a gateway!"); } @@ -214,50 +214,48 @@ namespace llarp { log::info(logcat, "RoutePoker coming up; poking routes"); - vpn::IRouteManager& route = m_Router->vpn_platform()->RouteManager(); + vpn::AbstractRouteManager& route = router.vpn_platform()->RouteManager(); // black hole all routes if enabled - if (m_Router->config()->network.m_BlackholeRoutes) - route.AddBlackhole(); + if (router.config()->network.m_BlackholeRoutes) + route.add_blackhole(); // explicit route pokes for first hops - m_Router->ForEachPeer( - [this](auto session, auto) { AddRoute(session->GetRemoteEndpoint().getIPv4()); }, - false); + router.for_each_connection( + [this](link::Connection conn) { add_route(conn.remote_rc.addr); }); + + add_route(router.link_manager().local()); // add default route - const auto ep = m_Router->hiddenServiceContext().GetDefault(); + const auto ep = router.hidden_service_context().GetDefault(); if (auto* vpn = ep->GetVPNInterface()) - route.AddDefaultRouteViaInterface(*vpn); + route.add_default_route_via_interface(*vpn); log::info(logcat, "route poker up"); } } if (not was_up) - SetDNSMode(true); + set_dns_mode(true); } void - RoutePoker::Down() + RoutePoker::put_down() { // unpoke routes for first hops - m_Router->ForEachPeer( - [this](auto session, auto) { DelRoute(session->GetRemoteEndpoint().getIPv4()); }, false); - - // remove default route - - if (IsEnabled() and m_up) + router.for_each_connection( + [this](link::Connection conn) { delete_route(conn.remote_rc.addr); }); + if (is_enabled() and is_up) { - vpn::IRouteManager& route = m_Router->vpn_platform()->RouteManager(); - const auto ep = m_Router->hiddenServiceContext().GetDefault(); + vpn::AbstractRouteManager& route = router.vpn_platform()->RouteManager(); + const auto ep = router.hidden_service_context().GetDefault(); if (auto* vpn = ep->GetVPNInterface()) - route.DelDefaultRouteViaInterface(*vpn); + route.delete_default_route_via_interface(*vpn); // delete route blackhole - route.DelBlackhole(); + route.delete_blackhole(); log::info(logcat, "route poker down"); } - if (m_up) - SetDNSMode(false); - m_up = false; + if (is_up) + set_dns_mode(false); + is_up = false; } } // namespace llarp diff --git a/llarp/router/route_poker.hpp b/llarp/router/route_poker.hpp index a5399cecc7..e98346ec80 100644 --- a/llarp/router/route_poker.hpp +++ b/llarp/router/route_poker.hpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace llarp { @@ -12,57 +13,60 @@ namespace llarp struct RoutePoker : public std::enable_shared_from_this { + RoutePoker(Router& r) : router{r} + {} + void - AddRoute(net::ipv4addr_t ip); + add_route(oxen::quic::Address ip); void - DelRoute(net::ipv4addr_t ip); + delete_route(oxen::quic::Address ip); void - Start(Router* router); + start(); ~RoutePoker(); /// explicitly put routes up void - Up(); + put_up(); /// explicitly put routes down void - Down(); + put_down(); /// set dns resolver /// pass in if we are using exit node mode right now as a bool void - SetDNSMode(bool using_exit_mode) const; + set_dns_mode(bool using_exit_mode) const; private: void - Update(); + update(); bool - IsEnabled() const; + is_enabled() const; void - DeleteAllRoutes(); + delete_all_routes(); void - DisableAllRoutes(); + disable_all_routes(); void - RefreshAllRoutes(); + refresh_all_routes(); void - EnableRoute(net::ipv4addr_t ip, net::ipv4addr_t gateway); + enable_route(oxen::quic::Address ip, oxen::quic::Address gateway); void - DisableRoute(net::ipv4addr_t ip, net::ipv4addr_t gateway); + disable_route(oxen::quic::Address ip, oxen::quic::Address gateway); - std::unordered_map m_PokedRoutes; + std::unordered_map poked_routes; - std::optional m_CurrentGateway; + std::optional current_gateway; - Router* m_Router = nullptr; - bool m_up{false}; + Router& router; + bool is_up{false}; }; } // namespace llarp diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index e2dd076478..04560fc6a1 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -46,7 +46,7 @@ namespace llarp static auto logcat = log::Cat("router"); Router::Router(EventLoop_ptr loop, std::shared_ptr vpnPlatform) - : _route_poker{std::make_shared()} + : _route_poker{std::make_shared(this)} , _lmq{std::make_shared()} , _loop{std::move(loop)} , _vpn{std::move(vpnPlatform)} @@ -56,7 +56,6 @@ namespace llarp , _disk_thread{_lmq->add_tagged_thread("disk")} , m_RPCServer{nullptr} , _randomStartDelay{platform::is_simulation ? std::chrono::milliseconds{(llarp::randint() % 1250) + 2000} : 0s} - , inbound_link_msg_parser{this} , _hidden_service_context{this} { _key_manager = std::make_shared(); @@ -64,7 +63,7 @@ namespace llarp _lmq->MAX_MSG_SIZE = -1; is_stopping.store(false); is_running.store(false); - _lastTick = llarp::time_now_ms(); + _last_tick = llarp::time_now_ms(); _next_explore_at = std::chrono::steady_clock::now(); loop_wakeup = _loop->make_waker([this]() { PumpLL(); }); } @@ -206,16 +205,17 @@ namespace llarp // TODO: libquic change bool - Router::HandleRecvLinkMessageBuffer(AbstractLinkSession* session, const llarp_buffer_t& buf) + Router::recv_link_message_buffer(std::shared_ptr conn, bstring_view buf) { if (is_stopping) return true; - if (!session) + if (!conn) { - LogWarn("no link session"); + log::warning(quic_cat, "No connection to pass link message buffer to!"); return false; } + return inbound_link_msg_parser.ProcessFrom(session, buf); } @@ -224,15 +224,9 @@ namespace llarp { if (IsServiceNode()) return; - /* - *TODO: investigate changes needed for libquic integration - * - linkManager().ForEachPeer([](auto peer) { - if (peer) - peer->Close(); - }); - * - */ + + for_each_connection( + [this](link::Connection& conn) { loop()->call([&]() { conn.conn->close_connection(); }); }); } void @@ -240,30 +234,16 @@ namespace llarp { if (IsServiceNode()) return; - /* - *TODO: investigate changes needed for libquic integration - * - // get pubkeys we are connected to - std::unordered_set peerPubkeys; - linkManager().ForEachPeer([&peerPubkeys](auto peer) { - if (not peer) - return; - peerPubkeys.emplace(peer->GetPubKey()); - }); - // close our sessions to them on link layer - linkManager().ForEachOutboundLink([peerPubkeys](const auto& link) { - for (const auto& remote : peerPubkeys) - link->CloseSessionTo(remote); - }); - // thaw endpoints - hiddenServiceContext().ForEachService([](const auto& name, const auto& ep) -> bool { - LogInfo(name, " thawing..."); - ep->Thaw(); - return true; + + std::unordered_set peer_pubkeys; + + for_each_connection( + [&peer_pubkeys](link::Connection& conn) { peer_pubkeys.emplace(conn.remote_rc.pubkey); }); + + loop()->call([this, &peer_pubkeys]() { + for (auto& pk : peer_pubkeys) + _link_manager.close_connection(pk); }); - LogInfo("We are ready to go bruh... probably"); - * - */ } void @@ -316,20 +296,6 @@ namespace llarp return _outboundMessageHandler.QueueMessage(remote, msg, handler); } - // TODO: if still needed/useful, replace this in line with libquic impl - void - Router::ForEachPeer(std::function, bool) const - { - //_linkManager.ForEachPeer(visit, randomize); - } - - // TODO: if still needed/useful, replace this in line with libquic impl - void - Router::ForEachPeer(std::function) - { - //_linkManager.ForEachPeer(visit); - } - void Router::try_connect(fs::path rcfile) { @@ -347,6 +313,11 @@ namespace llarp else LogError(rcfile, " contains invalid RC"); } + void + Router::for_each_connection(std::function func) + { + return _link_manager.for_each_connection(func); + } bool Router::EnsureIdentity() @@ -528,8 +499,8 @@ namespace llarp Router::Close() { log::info(logcat, "closing"); - if (_onDown) - _onDown(); + if (_router_close_cb) + _router_close_cb(); log::debug(logcat, "stopping mainloop"); _loop->stop(); is_running.store(false); @@ -834,7 +805,7 @@ namespace llarp // API config if (not IsServiceNode()) { - hiddenServiceContext().AddEndpoint(conf); + hidden_service_context().AddEndpoint(conf); } return true; @@ -915,7 +886,7 @@ namespace llarp node_db()->NumLoaded(), NumberOfConnectedRouters()); - if (auto ep = hiddenServiceContext().GetDefault()) + if (auto ep = hidden_service_context().GetDefault()) { fmt::format_to( out, @@ -940,7 +911,7 @@ namespace llarp return; // LogDebug("tick router"); const auto now = Now(); - if (const auto delta = now - _lastTick; _lastTick != 0s and delta > TimeskipDetectedDuration) + if (const auto delta = now - _last_tick; _last_tick != 0s and delta > TimeskipDetectedDuration) { // we detected a time skip into the futre, thaw the network LogWarn("Timeskip of ", ToString(delta), " detected. Resetting network state"); @@ -962,27 +933,27 @@ namespace llarp _rc_lookup_handler.periodic_update(now); - const bool gotWhitelist = _rc_lookup_handler.has_received_whitelist(); - const bool isSvcNode = IsServiceNode(); - const bool decom = appears_decommed(); - bool shouldGossip = isSvcNode and follow_whitelist and gotWhitelist + const bool has_whitelist = _rc_lookup_handler.has_received_whitelist(); + const bool is_snode = IsServiceNode(); + const bool is_decommed = appears_decommed(); + bool should_gossip = is_snode and follow_whitelist and has_whitelist and _rc_lookup_handler.is_session_allowed(pubkey()); - if (isSvcNode + if (is_snode and (router_contact.ExpiresSoon(now, std::chrono::milliseconds(randint() % 10000)) or (now - router_contact.last_updated) > rc_regen_interval)) { LogInfo("regenerating RC"); if (update_rc()) { // our rc changed so we should gossip it - shouldGossip = true; + should_gossip = true; // remove our replay entry so it goes out _rcGossiper.Forget(pubkey()); } else LogError("failed to update our RC"); } - if (shouldGossip) + if (should_gossip) { // if we have the whitelist enabled, we have fetched the list and we are in either // the white or grey list, we want to gossip our RC @@ -1012,7 +983,7 @@ namespace llarp // clients have no notion of a whilelist // we short circuit logic here so we dont remove // routers that are not whitelisted for first hops - if (not isSvcNode) + if (not is_snode) { log::trace(logcat, "Not removing {}: we are a client and it looks fine", rc.pubkey); return false; @@ -1020,7 +991,7 @@ namespace llarp // if we have a whitelist enabled and we don't // have the whitelist yet don't remove the entry - if (follow_whitelist and not gotWhitelist) + if (follow_whitelist and not has_whitelist) { log::debug(logcat, "Skipping check on {}: don't have whitelist yet", rc.pubkey); return false; @@ -1029,7 +1000,7 @@ namespace llarp // 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 (gotWhitelist and not _rc_lookup_handler.is_session_allowed(rc.pubkey)) + if (has_whitelist and not _rc_lookup_handler.is_session_allowed(rc.pubkey)) { log::debug(logcat, "Removing {}: not a valid router", rc.pubkey); return true; @@ -1038,37 +1009,29 @@ namespace llarp }); // find all deregistered relays - std::unordered_set closePeers; + std::unordered_set close_peers; - /* - * TODO: change for libquic - * - _linkManager.ForEachPeer([&](auto session) { - if (whitelistRouters and not gotWhitelist) + for_each_connection([this, &has_whitelist, &close_peers](link::Connection& conn) { + if (follow_whitelist && has_whitelist) return; - if (not session) - return; - const auto pk = session->GetPubKey(); - if (session->IsRelay() and not _rcLookupHandler.SessionIsAllowed(pk)) - { - closePeers.emplace(pk); - } + + const auto pk = conn.remote_rc.pubkey; + + if (conn.remote_is_relay and not _rc_lookup_handler.is_session_allowed(pk)) + close_peers.emplace(pk); }); - * - * - */ // mark peers as de-registered - for (auto& peer : closePeers) + for (auto& peer : close_peers) _link_manager.deregister_peer(std::move(peer)); _link_manager.check_persisting_conns(now); size_t connected = NumberOfConnectedRouters(); - const int interval = isSvcNode ? 5 : 2; + const int interval = is_snode ? 5 : 2; const auto timepoint_now = std::chrono::steady_clock::now(); - if (timepoint_now >= _next_explore_at and not decom) + if (timepoint_now >= _next_explore_at and not is_decommed) { _rc_lookup_handler.explore_network(); _next_explore_at = timepoint_now + std::chrono::seconds(interval); @@ -1080,19 +1043,19 @@ namespace llarp connectToNum = strictConnect; } - if (isSvcNode and now >= _next_decomm_warning) + if (is_snode and now >= _next_decomm_warning) { constexpr auto DecommissionWarnInterval = 5min; if (auto registered = appears_registered(), funded = appears_funded(); - not(registered and funded and not decom)) + not(registered and funded and not is_decommed)) { // complain about being deregistered/decommed/unfunded log::error( logcat, "We are running as a service node but we seem to be {}", - not registered ? "deregistered" - : decom ? "decommissioned" - : "not fully staked"); + not registered ? "deregistered" + : is_decommed ? "decommissioned" + : "not fully staked"); _next_decomm_warning = now + DecommissionWarnInterval; } else if (insufficient_peers()) @@ -1107,7 +1070,7 @@ namespace llarp // if we need more sessions to routers and we are not a service node kicked from the network or // we are a client we shall connect out to others - if (connected < connectToNum and (appears_funded() or not isSvcNode)) + if (connected < connectToNum and (appears_funded() or not is_snode)) { size_t dlt = connectToNum - connected; LogDebug("connecting to ", dlt, " random routers to keep alive"); @@ -1148,25 +1111,18 @@ namespace llarp } } - /* - *TODO: libquic change - * - // get connected peers - std::set peersWeHave; - _linkManager.ForEachPeer([&peersWeHave](ILinkSession* s) { - if (!s->IsEstablished()) - return; - peersWeHave.emplace(s->GetPubKey()); - }); - // remove any nodes we don't have connections to - _dht->impl->Nodes()->RemoveIf( - [&peersWeHave](const dht::Key_t& k) -> bool { return peersWeHave.count(k) == 0; }); - // expire paths + std::set peer_keys; + + for_each_connection( + [&peer_keys](link::Connection& conn) { peer_keys.emplace(conn.remote_rc.pubkey); }); + + dht()->Nodes()->RemoveIf( + [&peer_keys](const dht::Key_t& k) -> bool { return peer_keys.count(k) == 0; }); + paths.ExpirePaths(now); - * - */ + // update tick timestamp - _lastTick = llarp::time_now_ms(); + _last_tick = llarp::time_now_ms(); } bool @@ -1175,35 +1131,6 @@ namespace llarp return CryptoManager::instance()->sign(sig, identity(), buf); } - // TODO: replace this in line with libquic impl - void - Router::SessionClosed(RouterID remote) - { - dht::Key_t k(remote); - dht()->Nodes()->DelNode(k); - - LogInfo("Session to ", remote, " fully closed"); - if (IsServiceNode()) - return; - if (const auto maybe = node_db()->Get(remote); maybe.has_value()) - { - for (const auto& addr : maybe->addrs) - m_RoutePoker->DelRoute(addr.IPv4()); - } - } - - // TODO: replace this in line with libquic impl - void - Router::ConnectionTimedOut(AbstractLinkSession* session) - { - if (_peer_db) - { - RouterID id{session->GetPubKey()}; - // TODO: make sure this is a public router (on whitelist)? - _peer_db->modifyPeerStats(id, [&](PeerStats& stats) { stats.numConnectionTimeouts++; }); - } - } - void Router::modify_rc(std::function(RouterContact)> modify) { @@ -1215,20 +1142,6 @@ namespace llarp } } - // TODO: replace this in line with libquic impl - bool - Router::ConnectionEstablished(AbstractLinkSession* session, bool inbound) - { - RouterID id{session->GetPubKey()}; - if (_peer_db) - { - // TODO: make sure this is a public router (on whitelist)? - _peer_db->modifyPeerStats(id, [&](PeerStats& stats) { stats.numConnectionSuccesses++; }); - } - notify_router_event(pubkey(), id, inbound); - return true; - } - bool Router::GetRandomConnectedRouter(RouterContact& result) const { @@ -1352,7 +1265,7 @@ namespace llarp } LogInfo("starting hidden service context..."); - if (!hiddenServiceContext().StartAll()) + if (!hidden_service_context().StartAll()) { LogError("Failed to start hidden service context"); return false; @@ -1375,7 +1288,7 @@ namespace llarp LogInfo("have ", _node_db->NumLoaded(), " routers"); _loop->call_every(ROUTER_TICK_INTERVAL, weak_from_this(), [this] { Tick(); }); - _route_poker->Start(this); + _route_poker->start(); is_running.store(true); _started_at = Now(); if (follow_whitelist) @@ -1514,7 +1427,7 @@ namespace llarp log::reset_level(log::Level::info); LogWarn("stopping router hard"); llarp::sys::service_manager->stopping(); - hiddenServiceContext().StopAll(); + hidden_service_context().StopAll(); _exit_context.Stop(); StopLinks(); Close(); @@ -1541,7 +1454,7 @@ namespace llarp log::info(logcat, "stopping"); llarp::sys::service_manager->stopping(); log::debug(logcat, "stopping hidden service context"); - hiddenServiceContext().StopAll(); + hidden_service_context().StopAll(); llarp::sys::service_manager->stopping(); log::debug(logcat, "stopping exit context"); _exit_context.Stop(); @@ -1628,7 +1541,7 @@ namespace llarp { if (IsServiceNode()) return false; - const auto ep = hiddenServiceContext().GetDefault(); + const auto& ep = hidden_service_context().GetDefault(); return ep and ep->HasExit(); } @@ -1690,7 +1603,7 @@ namespace llarp void Router::InitOutboundLinks() { - auto addrs = config->links.OutboundLinks; + auto addrs = config()->links.OutboundLinks; if (addrs.empty()) addrs.emplace_back(net().Wildcard()); @@ -1722,7 +1635,7 @@ namespace llarp } void - Router::handle_router_event(tooling::RouterEventPtr event) const + Router::handle_router_event(std::unique_ptr event) const { LogDebug(event->ToString()); } diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 42fc6a846e..d01adebe31 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -1,5 +1,9 @@ #pragma once +#include "rc_gossiper.hpp" +#include "rc_lookup_handler.hpp" +#include "route_poker.hpp" + #include #include #include @@ -10,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -18,10 +21,6 @@ #include #include #include -#include "outbound_message_handler.hpp" -#include "rc_gossiper.hpp" -#include "rc_lookup_handler.hpp" -#include "route_poker.hpp" #include #include #include @@ -46,7 +45,10 @@ #include -namespace libquic = oxen::quic; +/* + TONUKE: + - hidden_service_context +*/ namespace llarp { @@ -54,11 +56,11 @@ namespace llarp class RouteManager final /* : public Router */ { public: - std::shared_ptr + std::shared_ptr get_or_connect(); private: - std::shared_ptr ep; + std::shared_ptr ep; }; struct Router : std::enable_shared_from_this @@ -139,9 +141,6 @@ namespace llarp // should we be sending padded messages every interval? bool send_padding = false; - LinkMessageParser inbound_link_msg_parser; - routing::InboundMessageParser inbound_routing_msg_parser; - service::Context _hidden_service_context; consensus::reachability_testing router_testing; @@ -166,7 +165,7 @@ namespace llarp protected: void - handle_router_event(tooling::RouterEventPtr event) const; + handle_router_event(std::unique_ptr event) const; virtual bool disableGossipingRC_TestingOnly() @@ -175,6 +174,9 @@ namespace llarp }; public: + void + for_each_connection(std::function func); + std::shared_ptr config() const { @@ -364,36 +366,36 @@ namespace llarp Sign(Signature& sig, const llarp_buffer_t& buf) const; service::Context& - hiddenServiceContext() + hidden_service_context() { return _hidden_service_context; } const service::Context& - hiddenServiceContext() const + hidden_service_context() const { return _hidden_service_context; } - llarp_time_t _lastTick = 0s; + llarp_time_t _last_tick = 0s; - std::function _onDown; + std::function _router_close_cb; void - SetDownHook(std::function hook) + set_router_close_cb(std::function hook) { - _onDown = hook; + _router_close_cb = hook; } bool LooksAlive() const { const llarp_time_t now = Now(); - return now <= _lastTick || (now - _lastTick) <= llarp_time_t{30000}; + return now <= _last_tick || (now - _last_tick) <= llarp_time_t{30000}; } const std::shared_ptr& - routePoker() const + route_poker() const { return _route_poker; } @@ -410,8 +412,9 @@ namespace llarp void GossipRCIfNeeded(const RouterContact rc); + // TODO: this is not used anywhere? bool - HandleRecvLinkMessageBuffer(AbstractLinkSession* from, const llarp_buffer_t& msg); + recv_link_message_buffer(std::shared_ptr conn, bstring_view msg); void InitInboundLinks(); @@ -513,13 +516,6 @@ namespace llarp SendToOrQueue( const RouterID& remote, const AbstractLinkMessage& msg, SendStatusHandler handler); - void - ForEachPeer( - std::function visit, bool randomize = false) const; - - void - ForEachPeer(std::function visit); - bool IsBootstrapNode(RouterID) const; /// check if newRc matches oldRC and update local rc for this remote contact @@ -529,18 +525,6 @@ namespace llarp bool CheckRenegotiateValid(RouterContact newRc, RouterContact oldRC); - /// called by link when a remote session has no more sessions open - void - SessionClosed(RouterID remote); - - /// called by link when an unestablished connection times out - void - ConnectionTimedOut(AbstractLinkSession* session); - - /// called by link when session is fully established - bool - ConnectionEstablished(AbstractLinkSession* session, bool inbound); - /// call internal router ticker void Tick(); diff --git a/llarp/rpc/rpc_server.cpp b/llarp/rpc/rpc_server.cpp index ae7ac5f583..08c89fb484 100644 --- a/llarp/rpc/rpc_server.cpp +++ b/llarp/rpc/rpc_server.cpp @@ -84,7 +84,7 @@ namespace llarp::rpc return r.exitContext().GetExitEndpoint(name); } - return r.hiddenServiceContext().GetEndpointByName(name); + return r.hidden_service_context().GetEndpointByName(name); } template @@ -360,7 +360,7 @@ namespace llarp::rpc // steal replier from exit RPC endpoint exit_request.replier.emplace(mapexit.move()); - m_Router.hiddenServiceContext().GetDefault()->map_exit( + m_Router.hidden_service_context().GetDefault()->map_exit( mapexit.request.address, mapexit.request.token, mapexit.request.ip_range, @@ -375,13 +375,13 @@ namespace llarp::rpc void RPCServer::invoke(ListExits& listexits) { - if (not m_Router.hiddenServiceContext().hasEndpoints()) + if (not m_Router.hidden_service_context().hasEndpoints()) { SetJSONError("No mapped endpoints found", listexits.response); return; } - auto status = m_Router.hiddenServiceContext().GetDefault()->ExtractStatus()["exitMap"]; + auto status = m_Router.hidden_service_context().GetDefault()->ExtractStatus()["exitMap"]; SetJSONResponse((status.empty()) ? "No exits" : status, listexits.response); } @@ -413,7 +413,7 @@ namespace llarp::rpc { MapExit map_request; UnmapExit unmap_request; - auto endpoint = m_Router.hiddenServiceContext().GetDefault(); + auto endpoint = m_Router.hidden_service_context().GetDefault(); auto current_exits = endpoint->ExtractStatus()["exitMap"]; if (current_exits.empty()) diff --git a/llarp/service/context.hpp b/llarp/service/context.hpp index ce5ff8e8ae..f61a0fe90e 100644 --- a/llarp/service/context.hpp +++ b/llarp/service/context.hpp @@ -7,68 +7,70 @@ #include -namespace llarp +/* + TODO: + - if we are only using one local endpoint, does this need to change to account for that? +*/ + +namespace llarp::service { - namespace service + /// holds all the hidden service endpoints we own + /// this should be refactored (removed entirely...?) now that lokinet + /// only supports one endpoint per instance + struct Context { - /// holds all the hidden service endpoints we own - /// this should be refactored (removed entirely...?) now that lokinet - /// only supports one endpoint per instance - struct Context + explicit Context(Router* r); + ~Context(); + + void + Tick(llarp_time_t now); + + /// stop all held services + bool + StopAll(); + + util::StatusObject + ExtractStatus() const; + + bool + hasEndpoints(); + + /// function visitor returns false to prematurely break iteration + void + ForEachService(std::function visit) const; + + /// Pumps the hidden service endpoints, called during Router::PumpLL + void + Pump(); + + /// add endpoint via config + void + AddEndpoint(const Config& conf, bool autostart = false); + + /// inject endpoint instance + void + InjectEndpoint(std::string name, std::shared_ptr ep); + + /// stop and remove an endpoint by name + /// return false if we don't have the hidden service with that name + bool + RemoveEndpoint(const std::string& name); + + Endpoint_ptr + GetEndpointByName(const std::string& name) const; + + Endpoint_ptr + GetDefault() const { - explicit Context(Router* r); - ~Context(); - - void - Tick(llarp_time_t now); - - /// stop all held services - bool - StopAll(); - - util::StatusObject - ExtractStatus() const; - - bool - hasEndpoints(); - - /// function visitor returns false to prematurely break iteration - void - ForEachService(std::function visit) const; - - /// Pumps the hidden service endpoints, called during Router::PumpLL - void - Pump(); - - /// add endpoint via config - void - AddEndpoint(const Config& conf, bool autostart = false); - - /// inject endpoint instance - void - InjectEndpoint(std::string name, std::shared_ptr ep); - - /// stop and remove an endpoint by name - /// return false if we don't have the hidden service with that name - bool - RemoveEndpoint(const std::string& name); - - Endpoint_ptr - GetEndpointByName(const std::string& name) const; - - Endpoint_ptr - GetDefault() const - { - return GetEndpointByName("default"); - } - - bool - StartAll(); - - private: - Router* const m_Router; - std::unordered_map> m_Endpoints; - std::list> m_Stopped; - }; - } // namespace service -} // namespace llarp + return GetEndpointByName("default"); + } + + bool + StartAll(); + + private: + Router* const m_Router; + std::unordered_map> m_Endpoints; + std::list> m_Stopped; + }; +} // namespace llarp::service diff --git a/llarp/util/meta/memfn.hpp b/llarp/util/meta/memfn.hpp index 8d9366cf50..4ec196b8c2 100644 --- a/llarp/util/meta/memfn.hpp +++ b/llarp/util/meta/memfn.hpp @@ -5,71 +5,68 @@ #include #include -namespace llarp +namespace llarp::util { - namespace util + // Wraps a member function and instance into a callable object that invokes + // the method (non-const overload). + template < + typename Return, + typename Class, + typename Derived, + typename... Arg, + typename = std::enable_if_t::value>> + auto + memFn(Return (Class::*f)(Arg...), Derived* self) { - // Wraps a member function and instance into a callable object that invokes - // the method (non-const overload). - template < - typename Return, - typename Class, - typename Derived, - typename... Arg, - typename = std::enable_if_t::value>> - auto - memFn(Return (Class::*f)(Arg...), Derived* self) - { - return [f, self](Arg... args) -> Return { return (self->*f)(std::forward(args)...); }; - } + return [f, self](Arg... args) -> Return { return (self->*f)(std::forward(args)...); }; + } - // Wraps a member function and instance into a lambda that invokes the - // method (const overload). - template < - typename Return, - typename Class, - typename Derived, - typename... Arg, - typename = std::enable_if_t::value>> - auto - memFn(Return (Class::*f)(Arg...) const, const Derived* self) - { - return [f, self](Arg... args) -> Return { return (self->*f)(std::forward(args)...); }; - } + // Wraps a member function and instance into a lambda that invokes the + // method (const overload). + template < + typename Return, + typename Class, + typename Derived, + typename... Arg, + typename = std::enable_if_t::value>> + auto + memFn(Return (Class::*f)(Arg...) const, const Derived* self) + { + return [f, self](Arg... args) -> Return { return (self->*f)(std::forward(args)...); }; + } - // Wraps a member function and shared pointer to an instance into a lambda - // that invokes the method. - template < - typename Return, - typename Class, - typename Derived, - typename... Arg, - typename = std::enable_if_t::value>> - auto - memFn(Return (Class::*f)(Arg...), std::shared_ptr self) - { - return [f, self = std::move(self)](Arg... args) -> Return { - return (self.get()->*f)(std::forward(args)...); - }; - } + // Wraps a member function and shared pointer to an instance into a lambda + // that invokes the method. + template < + typename Return, + typename Class, + typename Derived, + typename... Arg, + typename = std::enable_if_t::value>> + auto + memFn(Return (Class::*f)(Arg...), std::shared_ptr self) + { + return [f, self = std::move(self)](Arg... args) -> Return { + return (self.get()->*f)(std::forward(args)...); + }; + } - // Wraps a member function and shared pointer to an instance into a lambda - // that invokes the method (const method overload). - template < - typename Return, - typename Class, - typename Derived, - typename... Arg, - typename = std::enable_if_t::value>> - auto - memFn(Return (Class::*f)(Arg...) const, std::shared_ptr self) - { - return [f, self = std::move(self)](Arg... args) -> Return { - return (self.get()->*f)(std::forward(args)...); - }; - } + // Wraps a member function and shared pointer to an instance into a lambda + // that invokes the method (const method overload). + template < + typename Return, + typename Class, + typename Derived, + typename... Arg, + typename = std::enable_if_t::value>> + auto + memFn(Return (Class::*f)(Arg...) const, std::shared_ptr self) + { + return [f, self = std::move(self)](Arg... args) -> Return { + return (self.get()->*f)(std::forward(args)...); + }; + } - } // namespace util -} // namespace llarp +} // namespace llarp::util #endif diff --git a/llarp/vpn/android.hpp b/llarp/vpn/android.hpp index 3cbe25e180..1ab0abfb2f 100644 --- a/llarp/vpn/android.hpp +++ b/llarp/vpn/android.hpp @@ -53,35 +53,35 @@ namespace llarp::vpn } }; - class AndroidRouteManager : public IRouteManager + class AndroidRouteManager : public AbstractRouteManager { - void AddRoute(net::ipaddr_t, net::ipaddr_t) override{}; + void add_route(oxen::quic::Address, oxen::quic::Address) override{}; - void DelRoute(net::ipaddr_t, net::ipaddr_t) override{}; + void delete_route(oxen::quic::Address, oxen::quic::Address) override{}; void - AddDefaultRouteViaInterface(NetworkInterface&) override{}; + add_default_route_via_interface(NetworkInterface&) override{}; void - DelDefaultRouteViaInterface(NetworkInterface&) override{}; + delete_default_route_via_interface(NetworkInterface&) override{}; void - AddRouteViaInterface(NetworkInterface&, IPRange) override{}; + add_route_via_interface(NetworkInterface&, IPRange) override{}; void - DelRouteViaInterface(NetworkInterface&, IPRange) override{}; + delete_route_via_interface(NetworkInterface&, IPRange) override{}; - std::vector - GetGatewaysNotOnInterface(NetworkInterface&) override + std::vector + get_non_interface_gateways(NetworkInterface&) override { - return std::vector{}; + return std::vector{}; }; }; class AndroidPlatform : public Platform { const int fd; - AndroidRouteManager _routeManager{}; + AndroidRouteManager _route_manager{}; public: AndroidPlatform(llarp::Context* ctx) : fd{ctx->androidFD} @@ -92,10 +92,10 @@ namespace llarp::vpn { return std::make_shared(std::move(info), fd); } - IRouteManager& + AbstractRouteManager& RouteManager() override { - return _routeManager; + return _route_manager; } }; diff --git a/llarp/vpn/linux.hpp b/llarp/vpn/linux.hpp index d39e11a7b5..6283f3be82 100644 --- a/llarp/vpn/linux.hpp +++ b/llarp/vpn/linux.hpp @@ -132,7 +132,7 @@ namespace llarp::vpn } }; - class LinuxRouteManager : public IRouteManager + class LinuxRouteManager : public AbstractRouteManager { const int fd; @@ -179,6 +179,15 @@ namespace llarp::vpn unsigned char bitlen; unsigned char data[sizeof(struct in6_addr)]; + _inet_addr(oxen::quic::Address& addr) + { + const auto& v4 = addr.is_ipv4(); + + family = (v4) ? AF_INET : AF_INET6; + bitlen = (v4) ? 32 : 128; + std::memcpy(data, addr.host().data(), (v4) ? 4 : 16); + } + _inet_addr(net::ipv4addr_t addr, size_t bits = 32) { family = AF_INET; @@ -195,7 +204,7 @@ namespace llarp::vpn }; void - Blackhole(int cmd, int flags, int af) + make_blackhole(int cmd, int flags, int af) { NLRequest nl_request{}; /* Initialize request structure */ @@ -221,7 +230,7 @@ namespace llarp::vpn } void - Route( + make_route( int cmd, int flags, const _inet_addr& dst, @@ -286,7 +295,7 @@ namespace llarp::vpn } void - DefaultRouteViaInterface(NetworkInterface& vpn, int cmd, int flags) + default_route_via_interface(NetworkInterface& vpn, int cmd, int flags) { const auto& info = vpn.Info(); @@ -298,8 +307,8 @@ namespace llarp::vpn const _inet_addr lower{ToNet(ipaddr_ipv4_bits(0, 0, 0, 0)), 1}; const _inet_addr upper{ToNet(ipaddr_ipv4_bits(128, 0, 0, 0)), 1}; - Route(cmd, flags, lower, gateway, GatewayMode::eLowerDefault, info.index); - Route(cmd, flags, upper, gateway, GatewayMode::eUpperDefault, info.index); + make_route(cmd, flags, lower, gateway, GatewayMode::eLowerDefault, info.index); + make_route(cmd, flags, upper, gateway, GatewayMode::eUpperDefault, info.index); if (const auto maybe6 = Net().GetInterfaceIPv6Address(info.ifname)) { @@ -307,13 +316,13 @@ namespace llarp::vpn for (const std::string str : {"::", "4000::", "8000::", "c000::"}) { const _inet_addr hole6{net::ipv6addr_t::from_string(str), 2}; - Route(cmd, flags, hole6, gateway6, GatewayMode::eUpperDefault, info.index); + make_route(cmd, flags, hole6, gateway6, GatewayMode::eUpperDefault, info.index); } } } void - RouteViaInterface(int cmd, int flags, NetworkInterface& vpn, IPRange range) + route_via_interface(int cmd, int flags, NetworkInterface& vpn, IPRange range) { const auto& info = vpn.Info(); if (range.IsV4()) @@ -328,7 +337,7 @@ namespace llarp::vpn ToNet(net::TruncateV6(range.addr)), bits::count_bits(net::TruncateV6(range.netmask_bits))}; - Route(cmd, flags, addr, gateway, GatewayMode::eUpperDefault, info.index); + make_route(cmd, flags, addr, gateway, GatewayMode::eUpperDefault, info.index); } else { @@ -337,17 +346,14 @@ namespace llarp::vpn throw std::runtime_error{"we dont have our own network interface?"}; const _inet_addr gateway{ToNet(*maybe), 128}; const _inet_addr addr{ToNet(range.addr), bits::count_bits(range.netmask_bits)}; - Route(cmd, flags, addr, gateway, GatewayMode::eUpperDefault, info.index); + make_route(cmd, flags, addr, gateway, GatewayMode::eUpperDefault, info.index); } } void - Route(int cmd, int flags, net::ipaddr_t ip, net::ipaddr_t gateway) + make_route(int cmd, int flags, oxen::quic::Address ip, oxen::quic::Address gateway) { - auto _ip = var::visit([](auto&& i) { return _inet_addr{i}; }, ip); - auto _gw = var::visit([](auto&& i) { return _inet_addr{i}; }, gateway); - - Route(cmd, flags, _ip, _gw, GatewayMode::eFirstHop, 0); + make_route(cmd, flags, _inet_addr{ip}, _inet_addr{gateway}, GatewayMode::eFirstHop, 0); } public: @@ -363,46 +369,47 @@ namespace llarp::vpn } void - AddRoute(net::ipaddr_t ip, net::ipaddr_t gateway) override + add_route(oxen::quic::Address ip, oxen::quic::Address gateway) override { - Route(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, ip, gateway); + make_route(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, ip, gateway); } void - DelRoute(net::ipaddr_t ip, net::ipaddr_t gateway) override + delete_route(oxen::quic::Address ip, oxen::quic::Address gateway) override { - Route(RTM_DELROUTE, 0, ip, gateway); + make_route(RTM_DELROUTE, 0, ip, gateway); } void - AddDefaultRouteViaInterface(NetworkInterface& vpn) override + add_default_route_via_interface(NetworkInterface& vpn) override { - DefaultRouteViaInterface(vpn, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL); + default_route_via_interface(vpn, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL); } void - DelDefaultRouteViaInterface(NetworkInterface& vpn) override + delete_default_route_via_interface(NetworkInterface& vpn) override { - DefaultRouteViaInterface(vpn, RTM_DELROUTE, 0); + default_route_via_interface(vpn, RTM_DELROUTE, 0); } void - AddRouteViaInterface(NetworkInterface& vpn, IPRange range) override + add_route_via_interface(NetworkInterface& vpn, IPRange range) override { - RouteViaInterface(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, vpn, range); + route_via_interface(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, vpn, range); } void - DelRouteViaInterface(NetworkInterface& vpn, IPRange range) override + delete_route_via_interface(NetworkInterface& vpn, IPRange range) override { - RouteViaInterface(RTM_DELROUTE, 0, vpn, range); + route_via_interface(RTM_DELROUTE, 0, vpn, range); } - std::vector - GetGatewaysNotOnInterface(NetworkInterface& vpn) override + std::vector + get_non_interface_gateways(NetworkInterface& vpn) override { const auto& ifname = vpn.Info().ifname; - std::vector gateways{}; + std::vector gateways{}; + std::ifstream inf{"/proc/net/route"}; for (std::string line; std::getline(inf, line);) { @@ -412,9 +419,10 @@ namespace llarp::vpn const auto& ip = parts[2]; if ((ip.size() == sizeof(uint32_t) * 2) and oxenc::is_hex(ip)) { - huint32_t x{}; - oxenc::from_hex(ip.begin(), ip.end(), reinterpret_cast(&x.h)); - gateways.emplace_back(net::ipv4addr_t::from_host(x.h)); + std::string buf; + oxenc::from_hex(ip.begin(), ip.end(), buf.data()); + oxen::quic::Address addr{buf, 0}; + gateways.push_back(std::move(addr)); } } } @@ -422,17 +430,17 @@ namespace llarp::vpn } void - AddBlackhole() override + add_blackhole() override { - Blackhole(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, AF_INET); - Blackhole(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, AF_INET6); + make_blackhole(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, AF_INET); + make_blackhole(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL, AF_INET6); } void - DelBlackhole() override + delete_blackhole() override { - Blackhole(RTM_DELROUTE, 0, AF_INET); - Blackhole(RTM_DELROUTE, 0, AF_INET6); + make_blackhole(RTM_DELROUTE, 0, AF_INET); + make_blackhole(RTM_DELROUTE, 0, AF_INET6); } }; @@ -447,7 +455,7 @@ namespace llarp::vpn return std::make_shared(std::move(info)); }; - IRouteManager& + AbstractRouteManager& RouteManager() override { return _routeManager; diff --git a/llarp/vpn/platform.cpp b/llarp/vpn/platform.cpp index 757894b612..28a93b96ae 100644 --- a/llarp/vpn/platform.cpp +++ b/llarp/vpn/platform.cpp @@ -17,7 +17,7 @@ namespace llarp::vpn { const llarp::net::Platform* - IRouteManager::Net_ptr() const + AbstractRouteManager::Net_ptr() const { return llarp::net::Platform::Default_ptr(); } diff --git a/llarp/vpn/platform.hpp b/llarp/vpn/platform.hpp index 0885518e49..f449b86db9 100644 --- a/llarp/vpn/platform.hpp +++ b/llarp/vpn/platform.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "i_packet_io.hpp" @@ -70,13 +71,13 @@ namespace llarp::vpn MaybeWakeUpperLayers() const {}; }; - class IRouteManager + class AbstractRouteManager { public: - IRouteManager() = default; - IRouteManager(const IRouteManager&) = delete; - IRouteManager(IRouteManager&&) = delete; - virtual ~IRouteManager() = default; + AbstractRouteManager() = default; + AbstractRouteManager(const AbstractRouteManager&) = delete; + AbstractRouteManager(AbstractRouteManager&&) = delete; + virtual ~AbstractRouteManager() = default; virtual const llarp::net::Platform* Net_ptr() const; @@ -88,31 +89,31 @@ namespace llarp::vpn } virtual void - AddRoute(net::ipaddr_t ip, net::ipaddr_t gateway) = 0; + add_route(oxen::quic::Address ip, oxen::quic::Address gateway) = 0; virtual void - DelRoute(net::ipaddr_t ip, net::ipaddr_t gateway) = 0; + delete_route(oxen::quic::Address ip, oxen::quic::Address gateway) = 0; virtual void - AddDefaultRouteViaInterface(NetworkInterface& vpn) = 0; + add_default_route_via_interface(NetworkInterface& vpn) = 0; virtual void - DelDefaultRouteViaInterface(NetworkInterface& vpn) = 0; + delete_default_route_via_interface(NetworkInterface& vpn) = 0; virtual void - AddRouteViaInterface(NetworkInterface& vpn, IPRange range) = 0; + add_route_via_interface(NetworkInterface& vpn, IPRange range) = 0; virtual void - DelRouteViaInterface(NetworkInterface& vpn, IPRange range) = 0; + delete_route_via_interface(NetworkInterface& vpn, IPRange range) = 0; - virtual std::vector - GetGatewaysNotOnInterface(NetworkInterface& vpn) = 0; + virtual std::vector + get_non_interface_gateways(NetworkInterface& vpn) = 0; virtual void - AddBlackhole(){}; + add_blackhole(){}; virtual void - DelBlackhole(){}; + delete_blackhole(){}; }; /// a vpn platform @@ -144,7 +145,7 @@ namespace llarp::vpn } /// get owned ip route manager for managing routing table - virtual IRouteManager& + virtual AbstractRouteManager& RouteManager() = 0; /// create a packet io that will read (and optionally write) packets on a network interface the diff --git a/llarp/vpn/win32.cpp b/llarp/vpn/win32.cpp index 2027076ba8..9002314902 100644 --- a/llarp/vpn/win32.cpp +++ b/llarp/vpn/win32.cpp @@ -16,24 +16,24 @@ namespace llarp::win32 } // namespace void - VPNPlatform::Route(std::string ip, std::string gw, std::string cmd) + VPNPlatform::make_route(std::string ip, std::string gw, std::string cmd) { llarp::win32::Exec( "route.exe", fmt::format("{} {} MASK 255.255.255.255 {} METRIC {}", cmd, ip, gw, m_Metric)); } void - VPNPlatform::DefaultRouteViaInterface(NetworkInterface& vpn, std::string cmd) + VPNPlatform::default_route_via_interface(NetworkInterface& vpn, std::string cmd) { // route hole for loopback bacause god is dead on windows llarp::win32::Exec("route.exe", fmt::format("{} 127.0.0.0 MASK 255.0.0.0 0.0.0.0", cmd)); // set up ipv4 routes - RouteViaInterface(vpn, "0.0.0.0", "128.0.0.0", cmd); - RouteViaInterface(vpn, "128.0.0.0", "128.0.0.0", cmd); + route_via_interface(vpn, "0.0.0.0", "128.0.0.0", cmd); + route_via_interface(vpn, "128.0.0.0", "128.0.0.0", cmd); } void - VPNPlatform::RouteViaInterface( + VPNPlatform::route_via_interface( NetworkInterface& vpn, std::string addr, std::string mask, std::string cmd) { const auto& info = vpn.Info(); @@ -46,68 +46,73 @@ namespace llarp::win32 } void - VPNPlatform::AddRoute(net::ipaddr_t ip, net::ipaddr_t gateway) + VPNPlatform::add_route(oxen::quic::Address ip, oxen::quic::Address gateway) { - Route(ip_to_string(ip), ip_to_string(gateway), "ADD"); + make_route(ip.to_string(), gateway.to_string(), "ADD"); } void - VPNPlatform::DelRoute(net::ipaddr_t ip, net::ipaddr_t gateway) + VPNPlatform::delete_route(oxen::quic::Address ip, oxen::quic::Address gateway) { - Route(ip_to_string(ip), ip_to_string(gateway), "DELETE"); + make_route(ip.to_string(), gateway.to_string(), "DELETE"); } void - VPNPlatform::AddRouteViaInterface(NetworkInterface& vpn, IPRange range) + VPNPlatform::add_route_via_interface(NetworkInterface& vpn, IPRange range) { - RouteViaInterface(vpn, range.BaseAddressString(), range.NetmaskString(), "ADD"); + route_via_interface(vpn, range.BaseAddressString(), range.NetmaskString(), "ADD"); } void - VPNPlatform::DelRouteViaInterface(NetworkInterface& vpn, IPRange range) + VPNPlatform::delete_route_via_interface(NetworkInterface& vpn, IPRange range) { - RouteViaInterface(vpn, range.BaseAddressString(), range.NetmaskString(), "DELETE"); + route_via_interface(vpn, range.BaseAddressString(), range.NetmaskString(), "DELETE"); } - std::vector - VPNPlatform::GetGatewaysNotOnInterface(NetworkInterface& vpn) + std::vector + VPNPlatform::get_non_interface_gateways(NetworkInterface& vpn) { - std::set gateways; + std::set gateways; const auto ifaddr = vpn.Info()[0]; for (const auto& iface : Net().AllNetworkInterfaces()) { if (not iface.gateway) continue; + + bool b = true; + for (const auto& range : iface.addrs) { if (not range.Contains(ifaddr)) - gateways.emplace(*iface.gateway); + b = false; } + if (b) + gateways.emplace(*iface.gateway); } return {gateways.begin(), gateways.end()}; } void - VPNPlatform::AddDefaultRouteViaInterface(NetworkInterface& vpn) + VPNPlatform::add_default_route_via_interface(NetworkInterface& vpn) { // kill ipv6 llarp::win32::Exec( "WindowsPowerShell\\v1.0\\powershell.exe", "-Command (Disable-NetAdapterBinding -Name \"* \" -ComponentID ms_tcpip6)"); - DefaultRouteViaInterface(vpn, "ADD"); + default_route_via_interface(vpn, "ADD"); } void - VPNPlatform::DelDefaultRouteViaInterface(NetworkInterface& vpn) + VPNPlatform::delete_default_route_via_interface(NetworkInterface& vpn) { // restore ipv6 llarp::win32::Exec( "WindowsPowerShell\\v1.0\\powershell.exe", "-Command (Enable-NetAdapterBinding -Name \"* \" -ComponentID ms_tcpip6)"); - DefaultRouteViaInterface(vpn, "DELETE"); + default_route_via_interface(vpn, "DELETE"); } std::shared_ptr diff --git a/llarp/vpn/win32.hpp b/llarp/vpn/win32.hpp index ac52489352..a14852e79b 100644 --- a/llarp/vpn/win32.hpp +++ b/llarp/vpn/win32.hpp @@ -1,18 +1,18 @@ #pragma once +#include +#include +#include #include #include #include -#include -#include -#include #include "platform.hpp" namespace llarp::win32 { using namespace llarp::vpn; - class VPNPlatform : public Platform, public IRouteManager + class VPNPlatform : public Platform, public AbstractRouteManager { llarp::Context* const _ctx; const int m_Metric{2}; @@ -20,17 +20,17 @@ namespace llarp::win32 const auto& Net() const { - return _ctx->router->Net(); + return _ctx->router->net(); } void - Route(std::string ip, std::string gw, std::string cmd); + make_route(std::string ip, std::string gw, std::string cmd); void - DefaultRouteViaInterface(NetworkInterface& vpn, std::string cmd); + default_route_via_interface(NetworkInterface& vpn, std::string cmd); void - RouteViaInterface(NetworkInterface& vpn, std::string addr, std::string mask, std::string cmd); + route_via_interface(NetworkInterface& vpn, std::string addr, std::string mask, std::string cmd); public: VPNPlatform(const VPNPlatform&) = delete; @@ -42,25 +42,25 @@ namespace llarp::win32 ~VPNPlatform() override = default; void - AddRoute(net::ipaddr_t ip, net::ipaddr_t gateway) override; + add_route(oxen::quic::Address ip, oxen::quic::Address gateway) override; void - DelRoute(net::ipaddr_t ip, net::ipaddr_t gateway) override; + delete_route(oxen::quic::Address ip, oxen::quic::Address gateway) override; void - AddRouteViaInterface(NetworkInterface& vpn, IPRange range) override; + add_route_via_interface(NetworkInterface& vpn, IPRange range) override; void - DelRouteViaInterface(NetworkInterface& vpn, IPRange range) override; + delete_route_via_interface(NetworkInterface& vpn, IPRange range) override; - std::vector - GetGatewaysNotOnInterface(NetworkInterface& vpn) override; + std::vector + get_non_interface_gateways(NetworkInterface& vpn) override; void - AddDefaultRouteViaInterface(NetworkInterface& vpn) override; + add_default_route_via_interface(NetworkInterface& vpn) override; void - DelDefaultRouteViaInterface(NetworkInterface& vpn) override; + delete_default_route_via_interface(NetworkInterface& vpn) override; std::shared_ptr ObtainInterface(InterfaceInfo info, Router* router) override; @@ -69,7 +69,7 @@ namespace llarp::win32 create_packet_io( unsigned int ifindex, const std::optional& dns_upstream_src) override; - IRouteManager& + AbstractRouteManager& RouteManager() override { return *this; From d0c383738481559ebe967a976257600b079e0dd7 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 21 Sep 2023 07:20:49 -0700 Subject: [PATCH 038/312] libquic bparser merged - bumped version to latest main branch commit - wired up callbacks to set RPC request stream on creation - methods for I/O of control and data messages through link_manager --- external/oxen-libquic | 2 +- llarp/link/connection.cpp | 2 +- llarp/link/connection.hpp | 11 +- llarp/link/link_manager.cpp | 177 +++++++++++++++++++++++++------- llarp/link/link_manager.hpp | 74 +++++++++---- llarp/messages/link_intro.cpp | 2 +- llarp/messages/relay.cpp | 4 +- llarp/messages/relay_commit.cpp | 13 ++- llarp/messages/relay_commit.hpp | 1 + llarp/messages/relay_status.cpp | 5 +- llarp/net/sock_addr.cpp | 1 - llarp/path/path_context.cpp | 22 ++-- llarp/path/path_context.hpp | 8 +- llarp/router/router.cpp | 21 +--- llarp/router/router.hpp | 10 +- 15 files changed, 239 insertions(+), 114 deletions(-) diff --git a/external/oxen-libquic b/external/oxen-libquic index 009d61e251..ba1958311a 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit 009d61e251cf4cfaa70f224b13c4bb7e905d734b +Subproject commit ba1958311a4ff672af6d7d947c46c13ac177a711 diff --git a/llarp/link/connection.cpp b/llarp/link/connection.cpp index 8fcb21cffa..2af983693f 100644 --- a/llarp/link/connection.cpp +++ b/llarp/link/connection.cpp @@ -4,7 +4,7 @@ namespace llarp::link { Connection::Connection( std::shared_ptr& c, - std::shared_ptr& s, + std::shared_ptr& s, RouterContact& rc) : conn{c}, control_stream{s}, remote_rc{std::move(rc)} {} diff --git a/llarp/link/connection.hpp b/llarp/link/connection.hpp index 9168036748..a314b01db6 100644 --- a/llarp/link/connection.hpp +++ b/llarp/link/connection.hpp @@ -3,14 +3,14 @@ #include #include -#include +#include namespace llarp::link { struct Connection { std::shared_ptr conn; - std::shared_ptr control_stream; + std::shared_ptr control_stream; RouterContact remote_rc; // one side of a connection will be responsible for some things, e.g. heartbeat @@ -19,7 +19,12 @@ namespace llarp::link Connection( std::shared_ptr& c, - std::shared_ptr& s, + std::shared_ptr& s, RouterContact& rc); }; } // namespace llarp::link + +/* + TODO: + - make control_stream a weak pointer? +*/ diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index ce2c8dfd7f..43c633923e 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -21,6 +21,15 @@ namespace llarp return nullptr; } + std::shared_ptr + Endpoint::get_conn(const RouterID& rid) const + { + if (auto itr = conns.find(rid); itr != conns.end()) + return itr->second; + + return nullptr; + } + bool Endpoint::have_conn(const RouterID& remote, bool client_only) const { @@ -118,35 +127,64 @@ namespace llarp return ep.for_each_connection(func); } - // TODO: pass connection open callback to endpoint constructor! + std::shared_ptr + LinkManager::startup_endpoint() + { + /** Parameters: + - local bind address + - conection open callback + - connection close callback + - stream constructor callback + - will return a BTRequestStream on the first call to get_new_stream + + */ + return quic->endpoint( + router.public_ip(), + [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); + }, + [this](oxen::quic::dgram_interface& di, bstring dgram) { recv_data_message(di, dgram); }, + [&](oxen::quic::Connection& c, + oxen::quic::Endpoint& e, + std::optional id) -> std::shared_ptr { + if (id && id == 0) + { + return std::make_shared( + c, e, [this](oxen::quic::message msg) { return recv_control_message(msg); }); + } + return std::make_shared(c, e); + }); + } + LinkManager::LinkManager(Router& r) : router{r} , quic{std::make_unique()} , tls_creds{oxen::quic::GNUTLSCreds::make_from_ed_keys( {reinterpret_cast(router.identity().data()), size_t{32}}, {reinterpret_cast(router.identity().toPublic().data()), size_t{32}})} - , ep{quic->endpoint( - router.public_ip(), - [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); - }), - *this} + , ep{startup_endpoint(), *this} {} - // TODO: replace with control/data message sending with libquic bool - LinkManager::send_to(const RouterID& remote, bstring data, uint16_t priority) + LinkManager::send_control_message( + const RouterID& remote, std::string endpoint, std::string body, bool is_request) { if (is_stopping) return false; - if (not have_connection_to(remote)) + if (auto conn = ep.get_conn(remote); conn) { - auto pending = PendingMessage(data, priority); + (is_request) ? conn->control_stream->request(endpoint, body) + : conn->control_stream->command(endpoint, body); + return true; + } + + router.loop()->call([&]() { + auto pending = PendingControlMessage(body, endpoint); auto [itr, b] = pending_conn_msg_queue.emplace(remote, MessageQueue()); - itr->second.push(std::move(pending)); + itr->second.push_back(std::move(pending)); rc_lookup->get_rc( remote, @@ -159,14 +197,41 @@ namespace llarp else log::warning(quic_cat, "Do something intelligent here for error handling"); }); + }); + + return false; + } - // TODO: some error callback to report message send failure - // or, should we connect and pass a send-msg callback as the connection successful cb? + bool + LinkManager::send_data_message(const RouterID& remote, std::string body) + { + if (is_stopping) return false; + + if (auto conn = ep.get_conn(remote); conn) + { + conn->conn->send_datagram(std::move(body)); + return true; } - // TODO: send the message - // TODO: if we keep bool return type, change this accordingly + router.loop()->call([&]() { + auto pending = PendingDataMessage(body); + + auto [itr, b] = pending_conn_msg_queue.emplace(remote, MessageQueue()); + itr->second.push_back(std::move(pending)); + + rc_lookup->get_rc( + remote, + [this]( + [[maybe_unused]] const RouterID& rid, + const RouterContact* const rc, + const RCRequestResult res) { + if (res == RCRequestResult::Success) + connect_to(*rc); + else + log::warning(quic_cat, "Do something intelligent here for error handling"); + }); + }); return false; } @@ -199,28 +264,18 @@ namespace llarp void LinkManager::connect_to(RouterContact rc) { - if (have_connection_to(rc.pubkey)) + if (auto conn = ep.get_conn(rc.pubkey); conn) { - // TODO: connection failed callback + // TODO: should implement some connection failed logic, but not the same logic that + // would be executed for another failure case return; } - // TODO: connection established/failed callbacks - oxen::quic::stream_data_callback stream_cb = - [this](oxen::quic::Stream& stream, bstring_view packet) { - recv_control_message(stream, packet); - }; - - // TODO: once "compatible link" cares about address, actually choose addr to connect to - // based on which one is compatible with the link we chose. For now, just use - // the first one. 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) - // TODO: does connect() inherit the endpoint's datagram data callback, and do we want it to if - // so? - if (auto rv = ep.establish_connection(remote_addr, rc, stream_cb, tls_creds); rv) + if (auto rv = ep.establish_connection(remote_addr, rc, tls_creds); rv) { log::info(quic_cat, "Connection to {} successfully established!", remote_addr); return; @@ -236,18 +291,29 @@ namespace llarp const auto& scid = conn_interface.scid(); const auto& rid = ep.connid_map[scid]; + // check to see if this connection was established while we were attempting to queue + // messages to the remote if (auto itr = pending_conn_msg_queue.find(rid); itr != pending_conn_msg_queue.end()) { auto& que = itr->second; while (not que.empty()) { - auto& m = que.top(); - - (m.is_control) ? ep.conns[rid]->control_stream->send(std::move(m.buf)) - : conn_interface.send_datagram(std::move(m.buf)); + auto& m = que.front(); + + if (m.is_control) + { + auto& msg = reinterpret_cast(m); + msg.is_request ? ep.conns[rid]->control_stream->request(msg.endpoint, msg.body) + : ep.conns[rid]->control_stream->command(msg.endpoint, msg.body); + } + else + { + auto& msg = reinterpret_cast(m); + conn_interface.send_datagram(std::move(msg.body)); + } - que.pop(); + que.pop_front(); } } }); @@ -410,9 +476,44 @@ namespace llarp } void - LinkManager::recv_control_message(oxen::quic::Stream&, bstring_view) + LinkManager::recv_control_message(oxen::quic::message msg) { - // TODO: this + // if the message is not expired, it will pass this conditional + if (msg) + { + std::string ep{msg.endpoint()}, body{msg.body()}; + bool is_request = (msg.type() == "Q"sv) ? true : false; + + if (auto itr = rpc_map.find(ep); itr != rpc_map.end()) + { + router.loop()->call([&]() { + // execute mapped callback + auto maybe_response = itr->second(body); + + if (is_request) + { + if (maybe_response) + { + // respond here + msg.respond(msg.rid(), *maybe_response); + } + + // TODO: revisit the logic of these conditionals after defining the callback functions + // to see if returning/taking optionals makes sense + } + }); + } + else + { + msg.respond(msg.rid(), "INVALID REQUEST", true); + return; + } + } + else + { + // RPC request was sent out but we received no response + log::info(link_cat, "RPC request (RID: {}) timed out", msg.rid()); + } } } // namespace llarp diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 063f9120a5..57c7f93fc0 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -8,7 +8,6 @@ #include #include -#include #include #include @@ -45,8 +44,11 @@ namespace llarp std::unordered_map> conns; std::unordered_map connid_map; + // TODO: see which of these is actually useful and delete the other std::shared_ptr get_conn(const RouterContact&) const; + std::shared_ptr + get_conn(const RouterID&) const; bool have_conn(const RouterID& remote, bool client_only) const; @@ -103,24 +105,62 @@ namespace llarp struct PendingMessage { - bstring buf; - uint16_t priority; + std::string body; + RouterID rid; bool is_control{false}; - PendingMessage(bstring b, uint16_t p, bool c = false) - : buf{std::move(b)}, priority{p}, is_control{c} + PendingMessage(std::string b, bool control = false) : body{std::move(b)}, is_control{control} + {} + }; + + struct PendingDataMessage : PendingMessage + { + PendingDataMessage(std::string b) : PendingMessage(b) + {} + }; + + struct PendingControlMessage : PendingMessage + { + std::string endpoint; + bool is_request{false}; // true if request, false if command + + PendingControlMessage(std::string b, std::string e, bool request = true) + : PendingMessage(b, true), endpoint{std::move(e)}, is_request{request} {} }; - using MessageQueue = util::ascending_priority_queue; + using MessageQueue = std::deque; struct Router; struct LinkManager { + public: + explicit LinkManager(Router& r); + + // set is_request to true for RPC requests, false for RPC commands + bool + send_control_message( + const RouterID& remote, std::string endpoint, std::string body, bool is_request = true); + + bool + send_data_message(const RouterID& remote, std::string data); + private: friend struct link::Endpoint; + const std::unordered_map< + std::string, + std::function(std::optional)>> + rpc_map{ + /** TODO: + key: RPC endpoint name + value: function that takes command body as parameter + + returns: commands will return std::nullopt while requests will return a response + */ + }; + std::atomic is_stopping; // DISCUSS: is this necessary? can we reduce the amount of locking and nuke this mutable util::Mutex m; // protects persisting_conns @@ -149,8 +189,9 @@ namespace llarp void recv_data_message(oxen::quic::dgram_interface& dgi, bstring dgram); + void - recv_control_message(oxen::quic::Stream& stream, bstring_view packet); + recv_control_message(oxen::quic::message msg); void on_conn_open(oxen::quic::connection_interface& ci); @@ -158,9 +199,10 @@ namespace llarp void on_conn_closed(oxen::quic::connection_interface& ci, uint64_t ec); - public: - explicit LinkManager(Router& r); + std::shared_ptr + startup_endpoint(); + public: const link::Endpoint& endpoint() { @@ -173,9 +215,6 @@ namespace llarp return addr; } - bool - send_to(const RouterID& remote, bstring data, uint16_t priority); - bool have_connection_to(const RouterID& remote, bool client_only = false) const; @@ -248,19 +287,15 @@ namespace llarp { try { - oxen::quic::dgram_data_callback dgram_cb = - [this](oxen::quic::dgram_interface& dgi, bstring dgram) { - link_manager.recv_data_message(dgi, dgram); - }; - auto conn_interface = - endpoint->connect(remote, link_manager.tls_creds, dgram_cb, std::forward(opts)...); + 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); - auto control_stream = conn_interface->get_new_stream(); + auto control_stream = + conn_interface->template get_new_stream(); itr->second = std::make_shared(conn_interface, rc, control_stream); return true; @@ -293,7 +328,6 @@ namespace llarp -> Yields mega-combo endpoint managing object? - Can avoid "kitchen sink" by greatly reducing complexity of implementation - llarp/router/outbound_message_handler.hpp - pendingsessionmessagequeue - establish queue of messages to be sent on a connection we are creating diff --git a/llarp/messages/link_intro.cpp b/llarp/messages/link_intro.cpp index 05377caa06..ef84653827 100644 --- a/llarp/messages/link_intro.cpp +++ b/llarp/messages/link_intro.cpp @@ -95,7 +95,7 @@ namespace llarp { if (!verify()) return false; - return session->GotLIM(this); + return conn->GotLIM(this); } void diff --git a/llarp/messages/relay.cpp b/llarp/messages/relay.cpp index 5eeaf8b6cb..cabc2aa9da 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(session->GetPubKey(), 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(session->GetPubKey(), 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/messages/relay_commit.cpp b/llarp/messages/relay_commit.cpp index c62cee90d0..c37f5bdbe5 100644 --- a/llarp/messages/relay_commit.cpp +++ b/llarp/messages/relay_commit.cpp @@ -201,11 +201,10 @@ namespace llarp , context(ctx) , hop(std::make_shared()) , fromAddr( - commit->session->GetRemoteRC().IsPublicRouter() - ? std::optional{} - : commit->session->GetRemoteEndpoint()) + commit->conn->remote_rc.IsPublicRouter() ? std::optional{} + : commit->conn->remote_rc.addr) { - hop->info.downstream = commit->session->GetPubKey(); + hop->info.downstream = commit->conn->remote_rc.pubkey; } ~LRCMFrameDecrypt() = default; @@ -434,8 +433,8 @@ namespace llarp // TODO: check if we really want to accept it self->hop->started = now; - self->context->router()->NotifyRouterEvent( - self->context->router()->pubkey(), self->hop); + // self->context->router()->NotifyRouterEvent( + // self->context->router()->pubkey(), self->hop); size_t sz = self->frames[0].size(); // shift @@ -487,7 +486,7 @@ namespace llarp // decrypt frames async frameDecrypt->decrypter->AsyncDecrypt( frameDecrypt->frames[0], frameDecrypt, [r = context->router()](auto func) { - r->QueueWork(std::move(func)); + r->loop()->call([&]() { func(); }); }); return true; } diff --git a/llarp/messages/relay_commit.hpp b/llarp/messages/relay_commit.hpp index b7c27c5e6b..388ea5e3d2 100644 --- a/llarp/messages/relay_commit.hpp +++ b/llarp/messages/relay_commit.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include diff --git a/llarp/messages/relay_status.cpp b/llarp/messages/relay_status.cpp index 6d881d6aed..6fce7f32e7 100644 --- a/llarp/messages/relay_status.cpp +++ b/llarp/messages/relay_status.cpp @@ -2,7 +2,6 @@ #include #include -#include #include #include #include @@ -129,14 +128,14 @@ namespace llarp bool LR_StatusMessage::handle_message(Router* router) const { - llarp::LogDebug("Received LR_Status message from (", session->GetPubKey(), ")"); + llarp::LogDebug("Received LR_Status message from (", conn->remote_rc.pubkey, ")"); if (frames.size() != path::max_len) { llarp::LogError("LRSM invalid number of records, ", frames.size(), "!=", path::max_len); return false; } - auto path = router->path_context().GetByUpstream(session->GetPubKey(), pathid); + auto path = router->path_context().GetByUpstream(conn->remote_rc.pubkey, pathid); if (not path) { llarp::LogWarn("unhandled LR_Status message: no associated path found pathid=", pathid); diff --git a/llarp/net/sock_addr.cpp b/llarp/net/sock_addr.cpp index 2832bc9eec..df4384e9ae 100644 --- a/llarp/net/sock_addr.cpp +++ b/llarp/net/sock_addr.cpp @@ -1,6 +1,5 @@ #include "sock_addr.hpp" #include "ip_range.hpp" -#include "address_info.hpp" #include "ip.hpp" #include "net_bits.hpp" #include "net.hpp" diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index 92ccace926..5dd1df7f85 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -10,7 +10,7 @@ namespace llarp::path static constexpr auto DefaultPathBuildLimit = 500ms; PathContext::PathContext(Router* router) - : router(router), m_AllowTransit(false), m_PathLimits(DefaultPathBuildLimit) + : _router(router), m_AllowTransit(false), m_PathLimits(DefaultPathBuildLimit) {} void @@ -43,19 +43,19 @@ namespace llarp::path const EventLoop_ptr& PathContext::loop() { - return router->loop(); + return _router->loop(); } const SecretKey& PathContext::EncryptionSecretKey() { - return router->encryption(); + return _router->encryption(); } bool PathContext::HopIsUs(const RouterID& k) const { - return std::equal(router->pubkey(), router->pubkey() + PUBKEYSIZE, k.begin()); + return std::equal(_router->pubkey(), _router->pubkey() + PUBKEYSIZE, k.begin()); } PathContext::EndpointPathPtrSet @@ -85,7 +85,7 @@ namespace llarp::path LogDebug("forwarding LRCM to ", nextHop); - return router->SendToOrQueue(nextHop, msg, handler); + return _router->SendToOrQueue(nextHop, msg, handler); } template < @@ -273,7 +273,7 @@ namespace llarp::path const byte_t* PathContext::OurRouterID() const { - return router->pubkey(); + return _router->pubkey(); } TransitHop_ptr @@ -296,15 +296,15 @@ namespace llarp::path void PathContext::PumpUpstream() { - m_TransitPaths.ForEach([&](auto& ptr) { ptr->FlushUpstream(router); }); - m_OurPaths.ForEach([&](auto& ptr) { ptr->FlushUpstream(router); }); + m_TransitPaths.ForEach([&](auto& ptr) { ptr->FlushUpstream(_router); }); + m_OurPaths.ForEach([&](auto& ptr) { ptr->FlushUpstream(_router); }); } void PathContext::PumpDownstream() { - m_TransitPaths.ForEach([&](auto& ptr) { ptr->FlushDownstream(router); }); - m_OurPaths.ForEach([&](auto& ptr) { ptr->FlushDownstream(router); }); + m_TransitPaths.ForEach([&](auto& ptr) { ptr->FlushDownstream(_router); }); + m_OurPaths.ForEach([&](auto& ptr) { ptr->FlushDownstream(_router); }); } uint64_t @@ -350,7 +350,7 @@ namespace llarp::path { if (itr->second->Expired(now)) { - router->outboundMessageHandler().RemovePath(itr->first); + _router->outboundMessageHandler().RemovePath(itr->first); itr = map.erase(itr); } else diff --git a/llarp/path/path_context.hpp b/llarp/path/path_context.hpp index b46ee56ee9..7f1bb7e7ba 100644 --- a/llarp/path/path_context.hpp +++ b/llarp/path/path_context.hpp @@ -174,8 +174,14 @@ namespace llarp uint64_t CurrentOwnedPaths(path::PathStatus status = path::PathStatus::ePathEstablished); + Router* + router() const + { + return _router; + } + private: - Router* router; + Router* _router; SyncTransitMap_t m_TransitPaths; SyncOwnedPathsMap_t m_OurPaths; bool m_AllowTransit; diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 04560fc6a1..feb869f986 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -84,7 +84,6 @@ namespace llarp paths.PumpDownstream(); paths.PumpUpstream(); _hidden_service_context.Pump(); - // _outboundMessageHandler.Pump(); llarp::LogTrace("Router::PumpLL() end"); } @@ -203,22 +202,6 @@ namespace llarp return stats; } - // TODO: libquic change - bool - Router::recv_link_message_buffer(std::shared_ptr conn, bstring_view buf) - { - if (is_stopping) - return true; - - if (!conn) - { - log::warning(quic_cat, "No connection to pass link message buffer to!"); - return false; - } - - return inbound_link_msg_parser.ProcessFrom(session, buf); - } - void Router::Freeze() { @@ -509,9 +492,7 @@ namespace llarp bool Router::ParseRoutingMessageBuffer( const llarp_buffer_t& buf, routing::AbstractRoutingMessageHandler* h, const PathID_t& rxid) - { - return inbound_routing_msg_parser.ParseMessageBuffer(buf, h, rxid, this); - } + {} bool Router::appears_decommed() const diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index d01adebe31..a54dae076f 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -210,7 +210,11 @@ namespace llarp return _dht; } - // TOFIX: THIS + /** TOFIX: this + - refactor path types (path_context, pathset) to use unified ID type, not PathID_t + - refactor all callers to use new implementation of remove_path + + */ OutboundMessageHandler& outboundMessageHandler() { @@ -412,10 +416,6 @@ namespace llarp void GossipRCIfNeeded(const RouterContact rc); - // TODO: this is not used anywhere? - bool - recv_link_message_buffer(std::shared_ptr conn, bstring_view msg); - void InitInboundLinks(); From ae319091d6f63c967ae244b86191bfd58d489aca Mon Sep 17 00:00:00 2001 From: dr7ana Date: Tue, 26 Sep 2023 10:54:50 -0700 Subject: [PATCH 039/312] libquic bump --- external/oxen-libquic | 2 +- llarp/messages/dht_immediate.cpp | 8 ++++---- llarp/messages/link_message.hpp | 5 +++++ llarp/messages/relay.hpp | 8 ++++++-- llarp/path/path.cpp | 2 +- llarp/path/transit_hop.cpp | 7 +++---- llarp/router/router.cpp | 12 ++++++++++++ llarp/router/router.hpp | 7 ++++++- llarp/service/protocol.hpp | 2 +- 9 files changed, 39 insertions(+), 14 deletions(-) diff --git a/external/oxen-libquic b/external/oxen-libquic index ba1958311a..26a269e6ba 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit ba1958311a4ff672af6d7d947c46c13ac177a711 +Subproject commit 26a269e6bab6f7a03503b8aae72d6a153f9ac345 diff --git a/llarp/messages/dht_immediate.cpp b/llarp/messages/dht_immediate.cpp index 2b1585084b..88c7bd104f 100644 --- a/llarp/messages/dht_immediate.cpp +++ b/llarp/messages/dht_immediate.cpp @@ -29,7 +29,7 @@ namespace llarp try { - btdp.append("a", ""); + btdp.append("a", "m"); { auto subdict = btdp.append_dict("m"); for (auto& m : msgs) @@ -50,7 +50,7 @@ namespace llarp DHTImmediateMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) { if (key.startswith("m")) - return llarp::dht::DecodeMessageList(dht::Key_t(session->GetPubKey()), buf, msgs); + return llarp::dht::DecodeMessageList(dht::Key_t(conn->remote_rc.pubkey), buf, msgs); if (key.startswith("v")) { if (!bencode_read_integer(buf, &version)) @@ -65,7 +65,7 @@ namespace llarp DHTImmediateMessage::handle_message(Router* router) const { DHTImmediateMessage reply; - reply.session = session; + reply.conn = conn; bool result = true; auto dht = router->dht(); for (const auto& msg : msgs) @@ -76,7 +76,7 @@ namespace llarp { if (result) { - result = router->SendToOrQueue(session->GetPubKey(), reply); + result = router->SendToOrQueue(conn->remote_rc.pubkey, reply); } } return true; diff --git a/llarp/messages/link_message.hpp b/llarp/messages/link_message.hpp index 6793886fa7..e9e77e08ce 100644 --- a/llarp/messages/link_message.hpp +++ b/llarp/messages/link_message.hpp @@ -72,4 +72,9 @@ namespace llarp } }; + struct AbstractDataMessage : public AbstractLinkMessage + { + using AbstractLinkMessage::AbstractLinkMessage; + }; + } // namespace llarp diff --git a/llarp/messages/relay.hpp b/llarp/messages/relay.hpp index 266a01aef3..f2202bd1a6 100644 --- a/llarp/messages/relay.hpp +++ b/llarp/messages/relay.hpp @@ -9,7 +9,11 @@ namespace llarp { - struct RelayUpstreamMessage final : public AbstractLinkMessage + /* + Data messages to be sent via quic datagrams + */ + + struct RelayUpstreamMessage final : public AbstractDataMessage { Encrypted enc; TunnelNonce nonce; @@ -38,7 +42,7 @@ namespace llarp } }; - struct RelayDownstreamMessage final : public AbstractLinkMessage + struct RelayDownstreamMessage final : public AbstractDataMessage { Encrypted enc; TunnelNonce nonce; diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index d0561c42c2..9fb03de468 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -488,7 +488,7 @@ namespace llarp::path { for (const auto& msg : msgs) { - if (r->SendToOrQueue(Upstream(), msg)) + if (r->send_data_message(Upstream(), msg)) { m_TXRate += msg.enc.size(); } diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index a134a8567b..1d8da5ef3e 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -206,7 +206,7 @@ namespace llarp::path info.downstream, " to ", info.upstream); - r->SendToOrQueue(info.upstream, msg); + r->send_data_message(info.upstream, msg); } } r->TriggerPump(); @@ -224,7 +224,7 @@ namespace llarp::path info.upstream, " to ", info.downstream); - r->SendToOrQueue(info.downstream, msg); + r->send_data_message(info.downstream, msg); } r->TriggerPump(); } @@ -299,8 +299,7 @@ namespace llarp::path } return SendRoutingMessage(grant, r); } - // TODO: exponential backoff - // TODO: rejected policies + // TODO: exponential backoff, rejected policies ? llarp::routing::RejectExitMessage reject; reject.sequence_number = NextSeqNo(); reject.tx_id = msg.tx_id; diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index feb869f986..8057caa3a7 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -279,6 +279,18 @@ namespace llarp return _outboundMessageHandler.QueueMessage(remote, msg, handler); } + bool + Router::send_data_message(const RouterID &remote, const AbstractDataMessage &msg) + { + return _link_manager.send_data_message(remote, msg.bt_encode()); + } + + bool + Router::send_control_message(const RouterID &remote, const AbstractLinkMessage &msg) + { + + } + void Router::try_connect(fs::path rcfile) { diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index a54dae076f..121702a671 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -213,7 +213,6 @@ namespace llarp /** TOFIX: this - refactor path types (path_context, pathset) to use unified ID type, not PathID_t - refactor all callers to use new implementation of remove_path - */ OutboundMessageHandler& outboundMessageHandler() @@ -516,6 +515,12 @@ namespace llarp SendToOrQueue( const RouterID& remote, const AbstractLinkMessage& msg, SendStatusHandler handler); + bool + send_data_message(const RouterID& remote, const AbstractDataMessage& msg); + + bool + send_control_message(const RouterID& remote, const AbstractLinkMessage& msg); + bool IsBootstrapNode(RouterID) const; /// check if newRc matches oldRC and update local rc for this remote contact diff --git a/llarp/service/protocol.hpp b/llarp/service/protocol.hpp index ef9757a99c..00eeea0e87 100644 --- a/llarp/service/protocol.hpp +++ b/llarp/service/protocol.hpp @@ -44,7 +44,7 @@ namespace llarp ~ProtocolMessage(); ProtocolType proto = ProtocolType::TrafficV4; llarp_time_t queued = 0s; - std::vector payload; + std::vector payload; // encrypted AbstractLinkMessage Introduction introReply; ServiceInfo sender; Endpoint* handler = nullptr; From d9ead7d0f6982b221160cb49b485dee9c71693b4 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Wed, 27 Sep 2023 07:09:48 -0700 Subject: [PATCH 040/312] crypto and message encoding - libsodium calls streamlined and moved away from stupid typedefs - buffer handling taken away from buffer_t and towards ustrings and strings - lots of stuff deleted - team is working well - re-implementing message handling in proper link_manager methods --- llarp/CMakeLists.txt | 3 - llarp/config/config.cpp | 9 +- llarp/constants/path.hpp | 64 ++-- llarp/crypto/crypto.cpp | 502 +++++++++++++++++++++++++++- llarp/crypto/crypto.hpp | 135 ++++---- llarp/crypto/crypto_libsodium.cpp | 518 ----------------------------- llarp/crypto/crypto_libsodium.hpp | 113 ------- llarp/crypto/encrypted_frame.cpp | 57 +--- llarp/crypto/types.hpp | 2 +- llarp/dht/bucket.hpp | 333 +++++++++---------- llarp/dht/context.cpp | 6 +- llarp/dht/context.hpp | 211 ------------ llarp/dht/explorenetworkjob.cpp | 2 +- llarp/dht/key.hpp | 2 +- llarp/dht/messages/consensus.hpp | 24 -- llarp/dht/messages/findintro.cpp | 2 +- llarp/dht/messages/findname.cpp | 7 +- llarp/dht/messages/gotintro.cpp | 2 +- llarp/dht/messages/pubintro.cpp | 15 +- llarp/dht/publishservicejob.cpp | 2 +- llarp/dht/serviceaddresslookup.cpp | 2 +- llarp/dht/taglookup.cpp | 2 +- llarp/exit/exit_messages.cpp | 82 ++--- llarp/exit/session.cpp | 10 +- llarp/exit/session.hpp | 2 +- llarp/handlers/exit.cpp | 4 +- llarp/handlers/tun.cpp | 28 +- llarp/link/link_endpoints.cpp | 4 + llarp/link/link_endpoints.hpp | 4 + llarp/link/link_manager.cpp | 244 ++++++++++++-- llarp/link/link_manager.hpp | 83 ++++- llarp/messages/dht_immediate.cpp | 84 ----- llarp/messages/dht_immediate.hpp | 35 -- llarp/messages/link_intro.cpp | 3 +- llarp/messages/relay_commit.cpp | 10 +- llarp/messages/relay_status.cpp | 4 +- llarp/path/path.cpp | 53 +-- llarp/path/path.hpp | 2 +- llarp/path/pathbuilder.cpp | 37 +-- llarp/path/pathset.hpp | 2 +- llarp/path/transit_hop.cpp | 33 +- llarp/path/transit_hop.hpp | 2 +- llarp/peerstats/peer_db.cpp | 13 + llarp/router/router.cpp | 36 +- llarp/router/router.hpp | 21 +- llarp/router_contact.cpp | 33 +- llarp/rpc/lokid_rpc_client.cpp | 5 +- llarp/rpc/lokid_rpc_client.hpp | 2 +- llarp/rpc/rpc_server.cpp | 4 +- llarp/service/address.hpp | 2 +- llarp/service/endpoint.cpp | 501 ++++++++++++++-------------- llarp/service/endpoint.hpp | 52 ++- llarp/service/identity.cpp | 25 +- llarp/service/identity.hpp | 4 +- llarp/service/info.cpp | 4 +- llarp/service/info.hpp | 2 +- llarp/service/intro_set.cpp | 94 +++--- llarp/service/intro_set.hpp | 23 +- llarp/service/lookup.cpp | 32 -- llarp/service/lookup.hpp | 113 ------- llarp/service/outbound_context.cpp | 22 +- llarp/service/protocol.cpp | 71 ++-- llarp/service/protocol.hpp | 5 +- llarp/service/sendcontext.cpp | 2 +- llarp/service/sendcontext.hpp | 6 +- llarp/service/session.hpp | 2 +- llarp/util/aligned.hpp | 18 +- llarp/util/buffer.hpp | 2 + 68 files changed, 1688 insertions(+), 2145 deletions(-) delete mode 100644 llarp/crypto/crypto_libsodium.cpp delete mode 100644 llarp/crypto/crypto_libsodium.hpp delete mode 100644 llarp/dht/context.hpp delete mode 100644 llarp/dht/messages/consensus.hpp create mode 100644 llarp/link/link_endpoints.cpp create mode 100644 llarp/link/link_endpoints.hpp delete mode 100644 llarp/messages/dht_immediate.cpp delete mode 100644 llarp/messages/dht_immediate.hpp delete mode 100644 llarp/service/lookup.cpp delete mode 100644 llarp/service/lookup.hpp diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index 494f7417a5..a8ded040a4 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -1,7 +1,6 @@ include(Version) target_sources(lokinet-cryptography PRIVATE - crypto/crypto_libsodium.cpp crypto/crypto.cpp crypto/encrypted_frame.cpp crypto/types.cpp @@ -150,7 +149,6 @@ add_library(lokinet-consensus # lokinet-dht holds all logic related to interacting with and participating in the DHT hashring add_library(lokinet-dht STATIC - dht/context.cpp dht/dht.cpp dht/explorenetworkjob.cpp dht/localtaglookup.cpp @@ -200,7 +198,6 @@ add_library(lokinet-layer-link STATIC link/connection.cpp link/link_manager.cpp - messages/dht_immediate.cpp messages/link_intro.cpp ) diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index b00e38e58e..208e3e1b5e 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -1343,13 +1343,10 @@ namespace llarp std::set seenRanges; for (const auto& hop : rcs) { - for (const auto& addr : hop.addrs) + const auto network_addr = net::In6ToHUInt(hop.addr.in6().sin6_addr) & netmask; + if (auto [it, inserted] = seenRanges.emplace(network_addr, netmask); not inserted) { - const auto network_addr = net::In6ToHUInt(addr.ip) & netmask; - if (auto [it, inserted] = seenRanges.emplace(network_addr, netmask); not inserted) - { - return false; - } + return false; } } return true; diff --git a/llarp/constants/path.hpp b/llarp/constants/path.hpp index 849fabf59c..1cb8410110 100644 --- a/llarp/constants/path.hpp +++ b/llarp/constants/path.hpp @@ -6,41 +6,37 @@ #include #include -namespace llarp +namespace llarp::path { - namespace path - { - /// maximum path length - constexpr std::size_t max_len = 8; - /// default path length - constexpr std::size_t default_len = 4; - /// pad messages to the nearest this many bytes - constexpr std::size_t pad_size = 128; - /// default path lifetime in ms - constexpr std::chrono::milliseconds default_lifetime = 20min; - /// minimum into lifetime we will advertise - constexpr std::chrono::milliseconds min_intro_lifetime = default_lifetime / 2; - /// number of slices of path lifetime to spread intros out via - constexpr auto intro_spread_slices = 4; - /// spacing frequency at which we try to build paths for introductions - constexpr std::chrono::milliseconds intro_path_spread = default_lifetime / intro_spread_slices; - /// how long away from expiration in millseconds do we consider an intro to become stale - constexpr std::chrono::milliseconds intro_stale_threshold = - default_lifetime - intro_path_spread; - /// Minimum paths to keep around for intros; mainly used at startup (the - /// spread, above, should be able to maintain more than this number of paths - /// normally once things are going). - constexpr std::size_t min_intro_paths = 4; - /// after this many ms a path build times out - constexpr auto build_timeout = 10s; + /// maximum path length + constexpr std::size_t MAX_LEN = 8; + /// default path length + constexpr std::size_t DEFAULT_LEN = 4; + /// pad messages to the nearest this many bytes + constexpr std::size_t PAD_SIZE = 128; + /// default path lifetime in ms + constexpr std::chrono::milliseconds DEFAULT_LIFETIME = 20min; + /// minimum into lifetime we will advertise + constexpr std::chrono::milliseconds MIN_INTRO_LIFETIME = DEFAULT_LIFETIME / 2; + /// number of slices of path lifetime to spread intros out via + constexpr auto INTRO_SPREAD_SLICES = 4; + /// spacing frequency at which we try to build paths for introductions + constexpr std::chrono::milliseconds INTRO_PATH_SPREAD = DEFAULT_LIFETIME / INTRO_SPREAD_SLICES; + /// how long away from expiration in millseconds do we consider an intro to become stale + constexpr std::chrono::milliseconds INTRO_STALE_THRESHOLD = DEFAULT_LIFETIME - INTRO_PATH_SPREAD; + /// Minimum paths to keep around for intros; mainly used at startup (the + /// spread, above, should be able to maintain more than this number of paths + /// normally once things are going). + constexpr std::size_t MIN_INTRO_PATHS = 4; + /// after this many ms a path build times out + constexpr auto BUILD_TIMEOUT = 10s; - /// measure latency every this interval ms - constexpr auto latency_interval = 20s; - /// if a path is inactive for this amount of time it's dead - constexpr auto alive_timeout = latency_interval * 1.5; + /// measure latency every this interval ms + constexpr auto LATENCY_INTERVAL = 20s; + /// if a path is inactive for this amount of time it's dead + constexpr auto ALIVE_TIMEOUT = LATENCY_INTERVAL * 1.5; - /// how big transit hop traffic queues are - constexpr std::size_t transit_hop_queue_size = 256; + /// how big transit hop traffic queues are + constexpr std::size_t TRANSIT_HOP_QUEUE_SIZE = 256; - } // namespace path -} // namespace llarp +} // namespace llarp::path diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index 011aedc886..7e0409e0a6 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -1,6 +1,504 @@ #include "crypto.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_CRYPT +#include +#endif + +#include + namespace llarp { - Crypto* CryptoManager::m_crypto = nullptr; -} + static bool + dh(llarp::SharedSecret& out, + const PubKey& client_pk, + const PubKey& server_pk, + const uint8_t* themPub, + const SecretKey& usSec) + { + llarp::SharedSecret shared; + crypto_generichash_state h; + + if (crypto_scalarmult_curve25519(shared.data(), usSec.data(), themPub)) + { + return false; + } + crypto_generichash_blake2b_init(&h, nullptr, 0U, shared.size()); + crypto_generichash_blake2b_update(&h, client_pk.data(), 32); + crypto_generichash_blake2b_update(&h, server_pk.data(), 32); + crypto_generichash_blake2b_update(&h, shared.data(), 32); + crypto_generichash_blake2b_final(&h, out.data(), shared.size()); + return true; + } + + static bool + dh_client_priv( + llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n) + { + llarp::SharedSecret dh_result; + + if (dh(dh_result, sk.toPublic(), pk, pk.data(), sk)) + { + return crypto_generichash_blake2b(shared.data(), 32, n.data(), 32, dh_result.data(), 32) + != -1; + } + llarp::LogWarn("crypto::dh_client - dh failed"); + return false; + } + + static bool + dh_server_priv( + llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n) + { + llarp::SharedSecret dh_result; + if (dh(dh_result, pk, sk.toPublic(), pk.data(), sk)) + { + return crypto_generichash_blake2b(shared.data(), 32, n.data(), 32, dh_result.data(), 32) + != -1; + } + llarp::LogWarn("crypto::dh_server - dh failed"); + return false; + } + + Crypto::Crypto() + { + if (sodium_init() == -1) + { + throw std::runtime_error("sodium_init() returned -1"); + } + char* avx2 = std::getenv("AVX2_FORCE_DISABLE"); + if (avx2 && std::string(avx2) == "1") + { + ntru_init(1); + } + else + { + ntru_init(0); + } + int seed = 0; + randombytes(reinterpret_cast(&seed), sizeof(seed)); + srand(seed); + } + + std::optional> + Crypto::maybe_decrypt_name(std::string_view ciphertext, SymmNonce nounce, std::string_view name) + { + const auto payloadsize = ciphertext.size() - crypto_aead_xchacha20poly1305_ietf_ABYTES; + if (payloadsize != 32) + return {}; + + SharedSecret derivedKey{}; + ShortHash namehash{}; + ustring name_buf{reinterpret_cast(name.data()), name.size()}; + + if (not shorthash(namehash, name_buf.data(), name_buf.size())) + return {}; + if (not hmac(derivedKey.data(), name_buf.data(), derivedKey.size(), namehash)) + return {}; + AlignedBuffer<32> result{}; + if (crypto_aead_xchacha20poly1305_ietf_decrypt( + result.data(), + nullptr, + nullptr, + reinterpret_cast(ciphertext.data()), + ciphertext.size(), + nullptr, + 0, + nounce.data(), + derivedKey.data()) + == -1) + { + return {}; + } + return result; + } + + bool + Crypto::xchacha20(uint8_t* buf, size_t size, const SharedSecret& k, const TunnelNonce& n) + { + return crypto_stream_xchacha20_xor(buf, buf, size, n.data(), k.data()) == 0; + } + + bool + Crypto::xchacha20_alt( + const llarp_buffer_t& out, const llarp_buffer_t& in, const SharedSecret& k, const byte_t* n) + { + if (in.sz > out.sz) + return false; + return crypto_stream_xchacha20_xor(out.base, in.base, in.sz, n, k.data()) == 0; + } + + bool + Crypto::dh_client( + llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n) + { + return dh_client_priv(shared, pk, sk, n); + } + /// path dh relay side + bool + Crypto::dh_server( + llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n) + { + return dh_server_priv(shared, pk, sk, n); + } + /// transport dh client side + bool + Crypto::transport_dh_client( + llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n) + { + return dh_client_priv(shared, pk, sk, n); + } + /// transport dh server side + bool + Crypto::transport_dh_server( + llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n) + { + return dh_server_priv(shared, pk, sk, n); + } + + bool + Crypto::shorthash(ShortHash& result, uint8_t* buf, size_t size) + { + return crypto_generichash_blake2b(result.data(), ShortHash::SIZE, buf, size, nullptr, 0) != -1; + } + + bool + Crypto::hmac(uint8_t* result, uint8_t* buf, size_t size, const SharedSecret& secret) + { + return crypto_generichash_blake2b(result, HMACSIZE, buf, size, secret.data(), HMACSECSIZE) + != -1; + } + + static bool + hash(uint8_t* result, const llarp_buffer_t& buff) + { + return crypto_generichash_blake2b(result, HASHSIZE, buff.base, buff.sz, nullptr, 0) != -1; + } + + bool + Crypto::sign(Signature& sig, const SecretKey& secret, uint8_t* buf, size_t size) + { + return crypto_sign_detached(sig.data(), nullptr, buf, size, secret.data()) != -1; + } + + bool + Crypto::sign(Signature& sig, const PrivateKey& privkey, uint8_t* buf, size_t size) + { + PubKey pubkey; + + privkey.toPublic(pubkey); + + crypto_hash_sha512_state hs; + unsigned char nonce[64]; + unsigned char hram[64]; + unsigned char mulres[32]; + + // r = H(s || M) where here s is pseudorandom bytes typically generated as + // part of hashing the seed (i.e. [a,s] = H(k)), but for derived + // PrivateKeys will come from a hash of the root key's s concatenated with + // the derivation hash. + crypto_hash_sha512_init(&hs); + crypto_hash_sha512_update(&hs, privkey.signingHash(), 32); + crypto_hash_sha512_update(&hs, buf, size); + crypto_hash_sha512_final(&hs, nonce); + crypto_core_ed25519_scalar_reduce(nonce, nonce); + + // copy pubkey into sig to make (for now) sig = (R || A) + memmove(sig.data() + 32, pubkey.data(), 32); + + // R = r * B + crypto_scalarmult_ed25519_base_noclamp(sig.data(), nonce); + + // hram = H(R || A || M) + crypto_hash_sha512_init(&hs); + crypto_hash_sha512_update(&hs, sig.data(), 64); + crypto_hash_sha512_update(&hs, buf, size); + crypto_hash_sha512_final(&hs, hram); + + // S = r + H(R || A || M) * s, so sig = (R || S) + crypto_core_ed25519_scalar_reduce(hram, hram); + crypto_core_ed25519_scalar_mul(mulres, hram, privkey.data()); + crypto_core_ed25519_scalar_add(sig.data() + 32, mulres, nonce); + + sodium_memzero(nonce, sizeof nonce); + + return true; + } + + bool + Crypto::verify(const PubKey& pub, uint8_t* buf, size_t size, const Signature& sig) + { + return crypto_sign_verify_detached(sig.data(), buf, size, pub.data()) != -1; + } + + bool + Crypto::verify(uint8_t* pub, uint8_t* buf, size_t size, uint8_t* sig) + { + return crypto_sign_verify_detached(sig, buf, size, pub) != -1; + } + + /// clamp a 32 byte ec point + static void + clamp_ed25519(byte_t* out) + { + out[0] &= 248; + out[31] &= 127; + out[31] |= 64; + } + + template + static K + clamp(const K& p) + { + K out = p; + clamp_ed25519(out); + return out; + } + + template + static bool + is_clamped(const K& key) + { + K other(key); + clamp_ed25519(other.data()); + return other == key; + } + + constexpr static char derived_key_hash_str[161] = + "just imagine what would happen if we all decided to understand. you " + "can't in the and by be or then before so just face it this text hurts " + "to read? lokinet yolo!"; + + template + static bool + make_scalar(AlignedBuffer<32>& out, const K& k, uint64_t i) + { + // b = BLIND-STRING || k || i + std::array buf; + std::copy(derived_key_hash_str, derived_key_hash_str + 160, buf.begin()); + std::copy(k.begin(), k.end(), buf.begin() + 160); + oxenc::write_host_as_little(i, buf.data() + 160 + K::SIZE); + // n = H(b) + // h = make_point(n) + ShortHash n; + return -1 + != crypto_generichash_blake2b(n.data(), ShortHash::SIZE, buf.data(), buf.size(), nullptr, 0) + && -1 != crypto_core_ed25519_from_uniform(out.data(), n.data()); + } + + static AlignedBuffer<32> zero; + + bool + Crypto::derive_subkey( + PubKey& out_pubkey, const PubKey& root_pubkey, uint64_t key_n, const AlignedBuffer<32>* hash) + { + // scalar h = H( BLIND-STRING || root_pubkey || key_n ) + AlignedBuffer<32> h; + if (hash) + h = *hash; + else if (not make_scalar(h, root_pubkey, key_n)) + { + LogError("cannot make scalar"); + return false; + } + + return 0 == crypto_scalarmult_ed25519(out_pubkey.data(), h.data(), root_pubkey.data()); + } + + bool + Crypto::derive_subkey_private( + PrivateKey& out_key, const SecretKey& root_key, uint64_t key_n, const AlignedBuffer<32>* hash) + { + // Derives a private subkey from a root key. + // + // The basic idea is: + // + // h = H( BLIND-STRING || A || key_n ) + // a - private key + // A = aB - public key + // s - signing hash + // a' = ah - derived private key + // A' = a'B = (ah)B - derived public key + // s' = H(h || s) - derived signing hash + // + // libsodium throws some wrenches in the mechanics which are a nuisance, + // the biggest of which is that sodium's secret key is *not* `a`; rather + // it is the seed. If you want to get the private key (i.e. "a"), you + // need to SHA-512 hash it and then clamp that. + // + // This also makes signature verification harder: we can't just use + // sodium's sign function because it wants to be given the seed rather + // than the private key, and moreover we can't actually *get* the seed to + // make libsodium happy because we only have `ah` above; thus we + // reimplemented most of sodium's detached signing function but without + // the hash step. + // + // Lastly, for the signing hash s', we need some value that is both + // different from the root s but also unknowable from the public key + // (since otherwise `r` in the signing function would be known), so we + // generate it from a hash of `h` and the root key's (psuedorandom) + // signing hash, `s`. + // + const auto root_pubkey = root_key.toPublic(); + + AlignedBuffer<32> h; + if (hash) + h = *hash; + else if (not make_scalar(h, root_pubkey, key_n)) + { + LogError("cannot make scalar"); + return false; + } + + h[0] &= 248; + h[31] &= 63; + h[31] |= 64; + + PrivateKey a; + if (!root_key.toPrivate(a)) + return false; + + // a' = ha + crypto_core_ed25519_scalar_mul(out_key.data(), h.data(), a.data()); + + // s' = H(h || s) + std::array buf; + std::copy(h.begin(), h.end(), buf.begin()); + std::copy(a.signingHash(), a.signingHash() + 32, buf.begin() + 32); + return -1 + != crypto_generichash_blake2b( + out_key.signingHash(), 32, buf.data(), buf.size(), nullptr, 0); + + 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(const llarp_buffer_t& buff) + { + randombytes((unsigned char*)buff.base, buff.sz); + } + + void + Crypto::randbytes(byte_t* ptr, size_t sz) + { + randombytes((unsigned char*)ptr, sz); + } + + void + Crypto::identity_keygen(llarp::SecretKey& keys) + { + PubKey pk; + int result = crypto_sign_keypair(pk.data(), keys.data()); + assert(result != -1); + const PubKey sk_pk = keys.toPublic(); + assert(pk == sk_pk); + (void)result; + (void)sk_pk; + + // encryption_keygen(keys); + } + + bool + Crypto::check_identity_privkey(const llarp::SecretKey& keys) + { + AlignedBuffer seed; + llarp::PubKey pk; + llarp::SecretKey sk; + if (crypto_sign_ed25519_sk_to_seed(seed.data(), keys.data()) == -1) + return false; + if (crypto_sign_seed_keypair(pk.data(), sk.data(), seed.data()) == -1) + return false; + return keys.toPublic() == pk && sk == keys; + } + + void + Crypto::encryption_keygen(llarp::SecretKey& keys) + { + auto d = keys.data(); + randbytes(d, 32); + crypto_scalarmult_curve25519_base(d + 32, d); + } + + bool + Crypto::pqe_encrypt(PQCipherBlock& ciphertext, SharedSecret& sharedkey, const PQPubKey& pubkey) + { + return crypto_kem_enc(ciphertext.data(), sharedkey.data(), pubkey.data()) != -1; + } + bool + Crypto::pqe_decrypt( + const PQCipherBlock& ciphertext, SharedSecret& sharedkey, const byte_t* secretkey) + { + return crypto_kem_dec(sharedkey.data(), ciphertext.data(), secretkey) != -1; + } + + void + Crypto::pqe_keygen(PQKeyPair& keypair) + { + auto d = keypair.data(); + crypto_kem_keypair(d + PQ_SECRETKEYSIZE, d); + } + + bool + Crypto::check_passwd_hash(std::string pwhash, std::string challenge) + { + (void)pwhash; + (void)challenge; + bool ret = false; +#ifdef HAVE_CRYPT + auto pos = pwhash.find_last_of('$'); + auto settings = pwhash.substr(0, pos); + crypt_data data{}; + if (char* ptr = crypt_r(challenge.c_str(), settings.c_str(), &data)) + { + ret = ptr == pwhash; + } + sodium_memzero(&data, sizeof(data)); +#endif + return ret; + } + + const byte_t* + seckey_topublic(const SecretKey& sec) + { + return sec.data() + 32; + } + + const byte_t* + pq_keypair_to_public(const PQKeyPair& k) + { + return k.data() + PQ_SECRETKEYSIZE; + } + + const byte_t* + pq_keypair_to_secret(const PQKeyPair& k) + { + return k.data(); + } + + uint64_t + randint() + { + uint64_t i; + randombytes((byte_t*)&i, sizeof(i)); + return i; + } +} // namespace llarp diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index 1af34e6b45..a1ecbcb32f 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -9,105 +9,106 @@ #include -/** - * crypto.hpp - * - * libsodium abstraction layer - * potentially allow libssl support in the future - */ - namespace llarp { - /// library crypto configuration struct Crypto { - virtual ~Crypto() = 0; + Crypto(); + + ~Crypto() = default; - /// decrypt cipherText name given the key generated from name - virtual std::optional> - maybe_decrypt_name(std::string_view ciphertext, SymmNonce nounce, std::string_view name) = 0; + /// decrypt cipherText given the key generated from name + std::optional> + maybe_decrypt_name(std::string_view ciphertext, SymmNonce nounce, std::string_view name); /// xchacha symmetric cipher - virtual bool - xchacha20(const llarp_buffer_t&, const SharedSecret&, const TunnelNonce&) = 0; + bool + xchacha20(uint8_t*, size_t size, const SharedSecret&, const TunnelNonce&); /// xchacha symmetric cipher (multibuffer) - virtual bool - xchacha20_alt( - const llarp_buffer_t&, const llarp_buffer_t&, const SharedSecret&, const byte_t*) = 0; + bool + xchacha20_alt(const llarp_buffer_t&, const llarp_buffer_t&, const SharedSecret&, const byte_t*); /// path dh creator's side - virtual bool - dh_client(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&) = 0; + bool + dh_client(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&); /// path dh relay side - virtual bool - dh_server(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&) = 0; + bool + dh_server(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&); /// transport dh client side - virtual bool - transport_dh_client(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&) = 0; + bool + transport_dh_client(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&); /// transport dh server side - virtual bool - transport_dh_server(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&) = 0; + bool + transport_dh_server(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&); /// blake2b 256 bit - virtual bool - shorthash(ShortHash&, const llarp_buffer_t&) = 0; - /// blake2s 256 bit "hmac" (keyed hash) - virtual bool - hmac(byte_t*, const llarp_buffer_t&, const SharedSecret&) = 0; + bool + shorthash(ShortHash&, uint8_t*, size_t size); + /// blake2s 256 bit hmac + bool + hmac(uint8_t*, uint8_t*, size_t, const SharedSecret&); /// ed25519 sign - virtual bool - sign(Signature&, const SecretKey&, const llarp_buffer_t&) = 0; + bool + sign(Signature&, const SecretKey&, uint8_t* buf, size_t size); /// ed25519 sign (custom with derived keys) - virtual bool - sign(Signature&, const PrivateKey&, const llarp_buffer_t&) = 0; + bool + sign(Signature&, const PrivateKey&, uint8_t* buf, size_t size); /// ed25519 verify - virtual bool - verify(const PubKey&, const llarp_buffer_t&, const Signature&) = 0; - - /// derive sub keys for public keys - virtual bool - derive_subkey(PubKey&, const PubKey&, uint64_t, const AlignedBuffer<32>* = nullptr) = 0; - - /// derive sub keys for private keys - virtual bool + bool + verify(const PubKey&, uint8_t*, size_t, const Signature&); + bool + verify(uint8_t*, uint8_t*, size_t, uint8_t*); + + /// derive sub keys for public keys. hash is really only intended for + /// testing ands key_n if given. + bool + derive_subkey( + PubKey& derived, + const PubKey& root, + uint64_t key_n, + const AlignedBuffer<32>* hash = nullptr); + + /// derive sub keys for private keys. hash is really only intended for + /// testing ands key_n if given. + bool derive_subkey_private( - PrivateKey&, const SecretKey&, uint64_t, const AlignedBuffer<32>* = nullptr) = 0; + PrivateKey& derived, + const SecretKey& root, + uint64_t key_n, + const AlignedBuffer<32>* hash = nullptr); /// seed to secretkey - virtual bool - seed_to_secretkey(llarp::SecretKey&, const llarp::IdentitySecret&) = 0; + bool + seed_to_secretkey(llarp::SecretKey&, const llarp::IdentitySecret&); /// randomize buffer - virtual void - randomize(const llarp_buffer_t&) = 0; + void + randomize(const llarp_buffer_t&); /// randomizer memory - virtual void - randbytes(byte_t*, size_t) = 0; + void + randbytes(byte_t*, size_t); /// generate signing keypair - virtual void - identity_keygen(SecretKey&) = 0; + void + identity_keygen(SecretKey&); /// generate encryption keypair - virtual void - encryption_keygen(SecretKey&) = 0; + void + encryption_keygen(SecretKey&); /// generate post quantum encrytion key - virtual void - pqe_keygen(PQKeyPair&) = 0; + void + pqe_keygen(PQKeyPair&); /// post quantum decrypt (buffer, sharedkey_dst, sec) - virtual bool - pqe_decrypt(const PQCipherBlock&, SharedSecret&, const byte_t*) = 0; + bool + pqe_decrypt(const PQCipherBlock&, SharedSecret&, const byte_t*); /// post quantum encrypt (buffer, sharedkey_dst, pub) - virtual bool - pqe_encrypt(PQCipherBlock&, SharedSecret&, const PQPubKey&) = 0; + bool + pqe_encrypt(PQCipherBlock&, SharedSecret&, const PQPubKey&); - virtual bool - check_identity_privkey(const SecretKey&) = 0; + bool + check_identity_privkey(const SecretKey&); - /// check if a password hash string matches the challenge - virtual bool - check_passwd_hash(std::string pwhash, std::string challenge) = 0; + bool + check_passwd_hash(std::string pwhash, std::string challenge); }; - inline Crypto::~Crypto() = default; - /// return random 64bit unsigned interger uint64_t randint(); diff --git a/llarp/crypto/crypto_libsodium.cpp b/llarp/crypto/crypto_libsodium.cpp deleted file mode 100644 index a5671a1511..0000000000 --- a/llarp/crypto/crypto_libsodium.cpp +++ /dev/null @@ -1,518 +0,0 @@ -#include "crypto_libsodium.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_CRYPT -#include -#endif - -#include - -extern "C" -{ - extern int - sodium_init(void); -} - -namespace llarp -{ - namespace sodium - { - static bool - dh(llarp::SharedSecret& out, - const PubKey& client_pk, - const PubKey& server_pk, - const uint8_t* themPub, - const SecretKey& usSec) - { - llarp::SharedSecret shared; - crypto_generichash_state h; - - if (crypto_scalarmult_curve25519(shared.data(), usSec.data(), themPub)) - { - return false; - } - crypto_generichash_blake2b_init(&h, nullptr, 0U, shared.size()); - crypto_generichash_blake2b_update(&h, client_pk.data(), 32); - crypto_generichash_blake2b_update(&h, server_pk.data(), 32); - crypto_generichash_blake2b_update(&h, shared.data(), 32); - crypto_generichash_blake2b_final(&h, out.data(), shared.size()); - return true; - } - - static bool - dh_client_priv( - llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n) - { - llarp::SharedSecret dh_result; - - if (dh(dh_result, sk.toPublic(), pk, pk.data(), sk)) - { - return crypto_generichash_blake2b(shared.data(), 32, n.data(), 32, dh_result.data(), 32) - != -1; - } - llarp::LogWarn("crypto::dh_client - dh failed"); - return false; - } - - static bool - dh_server_priv( - llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n) - { - llarp::SharedSecret dh_result; - if (dh(dh_result, pk, sk.toPublic(), pk.data(), sk)) - { - return crypto_generichash_blake2b(shared.data(), 32, n.data(), 32, dh_result.data(), 32) - != -1; - } - llarp::LogWarn("crypto::dh_server - dh failed"); - return false; - } - - CryptoLibSodium::CryptoLibSodium() - { - if (sodium_init() == -1) - { - throw std::runtime_error("sodium_init() returned -1"); - } - char* avx2 = std::getenv("AVX2_FORCE_DISABLE"); - if (avx2 && std::string(avx2) == "1") - { - ntru_init(1); - } - else - { - ntru_init(0); - } - int seed = 0; - randombytes(reinterpret_cast(&seed), sizeof(seed)); - srand(seed); - } - - std::optional> - CryptoLibSodium::maybe_decrypt_name( - std::string_view ciphertext, SymmNonce nounce, std::string_view name) - { - const auto payloadsize = ciphertext.size() - crypto_aead_xchacha20poly1305_ietf_ABYTES; - if (payloadsize != 32) - return {}; - - SharedSecret derivedKey{}; - ShortHash namehash{}; - const llarp_buffer_t namebuf(reinterpret_cast(name.data()), name.size()); - if (not shorthash(namehash, namebuf)) - return {}; - if (not hmac(derivedKey.data(), namebuf, namehash)) - return {}; - AlignedBuffer<32> result{}; - if (crypto_aead_xchacha20poly1305_ietf_decrypt( - result.data(), - nullptr, - nullptr, - reinterpret_cast(ciphertext.data()), - ciphertext.size(), - nullptr, - 0, - nounce.data(), - derivedKey.data()) - == -1) - { - return {}; - } - return result; - } - - bool - CryptoLibSodium::xchacha20( - const llarp_buffer_t& buff, const SharedSecret& k, const TunnelNonce& n) - { - return crypto_stream_xchacha20_xor(buff.base, buff.base, buff.sz, n.data(), k.data()) == 0; - } - - bool - CryptoLibSodium::xchacha20_alt( - const llarp_buffer_t& out, const llarp_buffer_t& in, const SharedSecret& k, const byte_t* n) - { - if (in.sz > out.sz) - return false; - return crypto_stream_xchacha20_xor(out.base, in.base, in.sz, n, k.data()) == 0; - } - - bool - CryptoLibSodium::dh_client( - llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n) - { - return dh_client_priv(shared, pk, sk, n); - } - /// path dh relay side - bool - CryptoLibSodium::dh_server( - llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n) - { - return dh_server_priv(shared, pk, sk, n); - } - /// transport dh client side - bool - CryptoLibSodium::transport_dh_client( - llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n) - { - return dh_client_priv(shared, pk, sk, n); - } - /// transport dh server side - bool - CryptoLibSodium::transport_dh_server( - llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n) - { - return dh_server_priv(shared, pk, sk, n); - } - - bool - CryptoLibSodium::shorthash(ShortHash& result, const llarp_buffer_t& buff) - { - return crypto_generichash_blake2b( - result.data(), ShortHash::SIZE, buff.base, buff.sz, nullptr, 0) - != -1; - } - - bool - CryptoLibSodium::hmac(byte_t* result, const llarp_buffer_t& buff, const SharedSecret& secret) - { - return crypto_generichash_blake2b( - result, HMACSIZE, buff.base, buff.sz, secret.data(), HMACSECSIZE) - != -1; - } - - static bool - hash(uint8_t* result, const llarp_buffer_t& buff) - { - return crypto_generichash_blake2b(result, HASHSIZE, buff.base, buff.sz, nullptr, 0) != -1; - } - - bool - CryptoLibSodium::sign(Signature& sig, const SecretKey& secret, const llarp_buffer_t& buf) - { - return crypto_sign_detached(sig.data(), nullptr, buf.base, buf.sz, secret.data()) != -1; - } - - bool - CryptoLibSodium::sign(Signature& sig, const PrivateKey& privkey, const llarp_buffer_t& buf) - { - PubKey pubkey; - - privkey.toPublic(pubkey); - - crypto_hash_sha512_state hs; - unsigned char nonce[64]; - unsigned char hram[64]; - unsigned char mulres[32]; - - // r = H(s || M) where here s is pseudorandom bytes typically generated as - // part of hashing the seed (i.e. [a,s] = H(k)), but for derived - // PrivateKeys will come from a hash of the root key's s concatenated with - // the derivation hash. - crypto_hash_sha512_init(&hs); - crypto_hash_sha512_update(&hs, privkey.signingHash(), 32); - crypto_hash_sha512_update(&hs, buf.base, buf.sz); - crypto_hash_sha512_final(&hs, nonce); - crypto_core_ed25519_scalar_reduce(nonce, nonce); - - // copy pubkey into sig to make (for now) sig = (R || A) - memmove(sig.data() + 32, pubkey.data(), 32); - - // R = r * B - crypto_scalarmult_ed25519_base_noclamp(sig.data(), nonce); - - // hram = H(R || A || M) - crypto_hash_sha512_init(&hs); - crypto_hash_sha512_update(&hs, sig.data(), 64); - crypto_hash_sha512_update(&hs, buf.base, buf.sz); - crypto_hash_sha512_final(&hs, hram); - - // S = r + H(R || A || M) * s, so sig = (R || S) - crypto_core_ed25519_scalar_reduce(hram, hram); - crypto_core_ed25519_scalar_mul(mulres, hram, privkey.data()); - crypto_core_ed25519_scalar_add(sig.data() + 32, mulres, nonce); - - sodium_memzero(nonce, sizeof nonce); - - return true; - } - - bool - CryptoLibSodium::verify(const PubKey& pub, const llarp_buffer_t& buf, const Signature& sig) - { - return crypto_sign_verify_detached(sig.data(), buf.base, buf.sz, pub.data()) != -1; - } - - /// clamp a 32 byte ec point - static void - clamp_ed25519(byte_t* out) - { - out[0] &= 248; - out[31] &= 127; - out[31] |= 64; - } - - template - static K - clamp(const K& p) - { - K out = p; - clamp_ed25519(out); - return out; - } - - template - static bool - is_clamped(const K& key) - { - K other(key); - clamp_ed25519(other.data()); - return other == key; - } - - constexpr static char derived_key_hash_str[161] = - "just imagine what would happen if we all decided to understand. you " - "can't in the and by be or then before so just face it this text hurts " - "to read? lokinet yolo!"; - - template - static bool - make_scalar(AlignedBuffer<32>& out, const K& k, uint64_t i) - { - // b = BLIND-STRING || k || i - std::array buf; - std::copy(derived_key_hash_str, derived_key_hash_str + 160, buf.begin()); - std::copy(k.begin(), k.end(), buf.begin() + 160); - oxenc::write_host_as_little(i, buf.data() + 160 + K::SIZE); - // n = H(b) - // h = make_point(n) - ShortHash n; - return -1 - != crypto_generichash_blake2b( - n.data(), ShortHash::SIZE, buf.data(), buf.size(), nullptr, 0) - && -1 != crypto_core_ed25519_from_uniform(out.data(), n.data()); - } - - static AlignedBuffer<32> zero; - - bool - CryptoLibSodium::derive_subkey( - PubKey& out_pubkey, - const PubKey& root_pubkey, - uint64_t key_n, - const AlignedBuffer<32>* hash) - { - // scalar h = H( BLIND-STRING || root_pubkey || key_n ) - AlignedBuffer<32> h; - if (hash) - h = *hash; - else if (not make_scalar(h, root_pubkey, key_n)) - { - LogError("cannot make scalar"); - return false; - } - - return 0 == crypto_scalarmult_ed25519(out_pubkey.data(), h.data(), root_pubkey.data()); - } - - bool - CryptoLibSodium::derive_subkey_private( - PrivateKey& out_key, - const SecretKey& root_key, - uint64_t key_n, - const AlignedBuffer<32>* hash) - { - // Derives a private subkey from a root key. - // - // The basic idea is: - // - // h = H( BLIND-STRING || A || key_n ) - // a - private key - // A = aB - public key - // s - signing hash - // a' = ah - derived private key - // A' = a'B = (ah)B - derived public key - // s' = H(h || s) - derived signing hash - // - // libsodium throws some wrenches in the mechanics which are a nuisance, - // the biggest of which is that sodium's secret key is *not* `a`; rather - // it is the seed. If you want to get the private key (i.e. "a"), you - // need to SHA-512 hash it and then clamp that. - // - // This also makes signature verification harder: we can't just use - // sodium's sign function because it wants to be given the seed rather - // than the private key, and moreover we can't actually *get* the seed to - // make libsodium happy because we only have `ah` above; thus we - // reimplemented most of sodium's detached signing function but without - // the hash step. - // - // Lastly, for the signing hash s', we need some value that is both - // different from the root s but also unknowable from the public key - // (since otherwise `r` in the signing function would be known), so we - // generate it from a hash of `h` and the root key's (psuedorandom) - // signing hash, `s`. - // - const auto root_pubkey = root_key.toPublic(); - - AlignedBuffer<32> h; - if (hash) - h = *hash; - else if (not make_scalar(h, root_pubkey, key_n)) - { - LogError("cannot make scalar"); - return false; - } - - h[0] &= 248; - h[31] &= 63; - h[31] |= 64; - - PrivateKey a; - if (!root_key.toPrivate(a)) - return false; - - // a' = ha - crypto_core_ed25519_scalar_mul(out_key.data(), h.data(), a.data()); - - // s' = H(h || s) - std::array buf; - std::copy(h.begin(), h.end(), buf.begin()); - std::copy(a.signingHash(), a.signingHash() + 32, buf.begin() + 32); - return -1 - != crypto_generichash_blake2b( - out_key.signingHash(), 32, buf.data(), buf.size(), nullptr, 0); - - return true; - } - - bool - CryptoLibSodium::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 - CryptoLibSodium::randomize(const llarp_buffer_t& buff) - { - randombytes((unsigned char*)buff.base, buff.sz); - } - - void - CryptoLibSodium::randbytes(byte_t* ptr, size_t sz) - { - randombytes((unsigned char*)ptr, sz); - } - - void - CryptoLibSodium::identity_keygen(llarp::SecretKey& keys) - { - PubKey pk; - int result = crypto_sign_keypair(pk.data(), keys.data()); - assert(result != -1); - const PubKey sk_pk = keys.toPublic(); - assert(pk == sk_pk); - (void)result; - (void)sk_pk; - - // encryption_keygen(keys); - } - - bool - CryptoLibSodium::check_identity_privkey(const llarp::SecretKey& keys) - { - AlignedBuffer seed; - llarp::PubKey pk; - llarp::SecretKey sk; - if (crypto_sign_ed25519_sk_to_seed(seed.data(), keys.data()) == -1) - return false; - if (crypto_sign_seed_keypair(pk.data(), sk.data(), seed.data()) == -1) - return false; - return keys.toPublic() == pk && sk == keys; - } - - void - CryptoLibSodium::encryption_keygen(llarp::SecretKey& keys) - { - auto d = keys.data(); - randbytes(d, 32); - crypto_scalarmult_curve25519_base(d + 32, d); - } - - bool - CryptoLibSodium::pqe_encrypt( - PQCipherBlock& ciphertext, SharedSecret& sharedkey, const PQPubKey& pubkey) - { - return crypto_kem_enc(ciphertext.data(), sharedkey.data(), pubkey.data()) != -1; - } - bool - CryptoLibSodium::pqe_decrypt( - const PQCipherBlock& ciphertext, SharedSecret& sharedkey, const byte_t* secretkey) - { - return crypto_kem_dec(sharedkey.data(), ciphertext.data(), secretkey) != -1; - } - - void - CryptoLibSodium::pqe_keygen(PQKeyPair& keypair) - { - auto d = keypair.data(); - crypto_kem_keypair(d + PQ_SECRETKEYSIZE, d); - } - - bool - CryptoLibSodium::check_passwd_hash(std::string pwhash, std::string challenge) - { - (void)pwhash; - (void)challenge; - bool ret = false; -#ifdef HAVE_CRYPT - auto pos = pwhash.find_last_of('$'); - auto settings = pwhash.substr(0, pos); - crypt_data data{}; - if (char* ptr = crypt_r(challenge.c_str(), settings.c_str(), &data)) - { - ret = ptr == pwhash; - } - sodium_memzero(&data, sizeof(data)); -#endif - return ret; - } - } // namespace sodium - - const byte_t* - seckey_topublic(const SecretKey& sec) - { - return sec.data() + 32; - } - - const byte_t* - pq_keypair_to_public(const PQKeyPair& k) - { - return k.data() + PQ_SECRETKEYSIZE; - } - - const byte_t* - pq_keypair_to_secret(const PQKeyPair& k) - { - return k.data(); - } - - uint64_t - randint() - { - uint64_t i; - randombytes((byte_t*)&i, sizeof(i)); - return i; - } - -} // namespace llarp diff --git a/llarp/crypto/crypto_libsodium.hpp b/llarp/crypto/crypto_libsodium.hpp deleted file mode 100644 index 6248e94848..0000000000 --- a/llarp/crypto/crypto_libsodium.hpp +++ /dev/null @@ -1,113 +0,0 @@ -#pragma once - -#include "crypto.hpp" - -namespace llarp -{ - namespace sodium - { - struct CryptoLibSodium final : public Crypto - { - CryptoLibSodium(); - - ~CryptoLibSodium() override = default; - - /// decrypt cipherText given the key generated from name - std::optional> - maybe_decrypt_name( - std::string_view ciphertext, SymmNonce nounce, std::string_view name) override; - - /// xchacha symmetric cipher - bool - xchacha20(const llarp_buffer_t&, const SharedSecret&, const TunnelNonce&) override; - - /// xchacha symmetric cipher (multibuffer) - bool - xchacha20_alt( - const llarp_buffer_t&, - const llarp_buffer_t&, - const SharedSecret&, - const byte_t*) override; - - /// path dh creator's side - bool - dh_client(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&) override; - /// path dh relay side - bool - dh_server(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&) override; - /// transport dh client side - bool - transport_dh_client( - SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&) override; - /// transport dh server side - bool - transport_dh_server( - SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&) override; - /// blake2b 256 bit - bool - shorthash(ShortHash&, const llarp_buffer_t&) override; - /// blake2s 256 bit hmac - bool - hmac(byte_t*, const llarp_buffer_t&, const SharedSecret&) override; - /// ed25519 sign - bool - sign(Signature&, const SecretKey&, const llarp_buffer_t&) override; - /// ed25519 sign (custom with derived keys) - bool - sign(Signature&, const PrivateKey&, const llarp_buffer_t&) override; - /// ed25519 verify - bool - verify(const PubKey&, const llarp_buffer_t&, const Signature&) override; - - /// derive sub keys for public keys. hash is really only intended for - /// testing and overrides key_n if given. - bool - derive_subkey( - PubKey& derived, - const PubKey& root, - uint64_t key_n, - const AlignedBuffer<32>* hash = nullptr) override; - - /// derive sub keys for private keys. hash is really only intended for - /// testing and overrides key_n if given. - bool - derive_subkey_private( - PrivateKey& derived, - const SecretKey& root, - uint64_t key_n, - const AlignedBuffer<32>* hash = nullptr) override; - - /// seed to secretkey - bool - seed_to_secretkey(llarp::SecretKey&, const llarp::IdentitySecret&) override; - /// randomize buffer - void - randomize(const llarp_buffer_t&) override; - /// randomizer memory - void - randbytes(byte_t*, size_t) override; - /// generate signing keypair - void - identity_keygen(SecretKey&) override; - /// generate encryption keypair - void - encryption_keygen(SecretKey&) override; - /// generate post quantum encrytion key - void - pqe_keygen(PQKeyPair&) override; - /// post quantum decrypt (buffer, sharedkey_dst, sec) - bool - pqe_decrypt(const PQCipherBlock&, SharedSecret&, const byte_t*) override; - /// post quantum encrypt (buffer, sharedkey_dst, pub) - bool - pqe_encrypt(PQCipherBlock&, SharedSecret&, const PQPubKey&) override; - - bool - check_identity_privkey(const SecretKey&) override; - - bool - check_passwd_hash(std::string pwhash, std::string challenge) override; - }; - } // namespace sodium - -} // namespace llarp diff --git a/llarp/crypto/encrypted_frame.cpp b/llarp/crypto/encrypted_frame.cpp index 210f0e1dca..6573d95330 100644 --- a/llarp/crypto/encrypted_frame.cpp +++ b/llarp/crypto/encrypted_frame.cpp @@ -9,42 +9,29 @@ namespace llarp bool EncryptedFrame::DoEncrypt(const SharedSecret& shared, bool noDH) { - byte_t* hash = data(); - byte_t* noncePtr = hash + SHORTHASHSIZE; - byte_t* pubkey = noncePtr + TUNNONCESIZE; - byte_t* body = pubkey + PUBKEYSIZE; - auto crypto = CryptoManager::instance(); - // if noDH flag, means key exchange has already taken place - // in this case, set pubkey to random noise and choose a - // random nonce here + uint8_t* hash_ptr = data(); + uint8_t* nonce_ptr = hash_ptr + SHORTHASHSIZE; + uint8_t* pubkey_ptr = nonce_ptr + TUNNONCESIZE; + uint8_t* body_ptr = pubkey_ptr + PUBKEYSIZE; + if (noDH) { - crypto->randbytes(noncePtr, TUNNONCESIZE); - crypto->randbytes(pubkey, PUBKEYSIZE); + crypto->randbytes(nonce_ptr, TUNNONCESIZE); + crypto->randbytes(pubkey_ptr, PUBKEYSIZE); } - TunnelNonce nonce(noncePtr); - - llarp_buffer_t buf; - buf.base = body; - buf.cur = buf.base; - buf.sz = size() - EncryptedFrameOverheadSize; + TunnelNonce nonce(nonce_ptr); // encrypt body - if (!crypto->xchacha20(buf, shared, nonce)) + if (!crypto->xchacha20(body_ptr, size() - EncryptedFrameOverheadSize, shared, nonce)) { llarp::LogError("encrypt failed"); return false; } - // generate message auth - buf.base = noncePtr; - buf.cur = buf.base; - buf.sz = size() - SHORTHASHSIZE; - - if (!crypto->hmac(hash, buf, shared)) + if (!crypto->hmac(hash_ptr, nonce_ptr, size() - SHORTHASHSIZE, shared)) { llarp::LogError("Failed to generate message auth"); return false; @@ -89,36 +76,28 @@ namespace llarp bool EncryptedFrame::DoDecrypt(const SharedSecret& shared) { - ShortHash hash(data()); - byte_t* noncePtr = data() + SHORTHASHSIZE; - byte_t* body = data() + EncryptedFrameOverheadSize; - TunnelNonce nonce(noncePtr); - auto crypto = CryptoManager::instance(); - llarp_buffer_t buf; - buf.base = noncePtr; - buf.cur = buf.base; - buf.sz = size() - SHORTHASHSIZE; + uint8_t* hash_ptr = data(); + uint8_t* nonce_ptr = hash_ptr + SHORTHASHSIZE; + uint8_t* body_ptr = hash_ptr + EncryptedFrameOverheadSize; + + TunnelNonce nonce(nonce_ptr); ShortHash digest; - if (!crypto->hmac(digest.data(), buf, shared)) + if (!crypto->hmac(digest.data(), nonce_ptr, size() - SHORTHASHSIZE, shared)) { llarp::LogError("Digest failed"); return false; } - if (!std::equal(digest.begin(), digest.end(), hash.begin())) + if (!std::equal(digest.begin(), digest.end(), hash_ptr)) { llarp::LogError("message authentication failed"); return false; } - buf.base = body; - buf.cur = body; - buf.sz = size() - EncryptedFrameOverheadSize; - - if (!crypto->xchacha20(buf, shared, nonce)) + if (!crypto->xchacha20(body_ptr, size() - EncryptedFrameOverheadSize, shared, nonce)) { llarp::LogError("decrypt failed"); return false; diff --git a/llarp/crypto/types.hpp b/llarp/crypto/types.hpp index bc4b6e2a2a..584383cf14 100644 --- a/llarp/crypto/types.hpp +++ b/llarp/crypto/types.hpp @@ -21,7 +21,7 @@ namespace llarp explicit PubKey(const byte_t* ptr) : AlignedBuffer(ptr) {} - explicit PubKey(const Data& data) : AlignedBuffer(data) + explicit PubKey(const std::array& data) : AlignedBuffer(data) {} explicit PubKey(const AlignedBuffer& other) : AlignedBuffer(other) diff --git a/llarp/dht/bucket.hpp b/llarp/dht/bucket.hpp index 03232d7d80..fd3e9ff35c 100644 --- a/llarp/dht/bucket.hpp +++ b/llarp/dht/bucket.hpp @@ -8,224 +8,221 @@ #include #include -namespace llarp +namespace llarp::dht { - namespace dht + template + struct Bucket { - template - struct Bucket - { - using BucketStorage_t = std::map; - using Random_t = std::function; + using BucketStorage_t = std::map; + using Random_t = std::function; - Bucket(const Key_t& us, Random_t r) : nodes(XorMetric(us)), random(std::move(r)) - {} + Bucket(const Key_t& us, Random_t r) : nodes(XorMetric(us)), random(std::move(r)) + {} - util::StatusObject - ExtractStatus() const + util::StatusObject + ExtractStatus() const + { + util::StatusObject obj{}; + for (const auto& item : nodes) { - util::StatusObject obj{}; - for (const auto& item : nodes) - { - obj[item.first.ToString()] = item.second.ExtractStatus(); - } - return obj; + obj[item.first.ToString()] = item.second.ExtractStatus(); } + return obj; + } - size_t - size() const - { - return nodes.size(); - } + size_t + size() const + { + return nodes.size(); + } - struct SetIntersector + struct SetIntersector + { + bool + operator()(const typename BucketStorage_t::value_type& lhs, const Key_t& rhs) { - bool - operator()(const typename BucketStorage_t::value_type& lhs, const Key_t& rhs) - { - return lhs.first < rhs; - } - - bool - operator()(const Key_t& lhs, const typename BucketStorage_t::value_type& rhs) - { - return lhs < rhs.first; - } - }; + return lhs.first < rhs; + } bool - GetRandomNodeExcluding(Key_t& result, const std::set& exclude) const + operator()(const Key_t& lhs, const typename BucketStorage_t::value_type& rhs) { - std::vector candidates; - std::set_difference( - nodes.begin(), - nodes.end(), - exclude.begin(), - exclude.end(), - std::back_inserter(candidates), - SetIntersector()); - - if (candidates.empty()) - { - return false; - } - result = candidates[random() % candidates.size()].first; - return true; + return lhs < rhs.first; } + }; - bool - FindClosest(const Key_t& target, Key_t& result) const + bool + GetRandomNodeExcluding(Key_t& result, const std::set& exclude) const + { + std::vector candidates; + std::set_difference( + nodes.begin(), + nodes.end(), + exclude.begin(), + exclude.end(), + std::back_inserter(candidates), + SetIntersector()); + + if (candidates.empty()) { - Key_t mindist; - mindist.Fill(0xff); - for (const auto& item : nodes) - { - auto curDist = item.first ^ target; - if (curDist < mindist) - { - mindist = curDist; - result = item.first; - } - } - return nodes.size() > 0; + return false; } + result = candidates[random() % candidates.size()].first; + return true; + } - bool - GetManyRandom(std::set& result, size_t N) const + bool + FindClosest(const Key_t& target, Key_t& result) const + { + Key_t mindist; + mindist.Fill(0xff); + for (const auto& item : nodes) { - if (nodes.size() < N || nodes.empty()) + auto curDist = item.first ^ target; + if (curDist < mindist) { - llarp::LogWarn("Not enough dht nodes, have ", nodes.size(), " want ", N); - return false; + mindist = curDist; + result = item.first; } - if (nodes.size() == N) - { - std::transform( - nodes.begin(), nodes.end(), std::inserter(result, result.end()), [](const auto& a) { - return a.first; - }); + } + return nodes.size() > 0; + } - return true; - } - size_t expecting = N; - size_t sz = nodes.size(); - while (N) - { - auto itr = nodes.begin(); - std::advance(itr, random() % sz); - if (result.insert(itr->first).second) - { - --N; - } - } - return result.size() == expecting; + bool + GetManyRandom(std::set& result, size_t N) const + { + if (nodes.size() < N || nodes.empty()) + { + llarp::LogWarn("Not enough dht nodes, have ", nodes.size(), " want ", N); + return false; } + if (nodes.size() == N) + { + std::transform( + nodes.begin(), nodes.end(), std::inserter(result, result.end()), [](const auto& a) { + return a.first; + }); - bool - FindCloseExcluding(const Key_t& target, Key_t& result, const std::set& exclude) const + return true; + } + size_t expecting = N; + size_t sz = nodes.size(); + while (N) { - Key_t maxdist; - maxdist.Fill(0xff); - Key_t mindist; - mindist.Fill(0xff); - for (const auto& item : nodes) + auto itr = nodes.begin(); + std::advance(itr, random() % sz); + if (result.insert(itr->first).second) { - if (exclude.count(item.first)) - { - continue; - } - - auto curDist = item.first ^ target; - if (curDist < mindist) - { - mindist = curDist; - result = item.first; - } + --N; } - return mindist < maxdist; } + return result.size() == expecting; + } - bool - GetManyNearExcluding( - const Key_t& target, - std::set& result, - size_t N, - const std::set& exclude) const + bool + FindCloseExcluding(const Key_t& target, Key_t& result, const std::set& exclude) const + { + Key_t maxdist; + maxdist.Fill(0xff); + Key_t mindist; + mindist.Fill(0xff); + for (const auto& item : nodes) { - std::set s(exclude.begin(), exclude.end()); - - Key_t peer; - while (N--) + if (exclude.count(item.first)) { - if (!FindCloseExcluding(target, peer, s)) - { - return false; - } - s.insert(peer); - result.insert(peer); + continue; } - return true; - } - void - PutNode(const Val_t& val) - { - auto itr = nodes.find(val.ID); - if (itr == nodes.end() || itr->second < val) + auto curDist = item.first ^ target; + if (curDist < mindist) { - nodes[val.ID] = val; + mindist = curDist; + result = item.first; } } + return mindist < maxdist; + } + + bool + GetManyNearExcluding( + const Key_t& target, + std::set& result, + size_t N, + const std::set& exclude) const + { + std::set s(exclude.begin(), exclude.end()); - void - DelNode(const Key_t& key) + Key_t peer; + while (N--) { - auto itr = nodes.find(key); - if (itr != nodes.end()) + if (!FindCloseExcluding(target, peer, s)) { - nodes.erase(itr); + return false; } + s.insert(peer); + result.insert(peer); } + return true; + } - bool - HasNode(const Key_t& key) const + void + PutNode(const Val_t& val) + { + auto itr = nodes.find(val.ID); + if (itr == nodes.end() || itr->second < val) { - return nodes.find(key) != nodes.end(); + nodes[val.ID] = val; } + } - // remove all nodes who's key matches a predicate - template - void - RemoveIf(Predicate pred) + void + DelNode(const Key_t& key) + { + auto itr = nodes.find(key); + if (itr != nodes.end()) { - auto itr = nodes.begin(); - while (itr != nodes.end()) - { - if (pred(itr->first)) - itr = nodes.erase(itr); - else - ++itr; - } + nodes.erase(itr); } + } + + bool + HasNode(const Key_t& key) const + { + return nodes.find(key) != nodes.end(); + } - template - void - ForEachNode(Visit_t visit) + // remove all nodes who's key matches a predicate + template + void + RemoveIf(Predicate pred) + { + auto itr = nodes.begin(); + while (itr != nodes.end()) { - for (const auto& item : nodes) - { - visit(item.second); - } + if (pred(itr->first)) + itr = nodes.erase(itr); + else + ++itr; } + } - void - Clear() + template + void + ForEachNode(Visit_t visit) + { + for (const auto& item : nodes) { - nodes.clear(); + visit(item.second); } + } - BucketStorage_t nodes; - Random_t random; - }; - } // namespace dht -} // namespace llarp + void + Clear() + { + nodes.clear(); + } + + BucketStorage_t nodes; + Random_t random; + }; +} // namespace llarp::dht diff --git a/llarp/dht/context.cpp b/llarp/dht/context.cpp index c9231df166..aa7eca5d88 100644 --- a/llarp/dht/context.cpp +++ b/llarp/dht/context.cpp @@ -483,9 +483,7 @@ namespace llarp::dht void DHTMessageHandler::DHTSendTo(const RouterID& peer, AbstractDHTMessage* msg, bool) { - DHTImmediateMessage m; - m.msgs.emplace_back(msg); - router->SendToOrQueue(peer, m); + router->SendToOrQueue(peer, msg); auto now = Now(); router->PersistSessionUntil(peer, now + 1min); } @@ -659,7 +657,7 @@ namespace llarp::dht llarp_time_t DHTMessageHandler::Now() const { - return router->Now(); + return router->now(); } std::unique_ptr diff --git a/llarp/dht/context.hpp b/llarp/dht/context.hpp deleted file mode 100644 index 292ae862fb..0000000000 --- a/llarp/dht/context.hpp +++ /dev/null @@ -1,211 +0,0 @@ -#ifndef LLARP_DHT_CONTEXT -#define LLARP_DHT_CONTEXT - -#include "bucket.hpp" -#include "dht.h" -#include "key.hpp" -#include "message.hpp" -#include -#include "node.hpp" -#include "tx.hpp" -#include "txholder.hpp" -#include "txowner.hpp" -#include -#include -#include - -#include -#include - -namespace llarp -{ - struct Router; - - namespace dht - { - /// number of routers to publish to - static constexpr size_t IntroSetRelayRedundancy = 2; - - /// number of dht locations handled per relay - static constexpr size_t IntroSetRequestsPerRelay = 2; - - static constexpr size_t IntroSetStorageRedundancy = - (IntroSetRelayRedundancy * IntroSetRequestsPerRelay); - - struct AbstractDHTMessageHandler /* : public AbstractMessageHandler */ - { - using PendingIntrosetLookups = TXHolder; - using PendingRouterLookups = TXHolder; - using PendingExploreLookups = TXHolder; - - virtual ~AbstractDHTMessageHandler() = 0; - - virtual bool - LookupRouter(const RouterID& target, RouterLookupHandler result) = 0; - - virtual void - LookupRouterRecursive( - const RouterID& target, - const Key_t& whoasked, - uint64_t whoaskedTX, - const Key_t& askpeer, - RouterLookupHandler result = nullptr) = 0; - - /// Ask a Service Node to perform an Introset lookup for us - virtual void - LookupIntroSetRelayed( - const Key_t& target, - const Key_t& whoasked, - uint64_t whoaskedTX, - const Key_t& askpeer, - uint64_t relayOrder, - service::EncryptedIntroSetLookupHandler result = - service::EncryptedIntroSetLookupHandler()) = 0; - - /// Directly as a Service Node for an Introset - virtual void - LookupIntroSetDirect( - const Key_t& target, - const Key_t& whoasked, - uint64_t whoaskedTX, - const Key_t& askpeer, - service::EncryptedIntroSetLookupHandler result = - service::EncryptedIntroSetLookupHandler()) = 0; - - virtual bool - HasRouterLookup(const RouterID& target) const = 0; - - /// issue dht lookup for router via askpeer and send reply to local path - virtual void - LookupRouterForPath( - const RouterID& target, uint64_t txid, const PathID_t& path, const Key_t& askpeer) = 0; - - virtual void - LookupIntroSetForPath( - const Key_t& addr, - uint64_t txid, - const PathID_t& path, - const Key_t& askpeer, - uint64_t relayOrder) = 0; - - virtual void - DHTSendTo(const RouterID& peer, AbstractDHTMessage* msg, bool keepalive = true) = 0; - - /// get routers closest to target excluding requester - virtual bool - HandleExploritoryRouterLookup( - const Key_t& requester, - uint64_t txid, - const RouterID& target, - std::vector>& reply) = 0; - - /// handle rc lookup from requester for target - virtual void - LookupRouterRelayed( - const Key_t& requester, - uint64_t txid, - const Key_t& target, - bool recursive, - std::vector>& replies) = 0; - - virtual bool - RelayRequestForPath(const PathID_t& localPath, const AbstractDHTMessage& msg) = 0; - - /// send introset to peer from source with S counter and excluding peers - virtual void - PropagateLocalIntroSet( - const PathID_t& path, - uint64_t sourceTX, - const service::EncryptedIntroSet& introset, - const Key_t& peer, - uint64_t relayOrder) = 0; - - /// send introset to peer from source with S counter and excluding peers - virtual void - PropagateIntroSetTo( - const Key_t& source, - uint64_t sourceTX, - const service::EncryptedIntroSet& introset, - const Key_t& peer, - uint64_t relayOrder) = 0; - - virtual void - Init(const Key_t& us, Router* router) = 0; - - virtual std::optional - GetIntroSetByLocation(const Key_t& location) const = 0; - - virtual llarp_time_t - Now() const = 0; - - virtual void - ExploreNetworkVia(const Key_t& peer) = 0; - - virtual llarp::Router* - GetRouter() const = 0; - - virtual bool - GetRCFromNodeDB(const Key_t& k, llarp::RouterContact& rc) const = 0; - - virtual const Key_t& - OurKey() const = 0; - - virtual PendingIntrosetLookups& - pendingIntrosetLookups() = 0; - - virtual const PendingIntrosetLookups& - pendingIntrosetLookups() const = 0; - - virtual PendingRouterLookups& - pendingRouterLookups() = 0; - - virtual const PendingRouterLookups& - pendingRouterLookups() const = 0; - - virtual PendingExploreLookups& - pendingExploreLookups() = 0; - - virtual const PendingExploreLookups& - pendingExploreLookups() const = 0; - - virtual Bucket* - services() = 0; - - virtual bool& - AllowTransit() = 0; - virtual const bool& - AllowTransit() const = 0; - - virtual Bucket* - Nodes() const = 0; - - virtual void - PutRCNodeAsync(const RCNode& val) = 0; - - virtual void - DelRCNodeAsync(const Key_t& val) = 0; - - virtual util::StatusObject - ExtractStatus() const = 0; - - virtual void - StoreRC(const RouterContact rc) const = 0; - - virtual bool - handle_message( - const AbstractDHTMessage&, std::vector>&) = 0; - }; - - std::unique_ptr - make_handler(); - } // namespace dht -} // namespace llarp - -struct llarp_dht_context -{ - std::unique_ptr impl; - llarp::Router* parent; - llarp_dht_context(llarp::Router* router); -}; - -#endif diff --git a/llarp/dht/explorenetworkjob.cpp b/llarp/dht/explorenetworkjob.cpp index e0c7ebc02e..7ce2023f53 100644 --- a/llarp/dht/explorenetworkjob.cpp +++ b/llarp/dht/explorenetworkjob.cpp @@ -19,7 +19,7 @@ namespace llarp auto router = parent->GetRouter(); if (router) { - router->NotifyRouterEvent(router->pubkey(), *msg); + router->notify_router_event(router->pubkey(), *msg); } parent->DHTSendTo(peer.node.as_array(), msg); } diff --git a/llarp/dht/key.hpp b/llarp/dht/key.hpp index a9c815717a..28ef35e3e5 100644 --- a/llarp/dht/key.hpp +++ b/llarp/dht/key.hpp @@ -15,7 +15,7 @@ namespace llarp explicit Key_t(const byte_t* buf) : AlignedBuffer(buf) {} - explicit Key_t(const Data& data) : AlignedBuffer(data) + explicit Key_t(const std::array& data) : AlignedBuffer(data) {} explicit Key_t(const AlignedBuffer& data) : AlignedBuffer(data) diff --git a/llarp/dht/messages/consensus.hpp b/llarp/dht/messages/consensus.hpp deleted file mode 100644 index 986823c2fc..0000000000 --- a/llarp/dht/messages/consensus.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include -#include - -namespace llarp::dht -{ - struct ConsensusMessage - { - /// H - ShortHash m_Hash; - /// K - std::vector m_Keys; - /// N - uint64_t m_NumberOfEntries; - /// O - uint64_t m_EntryOffset; - /// T - uint64_t m_TxID; - /// U - llarp_time_t m_NextUpdateRequired; - /// V - RouterVersion m_RotuerVersion; - }; -} // namespace llarp::dht diff --git a/llarp/dht/messages/findintro.cpp b/llarp/dht/messages/findintro.cpp index 7a3706cfc7..98a7f6ad97 100644 --- a/llarp/dht/messages/findintro.cpp +++ b/llarp/dht/messages/findintro.cpp @@ -84,7 +84,7 @@ namespace llarp::dht // we are relaying this message for e.g. a client if (relayed) { - if (relayOrder >= IntroSetStorageRedundancy) + if (relayOrder >= INTROSET_STORAGE_REDUNDANCY) { llarp::LogWarn("Invalid relayOrder received: ", relayOrder); replies.emplace_back(new GotIntroMessage({}, txID)); diff --git a/llarp/dht/messages/findname.cpp b/llarp/dht/messages/findname.cpp index aefa638630..abab5686a6 100644 --- a/llarp/dht/messages/findname.cpp +++ b/llarp/dht/messages/findname.cpp @@ -44,10 +44,9 @@ namespace llarp::dht bool FindNameMessage::handle_message( - AbstractDHTMessageHandler& dht, - std::vector>& replies) const + AbstractDHTMessageHandler&, std::vector>&) const { - (void)replies; + /* (void)replies; auto router = dht.GetRouter(); if (pathID.IsZero() or not router->IsServiceNode()) return false; @@ -67,7 +66,7 @@ namespace llarp::dht new GotNameMessage(dht::Key_t{}, TxID, service::EncryptedName{})); } path->SendRoutingMessage(msg, router); - }); + }); */ return true; } diff --git a/llarp/dht/messages/gotintro.cpp b/llarp/dht/messages/gotintro.cpp index 9be5a0e5f8..ddc1e2c01e 100644 --- a/llarp/dht/messages/gotintro.cpp +++ b/llarp/dht/messages/gotintro.cpp @@ -30,7 +30,7 @@ namespace llarp::dht for (const auto& introset : found) { - if (!introset.Verify(dht.Now())) + if (!introset.verify(dht.Now())) { LogWarn( "Invalid introset while handling direct GotIntro " diff --git a/llarp/dht/messages/pubintro.cpp b/llarp/dht/messages/pubintro.cpp index 13bb0b6197..f8ed8a079b 100644 --- a/llarp/dht/messages/pubintro.cpp +++ b/llarp/dht/messages/pubintro.cpp @@ -2,7 +2,6 @@ #include #include "gotintro.hpp" -#include #include #include #include @@ -59,10 +58,10 @@ namespace llarp::dht const llarp::dht::Key_t addr{introset.derivedSigningKey.data()}; auto router = dht.GetRouter(); - router->NotifyRouterEvent( + router->notify_router_event( router->pubkey(), Key_t(relayed ? router->pubkey() : From.data()), addr, txID, relayOrder); - if (!introset.Verify(now)) + if (!introset.verify(now)) { llarp::LogWarn("Received PublishIntroMessage with invalid introset: ", introset); // don't propogate or store @@ -80,8 +79,8 @@ namespace llarp::dht // identify closest 4 routers auto closestRCs = - dht.GetRouter()->node_db()->FindManyClosestTo(addr, IntroSetStorageRedundancy); - if (closestRCs.size() != IntroSetStorageRedundancy) + dht.GetRouter()->node_db()->FindManyClosestTo(addr, INTROSET_STORAGE_REDUNDANCY); + if (closestRCs.size() != INTROSET_STORAGE_REDUNDANCY) { llarp::LogWarn("Received PublishIntroMessage but only know ", closestRCs.size(), " nodes"); replies.emplace_back(new GotIntroMessage({}, txID)); @@ -92,7 +91,7 @@ namespace llarp::dht // function to identify the closest 4 routers we know of for this introset auto propagateIfNotUs = [&](size_t index) { - assert(index < IntroSetStorageRedundancy); + assert(index < INTROSET_STORAGE_REDUNDANCY); const auto& rc = closestRCs[index]; const Key_t peer{rc.pubkey}; @@ -120,7 +119,7 @@ namespace llarp::dht if (relayed) { - if (relayOrder >= IntroSetStorageRedundancy) + if (relayOrder >= INTROSET_STORAGE_REDUNDANCY) { llarp::LogWarn("Received PublishIntroMessage with invalid relayOrder: ", relayOrder); replies.emplace_back(new GotIntroMessage({}, txID)); @@ -179,7 +178,7 @@ namespace llarp::dht try { btdp.append("A", "I"); - btdp.append("T", introset.ToString()); + btdp.append("I", introset.ToString()); btdp.append("O", relayOrder); btdp.append("R", relayed ? 1 : 0); btdp.append("T", txID); diff --git a/llarp/dht/publishservicejob.cpp b/llarp/dht/publishservicejob.cpp index 0420688c3c..62011853e4 100644 --- a/llarp/dht/publishservicejob.cpp +++ b/llarp/dht/publishservicejob.cpp @@ -29,7 +29,7 @@ namespace llarp::dht return false; } const llarp_time_t now = llarp::time_now_ms(); - return value.Verify(now); + return value.verify(now); } void diff --git a/llarp/dht/serviceaddresslookup.cpp b/llarp/dht/serviceaddresslookup.cpp index 028465b86b..d769db3e98 100644 --- a/llarp/dht/serviceaddresslookup.cpp +++ b/llarp/dht/serviceaddresslookup.cpp @@ -26,7 +26,7 @@ namespace llarp bool ServiceAddressLookup::Validate(const service::EncryptedIntroSet& value) const { - if (!value.Verify(parent->Now())) + if (!value.verify(parent->Now())) { llarp::LogWarn("Got invalid introset from service lookup"); return false; diff --git a/llarp/dht/taglookup.cpp b/llarp/dht/taglookup.cpp index 85df37e377..5f0aa21f65 100644 --- a/llarp/dht/taglookup.cpp +++ b/llarp/dht/taglookup.cpp @@ -10,7 +10,7 @@ namespace llarp bool TagLookup::Validate(const service::EncryptedIntroSet& introset) const { - if (!introset.Verify(parent->Now())) + if (!introset.verify(parent->Now())) { llarp::LogWarn("got invalid introset from tag lookup"); return false; diff --git a/llarp/exit/exit_messages.cpp b/llarp/exit/exit_messages.cpp index 0385834f37..c51fde2815 100644 --- a/llarp/exit/exit_messages.cpp +++ b/llarp/exit/exit_messages.cpp @@ -8,33 +8,24 @@ namespace llarp::routing bool ObtainExitMessage::Sign(const llarp::SecretKey& sk) { - std::array tmp; - llarp_buffer_t buf(tmp); pubkey = seckey_topublic(sk); sig.Zero(); auto bte = bt_encode(); - buf.write(bte.begin(), bte.end()); - - buf.sz = buf.cur - buf.base; - return CryptoManager::instance()->sign(sig, sk, buf); + return CryptoManager::instance()->sign( + sig, sk, reinterpret_cast(bte.data()), bte.size()); } bool ObtainExitMessage::Verify() const { - std::array tmp; - llarp_buffer_t buf(tmp); ObtainExitMessage copy; copy = *this; copy.sig.Zero(); auto bte = copy.bt_encode(); - buf.write(bte.begin(), bte.end()); - - // rewind buffer - buf.sz = buf.cur - buf.base; - return CryptoManager::instance()->verify(pubkey, buf, sig); + return CryptoManager::instance()->verify( + pubkey, reinterpret_cast(bte.data()), bte.size(), sig); } std::string @@ -150,32 +141,24 @@ namespace llarp::routing bool GrantExitMessage::Verify(const llarp::PubKey& pk) const { - std::array tmp; - llarp_buffer_t buf(tmp); GrantExitMessage copy; copy = *this; copy.sig.Zero(); auto bte = copy.bt_encode(); - buf.write(bte.begin(), bte.end()); - - buf.sz = buf.cur - buf.base; - return CryptoManager::instance()->verify(pk, buf, sig); + return CryptoManager::instance()->verify( + pk, reinterpret_cast(bte.data()), bte.size(), sig); } bool GrantExitMessage::Sign(const llarp::SecretKey& sk) { - std::array tmp; - llarp_buffer_t buf(tmp); sig.Zero(); nonce.Randomize(); auto bte = bt_encode(); - buf.write(bte.begin(), bte.end()); - - buf.sz = buf.cur - buf.base; - return CryptoManager::instance()->sign(sig, sk, buf); + return CryptoManager::instance()->sign( + sig, sk, reinterpret_cast(bte.data()), bte.size()); } bool @@ -239,32 +222,24 @@ namespace llarp::routing bool RejectExitMessage::Sign(const llarp::SecretKey& sk) { - std::array tmp; - llarp_buffer_t buf(tmp); sig.Zero(); nonce.Randomize(); auto bte = bt_encode(); - buf.write(bte.begin(), bte.end()); - - buf.sz = buf.cur - buf.base; - return CryptoManager::instance()->sign(sig, sk, buf); + return CryptoManager::instance()->sign( + sig, sk, reinterpret_cast(bte.data()), bte.size()); } bool RejectExitMessage::Verify(const llarp::PubKey& pk) const { - std::array tmp; - llarp_buffer_t buf(tmp); RejectExitMessage copy; copy = *this; copy.sig.Zero(); auto bte = copy.bt_encode(); - buf.write(bte.begin(), bte.end()); - - buf.sz = buf.cur - buf.base; - return CryptoManager::instance()->verify(pk, buf, sig); + return CryptoManager::instance()->verify( + pk, reinterpret_cast(bte.data()), bte.size(), sig); } bool @@ -314,33 +289,24 @@ namespace llarp::routing bool UpdateExitMessage::Verify(const llarp::PubKey& pk) const - { - std::array tmp; - llarp_buffer_t buf(tmp); UpdateExitMessage copy; copy = *this; copy.sig.Zero(); auto bte = copy.bt_encode(); - buf.write(bte.begin(), bte.end()); - - buf.sz = buf.cur - buf.base; - return CryptoManager::instance()->verify(pk, buf, sig); + return CryptoManager::instance()->verify( + pk, reinterpret_cast(bte.data()), bte.size(), sig); } bool UpdateExitMessage::Sign(const llarp::SecretKey& sk) { - std::array tmp; - llarp_buffer_t buf(tmp); nonce.Randomize(); auto bte = bt_encode(); - buf.write(bte.begin(), bte.end()); - - buf.sz = buf.cur - buf.base; - return CryptoManager::instance()->sign(sig, sk, buf); + return CryptoManager::instance()->sign( + sig, sk, reinterpret_cast(bte.data()), bte.size()); } bool @@ -427,32 +393,24 @@ namespace llarp::routing bool CloseExitMessage::Verify(const llarp::PubKey& pk) const { - std::array tmp; - llarp_buffer_t buf(tmp); CloseExitMessage copy; copy = *this; copy.sig.Zero(); auto bte = copy.bt_encode(); - buf.write(bte.begin(), bte.end()); - - buf.sz = buf.cur - buf.base; - return CryptoManager::instance()->verify(pk, buf, sig); + return CryptoManager::instance()->verify( + pk, reinterpret_cast(bte.data()), bte.size(), sig); } bool CloseExitMessage::Sign(const llarp::SecretKey& sk) { - std::array tmp; - llarp_buffer_t buf(tmp); sig.Zero(); nonce.Randomize(); auto bte = bt_encode(); - buf.write(bte.begin(), bte.end()); - - buf.sz = buf.cur - buf.base; - return CryptoManager::instance()->sign(sig, sk, buf); + return CryptoManager::instance()->sign( + sig, sk, reinterpret_cast(bte.data()), bte.size()); } bool diff --git a/llarp/exit/session.cpp b/llarp/exit/session.cpp index a56b50d38b..4d5a3081e3 100644 --- a/llarp/exit/session.cpp +++ b/llarp/exit/session.cpp @@ -22,7 +22,7 @@ namespace llarp::exit , m_ExitRouter{routerId} , m_WritePacket{std::move(writepkt)} , m_Counter{0} - , m_LastUse{r->Now()} + , m_LastUse{r->now()} , m_BundleRC{false} , m_Parent{parent} { @@ -87,7 +87,7 @@ namespace llarp::exit bool BaseSession::CheckPathDead(path::Path_ptr, llarp_time_t dlt) { - return dlt >= path::alive_timeout; + return dlt >= path::ALIVE_TIMEOUT; } void @@ -214,7 +214,7 @@ namespace llarp::exit llarp::net::IPPacket pkt{buf.view_all()}; if (pkt.empty()) return false; - m_LastUse = m_router->Now(); + m_LastUse = m_router->now(); m_Downstream.emplace(counter, pkt); return true; } @@ -225,7 +225,7 @@ namespace llarp::exit BaseSession::HandleTrafficDrop(llarp::path::Path_ptr p, const PathID_t& path, uint64_t s) { llarp::LogError("dropped traffic on exit ", m_ExitRouter, " S=", s, " P=", path); - p->EnterState(path::ePathIgnore, m_router->Now()); + p->EnterState(path::ePathIgnore, m_router->now()); return true; } @@ -283,7 +283,7 @@ namespace llarp::exit bool BaseSession::FlushUpstream() { - auto now = m_router->Now(); + auto now = m_router->now(); auto path = PickEstablishedPath(llarp::path::ePathRoleExit); if (path) { diff --git a/llarp/exit/session.hpp b/llarp/exit/session.hpp index 6a34be8411..9c556e147f 100644 --- a/llarp/exit/session.hpp +++ b/llarp/exit/session.hpp @@ -27,7 +27,7 @@ namespace llarp using SessionReadyFunc = std::function; - static constexpr auto LifeSpan = path::default_lifetime; + static constexpr auto LifeSpan = path::DEFAULT_LIFETIME; /// a persisting exit session with an exit router struct BaseSession : public llarp::path::Builder, diff --git a/llarp/handlers/exit.cpp b/llarp/handlers/exit.cpp index 018e1d2ec7..02125cdf28 100644 --- a/llarp/handlers/exit.cpp +++ b/llarp/handlers/exit.cpp @@ -354,7 +354,7 @@ namespace llarp::handlers llarp_time_t ExitEndpoint::Now() const { - return router->Now(); + return router->now(); } bool @@ -650,7 +650,7 @@ namespace llarp::handlers void ExitEndpoint::MarkIPActive(huint128_t ip) { - ip_activity[ip] = GetRouter()->Now(); + ip_activity[ip] = GetRouter()->now(); } void diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index a9ea3010bf..cc43ed0862 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -279,18 +279,18 @@ namespace llarp { if (conf.m_reachable) { - m_PublishIntroSet = true; + _publish_introset = true; LogInfo(Name(), " setting to be reachable by default"); } else { - m_PublishIntroSet = false; + _publish_introset = false; LogInfo(Name(), " setting to be not reachable by default"); } if (conf.m_AuthType == service::AuthType::eAuthTypeFile) { - m_AuthPolicy = service::MakeFileAuthPolicy(m_router, conf.m_AuthFiles, conf.m_AuthFileType); + _auth_policy = service::MakeFileAuthPolicy(m_router, conf.m_AuthFiles, conf.m_AuthFileType); } else if (conf.m_AuthType != service::AuthType::eAuthTypeNone) { @@ -308,7 +308,7 @@ namespace llarp router()->lmq(), shared_from_this()); auth->Start(); - m_AuthPolicy = std::move(auth); + _auth_policy = std::move(auth); } m_DnsConfig = dnsConf; @@ -656,7 +656,7 @@ namespace llarp if (HasExit()) { std::string s; - m_ExitMap.ForEachEntry([&s](const auto& range, const auto& exit) { + _exit_map.ForEachEntry([&s](const auto& range, const auto& exit) { fmt::format_to(std::back_inserter(s), "{}={}; ", range, exit); }); msg.AddTXTReply(std::move(s)); @@ -727,7 +727,7 @@ namespace llarp const auto subdomain = msg.questions[0].Subdomains(); if (subdomain == "exit" and HasExit()) { - m_ExitMap.ForEachEntry( + _exit_map.ForEachEntry( [&msg](const auto&, const auto& exit) { msg.AddCNAMEReply(exit.ToString(), 1); }); } else @@ -783,7 +783,7 @@ namespace llarp { if (HasExit()) { - m_ExitMap.ForEachEntry( + _exit_map.ForEachEntry( [&msg](const auto&, const auto& exit) { msg.AddCNAMEReply(exit.ToString()); }); msg.AddINReply(ip, isV6); } @@ -794,7 +794,7 @@ namespace llarp } else { - msg.AddCNAMEReply(m_Identity.pub.Name(), 1); + msg.AddCNAMEReply(_identity.pub.Name(), 1); msg.AddINReply(ip, isV6); } } @@ -999,7 +999,7 @@ namespace llarp llarp::LogInfo(Name(), " set ", m_IfName, " to have address ", m_OurIP); llarp::LogInfo(Name(), " allocated up to ", m_MaxIP, " on range ", m_OurRange); - const service::Address ourAddr = m_Identity.pub.Addr(); + const service::Address ourAddr = _identity.pub.Addr(); if (not MapAddress(ourAddr, GetIfAddr(), false)) { @@ -1138,7 +1138,7 @@ namespace llarp // build up our candidates to choose std::unordered_set candidates; - for (const auto& entry : m_ExitMap.FindAllEntries(ip)) + for (const auto& entry : _exit_map.FindAllEntries(ip)) { // in the event the exit's range is a bogon range, make sure the ip is located in that range // to allow it @@ -1186,7 +1186,7 @@ namespace llarp } } - if (m_state->m_ExitEnabled) + if (_state->m_ExitEnabled) { dst = net::ExpandV4(net::TruncateV6(dst)); } @@ -1238,8 +1238,8 @@ namespace llarp else { to = service::Address{itr->second.as_array()}; - type = m_state->m_ExitEnabled and src != m_OurIP ? service::ProtocolType::Exit - : pkt.ServiceProtocol(); + type = _state->m_ExitEnabled and src != m_OurIP ? service::ProtocolType::Exit + : pkt.ServiceProtocol(); } // prepare packet for insertion into network @@ -1347,7 +1347,7 @@ namespace llarp if (not pkt.Load(buf)) return false; - if (m_state->m_ExitEnabled) + if (_state->m_ExitEnabled) { // exit side from exit diff --git a/llarp/link/link_endpoints.cpp b/llarp/link/link_endpoints.cpp new file mode 100644 index 0000000000..a8625dda0a --- /dev/null +++ b/llarp/link/link_endpoints.cpp @@ -0,0 +1,4 @@ +#include "link_endpoints.hpp" + +namespace llarp +{} // namespace llarp diff --git a/llarp/link/link_endpoints.hpp b/llarp/link/link_endpoints.hpp new file mode 100644 index 0000000000..3796e3b94b --- /dev/null +++ b/llarp/link/link_endpoints.hpp @@ -0,0 +1,4 @@ +#pragma once + +namespace llarp +{} // namespace llarp diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 43c633923e..a8239d356e 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -127,6 +127,19 @@ namespace llarp return ep.for_each_connection(func); } + void + LinkManager::register_commands(std::shared_ptr& s) + { + for (const auto& [name, func] : rpc_commands) + { + s->register_command(name, [this, f = func](oxen::quic::message m) { + router.loop()->call([this, func = f, msg = std::move(m)]() mutable { + std::invoke(func, this, std::move(msg)); + }); + }); + } + } + std::shared_ptr LinkManager::startup_endpoint() { @@ -136,7 +149,6 @@ namespace llarp - connection close callback - stream constructor callback - will return a BTRequestStream on the first call to get_new_stream - */ return quic->endpoint( router.public_ip(), @@ -150,8 +162,9 @@ namespace llarp std::optional id) -> std::shared_ptr { if (id && id == 0) { - return std::make_shared( - c, e, [this](oxen::quic::message msg) { return recv_control_message(msg); }); + auto s = std::make_shared(); + register_commands(s); + return s; } return std::make_shared(c, e); }); @@ -168,20 +181,22 @@ namespace llarp bool LinkManager::send_control_message( - const RouterID& remote, std::string endpoint, std::string body, bool is_request) + const RouterID& remote, + std::string endpoint, + std::string body, + std::function func) { if (is_stopping) return false; if (auto conn = ep.get_conn(remote); conn) { - (is_request) ? conn->control_stream->request(endpoint, body) - : conn->control_stream->command(endpoint, body); + conn->control_stream->command(endpoint, body, std::move(func)); return true; } router.loop()->call([&]() { - auto pending = PendingControlMessage(body, endpoint); + auto pending = PendingControlMessage(body, endpoint, func); auto [itr, b] = pending_conn_msg_queue.emplace(remote, MessageQueue()); itr->second.push_back(std::move(pending)); @@ -304,8 +319,7 @@ namespace llarp if (m.is_control) { auto& msg = reinterpret_cast(m); - msg.is_request ? ep.conns[rid]->control_stream->request(msg.endpoint, msg.body) - : ep.conns[rid]->control_stream->command(msg.endpoint, msg.body); + ep.conns[rid]->control_stream->command(msg.endpoint, msg.body, msg.func); } else { @@ -476,44 +490,204 @@ namespace llarp } void - LinkManager::recv_control_message(oxen::quic::message msg) + LinkManager::handle_find_name(oxen::quic::message m) + { + try + { + oxenc::bt_dict_consumer btdp{m.body()}; + std::string name_hash, tx_id; + + if (btdp.skip_until("H")) + name_hash = btdp.consume_string(); + + if (btdp.skip_until("T")) + tx_id = btdp.consume_string(); + + router.rpc_client()->LookupLNSNameHash(name_hash, [](auto /* maybe */) { + + }); + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + m.respond("ERROR", true); + } + } + + void + LinkManager::handle_find_router(oxen::quic::message) + {} + + void + LinkManager::handle_publish_intro(oxen::quic::message m) { - // if the message is not expired, it will pass this conditional - if (msg) + std::string introset, tx_id, derived_signing_key, sig; + uint64_t is_relayed, relay_order; + std::chrono::milliseconds signed_at; + + try { - std::string ep{msg.endpoint()}, body{msg.body()}; - bool is_request = (msg.type() == "Q"sv) ? true : false; + oxenc::bt_dict_consumer btdc_a{m.body()}; + + if (btdc_a.skip_until("I")) + introset = btdc_a.consume_string(); + + if (btdc_a.skip_until("O")) + relay_order = btdc_a.consume_integer(); - if (auto itr = rpc_map.find(ep); itr != rpc_map.end()) + if (btdc_a.skip_until("R")) + is_relayed = btdc_a.consume_integer(); + + if (btdc_a.skip_until("T")) + tx_id = btdc_a.consume_string(); + + oxenc::bt_dict_consumer btdc_b{introset}; + + if (btdc_b.skip_until("d")) + derived_signing_key = btdc_b.consume_string(); + + if (btdc_b.skip_until("s")) + signed_at = std::chrono::milliseconds{btdc_b.consume_integer()}; + + if (btdc_b.skip_until("z")) + sig = btdc_b.consume_string(); + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + m.respond("ERROR", true); + return; + } + + const auto now = router.now(); + const auto addr = dht::Key_t{reinterpret_cast(derived_signing_key.data())}; + const auto local_key = router.rc().pubkey; + + if (not service::EncryptedIntroSet::verify(introset, derived_signing_key, sig)) + { + log::error(link_cat, "Received PublishIntroMessage with invalid introset: {}", introset); + m.respond("INVALID INTROSET", true); + return; + } + + if (now + service::MAX_INTROSET_TIME_DELTA > signed_at + path::DEFAULT_LIFETIME) + { + log::error(link_cat, "Received PublishIntroMessage with expired introset: {}", introset); + m.respond("EXPIRED INTROSET", true); + return; + } + + auto closest_rcs = router.node_db()->FindManyClosestTo(addr, INTROSET_STORAGE_REDUNDANCY); + + if (closest_rcs.size() != INTROSET_STORAGE_REDUNDANCY) + { + log::error( + link_cat, "Received PublishIntroMessage but only know {} nodes", closest_rcs.size()); + m.respond("INSUFFICIENT NODES", true); + return; + } + + if (is_relayed) + { + if (relay_order >= INTROSET_STORAGE_REDUNDANCY) { - router.loop()->call([&]() { - // execute mapped callback - auto maybe_response = itr->second(body); + log::error( + link_cat, "Received PublishIntroMessage with invalide relay order: {}", relay_order); + m.respond("INVALID ORDER", true); + return; + } - if (is_request) - { - if (maybe_response) - { - // respond here - msg.respond(msg.rid(), *maybe_response); - } - - // TODO: revisit the logic of these conditionals after defining the callback functions - // to see if returning/taking optionals makes sense - } - }); + log::info(link_cat, "Relaying PublishIntroMessage for {} (TXID: {})", addr, tx_id); + + const auto& peer_rc = closest_rcs[relay_order]; + const auto& peer_key = peer_rc.pubkey; + + if (peer_key == local_key) + { + log::info( + link_cat, + "Received PublishIntroMessage in which we are peer index {}.. storing introset", + relay_order); + + // TODO: replace this concept + // dht->services()->PutNode(introset); + + // TODO: should this be a call to send_control_message instead? + m.respond("got_intro"); } else { - msg.respond(msg.rid(), "INVALID REQUEST", true); - return; + log::info( + link_cat, "Received PublishIntroMessage; propagating to peer index {}", relay_order); + + send_control_message( + peer_key, "publish_intro", std::move(introset), [this](oxen::quic::message m) { + return handle_got_intro(std::move(m)); + }); } + + return; } - else + + int rc_index = -1, index = 0; + + for (const auto& rc : closest_rcs) + { + if (rc.pubkey == local_key) + { + rc_index = index; + break; + } + ++index; + } + + if (rc_index >= 0) { - // RPC request was sent out but we received no response - log::info(link_cat, "RPC request (RID: {}) timed out", msg.rid()); + log::info(link_cat, "Received PublishIntroMessage for {} (TXID: {}); we are candidate {}"); + + // TODO: should this be a call to send_control_message instead? + m.respond("got_intro"); } + else + log::warning( + link_cat, + "Received non-relayed PublishIntroMessage from {}; we are not the candidate", + addr); } + void + LinkManager::handle_find_intro(oxen::quic::message) + {} + + void + LinkManager::handle_path_confirm(oxen::quic::message) + {} + + void + LinkManager::handle_path_latency(oxen::quic::message) + {} + + void + LinkManager::handle_update_exit(oxen::quic::message) + {} + + void + LinkManager::handle_obtain_exit(oxen::quic::message) + {} + + void + LinkManager::handle_close_exit(oxen::quic::message) + {} + + void + LinkManager::handle_got_intro(oxen::quic::message) + {} + + void + LinkManager::handle_got_name(oxen::quic::message) + {} + + void + LinkManager::handle_got_router(oxen::quic::message) + {} } // namespace llarp diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 57c7f93fc0..43dca97616 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -1,6 +1,7 @@ #pragma once #include "connection.hpp" +#include "link_endpoints.hpp" #include #include @@ -122,10 +123,11 @@ namespace llarp struct PendingControlMessage : PendingMessage { std::string endpoint; - bool is_request{false}; // true if request, false if command + std::function func; - PendingControlMessage(std::string b, std::string e, bool request = true) - : PendingMessage(b, true), endpoint{std::move(e)}, is_request{request} + PendingControlMessage( + std::string b, std::string e, std::function f = nullptr) + : PendingMessage(b, true), endpoint{std::move(e)}, func{std::move(f)} {} }; @@ -141,7 +143,10 @@ namespace llarp // set is_request to true for RPC requests, false for RPC commands bool send_control_message( - const RouterID& remote, std::string endpoint, std::string body, bool is_request = true); + const RouterID& remote, + std::string endpoint, + std::string body, + std::function = nullptr); bool send_data_message(const RouterID& remote, std::string data); @@ -149,18 +154,6 @@ namespace llarp private: friend struct link::Endpoint; - const std::unordered_map< - std::string, - std::function(std::optional)>> - rpc_map{ - /** TODO: - key: RPC endpoint name - value: function that takes command body as parameter - - returns: commands will return std::nullopt while requests will return a response - */ - }; - std::atomic is_stopping; // DISCUSS: is this necessary? can we reduce the amount of locking and nuke this mutable util::Mutex m; // protects persisting_conns @@ -171,7 +164,7 @@ namespace llarp // holds any messages we attempt to send while connections are establishing std::unordered_map pending_conn_msg_queue; - util::DecayingHashSet clients{path::default_lifetime}; + util::DecayingHashSet clients{path::DEFAULT_LIFETIME}; RCLookupHandler* rc_lookup; std::shared_ptr node_db; @@ -202,6 +195,9 @@ namespace llarp std::shared_ptr startup_endpoint(); + void + register_commands(std::shared_ptr& s); + public: const link::Endpoint& endpoint() @@ -276,6 +272,40 @@ namespace llarp size_t min_connected_routers = 4; /// hard upperbound limit on the number of router to router connections size_t max_connected_routers = 6; + + private: + // Control message + + // Bridge (relay) message + void handle_publish_intro(oxen::quic::message); + void handle_find_intro(oxen::quic::message); + void handle_find_name(oxen::quic::message); + void handle_path_confirm(oxen::quic::message); + void handle_path_latency(oxen::quic::message); + void handle_update_exit(oxen::quic::message); + void handle_obtain_exit(oxen::quic::message); + void handle_close_exit(oxen::quic::message); + + // Control and bridge message (separate into two type) + + // Unsure + void handle_find_router(oxen::quic::message); // maybe both + + std::unordered_map rpc_commands = { + {"find_name", &LinkManager::handle_find_name}, + {"find_router", &LinkManager::handle_find_router}, + {"publish_intro", &LinkManager::handle_publish_intro}, + {"find_intro", &LinkManager::handle_find_intro}, + {"path_confirm", &LinkManager::handle_path_confirm}, + {"path_latency", &LinkManager::handle_path_latency}, + {"update_exit", &LinkManager::handle_update_exit}, + {"obtain_exit", &LinkManager::handle_obtain_exit}, + {"close_exit", &LinkManager::handle_close_exit}}; + + // response handling functions + void handle_got_intro(oxen::quic::message); + void handle_got_name(oxen::quic::message); + void handle_got_router(oxen::quic::message); }; namespace link @@ -335,4 +365,23 @@ namespace llarp - if connection times out, flush queue - TOCHECK: is priority used at all?? + +std::unordered_map +rpc_commands = { + {"find_name", &handle_find_name}, + {"find_router", &handle_find_router}, + // ... +}; + +for (const auto& [name, mfn] : rpc_commands) + bparser.add_command(name, [this, mfn] (oxen::quic::message m) { + router->call([this, mfn, m=std::move(m)] mutable { + try { + std::invoke(mfn, this, std::move(m)); + } catch (const std::exception& e) { + m.respond("Error: "s + e.what(), true); + } + }); + }); + */ diff --git a/llarp/messages/dht_immediate.cpp b/llarp/messages/dht_immediate.cpp deleted file mode 100644 index 88c7bd104f..0000000000 --- a/llarp/messages/dht_immediate.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include "dht_immediate.hpp" - -#include -#include - -namespace llarp -{ - void - DHTImmediateMessage::clear() - { - msgs.clear(); - version = 0; - } - - /** Note: this is where AbstractDHTMessage::bt_encode() is called. Contextually, this is a - bit confusing as it is within the ::bt_encode() method of DHTImmediateMessage, which is - not an AbstractDHTMessage, but an AbstractLinkMessage. To see why AbstractLinkMessage - overrides the ::bt_encode() that returns an std::string, see the comment in llarp/router/ - outbound_message_handler.cpp above OutboundMessageHandler::EncodeBuffer(...). - - In this context, there is already a bt_dict_producer being used by DHTImmediateMessage's - bt_encode() method. This allows us to easily choose the override of bt_encode() that returns - nothing, but takes a bt_dict_producer as a reference. - */ - std::string - DHTImmediateMessage::bt_encode() const - { - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("a", "m"); - { - auto subdict = btdp.append_dict("m"); - for (auto& m : msgs) - m->bt_encode(subdict); - } - - btdp.append("v", llarp::constants::proto_version); - } - catch (...) - { - log::critical(link_cat, "Error: DHTImmediateMessage failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - - bool - DHTImmediateMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) - { - if (key.startswith("m")) - return llarp::dht::DecodeMessageList(dht::Key_t(conn->remote_rc.pubkey), buf, msgs); - if (key.startswith("v")) - { - if (!bencode_read_integer(buf, &version)) - return false; - return version == llarp::constants::proto_version; - } - // bad key - return false; - } - - bool - DHTImmediateMessage::handle_message(Router* router) const - { - DHTImmediateMessage reply; - reply.conn = conn; - bool result = true; - auto dht = router->dht(); - for (const auto& msg : msgs) - { - result &= dht->handle_message(*msg, reply.msgs); - } - if (reply.msgs.size()) - { - if (result) - { - result = router->SendToOrQueue(conn->remote_rc.pubkey, reply); - } - } - return true; - } -} // namespace llarp diff --git a/llarp/messages/dht_immediate.hpp b/llarp/messages/dht_immediate.hpp deleted file mode 100644 index 905fed8c47..0000000000 --- a/llarp/messages/dht_immediate.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include -#include "link_message.hpp" - -#include - -namespace llarp -{ - struct DHTImmediateMessage final : public AbstractLinkMessage - { - DHTImmediateMessage() = default; - ~DHTImmediateMessage() override = default; - - std::vector> msgs; - - std::string - bt_encode() const override; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; - - bool - handle_message(Router* router) const override; - - void - clear() override; - - const char* - name() const override - { - return "DHTImmediate"; - } - }; -} // namespace llarp diff --git a/llarp/messages/link_intro.cpp b/llarp/messages/link_intro.cpp index ef84653827..0966f75eb3 100644 --- a/llarp/messages/link_intro.cpp +++ b/llarp/messages/link_intro.cpp @@ -145,7 +145,8 @@ namespace llarp buf.cur = buf.base; // outer signature - if (!CryptoManager::instance()->verify(rc.pubkey, buf, sig)) + if (!CryptoManager::instance()->verify( + rc.pubkey, reinterpret_cast(bte.data()), bte.size(), sig)) { log::error(link_cat, "Error: outer signature failed!"); return false; diff --git a/llarp/messages/relay_commit.cpp b/llarp/messages/relay_commit.cpp index c37f5bdbe5..955ee0a7a8 100644 --- a/llarp/messages/relay_commit.cpp +++ b/llarp/messages/relay_commit.cpp @@ -70,9 +70,9 @@ namespace llarp bool LR_CommitMessage::handle_message(Router* router) const { - if (frames.size() != path::max_len) + if (frames.size() != path::MAX_LEN) { - llarp::LogError("LRCM invalid number of records, ", frames.size(), "!=", path::max_len); + llarp::LogError("LRCM invalid number of records, ", frames.size(), "!=", path::MAX_LEN); return false; } if (!router->path_context().AllowingTransit()) @@ -93,7 +93,7 @@ namespace llarp return false; if (!BEncodeWriteDictEntry("i", nextHop, buf)) return false; - if (lifetime > 10s && lifetime < path::default_lifetime) + if (lifetime > 10s && lifetime < path::DEFAULT_LIFETIME) { if (!BEncodeWriteDictInt("i", lifetime.count(), buf)) return false; @@ -370,7 +370,7 @@ namespace llarp static void HandleDecrypted(llarp_buffer_t* buf, std::shared_ptr self) { - auto now = self->context->router()->Now(); + auto now = self->context->router()->now(); auto& info = self->hop->info; if (!buf) { @@ -423,7 +423,7 @@ namespace llarp info); self->hop->lifetime += self->record.work->extendedLifetime; } - else if (self->record.lifetime < path::default_lifetime && self->record.lifetime > 10s) + else if (self->record.lifetime < path::DEFAULT_LIFETIME && self->record.lifetime > 10s) { self->hop->lifetime = self->record.lifetime; llarp::LogDebug( diff --git a/llarp/messages/relay_status.cpp b/llarp/messages/relay_status.cpp index 6fce7f32e7..2fa717baf6 100644 --- a/llarp/messages/relay_status.cpp +++ b/llarp/messages/relay_status.cpp @@ -129,9 +129,9 @@ namespace llarp LR_StatusMessage::handle_message(Router* router) const { llarp::LogDebug("Received LR_Status message from (", conn->remote_rc.pubkey, ")"); - if (frames.size() != path::max_len) + if (frames.size() != path::MAX_LEN) { - llarp::LogError("LRSM invalid number of records, ", frames.size(), "!=", path::max_len); + llarp::LogError("LRSM invalid number of records, ", frames.size(), "!=", path::MAX_LEN); return false; } diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 9fb03de468..2d57d5d2e1 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -272,7 +272,7 @@ namespace llarp::path if (failedAt) edge = *failedAt; r->loop()->call([r, self = shared_from_this(), edge]() { - self->EnterState(ePathFailed, r->Now()); + self->EnterState(ePathFailed, r->now()); if (auto parent = self->m_PathSet.lock()) { parent->HandlePathBuildFailedAt(self, edge); @@ -412,7 +412,7 @@ namespace llarp::path bool Path::SendLatencyMessage(Router* r) { - const auto now = r->Now(); + const auto now = r->now(); // send path latency test routing::PathLatencyMessage latency{}; latency.sent_time = randint(); @@ -445,7 +445,7 @@ namespace llarp::path if (now >= buildStarted) { const auto dlt = now - buildStarted; - if (dlt >= path::build_timeout) + if (dlt >= path::BUILD_TIMEOUT) { LogWarn(Name(), " waited for ", ToString(dlt), " and no path was built"); r->router_profiling().MarkPathFail(this); @@ -458,7 +458,7 @@ namespace llarp::path if (_status == ePathEstablished) { auto dlt = now - m_LastLatencyTestTime; - if (dlt > path::latency_interval && m_LastLatencyTestID == 0) + if (dlt > path::LATENCY_INTERVAL && m_LastLatencyTestID == 0) { SendLatencyMessage(r); // latency test FEC @@ -469,14 +469,14 @@ namespace llarp::path return; } dlt = now - m_LastRecvMessage; - if (dlt >= path::alive_timeout) + if (dlt >= path::ALIVE_TIMEOUT) { LogWarn(Name(), " waited for ", ToString(dlt), " and path looks dead"); r->router_profiling().MarkPathFail(this); EnterState(ePathTimeout, now); } } - if (_status == ePathIgnore and now - m_LastRecvMessage >= path::alive_timeout) + if (_status == ePathIgnore and now - m_LastRecvMessage >= path::ALIVE_TIMEOUT) { // clean up this path as we dont use it anymore EnterState(ePathExpired, now); @@ -507,15 +507,18 @@ namespace llarp::path size_t idx = 0; for (auto& ev : msgs) { - const llarp_buffer_t buf(ev.first); TunnelNonce n = ev.second; + + uint8_t* buf = ev.first.data(); + size_t sz = ev.first.size(); + for (const auto& hop : hops) { - CryptoManager::instance()->xchacha20(buf, hop.shared, n); + CryptoManager::instance()->xchacha20(buf, sz, hop.shared, n); n ^= hop.nonceXOR; } auto& msg = sendmsgs[idx]; - msg.enc = buf; + std::memcpy(msg.enc.data(), buf, sz); msg.nonce = ev.second; msg.pathid = TXID(); ++idx; @@ -581,14 +584,18 @@ namespace llarp::path size_t idx = 0; for (auto& ev : msgs) { - const llarp_buffer_t buf(ev.first); sendMsgs[idx].nonce = ev.second; + + uint8_t* buf = ev.first.data(); + size_t sz = ev.first.size(); + for (const auto& hop : hops) { sendMsgs[idx].nonce ^= hop.nonceXOR; - CryptoManager::instance()->xchacha20(buf, hop.shared, sendMsgs[idx].nonce); + CryptoManager::instance()->xchacha20(buf, sz, hop.shared, sendMsgs[idx].nonce); } - sendMsgs[idx].enc = buf; + + std::memcpy(sendMsgs[idx].enc.data(), buf, sz); ++idx; } r->loop()->call([self = shared_from_this(), msgs = std::move(sendMsgs), r]() mutable { @@ -606,7 +613,7 @@ namespace llarp::path if (HandleRoutingMessage(buf, r)) { r->TriggerPump(); - m_LastRecvMessage = r->Now(); + m_LastRecvMessage = r->now(); } } } @@ -672,11 +679,11 @@ namespace llarp::path N.Randomize(); buf.sz = buf.cur - buf.base; // pad smaller messages - if (buf.sz < pad_size) + if (buf.sz < PAD_SIZE) { // randomize padding - CryptoManager::instance()->randbytes(buf.cur, pad_size - buf.sz); - buf.sz = pad_size; + CryptoManager::instance()->randbytes(buf.cur, PAD_SIZE - buf.sz); + buf.sz = PAD_SIZE; } buf.cur = buf.base; LogDebug( @@ -699,7 +706,7 @@ namespace llarp::path bool Path::HandleDataDiscardMessage(const routing::DataDiscardMessage& msg, Router* r) { - MarkActive(r->Now()); + MarkActive(r->now()); if (m_DropHandler) return m_DropHandler(shared_from_this(), msg.path_id, msg.sequence_number); return true; @@ -760,7 +767,7 @@ namespace llarp::path bool Path::HandlePathLatencyMessage(const routing::PathLatencyMessage&, Router* r) { - const auto now = r->Now(); + const auto now = r->now(); MarkActive(now); if (m_LastLatencyTestID) { @@ -784,7 +791,7 @@ namespace llarp::path bool Path::HandleDHTMessage(const dht::AbstractDHTMessage& msg, Router* r) { - MarkActive(r->Now()); + MarkActive(r->now()); routing::PathDHTMessage reply; if (not r->dht()->handle_message(msg, reply.dht_msgs)) return false; @@ -859,7 +866,7 @@ namespace llarp::path return false; } LogInfo(Name(), " ", Endpoint(), " Rejected exit"); - MarkActive(r->Now()); + MarkActive(r->now()); return InformExitResult(llarp_time_t(msg.backoff_time)); } LogError(Name(), " got unwarranted RXM"); @@ -879,7 +886,7 @@ namespace llarp::path // we now can send exit traffic _role |= ePathRoleExit; LogInfo(Name(), " ", Endpoint(), " Granted exit"); - MarkActive(r->Now()); + MarkActive(r->now()); return InformExitResult(0s); } LogError(Name(), " got unwarranted GXM"); @@ -916,8 +923,8 @@ namespace llarp::path if (m_ExitTrafficHandler( self, llarp_buffer_t(pkt.data() + 8, pkt.size() - 8), counter, msg.protocol)) { - MarkActive(r->Now()); - EnterState(ePathEstablished, r->Now()); + MarkActive(r->now()); + EnterState(ePathEstablished, r->now()); } } return sent; diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 155ce748e5..c84e4685ee 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -55,7 +55,7 @@ namespace llarp /// nonce for key exchange TunnelNonce nonce; // lifetime - llarp_time_t lifetime = default_lifetime; + llarp_time_t lifetime = DEFAULT_LIFETIME; util::StatusObject ExtractStatus() const; diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index eb58efc166..5b791c8a83 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -73,7 +73,7 @@ namespace llarp record.nextRC = std::make_unique(path->hops[idx].rc); } // build record - record.lifetime = path::default_lifetime; + record.lifetime = path::DEFAULT_LIFETIME; record.version = llarp::constants::proto_version; record.txid = hop.txID; record.rxid = hop.rxID; @@ -125,7 +125,7 @@ namespace llarp result = func; work = worker; - for (size_t i = 0; i < path::max_len; ++i) + for (size_t i = 0; i < path::MAX_LEN; ++i) { LRCM.frames[i].Randomize(); } @@ -148,7 +148,7 @@ namespace llarp auto sentHandler = [router = ctx->router, path = ctx->path](auto status) { if (status != SendStatus::Success) { - path->EnterState(path::ePathFailed, router->Now()); + path->EnterState(path::ePathFailed, router->now()); } }; if (ctx->router->SendToOrQueue(remote, ctx->LRCM, sentHandler)) @@ -237,28 +237,23 @@ namespace llarp Builder::SelectFirstHop(const std::set& exclude) const { std::optional found = std::nullopt; - m_router->ForEachPeer( - [&](const AbstractLinkSession* s, bool isOutbound) { - if (s && s->IsEstablished() && isOutbound && not found.has_value()) - { - const RouterContact rc = s->GetRemoteRC(); + m_router->for_each_connection([&](link::Connection& conn) { + const auto& rc = conn.remote_rc; #ifndef TESTNET - if (m_router->IsBootstrapNode(rc.pubkey)) - return; + if (m_router->IsBootstrapNode(rc.pubkey)) + return; #endif - if (exclude.count(rc.pubkey)) - return; + if (exclude.count(rc.pubkey)) + return; - if (BuildCooldownHit(rc.pubkey)) - return; + if (BuildCooldownHit(rc.pubkey)) + return; - if (m_router->router_profiling().IsBadForPath(rc.pubkey)) - return; + if (m_router->router_profiling().IsBadForPath(rc.pubkey)) + return; - found = rc; - } - }, - true); + found = rc; + }); return found; } @@ -422,7 +417,7 @@ namespace llarp llarp_time_t Builder::Now() const { - return m_router->Now(); + return m_router->now(); } void diff --git a/llarp/path/pathset.hpp b/llarp/path/pathset.hpp index 7bd70048bd..456276c498 100644 --- a/llarp/path/pathset.hpp +++ b/llarp/path/pathset.hpp @@ -269,7 +269,7 @@ namespace llarp std::function filter) const; virtual bool - PublishIntroSet(const service::EncryptedIntroSet&, Router*) + PublishIntroSet(const service::EncryptedIntroSet&) { return false; } diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index 1d8da5ef3e..513f347a40 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -28,8 +28,8 @@ namespace llarp::path TransitHop::TransitHop() : AbstractHopHandler{} - , m_UpstreamGather{transit_hop_queue_size} - , m_DownstreamGather{transit_hop_queue_size} + , m_UpstreamGather{TRANSIT_HOP_QUEUE_SIZE} + , m_DownstreamGather{TRANSIT_HOP_QUEUE_SIZE} { m_UpstreamGather.enable(); m_DownstreamGather.enable(); @@ -100,10 +100,10 @@ namespace llarp::path N.Randomize(); buf.sz = buf.cur - buf.base; // pad to nearest MESSAGE_PAD_SIZE bytes - auto dlt = buf.sz % pad_size; + auto dlt = buf.sz % PAD_SIZE; if (dlt) { - dlt = pad_size - dlt; + dlt = PAD_SIZE - dlt; // randomize padding CryptoManager::instance()->randbytes(buf.cur, dlt); buf.sz += dlt; @@ -126,11 +126,17 @@ namespace llarp::path for (auto& ev : msgs) { RelayDownstreamMessage msg; - const llarp_buffer_t buf(ev.first); + + // const llarp_buffer_t buf(ev.first); + uint8_t* buf = ev.first.data(); + size_t sz = ev.first.size(); + msg.pathid = info.rxID; msg.nonce = ev.second ^ nonceXOR; - CryptoManager::instance()->xchacha20(buf, pathKey, ev.second); - msg.enc = buf; + + CryptoManager::instance()->xchacha20(buf, sz, pathKey, ev.second); + std::memcpy(msg.enc.data(), buf, sz); + llarp::LogDebug( "relay ", msg.enc.size(), @@ -153,12 +159,17 @@ namespace llarp::path { for (auto& ev : msgs) { - const llarp_buffer_t buf(ev.first); RelayUpstreamMessage msg; - CryptoManager::instance()->xchacha20(buf, pathKey, ev.second); + + uint8_t* buf = ev.first.data(); + size_t sz = ev.first.size(); + + CryptoManager::instance()->xchacha20(buf, sz, pathKey, ev.second); + msg.pathid = info.txID; msg.nonce = ev.second ^ nonceXOR; - msg.enc = buf; + std::memcpy(msg.enc.data(), buf, sz); + if (m_UpstreamGather.tryPushBack(msg) != thread::QueueReturn::Success) break; } @@ -186,7 +197,7 @@ namespace llarp::path { LogWarn("invalid upstream data on endpoint ", info); } - m_LastActivity = r->Now(); + m_LastActivity = r->now(); } FlushDownstream(r); for (const auto& other : m_FlushOthers) diff --git a/llarp/path/transit_hop.hpp b/llarp/path/transit_hop.hpp index d4cac25ea2..5b04ef5c98 100644 --- a/llarp/path/transit_hop.hpp +++ b/llarp/path/transit_hop.hpp @@ -63,7 +63,7 @@ namespace llarp ShortHash nonceXOR; llarp_time_t started = 0s; // 10 minutes default - llarp_time_t lifetime = default_lifetime; + llarp_time_t lifetime = DEFAULT_LIFETIME; llarp_proto_version_t version; llarp_time_t m_LastActivity = 0s; diff --git a/llarp/peerstats/peer_db.cpp b/llarp/peerstats/peer_db.cpp index d3b93b75b5..e14fca2c64 100644 --- a/llarp/peerstats/peer_db.cpp +++ b/llarp/peerstats/peer_db.cpp @@ -365,3 +365,16 @@ namespace llarp #endif }; // namespace llarp + +/* + - How does a SN/quorum of SN determine if an operator is acting in good faith on the network + - w/o the other operator knowing + - Observing and gathering data in a meaningful way + + - What type of stats could you even collect off lokinet? + - Collecting network-wide data can't be automatically actioned unless the SN is collecting + + - Redundancy model + - Don't rely on an individual, but a collection of them + +*/ diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 8057caa3a7..878c3b651a 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -54,7 +54,7 @@ namespace llarp , _exit_context{this} , _dht{dht::make_handler()} , _disk_thread{_lmq->add_tagged_thread("disk")} - , m_RPCServer{nullptr} + , _rpc_server{nullptr} , _randomStartDelay{platform::is_simulation ? std::chrono::milliseconds{(llarp::randint() % 1250) + 2000} : 0s} , _hidden_service_context{this} { @@ -280,15 +280,15 @@ namespace llarp } bool - Router::send_data_message(const RouterID &remote, const AbstractDataMessage &msg) + Router::send_data_message(const RouterID& remote, const AbstractDataMessage& msg) { - return _link_manager.send_data_message(remote, msg.bt_encode()); + return _link_manager.send_or_queue_data(remote, msg.bt_encode()); } bool - Router::send_control_message(const RouterID &remote, const AbstractLinkMessage &msg) + Router::send_control_message(const RouterID& remote, const AbstractLinkMessage& msg) { - + return _link_manager.send_or_queue_data(remote, msg.bt_encode()); } void @@ -300,7 +300,7 @@ namespace llarp LogError("failure to decode or verify of remote RC"); return; } - if (remote.Verify(Now())) + if (remote.Verify(now())) { LogDebug("verified signature"); _link_manager.connect_to(remote); @@ -455,7 +455,7 @@ namespace llarp Router::SaveRC() { LogDebug("verify RC signature"); - if (!router_contact.Verify(Now())) + if (!router_contact.Verify(now())) { Dump(rc()); LogError("RC is invalid, not saving"); @@ -503,8 +503,10 @@ namespace llarp bool Router::ParseRoutingMessageBuffer( - const llarp_buffer_t& buf, routing::AbstractRoutingMessageHandler* h, const PathID_t& rxid) - {} + const llarp_buffer_t&, routing::AbstractRoutingMessageHandler*, const PathID_t&) + { + return false; + } bool Router::appears_decommed() const @@ -710,7 +712,7 @@ namespace llarp { if (it->IsObsoleteBootstrap()) log::warning(logcat, "ignoring obsolete boostrap RC: {}", RouterID{it->pubkey}); - else if (not it->Verify(Now())) + else if (not it->Verify(now())) log::warning(logcat, "ignoring invalid bootstrap RC: {}", RouterID{it->pubkey}); else { @@ -830,7 +832,7 @@ namespace llarp void Router::report_stats() { - const auto now = Now(); + const auto now = now(); LogInfo(node_db()->NumLoaded(), " RCs loaded"); LogInfo(bootstrap_rc_list.size(), " bootstrap peers"); LogInfo(NumberOfConnectedRouters(), " router connections"); @@ -903,7 +905,7 @@ namespace llarp if (is_stopping) return; // LogDebug("tick router"); - const auto now = Now(); + const auto now = now(); if (const auto delta = now - _last_tick; _last_tick != 0s and delta > TimeskipDetectedDuration) { // we detected a time skip into the futre, thaw the network @@ -1183,7 +1185,7 @@ namespace llarp Router::StartRpcServer() { if (_config->api.m_enableRPCServer) - m_RPCServer = std::make_unique(_lmq, *this); + _rpc_server = std::make_unique(_lmq, *this); return true; } @@ -1283,7 +1285,7 @@ namespace llarp _loop->call_every(ROUTER_TICK_INTERVAL, weak_from_this(), [this] { Tick(); }); _route_poker->start(); is_running.store(true); - _started_at = Now(); + _started_at = now(); if (follow_whitelist) { // do service node testing if we are in service node whitelist mode @@ -1375,7 +1377,7 @@ namespace llarp llarp_time_t Router::Uptime() const { - const llarp_time_t _now = Now(); + const llarp_time_t _now = now(); if (_started_at > 0s && _now > _started_at) return _now - _started_at; return 0s; @@ -1602,9 +1604,7 @@ namespace llarp for (auto& bind_addr : addrs) { - AddressInfo ai; - ai.fromSockAddr(bind_addr); - _linkManager.connect_to({ai.IPString(), ai.port}, false); + _link_manager.connect_to({bind_addr.ToString()}, false); } } diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 121702a671..67b48187be 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -48,10 +47,22 @@ /* TONUKE: - hidden_service_context + + TODO: + - router should hold DHT nodes container? in either a class or a map + - */ namespace llarp { + /// number of routers to publish to + static constexpr size_t INTROSET_RELAY_REDUNDANCY = 2; + + /// number of dht locations handled per relay + static constexpr size_t INTROSET_REQS_PER_RELAY = 2; + + static constexpr size_t INTROSET_STORAGE_REDUNDANCY = + (INTROSET_RELAY_REDUNDANCY * INTROSET_REQS_PER_RELAY); class RouteManager final /* : public Router */ { @@ -120,7 +131,7 @@ namespace llarp std::shared_ptr _config; uint32_t _path_build_count = 0; - std::unique_ptr m_RPCServer; + std::unique_ptr _rpc_server; const llarp_time_t _randomStartDelay; @@ -393,8 +404,8 @@ namespace llarp bool LooksAlive() const { - const llarp_time_t now = Now(); - return now <= _last_tick || (now - _last_tick) <= llarp_time_t{30000}; + const llarp_time_t current = now(); + return current <= _last_tick || (current - _last_tick) <= llarp_time_t{30000}; } const std::shared_ptr& @@ -535,7 +546,7 @@ namespace llarp Tick(); llarp_time_t - Now() const + now() const { return llarp::time_now_ms(); } diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index 936bb1cf98..35cb8a3c1e 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -230,7 +230,6 @@ namespace llarp void RouterContact::Clear() { - addrs.clear(); signature.Zero(); nickname.Zero(); enckey.Zero(); @@ -248,7 +247,7 @@ namespace llarp {"lastUpdated", last_updated.count()}, {"publicRouter", IsPublicRouter()}, {"identity", pubkey.ToString()}, - {"addresses", addrs}}; + {"address", addr.to_string()}}; if (HasNick()) { @@ -344,7 +343,7 @@ namespace llarp RouterContact::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) { bool read = false; - if (!BEncodeMaybeReadDictList("a", addrs, read, key, buf)) + if (!BEncodeMaybeReadDictList("a", addr, read, key, buf)) return false; if (!BEncodeMaybeReadDictEntry("i", netID, read, key, buf)) @@ -406,7 +405,7 @@ namespace llarp { if (not routerVersion) return false; - return !addrs.empty(); + return addr.is_addressable(); } bool @@ -496,14 +495,13 @@ namespace llarp // TODO: make net* overridable const auto* net = net::Platform::Default_ptr(); - for (const auto& a : addrs) + + if (net->IsBogon(addr.in4()) && BlockBogons) { - if (net->IsBogon(a.ip) && BlockBogons) - { - log::error(logcat, "invalid address info: {}", a); - return false; - } + log::error(logcat, "invalid address info: {}", addr); + return false; } + if (!VerifySignature()) { log::error(logcat, "invalid signature: {}", *this); @@ -524,17 +522,18 @@ namespace llarp llarp_buffer_t buf(tmp); auto bte = copy.bt_encode(); - buf.write(bte.begin(), bte.end()); - - buf.sz = buf.cur - buf.base; - buf.cur = buf.base; - return CryptoManager::instance()->verify(pubkey, buf, signature); + return CryptoManager::instance()->verify( + pubkey, reinterpret_cast(bte.data()), bte.size(), signature); } /* else */ if (version == 1) { llarp_buffer_t buf{signed_bt_dict}; - return CryptoManager::instance()->verify(pubkey, buf, signature); + return CryptoManager::instance()->verify( + pubkey, + reinterpret_cast(const_cast(signed_bt_dict.data())), + signed_bt_dict.size(), + signature); } return false; @@ -603,7 +602,7 @@ namespace llarp last_updated.count(), netID, version, - fmt::format("{}", fmt::join(addrs, ",")), + fmt::format("{}", addr), enckey, signature); } diff --git a/llarp/rpc/lokid_rpc_client.cpp b/llarp/rpc/lokid_rpc_client.cpp index 0db01fd662..7e8e99cab0 100644 --- a/llarp/rpc/lokid_rpc_client.cpp +++ b/llarp/rpc/lokid_rpc_client.cpp @@ -352,10 +352,11 @@ namespace llarp::rpc void LokidRpcClient::LookupLNSNameHash( - dht::Key_t namehash, std::function)> resultHandler) + std::string namehash, + std::function)> resultHandler) { LogDebug("Looking Up LNS NameHash ", namehash); - const nlohmann::json req{{"type", 2}, {"name_hash", namehash.ToHex()}}; + const nlohmann::json req{{"type", 2}, {"name_hash", oxenc::to_hex(namehash)}}; Request( "rpc.lns_resolve", [this, resultHandler](bool success, std::vector data) { diff --git a/llarp/rpc/lokid_rpc_client.hpp b/llarp/rpc/lokid_rpc_client.hpp index becca7e29c..0cef8a90b5 100644 --- a/llarp/rpc/lokid_rpc_client.hpp +++ b/llarp/rpc/lokid_rpc_client.hpp @@ -37,7 +37,7 @@ namespace llarp void LookupLNSNameHash( - dht::Key_t namehash, + std::string namehash, std::function)> resultHandler); /// inform that if connected to a router successfully diff --git a/llarp/rpc/rpc_server.cpp b/llarp/rpc/rpc_server.cpp index 08c89fb484..fe0139e261 100644 --- a/llarp/rpc/rpc_server.cpp +++ b/llarp/rpc/rpc_server.cpp @@ -103,7 +103,7 @@ namespace llarp::rpc : m_LMQ{std::move(lmq)}, m_Router(r), log_subs{*m_LMQ, llarp::logRingBuffer} { // copied logic loop as placeholder - for (const auto& addr : r.get_config()->api.m_rpcBindAddresses) + for (const auto& addr : r.config()->api.m_rpcBindAddresses) { m_LMQ->listen_plain(addr.zmq_address()); LogInfo("Bound RPC server to ", addr.full_address()); @@ -392,7 +392,7 @@ namespace llarp::rpc try { for (auto& ip : unmapexit.request.ip_range) - m_Router.hiddenServiceContext().GetDefault()->UnmapExitRange(ip); + m_Router.hidden_service_context().GetDefault()->UnmapExitRange(ip); } catch (std::exception& e) { diff --git a/llarp/service/address.hpp b/llarp/service/address.hpp index fd437b76bc..40689a19ea 100644 --- a/llarp/service/address.hpp +++ b/llarp/service/address.hpp @@ -45,7 +45,7 @@ namespace llarp throw std::runtime_error("invalid address"); } - explicit Address(const Data& buf) : AlignedBuffer<32>(buf) + explicit Address(const std::array& buf) : AlignedBuffer<32>(buf) {} Address(const Address& other) diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 6cd921fb0f..03dacb0a22 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -49,20 +49,20 @@ namespace llarp static auto logcat = log::Cat("endpoint"); Endpoint::Endpoint(Router* r, Context* parent) - : path::Builder{r, 3, path::default_len} + : path::Builder{r, 3, path::DEFAULT_LEN} , context{parent} - , m_InboundTrafficQueue{512} - , m_SendQueue{512} - , m_RecvQueue{512} - , m_IntrosetLookupFilter{5s} + , _inbound_queue{512} + , _send_queue{512} + , _recv_event_queue{512} + , _introset_lookup_filter{5s} { - m_state = std::make_unique(); - m_state->m_Router = r; - m_state->m_Name = "endpoint"; - m_RecvQueue.enable(); + _state = std::make_unique(); + _state->m_Router = r; + _state->m_Name = "endpoint"; + _recv_event_queue.enable(); if (Loop()->MaybeGetUVWLoop()) - m_quic = std::make_unique(*this); + _tunnel_manager = std::make_unique(*this); } bool @@ -87,106 +87,25 @@ namespace llarp const auto itr = conf.m_LNSExitAuths.find(name); if (itr != conf.m_LNSExitAuths.end()) auth = itr->second; - m_StartupLNSMappings[name] = std::make_pair(range, auth); + _startup_ons_mappings[name] = std::make_pair(range, auth); }); - return m_state->Configure(conf); + return _state->Configure(conf); } bool Endpoint::HasPendingPathToService(const Address& addr) const { - return m_state->m_PendingServiceLookups.find(addr) != m_state->m_PendingServiceLookups.end(); - } - - void - Endpoint::RegenAndPublishIntroSet() - { - const auto now = llarp::time_now_ms(); - m_LastIntrosetRegenAttempt = now; - std::set intros; - if (const auto maybe = - GetCurrentIntroductionsWithFilter([now](const service::Introduction& intro) -> bool { - return not intro.ExpiresSoon(now, path::intro_stale_threshold); - })) - { - intros.insert(maybe->begin(), maybe->end()); - } - else - { - LogWarn( - "could not publish descriptors for endpoint ", - Name(), - " because we couldn't get enough valid introductions"); - BuildOne(); - return; - } - - introSet().supported_protocols.clear(); - - // add supported ethertypes - if (HasIfAddr()) - { - if (IPRange::V4MappedRange().Contains(GetIfAddr())) - { - introSet().supported_protocols.push_back(ProtocolType::TrafficV4); - } - else - { - introSet().supported_protocols.push_back(ProtocolType::TrafficV6); - } - - // exit related stuffo - if (m_state->m_ExitEnabled) - { - introSet().supported_protocols.push_back(ProtocolType::Exit); - introSet().exit_policy = GetExitPolicy(); - introSet().owned_ranges = GetOwnedRanges(); - } - } - // add quic ethertype if we have listeners set up - if (auto* quic = GetQUICTunnel()) - { - if (quic->hasListeners()) - introSet().supported_protocols.push_back(ProtocolType::QUIC); - } - - introSet().intros.clear(); - for (auto& intro : intros) - { - if (introSet().intros.size() < numDesiredPaths) - introSet().intros.emplace_back(std::move(intro)); - } - if (introSet().intros.empty()) - { - LogWarn("not enough intros to publish introset for ", Name()); - if (ShouldBuildMore(now)) - ManualRebuild(1); - return; - } - auto maybe = m_Identity.EncryptAndSignIntroSet(introSet(), now); - if (not maybe) - { - LogWarn("failed to generate introset for endpoint ", Name()); - return; - } - if (PublishIntroSet(*maybe, router())) - { - LogInfo("(re)publishing introset for endpoint ", Name()); - } - else - { - LogWarn("failed to publish intro set for endpoint ", Name()); - } + return _state->m_PendingServiceLookups.find(addr) != _state->m_PendingServiceLookups.end(); } bool Endpoint::is_ready() const { const auto now = Now(); - if (introSet().intros.empty()) + if (intro_set().intros.empty()) return false; - if (introSet().IsExpired(now)) + if (intro_set().IsExpired(now)) return false; return true; } @@ -194,7 +113,7 @@ namespace llarp bool Endpoint::HasPendingRouterLookup(const RouterID remote) const { - const auto& routers = m_state->m_PendingRouters; + const auto& routers = _state->m_PendingRouters; return routers.find(remote) != routers.end(); } @@ -207,7 +126,7 @@ namespace llarp return itr->second.remote.Addr(); } - for (const auto& item : m_state->m_SNodeSessions) + for (const auto& item : _state->m_SNodeSessions) { if (const auto maybe = item.second->CurrentPath()) { @@ -238,7 +157,7 @@ namespace llarp auth = AuthInfo{token}, ranges, result_handler, - poker = m_router->routePoker()](auto maybe_addr) { + poker = m_router->route_poker()](auto maybe_addr) { if (not maybe_addr) { result_handler(false, "exit not found: {}"_format(name)); @@ -271,7 +190,7 @@ namespace llarp ptr->MapExitRange(range, addr); if (poker) - poker->Up(); + poker->put_up(); result_handler(true, result.reason); }; @@ -297,7 +216,7 @@ namespace llarp auto handleGotPathToService = [resultHandler, service, this](auto addr) { // we can probably get this info before we have a path to them but we do this after we // have a path so when we send the response back they can send shit to them immediately - const auto& container = m_state->m_RemoteSessions; + const auto& container = _state->m_RemoteSessions; if (auto itr = container.find(addr); itr != container.end()) { // parse the stuff we need from this guy @@ -373,25 +292,25 @@ namespace llarp bool Endpoint::IntrosetIsStale() const { - return introSet().HasExpiredIntros(Now()); + return intro_set().HasExpiredIntros(Now()); } util::StatusObject Endpoint::ExtractStatus() const { auto obj = path::Builder::ExtractStatus(); - obj["exitMap"] = m_ExitMap.ExtractStatus(); - obj["identity"] = m_Identity.pub.Addr().ToString(); + obj["exitMap"] = _exit_map.ExtractStatus(); + obj["identity"] = _identity.pub.Addr().ToString(); obj["networkReady"] = ReadyForNetwork(); util::StatusObject authCodes; - for (const auto& [service, info] : m_RemoteAuthInfos) + for (const auto& [service, info] : _remote_auth_infos) { authCodes[service.ToString()] = info.token; } obj["authCodes"] = authCodes; - return m_state->ExtractStatus(obj); + return _state->ExtractStatus(obj); } void @@ -402,30 +321,30 @@ namespace llarp // publish descriptors if (ShouldPublishDescriptors(now)) { - RegenAndPublishIntroSet(); + regen_and_publish_introset(); } // decay introset lookup filter - m_IntrosetLookupFilter.Decay(now); + _introset_lookup_filter.Decay(now); // expire name cache - m_state->nameCache.Decay(now); + _state->nameCache.Decay(now); // expire snode sessions - EndpointUtil::ExpireSNodeSessions(now, m_state->m_SNodeSessions); + EndpointUtil::ExpireSNodeSessions(now, _state->m_SNodeSessions); // expire pending tx - EndpointUtil::ExpirePendingTx(now, m_state->m_PendingLookups); + EndpointUtil::ExpirePendingTx(now, _state->m_PendingLookups); // expire pending router lookups - EndpointUtil::ExpirePendingRouterLookups(now, m_state->m_PendingRouters); + EndpointUtil::ExpirePendingRouterLookups(now, _state->m_PendingRouters); // deregister dead sessions - EndpointUtil::DeregisterDeadSessions(now, m_state->m_DeadSessions); + EndpointUtil::DeregisterDeadSessions(now, _state->m_DeadSessions); // tick remote sessions EndpointUtil::TickRemoteSessions( - now, m_state->m_RemoteSessions, m_state->m_DeadSessions, Sessions()); + now, _state->m_RemoteSessions, _state->m_DeadSessions, Sessions()); // expire convotags EndpointUtil::ExpireConvoSessions(now, Sessions()); if (NumInStatus(path::ePathEstablished) > 1) { - for (const auto& item : m_StartupLNSMappings) + for (const auto& item : _startup_ons_mappings) { LookupNameAsync( item.first, [name = item.first, info = item.second, this](auto maybe_addr) { @@ -434,11 +353,11 @@ namespace llarp const auto maybe_range = info.first; const auto maybe_auth = info.second; - m_StartupLNSMappings.erase(name); + _startup_ons_mappings.erase(name); if (auto* addr = std::get_if(&*maybe_addr)) { if (maybe_range.has_value()) - m_ExitMap.Insert(*maybe_range, *addr); + _exit_map.Insert(*maybe_range, *addr); if (maybe_auth.has_value()) SetAuthInfoForEndpoint(*addr, *maybe_auth); } @@ -453,10 +372,10 @@ namespace llarp { // stop remote sessions log::debug(logcat, "Endpoint stopping remote sessions."); - EndpointUtil::StopRemoteSessions(m_state->m_RemoteSessions); + EndpointUtil::StopRemoteSessions(_state->m_RemoteSessions); // stop snode sessions log::debug(logcat, "Endpoint stopping snode sessions."); - EndpointUtil::StopSnodeSessions(m_state->m_SNodeSessions); + EndpointUtil::StopSnodeSessions(_state->m_SNodeSessions); log::debug(logcat, "Endpoint stopping its path builder."); return path::Builder::Stop(); } @@ -465,7 +384,7 @@ namespace llarp Endpoint::GenTXID() { uint64_t txid = randint(); - const auto& lookups = m_state->m_PendingLookups; + const auto& lookups = _state->m_PendingLookups; while (lookups.find(txid) != lookups.end()) ++txid; return txid; @@ -474,13 +393,13 @@ namespace llarp std::string Endpoint::Name() const { - return m_state->m_Name + ":" + m_Identity.pub.Name(); + return _state->m_Name + ":" + _identity.pub.Name(); } void Endpoint::PutLookup(IServiceLookup* lookup, uint64_t txid) { - m_state->m_PendingLookups.emplace(txid, std::unique_ptr(lookup)); + _state->m_PendingLookups.emplace(txid, std::unique_ptr(lookup)); } bool @@ -496,7 +415,7 @@ namespace llarp } remote.insert(introset); } - auto& lookups = m_state->m_PendingLookups; + auto& lookups = _state->m_PendingLookups; auto itr = lookups.find(msg->txid); if (itr == lookups.end()) { @@ -671,14 +590,14 @@ namespace llarp bool Endpoint::LoadKeyFile() { - const auto& keyfile = m_state->m_Keyfile; + const auto& keyfile = _state->m_Keyfile; if (!keyfile.empty()) { - m_Identity.EnsureKeys(keyfile, router()->key_manager()->needBackup()); + _identity.EnsureKeys(keyfile, router()->key_manager()->needBackup()); } else { - m_Identity.RegenerateKeys(); + _identity.RegenerateKeys(); } return true; } @@ -687,15 +606,15 @@ namespace llarp Endpoint::Start() { // how can I tell if a m_Identity isn't loaded? - if (!m_DataHandler) + if (!_data_handler) { - m_DataHandler = this; + _data_handler = this; } // this does network isolation - while (m_state->m_OnInit.size()) + while (_state->m_OnInit.size()) { - if (m_state->m_OnInit.front()()) - m_state->m_OnInit.pop_front(); + if (_state->m_OnInit.front()()) + _state->m_OnInit.pop_front(); else { LogWarn("Can't call init of network isolation"); @@ -709,21 +628,105 @@ namespace llarp // in endpoint.hpp for the unique_ptr member destructor. Endpoint::~Endpoint() = default; + void + Endpoint::regen_and_publish_introset() + { + const auto now = llarp::time_now_ms(); + _last_introset_regen_attempt = now; + std::set intros; + + if (const auto maybe = + GetCurrentIntroductionsWithFilter([now](const service::Introduction& intro) -> bool { + return not intro.ExpiresSoon(now, path::INTRO_STALE_THRESHOLD); + })) + { + intros.insert(maybe->begin(), maybe->end()); + } + else + { + LogWarn( + "could not publish descriptors for endpoint ", + Name(), + " because we couldn't get enough valid introductions"); + BuildOne(); + return; + } + + intro_set().supported_protocols.clear(); + + // add supported ethertypes + if (HasIfAddr()) + { + if (IPRange::V4MappedRange().Contains(GetIfAddr())) + { + intro_set().supported_protocols.push_back(ProtocolType::TrafficV4); + } + else + { + intro_set().supported_protocols.push_back(ProtocolType::TrafficV6); + } + + // exit related stuffo + if (_state->m_ExitEnabled) + { + intro_set().supported_protocols.push_back(ProtocolType::Exit); + intro_set().exit_policy = GetExitPolicy(); + intro_set().owned_ranges = GetOwnedRanges(); + } + } + // add quic ethertype if we have listeners set up + if (auto* quic = GetQUICTunnel()) + { + if (quic->hasListeners()) + intro_set().supported_protocols.push_back(ProtocolType::QUIC); + } + + intro_set().intros.clear(); + for (auto& intro : intros) + { + if (intro_set().intros.size() < numDesiredPaths) + intro_set().intros.emplace_back(std::move(intro)); + } + if (intro_set().intros.empty()) + { + LogWarn("not enough intros to publish introset for ", Name()); + if (ShouldBuildMore(now)) + ManualRebuild(1); + return; + } + auto maybe = _identity.encrypt_and_sign_introset(intro_set(), now); + if (not maybe) + { + LogWarn("failed to generate introset for endpoint ", Name()); + return; + } + if (PublishIntroSet(*maybe)) + { + LogInfo("(re)publishing introset for endpoint ", Name()); + } + else + { + LogWarn("failed to publish intro set for endpoint ", Name()); + } + } + bool - Endpoint::PublishIntroSet(const EncryptedIntroSet& introset, Router* r) + Endpoint::PublishIntroSet(const EncryptedIntroSet& introset) { + auto* r = router(); + const auto paths = GetManyPathsWithUniqueEndpoints( this, - llarp::dht::IntroSetRelayRedundancy, + llarp::dht::INTROSET_RELAY_REDUNDANCY, dht::Key_t{introset.derivedSigningKey.as_array()}); - if (paths.size() != llarp::dht::IntroSetRelayRedundancy) + if (paths.size() != llarp::dht::INTROSET_RELAY_REDUNDANCY) { LogWarn( "Cannot publish intro set because we only have ", paths.size(), " paths, but need ", - llarp::dht::IntroSetRelayRedundancy); + llarp::dht::INTROSET_RELAY_REDUNDANCY); return false; } @@ -732,7 +735,7 @@ namespace llarp for (const auto& path : paths) { - for (size_t i = 0; i < llarp::dht::IntroSetRequestsPerRelay; ++i) + for (size_t i = 0; i < llarp::dht::INTROSET_REQS_PER_RELAY; ++i) { r->notify_router_event( r->pubkey(), @@ -743,13 +746,13 @@ namespace llarp published++; } } - if (published != llarp::dht::IntroSetStorageRedundancy) + if (published != llarp::dht::INTROSET_STORAGE_REDUNDANCY) LogWarn( "Publish introset failed: could only publish ", published, " copies but wanted ", - llarp::dht::IntroSetStorageRedundancy); - return published == llarp::dht::IntroSetStorageRedundancy; + llarp::dht::INTROSET_STORAGE_REDUNDANCY); + return published == llarp::dht::INTROSET_STORAGE_REDUNDANCY; } struct PublishIntroSetJob : public IServiceLookup @@ -770,7 +773,7 @@ namespace llarp {} std::shared_ptr - BuildRequestMessage() override + BuildRequestMessage() { auto msg = std::make_shared(); msg->dht_msgs.emplace_back( @@ -779,7 +782,7 @@ namespace llarp } bool - HandleIntrosetResponse(const std::set& response) override + HandleIntrosetResponse(const std::set& response) { if (not response.empty()) m_Endpoint->IntroSetPublished(); @@ -796,11 +799,11 @@ namespace llarp auto now = Now(); if (ShouldPublishDescriptors(now)) { - RegenAndPublishIntroSet(); + regen_and_publish_introset(); } else if (NumInStatus(path::ePathEstablished) < 3) { - if (introSet().HasExpiredIntros(now)) + if (intro_set().HasExpiredIntros(now)) ManualRebuild(1); } } @@ -808,7 +811,7 @@ namespace llarp size_t Endpoint::UniqueEndpoints() const { - return m_state->m_RemoteSessions.size() + m_state->m_SNodeSessions.size(); + return _state->m_RemoteSessions.size() + _state->m_SNodeSessions.size(); } constexpr auto PublishIntrosetTimeout = 20s; @@ -821,7 +824,7 @@ namespace llarp new PublishIntroSetJob(this, GenTXID(), introset, relayOrder, PublishIntrosetTimeout); if (job->SendRequestViaPath(path, r)) { - m_state->m_LastPublishAttempt = Now(); + _state->m_LastPublishAttempt = Now(); return true; } return false; @@ -836,19 +839,19 @@ namespace llarp getter(item)->ResetInternalState(); }); }; - resetState(m_state->m_RemoteSessions, [](const auto& item) { return item.second; }); - resetState(m_state->m_SNodeSessions, [](const auto& item) { return item.second; }); + resetState(_state->m_RemoteSessions, [](const auto& item) { return item.second; }); + resetState(_state->m_SNodeSessions, [](const auto& item) { return item.second; }); } bool Endpoint::ShouldPublishDescriptors(llarp_time_t now) const { - if (not m_PublishIntroSet) + if (not _publish_introset) return false; - const auto lastEventAt = std::max(m_state->m_LastPublishAttempt, m_state->m_LastPublish); + const auto lastEventAt = std::max(_state->m_LastPublishAttempt, _state->m_LastPublish); const auto next_pub = lastEventAt - + (m_state->m_IntroSet.HasStaleIntros(now, path::intro_stale_threshold) + + (_state->m_IntroSet.HasStaleIntros(now, path::INTRO_STALE_THRESHOLD) ? IntrosetPublishRetryCooldown : IntrosetPublishInterval); @@ -862,12 +865,12 @@ namespace llarp // We usually get 4 confirmations back (one for each DHT location), which // is noisy: suppress this log message if we already had a confirmation in // the last second. - if (m_state->m_LastPublish < now - 1s) + if (_state->m_LastPublish < now - 1s) LogInfo(Name(), " IntroSet publish confirmed"); else LogDebug(Name(), " Additional IntroSet publish confirmed"); - m_state->m_LastPublish = now; + _state->m_LastPublish = now; } std::optional> @@ -902,9 +905,9 @@ namespace llarp void Endpoint::PutNewOutboundContext(const service::IntroSet& introset, llarp_time_t left) { - const Address addr{introset.addressKeys.Addr()}; + const Address addr{introset.address_keys.Addr()}; - auto& remoteSessions = m_state->m_RemoteSessions; + auto& remoteSessions = _state->m_RemoteSessions; if (remoteSessions.count(addr) < MaxOutboundContextPerRemote) { @@ -923,7 +926,7 @@ namespace llarp void Endpoint::HandleVerifyGotRouter(dht::GotRouterMessage_constptr msg, RouterID id, bool valid) { - auto& pendingRouters = m_state->m_PendingRouters; + auto& pendingRouters = _state->m_PendingRouters; auto itr = pendingRouters.find(id); if (itr != pendingRouters.end()) { @@ -953,7 +956,7 @@ namespace llarp } else { - auto& routers = m_state->m_PendingRouters; + auto& routers = _state->m_PendingRouters; auto itr = routers.begin(); while (itr != routers.end()) { @@ -982,7 +985,7 @@ namespace llarp : IServiceLookup(parent, id, lnsName), handler(resultHandler) { CryptoManager::instance()->shorthash( - namehash, llarp_buffer_t(lnsName.c_str(), lnsName.size())); + namehash, reinterpret_cast(lnsName.data()), lnsName.size()); } std::shared_ptr @@ -1011,13 +1014,13 @@ namespace llarp bool Endpoint::HasExit() const { - for (const auto& [name, info] : m_StartupLNSMappings) + for (const auto& [name, info] : _startup_ons_mappings) { if (info.first.has_value()) return true; } - return not m_ExitMap.Empty(); + return not _exit_map.Empty(); } path::Path::UniqueEndpointSet_t @@ -1054,7 +1057,7 @@ namespace llarp handler(ParseAddress(name)); return; } - auto& cache = m_state->nameCache; + auto& cache = _state->nameCache; const auto maybe = cache.Get(name); if (maybe.has_value()) { @@ -1104,7 +1107,7 @@ namespace llarp chosenpaths.resize(std::min(paths.size(), max_lns_lookup_endpoints)); auto resultHandler = - m_state->lnsTracker.MakeResultHandler(name, chosenpaths.size(), maybeInvalidateCache); + _state->lnsTracker.MakeResultHandler(name, chosenpaths.size(), maybeInvalidateCache); for (const auto& path : chosenpaths) { @@ -1117,7 +1120,7 @@ namespace llarp bool Endpoint::HandleGotNameMessage(std::shared_ptr msg) { - auto& lookups = m_state->m_PendingLookups; + auto& lookups = _state->m_PendingLookups; auto itr = lookups.find(msg->TxID); if (itr == lookups.end()) return false; @@ -1146,7 +1149,7 @@ namespace llarp { using llarp::dht::FindRouterMessage; - auto& routers = m_state->m_PendingRouters; + auto& routers = _state->m_PendingRouters; if (routers.find(rid) == routers.end()) { auto path = GetEstablishedPathClosestTo(rid); @@ -1199,13 +1202,13 @@ namespace llarp std::unordered_map Endpoint::NotifyParams() const { - return {{"LOKINET_ADDR", m_Identity.pub.Addr().ToString()}}; + return {{"LOKINET_ADDR", _identity.pub.Addr().ToString()}}; } void Endpoint::FlushRecvData() { - while (auto maybe = m_RecvQueue.tryPopFront()) + while (auto maybe = _recv_event_queue.tryPopFront()) { auto& ev = *maybe; ProtocolMessage::ProcessAsync(ev.fromPath, ev.pathid, ev.msg); @@ -1215,7 +1218,7 @@ namespace llarp void Endpoint::QueueRecvData(RecvDataEvent ev) { - m_RecvQueue.tryPushBack(std::move(ev)); + _recv_event_queue.tryPushBack(std::move(ev)); router()->TriggerPump(); } @@ -1238,7 +1241,7 @@ namespace llarp bool Endpoint::HasPathToSNode(const RouterID ident) const { - auto range = m_state->m_SNodeSessions.equal_range(ident); + auto range = _state->m_SNodeSessions.equal_range(ident); auto itr = range.first; while (itr != range.second) { @@ -1254,7 +1257,7 @@ namespace llarp EndpointBase::AddressVariant_t Endpoint::LocalAddress() const { - return m_Identity.pub.Addr(); + return _identity.pub.Addr(); } std::optional @@ -1272,7 +1275,7 @@ namespace llarp { remote.insert(item.second.remote.Addr()); } - for (const auto& item : m_state->m_SNodeSessions) + for (const auto& item : _state->m_SNodeSessions) { remote.insert(item.first); } @@ -1283,11 +1286,11 @@ namespace llarp Endpoint::ProcessDataMessage(std::shared_ptr msg) { if ((msg->proto == ProtocolType::Exit - && (m_state->m_ExitEnabled || m_ExitMap.ContainsValue(msg->sender.Addr()))) + && (_state->m_ExitEnabled || _exit_map.ContainsValue(msg->sender.Addr()))) || msg->proto == ProtocolType::TrafficV4 || msg->proto == ProtocolType::TrafficV6 - || (msg->proto == ProtocolType::QUIC and m_quic)) + || (msg->proto == ProtocolType::QUIC and _tunnel_manager)) { - m_InboundTrafficQueue.tryPushBack(std::move(msg)); + _inbound_queue.tryPushBack(std::move(msg)); router()->TriggerPump(); return true; } @@ -1304,12 +1307,12 @@ namespace llarp Endpoint::AsyncProcessAuthMessage( std::shared_ptr msg, std::function hook) { - if (m_AuthPolicy) + if (_auth_policy) { - if (not m_AuthPolicy->AsyncAuthPending(msg->tag)) + if (not _auth_policy->AsyncAuthPending(msg->tag)) { // do 1 authentication attempt and drop everything else - m_AuthPolicy->AuthenticateAsync(std::move(msg), std::move(hook)); + _auth_policy->AuthenticateAsync(std::move(msg), std::move(hook)); } } else @@ -1323,7 +1326,7 @@ namespace llarp path::Path_ptr path, PathID_t replyPath, ConvoTag tag, AuthResult result) { // not applicable because we are not an exit or don't have an endpoint auth policy - if ((not m_state->m_ExitEnabled) or m_AuthPolicy == nullptr) + if ((not _state->m_ExitEnabled) or _auth_policy == nullptr) return; ProtocolFrameMessage f{}; f.flag = AuthResultCodeAsInt(result.code); @@ -1338,7 +1341,7 @@ namespace llarp reason.resize(result.reason.size()); std::copy_n(result.reason.c_str(), reason.size(), reason.data()); msg.PutBuffer(reason); - if (m_AuthPolicy) + if (_auth_policy) msg.proto = ProtocolType::Auth; else msg.proto = ProtocolType::Control; @@ -1348,14 +1351,14 @@ namespace llarp LogError("Failed to send auth reply: no reply intro"); return; } - msg.sender = m_Identity.pub; + msg.sender = _identity.pub; SharedSecret sessionKey{}; if (not GetCachedSessionKeyFor(tag, sessionKey)) { LogError("failed to send auth reply: no cached session key"); return; } - if (not f.EncryptAndSign(msg, sessionKey, m_Identity)) + if (not f.EncryptAndSign(msg, sessionKey, _identity)) { LogError("Failed to encrypt and sign auth reply"); return; @@ -1363,13 +1366,13 @@ namespace llarp } else { - if (not f.Sign(m_Identity)) + if (not f.Sign(_identity)) { LogError("failed to sign auth reply result"); return; } } - m_SendQueue.tryPushBack( + _send_queue.tryPushBack( SendEvent_t{std::make_shared(f, replyPath), path}); } @@ -1387,11 +1390,11 @@ namespace llarp f.flag = 1; f.convo_tag = tag; f.path_id = p->intro.path_id; - f.Sign(m_Identity); + f.Sign(_identity); { LogWarn("invalidating convotag T=", tag); RemoveConvoTag(tag); - m_SendQueue.tryPushBack( + _send_queue.tryPushBack( SendEvent_t{std::make_shared(f, from), p}); } } @@ -1413,7 +1416,7 @@ namespace llarp RemoveConvoTag(frame.convo_tag); return true; } - if (not frame.AsyncDecryptAndVerify(router()->loop(), p, m_Identity, this)) + if (not frame.AsyncDecryptAndVerify(router()->loop(), p, _identity, this)) { ResetConvoTag(frame.convo_tag, p, frame.path_id); } @@ -1426,13 +1429,13 @@ namespace llarp m_router->router_profiling().MarkPathTimeout(p.get()); ManualRebuild(1); path::Builder::HandlePathDied(p); - RegenAndPublishIntroSet(); + regen_and_publish_introset(); } bool Endpoint::CheckPathIsDead(path::Path_ptr, llarp_time_t dlt) { - return dlt > path::alive_timeout; + return dlt > path::ALIVE_TIMEOUT; } bool @@ -1445,11 +1448,11 @@ namespace llarp { // tell all our existing remote sessions about this introset update - const auto now = router()->Now(); - auto& lookups = m_state->m_PendingServiceLookups; + const auto now = router()->now(); + auto& lookups = _state->m_PendingServiceLookups; if (introset) { - auto& sessions = m_state->m_RemoteSessions; + auto& sessions = _state->m_RemoteSessions; auto range = sessions.equal_range(addr); auto itr = range.first; while (itr != range.second) @@ -1471,7 +1474,7 @@ namespace llarp ++itr; } } - auto& fails = m_state->m_ServiceLookupFails; + auto& fails = _state->m_ServiceLookupFails; if (not introset or introset->IsExpired(now)) { LogError( @@ -1485,8 +1488,8 @@ namespace llarp fails[endpoint] = fails[endpoint] + 1; const auto pendingForAddr = std::count_if( - m_state->m_PendingLookups.begin(), - m_state->m_PendingLookups.end(), + _state->m_PendingLookups.begin(), + _state->m_PendingLookups.end(), [addr](const auto& item) -> bool { return item.second->IsFor(addr); }); // inform all if we have no more pending lookups for this address @@ -1504,7 +1507,7 @@ namespace llarp } // check for established outbound context - if (m_state->m_RemoteSessions.count(addr) > 0) + if (_state->m_RemoteSessions.count(addr) > 0) return true; PutNewOutboundContext(*introset, timeLeft); @@ -1515,19 +1518,19 @@ namespace llarp Endpoint::MarkAddressOutbound(AddressVariant_t addr) { if (auto* ptr = std::get_if
(&addr)) - m_state->m_OutboundSessions.insert(*ptr); + _state->m_OutboundSessions.insert(*ptr); } bool Endpoint::WantsOutboundSession(const Address& addr) const { - return m_state->m_OutboundSessions.count(addr) > 0; + return _state->m_OutboundSessions.count(addr) > 0; } void Endpoint::InformPathToService(const Address remote, OutboundContext* ctx) { - auto& serviceLookups = m_state->m_PendingServiceLookups; + auto& serviceLookups = _state->m_PendingServiceLookups; auto range = serviceLookups.equal_range(remote); auto itr = range.first; while (itr != range.second) @@ -1555,9 +1558,9 @@ namespace llarp static constexpr size_t RequestsPerLookup = 2; // add response hook to list for address. - m_state->m_PendingServiceLookups.emplace(remote, hook); + _state->m_PendingServiceLookups.emplace(remote, hook); - auto& sessions = m_state->m_RemoteSessions; + auto& sessions = _state->m_RemoteSessions; { auto range = sessions.equal_range(remote); auto itr = range.first; @@ -1572,7 +1575,7 @@ namespace llarp } } /// check replay filter - if (not m_IntrosetLookupFilter.Insert(remote)) + if (not _introset_lookup_filter.Insert(remote)) return true; const auto paths = GetManyPathsWithUniqueEndpoints(this, NumParallelLookups); @@ -1624,18 +1627,18 @@ namespace llarp void Endpoint::SRVRecordsChanged() { - auto& introset = introSet(); + auto& introset = intro_set(); introset.SRVs.clear(); for (const auto& srv : SRVRecords()) introset.SRVs.emplace_back(srv.toTuple()); - RegenAndPublishIntroSet(); + regen_and_publish_introset(); } bool Endpoint::EnsurePathToSNode(const RouterID snode, SNodeEnsureHook h) { - auto& nodeSessions = m_state->m_SNodeSessions; + auto& nodeSessions = _state->m_SNodeSessions; using namespace std::placeholders; if (nodeSessions.count(snode) == 0) @@ -1651,8 +1654,8 @@ namespace llarp return false; pkt.UpdateIPv4Address(src, dst); /// TODO: V6 - auto itr = m_state->m_SNodeSessions.find(snode); - if (itr == m_state->m_SNodeSessions.end()) + auto itr = _state->m_SNodeSessions.find(snode); + if (itr == _state->m_SNodeSessions.end()) return false; if (const auto maybe = itr->second->CurrentPath()) return HandleInboundPacket( @@ -1664,7 +1667,7 @@ namespace llarp numHops, false, this); - m_state->m_SNodeSessions[snode] = session; + _state->m_SNodeSessions[snode] = session; } EnsureRouterIsKnown(snode); auto range = nodeSessions.equal_range(snode); @@ -1706,10 +1709,10 @@ namespace llarp { if (auto* ptr = std::get_if
(&*maybe)) { - if (*ptr == m_Identity.pub.Addr()) + if (*ptr == _identity.pub.Addr()) { ConvoTagTX(tag); - m_state->m_Router->TriggerPump(); + _state->m_Router->TriggerPump(); if (not HandleInboundPacket(tag, pkt, t, 0)) return false; ConvoTagRX(tag); @@ -1747,15 +1750,15 @@ namespace llarp { FlushRecvData(); // send downstream packets to user for snode - for (const auto& [router, session] : m_state->m_SNodeSessions) + for (const auto& [router, session] : _state->m_SNodeSessions) session->FlushDownstream(); // handle inbound traffic sorted util::ascending_priority_queue queue; - while (not m_InboundTrafficQueue.empty()) + while (not _inbound_queue.empty()) { // succ it out - queue.emplace(std::move(*m_InboundTrafficQueue.popFront())); + queue.emplace(std::move(*_inbound_queue.popFront())); } while (not queue.empty()) { @@ -1781,19 +1784,19 @@ namespace llarp auto r = router(); // TODO: locking on this container - for (const auto& [addr, outctx] : m_state->m_RemoteSessions) + for (const auto& [addr, outctx] : _state->m_RemoteSessions) { outctx->FlushUpstream(); outctx->Pump(now); } // TODO: locking on this container - for (const auto& [r, session] : m_state->m_SNodeSessions) + for (const auto& [r, session] : _state->m_SNodeSessions) session->FlushUpstream(); // send queue flush - while (not m_SendQueue.empty()) + while (not _send_queue.empty()) { - SendEvent_t item = m_SendQueue.popFront(); + SendEvent_t item = _send_queue.popFront(); item.first->sequence_number = item.second->NextSeqNo(); if (item.second->SendRoutingMessage(*item.first, r)) ConvoTagTX(item.first->protocol_frame_msg.convo_tag); @@ -1816,7 +1819,7 @@ namespace llarp continue; if (session.remote.Addr() == *ptr) { - if (*ptr == m_Identity.pub.Addr()) + if (*ptr == _identity.pub.Addr()) { return tag; } @@ -1843,7 +1846,7 @@ namespace llarp } else { - auto range = m_state->m_RemoteSessions.equal_range(*ptr); + auto range = _state->m_RemoteSessions.equal_range(*ptr); auto itr = range.first; while (itr != range.second) { @@ -1864,8 +1867,8 @@ namespace llarp } if (auto* ptr = std::get_if(&remote)) { - auto itr = m_state->m_SNodeSessions.find(*ptr); - if (itr == m_state->m_SNodeSessions.end()) + auto itr = _state->m_SNodeSessions.find(*ptr); + if (itr == _state->m_SNodeSessions.end()) return std::nullopt; if (auto maybe = itr->second->CurrentPath()) return ConvoTag{maybe->as_array()}; @@ -1881,7 +1884,7 @@ namespace llarp { if (auto ptr = std::get_if
(&addr)) { - if (*ptr == m_Identity.pub.Addr()) + if (*ptr == _identity.pub.Addr()) { ConvoTag tag{}; @@ -1889,7 +1892,7 @@ namespace llarp tag = *maybe; else tag.Randomize(); - PutSenderFor(tag, m_Identity.pub, true); + PutSenderFor(tag, _identity.pub, true); ConvoTagTX(tag); Sessions()[tag].forever = true; Loop()->call_soon([tag, hook]() { hook(tag); }); @@ -1990,7 +1993,7 @@ namespace llarp transfer->nonce.Randomize(); m->proto = t; m->introReply = p->intro; - m->sender = m_Identity.pub; + m->sender = _identity.pub; if (auto maybe = GetSeqNoForConvo(f.convo_tag)) { m->seqno = *maybe; @@ -2004,14 +2007,14 @@ namespace llarp f.path_id = p->intro.path_id; transfer->path_id = replyIntro.path_id; router()->queue_work([transfer, p, m, K, this]() { - if (not transfer->protocol_frame_msg.EncryptAndSign(*m, K, m_Identity)) + if (not transfer->protocol_frame_msg.EncryptAndSign(*m, K, _identity)) { LogError( "failed to encrypt and sign for sessionn T=", transfer->protocol_frame_msg.convo_tag); return; } - m_SendQueue.tryPushBack(SendEvent_t{transfer, p}); + _send_queue.tryPushBack(SendEvent_t{transfer, p}); router()->TriggerPump(); }); return true; @@ -2035,7 +2038,7 @@ namespace llarp // Failed to find a suitable inbound convo, look for outbound LogTrace("Not an inbound convo"); - auto& sessions = m_state->m_RemoteSessions; + auto& sessions = _state->m_RemoteSessions; auto range = sessions.equal_range(remote); for (auto itr = range.first; itr != range.second; ++itr) { @@ -2048,7 +2051,7 @@ namespace llarp } LogTrace("Making an outbound session and queuing the data"); // add pending traffic - auto& traffic = m_state->m_PendingTraffic; + auto& traffic = _state->m_PendingTraffic; traffic[remote].emplace_back(data, t); EnsurePathToService( remote, @@ -2064,7 +2067,7 @@ namespace llarp { LogWarn("no path made to ", addr); } - m_state->m_PendingTraffic.erase(addr); + _state->m_PendingTraffic.erase(addr); }, PathAlignmentTimeout()); return true; @@ -2097,17 +2100,17 @@ namespace llarp { if (BuildCooldownHit(now)) return false; - const auto requiredPaths = std::max(numDesiredPaths, path::min_intro_paths); + const auto requiredPaths = std::max(numDesiredPaths, path::MIN_INTRO_PATHS); if (NumInStatus(path::ePathBuilding) >= requiredPaths) return false; - return NumPathsExistingAt(now + (path::default_lifetime - path::intro_path_spread)) + return NumPathsExistingAt(now + (path::DEFAULT_LIFETIME - path::INTRO_PATH_SPREAD)) < requiredPaths; } Router* Endpoint::router() { - return m_state->m_Router; + return _state->m_Router; } const EventLoop_ptr& @@ -2119,37 +2122,37 @@ namespace llarp void Endpoint::BlacklistSNode(const RouterID snode) { - m_state->m_SnodeBlacklist.insert(snode); + _state->m_SnodeBlacklist.insert(snode); } const std::set& Endpoint::SnodeBlacklist() const { - return m_state->m_SnodeBlacklist; + return _state->m_SnodeBlacklist; } const IntroSet& - Endpoint::introSet() const + Endpoint::intro_set() const { - return m_state->m_IntroSet; + return _state->m_IntroSet; } IntroSet& - Endpoint::introSet() + Endpoint::intro_set() { - return m_state->m_IntroSet; + return _state->m_IntroSet; } const ConvoMap& Endpoint::Sessions() const { - return m_state->m_Sessions; + return _state->m_Sessions; } ConvoMap& Endpoint::Sessions() { - return m_state->m_Sessions; + return _state->m_Sessions; } void @@ -2157,10 +2160,10 @@ namespace llarp { if (info.token.empty()) { - m_RemoteAuthInfos.erase(addr); + _remote_auth_infos.erase(addr); return; } - m_RemoteAuthInfos[addr] = std::move(info); + _remote_auth_infos[addr] = std::move(info); } void @@ -2168,7 +2171,7 @@ namespace llarp { if (not exit.IsZero()) LogInfo(Name(), " map ", range, " to exit at ", exit); - m_ExitMap.Insert(range, exit); + _exit_map.Insert(range, exit); } bool Endpoint::HasFlowToService(Address addr) const @@ -2180,22 +2183,22 @@ namespace llarp Endpoint::UnmapExitRange(IPRange range) { // unmap all ranges that fit in the range we gave - m_ExitMap.RemoveIf([&](const auto& item) -> bool { + _exit_map.RemoveIf([&](const auto& item) -> bool { if (not range.Contains(item.first)) return false; LogInfo(Name(), " unmap ", item.first, " exit range mapping"); return true; }); - if (m_ExitMap.Empty()) - m_router->routePoker()->Down(); + if (_exit_map.Empty()) + m_router->route_poker()->put_down(); } void Endpoint::UnmapRangeByExit(IPRange range, std::string exit) { // unmap all ranges that match the given exit when hot swapping - m_ExitMap.RemoveIf([&](const auto& item) -> bool { + _exit_map.RemoveIf([&](const auto& item) -> bool { if ((range.Contains(item.first)) and (item.second.ToString() == exit)) { log::info(logcat, "{} unmap {} range mapping to exit node {}", Name(), item.first, exit); @@ -2204,15 +2207,15 @@ namespace llarp return false; }); - if (m_ExitMap.Empty()) - m_router->routePoker()->Down(); + if (_exit_map.Empty()) + m_router->route_poker()->put_down(); } std::optional Endpoint::MaybeGetAuthInfoForEndpoint(Address remote) { - const auto itr = m_RemoteAuthInfos.find(remote); - if (itr == m_RemoteAuthInfos.end()) + const auto itr = _remote_auth_infos.find(remote); + if (itr == _remote_auth_infos.end()) return std::nullopt; return itr->second; } @@ -2220,7 +2223,7 @@ namespace llarp quic::TunnelManager* Endpoint::GetQUICTunnel() { - return m_quic.get(); + return _tunnel_manager.get(); } } // namespace service diff --git a/llarp/service/endpoint.hpp b/llarp/service/endpoint.hpp index 422d11c1e0..60e6c841c0 100644 --- a/llarp/service/endpoint.hpp +++ b/llarp/service/endpoint.hpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -51,7 +50,7 @@ namespace llarp struct OutboundContext; /// minimum interval for publishing introsets - inline constexpr auto IntrosetPublishInterval = path::intro_path_spread / 2; + inline constexpr auto IntrosetPublishInterval = path::INTRO_PATH_SPREAD / 2; /// how agressively should we retry publishing introset on failure inline constexpr auto IntrosetPublishRetryCooldown = 1s; @@ -62,10 +61,7 @@ namespace llarp /// number of unique snodes we want to talk to do to ons lookups inline constexpr size_t MIN_ENDPOINTS_FOR_LNS_LOOKUP = 2; - struct Endpoint : public path::Builder, - public ILookupHolder, - public IDataHandler, - public EndpointBase + struct Endpoint : public path::Builder, public IDataHandler, public EndpointBase { Endpoint(Router* r, Context* parent); ~Endpoint() override; @@ -189,7 +185,7 @@ namespace llarp } bool - PublishIntroSet(const EncryptedIntroSet& i, Router* r) override; + PublishIntroSet(const EncryptedIntroSet& i) override; bool PublishIntroSetVia( @@ -275,7 +271,7 @@ namespace llarp const Identity& GetIdentity() const { - return m_Identity; + return _identity; } void @@ -295,7 +291,7 @@ namespace llarp std::function result); void - PutLookup(IServiceLookup* lookup, uint64_t txid) override; + PutLookup(IServiceLookup* lookup, uint64_t txid); void HandlePathBuilt(path::Path_ptr path) override; @@ -442,7 +438,7 @@ namespace llarp std::optional> GetHopsForBuildWithEndpoint(RouterID endpoint); - virtual void + void PathBuildStarted(path::Path_ptr path) override; virtual void @@ -502,7 +498,7 @@ namespace llarp SupportsV6() const = 0; void - RegenAndPublishIntroSet(); + regen_and_publish_introset(); IServiceLookup* GenerateLookupByTag(const Tag& tag); @@ -549,26 +545,26 @@ namespace llarp path::Path::UniqueEndpointSet_t GetUniqueEndpointsForLookup() const; - IDataHandler* m_DataHandler = nullptr; - Identity m_Identity; - net::IPRangeMap m_ExitMap; - bool m_PublishIntroSet = true; - std::unique_ptr m_state; - std::shared_ptr m_AuthPolicy; - std::unordered_map m_RemoteAuthInfos; - std::unique_ptr m_quic; + IDataHandler* _data_handler = nullptr; + Identity _identity; + net::IPRangeMap _exit_map; + bool _publish_introset = true; + std::unique_ptr _state; + std::shared_ptr _auth_policy; + std::unordered_map _remote_auth_infos; + std::unique_ptr _tunnel_manager; - /// (lns name, optional exit range, optional auth info) for looking up on startup + /// (ons name, optional exit range, optional auth info) for looking up on startup std::unordered_map, std::optional>> - m_StartupLNSMappings; + _startup_ons_mappings; - RecvPacketQueue_t m_InboundTrafficQueue; + RecvPacketQueue_t _inbound_queue; public: - SendMessageQueue_t m_SendQueue; + SendMessageQueue_t _send_queue; private: - llarp_time_t m_LastIntrosetRegenAttempt = 0s; + llarp_time_t _last_introset_regen_attempt = 0s; protected: void @@ -577,17 +573,17 @@ namespace llarp friend struct EndpointUtil; // clang-format off - const IntroSet& introSet() const; - IntroSet& introSet(); + const IntroSet& intro_set() const; + IntroSet& intro_set(); using ConvoMap = std::unordered_map; const ConvoMap& Sessions() const; ConvoMap& Sessions(); // clang-format on - thread::Queue m_RecvQueue; + thread::Queue _recv_event_queue; /// for rate limiting introset lookups - util::DecayingHashSet
m_IntrosetLookupFilter; + util::DecayingHashSet
_introset_lookup_filter; }; using Endpoint_ptr = std::shared_ptr; diff --git a/llarp/service/identity.cpp b/llarp/service/identity.cpp index 1329ef739c..b7a6d1ffa8 100644 --- a/llarp/service/identity.cpp +++ b/llarp/service/identity.cpp @@ -66,9 +66,9 @@ namespace llarp::service } bool - Identity::Sign(Signature& sig, const llarp_buffer_t& buf) const + Identity::Sign(Signature& sig, uint8_t* buf, size_t size) const { - return CryptoManager::instance()->sign(sig, signkey, buf); + return CryptoManager::instance()->sign(sig, signkey, buf, size); } void @@ -151,12 +151,13 @@ namespace llarp::service } std::optional - Identity::EncryptAndSignIntroSet(const IntroSet& other_i, llarp_time_t now) const + Identity::encrypt_and_sign_introset(const IntroSet& other_i, llarp_time_t now) const { EncryptedIntroSet encrypted; if (other_i.intros.empty()) return std::nullopt; + IntroSet i{other_i}; encrypted.nounce.Randomize(); // set timestamp @@ -164,21 +165,17 @@ namespace llarp::service i.time_signed = now; encrypted.signedAt = now; // set service info - i.addressKeys = pub; + i.address_keys = pub; // set public encryption key i.sntru_pubkey = pq_keypair_to_public(pq); - std::array tmp; - llarp_buffer_t buf{tmp}; auto bte = i.bt_encode(); - buf.write(bte.begin(), bte.end()); - - // rewind and resize buffer - buf.sz = buf.cur - buf.base; - buf.cur = buf.base; - const SharedSecret k{i.addressKeys.Addr()}; - CryptoManager::instance()->xchacha20(buf, k, encrypted.nounce); - encrypted.introsetPayload = buf.copy(); + + const SharedSecret k{i.address_keys.Addr()}; + CryptoManager::instance()->xchacha20( + reinterpret_cast(bte.data()), bte.size(), k, encrypted.nounce); + + std::memcpy(encrypted.introsetPayload.data(), bte.data(), bte.size()); if (not encrypted.Sign(derivedSignKey)) return std::nullopt; diff --git a/llarp/service/identity.hpp b/llarp/service/identity.hpp index dfbf8ed253..7628ad3952 100644 --- a/llarp/service/identity.hpp +++ b/llarp/service/identity.hpp @@ -48,10 +48,10 @@ namespace llarp::service decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf); std::optional - EncryptAndSignIntroSet(const IntroSet& i, llarp_time_t now) const; + encrypt_and_sign_introset(const IntroSet& i, llarp_time_t now) const; bool - Sign(Signature& sig, const llarp_buffer_t& buf) const; + Sign(Signature& sig, uint8_t* buf, size_t size) const; /// zero out all secret key members void diff --git a/llarp/service/info.cpp b/llarp/service/info.cpp index 6ab6101a62..b3622d8bd7 100644 --- a/llarp/service/info.cpp +++ b/llarp/service/info.cpp @@ -12,9 +12,9 @@ namespace llarp::service { bool - ServiceInfo::Verify(const llarp_buffer_t& payload, const Signature& sig) const + ServiceInfo::verify(uint8_t* buf, size_t size, const Signature& sig) const { - return CryptoManager::instance()->verify(signkey, payload, sig); + return CryptoManager::instance()->verify(signkey, buf, size, sig); } bool diff --git a/llarp/service/info.hpp b/llarp/service/info.hpp index 8d9a43e45b..d773870c43 100644 --- a/llarp/service/info.hpp +++ b/llarp/service/info.hpp @@ -34,7 +34,7 @@ namespace llarp::service } bool - Verify(const llarp_buffer_t& payload, const Signature& sig) const; + verify(uint8_t* buf, size_t size, const Signature& sig) const; const PubKey& EncryptionPublicKey() const diff --git a/llarp/service/intro_set.cpp b/llarp/service/intro_set.cpp index 006741c1d8..6e6e38532b 100644 --- a/llarp/service/intro_set.cpp +++ b/llarp/service/intro_set.cpp @@ -14,24 +14,25 @@ namespace llarp::service {"location", derivedSigningKey.ToString()}, {"signedAt", to_json(signedAt)}, {"size", sz}}; } - bool - EncryptedIntroSet::BEncode(llarp_buffer_t* buf) const + std::string + EncryptedIntroSet::bt_encode() const { - if (not bencode_start_dict(buf)) - return false; - if (not BEncodeWriteDictEntry("d", derivedSigningKey, buf)) - return false; - if (not BEncodeWriteDictEntry("n", nounce, buf)) - return false; - if (not BEncodeWriteDictInt("s", signedAt.count(), buf)) - return false; - if (not bencode_write_bytestring(buf, "x", 1)) - return false; - if (not bencode_write_bytestring(buf, introsetPayload.data(), introsetPayload.size())) - return false; - if (not BEncodeWriteDictEntry("z", sig, buf)) - return false; - return bencode_end(buf); + oxenc::bt_dict_producer btdp; + + try + { + btdp.append("d", derivedSigningKey.ToView()); + btdp.append("n", nounce.ToView()); + btdp.append("s", signedAt.count()); + btdp.append("x", oxenc::bt_serialize(introsetPayload)); + btdp.append("z", sig.ToView()); + } + catch (...) + { + log::critical(net_cat, "Error: EncryptedIntroSet failed to bt encode contents!"); + } + + return std::move(btdp).str(); } bool @@ -88,7 +89,8 @@ namespace llarp::service IntroSet i; std::vector payload = introsetPayload; llarp_buffer_t buf(payload); - CryptoManager::instance()->xchacha20(buf, k, nounce); + + CryptoManager::instance()->xchacha20(payload.data(), payload.size(), k, nounce); if (not i.BDecode(&buf)) return {}; return i; @@ -97,7 +99,7 @@ namespace llarp::service bool EncryptedIntroSet::IsExpired(llarp_time_t now) const { - return now >= signedAt + path::default_lifetime; + return now >= signedAt + path::DEFAULT_LIFETIME; } bool @@ -107,33 +109,37 @@ namespace llarp::service if (not k.toPublic(derivedSigningKey)) return false; sig.Zero(); - std::array tmp; - llarp_buffer_t buf(tmp); - if (not BEncode(&buf)) - return false; - buf.sz = buf.cur - buf.base; - buf.cur = buf.base; - if (not CryptoManager::instance()->sign(sig, k, buf)) + auto bte = bt_encode(); + + if (not CryptoManager::instance()->sign( + sig, k, reinterpret_cast(bte.data()), bte.size())) return false; LogDebug("signed encrypted introset: ", *this); return true; } bool - EncryptedIntroSet::Verify(llarp_time_t now) const + EncryptedIntroSet::verify(llarp_time_t now) const { if (IsExpired(now)) return false; - std::array tmp; - llarp_buffer_t buf(tmp); + EncryptedIntroSet copy(*this); copy.sig.Zero(); - if (not copy.BEncode(&buf)) - return false; - LogDebug("verify encrypted introset: ", copy, " sig = ", sig); - buf.sz = buf.cur - buf.base; - buf.cur = buf.base; - return CryptoManager::instance()->verify(derivedSigningKey, buf, sig); + + auto bte = copy.bt_encode(); + return CryptoManager::instance()->verify( + derivedSigningKey, reinterpret_cast(bte.data()), bte.size(), sig); + } + + bool + EncryptedIntroSet::verify(std::string introset, std::string key, std::string sig) + { + return CryptoManager::instance()->verify( + reinterpret_cast(key.data()), + reinterpret_cast(introset.data()), + introset.size(), + reinterpret_cast(sig.data())); } util::StatusObject @@ -175,7 +181,7 @@ namespace llarp::service IntroSet::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) { bool read = false; - if (!BEncodeMaybeReadDictEntry("a", addressKeys, read, key, buf)) + if (!BEncodeMaybeReadDictEntry("a", address_keys, read, key, buf)) return false; if (key.startswith("e")) @@ -262,7 +268,7 @@ namespace llarp::service { { auto subdict = btdp.append_dict("a"); - addressKeys.bt_encode(subdict); + address_keys.bt_encode(subdict); } if (exit_policy) @@ -350,21 +356,15 @@ namespace llarp::service } bool - IntroSet::Verify(llarp_time_t now) const + IntroSet::verify(llarp_time_t now) const { - std::array tmp; - llarp_buffer_t buf{tmp}; IntroSet copy; copy = *this; copy.signature.Zero(); auto bte = copy.bt_encode(); - buf.write(bte.begin(), bte.end()); - // rewind and resize buffer - buf.sz = buf.cur - buf.base; - buf.cur = buf.base; - if (!addressKeys.Verify(buf, signature)) + if (!address_keys.verify(reinterpret_cast(bte.data()), bte.size(), signature)) { return false; } @@ -373,7 +373,7 @@ namespace llarp::service now += MAX_INTROSET_TIME_DELTA; for (const auto& intro : intros) { - if (intro.expiry > now && intro.expiry - now > path::default_lifetime) + if (intro.expiry > now && intro.expiry - now > path::DEFAULT_LIFETIME) { return false; } @@ -395,7 +395,7 @@ namespace llarp::service { return fmt::format( "[IntroSet addressKeys={} intros={{{}}} sntrupKey={} topic={} signedAt={} v={} sig={}]", - addressKeys, + address_keys, fmt::format("{}", fmt::join(intros, ",")), sntru_pubkey, topic, diff --git a/llarp/service/intro_set.hpp b/llarp/service/intro_set.hpp index 7556286dd3..a225b317a3 100644 --- a/llarp/service/intro_set.hpp +++ b/llarp/service/intro_set.hpp @@ -28,7 +28,7 @@ namespace llarp::service struct IntroSet { - ServiceInfo addressKeys; + ServiceInfo address_keys; std::vector intros; PQPubKey sntru_pubkey; Tag topic; @@ -90,7 +90,7 @@ namespace llarp::service decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf); bool - Verify(llarp_time_t now) const; + verify(llarp_time_t now) const; util::StatusObject ExtractStatus() const; @@ -99,14 +99,14 @@ namespace llarp::service inline bool operator<(const IntroSet& lhs, const IntroSet& rhs) { - return lhs.addressKeys < rhs.addressKeys; + return lhs.address_keys < rhs.address_keys; } inline bool operator==(const IntroSet& lhs, const IntroSet& rhs) { return std::tie( - lhs.addressKeys, + lhs.address_keys, lhs.intros, lhs.sntru_pubkey, lhs.time_signed, @@ -114,7 +114,7 @@ namespace llarp::service lhs.topic, lhs.signature) == std::tie( - rhs.addressKeys, + rhs.address_keys, rhs.intros, rhs.sntru_pubkey, rhs.time_signed, @@ -132,11 +132,9 @@ namespace llarp::service /// public version of the introset that is encrypted struct EncryptedIntroSet { - using Payload_t = std::vector; - PubKey derivedSigningKey; llarp_time_t signedAt = 0s; - Payload_t introsetPayload; + std::vector introsetPayload; TunnelNonce nounce; std::optional topic; Signature sig; @@ -147,8 +145,8 @@ namespace llarp::service bool IsExpired(llarp_time_t now) const; - bool - BEncode(llarp_buffer_t* buf) const; + std::string + bt_encode() const; bool BDecode(llarp_buffer_t* buf) @@ -164,7 +162,10 @@ namespace llarp::service /// verify signature and timestamp bool - Verify(llarp_time_t now) const; + verify(llarp_time_t now) const; + + static bool + verify(std::string introset, std::string key, std::string sig); std::string ToString() const; diff --git a/llarp/service/lookup.cpp b/llarp/service/lookup.cpp deleted file mode 100644 index ff6266a858..0000000000 --- a/llarp/service/lookup.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "lookup.hpp" - -#include -#include -#include -#include - -namespace llarp -{ - struct Router; - - namespace service - { - IServiceLookup::IServiceLookup( - ILookupHolder* p, uint64_t tx, std::string n, llarp_time_t timeout) - : m_parent(p), txid(tx), name(std::move(n)), m_created{time_now_ms()}, m_timeout{timeout} - { - p->PutLookup(this, tx); - } - - bool - IServiceLookup::SendRequestViaPath(path::Path_ptr path, Router* r) - { - auto msg = BuildRequestMessage(); - if (!msg) - return false; - r->loop()->call( - [path = std::move(path), msg = std::move(msg), r] { path->SendRoutingMessage(*msg, r); }); - return true; - } - } // namespace service -} // namespace llarp diff --git a/llarp/service/lookup.hpp b/llarp/service/lookup.hpp deleted file mode 100644 index 8a15a48b0e..0000000000 --- a/llarp/service/lookup.hpp +++ /dev/null @@ -1,113 +0,0 @@ -#pragma once - -#include -#include "intro_set.hpp" -#include - -#include - -#include - -namespace llarp -{ - // forward declare - namespace path - { - struct Path; - } - - namespace service - { - struct ILookupHolder; - - constexpr size_t MaxConcurrentLookups = size_t(16); - - struct IServiceLookup - { - IServiceLookup() = delete; - virtual ~IServiceLookup() = default; - - /// handle lookup result for introsets - virtual bool - HandleIntrosetResponse(const std::set&) - { - return false; - } - - /// handle lookup result for introsets - virtual bool - HandleNameResponse(std::optional
) - { - return false; - } - - virtual void - HandleTimeout() - { - HandleIntrosetResponse({}); - } - - /// determine if this request has timed out - bool - IsTimedOut(llarp_time_t now) const - { - return TimeLeft(now) == 0ms; - } - - /// return how long this request has left to be fufilled - llarp_time_t - TimeLeft(llarp_time_t now) const - { - if (now > (m_created + m_timeout)) - return 0s; - return now - (m_created + m_timeout); - } - - /// build request message for service lookup - virtual std::shared_ptr - BuildRequestMessage() = 0; - - /// build a new request message and send it via a path - virtual bool - SendRequestViaPath(path::Path_ptr p, Router* r); - - ILookupHolder* m_parent; - uint64_t txid; - const std::string name; - RouterID endpoint; - - /// return true if this lookup is for a remote address - virtual bool - IsFor(EndpointBase::AddressVariant_t) const - { - return false; - } - - util::StatusObject - ExtractStatus() const - { - auto now = time_now_ms(); - util::StatusObject obj{ - {"txid", txid}, - {"endpoint", endpoint.ToHex()}, - {"name", name}, - {"timedOut", IsTimedOut(now)}, - {"createdAt", m_created.count()}}; - return obj; - } - - protected: - IServiceLookup( - ILookupHolder* parent, uint64_t tx, std::string name, llarp_time_t timeout = 10s); - - const llarp_time_t m_created, m_timeout; - }; - - struct ILookupHolder - { - virtual void - PutLookup(IServiceLookup* l, uint64_t txid) = 0; - }; - - } // namespace service -} // namespace llarp diff --git a/llarp/service/outbound_context.cpp b/llarp/service/outbound_context.cpp index 672f00cf9c..4db279f901 100644 --- a/llarp/service/outbound_context.cpp +++ b/llarp/service/outbound_context.cpp @@ -54,9 +54,9 @@ namespace llarp::service OutboundContext::OutboundContext(const IntroSet& introset, Endpoint* parent) : path::Builder{parent->router(), OutboundContextNumPaths, parent->numHops} - , SendContext{introset.addressKeys, {}, this, parent} - , location{introset.addressKeys.Addr().ToKey()} - , addr{introset.addressKeys.Addr()} + , SendContext{introset.address_keys, {}, this, parent} + , location{introset.address_keys.Addr().ToKey()} + , addr{introset.address_keys.Addr()} , currentIntroSet{introset} { @@ -88,7 +88,7 @@ namespace llarp::service if (remoteIntro != m_NextIntro) { remoteIntro = m_NextIntro; - m_DataHandler->PutSenderFor(currentConvoTag, currentIntroSet.addressKeys, false); + m_DataHandler->PutSenderFor(currentConvoTag, currentIntroSet.address_keys, false); m_DataHandler->PutIntroFor(currentConvoTag, remoteIntro); ShiftIntroRouter(m_NextIntro.router); // if we have not made a handshake to the remote endpoint do so @@ -264,7 +264,7 @@ namespace llarp::service frame->flag = 0; generatedIntro = true; // ensure we have a sender put for this convo tag - m_DataHandler->PutSenderFor(currentConvoTag, currentIntroSet.addressKeys, false); + m_DataHandler->PutSenderFor(currentConvoTag, currentIntroSet.address_keys, false); // encrypt frame async m_Endpoint->router()->queue_work([ex, frame] { return AsyncKeyExchange::Encrypt(ex, frame); }); @@ -274,7 +274,7 @@ namespace llarp::service std::string OutboundContext::Name() const { - return "OBContext:" + currentIntroSet.addressKeys.Addr().ToString(); + return "OBContext:" + currentIntroSet.address_keys.Addr().ToString(); } void @@ -366,8 +366,8 @@ namespace llarp::service } // check for stale intros // update the introset if we think we need to - if (currentIntroSet.HasStaleIntros(now, path::intro_path_spread) - or remoteIntro.ExpiresSoon(now, path::intro_path_spread)) + if (currentIntroSet.HasStaleIntros(now, path::INTRO_PATH_SPREAD) + or remoteIntro.ExpiresSoon(now, path::INTRO_PATH_SPREAD)) { UpdateIntroSet(); ShiftIntroduction(false); @@ -381,7 +381,7 @@ namespace llarp::service std::vector otherIntros; ForEachPath([now, router = remoteIntro.router, &otherIntros](auto path) { if (path and path->IsReady() and path->Endpoint() != router - and not path->ExpiresSoon(now, path::intro_path_spread)) + and not path->ExpiresSoon(now, path::INTRO_PATH_SPREAD)) { otherIntros.emplace_back(path->intro); } @@ -485,7 +485,7 @@ namespace llarp::service ForEachPath([now, this, &havePathToNextIntro, &numValidPaths](path::Path_ptr path) { if (not path->IsReady()) return; - if (not path->intro.ExpiresSoon(now, path::default_lifetime - path::intro_path_spread)) + if (not path->intro.ExpiresSoon(now, path::DEFAULT_LIFETIME - path::INTRO_PATH_SPREAD)) { numValidPaths++; if (path->intro.router == m_NextIntro.router) @@ -699,7 +699,7 @@ namespace llarp::service { LogWarn("invalidating convotag T=", frame.convo_tag); m_Endpoint->RemoveConvoTag(frame.convo_tag); - m_Endpoint->m_SendQueue.tryPushBack( + m_Endpoint->_send_queue.tryPushBack( SendEvent_t{std::make_shared(f, frame.path_id), p}); } } diff --git a/llarp/service/protocol.cpp b/llarp/service/protocol.cpp index d3d4d63e72..7f4166abd5 100644 --- a/llarp/service/protocol.cpp +++ b/llarp/service/protocol.cpp @@ -193,10 +193,10 @@ namespace llarp::service ProtocolFrameMessage::DecryptPayloadInto( const SharedSecret& sharedkey, ProtocolMessage& msg) const { - Encrypted_t tmp = enc; - auto buf = tmp.Buffer(); - CryptoManager::instance()->xchacha20(*buf, sharedkey, nonce); - return bencode_decode_dict(msg, buf); + Encrypted<2048> tmp = enc; + CryptoManager::instance()->xchacha20(tmp.data(), tmp.size(), sharedkey, nonce); + + return bencode_decode_dict(msg, tmp.Buffer()); } bool @@ -213,7 +213,7 @@ namespace llarp::service buf.sz = buf.cur - buf.base; buf.cur = buf.base; // sign - return localIdent.Sign(sig, buf); + return localIdent.Sign(sig, reinterpret_cast(bte.data()), bte.size()); } bool @@ -224,25 +224,18 @@ namespace llarp::service llarp_buffer_t buf1(tmp); // encode message auto bte1 = msg.bt_encode(); - buf1.write(bte1.begin(), bte1.end()); - // rewind - buf1.sz = buf1.cur - buf1.base; - buf1.cur = buf1.base; // encrypt - CryptoManager::instance()->xchacha20(buf1, sessionKey, nonce); + CryptoManager::instance()->xchacha20( + reinterpret_cast(bte1.data()), bte1.size(), sessionKey, nonce); // put encrypted buffer + std::memcpy(enc.data(), bte1.data(), bte1.size()); enc = buf1; // zero out signature sig.Zero(); - llarp_buffer_t buf2(tmp); auto bte2 = bt_encode(); - buf2.write(bte2.begin(), bte2.end()); - // rewind - buf2.sz = buf2.cur - buf2.base; - buf2.cur = buf2.base; // sign - if (!localIdent.Sign(sig, buf2)) + if (!localIdent.Sign(sig, reinterpret_cast(bte2.data()), bte2.size())) { LogError("failed to sign? wtf?!"); return false; @@ -280,7 +273,7 @@ namespace llarp::service { auto crypto = CryptoManager::instance(); SharedSecret K; - SharedSecret sharedKey; + SharedSecret shared_key; // copy ProtocolFrameMessage frame(self->frame); if (!crypto->pqe_decrypt( @@ -291,15 +284,21 @@ namespace llarp::service return; } // decrypt - auto buf = frame.enc.Buffer(); - crypto->xchacha20(*buf, K, self->frame.nonce); - if (!bencode_decode_dict(*self->msg, buf)) + // auto buf = frame.enc.Buffer(); + uint8_t* buf = frame.enc.data(); + size_t sz = frame.enc.size(); + crypto->xchacha20(buf, sz, K, self->frame.nonce); + + auto bte = self->msg->bt_encode(); + + if (bte.empty()) { - LogError("failed to decode inner protocol message"); + log::error(logcat, "Failed to decode inner protocol message"); DumpBuffer(*buf); self->msg.reset(); return; } + // verify signature of outer message after we parsed the inner message if (!self->frame.Verify(self->msg->sender)) { @@ -323,23 +322,24 @@ namespace llarp::service } // PKE (A, B, N) - SharedSecret sharedSecret; + SharedSecret shared_secret; path_dh_func dh_server = util::memFn(&Crypto::dh_server, CryptoManager::instance()); if (!self->m_LocalIdentity.KeyExchange( - dh_server, sharedSecret, self->msg->sender, self->frame.nonce)) + dh_server, shared_secret, self->msg->sender, self->frame.nonce)) { LogError("x25519 key exchange failed"); Dump(self->frame); self->msg.reset(); return; } - std::array tmp; + std::array tmp; // K - std::copy(K.begin(), K.end(), tmp.begin()); + std::memcpy(tmp.begin(), K.begin(), K.size()); // S = HS( K + PKE( A, B, N)) - std::copy(sharedSecret.begin(), sharedSecret.end(), tmp.begin() + 32); - crypto->shorthash(sharedKey, llarp_buffer_t(tmp)); + std::memcpy(tmp.begin() + 32, shared_secret.begin(), shared_secret.size()); + + crypto->shorthash(shared_key, tmp.data(), tmp.size()); std::shared_ptr msg = std::move(self->msg); path::Path_ptr path = std::move(self->path); @@ -347,7 +347,7 @@ namespace llarp::service msg->handler = self->handler; self->handler->AsyncProcessAuthMessage( msg, - [path, msg, from, handler = self->handler, fromIntro = self->fromIntro, sharedKey]( + [path, msg, from, handler = self->handler, fromIntro = self->fromIntro, shared_key]( AuthResult result) { if (result.code == AuthResultCode::eAuthAccepted) { @@ -360,7 +360,7 @@ namespace llarp::service handler->PutSenderFor(msg->tag, msg->sender, true); } handler->PutReplyIntroFor(msg->tag, msg->introReply); - handler->PutCachedSessionKeyFor(msg->tag, sharedKey); + handler->PutCachedSessionKeyFor(msg->tag, shared_key); handler->SendAuthResult(path, from, msg->tag, result); LogInfo("auth okay for T=", msg->tag, " from ", msg->sender.Addr()); ProtocolMessage::ProcessAsync(path, from, msg); @@ -489,21 +489,10 @@ namespace llarp::service ProtocolFrameMessage::Verify(const ServiceInfo& svc) const { ProtocolFrameMessage copy(*this); - // save signature - // zero out signature for verify copy.sig.Zero(); - // serialize - std::array tmp; - llarp_buffer_t buf(tmp); auto bte = copy.bt_encode(); - buf.write(bte.begin(), bte.end()); - - // rewind buffer - buf.sz = buf.cur - buf.base; - buf.cur = buf.base; - // verify - return svc.Verify(buf, sig); + return svc.verify(reinterpret_cast(bte.data()), bte.size(), sig); } bool diff --git a/llarp/service/protocol.hpp b/llarp/service/protocol.hpp index 00eeea0e87..074acd95fa 100644 --- a/llarp/service/protocol.hpp +++ b/llarp/service/protocol.hpp @@ -44,7 +44,7 @@ namespace llarp ~ProtocolMessage(); ProtocolType proto = ProtocolType::TrafficV4; llarp_time_t queued = 0s; - std::vector payload; // encrypted AbstractLinkMessage + std::vector payload; // encrypted AbstractLinkMessage Introduction introReply; ServiceInfo sender; Endpoint* handler = nullptr; @@ -78,9 +78,8 @@ namespace llarp /// outer message struct ProtocolFrameMessage final : public routing::AbstractRoutingMessage { - using Encrypted_t = Encrypted<2048>; PQCipherBlock cipher; - Encrypted_t enc; + Encrypted<2048> enc; uint64_t flag; // set to indicate in plaintext a nack, aka "dont try again" KeyExchangeNonce nonce; Signature sig; diff --git a/llarp/service/sendcontext.cpp b/llarp/service/sendcontext.cpp index d0ca164643..5f400b5be3 100644 --- a/llarp/service/sendcontext.cpp +++ b/llarp/service/sendcontext.cpp @@ -48,7 +48,7 @@ namespace llarp::service msg->sequence_number = path->NextSeqNo(); if (path->SendRoutingMessage(*msg, r)) { - lastGoodSend = r->Now(); + lastGoodSend = r->now(); flushpaths.emplace(path); m_Endpoint->ConvoTagTX(msg->protocol_frame_msg.convo_tag); const auto rtt = (path->intro.latency + remoteIntro.latency) * 2; diff --git a/llarp/service/sendcontext.hpp b/llarp/service/sendcontext.hpp index ffddff0b4a..460cd0467f 100644 --- a/llarp/service/sendcontext.hpp +++ b/llarp/service/sendcontext.hpp @@ -44,9 +44,9 @@ namespace llarp uint64_t sequenceNo = 0; llarp_time_t lastGoodSend = 0s; const llarp_time_t createdAt; - llarp_time_t sendTimeout = path::build_timeout; - llarp_time_t connectTimeout = path::build_timeout * 2; - llarp_time_t shiftTimeout = (path::build_timeout * 5) / 2; + llarp_time_t sendTimeout = path::BUILD_TIMEOUT; + llarp_time_t connectTimeout = path::BUILD_TIMEOUT * 2; + llarp_time_t shiftTimeout = (path::BUILD_TIMEOUT * 5) / 2; llarp_time_t estimatedRTT = 0s; bool markedBad = false; using Msg_ptr = std::shared_ptr; diff --git a/llarp/service/session.hpp b/llarp/service/session.hpp index feb3aee4f0..3631182ebb 100644 --- a/llarp/service/session.hpp +++ b/llarp/service/session.hpp @@ -11,7 +11,7 @@ namespace llarp { namespace service { - static constexpr auto SessionLifetime = path::default_lifetime * 2; + static constexpr auto SessionLifetime = path::DEFAULT_LIFETIME * 2; struct Session { diff --git a/llarp/util/aligned.hpp b/llarp/util/aligned.hpp index 46768b318e..3f6549041c 100644 --- a/llarp/util/aligned.hpp +++ b/llarp/util/aligned.hpp @@ -42,8 +42,6 @@ namespace llarp static constexpr size_t SIZE = sz; - using Data = std::array; - virtual ~AlignedBuffer() = default; AlignedBuffer() @@ -56,7 +54,7 @@ namespace llarp *this = data; } - explicit AlignedBuffer(const Data& buf) + explicit AlignedBuffer(const std::array& buf) { m_data = buf; } @@ -159,13 +157,13 @@ namespace llarp m_data.fill(f); } - Data& + std::array& as_array() { return m_data; } - const Data& + const std::array& as_array() const { return m_data; @@ -207,25 +205,25 @@ namespace llarp randombytes(data(), SIZE); } - typename Data::iterator + typename std::array::iterator begin() { return m_data.begin(); } - typename Data::iterator + typename std::array::iterator end() { return m_data.end(); } - typename Data::const_iterator + typename std::array::const_iterator begin() const { return m_data.cbegin(); } - typename Data::const_iterator + typename std::array::const_iterator end() const { return m_data.cend(); @@ -294,7 +292,7 @@ namespace llarp } private: - Data m_data; + std::array m_data; }; namespace detail diff --git a/llarp/util/buffer.hpp b/llarp/util/buffer.hpp index 3ba3140568..b995d85f92 100644 --- a/llarp/util/buffer.hpp +++ b/llarp/util/buffer.hpp @@ -20,6 +20,8 @@ namespace llarp { using byte_view_t = std::basic_string_view; + using ustring = std::basic_string; + using ustring_view = std::basic_string_view; using bstring = std::basic_string; using bstring_view = std::basic_string_view; From ad007ff832e7130c2a5067f479c23a68a0cc57d4 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Fri, 29 Sep 2023 10:28:30 -0700 Subject: [PATCH 041/312] libquic/oxen-mq/oxenc version bumps --- external/oxen-libquic | 2 +- external/oxen-mq | 2 +- llarp/CMakeLists.txt | 1 - llarp/dht/messages/findintro.cpp | 21 +- llarp/dht/messages/findname.cpp | 10 +- llarp/dht/messages/findrouter.cpp | 2 +- llarp/dht/messages/pubintro.cpp | 1 - llarp/link/link_manager.cpp | 318 ++++++++++++++++++++++++------ llarp/link/link_manager.hpp | 30 ++- llarp/rpc/lokid_rpc_client.cpp | 2 +- llarp/rpc/lokid_rpc_client.hpp | 2 +- 11 files changed, 298 insertions(+), 93 deletions(-) diff --git a/external/oxen-libquic b/external/oxen-libquic index 26a269e6ba..33982d24a3 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit 26a269e6bab6f7a03503b8aae72d6a153f9ac345 +Subproject commit 33982d24a380268933ebea33976ad806e5c4e4bb diff --git a/external/oxen-mq b/external/oxen-mq index e1b66ced48..68b3420bad 160000 --- a/external/oxen-mq +++ b/external/oxen-mq @@ -1 +1 @@ -Subproject commit e1b66ced4803e1b0cb05ed554cb5fc82b14c13c0 +Subproject commit 68b3420bad5f0384f06d378b89ccdc06aba07465 diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index a8ded040a4..9958a07c51 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -283,7 +283,6 @@ add_library(lokinet-service-deprecated-kitchensink service/intro_set.cpp service/intro.cpp service/lns_tracker.cpp - service/lookup.cpp service/name.cpp service/outbound_context.cpp service/protocol.cpp diff --git a/llarp/dht/messages/findintro.cpp b/llarp/dht/messages/findintro.cpp index 98a7f6ad97..a61e4f61e6 100644 --- a/llarp/dht/messages/findintro.cpp +++ b/llarp/dht/messages/findintro.cpp @@ -1,4 +1,3 @@ -#include #include "findintro.hpp" #include "gotintro.hpp" #include @@ -20,6 +19,9 @@ namespace llarp::dht if (!BEncodeMaybeReadDictInt("O", relayOrder, read, k, val)) return false; + if (!BEncodeMaybeReadDictInt("R", relayed, read, k, val)) + return false; + if (!BEncodeMaybeReadDictEntry("S", location, read, k, val)) return false; @@ -38,17 +40,10 @@ namespace llarp::dht try { btdp.append("A", "F"); - if (tagName.Empty()) - { - btdp.append("O", relayOrder); - btdp.append("S", location.ToView()); - } - else - { - btdp.append("N", tagName.ToView()); - btdp.append("O", relayOrder); - } - + btdp.append("N", tagName.ToView()); + btdp.append("O", relayOrder); + btdp.append("R", relayed ? 1 : 0); + btdp.append("S", location.ToView()); btdp.append("T", txID); btdp.append("V", llarp::constants::proto_version); } @@ -92,7 +87,7 @@ namespace llarp::dht } auto closestRCs = - dht.GetRouter()->node_db()->FindManyClosestTo(location, IntroSetStorageRedundancy); + dht.GetRouter()->node_db()->FindManyClosestTo(location, INTROSET_STORAGE_REDUNDANCY); if (closestRCs.size() <= relayOrder) { diff --git a/llarp/dht/messages/findname.cpp b/llarp/dht/messages/findname.cpp index abab5686a6..a8d0bbebf2 100644 --- a/llarp/dht/messages/findname.cpp +++ b/llarp/dht/messages/findname.cpp @@ -1,6 +1,5 @@ #include "findname.hpp" #include -#include #include "gotname.hpp" #include #include @@ -44,13 +43,14 @@ namespace llarp::dht bool FindNameMessage::handle_message( - AbstractDHTMessageHandler&, std::vector>&) const + AbstractDHTMessageHandler& dht, + std::vector>& replies) const { - /* (void)replies; + (void)replies; auto router = dht.GetRouter(); if (pathID.IsZero() or not router->IsServiceNode()) return false; - router->rpc_client()->LookupLNSNameHash( + router->rpc_client()->lookup_ons_hash( NameHash, [router, pathID = pathID, TxID = TxID](auto maybe) { auto path = router->path_context().GetPathForTransfer(pathID); if (path == nullptr) @@ -66,7 +66,7 @@ namespace llarp::dht new GotNameMessage(dht::Key_t{}, TxID, service::EncryptedName{})); } path->SendRoutingMessage(msg, router); - }); */ + }); return true; } diff --git a/llarp/dht/messages/findrouter.cpp b/llarp/dht/messages/findrouter.cpp index a226723046..627019f1c9 100644 --- a/llarp/dht/messages/findrouter.cpp +++ b/llarp/dht/messages/findrouter.cpp @@ -59,7 +59,7 @@ namespace llarp::dht try { btdp.append("A", "R"); - btdp.append("T", exploratory ? 1 : 0); + btdp.append("E", exploratory ? 1 : 0); btdp.append("I", iterative ? 1 : 0); btdp.append("K", targetKey.ToView()); btdp.append("T", txid); diff --git a/llarp/dht/messages/pubintro.cpp b/llarp/dht/messages/pubintro.cpp index f8ed8a079b..36c43a2a27 100644 --- a/llarp/dht/messages/pubintro.cpp +++ b/llarp/dht/messages/pubintro.cpp @@ -1,6 +1,5 @@ #include "pubintro.hpp" -#include #include "gotintro.hpp" #include #include diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index a8239d356e..c13ffb6056 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -184,7 +184,7 @@ namespace llarp const RouterID& remote, std::string endpoint, std::string body, - std::function func) + std::function func) { if (is_stopping) return false; @@ -492,70 +492,97 @@ namespace llarp void LinkManager::handle_find_name(oxen::quic::message m) { + std::string name_hash; + uint64_t tx_id; + try { oxenc::bt_dict_consumer btdp{m.body()}; - std::string name_hash, tx_id; - - if (btdp.skip_until("H")) - name_hash = btdp.consume_string(); - - if (btdp.skip_until("T")) - tx_id = btdp.consume_string(); - router.rpc_client()->LookupLNSNameHash(name_hash, [](auto /* maybe */) { - - }); + safe_fetch_value(btdp, "H", name_hash); + safe_fetch_value(btdp, "T", tx_id); } catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); m.respond("ERROR", true); } + + router.rpc_client()->lookup_ons_hash( + name_hash, [this, msg = std::move(m)](std::optional maybe) mutable { + + if (maybe.has_value()) + msg.respond(serialize_response(true, {"NAME", maybe->ciphertext.c_str()})); + else + msg.respond(serialize_response(false, {"STATUS", "NOT FOUND"}), true); + }); } - void - LinkManager::handle_find_router(oxen::quic::message) - {} + std::string + LinkManager::serialize_response(bool success, oxenc::bt_dict supplement) + { + return oxenc::bt_serialize(oxenc::bt_list{(success) ? 1 : 0, supplement}); + } void - LinkManager::handle_publish_intro(oxen::quic::message m) + LinkManager::handle_find_router(oxen::quic::message m) { - std::string introset, tx_id, derived_signing_key, sig; - uint64_t is_relayed, relay_order; - std::chrono::milliseconds signed_at; + ustring target_key; + uint64_t is_exploratory, is_iterative, tx_id; try { - oxenc::bt_dict_consumer btdc_a{m.body()}; + oxenc::bt_dict_consumer btdc{m.body()}; - if (btdc_a.skip_until("I")) - introset = btdc_a.consume_string(); + - if (btdc_a.skip_until("O")) - relay_order = btdc_a.consume_integer(); + safe_fetch_value(btdc, "E", is_exploratory); + safe_fetch_value(btdc, "I", is_iterative); + safe_fetch_value(btdc, "K", target_key); + safe_fetch_value(btdc, "T", tx_id); + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + return; + } - if (btdc_a.skip_until("R")) - is_relayed = btdc_a.consume_integer(); + // TODO: do we need a replacement for dht.AllowTransit() etc here? - if (btdc_a.skip_until("T")) - tx_id = btdc_a.consume_string(); + // TODO: do we need a replacement for dht.pendingIntroSetLookups() etc here? - oxenc::bt_dict_consumer btdc_b{introset}; + const auto target_addr = dht::Key_t{}; - if (btdc_b.skip_until("d")) - derived_signing_key = btdc_b.consume_string(); + + } + + void + LinkManager::handle_publish_intro(oxen::quic::message m) + { + std::string introset, derived_signing_key, sig; + uint64_t is_relayed, relay_order, tx_id; + std::chrono::milliseconds signed_at; + + try + { + oxenc::bt_dict_consumer btdc_a{m.body()}; + + safe_fetch_value(btdc_a, "I", introset); + safe_fetch_value(btdc_a, "O", relay_order); + safe_fetch_value(btdc_a, "R", is_relayed); + safe_fetch_value(btdc_a, "T", tx_id); - if (btdc_b.skip_until("s")) - signed_at = std::chrono::milliseconds{btdc_b.consume_integer()}; + oxenc::bt_dict_consumer btdc_b{introset}; - if (btdc_b.skip_until("z")) - sig = btdc_b.consume_string(); + safe_fetch_value(btdc_b, "d", derived_signing_key); + safe_fetch_value(btdc_b, "s", signed_at); + safe_fetch_value(btdc_b, "z", sig); } catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond("ERROR", true); + m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); return; } @@ -566,14 +593,14 @@ namespace llarp if (not service::EncryptedIntroSet::verify(introset, derived_signing_key, sig)) { log::error(link_cat, "Received PublishIntroMessage with invalid introset: {}", introset); - m.respond("INVALID INTROSET", true); + m.respond(serialize_response(false, {"STATUS", "INVALID INTROSET"}), true); return; } if (now + service::MAX_INTROSET_TIME_DELTA > signed_at + path::DEFAULT_LIFETIME) { log::error(link_cat, "Received PublishIntroMessage with expired introset: {}", introset); - m.respond("EXPIRED INTROSET", true); + m.respond(serialize_response(false, {"STATUS", "EXPIRED INTROSET"}), true); return; } @@ -583,7 +610,7 @@ namespace llarp { log::error( link_cat, "Received PublishIntroMessage but only know {} nodes", closest_rcs.size()); - m.respond("INSUFFICIENT NODES", true); + m.respond(serialize_response(false, {"STATUS", "INSUFFICIENT NODES"}), true); return; } @@ -593,7 +620,7 @@ namespace llarp { log::error( link_cat, "Received PublishIntroMessage with invalide relay order: {}", relay_order); - m.respond("INVALID ORDER", true); + m.respond(serialize_response(false, {"STATUS", "INVALID ORDER"}), true); return; } @@ -611,9 +638,7 @@ namespace llarp // TODO: replace this concept // dht->services()->PutNode(introset); - - // TODO: should this be a call to send_control_message instead? - m.respond("got_intro"); + m.respond(serialize_response(true)); } else { @@ -621,8 +646,8 @@ namespace llarp link_cat, "Received PublishIntroMessage; propagating to peer index {}", relay_order); send_control_message( - peer_key, "publish_intro", std::move(introset), [this](oxen::quic::message m) { - return handle_got_intro(std::move(m)); + peer_key, "publish_intro", m.body_str(), [this](oxen::quic::message m) { + return handle_publish_intro_response(std::move(m)); }); } @@ -644,9 +669,9 @@ namespace llarp if (rc_index >= 0) { log::info(link_cat, "Received PublishIntroMessage for {} (TXID: {}); we are candidate {}"); - - // TODO: should this be a call to send_control_message instead? - m.respond("got_intro"); + // TODO: replace this concept + // dht->services()->PutNode(introset); + m.respond(serialize_response(true)); } else log::warning( @@ -656,38 +681,201 @@ namespace llarp } void - LinkManager::handle_find_intro(oxen::quic::message) - {} + LinkManager::handle_find_intro(oxen::quic::message m) + { + std::string tag_name, location; + uint64_t tx_id, relay_order, is_relayed; + + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + + safe_fetch_value(btdc, "N", tag_name); + safe_fetch_value(btdc, "O", relay_order); + safe_fetch_value(btdc, "R", is_relayed); + safe_fetch_value(btdc, "S", location); + safe_fetch_value(btdc, "T", tx_id); + safe_fetch_value(btdc, "N", tag_name); + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + return; + } + + // TODO: do we need a replacement for dht.pendingIntroSetLookups() etc here? + + const auto addr = dht::Key_t{reinterpret_cast(location.data())}; + + if (is_relayed) + { + if (relay_order >= INTROSET_STORAGE_REDUNDANCY) + { + log::warning( + link_cat, "Received FindIntroMessage with invalid relay order: {}", relay_order); + m.respond(serialize_response(false, {"STATUS", "INVALID ORDER"}), true); + return; + } + + auto closest_rcs = router.node_db()->FindManyClosestTo(addr, INTROSET_STORAGE_REDUNDANCY); + + if (closest_rcs.size() != INTROSET_STORAGE_REDUNDANCY) + { + log::error( + link_cat, "Received FindIntroMessage but only know {} nodes", closest_rcs.size()); + m.respond(serialize_response(false, {"STATUS", "INSUFFICIENT NODES"}), true); + return; + } + + log::info(link_cat, "Relaying FindIntroMessage for {} (TXID: {})", addr, tx_id); + + const auto& peer_rc = closest_rcs[relay_order]; + const auto& peer_key = peer_rc.pubkey; + + send_control_message(peer_key, "find_intro", m.body_str(), [this](oxen::quic::message m) { + return handle_find_intro_response(std::move(m)); + }); + return; + } + + // TODO: replace this concept and add it to the response + // const auto maybe = dht.GetIntroSetByLocation(location); + m.respond(serialize_response(true, {"INTROSET", ""})); + } void - LinkManager::handle_path_confirm(oxen::quic::message) - {} + LinkManager::handle_path_confirm(oxen::quic::message m) + { + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + return; + } + } void - LinkManager::handle_path_latency(oxen::quic::message) - {} + LinkManager::handle_path_latency(oxen::quic::message m) + { + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + return; + } + } void - LinkManager::handle_update_exit(oxen::quic::message) - {} + LinkManager::handle_update_exit(oxen::quic::message m) + { + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + return; + } + } void - LinkManager::handle_obtain_exit(oxen::quic::message) - {} + LinkManager::handle_obtain_exit(oxen::quic::message m) + { + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + return; + } + } void - LinkManager::handle_close_exit(oxen::quic::message) - {} + LinkManager::handle_close_exit(oxen::quic::message m) + { + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + return; + } + } void - LinkManager::handle_got_intro(oxen::quic::message) - {} + LinkManager::handle_publish_intro_response(oxen::quic::message m) + { + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + return; + } + } void - LinkManager::handle_got_name(oxen::quic::message) - {} + LinkManager::handle_find_name_response(oxen::quic::message m) + { + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + return; + } + } void - LinkManager::handle_got_router(oxen::quic::message) - {} + LinkManager::handle_find_router_response(oxen::quic::message m) + { + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + return; + } + } + + void + LinkManager::handle_find_intro_response(oxen::quic::message m) + { + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + return; + } + } } // namespace llarp diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 43dca97616..519a4dc8de 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -303,9 +303,33 @@ namespace llarp {"close_exit", &LinkManager::handle_close_exit}}; // response handling functions - void handle_got_intro(oxen::quic::message); - void handle_got_name(oxen::quic::message); - void handle_got_router(oxen::quic::message); + void handle_publish_intro_response(oxen::quic::message); + void handle_find_name_response(oxen::quic::message); // not used? + void handle_find_router_response(oxen::quic::message); + void handle_find_intro_response(oxen::quic::message); + + std::string + serialize_response(bool success, oxenc::bt_dict supplement = {}); + + /** Searches the bt dict held by a dict consumer for a specific key `k`, setting + the value at `dest` and throwing if not found. This is equivalent to calling: + + if (not bdca.skip_until(k)) + throw std::invalid_argument{"..."}; + dest = btdc.consume_integer() OR btdc.consume_string(); + */ + template + void + safe_fetch_value(oxenc::bt_dict_consumer& btdc, const char* k, T& dest) + { + if (not btdc.skip_until(k)) + throw std::invalid_argument{""}; + + if constexpr (std::is_integral_v) + dest = btdc.consume_integer(); + else + dest = btdc.consume_string(); + } }; namespace link diff --git a/llarp/rpc/lokid_rpc_client.cpp b/llarp/rpc/lokid_rpc_client.cpp index 7e8e99cab0..001a7c8a84 100644 --- a/llarp/rpc/lokid_rpc_client.cpp +++ b/llarp/rpc/lokid_rpc_client.cpp @@ -351,7 +351,7 @@ namespace llarp::rpc } void - LokidRpcClient::LookupLNSNameHash( + LokidRpcClient::lookup_ons_hash( std::string namehash, std::function)> resultHandler) { diff --git a/llarp/rpc/lokid_rpc_client.hpp b/llarp/rpc/lokid_rpc_client.hpp index 0cef8a90b5..306c59b117 100644 --- a/llarp/rpc/lokid_rpc_client.hpp +++ b/llarp/rpc/lokid_rpc_client.hpp @@ -36,7 +36,7 @@ namespace llarp } void - LookupLNSNameHash( + lookup_ons_hash( std::string namehash, std::function)> resultHandler); From 1a9f97720846d215e8bf5dfb89aec769f4ad7bdf Mon Sep 17 00:00:00 2001 From: dr7ana Date: Fri, 29 Sep 2023 14:00:13 -0700 Subject: [PATCH 042/312] Message method implementation continued - tons of surrounding stupid refactoring required --- llarp/CMakeLists.txt | 17 +- llarp/context.cpp | 5 +- llarp/crypto/types.cpp | 8 + llarp/crypto/types.hpp | 3 + llarp/dht/message.hpp | 11 -- llarp/link/contacts.cpp | 105 +++++++++++++ llarp/link/contacts.hpp | 78 ++++++++++ llarp/link/link_endpoints.cpp | 4 - llarp/link/link_endpoints.hpp | 4 - llarp/link/link_manager.cpp | 239 +++++++++++++++++++++-------- llarp/link/link_manager.hpp | 41 ++--- llarp/messages/common.hpp | 4 - llarp/messages/dht.hpp | 72 +++++++++ llarp/messages/link_intro.cpp | 3 +- llarp/messages/link_message.hpp | 11 -- llarp/messages/relay_commit.cpp | 16 +- llarp/messages/relay_status.cpp | 6 +- llarp/net/sock_addr.cpp | 5 - llarp/net/sock_addr.hpp | 4 - llarp/path/path_context.cpp | 28 +++- llarp/path/path_context.hpp | 5 +- llarp/path/pathbuilder.cpp | 2 +- llarp/path/pathbuilder.hpp | 212 +++++++++++++------------ llarp/path/pathset.cpp | 7 +- llarp/pow.cpp | 14 +- llarp/router/rc_lookup_handler.cpp | 23 +-- llarp/router/rc_lookup_handler.hpp | 6 +- llarp/router/router.cpp | 155 +++++++++---------- llarp/router/router.hpp | 45 ++---- llarp/router_contact.cpp | 118 +++----------- llarp/router_contact.hpp | 4 +- llarp/routing/message.hpp | 11 -- llarp/service/endpoint.cpp | 34 ++-- llarp/service/intro_set.cpp | 19 +++ llarp/service/intro_set.hpp | 12 ++ llarp/util/aligned.hpp | 57 ++++--- llarp/util/logging.hpp | 5 + 37 files changed, 830 insertions(+), 563 deletions(-) create mode 100644 llarp/link/contacts.cpp create mode 100644 llarp/link/contacts.hpp delete mode 100644 llarp/link/link_endpoints.cpp delete mode 100644 llarp/link/link_endpoints.hpp create mode 100644 llarp/messages/dht.hpp diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index 9958a07c51..f8676e96ab 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -149,19 +149,18 @@ add_library(lokinet-consensus # lokinet-dht holds all logic related to interacting with and participating in the DHT hashring add_library(lokinet-dht STATIC - dht/dht.cpp dht/explorenetworkjob.cpp dht/localtaglookup.cpp dht/localrouterlookup.cpp dht/localserviceaddresslookup.cpp dht/message.cpp - dht/messages/findintro.cpp - dht/messages/findrouter.cpp - dht/messages/gotintro.cpp - dht/messages/gotrouter.cpp - dht/messages/pubintro.cpp - dht/messages/findname.cpp - dht/messages/gotname.cpp + # dht/messages/findintro.cpp + # dht/messages/findrouter.cpp + # dht/messages/gotintro.cpp + # dht/messages/gotrouter.cpp + # dht/messages/pubintro.cpp + # dht/messages/findname.cpp + # dht/messages/gotname.cpp dht/publishservicejob.cpp dht/recursiverouterlookup.cpp dht/serviceaddresslookup.cpp @@ -197,6 +196,7 @@ add_library(lokinet-layer-onion add_library(lokinet-layer-link STATIC link/connection.cpp + link/contacts.cpp link/link_manager.cpp messages/link_intro.cpp ) @@ -220,7 +220,6 @@ add_library(lokinet-context STATIC context.cpp link/link_manager.cpp - router/outbound_message_handler.cpp router/rc_lookup_handler.cpp router/rc_gossiper.cpp router/router.cpp diff --git a/llarp/context.cpp b/llarp/context.cpp index 621c99cf11..990020346d 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -3,8 +3,7 @@ #include "constants/evloop.hpp" #include "config/config.hpp" -#include "crypto/crypto_libsodium.hpp" -#include "dht/context.hpp" +#include "crypto/crypto.hpp" #include "ev/ev.hpp" #include #include "nodedb.hpp" @@ -75,7 +74,7 @@ namespace llarp loop = EventLoop::create(jobQueueSize); } - crypto = std::make_shared(); + crypto = std::make_shared(); cryptoManager = std::make_shared(crypto.get()); router = makeRouter(loop); diff --git a/llarp/crypto/types.cpp b/llarp/crypto/types.cpp index 95dea93bb0..93b3099bd7 100644 --- a/llarp/crypto/types.cpp +++ b/llarp/crypto/types.cpp @@ -22,6 +22,14 @@ namespace llarp return true; } + PubKey + PubKey::from_string(const std::string& s) + { + PubKey p; + oxenc::from_hex(s.begin(), s.end(), p.begin()); + return p; + } + std::string PubKey::ToString() const { diff --git a/llarp/crypto/types.hpp b/llarp/crypto/types.hpp index 584383cf14..6a7a872596 100644 --- a/llarp/crypto/types.hpp +++ b/llarp/crypto/types.hpp @@ -33,6 +33,9 @@ namespace llarp bool FromString(const std::string& str); + static PubKey + from_string(const std::string& s); + operator RouterID() const { return {as_array()}; diff --git a/llarp/dht/message.hpp b/llarp/dht/message.hpp index a340f63b28..9b723021a4 100644 --- a/llarp/dht/message.hpp +++ b/llarp/dht/message.hpp @@ -1,6 +1,5 @@ #pragma once -#include "dht.h" #include "key.hpp" #include #include @@ -39,16 +38,6 @@ namespace llarp::dht decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) = 0; // methods we do not want to inherit onwards from AbstractSerializable - void - bt_encode(oxenc::bt_list_producer&) const final - { - throw std::runtime_error{"Error: DHT messages should encode directly to a bt dict producer!"}; - } - void - bt_encode(llarp_buffer&) const final - { - throw std::runtime_error{"Error: DHT messages should encode directly to a bt dict producer!"}; - } std::string bt_encode() const final { diff --git a/llarp/link/contacts.cpp b/llarp/link/contacts.cpp new file mode 100644 index 0000000000..43f6ce4b36 --- /dev/null +++ b/llarp/link/contacts.cpp @@ -0,0 +1,105 @@ +#include "contacts.hpp" + +#include +#include + +namespace llarp +{ + Contacts::Contacts(const dht::Key_t& k, Router& r) : _local_key{k}, _router{r} + { + 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 + { + auto& introsets = _introset_nodes->nodes; + + if (auto itr = introsets.find(key); itr != introsets.end()) + return itr->second.introset; + + 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.IsExpired(now)) + itr = nodes.erase(itr); + else + ++itr; + } + } + + if (_introset_nodes) + { + auto& svcs = _introset_nodes->nodes; + auto itr = svcs.begin(); + + while (itr != svcs.end()) + { + if (itr->second.introset.IsExpired(now)) + itr = svcs.erase(itr); + else + ++itr; + } + } + } + + util::StatusObject + Contacts::extract_status() const + { + util::StatusObject obj{ + {"nodes", _rc_nodes->ExtractStatus()}, + {"services", _introset_nodes->ExtractStatus()}, + {"local_key", _local_key.ToHex()}}; + return obj; + } + + bool + Contacts::lookup_router( + const RouterID& rid, std::function&)> func) + { + dht::Key_t ask_peer; + + if (not _rc_nodes->FindClosest(dht::Key_t{rid}, ask_peer)) + return false; + + _router.loop()->call([this, rid, func]() { + pending_lookups[rid] = [](const std::vector&) { + // TODO: combine this concept with service::Endpoint introset lookups? + }; + + _router.send_control_message( + rid, "find_router", FindRouterMessage::serialize(rid, false, false, 0)); + }); + + return true; + } + + 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) + { + _router.loop()->call([this, val]() { _rc_nodes->DelNode(val); }); + } + +} // namespace llarp diff --git a/llarp/link/contacts.hpp b/llarp/link/contacts.hpp new file mode 100644 index 0000000000..8164c7b5d1 --- /dev/null +++ b/llarp/link/contacts.hpp @@ -0,0 +1,78 @@ +#pragma once + +#include +#include + +namespace llarp +{ + struct Router; + + /// This class mediates storage, retrieval, and functionality for the various types + /// of contact information that needs to be stored locally by the link manager and + /// router, like RouterContacts and introsets for example + struct Contacts + { + 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}; + + // 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; + } + + std::unordered_map&)>> + pending_lookups; + + void + on_clean_contacts(); + + std::optional + get_introset_by_location(const dht::Key_t& key) const; + + util::StatusObject + extract_status() const; + + bool + lookup_router(const RouterID&, std::function&)>); + + 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(); + } + + dht::Bucket* + services() const + { + return _introset_nodes.get(); + } + + Router* + router() const + { + return &_router; + } + }; + +} // namespace llarp diff --git a/llarp/link/link_endpoints.cpp b/llarp/link/link_endpoints.cpp deleted file mode 100644 index a8625dda0a..0000000000 --- a/llarp/link/link_endpoints.cpp +++ /dev/null @@ -1,4 +0,0 @@ -#include "link_endpoints.hpp" - -namespace llarp -{} // namespace llarp diff --git a/llarp/link/link_endpoints.hpp b/llarp/link/link_endpoints.hpp deleted file mode 100644 index 3796e3b94b..0000000000 --- a/llarp/link/link_endpoints.hpp +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -namespace llarp -{} // namespace llarp diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index c13ffb6056..ed406fb559 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1,5 +1,6 @@ #include "link_manager.hpp" #include "connection.hpp" +#include "contacts.hpp" #include #include @@ -150,24 +151,27 @@ namespace llarp - stream constructor callback - will return a BTRequestStream on the first call to get_new_stream */ - return quic->endpoint( + auto ep = quic->endpoint( router.public_ip(), [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); }, - [this](oxen::quic::dgram_interface& di, bstring dgram) { recv_data_message(di, dgram); }, + [this](oxen::quic::dgram_interface& di, bstring dgram) { recv_data_message(di, dgram); }); + ep->listen( + tls_creds, [&](oxen::quic::Connection& c, oxen::quic::Endpoint& e, std::optional id) -> std::shared_ptr { if (id && id == 0) { - auto s = std::make_shared(); + auto s = std::make_shared(c, e); register_commands(s); return s; } return std::make_shared(c, e); }); + return ep; } LinkManager::LinkManager(Router& r) @@ -185,10 +189,37 @@ namespace llarp std::string endpoint, std::string body, std::function func) + { + if (func) + return send_control_message_impl( + remote, std::move(endpoint), std::move(body), std::move(func)); + + if (auto itr = rpc_responses.find(endpoint); itr != rpc_responses.end()) + return send_control_message_impl( + remote, std::move(endpoint), std::move(body), [&](oxen::quic::message m) { + return std::invoke(itr->second, this, std::move(m)); + }); + + return send_control_message_impl(remote, std::move(endpoint), std::move(body)); + } + + bool + LinkManager::send_control_message_impl( + const RouterID& remote, + std::string endpoint, + std::string body, + std::function func) { if (is_stopping) return false; + auto cb = [this, f = std::move(func), endpoint](oxen::quic::message m) { + f(m); + + if (auto itr = rpc_responses.find(endpoint); itr != rpc_responses.end()) + std::invoke(itr->second, this, std::move(m)); + }; + if (auto conn = ep.get_conn(remote); conn) { conn->control_stream->command(endpoint, body, std::move(func)); @@ -290,7 +321,7 @@ namespace llarp // TODO: confirm remote end is using the expected pubkey (RouterID). // TODO: ALPN for "client" vs "relay" (could just be set on endpoint creation) - if (auto rv = ep.establish_connection(remote_addr, rc, tls_creds); rv) + if (auto rv = ep.establish_connection(remote_addr, rc); rv) { log::info(quic_cat, "Connection to {} successfully established!", remote_addr); return; @@ -493,14 +524,14 @@ namespace llarp LinkManager::handle_find_name(oxen::quic::message m) { std::string name_hash; - uint64_t tx_id; + [[maybe_unused]] uint64_t tx_id; try { oxenc::bt_dict_consumer btdp{m.body()}; - safe_fetch_value(btdp, "H", name_hash); - safe_fetch_value(btdp, "T", tx_id); + name_hash = btdp.require("H"); + tx_id = btdp.require("T"); } catch (const std::exception& e) { @@ -510,11 +541,10 @@ namespace llarp router.rpc_client()->lookup_ons_hash( name_hash, [this, msg = std::move(m)](std::optional maybe) mutable { - if (maybe.has_value()) - msg.respond(serialize_response(true, {"NAME", maybe->ciphertext.c_str()})); + msg.respond(serialize_response(true, {{"NAME", maybe->ciphertext.c_str()}})); else - msg.respond(serialize_response(false, {"STATUS", "NOT FOUND"}), true); + msg.respond(serialize_response(false, {{"STATUS", "NOT FOUND"}}), true); }); } @@ -527,24 +557,21 @@ namespace llarp void LinkManager::handle_find_router(oxen::quic::message m) { - ustring target_key; - uint64_t is_exploratory, is_iterative, tx_id; + std::string target_key; + uint64_t is_exploratory, is_iterative; try { oxenc::bt_dict_consumer btdc{m.body()}; - - - safe_fetch_value(btdc, "E", is_exploratory); - safe_fetch_value(btdc, "I", is_iterative); - safe_fetch_value(btdc, "K", target_key); - safe_fetch_value(btdc, "T", tx_id); + is_exploratory = btdc.require("E"); + is_iterative = btdc.require("I"); + target_key = btdc.require("E"); } catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); return; } @@ -552,15 +579,82 @@ namespace llarp // TODO: do we need a replacement for dht.pendingIntroSetLookups() etc here? - const auto target_addr = dht::Key_t{}; + RouterID target_rid; + 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_key = dht::Key_t{local_rid}; + + if (is_exploratory) + { + std::string neighbors{}; + const auto closest_rcs = + router.node_db()->FindManyClosestTo(target_addr, RC_LOOKUP_STORAGE_REDUNDANCY); - + for (const auto& rc : closest_rcs) + { + const auto& rid = rc.pubkey; + if (router.router_profiling().IsBadForConnect(rid) || target_rid == rid || local_rid == rid) + continue; + + neighbors += oxenc::bt_serialize(rid.ToString()); + } + + m.respond( + serialize_response( + false, {{"STATUS", "RETRY EXPLORATORY"}, {"ROUTERS", neighbors.c_str()}}), + true); + } + else + { + const auto closest_rc = router.node_db()->FindClosestTo(target_addr); + const auto& closest_rid = closest_rc.pubkey; + const auto closest_key = dht::Key_t{closest_rid}; + + if (target_addr == closest_key) + { + if (closest_rc.ExpiresSoon(llarp::time_now_ms())) + { + send_control_message_impl( + target_rid, "find_router", m.body_str(), [this](oxen::quic::message m) { + return handle_find_router_response(std::move(m)); + }); + } + else + { + m.respond(serialize_response(true, {{"RC", closest_rc.ToString().c_str()}})); + } + } + else if (not is_iterative) + { + if ((closest_key ^ target_addr) < (local_key ^ target_addr)) + { + send_control_message_impl( + closest_rc.pubkey, "find_router", m.body_str(), [this](oxen::quic::message m) { + return handle_find_router_response(std::move(m)); + }); + } + else + { + m.respond(serialize_response(false, {{"STATUS", "RETRY ITERATIVE"}}), true); + } + } + else + { + m.respond( + serialize_response( + false, + {{"STATUS", "RETRY NEW RECIPIENT"}, + {"RECIPIENT", reinterpret_cast(closest_rid.data())}}), + true); + } + } } void LinkManager::handle_publish_intro(oxen::quic::message m) { - std::string introset, derived_signing_key, sig; + std::string introset, derived_signing_key, payload, sig, nonce; uint64_t is_relayed, relay_order, tx_id; std::chrono::milliseconds signed_at; @@ -568,21 +662,23 @@ namespace llarp { oxenc::bt_dict_consumer btdc_a{m.body()}; - safe_fetch_value(btdc_a, "I", introset); - safe_fetch_value(btdc_a, "O", relay_order); - safe_fetch_value(btdc_a, "R", is_relayed); - safe_fetch_value(btdc_a, "T", tx_id); + introset = btdc_a.require("I"); + relay_order = btdc_a.require("O"); + is_relayed = btdc_a.require("R"); + tx_id = btdc_a.require("T"); - oxenc::bt_dict_consumer btdc_b{introset}; + oxenc::bt_dict_consumer btdc_b{introset.data()}; - safe_fetch_value(btdc_b, "d", derived_signing_key); - safe_fetch_value(btdc_b, "s", signed_at); - safe_fetch_value(btdc_b, "z", sig); + derived_signing_key = btdc_b.require("d"); + nonce = btdc_b.require("n"); + signed_at = std::chrono::milliseconds{btdc_b.require("s")}; + payload = btdc_b.require("x"); + sig = btdc_b.require("z"); } catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); return; } @@ -593,14 +689,14 @@ namespace llarp if (not service::EncryptedIntroSet::verify(introset, derived_signing_key, sig)) { log::error(link_cat, "Received PublishIntroMessage with invalid introset: {}", introset); - m.respond(serialize_response(false, {"STATUS", "INVALID INTROSET"}), true); + m.respond(serialize_response(false, {{"STATUS", "INVALID INTROSET"}}), true); return; } if (now + service::MAX_INTROSET_TIME_DELTA > signed_at + path::DEFAULT_LIFETIME) { log::error(link_cat, "Received PublishIntroMessage with expired introset: {}", introset); - m.respond(serialize_response(false, {"STATUS", "EXPIRED INTROSET"}), true); + m.respond(serialize_response(false, {{"STATUS", "EXPIRED INTROSET"}}), true); return; } @@ -610,17 +706,19 @@ namespace llarp { log::error( link_cat, "Received PublishIntroMessage but only know {} nodes", closest_rcs.size()); - m.respond(serialize_response(false, {"STATUS", "INSUFFICIENT NODES"}), true); + m.respond(serialize_response(false, {{"STATUS", "INSUFFICIENT NODES"}}), true); return; } + service::EncryptedIntroSet enc{derived_signing_key, signed_at, payload, nonce, sig}; + if (is_relayed) { if (relay_order >= INTROSET_STORAGE_REDUNDANCY) { log::error( link_cat, "Received PublishIntroMessage with invalide relay order: {}", relay_order); - m.respond(serialize_response(false, {"STATUS", "INVALID ORDER"}), true); + m.respond(serialize_response(false, {{"STATUS", "INVALID ORDER"}}), true); return; } @@ -636,8 +734,7 @@ namespace llarp "Received PublishIntroMessage in which we are peer index {}.. storing introset", relay_order); - // TODO: replace this concept - // dht->services()->PutNode(introset); + router.contacts()->services()->PutNode(dht::ISNode{std::move(enc)}); m.respond(serialize_response(true)); } else @@ -645,7 +742,7 @@ namespace llarp log::info( link_cat, "Received PublishIntroMessage; propagating to peer index {}", relay_order); - send_control_message( + send_control_message_impl( peer_key, "publish_intro", m.body_str(), [this](oxen::quic::message m) { return handle_publish_intro_response(std::move(m)); }); @@ -669,8 +766,8 @@ namespace llarp if (rc_index >= 0) { log::info(link_cat, "Received PublishIntroMessage for {} (TXID: {}); we are candidate {}"); - // TODO: replace this concept - // dht->services()->PutNode(introset); + + router.contacts()->services()->PutNode(dht::ISNode{std::move(enc)}); m.respond(serialize_response(true)); } else @@ -690,17 +787,16 @@ namespace llarp { oxenc::bt_dict_consumer btdc{m.body()}; - safe_fetch_value(btdc, "N", tag_name); - safe_fetch_value(btdc, "O", relay_order); - safe_fetch_value(btdc, "R", is_relayed); - safe_fetch_value(btdc, "S", location); - safe_fetch_value(btdc, "T", tx_id); - safe_fetch_value(btdc, "N", tag_name); + tag_name = btdc.require("N"); + relay_order = btdc.require("O"); + is_relayed = btdc.require("R"); + location = btdc.require("S"); + tx_id = btdc.require("T"); } catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); return; } @@ -714,7 +810,7 @@ namespace llarp { log::warning( link_cat, "Received FindIntroMessage with invalid relay order: {}", relay_order); - m.respond(serialize_response(false, {"STATUS", "INVALID ORDER"}), true); + m.respond(serialize_response(false, {{"STATUS", "INVALID ORDER"}}), true); return; } @@ -724,7 +820,7 @@ namespace llarp { log::error( link_cat, "Received FindIntroMessage but only know {} nodes", closest_rcs.size()); - m.respond(serialize_response(false, {"STATUS", "INSUFFICIENT NODES"}), true); + m.respond(serialize_response(false, {{"STATUS", "INSUFFICIENT NODES"}}), true); return; } @@ -733,15 +829,16 @@ namespace llarp const auto& peer_rc = closest_rcs[relay_order]; const auto& peer_key = peer_rc.pubkey; - send_control_message(peer_key, "find_intro", m.body_str(), [this](oxen::quic::message m) { - return handle_find_intro_response(std::move(m)); - }); + send_control_message_impl( + peer_key, "find_intro", m.body_str(), [this](oxen::quic::message m) { + return handle_find_intro_response(std::move(m)); + }); return; } // TODO: replace this concept and add it to the response // const auto maybe = dht.GetIntroSetByLocation(location); - m.respond(serialize_response(true, {"INTROSET", ""})); + m.respond(serialize_response(true, {{"INTROSET", ""}})); } void @@ -754,7 +851,7 @@ namespace llarp catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); return; } } @@ -769,7 +866,7 @@ namespace llarp catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); return; } } @@ -784,7 +881,7 @@ namespace llarp catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); return; } } @@ -792,16 +889,30 @@ namespace llarp void LinkManager::handle_obtain_exit(oxen::quic::message m) { + // TODO: implement transit_hop things like nextseqno(), info.rxID, etc + std::string payload{m.body_str()}, pubkey; + [[maybe_unused]] uint64_t flag, tx_id, seq_no; + try { - oxenc::bt_dict_consumer btdc{m.body()}; + oxenc::bt_dict_consumer btdc{payload}; + + flag = btdc.require("E"); + pubkey = btdc.require("I"); + seq_no = btdc.require("S"); + tx_id = btdc.require("T"); } catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); return; } + + RouterID target; + target.FromString(pubkey); + + // auto handler = router.path_context().GetByDownstream(target, tx_id); } void @@ -814,7 +925,7 @@ namespace llarp catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); return; } } @@ -829,7 +940,7 @@ namespace llarp catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); return; } } @@ -844,7 +955,7 @@ namespace llarp catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); return; } } @@ -859,7 +970,7 @@ namespace llarp catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); return; } } @@ -874,8 +985,10 @@ namespace llarp catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {"STATUS", "EXCEPTION"}), true); + m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); return; } + + // check if we have any pending intro lookups in contacts } } // namespace llarp diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 519a4dc8de..4651f03ba9 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -1,7 +1,6 @@ #pragma once #include "connection.hpp" -#include "link_endpoints.hpp" #include #include @@ -140,7 +139,6 @@ namespace llarp public: explicit LinkManager(Router& r); - // set is_request to true for RPC requests, false for RPC commands bool send_control_message( const RouterID& remote, @@ -152,6 +150,13 @@ namespace llarp send_data_message(const RouterID& remote, std::string data); private: + bool + send_control_message_impl( + const RouterID& remote, + std::string endpoint, + std::string body, + std::function = nullptr); + friend struct link::Endpoint; std::atomic is_stopping; @@ -302,34 +307,20 @@ namespace llarp {"obtain_exit", &LinkManager::handle_obtain_exit}, {"close_exit", &LinkManager::handle_close_exit}}; + std::unordered_map rpc_responses = { + {"find_name", &LinkManager::handle_find_name_response}, + {"find_router", &LinkManager::handle_find_router_response}, + {"publish_intro", &LinkManager::handle_publish_intro_response}, + {"find_intro", &LinkManager::handle_find_intro_response}}; + // response handling functions void handle_publish_intro_response(oxen::quic::message); - void handle_find_name_response(oxen::quic::message); // not used? + void handle_find_name_response(oxen::quic::message); // not used? void handle_find_router_response(oxen::quic::message); void handle_find_intro_response(oxen::quic::message); std::string serialize_response(bool success, oxenc::bt_dict supplement = {}); - - /** Searches the bt dict held by a dict consumer for a specific key `k`, setting - the value at `dest` and throwing if not found. This is equivalent to calling: - - if (not bdca.skip_until(k)) - throw std::invalid_argument{"..."}; - dest = btdc.consume_integer() OR btdc.consume_string(); - */ - template - void - safe_fetch_value(oxenc::bt_dict_consumer& btdc, const char* k, T& dest) - { - if (not btdc.skip_until(k)) - throw std::invalid_argument{""}; - - if constexpr (std::is_integral_v) - dest = btdc.consume_integer(); - else - dest = btdc.consume_string(); - } }; namespace link @@ -346,11 +337,11 @@ namespace llarp // emplace immediately for connection open callback to find scid connid_map.emplace(conn_interface->scid(), rc.pubkey); - auto [itr, b] = conns.emplace(rc.pubkey); + auto [itr, b] = conns.emplace(rc.pubkey, nullptr); auto control_stream = conn_interface->template get_new_stream(); - itr->second = std::make_shared(conn_interface, rc, control_stream); + itr->second = std::make_shared(conn_interface, control_stream, rc); return true; } diff --git a/llarp/messages/common.hpp b/llarp/messages/common.hpp index 7b6618b446..f59700931c 100644 --- a/llarp/messages/common.hpp +++ b/llarp/messages/common.hpp @@ -18,11 +18,7 @@ namespace llarp virtual std::string bt_encode() const = 0; virtual void - bt_encode(llarp_buffer& b) const = 0; - virtual void bt_encode(oxenc::bt_dict_producer& btdp) const = 0; - virtual void - bt_encode(oxenc::bt_list_producer& btlp) const = 0; }; struct AbstractMessageHandler diff --git a/llarp/messages/dht.hpp b/llarp/messages/dht.hpp new file mode 100644 index 0000000000..fffc9e69f9 --- /dev/null +++ b/llarp/messages/dht.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include "common.hpp" + +#include +#include +#include +#include + +#include + +namespace llarp +{ + struct DHTMessage : public AbstractSerializable + {}; + + struct FindRouterMessage : public DHTMessage + { + private: + RouterID target; + bool is_iterative{false}; + bool is_exploratory{false}; + uint64_t tx_id{0}; + + public: + explicit FindRouterMessage(const RouterID& rid, bool is_itr, bool is_exp, uint64_t tx) + : target{rid}, is_iterative{is_itr}, is_exploratory{is_exp}, tx_id{tx} + {} + + std::string + bt_encode() const override + { + oxenc::bt_dict_producer btdp; + + try + { + btdp.append("A", "R"); + btdp.append("E", is_exploratory ? 1 : 0); + btdp.append("I", is_iterative ? 1 : 0); + btdp.append("K", target.ToView()); + btdp.append("T", tx_id); + } + catch (...) + { + log::error(link_cat, "Error: FindRouterMessage failed to bt encode contents!"); + } + + return std::move(btdp).str(); + } + + static std::string + serialize(const RouterID& rid, bool is_itr, bool is_exp, uint64_t tx) + { + oxenc::bt_dict_producer btdp; + + try + { + btdp.append("A", "R"); + btdp.append("E", is_exp ? 1 : 0); + btdp.append("I", is_itr ? 1 : 0); + btdp.append("K", rid.ToView()); + btdp.append("T", tx); + } + catch (...) + { + log::error(link_cat, "Error: FindRouterMessage failed to bt encode contents!"); + } + + return std::move(btdp).str(); + } + }; +} // namespace llarp diff --git a/llarp/messages/link_intro.cpp b/llarp/messages/link_intro.cpp index 0966f75eb3..fbbcf44206 100644 --- a/llarp/messages/link_intro.cpp +++ b/llarp/messages/link_intro.cpp @@ -95,7 +95,8 @@ namespace llarp { if (!verify()) return false; - return conn->GotLIM(this); + return true; + // return conn->GotLIM(this); } void diff --git a/llarp/messages/link_message.hpp b/llarp/messages/link_message.hpp index e9e77e08ce..7a60b880d5 100644 --- a/llarp/messages/link_message.hpp +++ b/llarp/messages/link_message.hpp @@ -54,22 +54,11 @@ namespace llarp // methods we do not want to inherit onwards from AbstractSerializable void - bt_encode(llarp_buffer&) const final - { - throw std::runtime_error{"Error: Link messages should not encode directly to a buffer!"}; - } - void bt_encode(oxenc::bt_dict_producer&) const final { throw std::runtime_error{ "Error: Link messages should not encode directly to a bt list producer!"}; } - void - bt_encode(oxenc::bt_list_producer&) const final - { - throw std::runtime_error{ - "Error: Link messages should not encode directly to a bt list producer!"}; - } }; struct AbstractDataMessage : public AbstractLinkMessage diff --git a/llarp/messages/relay_commit.cpp b/llarp/messages/relay_commit.cpp index 955ee0a7a8..ca5784f169 100644 --- a/llarp/messages/relay_commit.cpp +++ b/llarp/messages/relay_commit.cpp @@ -193,16 +193,16 @@ namespace llarp // the actual hop std::shared_ptr hop; - const std::optional fromAddr; + oxen::quic::Address from_addr; LRCMFrameDecrypt(Context* ctx, Decrypter_ptr dec, const LR_CommitMessage* commit) : decrypter(std::move(dec)) , frames(commit->frames) , context(ctx) , hop(std::make_shared()) - , fromAddr( - commit->conn->remote_rc.IsPublicRouter() ? std::optional{} - : commit->conn->remote_rc.addr) + , from_addr{ + commit->conn->remote_rc.IsPublicRouter() ? oxen::quic::Address{} + : commit->conn->remote_rc.addr} { hop->info.downstream = commit->conn->remote_rc.pubkey; } @@ -268,14 +268,14 @@ namespace llarp return; } - if (self->fromAddr) + if (self->from_addr.is_addressable()) { // only do ip limiting from non service nodes #ifndef LOKINET_HIVE - if (self->context->CheckPathLimitHitByIP(*self->fromAddr)) + if (self->context->CheckPathLimitHitByIP(self->from_addr.to_string())) { // we hit a limit so tell it to slow tf down - llarp::LogError("client path build hit limit ", *self->fromAddr); + llarp::LogError("client path build hit limit ", self->from_addr); OnForwardLRCMResult( self->context->router(), self->hop, @@ -413,7 +413,7 @@ namespace llarp return; } // generate hash of hop key for nonce mutation - crypto->shorthash(self->hop->nonceXOR, llarp_buffer_t(self->hop->pathKey)); + crypto->shorthash(self->hop->nonceXOR, self->hop->pathKey.data(), self->hop->pathKey.size()); if (self->record.work && self->record.work->IsValid(now)) { llarp::LogDebug( diff --git a/llarp/messages/relay_status.cpp b/llarp/messages/relay_status.cpp index 2fa717baf6..e53b9ab52c 100644 --- a/llarp/messages/relay_status.cpp +++ b/llarp/messages/relay_status.cpp @@ -249,8 +249,10 @@ namespace llarp // send the status message to previous hop // if it fails we are hitting a failure case we can't cope with so ... drop. - if (not router->SendToOrQueue(nextHop, *msg, resultCallback)) - resultCallback(SendStatus::Congestion); + + // TODO: replace with new message serialization + // if (not router->SendToOrQueue(nextHop, *msg, resultCallback)) + // resultCallback(SendStatus::Congestion); // trigger idempotent pump to make sure stuff gets sent router->TriggerPump(); diff --git a/llarp/net/sock_addr.cpp b/llarp/net/sock_addr.cpp index df4384e9ae..17f1868564 100644 --- a/llarp/net/sock_addr.cpp +++ b/llarp/net/sock_addr.cpp @@ -78,11 +78,6 @@ namespace llarp fromString(addr, false); } - SockAddr::SockAddr(const AddressInfo& info) : SockAddr{info.ip} - { - setPort(huint16_t{info.port}); - } - SockAddr::SockAddr(const SockAddr& other) { *this = other; diff --git a/llarp/net/sock_addr.hpp b/llarp/net/sock_addr.hpp index cda813e3e2..753519892f 100644 --- a/llarp/net/sock_addr.hpp +++ b/llarp/net/sock_addr.hpp @@ -17,8 +17,6 @@ namespace llarp { - struct AddressInfo; - /// A simple SockAddr wrapper which provides a sockaddr_in (IPv4). Memory management is handled /// in constructor and destructor (if needed) and copying is disabled. struct SockAddr @@ -39,8 +37,6 @@ namespace llarp SockAddr(std::string_view addr); SockAddr(std::string_view addr, huint16_t port); // port is in native (host) order - SockAddr(const AddressInfo&); - SockAddr(const SockAddr&); SockAddr& operator=(const SockAddr&); diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index 5dd1df7f85..5839d9e6cd 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -10,7 +10,7 @@ namespace llarp::path static constexpr auto DefaultPathBuildLimit = 500ms; PathContext::PathContext(Router* router) - : _router(router), m_AllowTransit(false), m_PathLimits(DefaultPathBuildLimit) + : _router(router), m_AllowTransit(false), path_limits(DefaultPathBuildLimit) {} void @@ -36,7 +36,22 @@ namespace llarp::path remote.setPort(0); // try inserting remote address by ip into decaying hash set // if it cannot insert it has hit a limit - return not m_PathLimits.Insert(remote); + return not path_limits.Insert(remote); +#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 } @@ -85,7 +100,9 @@ namespace llarp::path LogDebug("forwarding LRCM to ", nextHop); - return _router->SendToOrQueue(nextHop, msg, handler); + // TODO: replace with new message serialization for LRCM + // return _router->SendToOrQueue(nextHop, msg, handler); + return true; } template < @@ -340,7 +357,7 @@ namespace llarp::path PathContext::ExpirePaths(llarp_time_t now) { // decay limits - m_PathLimits.Decay(now); + path_limits.Decay(now); { SyncTransitMap_t::Lock_t lock(m_TransitPaths.first); @@ -350,7 +367,8 @@ namespace llarp::path { if (itr->second->Expired(now)) { - _router->outboundMessageHandler().RemovePath(itr->first); + // TODO: this + // _router->outboundMessageHandler().RemovePath(itr->first); itr = map.erase(itr); } else diff --git a/llarp/path/path_context.hpp b/llarp/path/path_context.hpp index 7f1bb7e7ba..02189fd0ab 100644 --- a/llarp/path/path_context.hpp +++ b/llarp/path/path_context.hpp @@ -53,6 +53,9 @@ namespace llarp bool CheckPathLimitHitByIP(const IpAddress& ip); + bool + CheckPathLimitHitByIP(const std::string& ip); + bool AllowingTransit() const; @@ -185,7 +188,7 @@ namespace llarp SyncTransitMap_t m_TransitPaths; SyncOwnedPathsMap_t m_OurPaths; bool m_AllowTransit; - util::DecayingHashSet m_PathLimits; + util::DecayingHashSet path_limits; }; } // namespace path } // namespace llarp diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index 5b791c8a83..285e40b569 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -57,7 +57,7 @@ namespace llarp return; } // generate nonceXOR valueself->hop->pathKey - crypto->shorthash(hop.nonceXOR, llarp_buffer_t(hop.shared)); + crypto->shorthash(hop.nonceXOR, hop.shared.data(), hop.shared.size()); ++idx; bool isFarthestHop = idx == path->hops.size(); diff --git a/llarp/path/pathbuilder.hpp b/llarp/path/pathbuilder.hpp index f9cf2e3d2a..a874cc214e 100644 --- a/llarp/path/pathbuilder.hpp +++ b/llarp/path/pathbuilder.hpp @@ -7,149 +7,145 @@ #include #include -namespace llarp +namespace llarp::path { - namespace path - { - // milliseconds waiting between builds on a path per router - static constexpr auto MIN_PATH_BUILD_INTERVAL = 500ms; - static constexpr auto PATH_BUILD_RATE = 100ms; - - /// limiter for path builds - /// prevents overload and such - class BuildLimiter - { - util::DecayingHashSet m_EdgeLimiter; + // milliseconds waiting between builds on a path per router + static constexpr auto MIN_PATH_BUILD_INTERVAL = 500ms; + static constexpr auto PATH_BUILD_RATE = 100ms; - public: - /// attempt a build - /// return true if we are allowed to continue - bool - Attempt(const RouterID& router); + /// limiter for path builds + /// prevents overload and such + class BuildLimiter + { + util::DecayingHashSet m_EdgeLimiter; - /// decay limit entries - void - Decay(llarp_time_t now); + public: + /// attempt a build + /// return true if we are allowed to continue + bool + Attempt(const RouterID& router); - /// return true if this router is currently limited - bool - Limited(const RouterID& router) const; - }; + /// decay limit entries + void + Decay(llarp_time_t now); - struct Builder : public PathSet - { - private: - llarp_time_t m_LastWarn = 0s; + /// return true if this router is currently limited + bool + Limited(const RouterID& router) const; + }; - protected: - /// flag for PathSet::Stop() - std::atomic _run; + struct Builder : public PathSet + { + private: + llarp_time_t m_LastWarn = 0s; - virtual bool - UrgentBuild(llarp_time_t now) const; + protected: + /// flag for PathSet::Stop() + std::atomic _run; - /// return true if we hit our soft limit for building paths too fast on a first hop - bool - BuildCooldownHit(RouterID edge) const; + virtual bool + UrgentBuild(llarp_time_t now) const; - private: - void - DoPathBuildBackoff(); + /// return true if we hit our soft limit for building paths too fast on a first hop + bool + BuildCooldownHit(RouterID edge) const; - public: - Router* const m_router; - SecretKey enckey; - size_t numHops; - llarp_time_t lastBuild = 0s; - llarp_time_t buildIntervalLimit = MIN_PATH_BUILD_INTERVAL; + private: + void + DoPathBuildBackoff(); - /// construct - Builder(Router* p_router, size_t numDesiredPaths, size_t numHops); + public: + Router* const m_router; + SecretKey enckey; + size_t numHops; + llarp_time_t lastBuild = 0s; + llarp_time_t buildIntervalLimit = MIN_PATH_BUILD_INTERVAL; - virtual ~Builder() = default; + /// construct + Builder(Router* p_router, size_t numDesiredPaths, size_t numHops); - util::StatusObject - ExtractStatus() const; + virtual ~Builder() = default; - bool - ShouldBuildMore(llarp_time_t now) const override; + util::StatusObject + ExtractStatus() const; - /// should we bundle RCs in builds? - virtual bool - ShouldBundleRC() const = 0; + bool + ShouldBuildMore(llarp_time_t now) const override; - void - ResetInternalState() override; + /// should we bundle RCs in builds? + virtual bool + ShouldBundleRC() const = 0; - /// return true if we hit our soft limit for building paths too fast - bool - BuildCooldownHit(llarp_time_t now) const; + void + ResetInternalState() override; - /// get roles for this path builder - virtual PathRole - GetRoles() const - { - return ePathRoleAny; - } + /// return true if we hit our soft limit for building paths too fast + bool + BuildCooldownHit(llarp_time_t now) const; - BuildStats - CurrentBuildStats() const - { - return m_BuildStats; - } + /// get roles for this path builder + virtual PathRole + GetRoles() const + { + return ePathRoleAny; + } - bool - Stop() override; + BuildStats + CurrentBuildStats() const + { + return m_BuildStats; + } - bool - IsStopped() const override; + bool + Stop() override; - bool - ShouldRemove() const override; + bool + IsStopped() const override; - llarp_time_t - Now() const override; + bool + ShouldRemove() const override; - virtual void - Tick(llarp_time_t now) override; + llarp_time_t + Now() const override; - void - BuildOne(PathRole roles = ePathRoleAny) override; + void + Tick(llarp_time_t now) override; - bool - BuildOneAlignedTo(const RouterID endpoint) override; + void + BuildOne(PathRole roles = ePathRoleAny) override; - std::optional> - GetHopsAlignedToForBuild(RouterID endpoint, const std::set& exclude = {}); + bool + BuildOneAlignedTo(const RouterID endpoint) override; - void - Build(std::vector hops, PathRole roles = ePathRoleAny) override; + std::optional> + GetHopsAlignedToForBuild(RouterID endpoint, const std::set& exclude = {}); - /// pick a first hop - std::optional - SelectFirstHop(const std::set& exclude = {}) const; + void + Build(std::vector hops, PathRole roles = ePathRoleAny) override; - virtual std::optional> - GetHopsForBuild() override; + /// pick a first hop + std::optional + SelectFirstHop(const std::set& exclude = {}) const; - void - ManualRebuild(size_t N, PathRole roles = ePathRoleAny); + std::optional> + GetHopsForBuild() override; - virtual const SecretKey& - GetTunnelEncryptionSecretKey() const; + void + ManualRebuild(size_t N, PathRole roles = ePathRoleAny); - virtual void - HandlePathBuilt(Path_ptr p) override; + const SecretKey& + GetTunnelEncryptionSecretKey() const; - virtual void - HandlePathBuildTimeout(Path_ptr p) override; + void + HandlePathBuilt(Path_ptr p) override; - virtual void - HandlePathBuildFailedAt(Path_ptr p, RouterID hop) override; - }; + void + HandlePathBuildTimeout(Path_ptr p) override; - using Builder_ptr = std::shared_ptr; + void + HandlePathBuildFailedAt(Path_ptr p, RouterID hop) override; + }; - } // namespace path + using Builder_ptr = std::shared_ptr; -} // namespace llarp +} // namespace llarp::path diff --git a/llarp/path/pathset.cpp b/llarp/path/pathset.cpp index f05a372f7f..35170bf27b 100644 --- a/llarp/path/pathset.cpp +++ b/llarp/path/pathset.cpp @@ -92,7 +92,7 @@ namespace llarp::path } void - PathSet::ExpirePaths(llarp_time_t now, Router* router) + PathSet::ExpirePaths(llarp_time_t now, [[maybe_unused]] Router* router) { Lock_t l(m_PathsMutex); if (m_Paths.size() == 0) @@ -102,10 +102,11 @@ namespace llarp::path { if (itr->second->Expired(now)) { + // TODO: this PathID_t txid = itr->second->TXID(); - router->outboundMessageHandler().RemovePath(std::move(txid)); + // router->outboundMessageHandler().RemovePath(std::move(txid)); PathID_t rxid = itr->second->RXID(); - router->outboundMessageHandler().RemovePath(std::move(rxid)); + // router->outboundMessageHandler().RemovePath(std::move(rxid)); itr = m_Paths.erase(itr); } else diff --git a/llarp/pow.cpp b/llarp/pow.cpp index 9143ca0416..1ca047f120 100644 --- a/llarp/pow.cpp +++ b/llarp/pow.cpp @@ -29,19 +29,11 @@ namespace llarp return false; ShortHash digest; - std::array tmp; - llarp_buffer_t buf(tmp); + auto buf = bt_encode(); - auto bte = bt_encode(); - - if (auto b = buf.write(bte.begin(), bte.end()); not b) - return false; - - // rewind - buf.sz = buf.cur - buf.base; - buf.cur = buf.base; // hash - if (!CryptoManager::instance()->shorthash(digest, buf)) + if (!CryptoManager::instance()->shorthash( + digest, reinterpret_cast(buf.data()), buf.size())) return false; // check bytes required uint32_t required = std::floor(std::log(extendedLifetime.count())); diff --git a/llarp/router/rc_lookup_handler.cpp b/llarp/router/rc_lookup_handler.cpp index 86305248f7..a01b744e90 100644 --- a/llarp/router/rc_lookup_handler.cpp +++ b/llarp/router/rc_lookup_handler.cpp @@ -1,6 +1,7 @@ #include #include "rc_lookup_handler.hpp" +#include #include #include #include @@ -8,7 +9,6 @@ #include #include #include -#include #include "router.hpp" #include @@ -113,7 +113,7 @@ namespace llarp LogWarn("cannot lookup ", router, " anonymously"); } - if (!dht->LookupRouter(router, fn)) + if (not contacts->lookup_router(router, fn)) { finalize_request(router, nullptr, RCRequestResult::RouterNotFound); } @@ -195,11 +195,11 @@ namespace llarp { if (not is_session_allowed(rc.pubkey)) { - dht->DelRCNodeAsync(dht::Key_t{rc.pubkey}); + contacts->delete_rc_node_async(dht::Key_t{rc.pubkey}); return false; } - if (not rc.Verify(dht->Now())) + if (not rc.Verify(llarp::time_now_ms())) { LogWarn("RC for ", RouterID(rc.pubkey), " is invalid"); return false; @@ -210,7 +210,7 @@ namespace llarp { LogDebug("Adding or updating RC for ", RouterID(rc.pubkey), " to nodedb and dht."); loop->call([rc, n = node_db] { n->PutIfNewer(rc); }); - dht->PutRCNodeAsync(rc); + contacts->put_rc_node_async(rc); } return true; @@ -251,9 +251,9 @@ namespace llarp work_func(func); // update dht if required - if (dht->Nodes()->HasNode(dht::Key_t{newrc.pubkey})) + if (contacts->rc_nodes()->HasNode(dht::Key_t{newrc.pubkey})) { - dht->Nodes()->PutNode(newrc); + contacts->rc_nodes()->PutNode(newrc); } // TODO: check for other places that need updating the RC @@ -295,7 +295,8 @@ namespace llarp for (const auto& rc : bootstrap_rc_list) { LogInfo("Doing explore via bootstrap node: ", RouterID(rc.pubkey)); - dht->ExploreNetworkVia(dht::Key_t{rc.pubkey}); + // TODO: replace this concept + // dht->ExploreNetworkVia(dht::Key_t{rc.pubkey}); } } @@ -332,7 +333,7 @@ namespace llarp return; } // service nodes gossip, not explore - if (dht->GetRouter()->IsServiceNode()) + if (contacts->router()->IsServiceNode()) return; // explore via every connected peer @@ -356,7 +357,7 @@ namespace llarp void RCLookupHandler::init( - std::shared_ptr d, + std::shared_ptr c, std::shared_ptr nodedb, EventLoop_ptr l, worker_func dowork, @@ -367,7 +368,7 @@ namespace llarp bool useWhitelist_arg, bool isServiceNode_arg) { - dht = d; + contacts = c; node_db = std::move(nodedb); loop = std::move(l); work_func = std::move(dowork); diff --git a/llarp/router/rc_lookup_handler.hpp b/llarp/router/rc_lookup_handler.hpp index 7220d4f154..ecd2c802a1 100644 --- a/llarp/router/rc_lookup_handler.hpp +++ b/llarp/router/rc_lookup_handler.hpp @@ -24,9 +24,9 @@ namespace llarp namespace service { struct Context; - } // namespace service + struct Contacts; struct LinkManager; struct RouterContact; @@ -109,7 +109,7 @@ namespace llarp void init( - std::shared_ptr dht, + std::shared_ptr contacts, std::shared_ptr nodedb, std::shared_ptr loop, worker_func dowork, @@ -143,7 +143,7 @@ namespace llarp mutable util::Mutex _mutex; // protects pendingCallbacks, whitelistRouters - std::shared_ptr dht = nullptr; + std::shared_ptr contacts = nullptr; std::shared_ptr node_db; std::shared_ptr loop; worker_func work_func = nullptr; diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 878c3b651a..4dc7a8962f 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -5,10 +5,9 @@ #include #include #include -#include #include -#include #include +#include #include #include #include @@ -46,16 +45,16 @@ namespace llarp static auto logcat = log::Cat("router"); Router::Router(EventLoop_ptr loop, std::shared_ptr vpnPlatform) - : _route_poker{std::make_shared(this)} + : _route_poker{std::make_shared(*this)} , _lmq{std::make_shared()} , _loop{std::move(loop)} , _vpn{std::move(vpnPlatform)} , paths{this} , _exit_context{this} - , _dht{dht::make_handler()} , _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} , _hidden_service_context{this} { _key_manager = std::make_shared(); @@ -70,7 +69,7 @@ namespace llarp Router::~Router() { - _dht.reset(); + _contacts.reset(); } // TODO: investigate changes needed for libquic integration @@ -97,7 +96,7 @@ namespace llarp return util::StatusObject{ {"running", true}, {"numNodesKnown", _node_db->NumLoaded()}, - {"dht", _dht->ExtractStatus()}, + {"contacts", _contacts->extract_status()}, {"services", _hidden_service_context.ExtractStatus()}, {"exit", _exit_context.ExtractStatus()}, {"links", _link_manager.extract_status()}, @@ -238,9 +237,6 @@ namespace llarp void Router::GossipRCIfNeeded(const RouterContact rc) { - if (disableGossipingRC_TestingOnly()) - return; - /// if we are not a service node forget about gossip if (not IsServiceNode()) return; @@ -272,23 +268,21 @@ namespace llarp loop_wakeup->Trigger(); } - bool - Router::SendToOrQueue( - const RouterID& remote, const AbstractLinkMessage& msg, SendStatusHandler handler) - { - return _outboundMessageHandler.QueueMessage(remote, msg, handler); - } - bool Router::send_data_message(const RouterID& remote, const AbstractDataMessage& msg) { - return _link_manager.send_or_queue_data(remote, msg.bt_encode()); + return _link_manager.send_data_message(remote, msg.bt_encode()); } bool - Router::send_control_message(const RouterID& remote, const AbstractLinkMessage& msg) + Router::send_control_message( + const RouterID& remote, + std::string ep, + std::string body, + std::function func) { - return _link_manager.send_or_queue_data(remote, msg.bt_encode()); + return _link_manager.send_control_message( + remote, std::move(ep), std::move(body), std::move(func)); } void @@ -754,10 +748,9 @@ namespace llarp LogInfo("Loaded ", bootstrap_rc_list.size(), " bootstrap routers"); // Init components after relevant config settings loaded - _outboundMessageHandler.Init(this); _link_manager.init(&_rc_lookup_handler); _rc_lookup_handler.init( - _dht, + _contacts, _node_db, _loop, util::memFn(&Router::queue_work, this), @@ -832,7 +825,7 @@ namespace llarp void Router::report_stats() { - const auto now = now(); + const auto now = llarp::time_now_ms(); LogInfo(node_db()->NumLoaded(), " RCs loaded"); LogInfo(bootstrap_rc_list.size(), " bootstrap peers"); LogInfo(NumberOfConnectedRouters(), " router connections"); @@ -905,7 +898,7 @@ namespace llarp if (is_stopping) return; // LogDebug("tick router"); - const auto now = now(); + const auto now = llarp::time_now_ms(); if (const auto delta = now - _last_tick; _last_tick != 0s and delta > TimeskipDetectedDuration) { // we detected a time skip into the futre, thaw the network @@ -1111,7 +1104,7 @@ namespace llarp for_each_connection( [&peer_keys](link::Connection& conn) { peer_keys.emplace(conn.remote_rc.pubkey); }); - dht()->Nodes()->RemoveIf( + _contacts->rc_nodes()->RemoveIf( [&peer_keys](const dht::Key_t& k) -> bool { return peer_keys.count(k) == 0; }); paths.ExpirePaths(now); @@ -1120,12 +1113,6 @@ namespace llarp _last_tick = llarp::time_now_ms(); } - bool - Router::Sign(Signature& sig, const llarp_buffer_t& buf) const - { - return CryptoManager::instance()->sign(sig, identity(), buf); - } - void Router::modify_rc(std::function(RouterContact)> modify) { @@ -1271,12 +1258,12 @@ namespace llarp _node_db->LoadFromDisk(); } - _dht->Init(llarp::dht::Key_t(pubkey()), this); + _contacts = std::make_shared(llarp::dht::Key_t(pubkey()), *this); for (const auto& rc : bootstrap_rc_list) { node_db()->Put(rc); - _dht->Nodes()->PutNode(rc); + _contacts->rc_nodes()->PutNode(rc); LogInfo("added bootstrap node ", RouterID{rc.pubkey}); } @@ -1494,7 +1481,7 @@ namespace llarp { LogInfo("accepting transit traffic"); paths.AllowTransit(); - _dht->AllowTransit() = true; + _contacts->set_transit_allowed(true); _exit_context.AddExitEndpoint("default", _config->network, _config->dns); return true; } @@ -1549,63 +1536,63 @@ namespace llarp void Router::InitInboundLinks() { - auto addrs = _config->links.InboundListenAddrs; - if (is_service_node and addrs.empty()) - { - LogInfo("Inferring Public Address"); - - auto maybe_port = _config->links.PublicPort; - if (_config->router.PublicPort and not maybe_port) - maybe_port = _config->router.PublicPort; - if (not maybe_port) - maybe_port = net::port_t::from_host(constants::DefaultInboundIWPPort); - - if (auto maybe_addr = net().MaybeInferPublicAddr(*maybe_port)) - { - LogInfo("Public Address looks to be ", *maybe_addr); - addrs.emplace_back(std::move(*maybe_addr)); - } - } - if (is_service_node and addrs.empty()) - throw std::runtime_error{"we are a service node and we have no inbound links configured"}; - - // create inbound links, if we are a service node - for (auto bind_addr : addrs) - { - if (bind_addr.getPort() == 0) - throw std::invalid_argument{"inbound link cannot use port 0"}; - - if (net().IsWildcardAddress(bind_addr.getIP())) - { - if (auto maybe_ip = public_ip()) - bind_addr.setIP(*maybe_ip); - else - throw std::runtime_error{"no public ip provided for inbound socket"}; - } - - AddressInfo ai; - ai.fromSockAddr(bind_addr); - - _link_manager.connect_to({ai.IPString(), ai.port}, true); - - ai.pubkey = llarp::seckey_topublic(_identity); - ai.dialect = "quicinet"; // FIXME: constant, also better name? - ai.rank = 2; // FIXME: hardcoded from the beginning...keep? - AddAddressToRC(ai); - } + // auto addrs = _config->links.InboundListenAddrs; + // if (is_service_node and addrs.empty()) + // { + // LogInfo("Inferring Public Address"); + + // auto maybe_port = _config->links.PublicPort; + // if (_config->router.PublicPort and not maybe_port) + // maybe_port = _config->router.PublicPort; + // if (not maybe_port) + // maybe_port = net::port_t::from_host(constants::DefaultInboundIWPPort); + + // if (auto maybe_addr = net().MaybeInferPublicAddr(*maybe_port)) + // { + // LogInfo("Public Address looks to be ", *maybe_addr); + // addrs.emplace_back(std::move(*maybe_addr)); + // } + // } + // if (is_service_node and addrs.empty()) + // throw std::runtime_error{"we are a service node and we have no inbound links configured"}; + + // // create inbound links, if we are a service node + // for (auto bind_addr : addrs) + // { + // if (bind_addr.getPort() == 0) + // throw std::invalid_argument{"inbound link cannot use port 0"}; + + // if (net().IsWildcardAddress(bind_addr.getIP())) + // { + // if (auto maybe_ip = public_ip()) + // bind_addr.setIP(public_ip().host()); + // else + // throw std::runtime_error{"no public ip provided for inbound socket"}; + // } + + // AddressInfo ai; + // ai.fromSockAddr(bind_addr); + + // _link_manager.connect_to({ai.IPString(), ai.port}, true); + + // ai.pubkey = llarp::seckey_topublic(_identity); + // ai.dialect = "quicinet"; // FIXME: constant, also better name? + // ai.rank = 2; // FIXME: hardcoded from the beginning...keep? + // AddAddressToRC(ai); + // } } void Router::InitOutboundLinks() { - auto addrs = config()->links.OutboundLinks; - if (addrs.empty()) - addrs.emplace_back(net().Wildcard()); + // auto addrs = config()->links.OutboundLinks; + // if (addrs.empty()) + // addrs.emplace_back(net().Wildcard()); - for (auto& bind_addr : addrs) - { - _link_manager.connect_to({bind_addr.ToString()}, false); - } + // for (auto& bind_addr : addrs) + // { + // _link_manager.connect_to({bind_addr.ToString()}, false); + // } } const llarp::net::Platform& diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 67b48187be..777660200a 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -64,6 +64,10 @@ namespace llarp static constexpr size_t INTROSET_STORAGE_REDUNDANCY = (INTROSET_RELAY_REDUNDANCY * INTROSET_REQS_PER_RELAY); + static constexpr size_t RC_LOOKUP_STORAGE_REDUNDANCY{4}; + + struct Contacts; + class RouteManager final /* : public Router */ { public: @@ -118,7 +122,8 @@ namespace llarp exit::Context _exit_context; SecretKey _identity; SecretKey _encryption; - std::shared_ptr _dht; + std::shared_ptr _dh_t; + std::shared_ptr _contacts; std::shared_ptr _node_db; llarp_time_t _started_at; const oxenmq::TaggedThreadID _disk_thread; @@ -140,7 +145,6 @@ namespace llarp oxenmq::address rpc_addr; Profiling _router_profiling; fs::path _profile_file; - OutboundMessageHandler _outboundMessageHandler; LinkManager _link_manager{*this}; RCLookupHandler _rc_lookup_handler; RCGossiper _rcGossiper; @@ -178,16 +182,16 @@ namespace llarp void handle_router_event(std::unique_ptr event) const; - virtual bool - disableGossipingRC_TestingOnly() - { - return false; - }; - public: void for_each_connection(std::function func); + Contacts* + contacts() const + { + return _contacts.get(); + } + std::shared_ptr config() const { @@ -215,22 +219,6 @@ namespace llarp return _rpc_client; } - std::shared_ptr - dht() const - { - return _dht; - } - - /** TOFIX: this - - refactor path types (path_context, pathset) to use unified ID type, not PathID_t - - refactor all callers to use new implementation of remove_path - */ - OutboundMessageHandler& - outboundMessageHandler() - { - return _outboundMessageHandler; - } - LinkManager& link_manager() { @@ -376,9 +364,6 @@ namespace llarp llarp_time_t Uptime() const; - bool - Sign(Signature& sig, const llarp_buffer_t& buf) const; - service::Context& hidden_service_context() { @@ -530,7 +515,11 @@ namespace llarp send_data_message(const RouterID& remote, const AbstractDataMessage& msg); bool - send_control_message(const RouterID& remote, const AbstractLinkMessage& msg); + send_control_message( + const RouterID& remote, + std::string endpoint, + std::string body, + std::function func = nullptr); bool IsBootstrapNode(RouterID) const; diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index 35cb8a3c1e..e1aa240ba5 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -136,95 +136,33 @@ namespace llarp return netID == NetID::DefaultValue(); } - bool - RouterContact::BEncodeSignedSection(llarp_buffer_t* buf) const + std::string + RouterContact::bencode_signed_section() const { - /* write dict begin */ - if (!bencode_start_dict(buf)) - return false; + oxenc::bt_dict_producer btdp; - /* write ai if they exist */ - if (!bencode_write_bytestring(buf, "a", 1)) - return false; - if (!BEncodeWriteList(addrs.begin(), addrs.end(), buf)) - return false; + btdp.append("a", addr.to_string()); + btdp.append("i", netID.ToView()); + btdp.append("k", pubkey.bt_encode()); - /* write netid */ - if (!bencode_write_bytestring(buf, "i", 1)) - return false; - if (!netID.BEncode(buf)) - return false; - /* write signing pubkey */ - if (!bencode_write_bytestring(buf, "k", 1)) - return false; - if (!pubkey.bt_encode(buf)) - return false; + auto n = Nick(); + if (not n.empty()) + btdp.append("n", n); - std::string nick = Nick(); - if (!nick.empty()) - { - /* write nickname */ - if (!bencode_write_bytestring(buf, "n", 1)) - { - return false; - } - if (!bencode_write_bytestring(buf, nick.c_str(), nick.size())) - { - return false; - } - } - - /* write encryption pubkey */ - if (!bencode_write_bytestring(buf, "p", 1)) - return false; - if (!enckey.bt_encode(buf)) - return false; + btdp.append("p", enckey.ToView()); + btdp.append("r", routerVersion); - // write router version if present - if (routerVersion) + if (not srvRecords.empty()) { - if (not BEncodeWriteDictEntry("r", *routerVersion, buf)) - return false; - } + auto sublist = btdp.append_list("s"); - if (version > 0) - { - // srv records if present - if (not BEncodeWriteDictList("s", srvRecords, buf)) - return false; - } - /* write last updated */ - if (!bencode_write_bytestring(buf, "u", 1)) - return false; - if (!bencode_write_uint64(buf, last_updated.count())) - return false; - - /* write versions */ - if (!bencode_write_uint64_entry(buf, "v", 1, version)) - return false; - - // D We can delete this? - if (serializeExit) - { - /* write xi if they exist */ - if (!bencode_write_bytestring(buf, "x", 1)) - return false; - /* no exits anymore in RCs */ - const std::vector> exits{}; - if (!BEncodeWriteList(exits.begin(), exits.end(), buf)) - return false; + for (auto& s : srvRecords) + sublist.append(s.bt_encode()); } - if (version == 0) - { - /* write signature */ - if (!bencode_write_bytestring(buf, "z", 1)) - return false; - if (!signature.bt_encode(buf)) - return false; - } + btdp.append("u", last_updated.count()); - return bencode_end(buf); + return std::move(btdp).str(); } void @@ -458,26 +396,16 @@ namespace llarp RouterContact::Sign(const SecretKey& secretkey) { pubkey = llarp::seckey_topublic(secretkey); - std::array tmp; - llarp_buffer_t buf(tmp); signature.Zero(); last_updated = time_now_ms(); - if (!BEncodeSignedSection(&buf)) - { - return false; - } - buf.sz = buf.cur - buf.base; - buf.cur = buf.base; - - signed_bt_dict = std::string(reinterpret_cast(buf.base), buf.sz); - - if (version == 0 or version == 1) - { - return CryptoManager::instance()->sign(signature, secretkey, buf); - } + signed_bt_dict = bencode_signed_section(); - return false; + return CryptoManager::instance()->sign( + signature, + secretkey, + reinterpret_cast(signed_bt_dict.data()), + signed_bt_dict.size()); } bool diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index 6fcd021aeb..765268328f 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -116,8 +116,8 @@ namespace llarp void bt_encode_subdict(oxenc::bt_list_producer& btlp) const; - bool - BEncodeSignedSection(llarp_buffer_t* buf) const; + std::string + bencode_signed_section() const; std::string ToTXTRecord() const; diff --git a/llarp/routing/message.hpp b/llarp/routing/message.hpp index ac04d30b36..c29b7be39b 100644 --- a/llarp/routing/message.hpp +++ b/llarp/routing/message.hpp @@ -42,17 +42,6 @@ namespace llarp // methods we do not want to inherit onwards from AbstractSerializable void - bt_encode(oxenc::bt_list_producer&) const final - { - throw std::runtime_error{ - "Error: Routing messages should not encode directly to a bt list producer!"}; - } - void - bt_encode(llarp_buffer&) const final - { - throw std::runtime_error{"Error: Routing messages should not encode directly to a buffer!"}; - } - void bt_encode(oxenc::bt_dict_producer&) const final { throw std::runtime_error{ diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 03dacb0a22..5194424569 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -1,7 +1,6 @@ #include "endpoint.hpp" #include "endpoint_state.hpp" #include "endpoint_util.hpp" -#include "hidden_service_address_lookup.hpp" #include "auth.hpp" #include "llarp/util/logging.hpp" #include "outbound_context.hpp" @@ -11,7 +10,6 @@ #include #include -#include #include #include #include @@ -408,7 +406,7 @@ namespace llarp std::set remote; for (const auto& introset : msg->found) { - if (not introset.Verify(Now())) + if (not introset.verify(Now())) { LogError(Name(), " got invalid introset"); return false; @@ -425,7 +423,7 @@ namespace llarp } std::unique_ptr lookup = std::move(itr->second); lookups.erase(itr); - lookup->HandleIntrosetResponse(remote); + // lookup->HandleIntrosetResponse(remote); return true; } @@ -716,43 +714,31 @@ namespace llarp auto* r = router(); const auto paths = GetManyPathsWithUniqueEndpoints( - this, - llarp::dht::INTROSET_RELAY_REDUNDANCY, - dht::Key_t{introset.derivedSigningKey.as_array()}); + this, INTROSET_RELAY_REDUNDANCY, dht::Key_t{introset.derivedSigningKey.as_array()}); - if (paths.size() != llarp::dht::INTROSET_RELAY_REDUNDANCY) + if (paths.size() != INTROSET_RELAY_REDUNDANCY) { LogWarn( "Cannot publish intro set because we only have ", paths.size(), " paths, but need ", - llarp::dht::INTROSET_RELAY_REDUNDANCY); + INTROSET_RELAY_REDUNDANCY); return false; } - // do publishing for each path selected - size_t published = 0; - for (const auto& path : paths) { - for (size_t i = 0; i < llarp::dht::INTROSET_REQS_PER_RELAY; ++i) + for (size_t i = 0; i < INTROSET_REQS_PER_RELAY; ++i) { r->notify_router_event( r->pubkey(), llarp::dht::Key_t{introset.derivedSigningKey.as_array()}, - RouterID(path->hops[path->hops.size() - 1].rc.pubkey), - published); - if (PublishIntroSetVia(introset, r, path, published)) - published++; + RouterID(path->hops[path->hops.size() - 1].rc.pubkey)); + + m_router->send_control_message(path->Upstream(), "publish_intro", introset.bt_encode()); } } - if (published != llarp::dht::INTROSET_STORAGE_REDUNDANCY) - LogWarn( - "Publish introset failed: could only publish ", - published, - " copies but wanted ", - llarp::dht::INTROSET_STORAGE_REDUNDANCY); - return published == llarp::dht::INTROSET_STORAGE_REDUNDANCY; + return true; } struct PublishIntroSetJob : public IServiceLookup diff --git a/llarp/service/intro_set.cpp b/llarp/service/intro_set.cpp index 6e6e38532b..a5e9386b11 100644 --- a/llarp/service/intro_set.cpp +++ b/llarp/service/intro_set.cpp @@ -6,6 +6,19 @@ namespace llarp::service { + EncryptedIntroSet::EncryptedIntroSet( + std::string signing_key, + std::chrono::milliseconds signed_at, + std::string enc_payload, + std::string nonce, + std::string s) + : signedAt{signed_at}, nounce{reinterpret_cast(nonce.data())} + { + derivedSigningKey = PubKey::from_string(signing_key); + introsetPayload = oxenc::bt_deserialize>(enc_payload); + sig.from_string(std::move(s)); + } + util::StatusObject EncryptedIntroSet::ExtractStatus() const { @@ -132,6 +145,12 @@ namespace llarp::service derivedSigningKey, reinterpret_cast(bte.data()), bte.size(), sig); } + bool + EncryptedIntroSet::verify(uint8_t* introset, size_t introset_size, uint8_t* key, uint8_t* sig) + { + return CryptoManager::instance()->verify(key, introset, introset_size, sig); + } + bool EncryptedIntroSet::verify(std::string introset, std::string key, std::string sig) { diff --git a/llarp/service/intro_set.hpp b/llarp/service/intro_set.hpp index a225b317a3..5107763303 100644 --- a/llarp/service/intro_set.hpp +++ b/llarp/service/intro_set.hpp @@ -139,6 +139,15 @@ namespace llarp::service std::optional topic; Signature sig; + EncryptedIntroSet() = default; + + explicit EncryptedIntroSet( + std::string signing_key, + std::chrono::milliseconds signed_at, + std::string enc_payload, + std::string nonce, + std::string sig); + bool Sign(const PrivateKey& k); @@ -164,6 +173,9 @@ namespace llarp::service bool verify(llarp_time_t now) const; + static bool + verify(uint8_t* introset, size_t introset_size, uint8_t* key, uint8_t* sig); + static bool verify(std::string introset, std::string key, std::string sig); diff --git a/llarp/util/aligned.hpp b/llarp/util/aligned.hpp index 3f6549041c..e1a1d6963b 100644 --- a/llarp/util/aligned.hpp +++ b/llarp/util/aligned.hpp @@ -56,13 +56,13 @@ namespace llarp explicit AlignedBuffer(const std::array& buf) { - m_data = buf; + _data = buf; } AlignedBuffer& operator=(const byte_t* data) { - std::memcpy(m_data.data(), data, sz); + std::memcpy(_data.data(), data, sz); return *this; } @@ -79,37 +79,37 @@ namespace llarp bool operator==(const AlignedBuffer& other) const { - return m_data == other.m_data; + return _data == other._data; } bool operator!=(const AlignedBuffer& other) const { - return m_data != other.m_data; + return _data != other._data; } bool operator<(const AlignedBuffer& other) const { - return m_data < other.m_data; + return _data < other._data; } bool operator>(const AlignedBuffer& other) const { - return m_data > other.m_data; + return _data > other._data; } bool operator<=(const AlignedBuffer& other) const { - return m_data <= other.m_data; + return _data <= other._data; } bool operator>=(const AlignedBuffer& other) const { - return m_data >= other.m_data; + return _data >= other._data; } AlignedBuffer @@ -126,7 +126,7 @@ namespace llarp // Mutate in place instead. for (size_t i = 0; i < sz; ++i) { - m_data[i] ^= other.m_data[i]; + _data[i] ^= other._data[i]; } return *this; } @@ -135,14 +135,14 @@ namespace llarp operator[](size_t idx) { assert(idx < SIZE); - return m_data[idx]; + return _data[idx]; } const byte_t& operator[](size_t idx) const { assert(idx < SIZE); - return m_data[idx]; + return _data[idx]; } static constexpr size_t @@ -154,31 +154,31 @@ namespace llarp void Fill(byte_t f) { - m_data.fill(f); + _data.fill(f); } std::array& as_array() { - return m_data; + return _data; } const std::array& as_array() const { - return m_data; + return _data; } byte_t* data() { - return m_data.data(); + return _data.data(); } const byte_t* data() const { - return m_data.data(); + return _data.data(); } bool @@ -196,7 +196,7 @@ namespace llarp void Zero() { - m_data.fill(0); + _data.fill(0); } virtual void @@ -208,25 +208,25 @@ namespace llarp typename std::array::iterator begin() { - return m_data.begin(); + return _data.begin(); } typename std::array::iterator end() { - return m_data.end(); + return _data.end(); } typename std::array::const_iterator begin() const { - return m_data.cbegin(); + return _data.cbegin(); } typename std::array::const_iterator end() const { - return m_data.cend(); + return _data.cend(); } bool @@ -241,6 +241,19 @@ namespace llarp return true; } + bool + from_string(std::string b) + { + if (b.size() != sz) + { + log::error(util_cat, "Error: buffer size mismatch in aligned buffer!"); + return false; + } + + std::memcpy(_data.data(), b.data(), b.size()); + return true; + } + bool bt_encode(llarp_buffer_t* buf) const { @@ -292,7 +305,7 @@ namespace llarp } private: - std::array m_data; + std::array _data; }; namespace detail diff --git a/llarp/util/logging.hpp b/llarp/util/logging.hpp index 09c31fc92b..40f1dbaf1e 100644 --- a/llarp/util/logging.hpp +++ b/llarp/util/logging.hpp @@ -15,6 +15,11 @@ namespace llarp namespace log = oxen::log; } +namespace +{ + static auto util_cat = llarp::log::Cat("lokinet.util"); +} // namespace + // Not ready to pollute these deprecation warnings everywhere yet #if 0 #define LOKINET_LOG_DEPRECATED(Meth) \ From 206bd0b85eab430b4acb406fd732a7b5130021d5 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Tue, 3 Oct 2023 13:00:23 -0700 Subject: [PATCH 043/312] wawaweewa --- daemon/lokinet.cpp | 4 +- llarp/CMakeLists.txt | 1 - llarp/config/config.hpp | 2 + llarp/dht/kademlia.hpp | 37 +- llarp/dht/key.hpp | 109 +- llarp/dht/messages/gotintro.cpp | 1 - llarp/dht/messages/gotname.cpp | 1 - llarp/dht/messages/gotrouter.cpp | 1 - llarp/dns/server.hpp | 1 + llarp/exit/session.cpp | 20 +- llarp/handlers/exit.hpp | 2 +- llarp/handlers/tun.cpp | 2426 ++++++++--------- llarp/handlers/tun.hpp | 530 ++-- llarp/link/contacts.cpp | 11 +- llarp/link/contacts.hpp | 8 +- llarp/link/link_manager.cpp | 389 ++- llarp/link/link_manager.hpp | 61 +- llarp/messages/common.hpp | 9 +- llarp/messages/dht.hpp | 121 +- llarp/messages/path.hpp | 25 + llarp/net/traffic_policy.cpp | 39 +- llarp/net/traffic_policy.hpp | 4 + llarp/path/pathbuilder.cpp | 48 +- llarp/path/pathbuilder.hpp | 2 +- llarp/path/pathset.hpp | 6 - llarp/router/rc_lookup_handler.cpp | 2 +- llarp/router/router.cpp | 2 +- llarp/router_contact.cpp | 50 +- llarp/router_contact.hpp | 2 + llarp/service/async_key_exchange.cpp | 18 +- llarp/service/async_key_exchange.hpp | 4 +- llarp/service/auth.hpp | 9 +- llarp/service/endpoint.cpp | 466 +--- llarp/service/endpoint.hpp | 88 +- llarp/service/endpoint_state.cpp | 30 +- llarp/service/endpoint_state.hpp | 75 +- llarp/service/endpoint_types.hpp | 23 +- llarp/service/endpoint_util.cpp | 26 +- llarp/service/endpoint_util.hpp | 26 +- llarp/service/handler.hpp | 84 - .../service/hidden_service_address_lookup.cpp | 58 - .../service/hidden_service_address_lookup.hpp | 50 - llarp/service/info.cpp | 16 +- llarp/service/info.hpp | 3 + llarp/service/intro.cpp | 30 +- llarp/service/intro.hpp | 4 +- llarp/service/intro_set.cpp | 129 +- llarp/service/intro_set.hpp | 12 +- llarp/service/outbound_context.cpp | 36 +- llarp/service/protocol.cpp | 3 - llarp/service/protocol.hpp | 2 +- llarp/service/sendcontext.hpp | 153 +- llarp/service/session.cpp | 87 +- llarp/service/session.hpp | 72 +- 54 files changed, 2628 insertions(+), 2790 deletions(-) create mode 100644 llarp/messages/path.hpp delete mode 100644 llarp/service/handler.hpp delete mode 100644 llarp/service/hidden_service_address_lookup.cpp delete mode 100644 llarp/service/hidden_service_address_lookup.hpp diff --git a/daemon/lokinet.cpp b/daemon/lokinet.cpp index f4607a9f96..4aa061ec11 100644 --- a/daemon/lokinet.cpp +++ b/daemon/lokinet.cpp @@ -508,7 +508,7 @@ namespace { auto deadlock_cat = llarp::log::Cat("deadlock"); for (const auto& wtf : - {"you have been visited by the mascott of the deadlocked router.", + {"you have been visited by the mascot of the deadlocked router.", "⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⣀⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠄⠄⠄⠄", "⠄⠄⠄⠄⠄⢀⣀⣀⡀⠄⠄⠄⡠⢲⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡀⠄⠄", "⠄⠄⠄⠔⣈⣀⠄⢔⡒⠳⡴⠊⠄⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠿⣿⣿⣧⠄⠄", @@ -674,4 +674,4 @@ main(int argc, char* argv[]) return 1; } #endif -} \ No newline at end of file +} diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index f8676e96ab..a3e138c8ca 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -276,7 +276,6 @@ add_library(lokinet-service-deprecated-kitchensink service/endpoint_state.cpp service/endpoint_util.cpp service/endpoint.cpp - service/hidden_service_address_lookup.cpp service/identity.cpp service/info.cpp service/intro_set.cpp diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index 3165f03543..af4f63ed86 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -1,6 +1,8 @@ #pragma once #include "ini.hpp" #include "definition.hpp" +#include +#include #include diff --git a/llarp/dht/kademlia.hpp b/llarp/dht/kademlia.hpp index af0ca20f07..b2889ac6ad 100644 --- a/llarp/dht/kademlia.hpp +++ b/llarp/dht/kademlia.hpp @@ -3,28 +3,25 @@ #include "key.hpp" #include -namespace llarp +namespace llarp::dht { - namespace dht + struct XorMetric { - struct XorMetric - { - const Key_t us; + const Key_t us; - XorMetric(const Key_t& ourKey) : us(ourKey) - {} + XorMetric(const Key_t& ourKey) : us(ourKey) + {} - bool - operator()(const Key_t& left, const Key_t& right) const - { - return (us ^ left) < (us ^ right); - } + bool + operator()(const Key_t& left, const Key_t& right) const + { + return (us ^ left) < (us ^ right); + } - bool - operator()(const RouterContact& left, const RouterContact& right) const - { - return (left.pubkey ^ us) < (right.pubkey ^ us); - } - }; - } // namespace dht -} // namespace llarp + bool + operator()(const RouterContact& left, const RouterContact& right) const + { + return (left.pubkey ^ us) < (right.pubkey ^ us); + } + }; +} // namespace llarp::dht diff --git a/llarp/dht/key.hpp b/llarp/dht/key.hpp index 28ef35e3e5..006bd9ff52 100644 --- a/llarp/dht/key.hpp +++ b/llarp/dht/key.hpp @@ -6,72 +6,69 @@ #include -namespace llarp +namespace llarp::dht { - namespace dht + struct Key_t : public AlignedBuffer<32> { - struct Key_t : public AlignedBuffer<32> - { - explicit Key_t(const byte_t* buf) : AlignedBuffer(buf) - {} + explicit Key_t(const byte_t* buf) : AlignedBuffer(buf) + {} - explicit Key_t(const std::array& data) : AlignedBuffer(data) - {} + explicit Key_t(const std::array& data) : AlignedBuffer(data) + {} - explicit Key_t(const AlignedBuffer& data) : AlignedBuffer(data) - {} + explicit Key_t(const AlignedBuffer& data) : AlignedBuffer(data) + {} - Key_t() : AlignedBuffer() - {} + Key_t() : AlignedBuffer() + {} - /// get snode address string - std::string - SNode() const - { - const RouterID rid{as_array()}; - return rid.ToString(); - } + /// get snode address string + std::string + SNode() const + { + const RouterID rid{as_array()}; + return rid.ToString(); + } - util::StatusObject - ExtractStatus() const; + util::StatusObject + ExtractStatus() const; - std::string - ToString() const - { - return SNode(); - } + std::string + ToString() const + { + return SNode(); + } - Key_t - operator^(const Key_t& other) const - { - Key_t dist; - std::transform(begin(), end(), other.begin(), dist.begin(), std::bit_xor()); - return dist; - } + Key_t + operator^(const Key_t& other) const + { + Key_t dist; + std::transform(begin(), end(), other.begin(), dist.begin(), std::bit_xor()); + return dist; + } - bool - operator==(const Key_t& other) const - { - return as_array() == other.as_array(); - } + bool + operator==(const Key_t& other) const + { + return as_array() == other.as_array(); + } - bool - operator!=(const Key_t& other) const - { - return as_array() != other.as_array(); - } + bool + operator!=(const Key_t& other) const + { + return as_array() != other.as_array(); + } - bool - operator<(const Key_t& other) const - { - return as_array() < other.as_array(); - } + bool + operator<(const Key_t& other) const + { + return as_array() < other.as_array(); + } - bool - operator>(const Key_t& other) const - { - return as_array() > other.as_array(); - } - }; - } // namespace dht -} // namespace llarp + bool + operator>(const Key_t& other) const + { + return as_array() > other.as_array(); + } + }; +} // namespace llarp::dht diff --git a/llarp/dht/messages/gotintro.cpp b/llarp/dht/messages/gotintro.cpp index ddc1e2c01e..e93fa6f60c 100644 --- a/llarp/dht/messages/gotintro.cpp +++ b/llarp/dht/messages/gotintro.cpp @@ -1,7 +1,6 @@ #include "gotintro.hpp" #include -#include #include #include #include diff --git a/llarp/dht/messages/gotname.cpp b/llarp/dht/messages/gotname.cpp index 1f927e31b2..d1b534d540 100644 --- a/llarp/dht/messages/gotname.cpp +++ b/llarp/dht/messages/gotname.cpp @@ -1,6 +1,5 @@ #include "gotname.hpp" #include -#include #include #include diff --git a/llarp/dht/messages/gotrouter.cpp b/llarp/dht/messages/gotrouter.cpp index 4113c0b3b2..79b3b2967d 100644 --- a/llarp/dht/messages/gotrouter.cpp +++ b/llarp/dht/messages/gotrouter.cpp @@ -1,4 +1,3 @@ -#include #include "gotrouter.hpp" #include diff --git a/llarp/dns/server.hpp b/llarp/dns/server.hpp index 6b1ba54b3f..f39b017e4b 100644 --- a/llarp/dns/server.hpp +++ b/llarp/dns/server.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include namespace llarp::dns diff --git a/llarp/exit/session.cpp b/llarp/exit/session.cpp index 4d5a3081e3..58112dbc83 100644 --- a/llarp/exit/session.cpp +++ b/llarp/exit/session.cpp @@ -76,7 +76,7 @@ namespace llarp::exit { if (numHops == 1) { - if (auto maybe = m_router->node_db()->Get(m_ExitRouter)) + if (auto maybe = router->node_db()->Get(m_ExitRouter)) return std::vector{*maybe}; return std::nullopt; } @@ -108,7 +108,7 @@ namespace llarp::exit llarp::LogError("Failed to sign exit request"); return; } - if (p->SendExitRequest(obtain, m_router)) + if (p->SendExitRequest(obtain, router)) llarp::LogInfo("asking ", m_ExitRouter, " for exit"); else llarp::LogError("failed to send exit request"); @@ -161,7 +161,7 @@ namespace llarp::exit { llarp::LogInfo(p->Name(), " closing exit path"); routing::CloseExitMessage msg; - if (msg.Sign(m_ExitIdentity) && p->SendExitClose(msg, m_router)) + if (msg.Sign(m_ExitIdentity) && p->SendExitClose(msg, router)) { p->ClearRoles(roles); } @@ -182,12 +182,12 @@ namespace llarp::exit { LogInfo(p->Name(), " closing exit path"); routing::CloseExitMessage msg; - if (!(msg.Sign(m_ExitIdentity) && p->SendExitClose(msg, m_router))) + if (!(msg.Sign(m_ExitIdentity) && p->SendExitClose(msg, router))) LogWarn(p->Name(), " failed to send exit close message"); } }; ForEachPath(sendExitClose); - m_router->path_context().RemovePathSet(shared_from_this()); + router->path_context().RemovePathSet(shared_from_this()); return path::Builder::Stop(); } @@ -214,7 +214,7 @@ namespace llarp::exit llarp::net::IPPacket pkt{buf.view_all()}; if (pkt.empty()) return false; - m_LastUse = m_router->now(); + m_LastUse = router->now(); m_Downstream.emplace(counter, pkt); return true; } @@ -225,7 +225,7 @@ namespace llarp::exit BaseSession::HandleTrafficDrop(llarp::path::Path_ptr p, const PathID_t& path, uint64_t s) { llarp::LogError("dropped traffic on exit ", m_ExitRouter, " S=", s, " P=", path); - p->EnterState(path::ePathIgnore, m_router->now()); + p->EnterState(path::ePathIgnore, router->now()); return true; } @@ -283,7 +283,7 @@ namespace llarp::exit bool BaseSession::FlushUpstream() { - auto now = m_router->now(); + auto now = router->now(); auto path = PickEstablishedPath(llarp::path::ePathRoleExit); if (path) { @@ -293,7 +293,7 @@ namespace llarp::exit { auto& msg = queue.front(); msg.sequence_number = path->NextSeqNo(); - path->SendRoutingMessage(msg, m_router); + path->SendRoutingMessage(msg, router); queue.pop_front(); } } @@ -308,7 +308,7 @@ namespace llarp::exit m_Upstream.clear(); if (numHops == 1) { - auto r = m_router; + auto r = router; if (const auto maybe = r->node_db()->Get(m_ExitRouter); maybe.has_value()) r->TryConnectAsync(*maybe, 5); else diff --git a/llarp/handlers/exit.hpp b/llarp/handlers/exit.hpp index 7899141fa6..8723734a6a 100644 --- a/llarp/handlers/exit.hpp +++ b/llarp/handlers/exit.hpp @@ -55,7 +55,7 @@ namespace llarp Loop() override; std::unordered_set - AllRemoteEndpoints() const override; + AllRemoteEndpoints() const; void SRVRecordsChanged() override; diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index cc43ed0862..8ac2822022 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -31,1516 +31,1512 @@ #include -namespace llarp +namespace llarp::handlers { - namespace handlers + static auto logcat = log::Cat("tun"); + + bool + TunEndpoint::MaybeHookDNS( + std::shared_ptr source, + const dns::Message& query, + const SockAddr& to, + const SockAddr& from) { - static auto logcat = log::Cat("tun"); - - bool - TunEndpoint::MaybeHookDNS( - std::shared_ptr source, - const dns::Message& query, - const SockAddr& to, - const SockAddr& from) - { - if (not ShouldHookDNSMessage(query)) - return false; + if (not ShouldHookDNSMessage(query)) + return false; - auto job = std::make_shared(source, query, to, from); - if (HandleHookedDNSMessage(query, [job](auto msg) { job->SendReply(msg.ToBuffer()); })) - router()->TriggerPump(); - else - job->Cancel(); - return true; - } + auto job = std::make_shared(source, query, to, from); + if (HandleHookedDNSMessage(query, [job](auto msg) { job->SendReply(msg.ToBuffer()); })) + router()->TriggerPump(); + else + job->Cancel(); + return true; + } + + /// Intercepts DNS IP packets on platforms where binding to a low port isn't viable. + /// (windows/macos/ios/android ... aka everything that is not linux... funny that) + class DnsInterceptor : public dns::PacketSource_Base + { + std::function m_Reply; + net::ipaddr_t m_OurIP; + llarp::DnsConfig m_Config; - /// Intercepts DNS IP packets on platforms where binding to a low port isn't viable. - /// (windows/macos/ios/android ... aka everything that is not linux... funny that) - class DnsInterceptor : public dns::PacketSource_Base - { - std::function m_Reply; - net::ipaddr_t m_OurIP; - llarp::DnsConfig m_Config; + public: + explicit DnsInterceptor( + std::function reply, net::ipaddr_t our_ip, llarp::DnsConfig conf) + : m_Reply{std::move(reply)}, m_OurIP{std::move(our_ip)}, m_Config{std::move(conf)} + {} - public: - explicit DnsInterceptor( - std::function reply, net::ipaddr_t our_ip, llarp::DnsConfig conf) - : m_Reply{std::move(reply)}, m_OurIP{std::move(our_ip)}, m_Config{std::move(conf)} - {} + ~DnsInterceptor() override = default; - ~DnsInterceptor() override = default; + void + SendTo(const SockAddr& to, const SockAddr& from, OwnedBuffer buf) const override + { + auto pkt = net::IPPacket::make_udp(from, to, std::move(buf)); - void - SendTo(const SockAddr& to, const SockAddr& from, OwnedBuffer buf) const override - { - auto pkt = net::IPPacket::make_udp(from, to, std::move(buf)); + if (pkt.empty()) + return; + m_Reply(std::move(pkt)); + } - if (pkt.empty()) - return; - m_Reply(std::move(pkt)); - } + void + Stop() override{}; - void - Stop() override{}; + std::optional + BoundOn() const override + { + return std::nullopt; + } - std::optional - BoundOn() const override + bool + WouldLoop(const SockAddr& to, const SockAddr& from) const override + { + if constexpr (platform::is_apple) { - return std::nullopt; + // DNS on Apple is a bit weird because in order for the NetworkExtension itself to send + // data through the tunnel we have to proxy DNS requests through Apple APIs (and so our + // actual upstream DNS won't be set in our resolvers, which is why the vanilla WouldLoop + // won't work for us). However when active the mac also only queries the main tunnel IP + // for DNS, so we consider anything else to be upstream-bound DNS to let it through the + // tunnel. + return to.getIP() != m_OurIP; } - - bool - WouldLoop(const SockAddr& to, const SockAddr& from) const override + else if (auto maybe_addr = m_Config.m_QueryBind) { - if constexpr (platform::is_apple) - { - // DNS on Apple is a bit weird because in order for the NetworkExtension itself to send - // data through the tunnel we have to proxy DNS requests through Apple APIs (and so our - // actual upstream DNS won't be set in our resolvers, which is why the vanilla WouldLoop - // won't work for us). However when active the mac also only queries the main tunnel IP - // for DNS, so we consider anything else to be upstream-bound DNS to let it through the - // tunnel. - return to.getIP() != m_OurIP; - } - else if (auto maybe_addr = m_Config.m_QueryBind) - { - const auto& addr = *maybe_addr; - // omit traffic to and from our dns socket - return addr == to or addr == from; - } - return false; + const auto& addr = *maybe_addr; + // omit traffic to and from our dns socket + return addr == to or addr == from; } - }; - - class TunDNS : public dns::Server - { - std::optional m_QueryBind; - net::ipaddr_t m_OurIP; - TunEndpoint* const m_Endpoint; + return false; + } + }; - public: - std::shared_ptr PacketSource; + class TunDNS : public dns::Server + { + std::optional m_QueryBind; + net::ipaddr_t m_OurIP; + TunEndpoint* const m_Endpoint; - virtual ~TunDNS() = default; + public: + std::shared_ptr PacketSource; - explicit TunDNS(TunEndpoint* ep, const llarp::DnsConfig& conf) - : dns::Server{ep->router()->loop(), conf, 0} - , m_QueryBind{conf.m_QueryBind} - , m_OurIP{ToNet(ep->GetIfAddr())} - , m_Endpoint{ep} - {} + virtual ~TunDNS() = default; - std::shared_ptr - MakePacketSourceOn(const SockAddr&, const llarp::DnsConfig& conf) override - { - auto ptr = std::make_shared( - [ep = m_Endpoint](auto pkt) { - ep->HandleWriteIPPacket(pkt.ConstBuffer(), pkt.srcv6(), pkt.dstv6(), 0); - }, - m_OurIP, - conf); - PacketSource = ptr; - return ptr; - } - }; + explicit TunDNS(TunEndpoint* ep, const llarp::DnsConfig& conf) + : dns::Server{ep->router()->loop(), conf, 0} + , m_QueryBind{conf.m_QueryBind} + , m_OurIP{ToNet(ep->GetIfAddr())} + , m_Endpoint{ep} + {} - TunEndpoint::TunEndpoint(Router* r, service::Context* parent) : service::Endpoint{r, parent} + std::shared_ptr + MakePacketSourceOn(const SockAddr&, const llarp::DnsConfig& conf) override { - m_PacketRouter = std::make_shared( - [this](net::IPPacket pkt) { HandleGotUserPacket(std::move(pkt)); }); + auto ptr = std::make_shared( + [ep = m_Endpoint](auto pkt) { + ep->HandleWriteIPPacket(pkt.ConstBuffer(), pkt.srcv6(), pkt.dstv6(), 0); + }, + m_OurIP, + conf); + PacketSource = ptr; + return ptr; } + }; - void - TunEndpoint::SetupDNS() + TunEndpoint::TunEndpoint(Router* r, service::Context* parent) : service::Endpoint{r, parent} + { + m_PacketRouter = std::make_shared( + [this](net::IPPacket pkt) { HandleGotUserPacket(std::move(pkt)); }); + } + + void + TunEndpoint::SetupDNS() + { + const auto& info = GetVPNInterface()->Info(); + if (m_DnsConfig.m_raw_dns) { - const auto& info = GetVPNInterface()->Info(); - if (m_DnsConfig.m_raw_dns) - { - auto dns = std::make_shared(this, m_DnsConfig); - m_DNS = dns; - - m_PacketRouter->AddUDPHandler(huint16_t{53}, [this, dns](net::IPPacket pkt) { - auto dns_pkt_src = dns->PacketSource; - if (const auto& reply = pkt.reply) - dns_pkt_src = std::make_shared(dns_pkt_src, reply); - if (dns->MaybeHandlePacket( - std::move(dns_pkt_src), pkt.dst(), pkt.src(), *pkt.L4OwnedBuffer())) - return; - - HandleGotUserPacket(std::move(pkt)); - }); - } - else - m_DNS = std::make_shared(Loop(), m_DnsConfig, info.index); + auto dns = std::make_shared(this, m_DnsConfig); + m_DNS = dns; + + m_PacketRouter->AddUDPHandler(huint16_t{53}, [this, dns](net::IPPacket pkt) { + auto dns_pkt_src = dns->PacketSource; + if (const auto& reply = pkt.reply) + dns_pkt_src = std::make_shared(dns_pkt_src, reply); + if (dns->MaybeHandlePacket( + std::move(dns_pkt_src), pkt.dst(), pkt.src(), *pkt.L4OwnedBuffer())) + return; - m_DNS->AddResolver(weak_from_this()); - m_DNS->Start(); + HandleGotUserPacket(std::move(pkt)); + }); + } + else + m_DNS = std::make_shared(Loop(), m_DnsConfig, info.index); + + m_DNS->AddResolver(weak_from_this()); + m_DNS->Start(); - if (m_DnsConfig.m_raw_dns) + if (m_DnsConfig.m_raw_dns) + { + if (auto vpn = router()->vpn_platform()) { - if (auto vpn = router()->vpn_platform()) + // get the first local address we know of + std::optional localaddr; + for (auto res : m_DNS->GetAllResolvers()) { - // get the first local address we know of - std::optional localaddr; - for (auto res : m_DNS->GetAllResolvers()) + if (auto ptr = res.lock()) { - if (auto ptr = res.lock()) + localaddr = ptr->GetLocalAddr(); + if (localaddr) + break; + } + } + if (platform::is_windows) + { + auto dns_io = vpn->create_packet_io(0, localaddr); + router()->loop()->add_ticker([r = router(), dns_io, handler = m_PacketRouter]() { + net::IPPacket pkt = dns_io->ReadNextPacket(); + while (not pkt.empty()) { - localaddr = ptr->GetLocalAddr(); - if (localaddr) - break; + handler->HandleIPPacket(std::move(pkt)); + pkt = dns_io->ReadNextPacket(); } - } - if (platform::is_windows) - { - auto dns_io = vpn->create_packet_io(0, localaddr); - router()->loop()->add_ticker([r = router(), dns_io, handler = m_PacketRouter]() { - net::IPPacket pkt = dns_io->ReadNextPacket(); - while (not pkt.empty()) - { - handler->HandleIPPacket(std::move(pkt)); - pkt = dns_io->ReadNextPacket(); - } - }); - m_RawDNS = dns_io; - } + }); + m_RawDNS = dns_io; } - - if (m_RawDNS) - m_RawDNS->Start(); } + + if (m_RawDNS) + m_RawDNS->Start(); + } + } + + util::StatusObject + TunEndpoint::ExtractStatus() const + { + auto obj = service::Endpoint::ExtractStatus(); + obj["ifaddr"] = m_OurRange.ToString(); + obj["ifname"] = m_IfName; + + std::vector upstreamRes; + for (const auto& ent : m_DnsConfig.m_upstreamDNS) + upstreamRes.emplace_back(ent.ToString()); + obj["ustreamResolvers"] = upstreamRes; + + std::vector localRes; + for (const auto& ent : m_DnsConfig.m_bind) + localRes.emplace_back(ent.ToString()); + obj["localResolvers"] = localRes; + + // for backwards compat + if (not m_DnsConfig.m_bind.empty()) + obj["localResolver"] = localRes[0]; + + util::StatusObject ips{}; + for (const auto& item : m_IPActivity) + { + util::StatusObject ipObj{{"lastActive", to_json(item.second)}}; + std::string remoteStr; + AlignedBuffer<32> addr = m_IPToAddr.at(item.first); + if (m_SNodes.at(addr)) + remoteStr = RouterID(addr.as_array()).ToString(); + else + remoteStr = service::Address(addr.as_array()).ToString(); + ipObj["remote"] = remoteStr; + std::string ipaddr = item.first.ToString(); + ips[ipaddr] = ipObj; } + obj["addrs"] = ips; + obj["ourIP"] = m_OurIP.ToString(); + obj["nextIP"] = m_NextIP.ToString(); + obj["maxIP"] = m_MaxIP.ToString(); + return obj; + } + + void + TunEndpoint::Thaw() + { + if (m_DNS) + m_DNS->Reset(); + } - util::StatusObject - TunEndpoint::ExtractStatus() const + void + TunEndpoint::ReconfigureDNS(std::vector servers) + { + if (m_DNS) { - auto obj = service::Endpoint::ExtractStatus(); - obj["ifaddr"] = m_OurRange.ToString(); - obj["ifname"] = m_IfName; - - std::vector upstreamRes; - for (const auto& ent : m_DnsConfig.m_upstreamDNS) - upstreamRes.emplace_back(ent.ToString()); - obj["ustreamResolvers"] = upstreamRes; - - std::vector localRes; - for (const auto& ent : m_DnsConfig.m_bind) - localRes.emplace_back(ent.ToString()); - obj["localResolvers"] = localRes; - - // for backwards compat - if (not m_DnsConfig.m_bind.empty()) - obj["localResolver"] = localRes[0]; - - util::StatusObject ips{}; - for (const auto& item : m_IPActivity) + for (auto weak : m_DNS->GetAllResolvers()) { - util::StatusObject ipObj{{"lastActive", to_json(item.second)}}; - std::string remoteStr; - AlignedBuffer<32> addr = m_IPToAddr.at(item.first); - if (m_SNodes.at(addr)) - remoteStr = RouterID(addr.as_array()).ToString(); - else - remoteStr = service::Address(addr.as_array()).ToString(); - ipObj["remote"] = remoteStr; - std::string ipaddr = item.first.ToString(); - ips[ipaddr] = ipObj; + if (auto ptr = weak.lock()) + ptr->ResetResolver(servers); } - obj["addrs"] = ips; - obj["ourIP"] = m_OurIP.ToString(); - obj["nextIP"] = m_NextIP.ToString(); - obj["maxIP"] = m_MaxIP.ToString(); - return obj; } + } - void - TunEndpoint::Thaw() + bool + TunEndpoint::Configure(const NetworkConfig& conf, const DnsConfig& dnsConf) + { + if (conf.m_reachable) { - if (m_DNS) - m_DNS->Reset(); + _publish_introset = true; + LogInfo(Name(), " setting to be reachable by default"); } - - void - TunEndpoint::ReconfigureDNS(std::vector servers) + else { - if (m_DNS) - { - for (auto weak : m_DNS->GetAllResolvers()) - { - if (auto ptr = weak.lock()) - ptr->ResetResolver(servers); - } - } + _publish_introset = false; + LogInfo(Name(), " setting to be not reachable by default"); } - bool - TunEndpoint::Configure(const NetworkConfig& conf, const DnsConfig& dnsConf) + if (conf.m_AuthType == service::AuthType::eAuthTypeFile) { - if (conf.m_reachable) - { - _publish_introset = true; - LogInfo(Name(), " setting to be reachable by default"); - } - else + _auth_policy = service::MakeFileAuthPolicy(router, conf.m_AuthFiles, conf.m_AuthFileType); + } + else if (conf.m_AuthType != service::AuthType::eAuthTypeNone) + { + std::string url, method; + if (conf.m_AuthUrl.has_value() and conf.m_AuthMethod.has_value()) { - _publish_introset = false; - LogInfo(Name(), " setting to be not reachable by default"); + url = *conf.m_AuthUrl; + method = *conf.m_AuthMethod; } + auto auth = std::make_shared( + url, + method, + conf.m_AuthWhitelist, + conf.m_AuthStaticTokens, + router()->lmq(), + shared_from_this()); + auth->Start(); + _auth_policy = std::move(auth); + } - if (conf.m_AuthType == service::AuthType::eAuthTypeFile) - { - _auth_policy = service::MakeFileAuthPolicy(m_router, conf.m_AuthFiles, conf.m_AuthFileType); - } - else if (conf.m_AuthType != service::AuthType::eAuthTypeNone) - { - std::string url, method; - if (conf.m_AuthUrl.has_value() and conf.m_AuthMethod.has_value()) - { - url = *conf.m_AuthUrl; - method = *conf.m_AuthMethod; - } - auto auth = std::make_shared( - url, - method, - conf.m_AuthWhitelist, - conf.m_AuthStaticTokens, - router()->lmq(), - shared_from_this()); - auth->Start(); - _auth_policy = std::move(auth); - } + m_DnsConfig = dnsConf; + m_TrafficPolicy = conf.m_TrafficPolicy; + m_OwnedRanges = conf.m_OwnedRanges; - m_DnsConfig = dnsConf; - m_TrafficPolicy = conf.m_TrafficPolicy; - m_OwnedRanges = conf.m_OwnedRanges; + m_BaseV6Address = conf.m_baseV6Address; - m_BaseV6Address = conf.m_baseV6Address; + if (conf.m_PathAlignmentTimeout) + { + m_PathAlignmentTimeout = *conf.m_PathAlignmentTimeout; + } + else + m_PathAlignmentTimeout = service::Endpoint::PathAlignmentTimeout(); - if (conf.m_PathAlignmentTimeout) - { - m_PathAlignmentTimeout = *conf.m_PathAlignmentTimeout; - } - else - m_PathAlignmentTimeout = service::Endpoint::PathAlignmentTimeout(); + for (const auto& item : conf.m_mapAddrs) + { + if (not MapAddress(item.second, item.first, false)) + return false; + } - for (const auto& item : conf.m_mapAddrs) - { - if (not MapAddress(item.second, item.first, false)) - return false; - } + m_IfName = conf.m_ifname; + if (m_IfName.empty()) + { + const auto maybe = router->net().FindFreeTun(); + if (not maybe.has_value()) + throw std::runtime_error("cannot find free interface name"); + m_IfName = *maybe; + } - m_IfName = conf.m_ifname; - if (m_IfName.empty()) + m_OurRange = conf.m_ifaddr; + if (!m_OurRange.addr.h) + { + const auto maybe = router->net().FindFreeRange(); + if (not maybe.has_value()) { - const auto maybe = m_router->net().FindFreeTun(); - if (not maybe.has_value()) - throw std::runtime_error("cannot find free interface name"); - m_IfName = *maybe; - } - - m_OurRange = conf.m_ifaddr; - if (!m_OurRange.addr.h) - { - const auto maybe = m_router->net().FindFreeRange(); - if (not maybe.has_value()) - { - throw std::runtime_error("cannot find free address range"); - } - m_OurRange = *maybe; + throw std::runtime_error("cannot find free address range"); } + m_OurRange = *maybe; + } - m_OurIP = m_OurRange.addr; - m_UseV6 = false; + m_OurIP = m_OurRange.addr; + m_UseV6 = false; - m_PersistAddrMapFile = conf.m_AddrMapPersistFile; - if (m_PersistAddrMapFile) + m_PersistAddrMapFile = conf.m_AddrMapPersistFile; + if (m_PersistAddrMapFile) + { + const auto& file = *m_PersistAddrMapFile; + if (fs::exists(file)) { - const auto& file = *m_PersistAddrMapFile; - if (fs::exists(file)) + bool shouldLoadFile = true; { - bool shouldLoadFile = true; + constexpr auto LastModifiedWindow = 1min; + const auto lastmodified = fs::last_write_time(file); + const auto now = decltype(lastmodified)::clock::now(); + if (now < lastmodified or now - lastmodified > LastModifiedWindow) { - constexpr auto LastModifiedWindow = 1min; - const auto lastmodified = fs::last_write_time(file); - const auto now = decltype(lastmodified)::clock::now(); - if (now < lastmodified or now - lastmodified > LastModifiedWindow) - { - shouldLoadFile = false; - } + shouldLoadFile = false; } - std::vector data; - if (auto maybe = util::OpenFileStream(file, std::ios_base::binary); - maybe and shouldLoadFile) + } + std::vector data; + if (auto maybe = util::OpenFileStream(file, std::ios_base::binary); + maybe and shouldLoadFile) + { + LogInfo(Name(), " loading address map file from ", file); + maybe->seekg(0, std::ios_base::end); + const size_t len = maybe->tellg(); + maybe->seekg(0, std::ios_base::beg); + data.resize(len); + LogInfo(Name(), " reading ", len, " bytes"); + maybe->read(data.data(), data.size()); + } + else + { + if (shouldLoadFile) { - LogInfo(Name(), " loading address map file from ", file); - maybe->seekg(0, std::ios_base::end); - const size_t len = maybe->tellg(); - maybe->seekg(0, std::ios_base::beg); - data.resize(len); - LogInfo(Name(), " reading ", len, " bytes"); - maybe->read(data.data(), data.size()); + LogInfo(Name(), " address map file ", file, " does not exist, so we won't load it"); } else + LogInfo(Name(), " address map file ", file, " not loaded because it's stale"); + } + if (not data.empty()) + { + std::string_view bdata{data.data(), data.size()}; + LogDebug(Name(), " parsing address map data: ", bdata); + const auto parsed = oxenc::bt_deserialize(bdata); + for (const auto& [key, value] : parsed) { - if (shouldLoadFile) + huint128_t ip{}; + if (not ip.FromString(key)) { - LogInfo(Name(), " address map file ", file, " does not exist, so we won't load it"); + LogWarn(Name(), " malformed IP in addr map data: ", key); + continue; } - else - LogInfo(Name(), " address map file ", file, " not loaded because it's stale"); - } - if (not data.empty()) - { - std::string_view bdata{data.data(), data.size()}; - LogDebug(Name(), " parsing address map data: ", bdata); - const auto parsed = oxenc::bt_deserialize(bdata); - for (const auto& [key, value] : parsed) + if (m_OurIP == ip) + continue; + if (not m_OurRange.Contains(ip)) { - huint128_t ip{}; - if (not ip.FromString(key)) - { - LogWarn(Name(), " malformed IP in addr map data: ", key); - continue; - } - if (m_OurIP == ip) - continue; - if (not m_OurRange.Contains(ip)) - { - LogWarn(Name(), " out of range IP in addr map data: ", ip); - continue; - } - EndpointBase::AddressVariant_t addr; + LogWarn(Name(), " out of range IP in addr map data: ", ip); + continue; + } + EndpointBase::AddressVariant_t addr; - if (const auto* str = std::get_if(&value)) + if (const auto* str = std::get_if(&value)) + { + if (auto maybe = service::ParseAddress(*str)) { - if (auto maybe = service::ParseAddress(*str)) - { - addr = *maybe; - } - else - { - LogWarn(Name(), " invalid address in addr map: ", *str); - continue; - } + addr = *maybe; } else { - LogWarn(Name(), " invalid first entry in addr map, not a string"); + LogWarn(Name(), " invalid address in addr map: ", *str); continue; } - if (const auto* loki = std::get_if(&addr)) - { - m_IPToAddr.emplace(ip, loki->data()); - m_AddrToIP.emplace(loki->data(), ip); - m_SNodes[*loki] = false; - LogInfo(Name(), " remapped ", ip, " to ", *loki); - } - if (const auto* snode = std::get_if(&addr)) - { - m_IPToAddr.emplace(ip, snode->data()); - m_AddrToIP.emplace(snode->data(), ip); - m_SNodes[*snode] = true; - LogInfo(Name(), " remapped ", ip, " to ", *snode); - } - if (m_NextIP < ip) - m_NextIP = ip; - // make sure we dont unmap this guy - MarkIPActive(ip); } + else + { + LogWarn(Name(), " invalid first entry in addr map, not a string"); + continue; + } + if (const auto* loki = std::get_if(&addr)) + { + m_IPToAddr.emplace(ip, loki->data()); + m_AddrToIP.emplace(loki->data(), ip); + m_SNodes[*loki] = false; + LogInfo(Name(), " remapped ", ip, " to ", *loki); + } + if (const auto* snode = std::get_if(&addr)) + { + m_IPToAddr.emplace(ip, snode->data()); + m_AddrToIP.emplace(snode->data(), ip); + m_SNodes[*snode] = true; + LogInfo(Name(), " remapped ", ip, " to ", *snode); + } + if (m_NextIP < ip) + m_NextIP = ip; + // make sure we dont unmap this guy + MarkIPActive(ip); } } - else - { - LogInfo( - Name(), " skipping loading addr map at ", file, " as it does not currently exist"); - } } - - if (auto* quic = GetQUICTunnel()) + else { - quic->listen([this](std::string_view, uint16_t port) { - return llarp::SockAddr{net::TruncateV6(GetIfAddr()), huint16_t{port}}; - }); + LogInfo(Name(), " skipping loading addr map at ", file, " as it does not currently exist"); } - return Endpoint::Configure(conf, dnsConf); } - bool - TunEndpoint::HasLocalIP(const huint128_t& ip) const + if (auto* quic = GetQUICTunnel()) { - return m_IPToAddr.find(ip) != m_IPToAddr.end(); + quic->listen([this](std::string_view, uint16_t port) { + return llarp::SockAddr{net::TruncateV6(GetIfAddr()), huint16_t{port}}; + }); } + return Endpoint::Configure(conf, dnsConf); + } - void - TunEndpoint::Pump(llarp_time_t now) + bool + TunEndpoint::HasLocalIP(const huint128_t& ip) const + { + return m_IPToAddr.find(ip) != m_IPToAddr.end(); + } + + void + TunEndpoint::Pump(llarp_time_t now) + { + // flush network to user + while (not m_NetworkToUserPktQueue.empty()) { - // flush network to user - while (not m_NetworkToUserPktQueue.empty()) + m_NetIf->WritePacket(m_NetworkToUserPktQueue.top().pkt); + m_NetworkToUserPktQueue.pop(); + } + + service::Endpoint::Pump(now); + } + + static bool + is_random_snode(const dns::Message& msg) + { + return msg.questions[0].IsName("random.snode"); + } + + static bool + is_localhost_loki(const dns::Message& msg) + { + return msg.questions[0].IsLocalhost(); + } + + static dns::Message& + clear_dns_message(dns::Message& msg) + { + msg.authorities.resize(0); + msg.additional.resize(0); + msg.answers.resize(0); + msg.hdr_fields &= ~dns::flags_RCODENameError; + return msg; + } + + std::optional> + TunEndpoint::ObtainAddrForIP(huint128_t ip) const + { + auto itr = m_IPToAddr.find(ip); + if (itr == m_IPToAddr.end()) + return std::nullopt; + if (m_SNodes.at(itr->second)) + return RouterID{itr->second.as_array()}; + else + return service::Address{itr->second.as_array()}; + } + + bool + TunEndpoint::HandleHookedDNSMessage(dns::Message msg, std::function reply) + { + auto ReplyToSNodeDNSWhenReady = [this, reply](RouterID snode, auto msg, bool isV6) -> bool { + return EnsurePathToSNode( + snode, + [this, snode, msg, reply, isV6]( + const RouterID&, exit::BaseSession_ptr s, [[maybe_unused]] service::ConvoTag tag) { + SendDNSReply(snode, s, msg, reply, isV6); + }); + }; + auto ReplyToLokiDNSWhenReady = [this, reply, timeout = PathAlignmentTimeout()]( + service::Address addr, auto msg, bool isV6) -> bool { + using service::Address; + using service::OutboundContext; + if (HasInboundConvo(addr)) { - m_NetIf->WritePacket(m_NetworkToUserPktQueue.top().pkt); - m_NetworkToUserPktQueue.pop(); + // if we have an inbound convo to this address don't mark as outbound so we don't have a + // state race this codepath is hit when an application verifies that reverse and forward + // dns records match for an inbound session + SendDNSReply(addr, this, msg, reply, isV6); + return true; } + MarkAddressOutbound(addr); + return EnsurePathToService( + addr, + [this, addr, msg, reply, isV6](const Address&, OutboundContext* ctx) { + SendDNSReply(addr, ctx, msg, reply, isV6); + }, + timeout); + }; - service::Endpoint::Pump(now); - } + auto ReplyToDNSWhenReady = [ReplyToLokiDNSWhenReady, ReplyToSNodeDNSWhenReady]( + auto addr, auto msg, bool isV6) { + if (auto ptr = std::get_if(&addr)) + { + ReplyToSNodeDNSWhenReady(*ptr, msg, isV6); + return; + } + if (auto ptr = std::get_if(&addr)) + { + ReplyToLokiDNSWhenReady(*ptr, msg, isV6); + return; + } + }; - static bool - is_random_snode(const dns::Message& msg) - { - return msg.questions[0].IsName("random.snode"); - } + auto ReplyToLokiSRVWhenReady = [this, reply, timeout = PathAlignmentTimeout()]( + service::Address addr, auto msg) -> bool { + using service::Address; + using service::OutboundContext; + // TODO: how do we handle SRV record lookups for inbound sessions? + MarkAddressOutbound(addr); + return EnsurePathToService( + addr, + [msg, addr, reply](const Address&, OutboundContext* ctx) { + if (ctx == nullptr) + return; + + const auto& introset = ctx->GetCurrentIntroSet(); + msg->AddSRVReply(introset.GetMatchingSRVRecords(addr.subdomain)); + reply(*msg); + }, + timeout); + }; - static bool - is_localhost_loki(const dns::Message& msg) + if (msg.answers.size() > 0) { - return msg.questions[0].IsLocalhost(); - } + const auto& answer = msg.answers[0]; + if (answer.HasCNameForTLD(".snode")) + { + llarp_buffer_t buf(answer.rData); + auto qname = dns::DecodeName(&buf, true); + if (not qname) + return false; + RouterID addr; + if (not addr.FromString(*qname)) + return false; + auto replyMsg = std::make_shared(clear_dns_message(msg)); + return ReplyToSNodeDNSWhenReady(addr, std::move(replyMsg), false); + } + else if (answer.HasCNameForTLD(".loki")) + { + llarp_buffer_t buf(answer.rData); + auto qname = dns::DecodeName(&buf, true); + if (not qname) + return false; - static dns::Message& - clear_dns_message(dns::Message& msg) + service::Address addr; + if (not addr.FromString(*qname)) + return false; + + auto replyMsg = std::make_shared(clear_dns_message(msg)); + return ReplyToLokiDNSWhenReady(addr, replyMsg, false); + } + } + if (msg.questions.size() != 1) { - msg.authorities.resize(0); - msg.additional.resize(0); - msg.answers.resize(0); - msg.hdr_fields &= ~dns::flags_RCODENameError; - return msg; + llarp::LogWarn("bad number of dns questions: ", msg.questions.size()); + return false; } - - std::optional> - TunEndpoint::ObtainAddrForIP(huint128_t ip) const + std::string qname = msg.questions[0].Name(); + const auto nameparts = split(qname, "."); + std::string lnsName; + if (nameparts.size() >= 2 and ends_with(qname, ".loki")) { - auto itr = m_IPToAddr.find(ip); - if (itr == m_IPToAddr.end()) - return std::nullopt; - if (m_SNodes.at(itr->second)) - return RouterID{itr->second.as_array()}; - else - return service::Address{itr->second.as_array()}; + lnsName = nameparts[nameparts.size() - 2]; + lnsName += ".loki"sv; } - - bool - TunEndpoint::HandleHookedDNSMessage(dns::Message msg, std::function reply) + if (msg.questions[0].qtype == dns::qTypeTXT) { - auto ReplyToSNodeDNSWhenReady = [this, reply](RouterID snode, auto msg, bool isV6) -> bool { - return EnsurePathToSNode( - snode, - [this, snode, msg, reply, isV6]( - const RouterID&, exit::BaseSession_ptr s, [[maybe_unused]] service::ConvoTag tag) { - SendDNSReply(snode, s, msg, reply, isV6); - }); - }; - auto ReplyToLokiDNSWhenReady = [this, reply, timeout = PathAlignmentTimeout()]( - service::Address addr, auto msg, bool isV6) -> bool { - using service::Address; - using service::OutboundContext; - if (HasInboundConvo(addr)) - { - // if we have an inbound convo to this address don't mark as outbound so we don't have a - // state race this codepath is hit when an application verifies that reverse and forward - // dns records match for an inbound session - SendDNSReply(addr, this, msg, reply, isV6); - return true; - } - MarkAddressOutbound(addr); - return EnsurePathToService( - addr, - [this, addr, msg, reply, isV6](const Address&, OutboundContext* ctx) { - SendDNSReply(addr, ctx, msg, reply, isV6); - }, - timeout); - }; - - auto ReplyToDNSWhenReady = [ReplyToLokiDNSWhenReady, ReplyToSNodeDNSWhenReady]( - auto addr, auto msg, bool isV6) { - if (auto ptr = std::get_if(&addr)) - { - ReplyToSNodeDNSWhenReady(*ptr, msg, isV6); - return; - } - if (auto ptr = std::get_if(&addr)) + RouterID snode; + if (snode.FromString(qname)) + { + router->LookupRouter(snode, [reply, msg = std::move(msg)](const auto& found) mutable { + if (found.empty()) + { + msg.AddNXReply(); + } + else + { + std::string recs; + for (const auto& rc : found) + recs += rc.ToTXTRecord(); + msg.AddTXTReply(std::move(recs)); + } + reply(msg); + }); + return true; + } + else if (msg.questions[0].IsLocalhost() and msg.questions[0].HasSubdomains()) + { + const auto subdomain = msg.questions[0].Subdomains(); + if (subdomain == "exit") { - ReplyToLokiDNSWhenReady(*ptr, msg, isV6); - return; + if (HasExit()) + { + std::string s; + _exit_map.ForEachEntry([&s](const auto& range, const auto& exit) { + fmt::format_to(std::back_inserter(s), "{}={}; ", range, exit); + }); + msg.AddTXTReply(std::move(s)); + } + else + { + msg.AddNXReply(); + } } - }; - - auto ReplyToLokiSRVWhenReady = [this, reply, timeout = PathAlignmentTimeout()]( - service::Address addr, auto msg) -> bool { - using service::Address; - using service::OutboundContext; - // TODO: how do we handle SRV record lookups for inbound sessions? - MarkAddressOutbound(addr); - return EnsurePathToService( - addr, - [msg, addr, reply](const Address&, OutboundContext* ctx) { - if (ctx == nullptr) - return; - - const auto& introset = ctx->GetCurrentIntroSet(); - msg->AddSRVReply(introset.GetMatchingSRVRecords(addr.subdomain)); - reply(*msg); - }, - timeout); - }; - - if (msg.answers.size() > 0) - { - const auto& answer = msg.answers[0]; - if (answer.HasCNameForTLD(".snode")) + else if (subdomain == "netid") { - llarp_buffer_t buf(answer.rData); - auto qname = dns::DecodeName(&buf, true); - if (not qname) - return false; - RouterID addr; - if (not addr.FromString(*qname)) - return false; - auto replyMsg = std::make_shared(clear_dns_message(msg)); - return ReplyToSNodeDNSWhenReady(addr, std::move(replyMsg), false); + msg.AddTXTReply(fmt::format("netid={};", router->rc().netID)); } - else if (answer.HasCNameForTLD(".loki")) + else { - llarp_buffer_t buf(answer.rData); - auto qname = dns::DecodeName(&buf, true); - if (not qname) - return false; - - service::Address addr; - if (not addr.FromString(*qname)) - return false; - - auto replyMsg = std::make_shared(clear_dns_message(msg)); - return ReplyToLokiDNSWhenReady(addr, replyMsg, false); + msg.AddNXReply(); } } - if (msg.questions.size() != 1) + else { - llarp::LogWarn("bad number of dns questions: ", msg.questions.size()); - return false; + msg.AddNXReply(); } - std::string qname = msg.questions[0].Name(); - const auto nameparts = split(qname, "."); - std::string lnsName; - if (nameparts.size() >= 2 and ends_with(qname, ".loki")) + + reply(msg); + } + else if (msg.questions[0].qtype == dns::qTypeMX) + { + // mx record + service::Address addr; + if (addr.FromString(qname, ".loki") || addr.FromString(qname, ".snode") + || is_random_snode(msg) || is_localhost_loki(msg)) { - lnsName = nameparts[nameparts.size() - 2]; - lnsName += ".loki"sv; + msg.AddMXReply(qname, 1); } - if (msg.questions[0].qtype == dns::qTypeTXT) + else if (service::NameIsValid(lnsName)) { - RouterID snode; - if (snode.FromString(qname)) - { - m_router->LookupRouter(snode, [reply, msg = std::move(msg)](const auto& found) mutable { - if (found.empty()) - { - msg.AddNXReply(); - } - else - { - std::string recs; - for (const auto& rc : found) - recs += rc.ToTXTRecord(); - msg.AddTXTReply(std::move(recs)); - } - reply(msg); - }); - return true; - } - else if (msg.questions[0].IsLocalhost() and msg.questions[0].HasSubdomains()) - { - const auto subdomain = msg.questions[0].Subdomains(); - if (subdomain == "exit") - { - if (HasExit()) - { - std::string s; - _exit_map.ForEachEntry([&s](const auto& range, const auto& exit) { - fmt::format_to(std::back_inserter(s), "{}={}; ", range, exit); - }); - msg.AddTXTReply(std::move(s)); - } - else - { - msg.AddNXReply(); - } - } - else if (subdomain == "netid") + LookupNameAsync(lnsName, [msg, lnsName, reply](auto maybe) mutable { + if (maybe.has_value()) { - msg.AddTXTReply(fmt::format("netid={};", m_router->rc().netID)); + var::visit([&](auto&& value) { msg.AddMXReply(value.ToString(), 1); }, *maybe); } else { msg.AddNXReply(); } - } - else - { - msg.AddNXReply(); - } - - reply(msg); + reply(msg); + }); + return true; } - else if (msg.questions[0].qtype == dns::qTypeMX) + else + msg.AddNXReply(); + reply(msg); + } + else if (msg.questions[0].qtype == dns::qTypeCNAME) + { + if (is_random_snode(msg)) { - // mx record - service::Address addr; - if (addr.FromString(qname, ".loki") || addr.FromString(qname, ".snode") - || is_random_snode(msg) || is_localhost_loki(msg)) + RouterID random; + if (router()->GetRandomGoodRouter(random)) { - msg.AddMXReply(qname, 1); - } - else if (service::NameIsValid(lnsName)) - { - LookupNameAsync(lnsName, [msg, lnsName, reply](auto maybe) mutable { - if (maybe.has_value()) - { - var::visit([&](auto&& value) { msg.AddMXReply(value.ToString(), 1); }, *maybe); - } - else - { - msg.AddNXReply(); - } - reply(msg); - }); - return true; + msg.AddCNAMEReply(random.ToString(), 1); } else msg.AddNXReply(); - reply(msg); } - else if (msg.questions[0].qtype == dns::qTypeCNAME) + else if (msg.questions[0].IsLocalhost() and msg.questions[0].HasSubdomains()) { - if (is_random_snode(msg)) + const auto subdomain = msg.questions[0].Subdomains(); + if (subdomain == "exit" and HasExit()) { - RouterID random; - if (router()->GetRandomGoodRouter(random)) - { - msg.AddCNAMEReply(random.ToString(), 1); - } - else - msg.AddNXReply(); + _exit_map.ForEachEntry( + [&msg](const auto&, const auto& exit) { msg.AddCNAMEReply(exit.ToString(), 1); }); } - else if (msg.questions[0].IsLocalhost() and msg.questions[0].HasSubdomains()) + else { - const auto subdomain = msg.questions[0].Subdomains(); - if (subdomain == "exit" and HasExit()) - { - _exit_map.ForEachEntry( - [&msg](const auto&, const auto& exit) { msg.AddCNAMEReply(exit.ToString(), 1); }); - } - else - { - msg.AddNXReply(); - } + msg.AddNXReply(); } - else if (is_localhost_loki(msg)) + } + else if (is_localhost_loki(msg)) + { + size_t counter = 0; + context->ForEachService( + [&](const std::string&, const std::shared_ptr& service) -> bool { + const service::Address addr = service->GetIdentity().pub.Addr(); + msg.AddCNAMEReply(addr.ToString(), 1); + ++counter; + return true; + }); + if (counter == 0) + msg.AddNXReply(); + } + else + msg.AddNXReply(); + reply(msg); + } + else if (msg.questions[0].qtype == dns::qTypeA || msg.questions[0].qtype == dns::qTypeAAAA) + { + const bool isV6 = msg.questions[0].qtype == dns::qTypeAAAA; + const bool isV4 = msg.questions[0].qtype == dns::qTypeA; + llarp::service::Address addr; + if (isV6 && !SupportsV6()) + { // empty reply but not a NXDOMAIN so that client can retry IPv4 + msg.AddNSReply("localhost.loki."); + } + // on MacOS this is a typeA query + else if (is_random_snode(msg)) + { + RouterID random; + if (router()->GetRandomGoodRouter(random)) { - size_t counter = 0; - context->ForEachService( - [&](const std::string&, const std::shared_ptr& service) -> bool { - const service::Address addr = service->GetIdentity().pub.Addr(); - msg.AddCNAMEReply(addr.ToString(), 1); - ++counter; - return true; - }); - if (counter == 0) - msg.AddNXReply(); + msg.AddCNAMEReply(random.ToString(), 1); + return ReplyToSNodeDNSWhenReady(random, std::make_shared(msg), isV6); } else msg.AddNXReply(); - reply(msg); } - else if (msg.questions[0].qtype == dns::qTypeA || msg.questions[0].qtype == dns::qTypeAAAA) + else if (is_localhost_loki(msg)) { - const bool isV6 = msg.questions[0].qtype == dns::qTypeAAAA; - const bool isV4 = msg.questions[0].qtype == dns::qTypeA; - llarp::service::Address addr; - if (isV6 && !SupportsV6()) - { // empty reply but not a NXDOMAIN so that client can retry IPv4 - msg.AddNSReply("localhost.loki."); - } - // on MacOS this is a typeA query - else if (is_random_snode(msg)) + const bool lookingForExit = msg.questions[0].Subdomains() == "exit"; + huint128_t ip = GetIfAddr(); + if (ip.h) { - RouterID random; - if (router()->GetRandomGoodRouter(random)) + if (lookingForExit) { - msg.AddCNAMEReply(random.ToString(), 1); - return ReplyToSNodeDNSWhenReady(random, std::make_shared(msg), isV6); - } - else - msg.AddNXReply(); - } - else if (is_localhost_loki(msg)) - { - const bool lookingForExit = msg.questions[0].Subdomains() == "exit"; - huint128_t ip = GetIfAddr(); - if (ip.h) - { - if (lookingForExit) + if (HasExit()) { - if (HasExit()) - { - _exit_map.ForEachEntry( - [&msg](const auto&, const auto& exit) { msg.AddCNAMEReply(exit.ToString()); }); - msg.AddINReply(ip, isV6); - } - else - { - msg.AddNXReply(); - } + _exit_map.ForEachEntry( + [&msg](const auto&, const auto& exit) { msg.AddCNAMEReply(exit.ToString()); }); + msg.AddINReply(ip, isV6); } else { - msg.AddCNAMEReply(_identity.pub.Name(), 1); - msg.AddINReply(ip, isV6); + msg.AddNXReply(); } } else { - msg.AddNXReply(); + msg.AddCNAMEReply(_identity.pub.Name(), 1); + msg.AddINReply(ip, isV6); } } - else if (addr.FromString(qname, ".loki")) + else { - if (isV4 && SupportsV6()) - { - msg.hdr_fields |= dns::flags_QR | dns::flags_AA | dns::flags_RA; - } - else - { - return ReplyToLokiDNSWhenReady(addr, std::make_shared(msg), isV6); - } + msg.AddNXReply(); } - else if (addr.FromString(qname, ".snode")) + } + else if (addr.FromString(qname, ".loki")) + { + if (isV4 && SupportsV6()) { - if (isV4 && SupportsV6()) - { - msg.hdr_fields |= dns::flags_QR | dns::flags_AA | dns::flags_RA; - } - else - { - return ReplyToSNodeDNSWhenReady( - addr.as_array(), std::make_shared(msg), isV6); - } + msg.hdr_fields |= dns::flags_QR | dns::flags_AA | dns::flags_RA; } - else if (service::NameIsValid(lnsName)) + else { - LookupNameAsync( - lnsName, - [msg = std::make_shared(msg), - name = Name(), - lnsName, - isV6, - reply, - ReplyToDNSWhenReady](auto maybe) { - if (not maybe.has_value()) - { - LogWarn(name, " lns name ", lnsName, " not resolved"); - msg->AddNXReply(); - reply(*msg); - return; - } - ReplyToDNSWhenReady(*maybe, msg, isV6); - }); - return true; + return ReplyToLokiDNSWhenReady(addr, std::make_shared(msg), isV6); } - else - msg.AddNXReply(); - - reply(msg); } - else if (msg.questions[0].qtype == dns::qTypePTR) + else if (addr.FromString(qname, ".snode")) { - // reverse dns - if (auto ip = dns::DecodePTR(msg.questions[0].qname)) + if (isV4 && SupportsV6()) { - if (auto maybe = ObtainAddrForIP(*ip)) - { - var::visit([&msg](auto&& result) { msg.AddAReply(result.ToString()); }, *maybe); - reply(msg); - return true; - } + msg.hdr_fields |= dns::flags_QR | dns::flags_AA | dns::flags_RA; } - - msg.AddNXReply(); - reply(msg); - return true; - } - else if (msg.questions[0].qtype == dns::qTypeSRV) - { - auto srv_for = msg.questions[0].Subdomains(); - auto name = msg.questions[0].qname; - if (is_localhost_loki(msg)) + else { - msg.AddSRVReply(introSet().GetMatchingSRVRecords(srv_for)); - reply(msg); - return true; + return ReplyToSNodeDNSWhenReady( + addr.as_array(), std::make_shared(msg), isV6); } - LookupServiceAsync( - name, - srv_for, - [reply, msg = std::make_shared(std::move(msg))](auto records) { - if (records.empty()) + } + else if (service::NameIsValid(lnsName)) + { + LookupNameAsync( + lnsName, + [msg = std::make_shared(msg), + name = Name(), + lnsName, + isV6, + reply, + ReplyToDNSWhenReady](auto maybe) { + if (not maybe.has_value()) { + LogWarn(name, " lns name ", lnsName, " not resolved"); msg->AddNXReply(); + reply(*msg); + return; } - else - { - msg->AddSRVReply(records); - } - reply(*msg); + ReplyToDNSWhenReady(*maybe, msg, isV6); }); return true; } else - { msg.AddNXReply(); - reply(msg); - } - return true; - } - void - TunEndpoint::ResetInternalState() - { - service::Endpoint::ResetInternalState(); + reply(msg); } - - bool - TunEndpoint::SupportsV6() const + else if (msg.questions[0].qtype == dns::qTypePTR) { - return m_UseV6; - } - - // FIXME: pass in which question it should be addressing - bool - TunEndpoint::ShouldHookDNSMessage(const dns::Message& msg) const - { - llarp::service::Address addr; - if (msg.questions.size() == 1) + // reverse dns + if (auto ip = dns::DecodePTR(msg.questions[0].qname)) { - /// hook every .loki - if (msg.questions[0].HasTLD(".loki")) - return true; - /// hook every .snode - if (msg.questions[0].HasTLD(".snode")) - return true; - // hook any ranges we own - if (msg.questions[0].qtype == llarp::dns::qTypePTR) + if (auto maybe = ObtainAddrForIP(*ip)) { - if (auto ip = dns::DecodePTR(msg.questions[0].qname)) - return m_OurRange.Contains(*ip); - return false; + var::visit([&msg](auto&& result) { msg.AddAReply(result.ToString()); }, *maybe); + reply(msg); + return true; } } - for (const auto& answer : msg.answers) + + msg.AddNXReply(); + reply(msg); + return true; + } + else if (msg.questions[0].qtype == dns::qTypeSRV) + { + auto srv_for = msg.questions[0].Subdomains(); + auto name = msg.questions[0].qname; + if (is_localhost_loki(msg)) { - if (answer.HasCNameForTLD(".loki")) - return true; - if (answer.HasCNameForTLD(".snode")) - return true; + msg.AddSRVReply(intro_set().GetMatchingSRVRecords(srv_for)); + reply(msg); + return true; } - return false; + LookupServiceAsync( + name, + srv_for, + [reply, msg = std::make_shared(std::move(msg))](auto records) { + if (records.empty()) + { + msg->AddNXReply(); + } + else + { + msg->AddSRVReply(records); + } + reply(*msg); + }); + return true; + } + else + { + msg.AddNXReply(); + reply(msg); } + return true; + } - bool - TunEndpoint::MapAddress(const service::Address& addr, huint128_t ip, bool SNode) + void + TunEndpoint::ResetInternalState() + { + service::Endpoint::ResetInternalState(); + } + + bool + TunEndpoint::SupportsV6() const + { + return m_UseV6; + } + + // FIXME: pass in which question it should be addressing + bool + TunEndpoint::ShouldHookDNSMessage(const dns::Message& msg) const + { + llarp::service::Address addr; + if (msg.questions.size() == 1) { - auto itr = m_IPToAddr.find(ip); - if (itr != m_IPToAddr.end()) + /// hook every .loki + if (msg.questions[0].HasTLD(".loki")) + return true; + /// hook every .snode + if (msg.questions[0].HasTLD(".snode")) + return true; + // hook any ranges we own + if (msg.questions[0].qtype == llarp::dns::qTypePTR) { - llarp::LogWarn( - ip, " already mapped to ", service::Address(itr->second.as_array()).ToString()); + if (auto ip = dns::DecodePTR(msg.questions[0].qname)) + return m_OurRange.Contains(*ip); return false; } - llarp::LogInfo(Name() + " map ", addr.ToString(), " to ", ip); + } + for (const auto& answer : msg.answers) + { + if (answer.HasCNameForTLD(".loki")) + return true; + if (answer.HasCNameForTLD(".snode")) + return true; + } + return false; + } + + bool + TunEndpoint::MapAddress(const service::Address& addr, huint128_t ip, bool SNode) + { + auto itr = m_IPToAddr.find(ip); + if (itr != m_IPToAddr.end()) + { + llarp::LogWarn( + ip, " already mapped to ", service::Address(itr->second.as_array()).ToString()); + return false; + } + llarp::LogInfo(Name() + " map ", addr.ToString(), " to ", ip); + + m_IPToAddr[ip] = addr; + m_AddrToIP[addr] = ip; + m_SNodes[addr] = SNode; + MarkIPActiveForever(ip); + MarkAddressOutbound(addr); + return true; + } + + std::string + TunEndpoint::GetIfName() const + { +#ifdef _WIN32 + return net::TruncateV6(GetIfAddr()).ToString(); +#else + return m_IfName; +#endif + } + + bool + TunEndpoint::Start() + { + if (not Endpoint::Start()) + return false; + return SetupNetworking(); + } + + bool + TunEndpoint::IsSNode() const + { + // TODO : implement me + return false; + } + + bool + TunEndpoint::SetupTun() + { + m_NextIP = m_OurIP; + m_MaxIP = m_OurRange.HighestAddr(); + llarp::LogInfo(Name(), " set ", m_IfName, " to have address ", m_OurIP); + llarp::LogInfo(Name(), " allocated up to ", m_MaxIP, " on range ", m_OurRange); - m_IPToAddr[ip] = addr; - m_AddrToIP[addr] = ip; - m_SNodes[addr] = SNode; - MarkIPActiveForever(ip); - MarkAddressOutbound(addr); - return true; - } + const service::Address ourAddr = _identity.pub.Addr(); - std::string - TunEndpoint::GetIfName() const + if (not MapAddress(ourAddr, GetIfAddr(), false)) { -#ifdef _WIN32 - return net::TruncateV6(GetIfAddr()).ToString(); -#else - return m_IfName; -#endif + return false; } - bool - TunEndpoint::Start() - { - if (not Endpoint::Start()) - return false; - return SetupNetworking(); - } + vpn::InterfaceInfo info; + info.addrs.emplace_back(m_OurRange); - bool - TunEndpoint::IsSNode() const + if (m_BaseV6Address) { - // TODO : implement me - return false; + IPRange v6range = m_OurRange; + v6range.addr = (*m_BaseV6Address) | m_OurRange.addr; + LogInfo(Name(), " using v6 range: ", v6range); + info.addrs.emplace_back(v6range, AF_INET6); } - bool - TunEndpoint::SetupTun() - { - m_NextIP = m_OurIP; - m_MaxIP = m_OurRange.HighestAddr(); - llarp::LogInfo(Name(), " set ", m_IfName, " to have address ", m_OurIP); - llarp::LogInfo(Name(), " allocated up to ", m_MaxIP, " on range ", m_OurRange); + info.ifname = m_IfName; - const service::Address ourAddr = _identity.pub.Addr(); + LogInfo(Name(), " setting up network..."); - if (not MapAddress(ourAddr, GetIfAddr(), false)) - { - return false; - } + try + { + m_NetIf = router()->vpn_platform()->CreateInterface(std::move(info), router()); + } + catch (std::exception& ex) + { + LogError(Name(), " failed to set up network interface: ", ex.what()); + return false; + } - vpn::InterfaceInfo info; - info.addrs.emplace_back(m_OurRange); + m_IfName = m_NetIf->Info().ifname; + LogInfo(Name(), " got network interface ", m_IfName); - if (m_BaseV6Address) - { - IPRange v6range = m_OurRange; - v6range.addr = (*m_BaseV6Address) | m_OurRange.addr; - LogInfo(Name(), " using v6 range: ", v6range); - info.addrs.emplace_back(v6range, AF_INET6); - } + auto handle_packet = [netif = m_NetIf, pkt_router = m_PacketRouter](auto pkt) { + pkt.reply = [netif](auto pkt) { netif->WritePacket(std::move(pkt)); }; + pkt_router->HandleIPPacket(std::move(pkt)); + }; - info.ifname = m_IfName; + if (not router()->loop()->add_network_interface(m_NetIf, std::move(handle_packet))) + { + LogError(Name(), " failed to add network interface"); + return false; + } - LogInfo(Name(), " setting up network..."); + m_OurIPv6 = llarp::huint128_t{ + llarp::uint128_t{0xfd2e'6c6f'6b69'0000, llarp::net::TruncateV6(m_OurRange.addr).h}}; - try - { - m_NetIf = router()->vpn_platform()->CreateInterface(std::move(info), router()); - } - catch (std::exception& ex) + if constexpr (not llarp::platform::is_apple) + { + if (auto maybe = router->net().GetInterfaceIPv6Address(m_IfName)) { - LogError(Name(), " failed to set up network interface: ", ex.what()); - return false; + m_OurIPv6 = *maybe; + LogInfo(Name(), " has ipv6 address ", m_OurIPv6); } + } - m_IfName = m_NetIf->Info().ifname; - LogInfo(Name(), " got network interface ", m_IfName); - - auto handle_packet = [netif = m_NetIf, pkt_router = m_PacketRouter](auto pkt) { - pkt.reply = [netif](auto pkt) { netif->WritePacket(std::move(pkt)); }; - pkt_router->HandleIPPacket(std::move(pkt)); - }; + LogInfo(Name(), " setting up dns..."); + SetupDNS(); + Loop()->call_soon([this]() { router->route_poker()->set_dns_mode(false); }); + return HasAddress(ourAddr); + } - if (not router()->loop()->add_network_interface(m_NetIf, std::move(handle_packet))) - { - LogError(Name(), " failed to add network interface"); - return false; - } + std::unordered_map + TunEndpoint::NotifyParams() const + { + auto env = Endpoint::NotifyParams(); + env.emplace("IP_ADDR", m_OurIP.ToString()); + env.emplace("IF_ADDR", m_OurRange.ToString()); + env.emplace("IF_NAME", m_IfName); + std::string strictConnect; + for (const auto& addr : m_StrictConnectAddrs) + strictConnect += addr.ToString() + " "; + env.emplace("STRICT_CONNECT_ADDRS", strictConnect); + return env; + } + + bool + TunEndpoint::SetupNetworking() + { + llarp::LogInfo("Set Up networking for ", Name()); + return SetupTun(); + } - m_OurIPv6 = llarp::huint128_t{ - llarp::uint128_t{0xfd2e'6c6f'6b69'0000, llarp::net::TruncateV6(m_OurRange.addr).h}}; + void + TunEndpoint::Tick(llarp_time_t now) + { + Endpoint::Tick(now); + } - if constexpr (not llarp::platform::is_apple) + bool + TunEndpoint::Stop() + { + // stop vpn tunnel + if (m_NetIf) + m_NetIf->Stop(); + if (m_RawDNS) + m_RawDNS->Stop(); + // save address map if applicable + if (m_PersistAddrMapFile and not platform::is_android) + { + const auto& file = *m_PersistAddrMapFile; + LogInfo(Name(), " saving address map to ", file); + if (auto maybe = util::OpenFileStream(file, std::ios_base::binary)) { - if (auto maybe = m_router->net().GetInterfaceIPv6Address(m_IfName)) + std::map addrmap; + for (const auto& [ip, addr] : m_IPToAddr) { - m_OurIPv6 = *maybe; - LogInfo(Name(), " has ipv6 address ", m_OurIPv6); + if (not m_SNodes.at(addr)) + { + const service::Address a{addr.as_array()}; + if (HasInboundConvo(a)) + addrmap[ip.ToString()] = a.ToString(); + } } + const auto data = oxenc::bt_serialize(addrmap); + maybe->write(data.data(), data.size()); } - - LogInfo(Name(), " setting up dns..."); - SetupDNS(); - Loop()->call_soon([this]() { m_router->routePoker()->SetDNSMode(false); }); - return HasAddress(ourAddr); } + if (m_DNS) + m_DNS->Stop(); + return llarp::service::Endpoint::Stop(); + } + + std::optional + TunEndpoint::ObtainExitAddressFor( + huint128_t ip, + std::function)> exitSelectionStrat) + { + // is it already mapped? return the mapping + if (auto itr = m_ExitIPToExitAddress.find(ip); itr != m_ExitIPToExitAddress.end()) + return itr->second; - std::unordered_map - TunEndpoint::NotifyParams() const + const auto& net = router->net(); + const bool is_bogon = net.IsBogonIP(ip); + // build up our candidates to choose + + std::unordered_set candidates; + for (const auto& entry : _exit_map.FindAllEntries(ip)) { - auto env = Endpoint::NotifyParams(); - env.emplace("IP_ADDR", m_OurIP.ToString()); - env.emplace("IF_ADDR", m_OurRange.ToString()); - env.emplace("IF_NAME", m_IfName); - std::string strictConnect; - for (const auto& addr : m_StrictConnectAddrs) - strictConnect += addr.ToString() + " "; - env.emplace("STRICT_CONNECT_ADDRS", strictConnect); - return env; + // in the event the exit's range is a bogon range, make sure the ip is located in that range + // to allow it + if ((is_bogon and net.IsBogonRange(entry.first) and entry.first.Contains(ip)) + or entry.first.Contains(ip)) + candidates.emplace(entry.second); } - - bool - TunEndpoint::SetupNetworking() + // no candidates? bail. + if (candidates.empty()) + return std::nullopt; + if (not exitSelectionStrat) { - llarp::LogInfo("Set Up networking for ", Name()); - return SetupTun(); + // default strat to random choice + exitSelectionStrat = [](auto candidates) { + auto itr = candidates.begin(); + std::advance(itr, llarp::randint() % candidates.size()); + return *itr; + }; } + // map the exit and return the endpoint we mapped it to + return m_ExitIPToExitAddress.emplace(ip, exitSelectionStrat(candidates)).first->second; + } - void - TunEndpoint::Tick(llarp_time_t now) + void + TunEndpoint::HandleGotUserPacket(net::IPPacket pkt) + { + huint128_t dst, src; + if (pkt.IsV4()) { - Endpoint::Tick(now); + dst = pkt.dst4to6(); + src = pkt.src4to6(); } - - bool - TunEndpoint::Stop() + else { - // stop vpn tunnel - if (m_NetIf) - m_NetIf->Stop(); - if (m_RawDNS) - m_RawDNS->Stop(); - // save address map if applicable - if (m_PersistAddrMapFile and not platform::is_android) - { - const auto& file = *m_PersistAddrMapFile; - LogInfo(Name(), " saving address map to ", file); - if (auto maybe = util::OpenFileStream(file, std::ios_base::binary)) - { - std::map addrmap; - for (const auto& [ip, addr] : m_IPToAddr) - { - if (not m_SNodes.at(addr)) - { - const service::Address a{addr.as_array()}; - if (HasInboundConvo(a)) - addrmap[ip.ToString()] = a.ToString(); - } - } - const auto data = oxenc::bt_serialize(addrmap); - maybe->write(data.data(), data.size()); - } - } - if (m_DNS) - m_DNS->Stop(); - return llarp::service::Endpoint::Stop(); + dst = pkt.dstv6(); + src = pkt.srcv6(); } - std::optional - TunEndpoint::ObtainExitAddressFor( - huint128_t ip, - std::function)> exitSelectionStrat) + if constexpr (llarp::platform::is_apple) { - // is it already mapped? return the mapping - if (auto itr = m_ExitIPToExitAddress.find(ip); itr != m_ExitIPToExitAddress.end()) - return itr->second; - - const auto& net = m_router->net(); - const bool is_bogon = net.IsBogonIP(ip); - // build up our candidates to choose - - std::unordered_set candidates; - for (const auto& entry : _exit_map.FindAllEntries(ip)) + if (dst == m_OurIP) { - // in the event the exit's range is a bogon range, make sure the ip is located in that range - // to allow it - if ((is_bogon and net.IsBogonRange(entry.first) and entry.first.Contains(ip)) - or entry.first.Contains(ip)) - candidates.emplace(entry.second); - } - // no candidates? bail. - if (candidates.empty()) - return std::nullopt; - if (not exitSelectionStrat) - { - // default strat to random choice - exitSelectionStrat = [](auto candidates) { - auto itr = candidates.begin(); - std::advance(itr, llarp::randint() % candidates.size()); - return *itr; - }; + HandleWriteIPPacket(pkt.ConstBuffer(), src, dst, 0); + return; } - // map the exit and return the endpoint we mapped it to - return m_ExitIPToExitAddress.emplace(ip, exitSelectionStrat(candidates)).first->second; } - void - TunEndpoint::HandleGotUserPacket(net::IPPacket pkt) + if (_state->is_exit_enabled) { - huint128_t dst, src; - if (pkt.IsV4()) - { - dst = pkt.dst4to6(); - src = pkt.src4to6(); - } - else - { - dst = pkt.dstv6(); - src = pkt.srcv6(); - } - - if constexpr (llarp::platform::is_apple) - { - if (dst == m_OurIP) - { - HandleWriteIPPacket(pkt.ConstBuffer(), src, dst, 0); - return; - } - } - - if (_state->m_ExitEnabled) - { - dst = net::ExpandV4(net::TruncateV6(dst)); - } - auto itr = m_IPToAddr.find(dst); - if (itr == m_IPToAddr.end()) - { - service::Address addr{}; - - if (auto maybe = ObtainExitAddressFor(dst)) - addr = *maybe; - else - { - // send icmp unreachable as we dont have any exits for this ip - if (const auto icmp = pkt.MakeICMPUnreachable()) - HandleWriteIPPacket(icmp->ConstBuffer(), dst, src, 0); + dst = net::ExpandV4(net::TruncateV6(dst)); + } + auto itr = m_IPToAddr.find(dst); + if (itr == m_IPToAddr.end()) + { + service::Address addr{}; - return; - } - std::function extra_cb; - if (not HasFlowToService(addr)) - { - extra_cb = [poker = router()->routePoker()]() { poker->Up(); }; - } - pkt.ZeroSourceAddress(); - MarkAddressOutbound(addr); - EnsurePathToService( - addr, - [pkt, extra_cb, this](service::Address addr, service::OutboundContext* ctx) { - if (ctx) - { - if (extra_cb) - extra_cb(); - ctx->SendPacketToRemote(pkt.ConstBuffer(), service::ProtocolType::Exit); - router()->TriggerPump(); - return; - } - LogWarn("cannot ensure path to exit ", addr, " so we drop some packets"); - }, - PathAlignmentTimeout()); - return; - } - std::variant to; - service::ProtocolType type; - if (m_SNodes.at(itr->second)) - { - to = RouterID{itr->second.as_array()}; - type = service::ProtocolType::TrafficV4; - } + if (auto maybe = ObtainExitAddressFor(dst)) + addr = *maybe; else { - to = service::Address{itr->second.as_array()}; - type = _state->m_ExitEnabled and src != m_OurIP ? service::ProtocolType::Exit - : pkt.ServiceProtocol(); - } + // send icmp unreachable as we dont have any exits for this ip + if (const auto icmp = pkt.MakeICMPUnreachable()) + HandleWriteIPPacket(icmp->ConstBuffer(), dst, src, 0); - // prepare packet for insertion into network - // this includes clearing IP addresses, recalculating checksums, etc - // this does not happen for exits because the point is they don't rewrite addresses - if (type != service::ProtocolType::Exit) - { - if (pkt.IsV4()) - pkt.UpdateIPv4Address({0}, {0}); - else - pkt.UpdateIPv6Address({0}, {0}); + return; } - // try sending it on an existing convotag - // this succeds for inbound convos, probably. - if (auto maybe = GetBestConvoTagFor(to)) + std::function extra_cb; + if (not HasFlowToService(addr)) { - if (SendToOrQueue(*maybe, pkt.ConstBuffer(), type)) - { - MarkIPActive(dst); - router()->TriggerPump(); - return; - } + extra_cb = [poker = router()->route_poker()]() { poker->put_up(); }; } - // try establishing a path to this guy - // will fail if it's an inbound convo - EnsurePathTo( - to, - [pkt, type, dst, to, this](auto maybe) { - if (not maybe) - { - var::visit( - [this](auto&& addr) { - LogWarn(Name(), " failed to ensure path to ", addr, " no convo tag found"); - }, - to); - } - if (SendToOrQueue(*maybe, pkt.ConstBuffer(), type)) + pkt.ZeroSourceAddress(); + MarkAddressOutbound(addr); + EnsurePathToService( + addr, + [pkt, extra_cb, this](service::Address addr, service::OutboundContext* ctx) { + if (ctx) { - MarkIPActive(dst); + if (extra_cb) + extra_cb(); + ctx->SendPacketToRemote(pkt.ConstBuffer(), service::ProtocolType::Exit); router()->TriggerPump(); + return; } - else - { - var::visit( - [this](auto&& addr) { - LogWarn(Name(), " failed to send to ", addr, ", SendToOrQueue failed"); - }, - to); - } + LogWarn("cannot ensure path to exit ", addr, " so we drop some packets"); }, PathAlignmentTimeout()); + return; + } + std::variant to; + service::ProtocolType type; + if (m_SNodes.at(itr->second)) + { + to = RouterID{itr->second.as_array()}; + type = service::ProtocolType::TrafficV4; + } + else + { + to = service::Address{itr->second.as_array()}; + type = _state->is_exit_enabled and src != m_OurIP ? service::ProtocolType::Exit + : pkt.ServiceProtocol(); } - bool - TunEndpoint::ShouldAllowTraffic(const net::IPPacket& pkt) const + // prepare packet for insertion into network + // this includes clearing IP addresses, recalculating checksums, etc + // this does not happen for exits because the point is they don't rewrite addresses + if (type != service::ProtocolType::Exit) { - if (const auto exitPolicy = GetExitPolicy()) + if (pkt.IsV4()) + pkt.UpdateIPv4Address({0}, {0}); + else + pkt.UpdateIPv6Address({0}, {0}); + } + // try sending it on an existing convotag + // this succeds for inbound convos, probably. + if (auto maybe = GetBestConvoTagFor(to)) + { + if (SendToOrQueue(*maybe, pkt.ConstBuffer(), type)) { - if (not exitPolicy->AllowsTraffic(pkt)) - return false; + MarkIPActive(dst); + router()->TriggerPump(); + return; } + } + // try establishing a path to this guy + // will fail if it's an inbound convo + EnsurePathTo( + to, + [pkt, type, dst, to, this](auto maybe) { + if (not maybe) + { + var::visit( + [this](auto&& addr) { + LogWarn(Name(), " failed to ensure path to ", addr, " no convo tag found"); + }, + to); + } + if (SendToOrQueue(*maybe, pkt.ConstBuffer(), type)) + { + MarkIPActive(dst); + router()->TriggerPump(); + } + else + { + var::visit( + [this](auto&& addr) { + LogWarn(Name(), " failed to send to ", addr, ", SendToOrQueue failed"); + }, + to); + } + }, + PathAlignmentTimeout()); + } - return true; + bool + TunEndpoint::ShouldAllowTraffic(const net::IPPacket& pkt) const + { + if (const auto exitPolicy = GetExitPolicy()) + { + if (not exitPolicy->AllowsTraffic(pkt)) + return false; } - bool - TunEndpoint::HandleInboundPacket( - const service::ConvoTag tag, - const llarp_buffer_t& buf, - service::ProtocolType t, - uint64_t seqno) + return true; + } + + bool + TunEndpoint::HandleInboundPacket( + const service::ConvoTag tag, + const llarp_buffer_t& buf, + service::ProtocolType t, + uint64_t seqno) + { + LogTrace("Inbound ", t, " packet (", buf.sz, "B) on convo ", tag); + if (t == service::ProtocolType::QUIC) { - LogTrace("Inbound ", t, " packet (", buf.sz, "B) on convo ", tag); - if (t == service::ProtocolType::QUIC) + auto* quic = GetQUICTunnel(); + if (!quic) { - auto* quic = GetQUICTunnel(); - if (!quic) - { - LogWarn("incoming quic packet but this endpoint is not quic capable; dropping"); - return false; - } - if (buf.sz < 4) - { - LogWarn("invalid incoming quic packet, dropping"); - return false; - } - LogInfo("tag active T=", tag); - quic->receive_packet(tag, buf); - return true; - } - - if (t != service::ProtocolType::TrafficV4 && t != service::ProtocolType::TrafficV6 - && t != service::ProtocolType::Exit) + LogWarn("incoming quic packet but this endpoint is not quic capable; dropping"); return false; - std::variant addr; - if (auto maybe = GetEndpointWithConvoTag(tag)) - { - addr = *maybe; } - else + if (buf.sz < 4) + { + LogWarn("invalid incoming quic packet, dropping"); return false; - huint128_t src, dst; + } + LogInfo("tag active T=", tag); + quic->receive_packet(tag, buf); + return true; + } - net::IPPacket pkt; - if (not pkt.Load(buf)) - return false; + if (t != service::ProtocolType::TrafficV4 && t != service::ProtocolType::TrafficV6 + && t != service::ProtocolType::Exit) + return false; + std::variant addr; + if (auto maybe = GetEndpointWithConvoTag(tag)) + { + addr = *maybe; + } + else + return false; + huint128_t src, dst; - if (_state->m_ExitEnabled) - { - // exit side from exit + net::IPPacket pkt; + if (not pkt.Load(buf)) + return false; - // check packet against exit policy and if as needed - if (not ShouldAllowTraffic(pkt)) - return false; + if (_state->is_exit_enabled) + { + // exit side from exit - src = ObtainIPForAddr(addr); - if (t == service::ProtocolType::Exit) - { - if (pkt.IsV4()) - dst = pkt.dst4to6(); - else if (pkt.IsV6()) - { - dst = pkt.dstv6(); - src = net::ExpandV4Lan(net::TruncateV6(src)); - } - } - else - { - // non exit traffic on exit - dst = m_OurIP; - } - } - else if (t == service::ProtocolType::Exit) + // check packet against exit policy and if as needed + if (not ShouldAllowTraffic(pkt)) + return false; + + src = ObtainIPForAddr(addr); + if (t == service::ProtocolType::Exit) { - // client side exit traffic from exit if (pkt.IsV4()) - { - dst = m_OurIP; - src = pkt.src4to6(); - } + dst = pkt.dst4to6(); else if (pkt.IsV6()) { - dst = m_OurIPv6; - src = pkt.srcv6(); - } - // find what exit we think this should be for - service::Address fromAddr{}; - if (const auto* ptr = std::get_if(&addr)) - { - fromAddr = *ptr; - } - else // don't allow snode - return false; - // make sure the mapping matches - if (auto itr = m_ExitIPToExitAddress.find(src); itr != m_ExitIPToExitAddress.end()) - { - if (itr->second != fromAddr) - return false; + dst = pkt.dstv6(); + src = net::ExpandV4Lan(net::TruncateV6(src)); } - else - return false; } else { - // snapp traffic - src = ObtainIPForAddr(addr); + // non exit traffic on exit dst = m_OurIP; } - HandleWriteIPPacket(buf, src, dst, seqno); - return true; } - - bool - TunEndpoint::HandleWriteIPPacket( - const llarp_buffer_t& b, huint128_t src, huint128_t dst, uint64_t seqno) + else if (t == service::ProtocolType::Exit) { - ManagedBuffer buf(b); - WritePacket write; - write.seqno = seqno; - auto& pkt = write.pkt; - // load - if (!pkt.Load(buf)) - { - return false; - } + // client side exit traffic from exit if (pkt.IsV4()) { - pkt.UpdateIPv4Address(xhtonl(net::TruncateV6(src)), xhtonl(net::TruncateV6(dst))); + dst = m_OurIP; + src = pkt.src4to6(); } else if (pkt.IsV6()) { - pkt.UpdateIPv6Address(src, dst); + dst = m_OurIPv6; + src = pkt.srcv6(); } - m_NetworkToUserPktQueue.push(std::move(write)); - // wake up so we ensure that all packets are written to user - router()->TriggerPump(); - return true; + // find what exit we think this should be for + service::Address fromAddr{}; + if (const auto* ptr = std::get_if(&addr)) + { + fromAddr = *ptr; + } + else // don't allow snode + return false; + // make sure the mapping matches + if (auto itr = m_ExitIPToExitAddress.find(src); itr != m_ExitIPToExitAddress.end()) + { + if (itr->second != fromAddr) + return false; + } + else + return false; } - - huint128_t - TunEndpoint::GetIfAddr() const + else { - return m_OurIP; + // snapp traffic + src = ObtainIPForAddr(addr); + dst = m_OurIP; } + HandleWriteIPPacket(buf, src, dst, seqno); + return true; + } - huint128_t - TunEndpoint::ObtainIPForAddr(std::variant addr) + bool + TunEndpoint::HandleWriteIPPacket( + const llarp_buffer_t& b, huint128_t src, huint128_t dst, uint64_t seqno) + { + ManagedBuffer buf(b); + WritePacket write; + write.seqno = seqno; + auto& pkt = write.pkt; + // load + if (!pkt.Load(buf)) + { + return false; + } + if (pkt.IsV4()) + { + pkt.UpdateIPv4Address(xhtonl(net::TruncateV6(src)), xhtonl(net::TruncateV6(dst))); + } + else if (pkt.IsV6()) { - llarp_time_t now = Now(); - huint128_t nextIP = {0}; - AlignedBuffer<32> ident{}; - bool snode = false; + pkt.UpdateIPv6Address(src, dst); + } + m_NetworkToUserPktQueue.push(std::move(write)); + // wake up so we ensure that all packets are written to user + router()->TriggerPump(); + return true; + } + + huint128_t + TunEndpoint::GetIfAddr() const + { + return m_OurIP; + } - var::visit([&ident](auto&& val) { ident = val.data(); }, addr); + huint128_t + TunEndpoint::ObtainIPForAddr(std::variant addr) + { + llarp_time_t now = Now(); + huint128_t nextIP = {0}; + AlignedBuffer<32> ident{}; + bool snode = false; - if (std::get_if(&addr)) - { - snode = true; - } + var::visit([&ident](auto&& val) { ident = val.data(); }, addr); + + if (std::get_if(&addr)) + { + snode = true; + } + { + // previously allocated address + auto itr = m_AddrToIP.find(ident); + if (itr != m_AddrToIP.end()) { - // previously allocated address - auto itr = m_AddrToIP.find(ident); - if (itr != m_AddrToIP.end()) - { - // mark ip active - MarkIPActive(itr->second); - return itr->second; - } + // mark ip active + MarkIPActive(itr->second); + return itr->second; } - // allocate new address - if (m_NextIP < m_MaxIP) + } + // allocate new address + if (m_NextIP < m_MaxIP) + { + do { - do - { - nextIP = ++m_NextIP; - } while (m_IPToAddr.find(nextIP) != m_IPToAddr.end() && m_NextIP < m_MaxIP); - if (nextIP < m_MaxIP) - { - m_AddrToIP[ident] = nextIP; - m_IPToAddr[nextIP] = ident; - m_SNodes[ident] = snode; - var::visit( - [&](auto&& remote) { llarp::LogInfo(Name(), " mapped ", remote, " to ", nextIP); }, - addr); - MarkIPActive(nextIP); - return nextIP; - } + nextIP = ++m_NextIP; + } while (m_IPToAddr.find(nextIP) != m_IPToAddr.end() && m_NextIP < m_MaxIP); + if (nextIP < m_MaxIP) + { + m_AddrToIP[ident] = nextIP; + m_IPToAddr[nextIP] = ident; + m_SNodes[ident] = snode; + var::visit( + [&](auto&& remote) { llarp::LogInfo(Name(), " mapped ", remote, " to ", nextIP); }, + addr); + MarkIPActive(nextIP); + return nextIP; } + } - // we are full - // expire least active ip - // TODO: prevent DoS - std::pair oldest = {huint128_t{0}, 0s}; + // we are full + // expire least active ip + // TODO: prevent DoS + std::pair oldest = {huint128_t{0}, 0s}; - // find oldest entry - auto itr = m_IPActivity.begin(); - while (itr != m_IPActivity.end()) + // find oldest entry + auto itr = m_IPActivity.begin(); + while (itr != m_IPActivity.end()) + { + if (itr->second <= now) { - if (itr->second <= now) + if ((now - itr->second) > oldest.second) { - if ((now - itr->second) > oldest.second) - { - oldest.first = itr->first; - oldest.second = itr->second; - } + oldest.first = itr->first; + oldest.second = itr->second; } - ++itr; } - // remap address - m_IPToAddr[oldest.first] = ident; - m_AddrToIP[ident] = oldest.first; - m_SNodes[ident] = snode; - nextIP = oldest.first; + ++itr; + } + // remap address + m_IPToAddr[oldest.first] = ident; + m_AddrToIP[ident] = oldest.first; + m_SNodes[ident] = snode; + nextIP = oldest.first; - // mark ip active - m_IPActivity[nextIP] = std::max(m_IPActivity[nextIP], now); + // mark ip active + m_IPActivity[nextIP] = std::max(m_IPActivity[nextIP], now); - return nextIP; - } + return nextIP; + } - bool - TunEndpoint::HasRemoteForIP(huint128_t ip) const - { - return m_IPToAddr.find(ip) != m_IPToAddr.end(); - } + bool + TunEndpoint::HasRemoteForIP(huint128_t ip) const + { + return m_IPToAddr.find(ip) != m_IPToAddr.end(); + } - void - TunEndpoint::MarkIPActive(huint128_t ip) - { - llarp::LogDebug(Name(), " address ", ip, " is active"); - m_IPActivity[ip] = std::max(Now(), m_IPActivity[ip]); - } + void + TunEndpoint::MarkIPActive(huint128_t ip) + { + llarp::LogDebug(Name(), " address ", ip, " is active"); + m_IPActivity[ip] = std::max(Now(), m_IPActivity[ip]); + } - void - TunEndpoint::MarkIPActiveForever(huint128_t ip) - { - m_IPActivity[ip] = std::numeric_limits::max(); - } + void + TunEndpoint::MarkIPActiveForever(huint128_t ip) + { + m_IPActivity[ip] = std::numeric_limits::max(); + } - TunEndpoint::~TunEndpoint() = default; + TunEndpoint::~TunEndpoint() = default; - } // namespace handlers -} // namespace llarp +} // namespace llarp::handlers diff --git a/llarp/handlers/tun.hpp b/llarp/handlers/tun.hpp index f9b41b74c1..694b3d36d1 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -16,313 +16,309 @@ #include #include -namespace llarp +namespace llarp::handlers { - namespace handlers + struct TunEndpoint : public service::Endpoint, + public dns::Resolver_Base, + public std::enable_shared_from_this { - struct TunEndpoint : public service::Endpoint, - public dns::Resolver_Base, - public std::enable_shared_from_this + TunEndpoint(Router* r, llarp::service::Context* parent); + ~TunEndpoint() override; + + vpn::NetworkInterface* + GetVPNInterface() override { - TunEndpoint(Router* r, llarp::service::Context* parent); - ~TunEndpoint() override; + return m_NetIf.get(); + } - vpn::NetworkInterface* - GetVPNInterface() override - { - return m_NetIf.get(); - } + int + Rank() const override + { + return 0; + } - int - Rank() const override - { - return 0; - } + std::string_view + ResolverName() const override + { + return "lokinet"; + } + + bool + MaybeHookDNS( + std::shared_ptr source, + const dns::Message& query, + const SockAddr& to, + const SockAddr& from) override; + + path::PathSet_ptr + GetSelf() override + { + return shared_from_this(); + } - std::string_view - ResolverName() const override - { - return "lokinet"; - } + std::weak_ptr + GetWeak() override + { + return weak_from_this(); + } - bool - MaybeHookDNS( - std::shared_ptr source, - const dns::Message& query, - const SockAddr& to, - const SockAddr& from) override; - - path::PathSet_ptr - GetSelf() override - { - return shared_from_this(); - } + void + Thaw() override; - std::weak_ptr - GetWeak() override - { - return weak_from_this(); - } + // Reconfigures DNS servers and restarts libunbound with the new servers. + void + ReconfigureDNS(std::vector servers); - void - Thaw() override; + bool + Configure(const NetworkConfig& conf, const DnsConfig& dnsConf) override; - // Reconfigures DNS servers and restarts libunbound with the new servers. - void - ReconfigureDNS(std::vector servers); + void + SendPacketToRemote(const llarp_buffer_t&, service::ProtocolType) override{}; - bool - Configure(const NetworkConfig& conf, const DnsConfig& dnsConf) override; + std::string + GetIfName() const override; - void - SendPacketToRemote(const llarp_buffer_t&, service::ProtocolType) override{}; + void + Tick(llarp_time_t now) override; - std::string - GetIfName() const override; + util::StatusObject + ExtractStatus() const override; - void - Tick(llarp_time_t now) override; + std::unordered_map + NotifyParams() const override; - util::StatusObject - ExtractStatus() const override; + bool + SupportsV6() const override; - std::unordered_map - NotifyParams() const override; + bool + ShouldHookDNSMessage(const dns::Message& msg) const; - bool - SupportsV6() const override; + bool + HandleHookedDNSMessage(dns::Message query, std::function sendreply); - bool - ShouldHookDNSMessage(const dns::Message& msg) const; + void + TickTun(llarp_time_t now); - bool - HandleHookedDNSMessage(dns::Message query, std::function sendreply); + bool + MapAddress(const service::Address& remote, huint128_t ip, bool SNode); - void - TickTun(llarp_time_t now); + bool + Start() override; - bool - MapAddress(const service::Address& remote, huint128_t ip, bool SNode); + bool + Stop() override; - bool - Start() override; - - bool - Stop() override; - - bool - IsSNode() const; - - /// set up tun interface, blocking - bool - SetupTun(); + bool + IsSNode() const; - void - SetupDNS(); + /// set up tun interface, blocking + bool + SetupTun(); - /// overrides Endpoint - std::shared_ptr - DNS() const override - { - return m_DNS; - }; + void + SetupDNS(); - /// overrides Endpoint - bool - SetupNetworking() override; + /// overrides Endpoint + std::shared_ptr + DNS() const override + { + return m_DNS; + }; - /// overrides Endpoint - bool - HandleInboundPacket( - const service::ConvoTag tag, - const llarp_buffer_t& pkt, - service::ProtocolType t, - uint64_t seqno) override; + /// overrides Endpoint + bool + SetupNetworking() override; + + /// overrides Endpoint + bool + HandleInboundPacket( + const service::ConvoTag tag, + const llarp_buffer_t& pkt, + service::ProtocolType t, + uint64_t seqno) override; + + /// handle inbound traffic + bool + HandleWriteIPPacket(const llarp_buffer_t& buf, huint128_t src, huint128_t dst, uint64_t seqno); + + /// we got a packet from the user + void + HandleGotUserPacket(llarp::net::IPPacket pkt); + + /// get the local interface's address + huint128_t + GetIfAddr() const override; + + /// we have an interface addr + bool + HasIfAddr() const override + { + return true; + } - /// handle inbound traffic - bool - HandleWriteIPPacket( - const llarp_buffer_t& buf, huint128_t src, huint128_t dst, uint64_t seqno); + bool + HasLocalIP(const huint128_t& ip) const; - /// we got a packet from the user - void - HandleGotUserPacket(llarp::net::IPPacket pkt); + std::optional + GetExitPolicy() const override + { + return m_TrafficPolicy; + } - /// get the local interface's address - huint128_t - GetIfAddr() const override; + std::set + GetOwnedRanges() const override + { + return m_OwnedRanges; + } - /// we have an interface addr - bool - HasIfAddr() const override - { - return true; - } + llarp_time_t + PathAlignmentTimeout() const override + { + return m_PathAlignmentTimeout; + } - bool - HasLocalIP(const huint128_t& ip) const; + /// ip packet against any exit policies we have + /// returns false if this traffic is disallowed by any of those policies + /// returns true otherwise + bool + ShouldAllowTraffic(const net::IPPacket& pkt) const; - std::optional - GetExitPolicy() const override - { - return m_TrafficPolicy; - } + /// get a key for ip address + std::optional> + ObtainAddrForIP(huint128_t ip) const override; - std::set - GetOwnedRanges() const override - { - return m_OwnedRanges; - } + bool + HasAddress(const AlignedBuffer<32>& addr) const + { + return m_AddrToIP.find(addr) != m_AddrToIP.end(); + } - llarp_time_t - PathAlignmentTimeout() const override - { - return m_PathAlignmentTimeout; - } + /// get ip address for key unconditionally + huint128_t + ObtainIPForAddr(std::variant addr) override; - /// ip packet against any exit policies we have - /// returns false if this traffic is disallowed by any of those policies - /// returns true otherwise - bool - ShouldAllowTraffic(const net::IPPacket& pkt) const; + void + ResetInternalState() override; - /// get a key for ip address - std::optional> - ObtainAddrForIP(huint128_t ip) const override; + protected: + struct WritePacket + { + uint64_t seqno; + net::IPPacket pkt; bool - HasAddress(const AlignedBuffer<32>& addr) const + operator>(const WritePacket& other) const { - return m_AddrToIP.find(addr) != m_AddrToIP.end(); + return seqno > other.seqno; } + }; - /// get ip address for key unconditionally - huint128_t - ObtainIPForAddr(std::variant addr) override; - - void - ResetInternalState() override; - - protected: - struct WritePacket - { - uint64_t seqno; - net::IPPacket pkt; - - bool - operator>(const WritePacket& other) const - { - return seqno > other.seqno; - } - }; - - /// queue for sending packets to user from network - util::ascending_priority_queue m_NetworkToUserPktQueue; - - void - Pump(llarp_time_t now) override; - - /// return true if we have a remote loki address for this ip address - bool - HasRemoteForIP(huint128_t ipv4) const; - - /// mark this address as active - void - MarkIPActive(huint128_t ip); - - /// mark this address as active forever - void - MarkIPActiveForever(huint128_t ip); - - /// flush writing ip packets to interface - void - FlushWrite(); - - /// maps ip to key (host byte order) - std::unordered_map> m_IPToAddr; - /// maps key to ip (host byte order) - std::unordered_map, huint128_t> m_AddrToIP; - - /// maps key to true if key is a service node, maps key to false if key is - /// a hidden service - std::unordered_map, bool> m_SNodes; - - /// maps ip address to an exit endpoint, useful when we have multiple exits on a range - std::unordered_map m_ExitIPToExitAddress; - - private: - /// given an ip address that is not mapped locally find the address it shall be forwarded to - /// optionally provide a custom selection strategy, if none is provided it will choose a - /// random entry from the available choices - /// return std::nullopt if we cannot route this address to an exit - std::optional - ObtainExitAddressFor( - huint128_t ip, - std::function)> exitSelectionStrat = - nullptr); - - template - void - SendDNSReply( - Addr_t addr, - Endpoint_t ctx, - std::shared_ptr query, - std::function reply, - bool sendIPv6) + /// queue for sending packets to user from network + util::ascending_priority_queue m_NetworkToUserPktQueue; + + void + Pump(llarp_time_t now) override; + + /// return true if we have a remote loki address for this ip address + bool + HasRemoteForIP(huint128_t ipv4) const; + + /// mark this address as active + void + MarkIPActive(huint128_t ip); + + /// mark this address as active forever + void + MarkIPActiveForever(huint128_t ip); + + /// flush writing ip packets to interface + void + FlushWrite(); + + /// maps ip to key (host byte order) + std::unordered_map> m_IPToAddr; + /// maps key to ip (host byte order) + std::unordered_map, huint128_t> m_AddrToIP; + + /// maps key to true if key is a service node, maps key to false if key is + /// a hidden service + std::unordered_map, bool> m_SNodes; + + /// maps ip address to an exit endpoint, useful when we have multiple exits on a range + std::unordered_map m_ExitIPToExitAddress; + + private: + /// given an ip address that is not mapped locally find the address it shall be forwarded to + /// optionally provide a custom selection strategy, if none is provided it will choose a + /// random entry from the available choices + /// return std::nullopt if we cannot route this address to an exit + std::optional + ObtainExitAddressFor( + huint128_t ip, + std::function)> exitSelectionStrat = + nullptr); + + template + void + SendDNSReply( + Addr_t addr, + Endpoint_t ctx, + std::shared_ptr query, + std::function reply, + bool sendIPv6) + { + if (ctx) { - if (ctx) - { - huint128_t ip = ObtainIPForAddr(addr); - query->answers.clear(); - query->AddINReply(ip, sendIPv6); - } - else - query->AddNXReply(); - reply(*query); + huint128_t ip = ObtainIPForAddr(addr); + query->answers.clear(); + query->AddINReply(ip, sendIPv6); } - - /// dns subsystem for this endpoint - std::shared_ptr m_DNS; - - DnsConfig m_DnsConfig; - - /// maps ip address to timestamp last active - std::unordered_map m_IPActivity; - /// our ip address (host byte order) - huint128_t m_OurIP; - /// our network interface's ipv6 address - huint128_t m_OurIPv6; - - /// next ip address to allocate (host byte order) - huint128_t m_NextIP; - /// highest ip address to allocate (host byte order) - huint128_t m_MaxIP; - /// our ip range we are using - llarp::IPRange m_OurRange; - /// list of strict connect addresses for hooks - std::vector m_StrictConnectAddrs; - /// use v6? - bool m_UseV6; - std::string m_IfName; - - std::optional m_BaseV6Address; - - std::shared_ptr m_NetIf; - - std::shared_ptr m_PacketRouter; - - std::optional m_TrafficPolicy; - /// ranges we advetise as reachable - std::set m_OwnedRanges; - /// how long to wait for path alignment - llarp_time_t m_PathAlignmentTimeout; - - /// a file to load / store the ephemeral address map to - std::optional m_PersistAddrMapFile; - - /// for raw packet dns - std::shared_ptr m_RawDNS; - }; - - } // namespace handlers -} // namespace llarp + else + query->AddNXReply(); + reply(*query); + } + + /// dns subsystem for this endpoint + std::shared_ptr m_DNS; + + DnsConfig m_DnsConfig; + + /// maps ip address to timestamp last active + std::unordered_map m_IPActivity; + /// our ip address (host byte order) + huint128_t m_OurIP; + /// our network interface's ipv6 address + huint128_t m_OurIPv6; + + /// next ip address to allocate (host byte order) + huint128_t m_NextIP; + /// highest ip address to allocate (host byte order) + huint128_t m_MaxIP; + /// our ip range we are using + llarp::IPRange m_OurRange; + /// list of strict connect addresses for hooks + std::vector m_StrictConnectAddrs; + /// use v6? + bool m_UseV6; + std::string m_IfName; + + std::optional m_BaseV6Address; + + std::shared_ptr m_NetIf; + + std::shared_ptr m_PacketRouter; + + std::optional m_TrafficPolicy; + /// ranges we advetise as reachable + std::set m_OwnedRanges; + /// how long to wait for path alignment + llarp_time_t m_PathAlignmentTimeout; + + /// a file to load / store the ephemeral address map to + std::optional m_PersistAddrMapFile; + + /// for raw packet dns + std::shared_ptr m_RawDNS; + }; + +} // namespace llarp::handlers diff --git a/llarp/link/contacts.cpp b/llarp/link/contacts.cpp index 43f6ce4b36..c90d8d13ac 100644 --- a/llarp/link/contacts.cpp +++ b/llarp/link/contacts.cpp @@ -60,7 +60,7 @@ namespace llarp } util::StatusObject - Contacts::extract_status() const + Contacts::ExtractStatus() const { util::StatusObject obj{ {"nodes", _rc_nodes->ExtractStatus()}, @@ -70,19 +70,14 @@ namespace llarp } bool - Contacts::lookup_router( - const RouterID& rid, std::function&)> func) + Contacts::lookup_router(const RouterID& rid) { dht::Key_t ask_peer; if (not _rc_nodes->FindClosest(dht::Key_t{rid}, ask_peer)) return false; - _router.loop()->call([this, rid, func]() { - pending_lookups[rid] = [](const std::vector&) { - // TODO: combine this concept with service::Endpoint introset lookups? - }; - + _router.loop()->call([this, rid]() { _router.send_control_message( rid, "find_router", FindRouterMessage::serialize(rid, false, false, 0)); }); diff --git a/llarp/link/contacts.hpp b/llarp/link/contacts.hpp index 8164c7b5d1..ed36b1a11f 100644 --- a/llarp/link/contacts.hpp +++ b/llarp/link/contacts.hpp @@ -35,20 +35,18 @@ namespace llarp return not transit_allowed.exchange(b) == b; } - std::unordered_map&)>> - pending_lookups; - void on_clean_contacts(); std::optional get_introset_by_location(const dht::Key_t& key) const; + // TODO: rename every ExtractStatus function to be uniformly snake cased util::StatusObject - extract_status() const; + ExtractStatus() const; bool - lookup_router(const RouterID&, std::function&)>); + lookup_router(const RouterID&); void put_rc_node_async(const dht::RCNode& val); diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index ed406fb559..74eacc6545 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -2,6 +2,7 @@ #include "connection.hpp" #include "contacts.hpp" +#include #include #include #include @@ -190,17 +191,14 @@ namespace llarp std::string body, std::function func) { - if (func) - return send_control_message_impl( - remote, std::move(endpoint), std::move(body), std::move(func)); - - if (auto itr = rpc_responses.find(endpoint); itr != rpc_responses.end()) - return send_control_message_impl( - remote, std::move(endpoint), std::move(body), [&](oxen::quic::message m) { - return std::invoke(itr->second, this, std::move(m)); - }); + if (not func and rpc_responses.count(endpoint)) + { + func = [&](oxen::quic::message m) { + return std::invoke(rpc_responses[endpoint], this, std::move(m)); + }; + } - return send_control_message_impl(remote, std::move(endpoint), std::move(body)); + return send_control_message_impl(remote, std::move(endpoint), std::move(body), std::move(func)); } bool @@ -213,12 +211,13 @@ namespace llarp if (is_stopping) return false; - auto cb = [this, f = std::move(func), endpoint](oxen::quic::message m) { - f(m); + // DISCUSS: uncomment this if we want to excecute two callbacks + // auto cb = [this, f = std::move(func), endpoint](oxen::quic::message m) { + // f(m); - if (auto itr = rpc_responses.find(endpoint); itr != rpc_responses.end()) - std::invoke(itr->second, this, std::move(m)); - }; + // if (auto itr = rpc_responses.find(endpoint); itr != rpc_responses.end()) + // std::invoke(itr->second, this, std::move(m)); + // }; if (auto conn = ep.get_conn(remote); conn) { @@ -520,6 +519,12 @@ namespace llarp // TODO: this } + std::string + LinkManager::serialize_response(oxenc::bt_dict supplement) + { + return oxenc::bt_serialize(supplement); + } + void LinkManager::handle_find_name(oxen::quic::message m) { @@ -536,22 +541,59 @@ namespace llarp catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond("ERROR", true); + m.respond(serialize_response({{"STATUS", FindNameMessage::EXCEPTION}}), true); } router.rpc_client()->lookup_ons_hash( name_hash, [this, msg = std::move(m)](std::optional maybe) mutable { if (maybe.has_value()) - msg.respond(serialize_response(true, {{"NAME", maybe->ciphertext.c_str()}})); + msg.respond(serialize_response({{"NAME", maybe->ciphertext.c_str()}})); else - msg.respond(serialize_response(false, {{"STATUS", "NOT FOUND"}}), true); + msg.respond(serialize_response({{"STATUS", FindNameMessage::NOT_FOUND}}), true); }); } - std::string - LinkManager::serialize_response(bool success, oxenc::bt_dict supplement) + void + LinkManager::handle_find_name_response(oxen::quic::message m) { - return oxenc::bt_serialize(oxenc::bt_list{(success) ? 1 : 0, supplement}); + if (m.timed_out) + { + // do something smart here inshallah + } + + std::string payload; + + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + payload = btdc.require(m ? "NAME" : "STATUS"); + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + return; + } + + if (m) + { + // TODO: wtf + } + else + { + if (payload == FindNameMessage::EXCEPTION) + { + log::critical(link_cat, "FindNameMessage failed with unkown error!"); + + // resend? + } + else if (payload == FindNameMessage::NOT_FOUND) + { + log::critical(link_cat, "FindNameMessage failed with unkown error!"); + // what to do here? + } + else + log::critical(link_cat, "FindNameMessage failed with unkown error!"); + } } void @@ -566,19 +608,18 @@ namespace llarp is_exploratory = btdc.require("E"); is_iterative = btdc.require("I"); - target_key = btdc.require("E"); + target_key = btdc.require("K"); } catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); + m.respond( + serialize_response({{"STATUS", FindRouterMessage::EXCEPTION}, {"RECIPIENT", ""}}), true); return; } // TODO: do we need a replacement for dht.AllowTransit() etc here? - // TODO: do we need a replacement for dht.pendingIntroSetLookups() etc here? - RouterID target_rid; target_rid.FromString(target_key); const auto target_addr = dht::Key_t{reinterpret_cast(target_key.data())}; @@ -602,7 +643,7 @@ namespace llarp m.respond( serialize_response( - false, {{"STATUS", "RETRY EXPLORATORY"}, {"ROUTERS", neighbors.c_str()}}), + {{"STATUS", FindRouterMessage::RETRY_EXP}, {"RECIPIENT", neighbors.c_str()}}), true); } else @@ -615,42 +656,106 @@ namespace llarp { if (closest_rc.ExpiresSoon(llarp::time_now_ms())) { - send_control_message_impl( - target_rid, "find_router", m.body_str(), [this](oxen::quic::message m) { - return handle_find_router_response(std::move(m)); - }); + send_control_message( + target_rid, "find_router", FindRouterMessage::serialize(target_rid, false, false, 0)); } else { - m.respond(serialize_response(true, {{"RC", closest_rc.ToString().c_str()}})); + m.respond(serialize_response({{"RC", closest_rc.ToString().c_str()}})); } } else if (not is_iterative) { if ((closest_key ^ target_addr) < (local_key ^ target_addr)) { - send_control_message_impl( - closest_rc.pubkey, "find_router", m.body_str(), [this](oxen::quic::message m) { - return handle_find_router_response(std::move(m)); - }); + send_control_message( + closest_rid, + "find_router", + FindRouterMessage::serialize(closest_rid, false, false, 0)); } else { - m.respond(serialize_response(false, {{"STATUS", "RETRY ITERATIVE"}}), true); + m.respond( + serialize_response( + {{"STATUS", FindRouterMessage::RETRY_ITER}, {"RECIPIENT", target_addr.data()}}), + true); } } else { m.respond( serialize_response( - false, - {{"STATUS", "RETRY NEW RECIPIENT"}, + {{"STATUS", FindRouterMessage::RETRY_NEW}, {"RECIPIENT", reinterpret_cast(closest_rid.data())}}), true); } } } + void + LinkManager::handle_find_router_response(oxen::quic::message m) + { + if (m.timed_out) + { + log::critical(link_cat, "FindRouterMessage timed out!"); + return; + } + + std::string status, payload; + + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + + if (m) + payload = btdc.require("RC"); + else + { + status = btdc.require("STATUS"); + payload = btdc.require("RECIPIENT"); + } + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + return; + } + + if (m) + { + router.node_db()->PutIfNewer(RouterContact{payload}); + } + else + { + if (status == FindRouterMessage::EXCEPTION) + { + log::critical(link_cat, "FindRouterMessage failed with remote exception!"); + // Do something smart here probably + return; + } + + RouterID target{reinterpret_cast(payload.data())}; + if (status == FindRouterMessage::RETRY_EXP) + { + log::critical(link_cat, "FindRouterMessage failed, retrying as exploratory!"); + send_control_message( + target, "find_router", FindRouterMessage::serialize(target, false, true, 0)); + } + else if (status == FindRouterMessage::RETRY_ITER) + { + log::critical(link_cat, "FindRouterMessage failed, retrying as iterative!"); + send_control_message( + target, "find_router", FindRouterMessage::serialize(target, true, false, 0)); + } + else if (status == FindRouterMessage::RETRY_NEW) + { + log::critical(link_cat, "FindRouterMessage failed, retrying with new recipient!"); + send_control_message( + target, "find_router", FindRouterMessage::serialize(target, false, false, 0)); + } + } + } + void LinkManager::handle_publish_intro(oxen::quic::message m) { @@ -678,7 +783,7 @@ namespace llarp catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); + m.respond(serialize_response({{"STATUS", PublishIntroMessage::EXCEPTION}}), true); return; } @@ -689,14 +794,14 @@ namespace llarp if (not service::EncryptedIntroSet::verify(introset, derived_signing_key, sig)) { log::error(link_cat, "Received PublishIntroMessage with invalid introset: {}", introset); - m.respond(serialize_response(false, {{"STATUS", "INVALID INTROSET"}}), true); + m.respond(serialize_response({{"STATUS", PublishIntroMessage::INVALID_INTROSET}}), true); return; } if (now + service::MAX_INTROSET_TIME_DELTA > signed_at + path::DEFAULT_LIFETIME) { log::error(link_cat, "Received PublishIntroMessage with expired introset: {}", introset); - m.respond(serialize_response(false, {{"STATUS", "EXPIRED INTROSET"}}), true); + m.respond(serialize_response({{"STATUS", PublishIntroMessage::EXPIRED}}), true); return; } @@ -706,7 +811,7 @@ namespace llarp { log::error( link_cat, "Received PublishIntroMessage but only know {} nodes", closest_rcs.size()); - m.respond(serialize_response(false, {{"STATUS", "INSUFFICIENT NODES"}}), true); + m.respond(serialize_response({{"STATUS", PublishIntroMessage::INSUFFICIENT}}), true); return; } @@ -718,7 +823,7 @@ namespace llarp { log::error( link_cat, "Received PublishIntroMessage with invalide relay order: {}", relay_order); - m.respond(serialize_response(false, {{"STATUS", "INVALID ORDER"}}), true); + m.respond(serialize_response({{"STATUS", PublishIntroMessage::INVALID_ORDER}}), true); return; } @@ -735,17 +840,17 @@ namespace llarp relay_order); router.contacts()->services()->PutNode(dht::ISNode{std::move(enc)}); - m.respond(serialize_response(true)); + m.respond(serialize_response({{"STATUS", ""}})); } else { log::info( link_cat, "Received PublishIntroMessage; propagating to peer index {}", relay_order); - send_control_message_impl( - peer_key, "publish_intro", m.body_str(), [this](oxen::quic::message m) { - return handle_publish_intro_response(std::move(m)); - }); + send_control_message( + peer_key, + "publish_intro", + PublishIntroMessage::serialize(introset, relay_order, is_relayed, tx_id)); } return; @@ -768,7 +873,7 @@ namespace llarp log::info(link_cat, "Received PublishIntroMessage for {} (TXID: {}); we are candidate {}"); router.contacts()->services()->PutNode(dht::ISNode{std::move(enc)}); - m.respond(serialize_response(true)); + m.respond(serialize_response()); } else log::warning( @@ -777,10 +882,53 @@ namespace llarp addr); } + void + LinkManager::handle_publish_intro_response(oxen::quic::message m) + { + std::string payload; + + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + payload = btdc.require("STATUS"); + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + return; + } + + if (m) + { + // DISCUSS: not sure what to do on success of a publish intro command? + } + else + { + if (payload == PublishIntroMessage::EXCEPTION) + { + log::critical(link_cat, "PublishIntroMessage failed with remote exception!"); + // Do something smart here probably + return; + } + + log::critical(link_cat, "PublishIntroMessage failed with error code: {}", payload); + + if (payload == PublishIntroMessage::INVALID_INTROSET) + {} + else if (payload == PublishIntroMessage::EXPIRED) + {} + else if (payload == PublishIntroMessage::INSUFFICIENT) + {} + else if (payload == PublishIntroMessage::INVALID_ORDER) + {} + } + } + void LinkManager::handle_find_intro(oxen::quic::message m) { - std::string tag_name, location; + std::string tag_name; + ustring location; uint64_t tx_id, relay_order, is_relayed; try @@ -790,19 +938,17 @@ namespace llarp tag_name = btdc.require("N"); relay_order = btdc.require("O"); is_relayed = btdc.require("R"); - location = btdc.require("S"); + location = btdc.require("S"); tx_id = btdc.require("T"); } catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); + m.respond(serialize_response({{"STATUS", FindIntroMessage::EXCEPTION}}), true); return; } - // TODO: do we need a replacement for dht.pendingIntroSetLookups() etc here? - - const auto addr = dht::Key_t{reinterpret_cast(location.data())}; + const auto addr = dht::Key_t{location.data()}; if (is_relayed) { @@ -810,7 +956,7 @@ namespace llarp { log::warning( link_cat, "Received FindIntroMessage with invalid relay order: {}", relay_order); - m.respond(serialize_response(false, {{"STATUS", "INVALID ORDER"}}), true); + m.respond(serialize_response({{"STATUS", FindIntroMessage::INVALID_ORDER}}), true); return; } @@ -820,7 +966,7 @@ namespace llarp { log::error( link_cat, "Received FindIntroMessage but only know {} nodes", closest_rcs.size()); - m.respond(serialize_response(false, {{"STATUS", "INSUFFICIENT NODES"}}), true); + m.respond(serialize_response({{"STATUS", FindIntroMessage::INSUFFICIENT_NODES}}), true); return; } @@ -829,94 +975,67 @@ namespace llarp const auto& peer_rc = closest_rcs[relay_order]; const auto& peer_key = peer_rc.pubkey; - send_control_message_impl( - peer_key, "find_intro", m.body_str(), [this](oxen::quic::message m) { - return handle_find_intro_response(std::move(m)); - }); - return; - } - - // TODO: replace this concept and add it to the response - // const auto maybe = dht.GetIntroSetByLocation(location); - m.respond(serialize_response(true, {{"INTROSET", ""}})); - } - - void - LinkManager::handle_path_confirm(oxen::quic::message m) - { - try - { - oxenc::bt_dict_consumer btdc{m.body()}; + send_control_message( + peer_key, + "find_intro", + FindIntroMessage::serialize( + dht::Key_t{peer_key}, tag_name, tx_id, is_relayed, relay_order)); } - catch (const std::exception& e) + else { - log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); - return; + if (auto maybe_intro = router.contacts()->get_introset_by_location(addr)) + m.respond(serialize_response({{"INTROSET", maybe_intro->bt_encode()}})); + else + { + log::warning( + link_cat, + "Received FindIntroMessage with relayed == false and no local introset entry"); + m.respond(serialize_response({{"STATUS", FindIntroMessage::NOT_FOUND}}), true); + } } } void - LinkManager::handle_path_latency(oxen::quic::message m) + LinkManager::handle_find_intro_response(oxen::quic::message m) { - try - { - oxenc::bt_dict_consumer btdc{m.body()}; - } - catch (const std::exception& e) + if (m.timed_out) { - log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); + log::critical(link_cat, "FindIntroMessage timed out!"); return; } - } - void - LinkManager::handle_update_exit(oxen::quic::message m) - { + std::string payload; + try { oxenc::bt_dict_consumer btdc{m.body()}; + + if (m) + payload = btdc.require("INTROSET"); + else + payload = btdc.require("STATUS"); } catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); return; } - } - void - LinkManager::handle_obtain_exit(oxen::quic::message m) - { - // TODO: implement transit_hop things like nextseqno(), info.rxID, etc - std::string payload{m.body_str()}, pubkey; - [[maybe_unused]] uint64_t flag, tx_id, seq_no; - - try + // success case, neither timed out nor errored + if (m) { - oxenc::bt_dict_consumer btdc{payload}; - - flag = btdc.require("E"); - pubkey = btdc.require("I"); - seq_no = btdc.require("S"); - tx_id = btdc.require("T"); + service::EncryptedIntroSet enc{payload}; + router.contacts()->services()->PutNode(std::move(enc)); } - catch (const std::exception& e) + else { - log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); - return; + log::critical(link_cat, "FindIntroMessage failed with error: {}", payload); + // Do something smart here probably } - - RouterID target; - target.FromString(pubkey); - - // auto handler = router.path_context().GetByDownstream(target, tx_id); } void - LinkManager::handle_close_exit(oxen::quic::message m) + LinkManager::handle_path_confirm(oxen::quic::message m) { try { @@ -925,13 +1044,13 @@ namespace llarp catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); + m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); return; } } void - LinkManager::handle_publish_intro_response(oxen::quic::message m) + LinkManager::handle_path_latency(oxen::quic::message m) { try { @@ -940,13 +1059,13 @@ namespace llarp catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); + m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); return; } } void - LinkManager::handle_find_name_response(oxen::quic::message m) + LinkManager::handle_update_exit(oxen::quic::message m) { try { @@ -955,28 +1074,42 @@ namespace llarp catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); + m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); return; } } void - LinkManager::handle_find_router_response(oxen::quic::message m) + LinkManager::handle_obtain_exit(oxen::quic::message m) { + // TODO: implement transit_hop things like nextseqno(), info.rxID, etc + std::string payload{m.body_str()}, pubkey; + [[maybe_unused]] uint64_t flag, tx_id, seq_no; + try { - oxenc::bt_dict_consumer btdc{m.body()}; + oxenc::bt_dict_consumer btdc{payload}; + + flag = btdc.require("E"); + pubkey = btdc.require("I"); + seq_no = btdc.require("S"); + tx_id = btdc.require("T"); } catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); + m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); return; } + + RouterID target; + target.FromString(pubkey); + + // auto handler = router.path_context().GetByDownstream(target, tx_id); } void - LinkManager::handle_find_intro_response(oxen::quic::message m) + LinkManager::handle_close_exit(oxen::quic::message m) { try { @@ -985,10 +1118,8 @@ namespace llarp catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response(false, {{"STATUS", "EXCEPTION"}}), true); + m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); return; } - - // check if we have any pending intro lookups in contacts } } // namespace llarp diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 4651f03ba9..395847693b 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -1,6 +1,8 @@ #pragma once #include "connection.hpp" +#include +#include #include #include @@ -279,22 +281,23 @@ namespace llarp size_t max_connected_routers = 6; private: - // Control message - - // Bridge (relay) message - void handle_publish_intro(oxen::quic::message); - void handle_find_intro(oxen::quic::message); - void handle_find_name(oxen::quic::message); - void handle_path_confirm(oxen::quic::message); - void handle_path_latency(oxen::quic::message); - void handle_update_exit(oxen::quic::message); - void handle_obtain_exit(oxen::quic::message); - void handle_close_exit(oxen::quic::message); - - // Control and bridge message (separate into two type) - - // Unsure - void handle_find_router(oxen::quic::message); // maybe both + // DHT messages + void handle_find_name(oxen::quic::message); // relay + void handle_find_intro(oxen::quic::message); // relay + void handle_publish_intro(oxen::quic::message); // relay + void handle_find_router(oxen::quic::message); // relay + path + + // Path messages + void handle_relay_commit(oxen::quic::message); // relay + void handle_relay_status(oxen::quic::message); // relay + void handle_path_confirm(oxen::quic::message); // relay + void handle_path_latency(oxen::quic::message); // relay + void handle_path_transfer(oxen::quic::message); // relay + + // Exit messages + void handle_obtain_exit(oxen::quic::message); // relay + void handle_update_exit(oxen::quic::message); // relay + void handle_close_exit(oxen::quic::message); // relay std::unordered_map rpc_commands = { {"find_name", &LinkManager::handle_find_name}, @@ -307,20 +310,32 @@ namespace llarp {"obtain_exit", &LinkManager::handle_obtain_exit}, {"close_exit", &LinkManager::handle_close_exit}}; + // DHT responses + void handle_find_name_response(oxen::quic::message); + void handle_find_intro_response(oxen::quic::message); + void handle_publish_intro_response(oxen::quic::message); + void handle_find_router_response(oxen::quic::message); + + // Path responses + void handle_relay_commit_response(oxen::quic::message); + void handle_relay_status_response(oxen::quic::message); + void handle_path_confirm_response(oxen::quic::message); + void handle_path_latency_response(oxen::quic::message); + void handle_path_transfer_response(oxen::quic::message); + + // Exit responses + void handle_obtain_exit_response(oxen::quic::message); + void handle_update_exit_response(oxen::quic::message); + void handle_close_exit_response(oxen::quic::message); + std::unordered_map rpc_responses = { {"find_name", &LinkManager::handle_find_name_response}, {"find_router", &LinkManager::handle_find_router_response}, {"publish_intro", &LinkManager::handle_publish_intro_response}, {"find_intro", &LinkManager::handle_find_intro_response}}; - // response handling functions - void handle_publish_intro_response(oxen::quic::message); - void handle_find_name_response(oxen::quic::message); // not used? - void handle_find_router_response(oxen::quic::message); - void handle_find_intro_response(oxen::quic::message); - std::string - serialize_response(bool success, oxenc::bt_dict supplement = {}); + serialize_response(oxenc::bt_dict supplement = {}); }; namespace link diff --git a/llarp/messages/common.hpp b/llarp/messages/common.hpp index f59700931c..32fd492833 100644 --- a/llarp/messages/common.hpp +++ b/llarp/messages/common.hpp @@ -1,10 +1,15 @@ #pragma once +#include +#include +#include +#include +#include #include -#include - #include +#include + namespace { static auto link_cat = llarp::log::Cat("lokinet.link"); diff --git a/llarp/messages/dht.hpp b/llarp/messages/dht.hpp index fffc9e69f9..48aed8db3b 100644 --- a/llarp/messages/dht.hpp +++ b/llarp/messages/dht.hpp @@ -2,42 +2,26 @@ #include "common.hpp" -#include -#include -#include -#include - -#include - namespace llarp { - struct DHTMessage : public AbstractSerializable - {}; - - struct FindRouterMessage : public DHTMessage + namespace FindRouterMessage { - private: - RouterID target; - bool is_iterative{false}; - bool is_exploratory{false}; - uint64_t tx_id{0}; - - public: - explicit FindRouterMessage(const RouterID& rid, bool is_itr, bool is_exp, uint64_t tx) - : target{rid}, is_iterative{is_itr}, is_exploratory{is_exp}, tx_id{tx} - {} - - std::string - bt_encode() const override + inline const char* EXCEPTION = "EXCEPTION"; + inline const char* RETRY_EXP = "RETRY AS EXPLORATORY"; + inline const char* RETRY_ITER = "RETRY AS ITERATIVE"; + inline const char* RETRY_NEW = "RETRY WITH NEW RECIPIENT"; + + inline static std::string + serialize(const RouterID& rid, bool is_iterative, bool is_exploratory, uint64_t tx_id) { oxenc::bt_dict_producer btdp; try { btdp.append("A", "R"); - btdp.append("E", is_exploratory ? 1 : 0); - btdp.append("I", is_iterative ? 1 : 0); - btdp.append("K", target.ToView()); + btdp.append("E", is_exploratory); + btdp.append("I", is_iterative); + btdp.append("K", rid.ToView()); btdp.append("T", tx_id); } catch (...) @@ -47,26 +31,91 @@ namespace llarp return std::move(btdp).str(); } + } // namespace FindRouterMessage - static std::string - serialize(const RouterID& rid, bool is_itr, bool is_exp, uint64_t tx) + namespace FindIntroMessage + { + inline const char* EXCEPTION = "EXCEPTION"; + inline const char* NOT_FOUND = "NOT FOUND"; + inline const char* INVALID_ORDER = "INVALID ORDER"; + inline const char* INSUFFICIENT_NODES = "INSUFFICIENT NODES"; + + inline static std::string + serialize( + const dht::Key_t& location, std::string tag, uint64_t txid, bool is_relayed, uint64_t order) { oxenc::bt_dict_producer btdp; try { - btdp.append("A", "R"); - btdp.append("E", is_exp ? 1 : 0); - btdp.append("I", is_itr ? 1 : 0); - btdp.append("K", rid.ToView()); - btdp.append("T", tx); + btdp.append("A", "F"); + btdp.append("N", tag); + btdp.append("O", order); + btdp.append("R", is_relayed ? 1 : 0); + btdp.append("S", location.ToView()); + btdp.append("T", txid); } catch (...) { - log::error(link_cat, "Error: FindRouterMessage failed to bt encode contents!"); + log::error(link_cat, "Error: FindIntroMessage failed to bt encode contents!"); + } + + return std::move(btdp).str(); + } + } // namespace FindIntroMessage + + namespace FindNameMessage + { + inline const char* EXCEPTION = "EXCEPTION"; + inline const char* NOT_FOUND = "NOT FOUND"; + + inline static std::string + serialize([[maybe_unused]] const dht::Key_t& from, dht::Key_t name_hash, uint64_t tx_id) + { + oxenc::bt_dict_producer btdp; + + try + { + btdp.append("A", "N"); + btdp.append("H", name_hash.ToView()); + btdp.append("T", tx_id); + } + catch (...) + { + log::error(link_cat, "Error: FindNameMessage failed to bt encode contents!"); + } + + return std::move(btdp).str(); + } + } // namespace FindNameMessage + + namespace PublishIntroMessage + { + inline const char* EXCEPTION = "EXCEPTION"; + inline const char* INVALID_INTROSET = "INVALID INTROSET"; + inline const char* EXPIRED = "EXPIRED INTROSET"; + inline const char* INSUFFICIENT = "INSUFFICIENT NODES"; + inline const char* INVALID_ORDER = "INVALID ORDER"; + + inline static std::string + serialize(std::string introset, uint64_t relay_order, uint64_t is_relayed, uint64_t tx_id) + { + oxenc::bt_dict_producer btdp; + + try + { + btdp.append("A", "I"); + btdp.append("I", introset); + btdp.append("O", relay_order); + btdp.append("R", is_relayed); + btdp.append("T", tx_id); + } + catch (...) + { + log::error(link_cat, "Error: FindNameMessage failed to bt encode contents!"); } return std::move(btdp).str(); } - }; + } // namespace PublishIntroMessage } // namespace llarp diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp new file mode 100644 index 0000000000..a548259c00 --- /dev/null +++ b/llarp/messages/path.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "common.hpp" + +namespace llarp +{ + struct PathMessage : public AbstractSerializable + {}; + + struct RelayCommitMessage : public PathMessage + {}; + + struct RelayStatusMessage : public PathMessage + {}; + + struct PathConfirmMessage : public PathMessage + {}; + + struct PathLatencyMessage : public PathMessage + {}; + + struct PathTransferMessage : public PathMessage + {}; + +} // namespace llarp diff --git a/llarp/net/traffic_policy.cpp b/llarp/net/traffic_policy.cpp index 794ac33830..e10b1eaae7 100644 --- a/llarp/net/traffic_policy.cpp +++ b/llarp/net/traffic_policy.cpp @@ -110,11 +110,7 @@ namespace llarp::net { try { - { - auto sublist = btlp.append_list(); - sublist.append(static_cast(protocol)); - } - + btlp.append(static_cast(protocol)); btlp.append(ToHost(*port).h); } catch (...) @@ -123,6 +119,39 @@ namespace llarp::net } } + ProtocolInfo::ProtocolInfo(std::string buf) + { + try + { + oxenc::bt_list_consumer btlc{std::move(buf)}; + protocol = static_cast(btlc.consume_integer()); + port->FromString(btlc.consume_string()); + } + catch (...) + { + log::critical(net_cat, "Error: ProtocolInfo failed to bt encode contents!"); + } + } + + void + TrafficPolicy::bt_decode(oxenc::bt_dict_consumer& btdc) + { + try + { + { + auto sublist = btdc.consume_list_consumer(); + while (not sublist.is_finished()) + { + protocols.emplace(sublist.consume_string()); + } + } + } + catch (...) + { + log::critical(net_cat, "Error: TrafficPolicy failed to populate with bt encoded contents"); + } + } + void TrafficPolicy::bt_encode(oxenc::bt_dict_producer& btdp) const { diff --git a/llarp/net/traffic_policy.hpp b/llarp/net/traffic_policy.hpp index 6175b54e85..dbfc52b76c 100644 --- a/llarp/net/traffic_policy.hpp +++ b/llarp/net/traffic_policy.hpp @@ -18,6 +18,8 @@ namespace llarp::net /// the layer 3 port if applicable std::optional port; + ProtocolInfo(std::string buf); + void bt_encode(oxenc::bt_list_producer& btlp) const; @@ -54,6 +56,8 @@ namespace llarp::net void bt_encode(oxenc::bt_dict_producer& btdp) const; + void + bt_decode(oxenc::bt_dict_consumer& btdc); bool BDecode(llarp_buffer_t* buf); diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index 285e40b569..360046568c 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -185,7 +185,7 @@ namespace llarp } Builder::Builder(Router* p_router, size_t pathNum, size_t hops) - : path::PathSet{pathNum}, _run{true}, m_router{p_router}, numHops{hops} + : path::PathSet{pathNum}, _run{true}, router{p_router}, numHops{hops} { CryptoManager::instance()->encryption_keygen(enckey); } @@ -202,12 +202,12 @@ namespace llarp { PathSet::Tick(now); now = llarp::time_now_ms(); - m_router->pathbuild_limiter().Decay(now); + router->pathbuild_limiter().Decay(now); - ExpirePaths(now, m_router); + ExpirePaths(now, router); if (ShouldBuildMore(now)) BuildOne(); - TickPaths(m_router); + TickPaths(router); if (m_BuildStats.attempts > 50) { if (m_BuildStats.SuccessRatio() <= BuildStats::MinGoodRatio && now - m_LastWarn > 5s) @@ -237,10 +237,10 @@ namespace llarp Builder::SelectFirstHop(const std::set& exclude) const { std::optional found = std::nullopt; - m_router->for_each_connection([&](link::Connection& conn) { + router->for_each_connection([&](link::Connection& conn) { const auto& rc = conn.remote_rc; #ifndef TESTNET - if (m_router->IsBootstrapNode(rc.pubkey)) + if (router->IsBootstrapNode(rc.pubkey)) return; #endif if (exclude.count(rc.pubkey)) @@ -249,7 +249,7 @@ namespace llarp if (BuildCooldownHit(rc.pubkey)) return; - if (m_router->router_profiling().IsBadForPath(rc.pubkey)) + if (router->router_profiling().IsBadForPath(rc.pubkey)) return; found = rc; @@ -260,10 +260,10 @@ namespace llarp std::optional> Builder::GetHopsForBuild() { - auto filter = [r = m_router](const auto& rc) -> bool { + auto filter = [r = router](const auto& rc) -> bool { return not r->router_profiling().IsBadForPath(rc.pubkey, 1); }; - if (const auto maybe = m_router->node_db()->GetRandom(filter)) + if (const auto maybe = router->node_db()->GetRandom(filter)) { return GetHopsAlignedToForBuild(maybe->pubkey); } @@ -304,7 +304,7 @@ namespace llarp bool Builder::BuildCooldownHit(RouterID edge) const { - return m_router->pathbuild_limiter().Limited(edge); + return router->pathbuild_limiter().Limited(edge); } bool @@ -339,7 +339,7 @@ namespace llarp std::optional> Builder::GetHopsAlignedToForBuild(RouterID endpoint, const std::set& exclude) { - const auto pathConfig = m_router->config()->paths; + const auto pathConfig = router->config()->paths; std::vector hops; { @@ -353,7 +353,7 @@ namespace llarp }; RouterContact endpointRC; - if (const auto maybe = m_router->node_db()->Get(endpoint)) + if (const auto maybe = router->node_db()->Get(endpoint)) { endpointRC = *maybe; } @@ -369,7 +369,7 @@ namespace llarp else { auto filter = - [&hops, r = m_router, endpointRC, pathConfig, exclude](const auto& rc) -> bool { + [&hops, r = router, endpointRC, pathConfig, exclude](const auto& rc) -> bool { if (exclude.count(rc.pubkey)) return false; @@ -393,7 +393,7 @@ namespace llarp return rc.pubkey != endpointRC.pubkey; }; - if (const auto maybe = m_router->node_db()->GetRandom(filter)) + if (const auto maybe = router->node_db()->GetRandom(filter)) hops.emplace_back(*maybe); else return std::nullopt; @@ -417,7 +417,7 @@ namespace llarp llarp_time_t Builder::Now() const { - return m_router->now(); + return router->now(); } void @@ -427,26 +427,26 @@ namespace llarp return; lastBuild = Now(); const RouterID edge{hops[0].pubkey}; - if (not m_router->pathbuild_limiter().Attempt(edge)) + if (not router->pathbuild_limiter().Attempt(edge)) { LogWarn(Name(), " building too fast to edge router ", edge); return; } // async generate keys auto ctx = std::make_shared(); - ctx->router = m_router; + ctx->router = router; auto self = GetSelf(); ctx->pathset = self; - std::string path_shortName = "[path " + m_router->ShortName() + "-"; - path_shortName = path_shortName + std::to_string(m_router->NextPathBuildNumber()) + "]"; + std::string path_shortName = "[path " + router->ShortName() + "-"; + path_shortName = path_shortName + std::to_string(router->NextPathBuildNumber()) + "]"; auto path = std::make_shared(hops, GetWeak(), roles, std::move(path_shortName)); LogInfo(Name(), " build ", path->ShortName(), ": ", path->HopsString()); path->SetBuildResultHook([self](Path_ptr p) { self->HandlePathBuilt(p); }); ctx->AsyncGenerateKeys( path, - m_router->loop(), - [r = m_router](auto func) { r->queue_work(std::move(func)); }, + router->loop(), + [r = router](auto func) { r->queue_work(std::move(func)); }, &PathBuilderKeysGenerated); } @@ -454,7 +454,7 @@ namespace llarp Builder::HandlePathBuilt(Path_ptr p) { buildIntervalLimit = PATH_BUILD_RATE; - m_router->router_profiling().MarkPathSuccess(p.get()); + router->router_profiling().MarkPathSuccess(p.get()); LogInfo(p->Name(), " built latency=", ToString(p->intro.latency)); m_BuildStats.success++; @@ -479,14 +479,14 @@ namespace llarp void Builder::HandlePathBuildTimeout(Path_ptr p) { - m_router->router_profiling().MarkPathTimeout(p.get()); + router->router_profiling().MarkPathTimeout(p.get()); PathSet::HandlePathBuildTimeout(p); DoPathBuildBackoff(); for (const auto& hop : p->hops) { const RouterID router{hop.rc.pubkey}; // look up router and see if it's still on the network - m_router->loop()->call_soon([router, r = m_router]() { + router->loop()->call_soon([router, r = router]() { LogInfo("looking up ", router, " because of path build timeout"); r->rc_lookup_handler().get_rc( router, diff --git a/llarp/path/pathbuilder.hpp b/llarp/path/pathbuilder.hpp index a874cc214e..a29bc869ef 100644 --- a/llarp/path/pathbuilder.hpp +++ b/llarp/path/pathbuilder.hpp @@ -55,7 +55,7 @@ namespace llarp::path DoPathBuildBackoff(); public: - Router* const m_router; + Router* const router; SecretKey enckey; size_t numHops; llarp_time_t lastBuild = 0s; diff --git a/llarp/path/pathset.hpp b/llarp/path/pathset.hpp index 456276c498..a380cf3a7b 100644 --- a/llarp/path/pathset.hpp +++ b/llarp/path/pathset.hpp @@ -268,12 +268,6 @@ namespace llarp GetCurrentIntroductionsWithFilter( std::function filter) const; - virtual bool - PublishIntroSet(const service::EncryptedIntroSet&) - { - return false; - } - /// reset all cooldown timers virtual void ResetInternalState() = 0; diff --git a/llarp/router/rc_lookup_handler.cpp b/llarp/router/rc_lookup_handler.cpp index a01b744e90..221048b43f 100644 --- a/llarp/router/rc_lookup_handler.cpp +++ b/llarp/router/rc_lookup_handler.cpp @@ -113,7 +113,7 @@ namespace llarp LogWarn("cannot lookup ", router, " anonymously"); } - if (not contacts->lookup_router(router, fn)) + if (not contacts->lookup_router(router)) { finalize_request(router, nullptr, RCRequestResult::RouterNotFound); } diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 4dc7a8962f..7aeb346c31 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -96,7 +96,7 @@ namespace llarp return util::StatusObject{ {"running", true}, {"numNodesKnown", _node_db->NumLoaded()}, - {"contacts", _contacts->extract_status()}, + {"contacts", _contacts->ExtractStatus()}, {"services", _hidden_service_context.ExtractStatus()}, {"exit", _exit_context.ExtractStatus()}, {"links", _link_manager.extract_status()}, diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index e1aa240ba5..cc89190de8 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -87,6 +87,21 @@ namespace llarp return bencode_write_bytestring(buf, data(), std::distance(begin(), term)); } + RouterContact::RouterContact(std::string buf) + { + try + { + oxenc::bt_list_consumer btlc{buf}; + + signature.from_string(btlc.consume_string()); + signed_bt_dict = btlc.consume_string(); + } + catch (...) + { + log::critical(llarp_cat, "Error: RouterContact failed to populate bt encoded contents!"); + } + } + std::string RouterContact::bt_encode() const { @@ -94,7 +109,6 @@ namespace llarp try { - btlp.append(1); btlp.append(signature.ToView()); btlp.append(signed_bt_dict); } @@ -104,16 +118,11 @@ namespace llarp } return std::move(btlp).str(); - - // NOTE: Confirm that we are cutting checks for version == 0 - // if (version == 0) - // return BEncodeSignedSection(buf); } void RouterContact::bt_encode_subdict(oxenc::bt_list_producer& btlp) const { - btlp.append("1"); btlp.append(signature.ToView()); btlp.append(signed_bt_dict); } @@ -441,30 +450,13 @@ namespace llarp bool RouterContact::VerifySignature() const { - if (version == 0) - { - RouterContact copy; - copy = *this; - copy.signature.Zero(); - std::array tmp; - llarp_buffer_t buf(tmp); - - auto bte = copy.bt_encode(); - return CryptoManager::instance()->verify( - pubkey, reinterpret_cast(bte.data()), bte.size(), signature); - } - /* else */ - if (version == 1) - { - llarp_buffer_t buf{signed_bt_dict}; - return CryptoManager::instance()->verify( - pubkey, - reinterpret_cast(const_cast(signed_bt_dict.data())), - signed_bt_dict.size(), - signature); - } + RouterContact copy; + copy = *this; + copy.signature.Zero(); - return false; + auto bte = copy.bt_encode(); + return CryptoManager::instance()->verify( + pubkey, reinterpret_cast(bte.data()), bte.size(), signature); } static constexpr std::array obsolete_bootstraps = { diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index 765268328f..8079cd7798 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -75,6 +75,8 @@ namespace llarp Clear(); } + RouterContact(std::string buf); + // advertised addresses oxen::quic::Address addr; // network identifier diff --git a/llarp/service/async_key_exchange.cpp b/llarp/service/async_key_exchange.cpp index 9723fe2927..38e5bbd5d6 100644 --- a/llarp/service/async_key_exchange.cpp +++ b/llarp/service/async_key_exchange.cpp @@ -1,4 +1,5 @@ #include "async_key_exchange.hpp" +#include "endpoint.hpp" #include #include @@ -13,7 +14,7 @@ namespace llarp::service const Identity& localident, const PQPubKey& introsetPubKey, const Introduction& remote, - IDataHandler* h, + Endpoint* h, const ConvoTag& t, ProtocolType proto) : loop(std::move(l)) @@ -44,9 +45,9 @@ namespace llarp::service std::shared_ptr self, std::shared_ptr frame) { // derive ntru session key component - SharedSecret K; + SharedSecret secret; auto crypto = CryptoManager::instance(); - crypto->pqe_encrypt(frame->cipher, K, self->introPubKey); + crypto->pqe_encrypt(frame->cipher, secret, self->introPubKey); // randomize Nonce frame->nonce.Randomize(); // compure post handshake session key @@ -57,12 +58,11 @@ namespace llarp::service { LogError("failed to derive x25519 shared key component"); } - std::array tmp = {{0}}; - // K - std::copy(K.begin(), K.end(), tmp.begin()); + + auto buf = secret.bt_encode() + sharedSecret.bt_encode(); // H (K + PKE(A, B, N)) - std::copy(sharedSecret.begin(), sharedSecret.end(), tmp.begin() + 32); - crypto->shorthash(self->sharedKey, llarp_buffer_t(tmp)); + crypto->shorthash(self->sharedKey, reinterpret_cast(buf.data()), buf.size()); + // set tag self->msg.tag = self->tag; // set sender @@ -70,7 +70,7 @@ namespace llarp::service // set version self->msg.version = llarp::constants::proto_version; // encrypt and sign - if (frame->EncryptAndSign(self->msg, K, self->m_LocalIdentity)) + if (frame->EncryptAndSign(self->msg, secret, self->m_LocalIdentity)) self->loop->call([self, frame] { AsyncKeyExchange::Result(self, frame); }); else { diff --git a/llarp/service/async_key_exchange.hpp b/llarp/service/async_key_exchange.hpp index be260c7f4b..108046563d 100644 --- a/llarp/service/async_key_exchange.hpp +++ b/llarp/service/async_key_exchange.hpp @@ -17,7 +17,7 @@ namespace llarp::service const PQPubKey introPubKey; Introduction remoteIntro; std::function)> hook; - IDataHandler* handler; + Endpoint* handler; ConvoTag tag; AsyncKeyExchange( @@ -26,7 +26,7 @@ namespace llarp::service const Identity& localident, const PQPubKey& introsetPubKey, const Introduction& remote, - IDataHandler* h, + Endpoint* h, const ConvoTag& t, ProtocolType proto); diff --git a/llarp/service/auth.hpp b/llarp/service/auth.hpp index f357ca86b8..fea367594d 100644 --- a/llarp/service/auth.hpp +++ b/llarp/service/auth.hpp @@ -3,9 +3,13 @@ #include #include #include "address.hpp" -#include "handler.hpp" #include +namespace llarp +{ + struct Router; +} + namespace llarp::service { /// authentication status code @@ -38,6 +42,9 @@ namespace llarp::service std::string reason; }; + struct ProtocolMessage; + struct ConvoTag; + /// maybe get auth result from string std::optional ParseAuthResultCode(std::string data); diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 5194424569..f02266babc 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -55,8 +55,8 @@ namespace llarp , _introset_lookup_filter{5s} { _state = std::make_unique(); - _state->m_Router = r; - _state->m_Name = "endpoint"; + _state->router = r; + _state->name = "endpoint"; _recv_event_queue.enable(); if (Loop()->MaybeGetUVWLoop()) @@ -94,13 +94,13 @@ namespace llarp bool Endpoint::HasPendingPathToService(const Address& addr) const { - return _state->m_PendingServiceLookups.find(addr) != _state->m_PendingServiceLookups.end(); + return _state->pending_service_lookups.find(addr) != _state->pending_service_lookups.end(); } bool Endpoint::is_ready() const { - const auto now = Now(); + const auto now = llarp::time_now_ms(); if (intro_set().intros.empty()) return false; if (intro_set().IsExpired(now)) @@ -111,7 +111,7 @@ namespace llarp bool Endpoint::HasPendingRouterLookup(const RouterID remote) const { - const auto& routers = _state->m_PendingRouters; + const auto& routers = _state->pending_routers; return routers.find(remote) != routers.end(); } @@ -124,7 +124,7 @@ namespace llarp return itr->second.remote.Addr(); } - for (const auto& item : _state->m_SNodeSessions) + for (const auto& item : _state->snode_sessions) { if (const auto maybe = item.second->CurrentPath()) { @@ -155,7 +155,7 @@ namespace llarp auth = AuthInfo{token}, ranges, result_handler, - poker = m_router->route_poker()](auto maybe_addr) { + poker = router()->route_poker()](auto maybe_addr) { if (not maybe_addr) { result_handler(false, "exit not found: {}"_format(name)); @@ -214,7 +214,7 @@ namespace llarp auto handleGotPathToService = [resultHandler, service, this](auto addr) { // we can probably get this info before we have a path to them but we do this after we // have a path so when we send the response back they can send shit to them immediately - const auto& container = _state->m_RemoteSessions; + const auto& container = _state->remote_sessions; if (auto itr = container.find(addr); itr != container.end()) { // parse the stuff we need from this guy @@ -290,7 +290,7 @@ namespace llarp bool Endpoint::IntrosetIsStale() const { - return intro_set().HasExpiredIntros(Now()); + return intro_set().HasExpiredIntros(llarp::time_now_ms()); } util::StatusObject @@ -326,17 +326,15 @@ namespace llarp // expire name cache _state->nameCache.Decay(now); // expire snode sessions - EndpointUtil::ExpireSNodeSessions(now, _state->m_SNodeSessions); - // expire pending tx - EndpointUtil::ExpirePendingTx(now, _state->m_PendingLookups); + EndpointUtil::ExpireSNodeSessions(now, _state->snode_sessions); // expire pending router lookups - EndpointUtil::ExpirePendingRouterLookups(now, _state->m_PendingRouters); + EndpointUtil::ExpirePendingRouterLookups(now, _state->pending_routers); // deregister dead sessions - EndpointUtil::DeregisterDeadSessions(now, _state->m_DeadSessions); + EndpointUtil::DeregisterDeadSessions(now, _state->dead_sessions); // tick remote sessions EndpointUtil::TickRemoteSessions( - now, _state->m_RemoteSessions, _state->m_DeadSessions, Sessions()); + now, _state->remote_sessions, _state->dead_sessions, Sessions()); // expire convotags EndpointUtil::ExpireConvoSessions(now, Sessions()); @@ -370,10 +368,10 @@ namespace llarp { // stop remote sessions log::debug(logcat, "Endpoint stopping remote sessions."); - EndpointUtil::StopRemoteSessions(_state->m_RemoteSessions); + EndpointUtil::StopRemoteSessions(_state->remote_sessions); // stop snode sessions log::debug(logcat, "Endpoint stopping snode sessions."); - EndpointUtil::StopSnodeSessions(_state->m_SNodeSessions); + EndpointUtil::StopSnodeSessions(_state->snode_sessions); log::debug(logcat, "Endpoint stopping its path builder."); return path::Builder::Stop(); } @@ -381,23 +379,13 @@ namespace llarp uint64_t Endpoint::GenTXID() { - uint64_t txid = randint(); - const auto& lookups = _state->m_PendingLookups; - while (lookups.find(txid) != lookups.end()) - ++txid; - return txid; + return randint(); } std::string Endpoint::Name() const { - return _state->m_Name + ":" + _identity.pub.Name(); - } - - void - Endpoint::PutLookup(IServiceLookup* lookup, uint64_t txid) - { - _state->m_PendingLookups.emplace(txid, std::unique_ptr(lookup)); + return _state->name + ":" + _identity.pub.Name(); } bool @@ -413,7 +401,7 @@ namespace llarp } remote.insert(introset); } - auto& lookups = _state->m_PendingLookups; + auto& lookups = _state->pending_lookups; auto itr = lookups.find(msg->txid); if (itr == lookups.end()) { @@ -588,7 +576,7 @@ namespace llarp bool Endpoint::LoadKeyFile() { - const auto& keyfile = _state->m_Keyfile; + const auto& keyfile = _state->key_file; if (!keyfile.empty()) { _identity.EnsureKeys(keyfile, router()->key_manager()->needBackup()); @@ -603,16 +591,11 @@ namespace llarp bool Endpoint::Start() { - // how can I tell if a m_Identity isn't loaded? - if (!_data_handler) - { - _data_handler = this; - } // this does network isolation - while (_state->m_OnInit.size()) + while (_state->on_init_callbacks.size()) { - if (_state->m_OnInit.front()()) - _state->m_OnInit.pop_front(); + if (_state->on_init_callbacks.front()()) + _state->on_init_callbacks.pop_front(); else { LogWarn("Can't call init of network isolation"); @@ -665,7 +648,7 @@ namespace llarp } // exit related stuffo - if (_state->m_ExitEnabled) + if (_state->is_exit_enabled) { intro_set().supported_protocols.push_back(ProtocolType::Exit); intro_set().exit_policy = GetExitPolicy(); @@ -698,7 +681,7 @@ namespace llarp LogWarn("failed to generate introset for endpoint ", Name()); return; } - if (PublishIntroSet(*maybe)) + if (publish_introset(*maybe)) { LogInfo("(re)publishing introset for endpoint ", Name()); } @@ -709,10 +692,8 @@ namespace llarp } bool - Endpoint::PublishIntroSet(const EncryptedIntroSet& introset) + Endpoint::publish_introset(const EncryptedIntroSet& introset) { - auto* r = router(); - const auto paths = GetManyPathsWithUniqueEndpoints( this, INTROSET_RELAY_REDUNDANCY, dht::Key_t{introset.derivedSigningKey.as_array()}); @@ -730,92 +711,21 @@ namespace llarp { for (size_t i = 0; i < INTROSET_REQS_PER_RELAY; ++i) { - r->notify_router_event( - r->pubkey(), - llarp::dht::Key_t{introset.derivedSigningKey.as_array()}, - RouterID(path->hops[path->hops.size() - 1].rc.pubkey)); - - m_router->send_control_message(path->Upstream(), "publish_intro", introset.bt_encode()); + router()->send_control_message(path->Upstream(), "publish_intro", introset.bt_encode()); } } - return true; - } - - struct PublishIntroSetJob : public IServiceLookup - { - EncryptedIntroSet m_IntroSet; - Endpoint* m_Endpoint; - uint64_t m_relayOrder; - PublishIntroSetJob( - Endpoint* parent, - uint64_t id, - EncryptedIntroSet introset, - uint64_t relayOrder, - llarp_time_t timeout) - : IServiceLookup(parent, id, "PublishIntroSet", timeout) - , m_IntroSet(std::move(introset)) - , m_Endpoint(parent) - , m_relayOrder(relayOrder) - {} - - std::shared_ptr - BuildRequestMessage() - { - auto msg = std::make_shared(); - msg->dht_msgs.emplace_back( - std::make_unique(m_IntroSet, txid, true, m_relayOrder)); - return msg; - } - bool - HandleIntrosetResponse(const std::set& response) - { - if (not response.empty()) - m_Endpoint->IntroSetPublished(); - else - m_Endpoint->IntroSetPublishFail(); - - return true; - } - }; - - void - Endpoint::IntroSetPublishFail() - { - auto now = Now(); - if (ShouldPublishDescriptors(now)) - { - regen_and_publish_introset(); - } - else if (NumInStatus(path::ePathEstablished) < 3) - { - if (intro_set().HasExpiredIntros(now)) - ManualRebuild(1); - } + return true; } size_t Endpoint::UniqueEndpoints() const { - return _state->m_RemoteSessions.size() + _state->m_SNodeSessions.size(); + return _state->remote_sessions.size() + _state->snode_sessions.size(); } constexpr auto PublishIntrosetTimeout = 20s; - bool - Endpoint::PublishIntroSetVia( - const EncryptedIntroSet& introset, Router* r, path::Path_ptr path, uint64_t relayOrder) - { - auto job = - new PublishIntroSetJob(this, GenTXID(), introset, relayOrder, PublishIntrosetTimeout); - if (job->SendRequestViaPath(path, r)) - { - _state->m_LastPublishAttempt = Now(); - return true; - } - return false; - } - void Endpoint::ResetInternalState() { @@ -825,8 +735,8 @@ namespace llarp getter(item)->ResetInternalState(); }); }; - resetState(_state->m_RemoteSessions, [](const auto& item) { return item.second; }); - resetState(_state->m_SNodeSessions, [](const auto& item) { return item.second; }); + resetState(_state->remote_sessions, [](const auto& item) { return item.second; }); + resetState(_state->snode_sessions, [](const auto& item) { return item.second; }); } bool @@ -835,37 +745,22 @@ namespace llarp if (not _publish_introset) return false; - const auto lastEventAt = std::max(_state->m_LastPublishAttempt, _state->m_LastPublish); + const auto lastEventAt = std::max(_state->last_publish_attempt, _state->last_publish); const auto next_pub = lastEventAt - + (_state->m_IntroSet.HasStaleIntros(now, path::INTRO_STALE_THRESHOLD) + + (_state->local_introset.HasStaleIntros(now, path::INTRO_STALE_THRESHOLD) ? IntrosetPublishRetryCooldown : IntrosetPublishInterval); return now >= next_pub; } - void - Endpoint::IntroSetPublished() - { - const auto now = Now(); - // We usually get 4 confirmations back (one for each DHT location), which - // is noisy: suppress this log message if we already had a confirmation in - // the last second. - if (_state->m_LastPublish < now - 1s) - LogInfo(Name(), " IntroSet publish confirmed"); - else - LogDebug(Name(), " Additional IntroSet publish confirmed"); - - _state->m_LastPublish = now; - } - std::optional> Endpoint::GetHopsForBuild() { std::unordered_set exclude; ForEachPath([&exclude](auto path) { exclude.insert(path->Endpoint()); }); const auto maybe = - m_router->node_db()->GetRandom([exclude, r = m_router](const auto& rc) -> bool { + router()->node_db()->GetRandom([exclude, r = router()](const auto& rc) -> bool { return exclude.count(rc.pubkey) == 0 and not r->router_profiling().IsBadForPath(rc.pubkey); }); @@ -893,7 +788,7 @@ namespace llarp { const Address addr{introset.address_keys.Addr()}; - auto& remoteSessions = _state->m_RemoteSessions; + auto& remoteSessions = _state->remote_sessions; if (remoteSessions.count(addr) < MaxOutboundContextPerRemote) { @@ -912,7 +807,7 @@ namespace llarp void Endpoint::HandleVerifyGotRouter(dht::GotRouterMessage_constptr msg, RouterID id, bool valid) { - auto& pendingRouters = _state->m_PendingRouters; + auto& pendingRouters = _state->pending_routers; auto itr = pendingRouters.find(id); if (itr != pendingRouters.end()) { @@ -942,7 +837,7 @@ namespace llarp } else { - auto& routers = _state->m_PendingRouters; + auto& routers = _state->pending_routers; auto itr = routers.begin(); while (itr != routers.end()) { @@ -958,45 +853,6 @@ namespace llarp return true; } - struct LookupNameJob : public IServiceLookup - { - std::function)> handler; - ShortHash namehash; - - LookupNameJob( - Endpoint* parent, - uint64_t id, - std::string lnsName, - std::function)> resultHandler) - : IServiceLookup(parent, id, lnsName), handler(resultHandler) - { - CryptoManager::instance()->shorthash( - namehash, reinterpret_cast(lnsName.data()), lnsName.size()); - } - - std::shared_ptr - BuildRequestMessage() override - { - auto msg = std::make_shared(); - msg->dht_msgs.emplace_back(std::make_unique( - dht::Key_t{}, dht::Key_t{namehash.as_array()}, txid)); - return msg; - } - - bool - HandleNameResponse(std::optional
addr) override - { - handler(addr); - return true; - } - - void - HandleTimeout() override - { - HandleNameResponse(std::nullopt); - } - }; - bool Endpoint::HasExit() const { @@ -1099,14 +955,14 @@ namespace llarp { LogInfo(Name(), " lookup ", name, " from ", path->Endpoint()); auto job = new LookupNameJob{this, GenTXID(), name, resultHandler}; - job->SendRequestViaPath(path, m_router); + job->SendRequestViaPath(path, router); } } bool Endpoint::HandleGotNameMessage(std::shared_ptr msg) { - auto& lookups = _state->m_PendingLookups; + auto& lookups = _state->pending_lookups; auto itr = lookups.find(msg->TxID); if (itr == lookups.end()) return false; @@ -1135,7 +991,7 @@ namespace llarp { using llarp::dht::FindRouterMessage; - auto& routers = _state->m_PendingRouters; + auto& routers = _state->pending_routers; if (routers.find(rid) == routers.end()) { auto path = GetEstablishedPathClosestTo(rid); @@ -1146,7 +1002,7 @@ namespace llarp msg.sequence_number = path->NextSeqNo(); if (path && path->SendRoutingMessage(msg, router())) { - RouterLookupJob job{this, [handler, rid, nodedb = m_router->node_db()](auto results) { + RouterLookupJob job{this, [handler, rid, nodedb = router()->node_db()](auto results) { if (results.empty()) { LogInfo("could not find ", rid, ", remove it from nodedb"); @@ -1160,8 +1016,6 @@ namespace llarp auto dhtMsg = dynamic_cast(msg.dht_msgs[0].get()); assert(dhtMsg != nullptr); - m_router->notify_router_event(router()->pubkey(), *dhtMsg); - routers.emplace(rid, std::move(job)); return true; } @@ -1227,7 +1081,7 @@ namespace llarp bool Endpoint::HasPathToSNode(const RouterID ident) const { - auto range = _state->m_SNodeSessions.equal_range(ident); + auto range = _state->snode_sessions.equal_range(ident); auto itr = range.first; while (itr != range.second) { @@ -1261,7 +1115,7 @@ namespace llarp { remote.insert(item.second.remote.Addr()); } - for (const auto& item : _state->m_SNodeSessions) + for (const auto& item : _state->snode_sessions) { remote.insert(item.first); } @@ -1272,7 +1126,7 @@ namespace llarp Endpoint::ProcessDataMessage(std::shared_ptr msg) { if ((msg->proto == ProtocolType::Exit - && (_state->m_ExitEnabled || _exit_map.ContainsValue(msg->sender.Addr()))) + && (_state->is_exit_enabled || _exit_map.ContainsValue(msg->sender.Addr()))) || msg->proto == ProtocolType::TrafficV4 || msg->proto == ProtocolType::TrafficV6 || (msg->proto == ProtocolType::QUIC and _tunnel_manager)) { @@ -1312,7 +1166,7 @@ namespace llarp path::Path_ptr path, PathID_t replyPath, ConvoTag tag, AuthResult result) { // not applicable because we are not an exit or don't have an endpoint auth policy - if ((not _state->m_ExitEnabled) or _auth_policy == nullptr) + if ((not _state->is_exit_enabled) or _auth_policy == nullptr) return; ProtocolFrameMessage f{}; f.flag = AuthResultCodeAsInt(result.code); @@ -1359,7 +1213,7 @@ namespace llarp } } _send_queue.tryPushBack( - SendEvent_t{std::make_shared(f, replyPath), path}); + SendEvent{std::make_shared(f, replyPath), path}); } void @@ -1381,7 +1235,7 @@ namespace llarp LogWarn("invalidating convotag T=", tag); RemoveConvoTag(tag); _send_queue.tryPushBack( - SendEvent_t{std::make_shared(f, from), p}); + SendEvent{std::make_shared(f, from), p}); } } @@ -1412,7 +1266,7 @@ namespace llarp void Endpoint::HandlePathDied(path::Path_ptr p) { - m_router->router_profiling().MarkPathTimeout(p.get()); + router()->router_profiling().MarkPathTimeout(p.get()); ManualRebuild(1); path::Builder::HandlePathDied(p); regen_and_publish_introset(); @@ -1435,10 +1289,10 @@ namespace llarp // tell all our existing remote sessions about this introset update const auto now = router()->now(); - auto& lookups = _state->m_PendingServiceLookups; + auto& lookups = _state->pending_service_lookups; if (introset) { - auto& sessions = _state->m_RemoteSessions; + auto& sessions = _state->remote_sessions; auto range = sessions.equal_range(addr); auto itr = range.first; while (itr != range.second) @@ -1460,7 +1314,7 @@ namespace llarp ++itr; } } - auto& fails = _state->m_ServiceLookupFails; + auto& fails = _state->service_lookup_fails; if (not introset or introset->IsExpired(now)) { LogError( @@ -1474,8 +1328,8 @@ namespace llarp fails[endpoint] = fails[endpoint] + 1; const auto pendingForAddr = std::count_if( - _state->m_PendingLookups.begin(), - _state->m_PendingLookups.end(), + _state->pending_lookups.begin(), + _state->pending_lookups.end(), [addr](const auto& item) -> bool { return item.second->IsFor(addr); }); // inform all if we have no more pending lookups for this address @@ -1493,7 +1347,7 @@ namespace llarp } // check for established outbound context - if (_state->m_RemoteSessions.count(addr) > 0) + if (_state->remote_sessions.count(addr) > 0) return true; PutNewOutboundContext(*introset, timeLeft); @@ -1516,7 +1370,7 @@ namespace llarp void Endpoint::InformPathToService(const Address remote, OutboundContext* ctx) { - auto& serviceLookups = _state->m_PendingServiceLookups; + auto& serviceLookups = _state->pending_service_lookups; auto range = serviceLookups.equal_range(remote); auto itr = range.first; while (itr != range.second) @@ -1528,7 +1382,8 @@ namespace llarp } bool - Endpoint::EnsurePathToService(const Address remote, PathEnsureHook hook, llarp_time_t timeout) + Endpoint::EnsurePathToService( + const Address remote, PathEnsureHook hook, [[maybe_unused]] llarp_time_t timeout) { if (not WantsOutboundSession(remote)) { @@ -1544,9 +1399,9 @@ namespace llarp static constexpr size_t RequestsPerLookup = 2; // add response hook to list for address. - _state->m_PendingServiceLookups.emplace(remote, hook); + _state->pending_service_lookups.emplace(remote, hook); - auto& sessions = _state->m_RemoteSessions; + auto& sessions = _state->remote_sessions; { auto range = sessions.equal_range(remote); auto itr = range.first; @@ -1624,7 +1479,7 @@ namespace llarp bool Endpoint::EnsurePathToSNode(const RouterID snode, SNodeEnsureHook h) { - auto& nodeSessions = _state->m_SNodeSessions; + auto& nodeSessions = _state->snode_sessions; using namespace std::placeholders; if (nodeSessions.count(snode) == 0) @@ -1640,8 +1495,8 @@ namespace llarp return false; pkt.UpdateIPv4Address(src, dst); /// TODO: V6 - auto itr = _state->m_SNodeSessions.find(snode); - if (itr == _state->m_SNodeSessions.end()) + auto itr = _state->snode_sessions.find(snode); + if (itr == _state->snode_sessions.end()) return false; if (const auto maybe = itr->second->CurrentPath()) return HandleInboundPacket( @@ -1653,7 +1508,7 @@ namespace llarp numHops, false, this); - _state->m_SNodeSessions[snode] = session; + _state->snode_sessions[snode] = session; } EnsureRouterIsKnown(snode); auto range = nodeSessions.equal_range(snode); @@ -1698,7 +1553,7 @@ namespace llarp if (*ptr == _identity.pub.Addr()) { ConvoTagTX(tag); - _state->m_Router->TriggerPump(); + _state->router->TriggerPump(); if (not HandleInboundPacket(tag, pkt, t, 0)) return false; ConvoTagRX(tag); @@ -1713,30 +1568,12 @@ namespace llarp return false; } - bool - Endpoint::SendToOrQueue(const RouterID& addr, const llarp_buffer_t& buf, ProtocolType t) - { - LogTrace("SendToOrQueue: sending to snode ", addr); - auto pkt = std::make_shared(); - if (!pkt->Load(buf)) - return false; - EnsurePathToSNode( - addr, [this, t, pkt = std::move(pkt)](RouterID, exit::BaseSession_ptr s, ConvoTag) { - if (s) - { - s->SendPacketToRemote(pkt->ConstBuffer(), t); - router()->TriggerPump(); - } - }); - return true; - } - void Endpoint::Pump(llarp_time_t now) { FlushRecvData(); // send downstream packets to user for snode - for (const auto& [router, session] : _state->m_SNodeSessions) + for (const auto& [router, session] : _state->snode_sessions) session->FlushDownstream(); // handle inbound traffic sorted @@ -1770,19 +1607,19 @@ namespace llarp auto r = router(); // TODO: locking on this container - for (const auto& [addr, outctx] : _state->m_RemoteSessions) + for (const auto& [addr, outctx] : _state->remote_sessions) { outctx->FlushUpstream(); outctx->Pump(now); } // TODO: locking on this container - for (const auto& [r, session] : _state->m_SNodeSessions) + for (const auto& [r, session] : _state->snode_sessions) session->FlushUpstream(); // send queue flush while (not _send_queue.empty()) { - SendEvent_t item = _send_queue.popFront(); + SendEvent item = _send_queue.popFront(); item.first->sequence_number = item.second->NextSeqNo(); if (item.second->SendRoutingMessage(*item.first, r)) ConvoTagTX(item.first->protocol_frame_msg.convo_tag); @@ -1832,7 +1669,7 @@ namespace llarp } else { - auto range = _state->m_RemoteSessions.equal_range(*ptr); + auto range = _state->remote_sessions.equal_range(*ptr); auto itr = range.first; while (itr != range.second) { @@ -1853,8 +1690,8 @@ namespace llarp } if (auto* ptr = std::get_if(&remote)) { - auto itr = _state->m_SNodeSessions.find(*ptr); - if (itr == _state->m_SNodeSessions.end()) + auto itr = _state->snode_sessions.find(*ptr); + if (itr == _state->snode_sessions.end()) return std::nullopt; if (auto maybe = itr->second->CurrentPath()) return ConvoTag{maybe->as_array()}; @@ -1921,151 +1758,6 @@ namespace llarp return false; } - bool - Endpoint::SendToOrQueue(const Address& remote, const llarp_buffer_t& data, ProtocolType t) - { - LogTrace("SendToOrQueue: sending to address ", remote); - if (data.sz == 0) - { - LogTrace("SendToOrQueue: dropping because data.sz == 0"); - return false; - } - if (HasInboundConvo(remote)) - { - // inbound conversation - LogTrace("Have inbound convo"); - auto transfer = std::make_shared(); - ProtocolFrameMessage& f = transfer->protocol_frame_msg; - f.flag = 0; - std::shared_ptr p; - if (const auto maybe = GetBestConvoTagFor(remote)) - { - // the remote guy's intro - Introduction replyIntro; - SharedSecret K; - const auto tag = *maybe; - - if (not GetCachedSessionKeyFor(tag, K)) - { - LogError(Name(), " no cached key for inbound session from ", remote, " T=", tag); - return false; - } - if (not GetReplyIntroFor(tag, replyIntro)) - { - LogError(Name(), "no reply intro for inbound session from ", remote, " T=", tag); - return false; - } - // get path for intro - auto p = GetPathByRouter(replyIntro.router); - - if (not p) - { - LogWarn( - Name(), - " has no path for intro router ", - RouterID{replyIntro.router}, - " for inbound convo T=", - tag); - return false; - } - - f.convo_tag = tag; - // TODO: check expiration of our end - auto m = std::make_shared(f.convo_tag); - m->PutBuffer(data); - f.nonce.Randomize(); - f.cipher.Zero(); - f.flag = 0; - transfer->nonce.Randomize(); - m->proto = t; - m->introReply = p->intro; - m->sender = _identity.pub; - if (auto maybe = GetSeqNoForConvo(f.convo_tag)) - { - m->seqno = *maybe; - } - else - { - LogWarn(Name(), " could not set sequence number, no session T=", f.convo_tag); - return false; - } - f.sequence_number = m->seqno; - f.path_id = p->intro.path_id; - transfer->path_id = replyIntro.path_id; - router()->queue_work([transfer, p, m, K, this]() { - if (not transfer->protocol_frame_msg.EncryptAndSign(*m, K, _identity)) - { - LogError( - "failed to encrypt and sign for sessionn T=", - transfer->protocol_frame_msg.convo_tag); - return; - } - _send_queue.tryPushBack(SendEvent_t{transfer, p}); - router()->TriggerPump(); - }); - return true; - } - - LogWarn( - Name(), - " SendToOrQueue on inbound convo from ", - remote, - " but get-best returned none; bug?"); - } - if (not WantsOutboundSession(remote)) - { - LogWarn( - Name(), - " SendToOrQueue on outbound session we did not mark as outbound (remote=", - remote, - ")"); - return false; - } - - // Failed to find a suitable inbound convo, look for outbound - LogTrace("Not an inbound convo"); - auto& sessions = _state->m_RemoteSessions; - auto range = sessions.equal_range(remote); - for (auto itr = range.first; itr != range.second; ++itr) - { - if (itr->second->ReadyToSend()) - { - LogTrace("Found an outbound session to use to reach ", remote); - itr->second->AsyncEncryptAndSendTo(data, t); - return true; - } - } - LogTrace("Making an outbound session and queuing the data"); - // add pending traffic - auto& traffic = _state->m_PendingTraffic; - traffic[remote].emplace_back(data, t); - EnsurePathToService( - remote, - [this](Address addr, OutboundContext* ctx) { - if (ctx) - { - for (auto& pending : m_state->m_PendingTraffic[addr]) - { - ctx->AsyncEncryptAndSendTo(pending.Buffer(), pending.protocol); - } - } - else - { - LogWarn("no path made to ", addr); - } - _state->m_PendingTraffic.erase(addr); - }, - PathAlignmentTimeout()); - return true; - } - - bool - Endpoint::SendToOrQueue( - const std::variant& addr, const llarp_buffer_t& data, ProtocolType t) - { - return var::visit([&](auto& addr) { return SendToOrQueue(addr, data, t); }, addr); - } - bool Endpoint::HasConvoTag(const ConvoTag& t) const { @@ -2096,7 +1788,7 @@ namespace llarp Router* Endpoint::router() { - return _state->m_Router; + return _state->router; } const EventLoop_ptr& @@ -2108,34 +1800,34 @@ namespace llarp void Endpoint::BlacklistSNode(const RouterID snode) { - _state->m_SnodeBlacklist.insert(snode); + _state->snode_blacklist.insert(snode); } const std::set& Endpoint::SnodeBlacklist() const { - return _state->m_SnodeBlacklist; + return _state->snode_blacklist; } const IntroSet& Endpoint::intro_set() const { - return _state->m_IntroSet; + return _state->local_introset; } IntroSet& Endpoint::intro_set() { - return _state->m_IntroSet; + return _state->local_introset; } - const ConvoMap& + const std::unordered_map& Endpoint::Sessions() const { return _state->m_Sessions; } - ConvoMap& + std::unordered_map& Endpoint::Sessions() { return _state->m_Sessions; @@ -2177,7 +1869,7 @@ namespace llarp }); if (_exit_map.Empty()) - m_router->route_poker()->put_down(); + router()->route_poker()->put_down(); } void @@ -2194,7 +1886,7 @@ namespace llarp }); if (_exit_map.Empty()) - m_router->route_poker()->put_down(); + router()->route_poker()->put_down(); } std::optional diff --git a/llarp/service/endpoint.hpp b/llarp/service/endpoint.hpp index 60e6c841c0..8d65b0103e 100644 --- a/llarp/service/endpoint.hpp +++ b/llarp/service/endpoint.hpp @@ -10,7 +10,6 @@ // --- begin kitchen sink headers ---- #include -#include #include #include #include @@ -61,7 +60,15 @@ namespace llarp /// number of unique snodes we want to talk to do to ons lookups inline constexpr size_t MIN_ENDPOINTS_FOR_LNS_LOOKUP = 2; - struct Endpoint : public path::Builder, public IDataHandler, public EndpointBase + // TODO: delete this, it is copied from the late llarp/service/handler.hpp + struct RecvDataEvent + { + path::Path_ptr fromPath; + PathID_t pathid; + std::shared_ptr msg; + }; + + struct Endpoint : public path::Builder, public EndpointBase { Endpoint(Router* r, Context* parent); ~Endpoint() override; @@ -73,7 +80,7 @@ namespace llarp is_ready() const; void - QueueRecvData(RecvDataEvent ev) override; + QueueRecvData(RecvDataEvent ev); /// return true if our introset has expired intros bool @@ -86,9 +93,6 @@ namespace llarp virtual util::StatusObject ExtractStatus() const; - void - SetHandler(IDataHandler* h); - virtual bool Configure(const NetworkConfig& conf, const DnsConfig& dnsConf); @@ -185,11 +189,7 @@ namespace llarp } bool - PublishIntroSet(const EncryptedIntroSet& i) override; - - bool - PublishIntroSetVia( - const EncryptedIntroSet& i, Router* r, path::Path_ptr p, uint64_t relayOrder); + publish_introset(const EncryptedIntroSet& i); bool HandleGotIntroMessage(std::shared_ptr msg) override; @@ -226,7 +226,7 @@ namespace llarp bool HandleDataMessage( - path::Path_ptr path, const PathID_t from, std::shared_ptr msg) override; + path::Path_ptr path, const PathID_t from, std::shared_ptr msg); /// handle packet io from service node or hidden service to frontend virtual bool @@ -290,9 +290,6 @@ namespace llarp std::vector ranges, std::function result); - void - PutLookup(IServiceLookup* lookup, uint64_t txid); - void HandlePathBuilt(path::Path_ptr path) override; @@ -308,7 +305,7 @@ namespace llarp RemoveAllConvoTagsFor(service::Address remote); bool - WantsOutboundSession(const Address&) const override; + WantsOutboundSession(const Address&) const; /// this MUST be called if you want to call EnsurePathTo on the given address void MarkAddressOutbound(AddressVariant_t) override; @@ -327,7 +324,7 @@ namespace llarp GetEndpointWithConvoTag(ConvoTag t) const override; bool - HasConvoTag(const ConvoTag& t) const override; + HasConvoTag(const ConvoTag& t) const; bool ShouldBuildMore(llarp_time_t now) const override; @@ -379,45 +376,46 @@ namespace llarp HasFlowToService(const Address remote) const; void - PutSenderFor(const ConvoTag& tag, const ServiceInfo& info, bool inbound) override; + PutSenderFor(const ConvoTag& tag, const ServiceInfo& info, bool inbound); bool - HasInboundConvo(const Address& addr) const override; + HasInboundConvo(const Address& addr) const; bool - HasOutboundConvo(const Address& addr) const override; + HasOutboundConvo(const Address& addr) const; bool - GetCachedSessionKeyFor(const ConvoTag& remote, SharedSecret& secret) const override; + GetCachedSessionKeyFor(const ConvoTag& remote, SharedSecret& secret) const; + void - PutCachedSessionKeyFor(const ConvoTag& remote, const SharedSecret& secret) override; + PutCachedSessionKeyFor(const ConvoTag& remote, const SharedSecret& secret); bool - GetSenderFor(const ConvoTag& remote, ServiceInfo& si) const override; + GetSenderFor(const ConvoTag& remote, ServiceInfo& si) const; void - PutIntroFor(const ConvoTag& remote, const Introduction& intro) override; + PutIntroFor(const ConvoTag& remote, const Introduction& intro); bool - GetIntroFor(const ConvoTag& remote, Introduction& intro) const override; + GetIntroFor(const ConvoTag& remote, Introduction& intro) const; void - RemoveConvoTag(const ConvoTag& remote) override; + RemoveConvoTag(const ConvoTag& remote); void - ConvoTagTX(const ConvoTag& remote) override; + ConvoTagTX(const ConvoTag& remote); void - ConvoTagRX(const ConvoTag& remote) override; + ConvoTagRX(const ConvoTag& remote); void - PutReplyIntroFor(const ConvoTag& remote, const Introduction& intro) override; + PutReplyIntroFor(const ConvoTag& remote, const Introduction& intro); bool - GetReplyIntroFor(const ConvoTag& remote, Introduction& intro) const override; + GetReplyIntroFor(const ConvoTag& remote, Introduction& intro) const; bool - GetConvoTagsForService(const Address& si, std::set& tag) const override; + GetConvoTagsForService(const Address& si, std::set& tag) const; void PutNewOutboundContext(const IntroSet& introset, llarp_time_t timeLeftToAlign); @@ -441,11 +439,6 @@ namespace llarp void PathBuildStarted(path::Path_ptr path) override; - virtual void - IntroSetPublishFail(); - virtual void - IntroSetPublished(); - void AsyncProcessAuthMessage( std::shared_ptr msg, std::function hook); @@ -467,21 +460,6 @@ namespace llarp bool SendToOrQueue(ConvoTag tag, const llarp_buffer_t& payload, ProtocolType t) override; - // Send a to (or queues for sending) to either an address or router id - bool - SendToOrQueue( - const std::variant& addr, - const llarp_buffer_t& payload, - ProtocolType t); - - // Sends to (or queues for sending) to a remote client - bool - SendToOrQueue(const Address& addr, const llarp_buffer_t& payload, ProtocolType t); - - // Sends to (or queues for sending) to a router - bool - SendToOrQueue(const RouterID& addr, const llarp_buffer_t& payload, ProtocolType t); - std::optional MaybeGetAuthInfoForEndpoint(service::Address addr); @@ -545,7 +523,6 @@ namespace llarp path::Path::UniqueEndpointSet_t GetUniqueEndpointsForLookup() const; - IDataHandler* _data_handler = nullptr; Identity _identity; net::IPRangeMap _exit_map; bool _publish_introset = true; @@ -561,7 +538,7 @@ namespace llarp RecvPacketQueue_t _inbound_queue; public: - SendMessageQueue_t _send_queue; + SendMessageEventQueue _send_queue; private: llarp_time_t _last_introset_regen_attempt = 0s; @@ -576,9 +553,8 @@ namespace llarp const IntroSet& intro_set() const; IntroSet& intro_set(); - using ConvoMap = std::unordered_map; - const ConvoMap& Sessions() const; - ConvoMap& Sessions(); + const std::unordered_map& Sessions() const; + std::unordered_map& Sessions(); // clang-format on thread::Queue _recv_event_queue; diff --git a/llarp/service/endpoint_state.cpp b/llarp/service/endpoint_state.cpp index 95f013a275..0e5eb3b7cc 100644 --- a/llarp/service/endpoint_state.cpp +++ b/llarp/service/endpoint_state.cpp @@ -13,13 +13,13 @@ namespace llarp EndpointState::Configure(const NetworkConfig& conf) { if (conf.m_keyfile.has_value()) - m_Keyfile = conf.m_keyfile->string(); - m_SnodeBlacklist = conf.m_snodeBlacklist; - m_ExitEnabled = conf.m_AllowExit; + key_file = conf.m_keyfile->string(); + snode_blacklist = conf.m_snodeBlacklist; + is_exit_enabled = conf.m_AllowExit; for (const auto& record : conf.m_SRVRecords) { - m_IntroSet.SRVs.push_back(record.toTuple()); + local_introset.SRVs.push_back(record.toTuple()); } return true; @@ -28,32 +28,32 @@ namespace llarp util::StatusObject EndpointState::ExtractStatus(util::StatusObject& obj) const { - obj["lastPublished"] = to_json(m_LastPublish); - obj["lastPublishAttempt"] = to_json(m_LastPublishAttempt); - obj["introset"] = m_IntroSet.ExtractStatus(); + obj["lastPublished"] = to_json(last_publish); + obj["lastPublishAttempt"] = to_json(last_publish_attempt); + obj["introset"] = local_introset.ExtractStatus(); static auto getSecond = [](const auto& item) -> auto { return item.second->ExtractStatus(); }; std::transform( - m_DeadSessions.begin(), - m_DeadSessions.end(), + dead_sessions.begin(), + dead_sessions.end(), std::back_inserter(obj["deadSessions"]), getSecond); std::transform( - m_RemoteSessions.begin(), - m_RemoteSessions.end(), + remote_sessions.begin(), + remote_sessions.end(), std::back_inserter(obj["remoteSessions"]), getSecond); std::transform( - m_PendingLookups.begin(), - m_PendingLookups.end(), + pending_lookups.begin(), + pending_lookups.end(), std::back_inserter(obj["lookups"]), getSecond); std::transform( - m_SNodeSessions.begin(), - m_SNodeSessions.end(), + snode_sessions.begin(), + snode_sessions.end(), std::back_inserter(obj["snodeSessions"]), [](const auto& item) { return item.second->ExtractStatus(); }); diff --git a/llarp/service/endpoint_state.hpp b/llarp/service/endpoint_state.hpp index 4764effbbb..b774e63d77 100644 --- a/llarp/service/endpoint_state.hpp +++ b/llarp/service/endpoint_state.hpp @@ -18,60 +18,55 @@ #include -namespace llarp +namespace llarp::service { - namespace service + struct EndpointState { - struct EndpointState - { - std::set m_SnodeBlacklist; + std::set snode_blacklist; - Router* m_Router; - std::string m_Keyfile; - std::string m_Name; - std::string m_NetNS; - bool m_ExitEnabled = false; + Router* router; + std::string key_file; + std::string name; + std::string net_NS; + bool is_exit_enabled = false; - PendingTraffic m_PendingTraffic; + PendingTrafficMap pending_traffic; - Sessions m_RemoteSessions; - Sessions m_DeadSessions; + ConnectionMap remote_sessions; + ConnectionMap dead_sessions; - std::set m_InboundConvos; + std::set inbound_convotags; - SNodeSessions m_SNodeSessions; + SNodeConnectionMap snode_sessions; - std::unordered_multimap m_PendingServiceLookups; - std::unordered_map m_LastServiceLookupTimes; + std::unordered_multimap pending_service_lookups; + std::unordered_map last_service_lookup_time; - std::unordered_map m_ServiceLookupFails; + std::unordered_map service_lookup_fails; - PendingRouters m_PendingRouters; + PendingRoutersMap pending_routers; - llarp_time_t m_LastPublish = 0s; - llarp_time_t m_LastPublishAttempt = 0s; - /// our introset - IntroSet m_IntroSet; - /// pending remote service lookups by id - PendingLookups m_PendingLookups; - /// on initialize functions - std::list> m_OnInit; + llarp_time_t last_publish = 0s; + llarp_time_t last_publish_attempt = 0s; + /// our introset + IntroSet local_introset; + /// on initialize functions + std::list> on_init_callbacks; - /// conversations - ConvoMap m_Sessions; + /// conversations + std::unordered_map m_Sessions; - OutboundSessions_t m_OutboundSessions; + std::unordered_set
m_OutboundSessions; - util::DecayingHashTable, std::hash> - nameCache; + util::DecayingHashTable, std::hash> + nameCache; - LNSLookupTracker lnsTracker; + LNSLookupTracker lnsTracker; - bool - Configure(const NetworkConfig& conf); + bool + Configure(const NetworkConfig& conf); - util::StatusObject - ExtractStatus(util::StatusObject& obj) const; - }; - } // namespace service -} // namespace llarp + util::StatusObject + ExtractStatus(util::StatusObject& obj) const; + }; +} // namespace llarp::service diff --git a/llarp/service/endpoint_types.hpp b/llarp/service/endpoint_types.hpp index 1647c3002f..2999344744 100644 --- a/llarp/service/endpoint_types.hpp +++ b/llarp/service/endpoint_types.hpp @@ -26,31 +26,28 @@ namespace llarp using Msg_ptr = std::shared_ptr; - using SendEvent_t = std::pair; - using SendMessageQueue_t = thread::Queue; + using SendEvent = std::pair; + using SendMessageEventQueue = thread::Queue; - using PendingBufferQueue = std::deque; - using PendingTraffic = std::unordered_map; + using PendingBufferDeque = std::deque; + using PendingTrafficMap = std::unordered_map; using ProtocolMessagePtr = std::shared_ptr; using RecvPacketQueue_t = thread::Queue; - using PendingRouters = std::unordered_map; + using PendingRoutersMap = std::unordered_map; - using PendingLookups = std::unordered_map>; + using PendingLookupsMap = std::unordered_map>; - using Sessions = std::unordered_multimap>; + using ConnectionMap = std::unordered_multimap>; - using SNodeSessions = std::unordered_map>; + using SNodeConnectionMap = std::unordered_map>; using ConvoMap = std::unordered_map; - /// set of outbound addresses to maintain to - using OutboundSessions_t = std::unordered_set
; + using EnsurePathCallback = std::function; - using PathEnsureHook = std::function; - - using LNSNameCache = std::unordered_map>; + using ONSNameCache = std::unordered_map>; } // namespace service } // namespace llarp diff --git a/llarp/service/endpoint_util.cpp b/llarp/service/endpoint_util.cpp index 06dec211f1..22a2929390 100644 --- a/llarp/service/endpoint_util.cpp +++ b/llarp/service/endpoint_util.cpp @@ -10,7 +10,7 @@ namespace llarp namespace service { void - EndpointUtil::ExpireSNodeSessions(llarp_time_t now, SNodeSessions& sessions) + EndpointUtil::ExpireSNodeSessions(llarp_time_t now, SNodeConnectionMap& sessions) { auto itr = sessions.begin(); while (itr != sessions.end()) @@ -35,7 +35,7 @@ namespace llarp } void - EndpointUtil::ExpirePendingTx(llarp_time_t now, PendingLookups& lookups) + EndpointUtil::ExpirePendingTx(llarp_time_t now, PendingLookupsMap& lookups) { std::vector> timedout; for (auto itr = lookups.begin(); itr != lookups.end();) @@ -57,7 +57,7 @@ namespace llarp } void - EndpointUtil::ExpirePendingRouterLookups(llarp_time_t now, PendingRouters& routers) + EndpointUtil::ExpirePendingRouterLookups(llarp_time_t now, PendingRoutersMap& routers) { for (auto itr = routers.begin(); itr != routers.end();) { @@ -73,7 +73,7 @@ namespace llarp } void - EndpointUtil::DeregisterDeadSessions(llarp_time_t now, Sessions& sessions) + EndpointUtil::DeregisterDeadSessions(llarp_time_t now, ConnectionMap& sessions) { auto itr = sessions.begin(); while (itr != sessions.end()) @@ -91,7 +91,10 @@ namespace llarp void EndpointUtil::TickRemoteSessions( - llarp_time_t now, Sessions& remoteSessions, Sessions& deadSessions, ConvoMap& sessions) + llarp_time_t now, + ConnectionMap& remoteSessions, + ConnectionMap& deadSessions, + std::unordered_map& sessions) { auto itr = remoteSessions.begin(); while (itr != remoteSessions.end()) @@ -121,7 +124,8 @@ namespace llarp } void - EndpointUtil::ExpireConvoSessions(llarp_time_t now, ConvoMap& sessions) + EndpointUtil::ExpireConvoSessions( + llarp_time_t now, std::unordered_map& sessions) { auto itr = sessions.begin(); while (itr != sessions.end()) @@ -137,7 +141,7 @@ namespace llarp } void - EndpointUtil::StopRemoteSessions(Sessions& remoteSessions) + EndpointUtil::StopRemoteSessions(ConnectionMap& remoteSessions) { for (auto& item : remoteSessions) { @@ -146,7 +150,7 @@ namespace llarp } void - EndpointUtil::StopSnodeSessions(SNodeSessions& sessions) + EndpointUtil::StopSnodeSessions(SNodeConnectionMap& sessions) { for (auto& item : sessions) { @@ -155,7 +159,7 @@ namespace llarp } bool - EndpointUtil::HasPathToService(const Address& addr, const Sessions& remoteSessions) + EndpointUtil::HasPathToService(const Address& addr, const ConnectionMap& remoteSessions) { auto range = remoteSessions.equal_range(addr); auto itr = range.first; @@ -170,7 +174,9 @@ namespace llarp bool EndpointUtil::GetConvoTagsForService( - const ConvoMap& sessions, const Address& info, std::set& tags) + const std::unordered_map& sessions, + const Address& info, + std::set& tags) { bool inserted = false; auto itr = sessions.begin(); diff --git a/llarp/service/endpoint_util.hpp b/llarp/service/endpoint_util.hpp index 62792f7827..3839dd76ca 100644 --- a/llarp/service/endpoint_util.hpp +++ b/llarp/service/endpoint_util.hpp @@ -7,35 +7,41 @@ namespace llarp::service struct EndpointUtil { static void - ExpireSNodeSessions(llarp_time_t now, SNodeSessions& sessions); + ExpireSNodeSessions(llarp_time_t now, SNodeConnectionMap& sessions); static void - ExpirePendingTx(llarp_time_t now, PendingLookups& lookups); + ExpirePendingTx(llarp_time_t now, PendingLookupsMap& lookups); static void - ExpirePendingRouterLookups(llarp_time_t now, PendingRouters& routers); + ExpirePendingRouterLookups(llarp_time_t now, PendingRoutersMap& routers); static void - DeregisterDeadSessions(llarp_time_t now, Sessions& sessions); + DeregisterDeadSessions(llarp_time_t now, ConnectionMap& sessions); static void TickRemoteSessions( - llarp_time_t now, Sessions& remoteSessions, Sessions& deadSessions, ConvoMap& sessions); + llarp_time_t now, + ConnectionMap& remoteSessions, + ConnectionMap& deadSessions, + std::unordered_map& sessions); static void - ExpireConvoSessions(llarp_time_t now, ConvoMap& sessions); + ExpireConvoSessions(llarp_time_t now, std::unordered_map& sessions); static void - StopRemoteSessions(Sessions& remoteSessions); + StopRemoteSessions(ConnectionMap& remoteSessions); static void - StopSnodeSessions(SNodeSessions& sessions); + StopSnodeSessions(SNodeConnectionMap& sessions); static bool - HasPathToService(const Address& addr, const Sessions& remoteSessions); + HasPathToService(const Address& addr, const ConnectionMap& remoteSessions); static bool - GetConvoTagsForService(const ConvoMap& sessions, const Address& addr, std::set& tags); + GetConvoTagsForService( + const std::unordered_map& sessions, + const Address& addr, + std::set& tags); }; template diff --git a/llarp/service/handler.hpp b/llarp/service/handler.hpp deleted file mode 100644 index 74498c0caa..0000000000 --- a/llarp/service/handler.hpp +++ /dev/null @@ -1,84 +0,0 @@ -#pragma once - -#include -#include -#include "intro_set.hpp" -#include "convotag.hpp" - -#include -#include - -namespace llarp -{ - namespace service - { - struct ProtocolMessage; - - struct RecvDataEvent - { - path::Path_ptr fromPath; - PathID_t pathid; - std::shared_ptr msg; - }; - - struct ProtocolMessage; - struct IDataHandler - { - virtual bool - HandleDataMessage( - path::Path_ptr path, const PathID_t from, std::shared_ptr msg) = 0; - - virtual bool - GetCachedSessionKeyFor(const ConvoTag& remote, SharedSecret& secret) const = 0; - virtual void - PutCachedSessionKeyFor(const ConvoTag& remote, const SharedSecret& secret) = 0; - - /// called when we send data to remote on a convotag - virtual void - ConvoTagTX(const ConvoTag& tag) = 0; - - /// called when we got data from remote on a convotag - virtual void - ConvoTagRX(const ConvoTag& tag) = 0; - - virtual void - RemoveConvoTag(const ConvoTag& remote) = 0; - - virtual bool - HasConvoTag(const ConvoTag& remote) const = 0; - - virtual void - PutSenderFor(const ConvoTag& remote, const ServiceInfo& si, bool inbound) = 0; - - virtual bool - GetSenderFor(const ConvoTag& remote, ServiceInfo& si) const = 0; - - virtual void - PutIntroFor(const ConvoTag& remote, const Introduction& intro) = 0; - - virtual bool - GetIntroFor(const ConvoTag& remote, Introduction& intro) const = 0; - - virtual void - PutReplyIntroFor(const ConvoTag& remote, const Introduction& intro) = 0; - - virtual bool - GetReplyIntroFor(const ConvoTag& remote, Introduction& intro) const = 0; - - virtual bool - GetConvoTagsForService(const Address& si, std::set& tag) const = 0; - - virtual bool - HasInboundConvo(const Address& addr) const = 0; - - virtual bool - HasOutboundConvo(const Address& addr) const = 0; - - /// do we want a session outbound to addr - virtual bool - WantsOutboundSession(const Address& addr) const = 0; - virtual void - QueueRecvData(RecvDataEvent ev) = 0; - }; - } // namespace service -} // namespace llarp diff --git a/llarp/service/hidden_service_address_lookup.cpp b/llarp/service/hidden_service_address_lookup.cpp deleted file mode 100644 index 64d0f5fed9..0000000000 --- a/llarp/service/hidden_service_address_lookup.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "hidden_service_address_lookup.hpp" - -#include -#include "endpoint.hpp" -#include - -namespace llarp::service -{ - HiddenServiceAddressLookup::HiddenServiceAddressLookup( - Endpoint* p, - HandlerFunc h, - const dht::Key_t& l, - const PubKey& k, - const RouterID& ep, - uint64_t order, - uint64_t tx, - llarp_time_t timeout) - : IServiceLookup(p, tx, "HSLookup", timeout) - , rootkey(k) - , relayOrder(order) - , location(l) - , handle(std::move(h)) - { - endpoint = ep; - } - - bool - HiddenServiceAddressLookup::HandleIntrosetResponse(const std::set& results) - { - std::optional found; - const Address remote{rootkey}; - if (results.size() > 0) - { - EncryptedIntroSet selected; - for (const auto& introset : results) - { - if (selected.OtherIsNewer(introset)) - selected = introset; - } - const auto maybe = selected.MaybeDecrypt(rootkey); - if (maybe) - { - LogInfo("found result for ", remote.ToString()); - found = *maybe; - } - } - return handle(remote, found, endpoint, TimeLeft(time_now_ms()), relayOrder); - } - - std::shared_ptr - HiddenServiceAddressLookup::BuildRequestMessage() - { - auto msg = std::make_shared(); - msg->dht_msgs.emplace_back(std::make_unique(txid, location, relayOrder)); - return msg; - } - -} // namespace llarp::service diff --git a/llarp/service/hidden_service_address_lookup.hpp b/llarp/service/hidden_service_address_lookup.hpp deleted file mode 100644 index f81b9b1556..0000000000 --- a/llarp/service/hidden_service_address_lookup.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include -#include "intro_set.hpp" -#include "lookup.hpp" - -namespace llarp::service -{ - /// interval for which we will add to lookup timeout interval - constexpr auto IntrosetLookupGraceInterval = 20s; - - struct Endpoint; - struct HiddenServiceAddressLookup : public IServiceLookup - { - const PubKey rootkey; - uint64_t relayOrder; - const dht::Key_t location; - using HandlerFunc = std::function, const RouterID&, llarp_time_t, uint64_t)>; - HandlerFunc handle; - - HiddenServiceAddressLookup( - Endpoint* p, - HandlerFunc h, - const dht::Key_t& location, - const PubKey& rootkey, - const RouterID& routerAsked, - uint64_t relayOrder, - uint64_t tx, - llarp_time_t timeout); - - ~HiddenServiceAddressLookup() override = default; - - bool - IsFor(EndpointBase::AddressVariant_t addr) const override - { - if (const auto* ptr = std::get_if
(&addr)) - { - return Address{rootkey} == *ptr; - } - return false; - } - - bool - HandleIntrosetResponse(const std::set& results) override; - - std::shared_ptr - BuildRequestMessage() override; - }; -} // namespace llarp::service diff --git a/llarp/service/info.cpp b/llarp/service/info.cpp index b3622d8bd7..f236307300 100644 --- a/llarp/service/info.cpp +++ b/llarp/service/info.cpp @@ -45,12 +45,26 @@ namespace llarp::service return read; } + void + ServiceInfo::bt_decode(oxenc::bt_dict_consumer& btdc) + { + try + { + enckey.FromString(btdc.require("e")); + signkey.FromString(btdc.require("s")); + vanity.from_string(btdc.require("x")); + } + catch (...) + { + log::critical(info_cat, "ServiceInfo failed to populate with bt encoded contents"); + } + } + void ServiceInfo::bt_encode(oxenc::bt_dict_producer& btdp) const { btdp.append("e", enckey.ToView()); btdp.append("s", signkey.ToView()); - btdp.append("v", version); if (not vanity.IsZero()) btdp.append("x", vanity.ToView()); diff --git a/llarp/service/info.hpp b/llarp/service/info.hpp index d773870c43..bf610d6ad7 100644 --- a/llarp/service/info.hpp +++ b/llarp/service/info.hpp @@ -100,6 +100,9 @@ namespace llarp::service return UpdateAddr(); } + void + bt_decode(oxenc::bt_dict_consumer&); + void bt_encode(oxenc::bt_dict_producer& btdp) const; diff --git a/llarp/service/intro.cpp b/llarp/service/intro.cpp index bcb1eac99d..81db1aedf5 100644 --- a/llarp/service/intro.cpp +++ b/llarp/service/intro.cpp @@ -32,16 +32,34 @@ namespace llarp::service return read; } + Introduction::Introduction(std::string buf) + { + try + { + oxenc::bt_dict_consumer btdc{std::move(buf)}; + + router.FromString(btdc.require("k")); + latency = std::chrono::milliseconds{btdc.require("l")}; + path_id.from_string(btdc.require("p")); + expiry = std::chrono::milliseconds{btdc.require("x")}; + } + catch (...) + { + log::critical(intro_cat, "Error: Introduction failed to populate with bt encoded contents"); + } + } + void - Introduction::bt_encode(oxenc::bt_dict_producer& btdp) const + Introduction::bt_encode(oxenc::bt_list_producer& btlp) const { try { - btdp.append("k", router.ToView()); - btdp.append("l", latency.count()); - btdp.append("p", path_id.ToView()); - btdp.append("v", version); - btdp.append("x", expiry.count()); + auto subdict = btlp.append_dict(); + + subdict.append("k", router.ToView()); + subdict.append("l", latency.count()); + subdict.append("p", path_id.ToView()); + subdict.append("x", expiry.count()); } catch (...) { diff --git a/llarp/service/intro.hpp b/llarp/service/intro.hpp index ebfcf03660..caf073a785 100644 --- a/llarp/service/intro.hpp +++ b/llarp/service/intro.hpp @@ -24,6 +24,8 @@ namespace llarp::service llarp_time_t expiry = 0s; uint64_t version = llarp::constants::proto_version; + Introduction(std::string buf); + util::StatusObject ExtractStatus() const; @@ -43,7 +45,7 @@ namespace llarp::service ToString() const; void - bt_encode(oxenc::bt_dict_producer& btdp) const; + bt_encode(oxenc::bt_list_producer& btlp) const; bool BDecode(llarp_buffer_t* buf) diff --git a/llarp/service/intro_set.cpp b/llarp/service/intro_set.cpp index a5e9386b11..ad18727c02 100644 --- a/llarp/service/intro_set.cpp +++ b/llarp/service/intro_set.cpp @@ -12,13 +12,32 @@ namespace llarp::service std::string enc_payload, std::string nonce, std::string s) - : signedAt{signed_at}, nounce{reinterpret_cast(nonce.data())} + : signedAt{signed_at} + , introsetPayload{reinterpret_cast(enc_payload.data()), enc_payload.size()} + , nounce{reinterpret_cast(nonce.data())} { derivedSigningKey = PubKey::from_string(signing_key); - introsetPayload = oxenc::bt_deserialize>(enc_payload); sig.from_string(std::move(s)); } + EncryptedIntroSet::EncryptedIntroSet(std::string bt_payload) + { + try + { + oxenc::bt_dict_consumer btdc{bt_payload}; + + derivedSigningKey = PubKey::from_string(btdc.require("d")); + nounce.from_string(btdc.require("n")); + signedAt = std::chrono::milliseconds{btdc.require("s")}; + introsetPayload = btdc.require("x"); + sig.from_string(btdc.require("z")); + } + catch (...) + { + log::critical(net_cat, "Error: EncryptedIntroSet failed to bt encode contents!"); + } + } + util::StatusObject EncryptedIntroSet::ExtractStatus() const { @@ -37,7 +56,10 @@ namespace llarp::service btdp.append("d", derivedSigningKey.ToView()); btdp.append("n", nounce.ToView()); btdp.append("s", signedAt.count()); - btdp.append("x", oxenc::bt_serialize(introsetPayload)); + btdp.append( + "x", + std::string_view{ + reinterpret_cast(introsetPayload.data()), introsetPayload.size()}); btdp.append("z", sig.ToView()); } catch (...) @@ -95,18 +117,17 @@ namespace llarp::service sig); } - std::optional - EncryptedIntroSet::MaybeDecrypt(const PubKey& root) const + IntroSet + EncryptedIntroSet::decrypt(const PubKey& root) const { SharedSecret k(root); - IntroSet i; - std::vector payload = introsetPayload; - llarp_buffer_t buf(payload); - - CryptoManager::instance()->xchacha20(payload.data(), payload.size(), k, nounce); - if (not i.BDecode(&buf)) - return {}; - return i; + std::string payload{ + reinterpret_cast(introsetPayload.data()), introsetPayload.size()}; + + CryptoManager::instance()->xchacha20( + reinterpret_cast(payload.data()), payload.size(), k, nounce); + + return IntroSet{payload}; } bool @@ -278,6 +299,75 @@ namespace llarp::service return read or bencode_discard(buf); } + IntroSet::IntroSet(std::string bt_payload) + { + try + { + oxenc::bt_dict_consumer btdc{bt_payload}; + + if (btdc.key() == "a") + { + auto subdict = btdc.consume_dict_consumer(); + address_keys.bt_decode(subdict); + } + + if (btdc.key() == "e") + { + auto subdict = btdc.consume_dict_consumer(); + exit_policy->bt_decode(subdict); + } + + if (btdc.key() == "i") + { + auto sublist = btdc.consume_list_consumer(); + while (not sublist.is_finished()) + { + intros.emplace_back(sublist.consume_string()); + } + } + + sntru_pubkey.from_string(btdc.require("k")); + topic.from_string(btdc.require("n")); + + if (btdc.key() == "p") + { + auto sublist = btdc.consume_list_consumer(); + while (not sublist.is_finished()) + { + supported_protocols.emplace_back(sublist.consume_integer()); + } + } + + if (btdc.key() == "r") + { + auto sublist = btdc.consume_list_consumer(); + while (not sublist.is_finished()) + { + owned_ranges.emplace(sublist.consume_string()); + } + } + + if (btdc.key() == "s") + { + // TODO: fuck everything about these tuples + // auto sublist = btdc.consume_list_consumer(); + // while (not sublist.is_finished()) + // { + // // auto s = oxenc:: + // auto sd = SRVs.emplace_back(); + + // } + } + + time_signed = std::chrono::milliseconds{btdc.require("t")}; + signature.from_string(btdc.require("z")); + } + catch (...) + { + log::critical(net_cat, "Error: EncryptedIntroSet failed to bt encode contents!"); + } + } + std::string IntroSet::bt_encode() const { @@ -297,9 +387,9 @@ namespace llarp::service } { - auto subdict = btdp.append_dict("i"); + auto sublist = btdp.append_list("i"); for (auto& i : intros) - i.bt_encode(subdict); + i.bt_encode(sublist); } btdp.append("k", sntru_pubkey.ToView()); @@ -314,16 +404,19 @@ namespace llarp::service if (not owned_ranges.empty()) { - auto sublist = btdp.append_list("s"); + auto sublist = btdp.append_list("r"); for (auto& r : owned_ranges) r.bt_encode(sublist); } if (not SRVs.empty()) - btdp.append("s", oxenc::bt_serialize(SRVs)); + { + auto sublist = btdp.append_list("s"); + for (auto& s : SRVs) + sublist.append(oxenc::bt_serialize(s)); + } btdp.append("t", time_signed.count()); - btdp.append("v", version); btdp.append("z", signature.ToView()); } catch (...) diff --git a/llarp/service/intro_set.hpp b/llarp/service/intro_set.hpp index 5107763303..725e240095 100644 --- a/llarp/service/intro_set.hpp +++ b/llarp/service/intro_set.hpp @@ -35,6 +35,10 @@ namespace llarp::service std::vector SRVs; llarp_time_t time_signed = 0s; + IntroSet() = default; + + explicit IntroSet(std::string bt_payload); + /// ethertypes we advertise that we speak std::vector supported_protocols; /// aonnuce that these ranges are reachable via our endpoint @@ -134,7 +138,7 @@ namespace llarp::service { PubKey derivedSigningKey; llarp_time_t signedAt = 0s; - std::vector introsetPayload; + ustring introsetPayload; TunnelNonce nounce; std::optional topic; Signature sig; @@ -148,6 +152,8 @@ namespace llarp::service std::string nonce, std::string sig); + explicit EncryptedIntroSet(std::string bt_payload); + bool Sign(const PrivateKey& k); @@ -185,8 +191,8 @@ namespace llarp::service util::StatusObject ExtractStatus() const; - std::optional - MaybeDecrypt(const PubKey& rootKey) const; + IntroSet + decrypt(const PubKey& root) const; }; inline bool diff --git a/llarp/service/outbound_context.cpp b/llarp/service/outbound_context.cpp index 4db279f901..630127ac39 100644 --- a/llarp/service/outbound_context.cpp +++ b/llarp/service/outbound_context.cpp @@ -1,6 +1,5 @@ #include "outbound_context.hpp" #include "async_key_exchange.hpp" -#include "hidden_service_address_lookup.hpp" #include "endpoint.hpp" #include "endpoint_util.hpp" #include "protocol_type.hpp" @@ -289,21 +288,24 @@ namespace llarp::service // we want to use the parent endpoint's paths because outbound context // does not implement path::PathSet::HandleGotIntroMessage const auto paths = GetManyPathsWithUniqueEndpoints(m_Endpoint, 2, location); - uint64_t relayOrder = 0; - for (const auto& path : paths) - { - HiddenServiceAddressLookup* job = new HiddenServiceAddressLookup( - m_Endpoint, - util::memFn(&OutboundContext::OnIntroSetUpdate, shared_from_this()), - location, - PubKey{addr.as_array()}, - path->Endpoint(), - relayOrder, - m_Endpoint->GenTXID(), - (IntrosetUpdateInterval / 2) + (2 * path->intro.latency) + IntrosetLookupGraceInterval); - relayOrder++; - if (job->SendRequestViaPath(path, m_Endpoint->router())) - updatingIntroSet = true; + [[maybe_unused]] uint64_t relayOrder = 0; + for ([[maybe_unused]] const auto& path : paths) + { + // TODO: implement this + + // HiddenServiceAddressLookup* job = new HiddenServiceAddressLookup( + // m_Endpoint, + // util::memFn(&OutboundContext::OnIntroSetUpdate, shared_from_this()), + // location, + // PubKey{addr.as_array()}, + // path->Endpoint(), + // relayOrder, + // m_Endpoint->GenTXID(), + // (IntrosetUpdateInterval / 2) + (2 * path->intro.latency) + + // IntrosetLookupGraceInterval); + // relayOrder++; + // if (job->SendRequestViaPath(path, m_Endpoint->router())) + // updatingIntroSet = true; } } @@ -449,7 +451,7 @@ namespace llarp::service } if (m_ReadyHooks.empty()) { - m_router->loop()->call_later(timeout, [this]() { + router->loop()->call_later(timeout, [this]() { LogWarn(Name(), " did not obtain session in time"); for (const auto& hook : m_ReadyHooks) hook(nullptr); diff --git a/llarp/service/protocol.cpp b/llarp/service/protocol.cpp index 7f4166abd5..26b82747a0 100644 --- a/llarp/service/protocol.cpp +++ b/llarp/service/protocol.cpp @@ -220,8 +220,6 @@ namespace llarp::service ProtocolFrameMessage::EncryptAndSign( const ProtocolMessage& msg, const SharedSecret& sessionKey, const Identity& localIdent) { - std::array tmp; - llarp_buffer_t buf1(tmp); // encode message auto bte1 = msg.bt_encode(); // encrypt @@ -229,7 +227,6 @@ namespace llarp::service reinterpret_cast(bte1.data()), bte1.size(), sessionKey, nonce); // put encrypted buffer std::memcpy(enc.data(), bte1.data(), bte1.size()); - enc = buf1; // zero out signature sig.Zero(); diff --git a/llarp/service/protocol.hpp b/llarp/service/protocol.hpp index 074acd95fa..f6e882c794 100644 --- a/llarp/service/protocol.hpp +++ b/llarp/service/protocol.hpp @@ -4,11 +4,11 @@ #include #include #include +#include #include "protocol_type.hpp" #include "identity.hpp" #include "info.hpp" #include "intro.hpp" -#include "handler.hpp" #include #include #include diff --git a/llarp/service/sendcontext.hpp b/llarp/service/sendcontext.hpp index 460cd0467f..f67266fe5f 100644 --- a/llarp/service/sendcontext.hpp +++ b/llarp/service/sendcontext.hpp @@ -1,8 +1,10 @@ #pragma once +#include "intro.hpp" #include #include -#include "intro.hpp" +#include +#include #include "protocol.hpp" #include #include @@ -10,82 +12,79 @@ #include -namespace llarp +namespace llarp::service { - namespace service - { - struct ServiceInfo; - struct Endpoint; - struct Introduction; + struct ServiceInfo; + struct Endpoint; + struct Introduction; - struct SendContext + struct SendContext + { + SendContext(ServiceInfo ident, const Introduction& intro, path::PathSet* send, Endpoint* ep); + + void + AsyncEncryptAndSendTo(const llarp_buffer_t& payload, ProtocolType t); + + /// queue send a fully encrypted hidden service frame + /// via a path + bool + Send(std::shared_ptr f, path::Path_ptr path); + + /// flush upstream traffic when in router thread + void + FlushUpstream(); + + SharedSecret sharedKey; + ServiceInfo remoteIdent; + Introduction remoteIntro; + ConvoTag currentConvoTag; + path::PathSet* const m_PathSet; + Endpoint* const m_DataHandler; + Endpoint* const m_Endpoint; + uint64_t sequenceNo = 0; + llarp_time_t lastGoodSend = 0s; + const llarp_time_t createdAt; + llarp_time_t sendTimeout = path::BUILD_TIMEOUT; + llarp_time_t connectTimeout = path::BUILD_TIMEOUT * 2; + llarp_time_t shiftTimeout = (path::BUILD_TIMEOUT * 5) / 2; + llarp_time_t estimatedRTT = 0s; + bool markedBad = false; + using Msg_ptr = std::shared_ptr; + using SendEvent_t = std::pair; + + thread::Queue m_SendQueue; + + std::function authResultListener; + + virtual bool + ShiftIntroduction(bool rebuild = true) { - SendContext(ServiceInfo ident, const Introduction& intro, path::PathSet* send, Endpoint* ep); - - void - AsyncEncryptAndSendTo(const llarp_buffer_t& payload, ProtocolType t); - - /// queue send a fully encrypted hidden service frame - /// via a path - bool - Send(std::shared_ptr f, path::Path_ptr path); - - /// flush upstream traffic when in router thread - void - FlushUpstream(); - - SharedSecret sharedKey; - ServiceInfo remoteIdent; - Introduction remoteIntro; - ConvoTag currentConvoTag; - path::PathSet* const m_PathSet; - IDataHandler* const m_DataHandler; - Endpoint* const m_Endpoint; - uint64_t sequenceNo = 0; - llarp_time_t lastGoodSend = 0s; - const llarp_time_t createdAt; - llarp_time_t sendTimeout = path::BUILD_TIMEOUT; - llarp_time_t connectTimeout = path::BUILD_TIMEOUT * 2; - llarp_time_t shiftTimeout = (path::BUILD_TIMEOUT * 5) / 2; - llarp_time_t estimatedRTT = 0s; - bool markedBad = false; - using Msg_ptr = std::shared_ptr; - using SendEvent_t = std::pair; - - thread::Queue m_SendQueue; - - std::function authResultListener; - - virtual bool - ShiftIntroduction(bool rebuild = true) - { - (void)rebuild; - return true; - } - - virtual void - ShiftIntroRouter(const RouterID) = 0; - - virtual void - UpdateIntroSet() = 0; - - virtual void - MarkCurrentIntroBad(llarp_time_t now) = 0; - - void - AsyncSendAuth(std::function replyHandler); - - private: - virtual bool - IntroGenerated() const = 0; - virtual bool - IntroSent() const = 0; - - void - EncryptAndSendTo(const llarp_buffer_t& payload, ProtocolType t); - - virtual void - AsyncGenIntro(const llarp_buffer_t& payload, ProtocolType t) = 0; - }; - } // namespace service -} // namespace llarp + (void)rebuild; + return true; + } + + virtual void + ShiftIntroRouter(const RouterID) = 0; + + virtual void + UpdateIntroSet() = 0; + + virtual void + MarkCurrentIntroBad(llarp_time_t now) = 0; + + void + AsyncSendAuth(std::function replyHandler); + + private: + virtual bool + IntroGenerated() const = 0; + virtual bool + IntroSent() const = 0; + + void + EncryptAndSendTo(const llarp_buffer_t& payload, ProtocolType t); + + virtual void + AsyncGenIntro(const llarp_buffer_t& payload, ProtocolType t) = 0; + }; +} // namespace llarp::service diff --git a/llarp/service/session.cpp b/llarp/service/session.cpp index e54f722ca3..e47837b08d 100644 --- a/llarp/service/session.cpp +++ b/llarp/service/session.cpp @@ -1,54 +1,51 @@ #include "session.hpp" -namespace llarp +namespace llarp::service { - namespace service + util::StatusObject + Session::ExtractStatus() const { - util::StatusObject - Session::ExtractStatus() const - { - util::StatusObject obj{ - {"lastSend", to_json(lastSend)}, - {"lastRecv", to_json(lastRecv)}, - {"replyIntro", replyIntro.ExtractStatus()}, - {"remote", Addr().ToString()}, - {"seqno", seqno}, - {"tx", messagesSend}, - {"rx", messagesRecv}, - {"intro", intro.ExtractStatus()}}; - return obj; - } + util::StatusObject obj{ + {"lastSend", to_json(lastSend)}, + {"lastRecv", to_json(lastRecv)}, + {"replyIntro", replyIntro.ExtractStatus()}, + {"remote", Addr().ToString()}, + {"seqno", seqno}, + {"tx", messagesSend}, + {"rx", messagesRecv}, + {"intro", intro.ExtractStatus()}}; + return obj; + } - Address - Session::Addr() const - { - return remote.Addr(); - } + Address + Session::Addr() const + { + return remote.Addr(); + } - bool - Session::IsExpired(llarp_time_t now, llarp_time_t lifetime) const - { - if (forever) - return false; - const auto lastUsed = std::max(lastSend, lastRecv); - if (lastUsed == 0s) - return intro.IsExpired(now); - return now >= lastUsed && (now - lastUsed > lifetime); - } + bool + Session::IsExpired(llarp_time_t now, llarp_time_t lifetime) const + { + if (forever) + return false; + const auto lastUsed = std::max(lastSend, lastRecv); + if (lastUsed == 0s) + return intro.IsExpired(now); + return now >= lastUsed && (now - lastUsed > lifetime); + } - void - Session::TX() - { - messagesSend++; - lastSend = time_now_ms(); - } + void + Session::TX() + { + messagesSend++; + lastSend = time_now_ms(); + } - void - Session::RX() - { - messagesRecv++; - lastRecv = time_now_ms(); - } + void + Session::RX() + { + messagesRecv++; + lastRecv = time_now_ms(); + } - } // namespace service -} // namespace llarp +} // namespace llarp::service diff --git a/llarp/service/session.hpp b/llarp/service/session.hpp index 3631182ebb..856816d270 100644 --- a/llarp/service/session.hpp +++ b/llarp/service/session.hpp @@ -7,53 +7,49 @@ #include #include -namespace llarp +namespace llarp::service { - namespace service - { - static constexpr auto SessionLifetime = path::DEFAULT_LIFETIME * 2; - - struct Session - { - /// the intro we have - Introduction replyIntro; - SharedSecret sharedKey; - ServiceInfo remote; - /// the intro they have - Introduction intro; + static constexpr auto SessionLifetime = path::DEFAULT_LIFETIME * 2; - /// the sequence number we are to use for the next message - uint64_t seqno = 0; + struct Session + { + /// the intro we have + Introduction replyIntro; + SharedSecret sharedKey; + ServiceInfo remote; + /// the intro they have + Introduction intro; - /// number of remote messages we sent to them - uint64_t messagesSend = 0; - /// number of remote messages we got from them - uint64_t messagesRecv = 0; + /// the sequence number we are to use for the next message + uint64_t seqno = 0; - bool inbound = false; - bool forever = false; + /// number of remote messages we sent to them + uint64_t messagesSend = 0; + /// number of remote messages we got from them + uint64_t messagesRecv = 0; - Duration_t lastSend{}; - Duration_t lastRecv{}; + bool inbound = false; + bool forever = false; - util::StatusObject - ExtractStatus() const; + Duration_t lastSend{}; + Duration_t lastRecv{}; - /// called to indicate we recieved on this session - void - RX(); + util::StatusObject + ExtractStatus() const; - /// called to indicate we transimitted on this session - void - TX(); + /// called to indicate we recieved on this session + void + RX(); - bool - IsExpired(llarp_time_t now, llarp_time_t lifetime = SessionLifetime) const; + /// called to indicate we transimitted on this session + void + TX(); - Address - Addr() const; - }; + bool + IsExpired(llarp_time_t now, llarp_time_t lifetime = SessionLifetime) const; - } // namespace service + Address + Addr() const; + }; -} // namespace llarp +} // namespace llarp::service From f35f7fe3f2d0c18e25224e451d77261c88c21a36 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Tue, 3 Oct 2023 21:59:50 -0400 Subject: [PATCH 044/312] refactor path build message construction, no more async nonsense --- llarp/constants/path.hpp | 2 +- llarp/link/link_manager.cpp | 4 + llarp/link/link_manager.hpp | 5 +- llarp/path/path.hpp | 24 --- llarp/path/pathbuilder.cpp | 309 ++++++++++++++++++------------------ llarp/path/pathbuilder.hpp | 36 ++++- 6 files changed, 192 insertions(+), 188 deletions(-) diff --git a/llarp/constants/path.hpp b/llarp/constants/path.hpp index 1cb8410110..9b066adb30 100644 --- a/llarp/constants/path.hpp +++ b/llarp/constants/path.hpp @@ -16,7 +16,7 @@ namespace llarp::path constexpr std::size_t PAD_SIZE = 128; /// default path lifetime in ms constexpr std::chrono::milliseconds DEFAULT_LIFETIME = 20min; - /// minimum into lifetime we will advertise + /// minimum intro lifetime we will advertise constexpr std::chrono::milliseconds MIN_INTRO_LIFETIME = DEFAULT_LIFETIME / 2; /// number of slices of path lifetime to spread intros out via constexpr auto INTRO_SPREAD_SLICES = 4; diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 74eacc6545..317c956b0c 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1122,4 +1122,8 @@ namespace llarp return; } } + + void + LinkManager::handle_path_build(oxen::quic::message) + {} } // namespace llarp diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 395847693b..c337a10a2f 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -288,7 +288,7 @@ namespace llarp void handle_find_router(oxen::quic::message); // relay + path // Path messages - void handle_relay_commit(oxen::quic::message); // relay + void handle_path_build(oxen::quic::message); // relay void handle_relay_status(oxen::quic::message); // relay void handle_path_confirm(oxen::quic::message); // relay void handle_path_latency(oxen::quic::message); // relay @@ -304,6 +304,7 @@ namespace llarp {"find_router", &LinkManager::handle_find_router}, {"publish_intro", &LinkManager::handle_publish_intro}, {"find_intro", &LinkManager::handle_find_intro}, + {"path_build", &LinkManager::handle_path_build}, {"path_confirm", &LinkManager::handle_path_confirm}, {"path_latency", &LinkManager::handle_path_latency}, {"update_exit", &LinkManager::handle_update_exit}, @@ -317,7 +318,7 @@ namespace llarp void handle_find_router_response(oxen::quic::message); // Path responses - void handle_relay_commit_response(oxen::quic::message); + void handle_path_build_response(oxen::quic::message); void handle_relay_status_response(oxen::quic::message); void handle_path_confirm_response(oxen::quic::message); void handle_path_latency_response(oxen::quic::message); diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index c84e4685ee..55483f7faf 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -37,30 +37,6 @@ namespace llarp using TransitHop_ptr = std::shared_ptr; - /// configuration for a single hop when building a path - struct PathHopConfig - { - /// path id - PathID_t txID, rxID; - // router contact of router - RouterContact rc; - // temp public encryption key - SecretKey commkey; - /// shared secret at this hop - SharedSecret shared; - /// hash of shared secret used for nonce mutation - ShortHash nonceXOR; - /// next hop's router id - RouterID upstream; - /// nonce for key exchange - TunnelNonce nonce; - // lifetime - llarp_time_t lifetime = DEFAULT_LIFETIME; - - util::StatusObject - ExtractStatus() const; - }; - inline bool operator<(const PathHopConfig& lhs, const PathHopConfig& rhs) { diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index 360046568c..d34d9eb881 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -21,173 +21,141 @@ namespace llarp auto log_path = log::Cat("path"); } - struct AsyncPathKeyExchangeContext : std::enable_shared_from_this + namespace path { - using WorkFunc_t = std::function; - using WorkerFunc_t = std::function; - using Path_t = path::Path_ptr; - using PathSet_t = path::PathSet_ptr; - PathSet_t pathset = nullptr; - Path_t path = nullptr; - using Handler = std::function)>; - - Handler result; - size_t idx = 0; - Router* router = nullptr; - WorkerFunc_t work; - EventLoop_ptr loop; - LR_CommitMessage LRCM; + bool + BuildLimiter::Attempt(const RouterID& router) + { + return m_EdgeLimiter.Insert(router); + } void - GenerateNextKey() + BuildLimiter::Decay(llarp_time_t now) { - // current hop - auto& hop = path->hops[idx]; - auto& frame = LRCM.frames[idx]; + m_EdgeLimiter.Decay(now); + } + bool + BuildLimiter::Limited(const RouterID& router) const + { + return m_EdgeLimiter.Contains(router); + } + + Builder::Builder(Router* p_router, size_t pathNum, size_t hops) + : path::PathSet{pathNum}, _run{true}, router{p_router}, numHops{hops} + {} + + /* - For each hop: + * SetupHopKeys: + * - Generate Ed keypair for the hop. ("commkey") + * - Use that key and the hop's pubkey for DH key exchange (makes "hop.shared") + * - Note: this *was* using hop's "enckey" but we're getting rid of that + * - hop's "upstream" RouterID is next hop, or that hop's ID if it is terminal hop + * - hop's chacha nonce is hash of symmetric key (hop.shared) from DH + * - hop's "txID" and "rxID" are chosen before this step + * - txID is the path ID for messages coming *from* the client/path origin + * - rxID is the path ID for messages going *to* it. + * + * CreateHopInfoFrame: + * - bt-encode "hop info": + * - path lifetime + * - protocol version + * - txID + * - rxID + * - nonce + * - upstream hop RouterID + * - ephemeral public key (for DH) + * - generate *second* ephemeral Ed keypair... ("framekey") TODO: why? + * - generate DH symmetric key using "framekey" and hop's pubkey + * - generate nonce for second encryption + * - encrypt "hop info" using this symmetric key + * - bt-encode nonce, "framekey" pubkey, encrypted "hop info" + * - hash this bt-encoded string + * - bt-encode hash and the frame in a dict, serialize + * + * + * all of these "frames" go in a list, along with any needed dummy frames + */ + + void + Builder::SetupHopKeys(path::PathHopConfig& hop, const RouterID& nextHop) + { auto crypto = CryptoManager::instance(); // generate key crypto->encryption_keygen(hop.commkey); + hop.nonce.Randomize(); // do key exchange - if (!crypto->dh_client(hop.shared, hop.rc.enckey, hop.commkey, hop.nonce)) + if (!crypto->dh_client(hop.shared, hop.rc.pubkey, hop.commkey, hop.nonce)) { - LogError(pathset->Name(), " Failed to generate shared key for path build"); - return; + LogError(Name(), " Failed to generate shared key for path build"); + throw std::runtime_error{"Failed to generate shared key for path build"}; } - // generate nonceXOR valueself->hop->pathKey - crypto->shorthash(hop.nonceXOR, hop.shared.data(), hop.shared.size()); - ++idx; + // generate nonceXOR value self->hop->pathKey + crypto->shorthash(hop.nonceXOR, llarp_buffer_t(hop.shared)); - bool isFarthestHop = idx == path->hops.size(); + hop.upstream = nextHop; + } - LR_CommitRecord record; - if (isFarthestHop) - { - hop.upstream = hop.rc.pubkey; - } - else - { - hop.upstream = path->hops[idx].rc.pubkey; - record.nextRC = std::make_unique(path->hops[idx].rc); - } - // build record - record.lifetime = path::DEFAULT_LIFETIME; - record.version = llarp::constants::proto_version; - record.txid = hop.txID; - record.rxid = hop.rxID; - record.tunnelNonce = hop.nonce; - record.nextHop = hop.upstream; - record.commkey = seckey_topublic(hop.commkey); - - llarp_buffer_t buf(frame.data(), frame.size()); - buf.cur = buf.base + EncryptedFrameOverheadSize; - // encode record - if (!record.BEncode(&buf)) - { - // failed to encode? - LogError(pathset->Name(), " Failed to generate Commit Record"); - DumpBuffer(buf); - return; - } - // use ephemeral keypair for frame + // FIXME: this is definitely not optimal using bt_dict instead of bt_dict_producer, among other + // things + std::string + Builder::CreateHopInfoFrame(const path::PathHopConfig& hop) + { + auto crypto = CryptoManager::instance(); + + oxenc::bt_dict hop_info_dict; + hop_info_dict["lifetime"] = path::DEFAULT_LIFETIME.count(); // milliseconds + hop_info_dict["txid"] = hop.txID; + hop_info_dict["rxid"] = hop.rxID; + hop_info_dict["nonce"] = hop.nonce; + hop_info_dict["next"] = hop.upstream; + hop_info_dict["commkey"] = hop.commkey.toPublic(); // pubkey of ephemeral Ed key for DH + + auto hop_info = oxenc::bt_serialize(hop_info_dict); SecretKey framekey; crypto->encryption_keygen(framekey); - if (!frame.EncryptInPlace(framekey, hop.rc.enckey)) - { - LogError(pathset->Name(), " Failed to encrypt LRCR"); - return; - } - if (isFarthestHop) - { - // farthest hop - // TODO: encrypt junk frames because our public keys are not eligator - loop->call([self = shared_from_this()] { - self->result(self); - self->result = nullptr; - }); - } - else + SharedSecret shared; + TunnelNonce outer_nonce; + outer_nonce.Randomize(); + // derive (outer) shared key + if (!crypto->dh_client(shared, hop.rc.pubkey, framekey, outer_nonce)) { - // next hop - work([self = shared_from_this()] { self->GenerateNextKey(); }); + llarp::LogError("DH failed during hop info encryption"); + throw std::runtime_error{"DH failed during hop info encryption"}; } - } - /// Generate all keys asynchronously and call handler when done - void - AsyncGenerateKeys(Path_t p, EventLoop_ptr l, WorkerFunc_t worker, Handler func) - { - path = p; - loop = std::move(l); - result = func; - work = worker; - - for (size_t i = 0; i < path::MAX_LEN; ++i) + // encrypt hop_info (mutates in-place) + if (!crypto->xchacha20( + reinterpret_cast(hop_info.data()), hop_info.size(), shared, outer_nonce)) { - LRCM.frames[i].Randomize(); + llarp::LogError("hop info encrypt failed"); + throw std::runtime_error{"hop info encrypt failed"}; } - work([self = shared_from_this()] { self->GenerateNextKey(); }); - } - }; - - static void - PathBuilderKeysGenerated(std::shared_ptr ctx) - { - if (ctx->pathset->IsStopped()) - return; - - ctx->router->notify_router_event(ctx->router->pubkey(), ctx->path); - - ctx->router->path_context().AddOwnPath(ctx->pathset, ctx->path); - ctx->pathset->PathBuildStarted(ctx->path); - - const RouterID remote = ctx->path->Upstream(); - auto sentHandler = [router = ctx->router, path = ctx->path](auto status) { - if (status != SendStatus::Success) + oxenc::bt_dict hashed_dict; + hashed_dict["encrypted"] = hop_info; + hashed_dict["pubkey"] = framekey.toPublic(); + hashed_dict["nonce"] = nonce; + auto hashed_data = oxenc::bt_serialize(hashed_dict); + + std::basic_string hash{SHORTHASHSIZE, '\0'}; + if (!crypto->hmac( + hash.data(), + reinterpret_cast(hashed_data.data()), + hashed_data.size(), + shared)) { - path->EnterState(path::ePathFailed, router->now()); + llarp::LogError("Failed to generate HMAC for hop info"); + throw std::runtime_error{"Failed to generate HMAC for hop info"}; } - }; - if (ctx->router->SendToOrQueue(remote, ctx->LRCM, sentHandler)) - { - // persist session with router until this path is done - if (ctx->path) - ctx->router->PersistSessionUntil(remote, ctx->path->ExpireTime()); - } - else - { - LogError(ctx->pathset->Name(), " failed to queue LRCM to ", remote); - sentHandler(SendStatus::NoLink); - } - } - namespace path - { - bool - BuildLimiter::Attempt(const RouterID& router) - { - return m_EdgeLimiter.Insert(router); - } - - void - BuildLimiter::Decay(llarp_time_t now) - { - m_EdgeLimiter.Decay(now); - } + oxenc::bt_dict final_frame; + final_frame["hash"] = hash; + final_frame["frame"] = hashed_data; - bool - BuildLimiter::Limited(const RouterID& router) const - { - return m_EdgeLimiter.Contains(router); - } - - Builder::Builder(Router* p_router, size_t pathNum, size_t hops) - : path::PathSet{pathNum}, _run{true}, router{p_router}, numHops{hops} - { - CryptoManager::instance()->encryption_keygen(enckey); + return oxenc::bt_serialize(final_frame); } void @@ -295,12 +263,6 @@ namespace llarp return IsStopped() and NumInStatus(ePathEstablished) == 0; } - const SecretKey& - Builder::GetTunnelEncryptionSecretKey() const - { - return enckey; - } - bool Builder::BuildCooldownHit(RouterID edge) const { @@ -432,22 +394,55 @@ namespace llarp LogWarn(Name(), " building too fast to edge router ", edge); return; } - // async generate keys - auto ctx = std::make_shared(); - ctx->router = router; - auto self = GetSelf(); - ctx->pathset = self; + std::string path_shortName = "[path " + router->ShortName() + "-"; path_shortName = path_shortName + std::to_string(router->NextPathBuildNumber()) + "]"; auto path = std::make_shared(hops, GetWeak(), roles, std::move(path_shortName)); LogInfo(Name(), " build ", path->ShortName(), ": ", path->HopsString()); - path->SetBuildResultHook([self](Path_ptr p) { self->HandlePathBuilt(p); }); - ctx->AsyncGenerateKeys( - path, - router->loop(), - [r = router](auto func) { r->queue_work(std::move(func)); }, - &PathBuilderKeysGenerated); + oxenc::bt_list_producer frames; + auto& path_hops = path->hops; + size_t last_len{0}; + for (size_t i = 0; i < path_hops.size(); i++) + { + bool lastHop = (i == (path_hops.size() - 1)); + const auto& nextHop = lastHop ? path_hops[i].rc.pubkey : path_hops[i + 1].rc.pubkey; + SetupHopKeys(path_hops[i], nextHop); + auto frame_str = CreateHopInfoFrame(path_hops[i]); + if (last_len != 0) + assert( + frame_str.size() + == last_len); // all frames should be the same length...not sure what that is yet + last_len = frame_str.size(); + frames.append(frame_str); + } + + std::string dummy{last_len, '\0'}; + // append dummy frames; path build request must always have MAX_LEN frames + for (size_t i = 0; i < path::MAX_LEN - path_hops.size(); i++) + { + randombytes(reinterpret_cast(dummy.data()), dummy.size()); + frames.append(dummy); + } + + m_router->notify_router_event(m_router->pubkey(), path); + + auto self = GetSelf(); + m_router->path_context().AddOwnPath(self, path); + PathBuildStarted(path); + + auto response_cb = [self](oxen::quic::message m) { + // TODO: this (replaces handling LRSM, which also needs replacing) + }; + + if (not m_router->send_control_message( + path->Upstream(), "path_build", std::move(frames.str()), std::move(response_cb))) + { + log::warning(log_path, "Error sending path_build control message"); + path->EnterState(path::ePathFailed, m_router->now()); + } + + m_router->PersistSessionUntil(path->Upstream(), path->ExpireTime()); } void diff --git a/llarp/path/pathbuilder.hpp b/llarp/path/pathbuilder.hpp index a29bc869ef..6731c352ad 100644 --- a/llarp/path/pathbuilder.hpp +++ b/llarp/path/pathbuilder.hpp @@ -3,12 +3,38 @@ #include "pathset.hpp" #include #include +#include "path.hpp" #include #include namespace llarp::path { + + /// configuration for a single hop when building a path + struct PathHopConfig + { + /// path id + PathID_t txID, rxID; + // router contact of router + RouterContact rc; + // temp public encryption key + SecretKey commkey; + /// shared secret at this hop + SharedSecret shared; + /// hash of shared secret used for nonce mutation + ShortHash nonceXOR; + /// next hop's router id + RouterID upstream; + /// nonce for key exchange + TunnelNonce nonce; + // lifetime + llarp_time_t lifetime = DEFAULT_LIFETIME; + + util::StatusObject + ExtractStatus() const; + }; + // milliseconds waiting between builds on a path per router static constexpr auto MIN_PATH_BUILD_INTERVAL = 500ms; static constexpr auto PATH_BUILD_RATE = 100ms; @@ -54,9 +80,14 @@ namespace llarp::path void DoPathBuildBackoff(); + void + SetupHopKeys(path::PathHopConfig& hop, const RouterID& nextHop); + + std::string + CreateHopInfoFrame(const path::PathHopConfig& hop); + public: Router* const router; - SecretKey enckey; size_t numHops; llarp_time_t lastBuild = 0s; llarp_time_t buildIntervalLimit = MIN_PATH_BUILD_INTERVAL; @@ -133,9 +164,6 @@ namespace llarp::path void ManualRebuild(size_t N, PathRole roles = ePathRoleAny); - const SecretKey& - GetTunnelEncryptionSecretKey() const; - void HandlePathBuilt(Path_ptr p) override; From 4ed6a01e02086b20fd8a1940dbff965ee3afa7cd Mon Sep 17 00:00:00 2001 From: dr7ana Date: Wed, 4 Oct 2023 06:25:25 -0700 Subject: [PATCH 045/312] following up before Tom meeting --- llarp/exit/exit_messages.cpp | 35 ------ llarp/exit/exit_messages.hpp | 6 - llarp/exit/session.cpp | 8 +- llarp/exit/session.hpp | 4 +- llarp/link/link_manager.cpp | 189 +++++++++++++++++++++++++++----- llarp/link/link_manager.hpp | 4 +- llarp/messages/common.hpp | 1 + llarp/messages/dht.hpp | 34 +++--- llarp/messages/exit.hpp | 25 +++++ llarp/messages/path.hpp | 121 ++++++++++++++++++-- llarp/messages/relay_commit.cpp | 6 +- llarp/path/path.cpp | 59 +++++----- llarp/path/path.hpp | 14 +-- llarp/path/path_types.hpp | 45 ++++++++ llarp/path/pathbuilder.cpp | 164 ++++++++++++++++----------- llarp/path/pathbuilder.hpp | 33 +----- llarp/path/pathset.cpp | 4 +- llarp/path/transit_hop.cpp | 15 +-- llarp/router/router.cpp | 2 +- llarp/router/router.hpp | 2 +- llarp/service/endpoint.cpp | 2 +- llarp/service/intro.hpp | 1 + llarp/service/protocol.cpp | 2 +- 23 files changed, 517 insertions(+), 259 deletions(-) create mode 100644 llarp/messages/exit.hpp diff --git a/llarp/exit/exit_messages.cpp b/llarp/exit/exit_messages.cpp index c51fde2815..0d8ac8a9c2 100644 --- a/llarp/exit/exit_messages.cpp +++ b/llarp/exit/exit_messages.cpp @@ -35,28 +35,11 @@ namespace llarp::routing try { - btdp.append("A", "O"); - - { - auto subdict = btdp.append_dict("B"); - - for (auto& b : blacklist_policy) - b.bt_encode(subdict); - } - btdp.append("E", flag); btdp.append("I", pubkey.ToView()); btdp.append("S", sequence_number); btdp.append("T", tx_id); btdp.append("V", version); - - { - auto subdict = btdp.append_dict("B"); - - for (auto& w : whitelist_policy) - w.bt_encode(subdict); - } - btdp.append("X", address_lifetime); btdp.append("Z", sig.ToView()); } @@ -72,8 +55,6 @@ namespace llarp::routing ObtainExitMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) { bool read = false; - if (!BEncodeMaybeReadDictList("B", blacklist_policy, read, k, buf)) - return false; if (!BEncodeMaybeReadDictInt("E", flag, read, k, buf)) return false; if (!BEncodeMaybeReadDictEntry("I", pubkey, read, k, buf)) @@ -84,8 +65,6 @@ namespace llarp::routing return false; if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) return false; - if (!BEncodeMaybeReadDictList("W", whitelist_policy, read, k, buf)) - return false; if (!BEncodeMaybeReadDictInt("X", address_lifetime, read, k, buf)) return false; if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf)) @@ -106,7 +85,6 @@ namespace llarp::routing try { - btdp.append("A", "G"); btdp.append("S", sequence_number); btdp.append("T", tx_id); btdp.append("V", version); @@ -174,16 +152,7 @@ namespace llarp::routing try { - btdp.append("A", "J"); btdp.append("B", backoff_time); - - { - auto subdict = btdp.append_dict("R"); - - for (auto& b : blacklist_policy) - b.bt_encode(subdict); - } - btdp.append("S", sequence_number); btdp.append("T", tx_id); btdp.append("V", version); @@ -204,8 +173,6 @@ namespace llarp::routing bool read = false; if (!BEncodeMaybeReadDictInt("B", backoff_time, read, k, buf)) return false; - if (!BEncodeMaybeReadDictList("R", blacklist_policy, read, k, buf)) - return false; if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf)) return false; if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf)) @@ -255,7 +222,6 @@ namespace llarp::routing try { - btdp.append("A", "V"); btdp.append("P", path_id.ToView()); btdp.append("S", sequence_number); btdp.append("T", tx_id); @@ -322,7 +288,6 @@ namespace llarp::routing try { - btdp.append("A", "V"); btdp.append("S", sequence_number); btdp.append("T", tx_id); btdp.append("V", version); diff --git a/llarp/exit/exit_messages.hpp b/llarp/exit/exit_messages.hpp index 18e04187ed..0bc9573314 100644 --- a/llarp/exit/exit_messages.hpp +++ b/llarp/exit/exit_messages.hpp @@ -10,11 +10,9 @@ namespace llarp::routing { struct ObtainExitMessage final : public AbstractRoutingMessage { - std::vector blacklist_policy; uint64_t flag{0}; // 0 for snode, 1 for internet access llarp::PubKey pubkey; uint64_t tx_id{0}; - std::vector whitelist_policy; uint64_t address_lifetime{0}; llarp::Signature sig; @@ -26,11 +24,9 @@ namespace llarp::routing void clear() override { - blacklist_policy.clear(); flag = 0; pubkey.Zero(); tx_id = 0; - whitelist_policy.clear(); address_lifetime = 0; sig.Zero(); } @@ -88,7 +84,6 @@ namespace llarp::routing { using Nonce_t = llarp::AlignedBuffer<16>; uint64_t backoff_time; - std::vector blacklist_policy; uint64_t tx_id; Nonce_t nonce; llarp::Signature sig; @@ -97,7 +92,6 @@ namespace llarp::routing clear() override { backoff_time = 0; - blacklist_policy.clear(); tx_id = 0; nonce.Zero(); sig.Zero(); diff --git a/llarp/exit/session.cpp b/llarp/exit/session.cpp index 58112dbc83..638a1c716e 100644 --- a/llarp/exit/session.cpp +++ b/llarp/exit/session.cpp @@ -159,14 +159,14 @@ namespace llarp::exit const static auto roles = llarp::path::ePathRoleExit | llarp::path::ePathRoleSVC; if (p->SupportsAnyRoles(roles)) { - llarp::LogInfo(p->Name(), " closing exit path"); + llarp::LogInfo(p->name(), " closing exit path"); routing::CloseExitMessage msg; if (msg.Sign(m_ExitIdentity) && p->SendExitClose(msg, router)) { p->ClearRoles(roles); } else - llarp::LogWarn(p->Name(), " failed to send exit close message"); + llarp::LogWarn(p->name(), " failed to send exit close message"); } }; ForEachPath(sendExitClose); @@ -180,10 +180,10 @@ namespace llarp::exit auto sendExitClose = [&](const path::Path_ptr p) { if (p->SupportsAnyRoles(path::ePathRoleExit)) { - LogInfo(p->Name(), " closing exit path"); + LogInfo(p->name(), " closing exit path"); routing::CloseExitMessage msg; if (!(msg.Sign(m_ExitIdentity) && p->SendExitClose(msg, router))) - LogWarn(p->Name(), " failed to send exit close message"); + LogWarn(p->name(), " failed to send exit close message"); } }; ForEachPath(sendExitClose); diff --git a/llarp/exit/session.hpp b/llarp/exit/session.hpp index 9c556e147f..f6b342fda9 100644 --- a/llarp/exit/session.hpp +++ b/llarp/exit/session.hpp @@ -210,7 +210,7 @@ namespace llarp std::string Name() const override; - virtual void + void SendPacketToRemote(const llarp_buffer_t& pkt, service::ProtocolType t) override; protected: @@ -239,7 +239,7 @@ namespace llarp std::string Name() const override; - virtual void + void SendPacketToRemote(const llarp_buffer_t& pkt, service::ProtocolType t) override; protected: diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 317c956b0c..967698c54e 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -3,6 +3,8 @@ #include "contacts.hpp" #include +#include +#include #include #include #include @@ -198,6 +200,13 @@ namespace llarp }; } + if (func) + { + func = [this, f = std::move(func)](oxen::quic::message m) mutable { + router.loop()->call([func = std::move(f), msg = std::move(m)]() mutable { func(msg); }); + }; + } + return send_control_message_impl(remote, std::move(endpoint), std::move(body), std::move(func)); } @@ -211,22 +220,14 @@ namespace llarp if (is_stopping) return false; - // DISCUSS: uncomment this if we want to excecute two callbacks - // auto cb = [this, f = std::move(func), endpoint](oxen::quic::message m) { - // f(m); - - // if (auto itr = rpc_responses.find(endpoint); itr != rpc_responses.end()) - // std::invoke(itr->second, this, std::move(m)); - // }; - if (auto conn = ep.get_conn(remote); conn) { conn->control_stream->command(endpoint, body, std::move(func)); return true; } - router.loop()->call([&]() { - auto pending = PendingControlMessage(body, endpoint, func); + router.loop()->call([this, remote, endpoint, body, f = std::move(func)]() { + auto pending = PendingControlMessage(body, endpoint, f); auto [itr, b] = pending_conn_msg_queue.emplace(remote, MessageQueue()); itr->second.push_back(std::move(pending)); @@ -547,7 +548,7 @@ namespace llarp router.rpc_client()->lookup_ons_hash( name_hash, [this, msg = std::move(m)](std::optional maybe) mutable { if (maybe.has_value()) - msg.respond(serialize_response({{"NAME", maybe->ciphertext.c_str()}})); + msg.respond(serialize_response({{"NAME", maybe->ciphertext}})); else msg.respond(serialize_response({{"STATUS", FindNameMessage::NOT_FOUND}}), true); }); @@ -600,14 +601,14 @@ namespace llarp LinkManager::handle_find_router(oxen::quic::message m) { std::string target_key; - uint64_t is_exploratory, is_iterative; + bool is_exploratory, is_iterative; try { oxenc::bt_dict_consumer btdc{m.body()}; - is_exploratory = btdc.require("E"); - is_iterative = btdc.require("I"); + is_exploratory = btdc.require("E"); + is_iterative = btdc.require("I"); target_key = btdc.require("K"); } catch (const std::exception& e) @@ -642,8 +643,7 @@ namespace llarp } m.respond( - serialize_response( - {{"STATUS", FindRouterMessage::RETRY_EXP}, {"RECIPIENT", neighbors.c_str()}}), + serialize_response({{"STATUS", FindRouterMessage::RETRY_EXP}, {"RECIPIENT", neighbors}}), true); } else @@ -661,7 +661,7 @@ namespace llarp } else { - m.respond(serialize_response({{"RC", closest_rc.ToString().c_str()}})); + m.respond(serialize_response({{"RC", closest_rc.ToString()}})); } } else if (not is_iterative) @@ -735,6 +735,7 @@ namespace llarp } RouterID target{reinterpret_cast(payload.data())}; + if (status == FindRouterMessage::RETRY_EXP) { log::critical(link_cat, "FindRouterMessage failed, retrying as exploratory!"); @@ -1034,6 +1035,36 @@ namespace llarp } } + void + LinkManager::handle_path_build(oxen::quic::message m) + { + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); + return; + } + } + + void + LinkManager::handle_path_build_response(oxen::quic::message m) + { + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + // m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); + return; + } + } + void LinkManager::handle_path_confirm(oxen::quic::message m) { @@ -1049,6 +1080,21 @@ namespace llarp } } + void + LinkManager::handle_path_confirm_response(oxen::quic::message m) + { + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + // m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); + return; + } + } + void LinkManager::handle_path_latency(oxen::quic::message m) { @@ -1065,7 +1111,37 @@ namespace llarp } void - LinkManager::handle_update_exit(oxen::quic::message m) + LinkManager::handle_path_latency_response(oxen::quic::message m) + { + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + // m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); + return; + } + } + + void + LinkManager::handle_path_transfer(oxen::quic::message m) + { + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); + return; + } + } + + void + LinkManager::handle_path_transfer_response(oxen::quic::message m) { try { @@ -1083,17 +1159,40 @@ namespace llarp LinkManager::handle_obtain_exit(oxen::quic::message m) { // TODO: implement transit_hop things like nextseqno(), info.rxID, etc - std::string payload{m.body_str()}, pubkey; - [[maybe_unused]] uint64_t flag, tx_id, seq_no; + std::string copy{m.body_str()}; + ustring pubkey, signature; + uint64_t flag, tx_id, seq_no; try { - oxenc::bt_dict_consumer btdc{payload}; + oxenc::bt_dict_consumer btdc{copy}; flag = btdc.require("E"); - pubkey = btdc.require("I"); + pubkey = btdc.require("I"); seq_no = btdc.require("S"); tx_id = btdc.require("T"); + signature = btdc.require("Z"); + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + m.respond(serialize_response({{"STATUS", ObtainExit::EXCEPTION}}), true); + return; + } + + RouterID target{pubkey.data()}; + + if (CryptoManager::instance()->verify( + pubkey.data(), reinterpret_cast(copy.data()), copy.size(), signature.data())) + {} + } + + void + LinkManager::handle_obtain_exit_response(oxen::quic::message m) + { + try + { + oxenc::bt_dict_consumer btdc{m.body()}; } catch (const std::exception& e) { @@ -1101,11 +1200,36 @@ namespace llarp m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); return; } + } - RouterID target; - target.FromString(pubkey); + void + LinkManager::handle_update_exit(oxen::quic::message m) + { + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); + return; + } + } - // auto handler = router.path_context().GetByDownstream(target, tx_id); + void + LinkManager::handle_update_exit_response(oxen::quic::message m) + { + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); + return; + } } void @@ -1124,6 +1248,17 @@ namespace llarp } void - LinkManager::handle_path_build(oxen::quic::message) - {} + LinkManager::handle_close_exit_response(oxen::quic::message m) + { + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); + return; + } + } } // namespace llarp diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index c337a10a2f..92e0529a87 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -289,10 +289,11 @@ namespace llarp // Path messages void handle_path_build(oxen::quic::message); // relay - void handle_relay_status(oxen::quic::message); // relay void handle_path_confirm(oxen::quic::message); // relay void handle_path_latency(oxen::quic::message); // relay void handle_path_transfer(oxen::quic::message); // relay + void handle_relay_commit(oxen::quic::message); // relay + void handle_relay_status(oxen::quic::message); // relay // Exit messages void handle_obtain_exit(oxen::quic::message); // relay @@ -319,6 +320,7 @@ namespace llarp // Path responses void handle_path_build_response(oxen::quic::message); + void handle_relay_commit_response(oxen::quic::message); void handle_relay_status_response(oxen::quic::message); void handle_path_confirm_response(oxen::quic::message); void handle_path_latency_response(oxen::quic::message); diff --git a/llarp/messages/common.hpp b/llarp/messages/common.hpp index 32fd492833..e230b4a89b 100644 --- a/llarp/messages/common.hpp +++ b/llarp/messages/common.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include diff --git a/llarp/messages/dht.hpp b/llarp/messages/dht.hpp index 48aed8db3b..9204e1b9f0 100644 --- a/llarp/messages/dht.hpp +++ b/llarp/messages/dht.hpp @@ -6,10 +6,10 @@ namespace llarp { namespace FindRouterMessage { - inline const char* EXCEPTION = "EXCEPTION"; - inline const char* RETRY_EXP = "RETRY AS EXPLORATORY"; - inline const char* RETRY_ITER = "RETRY AS ITERATIVE"; - inline const char* RETRY_NEW = "RETRY WITH NEW RECIPIENT"; + inline auto EXCEPTION = "EXCEPTION"sv; + inline auto RETRY_EXP = "RETRY AS EXPLORATORY"sv; + inline auto RETRY_ITER = "RETRY AS ITERATIVE"sv; + inline auto RETRY_NEW = "RETRY WITH NEW RECIPIENT"sv; inline static std::string serialize(const RouterID& rid, bool is_iterative, bool is_exploratory, uint64_t tx_id) @@ -18,7 +18,6 @@ namespace llarp try { - btdp.append("A", "R"); btdp.append("E", is_exploratory); btdp.append("I", is_iterative); btdp.append("K", rid.ToView()); @@ -35,10 +34,10 @@ namespace llarp namespace FindIntroMessage { - inline const char* EXCEPTION = "EXCEPTION"; - inline const char* NOT_FOUND = "NOT FOUND"; - inline const char* INVALID_ORDER = "INVALID ORDER"; - inline const char* INSUFFICIENT_NODES = "INSUFFICIENT NODES"; + inline auto EXCEPTION = "EXCEPTION"sv; + inline auto NOT_FOUND = "NOT FOUND"sv; + inline auto INVALID_ORDER = "INVALID ORDER"sv; + inline auto INSUFFICIENT_NODES = "INSUFFICIENT NODES"sv; inline static std::string serialize( @@ -48,7 +47,6 @@ namespace llarp try { - btdp.append("A", "F"); btdp.append("N", tag); btdp.append("O", order); btdp.append("R", is_relayed ? 1 : 0); @@ -66,8 +64,8 @@ namespace llarp namespace FindNameMessage { - inline const char* EXCEPTION = "EXCEPTION"; - inline const char* NOT_FOUND = "NOT FOUND"; + inline auto EXCEPTION = "EXCEPTION"sv; + inline auto NOT_FOUND = "NOT FOUND"sv; inline static std::string serialize([[maybe_unused]] const dht::Key_t& from, dht::Key_t name_hash, uint64_t tx_id) @@ -76,7 +74,6 @@ namespace llarp try { - btdp.append("A", "N"); btdp.append("H", name_hash.ToView()); btdp.append("T", tx_id); } @@ -91,11 +88,11 @@ namespace llarp namespace PublishIntroMessage { - inline const char* EXCEPTION = "EXCEPTION"; - inline const char* INVALID_INTROSET = "INVALID INTROSET"; - inline const char* EXPIRED = "EXPIRED INTROSET"; - inline const char* INSUFFICIENT = "INSUFFICIENT NODES"; - inline const char* INVALID_ORDER = "INVALID ORDER"; + inline auto EXCEPTION = "EXCEPTION"sv; + inline auto INVALID_INTROSET = "INVALID INTROSET"sv; + inline auto EXPIRED = "EXPIRED INTROSET"sv; + inline auto INSUFFICIENT = "INSUFFICIENT NODES"sv; + inline auto INVALID_ORDER = "INVALID ORDER"sv; inline static std::string serialize(std::string introset, uint64_t relay_order, uint64_t is_relayed, uint64_t tx_id) @@ -104,7 +101,6 @@ namespace llarp try { - btdp.append("A", "I"); btdp.append("I", introset); btdp.append("O", relay_order); btdp.append("R", is_relayed); diff --git a/llarp/messages/exit.hpp b/llarp/messages/exit.hpp new file mode 100644 index 0000000000..bbe5c0df4d --- /dev/null +++ b/llarp/messages/exit.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "common.hpp" + +namespace llarp +{ + namespace ObtainExit + { + inline auto EXCEPTION = "EXCEPTION"sv; + + } + + namespace UpdateExit + { + inline auto EXCEPTION = "EXCEPTION"sv; + + } + + namespace CloseExit + { + inline auto EXCEPTION = "EXCEPTION"sv; + + } + +} // namespace llarp diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index a548259c00..3dae963b98 100644 --- a/llarp/messages/path.hpp +++ b/llarp/messages/path.hpp @@ -4,22 +4,119 @@ namespace llarp { - struct PathMessage : public AbstractSerializable - {}; + namespace PathBuildMessage + { + inline static void + setup_hop_keys(path::PathHopConfig& hop, const RouterID& nextHop) + { + auto crypto = CryptoManager::instance(); - struct RelayCommitMessage : public PathMessage - {}; + // generate key + crypto->encryption_keygen(hop.commkey); - struct RelayStatusMessage : public PathMessage - {}; + hop.nonce.Randomize(); + // do key exchange + 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::error(path_cat, err); + throw std::runtime_error{std::move(err)}; + } + // generate nonceXOR value self->hop->pathKey + crypto->shorthash(hop.nonceXOR, hop.shared.data(), hop.shared.size()); - struct PathConfirmMessage : public PathMessage - {}; + hop.upstream = nextHop; + } - struct PathLatencyMessage : public PathMessage - {}; + inline static std::string + serialize(const path::PathHopConfig& hop) + { + auto crypto = CryptoManager::instance(); - struct PathTransferMessage : public PathMessage - {}; + std::string hop_info; + + { + oxenc::bt_dict_producer btdp; + + btdp.append("lifetime", path::DEFAULT_LIFETIME.count()); + btdp.append("txid", hop.txID.ToView()); + btdp.append("rxid", hop.rxID.ToView()); + btdp.append("nonce", hop.nonce.ToView()); + btdp.append("next", hop.upstream.ToView()); + btdp.append("commkey", hop.commkey.toPublic().ToView()); + + hop_info = std::move(btdp).str(); + } + + SecretKey framekey; + crypto->encryption_keygen(framekey); + + SharedSecret shared; + TunnelNonce outer_nonce; + outer_nonce.Randomize(); + + // derive (outer) shared key + 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"}; + } + + // encrypt hop_info (mutates in-place) + if (!crypto->xchacha20( + reinterpret_cast(hop_info.data()), hop_info.size(), shared, outer_nonce)) + { + log::error(path_cat, "Hop info encryption failed!"); + throw std::runtime_error{"Hop info encrypttion failed"}; + } + + std::string hashed_data; + + { + oxenc::bt_dict_producer btdp; + + btdp.append("encrypted", hop_info); + btdp.append("pubkey", framekey.toPublic().ToView()); + btdp.append("nonce", outer_nonce.ToView()); + + hashed_data = std::move(btdp).str(); + } + + std::string hash; + hash.reserve(SHORTHASHSIZE); + + if (!crypto->hmac( + reinterpret_cast(hash.data()), + reinterpret_cast(hashed_data.data()), + hashed_data.size(), + shared)) + { + log::error(path_cat, "Failed to generate HMAC for hop info"); + throw std::runtime_error{"Failed to generate HMAC for hop info"}; + } + + oxenc::bt_dict_producer btdp; + + btdp.append("hash", hash); + btdp.append("frame", hashed_data); + + return std::move(btdp).str(); + } + } // namespace PathBuildMessage + + namespace RelayCommitMessage + {} + + namespace RelayStatusMessage + {} + + namespace PathConfirmMessage + {} + + namespace PathLatencyMessage + {} + + namespace PathTransferMessage + {} } // namespace llarp diff --git a/llarp/messages/relay_commit.cpp b/llarp/messages/relay_commit.cpp index ca5784f169..529bd96ab7 100644 --- a/llarp/messages/relay_commit.cpp +++ b/llarp/messages/relay_commit.cpp @@ -308,9 +308,9 @@ namespace llarp } // persist sessions to upstream and downstream routers until the commit // ends - self->context->router()->PersistSessionUntil( + self->context->router()->persist_connection_until( self->hop->info.downstream, self->hop->ExpireTime() + 10s); - self->context->router()->PersistSessionUntil( + self->context->router()->persist_connection_until( self->hop->info.upstream, self->hop->ExpireTime() + 10s); // put hop self->context->PutTransitHop(self->hop); @@ -345,7 +345,7 @@ namespace llarp else { // persist session to downstream until path expiration - self->context->router()->PersistSessionUntil( + self->context->router()->persist_connection_until( self->hop->info.downstream, self->hop->ExpireTime() + 10s); // put hop self->context->PutTransitHop(self->hop); diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 2d57d5d2e1..6f0a61c777 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -1,6 +1,5 @@ #include "path.hpp" -#include #include #include #include @@ -114,13 +113,13 @@ namespace llarp::path } bool - Path::IsEndpoint(const RouterID& r, const PathID_t& id) const + 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; } RouterID - Path::Upstream() const + Path::upstream() const { return hops[0].rc.pubkey; } @@ -206,7 +205,7 @@ namespace llarp::path { r->notify_router_event(Endpoint(), RXID(), *failedAt); LogWarn( - Name(), + name(), " build failed at ", *failedAt, " status=", @@ -302,16 +301,16 @@ namespace llarp::path } else if (st == ePathBuilding) { - LogInfo("path ", Name(), " is building"); + LogInfo("path ", name(), " is building"); buildStarted = now; } else if (st == ePathEstablished && _status == ePathBuilding) { - LogInfo("path ", Name(), " is built, took ", ToString(now - buildStarted)); + LogInfo("path ", name(), " is built, took ", ToString(now - buildStarted)); } else if (st == ePathTimeout && _status == ePathEstablished) { - LogInfo("path ", Name(), " died"); + LogInfo("path ", name(), " died"); _status = st; if (auto parent = m_PathSet.lock()) { @@ -320,11 +319,11 @@ namespace llarp::path } else if (st == ePathEstablished && _status == ePathTimeout) { - LogInfo("path ", Name(), " reanimated"); + LogInfo("path ", name(), " reanimated"); } else if (st == ePathIgnore) { - LogInfo("path ", Name(), " ignored"); + LogInfo("path ", name(), " ignored"); } _status = st; } @@ -404,7 +403,7 @@ namespace llarp::path std::vector newHops; for (const auto& hop : hops) newHops.emplace_back(hop.rc); - LogInfo(Name(), " rebuilding on ", ShortName()); + LogInfo(name(), " rebuilding on ", ShortName()); parent->Build(newHops); } } @@ -419,7 +418,7 @@ namespace llarp::path latency.sequence_number = NextSeqNo(); m_LastLatencyTestID = latency.sent_time; m_LastLatencyTestTime = now; - LogDebug(Name(), " send latency test id=", latency.sent_time); + LogDebug(name(), " send latency test id=", latency.sent_time); if (not SendRoutingMessage(latency, r)) return false; FlushUpstream(r); @@ -447,7 +446,7 @@ namespace llarp::path const auto dlt = now - buildStarted; if (dlt >= path::BUILD_TIMEOUT) { - LogWarn(Name(), " waited for ", ToString(dlt), " and no path was built"); + LogWarn(name(), " waited for ", ToString(dlt), " and no path was built"); r->router_profiling().MarkPathFail(this); EnterState(ePathExpired, now); return; @@ -471,7 +470,7 @@ namespace llarp::path dlt = now - m_LastRecvMessage; if (dlt >= path::ALIVE_TIMEOUT) { - LogWarn(Name(), " waited for ", ToString(dlt), " and path looks dead"); + LogWarn(name(), " waited for ", ToString(dlt), " and path looks dead"); r->router_profiling().MarkPathFail(this); EnterState(ePathTimeout, now); } @@ -488,13 +487,13 @@ namespace llarp::path { for (const auto& msg : msgs) { - if (r->send_data_message(Upstream(), msg)) + if (r->send_data_message(upstream(), msg)) { m_TXRate += msg.enc.size(); } else { - LogDebug("failed to send upstream to ", Upstream()); + LogDebug("failed to send upstream to ", upstream()); } } r->TriggerPump(); @@ -572,7 +571,7 @@ namespace llarp::path } std::string - Path::Name() const + Path::name() const { return fmt::format("TX={} RX={}", TXID(), RXID()); } @@ -725,7 +724,7 @@ namespace llarp::path r->router_profiling().MarkPathSuccess(this); // persist session with upstream router until the path is done - r->PersistSessionUntil(Upstream(), intro.expiry); + r->persist_connection_until(upstream(), intro.expiry); MarkActive(now); return SendLatencyMessage(r); } @@ -808,22 +807,22 @@ namespace llarp::path { if (msg.Verify(EndpointPubKey())) { - LogInfo(Name(), " had its exit closed"); + LogInfo(name(), " had its exit closed"); _role &= ~ePathRoleExit; return true; } - LogError(Name(), " CXM from exit with bad signature"); + LogError(name(), " CXM from exit with bad signature"); } else - LogError(Name(), " unwarranted CXM"); + LogError(name(), " unwarranted CXM"); return false; } bool Path::SendExitRequest(const routing::ObtainExitMessage& msg, Router* r) { - LogInfo(Name(), " sending exit request to ", Endpoint()); + LogInfo(name(), " sending exit request to ", Endpoint()); m_ExitObtainTX = msg.tx_id; return SendRoutingMessage(msg, r); } @@ -831,7 +830,7 @@ namespace llarp::path bool Path::SendExitClose(const routing::CloseExitMessage& msg, Router* r) { - LogInfo(Name(), " closing exit to ", Endpoint()); + LogInfo(name(), " closing exit to ", Endpoint()); // mark as not exit anymore _role &= ~ePathRoleExit; return SendRoutingMessage(msg, r); @@ -842,7 +841,7 @@ namespace llarp::path { (void)msg; (void)r; - LogError(Name(), " got unwarranted OXM"); + LogError(name(), " got unwarranted OXM"); return false; } @@ -851,7 +850,7 @@ namespace llarp::path { (void)msg; (void)r; - LogError(Name(), " got unwarranted UXM"); + LogError(name(), " got unwarranted UXM"); return false; } @@ -862,14 +861,14 @@ namespace llarp::path { if (!msg.Verify(EndpointPubKey())) { - LogError(Name(), "RXM invalid signature"); + LogError(name(), "RXM invalid signature"); return false; } - LogInfo(Name(), " ", Endpoint(), " Rejected exit"); + LogInfo(name(), " ", Endpoint(), " Rejected exit"); MarkActive(r->now()); return InformExitResult(llarp_time_t(msg.backoff_time)); } - LogError(Name(), " got unwarranted RXM"); + LogError(name(), " got unwarranted RXM"); return false; } @@ -880,16 +879,16 @@ namespace llarp::path { if (!msg.Verify(EndpointPubKey())) { - LogError(Name(), " GXM signature failed"); + LogError(name(), " GXM signature failed"); return false; } // we now can send exit traffic _role |= ePathRoleExit; - LogInfo(Name(), " ", Endpoint(), " Granted exit"); + LogInfo(name(), " ", Endpoint(), " Granted exit"); MarkActive(r->now()); return InformExitResult(0s); } - LogError(Name(), " got unwarranted GXM"); + LogError(name(), " got unwarranted GXM"); return false; } diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 55483f7faf..eee576ad0f 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -34,16 +34,10 @@ namespace llarp { struct TransitHop; struct TransitHopInfo; + struct PathHopConfig; using TransitHop_ptr = std::shared_ptr; - inline bool - operator<(const PathHopConfig& lhs, const PathHopConfig& rhs) - { - return std::tie(lhs.txID, lhs.rxID, lhs.rc, lhs.upstream, lhs.lifetime) - < std::tie(rhs.txID, rhs.rxID, rhs.rc, rhs.upstream, rhs.lifetime); - } - /// A path we made struct Path final : public AbstractHopHandler, public routing::AbstractRoutingMessageHandler, @@ -330,16 +324,16 @@ namespace llarp EndpointPubKey() const; bool - IsEndpoint(const RouterID& router, const PathID_t& path) const; + is_endpoint(const RouterID& router, const PathID_t& path) const; PathID_t RXID() const override; RouterID - Upstream() const; + upstream() const; std::string - Name() const; + name() const; void AddObtainExitHandler(ObtainedExitHandler handler) diff --git a/llarp/path/path_types.hpp b/llarp/path/path_types.hpp index 63a5bb24ec..1a356e063c 100644 --- a/llarp/path/path_types.hpp +++ b/llarp/path/path_types.hpp @@ -1,7 +1,15 @@ #pragma once +#include #include #include +#include +#include + +namespace +{ + static auto path_cat = llarp::log::Cat("lokinet.path"); +} // namespace namespace llarp { @@ -10,6 +18,43 @@ namespace llarp using AlignedBuffer::AlignedBuffer; }; + namespace path + { + /// configuration for a single hop when building a path + struct PathHopConfig + { + /// path id + PathID_t txID, rxID; + // router contact of router + RouterContact rc; + // temp public encryption key + SecretKey commkey; + /// shared secret at this hop + SharedSecret shared; + /// hash of shared secret used for nonce mutation + ShortHash nonceXOR; + /// next hop's router id + RouterID upstream; + /// nonce for key exchange + TunnelNonce nonce; + // lifetime + llarp_time_t lifetime = DEFAULT_LIFETIME; + + util::StatusObject + ExtractStatus() const; + }; + + inline bool + operator<(const PathHopConfig& lhs, const PathHopConfig& rhs) + { + return std::tie(lhs.txID, lhs.rxID, lhs.rc, lhs.upstream, lhs.lifetime) + < std::tie(rhs.txID, rhs.rxID, rhs.rc, rhs.upstream, rhs.lifetime); + } + + // milliseconds waiting between builds on a path per router + static constexpr auto MIN_PATH_BUILD_INTERVAL = 500ms; + static constexpr auto PATH_BUILD_RATE = 100ms; + } // namespace path } // namespace llarp namespace std diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index d34d9eb881..cbb61b090e 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -2,15 +2,16 @@ #include "path_context.hpp" #include +#include +#include #include #include -#include #include #include #include -#include #include -#include +#include +#include #include @@ -78,7 +79,7 @@ namespace llarp */ void - Builder::SetupHopKeys(path::PathHopConfig& hop, const RouterID& nextHop) + Builder::setup_hop_keys(path::PathHopConfig& hop, const RouterID& nextHop) { auto crypto = CryptoManager::instance(); @@ -89,41 +90,47 @@ namespace llarp // do key exchange if (!crypto->dh_client(hop.shared, hop.rc.pubkey, hop.commkey, hop.nonce)) { - LogError(Name(), " Failed to generate shared key for path build"); - throw std::runtime_error{"Failed to generate shared key for path build"}; + auto err = fmt::format("{} failed to generate shared key for path build!", Name()); + log::error(path_cat, err); + throw std::runtime_error{std::move(err)}; } // generate nonceXOR value self->hop->pathKey - crypto->shorthash(hop.nonceXOR, llarp_buffer_t(hop.shared)); + crypto->shorthash(hop.nonceXOR, hop.shared.data(), hop.shared.size()); hop.upstream = nextHop; } - // FIXME: this is definitely not optimal using bt_dict instead of bt_dict_producer, among other - // things std::string - Builder::CreateHopInfoFrame(const path::PathHopConfig& hop) + Builder::create_hop_info_frame(const path::PathHopConfig& hop) { auto crypto = CryptoManager::instance(); - oxenc::bt_dict hop_info_dict; - hop_info_dict["lifetime"] = path::DEFAULT_LIFETIME.count(); // milliseconds - hop_info_dict["txid"] = hop.txID; - hop_info_dict["rxid"] = hop.rxID; - hop_info_dict["nonce"] = hop.nonce; - hop_info_dict["next"] = hop.upstream; - hop_info_dict["commkey"] = hop.commkey.toPublic(); // pubkey of ephemeral Ed key for DH + std::string hop_info; + + { + oxenc::bt_dict_producer btdp; + + btdp.append("lifetime", path::DEFAULT_LIFETIME.count()); + btdp.append("txid", hop.txID.ToView()); + btdp.append("rxid", hop.rxID.ToView()); + btdp.append("nonce", hop.nonce.ToView()); + btdp.append("next", hop.upstream.ToView()); + btdp.append("commkey", hop.commkey.toPublic().ToView()); + + hop_info = std::move(btdp).str(); + } - auto hop_info = oxenc::bt_serialize(hop_info_dict); SecretKey framekey; crypto->encryption_keygen(framekey); SharedSecret shared; TunnelNonce outer_nonce; outer_nonce.Randomize(); + // derive (outer) shared key if (!crypto->dh_client(shared, hop.rc.pubkey, framekey, outer_nonce)) { - llarp::LogError("DH failed during hop info encryption"); + log::error(path_cat, "DH client failed during hop info encryption!"); throw std::runtime_error{"DH failed during hop info encryption"}; } @@ -131,31 +138,41 @@ namespace llarp if (!crypto->xchacha20( reinterpret_cast(hop_info.data()), hop_info.size(), shared, outer_nonce)) { - llarp::LogError("hop info encrypt failed"); - throw std::runtime_error{"hop info encrypt failed"}; + log::error(path_cat, "Hop info encryption failed!"); + throw std::runtime_error{"Hop info encrypttion failed"}; } - oxenc::bt_dict hashed_dict; - hashed_dict["encrypted"] = hop_info; - hashed_dict["pubkey"] = framekey.toPublic(); - hashed_dict["nonce"] = nonce; - auto hashed_data = oxenc::bt_serialize(hashed_dict); - std::basic_string hash{SHORTHASHSIZE, '\0'}; + std::string hashed_data; + + { + oxenc::bt_dict_producer btdp; + + btdp.append("encrypted", hop_info); + btdp.append("pubkey", framekey.toPublic().ToView()); + btdp.append("nonce", outer_nonce.ToView()); + + hashed_data = std::move(btdp).str(); + } + + std::string hash; + hash.reserve(SHORTHASHSIZE); + if (!crypto->hmac( - hash.data(), + reinterpret_cast(hash.data()), reinterpret_cast(hashed_data.data()), hashed_data.size(), shared)) { - llarp::LogError("Failed to generate HMAC for hop info"); + log::error(path_cat, "Failed to generate HMAC for hop info"); throw std::runtime_error{"Failed to generate HMAC for hop info"}; } - oxenc::bt_dict final_frame; - final_frame["hash"] = hash; - final_frame["frame"] = hashed_data; + oxenc::bt_dict_producer btdp; - return oxenc::bt_serialize(final_frame); + btdp.append("hash", hash); + btdp.append("frame", hashed_data); + + return std::move(btdp).str(); } void @@ -386,63 +403,83 @@ namespace llarp Builder::Build(std::vector hops, PathRole roles) { if (IsStopped()) + { + log::info(path_cat, "Path builder is stopped, aborting path build..."); return; - lastBuild = Now(); + } + + lastBuild = llarp::time_now_ms(); const RouterID edge{hops[0].pubkey}; + if (not router->pathbuild_limiter().Attempt(edge)) { - LogWarn(Name(), " building too fast to edge router ", edge); + log::warning(path_cat, "{} building too quickly to edge router {}", Name(), edge); return; } std::string path_shortName = "[path " + router->ShortName() + "-"; path_shortName = path_shortName + std::to_string(router->NextPathBuildNumber()) + "]"; auto path = std::make_shared(hops, GetWeak(), roles, std::move(path_shortName)); - LogInfo(Name(), " build ", path->ShortName(), ": ", path->HopsString()); + + log::info( + path_cat, "{} building path -> {} : {}", Name(), path->ShortName(), path->HopsString()); oxenc::bt_list_producer frames; + auto& path_hops = path->hops; + size_t n_hops = path_hops.size(); size_t last_len{0}; - for (size_t i = 0; i < path_hops.size(); i++) + + for (size_t i = 0; i < n_hops; i++) { - bool lastHop = (i == (path_hops.size() - 1)); + bool lastHop = (i == (n_hops - 1)); + const auto& nextHop = lastHop ? path_hops[i].rc.pubkey : path_hops[i + 1].rc.pubkey; - SetupHopKeys(path_hops[i], nextHop); - auto frame_str = CreateHopInfoFrame(path_hops[i]); + + // TODO: talk to Tom about what he thinks about this + PathBuildMessage::setup_hop_keys(path_hops[i], nextHop); + auto frame_str = PathBuildMessage::serialize(path_hops[i]); + + // all frames should be the same length...not sure what that is yet if (last_len != 0) - assert( - frame_str.size() - == last_len); // all frames should be the same length...not sure what that is yet + assert(frame_str.size() == last_len); + last_len = frame_str.size(); - frames.append(frame_str); + frames.append(std::move(frame_str)); } - std::string dummy{last_len, '\0'}; + std::string dummy; + dummy.reserve(last_len); + // append dummy frames; path build request must always have MAX_LEN frames - for (size_t i = 0; i < path::MAX_LEN - path_hops.size(); i++) + for (size_t i = 0; i < path::MAX_LEN - n_hops; i++) { randombytes(reinterpret_cast(dummy.data()), dummy.size()); frames.append(dummy); } - m_router->notify_router_event(m_router->pubkey(), path); + // TODO: talk to Tom about whether we do still this or not + // router->notify_router_event(router->pubkey(), path); auto self = GetSelf(); - m_router->path_context().AddOwnPath(self, path); + router->path_context().AddOwnPath(self, path); PathBuildStarted(path); - auto response_cb = [self](oxen::quic::message m) { + auto response_cb = [self](oxen::quic::message) { // TODO: this (replaces handling LRSM, which also needs replacing) + + // TODO: Talk to Tom about why are we using it as a response callback? + // Do you mean TransitHop::HandleLRSM? }; - if (not m_router->send_control_message( - path->Upstream(), "path_build", std::move(frames.str()), std::move(response_cb))) + if (not router->send_control_message( + path->upstream(), "path_build", std::move(frames).str(), std::move(response_cb))) { log::warning(log_path, "Error sending path_build control message"); - path->EnterState(path::ePathFailed, m_router->now()); + path->EnterState(path::ePathFailed, router->now()); } - m_router->PersistSessionUntil(path->Upstream(), path->ExpireTime()); + router->persist_connection_until(path->upstream(), path->ExpireTime()); } void @@ -451,7 +488,7 @@ namespace llarp buildIntervalLimit = PATH_BUILD_RATE; router->router_profiling().MarkPathSuccess(p.get()); - LogInfo(p->Name(), " built latency=", ToString(p->intro.latency)); + LogInfo(p->name(), " built latency=", ToString(p->intro.latency)); m_BuildStats.success++; } @@ -479,24 +516,25 @@ namespace llarp DoPathBuildBackoff(); for (const auto& hop : p->hops) { - const RouterID router{hop.rc.pubkey}; + const RouterID rid{hop.rc.pubkey}; // look up router and see if it's still on the network - router->loop()->call_soon([router, r = router]() { - LogInfo("looking up ", router, " because of path build timeout"); + router->loop()->call_soon([rid, r = router]() { + log::info(path_cat, "Looking up RouterID {} due to path build timeout", rid); r->rc_lookup_handler().get_rc( - router, - [r](const auto& router, const auto* rc, auto result) { + rid, + [r](const auto& rid, const auto* rc, auto result) { if (result == RCRequestResult::Success && rc != nullptr) { - LogInfo("refreshed rc for ", router); + log::info(path_cat, "Refreshed RouterContact for {}", rid); + ; r->node_db()->PutIfNewer(*rc); } else { // remove all connections to this router as it's probably not registered anymore - LogWarn("removing router ", router, " because of path build timeout"); - r->link_manager().deregister_peer(router); - r->node_db()->Remove(router); + log::warning(path_cat, "Removing router {} due to path build timeout", rid); + r->link_manager().deregister_peer(rid); + r->node_db()->Remove(rid); } }, true); diff --git a/llarp/path/pathbuilder.hpp b/llarp/path/pathbuilder.hpp index 6731c352ad..f79e9d8431 100644 --- a/llarp/path/pathbuilder.hpp +++ b/llarp/path/pathbuilder.hpp @@ -10,35 +10,6 @@ namespace llarp::path { - - /// configuration for a single hop when building a path - struct PathHopConfig - { - /// path id - PathID_t txID, rxID; - // router contact of router - RouterContact rc; - // temp public encryption key - SecretKey commkey; - /// shared secret at this hop - SharedSecret shared; - /// hash of shared secret used for nonce mutation - ShortHash nonceXOR; - /// next hop's router id - RouterID upstream; - /// nonce for key exchange - TunnelNonce nonce; - // lifetime - llarp_time_t lifetime = DEFAULT_LIFETIME; - - util::StatusObject - ExtractStatus() const; - }; - - // milliseconds waiting between builds on a path per router - static constexpr auto MIN_PATH_BUILD_INTERVAL = 500ms; - static constexpr auto PATH_BUILD_RATE = 100ms; - /// limiter for path builds /// prevents overload and such class BuildLimiter @@ -81,10 +52,10 @@ namespace llarp::path DoPathBuildBackoff(); void - SetupHopKeys(path::PathHopConfig& hop, const RouterID& nextHop); + setup_hop_keys(path::PathHopConfig& hop, const RouterID& nextHop); std::string - CreateHopInfoFrame(const path::PathHopConfig& hop); + create_hop_info_frame(const path::PathHopConfig& hop); public: Router* const router; diff --git a/llarp/path/pathset.cpp b/llarp/path/pathset.cpp index 35170bf27b..1985055bda 100644 --- a/llarp/path/pathset.cpp +++ b/llarp/path/pathset.cpp @@ -233,7 +233,7 @@ namespace llarp::path auto itr = m_Paths.begin(); while (itr != m_Paths.end()) { - if (itr->second->IsEndpoint(ep, id)) + if (itr->second->is_endpoint(ep, id)) { return itr->second; } @@ -290,7 +290,7 @@ namespace llarp::path PathSet::AddPath(Path_ptr path) { Lock_t l(m_PathsMutex); - const auto upstream = path->Upstream(); // RouterID + const auto upstream = path->upstream(); // RouterID const auto RXID = path->RXID(); // PathID if (not m_Paths.emplace(std::make_pair(upstream, RXID), path).second) { diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index 513f347a40..4ea12cdbfb 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -90,25 +90,20 @@ namespace llarp::path if (!IsEndpoint(r->pubkey())) return false; - std::array tmp; - llarp_buffer_t buf(tmp); - - auto bte = msg.bt_encode(); - buf.write(bte.begin(), bte.end()); + auto buf = msg.bt_encode(); TunnelNonce N; N.Randomize(); - buf.sz = buf.cur - buf.base; // pad to nearest MESSAGE_PAD_SIZE bytes - auto dlt = buf.sz % PAD_SIZE; + auto dlt = buf.size() % PAD_SIZE; + if (dlt) { dlt = PAD_SIZE - dlt; // randomize padding - CryptoManager::instance()->randbytes(buf.cur, dlt); - buf.sz += dlt; + CryptoManager::instance()->randbytes(reinterpret_cast(buf.data()), dlt); } - buf.cur = buf.base; + return HandleDownstream(buf, N, r); } diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 7aeb346c31..ad42e3027c 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -229,7 +229,7 @@ namespace llarp } void - Router::PersistSessionUntil(const RouterID& remote, llarp_time_t until) + Router::persist_connection_until(const RouterID& remote, llarp_time_t until) { _link_manager.set_conn_persist(remote, until); } diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 777660200a..eafd591864 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -466,7 +466,7 @@ namespace llarp StopLinks(); void - PersistSessionUntil(const RouterID& remote, llarp_time_t until); + persist_connection_until(const RouterID& remote, llarp_time_t until); bool EnsureIdentity(); diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index f02266babc..3269f6cff7 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -711,7 +711,7 @@ namespace llarp { for (size_t i = 0; i < INTROSET_REQS_PER_RELAY; ++i) { - router()->send_control_message(path->Upstream(), "publish_intro", introset.bt_encode()); + router()->send_control_message(path->upstream(), "publish_intro", introset.bt_encode()); } } diff --git a/llarp/service/intro.hpp b/llarp/service/intro.hpp index caf073a785..699da44310 100644 --- a/llarp/service/intro.hpp +++ b/llarp/service/intro.hpp @@ -24,6 +24,7 @@ namespace llarp::service llarp_time_t expiry = 0s; uint64_t version = llarp::constants::proto_version; + Introduction() = default; Introduction(std::string buf); util::StatusObject diff --git a/llarp/service/protocol.cpp b/llarp/service/protocol.cpp index 26b82747a0..7727166613 100644 --- a/llarp/service/protocol.cpp +++ b/llarp/service/protocol.cpp @@ -32,7 +32,7 @@ namespace llarp::service path::Path_ptr path, PathID_t from, std::shared_ptr self) { if (!self->handler->HandleDataMessage(path, from, self)) - LogWarn("failed to handle data message from ", path->Name()); + LogWarn("failed to handle data message from ", path->name()); } bool From 65bd224cf096d211437cf232d5a28a6f0fdd70a7 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Fri, 6 Oct 2023 08:34:50 -0700 Subject: [PATCH 046/312] Exit endpoints implemented - free standing functions in link_manager - sign and serialize functionalities siloed in llarp/messages/exit.hpp --- llarp/crypto/crypto.cpp | 29 ++-- llarp/crypto/crypto.hpp | 16 ++- llarp/exit/exit_messages.cpp | 22 --- llarp/exit/exit_messages.hpp | 19 +-- llarp/link/link_manager.cpp | 251 ++++++++++++++++++++++++++++------- llarp/link/link_manager.hpp | 5 +- llarp/messages/dht.hpp | 1 + llarp/messages/exit.hpp | 160 +++++++++++++++++++++- llarp/path/path.cpp | 16 +++ llarp/path/path.hpp | 19 +++ llarp/path/path_context.cpp | 20 +-- llarp/path/pathbuilder.cpp | 4 - llarp/util/buffer.hpp | 7 + llarp/util/str.cpp | 95 ------------- llarp/util/str.hpp | 52 -------- 15 files changed, 455 insertions(+), 261 deletions(-) diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index 7e0409e0a6..9de7ee666d 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -133,15 +133,6 @@ namespace llarp return crypto_stream_xchacha20_xor(buf, buf, size, n.data(), k.data()) == 0; } - bool - Crypto::xchacha20_alt( - const llarp_buffer_t& out, const llarp_buffer_t& in, const SharedSecret& k, const byte_t* n) - { - if (in.sz > out.sz) - return false; - return crypto_stream_xchacha20_xor(out.base, in.base, in.sz, n, k.data()) == 0; - } - bool Crypto::dh_client( llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n) @@ -195,6 +186,18 @@ namespace llarp return crypto_sign_detached(sig.data(), nullptr, buf, size, secret.data()) != -1; } + bool + Crypto::sign(uint8_t* sig, uint8_t* sk, uint8_t* buf, size_t size) + { + return crypto_sign_detached(sig, nullptr, buf, size, sk) != -1; + } + + bool + Crypto::sign(uint8_t* sig, const SecretKey& sk, ustring_view buf) + { + return crypto_sign_detached(sig, nullptr, buf.data(), buf.size(), sk.data()) != -1; + } + bool Crypto::sign(Signature& sig, const PrivateKey& privkey, uint8_t* buf, size_t size) { @@ -245,6 +248,14 @@ namespace llarp return crypto_sign_verify_detached(sig.data(), buf, size, pub.data()) != -1; } + bool + Crypto::verify(ustring_view pub, ustring_view buf, ustring_view sig) + { + return (pub.size() == 32 && sig.size() == 64) + ? crypto_sign_verify_detached(sig.data(), buf.data(), buf.size(), pub.data()) != -1 + : false; + } + bool Crypto::verify(uint8_t* pub, uint8_t* buf, size_t size, uint8_t* sig) { diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index a1ecbcb32f..fd5adaf4de 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -11,6 +11,12 @@ namespace llarp { + /* + TODO: + - make uint8_t pointers const where needed + - + */ + struct Crypto { Crypto(); @@ -25,10 +31,6 @@ namespace llarp bool xchacha20(uint8_t*, size_t size, const SharedSecret&, const TunnelNonce&); - /// xchacha symmetric cipher (multibuffer) - bool - xchacha20_alt(const llarp_buffer_t&, const llarp_buffer_t&, const SharedSecret&, const byte_t*); - /// path dh creator's side bool dh_client(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&); @@ -50,12 +52,18 @@ namespace llarp /// ed25519 sign bool sign(Signature&, const SecretKey&, uint8_t* buf, size_t size); + /// ed25519 sign, using pointers + bool + sign(uint8_t* sig, uint8_t* sk, uint8_t* buf, size_t size); + bool + sign(uint8_t* sig, const SecretKey& sk, ustring_view buf); /// ed25519 sign (custom with derived keys) bool sign(Signature&, const PrivateKey&, uint8_t* buf, size_t size); /// ed25519 verify bool verify(const PubKey&, uint8_t*, size_t, const Signature&); + bool verify(ustring_view, ustring_view, ustring_view); bool verify(uint8_t*, uint8_t*, size_t, uint8_t*); diff --git a/llarp/exit/exit_messages.cpp b/llarp/exit/exit_messages.cpp index 0d8ac8a9c2..d1536418df 100644 --- a/llarp/exit/exit_messages.cpp +++ b/llarp/exit/exit_messages.cpp @@ -39,8 +39,6 @@ namespace llarp::routing btdp.append("I", pubkey.ToView()); btdp.append("S", sequence_number); btdp.append("T", tx_id); - btdp.append("V", version); - btdp.append("X", address_lifetime); btdp.append("Z", sig.ToView()); } catch (...) @@ -63,10 +61,6 @@ namespace llarp::routing return false; if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf)) return false; - if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("X", address_lifetime, read, k, buf)) - return false; if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf)) return false; return read; @@ -87,7 +81,6 @@ namespace llarp::routing { btdp.append("S", sequence_number); btdp.append("T", tx_id); - btdp.append("V", version); btdp.append("Y", nonce.ToView()); btdp.append("Z", sig.ToView()); } @@ -107,8 +100,6 @@ namespace llarp::routing return false; if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf)) return false; - if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) - return false; if (!BEncodeMaybeReadDictEntry("Y", nonce, read, k, buf)) return false; if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf)) @@ -155,7 +146,6 @@ namespace llarp::routing btdp.append("B", backoff_time); btdp.append("S", sequence_number); btdp.append("T", tx_id); - btdp.append("V", version); btdp.append("Y", nonce.ToView()); btdp.append("Z", sig.ToView()); } @@ -177,8 +167,6 @@ namespace llarp::routing return false; if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf)) return false; - if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) - return false; if (!BEncodeMaybeReadDictEntry("Y", nonce, read, k, buf)) return false; if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf)) @@ -225,7 +213,6 @@ namespace llarp::routing btdp.append("P", path_id.ToView()); btdp.append("S", sequence_number); btdp.append("T", tx_id); - btdp.append("V", version); btdp.append("Z", sig.ToView()); } catch (...) @@ -244,8 +231,6 @@ namespace llarp::routing return false; if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf)) return false; - if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) - return false; if (!BEncodeMaybeReadDictEntry("P", path_id, read, k, buf)) return false; if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf)) @@ -290,7 +275,6 @@ namespace llarp::routing { btdp.append("S", sequence_number); btdp.append("T", tx_id); - btdp.append("V", version); } catch (...) { @@ -308,8 +292,6 @@ namespace llarp::routing return false; if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf)) return false; - if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) - return false; return read; } @@ -326,9 +308,7 @@ namespace llarp::routing try { - btdp.append("A", "C"); btdp.append("S", sequence_number); - btdp.append("V", version); btdp.append("Y", nonce.ToView()); btdp.append("Z", sig.ToView()); } @@ -346,8 +326,6 @@ namespace llarp::routing bool read = false; if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf)) return false; - if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) - return false; if (!BEncodeMaybeReadDictEntry("Y", nonce, read, k, buf)) return false; if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf)) diff --git a/llarp/exit/exit_messages.hpp b/llarp/exit/exit_messages.hpp index 0bc9573314..874e1390e4 100644 --- a/llarp/exit/exit_messages.hpp +++ b/llarp/exit/exit_messages.hpp @@ -13,7 +13,6 @@ namespace llarp::routing uint64_t flag{0}; // 0 for snode, 1 for internet access llarp::PubKey pubkey; uint64_t tx_id{0}; - uint64_t address_lifetime{0}; llarp::Signature sig; ObtainExitMessage() : AbstractRoutingMessage() @@ -27,7 +26,6 @@ namespace llarp::routing flag = 0; pubkey.Zero(); tx_id = 0; - address_lifetime = 0; sig.Zero(); } @@ -50,10 +48,8 @@ namespace llarp::routing struct GrantExitMessage final : public AbstractRoutingMessage { - using Nonce_t = llarp::AlignedBuffer<16>; - uint64_t tx_id; - Nonce_t nonce; + llarp::AlignedBuffer<16> nonce; llarp::Signature sig; std::string @@ -82,10 +78,9 @@ namespace llarp::routing struct RejectExitMessage final : public AbstractRoutingMessage { - using Nonce_t = llarp::AlignedBuffer<16>; uint64_t backoff_time; uint64_t tx_id; - Nonce_t nonce; + llarp::AlignedBuffer<16> nonce; llarp::Signature sig; void @@ -115,9 +110,8 @@ namespace llarp::routing struct UpdateExitVerifyMessage final : public AbstractRoutingMessage { - using Nonce_t = llarp::AlignedBuffer<16>; uint64_t tx_id; - Nonce_t nonce; + llarp::AlignedBuffer<16> nonce; llarp::Signature sig; ~UpdateExitVerifyMessage() override = default; @@ -142,10 +136,9 @@ namespace llarp::routing struct UpdateExitMessage final : public AbstractRoutingMessage { - using Nonce_t = llarp::AlignedBuffer<16>; llarp::PathID_t path_id; uint64_t tx_id; - Nonce_t nonce; + llarp::AlignedBuffer<16> nonce; llarp::Signature sig; bool @@ -175,9 +168,7 @@ namespace llarp::routing struct CloseExitMessage final : public AbstractRoutingMessage { - using Nonce_t = llarp::AlignedBuffer<16>; - - Nonce_t nonce; + llarp::AlignedBuffer<16> nonce; llarp::Signature sig; std::string diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 967698c54e..b73d454258 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -559,7 +559,8 @@ namespace llarp { if (m.timed_out) { - // do something smart here inshallah + log::info(link_cat, "FindNameMessage timed out!"); + return; } std::string payload; @@ -583,17 +584,17 @@ namespace llarp { if (payload == FindNameMessage::EXCEPTION) { - log::critical(link_cat, "FindNameMessage failed with unkown error!"); + log::info(link_cat, "FindNameMessage failed with unkown error!"); // resend? } else if (payload == FindNameMessage::NOT_FOUND) { - log::critical(link_cat, "FindNameMessage failed with unkown error!"); + log::info(link_cat, "FindNameMessage failed with unkown error!"); // what to do here? } else - log::critical(link_cat, "FindNameMessage failed with unkown error!"); + log::info(link_cat, "FindNameMessage failed with unkown error!"); } } @@ -697,7 +698,7 @@ namespace llarp { if (m.timed_out) { - log::critical(link_cat, "FindRouterMessage timed out!"); + log::info(link_cat, "FindRouterMessage timed out!"); return; } @@ -729,7 +730,7 @@ namespace llarp { if (status == FindRouterMessage::EXCEPTION) { - log::critical(link_cat, "FindRouterMessage failed with remote exception!"); + log::info(link_cat, "FindRouterMessage failed with remote exception!"); // Do something smart here probably return; } @@ -738,19 +739,19 @@ namespace llarp if (status == FindRouterMessage::RETRY_EXP) { - log::critical(link_cat, "FindRouterMessage failed, retrying as exploratory!"); + log::info(link_cat, "FindRouterMessage failed, retrying as exploratory!"); send_control_message( target, "find_router", FindRouterMessage::serialize(target, false, true, 0)); } else if (status == FindRouterMessage::RETRY_ITER) { - log::critical(link_cat, "FindRouterMessage failed, retrying as iterative!"); + log::info(link_cat, "FindRouterMessage failed, retrying as iterative!"); send_control_message( target, "find_router", FindRouterMessage::serialize(target, true, false, 0)); } else if (status == FindRouterMessage::RETRY_NEW) { - log::critical(link_cat, "FindRouterMessage failed, retrying with new recipient!"); + log::info(link_cat, "FindRouterMessage failed, retrying with new recipient!"); send_control_message( target, "find_router", FindRouterMessage::serialize(target, false, false, 0)); } @@ -886,6 +887,12 @@ namespace llarp void LinkManager::handle_publish_intro_response(oxen::quic::message m) { + if (m.timed_out) + { + log::info(link_cat, "PublishIntroMessage timed out!"); + return; + } + std::string payload; try @@ -907,12 +914,12 @@ namespace llarp { if (payload == PublishIntroMessage::EXCEPTION) { - log::critical(link_cat, "PublishIntroMessage failed with remote exception!"); + log::info(link_cat, "PublishIntroMessage failed with remote exception!"); // Do something smart here probably return; } - log::critical(link_cat, "PublishIntroMessage failed with error code: {}", payload); + log::info(link_cat, "PublishIntroMessage failed with error code: {}", payload); if (payload == PublishIntroMessage::INVALID_INTROSET) {} @@ -980,7 +987,22 @@ namespace llarp peer_key, "find_intro", FindIntroMessage::serialize( - dht::Key_t{peer_key}, tag_name, tx_id, is_relayed, relay_order)); + dht::Key_t{peer_key}, tag_name, tx_id, is_relayed, relay_order), + [original_msg = std::move(m)](oxen::quic::message relay_response) mutable { + if (relay_response) + log::info( + link_cat, + "Relayed FindIntroMessage returned successful response; transmitting to initial " + "requester"); + else if (relay_response.timed_out) + log::critical( + link_cat, "Relayed FindIntroMessage timed out! Notifying initial requester"); + else + log::critical( + link_cat, "Relayed FindIntroMessage failed! Notifying initial requester"); + + original_msg.respond(relay_response.body_str(), not relay_response); + }); } else { @@ -1001,7 +1023,7 @@ namespace llarp { if (m.timed_out) { - log::critical(link_cat, "FindIntroMessage timed out!"); + log::info(link_cat, "FindIntroMessage timed out!"); return; } @@ -1010,11 +1032,7 @@ namespace llarp try { oxenc::bt_dict_consumer btdc{m.body()}; - - if (m) - payload = btdc.require("INTROSET"); - else - payload = btdc.require("STATUS"); + payload = btdc.require((m) ? "INTROSET" : "STATUS"); } catch (const std::exception& e) { @@ -1030,7 +1048,7 @@ namespace llarp } else { - log::critical(link_cat, "FindIntroMessage failed with error: {}", payload); + log::info(link_cat, "FindIntroMessage failed with error: {}", payload); // Do something smart here probably } } @@ -1158,47 +1176,79 @@ namespace llarp void LinkManager::handle_obtain_exit(oxen::quic::message m) { - // TODO: implement transit_hop things like nextseqno(), info.rxID, etc - std::string copy{m.body_str()}; - ustring pubkey, signature; - uint64_t flag, tx_id, seq_no; - try { - oxenc::bt_dict_consumer btdc{copy}; + uint64_t flag; + ustring_view pubkey, sig; + std::string_view tx_id; + + oxenc::bt_list_consumer btlc{m.body()}; + auto dict_data = btlc.consume_dict_data(); + oxenc::bt_dict_consumer btdc{dict_data}; + sig = to_usv(btlc.consume_string_view()); flag = btdc.require("E"); - pubkey = btdc.require("I"); - seq_no = btdc.require("S"); - tx_id = btdc.require("T"); - signature = btdc.require("Z"); + pubkey = btdc.require("I"); + tx_id = btdc.require("T"); + + RouterID target{pubkey.data()}; + auto transit_hop = std::static_pointer_cast( + router.path_context().GetByUpstream(target, PathID_t{to_usv(tx_id).data()})); + + const auto rx_id = transit_hop->info.rxID; + const auto next_seqno = transit_hop->NextSeqNo(); + + auto success = + (CryptoManager::instance()->verify(pubkey, to_usv(dict_data), sig) + and router.exitContext().ObtainNewExit(PubKey{pubkey.data()}, rx_id, flag != 0)); + + m.respond( + ObtainExit::sign_and_serialize_response(router.identity(), next_seqno, tx_id), + not success); } catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); m.respond(serialize_response({{"STATUS", ObtainExit::EXCEPTION}}), true); - return; + throw; } - - RouterID target{pubkey.data()}; - - if (CryptoManager::instance()->verify( - pubkey.data(), reinterpret_cast(copy.data()), copy.size(), signature.data())) - {} } void LinkManager::handle_obtain_exit_response(oxen::quic::message m) { + if (m.timed_out) + { + log::info(link_cat, "ObtainExitMessage timed out!"); + return; + } + if (m.is_error) + { + // TODO: what to do here + } + try { - oxenc::bt_dict_consumer btdc{m.body()}; + std::string_view tx_id; + ustring_view sig; + + oxenc::bt_list_consumer btlc{m.body()}; + auto dict_data = btlc.consume_dict_data(); + oxenc::bt_dict_consumer btdc{dict_data}; + + sig = to_usv(btlc.consume_string_view()); + tx_id = btdc.require("T"); + + auto path_ptr = std::static_pointer_cast( + router.path_context().GetByDownstream(router.pubkey(), PathID_t{to_usv(tx_id).data()})); + + if (CryptoManager::instance()->verify(router.pubkey(), to_usv(dict_data), sig)) + path_ptr->enable_exit_traffic(); } catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); - return; + throw; } } @@ -1207,12 +1257,38 @@ namespace llarp { try { - oxenc::bt_dict_consumer btdc{m.body()}; + std::string_view path_id, tx_id; + ustring_view sig; + + oxenc::bt_list_consumer btlc{m.body()}; + auto dict_data = btlc.consume_dict_data(); + oxenc::bt_dict_consumer btdc{dict_data}; + + sig = to_usv(btlc.consume_string_view()); + path_id = btdc.require("P"); + tx_id = btdc.require("T"); + + auto transit_hop = std::static_pointer_cast( + router.path_context().GetByUpstream(router.pubkey(), PathID_t{to_usv(tx_id).data()})); + + const auto next_seqno = transit_hop->NextSeqNo(); + + if (auto exit_ep = router.exitContext().FindEndpointForPath(PathID_t{to_usv(path_id).data()})) + { + if (CryptoManager::instance()->verify(exit_ep->PubKey().data(), to_usv(dict_data), sig)) + { + (exit_ep->UpdateLocalPath(transit_hop->info.rxID)) + ? m.respond( + UpdateExit::sign_and_serialize_response(router.identity(), next_seqno, tx_id)) + : m.respond(serialize_response({{"STATUS", UpdateExit::UPDATE_FAILED}}), true); + } + // If we fail to verify the message, no-op + } } catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); + m.respond(serialize_response({{"STATUS", UpdateExit::EXCEPTION}}), true); return; } } @@ -1220,14 +1296,45 @@ namespace llarp void LinkManager::handle_update_exit_response(oxen::quic::message m) { + if (m.timed_out) + { + log::info(link_cat, "UpdateExitMessage timed out!"); + return; + } + if (m.is_error) + { + // TODO: what to do here + } + try { - oxenc::bt_dict_consumer btdc{m.body()}; + std::string tx_id; + ustring_view sig; + + oxenc::bt_list_consumer btlc{m.body()}; + auto dict_data = btlc.consume_dict_data(); + oxenc::bt_dict_consumer btdc{dict_data}; + + sig = to_usv(btlc.consume_string_view()); + tx_id = btdc.require("T"); + + auto path_ptr = std::static_pointer_cast( + router.path_context().GetByDownstream(router.pubkey(), PathID_t{to_usv(tx_id).data()})); + + if (CryptoManager::instance()->verify(router.pubkey(), to_usv(dict_data), sig)) + { + if (path_ptr->update_exit(std::stoul(tx_id))) + { + // TODO: talk to tom and Jason about how this stupid shit was a no-op originally + // see Path::HandleUpdateExitVerifyMessage + } + else + {} + } } catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); return; } } @@ -1237,12 +1344,37 @@ namespace llarp { try { - oxenc::bt_dict_consumer btdc{m.body()}; + std::string_view tx_id; + ustring_view sig; + + oxenc::bt_list_consumer btlc{m.body()}; + auto dict_data = btlc.consume_dict_data(); + oxenc::bt_dict_consumer btdc{dict_data}; + + sig = to_usv(btlc.consume_string_view()); + tx_id = btdc.require("T"); + + auto transit_hop = std::static_pointer_cast( + router.path_context().GetByUpstream(router.pubkey(), PathID_t{to_usv(tx_id).data()})); + + const auto rx_id = transit_hop->info.rxID; + const auto next_seqno = transit_hop->NextSeqNo(); + + if (auto exit_ep = router.exitContext().FindEndpointForPath(rx_id)) + { + if (CryptoManager::instance()->verify(exit_ep->PubKey().data(), to_usv(dict_data), sig)) + { + exit_ep->Close(); + m.respond(CloseExit::sign_and_serialize_response(router.identity(), next_seqno, tx_id)); + } + } + + m.respond(serialize_response({{"STATUS", CloseExit::UPDATE_FAILED}}), true); } catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); + m.respond(serialize_response({{"STATUS", CloseExit::EXCEPTION}}), true); return; } } @@ -1250,14 +1382,39 @@ namespace llarp void LinkManager::handle_close_exit_response(oxen::quic::message m) { + if (m.timed_out) + { + log::info(link_cat, "CloseExitMessage timed out!"); + return; + } + if (m.is_error) + { + // TODO: what to do here + } + try { - oxenc::bt_dict_consumer btdc{m.body()}; + std::string_view nonce, tx_id; + ustring_view sig; + + oxenc::bt_list_consumer btlc{m.body()}; + auto dict_data = btlc.consume_dict_data(); + oxenc::bt_dict_consumer btdc{dict_data}; + + sig = to_usv(btlc.consume_string_view()); + tx_id = btdc.require("T"); + nonce = btdc.require("Y"); + + auto path_ptr = std::static_pointer_cast( + router.path_context().GetByDownstream(router.pubkey(), PathID_t{to_usv(tx_id).data()})); + + if (path_ptr->SupportsAnyRoles(path::ePathRoleExit | path::ePathRoleSVC) + and CryptoManager::instance()->verify(router.pubkey(), to_usv(dict_data), sig)) + path_ptr->close_exit(); } catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); return; } } diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 92e0529a87..b9bc52227b 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -335,7 +335,10 @@ namespace llarp {"find_name", &LinkManager::handle_find_name_response}, {"find_router", &LinkManager::handle_find_router_response}, {"publish_intro", &LinkManager::handle_publish_intro_response}, - {"find_intro", &LinkManager::handle_find_intro_response}}; + {"find_intro", &LinkManager::handle_find_intro_response}, + {"update_exit", &LinkManager::handle_update_exit_response}, + {"obtain_exit", &LinkManager::handle_obtain_exit_response}, + {"close_exit", &LinkManager::handle_close_exit_response}}; std::string serialize_response(oxenc::bt_dict supplement = {}); diff --git a/llarp/messages/dht.hpp b/llarp/messages/dht.hpp index 9204e1b9f0..c403973409 100644 --- a/llarp/messages/dht.hpp +++ b/llarp/messages/dht.hpp @@ -36,6 +36,7 @@ namespace llarp { inline auto EXCEPTION = "EXCEPTION"sv; inline auto NOT_FOUND = "NOT FOUND"sv; + inline auto TIMED_OUT = "TIMED OUT"sv; inline auto INVALID_ORDER = "INVALID ORDER"sv; inline auto INSUFFICIENT_NODES = "INSUFFICIENT NODES"sv; diff --git a/llarp/messages/exit.hpp b/llarp/messages/exit.hpp index bbe5c0df4d..d60fd1f74a 100644 --- a/llarp/messages/exit.hpp +++ b/llarp/messages/exit.hpp @@ -4,22 +4,176 @@ namespace llarp { + /* + TODO: + - change these parameters to ustringviews and ustrings where needed + */ + namespace ObtainExit { inline auto EXCEPTION = "EXCEPTION"sv; - } + // flag: 0 = Exit, 1 = Snode + inline std::string + sign_and_serialize( + SecretKey sk, uint64_t flag, std::string pubkey, uint64_t seq_no, std::string tx_id) + { + oxenc::bt_list_producer btlp; + std::string sig(64, '\0'); + + { + auto btdp = btlp.append_dict(); + + btdp.append("E", flag); + btdp.append("I", pubkey); + btdp.append("S", seq_no); + btdp.append("T", tx_id); + + if (not CryptoManager::instance()->sign( + reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) + throw std::runtime_error{ + "Error: ObtainExitMessage failed to sign and serialize contents!"}; + } + + btlp.append(sig.data()); + return std::move(btlp).str(); + } + + inline std::string + sign_and_serialize_response(SecretKey sk, uint64_t seq_no, std::string_view tx_id) + { + oxenc::bt_list_producer btlp; + std::string sig(64, '\0'); + std::string nonce(16, '\0'); + randombytes(reinterpret_cast(nonce.data()), 16); + + { + oxenc::bt_dict_producer btdp; + + btdp.append("S", seq_no); + btdp.append("T", tx_id); + btdp.append("Y", nonce); + + if (CryptoManager::instance()->sign( + reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) + throw std::runtime_error{ + "Error: ObtainExitMessage response failed to sign and serialize contents!"}; + } + + btlp.append(sig.data()); + return std::move(btlp).str(); + } + + } // namespace ObtainExit namespace UpdateExit { inline auto EXCEPTION = "EXCEPTION"sv; + inline auto UPDATE_FAILED = "EXIT UPDATE FAILED"sv; + + inline std::string + sign_and_serialize(SecretKey sk, std::string path_id, std::string seq_no, std::string tx_id) + { + oxenc::bt_list_producer btlp; + std::string sig(64, '\0'); + + { + auto btdp = btlp.append_dict(); + + btdp.append("P", path_id); + btdp.append("S", seq_no); + btdp.append("T", tx_id); + + if (not CryptoManager::instance()->sign( + reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) + throw std::runtime_error{ + "Error: UpdateExitMessage failed to sign and serialize contents!"}; + } - } + btlp.append(sig.data()); + return std::move(btlp).str(); + } + + inline std::string + sign_and_serialize_response(SecretKey sk, uint64_t seq_no, std::string_view tx_id) + { + oxenc::bt_list_producer btlp; + std::string sig(64, '\0'); + std::string nonce(16, '\0'); + randombytes(reinterpret_cast(nonce.data()), 16); + + { + oxenc::bt_dict_producer btdp; + + btdp.append("S", seq_no); + btdp.append("T", tx_id); + btdp.append("Y", nonce); + + if (CryptoManager::instance()->sign( + reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) + throw std::runtime_error{ + "Error: UpdateExitMessage response failed to sign and serialize contents!"}; + } + + btlp.append(sig.data()); + return std::move(btlp).str(); + } + } // namespace UpdateExit namespace CloseExit { inline auto EXCEPTION = "EXCEPTION"sv; + inline auto UPDATE_FAILED = "CLOSE EXIT FAILED"sv; + + inline std::string + sign_and_serialize(SecretKey sk, std::string seq_no, std::string tx_id) + { + oxenc::bt_list_producer btlp; + std::string sig(64, '\0'); + std::string nonce(16, '\0'); + randombytes(reinterpret_cast(nonce.data()), 16); + + { + auto btdp = btlp.append_dict(); + + btdp.append("S", seq_no); + btdp.append("T", tx_id); + btdp.append("Y", nonce); + + if (not CryptoManager::instance()->sign( + reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) + throw std::runtime_error{ + "Error: CloseExitMessage failed to sign and serialize contents!"}; + } + + btlp.append(sig.data()); + return std::move(btlp).str(); + } + + inline std::string + sign_and_serialize_response(SecretKey sk, uint64_t seq_no, std::string_view tx_id) + { + oxenc::bt_list_producer btlp; + std::string sig(64, '\0'); + std::string nonce(16, '\0'); + randombytes(reinterpret_cast(nonce.data()), 16); + + { + oxenc::bt_dict_producer btdp; + + btdp.append("S", seq_no); + btdp.append("T", tx_id); + btdp.append("Y", nonce); + + if (CryptoManager::instance()->sign( + reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) + throw std::runtime_error{ + "Error: CloseExitMessage response failed to sign and serialize contents!"}; + } - } + btlp.append(sig.data()); + return std::move(btlp).str(); + } + } // namespace CloseExit } // namespace llarp diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 6f0a61c777..a0ece24c8e 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -425,6 +425,22 @@ namespace llarp::path return true; } + bool + Path::update_exit(uint64_t tx_id) + { + if (m_UpdateExitTX && tx_id == m_UpdateExitTX) + { + if (m_ExitUpdated) + return m_ExitUpdated(shared_from_this()); + } + if (m_CloseExitTX && tx_id == m_CloseExitTX) + { + if (m_ExitClosed) + return m_ExitClosed(shared_from_this()); + } + return false; + } + void Path::Tick(llarp_time_t now, Router* r) { diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index eee576ad0f..3db04fd75f 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -248,6 +248,23 @@ namespace llarp return now >= (ExpireTime() - dlt); } + void + enable_exit_traffic() + { + log::info(path_cat, "{} {} granted exit", name(), Endpoint()); + _role |= ePathRoleExit; + } + + void + close_exit() + { + log::info(path_cat, "{} hd its exit closed", name()); + _role &= ePathRoleExit; + } + + bool + update_exit(uint64_t tx_id); + bool Expired(llarp_time_t now) const override; @@ -277,8 +294,10 @@ namespace llarp bool HandleCloseExitMessage(const routing::CloseExitMessage& msg, Router* r) override; + bool HandleGrantExitMessage(const routing::GrantExitMessage& msg, Router* r) override; + bool HandleRejectExitMessage(const routing::RejectExitMessage& msg, Router* r) override; diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index 5839d9e6cd..2661252752 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -251,16 +251,6 @@ namespace llarp::path [](const std::shared_ptr& h) -> HopHandler_ptr { return h; }); } - bool - PathContext::TransitHopPreviousIsRouter(const PathID_t& path, const RouterID& otherRouter) - { - SyncTransitMap_t::Lock_t lock(m_TransitPaths.first); - auto itr = m_TransitPaths.second.find(path); - if (itr == m_TransitPaths.second.end()) - return false; - return itr->second->info.downstream == otherRouter; - } - HopHandler_ptr PathContext::GetByDownstream(const RouterID& remote, const PathID_t& id) { @@ -273,6 +263,16 @@ namespace llarp::path [](const std::shared_ptr& h) -> HopHandler_ptr { return h; }); } + bool + PathContext::TransitHopPreviousIsRouter(const PathID_t& path, const RouterID& otherRouter) + { + SyncTransitMap_t::Lock_t lock(m_TransitPaths.first); + auto itr = m_TransitPaths.second.find(path); + if (itr == m_TransitPaths.second.end()) + return false; + return itr->second->info.downstream == otherRouter; + } + PathSet_ptr PathContext::GetLocalPathSet(const PathID_t& id) { diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index cbb61b090e..1110d31984 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -436,7 +436,6 @@ namespace llarp const auto& nextHop = lastHop ? path_hops[i].rc.pubkey : path_hops[i + 1].rc.pubkey; - // TODO: talk to Tom about what he thinks about this PathBuildMessage::setup_hop_keys(path_hops[i], nextHop); auto frame_str = PathBuildMessage::serialize(path_hops[i]); @@ -458,9 +457,6 @@ namespace llarp frames.append(dummy); } - // TODO: talk to Tom about whether we do still this or not - // router->notify_router_event(router->pubkey(), path); - auto self = GetSelf(); router->path_context().AddOwnPath(self, path); PathBuildStarted(path); diff --git a/llarp/util/buffer.hpp b/llarp/util/buffer.hpp index b995d85f92..81b623a6f7 100644 --- a/llarp/util/buffer.hpp +++ b/llarp/util/buffer.hpp @@ -25,6 +25,13 @@ namespace llarp using bstring = std::basic_string; using bstring_view = std::basic_string_view; + // Helper function to switch between string_view and ustring_view + inline ustring_view + to_usv(std::string_view v) + { + return {reinterpret_cast(v.data()), v.size()}; + } + struct llarp_buffer { private: diff --git a/llarp/util/str.cpp b/llarp/util/str.cpp index 56ca034cf6..1834e6ffcc 100644 --- a/llarp/util/str.cpp +++ b/llarp/util/str.cpp @@ -15,44 +15,6 @@ namespace llarp { - bool - CaselessLessThan::operator()(std::string_view lhs, std::string_view rhs) const - { - const size_t s = std::min(lhs.size(), rhs.size()); - for (size_t i = 0; i < s; ++i) - { - auto l = std::tolower(lhs[i]); - auto r = std::tolower(rhs[i]); - - if (l < r) - { - return true; - } - if (l > r) - { - return false; - } - } - - return lhs.size() < rhs.size(); - } - - bool - IsFalseValue(std::string_view str) - { - static const std::set vals{"no", "false", "0", "off"}; - - return vals.count(str) > 0; - } - - bool - IsTrueValue(std::string_view str) - { - static const std::set vals{"yes", "true", "1", "on"}; - - return vals.count(str) > 0; - } - constexpr static char whitespace[] = " \t\n\r\f\v"; std::string_view @@ -127,22 +89,6 @@ namespace llarp return results; } - void - trim(std::string_view& s) - { - constexpr auto simple_whitespace = " \t\r\n"sv; - auto pos = s.find_first_not_of(simple_whitespace); - if (pos == std::string_view::npos) - { // whole string is whitespace - s.remove_prefix(s.size()); - return; - } - s.remove_prefix(pos); - pos = s.find_last_not_of(simple_whitespace); - assert(pos != std::string_view::npos); - s.remove_suffix(s.size() - (pos + 1)); - } - std::string lowercase_ascii_string(std::string src) { @@ -151,45 +97,4 @@ namespace llarp ch = ch + ('a' - 'A'); return src; } - - std::string - friendly_duration(std::chrono::nanoseconds dur) - { - const double dsecs = std::chrono::duration(dur).count(); - return fmt::format( - dur >= 24h ? "{0}d{1}h{2}m{3}s" - : dur >= 1h ? "{1}h{2}m{3}s" - : dur >= 1min ? "{2}m{3}s" - : dur >= 1s ? "{4:.3f}s" - : dur >= 1ms ? "{5:.3f}s" - : dur >= 1us ? u8"{6:.3f}µs" - : "{7}ns", - dur / 24h, - dur / 1h, - dur / 1min, - dur / 1s, - dsecs, - dsecs * 1'000, - dsecs * 1'000'000, - dur.count()); - } - - std::wstring - to_wide(std::string data) - { - std::wstring buf; - buf.resize(data.size()); -#ifdef _WIN32 - // win32 specific codepath because balmer made windows so that man may suffer - if (MultiByteToWideChar(CP_UTF8, 0, data.c_str(), data.size(), buf.data(), buf.size()) == 0) - throw win32::error{GetLastError(), "failed to convert string to wide string"}; - -#else - // this dumb but probably works (i guess?) - std::transform( - data.begin(), data.end(), buf.begin(), [](const auto& ch) -> wchar_t { return ch; }); -#endif - return buf; - } - } // namespace llarp diff --git a/llarp/util/str.hpp b/llarp/util/str.hpp index eed00482e4..9169cefb73 100644 --- a/llarp/util/str.hpp +++ b/llarp/util/str.hpp @@ -9,44 +9,6 @@ namespace llarp { - bool - IsFalseValue(std::string_view str); - - struct CaselessLessThan - { - bool - operator()(std::string_view lhs, std::string_view rhs) const; - }; - - bool - IsTrueValue(std::string_view str); - - /// Trim leading and trailing (ascii) whitespace from the given string; - /// returns a std::string_view of the trimmed part of the string. - [[nodiscard]] std::string_view - TrimWhitespace(std::string_view str); - - using namespace std::literals; - - /// Returns true if the first string is equal to the second string, compared case-insensitively. - inline bool - string_iequal(std::string_view s1, std::string_view s2) - { - return std::equal(s1.begin(), s1.end(), s2.begin(), s2.end(), [](char a, char b) { - return std::tolower(static_cast(a)) - == std::tolower(static_cast(b)); - }); - } - - /// Returns true if the first string matches any of the given strings case-insensitively. - /// Arguments must be string literals, std::string, or std::string_views - template - bool - string_iequal_any(const S1& s1, const S&... s) - { - return (... || string_iequal(s1, s)); - } - /// Returns true if the first argument begins with the second argument inline constexpr bool starts_with(std::string_view str, std::string_view prefix) @@ -112,11 +74,6 @@ namespace llarp return join(delimiter, c.begin(), c.end()); } - /// Simple version of whitespace trimming: mutates the given string view to remove leading - /// space, \t, \r, \n. (More exotic and locale-dependent whitespace is not removed). - void - trim(std::string_view& s); - /// Parses an integer of some sort from a string, requiring that the entire string be consumed /// during parsing. Return false if parsing failed, sets `value` and returns true if the entire /// string was consumed. @@ -135,13 +92,4 @@ namespace llarp std::string lowercase_ascii_string(std::string src); - - /// Converts a duration into a human friendlier string. - std::string - friendly_duration(std::chrono::nanoseconds dur); - - /// convert a "normal" string into a wide string - std::wstring - to_wide(std::string data); - } // namespace llarp From bd81357f62db55d6eeed8180407b8aad48954827 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Tue, 10 Oct 2023 13:49:53 -0700 Subject: [PATCH 047/312] Path message transmission - implementing DHT message transmission methods and surrounding functionalities across paths --- llarp/config/config.cpp | 4 +- llarp/endpoint_base.hpp | 6 +- llarp/exit/session.hpp | 4 +- llarp/handlers/exit.cpp | 4 +- llarp/handlers/exit.hpp | 8 +- llarp/handlers/tun.cpp | 97 ++-- llarp/link/contacts.cpp | 2 +- llarp/link/link_manager.cpp | 40 +- llarp/messages/dht.hpp | 49 +- llarp/messages/exit.hpp | 3 +- llarp/path/abstracthophandler.hpp | 6 + llarp/path/path.cpp | 29 +- llarp/path/path.hpp | 14 + llarp/path/pathset.hpp | 21 - llarp/path/transit_hop.hpp | 6 + llarp/quic/tunnel.cpp | 48 +- llarp/router/rc_lookup_handler.cpp | 8 +- llarp/service/address.cpp | 2 +- llarp/service/address.hpp | 2 +- llarp/service/endpoint.cpp | 688 +++++++++++------------------ llarp/service/endpoint.hpp | 35 +- llarp/service/name.cpp | 2 +- llarp/service/name.hpp | 2 +- 23 files changed, 509 insertions(+), 571 deletions(-) diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index 208e3e1b5e..4402fcb656 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -527,7 +527,7 @@ namespace llarp arg = arg.substr(0, pos); } - if (service::NameIsValid(arg)) + if (service::is_valid_name(arg)) { m_LNSExitMap.Insert(range, arg); return; @@ -567,7 +567,7 @@ namespace llarp const auto exit_str = arg.substr(0, pos); auth.token = arg.substr(pos + 1); - if (service::NameIsValid(exit_str)) + if (service::is_valid_name(exit_str)) { m_LNSExitAuths.emplace(exit_str, auth); return; diff --git a/llarp/endpoint_base.hpp b/llarp/endpoint_base.hpp index 6bbd97bce3..b33ed9df84 100644 --- a/llarp/endpoint_base.hpp +++ b/llarp/endpoint_base.hpp @@ -15,6 +15,7 @@ #include #include #include "oxenc/variant.h" +#include namespace llarp { @@ -126,8 +127,7 @@ namespace llarp llarp_time_t timeout) = 0; virtual void - LookupNameAsync( - std::string name, std::function)> resultHandler) = 0; + lookup_name(std::string name, std::function func) = 0; virtual const EventLoop_ptr& Loop() = 0; @@ -144,7 +144,7 @@ namespace llarp std::function)> resultHandler) = 0; virtual void - MarkAddressOutbound(AddressVariant_t remote) = 0; + MarkAddressOutbound(service::Address remote) = 0; }; } // namespace llarp diff --git a/llarp/exit/session.hpp b/llarp/exit/session.hpp index f6b342fda9..b654af8010 100644 --- a/llarp/exit/session.hpp +++ b/llarp/exit/session.hpp @@ -218,7 +218,7 @@ namespace llarp PopulateRequest(llarp::routing::ObtainExitMessage& msg) const override { // TODO: set expiration time - msg.address_lifetime = 0; + // msg.address_lifetime = 0; msg.flag = 1; } }; @@ -247,7 +247,7 @@ namespace llarp PopulateRequest(llarp::routing::ObtainExitMessage& msg) const override { // TODO: set expiration time - msg.address_lifetime = 0; + // msg.address_lifetime = 0; msg.flag = 0; } }; diff --git a/llarp/handlers/exit.cpp b/llarp/handlers/exit.cpp index 02125cdf28..b8a8b8372e 100644 --- a/llarp/handlers/exit.cpp +++ b/llarp/handlers/exit.cpp @@ -27,11 +27,9 @@ namespace llarp::handlers ExitEndpoint::~ExitEndpoint() = default; void - ExitEndpoint::LookupNameAsync( - std::string, std::function)> resultHandler) + ExitEndpoint::lookup_name(std::string, std::function) { // TODO: implement me - resultHandler(std::nullopt); } void diff --git a/llarp/handlers/exit.hpp b/llarp/handlers/exit.hpp index 8723734a6a..fd322aeb1b 100644 --- a/llarp/handlers/exit.hpp +++ b/llarp/handlers/exit.hpp @@ -47,20 +47,18 @@ namespace llarp llarp_time_t timeout) override; void - LookupNameAsync( - std::string name, - std::function)> resultHandler) override; + lookup_name(std::string name, std::function func) override; const EventLoop_ptr& Loop() override; std::unordered_set - AllRemoteEndpoints() const; + AllRemoteEndpoints() const override; void SRVRecordsChanged() override; - void MarkAddressOutbound(AddressVariant_t) override{}; + void MarkAddressOutbound(service::Address) override{}; bool SendToOrQueue( diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 8ac2822022..91285557c9 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -288,7 +288,7 @@ namespace llarp::handlers if (conf.m_AuthType == service::AuthType::eAuthTypeFile) { - _auth_policy = service::MakeFileAuthPolicy(router, conf.m_AuthFiles, conf.m_AuthFileType); + _auth_policy = service::MakeFileAuthPolicy(router(), conf.m_AuthFiles, conf.m_AuthFileType); } else if (conf.m_AuthType != service::AuthType::eAuthTypeNone) { @@ -331,7 +331,7 @@ namespace llarp::handlers m_IfName = conf.m_ifname; if (m_IfName.empty()) { - const auto maybe = router->net().FindFreeTun(); + const auto maybe = router()->net().FindFreeTun(); if (not maybe.has_value()) throw std::runtime_error("cannot find free interface name"); m_IfName = *maybe; @@ -340,7 +340,7 @@ namespace llarp::handlers m_OurRange = conf.m_ifaddr; if (!m_OurRange.addr.h) { - const auto maybe = router->net().FindFreeRange(); + const auto maybe = router()->net().FindFreeRange(); if (not maybe.has_value()) { throw std::runtime_error("cannot find free address range"); @@ -412,7 +412,7 @@ namespace llarp::handlers if (const auto* str = std::get_if(&value)) { - if (auto maybe = service::ParseAddress(*str)) + if (auto maybe = service::parse_address(*str)) { addr = *maybe; } @@ -549,17 +549,12 @@ namespace llarp::handlers }; auto ReplyToDNSWhenReady = [ReplyToLokiDNSWhenReady, ReplyToSNodeDNSWhenReady]( - auto addr, auto msg, bool isV6) { - if (auto ptr = std::get_if(&addr)) - { - ReplyToSNodeDNSWhenReady(*ptr, msg, isV6); - return; - } - if (auto ptr = std::get_if(&addr)) - { - ReplyToLokiDNSWhenReady(*ptr, msg, isV6); - return; - } + std::string name, auto msg, bool isV6) { + if (auto saddr = service::Address(); saddr.FromString(name)) + ReplyToLokiDNSWhenReady(saddr, msg, isV6); + + if (auto rid = RouterID(); rid.FromString(name)) + ReplyToSNodeDNSWhenReady(rid, msg, isV6); }; auto ReplyToLokiSRVWhenReady = [this, reply, timeout = PathAlignmentTimeout()]( @@ -618,18 +613,18 @@ namespace llarp::handlers } std::string qname = msg.questions[0].Name(); const auto nameparts = split(qname, "."); - std::string lnsName; + std::string ons_name; if (nameparts.size() >= 2 and ends_with(qname, ".loki")) { - lnsName = nameparts[nameparts.size() - 2]; - lnsName += ".loki"sv; + ons_name = nameparts[nameparts.size() - 2]; + ons_name += ".loki"sv; } if (msg.questions[0].qtype == dns::qTypeTXT) { RouterID snode; if (snode.FromString(qname)) { - router->LookupRouter(snode, [reply, msg = std::move(msg)](const auto& found) mutable { + router()->LookupRouter(snode, [reply, msg = std::move(msg)](const auto& found) mutable { if (found.empty()) { msg.AddNXReply(); @@ -665,7 +660,7 @@ namespace llarp::handlers } else if (subdomain == "netid") { - msg.AddTXTReply(fmt::format("netid={};", router->rc().netID)); + msg.AddTXTReply(fmt::format("netid={};", router()->rc().netID)); } else { @@ -688,19 +683,31 @@ namespace llarp::handlers { msg.AddMXReply(qname, 1); } - else if (service::NameIsValid(lnsName)) + else if (service::is_valid_name(ons_name)) { - LookupNameAsync(lnsName, [msg, lnsName, reply](auto maybe) mutable { - if (maybe.has_value()) + lookup_name(ons_name, [msg, ons_name, reply](oxen::quic::message m) mutable { + if (m) { - var::visit([&](auto&& value) { msg.AddMXReply(value.ToString(), 1); }, *maybe); + std::string result; + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + result = btdc.require("NAME"); + } + catch (...) + { + log::warning(log_cat, "Failed to parse find name response!"); + throw; + } + + msg.AddMXReply(result, 1); } else - { msg.AddNXReply(); - } + reply(msg); }); + return true; } else @@ -823,24 +830,38 @@ namespace llarp::handlers addr.as_array(), std::make_shared(msg), isV6); } } - else if (service::NameIsValid(lnsName)) + else if (service::is_valid_name(ons_name)) { - LookupNameAsync( - lnsName, + lookup_name( + ons_name, [msg = std::make_shared(msg), name = Name(), - lnsName, + ons_name, isV6, reply, - ReplyToDNSWhenReady](auto maybe) { - if (not maybe.has_value()) + ReplyToDNSWhenReady](oxen::quic::message m) mutable { + if (m) + { + std::string name; + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + name = btdc.require("NAME"); + } + catch (...) + { + log::warning(log_cat, "Failed to parse find name response!"); + throw; + } + + ReplyToDNSWhenReady(name, msg, isV6); + } + else { - LogWarn(name, " lns name ", lnsName, " not resolved"); + log::warning(log_cat, "{} (ONS name: {}) not resolved", name, ons_name); msg->AddNXReply(); reply(*msg); - return; } - ReplyToDNSWhenReady(*maybe, msg, isV6); }); return true; } @@ -1047,7 +1068,7 @@ namespace llarp::handlers if constexpr (not llarp::platform::is_apple) { - if (auto maybe = router->net().GetInterfaceIPv6Address(m_IfName)) + if (auto maybe = router()->net().GetInterfaceIPv6Address(m_IfName)) { m_OurIPv6 = *maybe; LogInfo(Name(), " has ipv6 address ", m_OurIPv6); @@ -1056,7 +1077,7 @@ namespace llarp::handlers LogInfo(Name(), " setting up dns..."); SetupDNS(); - Loop()->call_soon([this]() { router->route_poker()->set_dns_mode(false); }); + Loop()->call_soon([this]() { router()->route_poker()->set_dns_mode(false); }); return HasAddress(ourAddr); } @@ -1130,7 +1151,7 @@ namespace llarp::handlers if (auto itr = m_ExitIPToExitAddress.find(ip); itr != m_ExitIPToExitAddress.end()) return itr->second; - const auto& net = router->net(); + const auto& net = router()->net(); const bool is_bogon = net.IsBogonIP(ip); // build up our candidates to choose diff --git a/llarp/link/contacts.cpp b/llarp/link/contacts.cpp index c90d8d13ac..5c5d1d08dd 100644 --- a/llarp/link/contacts.cpp +++ b/llarp/link/contacts.cpp @@ -79,7 +79,7 @@ namespace llarp _router.loop()->call([this, rid]() { _router.send_control_message( - rid, "find_router", FindRouterMessage::serialize(rid, false, false, 0)); + rid, "find_router", FindRouterMessage::serialize(rid, false, false)); }); return true; diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index b73d454258..a566f7eb86 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -196,7 +196,7 @@ namespace llarp if (not func and rpc_responses.count(endpoint)) { func = [&](oxen::quic::message m) { - return std::invoke(rpc_responses[endpoint], this, std::move(m)); + std::invoke(rpc_responses[endpoint], this, std::move(m)); }; } @@ -530,14 +530,12 @@ namespace llarp LinkManager::handle_find_name(oxen::quic::message m) { std::string name_hash; - [[maybe_unused]] uint64_t tx_id; try { oxenc::bt_dict_consumer btdp{m.body()}; name_hash = btdp.require("H"); - tx_id = btdp.require("T"); } catch (const std::exception& e) { @@ -598,6 +596,8 @@ namespace llarp } } + // TODO: add callback to relayed messages (calls to send_control_message so the + // response finds its way back) void LinkManager::handle_find_router(oxen::quic::message m) { @@ -624,6 +624,7 @@ namespace llarp RouterID target_rid; 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_key = dht::Key_t{local_rid}; @@ -658,7 +659,12 @@ namespace llarp if (closest_rc.ExpiresSoon(llarp::time_now_ms())) { send_control_message( - target_rid, "find_router", FindRouterMessage::serialize(target_rid, false, false, 0)); + target_rid, + "find_router", + FindRouterMessage::serialize(target_rid, false, false), + [original = std::move(m)](oxen::quic::message msg) mutable { + original.respond(msg.body_str(), not msg); + }); } else { @@ -672,7 +678,10 @@ namespace llarp send_control_message( closest_rid, "find_router", - FindRouterMessage::serialize(closest_rid, false, false, 0)); + FindRouterMessage::serialize(closest_rid, false, false), + [original = std::move(m)](oxen::quic::message msg) mutable { + original.respond(msg.body_str(), not msg); + }); } else { @@ -741,19 +750,19 @@ namespace llarp { log::info(link_cat, "FindRouterMessage failed, retrying as exploratory!"); send_control_message( - target, "find_router", FindRouterMessage::serialize(target, false, true, 0)); + target, "find_router", FindRouterMessage::serialize(target, false, true)); } else if (status == FindRouterMessage::RETRY_ITER) { log::info(link_cat, "FindRouterMessage failed, retrying as iterative!"); send_control_message( - target, "find_router", FindRouterMessage::serialize(target, true, false, 0)); + target, "find_router", FindRouterMessage::serialize(target, true, false)); } else if (status == FindRouterMessage::RETRY_NEW) { log::info(link_cat, "FindRouterMessage failed, retrying with new recipient!"); send_control_message( - target, "find_router", FindRouterMessage::serialize(target, false, false, 0)); + target, "find_router", FindRouterMessage::serialize(target, false, false)); } } } @@ -762,7 +771,7 @@ namespace llarp LinkManager::handle_publish_intro(oxen::quic::message m) { std::string introset, derived_signing_key, payload, sig, nonce; - uint64_t is_relayed, relay_order, tx_id; + uint64_t is_relayed, relay_order; std::chrono::milliseconds signed_at; try @@ -772,7 +781,6 @@ namespace llarp introset = btdc_a.require("I"); relay_order = btdc_a.require("O"); is_relayed = btdc_a.require("R"); - tx_id = btdc_a.require("T"); oxenc::bt_dict_consumer btdc_b{introset.data()}; @@ -829,7 +837,7 @@ namespace llarp return; } - log::info(link_cat, "Relaying PublishIntroMessage for {} (TXID: {})", addr, tx_id); + log::info(link_cat, "Relaying PublishIntroMessage for {}", addr); const auto& peer_rc = closest_rcs[relay_order]; const auto& peer_key = peer_rc.pubkey; @@ -852,7 +860,7 @@ namespace llarp send_control_message( peer_key, "publish_intro", - PublishIntroMessage::serialize(introset, relay_order, is_relayed, tx_id)); + PublishIntroMessage::serialize(introset, relay_order, is_relayed)); } return; @@ -937,7 +945,7 @@ namespace llarp { std::string tag_name; ustring location; - uint64_t tx_id, relay_order, is_relayed; + uint64_t relay_order, is_relayed; try { @@ -947,7 +955,6 @@ namespace llarp relay_order = btdc.require("O"); is_relayed = btdc.require("R"); location = btdc.require("S"); - tx_id = btdc.require("T"); } catch (const std::exception& e) { @@ -978,7 +985,7 @@ namespace llarp return; } - log::info(link_cat, "Relaying FindIntroMessage for {} (TXID: {})", addr, tx_id); + log::info(link_cat, "Relaying FindIntroMessage for {}", addr); const auto& peer_rc = closest_rcs[relay_order]; const auto& peer_key = peer_rc.pubkey; @@ -986,8 +993,7 @@ namespace llarp send_control_message( peer_key, "find_intro", - FindIntroMessage::serialize( - dht::Key_t{peer_key}, tag_name, tx_id, is_relayed, relay_order), + FindIntroMessage::serialize(dht::Key_t{peer_key}, tag_name, is_relayed, relay_order), [original_msg = std::move(m)](oxen::quic::message relay_response) mutable { if (relay_response) log::info( diff --git a/llarp/messages/dht.hpp b/llarp/messages/dht.hpp index c403973409..cc032afbb1 100644 --- a/llarp/messages/dht.hpp +++ b/llarp/messages/dht.hpp @@ -12,7 +12,7 @@ namespace llarp inline auto RETRY_NEW = "RETRY WITH NEW RECIPIENT"sv; inline static std::string - serialize(const RouterID& rid, bool is_iterative, bool is_exploratory, uint64_t tx_id) + serialize(const RouterID& rid, bool is_iterative, bool is_exploratory) { oxenc::bt_dict_producer btdp; @@ -21,7 +21,25 @@ namespace llarp btdp.append("E", is_exploratory); btdp.append("I", is_iterative); btdp.append("K", rid.ToView()); - btdp.append("T", tx_id); + } + catch (...) + { + log::error(link_cat, "Error: FindRouterMessage failed to bt encode contents!"); + } + + return std::move(btdp).str(); + } + + inline static std::string + serialize(const std::string& rid, bool is_iterative, bool is_exploratory) + { + oxenc::bt_dict_producer btdp; + + try + { + btdp.append("E", is_exploratory); + btdp.append("I", is_iterative); + btdp.append("K", std::move(rid)); } catch (...) { @@ -41,8 +59,7 @@ namespace llarp inline auto INSUFFICIENT_NODES = "INSUFFICIENT NODES"sv; inline static std::string - serialize( - const dht::Key_t& location, std::string tag, uint64_t txid, bool is_relayed, uint64_t order) + serialize(const dht::Key_t& location, std::string tag, bool is_relayed, uint64_t order) { oxenc::bt_dict_producer btdp; @@ -52,7 +69,6 @@ namespace llarp btdp.append("O", order); btdp.append("R", is_relayed ? 1 : 0); btdp.append("S", location.ToView()); - btdp.append("T", txid); } catch (...) { @@ -69,14 +85,30 @@ namespace llarp inline auto NOT_FOUND = "NOT FOUND"sv; inline static std::string - serialize([[maybe_unused]] const dht::Key_t& from, dht::Key_t name_hash, uint64_t tx_id) + serialize(dht::Key_t name_hash) { oxenc::bt_dict_producer btdp; try { btdp.append("H", name_hash.ToView()); - btdp.append("T", tx_id); + } + catch (...) + { + log::error(link_cat, "Error: FindNameMessage failed to bt encode contents!"); + } + + return std::move(btdp).str(); + } + + inline static std::string + serialize(std::string name_hash) + { + oxenc::bt_dict_producer btdp; + + try + { + btdp.append("H", std::move(name_hash)); } catch (...) { @@ -96,7 +128,7 @@ namespace llarp inline auto INVALID_ORDER = "INVALID ORDER"sv; inline static std::string - serialize(std::string introset, uint64_t relay_order, uint64_t is_relayed, uint64_t tx_id) + serialize(std::string introset, uint64_t relay_order, uint64_t is_relayed) { oxenc::bt_dict_producer btdp; @@ -105,7 +137,6 @@ namespace llarp btdp.append("I", introset); btdp.append("O", relay_order); btdp.append("R", is_relayed); - btdp.append("T", tx_id); } catch (...) { diff --git a/llarp/messages/exit.hpp b/llarp/messages/exit.hpp index d60fd1f74a..e377c2a989 100644 --- a/llarp/messages/exit.hpp +++ b/llarp/messages/exit.hpp @@ -6,7 +6,8 @@ namespace llarp { /* TODO: - - change these parameters to ustringviews and ustrings where needed + - change these parameters to ustringviews and ustrings where needed after bumping oxenc + - nuke seq_no's */ namespace ObtainExit diff --git a/llarp/path/abstracthophandler.hpp b/llarp/path/abstracthophandler.hpp index 593db5d519..5a33f169f1 100644 --- a/llarp/path/abstracthophandler.hpp +++ b/llarp/path/abstracthophandler.hpp @@ -41,6 +41,12 @@ namespace llarp virtual bool ExpiresSoon(llarp_time_t now, llarp_time_t dlt) const = 0; + virtual void + send_path_control_message( + std::string method, + std::string body, + std::function func) = 0; + /// send routing message and increment sequence number virtual bool SendRoutingMessage(const routing::AbstractRoutingMessage& msg, Router* r) = 0; diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index a0ece24c8e..5e554f0c96 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -24,12 +25,15 @@ namespace llarp::path { Path::Path( + Router* rtr, const std::vector& h, std::weak_ptr pathset, PathRole startingRoles, std::string shortName) - : m_PathSet{std::move(pathset)}, _role{startingRoles}, m_shortName{std::move(shortName)} - + : m_PathSet{std::move(pathset)} + , router{*rtr} + , _role{startingRoles} + , m_shortName{std::move(shortName)} { hops.resize(h.size()); size_t hsz = h.size(); @@ -58,6 +62,27 @@ namespace llarp::path EnterState(ePathBuilding, parent->Now()); } + void + Path::find_name(std::string name, std::function func) + { + send_path_control_message( + "find_router", FindNameMessage::serialize(std::move(name)), std::move(func)); + } + + void + Path::find_router(std::string rid, std::function func) + { + send_path_control_message( + "find_router", FindRouterMessage::serialize(std::move(rid), false, false), std::move(func)); + } + + void + Path::send_path_control_message( + std::string method, std::string body, std::function func) + { + router.send_control_message(upstream(), std::move(method), std::move(body), std::move(func)); + } + void Path::SetBuildResultHook(BuildResultHookFunc func) { diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 3db04fd75f..1d90d81663 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -64,6 +64,7 @@ namespace llarp llarp_time_t buildStarted = 0s; Path( + Router* rtr, const std::vector& routers, std::weak_ptr parent, PathRole startingRoles, @@ -276,6 +277,18 @@ namespace llarp void Tick(llarp_time_t now, Router* r); + void + find_name(std::string name, std::function func = nullptr); + + void + find_router(std::string rid, std::function func = nullptr); + + void + send_path_control_message( + std::string method, + std::string body, + std::function func = nullptr) override; + bool SendRoutingMessage(const routing::AbstractRoutingMessage& msg, Router* r) override; @@ -393,6 +406,7 @@ namespace llarp bool InformExitResult(llarp_time_t b); + Router& router; BuildResultHookFunc m_BuiltHook; DataHandlerFunc m_DataHandler; DropHandlerFunc m_DropHandler; diff --git a/llarp/path/pathset.hpp b/llarp/path/pathset.hpp index a380cf3a7b..986be4ed1f 100644 --- a/llarp/path/pathset.hpp +++ b/llarp/path/pathset.hpp @@ -210,27 +210,6 @@ namespace llarp virtual void BlacklistSNode(const RouterID) = 0; - /// override me in subtype - virtual bool - HandleGotIntroMessage(std::shared_ptr) - { - return false; - } - - /// override me in subtype - virtual bool - HandleGotRouterMessage(std::shared_ptr) - { - return false; - } - - /// override me in subtype - virtual bool - HandleGotNameMessage(std::shared_ptr) - { - return false; - } - virtual routing::AbstractRoutingMessageHandler* GetDHTHandler() { diff --git a/llarp/path/transit_hop.hpp b/llarp/path/transit_hop.hpp index 5b04ef5c98..42b5c0e02d 100644 --- a/llarp/path/transit_hop.hpp +++ b/llarp/path/transit_hop.hpp @@ -114,6 +114,12 @@ namespace llarp return now >= ExpireTime() - dlt; } + void + send_path_control_message( + std::string method, + std::string body, + std::function func) override; + // send routing message when end of path bool SendRoutingMessage(const routing::AbstractRoutingMessage& msg, Router* r) override; diff --git a/llarp/quic/tunnel.cpp b/llarp/quic/tunnel.cpp index 3e85a08368..2c216bb2dd 100644 --- a/llarp/quic/tunnel.cpp +++ b/llarp/quic/tunnel.cpp @@ -436,10 +436,10 @@ namespace llarp::quic std::pair result; auto& [saddr, pport] = result; - auto maybe_remote = service::ParseAddress(remote_addr); + auto maybe_remote = service::parse_address(remote_addr); if (!maybe_remote) { - if (not service::NameIsValid(remote_addr)) + if (not service::is_valid_name(remote_addr)) throw std::invalid_argument{"Invalid remote lokinet name/address"}; // Otherwise it's a valid ONS name, so we'll initiate an ONS lookup below } @@ -518,17 +518,46 @@ namespace llarp::quic { // We were given an ONS address, so it's a two-step process: first we resolve the ONS name, // then we have to build a path to that address. - service_endpoint_.LookupNameAsync( + service_endpoint_.lookup_name( + remote_addr, + [this, raddr = std::move(remote_addr), after = std::move(after_path), pp = pport]( + oxen::quic::message m) mutable { + if (not continue_connecting(pp, m, "endpoint ONS lookup", raddr)) + return; + + service::Address addr{}; + }); + + service_endpoint_.lookup_name( remote_addr, [this, after_path = std::move(after_path), pport = pport, - remote_addr = std::move(remote_addr)](auto maybe_remote) { - if (not continue_connecting( - pport, (bool)maybe_remote, "endpoint ONS lookup", remote_addr)) + remote_addr = std::move(remote_addr)](oxen::quic::message m) { + if (not continue_connecting(pport, (bool)m, "endpoint ONS lookup", remote_addr)) return; - service_endpoint_.MarkAddressOutbound(*maybe_remote); - service_endpoint_.EnsurePathTo(*maybe_remote, after_path, open_timeout); + + std::string name; + + if (m) + { + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + name = btdc.require("NAME"); + } + catch (...) + { + log::warning(log_cat, "Tunnel Manager failed to parse find name response"); + throw; + } + + if (auto saddr = service::Address(); saddr.FromString(name)) + { + service_endpoint_.MarkAddressOutbound(saddr); + service_endpoint_.EnsurePathTo(saddr, std::move(after_path), open_timeout); + } + } }); return result; } @@ -540,7 +569,8 @@ namespace llarp::quic after_path(maybe_convo); else { - service_endpoint_.MarkAddressOutbound(remote); + if (auto* ptr = std::get_if(&remote)) + service_endpoint_.MarkAddressOutbound(*ptr); service_endpoint_.EnsurePathTo(remote, after_path, open_timeout); } diff --git a/llarp/router/rc_lookup_handler.cpp b/llarp/router/rc_lookup_handler.cpp index 221048b43f..4b3b9250ee 100644 --- a/llarp/router/rc_lookup_handler.cpp +++ b/llarp/router/rc_lookup_handler.cpp @@ -95,8 +95,6 @@ namespace llarp if (shouldDoLookup) { - auto fn = [this, router](const auto& res) { handle_dht_lookup_result(router, res); }; - // if we are a client try using the hidden service endpoints if (!isServiceNode) { @@ -104,7 +102,7 @@ namespace llarp LogInfo("Lookup ", router, " anonymously"); hidden_service_context->ForEachService( [&](const std::string&, const std::shared_ptr& ep) -> bool { - const bool success = ep->LookupRouterAnon(router, fn); + const bool success = ep->lookup_router(router); sent = sent || success; return !success; }); @@ -114,13 +112,9 @@ namespace llarp } if (not contacts->lookup_router(router)) - { finalize_request(router, nullptr, RCRequestResult::RouterNotFound); - } else - { router_lookup_times[router] = std::chrono::steady_clock::now(); - } } } diff --git a/llarp/service/address.cpp b/llarp/service/address.cpp index 940658c286..fe75cb6c46 100644 --- a/llarp/service/address.cpp +++ b/llarp/service/address.cpp @@ -72,7 +72,7 @@ namespace llarp::service } std::optional> - ParseAddress(std::string_view lokinet_addr) + parse_address(std::string_view lokinet_addr) { RouterID router{}; service::Address addr{}; diff --git a/llarp/service/address.hpp b/llarp/service/address.hpp index 40689a19ea..a5ad0eeba4 100644 --- a/llarp/service/address.hpp +++ b/llarp/service/address.hpp @@ -87,7 +87,7 @@ namespace llarp }; std::optional> - ParseAddress(std::string_view lokinet_addr); + parse_address(std::string_view lokinet_addr); } // namespace service diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 3269f6cff7..818659a606 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -148,59 +149,70 @@ namespace llarp return; } - LookupNameAsync( + lookup_name( name, [ptr = std::static_pointer_cast(GetSelf()), name, auth = AuthInfo{token}, ranges, result_handler, - poker = router()->route_poker()](auto maybe_addr) { - if (not maybe_addr) + poker = router()->route_poker()](oxen::quic::message m) mutable { + if (m) { - result_handler(false, "exit not found: {}"_format(name)); - return; + std::string name; + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + name = btdc.require("NAME"); + } + catch (...) + { + log::warning(log_cat, "Failed to parse find name response!"); + throw; + } + + if (auto saddr = service::Address(); saddr.FromString(name)) + { + ptr->SetAuthInfoForEndpoint(saddr, auth); + ptr->MarkAddressOutbound(saddr); + + auto result = ptr->EnsurePathToService( + saddr, + [ptr, name, ranges, result_handler, poker](auto addr, auto* ctx) { + if (ctx == nullptr) + { + result_handler(false, "could not establish flow to {}"_format(name)); + return; + } + + // make a lambda that sends the reply after doing auth + auto apply_result = + [ptr, poker, addr, result_handler, ranges](AuthResult result) { + if (result.code != AuthResultCode::eAuthAccepted) + { + result_handler(false, result.reason); + return; + } + for (const auto& range : ranges) + ptr->MapExitRange(range, addr); + + if (poker) + poker->put_up(); + result_handler(true, result.reason); + }; + + ctx->AsyncSendAuth(apply_result); + }, + ptr->PathAlignmentTimeout()); + + if (not result) + result_handler(false, "Could not build path to {}"_format(name)); + } } - if (auto* addr_ptr = std::get_if
(&*maybe_addr)) + else { - Address addr{*addr_ptr}; - - ptr->SetAuthInfoForEndpoint(addr, auth); - ptr->MarkAddressOutbound(addr); - auto result = ptr->EnsurePathToService( - addr, - [ptr, name, ranges, result_handler, poker](auto addr, auto* ctx) { - if (ctx == nullptr) - { - result_handler(false, "could not establish flow to {}"_format(name)); - return; - } - - // make a lambda that sends the reply after doing auth - auto apply_result = - [ptr, poker, addr, result_handler, ranges](AuthResult result) { - if (result.code != AuthResultCode::eAuthAccepted) - { - result_handler(false, result.reason); - return; - } - for (const auto& range : ranges) - ptr->MapExitRange(range, addr); - - if (poker) - poker->put_up(); - result_handler(true, result.reason); - }; - - ctx->AsyncSendAuth(apply_result); - }, - ptr->PathAlignmentTimeout()); - - if (not result) - result_handler(false, "did not build path to {}"_format(name)); + result_handler(false, "Exit {} not found!"_format(name)); } - else - result_handler(false, "exit via snode not supported"); }); } @@ -262,7 +274,7 @@ namespace llarp }; // handles when we know a long address of a remote resource - auto handleGotAddress = [resultHandler, handleGotPathTo, this](auto address) { + auto handleGotAddress = [resultHandler, handleGotPathTo, this](AddressVariant_t address) { // we will attempt a build to whatever we looked up const auto result = EnsurePathTo( address, @@ -275,10 +287,26 @@ namespace llarp }; // look up this name async and start the entire chain of events - LookupNameAsync(name, [handleGotAddress, resultHandler](auto maybe_addr) { - if (maybe_addr) + lookup_name(name, [handleGotAddress, resultHandler](oxen::quic::message m) mutable { + if (m) { - handleGotAddress(*maybe_addr); + std::string name; + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + name = btdc.require("NAME"); + } + catch (...) + { + log::warning(log_cat, "Failed to parse find name response!"); + throw; + } + + if (auto saddr = service::Address(); saddr.FromString(name)) + handleGotAddress(saddr); + + if (auto rid = RouterID(); rid.FromString(name)) + handleGotAddress(rid); } else { @@ -342,23 +370,37 @@ namespace llarp { for (const auto& item : _startup_ons_mappings) { - LookupNameAsync( - item.first, [name = item.first, info = item.second, this](auto maybe_addr) { - if (maybe_addr.has_value()) - { - const auto maybe_range = info.first; - const auto maybe_auth = info.second; + auto& name = item.first; - _startup_ons_mappings.erase(name); - if (auto* addr = std::get_if(&*maybe_addr)) - { - if (maybe_range.has_value()) - _exit_map.Insert(*maybe_range, *addr); - if (maybe_auth.has_value()) - SetAuthInfoForEndpoint(*addr, *maybe_auth); - } - } - }); + lookup_name(name, [this, name, info = item.second](oxen::quic::message m) mutable { + if (m) + { + std::string result; + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + result = btdc.require("NAME"); + } + catch (...) + { + log::warning(log_cat, "Failed to parse find name response!"); + throw; + } + + const auto maybe_range = info.first; + const auto maybe_auth = info.second; + + _startup_ons_mappings.erase(name); + + if (auto saddr = service::Address(); saddr.FromString(result)) + { + if (maybe_range.has_value()) + _exit_map.Insert(*maybe_range, saddr); + if (maybe_auth.has_value()) + SetAuthInfoForEndpoint(saddr, *maybe_auth); + } + } + }); } } } @@ -388,33 +430,6 @@ namespace llarp return _state->name + ":" + _identity.pub.Name(); } - bool - Endpoint::HandleGotIntroMessage(dht::GotIntroMessage_constptr msg) - { - std::set remote; - for (const auto& introset : msg->found) - { - if (not introset.verify(Now())) - { - LogError(Name(), " got invalid introset"); - return false; - } - remote.insert(introset); - } - auto& lookups = _state->pending_lookups; - auto itr = lookups.find(msg->txid); - if (itr == lookups.end()) - { - LogWarn( - "invalid lookup response for hidden service endpoint ", Name(), " txid=", msg->txid); - return true; - } - std::unique_ptr lookup = std::move(itr->second); - lookups.erase(itr); - // lookup->HandleIntrosetResponse(remote); - return true; - } - bool Endpoint::HasInboundConvo(const Address& addr) const { @@ -819,40 +834,6 @@ namespace llarp } } - bool - Endpoint::HandleGotRouterMessage(dht::GotRouterMessage_constptr msg) - { - if (not msg->foundRCs.empty()) - { - for (auto& rc : msg->foundRCs) - { - router()->queue_work([this, rc, msg]() mutable { - bool valid = rc.Verify(llarp::time_now_ms()); - router()->loop()->call([this, valid, rc = std::move(rc), msg] { - router()->node_db()->PutIfNewer(rc); - HandleVerifyGotRouter(msg, rc.pubkey, valid); - }); - }); - } - } - else - { - auto& routers = _state->pending_routers; - auto itr = routers.begin(); - while (itr != routers.end()) - { - if (itr->second.txid == msg->txid) - { - itr->second.InformResult({}); - itr = routers.erase(itr); - } - else - ++itr; - } - } - return true; - } - bool Endpoint::HasExit() const { @@ -886,95 +867,57 @@ namespace llarp Endpoint::ReadyToDoLookup(size_t num_paths) const { // Currently just checks the number of paths, but could do more checks in the future. - return num_paths >= MIN_ENDPOINTS_FOR_LNS_LOOKUP; + return num_paths >= MIN_ONS_LOOKUP_ENDPOINTS; } void - Endpoint::LookupNameAsync( - std::string name, - std::function>)> handler) + Endpoint::lookup_name(std::string name, std::function func) { - if (not NameIsValid(name)) - { - handler(ParseAddress(name)); - return; - } - auto& cache = _state->nameCache; - const auto maybe = cache.Get(name); - if (maybe.has_value()) - { - handler(maybe); - return; - } - LogInfo(Name(), " looking up LNS name: ", name); + // TODO: so fuck all this? + + // if (not is_valid_name(name)) + // { + // handler(parse_address(name)); + // return; + // } + + // auto& cache = _state->nameCache; + // const auto maybe = cache.Get(name); + // if (maybe.has_value()) + // { + // handler(maybe); + // return; + // } + + log::info(log_cat, "{} looking up ONS name {}", Name(), name); auto paths = GetUniqueEndpointsForLookup(); - // not enough paths - if (not ReadyToDoLookup(paths.size())) - { - LogWarn( - Name(), - " not enough paths for lns lookup, have ", - paths.size(), - " need ", - MIN_ENDPOINTS_FOR_LNS_LOOKUP); - handler(std::nullopt); - return; - } - auto maybeInvalidateCache = [handler, &cache, name](auto result) { - if (result) - { - var::visit( - [&result, &cache, name](auto&& value) { - if (value.IsZero()) - { - cache.Remove(name); - result = std::nullopt; - } - }, - *result); - } - if (result) - { - cache.Put(name, *result); - } - handler(result); - }; + // // not enough paths + // if (not ReadyToDoLookup(paths.size())) + // { + // LogWarn( + // Name(), + // " not enough paths for lns lookup, have ", + // paths.size(), + // " need ", + // MIN_ONS_LOOKUP_ENDPOINTS); + // handler(std::nullopt); + // return; + // } - constexpr size_t max_lns_lookup_endpoints = 7; // pick up to max_unique_lns_endpoints random paths to do lookups from std::vector chosenpaths; chosenpaths.insert(chosenpaths.begin(), paths.begin(), paths.end()); std::shuffle(chosenpaths.begin(), chosenpaths.end(), CSRNG{}); - chosenpaths.resize(std::min(paths.size(), max_lns_lookup_endpoints)); - - auto resultHandler = - _state->lnsTracker.MakeResultHandler(name, chosenpaths.size(), maybeInvalidateCache); + chosenpaths.resize(std::min(paths.size(), MAX_ONS_LOOKUP_ENDPOINTS)); for (const auto& path : chosenpaths) { - LogInfo(Name(), " lookup ", name, " from ", path->Endpoint()); - auto job = new LookupNameJob{this, GenTXID(), name, resultHandler}; - job->SendRequestViaPath(path, router); + log::info(log_cat, "{} lookup {} from {}", Name(), name, path->Endpoint()); + path->find_name(name, func); } } - bool - Endpoint::HandleGotNameMessage(std::shared_ptr msg) - { - auto& lookups = _state->pending_lookups; - auto itr = lookups.find(msg->TxID); - if (itr == lookups.end()) - return false; - - // decrypt entry - const auto maybe = msg->result.Decrypt(itr->second->name); - // inform result - itr->second->HandleNameResponse(maybe); - lookups.erase(itr); - return true; - } - void Endpoint::EnsureRouterIsKnown(const RouterID& rid) { @@ -982,44 +925,24 @@ namespace llarp return; if (!router()->node_db()->Has(rid)) { - LookupRouterAnon(rid, nullptr); + lookup_router(rid); } } bool - Endpoint::LookupRouterAnon(RouterID rid, RouterLookupHandler handler) + Endpoint::lookup_router(RouterID rid) { using llarp::dht::FindRouterMessage; auto& routers = _state->pending_routers; + if (routers.find(rid) == routers.end()) { auto path = GetEstablishedPathClosestTo(rid); - routing::PathDHTMessage msg; - auto txid = GenTXID(); - msg.dht_msgs.emplace_back(std::make_unique(txid, rid)); - if (path) - msg.sequence_number = path->NextSeqNo(); - if (path && path->SendRoutingMessage(msg, router())) - { - RouterLookupJob job{this, [handler, rid, nodedb = router()->node_db()](auto results) { - if (results.empty()) - { - LogInfo("could not find ", rid, ", remove it from nodedb"); - nodedb->Remove(rid); - } - if (handler) - handler(results); - }}; - - assert(msg.dht_msgs.size() == 1); - auto dhtMsg = dynamic_cast(msg.dht_msgs[0].get()); - assert(dhtMsg != nullptr); - - routers.emplace(rid, std::move(job)); - return true; - } + path->find_router("find_router"); + return true; } + return false; } @@ -1278,87 +1201,10 @@ namespace llarp return dlt > path::ALIVE_TIMEOUT; } - bool - Endpoint::OnLookup( - const Address& addr, - std::optional introset, - const RouterID& endpoint, - llarp_time_t timeLeft, - uint64_t relayOrder) - { - // tell all our existing remote sessions about this introset update - - const auto now = router()->now(); - auto& lookups = _state->pending_service_lookups; - if (introset) - { - auto& sessions = _state->remote_sessions; - auto range = sessions.equal_range(addr); - auto itr = range.first; - while (itr != range.second) - { - itr->second->OnIntroSetUpdate(addr, introset, endpoint, timeLeft, relayOrder); - // we got a successful lookup - if (itr->second->ReadyToSend() and not introset->IsExpired(now)) - { - // inform all lookups - auto lookup_range = lookups.equal_range(addr); - auto i = lookup_range.first; - while (i != lookup_range.second) - { - i->second(addr, itr->second.get()); - ++i; - } - lookups.erase(addr); - } - ++itr; - } - } - auto& fails = _state->service_lookup_fails; - if (not introset or introset->IsExpired(now)) - { - LogError( - Name(), - " failed to lookup ", - addr.ToString(), - " from ", - endpoint, - " order=", - relayOrder); - fails[endpoint] = fails[endpoint] + 1; - - const auto pendingForAddr = std::count_if( - _state->pending_lookups.begin(), - _state->pending_lookups.end(), - [addr](const auto& item) -> bool { return item.second->IsFor(addr); }); - - // inform all if we have no more pending lookups for this address - if (pendingForAddr == 0) - { - auto range = lookups.equal_range(addr); - auto itr = range.first; - while (itr != range.second) - { - itr->second(addr, nullptr); - itr = lookups.erase(itr); - } - } - return false; - } - // check for established outbound context - - if (_state->remote_sessions.count(addr) > 0) - return true; - - PutNewOutboundContext(*introset, timeLeft); - return true; - } - void - Endpoint::MarkAddressOutbound(AddressVariant_t addr) + Endpoint::MarkAddressOutbound(service::Address addr) { - if (auto* ptr = std::get_if
(&addr)) - _state->m_OutboundSessions.insert(*ptr); + _state->m_OutboundSessions.insert(addr); } bool @@ -1381,6 +1227,126 @@ namespace llarp serviceLookups.erase(remote); } + bool + Endpoint::EnsurePathTo( + std::variant addr, + std::function)> hook, + llarp_time_t timeout) + { + if (auto ptr = std::get_if
(&addr)) + { + if (*ptr == _identity.pub.Addr()) + { + ConvoTag tag{}; + + if (auto maybe = GetBestConvoTagFor(*ptr)) + tag = *maybe; + else + tag.Randomize(); + PutSenderFor(tag, _identity.pub, true); + ConvoTagTX(tag); + Sessions()[tag].forever = true; + Loop()->call_soon([tag, hook]() { hook(tag); }); + return true; + } + if (not WantsOutboundSession(*ptr)) + { + // we don't want to connect back to inbound sessions + hook(std::nullopt); + return true; + } + + return EnsurePathToService( + *ptr, + [hook](auto, auto* ctx) { + if (ctx) + { + hook(ctx->currentConvoTag); + } + else + { + hook(std::nullopt); + } + }, + timeout); + } + if (auto ptr = std::get_if(&addr)) + { + return EnsurePathToSNode(*ptr, [hook](auto, auto session, auto tag) { + if (session) + { + hook(tag); + } + else + { + hook(std::nullopt); + } + }); + } + return false; + } + + bool + Endpoint::EnsurePathToSNode(const RouterID snode, SNodeEnsureHook h) + { + auto& nodeSessions = _state->snode_sessions; + + using namespace std::placeholders; + if (nodeSessions.count(snode) == 0) + { + const auto src = xhtonl(net::TruncateV6(GetIfAddr())); + const auto dst = xhtonl(net::TruncateV6(ObtainIPForAddr(snode))); + + auto session = std::make_shared( + snode, + [=](const llarp_buffer_t& buf) -> bool { + net::IPPacket pkt; + if (not pkt.Load(buf)) + return false; + pkt.UpdateIPv4Address(src, dst); + /// TODO: V6 + auto itr = _state->snode_sessions.find(snode); + if (itr == _state->snode_sessions.end()) + return false; + if (const auto maybe = itr->second->CurrentPath()) + return HandleInboundPacket( + ConvoTag{maybe->as_array()}, pkt.ConstBuffer(), ProtocolType::TrafficV4, 0); + return false; + }, + router(), + 1, + numHops, + false, + this); + _state->snode_sessions[snode] = session; + } + EnsureRouterIsKnown(snode); + auto range = nodeSessions.equal_range(snode); + auto itr = range.first; + while (itr != range.second) + { + if (itr->second->IsReady()) + h(snode, itr->second, ConvoTag{itr->second->CurrentPath()->as_array()}); + else + { + itr->second->AddReadyHook([h, snode](auto session) { + if (session) + { + h(snode, session, ConvoTag{session->CurrentPath()->as_array()}); + } + else + { + h(snode, nullptr, ConvoTag{}); + } + }); + if (not itr->second->BuildCooldownHit(Now())) + itr->second->BuildOne(); + } + ++itr; + } + return true; + } + bool Endpoint::EnsurePathToService( const Address remote, PathEnsureHook hook, [[maybe_unused]] llarp_time_t timeout) @@ -1476,67 +1442,6 @@ namespace llarp regen_and_publish_introset(); } - bool - Endpoint::EnsurePathToSNode(const RouterID snode, SNodeEnsureHook h) - { - auto& nodeSessions = _state->snode_sessions; - - using namespace std::placeholders; - if (nodeSessions.count(snode) == 0) - { - const auto src = xhtonl(net::TruncateV6(GetIfAddr())); - const auto dst = xhtonl(net::TruncateV6(ObtainIPForAddr(snode))); - - auto session = std::make_shared( - snode, - [=](const llarp_buffer_t& buf) -> bool { - net::IPPacket pkt; - if (not pkt.Load(buf)) - return false; - pkt.UpdateIPv4Address(src, dst); - /// TODO: V6 - auto itr = _state->snode_sessions.find(snode); - if (itr == _state->snode_sessions.end()) - return false; - if (const auto maybe = itr->second->CurrentPath()) - return HandleInboundPacket( - ConvoTag{maybe->as_array()}, pkt.ConstBuffer(), ProtocolType::TrafficV4, 0); - return false; - }, - router(), - 1, - numHops, - false, - this); - _state->snode_sessions[snode] = session; - } - EnsureRouterIsKnown(snode); - auto range = nodeSessions.equal_range(snode); - auto itr = range.first; - while (itr != range.second) - { - if (itr->second->IsReady()) - h(snode, itr->second, ConvoTag{itr->second->CurrentPath()->as_array()}); - else - { - itr->second->AddReadyHook([h, snode](auto session) { - if (session) - { - h(snode, session, ConvoTag{session->CurrentPath()->as_array()}); - } - else - { - h(snode, nullptr, ConvoTag{}); - } - }); - if (not itr->second->BuildCooldownHit(Now())) - itr->second->BuildOne(); - } - ++itr; - } - return true; - } - bool Endpoint::SendToOrQueue(ConvoTag tag, const llarp_buffer_t& pkt, ProtocolType t) { @@ -1699,65 +1604,6 @@ namespace llarp return std::nullopt; } - bool - Endpoint::EnsurePathTo( - std::variant addr, - std::function)> hook, - llarp_time_t timeout) - { - if (auto ptr = std::get_if
(&addr)) - { - if (*ptr == _identity.pub.Addr()) - { - ConvoTag tag{}; - - if (auto maybe = GetBestConvoTagFor(*ptr)) - tag = *maybe; - else - tag.Randomize(); - PutSenderFor(tag, _identity.pub, true); - ConvoTagTX(tag); - Sessions()[tag].forever = true; - Loop()->call_soon([tag, hook]() { hook(tag); }); - return true; - } - if (not WantsOutboundSession(*ptr)) - { - // we don't want to connect back to inbound sessions - hook(std::nullopt); - return true; - } - - return EnsurePathToService( - *ptr, - [hook](auto, auto* ctx) { - if (ctx) - { - hook(ctx->currentConvoTag); - } - else - { - hook(std::nullopt); - } - }, - timeout); - } - if (auto ptr = std::get_if(&addr)) - { - return EnsurePathToSNode(*ptr, [hook](auto, auto session, auto tag) { - if (session) - { - hook(tag); - } - else - { - hook(std::nullopt); - } - }); - } - return false; - } - bool Endpoint::HasConvoTag(const ConvoTag& t) const { diff --git a/llarp/service/endpoint.hpp b/llarp/service/endpoint.hpp index 8d65b0103e..c483f4f9f1 100644 --- a/llarp/service/endpoint.hpp +++ b/llarp/service/endpoint.hpp @@ -58,7 +58,9 @@ namespace llarp inline constexpr auto IntrosetLookupCooldown = 250ms; /// number of unique snodes we want to talk to do to ons lookups - inline constexpr size_t MIN_ENDPOINTS_FOR_LNS_LOOKUP = 2; + inline constexpr size_t MIN_ONS_LOOKUP_ENDPOINTS = 2; + + inline constexpr size_t MAX_ONS_LOOKUP_ENDPOINTS = 7; // TODO: delete this, it is copied from the late llarp/service/handler.hpp struct RecvDataEvent @@ -191,15 +193,6 @@ namespace llarp bool publish_introset(const EncryptedIntroSet& i); - bool - HandleGotIntroMessage(std::shared_ptr msg) override; - - bool - HandleGotRouterMessage(std::shared_ptr msg) override; - - bool - HandleGotNameMessage(std::shared_ptr msg) override; - bool HandleHiddenServiceFrame(path::Path_ptr p, const service::ProtocolFrameMessage& msg); @@ -244,16 +237,14 @@ namespace llarp void EnsureRouterIsKnown(const RouterID& router); - /// lookup a router via closest path + // "find router" via closest path bool - LookupRouterAnon(RouterID router, RouterLookupHandler handler); + lookup_router(RouterID router); + // "find name" void - LookupNameAsync( - std::string name, - std::function>)> resultHandler) - override; - + lookup_name(std::string name, std::function func) override; + // "find introset?"" void LookupServiceAsync( std::string name, @@ -308,7 +299,7 @@ namespace llarp WantsOutboundSession(const Address&) const; /// this MUST be called if you want to call EnsurePathTo on the given address - void MarkAddressOutbound(AddressVariant_t) override; + void MarkAddressOutbound(service::Address) override; bool ShouldBundleRC() const override @@ -488,14 +479,6 @@ namespace llarp void HandleVerifyGotRouter(dht::GotRouterMessage_constptr msg, RouterID id, bool valid); - bool - OnLookup( - const service::Address& addr, - std::optional i, - const RouterID& endpoint, - llarp_time_t timeLeft, - uint64_t relayOrder); - bool DoNetworkIsolation(bool failed); diff --git a/llarp/service/name.cpp b/llarp/service/name.cpp index a1af5f439e..056c62c239 100644 --- a/llarp/service/name.cpp +++ b/llarp/service/name.cpp @@ -17,7 +17,7 @@ namespace llarp::service } bool - NameIsValid(std::string_view lnsName) + is_valid_name(std::string_view lnsName) { // make sure it ends with .loki because no fucking shit right? if (not ends_with(lnsName, ".loki")) diff --git a/llarp/service/name.hpp b/llarp/service/name.hpp index 2f8779a4da..c16a8d025a 100644 --- a/llarp/service/name.hpp +++ b/llarp/service/name.hpp @@ -15,6 +15,6 @@ namespace llarp::service /// check if an lns name complies with the registration rules bool - NameIsValid(std::string_view name); + is_valid_name(std::string_view name); } // namespace llarp::service From 2cc02d7b609856b8bd4d9a364be8ff84b0407888 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Tue, 10 Oct 2023 20:30:14 -0400 Subject: [PATCH 048/312] handle path build requests, generate responses --- llarp/link/link_manager.cpp | 168 +++++++++++++++++++++++++++++++++++- llarp/messages/path.hpp | 13 ++- llarp/path/pathbuilder.cpp | 3 + llarp/util/aligned.hpp | 8 +- 4 files changed, 188 insertions(+), 4 deletions(-) diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index a566f7eb86..0522480473 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1062,14 +1062,178 @@ namespace llarp void LinkManager::handle_path_build(oxen::quic::message m) { + if (!router.path_context().AllowingTransit()) + { + log::warning("got path build request when not permitting transit"); + m.respond(serialize_response({{"STATUS", PathBuildMessage::NO_TRANSIT}}), true); + return; + } try { - oxenc::bt_dict_consumer btdc{m.body()}; + // not using list_consumer here because we need to move the first (our) frame + // to the end and re-send, unless we're the terminal hop. This could be done + // with list_consumer, but it would involve messy mucking around with the + // encoded list. Revisit if optimization issue (shouldn't be). + auto frame_list = oxenc::bt_deserialize(m.body()); + if (frames.size() != path::MAX_LEN) + { + log::info( + link_cat, + "Path build request has invalid number of records, ", + frame_list.size(), + "!=", + path::MAX_LEN); + m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_FRAMES}}), true); + return; + } + + const auto& hash = frame_list[0].at("hash"); + auto& frame_str = frame_list[0].at("frame"); + + oxenc::bt_dict_consumer frame_dict{frame_str}; + + auto hop_info = frame_dict.require("encrypted"); + TunnelNonce nonce; + nonce.from_string_view(frame_dict.require("nonce")); + Pubkey otherPubkey; + otherPubkey.from_string_view(frame_dict.require("pubkey")); + + auto crypto = CryptoManager::instance(); + + SharedSecret shared; + // derive shared secret using ephemeral pubkey and our secret key (and nonce) + if (!crypto->dh_server(shared, otherPubkey, router.identity(), nonce)) + { + log::info("DH failed during path build."); + m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true); + return; + } + + // hash data and check against given hash + ShortHash digest; + if (!crypto->hmac( + digest.data(), + reinterpret_cast(frame_str.data()), + frame_str.size(), + shared)) + { + log::error(link_cat, "HMAC failed on path build request"); + m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true); + return; + } + if (!std::equal( + digest.begin(), digest.end(), reinterpret_cast(hash.data()))) + { + log::info("HMAC mismatch on path build request"); + m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true); + return; + } + + // decrypt frame with our hop info + if (!crypto->xchacha20( + reinterpret_cast(hop_info.data()), hop_info.size(), shared, nonce)) + { + log::info("decrypt failed on path build request"); + m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true); + return; + } + + // populate transit hop object with hop info + // TODO: how to get downstream hop RouterID from here (all we have is oxen::quic::message) + // could do message->btstream->stream->connection_interface->connectionid + // and check our mapping, but that feels ugly as sin (and message->stream is private) + // TODO: also need downstream for IP / path build limiting clients + auto hop = std::make_shared(); + // hop->info.downstream = m.from(); // TODO: RouterID m.from() or similar + auto hop_dict = oxenc::bt_dict_consumer{hop_info}; + + // extract pathIDs and check if zero or used + hop->info.txID.from_string_view(hop_dict.require("txid")); + hop->info.rxID.from_string_view(hop_dict.require("rxid")); + if (info.txID.IsZero() || info.rxID.IsZero()) + { + log::info("Invalid PathID; PathIDs must be non-zero."); + m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_PATHID}}), true); + return; + } + hop->info.upstream.from_string_view(hop_dict.require("next"); + + // TODO: need downstream (above), and also the whole transit hop container is garbage. + // namely the PathID uniqueness checking uses the PathIDs and upstream/downstream + // but if someone made a path with txid, rxid, and downstream the same but + // a different upstream, that would be "unique" but we wouldn't know where + // to route messages (nevermind that messages don't currently know the RouterID + // they came from). + if (router.path_context.HasTransitHop(hop->info)) + { + log::info("Invalid PathID; PathIDs must be unique."); + m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_PATHID}}), true); + return; + } + + otherPubkey.from_string_view(hop_dict.require("commkey")); + nonce.from_string_view(hop_dict.require("nonce")); + + if (!crypto->dh_server(hop->pathKey, otherPubkey, router.identity(), nonce)) + { + log::info("DH failed during path build."); + m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true); + return; + } + // generate hash of hop key for nonce mutation + crypto->shorthash(hop->nonceXOR, hop->pathKey.data(), hop->pathKey.size()); + + // set and check path lifetime + hop->lifetime = 1ms * hop_dict.require("lifetime"); + if (hop->lifetime >= path::DEFAULT_LIFETIME) + { + log::info("path build attempt with too long of a lifetime."); + m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_LIFETIME}}), true); + return; + } + hop->started = router.now(); + router.persist_connection_until(hop->info.downstream, hop->ExpireTime() + 10s); + + if (hop->info.upstream == router.pubkey()) + { + // we are terminal hop and everything is okay + router.path_context.PutTransitHop(hop); + m.respond(serialize_response({{"STATUS", PathBuildMessage::OK}}), false); + return; + } + else + { + // rotate our frame to the end of the list and forward upstream + frame_list.splice(frame_list.end(), frame_list, frame_list.begin()); + + send_control_message( + hop->info.upstream, + "path_build", + bt_serialize(frame_list), + [hop, this, prev_message = std::move(m)](oxen::quic::message response) { + if (response) + { + log::info( + link_cat, + "Upstream returned successful path build response; giving hop info to Router, " + "then relaying response"); + router.path_context.PutTransitHop(hop); + m.respond(response.body_str(), false); + return; + } + else if (response.timed_out) + log::info(link_cat, "Upstream timed out on path build; relaying timeout"); + else + log::info(link_cat, "Upstream returned path build failure; relaying response"); + + m.respond(response.body_str(), true); + }); + } } catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); + m.respond(serialize_response({{"STATUS", PathBuildMessage::EXCEPTION}}), true); return; } } diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index 3dae963b98..0fb176f810 100644 --- a/llarp/messages/path.hpp +++ b/llarp/messages/path.hpp @@ -6,6 +6,14 @@ namespace llarp { namespace PathBuildMessage { + inline auto OK = "OK"sv; + inline auto EXCEPTION = "EXCEPTION"sv; + inline auto BAD_FRAMES = "BAD_FRAMES"sv; + inline auto BAD_CRYPTO = "BAD_CRYPTO"sv; + inline auto NO_TRANSIT = "NOT ALLOWING TRANSIT"sv; + inline auto BAD_PATHID = "BAD PATH ID"sv; + inline auto BAD_LIFETIME = "BAD PATH LIFETIME (TOO LONG)"sv; + inline static void setup_hop_keys(path::PathHopConfig& hop, const RouterID& nextHop) { @@ -64,7 +72,10 @@ namespace llarp // encrypt hop_info (mutates in-place) if (!crypto->xchacha20( - reinterpret_cast(hop_info.data()), hop_info.size(), shared, outer_nonce)) + reinterpret_cast(hop_info.data()), + hop_info.size(), + shared, + outer_nonce)) { log::error(path_cat, "Hop info encryption failed!"); throw std::runtime_error{"Hop info encrypttion failed"}; diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index 1110d31984..02cb7f328d 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -451,6 +451,9 @@ namespace llarp dummy.reserve(last_len); // append dummy frames; path build request must always have MAX_LEN frames + // TODO: with the data structured as it is now (bt-encoded dict as each frame) + // the dummy frames can't be completely random; they need to look like + // normal frames for (size_t i = 0; i < path::MAX_LEN - n_hops; i++) { randombytes(reinterpret_cast(dummy.data()), dummy.size()); diff --git a/llarp/util/aligned.hpp b/llarp/util/aligned.hpp index e1a1d6963b..302279787a 100644 --- a/llarp/util/aligned.hpp +++ b/llarp/util/aligned.hpp @@ -242,7 +242,7 @@ namespace llarp } bool - from_string(std::string b) + from_string_view(std::string_view b) { if (b.size() != sz) { @@ -254,6 +254,12 @@ namespace llarp return true; } + bool + from_string(std::string b) + { + return from_string_view(b); + } + bool bt_encode(llarp_buffer_t* buf) const { From c8dae875b55faee34fd33226dd1a517bdab31b55 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Wed, 11 Oct 2023 14:17:00 -0700 Subject: [PATCH 049/312] Path routing partially implementing - Reworking how paths to services and snodes - pushing for Tom to rebase for path handling --- llarp/dht/serviceaddresslookup.cpp | 1 - llarp/link/link_manager.cpp | 4 +- llarp/messages/dht.hpp | 3 +- llarp/path/path.cpp | 13 +- llarp/path/path.hpp | 7 + llarp/service/endpoint.cpp | 80 ++++----- llarp/service/endpoint.hpp | 18 +- llarp/service/outbound_context.cpp | 49 ++--- llarp/service/outbound_context.hpp | 278 ++++++++++++++--------------- llarp/service/sendcontext.cpp | 27 ++- llarp/service/sendcontext.hpp | 4 +- 11 files changed, 242 insertions(+), 242 deletions(-) diff --git a/llarp/dht/serviceaddresslookup.cpp b/llarp/dht/serviceaddresslookup.cpp index d769db3e98..44dc38b063 100644 --- a/llarp/dht/serviceaddresslookup.cpp +++ b/llarp/dht/serviceaddresslookup.cpp @@ -1,6 +1,5 @@ #include "serviceaddresslookup.hpp" -#include "context.hpp" #include #include #include diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 0522480473..7676400767 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -943,7 +943,6 @@ namespace llarp void LinkManager::handle_find_intro(oxen::quic::message m) { - std::string tag_name; ustring location; uint64_t relay_order, is_relayed; @@ -951,7 +950,6 @@ namespace llarp { oxenc::bt_dict_consumer btdc{m.body()}; - tag_name = btdc.require("N"); relay_order = btdc.require("O"); is_relayed = btdc.require("R"); location = btdc.require("S"); @@ -993,7 +991,7 @@ namespace llarp send_control_message( peer_key, "find_intro", - FindIntroMessage::serialize(dht::Key_t{peer_key}, tag_name, is_relayed, relay_order), + FindIntroMessage::serialize(dht::Key_t{peer_key}, is_relayed, relay_order), [original_msg = std::move(m)](oxen::quic::message relay_response) mutable { if (relay_response) log::info( diff --git a/llarp/messages/dht.hpp b/llarp/messages/dht.hpp index cc032afbb1..fc7f72055a 100644 --- a/llarp/messages/dht.hpp +++ b/llarp/messages/dht.hpp @@ -59,13 +59,12 @@ namespace llarp inline auto INSUFFICIENT_NODES = "INSUFFICIENT NODES"sv; inline static std::string - serialize(const dht::Key_t& location, std::string tag, bool is_relayed, uint64_t order) + serialize(const dht::Key_t& location, bool is_relayed, uint64_t order) { oxenc::bt_dict_producer btdp; try { - btdp.append("N", tag); btdp.append("O", order); btdp.append("R", is_relayed ? 1 : 0); btdp.append("S", location.ToView()); diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 5e554f0c96..deaf3a627c 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -62,11 +62,22 @@ namespace llarp::path EnterState(ePathBuilding, parent->Now()); } + void + Path::find_intro( + const dht::Key_t& location, + bool is_relayed, + uint64_t order, + std::function func) + { + send_path_control_message( + "find_intro", FindIntroMessage::serialize(location, is_relayed, order), std::move(func)); + } + void Path::find_name(std::string name, std::function func) { send_path_control_message( - "find_router", FindNameMessage::serialize(std::move(name)), std::move(func)); + "find_name", FindNameMessage::serialize(std::move(name)), std::move(func)); } void diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 1d90d81663..ad90b70ca7 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -283,6 +283,13 @@ namespace llarp void find_router(std::string rid, std::function func = nullptr); + void + find_intro( + const dht::Key_t& location, + bool is_relayed = false, + uint64_t order = 0, + std::function func = nullptr); + void send_path_control_message( std::string method, diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 818659a606..206e3a38e3 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -2,7 +2,6 @@ #include "endpoint_state.hpp" #include "endpoint_util.hpp" #include "auth.hpp" -#include "llarp/util/logging.hpp" #include "outbound_context.hpp" #include "protocol.hpp" #include "info.hpp" @@ -19,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -930,16 +931,14 @@ namespace llarp } bool - Endpoint::lookup_router(RouterID rid) + Endpoint::lookup_router(RouterID rid, std::function func) { - using llarp::dht::FindRouterMessage; - - auto& routers = _state->pending_routers; + const auto& routers = _state->pending_routers; if (routers.find(rid) == routers.end()) { auto path = GetEstablishedPathClosestTo(rid); - path->find_router("find_router"); + path->find_router("find_router", func); return true; } @@ -1287,7 +1286,9 @@ namespace llarp } bool - Endpoint::EnsurePathToSNode(const RouterID snode, SNodeEnsureHook h) + Endpoint::EnsurePathToSNode( + const RouterID snode, + std::function hook) { auto& nodeSessions = _state->snode_sessions; @@ -1326,17 +1327,17 @@ namespace llarp while (itr != range.second) { if (itr->second->IsReady()) - h(snode, itr->second, ConvoTag{itr->second->CurrentPath()->as_array()}); + hook(snode, itr->second, ConvoTag{itr->second->CurrentPath()->as_array()}); else { - itr->second->AddReadyHook([h, snode](auto session) { + itr->second->AddReadyHook([hook, snode](auto session) { if (session) { - h(snode, session, ConvoTag{session->CurrentPath()->as_array()}); + hook(snode, session, ConvoTag{session->CurrentPath()->as_array()}); } else { - h(snode, nullptr, ConvoTag{}); + hook(snode, nullptr, ConvoTag{}); } }); if (not itr->second->BuildCooldownHit(Now())) @@ -1349,7 +1350,9 @@ namespace llarp bool Endpoint::EnsurePathToService( - const Address remote, PathEnsureHook hook, [[maybe_unused]] llarp_time_t timeout) + const Address remote, + std::function hook, + [[maybe_unused]] llarp_time_t timeout) { if (not WantsOutboundSession(remote)) { @@ -1361,8 +1364,6 @@ namespace llarp /// how many routers to use for lookups static constexpr size_t NumParallelLookups = 2; - /// how many requests per router - static constexpr size_t RequestsPerLookup = 2; // add response hook to list for address. _state->pending_service_lookups.emplace(remote, hook); @@ -1387,9 +1388,7 @@ namespace llarp const auto paths = GetManyPathsWithUniqueEndpoints(this, NumParallelLookups); - using namespace std::placeholders; const dht::Key_t location = remote.ToKey(); - uint64_t order = 0; // flag to only add callback to list of callbacks for // address once. @@ -1397,36 +1396,28 @@ namespace llarp for (const auto& path : paths) { - for (size_t count = 0; count < RequestsPerLookup; ++count) - { - HiddenServiceAddressLookup* job = new HiddenServiceAddressLookup( - this, - [this](auto addr, auto result, auto from, auto left, auto order) { - return OnLookup(addr, result, from, left, order); - }, - location, - PubKey{remote.as_array()}, - path->Endpoint(), - order, - GenTXID(), - timeout + (2 * path->intro.latency) + IntrosetLookupGraceInterval); - LogInfo( - "doing lookup for ", - remote, - " via ", - path->Endpoint(), - " at ", - location, - " order=", - order); - order++; - if (job->SendRequestViaPath(path, router())) + path->find_intro(location, false, 0, [this, hook](oxen::quic::message m) mutable { + if (m) { - hookAdded = true; + std::string introset; + + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + introset = btdc.require("INTROSET"); + } + catch (...) + { + log::warning(log_cat, "Failed to parse find name response!"); + throw; + } + + service::EncryptedIntroSet enc{introset}; + router()->contacts()->services()->PutNode(std::move(enc)); + + // TODO: finish this } - else - LogError(Name(), " send via path failed for lookup"); - } + }); } return hookAdded; } @@ -1450,6 +1441,7 @@ namespace llarp LogWarn("SendToOrQueue failed: convo tag is zero"); return false; } + LogDebug(Name(), " send ", pkt.sz, " bytes on T=", tag); if (auto maybe = GetEndpointWithConvoTag(tag)) { diff --git a/llarp/service/endpoint.hpp b/llarp/service/endpoint.hpp index c483f4f9f1..00a292d290 100644 --- a/llarp/service/endpoint.hpp +++ b/llarp/service/endpoint.hpp @@ -239,11 +239,13 @@ namespace llarp // "find router" via closest path bool - lookup_router(RouterID router); + lookup_router(RouterID router, std::function func = nullptr); // "find name" void - lookup_name(std::string name, std::function func) override; + lookup_name( + std::string name, std::function func = nullptr) override; + // "find introset?"" void LookupServiceAsync( @@ -333,10 +335,6 @@ namespace llarp std::function)> hook, llarp_time_t timeout) override; - // passed a sendto context when we have a path established otherwise - // nullptr if the path was not made before the timeout - using PathEnsureHook = std::function; - static constexpr auto DefaultPathEnsureTimeout = 2s; /// return false if we have already called this function before for this @@ -344,17 +342,17 @@ namespace llarp bool EnsurePathToService( const Address remote, - PathEnsureHook h, + std::function h, llarp_time_t timeoutMS = DefaultPathEnsureTimeout); - using SNodeEnsureHook = std::function; - void InformPathToService(const Address remote, OutboundContext* ctx); /// ensure a path to a service node by public key bool - EnsurePathToSNode(const RouterID remote, SNodeEnsureHook h); + EnsurePathToSNode( + const RouterID remote, + std::function h); /// return true if this endpoint is trying to lookup this router right now bool diff --git a/llarp/service/outbound_context.cpp b/llarp/service/outbound_context.cpp index 630127ac39..18a920c1ea 100644 --- a/llarp/service/outbound_context.cpp +++ b/llarp/service/outbound_context.cpp @@ -31,7 +31,7 @@ namespace llarp::service bool OutboundContext::ShouldBundleRC() const { - return m_Endpoint->ShouldBundleRC(); + return service_endpoint->ShouldBundleRC(); } bool @@ -87,8 +87,8 @@ namespace llarp::service if (remoteIntro != m_NextIntro) { remoteIntro = m_NextIntro; - m_DataHandler->PutSenderFor(currentConvoTag, currentIntroSet.address_keys, false); - m_DataHandler->PutIntroFor(currentConvoTag, remoteIntro); + service_endpoint->PutSenderFor(currentConvoTag, currentIntroSet.address_keys, false); + service_endpoint->PutIntroFor(currentConvoTag, remoteIntro); ShiftIntroRouter(m_NextIntro.router); // if we have not made a handshake to the remote endpoint do so if (not IntroGenerated()) @@ -241,19 +241,19 @@ namespace llarp::service auto frame = std::make_shared(); frame->clear(); auto ex = std::make_shared( - m_Endpoint->Loop(), + service_endpoint->Loop(), remoteIdent, - m_Endpoint->GetIdentity(), + service_endpoint->GetIdentity(), currentIntroSet.sntru_pubkey, remoteIntro, - m_DataHandler, + service_endpoint, currentConvoTag, t); ex->hook = [self = shared_from_this(), path](auto frame) { if (not self->Send(std::move(frame), path)) return; - self->m_Endpoint->Loop()->call_later( + self->service_endpoint->Loop()->call_later( self->remoteIntro.latency, [self]() { self->sentIntro = true; }); }; @@ -263,9 +263,10 @@ namespace llarp::service frame->flag = 0; generatedIntro = true; // ensure we have a sender put for this convo tag - m_DataHandler->PutSenderFor(currentConvoTag, currentIntroSet.address_keys, false); + service_endpoint->PutSenderFor(currentConvoTag, currentIntroSet.address_keys, false); // encrypt frame async - m_Endpoint->router()->queue_work([ex, frame] { return AsyncKeyExchange::Encrypt(ex, frame); }); + service_endpoint->router()->queue_work( + [ex, frame] { return AsyncKeyExchange::Encrypt(ex, frame); }); LogInfo(Name(), " send intro frame T=", currentConvoTag); } @@ -287,7 +288,7 @@ namespace llarp::service m_LastIntrosetUpdateAt = now; // we want to use the parent endpoint's paths because outbound context // does not implement path::PathSet::HandleGotIntroMessage - const auto paths = GetManyPathsWithUniqueEndpoints(m_Endpoint, 2, location); + const auto paths = GetManyPathsWithUniqueEndpoints(service_endpoint, 2, location); [[maybe_unused]] uint64_t relayOrder = 0; for ([[maybe_unused]] const auto& path : paths) { @@ -352,7 +353,7 @@ namespace llarp::service // if we dont have a cached session key after sending intro we are in a fugged state so // expunge SharedSecret discardme; - if (not m_DataHandler->GetCachedSessionKeyFor(currentConvoTag, discardme)) + if (not service_endpoint->GetCachedSessionKeyFor(currentConvoTag, discardme)) { LogError(Name(), " no cached key after sending intro, we are in a fugged state, oh no"); return true; @@ -397,7 +398,7 @@ namespace llarp::service } // lookup router in intro if set and unknown if (not m_NextIntro.router.IsZero()) - m_Endpoint->EnsureRouterIsKnown(m_NextIntro.router); + service_endpoint->EnsureRouterIsKnown(m_NextIntro.router); if (ReadyToSend() and not m_ReadyHooks.empty()) { @@ -470,7 +471,7 @@ namespace llarp::service } if (m_NextIntro.router.IsZero()) return std::nullopt; - return GetHopsAlignedToForBuild(m_NextIntro.router, m_Endpoint->SnodeBlacklist()); + return GetHopsAlignedToForBuild(m_NextIntro.router, service_endpoint->SnodeBlacklist()); } bool @@ -538,7 +539,7 @@ namespace llarp::service { if (intro.ExpiresSoon(now)) continue; - if (m_Endpoint->SnodeBlacklist().count(intro.router)) + if (service_endpoint->SnodeBlacklist().count(intro.router)) continue; if (remoteIntro.router == intro.router) { @@ -554,9 +555,9 @@ namespace llarp::service /// pick newer intro not on same router for (const auto& intro : intros) { - if (m_Endpoint->SnodeBlacklist().count(intro.router)) + if (service_endpoint->SnodeBlacklist().count(intro.router)) continue; - m_Endpoint->EnsureRouterIsKnown(intro.router); + service_endpoint->EnsureRouterIsKnown(intro.router); if (intro.ExpiresSoon(now)) continue; if (m_NextIntro != intro) @@ -627,13 +628,13 @@ namespace llarp::service bool OutboundContext::HandleHiddenServiceFrame(path::Path_ptr p, const ProtocolFrameMessage& frame) { - m_LastInboundTraffic = m_Endpoint->Now(); + m_LastInboundTraffic = service_endpoint->Now(); m_GotInboundTraffic = true; if (frame.flag) { // handle discard ServiceInfo si; - if (!m_Endpoint->GetSenderFor(frame.convo_tag, si)) + if (!service_endpoint->GetSenderFor(frame.convo_tag, si)) { LogWarn("no sender for T=", frame.convo_tag); return false; @@ -651,7 +652,7 @@ namespace llarp::service if (const auto maybe = AuthResultCodeFromInt(frame.flag)) result.code = *maybe; SharedSecret sessionKey{}; - if (m_DataHandler->GetCachedSessionKeyFor(frame.convo_tag, sessionKey)) + if (service_endpoint->GetCachedSessionKeyFor(frame.convo_tag, sessionKey)) { ProtocolMessage msg{}; if (frame.DecryptPayloadInto(sessionKey, msg)) @@ -664,7 +665,7 @@ namespace llarp::service } } - m_Endpoint->RemoveConvoTag(frame.convo_tag); + service_endpoint->RemoveConvoTag(frame.convo_tag); if (authResultListener) { authResultListener(result); @@ -687,8 +688,8 @@ namespace llarp::service handler(result); }; } - const auto& ident = m_Endpoint->GetIdentity(); - if (not frame.AsyncDecryptAndVerify(m_Endpoint->Loop(), p, ident, m_Endpoint, hook)) + const auto& ident = service_endpoint->GetIdentity(); + if (not frame.AsyncDecryptAndVerify(service_endpoint->Loop(), p, ident, service_endpoint, hook)) { // send reset convo tag message LogError("failed to decrypt and verify frame"); @@ -700,8 +701,8 @@ namespace llarp::service f.Sign(ident); { LogWarn("invalidating convotag T=", frame.convo_tag); - m_Endpoint->RemoveConvoTag(frame.convo_tag); - m_Endpoint->_send_queue.tryPushBack( + service_endpoint->RemoveConvoTag(frame.convo_tag); + service_endpoint->_send_queue.tryPushBack( SendEvent_t{std::make_shared(f, frame.path_id), p}); } } diff --git a/llarp/service/outbound_context.hpp b/llarp/service/outbound_context.hpp index 8073487823..65e9ec8fd9 100644 --- a/llarp/service/outbound_context.hpp +++ b/llarp/service/outbound_context.hpp @@ -7,177 +7,173 @@ #include #include -namespace llarp +namespace llarp::service { - namespace service + struct AsyncKeyExchange; + struct Endpoint; + + /// context needed to initiate an outbound hidden service session + struct OutboundContext : public path::Builder, + public SendContext, + public std::enable_shared_from_this { - struct AsyncKeyExchange; - struct Endpoint; + OutboundContext(const IntroSet& introSet, Endpoint* parent); - /// context needed to initiate an outbound hidden service session - struct OutboundContext : public path::Builder, - public SendContext, - public std::enable_shared_from_this - { - OutboundContext(const IntroSet& introSet, Endpoint* parent); + ~OutboundContext() override; + + void + Tick(llarp_time_t now) override; + + util::StatusObject + ExtractStatus() const; - ~OutboundContext() override; + void + BlacklistSNode(const RouterID) override{}; - void - Tick(llarp_time_t now) override; + bool + ShouldBundleRC() const override; - util::StatusObject - ExtractStatus() const; + path::PathSet_ptr + GetSelf() override + { + return shared_from_this(); + } + + std::weak_ptr + GetWeak() override + { + return weak_from_this(); + } - void - BlacklistSNode(const RouterID) override{}; + Address + Addr() const; - bool - ShouldBundleRC() const override; + bool + Stop() override; - path::PathSet_ptr - GetSelf() override - { - return shared_from_this(); - } + bool + HandleDataDrop(path::Path_ptr p, const PathID_t& dst, uint64_t s); - std::weak_ptr - GetWeak() override - { - return weak_from_this(); - } + void + HandlePathDied(path::Path_ptr p) override; - Address - Addr() const; + /// set to true if we are updating the remote introset right now + bool updatingIntroSet; - bool - Stop() override; + /// update the current selected intro to be a new best introduction + /// return true if we have changed intros + bool + ShiftIntroduction(bool rebuild = true) override; - bool - HandleDataDrop(path::Path_ptr p, const PathID_t& dst, uint64_t s); + /// shift the intro off the current router it is using + void + ShiftIntroRouter(const RouterID remote) override; - void - HandlePathDied(path::Path_ptr p) override; + /// mark the current remote intro as bad + void + MarkCurrentIntroBad(llarp_time_t now) override; - /// set to true if we are updating the remote introset right now - bool updatingIntroSet; + void + MarkIntroBad(const Introduction& marked, llarp_time_t now); - /// update the current selected intro to be a new best introduction - /// return true if we have changed intros - bool - ShiftIntroduction(bool rebuild = true) override; + /// return true if we are ready to send + bool + ReadyToSend() const; - /// shift the intro off the current router it is using - void - ShiftIntroRouter(const RouterID remote) override; + void + AddReadyHook(std::function readyHook, llarp_time_t timeout); - /// mark the current remote intro as bad - void - MarkCurrentIntroBad(llarp_time_t now) override; + /// for exits + void + SendPacketToRemote(const llarp_buffer_t&, ProtocolType t) override; - void - MarkIntroBad(const Introduction& marked, llarp_time_t now); + bool + ShouldBuildMore(llarp_time_t now) const override; - /// return true if we are ready to send - bool - ReadyToSend() const; + /// pump internal state + /// return true to mark as dead + bool + Pump(llarp_time_t now); - void - AddReadyHook(std::function readyHook, llarp_time_t timeout); + /// return true if it's safe to remove ourselves + bool + IsDone(llarp_time_t now) const; - /// for exits - void - SendPacketToRemote(const llarp_buffer_t&, ProtocolType t) override; + bool + CheckPathIsDead(path::Path_ptr p, llarp_time_t dlt); - bool - ShouldBuildMore(llarp_time_t now) const override; + void + AsyncGenIntro(const llarp_buffer_t& payload, ProtocolType t) override; - /// pump internal state - /// return true to mark as dead - bool - Pump(llarp_time_t now); + /// issues a lookup to find the current intro set of the remote service + void + UpdateIntroSet() override; - /// return true if it's safe to remove ourselves - bool - IsDone(llarp_time_t now) const; + void + HandlePathBuilt(path::Path_ptr path) override; - bool - CheckPathIsDead(path::Path_ptr p, llarp_time_t dlt); + void + HandlePathBuildTimeout(path::Path_ptr path) override; - void - AsyncGenIntro(const llarp_buffer_t& payload, ProtocolType t) override; + void + HandlePathBuildFailedAt(path::Path_ptr path, RouterID hop) override; - /// issues a lookup to find the current intro set of the remote service - void - UpdateIntroSet() override; + std::optional> + GetHopsForBuild() override; - void - HandlePathBuilt(path::Path_ptr path) override; + bool + HandleHiddenServiceFrame(path::Path_ptr p, const ProtocolFrameMessage& frame); - void - HandlePathBuildTimeout(path::Path_ptr path) override; + std::string + Name() const override; - void - HandlePathBuildFailedAt(path::Path_ptr path, RouterID hop) override; + void + KeepAlive(); - std::optional> - GetHopsForBuild() override; + bool + ShouldKeepAlive(llarp_time_t now) const; - bool - HandleHiddenServiceFrame(path::Path_ptr p, const ProtocolFrameMessage& frame); - - std::string - Name() const override; - - void - KeepAlive(); - - bool - ShouldKeepAlive(llarp_time_t now) const; - - const IntroSet& - GetCurrentIntroSet() const - { - return currentIntroSet; - } - - llarp_time_t - RTT() const; - - bool - OnIntroSetUpdate( - const Address& addr, - std::optional i, - const RouterID& endpoint, - llarp_time_t, - uint64_t relayOrder); - - private: - /// swap remoteIntro with next intro - void - SwapIntros(); - - bool - IntroGenerated() const override; - bool - IntroSent() const override; - - const dht::Key_t location; - const Address addr; - uint64_t m_UpdateIntrosetTX = 0; - IntroSet currentIntroSet; - Introduction m_NextIntro; - llarp_time_t lastShift = 0s; - uint16_t m_LookupFails = 0; - uint16_t m_BuildFails = 0; - llarp_time_t m_LastInboundTraffic = 0s; - bool m_GotInboundTraffic = false; - bool generatedIntro = false; - bool sentIntro = false; - std::vector> m_ReadyHooks; - llarp_time_t m_LastIntrosetUpdateAt = 0s; - llarp_time_t m_LastKeepAliveAt = 0s; - }; - } // namespace service - -} // namespace llarp + const IntroSet& + GetCurrentIntroSet() const + { + return currentIntroSet; + } + + llarp_time_t + RTT() const; + + bool + OnIntroSetUpdate( + const Address& addr, + std::optional i, + const RouterID& endpoint, + llarp_time_t, + uint64_t relayOrder); + + private: + /// swap remoteIntro with next intro + void + SwapIntros(); + + bool + IntroGenerated() const override; + bool + IntroSent() const override; + + const dht::Key_t location; + const Address addr; + uint64_t m_UpdateIntrosetTX = 0; + IntroSet currentIntroSet; + Introduction m_NextIntro; + llarp_time_t lastShift = 0s; + uint16_t m_LookupFails = 0; + uint16_t m_BuildFails = 0; + llarp_time_t m_LastInboundTraffic = 0s; + bool m_GotInboundTraffic = false; + bool generatedIntro = false; + bool sentIntro = false; + std::vector> m_ReadyHooks; + llarp_time_t m_LastIntrosetUpdateAt = 0s; + llarp_time_t m_LastKeepAliveAt = 0s; + }; +} // namespace llarp::service diff --git a/llarp/service/sendcontext.cpp b/llarp/service/sendcontext.cpp index 5f400b5be3..e214dfc82f 100644 --- a/llarp/service/sendcontext.cpp +++ b/llarp/service/sendcontext.cpp @@ -16,8 +16,7 @@ namespace llarp::service : remoteIdent(std::move(ident)) , remoteIntro(intro) , m_PathSet(send) - , m_DataHandler(ep) - , m_Endpoint(ep) + , service_endpoint(ep) , createdAt(ep->Now()) , m_SendQueue(SendContextQueueSize) {} @@ -30,7 +29,7 @@ namespace llarp::service std::make_shared(*msg, remoteIntro.path_id), path)) == thread::QueueReturn::Success) { - m_Endpoint->router()->TriggerPump(); + service_endpoint->router()->TriggerPump(); return true; } return false; @@ -39,7 +38,7 @@ namespace llarp::service void SendContext::FlushUpstream() { - auto r = m_Endpoint->router(); + auto r = service_endpoint->router(); std::unordered_set flushpaths; auto rttRMS = 0ms; while (auto maybe = m_SendQueue.tryPopFront()) @@ -50,7 +49,7 @@ namespace llarp::service { lastGoodSend = r->now(); flushpaths.emplace(path); - m_Endpoint->ConvoTagTX(msg->protocol_frame_msg.convo_tag); + service_endpoint->ConvoTagTX(msg->protocol_frame_msg.convo_tag); const auto rtt = (path->intro.latency + remoteIntro.latency) * 2; rttRMS += rtt * rtt.count(); } @@ -85,7 +84,7 @@ namespace llarp::service return; } - if (!m_DataHandler->GetCachedSessionKeyFor(f->convo_tag, shared)) + if (!service_endpoint->GetCachedSessionKeyFor(f->convo_tag, shared)) { LogWarn( m_PathSet->Name(), @@ -95,10 +94,10 @@ namespace llarp::service } auto m = std::make_shared(); - m_DataHandler->PutIntroFor(f->convo_tag, remoteIntro); - m_DataHandler->PutReplyIntroFor(f->convo_tag, path->intro); + service_endpoint->PutIntroFor(f->convo_tag, remoteIntro); + service_endpoint->PutReplyIntroFor(f->convo_tag, path->intro); m->proto = t; - if (auto maybe = m_Endpoint->GetSeqNoForConvo(f->convo_tag)) + if (auto maybe = service_endpoint->GetSeqNoForConvo(f->convo_tag)) { m->seqno = *maybe; } @@ -109,11 +108,11 @@ namespace llarp::service } m->introReply = path->intro; f->path_id = m->introReply.path_id; - m->sender = m_Endpoint->GetIdentity().pub; + m->sender = service_endpoint->GetIdentity().pub; m->tag = f->convo_tag; m->PutBuffer(payload); - m_Endpoint->router()->queue_work([f, m, shared, path, this] { - if (not f->EncryptAndSign(*m, shared, m_Endpoint->GetIdentity())) + service_endpoint->router()->queue_work([f, m, shared, path, this] { + if (not f->EncryptAndSign(*m, shared, service_endpoint->GetIdentity())) { LogError(m_PathSet->Name(), " failed to sign message"); return; @@ -125,7 +124,7 @@ namespace llarp::service void SendContext::AsyncSendAuth(std::function resultHandler) { - if (const auto maybe = m_Endpoint->MaybeGetAuthInfoForEndpoint(remoteIdent.Addr())) + if (const auto maybe = service_endpoint->MaybeGetAuthInfoForEndpoint(remoteIdent.Addr())) { // send auth message const llarp_buffer_t authdata{maybe->token}; @@ -154,7 +153,7 @@ namespace llarp::service "to prevent bullshittery"); return; } - const auto maybe = m_Endpoint->MaybeGetAuthInfoForEndpoint(remoteIdent.Addr()); + const auto maybe = service_endpoint->MaybeGetAuthInfoForEndpoint(remoteIdent.Addr()); if (maybe.has_value()) { // send auth message diff --git a/llarp/service/sendcontext.hpp b/llarp/service/sendcontext.hpp index f67266fe5f..f5f5731514 100644 --- a/llarp/service/sendcontext.hpp +++ b/llarp/service/sendcontext.hpp @@ -39,8 +39,8 @@ namespace llarp::service Introduction remoteIntro; ConvoTag currentConvoTag; path::PathSet* const m_PathSet; - Endpoint* const m_DataHandler; - Endpoint* const m_Endpoint; + // Endpoint* const m_DataHandler; + Endpoint* const service_endpoint; uint64_t sequenceNo = 0; llarp_time_t lastGoodSend = 0s; const llarp_time_t createdAt; From 5ccec244705ddbf0effb0d3dc8bab56a35136a54 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 12 Oct 2023 06:43:07 -0700 Subject: [PATCH 050/312] callsafe - Added call_get to ev.hpp to queue event loop operations w/ a return value - de-mutexed NodeDB and made all operations via event loop. Some calls to NodeDB methods (like ::put_if_newer) were wrapped in call->get's, but some weren't. All function bodies were using mutex locks --- llarp/dht/context.cpp | 32 ++--- llarp/dht/explorenetworkjob.cpp | 50 ++++---- llarp/dht/explorenetworkjob.hpp | 37 +++--- llarp/dht/tx.hpp | 109 ++++++++-------- llarp/ev/ev.hpp | 46 +++++++ llarp/exit/session.cpp | 73 +++++++---- llarp/exit/session.hpp | 14 +-- llarp/handlers/tun.cpp | 46 ++++--- llarp/link/contacts.cpp | 15 +-- llarp/link/contacts.hpp | 2 +- llarp/link/link_manager.cpp | 167 +++++++++++++++--------- llarp/link/link_manager.hpp | 28 +++-- llarp/nodedb.cpp | 196 +++++++++++++++-------------- llarp/nodedb.hpp | 114 +++++++++-------- llarp/path/path.cpp | 2 +- llarp/path/pathbuilder.cpp | 6 +- llarp/router/rc_lookup_handler.cpp | 62 ++++++--- llarp/router/router.cpp | 116 ++++++----------- llarp/router/router.hpp | 29 ++--- llarp/service/endpoint.cpp | 4 +- 20 files changed, 631 insertions(+), 517 deletions(-) diff --git a/llarp/dht/context.cpp b/llarp/dht/context.cpp index aa7eca5d88..4bbc4572a3 100644 --- a/llarp/dht/context.cpp +++ b/llarp/dht/context.cpp @@ -42,22 +42,22 @@ namespace llarp::dht GetRouter()->rc_lookup_handler().check_rc(rc); } - void - LookupIntroSetRelayed( - const Key_t& target, - const Key_t& whoasked, - uint64_t whoaskedTX, - const Key_t& askpeer, - uint64_t relayOrder, - service::EncryptedIntroSetLookupHandler result = nullptr) override; - - void - LookupIntroSetDirect( - const Key_t& target, - const Key_t& whoasked, - uint64_t whoaskedTX, - const Key_t& askpeer, - service::EncryptedIntroSetLookupHandler result = nullptr) override; + // void + // LookupIntroSetRelayed( + // const Key_t& target, + // const Key_t& whoasked, + // uint64_t whoaskedTX, + // const Key_t& askpeer, + // uint64_t relayOrder, + // service::EncryptedIntroSetLookupHandler result = nullptr) override; + + // void + // LookupIntroSetDirect( + // const Key_t& target, + // const Key_t& whoasked, + // uint64_t whoaskedTX, + // const Key_t& askpeer, + // service::EncryptedIntroSetLookupHandler result = nullptr) override; /// on behalf of whoasked request router with public key target from dht /// router with key askpeer diff --git a/llarp/dht/explorenetworkjob.cpp b/llarp/dht/explorenetworkjob.cpp index 7ce2023f53..485228b3be 100644 --- a/llarp/dht/explorenetworkjob.cpp +++ b/llarp/dht/explorenetworkjob.cpp @@ -1,6 +1,5 @@ #include "explorenetworkjob.hpp" -#include "context.hpp" #include #include @@ -8,36 +7,33 @@ #include -namespace llarp +namespace llarp::dht { - namespace dht + void + ExploreNetworkJob::Start(const TXOwner& peer) { - void - ExploreNetworkJob::Start(const TXOwner& peer) + auto msg = new FindRouterMessage(peer.txid); + auto router = parent->GetRouter(); + if (router) { - auto msg = new FindRouterMessage(peer.txid); - auto router = parent->GetRouter(); - if (router) - { - router->notify_router_event(router->pubkey(), *msg); - } - parent->DHTSendTo(peer.node.as_array(), msg); + router->notify_router_event(router->pubkey(), *msg); } + parent->DHTSendTo(peer.node.as_array(), msg); + } - void - ExploreNetworkJob::SendReply() - { - llarp::LogDebug("got ", valuesFound.size(), " routers from exploration"); + void + ExploreNetworkJob::SendReply() + { + llarp::LogDebug("got ", valuesFound.size(), " routers from exploration"); - auto router = parent->GetRouter(); - for (const auto& pk : valuesFound) - { - // lookup router - if (router and router->node_db()->Has(pk)) - continue; - parent->LookupRouter( - pk, [router, pk](const auto& res) { router->HandleDHTLookupForExplore(pk, res); }); - } + auto router = parent->GetRouter(); + for (const auto& pk : valuesFound) + { + // lookup router + if (router and router->node_db()->Has(pk)) + continue; + parent->LookupRouter( + pk, [router, pk](const auto& res) { router->HandleDHTLookupForExplore(pk, res); }); } - } // namespace dht -} // namespace llarp + } +} // namespace llarp::dht diff --git a/llarp/dht/explorenetworkjob.hpp b/llarp/dht/explorenetworkjob.hpp index ac97ed778c..472246f83e 100644 --- a/llarp/dht/explorenetworkjob.hpp +++ b/llarp/dht/explorenetworkjob.hpp @@ -4,30 +4,27 @@ #include "tx.hpp" #include -namespace llarp +namespace llarp::dht { - namespace dht + struct ExploreNetworkJob : public TX { - struct ExploreNetworkJob : public TX - { - ExploreNetworkJob(const RouterID& peer, AbstractDHTMessageHandler* ctx) - : TX(TXOwner{}, peer, ctx) - {} + ExploreNetworkJob(const RouterID& peer, AbstractDHTMessageHandler* ctx) + : TX(TXOwner{}, peer, ctx) + {} - bool - Validate(const RouterID&) const override - { - // TODO: check with lokid - return true; - } + bool + Validate(const RouterID&) const override + { + // TODO: check with lokid + return true; + } - void - Start(const TXOwner& peer) override; + void + Start(const TXOwner& peer) override; - void - SendReply() override; - }; - } // namespace dht -} // namespace llarp + void + SendReply() override; + }; +} // namespace llarp::dht #endif diff --git a/llarp/dht/tx.hpp b/llarp/dht/tx.hpp index 02e5ec7ef8..72a75fca3e 100644 --- a/llarp/dht/tx.hpp +++ b/llarp/dht/tx.hpp @@ -9,74 +9,71 @@ #include #include -namespace llarp +namespace llarp::dht { - namespace dht - { - struct AbstractDHTMessageHandler; + struct AbstractDHTMessageHandler; - template - struct TX - { - K target; - AbstractDHTMessageHandler* parent; - std::set peersAsked; - std::vector valuesFound; - TXOwner whoasked; + template + struct TX + { + K target; + AbstractDHTMessageHandler* parent; + std::set peersAsked; + std::vector valuesFound; + TXOwner whoasked; - TX(const TXOwner& asker, const K& k, AbstractDHTMessageHandler* p) - : target(k), parent(p), whoasked(asker) - {} + TX(const TXOwner& asker, const K& k, AbstractDHTMessageHandler* p) + : target(k), parent(p), whoasked(asker) + {} - virtual ~TX() = default; + virtual ~TX() = default; - void - OnFound(const Key_t& askedPeer, const V& value); + void + OnFound(const Key_t& askedPeer, const V& value); - util::StatusObject - ExtractStatus() const - { - util::StatusObject obj{ - {"whoasked", whoasked.ExtractStatus()}, {"target", target.ExtractStatus()}}; - std::vector foundObjs; - std::transform( - valuesFound.begin(), - valuesFound.end(), - std::back_inserter(foundObjs), - [](const auto& item) -> util::StatusObject { return item.ExtractStatus(); }); + util::StatusObject + ExtractStatus() const + { + util::StatusObject obj{ + {"whoasked", whoasked.ExtractStatus()}, {"target", target.ExtractStatus()}}; + std::vector foundObjs; + std::transform( + valuesFound.begin(), + valuesFound.end(), + std::back_inserter(foundObjs), + [](const auto& item) -> util::StatusObject { return item.ExtractStatus(); }); - obj["found"] = foundObjs; - std::vector asked; - std::transform( - peersAsked.begin(), - peersAsked.end(), - std::back_inserter(asked), - [](const auto& item) -> std::string { return item.ToString(); }); - obj["asked"] = asked; - return obj; - } + obj["found"] = foundObjs; + std::vector asked; + std::transform( + peersAsked.begin(), + peersAsked.end(), + std::back_inserter(asked), + [](const auto& item) -> std::string { return item.ToString(); }); + obj["asked"] = asked; + return obj; + } - virtual bool - Validate(const V& value) const = 0; + virtual bool + Validate(const V& value) const = 0; - virtual void - Start(const TXOwner& peer) = 0; + virtual void + Start(const TXOwner& peer) = 0; - virtual void - SendReply() = 0; - }; + virtual void + SendReply() = 0; + }; - template - inline void - TX::OnFound(const Key_t& askedPeer, const V& value) + template + inline void + TX::OnFound(const Key_t& askedPeer, const V& value) + { + peersAsked.insert(askedPeer); + if (Validate(value)) { - peersAsked.insert(askedPeer); - if (Validate(value)) - { - valuesFound.push_back(value); - } + valuesFound.push_back(value); } - } // namespace dht -} // namespace llarp + } +} // namespace llarp::dht #endif diff --git a/llarp/ev/ev.hpp b/llarp/ev/ev.hpp index 6addbf3d5f..329a49b289 100644 --- a/llarp/ev/ev.hpp +++ b/llarp/ev/ev.hpp @@ -11,6 +11,8 @@ #include #include +using oxen::log::slns::source_location; + namespace uvw { class Loop; @@ -21,6 +23,21 @@ namespace llarp struct SockAddr; struct UDPHandle; + static auto loop_cat = llarp::log::Cat("ev-loop"); + + template + void + loop_trace_log( + const log::logger_ptr& cat_logger, + [[maybe_unused]] const source_location& location, + [[maybe_unused]] fmt::format_string fmt, + [[maybe_unused]] T&&... args) + { + if (cat_logger) + cat_logger->log( + log::detail::spdlog_sloc(location), log::Level::trace, fmt, std::forward(args)...); + } + namespace vpn { class NetworkInterface; @@ -143,6 +160,35 @@ namespace llarp }); } + /// Calls a function and synchronously obtains its return value. If called from within the + /// event loop, the function is called and returned immediately, otherwise a promise/future + /// is used with `call_soon` to block until the event loop comes around and calls the + /// function. + template ()())> + Ret + call_get(Callable&& f, source_location src = source_location::current()) + { + if (inEventLoop()) + { + loop_trace_log(loop_cat, src, "Event loop calling `{}`", src.function_name()); + return f(); + } + + std::promise prom; + auto fut = prom.get_future(); + call_soon([&f, &prom] { + try + { + prom.set_value(f()); + } + catch (...) + { + prom.set_exception(std::current_exception()); + } + }); + return fut.get(); + } + // Wraps a lambda with a lambda that triggers it to be called via loop->call() // when invoked. E.g.: // diff --git a/llarp/exit/session.cpp b/llarp/exit/session.cpp index 638a1c716e..c1b9bbcc93 100644 --- a/llarp/exit/session.cpp +++ b/llarp/exit/session.cpp @@ -19,14 +19,14 @@ namespace llarp::exit size_t hoplen, EndpointBase* parent) : llarp::path::Builder{r, numpaths, hoplen} - , m_ExitRouter{routerId} - , m_WritePacket{std::move(writepkt)} + , exit_router{routerId} + , packet_write_func{std::move(writepkt)} , m_Counter{0} , m_LastUse{r->now()} , m_BundleRC{false} , m_Parent{parent} { - CryptoManager::instance()->identity_keygen(m_ExitIdentity); + CryptoManager::instance()->identity_keygen(exit_key); } BaseSession::~BaseSession() = default; @@ -42,16 +42,16 @@ namespace llarp::exit { auto obj = path::Builder::ExtractStatus(); obj["lastExitUse"] = to_json(m_LastUse); - auto pub = m_ExitIdentity.toPublic(); + auto pub = exit_key.toPublic(); obj["exitIdentity"] = pub.ToString(); - obj["endpoint"] = m_ExitRouter.ToString(); + obj["endpoint"] = exit_router.ToString(); return obj; } bool BaseSession::LoadIdentityFromFile(const char* fname) { - return m_ExitIdentity.LoadFromFile(fname); + return exit_key.LoadFromFile(fname); } bool @@ -68,7 +68,7 @@ namespace llarp::exit void BaseSession::BlacklistSNode(const RouterID snode) { - m_SnodeBlacklist.insert(std::move(snode)); + snode_blacklist.insert(std::move(snode)); } std::optional> @@ -76,12 +76,12 @@ namespace llarp::exit { if (numHops == 1) { - if (auto maybe = router->node_db()->Get(m_ExitRouter)) + if (auto maybe = router->node_db()->get_rc(exit_router)) return std::vector{*maybe}; return std::nullopt; } else - return GetHopsAlignedToForBuild(m_ExitRouter); + return GetHopsAlignedToForBuild(exit_router); } bool @@ -103,13 +103,13 @@ namespace llarp::exit obtain.sequence_number = p->NextSeqNo(); obtain.tx_id = llarp::randint(); PopulateRequest(obtain); - if (!obtain.Sign(m_ExitIdentity)) + if (!obtain.Sign(exit_key)) { llarp::LogError("Failed to sign exit request"); return; } if (p->SendExitRequest(obtain, router)) - llarp::LogInfo("asking ", m_ExitRouter, " for exit"); + llarp::LogInfo("asking ", exit_router, " for exit"); else llarp::LogError("failed to send exit request"); } @@ -161,7 +161,7 @@ namespace llarp::exit { llarp::LogInfo(p->name(), " closing exit path"); routing::CloseExitMessage msg; - if (msg.Sign(m_ExitIdentity) && p->SendExitClose(msg, router)) + if (msg.Sign(exit_key) && p->SendExitClose(msg, router)) { p->ClearRoles(roles); } @@ -182,7 +182,7 @@ namespace llarp::exit { LogInfo(p->name(), " closing exit path"); routing::CloseExitMessage msg; - if (!(msg.Sign(m_ExitIdentity) && p->SendExitClose(msg, router))) + if (!(msg.Sign(exit_key) && p->SendExitClose(msg, router))) LogWarn(p->name(), " failed to send exit close message"); } }; @@ -209,7 +209,7 @@ namespace llarp::exit return true; } - if (m_WritePacket) + if (packet_write_func) { llarp::net::IPPacket pkt{buf.view_all()}; if (pkt.empty()) @@ -224,7 +224,7 @@ namespace llarp::exit bool BaseSession::HandleTrafficDrop(llarp::path::Path_ptr p, const PathID_t& path, uint64_t s) { - llarp::LogError("dropped traffic on exit ", m_ExitRouter, " S=", s, " P=", path); + llarp::LogError("dropped traffic on exit ", exit_router, " S=", s, " P=", path); p->EnterState(path::ePathIgnore, router->now()); return true; } @@ -309,16 +309,37 @@ namespace llarp::exit if (numHops == 1) { auto r = router; - if (const auto maybe = r->node_db()->Get(m_ExitRouter); maybe.has_value()) - r->TryConnectAsync(*maybe, 5); + if (const auto maybe = r->node_db()->get_rc(exit_router); maybe.has_value()) + r->connect_to(*maybe); else - r->LookupRouter(m_ExitRouter, [r](const std::vector& results) { - if (results.size()) - r->TryConnectAsync(results[0], 5); + r->lookup_router(exit_router, [r](oxen::quic::message m) mutable { + if (m) + { + std::string payload; + + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + payload = btdc.require("RC"); + } + catch (...) + { + log::warning(link_cat, "Failed to parse Find Router response!"); + throw; + } + + RouterContact result{std::move(payload)}; + r->node_db()->put_rc_if_newer(result); + r->connect_to(result); + } + else + { + r->link_manager().handle_find_router_error(std::move(m)); + } }); } else if (UrgentBuild(now)) - BuildOneAlignedTo(m_ExitRouter); + BuildOneAlignedTo(exit_router); } return true; } @@ -328,8 +349,8 @@ namespace llarp::exit { while (m_Downstream.size()) { - if (m_WritePacket) - m_WritePacket(const_cast(m_Downstream.top().second).steal()); + if (packet_write_func) + packet_write_func(const_cast(m_Downstream.top().second).steal()); m_Downstream.pop(); } } @@ -346,20 +367,20 @@ namespace llarp::exit { if (useRouterSNodeKey) { - m_ExitIdentity = r->identity(); + exit_key = r->identity(); } } std::string SNodeSession::Name() const { - return "SNode::" + m_ExitRouter.ToString(); + return "SNode::" + exit_router.ToString(); } std::string ExitSession::Name() const { - return "Exit::" + m_ExitRouter.ToString(); + return "Exit::" + exit_router.ToString(); } void diff --git a/llarp/exit/session.hpp b/llarp/exit/session.hpp index b654af8010..9be71f216c 100644 --- a/llarp/exit/session.hpp +++ b/llarp/exit/session.hpp @@ -117,7 +117,7 @@ namespace llarp const llarp::RouterID Endpoint() const { - return m_ExitRouter; + return exit_router; } std::optional @@ -138,9 +138,9 @@ namespace llarp AddReadyHook(SessionReadyFunc func); protected: - llarp::RouterID m_ExitRouter; - llarp::SecretKey m_ExitIdentity; - std::function m_WritePacket; + llarp::RouterID exit_router; + llarp::SecretKey exit_key; + std::function packet_write_func; virtual void PopulateRequest(llarp::routing::ObtainExitMessage& msg) const = 0; @@ -159,11 +159,9 @@ namespace llarp service::ProtocolType t); private: - std::set m_SnodeBlacklist; + std::set snode_blacklist; - using UpstreamTrafficQueue_t = std::deque; - using TieredQueue_t = std::map; - TieredQueue_t m_Upstream; + std::map> m_Upstream; PathID_t m_CurrentPath; diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 91285557c9..5c651624ef 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -624,23 +624,39 @@ namespace llarp::handlers RouterID snode; if (snode.FromString(qname)) { - router()->LookupRouter(snode, [reply, msg = std::move(msg)](const auto& found) mutable { - if (found.empty()) - { - msg.AddNXReply(); - } - else - { - std::string recs; - for (const auto& rc : found) - recs += rc.ToTXTRecord(); - msg.AddTXTReply(std::move(recs)); - } - reply(msg); - }); + router()->lookup_router( + snode, [r = router(), msg = std::move(msg), reply](oxen::quic::message m) mutable { + if (m) + { + std::string payload; + + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + payload = btdc.require("RC"); + } + catch (...) + { + log::warning(link_cat, "Failed to parse Find Router response!"); + throw; + } + + r->node_db()->put_rc_if_newer(RouterContact{payload}); + msg.AddTXTReply(payload); + } + else + { + msg.AddNXReply(); + r->link_manager().handle_find_router_error(std::move(m)); + } + + reply(msg); + }); + return true; } - else if (msg.questions[0].IsLocalhost() and msg.questions[0].HasSubdomains()) + + if (msg.questions[0].IsLocalhost() and msg.questions[0].HasSubdomains()) { const auto subdomain = msg.questions[0].Subdomains(); if (subdomain == "exit") diff --git a/llarp/link/contacts.cpp b/llarp/link/contacts.cpp index 5c5d1d08dd..ef58acaacf 100644 --- a/llarp/link/contacts.cpp +++ b/llarp/link/contacts.cpp @@ -70,19 +70,10 @@ namespace llarp } bool - Contacts::lookup_router(const RouterID& rid) + Contacts::lookup_router(const RouterID& rid, std::function func) { - dht::Key_t ask_peer; - - if (not _rc_nodes->FindClosest(dht::Key_t{rid}, ask_peer)) - return false; - - _router.loop()->call([this, rid]() { - _router.send_control_message( - rid, "find_router", FindRouterMessage::serialize(rid, false, false)); - }); - - return true; + return _router.send_control_message( + rid, "find_router", FindRouterMessage::serialize(rid, false, false), std::move(func)); } void diff --git a/llarp/link/contacts.hpp b/llarp/link/contacts.hpp index ed36b1a11f..c46c3a6c72 100644 --- a/llarp/link/contacts.hpp +++ b/llarp/link/contacts.hpp @@ -46,7 +46,7 @@ namespace llarp ExtractStatus() const; bool - lookup_router(const RouterID&); + lookup_router(const RouterID&, std::function = nullptr); void put_rc_node_async(const dht::RCNode& val); diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 7676400767..550a9f323f 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -54,7 +54,7 @@ namespace llarp auto& c = itr->second; auto& _scid = c->conn->scid(); - link_manager.router.loop()->call([this, scid = _scid, rid = _rid]() { + link_manager._router.loop()->call([this, scid = _scid, rid = _rid]() { endpoint->close_connection(scid); conns.erase(rid); @@ -111,7 +111,7 @@ namespace llarp auto& c = itr->second; auto& _scid = c->conn->scid(); - link_manager.router.loop()->call([this, scid = _scid, rid = _rid]() { + link_manager._router.loop()->call([this, scid = _scid, rid = _rid]() { endpoint->close_connection(scid); conns.erase(rid); @@ -137,7 +137,7 @@ namespace llarp for (const auto& [name, func] : rpc_commands) { s->register_command(name, [this, f = func](oxen::quic::message m) { - router.loop()->call([this, func = f, msg = std::move(m)]() mutable { + _router.loop()->call([this, func = f, msg = std::move(m)]() mutable { std::invoke(func, this, std::move(msg)); }); }); @@ -155,7 +155,7 @@ namespace llarp - will return a BTRequestStream on the first call to get_new_stream */ auto ep = quic->endpoint( - router.public_ip(), + _router.public_ip(), [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); @@ -178,11 +178,11 @@ namespace llarp } LinkManager::LinkManager(Router& r) - : router{r} + : _router{r} , quic{std::make_unique()} , tls_creds{oxen::quic::GNUTLSCreds::make_from_ed_keys( - {reinterpret_cast(router.identity().data()), size_t{32}}, - {reinterpret_cast(router.identity().toPublic().data()), size_t{32}})} + {reinterpret_cast(_router.identity().data()), size_t{32}}, + {reinterpret_cast(_router.identity().toPublic().data()), size_t{32}})} , ep{startup_endpoint(), *this} {} @@ -203,7 +203,7 @@ namespace llarp if (func) { func = [this, f = std::move(func)](oxen::quic::message m) mutable { - router.loop()->call([func = std::move(f), msg = std::move(m)]() mutable { func(msg); }); + _router.loop()->call([func = std::move(f), msg = std::move(m)]() mutable { func(msg); }); }; } @@ -226,7 +226,7 @@ namespace llarp return true; } - router.loop()->call([this, remote, endpoint, body, f = std::move(func)]() { + _router.loop()->call([this, remote, endpoint, body, f = std::move(func)]() { auto pending = PendingControlMessage(body, endpoint, f); auto [itr, b] = pending_conn_msg_queue.emplace(remote, MessageQueue()); @@ -260,7 +260,7 @@ namespace llarp return true; } - router.loop()->call([&]() { + _router.loop()->call([&]() { auto pending = PendingDataMessage(body); auto [itr, b] = pending_conn_msg_queue.emplace(remote, MessageQueue()); @@ -289,7 +289,7 @@ namespace llarp } void - LinkManager::connect_to(RouterID rid) + LinkManager::connect_to(const RouterID& rid) { rc_lookup->get_rc( rid, @@ -308,7 +308,7 @@ namespace llarp // This function assumes the RC has already had its signature verified and connection is allowed. void - LinkManager::connect_to(RouterContact rc) + LinkManager::connect_to(const RouterContact& rc) { if (auto conn = ep.get_conn(rc.pubkey); conn) { @@ -333,7 +333,7 @@ namespace llarp void LinkManager::on_conn_open(oxen::quic::connection_interface& ci) { - router.loop()->call([this, &conn_interface = ci]() { + _router.loop()->call([this, &conn_interface = ci]() { const auto& scid = conn_interface.scid(); const auto& rid = ep.connid_map[scid]; @@ -367,7 +367,7 @@ namespace llarp void LinkManager::on_conn_closed(oxen::quic::connection_interface& ci, uint64_t ec) { - router.loop()->call([this, &conn_interface = ci, error_code = ec]() { + _router.loop()->call([this, &conn_interface = ci, error_code = ec]() { const auto& scid = conn_interface.scid(); log::debug(quic_cat, "Purging quic connection CID:{} (ec: {})", scid, error_code); @@ -488,7 +488,7 @@ namespace llarp { is_stopping = false; rc_lookup = rcLookup; - node_db = router.node_db(); + node_db = _router.node_db(); } void @@ -543,7 +543,7 @@ namespace llarp m.respond(serialize_response({{"STATUS", FindNameMessage::EXCEPTION}}), true); } - router.rpc_client()->lookup_ons_hash( + _router.rpc_client()->lookup_ons_hash( name_hash, [this, msg = std::move(m)](std::optional maybe) mutable { if (maybe.has_value()) msg.respond(serialize_response({{"NAME", maybe->ciphertext}})); @@ -616,7 +616,7 @@ namespace llarp { log::warning(link_cat, "Exception: {}", e.what()); m.respond( - serialize_response({{"STATUS", FindRouterMessage::EXCEPTION}, {"RECIPIENT", ""}}), true); + serialize_response({{"STATUS", FindRouterMessage::EXCEPTION}, {"TARGET", ""}}), true); return; } @@ -626,31 +626,32 @@ 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().pubkey; const auto local_key = dht::Key_t{local_rid}; if (is_exploratory) { std::string neighbors{}; const auto closest_rcs = - router.node_db()->FindManyClosestTo(target_addr, RC_LOOKUP_STORAGE_REDUNDANCY); + _router.node_db()->find_many_closest_to(target_addr, RC_LOOKUP_STORAGE_REDUNDANCY); for (const auto& rc : closest_rcs) { const auto& rid = rc.pubkey; - if (router.router_profiling().IsBadForConnect(rid) || target_rid == rid || local_rid == rid) + if (_router.router_profiling().IsBadForConnect(rid) || target_rid == rid + || local_rid == rid) continue; - neighbors += oxenc::bt_serialize(rid.ToString()); + neighbors += rid.bt_encode(); } m.respond( - serialize_response({{"STATUS", FindRouterMessage::RETRY_EXP}, {"RECIPIENT", neighbors}}), + serialize_response({{"STATUS", FindRouterMessage::RETRY_EXP}, {"TARGET", neighbors}}), true); } else { - const auto closest_rc = router.node_db()->FindClosestTo(target_addr); + const auto closest_rc = _router.node_db()->find_closest_to(target_addr); const auto& closest_rid = closest_rc.pubkey; const auto closest_key = dht::Key_t{closest_rid}; @@ -668,7 +669,7 @@ namespace llarp } else { - m.respond(serialize_response({{"RC", closest_rc.ToString()}})); + m.respond(serialize_response({{"RC", closest_rc.bt_encode()}})); } } else if (not is_iterative) @@ -687,7 +688,7 @@ namespace llarp { m.respond( serialize_response( - {{"STATUS", FindRouterMessage::RETRY_ITER}, {"RECIPIENT", target_addr.data()}}), + {{"STATUS", FindRouterMessage::RETRY_ITER}, {"TARGET", target_addr.data()}}), true); } } @@ -696,7 +697,7 @@ namespace llarp m.respond( serialize_response( {{"STATUS", FindRouterMessage::RETRY_NEW}, - {"RECIPIENT", reinterpret_cast(closest_rid.data())}}), + {"TARGET", reinterpret_cast(closest_rid.data())}}), true); } } @@ -721,8 +722,8 @@ namespace llarp payload = btdc.require("RC"); else { - status = btdc.require("STATUS"); payload = btdc.require("RECIPIENT"); + status = btdc.require("TARGET"); } } catch (const std::exception& e) @@ -733,7 +734,7 @@ namespace llarp if (m) { - router.node_db()->PutIfNewer(RouterContact{payload}); + _router.node_db()->put_rc_if_newer(RouterContact{payload}); } else { @@ -767,6 +768,53 @@ namespace llarp } } + void + LinkManager::handle_find_router_error(oxen::quic::message&& m) + { + std::string status, payload; + + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + + payload = btdc.require("RECIPIENT"); + status = btdc.require("TARGET"); + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + return; + } + + if (status == FindRouterMessage::EXCEPTION) + { + log::info(link_cat, "FindRouterMessage failed with remote exception!"); + // Do something smart here probably + return; + } + + RouterID target{reinterpret_cast(payload.data())}; + + if (status == FindRouterMessage::RETRY_EXP) + { + log::info(link_cat, "FindRouterMessage failed, retrying as exploratory!"); + send_control_message( + target, "find_router", FindRouterMessage::serialize(target, false, true)); + } + else if (status == FindRouterMessage::RETRY_ITER) + { + log::info(link_cat, "FindRouterMessage failed, retrying as iterative!"); + send_control_message( + target, "find_router", FindRouterMessage::serialize(target, true, false)); + } + else if (status == FindRouterMessage::RETRY_NEW) + { + log::info(link_cat, "FindRouterMessage failed, retrying with new recipient!"); + send_control_message( + target, "find_router", FindRouterMessage::serialize(target, false, false)); + } + } + void LinkManager::handle_publish_intro(oxen::quic::message m) { @@ -797,9 +845,9 @@ namespace llarp return; } - const auto now = router.now(); + 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().pubkey; if (not service::EncryptedIntroSet::verify(introset, derived_signing_key, sig)) { @@ -815,7 +863,7 @@ namespace llarp return; } - auto closest_rcs = router.node_db()->FindManyClosestTo(addr, INTROSET_STORAGE_REDUNDANCY); + auto closest_rcs = _router.node_db()->find_many_closest_to(addr, INTROSET_STORAGE_REDUNDANCY); if (closest_rcs.size() != INTROSET_STORAGE_REDUNDANCY) { @@ -849,7 +897,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()->services()->PutNode(dht::ISNode{std::move(enc)}); m.respond(serialize_response({{"STATUS", ""}})); } else @@ -882,7 +930,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()->services()->PutNode(dht::ISNode{std::move(enc)}); m.respond(serialize_response()); } else @@ -973,7 +1021,7 @@ namespace llarp return; } - auto closest_rcs = router.node_db()->FindManyClosestTo(addr, INTROSET_STORAGE_REDUNDANCY); + auto closest_rcs = _router.node_db()->find_many_closest_to(addr, INTROSET_STORAGE_REDUNDANCY); if (closest_rcs.size() != INTROSET_STORAGE_REDUNDANCY) { @@ -1010,7 +1058,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)) m.respond(serialize_response({{"INTROSET", maybe_intro->bt_encode()}})); else { @@ -1048,7 +1096,7 @@ namespace llarp if (m) { service::EncryptedIntroSet enc{payload}; - router.contacts()->services()->PutNode(std::move(enc)); + _router.contacts()->services()->PutNode(std::move(enc)); } else { @@ -1060,7 +1108,7 @@ namespace llarp void LinkManager::handle_path_build(oxen::quic::message m) { - if (!router.path_context().AllowingTransit()) + if (!_router.path_context().AllowingTransit()) { log::warning("got path build request when not permitting transit"); m.respond(serialize_response({{"STATUS", PathBuildMessage::NO_TRANSIT}}), true); @@ -1100,7 +1148,7 @@ namespace llarp SharedSecret shared; // derive shared secret using ephemeral pubkey and our secret key (and nonce) - if (!crypto->dh_server(shared, otherPubkey, router.identity(), nonce)) + if (!crypto->dh_server(shared, otherPubkey, _router.identity(), nonce)) { log::info("DH failed during path build."); m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true); @@ -1162,7 +1210,7 @@ namespace llarp // a different upstream, that would be "unique" but we wouldn't know where // to route messages (nevermind that messages don't currently know the RouterID // they came from). - if (router.path_context.HasTransitHop(hop->info)) + if (_router.path_context.HasTransitHop(hop->info)) { log::info("Invalid PathID; PathIDs must be unique."); m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_PATHID}}), true); @@ -1172,7 +1220,7 @@ namespace llarp otherPubkey.from_string_view(hop_dict.require("commkey")); nonce.from_string_view(hop_dict.require("nonce")); - if (!crypto->dh_server(hop->pathKey, otherPubkey, router.identity(), nonce)) + if (!crypto->dh_server(hop->pathKey, otherPubkey, _router.identity(), nonce)) { log::info("DH failed during path build."); m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true); @@ -1189,13 +1237,13 @@ namespace llarp m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_LIFETIME}}), true); return; } - hop->started = router.now(); - router.persist_connection_until(hop->info.downstream, hop->ExpireTime() + 10s); + hop->started = _router.now(); + _router.persist_connection_until(hop->info.downstream, hop->ExpireTime() + 10s); - if (hop->info.upstream == router.pubkey()) + if (hop->info.upstream == _router.pubkey()) { // we are terminal hop and everything is okay - router.path_context.PutTransitHop(hop); + _router.path_context.PutTransitHop(hop); m.respond(serialize_response({{"STATUS", PathBuildMessage::OK}}), false); return; } @@ -1215,7 +1263,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.PutTransitHop(hop); m.respond(response.body_str(), false); return; } @@ -1361,17 +1409,17 @@ namespace llarp RouterID target{pubkey.data()}; auto transit_hop = std::static_pointer_cast( - router.path_context().GetByUpstream(target, PathID_t{to_usv(tx_id).data()})); + _router.path_context().GetByUpstream(target, PathID_t{to_usv(tx_id).data()})); const auto rx_id = transit_hop->info.rxID; const auto next_seqno = transit_hop->NextSeqNo(); auto success = (CryptoManager::instance()->verify(pubkey, to_usv(dict_data), sig) - and router.exitContext().ObtainNewExit(PubKey{pubkey.data()}, rx_id, flag != 0)); + and _router.exitContext().ObtainNewExit(PubKey{pubkey.data()}, rx_id, flag != 0)); m.respond( - ObtainExit::sign_and_serialize_response(router.identity(), next_seqno, tx_id), + ObtainExit::sign_and_serialize_response(_router.identity(), next_seqno, tx_id), not success); } catch (const std::exception& e) @@ -1408,9 +1456,9 @@ namespace llarp tx_id = btdc.require("T"); auto path_ptr = std::static_pointer_cast( - router.path_context().GetByDownstream(router.pubkey(), PathID_t{to_usv(tx_id).data()})); + _router.path_context().GetByDownstream(_router.pubkey(), PathID_t{to_usv(tx_id).data()})); - if (CryptoManager::instance()->verify(router.pubkey(), to_usv(dict_data), sig)) + if (CryptoManager::instance()->verify(_router.pubkey(), to_usv(dict_data), sig)) path_ptr->enable_exit_traffic(); } catch (const std::exception& e) @@ -1437,17 +1485,18 @@ namespace llarp tx_id = btdc.require("T"); auto transit_hop = std::static_pointer_cast( - router.path_context().GetByUpstream(router.pubkey(), PathID_t{to_usv(tx_id).data()})); + _router.path_context().GetByUpstream(_router.pubkey(), PathID_t{to_usv(tx_id).data()})); const auto next_seqno = transit_hop->NextSeqNo(); - if (auto exit_ep = router.exitContext().FindEndpointForPath(PathID_t{to_usv(path_id).data()})) + if (auto exit_ep = + _router.exitContext().FindEndpointForPath(PathID_t{to_usv(path_id).data()})) { if (CryptoManager::instance()->verify(exit_ep->PubKey().data(), to_usv(dict_data), sig)) { (exit_ep->UpdateLocalPath(transit_hop->info.rxID)) ? m.respond( - UpdateExit::sign_and_serialize_response(router.identity(), next_seqno, tx_id)) + UpdateExit::sign_and_serialize_response(_router.identity(), next_seqno, tx_id)) : m.respond(serialize_response({{"STATUS", UpdateExit::UPDATE_FAILED}}), true); } // If we fail to verify the message, no-op @@ -1487,9 +1536,9 @@ namespace llarp tx_id = btdc.require("T"); auto path_ptr = std::static_pointer_cast( - router.path_context().GetByDownstream(router.pubkey(), PathID_t{to_usv(tx_id).data()})); + _router.path_context().GetByDownstream(_router.pubkey(), PathID_t{to_usv(tx_id).data()})); - if (CryptoManager::instance()->verify(router.pubkey(), to_usv(dict_data), sig)) + if (CryptoManager::instance()->verify(_router.pubkey(), to_usv(dict_data), sig)) { if (path_ptr->update_exit(std::stoul(tx_id))) { @@ -1523,7 +1572,7 @@ namespace llarp tx_id = btdc.require("T"); auto transit_hop = std::static_pointer_cast( - router.path_context().GetByUpstream(router.pubkey(), PathID_t{to_usv(tx_id).data()})); + _router.path_context().GetByUpstream(_router.pubkey(), PathID_t{to_usv(tx_id).data()})); const auto rx_id = transit_hop->info.rxID; const auto next_seqno = transit_hop->NextSeqNo(); @@ -1533,7 +1582,7 @@ namespace llarp if (CryptoManager::instance()->verify(exit_ep->PubKey().data(), to_usv(dict_data), sig)) { exit_ep->Close(); - m.respond(CloseExit::sign_and_serialize_response(router.identity(), next_seqno, tx_id)); + m.respond(CloseExit::sign_and_serialize_response(_router.identity(), next_seqno, tx_id)); } } @@ -1574,10 +1623,10 @@ namespace llarp nonce = btdc.require("Y"); auto path_ptr = std::static_pointer_cast( - router.path_context().GetByDownstream(router.pubkey(), PathID_t{to_usv(tx_id).data()})); + _router.path_context().GetByDownstream(_router.pubkey(), PathID_t{to_usv(tx_id).data()})); if (path_ptr->SupportsAnyRoles(path::ePathRoleExit | path::ePathRoleSVC) - and CryptoManager::instance()->verify(router.pubkey(), to_usv(dict_data), sig)) + and CryptoManager::instance()->verify(_router.pubkey(), to_usv(dict_data), sig)) path_ptr->close_exit(); } catch (const std::exception& e) diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index b9bc52227b..03b5aca3c9 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -63,13 +63,11 @@ namespace llarp bool get_random_connection(RouterContact& router) const; - // DISCUSS: added template to forward callbacks/etc to endpoint->connect(...). - // This would be useful after combining link_manager with the redundant classes - // listed below. As a result, link_manager would be holding all the relevant - // callbacks, tls_creds, and other context required for endpoint management + template bool - establish_connection(const oxen::quic::Address& remote, RouterContact& rc, Opt&&... opts); + establish_connection( + const oxen::quic::Address& remote, const RouterContact& rc, Opt&&... opts); void for_each_connection(std::function func); @@ -151,6 +149,12 @@ namespace llarp bool send_data_message(const RouterID& remote, std::string data); + Router& + router() const + { + return _router; + } + private: bool send_control_message_impl( @@ -178,7 +182,7 @@ namespace llarp oxen::quic::Address addr; - Router& router; + Router& _router; // FIXME: Lokinet currently expects to be able to kill all network functionality before // finishing other shutdown things, including destroying this class, and that is all in @@ -228,10 +232,10 @@ namespace llarp deregister_peer(RouterID remote); void - connect_to(RouterID router); + connect_to(const RouterID& router); void - connect_to(RouterContact rc); + connect_to(const RouterContact& rc); void close_connection(RouterID rid); @@ -342,6 +346,12 @@ namespace llarp std::string serialize_response(oxenc::bt_dict supplement = {}); + + public: + // Public response functions and error handling functions invoked elsehwere. These take + // r-value references s.t. that message is taken out of calling scope + void + handle_find_router_error(oxen::quic::message&& m); }; namespace link @@ -349,7 +359,7 @@ namespace llarp template bool Endpoint::establish_connection( - const oxen::quic::Address& remote, RouterContact& rc, Opt&&... opts) + const oxen::quic::Address& remote, const RouterContact& rc, Opt&&... opts) { try { diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index e7e8f3900c..29b5de6b10 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -1,8 +1,8 @@ #include "nodedb.hpp" +#include "router_contact.hpp" #include "crypto/crypto.hpp" #include "crypto/types.hpp" -#include "router_contact.hpp" #include "util/buffer.hpp" #include "util/fs.hpp" #include "util/logging.hpp" @@ -58,15 +58,14 @@ namespace llarp constexpr auto FlushInterval = 5min; - NodeDB::NodeDB(fs::path root, std::function)> diskCaller) - : m_Root{std::move(root)} + NodeDB::NodeDB(fs::path root, std::function)> diskCaller, Router* r) + : router{*r} + , m_Root{std::move(root)} , disk(std::move(diskCaller)) , m_NextFlushAt{time_now_ms() + FlushInterval} { EnsureSkiplist(m_Root); } - NodeDB::NodeDB() : m_Root{}, disk{[](auto) {}}, m_NextFlushAt{0s} - {} void NodeDB::Tick(llarp_time_t now) @@ -79,21 +78,21 @@ namespace llarp m_NextFlushAt += FlushInterval; // make copy of all rcs std::vector copy; - for (const auto& item : m_Entries) + for (const auto& item : entries) copy.push_back(item.second.rc); // flush them to disk in one big job // TODO: split this up? idk maybe some day... disk([this, data = std::move(copy)]() { for (const auto& rc : data) { - rc.Write(GetPathForPubkey(rc.pubkey)); + rc.Write(get_path_by_pubkey(rc.pubkey)); } }); } } fs::path - NodeDB::GetPathForPubkey(RouterID pubkey) const + NodeDB::get_path_by_pubkey(RouterID pubkey) const { std::string hexString = oxenc::to_hex(pubkey.begin(), pubkey.end()); std::string skiplistDir; @@ -107,7 +106,7 @@ namespace llarp } void - NodeDB::LoadFromDisk() + NodeDB::load_from_disk() { if (m_Root.empty()) return; @@ -151,7 +150,7 @@ namespace llarp // validate signature and purge entries with invalid signatures // load ones with valid signatures if (rc.VerifySignature()) - m_Entries.emplace(rc.pubkey, rc); + entries.emplace(rc.pubkey, rc); else purge.emplace(f); @@ -169,94 +168,97 @@ namespace llarp } void - NodeDB::SaveToDisk() const + NodeDB::save_to_disk() const { if (m_Root.empty()) return; - for (const auto& item : m_Entries) - { - item.second.rc.Write(GetPathForPubkey(item.first)); - } + router.loop()->call([this]() { + for (const auto& item : entries) + item.second.rc.Write(get_path_by_pubkey(item.first)); + }); } bool - NodeDB::Has(RouterID pk) const + NodeDB::has_router(RouterID pk) const { - util::NullLock lock{m_Access}; - return m_Entries.find(pk) != m_Entries.end(); + return router.loop()->call_get([this, pk]() { return entries.find(pk) != entries.end(); }); } std::optional - NodeDB::Get(RouterID pk) const + NodeDB::get_rc(RouterID pk) const { - util::NullLock lock{m_Access}; - const auto itr = m_Entries.find(pk); - if (itr == m_Entries.end()) - return std::nullopt; - return itr->second.rc; + return router.loop()->call_get([this, pk]() -> std::optional { + const auto itr = entries.find(pk); + if (itr == entries.end()) + return std::nullopt; + return itr->second.rc; + }); } void - NodeDB::Remove(RouterID pk) + NodeDB::remove_router(RouterID pk) { - util::NullLock lock{m_Access}; - m_Entries.erase(pk); - AsyncRemoveManyFromDisk({pk}); + router.loop()->call([this, pk]() { + entries.erase(pk); + remove_many_from_disk_async({pk}); + }); } void - NodeDB::RemoveStaleRCs(std::unordered_set keep, llarp_time_t cutoff) + NodeDB::remove_stale_rcs(std::unordered_set keep, llarp_time_t cutoff) { - util::NullLock lock{m_Access}; - std::unordered_set removed; - auto itr = m_Entries.begin(); - while (itr != m_Entries.end()) - { - if (itr->second.insertedAt < cutoff and keep.count(itr->second.rc.pubkey) == 0) + router.loop()->call([this, keep, cutoff]() { + std::unordered_set removed; + auto itr = entries.begin(); + while (itr != entries.end()) { - removed.insert(itr->second.rc.pubkey); - itr = m_Entries.erase(itr); + if (itr->second.insertedAt < cutoff and keep.count(itr->second.rc.pubkey) == 0) + { + removed.insert(itr->second.rc.pubkey); + itr = entries.erase(itr); + } + else + ++itr; } - else - ++itr; - } - if (not removed.empty()) - AsyncRemoveManyFromDisk(std::move(removed)); + if (not removed.empty()) + remove_many_from_disk_async(std::move(removed)); + }); } void - NodeDB::Put(RouterContact rc) + NodeDB::put_rc(RouterContact rc) { - util::NullLock lock{m_Access}; - m_Entries.erase(rc.pubkey); - m_Entries.emplace(rc.pubkey, rc); + router.loop()->call([this, rc]() { + entries.erase(rc.pubkey); + entries.emplace(rc.pubkey, rc); + }); } size_t - NodeDB::NumLoaded() const + NodeDB::num_loaded() const { - util::NullLock lock{m_Access}; - return m_Entries.size(); + return router.loop()->call_get([this]() { return entries.size(); }); } void - NodeDB::PutIfNewer(RouterContact rc) + NodeDB::put_rc_if_newer(RouterContact rc) { - util::NullLock lock{m_Access}; - auto itr = m_Entries.find(rc.pubkey); - if (itr == m_Entries.end() or itr->second.rc.OtherIsNewer(rc)) - { - // delete if existing - if (itr != m_Entries.end()) - m_Entries.erase(itr); - // add new entry - m_Entries.emplace(rc.pubkey, rc); - } + router.loop()->call([this, rc]() { + auto itr = entries.find(rc.pubkey); + if (itr == entries.end() or itr->second.rc.OtherIsNewer(rc)) + { + // delete if existing + if (itr != entries.end()) + entries.erase(itr); + // add new entry + entries.emplace(rc.pubkey, rc); + } + }); } void - NodeDB::AsyncRemoveManyFromDisk(std::unordered_set remove) const + NodeDB::remove_many_from_disk_async(std::unordered_set remove) const { if (m_Root.empty()) return; @@ -264,7 +266,7 @@ namespace llarp std::set files; for (auto id : remove) { - files.emplace(GetPathForPubkey(std::move(id))); + files.emplace(get_path_by_pubkey(std::move(id))); } // remove them from the disk via the diskio thread disk([files]() { @@ -274,50 +276,50 @@ namespace llarp } llarp::RouterContact - NodeDB::FindClosestTo(llarp::dht::Key_t location) const + NodeDB::find_closest_to(llarp::dht::Key_t location) const { - util::NullLock lock{m_Access}; - llarp::RouterContact rc; - const llarp::dht::XorMetric compare(location); - VisitAll([&rc, compare](const auto& otherRC) { - if (rc.pubkey.IsZero()) - { - rc = otherRC; - return; - } - if (compare( - llarp::dht::Key_t{otherRC.pubkey.as_array()}, - llarp::dht::Key_t{rc.pubkey.as_array()})) - rc = otherRC; + return router.loop()->call_get([this, location]() { + llarp::RouterContact rc; + const llarp::dht::XorMetric compare(location); + VisitAll([&rc, compare](const auto& otherRC) { + if (rc.pubkey.IsZero()) + { + rc = otherRC; + return; + } + if (compare( + llarp::dht::Key_t{otherRC.pubkey.as_array()}, + llarp::dht::Key_t{rc.pubkey.as_array()})) + rc = otherRC; + }); + return rc; }); - return rc; } std::vector - NodeDB::FindManyClosestTo(llarp::dht::Key_t location, uint32_t numRouters) const + NodeDB::find_many_closest_to(llarp::dht::Key_t location, uint32_t numRouters) const { - util::NullLock lock{m_Access}; - std::vector all; + return router.loop()->call_get([this, location, numRouters]() { + std::vector all; - const auto& entries = m_Entries; - - all.reserve(entries.size()); - for (auto& entry : entries) - { - all.push_back(&entry.second.rc); - } + all.reserve(entries.size()); + for (auto& entry : entries) + { + all.push_back(&entry.second.rc); + } - auto it_mid = numRouters < all.size() ? all.begin() + numRouters : all.end(); - std::partial_sort( - all.begin(), it_mid, all.end(), [compare = dht::XorMetric{location}](auto* a, auto* b) { - return compare(*a, *b); - }); + auto it_mid = numRouters < all.size() ? all.begin() + numRouters : all.end(); + std::partial_sort( + all.begin(), it_mid, all.end(), [compare = dht::XorMetric{location}](auto* a, auto* b) { + return compare(*a, *b); + }); - std::vector closest; - closest.reserve(numRouters); - for (auto it = all.begin(); it != it_mid; ++it) - closest.push_back(**it); + std::vector closest; + closest.reserve(numRouters); + for (auto it = all.begin(); it != it_mid; ++it) + closest.push_back(**it); - return closest; + return closest; + }); } } // namespace llarp diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index 52330bc9ae..c1e5c2a988 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -2,12 +2,13 @@ #include "router_contact.hpp" #include "router_id.hpp" +#include "dht/key.hpp" +#include "crypto/crypto.hpp" #include "util/common.hpp" #include "util/fs.hpp" #include "util/thread/threading.hpp" #include "util/thread/annotations.hpp" -#include "dht/key.hpp" -#include "crypto/crypto.hpp" +#include #include #include @@ -19,6 +20,8 @@ namespace llarp { + struct Router; + class NodeDB { struct Entry @@ -27,12 +30,13 @@ namespace llarp llarp_time_t insertedAt; explicit Entry(RouterContact rc); }; + using NodeMap = std::unordered_map; - NodeMap m_Entries; + NodeMap entries; + const Router& router; const fs::path m_Root; - const std::function)> disk; llarp_time_t m_NextFlushAt; @@ -41,29 +45,30 @@ namespace llarp /// asynchronously remove the files for a set of rcs on disk given their public ident key void - AsyncRemoveManyFromDisk(std::unordered_set idents) const; + remove_many_from_disk_async(std::unordered_set idents) const; /// get filename of an RC file given its public ident key fs::path - GetPathForPubkey(RouterID pk) const; + get_path_by_pubkey(RouterID pk) const; public: - explicit NodeDB(fs::path rootdir, std::function)> diskCaller); + explicit NodeDB( + fs::path rootdir, std::function)> diskCaller, Router* r); /// in memory nodedb NodeDB(); /// load all entries from disk syncrhonously void - LoadFromDisk(); + load_from_disk(); /// explicit save all RCs to disk synchronously void - SaveToDisk() const; + save_to_disk() const; /// the number of RCs that are loaded from disk size_t - NumLoaded() const; + num_loaded() const; /// do periodic tasks like flush to disk and expiration void @@ -71,39 +76,39 @@ namespace llarp /// find the absolute closets router to a dht location RouterContact - FindClosestTo(dht::Key_t location) const; + find_closest_to(dht::Key_t location) const; /// find many routers closest to dht key std::vector - FindManyClosestTo(dht::Key_t location, uint32_t numRouters) const; + find_many_closest_to(dht::Key_t location, uint32_t numRouters) const; /// return true if we have an rc by its ident pubkey bool - Has(RouterID pk) const; + has_router(RouterID pk) const; /// maybe get an rc by its ident pubkey std::optional - Get(RouterID pk) const; + get_rc(RouterID pk) const; template std::optional GetRandom(Filter visit) const { - util::NullLock lock{m_Access}; + return router.loop()->call_get([this, visit]() -> std::optional { + std::vector entries; + for (const auto& entry : entries) + entries.push_back(entry); - std::vector entries; - for (const auto& entry : m_Entries) - entries.push_back(&entry); + std::shuffle(entries.begin(), entries.end(), llarp::CSRNG{}); - std::shuffle(entries.begin(), entries.end(), llarp::CSRNG{}); - - for (const auto entry : entries) - { - if (visit(entry->second.rc)) - return entry->second.rc; - } + for (const auto entry : entries) + { + if (visit(entry->second.rc)) + return entry->second.rc; + } - return std::nullopt; + return std::nullopt; + }); } /// visit all entries @@ -111,11 +116,10 @@ namespace llarp void VisitAll(Visit visit) const { - util::NullLock lock{m_Access}; - for (const auto& item : m_Entries) - { - visit(item.second.rc); - } + router.loop()->call([this, visit]() { + for (const auto& item : entries) + visit(item.second.rc); + }); } /// visit all entries inserted before a timestamp @@ -123,50 +127,52 @@ namespace llarp void VisitInsertedBefore(Visit visit, llarp_time_t insertedBefore) { - util::NullLock lock{m_Access}; - for (const auto& item : m_Entries) - { - if (item.second.insertedAt < insertedBefore) - visit(item.second.rc); - } + router.loop()->call([this, visit, insertedBefore]() { + for (const auto& item : entries) + { + if (item.second.insertedAt < insertedBefore) + visit(item.second.rc); + } + }); } /// remove an entry via its ident pubkey void - Remove(RouterID pk); + remove_router(RouterID pk); /// remove an entry given a filter that inspects the rc template void RemoveIf(Filter visit) { - util::NullLock lock{m_Access}; - std::unordered_set removed; - auto itr = m_Entries.begin(); - while (itr != m_Entries.end()) - { - if (visit(itr->second.rc)) + router.loop()->call([this, visit]() { + std::unordered_set removed; + auto itr = entries.begin(); + while (itr != entries.end()) { - removed.insert(itr->second.rc.pubkey); - itr = m_Entries.erase(itr); + if (visit(itr->second.rc)) + { + removed.insert(itr->second.rc.pubkey); + itr = entries.erase(itr); + } + else + ++itr; } - else - ++itr; - } - if (not removed.empty()) - AsyncRemoveManyFromDisk(std::move(removed)); + if (not removed.empty()) + remove_many_from_disk_async(std::move(removed)); + }); } /// remove rcs that are not in keep and have been inserted before cutoff void - RemoveStaleRCs(std::unordered_set keep, llarp_time_t cutoff); + remove_stale_rcs(std::unordered_set keep, llarp_time_t cutoff); /// put this rc into the cache if it is not there or newer than the one there already void - PutIfNewer(RouterContact rc); + put_rc_if_newer(RouterContact rc); /// unconditional put of rc into cache void - Put(RouterContact rc); + put_rc(RouterContact rc); }; } // namespace llarp diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index deaf3a627c..1d8e71c504 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -277,7 +277,7 @@ namespace llarp::path { r->loop()->call([nodedb = r->node_db(), router = *failedAt]() { LogInfo("router ", router, " is deregistered so we remove it"); - nodedb->Remove(router); + nodedb->remove_router(router); }); } } diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index 02cb7f328d..628cd8e00c 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -332,7 +332,7 @@ namespace llarp }; RouterContact endpointRC; - if (const auto maybe = router->node_db()->Get(endpoint)) + if (const auto maybe = router->node_db()->get_rc(endpoint)) { endpointRC = *maybe; } @@ -526,14 +526,14 @@ namespace llarp { log::info(path_cat, "Refreshed RouterContact for {}", rid); ; - r->node_db()->PutIfNewer(*rc); + r->node_db()->put_rc_if_newer(*rc); } else { // remove all connections to this router as it's probably not registered anymore log::warning(path_cat, "Removing router {} due to path build timeout", rid); r->link_manager().deregister_peer(rid); - r->node_db()->Remove(rid); + r->node_db()->remove_router(rid); } }, true); diff --git a/llarp/router/rc_lookup_handler.cpp b/llarp/router/rc_lookup_handler.cpp index 4b3b9250ee..9a0df0e5eb 100644 --- a/llarp/router/rc_lookup_handler.cpp +++ b/llarp/router/rc_lookup_handler.cpp @@ -68,7 +68,7 @@ namespace llarp RouterContact remoteRC; if (not forceLookup) { - if (const auto maybe = node_db->Get(router); maybe.has_value()) + if (const auto maybe = node_db->get_rc(router); maybe.has_value()) { remoteRC = *maybe; if (callback) @@ -95,14 +95,43 @@ namespace llarp if (shouldDoLookup) { + auto lookup_cb = [this](oxen::quic::message m) mutable { + auto& r = link_manager->router(); + + if (m) + { + std::string payload; + + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + payload = btdc.require("RC"); + } + catch (...) + { + log::warning(link_cat, "Failed to parse Find Router response!"); + throw; + } + + RouterContact result{std::move(payload)}; + r.node_db()->put_rc_if_newer(result); + r.connect_to(result); + } + else + { + link_manager->handle_find_router_error(std::move(m)); + } + }; + // if we are a client try using the hidden service endpoints if (!isServiceNode) { bool sent = false; LogInfo("Lookup ", router, " anonymously"); hidden_service_context->ForEachService( - [&](const std::string&, const std::shared_ptr& ep) -> bool { - const bool success = ep->lookup_router(router); + [&, cb = lookup_cb]( + const std::string&, const std::shared_ptr& ep) -> bool { + const bool success = ep->lookup_router(router, cb); sent = sent || success; return !success; }); @@ -111,7 +140,7 @@ namespace llarp LogWarn("cannot lookup ", router, " anonymously"); } - if (not contacts->lookup_router(router)) + if (not contacts->lookup_router(router, lookup_cb)) finalize_request(router, nullptr, RCRequestResult::RouterNotFound); else router_lookup_times[router] = std::chrono::steady_clock::now(); @@ -203,7 +232,7 @@ namespace llarp if (rc.IsPublicRouter()) { LogDebug("Adding or updating RC for ", RouterID(rc.pubkey), " to nodedb and dht."); - loop->call([rc, n = node_db] { n->PutIfNewer(rc); }); + loop->call([rc, n = node_db] { n->put_rc_if_newer(rc); }); contacts->put_rc_node_async(rc); } @@ -273,13 +302,13 @@ namespace llarp get_rc(router, nullptr, true); } - node_db->RemoveStaleRCs(boostrap_rid_list, now - RouterContact::StaleInsertionAge); + node_db->remove_stale_rcs(boostrap_rid_list, now - RouterContact::StaleInsertionAge); } void RCLookupHandler::explore_network() { - const size_t known = node_db->NumLoaded(); + const size_t known = node_db->num_loaded(); if (bootstrap_rc_list.empty() && known == 0) { LogError("we have no bootstrap nodes specified"); @@ -302,19 +331,20 @@ namespace llarp std::vector lookupRouters; lookupRouters.reserve(LookupPerTick); - const auto now = std::chrono::steady_clock::now(); + std::vector lrs = link_manager->router().loop()->call_get([this]() { + std::vector lookups; + lookups.reserve(LookupPerTick); + + const auto now = std::chrono::steady_clock::now(); - { - // if we are using a whitelist look up a few routers we don't have - util::Lock l(_mutex); for (const auto& r : router_whitelist) { - if (now > router_lookup_times[r] + RerequestInterval and not node_db->Has(r)) - { - lookupRouters.emplace_back(r); - } + if (now > router_lookup_times[r] + RerequestInterval and not node_db->has_router(r)) + lookups.emplace_back(r); } - } + + return lookups; + }); if (lookupRouters.size() > LookupPerTick) { diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index ad42e3027c..4826a721f5 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -1,31 +1,32 @@ -#include #include "router.hpp" +#include #include #include #include #include #include #include +#include #include +#include #include #include -#include +#include +#include #include #include #include #include -#include -#include - -#include #include +#include #include #include #include #include #include +#include #if defined(ANDROID) || defined(IOS) #include #endif @@ -95,7 +96,7 @@ namespace llarp return util::StatusObject{ {"running", true}, - {"numNodesKnown", _node_db->NumLoaded()}, + {"numNodesKnown", _node_db->num_loaded()}, {"contacts", _contacts->ExtractStatus()}, {"services", _hidden_service_context.ExtractStatus()}, {"exit", _exit_context.ExtractStatus()}, @@ -185,7 +186,7 @@ namespace llarp {"uptime", to_json(Uptime())}, {"numPathsBuilt", pathsCount}, {"numPeersConnected", peers}, - {"numRoutersKnown", _node_db->NumLoaded()}, + {"numRoutersKnown", _node_db->num_loaded()}, {"ratio", ratio}, {"txRate", tx_rate}, {"rxRate", rx_rate}, @@ -268,6 +269,28 @@ namespace llarp loop_wakeup->Trigger(); } + void + Router::connect_to(const RouterID& rid) + { + _link_manager.connect_to(rid); + } + + void + Router::connect_to(const RouterContact& rc) + { + _link_manager.connect_to(rc); + } + + void + Router::lookup_router(RouterID rid, std::function func) + { + _link_manager.send_control_message( + rid, + "find_router", + FindRouterMessage::serialize(std::move(rid), false, false), + std::move(func)); + } + bool Router::send_data_message(const RouterID& remote, const AbstractDataMessage& msg) { @@ -285,23 +308,6 @@ namespace llarp remote, std::move(ep), std::move(body), std::move(func)); } - void - Router::try_connect(fs::path rcfile) - { - RouterContact remote; - if (!remote.Read(rcfile.string().c_str())) - { - LogError("failure to decode or verify of remote RC"); - return; - } - if (remote.Verify(now())) - { - LogDebug("verified signature"); - _link_manager.connect_to(remote); - } - else - LogError(rcfile, " contains invalid RC"); - } void Router::for_each_connection(std::function func) { @@ -456,7 +462,7 @@ namespace llarp return false; } if (is_service_node) - _node_db->Put(router_contact); + _node_db->put_rc(router_contact); queue_disk_io([&]() { HandleSaveRC(); }); return true; } @@ -471,7 +477,7 @@ namespace llarp Router::insufficient_peers() const { constexpr int KnownPeerWarningThreshold = 5; - return node_db()->NumLoaded() < KnownPeerWarningThreshold; + return node_db()->num_loaded() < KnownPeerWarningThreshold; } std::optional @@ -826,7 +832,7 @@ namespace llarp Router::report_stats() { const auto now = llarp::time_now_ms(); - LogInfo(node_db()->NumLoaded(), " RCs loaded"); + LogInfo(node_db()->num_loaded(), " RCs loaded"); LogInfo(bootstrap_rc_list.size(), " bootstrap peers"); LogInfo(NumberOfConnectedRouters(), " router connections"); if (IsServiceNode()) @@ -851,7 +857,7 @@ namespace llarp fmt::format_to( out, " snode | known/svc/clients: {}/{}/{}", - node_db()->NumLoaded(), + node_db()->num_loaded(), NumberOfConnectedRouters(), NumberOfConnectedClients()); fmt::format_to( @@ -871,7 +877,7 @@ namespace llarp fmt::format_to( out, " client | known/connected: {}/{}", - node_db()->NumLoaded(), + node_db()->num_loaded(), NumberOfConnectedRouters()); if (auto ep = hidden_service_context().GetDefault()) @@ -1051,7 +1057,7 @@ namespace llarp log::error( logcat, "We appear to be an active service node, but have only {} known peers.", - node_db()->NumLoaded()); + node_db()->num_loaded()); _next_decomm_warning = now + DecommissionWarnInterval; } } @@ -1139,26 +1145,6 @@ namespace llarp } } - // TODO: refactor callers and remove this function - void - Router::LookupRouter(RouterID remote, RouterLookupHandler resultHandler) - { - _rc_lookup_handler.get_rc( - remote, - [=](const RouterID& id, const RouterContact* const rc, const RCRequestResult result) { - (void)id; - if (resultHandler) - { - std::vector routers; - if (result == RCRequestResult::Success && rc != nullptr) - { - routers.push_back(*rc); - } - resultHandler(routers); - } - }); - } - void Router::set_router_whitelist( const std::vector& whitelist, @@ -1255,19 +1241,19 @@ namespace llarp { LogInfo("Loading nodedb from disk..."); - _node_db->LoadFromDisk(); + _node_db->load_from_disk(); } _contacts = std::make_shared(llarp::dht::Key_t(pubkey()), *this); for (const auto& rc : bootstrap_rc_list) { - node_db()->Put(rc); + node_db()->put_rc(rc); _contacts->rc_nodes()->PutNode(rc); LogInfo("added bootstrap node ", RouterID{rc.pubkey}); } - LogInfo("have ", _node_db->NumLoaded(), " routers"); + LogInfo("have ", _node_db->num_loaded(), " routers"); _loop->call_every(ROUTER_TICK_INTERVAL, weak_from_this(), [this] { Tick(); }); _route_poker->start(); @@ -1386,7 +1372,7 @@ namespace llarp log::debug(logcat, "stopping links"); StopLinks(); log::debug(logcat, "saving nodedb to disk"); - node_db()->SaveToDisk(); + node_db()->save_to_disk(); _loop->call_later(200ms, [this] { AfterStopLinks(); }); } @@ -1486,26 +1472,6 @@ namespace llarp return true; } - bool - Router::TryConnectAsync(RouterContact rc, uint16_t tries) - { - (void)tries; - - if (rc.pubkey == pubkey()) - { - return false; - } - - if (not _rc_lookup_handler.is_session_allowed(rc.pubkey)) - { - return false; - } - - _link_manager.connect_to(rc); - - return true; - } - void Router::queue_work(std::function func) { diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index eafd591864..9d9b78c355 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -68,16 +67,6 @@ namespace llarp struct Contacts; - class RouteManager final /* : public Router */ - { - public: - std::shared_ptr - get_or_connect(); - - private: - std::shared_ptr ep; - }; - struct Router : std::enable_shared_from_this { explicit Router(EventLoop_ptr loop, std::shared_ptr vpnPlatform); @@ -186,6 +175,15 @@ namespace llarp void for_each_connection(std::function func); + void + lookup_router(RouterID rid, std::function = nullptr); + + void + connect_to(const RouterID& rid); + + void + connect_to(const RouterContact& rc); + Contacts* contacts() const { @@ -496,12 +494,6 @@ namespace llarp return seckey_topublic(_identity); } - void - try_connect(fs::path rcfile); - - bool - TryConnectAsync(RouterContact rc, uint16_t tries); - /// send to remote router or queue for sending /// returns false on overflow /// returns true on successful queue @@ -564,9 +556,6 @@ namespace llarp void HandleDHTLookupForExplore(RouterID remote, const std::vector& results); - void - LookupRouter(RouterID remote, RouterLookupHandler resultHandler); - bool HasSessionTo(const RouterID& remote) const; diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 206e3a38e3..01d8b678b2 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -240,7 +240,7 @@ namespace llarp // 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(router_id)) + if (auto maybe_rc = nodedb->get_rc(router_id)) { result = maybe_rc->srvRecords; } @@ -924,7 +924,7 @@ namespace llarp { if (rid.IsZero()) return; - if (!router()->node_db()->Has(rid)) + if (!router()->node_db()->has_router(rid)) { lookup_router(rid); } From 577f5e61ea03a6ff391b98005d3b526997b16ec0 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 12 Oct 2023 11:46:31 -0700 Subject: [PATCH 051/312] De-mutexing - mutexes in nodedb and rc_lookup_handler removed - implemented thread-safe queueing to event loop for previously locked accesses --- llarp/link/contacts.cpp | 10 +- llarp/link/link_manager.cpp | 68 +++-- llarp/nodedb.cpp | 127 ++++----- llarp/nodedb.hpp | 2 - llarp/path/pathbuilder.cpp | 42 ++- llarp/router/outbound_message_handler.hpp | 224 ---------------- llarp/router/outbound_session_maker.hpp | 146 ----------- llarp/router/rc_lookup_handler.cpp | 301 +++++++++------------- llarp/router/rc_lookup_handler.hpp | 63 ++--- llarp/router_contact.hpp | 6 + 10 files changed, 266 insertions(+), 723 deletions(-) delete mode 100644 llarp/router/outbound_message_handler.hpp delete mode 100644 llarp/router/outbound_session_maker.hpp diff --git a/llarp/link/contacts.cpp b/llarp/link/contacts.cpp index ef58acaacf..82c7b7b440 100644 --- a/llarp/link/contacts.cpp +++ b/llarp/link/contacts.cpp @@ -17,12 +17,14 @@ namespace llarp std::optional Contacts::get_introset_by_location(const dht::Key_t& key) const { - auto& introsets = _introset_nodes->nodes; + return _router.loop()->call_get([this, key]() -> std::optional { + auto& introsets = _introset_nodes->nodes; - if (auto itr = introsets.find(key); itr != introsets.end()) - return itr->second.introset; + if (auto itr = introsets.find(key); itr != introsets.end()) + return itr->second.introset; - return std::nullopt; + return std::nullopt; + }); } void diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 550a9f323f..1eaab490c9 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -232,17 +232,15 @@ namespace llarp auto [itr, b] = pending_conn_msg_queue.emplace(remote, MessageQueue()); itr->second.push_back(std::move(pending)); - rc_lookup->get_rc( - remote, - [this]( - [[maybe_unused]] const RouterID& rid, - const RouterContact* const rc, - const RCRequestResult res) { - if (res == RCRequestResult::Success) - connect_to(*rc); - else - log::warning(quic_cat, "Do something intelligent here for error handling"); - }); + rc_lookup->get_rc(remote, [this]([[maybe_unused]] auto rid, auto rc, auto success) { + if (success) + { + _router.node_db()->put_rc_if_newer(*rc); + connect_to(*rc); + } + else + log::warning(quic_cat, "Do something intelligent here for error handling"); + }); }); return false; @@ -266,17 +264,15 @@ namespace llarp auto [itr, b] = pending_conn_msg_queue.emplace(remote, MessageQueue()); itr->second.push_back(std::move(pending)); - rc_lookup->get_rc( - remote, - [this]( - [[maybe_unused]] const RouterID& rid, - const RouterContact* const rc, - const RCRequestResult res) { - if (res == RCRequestResult::Success) - connect_to(*rc); - else - log::warning(quic_cat, "Do something intelligent here for error handling"); - }); + rc_lookup->get_rc(remote, [this]([[maybe_unused]] auto rid, auto rc, auto success) { + if (success) + { + _router.node_db()->put_rc_if_newer(*rc); + connect_to(*rc); + } + else + log::warning(quic_cat, "Do something intelligent here for error handling"); + }); }); return false; @@ -291,19 +287,15 @@ namespace llarp void LinkManager::connect_to(const RouterID& rid) { - rc_lookup->get_rc( - rid, - [this]( - [[maybe_unused]] const RouterID& rid, - const RouterContact* const rc, - const RCRequestResult res) { - if (res == RCRequestResult::Success) - connect_to(*rc); - /* TODO: - else - RC lookup failure callback here - */ - }); + rc_lookup->get_rc(rid, [this]([[maybe_unused]] auto rid, auto rc, auto success) { + if (success) + { + _router.node_db()->put_rc_if_newer(*rc); + connect_to(*rc); + } + else + log::warning(quic_cat, "Do something intelligent here for error handling"); + }); } // This function assumes the RC has already had its signature verified and connection is allowed. @@ -771,6 +763,12 @@ namespace llarp void LinkManager::handle_find_router_error(oxen::quic::message&& m) { + if (m.timed_out) + { + log::info(link_cat, "FindRouterMessage timed out!"); + return; + } + std::string status, payload; try diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index 29b5de6b10..6b198496d8 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -75,18 +75,18 @@ namespace llarp if (now > m_NextFlushAt) { - m_NextFlushAt += FlushInterval; - // make copy of all rcs - std::vector copy; - for (const auto& item : entries) - copy.push_back(item.second.rc); - // flush them to disk in one big job - // 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)); - } + router.loop()->call([this]() { + m_NextFlushAt += FlushInterval; + // make copy of all rcs + std::vector copy; + for (const auto& item : entries) + copy.push_back(item.second.rc); + // flush them to disk in one big job + // 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)); + }); }); } } @@ -110,61 +110,64 @@ namespace llarp { if (m_Root.empty()) return; - std::set purge; - - for (const char& ch : skiplist_subdirs) - { - if (!ch) - continue; - std::string p; - p += ch; - fs::path sub = m_Root / p; - - llarp::util::IterDir(sub, [&](const fs::path& f) -> bool { - // skip files that are not suffixed with .signed - if (not(fs::is_regular_file(f) and f.extension() == RC_FILE_EXT)) - return true; - - RouterContact rc{}; - if (not rc.Read(f)) - { - // try loading it, purge it if it is junk - purge.emplace(f); - return true; - } + router.loop()->call([this]() { + std::set purge; - if (not rc.FromOurNetwork()) - { - // skip entries that are not from our network - return true; - } + for (const char& ch : skiplist_subdirs) + { + if (!ch) + continue; + std::string p; + p += ch; + fs::path sub = m_Root / p; + + llarp::util::IterDir(sub, [&](const fs::path& f) -> bool { + // skip files that are not suffixed with .signed + if (not(fs::is_regular_file(f) and f.extension() == RC_FILE_EXT)) + return true; + + RouterContact rc{}; + + 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())) + { + // rc expired dont load it and purge it later + purge.emplace(f); + return true; + } + + // validate signature and purge entries with invalid signatures + // load ones with valid signatures + if (rc.VerifySignature()) + entries.emplace(rc.pubkey, rc); + else + purge.emplace(f); - if (rc.IsExpired(time_now_ms())) - { - // rc expired dont load it and purge it later - purge.emplace(f); return true; - } - - // validate signature and purge entries with invalid signatures - // load ones with valid signatures - if (rc.VerifySignature()) - entries.emplace(rc.pubkey, rc); - else - purge.emplace(f); - - return true; - }); - } + }); + } - if (not purge.empty()) - { - log::warning(logcat, "removing {} invalid RCs from disk", purge.size()); + if (not purge.empty()) + { + log::warning(logcat, "removing {} invalid RCs from disk", purge.size()); - for (const auto& fpath : purge) - fs::remove(fpath); - } + for (const auto& fpath : purge) + fs::remove(fpath); + } + }); } void @@ -190,8 +193,10 @@ namespace llarp { return router.loop()->call_get([this, pk]() -> std::optional { const auto itr = entries.find(pk); + if (itr == entries.end()) return std::nullopt; + return itr->second.rc; }); } diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index c1e5c2a988..6082c28571 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -41,8 +41,6 @@ namespace llarp llarp_time_t m_NextFlushAt; - mutable util::NullMutex m_Access; - /// asynchronously remove the files for a set of rcs on disk given their public ident key void remove_many_from_disk_async(std::unordered_set idents) const; diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index 628cd8e00c..a48505bba2 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -515,29 +515,27 @@ namespace llarp DoPathBuildBackoff(); for (const auto& hop : p->hops) { - const RouterID rid{hop.rc.pubkey}; + const RouterID target{hop.rc.pubkey}; // look up router and see if it's still on the network - router->loop()->call_soon([rid, r = router]() { - log::info(path_cat, "Looking up RouterID {} due to path build timeout", rid); - r->rc_lookup_handler().get_rc( - rid, - [r](const auto& rid, const auto* rc, auto result) { - if (result == RCRequestResult::Success && rc != nullptr) - { - log::info(path_cat, "Refreshed RouterContact for {}", rid); - ; - r->node_db()->put_rc_if_newer(*rc); - } - else - { - // remove all connections to this router as it's probably not registered anymore - log::warning(path_cat, "Removing router {} due to path build timeout", rid); - r->link_manager().deregister_peer(rid); - r->node_db()->remove_router(rid); - } - }, - true); - }); + log::info(path_cat, "Looking up RouterID {} due to path build timeout", target); + + router->rc_lookup_handler().get_rc( + target, + [this](auto rid, auto rc, auto success) { + if (success && rc) + { + log::info(path_cat, "Refreshed RouterContact for {}", rid); + router->node_db()->put_rc_if_newer(*rc); + } + else + { + // remove all connections to this router as it's probably not registered anymore + log::warning(path_cat, "Removing router {} due to path build timeout", rid); + router->link_manager().deregister_peer(rid); + router->node_db()->remove_router(rid); + } + }, + true); } } diff --git a/llarp/router/outbound_message_handler.hpp b/llarp/router/outbound_message_handler.hpp deleted file mode 100644 index da688b75a7..0000000000 --- a/llarp/router/outbound_message_handler.hpp +++ /dev/null @@ -1,224 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -struct llarp_buffer_t; - -namespace llarp -{ - enum class SendStatus - { - Success, - Timeout, - NoLink, - InvalidRouter, - RouterNotFound, - Congestion - }; - - struct Router; - enum class SessionResult; - struct AbstractLinkMessage; - struct RouterID; - struct PathID_t; - - static const size_t MAX_PATH_QUEUE_SIZE = 100; - static const size_t MAX_OUTBOUND_QUEUE_SIZE = 1000; - static const size_t MAX_OUTBOUND_MESSAGES_PER_TICK = 500; - - using SendStatusHandler = std::function; - - struct OutboundMessageHandler final - { - public: - ~OutboundMessageHandler() = default; - - OutboundMessageHandler(size_t maxQueueSize = MAX_OUTBOUND_QUEUE_SIZE); - - /* Called to queue a message to be sent to a router. - * - * If there is no session with the destination router, the message is added to a - * pending session queue for that router. If there is no pending session to that - * router, one is created. - * - * If there is a session to the destination router, the message is placed on the shared - * outbound message queue to be processed on Pump(). - * - * When this class' Pump() is called, that queue is emptied and the messages there - * are placed in their paths' respective individual queues. - * - * Returns false if encoding the message into a buffer fails, true otherwise. - * A return value of true merely means we successfully processed the queue request, - * so for example an invalid destination still yields a true return. - */ - bool - QueueMessage(const RouterID& remote, const AbstractLinkMessage& msg, SendStatusHandler callback) - EXCLUDES(_mutex); - - /* Called when pumping output queues, typically scheduled via a call to Router::TriggerPump(). - * - * Processes messages on the shared message queue into their paths' respective - * individual queues. - * - * Removes the individual queues for paths which have died / expired, as informed by - * QueueRemoveEmptyPath. - * - * Sends all routing messages that have been queued, indicated by pathid 0 when queued. - * Sends messages from path queues until all are empty or a set cap has been reached. - */ - void - Pump(); - - /* Called from outside this class to inform it that a path has died / expired - * and its queue should be discarded. - */ - void - RemovePath(const PathID_t& pathid); - - util::StatusObject - ExtractStatus() const; - - void - Init(Router* router); - - private: - /* A message that has been queued for sending, but not yet - * processed into an individual path's message queue. - */ - struct MessageQueueEntry - { - uint16_t priority; - std::vector message; - SendStatusHandler inform; - PathID_t pathid; - RouterID router; - - bool - operator>(const MessageQueueEntry& other) const - { - return priority > other.priority; - } - }; - - struct MessageQueueStats - { - uint64_t queued = 0; - uint64_t dropped = 0; - uint64_t sent = 0; - uint32_t queueWatermark = 0; - - uint32_t perTickMax = 0; - uint32_t numTicks = 0; - }; - - using MessageQueue = util::ascending_priority_queue; - - /* If a session is not yet created with the destination router for a message, - * a special queue is created for that router and an attempt is made to - * establish a session. When this establish attempt concludes, either - * the messages are then sent to that router immediately, on success, or - * the messages are dropped and their send status callbacks are invoked with - * the appropriate send status. - */ - void - OnSessionResult(const RouterID& router, const SessionResult result); - - /* queues a message's send result callback onto the event loop */ - void - DoCallback(SendStatusHandler callback, SendStatus status); - - void - QueueSessionCreation(const RouterID& remote); - - bool - EncodeBuffer(const AbstractLinkMessage& msg, std::string& buf); - - /* sends the message along to the link layer, and hopefully out to the network - * - * returns the result of the call to LinkManager::SendTo() - */ - bool - Send(const MessageQueueEntry& ent); - - /* Sends the message along to the link layer if we have a session to the remote - * - * returns the result of the Send() call, or false if no session. - */ - bool - SendIfSession(const MessageQueueEntry& ent); - - /* queues a message to the shared outbound message queue. - * - * If the queue is full, the message is dropped and the message's status - * callback is invoked with a congestion status. - * - * When this class' Pump() is called, that queue is emptied and the messages there - * are placed in their paths' respective individual queues. - */ - bool - QueueOutboundMessage(MessageQueueEntry entry); - - /* Processes messages on the shared message queue into their paths' respective - * individual queues. - */ - void - ProcessOutboundQueue(); - - /* - * Sends routing messages that have been queued, indicated by pathid 0 when queued. - * - * Sends messages from path queues until all are empty or a set cap has been reached. - * This will send one message from each queue in a round-robin fashion such that they - * all have roughly equal access to bandwidth. A notion of priority may be introduced - * at a later time, but for now only routing messages get priority. - * - * Returns true if there is more to send (i.e. we hit the limit before emptying all path - * queues), false if all queues were drained. - */ - bool - SendRoundRobin(); - - /* Invoked when an outbound session establish attempt has concluded. - * - * If the outbound session was successfully created, sends any messages queued - * for that destination along to it. - * - * If the session was unsuccessful, invokes the send status callbacks of those - * queued messages and drops them. - */ - void - FinalizeSessionRequest(const RouterID& router, SendStatus status) EXCLUDES(_mutex); - - llarp::thread::Queue outboundQueue; - llarp::util::DecayingHashSet recentlyRemovedPaths; - bool removedSomePaths; - - mutable util::Mutex _mutex; // protects pendingSessionMessageQueues - - std::unordered_map pendingSessionMessageQueues GUARDED_BY(_mutex); - - std::unordered_map outboundMessageQueues; - - std::queue roundRobinOrder; - - Router* _router; - - util::ContentionKiller m_Killer; - - // paths cannot have pathid "0", so it can be used as the "pathid" - // for non-traffic (control) messages, so they can be prioritized. - static const PathID_t zeroID; - - MessageQueueStats m_queueStats; - }; - -} // namespace llarp diff --git a/llarp/router/outbound_session_maker.hpp b/llarp/router/outbound_session_maker.hpp deleted file mode 100644 index 6f2a871250..0000000000 --- a/llarp/router/outbound_session_maker.hpp +++ /dev/null @@ -1,146 +0,0 @@ -#pragma once - -/* - Note: - - this class is marked for destruction - - functionality to be absorbed into llarp/link/link_manager.hpp - - can be subdivided into multiple objects - -*/ - -#include "rc_lookup_handler.hpp" - -#include -#include -#include -#include - -#include -#include -#include - -namespace llarp -{ - struct PendingSession; - - struct LinkManager; - struct I_RCLookupHandler; - - enum class SessionResult - { - Establish, - Timeout, - RouterNotFound, - InvalidRouter, - NoLink, - EstablishFail - }; - - constexpr std::string_view - ToString(SessionResult sr) - { - return sr == llarp::SessionResult::Establish ? "success"sv - : sr == llarp::SessionResult::Timeout ? "timeout"sv - : sr == llarp::SessionResult::NoLink ? "no link"sv - : sr == llarp::SessionResult::InvalidRouter ? "invalid router"sv - : sr == llarp::SessionResult::RouterNotFound ? "not found"sv - : sr == llarp::SessionResult::EstablishFail ? "establish failed"sv - : "???"sv; - } - template <> - constexpr inline bool IsToStringFormattable = true; - - using RouterCallback = std::function; - - struct OutboundSessionMaker - { - using Work_t = std::function; - using WorkerFunc_t = std::function; - - using CallbacksQueue = std::list; - - public: - ~OutboundSessionMaker() = default; - - bool - OnSessionEstablished(AbstractLinkSession* session); - - void - OnConnectTimeout(AbstractLinkSession* session); - - void - CreateSessionTo(const RouterID& router, RouterCallback on_result) EXCLUDES(_mutex); - - void - CreateSessionTo(const RouterContact& rc, RouterCallback on_result) EXCLUDES(_mutex); - - bool - HavePendingSessionTo(const RouterID& router) const EXCLUDES(_mutex); - - void - ConnectToRandomRouters(int numDesired); - - util::StatusObject - ExtractStatus() const; - - bool - ShouldConnectTo(const RouterID& router) const EXCLUDES(_mutex); - - void - Init( - Router* router, - LinkManager* linkManager, - RCLookupHandler* rcLookup, - Profiling* profiler, - EventLoop_ptr loop, - WorkerFunc_t work); - - void - SetOurRouter(RouterID r) - { - us = std::move(r); - } - - /// always maintain this many connections to other routers - size_t minConnectedRouters = 4; - /// hard upperbound limit on the number of router to router connections - size_t maxConnectedRouters = 6; - - private: - void - GotRouterContact(const RouterID& router, const RouterContact& rc) EXCLUDES(_mutex); - - void - InvalidRouter(const RouterID& router); - - void - RouterNotFound(const RouterID& router); - - void - OnRouterContactResult( - const RouterID& router, const RouterContact* const rc, const RCRequestResult result); - - void - VerifyRC(const RouterContact rc); - - void - CreatePendingSession(const RouterID& router) EXCLUDES(_mutex); - - void - FinalizeRequest(const RouterID& router, const SessionResult type) EXCLUDES(_mutex); - - mutable util::Mutex _mutex; // protects pendingCallbacks - - std::unordered_map pendingCallbacks GUARDED_BY(_mutex); - - Router* _router = nullptr; - LinkManager* _linkManager = nullptr; - RCLookupHandler* _rcLookup = nullptr; - Profiling* _profiler = nullptr; - std::shared_ptr _nodedb; - EventLoop_ptr _loop; - WorkerFunc_t work; - RouterID us; - }; - -} // namespace llarp diff --git a/llarp/router/rc_lookup_handler.cpp b/llarp/router/rc_lookup_handler.cpp index 9a0df0e5eb..54ce72dcf9 100644 --- a/llarp/router/rc_lookup_handler.cpp +++ b/llarp/router/rc_lookup_handler.cpp @@ -18,17 +18,15 @@ namespace llarp { void - RCLookupHandler::add_valid_router(const RouterID& router) + RCLookupHandler::add_valid_router(const RouterID& rid) { - util::Lock l(_mutex); - router_whitelist.insert(router); + router->loop()->call([this, rid]() { router_whitelist.insert(rid); }); } void - RCLookupHandler::remove_valid_router(const RouterID& router) + RCLookupHandler::remove_valid_router(const RouterID& rid) { - util::Lock l(_mutex); - router_whitelist.erase(router); + router->loop()->call([this, rid]() { router_whitelist.erase(rid); }); } static void @@ -46,105 +44,102 @@ namespace llarp { if (whitelist.empty()) return; - util::Lock l(_mutex); - loadColourList(router_whitelist, whitelist); - loadColourList(router_greylist, greylist); - loadColourList(router_greenlist, greenlist); - - LogInfo("lokinet service node list now has ", router_whitelist.size(), " active routers"); + router->loop()->call([this, whitelist, greylist, greenlist]() { + loadColourList(router_whitelist, whitelist); + loadColourList(router_greylist, greylist); + loadColourList(router_greenlist, greenlist); + LogInfo("lokinet service node list now has ", router_whitelist.size(), " active routers"); + }); } bool RCLookupHandler::has_received_whitelist() const { - util::Lock l(_mutex); - return not router_whitelist.empty(); + return router->loop()->call_get([this]() { return not router_whitelist.empty(); }); + } + + std::unordered_set + RCLookupHandler::whitelist() const + { + return router->loop()->call_get([this]() { return router_whitelist; }); } void - RCLookupHandler::get_rc(const RouterID& router, RCRequestCallback callback, bool forceLookup) + RCLookupHandler::get_rc(const RouterID& rid, RCRequestCallback callback, bool forceLookup) { RouterContact remoteRC; + if (not forceLookup) { - if (const auto maybe = node_db->get_rc(router); maybe.has_value()) + if (const auto maybe = node_db->get_rc(rid); maybe.has_value()) { remoteRC = *maybe; + if (callback) { - callback(router, &remoteRC, RCRequestResult::Success); + callback(rid, remoteRC, true); } - finalize_request(router, &remoteRC, RCRequestResult::Success); + return; } } - bool shouldDoLookup = false; - - { - util::Lock l(_mutex); - auto itr_pair = pending_callbacks.emplace(router, callback_que{}); + auto lookup_cb = [this, callback, rid](oxen::quic::message m) mutable { + auto& r = link_manager->router(); - if (callback) + if (m) { - itr_pair.first->second.push_back(callback); - } - shouldDoLookup = itr_pair.second; - } + std::string payload; - if (shouldDoLookup) - { - auto lookup_cb = [this](oxen::quic::message m) mutable { - auto& r = link_manager->router(); + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + payload = btdc.require("RC"); + } + catch (...) + { + log::warning(link_cat, "Failed to parse Find Router response!"); + throw; + } + + RouterContact result{std::move(payload)}; - if (m) + if (callback) + callback(result.router_id(), result, true); + else { - std::string payload; - - try - { - oxenc::bt_dict_consumer btdc{m.body()}; - payload = btdc.require("RC"); - } - catch (...) - { - log::warning(link_cat, "Failed to parse Find Router response!"); - throw; - } - - RouterContact result{std::move(payload)}; r.node_db()->put_rc_if_newer(result); r.connect_to(result); } + } + else + { + if (callback) + callback(rid, std::nullopt, false); else - { link_manager->handle_find_router_error(std::move(m)); - } - }; - - // if we are a client try using the hidden service endpoints - if (!isServiceNode) - { - bool sent = false; - LogInfo("Lookup ", router, " anonymously"); - hidden_service_context->ForEachService( - [&, cb = lookup_cb]( - const std::string&, const std::shared_ptr& ep) -> bool { - const bool success = ep->lookup_router(router, cb); - sent = sent || success; - return !success; - }); - if (sent) - return; - LogWarn("cannot lookup ", router, " anonymously"); } + }; - if (not contacts->lookup_router(router, lookup_cb)) - finalize_request(router, nullptr, RCRequestResult::RouterNotFound); - else - router_lookup_times[router] = std::chrono::steady_clock::now(); + // if we are a client try using the hidden service endpoints + if (!isServiceNode) + { + bool sent = false; + LogInfo("Lookup ", rid, " anonymously"); + hidden_service_context->ForEachService( + [&, cb = lookup_cb]( + const std::string&, const std::shared_ptr& ep) -> bool { + const bool success = ep->lookup_router(rid, cb); + sent = sent || success; + return !success; + }); + if (sent) + return; + LogWarn("cannot lookup ", rid, " anonymously"); } + + contacts->lookup_router(rid, lookup_cb); } bool @@ -159,58 +154,56 @@ namespace llarp if (not useWhitelist) return false; - util::Lock lock{_mutex}; - - return router_greylist.count(remote); + return router->loop()->call_get([this, remote]() { return router_greylist.count(remote); }); } bool RCLookupHandler::is_green_listed(const RouterID& remote) const { - util::Lock lock{_mutex}; - return router_greenlist.count(remote); + return router->loop()->call_get([this, remote]() { return router_greenlist.count(remote); }); } bool - RCLookupHandler::is_registered(const RouterID& remote) const + RCLookupHandler::is_registered(const RouterID& rid) const { - util::Lock lock{_mutex}; - return router_whitelist.count(remote) || router_greylist.count(remote) - || router_greenlist.count(remote); + return router->loop()->call_get([this, rid]() { + return router_whitelist.count(rid) || router_greylist.count(rid) + || router_greenlist.count(rid); + }); } bool - RCLookupHandler::is_path_allowed(const RouterID& remote) const + RCLookupHandler::is_path_allowed(const RouterID& rid) const { - if (strict_connect_pubkeys.size() && strict_connect_pubkeys.count(remote) == 0 - && !is_remote_in_bootstrap(remote)) - { - return false; - } - - if (not useWhitelist) - return true; + return router->loop()->call_get([this, rid]() { + if (strict_connect_pubkeys.size() && strict_connect_pubkeys.count(rid) == 0 + && !is_remote_in_bootstrap(rid)) + { + return false; + } - util::Lock lock{_mutex}; + if (not useWhitelist) + return true; - return router_whitelist.count(remote); + return router_whitelist.count(rid) != 0; + }); } bool - RCLookupHandler::is_session_allowed(const RouterID& remote) const + RCLookupHandler::is_session_allowed(const RouterID& rid) const { - if (strict_connect_pubkeys.size() && strict_connect_pubkeys.count(remote) == 0 - && !is_remote_in_bootstrap(remote)) - { - return false; - } - - if (not useWhitelist) - return true; + return router->loop()->call_get([this, rid]() { + if (strict_connect_pubkeys.size() && strict_connect_pubkeys.count(rid) == 0 + && !is_remote_in_bootstrap(rid)) + { + return false; + } - util::Lock lock{_mutex}; + if (not useWhitelist) + return true; - return router_whitelist.count(remote) or router_greylist.count(remote); + return router_whitelist.count(rid) or router_greylist.count(rid); + }); } bool @@ -232,7 +225,7 @@ namespace llarp if (rc.IsPublicRouter()) { LogDebug("Adding or updating RC for ", RouterID(rc.pubkey), " to nodedb and dht."); - loop->call([rc, n = node_db] { n->put_rc_if_newer(rc); }); + node_db->put_rc_if_newer(rc); contacts->put_rc_node_async(rc); } @@ -246,18 +239,18 @@ namespace llarp } bool - RCLookupHandler::get_random_whitelist_router(RouterID& router) const + RCLookupHandler::get_random_whitelist_router(RouterID& rid) const { - util::Lock l(_mutex); - - const auto sz = router_whitelist.size(); - auto itr = router_whitelist.begin(); - if (sz == 0) - return false; - if (sz > 1) - std::advance(itr, randint() % sz); - router = *itr; - return true; + return router->loop()->call_get([this, rid]() mutable { + const auto sz = router_whitelist.size(); + auto itr = router_whitelist.begin(); + if (sz == 0) + return false; + if (sz > 1) + std::advance(itr, randint() % sz); + rid = *itr; + return true; + }); } bool @@ -290,11 +283,7 @@ namespace llarp std::unordered_set routersToLookUp; node_db->VisitInsertedBefore( - [&](const RouterContact& rc) { - if (has_pending_lookup(rc.pubkey)) - return; - routersToLookUp.insert(rc.pubkey); - }, + [&](const RouterContact& rc) { routersToLookUp.insert(rc.pubkey); }, now - RouterContact::UpdateInterval); for (const auto& router : routersToLookUp) @@ -325,34 +314,28 @@ namespace llarp if (useWhitelist) { - static constexpr auto RerequestInterval = 10min; static constexpr size_t LookupPerTick = 5; - std::vector lookupRouters; - lookupRouters.reserve(LookupPerTick); - - std::vector lrs = link_manager->router().loop()->call_get([this]() { + std::vector lookup_routers = router->loop()->call_get([this]() { std::vector lookups; lookups.reserve(LookupPerTick); - const auto now = std::chrono::steady_clock::now(); - for (const auto& r : router_whitelist) { - if (now > router_lookup_times[r] + RerequestInterval and not node_db->has_router(r)) + if (not node_db->has_router(r)) lookups.emplace_back(r); } return lookups; }); - if (lookupRouters.size() > LookupPerTick) + if (lookup_routers.size() > LookupPerTick) { - std::shuffle(lookupRouters.begin(), lookupRouters.end(), CSRNG{}); - lookupRouters.resize(LookupPerTick); + std::shuffle(lookup_routers.begin(), lookup_routers.end(), CSRNG{}); + lookup_routers.resize(LookupPerTick); } - for (const auto& r : lookupRouters) + for (const auto& r : lookup_routers) get_rc(r, nullptr, true); return; } @@ -384,7 +367,7 @@ namespace llarp std::shared_ptr c, std::shared_ptr nodedb, EventLoop_ptr l, - worker_func dowork, + std::function)> dowork, LinkManager* linkManager, service::Context* hiddenServiceContext, const std::unordered_set& strictConnectPubkeys, @@ -400,6 +383,7 @@ namespace llarp strict_connect_pubkeys = strictConnectPubkeys; bootstrap_rc_list = bootstrapRCList; link_manager = linkManager; + router = &link_manager->router(); useWhitelist = useWhitelist_arg; isServiceNode = isServiceNode_arg; @@ -409,38 +393,6 @@ namespace llarp } } - void - RCLookupHandler::handle_dht_lookup_result( - RouterID remote, const std::vector& results) - { - if (not results.size()) - { - finalize_request(remote, nullptr, RCRequestResult::RouterNotFound); - return; - } - - if (not is_session_allowed(remote)) - { - finalize_request(remote, &results[0], RCRequestResult::InvalidRouter); - return; - } - - if (not check_rc(results[0])) - { - finalize_request(remote, &results[0], RCRequestResult::BadRC); - return; - } - - finalize_request(remote, &results[0], RCRequestResult::Success); - } - - bool - RCLookupHandler::has_pending_lookup(RouterID remote) const - { - util::Lock l(_mutex); - return pending_callbacks.find(remote) != pending_callbacks.end(); - } - bool RCLookupHandler::is_remote_in_bootstrap(const RouterID& remote) const { @@ -454,27 +406,4 @@ namespace llarp return false; } - void - RCLookupHandler::finalize_request( - const RouterID& router, const RouterContact* const rc, RCRequestResult result) - { - callback_que movedCallbacks; - { - util::Lock l(_mutex); - - auto itr = pending_callbacks.find(router); - - if (itr != pending_callbacks.end()) - { - movedCallbacks.splice(movedCallbacks.begin(), itr->second); - pending_callbacks.erase(itr); - } - } // lock - - for (const auto& callback : movedCallbacks) - { - callback(router, rc, result); - } - } - } // namespace llarp diff --git a/llarp/router/rc_lookup_handler.hpp b/llarp/router/rc_lookup_handler.hpp index ecd2c802a1..1324b4c5e2 100644 --- a/llarp/router/rc_lookup_handler.hpp +++ b/llarp/router/rc_lookup_handler.hpp @@ -14,6 +14,7 @@ struct llarp_dht_context; namespace llarp { class NodeDB; + struct Router; class EventLoop; namespace dht @@ -39,61 +40,55 @@ namespace llarp }; using RCRequestCallback = - std::function; + std::function, bool success)>; struct RCLookupHandler { public: - using worker_func = std::function)>; - using callback_que = std::list; - ~RCLookupHandler() = default; void - add_valid_router(const RouterID& router) EXCLUDES(_mutex); + add_valid_router(const RouterID& router); void - remove_valid_router(const RouterID& router) EXCLUDES(_mutex); + remove_valid_router(const RouterID& router); void set_router_whitelist( const std::vector& whitelist, const std::vector& greylist, - const std::vector& greenlist - - ) EXCLUDES(_mutex); + const std::vector& greenlist); bool has_received_whitelist() const; void - get_rc(const RouterID& router, RCRequestCallback callback, bool forceLookup = false) - EXCLUDES(_mutex); + get_rc(const RouterID& router, RCRequestCallback callback, bool forceLookup = false); bool - is_path_allowed(const RouterID& remote) const EXCLUDES(_mutex); + is_path_allowed(const RouterID& remote) const; bool - is_session_allowed(const RouterID& remote) const EXCLUDES(_mutex); + is_session_allowed(const RouterID& remote) const; bool - is_grey_listed(const RouterID& remote) const EXCLUDES(_mutex); + is_grey_listed(const RouterID& remote) const; // "greenlist" = new routers (i.e. "green") that aren't fully funded yet bool - is_green_listed(const RouterID& remote) const EXCLUDES(_mutex); + is_green_listed(const RouterID& remote) const; // registered just means that there is at least an operator stake, but doesn't require the node // be fully funded, active, or not decommed. (In other words: it is any of the white, grey, or // green list). bool - is_registered(const RouterID& remote) const EXCLUDES(_mutex); + is_registered(const RouterID& remote) const; bool check_rc(const RouterContact& rc) const; bool - get_random_whitelist_router(RouterID& router) const EXCLUDES(_mutex); + get_random_whitelist_router(RouterID& router) const; bool check_renegotiate_valid(RouterContact newrc, RouterContact oldrc); @@ -112,7 +107,7 @@ namespace llarp std::shared_ptr contacts, std::shared_ptr nodedb, std::shared_ptr loop, - worker_func dowork, + std::function)> dowork, LinkManager* linkManager, service::Context* hiddenServiceContext, const std::unordered_set& strictConnectPubkeys, @@ -121,34 +116,19 @@ namespace llarp bool isServiceNode_arg); std::unordered_set - whitelist() const - { - util::Lock lock{_mutex}; - return router_whitelist; - } + whitelist() const; private: - void - handle_dht_lookup_result(RouterID remote, const std::vector& results); - - bool - has_pending_lookup(RouterID remote) const EXCLUDES(_mutex); - bool is_remote_in_bootstrap(const RouterID& remote) const; - void - finalize_request(const RouterID& router, const RouterContact* const rc, RCRequestResult result) - EXCLUDES(_mutex); - - mutable util::Mutex _mutex; // protects pendingCallbacks, whitelistRouters - std::shared_ptr contacts = nullptr; std::shared_ptr node_db; std::shared_ptr loop; - worker_func work_func = nullptr; + std::function)> work_func = nullptr; service::Context* hidden_service_context = nullptr; LinkManager* link_manager = nullptr; + Router* router; /// explicit whitelist of routers we will connect to directly (not for /// service nodes) @@ -157,10 +137,10 @@ namespace llarp std::set bootstrap_rc_list; std::unordered_set boostrap_rid_list; - std::unordered_map pending_callbacks GUARDED_BY(_mutex); - - bool useWhitelist = false; - bool isServiceNode = false; + // Now that all calls are made through the event loop, any access to these + // booleans is not guarded by a mutex + std::atomic useWhitelist = false; + std::atomic isServiceNode = false; // whitelist = active routers std::unordered_set router_whitelist GUARDED_BY(_mutex); @@ -168,9 +148,6 @@ namespace llarp std::unordered_set router_greylist GUARDED_BY(_mutex); // greenlist = registered but not fully-staked routers std::unordered_set router_greenlist GUARDED_BY(_mutex); - - using TimePoint = std::chrono::steady_clock::time_point; - std::unordered_map router_lookup_times; }; } // namespace llarp diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index 8079cd7798..d389476159 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -103,6 +103,12 @@ namespace llarp util::StatusObject ExtractStatus() const; + RouterID + router_id() const + { + return pubkey; + } + nlohmann::json ToJson() const { From a6f901a3a996a3b5bc52355b47ea84f1182e5cb9 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 12 Oct 2023 13:37:45 -0700 Subject: [PATCH 052/312] RIP everything --- llarp/CMakeLists.txt | 88 +- llarp/dht/message.hpp | 62 - llarp/dht/messages/findintro.cpp | 119 -- llarp/dht/messages/findintro.hpp | 47 - llarp/dht/messages/findname.cpp | 73 -- llarp/dht/messages/findname.hpp | 26 - llarp/dht/messages/findrouter.cpp | 149 --- llarp/dht/messages/findrouter.hpp | 57 - llarp/dht/messages/gotintro.cpp | 125 -- llarp/dht/messages/gotintro.hpp | 65 -- llarp/dht/messages/gotname.cpp | 69 -- llarp/dht/messages/gotname.hpp | 26 - llarp/dht/messages/gotrouter.cpp | 130 --- llarp/dht/messages/gotrouter.hpp | 66 -- llarp/dht/messages/pubintro.cpp | 191 --- llarp/dht/messages/pubintro.hpp | 46 - llarp/endpoint_base.hpp | 3 +- llarp/handlers/exit.cpp | 5 +- llarp/handlers/exit.hpp | 3 +- llarp/handlers/tun.cpp | 12 +- llarp/layers/flow/stub.cpp | 0 llarp/layers/platform/stub.cpp | 0 llarp/link/link_manager.cpp | 4 +- llarp/{quic => link}/tunnel.cpp | 48 +- llarp/{quic => link}/tunnel.hpp | 12 +- llarp/messages/link_intro.cpp | 2 - llarp/messages/link_intro.hpp | 54 - llarp/messages/relay_commit.hpp | 88 -- llarp/messages/relay_status.cpp | 2 - llarp/messages/relay_status.hpp | 124 -- llarp/net/ip_packet.hpp | 12 + llarp/path/path.cpp | 2 +- llarp/path/path_context.cpp | 22 - llarp/path/path_context.hpp | 7 - llarp/quic/address.cpp | 48 - llarp/quic/address.hpp | 154 --- llarp/quic/client.cpp | 67 -- llarp/quic/client.hpp | 29 - llarp/quic/connection.cpp | 1217 -------------------- llarp/quic/connection.hpp | 334 ------ llarp/quic/endpoint.cpp | 392 ------- llarp/quic/endpoint.hpp | 257 ----- llarp/quic/io_result.hpp | 38 - llarp/quic/null_crypto.cpp | 93 -- llarp/quic/null_crypto.hpp | 44 - llarp/quic/packet.hpp | 15 - llarp/quic/server.cpp | 73 -- llarp/quic/server.hpp | 35 - llarp/quic/stream.cpp | 354 ------ llarp/quic/stream.hpp | 368 ------ llarp/router/outbound_message_handler.cpp | 1 - llarp/router/rc_gossiper.hpp | 6 +- llarp/router/router.cpp | 22 +- llarp/router/router.hpp | 11 +- llarp/routing/handler.hpp | 78 -- llarp/routing/message.hpp | 59 - llarp/routing/message_parser.cpp | 142 --- llarp/routing/message_parser.hpp | 43 - llarp/routing/path_confirm_message.cpp | 55 - llarp/routing/path_confirm_message.hpp | 33 - llarp/routing/path_dht_message.cpp | 74 -- llarp/routing/path_dht_message.hpp | 31 - llarp/routing/path_latency_message.cpp | 51 - llarp/routing/path_latency_message.hpp | 30 - llarp/routing/path_transfer_message.cpp | 52 - llarp/routing/path_transfer_message.hpp | 43 - llarp/routing/transfer_traffic_message.cpp | 73 -- llarp/routing/transfer_traffic_message.hpp | 49 - llarp/service/address.hpp | 2 +- llarp/service/endpoint.cpp | 29 +- llarp/service/endpoint.hpp | 4 +- 71 files changed, 77 insertions(+), 6068 deletions(-) delete mode 100644 llarp/dht/message.hpp delete mode 100644 llarp/dht/messages/findintro.cpp delete mode 100644 llarp/dht/messages/findintro.hpp delete mode 100644 llarp/dht/messages/findname.cpp delete mode 100644 llarp/dht/messages/findname.hpp delete mode 100644 llarp/dht/messages/findrouter.cpp delete mode 100644 llarp/dht/messages/findrouter.hpp delete mode 100644 llarp/dht/messages/gotintro.cpp delete mode 100644 llarp/dht/messages/gotintro.hpp delete mode 100644 llarp/dht/messages/gotname.cpp delete mode 100644 llarp/dht/messages/gotname.hpp delete mode 100644 llarp/dht/messages/gotrouter.cpp delete mode 100644 llarp/dht/messages/gotrouter.hpp delete mode 100644 llarp/dht/messages/pubintro.cpp delete mode 100644 llarp/dht/messages/pubintro.hpp delete mode 100644 llarp/layers/flow/stub.cpp delete mode 100644 llarp/layers/platform/stub.cpp rename llarp/{quic => link}/tunnel.cpp (94%) rename llarp/{quic => link}/tunnel.hpp (97%) delete mode 100644 llarp/messages/link_intro.hpp delete mode 100644 llarp/messages/relay_commit.hpp delete mode 100644 llarp/messages/relay_status.hpp delete mode 100644 llarp/quic/address.cpp delete mode 100644 llarp/quic/address.hpp delete mode 100644 llarp/quic/client.cpp delete mode 100644 llarp/quic/client.hpp delete mode 100644 llarp/quic/connection.cpp delete mode 100644 llarp/quic/connection.hpp delete mode 100644 llarp/quic/endpoint.cpp delete mode 100644 llarp/quic/endpoint.hpp delete mode 100644 llarp/quic/io_result.hpp delete mode 100644 llarp/quic/null_crypto.cpp delete mode 100644 llarp/quic/null_crypto.hpp delete mode 100644 llarp/quic/packet.hpp delete mode 100644 llarp/quic/server.cpp delete mode 100644 llarp/quic/server.hpp delete mode 100644 llarp/quic/stream.cpp delete mode 100644 llarp/quic/stream.hpp delete mode 100644 llarp/routing/handler.hpp delete mode 100644 llarp/routing/message.hpp delete mode 100644 llarp/routing/message_parser.cpp delete mode 100644 llarp/routing/message_parser.hpp delete mode 100644 llarp/routing/path_confirm_message.cpp delete mode 100644 llarp/routing/path_confirm_message.hpp delete mode 100644 llarp/routing/path_dht_message.cpp delete mode 100644 llarp/routing/path_dht_message.hpp delete mode 100644 llarp/routing/path_latency_message.cpp delete mode 100644 llarp/routing/path_latency_message.hpp delete mode 100644 llarp/routing/path_transfer_message.cpp delete mode 100644 llarp/routing/path_transfer_message.hpp delete mode 100644 llarp/routing/transfer_traffic_message.cpp delete mode 100644 llarp/routing/transfer_traffic_message.hpp diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index a3e138c8ca..e06cd340e0 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -131,14 +131,14 @@ endforeach() configure_file("bootstrap-fallbacks.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/bootstrap-fallbacks.cpp" @ONLY) target_sources(lokinet-nodedb PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/bootstrap-fallbacks.cpp") - # lokinet-config is for all configuration types and parsers add_library(lokinet-config STATIC config/config.cpp config/definition.cpp config/ini.cpp - config/key_manager.cpp) + config/key_manager.cpp +) # lokinet-consensus is for deriving and tracking network consensus state for both service nodes and clients add_library(lokinet-consensus @@ -146,35 +146,6 @@ add_library(lokinet-consensus consensus/reachability_testing.cpp ) -# lokinet-dht holds all logic related to interacting with and participating in the DHT hashring -add_library(lokinet-dht - STATIC - dht/explorenetworkjob.cpp - dht/localtaglookup.cpp - dht/localrouterlookup.cpp - dht/localserviceaddresslookup.cpp - dht/message.cpp - # dht/messages/findintro.cpp - # dht/messages/findrouter.cpp - # dht/messages/gotintro.cpp - # dht/messages/gotrouter.cpp - # dht/messages/pubintro.cpp - # dht/messages/findname.cpp - # dht/messages/gotname.cpp - dht/publishservicejob.cpp - dht/recursiverouterlookup.cpp - dht/serviceaddresslookup.cpp - dht/taglookup.cpp -) - -# lokinet-layer-flow is the flow layer which sits atop the routing layer which manages -# flows between lokinet snapp endpoints be they .loki or .snode -add_library(lokinet-layer-flow - STATIC - layers/flow/stub.cpp # todo: remove me -) - - # lokinet-layer-onion is the "dumb" onion routing layer with builds manages and does i/o # with onion paths. onion paths anonymize routing layer pdu. add_library(lokinet-layer-onion @@ -186,11 +157,8 @@ add_library(lokinet-layer-onion path/pathset.cpp path/transit_hop.cpp messages/relay.cpp - messages/relay_commit.cpp - messages/relay_status.cpp ) - # lokinet-layer-link is for our layer 2 analog which splits up layer 2 frames into # a series of layer 1 symbols which are then transmitted between lokinet instances add_library(lokinet-layer-link @@ -198,20 +166,7 @@ add_library(lokinet-layer-link link/connection.cpp link/contacts.cpp link/link_manager.cpp - messages/link_intro.cpp -) - -# lokinet-plainquic is for holding the tunneled plainquic code, not quic wire protocol code -add_library(lokinet-plainquic - STATIC - quic/address.cpp - quic/client.cpp - quic/connection.cpp - quic/endpoint.cpp - quic/null_crypto.cpp - quic/server.cpp - quic/stream.cpp - quic/tunnel.cpp + # link/tunnel.cpp ) # lokinet-context holds the contextualized god objects for a lokinet instance @@ -244,18 +199,6 @@ add_library(lokinet-peerstats peerstats/types.cpp ) -# lokinet-layer-routing holds logic related to the routing layer -# routing layer is anonymized over the onion layer -add_library(lokinet-layer-routing - STATIC - routing/path_dht_message.cpp - routing/message_parser.cpp - routing/path_confirm_message.cpp - routing/path_latency_message.cpp - routing/path_transfer_message.cpp - routing/transfer_traffic_message.cpp -) - # kitchen sink to be removed after refactor add_library(lokinet-service-deprecated-kitchensink STATIC @@ -284,17 +227,11 @@ add_library(lokinet-service-deprecated-kitchensink service/name.cpp service/outbound_context.cpp service/protocol.cpp - service/router_lookup_job.cpp service/sendcontext.cpp service/session.cpp service/tag.cpp ) -add_library(lokinet-layer-platform - STATIC - layers/platform/stub.cpp # todo: remove me -) - # interal tooling for pybind add_library(lokinet-tooling INTERFACE) @@ -308,7 +245,6 @@ if(WITH_HIVE) target_link_libraries(lokinet-tooling INTERFACE lokinet-hive-tooling) endif() - # interface library for setting commone includes, linkage and flags. add_library(lokinet-base INTERFACE) target_include_directories(lokinet-base @@ -369,12 +305,7 @@ lokinet_link_lib(lokinet-context lokinet-rpc ) -lokinet_link_lib(lokinet-dht - lokinet-util - lokinet-nodedb -) - -lokinet_link_lib(lokinet-plainquic +lokinet_link_lib( lokinet-platform lokinet-config ) @@ -428,9 +359,6 @@ function(link_lokinet_layers) endfunction() link_lokinet_layers( - lokinet-layer-platform - lokinet-layer-flow - lokinet-layer-routing lokinet-layer-onion lokinet-layer-link ) @@ -443,10 +371,7 @@ if(use_old_impl) lokinet-dns lokinet-nodedb lokinet-context - lokinet-plainquic - lokinet-layer-routing lokinet-layer-onion - lokinet-dht lokinet-platform lokinet-rpc ) @@ -454,9 +379,6 @@ if(use_old_impl) endif() target_link_libraries(lokinet-layers INTERFACE - lokinet-layer-platform - lokinet-layer-flow - lokinet-layer-routing lokinet-layer-onion lokinet-layer-link ) @@ -491,7 +413,7 @@ target_link_libraries(lokinet-util PUBLIC oxenc::oxenc ) -target_link_libraries(lokinet-plainquic PUBLIC +target_link_libraries(lokinet-layer-link PUBLIC quic uvw ) diff --git a/llarp/dht/message.hpp b/llarp/dht/message.hpp deleted file mode 100644 index 9b723021a4..0000000000 --- a/llarp/dht/message.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#pragma once - -#include "key.hpp" -#include -#include -#include - -#include - -namespace -{ - static auto dht_cat = llarp::log::Cat("lokinet.dht"); -} // namespace - -namespace llarp::dht -{ - constexpr size_t MAX_MSG_SIZE = 2048; - - struct AbstractDHTMessageHandler; - - struct AbstractDHTMessage : private AbstractSerializable - { - virtual ~AbstractDHTMessage() = default; - - /// construct - AbstractDHTMessage(const Key_t& from) : From(from) - {} - - virtual bool - handle_message( - AbstractDHTMessageHandler& dht, - std::vector>& replies) const = 0; - - void - bt_encode(oxenc::bt_dict_producer& btdp) const override = 0; - - virtual bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) = 0; - - // methods we do not want to inherit onwards from AbstractSerializable - std::string - bt_encode() const final - { - throw std::runtime_error{"Error: DHT messages should encode directly to a bt dict producer!"}; - } - - Key_t From; - PathID_t pathID; - uint64_t version = llarp::constants::proto_version; - }; - - std::unique_ptr - DecodeMessage(const Key_t& from, llarp_buffer_t* buf, bool relayed = false); - - bool - DecodeMessageList( - Key_t from, - llarp_buffer_t* buf, - std::vector>& list, - bool relayed = false); - -} // namespace llarp::dht diff --git a/llarp/dht/messages/findintro.cpp b/llarp/dht/messages/findintro.cpp deleted file mode 100644 index a61e4f61e6..0000000000 --- a/llarp/dht/messages/findintro.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include "findintro.hpp" -#include "gotintro.hpp" -#include -#include -#include - -namespace llarp::dht -{ - FindIntroMessage::~FindIntroMessage() = default; - - bool - FindIntroMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* val) - { - bool read = false; - - if (!BEncodeMaybeReadDictEntry("N", tagName, read, k, val)) - return false; - - if (!BEncodeMaybeReadDictInt("O", relayOrder, read, k, val)) - return false; - - if (!BEncodeMaybeReadDictInt("R", relayed, read, k, val)) - return false; - - if (!BEncodeMaybeReadDictEntry("S", location, read, k, val)) - return false; - - if (!BEncodeMaybeReadDictInt("T", txID, read, k, val)) - return false; - - if (!BEncodeMaybeVerifyVersion("V", version, llarp::constants::proto_version, read, k, val)) - return false; - - return read; - } - - void - FindIntroMessage::bt_encode(oxenc::bt_dict_producer& btdp) const - { - try - { - btdp.append("A", "F"); - btdp.append("N", tagName.ToView()); - btdp.append("O", relayOrder); - btdp.append("R", relayed ? 1 : 0); - btdp.append("S", location.ToView()); - btdp.append("T", txID); - btdp.append("V", llarp::constants::proto_version); - } - catch (...) - { - log::critical(dht_cat, "FindIntroMessage failed to bt encode contents!"); - } - } - - bool - FindIntroMessage::handle_message( - AbstractDHTMessageHandler& dht, - std::vector>& replies) const - { - if (dht.pendingIntrosetLookups().HasPendingLookupFrom(TXOwner{From, txID})) - { - llarp::LogWarn("duplicate FIM from ", From, " txid=", txID); - return false; - } - - if (not tagName.Empty()) - { - return false; - } - // bad request (request for zero-key) - if (location.IsZero()) - { - // we dont got it - replies.emplace_back(new GotIntroMessage({}, txID)); - return true; - } - - // we are relaying this message for e.g. a client - if (relayed) - { - if (relayOrder >= INTROSET_STORAGE_REDUNDANCY) - { - llarp::LogWarn("Invalid relayOrder received: ", relayOrder); - replies.emplace_back(new GotIntroMessage({}, txID)); - return true; - } - - auto closestRCs = - dht.GetRouter()->node_db()->FindManyClosestTo(location, INTROSET_STORAGE_REDUNDANCY); - - if (closestRCs.size() <= relayOrder) - { - llarp::LogWarn("Can't fulfill FindIntro for relayOrder: ", relayOrder); - replies.emplace_back(new GotIntroMessage({}, txID)); - return true; - } - - const auto& entry = closestRCs[relayOrder]; - Key_t peer = Key_t(entry.pubkey); - dht.LookupIntroSetForPath(location, txID, pathID, peer, 0); - } - else - { - // we should have this value if introset was propagated properly - const auto maybe = dht.GetIntroSetByLocation(location); - if (maybe) - { - replies.emplace_back(new GotIntroMessage({*maybe}, txID)); - } - else - { - LogWarn("Got FIM with relayed == false and we don't have entry"); - replies.emplace_back(new GotIntroMessage({}, txID)); - } - } - return true; - } -} // namespace llarp::dht diff --git a/llarp/dht/messages/findintro.hpp b/llarp/dht/messages/findintro.hpp deleted file mode 100644 index 2390a77e09..0000000000 --- a/llarp/dht/messages/findintro.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace llarp::dht -{ - struct FindIntroMessage final : public AbstractDHTMessage - { - Key_t location; - llarp::service::Tag tagName; - uint64_t txID = 0; - bool relayed = false; - uint64_t relayOrder = 0; - - FindIntroMessage(const Key_t& from, bool relay, uint64_t order) : AbstractDHTMessage(from) - { - relayed = relay; - relayOrder = order; - } - - FindIntroMessage(const llarp::service::Tag& tag, uint64_t txid) - : AbstractDHTMessage({}), tagName(tag), txID(txid) - {} - - explicit FindIntroMessage(uint64_t txid, const Key_t& addr, uint64_t order) - : AbstractDHTMessage({}), location(addr), txID(txid), relayOrder(order) - { - tagName.Zero(); - } - - ~FindIntroMessage() override; - - void - bt_encode(oxenc::bt_dict_producer& btdp) const override; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; - - bool - handle_message( - AbstractDHTMessageHandler& dht, - std::vector>& replies) const override; - }; -} // namespace llarp::dht diff --git a/llarp/dht/messages/findname.cpp b/llarp/dht/messages/findname.cpp deleted file mode 100644 index a8d0bbebf2..0000000000 --- a/llarp/dht/messages/findname.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "findname.hpp" -#include -#include "gotname.hpp" -#include -#include -#include -#include - -namespace llarp::dht -{ - FindNameMessage::FindNameMessage(const Key_t& from, Key_t namehash, uint64_t txid) - : AbstractDHTMessage(from), NameHash(std::move(namehash)), TxID(txid) - {} - - void - FindNameMessage::bt_encode(oxenc::bt_dict_producer& btdp) const - { - try - { - btdp.append("A", "N"); - btdp.append("H", NameHash.ToView()); - btdp.append("T", TxID); - } - catch (...) - { - log::error(dht_cat, "Error: FindNameMessage failed to bt encode contents!"); - } - } - - bool - FindNameMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) - { - if (key.startswith("H")) - { - return NameHash.BDecode(val); - } - if (key.startswith("T")) - { - return bencode_read_integer(val, &TxID); - } - return bencode_discard(val); - } - - bool - FindNameMessage::handle_message( - AbstractDHTMessageHandler& dht, - std::vector>& replies) const - { - (void)replies; - auto router = dht.GetRouter(); - if (pathID.IsZero() or not router->IsServiceNode()) - return false; - router->rpc_client()->lookup_ons_hash( - NameHash, [router, pathID = pathID, TxID = TxID](auto maybe) { - auto path = router->path_context().GetPathForTransfer(pathID); - if (path == nullptr) - return; - routing::PathDHTMessage msg; - if (maybe.has_value()) - { - msg.dht_msgs.emplace_back(new GotNameMessage(dht::Key_t{}, TxID, *maybe)); - } - else - { - msg.dht_msgs.emplace_back( - new GotNameMessage(dht::Key_t{}, TxID, service::EncryptedName{})); - } - path->SendRoutingMessage(msg, router); - }); - return true; - } - -} // namespace llarp::dht diff --git a/llarp/dht/messages/findname.hpp b/llarp/dht/messages/findname.hpp deleted file mode 100644 index 49f8f73f5f..0000000000 --- a/llarp/dht/messages/findname.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include - -namespace llarp::dht -{ - struct FindNameMessage : public AbstractDHTMessage - { - explicit FindNameMessage(const Key_t& from, Key_t namehash, uint64_t txid); - - void - bt_encode(oxenc::bt_dict_producer& btdp) const override; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; - - bool - handle_message( - AbstractDHTMessageHandler& dht, - std::vector>& replies) const override; - - Key_t NameHash; - uint64_t TxID; - }; - -} // namespace llarp::dht diff --git a/llarp/dht/messages/findrouter.cpp b/llarp/dht/messages/findrouter.cpp deleted file mode 100644 index 627019f1c9..0000000000 --- a/llarp/dht/messages/findrouter.cpp +++ /dev/null @@ -1,149 +0,0 @@ -#include "findrouter.hpp" - -#include -#include "gotrouter.hpp" -#include -#include -#include -#include - -#include - -namespace llarp::dht -{ - bool - RelayedFindRouterMessage::handle_message( - AbstractDHTMessageHandler& dht, - std::vector>& replies) const - { - /// lookup for us, send an immeidate reply - const Key_t us = dht.OurKey(); - const Key_t k{targetKey}; - if (k == us) - { - auto path = dht.GetRouter()->path_context().GetByUpstream(targetKey, pathID); - if (path) - { - replies.emplace_back(new GotRouterMessage(k, txid, {dht.GetRouter()->rc()}, false)); - return true; - } - return false; - } - - Key_t peer; - // check if we know this in our nodedb first - if (not dht.GetRouter()->SessionToRouterAllowed(targetKey)) - { - // explicitly disallowed by network - replies.emplace_back(new GotRouterMessage(k, txid, {}, false)); - return true; - } - // check netdb - const auto rc = dht.GetRouter()->node_db()->FindClosestTo(k); - if (rc.pubkey == targetKey) - { - replies.emplace_back(new GotRouterMessage(k, txid, {rc}, false)); - return true; - } - peer = Key_t(rc.pubkey); - // lookup if we don't have it in our nodedb - dht.LookupRouterForPath(targetKey, txid, pathID, peer); - return true; - } - - FindRouterMessage::~FindRouterMessage() = default; - - void - FindRouterMessage::bt_encode(oxenc::bt_dict_producer& btdp) const - { - try - { - btdp.append("A", "R"); - btdp.append("E", exploratory ? 1 : 0); - btdp.append("I", iterative ? 1 : 0); - btdp.append("K", targetKey.ToView()); - btdp.append("T", txid); - btdp.append("V", version); - } - catch (...) - { - log::error(dht_cat, "Error: FindRouterMessage failed to bt encode contents!"); - } - } - - bool - FindRouterMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) - { - llarp_buffer_t strbuf; - - if (key.startswith("E")) - { - uint64_t result; - if (!bencode_read_integer(val, &result)) - return false; - - exploratory = result != 0; - return true; - } - - if (key.startswith("I")) - { - uint64_t result; - if (!bencode_read_integer(val, &result)) - return false; - - iterative = result != 0; - return true; - } - if (key.startswith("K")) - { - if (!bencode_read_string(val, &strbuf)) - return false; - if (strbuf.sz != targetKey.size()) - return false; - - std::copy(strbuf.base, strbuf.base + targetKey.SIZE, targetKey.begin()); - return true; - } - if (key.startswith("T")) - { - return bencode_read_integer(val, &txid); - } - if (key.startswith("V")) - { - return bencode_read_integer(val, &version); - } - return false; - } - - bool - FindRouterMessage::handle_message( - AbstractDHTMessageHandler& dht, - std::vector>& replies) const - { - auto router = dht.GetRouter(); - router->notify_router_event(router->pubkey(), *this); - - if (!dht.AllowTransit()) - { - llarp::LogWarn("Got DHT lookup from ", From, " when we are not allowing dht transit"); - return false; - } - if (dht.pendingRouterLookups().HasPendingLookupFrom({From, txid})) - { - llarp::LogWarn("Duplicate FRM from ", From, " txid=", txid); - return false; - } - RouterContact found; - if (targetKey.IsZero()) - { - llarp::LogError("invalid FRM from ", From, " key is zero"); - return false; - } - const Key_t k(targetKey); - if (exploratory) - return dht.HandleExploritoryRouterLookup(From, txid, targetKey, replies); - dht.LookupRouterRelayed(From, txid, k, !iterative, replies); - return true; - } -} // namespace llarp::dht diff --git a/llarp/dht/messages/findrouter.hpp b/llarp/dht/messages/findrouter.hpp deleted file mode 100644 index 7dd0b78fbe..0000000000 --- a/llarp/dht/messages/findrouter.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once -#include - -namespace llarp::dht -{ - struct FindRouterMessage : public AbstractDHTMessage - { - // inbound parsing - FindRouterMessage(const Key_t& from) : AbstractDHTMessage(from) - {} - - // find by routerid - FindRouterMessage(uint64_t id, const RouterID& target) - : AbstractDHTMessage({}), targetKey(target), txid(id) - {} - - // exploritory - FindRouterMessage(uint64_t id) : AbstractDHTMessage({}), exploratory(true), txid(id) - { - targetKey.Randomize(); - } - - ~FindRouterMessage() override; - - void - bt_encode(oxenc::bt_dict_producer& btdp) const override; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; - - bool - handle_message( - AbstractDHTMessageHandler& dht, - std::vector>& replies) const override; - - RouterID targetKey; - bool iterative = false; - bool exploratory = false; - uint64_t txid = 0; - uint64_t version = 0; - }; - - /// variant of FindRouterMessage relayed via path - struct RelayedFindRouterMessage final : public FindRouterMessage - { - RelayedFindRouterMessage(const Key_t& from) : FindRouterMessage(from) - {} - - /// handle a relayed FindRouterMessage, do a lookup on the dht and inform - /// the path of the result - /// TODO: smart path expiration logic needs to be implemented - bool - handle_message( - AbstractDHTMessageHandler& dht, - std::vector>& replies) const override; - }; -} // namespace llarp::dht diff --git a/llarp/dht/messages/gotintro.cpp b/llarp/dht/messages/gotintro.cpp deleted file mode 100644 index e93fa6f60c..0000000000 --- a/llarp/dht/messages/gotintro.cpp +++ /dev/null @@ -1,125 +0,0 @@ -#include "gotintro.hpp" - -#include -#include -#include -#include -#include -#include -#include - -namespace llarp::dht -{ - GotIntroMessage::GotIntroMessage(std::vector results, uint64_t tx) - : AbstractDHTMessage({}), found(std::move(results)), txid(tx) - {} - - bool - GotIntroMessage::handle_message( - AbstractDHTMessageHandler& dht, - std::vector>& /*replies*/) const - { - auto* router = dht.GetRouter(); - - router->notify_router_event( - router->pubkey(), - Key_t(From.data()), - (found.size() > 0 ? found[0] : llarp::service::EncryptedIntroSet{}), - txid); - - for (const auto& introset : found) - { - if (!introset.verify(dht.Now())) - { - LogWarn( - "Invalid introset while handling direct GotIntro " - "from ", - From); - return false; - } - } - TXOwner owner(From, txid); - - auto serviceLookup = dht.pendingIntrosetLookups().GetPendingLookupFrom(owner); - if (serviceLookup) - { - if (not found.empty()) - { - dht.pendingIntrosetLookups().Found(owner, serviceLookup->target, found); - } - else - { - dht.pendingIntrosetLookups().NotFound(owner, nullptr); - } - return true; - } - LogError("no pending TX for GIM from ", From, " txid=", txid); - return false; - } - - bool - RelayedGotIntroMessage::handle_message( - AbstractDHTMessageHandler& dht, - [[maybe_unused]] std::vector>& replies) const - { - // TODO: implement me better? - auto pathset = dht.GetRouter()->path_context().GetLocalPathSet(pathID); - if (pathset) - { - auto copy = std::make_shared(*this); - return pathset->HandleGotIntroMessage(copy); - } - LogWarn("No path for got intro message pathid=", pathID); - return false; - } - - bool - GotIntroMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) - { - if (key.startswith("I")) - { - return BEncodeReadList(found, buf); - } - if (key.startswith("K")) - { - if (closer) // duplicate key? - return false; - dht::Key_t K; - if (not K.BDecode(buf)) - return false; - closer = K; - return true; - } - bool read = false; - if (!BEncodeMaybeReadDictInt("T", txid, read, key, buf)) - return false; - if (!BEncodeMaybeReadDictInt("V", version, read, key, buf)) - return false; - return read; - } - - void - GotIntroMessage::bt_encode(oxenc::bt_dict_producer& btdp) const - { - try - { - btdp.append("A", "G"); - - { - auto sublist = btdp.append_list("I"); - for (auto f : found) - sublist.append(f.ToString()); - } - - if (closer) - btdp.append("K", closer->ToView()); - - btdp.append("T", txid); - btdp.append("V", version); - } - catch (...) - { - log::error(dht_cat, "Error: GotIntroMessage failed to bt encode contents!"); - } - } -} // namespace llarp::dht diff --git a/llarp/dht/messages/gotintro.hpp b/llarp/dht/messages/gotintro.hpp deleted file mode 100644 index 7fd61b10e5..0000000000 --- a/llarp/dht/messages/gotintro.hpp +++ /dev/null @@ -1,65 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include - -namespace llarp::dht -{ - /// acknowledgement to PublishIntroMessage or reply to FindIntroMessage - struct GotIntroMessage : public AbstractDHTMessage - { - /// the found introsets - std::vector found; - /// txid - uint64_t txid = 0; - /// the key of a router closer in keyspace if iterative lookup - std::optional closer; - - GotIntroMessage(const Key_t& from) : AbstractDHTMessage(from) - {} - - GotIntroMessage(const GotIntroMessage& other) - : AbstractDHTMessage(other.From), found(other.found), txid(other.txid), closer(other.closer) - { - version = other.version; - } - - /// for iterative reply - GotIntroMessage(const Key_t& from, const Key_t& _closer, uint64_t _txid) - : AbstractDHTMessage(from), txid(_txid), closer(_closer) - {} - - /// for recursive reply - GotIntroMessage(std::vector results, uint64_t txid); - - ~GotIntroMessage() override = default; - - void - bt_encode(oxenc::bt_dict_producer& btdp) const override; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; - - bool - handle_message( - AbstractDHTMessageHandler& dht, - std::vector>& replies) const override; - }; - - struct RelayedGotIntroMessage final : public GotIntroMessage - { - RelayedGotIntroMessage() : GotIntroMessage({}) - {} - - bool - handle_message( - AbstractDHTMessageHandler& dht, - std::vector>& replies) const override; - }; - - using GotIntroMessage_constptr = std::shared_ptr; -} // namespace llarp::dht diff --git a/llarp/dht/messages/gotname.cpp b/llarp/dht/messages/gotname.cpp deleted file mode 100644 index d1b534d540..0000000000 --- a/llarp/dht/messages/gotname.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include "gotname.hpp" -#include -#include -#include - -namespace llarp::dht -{ - constexpr size_t NameSizeLimit = 128; - - GotNameMessage::GotNameMessage(const Key_t& from, uint64_t txid, service::EncryptedName data) - : AbstractDHTMessage(from), result(std::move(data)), TxID(txid) - { - if (result.ciphertext.size() > NameSizeLimit) - throw std::invalid_argument("name data too big"); - } - - void - GotNameMessage::bt_encode(oxenc::bt_dict_producer& btdp) const - { - try - { - btdp.append("A", "M"); - btdp.append("D", result.ciphertext); - btdp.append("N", result.nonce.ToView()); - btdp.append("T", TxID); - } - catch (...) - { - log::error(dht_cat, "Error: GotNameMessage failed to bt encode contents!"); - } - } - - bool - GotNameMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) - { - if (key.startswith("D")) - { - llarp_buffer_t str{}; - if (not bencode_read_string(val, &str)) - return false; - if (str.sz > NameSizeLimit) - return false; - result.ciphertext.resize(str.sz); - std::copy_n(str.cur, str.sz, result.ciphertext.data()); - return true; - } - if (key.startswith("N")) - { - return result.nonce.BDecode(val); - } - if (key.startswith("T")) - { - return bencode_read_integer(val, &TxID); - } - return bencode_discard(val); - } - - bool - GotNameMessage::handle_message( - AbstractDHTMessageHandler& dht, std::vector>&) const - { - auto pathset = dht.GetRouter()->path_context().GetLocalPathSet(pathID); - if (pathset == nullptr) - return false; - auto copy = std::make_shared(*this); - return pathset->HandleGotNameMessage(copy); - } - -} // namespace llarp::dht diff --git a/llarp/dht/messages/gotname.hpp b/llarp/dht/messages/gotname.hpp deleted file mode 100644 index 63db881e76..0000000000 --- a/llarp/dht/messages/gotname.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include -#include - -namespace llarp::dht -{ - struct GotNameMessage : public AbstractDHTMessage - { - explicit GotNameMessage(const Key_t& from, uint64_t txid, service::EncryptedName data); - - void - bt_encode(oxenc::bt_dict_producer& btdp) const override; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; - - bool - handle_message( - AbstractDHTMessageHandler& dht, - std::vector>& replies) const override; - - service::EncryptedName result; - uint64_t TxID; - }; -} // namespace llarp::dht diff --git a/llarp/dht/messages/gotrouter.cpp b/llarp/dht/messages/gotrouter.cpp deleted file mode 100644 index 79b3b2967d..0000000000 --- a/llarp/dht/messages/gotrouter.cpp +++ /dev/null @@ -1,130 +0,0 @@ -#include "gotrouter.hpp" - -#include -#include -#include -#include -#include - -namespace llarp::dht -{ - GotRouterMessage::~GotRouterMessage() = default; - - void - GotRouterMessage::bt_encode(oxenc::bt_dict_producer& btdp) const - { - try - { - btdp.append("A", "S"); - - if (closerTarget) - btdp.append("K", closerTarget->ToView()); - - { - auto sublist = btdp.append_list("N"); - - for (auto& k : nearKeys) - sublist.append(k.ToView()); - } - - { - auto sublist = btdp.append_list("R"); - - for (auto& r : foundRCs) - sublist.append(r.ToString()); - } - - btdp.append("T", txid); - btdp.append("V", version); - } - catch (...) - { - log::error(dht_cat, "Error: GotRouterMessage failed to bt encode contents!"); - } - } - - bool - GotRouterMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) - { - if (key.startswith("K")) - { - if (closerTarget) // duplicate key? - return false; - closerTarget = std::make_unique(); - return closerTarget->BDecode(val); - } - if (key.startswith("N")) - { - return BEncodeReadList(nearKeys, val); - } - if (key.startswith("R")) - { - return BEncodeReadList(foundRCs, val); - } - if (key.startswith("T")) - { - return bencode_read_integer(val, &txid); - } - bool read = false; - if (!BEncodeMaybeVerifyVersion("V", version, llarp::constants::proto_version, read, key, val)) - return false; - - return read; - } - - bool - GotRouterMessage::handle_message( - AbstractDHTMessageHandler& dht, - [[maybe_unused]] std::vector>& replies) const - { - if (relayed) - { - auto pathset = dht.GetRouter()->path_context().GetLocalPathSet(pathID); - auto copy = std::make_shared(*this); - return pathset && pathset->HandleGotRouterMessage(copy); - } - // not relayed - const TXOwner owner(From, txid); - - if (dht.pendingExploreLookups().HasPendingLookupFrom(owner)) - { - LogDebug("got ", nearKeys.size(), " results in GRM for explore"); - if (nearKeys.empty()) - dht.pendingExploreLookups().NotFound(owner, closerTarget); - else - { - dht.pendingExploreLookups().Found(owner, From.as_array(), nearKeys); - } - return true; - } - // not explore lookup - if (dht.pendingRouterLookups().HasPendingLookupFrom(owner)) - { - LogDebug("got ", foundRCs.size(), " results in GRM for lookup"); - if (foundRCs.empty()) - dht.pendingRouterLookups().NotFound(owner, closerTarget); - else if (foundRCs[0].pubkey.IsZero()) - return false; - else - dht.pendingRouterLookups().Found(owner, foundRCs[0].pubkey, foundRCs); - return true; - } - // store if valid - for (const auto& rc : foundRCs) - { - if (not dht.GetRouter()->rc_lookup_handler().check_rc(rc)) - return false; - if (txid == 0) // txid == 0 on gossip - { - auto* router = dht.GetRouter(); - router->notify_router_event(router->pubkey(), rc); - router->GossipRCIfNeeded(rc); - - auto peerDb = router->peer_db(); - if (peerDb) - peerDb->handleGossipedRC(rc); - } - } - return true; - } -} // namespace llarp::dht diff --git a/llarp/dht/messages/gotrouter.hpp b/llarp/dht/messages/gotrouter.hpp deleted file mode 100644 index cca17f2d5e..0000000000 --- a/llarp/dht/messages/gotrouter.hpp +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#include - -namespace llarp::dht -{ - struct GotRouterMessage final : public AbstractDHTMessage - { - GotRouterMessage(const Key_t& from, bool tunneled) : AbstractDHTMessage(from), relayed(tunneled) - {} - GotRouterMessage( - const Key_t& from, uint64_t id, const std::vector& results, bool tunneled) - : AbstractDHTMessage(from), foundRCs(results), txid(id), relayed(tunneled) - {} - - GotRouterMessage(const Key_t& from, const Key_t& closer, uint64_t id, bool tunneled) - : AbstractDHTMessage(from), closerTarget(new Key_t(closer)), txid(id), relayed(tunneled) - {} - - GotRouterMessage(uint64_t id, std::vector _near, bool tunneled) - : AbstractDHTMessage({}), nearKeys(std::move(_near)), txid(id), relayed(tunneled) - {} - - /// gossip message - GotRouterMessage(const RouterContact rc) : AbstractDHTMessage({}), foundRCs({rc}), txid(0) - { - version = llarp::constants::proto_version; - } - - GotRouterMessage(const GotRouterMessage& other) - : AbstractDHTMessage(other.From) - , foundRCs(other.foundRCs) - , nearKeys(other.nearKeys) - , closerTarget(copy_or_nullptr(other.closerTarget)) - , txid(other.txid) - , relayed(other.relayed) - { - version = other.version; - } - - ~GotRouterMessage() override; - - void - bt_encode(oxenc::bt_dict_producer& btdp) const override; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; - - bool - handle_message( - AbstractDHTMessageHandler& dht, - std::vector>& replies) const override; - - std::vector foundRCs; - std::vector nearKeys; - std::unique_ptr closerTarget; - uint64_t txid = 0; - bool relayed = false; - }; - - using GotRouterMessage_constptr = std::shared_ptr; -} // namespace llarp::dht diff --git a/llarp/dht/messages/pubintro.cpp b/llarp/dht/messages/pubintro.cpp deleted file mode 100644 index 36c43a2a27..0000000000 --- a/llarp/dht/messages/pubintro.cpp +++ /dev/null @@ -1,191 +0,0 @@ -#include "pubintro.hpp" - -#include "gotintro.hpp" -#include -#include -#include - -#include - -namespace llarp::dht -{ - const uint64_t PublishIntroMessage::MaxPropagationDepth = 5; - PublishIntroMessage::~PublishIntroMessage() = default; - - bool - PublishIntroMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) - { - bool read = false; - if (!BEncodeMaybeReadDictEntry("I", introset, read, key, val)) - return false; - if (read) - return true; - - if (!BEncodeMaybeReadDictInt("O", relayOrder, read, key, val)) - return false; - if (read) - return true; - - uint64_t relayedInt = (relayed ? 1 : 0); - if (!BEncodeMaybeReadDictInt("R", relayedInt, read, key, val)) - return false; - if (read) - { - relayed = relayedInt; - return true; - } - - if (!BEncodeMaybeReadDictInt("T", txID, read, key, val)) - return false; - if (read) - return true; - - if (!BEncodeMaybeReadDictInt("V", version, read, key, val)) - return false; - if (read) - return true; - - return false; - } - - bool - PublishIntroMessage::handle_message( - AbstractDHTMessageHandler& dht, - std::vector>& replies) const - { - const auto now = dht.Now(); - const llarp::dht::Key_t addr{introset.derivedSigningKey.data()}; - - auto router = dht.GetRouter(); - router->notify_router_event( - router->pubkey(), Key_t(relayed ? router->pubkey() : From.data()), addr, txID, relayOrder); - - if (!introset.verify(now)) - { - llarp::LogWarn("Received PublishIntroMessage with invalid introset: ", introset); - // don't propogate or store - replies.emplace_back(new GotIntroMessage({}, txID)); - return true; - } - - if (introset.IsExpired(now + llarp::service::MAX_INTROSET_TIME_DELTA)) - { - // don't propogate or store - llarp::LogWarn("Received PublishIntroMessage with expired Introset: ", introset); - replies.emplace_back(new GotIntroMessage({}, txID)); - return true; - } - - // identify closest 4 routers - auto closestRCs = - dht.GetRouter()->node_db()->FindManyClosestTo(addr, INTROSET_STORAGE_REDUNDANCY); - if (closestRCs.size() != INTROSET_STORAGE_REDUNDANCY) - { - llarp::LogWarn("Received PublishIntroMessage but only know ", closestRCs.size(), " nodes"); - replies.emplace_back(new GotIntroMessage({}, txID)); - return true; - } - - const auto& us = dht.OurKey(); - - // function to identify the closest 4 routers we know of for this introset - auto propagateIfNotUs = [&](size_t index) { - assert(index < INTROSET_STORAGE_REDUNDANCY); - - const auto& rc = closestRCs[index]; - const Key_t peer{rc.pubkey}; - - if (peer == us) - { - llarp::LogInfo("we are peer ", index, " so storing instead of propagating"); - - dht.services()->PutNode(introset); - replies.emplace_back(new GotIntroMessage({introset}, txID)); - } - else - { - llarp::LogInfo("propagating to peer ", index); - if (relayed) - { - dht.PropagateLocalIntroSet(pathID, txID, introset, peer, 0); - } - else - { - dht.PropagateIntroSetTo(From, txID, introset, peer, 0); - } - } - }; - - if (relayed) - { - if (relayOrder >= INTROSET_STORAGE_REDUNDANCY) - { - llarp::LogWarn("Received PublishIntroMessage with invalid relayOrder: ", relayOrder); - replies.emplace_back(new GotIntroMessage({}, txID)); - return true; - } - - llarp::LogInfo("Relaying PublishIntroMessage for ", addr, ", txid=", txID); - - propagateIfNotUs(relayOrder); - } - else - { - int candidateNumber = -1; - int index = 0; - for (const auto& rc : closestRCs) - { - if (rc.pubkey == dht.OurKey()) - { - candidateNumber = index; - break; - } - ++index; - } - - if (candidateNumber >= 0) - { - LogInfo( - "Received PubIntro for ", - addr, - ", txid=", - txID, - " and we are candidate ", - candidateNumber); - dht.services()->PutNode(introset); - replies.emplace_back(new GotIntroMessage({introset}, txID)); - } - else - { - LogWarn( - "!!! Received PubIntro with relayed==false but we aren't" - " candidate, intro derived key: ", - addr, - ", txid=", - txID, - ", message from: ", - From); - } - } - - return true; - } - - void - PublishIntroMessage::bt_encode(oxenc::bt_dict_producer& btdp) const - { - try - { - btdp.append("A", "I"); - btdp.append("I", introset.ToString()); - btdp.append("O", relayOrder); - btdp.append("R", relayed ? 1 : 0); - btdp.append("T", txID); - btdp.append("V", llarp::constants::proto_version); - } - catch (...) - { - log::error(dht_cat, "Error: PublishIntroMessage failed to bt encode contents!"); - } - } -} // namespace llarp::dht diff --git a/llarp/dht/messages/pubintro.hpp b/llarp/dht/messages/pubintro.hpp deleted file mode 100644 index da877f079b..0000000000 --- a/llarp/dht/messages/pubintro.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once -#include -#include - -#include -#include - -namespace llarp::dht -{ - struct PublishIntroMessage final : public AbstractDHTMessage - { - static const uint64_t MaxPropagationDepth; - llarp::service::EncryptedIntroSet introset; - bool relayed = false; - uint64_t relayOrder = 0; - uint64_t txID = 0; - PublishIntroMessage(const Key_t& from, bool relayed_) - : AbstractDHTMessage(from), relayed(relayed_) - {} - - PublishIntroMessage( - const llarp::service::EncryptedIntroSet& introset_, - uint64_t tx, - bool relayed_, - uint64_t relayOrder_) - : AbstractDHTMessage({}) - , introset(introset_) - , relayed(relayed_) - , relayOrder(relayOrder_) - , txID(tx) - {} - - ~PublishIntroMessage() override; - - void - bt_encode(oxenc::bt_dict_producer& btdp) const override; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; - - bool - handle_message( - AbstractDHTMessageHandler& dht, - std::vector>& replies) const override; - }; -} // namespace llarp::dht diff --git a/llarp/endpoint_base.hpp b/llarp/endpoint_base.hpp index b33ed9df84..3fd0450a8f 100644 --- a/llarp/endpoint_base.hpp +++ b/llarp/endpoint_base.hpp @@ -133,8 +133,7 @@ namespace llarp Loop() = 0; virtual bool - SendToOrQueue( - service::ConvoTag tag, const llarp_buffer_t& payload, service::ProtocolType t) = 0; + send_to(service::ConvoTag tag, std::string payload) = 0; /// lookup srv records async virtual void diff --git a/llarp/handlers/exit.cpp b/llarp/handlers/exit.cpp index b8a8b8372e..9c8ee2cb5f 100644 --- a/llarp/handlers/exit.cpp +++ b/llarp/handlers/exit.cpp @@ -94,8 +94,7 @@ namespace llarp::handlers } bool - ExitEndpoint::SendToOrQueue( - service::ConvoTag tag, const llarp_buffer_t& payload, service::ProtocolType type) + ExitEndpoint::send_to(service::ConvoTag tag, std::string payload) { if (auto maybeAddr = GetEndpointWithConvoTag(tag)) { @@ -758,7 +757,7 @@ namespace llarp::handlers } huint128_t - ExitEndpoint::ObtainServiceNodeIP(const RouterID& other) + ExitEndpoint::ObtainServiceNodeIP(const RouterID& other) // "find router" { const PubKey pubKey{other}; const PubKey us{router->pubkey()}; diff --git a/llarp/handlers/exit.hpp b/llarp/handlers/exit.hpp index fd322aeb1b..42438edd3a 100644 --- a/llarp/handlers/exit.hpp +++ b/llarp/handlers/exit.hpp @@ -61,8 +61,7 @@ namespace llarp void MarkAddressOutbound(service::Address) override{}; bool - SendToOrQueue( - service::ConvoTag tag, const llarp_buffer_t& payload, service::ProtocolType t) override; + send_to(service::ConvoTag tag, std::string payload) override; void Tick(llarp_time_t now); diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 5c651624ef..701a09c0ba 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -1224,7 +1224,9 @@ namespace llarp::handlers { dst = net::ExpandV4(net::TruncateV6(dst)); } + auto itr = m_IPToAddr.find(dst); + if (itr == m_IPToAddr.end()) { service::Address addr{}; @@ -1239,13 +1241,17 @@ namespace llarp::handlers return; } + std::function extra_cb; + if (not HasFlowToService(addr)) { extra_cb = [poker = router()->route_poker()]() { poker->put_up(); }; } + pkt.ZeroSourceAddress(); MarkAddressOutbound(addr); + EnsurePathToService( addr, [pkt, extra_cb, this](service::Address addr, service::OutboundContext* ctx) { @@ -1290,7 +1296,7 @@ namespace llarp::handlers // this succeds for inbound convos, probably. if (auto maybe = GetBestConvoTagFor(to)) { - if (SendToOrQueue(*maybe, pkt.ConstBuffer(), type)) + if (send_to(*maybe, pkt.to_string())) { MarkIPActive(dst); router()->TriggerPump(); @@ -1301,7 +1307,7 @@ namespace llarp::handlers // will fail if it's an inbound convo EnsurePathTo( to, - [pkt, type, dst, to, this](auto maybe) { + [pkt, dst, to, this](auto maybe) mutable { if (not maybe) { var::visit( @@ -1310,7 +1316,7 @@ namespace llarp::handlers }, to); } - if (SendToOrQueue(*maybe, pkt.ConstBuffer(), type)) + if (send_to(*maybe, pkt.to_string())) { MarkIPActive(dst); router()->TriggerPump(); diff --git a/llarp/layers/flow/stub.cpp b/llarp/layers/flow/stub.cpp deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/llarp/layers/platform/stub.cpp b/llarp/layers/platform/stub.cpp deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 1eaab490c9..35efaf78bf 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -222,7 +222,7 @@ namespace llarp if (auto conn = ep.get_conn(remote); conn) { - conn->control_stream->command(endpoint, body, std::move(func)); + conn->control_stream->command(std::move(endpoint), std::move(body), std::move(func)); return true; } @@ -537,7 +537,7 @@ namespace llarp _router.rpc_client()->lookup_ons_hash( name_hash, [this, msg = std::move(m)](std::optional maybe) mutable { - if (maybe.has_value()) + if (maybe) msg.respond(serialize_response({{"NAME", maybe->ciphertext}})); else msg.respond(serialize_response({{"STATUS", FindNameMessage::NOT_FOUND}}), true); diff --git a/llarp/quic/tunnel.cpp b/llarp/link/tunnel.cpp similarity index 94% rename from llarp/quic/tunnel.cpp rename to llarp/link/tunnel.cpp index 2c216bb2dd..3e85a08368 100644 --- a/llarp/quic/tunnel.cpp +++ b/llarp/link/tunnel.cpp @@ -436,10 +436,10 @@ namespace llarp::quic std::pair result; auto& [saddr, pport] = result; - auto maybe_remote = service::parse_address(remote_addr); + auto maybe_remote = service::ParseAddress(remote_addr); if (!maybe_remote) { - if (not service::is_valid_name(remote_addr)) + if (not service::NameIsValid(remote_addr)) throw std::invalid_argument{"Invalid remote lokinet name/address"}; // Otherwise it's a valid ONS name, so we'll initiate an ONS lookup below } @@ -518,46 +518,17 @@ namespace llarp::quic { // We were given an ONS address, so it's a two-step process: first we resolve the ONS name, // then we have to build a path to that address. - service_endpoint_.lookup_name( - remote_addr, - [this, raddr = std::move(remote_addr), after = std::move(after_path), pp = pport]( - oxen::quic::message m) mutable { - if (not continue_connecting(pp, m, "endpoint ONS lookup", raddr)) - return; - - service::Address addr{}; - }); - - service_endpoint_.lookup_name( + service_endpoint_.LookupNameAsync( remote_addr, [this, after_path = std::move(after_path), pport = pport, - remote_addr = std::move(remote_addr)](oxen::quic::message m) { - if (not continue_connecting(pport, (bool)m, "endpoint ONS lookup", remote_addr)) + remote_addr = std::move(remote_addr)](auto maybe_remote) { + if (not continue_connecting( + pport, (bool)maybe_remote, "endpoint ONS lookup", remote_addr)) return; - - std::string name; - - if (m) - { - try - { - oxenc::bt_dict_consumer btdc{m.body()}; - name = btdc.require("NAME"); - } - catch (...) - { - log::warning(log_cat, "Tunnel Manager failed to parse find name response"); - throw; - } - - if (auto saddr = service::Address(); saddr.FromString(name)) - { - service_endpoint_.MarkAddressOutbound(saddr); - service_endpoint_.EnsurePathTo(saddr, std::move(after_path), open_timeout); - } - } + service_endpoint_.MarkAddressOutbound(*maybe_remote); + service_endpoint_.EnsurePathTo(*maybe_remote, after_path, open_timeout); }); return result; } @@ -569,8 +540,7 @@ namespace llarp::quic after_path(maybe_convo); else { - if (auto* ptr = std::get_if(&remote)) - service_endpoint_.MarkAddressOutbound(*ptr); + service_endpoint_.MarkAddressOutbound(remote); service_endpoint_.EnsurePathTo(remote, after_path, open_timeout); } diff --git a/llarp/quic/tunnel.hpp b/llarp/link/tunnel.hpp similarity index 97% rename from llarp/quic/tunnel.hpp rename to llarp/link/tunnel.hpp index c6fae5ea57..bbe67ab608 100644 --- a/llarp/quic/tunnel.hpp +++ b/llarp/link/tunnel.hpp @@ -1,10 +1,6 @@ #pragma once #include -#include "stream.hpp" -#include "address.hpp" -#include "client.hpp" -#include "server.hpp" #include #include @@ -13,8 +9,10 @@ #include -namespace llarp::quic +namespace llarp::link { + struct Endpoint; + namespace tunnel { // The server sends back a 0x00 to signal that the remote TCP connection was established and @@ -144,7 +142,7 @@ namespace llarp::quic struct ClientTunnel { // quic endpoint - std::unique_ptr client; + std::unique_ptr client; // Callback to invoke on quic connection established (true argument) or failed (false arg) OpenCallback open_cb; // TCP listening socket @@ -202,4 +200,4 @@ namespace llarp::quic std::shared_ptr timer_keepalive_ = std::make_shared(0); }; -} // namespace llarp::quic +} // namespace llarp::link diff --git a/llarp/messages/link_intro.cpp b/llarp/messages/link_intro.cpp index fbbcf44206..fd8b96278e 100644 --- a/llarp/messages/link_intro.cpp +++ b/llarp/messages/link_intro.cpp @@ -1,5 +1,3 @@ -#include "link_intro.hpp" - #include #include #include diff --git a/llarp/messages/link_intro.hpp b/llarp/messages/link_intro.hpp deleted file mode 100644 index 51b5276e03..0000000000 --- a/llarp/messages/link_intro.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include -#include "link_message.hpp" -#include - -namespace llarp -{ - struct AbstractLinkSession; - - struct LinkIntroMessage final : public AbstractLinkMessage - { - static constexpr size_t MAX_MSG_SIZE = MAX_RC_SIZE + 256; - - LinkIntroMessage() : AbstractLinkMessage() - {} - - RouterContact rc; - KeyExchangeNonce nonce; - Signature sig; - uint64_t session_period; - - std::string - bt_encode() const override; - - bool - handle_message(Router* router) const override; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; - - bool - sign(std::function signer); - - bool - verify() const; - - void - clear() override; - - const char* - name() const override - { - return "LinkIntro"; - } - - // always first - uint16_t - priority() const override - { - return std::numeric_limits::max(); - } - }; -} // namespace llarp diff --git a/llarp/messages/relay_commit.hpp b/llarp/messages/relay_commit.hpp deleted file mode 100644 index 388ea5e3d2..0000000000 --- a/llarp/messages/relay_commit.hpp +++ /dev/null @@ -1,88 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace llarp -{ - // forward declare - struct Router; - namespace path - { - struct PathContext; - } - - struct LR_CommitRecord - { - PubKey commkey; - RouterID nextHop; - TunnelNonce tunnelNonce; - PathID_t txid, rxid; - - std::unique_ptr nextRC; - std::unique_ptr work; - uint64_t version = 0; - llarp_time_t lifetime = 0s; - - bool - BDecode(llarp_buffer_t* buf); - - bool - BEncode(llarp_buffer_t* buf) const; - - bool - operator==(const LR_CommitRecord& other) const; - - private: - bool - OnKey(llarp_buffer_t* buffer, llarp_buffer_t* key); - }; - - struct LR_CommitMessage final : public AbstractLinkMessage - { - std::array frames; - - LR_CommitMessage(std::array _frames) - : AbstractLinkMessage(), frames(std::move(_frames)) - {} - - LR_CommitMessage() = default; - - ~LR_CommitMessage() override = default; - - void - clear() override; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; - - std::string - bt_encode() const override; - - bool - handle_message(Router* router) const override; - - bool - AsyncDecrypt(llarp::path::PathContext* context) const; - - const char* - name() const override - { - return "RelayCommit"; - } - - uint16_t - priority() const override - { - return 5; - } - }; -} // namespace llarp diff --git a/llarp/messages/relay_status.cpp b/llarp/messages/relay_status.cpp index e53b9ab52c..62c14f84ae 100644 --- a/llarp/messages/relay_status.cpp +++ b/llarp/messages/relay_status.cpp @@ -1,5 +1,3 @@ -#include "relay_status.hpp" - #include #include #include diff --git a/llarp/messages/relay_status.hpp b/llarp/messages/relay_status.hpp deleted file mode 100644 index 941f7b4619..0000000000 --- a/llarp/messages/relay_status.hpp +++ /dev/null @@ -1,124 +0,0 @@ -#pragma once - -#include -#include -#include "link_message.hpp" -#include -#include - -#include -#include -#include - -namespace llarp -{ - // forward declare - struct Router; - namespace path - { - struct PathContext; - struct AbstractHopHandler; - struct TransitHop; - } // namespace path - - struct LR_StatusRecord - { - static constexpr uint64_t SUCCESS = 1 << 0; - static constexpr uint64_t FAIL_TIMEOUT = 1 << 1; - static constexpr uint64_t FAIL_CONGESTION = 1 << 2; - static constexpr uint64_t FAIL_DEST_UNKNOWN = 1 << 3; - static constexpr uint64_t FAIL_DECRYPT_ERROR = 1 << 4; - static constexpr uint64_t FAIL_MALFORMED_RECORD = 1 << 5; - static constexpr uint64_t FAIL_DEST_INVALID = 1 << 6; - static constexpr uint64_t FAIL_CANNOT_CONNECT = 1 << 7; - static constexpr uint64_t FAIL_DUPLICATE_HOP = 1 << 8; - - uint64_t status = 0; - uint64_t version = 0; - - bool - BDecode(llarp_buffer_t* buf); - - bool - BEncode(llarp_buffer_t* buf) const; - - bool - operator==(const LR_StatusRecord& other) const; - - private: - bool - OnKey(llarp_buffer_t* buffer, llarp_buffer_t* key); - }; - - std::string - LRStatusCodeToString(uint64_t status); - - struct LR_StatusMessage final : public AbstractLinkMessage - { - std::array frames; - - PathID_t pathid; - - uint64_t status = 0; - - LR_StatusMessage(std::array _frames) - : AbstractLinkMessage(), frames(std::move(_frames)) - {} - - LR_StatusMessage() = default; - - ~LR_StatusMessage() override = default; - - void - clear() override; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; - - std::string - bt_encode() const override; - - bool - handle_message(Router* router) const override; - - void - SetDummyFrames(); - - static bool - CreateAndSend( - Router* router, - std::shared_ptr hop, - const PathID_t pathid, - const RouterID nextHop, - const SharedSecret pathKey, - uint64_t status); - - bool - AddFrame(const SharedSecret& pathKey, uint64_t newStatus); - - static void - QueueSendMessage( - Router* router, - const RouterID nextHop, - std::shared_ptr msg, - std::shared_ptr hop); - - static void - SendMessage( - Router* router, - const RouterID nextHop, - std::shared_ptr msg, - std::shared_ptr hop); - - const char* - name() const override - { - return "RelayStatus"; - } - uint16_t - priority() const override - { - return 6; - } - }; -} // namespace llarp diff --git a/llarp/net/ip_packet.hpp b/llarp/net/ip_packet.hpp index 50565e4aa3..1f01e6865a 100644 --- a/llarp/net/ip_packet.hpp +++ b/llarp/net/ip_packet.hpp @@ -188,6 +188,18 @@ namespace llarp::net return buf; } + inline std::string + to_string() + { + return {reinterpret_cast(_buf.data()), _buf.size()}; + } + + inline std::string_view + to_view() + { + return {reinterpret_cast(_buf.data()), _buf.size()}; + } + inline byte_t* data() { diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 1d8e71c504..bcae1c4ce3 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -539,7 +539,7 @@ namespace llarp::path { for (const auto& msg : msgs) { - if (r->send_data_message(upstream(), msg)) + if (r->send_data_message(upstream(), msg.bt_encode())) { m_TXRate += msg.enc.size(); } diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index 2661252752..a54b674a8b 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -3,7 +3,6 @@ #include #include -#include namespace llarp::path { @@ -84,27 +83,6 @@ namespace llarp::path return found; } - bool - PathContext::ForwardLRCM( - const RouterID& nextHop, - const std::array& frames, - SendStatusHandler handler) - { - if (handler == nullptr) - { - LogError("Calling ForwardLRCM without passing result handler"); - return false; - } - - const LR_CommitMessage msg{frames}; - - LogDebug("forwarding LRCM to ", nextHop); - - // TODO: replace with new message serialization for LRCM - // return _router->SendToOrQueue(nextHop, msg, handler); - return true; - } - template < typename Lock_t, typename Map_t, diff --git a/llarp/path/path_context.hpp b/llarp/path/path_context.hpp index 02189fd0ab..7743a8e2ea 100644 --- a/llarp/path/path_context.hpp +++ b/llarp/path/path_context.hpp @@ -7,7 +7,6 @@ #include "pathset.hpp" #include "transit_hop.hpp" #include -#include #include #include #include @@ -97,12 +96,6 @@ namespace llarp EndpointPathPtrSet FindOwnedPathsWithEndpoint(const RouterID& r); - bool - ForwardLRCM( - const RouterID& nextHop, - const std::array& frames, - SendStatusHandler handler); - bool HopIsUs(const RouterID& k) const; diff --git a/llarp/quic/address.cpp b/llarp/quic/address.cpp deleted file mode 100644 index 89e171104c..0000000000 --- a/llarp/quic/address.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "address.hpp" -#include -#include - -namespace llarp::quic -{ - using namespace std::literals; - - Address::Address(const SockAddr& addr) : saddr{*addr.operator const sockaddr_in6*()} - {} - - Address& - Address::operator=(const Address& other) - { - std::memmove(&saddr, &other.saddr, sizeof(saddr)); - a.addrlen = other.a.addrlen; - return *this; - } - - Address::operator service::ConvoTag() const - { - service::ConvoTag tag{}; - tag.FromV6(saddr); - return tag; - } - - std::string - Address::ToString() const - { - if (a.addrlen != sizeof(sockaddr_in6)) - return "(unknown-addr)"; - std::string result; - result.resize(8 + INET6_ADDRSTRLEN); - result[0] = '['; - inet_ntop(AF_INET6, &saddr.sin6_addr, &result[1], INET6_ADDRSTRLEN); - result.resize(result.find(char{0})); - result += "]:"; - result += std::to_string(ToHost(nuint16_t{saddr.sin6_port}).h); - return result; - } - - std::string - Path::ToString() const - { - return local.ToString() + "<-" + remote.ToString(); - } - -} // namespace llarp::quic diff --git a/llarp/quic/address.hpp b/llarp/quic/address.hpp deleted file mode 100644 index 847a58caec..0000000000 --- a/llarp/quic/address.hpp +++ /dev/null @@ -1,154 +0,0 @@ -#pragma once - -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -namespace llarp::quic -{ - // Wrapper around a sockaddr; ngtcp2 requires more intrusive access that llarp::SockAddr is meant - // to deal with, hence this wrapper (rather than trying to abuse llarp::SockAddr). - class Address - { - sockaddr_in6 saddr{}; - ngtcp2_addr a{reinterpret_cast(&saddr), sizeof(saddr)}; - - public: - Address() = default; - Address(const SockAddr& addr); - - Address(const Address& other) - { - *this = other; - } - - Address& - operator=(const Address&); - - // Implicit conversion to sockaddr* and ngtcp2_addr& so that an Address can be passed wherever - // one of those is expected. Templatized so that implicit conversion to other things doesn't - // happen. - template , int> = 0> - operator T*() - { - return reinterpret_cast(&saddr); - } - - template , int> = 0> - operator const T*() const - { - return reinterpret_cast(&saddr); - } - - operator ngtcp2_addr&() - { - return a; - } - - operator const ngtcp2_addr&() const - { - return a; - } - - size_t - sockaddr_size() const - { - return sizeof(sockaddr_in6); - } - - // Implicit conversion to a convo tag so you can pass an Address to things taking a ConvoTag - operator service::ConvoTag() const; - - // Returns the lokinet pseudo-port for the quic connection (which routes this quic packet to the - // correct waiting quic instance on the remote). - nuint16_t - port() const - { - return nuint16_t{saddr.sin6_port}; - } - - // Sets the address port - void - port(nuint16_t port) - { - saddr.sin6_port = port.n; - } - - // Implicit conversion to SockAddr for going back to general llarp code - // FIXME: see if this is still needed, I think it may have been refactored away with the - // ConvoTag operator - operator SockAddr() const - { - return SockAddr(saddr); - } - - std::string - ToString() const; - }; - - // Wraps an ngtcp2_path (which is basically just and address pair) with remote/local components. - // Implicitly convertable to a ngtcp2_path* so that this can be passed wherever a ngtcp2_path* is - // taken in the ngtcp2 API. - struct Path - { - private: - Address local_, remote_; - - public: - ngtcp2_path path{ - {local_, static_cast(local_.sockaddr_size())}, - {remote_, static_cast(remote_.sockaddr_size())}, - nullptr}; - - // Public accessors are const: - const Address& local = local_; - const Address& remote = remote_; - - Path() = default; - Path(const Address& laddr, const Address& raddr) : local_{laddr}, remote_{raddr} - {} - - Path(const Path& p) : Path{p.local, p.remote} - {} - - Path& - operator=(const Path& p) - { - local_ = p.local_; - remote_ = p.remote_; - return *this; - } - - // Equivalent to `&obj.path`, but slightly more convenient for passing into ngtcp2 functions - // taking a ngtcp2_path pointer. Templatized to prevent implicit conversion to other type of - // pointers/ints. - template , int> = 0> - operator T*() - { - return &path; - } - template , int> = 0> - operator const T*() const - { - return &path; - } - - std::string - ToString() const; - }; -} // namespace llarp::quic - -template <> -constexpr inline bool llarp::IsToStringFormattable = true; -template <> -constexpr inline bool llarp::IsToStringFormattable = true; diff --git a/llarp/quic/client.cpp b/llarp/quic/client.cpp deleted file mode 100644 index 007e8e8b67..0000000000 --- a/llarp/quic/client.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "client.hpp" -#include "tunnel.hpp" -#include -#include - -#include -#include -#include -#include - -#include - -namespace llarp::quic -{ - Client::Client(EndpointBase& ep, const SockAddr& remote, uint16_t pseudo_port) : Endpoint{ep} - { - default_stream_buffer_size = - 0; // We steal uvw's provided buffers so don't need an outgoing data buffer - - // *Our* port; we stuff this in the llarp quic header so it knows how to target quic packets - // back to *this* client. - local_addr.port(ToNet(huint16_t{pseudo_port})); - - uint16_t tunnel_port = remote.getPort(); - if (tunnel_port == 0) - throw std::logic_error{"Cannot tunnel to port 0"}; - - // TODO: need timers for: - // - // - timeout (to disconnect if idle for too long) - // - // - probably don't need for lokinet tunnel: change local addr -- attempts to re-bind the local - // socket - // - // - key_update_timer - - Path path{local_addr, remote}; - llarp::LogDebug("Connecting to ", remote); - - auto conn = std::make_shared(*this, ConnectionID::random(), path, tunnel_port); - conn->io_ready(); - conns.emplace(conn->base_cid, std::move(conn)); - } - - std::shared_ptr - Client::get_connection() - { - // A client only has one outgoing connection, so everything in conns should either be a - // shared_ptr or weak_ptr to that same outgoing connection so we can just use the first one. - auto it = conns.begin(); - if (it == conns.end()) - return nullptr; - if (auto* wptr = std::get_if(&it->second)) - return wptr->lock(); - return var::get(it->second); - } - - size_t - Client::write_packet_header(nuint16_t, uint8_t ecn) - { - buf_[0] = CLIENT_TO_SERVER; - auto pseudo_port = local_addr.port(); - std::memcpy(&buf_[1], &pseudo_port.n, 2); // remote quic pseudo-port (network order u16) - buf_[3] = std::byte{ecn}; - return 4; - } -} // namespace llarp::quic diff --git a/llarp/quic/client.hpp b/llarp/quic/client.hpp deleted file mode 100644 index d6d7281536..0000000000 --- a/llarp/quic/client.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include "endpoint.hpp" -#include "llarp/endpoint_base.hpp" - -#include - -namespace llarp::quic -{ - class Client : public Endpoint - { - public: - // Constructs a client that establishes an outgoing connection to `remote` to tunnel packets to - // `remote.getPort()` on the remote's lokinet address. `pseudo_port` is *our* unique local - // identifier which we include in outgoing packets (so that the remote server knows where to - // send the back to *this* client). - Client(EndpointBase& ep, const SockAddr& remote, uint16_t pseudo_port); - - // Returns a reference to the client's connection to the server. Returns a nullptr if there is - // no connection. - std::shared_ptr - get_connection(); - - private: - size_t - write_packet_header(nuint16_t remote_port, uint8_t ecn) override; - }; - -} // namespace llarp::quic diff --git a/llarp/quic/connection.cpp b/llarp/quic/connection.cpp deleted file mode 100644 index 27de0511f6..0000000000 --- a/llarp/quic/connection.cpp +++ /dev/null @@ -1,1217 +0,0 @@ -#include "connection.hpp" -#include "client.hpp" -#include "server.hpp" -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -extern "C" -{ -#include -} - -namespace llarp::quic -{ - ConnectionID::ConnectionID(const uint8_t* cid, size_t length) - { - assert(length <= max_size()); - datalen = length; - std::memmove(data, cid, datalen); - } - - std::string - ConnectionID::ToString() const - { - return oxenc::to_hex(data, data + datalen); - } - - ConnectionID - ConnectionID::random(size_t size) - { - ConnectionID r; - r.datalen = std::min(size, ConnectionID::max_size()); - randombytes_buf(r.data, r.datalen); - return r; - } - - namespace - { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" - - constexpr int FAIL = NGTCP2_ERR_CALLBACK_FAILURE; - - int - client_initial(ngtcp2_conn* conn_, void* user_data) - { - LogTrace("######################", __func__); - - // Initialization the connection and send our transport parameters to the server. This will - // put the connection into NGTCP2_CS_CLIENT_WAIT_HANDSHAKE state. - return static_cast(user_data)->init_client(); - } - int - recv_client_initial(ngtcp2_conn* conn_, const ngtcp2_cid* dcid, void* user_data) - { - LogTrace("######################", __func__); - - // New incoming connection from a client: our server connection starts out here in state - // NGTCP2_CS_SERVER_INITIAL, but we should immediately get into recv_crypto_data because the - // initial client packet should contain the client's transport parameters. - - auto& conn = *static_cast(user_data); - assert(conn_ == conn.conn.get()); - - if (0 != conn.setup_server_crypto_initial()) - return FAIL; - - return 0; - } - int - recv_crypto_data( - ngtcp2_conn* conn_, - ngtcp2_encryption_level crypto_level, - uint64_t offset, - const uint8_t* rawdata, - size_t rawdatalen, - void* user_data) - { - std::basic_string_view data{rawdata, rawdatalen}; - log::trace(log_cat, "Receiving crypto data: {}", buffer_printer{data}); - - auto& conn = *static_cast(user_data); - switch (crypto_level) - { - // case NGTCP2_CRYPTO_LEVEL_EARLY: - // // We don't currently use or support 0rtt - // LogWarn("Invalid EARLY crypto level"); - // return FAIL; - - case NGTCP2_ENCRYPTION_LEVEL_INITIAL: - log::trace(log_cat, "Receiving initial crypto..."); - // "Initial" level means we are still handshaking; if we are server then we receive - // the client's transport params (sent in client_initial, above) and blast ours - // back. If we are a client then getting here means we received a response from the - // server, which is that returned server transport params. - - if (auto rv = conn.recv_initial_crypto(data); rv != 0) - return rv; - - if (ngtcp2_conn_is_server(conn)) - { - if (auto rv = conn.send_magic(NGTCP2_ENCRYPTION_LEVEL_INITIAL); rv != 0) - return rv; - if (auto rv = conn.send_transport_params(NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE); rv != 0) - return rv; - } - - break; - - case NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE: - log::trace(log_cat, "Receiving handshake crypto..."); - if (!ngtcp2_conn_is_server(conn)) - { - if (auto rv = conn.recv_transport_params(data); rv != 0) - return rv; - // At this stage of the protocol with TLS the client sends back TLS info so that - // the server can install our rx key; we have to send *something* back to invoke - // the server's HANDSHAKE callback (so that it knows handshake is complete) so - // send the magic again. - if (auto rv = conn.send_magic(NGTCP2_ENCRYPTION_LEVEL_HANDSHAKE); rv != 0) - return rv; - } - else - { - // Check that we received the above as expected - if (data != handshake_magic) - { - LogWarn("Invalid handshake crypto frame from client: did not find expected magic"); - return NGTCP2_ERR_CALLBACK_FAILURE; - } - } - - conn.complete_handshake(); - break; - - default: - LogWarn("Unhandled crypto_level"); - return FAIL; - } - conn.io_ready(); - return 0; - } - int - encrypt( - uint8_t* dest, - const ngtcp2_crypto_aead* aead, - const ngtcp2_crypto_aead_ctx* aead_ctx, - const uint8_t* plaintext, - size_t plaintextlen, - const uint8_t* nonce, - size_t noncelen, - const uint8_t* ad, - size_t adlen) - { - LogTrace("######################", __func__); - LogTrace("Lengths: ", plaintextlen, "+", noncelen, "+", adlen); - if (dest != plaintext) - std::memmove(dest, plaintext, plaintextlen); - return 0; - } - int - decrypt( - uint8_t* dest, - const ngtcp2_crypto_aead* aead, - const ngtcp2_crypto_aead_ctx* aead_ctx, - const uint8_t* ciphertext, - size_t ciphertextlen, - const uint8_t* nonce, - size_t noncelen, - const uint8_t* ad, - size_t adlen) - { - LogTrace("######################", __func__); - LogTrace("Lengths: ", ciphertextlen, "+", noncelen, "+", adlen); - if (dest != ciphertext) - std::memmove(dest, ciphertext, ciphertextlen); - return 0; - } - int - hp_mask( - uint8_t* dest, - const ngtcp2_crypto_cipher* hp, - const ngtcp2_crypto_cipher_ctx* hp_ctx, - const uint8_t* sample) - { - LogTrace("######################", __func__); - memset(dest, 0, NGTCP2_HP_MASKLEN); - return 0; - } - int - recv_stream_data( - ngtcp2_conn* conn, - uint32_t flags, - int64_t stream_id, - uint64_t offset, - const uint8_t* data, - size_t datalen, - void* user_data, - void* stream_user_data) - { - LogTrace("######################", __func__); - return static_cast(user_data)->stream_receive( - {stream_id}, - {reinterpret_cast(data), datalen}, - flags & NGTCP2_STREAM_DATA_FLAG_FIN); - } - - int - acked_stream_data_offset( - ngtcp2_conn* conn_, - int64_t stream_id, - uint64_t offset, - uint64_t datalen, - void* user_data, - void* stream_user_data) - { - LogTrace("######################", __func__); - LogTrace("Ack [", offset, ",", offset + datalen, ")"); - return static_cast(user_data)->stream_ack({stream_id}, datalen); - } - - int - stream_open(ngtcp2_conn* conn, int64_t stream_id, void* user_data) - { - LogTrace("######################", __func__); - return static_cast(user_data)->stream_opened({stream_id}); - } - int - stream_close_cb( - ngtcp2_conn* conn, - uint32_t flags, - int64_t stream_id, - uint64_t app_error_code, - void* user_data, - void* stream_user_data) - { - LogTrace("######################", __func__); - static_cast(user_data)->stream_closed({stream_id}, app_error_code); - return 0; - } - - // (client only) - int - recv_retry(ngtcp2_conn* conn, const ngtcp2_pkt_hd* hd, void* user_data) - { - LogTrace("######################", __func__); - LogError("FIXME UNIMPLEMENTED ", __func__); - // FIXME - return 0; - } - int - extend_max_local_streams_bidi(ngtcp2_conn* conn_, uint64_t max_streams, void* user_data) - { - LogTrace("######################", __func__); - auto& conn = *static_cast(user_data); - if (conn.on_stream_available) - if (uint64_t left = ngtcp2_conn_get_streams_bidi_left(conn); left > 0) - conn.on_stream_available(conn); - - return 0; - } - - void - rand(uint8_t* dest, size_t destlen, const ngtcp2_rand_ctx* rand_ctx) - { - LogTrace("######################", __func__); - randombytes_buf(dest, destlen); - } - - int - get_new_connection_id( - ngtcp2_conn* conn_, ngtcp2_cid* cid_, uint8_t* token, size_t cidlen, void* user_data) - { - LogTrace("######################", __func__); - - auto& conn = *static_cast(user_data); - auto cid = conn.make_alias_id(cidlen); - assert(cid.datalen == cidlen); - *cid_ = cid; - - conn.endpoint.make_stateless_reset_token(cid, token); - LogDebug( - "make stateless reset token ", - oxenc::to_hex(token, token + NGTCP2_STATELESS_RESET_TOKENLEN)); - - return 0; - } - int - remove_connection_id(ngtcp2_conn* conn, const ngtcp2_cid* cid, void* user_data) - { - LogTrace("######################", __func__); - LogError("FIXME UNIMPLEMENTED ", __func__); - // FIXME - return 0; - } - int - update_key( - ngtcp2_conn* conn, - uint8_t* rx_secret, - uint8_t* tx_secret, - ngtcp2_crypto_aead_ctx* rx_aead_ctx, - uint8_t* rx_iv, - ngtcp2_crypto_aead_ctx* tx_aead_ctx, - uint8_t* tx_iv, - const uint8_t* current_rx_secret, - const uint8_t* current_tx_secret, - size_t secretlen, - void* user_data) - { - // This is a no-op since we don't encrypt anything in the first place - return 0; - } -#pragma GCC diagnostic pop - } // namespace - -#ifndef NDEBUG - extern "C" inline void - ngtcp_trace_logger([[maybe_unused]] void* user_data, const char* fmt, ...) - { - std::array buf{}; - va_list ap; - va_start(ap, fmt); - if (vsnprintf(buf.data(), buf.size(), fmt, ap) >= 0) - LogTrace(fmt::format("{}", buf.data())); - va_end(ap); - } -#endif - - io_result - Connection::send() - { - assert(send_buffer_size <= send_buffer.size()); - io_result rv{}; - bstring_view send_data{send_buffer.data(), send_buffer_size}; - - if (!send_data.empty()) - { - rv = endpoint.send_packet(path.remote, send_data, send_pkt_info.ecn); - } - return rv; - } - - std::tuple - Connection::init() - { - auto loop = endpoint.get_loop(); - io_trigger = loop->resource(); - io_trigger->on([this](auto&, auto&) { on_io_ready(); }); - - retransmit_timer = loop->resource(); - retransmit_timer->on([this](auto&, auto&) { - LogTrace("Retransmit timer fired!"); - if (auto rv = ngtcp2_conn_handle_expiry(*this, get_timestamp()); rv != 0) - { - LogWarn("expiry handler invocation returned an error: ", ngtcp2_strerror(rv)); - endpoint.close_connection(*this, ngtcp2_err_infer_quic_transport_error_code(rv), false); - } - else - { - flush_streams(); - } - }); - retransmit_timer->start(0ms, 0ms); - - auto result = std::tuple{}; - auto& [settings, tparams, cb] = result; - cb.recv_crypto_data = recv_crypto_data; - cb.encrypt = encrypt; - cb.decrypt = decrypt; - cb.hp_mask = hp_mask; - cb.recv_stream_data = recv_stream_data; - cb.acked_stream_data_offset = acked_stream_data_offset; - cb.stream_open = stream_open; - cb.stream_close = stream_close_cb; - cb.extend_max_local_streams_bidi = extend_max_local_streams_bidi; - cb.rand = rand; - cb.get_new_connection_id = get_new_connection_id; - cb.remove_connection_id = remove_connection_id; - cb.update_key = update_key; - - ngtcp2_settings_default(&settings); -#ifndef NDEBUG - settings.log_printf = ngtcp_trace_logger; -#endif - - settings.initial_ts = get_timestamp(); - // FIXME: IPv6 - settings.max_tx_udp_payload_size = Endpoint::max_pkt_size_v4; - settings.cc_algo = NGTCP2_CC_ALGO_CUBIC; - // settings.initial_rtt = ???; # NGTCP2's default is 333ms - - ngtcp2_transport_params_default(&tparams); - - // Connection level flow control window: - tparams.initial_max_data = CONNECTION_BUFFER; - // Max send buffer for a streams (local is for streams we initiate, remote is for replying on - // streams they initiate to us): - tparams.initial_max_stream_data_bidi_local = STREAM_BUFFER; - tparams.initial_max_stream_data_bidi_remote = STREAM_BUFFER; - // Max *cumulative* streams we support on a connection: - tparams.initial_max_streams_bidi = STREAM_LIMIT; - tparams.initial_max_streams_uni = 0; - tparams.max_idle_timeout = std::chrono::nanoseconds(IDLE_TIMEOUT).count(); - tparams.active_connection_id_limit = 8; - - LogDebug("Done basic connection initialization"); - - return result; - } - - Connection::Connection( - Server& s, const ConnectionID& base_cid_, ngtcp2_pkt_hd& header, const Path& path) - : endpoint{s}, base_cid{base_cid_}, dest_cid{header.scid}, path{path} - { - auto [settings, tparams, cb] = init(); - - cb.recv_client_initial = recv_client_initial; - - // ConnectionIDs are a little complicated: - // - when a client creates a new connection to us, it creates a random source connection ID - // *and* a random destination connection id. The server won't have that connection ID, of - // course, but we use it to recognize that we should try accepting it as a new connection. - // - When we talk to the client we use the random source connection ID that it generated as our - // destination connection ID. - // - We choose our own source ID, however: we *don't* use the random one the client picked for - // us. Instead we generate a random one and sent it back as *our* source connection ID in the - // reply to the client. - // - the client still needs to match up that reply with that request, and so we include the - // destination connection ID that the client generated for us in the transport parameters as - // the original_dcid: this lets the client match up the request, after which it can't promptly - // forget about it and start using the source CID that we gave it. - // - // So, in other words, the conversation goes like this: - // - Client: [SCID:clientid, DCID:randomid, TRANSPORT_PARAMS] - // - Server: [SCID:serverid, DCID:clientid TRANSPORT_PARAMS(origid=randomid)] - // - // - For the client, .base_cid={clientid} and .dest_cid={randomid} initially but gets updated to - // .dest_cid={serverid} when we hear back from the server. - // - For the server, .base_cid={serverid} and .dest_cid={clientid} - - tparams.original_dcid = header.dcid; - - LogDebug("original_dcid is now set to ", ConnectionID(tparams.original_dcid)); - - settings.token = header.token; - - // FIXME is this required? - randombytes_buf(tparams.stateless_reset_token, sizeof(tparams.stateless_reset_token)); - tparams.stateless_reset_token_present = 1; - - ngtcp2_conn* connptr; - LogDebug("server_new, path=", path); - if (auto rv = ngtcp2_conn_server_new( - &connptr, - &dest_cid, - &base_cid, - path, - header.version, - &cb, - &settings, - &tparams, - nullptr /*default mem allocator*/, - this); - rv != 0) - throw std::runtime_error{"Failed to initialize server connection: "s + ngtcp2_strerror(rv)}; - conn.reset(connptr); - - LogDebug("Created new server conn ", base_cid); - } - - Connection::Connection( - Client& c, const ConnectionID& scid, const Path& path, uint16_t tunnel_port) - : tunnel_port{tunnel_port} - , endpoint{c} - , base_cid{scid} - , dest_cid{ConnectionID::random()} - , path{path} - { - auto [settings, tparams, cb] = init(); - - assert(tunnel_port != 0); - - cb.client_initial = client_initial; - cb.recv_retry = recv_retry; - // cb.extend_max_local_streams_bidi = extend_max_local_streams_bidi; - // cb.recv_new_token = recv_new_token; - - ngtcp2_conn* connptr; - - if (auto rv = ngtcp2_conn_client_new( - &connptr, - &dest_cid, - &scid, - path, - NGTCP2_PROTO_VER_V1, - &cb, - &settings, - &tparams, - nullptr, - this); - rv != 0) - throw std::runtime_error{"Failed to initialize client connection: "s + ngtcp2_strerror(rv)}; - conn.reset(connptr); - - LogDebug("Created new client conn ", scid); - } - - Connection::~Connection() - { - if (io_trigger) - io_trigger->close(); - if (retransmit_timer) - { - retransmit_timer->stop(); - retransmit_timer->close(); - } - } - - void - Connection::io_ready() - { - io_trigger->send(); - } - - void - Connection::on_io_ready() - { - LogTrace(__func__); - flush_streams(); - LogTrace("done ", __func__); - } - - void - Connection::flush_streams() - { - // conn, path, pi, dest, destlen, and ts - std::optional ts; - - send_pkt_info = {}; - - auto add_stream_data = - [&](StreamID stream_id, const ngtcp2_vec* datav, size_t datalen, uint32_t flags = 0) { - std::array result; - auto& [nwrite, consumed] = result; - if (!ts) - ts = get_timestamp(); - - LogTrace( - "send_buffer size=", send_buffer.size(), ", datalen=", datalen, ", flags=", flags); - nwrite = ngtcp2_conn_writev_stream( - conn.get(), - &path.path, - &send_pkt_info, - u8data(send_buffer), - send_buffer.size(), - &consumed, - NGTCP2_WRITE_STREAM_FLAG_MORE | flags, - stream_id.id, - datav, - datalen, - *ts); - return result; - }; - - auto send_packet = [&](auto nwrite) -> bool { - send_buffer_size = nwrite; - LogTrace("Sending ", send_buffer_size, "B packet"); - - auto sent = send(); - if (sent.blocked()) - { - schedule_retransmit(); - return false; - } - - send_buffer_size = 0; - if (!sent) - { - LogWarn("I/O error while trying to send packet: ", sent.str()); - // FIXME: disconnect? - return false; - } - LogTrace("packet away!"); - return true; - }; - - std::list strs; - for (auto& [stream_id, stream_ptr] : streams) - if (stream_ptr) - strs.push_back(stream_ptr.get()); - - // Maximum number of stream data packets to send out at once; if we reach this then we'll - // schedule another event loop call of ourselves (so that we don't starve the loop). - constexpr int max_stream_packets = 15; - int stream_packets = 0; - while (!strs.empty() && stream_packets < max_stream_packets) - { - for (auto it = strs.begin(); it != strs.end();) - { - auto& stream = **it; - auto bufs = stream.pending(); - std::vector vecs; - vecs.reserve(bufs.size()); - std::transform(bufs.begin(), bufs.end(), std::back_inserter(vecs), [](const auto& buf) { - return ngtcp2_vec{const_cast(u8data(buf)), buf.size()}; - }); - -#ifndef NDEBUG - { - std::string buf_sizes; - for (auto& b : bufs) - { - if (!buf_sizes.empty()) - buf_sizes += '+'; - buf_sizes += std::to_string(b.size()); - } - LogDebug("Sending ", buf_sizes.empty() ? "no" : buf_sizes, " data for ", stream.id()); - } -#endif - - uint32_t extra_flags = 0; - if (stream.is_closing && !stream.sent_fin) - { - LogDebug("Sending FIN"); - extra_flags |= NGTCP2_WRITE_STREAM_FLAG_FIN; - stream.sent_fin = true; - } - else if (stream.is_new) - { - stream.is_new = false; - } - - auto [nwrite, consumed] = - add_stream_data(stream.id(), vecs.data(), vecs.size(), extra_flags); - LogTrace( - "add_stream_data for stream ", stream.id(), " returned [", nwrite, ",", consumed, "]"); - - if (nwrite > 0) - { - if (consumed >= 0) - { - LogTrace("consumed ", consumed, " bytes from stream ", stream.id()); - stream.wrote(consumed); - } - - LogTrace("Sending stream data packet"); - if (!send_packet(nwrite)) - return; - ++stream_packets; - ++it; - continue; - } - - switch (nwrite) - { - case 0: - LogTrace( - "Done stream writing to ", - stream.id(), - " (either stream is congested or we have nothing else to send right now)"); - assert(consumed <= 0); - break; - case NGTCP2_ERR_WRITE_MORE: - LogTrace( - "consumed ", consumed, " bytes from stream ", stream.id(), " and have space left"); - stream.wrote(consumed); - if (stream.unsent() > 0) - { - // We have more to send on this stream, so keep us in the queue - ++it; - continue; - } - break; - case NGTCP2_ERR_STREAM_DATA_BLOCKED: - LogDebug("cannot add to stream ", stream.id(), " right now: stream is blocked"); - break; - case NGTCP2_ERR_STREAM_SHUT_WR: - LogDebug("cannot write to ", stream.id(), ": stream is shut down"); - break; - default: - assert(consumed <= 0); - LogWarn("Error writing to stream ", stream.id(), ": ", ngtcp2_strerror(nwrite)); - break; - } - it = strs.erase(it); - } - } - - // Now try more with stream id -1 and no data: this takes care of things like initial handshake - // packets, and also finishes off any partially-filled packet from above. - for (;;) - { - auto [nwrite, consumed] = add_stream_data(StreamID{}, nullptr, 0); - LogTrace("add_stream_data for non-stream returned [", nwrite, ",", consumed, "]"); - assert(consumed <= 0); - if (nwrite == NGTCP2_ERR_WRITE_MORE) - { - LogTrace("Writing non-stream data, and have space left"); - continue; - } - if (nwrite < 0) - { - LogWarn("Error writing non-stream data: ", ngtcp2_strerror(nwrite)); - break; - } - if (nwrite == 0) - { - LogTrace("Nothing else to write for non-stream data for now (or we are congested)"); - break; - } - - LogTrace("Sending non-stream data packet"); - if (!send_packet(nwrite)) - return; - } - - schedule_retransmit(); - } - - void - Connection::schedule_retransmit() - { - auto exp = ngtcp2_conn_get_expiry(*this); - if (exp == std::numeric_limits::max()) - { - LogTrace("no retransmit currently needed"); - retransmit_timer->stop(); - return; - } - - auto expiry = std::chrono::nanoseconds{static_cast(exp)}; - auto expires_in = std::max( - 0ms, - std::chrono::duration_cast( - expiry - get_time().time_since_epoch())); - LogDebug("Next retransmit in ", expires_in.count(), "ms"); - retransmit_timer->stop(); - retransmit_timer->start(expires_in, 0ms); - } - - int - Connection::stream_opened(StreamID id) - { - LogDebug("New stream ", id); - auto* serv = server(); - if (!serv) - { - LogWarn("We are a client, incoming streams are not accepted"); - return NGTCP2_ERR_CALLBACK_FAILURE; - } - - std::shared_ptr stream{new Stream{*this, id, endpoint.default_stream_buffer_size}}; - stream->stream_id = id; - bool good = true; - if (serv->stream_open_callback) - good = serv->stream_open_callback(*stream, tunnel_port); - if (!good) - { - LogDebug("stream_open_callback returned failure, dropping stream ", id); - ngtcp2_conn_shutdown_stream(*this, 0, id.id, 1); - io_ready(); - return NGTCP2_ERR_CALLBACK_FAILURE; - } - - [[maybe_unused]] auto [it, ins] = streams.emplace(id, std::move(stream)); - assert(ins); - LogDebug("Created new incoming stream ", id); - return 0; - } - - int - Connection::stream_receive(StreamID id, const bstring_view data, bool fin) - { - auto str = get_stream(id); - if (!str->data_callback) - LogDebug("Dropping incoming data on stream ", str->id(), ": stream has no data callback set"); - else - { - bool good = false; - try - { - str->data_callback(*str, data); - good = true; - } - catch (const std::exception& e) - { - LogWarn( - "Stream ", - str->id(), - " data callback raised exception (", - e.what(), - "); closing stream with app code ", - STREAM_ERROR_EXCEPTION); - } - catch (...) - { - LogWarn( - "Stream ", - str->id(), - " data callback raised an unknown exception; closing stream with app code ", - STREAM_ERROR_EXCEPTION); - } - if (!good) - { - str->close(STREAM_ERROR_EXCEPTION); - return NGTCP2_ERR_CALLBACK_FAILURE; - } - } - if (fin) - { - LogTrace("Stream ", str->id(), " closed by remote"); - // Don't cleanup here; stream_closed is going to be called right away to deal with that - } - else - { - ngtcp2_conn_extend_max_stream_offset(*this, id.id, data.size()); - ngtcp2_conn_extend_max_offset(*this, data.size()); - } - return 0; - } - - void - Connection::stream_closed(StreamID id, uint64_t app_code) - { - assert(ngtcp2_is_bidi_stream(id.id)); - LogDebug(id, " closed with code ", app_code); - auto it = streams.find(id); - if (it == streams.end()) - return; - auto& stream = *it->second; - const bool was_closing = stream.is_closing; - stream.is_closing = stream.is_shutdown = true; - if (!was_closing && stream.close_callback) - { - LogDebug("Invoke stream close callback"); - std::optional code; - if (app_code != 0) - code = app_code; - stream.close_callback(stream, code); - } - - LogDebug("Erasing stream ", id, " from ", (void*)it->second.get()); - streams.erase(it); - - if (!ngtcp2_conn_is_local_stream(*this, id.id)) - ngtcp2_conn_extend_max_streams_bidi(*this, 1); - - io_ready(); // Probably superfluous but sometimes we might need to send a FIN or something. - } - - int - Connection::stream_ack(StreamID id, size_t size) - { - if (auto it = streams.find(id); it != streams.end()) - { - it->second->acknowledge(size); - return 0; - } - return NGTCP2_ERR_CALLBACK_FAILURE; - } - - Server* - Connection::server() - { - return dynamic_cast(&endpoint); - } - - Client* - Connection::client() - { - return dynamic_cast(&endpoint); - } - - int - Connection::setup_server_crypto_initial() - { - auto* s = server(); - assert(s); - s->null_crypto.server_initial(*this); - io_ready(); - return 0; - } - - ConnectionID - Connection::make_alias_id(size_t cidlen) - { - return endpoint.add_connection_id(*this, cidlen); - } - - bool - Connection::get_handshake_completed() - { - return ngtcp2_conn_get_handshake_completed(*this) != 0; - } - - int - Connection::get_streams_available() - { - uint64_t left = ngtcp2_conn_get_streams_bidi_left(*this); - constexpr int max_int = std::numeric_limits::max(); - if (left > static_cast(max_int)) - return max_int; - return static_cast(left); - } - - const std::shared_ptr& - Connection::open_stream(Stream::data_callback_t data_cb, Stream::close_callback_t close_cb) - { - std::shared_ptr stream{new Stream{ - *this, std::move(data_cb), std::move(close_cb), endpoint.default_stream_buffer_size}}; - if (int rv = ngtcp2_conn_open_bidi_stream(*this, &stream->stream_id.id, stream.get()); rv != 0) - throw std::runtime_error{"Stream creation failed: "s + ngtcp2_strerror(rv)}; - - auto& str = streams[stream->stream_id]; - str = std::move(stream); - - return str; - } - - const std::shared_ptr& - Connection::get_stream(StreamID s) const - { - return streams.at(s); - } - - int - Connection::init_client() - { - endpoint.null_crypto.client_initial(*this); - - if (int rv = send_magic(NGTCP2_ENCRYPTION_LEVEL_INITIAL); rv != 0) - return rv; - if (int rv = send_transport_params(NGTCP2_ENCRYPTION_LEVEL_INITIAL); rv != 0) - return rv; - - io_ready(); - return 0; - } - - int - Connection::recv_initial_crypto(std::basic_string_view data) - { - if (data.substr(0, handshake_magic.size()) != handshake_magic) - { - LogWarn("Invalid initial crypto frame: did not find expected magic prefix"); - return NGTCP2_ERR_CALLBACK_FAILURE; - } - data.remove_prefix(handshake_magic.size()); - - const bool is_server = ngtcp2_conn_is_server(*this); - if (is_server) - { - // For a server, we receive the transport parameters in the initial packet (prepended by the - // magic that we just removed): - if (auto rv = recv_transport_params(data); rv != 0) - return rv; - } - else - { - // For a client our initial crypto data should be just the magic string (the packet also - // contains transport parameters, but they are at HANDSHAKE crypto level and so will result - // in a second callback to handle them). - if (!data.empty()) - { - LogWarn("Invalid initial crypto frame: unexpected post-magic data found"); - return NGTCP2_ERR_CALLBACK_FAILURE; - } - } - - endpoint.null_crypto.install_rx_handshake_key(*this); - endpoint.null_crypto.install_tx_handshake_key(*this); - if (is_server) - endpoint.null_crypto.install_tx_key(*this); - - return 0; - } - - void - Connection::complete_handshake() - { - endpoint.null_crypto.install_rx_key(*this); - if (!ngtcp2_conn_is_server(*this)) - endpoint.null_crypto.install_tx_key(*this); - ngtcp2_conn_tls_handshake_completed(*this); - - if (on_handshake_complete) - { - on_handshake_complete(*this); - on_handshake_complete = nullptr; - } - } - - // ngtcp2 doesn't expose the varint encoding, but it's fairly simple: - // 0bXXyyyyyy -- XX indicates the encoded size (00=1, 01=2, 10=4, 11=8) and the rest of the bits - // (6, 14, 30, or 62) are the number, with bytes in network order for >6-bit values. - - // Returns {value, consumed} where consumed is the number of bytes consumed, or 0 on failure. - static constexpr std::pair - decode_varint(std::basic_string_view data) - { - std::pair result = {0, 0}; - auto& [val, enc_size] = result; - if (data.empty()) - return result; - enc_size = 1 << (data[0] >> 6); // first two bits are log₂ of the length - if (data.size() < enc_size) - { - enc_size = 0; - return result; - } - val = data[0] & 0b0011'1111; - for (size_t i = 1; i < enc_size; i++) - val = (val << 8) | data[i]; - return result; - } - - // Encodes an unsigned integer in QUIC encoding format; return the bytes and the length (bytes - // beyond `length` are uninitialized). - static constexpr std::pair, uint8_t> - encode_varint(uint64_t val) - { - assert(val < (1ULL << 62)); - std::pair, uint8_t> result; - uint8_t size = val < (1ULL << 6) ? 0 : val < (1ULL << 14) ? 1 : val < (1ULL << 30) ? 2 : 3; - auto& [enc, len] = result; - len = 1 << size; - for (uint8_t i = 1; i <= len; i++) - { - enc[len - i] = val & 0xff; - val >>= 8; - } - enc[0] = (enc[0] & 0b00'111111) | (size << 6); - enc[0] |= size << 6; - return result; - } - - // We add some lokinet-specific data into the transport request and *always* as the first - // transport parameter, but we do it in a way that the parameter gets ignored by the QUIC - // protocol, which encodes as {varint[code], varint[length], data}, and requires a code value - // 31*N+27 (for integer N). Naturally we use N=42, which gives us 1329=0b10100110001 which - // encodes in QUIC as 0b01000101 0b00110001 (the first two bits of the first byte give the integer - // size, and the rest are the value in network order). - static constexpr uint64_t lokinet_transport_param_N = 42; - static constexpr auto lokinet_metadata_code_raw = - encode_varint(31 * lokinet_transport_param_N + 27); - static constexpr std::basic_string_view lokinet_metadata_code{ - lokinet_metadata_code_raw.first.data(), lokinet_metadata_code_raw.second}; - static_assert( - lokinet_metadata_code.size() == 2 && lokinet_metadata_code[0] == 0b01000101 - && lokinet_metadata_code[1] == 0b00110001); - - int - Connection::recv_transport_params(std::basic_string_view data) - { - if (data.substr(0, lokinet_metadata_code.size()) != lokinet_metadata_code) - { - LogWarn("transport params did not begin with expected lokinet metadata"); - return NGTCP2_ERR_TRANSPORT_PARAM; - } - auto [meta_len, meta_len_bytes] = decode_varint(data.substr(lokinet_metadata_code.size())); - if (meta_len_bytes == 0) - { - LogWarn("transport params lokinet metadata has truncated size"); - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - std::string_view lokinet_metadata{ - reinterpret_cast( - data.substr(lokinet_metadata_code.size() + meta_len_bytes).data()), - static_cast(meta_len)}; - LogDebug("Received bencoded lokinet metadata: ", buffer_printer{lokinet_metadata}); - - uint16_t port; - try - { - oxenc::bt_dict_consumer meta{lokinet_metadata}; - // '#' contains the port the client wants us to forward to - if (!meta.skip_until("#")) - { - LogWarn("transport params # (port) is missing but required"); - return NGTCP2_ERR_TRANSPORT_PARAM; - } - port = meta.consume_integer(); - if (port == 0) - { - LogWarn("transport params tunnel port (#) is invalid: 0 is not permitted"); - return NGTCP2_ERR_TRANSPORT_PARAM; - } - LogDebug("decoded lokinet tunnel port = ", port); - } - catch (const oxenc::bt_deserialize_invalid& c) - { - LogWarn("transport params lokinet metadata is invalid: ", c.what()); - return NGTCP2_ERR_TRANSPORT_PARAM; - } - - const bool is_server = ngtcp2_conn_is_server(*this); - - if (is_server) - { - tunnel_port = port; - } - else - { - // Make sure the server reflected the proper port - if (tunnel_port != port) - { - LogWarn("server returned invalid port; expected ", tunnel_port, ", got ", port); - return NGTCP2_ERR_TRANSPORT_PARAM; - } - } - - // ngtcp2_transport_params params; - - // auto exttype = is_server ? NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO - // : NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS; - - auto rv = ngtcp2_conn_decode_and_set_remote_transport_params(*this, data.data(), data.size()); - // auto rv = ngtcp2_decode_transport_params(¶ms, exttype, data.data(), data.size()); - // LogDebug("Decode transport params ", rv == 0 ? "success" : "fail: "s + ngtcp2_strerror(rv)); - // LogTrace("params orig dcid = ", ConnectionID(params.original_dcid)); - // LogTrace("params init scid = ", ConnectionID(params.initial_scid)); - // if (rv == 0) - // { - // rv = ngtcp2_conn_set_remote_transport_params(*this, ¶ms); - // LogDebug( - // "Set remote transport params ", rv == 0 ? "success" : "fail: "s + ngtcp2_strerror(rv)); - // } - - if (rv != 0) - { - ngtcp2_conn_set_tls_error(*this, rv); - return rv; - } - - return 0; - } - - // Sends our magic string at the given level. This fixed magic string is taking the place of TLS - // parameters in full QUIC. - int - Connection::send_magic(ngtcp2_encryption_level level) - { - return ngtcp2_conn_submit_crypto_data( - *this, level, handshake_magic.data(), handshake_magic.size()); - } - - template - static void - copy_and_advance(uint8_t*& buf, const String& s) - { - static_assert(sizeof(typename String::value_type) == 1, "not a char-compatible type"); - std::memcpy(buf, s.data(), s.size()); - buf += s.size(); - } - - // Sends transport parameters. `level` is expected to be INITIAL for clients (which send the - // transport parameters in the initial packet), or HANDSHAKE for servers. - int - Connection::send_transport_params(ngtcp2_encryption_level level) - { - [[maybe_unused]] ngtcp2_transport_params tparams = - *ngtcp2_conn_get_local_transport_params(*this); - - assert(conn_buffer.empty()); - conn_buffer.resize(Endpoint::max_pkt_size_v4); - - auto* buf = u8data(conn_buffer); - auto* bufend = buf + conn_buffer.size(); - { - // Send our first parameter, the lokinet metadata, in a QUIC-compatible way (by using a - // reserved field code that QUIC parsers must ignore); currently we only include the port in - // here (from the client to tell the server what it's trying to reach, and reflected from - // the server for the client to verify). - std::string lokinet_metadata = bt_serialize(oxenc::bt_dict{ - {"#", tunnel_port}, - }); - copy_and_advance(buf, lokinet_metadata_code); - auto [bytes, size] = encode_varint(lokinet_metadata.size()); - copy_and_advance(buf, std::basic_string_view{bytes.data(), size}); - copy_and_advance(buf, lokinet_metadata); - assert(buf < bufend); - } - - // const bool is_server = ngtcp2_conn_is_server(*this); - // auto exttype = is_server ? NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS - // : NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO; - - if (ngtcp2_ssize nwrite = ngtcp2_conn_encode_local_transport_params(*this, buf, bufend - buf); - nwrite >= 0) - { - assert(nwrite > 0); - conn_buffer.resize(buf - u8data(conn_buffer) + nwrite); - } - else - { - conn_buffer.clear(); - return nwrite; - } - - LogDebug("encoded transport params: ", buffer_printer{conn_buffer}); - return ngtcp2_conn_submit_crypto_data(*this, level, u8data(conn_buffer), conn_buffer.size()); - } - -} // namespace llarp::quic diff --git a/llarp/quic/connection.hpp b/llarp/quic/connection.hpp deleted file mode 100644 index d483ee8195..0000000000 --- a/llarp/quic/connection.hpp +++ /dev/null @@ -1,334 +0,0 @@ -#pragma once - -#include "address.hpp" -#include "stream.hpp" -#include "io_result.hpp" - -#include -#include -#include -#include -#include -#include -#include - -extern "C" -{ -#include -#include -} -#include -#include -#include - -namespace -{ - static auto log_cat = llarp::log::Cat("lokinet.quic"); -} // namespace - -namespace llarp::quic -{ - // We send and verify this in the initial connection and handshake; this is designed to allow - // future changes (by either breaking or handling backwards compat). - constexpr const std::array handshake_magic_bytes{ - 'l', 'o', 'k', 'i', 'n', 'e', 't', 0x01}; - constexpr std::basic_string_view handshake_magic{ - handshake_magic_bytes.data(), handshake_magic_bytes.size()}; - - // Flow control window sizes for a buffer and individual streams: - constexpr uint64_t CONNECTION_BUFFER = 1024 * 1024; - constexpr uint64_t STREAM_BUFFER = 64 * 1024; - // Max number of simultaneous streams we support over one connection - constexpr uint64_t STREAM_LIMIT = 32; - - using bstring_view = std::basic_string_view; - - class Endpoint; - class Server; - class Client; - - struct alignas(size_t) ConnectionID : ngtcp2_cid - { - ConnectionID() = default; - ConnectionID(const uint8_t* cid, size_t length); - ConnectionID(const ConnectionID& c) = default; - ConnectionID(ngtcp2_cid c) : ConnectionID(c.data, c.datalen) - {} - ConnectionID& - operator=(const ConnectionID& c) = default; - - static constexpr size_t - max_size() - { - return NGTCP2_MAX_CIDLEN; - } - static_assert(NGTCP2_MAX_CIDLEN <= std::numeric_limits::max()); - - bool - operator==(const ConnectionID& other) const - { - return datalen == other.datalen && std::memcmp(data, other.data, datalen) == 0; - } - bool - operator!=(const ConnectionID& other) const - { - return !(*this == other); - } - - static ConnectionID - random(size_t size = ConnectionID::max_size()); - - std::string - ToString() const; - }; - -} // namespace llarp::quic - -template <> -constexpr inline bool llarp::IsToStringFormattable = true; - -namespace std -{ - template <> - struct hash - { - // We pick our own source_cid randomly, so it's a perfectly good hash already. - size_t - operator()(const llarp::quic::ConnectionID& c) const - { - static_assert( - alignof(llarp::quic::ConnectionID) >= alignof(size_t) - && offsetof(llarp::quic::ConnectionID, data) % sizeof(size_t) == 0); - return *reinterpret_cast(c.data); - } - }; -} // namespace std -namespace llarp::quic -{ - /// Returns the current (monotonic) time as a time_point - inline auto - get_time() - { - return std::chrono::steady_clock::now(); - } - - /// Converts a time_point as returned by get_time to a nanosecond timestamp (as ngtcp2 expects). - inline uint64_t - get_timestamp(const std::chrono::steady_clock::time_point& t = get_time()) - { - return std::chrono::duration_cast(t.time_since_epoch()).count(); - } - - // Stores an established connection between server/client. - class Connection : public std::enable_shared_from_this - { - private: - struct connection_deleter - { - void - operator()(ngtcp2_conn* c) const - { - ngtcp2_conn_del(c); - } - }; - - // Packet data storage for a packet we are currently sending - std::array send_buffer{}; - size_t send_buffer_size = 0; - ngtcp2_pkt_info send_pkt_info{}; - - // Attempts to send the packet in `send_buffer`. If sending blocks then we set up a write poll - // on the socket to wait for it to become available, and return an io_result with `.blocked()` - // set to true. On other I/O errors we return the errno, and on successful sending we return a - // "true" (i.e. no error code) io_result. - io_result - send(); - - // Internal base method called invoked during construction to set up common client/server - // settings. dest_cid and path must already be set. - std::tuple - init(); - - // Event trigger used to queue packet processing for this connection - std::shared_ptr io_trigger; - - // Schedules a retransmit in the event loop (according to when ngtcp2 tells us we should) - void - schedule_retransmit(); - std::shared_ptr retransmit_timer; - - // The port the client wants to connect to on the server - uint16_t tunnel_port = 0; - - public: - // The endpoint that owns this connection - Endpoint& endpoint; - - /// The primary connection id of this Connection. This is the key of endpoint.conns that stores - /// the actual shared_ptr (everything else in `conns` is a weak_ptr alias). - const ConnectionID base_cid; - - /// The destination connection id we use to send to the other end; the remote end sets this as - /// the source cid in the header. - ConnectionID dest_cid; - - /// The underlying ngtcp2 connection object - std::unique_ptr conn; - - /// The most recent Path we have to/from the remote - Path path; - - /// True if we are draining (that is, we recently received a connection close from the other end - /// and should discard everything that comes in on this connection). Do not set this directly: - /// instead call Endpoint::start_draining(conn). - bool draining = false; - - /// True when we are closing; conn_buffer will contain the closing stanza. - bool closing = false; - - /// Buffer where we store non-stream connection data, e.g. for initial transport params during - /// connection and the closing stanza when disconnecting. - std::basic_string conn_buffer; - - // Stores callbacks of active streams, indexed by our local source connection ID that we assign - // when the connection is initiated. - std::map> streams; - - /// Constructs and initializes a new incoming connection - /// - /// \param server - the Server object that owns this connection - /// \param base_cid - the local "primary" ConnectionID we use for this connection, typically - /// random - /// \param header - packet header that initiated the connection \param path - the network path - /// to reach the remote - Connection( - Server& server, const ConnectionID& base_cid, ngtcp2_pkt_hd& header, const Path& path); - - /// Establishes a connection from the local Client to a remote Server - /// \param client - the Endpoint object that owns this connection - /// \param base_cid - the client's source (i.e. local) connection ID, typically random - /// \param path - the network path to reach the remote - /// \param tunnel_port - the port that this connection should tunnel to on the remote end - Connection(Client& client, const ConnectionID& scid, const Path& path, uint16_t tunnel_port); - - // Non-movable, non-copyable: - Connection(Connection&&) = delete; - Connection(const Connection&) = delete; - Connection& - operator=(Connection&&) = delete; - Connection& - operator=(const Connection&) = delete; - - ~Connection(); - - operator const ngtcp2_conn*() const - { - return conn.get(); - } - operator ngtcp2_conn*() - { - return conn.get(); - } - - // If this connection's endpoint is a server, returns a pointer to it. Otherwise returns - // nullptr. - Server* - server(); - - // If this connection's endpoint is a client, returns a pointer to it. Otherwise returs - // nullptr. - Client* - client(); - - // Called to signal libuv that this connection has stuff to do - void - io_ready(); - // Called (via libuv) when it wants us to do our stuff. Call io_ready() to schedule this. - void - on_io_ready(); - - int - setup_server_crypto_initial(); - - // Flush any streams with pending data. Note that, depending on available ngtcp2 state, we may - // not fully flush all streams -- some streams can individually block while waiting for - // confirmation. - void - flush_streams(); - - // Called when a new stream is opened - int - stream_opened(StreamID id); - - // Called when data is received for a stream - int - stream_receive(StreamID id, bstring_view data, bool fin); - - // Called when a stream is closed - void - stream_closed(StreamID id, uint64_t app_error_code); - - // Called when stream data has been acknowledged and can be freed - int - stream_ack(StreamID id, size_t size); - - // Asks the endpoint for a new connection ID alias to use for this connection. cidlen can be - // used to specify the size of the cid (default is full size). - ConnectionID - make_alias_id(size_t cidlen = ConnectionID::max_size()); - - // A callback to invoke when the connection handshake completes. Will be cleared after being - // called. - std::function on_handshake_complete; - - // Returns true iff this connection has completed a handshake with the remote end. - bool - get_handshake_completed(); - - // Callback that is invoked whenever new streams become available: i.e. after handshaking, or - // after existing streams are closed. Note that this callback is invoked whenever the number of - // available streams increases, even if it was initially non-zero before the increase. To see - // how many streams are currently available call `get_streams_available()` (it will always be at - // least 1 when this callback is invoked). - std::function on_stream_available; - - // Returns the number of available streams that can currently be opened on the connection - int - get_streams_available(); - - // Opens a stream over this connection; when the server receives this it attempts to establish a - // TCP connection to the tunnel configured in the connection. The data callback is invoked as - // data is received on this stream. The close callback is called if the stream is closed - // (either by the remote, or locally after a stream->close() call). - // - // \param data_cb -- callback to invoke when data is received - // \param close_cb -- callback to invoke when the connection is closed - // - // Throws a `std::runtime_error` if the stream creation fails (e.g. because the connection has - // no free stream capacity). - // - // Returns a const reference to the stored Stream shared_ptr (so that the caller can decide - // whether they want a copy or not). - const std::shared_ptr& - open_stream(Stream::data_callback_t data_cb, Stream::close_callback_t close_cb); - - // Accesses the stream via its StreamID; throws std::out_of_range if the stream doesn't exist. - const std::shared_ptr& - get_stream(StreamID s) const; - - // Internal methods that need to be publicly callable because we call them from C functions: - int - init_client(); - int - recv_initial_crypto(std::basic_string_view data); - int - recv_transport_params(std::basic_string_view data); - int - send_magic(ngtcp2_encryption_level level); - int - send_transport_params(ngtcp2_encryption_level level); - void - complete_handshake(); - }; - -} // namespace llarp::quic diff --git a/llarp/quic/endpoint.cpp b/llarp/quic/endpoint.cpp deleted file mode 100644 index b96694e08c..0000000000 --- a/llarp/quic/endpoint.cpp +++ /dev/null @@ -1,392 +0,0 @@ -#include "endpoint.hpp" -#include "client.hpp" -#include "server.hpp" -#include "uvw/async.h" -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -extern "C" -{ -#include -#include -} - -namespace llarp::quic -{ - Endpoint::Endpoint(EndpointBase& ep) : service_endpoint{ep} - { - randombytes_buf(static_secret.data(), static_secret.size()); - - // Set up a callback every 250ms to clean up stale sockets, etc. - expiry_timer = get_loop()->resource(); - expiry_timer->on([this](const auto&, auto&) { check_timeouts(); }); - expiry_timer->start(250ms, 250ms); - - LogDebug("Created QUIC endpoint"); - } - - Endpoint::~Endpoint() - { - if (expiry_timer) - expiry_timer->close(); - } - - std::shared_ptr - Endpoint::get_loop() - { - auto loop = service_endpoint.Loop()->MaybeGetUVWLoop(); - assert(loop); // This object should never have been constructed if we aren't using uvw - return loop; - } - - void - Endpoint::receive_packet(const SockAddr& src, uint8_t ecn, bstring_view data) - { - // ngtcp2 wants a local address but we don't necessarily have something so just set it to - // IPv4 or IPv6 "unspecified" address (0.0.0.0 or ::) - SockAddr local = src.isIPv6() ? SockAddr{in6addr_any} : SockAddr{nuint32_t{INADDR_ANY}}; - - Packet pkt{Path{local, src}, data, ngtcp2_pkt_info{.ecn = ecn}}; - - LogTrace("[", pkt.path, ",ecn=", pkt.info.ecn, "]: received ", data.size(), " bytes"); - - handle_packet(pkt); - - LogTrace("Done handling packet"); - } - - void - Endpoint::handle_packet(const Packet& p) - { - LogTrace("Handling incoming quic packet: ", buffer_printer{p.data}); - auto maybe_dcid = handle_packet_init(p); - if (!maybe_dcid) - return; - auto& dcid = *maybe_dcid; - - // See if we have an existing connection already established for it - LogTrace("Incoming connection id ", dcid); - auto [connptr, alias] = get_conn(dcid); - if (!connptr) - { - if (alias) - { - LogDebug("Incoming packet QUIC CID is an expired alias; dropping"); - return; - } - connptr = accept_initial_connection(p); - if (!connptr) - return; - } - if (alias) - LogTrace("CID is alias for primary CID ", connptr->base_cid); - else - LogTrace("CID is primary CID"); - - handle_conn_packet(*connptr, p); - } - - std::optional - Endpoint::handle_packet_init(const Packet& p) - { - ngtcp2_version_cid vid; - auto rv = ngtcp2_pkt_decode_version_cid(&vid, u8data(p.data), p.data.size(), NGTCP2_MAX_CIDLEN); - if (rv == 1) - { // 1 means Version Negotiation should be sent and otherwise the packet should be ignored - send_version_negotiation(vid, p.path.remote); - return std::nullopt; - } - if (rv != 0) - { - LogWarn("QUIC packet header decode failed: ", ngtcp2_strerror(rv)); - return std::nullopt; - } - - if (vid.dcidlen > ConnectionID::max_size()) - { - LogWarn("Internal error: destination ID is longer than should be allowed"); - return std::nullopt; - } - - return std::make_optional(vid.dcid, vid.dcidlen); - } - - void - Endpoint::handle_conn_packet(Connection& conn, const Packet& p) - { - if (ngtcp2_conn_in_closing_period(conn)) - { - LogDebug("Connection is in closing period, dropping"); - close_connection(conn); - return; - } - if (conn.draining) - { - LogDebug("Connection is draining, dropping"); - // "draining" state means we received a connection close and we're keeping the - // connection alive just to catch (and discard) straggling packets that arrive - // out of order w.r.t to connection close. - return; - } - - if (auto result = read_packet(p, conn); !result) - { - LogWarn("Read packet failed! ", ngtcp2_strerror(result.error_code)); - } - - // FIXME - reset idle timer? - LogTrace("Done with incoming packet"); - } - - io_result - Endpoint::read_packet(const Packet& p, Connection& conn) - { - LogTrace("Reading packet from ", p.path); - auto rv = - ngtcp2_conn_read_pkt(conn, p.path, &p.info, u8data(p.data), p.data.size(), get_timestamp()); - - if (rv == 0) - conn.io_ready(); - else - LogWarn("read pkt error: ", ngtcp2_strerror(rv)); - - if (rv == NGTCP2_ERR_DRAINING) - start_draining(conn); - else if (rv == NGTCP2_ERR_DROP_CONN) - delete_conn(conn.base_cid); - - return {rv}; - } - - io_result - Endpoint::send_packet(const Address& to, bstring_view data, uint8_t ecn) - { - assert(service_endpoint.Loop()->inEventLoop()); - - size_t header_size = write_packet_header(to.port(), ecn); - size_t outgoing_len = header_size + data.size(); - assert(outgoing_len <= buf_.size()); - std::memcpy(&buf_[header_size], data.data(), data.size()); - bstring_view outgoing{buf_.data(), outgoing_len}; - - if (service_endpoint.SendToOrQueue( - to, llarp_buffer_t{outgoing.data(), outgoing.size()}, service::ProtocolType::QUIC)) - { - LogTrace("[", to, "]: sent ", buffer_printer{outgoing}); - } - else - { - LogDebug("Failed to send to quic endpoint ", to, "; was sending ", outgoing.size(), "B"); - } - return {}; - } - - void - Endpoint::send_version_negotiation(const ngtcp2_version_cid& vi, const Address& source) - { - std::array buf; - std::array versions; - std::iota(versions.begin() + 1, versions.end(), NGTCP2_PROTO_VER_MIN); - // we're supposed to send some 0x?a?a?a?a version to trigger version negotiation - versions[0] = 0x1a2a3a4au; - - CSRNG rng{}; - auto nwrote = ngtcp2_pkt_write_version_negotiation( - u8data(buf), - buf.size(), - std::uniform_int_distribution{0, 255}(rng), - vi.dcid, - vi.dcidlen, - vi.scid, - vi.scidlen, - versions.data(), - versions.size()); - if (nwrote < 0) - LogWarn("Failed to construct version negotiation packet: ", ngtcp2_strerror(nwrote)); - if (nwrote <= 0) - return; - - send_packet(source, bstring_view{buf.data(), static_cast(nwrote)}, 0); - } - - void - Endpoint::close_connection( - Connection& conn, - uint64_t code, - [[maybe_unused]] bool application, - std::string_view close_reason) - { - LogDebug("Closing connection ", conn.base_cid); - if (!conn.closing) - { - conn.conn_buffer.resize(max_pkt_size_v4); - Path path; - ngtcp2_pkt_info pi; - - ngtcp2_ccerr err; - ngtcp2_ccerr_set_liberr( - &err, - code, - reinterpret_cast(const_cast(close_reason.data())), - close_reason.size()); - - auto written = ngtcp2_conn_write_connection_close( - conn, - path, - &pi, - u8data(conn.conn_buffer), - conn.conn_buffer.size(), - &err, - get_timestamp()); - if (written <= 0) - { - LogWarn( - "Failed to write connection close packet: ", - written < 0 ? ngtcp2_strerror(written) : "unknown error: closing is 0 bytes??"); - return; - } - assert(written <= (long)conn.conn_buffer.size()); - conn.conn_buffer.resize(written); - conn.closing = true; - - conn.path = path; - } - assert(conn.closing && !conn.conn_buffer.empty()); - - if (auto sent = send_packet(conn.path.remote, conn.conn_buffer, 0); not sent) - { - LogWarn( - "Failed to send packet: ", - strerror(sent.error_code), - "; removing connection ", - conn.base_cid); - delete_conn(conn.base_cid); - return; - } - } - - /// Puts a connection into draining mode (i.e. after getting a connection close). This will - /// keep the connection registered for the recommended 3*Probe Timeout, during which we drop - /// packets that use the connection id and after which we will forget about it. - void - Endpoint::start_draining(Connection& conn) - { - if (conn.draining) - return; - LogDebug("Putting ", conn.base_cid, " into draining mode"); - conn.draining = true; - // Recommended draining time is 3*Probe Timeout - draining.emplace(conn.base_cid, get_time() + ngtcp2_conn_get_pto(conn) * 3 * 1ns); - } - - void - Endpoint::check_timeouts() - { - auto now = get_time(); - uint64_t now_ts = get_timestamp(now); - - // Destroy any connections that are finished draining - bool cleanup = false; - while (!draining.empty() && draining.front().second < now) - { - if (auto it = conns.find(draining.front().first); it != conns.end()) - { - if (std::holds_alternative(it->second)) - cleanup = true; - LogDebug("Deleting connection ", it->first); - conns.erase(it); - } - draining.pop(); - } - if (cleanup) - clean_alias_conns(); - - for (auto it = conns.begin(); it != conns.end(); ++it) - { - if (auto* conn_ptr = std::get_if(&it->second)) - { - Connection& conn = **conn_ptr; - auto exp = ngtcp2_conn_get_expiry(conn); - if (exp >= now_ts || conn.draining) - continue; - start_draining(conn); - } - } - } - - std::pair, bool> - Endpoint::get_conn(const ConnectionID& cid) - { - if (auto it = conns.find(cid); it != conns.end()) - { - if (auto* wptr = std::get_if(&it->second)) - return {wptr->lock(), true}; - return {var::get(it->second), false}; - } - return {nullptr, false}; - } - - bool - Endpoint::delete_conn(const ConnectionID& cid) - { - auto it = conns.find(cid); - if (it == conns.end()) - { - LogDebug("Cannot delete connection ", cid, ": cid not found"); - return false; - } - - bool primary = std::holds_alternative(it->second); - LogDebug("Deleting ", primary ? "primary" : "alias", " connection ", cid); - conns.erase(it); - if (primary) - clean_alias_conns(); - return true; - } - - void - Endpoint::clean_alias_conns() - { - for (auto it = conns.begin(); it != conns.end();) - { - if (auto* conn_wptr = std::get_if(&it->second); - conn_wptr && conn_wptr->expired()) - it = conns.erase(it); - else - ++it; - } - } - - ConnectionID - Endpoint::add_connection_id(Connection& conn, size_t cid_length) - { - ConnectionID cid; - for (bool inserted = false; !inserted;) - { - cid = ConnectionID::random(cid_length); - inserted = conns.emplace(cid, conn.weak_from_this()).second; - } - LogDebug("Created cid ", cid, " alias for ", conn.base_cid); - return cid; - } - - void - Endpoint::make_stateless_reset_token(const ConnectionID& cid, unsigned char* dest) - { - crypto_generichash_state state; - crypto_generichash_init(&state, nullptr, 0, NGTCP2_STATELESS_RESET_TOKENLEN); - crypto_generichash_update(&state, u8data(static_secret), static_secret.size()); - crypto_generichash_update(&state, cid.data, cid.datalen); - crypto_generichash_final(&state, dest, NGTCP2_STATELESS_RESET_TOKENLEN); - } - -} // namespace llarp::quic diff --git a/llarp/quic/endpoint.hpp b/llarp/quic/endpoint.hpp deleted file mode 100644 index 010e15c415..0000000000 --- a/llarp/quic/endpoint.hpp +++ /dev/null @@ -1,257 +0,0 @@ -#pragma once - -#include "address.hpp" -#include "connection.hpp" -#include "io_result.hpp" -#include "null_crypto.hpp" -#include "packet.hpp" -#include "stream.hpp" -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace llarp -{ - class EndpointBase; -} // namespace llarp - -namespace llarp::quic -{ - using namespace std::literals; - - inline constexpr auto IDLE_TIMEOUT = 5min; - - inline constexpr std::byte CLIENT_TO_SERVER{1}; - inline constexpr std::byte SERVER_TO_CLIENT{2}; - - /// QUIC Tunnel Endpoint; this is the class that implements either end of a quic tunnel for both - /// servers and clients. - class Endpoint - { - public: - /// Called from tun code via TunnelManager to deliver an incoming packet to us. - /// - /// \param src - the source address; this may be a tun interface address, or may be a fake IPv6 - /// address based on the convo tag. The port is not used. - /// \param ecn - the packet ecn parameter - void - receive_packet(const SockAddr& src, uint8_t ecn, bstring_view data); - - /// Returns a shared pointer to the uvw loop. - std::shared_ptr - get_loop(); - - protected: - /// the service endpoint we are owned by - EndpointBase& service_endpoint; - - /// local "address" is the IPv6 unspecified address since we don't have (or care about) the - /// actual local address for building quic packets. The port of this address must be set to our - /// local pseudo-port, for clients, and 0 for a server. - Address local_addr{in6addr_any}; - - std::shared_ptr expiry_timer; - - std::vector buf; - // Max theoretical size of a UDP packet is 2^16-1 minus IP/UDP header overhead - static constexpr size_t max_buf_size = 64 * 1024; - // Max size of a UDP packet that we'll send - static constexpr size_t max_pkt_size_v4 = NGTCP2_MAX_UDP_PAYLOAD_SIZE; - static constexpr size_t max_pkt_size_v6 = NGTCP2_MAX_UDP_PAYLOAD_SIZE; - - using primary_conn_ptr = std::shared_ptr; - using alias_conn_ptr = std::weak_ptr; - - // Connections. When a client establishes a new connection it chooses its own source connection - // ID and a destination connection ID and sends them to the server. - // - // This container stores the primary Connection instance as a shared_ptr, and any connection - // aliases as weak_ptrs referencing the primary instance (so that we don't have to double a - // double-hash lookup on incoming packets, since those frequently use aliases). - // - // The destination connection ID should be entirely random and can be up to 160 bits, but the - // source connection ID does not have to be (i.e. it can encode some information, if desired). - // - // The server is going to include in the response: - // - destination connection ID equal to the client's source connection ID - // - a new random source connection ID. (We don't use the client's destination ID but generate - // our own). Like the clients source ID, this can contain embedded info. - // - // The client stores this, and so we end up with client-scid == server-dcid, and client-dcid == - // server-scid, where each side chose its own source connection ID. - // - // Ultimately, we store here our own {source connection ID -> Connection} pairs (or - // equivalently, on incoming packets, the key will be the packet's dest conn ID). - std::unordered_map> conns; - - using conns_iterator = decltype(conns)::iterator; - - // Connections that are draining (i.e. we are dropping, but need to keep around for a while - // to catch and drop lagged packets). The time point is the scheduled removal time. - std::queue> draining; - - NullCrypto null_crypto; - - // Random data that we hash together with a CID to make a stateless reset token - std::array static_secret; - - friend class Connection; - - explicit Endpoint(EndpointBase& service_endpoint_); - - virtual ~Endpoint(); - - // Version & connection id info that we can potentially extract when decoding a packet - struct version_info - { - uint32_t version; - const uint8_t* dcid; - size_t dcid_len; - const uint8_t* scid; - size_t scid_len; - }; - - // Called to handle an incoming packet - void - handle_packet(const Packet& p); - - // Internal method: handles initial common packet decoding, returns the connection ID or nullopt - // if decoding failed. - std::optional - handle_packet_init(const Packet& p); - // Internal method: handles a packet sent to the given connection - void - handle_conn_packet(Connection& c, const Packet& p); - - // Accept a new incoming connection, i.e. pre-handshake. Returns a nullptr if the connection - // can't be created (e.g. because of invalid initial data), or if incoming connections are not - // accepted by this endpoint (i.e. because it is not a Server instance, or because there are no - // registered listen handlers). The base class default returns nullptr. - virtual std::shared_ptr - accept_initial_connection(const Packet&) - { - return nullptr; - } - - // Reads a packet and handles various error conditions. Returns an io_result. Note that it is - // possible for the conn_it to be erased from `conns` if the error code is anything other than - // success (0) or NGTCP2_ERR_RETRY. - io_result - read_packet(const Packet& p, Connection& conn); - - // Writes the lokinet packet header to the beginning of `buf_`; the header is prepend to quic - // packets to identify which quic server the packet should be delivered to and consists of: - // - type [1 byte]: 1 for client->server packets; 2 for server->client packets (other values - // reserved) - // - port [2 bytes, network order]: client pseudoport (i.e. either a source or destination port - // depending on type) - // - ecn value [1 byte]: provided by ngtcp2. (Only the lower 2 bits are actually used). - // - // \param psuedo_port - the remote's pseudo-port (will be 0 if the remote is a server, > 0 for - // a client remote) - // \param ecn - the ecn value from ngtcp2 - // - // Returns the number of bytes written to buf_. - virtual size_t - write_packet_header(nuint16_t pseudo_port, uint8_t ecn) = 0; - - // Sends a packet to `to` containing `data`. Returns a non-error io_result on success, - // an io_result with .error_code set to the errno of the failure on failure. - io_result - send_packet(const Address& to, bstring_view data, uint8_t ecn); - - // Wrapper around the above that takes a regular std::string_view (i.e. of chars) and recasts - // it to an string_view of std::bytes. - io_result - send_packet(const Address& to, std::string_view data, uint8_t ecn) - { - return send_packet( - to, bstring_view{reinterpret_cast(data.data()), data.size()}, ecn); - } - - // Another wrapper taking a vector - io_result - send_packet(const Address& to, const std::vector& data, uint8_t ecn) - { - return send_packet(to, bstring_view{data.data(), data.size()}, ecn); - } - - void - send_version_negotiation(const ngtcp2_version_cid& vi, const Address& source); - - // Looks up a connection. Returns a shared_ptr (either copied for a primary connection, or - // locked from an alias's weak pointer) if the connection was found or nullptr if not; and a - // bool indicating whether this connection ID was an alias (true) or not (false). [Note: the - // alias value can be true even if the shared_ptr is null in the case of an expired alias that - // hasn't yet been cleaned up]. - std::pair, bool> - get_conn(const ConnectionID& cid); - - // Called to start closing (or continue closing) a connection by sending a connection close - // response to any incoming packets. - // - // Takes the iterator to the connection pair from `conns` and optional error parameters: if - // `application` is false (the default) then we do a hard connection close because of transport - // error, if true we do a graceful application close. `close_reason` can be provided for - // propagating reason for close to remote, defaults to empty string. For application closes the - // code is application-defined; for hard closes the code should be one of the NGTCP2_*_ERROR - // values. - void - close_connection( - Connection& conn, - uint64_t code = NGTCP2_NO_ERROR, - bool application = false, - std::string_view close_reason = ""sv); - - /// Puts a connection into draining mode (i.e. after getting a connection close). This will - /// keep the connection registered for the recommended 3*Probe Timeout, during which we drop - /// packets that use the connection id and after which we will forget about it. - void - start_draining(Connection& conn); - - void - check_timeouts(); - - /// Deletes a connection from `conns`; if the connecion is a primary connection shared pointer - /// then it is removed and clean_alias_conns() is immediately called to remove any aliases to - /// the connection. If the given connection is an alias connection then it is removed but no - /// cleanup is performed. Returns true if something was removed, false if the connection was - /// not found. - bool - delete_conn(const ConnectionID& cid); - - /// Removes any connection id aliases that no longer have associated Connections. - void - clean_alias_conns(); - - /// Creates a new, unused connection ID alias for the given connection; adds the alias to - /// `conns` and returns the ConnectionID. - ConnectionID - add_connection_id(Connection& conn, size_t cid_length = ConnectionID::max_size()); - - public: - // Makes a deterministic stateless reset token for the given connection ID. Writes it to dest - // (which must have NGTCP2_STATELESS_RESET_TOKENLEN bytes available). - void - make_stateless_reset_token(const ConnectionID& cid, unsigned char* dest); - - // Default stream buffer size for streams opened through this endpoint. - size_t default_stream_buffer_size = 64 * 1024; - - // Packet buffer we use when constructing custom packets to fire over lokinet - std::array buf_; - - // Non-copyable, non-movable - Endpoint(const Endpoint&) = delete; - Endpoint(Endpoint&&) = delete; - }; - -} // namespace llarp::quic diff --git a/llarp/quic/io_result.hpp b/llarp/quic/io_result.hpp deleted file mode 100644 index 00eb877349..0000000000 --- a/llarp/quic/io_result.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace llarp::quic -{ - // Return result from a read or write operation that wraps an errno value. It is implicitly - // convertible to bool to test for "is not an error" (which is the inverse of casting a plain - // integer error code value to bool). - struct io_result - { - // An error code, typically an errno value - int error_code{0}; - // Returns true if this represent a successful result, i.e. an error_code of 0. - operator bool() const - { - return error_code == 0; - } - - // Returns true if this is an error value indicating a failure to write without blocking (only - // applied to io_result's capturing an errno). - bool - blocked() const - { - return error_code == EAGAIN || error_code == EWOULDBLOCK; - } - - // Returns the errno string for the given error code. - std::string_view - str() const - { - return strerror(error_code); - } - }; - -} // namespace llarp::quic diff --git a/llarp/quic/null_crypto.cpp b/llarp/quic/null_crypto.cpp deleted file mode 100644 index 5043fcf8ae..0000000000 --- a/llarp/quic/null_crypto.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include "null_crypto.hpp" -#include - -#include - -namespace llarp::quic -{ - // Cranks a value to "11", i.e. set it to its maximum - template - void - crank_to_eleven(T& val) - { - val = std::numeric_limits::max(); - } - - NullCrypto::NullCrypto() - { - crank_to_eleven(null_ctx.max_encryption); - crank_to_eleven(null_ctx.max_decryption_failure); - null_ctx.aead.max_overhead = 1; // Fails an assertion if 0 - null_aead.max_overhead = 1; // FIXME - can this be 0? - } - - void - NullCrypto::client_initial(Connection& conn) - { - ngtcp2_conn_set_initial_crypto_ctx(conn, &null_ctx); - ngtcp2_conn_install_initial_key( - conn, - &null_aead_ctx, - null_iv.data(), - &null_cipher_ctx, - &null_aead_ctx, - null_iv.data(), - &null_cipher_ctx, - null_iv.size()); - ngtcp2_conn_set_retry_aead(conn, &null_aead, &null_aead_ctx); - ngtcp2_conn_set_crypto_ctx(conn, &null_ctx); - } - - void - NullCrypto::server_initial(Connection& conn) - { - LogDebug("Server initial null crypto setup"); - ngtcp2_conn_set_initial_crypto_ctx(conn, &null_ctx); - ngtcp2_conn_install_initial_key( - conn, - &null_aead_ctx, - null_iv.data(), - &null_cipher_ctx, - &null_aead_ctx, - null_iv.data(), - &null_cipher_ctx, - null_iv.size()); - ngtcp2_conn_set_crypto_ctx(conn, &null_ctx); - } - - bool - NullCrypto::install_tx_handshake_key(Connection& conn) - { - return ngtcp2_conn_install_tx_handshake_key( - conn, &null_aead_ctx, null_iv.data(), null_iv.size(), &null_cipher_ctx) - == 0; - } - bool - NullCrypto::install_rx_handshake_key(Connection& conn) - { - return ngtcp2_conn_install_rx_handshake_key( - conn, &null_aead_ctx, null_iv.data(), null_iv.size(), &null_cipher_ctx) - == 0; - } - bool - NullCrypto::install_tx_key(Connection& conn) - { - return ngtcp2_conn_install_tx_key( - conn, - null_iv.data(), - null_iv.size(), - &null_aead_ctx, - null_iv.data(), - null_iv.size(), - &null_cipher_ctx) - == 0; - } - bool - NullCrypto::install_rx_key(Connection& conn) - { - return ngtcp2_conn_install_rx_key( - conn, nullptr, 0, &null_aead_ctx, null_iv.data(), null_iv.size(), &null_cipher_ctx) - == 0; - } - -} // namespace llarp::quic diff --git a/llarp/quic/null_crypto.hpp b/llarp/quic/null_crypto.hpp deleted file mode 100644 index 43449a0150..0000000000 --- a/llarp/quic/null_crypto.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include "connection.hpp" - -#include -#include - -#include - -namespace llarp::quic -{ - // Class providing do-nothing stubs for quic crypto operations: everything over lokinet is already - // encrypted so we just no-op QUIC's built in crypto operations. - struct NullCrypto - { - NullCrypto(); - - void - client_initial(Connection& conn); - - void - server_initial(Connection& conn); - - bool - install_tx_handshake_key(Connection& conn); - bool - install_tx_key(Connection& conn); - - bool - install_rx_handshake_key(Connection& conn); - bool - install_rx_key(Connection& conn); - - private: - std::array null_iv{}; - // std::array null_data{}; - - ngtcp2_crypto_ctx null_ctx{}; - ngtcp2_crypto_aead null_aead{}; - ngtcp2_crypto_aead_ctx null_aead_ctx{}; - ngtcp2_crypto_cipher_ctx null_cipher_ctx{}; - }; - -} // namespace llarp::quic diff --git a/llarp/quic/packet.hpp b/llarp/quic/packet.hpp deleted file mode 100644 index a50d283a95..0000000000 --- a/llarp/quic/packet.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "connection.hpp" - -namespace llarp::quic -{ - // Encapsulates a packet, i.e. the remote addr, packet data, plus metadata. - struct Packet - { - Path path; - bstring_view data; - ngtcp2_pkt_info info; - }; - -} // namespace llarp::quic diff --git a/llarp/quic/server.cpp b/llarp/quic/server.cpp deleted file mode 100644 index f996f9d1b6..0000000000 --- a/llarp/quic/server.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "server.hpp" -#include -#include - -#include -#include - -#include -#include -#include - -namespace llarp::quic -{ - std::shared_ptr - Server::accept_initial_connection(const Packet& p) - { - LogDebug("Accepting new connection"); - - // This is a new incoming connection - ngtcp2_pkt_hd hd; - auto rv = ngtcp2_accept(&hd, u8data(p.data), p.data.size()); - - if (rv == -1) - { // Invalid packet - LogWarn("Invalid packet received, length=", p.data.size()); - LogTrace("packet body: ", buffer_printer{p.data}); - return nullptr; - } - - if (rv == 1) - { // Invalid/unexpected version, send a version negotiation - LogDebug("Invalid/unsupported version; sending version negotiation"); - send_version_negotiation( - ngtcp2_version_cid{ - hd.version, hd.dcid.data, hd.dcid.datalen, hd.scid.data, hd.scid.datalen}, - p.path.remote); - return nullptr; - } - - if (hd.type == NGTCP2_PKT_0RTT) - { - LogWarn("Received 0-RTT packet, which shouldn't happen in our implementation; dropping"); - return nullptr; - } - - if (hd.type == NGTCP2_PKT_INITIAL && hd.tokenlen) - { - // This is a normal QUIC thing, but we don't do it: - LogWarn("Unexpected token in initial packet"); - } - - // create and store Connection - for (;;) - { - if (auto [it, ins] = conns.emplace(ConnectionID::random(), primary_conn_ptr{}); ins) - { - auto connptr = std::make_shared(*this, it->first, hd, p.path); - it->second = connptr; - return connptr; - } - } - } - - size_t - Server::write_packet_header(nuint16_t pport, uint8_t ecn) - { - buf_[0] = SERVER_TO_CLIENT; - std::memcpy(&buf_[1], &pport.n, 2); // remote quic pseudo-port (network order u16) - buf_[3] = std::byte{ecn}; - return 4; - } - -} // namespace llarp::quic diff --git a/llarp/quic/server.hpp b/llarp/quic/server.hpp deleted file mode 100644 index aededc0328..0000000000 --- a/llarp/quic/server.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -#include "endpoint.hpp" -#include "llarp/endpoint_base.hpp" -#include - -namespace llarp::quic -{ - class Server : public Endpoint - { - public: - using stream_open_callback_t = std::function; - - Server(EndpointBase& service_endpoint) : Endpoint{service_endpoint} - { - default_stream_buffer_size = 0; // We don't currently use the endpoint ring buffer - } - - // Stream callback: takes the server, the (just-created) stream, and the connection port. - // Returns true if the stream should be allowed or false to reject the stream. The callback - // should set up the data_callback and close_callback on the stream: they will default to null - // (which means incoming data will simply be dropped). - stream_open_callback_t stream_open_callback; - - private: - // Accept a new incoming connection, i.e. pre-handshake. Returns a nullptr if the connection - // can't be created (e.g. because of invalid initial data), or is invalid. - std::shared_ptr - accept_initial_connection(const Packet& p) override; - - size_t - write_packet_header(nuint16_t pport, uint8_t ecn) override; - }; - -} // namespace llarp::quic diff --git a/llarp/quic/stream.cpp b/llarp/quic/stream.cpp deleted file mode 100644 index 0ddaf73721..0000000000 --- a/llarp/quic/stream.cpp +++ /dev/null @@ -1,354 +0,0 @@ -#include "stream.hpp" -#include "connection.hpp" -#include "endpoint.hpp" -#include - -#include -#include - -// We use a single circular buffer with a pointer to the starting byte (denoted `á` or `ŕ`), the -// overall size, and the number of sent-but-unacked bytes (denoted `a`). `r` denotes an unsent -// byte. -// [ áaaaaaaarrrr ] -// ^ == start -// ------------ == size (== unacked + unsent bytes) -// -------- == unacked_size -// ^ -- the next write starts here -// ^^^^^^^ ^^^^^^^ -- unused buffer space -// -// we give ngtcp2 direct control over the unacked part of this buffer (it will let us know once the -// buffered data is no longer needed, i.e. once it is acknowledged by the remote side). -// -// The complication is that this buffer wraps, so if we write a bunch of data to the above it would -// end up looking like this: -// -// [rrr áaaaaaaarrrrrrrrrrr] -// -// This complicates things a bit, especially when returning the buffer to be written because we -// might have to return two separate string_views (the first would contain [rrrrrrrrrrr] and the -// second would contain [rrr]). As soon as we pass those buffer pointers off to ngtcp2 then our -// buffer looks like: -// -// [aaa áaaaaaaaaaaaaaaaaaa] -// -// Once we get an acknowledgement from the other end of the QUIC connection we can move up B (the -// beginning of the buffer); for example, suppose it acknowledges the next 10 bytes and then the -// following 10; we'll have: -// -// [aaa áaaaaaaaa] -- first 10 acked -// [ áa ] -- next 10 acked -// -// As a special case, if the buffer completely empties (i.e. all data is sent and acked) then we -// reset the starting bytes to the beginning of the buffer. - -namespace llarp::quic -{ - std::string - StreamID::ToString() const - { - return fmt::format(u8"Str❰{}❱", id); - } - - Stream::Stream( - Connection& conn, - data_callback_t data_cb, - close_callback_t close_cb, - size_t buffer_size, - StreamID id) - : data_callback{std::move(data_cb)} - , close_callback{std::move(close_cb)} - , conn{conn} - , stream_id{std::move(id)} - , buffer{buffer_size} - , avail_trigger{conn.endpoint.get_loop()->resource()} - { - avail_trigger->on([this](auto&, auto&) { handle_unblocked(); }); - } - - Stream::Stream(Connection& conn, StreamID id, size_t buffer_size) - : Stream{conn, nullptr, nullptr, buffer_size, std::move(id)} - {} - - Stream::~Stream() - { - LogTrace("Destroying stream ", stream_id); - if (avail_trigger) - { - avail_trigger->close(); - avail_trigger.reset(); - } - bool was_closing = is_closing; - is_closing = is_shutdown = true; - if (!was_closing && close_callback) - close_callback(*this, STREAM_ERROR_CONNECTION_EXPIRED); - } - - void - Stream::set_buffer_size(size_t size) - { - if (used() != 0) - throw std::runtime_error{"Cannot update buffer size while buffer is in use"}; - if (size > 0 && size < 2048) - size = 2048; - - buffer.resize(size); - buffer.shrink_to_fit(); - start = size = unacked_size = 0; - } - - size_t - Stream::buffer_size() const - { - return buffer.empty() ? size + start // start is the acked amount of the first buffer - : buffer.size(); - } - - bool - Stream::append(bstring_view data) - { - assert(!buffer.empty()); - - if (data.size() > available()) - return false; - - // When we are appending we have three cases: - // - data doesn't fit -- we simply abort (return false, above). - // - data fits between the buffer end and `]` -- simply append it and update size - // - data is larger -- copy from the end up to `]`, then copy the rest into the beginning of the - // buffer (i.e. after `[`). - - size_t wpos = (start + size) % buffer.size(); - if (wpos + data.size() > buffer.size()) - { - // We are wrapping - auto data_split = data.begin() + (buffer.size() - wpos); - std::copy(data.begin(), data_split, buffer.begin() + wpos); - std::copy(data_split, data.end(), buffer.begin()); - LogTrace( - "Wrote ", - data.size(), - " bytes to buffer ranges [", - wpos, - ",", - buffer.size(), - ")+[0,", - data.end() - data_split, - ")"); - } - else - { - // No wrap needs, it fits before the end: - std::copy(data.begin(), data.end(), buffer.begin() + wpos); - LogTrace( - "Wrote ", data.size(), " bytes to buffer range [", wpos, ",", wpos + data.size(), ")"); - } - size += data.size(); - LogTrace("New stream buffer: ", size, "/", buffer.size(), " bytes beginning at ", start); - conn.io_ready(); - return true; - } - size_t - Stream::append_any(bstring_view data) - { - if (size_t avail = available(); data.size() > avail) - data.remove_suffix(data.size() - avail); - [[maybe_unused]] bool appended = append(data); - assert(appended); - return data.size(); - } - - void - Stream::append_buffer(const std::byte* buffer, size_t length) - { - assert(this->buffer.empty()); - user_buffers.emplace_back(buffer, length); - size += length; - conn.io_ready(); - } - - void - Stream::acknowledge(size_t bytes) - { - // Frees bytes; e.g. acknowledge(3) changes: - // [ áaaaaarr ] to [ áaarr ] - // [aaarr áa] to [ áarr ] - // [ áaarrr ] to [ ŕrr ] - // [ áaa ] to [´ ] (i.e. empty buffer *and* reset start pos) - // - assert(bytes <= unacked_size && unacked_size <= size); - - LogTrace("Acked ", bytes, " bytes of ", unacked_size, "/", size, " unacked/total"); - - unacked_size -= bytes; - size -= bytes; - if (!buffer.empty()) - start = size == 0 ? 0 - : (start + bytes) - % buffer.size(); // reset start to 0 (to reduce wrapping buffers) if empty - else if (size == 0) - { - user_buffers.clear(); - start = 0; - } - else - { - while (bytes) - { - assert(!user_buffers.empty()); - assert(start < user_buffers.front().second); - if (size_t remaining = user_buffers.front().second - start; bytes >= remaining) - { - user_buffers.pop_front(); - start = 0; - bytes -= remaining; - } - else - { - start += bytes; - bytes = 0; - } - } - } - - if (!unblocked_callbacks.empty()) - available_ready(); - } - - auto - get_buffer_it( - std::deque, size_t>>& bufs, size_t offset) - { - auto it = bufs.begin(); - while (offset >= it->second) - { - offset -= it->second; - it++; - } - return std::make_pair(std::move(it), offset); - } - - std::vector - Stream::pending() - { - std::vector bufs; - size_t rsize = unsent(); - if (!rsize) - return bufs; - if (!buffer.empty()) - { - size_t rpos = (start + unacked_size) % buffer.size(); - if (size_t rend = rpos + rsize; rend <= buffer.size()) - { - bufs.emplace_back(buffer.data() + rpos, rsize); - } - else - { // wrapping - bufs.reserve(2); - bufs.emplace_back(buffer.data() + rpos, buffer.size() - rpos); - bufs.emplace_back(buffer.data(), rend % buffer.size()); - } - } - else - { - assert(!user_buffers.empty()); // If empty then unsent() should have been 0 - auto [it, offset] = get_buffer_it(user_buffers, start + unacked_size); - bufs.reserve(std::distance(it, user_buffers.end())); - assert(it != user_buffers.end()); - bufs.emplace_back(it->first.get() + offset, it->second - offset); - for (++it; it != user_buffers.end(); ++it) - bufs.emplace_back(it->first.get(), it->second); - } - return bufs; - } - - void - Stream::when_available(unblocked_callback_t unblocked_cb) - { - assert(available() == 0); - unblocked_callbacks.push(std::move(unblocked_cb)); - } - - void - Stream::handle_unblocked() - { - if (is_closing) - return; - if (buffer.empty()) - { - while (!unblocked_callbacks.empty() && unblocked_callbacks.front()(*this)) - unblocked_callbacks.pop(); - } - while (!unblocked_callbacks.empty() && available() > 0) - { - if (unblocked_callbacks.front()(*this)) - unblocked_callbacks.pop(); - else - assert(available() == 0); - } - conn.io_ready(); - } - - void - Stream::io_ready() - { - conn.io_ready(); - } - - void - Stream::available_ready() - { - if (avail_trigger) - avail_trigger->send(); - } - - void - Stream::wrote(size_t bytes) - { - // Called to tell us we sent some bytes off, e.g. wrote(3) changes: - // [ áaarrrrrr ] or [rr áaar] - // to: - // [ áaaaaarrr ] or [aa áaaa] - LogTrace("wrote ", bytes, ", unsent=", unsent()); - assert(bytes <= unsent()); - unacked_size += bytes; - } - - void - Stream::close(std::optional error_code) - { - LogDebug( - "Closing ", - stream_id, - error_code ? " immediately with code " + std::to_string(*error_code) : " gracefully"); - - if (is_shutdown) - LogDebug("Stream is already shutting down"); - else if (error_code) - { - is_closing = is_shutdown = true; - ngtcp2_conn_shutdown_stream(conn, 0, stream_id.id, *error_code); - } - else if (is_closing) - LogDebug("Stream is already closing"); - else - is_closing = true; - - if (is_shutdown) - data_callback = {}; - - conn.io_ready(); - } - - void - Stream::data(std::shared_ptr data) - { - user_data = std::move(data); - } - - void - Stream::weak_data(std::weak_ptr data) - { - user_data = std::move(data); - } - -} // namespace llarp::quic diff --git a/llarp/quic/stream.hpp b/llarp/quic/stream.hpp deleted file mode 100644 index bed6f483a4..0000000000 --- a/llarp/quic/stream.hpp +++ /dev/null @@ -1,368 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace llarp::quic -{ - class Connection; - - using bstring_view = std::basic_string_view; - - // Shortcut for a const-preserving `reinterpret_cast`ing c.data() from a std::byte to a uint8_t - // pointer, because we need it all over the place in the ngtcp2 API and I'd rather deal with - // std::byte's out here for type safety. - template < - typename Container, - typename = std::enable_if_t< - sizeof(typename std::remove_reference_t::value_type) == sizeof(uint8_t)>> - inline auto* - u8data(Container&& c) - { - using u8_sameconst_t = std::conditional_t< - std::is_const_v>, - const uint8_t, - uint8_t>; - return reinterpret_cast(c.data()); - } - - // Type-safe wrapper around a int64_t stream id. Default construction is ngtcp2's special - // "no-stream" id. - struct StreamID - { - int64_t id{-1}; - bool - operator==(const StreamID& s) const - { - return s.id == id; - } - bool - operator!=(const StreamID& s) const - { - return s.id != id; - } - bool - operator<(const StreamID& s) const - { - return s.id < id; - } - bool - operator<=(const StreamID& s) const - { - return s.id <= id; - } - bool - operator>(const StreamID& s) const - { - return s.id > id; - } - bool - operator>=(const StreamID& s) const - { - return s.id >= id; - } - - std::string - ToString() const; - }; - - // Application error code we close with if the data handle throws - inline constexpr uint64_t STREAM_ERROR_EXCEPTION = (1ULL << 62) - 2; - - // Error code we send to a stream close callback if the stream's connection expires; this is *not* - // sent over quic, hence using a value >= 2^62 (quic's maximum serializable integer). - inline constexpr uint64_t STREAM_ERROR_CONNECTION_EXPIRED = (1ULL << 62) + 1; -} // namespace llarp::quic - -template <> -constexpr inline bool llarp::IsToStringFormattable = true; - -namespace std -{ - template <> - struct hash - { - size_t - operator()(const llarp::quic::StreamID& s) const - { - return std::hash{}(s.id); - } - }; -} // namespace std - -namespace llarp::quic -{ - // Class for an established stream (a single connection has multiple streams): we have a - // fixed-sized ring buffer for holding outgoing data, and a callback to invoke on received data. - // To construct a Stream call `conn.open_stream()`. - class Stream : public std::enable_shared_from_this - { - public: - // Returns the StreamID of this stream - const StreamID& - id() const - { - return stream_id; - } - - // Sets the size of the outgoing data buffer. This may *only* be used if the buffer is - // currently entirely empty; otherwise a runtime_error is thrown. The minimum buffer size is - // 2048, the default is 64kiB. A value of 0 puts the Stream into user-provided buffer mode - // where only the version of `append` taking ownership of a char* is permitted. - void - set_buffer_size(size_t size); - - // Returns the size of the buffer (including both pending and free space). If using - // user-provided buffer mode then this is the sum of all held buffers. - size_t - buffer_size() const; - - // Returns the number of free bytes available in the outgoing stream data buffer. Always 0 in - // user-provided buffer mode. - size_t - available() const - { - return is_closing || buffer.empty() ? 0 : buffer.size() - size; - } - - // Returns the number of bytes currently referenced in the buffer (i.e. pending or - // sent-but-unacknowledged). - size_t - used() const - { - return size; - } - - // Returns the number of bytes of the buffer that have been sent but not yet acknowledged and - // thus are still required. - size_t - unacked() const - { - return unacked_size; - } - - // Returns the number of bytes of the buffer that have not yet been sent. - size_t - unsent() const - { - return used() - unacked(); - } - - // Try to append all of the given bytes to the outgoing stream data buffer. Returns true if - // successful, false (without appending anything) if there is insufficient space. If you want - // to append as much as possible then use `append_any` instead. - bool - append(bstring_view data); - bool - append(std::string_view data) - { - return append(bstring_view{reinterpret_cast(data.data()), data.size()}); - } - - // Append bytes to the outgoing stream data buffer, allowing partial consumption of data if the - // entire provided data cannot be appended. Returns the number of appended bytes (which will be - // less than the total provided if the provided data is larger than `available()`). If you want - // an all-or-nothing append then use `append` instead. - size_t - append_any(bstring_view data); - size_t - append_any(std::string_view data) - { - return append_any(bstring_view{reinterpret_cast(data.data()), data.size()}); - } - - // Takes ownership of the given buffer pointer, queuing it to be sent after any existing buffers - // and freed once fully acked. You *must* have called `set_buffer_size(0)` (or set the - // endpoint's default_stream_buffer_size to 0) in order to use this. - void - append_buffer(const std::byte* buf, size_t length); - - // Starting closing the stream and prevent any more outgoing data from being appended. If - // `error_code` is provided then we close immediately with the given code; if std::nullopt (the - // default) we close gracefully by sending a FIN bit. - void - close(std::optional error_code = std::nullopt); - - // Returns true if this Stream is closing (or already closed). - bool - closing() const - { - return is_closing; - } - - // Callback invoked when data is received - using data_callback_t = std::function; - - // Callback invoked when the stream is closed - using close_callback_t = std::function error_code)>; - - // Callback invoked when free stream buffer space becomes available. Should return true if the - // callback is finished and can be discarded, false if the callback is still needed. If - // returning false then it *must* have filled the stream's outgoing buffer (this is asserted in - // a debug build). - using unblocked_callback_t = std::function; - - // Callback to invoke when we receive some incoming data; there's no particular guarantee on the - // size of the data, just that this will always be called in sequential order. - data_callback_t data_callback; - - // Callback to invoke when the connection has closed. If the close was an abrupt stream close - // initiated by the remote then `error_code` will be set to whatever code the remote side - // provided; for graceful closing or locally initiated closing the error code will be null. - close_callback_t close_callback; - - // Queues a callback to be invoked when space becomes available for writing in the buffer. The - // callback should true if it completed, false if it still needs more buffer space. If multiple - // callbacks are queued they are invoked in order, space permitting. The stored std::function - // will not be moved or copied after being invoked (i.e. if invoked multiple times it will - // always be invoked on the same instance). - // - // Available callbacks should only be used when the buffer is full, typically immediately after - // an `append_any` call that returns less than the full write. Similarly a false return from an - // unblock function (which keeps the callback alive) should satisfy the same condition. - // - // In user-provided buffer mode the callback will be invoked after any data has been acked: it - // is up to the caller to look at used()/buffer_size()/etc. to decide what to do. As described - // above, return true to remove this callback, false to keep it and try again after the next - // ack. - void - when_available(unblocked_callback_t unblocked_cb); - - // Calls io_ready() on the stream's connection to scheduling sending outbound data - void - io_ready(); - - // Schedules processing of the "when_available" callbacks - void - available_ready(); - - // Lets you stash some arbitrary data in a shared_ptr; this is not used internally. - void - data(std::shared_ptr data); - - // Variation of data() that holds the pointer in a weak_ptr instead of a shared_ptr. (Note that - // setting this replaces data() and vice versa). - void - weak_data(std::weak_ptr data); - - // Retrieves the stashed data, with a static_cast to the desired type. This is used for - // retrieval of both shared or weak data types (if held as a weak_ptr it is lock()ed first). - template - std::shared_ptr - data() const - { - return std::static_pointer_cast( - std::holds_alternative>(user_data) - ? var::get>(user_data) - : var::get>(user_data).lock()); - } - - // Returns a reference to the connection that owns this stream - Connection& - get_connection() - { - return conn; - } - - ~Stream(); - - private: - friend class Connection; - - Stream( - Connection& conn, - data_callback_t data_cb, - close_callback_t close_cb, - size_t buffer_size, - StreamID id = {-1}); - Stream(Connection& conn, StreamID id, size_t buffer_size); - - // Non-copyable, non-movable; we manage it via a unique_ptr held by its Connection - Stream(const Stream&) = delete; - const Stream& - operator=(const Stream&) = delete; - Stream(Stream&&) = delete; - Stream& - operator=(Stream&&) = delete; - - Connection& conn; - - // Callback(s) to invoke once we have the requested amount of space available in the buffer. - std::queue unblocked_callbacks; - void - handle_unblocked(); // Processes the above if space is available - - // Called to advance the number of acknowledged bytes (freeing up that space in the buffer for - // appending data). - void - acknowledge(size_t bytes); - - // Returns a view into unwritten stream data. This returns a vector of string_views of the data - // to write, in order. After writing any of the provided data you must call `wrote()` to signal - // how much of the given data was consumed (to advance the next pending() call). - std::vector - pending(); - - // Called to signal that bytes have been written and should now be considered sent (but still - // unacknowledged), thereby advancing the initial data position returned by the next `pending()` - // call. Should typically be called after `pending()` to signal how much of the pending data - // was actually used. - void - wrote(size_t bytes); - - // Called by the owning Connection to do a "hard" close of a stream during Connection - // destruction: unlike a regular close this doesn't try to transmit a close over the wire (which - // won't work since the Connection is dead), it just fires the close callback and cleans up. - void - hard_close(); - - // ngtcp2 stream_id, assigned during stream creation - StreamID stream_id{-1}; - - // ring buffer of outgoing stream data that has not yet been acknowledged. This cannot be - // resized once used as ngtcp2 will have pointers into the data. If this is empty then we are - // in user-provided buffer mode. - std::vector buffer{65536}; - - // user-provided buffers; only used when `buffer` is empty (via a `set_buffer_size(0)` or a 0 - // size given in the constructor). - std::deque, size_t>> user_buffers; - - // Offset of the first used byte in the circular buffer, will always be in [0, buffer.size()). - // For user-provided buffers this is the starting offset in the currently sending user-provided - // buffer. - size_t start{0}; - - // Number of sent-but-unacked packets in the buffer (i.e. [start, start+unacked_size) are sent - // but not yet acked). - size_t unacked_size{0}; - - // Number of used bytes in the buffer; thus start+size is the next write location and - // [start+unacked_size, start+size) is the range of not-yet-sent bytes. (Note that this - // description is ignoring the circularity of the buffer). - size_t size{0}; - - bool is_new{true}; - bool is_closing{false}; - bool sent_fin{false}; - bool is_shutdown{false}; - - // Async trigger we use to schedule when_available callbacks (so that we can make them happen in - // batches rather than after each and every packet ack). - std::shared_ptr avail_trigger; - - std::variant, std::weak_ptr> user_data; - }; - -} // namespace llarp::quic diff --git a/llarp/router/outbound_message_handler.cpp b/llarp/router/outbound_message_handler.cpp index 5743f9dbc1..ea85707d8e 100644 --- a/llarp/router/outbound_message_handler.cpp +++ b/llarp/router/outbound_message_handler.cpp @@ -1,4 +1,3 @@ -#include "outbound_message_handler.hpp" #include #include "router.hpp" diff --git a/llarp/router/rc_gossiper.hpp b/llarp/router/rc_gossiper.hpp index d6cc4dab3e..bd580646e1 100644 --- a/llarp/router/rc_gossiper.hpp +++ b/llarp/router/rc_gossiper.hpp @@ -1,10 +1,14 @@ #pragma once #include -#include "outbound_message_handler.hpp" + +#include +#include "llarp/router_id.hpp" namespace llarp { + struct Router; + /// The maximum number of peers we will flood a gossiped RC to when propagating an RC constexpr size_t MaxGossipPeers = 20; struct LinkManager; diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 4826a721f5..fd21487b52 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -75,6 +75,9 @@ namespace llarp // TODO: investigate changes needed for libquic integration // still needed at all? + + // TODO: No. The answer is No. + // TONUKE: EVERYTHING ABOUT THIS void Router::PumpLL() { @@ -255,7 +258,7 @@ namespace llarp return _rc_lookup_handler.get_random_whitelist_router(router); } - if (const auto maybe = node_db()->GetRandom([](const auto&) -> bool { return true; })) + if (auto maybe = node_db()->GetRandom([](const auto&) -> bool { return true; })) { router = maybe->pubkey; return true; @@ -292,9 +295,9 @@ namespace llarp } bool - Router::send_data_message(const RouterID& remote, const AbstractDataMessage& msg) + Router::send_data_message(const RouterID& remote, std::string payload) { - return _link_manager.send_data_message(remote, msg.bt_encode()); + return _link_manager.send_data_message(remote, std::move(payload)); } bool @@ -1567,19 +1570,6 @@ namespace llarp return *llarp::net::Platform::Default_ptr(); } - void - Router::message_sent(const RouterID& remote, SendStatus status) - { - if (status == SendStatus::Success) - { - LogDebug("Message successfully sent to ", remote); - } - else - { - LogDebug("Message failed sending to ", remote); - } - } - void Router::handle_router_event(std::unique_ptr event) const { diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 9d9b78c355..81487a6b58 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -161,9 +161,6 @@ namespace llarp bool from_config(const Config& conf); - void - message_sent(const RouterID& remote, SendStatus status); - bool insufficient_peers() const; @@ -499,12 +496,12 @@ namespace llarp /// returns true on successful queue /// NOT threadsafe /// MUST be called in the logic thread - bool - SendToOrQueue( - const RouterID& remote, const AbstractLinkMessage& msg, SendStatusHandler handler); + // bool + // SendToOrQueue( + // const RouterID& remote, const AbstractLinkMessage& msg, SendStatusHandler handler); bool - send_data_message(const RouterID& remote, const AbstractDataMessage& msg); + send_data_message(const RouterID& remote, std::string payload); bool send_control_message( diff --git a/llarp/routing/handler.hpp b/llarp/routing/handler.hpp deleted file mode 100644 index e28a1f4c00..0000000000 --- a/llarp/routing/handler.hpp +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once - -#include - -namespace llarp -{ - struct Router; - - namespace dht - { - struct AbstractDHTMessage; - } - - namespace service - { - struct ProtocolFrameMessage; - } - - namespace routing - { - struct DataDiscardMessage; - struct GrantExitMessage; - struct ObtainExitMessage; - struct RejectExitMessage; - struct TransferTrafficMessage; - struct UpdateExitMessage; - struct UpdateExitVerifyMessage; - struct CloseExitMessage; - struct PathTransferMessage; - struct PathConfirmMessage; - struct PathLatencyMessage; - - // handles messages on the routing level - struct AbstractRoutingMessageHandler - { - virtual bool - HandleObtainExitMessage(const ObtainExitMessage& msg, Router* r) = 0; - - virtual bool - HandleGrantExitMessage(const GrantExitMessage& msg, Router* r) = 0; - - virtual bool - HandleRejectExitMessage(const RejectExitMessage& msg, Router* r) = 0; - - virtual bool - HandleTransferTrafficMessage(const TransferTrafficMessage& msg, Router* r) = 0; - - virtual bool - HandleUpdateExitMessage(const UpdateExitMessage& msg, Router* r) = 0; - - virtual bool - HandleUpdateExitVerifyMessage(const UpdateExitVerifyMessage& msg, Router* r) = 0; - - virtual bool - HandleCloseExitMessage(const CloseExitMessage& msg, Router* r) = 0; - - virtual bool - HandleDataDiscardMessage(const DataDiscardMessage& msg, Router* r) = 0; - - virtual bool - HandlePathTransferMessage(const PathTransferMessage& msg, Router* r) = 0; - - virtual bool - HandleHiddenServiceFrame(const service::ProtocolFrameMessage& msg) = 0; - - virtual bool - HandlePathConfirmMessage(const PathConfirmMessage& msg, Router* r) = 0; - - virtual bool - HandlePathLatencyMessage(const PathLatencyMessage& msg, Router* r) = 0; - virtual bool - HandleDHTMessage(const dht::AbstractDHTMessage& msg, Router* r) = 0; - }; - - using MessageHandler_ptr = std::shared_ptr; - - } // namespace routing -} // namespace llarp diff --git a/llarp/routing/message.hpp b/llarp/routing/message.hpp deleted file mode 100644 index c29b7be39b..0000000000 --- a/llarp/routing/message.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -namespace -{ - static auto route_cat = llarp::log::Cat("lokinet.routing"); -} // namespace - -namespace llarp -{ - struct Router; - namespace routing - { - struct AbstractRoutingMessageHandler; - - struct AbstractRoutingMessage : private AbstractSerializable - { - PathID_t from; - uint64_t sequence_number{0}; - uint64_t version = llarp::constants::proto_version; - - AbstractRoutingMessage() = default; - - virtual ~AbstractRoutingMessage() = default; - - virtual bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) = 0; - - std::string - bt_encode() const override = 0; - - virtual bool - handle_message(AbstractRoutingMessageHandler* h, Router* r) const = 0; - - virtual void - clear() = 0; - - // methods we do not want to inherit onwards from AbstractSerializable - void - bt_encode(oxenc::bt_dict_producer&) const final - { - throw std::runtime_error{ - "Error: Routing messages should not encode directly to a bt dict producer!"}; - } - - bool - operator<(const AbstractRoutingMessage& other) const - { - return other.sequence_number < sequence_number; - } - }; - - } // namespace routing -} // namespace llarp diff --git a/llarp/routing/message_parser.cpp b/llarp/routing/message_parser.cpp deleted file mode 100644 index 64b214d138..0000000000 --- a/llarp/routing/message_parser.cpp +++ /dev/null @@ -1,142 +0,0 @@ -#include "message_parser.hpp" - -#include -#include -#include -#include "path_dht_message.hpp" -#include "path_confirm_message.hpp" -#include "path_latency_message.hpp" -#include "path_transfer_message.hpp" -#include "transfer_traffic_message.hpp" -#include - -namespace llarp::routing -{ - struct InboundMessageParser::MessageHolder - { - DataDiscardMessage D; - PathLatencyMessage L; - PathDHTMessage M; - PathConfirmMessage P; - PathTransferMessage T; - service::ProtocolFrameMessage H; - TransferTrafficMessage I; - GrantExitMessage G; - RejectExitMessage J; - ObtainExitMessage O; - UpdateExitMessage U; - CloseExitMessage C; - }; - - InboundMessageParser::InboundMessageParser() : m_Holder(std::make_unique()) - {} - - InboundMessageParser::~InboundMessageParser() = default; - - bool - InboundMessageParser::operator()(llarp_buffer_t* buffer, llarp_buffer_t* key) - { - if (key == nullptr && firstKey) - { - // empty dict - return false; - } - if (!key) - return true; - if (firstKey) - { - llarp_buffer_t strbuf; - if (!(key->startswith("A"))) - return false; - if (!bencode_read_string(buffer, &strbuf)) - return false; - if (strbuf.sz != 1) - return false; - ourKey = *strbuf.cur; - LogDebug("routing message '", std::string{ourKey, 1}, "'"); - switch (ourKey) - { - case 'D': - msg = &m_Holder->D; - break; - case 'L': - msg = &m_Holder->L; - break; - case 'M': - msg = &m_Holder->M; - break; - case 'P': - msg = &m_Holder->P; - break; - case 'T': - msg = &m_Holder->T; - break; - case 'H': - msg = &m_Holder->H; - break; - case 'I': - msg = &m_Holder->I; - break; - case 'G': - msg = &m_Holder->G; - break; - case 'J': - msg = &m_Holder->J; - break; - case 'O': - msg = &m_Holder->O; - break; - case 'U': - msg = &m_Holder->U; - break; - case 'C': - msg = &m_Holder->C; - break; - default: - llarp::LogError("invalid routing message id: ", *strbuf.cur); - } - if (msg) - msg->version = version; - firstKey = false; - return msg != nullptr; - } - - return msg->decode_key(*key, buffer); - } - - bool - InboundMessageParser::ParseMessageBuffer( - const llarp_buffer_t& buf, AbstractRoutingMessageHandler* h, const PathID_t& from, Router* r) - { - bool result = false; - msg = nullptr; - firstKey = true; - ManagedBuffer copiedBuf(buf); - auto& copy = copiedBuf.underlying; - uint64_t v = 0; - if (BEncodeSeekDictVersion(v, ©, 'V')) - { - version = v; - } - if (bencode_read_dict(*this, ©)) - { - msg->from = from; - LogDebug("handle routing message ", msg->sequence_number, " from ", from); - result = msg->handle_message(h, r); - if (!result) - { - llarp::LogWarn("Failed to handle inbound routing message ", ourKey); - } - } - else - { - llarp::LogError("read dict failed in routing layer"); - llarp::DumpBuffer(buf); - } - if (msg) - msg->clear(); - msg = nullptr; - version = 0; - return result; - } -} // namespace llarp::routing diff --git a/llarp/routing/message_parser.hpp b/llarp/routing/message_parser.hpp deleted file mode 100644 index 0ee7a5ceef..0000000000 --- a/llarp/routing/message_parser.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include -#include - -#include - -namespace llarp -{ - struct Router; - struct PathID_t; - - namespace routing - { - struct AbstractRoutingMessage; - struct AbstractRoutingMessageHandler; - - struct InboundMessageParser - { - InboundMessageParser(); - ~InboundMessageParser(); - - bool - ParseMessageBuffer( - const llarp_buffer_t& buf, - AbstractRoutingMessageHandler* handler, - const PathID_t& from, - Router* r); - - bool - operator()(llarp_buffer_t* buffer, llarp_buffer_t* key); - - private: - uint64_t version = 0; - bool firstKey{false}; - char ourKey{'\0'}; - struct MessageHolder; - - AbstractRoutingMessage* msg{nullptr}; - std::unique_ptr m_Holder; - }; - } // namespace routing -} // namespace llarp diff --git a/llarp/routing/path_confirm_message.cpp b/llarp/routing/path_confirm_message.cpp deleted file mode 100644 index 268e2e4b83..0000000000 --- a/llarp/routing/path_confirm_message.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "path_confirm_message.hpp" - -#include "handler.hpp" -#include -#include - -namespace llarp::routing -{ - PathConfirmMessage::PathConfirmMessage(llarp_time_t lifetime) - : path_lifetime(lifetime), path_created_time(time_now_ms()) - {} - - bool - PathConfirmMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) - { - bool read = false; - if (!BEncodeMaybeReadDictInt("L", path_lifetime, read, key, val)) - return false; - if (!BEncodeMaybeReadDictInt("S", sequence_number, read, key, val)) - return false; - if (!BEncodeMaybeReadDictInt("T", path_created_time, read, key, val)) - return false; - if (!BEncodeMaybeReadDictInt("V", version, read, key, val)) - return false; - return read; - } - - std::string - PathConfirmMessage::bt_encode() const - { - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("A", "P"); - btdp.append("L", path_lifetime.count()); - btdp.append("S", sequence_number); - btdp.append("T", path_created_time.count()); - btdp.append("V", version); - } - catch (...) - { - log::critical(route_cat, "Error: PathConfirmMessage failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - - bool - PathConfirmMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const - { - return h && h->HandlePathConfirmMessage(*this, r); - } - -} // namespace llarp::routing diff --git a/llarp/routing/path_confirm_message.hpp b/llarp/routing/path_confirm_message.hpp deleted file mode 100644 index d7f4f1624c..0000000000 --- a/llarp/routing/path_confirm_message.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include "message.hpp" - -namespace llarp::routing -{ - struct PathConfirmMessage final : public AbstractRoutingMessage - { - llarp_time_t path_lifetime = 0s; - llarp_time_t path_created_time = 0s; - - PathConfirmMessage() = default; - PathConfirmMessage(llarp_time_t lifetime); - ~PathConfirmMessage() override = default; - - std::string - bt_encode() const override; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; - - bool - handle_message(AbstractRoutingMessageHandler* h, Router* r) const override; - - void - clear() override - { - path_lifetime = 0s; - path_created_time = 0s; - version = 0; - } - }; -} // namespace llarp::routing diff --git a/llarp/routing/path_dht_message.cpp b/llarp/routing/path_dht_message.cpp deleted file mode 100644 index bca3ad5e9e..0000000000 --- a/llarp/routing/path_dht_message.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include "path_dht_message.hpp" - -#include -#include "handler.hpp" - -namespace llarp::routing -{ - bool - PathDHTMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) - { - if (key.startswith("M")) - { - llarp::dht::Key_t fromKey; - fromKey.Zero(); - return llarp::dht::DecodeMessageList(fromKey, val, dht_msgs, true); - } - if (key.startswith("S")) - { - return bencode_read_integer(val, &sequence_number); - } - if (key.startswith("V")) - { - return bencode_read_integer(val, &version); - } - return false; - } - - std::string - PathDHTMessage::bt_encode() const - { - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("A", "M"); - - { - auto subdict = btdp.append_dict("M"); - - for (auto& m : dht_msgs) - m->bt_encode(subdict); - } - - btdp.append("S", sequence_number); - btdp.append("V", version); - } - catch (...) - { - log::critical(route_cat, "Error: DHTMessage failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - - /// 'h' here is either TransitHop or Path. - /// TransitHop chains to dht::Context::RelayRequestForPath and is where the - /// end of a path handles a client's DHT message Path handles the message - /// (e.g. dht::IMessage::HandleMessage()) in-place and is the case where a - /// client receives a DHT message - bool - PathDHTMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const - { - // set source as us - const llarp::dht::Key_t us(r->pubkey()); - for (const auto& msg : dht_msgs) - { - msg->From = us; - msg->pathID = from; - if (!h->HandleDHTMessage(*msg, r)) - return false; - } - return true; - } -} // namespace llarp::routing diff --git a/llarp/routing/path_dht_message.hpp b/llarp/routing/path_dht_message.hpp deleted file mode 100644 index 365a2e8376..0000000000 --- a/llarp/routing/path_dht_message.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include -#include "message.hpp" - -#include - -namespace llarp::routing -{ - struct PathDHTMessage final : public AbstractRoutingMessage - { - std::vector> dht_msgs; - - ~PathDHTMessage() override = default; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; - - std::string - bt_encode() const override; - - bool - handle_message(AbstractRoutingMessageHandler* h, Router* r) const override; - - void - clear() override - { - dht_msgs.clear(); - } - }; -} // namespace llarp::routing diff --git a/llarp/routing/path_latency_message.cpp b/llarp/routing/path_latency_message.cpp deleted file mode 100644 index b70b7041ca..0000000000 --- a/llarp/routing/path_latency_message.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "path_latency_message.hpp" - -#include "handler.hpp" -#include - -namespace llarp::routing -{ - PathLatencyMessage::PathLatencyMessage() = default; - - bool - PathLatencyMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) - { - bool read = false; - if (!BEncodeMaybeReadDictInt("L", latency, read, key, val)) - return false; - if (!BEncodeMaybeReadDictInt("S", sequence_number, read, key, val)) - return false; - if (!BEncodeMaybeReadDictInt("T", sent_time, read, key, val)) - return false; - return read; - } - - std::string - PathLatencyMessage::bt_encode() const - { - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("A", "L"); - if (latency) - btdp.append("L", latency); - if (sent_time) - btdp.append("T", sent_time); - btdp.append("S", sequence_number); - } - catch (...) - { - log::critical(route_cat, "Error: PathLatencyMessage failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - - bool - PathLatencyMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const - { - return h && h->HandlePathLatencyMessage(*this, r); - } - -} // namespace llarp::routing diff --git a/llarp/routing/path_latency_message.hpp b/llarp/routing/path_latency_message.hpp deleted file mode 100644 index fdbfc42ed7..0000000000 --- a/llarp/routing/path_latency_message.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "message.hpp" - -namespace llarp::routing -{ - struct PathLatencyMessage final : public AbstractRoutingMessage - { - uint64_t sent_time = 0; - uint64_t latency = 0; - PathLatencyMessage(); - - std::string - bt_encode() const override; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; - - void - clear() override - { - sent_time = 0; - latency = 0; - version = 0; - } - - bool - handle_message(AbstractRoutingMessageHandler* h, Router* r) const override; - }; -} // namespace llarp::routing diff --git a/llarp/routing/path_transfer_message.cpp b/llarp/routing/path_transfer_message.cpp deleted file mode 100644 index fd840997dc..0000000000 --- a/llarp/routing/path_transfer_message.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "path_transfer_message.hpp" - -#include "handler.hpp" -#include - -namespace llarp::routing -{ - bool - PathTransferMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) - { - bool read = false; - if (!BEncodeMaybeReadDictEntry("P", path_id, read, key, val)) - return false; - if (!BEncodeMaybeReadDictInt("S", sequence_number, read, key, val)) - return false; - if (!BEncodeMaybeReadDictEntry("T", protocol_frame_msg, read, key, val)) - return false; - if (!BEncodeMaybeReadDictInt("V", version, read, key, val)) - return false; - if (!BEncodeMaybeReadDictEntry("Y", nonce, read, key, val)) - return false; - return read; - } - - std::string - PathTransferMessage::bt_encode() const - { - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("A", "T"); - btdp.append("P", path_id.ToView()); - btdp.append("T", protocol_frame_msg.bt_encode()); - btdp.append("V", version); - btdp.append("Y", nonce.ToView()); - } - catch (...) - { - log::critical(route_cat, "Error: PathTransferMessage failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - - bool - PathTransferMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const - { - return h->HandlePathTransferMessage(*this, r); - } - -} // namespace llarp::routing diff --git a/llarp/routing/path_transfer_message.hpp b/llarp/routing/path_transfer_message.hpp deleted file mode 100644 index d156ef2ff7..0000000000 --- a/llarp/routing/path_transfer_message.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include -#include -#include "message.hpp" -#include - -namespace llarp::routing -{ - struct PathTransferMessage final : public AbstractRoutingMessage - { - PathID_t path_id; - service::ProtocolFrameMessage protocol_frame_msg; - TunnelNonce nonce; - - PathTransferMessage() = default; - PathTransferMessage(const service::ProtocolFrameMessage& f, const PathID_t& p) - : path_id(p), protocol_frame_msg(f) - { - nonce.Randomize(); - } - ~PathTransferMessage() override = default; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; - - std::string - bt_encode() const override; - - bool - handle_message(AbstractRoutingMessageHandler*, Router* r) const override; - - void - clear() override - { - path_id.Zero(); - protocol_frame_msg.clear(); - nonce.Zero(); - version = 0; - } - }; - -} // namespace llarp::routing diff --git a/llarp/routing/transfer_traffic_message.cpp b/llarp/routing/transfer_traffic_message.cpp deleted file mode 100644 index 3e27377104..0000000000 --- a/llarp/routing/transfer_traffic_message.cpp +++ /dev/null @@ -1,73 +0,0 @@ -#include "transfer_traffic_message.hpp" - -#include "handler.hpp" -#include - -#include - -namespace llarp::routing -{ - bool - TransferTrafficMessage::PutBuffer(const llarp_buffer_t& buf, uint64_t counter) - { - if (buf.sz > MAX_EXIT_MTU) - return false; - enc_buf.emplace_back(buf.sz + 8); - byte_t* ptr = enc_buf.back().data(); - oxenc::write_host_as_big(counter, ptr); - ptr += 8; - memcpy(ptr, buf.base, buf.sz); - // 8 bytes encoding overhead and 8 bytes counter - _size += buf.sz + 16; - return true; - } - - std::string - TransferTrafficMessage::bt_encode() const - { - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("A", "I"); - btdp.append("P", static_cast(protocol)); - btdp.append("S", sequence_number); - btdp.append("V", version); - - { - auto sublist = btdp.append_list("X"); - - for (auto& b : enc_buf) - sublist.append(std::string_view{reinterpret_cast(b.data()), b.size()}); - } - } - catch (...) - { - log::critical(route_cat, "Error: PathLatencyMessage failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - - bool - TransferTrafficMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) - { - bool read = false; - if (!BEncodeMaybeReadDictInt("S", sequence_number, read, key, buf)) - return false; - if (!BEncodeMaybeReadDictInt("P", protocol, read, key, buf)) - return false; - if (!BEncodeMaybeReadDictInt("V", version, read, key, buf)) - return false; - if (!BEncodeMaybeReadDictList("X", enc_buf, read, key, buf)) - return false; - return read or bencode_discard(buf); - } - - bool - TransferTrafficMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const - { - return h->HandleTransferTrafficMessage(*this, r); - } - -} // namespace llarp::routing diff --git a/llarp/routing/transfer_traffic_message.hpp b/llarp/routing/transfer_traffic_message.hpp deleted file mode 100644 index 890c178f45..0000000000 --- a/llarp/routing/transfer_traffic_message.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include -#include "message.hpp" -#include - -#include - -namespace llarp::routing -{ - constexpr size_t EXIT_PAD_SIZE = 512 - 48; - constexpr size_t MAX_EXIT_MTU = 1500; - constexpr size_t EXIT_OVERHEAD = sizeof(uint64_t); - - struct TransferTrafficMessage final : public AbstractRoutingMessage - { - std::vector> enc_buf; - service::ProtocolType protocol; - size_t _size = 0; - - void - clear() override - { - enc_buf.clear(); - _size = 0; - version = 0; - protocol = service::ProtocolType::TrafficV4; - } - - size_t - Size() const - { - return _size; - } - - /// append buffer to X - bool - PutBuffer(const llarp_buffer_t& buf, uint64_t counter); - - std::string - bt_encode() const override; - - bool - decode_key(const llarp_buffer_t& k, llarp_buffer_t* val) override; - - bool - handle_message(AbstractRoutingMessageHandler* h, Router* r) const override; - }; -} // namespace llarp::routing diff --git a/llarp/service/address.hpp b/llarp/service/address.hpp index a5ad0eeba4..e65b4c6831 100644 --- a/llarp/service/address.hpp +++ b/llarp/service/address.hpp @@ -82,7 +82,7 @@ namespace llarp RouterID ToRouter() const { - return RouterID(as_array()); + return {as_array()}; } }; diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 01d8b678b2..c6b7cedd47 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -1434,34 +1434,29 @@ namespace llarp } bool - Endpoint::SendToOrQueue(ConvoTag tag, const llarp_buffer_t& pkt, ProtocolType t) + Endpoint::send_to(ConvoTag tag, std::string payload) { if (tag.IsZero()) { - LogWarn("SendToOrQueue failed: convo tag is zero"); + log::warning(log_cat, "SendToOrQueue failed: convo tag is zero"); return false; } - LogDebug(Name(), " send ", pkt.sz, " bytes on T=", tag); + log::debug(log_cat, "{} sending {} bytes (Tag: {})", Name(), payload.size(), tag); + if (auto maybe = GetEndpointWithConvoTag(tag)) { - if (auto* ptr = std::get_if
(&*maybe)) + if (auto rid = std::get_if(&*maybe)) { - if (*ptr == _identity.pub.Addr()) - { - ConvoTagTX(tag); - _state->router->TriggerPump(); - if (not HandleInboundPacket(tag, pkt, t, 0)) - return false; - ConvoTagRX(tag); - return true; - } + return router()->send_data_message(*rid, payload); + } + if (auto saddr = std::get_if
(&*maybe)) + { + return router()->send_data_message(saddr->ToRouter(), payload); } - if (not SendToOrQueue(*maybe, pkt, t)) - return false; - return true; } - LogDebug("SendToOrQueue failed: no endpoint for convo tag ", tag); + + log::debug(log_cat, "SendToOrQueue failed: no endpoint for convo tag {}", tag); return false; } diff --git a/llarp/service/endpoint.hpp b/llarp/service/endpoint.hpp index 00a292d290..573fd703f7 100644 --- a/llarp/service/endpoint.hpp +++ b/llarp/service/endpoint.hpp @@ -246,7 +246,7 @@ namespace llarp lookup_name( std::string name, std::function func = nullptr) override; - // "find introset?"" + // "find introset?" void LookupServiceAsync( std::string name, @@ -447,7 +447,7 @@ namespace llarp // Looks up the ConvoTag and, if it exists, calls SendToOrQueue to send it to a remote client // or a snode (or nothing, if the convo tag is unknown). bool - SendToOrQueue(ConvoTag tag, const llarp_buffer_t& payload, ProtocolType t) override; + send_to(ConvoTag tag, std::string payload) override; std::optional MaybeGetAuthInfoForEndpoint(service::Address addr); From 6b1e3fbbc0d8d2999dcf0d2094d87e31e34eac4a Mon Sep 17 00:00:00 2001 From: dr7ana Date: Mon, 16 Oct 2023 06:39:57 -0700 Subject: [PATCH 053/312] Touched up path build message handling --- llarp/crypto/crypto.cpp | 54 +++++++++ llarp/crypto/crypto.hpp | 8 ++ llarp/exit/endpoint.hpp | 1 - llarp/link/link_manager.cpp | 236 +++++++++++++++++++----------------- llarp/messages/exit.hpp | 19 +-- llarp/messages/path.hpp | 32 ++--- llarp/path/pathbuilder.cpp | 1 + 7 files changed, 208 insertions(+), 143 deletions(-) diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index 9de7ee666d..471fa3187d 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -45,6 +45,28 @@ namespace llarp return true; } + static bool + dh(uint8_t* out, + const uint8_t* client_pk, + const uint8_t* server_pk, + const uint8_t* themPub, + const uint8_t* usSec) + { + llarp::SharedSecret shared; + crypto_generichash_state h; + + if (crypto_scalarmult_curve25519(shared.data(), usSec, themPub)) + { + return false; + } + crypto_generichash_blake2b_init(&h, nullptr, 0U, shared.size()); + crypto_generichash_blake2b_update(&h, client_pk, 32); + crypto_generichash_blake2b_update(&h, server_pk, 32); + crypto_generichash_blake2b_update(&h, shared.data(), 32); + crypto_generichash_blake2b_final(&h, out, shared.size()); + return true; + } + static bool dh_client_priv( llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n) @@ -56,6 +78,7 @@ namespace llarp return crypto_generichash_blake2b(shared.data(), 32, n.data(), 32, dh_result.data(), 32) != -1; } + llarp::LogWarn("crypto::dh_client - dh failed"); return false; } @@ -65,11 +88,27 @@ namespace llarp llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n) { llarp::SharedSecret dh_result; + if (dh(dh_result, pk, sk.toPublic(), pk.data(), sk)) { return crypto_generichash_blake2b(shared.data(), 32, n.data(), 32, dh_result.data(), 32) != -1; } + + llarp::LogWarn("crypto::dh_server - dh failed"); + return false; + } + + static bool + dh_server_priv(uint8_t* shared, const uint8_t* pk, const uint8_t* sk, const uint8_t* nonce) + { + llarp::SharedSecret dh_result; + + if (dh(dh_result.data(), pk, sk, pk, sk)) + { + return crypto_generichash_blake2b(shared, 32, nonce, 32, dh_result.data(), 32) != -1; + } + llarp::LogWarn("crypto::dh_server - dh failed"); return false; } @@ -133,6 +172,12 @@ namespace llarp return crypto_stream_xchacha20_xor(buf, buf, size, n.data(), k.data()) == 0; } + bool + Crypto::xchacha20(uint8_t* buf, size_t size, const uint8_t* secret, const uint8_t* nonce) + { + return crypto_stream_xchacha20_xor(buf, buf, size, nonce, secret) == 0; + } + bool Crypto::dh_client( llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n) @@ -146,6 +191,15 @@ namespace llarp { return dh_server_priv(shared, pk, sk, n); } + bool + Crypto::dh_server( + uint8_t* shared_secret, + const uint8_t* other_pk, + const uint8_t* local_pk, + const uint8_t* nonce) + { + return dh_server_priv(shared_secret, other_pk, local_pk, nonce); + } /// transport dh client side bool Crypto::transport_dh_client( diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index fd5adaf4de..25d7b2705e 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -30,6 +30,8 @@ namespace llarp /// xchacha symmetric cipher bool xchacha20(uint8_t*, size_t size, const SharedSecret&, const TunnelNonce&); + bool + xchacha20(uint8_t*, size_t size, const uint8_t*, const uint8_t*); /// path dh creator's side bool @@ -37,6 +39,12 @@ namespace llarp /// path dh relay side bool dh_server(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&); + bool + dh_server( + uint8_t* shared_secret, + const uint8_t* other_pk, + const uint8_t* local_pk, + const uint8_t* nonce); /// transport dh client side bool transport_dh_client(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&); diff --git a/llarp/exit/endpoint.hpp b/llarp/exit/endpoint.hpp index 9f0943f8de..45e11f160a 100644 --- a/llarp/exit/endpoint.hpp +++ b/llarp/exit/endpoint.hpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 35efaf78bf..b0de207910 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -536,7 +536,9 @@ namespace llarp } _router.rpc_client()->lookup_ons_hash( - name_hash, [this, msg = std::move(m)](std::optional maybe) mutable { + name_hash, + [this, + msg = std::move(m)]([[maybe_unused]] std::optional maybe) mutable { if (maybe) msg.respond(serialize_response({{"NAME", maybe->ciphertext}})); else @@ -1108,77 +1110,93 @@ namespace llarp { if (!_router.path_context().AllowingTransit()) { - log::warning("got path build request when not permitting transit"); + log::warning(link_cat, "got path build request when not permitting transit"); m.respond(serialize_response({{"STATUS", PathBuildMessage::NO_TRANSIT}}), true); return; } try { - // not using list_consumer here because we need to move the first (our) frame - // to the end and re-send, unless we're the terminal hop. This could be done - // with list_consumer, but it would involve messy mucking around with the - // encoded list. Revisit if optimization issue (shouldn't be). - auto frame_list = oxenc::bt_deserialize(m.body()); - if (frames.size() != path::MAX_LEN) - { - log::info( - link_cat, - "Path build request has invalid number of records, ", - frame_list.size(), - "!=", - path::MAX_LEN); - m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_FRAMES}}), true); - return; - } - - const auto& hash = frame_list[0].at("hash"); - auto& frame_str = frame_list[0].at("frame"); - - oxenc::bt_dict_consumer frame_dict{frame_str}; - - auto hop_info = frame_dict.require("encrypted"); - TunnelNonce nonce; - nonce.from_string_view(frame_dict.require("nonce")); - Pubkey otherPubkey; - otherPubkey.from_string_view(frame_dict.require("pubkey")); + std::string payload{m.body()}, frame_payload; + std::string frame, hash, hop_payload, commkey, rx_id, tx_id, upstream; + ustring other_pubkey, outer_nonce, inner_nonce; + uint64_t lifetime; auto crypto = CryptoManager::instance(); - SharedSecret shared; - // derive shared secret using ephemeral pubkey and our secret key (and nonce) - if (!crypto->dh_server(shared, otherPubkey, _router.identity(), nonce)) + try { - log::info("DH failed during path build."); - m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true); - return; - } + oxenc::bt_list_consumer btlc{payload}; + frame_payload = btlc.consume_string(); + + oxenc::bt_dict_consumer frame_info{frame_payload}; + hash = frame_info.require("HASH"); + frame = frame_info.require("FRAME"); + + oxenc::bt_dict_consumer hop_dict{frame}; + hop_payload = frame_info.require("ENCRYPTED"); + outer_nonce = frame_info.require("NONCE"); + other_pubkey = frame_info.require("PUBKEY"); + + SharedSecret shared; + // derive shared secret using ephemeral pubkey and our secret key (and nonce) + if (!crypto->dh_server( + shared.data(), other_pubkey.data(), _router.pubkey(), inner_nonce.data())) + { + log::info(link_cat, "DH server initialization failed during path build"); + m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true); + return; + } - // hash data and check against given hash - ShortHash digest; - if (!crypto->hmac( - digest.data(), - reinterpret_cast(frame_str.data()), - frame_str.size(), - shared)) - { - log::error(link_cat, "HMAC failed on path build request"); - m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true); - return; + // hash data and check against given hash + ShortHash digest; + if (!crypto->hmac( + digest.data(), + reinterpret_cast(frame.data()), + frame.size(), + shared)) + { + log::error(link_cat, "HMAC failed on path build request"); + m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true); + return; + } + if (!std::equal( + digest.begin(), digest.end(), reinterpret_cast(hash.data()))) + { + log::info(link_cat, "HMAC mismatch on path build request"); + m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true); + return; + } + + // decrypt frame with our hop info + if (!crypto->xchacha20( + reinterpret_cast(hop_payload.data()), + hop_payload.size(), + shared.data(), + outer_nonce.data())) + { + log::info(link_cat, "Decrypt failed on path build request"); + m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true); + return; + } + + oxenc::bt_dict_consumer hop_info{hop_payload}; + commkey = hop_info.require("COMMKEY"); + lifetime = hop_info.require("LIFETIME"); + inner_nonce = hop_info.require("NONCE"); + rx_id = hop_info.require("RX"); + tx_id = hop_info.require("TX"); + upstream = hop_info.require("UPSTREAM"); } - if (!std::equal( - digest.begin(), digest.end(), reinterpret_cast(hash.data()))) + catch (...) { - log::info("HMAC mismatch on path build request"); - m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true); - return; + log::warning(link_cat, "Error: failed to deserialize path build message"); + throw; } - // decrypt frame with our hop info - if (!crypto->xchacha20( - reinterpret_cast(hop_info.data()), hop_info.size(), shared, nonce)) + if (frame.empty()) { - log::info("decrypt failed on path build request"); - m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true); + log::info(link_cat, "Path build request received invalid frame"); + m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_FRAMES}}), true); return; } @@ -1189,18 +1207,20 @@ namespace llarp // TODO: also need downstream for IP / path build limiting clients auto hop = std::make_shared(); // hop->info.downstream = m.from(); // TODO: RouterID m.from() or similar - auto hop_dict = oxenc::bt_dict_consumer{hop_info}; // extract pathIDs and check if zero or used - hop->info.txID.from_string_view(hop_dict.require("txid")); - hop->info.rxID.from_string_view(hop_dict.require("rxid")); - if (info.txID.IsZero() || info.rxID.IsZero()) + auto& hop_info = hop->info; + hop_info.txID.from_string_view(tx_id); + hop_info.rxID.from_string_view(rx_id); + + if (hop_info.txID.IsZero() || hop_info.rxID.IsZero()) { - log::info("Invalid PathID; PathIDs must be non-zero."); + log::warning(link_cat, "Invalid PathID; PathIDs must be non-zero"); m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_PATHID}}), true); return; } - hop->info.upstream.from_string_view(hop_dict.require("next"); + + hop_info.upstream.from_string_view(upstream); // TODO: need downstream (above), and also the whole transit hop container is garbage. // namely the PathID uniqueness checking uses the PathIDs and upstream/downstream @@ -1208,19 +1228,17 @@ namespace llarp // a different upstream, that would be "unique" but we wouldn't know where // to route messages (nevermind that messages don't currently know the RouterID // they came from). - if (_router.path_context.HasTransitHop(hop->info)) + if (_router.path_context().HasTransitHop(hop_info)) { - log::info("Invalid PathID; PathIDs must be unique."); + log::warning(link_cat, "Invalid PathID; PathIDs must be unique"); m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_PATHID}}), true); return; } - otherPubkey.from_string_view(hop_dict.require("commkey")); - nonce.from_string_view(hop_dict.require("nonce")); - - if (!crypto->dh_server(hop->pathKey, otherPubkey, _router.identity(), nonce)) + if (!crypto->dh_server( + hop->pathKey.data(), other_pubkey.data(), _router.pubkey(), inner_nonce.data())) { - log::info("DH failed during path build."); + log::warning(link_cat, "DH failed during path build."); m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_CRYPTO}}), true); return; } @@ -1228,51 +1246,50 @@ namespace llarp crypto->shorthash(hop->nonceXOR, hop->pathKey.data(), hop->pathKey.size()); // set and check path lifetime - hop->lifetime = 1ms * hop_dict.require("lifetime"); + hop->lifetime = 1ms * lifetime; + if (hop->lifetime >= path::DEFAULT_LIFETIME) { - log::info("path build attempt with too long of a lifetime."); + log::warning(link_cat, "Path build attempt with too long of a lifetime."); m.respond(serialize_response({{"STATUS", PathBuildMessage::BAD_LIFETIME}}), true); return; } + hop->started = _router.now(); - _router.persist_connection_until(hop->info.downstream, hop->ExpireTime() + 10s); + _router.persist_connection_until(hop_info.downstream, hop->ExpireTime() + 10s); - if (hop->info.upstream == _router.pubkey()) + if (hop_info.upstream == _router.pubkey()) { // we are terminal hop and everything is okay - _router.path_context.PutTransitHop(hop); + _router.path_context().PutTransitHop(hop); m.respond(serialize_response({{"STATUS", PathBuildMessage::OK}}), false); return; } - else - { - // rotate our frame to the end of the list and forward upstream - frame_list.splice(frame_list.end(), frame_list, frame_list.begin()); + // rotate our frame to the end of the list and forward upstream - send_control_message( - hop->info.upstream, - "path_build", - bt_serialize(frame_list), - [hop, this, prev_message = std::move(m)](oxen::quic::message response) { - if (response) - { - log::info( - link_cat, - "Upstream returned successful path build response; giving hop info to Router, " - "then relaying response"); - _router.path_context.PutTransitHop(hop); - m.respond(response.body_str(), false); - return; - } - else if (response.timed_out) - log::info(link_cat, "Upstream timed out on path build; relaying timeout"); - else - log::info(link_cat, "Upstream returned path build failure; relaying response"); - - m.respond(response.body_str(), true); - }); - } + auto payload_list = oxenc::bt_deserialize(payload); + payload_list.splice(payload_list.end(), payload_list, payload_list.begin()); + + send_control_message( + hop->info.upstream, + "path_build", + bt_serialize(payload_list), + [hop, this, prev_message = std::move(m)](oxen::quic::message m) { + if (m) + { + log::info( + link_cat, + "Upstream returned successful path build response; giving hop info to Router, " + "then relaying response"); + _router.path_context().PutTransitHop(hop); + } + if (m.timed_out) + log::info(link_cat, "Upstream timed out on path build; relaying timeout"); + else + log::info(link_cat, "Upstream returned path build failure; relaying response"); + + m.respond(m.body_str(), not m); + }); } catch (const std::exception& e) { @@ -1410,15 +1427,12 @@ namespace llarp _router.path_context().GetByUpstream(target, PathID_t{to_usv(tx_id).data()})); const auto rx_id = transit_hop->info.rxID; - const auto next_seqno = transit_hop->NextSeqNo(); auto success = (CryptoManager::instance()->verify(pubkey, to_usv(dict_data), sig) and _router.exitContext().ObtainNewExit(PubKey{pubkey.data()}, rx_id, flag != 0)); - m.respond( - ObtainExit::sign_and_serialize_response(_router.identity(), next_seqno, tx_id), - not success); + m.respond(ObtainExit::sign_and_serialize_response(_router.identity(), tx_id), not success); } catch (const std::exception& e) { @@ -1485,16 +1499,13 @@ namespace llarp auto transit_hop = std::static_pointer_cast( _router.path_context().GetByUpstream(_router.pubkey(), PathID_t{to_usv(tx_id).data()})); - const auto next_seqno = transit_hop->NextSeqNo(); - if (auto exit_ep = _router.exitContext().FindEndpointForPath(PathID_t{to_usv(path_id).data()})) { if (CryptoManager::instance()->verify(exit_ep->PubKey().data(), to_usv(dict_data), sig)) { (exit_ep->UpdateLocalPath(transit_hop->info.rxID)) - ? m.respond( - UpdateExit::sign_and_serialize_response(_router.identity(), next_seqno, tx_id)) + ? m.respond(UpdateExit::sign_and_serialize_response(_router.identity(), tx_id)) : m.respond(serialize_response({{"STATUS", UpdateExit::UPDATE_FAILED}}), true); } // If we fail to verify the message, no-op @@ -1573,14 +1584,13 @@ namespace llarp _router.path_context().GetByUpstream(_router.pubkey(), PathID_t{to_usv(tx_id).data()})); const auto rx_id = transit_hop->info.rxID; - const auto next_seqno = transit_hop->NextSeqNo(); - if (auto exit_ep = router.exitContext().FindEndpointForPath(rx_id)) + if (auto exit_ep = router().exitContext().FindEndpointForPath(rx_id)) { if (CryptoManager::instance()->verify(exit_ep->PubKey().data(), to_usv(dict_data), sig)) { exit_ep->Close(); - m.respond(CloseExit::sign_and_serialize_response(_router.identity(), next_seqno, tx_id)); + m.respond(CloseExit::sign_and_serialize_response(_router.identity(), tx_id)); } } diff --git a/llarp/messages/exit.hpp b/llarp/messages/exit.hpp index e377c2a989..da6226acec 100644 --- a/llarp/messages/exit.hpp +++ b/llarp/messages/exit.hpp @@ -16,8 +16,7 @@ namespace llarp // flag: 0 = Exit, 1 = Snode inline std::string - sign_and_serialize( - SecretKey sk, uint64_t flag, std::string pubkey, uint64_t seq_no, std::string tx_id) + sign_and_serialize(SecretKey sk, uint64_t flag, std::string pubkey, std::string tx_id) { oxenc::bt_list_producer btlp; std::string sig(64, '\0'); @@ -27,7 +26,6 @@ namespace llarp btdp.append("E", flag); btdp.append("I", pubkey); - btdp.append("S", seq_no); btdp.append("T", tx_id); if (not CryptoManager::instance()->sign( @@ -41,7 +39,7 @@ namespace llarp } inline std::string - sign_and_serialize_response(SecretKey sk, uint64_t seq_no, std::string_view tx_id) + sign_and_serialize_response(SecretKey sk, std::string_view tx_id) { oxenc::bt_list_producer btlp; std::string sig(64, '\0'); @@ -51,7 +49,6 @@ namespace llarp { oxenc::bt_dict_producer btdp; - btdp.append("S", seq_no); btdp.append("T", tx_id); btdp.append("Y", nonce); @@ -73,7 +70,7 @@ namespace llarp inline auto UPDATE_FAILED = "EXIT UPDATE FAILED"sv; inline std::string - sign_and_serialize(SecretKey sk, std::string path_id, std::string seq_no, std::string tx_id) + sign_and_serialize(SecretKey sk, std::string path_id, std::string tx_id) { oxenc::bt_list_producer btlp; std::string sig(64, '\0'); @@ -82,7 +79,6 @@ namespace llarp auto btdp = btlp.append_dict(); btdp.append("P", path_id); - btdp.append("S", seq_no); btdp.append("T", tx_id); if (not CryptoManager::instance()->sign( @@ -96,7 +92,7 @@ namespace llarp } inline std::string - sign_and_serialize_response(SecretKey sk, uint64_t seq_no, std::string_view tx_id) + sign_and_serialize_response(SecretKey sk, std::string_view tx_id) { oxenc::bt_list_producer btlp; std::string sig(64, '\0'); @@ -106,7 +102,6 @@ namespace llarp { oxenc::bt_dict_producer btdp; - btdp.append("S", seq_no); btdp.append("T", tx_id); btdp.append("Y", nonce); @@ -127,7 +122,7 @@ namespace llarp inline auto UPDATE_FAILED = "CLOSE EXIT FAILED"sv; inline std::string - sign_and_serialize(SecretKey sk, std::string seq_no, std::string tx_id) + sign_and_serialize(SecretKey sk, std::string tx_id) { oxenc::bt_list_producer btlp; std::string sig(64, '\0'); @@ -137,7 +132,6 @@ namespace llarp { auto btdp = btlp.append_dict(); - btdp.append("S", seq_no); btdp.append("T", tx_id); btdp.append("Y", nonce); @@ -152,7 +146,7 @@ namespace llarp } inline std::string - sign_and_serialize_response(SecretKey sk, uint64_t seq_no, std::string_view tx_id) + sign_and_serialize_response(SecretKey sk, std::string_view tx_id) { oxenc::bt_list_producer btlp; std::string sig(64, '\0'); @@ -162,7 +156,6 @@ namespace llarp { oxenc::bt_dict_producer btdp; - btdp.append("S", seq_no); btdp.append("T", tx_id); btdp.append("Y", nonce); diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index 0fb176f810..f2e60c424b 100644 --- a/llarp/messages/path.hpp +++ b/llarp/messages/path.hpp @@ -27,7 +27,7 @@ namespace llarp 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::error(path_cat, err); + log::warning(path_cat, err); throw std::runtime_error{std::move(err)}; } // generate nonceXOR value self->hop->pathKey @@ -46,12 +46,12 @@ namespace llarp { oxenc::bt_dict_producer btdp; - btdp.append("lifetime", path::DEFAULT_LIFETIME.count()); - btdp.append("txid", hop.txID.ToView()); - btdp.append("rxid", hop.rxID.ToView()); - btdp.append("nonce", hop.nonce.ToView()); - btdp.append("next", hop.upstream.ToView()); - btdp.append("commkey", hop.commkey.toPublic().ToView()); + btdp.append("COMMKEY", hop.commkey.toPublic().ToView()); + btdp.append("LIFETIME", path::DEFAULT_LIFETIME.count()); + btdp.append("NONCE", hop.nonce.ToView()); + btdp.append("RX", hop.rxID.ToView()); + btdp.append("TX", hop.txID.ToView()); + btdp.append("UPSTREAM", hop.upstream.ToView()); hop_info = std::move(btdp).str(); } @@ -66,7 +66,7 @@ namespace llarp // derive (outer) shared key if (!crypto->dh_client(shared, hop.rc.pubkey, framekey, outer_nonce)) { - log::error(path_cat, "DH client failed during hop info encryption!"); + log::warning(path_cat, "DH client failed during hop info encryption!"); throw std::runtime_error{"DH failed during hop info encryption"}; } @@ -77,8 +77,8 @@ namespace llarp shared, outer_nonce)) { - log::error(path_cat, "Hop info encryption failed!"); - throw std::runtime_error{"Hop info encrypttion failed"}; + log::warning(path_cat, "Hop info encryption failed!"); + throw std::runtime_error{"Hop info encryption failed"}; } std::string hashed_data; @@ -86,9 +86,9 @@ namespace llarp { oxenc::bt_dict_producer btdp; - btdp.append("encrypted", hop_info); - btdp.append("pubkey", framekey.toPublic().ToView()); - btdp.append("nonce", outer_nonce.ToView()); + btdp.append("ENCRYPTED", hop_info); + btdp.append("NONCE", outer_nonce.ToView()); + btdp.append("PUBKEY", framekey.toPublic().ToView()); hashed_data = std::move(btdp).str(); } @@ -102,14 +102,14 @@ namespace llarp hashed_data.size(), shared)) { - log::error(path_cat, "Failed to generate HMAC for hop info"); + log::warning(path_cat, "Failed to generate HMAC for hop info"); throw std::runtime_error{"Failed to generate HMAC for hop info"}; } oxenc::bt_dict_producer btdp; - btdp.append("hash", hash); - btdp.append("frame", hashed_data); + btdp.append("HASH", hash); + btdp.append("FRAME", hashed_data); return std::move(btdp).str(); } diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index a48505bba2..9554b7fc83 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -478,6 +478,7 @@ namespace llarp path->EnterState(path::ePathFailed, router->now()); } + // TODO: we don't use this concept anymore? router->persist_connection_until(path->upstream(), path->ExpireTime()); } From e4315cdc691604b75875f6b8719b003d19428c23 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Mon, 16 Oct 2023 09:55:51 -0700 Subject: [PATCH 054/312] More message handling underway --- llarp/exit/exit_messages.hpp | 1 - llarp/exit/session.cpp | 34 +- llarp/exit/session.hpp | 2 - llarp/handlers/tun.cpp | 8 +- llarp/handlers/tun.hpp | 6 - llarp/link/link_manager.cpp | 21 +- llarp/messages/exit.hpp | 15 +- llarp/path/abstracthophandler.hpp | 5 +- llarp/path/path.cpp | 496 +----- llarp/path/path.hpp | 264 +-- llarp/path/pathbuilder.cpp | 23 +- llarp/path/pathbuilder.hpp | 1 - llarp/path/pathset.cpp | 3 - llarp/path/pathset.hpp | 8 +- llarp/path/transit_hop.cpp | 213 +-- llarp/path/transit_hop.hpp | 59 +- llarp/service/endpoint.cpp | 2757 ++++++++++++++--------------- llarp/service/endpoint.hpp | 28 +- llarp/service/endpoint_util.hpp | 4 +- llarp/service/protocol.hpp | 2 - llarp/service/sendcontext.cpp | 4 +- llarp/service/sendcontext.hpp | 7 +- 22 files changed, 1578 insertions(+), 2383 deletions(-) diff --git a/llarp/exit/exit_messages.hpp b/llarp/exit/exit_messages.hpp index 874e1390e4..5a50702329 100644 --- a/llarp/exit/exit_messages.hpp +++ b/llarp/exit/exit_messages.hpp @@ -2,7 +2,6 @@ #include #include "policy.hpp" -#include #include diff --git a/llarp/exit/session.cpp b/llarp/exit/session.cpp index c1b9bbcc93..b9b5a498fd 100644 --- a/llarp/exit/session.cpp +++ b/llarp/exit/session.cpp @@ -94,24 +94,16 @@ namespace llarp::exit BaseSession::HandlePathBuilt(llarp::path::Path_ptr p) { path::Builder::HandlePathBuilt(p); - p->SetDropHandler(util::memFn(&BaseSession::HandleTrafficDrop, this)); - p->SetDeadChecker(util::memFn(&BaseSession::CheckPathDead, this)); - p->SetExitTrafficHandler(util::memFn(&BaseSession::HandleTraffic, this)); - p->AddObtainExitHandler(util::memFn(&BaseSession::HandleGotExit, this)); - - routing::ObtainExitMessage obtain; - obtain.sequence_number = p->NextSeqNo(); - obtain.tx_id = llarp::randint(); - PopulateRequest(obtain); - if (!obtain.Sign(exit_key)) - { - llarp::LogError("Failed to sign exit request"); - return; - } - if (p->SendExitRequest(obtain, router)) - llarp::LogInfo("asking ", exit_router, " for exit"); + // p->SetDropHandler(util::memFn(&BaseSession::HandleTrafficDrop, this)); + // p->SetDeadChecker(util::memFn(&BaseSession::CheckPathDead, this)); + // p->SetExitTrafficHandler(util::memFn(&BaseSession::HandleTraffic, this)); + // p->AddObtainExitHandler(util::memFn(&BaseSession::HandleGotExit, this)); + + if (p->obtain_exit( + exit_key, std::is_same_v ? 1 : 0, p->TXID().bt_encode())) + log::info(link_cat, "Asking {} for exit", exit_router); else - llarp::LogError("failed to send exit request"); + log::warning(link_cat, "Failed to send exit request"); } void @@ -159,16 +151,14 @@ namespace llarp::exit const static auto roles = llarp::path::ePathRoleExit | llarp::path::ePathRoleSVC; if (p->SupportsAnyRoles(roles)) { - llarp::LogInfo(p->name(), " closing exit path"); - routing::CloseExitMessage msg; - if (msg.Sign(exit_key) && p->SendExitClose(msg, router)) - { + log::info(link_cat, "{} closing exit path", p->name()); + if (p->close_exit(exit_key, p->TXID().bt_encode())) p->ClearRoles(roles); - } else llarp::LogWarn(p->name(), " failed to send exit close message"); } }; + ForEachPath(sendExitClose); path::Builder::ResetInternalState(); } diff --git a/llarp/exit/session.hpp b/llarp/exit/session.hpp index 9be71f216c..c55b63185a 100644 --- a/llarp/exit/session.hpp +++ b/llarp/exit/session.hpp @@ -1,10 +1,8 @@ #pragma once -#include "exit_messages.hpp" #include #include #include -#include #include #include diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 701a09c0ba..ad4f902319 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -113,9 +113,9 @@ namespace llarp::handlers class TunDNS : public dns::Server { + TunEndpoint* const m_Endpoint; std::optional m_QueryBind; net::ipaddr_t m_OurIP; - TunEndpoint* const m_Endpoint; public: std::shared_ptr PacketSource; @@ -124,9 +124,9 @@ namespace llarp::handlers explicit TunDNS(TunEndpoint* ep, const llarp::DnsConfig& conf) : dns::Server{ep->router()->loop(), conf, 0} + , m_Endpoint{ep} , m_QueryBind{conf.m_QueryBind} , m_OurIP{ToNet(ep->GetIfAddr())} - , m_Endpoint{ep} {} std::shared_ptr @@ -278,12 +278,12 @@ namespace llarp::handlers if (conf.m_reachable) { _publish_introset = true; - LogInfo(Name(), " setting to be reachable by default"); + log::info(link_cat, "TunEndpoint setting to be reachable by default"); } else { _publish_introset = false; - LogInfo(Name(), " setting to be not reachable by default"); + log::info(link_cat, "TunEndpoint setting to be not reachable by default"); } if (conf.m_AuthType == service::AuthType::eAuthTypeFile) diff --git a/llarp/handlers/tun.hpp b/llarp/handlers/tun.hpp index 694b3d36d1..3513735678 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -213,12 +213,6 @@ namespace llarp::handlers } }; - /// queue for sending packets to user from network - util::ascending_priority_queue m_NetworkToUserPktQueue; - - void - Pump(llarp_time_t now) override; - /// return true if we have a remote loki address for this ip address bool HasRemoteForIP(huint128_t ipv4) const; diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index b0de207910..d906c71dc3 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1265,8 +1265,8 @@ namespace llarp m.respond(serialize_response({{"STATUS", PathBuildMessage::OK}}), false); return; } - // rotate our frame to the end of the list and forward upstream + // rotate our frame to the end of the list and forward upstream auto payload_list = oxenc::bt_deserialize(payload); payload_list.splice(payload_list.end(), payload_list, payload_list.begin()); @@ -1432,12 +1432,13 @@ namespace llarp (CryptoManager::instance()->verify(pubkey, to_usv(dict_data), sig) and _router.exitContext().ObtainNewExit(PubKey{pubkey.data()}, rx_id, flag != 0)); - m.respond(ObtainExit::sign_and_serialize_response(_router.identity(), tx_id), not success); + m.respond( + ObtainExitMessage::sign_and_serialize_response(_router.identity(), tx_id), not success); } catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response({{"STATUS", ObtainExit::EXCEPTION}}), true); + m.respond(serialize_response({{"STATUS", ObtainExitMessage::EXCEPTION}}), true); throw; } } @@ -1505,8 +1506,8 @@ namespace llarp if (CryptoManager::instance()->verify(exit_ep->PubKey().data(), to_usv(dict_data), sig)) { (exit_ep->UpdateLocalPath(transit_hop->info.rxID)) - ? m.respond(UpdateExit::sign_and_serialize_response(_router.identity(), tx_id)) - : m.respond(serialize_response({{"STATUS", UpdateExit::UPDATE_FAILED}}), true); + ? m.respond(UpdateExitMessage::sign_and_serialize_response(_router.identity(), tx_id)) + : m.respond(serialize_response({{"STATUS", UpdateExitMessage::UPDATE_FAILED}}), true); } // If we fail to verify the message, no-op } @@ -1514,7 +1515,7 @@ namespace llarp catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response({{"STATUS", UpdateExit::EXCEPTION}}), true); + m.respond(serialize_response({{"STATUS", UpdateExitMessage::EXCEPTION}}), true); return; } } @@ -1590,16 +1591,16 @@ namespace llarp if (CryptoManager::instance()->verify(exit_ep->PubKey().data(), to_usv(dict_data), sig)) { exit_ep->Close(); - m.respond(CloseExit::sign_and_serialize_response(_router.identity(), tx_id)); + m.respond(CloseExitMessage::sign_and_serialize_response(_router.identity(), tx_id)); } } - m.respond(serialize_response({{"STATUS", CloseExit::UPDATE_FAILED}}), true); + m.respond(serialize_response({{"STATUS", CloseExitMessage::UPDATE_FAILED}}), true); } catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); - m.respond(serialize_response({{"STATUS", CloseExit::EXCEPTION}}), true); + m.respond(serialize_response({{"STATUS", CloseExitMessage::EXCEPTION}}), true); return; } } @@ -1635,7 +1636,7 @@ namespace llarp if (path_ptr->SupportsAnyRoles(path::ePathRoleExit | path::ePathRoleSVC) and CryptoManager::instance()->verify(_router.pubkey(), to_usv(dict_data), sig)) - path_ptr->close_exit(); + path_ptr->mark_exit_closed(); } catch (const std::exception& e) { diff --git a/llarp/messages/exit.hpp b/llarp/messages/exit.hpp index da6226acec..e5a77b17f0 100644 --- a/llarp/messages/exit.hpp +++ b/llarp/messages/exit.hpp @@ -10,13 +10,13 @@ namespace llarp - nuke seq_no's */ - namespace ObtainExit + namespace ObtainExitMessage { inline auto EXCEPTION = "EXCEPTION"sv; // flag: 0 = Exit, 1 = Snode inline std::string - sign_and_serialize(SecretKey sk, uint64_t flag, std::string pubkey, std::string tx_id) + sign_and_serialize(SecretKey sk, uint64_t flag, std::string tx_id) { oxenc::bt_list_producer btlp; std::string sig(64, '\0'); @@ -25,7 +25,6 @@ namespace llarp auto btdp = btlp.append_dict(); btdp.append("E", flag); - btdp.append("I", pubkey); btdp.append("T", tx_id); if (not CryptoManager::instance()->sign( @@ -62,9 +61,9 @@ namespace llarp return std::move(btlp).str(); } - } // namespace ObtainExit + } // namespace ObtainExitMessage - namespace UpdateExit + namespace UpdateExitMessage { inline auto EXCEPTION = "EXCEPTION"sv; inline auto UPDATE_FAILED = "EXIT UPDATE FAILED"sv; @@ -114,9 +113,9 @@ namespace llarp btlp.append(sig.data()); return std::move(btlp).str(); } - } // namespace UpdateExit + } // namespace UpdateExitMessage - namespace CloseExit + namespace CloseExitMessage { inline auto EXCEPTION = "EXCEPTION"sv; inline auto UPDATE_FAILED = "CLOSE EXIT FAILED"sv; @@ -168,6 +167,6 @@ namespace llarp btlp.append(sig.data()); return std::move(btlp).str(); } - } // namespace CloseExit + } // namespace CloseExitMessage } // namespace llarp diff --git a/llarp/path/abstracthophandler.hpp b/llarp/path/abstracthophandler.hpp index 5a33f169f1..468b9acd03 100644 --- a/llarp/path/abstracthophandler.hpp +++ b/llarp/path/abstracthophandler.hpp @@ -41,7 +41,7 @@ namespace llarp virtual bool ExpiresSoon(llarp_time_t now, llarp_time_t dlt) const = 0; - virtual void + virtual bool send_path_control_message( std::string method, std::string body, @@ -62,9 +62,6 @@ namespace llarp virtual llarp_time_t LastRemoteActivityAt() const = 0; - virtual bool - HandleLRSM(uint64_t status, std::array& frames, Router* r) = 0; - uint64_t NextSeqNo() { diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index bcae1c4ce3..169b9e36a9 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -1,19 +1,15 @@ #include "path.hpp" +#include "pathbuilder.hpp" +#include "transit_hop.hpp" #include #include #include #include -#include -#include -#include "pathbuilder.hpp" -#include "transit_hop.hpp" +#include #include #include #include -#include -#include -#include #include #include @@ -62,42 +58,57 @@ namespace llarp::path EnterState(ePathBuilding, parent->Now()); } - void + bool + Path::obtain_exit( + SecretKey sk, + uint64_t flag, + std::string tx_id, + std::function func) + { + return send_path_control_message( + "obtain_exit", + ObtainExitMessage::sign_and_serialize(sk, flag, std::move(tx_id)), + std::move(func)); + } + + bool + Path::close_exit(SecretKey sk, std::string tx_id, std::function func) + { + return send_path_control_message( + "close_exit", CloseExitMessage::sign_and_serialize(sk, std::move(tx_id)), std::move(func)); + } + + bool Path::find_intro( const dht::Key_t& location, bool is_relayed, uint64_t order, std::function func) { - send_path_control_message( + return send_path_control_message( "find_intro", FindIntroMessage::serialize(location, is_relayed, order), std::move(func)); } - void + bool Path::find_name(std::string name, std::function func) { - send_path_control_message( + return send_path_control_message( "find_name", FindNameMessage::serialize(std::move(name)), std::move(func)); } - void + bool Path::find_router(std::string rid, std::function func) { - send_path_control_message( + return send_path_control_message( "find_router", FindRouterMessage::serialize(std::move(rid), false, false), std::move(func)); } - void + bool Path::send_path_control_message( std::string method, std::string body, std::function func) { - router.send_control_message(upstream(), std::move(method), std::move(body), std::move(func)); - } - - void - Path::SetBuildResultHook(BuildResultHookFunc func) - { - m_BuiltHook = func; + return router.send_control_message( + upstream(), std::move(method), std::move(body), std::move(func)); } bool @@ -180,145 +191,6 @@ namespace llarp::path return hops_str; } - bool - Path::HandleLRSM(uint64_t status, std::array& frames, Router* r) - { - uint64_t currentStatus = status; - - size_t index = 0; - std::optional failedAt; - while (index < hops.size()) - { - if (!frames[index].DoDecrypt(hops[index].shared)) - { - currentStatus = LR_StatusRecord::FAIL_DECRYPT_ERROR; - failedAt = hops[index].rc.pubkey; - break; - } - llarp::LogDebug("decrypted LRSM frame from ", hops[index].rc.pubkey); - - llarp_buffer_t* buf = frames[index].Buffer(); - buf->cur = buf->base + EncryptedFrameOverheadSize; - - LR_StatusRecord record; - // successful decrypt - if (!record.BDecode(buf)) - { - llarp::LogWarn("malformed frame inside LRCM from ", hops[index].rc.pubkey); - currentStatus = LR_StatusRecord::FAIL_MALFORMED_RECORD; - failedAt = hops[index].rc.pubkey; - break; - } - llarp::LogDebug("Decoded LR Status Record from ", hops[index].rc.pubkey); - - currentStatus = record.status; - if ((record.status & LR_StatusRecord::SUCCESS) != LR_StatusRecord::SUCCESS) - { - if (record.status & LR_StatusRecord::FAIL_CONGESTION and index == 0) - { - // first hop building too fast - failedAt = hops[index].rc.pubkey; - break; - } - // failed at next hop - if (index + 1 < hops.size()) - { - failedAt = hops[index + 1].rc.pubkey; - } - break; - } - ++index; - } - - if ((currentStatus & LR_StatusRecord::SUCCESS) == LR_StatusRecord::SUCCESS) - { - llarp::LogDebug("LR_Status message processed, path build successful"); - r->loop()->call([r, self = shared_from_this()] { self->HandlePathConfirmMessage(r); }); - } - else - { - if (failedAt) - { - r->notify_router_event(Endpoint(), RXID(), *failedAt); - LogWarn( - name(), - " build failed at ", - *failedAt, - " status=", - LRStatusCodeToString(currentStatus), - " hops=", - HopsString()); - r->router_profiling().MarkHopFail(*failedAt); - } - else - r->router_profiling().MarkPathFail(this); - llarp::LogDebug("LR_Status message processed, path build failed"); - - if (currentStatus & LR_StatusRecord::FAIL_TIMEOUT) - { - llarp::LogDebug("Path build failed due to timeout"); - } - else if (currentStatus & LR_StatusRecord::FAIL_CONGESTION) - { - llarp::LogDebug("Path build failed due to congestion"); - } - else if (currentStatus & LR_StatusRecord::FAIL_DEST_UNKNOWN) - { - llarp::LogDebug( - "Path build failed due to one or more nodes giving destination " - "unknown"); - } - else if (currentStatus & LR_StatusRecord::FAIL_DEST_INVALID) - { - llarp::LogDebug( - "Path build failed due to one or more nodes considered an " - "invalid destination"); - if (failedAt) - { - r->loop()->call([nodedb = r->node_db(), router = *failedAt]() { - LogInfo("router ", router, " is deregistered so we remove it"); - nodedb->remove_router(router); - }); - } - } - else if (currentStatus & LR_StatusRecord::FAIL_CANNOT_CONNECT) - { - llarp::LogDebug( - "Path build failed due to a node being unable to connect to the " - "next hop"); - } - else if (currentStatus & LR_StatusRecord::FAIL_MALFORMED_RECORD) - { - llarp::LogDebug( - "Path build failed due to a malformed record in the build status " - "message"); - } - else if (currentStatus & LR_StatusRecord::FAIL_DECRYPT_ERROR) - { - llarp::LogDebug( - "Path build failed due to a decrypt error in the build status " - "message"); - } - else - { - llarp::LogDebug("Path build failed for an unspecified reason"); - } - RouterID edge{}; - if (failedAt) - edge = *failedAt; - r->loop()->call([r, self = shared_from_this(), edge]() { - self->EnterState(ePathFailed, r->now()); - if (auto parent = self->m_PathSet.lock()) - { - parent->HandlePathBuildFailedAt(self, edge); - } - }); - } - - // TODO: meaningful return value? - return true; - } // namespace path - void Path::EnterState(PathStatus st, llarp_time_t now) { @@ -445,35 +317,26 @@ namespace llarp::path } bool - Path::SendLatencyMessage(Router* r) - { - const auto now = r->now(); - // send path latency test - routing::PathLatencyMessage latency{}; - latency.sent_time = randint(); - latency.sequence_number = NextSeqNo(); - m_LastLatencyTestID = latency.sent_time; - m_LastLatencyTestTime = now; - LogDebug(name(), " send latency test id=", latency.sent_time); - if (not SendRoutingMessage(latency, r)) - return false; - FlushUpstream(r); + Path::SendLatencyMessage(Router*) + { + // const auto now = r->now(); + // // send path latency test + // routing::PathLatencyMessage latency{}; + // latency.sent_time = randint(); + // latency.sequence_number = NextSeqNo(); + // m_LastLatencyTestID = latency.sent_time; + // m_LastLatencyTestTime = now; + // LogDebug(name(), " send latency test id=", latency.sent_time); + // if (not SendRoutingMessage(latency, r)) + // return false; + // FlushUpstream(r); return true; } bool - Path::update_exit(uint64_t tx_id) + Path::update_exit(uint64_t) { - if (m_UpdateExitTX && tx_id == m_UpdateExitTX) - { - if (m_ExitUpdated) - return m_ExitUpdated(shared_from_this()); - } - if (m_CloseExitTX && tx_id == m_CloseExitTX) - { - if (m_ExitClosed) - return m_ExitClosed(shared_from_this()); - } + // TODO: do we still want this concept? return false; } @@ -661,40 +524,12 @@ namespace llarp::path { const llarp_buffer_t buf{msg.enc}; m_RXRate += buf.sz; - if (HandleRoutingMessage(buf, r)) - { - r->TriggerPump(); - m_LastRecvMessage = r->now(); - } - } - } - - bool - Path::HandleRoutingMessage(const llarp_buffer_t& buf, Router* r) - { - if (!r->ParseRoutingMessageBuffer(buf, this, RXID())) - { - LogWarn("Failed to parse inbound routing message"); - return false; + // if (HandleRoutingMessage(buf, r)) + // { + // r->TriggerPump(); + // m_LastRecvMessage = r->now(); + // } } - return true; - } - - bool - Path::HandleUpdateExitVerifyMessage(const routing::UpdateExitVerifyMessage& msg, Router* r) - { - (void)r; - if (m_UpdateExitTX && msg.tx_id == m_UpdateExitTX) - { - if (m_ExitUpdated) - return m_ExitUpdated(shared_from_this()); - } - if (m_CloseExitTX && msg.tx_id == m_CloseExitTX) - { - if (m_ExitClosed) - return m_ExitClosed(shared_from_this()); - } - return false; } /** Note: this is one of two places where AbstractRoutingMessage::bt_encode() is called, the @@ -717,10 +552,6 @@ namespace llarp::path { std::array tmp; llarp_buffer_t buf(tmp); - // should help prevent bad paths with uninitialized members - // FIXME: Why would we get uninitialized IMessages? - if (msg.version != llarp::constants::proto_version) - return false; auto bte = msg.bt_encode(); buf.write(bte.begin(), bte.end()); @@ -747,60 +578,6 @@ namespace llarp::path return HandleUpstream(buf, N, r); } - bool - Path::HandlePathTransferMessage(const routing::PathTransferMessage& /*msg*/, Router* /*r*/) - { - LogWarn("unwarranted path transfer message on tx=", TXID(), " rx=", RXID()); - return false; - } - - bool - Path::HandleDataDiscardMessage(const routing::DataDiscardMessage& msg, Router* r) - { - MarkActive(r->now()); - if (m_DropHandler) - return m_DropHandler(shared_from_this(), msg.path_id, msg.sequence_number); - return true; - } - - bool - Path::HandlePathConfirmMessage(Router* r) - { - LogDebug("Path Build Confirm, path: ", ShortName()); - const auto now = llarp::time_now_ms(); - if (_status == ePathBuilding) - { - // finish initializing introduction - intro.expiry = buildStarted + hops[0].lifetime; - - r->router_profiling().MarkPathSuccess(this); - - // persist session with upstream router until the path is done - r->persist_connection_until(upstream(), intro.expiry); - MarkActive(now); - return SendLatencyMessage(r); - } - LogWarn("got unwarranted path confirm message on tx=", RXID(), " rx=", RXID()); - return false; - } - - bool - Path::HandlePathConfirmMessage(const routing::PathConfirmMessage& /*msg*/, Router* r) - { - return HandlePathConfirmMessage(r); - } - - bool - Path::HandleHiddenServiceFrame(const service::ProtocolFrameMessage& frame) - { - if (auto parent = m_PathSet.lock()) - { - MarkActive(parent->Now()); - return m_DataHandler && m_DataHandler(shared_from_this(), frame); - } - return false; - } - template static llarp_time_t computeLatency(const Samples_t& samps) @@ -812,173 +589,4 @@ namespace llarp::path mean += samp; return mean / samps.size(); } - - constexpr auto MaxLatencySamples = 8; - - bool - Path::HandlePathLatencyMessage(const routing::PathLatencyMessage&, Router* r) - { - const auto now = r->now(); - MarkActive(now); - if (m_LastLatencyTestID) - { - m_LatencySamples.emplace_back(now - m_LastLatencyTestTime); - - while (m_LatencySamples.size() > MaxLatencySamples) - m_LatencySamples.pop_front(); - - intro.latency = computeLatency(m_LatencySamples); - m_LastLatencyTestID = 0; - EnterState(ePathEstablished, now); - if (m_BuiltHook) - m_BuiltHook(shared_from_this()); - m_BuiltHook = nullptr; - } - return true; - } - - /// this is the Client's side of handling a DHT message. it's handled - /// in-place. - bool - Path::HandleDHTMessage(const dht::AbstractDHTMessage& msg, Router* r) - { - MarkActive(r->now()); - routing::PathDHTMessage reply; - if (not r->dht()->handle_message(msg, reply.dht_msgs)) - return false; - if (reply.dht_msgs.size()) - return SendRoutingMessage(reply, r); - return true; - } - - bool - Path::HandleCloseExitMessage(const routing::CloseExitMessage& msg, Router* /*r*/) - { - /// allows exits to close from their end - if (SupportsAnyRoles(ePathRoleExit | ePathRoleSVC)) - { - if (msg.Verify(EndpointPubKey())) - { - LogInfo(name(), " had its exit closed"); - _role &= ~ePathRoleExit; - return true; - } - - LogError(name(), " CXM from exit with bad signature"); - } - else - LogError(name(), " unwarranted CXM"); - return false; - } - - bool - Path::SendExitRequest(const routing::ObtainExitMessage& msg, Router* r) - { - LogInfo(name(), " sending exit request to ", Endpoint()); - m_ExitObtainTX = msg.tx_id; - return SendRoutingMessage(msg, r); - } - - bool - Path::SendExitClose(const routing::CloseExitMessage& msg, Router* r) - { - LogInfo(name(), " closing exit to ", Endpoint()); - // mark as not exit anymore - _role &= ~ePathRoleExit; - return SendRoutingMessage(msg, r); - } - - bool - Path::HandleObtainExitMessage(const routing::ObtainExitMessage& msg, Router* r) - { - (void)msg; - (void)r; - LogError(name(), " got unwarranted OXM"); - return false; - } - - bool - Path::HandleUpdateExitMessage(const routing::UpdateExitMessage& msg, Router* r) - { - (void)msg; - (void)r; - LogError(name(), " got unwarranted UXM"); - return false; - } - - bool - Path::HandleRejectExitMessage(const routing::RejectExitMessage& msg, Router* r) - { - if (m_ExitObtainTX && msg.tx_id == m_ExitObtainTX) - { - if (!msg.Verify(EndpointPubKey())) - { - LogError(name(), "RXM invalid signature"); - return false; - } - LogInfo(name(), " ", Endpoint(), " Rejected exit"); - MarkActive(r->now()); - return InformExitResult(llarp_time_t(msg.backoff_time)); - } - LogError(name(), " got unwarranted RXM"); - return false; - } - - bool - Path::HandleGrantExitMessage(const routing::GrantExitMessage& msg, Router* r) - { - if (m_ExitObtainTX && msg.tx_id == m_ExitObtainTX) - { - if (!msg.Verify(EndpointPubKey())) - { - LogError(name(), " GXM signature failed"); - return false; - } - // we now can send exit traffic - _role |= ePathRoleExit; - LogInfo(name(), " ", Endpoint(), " Granted exit"); - MarkActive(r->now()); - return InformExitResult(0s); - } - LogError(name(), " got unwarranted GXM"); - return false; - } - - bool - Path::InformExitResult(llarp_time_t B) - { - auto self = shared_from_this(); - bool result = true; - for (const auto& hook : m_ObtainedExitHooks) - result = hook(self, B) and result; - m_ObtainedExitHooks.clear(); - return result; - } - - bool - Path::HandleTransferTrafficMessage(const routing::TransferTrafficMessage& msg, Router* r) - { - // check if we can handle exit data - if (!SupportsAnyRoles(ePathRoleExit | ePathRoleSVC)) - return false; - // handle traffic if we have a handler - if (!m_ExitTrafficHandler) - return false; - bool sent = msg.enc_buf.size() > 0; - auto self = shared_from_this(); - for (const auto& pkt : msg.enc_buf) - { - if (pkt.size() <= 8) - continue; - auto counter = oxenc::load_big_to_host(pkt.data()); - if (m_ExitTrafficHandler( - self, llarp_buffer_t(pkt.data() + 8, pkt.size() - 8), counter, msg.protocol)) - { - MarkActive(r->now()); - EnterState(ePathEstablished, r->now()); - } - } - return sent; - } - } // namespace llarp::path diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index ad90b70ca7..8be7ed0e76 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -1,16 +1,15 @@ #pragma once +#include "abstracthophandler.hpp" +#include "path_types.hpp" +#include "pathset.hpp" +// #include "pathbuilder.hpp" + #include #include #include #include -#include "abstracthophandler.hpp" -#include "path_types.hpp" -#include "pathbuilder.hpp" -#include "pathset.hpp" #include -#include -#include #include #include #include @@ -38,16 +37,22 @@ namespace llarp using TransitHop_ptr = std::shared_ptr; + struct Ptr_hash; + struct Endpoint_Hash; + struct endpoint_comparator; + + /// unordered set of paths with unique endpoints + using UniqueEndpointSet_t = std::unordered_set; + /// A path we made - struct Path final : public AbstractHopHandler, - public routing::AbstractRoutingMessageHandler, - public std::enable_shared_from_this + struct Path final : public AbstractHopHandler, public std::enable_shared_from_this { using BuildResultHookFunc = std::function; using CheckForDeadFunc = std::function; using DropHandlerFunc = std::function; using HopList = std::vector; - using DataHandlerFunc = std::function; + // using DataHandlerFunc = std::function; using ExitUpdatedFunc = std::function; using ExitClosedFunc = std::function; using ExitTrafficHandlerFunc = @@ -79,60 +84,6 @@ namespace llarp return _role; } - struct Hash - { - size_t - operator()(const Path& p) const - { - const auto& tx = p.hops[0].txID; - const auto& rx = p.hops[0].rxID; - const auto& r = p.hops[0].upstream; - const size_t rhash = std::accumulate(r.begin(), r.end(), 0, std::bit_xor{}); - return std::accumulate( - rx.begin(), - rx.begin(), - std::accumulate(tx.begin(), tx.end(), rhash, std::bit_xor{}), - std::bit_xor{}); - } - }; - - /// hash for std::shared_ptr - struct Ptr_Hash - { - size_t - operator()(const Path_ptr& p) const - { - if (p == nullptr) - return 0; - return Hash{}(*p); - } - }; - - /// hash for std::shared_ptr by path endpoint - struct Endpoint_Hash - { - size_t - operator()(const Path_ptr& p) const - { - if (p == nullptr) - return 0; - return std::hash{}(p->Endpoint()); - } - }; - - /// comparision for equal endpoints - struct Endpoint_Equals - { - bool - operator()(const Path_ptr& left, const Path_ptr& right) const - { - return left && right && left->Endpoint() == left->Endpoint(); - } - }; - - /// unordered set of paths with unique endpoints - using UniqueEndpointSet_t = std::unordered_set; - bool operator<(const Path& other) const { @@ -192,48 +143,6 @@ namespace llarp return m_LastRecvMessage; } - bool - HandleLRSM(uint64_t status, std::array& frames, Router* r) override; - - void - SetBuildResultHook(BuildResultHookFunc func); - - void - SetExitTrafficHandler(ExitTrafficHandlerFunc handler) - { - m_ExitTrafficHandler = handler; - } - - void - SetCloseExitFunc(ExitClosedFunc handler) - { - m_ExitClosed = handler; - } - - void - SetUpdateExitFunc(ExitUpdatedFunc handler) - { - m_ExitUpdated = handler; - } - - void - SetDataHandler(DataHandlerFunc func) - { - m_DataHandler = func; - } - - void - SetDropHandler(DropHandlerFunc func) - { - m_DropHandler = func; - } - - void - SetDeadChecker(CheckForDeadFunc func) - { - m_CheckForDead = func; - } - void EnterState(PathStatus st, llarp_time_t now); @@ -257,7 +166,7 @@ namespace llarp } void - close_exit() + mark_exit_closed() { log::info(path_cat, "{} hd its exit closed", name()); _role &= ePathRoleExit; @@ -277,76 +186,40 @@ namespace llarp void Tick(llarp_time_t now, Router* r); - void + bool find_name(std::string name, std::function func = nullptr); - void + bool find_router(std::string rid, std::function func = nullptr); - void + bool find_intro( const dht::Key_t& location, bool is_relayed = false, uint64_t order = 0, std::function func = nullptr); - void - send_path_control_message( - std::string method, - std::string body, - std::function func = nullptr) override; - - bool - SendRoutingMessage(const routing::AbstractRoutingMessage& msg, Router* r) override; - - bool - HandleObtainExitMessage(const routing::ObtainExitMessage& msg, Router* r) override; - - bool - HandleUpdateExitVerifyMessage( - const routing::UpdateExitVerifyMessage& msg, Router* r) override; - - bool - HandleTransferTrafficMessage(const routing::TransferTrafficMessage& msg, Router* r) override; - - bool - HandleUpdateExitMessage(const routing::UpdateExitMessage& msg, Router* r) override; - - bool - HandleCloseExitMessage(const routing::CloseExitMessage& msg, Router* r) override; - - bool - HandleGrantExitMessage(const routing::GrantExitMessage& msg, Router* r) override; - - bool - HandleRejectExitMessage(const routing::RejectExitMessage& msg, Router* r) override; - - bool - HandleDataDiscardMessage(const routing::DataDiscardMessage& msg, Router* r) override; - bool - HandlePathConfirmMessage(Router* r); - - bool - HandlePathConfirmMessage(const routing::PathConfirmMessage& msg, Router* r) override; - - bool - HandlePathLatencyMessage(const routing::PathLatencyMessage& msg, Router* r) override; - - bool - HandlePathTransferMessage(const routing::PathTransferMessage& msg, Router* r) override; - - bool - HandleHiddenServiceFrame(const service::ProtocolFrameMessage& frame) override; + close_exit( + SecretKey sk, + std::string tx_id, + std::function func = nullptr); bool - HandleGotIntroMessage(const dht::GotIntroMessage& msg); + obtain_exit( + SecretKey sk, + uint64_t flag, + std::string tx_id, + std::function func = nullptr); bool - HandleDHTMessage(const dht::AbstractDHTMessage& msg, Router* r) override; + send_path_control_message( + std::string method, + std::string body, + std::function func = nullptr) override; bool - HandleRoutingMessage(const llarp_buffer_t& buf, Router* r); + SendRoutingMessage(const routing::AbstractRoutingMessage& msg, Router* r) override; bool IsReady() const; @@ -374,18 +247,6 @@ namespace llarp std::string name() const; - void - AddObtainExitHandler(ObtainedExitHandler handler) - { - m_ObtainedExitHooks.push_back(handler); - } - - bool - SendExitRequest(const routing::ObtainExitMessage& msg, Router* r); - - bool - SendExitClose(const routing::CloseExitMessage& msg, Router* r); - void FlushUpstream(Router* r) override; @@ -414,14 +275,6 @@ namespace llarp InformExitResult(llarp_time_t b); Router& router; - BuildResultHookFunc m_BuiltHook; - DataHandlerFunc m_DataHandler; - DropHandlerFunc m_DropHandler; - CheckForDeadFunc m_CheckForDead; - ExitUpdatedFunc m_ExitUpdated; - ExitClosedFunc m_ExitClosed; - ExitTrafficHandlerFunc m_ExitTrafficHandler; - std::vector m_ObtainedExitHooks; llarp_time_t m_LastRecvMessage = 0s; llarp_time_t m_LastLatencyTestTime = 0s; uint64_t m_LastLatencyTestID = 0; @@ -437,5 +290,56 @@ namespace llarp std::deque m_LatencySamples; const std::string m_shortName; }; + + struct Hash + { + size_t + operator()(const Path& p) const + { + const auto& tx = p.hops[0].txID; + const auto& rx = p.hops[0].rxID; + const auto& r = p.hops[0].upstream; + const size_t rhash = std::accumulate(r.begin(), r.end(), 0, std::bit_xor{}); + return std::accumulate( + rx.begin(), + rx.begin(), + std::accumulate(tx.begin(), tx.end(), rhash, std::bit_xor{}), + std::bit_xor{}); + } + }; + + /// hash for std::shared_ptr + struct Ptr_Hash + { + size_t + operator()(const Path_ptr& p) const + { + if (p == nullptr) + return 0; + return Hash{}(*p); + } + }; + + /// hash for std::shared_ptr by path endpoint + struct Endpoint_Hash + { + size_t + operator()(const Path_ptr& p) const + { + if (p == nullptr) + return 0; + return std::hash{}(p->Endpoint()); + } + }; + + /// comparision for equal endpoints + struct endpoint_comparator + { + bool + operator()(const Path_ptr& left, const Path_ptr& right) const + { + return left && right && left->Endpoint() == left->Endpoint(); + } + }; } // namespace path } // namespace llarp diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index 9554b7fc83..7123ffd8fd 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -1,4 +1,5 @@ #include "pathbuilder.hpp" +#include "path.hpp" #include "path_context.hpp" #include @@ -110,12 +111,12 @@ namespace llarp { oxenc::bt_dict_producer btdp; - btdp.append("lifetime", path::DEFAULT_LIFETIME.count()); - btdp.append("txid", hop.txID.ToView()); - btdp.append("rxid", hop.rxID.ToView()); - btdp.append("nonce", hop.nonce.ToView()); - btdp.append("next", hop.upstream.ToView()); - btdp.append("commkey", hop.commkey.toPublic().ToView()); + btdp.append("COMMKEY", hop.commkey.toPublic().ToView()); + btdp.append("LIFETIME", path::DEFAULT_LIFETIME.count()); + btdp.append("NONCE", hop.nonce.ToView()); + btdp.append("RX", hop.rxID.ToView()); + btdp.append("TX", hop.txID.ToView()); + btdp.append("UPSTREAM", hop.upstream.ToView()); hop_info = std::move(btdp).str(); } @@ -147,9 +148,9 @@ namespace llarp { oxenc::bt_dict_producer btdp; - btdp.append("encrypted", hop_info); - btdp.append("pubkey", framekey.toPublic().ToView()); - btdp.append("nonce", outer_nonce.ToView()); + btdp.append("ENCRYPTED", hop_info); + btdp.append("NONCE", outer_nonce.ToView()); + btdp.append("PUBKEY", framekey.toPublic().ToView()); hashed_data = std::move(btdp).str(); } @@ -169,8 +170,8 @@ namespace llarp oxenc::bt_dict_producer btdp; - btdp.append("hash", hash); - btdp.append("frame", hashed_data); + btdp.append("FRAME", hashed_data); + btdp.append("HASH", hash); return std::move(btdp).str(); } diff --git a/llarp/path/pathbuilder.hpp b/llarp/path/pathbuilder.hpp index f79e9d8431..c2c8548abe 100644 --- a/llarp/path/pathbuilder.hpp +++ b/llarp/path/pathbuilder.hpp @@ -3,7 +3,6 @@ #include "pathset.hpp" #include #include -#include "path.hpp" #include #include diff --git a/llarp/path/pathset.cpp b/llarp/path/pathset.cpp index 1985055bda..f0c2d2fbfa 100644 --- a/llarp/path/pathset.cpp +++ b/llarp/path/pathset.cpp @@ -1,9 +1,6 @@ #include "path.hpp" #include "pathset.hpp" -#include -#include -#include #include #include diff --git a/llarp/path/pathset.hpp b/llarp/path/pathset.hpp index 986be4ed1f..cfd8c1c748 100644 --- a/llarp/path/pathset.hpp +++ b/llarp/path/pathset.hpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -31,6 +30,7 @@ namespace std namespace llarp { + struct Router; struct RouterContact; class NodeDB; @@ -210,12 +210,6 @@ namespace llarp virtual void BlacklistSNode(const RouterID) = 0; - virtual routing::AbstractRoutingMessageHandler* - GetDHTHandler() - { - return nullptr; - } - Path_ptr GetEstablishedPathClosestTo( RouterID router, diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index 4ea12cdbfb..e7407e29a0 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -1,18 +1,12 @@ #include "path.hpp" +#include "path_context.hpp" +#include "transit_hop.hpp" -#include #include #include #include #include -#include -#include -#include "path_context.hpp" -#include "transit_hop.hpp" #include -#include -#include -#include #include #include @@ -49,22 +43,6 @@ namespace llarp::path return started + lifetime; } - bool - TransitHop::HandleLRSM(uint64_t status, std::array& frames, Router* r) - { - auto msg = std::make_shared(frames); - msg->status = status; - msg->pathid = info.rxID; - - // TODO: add to IHopHandler some notion of "path status" - - const uint64_t ourStatus = LR_StatusRecord::SUCCESS; - - msg->AddFrame(pathKey, ourStatus); - LR_StatusMessage::QueueSendMessage(r, info.downstream, msg, shared_from_this()); - return true; - } - TransitHopInfo::TransitHopInfo(const RouterID& down, const LR_CommitRecord& record) : txID(record.txid), rxID(record.rxid), upstream(record.nextHop), downstream(down) {} @@ -223,15 +201,15 @@ namespace llarp::path { for (const auto& msg : msgs) { - llarp::LogDebug( - "relay ", + log::debug( + path_cat, + "Relaying {} bytes downstream from {} to {}", msg.enc.size(), - " bytes downstream from ", info.upstream, - " to ", info.downstream); - r->send_data_message(info.downstream, msg); + r->send_data_message(info.downstream, msg.bt_encode()); } + r->TriggerPump(); } @@ -257,183 +235,6 @@ namespace llarp::path } } - /// this is where a DHT message is handled at the end of a path, that is, - /// where a SNode receives a DHT message from a client along a path. - bool - TransitHop::HandleDHTMessage(const llarp::dht::AbstractDHTMessage& msg, Router* r) - { - return r->dht()->RelayRequestForPath(info.rxID, msg); - } - - bool - TransitHop::HandlePathLatencyMessage(const llarp::routing::PathLatencyMessage& msg, Router* r) - { - llarp::routing::PathLatencyMessage reply; - reply.latency = msg.sent_time; - reply.sequence_number = msg.sequence_number; - return SendRoutingMessage(reply, r); - } - - bool - TransitHop::HandlePathConfirmMessage( - [[maybe_unused]] const llarp::routing::PathConfirmMessage& msg, [[maybe_unused]] Router* r) - { - llarp::LogWarn("unwarranted path confirm message on ", info); - return false; - } - - bool - TransitHop::HandleDataDiscardMessage( - [[maybe_unused]] const llarp::routing::DataDiscardMessage& msg, [[maybe_unused]] Router* r) - { - llarp::LogWarn("unwarranted path data discard message on ", info); - return false; - } - - bool - TransitHop::HandleObtainExitMessage(const llarp::routing::ObtainExitMessage& msg, Router* r) - { - if (msg.Verify() && r->exitContext().ObtainNewExit(msg.pubkey, info.rxID, msg.flag != 0)) - { - llarp::routing::GrantExitMessage grant; - grant.sequence_number = NextSeqNo(); - grant.tx_id = msg.tx_id; - if (!grant.Sign(r->identity())) - { - llarp::LogError("Failed to sign grant exit message"); - return false; - } - return SendRoutingMessage(grant, r); - } - // TODO: exponential backoff, rejected policies ? - llarp::routing::RejectExitMessage reject; - reject.sequence_number = NextSeqNo(); - reject.tx_id = msg.tx_id; - if (!reject.Sign(r->identity())) - { - llarp::LogError("Failed to sign reject exit message"); - return false; - } - return SendRoutingMessage(reject, r); - } - - bool - TransitHop::HandleCloseExitMessage(const llarp::routing::CloseExitMessage& msg, Router* r) - { - const llarp::routing::DataDiscardMessage discard(info.rxID, msg.sequence_number); - auto ep = r->exitContext().FindEndpointForPath(info.rxID); - if (ep && msg.Verify(ep->PubKey())) - { - llarp::routing::CloseExitMessage reply; - reply.nonce = msg.nonce; - reply.sequence_number = NextSeqNo(); - if (reply.Sign(r->identity())) - { - if (SendRoutingMessage(reply, r)) - { - ep->Close(); - return true; - } - } - } - return SendRoutingMessage(discard, r); - } - - bool - TransitHop::HandleUpdateExitVerifyMessage( - const llarp::routing::UpdateExitVerifyMessage& msg, Router* r) - { - (void)msg; - (void)r; - llarp::LogError("unwarranted exit verify on ", info); - return false; - } - - bool - TransitHop::HandleUpdateExitMessage(const llarp::routing::UpdateExitMessage& msg, Router* r) - { - auto ep = r->exitContext().FindEndpointForPath(msg.path_id); - if (ep) - { - if (!msg.Verify(ep->PubKey())) - return false; - - if (ep->UpdateLocalPath(info.rxID)) - { - llarp::routing::UpdateExitVerifyMessage reply; - reply.tx_id = msg.tx_id; - reply.sequence_number = NextSeqNo(); - return SendRoutingMessage(reply, r); - } - } - // on fail tell message was discarded - llarp::routing::DataDiscardMessage discard(info.rxID, msg.sequence_number); - return SendRoutingMessage(discard, r); - } - - bool - TransitHop::HandleRejectExitMessage(const llarp::routing::RejectExitMessage& msg, Router* r) - { - (void)msg; - (void)r; - llarp::LogError(info, " got unwarranted RXM"); - return false; - } - - bool - TransitHop::HandleGrantExitMessage(const llarp::routing::GrantExitMessage& msg, Router* r) - { - (void)msg; - (void)r; - llarp::LogError(info, " got unwarranted GXM"); - return false; - } - - bool - TransitHop::HandleTransferTrafficMessage( - const llarp::routing::TransferTrafficMessage& msg, Router* r) - { - auto endpoint = r->exitContext().FindEndpointForPath(info.rxID); - if (endpoint) - { - bool sent = true; - for (const auto& pkt : msg.enc_buf) - { - // check short packet buffer - if (pkt.size() <= 8) - continue; - auto counter = oxenc::load_big_to_host(pkt.data()); - llarp_buffer_t buf{pkt.data() + 8, pkt.size() - 8}; - sent = - endpoint->QueueOutboundTraffic(info.rxID, buf.copy(), counter, msg.protocol) and sent; - } - return sent; - } - - llarp::LogError("No exit endpoint on ", info); - // discarded - llarp::routing::DataDiscardMessage discard(info.rxID, msg.sequence_number); - return SendRoutingMessage(discard, r); - } - - bool - TransitHop::HandlePathTransferMessage(const llarp::routing::PathTransferMessage& msg, Router* r) - { - auto path = r->path_context().GetPathForTransfer(msg.path_id); - llarp::routing::DataDiscardMessage discarded{msg.path_id, msg.sequence_number}; - if (path == nullptr || msg.protocol_frame_msg.path_id != info.txID) - { - return SendRoutingMessage(discarded, r); - } - // send routing message - if (path->SendRoutingMessage(msg.protocol_frame_msg, r)) - { - m_FlushOthers.emplace(path); - return true; - } - return SendRoutingMessage(discarded, r); - } - std::string TransitHop::ToString() const { diff --git a/llarp/path/transit_hop.hpp b/llarp/path/transit_hop.hpp index 42b5c0e02d..1a1725edbc 100644 --- a/llarp/path/transit_hop.hpp +++ b/llarp/path/transit_hop.hpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -52,9 +51,7 @@ namespace llarp < std::tie(rhs.txID, rhs.rxID, rhs.upstream, rhs.downstream); } - struct TransitHop : public AbstractHopHandler, - public routing::AbstractRoutingMessageHandler, - std::enable_shared_from_this + struct TransitHop : public AbstractHopHandler, std::enable_shared_from_this { TransitHop(); @@ -99,9 +96,6 @@ namespace llarp return m_LastActivity; } - bool - HandleLRSM(uint64_t status, std::array& frames, Router* r) override; - std::string ToString() const; @@ -114,7 +108,7 @@ namespace llarp return now >= ExpireTime() - dlt; } - void + bool send_path_control_message( std::string method, std::string body, @@ -124,55 +118,6 @@ namespace llarp bool SendRoutingMessage(const routing::AbstractRoutingMessage& msg, Router* r) override; - // handle routing message when end of path - bool - HandleRoutingMessage(const routing::AbstractRoutingMessage& msg, Router* r); - - bool - HandleDataDiscardMessage(const routing::DataDiscardMessage& msg, Router* r) override; - - bool - HandlePathConfirmMessage(Router* r); - - bool - HandlePathConfirmMessage(const routing::PathConfirmMessage& msg, Router* r) override; - bool - HandlePathTransferMessage(const routing::PathTransferMessage& msg, Router* r) override; - bool - HandlePathLatencyMessage(const routing::PathLatencyMessage& msg, Router* r) override; - - bool - HandleObtainExitMessage(const routing::ObtainExitMessage& msg, Router* r) override; - - bool - HandleUpdateExitVerifyMessage( - const routing::UpdateExitVerifyMessage& msg, Router* r) override; - - bool - HandleTransferTrafficMessage(const routing::TransferTrafficMessage& msg, Router* r) override; - - bool - HandleUpdateExitMessage(const routing::UpdateExitMessage& msg, Router* r) override; - - bool - HandleGrantExitMessage(const routing::GrantExitMessage& msg, Router* r) override; - bool - HandleRejectExitMessage(const routing::RejectExitMessage& msg, Router* r) override; - - bool - HandleCloseExitMessage(const routing::CloseExitMessage& msg, Router* r) override; - - bool - HandleHiddenServiceFrame(const service::ProtocolFrameMessage& /*frame*/) override - { - /// TODO: implement me - LogWarn("Got hidden service data on transit hop"); - return false; - } - - bool - HandleGotIntroMessage(const dht::GotIntroMessage& msg); - bool HandleDHTMessage(const dht::AbstractDHTMessage& msg, Router* r) override; diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index c6b7cedd47..70faaeef9d 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -7,33 +7,23 @@ #include "info.hpp" #include "protocol_type.hpp" -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include #include #include +#include #include #include -#include -#include +#include #include #include #include -#include #include -#include -#include -#include #include #include @@ -42,1700 +32,1683 @@ #include #include -namespace llarp +namespace llarp::service { - namespace service + static auto logcat = log::Cat("endpoint"); + + Endpoint::Endpoint(Router* r, Context* parent) + : path::Builder{r, 3, path::DEFAULT_LEN} + , context{parent} + , _inbound_queue{512} + , _send_queue{512} + , _recv_event_queue{512} + , _introset_lookup_filter{5s} { - static auto logcat = log::Cat("endpoint"); + _state = std::make_unique(); + _state->router = r; + _state->name = "endpoint"; + _recv_event_queue.enable(); - Endpoint::Endpoint(Router* r, Context* parent) - : path::Builder{r, 3, path::DEFAULT_LEN} - , context{parent} - , _inbound_queue{512} - , _send_queue{512} - , _recv_event_queue{512} - , _introset_lookup_filter{5s} - { - _state = std::make_unique(); - _state->router = r; - _state->name = "endpoint"; - _recv_event_queue.enable(); + if (Loop()->MaybeGetUVWLoop()) + _tunnel_manager = std::make_unique(*this); + } - if (Loop()->MaybeGetUVWLoop()) - _tunnel_manager = std::make_unique(*this); - } + bool + Endpoint::Configure(const NetworkConfig& conf, [[maybe_unused]] const DnsConfig& dnsConf) + { + if (conf.m_Paths.has_value()) + numDesiredPaths = *conf.m_Paths; + + if (conf.m_Hops.has_value()) + numHops = *conf.m_Hops; - bool - Endpoint::Configure(const NetworkConfig& conf, [[maybe_unused]] const DnsConfig& dnsConf) + conf.m_ExitMap.ForEachEntry( + [&](const IPRange& range, const service::Address& addr) { MapExitRange(range, addr); }); + + for (auto [exit, auth] : conf.m_ExitAuths) { - if (conf.m_Paths.has_value()) - numDesiredPaths = *conf.m_Paths; + SetAuthInfoForEndpoint(exit, auth); + } - if (conf.m_Hops.has_value()) - numHops = *conf.m_Hops; + conf.m_LNSExitMap.ForEachEntry([&](const IPRange& range, const std::string& name) { + std::optional auth; + const auto itr = conf.m_LNSExitAuths.find(name); + if (itr != conf.m_LNSExitAuths.end()) + auth = itr->second; + _startup_ons_mappings[name] = std::make_pair(range, auth); + }); - conf.m_ExitMap.ForEachEntry( - [&](const IPRange& range, const service::Address& addr) { MapExitRange(range, addr); }); + return _state->Configure(conf); + } - for (auto [exit, auth] : conf.m_ExitAuths) - { - SetAuthInfoForEndpoint(exit, auth); - } + bool + Endpoint::HasPendingPathToService(const Address& addr) const + { + return _state->pending_service_lookups.find(addr) != _state->pending_service_lookups.end(); + } - conf.m_LNSExitMap.ForEachEntry([&](const IPRange& range, const std::string& name) { - std::optional auth; - const auto itr = conf.m_LNSExitAuths.find(name); - if (itr != conf.m_LNSExitAuths.end()) - auth = itr->second; - _startup_ons_mappings[name] = std::make_pair(range, auth); - }); + bool + Endpoint::is_ready() const + { + const auto now = llarp::time_now_ms(); + if (intro_set().intros.empty()) + return false; + if (intro_set().IsExpired(now)) + return false; + return true; + } - return _state->Configure(conf); - } + bool + Endpoint::HasPendingRouterLookup(const RouterID remote) const + { + const auto& routers = _state->pending_routers; + return routers.find(remote) != routers.end(); + } - bool - Endpoint::HasPendingPathToService(const Address& addr) const + std::optional> + Endpoint::GetEndpointWithConvoTag(ConvoTag tag) const + { + auto itr = Sessions().find(tag); + if (itr != Sessions().end()) { - return _state->pending_service_lookups.find(addr) != _state->pending_service_lookups.end(); + return itr->second.remote.Addr(); } - bool - Endpoint::is_ready() const + for (const auto& item : _state->snode_sessions) { - const auto now = llarp::time_now_ms(); - if (intro_set().intros.empty()) - return false; - if (intro_set().IsExpired(now)) - return false; - return true; + if (const auto maybe = item.second->CurrentPath()) + { + if (ConvoTag{maybe->as_array()} == tag) + return item.first; + } } + return std::nullopt; + } - bool - Endpoint::HasPendingRouterLookup(const RouterID remote) const + void + Endpoint::map_exit( + std::string name, + std::string token, + std::vector ranges, + std::function result_handler) + { + if (ranges.empty()) { - const auto& routers = _state->pending_routers; - return routers.find(remote) != routers.end(); + result_handler(false, "no ranges provided"); + return; } - std::optional> - Endpoint::GetEndpointWithConvoTag(ConvoTag tag) const - { - auto itr = Sessions().find(tag); - if (itr != Sessions().end()) - { - return itr->second.remote.Addr(); + lookup_name( + name, + [ptr = std::static_pointer_cast(GetSelf()), + name, + auth = AuthInfo{token}, + ranges, + result_handler, + poker = router()->route_poker()](oxen::quic::message m) mutable { + if (m) + { + std::string name; + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + name = btdc.require("NAME"); + } + catch (...) + { + log::warning(link_cat, "Failed to parse find name response!"); + throw; + } + + if (auto saddr = service::Address(); saddr.FromString(name)) + { + ptr->SetAuthInfoForEndpoint(saddr, auth); + ptr->MarkAddressOutbound(saddr); + + auto result = ptr->EnsurePathToService( + saddr, + [ptr, name, ranges, result_handler, poker](auto addr, auto* ctx) { + if (ctx == nullptr) + { + result_handler(false, "could not establish flow to {}"_format(name)); + return; + } + + // make a lambda that sends the reply after doing auth + auto apply_result = + [ptr, poker, addr, result_handler, ranges](AuthResult result) { + if (result.code != AuthResultCode::eAuthAccepted) + { + result_handler(false, result.reason); + return; + } + for (const auto& range : ranges) + ptr->MapExitRange(range, addr); + + if (poker) + poker->put_up(); + result_handler(true, result.reason); + }; + + ctx->AsyncSendAuth(apply_result); + }, + ptr->PathAlignmentTimeout()); + + if (not result) + result_handler(false, "Could not build path to {}"_format(name)); + } + } + else + { + result_handler(false, "Exit {} not found!"_format(name)); + } + }); + } + + void + Endpoint::LookupServiceAsync( + std::string name, + std::string service, + std::function)> resultHandler) + { + // handles when we aligned to a loki address + auto handleGotPathToService = [resultHandler, service, this](auto addr) { + // we can probably get this info before we have a path to them but we do this after we + // have a path so when we send the response back they can send shit to them immediately + const auto& container = _state->remote_sessions; + if (auto itr = container.find(addr); itr != container.end()) + { + // parse the stuff we need from this guy + resultHandler(itr->second->GetCurrentIntroSet().GetMatchingSRVRecords(service)); + return; } + resultHandler({}); + }; - for (const auto& item : _state->snode_sessions) + // 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)) { - if (const auto maybe = item.second->CurrentPath()) - { - if (ConvoTag{maybe->as_array()} == tag) - return item.first; - } + result = maybe_rc->srvRecords; } - return std::nullopt; - } + resultHandler(std::move(result)); + }; - void - Endpoint::map_exit( - std::string name, - std::string token, - std::vector ranges, - std::function result_handler) - { - if (ranges.empty()) + // handles when we got a path to a remote thing + auto handleGotPathTo = [handleGotPathToService, handleResolvedSNodeName, resultHandler]( + auto maybe_tag, auto address) { + if (not maybe_tag) { - result_handler(false, "no ranges provided"); + resultHandler({}); return; } - lookup_name( - name, - [ptr = std::static_pointer_cast(GetSelf()), - name, - auth = AuthInfo{token}, - ranges, - result_handler, - poker = router()->route_poker()](oxen::quic::message m) mutable { - if (m) - { - std::string name; - try - { - oxenc::bt_dict_consumer btdc{m.body()}; - name = btdc.require("NAME"); - } - catch (...) - { - log::warning(log_cat, "Failed to parse find name response!"); - throw; - } + if (auto* addr = std::get_if
(&address)) + { + // .loki case + handleGotPathToService(*addr); + } + else if (auto* router_id = std::get_if(&address)) + { + // .snode case + handleResolvedSNodeName(*router_id); + } + else + { + // fallback case + // XXX: never should happen but we'll handle it anyways + resultHandler({}); + } + }; - if (auto saddr = service::Address(); saddr.FromString(name)) - { - ptr->SetAuthInfoForEndpoint(saddr, auth); - ptr->MarkAddressOutbound(saddr); - - auto result = ptr->EnsurePathToService( - saddr, - [ptr, name, ranges, result_handler, poker](auto addr, auto* ctx) { - if (ctx == nullptr) - { - result_handler(false, "could not establish flow to {}"_format(name)); - return; - } - - // make a lambda that sends the reply after doing auth - auto apply_result = - [ptr, poker, addr, result_handler, ranges](AuthResult result) { - if (result.code != AuthResultCode::eAuthAccepted) - { - result_handler(false, result.reason); - return; - } - for (const auto& range : ranges) - ptr->MapExitRange(range, addr); - - if (poker) - poker->put_up(); - result_handler(true, result.reason); - }; - - ctx->AsyncSendAuth(apply_result); - }, - ptr->PathAlignmentTimeout()); - - if (not result) - result_handler(false, "Could not build path to {}"_format(name)); - } - } - else - { - result_handler(false, "Exit {} not found!"_format(name)); - } - }); - } + // handles when we know a long address of a remote resource + auto handleGotAddress = [resultHandler, handleGotPathTo, this](AddressVariant_t address) { + // we will attempt a build to whatever we looked up + const auto result = EnsurePathTo( + address, + [address, handleGotPathTo](auto maybe_tag) { handleGotPathTo(maybe_tag, address); }, + PathAlignmentTimeout()); - void - Endpoint::LookupServiceAsync( - std::string name, - std::string service, - std::function)> resultHandler) - { - // handles when we aligned to a loki address - auto handleGotPathToService = [resultHandler, service, this](auto addr) { - // we can probably get this info before we have a path to them but we do this after we - // have a path so when we send the response back they can send shit to them immediately - const auto& container = _state->remote_sessions; - if (auto itr = container.find(addr); itr != container.end()) - { - // parse the stuff we need from this guy - resultHandler(itr->second->GetCurrentIntroSet().GetMatchingSRVRecords(service)); - return; - } + // on path build start fail short circuit + if (not result) resultHandler({}); - }; + }; - // 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)) + // look up this name async and start the entire chain of events + lookup_name(name, [handleGotAddress, resultHandler](oxen::quic::message m) mutable { + if (m) + { + std::string name; + try { - result = maybe_rc->srvRecords; + oxenc::bt_dict_consumer btdc{m.body()}; + name = btdc.require("NAME"); } - resultHandler(std::move(result)); - }; - - // handles when we got a path to a remote thing - auto handleGotPathTo = [handleGotPathToService, handleResolvedSNodeName, resultHandler]( - auto maybe_tag, auto address) { - if (not maybe_tag) + catch (...) { - resultHandler({}); - return; + log::warning(link_cat, "Failed to parse find name response!"); + throw; } - if (auto* addr = std::get_if
(&address)) - { - // .loki case - handleGotPathToService(*addr); - } - else if (auto* router_id = std::get_if(&address)) - { - // .snode case - handleResolvedSNodeName(*router_id); - } - else - { - // fallback case - // XXX: never should happen but we'll handle it anyways - resultHandler({}); - } - }; - - // handles when we know a long address of a remote resource - auto handleGotAddress = [resultHandler, handleGotPathTo, this](AddressVariant_t address) { - // we will attempt a build to whatever we looked up - const auto result = EnsurePathTo( - address, - [address, handleGotPathTo](auto maybe_tag) { handleGotPathTo(maybe_tag, address); }, - PathAlignmentTimeout()); - - // on path build start fail short circuit - if (not result) - resultHandler({}); - }; - - // look up this name async and start the entire chain of events - lookup_name(name, [handleGotAddress, resultHandler](oxen::quic::message m) mutable { - if (m) - { - std::string name; - try - { - oxenc::bt_dict_consumer btdc{m.body()}; - name = btdc.require("NAME"); - } - catch (...) - { - log::warning(log_cat, "Failed to parse find name response!"); - throw; - } + if (auto saddr = service::Address(); saddr.FromString(name)) + handleGotAddress(saddr); - if (auto saddr = service::Address(); saddr.FromString(name)) - handleGotAddress(saddr); + if (auto rid = RouterID(); rid.FromString(name)) + handleGotAddress(rid); + } + else + { + resultHandler({}); + } + }); + } - if (auto rid = RouterID(); rid.FromString(name)) - handleGotAddress(rid); - } - else - { - resultHandler({}); - } - }); - } + bool + Endpoint::IntrosetIsStale() const + { + return intro_set().HasExpiredIntros(llarp::time_now_ms()); + } - bool - Endpoint::IntrosetIsStale() const - { - return intro_set().HasExpiredIntros(llarp::time_now_ms()); - } + util::StatusObject + Endpoint::ExtractStatus() const + { + auto obj = path::Builder::ExtractStatus(); + obj["exitMap"] = _exit_map.ExtractStatus(); + obj["identity"] = _identity.pub.Addr().ToString(); + obj["networkReady"] = ReadyForNetwork(); - util::StatusObject - Endpoint::ExtractStatus() const + util::StatusObject authCodes; + for (const auto& [service, info] : _remote_auth_infos) { - auto obj = path::Builder::ExtractStatus(); - obj["exitMap"] = _exit_map.ExtractStatus(); - obj["identity"] = _identity.pub.Addr().ToString(); - obj["networkReady"] = ReadyForNetwork(); + authCodes[service.ToString()] = info.token; + } + obj["authCodes"] = authCodes; - util::StatusObject authCodes; - for (const auto& [service, info] : _remote_auth_infos) - { - authCodes[service.ToString()] = info.token; - } - obj["authCodes"] = authCodes; + return _state->ExtractStatus(obj); + } - return _state->ExtractStatus(obj); + void + Endpoint::Tick(llarp_time_t) + { + const auto now = llarp::time_now_ms(); + path::Builder::Tick(now); + // publish descriptors + if (ShouldPublishDescriptors(now)) + { + regen_and_publish_introset(); } + // decay introset lookup filter + _introset_lookup_filter.Decay(now); + // expire name cache + _state->nameCache.Decay(now); + // expire snode sessions + EndpointUtil::ExpireSNodeSessions(now, _state->snode_sessions); + // expire pending router lookups + EndpointUtil::ExpirePendingRouterLookups(now, _state->pending_routers); - void - Endpoint::Tick(llarp_time_t) + // deregister dead sessions + EndpointUtil::DeregisterDeadSessions(now, _state->dead_sessions); + // tick remote sessions + EndpointUtil::TickRemoteSessions( + now, _state->remote_sessions, _state->dead_sessions, Sessions()); + // expire convotags + EndpointUtil::ExpireConvoSessions(now, Sessions()); + + if (NumInStatus(path::ePathEstablished) > 1) { - const auto now = llarp::time_now_ms(); - path::Builder::Tick(now); - // publish descriptors - if (ShouldPublishDescriptors(now)) - { - regen_and_publish_introset(); - } - // decay introset lookup filter - _introset_lookup_filter.Decay(now); - // expire name cache - _state->nameCache.Decay(now); - // expire snode sessions - EndpointUtil::ExpireSNodeSessions(now, _state->snode_sessions); - // expire pending router lookups - EndpointUtil::ExpirePendingRouterLookups(now, _state->pending_routers); - - // deregister dead sessions - EndpointUtil::DeregisterDeadSessions(now, _state->dead_sessions); - // tick remote sessions - EndpointUtil::TickRemoteSessions( - now, _state->remote_sessions, _state->dead_sessions, Sessions()); - // expire convotags - EndpointUtil::ExpireConvoSessions(now, Sessions()); - - if (NumInStatus(path::ePathEstablished) > 1) + for (const auto& item : _startup_ons_mappings) { - for (const auto& item : _startup_ons_mappings) - { - auto& name = item.first; + auto& name = item.first; - lookup_name(name, [this, name, info = item.second](oxen::quic::message m) mutable { - if (m) + lookup_name(name, [this, name, info = item.second](oxen::quic::message m) mutable { + if (m) + { + std::string result; + try { - std::string result; - try - { - oxenc::bt_dict_consumer btdc{m.body()}; - result = btdc.require("NAME"); - } - catch (...) - { - log::warning(log_cat, "Failed to parse find name response!"); - throw; - } + oxenc::bt_dict_consumer btdc{m.body()}; + result = btdc.require("NAME"); + } + catch (...) + { + log::warning(link_cat, "Failed to parse find name response!"); + throw; + } - const auto maybe_range = info.first; - const auto maybe_auth = info.second; + const auto maybe_range = info.first; + const auto maybe_auth = info.second; - _startup_ons_mappings.erase(name); + _startup_ons_mappings.erase(name); - if (auto saddr = service::Address(); saddr.FromString(result)) - { - if (maybe_range.has_value()) - _exit_map.Insert(*maybe_range, saddr); - if (maybe_auth.has_value()) - SetAuthInfoForEndpoint(saddr, *maybe_auth); - } + if (auto saddr = service::Address(); saddr.FromString(result)) + { + if (maybe_range.has_value()) + _exit_map.Insert(*maybe_range, saddr); + if (maybe_auth.has_value()) + SetAuthInfoForEndpoint(saddr, *maybe_auth); } - }); - } + } + }); } } + } + + bool + Endpoint::Stop() + { + // stop remote sessions + log::debug(logcat, "Endpoint stopping remote sessions."); + EndpointUtil::StopRemoteSessions(_state->remote_sessions); + // stop snode sessions + log::debug(logcat, "Endpoint stopping snode sessions."); + EndpointUtil::StopSnodeSessions(_state->snode_sessions); + log::debug(logcat, "Endpoint stopping its path builder."); + return path::Builder::Stop(); + } + + uint64_t + Endpoint::GenTXID() + { + return randint(); + } + + std::string + Endpoint::Name() const + { + return _state->name + ":" + _identity.pub.Name(); + } - bool - Endpoint::Stop() + bool + Endpoint::HasInboundConvo(const Address& addr) const + { + for (const auto& item : Sessions()) { - // stop remote sessions - log::debug(logcat, "Endpoint stopping remote sessions."); - EndpointUtil::StopRemoteSessions(_state->remote_sessions); - // stop snode sessions - log::debug(logcat, "Endpoint stopping snode sessions."); - EndpointUtil::StopSnodeSessions(_state->snode_sessions); - log::debug(logcat, "Endpoint stopping its path builder."); - return path::Builder::Stop(); + if (item.second.remote.Addr() == addr and item.second.inbound) + return true; } + return false; + } - uint64_t - Endpoint::GenTXID() + bool + Endpoint::HasOutboundConvo(const Address& addr) const + { + for (const auto& item : Sessions()) { - return randint(); + if (item.second.remote.Addr() == addr && not item.second.inbound) + return true; } + return false; + } - std::string - Endpoint::Name() const + void + Endpoint::PutSenderFor(const ConvoTag& tag, const ServiceInfo& info, bool inbound) + { + if (info.Addr().IsZero()) { - return _state->name + ":" + _identity.pub.Name(); + LogError(Name(), " cannot put invalid service info ", info, " T=", tag); + return; } - - bool - Endpoint::HasInboundConvo(const Address& addr) const + auto itr = Sessions().find(tag); + if (itr == Sessions().end()) { - for (const auto& item : Sessions()) + if (WantsOutboundSession(info.Addr()) and inbound) { - if (item.second.remote.Addr() == addr and item.second.inbound) - return true; + LogWarn( + Name(), + " not adding sender for ", + info.Addr(), + " session is inbound and we want outbound T=", + tag); + return; } - return false; + itr = Sessions().emplace(tag, Session{}).first; + itr->second.inbound = inbound; + itr->second.remote = info; } + } - bool - Endpoint::HasOutboundConvo(const Address& addr) const + size_t + Endpoint::RemoveAllConvoTagsFor(service::Address remote) + { + size_t removed = 0; + auto& sessions = Sessions(); + auto itr = sessions.begin(); + while (itr != sessions.end()) { - for (const auto& item : Sessions()) + if (itr->second.remote.Addr() == remote) { - if (item.second.remote.Addr() == addr && not item.second.inbound) - return true; + itr = sessions.erase(itr); + removed++; } + else + ++itr; + } + return removed; + } + + bool + Endpoint::GetSenderFor(const ConvoTag& tag, ServiceInfo& si) const + { + auto itr = Sessions().find(tag); + if (itr == Sessions().end()) + return false; + si = itr->second.remote; + si.UpdateAddr(); + return true; + } + + void + Endpoint::PutIntroFor(const ConvoTag& tag, const Introduction& intro) + { + auto& s = Sessions()[tag]; + s.intro = intro; + } + + bool + Endpoint::GetIntroFor(const ConvoTag& tag, Introduction& intro) const + { + auto itr = Sessions().find(tag); + if (itr == Sessions().end()) return false; + intro = itr->second.intro; + return true; + } + + void + Endpoint::PutReplyIntroFor(const ConvoTag& tag, const Introduction& intro) + { + auto itr = Sessions().find(tag); + if (itr == Sessions().end()) + { + return; } + itr->second.replyIntro = intro; + } + + bool + Endpoint::GetReplyIntroFor(const ConvoTag& tag, Introduction& intro) const + { + auto itr = Sessions().find(tag); + if (itr == Sessions().end()) + return false; + intro = itr->second.replyIntro; + return true; + } + + bool + Endpoint::GetConvoTagsForService(const Address& addr, std::set& tags) const + { + return EndpointUtil::GetConvoTagsForService(Sessions(), addr, tags); + } + + bool + Endpoint::GetCachedSessionKeyFor(const ConvoTag& tag, SharedSecret& secret) const + { + auto itr = Sessions().find(tag); + if (itr == Sessions().end()) + return false; + secret = itr->second.sharedKey; + return true; + } - void - Endpoint::PutSenderFor(const ConvoTag& tag, const ServiceInfo& info, bool inbound) + void + Endpoint::PutCachedSessionKeyFor(const ConvoTag& tag, const SharedSecret& k) + { + auto itr = Sessions().find(tag); + if (itr == Sessions().end()) { - if (info.Addr().IsZero()) - { - LogError(Name(), " cannot put invalid service info ", info, " T=", tag); - return; - } - auto itr = Sessions().find(tag); - if (itr == Sessions().end()) - { - if (WantsOutboundSession(info.Addr()) and inbound) - { - LogWarn( - Name(), - " not adding sender for ", - info.Addr(), - " session is inbound and we want outbound T=", - tag); - return; - } - itr = Sessions().emplace(tag, Session{}).first; - itr->second.inbound = inbound; - itr->second.remote = info; - } + itr = Sessions().emplace(tag, Session{}).first; } + itr->second.sharedKey = k; + } + + void + Endpoint::ConvoTagTX(const ConvoTag& tag) + { + if (Sessions().count(tag)) + Sessions()[tag].TX(); + } - size_t - Endpoint::RemoveAllConvoTagsFor(service::Address remote) + void + Endpoint::ConvoTagRX(const ConvoTag& tag) + { + if (Sessions().count(tag)) + Sessions()[tag].RX(); + } + + bool + Endpoint::LoadKeyFile() + { + const auto& keyfile = _state->key_file; + if (!keyfile.empty()) { - size_t removed = 0; - auto& sessions = Sessions(); - auto itr = sessions.begin(); - while (itr != sessions.end()) - { - if (itr->second.remote.Addr() == remote) - { - itr = sessions.erase(itr); - removed++; - } - else - ++itr; - } - return removed; + _identity.EnsureKeys(keyfile, router()->key_manager()->needBackup()); } + else + { + _identity.RegenerateKeys(); + } + return true; + } - bool - Endpoint::GetSenderFor(const ConvoTag& tag, ServiceInfo& si) const + bool + Endpoint::Start() + { + // this does network isolation + while (_state->on_init_callbacks.size()) { - auto itr = Sessions().find(tag); - if (itr == Sessions().end()) + if (_state->on_init_callbacks.front()()) + _state->on_init_callbacks.pop_front(); + else + { + LogWarn("Can't call init of network isolation"); return false; - si = itr->second.remote; - si.UpdateAddr(); - return true; + } } + return true; + } + + // Keep this here (rather than the header) so that we don't need to include endpoint_state.hpp + // in endpoint.hpp for the unique_ptr member destructor. + Endpoint::~Endpoint() = default; - void - Endpoint::PutIntroFor(const ConvoTag& tag, const Introduction& intro) + void + Endpoint::regen_and_publish_introset() + { + const auto now = llarp::time_now_ms(); + _last_introset_regen_attempt = now; + std::set intros; + + if (const auto maybe = + GetCurrentIntroductionsWithFilter([now](const service::Introduction& intro) -> bool { + return not intro.ExpiresSoon(now, path::INTRO_STALE_THRESHOLD); + })) { - auto& s = Sessions()[tag]; - s.intro = intro; + intros.insert(maybe->begin(), maybe->end()); } - - bool - Endpoint::GetIntroFor(const ConvoTag& tag, Introduction& intro) const + else { - auto itr = Sessions().find(tag); - if (itr == Sessions().end()) - return false; - intro = itr->second.intro; - return true; + LogWarn( + "could not publish descriptors for endpoint ", + Name(), + " because we couldn't get enough valid introductions"); + BuildOne(); + return; } - void - Endpoint::PutReplyIntroFor(const ConvoTag& tag, const Introduction& intro) + intro_set().supported_protocols.clear(); + + // add supported ethertypes + if (HasIfAddr()) { - auto itr = Sessions().find(tag); - if (itr == Sessions().end()) + if (IPRange::V4MappedRange().Contains(GetIfAddr())) { - return; + intro_set().supported_protocols.push_back(ProtocolType::TrafficV4); + } + else + { + intro_set().supported_protocols.push_back(ProtocolType::TrafficV6); } - itr->second.replyIntro = intro; - } - bool - Endpoint::GetReplyIntroFor(const ConvoTag& tag, Introduction& intro) const + // exit related stuffo + if (_state->is_exit_enabled) + { + intro_set().supported_protocols.push_back(ProtocolType::Exit); + intro_set().exit_policy = GetExitPolicy(); + intro_set().owned_ranges = GetOwnedRanges(); + } + } + // add quic ethertype if we have listeners set up + if (auto* quic = GetQUICTunnel()) { - auto itr = Sessions().find(tag); - if (itr == Sessions().end()) - return false; - intro = itr->second.replyIntro; - return true; + if (quic->hasListeners()) + intro_set().supported_protocols.push_back(ProtocolType::QUIC); } - bool - Endpoint::GetConvoTagsForService(const Address& addr, std::set& tags) const + intro_set().intros.clear(); + for (auto& intro : intros) { - return EndpointUtil::GetConvoTagsForService(Sessions(), addr, tags); + if (intro_set().intros.size() < numDesiredPaths) + intro_set().intros.emplace_back(std::move(intro)); } - - bool - Endpoint::GetCachedSessionKeyFor(const ConvoTag& tag, SharedSecret& secret) const + if (intro_set().intros.empty()) { - auto itr = Sessions().find(tag); - if (itr == Sessions().end()) - return false; - secret = itr->second.sharedKey; - return true; + LogWarn("not enough intros to publish introset for ", Name()); + if (ShouldBuildMore(now)) + ManualRebuild(1); + return; } - - void - Endpoint::PutCachedSessionKeyFor(const ConvoTag& tag, const SharedSecret& k) + auto maybe = _identity.encrypt_and_sign_introset(intro_set(), now); + if (not maybe) { - auto itr = Sessions().find(tag); - if (itr == Sessions().end()) - { - itr = Sessions().emplace(tag, Session{}).first; - } - itr->second.sharedKey = k; + LogWarn("failed to generate introset for endpoint ", Name()); + return; } - - void - Endpoint::ConvoTagTX(const ConvoTag& tag) + if (publish_introset(*maybe)) { - if (Sessions().count(tag)) - Sessions()[tag].TX(); + LogInfo("(re)publishing introset for endpoint ", Name()); } - - void - Endpoint::ConvoTagRX(const ConvoTag& tag) + else { - if (Sessions().count(tag)) - Sessions()[tag].RX(); + LogWarn("failed to publish intro set for endpoint ", Name()); } + } - bool - Endpoint::LoadKeyFile() + bool + Endpoint::publish_introset(const EncryptedIntroSet& introset) + { + const auto paths = GetManyPathsWithUniqueEndpoints( + this, INTROSET_RELAY_REDUNDANCY, dht::Key_t{introset.derivedSigningKey.as_array()}); + + if (paths.size() != INTROSET_RELAY_REDUNDANCY) { - const auto& keyfile = _state->key_file; - if (!keyfile.empty()) - { - _identity.EnsureKeys(keyfile, router()->key_manager()->needBackup()); - } - else - { - _identity.RegenerateKeys(); - } - return true; + LogWarn( + "Cannot publish intro set because we only have ", + paths.size(), + " paths, but need ", + INTROSET_RELAY_REDUNDANCY); + return false; } - bool - Endpoint::Start() + for (const auto& path : paths) { - // this does network isolation - while (_state->on_init_callbacks.size()) + for (size_t i = 0; i < INTROSET_REQS_PER_RELAY; ++i) { - if (_state->on_init_callbacks.front()()) - _state->on_init_callbacks.pop_front(); - else - { - LogWarn("Can't call init of network isolation"); - return false; - } + router()->send_control_message(path->upstream(), "publish_intro", introset.bt_encode()); } - return true; } - // Keep this here (rather than the header) so that we don't need to include endpoint_state.hpp - // in endpoint.hpp for the unique_ptr member destructor. - Endpoint::~Endpoint() = default; + return true; + } - void - Endpoint::regen_and_publish_introset() - { - const auto now = llarp::time_now_ms(); - _last_introset_regen_attempt = now; - std::set intros; + size_t + Endpoint::UniqueEndpoints() const + { + return _state->remote_sessions.size() + _state->snode_sessions.size(); + } - if (const auto maybe = - GetCurrentIntroductionsWithFilter([now](const service::Introduction& intro) -> bool { - return not intro.ExpiresSoon(now, path::INTRO_STALE_THRESHOLD); - })) - { - intros.insert(maybe->begin(), maybe->end()); - } - else - { - LogWarn( - "could not publish descriptors for endpoint ", - Name(), - " because we couldn't get enough valid introductions"); - BuildOne(); - return; - } - - intro_set().supported_protocols.clear(); - - // add supported ethertypes - if (HasIfAddr()) - { - if (IPRange::V4MappedRange().Contains(GetIfAddr())) - { - intro_set().supported_protocols.push_back(ProtocolType::TrafficV4); - } - else - { - intro_set().supported_protocols.push_back(ProtocolType::TrafficV6); - } - - // exit related stuffo - if (_state->is_exit_enabled) - { - intro_set().supported_protocols.push_back(ProtocolType::Exit); - intro_set().exit_policy = GetExitPolicy(); - intro_set().owned_ranges = GetOwnedRanges(); - } - } - // add quic ethertype if we have listeners set up - if (auto* quic = GetQUICTunnel()) - { - if (quic->hasListeners()) - intro_set().supported_protocols.push_back(ProtocolType::QUIC); - } + constexpr auto PublishIntrosetTimeout = 20s; - intro_set().intros.clear(); - for (auto& intro : intros) - { - if (intro_set().intros.size() < numDesiredPaths) - intro_set().intros.emplace_back(std::move(intro)); - } - if (intro_set().intros.empty()) - { - LogWarn("not enough intros to publish introset for ", Name()); - if (ShouldBuildMore(now)) - ManualRebuild(1); - return; - } - auto maybe = _identity.encrypt_and_sign_introset(intro_set(), now); - if (not maybe) - { - LogWarn("failed to generate introset for endpoint ", Name()); - return; - } - if (publish_introset(*maybe)) - { - LogInfo("(re)publishing introset for endpoint ", Name()); - } - else - { - LogWarn("failed to publish intro set for endpoint ", Name()); - } - } + void + Endpoint::ResetInternalState() + { + path::Builder::ResetInternalState(); + static auto resetState = [](auto& container, auto getter) { + std::for_each(container.begin(), container.end(), [getter](auto& item) { + getter(item)->ResetInternalState(); + }); + }; + resetState(_state->remote_sessions, [](const auto& item) { return item.second; }); + resetState(_state->snode_sessions, [](const auto& item) { return item.second; }); + } - bool - Endpoint::publish_introset(const EncryptedIntroSet& introset) - { - const auto paths = GetManyPathsWithUniqueEndpoints( - this, INTROSET_RELAY_REDUNDANCY, dht::Key_t{introset.derivedSigningKey.as_array()}); + bool + Endpoint::ShouldPublishDescriptors(llarp_time_t now) const + { + if (not _publish_introset) + return false; - if (paths.size() != INTROSET_RELAY_REDUNDANCY) - { - LogWarn( - "Cannot publish intro set because we only have ", - paths.size(), - " paths, but need ", - INTROSET_RELAY_REDUNDANCY); - return false; - } + const auto lastEventAt = std::max(_state->last_publish_attempt, _state->last_publish); + const auto next_pub = lastEventAt + + (_state->local_introset.HasStaleIntros(now, path::INTRO_STALE_THRESHOLD) + ? IntrosetPublishRetryCooldown + : IntrosetPublishInterval); - for (const auto& path : paths) - { - for (size_t i = 0; i < INTROSET_REQS_PER_RELAY; ++i) - { - router()->send_control_message(path->upstream(), "publish_intro", introset.bt_encode()); - } - } + return now >= next_pub; + } - return true; - } - - size_t - Endpoint::UniqueEndpoints() const - { - return _state->remote_sessions.size() + _state->snode_sessions.size(); - } + std::optional> + Endpoint::GetHopsForBuild() + { + std::unordered_set exclude; + ForEachPath([&exclude](auto path) { exclude.insert(path->Endpoint()); }); + const auto maybe = + router()->node_db()->GetRandom([exclude, r = router()](const auto& rc) -> bool { + return exclude.count(rc.pubkey) == 0 + and not r->router_profiling().IsBadForPath(rc.pubkey); + }); + if (not maybe.has_value()) + return std::nullopt; + return GetHopsForBuildWithEndpoint(maybe->pubkey); + } - constexpr auto PublishIntrosetTimeout = 20s; + std::optional> + Endpoint::GetHopsForBuildWithEndpoint(RouterID endpoint) + { + return path::Builder::GetHopsAlignedToForBuild(endpoint, SnodeBlacklist()); + } - void - Endpoint::ResetInternalState() - { - path::Builder::ResetInternalState(); - static auto resetState = [](auto& container, auto getter) { - std::for_each(container.begin(), container.end(), [getter](auto& item) { - getter(item)->ResetInternalState(); - }); - }; - resetState(_state->remote_sessions, [](const auto& item) { return item.second; }); - resetState(_state->snode_sessions, [](const auto& item) { return item.second; }); - } + void + Endpoint::PathBuildStarted(path::Path_ptr path) + { + path::Builder::PathBuildStarted(path); + } - bool - Endpoint::ShouldPublishDescriptors(llarp_time_t now) const - { - if (not _publish_introset) - return false; + constexpr auto MaxOutboundContextPerRemote = 1; - const auto lastEventAt = std::max(_state->last_publish_attempt, _state->last_publish); - const auto next_pub = lastEventAt - + (_state->local_introset.HasStaleIntros(now, path::INTRO_STALE_THRESHOLD) - ? IntrosetPublishRetryCooldown - : IntrosetPublishInterval); + void + Endpoint::PutNewOutboundContext(const service::IntroSet& introset, llarp_time_t left) + { + const Address addr{introset.address_keys.Addr()}; - return now >= next_pub; - } + auto& remoteSessions = _state->remote_sessions; - std::optional> - Endpoint::GetHopsForBuild() + if (remoteSessions.count(addr) < MaxOutboundContextPerRemote) { - std::unordered_set exclude; - ForEachPath([&exclude](auto path) { exclude.insert(path->Endpoint()); }); - const auto maybe = - router()->node_db()->GetRandom([exclude, r = router()](const auto& rc) -> bool { - return exclude.count(rc.pubkey) == 0 - and not r->router_profiling().IsBadForPath(rc.pubkey); - }); - if (not maybe.has_value()) - return std::nullopt; - return GetHopsForBuildWithEndpoint(maybe->pubkey); + remoteSessions.emplace(addr, std::make_shared(introset, this)); + LogInfo("Created New outbound context for ", addr.ToString()); } - std::optional> - Endpoint::GetHopsForBuildWithEndpoint(RouterID endpoint) + auto sessionRange = remoteSessions.equal_range(addr); + for (auto itr = sessionRange.first; itr != sessionRange.second; ++itr) { - return path::Builder::GetHopsAlignedToForBuild(endpoint, SnodeBlacklist()); + itr->second->AddReadyHook( + [addr, this](auto session) { InformPathToService(addr, session); }, left); } + } - void - Endpoint::PathBuildStarted(path::Path_ptr path) + bool + Endpoint::HasExit() const + { + for (const auto& [name, info] : _startup_ons_mappings) { - path::Builder::PathBuildStarted(path); + if (info.first.has_value()) + return true; } - constexpr auto MaxOutboundContextPerRemote = 1; - - void - Endpoint::PutNewOutboundContext(const service::IntroSet& introset, llarp_time_t left) - { - const Address addr{introset.address_keys.Addr()}; + return not _exit_map.Empty(); + } - auto& remoteSessions = _state->remote_sessions; - - if (remoteSessions.count(addr) < MaxOutboundContextPerRemote) - { - remoteSessions.emplace(addr, std::make_shared(introset, this)); - LogInfo("Created New outbound context for ", addr.ToString()); - } + auto + Endpoint::GetUniqueEndpointsForLookup() const + { + path::UniqueEndpointSet_t paths; - auto sessionRange = remoteSessions.equal_range(addr); - for (auto itr = sessionRange.first; itr != sessionRange.second; ++itr) - { - itr->second->AddReadyHook( - [addr, this](auto session) { InformPathToService(addr, session); }, left); - } - } + ForEachPath([&paths](auto path) { + if (path and path->IsReady()) + paths.insert(path); + }); - void - Endpoint::HandleVerifyGotRouter(dht::GotRouterMessage_constptr msg, RouterID id, bool valid) - { - auto& pendingRouters = _state->pending_routers; - auto itr = pendingRouters.find(id); - if (itr != pendingRouters.end()) - { - if (valid) - itr->second.InformResult(msg->foundRCs); - else - itr->second.InformResult({}); - pendingRouters.erase(itr); - } - } + return paths; + } - bool - Endpoint::HasExit() const - { - for (const auto& [name, info] : _startup_ons_mappings) - { - if (info.first.has_value()) - return true; - } + bool + Endpoint::ReadyForNetwork() const + { + return is_ready() and ReadyToDoLookup(GetUniqueEndpointsForLookup().size()); + } - return not _exit_map.Empty(); - } + bool + Endpoint::ReadyToDoLookup(size_t num_paths) const + { + // Currently just checks the number of paths, but could do more checks in the future. + return num_paths >= MIN_ONS_LOOKUP_ENDPOINTS; + } - path::Path::UniqueEndpointSet_t - Endpoint::GetUniqueEndpointsForLookup() const + void + Endpoint::lookup_name(std::string name, std::function func) + { + // TODO: so fuck all this? + + // if (not is_valid_name(name)) + // { + // handler(parse_address(name)); + // return; + // } + + // auto& cache = _state->nameCache; + // const auto maybe = cache.Get(name); + // if (maybe.has_value()) + // { + // handler(maybe); + // return; + // } + + log::info(link_cat, "{} looking up ONS name {}", Name(), name); + auto paths = GetUniqueEndpointsForLookup(); + + // // not enough paths + // if (not ReadyToDoLookup(paths.size())) + // { + // LogWarn( + // Name(), + // " not enough paths for lns lookup, have ", + // paths.size(), + // " need ", + // MIN_ONS_LOOKUP_ENDPOINTS); + // handler(std::nullopt); + // return; + // } + + // pick up to max_unique_lns_endpoints random paths to do lookups from + std::vector chosenpaths; + chosenpaths.insert(chosenpaths.begin(), paths.begin(), paths.end()); + std::shuffle(chosenpaths.begin(), chosenpaths.end(), CSRNG{}); + chosenpaths.resize(std::min(paths.size(), MAX_ONS_LOOKUP_ENDPOINTS)); + + for (const auto& path : chosenpaths) + { + log::info(link_cat, "{} lookup {} from {}", Name(), name, path->Endpoint()); + path->find_name(name, func); + } + } + + void + Endpoint::EnsureRouterIsKnown(const RouterID& rid) + { + if (rid.IsZero()) + return; + if (!router()->node_db()->has_router(rid)) { - path::Path::UniqueEndpointSet_t paths; - ForEachPath([&paths](auto path) { - if (path and path->IsReady()) - paths.insert(path); - }); - return paths; + lookup_router(rid); } + } - bool - Endpoint::ReadyForNetwork() const - { - return is_ready() and ReadyToDoLookup(GetUniqueEndpointsForLookup().size()); - } + bool + Endpoint::lookup_router(RouterID rid, std::function func) + { + const auto& routers = _state->pending_routers; - bool - Endpoint::ReadyToDoLookup(size_t num_paths) const + if (routers.find(rid) == routers.end()) { - // Currently just checks the number of paths, but could do more checks in the future. - return num_paths >= MIN_ONS_LOOKUP_ENDPOINTS; + auto path = GetEstablishedPathClosestTo(rid); + path->find_router("find_router", func); + return true; } - void - Endpoint::lookup_name(std::string name, std::function func) - { - // TODO: so fuck all this? - - // if (not is_valid_name(name)) - // { - // handler(parse_address(name)); - // return; - // } + return false; + } - // auto& cache = _state->nameCache; - // const auto maybe = cache.Get(name); - // if (maybe.has_value()) - // { - // handler(maybe); - // return; - // } - - log::info(log_cat, "{} looking up ONS name {}", Name(), name); - auto paths = GetUniqueEndpointsForLookup(); - - // // not enough paths - // if (not ReadyToDoLookup(paths.size())) - // { - // LogWarn( - // Name(), - // " not enough paths for lns lookup, have ", - // paths.size(), - // " need ", - // MIN_ONS_LOOKUP_ENDPOINTS); - // handler(std::nullopt); - // return; - // } + void + Endpoint::HandlePathBuilt(path::Path_ptr p) + { + // p->SetDataHandler(util::memFn(&Endpoint::HandleHiddenServiceFrame, this)); + // p->SetDropHandler(util::memFn(&Endpoint::HandleDataDrop, this)); + // p->SetDeadChecker(util::memFn(&Endpoint::CheckPathIsDead, this)); + path::Builder::HandlePathBuilt(p); + } + + bool + Endpoint::HandleDataDrop(path::Path_ptr p, const PathID_t& dst, uint64_t seq) + { + LogWarn(Name(), " message ", seq, " dropped by endpoint ", p->Endpoint(), " via ", dst); + return true; + } - // pick up to max_unique_lns_endpoints random paths to do lookups from - std::vector chosenpaths; - chosenpaths.insert(chosenpaths.begin(), paths.begin(), paths.end()); - std::shuffle(chosenpaths.begin(), chosenpaths.end(), CSRNG{}); - chosenpaths.resize(std::min(paths.size(), MAX_ONS_LOOKUP_ENDPOINTS)); + std::unordered_map + Endpoint::NotifyParams() const + { + return {{"LOKINET_ADDR", _identity.pub.Addr().ToString()}}; + } - for (const auto& path : chosenpaths) - { - log::info(log_cat, "{} lookup {} from {}", Name(), name, path->Endpoint()); - path->find_name(name, func); - } + void + Endpoint::FlushRecvData() + { + while (auto maybe = _recv_event_queue.tryPopFront()) + { + auto& ev = *maybe; + ProtocolMessage::ProcessAsync(ev.fromPath, ev.pathid, ev.msg); } + } - void - Endpoint::EnsureRouterIsKnown(const RouterID& rid) + void + Endpoint::QueueRecvData(RecvDataEvent ev) + { + _recv_event_queue.tryPushBack(std::move(ev)); + router()->TriggerPump(); + } + + bool + Endpoint::HandleDataMessage( + path::Path_ptr p, const PathID_t from, std::shared_ptr msg) + { + PutSenderFor(msg->tag, msg->sender, true); + Introduction intro = msg->introReply; + if (HasInboundConvo(msg->sender.Addr())) { - if (rid.IsZero()) - return; - if (!router()->node_db()->has_router(rid)) - { - lookup_router(rid); - } + intro.path_id = from; + intro.router = p->Endpoint(); } + PutReplyIntroFor(msg->tag, intro); + ConvoTagRX(msg->tag); + return ProcessDataMessage(msg); + } - bool - Endpoint::lookup_router(RouterID rid, std::function func) + bool + Endpoint::HasPathToSNode(const RouterID ident) const + { + auto range = _state->snode_sessions.equal_range(ident); + auto itr = range.first; + while (itr != range.second) { - const auto& routers = _state->pending_routers; - - if (routers.find(rid) == routers.end()) + if (itr->second->IsReady()) { - auto path = GetEstablishedPathClosestTo(rid); - path->find_router("find_router", func); return true; } - - return false; + ++itr; } + return false; + } - void - Endpoint::HandlePathBuilt(path::Path_ptr p) - { - p->SetDataHandler(util::memFn(&Endpoint::HandleHiddenServiceFrame, this)); - p->SetDropHandler(util::memFn(&Endpoint::HandleDataDrop, this)); - p->SetDeadChecker(util::memFn(&Endpoint::CheckPathIsDead, this)); - path::Builder::HandlePathBuilt(p); - } + EndpointBase::AddressVariant_t + Endpoint::LocalAddress() const + { + return _identity.pub.Addr(); + } - bool - Endpoint::HandleDataDrop(path::Path_ptr p, const PathID_t& dst, uint64_t seq) - { - LogWarn(Name(), " message ", seq, " dropped by endpoint ", p->Endpoint(), " via ", dst); - return true; - } + std::optional + Endpoint::GetStatFor(AddressVariant_t) const + { + // TODO: implement me + return std::nullopt; + } - std::unordered_map - Endpoint::NotifyParams() const + std::unordered_set + Endpoint::AllRemoteEndpoints() const + { + std::unordered_set remote; + for (const auto& item : Sessions()) { - return {{"LOKINET_ADDR", _identity.pub.Addr().ToString()}}; + remote.insert(item.second.remote.Addr()); } - - void - Endpoint::FlushRecvData() + for (const auto& item : _state->snode_sessions) { - while (auto maybe = _recv_event_queue.tryPopFront()) - { - auto& ev = *maybe; - ProtocolMessage::ProcessAsync(ev.fromPath, ev.pathid, ev.msg); - } + remote.insert(item.first); } + return remote; + } - void - Endpoint::QueueRecvData(RecvDataEvent ev) + bool + Endpoint::ProcessDataMessage(std::shared_ptr msg) + { + if ((msg->proto == ProtocolType::Exit + && (_state->is_exit_enabled || _exit_map.ContainsValue(msg->sender.Addr()))) + || msg->proto == ProtocolType::TrafficV4 || msg->proto == ProtocolType::TrafficV6 + || (msg->proto == ProtocolType::QUIC and _tunnel_manager)) { - _recv_event_queue.tryPushBack(std::move(ev)); + _inbound_queue.tryPushBack(std::move(msg)); router()->TriggerPump(); + return true; } - - bool - Endpoint::HandleDataMessage( - path::Path_ptr p, const PathID_t from, std::shared_ptr msg) + if (msg->proto == ProtocolType::Control) { - PutSenderFor(msg->tag, msg->sender, true); - Introduction intro = msg->introReply; - if (HasInboundConvo(msg->sender.Addr())) - { - intro.path_id = from; - intro.router = p->Endpoint(); - } - PutReplyIntroFor(msg->tag, intro); - ConvoTagRX(msg->tag); - return ProcessDataMessage(msg); + // TODO: implement me (?) + // right now it's just random noise + return true; } + return false; + } - bool - Endpoint::HasPathToSNode(const RouterID ident) const + void + Endpoint::AsyncProcessAuthMessage( + std::shared_ptr msg, std::function hook) + { + if (_auth_policy) { - auto range = _state->snode_sessions.equal_range(ident); - auto itr = range.first; - while (itr != range.second) + if (not _auth_policy->AsyncAuthPending(msg->tag)) { - if (itr->second->IsReady()) - { - return true; - } - ++itr; + // do 1 authentication attempt and drop everything else + _auth_policy->AuthenticateAsync(std::move(msg), std::move(hook)); } - return false; } - - EndpointBase::AddressVariant_t - Endpoint::LocalAddress() const + else { - return _identity.pub.Addr(); + router()->loop()->call([h = std::move(hook)] { h({AuthResultCode::eAuthAccepted, "OK"}); }); } + } - std::optional - Endpoint::GetStatFor(AddressVariant_t) const - { - // TODO: implement me - return std::nullopt; - } + void + Endpoint::SendAuthResult(path::Path_ptr path, PathID_t replyPath, ConvoTag tag, AuthResult result) + { + // not applicable because we are not an exit or don't have an endpoint auth policy + if ((not _state->is_exit_enabled) or _auth_policy == nullptr) + return; + ProtocolFrameMessage f{}; + f.flag = AuthResultCodeAsInt(result.code); + f.convo_tag = tag; + f.path_id = path->intro.path_id; + f.nonce.Randomize(); + if (result.code == AuthResultCode::eAuthAccepted) + { + ProtocolMessage msg; + + std::vector reason{}; + reason.resize(result.reason.size()); + std::copy_n(result.reason.c_str(), reason.size(), reason.data()); + msg.PutBuffer(reason); + if (_auth_policy) + msg.proto = ProtocolType::Auth; + else + msg.proto = ProtocolType::Control; - std::unordered_set - Endpoint::AllRemoteEndpoints() const - { - std::unordered_set remote; - for (const auto& item : Sessions()) - { - remote.insert(item.second.remote.Addr()); - } - for (const auto& item : _state->snode_sessions) + if (not GetReplyIntroFor(tag, msg.introReply)) { - remote.insert(item.first); + LogError("Failed to send auth reply: no reply intro"); + return; } - return remote; - } - - bool - Endpoint::ProcessDataMessage(std::shared_ptr msg) - { - if ((msg->proto == ProtocolType::Exit - && (_state->is_exit_enabled || _exit_map.ContainsValue(msg->sender.Addr()))) - || msg->proto == ProtocolType::TrafficV4 || msg->proto == ProtocolType::TrafficV6 - || (msg->proto == ProtocolType::QUIC and _tunnel_manager)) + msg.sender = _identity.pub; + SharedSecret sessionKey{}; + if (not GetCachedSessionKeyFor(tag, sessionKey)) { - _inbound_queue.tryPushBack(std::move(msg)); - router()->TriggerPump(); - return true; + LogError("failed to send auth reply: no cached session key"); + return; } - if (msg->proto == ProtocolType::Control) + if (not f.EncryptAndSign(msg, sessionKey, _identity)) { - // TODO: implement me (?) - // right now it's just random noise - return true; + LogError("Failed to encrypt and sign auth reply"); + return; } - return false; } - - void - Endpoint::AsyncProcessAuthMessage( - std::shared_ptr msg, std::function hook) + else { - if (_auth_policy) + if (not f.Sign(_identity)) { - if (not _auth_policy->AsyncAuthPending(msg->tag)) - { - // do 1 authentication attempt and drop everything else - _auth_policy->AuthenticateAsync(std::move(msg), std::move(hook)); - } - } - else - { - router()->loop()->call([h = std::move(hook)] { h({AuthResultCode::eAuthAccepted, "OK"}); }); - } - } - - void - Endpoint::SendAuthResult( - path::Path_ptr path, PathID_t replyPath, ConvoTag tag, AuthResult result) - { - // not applicable because we are not an exit or don't have an endpoint auth policy - if ((not _state->is_exit_enabled) or _auth_policy == nullptr) + LogError("failed to sign auth reply result"); return; - ProtocolFrameMessage f{}; - f.flag = AuthResultCodeAsInt(result.code); - f.convo_tag = tag; - f.path_id = path->intro.path_id; - f.nonce.Randomize(); - if (result.code == AuthResultCode::eAuthAccepted) - { - ProtocolMessage msg; - - std::vector reason{}; - reason.resize(result.reason.size()); - std::copy_n(result.reason.c_str(), reason.size(), reason.data()); - msg.PutBuffer(reason); - if (_auth_policy) - msg.proto = ProtocolType::Auth; - else - msg.proto = ProtocolType::Control; - - if (not GetReplyIntroFor(tag, msg.introReply)) - { - LogError("Failed to send auth reply: no reply intro"); - return; - } - msg.sender = _identity.pub; - SharedSecret sessionKey{}; - if (not GetCachedSessionKeyFor(tag, sessionKey)) - { - LogError("failed to send auth reply: no cached session key"); - return; - } - if (not f.EncryptAndSign(msg, sessionKey, _identity)) - { - LogError("Failed to encrypt and sign auth reply"); - return; - } - } - else - { - if (not f.Sign(_identity)) - { - LogError("failed to sign auth reply result"); - return; - } } - _send_queue.tryPushBack( - SendEvent{std::make_shared(f, replyPath), path}); } + _send_queue.tryPushBack( + SendEvent{std::make_shared(f, replyPath), path}); + } - void - Endpoint::RemoveConvoTag(const ConvoTag& t) - { - Sessions().erase(t); - } + void + Endpoint::RemoveConvoTag(const ConvoTag& t) + { + Sessions().erase(t); + } - void - Endpoint::ResetConvoTag(ConvoTag tag, path::Path_ptr p, PathID_t from) - { - // send reset convo tag message - ProtocolFrameMessage f{}; - f.flag = 1; - f.convo_tag = tag; - f.path_id = p->intro.path_id; - f.Sign(_identity); - { - LogWarn("invalidating convotag T=", tag); - RemoveConvoTag(tag); - _send_queue.tryPushBack( - SendEvent{std::make_shared(f, from), p}); - } + void + Endpoint::ResetConvoTag(ConvoTag tag, path::Path_ptr p, PathID_t from) + { + // send reset convo tag message + ProtocolFrameMessage f{}; + f.flag = 1; + f.convo_tag = tag; + f.path_id = p->intro.path_id; + f.Sign(_identity); + { + LogWarn("invalidating convotag T=", tag); + RemoveConvoTag(tag); + _send_queue.tryPushBack( + SendEvent{std::make_shared(f, from), p}); } + } - bool - Endpoint::HandleHiddenServiceFrame(path::Path_ptr p, const ProtocolFrameMessage& frame) + bool + Endpoint::HandleHiddenServiceFrame(path::Path_ptr p, const ProtocolFrameMessage& frame) + { + if (frame.flag) { - if (frame.flag) - { - // handle discard - ServiceInfo si; - if (!GetSenderFor(frame.convo_tag, si)) - return false; - // verify source - if (!frame.Verify(si)) - return false; - // remove convotag it doesn't exist - LogWarn("remove convotag T=", frame.convo_tag, " R=", frame.flag, " from ", si.Addr()); - RemoveConvoTag(frame.convo_tag); - return true; - } - if (not frame.AsyncDecryptAndVerify(router()->loop(), p, _identity, this)) - { - ResetConvoTag(frame.convo_tag, p, frame.path_id); - } + // handle discard + ServiceInfo si; + if (!GetSenderFor(frame.convo_tag, si)) + return false; + // verify source + if (!frame.Verify(si)) + return false; + // remove convotag it doesn't exist + LogWarn("remove convotag T=", frame.convo_tag, " R=", frame.flag, " from ", si.Addr()); + RemoveConvoTag(frame.convo_tag); return true; } - - void - Endpoint::HandlePathDied(path::Path_ptr p) + if (not frame.AsyncDecryptAndVerify(router()->loop(), p, _identity, this)) { - router()->router_profiling().MarkPathTimeout(p.get()); - ManualRebuild(1); - path::Builder::HandlePathDied(p); - regen_and_publish_introset(); + ResetConvoTag(frame.convo_tag, p, frame.path_id); } + return true; + } - bool - Endpoint::CheckPathIsDead(path::Path_ptr, llarp_time_t dlt) - { - return dlt > path::ALIVE_TIMEOUT; - } + void + Endpoint::HandlePathDied(path::Path_ptr p) + { + router()->router_profiling().MarkPathTimeout(p.get()); + ManualRebuild(1); + path::Builder::HandlePathDied(p); + regen_and_publish_introset(); + } + + bool + Endpoint::CheckPathIsDead(path::Path_ptr, llarp_time_t dlt) + { + return dlt > path::ALIVE_TIMEOUT; + } - void - Endpoint::MarkAddressOutbound(service::Address addr) - { - _state->m_OutboundSessions.insert(addr); - } + void + Endpoint::MarkAddressOutbound(service::Address addr) + { + _state->m_OutboundSessions.insert(addr); + } - bool - Endpoint::WantsOutboundSession(const Address& addr) const - { - return _state->m_OutboundSessions.count(addr) > 0; - } + bool + Endpoint::WantsOutboundSession(const Address& addr) const + { + return _state->m_OutboundSessions.count(addr) > 0; + } - void - Endpoint::InformPathToService(const Address remote, OutboundContext* ctx) + void + Endpoint::InformPathToService(const Address remote, OutboundContext* ctx) + { + auto& serviceLookups = _state->pending_service_lookups; + auto range = serviceLookups.equal_range(remote); + auto itr = range.first; + while (itr != range.second) + { + itr->second(remote, ctx); + ++itr; + } + serviceLookups.erase(remote); + } + + bool + Endpoint::EnsurePathTo( + std::variant addr, + std::function)> hook, + llarp_time_t timeout) + { + if (auto ptr = std::get_if
(&addr)) { - auto& serviceLookups = _state->pending_service_lookups; - auto range = serviceLookups.equal_range(remote); - auto itr = range.first; - while (itr != range.second) + if (*ptr == _identity.pub.Addr()) { - itr->second(remote, ctx); - ++itr; + ConvoTag tag{}; + + if (auto maybe = GetBestConvoTagFor(*ptr)) + tag = *maybe; + else + tag.Randomize(); + PutSenderFor(tag, _identity.pub, true); + ConvoTagTX(tag); + Sessions()[tag].forever = true; + Loop()->call_soon([tag, hook]() { hook(tag); }); + return true; + } + if (not WantsOutboundSession(*ptr)) + { + // we don't want to connect back to inbound sessions + hook(std::nullopt); + return true; } - serviceLookups.erase(remote); - } - bool - Endpoint::EnsurePathTo( - std::variant addr, - std::function)> hook, - llarp_time_t timeout) + return EnsurePathToService( + *ptr, + [hook](auto, auto* ctx) { + if (ctx) + { + hook(ctx->currentConvoTag); + } + else + { + hook(std::nullopt); + } + }, + timeout); + } + if (auto ptr = std::get_if(&addr)) { - if (auto ptr = std::get_if
(&addr)) - { - if (*ptr == _identity.pub.Addr()) + return EnsurePathToSNode(*ptr, [hook](auto, auto session, auto tag) { + if (session) { - ConvoTag tag{}; - - if (auto maybe = GetBestConvoTagFor(*ptr)) - tag = *maybe; - else - tag.Randomize(); - PutSenderFor(tag, _identity.pub, true); - ConvoTagTX(tag); - Sessions()[tag].forever = true; - Loop()->call_soon([tag, hook]() { hook(tag); }); - return true; + hook(tag); } - if (not WantsOutboundSession(*ptr)) + else { - // we don't want to connect back to inbound sessions hook(std::nullopt); - return true; } + }); + } + return false; + } - return EnsurePathToService( - *ptr, - [hook](auto, auto* ctx) { - if (ctx) - { - hook(ctx->currentConvoTag); - } - else - { - hook(std::nullopt); - } - }, - timeout); - } - if (auto ptr = std::get_if(&addr)) + bool + Endpoint::EnsurePathToSNode( + const RouterID snode, + std::function hook) + { + auto& nodeSessions = _state->snode_sessions; + + using namespace std::placeholders; + if (nodeSessions.count(snode) == 0) + { + const auto src = xhtonl(net::TruncateV6(GetIfAddr())); + const auto dst = xhtonl(net::TruncateV6(ObtainIPForAddr(snode))); + + auto session = std::make_shared( + snode, + [=](const llarp_buffer_t& buf) -> bool { + net::IPPacket pkt; + if (not pkt.Load(buf)) + return false; + pkt.UpdateIPv4Address(src, dst); + /// TODO: V6 + auto itr = _state->snode_sessions.find(snode); + if (itr == _state->snode_sessions.end()) + return false; + if (const auto maybe = itr->second->CurrentPath()) + return HandleInboundPacket( + ConvoTag{maybe->as_array()}, pkt.ConstBuffer(), ProtocolType::TrafficV4, 0); + return false; + }, + router(), + 1, + numHops, + false, + this); + _state->snode_sessions[snode] = session; + } + EnsureRouterIsKnown(snode); + auto range = nodeSessions.equal_range(snode); + auto itr = range.first; + while (itr != range.second) + { + if (itr->second->IsReady()) + hook(snode, itr->second, ConvoTag{itr->second->CurrentPath()->as_array()}); + else { - return EnsurePathToSNode(*ptr, [hook](auto, auto session, auto tag) { + itr->second->AddReadyHook([hook, snode](auto session) { if (session) { - hook(tag); + hook(snode, session, ConvoTag{session->CurrentPath()->as_array()}); } else { - hook(std::nullopt); + hook(snode, nullptr, ConvoTag{}); } }); + if (not itr->second->BuildCooldownHit(Now())) + itr->second->BuildOne(); } - return false; + ++itr; } + return true; + } - bool - Endpoint::EnsurePathToSNode( - const RouterID snode, - std::function hook) + bool + Endpoint::EnsurePathToService( + const Address remote, + std::function hook, + [[maybe_unused]] llarp_time_t timeout) + { + if (not WantsOutboundSession(remote)) { - auto& nodeSessions = _state->snode_sessions; + // we don't want to ensure paths to addresses that are inbound + // inform fail right away in that case + hook(remote, nullptr); + return false; + } - using namespace std::placeholders; - if (nodeSessions.count(snode) == 0) - { - const auto src = xhtonl(net::TruncateV6(GetIfAddr())); - const auto dst = xhtonl(net::TruncateV6(ObtainIPForAddr(snode))); - - auto session = std::make_shared( - snode, - [=](const llarp_buffer_t& buf) -> bool { - net::IPPacket pkt; - if (not pkt.Load(buf)) - return false; - pkt.UpdateIPv4Address(src, dst); - /// TODO: V6 - auto itr = _state->snode_sessions.find(snode); - if (itr == _state->snode_sessions.end()) - return false; - if (const auto maybe = itr->second->CurrentPath()) - return HandleInboundPacket( - ConvoTag{maybe->as_array()}, pkt.ConstBuffer(), ProtocolType::TrafficV4, 0); - return false; - }, - router(), - 1, - numHops, - false, - this); - _state->snode_sessions[snode] = session; - } - EnsureRouterIsKnown(snode); - auto range = nodeSessions.equal_range(snode); + /// how many routers to use for lookups + static constexpr size_t NumParallelLookups = 2; + + // add response hook to list for address. + _state->pending_service_lookups.emplace(remote, hook); + + auto& sessions = _state->remote_sessions; + { + auto range = sessions.equal_range(remote); auto itr = range.first; while (itr != range.second) { - if (itr->second->IsReady()) - hook(snode, itr->second, ConvoTag{itr->second->CurrentPath()->as_array()}); - else + if (itr->second->ReadyToSend()) { - itr->second->AddReadyHook([hook, snode](auto session) { - if (session) - { - hook(snode, session, ConvoTag{session->CurrentPath()->as_array()}); - } - else - { - hook(snode, nullptr, ConvoTag{}); - } - }); - if (not itr->second->BuildCooldownHit(Now())) - itr->second->BuildOne(); + InformPathToService(remote, itr->second.get()); + return true; } ++itr; } - return true; } + /// check replay filter + if (not _introset_lookup_filter.Insert(remote)) + return true; - bool - Endpoint::EnsurePathToService( - const Address remote, - std::function hook, - [[maybe_unused]] llarp_time_t timeout) - { - if (not WantsOutboundSession(remote)) - { - // we don't want to ensure paths to addresses that are inbound - // inform fail right away in that case - hook(remote, nullptr); - return false; - } + const auto paths = GetManyPathsWithUniqueEndpoints(this, NumParallelLookups); - /// how many routers to use for lookups - static constexpr size_t NumParallelLookups = 2; + const dht::Key_t location = remote.ToKey(); - // add response hook to list for address. - _state->pending_service_lookups.emplace(remote, hook); + // flag to only add callback to list of callbacks for + // address once. + bool hookAdded = false; - auto& sessions = _state->remote_sessions; - { - auto range = sessions.equal_range(remote); - auto itr = range.first; - while (itr != range.second) + for (const auto& path : paths) + { + path->find_intro(location, false, 0, [this, hook](oxen::quic::message m) mutable { + if (m) { - if (itr->second->ReadyToSend()) + std::string introset; + + try { - InformPathToService(remote, itr->second.get()); - return true; + oxenc::bt_dict_consumer btdc{m.body()}; + introset = btdc.require("INTROSET"); } - ++itr; - } - } - /// check replay filter - if (not _introset_lookup_filter.Insert(remote)) - return true; - - const auto paths = GetManyPathsWithUniqueEndpoints(this, NumParallelLookups); - - const dht::Key_t location = remote.ToKey(); - - // flag to only add callback to list of callbacks for - // address once. - bool hookAdded = false; - - for (const auto& path : paths) - { - path->find_intro(location, false, 0, [this, hook](oxen::quic::message m) mutable { - if (m) + catch (...) { - std::string introset; - - try - { - oxenc::bt_dict_consumer btdc{m.body()}; - introset = btdc.require("INTROSET"); - } - catch (...) - { - log::warning(log_cat, "Failed to parse find name response!"); - throw; - } - - service::EncryptedIntroSet enc{introset}; - router()->contacts()->services()->PutNode(std::move(enc)); - - // TODO: finish this + log::warning(link_cat, "Failed to parse find name response!"); + throw; } - }); - } - return hookAdded; - } - void - Endpoint::SRVRecordsChanged() - { - auto& introset = intro_set(); - introset.SRVs.clear(); - for (const auto& srv : SRVRecords()) - introset.SRVs.emplace_back(srv.toTuple()); + service::EncryptedIntroSet enc{introset}; + router()->contacts()->services()->PutNode(std::move(enc)); - regen_and_publish_introset(); + // TODO: finish this + } + }); } + return hookAdded; + } - bool - Endpoint::send_to(ConvoTag tag, std::string payload) - { - if (tag.IsZero()) - { - log::warning(log_cat, "SendToOrQueue failed: convo tag is zero"); - return false; - } + void + Endpoint::SRVRecordsChanged() + { + auto& introset = intro_set(); + introset.SRVs.clear(); + for (const auto& srv : SRVRecords()) + introset.SRVs.emplace_back(srv.toTuple()); - log::debug(log_cat, "{} sending {} bytes (Tag: {})", Name(), payload.size(), tag); + regen_and_publish_introset(); + } - if (auto maybe = GetEndpointWithConvoTag(tag)) - { - if (auto rid = std::get_if(&*maybe)) - { - return router()->send_data_message(*rid, payload); - } - if (auto saddr = std::get_if
(&*maybe)) - { - return router()->send_data_message(saddr->ToRouter(), payload); - } - } - - log::debug(log_cat, "SendToOrQueue failed: no endpoint for convo tag {}", tag); + bool + Endpoint::send_to(ConvoTag tag, std::string payload) + { + if (tag.IsZero()) + { + log::warning(link_cat, "SendToOrQueue failed: convo tag is zero"); return false; } - void - Endpoint::Pump(llarp_time_t now) - { - FlushRecvData(); - // send downstream packets to user for snode - for (const auto& [router, session] : _state->snode_sessions) - session->FlushDownstream(); + log::debug(link_cat, "{} sending {} bytes (Tag: {})", Name(), payload.size(), tag); - // handle inbound traffic sorted - util::ascending_priority_queue queue; - while (not _inbound_queue.empty()) + if (auto maybe = GetEndpointWithConvoTag(tag)) + { + if (auto rid = std::get_if(&*maybe)) { - // succ it out - queue.emplace(std::move(*_inbound_queue.popFront())); + return router()->send_data_message(*rid, payload); } - while (not queue.empty()) + if (auto saddr = std::get_if
(&*maybe)) { - const auto& msg = queue.top(); - LogDebug( - Name(), - " handle inbound packet on ", - msg.tag, - " ", - msg.payload.size(), - " bytes seqno=", - msg.seqno); - if (HandleInboundPacket(msg.tag, msg.payload, msg.proto, msg.seqno)) - { - ConvoTagRX(msg.tag); - } - else - { - LogWarn("Failed to handle inbound message"); - } - queue.pop(); + return router()->send_data_message(saddr->ToRouter(), payload); } + } - auto r = router(); - // TODO: locking on this container - for (const auto& [addr, outctx] : _state->remote_sessions) + log::debug(link_cat, "SendToOrQueue failed: no endpoint for convo tag {}", tag); + return false; + } + + void + Endpoint::Pump(llarp_time_t now) + { + FlushRecvData(); + // send downstream packets to user for snode + for (const auto& [router, session] : _state->snode_sessions) + session->FlushDownstream(); + + // handle inbound traffic sorted + util::ascending_priority_queue queue; + while (not _inbound_queue.empty()) + { + // succ it out + queue.emplace(std::move(*_inbound_queue.popFront())); + } + while (not queue.empty()) + { + const auto& msg = queue.top(); + LogDebug( + Name(), + " handle inbound packet on ", + msg.tag, + " ", + msg.payload.size(), + " bytes seqno=", + msg.seqno); + if (HandleInboundPacket(msg.tag, msg.payload, msg.proto, msg.seqno)) { - outctx->FlushUpstream(); - outctx->Pump(now); + ConvoTagRX(msg.tag); } - // TODO: locking on this container - for (const auto& [r, session] : _state->snode_sessions) - session->FlushUpstream(); - - // send queue flush - while (not _send_queue.empty()) + else { - SendEvent item = _send_queue.popFront(); - item.first->sequence_number = item.second->NextSeqNo(); - if (item.second->SendRoutingMessage(*item.first, r)) - ConvoTagTX(item.first->protocol_frame_msg.convo_tag); + LogWarn("Failed to handle inbound message"); } + queue.pop(); + } - UpstreamFlush(r); + auto r = router(); + // TODO: locking on this container + for (const auto& [addr, outctx] : _state->remote_sessions) + { + outctx->FlushUpstream(); + outctx->Pump(now); } + // TODO: locking on this container + for (const auto& [r, session] : _state->snode_sessions) + session->FlushUpstream(); + + // send queue flush + while (not _send_queue.empty()) + { + SendEvent item = _send_queue.popFront(); + item.first->sequence_number = item.second->NextSeqNo(); + if (item.second->SendRoutingMessage(*item.first, r)) + ConvoTagTX(item.first->protocol_frame_msg.convo_tag); + } + + UpstreamFlush(r); + } - std::optional - Endpoint::GetBestConvoTagFor(std::variant remote) const + std::optional + Endpoint::GetBestConvoTagFor(std::variant remote) const + { + // get convotag with lowest estimated RTT + if (auto ptr = std::get_if
(&remote)) { - // get convotag with lowest estimated RTT - if (auto ptr = std::get_if
(&remote)) + llarp_time_t rtt = 30s; + std::optional ret = std::nullopt; + for (const auto& [tag, session] : Sessions()) { - llarp_time_t rtt = 30s; - std::optional ret = std::nullopt; - for (const auto& [tag, session] : Sessions()) + if (tag.IsZero()) + continue; + if (session.remote.Addr() == *ptr) { - if (tag.IsZero()) - continue; - if (session.remote.Addr() == *ptr) + if (*ptr == _identity.pub.Addr()) + { + return tag; + } + if (session.inbound) { - if (*ptr == _identity.pub.Addr()) + auto path = GetPathByRouter(session.replyIntro.router); + // if we have no path to the remote router that's fine still use it just in case this + // is the ONLY one we have + if (path == nullptr) { - return tag; + ret = tag; + continue; } - if (session.inbound) + + if (path and path->IsReady()) { - auto path = GetPathByRouter(session.replyIntro.router); - // if we have no path to the remote router that's fine still use it just in case this - // is the ONLY one we have - if (path == nullptr) + const auto rttEstimate = (session.replyIntro.latency + path->intro.latency) * 2; + if (rttEstimate < rtt) { ret = tag; - continue; - } - - if (path and path->IsReady()) - { - const auto rttEstimate = (session.replyIntro.latency + path->intro.latency) * 2; - if (rttEstimate < rtt) - { - ret = tag; - rtt = rttEstimate; - } + rtt = rttEstimate; } } - else + } + else + { + auto range = _state->remote_sessions.equal_range(*ptr); + auto itr = range.first; + while (itr != range.second) { - auto range = _state->remote_sessions.equal_range(*ptr); - auto itr = range.first; - while (itr != range.second) + if (itr->second->ReadyToSend() and itr->second->estimatedRTT > 0s) { - if (itr->second->ReadyToSend() and itr->second->estimatedRTT > 0s) + if (itr->second->estimatedRTT < rtt) { - if (itr->second->estimatedRTT < rtt) - { - ret = tag; - rtt = itr->second->estimatedRTT; - } + ret = tag; + rtt = itr->second->estimatedRTT; } - itr++; } + itr++; } } } - return ret; - } - if (auto* ptr = std::get_if(&remote)) - { - auto itr = _state->snode_sessions.find(*ptr); - if (itr == _state->snode_sessions.end()) - return std::nullopt; - if (auto maybe = itr->second->CurrentPath()) - return ConvoTag{maybe->as_array()}; } - return std::nullopt; - } - - bool - Endpoint::HasConvoTag(const ConvoTag& t) const - { - return Sessions().find(t) != Sessions().end(); + return ret; } - - std::optional - Endpoint::GetSeqNoForConvo(const ConvoTag& tag) + if (auto* ptr = std::get_if(&remote)) { - auto itr = Sessions().find(tag); - if (itr == Sessions().end()) + auto itr = _state->snode_sessions.find(*ptr); + if (itr == _state->snode_sessions.end()) return std::nullopt; - return itr->second.seqno++; + if (auto maybe = itr->second->CurrentPath()) + return ConvoTag{maybe->as_array()}; } + return std::nullopt; + } - bool - Endpoint::ShouldBuildMore(llarp_time_t now) const - { - if (BuildCooldownHit(now)) - return false; - const auto requiredPaths = std::max(numDesiredPaths, path::MIN_INTRO_PATHS); - if (NumInStatus(path::ePathBuilding) >= requiredPaths) - return false; - return NumPathsExistingAt(now + (path::DEFAULT_LIFETIME - path::INTRO_PATH_SPREAD)) - < requiredPaths; - } + bool + Endpoint::HasConvoTag(const ConvoTag& t) const + { + return Sessions().find(t) != Sessions().end(); + } - Router* - Endpoint::router() - { - return _state->router; - } + std::optional + Endpoint::GetSeqNoForConvo(const ConvoTag& tag) + { + auto itr = Sessions().find(tag); + if (itr == Sessions().end()) + return std::nullopt; + return itr->second.seqno++; + } - const EventLoop_ptr& - Endpoint::Loop() - { - return router()->loop(); - } + bool + Endpoint::ShouldBuildMore(llarp_time_t now) const + { + if (BuildCooldownHit(now)) + return false; + const auto requiredPaths = std::max(numDesiredPaths, path::MIN_INTRO_PATHS); + if (NumInStatus(path::ePathBuilding) >= requiredPaths) + return false; + return NumPathsExistingAt(now + (path::DEFAULT_LIFETIME - path::INTRO_PATH_SPREAD)) + < requiredPaths; + } - void - Endpoint::BlacklistSNode(const RouterID snode) - { - _state->snode_blacklist.insert(snode); - } + Router* + Endpoint::router() + { + return _state->router; + } - const std::set& - Endpoint::SnodeBlacklist() const - { - return _state->snode_blacklist; - } + const EventLoop_ptr& + Endpoint::Loop() + { + return router()->loop(); + } - const IntroSet& - Endpoint::intro_set() const - { - return _state->local_introset; - } + void + Endpoint::BlacklistSNode(const RouterID snode) + { + _state->snode_blacklist.insert(snode); + } - IntroSet& - Endpoint::intro_set() - { - return _state->local_introset; - } + const std::set& + Endpoint::SnodeBlacklist() const + { + return _state->snode_blacklist; + } - const std::unordered_map& - Endpoint::Sessions() const - { - return _state->m_Sessions; - } + const IntroSet& + Endpoint::intro_set() const + { + return _state->local_introset; + } - std::unordered_map& - Endpoint::Sessions() - { - return _state->m_Sessions; - } + IntroSet& + Endpoint::intro_set() + { + return _state->local_introset; + } - void - Endpoint::SetAuthInfoForEndpoint(Address addr, AuthInfo info) - { - if (info.token.empty()) - { - _remote_auth_infos.erase(addr); - return; - } - _remote_auth_infos[addr] = std::move(info); - } + const std::unordered_map& + Endpoint::Sessions() const + { + return _state->m_Sessions; + } - void - Endpoint::MapExitRange(IPRange range, Address exit) - { - if (not exit.IsZero()) - LogInfo(Name(), " map ", range, " to exit at ", exit); - _exit_map.Insert(range, exit); - } - bool - Endpoint::HasFlowToService(Address addr) const - { - return HasOutboundConvo(addr) or HasInboundConvo(addr); - } + std::unordered_map& + Endpoint::Sessions() + { + return _state->m_Sessions; + } - void - Endpoint::UnmapExitRange(IPRange range) + void + Endpoint::SetAuthInfoForEndpoint(Address addr, AuthInfo info) + { + if (info.token.empty()) { - // unmap all ranges that fit in the range we gave - _exit_map.RemoveIf([&](const auto& item) -> bool { - if (not range.Contains(item.first)) - return false; - LogInfo(Name(), " unmap ", item.first, " exit range mapping"); - return true; - }); - - if (_exit_map.Empty()) - router()->route_poker()->put_down(); + _remote_auth_infos.erase(addr); + return; } + _remote_auth_infos[addr] = std::move(info); + } - void - Endpoint::UnmapRangeByExit(IPRange range, std::string exit) - { - // unmap all ranges that match the given exit when hot swapping - _exit_map.RemoveIf([&](const auto& item) -> bool { - if ((range.Contains(item.first)) and (item.second.ToString() == exit)) - { - log::info(logcat, "{} unmap {} range mapping to exit node {}", Name(), item.first, exit); - return true; - } + void + Endpoint::MapExitRange(IPRange range, Address exit) + { + if (not exit.IsZero()) + LogInfo(Name(), " map ", range, " to exit at ", exit); + _exit_map.Insert(range, exit); + } + bool + Endpoint::HasFlowToService(Address addr) const + { + return HasOutboundConvo(addr) or HasInboundConvo(addr); + } + + void + Endpoint::UnmapExitRange(IPRange range) + { + // unmap all ranges that fit in the range we gave + _exit_map.RemoveIf([&](const auto& item) -> bool { + if (not range.Contains(item.first)) return false; - }); + LogInfo(Name(), " unmap ", item.first, " exit range mapping"); + return true; + }); - if (_exit_map.Empty()) - router()->route_poker()->put_down(); - } + if (_exit_map.Empty()) + router()->route_poker()->put_down(); + } - std::optional - Endpoint::MaybeGetAuthInfoForEndpoint(Address remote) - { - const auto itr = _remote_auth_infos.find(remote); - if (itr == _remote_auth_infos.end()) - return std::nullopt; - return itr->second; - } + void + Endpoint::UnmapRangeByExit(IPRange range, std::string exit) + { + // unmap all ranges that match the given exit when hot swapping + _exit_map.RemoveIf([&](const auto& item) -> bool { + if ((range.Contains(item.first)) and (item.second.ToString() == exit)) + { + log::info(logcat, "{} unmap {} range mapping to exit node {}", Name(), item.first, exit); + return true; + } + return false; + }); - quic::TunnelManager* - Endpoint::GetQUICTunnel() - { - return _tunnel_manager.get(); - } + if (_exit_map.Empty()) + router()->route_poker()->put_down(); + } + + std::optional + Endpoint::MaybeGetAuthInfoForEndpoint(Address remote) + { + const auto itr = _remote_auth_infos.find(remote); + if (itr == _remote_auth_infos.end()) + return std::nullopt; + return itr->second; + } + + quic::TunnelManager* + Endpoint::GetQUICTunnel() + { + return _tunnel_manager.get(); + } - } // namespace service -} // namespace llarp +} // namespace llarp::service diff --git a/llarp/service/endpoint.hpp b/llarp/service/endpoint.hpp index 573fd703f7..c2ea6c8628 100644 --- a/llarp/service/endpoint.hpp +++ b/llarp/service/endpoint.hpp @@ -1,10 +1,9 @@ #pragma once -#include +#include #include #include #include #include -#include #include #include @@ -70,7 +69,9 @@ namespace llarp std::shared_ptr msg; }; - struct Endpoint : public path::Builder, public EndpointBase + struct Endpoint : public path::Builder, + public EndpointBase, + public std::enable_shared_from_this { Endpoint(Router* r, Context* parent); ~Endpoint() override; @@ -474,9 +475,6 @@ namespace llarp PrefetchServicesByTag(const Tag& tag); private: - void - HandleVerifyGotRouter(dht::GotRouterMessage_constptr msg, RouterID id, bool valid); - bool DoNetworkIsolation(bool failed); @@ -501,7 +499,8 @@ namespace llarp protected: bool ReadyToDoLookup(size_t num_paths) const; - path::Path::UniqueEndpointSet_t + + auto GetUniqueEndpointsForLookup() const; Identity _identity; @@ -530,13 +529,16 @@ namespace llarp friend struct EndpointUtil; - // clang-format off - const IntroSet& intro_set() const; - IntroSet& intro_set(); + const IntroSet& + intro_set() const; + IntroSet& + intro_set(); + + const std::unordered_map& + Sessions() const; + std::unordered_map& + Sessions(); - const std::unordered_map& Sessions() const; - std::unordered_map& Sessions(); - // clang-format on thread::Queue _recv_event_queue; /// for rate limiting introset lookups diff --git a/llarp/service/endpoint_util.hpp b/llarp/service/endpoint_util.hpp index 3839dd76ca..5290a6ebc9 100644 --- a/llarp/service/endpoint_util.hpp +++ b/llarp/service/endpoint_util.hpp @@ -45,7 +45,7 @@ namespace llarp::service }; template - static path::Path::UniqueEndpointSet_t + static std::unordered_set GetManyPathsWithUniqueEndpoints( Endpoint_t* ep, size_t N, @@ -53,7 +53,7 @@ namespace llarp::service size_t tries = 10) { std::unordered_set exclude; - path::Path::UniqueEndpointSet_t paths; + path::UniqueEndpointSet_t paths; do { --tries; diff --git a/llarp/service/protocol.hpp b/llarp/service/protocol.hpp index f6e882c794..e1e2a34837 100644 --- a/llarp/service/protocol.hpp +++ b/llarp/service/protocol.hpp @@ -2,8 +2,6 @@ #include #include -#include -#include #include #include "protocol_type.hpp" #include "identity.hpp" diff --git a/llarp/service/sendcontext.cpp b/llarp/service/sendcontext.cpp index e214dfc82f..6f7d5586be 100644 --- a/llarp/service/sendcontext.cpp +++ b/llarp/service/sendcontext.cpp @@ -1,5 +1,6 @@ #include "sendcontext.hpp" +#include #include #include #include "endpoint.hpp" @@ -18,7 +19,6 @@ namespace llarp::service , m_PathSet(send) , service_endpoint(ep) , createdAt(ep->Now()) - , m_SendQueue(SendContextQueueSize) {} bool @@ -39,7 +39,7 @@ namespace llarp::service SendContext::FlushUpstream() { auto r = service_endpoint->router(); - std::unordered_set flushpaths; + std::unordered_set flushpaths; auto rttRMS = 0ms; while (auto maybe = m_SendQueue.tryPopFront()) { diff --git a/llarp/service/sendcontext.hpp b/llarp/service/sendcontext.hpp index f5f5731514..2daf23247e 100644 --- a/llarp/service/sendcontext.hpp +++ b/llarp/service/sendcontext.hpp @@ -1,11 +1,10 @@ #pragma once #include "intro.hpp" +#include "protocol.hpp" #include -#include #include #include -#include "protocol.hpp" #include #include #include @@ -49,10 +48,6 @@ namespace llarp::service llarp_time_t shiftTimeout = (path::BUILD_TIMEOUT * 5) / 2; llarp_time_t estimatedRTT = 0s; bool markedBad = false; - using Msg_ptr = std::shared_ptr; - using SendEvent_t = std::pair; - - thread::Queue m_SendQueue; std::function authResultListener; From 98f2d0210312a2276fc9b0a7f8258d9bdb07df93 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Mon, 16 Oct 2023 17:53:01 -0300 Subject: [PATCH 055/312] Untangle messy nested dependency tree lokinet-cryptography depends on lokinet-base which depends on lokinet-cryptography. Fixed this but splitting lokinet-cryptography into the libntrup code (which is what is really needed) and the llarp/crypto code (which isn't needed for lokinet-base). --- crypto/CMakeLists.txt | 14 +++++++------- llarp/CMakeLists.txt | 7 ++++--- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt index c73a6ed142..b39422f28b 100644 --- a/crypto/CMakeLists.txt +++ b/crypto/CMakeLists.txt @@ -1,5 +1,5 @@ -add_library(lokinet-cryptography +add_library(lokinet-libntrup STATIC libntrup/src/ntru.cpp libntrup/src/ref/randomsmall.c @@ -20,7 +20,7 @@ add_library(lokinet-cryptography libntrup/src/ref/rq.c ) -target_include_directories(lokinet-cryptography PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/libntrup/include) +target_include_directories(lokinet-libntrup PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/libntrup/include) # The avx implementation uses runtime CPU feature detection to enable itself, so we *always* want to # compile it with avx2/fma support when supported by the compiler even if we aren't compiling with @@ -48,19 +48,19 @@ include(CheckCXXCompilerFlag) check_cxx_compiler_flag(-mavx2 COMPILER_SUPPORTS_AVX2) check_cxx_compiler_flag(-mfma COMPILER_SUPPORTS_FMA) if(COMPILER_SUPPORTS_AVX2 AND COMPILER_SUPPORTS_FMA AND (NOT ANDROID)) - target_sources(lokinet-cryptography PRIVATE ${NTRU_AVX_SRC}) + target_sources(lokinet-libntrup PRIVATE ${NTRU_AVX_SRC}) set_property(SOURCE ${NTRU_AVX_SRC} APPEND PROPERTY COMPILE_FLAGS "-mavx2 -mfma") message(STATUS "Building libntrup with runtime AVX2/FMA support") else() - target_sources(lokinet-cryptography PRIVATE libntrup/src/noavx-stubs.c) + target_sources(lokinet-libntrup PRIVATE libntrup/src/noavx-stubs.c) message(STATUS "Not building with libntrup runtime AVX2/FMA support (either this architecture doesn't support them, or your compile doesn't support the -mavx2 -mfma flags") endif() -enable_lto(lokinet-cryptography) +enable_lto(lokinet-libntrup) if (WARNINGS_AS_ERRORS) - target_compile_options(lokinet-cryptography PUBLIC -Wall -Wextra -Werror) + target_compile_options(lokinet-libntrup PUBLIC -Wall -Wextra -Werror) endif() -target_link_libraries(lokinet-cryptography PUBLIC sodium) +target_link_libraries(lokinet-libntrup PUBLIC sodium) diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index e06cd340e0..e42eca201d 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -1,6 +1,7 @@ include(Version) -target_sources(lokinet-cryptography PRIVATE +add_library(lokinet-cryptography + STATIC crypto/crypto.cpp crypto/encrypted_frame.cpp crypto/types.cpp @@ -250,7 +251,7 @@ add_library(lokinet-base INTERFACE) target_include_directories(lokinet-base INTERFACE ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/include ) -target_link_libraries(lokinet-base INTERFACE quic lokinet-cryptography) +target_link_libraries(lokinet-base INTERFACE quic) if(WITH_PEERSTATS) target_compile_definitions(lokinet-base INTERFACE -DLOKINET_PEERSTATS_BACKEND) @@ -270,7 +271,7 @@ function(lokinet_link_lib libname) endfunction() # internal public linkages of components -lokinet_link_lib(lokinet-util) +lokinet_link_lib(lokinet-util lokinet-libntrup) lokinet_link_lib(lokinet-cryptography lokinet-libcrypt lokinet-util) lokinet_link_lib(lokinet-peerstats lokinet-context) lokinet_link_lib(lokinet-consensus lokinet-context) From 0b45024883cb529a9819c70c99a4d8e7105e26c1 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Tue, 17 Oct 2023 17:42:38 -0300 Subject: [PATCH 056/312] Remove router nickname I don't think Kee needs it anymore. --- llarp/config/config.cpp | 2 +- llarp/config/config.hpp | 1 - llarp/router/router.cpp | 1 - llarp/router_contact.cpp | 47 ---------------------------------------- llarp/router_contact.hpp | 14 +----------- 5 files changed, 2 insertions(+), 63 deletions(-) diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index 4402fcb656..515fd7246e 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -110,7 +110,7 @@ namespace llarp m_maxConnectedRouters = arg; }); - conf.defineOption("router", "nickname", Hidden, AssignmentAcceptor(m_nickname)); + conf.defineOption("router", "nickname", Deprecated); conf.defineOption( "router", diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index af4f63ed86..b53206f85c 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -61,7 +61,6 @@ namespace llarp size_t m_maxConnectedRouters = 0; std::string m_netId; - std::string m_nickname; fs::path m_dataDir; diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index fd21487b52..6e82694cd6 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -635,7 +635,6 @@ namespace llarp } // Router config - router_contact.SetNick(conf.router.m_nickname); _link_manager.max_connected_routers = conf.router.m_maxConnectedRouters; _link_manager.min_connected_routers = conf.router.m_minConnectedRouters; diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index cc89190de8..b740028d32 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -153,11 +153,6 @@ namespace llarp btdp.append("a", addr.to_string()); btdp.append("i", netID.ToView()); btdp.append("k", pubkey.bt_encode()); - - auto n = Nick(); - if (not n.empty()) - btdp.append("n", n); - btdp.append("p", enckey.ToView()); btdp.append("r", routerVersion); @@ -178,7 +173,6 @@ namespace llarp RouterContact::Clear() { signature.Zero(); - nickname.Zero(); enckey.Zero(); pubkey.Zero(); routerVersion = std::optional{}; @@ -196,10 +190,6 @@ namespace llarp {"identity", pubkey.ToString()}, {"address", addr.to_string()}}; - if (HasNick()) - { - obj["nickname"] = Nick(); - } if (routerVersion) { obj["routerVersion"] = routerVersion->ToString(); @@ -308,22 +298,6 @@ namespace llarp return true; } - if (key.startswith("n")) - { - llarp_buffer_t strbuf; - if (!bencode_read_string(buf, &strbuf)) - { - return false; - } - if (strbuf.sz > llarp::AlignedBuffer<(32)>::size()) - { - return false; - } - nickname.Zero(); - std::copy(strbuf.base, strbuf.base + strbuf.sz, nickname.begin()); - return true; - } - if (not BEncodeMaybeReadDictList("s", srvRecords, read, key, buf)) return false; @@ -355,20 +329,6 @@ namespace llarp return addr.is_addressable(); } - bool - RouterContact::HasNick() const - { - return nickname[0] != 0; - } - - void - RouterContact::SetNick(std::string_view nick) - { - nickname.Zero(); - std::copy( - nick.begin(), nick.begin() + std::min(nick.size(), nickname.size()), nickname.begin()); - } - bool RouterContact::IsExpired(llarp_time_t now) const { @@ -394,13 +354,6 @@ namespace llarp return TimeUntilExpires(now) <= dlt; } - std::string - RouterContact::Nick() const - { - auto term = std::find(nickname.begin(), nickname.end(), '\0'); - return std::string(nickname.begin(), term); - } - bool RouterContact::Sign(const SecretKey& secretkey) { diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index d389476159..6775362632 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -18,7 +18,6 @@ #include #define MAX_RC_SIZE (1024) -#define NICKLEN (32) namespace oxenc { @@ -87,8 +86,6 @@ namespace llarp llarp::PubKey pubkey; // signature llarp::Signature signature; - /// node nickname, yw kee - llarp::AlignedBuffer nickname; llarp_time_t last_updated = 0s; uint64_t version = llarp::constants::proto_version; @@ -134,7 +131,7 @@ namespace llarp operator==(const RouterContact& other) const { return addr == other.addr && enckey == other.enckey && pubkey == other.pubkey - && signature == other.signature && nickname == other.nickname + && signature == other.signature && last_updated == other.last_updated && netID == other.netID; } @@ -165,18 +162,9 @@ namespace llarp bool decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf); - bool - HasNick() const; - - std::string - Nick() const; - bool IsPublicRouter() const; - void - SetNick(std::string_view nick); - bool Verify(llarp_time_t now, bool allowExpired = true) const; From 570e87e1d4ef6e29da006e7d25ccb750c84b01c7 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Tue, 17 Oct 2023 17:54:02 -0300 Subject: [PATCH 057/312] Remove optional relay whitelist disabling Whitelisting is now always-on for relays. Disabling the option is never used and is unsupported/unmaintained (it was, in theory, to allow lokinet as a separate usage in a non-service-node relay mode, i.e. on a completely separate network). Confusingly, the option was enabled by the `[lokid]:enabled` config parameter. --- llarp/config/config.cpp | 10 +---- llarp/config/config.hpp | 1 - llarp/config/key_manager.cpp | 2 +- llarp/router/rc_lookup_handler.cpp | 10 ++--- llarp/router/rc_lookup_handler.hpp | 2 - llarp/router/router.cpp | 72 ++++++++++++++---------------- llarp/router/router.hpp | 6 ++- 7 files changed, 43 insertions(+), 60 deletions(-) diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index 515fd7246e..eb038c2184 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -1163,15 +1163,7 @@ namespace llarp { (void)params; - conf.defineOption( - "lokid", - "enabled", - RelayOnly, - Default{true}, - Comment{ - "Whether or not we should talk to oxend. Must be enabled for staked routers.", - }, - AssignmentAcceptor(whitelistRouters)); + conf.defineOption("lokid", "enabled", RelayOnly, Deprecated); conf.defineOption("lokid", "jsonrpc", RelayOnly, [](std::string arg) { if (arg.empty()) diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index b53206f85c..9d0e7a54c9 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -198,7 +198,6 @@ namespace llarp struct LokidConfig { - bool whitelistRouters = false; fs::path ident_keyfile; oxenmq::address lokidRPCAddr; diff --git a/llarp/config/key_manager.cpp b/llarp/config/key_manager.cpp index 8268d089fb..c1968d0a97 100644 --- a/llarp/config/key_manager.cpp +++ b/llarp/config/key_manager.cpp @@ -88,7 +88,7 @@ namespace llarp } } - if (not config.lokid.whitelistRouters) + if (not config.router.m_isRelay) { // load identity key or create if needed auto identityKeygen = [](llarp::SecretKey& key) { diff --git a/llarp/router/rc_lookup_handler.cpp b/llarp/router/rc_lookup_handler.cpp index 54ce72dcf9..d2b6f8aa11 100644 --- a/llarp/router/rc_lookup_handler.cpp +++ b/llarp/router/rc_lookup_handler.cpp @@ -151,7 +151,7 @@ namespace llarp return false; } - if (not useWhitelist) + if (not isServiceNode) return false; return router->loop()->call_get([this, remote]() { return router_greylist.count(remote); }); @@ -182,7 +182,7 @@ namespace llarp return false; } - if (not useWhitelist) + if (not isServiceNode) return true; return router_whitelist.count(rid) != 0; @@ -199,7 +199,7 @@ namespace llarp return false; } - if (not useWhitelist) + if (not isServiceNode) return true; return router_whitelist.count(rid) or router_greylist.count(rid); @@ -312,7 +312,7 @@ namespace llarp } } - if (useWhitelist) + if (isServiceNode) { static constexpr size_t LookupPerTick = 5; @@ -372,7 +372,6 @@ namespace llarp service::Context* hiddenServiceContext, const std::unordered_set& strictConnectPubkeys, const std::set& bootstrapRCList, - bool useWhitelist_arg, bool isServiceNode_arg) { contacts = c; @@ -384,7 +383,6 @@ namespace llarp bootstrap_rc_list = bootstrapRCList; link_manager = linkManager; router = &link_manager->router(); - useWhitelist = useWhitelist_arg; isServiceNode = isServiceNode_arg; for (const auto& rc : bootstrap_rc_list) diff --git a/llarp/router/rc_lookup_handler.hpp b/llarp/router/rc_lookup_handler.hpp index 1324b4c5e2..a0f5ade36f 100644 --- a/llarp/router/rc_lookup_handler.hpp +++ b/llarp/router/rc_lookup_handler.hpp @@ -112,7 +112,6 @@ namespace llarp service::Context* hiddenServiceContext, const std::unordered_set& strictConnectPubkeys, const std::set& bootstrapRCList, - bool useWhitelist_arg, bool isServiceNode_arg); std::unordered_set @@ -139,7 +138,6 @@ namespace llarp // Now that all calls are made through the event loop, any access to these // booleans is not guarded by a mutex - std::atomic useWhitelist = false; std::atomic isServiceNode = false; // whitelist = active routers diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 6e82694cd6..3d897c1852 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -253,7 +253,7 @@ namespace llarp bool Router::GetRandomGoodRouter(RouterID& router) { - if (follow_whitelist) + if (IsServiceNode()) { return _rc_lookup_handler.get_random_whitelist_router(router); } @@ -322,7 +322,7 @@ namespace llarp { _encryption = _key_manager->encryptionKey; - if (follow_whitelist) + if (IsServiceNode()) { #if defined(ANDROID) || defined(IOS) LogError("running a service node on mobile device is not possible."); @@ -404,8 +404,9 @@ namespace llarp log::debug(logcat, "Configuring router"); - follow_whitelist = conf.lokid.whitelistRouters; - if (follow_whitelist) + is_service_node = conf.router.m_isRelay; + + if (is_service_node) { rpc_addr = oxenmq::address(conf.lokid.lokidRPCAddr); _rpc_client = std::make_shared(_lmq, weak_from_this()); @@ -423,11 +424,10 @@ namespace llarp _node_db = std::move(nodedb); - is_service_node = conf.router.m_isRelay; log::debug( logcat, is_service_node ? "Running as a relay (service node)" : "Running as a client"); - if (follow_whitelist) + if (is_service_node) { _rpc_client->ConnectAsync(rpc_addr); } @@ -511,37 +511,34 @@ namespace llarp return false; } + bool + Router::have_snode_whitelist() const + { + return IsServiceNode() and _rc_lookup_handler.has_received_whitelist(); + } + bool Router::appears_decommed() const { - return IsServiceNode() and follow_whitelist and _rc_lookup_handler.has_received_whitelist() - and _rc_lookup_handler.is_grey_listed(pubkey()); + return have_snode_whitelist() and _rc_lookup_handler.is_grey_listed(pubkey()); } bool Router::appears_funded() const { - return IsServiceNode() and follow_whitelist and _rc_lookup_handler.has_received_whitelist() - and _rc_lookup_handler.is_session_allowed(pubkey()); + return have_snode_whitelist() and _rc_lookup_handler.is_session_allowed(pubkey()); } bool Router::appears_registered() const { - return IsServiceNode() and follow_whitelist and _rc_lookup_handler.has_received_whitelist() - and _rc_lookup_handler.is_registered(pubkey()); + return have_snode_whitelist() and _rc_lookup_handler.is_registered(pubkey()); } bool Router::can_test_routers() const { - if (not IsServiceNode()) - return false; - if (not follow_whitelist) - return true; - if (not _rc_lookup_handler.has_received_whitelist()) - return false; - return _rc_lookup_handler.is_session_allowed(pubkey()); + return appears_funded(); } bool @@ -766,7 +763,6 @@ namespace llarp &_hidden_service_context, strictConnectPubkeys, bootstrap_rc_list, - follow_whitelist, is_service_node); // FIXME: kludge for now, will be part of larger cleanup effort. @@ -932,8 +928,7 @@ namespace llarp const bool has_whitelist = _rc_lookup_handler.has_received_whitelist(); const bool is_snode = IsServiceNode(); const bool is_decommed = appears_decommed(); - bool should_gossip = is_snode and follow_whitelist and has_whitelist - and _rc_lookup_handler.is_session_allowed(pubkey()); + 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)) @@ -985,9 +980,8 @@ namespace llarp return false; } - // if we have a whitelist enabled and we don't - // have the whitelist yet don't remove the entry - if (follow_whitelist and not has_whitelist) + // 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); return false; @@ -1004,22 +998,22 @@ namespace llarp return false; }); - // find all deregistered relays - std::unordered_set close_peers; - - for_each_connection([this, &has_whitelist, &close_peers](link::Connection& conn) { - if (follow_whitelist && has_whitelist) - return; + if (not is_snode or not has_whitelist) + { + // find all deregistered relays + std::unordered_set close_peers; - const auto pk = conn.remote_rc.pubkey; + for_each_connection([this, &close_peers](link::Connection& conn) { + const auto& pk = conn.remote_rc.pubkey; - if (conn.remote_is_relay and not _rc_lookup_handler.is_session_allowed(pk)) - close_peers.emplace(pk); - }); + if (conn.remote_is_relay and not _rc_lookup_handler.is_session_allowed(pk)) + close_peers.insert(pk); + }); - // mark peers as de-registered - for (auto& peer : close_peers) - _link_manager.deregister_peer(std::move(peer)); + // mark peers as de-registered + for (auto& peer : close_peers) + _link_manager.deregister_peer(std::move(peer)); + } _link_manager.check_persisting_conns(now); @@ -1261,7 +1255,7 @@ namespace llarp _route_poker->start(); is_running.store(true); _started_at = now(); - if (follow_whitelist) + if (IsServiceNode()) { // do service node testing if we are in service node whitelist mode _loop->call_every(consensus::REACHABILITY_TESTING_TIMER_INTERVAL, weak_from_this(), [this] { diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 81487a6b58..87d73a62a9 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -90,8 +90,6 @@ namespace llarp bool use_file_logging = false; // our router contact RouterContact router_contact; - /// should we obey the service node whitelist? - bool follow_whitelist = false; std::shared_ptr _lmq; path::BuildLimiter _pathbuild_limiter; std::shared_ptr loop_wakeup; @@ -337,6 +335,10 @@ namespace llarp void queue_disk_io(std::function func); + /// Return true if we are operating as a service node and have received a service node whitelist + bool + have_snode_whitelist() const; + /// return true if we look like we are a decommissioned service node bool appears_decommed() const; From cb6d594a89cac8fe5d0b0618b8fdfcb633897eed Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Tue, 17 Oct 2023 18:07:16 -0300 Subject: [PATCH 058/312] Remove RC key rotation We don't have/want this anymore (and on top of that, we *never* used it in the first place and it probably didn't even work). --- llarp/router/router.cpp | 26 +------------------------- llarp/router/router.hpp | 2 +- 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 3d897c1852..1cdd46708d 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -571,39 +571,15 @@ namespace llarp } bool - Router::update_rc(bool rotateKeys) + Router::update_rc() { SecretKey nextOnionKey; RouterContact nextRC = router_contact; - if (rotateKeys) - { - CryptoManager::instance()->encryption_keygen(nextOnionKey); - std::string f = encryption_keyfile.string(); - // TODO: use disk worker - if (nextOnionKey.SaveToFile(f.c_str())) - { - nextRC.enckey = seckey_topublic(nextOnionKey); - _encryption = nextOnionKey; - } - } if (!nextRC.Sign(identity())) return false; if (!nextRC.Verify(time_now_ms(), false)) return false; router_contact = std::move(nextRC); - if (rotateKeys) - { - // TODO: libquic change - // propagate RC by renegotiating sessions - /* - ForEachPeer([](ILinkSession* s) { - if (s->RenegotiateSession()) - LogInfo("renegotiated session"); - else - LogWarn("failed to renegotiate session"); - }); - */ - } if (IsServiceNode()) return SaveRC(); return true; diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 87d73a62a9..9add6d3b2e 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -154,7 +154,7 @@ namespace llarp report_stats(); bool - update_rc(bool rotateKeys = false); + update_rc(); bool from_config(const Config& conf); From b805f55ba8ac65471b3abb78f4fbc3026dec4195 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Wed, 18 Oct 2023 12:44:37 -0300 Subject: [PATCH 059/312] Coalesce from_string/from_string_view The version taking a string_view will already be perfectly callable with a string, so just combine them into one. --- llarp/link/link_manager.cpp | 6 +++--- llarp/util/aligned.hpp | 8 +------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index d906c71dc3..73a060816d 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1210,8 +1210,8 @@ namespace llarp // extract pathIDs and check if zero or used auto& hop_info = hop->info; - hop_info.txID.from_string_view(tx_id); - hop_info.rxID.from_string_view(rx_id); + hop_info.txID.from_string(tx_id); + hop_info.rxID.from_string(rx_id); if (hop_info.txID.IsZero() || hop_info.rxID.IsZero()) { @@ -1220,7 +1220,7 @@ namespace llarp return; } - hop_info.upstream.from_string_view(upstream); + hop_info.upstream.from_string(upstream); // TODO: need downstream (above), and also the whole transit hop container is garbage. // namely the PathID uniqueness checking uses the PathIDs and upstream/downstream diff --git a/llarp/util/aligned.hpp b/llarp/util/aligned.hpp index 302279787a..b28199d19d 100644 --- a/llarp/util/aligned.hpp +++ b/llarp/util/aligned.hpp @@ -242,7 +242,7 @@ namespace llarp } bool - from_string_view(std::string_view b) + from_string(std::string_view b) { if (b.size() != sz) { @@ -254,12 +254,6 @@ namespace llarp return true; } - bool - from_string(std::string b) - { - return from_string_view(b); - } - bool bt_encode(llarp_buffer_t* buf) const { From 5441e27fa4eb665a01b1a69cc5c1f7811b016fc8 Mon Sep 17 00:00:00 2001 From: Thomas Winget Date: Mon, 16 Oct 2023 22:06:02 -0400 Subject: [PATCH 060/312] implement sending "path control" (onioned control) message TODO: handle at transit hop, handle at terminal hop, create and handle responses --- llarp/path/path.cpp | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 169b9e36a9..09979af635 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -107,8 +107,33 @@ namespace llarp::path Path::send_path_control_message( std::string method, std::string body, std::function func) { + oxenc::bt_dict_producer btdp; + btdp.append("METHOD", method); + btdp.append("BODY", body); + auto payload = std::move(btdp).str(); + auto* payload_ptr = reinterpret_cast(payload.data()); + + // TODO: old impl padded messages if smaller than a certain size; do we still want to? + + auto crypto = CryptoManager::instance(); + + TunnelNonce nonce; + outer_nonce.Randomize(); + for (const auto& hop : hops) + { + // do a round of chacha for each hop and mutate the nonce with that hop's nonce + CryptoManager::instance()->xchacha20(payload_ptr, hop.shared, nonce); + nonce ^= hop.nonceXOR; + } + + oxenc::bt_dict_producer outer_dict; + outer_dict.append("PATHID", TXID().ToView()); + outer_dict.append("NONCE", nonce.ToView()); + outer_dict.append("PAYLOAD", payload); + + return router.send_control_message( - upstream(), std::move(method), std::move(body), std::move(func)); + upstream(), "path_control", std::move(outer_dict.str()), std::move(func)); } bool From cc08c7cdaab8698f19b7098789dec99436778413 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Mon, 16 Oct 2023 11:21:24 -0700 Subject: [PATCH 061/312] initial commit for next PR --- llarp/handlers/tun.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index ad4f902319..54060d28c2 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -712,7 +712,7 @@ namespace llarp::handlers } catch (...) { - log::warning(log_cat, "Failed to parse find name response!"); + log::warning(logcat, "Failed to parse find name response!"); throw; } @@ -790,8 +790,8 @@ namespace llarp::handlers msg.AddCNAMEReply(random.ToString(), 1); return ReplyToSNodeDNSWhenReady(random, std::make_shared(msg), isV6); } - else - msg.AddNXReply(); + + msg.AddNXReply(); } else if (is_localhost_loki(msg)) { @@ -866,7 +866,7 @@ namespace llarp::handlers } catch (...) { - log::warning(log_cat, "Failed to parse find name response!"); + log::warning(logcat, "Failed to parse find name response!"); throw; } @@ -874,7 +874,7 @@ namespace llarp::handlers } else { - log::warning(log_cat, "{} (ONS name: {}) not resolved", name, ons_name); + log::warning(logcat, "{} (ONS name: {}) not resolved", name, ons_name); msg->AddNXReply(); reply(*msg); } From 6338f3b3cd4ab39b719f5f0e7e6341de2e24d0f9 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Tue, 17 Oct 2023 08:42:27 -0700 Subject: [PATCH 062/312] introset and message transmission underway - message handling through classes that inherit from PathSet - cleanups around link_manager - etc etc --- llarp/crypto/crypto.cpp | 4 +- llarp/crypto/crypto.hpp | 2 +- llarp/dht/explorenetworkjob.cpp | 1 - llarp/exit/session.cpp | 31 ++- llarp/exit/session.hpp | 41 +-- llarp/handlers/exit.cpp | 8 +- llarp/handlers/null.hpp | 10 +- llarp/handlers/tun.cpp | 4 +- llarp/handlers/tun.hpp | 2 +- llarp/link/link_manager.cpp | 30 +- llarp/link/link_manager.hpp | 12 +- llarp/link/tunnel.cpp | 1 - llarp/messages/path.hpp | 2 +- llarp/path/path.cpp | 34 ++- llarp/path/pathbuilder.cpp | 44 ++- llarp/path/pathbuilder.hpp | 4 - llarp/path/pathset.hpp | 4 +- llarp/router/rc_lookup_handler.cpp | 5 +- llarp/router_contact.hpp | 2 +- llarp/service/endpoint.cpp | 6 - llarp/service/endpoint.hpp | 9 - llarp/service/outbound_context.cpp | 434 ++++++++++------------------- llarp/service/outbound_context.hpp | 113 ++++---- 23 files changed, 328 insertions(+), 475 deletions(-) diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index 471fa3187d..b30cd8c0e2 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -457,9 +457,9 @@ namespace llarp return crypto_sign_ed25519_seed_keypair(secret.data() + 32, secret.data(), seed.data()) != -1; } void - Crypto::randomize(const llarp_buffer_t& buff) + Crypto::randomize(uint8_t* buf, size_t len) { - randombytes((unsigned char*)buff.base, buff.sz); + randombytes(buf, len); } void diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index 25d7b2705e..a8f75a5f04 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -98,7 +98,7 @@ namespace llarp seed_to_secretkey(llarp::SecretKey&, const llarp::IdentitySecret&); /// randomize buffer void - randomize(const llarp_buffer_t&); + randomize(uint8_t* buf, size_t len); /// randomizer memory void randbytes(byte_t*, size_t); diff --git a/llarp/dht/explorenetworkjob.cpp b/llarp/dht/explorenetworkjob.cpp index 485228b3be..e0b96dd672 100644 --- a/llarp/dht/explorenetworkjob.cpp +++ b/llarp/dht/explorenetworkjob.cpp @@ -1,6 +1,5 @@ #include "explorenetworkjob.hpp" -#include #include #include diff --git a/llarp/exit/session.cpp b/llarp/exit/session.cpp index b9b5a498fd..fe6b9832ca 100644 --- a/llarp/exit/session.cpp +++ b/llarp/exit/session.cpp @@ -21,8 +21,8 @@ namespace llarp::exit : llarp::path::Builder{r, numpaths, hoplen} , exit_router{routerId} , packet_write_func{std::move(writepkt)} - , m_Counter{0} - , m_LastUse{r->now()} + , _counter{0} + , _last_use{r->now()} , m_BundleRC{false} , m_Parent{parent} { @@ -41,7 +41,7 @@ namespace llarp::exit BaseSession::ExtractStatus() const { auto obj = path::Builder::ExtractStatus(); - obj["lastExitUse"] = to_json(m_LastUse); + obj["lastExitUse"] = to_json(_last_use); auto pub = exit_key.toPublic(); obj["exitIdentity"] = pub.ToString(); obj["endpoint"] = exit_router.ToString(); @@ -80,8 +80,8 @@ namespace llarp::exit return std::vector{*maybe}; return std::nullopt; } - else - return GetHopsAlignedToForBuild(exit_router); + + return GetHopsAlignedToForBuild(exit_router); } bool @@ -204,7 +204,7 @@ namespace llarp::exit llarp::net::IPPacket pkt{buf.view_all()}; if (pkt.empty()) return false; - m_LastUse = router->now(); + _last_use = router->now(); m_Downstream.emplace(counter, pkt); return true; } @@ -231,7 +231,7 @@ namespace llarp::exit { queue.emplace_back(); queue.back().protocol = t; - return queue.back().PutBuffer(llarp_buffer_t{pkt}, m_Counter++); + return queue.back().PutBuffer(llarp_buffer_t{pkt}, _counter++); } auto& back = queue.back(); // pack to nearest N @@ -239,10 +239,10 @@ namespace llarp::exit { queue.emplace_back(); queue.back().protocol = t; - return queue.back().PutBuffer(llarp_buffer_t{pkt}, m_Counter++); + return queue.back().PutBuffer(llarp_buffer_t{pkt}, _counter++); } back.protocol = t; - return back.PutBuffer(llarp_buffer_t{pkt}, m_Counter++); + return back.PutBuffer(llarp_buffer_t{pkt}, _counter++); } bool @@ -257,7 +257,7 @@ namespace llarp::exit bool BaseSession::IsExpired(llarp_time_t now) const { - return now > m_LastUse && now - m_LastUse > LifeSpan; + return now > _last_use && now - _last_use > LifeSpan; } bool @@ -296,6 +296,7 @@ namespace llarp::exit for (auto& [i, queue] : m_Upstream) queue.clear(); m_Upstream.clear(); + if (numHops == 1) { auto r = router; @@ -374,23 +375,25 @@ namespace llarp::exit } void - SNodeSession::SendPacketToRemote(const llarp_buffer_t& buf, service::ProtocolType t) + ExitSession::send_packet_to_remote(std::string buf) { net::IPPacket pkt{buf.view_all()}; if (pkt.empty()) return; pkt.ZeroAddresses(); - QueueUpstreamTraffic(std::move(pkt), llarp::routing::EXIT_PAD_SIZE, t); + + // QueueUpstreamTraffic(std::move(pkt), llarp::routing::EXIT_PAD_SIZE, t); } void - ExitSession::SendPacketToRemote(const llarp_buffer_t& buf, service::ProtocolType t) + SNodeSession::send_packet_to_remote(std::string buf) { net::IPPacket pkt{buf.view_all()}; if (pkt.empty()) return; pkt.ZeroSourceAddress(); - QueueUpstreamTraffic(std::move(pkt), llarp::routing::EXIT_PAD_SIZE, t); + + // QueueUpstreamTraffic(std::move(pkt), llarp::routing::EXIT_PAD_SIZE, t); } } // namespace llarp::exit diff --git a/llarp/exit/session.hpp b/llarp/exit/session.hpp index c55b63185a..1c9810b0ce 100644 --- a/llarp/exit/session.hpp +++ b/llarp/exit/session.hpp @@ -61,12 +61,6 @@ namespace llarp util::StatusObject ExtractStatus() const; - bool - ShouldBundleRC() const override - { - return m_BundleRC; - } - void ResetInternalState() override; @@ -140,9 +134,6 @@ namespace llarp llarp::SecretKey exit_key; std::function packet_write_func; - virtual void - PopulateRequest(llarp::routing::ObtainExitMessage& msg) const = 0; - bool HandleTrafficDrop(llarp::path::Path_ptr p, const llarp::PathID_t& path, uint64_t s); @@ -159,8 +150,6 @@ namespace llarp private: std::set snode_blacklist; - std::map> m_Upstream; - PathID_t m_CurrentPath; using DownstreamPkt = std::pair; @@ -174,12 +163,8 @@ namespace llarp } }; - using DownstreamTrafficQueue_t = - std::priority_queue, DownstreamPktSorter>; - DownstreamTrafficQueue_t m_Downstream; - - uint64_t m_Counter; - llarp_time_t m_LastUse; + uint64_t _counter; + llarp_time_t _last_use; std::vector m_PendingCallbacks; const bool m_BundleRC; @@ -207,16 +192,7 @@ namespace llarp Name() const override; void - SendPacketToRemote(const llarp_buffer_t& pkt, service::ProtocolType t) override; - - protected: - void - PopulateRequest(llarp::routing::ObtainExitMessage& msg) const override - { - // TODO: set expiration time - // msg.address_lifetime = 0; - msg.flag = 1; - } + send_packet_to_remote(std::string buf) override; }; struct SNodeSession final : public BaseSession @@ -236,16 +212,7 @@ namespace llarp Name() const override; void - SendPacketToRemote(const llarp_buffer_t& pkt, service::ProtocolType t) override; - - protected: - void - PopulateRequest(llarp::routing::ObtainExitMessage& msg) const override - { - // TODO: set expiration time - // msg.address_lifetime = 0; - msg.flag = 0; - } + send_packet_to_remote(std::string buf) override; }; } // namespace exit diff --git a/llarp/handlers/exit.cpp b/llarp/handlers/exit.cpp index 9c8ee2cb5f..0b1ec7a728 100644 --- a/llarp/handlers/exit.cpp +++ b/llarp/handlers/exit.cpp @@ -114,10 +114,10 @@ namespace llarp::handlers if (not router->PathToRouterAllowed(*rid)) return false; - ObtainSNodeSession(*rid, [pkt = payload.copy(), type](auto session) mutable { + ObtainSNodeSession(*rid, [pkt = std::move(payload)](auto session) mutable { if (session and session->IsReady()) { - session->SendPacketToRemote(std::move(pkt), type); + session->send_packet_to_remote(std::move(pkt)); } }); } @@ -381,7 +381,7 @@ namespace llarp::handlers maybe_pk = itr->second; } - auto buf = const_cast(top).steal(); + auto buf = const_cast(top); inet_to_network.pop(); // we have no session for public key so drop if (not maybe_pk) @@ -398,7 +398,7 @@ namespace llarp::handlers auto itr = snode_sessions.find(pk); if (itr != snode_sessions.end()) { - itr->second->SendPacketToRemote(std::move(buf), service::ProtocolType::TrafficV4); + itr->second->send_packet_to_remote(buf.to_string()); // we are in a while loop continue; } diff --git a/llarp/handlers/null.hpp b/llarp/handlers/null.hpp index 4d5202fe02..1d216456a2 100644 --- a/llarp/handlers/null.hpp +++ b/llarp/handlers/null.hpp @@ -1,8 +1,8 @@ #pragma once +#include #include #include -#include #include #include #include @@ -25,7 +25,7 @@ namespace llarp::handlers r->loop()->add_ticker([this] { Pump(Now()); }); } - virtual bool + bool HandleInboundPacket( const service::ConvoTag tag, const llarp_buffer_t& buf, @@ -74,6 +74,9 @@ namespace llarp::handlers return true; } + void + send_packet_to_remote(std::string) override {}; + std::string GetIfName() const override { @@ -98,9 +101,6 @@ namespace llarp::handlers return false; } - void - SendPacketToRemote(const llarp_buffer_t&, service::ProtocolType) override{}; - huint128_t ObtainIPForAddr(std::variant) override { diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 54060d28c2..c313a235e1 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -1254,12 +1254,12 @@ namespace llarp::handlers EnsurePathToService( addr, - [pkt, extra_cb, this](service::Address addr, service::OutboundContext* ctx) { + [pkt, extra_cb, this](service::Address addr, service::OutboundContext* ctx) mutable { if (ctx) { if (extra_cb) extra_cb(); - ctx->SendPacketToRemote(pkt.ConstBuffer(), service::ProtocolType::Exit); + ctx->send_packet_to_remote(pkt.to_string()); router()->TriggerPump(); return; } diff --git a/llarp/handlers/tun.hpp b/llarp/handlers/tun.hpp index 3513735678..89d07f1c9a 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -73,7 +73,7 @@ namespace llarp::handlers Configure(const NetworkConfig& conf, const DnsConfig& dnsConf) override; void - SendPacketToRemote(const llarp_buffer_t&, service::ProtocolType) override{}; + send_packet_to_remote(std::string) override{}; std::string GetIfName() const override; diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 73a060816d..610a245150 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -512,12 +512,6 @@ namespace llarp // TODO: this } - std::string - LinkManager::serialize_response(oxenc::bt_dict supplement) - { - return oxenc::bt_serialize(supplement); - } - void LinkManager::handle_find_name(oxen::quic::message m) { @@ -537,8 +531,7 @@ namespace llarp _router.rpc_client()->lookup_ons_hash( name_hash, - [this, - msg = std::move(m)]([[maybe_unused]] std::optional maybe) mutable { + [msg = std::move(m)]([[maybe_unused]] std::optional maybe) mutable { if (maybe) msg.respond(serialize_response({{"NAME", maybe->ciphertext}})); else @@ -1644,4 +1637,25 @@ namespace llarp return; } } + + void + LinkManager::handle_path_control(oxen::quic::message m) + { + if (m.timed_out) + { + log::info(link_cat, "Path control message timed out!"); + return; + } + + try + { + + } + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + return; + } + } + } // namespace llarp diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 03b5aca3c9..c7f11e01c7 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -28,6 +28,12 @@ namespace llarp { struct LinkManager; + inline std::string + serialize_response(oxenc::bt_dict supplement = {}) + { + return oxenc::bt_serialize(supplement); + } + namespace link { struct Connection; @@ -316,6 +322,9 @@ namespace llarp {"obtain_exit", &LinkManager::handle_obtain_exit}, {"close_exit", &LinkManager::handle_close_exit}}; + // Path relaying + void handle_path_control(oxen::quic::message); + // DHT responses void handle_find_name_response(oxen::quic::message); void handle_find_intro_response(oxen::quic::message); @@ -344,9 +353,6 @@ namespace llarp {"obtain_exit", &LinkManager::handle_obtain_exit_response}, {"close_exit", &LinkManager::handle_close_exit_response}}; - std::string - serialize_response(oxenc::bt_dict supplement = {}); - public: // Public response functions and error handling functions invoked elsehwere. These take // r-value references s.t. that message is taken out of calling scope diff --git a/llarp/link/tunnel.cpp b/llarp/link/tunnel.cpp index 3e85a08368..0c5fa5bb46 100644 --- a/llarp/link/tunnel.cpp +++ b/llarp/link/tunnel.cpp @@ -2,7 +2,6 @@ #include #include #include -#include "stream.hpp" #include #include #include diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index f2e60c424b..c12e7930a9 100644 --- a/llarp/messages/path.hpp +++ b/llarp/messages/path.hpp @@ -108,8 +108,8 @@ namespace llarp oxenc::bt_dict_producer btdp; - btdp.append("HASH", hash); btdp.append("FRAME", hashed_data); + btdp.append("HASH", hash); return std::move(btdp).str(); } diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 09979af635..9884532e10 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -107,33 +107,41 @@ namespace llarp::path Path::send_path_control_message( std::string method, std::string body, std::function func) { - oxenc::bt_dict_producer btdp; - btdp.append("METHOD", method); - btdp.append("BODY", body); - auto payload = std::move(btdp).str(); - auto* payload_ptr = reinterpret_cast(payload.data()); + std::string payload; - // TODO: old impl padded messages if smaller than a certain size; do we still want to? - - auto crypto = CryptoManager::instance(); + { + oxenc::bt_dict_producer btdp; + btdp.append("BODY", body); + btdp.append("METHOD", method); + payload = std::move(btdp).str(); + } TunnelNonce nonce; - outer_nonce.Randomize(); + nonce.Randomize(); + for (const auto& hop : hops) { // do a round of chacha for each hop and mutate the nonce with that hop's nonce - CryptoManager::instance()->xchacha20(payload_ptr, hop.shared, nonce); + CryptoManager::instance()->xchacha20( + reinterpret_cast(payload.data()), payload.size(), hop.shared, nonce); + nonce ^= hop.nonceXOR; } oxenc::bt_dict_producer outer_dict; - outer_dict.append("PATHID", TXID().ToView()); outer_dict.append("NONCE", nonce.ToView()); + outer_dict.append("PATHID", TXID().ToView()); outer_dict.append("PAYLOAD", payload); - return router.send_control_message( - upstream(), "path_control", std::move(outer_dict.str()), std::move(func)); + upstream(), + "path_control", + std::move(outer_dict).str(), + [response_cb = std::move(func)](oxen::quic::message m) { + { + // do path hop logic here + } + }); } bool diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index 7123ffd8fd..c3243893cf 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -20,7 +20,7 @@ namespace llarp { namespace { - auto log_path = log::Cat("path"); + auto path_cat = log::Cat("path"); } namespace path @@ -326,7 +326,7 @@ namespace llarp const auto maybe = SelectFirstHop(exclude); if (not maybe.has_value()) { - log::warning(log_path, "{} has no first hop candidate", Name()); + log::warning(path_cat, "{} has no first hop candidate", Name()); return std::nullopt; } hops.emplace_back(*maybe); @@ -465,22 +465,44 @@ namespace llarp router->path_context().AddOwnPath(self, path); PathBuildStarted(path); - auto response_cb = [self](oxen::quic::message) { - // TODO: this (replaces handling LRSM, which also needs replacing) - - // TODO: Talk to Tom about why are we using it as a response callback? - // Do you mean TransitHop::HandleLRSM? + // TODO: + // Path build fail and success are handled poorly at best and changing how we + // handle these responses as well as how we store and use Paths as a whole might + // be worth doing sooner rather than later. Leaving some TODOs below where fail + // and success live. + auto response_cb = [self](oxen::quic::message m) { + if (m) + { + std::string status; + + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + status = btdc.require("STATUS"); + } + catch (...) + { + log::warning(path_cat, "Error: Failed to parse path build response!", status); + m.respond(serialize_response({{"STATUS", "EXCEPTION"}}), true); + throw; + } + + // TODO: success logic + } + else + { + log::warning(path_cat, "Path build request returned failure {}"); + // TODO: failure logic + } }; if (not router->send_control_message( path->upstream(), "path_build", std::move(frames).str(), std::move(response_cb))) { - log::warning(log_path, "Error sending path_build control message"); + log::warning(path_cat, "Error sending path_build control message"); + // TODO: inform failure (what this means needs revisiting, badly) path->EnterState(path::ePathFailed, router->now()); } - - // TODO: we don't use this concept anymore? - router->persist_connection_until(path->upstream(), path->ExpireTime()); } void diff --git a/llarp/path/pathbuilder.hpp b/llarp/path/pathbuilder.hpp index c2c8548abe..1886e57d21 100644 --- a/llarp/path/pathbuilder.hpp +++ b/llarp/path/pathbuilder.hpp @@ -73,10 +73,6 @@ namespace llarp::path bool ShouldBuildMore(llarp_time_t now) const override; - /// should we bundle RCs in builds? - virtual bool - ShouldBundleRC() const = 0; - void ResetInternalState() override; diff --git a/llarp/path/pathset.hpp b/llarp/path/pathset.hpp index cfd8c1c748..adb2ca1120 100644 --- a/llarp/path/pathset.hpp +++ b/llarp/path/pathset.hpp @@ -140,7 +140,7 @@ namespace llarp virtual void HandlePathBuildFailedAt(Path_ptr path, RouterID hop); - virtual void + void PathBuildStarted(Path_ptr path); /// a path died now what? @@ -249,7 +249,7 @@ namespace llarp BuildOneAlignedTo(const RouterID endpoint) = 0; virtual void - SendPacketToRemote(const llarp_buffer_t& pkt, service::ProtocolType t) = 0; + send_packet_to_remote(std::string buf) = 0; virtual std::optional> GetHopsForBuild() = 0; diff --git a/llarp/router/rc_lookup_handler.cpp b/llarp/router/rc_lookup_handler.cpp index d2b6f8aa11..d40a8e59c6 100644 --- a/llarp/router/rc_lookup_handler.cpp +++ b/llarp/router/rc_lookup_handler.cpp @@ -110,7 +110,7 @@ namespace llarp else { r.node_db()->put_rc_if_newer(result); - r.connect_to(result); + // r.connect_to(result); } } else @@ -306,7 +306,8 @@ namespace llarp { for (const auto& rc : bootstrap_rc_list) { - LogInfo("Doing explore via bootstrap node: ", RouterID(rc.pubkey)); + log::info(link_cat, "Doing explore via bootstrap node: {}", RouterID(rc.pubkey)); + // TODO: replace this concept // dht->ExploreNetworkVia(dht::Key_t{rc.pubkey}); } diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index 6775362632..a1c7e450c8 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -64,7 +64,7 @@ namespace llarp { /// for unit tests static bool BlockBogons; - + static llarp_time_t Lifetime; static llarp_time_t UpdateInterval; static llarp_time_t StaleInsertionAge; diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 70faaeef9d..67a9300be8 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -779,12 +779,6 @@ namespace llarp::service return path::Builder::GetHopsAlignedToForBuild(endpoint, SnodeBlacklist()); } - void - Endpoint::PathBuildStarted(path::Path_ptr path) - { - path::Builder::PathBuildStarted(path); - } - constexpr auto MaxOutboundContextPerRemote = 1; void diff --git a/llarp/service/endpoint.hpp b/llarp/service/endpoint.hpp index c2ea6c8628..9051566bfd 100644 --- a/llarp/service/endpoint.hpp +++ b/llarp/service/endpoint.hpp @@ -304,12 +304,6 @@ namespace llarp /// this MUST be called if you want to call EnsurePathTo on the given address void MarkAddressOutbound(service::Address) override; - bool - ShouldBundleRC() const override - { - return false; - } - void BlacklistSNode(const RouterID snode) override; @@ -426,9 +420,6 @@ namespace llarp std::optional> GetHopsForBuildWithEndpoint(RouterID endpoint); - void - PathBuildStarted(path::Path_ptr path) override; - void AsyncProcessAuthMessage( std::shared_ptr msg, std::function hook); diff --git a/llarp/service/outbound_context.cpp b/llarp/service/outbound_context.cpp index 18a920c1ea..e9077956bb 100644 --- a/llarp/service/outbound_context.cpp +++ b/llarp/service/outbound_context.cpp @@ -17,46 +17,27 @@ namespace llarp::service bool OutboundContext::Stop() { - markedBad = true; + marked_bad = true; return path::Builder::Stop(); } bool - OutboundContext::IsDone(llarp_time_t now) const + OutboundContext::IsDone(std::chrono::milliseconds now) const { (void)now; return AvailablePaths(path::ePathRoleAny) == 0 && ShouldRemove(); } - bool - OutboundContext::ShouldBundleRC() const - { - return service_endpoint->ShouldBundleRC(); - } - - bool - OutboundContext::HandleDataDrop(path::Path_ptr p, const PathID_t& dst, uint64_t seq) - { - // pick another intro - if (dst == remoteIntro.path_id && remoteIntro.router == p->Endpoint()) - { - LogWarn(Name(), " message ", seq, " dropped by endpoint ", p->Endpoint(), " via ", dst); - markedBad = remoteIntro.IsExpired(Now()); - MarkCurrentIntroBad(Now()); - ShiftIntroRouter(p->Endpoint()); - UpdateIntroSet(); - } - return true; - } - constexpr auto OutboundContextNumPaths = 4; OutboundContext::OutboundContext(const IntroSet& introset, Endpoint* parent) : path::Builder{parent->router(), OutboundContextNumPaths, parent->numHops} - , SendContext{introset.address_keys, {}, this, parent} - , location{introset.address_keys.Addr().ToKey()} - , addr{introset.address_keys.Addr()} - , currentIntroSet{introset} + , ep{*parent} + , current_intro{introset} + , location{current_intro.address_keys.Addr().ToKey()} + , addr{current_intro.address_keys.Addr()} + , remote_identity{current_intro.address_keys} + , created_at{ep.Now()} { assert(not introset.intros.empty()); @@ -69,29 +50,29 @@ namespace llarp::service CSRNG rng{}; it += std::uniform_int_distribution{0, introset.intros.size() - 1}(rng); } - m_NextIntro = *it; - currentConvoTag.Randomize(); - lastShift = Now(); + next_intro = *it; + current_tag.Randomize(); + last_shift = Now(); // add send and connect timeouts to the parent endpoints path alignment timeout // this will make it so that there is less of a chance for timing races - sendTimeout += parent->PathAlignmentTimeout(); - connectTimeout += parent->PathAlignmentTimeout(); + send_timeout += parent->PathAlignmentTimeout(); + connect_timeout += parent->PathAlignmentTimeout(); } OutboundContext::~OutboundContext() = default; /// actually swap intros void - OutboundContext::SwapIntros() + OutboundContext::swap_intros() { - if (remoteIntro != m_NextIntro) + if (remote_intro != next_intro) { - remoteIntro = m_NextIntro; - service_endpoint->PutSenderFor(currentConvoTag, currentIntroSet.address_keys, false); - service_endpoint->PutIntroFor(currentConvoTag, remoteIntro); - ShiftIntroRouter(m_NextIntro.router); + remote_intro = next_intro; + ep.PutSenderFor(current_tag, current_intro.address_keys, false); + ep.PutIntroFor(current_tag, remote_intro); + ShiftIntroRouter(next_intro.router); // if we have not made a handshake to the remote endpoint do so - if (not IntroGenerated()) + if (not generated_intro) { KeepAlive(); } @@ -109,10 +90,10 @@ namespace llarp::service const Address&, std::optional foundIntro, const RouterID& endpoint, - llarp_time_t, + std::chrono::milliseconds, uint64_t relayOrder) { - if (markedBad) + if (marked_bad) return true; updatingIntroSet = false; if (foundIntro) @@ -122,25 +103,25 @@ namespace llarp::service LogWarn(Name(), " got introset with zero timestamp: ", *foundIntro); return true; } - if (currentIntroSet.time_signed > foundIntro->time_signed) + if (current_intro.time_signed > foundIntro->time_signed) { LogInfo("introset is old, dropping"); return true; } - const llarp_time_t now = Now(); + const std::chrono::milliseconds now = Now(); if (foundIntro->IsExpired(now)) { LogError("got expired introset from lookup from ", endpoint); return true; } - currentIntroSet = *foundIntro; + current_intro = *foundIntro; ShiftIntroRouter(RouterID{}); } else if (relayOrder > 0) { - ++m_LookupFails; - LogWarn(Name(), " failed to look up introset, fails=", m_LookupFails); + ++lookup_fails; + LogWarn(Name(), " failed to look up introset, fails=", lookup_fails); } return true; } @@ -148,11 +129,11 @@ namespace llarp::service bool OutboundContext::ReadyToSend() const { - if (markedBad) + if (marked_bad) return false; - if (remoteIntro.router.IsZero()) + if (remote_intro.router.IsZero()) return false; - return IntroSent() and GetPathByRouter(remoteIntro.router); + return sent_intro and GetPathByRouter(remote_intro.router); } void @@ -160,7 +141,7 @@ namespace llarp::service { const auto now = Now(); Introduction selectedIntro{}; - for (const auto& intro : currentIntroSet.intros) + for (const auto& intro : current_intro.intros) { if (intro.expiry > selectedIntro.expiry and intro.router != r) { @@ -169,8 +150,8 @@ namespace llarp::service } if (selectedIntro.router.IsZero() || selectedIntro.ExpiresSoon(now)) return; - m_NextIntro = selectedIntro; - lastShift = now; + next_intro = selectedIntro; + last_shift = now; } void @@ -195,86 +176,86 @@ namespace llarp::service OutboundContext::HandlePathBuilt(path::Path_ptr p) { path::Builder::HandlePathBuilt(p); - p->SetDataHandler([self = weak_from_this()](auto path, auto frame) { - if (auto ptr = self.lock()) - return ptr->HandleHiddenServiceFrame(path, frame); - return false; - }); - p->SetDropHandler([self = weak_from_this()](auto path, auto id, auto seqno) { - if (auto ptr = self.lock()) - return ptr->HandleDataDrop(path, id, seqno); - return false; - }); - if (markedBad) + // p->SetDataHandler([self = weak_from_this()](auto path, auto frame) { + // if (auto ptr = self.lock()) + // return ptr->HandleHiddenServiceFrame(path, frame); + // return false; + // }); + // p->SetDropHandler([self = weak_from_this()](auto path, auto id, auto seqno) { + // if (auto ptr = self.lock()) + // return ptr->HandleDataDrop(path, id, seqno); + // return false; + // }); + if (marked_bad) { // ignore new path if we are marked dead LogInfo(Name(), " marked bad, ignoring new path"); p->EnterState(path::ePathIgnore, Now()); } - else if (p->Endpoint() == m_NextIntro.router) + else if (p->Endpoint() == next_intro.router) { // we now have a path to the next intro, swap intros - SwapIntros(); + swap_intros(); } } void OutboundContext::AsyncGenIntro(const llarp_buffer_t& payload, ProtocolType t) { - if (generatedIntro) + if (generated_intro) { LogWarn(Name(), " dropping packet as we are not fully handshaked right now"); return; } - if (remoteIntro.router.IsZero()) + if (remote_intro.router.IsZero()) { LogWarn(Name(), " dropping intro frame we have no intro ready yet"); return; } - auto path = GetPathByRouter(remoteIntro.router); + auto path = GetPathByRouter(remote_intro.router); if (path == nullptr) { - LogError(Name(), " has no path to ", remoteIntro.router, " when we should have had one"); + LogError(Name(), " has no path to ", remote_intro.router, " when we should have had one"); return; } auto frame = std::make_shared(); frame->clear(); auto ex = std::make_shared( - service_endpoint->Loop(), - remoteIdent, - service_endpoint->GetIdentity(), - currentIntroSet.sntru_pubkey, - remoteIntro, - service_endpoint, - currentConvoTag, + ep.Loop(), + remote_identity, + ep.GetIdentity(), + current_intro.sntru_pubkey, + remote_intro, + ep, + current_tag, t); ex->hook = [self = shared_from_this(), path](auto frame) { if (not self->Send(std::move(frame), path)) return; - self->service_endpoint->Loop()->call_later( - self->remoteIntro.latency, [self]() { self->sentIntro = true; }); + self->ep.Loop()->call_later( + self->remote_intro.latency, [self]() { self->sent_intro = true; }); }; ex->msg.PutBuffer(payload); ex->msg.introReply = path->intro; frame->path_id = ex->msg.introReply.path_id; frame->flag = 0; - generatedIntro = true; + generated_intro = true; // ensure we have a sender put for this convo tag - service_endpoint->PutSenderFor(currentConvoTag, currentIntroSet.address_keys, false); + ep.PutSenderFor(current_tag, current_intro.address_keys, false); // encrypt frame async - service_endpoint->router()->queue_work( + ep.router()->queue_work( [ex, frame] { return AsyncKeyExchange::Encrypt(ex, frame); }); - LogInfo(Name(), " send intro frame T=", currentConvoTag); + LogInfo(Name(), " send intro frame T=", current_tag); } std::string OutboundContext::Name() const { - return "OBContext:" + currentIntroSet.address_keys.Addr().ToString(); + return "OBContext:" + current_intro.address_keys.Addr().ToString(); } void @@ -282,14 +263,17 @@ namespace llarp::service { constexpr auto IntrosetUpdateInterval = 10s; const auto now = Now(); - if (updatingIntroSet or markedBad or now < m_LastIntrosetUpdateAt + IntrosetUpdateInterval) + if (updatingIntroSet or marked_bad or now < last_introset_update + IntrosetUpdateInterval) return; - LogInfo(Name(), " updating introset"); - m_LastIntrosetUpdateAt = now; + + log::info(link_cat, "{} updating introset", Name()); + last_introset_update = now; + // we want to use the parent endpoint's paths because outbound context // does not implement path::PathSet::HandleGotIntroMessage - const auto paths = GetManyPathsWithUniqueEndpoints(service_endpoint, 2, location); + const auto paths = GetManyPathsWithUniqueEndpoints(&ep, 2, location); [[maybe_unused]] uint64_t relayOrder = 0; + for ([[maybe_unused]] const auto& path : paths) { // TODO: implement this @@ -314,19 +298,17 @@ namespace llarp::service OutboundContext::ExtractStatus() const { auto obj = path::Builder::ExtractStatus(); - obj["estimatedRTT"] = to_json(estimatedRTT); - obj["currentConvoTag"] = currentConvoTag.ToHex(); - obj["remoteIntro"] = remoteIntro.ExtractStatus(); - obj["sessionCreatedAt"] = to_json(createdAt); - obj["lastGoodSend"] = to_json(lastGoodSend); - obj["lastRecv"] = to_json(m_LastInboundTraffic); - obj["lastIntrosetUpdate"] = to_json(m_LastIntrosetUpdateAt); - obj["seqno"] = sequenceNo; - obj["markedBad"] = markedBad; - obj["lastShift"] = to_json(lastShift); - obj["remoteIdentity"] = addr.ToString(); - obj["currentRemoteIntroset"] = currentIntroSet.ExtractStatus(); - obj["nextIntro"] = m_NextIntro.ExtractStatus(); + obj["current_tag"] = current_tag.ToHex(); + obj["remote_intro"] = remote_intro.ExtractStatus(); + obj["session_created"] = to_json(created_at); + obj["last_send"] = to_json(last_send); + obj["lastRecv"] = to_json(last_inbound_traffic); + obj["lastIntrosetUpdate"] = to_json(last_introset_update); + obj["marked_bad"] = marked_bad; + obj["last_shift"] = to_json(last_shift); + obj["remote_identityity"] = addr.ToString(); + obj["currentRemote_introset"] = current_intro.ExtractStatus(); + obj["nextIntro"] = next_intro.ExtractStatus(); obj["readyToSend"] = ReadyToSend(); return obj; } @@ -334,43 +316,45 @@ namespace llarp::service void OutboundContext::KeepAlive() { - std::array tmp; - llarp_buffer_t buf{tmp}; - CryptoManager::instance()->randomize(buf); + ustring buf(64, '\0'); + + CryptoManager::instance()->randomize(buf.data(), buf.size()); + SendPacketToRemote(buf, ProtocolType::Control); - m_LastKeepAliveAt = Now(); + + last_keep_alive = Now(); } bool - OutboundContext::Pump(llarp_time_t now) + OutboundContext::Pump(std::chrono::milliseconds now) { - if (ReadyToSend() and remoteIntro.router.IsZero()) + if (ReadyToSend() and remote_intro.router.IsZero()) { - SwapIntros(); + swap_intros(); } if (ReadyToSend()) { // if we dont have a cached session key after sending intro we are in a fugged state so // expunge SharedSecret discardme; - if (not service_endpoint->GetCachedSessionKeyFor(currentConvoTag, discardme)) + if (not ep.GetCachedSessionKeyFor(current_tag, discardme)) { LogError(Name(), " no cached key after sending intro, we are in a fugged state, oh no"); return true; } } - if (m_GotInboundTraffic and m_LastInboundTraffic + sendTimeout <= now) + if (got_inbound_traffic and last_inbound_traffic + send_timeout <= now) { // timeout on other side UpdateIntroSet(); MarkCurrentIntroBad(now); - ShiftIntroRouter(remoteIntro.router); + ShiftIntroRouter(remote_intro.router); } // check for stale intros // update the introset if we think we need to - if (currentIntroSet.HasStaleIntros(now, path::INTRO_PATH_SPREAD) - or remoteIntro.ExpiresSoon(now, path::INTRO_PATH_SPREAD)) + if (current_intro.HasStaleIntros(now, path::INTRO_PATH_SPREAD) + or remote_intro.ExpiresSoon(now, path::INTRO_PATH_SPREAD)) { UpdateIntroSet(); ShiftIntroduction(false); @@ -378,11 +362,11 @@ namespace llarp::service if (ReadyToSend()) { - if (not remoteIntro.router.IsZero() and not GetPathByRouter(remoteIntro.router)) + if (not remote_intro.router.IsZero() and not GetPathByRouter(remote_intro.router)) { // pick another good intro if we have no path on our current intro std::vector otherIntros; - ForEachPath([now, router = remoteIntro.router, &otherIntros](auto path) { + ForEachPath([now, router = remote_intro.router, &otherIntros](auto path) { if (path and path->IsReady() and path->Endpoint() != router and not path->ExpiresSoon(now, path::INTRO_PATH_SPREAD)) { @@ -392,33 +376,30 @@ namespace llarp::service if (not otherIntros.empty()) { std::shuffle(otherIntros.begin(), otherIntros.end(), CSRNG{}); - remoteIntro = otherIntros[0]; + remote_intro = otherIntros[0]; } } } // lookup router in intro if set and unknown - if (not m_NextIntro.router.IsZero()) - service_endpoint->EnsureRouterIsKnown(m_NextIntro.router); + if (not next_intro.router.IsZero()) + ep.EnsureRouterIsKnown(next_intro.router); - if (ReadyToSend() and not m_ReadyHooks.empty()) + if (ReadyToSend() and not ready_hooks.empty()) { - const auto path = GetPathByRouter(remoteIntro.router); + const auto path = GetPathByRouter(remote_intro.router); if (not path) { - LogWarn(Name(), " ready but no path to ", remoteIntro.router, " ???"); + LogWarn(Name(), " ready but no path to ", remote_intro.router, " ???"); return true; } - for (const auto& hook : m_ReadyHooks) - hook(this); - m_ReadyHooks.clear(); } - const auto timeout = std::max(lastGoodSend, m_LastInboundTraffic); - if (lastGoodSend > 0s and now >= timeout + (sendTimeout / 2)) + const auto timeout = std::max(last_send, last_inbound_traffic); + if (last_send > 0s and now >= timeout + (send_timeout / 2)) { // send a keep alive to keep this session alive KeepAlive(); - if (markedBad) + if (marked_bad) { LogWarn(Name(), " keepalive timeout hit"); return true; @@ -426,14 +407,14 @@ namespace llarp::service } // check for half open state where we can send but we get nothing back - if (m_LastInboundTraffic == 0s and now - createdAt > connectTimeout) + if (last_inbound_traffic == 0s and now - created_at > connect_timeout) { LogWarn(Name(), " half open state, we can send but we got nothing back"); return true; } // if we are dead return true so we are removed - const bool removeIt = timeout > 0s ? (now >= timeout && now - timeout > sendTimeout) - : (now >= createdAt && now - createdAt > connectTimeout); + const bool removeIt = timeout > 0s ? (now >= timeout && now - timeout > send_timeout) + : (now >= created_at && now - created_at > connect_timeout); if (removeIt) { LogInfo(Name(), " session is stale"); @@ -442,42 +423,22 @@ namespace llarp::service return false; } - void - OutboundContext::AddReadyHook(std::function hook, llarp_time_t timeout) - { - if (ReadyToSend()) - { - hook(this); - return; - } - if (m_ReadyHooks.empty()) - { - router->loop()->call_later(timeout, [this]() { - LogWarn(Name(), " did not obtain session in time"); - for (const auto& hook : m_ReadyHooks) - hook(nullptr); - m_ReadyHooks.clear(); - }); - } - m_ReadyHooks.push_back(hook); - } - std::optional> OutboundContext::GetHopsForBuild() { - if (m_NextIntro.router.IsZero()) + if (next_intro.router.IsZero()) { ShiftIntroduction(false); } - if (m_NextIntro.router.IsZero()) + if (next_intro.router.IsZero()) return std::nullopt; - return GetHopsAlignedToForBuild(m_NextIntro.router, service_endpoint->SnodeBlacklist()); + return GetHopsAlignedToForBuild(next_intro.router, ep.SnodeBlacklist()); } bool - OutboundContext::ShouldBuildMore(llarp_time_t now) const + OutboundContext::ShouldBuildMore(std::chrono::milliseconds now) const { - if (markedBad or path::Builder::BuildCooldownHit(now)) + if (marked_bad or path::Builder::BuildCooldownHit(now)) return false; if (NumInStatus(path::ePathBuilding) >= std::max(numDesiredPaths / size_t{2}, size_t{1})) @@ -491,44 +452,25 @@ namespace llarp::service if (not path->intro.ExpiresSoon(now, path::DEFAULT_LIFETIME - path::INTRO_PATH_SPREAD)) { numValidPaths++; - if (path->intro.router == m_NextIntro.router) + if (path->intro.router == next_intro.router) havePathToNextIntro = true; } }); return numValidPaths < numDesiredPaths or not havePathToNextIntro; } - void - OutboundContext::MarkCurrentIntroBad(llarp_time_t now) - { - MarkIntroBad(remoteIntro, now); - } - - void - OutboundContext::MarkIntroBad(const Introduction&, llarp_time_t) - {} - - bool - OutboundContext::IntroSent() const - { - return sentIntro; - } - - bool - OutboundContext::IntroGenerated() const - { - return generatedIntro; - } - bool OutboundContext::ShiftIntroduction(bool rebuild) { - bool success = false; + bool success = false, shifted = false; const auto now = Now(); - if (abs(now - lastShift) < shiftTimeout) + auto shift_timeout = send_timeout * 5 / 2; + + if (abs(now - last_shift) < shift_timeout) return false; - bool shifted = false; - std::vector intros = currentIntroSet.intros; + + std::vector intros = current_intro.intros; + if (intros.size() > 1) { std::shuffle(intros.begin(), intros.end(), CSRNG{}); @@ -539,14 +481,14 @@ namespace llarp::service { if (intro.ExpiresSoon(now)) continue; - if (service_endpoint->SnodeBlacklist().count(intro.router)) + if (ep.SnodeBlacklist().count(intro.router)) continue; - if (remoteIntro.router == intro.router) + if (remote_intro.router == intro.router) { - if (intro.expiry > m_NextIntro.expiry) + if (intro.expiry > next_intro.expiry) { success = true; - m_NextIntro = intro; + next_intro = intro; } } } @@ -555,28 +497,28 @@ namespace llarp::service /// pick newer intro not on same router for (const auto& intro : intros) { - if (service_endpoint->SnodeBlacklist().count(intro.router)) + if (ep.SnodeBlacklist().count(intro.router)) continue; - service_endpoint->EnsureRouterIsKnown(intro.router); + ep.EnsureRouterIsKnown(intro.router); if (intro.ExpiresSoon(now)) continue; - if (m_NextIntro != intro) + if (next_intro != intro) { - if (intro.expiry > m_NextIntro.expiry) + if (intro.expiry > next_intro.expiry) { - shifted = intro.router != m_NextIntro.router; - m_NextIntro = intro; + shifted = intro.router != next_intro.router; + next_intro = intro; success = true; } } } } - if (m_NextIntro.router.IsZero()) + if (next_intro.router.IsZero()) return false; if (shifted) - lastShift = now; + last_shift = now; if (rebuild && !BuildCooldownHit(Now())) - BuildOneAlignedTo(m_NextIntro.router); + BuildOneAlignedTo(next_intro.router); return success; } @@ -587,7 +529,7 @@ namespace llarp::service UpdateIntroSet(); const RouterID endpoint{path->Endpoint()}; // if a path to our current intro died... - if (endpoint == remoteIntro.router) + if (endpoint == remote_intro.router) { // figure out how many paths to this router we have size_t num = 0; @@ -600,117 +542,33 @@ namespace llarp::service // we have no more paths to this endpoint so we want to pivot off of it MarkCurrentIntroBad(Now()); ShiftIntroRouter(endpoint); - if (m_NextIntro.router != endpoint) - BuildOneAlignedTo(m_NextIntro.router); + if (next_intro.router != endpoint) + BuildOneAlignedTo(next_intro.router); } } } bool - OutboundContext::ShouldKeepAlive(llarp_time_t now) const + OutboundContext::ShouldKeepAlive(std::chrono::milliseconds now) const { - const auto SendKeepAliveInterval = sendTimeout / 2; - if (not m_GotInboundTraffic) + const auto SendKeepAliveInterval = send_timeout / 2; + if (not got_inbound_traffic) return false; - if (m_LastInboundTraffic == 0s) + if (last_inbound_traffic == 0s) return false; - return (now - m_LastKeepAliveAt) >= SendKeepAliveInterval; + return (now - last_keep_alive) >= SendKeepAliveInterval; } void - OutboundContext::Tick(llarp_time_t now) + OutboundContext::Tick(std::chrono::milliseconds now) { path::Builder::Tick(now); if (ShouldKeepAlive(now)) KeepAlive(); } - bool - OutboundContext::HandleHiddenServiceFrame(path::Path_ptr p, const ProtocolFrameMessage& frame) - { - m_LastInboundTraffic = service_endpoint->Now(); - m_GotInboundTraffic = true; - if (frame.flag) - { - // handle discard - ServiceInfo si; - if (!service_endpoint->GetSenderFor(frame.convo_tag, si)) - { - LogWarn("no sender for T=", frame.convo_tag); - return false; - } - // verify source - if (!frame.Verify(si)) - { - LogWarn("signature verification failed, T=", frame.convo_tag); - return false; - } - // remove convotag it doesn't exist - LogWarn("remove convotag T=", frame.convo_tag, " R=", frame.flag); - - AuthResult result{AuthResultCode::eAuthFailed, "unknown reason"}; - if (const auto maybe = AuthResultCodeFromInt(frame.flag)) - result.code = *maybe; - SharedSecret sessionKey{}; - if (service_endpoint->GetCachedSessionKeyFor(frame.convo_tag, sessionKey)) - { - ProtocolMessage msg{}; - if (frame.DecryptPayloadInto(sessionKey, msg)) - { - if (msg.proto == ProtocolType::Auth and not msg.payload.empty()) - { - result.reason = - std::string{reinterpret_cast(msg.payload.data()), msg.payload.size()}; - } - } - } - - service_endpoint->RemoveConvoTag(frame.convo_tag); - if (authResultListener) - { - authResultListener(result); - authResultListener = nullptr; - } - return true; - } - std::function)> hook = nullptr; - if (authResultListener) - { - std::function handler = authResultListener; - authResultListener = nullptr; - hook = [handler](std::shared_ptr msg) { - AuthResult result{AuthResultCode::eAuthAccepted, "OK"}; - if (msg->proto == ProtocolType::Auth and not msg->payload.empty()) - { - result.reason = - std::string{reinterpret_cast(msg->payload.data()), msg->payload.size()}; - } - handler(result); - }; - } - const auto& ident = service_endpoint->GetIdentity(); - if (not frame.AsyncDecryptAndVerify(service_endpoint->Loop(), p, ident, service_endpoint, hook)) - { - // send reset convo tag message - LogError("failed to decrypt and verify frame"); - ProtocolFrameMessage f; - f.flag = 1; - f.convo_tag = frame.convo_tag; - f.path_id = p->intro.path_id; - - f.Sign(ident); - { - LogWarn("invalidating convotag T=", frame.convo_tag); - service_endpoint->RemoveConvoTag(frame.convo_tag); - service_endpoint->_send_queue.tryPushBack( - SendEvent_t{std::make_shared(f, frame.path_id), p}); - } - } - return true; - } - void - OutboundContext::SendPacketToRemote(const llarp_buffer_t& buf, service::ProtocolType t) + OutboundContext::send_packet_to_remote(std::string buf) { AsyncEncryptAndSendTo(buf, t); } diff --git a/llarp/service/outbound_context.hpp b/llarp/service/outbound_context.hpp index 65e9ec8fd9..7c2e9f657d 100644 --- a/llarp/service/outbound_context.hpp +++ b/llarp/service/outbound_context.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include "sendcontext.hpp" +#include #include #include @@ -13,16 +13,51 @@ namespace llarp::service struct Endpoint; /// context needed to initiate an outbound hidden service session - struct OutboundContext : public path::Builder, - public SendContext, + struct OutboundContext : public llarp::path::Builder, public std::enable_shared_from_this { - OutboundContext(const IntroSet& introSet, Endpoint* parent); + private: + Endpoint& ep; + IntroSet current_intro; + Introduction next_intro; + + const dht::Key_t location; + const Address addr; + + ServiceInfo remote_identity; + Introduction remote_intro; + + ConvoTag current_tag; + + uint64_t update_introset_tx = 0; + uint16_t lookup_fails = 0; + uint16_t build_fails = 0; + + bool got_inbound_traffic = false; + bool generated_intro = false; + bool sent_intro = false; + bool marked_bad = false; + + const std::chrono::milliseconds created_at; + std::chrono::milliseconds last_send = 0ms; + std::chrono::milliseconds send_timeout = path::BUILD_TIMEOUT; + std::chrono::milliseconds connect_timeout = send_timeout * 2; + std::chrono::milliseconds last_shift = 0ms; + std::chrono::milliseconds last_inbound_traffic = 0ms; + std::chrono::milliseconds last_introset_update = 0ms; + std::chrono::milliseconds last_keep_alive = 0ms; + + public: + OutboundContext(const IntroSet& introSet, Endpoint* parent); + ~OutboundContext() override; void - Tick(llarp_time_t now) override; + encrypt_and_send(std::string buf); + + void + Tick(std::chrono::milliseconds now) override; util::StatusObject ExtractStatus() const; @@ -30,9 +65,6 @@ namespace llarp::service void BlacklistSNode(const RouterID) override{}; - bool - ShouldBundleRC() const override; - path::PathSet_ptr GetSelf() override { @@ -51,9 +83,6 @@ namespace llarp::service bool Stop() override; - bool - HandleDataDrop(path::Path_ptr p, const PathID_t& dst, uint64_t s); - void HandlePathDied(path::Path_ptr p) override; @@ -63,51 +92,41 @@ namespace llarp::service /// update the current selected intro to be a new best introduction /// return true if we have changed intros bool - ShiftIntroduction(bool rebuild = true) override; + ShiftIntroduction(bool rebuild = true); /// shift the intro off the current router it is using void - ShiftIntroRouter(const RouterID remote) override; - - /// mark the current remote intro as bad - void - MarkCurrentIntroBad(llarp_time_t now) override; - - void - MarkIntroBad(const Introduction& marked, llarp_time_t now); + ShiftIntroRouter(const RouterID remote); /// return true if we are ready to send bool ReadyToSend() const; - void - AddReadyHook(std::function readyHook, llarp_time_t timeout); - /// for exits void - SendPacketToRemote(const llarp_buffer_t&, ProtocolType t) override; + send_packet_to_remote(std::string buf) override; bool - ShouldBuildMore(llarp_time_t now) const override; + ShouldBuildMore(std::chrono::milliseconds now) const override; /// pump internal state /// return true to mark as dead bool - Pump(llarp_time_t now); + Pump(std::chrono::milliseconds now); /// return true if it's safe to remove ourselves bool - IsDone(llarp_time_t now) const; + IsDone(std::chrono::milliseconds now) const; bool - CheckPathIsDead(path::Path_ptr p, llarp_time_t dlt); + CheckPathIsDead(path::Path_ptr p, std::chrono::milliseconds dlt); void - AsyncGenIntro(const llarp_buffer_t& payload, ProtocolType t) override; + AsyncGenIntro(const llarp_buffer_t& payload, ProtocolType t); /// issues a lookup to find the current intro set of the remote service void - UpdateIntroSet() override; + UpdateIntroSet(); void HandlePathBuilt(path::Path_ptr path) override; @@ -121,9 +140,6 @@ namespace llarp::service std::optional> GetHopsForBuild() override; - bool - HandleHiddenServiceFrame(path::Path_ptr p, const ProtocolFrameMessage& frame); - std::string Name() const override; @@ -131,15 +147,15 @@ namespace llarp::service KeepAlive(); bool - ShouldKeepAlive(llarp_time_t now) const; + ShouldKeepAlive(std::chrono::milliseconds now) const; const IntroSet& GetCurrentIntroSet() const { - return currentIntroSet; + return current_intro; } - llarp_time_t + std::chrono::milliseconds RTT() const; bool @@ -147,33 +163,12 @@ namespace llarp::service const Address& addr, std::optional i, const RouterID& endpoint, - llarp_time_t, + std::chrono::milliseconds, uint64_t relayOrder); private: /// swap remoteIntro with next intro void - SwapIntros(); - - bool - IntroGenerated() const override; - bool - IntroSent() const override; - - const dht::Key_t location; - const Address addr; - uint64_t m_UpdateIntrosetTX = 0; - IntroSet currentIntroSet; - Introduction m_NextIntro; - llarp_time_t lastShift = 0s; - uint16_t m_LookupFails = 0; - uint16_t m_BuildFails = 0; - llarp_time_t m_LastInboundTraffic = 0s; - bool m_GotInboundTraffic = false; - bool generatedIntro = false; - bool sentIntro = false; - std::vector> m_ReadyHooks; - llarp_time_t m_LastIntrosetUpdateAt = 0s; - llarp_time_t m_LastKeepAliveAt = 0s; + swap_intros(); }; } // namespace llarp::service From 88fd0852db5a40cfb80262d894eef77154a1de86 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Wed, 18 Oct 2023 05:48:09 -0700 Subject: [PATCH 063/312] Outbound context absorbed sendcontex - message transmission routed through refactored handling - still work to be done, but now to make it compile at least --- llarp/exit/session.cpp | 8 +- llarp/handlers/exit.cpp | 19 +-- llarp/handlers/null.hpp | 3 +- llarp/handlers/tun.hpp | 3 +- llarp/link/link_manager.cpp | 4 +- llarp/link/link_manager.hpp | 6 +- llarp/nodedb.cpp | 5 +- llarp/nodedb.hpp | 5 +- llarp/path/path.cpp | 1 + llarp/router_contact.hpp | 2 +- llarp/rpc/endpoint_rpc.cpp | 21 +-- llarp/rpc/endpoint_rpc.hpp | 2 +- llarp/service/async_key_exchange.cpp | 15 +- llarp/service/async_key_exchange.hpp | 3 +- llarp/service/auth.cpp | 4 +- llarp/service/auth.hpp | 2 +- llarp/service/endpoint.cpp | 45 ++++-- llarp/service/endpoint.hpp | 6 +- llarp/service/intro.cpp | 16 ++ llarp/service/intro.hpp | 2 + llarp/service/outbound_context.cpp | 219 ++++++++++++++++++--------- llarp/service/outbound_context.hpp | 34 +++-- llarp/service/protocol.cpp | 82 ++++------ llarp/service/protocol.hpp | 43 ++---- llarp/service/sendcontext.cpp | 2 +- llarp/util/buffer.hpp | 6 + 26 files changed, 318 insertions(+), 240 deletions(-) diff --git a/llarp/exit/session.cpp b/llarp/exit/session.cpp index fe6b9832ca..70bed01cfb 100644 --- a/llarp/exit/session.cpp +++ b/llarp/exit/session.cpp @@ -80,7 +80,7 @@ namespace llarp::exit return std::vector{*maybe}; return std::nullopt; } - + return GetHopsAlignedToForBuild(exit_router); } @@ -377,7 +377,7 @@ namespace llarp::exit void ExitSession::send_packet_to_remote(std::string buf) { - net::IPPacket pkt{buf.view_all()}; + net::IPPacket pkt{buf}; if (pkt.empty()) return; pkt.ZeroAddresses(); @@ -388,12 +388,12 @@ namespace llarp::exit void SNodeSession::send_packet_to_remote(std::string buf) { - net::IPPacket pkt{buf.view_all()}; + net::IPPacket pkt{buf}; if (pkt.empty()) return; pkt.ZeroSourceAddress(); - + // QueueUpstreamTraffic(std::move(pkt), llarp::routing::EXIT_PAD_SIZE, t); } } // namespace llarp::exit diff --git a/llarp/handlers/exit.cpp b/llarp/handlers/exit.cpp index 0b1ec7a728..6ab5f8fee0 100644 --- a/llarp/handlers/exit.cpp +++ b/llarp/handlers/exit.cpp @@ -106,20 +106,21 @@ namespace llarp::handlers { if (not itr->second->LooksDead(Now())) { - if (itr->second->QueueInboundTraffic(payload.copy(), type)) - return true; + return router->send_data_message(itr->second->PubKey(), std::move(payload)); } } if (not router->PathToRouterAllowed(*rid)) return false; - ObtainSNodeSession(*rid, [pkt = std::move(payload)](auto session) mutable { - if (session and session->IsReady()) - { - session->send_packet_to_remote(std::move(pkt)); - } - }); + ObtainSNodeSession( + *rid, + [pkt = std::move(payload)](std::shared_ptr session) mutable { + if (session and session->IsReady()) + { + session->send_packet_to_remote(std::move(pkt)); + } + }); } return true; } @@ -404,7 +405,7 @@ namespace llarp::handlers } } auto tryFlushingTraffic = [this, buf = std::move(buf), pk](exit::Endpoint* const ep) -> bool { - if (!ep->QueueInboundTraffic(buf, service::ProtocolType::TrafficV4)) + if (!ep->QueueInboundTraffic(buf._buf, service::ProtocolType::TrafficV4)) { LogWarn( Name(), diff --git a/llarp/handlers/null.hpp b/llarp/handlers/null.hpp index 1d216456a2..7b16c5c93f 100644 --- a/llarp/handlers/null.hpp +++ b/llarp/handlers/null.hpp @@ -74,8 +74,7 @@ namespace llarp::handlers return true; } - void - send_packet_to_remote(std::string) override {}; + void send_packet_to_remote(std::string) override{}; std::string GetIfName() const override diff --git a/llarp/handlers/tun.hpp b/llarp/handlers/tun.hpp index 89d07f1c9a..f4241d9014 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -72,8 +72,7 @@ namespace llarp::handlers bool Configure(const NetworkConfig& conf, const DnsConfig& dnsConf) override; - void - send_packet_to_remote(std::string) override{}; + void send_packet_to_remote(std::string) override{}; std::string GetIfName() const override; diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 610a245150..11dab5c266 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1648,9 +1648,7 @@ namespace llarp } try - { - - } + {} catch (const std::exception& e) { log::warning(link_cat, "Exception: {}", e.what()); diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index c7f11e01c7..e57190cf79 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -310,6 +310,9 @@ namespace llarp void handle_update_exit(oxen::quic::message); // relay void handle_close_exit(oxen::quic::message); // relay + // Misc + void handle_convo_intro(oxen::quic::message); + std::unordered_map rpc_commands = { {"find_name", &LinkManager::handle_find_name}, {"find_router", &LinkManager::handle_find_router}, @@ -320,7 +323,8 @@ namespace llarp {"path_latency", &LinkManager::handle_path_latency}, {"update_exit", &LinkManager::handle_update_exit}, {"obtain_exit", &LinkManager::handle_obtain_exit}, - {"close_exit", &LinkManager::handle_close_exit}}; + {"close_exit", &LinkManager::handle_close_exit}, + {"convo_intro", &LinkManager::handle_convo_intro}}; // Path relaying void handle_path_control(oxen::quic::message); diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index 6b198496d8..0bcbefa6cf 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -185,7 +185,8 @@ namespace llarp bool NodeDB::has_router(RouterID pk) const { - return router.loop()->call_get([this, pk]() { return entries.find(pk) != entries.end(); }); + return router.loop()->call_get( + [this, pk]() -> bool { return entries.find(pk) != entries.end(); }); } std::optional @@ -243,7 +244,7 @@ namespace llarp size_t NodeDB::num_loaded() const { - return router.loop()->call_get([this]() { return entries.size(); }); + return router.loop()->call_get([this]() -> size_t { return entries.size(); }); } void diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index 6082c28571..8bc1289a63 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -2,10 +2,11 @@ #include "router_contact.hpp" #include "router_id.hpp" -#include "dht/key.hpp" -#include "crypto/crypto.hpp" + #include "util/common.hpp" #include "util/fs.hpp" +#include "dht/key.hpp" +#include "crypto/crypto.hpp" #include "util/thread/threading.hpp" #include "util/thread/annotations.hpp" #include diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 9884532e10..13eeb09800 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -138,6 +138,7 @@ namespace llarp::path "path_control", std::move(outer_dict).str(), [response_cb = std::move(func)](oxen::quic::message m) { + if (m) { // do path hop logic here } diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index a1c7e450c8..6775362632 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -64,7 +64,7 @@ namespace llarp { /// for unit tests static bool BlockBogons; - + static llarp_time_t Lifetime; static llarp_time_t UpdateInterval; static llarp_time_t StaleInsertionAge; diff --git a/llarp/rpc/endpoint_rpc.cpp b/llarp/rpc/endpoint_rpc.cpp index a5edd2c34f..ca2e4e41a6 100644 --- a/llarp/rpc/endpoint_rpc.cpp +++ b/llarp/rpc/endpoint_rpc.cpp @@ -44,26 +44,26 @@ namespace llarp::rpc void EndpointAuthRPC::AuthenticateAsync( std::shared_ptr msg, - std::function hook) + std::function hook) { service::ConvoTag tag = msg->tag; m_PendingAuths.insert(tag); const auto from = msg->sender.Addr(); - auto reply = m_Endpoint->Loop()->make_caller([this, tag, hook](service::AuthResult result) { + auto reply = m_Endpoint->Loop()->make_caller([this, tag, hook](std::string code, bool success) { m_PendingAuths.erase(tag); - hook(result); + hook(code, success); }); if (m_AuthWhitelist.count(from)) { // explicitly whitelisted source - reply(service::AuthResult{service::AuthResultCode::eAuthAccepted, "explicitly whitelisted"}); + reply("explicitly whitelisted", true); return; } if (msg->proto != llarp::service::ProtocolType::Auth) { // not an auth message, reject - reply(service::AuthResult{service::AuthResultCode::eAuthRejected, "protocol error"}); + reply("protocol error", false); return; } @@ -71,7 +71,7 @@ namespace llarp::rpc if (m_AuthStaticTokens.count(payload)) { - reply(service::AuthResult{service::AuthResultCode::eAuthAccepted, "explicitly whitelisted"}); + reply("explicitly whitelisted", true); return; } @@ -80,13 +80,12 @@ namespace llarp::rpc if (m_AuthStaticTokens.empty()) { // we don't have a connection to the backend so it's failed - reply(service::AuthResult{ - service::AuthResultCode::eAuthFailed, "remote has no connection to auth backend"}); + reply("remote has no connection to auth backend", false); } else { // static auth mode - reply(service::AuthResult{service::AuthResultCode::eAuthRejected, "access not permitted"}); + reply("access not permitted", true); } return; } @@ -100,6 +99,7 @@ namespace llarp::rpc [self = shared_from_this(), reply = std::move(reply)]( bool success, std::vector data) { service::AuthResult result{service::AuthResultCode::eAuthFailed, "no reason given"}; + if (success and not data.empty()) { if (const auto maybe = service::ParseAuthResultCode(data[0])) @@ -115,7 +115,8 @@ namespace llarp::rpc result.reason = data[1]; } } - reply(result); + + reply(result.reason, success); }, metainfo, payload); diff --git a/llarp/rpc/endpoint_rpc.hpp b/llarp/rpc/endpoint_rpc.hpp index 02e573d6d3..b521537ebb 100644 --- a/llarp/rpc/endpoint_rpc.hpp +++ b/llarp/rpc/endpoint_rpc.hpp @@ -32,7 +32,7 @@ namespace llarp::rpc void AuthenticateAsync( std::shared_ptr msg, - std::function hook) override; + std::function hook) override; bool AsyncAuthPending(service::ConvoTag tag) const override; diff --git a/llarp/service/async_key_exchange.cpp b/llarp/service/async_key_exchange.cpp index 38e5bbd5d6..2cfecad428 100644 --- a/llarp/service/async_key_exchange.cpp +++ b/llarp/service/async_key_exchange.cpp @@ -15,8 +15,7 @@ namespace llarp::service const PQPubKey& introsetPubKey, const Introduction& remote, Endpoint* h, - const ConvoTag& t, - ProtocolType proto) + const ConvoTag& t) : loop(std::move(l)) , m_remote(std::move(r)) , m_LocalIdentity(localident) @@ -24,9 +23,7 @@ namespace llarp::service , remoteIntro(remote) , handler(h) , tag(t) - { - msg.proto = proto; - } + {} void AsyncKeyExchange::Result( @@ -47,13 +44,15 @@ namespace llarp::service // derive ntru session key component SharedSecret secret; auto crypto = CryptoManager::instance(); + crypto->pqe_encrypt(frame->cipher, secret, self->introPubKey); - // randomize Nonce frame->nonce.Randomize(); - // compure post handshake session key + + // compute post handshake session key // PKE (A, B, N) SharedSecret sharedSecret; path_dh_func dh_client = util::memFn(&Crypto::dh_client, crypto); + if (!self->m_LocalIdentity.KeyExchange(dh_client, sharedSecret, self->m_remote, frame->nonce)) { LogError("failed to derive x25519 shared key component"); @@ -67,8 +66,6 @@ namespace llarp::service self->msg.tag = self->tag; // set sender self->msg.sender = self->m_LocalIdentity.pub; - // set version - self->msg.version = llarp::constants::proto_version; // encrypt and sign if (frame->EncryptAndSign(self->msg, secret, self->m_LocalIdentity)) self->loop->call([self, frame] { AsyncKeyExchange::Result(self, frame); }); diff --git a/llarp/service/async_key_exchange.hpp b/llarp/service/async_key_exchange.hpp index 108046563d..3957bc4ac8 100644 --- a/llarp/service/async_key_exchange.hpp +++ b/llarp/service/async_key_exchange.hpp @@ -27,8 +27,7 @@ namespace llarp::service const PQPubKey& introsetPubKey, const Introduction& remote, Endpoint* h, - const ConvoTag& t, - ProtocolType proto); + const ConvoTag& t); static void Result(std::shared_ptr user, std::shared_ptr frame); diff --git a/llarp/service/auth.cpp b/llarp/service/auth.cpp index 90faef6f3f..b4edf2ae46 100644 --- a/llarp/service/auth.cpp +++ b/llarp/service/auth.cpp @@ -137,7 +137,7 @@ namespace llarp::service void AuthenticateAsync( - std::shared_ptr msg, std::function hook) override + std::shared_ptr msg, std::function hook) override { auto reply = m_Router->loop()->make_caller( [tag = msg->tag, hook, self = shared_from_this()](AuthResult result) { @@ -145,7 +145,7 @@ namespace llarp::service util::Lock _lock{self->m_Access}; self->m_Pending.erase(tag); } - hook(result); + hook(result.reason, result.code == AuthResultCode::eAuthAccepted); }); { util::Lock _lock{m_Access}; diff --git a/llarp/service/auth.hpp b/llarp/service/auth.hpp index fea367594d..eb2f1a3c0e 100644 --- a/llarp/service/auth.hpp +++ b/llarp/service/auth.hpp @@ -57,7 +57,7 @@ namespace llarp::service /// result later virtual void AuthenticateAsync( - std::shared_ptr msg, std::function hook) = 0; + std::shared_ptr msg, std::function hook) = 0; /// return true if we are asynchronously processing authentication on this convotag virtual bool diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 67a9300be8..f725eec7ad 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -182,11 +182,13 @@ namespace llarp::service result_handler(false, result.reason); return; } + for (const auto& range : ranges) ptr->MapExitRange(range, addr); if (poker) poker->put_up(); + result_handler(true, result.reason); }; @@ -959,11 +961,13 @@ namespace llarp::service { PutSenderFor(msg->tag, msg->sender, true); Introduction intro = msg->introReply; + if (HasInboundConvo(msg->sender.Addr())) { intro.path_id = from; intro.router = p->Endpoint(); } + PutReplyIntroFor(msg->tag, intro); ConvoTagRX(msg->tag); return ProcessDataMessage(msg); @@ -1036,7 +1040,7 @@ namespace llarp::service void Endpoint::AsyncProcessAuthMessage( - std::shared_ptr msg, std::function hook) + std::shared_ptr msg, std::function hook) { if (_auth_policy) { @@ -1048,29 +1052,29 @@ namespace llarp::service } else { - router()->loop()->call([h = std::move(hook)] { h({AuthResultCode::eAuthAccepted, "OK"}); }); + router()->loop()->call([h = std::move(hook)] { h("OK", true); }); } } void - Endpoint::SendAuthResult(path::Path_ptr path, PathID_t replyPath, ConvoTag tag, AuthResult result) + Endpoint::SendAuthResult( + path::Path_ptr path, PathID_t replyPath, ConvoTag tag, std::string result, bool success) { // not applicable because we are not an exit or don't have an endpoint auth policy if ((not _state->is_exit_enabled) or _auth_policy == nullptr) return; + ProtocolFrameMessage f{}; - f.flag = AuthResultCodeAsInt(result.code); + f.flag = int(not success); f.convo_tag = tag; f.path_id = path->intro.path_id; f.nonce.Randomize(); - if (result.code == AuthResultCode::eAuthAccepted) + + if (success) { ProtocolMessage msg; + msg.put_buffer(result); - std::vector reason{}; - reason.resize(result.reason.size()); - std::copy_n(result.reason.c_str(), reason.size(), reason.data()); - msg.PutBuffer(reason); if (_auth_policy) msg.proto = ProtocolType::Auth; else @@ -1081,13 +1085,16 @@ namespace llarp::service LogError("Failed to send auth reply: no reply intro"); return; } + msg.sender = _identity.pub; SharedSecret sessionKey{}; + if (not GetCachedSessionKeyFor(tag, sessionKey)) { LogError("failed to send auth reply: no cached session key"); return; } + if (not f.EncryptAndSign(msg, sessionKey, _identity)) { LogError("Failed to encrypt and sign auth reply"); @@ -1225,7 +1232,7 @@ namespace llarp::service return EnsurePathToService( *ptr, - [hook](auto, auto* ctx) { + [hook](auto, auto* ctx) -> bool { if (ctx) { hook(ctx->currentConvoTag); @@ -1438,22 +1445,23 @@ namespace llarp::service // handle inbound traffic sorted util::ascending_priority_queue queue; + while (not _inbound_queue.empty()) { // succ it out queue.emplace(std::move(*_inbound_queue.popFront())); } + while (not queue.empty()) { const auto& msg = queue.top(); - LogDebug( + log::debug( + logcat, + "{} handling inbound packet (size {}B) on tag {}", Name(), - " handle inbound packet on ", msg.tag, - " ", - msg.payload.size(), - " bytes seqno=", - msg.seqno); + msg.payload.size()); + if (HandleInboundPacket(msg.tag, msg.payload, msg.proto, msg.seqno)) { ConvoTagRX(msg.tag); @@ -1462,10 +1470,13 @@ namespace llarp::service { LogWarn("Failed to handle inbound message"); } + queue.pop(); + a } auto r = router(); + // TODO: locking on this container for (const auto& [addr, outctx] : _state->remote_sessions) { @@ -1694,8 +1705,10 @@ namespace llarp::service Endpoint::MaybeGetAuthInfoForEndpoint(Address remote) { const auto itr = _remote_auth_infos.find(remote); + if (itr == _remote_auth_infos.end()) return std::nullopt; + return itr->second; } diff --git a/llarp/service/endpoint.hpp b/llarp/service/endpoint.hpp index 9051566bfd..5d11fcdb14 100644 --- a/llarp/service/endpoint.hpp +++ b/llarp/service/endpoint.hpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -422,10 +421,11 @@ namespace llarp void AsyncProcessAuthMessage( - std::shared_ptr msg, std::function hook); + std::shared_ptr msg, std::function hook); void - SendAuthResult(path::Path_ptr path, PathID_t replyPath, ConvoTag tag, AuthResult st); + SendAuthResult( + path::Path_ptr path, PathID_t replyPath, ConvoTag tag, std::string result, bool success); uint64_t GenTXID(); diff --git a/llarp/service/intro.cpp b/llarp/service/intro.cpp index 81db1aedf5..c239da5aba 100644 --- a/llarp/service/intro.cpp +++ b/llarp/service/intro.cpp @@ -67,6 +67,22 @@ namespace llarp::service } } + void + Introduction::bt_encode(oxenc::bt_dict_producer& subdict) const + { + try + { + subdict.append("k", router.ToView()); + subdict.append("l", latency.count()); + subdict.append("p", path_id.ToView()); + subdict.append("x", expiry.count()); + } + catch (...) + { + log::critical(intro_cat, "Error: Introduction failed to bt encode contents!"); + } + } + void Introduction::Clear() { diff --git a/llarp/service/intro.hpp b/llarp/service/intro.hpp index 699da44310..7dd780c86c 100644 --- a/llarp/service/intro.hpp +++ b/llarp/service/intro.hpp @@ -47,6 +47,8 @@ namespace llarp::service void bt_encode(oxenc::bt_list_producer& btlp) const; + void + bt_encode(oxenc::bt_dict_producer& subdict) const; bool BDecode(llarp_buffer_t* buf) diff --git a/llarp/service/outbound_context.cpp b/llarp/service/outbound_context.cpp index e9077956bb..0ff11d1408 100644 --- a/llarp/service/outbound_context.cpp +++ b/llarp/service/outbound_context.cpp @@ -38,7 +38,6 @@ namespace llarp::service , addr{current_intro.address_keys.Addr()} , remote_identity{current_intro.address_keys} , created_at{ep.Now()} - { assert(not introset.intros.empty()); updatingIntroSet = false; @@ -72,7 +71,7 @@ namespace llarp::service ep.PutIntroFor(current_tag, remote_intro); ShiftIntroRouter(next_intro.router); // if we have not made a handshake to the remote endpoint do so - if (not generated_intro) + if (not generated_convo_intro) { KeepAlive(); } @@ -133,7 +132,7 @@ namespace llarp::service return false; if (remote_intro.router.IsZero()) return false; - return sent_intro and GetPathByRouter(remote_intro.router); + return sent_convo_intro and GetPathByRouter(remote_intro.router); } void @@ -199,59 +198,6 @@ namespace llarp::service } } - void - OutboundContext::AsyncGenIntro(const llarp_buffer_t& payload, ProtocolType t) - { - if (generated_intro) - { - LogWarn(Name(), " dropping packet as we are not fully handshaked right now"); - return; - } - if (remote_intro.router.IsZero()) - { - LogWarn(Name(), " dropping intro frame we have no intro ready yet"); - return; - } - - auto path = GetPathByRouter(remote_intro.router); - if (path == nullptr) - { - LogError(Name(), " has no path to ", remote_intro.router, " when we should have had one"); - return; - } - auto frame = std::make_shared(); - frame->clear(); - auto ex = std::make_shared( - ep.Loop(), - remote_identity, - ep.GetIdentity(), - current_intro.sntru_pubkey, - remote_intro, - ep, - current_tag, - t); - - ex->hook = [self = shared_from_this(), path](auto frame) { - if (not self->Send(std::move(frame), path)) - return; - self->ep.Loop()->call_later( - self->remote_intro.latency, [self]() { self->sent_intro = true; }); - }; - - ex->msg.PutBuffer(payload); - ex->msg.introReply = path->intro; - frame->path_id = ex->msg.introReply.path_id; - frame->flag = 0; - generated_intro = true; - // ensure we have a sender put for this convo tag - ep.PutSenderFor(current_tag, current_intro.address_keys, false); - // encrypt frame async - ep.router()->queue_work( - [ex, frame] { return AsyncKeyExchange::Encrypt(ex, frame); }); - - LogInfo(Name(), " send intro frame T=", current_tag); - } - std::string OutboundContext::Name() const { @@ -265,7 +211,7 @@ namespace llarp::service const auto now = Now(); if (updatingIntroSet or marked_bad or now < last_introset_update + IntrosetUpdateInterval) return; - + log::info(link_cat, "{} updating introset", Name()); last_introset_update = now; @@ -273,7 +219,7 @@ namespace llarp::service // does not implement path::PathSet::HandleGotIntroMessage const auto paths = GetManyPathsWithUniqueEndpoints(&ep, 2, location); [[maybe_unused]] uint64_t relayOrder = 0; - + for ([[maybe_unused]] const auto& path : paths) { // TODO: implement this @@ -316,12 +262,11 @@ namespace llarp::service void OutboundContext::KeepAlive() { - ustring buf(64, '\0'); - - CryptoManager::instance()->randomize(buf.data(), buf.size()); - - SendPacketToRemote(buf, ProtocolType::Control); + std::string buf(64, '\0'); + + CryptoManager::instance()->randomize(reinterpret_cast(buf.data()), buf.size()); + send_packet_to_remote(buf); last_keep_alive = Now(); } @@ -348,7 +293,6 @@ namespace llarp::service { // timeout on other side UpdateIntroSet(); - MarkCurrentIntroBad(now); ShiftIntroRouter(remote_intro.router); } // check for stale intros @@ -384,7 +328,7 @@ namespace llarp::service if (not next_intro.router.IsZero()) ep.EnsureRouterIsKnown(next_intro.router); - if (ReadyToSend() and not ready_hooks.empty()) + if (ReadyToSend()) { const auto path = GetPathByRouter(remote_intro.router); if (not path) @@ -465,12 +409,12 @@ namespace llarp::service bool success = false, shifted = false; const auto now = Now(); auto shift_timeout = send_timeout * 5 / 2; - + if (abs(now - last_shift) < shift_timeout) return false; - + std::vector intros = current_intro.intros; - + if (intros.size() > 1) { std::shuffle(intros.begin(), intros.end(), CSRNG{}); @@ -540,7 +484,6 @@ namespace llarp::service if (num == 0) { // we have no more paths to this endpoint so we want to pivot off of it - MarkCurrentIntroBad(Now()); ShiftIntroRouter(endpoint); if (next_intro.router != endpoint) BuildOneAlignedTo(next_intro.router); @@ -552,10 +495,13 @@ namespace llarp::service OutboundContext::ShouldKeepAlive(std::chrono::milliseconds now) const { const auto SendKeepAliveInterval = send_timeout / 2; + if (not got_inbound_traffic) return false; + if (last_inbound_traffic == 0s) return false; + return (now - last_keep_alive) >= SendKeepAliveInterval; } @@ -563,14 +509,147 @@ namespace llarp::service OutboundContext::Tick(std::chrono::milliseconds now) { path::Builder::Tick(now); + if (ShouldKeepAlive(now)) KeepAlive(); } + void + OutboundContext::send_auth_async(std::function resultHandler) + { + if (const auto maybe = ep.MaybeGetAuthInfoForEndpoint(remote_identity.Addr())) + gen_intro_async_impl(maybe->token, std::move(resultHandler)); + else + resultHandler("No auth needed", true); + } + + void + OutboundContext::gen_intro_async_impl( + std::string payload, std::function func) + { + auto path = GetPathByRouter(remote_intro.router); + + if (path == nullptr) + { + log::warning(logcat, "{} unexpectedly has no path to remote {}", Name(), remote_intro.router); + return; + } + + auto frame = std::make_shared(); + frame->clear(); + + auto ex = std::make_shared( + ep.Loop(), + remote_identity, + ep.GetIdentity(), + current_intro.sntru_pubkey, + remote_intro, + ep, + current_tag); + + if (const auto maybe = ep.MaybeGetAuthInfoForEndpoint(remote_identity.Addr()); not maybe) + ex->msg.proto = ProtocolType::Auth; + + ex->hook = [this, path, cb = std::move(func)](auto frame) mutable { + auto hook = [&, frame, path](oxen::quic::message) { + // TODO: revisit this + ep.HandleHiddenServiceFrame(path, *frame.get()); + }; + + if (path->send_path_control_message("convo_intro", frame->bt_encode(), hook)) + sent_convo_intro = true; + }; + + ex->msg.put_buffer(payload); + ex->msg.introReply = path->intro; + frame->path_id = ex->msg.introReply.path_id; + frame->flag = 0; + generated_convo_intro = true; + // ensure we have a sender put for this convo tag + ep.PutSenderFor(current_tag, current_intro.address_keys, false); + // encrypt frame async + ep.router()->queue_work([ex, frame] { return AsyncKeyExchange::Encrypt(ex, frame); }); + + log::info(logcat, "{} send convo intro frame for tag {}", Name(), current_tag); + } + + void + OutboundContext::gen_intro_async(std::string payload) + { + if (generated_convo_intro) + { + LogWarn(Name(), " dropping packet as we are not fully handshaked right now"); + return; + } + if (remote_intro.router.IsZero()) + { + LogWarn(Name(), " dropping convo intro frame we have no intro ready yet"); + return; + } + + gen_intro_async_impl(std::move(payload)); + } + void OutboundContext::send_packet_to_remote(std::string buf) { - AsyncEncryptAndSendTo(buf, t); + if (sent_convo_intro) + { + encrypt_and_send(std::move(buf)); + return; + } + + if (generated_convo_intro) + { + log::warning(link_cat, "{} has generated an unsent initial handshake; dropping packet"); + return; + } + + gen_intro_async(std::move(buf)); + } + + void + OutboundContext::encrypt_and_send(std::string buf) + { + SharedSecret shared; + auto f = std::make_shared(); + f->flag = 0; + f->nonce.Randomize(); + f->convo_tag = current_tag; + + auto path = GetPathByRouter(remote_intro.router); + + if (!path) + { + ShiftIntroRouter(remote_intro.router); + log::warning( + logcat, "{} cannot encrypt and send: no path for intro {}", Name(), remote_intro); + return; + } + + if (!ep.GetCachedSessionKeyFor(f->convo_tag, shared)) + { + log::warning( + logcat, "{} could not send; no cached session keys for tag {}", Name(), f->convo_tag); + return; + } + + auto msg = std::make_shared(); + ep.PutIntroFor(f->convo_tag, remote_intro); + ep.PutReplyIntroFor(f->convo_tag, path->intro); + + msg->introReply = path->intro; + f->path_id = msg->introReply.path_id; + msg->sender = ep.GetIdentity().pub; + msg->tag = f->convo_tag; + msg->put_buffer(buf); + + router->loop()->call_soon([this, f, msg, shared, path]() { + if (f->EncryptAndSign(*msg, shared, ep.GetIdentity())) + path->send_path_control_message("convo_intro", msg->bt_encode()); + else + log::warning(logcat, "{} failed to sign protocol frame message!", Name()); + }); } } // namespace llarp::service diff --git a/llarp/service/outbound_context.hpp b/llarp/service/outbound_context.hpp index 7c2e9f657d..cffcff092b 100644 --- a/llarp/service/outbound_context.hpp +++ b/llarp/service/outbound_context.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -29,16 +30,16 @@ namespace llarp::service Introduction remote_intro; ConvoTag current_tag; - + uint64_t update_introset_tx = 0; uint16_t lookup_fails = 0; uint16_t build_fails = 0; - + bool got_inbound_traffic = false; - bool generated_intro = false; - bool sent_intro = false; + bool generated_convo_intro = false; + bool sent_convo_intro = false; bool marked_bad = false; - + const std::chrono::milliseconds created_at; std::chrono::milliseconds last_send = 0ms; std::chrono::milliseconds send_timeout = path::BUILD_TIMEOUT; @@ -48,14 +49,28 @@ namespace llarp::service std::chrono::milliseconds last_introset_update = 0ms; std::chrono::milliseconds last_keep_alive = 0ms; + void + gen_intro_async_impl( + std::string payload, std::function func = nullptr); + public: OutboundContext(const IntroSet& introSet, Endpoint* parent); - + ~OutboundContext() override; + void + gen_intro_async(std::string payload); + void encrypt_and_send(std::string buf); + /// for exits + void + send_packet_to_remote(std::string buf) override; + + void + send_auth_async(std::function resultHandler); + void Tick(std::chrono::milliseconds now) override; @@ -102,10 +117,6 @@ namespace llarp::service bool ReadyToSend() const; - /// for exits - void - send_packet_to_remote(std::string buf) override; - bool ShouldBuildMore(std::chrono::milliseconds now) const override; @@ -121,9 +132,6 @@ namespace llarp::service bool CheckPathIsDead(path::Path_ptr p, std::chrono::milliseconds dlt); - void - AsyncGenIntro(const llarp_buffer_t& payload, ProtocolType t); - /// issues a lookup to find the current intro set of the remote service void UpdateIntroSet(); diff --git a/llarp/service/protocol.cpp b/llarp/service/protocol.cpp index 7727166613..f1f32b4f53 100644 --- a/llarp/service/protocol.cpp +++ b/llarp/service/protocol.cpp @@ -1,10 +1,9 @@ #include "protocol.hpp" +#include "endpoint.hpp" + #include -#include #include #include -#include -#include "endpoint.hpp" #include #include @@ -21,10 +20,10 @@ namespace llarp::service ProtocolMessage::~ProtocolMessage() = default; void - ProtocolMessage::PutBuffer(const llarp_buffer_t& buf) + ProtocolMessage::put_buffer(std::string buf) { - payload.resize(buf.sz); - memcpy(payload.data(), buf.base, buf.sz); + payload.resize(buf.size()); + memcpy(payload.data(), buf.data(), buf.size()); } void @@ -39,26 +38,22 @@ namespace llarp::service ProtocolMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) { bool read = false; - if (!BEncodeMaybeReadDictInt("a", proto, read, k, buf)) - return false; + // if (!BEncodeMaybeReadDictInt("a", proto, read, k, buf)) + // return false; if (k.startswith("d")) { llarp_buffer_t strbuf; if (!bencode_read_string(buf, &strbuf)) return false; - PutBuffer(strbuf); + put_buffer(strbuf.to_string()); return true; } if (!BEncodeMaybeReadDictEntry("i", introReply, read, k, buf)) return false; - if (!BEncodeMaybeReadDictInt("n", seqno, read, k, buf)) - return false; if (!BEncodeMaybeReadDictEntry("s", sender, read, k, buf)) return false; if (!BEncodeMaybeReadDictEntry("t", tag, read, k, buf)) return false; - if (!BEncodeMaybeReadDictInt("v", version, read, k, buf)) - return false; return read; } @@ -69,7 +64,7 @@ namespace llarp::service try { - btdp.append("a", static_cast(proto)); + // btdp.append("a", static_cast(proto)); if (not payload.empty()) btdp.append( @@ -80,19 +75,16 @@ namespace llarp::service introReply.bt_encode(subdict); } - btdp.append("n", seqno); - { auto subdict = btdp.append_dict("s"); sender.bt_encode(subdict); } btdp.append("t", tag.ToView()); - btdp.append("v", version); } catch (...) { - log::critical(route_cat, "Error: ProtocolMessage failed to bt encode contents!"); + log::critical(logcat, "Error: ProtocolMessage failed to bt encode contents!"); } return std::move(btdp).str(); @@ -105,7 +97,7 @@ namespace llarp::service try { - btdp.append("a", static_cast(proto)); + // btdp.append("a", static_cast(proto)); { auto subdict = btdp.append_dict("s"); @@ -113,11 +105,10 @@ namespace llarp::service } btdp.append("t", tag.ToView()); - btdp.append("v", version); } catch (...) { - log::critical(route_cat, "Error: ProtocolMessage failed to bt encode auth info"); + log::critical(logcat, "Error: ProtocolMessage failed to bt encode auth info"); } auto view = btdp.view(); @@ -128,8 +119,6 @@ namespace llarp::service return data; } - ProtocolFrameMessage::~ProtocolFrameMessage() = default; - std::string ProtocolFrameMessage::bt_encode() const { @@ -144,12 +133,11 @@ namespace llarp::service btdp.append("N", nonce.ToView()); btdp.append("R", flag); btdp.append("T", convo_tag.ToView()); - btdp.append("V", version); btdp.append("Z", sig.ToView()); } catch (...) { - log::critical(route_cat, "Error: ProtocolFrameMessage failed to bt encode contents!"); + log::critical(logcat, "Error: ProtocolFrameMessage failed to bt encode contents!"); } return std::move(btdp).str(); @@ -176,14 +164,10 @@ namespace llarp::service return false; if (!BEncodeMaybeReadDictEntry("N", nonce, read, key, val)) return false; - if (!BEncodeMaybeReadDictInt("S", sequence_number, read, key, val)) - return false; if (!BEncodeMaybeReadDictInt("R", flag, read, key, val)) return false; if (!BEncodeMaybeReadDictEntry("T", convo_tag, read, key, val)) return false; - if (!BEncodeMaybeVerifyVersion("V", version, llarp::constants::proto_version, read, key, val)) - return false; if (!BEncodeMaybeReadDictEntry("Z", sig, read, key, val)) return false; return read; @@ -320,7 +304,9 @@ namespace llarp::service // PKE (A, B, N) SharedSecret shared_secret; - path_dh_func dh_server = util::memFn(&Crypto::dh_server, CryptoManager::instance()); + path_dh_func dh_server = [crypto = CryptoManager::instance()](auto&& params...) -> bool { + return crypto->dh_server(std::forward(params)); + }; if (!self->m_LocalIdentity.KeyExchange( dh_server, shared_secret, self->msg->sender, self->frame.nonce)) @@ -345,8 +331,8 @@ namespace llarp::service self->handler->AsyncProcessAuthMessage( msg, [path, msg, from, handler = self->handler, fromIntro = self->fromIntro, shared_key]( - AuthResult result) { - if (result.code == AuthResultCode::eAuthAccepted) + std::string result, bool success) { + if (success) { if (handler->WantsOutboundSession(msg->sender.Addr())) { @@ -358,34 +344,22 @@ namespace llarp::service } handler->PutReplyIntroFor(msg->tag, msg->introReply); handler->PutCachedSessionKeyFor(msg->tag, shared_key); - handler->SendAuthResult(path, from, msg->tag, result); - LogInfo("auth okay for T=", msg->tag, " from ", msg->sender.Addr()); + handler->SendAuthResult(path, from, msg->tag, result, success); + + log::info( + logcat, "Auth accepted for tag {} from sender {}", msg->tag, msg->sender.Addr()); ProtocolMessage::ProcessAsync(path, from, msg); } else { - LogWarn("auth not okay for T=", msg->tag, ": ", result.reason); + log::warning(logcat, "Auth invalid for tag {} (code: {})", msg->tag, result); } + handler->Pump(time_now_ms()); }); } }; - ProtocolFrameMessage& - ProtocolFrameMessage::operator=(const ProtocolFrameMessage& other) - { - cipher = other.cipher; - enc = other.enc; - path_id = other.path_id; - nonce = other.nonce; - sig = other.sig; - convo_tag = other.convo_tag; - flag = other.flag; - sequence_number = other.sequence_number; - version = other.version; - return *this; - } - struct AsyncDecrypt { ServiceInfo si; @@ -478,8 +452,7 @@ namespace llarp::service ProtocolFrameMessage::operator==(const ProtocolFrameMessage& other) const { return cipher == other.cipher && enc == other.enc && nonce == other.nonce && sig == other.sig - && convo_tag == other.convo_tag && sequence_number == other.sequence_number - && version == other.version; + && convo_tag == other.convo_tag; } bool @@ -493,10 +466,9 @@ namespace llarp::service } bool - ProtocolFrameMessage::handle_message( - routing::AbstractRoutingMessageHandler* h, Router* /*r*/) const + ProtocolFrameMessage::handle_message(Router* /*r*/) const { - return h->HandleHiddenServiceFrame(*this); + return true; } } // namespace llarp::service diff --git a/llarp/service/protocol.hpp b/llarp/service/protocol.hpp index e1e2a34837..b7cfd20ba6 100644 --- a/llarp/service/protocol.hpp +++ b/llarp/service/protocol.hpp @@ -29,11 +29,6 @@ namespace llarp constexpr std::size_t MAX_PROTOCOL_MESSAGE_SIZE = 2048 * 2; - /* Note: Talk to Tom and Jason about switching the names of ProtocolFrameMessage (carrier - object) and ProtocolMessage (inner object) to something like ProtocolMessageCarrier and - ProtocolMessage? - */ - /// inner message struct ProtocolMessage { @@ -47,8 +42,7 @@ namespace llarp ServiceInfo sender; Endpoint* handler = nullptr; ConvoTag tag; - uint64_t seqno = 0; - uint64_t version = llarp::constants::proto_version; + std::chrono::milliseconds creation_time{time_now_ms()}; /// encode metainfo for lmq endpoint auth std::vector @@ -61,7 +55,7 @@ namespace llarp bt_encode() const; void - PutBuffer(const llarp_buffer_t& payload); + put_buffer(std::string buf); static void ProcessAsync(path::Path_ptr p, PathID_t from, std::shared_ptr self); @@ -69,12 +63,12 @@ namespace llarp bool operator>(const ProtocolMessage& other) const { - return seqno > other.seqno; + return creation_time > other.creation_time; } }; /// outer message - struct ProtocolFrameMessage final : public routing::AbstractRoutingMessage + struct ProtocolFrameMessage { PQCipherBlock cipher; Encrypted<2048> enc; @@ -84,26 +78,14 @@ namespace llarp PathID_t path_id; service::ConvoTag convo_tag; - ProtocolFrameMessage(const ProtocolFrameMessage& other) - : routing::AbstractRoutingMessage(other) - , cipher(other.cipher) - , enc(other.enc) - , flag(other.flag) - , nonce(other.nonce) - , sig(other.sig) - , path_id(other.path_id) - , convo_tag(other.convo_tag) - { - sequence_number = other.sequence_number; - version = other.version; - } + ProtocolFrameMessage(const ProtocolFrameMessage& other) = default; - ProtocolFrameMessage() : routing::AbstractRoutingMessage{} + ProtocolFrameMessage() { clear(); } - ~ProtocolFrameMessage() override; + ~ProtocolFrameMessage() = default; bool operator==(const ProtocolFrameMessage& other) const; @@ -115,7 +97,7 @@ namespace llarp } ProtocolFrameMessage& - operator=(const ProtocolFrameMessage& other); + operator=(const ProtocolFrameMessage& other) = default; bool EncryptAndSign( @@ -136,7 +118,7 @@ namespace llarp DecryptPayloadInto(const SharedSecret& sharedkey, ProtocolMessage& into) const; bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* val) override; + decode_key(const llarp_buffer_t& key, llarp_buffer_t* val); /** Note: this method needs to be re-examined where it is called in the other class methods, like ::Sign(), ::EncryptAndSign(), and ::Verify(). In all 3 of these cases, the subsequent @@ -144,7 +126,7 @@ namespace llarp redesigned llarp_buffer, or some span backport. */ std::string - bt_encode() const override; + bt_encode() const; bool BDecode(llarp_buffer_t* buf) @@ -153,7 +135,7 @@ namespace llarp } void - clear() override + clear() { cipher.Zero(); enc.Clear(); @@ -162,14 +144,13 @@ namespace llarp nonce.Zero(); sig.Zero(); flag = 0; - version = llarp::constants::proto_version; } bool Verify(const ServiceInfo& from) const; bool - handle_message(routing::AbstractRoutingMessageHandler* h, Router* r) const override; + handle_message(Router* r) const; }; } // namespace service } // namespace llarp diff --git a/llarp/service/sendcontext.cpp b/llarp/service/sendcontext.cpp index 6f7d5586be..ff514c7d2e 100644 --- a/llarp/service/sendcontext.cpp +++ b/llarp/service/sendcontext.cpp @@ -110,7 +110,7 @@ namespace llarp::service f->path_id = m->introReply.path_id; m->sender = service_endpoint->GetIdentity().pub; m->tag = f->convo_tag; - m->PutBuffer(payload); + m->put_buffer(payload); service_endpoint->router()->queue_work([f, m, shared, path, this] { if (not f->EncryptAndSign(*m, shared, service_endpoint->GetIdentity())) { diff --git a/llarp/util/buffer.hpp b/llarp/util/buffer.hpp index 81b623a6f7..e7caa8e21a 100644 --- a/llarp/util/buffer.hpp +++ b/llarp/util/buffer.hpp @@ -182,6 +182,12 @@ struct /* [[deprecated("this type is stupid, use something else")]] */ llarp_buf explicit llarp_buffer_t(T&& t) : llarp_buffer_t{t.data(), t.size()} {} + std::string + to_string() const + { + return {reinterpret_cast(base), sz}; + } + byte_t* begin() { From 66ec886480e9f8492919ac342de8ce6077ca8f84 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 19 Oct 2023 04:49:46 -0700 Subject: [PATCH 064/312] Compilation fixes - almost all errors have been commented out for refactor or already refactored - committing this prior to sorting out the cmake structure - upcoming include-what-you-use application --- llarp/CMakeLists.txt | 24 +- llarp/context.cpp | 25 +- llarp/dht/context.cpp | 7 - llarp/dht/dht.cpp | 61 ++- llarp/dht/explorenetworkjob.cpp | 38 -- llarp/dht/explorenetworkjob.hpp | 30 -- llarp/dht/localrouterlookup.cpp | 61 --- llarp/dht/localrouterlookup.hpp | 27 -- llarp/dht/localserviceaddresslookup.cpp | 58 --- llarp/dht/localserviceaddresslookup.hpp | 28 -- llarp/dht/localtaglookup.cpp | 42 -- llarp/dht/localtaglookup.hpp | 23 -- llarp/dht/message.cpp | 138 ------- llarp/dht/publishservicejob.cpp | 81 ---- llarp/dht/publishservicejob.hpp | 51 --- llarp/dht/recursiverouterlookup.cpp | 71 ---- llarp/dht/recursiverouterlookup.hpp | 34 -- llarp/dht/serviceaddresslookup.cpp | 70 ---- llarp/dht/serviceaddresslookup.hpp | 41 -- llarp/dht/taglookup.cpp | 40 -- llarp/dht/taglookup.hpp | 35 -- llarp/dht/tx.hpp | 106 ++--- llarp/dht/txholder.hpp | 334 ++++++++-------- llarp/dht/txowner.hpp | 67 ++-- llarp/endpoint_base.hpp | 9 +- llarp/exit/endpoint.cpp | 268 ++++++------- llarp/exit/endpoint.hpp | 53 +-- llarp/exit/exit_messages.cpp | 364 ----------------- llarp/exit/exit_messages.hpp | 195 ---------- llarp/exit/session.cpp | 165 ++++---- llarp/exit/session.hpp | 8 +- llarp/handlers/exit.cpp | 18 +- llarp/handlers/exit.hpp | 4 +- llarp/handlers/null.hpp | 11 +- llarp/handlers/tun.cpp | 39 +- llarp/link/connection.cpp | 2 +- llarp/link/connection.hpp | 2 +- llarp/link/link_manager.cpp | 21 +- llarp/link/tunnel.hpp | 15 +- llarp/lokinet_shared.cpp | 39 +- llarp/messages/dht.hpp | 8 +- llarp/messages/discard.hpp | 127 ------ llarp/messages/relay_commit.cpp | 493 ------------------------ llarp/messages/relay_status.cpp | 325 ---------------- llarp/net/traffic_policy.cpp | 4 +- llarp/nodedb.hpp | 2 +- llarp/path/abstracthophandler.hpp | 2 +- llarp/path/path.cpp | 36 +- llarp/path/path.hpp | 4 +- llarp/path/path_context.cpp | 26 -- llarp/path/path_context.hpp | 21 +- llarp/path/pathbuilder.cpp | 6 +- llarp/path/transit_hop.cpp | 22 +- llarp/path/transit_hop.hpp | 9 +- llarp/router/rc_gossiper.cpp | 10 +- llarp/router/rc_lookup_handler.hpp | 5 - llarp/router/router.cpp | 11 +- llarp/router/router.hpp | 21 +- llarp/router_contact.cpp | 14 +- llarp/router_contact.hpp | 4 +- llarp/rpc/endpoint_rpc.cpp | 1 + llarp/rpc/endpoint_rpc.hpp | 5 +- llarp/rpc/rpc_server.cpp | 19 +- llarp/service/auth.cpp | 5 +- llarp/service/endpoint.cpp | 148 +++---- llarp/service/endpoint.hpp | 9 +- llarp/service/endpoint_state.cpp | 105 +++-- llarp/service/endpoint_util.cpp | 263 ++++++------- llarp/service/endpoint_util.hpp | 3 - llarp/service/intro_set.cpp | 2 +- llarp/service/outbound_context.cpp | 111 +++--- llarp/service/outbound_context.hpp | 16 +- llarp/service/protocol.cpp | 10 +- llarp/service/sendcontext.cpp | 168 -------- llarp/service/sendcontext.hpp | 85 ---- llarp/tooling/dht_event.hpp | 130 ------- llarp/tooling/hive_context.cpp | 30 -- llarp/tooling/hive_context.hpp | 28 -- llarp/tooling/hive_router.cpp | 36 -- llarp/tooling/hive_router.hpp | 38 -- llarp/tooling/path_event.hpp | 132 ------- llarp/tooling/peer_stats_event.hpp | 42 -- llarp/tooling/rc_event.hpp | 53 --- llarp/tooling/router_event.hpp | 56 --- llarp/tooling/router_hive.cpp | 249 ------------ llarp/tooling/router_hive.hpp | 95 ----- llarp/util/str.hpp | 3 + 87 files changed, 1024 insertions(+), 4673 deletions(-) delete mode 100644 llarp/dht/explorenetworkjob.cpp delete mode 100644 llarp/dht/explorenetworkjob.hpp delete mode 100644 llarp/dht/localrouterlookup.cpp delete mode 100644 llarp/dht/localrouterlookup.hpp delete mode 100644 llarp/dht/localserviceaddresslookup.cpp delete mode 100644 llarp/dht/localserviceaddresslookup.hpp delete mode 100644 llarp/dht/localtaglookup.cpp delete mode 100644 llarp/dht/localtaglookup.hpp delete mode 100644 llarp/dht/message.cpp delete mode 100644 llarp/dht/publishservicejob.cpp delete mode 100644 llarp/dht/publishservicejob.hpp delete mode 100644 llarp/dht/recursiverouterlookup.cpp delete mode 100644 llarp/dht/recursiverouterlookup.hpp delete mode 100644 llarp/dht/serviceaddresslookup.cpp delete mode 100644 llarp/dht/serviceaddresslookup.hpp delete mode 100644 llarp/dht/taglookup.cpp delete mode 100644 llarp/dht/taglookup.hpp delete mode 100644 llarp/exit/exit_messages.cpp delete mode 100644 llarp/exit/exit_messages.hpp delete mode 100644 llarp/messages/discard.hpp delete mode 100644 llarp/messages/relay_commit.cpp delete mode 100644 llarp/messages/relay_status.cpp delete mode 100644 llarp/service/sendcontext.cpp delete mode 100644 llarp/service/sendcontext.hpp delete mode 100644 llarp/tooling/dht_event.hpp delete mode 100644 llarp/tooling/hive_context.cpp delete mode 100644 llarp/tooling/hive_context.hpp delete mode 100644 llarp/tooling/hive_router.cpp delete mode 100644 llarp/tooling/hive_router.hpp delete mode 100644 llarp/tooling/path_event.hpp delete mode 100644 llarp/tooling/peer_stats_event.hpp delete mode 100644 llarp/tooling/rc_event.hpp delete mode 100644 llarp/tooling/router_event.hpp delete mode 100644 llarp/tooling/router_hive.cpp delete mode 100644 llarp/tooling/router_hive.hpp diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index e42eca201d..cc2d51d5e4 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -206,7 +206,6 @@ add_library(lokinet-service-deprecated-kitchensink endpoint_base.cpp exit/context.cpp exit/endpoint.cpp - exit/exit_messages.cpp exit/policy.cpp exit/session.cpp handlers/exit.cpp @@ -228,24 +227,10 @@ add_library(lokinet-service-deprecated-kitchensink service/name.cpp service/outbound_context.cpp service/protocol.cpp - service/sendcontext.cpp service/session.cpp service/tag.cpp ) - -# interal tooling for pybind -add_library(lokinet-tooling INTERFACE) -if(WITH_HIVE) - add_library(lokinet-hive-tooling - STATIC - tooling/router_hive.cpp - tooling/hive_router.cpp - tooling/hive_context.cpp - ) - target_link_libraries(lokinet-tooling INTERFACE lokinet-hive-tooling) -endif() - # interface library for setting commone includes, linkage and flags. add_library(lokinet-base INTERFACE) target_include_directories(lokinet-base @@ -264,7 +249,8 @@ add_library(lokinet-amalgum INTERFACE) # helper function to link a library to lokinet-base, enable lto, add to lokinet-amalgum and then link to other libs function(lokinet_link_lib libname) - message(DEBUG "created target: ${libname}") + # Absolutely fuck this line, it doesn't "create" the target, as the target already exists + # message(DEBUG "created target: ${libname}") enable_lto(${libname}) target_link_libraries(${libname} PUBLIC lokinet-base ${ARGN}) target_link_libraries(lokinet-amalgum INTERFACE ${libname}) @@ -275,11 +261,7 @@ lokinet_link_lib(lokinet-util lokinet-libntrup) lokinet_link_lib(lokinet-cryptography lokinet-libcrypt lokinet-util) lokinet_link_lib(lokinet-peerstats lokinet-context) lokinet_link_lib(lokinet-consensus lokinet-context) -lokinet_link_lib(lokinet-layer-link lokinet-peerstats) - -if(TARGET lokinet-hive-tooling) - lokinet_link_lib(lokinet-hive-tooling lokinet-context) -endif() +lokinet_link_lib(lokinet-layer-link lokinet-cryptography lokinet-peerstats) if(TARGET lokinet-dns-systemd) lokinet_link_lib(lokinet-dns-systemd diff --git a/llarp/context.cpp b/llarp/context.cpp index 990020346d..df1f320e88 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -1,22 +1,21 @@ -#include -#include "constants/version.hpp" -#include "constants/evloop.hpp" - -#include "config/config.hpp" -#include "crypto/crypto.hpp" -#include "ev/ev.hpp" -#include #include "nodedb.hpp" -#include "router/router.hpp" -#include "service/context.hpp" -#include "util/logging.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include #include +#include #include #include @@ -89,7 +88,9 @@ namespace llarp Context::makeNodeDB() { return std::make_shared( - nodedb_dirname, [r = router.get()](auto call) { r->queue_disk_io(std::move(call)); }); + nodedb_dirname, + [r = router.get()](auto call) { r->queue_disk_io(std::move(call)); }, + router.get()); } std::shared_ptr diff --git a/llarp/dht/context.cpp b/llarp/dht/context.cpp index 4bbc4572a3..bec9eda83e 100644 --- a/llarp/dht/context.cpp +++ b/llarp/dht/context.cpp @@ -1,22 +1,15 @@ -#include "context.hpp" #include "explorenetworkjob.hpp" #include "localrouterlookup.hpp" #include "localserviceaddresslookup.hpp" #include "localtaglookup.hpp" -#include -#include -#include -#include #include "node.hpp" #include "publishservicejob.hpp" #include "recursiverouterlookup.hpp" #include "serviceaddresslookup.hpp" #include "taglookup.hpp" -#include #include #include -#include #include #include #include diff --git a/llarp/dht/dht.cpp b/llarp/dht/dht.cpp index 8b1b1b4fcc..ba8149feca 100644 --- a/llarp/dht/dht.cpp +++ b/llarp/dht/dht.cpp @@ -1,42 +1,41 @@ -#include "context.hpp" #include "dht.h" #include -llarp_dht_context::llarp_dht_context(llarp::Router* router) -{ - parent = router; - impl = llarp::dht::make_handler(); -} +// llarp_dht_context::llarp_dht_context(llarp::Router* router) +// { +// parent = router; +// impl = llarp::dht::make_handler(); +// } -struct llarp_dht_context* -llarp_dht_context_new(llarp::Router* router) -{ - return new llarp_dht_context(router); -} +// struct llarp_dht_context* +// llarp_dht_context_new(llarp::Router* router) +// { +// return new llarp_dht_context(router); +// } -void -llarp_dht_context_free(struct llarp_dht_context* ctx) -{ - delete ctx; -} +// void +// llarp_dht_context_free(struct llarp_dht_context* ctx) +// { +// delete ctx; +// } -void -__llarp_dht_remove_peer(struct llarp_dht_context* ctx, const byte_t* id) -{ - ctx->impl->Nodes()->DelNode(llarp::dht::Key_t(id)); -} +// void +// __llarp_dht_remove_peer(struct llarp_dht_context* ctx, const byte_t* id) +// { +// ctx->impl->Nodes()->DelNode(llarp::dht::Key_t(id)); +// } -void -llarp_dht_allow_transit(llarp_dht_context* ctx) -{ - ctx->impl->AllowTransit() = true; -} +// void +// llarp_dht_allow_transit(llarp_dht_context* ctx) +// { +// ctx->impl->AllowTransit() = true; +// } -void -llarp_dht_context_start(struct llarp_dht_context* ctx, const byte_t* key) -{ - ctx->impl->Init(llarp::dht::Key_t(key), ctx->parent); -} +// void +// llarp_dht_context_start(struct llarp_dht_context* ctx, const byte_t* key) +// { +// ctx->impl->Init(llarp::dht::Key_t(key), ctx->parent); +// } void llarp_dht_lookup_router(struct llarp_dht_context* ctx, struct llarp_router_lookup_job* job) diff --git a/llarp/dht/explorenetworkjob.cpp b/llarp/dht/explorenetworkjob.cpp deleted file mode 100644 index e0b96dd672..0000000000 --- a/llarp/dht/explorenetworkjob.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "explorenetworkjob.hpp" - -#include - -#include - -#include - -namespace llarp::dht -{ - void - ExploreNetworkJob::Start(const TXOwner& peer) - { - auto msg = new FindRouterMessage(peer.txid); - auto router = parent->GetRouter(); - if (router) - { - router->notify_router_event(router->pubkey(), *msg); - } - parent->DHTSendTo(peer.node.as_array(), msg); - } - - void - ExploreNetworkJob::SendReply() - { - llarp::LogDebug("got ", valuesFound.size(), " routers from exploration"); - - auto router = parent->GetRouter(); - for (const auto& pk : valuesFound) - { - // lookup router - if (router and router->node_db()->Has(pk)) - continue; - parent->LookupRouter( - pk, [router, pk](const auto& res) { router->HandleDHTLookupForExplore(pk, res); }); - } - } -} // namespace llarp::dht diff --git a/llarp/dht/explorenetworkjob.hpp b/llarp/dht/explorenetworkjob.hpp deleted file mode 100644 index 472246f83e..0000000000 --- a/llarp/dht/explorenetworkjob.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef LLARP_DHT_EXPLORENETWORKJOB -#define LLARP_DHT_EXPLORENETWORKJOB - -#include "tx.hpp" -#include - -namespace llarp::dht -{ - struct ExploreNetworkJob : public TX - { - ExploreNetworkJob(const RouterID& peer, AbstractDHTMessageHandler* ctx) - : TX(TXOwner{}, peer, ctx) - {} - - bool - Validate(const RouterID&) const override - { - // TODO: check with lokid - return true; - } - - void - Start(const TXOwner& peer) override; - - void - SendReply() override; - }; -} // namespace llarp::dht - -#endif diff --git a/llarp/dht/localrouterlookup.cpp b/llarp/dht/localrouterlookup.cpp deleted file mode 100644 index aeb8fafa95..0000000000 --- a/llarp/dht/localrouterlookup.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "localrouterlookup.hpp" - -#include "context.hpp" -#include - -#include -#include -#include -#include - -namespace llarp::dht -{ - LocalRouterLookup::LocalRouterLookup( - const PathID_t& path, uint64_t txid, const RouterID& _target, AbstractDHTMessageHandler* ctx) - : RecursiveRouterLookup(TXOwner{ctx->OurKey(), txid}, _target, ctx, nullptr), localPath(path) - {} - - void - LocalRouterLookup::SendReply() - { - auto path = - parent->GetRouter()->path_context().GetByUpstream(parent->OurKey().as_array(), localPath); - if (!path) - { - llarp::LogWarn( - "did not send reply for relayed dht request, no such local path " - "for pathid=", - localPath); - return; - } - if (valuesFound.size()) - { - RouterContact found; - for (const auto& rc : valuesFound) - { - if (rc.OtherIsNewer(found)) - found = rc; - } - valuesFound.clear(); - if (not found.pubkey.IsZero()) - { - valuesFound.resize(1); - valuesFound[0] = found; - } - else - { - llarp::LogWarn("We found a null RC for dht request, dropping it"); - } - } - routing::PathDHTMessage msg; - msg.dht_msgs.emplace_back( - new GotRouterMessage(parent->OurKey(), whoasked.txid, valuesFound, true)); - if (!path->SendRoutingMessage(msg, parent->GetRouter())) - { - llarp::LogWarn( - "failed to send routing message when informing result of dht " - "request, pathid=", - localPath); - } - } -} // namespace llarp::dht diff --git a/llarp/dht/localrouterlookup.hpp b/llarp/dht/localrouterlookup.hpp deleted file mode 100644 index fc7b4b0299..0000000000 --- a/llarp/dht/localrouterlookup.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef LLARP_DHT_LOCALROUTERLOOKUP -#define LLARP_DHT_LOCALROUTERLOOKUP - -#include "recursiverouterlookup.hpp" - -#include -#include -#include - -namespace llarp::dht -{ - struct LocalRouterLookup : public RecursiveRouterLookup - { - PathID_t localPath; - - LocalRouterLookup( - const PathID_t& path, - uint64_t txid, - const RouterID& target, - AbstractDHTMessageHandler* ctx); - - void - SendReply() override; - }; -} // namespace llarp::dht - -#endif diff --git a/llarp/dht/localserviceaddresslookup.cpp b/llarp/dht/localserviceaddresslookup.cpp deleted file mode 100644 index 45333d61fe..0000000000 --- a/llarp/dht/localserviceaddresslookup.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "localserviceaddresslookup.hpp" - -#include "context.hpp" -#include -#include -#include -#include -#include - -namespace llarp::dht -{ - LocalServiceAddressLookup::LocalServiceAddressLookup( - const PathID_t& pathid, - uint64_t txid, - uint64_t relayOrder, - const Key_t& addr, - AbstractDHTMessageHandler* ctx, - [[maybe_unused]] const Key_t& askpeer) - : ServiceAddressLookup(TXOwner{ctx->OurKey(), txid}, addr, ctx, relayOrder, nullptr) - , localPath(pathid) - {} - - void - LocalServiceAddressLookup::SendReply() - { - auto path = - parent->GetRouter()->path_context().GetByUpstream(parent->OurKey().as_array(), localPath); - if (!path) - { - llarp::LogWarn( - "did not send reply for relayed dht request, no such local path " - "for pathid=", - localPath); - return; - } - // pick newest if we have more than 1 result - if (valuesFound.size()) - { - service::EncryptedIntroSet found; - for (const auto& introset : valuesFound) - { - if (found.OtherIsNewer(introset)) - found = introset; - } - valuesFound.clear(); - valuesFound.emplace_back(found); - } - routing::PathDHTMessage msg; - msg.dht_msgs.emplace_back(new GotIntroMessage(valuesFound, whoasked.txid)); - if (!path->SendRoutingMessage(msg, parent->GetRouter())) - { - llarp::LogWarn( - "failed to send routing message when informing result of dht " - "request, pathid=", - localPath); - } - } -} // namespace llarp::dht diff --git a/llarp/dht/localserviceaddresslookup.hpp b/llarp/dht/localserviceaddresslookup.hpp deleted file mode 100644 index 8263cab6ee..0000000000 --- a/llarp/dht/localserviceaddresslookup.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef LLARP_DHT_LOCALSERVICEADDRESSLOOKUP -#define LLARP_DHT_LOCALSERVICEADDRESSLOOKUP - -#include "serviceaddresslookup.hpp" - -#include - -namespace llarp::dht -{ - struct LocalServiceAddressLookup : public ServiceAddressLookup - { - PathID_t localPath; - - LocalServiceAddressLookup( - const PathID_t& pathid, - uint64_t txid, - uint64_t relayOrder, - const Key_t& addr, - AbstractDHTMessageHandler* ctx, - [[maybe_unused]] const Key_t& askpeer); - - void - SendReply() override; - }; - -} // namespace llarp::dht - -#endif diff --git a/llarp/dht/localtaglookup.cpp b/llarp/dht/localtaglookup.cpp deleted file mode 100644 index 435d770a7a..0000000000 --- a/llarp/dht/localtaglookup.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "localtaglookup.hpp" - -#include "context.hpp" -#include -#include -#include -#include - -namespace llarp::dht -{ - LocalTagLookup::LocalTagLookup( - const PathID_t& path, - uint64_t txid, - const service::Tag& _target, - AbstractDHTMessageHandler* ctx) - : TagLookup(TXOwner{ctx->OurKey(), txid}, _target, ctx, 0), localPath(path) - {} - - void - LocalTagLookup::SendReply() - { - auto path = - parent->GetRouter()->path_context().GetByUpstream(parent->OurKey().as_array(), localPath); - if (!path) - { - llarp::LogWarn( - "did not send reply for relayed dht request, no such local path " - "for pathid=", - localPath); - return; - } - routing::PathDHTMessage msg; - msg.dht_msgs.emplace_back(new GotIntroMessage(valuesFound, whoasked.txid)); - if (!path->SendRoutingMessage(msg, parent->GetRouter())) - { - llarp::LogWarn( - "failed to send routing message when informing result of dht " - "request, pathid=", - localPath); - } - } -} // namespace llarp::dht diff --git a/llarp/dht/localtaglookup.hpp b/llarp/dht/localtaglookup.hpp deleted file mode 100644 index d9e3d7de3b..0000000000 --- a/llarp/dht/localtaglookup.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef LLARP_DHT_LOOKUPTAGLOOKUP -#define LLARP_DHT_LOOKUPTAGLOOKUP - -#include "taglookup.hpp" - -namespace llarp::dht -{ - struct LocalTagLookup : public TagLookup - { - PathID_t localPath; - - LocalTagLookup( - const PathID_t& path, - uint64_t txid, - const service::Tag& target, - AbstractDHTMessageHandler* ctx); - - void - SendReply() override; - }; -} // namespace llarp::dht - -#endif diff --git a/llarp/dht/message.cpp b/llarp/dht/message.cpp deleted file mode 100644 index b11ee145c3..0000000000 --- a/llarp/dht/message.cpp +++ /dev/null @@ -1,138 +0,0 @@ -#include "context.hpp" -#include "oxenc/bt_serialize.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace llarp::dht -{ - struct MessageDecoder - { - const Key_t& From; - std::unique_ptr msg; - bool firstKey = true; - bool relayed = false; - - MessageDecoder(const Key_t& from, bool wasRelayed) : From(from), relayed(wasRelayed) - {} - - bool - operator()(llarp_buffer_t* buffer, llarp_buffer_t* key) - { - llarp_buffer_t strbuf; - // check for empty dict - if (!key) - return !firstKey; - // first key - if (firstKey) - { - if (!(key->startswith("A"))) - return false; - if (!bencode_read_string(buffer, &strbuf)) - return false; - // bad msg size? - if (strbuf.sz != 1) - return false; - llarp::LogDebug("Handle DHT message ", *strbuf.base, " relayed=", relayed); - switch (*strbuf.base) - { - case 'N': - msg = std::make_unique(From, Key_t{}, 0); - break; - case 'M': - msg = std::make_unique(From, 0, service::EncryptedName{}); - break; - case 'F': - msg = std::make_unique(From, relayed, 0); - break; - case 'R': - if (relayed) - msg = std::make_unique(From); - else - msg = std::make_unique(From); - break; - case 'S': - msg = std::make_unique(From, relayed); - break; - case 'I': - msg = std::make_unique(From, relayed); - break; - case 'G': - if (relayed) - { - msg = std::make_unique(); - break; - } - else - { - msg = std::make_unique(From); - break; - } - default: - llarp::LogWarn("unknown dht message type: ", (char)*strbuf.base); - // bad msg type - return false; - } - firstKey = false; - return msg != nullptr; - } - - return msg->decode_key(*key, buffer); - } - }; - - std::unique_ptr - DecodeMessage(const Key_t& from, llarp_buffer_t* buf, bool relayed) - { - MessageDecoder dec(from, relayed); - if (!bencode_read_dict(dec, buf)) - return nullptr; - - return std::move(dec.msg); - } - - struct ListDecoder - { - ListDecoder( - bool hasRelayed, const Key_t& from, std::vector>& list) - : relayed(hasRelayed), From(from), l(list) - {} - - bool relayed; - const Key_t& From; - std::vector>& l; - - bool - operator()(llarp_buffer_t* buffer, bool has) - { - if (!has) - return true; - auto msg = DecodeMessage(From, buffer, relayed); - if (msg) - { - l.emplace_back(std::move(msg)); - return true; - } - - return false; - } - }; - - bool - DecodeMessageList( - Key_t from, - llarp_buffer_t* buf, - std::vector>& list, - bool relayed) - { - ListDecoder dec(relayed, from, list); - return bencode_read_list(dec, buf); - } -} // namespace llarp::dht diff --git a/llarp/dht/publishservicejob.cpp b/llarp/dht/publishservicejob.cpp deleted file mode 100644 index 62011853e4..0000000000 --- a/llarp/dht/publishservicejob.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "publishservicejob.hpp" - -#include "context.hpp" -#include -#include -#include -#include -#include - -#include -namespace llarp::dht -{ - PublishServiceJob::PublishServiceJob( - const TXOwner& asker, - const service::EncryptedIntroSet& introset_, - AbstractDHTMessageHandler* ctx, - uint64_t relayOrder_) - : TX(asker, asker, ctx) - , relayOrder(relayOrder_) - , introset(introset_) - {} - - bool - PublishServiceJob::Validate(const service::EncryptedIntroSet& value) const - { - if (value.derivedSigningKey != introset.derivedSigningKey) - { - llarp::LogWarn("publish introset acknowledgement acked a different service"); - return false; - } - const llarp_time_t now = llarp::time_now_ms(); - return value.verify(now); - } - - void - PublishServiceJob::Start(const TXOwner& peer) - { - parent->DHTSendTo( - peer.node.as_array(), new PublishIntroMessage(introset, peer.txid, false, relayOrder)); - } - - void - PublishServiceJob::SendReply() - { - parent->DHTSendTo(whoasked.node.as_array(), new GotIntroMessage({introset}, whoasked.txid)); - } - - LocalPublishServiceJob::LocalPublishServiceJob( - const TXOwner& peer, - const PathID_t& fromID, - uint64_t _txid, - const service::EncryptedIntroSet& introset, - AbstractDHTMessageHandler* ctx, - uint64_t relayOrder) - : PublishServiceJob(peer, introset, ctx, relayOrder), localPath(fromID), txid(_txid) - {} - - void - LocalPublishServiceJob::SendReply() - { - auto path = - parent->GetRouter()->path_context().GetByUpstream(parent->OurKey().as_array(), localPath); - if (!path) - { - llarp::LogWarn( - "did not send reply for relayed dht request, no such local path " - "for pathid=", - localPath); - return; - } - routing::PathDHTMessage msg; - msg.dht_msgs.emplace_back(new GotIntroMessage({introset}, txid)); - if (!path->SendRoutingMessage(msg, parent->GetRouter())) - { - llarp::LogWarn( - "failed to send routing message when informing result of dht " - "request, pathid=", - localPath); - } - } -} // namespace llarp::dht diff --git a/llarp/dht/publishservicejob.hpp b/llarp/dht/publishservicejob.hpp deleted file mode 100644 index c0badfe8fd..0000000000 --- a/llarp/dht/publishservicejob.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef LLARP_DHT_PUBLISHSERVICEJOB -#define LLARP_DHT_PUBLISHSERVICEJOB - -#include "tx.hpp" -#include "txowner.hpp" -#include -#include - -#include - -namespace llarp::dht -{ - struct PublishServiceJob : public TX - { - uint64_t relayOrder; - service::EncryptedIntroSet introset; - - PublishServiceJob( - const TXOwner& asker, - const service::EncryptedIntroSet& introset, - AbstractDHTMessageHandler* ctx, - uint64_t relayOrder); - - bool - Validate(const service::EncryptedIntroSet& introset) const override; - - void - Start(const TXOwner& peer) override; - - void - SendReply() override; - }; - - struct LocalPublishServiceJob : public PublishServiceJob - { - PathID_t localPath; - uint64_t txid; - LocalPublishServiceJob( - const TXOwner& peer, - const PathID_t& fromID, - uint64_t txid, - const service::EncryptedIntroSet& introset, - AbstractDHTMessageHandler* ctx, - uint64_t relayOrder); - - void - SendReply() override; - }; -} // namespace llarp::dht - -#endif diff --git a/llarp/dht/recursiverouterlookup.cpp b/llarp/dht/recursiverouterlookup.cpp deleted file mode 100644 index 6ae5096a1a..0000000000 --- a/llarp/dht/recursiverouterlookup.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "recursiverouterlookup.hpp" - -#include "context.hpp" -#include -#include - -#include -#include - -#include - -namespace llarp -{ - namespace dht - { - RecursiveRouterLookup::RecursiveRouterLookup( - const TXOwner& _whoasked, - const RouterID& _target, - AbstractDHTMessageHandler* ctx, - RouterLookupHandler result) - : TX(_whoasked, _target, ctx), resultHandler(std::move(result)) - - { - peersAsked.insert(ctx->OurKey()); - } - - bool - RecursiveRouterLookup::Validate(const RouterContact& rc) const - { - if (!rc.Verify(parent->Now())) - { - llarp::LogWarn("rc from lookup result is invalid"); - return false; - } - return true; - } - - void - RecursiveRouterLookup::Start(const TXOwner& peer) - { - parent->DHTSendTo(peer.node.as_array(), new FindRouterMessage(peer.txid, target)); - } - - void - RecursiveRouterLookup::SendReply() - { - if (valuesFound.size()) - { - RouterContact found; - for (const auto& rc : valuesFound) - { - if (found.OtherIsNewer(rc) && parent->GetRouter()->rc_lookup_handler().check_rc(rc)) - found = rc; - } - valuesFound.clear(); - valuesFound.emplace_back(found); - } - if (resultHandler) - { - resultHandler(valuesFound); - } - if (whoasked.node != parent->OurKey()) - { - parent->DHTSendTo( - whoasked.node.as_array(), - new GotRouterMessage({}, whoasked.txid, valuesFound, false), - false); - } - } - } // namespace dht -} // namespace llarp diff --git a/llarp/dht/recursiverouterlookup.hpp b/llarp/dht/recursiverouterlookup.hpp deleted file mode 100644 index 8e592547e1..0000000000 --- a/llarp/dht/recursiverouterlookup.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef LLARP_DHT_RECURSIVEROUTERLOOKUP -#define LLARP_DHT_RECURSIVEROUTERLOOKUP - -#include "tx.hpp" - -#include -#include - -namespace llarp -{ - namespace dht - { - struct RecursiveRouterLookup : public TX - { - RouterLookupHandler resultHandler; - RecursiveRouterLookup( - const TXOwner& whoasked, - const RouterID& target, - AbstractDHTMessageHandler* ctx, - RouterLookupHandler result); - - bool - Validate(const RouterContact& rc) const override; - - void - Start(const TXOwner& peer) override; - - void - SendReply() override; - }; - } // namespace dht -} // namespace llarp - -#endif diff --git a/llarp/dht/serviceaddresslookup.cpp b/llarp/dht/serviceaddresslookup.cpp deleted file mode 100644 index 44dc38b063..0000000000 --- a/llarp/dht/serviceaddresslookup.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "serviceaddresslookup.hpp" - -#include -#include -#include - -namespace llarp -{ - namespace dht - { - ServiceAddressLookup::ServiceAddressLookup( - const TXOwner& asker, - const Key_t& addr, - AbstractDHTMessageHandler* ctx, - uint32_t order, - service::EncryptedIntroSetLookupHandler handler) - : TX(asker, asker, ctx) - , location(addr) - , handleResult(std::move(handler)) - , relayOrder(order) - { - peersAsked.insert(ctx->OurKey()); - } - - bool - ServiceAddressLookup::Validate(const service::EncryptedIntroSet& value) const - { - if (!value.verify(parent->Now())) - { - llarp::LogWarn("Got invalid introset from service lookup"); - return false; - } - if (value.derivedSigningKey != location) - { - llarp::LogWarn("got introset with wrong target from service lookup"); - return false; - } - return true; - } - - void - ServiceAddressLookup::Start(const TXOwner& peer) - { - parent->DHTSendTo( - peer.node.as_array(), new FindIntroMessage(peer.txid, location, relayOrder)); - } - - void - ServiceAddressLookup::SendReply() - { - // get newest introset - if (valuesFound.size()) - { - llarp::service::EncryptedIntroSet found; - for (const auto& introset : valuesFound) - { - if (found.OtherIsNewer(introset)) - found = introset; - } - valuesFound.clear(); - valuesFound.emplace_back(found); - } - if (handleResult) - { - handleResult(valuesFound); - } - parent->DHTSendTo(whoasked.node.as_array(), new GotIntroMessage(valuesFound, whoasked.txid)); - } - } // namespace dht -} // namespace llarp diff --git a/llarp/dht/serviceaddresslookup.hpp b/llarp/dht/serviceaddresslookup.hpp deleted file mode 100644 index ad642727f9..0000000000 --- a/llarp/dht/serviceaddresslookup.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef LLARP_DHT_SERVICEADDRESSLOOKUP -#define LLARP_DHT_SERVICEADDRESSLOOKUP - -#include "key.hpp" -#include "tx.hpp" -#include -#include - -namespace llarp -{ - namespace dht - { - struct TXOwner; - - struct ServiceAddressLookup : public TX - { - Key_t location; - service::EncryptedIntroSetLookupHandler handleResult; - uint32_t relayOrder; - - ServiceAddressLookup( - const TXOwner& asker, - const Key_t& addr, - AbstractDHTMessageHandler* ctx, - uint32_t relayOrder, - service::EncryptedIntroSetLookupHandler handler); - - bool - Validate(const service::EncryptedIntroSet& value) const override; - - void - Start(const TXOwner& peer) override; - - void - SendReply() override; - }; - } // namespace dht - -} // namespace llarp - -#endif diff --git a/llarp/dht/taglookup.cpp b/llarp/dht/taglookup.cpp deleted file mode 100644 index 5f0aa21f65..0000000000 --- a/llarp/dht/taglookup.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "taglookup.hpp" - -#include "context.hpp" -#include - -namespace llarp -{ - namespace dht - { - bool - TagLookup::Validate(const service::EncryptedIntroSet& introset) const - { - if (!introset.verify(parent->Now())) - { - llarp::LogWarn("got invalid introset from tag lookup"); - return false; - } - if (not introset.topic) - return false; - if (*introset.topic != target) - { - llarp::LogWarn("got introset with mismatched topic in tag lookup"); - return false; - } - return true; - } - - void - TagLookup::Start(const TXOwner& peer) - { - parent->DHTSendTo(peer.node.as_array(), new FindIntroMessage(target, peer.txid)); - } - - void - TagLookup::SendReply() - { - parent->DHTSendTo(whoasked.node.as_array(), new GotIntroMessage({}, whoasked.txid)); - } - } // namespace dht -} // namespace llarp diff --git a/llarp/dht/taglookup.hpp b/llarp/dht/taglookup.hpp deleted file mode 100644 index 8a96c14bcd..0000000000 --- a/llarp/dht/taglookup.hpp +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef LLARP_DHT_TAGLOOKUP -#define LLARP_DHT_TAGLOOKUP - -#include "tx.hpp" -#include -#include - -namespace llarp -{ - namespace dht - { - struct TagLookup : public TX - { - uint64_t recursionDepth; - TagLookup( - const TXOwner& asker, - const service::Tag& tag, - AbstractDHTMessageHandler* ctx, - uint64_t recursion) - : TX(asker, tag, ctx), recursionDepth(recursion) - {} - - bool - Validate(const service::EncryptedIntroSet& introset) const override; - - void - Start(const TXOwner& peer) override; - - void - SendReply() override; - }; - } // namespace dht -} // namespace llarp - -#endif diff --git a/llarp/dht/tx.hpp b/llarp/dht/tx.hpp index 72a75fca3e..b2c3ebc87a 100644 --- a/llarp/dht/tx.hpp +++ b/llarp/dht/tx.hpp @@ -3,77 +3,77 @@ #include "key.hpp" #include "txowner.hpp" + #include #include #include #include -namespace llarp::dht +namespace llarp { - struct AbstractDHTMessageHandler; + struct Router; - template - struct TX + namespace dht { - K target; - AbstractDHTMessageHandler* parent; - std::set peersAsked; - std::vector valuesFound; - TXOwner whoasked; - - TX(const TXOwner& asker, const K& k, AbstractDHTMessageHandler* p) - : target(k), parent(p), whoasked(asker) - {} + template + struct TX + { + K target; + Router* router; + std::set peersAsked; + std::vector valuesFound; + TXOwner whoasked; - virtual ~TX() = default; + TX(const TXOwner& asker, const K& k, Router* r) : target(k), router{r}, whoasked(asker) + {} - void - OnFound(const Key_t& askedPeer, const V& value); + virtual ~TX() = default; - util::StatusObject - ExtractStatus() const - { - util::StatusObject obj{ - {"whoasked", whoasked.ExtractStatus()}, {"target", target.ExtractStatus()}}; - std::vector foundObjs; - std::transform( - valuesFound.begin(), - valuesFound.end(), - std::back_inserter(foundObjs), - [](const auto& item) -> util::StatusObject { return item.ExtractStatus(); }); + void + OnFound(const Key_t& askedPeer, const V& value); - obj["found"] = foundObjs; - std::vector asked; - std::transform( - peersAsked.begin(), - peersAsked.end(), - std::back_inserter(asked), - [](const auto& item) -> std::string { return item.ToString(); }); - obj["asked"] = asked; - return obj; - } + util::StatusObject + ExtractStatus() const + { + util::StatusObject obj{ + {"whoasked", whoasked.ExtractStatus()}, {"target", target.ExtractStatus()}}; + std::vector foundObjs; + std::transform( + valuesFound.begin(), + valuesFound.end(), + std::back_inserter(foundObjs), + [](const auto& item) -> util::StatusObject { return item.ExtractStatus(); }); - virtual bool - Validate(const V& value) const = 0; + obj["found"] = foundObjs; + std::vector asked; + std::transform( + peersAsked.begin(), + peersAsked.end(), + std::back_inserter(asked), + [](const auto& item) -> std::string { return item.ToString(); }); + obj["asked"] = asked; + return obj; + } - virtual void - Start(const TXOwner& peer) = 0; + virtual bool + Validate(const V& value) const = 0; - virtual void - SendReply() = 0; - }; + virtual void + Start(const TXOwner& peer) = 0; + }; - template - inline void - TX::OnFound(const Key_t& askedPeer, const V& value) - { - peersAsked.insert(askedPeer); - if (Validate(value)) + template + inline void + TX::OnFound(const Key_t& askedPeer, const V& value) { - valuesFound.push_back(value); + peersAsked.insert(askedPeer); + if (Validate(value)) + { + valuesFound.push_back(value); + } } - } -} // namespace llarp::dht + } // namespace dht +} // namespace llarp #endif diff --git a/llarp/dht/txholder.hpp b/llarp/dht/txholder.hpp index b175861740..c75effe710 100644 --- a/llarp/dht/txholder.hpp +++ b/llarp/dht/txholder.hpp @@ -9,208 +9,204 @@ #include #include -namespace llarp +namespace llarp::dht { - namespace dht + template + struct TXHolder { - template - struct TXHolder - { - using TXPtr = std::unique_ptr>; - // tx who are waiting for a reply for each key - std::unordered_multimap waiting; - // tx timesouts by key - std::unordered_map timeouts; - // maps remote peer with tx to handle reply from them - std::unordered_map tx; - - const TX* - GetPendingLookupFrom(const TXOwner& owner) const; - - util::StatusObject - ExtractStatus() const - { - util::StatusObject obj{}; - std::vector txObjs, timeoutsObjs, waitingObjs; - std::transform( - tx.begin(), - tx.end(), - std::back_inserter(txObjs), - [](const auto& item) -> util::StatusObject { - return util::StatusObject{ - {"owner", item.first.ExtractStatus()}, {"tx", item.second->ExtractStatus()}}; - }); - obj["tx"] = txObjs; - std::transform( - timeouts.begin(), - timeouts.end(), - std::back_inserter(timeoutsObjs), - [](const auto& item) -> util::StatusObject { - return util::StatusObject{ - {"time", to_json(item.second)}, {"target", item.first.ExtractStatus()}}; - }); - obj["timeouts"] = timeoutsObjs; - std::transform( - waiting.begin(), - waiting.end(), - std::back_inserter(waitingObjs), - [](const auto& item) -> util::StatusObject { - return util::StatusObject{ - {"target", item.first.ExtractStatus()}, - {"whoasked", item.second.ExtractStatus()}}; - }); - obj["waiting"] = waitingObjs; - return obj; - } - - bool - HasLookupFor(const K& target) const - { - return timeouts.find(target) != timeouts.end(); - } - - bool - HasPendingLookupFrom(const TXOwner& owner) const - { - return GetPendingLookupFrom(owner) != nullptr; - } + using TXPtr = std::unique_ptr>; + // tx who are waiting for a reply for each key + std::unordered_multimap waiting; + // tx timesouts by key + std::unordered_map timeouts; + // maps remote peer with tx to handle reply from them + std::unordered_map tx; - void - NewTX( - const TXOwner& askpeer, - const TXOwner& whoasked, - const K& k, - TX* t, - llarp_time_t requestTimeoutMS = 15s); - - /// mark tx as not fond - void - NotFound(const TXOwner& from, const std::unique_ptr& next); - - void - Found(const TXOwner& from, const K& k, const std::vector& values) - { - Inform(from, k, values, true); - } - - /// inform all watches for key of values found - void - Inform( - TXOwner from, - K key, - std::vector values, - bool sendreply = false, - bool removeTimeouts = true); + const TX* + GetPendingLookupFrom(const TXOwner& owner) const; - void - Expire(llarp_time_t now); - }; + util::StatusObject + ExtractStatus() const + { + util::StatusObject obj{}; + std::vector txObjs, timeoutsObjs, waitingObjs; + std::transform( + tx.begin(), + tx.end(), + std::back_inserter(txObjs), + [](const auto& item) -> util::StatusObject { + return util::StatusObject{ + {"owner", item.first.ExtractStatus()}, {"tx", item.second->ExtractStatus()}}; + }); + obj["tx"] = txObjs; + std::transform( + timeouts.begin(), + timeouts.end(), + std::back_inserter(timeoutsObjs), + [](const auto& item) -> util::StatusObject { + return util::StatusObject{ + {"time", to_json(item.second)}, {"target", item.first.ExtractStatus()}}; + }); + obj["timeouts"] = timeoutsObjs; + std::transform( + waiting.begin(), + waiting.end(), + std::back_inserter(waitingObjs), + [](const auto& item) -> util::StatusObject { + return util::StatusObject{ + {"target", item.first.ExtractStatus()}, {"whoasked", item.second.ExtractStatus()}}; + }); + obj["waiting"] = waitingObjs; + return obj; + } - template - const TX* - TXHolder::GetPendingLookupFrom(const TXOwner& owner) const + bool + HasLookupFor(const K& target) const { - auto itr = tx.find(owner); - if (itr == tx.end()) - { - return nullptr; - } + return timeouts.find(target) != timeouts.end(); + } - return itr->second.get(); + bool + HasPendingLookupFrom(const TXOwner& owner) const + { + return GetPendingLookupFrom(owner) != nullptr; } - template void - TXHolder::NewTX( + NewTX( const TXOwner& askpeer, const TXOwner& whoasked, const K& k, TX* t, - llarp_time_t requestTimeoutMS) - { - (void)whoasked; - tx.emplace(askpeer, std::unique_ptr>(t)); - auto count = waiting.count(k); - waiting.emplace(k, askpeer); + llarp_time_t requestTimeoutMS = 15s); - auto itr = timeouts.find(k); - if (itr == timeouts.end()) - { - timeouts.emplace(k, time_now_ms() + requestTimeoutMS); - } - if (count == 0) - { - t->Start(askpeer); - } - } + /// mark tx as not fond + void + NotFound(const TXOwner& from, const std::unique_ptr& next); - template void - TXHolder::NotFound(const TXOwner& from, const std::unique_ptr&) + Found(const TXOwner& from, const K& k, const std::vector& values) { - auto txitr = tx.find(from); - if (txitr == tx.end()) - { - return; - } - Inform(from, txitr->second->target, {}, true, true); + Inform(from, k, values, true); } - template + /// inform all watches for key of values found void - TXHolder::Inform( - TXOwner from, K key, std::vector values, bool sendreply, bool removeTimeouts) + Inform( + TXOwner from, + K key, + std::vector values, + bool sendreply = false, + bool removeTimeouts = true); + + void + Expire(llarp_time_t now); + }; + + template + const TX* + TXHolder::GetPendingLookupFrom(const TXOwner& owner) const + { + auto itr = tx.find(owner); + if (itr == tx.end()) { - auto range = waiting.equal_range(key); - auto itr = range.first; - while (itr != range.second) - { - auto txitr = tx.find(itr->second); - if (txitr != tx.end()) - { - for (const auto& value : values) - { - txitr->second->OnFound(from.node, value); - } - if (sendreply) - { - txitr->second->SendReply(); - tx.erase(txitr); - } - } - ++itr; - } + return nullptr; + } - if (sendreply) - { - waiting.erase(key); - } + return itr->second.get(); + } + + template + void + TXHolder::NewTX( + const TXOwner& askpeer, + const TXOwner& whoasked, + const K& k, + TX* t, + llarp_time_t requestTimeoutMS) + { + (void)whoasked; + tx.emplace(askpeer, std::unique_ptr>(t)); + auto count = waiting.count(k); + waiting.emplace(k, askpeer); - if (removeTimeouts) - { - timeouts.erase(key); - } + auto itr = timeouts.find(k); + if (itr == timeouts.end()) + { + timeouts.emplace(k, time_now_ms() + requestTimeoutMS); + } + if (count == 0) + { + t->Start(askpeer); } + } - template - void - TXHolder::Expire(llarp_time_t now) + template + void + TXHolder::NotFound(const TXOwner& from, const std::unique_ptr&) + { + auto txitr = tx.find(from); + if (txitr == tx.end()) { - auto itr = timeouts.begin(); - while (itr != timeouts.end()) + return; + } + Inform(from, txitr->second->target, {}, true, true); + } + + template + void + TXHolder::Inform( + TXOwner from, K key, std::vector values, bool sendreply, bool removeTimeouts) + { + auto range = waiting.equal_range(key); + auto itr = range.first; + while (itr != range.second) + { + auto txitr = tx.find(itr->second); + if (txitr != tx.end()) { - if (now >= itr->second) + for (const auto& value : values) { - Inform(TXOwner{}, itr->first, {}, true, false); - itr = timeouts.erase(itr); + txitr->second->OnFound(from.node, value); } - else + if (sendreply) { - ++itr; + txitr->second->SendReply(); + tx.erase(txitr); } } + ++itr; + } + + if (sendreply) + { + waiting.erase(key); + } + + if (removeTimeouts) + { + timeouts.erase(key); + } + } + + template + void + TXHolder::Expire(llarp_time_t now) + { + auto itr = timeouts.begin(); + while (itr != timeouts.end()) + { + if (now >= itr->second) + { + Inform(TXOwner{}, itr->first, {}, true, false); + itr = timeouts.erase(itr); + } + else + { + ++itr; + } } - } // namespace dht -} // namespace llarp + } +} // namespace llarp::dht #endif diff --git a/llarp/dht/txowner.hpp b/llarp/dht/txowner.hpp index e21c878a11..0fb7b25196 100644 --- a/llarp/dht/txowner.hpp +++ b/llarp/dht/txowner.hpp @@ -4,49 +4,46 @@ #include #include -namespace llarp +namespace llarp::dht { - namespace dht + struct TXOwner { - struct TXOwner - { - Key_t node; - uint64_t txid = 0; + Key_t node; + uint64_t txid = 0; - TXOwner() = default; - TXOwner(const TXOwner&) = default; - TXOwner(TXOwner&&) = default; + TXOwner() = default; + TXOwner(const TXOwner&) = default; + TXOwner(TXOwner&&) = default; - TXOwner& - operator=(const TXOwner&) = default; + TXOwner& + operator=(const TXOwner&) = default; - TXOwner(const Key_t& k, uint64_t id) : node(k), txid(id) - {} + TXOwner(const Key_t& k, uint64_t id) : node(k), txid(id) + {} - util::StatusObject - ExtractStatus() const - { - util::StatusObject obj{ - {"txid", txid}, - {"node", node.ToHex()}, - }; - return obj; - } + util::StatusObject + ExtractStatus() const + { + util::StatusObject obj{ + {"txid", txid}, + {"node", node.ToHex()}, + }; + return obj; + } - bool - operator==(const TXOwner& other) const - { - return std::tie(txid, node) == std::tie(other.txid, other.node); - } + bool + operator==(const TXOwner& other) const + { + return std::tie(txid, node) == std::tie(other.txid, other.node); + } - bool - operator<(const TXOwner& other) const - { - return std::tie(txid, node) < std::tie(other.txid, other.node); - } - }; - } // namespace dht -} // namespace llarp + bool + operator<(const TXOwner& other) const + { + return std::tie(txid, node) < std::tie(other.txid, other.node); + } + }; +} // namespace llarp::dht namespace std { diff --git a/llarp/endpoint_base.hpp b/llarp/endpoint_base.hpp index 3fd0450a8f..68144935e3 100644 --- a/llarp/endpoint_base.hpp +++ b/llarp/endpoint_base.hpp @@ -7,6 +7,8 @@ #include "llarp/ev/ev.hpp" #include "llarp/dns/srv_data.hpp" +#include + #include #include #include @@ -19,11 +21,6 @@ namespace llarp { - namespace quic - { - class TunnelManager; - } - namespace dns { class Server; @@ -111,7 +108,7 @@ namespace llarp virtual AddressVariant_t LocalAddress() const = 0; - virtual quic::TunnelManager* + virtual link::TunnelManager* GetQUICTunnel() = 0; virtual std::optional diff --git a/llarp/exit/endpoint.cpp b/llarp/exit/endpoint.cpp index 7a0c418d19..590d48a7be 100644 --- a/llarp/exit/endpoint.cpp +++ b/llarp/exit/endpoint.cpp @@ -3,7 +3,6 @@ #include #include #include -#include namespace llarp::exit { @@ -14,38 +13,38 @@ namespace llarp::exit huint128_t ip, llarp::handlers::ExitEndpoint* parent) : createdAt{parent->Now()} - , m_Parent{parent} - , m_remoteSignKey{remoteIdent} - , m_CurrentPath{beginPath} - , m_IP{ip} - , m_RewriteSource{rewriteIP} + , parent{parent} + , remote_signkey{remoteIdent} + , current_path{beginPath} + , IP{ip} + , rewrite_source{rewriteIP} { - m_LastActive = parent->Now(); + last_active = parent->Now(); } Endpoint::~Endpoint() { - if (m_CurrentPath) - m_Parent->DelEndpointInfo(m_CurrentPath->RXID()); + if (current_path) + parent->DelEndpointInfo(current_path->RXID()); } void Endpoint::Close() { - m_Parent->RemoveExit(this); + parent->RemoveExit(this); } util::StatusObject Endpoint::ExtractStatus() const { - auto now = m_Parent->Now(); + auto now = parent->Now(); util::StatusObject obj{ - {"identity", m_remoteSignKey.ToString()}, - {"ip", m_IP.ToString()}, - {"txRate", m_TxRate}, - {"rxRate", m_RxRate}, + {"identity", remote_signkey.ToString()}, + {"ip", IP.ToString()}, + {"txRate", tx_rate}, + {"rxRate", rx_rate}, {"createdAt", to_json(createdAt)}, - {"exiting", !m_RewriteSource}, + {"exiting", !rewrite_source}, {"looksDead", LooksDead(now)}, {"expiresSoon", ExpiresSoon(now)}, {"expired", IsExpired(now)}}; @@ -55,10 +54,10 @@ namespace llarp::exit bool Endpoint::UpdateLocalPath(const llarp::PathID_t& nextPath) { - if (!m_Parent->UpdateEndpointPath(m_remoteSignKey, nextPath)) + if (!parent->UpdateEndpointPath(remote_signkey, nextPath)) return false; - const RouterID us{m_Parent->GetRouter()->pubkey()}; - m_CurrentPath = m_Parent->GetRouter()->path_context().GetByUpstream(us, nextPath); + const RouterID us{parent->GetRouter()->pubkey()}; + current_path = parent->GetRouter()->path_context().GetByUpstream(us, nextPath); return true; } @@ -66,8 +65,8 @@ namespace llarp::exit Endpoint::Tick(llarp_time_t now) { (void)now; - m_RxRate = 0; - m_TxRate = 0; + rx_rate = 0; + tx_rate = 0; } bool @@ -85,8 +84,8 @@ namespace llarp::exit bool Endpoint::ExpiresSoon(llarp_time_t now, llarp_time_t dlt) const { - if (m_CurrentPath) - return m_CurrentPath->ExpiresSoon(now, dlt); + if (current_path) + return current_path->ExpiresSoon(now, dlt); return true; } @@ -100,138 +99,145 @@ namespace llarp::exit return true; auto lastPing = path->LastRemoteActivityAt(); if (lastPing == 0s || (now > lastPing && now - lastPing > timeout)) - return now > m_LastActive && now - m_LastActive > timeout; + return now > last_active && now - last_active > timeout; else if (lastPing > 0s) // NOLINT return now > lastPing && now - lastPing > timeout; return lastPing > 0s; } - bool - Endpoint::QueueOutboundTraffic( - PathID_t path, std::vector buf, uint64_t counter, service::ProtocolType t) - { - const service::ConvoTag tag{path.as_array()}; - if (t == service::ProtocolType::QUIC) + /* bool + Endpoint::QueueOutboundTraffic( + PathID_t path, std::vector buf, uint64_t counter, service::ProtocolType t) { - auto quic = m_Parent->GetQUICTunnel(); - if (not quic) - return false; - m_TxRate += buf.size(); - quic->receive_packet(tag, std::move(buf)); - m_LastActive = m_Parent->Now(); - return true; - } - // queue overflow - if (m_UpstreamQueue.size() > MaxUpstreamQueueSize) - return false; + const service::ConvoTag tag{path.as_array()}; - llarp::net::IPPacket pkt{std::move(buf)}; - if (pkt.empty()) - return false; + // current_path->send_path_control_message(std::string method, std::string body, + std::function func) - if (pkt.IsV6() && m_Parent->SupportsV6()) - { - huint128_t dst; - if (m_RewriteSource) - dst = m_Parent->GetIfAddr(); - else - dst = pkt.dstv6(); - pkt.UpdateIPv6Address(m_IP, dst); - } - else if (pkt.IsV4() && !m_Parent->SupportsV6()) - { - huint32_t dst; - if (m_RewriteSource) - dst = net::TruncateV6(m_Parent->GetIfAddr()); - else - dst = pkt.dstv4(); - pkt.UpdateIPv4Address(xhtonl(net::TruncateV6(m_IP)), xhtonl(dst)); - } - else - { - return false; - } - m_TxRate += pkt.size(); - m_UpstreamQueue.emplace(std::move(pkt), counter); - m_LastActive = m_Parent->Now(); - return true; - } + if (t == service::ProtocolType::QUIC) + { + auto quic = parent->GetQUICTunnel(); + if (not quic) + return false; + tx_rate += buf.size(); + quic->receive_packet(tag, std::move(buf)); + last_active = parent->Now(); + return true; + } + // queue overflow + if (m_UpstreamQueue.size() > MaxUpstreamQueueSize) + return false; - bool - Endpoint::QueueInboundTraffic(std::vector buf, service::ProtocolType type) - { - if (type != service::ProtocolType::QUIC) - { llarp::net::IPPacket pkt{std::move(buf)}; if (pkt.empty()) return false; - huint128_t src; - if (m_RewriteSource) - src = m_Parent->GetIfAddr(); - else - src = pkt.srcv6(); - if (pkt.IsV6()) - pkt.UpdateIPv6Address(src, m_IP); + if (pkt.IsV6() && parent->SupportsV6()) + { + huint128_t dst; + if (rewrite_source) + dst = parent->GetIfAddr(); + else + dst = pkt.dstv6(); + pkt.UpdateIPv6Address(IP, dst); + } + else if (pkt.IsV4() && !parent->SupportsV6()) + { + huint32_t dst; + if (rewrite_source) + dst = net::TruncateV6(parent->GetIfAddr()); + else + dst = pkt.dstv4(); + pkt.UpdateIPv4Address(xhtonl(net::TruncateV6(IP)), xhtonl(dst)); + } else - pkt.UpdateIPv4Address(xhtonl(net::TruncateV6(src)), xhtonl(net::TruncateV6(m_IP))); - - buf = pkt.steal(); - } + { + return false; + } + tx_rate += pkt.size(); + m_UpstreamQueue.emplace(std::move(pkt), counter); + last_active = parent->Now(); + return true; + } */ - const uint8_t queue_idx = buf.size() / llarp::routing::EXIT_PAD_SIZE; - if (m_DownstreamQueues.find(queue_idx) == m_DownstreamQueues.end()) - m_DownstreamQueues.emplace(queue_idx, InboundTrafficQueue_t{}); - auto& queue = m_DownstreamQueues.at(queue_idx); - if (queue.size() == 0) - { - queue.emplace_back(); - queue.back().protocol = type; - return queue.back().PutBuffer(std::move(buf), m_Counter++); - } - auto& msg = queue.back(); - if (msg.Size() + buf.size() > llarp::routing::EXIT_PAD_SIZE) - { - queue.emplace_back(); - queue.back().protocol = type; - return queue.back().PutBuffer(std::move(buf), m_Counter++); - } - msg.protocol = type; - return msg.PutBuffer(std::move(buf), m_Counter++); + bool + Endpoint::QueueInboundTraffic(std::vector, service::ProtocolType) + { + // TODO: this will go away with removing flush + + // if (type != service::ProtocolType::QUIC) + // { + // llarp::net::IPPacket pkt{std::move(buf)}; + // if (pkt.empty()) + // return false; + + // huint128_t src; + // if (m_RewriteSource) + // src = m_Parent->GetIfAddr(); + // else + // src = pkt.srcv6(); + // if (pkt.IsV6()) + // pkt.UpdateIPv6Address(src, m_IP); + // else + // pkt.UpdateIPv4Address(xhtonl(net::TruncateV6(src)), xhtonl(net::TruncateV6(m_IP))); + + // buf = pkt.steal(); + // } + + // const uint8_t queue_idx = buf.size() / llarp::routing::EXIT_PAD_SIZE; + // if (m_DownstreamQueues.find(queue_idx) == m_DownstreamQueues.end()) + // m_DownstreamQueues.emplace(queue_idx, InboundTrafficQueue_t{}); + // auto& queue = m_DownstreamQueues.at(queue_idx); + // if (queue.size() == 0) + // { + // queue.emplace_back(); + // queue.back().protocol = type; + // return queue.back().PutBuffer(std::move(buf), m_Counter++); + // } + // auto& msg = queue.back(); + // if (msg.Size() + buf.size() > llarp::routing::EXIT_PAD_SIZE) + // { + // queue.emplace_back(); + // queue.back().protocol = type; + // return queue.back().PutBuffer(std::move(buf), m_Counter++); + // } + // msg.protocol = type; + // return msg.PutBuffer(std::move(buf), m_Counter++); + return true; } bool Endpoint::Flush() { // flush upstream queue - while (m_UpstreamQueue.size()) - { - m_Parent->QueueOutboundTraffic(const_cast(m_UpstreamQueue.top().pkt).steal()); - m_UpstreamQueue.pop(); - } + // while (m_UpstreamQueue.size()) + // { + // parent->QueueOutboundTraffic(const_cast(m_UpstreamQueue.top().pkt).steal()); + // m_UpstreamQueue.pop(); + // } // flush downstream queue auto path = GetCurrentPath(); bool sent = path != nullptr; - if (path) - { - for (auto& item : m_DownstreamQueues) - { - auto& queue = item.second; - while (queue.size()) - { - auto& msg = queue.front(); - msg.sequence_number = path->NextSeqNo(); - if (path->SendRoutingMessage(msg, m_Parent->GetRouter())) - { - m_RxRate += msg.Size(); - sent = true; - } - queue.pop_front(); - } - } - } - for (auto& item : m_DownstreamQueues) - item.second.clear(); + // if (path) + // { + // for (auto& item : m_DownstreamQueues) + // { + // auto& queue = item.second; + // while (queue.size()) + // { + // auto& msg = queue.front(); + // msg.sequence_number = path->NextSeqNo(); + // if (path->SendRoutingMessage(msg, m_Parent->GetRouter())) + // { + // m_RxRate += msg.Size(); + // sent = true; + // } + // queue.pop_front(); + // } + // } + // } + // for (auto& item : m_DownstreamQueues) + // item.second.clear(); return sent; } } // namespace llarp::exit diff --git a/llarp/exit/endpoint.hpp b/llarp/exit/endpoint.hpp index 45e11f160a..7405ce1f9b 100644 --- a/llarp/exit/endpoint.hpp +++ b/llarp/exit/endpoint.hpp @@ -65,9 +65,9 @@ namespace llarp /// queue outbound traffic /// does ip rewrite here - bool - QueueOutboundTraffic( - PathID_t txid, std::vector data, uint64_t counter, service::ProtocolType t); + // bool + // QueueOutboundTraffic( + // PathID_t txid, std::vector data, uint64_t counter, service::ProtocolType t); /// update local path id and cascade information to parent /// return true if success @@ -77,66 +77,43 @@ namespace llarp llarp::path::HopHandler_ptr GetCurrentPath() const { - return m_CurrentPath; + return current_path; } const llarp::PubKey& PubKey() const { - return m_remoteSignKey; + return remote_signkey; } uint64_t TxRate() const { - return m_TxRate; + return tx_rate; } uint64_t RxRate() const { - return m_RxRate; + return rx_rate; } huint128_t LocalIP() const { - return m_IP; + return IP; } const llarp_time_t createdAt; private: - llarp::handlers::ExitEndpoint* m_Parent; - llarp::PubKey m_remoteSignKey; - llarp::path::HopHandler_ptr m_CurrentPath; - llarp::huint128_t m_IP; - uint64_t m_TxRate, m_RxRate; - llarp_time_t m_LastActive; - bool m_RewriteSource; - using InboundTrafficQueue_t = std::deque; - using TieredQueue = std::map; - // maps number of fragments the message will fit in to the queue for it - TieredQueue m_DownstreamQueues; - - struct UpstreamBuffer - { - UpstreamBuffer(llarp::net::IPPacket p, uint64_t c) : pkt{std::move(p)}, counter(c) - {} - - llarp::net::IPPacket pkt; - uint64_t counter; - - bool - operator<(const UpstreamBuffer& other) const - { - return counter < other.counter; - } - }; - - using UpstreamQueue_t = std::priority_queue; - UpstreamQueue_t m_UpstreamQueue; - uint64_t m_Counter; + llarp::handlers::ExitEndpoint* parent; + llarp::PubKey remote_signkey; + llarp::path::HopHandler_ptr current_path; + llarp::huint128_t IP; + uint64_t tx_rate, rx_rate; + llarp_time_t last_active; + bool rewrite_source; }; } // namespace exit } // namespace llarp diff --git a/llarp/exit/exit_messages.cpp b/llarp/exit/exit_messages.cpp deleted file mode 100644 index d1536418df..0000000000 --- a/llarp/exit/exit_messages.cpp +++ /dev/null @@ -1,364 +0,0 @@ -#include "exit_messages.hpp" - -#include -#include - -namespace llarp::routing -{ - bool - ObtainExitMessage::Sign(const llarp::SecretKey& sk) - { - pubkey = seckey_topublic(sk); - sig.Zero(); - - auto bte = bt_encode(); - return CryptoManager::instance()->sign( - sig, sk, reinterpret_cast(bte.data()), bte.size()); - } - - bool - ObtainExitMessage::Verify() const - { - ObtainExitMessage copy; - copy = *this; - copy.sig.Zero(); - - auto bte = copy.bt_encode(); - return CryptoManager::instance()->verify( - pubkey, reinterpret_cast(bte.data()), bte.size(), sig); - } - - std::string - ObtainExitMessage::bt_encode() const - { - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("E", flag); - btdp.append("I", pubkey.ToView()); - btdp.append("S", sequence_number); - btdp.append("T", tx_id); - btdp.append("Z", sig.ToView()); - } - catch (...) - { - log::critical(route_cat, "Error: ObtainExitMessage failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - - bool - ObtainExitMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) - { - bool read = false; - if (!BEncodeMaybeReadDictInt("E", flag, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("I", pubkey, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf)) - return false; - return read; - } - - bool - ObtainExitMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const - { - return h->HandleObtainExitMessage(*this, r); - } - - std::string - GrantExitMessage::bt_encode() const - { - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("S", sequence_number); - btdp.append("T", tx_id); - btdp.append("Y", nonce.ToView()); - btdp.append("Z", sig.ToView()); - } - catch (...) - { - log::critical(route_cat, "Error: GrantExitMessage failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - - bool - GrantExitMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) - { - bool read = false; - if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("Y", nonce, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf)) - return false; - return read; - } - - bool - GrantExitMessage::Verify(const llarp::PubKey& pk) const - { - GrantExitMessage copy; - copy = *this; - copy.sig.Zero(); - - auto bte = copy.bt_encode(); - return CryptoManager::instance()->verify( - pk, reinterpret_cast(bte.data()), bte.size(), sig); - } - - bool - GrantExitMessage::Sign(const llarp::SecretKey& sk) - { - sig.Zero(); - nonce.Randomize(); - - auto bte = bt_encode(); - return CryptoManager::instance()->sign( - sig, sk, reinterpret_cast(bte.data()), bte.size()); - } - - bool - GrantExitMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const - { - return h->HandleGrantExitMessage(*this, r); - } - - std::string - RejectExitMessage::bt_encode() const - { - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("B", backoff_time); - btdp.append("S", sequence_number); - btdp.append("T", tx_id); - btdp.append("Y", nonce.ToView()); - btdp.append("Z", sig.ToView()); - } - catch (...) - { - log::critical(route_cat, "Error: RejectExitMessage failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - - bool - RejectExitMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) - { - bool read = false; - if (!BEncodeMaybeReadDictInt("B", backoff_time, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("Y", nonce, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf)) - return false; - return read; - } - - bool - RejectExitMessage::Sign(const llarp::SecretKey& sk) - { - sig.Zero(); - nonce.Randomize(); - - auto bte = bt_encode(); - return CryptoManager::instance()->sign( - sig, sk, reinterpret_cast(bte.data()), bte.size()); - } - - bool - RejectExitMessage::Verify(const llarp::PubKey& pk) const - { - RejectExitMessage copy; - copy = *this; - copy.sig.Zero(); - - auto bte = copy.bt_encode(); - return CryptoManager::instance()->verify( - pk, reinterpret_cast(bte.data()), bte.size(), sig); - } - - bool - RejectExitMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const - { - return h->HandleRejectExitMessage(*this, r); - } - - std::string - UpdateExitMessage::bt_encode() const - { - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("P", path_id.ToView()); - btdp.append("S", sequence_number); - btdp.append("T", tx_id); - btdp.append("Z", sig.ToView()); - } - catch (...) - { - log::critical(route_cat, "Error: UpdateExitMessage failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - - bool - UpdateExitMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) - { - bool read = false; - if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("P", path_id, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf)) - return false; - return read; - } - - bool - UpdateExitMessage::Verify(const llarp::PubKey& pk) const - { - UpdateExitMessage copy; - copy = *this; - copy.sig.Zero(); - - auto bte = copy.bt_encode(); - return CryptoManager::instance()->verify( - pk, reinterpret_cast(bte.data()), bte.size(), sig); - } - - bool - UpdateExitMessage::Sign(const llarp::SecretKey& sk) - { - nonce.Randomize(); - - auto bte = bt_encode(); - return CryptoManager::instance()->sign( - sig, sk, reinterpret_cast(bte.data()), bte.size()); - } - - bool - UpdateExitMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const - { - return h->HandleUpdateExitMessage(*this, r); - } - - std::string - UpdateExitVerifyMessage::bt_encode() const - { - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("S", sequence_number); - btdp.append("T", tx_id); - } - catch (...) - { - log::critical(route_cat, "Error: UpdateExitVerifyMessage failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - - bool - UpdateExitVerifyMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) - { - bool read = false; - if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("T", tx_id, read, k, buf)) - return false; - return read; - } - - bool - UpdateExitVerifyMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const - { - return h->HandleUpdateExitVerifyMessage(*this, r); - } - - std::string - CloseExitMessage::bt_encode() const - { - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("S", sequence_number); - btdp.append("Y", nonce.ToView()); - btdp.append("Z", sig.ToView()); - } - catch (...) - { - log::critical(route_cat, "Error: CloseExitMessage failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - - bool - CloseExitMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) - { - bool read = false; - if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("Y", nonce, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictEntry("Z", sig, read, k, buf)) - return false; - return read; - } - - bool - CloseExitMessage::Verify(const llarp::PubKey& pk) const - { - CloseExitMessage copy; - copy = *this; - copy.sig.Zero(); - - auto bte = copy.bt_encode(); - return CryptoManager::instance()->verify( - pk, reinterpret_cast(bte.data()), bte.size(), sig); - } - - bool - CloseExitMessage::Sign(const llarp::SecretKey& sk) - { - sig.Zero(); - nonce.Randomize(); - - auto bte = bt_encode(); - return CryptoManager::instance()->sign( - sig, sk, reinterpret_cast(bte.data()), bte.size()); - } - - bool - CloseExitMessage::handle_message(AbstractRoutingMessageHandler* h, Router* r) const - { - return h->HandleCloseExitMessage(*this, r); - } -} // namespace llarp::routing diff --git a/llarp/exit/exit_messages.hpp b/llarp/exit/exit_messages.hpp deleted file mode 100644 index 5a50702329..0000000000 --- a/llarp/exit/exit_messages.hpp +++ /dev/null @@ -1,195 +0,0 @@ -#pragma once - -#include -#include "policy.hpp" - -#include - -namespace llarp::routing -{ - struct ObtainExitMessage final : public AbstractRoutingMessage - { - uint64_t flag{0}; // 0 for snode, 1 for internet access - llarp::PubKey pubkey; - uint64_t tx_id{0}; - llarp::Signature sig; - - ObtainExitMessage() : AbstractRoutingMessage() - {} - - ~ObtainExitMessage() override = default; - - void - clear() override - { - flag = 0; - pubkey.Zero(); - tx_id = 0; - sig.Zero(); - } - - /// populates I and signs - bool - Sign(const llarp::SecretKey& sk); - - bool - Verify() const; - - std::string - bt_encode() const override; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; - - bool - handle_message(AbstractRoutingMessageHandler* h, Router* r) const override; - }; - - struct GrantExitMessage final : public AbstractRoutingMessage - { - uint64_t tx_id; - llarp::AlignedBuffer<16> nonce; - llarp::Signature sig; - - std::string - bt_encode() const override; - - bool - Sign(const llarp::SecretKey& sk); - - bool - Verify(const llarp::PubKey& pk) const; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; - - bool - handle_message(AbstractRoutingMessageHandler* h, Router* r) const override; - - void - clear() override - { - tx_id = 0; - nonce.Zero(); - sig.Zero(); - } - }; - - struct RejectExitMessage final : public AbstractRoutingMessage - { - uint64_t backoff_time; - uint64_t tx_id; - llarp::AlignedBuffer<16> nonce; - llarp::Signature sig; - - void - clear() override - { - backoff_time = 0; - tx_id = 0; - nonce.Zero(); - sig.Zero(); - } - - bool - Sign(const llarp::SecretKey& sk); - - bool - Verify(const llarp::PubKey& pk) const; - - std::string - bt_encode() const override; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; - - bool - handle_message(AbstractRoutingMessageHandler* h, Router* r) const override; - }; - - struct UpdateExitVerifyMessage final : public AbstractRoutingMessage - { - uint64_t tx_id; - llarp::AlignedBuffer<16> nonce; - llarp::Signature sig; - - ~UpdateExitVerifyMessage() override = default; - - void - clear() override - { - tx_id = 0; - nonce.Zero(); - sig.Zero(); - } - - std::string - bt_encode() const override; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; - - bool - handle_message(AbstractRoutingMessageHandler* h, Router* r) const override; - }; - - struct UpdateExitMessage final : public AbstractRoutingMessage - { - llarp::PathID_t path_id; - uint64_t tx_id; - llarp::AlignedBuffer<16> nonce; - llarp::Signature sig; - - bool - Sign(const llarp::SecretKey& sk); - - bool - Verify(const llarp::PubKey& pk) const; - - std::string - bt_encode() const override; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; - - bool - handle_message(AbstractRoutingMessageHandler* h, Router* r) const override; - - void - clear() override - { - path_id.Zero(); - tx_id = 0; - nonce.Zero(); - sig.Zero(); - } - }; - - struct CloseExitMessage final : public AbstractRoutingMessage - { - llarp::AlignedBuffer<16> nonce; - llarp::Signature sig; - - std::string - bt_encode() const override; - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override; - - bool - handle_message(AbstractRoutingMessageHandler* h, Router* r) const override; - - bool - Sign(const llarp::SecretKey& sk); - - bool - Verify(const llarp::PubKey& pk) const; - - void - clear() override - { - nonce.Zero(); - sig.Zero(); - } - }; -} // namespace llarp::routing diff --git a/llarp/exit/session.cpp b/llarp/exit/session.cpp index 70bed01cfb..a168354a3d 100644 --- a/llarp/exit/session.cpp +++ b/llarp/exit/session.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -99,6 +98,7 @@ namespace llarp::exit // p->SetExitTrafficHandler(util::memFn(&BaseSession::HandleTraffic, this)); // p->AddObtainExitHandler(util::memFn(&BaseSession::HandleGotExit, this)); + // TODO: add callback here if (p->obtain_exit( exit_key, std::is_same_v ? 1 : 0, p->TXID().bt_encode())) log::info(link_cat, "Asking {} for exit", exit_router); @@ -171,9 +171,12 @@ namespace llarp::exit if (p->SupportsAnyRoles(path::ePathRoleExit)) { LogInfo(p->name(), " closing exit path"); - routing::CloseExitMessage msg; - if (!(msg.Sign(exit_key) && p->SendExitClose(msg, router))) - LogWarn(p->name(), " failed to send exit close message"); + // TODO: add callback here + + if (p->close_exit(exit_key, p->TXID().bt_encode())) + log::info(link_cat, ""); + else + log::warning(link_cat, "{} failed to send exit close message", p->name()); } }; ForEachPath(sendExitClose); @@ -183,31 +186,28 @@ namespace llarp::exit bool BaseSession::HandleTraffic( - llarp::path::Path_ptr path, - const llarp_buffer_t& buf, - uint64_t counter, - service::ProtocolType t) + llarp::path::Path_ptr, const llarp_buffer_t&, uint64_t, service::ProtocolType) { - const service::ConvoTag tag{path->RXID().as_array()}; - - if (t == service::ProtocolType::QUIC) - { - auto quic = m_Parent->GetQUICTunnel(); - if (not quic) - return false; - quic->receive_packet(tag, buf); - return true; - } - - if (packet_write_func) - { - llarp::net::IPPacket pkt{buf.view_all()}; - if (pkt.empty()) - return false; - _last_use = router->now(); - m_Downstream.emplace(counter, pkt); - return true; - } + // const service::ConvoTag tag{path->RXID().as_array()}; + + // if (t == service::ProtocolType::QUIC) + // { + // auto quic = m_Parent->GetQUICTunnel(); + // if (not quic) + // return false; + // quic->receive_packet(tag, buf); + // return true; + // } + + // if (packet_write_func) + // { + // llarp::net::IPPacket pkt{buf.view_all()}; + // if (pkt.empty()) + // return false; + // _last_use = router->now(); + // m_Downstream.emplace(counter, pkt); + // return true; + // } return false; } @@ -220,29 +220,31 @@ namespace llarp::exit } bool - BaseSession::QueueUpstreamTraffic( - llarp::net::IPPacket pkt, const size_t N, service::ProtocolType t) + BaseSession::QueueUpstreamTraffic(llarp::net::IPPacket, const size_t, service::ProtocolType) { - auto& queue = m_Upstream[pkt.size() / N]; + // auto& queue = m_Upstream[pkt.size() / N]; // queue overflow - if (queue.size() >= MaxUpstreamQueueLength) - return false; - if (queue.size() == 0) - { - queue.emplace_back(); - queue.back().protocol = t; - return queue.back().PutBuffer(llarp_buffer_t{pkt}, _counter++); - } - auto& back = queue.back(); - // pack to nearest N - if (back.Size() + pkt.size() > N) - { - queue.emplace_back(); - queue.back().protocol = t; - return queue.back().PutBuffer(llarp_buffer_t{pkt}, _counter++); - } - back.protocol = t; - return back.PutBuffer(llarp_buffer_t{pkt}, _counter++); + // if (queue.size() >= MaxUpstreamQueueLength) + // return false; + // if (queue.size() == 0) + // { + // queue.emplace_back(); + // queue.back().protocol = t; + // return queue.back().PutBuffer(llarp_buffer_t{pkt}, _counter++); + // } + + // auto& back = queue.back(); + // // pack to nearest N + // if (back.Size() + pkt.size() > N) + // { + // queue.emplace_back(); + // queue.back().protocol = t; + // return queue.back().PutBuffer(llarp_buffer_t{pkt}, _counter++); + // } + // back.protocol = t; + // return back.PutBuffer(llarp_buffer_t{pkt}, _counter++); + + return true; } bool @@ -277,25 +279,25 @@ namespace llarp::exit auto path = PickEstablishedPath(llarp::path::ePathRoleExit); if (path) { - for (auto& [i, queue] : m_Upstream) - { - while (queue.size()) - { - auto& msg = queue.front(); - msg.sequence_number = path->NextSeqNo(); - path->SendRoutingMessage(msg, router); - queue.pop_front(); - } - } + // for (auto& [i, queue] : m_Upstream) + // { + // while (queue.size()) + // { + // auto& msg = queue.front(); + // msg.sequence_number = path->NextSeqNo(); + // path->SendRoutingMessage(msg, router); + // queue.pop_front(); + // } + // } } else { - if (m_Upstream.size()) - llarp::LogWarn("no path for exit session"); - // discard upstream - for (auto& [i, queue] : m_Upstream) - queue.clear(); - m_Upstream.clear(); + // if (m_Upstream.size()) + // llarp::LogWarn("no path for exit session"); + // // discard upstream + // for (auto& [i, queue] : m_Upstream) + // queue.clear(); + // m_Upstream.clear(); if (numHops == 1) { @@ -338,12 +340,12 @@ namespace llarp::exit void BaseSession::FlushDownstream() { - while (m_Downstream.size()) - { - if (packet_write_func) - packet_write_func(const_cast(m_Downstream.top().second).steal()); - m_Downstream.pop(); - } + // while (m_Downstream.size()) + // { + // if (packet_write_func) + // packet_write_func(const_cast(m_Downstream.top().second).steal()); + // m_Downstream.pop(); + // } } SNodeSession::SNodeSession( @@ -377,23 +379,26 @@ namespace llarp::exit void ExitSession::send_packet_to_remote(std::string buf) { - net::IPPacket pkt{buf}; - if (pkt.empty()) + if (buf.empty()) return; - pkt.ZeroAddresses(); - // QueueUpstreamTraffic(std::move(pkt), llarp::routing::EXIT_PAD_SIZE, t); + if (auto path = PickEstablishedPath(llarp::path::ePathRoleExit)) + {} + else + {} } void SNodeSession::send_packet_to_remote(std::string buf) { - net::IPPacket pkt{buf}; - if (pkt.empty()) + if (buf.empty()) return; - pkt.ZeroSourceAddress(); - - // QueueUpstreamTraffic(std::move(pkt), llarp::routing::EXIT_PAD_SIZE, t); + if (auto path = PickEstablishedPath(llarp::path::ePathRoleExit)) + { + // + } + else + {} } } // namespace llarp::exit diff --git a/llarp/exit/session.hpp b/llarp/exit/session.hpp index 1c9810b0ce..db4484cabf 100644 --- a/llarp/exit/session.hpp +++ b/llarp/exit/session.hpp @@ -12,7 +12,7 @@ namespace llarp { class EndpointBase; - namespace quic + namespace link { class TunnelManager; } @@ -163,12 +163,12 @@ namespace llarp } }; - uint64_t _counter; + [[maybe_unused]] uint64_t _counter; llarp_time_t _last_use; std::vector m_PendingCallbacks; - const bool m_BundleRC; - EndpointBase* const m_Parent; + [[maybe_unused]] const bool m_BundleRC; + [[maybe_unused]] EndpointBase* const m_Parent; void CallPendingCallbacks(bool success); diff --git a/llarp/handlers/exit.cpp b/llarp/handlers/exit.cpp index 6ab5f8fee0..1432f5b26e 100644 --- a/llarp/handlers/exit.cpp +++ b/llarp/handlers/exit.cpp @@ -7,7 +7,6 @@ #include #include -#include #include #include @@ -18,10 +17,9 @@ namespace llarp::handlers ExitEndpoint::ExitEndpoint(std::string name, Router* r) : router(r) , name(std::move(name)) - , tunnel_manager{std::make_shared(*this)} + , tunnel_manager{std::make_shared(*this)} { should_init_tun = true; - tunnel_manager = std::make_shared(*this); } ExitEndpoint::~ExitEndpoint() = default; @@ -749,12 +747,12 @@ namespace llarp::handlers if_name = *maybe; } LogInfo(Name(), " set ifname to ", if_name); - if (auto* quic = GetQUICTunnel()) - { - quic->listen([ifaddr = net::TruncateV6(if_addr)](std::string_view, uint16_t port) { - return llarp::SockAddr{ifaddr, huint16_t{port}}; - }); - } + // if (auto* quic = GetQUICTunnel()) + // { + // quic->listen([ifaddr = net::TruncateV6(if_addr)](std::string_view, uint16_t port) { + // return llarp::SockAddr{ifaddr, huint16_t{port}}; + // }); + // } } huint128_t @@ -783,7 +781,7 @@ namespace llarp::handlers return ip; } - quic::TunnelManager* + link::TunnelManager* ExitEndpoint::GetQUICTunnel() { return tunnel_manager.get(); diff --git a/llarp/handlers/exit.hpp b/llarp/handlers/exit.hpp index 42438edd3a..84365a2bcc 100644 --- a/llarp/handlers/exit.hpp +++ b/llarp/handlers/exit.hpp @@ -162,7 +162,7 @@ namespace llarp void Flush(); - quic::TunnelManager* + link::TunnelManager* GetQUICTunnel() override; huint128_t @@ -226,7 +226,7 @@ namespace llarp SockAddr resolver_addr; std::vector upstream_resolvers; - std::shared_ptr tunnel_manager; + std::shared_ptr tunnel_manager; using PacketQueue_t = std:: priority_queue, net::IPPacket::CompareOrder>; diff --git a/llarp/handlers/null.hpp b/llarp/handlers/null.hpp index 7b16c5c93f..ecf1f61fec 100644 --- a/llarp/handlers/null.hpp +++ b/llarp/handlers/null.hpp @@ -50,11 +50,9 @@ namespace llarp::handlers m_PacketRouter->HandleIPPacketFrom(std::move(*from), std::move(pkt)); return true; } - else - { - LogWarn("did not handle packet, no endpoint with convotag T=", tag); - return false; - } + + LogWarn("did not handle packet, no endpoint with convotag T=", tag); + return false; } if (t != service::ProtocolType::QUIC) return false; @@ -70,7 +68,8 @@ namespace llarp::handlers LogWarn("invalid incoming quic packet, dropping"); return false; } - quic->receive_packet(tag, buf); + // TODO: + // quic->receive_packet(tag, buf); return true; } diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index c313a235e1..cd9ee3876d 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -391,8 +390,11 @@ namespace llarp::handlers if (not data.empty()) { std::string_view bdata{data.data(), data.size()}; + LogDebug(Name(), " parsing address map data: ", bdata); + const auto parsed = oxenc::bt_deserialize(bdata); + for (const auto& [key, value] : parsed) { huint128_t ip{}; @@ -454,12 +456,13 @@ namespace llarp::handlers } } - if (auto* quic = GetQUICTunnel()) - { - quic->listen([this](std::string_view, uint16_t port) { - return llarp::SockAddr{net::TruncateV6(GetIfAddr()), huint16_t{port}}; - }); - } + // if (auto* quic = GetQUICTunnel()) + // { + // TODO: + // quic->listen([this](std::string_view, uint16_t port) { + // return llarp::SockAddr{net::TruncateV6(GetIfAddr()), huint16_t{port}}; + // }); + // } return Endpoint::Configure(conf, dnsConf); } @@ -469,19 +472,6 @@ namespace llarp::handlers return m_IPToAddr.find(ip) != m_IPToAddr.end(); } - void - TunEndpoint::Pump(llarp_time_t now) - { - // flush network to user - while (not m_NetworkToUserPktQueue.empty()) - { - m_NetIf->WritePacket(m_NetworkToUserPktQueue.top().pkt); - m_NetworkToUserPktQueue.pop(); - } - - service::Endpoint::Pump(now); - } - static bool is_random_snode(const dns::Message& msg) { @@ -1367,7 +1357,9 @@ namespace llarp::handlers return false; } LogInfo("tag active T=", tag); - quic->receive_packet(tag, buf); + + // TODO: + // quic->receive_packet(tag, buf); return true; } @@ -1473,7 +1465,10 @@ namespace llarp::handlers { pkt.UpdateIPv6Address(src, dst); } - m_NetworkToUserPktQueue.push(std::move(write)); + + // TODO: send this along but without a fucking huint182_t + // m_NetworkToUserPktQueue.push(std::move(write)); + // wake up so we ensure that all packets are written to user router()->TriggerPump(); return true; diff --git a/llarp/link/connection.cpp b/llarp/link/connection.cpp index 2af983693f..01aaa4fc89 100644 --- a/llarp/link/connection.cpp +++ b/llarp/link/connection.cpp @@ -5,7 +5,7 @@ namespace llarp::link Connection::Connection( std::shared_ptr& c, std::shared_ptr& s, - RouterContact& rc) + const RouterContact& rc) : conn{c}, control_stream{s}, remote_rc{std::move(rc)} {} diff --git a/llarp/link/connection.hpp b/llarp/link/connection.hpp index a314b01db6..7fae51b4e8 100644 --- a/llarp/link/connection.hpp +++ b/llarp/link/connection.hpp @@ -20,7 +20,7 @@ namespace llarp::link Connection( std::shared_ptr& c, std::shared_ptr& s, - RouterContact& rc); + const RouterContact& rc); }; } // namespace llarp::link diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 11dab5c266..69729db2e1 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -675,7 +675,8 @@ namespace llarp { m.respond( serialize_response( - {{"STATUS", FindRouterMessage::RETRY_ITER}, {"TARGET", target_addr.data()}}), + {{"STATUS", FindRouterMessage::RETRY_ITER}, + {"TARGET", reinterpret_cast(target_addr.data())}}), true); } } @@ -1656,4 +1657,22 @@ namespace llarp } } + void + LinkManager::handle_convo_intro(oxen::quic::message m) + { + if (m.timed_out) + { + log::info(link_cat, "Path control message timed out!"); + return; + } + + try + {} + catch (const std::exception& e) + { + log::warning(link_cat, "Exception: {}", e.what()); + return; + } + } + } // namespace llarp diff --git a/llarp/link/tunnel.hpp b/llarp/link/tunnel.hpp index bbe67ab608..825e77b021 100644 --- a/llarp/link/tunnel.hpp +++ b/llarp/link/tunnel.hpp @@ -1,18 +1,29 @@ #pragma once -#include +#include +#include +#include #include #include +#include +#include #include #include #include +namespace llarp +{ + class EndpointBase; +} + namespace llarp::link { struct Endpoint; + using namespace std::chrono_literals; + namespace tunnel { // The server sends back a 0x00 to signal that the remote TCP connection was established and @@ -176,7 +187,7 @@ namespace llarp::link // Server instance; this listens on pseudo-port 0 (if it listens). This is automatically // instantiated the first time `listen()` is called; if not instantiated we simply drop any // inbound client-to-server quic packets. - std::unique_ptr server_; + // std::unique_ptr server_; void make_server(); diff --git a/llarp/lokinet_shared.cpp b/llarp/lokinet_shared.cpp index 33488edb29..5dbd83766a 100644 --- a/llarp/lokinet_shared.cpp +++ b/llarp/lokinet_shared.cpp @@ -1,11 +1,11 @@ #include #include #include -#include +#include #include #include -#include +#include #include #include @@ -305,7 +305,7 @@ struct lokinet_context [[nodiscard]] auto endpoint(std::string name = "default") const { - return impl->router->hiddenServiceContext().GetEndpointByName(name); + return impl->router->hidden_service_context().GetEndpointByName(name); } std::unordered_map streams; @@ -490,7 +490,7 @@ extern "C" return -3; auto lock = ctx->acquire(); // add a temp cryptography implementation here so rc.Verify works - llarp::CryptoManager instance{new llarp::sodium::CryptoLibSodium{}}; + llarp::CryptoManager instance{new llarp::Crypto{}}; if (data[0] == 'l') { if (not ctx->config->bootstrap.routers.BDecode(&buf)) @@ -577,7 +577,7 @@ extern "C" return -3; if (not ctx->impl->LooksAlive()) return -2; - return ctx->endpoint()->IsReady() ? 0 : -1; + return ctx->endpoint()->is_ready() ? 0 : -1; } int EXPORT @@ -593,12 +593,12 @@ extern "C" ms = 10; iterations = 1; } - while (not ep->IsReady() and iterations > 0) + while (not ep->is_ready() and iterations > 0) { std::this_thread::sleep_for(std::chrono::milliseconds{ms / 10}); iterations--; } - return ep->IsReady() ? 0 : -1; + return ep->is_ready() ? 0 : -1; } void EXPORT @@ -945,7 +945,7 @@ extern "C" else return EHOSTUNREACH; } - if (auto maybe = llarp::service::ParseAddress(std::string{remote->remote_host})) + if (auto maybe = llarp::service::parse_address(std::string{remote->remote_host})) { llarp::net::IPPacket pkt = llarp::net::IPPacket::UDP( llarp::nuint32_t{0}, @@ -957,10 +957,10 @@ extern "C" if (pkt.empty()) return EINVAL; std::promise ret; - ctx->impl->router->loop()->call([addr = *maybe, pkt = std::move(pkt), ep, &ret]() { + ctx->impl->router->loop()->call([addr = *maybe, pkt = pkt.to_string(), ep, &ret]() { if (auto tag = ep->GetBestConvoTagFor(addr)) { - if (ep->SendToOrQueue(*tag, pkt.ConstBuffer(), llarp::service::ProtocolType::TrafficV4)) + if (ep->send_to(*tag, pkt)) { ret.set_value(0); return; @@ -997,7 +997,7 @@ extern "C" else return EHOSTUNREACH; } - if (auto maybe = llarp::service::ParseAddress(std::string{remote->remote_host})) + if (auto maybe = llarp::service::parse_address(std::string{remote->remote_host})) { { // check for pre existing flow @@ -1012,14 +1012,19 @@ extern "C" } } } + std::promise gotten; - ctx->impl->router->loop()->call([addr = *maybe, ep, &gotten]() { - ep->MarkAddressOutbound(addr); - auto res = ep->EnsurePathTo( - addr, [&gotten](auto result) { gotten.set_value(result.has_value()); }, 5s); - if (not res) + + ctx->impl->router->loop()->call([maybe_addr = *maybe, ep, &gotten]() { + if (auto* addr = std::get_if(&maybe_addr)) { - gotten.set_value(false); + ep->MarkAddressOutbound(*addr); + auto res = ep->EnsurePathTo( + *addr, [&gotten](auto result) { gotten.set_value(result.has_value()); }, 5s); + if (not res) + { + gotten.set_value(false); + } } }); if (gotten.get_future().get()) diff --git a/llarp/messages/dht.hpp b/llarp/messages/dht.hpp index fc7f72055a..8b5b9341a8 100644 --- a/llarp/messages/dht.hpp +++ b/llarp/messages/dht.hpp @@ -18,8 +18,8 @@ namespace llarp try { - btdp.append("E", is_exploratory); - btdp.append("I", is_iterative); + btdp.append("E", is_exploratory ? 1 : 0); + btdp.append("I", is_iterative ? 1 : 0); btdp.append("K", rid.ToView()); } catch (...) @@ -37,8 +37,8 @@ namespace llarp try { - btdp.append("E", is_exploratory); - btdp.append("I", is_iterative); + btdp.append("E", is_exploratory ? 1 : 0); + btdp.append("I", is_iterative ? 1 : 0); btdp.append("K", std::move(rid)); } catch (...) diff --git a/llarp/messages/discard.hpp b/llarp/messages/discard.hpp deleted file mode 100644 index 44535e7344..0000000000 --- a/llarp/messages/discard.hpp +++ /dev/null @@ -1,127 +0,0 @@ -#pragma once - -#include "link_message.hpp" -#include -#include -#include - -namespace llarp -{ - struct LinkDiscardMessage final : public AbstractLinkMessage - { - LinkDiscardMessage() : AbstractLinkMessage() - {} - - std::string - bt_encode() const override - { - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("a", "x"); - } - catch (...) - { - log::critical(link_cat, "Error: RelayDownstreamMessage failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - - void - clear() override - { - version = 0; - } - - const char* - name() const override - { - return "Discard"; - } - - bool - decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override - { - if (key.startswith("a")) - { - llarp_buffer_t strbuf; - if (!bencode_read_string(buf, &strbuf)) - return false; - if (strbuf.sz != 1) - return false; - return *strbuf.cur == 'x'; - } - return false; - } - - bool - handle_message(Router* /*router*/) const override - { - return true; - } - }; - - namespace routing - { - struct DataDiscardMessage final : public AbstractRoutingMessage - { - PathID_t path_id; - - DataDiscardMessage() = default; - - DataDiscardMessage(const PathID_t& dst, uint64_t s) : path_id(dst) - { - sequence_number = s; - version = llarp::constants::proto_version; - } - - void - clear() override - { - version = 0; - } - - bool - handle_message(AbstractRoutingMessageHandler* h, Router* r) const override - { - return h->HandleDataDiscardMessage(*this, r); - } - - bool - decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) override - { - bool read = false; - if (!BEncodeMaybeReadDictEntry("P", path_id, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("S", sequence_number, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("V", version, read, k, buf)) - return false; - return read; - } - - std::string - bt_encode() const override - { - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("A", "D"); - btdp.append("P", path_id.ToView()); - btdp.append("S", sequence_number); - btdp.append("V", version); - } - catch (...) - { - log::critical(route_cat, "Error: DataDiscardMessage failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - }; - } // namespace routing - -} // namespace llarp diff --git a/llarp/messages/relay_commit.cpp b/llarp/messages/relay_commit.cpp deleted file mode 100644 index 529bd96ab7..0000000000 --- a/llarp/messages/relay_commit.cpp +++ /dev/null @@ -1,493 +0,0 @@ -#include "relay_commit.hpp" -#include "relay_status.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace llarp -{ - bool - LR_CommitMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) - { - if (key.startswith("c")) - { - /// so we dont put it into the shitty queue - pathid.Fill('c'); - return BEncodeReadArray(frames, buf); - } - bool read = false; - if (!BEncodeMaybeVerifyVersion("v", version, llarp::constants::proto_version, read, key, buf)) - return false; - - return read; - } - - void - LR_CommitMessage::clear() - { - std::for_each(frames.begin(), frames.end(), [](auto& f) { f.Clear(); }); - version = 0; - } - - std::string - LR_CommitMessage::bt_encode() const - { - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("a", "c"); - { - auto sublist = btdp.append_list("c"); - - for (auto& f : frames) - sublist.append({reinterpret_cast(f.data()), f.size()}); - } - - btdp.append("v", llarp::constants::proto_version); - } - catch (...) - { - log::critical(link_cat, "Error: LR_CommitMessage failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - - bool - LR_CommitMessage::handle_message(Router* router) const - { - if (frames.size() != path::MAX_LEN) - { - llarp::LogError("LRCM invalid number of records, ", frames.size(), "!=", path::MAX_LEN); - return false; - } - if (!router->path_context().AllowingTransit()) - { - llarp::LogError("got LRCM when not permitting transit"); - return false; - } - return AsyncDecrypt(&router->path_context()); - } - - bool - LR_CommitRecord::BEncode(llarp_buffer_t* buf) const - { - if (!bencode_start_dict(buf)) - return false; - - if (!BEncodeWriteDictEntry("c", commkey, buf)) - return false; - if (!BEncodeWriteDictEntry("i", nextHop, buf)) - return false; - if (lifetime > 10s && lifetime < path::DEFAULT_LIFETIME) - { - if (!BEncodeWriteDictInt("i", lifetime.count(), buf)) - return false; - } - if (!BEncodeWriteDictEntry("n", tunnelNonce, buf)) - return false; - if (!BEncodeWriteDictEntry("r", rxid, buf)) - return false; - if (!BEncodeWriteDictEntry("t", txid, buf)) - return false; - if (nextRC) - { - if (!BEncodeWriteDictEntry("u", *nextRC, buf)) - return false; - } - - if (not bencode_write_uint64_entry(buf, "v", 1, llarp::constants::proto_version)) - return false; - if (work and not BEncodeWriteDictEntry("w", *work, buf)) - return false; - - return bencode_end(buf); - } - - bool - LR_CommitRecord::OnKey(llarp_buffer_t* buffer, llarp_buffer_t* key) - { - if (!key) - return true; - - bool read = false; - - if (!BEncodeMaybeReadDictEntry("c", commkey, read, *key, buffer)) - return false; - if (!BEncodeMaybeReadDictEntry("i", nextHop, read, *key, buffer)) - return false; - if (!BEncodeMaybeReadDictInt("l", lifetime, read, *key, buffer)) - return false; - if (!BEncodeMaybeReadDictEntry("n", tunnelNonce, read, *key, buffer)) - return false; - if (!BEncodeMaybeReadDictEntry("r", rxid, read, *key, buffer)) - return false; - if (!BEncodeMaybeReadDictEntry("t", txid, read, *key, buffer)) - return false; - if (key->startswith("u")) - { - nextRC = std::make_unique(); - return nextRC->BDecode(buffer); - } - if (!BEncodeMaybeVerifyVersion( - "v", version, llarp::constants::proto_version, read, *key, buffer)) - return false; - if (key->startswith("w")) - { - // check for duplicate - if (work) - { - llarp::LogWarn("duplicate POW in LRCR"); - return false; - } - - work = std::make_unique(); - return bencode_decode_dict(*work, buffer); - } - return read; - } - - bool - LR_CommitRecord::BDecode(llarp_buffer_t* buf) - { - return bencode_read_dict(util::memFn(&LR_CommitRecord::OnKey, this), buf); - } - - bool - LR_CommitRecord::operator==(const LR_CommitRecord& other) const - { - if (work && other.work) - { - if (*work != *other.work) - return false; - } - return nextHop == other.nextHop && commkey == other.commkey && txid == other.txid - && rxid == other.rxid; - } - - struct LRCMFrameDecrypt - { - using Context = llarp::path::PathContext; - using Hop = llarp::path::TransitHop; - using Decrypter = AsyncFrameDecrypter; - using Decrypter_ptr = std::unique_ptr; - Decrypter_ptr decrypter; - std::array frames; - Context* context; - // decrypted record - LR_CommitRecord record; - // the actual hop - std::shared_ptr hop; - - oxen::quic::Address from_addr; - - LRCMFrameDecrypt(Context* ctx, Decrypter_ptr dec, const LR_CommitMessage* commit) - : decrypter(std::move(dec)) - , frames(commit->frames) - , context(ctx) - , hop(std::make_shared()) - , from_addr{ - commit->conn->remote_rc.IsPublicRouter() ? oxen::quic::Address{} - : commit->conn->remote_rc.addr} - { - hop->info.downstream = commit->conn->remote_rc.pubkey; - } - - ~LRCMFrameDecrypt() = default; - - static void - OnForwardLRCMResult( - Router* router, - std::shared_ptr path, - const PathID_t pathid, - const RouterID nextHop, - const SharedSecret pathKey, - SendStatus sendStatus) - { - uint64_t status = LR_StatusRecord::FAIL_DEST_INVALID; - - switch (sendStatus) - { - case SendStatus::Success: - // do nothing, will forward success message later - return; - case SendStatus::Timeout: - status = LR_StatusRecord::FAIL_TIMEOUT; - break; - case SendStatus::NoLink: - status = LR_StatusRecord::FAIL_CANNOT_CONNECT; - break; - case SendStatus::InvalidRouter: - status = LR_StatusRecord::FAIL_DEST_INVALID; - break; - case SendStatus::RouterNotFound: - status = LR_StatusRecord::FAIL_DEST_UNKNOWN; - break; - case SendStatus::Congestion: - status = LR_StatusRecord::FAIL_CONGESTION; - break; - default: - LogError("llarp::SendStatus value not in enum class"); - std::abort(); - break; - } - router->queue_work([router, path, pathid, nextHop, pathKey, status] { - LR_StatusMessage::CreateAndSend(router, path, pathid, nextHop, pathKey, status); - }); - } - - /// this is done from logic thread - static void - SendLRCM(std::shared_ptr self) - { - if (self->context->HasTransitHop(self->hop->info)) - { - llarp::LogError("duplicate transit hop ", self->hop->info); - LR_StatusMessage::CreateAndSend( - self->context->router(), - self->hop, - self->hop->info.rxID, - self->hop->info.downstream, - self->hop->pathKey, - LR_StatusRecord::FAIL_DUPLICATE_HOP); - self->hop = nullptr; - return; - } - - if (self->from_addr.is_addressable()) - { - // only do ip limiting from non service nodes -#ifndef LOKINET_HIVE - if (self->context->CheckPathLimitHitByIP(self->from_addr.to_string())) - { - // we hit a limit so tell it to slow tf down - llarp::LogError("client path build hit limit ", self->from_addr); - OnForwardLRCMResult( - self->context->router(), - self->hop, - self->hop->info.rxID, - self->hop->info.downstream, - self->hop->pathKey, - SendStatus::Congestion); - self->hop = nullptr; - return; - } -#endif - } - - if (not self->context->router()->PathToRouterAllowed(self->hop->info.upstream)) - { - // we are not allowed to forward it ... now what? - llarp::LogError( - "path to ", - self->hop->info.upstream, - "not allowed, dropping build request on the floor"); - OnForwardLRCMResult( - self->context->router(), - self->hop, - self->hop->info.rxID, - self->hop->info.downstream, - self->hop->pathKey, - SendStatus::InvalidRouter); - self->hop = nullptr; - return; - } - // persist sessions to upstream and downstream routers until the commit - // ends - self->context->router()->persist_connection_until( - self->hop->info.downstream, self->hop->ExpireTime() + 10s); - self->context->router()->persist_connection_until( - self->hop->info.upstream, self->hop->ExpireTime() + 10s); - // put hop - self->context->PutTransitHop(self->hop); - // forward to next hop - using std::placeholders::_1; - auto func = [self](auto status) { - OnForwardLRCMResult( - self->context->router(), - self->hop, - self->hop->info.rxID, - self->hop->info.downstream, - self->hop->pathKey, - status); - self->hop = nullptr; - }; - self->context->ForwardLRCM(self->hop->info.upstream, self->frames, func); - // trigger idempotent pump to ensure that the build messages propagate - self->context->router()->TriggerPump(); - } - - // this is called from the logic thread - static void - SendPathConfirm(std::shared_ptr self) - { - // send path confirmation - // TODO: other status flags? - uint64_t status = LR_StatusRecord::SUCCESS; - if (self->context->HasTransitHop(self->hop->info)) - { - status = LR_StatusRecord::FAIL_DUPLICATE_HOP; - } - else - { - // persist session to downstream until path expiration - self->context->router()->persist_connection_until( - self->hop->info.downstream, self->hop->ExpireTime() + 10s); - // put hop - self->context->PutTransitHop(self->hop); - } - - if (!LR_StatusMessage::CreateAndSend( - self->context->router(), - self->hop, - self->hop->info.rxID, - self->hop->info.downstream, - self->hop->pathKey, - status)) - { - llarp::LogError("failed to send path confirmation for ", self->hop->info); - } - self->hop = nullptr; - } - - // TODO: If decryption has succeeded here but we otherwise don't - // want to or can't accept the path build request, send - // a status message saying as much. - static void - HandleDecrypted(llarp_buffer_t* buf, std::shared_ptr self) - { - auto now = self->context->router()->now(); - auto& info = self->hop->info; - if (!buf) - { - llarp::LogError("LRCM decrypt failed from ", info.downstream); - self->decrypter = nullptr; - return; - } - buf->cur = buf->base + EncryptedFrameOverheadSize; - llarp::LogDebug("decrypted LRCM from ", info.downstream); - // successful decrypt - if (!self->record.BDecode(buf)) - { - llarp::LogError("malformed frame inside LRCM from ", info.downstream); - self->decrypter = nullptr; - return; - } - - info.txID = self->record.txid; - info.rxID = self->record.rxid; - - if (info.txID.IsZero() || info.rxID.IsZero()) - { - llarp::LogError("LRCM refusing zero pathid"); - self->decrypter = nullptr; - return; - } - - info.upstream = self->record.nextHop; - - // generate path key as we are in a worker thread - auto crypto = CryptoManager::instance(); - if (!crypto->dh_server( - self->hop->pathKey, - self->record.commkey, - self->context->EncryptionSecretKey(), - self->record.tunnelNonce)) - { - llarp::LogError("LRCM DH Failed ", info); - self->decrypter = nullptr; - return; - } - // generate hash of hop key for nonce mutation - crypto->shorthash(self->hop->nonceXOR, self->hop->pathKey.data(), self->hop->pathKey.size()); - if (self->record.work && self->record.work->IsValid(now)) - { - llarp::LogDebug( - "LRCM extended lifetime by ", - ToString(self->record.work->extendedLifetime), - " for ", - info); - self->hop->lifetime += self->record.work->extendedLifetime; - } - else if (self->record.lifetime < path::DEFAULT_LIFETIME && self->record.lifetime > 10s) - { - self->hop->lifetime = self->record.lifetime; - llarp::LogDebug( - "LRCM short lifespan set to ", ToString(self->hop->lifetime), " for ", info); - } - - // TODO: check if we really want to accept it - self->hop->started = now; - - // self->context->router()->NotifyRouterEvent( - // self->context->router()->pubkey(), self->hop); - - size_t sz = self->frames[0].size(); - // shift - std::array frames; - frames[0] = self->frames[1]; - frames[1] = self->frames[2]; - frames[2] = self->frames[3]; - frames[3] = self->frames[4]; - frames[4] = self->frames[5]; - frames[5] = self->frames[6]; - frames[6] = self->frames[7]; - // put our response on the end - frames[7] = EncryptedFrame(sz - EncryptedFrameOverheadSize); - // random junk for now - frames[7].Randomize(); - self->frames = std::move(frames); - if (self->context->HopIsUs(info.upstream)) - { - // we are the farthest hop - llarp::LogDebug("We are the farthest hop for ", info); - // send a LRSM down the path - self->context->loop()->call([self] { - SendPathConfirm(self); - self->decrypter = nullptr; - }); - } - else - { - // forward upstream - // we are still in the worker thread so post job to logic - self->context->loop()->call([self] { - SendLRCM(self); - self->decrypter = nullptr; - }); - } - // trigger idempotent pump to ensure that the build messages propagate - self->context->router()->TriggerPump(); - } - }; - - bool - LR_CommitMessage::AsyncDecrypt(llarp::path::PathContext* context) const - { - auto decrypter = std::make_unique( - context->EncryptionSecretKey(), &LRCMFrameDecrypt::HandleDecrypted); - // copy frames so we own them - auto frameDecrypt = std::make_shared(context, std::move(decrypter), this); - - // decrypt frames async - frameDecrypt->decrypter->AsyncDecrypt( - frameDecrypt->frames[0], frameDecrypt, [r = context->router()](auto func) { - r->loop()->call([&]() { func(); }); - }); - return true; - } -} // namespace llarp diff --git a/llarp/messages/relay_status.cpp b/llarp/messages/relay_status.cpp deleted file mode 100644 index 62c14f84ae..0000000000 --- a/llarp/messages/relay_status.cpp +++ /dev/null @@ -1,325 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -namespace llarp -{ - struct LRSM_AsyncHandler : public std::enable_shared_from_this - { - using HopHandler_ptr = std::shared_ptr; - - std::array frames; - uint64_t status = 0; - HopHandler_ptr hop; - Router* router; - PathID_t pathid; - - LRSM_AsyncHandler( - std::array _frames, - uint64_t _status, - HopHandler_ptr _hop, - Router* _router, - PathID_t pathid) - : frames{std::move(_frames)} - , status{_status} - , hop{std::move(_hop)} - , router{_router} - , pathid{std::move(pathid)} - {} - - ~LRSM_AsyncHandler() = default; - - void - handle() - { - router->notify_router_event( - router->pubkey(), pathid, status); - hop->HandleLRSM(status, frames, router); - } - - void - queue_handle() - { - auto func = [self = shared_from_this()] { self->handle(); }; - router->queue_work(func); - } - }; - - bool - LR_StatusMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) - { - bool read = false; - if (key.startswith("c")) - { - return BEncodeReadArray(frames, buf); - } - if (key.startswith("p")) - { - if (!BEncodeMaybeReadDictEntry("p", pathid, read, key, buf)) - { - return false; - } - } - else if (key.startswith("s")) - { - if (!BEncodeMaybeReadDictInt("s", status, read, key, buf)) - { - return false; - } - } - else if (key.startswith("v")) - { - if (!BEncodeMaybeVerifyVersion("v", version, llarp::constants::proto_version, read, key, buf)) - { - return false; - } - } - - return read; - } - - void - LR_StatusMessage::clear() - { - std::for_each(frames.begin(), frames.end(), [](auto& f) { f.Clear(); }); - version = 0; - status = 0; - } - - std::string - LR_StatusMessage::bt_encode() const - { - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("a", "s"); - - { - auto sublist = btdp.append_list("c"); - - for (auto& f : frames) - sublist.append({reinterpret_cast(f.data()), f.size()}); - } - - btdp.append("p", pathid.ToView()); - btdp.append("s", status); - btdp.append("v", llarp::constants::proto_version); - } - catch (...) - { - log::critical(link_cat, "Error: LR_StatusMessage failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - - bool - LR_StatusMessage::handle_message(Router* router) const - { - llarp::LogDebug("Received LR_Status message from (", conn->remote_rc.pubkey, ")"); - if (frames.size() != path::MAX_LEN) - { - llarp::LogError("LRSM invalid number of records, ", frames.size(), "!=", path::MAX_LEN); - return false; - } - - auto path = router->path_context().GetByUpstream(conn->remote_rc.pubkey, pathid); - if (not path) - { - llarp::LogWarn("unhandled LR_Status message: no associated path found pathid=", pathid); - return false; - } - auto handler = std::make_shared(frames, status, path, router, pathid); - handler->queue_handle(); - return true; - } - - void - LR_StatusMessage::SetDummyFrames() - { - for (auto& f : frames) - f.Randomize(); - } - - // call this from a worker thread - bool - LR_StatusMessage::CreateAndSend( - Router* router, - std::shared_ptr hop, - const PathID_t pathid, - const RouterID nextHop, - const SharedSecret pathKey, - uint64_t status) - { - auto message = std::make_shared(); - - message->status = status; - message->pathid = pathid; - - message->SetDummyFrames(); - - message->AddFrame(pathKey, status); - - QueueSendMessage(router, nextHop, message, hop); - return true; // can't guarantee delivery here, as far as we know it's fine - } - - bool - LR_StatusMessage::AddFrame(const SharedSecret& pathKey, uint64_t newStatus) - { - frames[7] = frames[6]; - frames[6] = frames[5]; - frames[5] = frames[4]; - frames[4] = frames[3]; - frames[3] = frames[2]; - frames[2] = frames[1]; - frames[1] = frames[0]; - - auto& frame = frames[0]; - - frame.Randomize(); - - LR_StatusRecord record; - - record.status = newStatus; - record.version = llarp::constants::proto_version; - - llarp_buffer_t buf(frame.data(), frame.size()); - buf.cur = buf.base + EncryptedFrameOverheadSize; - // encode record - if (!record.BEncode(&buf)) - { - // failed to encode? - LogError(name(), " Failed to generate Status Record"); - DumpBuffer(buf); - return false; - } - // use ephemeral keypair for frame - if (!frame.DoEncrypt(pathKey, true)) - { - LogError(name(), " Failed to encrypt LRSR"); - DumpBuffer(buf); - return false; - } - - return true; - } - - void - LR_StatusMessage::QueueSendMessage( - Router* router, - const RouterID nextHop, - std::shared_ptr msg, - std::shared_ptr hop) - { - router->loop()->call([router, nextHop, msg = std::move(msg), hop = std::move(hop)] { - SendMessage(router, nextHop, msg, hop); - }); - } - - void - LR_StatusMessage::SendMessage( - Router* router, - const RouterID nextHop, - std::shared_ptr msg, - std::shared_ptr hop) - { - llarp::LogDebug("Attempting to send LR_Status message to (", nextHop, ")"); - - auto resultCallback = [hop, router, msg, nextHop](auto status) { - if ((msg->status & LR_StatusRecord::SUCCESS) != LR_StatusRecord::SUCCESS - or status != SendStatus::Success) - { - llarp::LogError("Failed to propagate LR_Status message to ", nextHop); - hop->QueueDestroySelf(router); - } - }; - - // send the status message to previous hop - // if it fails we are hitting a failure case we can't cope with so ... drop. - - // TODO: replace with new message serialization - // if (not router->SendToOrQueue(nextHop, *msg, resultCallback)) - // resultCallback(SendStatus::Congestion); - - // trigger idempotent pump to make sure stuff gets sent - router->TriggerPump(); - } - - bool - LR_StatusRecord::BEncode(llarp_buffer_t* buf) const - { - return bencode_start_dict(buf) && BEncodeWriteDictInt("s", status, buf) - && bencode_write_uint64_entry(buf, "v", 1, llarp::constants::proto_version) - && bencode_end(buf); - } - - bool - LR_StatusRecord::OnKey(llarp_buffer_t* buffer, llarp_buffer_t* key) - { - if (!key) - return true; - - bool read = false; - - if (!BEncodeMaybeReadDictInt("s", status, read, *key, buffer)) - return false; - if (!BEncodeMaybeVerifyVersion( - "v", version, llarp::constants::proto_version, read, *key, buffer)) - return false; - - return read; - } - - bool - LR_StatusRecord::BDecode(llarp_buffer_t* buf) - { - return bencode_read_dict(util::memFn(&LR_StatusRecord::OnKey, this), buf); - } - - bool - LR_StatusRecord::operator==(const LR_StatusRecord& other) const - { - return status == other.status; - } - - using namespace std::literals; - static constexpr std::array code_strings = { - std::make_pair(LR_StatusRecord::SUCCESS, "success"sv), - std::make_pair(LR_StatusRecord::FAIL_TIMEOUT, "timeout"sv), - std::make_pair(LR_StatusRecord::FAIL_CONGESTION, "congestion"sv), - std::make_pair(LR_StatusRecord::FAIL_DEST_UNKNOWN, "destination unknown"sv), - std::make_pair(LR_StatusRecord::FAIL_DECRYPT_ERROR, "decrypt error"sv), - std::make_pair(LR_StatusRecord::FAIL_MALFORMED_RECORD, "malformed record"sv), - std::make_pair(LR_StatusRecord::FAIL_DEST_INVALID, "destination invalid"sv), - std::make_pair(LR_StatusRecord::FAIL_CANNOT_CONNECT, "cannot connect"sv), - std::make_pair(LR_StatusRecord::FAIL_DUPLICATE_HOP, "duplicate hop"sv)}; - - std::string - LRStatusCodeToString(uint64_t status) - { - std::string s = "["; - for (const auto& [val, message] : code_strings) - { - if ((status & val) == val) - { - if (s.size() > 1) - s += ", "; - s += message; - } - } - s += ']'; - return s; - } - -} // namespace llarp diff --git a/llarp/net/traffic_policy.cpp b/llarp/net/traffic_policy.cpp index e10b1eaae7..62701f955b 100644 --- a/llarp/net/traffic_policy.cpp +++ b/llarp/net/traffic_policy.cpp @@ -1,5 +1,7 @@ #include "traffic_policy.hpp" -#include "llarp/util/str.hpp" + +#include +#include namespace llarp::net { diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index 8bc1289a63..7c5661b1a3 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -93,7 +93,7 @@ namespace llarp std::optional GetRandom(Filter visit) const { - return router.loop()->call_get([this, visit]() -> std::optional { + return router.loop()->call_get([visit]() -> std::optional { std::vector entries; for (const auto& entry : entries) entries.push_back(entry); diff --git a/llarp/path/abstracthophandler.hpp b/llarp/path/abstracthophandler.hpp index 468b9acd03..69fcb7c367 100644 --- a/llarp/path/abstracthophandler.hpp +++ b/llarp/path/abstracthophandler.hpp @@ -49,7 +49,7 @@ namespace llarp /// send routing message and increment sequence number virtual bool - SendRoutingMessage(const routing::AbstractRoutingMessage& msg, Router* r) = 0; + SendRoutingMessage(std::string payload, Router* r) = 0; // handle data in upstream direction virtual bool diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 13eeb09800..fe2551f7e1 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -2,16 +2,13 @@ #include "pathbuilder.hpp" #include "transit_hop.hpp" -#include #include #include -#include #include #include #include #include #include -#include #include @@ -552,7 +549,7 @@ namespace llarp::path } void - Path::HandleAllDownstream(std::vector msgs, Router* r) + Path::HandleAllDownstream(std::vector msgs, Router* /* r */) { for (const auto& msg : msgs) { @@ -582,34 +579,27 @@ namespace llarp::path std::move around. */ bool - Path::SendRoutingMessage(const routing::AbstractRoutingMessage& msg, Router* r) + Path::SendRoutingMessage(std::string payload, Router*) { - std::array tmp; - llarp_buffer_t buf(tmp); - - auto bte = msg.bt_encode(); - buf.write(bte.begin(), bte.end()); + std::string buf(MAX_LINK_MSG_SIZE / 2, '\0'); + buf.insert(0, payload); // make nonce TunnelNonce N; N.Randomize(); - buf.sz = buf.cur - buf.base; + // pad smaller messages - if (buf.sz < PAD_SIZE) + if (payload.size() < PAD_SIZE) { // randomize padding - CryptoManager::instance()->randbytes(buf.cur, PAD_SIZE - buf.sz); - buf.sz = PAD_SIZE; + CryptoManager::instance()->randbytes( + reinterpret_cast(buf.data()) + payload.size(), PAD_SIZE - payload.size()); } - buf.cur = buf.base; - LogDebug( - "send routing message ", - msg.sequence_number, - " with ", - buf.sz, - " bytes to endpoint ", - Endpoint()); - return HandleUpstream(buf, N, r); + log::debug(path_cat, "Sending {}B routing message to {}", buf.size(), Endpoint()); + + // TODO: path relaying here + + return true; } template diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 8be7ed0e76..bb3a294ede 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -3,7 +3,6 @@ #include "abstracthophandler.hpp" #include "path_types.hpp" #include "pathset.hpp" -// #include "pathbuilder.hpp" #include #include @@ -27,7 +26,6 @@ namespace llarp { struct Router; - struct LR_CommitMessage; namespace path { @@ -219,7 +217,7 @@ namespace llarp std::function func = nullptr) override; bool - SendRoutingMessage(const routing::AbstractRoutingMessage& msg, Router* r) override; + SendRoutingMessage(std::string payload, Router* r) override; bool IsReady() const; diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index a54b674a8b..ef4ebbe7a1 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -1,7 +1,6 @@ #include "path.hpp" #include "path_context.hpp" -#include #include namespace llarp::path @@ -375,31 +374,6 @@ namespace llarp::path } } - routing::MessageHandler_ptr - PathContext::GetHandler(const PathID_t& id) - { - routing::MessageHandler_ptr h = nullptr; - auto pathset = GetLocalPathSet(id); - if (pathset) - { - h = pathset->GetPathByID(id); - } - if (h) - return h; - const RouterID us(OurRouterID()); - auto& map = m_TransitPaths; - { - SyncTransitMap_t::Lock_t lock(map.first); - auto range = map.second.equal_range(id); - for (auto i = range.first; i != range.second; ++i) - { - if (i->second->info.upstream == us) - return i->second; - } - } - return nullptr; - } - void PathContext::RemovePathSet(PathSet_ptr) {} diff --git a/llarp/path/path_context.hpp b/llarp/path/path_context.hpp index 7743a8e2ea..8cf8138a74 100644 --- a/llarp/path/path_context.hpp +++ b/llarp/path/path_context.hpp @@ -1,12 +1,12 @@ #pragma once -#include -#include #include "abstracthophandler.hpp" #include "path_types.hpp" #include "pathset.hpp" #include "transit_hop.hpp" -#include + +#include +#include #include #include #include @@ -17,9 +17,6 @@ namespace llarp { struct Router; - struct LR_CommitMessage; - struct RelayDownstreamMessage; - struct RelayUpstreamMessage; struct RouterID; namespace path @@ -61,9 +58,6 @@ namespace llarp bool HasTransitHop(const TransitHopInfo& info); - bool - HandleRelayCommit(const LR_CommitMessage& msg); - void PutTransitHop(std::shared_ptr hop); @@ -88,9 +82,6 @@ namespace llarp PathSet_ptr GetLocalPathSet(const PathID_t& id); - routing::MessageHandler_ptr - GetHandler(const PathID_t& id); - using EndpointPathPtrSet = std::set>; /// get a set of all paths that we own who's endpoint is r EndpointPathPtrSet @@ -99,12 +90,6 @@ namespace llarp bool HopIsUs(const RouterID& k) const; - bool - HandleLRUM(const RelayUpstreamMessage& msg); - - bool - HandleLRDM(const RelayDownstreamMessage& msg); - void AddOwnPath(PathSet_ptr set, Path_ptr p); diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index c3243893cf..7c1487011e 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -5,12 +5,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include @@ -420,7 +418,9 @@ namespace llarp std::string path_shortName = "[path " + router->ShortName() + "-"; path_shortName = path_shortName + std::to_string(router->NextPathBuildNumber()) + "]"; - auto path = std::make_shared(hops, GetWeak(), roles, std::move(path_shortName)); + + auto path = + std::make_shared(router, hops, GetWeak(), roles, std::move(path_shortName)); log::info( path_cat, "{} building path -> {} : {}", Name(), path->ShortName(), path->HopsString()); diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index e7407e29a0..bcf867a92e 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -3,9 +3,7 @@ #include "transit_hop.hpp" #include -#include #include -#include #include #include @@ -43,8 +41,7 @@ namespace llarp::path return started + lifetime; } - TransitHopInfo::TransitHopInfo(const RouterID& down, const LR_CommitRecord& record) - : txID(record.txid), rxID(record.rxid), upstream(record.nextHop), downstream(down) + TransitHopInfo::TransitHopInfo(const RouterID& down) : downstream(down) {} /** Note: this is one of two places where AbstractRoutingMessage::bt_encode() is called, the @@ -63,26 +60,26 @@ namespace llarp::path std::move around. */ bool - TransitHop::SendRoutingMessage(const routing::AbstractRoutingMessage& msg, Router* r) + TransitHop::SendRoutingMessage(std::string payload, Router* r) { if (!IsEndpoint(r->pubkey())) return false; - auto buf = msg.bt_encode(); - TunnelNonce N; N.Randomize(); // pad to nearest MESSAGE_PAD_SIZE bytes - auto dlt = buf.size() % PAD_SIZE; + auto dlt = payload.size() % PAD_SIZE; if (dlt) { dlt = PAD_SIZE - dlt; // randomize padding - CryptoManager::instance()->randbytes(reinterpret_cast(buf.data()), dlt); + CryptoManager::instance()->randbytes(reinterpret_cast(payload.data()), dlt); } - return HandleDownstream(buf, N, r); + // TODO: relay message along + + return true; } void @@ -166,7 +163,7 @@ namespace llarp::path for (const auto& msg : msgs) { const llarp_buffer_t buf(msg.enc); - if (!r->ParseRoutingMessageBuffer(buf, this, info.rxID)) + if (!r->ParseRoutingMessageBuffer(buf, *this, info.rxID)) { LogWarn("invalid upstream data on endpoint ", info); } @@ -190,7 +187,7 @@ namespace llarp::path info.downstream, " to ", info.upstream); - r->send_data_message(info.upstream, msg); + r->send_data_message(info.upstream, msg.bt_encode()); } } r->TriggerPump(); @@ -207,6 +204,7 @@ namespace llarp::path msg.enc.size(), info.upstream, info.downstream); + // TODO: is this right? r->send_data_message(info.downstream, msg.bt_encode()); } diff --git a/llarp/path/transit_hop.hpp b/llarp/path/transit_hop.hpp index 1a1725edbc..956a99691f 100644 --- a/llarp/path/transit_hop.hpp +++ b/llarp/path/transit_hop.hpp @@ -9,8 +9,6 @@ namespace llarp { - struct LR_CommitRecord; - namespace dht { struct GotIntroMessage; @@ -21,7 +19,7 @@ namespace llarp struct TransitHopInfo { TransitHopInfo() = default; - TransitHopInfo(const RouterID& down, const LR_CommitRecord& record); + TransitHopInfo(const RouterID& down); PathID_t txID, rxID; RouterID upstream; @@ -116,10 +114,7 @@ namespace llarp // send routing message when end of path bool - SendRoutingMessage(const routing::AbstractRoutingMessage& msg, Router* r) override; - - bool - HandleDHTMessage(const dht::AbstractDHTMessage& msg, Router* r) override; + SendRoutingMessage(std::string payload, Router* r) override; void FlushUpstream(Router* r) override; diff --git a/llarp/router/rc_gossiper.cpp b/llarp/router/rc_gossiper.cpp index b394962c29..fce7bacdcb 100644 --- a/llarp/router/rc_gossiper.cpp +++ b/llarp/router/rc_gossiper.cpp @@ -1,9 +1,7 @@ #include "rc_gossiper.hpp" -#include -#include + #include #include -#include #include namespace llarp @@ -95,10 +93,10 @@ namespace llarp } // send a GRCM as gossip method - DHTImmediateMessage gossip; - gossip.msgs.emplace_back(new dht::GotRouterMessage(dht::Key_t{}, 0, {rc}, false)); + // DHTImmediateMessage gossip; + // gossip.msgs.emplace_back(new dht::GotRouterMessage(dht::Key_t{}, 0, {rc}, false)); - std::vector gossipTo; + // std::vector gossipTo; /* * TODO: gossip RC via libquic diff --git a/llarp/router/rc_lookup_handler.hpp b/llarp/router/rc_lookup_handler.hpp index a0f5ade36f..cad8c46e2f 100644 --- a/llarp/router/rc_lookup_handler.hpp +++ b/llarp/router/rc_lookup_handler.hpp @@ -17,11 +17,6 @@ namespace llarp struct Router; class EventLoop; - namespace dht - { - struct AbstractDHTMessageHandler; - } // namespace dht - namespace service { struct Context; diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 1cdd46708d..01386828ab 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -12,8 +12,6 @@ #include #include #include -#include -#include #include #include #include @@ -506,8 +504,9 @@ namespace llarp bool Router::ParseRoutingMessageBuffer( - const llarp_buffer_t&, routing::AbstractRoutingMessageHandler*, const PathID_t&) + const llarp_buffer_t&, path::AbstractHopHandler&, const PathID_t&) { + // TODO: will go away with the removal of flush upstream/downstream return false; } @@ -1539,10 +1538,4 @@ namespace llarp return *llarp::net::Platform::Default_ptr(); } - void - Router::handle_router_event(std::unique_ptr event) const - { - LogDebug(event->ToString()); - } - } // namespace llarp diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 9add6d3b2e..11e00190f7 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -18,13 +18,9 @@ #include #include #include -#include -#include -#include #include #include #include -#include #include #include #include @@ -33,6 +29,7 @@ #include #include +#include #include #include #include @@ -109,7 +106,6 @@ namespace llarp exit::Context _exit_context; SecretKey _identity; SecretKey _encryption; - std::shared_ptr _dh_t; std::shared_ptr _contacts; std::shared_ptr _node_db; llarp_time_t _started_at; @@ -162,10 +158,6 @@ namespace llarp bool insufficient_peers() const; - protected: - void - handle_router_event(std::unique_ptr event) const; - public: void for_each_connection(std::function func); @@ -320,15 +312,6 @@ namespace llarp const std::vector& greylist, const std::vector& unfunded); - template - void - notify_router_event([[maybe_unused]] Params&&... args) const - { - // TODO: no-op when appropriate - auto event = std::make_unique(args...); - handle_router_event(std::move(event)); - } - void queue_work(std::function func); @@ -536,7 +519,7 @@ namespace llarp /// return false bool ParseRoutingMessageBuffer( - const llarp_buffer_t& buf, routing::AbstractRoutingMessageHandler* h, const PathID_t& rxid); + const llarp_buffer_t& buf, path::AbstractHopHandler& p, const PathID_t& rxid); void ConnectToRandomRouters(int N); diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index b740028d32..1ad7f1da02 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -95,10 +95,12 @@ namespace llarp signature.from_string(btlc.consume_string()); signed_bt_dict = btlc.consume_string(); + + // TODO: parse bt dict } catch (...) { - log::critical(llarp_cat, "Error: RouterContact failed to populate bt encoded contents!"); + log::warning(llarp_cat, "Error: RouterContact failed to populate bt encoded contents!"); } } @@ -114,7 +116,7 @@ namespace llarp } catch (...) { - log::critical(llarp_cat, "Error: RouterContact failed to bt encode contents!"); + log::warning(llarp_cat, "Error: RouterContact failed to bt encode contents!"); } return std::move(btlp).str(); @@ -154,7 +156,7 @@ namespace llarp btdp.append("i", netID.ToView()); btdp.append("k", pubkey.bt_encode()); btdp.append("p", enckey.ToView()); - btdp.append("r", routerVersion); + btdp.append("r", routerVersion->ToString()); if (not srvRecords.empty()) { @@ -280,8 +282,10 @@ namespace llarp RouterContact::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) { bool read = false; - if (!BEncodeMaybeReadDictList("a", addr, read, key, buf)) - return false; + + // 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; diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index 6775362632..31eaabacb5 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -131,8 +131,8 @@ namespace llarp 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; + && signature == other.signature && last_updated == other.last_updated + && netID == other.netID; } bool diff --git a/llarp/rpc/endpoint_rpc.cpp b/llarp/rpc/endpoint_rpc.cpp index ca2e4e41a6..58fa0e2a6b 100644 --- a/llarp/rpc/endpoint_rpc.cpp +++ b/llarp/rpc/endpoint_rpc.cpp @@ -1,4 +1,5 @@ #include "endpoint_rpc.hpp" + #include namespace llarp::rpc diff --git a/llarp/rpc/endpoint_rpc.hpp b/llarp/rpc/endpoint_rpc.hpp index b521537ebb..73cfd12709 100644 --- a/llarp/rpc/endpoint_rpc.hpp +++ b/llarp/rpc/endpoint_rpc.hpp @@ -1,6 +1,8 @@ #pragma once #include +#include + #include namespace llarp::service @@ -24,7 +26,8 @@ namespace llarp::rpc std::unordered_set token_whitelist, LMQ_ptr lmq, Endpoint_ptr endpoint); - virtual ~EndpointAuthRPC() = default; + + ~EndpointAuthRPC() override = default; void Start(); diff --git a/llarp/rpc/rpc_server.cpp b/llarp/rpc/rpc_server.cpp index fe0139e261..2f08011ce9 100644 --- a/llarp/rpc/rpc_server.cpp +++ b/llarp/rpc/rpc_server.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -214,7 +213,8 @@ namespace llarp::rpc if (quicconnect.request.closeID) { - quic->forget(quicconnect.request.closeID); + // TODO: + // quic->forget(quicconnect.request.closeID); SetJSONResponse("OK", quicconnect.response); return; } @@ -223,12 +223,13 @@ namespace llarp::rpc try { - auto [addr, id] = quic->open( - quicconnect.request.remoteHost, quicconnect.request.port, [](auto&&) {}, laddr); + // TODO: + // auto [addr, id] = quic->open( + // quicconnect.request.remoteHost, quicconnect.request.port, [](auto&&) {}, laddr); util::StatusObject status; - status["addr"] = addr.ToString(); - status["id"] = id; + // status["addr"] = addr.ToString(); + // status["id"] = id; SetJSONResponse(status, quicconnect.response); } @@ -269,7 +270,8 @@ namespace llarp::rpc if (quiclistener.request.closeID) { - quic->forget(quiclistener.request.closeID); + // TODO: + // quic->forget(quiclistener.request.closeID); SetJSONResponse("OK", quiclistener.response); return; } @@ -280,7 +282,8 @@ namespace llarp::rpc try { SockAddr addr{quiclistener.request.remoteHost, huint16_t{quiclistener.request.port}}; - id = quic->listen(addr); + // TODO: + // id = quic->listen(addr); } catch (std::exception& e) { diff --git a/llarp/service/auth.cpp b/llarp/service/auth.cpp index b4edf2ae46..8ef7e52505 100644 --- a/llarp/service/auth.cpp +++ b/llarp/service/auth.cpp @@ -1,11 +1,12 @@ #include "auth.hpp" -#include +#include "protocol.hpp" #include -#include "protocol.hpp" #include #include +#include + namespace llarp::service { /// maybe get auth result from string diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index f725eec7ad..4ede9518c0 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -19,7 +20,6 @@ #include #include -#include #include #include #include @@ -50,7 +50,7 @@ namespace llarp::service _recv_event_queue.enable(); if (Loop()->MaybeGetUVWLoop()) - _tunnel_manager = std::make_unique(*this); + _tunnel_manager = std::make_unique(*this); } bool @@ -167,7 +167,7 @@ namespace llarp::service auto result = ptr->EnsurePathToService( saddr, - [ptr, name, ranges, result_handler, poker](auto addr, auto* ctx) { + [ptr, name, ranges, result_handler, poker](auto addr, OutboundContext* ctx) { if (ctx == nullptr) { result_handler(false, "could not establish flow to {}"_format(name)); @@ -175,24 +175,23 @@ namespace llarp::service } // make a lambda that sends the reply after doing auth - auto apply_result = - [ptr, poker, addr, result_handler, ranges](AuthResult result) { - if (result.code != AuthResultCode::eAuthAccepted) - { - result_handler(false, result.reason); - return; - } + auto apply_result = [ptr, poker, addr, result_handler, ranges]( + std::string result, bool success) { + if (success) + { + for (const auto& range : ranges) + ptr->MapExitRange(range, addr); - for (const auto& range : ranges) - ptr->MapExitRange(range, addr); + if (poker) + poker->put_up(); - if (poker) - poker->put_up(); + result_handler(true, result); + } - result_handler(true, result.reason); - }; + result_handler(false, result); + }; - ctx->AsyncSendAuth(apply_result); + ctx->send_auth_async(apply_result); }, ptr->PathAlignmentTimeout()); @@ -662,11 +661,12 @@ namespace llarp::service } } // add quic ethertype if we have listeners set up - if (auto* quic = GetQUICTunnel()) - { - if (quic->hasListeners()) - intro_set().supported_protocols.push_back(ProtocolType::QUIC); - } + // if (auto* quic = GetQUICTunnel()) + // { + // TODO: + // if (quic->hasListeners()) + // intro_set().supported_protocols.push_back(ProtocolType::QUIC); + // } intro_set().intros.clear(); for (auto& intro : intros) @@ -730,7 +730,7 @@ namespace llarp::service return _state->remote_sessions.size() + _state->snode_sessions.size(); } - constexpr auto PublishIntrosetTimeout = 20s; + [[maybe_unused]] constexpr auto PublishIntrosetTimeout = 20s; void Endpoint::ResetInternalState() @@ -784,7 +784,7 @@ namespace llarp::service constexpr auto MaxOutboundContextPerRemote = 1; void - Endpoint::PutNewOutboundContext(const service::IntroSet& introset, llarp_time_t left) + Endpoint::PutNewOutboundContext(const service::IntroSet& introset, llarp_time_t) { const Address addr{introset.address_keys.Addr()}; @@ -799,8 +799,9 @@ namespace llarp::service auto sessionRange = remoteSessions.equal_range(addr); for (auto itr = sessionRange.first; itr != sessionRange.second; ++itr) { - itr->second->AddReadyHook( - [addr, this](auto session) { InformPathToService(addr, session); }, left); + // TODO: + // itr->second->AddReadyHook( + // [addr, this](auto session) { InformPathToService(addr, session); }, left); } } @@ -1058,7 +1059,7 @@ namespace llarp::service void Endpoint::SendAuthResult( - path::Path_ptr path, PathID_t replyPath, ConvoTag tag, std::string result, bool success) + path::Path_ptr path, PathID_t /* replyPath */, ConvoTag tag, std::string result, bool success) { // not applicable because we are not an exit or don't have an endpoint auth policy if ((not _state->is_exit_enabled) or _auth_policy == nullptr) @@ -1109,8 +1110,10 @@ namespace llarp::service return; } } - _send_queue.tryPushBack( - SendEvent{std::make_shared(f, replyPath), path}); + + // TODO: + // _send_queue.tryPushBack( + // SendEvent{std::make_shared(f, replyPath), path}); } void @@ -1120,7 +1123,7 @@ namespace llarp::service } void - Endpoint::ResetConvoTag(ConvoTag tag, path::Path_ptr p, PathID_t from) + Endpoint::ResetConvoTag(ConvoTag tag, path::Path_ptr p, PathID_t /* from */) { // send reset convo tag message ProtocolFrameMessage f{}; @@ -1131,8 +1134,9 @@ namespace llarp::service { LogWarn("invalidating convotag T=", tag); RemoveConvoTag(tag); - _send_queue.tryPushBack( - SendEvent{std::make_shared(f, from), p}); + // TODO: + // _send_queue.tryPushBack( + // SendEvent{std::make_shared(f, from), p}); } } @@ -1235,12 +1239,12 @@ namespace llarp::service [hook](auto, auto* ctx) -> bool { if (ctx) { - hook(ctx->currentConvoTag); - } - else - { - hook(std::nullopt); + hook(ctx->get_current_tag()); + return true; } + + hook(std::nullopt); + return false; }, timeout); } @@ -1436,7 +1440,7 @@ namespace llarp::service } void - Endpoint::Pump(llarp_time_t now) + Endpoint::Pump(llarp_time_t) { FlushRecvData(); // send downstream packets to user for snode @@ -1462,39 +1466,38 @@ namespace llarp::service msg.tag, msg.payload.size()); - if (HandleInboundPacket(msg.tag, msg.payload, msg.proto, msg.seqno)) - { - ConvoTagRX(msg.tag); - } - else - { - LogWarn("Failed to handle inbound message"); - } + // if (HandleInboundPacket(msg.tag, msg.payload, msg.proto, msg.seqno)) + // { + // ConvoTagRX(msg.tag); + // } + // else + // { + // LogWarn("Failed to handle inbound message"); + // } queue.pop(); - a } auto r = router(); // TODO: locking on this container - for (const auto& [addr, outctx] : _state->remote_sessions) - { - outctx->FlushUpstream(); - outctx->Pump(now); - } - // TODO: locking on this container - for (const auto& [r, session] : _state->snode_sessions) - session->FlushUpstream(); + // for (const auto& [addr, outctx] : _state->remote_sessions) + // { + // outctx->FlushUpstream(); + // outctx->Pump(now); + // } + // // TODO: locking on this container + // for (const auto& [r, session] : _state->snode_sessions) + // session->FlushUpstream(); - // send queue flush - while (not _send_queue.empty()) - { - SendEvent item = _send_queue.popFront(); - item.first->sequence_number = item.second->NextSeqNo(); - if (item.second->SendRoutingMessage(*item.first, r)) - ConvoTagTX(item.first->protocol_frame_msg.convo_tag); - } + // // send queue flush + // while (not _send_queue.empty()) + // { + // SendEvent item = _send_queue.popFront(); + // item.first->sequence_number = item.second->NextSeqNo(); + // if (item.second->SendRoutingMessage(*item.first, r)) + // ConvoTagTX(item.first->protocol_frame_msg.convo_tag); + // } UpstreamFlush(r); } @@ -1544,14 +1547,15 @@ namespace llarp::service auto itr = range.first; while (itr != range.second) { - if (itr->second->ReadyToSend() and itr->second->estimatedRTT > 0s) - { - if (itr->second->estimatedRTT < rtt) - { - ret = tag; - rtt = itr->second->estimatedRTT; - } - } + // TODO: + // if (itr->second->ReadyToSend() and itr->second->estimatedRTT > 0s) + // { + // if (itr->second->estimatedRTT < rtt) + // { + // ret = tag; + // rtt = itr->second->estimatedRTT; + // } + // } itr++; } } @@ -1712,7 +1716,7 @@ namespace llarp::service return itr->second; } - quic::TunnelManager* + link::TunnelManager* Endpoint::GetQUICTunnel() { return _tunnel_manager.get(); diff --git a/llarp/service/endpoint.hpp b/llarp/service/endpoint.hpp index 5d11fcdb14..3d1dfb073a 100644 --- a/llarp/service/endpoint.hpp +++ b/llarp/service/endpoint.hpp @@ -68,9 +68,8 @@ namespace llarp std::shared_ptr msg; }; - struct Endpoint : public path::Builder, - public EndpointBase, - public std::enable_shared_from_this + struct Endpoint : public path::Builder, public EndpointBase + // public std::enable_shared_from_this { Endpoint(Router* r, Context* parent); ~Endpoint() override; @@ -446,7 +445,7 @@ namespace llarp /// Returns a pointer to the quic::Tunnel object handling quic connections for this endpoint. /// Returns nullptr if quic is not supported. - quic::TunnelManager* + link::TunnelManager* GetQUICTunnel() override; protected: @@ -500,7 +499,7 @@ namespace llarp std::unique_ptr _state; std::shared_ptr _auth_policy; std::unordered_map _remote_auth_infos; - std::unique_ptr _tunnel_manager; + std::unique_ptr _tunnel_manager; /// (ons name, optional exit range, optional auth info) for looking up on startup std::unordered_map, std::optional>> diff --git a/llarp/service/endpoint_state.cpp b/llarp/service/endpoint_state.cpp index 0e5eb3b7cc..7713a2df4b 100644 --- a/llarp/service/endpoint_state.cpp +++ b/llarp/service/endpoint_state.cpp @@ -5,68 +5,61 @@ #include "outbound_context.hpp" #include -namespace llarp +namespace llarp::service { - namespace service + bool + EndpointState::Configure(const NetworkConfig& conf) { - bool - EndpointState::Configure(const NetworkConfig& conf) - { - if (conf.m_keyfile.has_value()) - key_file = conf.m_keyfile->string(); - snode_blacklist = conf.m_snodeBlacklist; - is_exit_enabled = conf.m_AllowExit; - - for (const auto& record : conf.m_SRVRecords) - { - local_introset.SRVs.push_back(record.toTuple()); - } + if (conf.m_keyfile.has_value()) + key_file = conf.m_keyfile->string(); + snode_blacklist = conf.m_snodeBlacklist; + is_exit_enabled = conf.m_AllowExit; - return true; + for (const auto& record : conf.m_SRVRecords) + { + local_introset.SRVs.push_back(record.toTuple()); } - util::StatusObject - EndpointState::ExtractStatus(util::StatusObject& obj) const - { - obj["lastPublished"] = to_json(last_publish); - obj["lastPublishAttempt"] = to_json(last_publish_attempt); - obj["introset"] = local_introset.ExtractStatus(); - static auto getSecond = [](const auto& item) -> auto - { - return item.second->ExtractStatus(); - }; + return true; + } - std::transform( - dead_sessions.begin(), - dead_sessions.end(), - std::back_inserter(obj["deadSessions"]), - getSecond); - std::transform( - remote_sessions.begin(), - remote_sessions.end(), - std::back_inserter(obj["remoteSessions"]), - getSecond); - std::transform( - pending_lookups.begin(), - pending_lookups.end(), - std::back_inserter(obj["lookups"]), - getSecond); - std::transform( - snode_sessions.begin(), - snode_sessions.end(), - std::back_inserter(obj["snodeSessions"]), - [](const auto& item) { return item.second->ExtractStatus(); }); + util::StatusObject + EndpointState::ExtractStatus(util::StatusObject& obj) const + { + obj["lastPublished"] = to_json(last_publish); + obj["lastPublishAttempt"] = to_json(last_publish_attempt); + obj["introset"] = local_introset.ExtractStatus(); + // static auto getSecond = [](const auto& item) -> auto + // { + // return item.second.ExtractStatus(); + // }; - util::StatusObject sessionObj{}; + // std::transform( + // dead_sessions.begin(), + // dead_sessions.end(), + // std::back_inserter(obj["deadSessions"]), + // getSecond); + // std::transform( + // remote_sessions.begin(), + // remote_sessions.end(), + // std::back_inserter(obj["remoteSessions"]), + // getSecond); + // std::transform( + // snode_sessions.begin(), + // snode_sessions.end(), + // std::back_inserter(obj["snodeSessions"]), + // [](const auto& item) { return item.second->ExtractStatus(); }); - for (const auto& item : m_Sessions) - { - std::string k = item.first.ToHex(); - sessionObj[k] = item.second.ExtractStatus(); - } + util::StatusObject sessionObj{}; - obj["converstations"] = sessionObj; - return obj; - } - } // namespace service -} // namespace llarp + // TODO: + // for (const auto& item : m_Sessions) + // { + // std::string k = item.first.ToHex(); + // sessionObj[k] = item.second.ExtractStatus(); + // } + + obj["converstations"] = sessionObj; + return obj; + } +} // namespace llarp::service diff --git a/llarp/service/endpoint_util.cpp b/llarp/service/endpoint_util.cpp index 22a2929390..94e64c911b 100644 --- a/llarp/service/endpoint_util.cpp +++ b/llarp/service/endpoint_util.cpp @@ -1,197 +1,172 @@ #include "endpoint_util.hpp" -#include #include "outbound_context.hpp" -#include "lookup.hpp" + +#include #include -namespace llarp +namespace llarp::service { - namespace service + void + EndpointUtil::ExpireSNodeSessions(llarp_time_t now, SNodeConnectionMap& sessions) { - void - EndpointUtil::ExpireSNodeSessions(llarp_time_t now, SNodeConnectionMap& sessions) + auto itr = sessions.begin(); + while (itr != sessions.end()) { - auto itr = sessions.begin(); - while (itr != sessions.end()) + if (itr->second->ShouldRemove() && itr->second->IsStopped()) { - if (itr->second->ShouldRemove() && itr->second->IsStopped()) - { - itr = sessions.erase(itr); - continue; - } - // expunge next tick - if (itr->second->IsExpired(now)) - { - itr->second->Stop(); - } - else - { - itr->second->Tick(now); - } - - ++itr; + itr = sessions.erase(itr); + continue; } - } - - void - EndpointUtil::ExpirePendingTx(llarp_time_t now, PendingLookupsMap& lookups) - { - std::vector> timedout; - for (auto itr = lookups.begin(); itr != lookups.end();) + // expunge next tick + if (itr->second->IsExpired(now)) { - if (!itr->second->IsTimedOut(now)) - { - ++itr; - continue; - } - timedout.emplace_back(std::move(itr->second)); - itr = lookups.erase(itr); + itr->second->Stop(); } - - for (const auto& lookup : timedout) + else { - LogWarn(lookup->name, " timed out txid=", lookup->txid); - lookup->HandleTimeout(); + itr->second->Tick(now); } + + ++itr; } + } - void - EndpointUtil::ExpirePendingRouterLookups(llarp_time_t now, PendingRoutersMap& routers) + void + EndpointUtil::ExpirePendingRouterLookups(llarp_time_t now, PendingRoutersMap& routers) + { + for (auto itr = routers.begin(); itr != routers.end();) { - for (auto itr = routers.begin(); itr != routers.end();) + if (!itr->second.IsExpired(now)) { - if (!itr->second.IsExpired(now)) - { - ++itr; - continue; - } - LogWarn("lookup for ", itr->first, " timed out"); - itr->second.InformResult({}); - itr = routers.erase(itr); + ++itr; + continue; } + LogWarn("lookup for ", itr->first, " timed out"); + itr->second.InformResult({}); + itr = routers.erase(itr); } + } - void - EndpointUtil::DeregisterDeadSessions(llarp_time_t now, ConnectionMap& sessions) + void + EndpointUtil::DeregisterDeadSessions(llarp_time_t now, ConnectionMap& sessions) + { + auto itr = sessions.begin(); + while (itr != sessions.end()) { - auto itr = sessions.begin(); - while (itr != sessions.end()) + if (itr->second->IsDone(now)) { - if (itr->second->IsDone(now)) - { - itr = sessions.erase(itr); - } - else - { - ++itr; - } + itr = sessions.erase(itr); + } + else + { + ++itr; } } + } - void - EndpointUtil::TickRemoteSessions( - llarp_time_t now, - ConnectionMap& remoteSessions, - ConnectionMap& deadSessions, - std::unordered_map& sessions) + void + EndpointUtil::TickRemoteSessions( + llarp_time_t now, + ConnectionMap& remoteSessions, + ConnectionMap& deadSessions, + std::unordered_map& sessions) + { + auto itr = remoteSessions.begin(); + while (itr != remoteSessions.end()) { - auto itr = remoteSessions.begin(); - while (itr != remoteSessions.end()) + itr->second->Tick(now); + if (itr->second->Pump(now)) { - itr->second->Tick(now); - if (itr->second->Pump(now)) - { - LogInfo( - "marking session as dead T=", - itr->second->currentConvoTag, - " to ", - itr->second->Addr()); - itr->second->Stop(); - sessions.erase(itr->second->currentConvoTag); - deadSessions.emplace(std::move(*itr)); - itr = remoteSessions.erase(itr); - } - else - { - ++itr; - } + LogInfo( + "marking session as dead T=", + itr->second->get_current_tag(), + " to ", + itr->second->Addr()); + itr->second->Stop(); + sessions.erase(itr->second->get_current_tag()); + deadSessions.emplace(std::move(*itr)); + itr = remoteSessions.erase(itr); } - for (auto& item : deadSessions) + else { - item.second->Tick(now); + ++itr; } } + for (auto& item : deadSessions) + { + item.second->Tick(now); + } + } - void - EndpointUtil::ExpireConvoSessions( - llarp_time_t now, std::unordered_map& sessions) + void + EndpointUtil::ExpireConvoSessions( + llarp_time_t now, std::unordered_map& sessions) + { + auto itr = sessions.begin(); + while (itr != sessions.end()) { - auto itr = sessions.begin(); - while (itr != sessions.end()) + if (itr->second.IsExpired(now)) { - if (itr->second.IsExpired(now)) - { - LogInfo("Expire session T=", itr->first, " to ", itr->second.Addr()); - itr = sessions.erase(itr); - } - else - ++itr; + LogInfo("Expire session T=", itr->first, " to ", itr->second.Addr()); + itr = sessions.erase(itr); } + else + ++itr; } + } - void - EndpointUtil::StopRemoteSessions(ConnectionMap& remoteSessions) + void + EndpointUtil::StopRemoteSessions(ConnectionMap& remoteSessions) + { + for (auto& item : remoteSessions) { - for (auto& item : remoteSessions) - { - item.second->Stop(); - } + item.second->Stop(); } + } - void - EndpointUtil::StopSnodeSessions(SNodeConnectionMap& sessions) + void + EndpointUtil::StopSnodeSessions(SNodeConnectionMap& sessions) + { + for (auto& item : sessions) { - for (auto& item : sessions) - { - item.second->Stop(); - } + item.second->Stop(); } + } - bool - EndpointUtil::HasPathToService(const Address& addr, const ConnectionMap& remoteSessions) + bool + EndpointUtil::HasPathToService(const Address& addr, const ConnectionMap& remoteSessions) + { + auto range = remoteSessions.equal_range(addr); + auto itr = range.first; + while (itr != range.second) { - auto range = remoteSessions.equal_range(addr); - auto itr = range.first; - while (itr != range.second) - { - if (itr->second->ReadyToSend()) - return true; - ++itr; - } - return false; + if (itr->second->ReadyToSend()) + return true; + ++itr; } + return false; + } - bool - EndpointUtil::GetConvoTagsForService( - const std::unordered_map& sessions, - const Address& info, - std::set& tags) + bool + EndpointUtil::GetConvoTagsForService( + const std::unordered_map& sessions, + const Address& info, + std::set& tags) + { + bool inserted = false; + auto itr = sessions.begin(); + while (itr != sessions.end()) { - bool inserted = false; - auto itr = sessions.begin(); - while (itr != sessions.end()) + if (itr->second.remote.Addr() == info) { - if (itr->second.remote.Addr() == info) + if (tags.emplace(itr->first).second) { - if (tags.emplace(itr->first).second) - { - inserted = true; - } + inserted = true; } - ++itr; } - return inserted; + ++itr; } - } // namespace service -} // namespace llarp + return inserted; + } +} // namespace llarp::service diff --git a/llarp/service/endpoint_util.hpp b/llarp/service/endpoint_util.hpp index 5290a6ebc9..48aeee5863 100644 --- a/llarp/service/endpoint_util.hpp +++ b/llarp/service/endpoint_util.hpp @@ -9,9 +9,6 @@ namespace llarp::service static void ExpireSNodeSessions(llarp_time_t now, SNodeConnectionMap& sessions); - static void - ExpirePendingTx(llarp_time_t now, PendingLookupsMap& lookups); - static void ExpirePendingRouterLookups(llarp_time_t now, PendingRoutersMap& routers); diff --git a/llarp/service/intro_set.cpp b/llarp/service/intro_set.cpp index ad18727c02..e4410fc41e 100644 --- a/llarp/service/intro_set.cpp +++ b/llarp/service/intro_set.cpp @@ -334,7 +334,7 @@ namespace llarp::service auto sublist = btdc.consume_list_consumer(); while (not sublist.is_finished()) { - supported_protocols.emplace_back(sublist.consume_integer()); + supported_protocols.emplace_back(ProtocolType{sublist.consume_integer()}); } } diff --git a/llarp/service/outbound_context.cpp b/llarp/service/outbound_context.cpp index 0ff11d1408..5581f663ef 100644 --- a/llarp/service/outbound_context.cpp +++ b/llarp/service/outbound_context.cpp @@ -84,47 +84,6 @@ namespace llarp::service return addr; } - bool - OutboundContext::OnIntroSetUpdate( - const Address&, - std::optional foundIntro, - const RouterID& endpoint, - std::chrono::milliseconds, - uint64_t relayOrder) - { - if (marked_bad) - return true; - updatingIntroSet = false; - if (foundIntro) - { - if (foundIntro->time_signed == 0s) - { - LogWarn(Name(), " got introset with zero timestamp: ", *foundIntro); - return true; - } - if (current_intro.time_signed > foundIntro->time_signed) - { - LogInfo("introset is old, dropping"); - return true; - } - - const std::chrono::milliseconds now = Now(); - if (foundIntro->IsExpired(now)) - { - LogError("got expired introset from lookup from ", endpoint); - return true; - } - current_intro = *foundIntro; - ShiftIntroRouter(RouterID{}); - } - else if (relayOrder > 0) - { - ++lookup_fails; - LogWarn(Name(), " failed to look up introset, fails=", lookup_fails); - } - return true; - } - bool OutboundContext::ReadyToSend() const { @@ -215,28 +174,58 @@ namespace llarp::service log::info(link_cat, "{} updating introset", Name()); last_introset_update = now; - // we want to use the parent endpoint's paths because outbound context - // does not implement path::PathSet::HandleGotIntroMessage const auto paths = GetManyPathsWithUniqueEndpoints(&ep, 2, location); - [[maybe_unused]] uint64_t relayOrder = 0; + uint64_t relayOrder = 0; - for ([[maybe_unused]] const auto& path : paths) + for (const auto& path : paths) { - // TODO: implement this - - // HiddenServiceAddressLookup* job = new HiddenServiceAddressLookup( - // m_Endpoint, - // util::memFn(&OutboundContext::OnIntroSetUpdate, shared_from_this()), - // location, - // PubKey{addr.as_array()}, - // path->Endpoint(), - // relayOrder, - // m_Endpoint->GenTXID(), - // (IntrosetUpdateInterval / 2) + (2 * path->intro.latency) + - // IntrosetLookupGraceInterval); - // relayOrder++; - // if (job->SendRequestViaPath(path, m_Endpoint->router())) - // updatingIntroSet = true; + path->find_intro(location, false, relayOrder, [this](oxen::quic::message m) mutable { + if (marked_bad) + { + log::info(link_cat, "Outbound context has been marked bad (whatever that means)"); + return; + } + + updatingIntroSet = false; + + if (m) + { + std::string introset; + + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + introset = btdc.require("INTROSET"); + } + catch (...) + { + log::warning(link_cat, "Failed to parse find name response!"); + throw; + } + + service::EncryptedIntroSet enc{introset}; + const auto intro = enc.decrypt(PubKey{addr.as_array()}); + + if (intro.time_signed == 0s) + { + log::warning(link_cat, "{} recieved introset with zero timestamp"); + return; + } + if (current_intro.time_signed > intro.time_signed) + { + log::info(link_cat, "{} received outdated introset; dropping", Name()); + return; + } + if (intro.IsExpired(llarp::time_now_ms())) + { + log::warning(link_cat, "{} received expired introset", Name()); + return; + } + + current_intro = intro; + ShiftIntroRouter(); + } + }); } } @@ -544,7 +533,7 @@ namespace llarp::service ep.GetIdentity(), current_intro.sntru_pubkey, remote_intro, - ep, + &ep, current_tag); if (const auto maybe = ep.MaybeGetAuthInfoForEndpoint(remote_identity.Addr()); not maybe) diff --git a/llarp/service/outbound_context.hpp b/llarp/service/outbound_context.hpp index cffcff092b..4d89e0646e 100644 --- a/llarp/service/outbound_context.hpp +++ b/llarp/service/outbound_context.hpp @@ -58,6 +58,12 @@ namespace llarp::service ~OutboundContext() override; + ConvoTag + get_current_tag() const + { + return current_tag; + } + void gen_intro_async(std::string payload); @@ -111,7 +117,7 @@ namespace llarp::service /// shift the intro off the current router it is using void - ShiftIntroRouter(const RouterID remote); + ShiftIntroRouter(const RouterID remote = RouterID{}); /// return true if we are ready to send bool @@ -166,14 +172,6 @@ namespace llarp::service std::chrono::milliseconds RTT() const; - bool - OnIntroSetUpdate( - const Address& addr, - std::optional i, - const RouterID& endpoint, - std::chrono::milliseconds, - uint64_t relayOrder); - private: /// swap remoteIntro with next intro void diff --git a/llarp/service/protocol.cpp b/llarp/service/protocol.cpp index f1f32b4f53..02b0153a92 100644 --- a/llarp/service/protocol.cpp +++ b/llarp/service/protocol.cpp @@ -275,7 +275,7 @@ namespace llarp::service if (bte.empty()) { log::error(logcat, "Failed to decode inner protocol message"); - DumpBuffer(*buf); + // DumpBuffer(*buf); self->msg.reset(); return; } @@ -304,8 +304,12 @@ namespace llarp::service // PKE (A, B, N) SharedSecret shared_secret; - path_dh_func dh_server = [crypto = CryptoManager::instance()](auto&& params...) -> bool { - return crypto->dh_server(std::forward(params)); + path_dh_func dh_server = [crypto = CryptoManager::instance()]( + llarp::SharedSecret& shared, + const PubKey& pk, + const SecretKey& sk, + const TunnelNonce& n) -> bool { + return crypto->dh_server(shared, pk, sk, n); }; if (!self->m_LocalIdentity.KeyExchange( diff --git a/llarp/service/sendcontext.cpp b/llarp/service/sendcontext.cpp deleted file mode 100644 index ff514c7d2e..0000000000 --- a/llarp/service/sendcontext.cpp +++ /dev/null @@ -1,168 +0,0 @@ -#include "sendcontext.hpp" - -#include -#include -#include -#include "endpoint.hpp" -#include -#include -#include - -namespace llarp::service -{ - static constexpr size_t SendContextQueueSize = 512; - - SendContext::SendContext( - ServiceInfo ident, const Introduction& intro, path::PathSet* send, Endpoint* ep) - : remoteIdent(std::move(ident)) - , remoteIntro(intro) - , m_PathSet(send) - , service_endpoint(ep) - , createdAt(ep->Now()) - {} - - bool - SendContext::Send(std::shared_ptr msg, path::Path_ptr path) - { - if (path->IsReady() - and m_SendQueue.tryPushBack(std::make_pair( - std::make_shared(*msg, remoteIntro.path_id), path)) - == thread::QueueReturn::Success) - { - service_endpoint->router()->TriggerPump(); - return true; - } - return false; - } - - void - SendContext::FlushUpstream() - { - auto r = service_endpoint->router(); - std::unordered_set flushpaths; - auto rttRMS = 0ms; - while (auto maybe = m_SendQueue.tryPopFront()) - { - auto& [msg, path] = *maybe; - msg->sequence_number = path->NextSeqNo(); - if (path->SendRoutingMessage(*msg, r)) - { - lastGoodSend = r->now(); - flushpaths.emplace(path); - service_endpoint->ConvoTagTX(msg->protocol_frame_msg.convo_tag); - const auto rtt = (path->intro.latency + remoteIntro.latency) * 2; - rttRMS += rtt * rtt.count(); - } - } - // flush the select path's upstream - for (const auto& path : flushpaths) - { - path->FlushUpstream(r); - } - if (flushpaths.empty()) - return; - estimatedRTT = std::chrono::milliseconds{ - static_cast(std::sqrt(rttRMS.count() / flushpaths.size()))}; - } - - /// send on an established convo tag - void - SendContext::EncryptAndSendTo(const llarp_buffer_t& payload, ProtocolType t) - { - SharedSecret shared; - auto f = std::make_shared(); - f->flag = 0; - f->nonce.Randomize(); - f->convo_tag = currentConvoTag; - f->sequence_number = ++sequenceNo; - - auto path = m_PathSet->GetPathByRouter(remoteIntro.router); - if (!path) - { - ShiftIntroRouter(remoteIntro.router); - LogWarn(m_PathSet->Name(), " cannot encrypt and send: no path for intro ", remoteIntro); - return; - } - - if (!service_endpoint->GetCachedSessionKeyFor(f->convo_tag, shared)) - { - LogWarn( - m_PathSet->Name(), - " could not send, has no cached session key on session T=", - f->convo_tag); - return; - } - - auto m = std::make_shared(); - service_endpoint->PutIntroFor(f->convo_tag, remoteIntro); - service_endpoint->PutReplyIntroFor(f->convo_tag, path->intro); - m->proto = t; - if (auto maybe = service_endpoint->GetSeqNoForConvo(f->convo_tag)) - { - m->seqno = *maybe; - } - else - { - LogWarn(m_PathSet->Name(), " could not get sequence number for session T=", f->convo_tag); - return; - } - m->introReply = path->intro; - f->path_id = m->introReply.path_id; - m->sender = service_endpoint->GetIdentity().pub; - m->tag = f->convo_tag; - m->put_buffer(payload); - service_endpoint->router()->queue_work([f, m, shared, path, this] { - if (not f->EncryptAndSign(*m, shared, service_endpoint->GetIdentity())) - { - LogError(m_PathSet->Name(), " failed to sign message"); - return; - } - Send(f, path); - }); - } - - void - SendContext::AsyncSendAuth(std::function resultHandler) - { - if (const auto maybe = service_endpoint->MaybeGetAuthInfoForEndpoint(remoteIdent.Addr())) - { - // send auth message - const llarp_buffer_t authdata{maybe->token}; - AsyncGenIntro(authdata, ProtocolType::Auth); - authResultListener = resultHandler; - } - else - resultHandler({AuthResultCode::eAuthAccepted, "no auth needed"}); - } - - void - SendContext::AsyncEncryptAndSendTo(const llarp_buffer_t& data, ProtocolType protocol) - { - if (IntroSent()) - { - EncryptAndSendTo(data, protocol); - return; - } - // have we generated the initial intro but not sent it yet? bail here so we don't cause - // bullshittery - if (IntroGenerated() and not IntroSent()) - { - LogWarn( - m_PathSet->Name(), - " we have generated an intial handshake but have not sent it yet so we drop a packet " - "to prevent bullshittery"); - return; - } - const auto maybe = service_endpoint->MaybeGetAuthInfoForEndpoint(remoteIdent.Addr()); - if (maybe.has_value()) - { - // send auth message - const llarp_buffer_t authdata(maybe->token); - AsyncGenIntro(authdata, ProtocolType::Auth); - } - else - { - AsyncGenIntro(data, protocol); - } - } -} // namespace llarp::service diff --git a/llarp/service/sendcontext.hpp b/llarp/service/sendcontext.hpp deleted file mode 100644 index 2daf23247e..0000000000 --- a/llarp/service/sendcontext.hpp +++ /dev/null @@ -1,85 +0,0 @@ -#pragma once -#include "intro.hpp" -#include "protocol.hpp" - -#include -#include -#include -#include -#include -#include - -#include - -namespace llarp::service -{ - struct ServiceInfo; - struct Endpoint; - struct Introduction; - - struct SendContext - { - SendContext(ServiceInfo ident, const Introduction& intro, path::PathSet* send, Endpoint* ep); - - void - AsyncEncryptAndSendTo(const llarp_buffer_t& payload, ProtocolType t); - - /// queue send a fully encrypted hidden service frame - /// via a path - bool - Send(std::shared_ptr f, path::Path_ptr path); - - /// flush upstream traffic when in router thread - void - FlushUpstream(); - - SharedSecret sharedKey; - ServiceInfo remoteIdent; - Introduction remoteIntro; - ConvoTag currentConvoTag; - path::PathSet* const m_PathSet; - // Endpoint* const m_DataHandler; - Endpoint* const service_endpoint; - uint64_t sequenceNo = 0; - llarp_time_t lastGoodSend = 0s; - const llarp_time_t createdAt; - llarp_time_t sendTimeout = path::BUILD_TIMEOUT; - llarp_time_t connectTimeout = path::BUILD_TIMEOUT * 2; - llarp_time_t shiftTimeout = (path::BUILD_TIMEOUT * 5) / 2; - llarp_time_t estimatedRTT = 0s; - bool markedBad = false; - - std::function authResultListener; - - virtual bool - ShiftIntroduction(bool rebuild = true) - { - (void)rebuild; - return true; - } - - virtual void - ShiftIntroRouter(const RouterID) = 0; - - virtual void - UpdateIntroSet() = 0; - - virtual void - MarkCurrentIntroBad(llarp_time_t now) = 0; - - void - AsyncSendAuth(std::function replyHandler); - - private: - virtual bool - IntroGenerated() const = 0; - virtual bool - IntroSent() const = 0; - - void - EncryptAndSendTo(const llarp_buffer_t& payload, ProtocolType t); - - virtual void - AsyncGenIntro(const llarp_buffer_t& payload, ProtocolType t) = 0; - }; -} // namespace llarp::service diff --git a/llarp/tooling/dht_event.hpp b/llarp/tooling/dht_event.hpp deleted file mode 100644 index f0f0e7850f..0000000000 --- a/llarp/tooling/dht_event.hpp +++ /dev/null @@ -1,130 +0,0 @@ -#pragma once - -#include "router_event.hpp" -#include -#include -#include - -namespace tooling -{ - struct PubIntroSentEvent : public RouterEvent - { - llarp::dht::Key_t introsetPubkey; - llarp::RouterID relay; - uint64_t relayIndex; - - PubIntroSentEvent( - const llarp::RouterID& ourRouter, - const llarp::dht::Key_t& introsetPubkey_, - const llarp::RouterID& relay_, - uint64_t relayIndex_) - : RouterEvent("DHT: PubIntroSentEvent", ourRouter, false) - , introsetPubkey(introsetPubkey_) - , relay(relay_) - , relayIndex(relayIndex_) - {} - - std::string - ToString() const - { - return RouterEvent::ToString() + " ---- introset pubkey: " + introsetPubkey.ShortHex() - + ", relay: " + relay.ShortString() + ", relayIndex: " + std::to_string(relayIndex); - } - }; - - struct PubIntroReceivedEvent : public RouterEvent - { - llarp::dht::Key_t from; - llarp::dht::Key_t location; - uint64_t txid; - uint64_t relayOrder; - - PubIntroReceivedEvent( - const llarp::RouterID& ourRouter, - const llarp::dht::Key_t& from_, - const llarp::dht::Key_t& location_, - uint64_t txid_, - uint64_t relayOrder_) - : RouterEvent("DHT: PubIntroReceivedEvent", ourRouter, true) - , from(from_) - , location(location_) - , txid(txid_) - , relayOrder(relayOrder_) - {} - - std::string - ToString() const override - { - return RouterEvent::ToString() + "from " + from.ShortHex() - + " location=" + location.ShortHex() + " order=" + std::to_string(relayOrder) - + " txid=" + std::to_string(txid); - } - }; - - struct GotIntroReceivedEvent : public RouterEvent - { - llarp::dht::Key_t From; - llarp::service::EncryptedIntroSet Introset; - uint64_t RelayOrder; - uint64_t TxID; - - GotIntroReceivedEvent( - const llarp::RouterID& ourRouter_, - const llarp::dht::Key_t& from_, - const llarp::service::EncryptedIntroSet& introset_, - uint64_t txid_) - : RouterEvent("DHT:: GotIntroReceivedEvent", ourRouter_, true) - , From(from_) - , Introset(introset_) - , TxID(txid_) - {} - - std::string - ToString() const override - { - return RouterEvent::ToString() + "from " + From.ShortHex() - + " location=" + Introset.derivedSigningKey.ShortHex() - + " order=" + std::to_string(RelayOrder) + " txid=" + std::to_string(TxID); - } - }; - - struct FindRouterEvent : public RouterEvent - { - llarp::dht::Key_t from; - llarp::RouterID targetKey; - bool iterative; - bool exploritory; - uint64_t txid; - uint64_t version; - - FindRouterEvent(const llarp::RouterID& ourRouter, const llarp::dht::FindRouterMessage& msg) - : RouterEvent("DHT: FindRouterEvent", ourRouter, true) - , from(msg.From) - , targetKey(msg.targetKey) - , iterative(msg.iterative) - , exploritory(msg.exploratory) - , txid(msg.txid) - , version(msg.version) - {} - - std::string - ToString() const override - { - return RouterEvent::ToString() + " from " + from.ShortHex() - + ", targetKey: " + targetKey.ToString() + ", iterative: " + std::to_string(iterative) - + ", exploritory " + std::to_string(exploritory) + ", txid " + std::to_string(txid) - + ", version " + std::to_string(version); - } - }; - - struct FindRouterReceivedEvent : public FindRouterEvent - { - using FindRouterEvent::FindRouterEvent; - }; - - struct FindRouterSentEvent : public FindRouterEvent - { - using FindRouterEvent::FindRouterEvent; - }; - -} // namespace tooling diff --git a/llarp/tooling/hive_context.cpp b/llarp/tooling/hive_context.cpp deleted file mode 100644 index 130fe28e0f..0000000000 --- a/llarp/tooling/hive_context.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "hive_context.hpp" - -#include "hive_router.hpp" - -namespace tooling -{ - HiveContext::HiveContext(RouterHive* hive) : m_hive(hive) - {} - - std::shared_ptr - HiveContext::makeRouter(const llarp::EventLoop_ptr& loop) - { - return std::make_shared(loop, makeVPNPlatform(), m_hive); - } - - HiveRouter* - HiveContext::getRouterAsHiveRouter() - { - if (not router) - return nullptr; - - HiveRouter* hiveRouter = dynamic_cast(router.get()); - - if (hiveRouter == nullptr) - throw std::runtime_error("HiveContext has a router not of type HiveRouter"); - - return hiveRouter; - } - -} // namespace tooling diff --git a/llarp/tooling/hive_context.hpp b/llarp/tooling/hive_context.hpp deleted file mode 100644 index c9fd3a80a4..0000000000 --- a/llarp/tooling/hive_context.hpp +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include -#include "hive_router.hpp" - -namespace tooling -{ - /// HiveContext is a subclass of llarp::Context which allows RouterHive to - /// perform custom behavior which might be undesirable in production code. - struct HiveContext : public llarp::Context - { - HiveContext(RouterHive* hive); - - std::shared_ptr - makeRouter(const llarp::EventLoop_ptr& loop) override; - - /// Get this context's router as a HiveRouter. - /// - /// Returns nullptr if there is no router or throws an exception if the - /// router is somehow not an instance of HiveRouter. - HiveRouter* - getRouterAsHiveRouter(); - - protected: - RouterHive* m_hive = nullptr; - }; - -} // namespace tooling diff --git a/llarp/tooling/hive_router.cpp b/llarp/tooling/hive_router.cpp deleted file mode 100644 index d1697560e4..0000000000 --- a/llarp/tooling/hive_router.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "hive_router.hpp" - -#include "router_hive.hpp" - -namespace tooling -{ - HiveRouter::HiveRouter( - llarp::EventLoop_ptr loop, std::shared_ptr plat, RouterHive* hive) - : Router(loop, plat), m_hive(hive) - {} - - bool - HiveRouter::disableGossipingRC_TestingOnly() - { - return m_disableGossiping; - } - - void - HiveRouter::disableGossiping() - { - m_disableGossiping = true; - } - - void - HiveRouter::enableGossiping() - { - m_disableGossiping = false; - } - - void - HiveRouter::HandleRouterEvent(RouterEventPtr event) const - { - m_hive->NotifyEvent(std::move(event)); - } - -} // namespace tooling diff --git a/llarp/tooling/hive_router.hpp b/llarp/tooling/hive_router.hpp deleted file mode 100644 index 521239eb1b..0000000000 --- a/llarp/tooling/hive_router.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include - -namespace tooling -{ - /// HiveRouter is a subclass of Router which overrides specific behavior in - /// order to perform testing-related functions. It exists largely to prevent - /// this behavior (which may often be "dangerous") from leaking into release - /// code. - struct HiveRouter : public llarp::Router - { - explicit HiveRouter( - llarp::EventLoop_ptr loop, - std::shared_ptr vpnPlatform, - RouterHive* hive); - - virtual ~HiveRouter() = default; - - /// Override logic to prevent base Router class from gossiping its RC. - virtual bool - disableGossipingRC_TestingOnly() override; - - void - disableGossiping(); - - void - enableGossiping(); - - protected: - bool m_disableGossiping = false; - RouterHive* m_hive = nullptr; - - virtual void - HandleRouterEvent(RouterEventPtr event) const override; - }; - -} // namespace tooling diff --git a/llarp/tooling/path_event.hpp b/llarp/tooling/path_event.hpp deleted file mode 100644 index a1fd0adf7e..0000000000 --- a/llarp/tooling/path_event.hpp +++ /dev/null @@ -1,132 +0,0 @@ -#include "router_event.hpp" - -#include -#include -#include - -namespace tooling -{ - struct PathAttemptEvent : public RouterEvent - { - std::vector hops; - llarp::PathID_t pathid; - - PathAttemptEvent(const llarp::RouterID& routerID, std::shared_ptr path) - : RouterEvent("PathAttemptEvent", routerID, false) - , hops(path->hops) - , pathid(path->hops[0].rxID) - {} - - std::string - ToString() const - { - std::string result = RouterEvent::ToString(); - result += "---- ["; - - size_t i = 0; - for (const auto& hop : hops) - { - i++; - - result += llarp::RouterID(hop.rc.pubkey).ShortString(); - result += "]"; - - if (i != hops.size()) - { - result += " -> ["; - } - } - - return result; - } - }; - - struct PathRequestReceivedEvent : public RouterEvent - { - llarp::RouterID prevHop; - llarp::RouterID nextHop; - llarp::PathID_t txid; - llarp::PathID_t rxid; - bool isEndpoint = false; - - PathRequestReceivedEvent( - const llarp::RouterID& routerID, std::shared_ptr hop) - : RouterEvent("PathRequestReceivedEvent", routerID, true) - , prevHop(hop->info.downstream) - , nextHop(hop->info.upstream) - , txid(hop->info.txID) - , rxid(hop->info.rxID) - , isEndpoint(routerID == nextHop ? true : false) - {} - - std::string - ToString() const - { - std::string result = RouterEvent::ToString(); - result += "---- ["; - result += prevHop.ShortString(); - result += "] -> [*"; - result += routerID.ShortString(); - result += "] -> ["; - - if (isEndpoint) - { - result += "nowhere]"; - } - else - { - result += nextHop.ShortString(); - result += "]"; - } - - return result; - } - }; - - struct PathStatusReceivedEvent : public RouterEvent - { - llarp::PathID_t rxid; - uint64_t status; - - PathStatusReceivedEvent( - const llarp::RouterID& routerID, const llarp::PathID_t rxid_, uint64_t status_) - : RouterEvent("PathStatusReceivedEvent", routerID, true), rxid(rxid_), status(status_) - {} - - std::string - ToString() const - { - std::string result = RouterEvent::ToString(); - result += "---- path rxid: " + rxid.ShortHex(); - result += ", status: " + std::to_string(status); - - return result; - } - }; - - struct PathBuildRejectedEvent : public RouterEvent - { - llarp::PathID_t rxid; - llarp::RouterID rejectedBy; - - PathBuildRejectedEvent( - const llarp::RouterID& routerID, - const llarp::PathID_t rxid_, - const llarp::RouterID& rejectedBy_) - : RouterEvent("PathBuildRejectedEvent", routerID, false) - , rxid(rxid_) - , rejectedBy(rejectedBy_) - {} - - std::string - ToString() const - { - std::string result = RouterEvent::ToString(); - result += "---- path rxid: " + rxid.ShortHex(); - result += ", rejectedBy: " + rejectedBy.ShortString(); - - return result; - } - }; - -} // namespace tooling diff --git a/llarp/tooling/peer_stats_event.hpp b/llarp/tooling/peer_stats_event.hpp deleted file mode 100644 index 13b063241a..0000000000 --- a/llarp/tooling/peer_stats_event.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "router_event.hpp" - -namespace tooling -{ - struct LinkSessionEstablishedEvent : public RouterEvent - { - llarp::RouterID remoteId; - bool inbound = false; - - LinkSessionEstablishedEvent( - const llarp::RouterID& ourRouterId, const llarp::RouterID& remoteId_, bool inbound_) - : RouterEvent("Link: LinkSessionEstablishedEvent", ourRouterId, false) - , remoteId(remoteId_) - , inbound(inbound_) - {} - - std::string - ToString() const - { - return RouterEvent::ToString() + (inbound ? "inbound" : "outbound") - + " : LinkSessionEstablished with " + remoteId.ToString(); - } - }; - - struct ConnectionAttemptEvent : public RouterEvent - { - llarp::RouterID remoteId; - - ConnectionAttemptEvent(const llarp::RouterID& ourRouterId, const llarp::RouterID& remoteId_) - : RouterEvent("Link: ConnectionAttemptEvent", ourRouterId, false), remoteId(remoteId_) - {} - - std::string - ToString() const - { - return RouterEvent::ToString() + " : LinkSessionEstablished with " + remoteId.ToString(); - } - }; - -} // namespace tooling diff --git a/llarp/tooling/rc_event.hpp b/llarp/tooling/rc_event.hpp deleted file mode 100644 index db23f5fe1b..0000000000 --- a/llarp/tooling/rc_event.hpp +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include "router_event.hpp" - -#include - -namespace tooling -{ - struct RCGossipReceivedEvent : public RouterEvent - { - RCGossipReceivedEvent(const llarp::RouterID& routerID, const llarp::RouterContact& rc_) - : RouterEvent("RCGossipReceivedEvent", routerID, true), rc(rc_) - {} - - std::string - ToString() const override - { - return RouterEvent::ToString() - + " ---- other RouterID: " + llarp::RouterID(rc.pubkey).ShortString(); - } - - std::string - LongString() const - { - return RouterEvent::ToString() + " ---- RC: " + rc.ToString(); - } - - llarp::RouterContact rc; - }; - - struct RCGossipSentEvent : public RouterEvent - { - RCGossipSentEvent(const llarp::RouterID& routerID, const llarp::RouterContact& rc_) - : RouterEvent("RCGossipSentEvent", routerID, true), rc(rc_) - {} - - std::string - ToString() const override - { - return RouterEvent::ToString() - + " ---- sending RC for RouterID: " + llarp::RouterID(rc.pubkey).ShortString(); - } - - std::string - LongString() const - { - return RouterEvent::ToString() + " ---- RC: " + rc.ToString(); - } - - llarp::RouterContact rc; - }; - -} // namespace tooling diff --git a/llarp/tooling/router_event.hpp b/llarp/tooling/router_event.hpp deleted file mode 100644 index 9c49537105..0000000000 --- a/llarp/tooling/router_event.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include - -#include -#include -#include - -namespace llarp -{ - struct PathID_t; - - namespace path - { - struct Path; - struct PathHopConfig; - - struct TransitHop; - - } // namespace path - -} // namespace llarp - -namespace tooling -{ - struct RouterHive; - - struct RouterEvent - { - RouterEvent(std::string eventType, llarp::RouterID routerID, bool triggered) - : eventType(eventType), routerID(routerID), triggered(triggered) - {} - - virtual ~RouterEvent() = default; - - virtual std::string - ToString() const - { - std::string result; - result += eventType; - result += " ["; - result += routerID.ShortString(); - result += "] -- "; - return result; - } - - const std::string eventType; - - llarp::RouterID routerID; - - bool triggered = false; - }; - - using RouterEventPtr = std::unique_ptr; - -} // namespace tooling diff --git a/llarp/tooling/router_hive.cpp b/llarp/tooling/router_hive.cpp deleted file mode 100644 index ea77071e28..0000000000 --- a/llarp/tooling/router_hive.cpp +++ /dev/null @@ -1,249 +0,0 @@ -#include "router_hive.hpp" - -#include -#include -#include - -#include -#include -#include - -using namespace std::chrono_literals; - -namespace tooling -{ - void - RouterHive::AddRouter(const std::shared_ptr& config, bool isSNode) - { - auto& container = (isSNode ? relays : clients); - - llarp::RuntimeOptions opts; - opts.isSNode = isSNode; - - Context_ptr context = std::make_shared(this); - context->Configure(config); - context->Setup(opts); - - auto routerId = llarp::RouterID(context->router->pubkey()); - container[routerId] = context; - fmt::print("Generated router with ID {}\n", routerId); - } - - void - RouterHive::AddRelay(const std::shared_ptr& config) - { - AddRouter(config, true); - } - - void - RouterHive::AddClient(const std::shared_ptr& config) - { - AddRouter(config, false); - } - - void - RouterHive::StartRouters(bool isRelay) - { - auto& container = (isRelay ? relays : clients); - - for (const auto& [routerId, ctx] : container) - { - routerMainThreads.emplace_back([ctx = ctx, isRelay = isRelay]() { - ctx->Run(llarp::RuntimeOptions{false, false, isRelay}); - }); - std::this_thread::sleep_for(2ms); - } - } - - void - RouterHive::StartRelays() - { - StartRouters(true); - } - - void - RouterHive::StartClients() - { - StartRouters(false); - } - - void - RouterHive::StopRouters() - { - llarp::LogInfo("Signalling all routers to stop"); - for (auto& [routerId, ctx] : relays) - { - ctx->loop->call([ctx = ctx]() { ctx->HandleSignal(SIGINT); }); - } - for (auto& [routerId, ctx] : clients) - { - ctx->loop->call([ctx = ctx]() { ctx->HandleSignal(SIGINT); }); - } - - llarp::LogInfo("Waiting on routers to be stopped"); - for (auto [routerId, ctx] : relays) - { - while (ctx->IsUp()) - { - std::this_thread::sleep_for(10ms); - } - } - for (auto [routerId, ctx] : clients) - { - while (ctx->IsUp()) - { - std::this_thread::sleep_for(10ms); - } - } - - llarp::LogInfo("Joining all router threads"); - for (auto& thread : routerMainThreads) - { - while (not thread.joinable()) - { - std::this_thread::sleep_for(500ms); - } - thread.join(); - } - - llarp::LogInfo("RouterHive::StopRouters finished"); - } - - void - RouterHive::NotifyEvent(RouterEventPtr event) - { - std::lock_guard guard{eventQueueMutex}; - - eventQueue.push_back(std::move(event)); - } - - RouterEventPtr - RouterHive::GetNextEvent() - { - std::lock_guard guard{eventQueueMutex}; - - if (not eventQueue.empty()) - { - auto ptr = std::move(eventQueue.front()); - eventQueue.pop_front(); - return ptr; - } - return nullptr; - } - - std::deque - RouterHive::GetAllEvents() - { - std::lock_guard guard{eventQueueMutex}; - - std::deque events; - if (not eventQueue.empty()) - { - eventQueue.swap(events); - } - return events; - } - - void - RouterHive::VisitRouter(Context_ptr ctx, std::function visit) - { - // TODO: this should be called from each router's appropriate Loop, e.g.: - // ctx->loop->call([visit, ctx]() { visit(ctx); }); - // however, this causes visit calls to be deferred - visit(ctx); - } - - HiveRouter* - RouterHive::GetRelay(const llarp::RouterID& id, bool needMutexLock) - { - auto guard = - needMutexLock ? std::make_optional>(routerMutex) : std::nullopt; - - auto itr = relays.find(id); - if (itr == relays.end()) - return nullptr; - - auto ctx = itr->second; - return ctx->getRouterAsHiveRouter(); - } - - std::vector - RouterHive::RelayConnectedRelays() - { - std::lock_guard guard{routerMutex}; - std::vector results; - results.resize(relays.size()); - std::mutex results_lock; - - size_t i = 0; - size_t done_count = 0; - for (auto& [routerId, ctx] : relays) - { - ctx->loop->call([&, i, ctx = ctx]() { - size_t count = ctx->router->NumberOfConnectedRouters(); - std::lock_guard guard{results_lock}; - results[i] = count; - done_count++; - }); - i++; - } - - while (true) - { - size_t read_done_count = 0; - { - std::lock_guard guard{results_lock}; - read_done_count = done_count; - } - if (read_done_count == relays.size()) - break; - - std::this_thread::sleep_for(100ms); - } - return results; - } - - // TODO: DRY -- this smells a lot like RelayConnectedRelays() - std::vector - RouterHive::GetRelayRCs() - { - std::lock_guard guard{routerMutex}; - std::vector results; - results.resize(relays.size()); - - size_t i = 0; - for (auto [routerId, ctx] : relays) - { - results[i] = ctx->router->rc(); - i++; - } - return results; - } - - void - RouterHive::ForEachRelay(std::function visit) - { - for (auto [routerId, ctx] : relays) - { - VisitRouter(ctx, visit); - } - } - - void - RouterHive::ForEachClient(std::function visit) - { - for (auto [routerId, ctx] : clients) - { - VisitRouter(ctx, visit); - } - } - - /// safely visit every router context - void - RouterHive::ForEachRouter(std::function visit) - { - ForEachRelay(visit); - ForEachClient(visit); - } - -} // namespace tooling diff --git a/llarp/tooling/router_hive.hpp b/llarp/tooling/router_hive.hpp deleted file mode 100644 index 760205ea6d..0000000000 --- a/llarp/tooling/router_hive.hpp +++ /dev/null @@ -1,95 +0,0 @@ -#pragma once - -#include "router_event.hpp" - -#include -#include -#include - -#include -#include -#include -#include - -struct llarp_config; -struct llarp_main; - -namespace llarp -{ - struct Context; -} // namespace llarp - -namespace tooling -{ - struct HiveRouter; // Hive's version of Router - - struct RouterHive - { - using Context_ptr = std::shared_ptr; - - private: - void - StartRouters(bool isRelay); - - void - AddRouter(const std::shared_ptr& config, bool isRelay); - - /// safely visit router (asynchronously) - void - VisitRouter(Context_ptr ctx, std::function visit); - - public: - RouterHive() = default; - - void - AddRelay(const std::shared_ptr& conf); - - void - AddClient(const std::shared_ptr& conf); - - void - StartRelays(); - - void - StartClients(); - - void - StopRouters(); - - void - NotifyEvent(RouterEventPtr event); - - RouterEventPtr - GetNextEvent(); - - std::deque - GetAllEvents(); - - // functions to safely visit each relay and/or client's HiveContext - void - ForEachRelay(std::function visit); - void - ForEachClient(std::function visit); - void - ForEachRouter(std::function visit); - - HiveRouter* - GetRelay(const llarp::RouterID& id, bool needMutexLock = true); - - std::vector - RelayConnectedRelays(); - - std::vector - GetRelayRCs(); - - std::mutex routerMutex; - std::unordered_map relays; - std::unordered_map clients; - - std::vector routerMainThreads; - - std::mutex eventQueueMutex; - std::deque eventQueue; - }; - -} // namespace tooling diff --git a/llarp/util/str.hpp b/llarp/util/str.hpp index 9169cefb73..2e510c734f 100644 --- a/llarp/util/str.hpp +++ b/llarp/util/str.hpp @@ -92,4 +92,7 @@ namespace llarp std::string lowercase_ascii_string(std::string src); + + std::string_view + TrimWhitespace(std::string_view str); } // namespace llarp From c0b19de963d0f4441fa2cd68efbf8fc151475f3f Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 19 Oct 2023 14:59:57 -0700 Subject: [PATCH 065/312] Review commit --- .gitignore | 1 + cmake/CMakeGraphVizOptions.cmake | 5 + crypto/libntrup/src/ntru.cpp | 2 + daemon/lokinet-bootstrap.cpp | 11 +- daemon/lokinet-vpn.cpp | 14 +- daemon/lokinet.cpp | 39 +- llarp/CMakeLists.txt | 497 +++++++-------- llarp/CMakeLists_old.txt | 421 +++++++++++++ llarp/bootstrap.cpp | 2 +- llarp/bootstrap.hpp | 3 +- llarp/bootstrap_fallbacks.cpp | 25 + llarp/config/config.cpp | 13 +- llarp/config/config.hpp | 11 +- llarp/config/definition.hpp | 5 +- llarp/config/ini.cpp | 3 - llarp/config/ini.hpp | 2 +- llarp/config/key_manager.hpp | 5 +- llarp/consensus/reachability_testing.cpp | 2 +- llarp/consensus/reachability_testing.hpp | 5 +- llarp/context.cpp | 10 +- llarp/crypto/crypto.cpp | 5 - llarp/crypto/crypto.hpp | 8 +- llarp/crypto/encrypted_frame.cpp | 4 +- llarp/crypto/encrypted_frame.hpp | 7 +- llarp/crypto/types.cpp | 8 +- llarp/crypto/types.hpp | 6 +- llarp/dns/dns.hpp | 43 +- llarp/dns/message.cpp | 702 +++++++++++----------- llarp/dns/name.cpp | 224 ++++--- llarp/dns/name.hpp | 28 +- llarp/dns/platform.hpp | 4 +- llarp/dns/query.hpp | 1 - llarp/dns/question.cpp | 205 ++++--- llarp/dns/question.hpp | 94 ++- llarp/dns/rr.cpp | 199 +++--- llarp/dns/rr.hpp | 79 ++- llarp/dns/serialize.cpp | 66 +- llarp/dns/serialize.hpp | 41 +- llarp/dns/server.cpp | 12 +- llarp/dns/server.hpp | 5 +- llarp/dns/srv_data.cpp | 10 +- llarp/dns/srv_data.hpp | 6 +- llarp/dns/string.hpp | 21 +- llarp/endpoint_base.hpp | 17 +- llarp/ev/ev.cpp | 6 +- llarp/ev/libuv.cpp | 8 +- llarp/ev/libuv.hpp | 7 +- llarp/exit/context.hpp | 4 +- llarp/exit/endpoint.hpp | 1 - llarp/exit/session.cpp | 1 - llarp/exit/session.hpp | 1 - llarp/handlers/exit.cpp | 11 +- llarp/handlers/exit.hpp | 5 +- llarp/handlers/tun.cpp | 10 +- llarp/handlers/tun.hpp | 1 - llarp/link/connection.hpp | 1 - llarp/link/link_manager.cpp | 5 - llarp/link/link_manager.hpp | 13 +- llarp/link/tunnel.hpp | 27 +- llarp/messages/link_intro.cpp | 162 ----- llarp/messages/relay.hpp | 4 +- llarp/net/exit_info.cpp | 8 +- llarp/net/exit_info.hpp | 4 +- llarp/net/interface_info.hpp | 3 +- llarp/net/ip.hpp | 2 + llarp/net/ip_address.cpp | 3 +- llarp/net/ip_address.hpp | 6 +- llarp/net/ip_packet.cpp | 7 +- llarp/net/ip_packet.hpp | 5 +- llarp/net/ip_range.hpp | 6 +- llarp/net/net_bits.hpp | 2 + llarp/net/net_if.hpp | 2 + llarp/net/net_int.hpp | 9 +- llarp/net/posix.cpp | 12 +- llarp/net/sock_addr.cpp | 11 +- llarp/net/sock_addr.hpp | 5 +- llarp/net/traffic_policy.hpp | 7 +- llarp/nodedb.cpp | 14 +- llarp/nodedb.hpp | 19 +- llarp/path/abstracthophandler.hpp | 1 - llarp/path/path.cpp | 9 - llarp/path/path.hpp | 10 +- llarp/path/path_context.hpp | 11 +- llarp/path/pathbuilder.cpp | 6 +- llarp/path/pathset.cpp | 4 - llarp/path/pathset.hpp | 4 +- llarp/path/transit_hop.cpp | 17 +- llarp/peerstats/orm.hpp | 133 ---- llarp/peerstats/peer_db.cpp | 380 ------------ llarp/peerstats/peer_db.hpp | 141 ----- llarp/peerstats/types.cpp | 146 ----- llarp/peerstats/types.hpp | 59 -- llarp/pow.cpp | 5 +- llarp/profiling.cpp | 2 +- llarp/profiling.hpp | 4 +- llarp/router/outbound_message_handler.cpp | 389 ------------ llarp/router/outbound_session_maker.cpp | 319 ---------- llarp/router/rc_gossiper.cpp | 3 +- llarp/router/rc_lookup_handler.cpp | 10 +- llarp/router/rc_lookup_handler.hpp | 1 - llarp/router/route_poker.cpp | 7 +- llarp/router/route_poker.hpp | 4 +- llarp/router/router.cpp | 30 - llarp/router/router.hpp | 18 +- llarp/router_contact.cpp | 7 +- llarp/router_contact.hpp | 14 +- llarp/router_version.cpp | 3 - llarp/router_version.hpp | 1 + llarp/rpc/endpoint_rpc.hpp | 1 - llarp/rpc/json_conversions.hpp | 1 + llarp/rpc/lokid_rpc_client.cpp | 77 +-- llarp/rpc/lokid_rpc_client.hpp | 5 - llarp/rpc/rpc_request_definitions.hpp | 12 +- llarp/rpc/rpc_request_parser.cpp | 6 +- llarp/rpc/rpc_request_parser.hpp | 5 +- llarp/rpc/rpc_server.cpp | 33 +- llarp/rpc/rpc_server.hpp | 12 +- llarp/service/async_key_exchange.hpp | 1 + llarp/service/auth.hpp | 3 +- llarp/service/context.cpp | 5 +- llarp/service/context.hpp | 4 +- llarp/service/convotag.cpp | 1 - llarp/service/convotag.hpp | 1 - llarp/service/endpoint.cpp | 27 +- llarp/service/endpoint.hpp | 9 +- llarp/service/endpoint_state.cpp | 5 - llarp/service/endpoint_state.hpp | 15 +- llarp/service/identity.cpp | 2 - llarp/service/identity.hpp | 6 +- llarp/service/info.cpp | 7 +- llarp/service/info.hpp | 7 +- llarp/service/intro.hpp | 2 - llarp/service/intro_set.cpp | 57 +- llarp/service/intro_set.hpp | 11 +- llarp/service/lns_tracker.hpp | 4 +- llarp/service/name.hpp | 1 + llarp/service/outbound_context.cpp | 13 +- llarp/service/outbound_context.hpp | 2 +- llarp/service/protocol.cpp | 4 +- llarp/service/protocol.hpp | 10 +- llarp/service/session.hpp | 5 +- llarp/service/tag.hpp | 1 - llarp/util/bencode.cpp | 2 +- llarp/util/bencode.h | 7 +- llarp/util/bencode.hpp | 10 +- llarp/util/buffer.hpp | 9 +- llarp/util/easter_eggs.cpp | 39 -- llarp/util/file.cpp | 11 +- llarp/util/file.hpp | 4 +- llarp/util/json.cpp | 59 -- llarp/util/json.hpp | 42 -- llarp/util/logging/buffer.cpp | 2 - llarp/util/logging/buffer.hpp | 1 - llarp/util/str.cpp | 4 - llarp/util/str.hpp | 2 +- llarp/util/thread/queue_manager.cpp | 1 - llarp/util/thread/threading.hpp | 7 +- llarp/util/time.cpp | 3 +- llarp/util/time.hpp | 5 +- llarp/vpn/platform.cpp | 2 - llarp/vpn/platform.hpp | 3 +- 161 files changed, 1916 insertions(+), 3653 deletions(-) create mode 100644 cmake/CMakeGraphVizOptions.cmake create mode 100644 llarp/CMakeLists_old.txt create mode 100644 llarp/bootstrap_fallbacks.cpp delete mode 100644 llarp/dns/query.hpp delete mode 100644 llarp/messages/link_intro.cpp delete mode 100644 llarp/peerstats/orm.hpp delete mode 100644 llarp/peerstats/peer_db.cpp delete mode 100644 llarp/peerstats/peer_db.hpp delete mode 100644 llarp/peerstats/types.cpp delete mode 100644 llarp/peerstats/types.hpp delete mode 100644 llarp/router/outbound_message_handler.cpp delete mode 100644 llarp/router/outbound_session_maker.cpp delete mode 100644 llarp/util/easter_eggs.cpp delete mode 100644 llarp/util/json.cpp delete mode 100644 llarp/util/json.hpp diff --git a/.gitignore b/.gitignore index d0dfc98445..a1d1593df7 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,4 @@ regdbhelper.dll # xcode xcuserdata/ +scc.py diff --git a/cmake/CMakeGraphVizOptions.cmake b/cmake/CMakeGraphVizOptions.cmake new file mode 100644 index 0000000000..f0de4137e8 --- /dev/null +++ b/cmake/CMakeGraphVizOptions.cmake @@ -0,0 +1,5 @@ +set(GRAPHVIZ_MODULE_LIBS OFF CACHE BOOL "") +set(GRAPHVIZ_EXTERNAL_LIBS OFF CACHE BOOL "") +set(GRAPHVIZ_GENERATE_PER_TARGET OFF CACHE BOOL "") +set(GRAPHVIZ_GENERATE_DEPENDERS OFF CACHE BOOL "") +set(GRAPHVIZ_OBJECT_LIBS OFF CACHE BOOL "") diff --git a/crypto/libntrup/src/ntru.cpp b/crypto/libntrup/src/ntru.cpp index b21fdc690a..c3fab075f7 100644 --- a/crypto/libntrup/src/ntru.cpp +++ b/crypto/libntrup/src/ntru.cpp @@ -1,5 +1,7 @@ #include +#include "libntrup/ntru_api.h" + #ifdef __x86_64__ #include #include diff --git a/daemon/lokinet-bootstrap.cpp b/daemon/lokinet-bootstrap.cpp index 435ec6767b..435934cdd0 100644 --- a/daemon/lokinet-bootstrap.cpp +++ b/daemon/lokinet-bootstrap.cpp @@ -1,13 +1,10 @@ #include + #include #include -#include #include -#include -#include #include - #include #include @@ -15,12 +12,6 @@ #include #endif -#include - -#ifndef _WIN32 -#include -#endif - namespace { int diff --git a/daemon/lokinet-vpn.cpp b/daemon/lokinet-vpn.cpp index 64b41dddb9..aae574cbab 100644 --- a/daemon/lokinet-vpn.cpp +++ b/daemon/lokinet-vpn.cpp @@ -1,16 +1,11 @@ -#include -#include -#include #include #include -#include -#include #include -#include -#include -#include -#include "oxenmq/address.h" +#include +#include +#include +#include #ifdef _WIN32 // add the unholy windows headers for iphlpapi @@ -19,7 +14,6 @@ #include #include #else -#include #endif /// do a oxenmq request on an omq instance blocking style diff --git a/daemon/lokinet.cpp b/daemon/lokinet.cpp index 4aa061ec11..2d87fc7bba 100644 --- a/daemon/lokinet.cpp +++ b/daemon/lokinet.cpp @@ -3,8 +3,7 @@ #include #include #include -#include -#include +#include #ifdef _WIN32 #include @@ -13,16 +12,38 @@ #include #endif -#include +#include +#include #include #include #include #include - -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "CLI/Error.hpp" +#include "CLI/Option.hpp" +#include "CLI/impl/App_inl.hpp" +#include "CLI/impl/Option_inl.hpp" +#include "fmt/core.h" +#include "llarp/constants/files.hpp" +#include "llarp/constants/platform.hpp" +#include "llarp/ev/ev.hpp" +#include "llarp/util/logging.hpp" +#include "llarp/util/thread/threading.hpp" +#include "oxen/log.hpp" +#include "oxen/log/catlogger.hpp" +#include "oxen/log/level.hpp" +#include "oxen/log/ring_buffer_sink.hpp" +#include "oxen/log/type.hpp" +#include "spdlog/common.h" namespace { @@ -350,8 +371,8 @@ namespace int lokinet_main(int argc, char** argv) { - if (auto result = Lokinet_INIT()) - return result; + // if (auto result = Lokinet_INIT()) + // return result; llarp::RuntimeOptions opts; opts.showBanner = false; diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index cc2d51d5e4..aec3b59f0e 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -7,38 +7,128 @@ add_library(lokinet-cryptography crypto/types.cpp ) -add_library(lokinet-util +# files only included by lokinet-core +add_library(lokinet-core-internal + STATIC + router/rc_gossiper.cpp + service/info.cpp + service/lns_tracker.cpp + service/session.cpp +) + +# Functional objects use by lokinet-core and other libraries +# needed by vpn/ router/ rpc/ handlers/ net/ link/ +add_library(lokinet-core-utils + STATIC + endpoint_base.cpp + exit/context.cpp + exit/endpoint.cpp # handlers/exit.hpp + exit/policy.cpp # net/ + service/auth.cpp # config/ + service/context.cpp + service/identity.cpp + service/intro.cpp # path + service/name.cpp + service/tag.cpp +) + +add_library(lokinet-core + STATIC + context.cpp + consensus/reachability_testing.cpp + exit/session.cpp + handlers/exit.cpp # link/ exit/ + handlers/tun.cpp + link/link_manager.cpp + router/router.cpp + router/route_poker.cpp + service/async_key_exchange.cpp + service/endpoint_util.cpp + service/endpoint.cpp + service/endpoint_state.cpp + service/name.cpp + service/outbound_context.cpp + service/protocol.cpp + vpn/egres_packet_router.cpp +) + +# Files only included by lokinet-rpc +# add_library(lokinet-rpc-internal +# STATIC +# ) + + add_library(lokinet-rpc + STATIC + rpc/json_binary_proxy.cpp + rpc/json_conversions.cpp + rpc/lokid_rpc_client.cpp + rpc/rpc_request_parser.cpp + rpc/rpc_server.cpp + rpc/endpoint_rpc.cpp +) + +# Files only included by lokinet-wire +add_library(lokinet-wire-internal + STATIC + link/connection.cpp +) + +add_library(lokinet-wire + STATIC + link/contacts.cpp + link/link_manager.cpp + # link/tunnel.cpp +) + +add_library(lokinet-utils-internal + STATIC + util/thread/queue_manager.cpp +) + +# config, crypto, timeplace, nodedb, bootstrap.cpp, net, router +add_library(lokinet-utils STATIC ${CMAKE_CURRENT_BINARY_DIR}/constants/version.cpp util/bencode.cpp util/buffer.cpp util/file.cpp - util/json.cpp - util/logging/buffer.cpp - util/easter_eggs.cpp util/mem.cpp util/str.cpp - util/thread/queue_manager.cpp util/thread/threading.cpp - util/time.cpp) - -add_dependencies(lokinet-util genversion) + util/time.cpp + util/logging/buffer.cpp +) + +add_dependencies(lokinet-utils genversion) -# lokinet-platform holds all platform specific code -add_library(lokinet-platform +# Addressing and event loop files used by lokinet-core and other libraries +# needed by rpc/ link/ service/ config/ path/ dht/ +add_library(lokinet-time-place STATIC - # for networking + pow.cpp # only intro_set + router_contact.cpp + router_id.cpp + router_version.cpp # to be deleted shortly ev/ev.cpp ev/libuv.cpp - net/interface_info.cpp + net/exit_info.cpp # only router_contact net/ip.cpp net/ip_address.cpp net/ip_packet.cpp net/ip_range.cpp net/net_int.cpp net/sock_addr.cpp + service/address.cpp + service/convotag.cpp + service/intro_set.cpp +) + +# lokinet-platform holds all platform specific code +add_library(lokinet-platform + STATIC + router/rc_lookup_handler.cpp + net/interface_info.cpp vpn/packet_router.cpp - vpn/egres_packet_router.cpp vpn/platform.cpp ) @@ -80,16 +170,21 @@ endif() # parse modify and reconstitute dns wire proto, dns queries and RR # should have no concept of dns caching, this is left as an implementation # detail of dns resolvers (LATER: make separate lib for dns resolvers) -add_library(lokinet-dns +add_library(lokinet-dns-internal STATIC - dns/message.cpp - dns/name.cpp + dns/name.cpp # srv_data, question, rr dns/platform.cpp - dns/question.cpp + dns/question.cpp # message dns/rr.cpp dns/serialize.cpp - dns/server.cpp - dns/srv_data.cpp) +) + +add_library(lokinet-dns + STATIC + dns/message.cpp # dns/server + dns/server.cpp # handlers/exit+tun and service/endpoint + dns/srv_data.cpp +) # platform specific bits and bobs for setting dns add_library(lokinet-dns-platform INTERFACE) @@ -102,15 +197,10 @@ endif() # nodedb data published to the network and versions of it stored locally add_library(lokinet-nodedb STATIC - bootstrap.cpp - net/exit_info.cpp - net/traffic_policy.cpp + bootstrap.cpp # config, router.hpp nodedb.cpp - pow.cpp - profiling.cpp - router_contact.cpp - router_id.cpp - router_version.cpp + profiling.cpp # path, router, service::endpoint + net/traffic_policy.cpp # config, intro_set ) set(BOOTSTRAP_FALLBACKS) @@ -141,15 +231,8 @@ add_library(lokinet-config config/key_manager.cpp ) -# lokinet-consensus is for deriving and tracking network consensus state for both service nodes and clients -add_library(lokinet-consensus - STATIC - consensus/reachability_testing.cpp -) - -# lokinet-layer-onion is the "dumb" onion routing layer with builds manages and does i/o -# with onion paths. onion paths anonymize routing layer pdu. -add_library(lokinet-layer-onion +# All path objects; link directly to lokinet-core +add_library(lokinet-path STATIC path/abstracthophandler.cpp path/path_context.cpp @@ -160,262 +243,140 @@ add_library(lokinet-layer-onion messages/relay.cpp ) -# lokinet-layer-link is for our layer 2 analog which splits up layer 2 frames into -# a series of layer 1 symbols which are then transmitted between lokinet instances -add_library(lokinet-layer-link - STATIC - link/connection.cpp - link/contacts.cpp - link/link_manager.cpp - # link/tunnel.cpp -) - -# lokinet-context holds the contextualized god objects for a lokinet instance -# it is what any main function would link to in practice but it is hidden behind an interface library (lokinet-amalgum) -add_library(lokinet-context - STATIC - context.cpp - link/link_manager.cpp - router/rc_lookup_handler.cpp - router/rc_gossiper.cpp - router/router.cpp - router/route_poker.cpp -) - -# lokinet-rpc holds all rpc related compilation units -add_library(lokinet-rpc - STATIC - rpc/json_binary_proxy.cpp - rpc/json_conversions.cpp - rpc/lokid_rpc_client.cpp - rpc/rpc_request_parser.cpp - rpc/rpc_server.cpp - rpc/endpoint_rpc.cpp -) - -# optional peer stats library -add_library(lokinet-peerstats - STATIC - peerstats/peer_db.cpp - peerstats/types.cpp -) - -# kitchen sink to be removed after refactor -add_library(lokinet-service-deprecated-kitchensink - STATIC - endpoint_base.cpp - exit/context.cpp - exit/endpoint.cpp - exit/policy.cpp - exit/session.cpp - handlers/exit.cpp - handlers/tun.cpp - service/name.cpp - service/address.cpp - service/async_key_exchange.cpp - service/auth.cpp - service/convotag.cpp - service/context.cpp - service/endpoint_state.cpp - service/endpoint_util.cpp - service/endpoint.cpp - service/identity.cpp - service/info.cpp - service/intro_set.cpp - service/intro.cpp - service/lns_tracker.cpp - service/name.cpp - service/outbound_context.cpp - service/protocol.cpp - service/session.cpp - service/tag.cpp -) +add_library(lokinet-amalgum INTERFACE) -# interface library for setting commone includes, linkage and flags. +# interface library for setting common includes, linkage and flags. add_library(lokinet-base INTERFACE) target_include_directories(lokinet-base INTERFACE ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/include ) target_link_libraries(lokinet-base INTERFACE quic) -if(WITH_PEERSTATS) - target_compile_definitions(lokinet-base INTERFACE -DLOKINET_PEERSTATS_BACKEND) - target_link_libraries(lokinet-base INTERFACE sqlite_orm) -endif() - -# interface libraries for internal linkage -add_library(lokinet-layers INTERFACE) -add_library(lokinet-amalgum INTERFACE) - -# helper function to link a library to lokinet-base, enable lto, add to lokinet-amalgum and then link to other libs -function(lokinet_link_lib libname) - # Absolutely fuck this line, it doesn't "create" the target, as the target already exists - # message(DEBUG "created target: ${libname}") - enable_lto(${libname}) - target_link_libraries(${libname} PUBLIC lokinet-base ${ARGN}) - target_link_libraries(lokinet-amalgum INTERFACE ${libname}) -endfunction() - -# internal public linkages of components -lokinet_link_lib(lokinet-util lokinet-libntrup) -lokinet_link_lib(lokinet-cryptography lokinet-libcrypt lokinet-util) -lokinet_link_lib(lokinet-peerstats lokinet-context) -lokinet_link_lib(lokinet-consensus lokinet-context) -lokinet_link_lib(lokinet-layer-link lokinet-cryptography lokinet-peerstats) - -if(TARGET lokinet-dns-systemd) - lokinet_link_lib(lokinet-dns-systemd - lokinet-dns - lokinet-platform - ) +# Link libraries to their internals +target_link_libraries(lokinet-core-internal PUBLIC lokinet-utils lokinet-core-utils) +target_link_libraries(lokinet-core PRIVATE lokinet-core-internal) +# target_link_libraries(lokinet-rpc PRIVATE lokinet-rpc-internal) +target_link_libraries(lokinet-wire PRIVATE lokinet-wire-internal) +# target_link_libraries(lokinet-time-place PRIVATE lokinet-time-place-internal) +target_link_libraries(lokinet-dns PRIVATE lokinet-dns-internal) +target_link_libraries(lokinet-utils PRIVATE lokinet-utils-internal) + +# Link lokinet-dns to alternate libraries +target_link_libraries(lokinet-dns PUBLIC lokinet-dns-platform) +if (TARGET lokinet-dns-systemd) + target_link_libraries(lokinet-dns PUBLIC lokinet-dns-systemd) endif() -lokinet_link_lib(lokinet-platform lokinet-util) - -lokinet_link_lib(lokinet-config - lokinet-util +# Link relevant to lokinet-base +target_link_libraries(lokinet-core PUBLIC lokinet-base) +target_link_libraries(lokinet-rpc PUBLIC lokinet-base) +target_link_libraries(lokinet-nodedb PUBLIC lokinet-base) +target_link_libraries(lokinet-wire PUBLIC lokinet-base) +target_link_libraries(lokinet-time-place PUBLIC lokinet-base) +target_link_libraries(lokinet-dns PUBLIC lokinet-base) +target_link_libraries(lokinet-platform PUBLIC lokinet-base) +target_link_libraries(lokinet-utils PUBLIC lokinet-base) +target_link_libraries(lokinet-libntrup PUBLIC lokinet-base) + +# Link relevant to amalgum +target_link_libraries(lokinet-amalgum + INTERFACE + lokinet-core + lokinet-rpc lokinet-nodedb + lokinet-wire + lokinet-time-place lokinet-dns lokinet-platform + lokinet-utils + lokinet-cryptography + lokinet-path ) - -lokinet_link_lib(lokinet-context - lokinet-config - lokinet-platform - lokinet-peerstats - lokinet-layers - lokinet-consensus - lokinet-rpc +#or just do this?? +# target_link_libraries(lokinet-amalgum INTERFACE lokinet-base) +target_link_libraries(lokinet-wire-internal PUBLIC lokinet-time-place) +target_link_libraries(lokinet-dns-internal PUBLIC lokinet-utils lokinet-config) +target_link_libraries(lokinet-dns PUBLIC lokinet-cryptography) +target_link_libraries(lokinet-nodedb PUBLIC lokinet-cryptography) +target_link_libraries(lokinet-platform PUBLIC lokinet-cryptography) +target_link_libraries(lokinet-rpc PUBLIC lokinet-wire) +target_link_libraries(lokinet-time-place PUBLIC lokinet-utils lokinet-cryptography) +target_link_libraries(lokinet-wire PUBLIC lokinet-cryptography) +target_link_libraries(lokinet-config PUBLIC lokinet-cryptography) + +target_link_libraries(lokinet-path + PUBLIC + lokinet-time-place ) -lokinet_link_lib( +target_link_libraries(lokinet-core-utils + PUBLIC + lokinet-core + lokinet-wire + lokinet-rpc lokinet-platform - lokinet-config ) -lokinet_link_lib(lokinet-dns - lokinet-platform - lokinet-dns-platform - lokinet-config +target_link_libraries(lokinet-cryptography + PUBLIC + lokinet-libcrypt + lokinet-libntrup ) -lokinet_link_lib(lokinet-nodedb - lokinet-util - lokinet-platform +target_link_libraries(lokinet-utils + PUBLIC + lokinet-cryptography ) -lokinet_link_lib(lokinet-util - lokinet-nodedb - lokinet-platform -) - -lokinet_link_lib(lokinet-rpc - lokinet-context - lokinet-peerstats - lokinet-util -) - -# inter lokinet-layer public/private linkage. -# when linking each layer, we consider the layer directly below private linkage and the layer above public linkage. -# this lets us hide functionality of layers below us when depended on by another component. -# -# from highest to lowest layer, the above layers are stacked as follows: -# -# platform (what lokinet snapps interact with, be it l3 os interaction or embedded lokinet) -# flow (how we want to route and stripe over our onion routing) -# routing (what we are onion routing) -# onion (how the onion routing happens) -# link (what we want to send over the wire and to where) -# wire (what is actually sent over the wire) -# -function(link_lokinet_layers) - set(lib ${ARGV0}) - if(${ARGC} GREATER 1) - lokinet_link_lib(${ARGV1} ${lib}) - list(REMOVE_AT ARGV 1) - target_link_libraries(${lib} PRIVATE ${ARGV1}) - # recursion :D - link_lokinet_layers(${ARGV}) - else() - lokinet_link_lib(${lib}) - endif() -endfunction() - -link_lokinet_layers( - lokinet-layer-onion - lokinet-layer-link -) - -# set me to OFF to disable old codepath -set(use_old_impl ON) -if(use_old_impl) - # flow layer deprecated-kitchensink (remove me after refactor) - lokinet_link_lib(lokinet-service-deprecated-kitchensink - lokinet-dns - lokinet-nodedb - lokinet-context - lokinet-layer-onion - lokinet-platform - lokinet-rpc - ) - target_link_libraries(lokinet-layers INTERFACE lokinet-service-deprecated-kitchensink) -endif() - -target_link_libraries(lokinet-layers INTERFACE - lokinet-layer-onion - lokinet-layer-link +# cross linkage +target_link_libraries(lokinet-core + PUBLIC + lokinet-rpc + lokinet-wire + lokinet-nodedb + lokinet-config + lokinet-cryptography ) # per component external deps - +# target_link_libraries(oxenmq::oxenmq +# PUBLIC +# lokinet-time-place +# lokinet-core +# lokinet-config +# lokinet-platform +# lokinet-dns +# lokinet-rpc +# ) + +target_link_libraries(lokinet-rpc PUBLIC oxenmq::oxenmq oxenc::oxenc) +target_link_libraries(lokinet-core PUBLIC oxenmq::oxenmq CLI11 uvw) target_link_libraries(lokinet-config PUBLIC oxenmq::oxenmq) -target_link_libraries(lokinet-platform PUBLIC oxenmq::oxenmq) -target_link_libraries(lokinet-dns PUBLIC libunbound) - -target_link_libraries(lokinet-cryptography PUBLIC - oxenc::oxenc - sodium -) - -target_link_libraries(lokinet-context PUBLIC - CLI11 - oxenmq::oxenmq - uvw -) - -target_link_libraries(lokinet-platform PUBLIC - Threads::Threads - base_libs - uvw -) - -target_link_libraries(lokinet-util PUBLIC - nlohmann_json::nlohmann_json -# filesystem - oxenc::oxenc -) - -target_link_libraries(lokinet-layer-link PUBLIC - quic - uvw -) - -if(WITH_EMBEDDED_LOKINET) - include(GNUInstallDirs) - add_library(lokinet-shared SHARED lokinet_shared.cpp) - target_link_libraries(lokinet-shared PUBLIC lokinet-amalgum) - if(WIN32) - set(CMAKE_SHARED_LIBRARY_PREFIX_CXX "") - endif() - set_target_properties(lokinet-shared PROPERTIES OUTPUT_NAME lokinet) - if(WIN32) - target_link_libraries(lokinet-shared PUBLIC ws2_32 iphlpapi -fstack-protector) - install(TARGETS lokinet-shared DESTINATION bin COMPONENT liblokinet) - elseif(NOT APPLE) - install(TARGETS lokinet-shared LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT liblokinet) - endif() -endif() - -file(GLOB_RECURSE docs_SRC */*.hpp *.hpp) -set(DOCS_SRC ${docs_SRC} PARENT_SCOPE) +target_link_libraries(lokinet-nodedb PUBLIC oxenmq::oxenmq uvw) +target_link_libraries(lokinet-path PUBLIC oxenmq::oxenmq) +target_link_libraries(lokinet-time-place PUBLIC uvw oxenc::oxenc) +target_link_libraries(lokinet-platform PUBLIC oxenmq::oxenmq Threads::Threads base_libs uvw) +target_link_libraries(lokinet-cryptography PUBLIC oxenc::oxenc sodium) +target_link_libraries(lokinet-dns PUBLIC libunbound uvw) +target_link_libraries(lokinet-utils PUBLIC nlohmann_json::nlohmann_json oxenc::oxenc) +target_link_libraries(lokinet-wire PUBLIC oxenmq::oxenmq quic uvw) + +# if(WITH_EMBEDDED_LOKINET) +# include(GNUInstallDirs) +# add_library(lokinet-shared SHARED lokinet_shared.cpp) +# target_link_libraries(lokinet-shared PUBLIC lokinet-amalgum) +# if(WIN32) +# set(CMAKE_SHARED_LIBRARY_PREFIX_CXX "") +# endif() +# set_target_properties(lokinet-shared PROPERTIES OUTPUT_NAME lokinet) +# if(WIN32) +# target_link_libraries(lokinet-shared PUBLIC ws2_32 iphlpapi -fstack-protector) +# install(TARGETS lokinet-shared DESTINATION bin COMPONENT liblokinet) +# elseif(NOT APPLE) +# install(TARGETS lokinet-shared LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT liblokinet) +# endif() +# endif() + +# file(GLOB_RECURSE docs_SRC */*.hpp *.hpp) +# set(DOCS_SRC ${docs_SRC} PARENT_SCOPE) diff --git a/llarp/CMakeLists_old.txt b/llarp/CMakeLists_old.txt new file mode 100644 index 0000000000..cc2d51d5e4 --- /dev/null +++ b/llarp/CMakeLists_old.txt @@ -0,0 +1,421 @@ +include(Version) + +add_library(lokinet-cryptography + STATIC + crypto/crypto.cpp + crypto/encrypted_frame.cpp + crypto/types.cpp +) + +add_library(lokinet-util + STATIC + ${CMAKE_CURRENT_BINARY_DIR}/constants/version.cpp + util/bencode.cpp + util/buffer.cpp + util/file.cpp + util/json.cpp + util/logging/buffer.cpp + util/easter_eggs.cpp + util/mem.cpp + util/str.cpp + util/thread/queue_manager.cpp + util/thread/threading.cpp + util/time.cpp) + +add_dependencies(lokinet-util genversion) + +# lokinet-platform holds all platform specific code +add_library(lokinet-platform + STATIC + # for networking + ev/ev.cpp + ev/libuv.cpp + net/interface_info.cpp + net/ip.cpp + net/ip_address.cpp + net/ip_packet.cpp + net/ip_range.cpp + net/net_int.cpp + net/sock_addr.cpp + vpn/packet_router.cpp + vpn/egres_packet_router.cpp + vpn/platform.cpp +) + +if (ANDROID) + target_sources(lokinet-platform PRIVATE android/ifaddrs.c util/nop_service_manager.cpp) +endif() + +if(CMAKE_SYSTEM_NAME MATCHES "Linux") + target_sources(lokinet-platform PRIVATE linux/dbus.cpp) + if(WITH_SYSTEMD) + target_sources(lokinet-platform PRIVATE linux/sd_service_manager.cpp) + else() + target_sources(lokinet-platform PRIVATE util/nop_service_manager.cpp) + endif() +endif() + +if (WIN32) + target_sources(lokinet-platform PRIVATE + net/win32.cpp + vpn/win32.cpp + win32/service_manager.cpp + win32/exec.cpp + win32/dll.cpp + win32/exception.cpp + win32/wintun.cpp + win32/windivert.cpp) + target_include_directories(lokinet-platform PRIVATE ${CMAKE_BINARY_DIR}/wintun/include/ ${CMAKE_BINARY_DIR}/WinDivert-${WINDIVERT_VERSION}/include/) +else() + target_sources(lokinet-platform PRIVATE + net/posix.cpp) +endif() + +if(APPLE) + add_subdirectory(apple) + target_sources(lokinet-platform PRIVATE util/nop_service_manager.cpp) +endif() + +# lokinet-dns is the dns parsing and hooking library that we use to +# parse modify and reconstitute dns wire proto, dns queries and RR +# should have no concept of dns caching, this is left as an implementation +# detail of dns resolvers (LATER: make separate lib for dns resolvers) +add_library(lokinet-dns + STATIC + dns/message.cpp + dns/name.cpp + dns/platform.cpp + dns/question.cpp + dns/rr.cpp + dns/serialize.cpp + dns/server.cpp + dns/srv_data.cpp) + +# platform specific bits and bobs for setting dns +add_library(lokinet-dns-platform INTERFACE) +if(WITH_SYSTEMD) + add_library(lokinet-dns-systemd STATIC dns/nm_platform.cpp dns/sd_platform.cpp) + target_link_libraries(lokinet-dns-platform INTERFACE lokinet-dns-systemd) +endif() + +# lokinet-nodedb holds all types and logic for storing parsing and constructing +# nodedb data published to the network and versions of it stored locally +add_library(lokinet-nodedb + STATIC + bootstrap.cpp + net/exit_info.cpp + net/traffic_policy.cpp + nodedb.cpp + pow.cpp + profiling.cpp + router_contact.cpp + router_id.cpp + router_version.cpp +) + +set(BOOTSTRAP_FALLBACKS) +foreach(bs IN ITEMS MAINNET TESTNET) + if(BOOTSTRAP_FALLBACK_${bs}) + message(STATUS "Building with ${bs} fallback boostrap path \"${BOOTSTRAP_FALLBACK_${bs}}\"") + file(READ "${BOOTSTRAP_FALLBACK_${bs}}" bs_data HEX) + if(bs STREQUAL TESTNET) + set(network "gamma") + elseif(bs STREQUAL MAINNET) + set(network "lokinet") + else() + string(TOLOWER "${bs}" network) + endif() + string(REGEX REPLACE "([0-9a-f][0-9a-f])" "\\\\x\\1" bs_data "${bs_data}") + set(BOOTSTRAP_FALLBACKS "${BOOTSTRAP_FALLBACKS}{\"${network}\"s, \"${bs_data}\"sv},\n") + endif() +endforeach() +configure_file("bootstrap-fallbacks.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/bootstrap-fallbacks.cpp" @ONLY) +target_sources(lokinet-nodedb PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/bootstrap-fallbacks.cpp") + +# lokinet-config is for all configuration types and parsers +add_library(lokinet-config + STATIC + config/config.cpp + config/definition.cpp + config/ini.cpp + config/key_manager.cpp +) + +# lokinet-consensus is for deriving and tracking network consensus state for both service nodes and clients +add_library(lokinet-consensus + STATIC + consensus/reachability_testing.cpp +) + +# lokinet-layer-onion is the "dumb" onion routing layer with builds manages and does i/o +# with onion paths. onion paths anonymize routing layer pdu. +add_library(lokinet-layer-onion + STATIC + path/abstracthophandler.cpp + path/path_context.cpp + path/path.cpp + path/pathbuilder.cpp + path/pathset.cpp + path/transit_hop.cpp + messages/relay.cpp +) + +# lokinet-layer-link is for our layer 2 analog which splits up layer 2 frames into +# a series of layer 1 symbols which are then transmitted between lokinet instances +add_library(lokinet-layer-link + STATIC + link/connection.cpp + link/contacts.cpp + link/link_manager.cpp + # link/tunnel.cpp +) + +# lokinet-context holds the contextualized god objects for a lokinet instance +# it is what any main function would link to in practice but it is hidden behind an interface library (lokinet-amalgum) +add_library(lokinet-context + STATIC + context.cpp + link/link_manager.cpp + router/rc_lookup_handler.cpp + router/rc_gossiper.cpp + router/router.cpp + router/route_poker.cpp +) + +# lokinet-rpc holds all rpc related compilation units +add_library(lokinet-rpc + STATIC + rpc/json_binary_proxy.cpp + rpc/json_conversions.cpp + rpc/lokid_rpc_client.cpp + rpc/rpc_request_parser.cpp + rpc/rpc_server.cpp + rpc/endpoint_rpc.cpp +) + +# optional peer stats library +add_library(lokinet-peerstats + STATIC + peerstats/peer_db.cpp + peerstats/types.cpp +) + +# kitchen sink to be removed after refactor +add_library(lokinet-service-deprecated-kitchensink + STATIC + endpoint_base.cpp + exit/context.cpp + exit/endpoint.cpp + exit/policy.cpp + exit/session.cpp + handlers/exit.cpp + handlers/tun.cpp + service/name.cpp + service/address.cpp + service/async_key_exchange.cpp + service/auth.cpp + service/convotag.cpp + service/context.cpp + service/endpoint_state.cpp + service/endpoint_util.cpp + service/endpoint.cpp + service/identity.cpp + service/info.cpp + service/intro_set.cpp + service/intro.cpp + service/lns_tracker.cpp + service/name.cpp + service/outbound_context.cpp + service/protocol.cpp + service/session.cpp + service/tag.cpp +) + +# interface library for setting commone includes, linkage and flags. +add_library(lokinet-base INTERFACE) +target_include_directories(lokinet-base + INTERFACE ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/include +) +target_link_libraries(lokinet-base INTERFACE quic) + +if(WITH_PEERSTATS) + target_compile_definitions(lokinet-base INTERFACE -DLOKINET_PEERSTATS_BACKEND) + target_link_libraries(lokinet-base INTERFACE sqlite_orm) +endif() + +# interface libraries for internal linkage +add_library(lokinet-layers INTERFACE) +add_library(lokinet-amalgum INTERFACE) + +# helper function to link a library to lokinet-base, enable lto, add to lokinet-amalgum and then link to other libs +function(lokinet_link_lib libname) + # Absolutely fuck this line, it doesn't "create" the target, as the target already exists + # message(DEBUG "created target: ${libname}") + enable_lto(${libname}) + target_link_libraries(${libname} PUBLIC lokinet-base ${ARGN}) + target_link_libraries(lokinet-amalgum INTERFACE ${libname}) +endfunction() + +# internal public linkages of components +lokinet_link_lib(lokinet-util lokinet-libntrup) +lokinet_link_lib(lokinet-cryptography lokinet-libcrypt lokinet-util) +lokinet_link_lib(lokinet-peerstats lokinet-context) +lokinet_link_lib(lokinet-consensus lokinet-context) +lokinet_link_lib(lokinet-layer-link lokinet-cryptography lokinet-peerstats) + +if(TARGET lokinet-dns-systemd) + lokinet_link_lib(lokinet-dns-systemd + lokinet-dns + lokinet-platform + ) +endif() + +lokinet_link_lib(lokinet-platform lokinet-util) + +lokinet_link_lib(lokinet-config + lokinet-util + lokinet-nodedb + lokinet-dns + lokinet-platform +) + +lokinet_link_lib(lokinet-context + lokinet-config + lokinet-platform + lokinet-peerstats + lokinet-layers + lokinet-consensus + lokinet-rpc +) + +lokinet_link_lib( + lokinet-platform + lokinet-config +) + +lokinet_link_lib(lokinet-dns + lokinet-platform + lokinet-dns-platform + lokinet-config +) + +lokinet_link_lib(lokinet-nodedb + lokinet-util + lokinet-platform +) + +lokinet_link_lib(lokinet-util + lokinet-nodedb + lokinet-platform +) + +lokinet_link_lib(lokinet-rpc + lokinet-context + lokinet-peerstats + lokinet-util +) + +# inter lokinet-layer public/private linkage. +# when linking each layer, we consider the layer directly below private linkage and the layer above public linkage. +# this lets us hide functionality of layers below us when depended on by another component. +# +# from highest to lowest layer, the above layers are stacked as follows: +# +# platform (what lokinet snapps interact with, be it l3 os interaction or embedded lokinet) +# flow (how we want to route and stripe over our onion routing) +# routing (what we are onion routing) +# onion (how the onion routing happens) +# link (what we want to send over the wire and to where) +# wire (what is actually sent over the wire) +# +function(link_lokinet_layers) + set(lib ${ARGV0}) + if(${ARGC} GREATER 1) + lokinet_link_lib(${ARGV1} ${lib}) + list(REMOVE_AT ARGV 1) + target_link_libraries(${lib} PRIVATE ${ARGV1}) + # recursion :D + link_lokinet_layers(${ARGV}) + else() + lokinet_link_lib(${lib}) + endif() +endfunction() + +link_lokinet_layers( + lokinet-layer-onion + lokinet-layer-link +) + +# set me to OFF to disable old codepath +set(use_old_impl ON) +if(use_old_impl) + # flow layer deprecated-kitchensink (remove me after refactor) + lokinet_link_lib(lokinet-service-deprecated-kitchensink + lokinet-dns + lokinet-nodedb + lokinet-context + lokinet-layer-onion + lokinet-platform + lokinet-rpc + ) + target_link_libraries(lokinet-layers INTERFACE lokinet-service-deprecated-kitchensink) +endif() + +target_link_libraries(lokinet-layers INTERFACE + lokinet-layer-onion + lokinet-layer-link +) + + +# per component external deps + +target_link_libraries(lokinet-config PUBLIC oxenmq::oxenmq) +target_link_libraries(lokinet-platform PUBLIC oxenmq::oxenmq) +target_link_libraries(lokinet-dns PUBLIC libunbound) + +target_link_libraries(lokinet-cryptography PUBLIC + oxenc::oxenc + sodium +) + +target_link_libraries(lokinet-context PUBLIC + CLI11 + oxenmq::oxenmq + uvw +) + +target_link_libraries(lokinet-platform PUBLIC + Threads::Threads + base_libs + uvw +) + +target_link_libraries(lokinet-util PUBLIC + nlohmann_json::nlohmann_json +# filesystem + oxenc::oxenc +) + +target_link_libraries(lokinet-layer-link PUBLIC + quic + uvw +) + +if(WITH_EMBEDDED_LOKINET) + include(GNUInstallDirs) + add_library(lokinet-shared SHARED lokinet_shared.cpp) + target_link_libraries(lokinet-shared PUBLIC lokinet-amalgum) + if(WIN32) + set(CMAKE_SHARED_LIBRARY_PREFIX_CXX "") + endif() + set_target_properties(lokinet-shared PROPERTIES OUTPUT_NAME lokinet) + if(WIN32) + target_link_libraries(lokinet-shared PUBLIC ws2_32 iphlpapi -fstack-protector) + install(TARGETS lokinet-shared DESTINATION bin COMPONENT liblokinet) + elseif(NOT APPLE) + install(TARGETS lokinet-shared LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT liblokinet) + endif() +endif() + +file(GLOB_RECURSE docs_SRC */*.hpp *.hpp) +set(DOCS_SRC ${docs_SRC} PARENT_SCOPE) diff --git a/llarp/bootstrap.cpp b/llarp/bootstrap.cpp index 32f830bdce..6247573223 100644 --- a/llarp/bootstrap.cpp +++ b/llarp/bootstrap.cpp @@ -1,8 +1,8 @@ #include "bootstrap.hpp" + #include "util/bencode.hpp" #include "util/logging.hpp" #include "util/logging/buffer.hpp" -#include "util/fs.hpp" namespace llarp { diff --git a/llarp/bootstrap.hpp b/llarp/bootstrap.hpp index c4a4b7d3fb..6c657a4b1a 100644 --- a/llarp/bootstrap.hpp +++ b/llarp/bootstrap.hpp @@ -1,8 +1,9 @@ #pragma once -#include "router_contact.hpp" #include #include + +#include "router_contact.hpp" #include "llarp/util/fs.hpp" namespace llarp diff --git a/llarp/bootstrap_fallbacks.cpp b/llarp/bootstrap_fallbacks.cpp new file mode 100644 index 0000000000..5be002098b --- /dev/null +++ b/llarp/bootstrap_fallbacks.cpp @@ -0,0 +1,25 @@ +#include +#include "llarp/bootstrap.hpp" + +namespace llarp +{ + using namespace std::literals; + + std::unordered_map + load_bootstrap_fallbacks() + { + std::unordered_map fallbacks; + using init_list = std::initializer_list>; + // clang-format off + for (const auto& [network, bootstrap] : init_list{ + // + }) + // clang-format on + { + llarp_buffer_t buf{bootstrap.data(), bootstrap.size()}; + auto& bsl = fallbacks[network]; + bsl.BDecode(&buf); + } + return fallbacks; + } +} // namespace llarp diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index eb038c2184..9df0d7c4cc 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -1,6 +1,4 @@ #include "config.hpp" -#include "definition.hpp" -#include "ini.hpp" #include #include @@ -8,19 +6,14 @@ #include #include #include -#include #include -#include #include -#include #include - #include +#include -#include -#include -#include -#include +#include "definition.hpp" +#include "ini.hpp" namespace llarp { diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index 9d0e7a54c9..692f8521bd 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -1,11 +1,6 @@ #pragma once -#include "ini.hpp" -#include "definition.hpp" #include #include - -#include - #include #include #include @@ -20,7 +15,8 @@ #include #include #include - +#include +#include #include #include #include @@ -29,7 +25,8 @@ #include #include -#include +#include "ini.hpp" +#include "definition.hpp" namespace llarp { diff --git a/llarp/config/definition.hpp b/llarp/config/definition.hpp index bd8d0fc173..c49b5161a8 100644 --- a/llarp/config/definition.hpp +++ b/llarp/config/definition.hpp @@ -1,11 +1,10 @@ #pragma once #include -#include -#include #include #include - +#include +#include #include #include #include diff --git a/llarp/config/ini.cpp b/llarp/config/ini.cpp index 06be65b560..b6fbb6166d 100644 --- a/llarp/config/ini.cpp +++ b/llarp/config/ini.cpp @@ -2,13 +2,10 @@ #include #include -#include #include #include #include -#include -#include #include namespace llarp diff --git a/llarp/config/ini.hpp b/llarp/config/ini.hpp index d327613936..3d72ee8cc6 100644 --- a/llarp/config/ini.hpp +++ b/llarp/config/ini.hpp @@ -1,12 +1,12 @@ #pragma once +#include #include #include #include #include #include #include -#include namespace llarp { diff --git a/llarp/config/key_manager.hpp b/llarp/config/key_manager.hpp index bb0c2075a0..060f13df92 100644 --- a/llarp/config/key_manager.hpp +++ b/llarp/config/key_manager.hpp @@ -1,9 +1,10 @@ #pragma once -#include -#include "config.hpp" #include #include +#include + +#include "config.hpp" namespace llarp { diff --git a/llarp/consensus/reachability_testing.cpp b/llarp/consensus/reachability_testing.cpp index 511f49a43d..33f0b9483b 100644 --- a/llarp/consensus/reachability_testing.cpp +++ b/llarp/consensus/reachability_testing.cpp @@ -1,6 +1,6 @@ #include "reachability_testing.hpp" -#include + #include #include #include diff --git a/llarp/consensus/reachability_testing.hpp b/llarp/consensus/reachability_testing.hpp index 9792c3ceec..8ac3636059 100644 --- a/llarp/consensus/reachability_testing.hpp +++ b/llarp/consensus/reachability_testing.hpp @@ -1,5 +1,7 @@ #pragma once +#include +#include #include #include #include @@ -7,9 +9,6 @@ #include #include -#include -#include - namespace llarp { struct Router; diff --git a/llarp/context.cpp b/llarp/context.cpp index df1f320e88..4dbb9d7096 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -1,5 +1,3 @@ -#include "nodedb.hpp" - #include #include #include @@ -7,18 +5,14 @@ #include #include #include -#include #include #include - -#include -#include -#include - #include #include #include +#include "nodedb.hpp" + #if (__FreeBSD__) || (__OpenBSD__) || (__NetBSD__) #include #endif diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index b30cd8c0e2..8491f2f18c 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -11,16 +10,12 @@ #include #include #include -#include -#include #include #include #ifdef HAVE_CRYPT #include #endif -#include - namespace llarp { static bool diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index a8f75a5f04..43db0b3595 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -1,14 +1,12 @@ #pragma once -#include "constants.hpp" -#include "types.hpp" - #include - #include - #include +#include "constants.hpp" +#include "types.hpp" + namespace llarp { /* diff --git a/llarp/crypto/encrypted_frame.cpp b/llarp/crypto/encrypted_frame.cpp index 6573d95330..f955183135 100644 --- a/llarp/crypto/encrypted_frame.cpp +++ b/llarp/crypto/encrypted_frame.cpp @@ -1,8 +1,8 @@ #include "encrypted_frame.hpp" -#include "crypto.hpp" #include -#include + +#include "crypto.hpp" namespace llarp { diff --git a/llarp/crypto/encrypted_frame.hpp b/llarp/crypto/encrypted_frame.hpp index 3bdd58b686..5c1c2ebea1 100644 --- a/llarp/crypto/encrypted_frame.hpp +++ b/llarp/crypto/encrypted_frame.hpp @@ -1,10 +1,11 @@ #pragma once -#include "encrypted.hpp" -#include "types.hpp" #include -#include #include +#include + +#include "encrypted.hpp" +#include "types.hpp" namespace llarp { diff --git a/llarp/crypto/types.cpp b/llarp/crypto/types.cpp index 93b3099bd7..9cf1c31591 100644 --- a/llarp/crypto/types.cpp +++ b/llarp/crypto/types.cpp @@ -2,14 +2,10 @@ #include #include - -#include - #include -#include -#include -#include +// #include +// #include namespace llarp { diff --git a/llarp/crypto/types.hpp b/llarp/crypto/types.hpp index 6a7a872596..abc77a1062 100644 --- a/llarp/crypto/types.hpp +++ b/llarp/crypto/types.hpp @@ -1,14 +1,16 @@ #pragma once -#include "constants.hpp" +#include + #include #include #include #include - #include #include +#include "constants.hpp" + namespace llarp { using SharedSecret = AlignedBuffer; diff --git a/llarp/dns/dns.hpp b/llarp/dns/dns.hpp index f6c3cf5a9d..bf21aeb291 100644 --- a/llarp/dns/dns.hpp +++ b/llarp/dns/dns.hpp @@ -1,30 +1,29 @@ #pragma once +#include + #include -namespace llarp +namespace llarp::dns { - namespace dns - { - constexpr uint16_t qTypeSRV = 33; - constexpr uint16_t qTypeAAAA = 28; - constexpr uint16_t qTypeTXT = 16; - constexpr uint16_t qTypeMX = 15; - constexpr uint16_t qTypePTR = 12; - constexpr uint16_t qTypeCNAME = 5; - constexpr uint16_t qTypeNS = 2; - constexpr uint16_t qTypeA = 1; + constexpr uint16_t qTypeSRV = 33; + constexpr uint16_t qTypeAAAA = 28; + constexpr uint16_t qTypeTXT = 16; + constexpr uint16_t qTypeMX = 15; + constexpr uint16_t qTypePTR = 12; + constexpr uint16_t qTypeCNAME = 5; + constexpr uint16_t qTypeNS = 2; + constexpr uint16_t qTypeA = 1; - constexpr uint16_t qClassIN = 1; + constexpr uint16_t qClassIN = 1; - constexpr uint16_t flags_QR = (1 << 15); - constexpr uint16_t flags_AA = (1 << 10); - constexpr uint16_t flags_TC = (1 << 9); - constexpr uint16_t flags_RD = (1 << 8); - constexpr uint16_t flags_RA = (1 << 7); - constexpr uint16_t flags_RCODENameError = (3); - constexpr uint16_t flags_RCODEServFail = (2); - constexpr uint16_t flags_RCODENoError = (0); + constexpr uint16_t flags_QR = (1 << 15); + constexpr uint16_t flags_AA = (1 << 10); + constexpr uint16_t flags_TC = (1 << 9); + constexpr uint16_t flags_RD = (1 << 8); + constexpr uint16_t flags_RA = (1 << 7); + constexpr uint16_t flags_RCODENameError = (3); + constexpr uint16_t flags_RCODEServFail = (2); + constexpr uint16_t flags_RCODENoError = (0); - } // namespace dns -} // namespace llarp +} // namespace llarp::dns diff --git a/llarp/dns/message.cpp b/llarp/dns/message.cpp index 48d84f7038..d527b03dd3 100644 --- a/llarp/dns/message.cpp +++ b/llarp/dns/message.cpp @@ -1,434 +1,430 @@ #include "message.hpp" -#include -#include "dns.hpp" -#include "srv_data.hpp" +#include #include -#include #include - #include -namespace llarp +#include "dns.hpp" +#include "srv_data.hpp" + +namespace llarp::dns { - namespace dns + static auto logcat = log::Cat("dns"); + + bool + MessageHeader::Encode(llarp_buffer_t* buf) const + { + if (!buf->put_uint16(id)) + return false; + if (!buf->put_uint16(fields)) + return false; + if (!buf->put_uint16(qd_count)) + return false; + if (!buf->put_uint16(an_count)) + return false; + if (!buf->put_uint16(ns_count)) + return false; + return buf->put_uint16(ar_count); + } + + bool + MessageHeader::Decode(llarp_buffer_t* buf) + { + if (!buf->read_uint16(id)) + return false; + if (!buf->read_uint16(fields)) + return false; + if (!buf->read_uint16(qd_count)) + return false; + if (!buf->read_uint16(an_count)) + return false; + if (!buf->read_uint16(ns_count)) + return false; + if (!buf->read_uint16(ar_count)) + return false; + return true; + } + + util::StatusObject + MessageHeader::ToJSON() const + { + return util::StatusObject{}; + } + + Message::Message(Message&& other) + : hdr_id(std::move(other.hdr_id)) + , hdr_fields(std::move(other.hdr_fields)) + , questions(std::move(other.questions)) + , answers(std::move(other.answers)) + , authorities(std::move(other.authorities)) + , additional(std::move(other.additional)) + {} + + Message::Message(const Message& other) + : hdr_id(other.hdr_id) + , hdr_fields(other.hdr_fields) + , questions(other.questions) + , answers(other.answers) + , authorities(other.authorities) + , additional(other.additional) + {} + + Message::Message(const MessageHeader& hdr) : hdr_id(hdr.id), hdr_fields(hdr.fields) { - static auto logcat = log::Cat("dns"); + questions.resize(size_t(hdr.qd_count)); + answers.resize(size_t(hdr.an_count)); + authorities.resize(size_t(hdr.ns_count)); + additional.resize(size_t(hdr.ar_count)); + } - bool - MessageHeader::Encode(llarp_buffer_t* buf) const - { - if (!buf->put_uint16(id)) - return false; - if (!buf->put_uint16(fields)) - return false; - if (!buf->put_uint16(qd_count)) - return false; - if (!buf->put_uint16(an_count)) - return false; - if (!buf->put_uint16(ns_count)) - return false; - return buf->put_uint16(ar_count); - } + Message::Message(const Question& question) : hdr_id{0}, hdr_fields{} + { + questions.emplace_back(question); + } - bool - MessageHeader::Decode(llarp_buffer_t* buf) - { - if (!buf->read_uint16(id)) - return false; - if (!buf->read_uint16(fields)) - return false; - if (!buf->read_uint16(qd_count)) - return false; - if (!buf->read_uint16(an_count)) - return false; - if (!buf->read_uint16(ns_count)) - return false; - if (!buf->read_uint16(ar_count)) + bool + Message::Encode(llarp_buffer_t* buf) const + { + MessageHeader hdr; + hdr.id = hdr_id; + hdr.fields = hdr_fields; + hdr.qd_count = questions.size(); + hdr.an_count = answers.size(); + hdr.ns_count = 0; + hdr.ar_count = 0; + + if (!hdr.Encode(buf)) + return false; + + for (const auto& question : questions) + if (!question.Encode(buf)) return false; - return true; - } - - util::StatusObject - MessageHeader::ToJSON() const - { - return util::StatusObject{}; - } - - Message::Message(Message&& other) - : hdr_id(std::move(other.hdr_id)) - , hdr_fields(std::move(other.hdr_fields)) - , questions(std::move(other.questions)) - , answers(std::move(other.answers)) - , authorities(std::move(other.authorities)) - , additional(std::move(other.additional)) - {} - - Message::Message(const Message& other) - : hdr_id(other.hdr_id) - , hdr_fields(other.hdr_fields) - , questions(other.questions) - , answers(other.answers) - , authorities(other.authorities) - , additional(other.additional) - {} - - Message::Message(const MessageHeader& hdr) : hdr_id(hdr.id), hdr_fields(hdr.fields) - { - questions.resize(size_t(hdr.qd_count)); - answers.resize(size_t(hdr.an_count)); - authorities.resize(size_t(hdr.ns_count)); - additional.resize(size_t(hdr.ar_count)); - } - - Message::Message(const Question& question) : hdr_id{0}, hdr_fields{} - { - questions.emplace_back(question); - } - bool - Message::Encode(llarp_buffer_t* buf) const - { - MessageHeader hdr; - hdr.id = hdr_id; - hdr.fields = hdr_fields; - hdr.qd_count = questions.size(); - hdr.an_count = answers.size(); - hdr.ns_count = 0; - hdr.ar_count = 0; - - if (!hdr.Encode(buf)) + for (const auto& answer : answers) + if (!answer.Encode(buf)) return false; - for (const auto& question : questions) - if (!question.Encode(buf)) - return false; - - for (const auto& answer : answers) - if (!answer.Encode(buf)) - return false; - - return true; - } + return true; + } - bool - Message::Decode(llarp_buffer_t* buf) + bool + Message::Decode(llarp_buffer_t* buf) + { + for (auto& qd : questions) { - for (auto& qd : questions) - { - if (!qd.Decode(buf)) - { - log::error(logcat, "failed to decode question"); - return false; - } - log::debug(logcat, "question: {}", qd); - } - for (auto& an : answers) + if (!qd.Decode(buf)) { - if (not an.Decode(buf)) - { - log::debug(logcat, "failed to decode answer"); - return false; - } + log::error(logcat, "failed to decode question"); + return false; } - return true; + log::debug(logcat, "question: {}", qd); } - - util::StatusObject - Message::ToJSON() const + for (auto& an : answers) { - std::vector ques; - std::vector ans; - for (const auto& q : questions) - { - ques.push_back(q.ToJSON()); - } - for (const auto& a : answers) + if (not an.Decode(buf)) { - ans.push_back(a.ToJSON()); + log::debug(logcat, "failed to decode answer"); + return false; } - return util::StatusObject{{"questions", ques}, {"answers", ans}}; } + return true; + } - OwnedBuffer - Message::ToBuffer() const + util::StatusObject + Message::ToJSON() const + { + std::vector ques; + std::vector ans; + for (const auto& q : questions) { - std::array tmp; - llarp_buffer_t buf{tmp}; - if (not Encode(&buf)) - throw std::runtime_error("cannot encode dns message"); - return OwnedBuffer::copy_used(buf); + ques.push_back(q.ToJSON()); } - - void - Message::AddServFail(RR_TTL_t) + for (const auto& a : answers) { - if (questions.size()) - { - hdr_fields |= flags_RCODEServFail; - // authorative response with recursion available - hdr_fields |= flags_QR | flags_AA | flags_RA; - // don't allow recursion on this request - hdr_fields &= ~flags_RD; - } + ans.push_back(a.ToJSON()); } + return util::StatusObject{{"questions", ques}, {"answers", ans}}; + } - static constexpr uint16_t - reply_flags(uint16_t setbits) + OwnedBuffer + Message::ToBuffer() const + { + std::array tmp; + llarp_buffer_t buf{tmp}; + if (not Encode(&buf)) + throw std::runtime_error("cannot encode dns message"); + return OwnedBuffer::copy_used(buf); + } + + void + Message::AddServFail(RR_TTL_t) + { + if (questions.size()) { - return setbits | flags_QR | flags_AA | flags_RA; + hdr_fields |= flags_RCODEServFail; + // authorative response with recursion available + hdr_fields |= flags_QR | flags_AA | flags_RA; + // don't allow recursion on this request + hdr_fields &= ~flags_RD; } + } + + static constexpr uint16_t + reply_flags(uint16_t setbits) + { + return setbits | flags_QR | flags_AA | flags_RA; + } - void - Message::AddINReply(llarp::huint128_t ip, bool isV6, RR_TTL_t ttl) + void + Message::AddINReply(llarp::huint128_t ip, bool isV6, RR_TTL_t ttl) + { + if (questions.size()) { - if (questions.size()) + hdr_fields = reply_flags(hdr_fields); + ResourceRecord rec; + rec.rr_name = questions[0].qname; + rec.rr_class = qClassIN; + rec.ttl = ttl; + if (isV6) { - hdr_fields = reply_flags(hdr_fields); - ResourceRecord rec; - rec.rr_name = questions[0].qname; - rec.rr_class = qClassIN; - rec.ttl = ttl; - if (isV6) - { - rec.rr_type = qTypeAAAA; - ip.ToV6(rec.rData); - } - else - { - const auto addr = net::TruncateV6(ip); - rec.rr_type = qTypeA; - rec.rData.resize(4); - oxenc::write_host_as_big(addr.h, rec.rData.data()); - } - answers.emplace_back(std::move(rec)); + rec.rr_type = qTypeAAAA; + ip.ToV6(rec.rData); } - } - - void - Message::AddAReply(std::string name, RR_TTL_t ttl) - { - if (questions.size()) + else { - hdr_fields = reply_flags(hdr_fields); - - const auto& question = questions[0]; - answers.emplace_back(); - auto& rec = answers.back(); - rec.rr_name = question.qname; - rec.rr_type = question.qtype; - rec.rr_class = qClassIN; - rec.ttl = ttl; - std::array tmp = {{0}}; - llarp_buffer_t buf(tmp); - if (EncodeNameTo(&buf, name)) - { - buf.sz = buf.cur - buf.base; - rec.rData.resize(buf.sz); - memcpy(rec.rData.data(), buf.base, buf.sz); - } + const auto addr = net::TruncateV6(ip); + rec.rr_type = qTypeA; + rec.rData.resize(4); + oxenc::write_host_as_big(addr.h, rec.rData.data()); } + answers.emplace_back(std::move(rec)); } + } - void - Message::AddNSReply(std::string name, RR_TTL_t ttl) + void + Message::AddAReply(std::string name, RR_TTL_t ttl) + { + if (questions.size()) { - if (not questions.empty()) + hdr_fields = reply_flags(hdr_fields); + + const auto& question = questions[0]; + answers.emplace_back(); + auto& rec = answers.back(); + rec.rr_name = question.qname; + rec.rr_type = question.qtype; + rec.rr_class = qClassIN; + rec.ttl = ttl; + std::array tmp = {{0}}; + llarp_buffer_t buf(tmp); + if (EncodeNameTo(&buf, name)) { - hdr_fields = reply_flags(hdr_fields); - - const auto& question = questions[0]; - answers.emplace_back(); - auto& rec = answers.back(); - rec.rr_name = question.qname; - rec.rr_type = qTypeNS; - rec.rr_class = qClassIN; - rec.ttl = ttl; - std::array tmp = {{0}}; - llarp_buffer_t buf(tmp); - if (EncodeNameTo(&buf, name)) - { - buf.sz = buf.cur - buf.base; - rec.rData.resize(buf.sz); - memcpy(rec.rData.data(), buf.base, buf.sz); - } + buf.sz = buf.cur - buf.base; + rec.rData.resize(buf.sz); + memcpy(rec.rData.data(), buf.base, buf.sz); } } + } - void - Message::AddCNAMEReply(std::string name, RR_TTL_t ttl) + void + Message::AddNSReply(std::string name, RR_TTL_t ttl) + { + if (not questions.empty()) { - if (questions.size()) + hdr_fields = reply_flags(hdr_fields); + + const auto& question = questions[0]; + answers.emplace_back(); + auto& rec = answers.back(); + rec.rr_name = question.qname; + rec.rr_type = qTypeNS; + rec.rr_class = qClassIN; + rec.ttl = ttl; + std::array tmp = {{0}}; + llarp_buffer_t buf(tmp); + if (EncodeNameTo(&buf, name)) { - hdr_fields = reply_flags(hdr_fields); - - const auto& question = questions[0]; - answers.emplace_back(); - auto& rec = answers.back(); - rec.rr_name = question.qname; - rec.rr_type = qTypeCNAME; - rec.rr_class = qClassIN; - rec.ttl = ttl; - std::array tmp = {{0}}; - llarp_buffer_t buf(tmp); - if (EncodeNameTo(&buf, name)) - { - buf.sz = buf.cur - buf.base; - rec.rData.resize(buf.sz); - memcpy(rec.rData.data(), buf.base, buf.sz); - } + buf.sz = buf.cur - buf.base; + rec.rData.resize(buf.sz); + memcpy(rec.rData.data(), buf.base, buf.sz); } } + } - void - Message::AddMXReply(std::string name, uint16_t priority, RR_TTL_t ttl) + void + Message::AddCNAMEReply(std::string name, RR_TTL_t ttl) + { + if (questions.size()) { - if (questions.size()) + hdr_fields = reply_flags(hdr_fields); + + const auto& question = questions[0]; + answers.emplace_back(); + auto& rec = answers.back(); + rec.rr_name = question.qname; + rec.rr_type = qTypeCNAME; + rec.rr_class = qClassIN; + rec.ttl = ttl; + std::array tmp = {{0}}; + llarp_buffer_t buf(tmp); + if (EncodeNameTo(&buf, name)) { - hdr_fields = reply_flags(hdr_fields); - - const auto& question = questions[0]; - answers.emplace_back(); - auto& rec = answers.back(); - rec.rr_name = question.qname; - rec.rr_type = qTypeMX; - rec.rr_class = qClassIN; - rec.ttl = ttl; - std::array tmp = {{0}}; - llarp_buffer_t buf(tmp); - buf.put_uint16(priority); - if (EncodeNameTo(&buf, name)) - { - buf.sz = buf.cur - buf.base; - rec.rData.resize(buf.sz); - memcpy(rec.rData.data(), buf.base, buf.sz); - } + buf.sz = buf.cur - buf.base; + rec.rData.resize(buf.sz); + memcpy(rec.rData.data(), buf.base, buf.sz); } } + } - void - Message::AddSRVReply(std::vector records, RR_TTL_t ttl) + void + Message::AddMXReply(std::string name, uint16_t priority, RR_TTL_t ttl) + { + if (questions.size()) { hdr_fields = reply_flags(hdr_fields); const auto& question = questions[0]; - - for (const auto& srv : records) + answers.emplace_back(); + auto& rec = answers.back(); + rec.rr_name = question.qname; + rec.rr_type = qTypeMX; + rec.rr_class = qClassIN; + rec.ttl = ttl; + std::array tmp = {{0}}; + llarp_buffer_t buf(tmp); + buf.put_uint16(priority); + if (EncodeNameTo(&buf, name)) { - if (not srv.IsValid()) - { - AddNXReply(); - return; - } - - answers.emplace_back(); - auto& rec = answers.back(); - rec.rr_name = question.qname; - rec.rr_type = qTypeSRV; - rec.rr_class = qClassIN; - rec.ttl = ttl; - - std::array tmp = {{0}}; - llarp_buffer_t buf(tmp); - - buf.put_uint16(srv.priority); - buf.put_uint16(srv.weight); - buf.put_uint16(srv.port); - - std::string target; - if (srv.target == "") - { - // get location of second dot (after service.proto) in qname - size_t pos = question.qname.find("."); - pos = question.qname.find(".", pos + 1); - - target = question.qname.substr(pos + 1); - } - else - { - target = srv.target; - } - - if (not EncodeNameTo(&buf, target)) - { - AddNXReply(); - return; - } - buf.sz = buf.cur - buf.base; rec.rData.resize(buf.sz); memcpy(rec.rData.data(), buf.base, buf.sz); } } + } + + void + Message::AddSRVReply(std::vector records, RR_TTL_t ttl) + { + hdr_fields = reply_flags(hdr_fields); + + const auto& question = questions[0]; - void - Message::AddTXTReply(std::string str, RR_TTL_t ttl) + for (const auto& srv : records) { - auto& rec = answers.emplace_back(); - rec.rr_name = questions[0].qname; + if (not srv.IsValid()) + { + AddNXReply(); + return; + } + + answers.emplace_back(); + auto& rec = answers.back(); + rec.rr_name = question.qname; + rec.rr_type = qTypeSRV; rec.rr_class = qClassIN; - rec.rr_type = qTypeTXT; rec.ttl = ttl; - std::array tmp{}; + + std::array tmp = {{0}}; llarp_buffer_t buf(tmp); - while (not str.empty()) + + buf.put_uint16(srv.priority); + buf.put_uint16(srv.weight); + buf.put_uint16(srv.port); + + std::string target; + if (srv.target == "") + { + // get location of second dot (after service.proto) in qname + size_t pos = question.qname.find("."); + pos = question.qname.find(".", pos + 1); + + target = question.qname.substr(pos + 1); + } + else { - const auto left = std::min(str.size(), size_t{256}); - const auto sub = str.substr(0, left); - uint8_t byte = left; - *buf.cur = byte; - buf.cur++; - if (not buf.write(sub.begin(), sub.end())) - throw std::length_error("text record too big"); - str = str.substr(left); + target = srv.target; } - buf.sz = buf.cur - buf.base; - rec.rData.resize(buf.sz); - std::copy_n(buf.base, buf.sz, rec.rData.data()); - } - void - Message::AddNXReply(RR_TTL_t) - { - if (questions.size()) + if (not EncodeNameTo(&buf, target)) { - answers.clear(); - authorities.clear(); - additional.clear(); - - // authorative response with recursion available - hdr_fields = reply_flags(hdr_fields); - // don't allow recursion on this request - hdr_fields &= ~flags_RD; - hdr_fields |= flags_RCODENameError; + AddNXReply(); + return; } + + buf.sz = buf.cur - buf.base; + rec.rData.resize(buf.sz); + memcpy(rec.rData.data(), buf.base, buf.sz); } + } - std::string - Message::ToString() const + void + Message::AddTXTReply(std::string str, RR_TTL_t ttl) + { + auto& rec = answers.emplace_back(); + rec.rr_name = questions[0].qname; + rec.rr_class = qClassIN; + rec.rr_type = qTypeTXT; + rec.ttl = ttl; + std::array tmp{}; + llarp_buffer_t buf(tmp); + while (not str.empty()) { - return fmt::format( - "[DNSMessage id={:x} fields={:x} questions={{{}}} answers={{{}}} authorities={{{}}} " - "additional={{{}}}]", - hdr_id, - hdr_fields, - fmt::format("{}", fmt::join(questions, ",")), - fmt::format("{}", fmt::join(answers, ",")), - fmt::format("{}", fmt::join(authorities, ",")), - fmt::format("{}", fmt::join(additional, ","))); + const auto left = std::min(str.size(), size_t{256}); + const auto sub = str.substr(0, left); + uint8_t byte = left; + *buf.cur = byte; + buf.cur++; + if (not buf.write(sub.begin(), sub.end())) + throw std::length_error("text record too big"); + str = str.substr(left); } + buf.sz = buf.cur - buf.base; + rec.rData.resize(buf.sz); + std::copy_n(buf.base, buf.sz, rec.rData.data()); + } - std::optional - MaybeParseDNSMessage(llarp_buffer_t buf) + void + Message::AddNXReply(RR_TTL_t) + { + if (questions.size()) { - MessageHeader hdr{}; - if (not hdr.Decode(&buf)) - return std::nullopt; - - Message msg{hdr}; - if (not msg.Decode(&buf)) - return std::nullopt; - return msg; + answers.clear(); + authorities.clear(); + additional.clear(); + + // authorative response with recursion available + hdr_fields = reply_flags(hdr_fields); + // don't allow recursion on this request + hdr_fields &= ~flags_RD; + hdr_fields |= flags_RCODENameError; } - } // namespace dns -} // namespace llarp + } + + std::string + Message::ToString() const + { + return fmt::format( + "[DNSMessage id={:x} fields={:x} questions={{{}}} answers={{{}}} authorities={{{}}} " + "additional={{{}}}]", + hdr_id, + hdr_fields, + fmt::format("{}", fmt::join(questions, ",")), + fmt::format("{}", fmt::join(answers, ",")), + fmt::format("{}", fmt::join(authorities, ",")), + fmt::format("{}", fmt::join(additional, ","))); + } + + std::optional + MaybeParseDNSMessage(llarp_buffer_t buf) + { + MessageHeader hdr{}; + if (not hdr.Decode(&buf)) + return std::nullopt; + + Message msg{hdr}; + if (not msg.Decode(&buf)) + return std::nullopt; + return msg; + } +} // namespace llarp::dns diff --git a/llarp/dns/name.cpp b/llarp/dns/name.cpp index 4d7363b1fb..e78a8cf9d2 100644 --- a/llarp/dns/name.cpp +++ b/llarp/dns/name.cpp @@ -1,139 +1,137 @@ #include "name.hpp" -#include + #include #include +#include #include -namespace llarp +namespace llarp::dns { - namespace dns + std::optional + DecodeName(llarp_buffer_t* buf, bool trimTrailingDot) { - std::optional - DecodeName(llarp_buffer_t* buf, bool trimTrailingDot) + if (buf->size_left() < 1) + return std::nullopt; + auto result = std::make_optional(); + auto& name = *result; + size_t l; + do { - if (buf->size_left() < 1) - return std::nullopt; - auto result = std::make_optional(); - auto& name = *result; - size_t l; - do + l = *buf->cur; + buf->cur++; + if (l) { - l = *buf->cur; - buf->cur++; - if (l) - { - if (buf->size_left() < l) - return std::nullopt; + if (buf->size_left() < l) + return std::nullopt; - name.append((const char*)buf->cur, l); - name += '.'; - } - buf->cur = buf->cur + l; - } while (l); - /// trim off last dot - if (trimTrailingDot) - name.pop_back(); - return result; - } + name.append((const char*)buf->cur, l); + name += '.'; + } + buf->cur = buf->cur + l; + } while (l); + /// trim off last dot + if (trimTrailingDot) + name.pop_back(); + return result; + } - bool - EncodeNameTo(llarp_buffer_t* buf, std::string_view name) - { - if (name.size() && name.back() == '.') - name.remove_suffix(1); + bool + EncodeNameTo(llarp_buffer_t* buf, std::string_view name) + { + if (name.size() && name.back() == '.') + name.remove_suffix(1); - for (auto part : llarp::split(name, ".")) + for (auto part : llarp::split(name, ".")) + { + size_t l = part.length(); + if (l > 63) + return false; + *(buf->cur) = l; + buf->cur++; + if (buf->size_left() < l) + return false; + if (l) { - size_t l = part.length(); - if (l > 63) - return false; - *(buf->cur) = l; - buf->cur++; - if (buf->size_left() < l) - return false; - if (l) - { - std::memcpy(buf->cur, part.data(), l); - buf->cur += l; - } - else - break; + std::memcpy(buf->cur, part.data(), l); + buf->cur += l; } - *buf->cur = 0; - buf->cur++; - return true; + else + break; } + *buf->cur = 0; + buf->cur++; + return true; + } - std::optional - DecodePTR(std::string_view name) + std::optional + DecodePTR(std::string_view name) + { + bool isV6 = false; + auto pos = name.find(".in-addr.arpa"); + if (pos == std::string::npos) { - bool isV6 = false; - auto pos = name.find(".in-addr.arpa"); - if (pos == std::string::npos) - { - pos = name.find(".ip6.arpa"); - isV6 = true; - } - if (pos == std::string::npos) - return std::nullopt; - name = name.substr(0, pos + 1); - const auto numdots = std::count(name.begin(), name.end(), '.'); - if (numdots == 4 && !isV6) + pos = name.find(".ip6.arpa"); + isV6 = true; + } + if (pos == std::string::npos) + return std::nullopt; + name = name.substr(0, pos + 1); + const auto numdots = std::count(name.begin(), name.end(), '.'); + if (numdots == 4 && !isV6) + { + std::array q; + for (int i = 3; i >= 0; i--) { - std::array q; - for (int i = 3; i >= 0; i--) - { - pos = name.find('.'); - if (!llarp::parse_int(name.substr(0, pos), q[i])) - return std::nullopt; - name.remove_prefix(pos + 1); - } - return net::ExpandV4(llarp::ipaddr_ipv4_bits(q[0], q[1], q[2], q[3])); + pos = name.find('.'); + if (!llarp::parse_int(name.substr(0, pos), q[i])) + return std::nullopt; + name.remove_prefix(pos + 1); } - if (numdots == 32 && name.size() == 64 && isV6) + return net::ExpandV4(llarp::ipaddr_ipv4_bits(q[0], q[1], q[2], q[3])); + } + if (numdots == 32 && name.size() == 64 && isV6) + { + // We're going to convert from nybbles a.b.c.d.e.f.0.1.2.3.[...] into hex string + // "badcfe1032...", then decode the hex string to bytes. + std::array in; + auto in_pos = in.data(); + for (size_t i = 0; i < 64; i += 4) { - // We're going to convert from nybbles a.b.c.d.e.f.0.1.2.3.[...] into hex string - // "badcfe1032...", then decode the hex string to bytes. - std::array in; - auto in_pos = in.data(); - for (size_t i = 0; i < 64; i += 4) - { - if (not(oxenc::is_hex_digit(name[i]) and name[i + 1] == '.' - and oxenc::is_hex_digit(name[i + 2]) and name[i + 3] == '.')) - return std::nullopt; + if (not(oxenc::is_hex_digit(name[i]) and name[i + 1] == '.' + and oxenc::is_hex_digit(name[i + 2]) and name[i + 3] == '.')) + return std::nullopt; - // Flip the nybbles because the smallest one is first - *in_pos++ = name[i + 2]; - *in_pos++ = name[i]; - } - assert(in_pos == in.data() + in.size()); - huint128_t ip; - static_assert(in.size() == 2 * sizeof(ip.h)); - // our string right now is the little endian representation, so load it as such on little - // endian, or in reverse on big endian. - if constexpr (oxenc::little_endian) - oxenc::from_hex(in.begin(), in.end(), reinterpret_cast(&ip.h)); - else - oxenc::from_hex(in.rbegin(), in.rend(), reinterpret_cast(&ip.h)); - - return ip; + // Flip the nybbles because the smallest one is first + *in_pos++ = name[i + 2]; + *in_pos++ = name[i]; } - return std::nullopt; + assert(in_pos == in.data() + in.size()); + huint128_t ip; + static_assert(in.size() == 2 * sizeof(ip.h)); + // our string right now is the little endian representation, so load it as such on little + // endian, or in reverse on big endian. + if constexpr (oxenc::little_endian) + oxenc::from_hex(in.begin(), in.end(), reinterpret_cast(&ip.h)); + else + oxenc::from_hex(in.rbegin(), in.rend(), reinterpret_cast(&ip.h)); + + return ip; } + return std::nullopt; + } - bool - NameIsReserved(std::string_view name) + bool + NameIsReserved(std::string_view name) + { + const std::vector reserved_names = { + ".snode.loki"sv, ".loki.loki"sv, ".snode.loki."sv, ".loki.loki."sv}; + for (const auto& reserved : reserved_names) { - const std::vector reserved_names = { - ".snode.loki"sv, ".loki.loki"sv, ".snode.loki."sv, ".loki.loki."sv}; - for (const auto& reserved : reserved_names) - { - if (ends_with(name, reserved)) // subdomain foo.loki.loki - return true; - if (name == reserved.substr(1)) // loki.loki itself - return true; - } - return false; + if (ends_with(name, reserved)) // subdomain foo.loki.loki + return true; + if (name == reserved.substr(1)) // loki.loki itself + return true; } - } // namespace dns -} // namespace llarp + return false; + } +} // namespace llarp::dns diff --git a/llarp/dns/name.hpp b/llarp/dns/name.hpp index 01e28a6360..718ebb0fc2 100644 --- a/llarp/dns/name.hpp +++ b/llarp/dns/name.hpp @@ -2,27 +2,23 @@ #include #include - #include #include -namespace llarp +namespace llarp::dns { - namespace dns - { - /// decode name from buffer; return nullopt on failure - std::optional - DecodeName(llarp_buffer_t* buf, bool trimTrailingDot = false); + /// decode name from buffer; return nullopt on failure + std::optional + DecodeName(llarp_buffer_t* buf, bool trimTrailingDot = false); - /// encode name to buffer - bool - EncodeNameTo(llarp_buffer_t* buf, std::string_view name); + /// encode name to buffer + bool + EncodeNameTo(llarp_buffer_t* buf, std::string_view name); - std::optional - DecodePTR(std::string_view name); + std::optional + DecodePTR(std::string_view name); - bool - NameIsReserved(std::string_view name); + bool + NameIsReserved(std::string_view name); - } // namespace dns -} // namespace llarp +} // namespace llarp::dns diff --git a/llarp/dns/platform.hpp b/llarp/dns/platform.hpp index 46fea1c132..e1db57ba18 100644 --- a/llarp/dns/platform.hpp +++ b/llarp/dns/platform.hpp @@ -1,8 +1,8 @@ #pragma once -#include -#include #include #include +#include +#include #include #ifndef _WIN32 diff --git a/llarp/dns/query.hpp b/llarp/dns/query.hpp deleted file mode 100644 index 6f70f09bee..0000000000 --- a/llarp/dns/query.hpp +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/llarp/dns/question.cpp b/llarp/dns/question.cpp index cd33b1d415..baa4c1d345 100644 --- a/llarp/dns/question.cpp +++ b/llarp/dns/question.cpp @@ -1,129 +1,126 @@ #include "question.hpp" -#include #include + #include "dns.hpp" -namespace llarp +namespace llarp::dns { - namespace dns + static auto logcat = log::Cat("dns"); + + Question::Question(Question&& other) + : qname(std::move(other.qname)) + , qtype(std::move(other.qtype)) + , qclass(std::move(other.qclass)) + {} + Question::Question(const Question& other) + : qname(other.qname), qtype(other.qtype), qclass(other.qclass) + {} + + Question::Question(std::string name, QType_t type) + : qname{std::move(name)}, qtype{type}, qclass{qClassIN} { - static auto logcat = log::Cat("dns"); - - Question::Question(Question&& other) - : qname(std::move(other.qname)) - , qtype(std::move(other.qtype)) - , qclass(std::move(other.qclass)) - {} - Question::Question(const Question& other) - : qname(other.qname), qtype(other.qtype), qclass(other.qclass) - {} - - Question::Question(std::string name, QType_t type) - : qname{std::move(name)}, qtype{type}, qclass{qClassIN} - { - if (qname.empty()) - throw std::invalid_argument{"qname cannot be empty"}; - } + if (qname.empty()) + throw std::invalid_argument{"qname cannot be empty"}; + } - bool - Question::Encode(llarp_buffer_t* buf) const + bool + Question::Encode(llarp_buffer_t* buf) const + { + if (!EncodeNameTo(buf, qname)) + return false; + if (!buf->put_uint16(qtype)) + return false; + return buf->put_uint16(qclass); + } + + bool + Question::Decode(llarp_buffer_t* buf) + { + if (auto name = DecodeName(buf)) + qname = *std::move(name); + else { - if (!EncodeNameTo(buf, qname)) - return false; - if (!buf->put_uint16(qtype)) - return false; - return buf->put_uint16(qclass); + log::error(logcat, "failed to decode name"); + return false; } - - bool - Question::Decode(llarp_buffer_t* buf) + if (!buf->read_uint16(qtype)) { - if (auto name = DecodeName(buf)) - qname = *std::move(name); - else - { - log::error(logcat, "failed to decode name"); - return false; - } - if (!buf->read_uint16(qtype)) - { - log::error(logcat, "failed to decode type"); - return false; - } - if (!buf->read_uint16(qclass)) - { - log::error(logcat, "failed to decode class"); - return false; - } - return true; + log::error(logcat, "failed to decode type"); + return false; } - - util::StatusObject - Question::ToJSON() const + if (!buf->read_uint16(qclass)) { - return util::StatusObject{{"qname", qname}, {"qtype", qtype}, {"qclass", qclass}}; + log::error(logcat, "failed to decode class"); + return false; } + return true; + } - bool - Question::IsName(const std::string& other) const - { - // does other have a . at the end? - if (other.find_last_of('.') == (other.size() - 1)) - return other == qname; - // no, add it and retry - return IsName(other + "."); - } + util::StatusObject + Question::ToJSON() const + { + return util::StatusObject{{"qname", qname}, {"qtype", qtype}, {"qclass", qclass}}; + } - bool - Question::IsLocalhost() const - { - return (qname == "localhost.loki." or llarp::ends_with(qname, ".localhost.loki.")); - } + bool + Question::IsName(const std::string& other) const + { + // does other have a . at the end? + if (other.find_last_of('.') == (other.size() - 1)) + return other == qname; + // no, add it and retry + return IsName(other + "."); + } + + bool + Question::IsLocalhost() const + { + return (qname == "localhost.loki." or llarp::ends_with(qname, ".localhost.loki.")); + } - bool - Question::HasSubdomains() const - { - const auto parts = split(qname, ".", true); - return parts.size() >= 3; - } + bool + Question::HasSubdomains() const + { + const auto parts = split(qname, ".", true); + return parts.size() >= 3; + } - std::string - Question::Subdomains() const - { - if (qname.size() < 2) - return ""; + std::string + Question::Subdomains() const + { + if (qname.size() < 2) + return ""; - size_t pos; + size_t pos; - pos = qname.rfind('.', qname.size() - 2); - if (pos == std::string::npos or pos == 0) - return ""; + pos = qname.rfind('.', qname.size() - 2); + if (pos == std::string::npos or pos == 0) + return ""; - pos = qname.rfind('.', pos - 1); - if (pos == std::string::npos or pos == 0) - return ""; + pos = qname.rfind('.', pos - 1); + if (pos == std::string::npos or pos == 0) + return ""; - return qname.substr(0, pos); - } + return qname.substr(0, pos); + } - std::string - Question::Name() const - { - return qname.substr(0, qname.find_last_of('.')); - } + std::string + Question::Name() const + { + return qname.substr(0, qname.find_last_of('.')); + } - bool - Question::HasTLD(const std::string& tld) const - { - return qname.find(tld) != std::string::npos - && qname.rfind(tld) == (qname.size() - tld.size()) - 1; - } + bool + Question::HasTLD(const std::string& tld) const + { + return qname.find(tld) != std::string::npos + && qname.rfind(tld) == (qname.size() - tld.size()) - 1; + } - std::string - Question::ToString() const - { - return fmt::format("[DNSQuestion qname={} qtype={:x} qclass={:x}]", qname, qtype, qclass); - } - } // namespace dns -} // namespace llarp + std::string + Question::ToString() const + { + return fmt::format("[DNSQuestion qname={} qtype={:x} qclass={:x}]", qname, qtype, qclass); + } +} // namespace llarp::dns diff --git a/llarp/dns/question.hpp b/llarp/dns/question.hpp index 4f0c2b10da..a5a1330e37 100644 --- a/llarp/dns/question.hpp +++ b/llarp/dns/question.hpp @@ -2,71 +2,69 @@ #include "serialize.hpp" #include "name.hpp" + #include -namespace llarp +namespace llarp::dns { - namespace dns - { - using QType_t = uint16_t; - using QClass_t = uint16_t; + using QType_t = uint16_t; + using QClass_t = uint16_t; - struct Question : public Serialize - { - Question() = default; + struct Question : public Serialize + { + Question() = default; - explicit Question(std::string name, QType_t type); + explicit Question(std::string name, QType_t type); - Question(Question&& other); - Question(const Question& other); - bool - Encode(llarp_buffer_t* buf) const override; + Question(Question&& other); + Question(const Question& other); + bool + Encode(llarp_buffer_t* buf) const override; - bool - Decode(llarp_buffer_t* buf) override; + bool + Decode(llarp_buffer_t* buf) override; - std::string - ToString() const; + std::string + ToString() const; - bool - operator==(const Question& other) const - { - return qname == other.qname && qtype == other.qtype && qclass == other.qclass; - } + bool + operator==(const Question& other) const + { + return qname == other.qname && qtype == other.qtype && qclass == other.qclass; + } - std::string qname; - QType_t qtype; - QClass_t qclass; + std::string qname; + QType_t qtype; + QClass_t qclass; - /// determine if we match a name - bool - IsName(const std::string& other) const; + /// determine if we match a name + bool + IsName(const std::string& other) const; - /// is the name [something.]localhost.loki. ? - bool - IsLocalhost() const; + /// is the name [something.]localhost.loki. ? + bool + IsLocalhost() const; - /// return true if we have subdomains in ths question - bool - HasSubdomains() const; + /// return true if we have subdomains in ths question + bool + HasSubdomains() const; - /// get subdomain(s), if any, from qname - std::string - Subdomains() const; + /// get subdomain(s), if any, from qname + std::string + Subdomains() const; - /// return qname with no trailing . - std::string - Name() const; + /// return qname with no trailing . + std::string + Name() const; - /// determine if we are using this TLD - bool - HasTLD(const std::string& tld) const; + /// determine if we are using this TLD + bool + HasTLD(const std::string& tld) const; - util::StatusObject - ToJSON() const override; - }; - } // namespace dns -} // namespace llarp + util::StatusObject + ToJSON() const override; + }; +} // namespace llarp::dns template <> constexpr inline bool llarp::IsToStringFormattable = true; diff --git a/llarp/dns/rr.cpp b/llarp/dns/rr.cpp index 8851ace305..5cdb4cdc0d 100644 --- a/llarp/dns/rr.cpp +++ b/llarp/dns/rr.cpp @@ -1,125 +1,116 @@ #include "rr.hpp" + #include "dns.hpp" -#include -#include -#include -namespace llarp +namespace llarp::dns { - namespace dns - { - static auto logcat = log::Cat("dns"); + static auto logcat = log::Cat("dns"); - ResourceRecord::ResourceRecord(const ResourceRecord& other) - : rr_name(other.rr_name) - , rr_type(other.rr_type) - , rr_class(other.rr_class) - , ttl(other.ttl) - , rData(other.rData) - {} + ResourceRecord::ResourceRecord(const ResourceRecord& other) + : rr_name(other.rr_name) + , rr_type(other.rr_type) + , rr_class(other.rr_class) + , ttl(other.ttl) + , rData(other.rData) + {} - ResourceRecord::ResourceRecord(ResourceRecord&& other) - : rr_name(std::move(other.rr_name)) - , rr_type(std::move(other.rr_type)) - , rr_class(std::move(other.rr_class)) - , ttl(std::move(other.ttl)) - , rData(std::move(other.rData)) - {} + ResourceRecord::ResourceRecord(ResourceRecord&& other) + : rr_name(std::move(other.rr_name)) + , rr_type(std::move(other.rr_type)) + , rr_class(std::move(other.rr_class)) + , ttl(std::move(other.ttl)) + , rData(std::move(other.rData)) + {} - ResourceRecord::ResourceRecord(std::string name, RRType_t type, RR_RData_t data) - : rr_name{std::move(name)} - , rr_type{type} - , rr_class{qClassIN} - , ttl{1} - , rData{std::move(data)} - {} + ResourceRecord::ResourceRecord(std::string name, RRType_t type, RR_RData_t data) + : rr_name{std::move(name)}, rr_type{type}, rr_class{qClassIN}, ttl{1}, rData{std::move(data)} + {} - bool - ResourceRecord::Encode(llarp_buffer_t* buf) const + bool + ResourceRecord::Encode(llarp_buffer_t* buf) const + { + if (not EncodeNameTo(buf, rr_name)) + return false; + if (!buf->put_uint16(rr_type)) { - if (not EncodeNameTo(buf, rr_name)) - return false; - if (!buf->put_uint16(rr_type)) - { - return false; - } - if (!buf->put_uint16(rr_class)) - { - return false; - } - if (!buf->put_uint32(ttl)) - { - return false; - } - if (!EncodeRData(buf, rData)) - { - return false; - } - return true; + return false; } - - bool - ResourceRecord::Decode(llarp_buffer_t* buf) + if (!buf->put_uint16(rr_class)) { - uint16_t discard; - if (!buf->read_uint16(discard)) - return false; - if (!buf->read_uint16(rr_type)) - { - log::debug(logcat, "failed to decode rr type"); - return false; - } - if (!buf->read_uint16(rr_class)) - { - log::debug(logcat, "failed to decode rr class"); - return false; - } - if (!buf->read_uint32(ttl)) - { - log::debug(logcat, "failed to decode ttl"); - return false; - } - if (!DecodeRData(buf, rData)) - { - log::debug(logcat, "failed to decode rr rdata {}", *this); - return false; - } - return true; + return false; } - - util::StatusObject - ResourceRecord::ToJSON() const + if (!buf->put_uint32(ttl)) { - return util::StatusObject{ - {"name", rr_name}, - {"type", rr_type}, - {"class", rr_class}, - {"ttl", ttl}, - {"rdata", std::string{reinterpret_cast(rData.data()), rData.size()}}}; + return false; } - - std::string - ResourceRecord::ToString() const + if (!EncodeRData(buf, rData)) { - return fmt::format( - "[RR name={} type={} class={} ttl={} rdata-size={}]", - rr_name, - rr_type, - rr_class, - ttl, - rData.size()); + return false; } + return true; + } - bool - ResourceRecord::HasCNameForTLD(const std::string& tld) const + bool + ResourceRecord::Decode(llarp_buffer_t* buf) + { + uint16_t discard; + if (!buf->read_uint16(discard)) + return false; + if (!buf->read_uint16(rr_type)) { - if (rr_type != qTypeCNAME) - return false; - llarp_buffer_t buf(rData); - if (auto name = DecodeName(&buf)) - return name->rfind(tld) == name->size() - tld.size() - 1; + log::debug(logcat, "failed to decode rr type"); return false; } + if (!buf->read_uint16(rr_class)) + { + log::debug(logcat, "failed to decode rr class"); + return false; + } + if (!buf->read_uint32(ttl)) + { + log::debug(logcat, "failed to decode ttl"); + return false; + } + if (!DecodeRData(buf, rData)) + { + log::debug(logcat, "failed to decode rr rdata {}", *this); + return false; + } + return true; + } + + util::StatusObject + ResourceRecord::ToJSON() const + { + return util::StatusObject{ + {"name", rr_name}, + {"type", rr_type}, + {"class", rr_class}, + {"ttl", ttl}, + {"rdata", std::string{reinterpret_cast(rData.data()), rData.size()}}}; + } + + std::string + ResourceRecord::ToString() const + { + return fmt::format( + "[RR name={} type={} class={} ttl={} rdata-size={}]", + rr_name, + rr_type, + rr_class, + ttl, + rData.size()); + } + + bool + ResourceRecord::HasCNameForTLD(const std::string& tld) const + { + if (rr_type != qTypeCNAME) + return false; + llarp_buffer_t buf(rData); + if (auto name = DecodeName(&buf)) + return name->rfind(tld) == name->size() - tld.size() - 1; + return false; + } - } // namespace dns -} // namespace llarp +} // namespace llarp::dns diff --git a/llarp/dns/rr.hpp b/llarp/dns/rr.hpp index 7bf290312c..b1c0b152c9 100644 --- a/llarp/dns/rr.hpp +++ b/llarp/dns/rr.hpp @@ -1,52 +1,49 @@ #pragma once -#include "name.hpp" -#include "serialize.hpp" #include - #include #include -namespace llarp +#include "name.hpp" +#include "serialize.hpp" + +namespace llarp::dns { - namespace dns + using RRClass_t = uint16_t; + using RRType_t = uint16_t; + using RR_RData_t = std::vector; + using RR_TTL_t = uint32_t; + + struct ResourceRecord : public Serialize { - using RRClass_t = uint16_t; - using RRType_t = uint16_t; - using RR_RData_t = std::vector; - using RR_TTL_t = uint32_t; - - struct ResourceRecord : public Serialize - { - ResourceRecord() = default; - ResourceRecord(const ResourceRecord& other); - ResourceRecord(ResourceRecord&& other); - - explicit ResourceRecord(std::string name, RRType_t type, RR_RData_t rdata); - - bool - Encode(llarp_buffer_t* buf) const override; - - bool - Decode(llarp_buffer_t* buf) override; - - util::StatusObject - ToJSON() const override; - - std::string - ToString() const; - - bool - HasCNameForTLD(const std::string& tld) const; - - std::string rr_name; - RRType_t rr_type; - RRClass_t rr_class; - RR_TTL_t ttl; - RR_RData_t rData; - }; - } // namespace dns -} // namespace llarp + ResourceRecord() = default; + ResourceRecord(const ResourceRecord& other); + ResourceRecord(ResourceRecord&& other); + + explicit ResourceRecord(std::string name, RRType_t type, RR_RData_t rdata); + + bool + Encode(llarp_buffer_t* buf) const override; + + bool + Decode(llarp_buffer_t* buf) override; + + util::StatusObject + ToJSON() const override; + + std::string + ToString() const; + + bool + HasCNameForTLD(const std::string& tld) const; + + std::string rr_name; + RRType_t rr_type; + RRClass_t rr_class; + RR_TTL_t ttl; + RR_RData_t rData; + }; +} // namespace llarp::dns template <> constexpr inline bool llarp::IsToStringFormattable = true; diff --git a/llarp/dns/serialize.cpp b/llarp/dns/serialize.cpp index 6f9d25c75f..54fa3b1f11 100644 --- a/llarp/dns/serialize.cpp +++ b/llarp/dns/serialize.cpp @@ -1,44 +1,40 @@ #include "serialize.hpp" -#include -namespace llarp +namespace llarp::dns { - namespace dns + Serialize::~Serialize() = default; + + bool + EncodeRData(llarp_buffer_t* buf, const std::vector& v) { - Serialize::~Serialize() = default; + if (v.size() > 65536) + return false; + uint16_t len = v.size(); + if (!buf->put_uint16(len)) + return false; + if (buf->size_left() < len) + return false; + memcpy(buf->cur, v.data(), len); + buf->cur += len; + return true; + } - bool - EncodeRData(llarp_buffer_t* buf, const std::vector& v) + bool + DecodeRData(llarp_buffer_t* buf, std::vector& v) + { + uint16_t len; + if (!buf->read_uint16(len)) + return false; + size_t left = buf->size_left(); + if (left < len) + return false; + v.resize(size_t(len)); + if (len) { - if (v.size() > 65536) - return false; - uint16_t len = v.size(); - if (!buf->put_uint16(len)) - return false; - if (buf->size_left() < len) - return false; - memcpy(buf->cur, v.data(), len); + memcpy(v.data(), buf->cur, len); buf->cur += len; - return true; - } - - bool - DecodeRData(llarp_buffer_t* buf, std::vector& v) - { - uint16_t len; - if (!buf->read_uint16(len)) - return false; - size_t left = buf->size_left(); - if (left < len) - return false; - v.resize(size_t(len)); - if (len) - { - memcpy(v.data(), buf->cur, len); - buf->cur += len; - } - return true; } + return true; + } - } // namespace dns -} // namespace llarp +} // namespace llarp::dns diff --git a/llarp/dns/serialize.hpp b/llarp/dns/serialize.hpp index 94388362a1..5ae8d15fc5 100644 --- a/llarp/dns/serialize.hpp +++ b/llarp/dns/serialize.hpp @@ -4,33 +4,30 @@ #include #include -namespace llarp +namespace llarp::dns { - namespace dns + /// base type for serializable dns entities + struct Serialize { - /// base type for serializable dns entities - struct Serialize - { - virtual ~Serialize() = 0; + virtual ~Serialize() = 0; - /// encode entity to buffer - virtual bool - Encode(llarp_buffer_t* buf) const = 0; + /// encode entity to buffer + virtual bool + Encode(llarp_buffer_t* buf) const = 0; - /// decode entity from buffer - virtual bool - Decode(llarp_buffer_t* buf) = 0; + /// decode entity from buffer + virtual bool + Decode(llarp_buffer_t* buf) = 0; - /// convert this whatever into json - virtual util::StatusObject - ToJSON() const = 0; - }; + /// convert this whatever into json + virtual util::StatusObject + ToJSON() const = 0; + }; - bool - EncodeRData(llarp_buffer_t* buf, const std::vector& rdata); + bool + EncodeRData(llarp_buffer_t* buf, const std::vector& rdata); - bool - DecodeRData(llarp_buffer_t* buf, std::vector& rdata); + bool + DecodeRData(llarp_buffer_t* buf, std::vector& rdata); - } // namespace dns -} // namespace llarp +} // namespace llarp::dns diff --git a/llarp/dns/server.cpp b/llarp/dns/server.cpp index 10ed944769..995f10a5d7 100644 --- a/llarp/dns/server.cpp +++ b/llarp/dns/server.cpp @@ -1,22 +1,20 @@ #include "server.hpp" + #include #include -#include "dns.hpp" -#include -#include -#include +#include +#include #include #include -#include #include #include -#include -#include #include "oxen/log.hpp" #include "sd_platform.hpp" #include "nm_platform.hpp" +#include + namespace llarp::dns { static auto logcat = log::Cat("dns"); diff --git a/llarp/dns/server.hpp b/llarp/dns/server.hpp index f39b017e4b..d4baef55cd 100644 --- a/llarp/dns/server.hpp +++ b/llarp/dns/server.hpp @@ -1,7 +1,5 @@ #pragma once -#include "message.hpp" -#include "platform.hpp" #include #include #include @@ -9,6 +7,9 @@ #include #include +#include "message.hpp" +#include "platform.hpp" + namespace llarp::dns { /// a job handling 1 dns query diff --git a/llarp/dns/srv_data.cpp b/llarp/dns/srv_data.cpp index 42f84479af..d5189856ad 100644 --- a/llarp/dns/srv_data.cpp +++ b/llarp/dns/srv_data.cpp @@ -1,12 +1,10 @@ #include "srv_data.hpp" -#include -#include - -#include #include -#include "llarp/util/bencode.h" -#include "llarp/util/types.hpp" + +#include +#include +#include namespace llarp::dns { diff --git a/llarp/dns/srv_data.hpp b/llarp/dns/srv_data.hpp index bcba9b672c..59b2603093 100644 --- a/llarp/dns/srv_data.hpp +++ b/llarp/dns/srv_data.hpp @@ -1,11 +1,11 @@ #pragma once -#include "name.hpp" -#include "serialize.hpp" - #include #include +#include "dns.hpp" +#include "name.hpp" +#include "serialize.hpp" #include "llarp/util/status.hpp" namespace llarp::dns diff --git a/llarp/dns/string.hpp b/llarp/dns/string.hpp index f32503d3f8..871eb3bf64 100644 --- a/llarp/dns/string.hpp +++ b/llarp/dns/string.hpp @@ -4,19 +4,16 @@ struct llarp_buffer_t; -namespace llarp +namespace llarp::dns { - namespace dns - { - using name_t = std::string; + using name_t = std::string; - /// decode name from buffer - bool - decode_name(llarp_buffer_t* buf, name_t& name); + /// decode name from buffer + bool + decode_name(llarp_buffer_t* buf, name_t& name); - /// encode name to buffer - bool - encode_name(llarp_buffer_t* buf, const name_t& name); + /// encode name to buffer + bool + encode_name(llarp_buffer_t* buf, const name_t& name); - } // namespace dns -} // namespace llarp +} // namespace llarp::dns diff --git a/llarp/endpoint_base.hpp b/llarp/endpoint_base.hpp index 68144935e3..a6629f7b4a 100644 --- a/llarp/endpoint_base.hpp +++ b/llarp/endpoint_base.hpp @@ -1,14 +1,7 @@ #pragma once -#include "llarp/service/address.hpp" -#include "llarp/service/convotag.hpp" -#include "llarp/service/protocol_type.hpp" -#include "router_id.hpp" -#include "llarp/ev/ev.hpp" -#include "llarp/dns/srv_data.hpp" - #include - +#include #include #include #include @@ -16,8 +9,14 @@ #include #include #include + +#include "llarp/service/address.hpp" +#include "llarp/service/convotag.hpp" +#include "llarp/service/protocol_type.hpp" +#include "router_id.hpp" +#include "llarp/ev/ev.hpp" +#include "llarp/dns/srv_data.hpp" #include "oxenc/variant.h" -#include namespace llarp { diff --git a/llarp/ev/ev.cpp b/llarp/ev/ev.cpp index 8170c8a829..04362f41b0 100644 --- a/llarp/ev/ev.cpp +++ b/llarp/ev/ev.cpp @@ -1,13 +1,9 @@ #include "ev.hpp" -#include -#include +#include #include -#include -#include #include "libuv.hpp" -#include namespace llarp { diff --git a/llarp/ev/libuv.cpp b/llarp/ev/libuv.cpp index ce9e573ed4..e76e58611c 100644 --- a/llarp/ev/libuv.cpp +++ b/llarp/ev/libuv.cpp @@ -1,13 +1,13 @@ #include "libuv.hpp" + +#include +#include + #include #include #include #include -#include -#include -#include - #include namespace llarp::uv diff --git a/llarp/ev/libuv.hpp b/llarp/ev/libuv.hpp index 32e8010ca7..d83865de14 100644 --- a/llarp/ev/libuv.hpp +++ b/llarp/ev/libuv.hpp @@ -1,18 +1,17 @@ #pragma once -#include "ev.hpp" -#include "udp_handle.hpp" #include #include - #include #include #include #include - #include #include #include +#include "ev.hpp" +#include "udp_handle.hpp" + namespace llarp::uv { class UVWakeup; diff --git a/llarp/exit/context.hpp b/llarp/exit/context.hpp index 7c12f60533..923106ebde 100644 --- a/llarp/exit/context.hpp +++ b/llarp/exit/context.hpp @@ -1,10 +1,10 @@ #pragma once -#include "policy.hpp" #include - #include #include +#include "policy.hpp" + namespace llarp::exit { /// owner of all the exit endpoints diff --git a/llarp/exit/endpoint.hpp b/llarp/exit/endpoint.hpp index 7405ce1f9b..547e697abd 100644 --- a/llarp/exit/endpoint.hpp +++ b/llarp/exit/endpoint.hpp @@ -5,7 +5,6 @@ #include #include #include - #include namespace llarp diff --git a/llarp/exit/session.cpp b/llarp/exit/session.cpp index a168354a3d..9ec25d57b1 100644 --- a/llarp/exit/session.cpp +++ b/llarp/exit/session.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include namespace llarp::exit diff --git a/llarp/exit/session.hpp b/llarp/exit/session.hpp index db4484cabf..a95f2baf4c 100644 --- a/llarp/exit/session.hpp +++ b/llarp/exit/session.hpp @@ -4,7 +4,6 @@ #include #include #include - #include #include diff --git a/llarp/handlers/exit.cpp b/llarp/handlers/exit.cpp index 1432f5b26e..a82c1fc728 100644 --- a/llarp/handlers/exit.cpp +++ b/llarp/handlers/exit.cpp @@ -4,20 +4,16 @@ #include #include #include -#include -#include - #include - -#include #include +#include namespace llarp::handlers { ExitEndpoint::ExitEndpoint(std::string name, Router* r) : router(r) , name(std::move(name)) - , tunnel_manager{std::make_shared(*this)} + // , tunnel_manager{std::make_shared(*this)} { should_init_tun = true; } @@ -784,7 +780,8 @@ namespace llarp::handlers link::TunnelManager* ExitEndpoint::GetQUICTunnel() { - return tunnel_manager.get(); + return nullptr; + // return tunnel_manager.get(); } bool diff --git a/llarp/handlers/exit.hpp b/llarp/handlers/exit.hpp index 84365a2bcc..8354bdb93c 100644 --- a/llarp/handlers/exit.hpp +++ b/llarp/handlers/exit.hpp @@ -1,10 +1,11 @@ #pragma once #include -#include "tun.hpp" #include #include +#include "tun.hpp" + namespace llarp { struct Router; @@ -226,7 +227,7 @@ namespace llarp SockAddr resolver_addr; std::vector upstream_resolvers; - std::shared_ptr tunnel_manager; + // std::shared_ptr tunnel_manager; using PacketQueue_t = std:: priority_queue, net::IPPacket::CompareOrder>; diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index cd9ee3876d..80aca87ff8 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -1,11 +1,10 @@ #include #include #include + #include "tun.hpp" -#include #ifndef _WIN32 #include -#include #endif #include @@ -16,20 +15,13 @@ #include #include #include -#include #include #include -#include #include #include #include -#include -#include -#include #include -#include - namespace llarp::handlers { static auto logcat = log::Cat("tun"); diff --git a/llarp/handlers/tun.hpp b/llarp/handlers/tun.hpp index f4241d9014..846e11dd24 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -11,7 +11,6 @@ #include #include #include - #include #include #include diff --git a/llarp/link/connection.hpp b/llarp/link/connection.hpp index 7fae51b4e8..69f88896bd 100644 --- a/llarp/link/connection.hpp +++ b/llarp/link/connection.hpp @@ -2,7 +2,6 @@ #include #include - #include namespace llarp::link diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 69729db2e1..dbfabbd3b9 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -463,11 +463,6 @@ namespace llarp return; } - // TODO: do we still need this concept? - void - LinkManager::update_peer_db(std::shared_ptr) - {} - // TODO: this util::StatusObject LinkManager::extract_status() const diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index e57190cf79..6788447b87 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -1,23 +1,19 @@ #pragma once -#include "connection.hpp" #include #include - #include #include -#include #include #include - #include - +#include +#include #include #include #include -#include -#include +#include "connection.hpp" namespace { @@ -264,9 +260,6 @@ namespace llarp void check_persisting_conns(llarp_time_t now); - void - update_peer_db(std::shared_ptr peerDb); - util::StatusObject extract_status() const; diff --git a/llarp/link/tunnel.hpp b/llarp/link/tunnel.hpp index 825e77b021..4825af186e 100644 --- a/llarp/link/tunnel.hpp +++ b/llarp/link/tunnel.hpp @@ -20,7 +20,7 @@ namespace llarp namespace llarp::link { - struct Endpoint; + // struct Endpoint; using namespace std::chrono_literals; @@ -153,7 +153,7 @@ namespace llarp::link struct ClientTunnel { // quic endpoint - std::unique_ptr client; + // std::unique_ptr client; // Callback to invoke on quic connection established (true argument) or failed (false arg) OpenCallback open_cb; // TCP listening socket @@ -164,7 +164,28 @@ namespace llarp::link // because we are still handshaking, or we reached the stream limit). std::queue> pending_incoming; - ~ClientTunnel(); + ~ClientTunnel() + { + // if (tcp) + // { + // tcp->close(); + // tcp->data(nullptr); + // tcp.reset(); + // } + // for (auto& conn : conns) + // conn->close(); + // conns.clear(); + + // while (not pending_incoming.empty()) + // { + // if (auto tcp = pending_incoming.front().lock()) + // { + // tcp->clear(); + // tcp->close(); + // } + // pending_incoming.pop(); + // } + } }; // pseudo-port -> Client instance (the "port" is used to route incoming quic packets to the diff --git a/llarp/messages/link_intro.cpp b/llarp/messages/link_intro.cpp deleted file mode 100644 index fd8b96278e..0000000000 --- a/llarp/messages/link_intro.cpp +++ /dev/null @@ -1,162 +0,0 @@ -#include -#include -#include -#include -#include - -#include - -namespace llarp -{ - bool - LinkIntroMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) - { - if (key.startswith("a")) - { - llarp_buffer_t strbuf; - if (!bencode_read_string(buf, &strbuf)) - return false; - if (strbuf.sz != 1) - return false; - return *strbuf.cur == 'i'; - } - if (key.startswith("n")) - { - if (nonce.BDecode(buf)) - return true; - llarp::LogWarn("failed to decode nonce in LIM"); - return false; - } - if (key.startswith("p")) - { - return bencode_read_integer(buf, &session_period); - } - if (key.startswith("r")) - { - if (rc.BDecode(buf)) - return true; - llarp::LogWarn("failed to decode RC in LIM"); - llarp::DumpBuffer(*buf); - return false; - } - if (key.startswith("v")) - { - if (!bencode_read_integer(buf, &version)) - return false; - if (version != llarp::constants::proto_version) - { - llarp::LogWarn( - "llarp protocol version mismatch ", version, " != ", llarp::constants::proto_version); - return false; - } - llarp::LogDebug("LIM version ", version); - return true; - } - if (key.startswith("z")) - { - return sig.BDecode(buf); - } - - llarp::LogWarn("invalid LIM key: ", *key.cur); - return false; - } - - std::string - LinkIntroMessage::bt_encode() const - { - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("a", "i"); - btdp.append("n", nonce.ToView()); - btdp.append("p", session_period); - - { - auto subdict = btdp.append_list("r"); - rc.bt_encode_subdict(subdict); - } - - btdp.append("v", llarp::constants::proto_version); - btdp.append("z", sig.ToView()); - } - catch (...) - { - log::critical(link_cat, "Error: LinkIntroMessage failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - - bool - LinkIntroMessage::handle_message(Router* /*router*/) const - { - if (!verify()) - return false; - return true; - // return conn->GotLIM(this); - } - - void - LinkIntroMessage::clear() - { - session_period = 0; - nonce.Zero(); - rc.Clear(); - sig.Zero(); - version = 0; - } - - bool - LinkIntroMessage::sign(std::function signer) - { - sig.Zero(); - // need to keep this as a llarp_buffer_t for now, as all the crypto code expects - // byte_t types -- fix this later - std::array tmp; - llarp_buffer_t buf(tmp); - - auto bte = bt_encode(); - buf.write(bte.begin(), bte.end()); - - buf.sz = buf.cur - buf.base; - buf.cur = buf.base; - - return signer(sig, buf); - } - - bool - LinkIntroMessage::verify() const - { - LinkIntroMessage copy; - copy = *this; - copy.sig.Zero(); - - // need to keep this as a llarp_buffer_t for now, as all the crypto code expects - // byte_t types -- fix this later - std::array tmp; - llarp_buffer_t buf(tmp); - - auto bte = copy.bt_encode(); - buf.write(bte.begin(), bte.end()); - - buf.sz = buf.cur - buf.base; - buf.cur = buf.base; - - // outer signature - if (!CryptoManager::instance()->verify( - rc.pubkey, reinterpret_cast(bte.data()), bte.size(), sig)) - { - log::error(link_cat, "Error: outer signature failed!"); - return false; - } - // verify RC - if (!rc.Verify(llarp::time_now_ms())) - { - log::error(link_cat, "Error: invalid RC in link intro!"); - return false; - } - return true; - } - -} // namespace llarp diff --git a/llarp/messages/relay.hpp b/llarp/messages/relay.hpp index f2202bd1a6..22cbb162fe 100644 --- a/llarp/messages/relay.hpp +++ b/llarp/messages/relay.hpp @@ -2,11 +2,11 @@ #include #include -#include "link_message.hpp" #include - #include +#include "link_message.hpp" + namespace llarp { /* diff --git a/llarp/net/exit_info.cpp b/llarp/net/exit_info.cpp index 4d28de57e5..20b8cce983 100644 --- a/llarp/net/exit_info.cpp +++ b/llarp/net/exit_info.cpp @@ -2,15 +2,11 @@ #include #endif -#include "exit_info.hpp" -#include "net.hpp" #include -#include -#include - -#include #include +#include "exit_info.hpp" + namespace llarp { bool diff --git a/llarp/net/exit_info.hpp b/llarp/net/exit_info.hpp index b190ec9e01..0ea3fac34e 100644 --- a/llarp/net/exit_info.hpp +++ b/llarp/net/exit_info.hpp @@ -1,11 +1,11 @@ #pragma once #include -#include "ip_address.hpp" #include - #include +#include "ip_address.hpp" + /** * exit_info.h * diff --git a/llarp/net/interface_info.hpp b/llarp/net/interface_info.hpp index a603b03bd3..107f7bf901 100644 --- a/llarp/net/interface_info.hpp +++ b/llarp/net/interface_info.hpp @@ -1,9 +1,10 @@ #pragma once +#include #include #include #include -#include + #include "ip_range.hpp" namespace llarp::net diff --git a/llarp/net/ip.hpp b/llarp/net/ip.hpp index 307e5ffe23..6eb60ea4ed 100644 --- a/llarp/net/ip.hpp +++ b/llarp/net/ip.hpp @@ -1,5 +1,7 @@ #pragma once + #include "net_int.hpp" + #include namespace llarp::net diff --git a/llarp/net/ip_address.cpp b/llarp/net/ip_address.cpp index 3503ff7c79..741c0b3443 100644 --- a/llarp/net/ip_address.cpp +++ b/llarp/net/ip_address.cpp @@ -1,6 +1,5 @@ #include "ip_address.hpp" - -#include "net.hpp" +#include "ip_range.hpp" namespace llarp { diff --git a/llarp/net/ip_address.hpp b/llarp/net/ip_address.hpp index e0a8f477f8..1730008fda 100644 --- a/llarp/net/ip_address.hpp +++ b/llarp/net/ip_address.hpp @@ -1,15 +1,13 @@ #pragma once -#include "sock_addr.hpp" - +#include #include #include #include +#include "sock_addr.hpp" #include "net_int.hpp" -#include - namespace llarp { /// A struct that can represent either an IPv4 or IPv6 address. It is meant for representation diff --git a/llarp/net/ip_packet.cpp b/llarp/net/ip_packet.cpp index c9bed51e9b..2065e6929e 100644 --- a/llarp/net/ip_packet.cpp +++ b/llarp/net/ip_packet.cpp @@ -1,17 +1,16 @@ #include "ip_packet.hpp" -#include "ip.hpp" + #include #include -#include #include + +#include "ip.hpp" #ifndef _WIN32 #include #endif #include - #include -#include namespace llarp::net { diff --git a/llarp/net/ip_packet.hpp b/llarp/net/ip_packet.hpp index 1f01e6865a..f381873952 100644 --- a/llarp/net/ip_packet.hpp +++ b/llarp/net/ip_packet.hpp @@ -2,13 +2,14 @@ #include #include -#include "net.hpp" #include #include -#include #include +#include #include +#include "net.hpp" + namespace llarp::net { struct ip_header_le diff --git a/llarp/net/ip_range.hpp b/llarp/net/ip_range.hpp index 20e5e87cf0..8c5d7aaed6 100644 --- a/llarp/net/ip_range.hpp +++ b/llarp/net/ip_range.hpp @@ -1,19 +1,19 @@ #pragma once -#include "ip.hpp" -#include "net_bits.hpp" #include #include #include #include #include #include - #include #include #include #include +#include "ip.hpp" +#include "net_bits.hpp" + namespace { static auto net_cat = llarp::log::Cat("lokinet.net"); diff --git a/llarp/net/net_bits.hpp b/llarp/net/net_bits.hpp index d362975931..426c269508 100644 --- a/llarp/net/net_bits.hpp +++ b/llarp/net/net_bits.hpp @@ -1,4 +1,6 @@ #pragma once + +#include "ip.hpp" #include "net_int.hpp" namespace llarp diff --git a/llarp/net/net_if.hpp b/llarp/net/net_if.hpp index 15e059db22..686213d4b6 100644 --- a/llarp/net/net_if.hpp +++ b/llarp/net/net_if.hpp @@ -14,6 +14,8 @@ if_nametoindex(const char* __ifname) __THROW; #endif #endif +#include + namespace llarp::net { /// get the name of the loopback interface diff --git a/llarp/net/net_int.hpp b/llarp/net/net_int.hpp index 9bb545107d..447dc4e320 100644 --- a/llarp/net/net_int.hpp +++ b/llarp/net/net_int.hpp @@ -8,18 +8,17 @@ #else #include #include + #define inet_aton(x, y) inet_pton(AF_INET, x, y) #endif -#include "net.h" - +#include +#include #include // for itoa #include #include -#include -#include - +#include "net.h" #include "uint128.hpp" namespace llarp diff --git a/llarp/net/posix.cpp b/llarp/net/posix.cpp index 6bc764a0b1..e20243d202 100644 --- a/llarp/net/posix.cpp +++ b/llarp/net/posix.cpp @@ -1,14 +1,8 @@ -#include "net.hpp" -#include "net_if.hpp" #include -#include - -#include -#include "ip.hpp" +#include "net.hpp" +#include "net_if.hpp" #include "ip_range.hpp" -#include -#include #ifdef ANDROID #include @@ -16,9 +10,7 @@ #include #endif -#include #include -#include namespace llarp::net { diff --git a/llarp/net/sock_addr.cpp b/llarp/net/sock_addr.cpp index 17f1868564..5f25830e01 100644 --- a/llarp/net/sock_addr.cpp +++ b/llarp/net/sock_addr.cpp @@ -1,14 +1,13 @@ #include "sock_addr.hpp" + +#include +#include +#include + #include "ip_range.hpp" #include "ip.hpp" #include "net_bits.hpp" #include "net.hpp" -#include -#include -#include - -#include -#include namespace llarp { diff --git a/llarp/net/sock_addr.hpp b/llarp/net/sock_addr.hpp index 753519892f..b44d49f1cc 100644 --- a/llarp/net/sock_addr.hpp +++ b/llarp/net/sock_addr.hpp @@ -9,11 +9,12 @@ #include #endif +#include +#include #include #include + #include "net_int.hpp" -#include -#include namespace llarp { diff --git a/llarp/net/traffic_policy.hpp b/llarp/net/traffic_policy.hpp index dbfc52b76c..ebdaa539d9 100644 --- a/llarp/net/traffic_policy.hpp +++ b/llarp/net/traffic_policy.hpp @@ -1,13 +1,12 @@ #pragma once +#include +#include + #include "ip_range.hpp" #include "ip_packet.hpp" #include "llarp/util/status.hpp" -#include - -#include - namespace llarp::net { /// information about an IP protocol diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index 0bcbefa6cf..c12c2f7314 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -1,20 +1,14 @@ #include "nodedb.hpp" +#include +#include +#include + #include "router_contact.hpp" -#include "crypto/crypto.hpp" #include "crypto/types.hpp" -#include "util/buffer.hpp" -#include "util/fs.hpp" -#include "util/logging.hpp" #include "util/time.hpp" -#include "util/mem.hpp" -#include "util/str.hpp" #include "dht/kademlia.hpp" -#include -#include -#include - static const char skiplist_subdirs[] = "0123456789abcdef"; static const std::string RC_FILE_EXT = ".signed"; diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index 7c5661b1a3..6404a0430f 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -1,16 +1,6 @@ #pragma once -#include "router_contact.hpp" -#include "router_id.hpp" - -#include "util/common.hpp" -#include "util/fs.hpp" -#include "dht/key.hpp" -#include "crypto/crypto.hpp" -#include "util/thread/threading.hpp" -#include "util/thread/annotations.hpp" #include - #include #include #include @@ -19,6 +9,15 @@ #include #include +#include "router_contact.hpp" +#include "router_id.hpp" +#include "util/common.hpp" +#include "util/fs.hpp" +#include "dht/key.hpp" +#include "crypto/crypto.hpp" +#include "util/thread/threading.hpp" +#include "util/thread/annotations.hpp" + namespace llarp { struct Router; diff --git a/llarp/path/abstracthophandler.hpp b/llarp/path/abstracthophandler.hpp index 69fcb7c367..f600116711 100644 --- a/llarp/path/abstracthophandler.hpp +++ b/llarp/path/abstracthophandler.hpp @@ -6,7 +6,6 @@ #include #include #include - #include struct llarp_buffer_t; diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index fe2551f7e1..534ab10eb7 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -1,20 +1,11 @@ #include "path.hpp" -#include "pathbuilder.hpp" -#include "transit_hop.hpp" -#include #include #include -#include #include #include #include -#include - -#include -#include - namespace llarp::path { Path::Path( diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index bb3a294ede..42aa214ab9 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -1,9 +1,5 @@ #pragma once -#include "abstracthophandler.hpp" -#include "path_types.hpp" -#include "pathset.hpp" - #include #include #include @@ -14,7 +10,6 @@ #include #include #include - #include #include #include @@ -23,6 +18,10 @@ #include #include +#include "abstracthophandler.hpp" +#include "path_types.hpp" +#include "pathset.hpp" + namespace llarp { struct Router; @@ -36,6 +35,7 @@ namespace llarp using TransitHop_ptr = std::shared_ptr; struct Ptr_hash; + struct Endpoint_Hash; struct endpoint_comparator; diff --git a/llarp/path/path_context.hpp b/llarp/path/path_context.hpp index 8cf8138a74..88911ab8fe 100644 --- a/llarp/path/path_context.hpp +++ b/llarp/path/path_context.hpp @@ -1,19 +1,18 @@ #pragma once -#include "abstracthophandler.hpp" -#include "path_types.hpp" -#include "pathset.hpp" -#include "transit_hop.hpp" - #include #include #include #include #include - #include #include +#include "abstracthophandler.hpp" +#include "path_types.hpp" +#include "pathset.hpp" +#include "transit_hop.hpp" + namespace llarp { struct Router; diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index 7c1487011e..a9758384ed 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -1,6 +1,4 @@ #include "pathbuilder.hpp" -#include "path.hpp" -#include "path_context.hpp" #include #include @@ -9,10 +7,10 @@ #include #include #include -#include #include -#include +#include "path.hpp" +#include "path_context.hpp" namespace llarp { diff --git a/llarp/path/pathset.cpp b/llarp/path/pathset.cpp index f0c2d2fbfa..7a0427d612 100644 --- a/llarp/path/pathset.cpp +++ b/llarp/path/pathset.cpp @@ -1,10 +1,6 @@ #include "path.hpp" #include "pathset.hpp" -#include - -#include - namespace llarp::path { PathSet::PathSet(size_t num) : numDesiredPaths(num) diff --git a/llarp/path/pathset.hpp b/llarp/path/pathset.hpp index adb2ca1120..9c98281277 100644 --- a/llarp/path/pathset.hpp +++ b/llarp/path/pathset.hpp @@ -1,6 +1,5 @@ #pragma once -#include "path_types.hpp" #include #include #include @@ -8,13 +7,14 @@ #include #include #include - #include #include #include #include #include +#include "path_types.hpp" + namespace std { template <> diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index bcf867a92e..bceae78a57 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -1,13 +1,7 @@ -#include "path.hpp" -#include "path_context.hpp" -#include "transit_hop.hpp" - -#include -#include #include #include -#include +#include "transit_hop.hpp" namespace llarp::path { @@ -29,6 +23,15 @@ namespace llarp::path m_DownstreamWorkCounter = 0; } + bool + TransitHop::send_path_control_message( + std::string, + std::string, + std::function) + { + return true; + } + bool TransitHop::Expired(llarp_time_t now) const { diff --git a/llarp/peerstats/orm.hpp b/llarp/peerstats/orm.hpp deleted file mode 100644 index 0c0df851b2..0000000000 --- a/llarp/peerstats/orm.hpp +++ /dev/null @@ -1,133 +0,0 @@ -#pragma once - -#include - -#include "types.hpp" - -/// Contains some code to help deal with sqlite_orm in hopes of keeping other headers clean - -namespace llarp -{ - inline auto - initStorage(const std::string& file) - { - using namespace sqlite_orm; - return make_storage( - file, - make_table( - "peerstats", - make_column("routerId", &PeerStats::routerId, primary_key(), unique()), - make_column("numConnectionAttempts", &PeerStats::numConnectionAttempts), - make_column("numConnectionSuccesses", &PeerStats::numConnectionSuccesses), - make_column("numConnectionRejections", &PeerStats::numConnectionRejections), - make_column("numConnectionTimeouts", &PeerStats::numConnectionTimeouts), - make_column("numPathBuilds", &PeerStats::numPathBuilds), - make_column("numPacketsAttempted", &PeerStats::numPacketsAttempted), - make_column("numPacketsSent", &PeerStats::numPacketsSent), - make_column("numPacketsDropped", &PeerStats::numPacketsDropped), - make_column("numPacketsResent", &PeerStats::numPacketsResent), - make_column("numDistinctRCsReceived", &PeerStats::numDistinctRCsReceived), - make_column("numLateRCs", &PeerStats::numLateRCs), - make_column("peakBandwidthBytesPerSec", &PeerStats::peakBandwidthBytesPerSec), - make_column("longestRCReceiveInterval", &PeerStats::longestRCReceiveInterval), - make_column("leastRCRemainingLifetime", &PeerStats::leastRCRemainingLifetime))); - } - - using PeerDbStorage = decltype(initStorage("")); - -} // namespace llarp - -/// "custom" types for sqlite_orm -/// reference: https://github.com/fnc12/sqlite_orm/blob/master/examples/enum_binding.cpp -namespace sqlite_orm -{ - /// llarp_time_t serialization - template <> - struct type_printer : public integer_printer - {}; - - template <> - struct statement_binder - { - int - bind(sqlite3_stmt* stmt, int index, const llarp_time_t& value) - { - return statement_binder().bind(stmt, index, value.count()); - } - }; - - template <> - struct field_printer - { - std::string - operator()(const llarp_time_t& value) const - { - return fmt::format("{}", value.count()); - } - }; - - template <> - struct row_extractor - { - llarp_time_t - extract(const char* row_value) - { - int64_t raw = static_cast(atoi(row_value)); - return llarp_time_t(raw); - } - - llarp_time_t - extract(sqlite3_stmt* stmt, int columnIndex) - { - auto str = sqlite3_column_text(stmt, columnIndex); - return this->extract((const char*)str); - } - }; - - /// RouterID serialization - template <> - struct type_printer : public text_printer - {}; - - template <> - struct statement_binder - { - int - bind(sqlite3_stmt* stmt, int index, const llarp::RouterID& value) - { - return statement_binder().bind(stmt, index, value.ToString()); - } - }; - - template <> - struct field_printer - { - std::string - operator()(const llarp::RouterID& value) const - { - return value.ToString(); - } - }; - - template <> - struct row_extractor - { - llarp::RouterID - extract(const char* row_value) - { - llarp::RouterID id; - if (not id.FromString(row_value)) - throw std::runtime_error("Invalid RouterID in sqlite3 database"); - - return id; - } - - llarp::RouterID - extract(sqlite3_stmt* stmt, int columnIndex) - { - auto str = sqlite3_column_text(stmt, columnIndex); - return this->extract((const char*)str); - } - }; - -} // namespace sqlite_orm diff --git a/llarp/peerstats/peer_db.cpp b/llarp/peerstats/peer_db.cpp deleted file mode 100644 index e14fca2c64..0000000000 --- a/llarp/peerstats/peer_db.cpp +++ /dev/null @@ -1,380 +0,0 @@ -#include "peer_db.hpp" - -#include -#include -#include - -namespace llarp -{ -#ifdef LOKINET_PEERSTATS_BACKEND - - PeerDb::PeerDb() - { - m_lastFlush.store({}); - } - - void - PeerDb::loadDatabase(std::optional file) - { - std::lock_guard guard(m_statsLock); - - if (m_storage) - throw std::runtime_error("Reloading database not supported"); // TODO - - m_peerStats.clear(); - - // sqlite_orm treats empty-string as an indicator to load a memory-backed database, which we'll - // use if file is an empty-optional - std::string fileString; - if (file.has_value()) - { - fileString = file->string(); - LogInfo("Loading PeerDb from file ", fileString); - } - else - { - LogInfo("Loading memory-backed PeerDb"); - } - - m_storage = std::make_unique(initStorage(fileString)); - m_storage->sync_schema(true); // true for "preserve" as in "don't nuke" (how cute!) - - auto allStats = m_storage->get_all(); - LogInfo("Loading ", allStats.size(), " PeerStats from table peerstats..."); - for (PeerStats& stats : allStats) - { - // we cleared m_peerStats, and the database should enforce that routerId is unique... - assert(m_peerStats.find(stats.routerId) == m_peerStats.end()); - - stats.stale = false; - m_peerStats[stats.routerId] = stats; - } - } - - void - PeerDb::flushDatabase() - { - LogDebug("flushing PeerDb..."); - - auto start = time_now_ms(); - if (not shouldFlush(start)) - { - LogWarn("Call to flushDatabase() while already in progress, ignoring"); - return; - } - - if (not m_storage) - throw std::runtime_error("Cannot flush database before it has been loaded"); - - std::vector staleStats; - - { - std::lock_guard guard(m_statsLock); - - // copy all stale entries - for (auto& entry : m_peerStats) - { - if (entry.second.stale) - { - staleStats.push_back(entry.second); - entry.second.stale = false; - } - } - } - - LogDebug("Updating ", staleStats.size(), " stats"); - - { - auto guard = m_storage->transaction_guard(); - - for (const auto& stats : staleStats) - { - m_storage->replace(stats); - } - - guard.commit(); - } - - auto end = time_now_ms(); - - auto elapsed = end - start; - LogDebug("PeerDb flush took about ", elapsed, " seconds"); - - m_lastFlush.store(end); - } - - void - PeerDb::accumulatePeerStats(const RouterID& routerId, const PeerStats& delta) - { - if (routerId != delta.routerId) - throw std::invalid_argument{ - fmt::format("routerId {} doesn't match {}", routerId, delta.routerId)}; - - std::lock_guard guard(m_statsLock); - auto itr = m_peerStats.find(routerId); - if (itr == m_peerStats.end()) - itr = m_peerStats.insert({routerId, delta}).first; - else - itr->second += delta; - - itr->second.stale = true; - } - - void - PeerDb::modifyPeerStats(const RouterID& routerId, std::function callback) - { - std::lock_guard guard(m_statsLock); - - PeerStats& stats = m_peerStats[routerId]; - stats.routerId = routerId; - stats.stale = true; - callback(stats); - } - - std::optional - PeerDb::getCurrentPeerStats(const RouterID& routerId) const - { - std::lock_guard guard(m_statsLock); - auto itr = m_peerStats.find(routerId); - if (itr == m_peerStats.end()) - return std::nullopt; - else - return itr->second; - } - - std::vector - PeerDb::listAllPeerStats() const - { - std::lock_guard guard(m_statsLock); - - std::vector statsList; - statsList.reserve(m_peerStats.size()); - - for (const auto& [routerId, stats] : m_peerStats) - { - statsList.push_back(stats); - } - - return statsList; - } - - std::vector - PeerDb::listPeerStats(const std::vector& ids) const - { - std::lock_guard guard(m_statsLock); - - std::vector statsList; - statsList.reserve(ids.size()); - - for (const auto& id : ids) - { - const auto itr = m_peerStats.find(id); - if (itr != m_peerStats.end()) - statsList.push_back(itr->second); - } - - return statsList; - } - - /// Assume we receive an RC at some point `R` in time which was signed at some point `S` in time - /// and expires at some point `E` in time, as depicted below: - /// - /// +-----------------------------+ - /// | signed rc | <- useful lifetime of RC - /// +-----------------------------+ - /// ^ [ . . . . . . . . ] <----------- window in which we receive this RC gossiped to us - /// | ^ ^ - /// | | | - /// S R E - /// - /// One useful metric from this is the difference between (E - R), the useful contact time of this - /// RC. As we track this metric over time, the high and low watermarks serve to tell us how - /// quickly we receive signed RCs from a given router and how close to expiration they are when - /// we receive them. The latter is particularly useful, and should always be a positive number for - /// a healthy router. A negative number indicates that we are receiving an expired RC. - /// - /// TODO: we actually discard expired RCs, so we currently would not detect a negative value for - /// (E - R) - /// - /// Another related metric is the distance between a newly received RC and the previous RC's - /// expiration, which represents how close we came to having no useful RC to work with. This - /// should be a high (positive) number for a healthy router, and if negative indicates that we - /// had no way to contact this router for a period of time. - /// - /// E1 E2 E3 - /// | | | - /// v | | - /// +-----------------------------+ | | - /// | signed rc 1 | | | - /// +-----------------------------+ | | - /// [ . . . . . ] v | - /// ^ +-----------------------------+ | - /// | | signed rc 2 | | - /// | +-----------------------------+ | - /// | [ . . . . . . . . . . ] v - /// | ^ +-----------------------------+ - /// | | | signed rc 3 | - /// | | +-----------------------------+ - /// | | [ . . ] - /// | | ^ - /// | | | - /// R1 R2 R3 - /// - /// Example: the delta between (E1 - R2) is healthy, but the delta between (E2 - R3) is indicates - /// that we had a brief period of time where we had no valid (non-expired) RC for this router - /// (because it is negative). - void - PeerDb::handleGossipedRC(const RouterContact& rc, llarp_time_t now) - { - std::lock_guard guard(m_statsLock); - - RouterID id(rc.pubkey); - auto& stats = m_peerStats[id]; - stats.routerId = id; - - const bool isNewRC = (stats.lastRCUpdated < rc.last_updated); - - if (isNewRC) - { - stats.numDistinctRCsReceived++; - - if (stats.numDistinctRCsReceived > 1) - { - auto prevRCExpiration = (stats.lastRCUpdated + RouterContact::Lifetime); - - // we track max expiry as the delta between (last expiration time - time received), - // and this value will be negative for an unhealthy router - // TODO: handle case where new RC is also expired? just ignore? - auto expiry = prevRCExpiration - now; - - if (stats.numDistinctRCsReceived == 2) - stats.leastRCRemainingLifetime = expiry; - else - stats.leastRCRemainingLifetime = std::min(stats.leastRCRemainingLifetime, expiry); - } - - stats.lastRCUpdated = rc.last_updated; - stats.stale = true; - } - } - - void - PeerDb::configure(const RouterConfig& routerConfig) - { - fs::path dbPath = routerConfig.m_dataDir / "peerstats.sqlite"; - - loadDatabase(dbPath); - } - - bool - PeerDb::shouldFlush(llarp_time_t now) - { - constexpr llarp_time_t TargetFlushInterval = 30s; - return (now - m_lastFlush.load() >= TargetFlushInterval); - } - - util::StatusObject - PeerDb::ExtractStatus() const - { - std::lock_guard guard(m_statsLock); - - bool loaded = (m_storage.get() != nullptr); - util::StatusObject dbFile = nullptr; - if (loaded) - dbFile = m_storage->filename(); - - std::vector statsObjs; - statsObjs.reserve(m_peerStats.size()); - for (const auto& pair : m_peerStats) - { - statsObjs.push_back(pair.second.toJson()); - } - - util::StatusObject obj{ - {"dbLoaded", loaded}, - {"dbFile", dbFile}, - {"lastFlushMs", m_lastFlush.load().count()}, - {"stats", statsObjs}, - }; - return obj; - } - -#else // !LOKINET_PEERSTATS - - // Empty stubs - - PeerDb::PeerDb() - { - throw std::logic_error{"Peer stats backend not enabled!"}; - } - - void - PeerDb::loadDatabase(std::optional) - {} - - void - PeerDb::flushDatabase() - {} - - void - PeerDb::accumulatePeerStats(const RouterID&, const PeerStats&) - {} - - void - PeerDb::modifyPeerStats(const RouterID&, std::function) - {} - - std::optional - PeerDb::getCurrentPeerStats(const RouterID&) const - { - return std::nullopt; - } - - std::vector - PeerDb::listAllPeerStats() const - { - return {}; - } - - std::vector - PeerDb::listPeerStats(const std::vector&) const - { - return {}; - } - - void - PeerDb::handleGossipedRC(const RouterContact&, llarp_time_t) - {} - - void - PeerDb::configure(const RouterConfig&) - {} - - bool - PeerDb::shouldFlush(llarp_time_t) - { - return false; - } - - util::StatusObject - PeerDb::ExtractStatus() const - { - return {}; - } - -#endif - -}; // namespace llarp - -/* - - How does a SN/quorum of SN determine if an operator is acting in good faith on the network - - w/o the other operator knowing - - Observing and gathering data in a meaningful way - - - What type of stats could you even collect off lokinet? - - Collecting network-wide data can't be automatically actioned unless the SN is collecting - - - Redundancy model - - Don't rely on an individual, but a collection of them - -*/ diff --git a/llarp/peerstats/peer_db.hpp b/llarp/peerstats/peer_db.hpp deleted file mode 100644 index d024306805..0000000000 --- a/llarp/peerstats/peer_db.hpp +++ /dev/null @@ -1,141 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include -#include -#include -#include -#include "types.hpp" -#ifdef LOKINET_PEERSTATS_BACKEND -#include "orm.hpp" -#endif - -namespace llarp -{ - /// Maintains a database of stats collected about the connections with our Service Node peers. - /// This uses a sqlite3 database behind the scenes as persistance, but this database is - /// periodically flushed to, meaning that it will become stale as PeerDb accumulates stats without - /// a flush. - struct PeerDb - { - /// Constructor - PeerDb(); - - /// Loads the database from disk using the provided filepath. If the file is equal to - /// `std::nullopt`, the database will be loaded into memory (useful for testing). - /// - /// This must be called prior to calling flushDatabase(), and will truncate any existing data. - /// - /// This is a blocking call, both in the sense that it blocks on disk/database I/O and that it - /// will sit on a mutex while the database is loaded. - /// - /// @param file is an optional file which doesn't have to exist but must be writable, if a value - /// is provided. If no value is provided, the database will be memory-backed. - /// @throws if sqlite_orm/sqlite3 is unable to open or create a database at the given file - void - loadDatabase(std::optional file); - - /// Flushes the database. Must be called after loadDatabase(). This call will block during I/O - /// and should be called in an appropriate threading context. However, it will make a temporary - /// copy of the peer stats so as to avoid sitting on a mutex lock during disk I/O. - /// - /// @throws if the database could not be written to (esp. if loadDatabase() has not been called) - void - flushDatabase(); - - /// Add the given stats to the cummulative stats for the given peer. For cummulative stats, the - /// stats are added together; for watermark stats, the max is kept. - /// - /// This is intended to be used in the following pattern: - /// - /// 1) Initialize an empty PeerStats - /// 2) Collect relevant stats - /// 3) Call accumulatePeerStats() with the stats - /// 4) Reset the stats to 0 - /// 5) - /// - /// @param routerId is the id of the router whose stats should be modified. - /// @param delta is the stats to add to the existing stats - void - accumulatePeerStats(const RouterID& routerId, const PeerStats& delta); - - /// Allows write-access to the stats for a given peer while appropriate mutex lock is held. This - /// is an alternative means of incrementing peer stats that is suitable for one-off - /// modifications. - /// - /// Note that this holds m_statsLock during the callback invocation, so the callback should - /// return as quickly as possible. - /// - /// @param routerId is the id of the router whose stats should be modified. - /// @param callback is a function which will be called immediately with mutex held - void - modifyPeerStats(const RouterID& routerId, std::function callback); - - /// Provides a snapshot of the most recent PeerStats we have for the given peer. If we don't - /// have any stats for the peer, std::nullopt - /// - /// @param routerId is the RouterID of the requested peer - /// @return a copy of the most recent peer stats or an empty one if no such peer is known - std::optional - getCurrentPeerStats(const RouterID& routerId) const; - - /// Lists all peer stats. This essentially dumps the database into a list of PeerStats objects. - /// - /// Note that this avoids disk I/O by copying from our cached map of peers. - /// - /// @return a list of all PeerStats we have maintained - std::vector - listAllPeerStats() const; - - /// Lists specific peer stats. - /// - /// @param peers is list of RouterIDs which are desired - /// @return a list of the requested peers. Peers not found will be omitted. - std::vector - listPeerStats(const std::vector& ids) const; - - /// Handles a new gossiped RC, updating stats as needed. The database tracks the last - /// advertised update time, so it knows whether this is a new RC or not. - /// - /// The given RC is assumed to be valid. - /// - /// @param rc is the RouterContact to handle - /// @param now is an optional time representing the current time - void - handleGossipedRC(const RouterContact& rc, llarp_time_t now = time_now_ms()); - - /// Configures the PeerDb based on RouterConfig - /// - /// @param routerConfig - void - configure(const RouterConfig& routerConfig); - - /// Returns whether or not we should flush, as determined by the last time we flushed and the - /// configured flush interval. - /// - /// @param now is the current[-ish] time - bool - shouldFlush(llarp_time_t now); - - /// Get JSON status for API - /// - /// @return JSON object representing our current status - util::StatusObject - ExtractStatus() const; - -#ifdef LOKINET_PEERSTATS_BACKEND - private: - std::unordered_map m_peerStats; - mutable std::mutex m_statsLock; - - std::unique_ptr m_storage; - - std::atomic m_lastFlush; -#endif - }; - -} // namespace llarp diff --git a/llarp/peerstats/types.cpp b/llarp/peerstats/types.cpp deleted file mode 100644 index 89b0129cc6..0000000000 --- a/llarp/peerstats/types.cpp +++ /dev/null @@ -1,146 +0,0 @@ -#include "types.hpp" - -#include -#include -#include - -namespace llarp -{ - constexpr auto RouterIdKey = "routerId"; - constexpr auto NumConnectionAttemptsKey = "numConnectionAttempts"; - constexpr auto NumConnectionSuccessesKey = "numConnectionSuccesses"; - constexpr auto NumConnectionRejectionsKey = "numConnectionRejections"; - constexpr auto NumConnectionTimeoutsKey = "numConnectionTimeouts"; - constexpr auto NumPathBuildsKey = "numPathBuilds"; - constexpr auto NumPacketsAttemptedKey = "numPacketsAttempted"; - constexpr auto NumPacketsSentKey = "numPacketsSent"; - constexpr auto NumPacketsDroppedKey = "numPacketsDropped"; - constexpr auto NumPacketsResentKey = "numPacketsResent"; - constexpr auto NumDistinctRCsReceivedKey = "numDistinctRCsReceived"; - constexpr auto NumLateRCsKey = "numLateRCs"; - constexpr auto PeakBandwidthBytesPerSecKey = "peakBandwidthBytesPerSec"; - constexpr auto LongestRCReceiveIntervalKey = "longestRCReceiveInterval"; - constexpr auto LeastRCRemainingLifetimeKey = "leastRCRemainingLifetime"; - constexpr auto LastRCUpdatedKey = "lastRCUpdated"; - - PeerStats::PeerStats() = default; - - PeerStats::PeerStats(const RouterID& routerId_) : routerId(routerId_) - {} - - PeerStats& - PeerStats::operator+=(const PeerStats& other) - { - numConnectionAttempts += other.numConnectionAttempts; - numConnectionSuccesses += other.numConnectionSuccesses; - numConnectionRejections += other.numConnectionRejections; - numConnectionTimeouts += other.numConnectionTimeouts; - - numPathBuilds += other.numPathBuilds; - numPacketsAttempted += other.numPacketsAttempted; - numPacketsSent += other.numPacketsSent; - numPacketsDropped += other.numPacketsDropped; - numPacketsResent += other.numPacketsResent; - - numDistinctRCsReceived += other.numDistinctRCsReceived; - numLateRCs += other.numLateRCs; - - peakBandwidthBytesPerSec = std::max(peakBandwidthBytesPerSec, other.peakBandwidthBytesPerSec); - longestRCReceiveInterval = std::max(longestRCReceiveInterval, other.longestRCReceiveInterval); - leastRCRemainingLifetime = std::max(leastRCRemainingLifetime, other.leastRCRemainingLifetime); - lastRCUpdated = std::max(lastRCUpdated, other.lastRCUpdated); - - return *this; - } - - bool - PeerStats::operator==(const PeerStats& other) const - { - return routerId == other.routerId and numConnectionAttempts == other.numConnectionAttempts - and numConnectionSuccesses == other.numConnectionSuccesses - and numConnectionRejections == other.numConnectionRejections - and numConnectionTimeouts == other.numConnectionTimeouts - - and numPathBuilds == other.numPathBuilds - and numPacketsAttempted == other.numPacketsAttempted - and numPacketsSent == other.numPacketsSent and numPacketsDropped == other.numPacketsDropped - and numPacketsResent == other.numPacketsResent - - and numDistinctRCsReceived == other.numDistinctRCsReceived - and numLateRCs == other.numLateRCs - - and peakBandwidthBytesPerSec == other.peakBandwidthBytesPerSec - and longestRCReceiveInterval == other.longestRCReceiveInterval - and leastRCRemainingLifetime == other.leastRCRemainingLifetime - and lastRCUpdated == other.lastRCUpdated; - } - - util::StatusObject - PeerStats::toJson() const - { - return { - {RouterIdKey, routerId.ToString()}, - {NumConnectionAttemptsKey, numConnectionAttempts}, - {NumConnectionSuccessesKey, numConnectionSuccesses}, - {NumConnectionRejectionsKey, numConnectionRejections}, - {NumConnectionTimeoutsKey, numConnectionTimeouts}, - {NumPathBuildsKey, numPathBuilds}, - {NumPacketsAttemptedKey, numPacketsAttempted}, - {NumPacketsSentKey, numPacketsSent}, - {NumPacketsDroppedKey, numPacketsDropped}, - {NumPacketsResentKey, numPacketsResent}, - {NumDistinctRCsReceivedKey, numDistinctRCsReceived}, - {NumLateRCsKey, numLateRCs}, - {PeakBandwidthBytesPerSecKey, peakBandwidthBytesPerSec}, - {LongestRCReceiveIntervalKey, longestRCReceiveInterval.count()}, - {LeastRCRemainingLifetimeKey, leastRCRemainingLifetime.count()}, - {LastRCUpdatedKey, lastRCUpdated.count()}, - }; - } - - void - PeerStats::BEncode(llarp_buffer_t* buf) const - { - if (not buf) - throw std::runtime_error("PeerStats: Can't use null buf"); - const oxenc::bt_dict data = { - {NumConnectionAttemptsKey, numConnectionAttempts}, - {NumConnectionSuccessesKey, numConnectionSuccesses}, - {NumConnectionRejectionsKey, numConnectionRejections}, - {NumConnectionTimeoutsKey, numConnectionTimeouts}, - {NumPathBuildsKey, numPathBuilds}, - {NumPacketsAttemptedKey, numPacketsAttempted}, - {NumPacketsSentKey, numPacketsSent}, - {NumPacketsDroppedKey, numPacketsDropped}, - {NumPacketsResentKey, numPacketsResent}, - {NumDistinctRCsReceivedKey, numDistinctRCsReceived}, - {NumLateRCsKey, numLateRCs}, - {PeakBandwidthBytesPerSecKey, (uint64_t)peakBandwidthBytesPerSec}, - {LongestRCReceiveIntervalKey, longestRCReceiveInterval.count()}, - {LeastRCRemainingLifetimeKey, leastRCRemainingLifetime.count()}, - {LastRCUpdatedKey, lastRCUpdated.count()}, - }; - const auto serialized = oxenc::bt_serialize(data); - if (not buf->write(serialized.begin(), serialized.end())) - throw std::runtime_error("PeerStats: buffer too small"); - } - - void - PeerStats::BEncodeList(const std::vector& statsList, llarp_buffer_t* buf) - { - if (not buf) - throw std::runtime_error("PeerStats: Can't use null buf"); - - if (not bencode_start_list(buf)) - throw std::runtime_error("PeerStats: Could not create bencode dict"); - - for (const auto& stats : statsList) - { - stats.BEncode(buf); - } - - if (not bencode_end(buf)) - throw std::runtime_error("PeerStats: Could not end bencode dict"); - } - -}; // namespace llarp diff --git a/llarp/peerstats/types.hpp b/llarp/peerstats/types.hpp deleted file mode 100644 index 1668936655..0000000000 --- a/llarp/peerstats/types.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -#include -#include - -#include -#include -#include - -/// Types stored in our peerstats database are declared here - -namespace llarp -{ - // Struct containing stats we know about a peer - struct PeerStats - { - RouterID routerId; - - int32_t numConnectionAttempts = 0; - int32_t numConnectionSuccesses = 0; - int32_t numConnectionRejections = 0; - int32_t numConnectionTimeouts = 0; - - int32_t numPathBuilds = 0; - int64_t numPacketsAttempted = 0; - int64_t numPacketsSent = 0; - int64_t numPacketsDropped = 0; - int64_t numPacketsResent = 0; - - int32_t numDistinctRCsReceived = 0; - int32_t numLateRCs = 0; - - double peakBandwidthBytesPerSec = 0; - llarp_time_t longestRCReceiveInterval = 0ms; - llarp_time_t leastRCRemainingLifetime = 0ms; - llarp_time_t lastRCUpdated = 0ms; - - // not serialized - bool stale = true; - - PeerStats(); - PeerStats(const RouterID& routerId); - - PeerStats& - operator+=(const PeerStats& other); - bool - operator==(const PeerStats& other) const; - - util::StatusObject - toJson() const; - - void - BEncode(llarp_buffer_t* buf) const; - - static void - BEncodeList(const std::vector& statsList, llarp_buffer_t* buf); - }; - -} // namespace llarp diff --git a/llarp/pow.cpp b/llarp/pow.cpp index 1ca047f120..858f2e1a7e 100644 --- a/llarp/pow.cpp +++ b/llarp/pow.cpp @@ -1,10 +1,9 @@ #include "pow.hpp" -#include "crypto/crypto.hpp" -#include "util/buffer.hpp" - #include +#include "crypto/crypto.hpp" + namespace llarp { PoW::~PoW() = default; diff --git a/llarp/profiling.cpp b/llarp/profiling.cpp index 45af9b9ff7..e1fcc9121f 100644 --- a/llarp/profiling.cpp +++ b/llarp/profiling.cpp @@ -1,9 +1,9 @@ #include "profiling.hpp" + #include #include #include "util/file.hpp" -#include "util/logging.hpp" using oxenc::bt_dict_consumer; using oxenc::bt_dict_producer; diff --git a/llarp/profiling.hpp b/llarp/profiling.hpp index c23199b32d..4e4c7a8c44 100644 --- a/llarp/profiling.hpp +++ b/llarp/profiling.hpp @@ -1,12 +1,12 @@ #pragma once +#include + #include "path/path.hpp" #include "router_id.hpp" #include "util/bencode.hpp" #include "util/thread/threading.hpp" - #include "util/thread/annotations.hpp" -#include namespace oxenc { diff --git a/llarp/router/outbound_message_handler.cpp b/llarp/router/outbound_message_handler.cpp deleted file mode 100644 index ea85707d8e..0000000000 --- a/llarp/router/outbound_message_handler.cpp +++ /dev/null @@ -1,389 +0,0 @@ - -#include -#include "router.hpp" -#include -#include -#include - -#include -#include - -namespace llarp -{ - const PathID_t OutboundMessageHandler::zeroID; - - using namespace std::chrono_literals; - - OutboundMessageHandler::OutboundMessageHandler(size_t maxQueueSize) - : outboundQueue(maxQueueSize), recentlyRemovedPaths(5s), removedSomePaths(false) - {} - - bool - OutboundMessageHandler::QueueMessage( - const RouterID& remote, const AbstractLinkMessage& msg, SendStatusHandler callback) - { - // if the destination is invalid, callback with failure and return - if (not _router->link_manager().have_client_connection_to(remote) - and not _router->rc_lookup_handler().is_session_allowed(remote)) - { - DoCallback(callback, SendStatus::InvalidRouter); - return true; - } - MessageQueueEntry ent; - ent.router = remote; - ent.inform = std::move(callback); - ent.pathid = msg.pathid; - ent.priority = msg.priority(); - - std::string _buf; - _buf.reserve(MAX_LINK_MSG_SIZE); - - if (!EncodeBuffer(msg, _buf)) - return false; - - ent.message.resize(_buf.size()); - - std::copy_n(_buf.data(), _buf.size(), ent.message.data()); - - // if we have a session to the destination, queue the message and return - if (_router->link_manager().have_connection_to(remote)) - { - QueueOutboundMessage(std::move(ent)); - return true; - } - - // if we don't have a session to the destination, queue the message onto - // a special pending session queue for that destination, and then create - // that pending session if there is not already a session establish attempt - // in progress. - bool shouldCreateSession = false; - { - util::Lock l{_mutex}; - - // create queue for if it doesn't exist, and get iterator - auto [queue_itr, is_new] = pendingSessionMessageQueues.emplace(remote, MessageQueue()); - queue_itr->second.push(std::move(ent)); - - shouldCreateSession = is_new; - } - - if (shouldCreateSession) - { - QueueSessionCreation(remote); - } - - return true; - } - - void - OutboundMessageHandler::Pump() - { - m_Killer.TryAccess([this]() { - recentlyRemovedPaths.Decay(); - ProcessOutboundQueue(); - // TODO: this probably shouldn't be pumping, as it defeats the purpose - // of having a limit on sends per tick, but chaning it is potentially bad - // and requires testing so it should be changed later. - if (/*bool more = */ SendRoundRobin()) - _router->TriggerPump(); - }); - } - - void - OutboundMessageHandler::RemovePath(const PathID_t& pathid) - { - m_Killer.TryAccess([this, pathid]() { - /* add the path id to a list of recently removed paths to act as a filter - * for messages that are queued but haven't been sorted into path queues yet. - * - * otherwise these messages would re-create the path queue we just removed, and - * those path queues would be leaked / never removed. - */ - recentlyRemovedPaths.Insert(pathid); - auto itr = outboundMessageQueues.find(pathid); - if (itr != outboundMessageQueues.end()) - { - outboundMessageQueues.erase(itr); - } - removedSomePaths = true; - }); - } - - util::StatusObject - OutboundMessageHandler::ExtractStatus() const - { - util::StatusObject status{ - "queueStats", - {{"queued", m_queueStats.queued}, - {"dropped", m_queueStats.dropped}, - {"sent", m_queueStats.sent}, - {"queueWatermark", m_queueStats.queueWatermark}, - {"perTickMax", m_queueStats.perTickMax}, - {"numTicks", m_queueStats.numTicks}}}; - - return status; - } - - void - OutboundMessageHandler::Init(Router* router) - { - _router = router; - outboundMessageQueues.emplace(zeroID, MessageQueue()); - } - - static inline SendStatus - ToSendStatus(const SessionResult result) - { - switch (result) - { - case SessionResult::Establish: - return SendStatus::Success; - case SessionResult::Timeout: - case SessionResult::EstablishFail: - return SendStatus::Timeout; - case SessionResult::RouterNotFound: - return SendStatus::RouterNotFound; - case SessionResult::InvalidRouter: - return SendStatus::InvalidRouter; - case SessionResult::NoLink: - return SendStatus::NoLink; - } - throw std::invalid_argument{ - fmt::format("SessionResult {} has no corresponding SendStatus when transforming", result)}; - } - - void - OutboundMessageHandler::OnSessionResult(const RouterID& router, const SessionResult result) - { - FinalizeSessionRequest(router, ToSendStatus(result)); - } - - void - OutboundMessageHandler::DoCallback(SendStatusHandler callback, SendStatus status) - { - if (callback) - _router->loop()->call([f = std::move(callback), status] { f(status); }); - } - - // TODO: still necessary/desired? - void - OutboundMessageHandler::QueueSessionCreation(const RouterID& remote) - { - _router->link_manager().Connect(remote); - } - - /** Note: This is where AbstractLinkMessage::bt_encode() is called. Contextually, this is - different than how the other Abstract message types invoke ::bt_encode(), namely that - there is no bt_dict_producer already being appended to. As a result, this use case - likely requires a span backport and/or re-designed llarp_buffer. Until then, the - ::bt_encode() override that returns an std::string upon destruction of its bt_dict_producer - will be used - */ - bool - OutboundMessageHandler::EncodeBuffer(const AbstractLinkMessage& msg, std::string& buf) - { - if (buf = msg.bt_encode(); not buf.empty()) - return true; - - log::error(link_cat, "Error: OutboundMessageHandler failed to encode outbound message!"); - return false; - } - - bool - OutboundMessageHandler::Send(const MessageQueueEntry& ent) - { - const llarp_buffer_t buf{ent.message}; - m_queueStats.sent++; - SendStatusHandler callback = ent.inform; - return _router->link_manager().send_to( - ent.router, - buf, - [this, callback](AbstractLinkSession::DeliveryStatus status) { - if (status == AbstractLinkSession::DeliveryStatus::eDeliverySuccess) - DoCallback(callback, SendStatus::Success); - else - { - DoCallback(callback, SendStatus::Congestion); - } - }, - ent.priority); - } - - bool - OutboundMessageHandler::SendIfSession(const MessageQueueEntry& ent) - { - if (_router->link_manager().have_connection_to(ent.router)) - { - return Send(ent); - } - return false; - } - - bool - OutboundMessageHandler::QueueOutboundMessage(MessageQueueEntry entry) - { - // copy callback in case we need to call it, so we can std::move(entry) - auto callback = entry.inform; - if (outboundQueue.tryPushBack(std::move(entry)) != llarp::thread::QueueReturn::Success) - { - m_queueStats.dropped++; - DoCallback(callback, SendStatus::Congestion); - } - else - { - m_queueStats.queued++; - uint32_t queueSize = outboundQueue.size(); - m_queueStats.queueWatermark = std::max(queueSize, m_queueStats.queueWatermark); - } - - return true; - } - - void - OutboundMessageHandler::ProcessOutboundQueue() - { - while (not outboundQueue.empty()) - { - MessageQueueEntry entry = outboundQueue.popFront(); - - // messages may still be queued for processing when a pathid is removed, - // so check here if the pathid was recently removed. - if (recentlyRemovedPaths.Contains(entry.pathid)) - { - continue; - } - - auto [queue_itr, is_new] = outboundMessageQueues.emplace(entry.pathid, MessageQueue()); - - if (is_new && !entry.pathid.IsZero()) - { - roundRobinOrder.push(entry.pathid); - } - - MessageQueue& path_queue = queue_itr->second; - - if (path_queue.size() < MAX_PATH_QUEUE_SIZE || entry.pathid.IsZero()) - { - path_queue.push(std::move(entry)); - } - else - { - DoCallback(entry.inform, SendStatus::Congestion); - m_queueStats.dropped++; - } - } - } - - bool - OutboundMessageHandler::SendRoundRobin() - { - m_queueStats.numTicks++; - - // send routing messages first priority - auto& routing_mq = outboundMessageQueues[zeroID]; - while (not routing_mq.empty()) - { - const MessageQueueEntry& entry = routing_mq.top(); - Send(entry); - routing_mq.pop(); - } - - size_t num_queues = roundRobinOrder.size(); - - // if any paths have been removed since last tick, remove any stale - // entries from the round-robin ordering - if (removedSomePaths) - { - for (size_t i = 0; i < num_queues; i++) - { - PathID_t pathid = std::move(roundRobinOrder.front()); - roundRobinOrder.pop(); - - if (outboundMessageQueues.find(pathid) != outboundMessageQueues.end()) - { - roundRobinOrder.push(std::move(pathid)); - } - } - } - removedSomePaths = false; - - num_queues = roundRobinOrder.size(); - if (num_queues == 0) - { - return false; - } - - // send messages for each pathid in roundRobinOrder, stopping when - // either every path's queue is empty or a set maximum amount of - // messages have been sent. - size_t consecutive_empty = 0; - for (size_t sent_count = 0; sent_count < MAX_OUTBOUND_MESSAGES_PER_TICK;) - { - PathID_t pathid = std::move(roundRobinOrder.front()); - roundRobinOrder.pop(); - - auto& message_queue = outboundMessageQueues[pathid]; - if (message_queue.size() > 0) - { - const MessageQueueEntry& entry = message_queue.top(); - - Send(entry); - message_queue.pop(); - - consecutive_empty = 0; - consecutive_empty++; - } - else - { - consecutive_empty++; - } - - roundRobinOrder.push(std::move(pathid)); - - // if num_queues empty queues in a row, all queues empty. - if (consecutive_empty == num_queues) - { - break; - } - } - - m_queueStats.perTickMax = std::max((uint32_t)consecutive_empty, m_queueStats.perTickMax); - - return consecutive_empty != num_queues; - } - - void - OutboundMessageHandler::FinalizeSessionRequest(const RouterID& router, SendStatus status) - { - MessageQueue movedMessages; - { - util::Lock l(_mutex); - auto itr = pendingSessionMessageQueues.find(router); - - if (itr == pendingSessionMessageQueues.end()) - { - return; - } - - movedMessages.swap(itr->second); - - pendingSessionMessageQueues.erase(itr); - } - - while (!movedMessages.empty()) - { - const MessageQueueEntry& entry = movedMessages.top(); - - if (status == SendStatus::Success) - { - Send(entry); - } - else - { - DoCallback(entry.inform, status); - } - movedMessages.pop(); - } - } - -} // namespace llarp diff --git a/llarp/router/outbound_session_maker.cpp b/llarp/router/outbound_session_maker.cpp deleted file mode 100644 index be7ead52e3..0000000000 --- a/llarp/router/outbound_session_maker.cpp +++ /dev/null @@ -1,319 +0,0 @@ -#include "outbound_session_maker.hpp" - -#include "router.hpp" -#include -#include -#include -#include "rc_lookup_handler.hpp" -#include -#include -#include -#include -#include -#include - -#include - -namespace llarp -{ - - bool - OutboundSessionMaker::OnSessionEstablished(AbstractLinkSession* session) - { - // TODO: do we want to keep it - const RouterContact rc = session->GetRemoteRC(); - const auto router = RouterID(session->GetPubKey()); - const bool isOutbound = not session->IsInbound(); - const std::string remoteType = rc.IsPublicRouter() ? "router" : "client"; - LogInfo( - "session with ", remoteType, " [", router, "] ", isOutbound ? "established" : "received"); - - if (not _rcLookup->SessionIsAllowed(router)) - { - FinalizeRequest(router, SessionResult::InvalidRouter); - return false; - } - - if (isOutbound) - { - work([this, rc] { VerifyRC(rc); }); - return true; - } - return _rcLookup->CheckRC(rc); - } - - void - OutboundSessionMaker::OnConnectTimeout(AbstractLinkSession* session) - { - const auto router = RouterID(session->GetPubKey()); - LogWarn("Session establish attempt to ", router, " timed out.", session->GetRemoteEndpoint()); - FinalizeRequest(router, SessionResult::Timeout); - } - - void - OutboundSessionMaker::CreateSessionTo(const RouterID& router, RouterCallback on_result) - { - { - util::Lock l(_mutex); - - auto itr_pair = pendingCallbacks.emplace(router, CallbacksQueue{}); - if (on_result) - itr_pair.first->second.push_back(on_result); - } - - if (HavePendingSessionTo(router)) - { - LogDebug("has pending session to", router); - return; - } - - CreatePendingSession(router); - - // short-circuit to success callback if we already have an outbound session - // to the remote - if (_linkManager->HasConnection(router)) - { - FinalizeRequest(router, SessionResult::Establish); - return; - } - - LogDebug("Creating session establish attempt to ", router, " ."); - - auto fn = util::memFn(&OutboundSessionMaker::OnRouterContactResult, this); - - _rcLookup->GetRC(router, fn); - } - - void - OutboundSessionMaker::CreateSessionTo(const RouterContact& rc, RouterCallback on_result) - { - const RouterID router{rc.pubkey}; - - { - util::Lock l(_mutex); - - auto itr_pair = pendingCallbacks.emplace(router, CallbacksQueue{}); - if (on_result) - itr_pair.first->second.push_back(on_result); - } - - if (not HavePendingSessionTo(router)) - { - LogDebug("Creating session establish attempt to ", router); - CreatePendingSession(router); - } - - GotRouterContact(router, rc); - } - - bool - OutboundSessionMaker::HavePendingSessionTo(const RouterID& router) const - { - util::Lock l(_mutex); - return pendingCallbacks.find(router) != pendingCallbacks.end(); - } - - void - OutboundSessionMaker::ConnectToRandomRouters(int numDesired) - { - int remainingDesired = numDesired; - std::set exclude; - do - { - auto filter = [exclude](const auto& rc) -> bool { return exclude.count(rc.pubkey) == 0; }; - - RouterContact other; - if (const auto maybe = _nodedb->GetRandom(filter)) - { - other = *maybe; - } - else - break; - - exclude.insert(other.pubkey); - if (not _rcLookup->SessionIsAllowed(other.pubkey)) - { - continue; - } - if (not(_linkManager->HasSessionTo(other.pubkey) || HavePendingSessionTo(other.pubkey))) - { - CreateSessionTo(other, nullptr); - --remainingDesired; - } - - } while (remainingDesired > 0); - LogDebug( - "connecting to ", numDesired - remainingDesired, " out of ", numDesired, " random routers"); - } - - // TODO: this - util::StatusObject - OutboundSessionMaker::ExtractStatus() const - { - util::StatusObject status{}; - return status; - } - - void - OutboundSessionMaker::Init( - Router* router, - LinkManager* linkManager, - RCLookupHandler* rcLookup, - Profiling* profiler, - EventLoop_ptr loop, - WorkerFunc_t dowork) - { - _router = router; - _linkManager = linkManager; - _rcLookup = rcLookup; - _loop = std::move(loop); - _nodedb = router->nodedb(); - _profiler = profiler; - work = std::move(dowork); - } - - void - OutboundSessionMaker::GotRouterContact(const RouterID& router, const RouterContact& rc) - { - if (not _rcLookup->CheckRC(rc)) - { - FinalizeRequest(rc.pubkey, SessionResult::InvalidRouter); - return; - } - - if (not ShouldConnectTo(router)) - { - FinalizeRequest(router, SessionResult::NoLink); - return; - } - - auto result = _linkManager->Connect(rc); - if (result) - FinalizeRequest(router, SessionResult::Establish); - else - FinalizeRequest(router, SessionResult::EstablishFail); - } - - bool - OutboundSessionMaker::ShouldConnectTo(const RouterID& router) const - { - if (router == us or not _rcLookup->SessionIsAllowed(router)) - return false; - if (_router->IsServiceNode()) - return true; - - size_t numPending = 0; - { - util::Lock lock(_mutex); - if (pendingCallbacks.find(router) == pendingCallbacks.end()) - numPending += pendingCallbacks.size(); - } - - return _linkManager->get_num_connected() + numPending < maxConnectedRouters; - } - - void - OutboundSessionMaker::InvalidRouter(const RouterID& router) - { - FinalizeRequest(router, SessionResult::InvalidRouter); - } - - void - OutboundSessionMaker::RouterNotFound(const RouterID& router) - { - FinalizeRequest(router, SessionResult::RouterNotFound); - } - - void - OutboundSessionMaker::OnRouterContactResult( - const RouterID& router, const RouterContact* const rc, const RCRequestResult result) - { - if (not HavePendingSessionTo(router)) - { - LogError("no pending session to ", router); - return; - } - - switch (result) - { - case RCRequestResult::Success: - if (rc) - { - GotRouterContact(router, *rc); - } - else - { - LogError("RCRequestResult::Success but null rc pointer given"); - InvalidRouter(router); - } - break; - case RCRequestResult::InvalidRouter: - InvalidRouter(router); - break; - case RCRequestResult::RouterNotFound: - RouterNotFound(router); - break; - default: - RouterNotFound(router); - break; - } - } - - void - OutboundSessionMaker::VerifyRC(const RouterContact rc) - { - if (not _rcLookup->CheckRC(rc)) - { - FinalizeRequest(rc.pubkey, SessionResult::InvalidRouter); - return; - } - - FinalizeRequest(rc.pubkey, SessionResult::Establish); - } - - // TODO: rename this, if we even want to keep it - void - OutboundSessionMaker::CreatePendingSession(const RouterID& router) - { - auto peerDb = _router->peerDb(); - if (peerDb) - { - peerDb->modifyPeerStats(router, [](PeerStats& stats) { stats.numConnectionAttempts++; }); - } - - _router->NotifyRouterEvent(_router->pubkey(), router); - } - - void - OutboundSessionMaker::FinalizeRequest(const RouterID& router, const SessionResult type) - { - CallbacksQueue movedCallbacks; - { - util::Lock l(_mutex); - - if (type == SessionResult::Establish) - { - _profiler->MarkConnectSuccess(router); - } - else - { - // TODO: add non timeout related fail case - _profiler->MarkConnectTimeout(router); - } - - auto itr = pendingCallbacks.find(router); - - if (itr != pendingCallbacks.end()) - { - movedCallbacks.splice(movedCallbacks.begin(), itr->second); - pendingCallbacks.erase(itr); - } - } - - for (const auto& callback : movedCallbacks) - { - _loop->call([callback, router, type] { return callback(router, type); }); - } - } - -} // namespace llarp diff --git a/llarp/router/rc_gossiper.cpp b/llarp/router/rc_gossiper.cpp index fce7bacdcb..be478e620e 100644 --- a/llarp/router/rc_gossiper.cpp +++ b/llarp/router/rc_gossiper.cpp @@ -1,8 +1,7 @@ #include "rc_gossiper.hpp" +#include #include -#include -#include namespace llarp { diff --git a/llarp/router/rc_lookup_handler.cpp b/llarp/router/rc_lookup_handler.cpp index d40a8e59c6..6b36cb743a 100644 --- a/llarp/router/rc_lookup_handler.cpp +++ b/llarp/router/rc_lookup_handler.cpp @@ -1,19 +1,15 @@ -#include -#include "rc_lookup_handler.hpp" - #include #include #include #include #include #include -#include #include -#include "router.hpp" - #include #include -#include + +#include "rc_lookup_handler.hpp" +#include "router.hpp" namespace llarp { diff --git a/llarp/router/rc_lookup_handler.hpp b/llarp/router/rc_lookup_handler.hpp index cad8c46e2f..5c1ea079fd 100644 --- a/llarp/router/rc_lookup_handler.hpp +++ b/llarp/router/rc_lookup_handler.hpp @@ -2,7 +2,6 @@ #include #include - #include #include #include diff --git a/llarp/router/route_poker.cpp b/llarp/router/route_poker.cpp index 14783454f9..5bb33a1334 100644 --- a/llarp/router/route_poker.cpp +++ b/llarp/router/route_poker.cpp @@ -1,9 +1,8 @@ #include "route_poker.hpp" -#include "router.hpp" -#include + #include -#include -#include + +#include "router.hpp" namespace llarp { diff --git a/llarp/router/route_poker.hpp b/llarp/router/route_poker.hpp index e98346ec80..c272a28830 100644 --- a/llarp/router/route_poker.hpp +++ b/llarp/router/route_poker.hpp @@ -1,11 +1,11 @@ #pragma once +#include +#include #include #include #include #include -#include -#include namespace llarp { diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 01386828ab..17680b402f 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -3,23 +3,17 @@ #include #include #include -#include #include #include #include #include #include #include -#include #include -#include #include #include -#include #include - #include -#include #include #include #include @@ -34,7 +28,6 @@ #endif #include - #include static constexpr std::chrono::milliseconds ROUTER_TICK_INTERVAL = 250ms; @@ -1053,29 +1046,6 @@ namespace llarp _node_db->Tick(now); - if (_peer_db) - { - // TODO: throttle this? - // TODO: need to capture session stats when session terminates / is removed from link - // manager - _link_manager.update_peer_db(_peer_db); - - if (_peer_db->shouldFlush(now)) - { - LogDebug("Queing database flush..."); - queue_disk_io([this]() { - try - { - _peer_db->flushDatabase(); - } - catch (std::exception& ex) - { - LogError("Could not flush peer stats database: ", ex.what()); - } - }); - } - } - std::set peer_keys; for_each_connection( diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 11e00190f7..f622ccde4c 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -1,9 +1,5 @@ #pragma once -#include "rc_gossiper.hpp" -#include "rc_lookup_handler.hpp" -#include "route_poker.hpp" - #include #include #include @@ -14,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -28,7 +23,7 @@ #include #include #include - +#include #include #include #include @@ -38,7 +33,9 @@ #include #include -#include +#include "rc_gossiper.hpp" +#include "rc_lookup_handler.hpp" +#include "route_poker.hpp" /* TONUKE: @@ -115,7 +112,6 @@ namespace llarp llarp_time_t _last_stats_report = 0s; llarp_time_t _next_decomm_warning = time_now_ms() + 15s; std::shared_ptr _key_manager; - std::shared_ptr _peer_db; std::shared_ptr _config; uint32_t _path_build_count = 0; @@ -216,12 +212,6 @@ namespace llarp return _rc_lookup_handler; } - std::shared_ptr - peer_db() - { - return _peer_db; - } - inline int outbound_udp_socket() const { diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index 1ad7f1da02..3b28ee35a9 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -1,16 +1,13 @@ #include "router_contact.hpp" +#include + #include "constants/version.hpp" #include "crypto/crypto.hpp" #include "net/net.hpp" #include "util/bencode.hpp" #include "util/buffer.hpp" -#include "util/logging.hpp" -#include "util/mem.hpp" #include "util/time.hpp" - -#include - #include "util/file.hpp" namespace llarp diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index 31eaabacb5..fc8a009251 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -1,5 +1,11 @@ #pragma once +#include +#include +#include +#include +#include + #include "llarp/constants/version.hpp" #include "llarp/crypto/types.hpp" #include "llarp/net/exit_info.hpp" @@ -7,16 +13,8 @@ #include "llarp/util/bencode.hpp" #include "llarp/util/status.hpp" #include "router_version.hpp" - #include "llarp/dns/srv_data.hpp" -#include - -#include -#include -#include -#include - #define MAX_RC_SIZE (1024) namespace oxenc diff --git a/llarp/router_version.cpp b/llarp/router_version.cpp index 84c57f9dae..a033ee609b 100644 --- a/llarp/router_version.cpp +++ b/llarp/router_version.cpp @@ -1,8 +1,5 @@ #include "router_version.hpp" -#include "constants/version.hpp" -#include "constants/proto.hpp" -#include #include namespace llarp diff --git a/llarp/router_version.hpp b/llarp/router_version.hpp index ace16fd017..d9fa722006 100644 --- a/llarp/router_version.hpp +++ b/llarp/router_version.hpp @@ -1,6 +1,7 @@ #pragma once #include + #include "util/bencode.hpp" #include "constants/version.hpp" #include "constants/proto.hpp" diff --git a/llarp/rpc/endpoint_rpc.hpp b/llarp/rpc/endpoint_rpc.hpp index 73cfd12709..3663e3ac45 100644 --- a/llarp/rpc/endpoint_rpc.hpp +++ b/llarp/rpc/endpoint_rpc.hpp @@ -2,7 +2,6 @@ #include #include - #include namespace llarp::service diff --git a/llarp/rpc/json_conversions.hpp b/llarp/rpc/json_conversions.hpp index 95b9d547cb..50d2426eb6 100644 --- a/llarp/rpc/json_conversions.hpp +++ b/llarp/rpc/json_conversions.hpp @@ -2,6 +2,7 @@ #include #include + #include "json_binary_proxy.hpp" namespace llarp diff --git a/llarp/rpc/lokid_rpc_client.cpp b/llarp/rpc/lokid_rpc_client.cpp index 001a7c8a84..65c2df893b 100644 --- a/llarp/rpc/lokid_rpc_client.cpp +++ b/llarp/rpc/lokid_rpc_client.cpp @@ -1,14 +1,10 @@ #include "lokid_rpc_client.hpp" -#include #include - #include - #include -#include #include -#include +#include namespace llarp::rpc { @@ -45,8 +41,6 @@ namespace llarp::rpc // TODO: proper auth here auto lokidCategory = m_lokiMQ->add_category("lokid", oxenmq::Access{oxenmq::AuthLevel::none}); - lokidCategory.add_request_command( - "get_peer_stats", [this](oxenmq::Message& m) { HandleGetPeerStats(m); }); m_UpdatingList = false; } @@ -392,73 +386,4 @@ namespace llarp::rpc req.dump()); } - void - LokidRpcClient::HandleGetPeerStats(oxenmq::Message& msg) - { - LogInfo("Got request for peer stats (size: ", msg.data.size(), ")"); - for (auto str : msg.data) - { - LogInfo(" :", str); - } - - if (auto router = m_Router.lock()) - { - if (not router->peer_db()) - { - LogWarn("HandleGetPeerStats called when router has no peerDb set up."); - - // TODO: this can sometimes occur if lokid hits our API before we're done configuring - // (mostly an issue in a loopback testnet) - msg.send_reply("EAGAIN"); - return; - } - - try - { - // msg.data[0] is expected to contain a bt list of router ids (in our preferred string - // format) - if (msg.data.empty()) - { - LogWarn("lokid requested peer stats with no request body"); - msg.send_reply("peer stats request requires list of router IDs"); - return; - } - - std::vector routerIdStrings; - oxenc::bt_deserialize(msg.data[0], routerIdStrings); - - std::vector routerIds; - routerIds.reserve(routerIdStrings.size()); - - for (const auto& routerIdString : routerIdStrings) - { - RouterID id; - if (not id.FromString(routerIdString)) - { - LogWarn("lokid sent us an invalid router id: ", routerIdString); - msg.send_reply("Invalid router id"); - return; - } - - routerIds.push_back(std::move(id)); - } - - auto statsList = router->peer_db()->listPeerStats(routerIds); - - int32_t bufSize = - 256 + (statsList.size() * 1024); // TODO: tune this or allow to grow dynamically - auto buf = std::unique_ptr(new uint8_t[bufSize]); - llarp_buffer_t llarpBuf(buf.get(), bufSize); - - PeerStats::BEncodeList(statsList, &llarpBuf); - - msg.send_reply(std::string_view((const char*)llarpBuf.base, llarpBuf.cur - llarpBuf.base)); - } - catch (const std::exception& e) - { - LogError("Failed to handle get_peer_stats request: ", e.what()); - msg.send_reply("server error"); - } - } - } } // namespace llarp::rpc diff --git a/llarp/rpc/lokid_rpc_client.hpp b/llarp/rpc/lokid_rpc_client.hpp index 306c59b117..bc13e18ad2 100644 --- a/llarp/rpc/lokid_rpc_client.hpp +++ b/llarp/rpc/lokid_rpc_client.hpp @@ -1,7 +1,6 @@ #pragma once #include - #include #include #include @@ -76,10 +75,6 @@ namespace llarp void HandleNewServiceNodeList(const nlohmann::json& json); - // Handles request from lokid for peer stats on a specific peer - void - HandleGetPeerStats(oxenmq::Message& msg); - // Handles notification of a new block void HandleNewBlock(oxenmq::Message& msg); diff --git a/llarp/rpc/rpc_request_definitions.hpp b/llarp/rpc/rpc_request_definitions.hpp index 340eb6c411..01b4a8872d 100644 --- a/llarp/rpc/rpc_request_definitions.hpp +++ b/llarp/rpc/rpc_request_definitions.hpp @@ -1,11 +1,13 @@ #pragma once #include "rpc_request_decorators.hpp" -#include "llarp/net/ip_range.hpp" -#include "llarp/router/route_poker.hpp" -#include "llarp/service/address.hpp" -#include "llarp/service/endpoint.hpp" -#include "llarp/service/outbound_context.hpp" + +#include +#include +#include +#include +#include + #include #include #include diff --git a/llarp/rpc/rpc_request_parser.cpp b/llarp/rpc/rpc_request_parser.cpp index 53eee05ae5..3cb40bffd2 100644 --- a/llarp/rpc/rpc_request_parser.cpp +++ b/llarp/rpc/rpc_request_parser.cpp @@ -1,11 +1,7 @@ #include "rpc_request_parser.hpp" + #include "llarp/rpc/rpc_request_definitions.hpp" #include "param_parser.hpp" -#include -#include -#include -#include -#include namespace llarp::rpc { diff --git a/llarp/rpc/rpc_request_parser.hpp b/llarp/rpc/rpc_request_parser.hpp index e28c128550..788bad17d5 100644 --- a/llarp/rpc/rpc_request_parser.hpp +++ b/llarp/rpc/rpc_request_parser.hpp @@ -1,11 +1,12 @@ #pragma once -#include "rpc_request_definitions.hpp" -#include #include #include #include #include +#include + +#include "rpc_request_definitions.hpp" namespace llarp::rpc { diff --git a/llarp/rpc/rpc_server.cpp b/llarp/rpc/rpc_server.cpp index 2f08011ce9..4b646914d0 100644 --- a/llarp/rpc/rpc_server.cpp +++ b/llarp/rpc/rpc_server.cpp @@ -1,25 +1,20 @@ #include "rpc_server.hpp" -#include "llarp/rpc/rpc_request_definitions.hpp" #include "rpc_request.hpp" -#include "llarp/service/address.hpp" -#include -#include -#include + #include #include -#include #include -#include +#include #include #include -#include -#include -#include -#include +#include #include -#include +#include + +#include + +#include #include -#include namespace llarp::rpc { @@ -599,7 +594,8 @@ namespace llarp::rpc if (endpoint == "unsubscribe") { - log::info(logcat, "New logs unsubscribe request from conn {}@{}", m.conn, m.remote); + log::info( + logcat, "New logs unsubscribe request from conn {}@{}", m.conn.to_string(), m.remote); log_subs.unsubscribe(m.conn); m.send_reply("OK"); return; @@ -609,13 +605,18 @@ namespace llarp::rpc if (is_new) { - log::info(logcat, "New logs subscription request from conn {}@{}", m.conn, m.remote); + log::info( + logcat, "New logs subscription request from conn {}@{}", m.conn.to_string(), m.remote); m.send_reply("OK"); log_subs.send_all(m.conn, endpoint); } else { - log::debug(logcat, "Renewed logs subscription request from conn id {}@{}", m.conn, m.remote); + log::debug( + logcat, + "Renewed logs subscription request from conn id {}@{}", + m.conn.to_string(), + m.remote); m.send_reply("ALREADY"); } } diff --git a/llarp/rpc/rpc_server.hpp b/llarp/rpc/rpc_server.hpp index 56bb1f11e0..9be8962557 100644 --- a/llarp/rpc/rpc_server.hpp +++ b/llarp/rpc/rpc_server.hpp @@ -1,15 +1,17 @@ #pragma once -#include "rpc_request_definitions.hpp" -#include "json_bt.hpp" -#include -#include -#include #include + +#include #include #include #include #include +#include +#include + +#include "rpc_request_definitions.hpp" +#include "json_bt.hpp" namespace llarp { diff --git a/llarp/service/async_key_exchange.hpp b/llarp/service/async_key_exchange.hpp index 3957bc4ac8..3ab0b8f4e0 100644 --- a/llarp/service/async_key_exchange.hpp +++ b/llarp/service/async_key_exchange.hpp @@ -1,6 +1,7 @@ #pragma once #include + #include "identity.hpp" #include "protocol.hpp" diff --git a/llarp/service/auth.hpp b/llarp/service/auth.hpp index eb2f1a3c0e..7f18e31049 100644 --- a/llarp/service/auth.hpp +++ b/llarp/service/auth.hpp @@ -1,9 +1,10 @@ #pragma once +#include #include #include #include + #include "address.hpp" -#include namespace llarp { diff --git a/llarp/service/context.cpp b/llarp/service/context.cpp index 68b62c0144..b465e8f076 100644 --- a/llarp/service/context.cpp +++ b/llarp/service/context.cpp @@ -2,11 +2,10 @@ #include #include -#include -#include -#include "endpoint.hpp" #include +#include "endpoint.hpp" + namespace llarp { namespace service diff --git a/llarp/service/context.hpp b/llarp/service/context.hpp index f61a0fe90e..d975697d3e 100644 --- a/llarp/service/context.hpp +++ b/llarp/service/context.hpp @@ -3,10 +3,10 @@ #include #include #include -#include "endpoint.hpp" - #include +#include "endpoint.hpp" + /* TODO: - if we are only using one local endpoint, does this need to change to account for that? diff --git a/llarp/service/convotag.cpp b/llarp/service/convotag.cpp index b4b4eec615..f9077e83d5 100644 --- a/llarp/service/convotag.cpp +++ b/llarp/service/convotag.cpp @@ -1,5 +1,4 @@ #include "convotag.hpp" -#include namespace llarp::service { diff --git a/llarp/service/convotag.hpp b/llarp/service/convotag.hpp index ec9cdbab88..431d4546e5 100644 --- a/llarp/service/convotag.hpp +++ b/llarp/service/convotag.hpp @@ -2,7 +2,6 @@ #include #include - #include namespace llarp::service diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 4ede9518c0..2da9031ce5 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -1,17 +1,8 @@ #include "endpoint.hpp" -#include "endpoint_state.hpp" -#include "endpoint_util.hpp" -#include "auth.hpp" -#include "outbound_context.hpp" -#include "protocol.hpp" -#include "info.hpp" -#include "protocol_type.hpp" #include #include -#include #include -#include #include #include #include @@ -19,19 +10,21 @@ #include #include #include - -#include -#include -#include #include #include - #include #include #include -#include #include +#include "endpoint_state.hpp" +#include "endpoint_util.hpp" +#include "auth.hpp" +#include "outbound_context.hpp" +#include "protocol.hpp" +#include "info.hpp" +#include "protocol_type.hpp" + namespace llarp::service { static auto logcat = log::Cat("endpoint"); @@ -49,8 +42,8 @@ namespace llarp::service _state->name = "endpoint"; _recv_event_queue.enable(); - if (Loop()->MaybeGetUVWLoop()) - _tunnel_manager = std::make_unique(*this); + // if (Loop()->MaybeGetUVWLoop()) + // _tunnel_manager = std::make_unique(*this); } bool diff --git a/llarp/service/endpoint.hpp b/llarp/service/endpoint.hpp index 3d1dfb073a..b974fa4eb5 100644 --- a/llarp/service/endpoint.hpp +++ b/llarp/service/endpoint.hpp @@ -6,7 +6,6 @@ #include #include #include - // --- begin kitchen sink headers ---- #include #include @@ -19,13 +18,12 @@ #include // ----- end kitchen sink headers ----- -#include -#include -#include #include - #include #include +#include +#include +#include // minimum time between introset shifts #ifndef MIN_SHIFT_INTERVAL @@ -42,6 +40,7 @@ namespace llarp namespace service { struct AsyncKeyExchange; + struct Context; struct EndpointState; struct OutboundContext; diff --git a/llarp/service/endpoint_state.cpp b/llarp/service/endpoint_state.cpp index 7713a2df4b..e8c5b5eab2 100644 --- a/llarp/service/endpoint_state.cpp +++ b/llarp/service/endpoint_state.cpp @@ -1,10 +1,5 @@ #include "endpoint_state.hpp" -#include -#include "endpoint.hpp" -#include "outbound_context.hpp" -#include - namespace llarp::service { bool diff --git a/llarp/service/endpoint_state.hpp b/llarp/service/endpoint_state.hpp index b774e63d77..ba42a22bf4 100644 --- a/llarp/service/endpoint_state.hpp +++ b/llarp/service/endpoint_state.hpp @@ -1,22 +1,21 @@ #pragma once #include -#include "address.hpp" -#include "pendingbuffer.hpp" -#include "router_lookup_job.hpp" -#include "session.hpp" -#include "endpoint_types.hpp" #include #include #include -#include "lns_tracker.hpp" - +#include #include #include #include #include -#include +#include "address.hpp" +#include "pendingbuffer.hpp" +#include "router_lookup_job.hpp" +#include "session.hpp" +#include "endpoint_types.hpp" +#include "lns_tracker.hpp" namespace llarp::service { diff --git a/llarp/service/identity.cpp b/llarp/service/identity.cpp index b7a6d1ffa8..cc28f047be 100644 --- a/llarp/service/identity.cpp +++ b/llarp/service/identity.cpp @@ -1,8 +1,6 @@ #include "identity.hpp" #include -#include -#include namespace llarp::service { diff --git a/llarp/service/identity.hpp b/llarp/service/identity.hpp index 7628ad3952..9c53cba6f1 100644 --- a/llarp/service/identity.hpp +++ b/llarp/service/identity.hpp @@ -3,13 +3,13 @@ #include #include #include +#include #include +#include + #include "info.hpp" #include "intro_set.hpp" #include "vanity.hpp" -#include - -#include namespace llarp::service { diff --git a/llarp/service/info.cpp b/llarp/service/info.cpp index f236307300..1f0630cfe1 100644 --- a/llarp/service/info.cpp +++ b/llarp/service/info.cpp @@ -1,13 +1,8 @@ #include "info.hpp" #include -#include "address.hpp" -#include - -#include -#include -#include +#include "address.hpp" namespace llarp::service { diff --git a/llarp/service/info.hpp b/llarp/service/info.hpp index bf610d6ad7..5e97e34ad3 100644 --- a/llarp/service/info.hpp +++ b/llarp/service/info.hpp @@ -1,14 +1,13 @@ #pragma once #include - #include -#include "address.hpp" -#include "vanity.hpp" #include - #include +#include "address.hpp" +#include "vanity.hpp" + namespace { static auto info_cat = llarp::log::Cat("lokinet.info"); diff --git a/llarp/service/intro.hpp b/llarp/service/intro.hpp index 7dd780c86c..0ec46b35d5 100644 --- a/llarp/service/intro.hpp +++ b/llarp/service/intro.hpp @@ -1,12 +1,10 @@ #pragma once #include - #include #include #include #include - #include namespace diff --git a/llarp/service/intro_set.cpp b/llarp/service/intro_set.cpp index e4410fc41e..68f1533cae 100644 --- a/llarp/service/intro_set.cpp +++ b/llarp/service/intro_set.cpp @@ -1,7 +1,6 @@ #include "intro_set.hpp" -#include -#include +#include #include namespace llarp::service @@ -186,33 +185,33 @@ namespace llarp::service IntroSet::ExtractStatus() const { util::StatusObject obj{{"published", to_json(time_signed)}}; - std::vector introsObjs; - std::transform( - intros.begin(), - intros.end(), - std::back_inserter(introsObjs), - [](const auto& intro) -> util::StatusObject { return intro.ExtractStatus(); }); - obj["intros"] = introsObjs; - if (!topic.IsZero()) - obj["topic"] = topic.ToString(); - - std::vector protocols; - std::transform( - supported_protocols.begin(), - supported_protocols.end(), - std::back_inserter(protocols), - [](const auto& proto) -> util::StatusObject { return service::ToString(proto); }); - obj["protos"] = protocols; - std::vector ranges; - std::transform( - owned_ranges.begin(), - owned_ranges.end(), - std::back_inserter(ranges), - [](const auto& range) -> util::StatusObject { return range.ToString(); }); - - obj["advertisedRanges"] = ranges; - if (exit_policy) - obj["exitPolicy"] = exit_policy->ExtractStatus(); + // std::vector introsObjs; + // std::transform( + // intros.begin(), + // intros.end(), + // std::back_inserter(introsObjs), + // [](const auto& intro) -> util::StatusObject { return intro.ExtractStatus(); }); + // obj["intros"] = introsObjs; + // if (!topic.IsZero()) + // obj["topic"] = topic.ToString(); + + // std::vector protocols; + // std::transform( + // supported_protocols.begin(), + // supported_protocols.end(), + // std::back_inserter(protocols), + // [](const auto& proto) -> util::StatusObject { return service::ToString(proto); }); + // obj["protos"] = protocols; + // std::vector ranges; + // std::transform( + // owned_ranges.begin(), + // owned_ranges.end(), + // std::back_inserter(ranges), + // [](const auto& range) -> util::StatusObject { return range.ToString(); }); + + // obj["advertisedRanges"] = ranges; + // if (exit_policy) + // obj["exitPolicy"] = exit_policy->ExtractStatus(); return obj; } diff --git a/llarp/service/intro_set.hpp b/llarp/service/intro_set.hpp index 725e240095..352d98f2ce 100644 --- a/llarp/service/intro_set.hpp +++ b/llarp/service/intro_set.hpp @@ -2,24 +2,23 @@ #include #include -#include "info.hpp" -#include "intro.hpp" -#include "tag.hpp" -#include "protocol_type.hpp" #include #include #include #include - #include #include - #include #include #include #include #include +#include "info.hpp" +#include "intro.hpp" +#include "tag.hpp" +#include "protocol_type.hpp" + namespace llarp::service { constexpr std::size_t MAX_INTROSET_SIZE = 4096; diff --git a/llarp/service/lns_tracker.hpp b/llarp/service/lns_tracker.hpp index aba31c509b..64fb1a3cdd 100644 --- a/llarp/service/lns_tracker.hpp +++ b/llarp/service/lns_tracker.hpp @@ -1,5 +1,7 @@ #pragma once +#include +#include #include #include #include @@ -7,8 +9,6 @@ #include #include "address.hpp" -#include -#include namespace llarp::service { diff --git a/llarp/service/name.hpp b/llarp/service/name.hpp index c16a8d025a..76e203b3c0 100644 --- a/llarp/service/name.hpp +++ b/llarp/service/name.hpp @@ -1,5 +1,6 @@ #pragma once #include + #include "address.hpp" namespace llarp::service diff --git a/llarp/service/outbound_context.cpp b/llarp/service/outbound_context.cpp index 5581f663ef..d1dcf74160 100644 --- a/llarp/service/outbound_context.cpp +++ b/llarp/service/outbound_context.cpp @@ -1,17 +1,14 @@ #include "outbound_context.hpp" -#include "async_key_exchange.hpp" -#include "endpoint.hpp" -#include "endpoint_util.hpp" -#include "protocol_type.hpp" #include -#include -#include -#include - #include #include +#include "async_key_exchange.hpp" +#include "endpoint.hpp" +#include "endpoint_util.hpp" +#include "protocol_type.hpp" + namespace llarp::service { bool diff --git a/llarp/service/outbound_context.hpp b/llarp/service/outbound_context.hpp index 4d89e0646e..802d6a9107 100644 --- a/llarp/service/outbound_context.hpp +++ b/llarp/service/outbound_context.hpp @@ -4,13 +4,13 @@ #include #include #include - #include #include namespace llarp::service { struct AsyncKeyExchange; + struct Endpoint; /// context needed to initiate an outbound hidden service session diff --git a/llarp/service/protocol.cpp b/llarp/service/protocol.cpp index 02b0153a92..59fc042e07 100644 --- a/llarp/service/protocol.cpp +++ b/llarp/service/protocol.cpp @@ -1,12 +1,12 @@ #include "protocol.hpp" -#include "endpoint.hpp" #include #include -#include #include #include +#include "endpoint.hpp" + namespace llarp::service { ProtocolMessage::ProtocolMessage() diff --git a/llarp/service/protocol.hpp b/llarp/service/protocol.hpp index b7cfd20ba6..bc85f0c285 100644 --- a/llarp/service/protocol.hpp +++ b/llarp/service/protocol.hpp @@ -3,16 +3,16 @@ #include #include #include -#include "protocol_type.hpp" -#include "identity.hpp" -#include "info.hpp" -#include "intro.hpp" #include #include #include - #include +#include "protocol_type.hpp" +#include "identity.hpp" +#include "info.hpp" +#include "intro.hpp" + struct llarp_threadpool; namespace llarp diff --git a/llarp/service/session.hpp b/llarp/service/session.hpp index 856816d270..a811e2c4fa 100644 --- a/llarp/service/session.hpp +++ b/llarp/service/session.hpp @@ -2,11 +2,12 @@ #include #include -#include "info.hpp" -#include "intro.hpp" #include #include +#include "info.hpp" +#include "intro.hpp" + namespace llarp::service { static constexpr auto SessionLifetime = path::DEFAULT_LIFETIME * 2; diff --git a/llarp/service/tag.hpp b/llarp/service/tag.hpp index a4e3dba4eb..64a9493407 100644 --- a/llarp/service/tag.hpp +++ b/llarp/service/tag.hpp @@ -3,7 +3,6 @@ #include #include #include - #include namespace llarp diff --git a/llarp/util/bencode.cpp b/llarp/util/bencode.cpp index 73966291be..2b94c52fb6 100644 --- a/llarp/util/bencode.cpp +++ b/llarp/util/bencode.cpp @@ -1,7 +1,7 @@ #include "bencode.hpp" + #include #include -#include bool bencode_read_integer(struct llarp_buffer_t* buffer, uint64_t* result) diff --git a/llarp/util/bencode.h b/llarp/util/bencode.h index fb6940d6a8..7770fc8ebd 100644 --- a/llarp/util/bencode.h +++ b/llarp/util/bencode.h @@ -1,13 +1,12 @@ #pragma once #include -#include "buffer.hpp" -#include "common.hpp" - #include - #include +#include "buffer.hpp" +#include "common.hpp" + /** * bencode.h * diff --git a/llarp/util/bencode.hpp b/llarp/util/bencode.hpp index 09a26bbabf..f54f198891 100644 --- a/llarp/util/bencode.hpp +++ b/llarp/util/bencode.hpp @@ -1,16 +1,16 @@ #pragma once -#include "buffer.hpp" -#include "bencode.h" -#include "file.hpp" #include #include -#include "mem.hpp" - #include #include #include +#include "buffer.hpp" +#include "bencode.h" +#include "file.hpp" +#include "mem.hpp" + namespace llarp { static auto ben_cat = log::Cat("stupid.bencode"); diff --git a/llarp/util/buffer.hpp b/llarp/util/buffer.hpp index e7caa8e21a..d9f87d8e7a 100644 --- a/llarp/util/buffer.hpp +++ b/llarp/util/buffer.hpp @@ -1,13 +1,8 @@ #pragma once #include -#include "common.hpp" -#include "mem.h" -#include "types.hpp" - #include #include - #include #include #include @@ -17,6 +12,10 @@ #include #include +#include "common.hpp" +#include "mem.h" +#include "types.hpp" + namespace llarp { using byte_view_t = std::basic_string_view; diff --git a/llarp/util/easter_eggs.cpp b/llarp/util/easter_eggs.cpp deleted file mode 100644 index c3a658db9e..0000000000 --- a/llarp/util/easter_eggs.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "lokinet_init.h" - -#if defined(_WIN32) -#include -#include -#include - -#define WineKiller \ - DieInCaseSomehowThisGetsRunInWineButLikeWTFThatShouldNotHappenButJustInCaseHandleItWithAPopupOrSomeShit - -struct WineKiller -{ - WineKiller() - { - if (auto hntdll = GetModuleHandle("ntdll.dll")) - { - if (GetProcAddress(hntdll, "wine_get_version")) - { - static const char* text = - "dont run lokinet in wine like wtf man we support linux and pretty " - "much every flavour of BSD, and even some flavours of unix system " - "5.x.\nThis Program Will now crash lmao."; - static const char* title = "srsly fam wtf"; - MessageBoxA(NULL, text, title, MB_ICONHAND); - abort(); - } - } - } -}; - -// i heckin love static initalization -WineKiller lmao{}; -#endif - -extern "C" int -Lokinet_INIT(void) -{ - return 0; -} diff --git a/llarp/util/file.cpp b/llarp/util/file.cpp index 2cb914263e..a207b22884 100644 --- a/llarp/util/file.cpp +++ b/llarp/util/file.cpp @@ -1,14 +1,11 @@ #include "file.hpp" +#include "formattable.hpp" +#include "logging.hpp" + +#include #include #include #include - -#include -#include - -#include -#include -#include #include #ifdef WIN32 diff --git a/llarp/util/file.hpp b/llarp/util/file.hpp index a66b1555fa..d6cd9dfa48 100644 --- a/llarp/util/file.hpp +++ b/llarp/util/file.hpp @@ -1,11 +1,11 @@ #pragma once -#include "fs.hpp" - #include #include #include #include +#include "fs.hpp" + #ifndef _MSC_VER #include #endif diff --git a/llarp/util/json.cpp b/llarp/util/json.cpp deleted file mode 100644 index da79892582..0000000000 --- a/llarp/util/json.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "json.hpp" - -#include -#include -#include - -namespace llarp -{ - namespace json - { - struct NlohmannJSONParser : public IParser - { - NlohmannJSONParser(size_t contentSize) : m_Buf(contentSize + 1), m_Offset(0) - { - assert(contentSize != 0); - } - - std::vector m_Buf; - size_t m_Offset; - - bool - FeedData(const char* buf, size_t sz) override - { - if (sz == 0) - return true; - if (m_Offset + sz > m_Buf.size() - 1) - return false; - std::copy_n(buf, sz, m_Buf.data() + m_Offset); - m_Offset += sz; - m_Buf[m_Offset] = 0; - return true; - } - - Result - Parse(nlohmann::json& obj) const override - { - if (m_Offset < m_Buf.size() - 1) - return eNeedData; - - try - { - obj = nlohmann::json::parse(m_Buf.data()); - return eDone; - } - catch (const nlohmann::json::exception&) - { - return eParseError; - } - } - }; - - IParser* - MakeParser(size_t contentSize) - { - return new NlohmannJSONParser(contentSize); - } - - } // namespace json -} // namespace llarp diff --git a/llarp/util/json.hpp b/llarp/util/json.hpp deleted file mode 100644 index 8e7bf58995..0000000000 --- a/llarp/util/json.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include - -#include -#include - -namespace llarp -{ - namespace json - { - using Object = nlohmann::json; - - struct IParser - { - virtual ~IParser() = default; - - /// result from feeding data to parser - enum Result - { - /// we need more data to finish parsing - eNeedData, - /// we have parsed the object fully - eDone, - /// we have a parsing syntax error - eParseError - }; - - /// feed data to parser return true if successful - virtual bool - FeedData(const char* buf, size_t sz) = 0; - /// parse internal buffer - virtual Result - Parse(Object& obj) const = 0; - }; - - /// create new parser - IParser* - MakeParser(size_t contentSize); - - } // namespace json -} // namespace llarp diff --git a/llarp/util/logging/buffer.cpp b/llarp/util/logging/buffer.cpp index fe055b9f72..7ac69c90ef 100644 --- a/llarp/util/logging/buffer.cpp +++ b/llarp/util/logging/buffer.cpp @@ -1,6 +1,4 @@ #include "buffer.hpp" -#include -#include namespace llarp { diff --git a/llarp/util/logging/buffer.hpp b/llarp/util/logging/buffer.hpp index c228927d21..a6c46cf361 100644 --- a/llarp/util/logging/buffer.hpp +++ b/llarp/util/logging/buffer.hpp @@ -2,7 +2,6 @@ #include #include - #include #include #include diff --git a/llarp/util/str.cpp b/llarp/util/str.cpp index 1834e6ffcc..0270f63dc4 100644 --- a/llarp/util/str.cpp +++ b/llarp/util/str.cpp @@ -1,11 +1,7 @@ #include "str.hpp" -#include -#include #include -#include #include -#include #ifdef _WIN32 #include diff --git a/llarp/util/str.hpp b/llarp/util/str.hpp index 2e510c734f..0c120cbc2c 100644 --- a/llarp/util/str.hpp +++ b/llarp/util/str.hpp @@ -1,11 +1,11 @@ #pragma once +#include #include #include #include #include #include -#include namespace llarp { diff --git a/llarp/util/thread/queue_manager.cpp b/llarp/util/thread/queue_manager.cpp index e47d77b9bd..38eabd7453 100644 --- a/llarp/util/thread/queue_manager.cpp +++ b/llarp/util/thread/queue_manager.cpp @@ -1,5 +1,4 @@ #include "queue_manager.hpp" -#include "threading.hpp" #include diff --git a/llarp/util/thread/threading.hpp b/llarp/util/thread/threading.hpp index 4afdb0eb3e..d50a630423 100644 --- a/llarp/util/thread/threading.hpp +++ b/llarp/util/thread/threading.hpp @@ -5,14 +5,14 @@ #include #include #include - -#include "annotations.hpp" - #include #include +#include "annotations.hpp" + #if defined(WIN32) && !defined(__GNUC__) #include + using pid_t = int; #else #include @@ -21,6 +21,7 @@ using pid_t = int; #ifdef TRACY_ENABLE #include + #define DECLARE_LOCK(type, var, ...) TracyLockable(type, var) #else #define DECLARE_LOCK(type, var, ...) type var __VA_ARGS__ diff --git a/llarp/util/time.cpp b/llarp/util/time.cpp index 1b0b243513..af36a55dd7 100644 --- a/llarp/util/time.cpp +++ b/llarp/util/time.cpp @@ -1,6 +1,5 @@ #include "time.hpp" -#include -#include + #include "types.hpp" namespace llarp diff --git a/llarp/util/time.hpp b/llarp/util/time.hpp index ef73f50fca..773083ba2d 100644 --- a/llarp/util/time.hpp +++ b/llarp/util/time.hpp @@ -1,10 +1,11 @@ #pragma once -#include "types.hpp" #include -#include #include #include +#include + +#include "types.hpp" using namespace std::chrono_literals; diff --git a/llarp/vpn/platform.cpp b/llarp/vpn/platform.cpp index 28a93b96ae..f59f15a008 100644 --- a/llarp/vpn/platform.cpp +++ b/llarp/vpn/platform.cpp @@ -12,8 +12,6 @@ #endif #endif -#include - namespace llarp::vpn { const llarp::net::Platform* diff --git a/llarp/vpn/platform.hpp b/llarp/vpn/platform.hpp index f449b86db9..62534d33c0 100644 --- a/llarp/vpn/platform.hpp +++ b/llarp/vpn/platform.hpp @@ -4,11 +4,10 @@ #include #include #include +#include #include "i_packet_io.hpp" -#include - namespace llarp { struct Context; From b597ae5a94bc18351f3c2b00a345b36130c58d1f Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Thu, 19 Oct 2023 20:09:22 -0300 Subject: [PATCH 066/312] "Refactor" aka delete Crypto/CryptoManager - Get rid of CryptoManager. - Get rid of Crypto. - Move all the Crypto instance methods to llarp::crypto functions. (None of them needed to be methods at all, so this is simple). - Move sodium/ntru initialization into static initialization. - Add llarp::csrng, which is an available llarp::CSRNG instance which is a bit easier than needing to construct a `CSRNG rng{};` in various places. - Various related small simplifications/cleanups. --- include/llarp.hpp | 4 - llarp/config/key_manager.cpp | 12 +-- llarp/consensus/reachability_testing.cpp | 11 +- llarp/context.cpp | 3 - llarp/crypto/crypto.cpp | 100 +++++++++--------- llarp/crypto/crypto.hpp | 47 ++------ llarp/crypto/encrypted_frame.cpp | 26 ++--- llarp/crypto/types.hpp | 6 +- llarp/exit/session.cpp | 2 +- llarp/link/link_manager.cpp | 24 ++--- llarp/lokinet_shared.cpp | 2 - llarp/messages/exit.hpp | 12 +-- llarp/messages/path.hpp | 18 ++-- llarp/nodedb.hpp | 2 +- llarp/path/path.cpp | 8 +- llarp/path/pathbuilder.cpp | 18 ++-- llarp/path/pathset.cpp | 7 +- llarp/path/transit_hop.cpp | 6 +- llarp/pow.cpp | 2 +- llarp/router/rc_gossiper.cpp | 3 +- llarp/router/rc_lookup_handler.cpp | 2 +- llarp/router/router.cpp | 4 +- llarp/router_contact.cpp | 4 +- llarp/service/address.cpp | 2 +- llarp/service/async_key_exchange.cpp | 11 +- llarp/service/auth.cpp | 2 +- llarp/service/endpoint.cpp | 2 +- llarp/service/identity.cpp | 20 ++-- llarp/service/info.cpp | 2 +- llarp/service/intro_set.cpp | 10 +- llarp/service/name.cpp | 3 +- llarp/service/outbound_context.cpp | 16 ++- llarp/service/protocol.cpp | 21 ++-- llarp/win32/guid.hpp | 2 +- test/crypto/test_llarp_crypto.cpp | 4 - test/crypto/test_llarp_key_manager.cpp | 3 +- test/llarp_test.hpp | 30 ------ .../test_llarp_routing_obtainexitmessage.cpp | 5 +- test/service/test_llarp_service_identity.cpp | 51 +++------ test/service/test_llarp_service_name.cpp | 5 +- test/test_llarp_encrypted_frame.cpp | 8 +- test/test_llarp_router_contact.cpp | 31 +++--- 42 files changed, 201 insertions(+), 350 deletions(-) delete mode 100644 test/llarp_test.hpp diff --git a/include/llarp.hpp b/include/llarp.hpp index 50955b868a..0767ff33e7 100644 --- a/include/llarp.hpp +++ b/include/llarp.hpp @@ -19,8 +19,6 @@ namespace llarp struct Config; struct RouterContact; struct Config; - struct Crypto; - struct CryptoManager; struct Router; class NodeDB; @@ -38,8 +36,6 @@ namespace llarp struct Context { - std::shared_ptr crypto = nullptr; - std::shared_ptr cryptoManager = nullptr; std::shared_ptr router = nullptr; std::shared_ptr loop = nullptr; std::shared_ptr nodedb = nullptr; diff --git a/llarp/config/key_manager.cpp b/llarp/config/key_manager.cpp index c1968d0a97..ae63a68f5e 100644 --- a/llarp/config/key_manager.cpp +++ b/llarp/config/key_manager.cpp @@ -19,9 +19,9 @@ namespace llarp if (not isSNode) { - CryptoManager::instance()->identity_keygen(identityKey); - CryptoManager::instance()->encryption_keygen(encryptionKey); - CryptoManager::instance()->encryption_keygen(transportKey); + crypto::identity_keygen(identityKey); + crypto::encryption_keygen(encryptionKey); + crypto::encryption_keygen(transportKey); return true; } @@ -93,7 +93,7 @@ namespace llarp // load identity key or create if needed auto identityKeygen = [](llarp::SecretKey& key) { // TODO: handle generating from service node seed - llarp::CryptoManager::instance()->identity_keygen(key); + llarp::crypto::identity_keygen(key); }; if (not loadOrCreateKey(m_idKeyPath, identityKey, identityKeygen)) return false; @@ -101,7 +101,7 @@ namespace llarp // load encryption key auto encryptionKeygen = [](llarp::SecretKey& key) { - llarp::CryptoManager::instance()->encryption_keygen(key); + llarp::crypto::encryption_keygen(key); }; if (not loadOrCreateKey(m_encKeyPath, encryptionKey, encryptionKeygen)) return false; @@ -109,7 +109,7 @@ namespace llarp // TODO: transport key (currently done in LinkLayer) auto transportKeygen = [](llarp::SecretKey& key) { key.Zero(); - CryptoManager::instance()->encryption_keygen(key); + crypto::encryption_keygen(key); }; if (not loadOrCreateKey(m_transportKeyPath, transportKey, transportKeygen)) return false; diff --git a/llarp/consensus/reachability_testing.cpp b/llarp/consensus/reachability_testing.cpp index 33f0b9483b..adaf82136d 100644 --- a/llarp/consensus/reachability_testing.cpp +++ b/llarp/consensus/reachability_testing.cpp @@ -76,9 +76,9 @@ namespace llarp::consensus { if (next_general_test > now) return std::nullopt; - CSRNG rng; - next_general_test = - now + std::chrono::duration_cast(fseconds(TESTING_INTERVAL(rng))); + next_general_test = now + + std::chrono::duration_cast( + fseconds(TESTING_INTERVAL(llarp::csrng))); // Pull the next element off the queue, but skip ourself, any that are no longer registered, and // any that are currently known to be failing (those are queued for testing separately). @@ -107,7 +107,7 @@ namespace llarp::consensus const auto all = router->router_whitelist(); testing_queue.insert(testing_queue.begin(), all.begin(), all.end()); - std::shuffle(testing_queue.begin(), testing_queue.end(), rng); + std::shuffle(testing_queue.begin(), testing_queue.end(), llarp::csrng); // Recurse with the rebuilt list, but don't let it try rebuilding again return next_random(router, now, false); @@ -138,9 +138,8 @@ namespace llarp::consensus if (previous_failures < 0) previous_failures = 0; - CSRNG rng; auto next_test_in = duration_cast( - previous_failures * TESTING_BACKOFF + fseconds{TESTING_INTERVAL(rng)}); + previous_failures * TESTING_BACKOFF + fseconds{TESTING_INTERVAL(llarp::csrng)}); if (next_test_in > TESTING_BACKOFF_MAX) next_test_in = TESTING_BACKOFF_MAX; diff --git a/llarp/context.cpp b/llarp/context.cpp index 4dbb9d7096..ec2377844d 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -67,9 +67,6 @@ namespace llarp loop = EventLoop::create(jobQueueSize); } - crypto = std::make_shared(); - cryptoManager = std::make_shared(crypto.get()); - router = makeRouter(loop); nodedb = makeNodeDB(); diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index 8491f2f18c..79b71ab8bf 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -108,28 +108,8 @@ namespace llarp return false; } - Crypto::Crypto() - { - if (sodium_init() == -1) - { - throw std::runtime_error("sodium_init() returned -1"); - } - char* avx2 = std::getenv("AVX2_FORCE_DISABLE"); - if (avx2 && std::string(avx2) == "1") - { - ntru_init(1); - } - else - { - ntru_init(0); - } - int seed = 0; - randombytes(reinterpret_cast(&seed), sizeof(seed)); - srand(seed); - } - std::optional> - Crypto::maybe_decrypt_name(std::string_view ciphertext, SymmNonce nounce, std::string_view name) + crypto::maybe_decrypt_name(std::string_view ciphertext, SymmNonce nounce, std::string_view name) { const auto payloadsize = ciphertext.size() - crypto_aead_xchacha20poly1305_ietf_ABYTES; if (payloadsize != 32) @@ -162,32 +142,33 @@ namespace llarp } bool - Crypto::xchacha20(uint8_t* buf, size_t size, const SharedSecret& k, const TunnelNonce& n) + crypto::xchacha20(uint8_t* buf, size_t size, const SharedSecret& k, const TunnelNonce& n) { - return crypto_stream_xchacha20_xor(buf, buf, size, n.data(), k.data()) == 0; + return xchacha20(buf, size, n.data(), k.data()); } bool - Crypto::xchacha20(uint8_t* buf, size_t size, const uint8_t* secret, const uint8_t* nonce) + crypto::xchacha20(uint8_t* buf, size_t size, const uint8_t* secret, const uint8_t* nonce) { return crypto_stream_xchacha20_xor(buf, buf, size, nonce, secret) == 0; } bool - Crypto::dh_client( + crypto::dh_client( llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n) { return dh_client_priv(shared, pk, sk, n); } /// path dh relay side bool - Crypto::dh_server( + crypto::dh_server( llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n) { return dh_server_priv(shared, pk, sk, n); } + bool - Crypto::dh_server( + crypto::dh_server( uint8_t* shared_secret, const uint8_t* other_pk, const uint8_t* local_pk, @@ -197,27 +178,27 @@ namespace llarp } /// transport dh client side bool - Crypto::transport_dh_client( + crypto::transport_dh_client( llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n) { return dh_client_priv(shared, pk, sk, n); } /// transport dh server side bool - Crypto::transport_dh_server( + crypto::transport_dh_server( llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n) { return dh_server_priv(shared, pk, sk, n); } bool - Crypto::shorthash(ShortHash& result, uint8_t* buf, size_t size) + crypto::shorthash(ShortHash& result, uint8_t* buf, size_t size) { return crypto_generichash_blake2b(result.data(), ShortHash::SIZE, buf, size, nullptr, 0) != -1; } bool - Crypto::hmac(uint8_t* result, uint8_t* buf, size_t size, const SharedSecret& secret) + crypto::hmac(uint8_t* result, uint8_t* buf, size_t size, const SharedSecret& secret) { return crypto_generichash_blake2b(result, HMACSIZE, buf, size, secret.data(), HMACSECSIZE) != -1; @@ -230,25 +211,25 @@ namespace llarp } bool - Crypto::sign(Signature& sig, const SecretKey& secret, uint8_t* buf, size_t size) + crypto::sign(Signature& sig, const SecretKey& secret, uint8_t* buf, size_t size) { return crypto_sign_detached(sig.data(), nullptr, buf, size, secret.data()) != -1; } bool - Crypto::sign(uint8_t* sig, uint8_t* sk, uint8_t* buf, size_t size) + crypto::sign(uint8_t* sig, uint8_t* sk, uint8_t* buf, size_t size) { return crypto_sign_detached(sig, nullptr, buf, size, sk) != -1; } bool - Crypto::sign(uint8_t* sig, const SecretKey& sk, ustring_view buf) + crypto::sign(uint8_t* sig, const SecretKey& sk, ustring_view buf) { return crypto_sign_detached(sig, nullptr, buf.data(), buf.size(), sk.data()) != -1; } bool - Crypto::sign(Signature& sig, const PrivateKey& privkey, uint8_t* buf, size_t size) + crypto::sign(Signature& sig, const PrivateKey& privkey, uint8_t* buf, size_t size) { PubKey pubkey; @@ -292,13 +273,13 @@ namespace llarp } bool - Crypto::verify(const PubKey& pub, uint8_t* buf, size_t size, const Signature& sig) + crypto::verify(const PubKey& pub, uint8_t* buf, size_t size, const Signature& sig) { return crypto_sign_verify_detached(sig.data(), buf, size, pub.data()) != -1; } bool - Crypto::verify(ustring_view pub, ustring_view buf, ustring_view sig) + crypto::verify(ustring_view pub, ustring_view buf, ustring_view sig) { return (pub.size() == 32 && sig.size() == 64) ? crypto_sign_verify_detached(sig.data(), buf.data(), buf.size(), pub.data()) != -1 @@ -306,7 +287,7 @@ namespace llarp } bool - Crypto::verify(uint8_t* pub, uint8_t* buf, size_t size, uint8_t* sig) + crypto::verify(uint8_t* pub, uint8_t* buf, size_t size, uint8_t* sig) { return crypto_sign_verify_detached(sig, buf, size, pub) != -1; } @@ -363,7 +344,7 @@ namespace llarp static AlignedBuffer<32> zero; bool - Crypto::derive_subkey( + crypto::derive_subkey( PubKey& out_pubkey, const PubKey& root_pubkey, uint64_t key_n, const AlignedBuffer<32>* hash) { // scalar h = H( BLIND-STRING || root_pubkey || key_n ) @@ -380,7 +361,7 @@ namespace llarp } bool - Crypto::derive_subkey_private( + crypto::derive_subkey_private( PrivateKey& out_key, const SecretKey& root_key, uint64_t key_n, const AlignedBuffer<32>* hash) { // Derives a private subkey from a root key. @@ -447,24 +428,24 @@ namespace llarp } bool - Crypto::seed_to_secretkey(llarp::SecretKey& secret, const llarp::IdentitySecret& seed) + 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) + crypto::randomize(uint8_t* buf, size_t len) { randombytes(buf, len); } void - Crypto::randbytes(byte_t* ptr, size_t sz) + crypto::randbytes(byte_t* ptr, size_t sz) { randombytes((unsigned char*)ptr, sz); } void - Crypto::identity_keygen(llarp::SecretKey& keys) + crypto::identity_keygen(llarp::SecretKey& keys) { PubKey pk; int result = crypto_sign_keypair(pk.data(), keys.data()); @@ -478,7 +459,7 @@ namespace llarp } bool - Crypto::check_identity_privkey(const llarp::SecretKey& keys) + crypto::check_identity_privkey(const llarp::SecretKey& keys) { AlignedBuffer seed; llarp::PubKey pk; @@ -491,7 +472,7 @@ namespace llarp } void - Crypto::encryption_keygen(llarp::SecretKey& keys) + crypto::encryption_keygen(llarp::SecretKey& keys) { auto d = keys.data(); randbytes(d, 32); @@ -499,26 +480,26 @@ namespace llarp } bool - Crypto::pqe_encrypt(PQCipherBlock& ciphertext, SharedSecret& sharedkey, const PQPubKey& pubkey) + crypto::pqe_encrypt(PQCipherBlock& ciphertext, SharedSecret& sharedkey, const PQPubKey& pubkey) { return crypto_kem_enc(ciphertext.data(), sharedkey.data(), pubkey.data()) != -1; } bool - Crypto::pqe_decrypt( + crypto::pqe_decrypt( const PQCipherBlock& ciphertext, SharedSecret& sharedkey, const byte_t* secretkey) { return crypto_kem_dec(sharedkey.data(), ciphertext.data(), secretkey) != -1; } void - Crypto::pqe_keygen(PQKeyPair& keypair) + crypto::pqe_keygen(PQKeyPair& keypair) { auto d = keypair.data(); crypto_kem_keypair(d + PQ_SECRETKEYSIZE, d); } bool - Crypto::check_passwd_hash(std::string pwhash, std::string challenge) + crypto::check_passwd_hash(std::string pwhash, std::string challenge) { (void)pwhash; (void)challenge; @@ -561,4 +542,23 @@ namespace llarp randombytes((byte_t*)&i, sizeof(i)); return i; } + + // Called during static initialization to initialize libsodium and ntru. (The CSRNG return is not + // useful, but just here to get this called during static initialization of `llarp::csrng`). + static CSRNG + _initialize_crypto() + { + if (sodium_init() == -1) + { + log::critical(log::Cat("initialization"), "sodium_init() failed, unable to continue!"); + std::abort(); + } + char* avx2 = std::getenv("AVX2_FORCE_DISABLE"); + ntru_init(avx2 && avx2 == "1"sv); + + return CSRNG{}; + } + + CSRNG csrng = _initialize_crypto(); + } // namespace llarp diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index 43db0b3595..2bb41122c2 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -15,12 +15,8 @@ namespace llarp - */ - struct Crypto + namespace crypto { - Crypto(); - - ~Crypto() = default; - /// decrypt cipherText given the key generated from name std::optional> maybe_decrypt_name(std::string_view ciphertext, SymmNonce nounce, std::string_view name); @@ -136,39 +132,6 @@ namespace llarp const byte_t* pq_keypair_to_secret(const PQKeyPair& keypair); - struct CryptoManager - { - private: - static Crypto* m_crypto; - - Crypto* m_prevCrypto; - - public: - explicit CryptoManager(Crypto* crypto) : m_prevCrypto(m_crypto) - { - m_crypto = crypto; - } - - ~CryptoManager() - { - m_crypto = m_prevCrypto; - } - - static Crypto* - instance() - { -#ifdef NDEBUG - return m_crypto; -#else - if (m_crypto) - return m_crypto; - - assert(false && "Cryptomanager::instance() was undefined"); - abort(); -#endif - } - }; - /// rng type that uses llarp::randint(), which is cryptographically secure struct CSRNG { @@ -178,19 +141,21 @@ namespace llarp min() { return std::numeric_limits::min(); - }; + } static constexpr uint64_t max() { return std::numeric_limits::max(); - }; + } uint64_t operator()() { return llarp::randint(); - }; + } }; + extern CSRNG csrng; + } // namespace llarp diff --git a/llarp/crypto/encrypted_frame.cpp b/llarp/crypto/encrypted_frame.cpp index f955183135..d8ca8c088e 100644 --- a/llarp/crypto/encrypted_frame.cpp +++ b/llarp/crypto/encrypted_frame.cpp @@ -9,8 +9,6 @@ namespace llarp bool EncryptedFrame::DoEncrypt(const SharedSecret& shared, bool noDH) { - auto crypto = CryptoManager::instance(); - uint8_t* hash_ptr = data(); uint8_t* nonce_ptr = hash_ptr + SHORTHASHSIZE; uint8_t* pubkey_ptr = nonce_ptr + TUNNONCESIZE; @@ -18,20 +16,20 @@ namespace llarp if (noDH) { - crypto->randbytes(nonce_ptr, TUNNONCESIZE); - crypto->randbytes(pubkey_ptr, PUBKEYSIZE); + crypto::randbytes(nonce_ptr, TUNNONCESIZE); + crypto::randbytes(pubkey_ptr, PUBKEYSIZE); } TunnelNonce nonce(nonce_ptr); // encrypt body - if (!crypto->xchacha20(body_ptr, size() - EncryptedFrameOverheadSize, shared, nonce)) + if (!crypto::xchacha20(body_ptr, size() - EncryptedFrameOverheadSize, shared, nonce)) { llarp::LogError("encrypt failed"); return false; } - if (!crypto->hmac(hash_ptr, nonce_ptr, size() - SHORTHASHSIZE, shared)) + if (!crypto::hmac(hash_ptr, nonce_ptr, size() - SHORTHASHSIZE, shared)) { llarp::LogError("Failed to generate message auth"); return false; @@ -55,16 +53,14 @@ namespace llarp SharedSecret shared; - auto crypto = CryptoManager::instance(); - // set our pubkey memcpy(pubkey, ourSecretKey.toPublic().data(), PUBKEYSIZE); // randomize nonce - crypto->randbytes(noncePtr, TUNNONCESIZE); + crypto::randbytes(noncePtr, TUNNONCESIZE); TunnelNonce nonce(noncePtr); // derive shared key - if (!crypto->dh_client(shared, otherPubkey, ourSecretKey, nonce)) + if (!crypto::dh_client(shared, otherPubkey, ourSecretKey, nonce)) { llarp::LogError("DH failed"); return false; @@ -76,8 +72,6 @@ namespace llarp bool EncryptedFrame::DoDecrypt(const SharedSecret& shared) { - auto crypto = CryptoManager::instance(); - uint8_t* hash_ptr = data(); uint8_t* nonce_ptr = hash_ptr + SHORTHASHSIZE; uint8_t* body_ptr = hash_ptr + EncryptedFrameOverheadSize; @@ -85,7 +79,7 @@ namespace llarp TunnelNonce nonce(nonce_ptr); ShortHash digest; - if (!crypto->hmac(digest.data(), nonce_ptr, size() - SHORTHASHSIZE, shared)) + if (!crypto::hmac(digest.data(), nonce_ptr, size() - SHORTHASHSIZE, shared)) { llarp::LogError("Digest failed"); return false; @@ -97,7 +91,7 @@ namespace llarp return false; } - if (!crypto->xchacha20(body_ptr, size() - EncryptedFrameOverheadSize, shared, nonce)) + if (!crypto::xchacha20(body_ptr, size() - EncryptedFrameOverheadSize, shared, nonce)) { llarp::LogError("decrypt failed"); return false; @@ -121,10 +115,8 @@ namespace llarp SharedSecret shared; - auto crypto = CryptoManager::instance(); - // use dh_server because we are not the creator of this message - if (!crypto->dh_server(shared, otherPubkey, ourSecretKey, nonce)) + if (!crypto::dh_server(shared, otherPubkey, ourSecretKey, nonce)) { llarp::LogError("DH failed"); return false; diff --git a/llarp/crypto/types.hpp b/llarp/crypto/types.hpp index abc77a1062..a20c84fd2a 100644 --- a/llarp/crypto/types.hpp +++ b/llarp/crypto/types.hpp @@ -221,14 +221,14 @@ namespace llarp /// PKE(result, publickey, secretkey, nonce) using path_dh_func = - std::function; + bool(*)(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&); /// TKE(result, publickey, secretkey, nonce) using transport_dh_func = - std::function; + bool(*)(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&); /// SH(result, body) - using shorthash_func = std::function; + using shorthash_func = bool(*)(ShortHash&, const llarp_buffer_t&); } // namespace llarp namespace std diff --git a/llarp/exit/session.cpp b/llarp/exit/session.cpp index 9ec25d57b1..6920c750c7 100644 --- a/llarp/exit/session.cpp +++ b/llarp/exit/session.cpp @@ -24,7 +24,7 @@ namespace llarp::exit , m_BundleRC{false} , m_Parent{parent} { - CryptoManager::instance()->identity_keygen(exit_key); + crypto::identity_keygen(exit_key); } BaseSession::~BaseSession() = default; diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index dbfabbd3b9..d9fe5583be 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1110,8 +1110,6 @@ namespace llarp ustring other_pubkey, outer_nonce, inner_nonce; uint64_t lifetime; - auto crypto = CryptoManager::instance(); - try { oxenc::bt_list_consumer btlc{payload}; @@ -1128,7 +1126,7 @@ namespace llarp SharedSecret shared; // derive shared secret using ephemeral pubkey and our secret key (and nonce) - if (!crypto->dh_server( + if (!crypto::dh_server( shared.data(), other_pubkey.data(), _router.pubkey(), inner_nonce.data())) { log::info(link_cat, "DH server initialization failed during path build"); @@ -1138,7 +1136,7 @@ namespace llarp // hash data and check against given hash ShortHash digest; - if (!crypto->hmac( + if (!crypto::hmac( digest.data(), reinterpret_cast(frame.data()), frame.size(), @@ -1157,7 +1155,7 @@ namespace llarp } // decrypt frame with our hop info - if (!crypto->xchacha20( + if (!crypto::xchacha20( reinterpret_cast(hop_payload.data()), hop_payload.size(), shared.data(), @@ -1224,7 +1222,7 @@ namespace llarp return; } - if (!crypto->dh_server( + if (!crypto::dh_server( hop->pathKey.data(), other_pubkey.data(), _router.pubkey(), inner_nonce.data())) { log::warning(link_cat, "DH failed during path build."); @@ -1232,7 +1230,7 @@ namespace llarp return; } // generate hash of hop key for nonce mutation - crypto->shorthash(hop->nonceXOR, hop->pathKey.data(), hop->pathKey.size()); + crypto::shorthash(hop->nonceXOR, hop->pathKey.data(), hop->pathKey.size()); // set and check path lifetime hop->lifetime = 1ms * lifetime; @@ -1418,7 +1416,7 @@ namespace llarp const auto rx_id = transit_hop->info.rxID; auto success = - (CryptoManager::instance()->verify(pubkey, to_usv(dict_data), sig) + (crypto::verify(pubkey, to_usv(dict_data), sig) and _router.exitContext().ObtainNewExit(PubKey{pubkey.data()}, rx_id, flag != 0)); m.respond( @@ -1460,7 +1458,7 @@ namespace llarp auto path_ptr = std::static_pointer_cast( _router.path_context().GetByDownstream(_router.pubkey(), PathID_t{to_usv(tx_id).data()})); - if (CryptoManager::instance()->verify(_router.pubkey(), to_usv(dict_data), sig)) + if (crypto::verify(_router.pubkey(), to_usv(dict_data), sig)) path_ptr->enable_exit_traffic(); } catch (const std::exception& e) @@ -1492,7 +1490,7 @@ namespace llarp if (auto exit_ep = _router.exitContext().FindEndpointForPath(PathID_t{to_usv(path_id).data()})) { - if (CryptoManager::instance()->verify(exit_ep->PubKey().data(), to_usv(dict_data), sig)) + if (crypto::verify(exit_ep->PubKey().data(), to_usv(dict_data), sig)) { (exit_ep->UpdateLocalPath(transit_hop->info.rxID)) ? m.respond(UpdateExitMessage::sign_and_serialize_response(_router.identity(), tx_id)) @@ -1537,7 +1535,7 @@ namespace llarp auto path_ptr = std::static_pointer_cast( _router.path_context().GetByDownstream(_router.pubkey(), PathID_t{to_usv(tx_id).data()})); - if (CryptoManager::instance()->verify(_router.pubkey(), to_usv(dict_data), sig)) + if (crypto::verify(_router.pubkey(), to_usv(dict_data), sig)) { if (path_ptr->update_exit(std::stoul(tx_id))) { @@ -1577,7 +1575,7 @@ namespace llarp if (auto exit_ep = router().exitContext().FindEndpointForPath(rx_id)) { - if (CryptoManager::instance()->verify(exit_ep->PubKey().data(), to_usv(dict_data), sig)) + if (crypto::verify(exit_ep->PubKey().data(), to_usv(dict_data), sig)) { exit_ep->Close(); m.respond(CloseExitMessage::sign_and_serialize_response(_router.identity(), tx_id)); @@ -1624,7 +1622,7 @@ namespace llarp _router.path_context().GetByDownstream(_router.pubkey(), PathID_t{to_usv(tx_id).data()})); if (path_ptr->SupportsAnyRoles(path::ePathRoleExit | path::ePathRoleSVC) - and CryptoManager::instance()->verify(_router.pubkey(), to_usv(dict_data), sig)) + and crypto::verify(_router.pubkey(), to_usv(dict_data), sig)) path_ptr->mark_exit_closed(); } catch (const std::exception& e) diff --git a/llarp/lokinet_shared.cpp b/llarp/lokinet_shared.cpp index 5dbd83766a..e933033253 100644 --- a/llarp/lokinet_shared.cpp +++ b/llarp/lokinet_shared.cpp @@ -489,8 +489,6 @@ extern "C" if (ctx == nullptr) return -3; auto lock = ctx->acquire(); - // add a temp cryptography implementation here so rc.Verify works - llarp::CryptoManager instance{new llarp::Crypto{}}; if (data[0] == 'l') { if (not ctx->config->bootstrap.routers.BDecode(&buf)) diff --git a/llarp/messages/exit.hpp b/llarp/messages/exit.hpp index e5a77b17f0..20d1084eb7 100644 --- a/llarp/messages/exit.hpp +++ b/llarp/messages/exit.hpp @@ -27,7 +27,7 @@ namespace llarp btdp.append("E", flag); btdp.append("T", tx_id); - if (not CryptoManager::instance()->sign( + if (not crypto::sign( reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) throw std::runtime_error{ "Error: ObtainExitMessage failed to sign and serialize contents!"}; @@ -51,7 +51,7 @@ namespace llarp btdp.append("T", tx_id); btdp.append("Y", nonce); - if (CryptoManager::instance()->sign( + if (crypto::sign( reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) throw std::runtime_error{ "Error: ObtainExitMessage response failed to sign and serialize contents!"}; @@ -80,7 +80,7 @@ namespace llarp btdp.append("P", path_id); btdp.append("T", tx_id); - if (not CryptoManager::instance()->sign( + if (not crypto::sign( reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) throw std::runtime_error{ "Error: UpdateExitMessage failed to sign and serialize contents!"}; @@ -104,7 +104,7 @@ namespace llarp btdp.append("T", tx_id); btdp.append("Y", nonce); - if (CryptoManager::instance()->sign( + if (crypto::sign( reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) throw std::runtime_error{ "Error: UpdateExitMessage response failed to sign and serialize contents!"}; @@ -134,7 +134,7 @@ namespace llarp btdp.append("T", tx_id); btdp.append("Y", nonce); - if (not CryptoManager::instance()->sign( + if (not crypto::sign( reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) throw std::runtime_error{ "Error: CloseExitMessage failed to sign and serialize contents!"}; @@ -158,7 +158,7 @@ namespace llarp btdp.append("T", tx_id); btdp.append("Y", nonce); - if (CryptoManager::instance()->sign( + if (crypto::sign( reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) throw std::runtime_error{ "Error: CloseExitMessage response failed to sign and serialize contents!"}; diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index c12e7930a9..053b967022 100644 --- a/llarp/messages/path.hpp +++ b/llarp/messages/path.hpp @@ -17,21 +17,19 @@ namespace llarp inline static void setup_hop_keys(path::PathHopConfig& hop, const RouterID& nextHop) { - auto crypto = CryptoManager::instance(); - // generate key - crypto->encryption_keygen(hop.commkey); + crypto::encryption_keygen(hop.commkey); 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); throw std::runtime_error{std::move(err)}; } // generate nonceXOR value self->hop->pathKey - crypto->shorthash(hop.nonceXOR, hop.shared.data(), hop.shared.size()); + crypto::shorthash(hop.nonceXOR, hop.shared.data(), hop.shared.size()); hop.upstream = nextHop; } @@ -39,8 +37,6 @@ namespace llarp inline static std::string serialize(const path::PathHopConfig& hop) { - auto crypto = CryptoManager::instance(); - std::string hop_info; { @@ -57,21 +53,21 @@ namespace llarp } SecretKey framekey; - crypto->encryption_keygen(framekey); + crypto::encryption_keygen(framekey); SharedSecret shared; TunnelNonce outer_nonce; 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"}; } // encrypt hop_info (mutates in-place) - if (!crypto->xchacha20( + if (!crypto::xchacha20( reinterpret_cast(hop_info.data()), hop_info.size(), shared, @@ -96,7 +92,7 @@ namespace llarp std::string hash; hash.reserve(SHORTHASHSIZE); - if (!crypto->hmac( + if (!crypto::hmac( reinterpret_cast(hash.data()), reinterpret_cast(hashed_data.data()), hashed_data.size(), diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index 6404a0430f..10eb836131 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -97,7 +97,7 @@ namespace llarp for (const auto& entry : entries) entries.push_back(entry); - std::shuffle(entries.begin(), entries.end(), llarp::CSRNG{}); + std::shuffle(entries.begin(), entries.end(), llarp::csrng); for (const auto entry : entries) { diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 534ab10eb7..75be48791b 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -110,7 +110,7 @@ namespace llarp::path for (const auto& hop : hops) { // do a round of chacha for each hop and mutate the nonce with that hop's nonce - CryptoManager::instance()->xchacha20( + crypto::xchacha20( reinterpret_cast(payload.data()), payload.size(), hop.shared, nonce); nonce ^= hop.nonceXOR; @@ -450,7 +450,7 @@ namespace llarp::path for (const auto& hop : hops) { - CryptoManager::instance()->xchacha20(buf, sz, hop.shared, n); + crypto::xchacha20(buf, sz, hop.shared, n); n ^= hop.nonceXOR; } auto& msg = sendmsgs[idx]; @@ -528,7 +528,7 @@ namespace llarp::path for (const auto& hop : hops) { sendMsgs[idx].nonce ^= hop.nonceXOR; - CryptoManager::instance()->xchacha20(buf, sz, hop.shared, sendMsgs[idx].nonce); + crypto::xchacha20(buf, sz, hop.shared, sendMsgs[idx].nonce); } std::memcpy(sendMsgs[idx].enc.data(), buf, sz); @@ -583,7 +583,7 @@ namespace llarp::path if (payload.size() < PAD_SIZE) { // randomize padding - CryptoManager::instance()->randbytes( + crypto::randbytes( reinterpret_cast(buf.data()) + payload.size(), PAD_SIZE - payload.size()); } log::debug(path_cat, "Sending {}B routing message to {}", buf.size(), Endpoint()); diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index a9758384ed..e3d312c3c5 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -78,21 +78,19 @@ namespace llarp void Builder::setup_hop_keys(path::PathHopConfig& hop, const RouterID& nextHop) { - auto crypto = CryptoManager::instance(); - // generate key - crypto->encryption_keygen(hop.commkey); + crypto::encryption_keygen(hop.commkey); 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); throw std::runtime_error{std::move(err)}; } // generate nonceXOR value self->hop->pathKey - crypto->shorthash(hop.nonceXOR, hop.shared.data(), hop.shared.size()); + crypto::shorthash(hop.nonceXOR, hop.shared.data(), hop.shared.size()); hop.upstream = nextHop; } @@ -100,8 +98,6 @@ namespace llarp std::string Builder::create_hop_info_frame(const path::PathHopConfig& hop) { - auto crypto = CryptoManager::instance(); - std::string hop_info; { @@ -118,21 +114,21 @@ namespace llarp } SecretKey framekey; - crypto->encryption_keygen(framekey); + crypto::encryption_keygen(framekey); SharedSecret shared; TunnelNonce outer_nonce; 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"}; } // encrypt hop_info (mutates in-place) - if (!crypto->xchacha20( + if (!crypto::xchacha20( reinterpret_cast(hop_info.data()), hop_info.size(), shared, outer_nonce)) { log::error(path_cat, "Hop info encryption failed!"); @@ -154,7 +150,7 @@ namespace llarp std::string hash; hash.reserve(SHORTHASHSIZE); - if (!crypto->hmac( + if (!crypto::hmac( reinterpret_cast(hash.data()), reinterpret_cast(hashed_data.data()), hashed_data.size(), diff --git a/llarp/path/pathset.cpp b/llarp/path/pathset.cpp index 7a0427d612..df92ef7c12 100644 --- a/llarp/path/pathset.cpp +++ b/llarp/path/pathset.cpp @@ -211,12 +211,7 @@ namespace llarp::path } if (chosen.empty()) return nullptr; - size_t idx = 0; - if (chosen.size() >= 2) - { - idx = rand() % chosen.size(); - } - return chosen[idx]; + return chosen[std::uniform_int_distribution{0, chosen.size() - 1}(llarp::csrng)]; } Path_ptr diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index bceae78a57..0e681455f6 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -77,7 +77,7 @@ namespace llarp::path { dlt = PAD_SIZE - dlt; // randomize padding - CryptoManager::instance()->randbytes(reinterpret_cast(payload.data()), dlt); + crypto::randbytes(reinterpret_cast(payload.data()), dlt); } // TODO: relay message along @@ -107,7 +107,7 @@ namespace llarp::path msg.pathid = info.rxID; msg.nonce = ev.second ^ nonceXOR; - CryptoManager::instance()->xchacha20(buf, sz, pathKey, ev.second); + crypto::xchacha20(buf, sz, pathKey, ev.second); std::memcpy(msg.enc.data(), buf, sz); llarp::LogDebug( @@ -137,7 +137,7 @@ namespace llarp::path uint8_t* buf = ev.first.data(); size_t sz = ev.first.size(); - CryptoManager::instance()->xchacha20(buf, sz, pathKey, ev.second); + crypto::xchacha20(buf, sz, pathKey, ev.second); msg.pathid = info.txID; msg.nonce = ev.second ^ nonceXOR; diff --git a/llarp/pow.cpp b/llarp/pow.cpp index 858f2e1a7e..5012ec394b 100644 --- a/llarp/pow.cpp +++ b/llarp/pow.cpp @@ -31,7 +31,7 @@ namespace llarp auto buf = bt_encode(); // hash - if (!CryptoManager::instance()->shorthash( + if (!crypto::shorthash( digest, reinterpret_cast(buf.data()), buf.size())) return false; // check bytes required diff --git a/llarp/router/rc_gossiper.cpp b/llarp/router/rc_gossiper.cpp index be478e620e..429a4b697d 100644 --- a/llarp/router/rc_gossiper.cpp +++ b/llarp/router/rc_gossiper.cpp @@ -117,7 +117,8 @@ namespace llarp std::unordered_set keys; // grab the keys we want to use std::sample( - gossipTo.begin(), gossipTo.end(), std::inserter(keys, keys.end()), MaxGossipPeers, CSRNG{}); + gossipTo.begin(), gossipTo.end(), std::inserter(keys, keys.end()), MaxGossipPeers, + llarp::csrng); m_LinkManager->ForEachPeer([&](AbstractLinkSession* peerSession) { if (not(peerSession && peerSession->IsEstablished())) diff --git a/llarp/router/rc_lookup_handler.cpp b/llarp/router/rc_lookup_handler.cpp index 6b36cb743a..ac705a88a5 100644 --- a/llarp/router/rc_lookup_handler.cpp +++ b/llarp/router/rc_lookup_handler.cpp @@ -328,7 +328,7 @@ namespace llarp if (lookup_routers.size() > LookupPerTick) { - std::shuffle(lookup_routers.begin(), lookup_routers.end(), CSRNG{}); + std::shuffle(lookup_routers.begin(), lookup_routers.end(), llarp::csrng); lookup_routers.resize(LookupPerTick); } diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 17680b402f..7aad6ca2e9 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -1162,8 +1162,8 @@ namespace llarp { // we are a client // regenerate keys and resign rc before everything else - CryptoManager::instance()->identity_keygen(_identity); - CryptoManager::instance()->encryption_keygen(_encryption); + crypto::identity_keygen(_identity); + crypto::encryption_keygen(_encryption); router_contact.pubkey = seckey_topublic(identity()); router_contact.enckey = seckey_topublic(encryption()); if (!router_contact.Sign(identity())) diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index 3b28ee35a9..3d5e439be9 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -364,7 +364,7 @@ namespace llarp signed_bt_dict = bencode_signed_section(); - return CryptoManager::instance()->sign( + return crypto::sign( signature, secretkey, reinterpret_cast(signed_bt_dict.data()), @@ -409,7 +409,7 @@ namespace llarp copy.signature.Zero(); auto bte = copy.bt_encode(); - return CryptoManager::instance()->verify( + return crypto::verify( pubkey, reinterpret_cast(bte.data()), bte.size(), signature); } diff --git a/llarp/service/address.cpp b/llarp/service/address.cpp index fe75cb6c46..704b193c9d 100644 --- a/llarp/service/address.cpp +++ b/llarp/service/address.cpp @@ -67,7 +67,7 @@ namespace llarp::service Address::ToKey() const { PubKey k; - CryptoManager::instance()->derive_subkey(k, PubKey(data()), 1); + crypto::derive_subkey(k, PubKey(data()), 1); return dht::Key_t{k.as_array()}; } diff --git a/llarp/service/async_key_exchange.cpp b/llarp/service/async_key_exchange.cpp index 2cfecad428..0def85fac4 100644 --- a/llarp/service/async_key_exchange.cpp +++ b/llarp/service/async_key_exchange.cpp @@ -43,24 +43,21 @@ namespace llarp::service { // derive ntru session key component SharedSecret secret; - auto crypto = CryptoManager::instance(); - - crypto->pqe_encrypt(frame->cipher, secret, self->introPubKey); + crypto::pqe_encrypt(frame->cipher, secret, self->introPubKey); + // randomize Nonce frame->nonce.Randomize(); // compute post handshake session key // PKE (A, B, N) SharedSecret sharedSecret; - path_dh_func dh_client = util::memFn(&Crypto::dh_client, crypto); - - if (!self->m_LocalIdentity.KeyExchange(dh_client, sharedSecret, self->m_remote, frame->nonce)) + if (!self->m_LocalIdentity.KeyExchange(crypto::dh_client, sharedSecret, self->m_remote, frame->nonce)) { LogError("failed to derive x25519 shared key component"); } auto buf = secret.bt_encode() + sharedSecret.bt_encode(); // H (K + PKE(A, B, N)) - crypto->shorthash(self->sharedKey, reinterpret_cast(buf.data()), buf.size()); + crypto::shorthash(self->sharedKey, reinterpret_cast(buf.data()), buf.size()); // set tag self->msg.tag = self->tag; diff --git a/llarp/service/auth.cpp b/llarp/service/auth.cpp index 8ef7e52505..f68f9e355c 100644 --- a/llarp/service/auth.cpp +++ b/llarp/service/auth.cpp @@ -124,7 +124,7 @@ namespace llarp::service case AuthFileType::eAuthFilePlain: return hash == challenge; case AuthFileType::eAuthFileHashes: - return CryptoManager::instance()->check_passwd_hash( + return crypto::check_passwd_hash( std::move(hash), std::move(challenge)); default: return false; diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 2da9031ce5..ae124233d4 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -874,7 +874,7 @@ namespace llarp::service // pick up to max_unique_lns_endpoints random paths to do lookups from std::vector chosenpaths; chosenpaths.insert(chosenpaths.begin(), paths.begin(), paths.end()); - std::shuffle(chosenpaths.begin(), chosenpaths.end(), CSRNG{}); + std::shuffle(chosenpaths.begin(), chosenpaths.end(), llarp::csrng); chosenpaths.resize(std::min(paths.size(), MAX_ONS_LOOKUP_ENDPOINTS)); for (const auto& path : chosenpaths) diff --git a/llarp/service/identity.cpp b/llarp/service/identity.cpp index cc28f047be..9cfdf45dfa 100644 --- a/llarp/service/identity.cpp +++ b/llarp/service/identity.cpp @@ -42,12 +42,11 @@ namespace llarp::service void Identity::RegenerateKeys() { - auto crypto = CryptoManager::instance(); - crypto->identity_keygen(signkey); - crypto->encryption_keygen(enckey); + crypto::identity_keygen(signkey); + crypto::encryption_keygen(enckey); pub.Update(seckey_topublic(signkey), seckey_topublic(enckey)); - crypto->pqe_keygen(pq); - if (not crypto->derive_subkey_private(derivedSignKey, signkey, 1)) + crypto::pqe_keygen(pq); + if (not crypto::derive_subkey_private(derivedSignKey, signkey, 1)) { throw std::runtime_error("failed to derive subkey"); } @@ -66,7 +65,7 @@ namespace llarp::service bool Identity::Sign(Signature& sig, uint8_t* buf, size_t size) const { - return CryptoManager::instance()->sign(sig, signkey, buf, size); + return crypto::sign(sig, signkey, buf, size); } void @@ -127,22 +126,21 @@ namespace llarp::service if (!bencode_decode_dict(*this, &buf)) throw std::length_error{"could not decode service identity"}; } - auto crypto = CryptoManager::instance(); // ensure that the encryption key is set if (enckey.IsZero()) - crypto->encryption_keygen(enckey); + crypto::encryption_keygen(enckey); // also ensure the ntru key is set if (pq.IsZero()) - crypto->pqe_keygen(pq); + crypto::pqe_keygen(pq); std::optional van; if (!vanity.IsZero()) van = vanity; // update pubkeys pub.Update(seckey_topublic(signkey), seckey_topublic(enckey), van); - if (not crypto->derive_subkey_private(derivedSignKey, signkey, 1)) + if (not crypto::derive_subkey_private(derivedSignKey, signkey, 1)) { throw std::runtime_error("failed to derive subkey"); } @@ -170,7 +168,7 @@ namespace llarp::service auto bte = i.bt_encode(); const SharedSecret k{i.address_keys.Addr()}; - CryptoManager::instance()->xchacha20( + crypto::xchacha20( reinterpret_cast(bte.data()), bte.size(), k, encrypted.nounce); std::memcpy(encrypted.introsetPayload.data(), bte.data(), bte.size()); diff --git a/llarp/service/info.cpp b/llarp/service/info.cpp index 1f0630cfe1..f45f5b93df 100644 --- a/llarp/service/info.cpp +++ b/llarp/service/info.cpp @@ -9,7 +9,7 @@ namespace llarp::service bool ServiceInfo::verify(uint8_t* buf, size_t size, const Signature& sig) const { - return CryptoManager::instance()->verify(signkey, buf, size, sig); + return crypto::verify(signkey, buf, size, sig); } bool diff --git a/llarp/service/intro_set.cpp b/llarp/service/intro_set.cpp index 68f1533cae..11dd6f9992 100644 --- a/llarp/service/intro_set.cpp +++ b/llarp/service/intro_set.cpp @@ -123,7 +123,7 @@ namespace llarp::service std::string payload{ reinterpret_cast(introsetPayload.data()), introsetPayload.size()}; - CryptoManager::instance()->xchacha20( + crypto::xchacha20( reinterpret_cast(payload.data()), payload.size(), k, nounce); return IntroSet{payload}; @@ -144,7 +144,7 @@ namespace llarp::service sig.Zero(); auto bte = bt_encode(); - if (not CryptoManager::instance()->sign( + if (not crypto::sign( sig, k, reinterpret_cast(bte.data()), bte.size())) return false; LogDebug("signed encrypted introset: ", *this); @@ -161,20 +161,20 @@ namespace llarp::service copy.sig.Zero(); auto bte = copy.bt_encode(); - return CryptoManager::instance()->verify( + return crypto::verify( derivedSigningKey, reinterpret_cast(bte.data()), bte.size(), sig); } bool EncryptedIntroSet::verify(uint8_t* introset, size_t introset_size, uint8_t* key, uint8_t* sig) { - return CryptoManager::instance()->verify(key, introset, introset_size, sig); + return crypto::verify(key, introset, introset_size, sig); } bool EncryptedIntroSet::verify(std::string introset, std::string key, std::string sig) { - return CryptoManager::instance()->verify( + return crypto::verify( reinterpret_cast(key.data()), reinterpret_cast(introset.data()), introset.size(), diff --git a/llarp/service/name.cpp b/llarp/service/name.cpp index 056c62c239..37c0afb1ef 100644 --- a/llarp/service/name.cpp +++ b/llarp/service/name.cpp @@ -9,8 +9,7 @@ namespace llarp::service { if (ciphertext.empty()) return std::nullopt; - const auto crypto = CryptoManager::instance(); - const auto maybe = crypto->maybe_decrypt_name(ciphertext, nonce, name); + const auto maybe = crypto::maybe_decrypt_name(ciphertext, nonce, name); if (maybe.has_value()) return Address{*maybe}; return std::nullopt; diff --git a/llarp/service/outbound_context.cpp b/llarp/service/outbound_context.cpp index d1dcf74160..5588de1187 100644 --- a/llarp/service/outbound_context.cpp +++ b/llarp/service/outbound_context.cpp @@ -40,13 +40,9 @@ namespace llarp::service updatingIntroSet = false; // pick random first intro - auto it = introset.intros.begin(); - if (introset.intros.size() > 1) - { - CSRNG rng{}; - it += std::uniform_int_distribution{0, introset.intros.size() - 1}(rng); - } - next_intro = *it; + next_intro = *std::next( + introset.intros.begin(), + std::uniform_int_distribution{0, introset.intros.size() - 1}(llarp::csrng)); current_tag.Randomize(); last_shift = Now(); // add send and connect timeouts to the parent endpoints path alignment timeout @@ -250,7 +246,7 @@ namespace llarp::service { std::string buf(64, '\0'); - CryptoManager::instance()->randomize(reinterpret_cast(buf.data()), buf.size()); + crypto::randomize(reinterpret_cast(buf.data()), buf.size()); send_packet_to_remote(buf); last_keep_alive = Now(); @@ -305,7 +301,7 @@ namespace llarp::service }); if (not otherIntros.empty()) { - std::shuffle(otherIntros.begin(), otherIntros.end(), CSRNG{}); + std::shuffle(otherIntros.begin(), otherIntros.end(), llarp::csrng); remote_intro = otherIntros[0]; } } @@ -403,7 +399,7 @@ namespace llarp::service if (intros.size() > 1) { - std::shuffle(intros.begin(), intros.end(), CSRNG{}); + std::shuffle(intros.begin(), intros.end(), llarp::csrng); } // to find a intro on the same router as before that is newer diff --git a/llarp/service/protocol.cpp b/llarp/service/protocol.cpp index 59fc042e07..a21a4b9b9a 100644 --- a/llarp/service/protocol.cpp +++ b/llarp/service/protocol.cpp @@ -178,7 +178,7 @@ namespace llarp::service const SharedSecret& sharedkey, ProtocolMessage& msg) const { Encrypted<2048> tmp = enc; - CryptoManager::instance()->xchacha20(tmp.data(), tmp.size(), sharedkey, nonce); + crypto::xchacha20(tmp.data(), tmp.size(), sharedkey, nonce); return bencode_decode_dict(msg, tmp.Buffer()); } @@ -207,7 +207,7 @@ namespace llarp::service // encode message auto bte1 = msg.bt_encode(); // encrypt - CryptoManager::instance()->xchacha20( + crypto::xchacha20( reinterpret_cast(bte1.data()), bte1.size(), sessionKey, nonce); // put encrypted buffer std::memcpy(enc.data(), bte1.data(), bte1.size()); @@ -252,12 +252,11 @@ namespace llarp::service static void Work(std::shared_ptr self) { - auto crypto = CryptoManager::instance(); SharedSecret K; SharedSecret shared_key; // copy ProtocolFrameMessage frame(self->frame); - if (!crypto->pqe_decrypt( + if (!crypto::pqe_decrypt( self->frame.cipher, K, pq_keypair_to_secret(self->m_LocalIdentity.pq))) { LogError("pqke failed C=", self->frame.cipher); @@ -268,7 +267,7 @@ namespace llarp::service // auto buf = frame.enc.Buffer(); uint8_t* buf = frame.enc.data(); size_t sz = frame.enc.size(); - crypto->xchacha20(buf, sz, K, self->frame.nonce); + crypto::xchacha20(buf, sz, K, self->frame.nonce); auto bte = self->msg->bt_encode(); @@ -304,16 +303,8 @@ namespace llarp::service // PKE (A, B, N) SharedSecret shared_secret; - path_dh_func dh_server = [crypto = CryptoManager::instance()]( - llarp::SharedSecret& shared, - const PubKey& pk, - const SecretKey& sk, - const TunnelNonce& n) -> bool { - return crypto->dh_server(shared, pk, sk, n); - }; - if (!self->m_LocalIdentity.KeyExchange( - dh_server, shared_secret, self->msg->sender, self->frame.nonce)) + crypto::dh_server, shared_secret, self->msg->sender, self->frame.nonce)) { LogError("x25519 key exchange failed"); Dump(self->frame); @@ -326,7 +317,7 @@ namespace llarp::service // S = HS( K + PKE( A, B, N)) std::memcpy(tmp.begin() + 32, shared_secret.begin(), shared_secret.size()); - crypto->shorthash(shared_key, tmp.data(), tmp.size()); + crypto::shorthash(shared_key, tmp.data(), tmp.size()); std::shared_ptr msg = std::move(self->msg); path::Path_ptr path = std::move(self->path); diff --git a/llarp/win32/guid.hpp b/llarp/win32/guid.hpp index 83c9265231..40e0cae095 100644 --- a/llarp/win32/guid.hpp +++ b/llarp/win32/guid.hpp @@ -13,7 +13,7 @@ namespace llarp::win32 MakeDeterministicGUID(Data data) { ShortHash h{}; - auto hash = [&h](auto data) { CryptoManager::instance()->shorthash(h, data); }; + auto hash = [&h](auto data) { crypto::shorthash(h, data); }; if constexpr (std::is_same_v) hash(llarp_buffer_t{reinterpret_cast(data.data()), data.size()}); diff --git a/test/crypto/test_llarp_crypto.cpp b/test/crypto/test_llarp_crypto.cpp index b78752375d..2eb3b03d9c 100644 --- a/test/crypto/test_llarp_crypto.cpp +++ b/test/crypto/test_llarp_crypto.cpp @@ -8,7 +8,6 @@ using namespace llarp; TEST_CASE("Identity key") { - llarp::sodium::CryptoLibSodium crypto; SecretKey secret; crypto.identity_keygen(secret); @@ -35,7 +34,6 @@ TEST_CASE("Identity key") TEST_CASE("PQ crypto") { - llarp::sodium::CryptoLibSodium crypto; PQKeyPair keys; crypto.pqe_keygen(keys); PQCipherBlock block; @@ -52,8 +50,6 @@ TEST_CASE("PQ crypto") TEST_CASE("passwd hash valid") { - llarp::sodium::CryptoLibSodium crypto; - // poggers password hashes std::set valid_hashes; // UNIX DES diff --git a/test/crypto/test_llarp_key_manager.cpp b/test/crypto/test_llarp_key_manager.cpp index 459ed309b8..31714e7870 100644 --- a/test/crypto/test_llarp_key_manager.cpp +++ b/test/crypto/test_llarp_key_manager.cpp @@ -1,4 +1,3 @@ -#include "llarp_test.hpp" #include "test_util.hpp" #include @@ -14,7 +13,7 @@ using namespace ::llarp; -struct KeyManagerTest : public test::LlarpTest +struct KeyManagerTest { // paranoid file guards for anything KeyManager might touch test::FileGuard m_rcFileGuard; diff --git a/test/llarp_test.hpp b/test/llarp_test.hpp deleted file mode 100644 index 914c4a224b..0000000000 --- a/test/llarp_test.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include -#include - -namespace llarp::test -{ - - template - class LlarpTest - { - protected: - CryptoImpl m_crypto; - CryptoManager cm; - - LlarpTest() : cm(&m_crypto) - { - static_assert(std::is_base_of::value, ""); - } - - ~LlarpTest() - {} - }; - - template <> - inline LlarpTest::~LlarpTest() - { - - } // namespace test -} diff --git a/test/routing/test_llarp_routing_obtainexitmessage.cpp b/test/routing/test_llarp_routing_obtainexitmessage.cpp index 6316520726..467519d3f4 100644 --- a/test/routing/test_llarp_routing_obtainexitmessage.cpp +++ b/test/routing/test_llarp_routing_obtainexitmessage.cpp @@ -1,4 +1,3 @@ -#include "llarp_test.hpp" #include #include #include @@ -16,10 +15,10 @@ fill(Signature& s) s.Fill(0xFF); } -TEST_CASE_METHOD(LlarpTest<>, "Sign-verify") +TEST_CASE("Sign-verify") { SecretKey alice{}; - CryptoManager::instance()->identity_keygen(alice); + crypto::identity_keygen(alice); REQUIRE(not alice.IsZero()); ObtainExitMessage msg{}; msg.S = randint(); diff --git a/test/service/test_llarp_service_identity.cpp b/test/service/test_llarp_service_identity.cpp index 560754280e..5d0bd42bec 100644 --- a/test/service/test_llarp_service_identity.cpp +++ b/test/service/test_llarp_service_identity.cpp @@ -7,7 +7,6 @@ #include #include -#include "test_util.hpp" #include using namespace llarp; @@ -44,8 +43,6 @@ TEST_CASE("test service::Identity throws on error") TEST_CASE("test subkey derivation", "[crypto]") { - CryptoManager manager(new sodium::CryptoLibSodium()); - // These values came out of a run of Tor's test code, so that we can confirm we are doing the same // blinding subkey crypto math as Tor. Our hash value is generated differently so we use the hash // from a Tor random test suite run. @@ -79,27 +76,22 @@ TEST_CASE("test subkey derivation", "[crypto]") CHECK(root.toPrivate(root_key)); CHECK(root_key.as_array() == root_key_data.as_array()); - auto crypto = CryptoManager::instance(); - PrivateKey aprime; // a' - CHECK(crypto->derive_subkey_private(aprime, root, 0, &hash)); + CHECK(crypto::derive_subkey_private(aprime, root, 0, &hash)); // We use a different signing hash than Tor // only the private key value (the first 32 bytes) will match: CHECK(std::memcmp(aprime.data(), derived_key_data.data(), 32) == 0); PubKey Aprime; // A' - CHECK(crypto->derive_subkey(Aprime, root.toPublic(), 0, &hash)); + CHECK(crypto::derive_subkey(Aprime, root.toPublic(), 0, &hash)); CHECK(Aprime.as_array() == derived_pub_data.as_array()); } TEST_CASE("test root key signing" , "[crypto]") { - CryptoManager manager(new sodium::CryptoLibSodium()); - - auto crypto = CryptoManager::instance(); SecretKey root_key; - crypto->identity_keygen(root_key); + crypto::identity_keygen(root_key); // We have our own reimplementation of sodium's signing function which can work with derived // private keys (unlike sodium's built-in which requires starting from a seed). This tests that @@ -109,23 +101,20 @@ TEST_CASE("test root key signing" , "[crypto]") llarp_buffer_t nibbs_buf{nibbs.data(), nibbs.size()}; Signature sig_sodium; - CHECK(crypto->sign(sig_sodium, root_key, nibbs_buf)); + CHECK(crypto::sign(sig_sodium, root_key, nibbs_buf)); PrivateKey root_privkey; CHECK(root_key.toPrivate(root_privkey)); Signature sig_ours; - CHECK(crypto->sign(sig_ours, root_privkey, nibbs_buf)); + CHECK(crypto::sign(sig_ours, root_privkey, nibbs_buf)); CHECK(sig_sodium == sig_ours); } TEST_CASE("Test generate derived key", "[crypto]") { - CryptoManager manager(new sodium::CryptoLibSodium()); - - auto crypto = CryptoManager::instance(); SecretKey root_key; - crypto->identity_keygen(root_key); + crypto::identity_keygen(root_key); PrivateKey root_privkey; CHECK(root_key.toPrivate(root_privkey)); @@ -144,10 +133,10 @@ TEST_CASE("Test generate derived key", "[crypto]") } PrivateKey aprime; // a' - CHECK(crypto->derive_subkey_private(aprime, root_key, 1)); + CHECK(crypto::derive_subkey_private(aprime, root_key, 1)); PubKey Aprime; // A' - CHECK(crypto->derive_subkey(Aprime, A, 1)); + CHECK(crypto::derive_subkey(Aprime, A, 1)); // We should also be able to derive A' via a': PubKey Aprime_alt; @@ -158,14 +147,14 @@ TEST_CASE("Test generate derived key", "[crypto]") // Generate using the same constant and make sure we get an identical privkey (including the // signing hash value) PrivateKey aprime_repeat; - CHECK(crypto->derive_subkey_private(aprime_repeat, root_key, 1)); + CHECK(crypto::derive_subkey_private(aprime_repeat, root_key, 1)); CHECK(aprime_repeat == aprime); // Generate another using a different constant and make sure we get something different PrivateKey a2; PubKey A2; - CHECK(crypto->derive_subkey_private(a2, root_key, 2)); - CHECK(crypto->derive_subkey(A2, A, 2)); + CHECK(crypto::derive_subkey_private(a2, root_key, 2)); + CHECK(crypto::derive_subkey(A2, A, 2)); CHECK(A2 != Aprime); CHECK(a2.ToHex().substr(0, 64) != aprime.ToHex().substr(0, 64)); CHECK(a2.ToHex().substr(64) != aprime.ToHex().substr(64)); // The hash should be different too @@ -173,11 +162,8 @@ TEST_CASE("Test generate derived key", "[crypto]") TEST_CASE("Test signing with derived key", "[crypto]") { - CryptoManager manager(new sodium::CryptoLibSodium()); - - auto crypto = CryptoManager::instance(); SecretKey root_key; - crypto->identity_keygen(root_key); + crypto::identity_keygen(root_key); PrivateKey root_privkey; root_key.toPrivate(root_privkey); @@ -188,24 +174,22 @@ TEST_CASE("Test signing with derived key", "[crypto]") a.toPublic(A); PrivateKey aprime; // a' - crypto->derive_subkey_private(aprime, root_key, 1); + crypto::derive_subkey_private(aprime, root_key, 1); PubKey Aprime; // A' - crypto->derive_subkey(Aprime, A, 1); + crypto::derive_subkey(Aprime, A, 1); const std::string s = "Jeff loves one-letter variable names."; llarp_buffer_t buf(s.data(), s.size()); Signature sig; - CHECK(crypto->sign(sig, aprime, buf)); - CHECK(crypto->verify(Aprime, buf, sig)); + CHECK(crypto::sign(sig, aprime, buf)); + CHECK(crypto::verify(Aprime, buf, sig)); } TEST_CASE("Test sign and encrypt introset", "[crypto]") { - CryptoManager manager(new sodium::CryptoLibSodium()); - service::Identity ident; ident.RegenerateKeys(); service::Address addr; @@ -227,7 +211,6 @@ TEST_CASE("Test sign and encrypt introset", "[crypto]") CHECK(maybe->Verify(now)); PubKey blind_key; const PubKey root_key(addr.as_array()); - auto crypto = CryptoManager::instance(); - CHECK(crypto->derive_subkey(blind_key, root_key, 1)); + CHECK(crypto::derive_subkey(blind_key, root_key, 1)); CHECK(blind_key == maybe->derivedSigningKey); } diff --git a/test/service/test_llarp_service_name.cpp b/test/service/test_llarp_service_name.cpp index 86f0324f34..6e0af69eae 100644 --- a/test/service/test_llarp_service_name.cpp +++ b/test/service/test_llarp_service_name.cpp @@ -1,5 +1,5 @@ #include "catch2/catch.hpp" -#include +#include #include #include @@ -7,7 +7,6 @@ using namespace std::literals; TEST_CASE("Test LNS name decrypt", "[lns]") { - llarp::sodium::CryptoLibSodium crypto; constexpr auto recordhex = "0ba76cbfdb6dc8f950da57ae781912f31c8ad0c55dbf86b88cb0391f563261a9656571a817be4092969f8a78ee0fcee260424acb4a1f4bbdd27348b71de006b6152dd04ed11bf3c4"sv; const auto recordbin = oxenc::from_hex(recordhex); CHECK(not recordbin.empty()); @@ -16,7 +15,7 @@ TEST_CASE("Test LNS name decrypt", "[lns]") const auto len = recordbin.size() - n.size(); std::copy_n(recordbin.cbegin() + len, n.size(), n.data()); std::copy_n(recordbin.cbegin(), len, std::back_inserter(ciphertext)); - const auto maybe = crypto.maybe_decrypt_name(std::string_view{reinterpret_cast(ciphertext.data()), ciphertext.size()}, n, "jason.loki"); + const auto maybe = llarp::crypto::maybe_decrypt_name(std::string_view{reinterpret_cast(ciphertext.data()), ciphertext.size()}, n, "jason.loki"); CHECK(maybe.has_value()); const llarp::service::Address addr{*maybe}; CHECK(addr.ToString() == "azfoj73snr9f3neh5c6sf7rtbaeabyxhr1m4un5aydsmsrxo964o.loki"); diff --git a/test/test_llarp_encrypted_frame.cpp b/test/test_llarp_encrypted_frame.cpp index 6648ba9b11..e42a00d808 100644 --- a/test/test_llarp_encrypted_frame.cpp +++ b/test/test_llarp_encrypted_frame.cpp @@ -2,7 +2,6 @@ #include "test_util.hpp" #include #include -#include #include #include @@ -13,14 +12,13 @@ using SecretKey = SecretKey; using PubKey = PubKey; using LRCR = LR_CommitRecord; -class FrameTest : public test::LlarpTest<> +class FrameTest { public: FrameTest() : test::LlarpTest<>{} { - auto crypto = CryptoManager::instance(); - crypto->encryption_keygen(alice); - crypto->encryption_keygen(bob); + crypto::encryption_keygen(alice); + crypto::encryption_keygen(bob); } SecretKey alice, bob; diff --git a/test/test_llarp_router_contact.cpp b/test/test_llarp_router_contact.cpp index f94e7904b3..f3a7611e5d 100644 --- a/test/test_llarp_router_contact.cpp +++ b/test/test_llarp_router_contact.cpp @@ -1,17 +1,10 @@ #include #include -#include #include #include #include -namespace -{ - llarp::sodium::CryptoLibSodium crypto; - llarp::CryptoManager cmanager(&crypto); -} - namespace llarp { @@ -20,10 +13,10 @@ TEST_CASE("RouterContact Sign and Verify", "[RC][RouterContact][signature][sign] RouterContact rc; SecretKey sign; - cmanager.instance()->identity_keygen(sign); + crypto::identity_keygen(sign); SecretKey encr; - cmanager.instance()->encryption_keygen(encr); + crypto::encryption_keygen(encr); rc.enckey = encr.toPublic(); rc.pubkey = sign.toPublic(); @@ -37,10 +30,10 @@ TEST_CASE("RouterContact Decode Version 1", "[RC][RouterContact][V1]") RouterContact rc; SecretKey sign; - cmanager.instance()->identity_keygen(sign); + crypto::identity_keygen(sign); SecretKey encr; - cmanager.instance()->encryption_keygen(encr); + crypto::encryption_keygen(encr); rc.version = 1; @@ -76,16 +69,16 @@ TEST_CASE("RouterContact Decode Mixed Versions", "[RC][RouterContact]") rc4.version = 1; SecretKey sign1, sign2, sign3, sign4; - cmanager.instance()->identity_keygen(sign1); - cmanager.instance()->identity_keygen(sign2); - cmanager.instance()->identity_keygen(sign3); - cmanager.instance()->identity_keygen(sign4); + crypto::identity_keygen(sign1); + crypto::identity_keygen(sign2); + crypto::identity_keygen(sign3); + crypto::identity_keygen(sign4); SecretKey encr1, encr2, encr3, encr4; - cmanager.instance()->encryption_keygen(encr1); - cmanager.instance()->encryption_keygen(encr2); - cmanager.instance()->encryption_keygen(encr3); - cmanager.instance()->encryption_keygen(encr4); + crypto::encryption_keygen(encr1); + crypto::encryption_keygen(encr2); + crypto::encryption_keygen(encr3); + crypto::encryption_keygen(encr4); rc1.enckey = encr1.toPublic(); rc2.enckey = encr2.toPublic(); From 12a89328fe8c343aae9a55d438ac736527e9bd26 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Mon, 23 Oct 2023 15:58:58 -0700 Subject: [PATCH 067/312] Cmake restructuring --- CMakeLists.txt | 21 +- cmake/CMakeGraphVizOptions.cmake | 9 +- daemon/CMakeLists.txt | 6 +- daemon/lokinet.cpp | 3 - external/CMakeLists.txt | 2 +- llarp/CMakeLists.txt | 226 ++++++-------- llarp/CMakeLists_old.txt | 421 --------------------------- llarp/config/config.hpp | 1 + llarp/config/key_manager.cpp | 4 +- llarp/crypto/crypto.cpp | 4 +- llarp/crypto/crypto.hpp | 4 +- llarp/crypto/encrypted_frame.cpp | 4 +- llarp/crypto/types.cpp | 3 - llarp/crypto/types.hpp | 7 +- llarp/handlers/exit.cpp | 6 +- llarp/link/tunnel.hpp | 18 +- llarp/messages/exit.hpp | 18 +- llarp/messages/path.hpp | 2 +- llarp/path/transit_hop.cpp | 4 +- llarp/pow.cpp | 3 +- llarp/router_contact.cpp | 3 +- llarp/service/async_key_exchange.cpp | 3 +- llarp/service/auth.cpp | 3 +- llarp/service/context.cpp | 337 +++++++++++---------- llarp/service/identity.cpp | 3 +- llarp/service/intro_set.cpp | 6 +- llarp/service/protocol.cpp | 3 +- 27 files changed, 311 insertions(+), 813 deletions(-) delete mode 100644 llarp/CMakeLists_old.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index eff2b914fc..4e68a24268 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15 CACHE STRING "macOS deployment target (Apple clang only)") option(BUILD_DAEMON "build lokinet daemon and associated utils" ON) - +option(GRAPH_DEPENDENCIES "Produce graphviz representation of cmake dependencies" OFF) set(LANGS C CXX) if(APPLE AND BUILD_DAEMON) @@ -257,23 +257,26 @@ pkg_check_modules(SD libsystemd IMPORTED_TARGET) # Default WITH_SYSTEMD to true if we found it option(WITH_SYSTEMD "enable systemd integration for sd_notify" ${SD_FOUND}) -# Base interface target where we set up global link libraries, definitions, includes, etc. -add_library(base_libs INTERFACE) +add_subdirectory(external) + +# interface library for setting common includes, linkage and flags +add_library(lokinet-base INTERFACE) +target_include_directories(lokinet-base INTERFACE . include) +target_link_libraries(lokinet-base INTERFACE quic) if(WITH_SYSTEMD AND (NOT ANDROID)) if(NOT SD_FOUND) message(FATAL_ERROR "libsystemd not found") endif() - target_link_libraries(base_libs INTERFACE PkgConfig::SD) - target_compile_definitions(base_libs INTERFACE WITH_SYSTEMD) + target_link_libraries(lokinet-base INTERFACE PkgConfig::SD) + target_compile_definitions(lokinet-base INTERFACE WITH_SYSTEMD) endif() -add_subdirectory(external) if(USE_JEMALLOC AND NOT STATIC_LINK) pkg_check_modules(JEMALLOC jemalloc IMPORTED_TARGET) if(JEMALLOC_FOUND) - target_link_libraries(base_libs INTERFACE PkgConfig::JEMALLOC) + target_link_libraries(lokinet-base INTERFACE PkgConfig::JEMALLOC) else() message(STATUS "jemalloc not found, not linking to jemalloc") endif() @@ -283,8 +286,8 @@ endif() if(ANDROID) - target_link_libraries(base_libs INTERFACE log) - target_compile_definitions(base_libs INTERFACE ANDROID) + target_link_libraries(lokinet-base INTERFACE log) + target_compile_definitions(lokinet-base INTERFACE ANDROID) set(ANDROID_PLATFORM_SRC android/ifaddrs.c) endif() diff --git a/cmake/CMakeGraphVizOptions.cmake b/cmake/CMakeGraphVizOptions.cmake index f0de4137e8..4d97401719 100644 --- a/cmake/CMakeGraphVizOptions.cmake +++ b/cmake/CMakeGraphVizOptions.cmake @@ -1,5 +1,6 @@ -set(GRAPHVIZ_MODULE_LIBS OFF CACHE BOOL "") -set(GRAPHVIZ_EXTERNAL_LIBS OFF CACHE BOOL "") -set(GRAPHVIZ_GENERATE_PER_TARGET OFF CACHE BOOL "") -set(GRAPHVIZ_GENERATE_DEPENDERS OFF CACHE BOOL "") +set(GRAPHVIZ_GRAPH_NAME "graph.dot" CACHE STRING "") +# set(GRAPHVIZ_MODULE_LIBS OFF CACHE BOOL "") +# set(GRAPHVIZ_EXTERNAL_LIBS OFF CACHE BOOL "") +set(GRAPHVIZ_GENERATE_PER_TARGET FALSE CACHE BOOL "") +set(GRAPHVIZ_GENERATE_DEPENDERS FALSE CACHE BOOL "") set(GRAPHVIZ_OBJECT_LIBS OFF CACHE BOOL "") diff --git a/daemon/CMakeLists.txt b/daemon/CMakeLists.txt index c9ff4aec6e..05685f44a8 100644 --- a/daemon/CMakeLists.txt +++ b/daemon/CMakeLists.txt @@ -59,7 +59,8 @@ foreach(exe ${exetargets}) elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") target_link_directories(${exe} PRIVATE /usr/local/lib) endif() - target_link_libraries(${exe} PUBLIC lokinet-amalgum hax_and_shims_for_cmake) + # target_link_libraries(${exe} PUBLIC lokinet-amalgum hax_and_shims_for_cmake) + target_link_libraries(${exe} PUBLIC lokinet-core hax_and_shims_for_cmake) if(STRIP_SYMBOLS) add_custom_command(TARGET ${exe} POST_BUILD @@ -79,6 +80,9 @@ foreach(exe ${exetargets}) endif() endforeach() +target_link_libraries(lokinet PRIVATE CLI11) +target_link_libraries(lokinet-vpn PRIVATE CLI11) + if(SETCAP) install(CODE "execute_process(COMMAND ${SETCAP} cap_net_admin,cap_net_bind_service=+eip ${CMAKE_INSTALL_PREFIX}/bin/lokinet)") endif() diff --git a/daemon/lokinet.cpp b/daemon/lokinet.cpp index 2d87fc7bba..b57e284494 100644 --- a/daemon/lokinet.cpp +++ b/daemon/lokinet.cpp @@ -371,9 +371,6 @@ namespace int lokinet_main(int argc, char** argv) { - // if (auto result = Lokinet_INIT()) - // return result; - llarp::RuntimeOptions opts; opts.showBanner = false; diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 5fb082101d..2b09d0ee5b 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -147,7 +147,7 @@ option(WITH_LIBCRYPT "enable fast password hash with libcrypt" ${default_libcryp add_library(lokinet-libcrypt INTERFACE) if(WITH_LIBCRYPT) pkg_check_modules(LIBCRYPT libcrypt IMPORTED_TARGET REQUIRED) - add_definitions(-DHAVE_CRYPT) + target_compile_definitions(lokinet-libcrypt INTERFACE -DHAVE_CRYPT) target_link_libraries(lokinet-libcrypt INTERFACE PkgConfig::LIBCRYPT) message(STATUS "using libcrypt ${LIBCRYPT_VERSION}") else() diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index aec3b59f0e..a3c698a2f1 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -1,44 +1,49 @@ include(Version) -add_library(lokinet-cryptography - STATIC + +# Add an internal lokinet static library target, enables LTO (if enabled) on the target, +# and links it to the common lokinet-base interface. +# Invoke with the target/library name (e.g. "lokinet-foo") and list of source files, e.g. +# lokinet_add_library(lokinet-foo foo/source1.cpp foo/source2.cpp) +function(lokinet_add_library libname) + add_library(${libname} STATIC ${ARGN}) + target_link_libraries(${libname} PUBLIC lokinet-base) + enable_lto(${libname}) +endfunction() + + +lokinet_add_library(lokinet-cryptography crypto/crypto.cpp crypto/encrypted_frame.cpp crypto/types.cpp ) -# files only included by lokinet-core -add_library(lokinet-core-internal - STATIC - router/rc_gossiper.cpp - service/info.cpp - service/lns_tracker.cpp - service/session.cpp -) - # Functional objects use by lokinet-core and other libraries # needed by vpn/ router/ rpc/ handlers/ net/ link/ -add_library(lokinet-core-utils - STATIC +lokinet_add_library(lokinet-core-utils endpoint_base.cpp exit/context.cpp exit/endpoint.cpp # handlers/exit.hpp exit/policy.cpp # net/ + handlers/exit.cpp # link/ exit/ + handlers/tun.cpp + router/rc_gossiper.cpp service/auth.cpp # config/ service/context.cpp service/identity.cpp + service/info.cpp service/intro.cpp # path + service/lns_tracker.cpp service/name.cpp + service/session.cpp service/tag.cpp + vpn/egres_packet_router.cpp ) -add_library(lokinet-core - STATIC +lokinet_add_library(lokinet-core context.cpp consensus/reachability_testing.cpp exit/session.cpp - handlers/exit.cpp # link/ exit/ - handlers/tun.cpp link/link_manager.cpp router/router.cpp router/route_poker.cpp @@ -49,16 +54,9 @@ add_library(lokinet-core service/name.cpp service/outbound_context.cpp service/protocol.cpp - vpn/egres_packet_router.cpp ) - -# Files only included by lokinet-rpc -# add_library(lokinet-rpc-internal -# STATIC -# ) - - add_library(lokinet-rpc - STATIC + +lokinet_add_library(lokinet-rpc rpc/json_binary_proxy.cpp rpc/json_conversions.cpp rpc/lokid_rpc_client.cpp @@ -66,28 +64,16 @@ add_library(lokinet-core rpc/rpc_server.cpp rpc/endpoint_rpc.cpp ) - -# Files only included by lokinet-wire -add_library(lokinet-wire-internal - STATIC + +lokinet_add_library(lokinet-wire link/connection.cpp -) - -add_library(lokinet-wire - STATIC link/contacts.cpp link/link_manager.cpp # link/tunnel.cpp ) -add_library(lokinet-utils-internal - STATIC - util/thread/queue_manager.cpp -) - # config, crypto, timeplace, nodedb, bootstrap.cpp, net, router -add_library(lokinet-utils - STATIC +lokinet_add_library(lokinet-utils ${CMAKE_CURRENT_BINARY_DIR}/constants/version.cpp util/bencode.cpp util/buffer.cpp @@ -95,16 +81,16 @@ add_library(lokinet-utils util/mem.cpp util/str.cpp util/thread/threading.cpp + util/thread/queue_manager.cpp util/time.cpp util/logging/buffer.cpp ) - + add_dependencies(lokinet-utils genversion) # Addressing and event loop files used by lokinet-core and other libraries # needed by rpc/ link/ service/ config/ path/ dht/ -add_library(lokinet-time-place - STATIC +lokinet_add_library(lokinet-time-place pow.cpp # only intro_set router_contact.cpp router_id.cpp @@ -124,8 +110,7 @@ add_library(lokinet-time-place ) # lokinet-platform holds all platform specific code -add_library(lokinet-platform - STATIC +lokinet_add_library(lokinet-platform router/rc_lookup_handler.cpp net/interface_info.cpp vpn/packet_router.cpp @@ -171,7 +156,6 @@ endif() # should have no concept of dns caching, this is left as an implementation # detail of dns resolvers (LATER: make separate lib for dns resolvers) add_library(lokinet-dns-internal - STATIC dns/name.cpp # srv_data, question, rr dns/platform.cpp dns/question.cpp # message @@ -179,8 +163,7 @@ add_library(lokinet-dns-internal dns/serialize.cpp ) -add_library(lokinet-dns - STATIC +lokinet_add_library(lokinet-dns dns/message.cpp # dns/server dns/server.cpp # handlers/exit+tun and service/endpoint dns/srv_data.cpp @@ -195,8 +178,7 @@ endif() # lokinet-nodedb holds all types and logic for storing parsing and constructing # nodedb data published to the network and versions of it stored locally -add_library(lokinet-nodedb - STATIC +lokinet_add_library(lokinet-nodedb bootstrap.cpp # config, router.hpp nodedb.cpp profiling.cpp # path, router, service::endpoint @@ -223,8 +205,7 @@ configure_file("bootstrap-fallbacks.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/bootstr target_sources(lokinet-nodedb PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/bootstrap-fallbacks.cpp") # lokinet-config is for all configuration types and parsers -add_library(lokinet-config - STATIC +lokinet_add_library(lokinet-config config/config.cpp config/definition.cpp config/ini.cpp @@ -232,8 +213,7 @@ add_library(lokinet-config ) # All path objects; link directly to lokinet-core -add_library(lokinet-path - STATIC +lokinet_add_library(lokinet-path path/abstracthophandler.cpp path/path_context.cpp path/path.cpp @@ -243,23 +223,11 @@ add_library(lokinet-path messages/relay.cpp ) -add_library(lokinet-amalgum INTERFACE) - -# interface library for setting common includes, linkage and flags. -add_library(lokinet-base INTERFACE) -target_include_directories(lokinet-base - INTERFACE ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/include -) -target_link_libraries(lokinet-base INTERFACE quic) - # Link libraries to their internals -target_link_libraries(lokinet-core-internal PUBLIC lokinet-utils lokinet-core-utils) -target_link_libraries(lokinet-core PRIVATE lokinet-core-internal) -# target_link_libraries(lokinet-rpc PRIVATE lokinet-rpc-internal) -target_link_libraries(lokinet-wire PRIVATE lokinet-wire-internal) -# target_link_libraries(lokinet-time-place PRIVATE lokinet-time-place-internal) +target_link_libraries(lokinet-core-utils PUBLIC lokinet-dns) +target_link_libraries(lokinet-core PUBLIC lokinet-core-utils) + target_link_libraries(lokinet-dns PRIVATE lokinet-dns-internal) -target_link_libraries(lokinet-utils PRIVATE lokinet-utils-internal) # Link lokinet-dns to alternate libraries target_link_libraries(lokinet-dns PUBLIC lokinet-dns-platform) @@ -267,36 +235,9 @@ if (TARGET lokinet-dns-systemd) target_link_libraries(lokinet-dns PUBLIC lokinet-dns-systemd) endif() -# Link relevant to lokinet-base -target_link_libraries(lokinet-core PUBLIC lokinet-base) -target_link_libraries(lokinet-rpc PUBLIC lokinet-base) -target_link_libraries(lokinet-nodedb PUBLIC lokinet-base) -target_link_libraries(lokinet-wire PUBLIC lokinet-base) -target_link_libraries(lokinet-time-place PUBLIC lokinet-base) -target_link_libraries(lokinet-dns PUBLIC lokinet-base) -target_link_libraries(lokinet-platform PUBLIC lokinet-base) -target_link_libraries(lokinet-utils PUBLIC lokinet-base) -target_link_libraries(lokinet-libntrup PUBLIC lokinet-base) - -# Link relevant to amalgum -target_link_libraries(lokinet-amalgum - INTERFACE - lokinet-core - lokinet-rpc - lokinet-nodedb - lokinet-wire - lokinet-time-place - lokinet-dns - lokinet-platform - lokinet-utils - lokinet-cryptography - lokinet-path -) -#or just do this?? -# target_link_libraries(lokinet-amalgum INTERFACE lokinet-base) -target_link_libraries(lokinet-wire-internal PUBLIC lokinet-time-place) -target_link_libraries(lokinet-dns-internal PUBLIC lokinet-utils lokinet-config) -target_link_libraries(lokinet-dns PUBLIC lokinet-cryptography) +target_link_libraries(lokinet-wire PUBLIC lokinet-time-place) +target_link_libraries(lokinet-dns-internal PUBLIC lokinet-utils) +target_link_libraries(lokinet-dns PUBLIC lokinet-cryptography lokinet-config) target_link_libraries(lokinet-nodedb PUBLIC lokinet-cryptography) target_link_libraries(lokinet-platform PUBLIC lokinet-cryptography) target_link_libraries(lokinet-rpc PUBLIC lokinet-wire) @@ -304,6 +245,11 @@ target_link_libraries(lokinet-time-place PUBLIC lokinet-utils lokinet-cryptograp target_link_libraries(lokinet-wire PUBLIC lokinet-cryptography) target_link_libraries(lokinet-config PUBLIC lokinet-cryptography) +target_link_libraries(lokinet-dns + PUBLIC + lokinet-time-place +) + target_link_libraries(lokinet-path PUBLIC lokinet-time-place @@ -311,10 +257,10 @@ target_link_libraries(lokinet-path target_link_libraries(lokinet-core-utils PUBLIC - lokinet-core - lokinet-wire - lokinet-rpc + lokinet-config lokinet-platform + lokinet-rpc + lokinet-wire ) target_link_libraries(lokinet-cryptography @@ -333,50 +279,42 @@ target_link_libraries(lokinet-core PUBLIC lokinet-rpc lokinet-wire - lokinet-nodedb - lokinet-config + lokinet-nodedb + lokinet-path lokinet-cryptography ) +target_link_libraries(lokinet-base INTERFACE oxenc::oxenc oxen::logging) -# per component external deps -# target_link_libraries(oxenmq::oxenmq -# PUBLIC -# lokinet-time-place -# lokinet-core -# lokinet-config -# lokinet-platform -# lokinet-dns -# lokinet-rpc -# ) - -target_link_libraries(lokinet-rpc PUBLIC oxenmq::oxenmq oxenc::oxenc) -target_link_libraries(lokinet-core PUBLIC oxenmq::oxenmq CLI11 uvw) +target_link_libraries(lokinet-rpc PUBLIC oxenmq::oxenmq) +target_link_libraries(lokinet-core PUBLIC oxenmq::oxenmq) target_link_libraries(lokinet-config PUBLIC oxenmq::oxenmq) -target_link_libraries(lokinet-nodedb PUBLIC oxenmq::oxenmq uvw) +target_link_libraries(lokinet-nodedb PUBLIC oxenmq::oxenmq) target_link_libraries(lokinet-path PUBLIC oxenmq::oxenmq) -target_link_libraries(lokinet-time-place PUBLIC uvw oxenc::oxenc) -target_link_libraries(lokinet-platform PUBLIC oxenmq::oxenmq Threads::Threads base_libs uvw) -target_link_libraries(lokinet-cryptography PUBLIC oxenc::oxenc sodium) -target_link_libraries(lokinet-dns PUBLIC libunbound uvw) -target_link_libraries(lokinet-utils PUBLIC nlohmann_json::nlohmann_json oxenc::oxenc) -target_link_libraries(lokinet-wire PUBLIC oxenmq::oxenmq quic uvw) - -# if(WITH_EMBEDDED_LOKINET) -# include(GNUInstallDirs) -# add_library(lokinet-shared SHARED lokinet_shared.cpp) -# target_link_libraries(lokinet-shared PUBLIC lokinet-amalgum) -# if(WIN32) -# set(CMAKE_SHARED_LIBRARY_PREFIX_CXX "") -# endif() -# set_target_properties(lokinet-shared PROPERTIES OUTPUT_NAME lokinet) -# if(WIN32) -# target_link_libraries(lokinet-shared PUBLIC ws2_32 iphlpapi -fstack-protector) -# install(TARGETS lokinet-shared DESTINATION bin COMPONENT liblokinet) -# elseif(NOT APPLE) -# install(TARGETS lokinet-shared LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT liblokinet) -# endif() -# endif() - -# file(GLOB_RECURSE docs_SRC */*.hpp *.hpp) -# set(DOCS_SRC ${docs_SRC} PARENT_SCOPE) +target_link_libraries(lokinet-time-place PUBLIC uvw) +# target_link_libraries(lokinet-platform PUBLIC oxenmq::oxenmq Threads::Threads base_libs uvw) +target_link_libraries(lokinet-platform PUBLIC oxenmq::oxenmq Threads::Threads uvw) +target_link_libraries(lokinet-cryptography PUBLIC sodium) +target_link_libraries(lokinet-dns PUBLIC libunbound) +target_link_libraries(lokinet-utils PUBLIC nlohmann_json::nlohmann_json) +target_link_libraries(lokinet-wire PUBLIC oxenmq::oxenmq quic) + +if(WITH_EMBEDDED_LOKINET) + include(GNUInstallDirs) + add_library(lokinet-shared SHARED lokinet_shared.cpp) + # target_link_libraries(lokinet-shared PUBLIC lokinet-amalgum) + target_link_libraries(lokinet-shared PUBLIC lokinet-core) + if(WIN32) + set(CMAKE_SHARED_LIBRARY_PREFIX_CXX "") + endif() + set_target_properties(lokinet-shared PROPERTIES OUTPUT_NAME lokinet) + if(WIN32) + target_link_libraries(lokinet-shared PUBLIC ws2_32 iphlpapi -fstack-protector) + install(TARGETS lokinet-shared DESTINATION bin COMPONENT liblokinet) + elseif(NOT APPLE) + install(TARGETS lokinet-shared LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT liblokinet) + endif() +endif() + +file(GLOB_RECURSE docs_SRC */*.hpp *.hpp) +set(DOCS_SRC ${docs_SRC} PARENT_SCOPE) diff --git a/llarp/CMakeLists_old.txt b/llarp/CMakeLists_old.txt deleted file mode 100644 index cc2d51d5e4..0000000000 --- a/llarp/CMakeLists_old.txt +++ /dev/null @@ -1,421 +0,0 @@ -include(Version) - -add_library(lokinet-cryptography - STATIC - crypto/crypto.cpp - crypto/encrypted_frame.cpp - crypto/types.cpp -) - -add_library(lokinet-util - STATIC - ${CMAKE_CURRENT_BINARY_DIR}/constants/version.cpp - util/bencode.cpp - util/buffer.cpp - util/file.cpp - util/json.cpp - util/logging/buffer.cpp - util/easter_eggs.cpp - util/mem.cpp - util/str.cpp - util/thread/queue_manager.cpp - util/thread/threading.cpp - util/time.cpp) - -add_dependencies(lokinet-util genversion) - -# lokinet-platform holds all platform specific code -add_library(lokinet-platform - STATIC - # for networking - ev/ev.cpp - ev/libuv.cpp - net/interface_info.cpp - net/ip.cpp - net/ip_address.cpp - net/ip_packet.cpp - net/ip_range.cpp - net/net_int.cpp - net/sock_addr.cpp - vpn/packet_router.cpp - vpn/egres_packet_router.cpp - vpn/platform.cpp -) - -if (ANDROID) - target_sources(lokinet-platform PRIVATE android/ifaddrs.c util/nop_service_manager.cpp) -endif() - -if(CMAKE_SYSTEM_NAME MATCHES "Linux") - target_sources(lokinet-platform PRIVATE linux/dbus.cpp) - if(WITH_SYSTEMD) - target_sources(lokinet-platform PRIVATE linux/sd_service_manager.cpp) - else() - target_sources(lokinet-platform PRIVATE util/nop_service_manager.cpp) - endif() -endif() - -if (WIN32) - target_sources(lokinet-platform PRIVATE - net/win32.cpp - vpn/win32.cpp - win32/service_manager.cpp - win32/exec.cpp - win32/dll.cpp - win32/exception.cpp - win32/wintun.cpp - win32/windivert.cpp) - target_include_directories(lokinet-platform PRIVATE ${CMAKE_BINARY_DIR}/wintun/include/ ${CMAKE_BINARY_DIR}/WinDivert-${WINDIVERT_VERSION}/include/) -else() - target_sources(lokinet-platform PRIVATE - net/posix.cpp) -endif() - -if(APPLE) - add_subdirectory(apple) - target_sources(lokinet-platform PRIVATE util/nop_service_manager.cpp) -endif() - -# lokinet-dns is the dns parsing and hooking library that we use to -# parse modify and reconstitute dns wire proto, dns queries and RR -# should have no concept of dns caching, this is left as an implementation -# detail of dns resolvers (LATER: make separate lib for dns resolvers) -add_library(lokinet-dns - STATIC - dns/message.cpp - dns/name.cpp - dns/platform.cpp - dns/question.cpp - dns/rr.cpp - dns/serialize.cpp - dns/server.cpp - dns/srv_data.cpp) - -# platform specific bits and bobs for setting dns -add_library(lokinet-dns-platform INTERFACE) -if(WITH_SYSTEMD) - add_library(lokinet-dns-systemd STATIC dns/nm_platform.cpp dns/sd_platform.cpp) - target_link_libraries(lokinet-dns-platform INTERFACE lokinet-dns-systemd) -endif() - -# lokinet-nodedb holds all types and logic for storing parsing and constructing -# nodedb data published to the network and versions of it stored locally -add_library(lokinet-nodedb - STATIC - bootstrap.cpp - net/exit_info.cpp - net/traffic_policy.cpp - nodedb.cpp - pow.cpp - profiling.cpp - router_contact.cpp - router_id.cpp - router_version.cpp -) - -set(BOOTSTRAP_FALLBACKS) -foreach(bs IN ITEMS MAINNET TESTNET) - if(BOOTSTRAP_FALLBACK_${bs}) - message(STATUS "Building with ${bs} fallback boostrap path \"${BOOTSTRAP_FALLBACK_${bs}}\"") - file(READ "${BOOTSTRAP_FALLBACK_${bs}}" bs_data HEX) - if(bs STREQUAL TESTNET) - set(network "gamma") - elseif(bs STREQUAL MAINNET) - set(network "lokinet") - else() - string(TOLOWER "${bs}" network) - endif() - string(REGEX REPLACE "([0-9a-f][0-9a-f])" "\\\\x\\1" bs_data "${bs_data}") - set(BOOTSTRAP_FALLBACKS "${BOOTSTRAP_FALLBACKS}{\"${network}\"s, \"${bs_data}\"sv},\n") - endif() -endforeach() -configure_file("bootstrap-fallbacks.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/bootstrap-fallbacks.cpp" @ONLY) -target_sources(lokinet-nodedb PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/bootstrap-fallbacks.cpp") - -# lokinet-config is for all configuration types and parsers -add_library(lokinet-config - STATIC - config/config.cpp - config/definition.cpp - config/ini.cpp - config/key_manager.cpp -) - -# lokinet-consensus is for deriving and tracking network consensus state for both service nodes and clients -add_library(lokinet-consensus - STATIC - consensus/reachability_testing.cpp -) - -# lokinet-layer-onion is the "dumb" onion routing layer with builds manages and does i/o -# with onion paths. onion paths anonymize routing layer pdu. -add_library(lokinet-layer-onion - STATIC - path/abstracthophandler.cpp - path/path_context.cpp - path/path.cpp - path/pathbuilder.cpp - path/pathset.cpp - path/transit_hop.cpp - messages/relay.cpp -) - -# lokinet-layer-link is for our layer 2 analog which splits up layer 2 frames into -# a series of layer 1 symbols which are then transmitted between lokinet instances -add_library(lokinet-layer-link - STATIC - link/connection.cpp - link/contacts.cpp - link/link_manager.cpp - # link/tunnel.cpp -) - -# lokinet-context holds the contextualized god objects for a lokinet instance -# it is what any main function would link to in practice but it is hidden behind an interface library (lokinet-amalgum) -add_library(lokinet-context - STATIC - context.cpp - link/link_manager.cpp - router/rc_lookup_handler.cpp - router/rc_gossiper.cpp - router/router.cpp - router/route_poker.cpp -) - -# lokinet-rpc holds all rpc related compilation units -add_library(lokinet-rpc - STATIC - rpc/json_binary_proxy.cpp - rpc/json_conversions.cpp - rpc/lokid_rpc_client.cpp - rpc/rpc_request_parser.cpp - rpc/rpc_server.cpp - rpc/endpoint_rpc.cpp -) - -# optional peer stats library -add_library(lokinet-peerstats - STATIC - peerstats/peer_db.cpp - peerstats/types.cpp -) - -# kitchen sink to be removed after refactor -add_library(lokinet-service-deprecated-kitchensink - STATIC - endpoint_base.cpp - exit/context.cpp - exit/endpoint.cpp - exit/policy.cpp - exit/session.cpp - handlers/exit.cpp - handlers/tun.cpp - service/name.cpp - service/address.cpp - service/async_key_exchange.cpp - service/auth.cpp - service/convotag.cpp - service/context.cpp - service/endpoint_state.cpp - service/endpoint_util.cpp - service/endpoint.cpp - service/identity.cpp - service/info.cpp - service/intro_set.cpp - service/intro.cpp - service/lns_tracker.cpp - service/name.cpp - service/outbound_context.cpp - service/protocol.cpp - service/session.cpp - service/tag.cpp -) - -# interface library for setting commone includes, linkage and flags. -add_library(lokinet-base INTERFACE) -target_include_directories(lokinet-base - INTERFACE ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/include -) -target_link_libraries(lokinet-base INTERFACE quic) - -if(WITH_PEERSTATS) - target_compile_definitions(lokinet-base INTERFACE -DLOKINET_PEERSTATS_BACKEND) - target_link_libraries(lokinet-base INTERFACE sqlite_orm) -endif() - -# interface libraries for internal linkage -add_library(lokinet-layers INTERFACE) -add_library(lokinet-amalgum INTERFACE) - -# helper function to link a library to lokinet-base, enable lto, add to lokinet-amalgum and then link to other libs -function(lokinet_link_lib libname) - # Absolutely fuck this line, it doesn't "create" the target, as the target already exists - # message(DEBUG "created target: ${libname}") - enable_lto(${libname}) - target_link_libraries(${libname} PUBLIC lokinet-base ${ARGN}) - target_link_libraries(lokinet-amalgum INTERFACE ${libname}) -endfunction() - -# internal public linkages of components -lokinet_link_lib(lokinet-util lokinet-libntrup) -lokinet_link_lib(lokinet-cryptography lokinet-libcrypt lokinet-util) -lokinet_link_lib(lokinet-peerstats lokinet-context) -lokinet_link_lib(lokinet-consensus lokinet-context) -lokinet_link_lib(lokinet-layer-link lokinet-cryptography lokinet-peerstats) - -if(TARGET lokinet-dns-systemd) - lokinet_link_lib(lokinet-dns-systemd - lokinet-dns - lokinet-platform - ) -endif() - -lokinet_link_lib(lokinet-platform lokinet-util) - -lokinet_link_lib(lokinet-config - lokinet-util - lokinet-nodedb - lokinet-dns - lokinet-platform -) - -lokinet_link_lib(lokinet-context - lokinet-config - lokinet-platform - lokinet-peerstats - lokinet-layers - lokinet-consensus - lokinet-rpc -) - -lokinet_link_lib( - lokinet-platform - lokinet-config -) - -lokinet_link_lib(lokinet-dns - lokinet-platform - lokinet-dns-platform - lokinet-config -) - -lokinet_link_lib(lokinet-nodedb - lokinet-util - lokinet-platform -) - -lokinet_link_lib(lokinet-util - lokinet-nodedb - lokinet-platform -) - -lokinet_link_lib(lokinet-rpc - lokinet-context - lokinet-peerstats - lokinet-util -) - -# inter lokinet-layer public/private linkage. -# when linking each layer, we consider the layer directly below private linkage and the layer above public linkage. -# this lets us hide functionality of layers below us when depended on by another component. -# -# from highest to lowest layer, the above layers are stacked as follows: -# -# platform (what lokinet snapps interact with, be it l3 os interaction or embedded lokinet) -# flow (how we want to route and stripe over our onion routing) -# routing (what we are onion routing) -# onion (how the onion routing happens) -# link (what we want to send over the wire and to where) -# wire (what is actually sent over the wire) -# -function(link_lokinet_layers) - set(lib ${ARGV0}) - if(${ARGC} GREATER 1) - lokinet_link_lib(${ARGV1} ${lib}) - list(REMOVE_AT ARGV 1) - target_link_libraries(${lib} PRIVATE ${ARGV1}) - # recursion :D - link_lokinet_layers(${ARGV}) - else() - lokinet_link_lib(${lib}) - endif() -endfunction() - -link_lokinet_layers( - lokinet-layer-onion - lokinet-layer-link -) - -# set me to OFF to disable old codepath -set(use_old_impl ON) -if(use_old_impl) - # flow layer deprecated-kitchensink (remove me after refactor) - lokinet_link_lib(lokinet-service-deprecated-kitchensink - lokinet-dns - lokinet-nodedb - lokinet-context - lokinet-layer-onion - lokinet-platform - lokinet-rpc - ) - target_link_libraries(lokinet-layers INTERFACE lokinet-service-deprecated-kitchensink) -endif() - -target_link_libraries(lokinet-layers INTERFACE - lokinet-layer-onion - lokinet-layer-link -) - - -# per component external deps - -target_link_libraries(lokinet-config PUBLIC oxenmq::oxenmq) -target_link_libraries(lokinet-platform PUBLIC oxenmq::oxenmq) -target_link_libraries(lokinet-dns PUBLIC libunbound) - -target_link_libraries(lokinet-cryptography PUBLIC - oxenc::oxenc - sodium -) - -target_link_libraries(lokinet-context PUBLIC - CLI11 - oxenmq::oxenmq - uvw -) - -target_link_libraries(lokinet-platform PUBLIC - Threads::Threads - base_libs - uvw -) - -target_link_libraries(lokinet-util PUBLIC - nlohmann_json::nlohmann_json -# filesystem - oxenc::oxenc -) - -target_link_libraries(lokinet-layer-link PUBLIC - quic - uvw -) - -if(WITH_EMBEDDED_LOKINET) - include(GNUInstallDirs) - add_library(lokinet-shared SHARED lokinet_shared.cpp) - target_link_libraries(lokinet-shared PUBLIC lokinet-amalgum) - if(WIN32) - set(CMAKE_SHARED_LIBRARY_PREFIX_CXX "") - endif() - set_target_properties(lokinet-shared PROPERTIES OUTPUT_NAME lokinet) - if(WIN32) - target_link_libraries(lokinet-shared PUBLIC ws2_32 iphlpapi -fstack-protector) - install(TARGETS lokinet-shared DESTINATION bin COMPONENT liblokinet) - elseif(NOT APPLE) - install(TARGETS lokinet-shared LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT liblokinet) - endif() -endif() - -file(GLOB_RECURSE docs_SRC */*.hpp *.hpp) -set(DOCS_SRC ${docs_SRC} PARENT_SCOPE) diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index 692f8521bd..ee357a3cf9 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -184,6 +184,7 @@ namespace llarp defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params); }; + // TODO: remove oxenmq from this header struct ApiConfig { bool m_enableRPCServer = false; diff --git a/llarp/config/key_manager.cpp b/llarp/config/key_manager.cpp index ae63a68f5e..96b73fb794 100644 --- a/llarp/config/key_manager.cpp +++ b/llarp/config/key_manager.cpp @@ -100,9 +100,7 @@ namespace llarp } // load encryption key - auto encryptionKeygen = [](llarp::SecretKey& key) { - llarp::crypto::encryption_keygen(key); - }; + auto encryptionKeygen = [](llarp::SecretKey& key) { llarp::crypto::encryption_keygen(key); }; if (not loadOrCreateKey(m_encKeyPath, encryptionKey, encryptionKeygen)) return false; diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index 79b71ab8bf..9ef4a3a420 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -109,7 +109,7 @@ namespace llarp } std::optional> - crypto::maybe_decrypt_name(std::string_view ciphertext, SymmNonce nounce, std::string_view name) + crypto::maybe_decrypt_name(std::string_view ciphertext, SymmNonce nonce, std::string_view name) { const auto payloadsize = ciphertext.size() - crypto_aead_xchacha20poly1305_ietf_ABYTES; if (payloadsize != 32) @@ -132,7 +132,7 @@ namespace llarp ciphertext.size(), nullptr, 0, - nounce.data(), + nonce.data(), derivedKey.data()) == -1) { diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index 2bb41122c2..2aae6a7ec2 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -19,7 +19,7 @@ namespace llarp { /// decrypt cipherText given the key generated from name std::optional> - maybe_decrypt_name(std::string_view ciphertext, SymmNonce nounce, std::string_view name); + maybe_decrypt_name(std::string_view ciphertext, SymmNonce nonce, std::string_view name); /// xchacha symmetric cipher bool @@ -117,7 +117,7 @@ namespace llarp bool check_passwd_hash(std::string pwhash, std::string challenge); - }; + }; // namespace crypto /// return random 64bit unsigned interger uint64_t diff --git a/llarp/crypto/encrypted_frame.cpp b/llarp/crypto/encrypted_frame.cpp index d8ca8c088e..7171c5eb2a 100644 --- a/llarp/crypto/encrypted_frame.cpp +++ b/llarp/crypto/encrypted_frame.cpp @@ -16,8 +16,8 @@ namespace llarp if (noDH) { - crypto::randbytes(nonce_ptr, TUNNONCESIZE); - crypto::randbytes(pubkey_ptr, PUBKEYSIZE); + crypto::randbytes(nonce_ptr, TUNNONCESIZE); + crypto::randbytes(pubkey_ptr, PUBKEYSIZE); } TunnelNonce nonce(nonce_ptr); diff --git a/llarp/crypto/types.cpp b/llarp/crypto/types.cpp index 9cf1c31591..bf375eda73 100644 --- a/llarp/crypto/types.cpp +++ b/llarp/crypto/types.cpp @@ -4,9 +4,6 @@ #include #include -// #include -// #include - namespace llarp { bool diff --git a/llarp/crypto/types.hpp b/llarp/crypto/types.hpp index a20c84fd2a..92bdd64f90 100644 --- a/llarp/crypto/types.hpp +++ b/llarp/crypto/types.hpp @@ -220,15 +220,14 @@ namespace llarp using PQKeyPair = AlignedBuffer; /// PKE(result, publickey, secretkey, nonce) - using path_dh_func = - bool(*)(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&); + using path_dh_func = bool (*)(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&); /// TKE(result, publickey, secretkey, nonce) using transport_dh_func = - bool(*)(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&); + bool (*)(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&); /// SH(result, body) - using shorthash_func = bool(*)(ShortHash&, const llarp_buffer_t&); + using shorthash_func = bool (*)(ShortHash&, const llarp_buffer_t&); } // namespace llarp namespace std diff --git a/llarp/handlers/exit.cpp b/llarp/handlers/exit.cpp index a82c1fc728..20578e5101 100644 --- a/llarp/handlers/exit.cpp +++ b/llarp/handlers/exit.cpp @@ -10,10 +10,8 @@ namespace llarp::handlers { - ExitEndpoint::ExitEndpoint(std::string name, Router* r) - : router(r) - , name(std::move(name)) - // , tunnel_manager{std::make_shared(*this)} + ExitEndpoint::ExitEndpoint(std::string name, Router* r) : router(r), name(std::move(name)) + // , tunnel_manager{std::make_shared(*this)} { should_init_tun = true; } diff --git a/llarp/link/tunnel.hpp b/llarp/link/tunnel.hpp index 4825af186e..4d5abca8e5 100644 --- a/llarp/link/tunnel.hpp +++ b/llarp/link/tunnel.hpp @@ -11,7 +11,7 @@ #include #include -#include +// #include namespace llarp { @@ -157,12 +157,12 @@ namespace llarp::link // Callback to invoke on quic connection established (true argument) or failed (false arg) OpenCallback open_cb; // TCP listening socket - std::shared_ptr tcp; - // Accepted TCP connections - std::unordered_set> conns; - // Queue of incoming connections that are waiting for a stream to become available (either - // because we are still handshaking, or we reached the stream limit). - std::queue> pending_incoming; + // std::shared_ptr tcp; + // // Accepted TCP connections + // std::unordered_set> conns; + // // Queue of incoming connections that are waiting for a stream to become available (either + // // because we are still handshaking, or we reached the stream limit). + // std::queue> pending_incoming; ~ClientTunnel() { @@ -225,8 +225,8 @@ namespace llarp::link std::map incoming_handlers_; int next_handler_id_ = 1; - std::shared_ptr - get_loop(); + // std::shared_ptr + // get_loop(); // Cleanup member std::shared_ptr timer_keepalive_ = std::make_shared(0); diff --git a/llarp/messages/exit.hpp b/llarp/messages/exit.hpp index 20d1084eb7..de53a01d7d 100644 --- a/llarp/messages/exit.hpp +++ b/llarp/messages/exit.hpp @@ -27,8 +27,7 @@ namespace llarp btdp.append("E", flag); btdp.append("T", tx_id); - if (not crypto::sign( - reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) + if (not crypto::sign(reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) throw std::runtime_error{ "Error: ObtainExitMessage failed to sign and serialize contents!"}; } @@ -51,8 +50,7 @@ namespace llarp btdp.append("T", tx_id); btdp.append("Y", nonce); - if (crypto::sign( - reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) + if (crypto::sign(reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) throw std::runtime_error{ "Error: ObtainExitMessage response failed to sign and serialize contents!"}; } @@ -80,8 +78,7 @@ namespace llarp btdp.append("P", path_id); btdp.append("T", tx_id); - if (not crypto::sign( - reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) + if (not crypto::sign(reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) throw std::runtime_error{ "Error: UpdateExitMessage failed to sign and serialize contents!"}; } @@ -104,8 +101,7 @@ namespace llarp btdp.append("T", tx_id); btdp.append("Y", nonce); - if (crypto::sign( - reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) + if (crypto::sign(reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) throw std::runtime_error{ "Error: UpdateExitMessage response failed to sign and serialize contents!"}; } @@ -134,8 +130,7 @@ namespace llarp btdp.append("T", tx_id); btdp.append("Y", nonce); - if (not crypto::sign( - reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) + if (not crypto::sign(reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) throw std::runtime_error{ "Error: CloseExitMessage failed to sign and serialize contents!"}; } @@ -158,8 +153,7 @@ namespace llarp btdp.append("T", tx_id); btdp.append("Y", nonce); - if (crypto::sign( - reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) + if (crypto::sign(reinterpret_cast(sig.data()), sk, to_usv(btdp.view()))) throw std::runtime_error{ "Error: CloseExitMessage response failed to sign and serialize contents!"}; } diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index 053b967022..e4885c620c 100644 --- a/llarp/messages/path.hpp +++ b/llarp/messages/path.hpp @@ -18,7 +18,7 @@ namespace llarp setup_hop_keys(path::PathHopConfig& hop, const RouterID& nextHop) { // generate key - crypto::encryption_keygen(hop.commkey); + crypto::encryption_keygen(hop.commkey); hop.nonce.Randomize(); // do key exchange diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index 0e681455f6..a228516c70 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -25,9 +25,7 @@ namespace llarp::path bool TransitHop::send_path_control_message( - std::string, - std::string, - std::function) + std::string, std::string, std::function) { return true; } diff --git a/llarp/pow.cpp b/llarp/pow.cpp index 5012ec394b..b0ae278986 100644 --- a/llarp/pow.cpp +++ b/llarp/pow.cpp @@ -31,8 +31,7 @@ namespace llarp auto buf = bt_encode(); // hash - if (!crypto::shorthash( - digest, reinterpret_cast(buf.data()), buf.size())) + if (!crypto::shorthash(digest, reinterpret_cast(buf.data()), buf.size())) return false; // check bytes required uint32_t required = std::floor(std::log(extendedLifetime.count())); diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index 3d5e439be9..e5396af499 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -409,8 +409,7 @@ namespace llarp copy.signature.Zero(); auto bte = copy.bt_encode(); - return crypto::verify( - pubkey, reinterpret_cast(bte.data()), bte.size(), signature); + return crypto::verify(pubkey, reinterpret_cast(bte.data()), bte.size(), signature); } static constexpr std::array obsolete_bootstraps = { diff --git a/llarp/service/async_key_exchange.cpp b/llarp/service/async_key_exchange.cpp index 0def85fac4..fbb42423c0 100644 --- a/llarp/service/async_key_exchange.cpp +++ b/llarp/service/async_key_exchange.cpp @@ -50,7 +50,8 @@ namespace llarp::service // compute post handshake session key // PKE (A, B, N) SharedSecret sharedSecret; - if (!self->m_LocalIdentity.KeyExchange(crypto::dh_client, sharedSecret, self->m_remote, frame->nonce)) + if (!self->m_LocalIdentity.KeyExchange( + crypto::dh_client, sharedSecret, self->m_remote, frame->nonce)) { LogError("failed to derive x25519 shared key component"); } diff --git a/llarp/service/auth.cpp b/llarp/service/auth.cpp index f68f9e355c..71e2f1509a 100644 --- a/llarp/service/auth.cpp +++ b/llarp/service/auth.cpp @@ -124,8 +124,7 @@ namespace llarp::service case AuthFileType::eAuthFilePlain: return hash == challenge; case AuthFileType::eAuthFileHashes: - return crypto::check_passwd_hash( - std::move(hash), std::move(challenge)); + return crypto::check_passwd_hash(std::move(hash), std::move(challenge)); default: return false; } diff --git a/llarp/service/context.cpp b/llarp/service/context.cpp index b465e8f076..abea6ca496 100644 --- a/llarp/service/context.cpp +++ b/llarp/service/context.cpp @@ -6,214 +6,211 @@ #include "endpoint.hpp" -namespace llarp +namespace llarp::service { - namespace service + static auto logcat = log::Cat("service"); + namespace { - static auto logcat = log::Cat("service"); - namespace - { - using EndpointConstructor = std::function; - using EndpointConstructors = std::map; - - static EndpointConstructors endpointConstructors = { - {"tun", - [](Router* r, service::Context* c) { - return std::make_shared(r, c); - }}, - {"android", - [](Router* r, service::Context* c) { - return std::make_shared(r, c); - }}, - {"ios", - [](Router* r, service::Context* c) { - return std::make_shared(r, c); - }}, - {"null", [](Router* r, service::Context* c) { - return std::make_shared(r, c); - }}}; - - } // namespace - Context::Context(Router* r) : m_Router(r) - {} - - Context::~Context() = default; - - bool - Context::StopAll() + using EndpointConstructor = std::function; + using EndpointConstructors = std::map; + + static EndpointConstructors endpointConstructors = { + {"tun", + [](Router* r, service::Context* c) { + return std::make_shared(r, c); + }}, + {"android", + [](Router* r, service::Context* c) { + return std::make_shared(r, c); + }}, + {"ios", + [](Router* r, service::Context* c) { + return std::make_shared(r, c); + }}, + {"null", [](Router* r, service::Context* c) { + return std::make_shared(r, c); + }}}; + + } // namespace + Context::Context(Router* r) : m_Router(r) + {} + + Context::~Context() = default; + + bool + Context::StopAll() + { + auto itr = m_Endpoints.begin(); + while (itr != m_Endpoints.end()) { - auto itr = m_Endpoints.begin(); - while (itr != m_Endpoints.end()) - { - log::debug(logcat, "Stopping endpoint {}.", itr->first); - itr->second->Stop(); - log::debug(logcat, "Endpoint {} stopped.", itr->first); - m_Stopped.emplace_back(std::move(itr->second)); - itr = m_Endpoints.erase(itr); - } - return true; + log::debug(logcat, "Stopping endpoint {}.", itr->first); + itr->second->Stop(); + log::debug(logcat, "Endpoint {} stopped.", itr->first); + m_Stopped.emplace_back(std::move(itr->second)); + itr = m_Endpoints.erase(itr); } + return true; + } - util::StatusObject - Context::ExtractStatus() const - { - util::StatusObject obj{}; - auto itr = m_Endpoints.begin(); - while (itr != m_Endpoints.end()) - { - obj[itr->first] = itr->second->ExtractStatus(); - ++itr; - } - return obj; - } - - void - Context::ForEachService( - std::function&)> visit) const + util::StatusObject + Context::ExtractStatus() const + { + util::StatusObject obj{}; + auto itr = m_Endpoints.begin(); + while (itr != m_Endpoints.end()) { - auto itr = m_Endpoints.begin(); - while (itr != m_Endpoints.end()) - { - if (visit(itr->first, itr->second)) - ++itr; - else - return; - } + obj[itr->first] = itr->second->ExtractStatus(); + ++itr; } + return obj; + } - void - Context::Pump() + void + Context::ForEachService( + std::function&)> visit) const + { + auto itr = m_Endpoints.begin(); + while (itr != m_Endpoints.end()) { - auto now = time_now_ms(); - for (auto& [name, endpoint] : m_Endpoints) - endpoint->Pump(now); + if (visit(itr->first, itr->second)) + ++itr; + else + return; } + } - bool - Context::RemoveEndpoint(const std::string& name) - { - auto itr = m_Endpoints.find(name); - if (itr == m_Endpoints.end()) - return false; - std::shared_ptr ep = std::move(itr->second); - m_Endpoints.erase(itr); - ep->Stop(); - m_Stopped.emplace_back(std::move(ep)); - return true; - } + void + Context::Pump() + { + auto now = time_now_ms(); + for (auto& [name, endpoint] : m_Endpoints) + endpoint->Pump(now); + } - void - Context::Tick(llarp_time_t now) + bool + Context::RemoveEndpoint(const std::string& name) + { + auto itr = m_Endpoints.find(name); + if (itr == m_Endpoints.end()) + return false; + std::shared_ptr ep = std::move(itr->second); + m_Endpoints.erase(itr); + ep->Stop(); + m_Stopped.emplace_back(std::move(ep)); + return true; + } + + void + Context::Tick(llarp_time_t now) + { + // erase stopped endpoints that are done { - // erase stopped endpoints that are done + auto itr = m_Stopped.begin(); + while (itr != m_Stopped.end()) { - auto itr = m_Stopped.begin(); - while (itr != m_Stopped.end()) - { - if ((*itr)->ShouldRemove()) - itr = m_Stopped.erase(itr); - else - ++itr; - } - } - // tick active endpoints - for (const auto& item : m_Endpoints) - { - item.second->Tick(now); + if ((*itr)->ShouldRemove()) + itr = m_Stopped.erase(itr); + else + ++itr; } } - - bool - Context::hasEndpoints() + // tick active endpoints + for (const auto& item : m_Endpoints) { - return m_Endpoints.size() ? true : false; + item.second->Tick(now); } + } - static const char* - DefaultEndpointType() - { + bool + Context::hasEndpoints() + { + return m_Endpoints.size() ? true : false; + } + + static const char* + DefaultEndpointType() + { #ifdef ANDROID - return "android"; + return "android"; #else #ifdef IOS - return "ios"; + return "ios"; #else - return "tun"; + return "tun"; #endif #endif - } + } - bool - Context::StartAll() + bool + Context::StartAll() + { + auto itr = m_Endpoints.begin(); + while (itr != m_Endpoints.end()) { - auto itr = m_Endpoints.begin(); - while (itr != m_Endpoints.end()) + if (!itr->second->Start()) { - if (!itr->second->Start()) - { - LogError(itr->first, " failed to start"); - return false; - } - LogInfo(itr->first, " started"); - ++itr; + LogError(itr->first, " failed to start"); + return false; } - return true; - } - - Endpoint_ptr - Context::GetEndpointByName(const std::string& name) const - { - auto itr = m_Endpoints.find(name); - if (itr != m_Endpoints.end()) - return itr->second; - return nullptr; + LogInfo(itr->first, " started"); + ++itr; } + return true; + } - void - Context::InjectEndpoint(std::string name, std::shared_ptr ep) + Endpoint_ptr + Context::GetEndpointByName(const std::string& name) const + { + auto itr = m_Endpoints.find(name); + if (itr != m_Endpoints.end()) + return itr->second; + return nullptr; + } + + void + Context::InjectEndpoint(std::string name, std::shared_ptr ep) + { + ep->LoadKeyFile(); + if (ep->Start()) { - ep->LoadKeyFile(); - if (ep->Start()) - { - m_Endpoints.emplace(std::move(name), std::move(ep)); - } + m_Endpoints.emplace(std::move(name), std::move(ep)); } + } - void - Context::AddEndpoint(const Config& conf, bool autostart) - { - constexpr auto endpointName = "default"; - - if (m_Endpoints.find(endpointName) != m_Endpoints.end()) - throw std::invalid_argument("service::Context only supports one endpoint now"); + void + Context::AddEndpoint(const Config& conf, bool autostart) + { + constexpr auto endpointName = "default"; - const auto& endpointType = conf.network.m_endpointType; - // use factory to create endpoint - const auto itr = endpointConstructors.find(endpointType); - if (itr == endpointConstructors.end()) - throw std::invalid_argument{fmt::format("Endpoint type {} does not exist", endpointType)}; + if (m_Endpoints.find(endpointName) != m_Endpoints.end()) + throw std::invalid_argument("service::Context only supports one endpoint now"); - auto service = itr->second(m_Router, this); - if (not service) - throw std::runtime_error{ - fmt::format("Failed to construct endpoint of type {}", endpointType)}; + const auto& endpointType = conf.network.m_endpointType; + // use factory to create endpoint + const auto itr = endpointConstructors.find(endpointType); + if (itr == endpointConstructors.end()) + throw std::invalid_argument{fmt::format("Endpoint type {} does not exist", endpointType)}; - // pass conf to service - service->Configure(conf.network, conf.dns); + auto service = itr->second(m_Router, this); + if (not service) + throw std::runtime_error{ + fmt::format("Failed to construct endpoint of type {}", endpointType)}; - if (not service->LoadKeyFile()) - throw std::runtime_error("Endpoint's keyfile could not be loaded"); + // pass conf to service + service->Configure(conf.network, conf.dns); - // autostart if requested - if (autostart) - { - if (service->Start()) - LogInfo("autostarting hidden service endpoint ", service->Name()); - else - throw std::runtime_error("failed to start hidden service endpoint"); - } + if (not service->LoadKeyFile()) + throw std::runtime_error("Endpoint's keyfile could not be loaded"); - m_Endpoints.emplace(endpointName, service); + // autostart if requested + if (autostart) + { + if (service->Start()) + LogInfo("autostarting hidden service endpoint ", service->Name()); + else + throw std::runtime_error("failed to start hidden service endpoint"); } - } // namespace service -} // namespace llarp + + m_Endpoints.emplace(endpointName, service); + } +} // namespace llarp::service diff --git a/llarp/service/identity.cpp b/llarp/service/identity.cpp index 9cfdf45dfa..3452146b5c 100644 --- a/llarp/service/identity.cpp +++ b/llarp/service/identity.cpp @@ -168,8 +168,7 @@ namespace llarp::service auto bte = i.bt_encode(); const SharedSecret k{i.address_keys.Addr()}; - crypto::xchacha20( - reinterpret_cast(bte.data()), bte.size(), k, encrypted.nounce); + crypto::xchacha20(reinterpret_cast(bte.data()), bte.size(), k, encrypted.nounce); std::memcpy(encrypted.introsetPayload.data(), bte.data(), bte.size()); diff --git a/llarp/service/intro_set.cpp b/llarp/service/intro_set.cpp index 11dd6f9992..bc2db09daf 100644 --- a/llarp/service/intro_set.cpp +++ b/llarp/service/intro_set.cpp @@ -123,8 +123,7 @@ namespace llarp::service std::string payload{ reinterpret_cast(introsetPayload.data()), introsetPayload.size()}; - crypto::xchacha20( - reinterpret_cast(payload.data()), payload.size(), k, nounce); + crypto::xchacha20(reinterpret_cast(payload.data()), payload.size(), k, nounce); return IntroSet{payload}; } @@ -144,8 +143,7 @@ namespace llarp::service sig.Zero(); auto bte = bt_encode(); - if (not crypto::sign( - sig, k, reinterpret_cast(bte.data()), bte.size())) + if (not crypto::sign(sig, k, reinterpret_cast(bte.data()), bte.size())) return false; LogDebug("signed encrypted introset: ", *this); return true; diff --git a/llarp/service/protocol.cpp b/llarp/service/protocol.cpp index a21a4b9b9a..1ec6783a62 100644 --- a/llarp/service/protocol.cpp +++ b/llarp/service/protocol.cpp @@ -207,8 +207,7 @@ namespace llarp::service // encode message auto bte1 = msg.bt_encode(); // encrypt - crypto::xchacha20( - reinterpret_cast(bte1.data()), bte1.size(), sessionKey, nonce); + crypto::xchacha20(reinterpret_cast(bte1.data()), bte1.size(), sessionKey, nonce); // put encrypted buffer std::memcpy(enc.data(), bte1.data(), bte1.size()); // zero out signature From f574cd798f05f70b3797d03bf9061d84a1f039bd Mon Sep 17 00:00:00 2001 From: dr7ana Date: Tue, 24 Oct 2023 06:18:03 -0700 Subject: [PATCH 068/312] Clang format include sorting + CMake - includes are now sorted in consistent, logical order; first step in an attempt to fix the tomfoolery (no relation to Tom) brought in by include-what-you-use - shuffled around some cmake linking to simplify dependency graph - superfluous files removed --- .clang-format | 26 +- CMakeLists.txt | 2 +- cmake/CMakeGraphVizOptions.cmake | 2 - crypto/libntrup/src/ntru.cpp | 3 +- daemon/lokinet-bootstrap.cpp | 10 +- daemon/lokinet-vpn.cpp | 13 +- daemon/lokinet.cpp | 94 ++-- include/lokinet.h | 4 +- jni/lokinet_config.cpp | 3 +- jni/lokinet_daemon.cpp | 3 +- jni/lokinet_jni_common.hpp | 3 +- llarp/CMakeLists.txt | 45 +- llarp/android/ifaddrs.c | 16 +- llarp/android/ifaddrs.h | 5 +- llarp/apple/DNSTrampoline.h | 2 +- llarp/apple/DNSTrampoline.m | 1 + llarp/apple/PacketTunnelProvider.m | 5 +- llarp/apple/context.hpp | 5 +- llarp/apple/context_wrapper.cpp | 21 +- llarp/apple/context_wrapper.h | 2 +- llarp/apple/route_manager.cpp | 4 +- llarp/apple/route_manager.hpp | 3 +- llarp/apple/vpn_interface.cpp | 2 + llarp/apple/vpn_interface.hpp | 3 +- llarp/apple/vpn_platform.cpp | 1 + llarp/apple/vpn_platform.hpp | 5 +- llarp/bootstrap-fallbacks.cpp.in | 2 +- llarp/bootstrap.hpp | 7 +- llarp/bootstrap_fallbacks.cpp | 3 +- llarp/config/config.cpp | 11 +- llarp/config/config.hpp | 29 +- llarp/config/definition.cpp | 3 +- llarp/config/definition.hpp | 14 +- llarp/config/ini.cpp | 2 +- llarp/config/ini.hpp | 5 +- llarp/config/key_manager.cpp | 6 +- llarp/config/key_manager.hpp | 5 +- llarp/consensus/reachability_testing.cpp | 2 +- llarp/consensus/reachability_testing.hpp | 3 +- llarp/constants/evloop.hpp | 7 - llarp/constants/files.hpp | 2 +- llarp/constants/link_layer.hpp | 2 +- llarp/constants/path.hpp | 6 +- llarp/constants/version.hpp | 2 +- llarp/context.cpp | 10 +- llarp/crypto/constants.hpp | 4 +- llarp/crypto/crypto.cpp | 11 +- llarp/crypto/crypto.hpp | 10 +- llarp/crypto/encrypted.hpp | 2 +- llarp/crypto/encrypted_frame.cpp | 4 +- llarp/crypto/encrypted_frame.hpp | 7 +- llarp/crypto/types.cpp | 3 + llarp/crypto/types.hpp | 7 +- llarp/dht/bucket.hpp | 1 + llarp/dht/context.cpp | 662 ----------------------- llarp/dht/dht.cpp | 52 -- llarp/dht/dht.h | 61 --- llarp/dht/kademlia.hpp | 1 + llarp/dht/key.hpp | 2 +- llarp/dht/node.hpp | 2 + llarp/dht/tx.hpp | 79 --- llarp/dht/txholder.hpp | 212 -------- llarp/dht/txowner.hpp | 61 --- llarp/dns/message.cpp | 12 +- llarp/dns/message.hpp | 4 +- llarp/dns/name.cpp | 3 +- llarp/dns/name.hpp | 3 +- llarp/dns/nm_platform.hpp | 1 + llarp/dns/platform.hpp | 3 +- llarp/dns/question.cpp | 4 +- llarp/dns/question.hpp | 2 +- llarp/dns/rr.hpp | 7 +- llarp/dns/sd_platform.hpp | 1 + llarp/dns/serialize.hpp | 1 + llarp/dns/server.cpp | 19 +- llarp/dns/server.hpp | 9 +- llarp/dns/srv_data.cpp | 6 +- llarp/dns/srv_data.hpp | 9 +- llarp/endpoint_base.cpp | 2 +- llarp/endpoint_base.hpp | 28 +- llarp/ev/ev.cpp | 5 +- llarp/ev/ev.hpp | 12 +- llarp/ev/libuv.cpp | 6 +- llarp/ev/libuv.hpp | 15 +- llarp/ev/udp_handle.hpp | 2 +- llarp/exit/context.cpp | 1 + llarp/exit/context.hpp | 5 +- llarp/exit/endpoint.hpp | 1 + llarp/exit/policy.hpp | 3 +- llarp/exit/session.cpp | 3 +- llarp/exit/session.hpp | 5 +- llarp/handlers/exit.cpp | 3 +- llarp/handlers/exit.hpp | 7 +- llarp/handlers/null.hpp | 4 +- llarp/handlers/tun.cpp | 14 +- llarp/handlers/tun.hpp | 1 + llarp/link/connection.hpp | 3 +- llarp/link/link_manager.cpp | 5 +- llarp/link/link_manager.hpp | 16 +- llarp/link/tunnel.cpp | 6 +- llarp/link/tunnel.hpp | 4 +- llarp/linux/sd_service_manager.cpp | 7 +- llarp/lokinet_shared.cpp | 12 +- llarp/messages/link_message.hpp | 8 +- llarp/messages/relay.hpp | 9 +- llarp/net/exit_info.cpp | 5 +- llarp/net/exit_info.hpp | 5 +- llarp/net/interface_info.hpp | 5 +- llarp/net/ip.cpp | 1 + llarp/net/ip_address.cpp | 1 + llarp/net/ip_address.hpp | 9 +- llarp/net/ip_packet.cpp | 5 +- llarp/net/ip_packet.hpp | 12 +- llarp/net/ip_range.cpp | 4 +- llarp/net/ip_range.hpp | 12 +- llarp/net/ip_range_map.hpp | 2 + llarp/net/net.h | 1 + llarp/net/net.hpp | 19 +- llarp/net/net_int.cpp | 6 +- llarp/net/net_int.hpp | 13 +- llarp/net/posix.cpp | 6 +- llarp/net/sock_addr.cpp | 13 +- llarp/net/sock_addr.hpp | 13 +- llarp/net/traffic_policy.hpp | 10 +- llarp/net/uint128.hpp | 6 +- llarp/net/win32.cpp | 11 +- llarp/nodedb.cpp | 10 +- llarp/nodedb.hpp | 25 +- llarp/path/abstracthophandler.cpp | 1 + llarp/path/abstracthophandler.hpp | 9 +- llarp/path/path.hpp | 9 +- llarp/path/path_context.cpp | 3 +- llarp/path/path_context.hpp | 12 +- llarp/path/path_types.hpp | 2 +- llarp/path/pathbuilder.cpp | 8 +- llarp/path/pathbuilder.hpp | 3 +- llarp/path/pathset.cpp | 3 +- llarp/path/pathset.hpp | 7 +- llarp/path/transit_hop.cpp | 4 +- llarp/pow.cpp | 4 +- llarp/profiling.cpp | 4 +- llarp/profiling.hpp | 6 +- llarp/router/rc_gossiper.hpp | 2 +- llarp/router/rc_lookup_handler.cpp | 16 +- llarp/router/rc_lookup_handler.hpp | 5 +- llarp/router/route_poker.cpp | 4 +- llarp/router/route_poker.hpp | 8 +- llarp/router/router.cpp | 8 +- llarp/router/router.hpp | 16 +- llarp/router_contact.cpp | 6 +- llarp/router_contact.hpp | 24 +- llarp/router_id.cpp | 1 + llarp/router_version.hpp | 8 +- llarp/rpc/endpoint_rpc.hpp | 1 + llarp/rpc/json_binary_proxy.cpp | 3 +- llarp/rpc/json_binary_proxy.hpp | 3 +- llarp/rpc/json_conversions.cpp | 1 + llarp/rpc/json_conversions.hpp | 5 +- llarp/rpc/lokid_rpc_client.cpp | 4 +- llarp/rpc/lokid_rpc_client.hpp | 7 +- llarp/rpc/param_parser.hpp | 6 +- llarp/rpc/rpc_request.hpp | 15 +- llarp/rpc/rpc_request_decorators.hpp | 11 +- llarp/rpc/rpc_request_definitions.hpp | 9 +- llarp/rpc/rpc_request_parser.cpp | 5 +- llarp/rpc/rpc_request_parser.hpp | 10 +- llarp/rpc/rpc_server.cpp | 3 +- llarp/rpc/rpc_server.hpp | 13 +- llarp/service/address.cpp | 3 + llarp/service/address.hpp | 2 +- llarp/service/async_key_exchange.cpp | 2 + llarp/service/async_key_exchange.hpp | 4 +- llarp/service/auth.cpp | 3 +- llarp/service/auth.hpp | 7 +- llarp/service/context.cpp | 5 +- llarp/service/context.hpp | 7 +- llarp/service/convotag.hpp | 4 +- llarp/service/endpoint.cpp | 21 +- llarp/service/endpoint.hpp | 14 +- llarp/service/endpoint_state.hpp | 16 +- llarp/service/endpoint_types.hpp | 1 + llarp/service/identity.hpp | 9 +- llarp/service/info.cpp | 4 +- llarp/service/info.hpp | 10 +- llarp/service/intro.cpp | 1 + llarp/service/intro.hpp | 4 +- llarp/service/intro_set.cpp | 1 + llarp/service/intro_set.hpp | 21 +- llarp/service/lns_tracker.hpp | 8 +- llarp/service/name.cpp | 1 + llarp/service/name.hpp | 4 +- llarp/service/outbound_context.cpp | 9 +- llarp/service/outbound_context.hpp | 1 + llarp/service/pendingbuffer.hpp | 2 + llarp/service/protocol.cpp | 7 +- llarp/service/protocol.hpp | 14 +- llarp/service/protocol_type.hpp | 4 +- llarp/service/router_lookup_job.cpp | 1 + llarp/service/session.hpp | 6 +- llarp/service/tag.hpp | 1 + llarp/simulation/sim_context.cpp | 1 + llarp/util/aligned.hpp | 5 +- llarp/util/bencode.cpp | 2 +- llarp/util/bencode.h | 9 +- llarp/util/bencode.hpp | 14 +- llarp/util/bits.hpp | 7 +- llarp/util/buffer.cpp | 1 + llarp/util/buffer.hpp | 18 +- llarp/util/decaying_hashset.hpp | 1 + llarp/util/decaying_hashtable.hpp | 1 + llarp/util/file.cpp | 2 + llarp/util/file.hpp | 4 +- llarp/util/formattable.hpp | 1 + llarp/util/logging.hpp | 9 +- llarp/util/logging/buffer.hpp | 5 +- llarp/util/logging/callback_sink.hpp | 3 +- llarp/util/mem.cpp | 1 + llarp/util/meta/memfn.hpp | 2 +- llarp/util/str.cpp | 5 +- llarp/util/str.hpp | 7 +- llarp/util/thread/barrier.hpp | 2 +- llarp/util/thread/queue.hpp | 2 +- llarp/util/thread/queue_manager.hpp | 2 +- llarp/util/thread/threading.cpp | 1 + llarp/util/thread/threading.hpp | 11 +- llarp/util/time.hpp | 9 +- llarp/util/types.hpp | 6 +- llarp/vpn/android.hpp | 9 +- llarp/vpn/common.hpp | 7 +- llarp/vpn/egres_packet_router.hpp | 5 +- llarp/vpn/i_packet_io.hpp | 3 +- llarp/vpn/linux.hpp | 29 +- llarp/vpn/packet_intercept.hpp | 3 +- llarp/vpn/packet_router.hpp | 3 +- llarp/vpn/platform.hpp | 10 +- llarp/vpn/win32.cpp | 2 + llarp/vpn/win32.hpp | 10 +- llarp/win32/dll.cpp | 1 + llarp/win32/dll.hpp | 4 +- llarp/win32/exception.cpp | 5 +- llarp/win32/exception.hpp | 3 +- llarp/win32/exec.cpp | 2 + llarp/win32/exec.hpp | 4 +- llarp/win32/guid.hpp | 2 + llarp/win32/service_manager.cpp | 9 +- llarp/win32/service_manager.hpp | 3 +- llarp/win32/win32_inet.c | 5 +- llarp/win32/windivert.cpp | 11 +- llarp/win32/windivert.hpp | 6 +- llarp/win32/wintun.cpp | 15 +- pybind/common.hpp | 6 +- pybind/llarp/config.cpp | 2 +- pybind/llarp/context.cpp | 7 +- pybind/llarp/crypto/types.cpp | 1 + pybind/llarp/handlers/pyhandler.hpp | 5 +- pybind/llarp/logger.cpp | 4 +- pybind/llarp/path/path_hop_config.cpp | 1 + pybind/llarp/peerstats.cpp | 2 +- pybind/llarp/router.cpp | 4 +- pybind/llarp/router_contact.cpp | 4 +- pybind/llarp/router_id.cpp | 4 +- pybind/llarp/service/address.cpp | 3 +- pybind/llarp/tooling/router_event.cpp | 13 +- pybind/llarp/tooling/router_hive.cpp | 10 +- pybind/module.cpp | 1 + 265 files changed, 971 insertions(+), 1894 deletions(-) delete mode 100644 llarp/constants/evloop.hpp delete mode 100644 llarp/dht/context.cpp delete mode 100644 llarp/dht/dht.cpp delete mode 100644 llarp/dht/dht.h delete mode 100644 llarp/dht/tx.hpp delete mode 100644 llarp/dht/txholder.hpp delete mode 100644 llarp/dht/txowner.hpp diff --git a/.clang-format b/.clang-format index 3f18c42194..ef24da8a0a 100644 --- a/.clang-format +++ b/.clang-format @@ -33,10 +33,12 @@ BraceWrapping: SplitEmptyNamespace: false BreakBeforeTernaryOperators: 'true' BreakConstructorInitializersBeforeComma: 'true' +ColumnLimit: 100 Cpp11BracedListStyle: 'true' KeepEmptyLinesAtTheStartOfBlocks: 'false' NamespaceIndentation: All PenaltyBreakString: '3' +SortIncludes: CaseInsensitive SpaceBeforeParens: ControlStatements SpacesInAngles: 'false' SpacesInContainerLiterals: 'false' @@ -44,8 +46,6 @@ SpacesInParentheses: 'false' SpacesInSquareBrackets: 'false' Standard: Cpp11 UseTab: Never -SortIncludes: false -ColumnLimit: 100 # treat pointers and reference declarations as if part of the type DerivePointerAlignment: false @@ -55,7 +55,21 @@ PointerAlignment: Left BinPackParameters: 'false' BinPackArguments: 'false' -# TODO: uncomment me when we are reading to rearrange the header includes -# IncludeBlocks: Regroup -# IncludeCategories: 'llarp/' - +# Include block sorting in the following order: +# - Main header for source file (clang-format default prioritizes this first) +# - Relative path includes in quotation marks +# - Absolute path includes in angle brackets +# - External dependencies +# - System dependencies +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '".+\.h' + Priority: 2 + - Regex: '^' + Priority: 4 + - Regex: '^<.*\.h(pp)?>$' + Priority: 5 + - Regex: '(<)(.)+(>)' + Priority: 6 diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e68a24268..9f50d4b313 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -262,7 +262,7 @@ add_subdirectory(external) # interface library for setting common includes, linkage and flags add_library(lokinet-base INTERFACE) target_include_directories(lokinet-base INTERFACE . include) -target_link_libraries(lokinet-base INTERFACE quic) +target_link_libraries(lokinet-base INTERFACE quic nlohmann_json::nlohmann_json) if(WITH_SYSTEMD AND (NOT ANDROID)) if(NOT SD_FOUND) diff --git a/cmake/CMakeGraphVizOptions.cmake b/cmake/CMakeGraphVizOptions.cmake index 4d97401719..322db57e3f 100644 --- a/cmake/CMakeGraphVizOptions.cmake +++ b/cmake/CMakeGraphVizOptions.cmake @@ -1,6 +1,4 @@ set(GRAPHVIZ_GRAPH_NAME "graph.dot" CACHE STRING "") -# set(GRAPHVIZ_MODULE_LIBS OFF CACHE BOOL "") -# set(GRAPHVIZ_EXTERNAL_LIBS OFF CACHE BOOL "") set(GRAPHVIZ_GENERATE_PER_TARGET FALSE CACHE BOOL "") set(GRAPHVIZ_GENERATE_DEPENDERS FALSE CACHE BOOL "") set(GRAPHVIZ_OBJECT_LIBS OFF CACHE BOOL "") diff --git a/crypto/libntrup/src/ntru.cpp b/crypto/libntrup/src/ntru.cpp index c3fab075f7..44b95cd4ec 100644 --- a/crypto/libntrup/src/ntru.cpp +++ b/crypto/libntrup/src/ntru.cpp @@ -1,6 +1,5 @@ #include - -#include "libntrup/ntru_api.h" +#include #ifdef __x86_64__ #include diff --git a/daemon/lokinet-bootstrap.cpp b/daemon/lokinet-bootstrap.cpp index 435934cdd0..e1ad9cb4dd 100644 --- a/daemon/lokinet-bootstrap.cpp +++ b/daemon/lokinet-bootstrap.cpp @@ -1,9 +1,9 @@ -#include - #include #include #include +#include + #include #include #include @@ -93,9 +93,9 @@ main(int argc, char* argv[]) { return fail("failed to fetch '" + bootstrap_url + "' HTTP " + std::to_string(resp.status_code)); } - std::stringstream ss; - ss << resp.text; - std::string data{ss.str()}; + + const auto& data = resp.text; + if (data[0] == 'l' or data[0] == 'd') { try diff --git a/daemon/lokinet-vpn.cpp b/daemon/lokinet-vpn.cpp index aae574cbab..2444ab5363 100644 --- a/daemon/lokinet-vpn.cpp +++ b/daemon/lokinet-vpn.cpp @@ -1,18 +1,19 @@ -#include -#include -#include - -#include #include +#include #include #include +#include +#include +#include + #ifdef _WIN32 // add the unholy windows headers for iphlpapi #include -#include + #include #include +#include #else #endif diff --git a/daemon/lokinet.cpp b/daemon/lokinet.cpp index b57e284494..b3cb416c80 100644 --- a/daemon/lokinet.cpp +++ b/daemon/lokinet.cpp @@ -1,49 +1,35 @@ +#include #include // for ensure_config +#include +#include #include -#include -#include +#include #include -#include - -#ifdef _WIN32 -#include -#include -#else -#include -#endif +#include +#include +#include #include +#include +#include #include -#include -#include -#include -#include #include -#include -#include -#include +#include #include #include #include +#include +#include #include -#include "CLI/Error.hpp" -#include "CLI/Option.hpp" -#include "CLI/impl/App_inl.hpp" -#include "CLI/impl/Option_inl.hpp" -#include "fmt/core.h" -#include "llarp/constants/files.hpp" -#include "llarp/constants/platform.hpp" -#include "llarp/ev/ev.hpp" -#include "llarp/util/logging.hpp" -#include "llarp/util/thread/threading.hpp" -#include "oxen/log.hpp" -#include "oxen/log/catlogger.hpp" -#include "oxen/log/level.hpp" -#include "oxen/log/ring_buffer_sink.hpp" -#include "oxen/log/type.hpp" -#include "spdlog/common.h" +#ifdef _WIN32 +#include + +#include +#else +#include +#endif namespace { @@ -290,9 +276,8 @@ namespace const auto flags = (MINIDUMP_TYPE)(MiniDumpWithFullMemory | MiniDumpWithFullMemoryInfo | MiniDumpWithHandleData | MiniDumpWithUnloadedModules | MiniDumpWithThreadInfo); - std::stringstream ss; - ss << "C:\\ProgramData\\lokinet\\crash-" << llarp::time_now_ms().count() << ".dmp"; - const std::string fname = ss.str(); + const std::string fname = + "C:\\ProgramData\\lokinet\\crash-{}.dump"_format(llarp::time_now_ms().count()); HANDLE hDumpFile; SYSTEMTIME stLocalTime; GetLocalTime(&stLocalTime); @@ -525,30 +510,8 @@ namespace if (ctx and ctx->IsUp() and not ctx->LooksAlive()) { auto deadlock_cat = llarp::log::Cat("deadlock"); - for (const auto& wtf : - {"you have been visited by the mascot of the deadlocked router.", - "⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⣀⣴⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄⠄⠄⠄⠄", - "⠄⠄⠄⠄⠄⢀⣀⣀⡀⠄⠄⠄⡠⢲⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡀⠄⠄", - "⠄⠄⠄⠔⣈⣀⠄⢔⡒⠳⡴⠊⠄⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠿⣿⣿⣧⠄⠄", - "⠄⢜⡴⢑⠖⠊⢐⣤⠞⣩⡇⠄⠄⠄⠙⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣆⠄⠝⠛⠋⠐", - "⢸⠏⣷⠈⠄⣱⠃⠄⢠⠃⠐⡀⠄⠄⠄⠄⠙⠻⢿⣿⣿⣿⣿⣿⣿⣿⡿⠛⠸⠄⠄⠄⠄", - "⠈⣅⠞⢁⣿⢸⠘⡄⡆⠄⠄⠈⠢⡀⠄⠄⠄⠄⠄⠄⠉⠙⠛⠛⠛⠉⠉⡀⠄⠡⢀⠄⣀", - "⠄⠙⡎⣹⢸⠄⠆⢘⠁⠄⠄⠄⢸⠈⠢⢄⡀⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠃⠄⠄⠄⠄⠄", - "⠄⠄⠑⢿⠈⢆⠘⢼⠄⠄⠄⠄⠸⢐⢾⠄⡘⡏⠲⠆⠠⣤⢤⢤⡤⠄⣖⡇⠄⠄⠄⠄⠄", - "⣴⣶⣿⣿⣣⣈⣢⣸⠄⠄⠄⠄⡾⣷⣾⣮⣤⡏⠁⠘⠊⢠⣷⣾⡛⡟⠈⠄⠄⠄⠄⠄⠄", - "⣿⣿⣿⣿⣿⠉⠒⢽⠄⠄⠄⠄⡇⣿⣟⣿⡇⠄⠄⠄⠄⢸⣻⡿⡇⡇⠄⠄⠄⠄⠄⠄⠄", - "⠻⣿⣿⣿⣿⣄⠰⢼⠄⠄⠄⡄⠁⢻⣍⣯⠃⠄⠄⠄⠄⠈⢿⣻⠃⠈⡆⡄⠄⠄⠄⠄⠄", - "⠄⠙⠿⠿⠛⣿⣶⣤⡇⠄⠄⢣⠄⠄⠈⠄⢠⠂⠄⠁⠄⡀⠄⠄⣀⠔⢁⠃⠄⠄⠄⠄⠄", - "⠄⠄⠄⠄⠄⣿⣿⣿⣿⣾⠢⣖⣶⣦⣤⣤⣬⣤⣤⣤⣴⣶⣶⡏⠠⢃⠌⠄⠄⠄⠄⠄⠄", - "⠄⠄⠄⠄⠄⠿⠿⠟⠛⡹⠉⠛⠛⠿⠿⣿⣿⣿⣿⣿⡿⠂⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄", - "⠠⠤⠤⠄⠄⣀⠄⠄⠄⠑⠠⣤⣀⣀⣀⡘⣿⠿⠙⠻⡍⢀⡈⠂⠄⠄⠄⠄⠄⠄⠄⠄⠄", - "⠄⠄⠄⠄⠄⠄⠑⠠⣠⣴⣾⣿⣿⣿⣿⣿⣿⣇⠉⠄⠻⣿⣷⣄⡀⠄⠄⠄⠄⠄⠄⠄⠄", - "file a bug report now or be cursed with this " - "annoying image in your syslog for all time."}) - { - llarp::log::critical(deadlock_cat, wtf); - llarp::log::flush(); - } + llarp::log::critical(deadlock_cat, "Router is deadlocked!"); + llarp::log::flush(); llarp::sys::service_manager->failed(); std::abort(); } @@ -669,6 +632,17 @@ main(int argc, char* argv[]) #ifndef _WIN32 return lokinet_main(argc, argv); #else + if (auto hntdll = GetModuleHandle("ntdll.dll")) + { + if (GetProcAddress(hntdll, "wine_get_version")) + { + static const char* text = "Don't run lokinet in wine, aborting startup"; + static const char* title = "Lokinet Wine Error"; + MessageBoxA(NULL, text, title, MB_ICONHAND); + abort(); + } + } + SERVICE_TABLE_ENTRY DispatchTable[] = { {strdup("lokinet"), (LPSERVICE_MAIN_FUNCTION)win32_daemon_entry}, {NULL, NULL}}; diff --git a/include/lokinet.h b/include/lokinet.h index 4cda5b53f9..26b57a9ff8 100644 --- a/include/lokinet.h +++ b/include/lokinet.h @@ -1,8 +1,8 @@ #pragma once +#include "lokinet/lokinet_addr.h" #include "lokinet/lokinet_context.h" -#include "lokinet/lokinet_srv.h" #include "lokinet/lokinet_misc.h" -#include "lokinet/lokinet_addr.h" +#include "lokinet/lokinet_srv.h" #include "lokinet/lokinet_stream.h" #include "lokinet/lokinet_udp.h" diff --git a/jni/lokinet_config.cpp b/jni/lokinet_config.cpp index 5313743c3f..09489f1a58 100644 --- a/jni/lokinet_config.cpp +++ b/jni/lokinet_config.cpp @@ -1,7 +1,8 @@ +#include "lokinet_jni_common.hpp" #include "network_loki_lokinet_LokinetConfig.h" + #include #include -#include "lokinet_jni_common.hpp" extern "C" { diff --git a/jni/lokinet_daemon.cpp b/jni/lokinet_daemon.cpp index 98b6e8b5a2..92e13d8324 100644 --- a/jni/lokinet_daemon.cpp +++ b/jni/lokinet_daemon.cpp @@ -1,5 +1,6 @@ -#include "network_loki_lokinet_LokinetDaemon.h" #include "lokinet_jni_common.hpp" +#include "network_loki_lokinet_LokinetDaemon.h" + #include #include #include diff --git a/jni/lokinet_jni_common.hpp b/jni/lokinet_jni_common.hpp index 8eb77069c3..0a8452de82 100644 --- a/jni/lokinet_jni_common.hpp +++ b/jni/lokinet_jni_common.hpp @@ -1,8 +1,9 @@ #pragma once #include -#include + #include +#include /// visit string as native bytes /// jvm uses some unholy encoding internally so we convert it to utf-8 diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index a3c698a2f1..831836ce9f 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -1,6 +1,5 @@ include(Version) - # Add an internal lokinet static library target, enables LTO (if enabled) on the target, # and links it to the common lokinet-base interface. # Invoke with the target/library name (e.g. "lokinet-foo") and list of source files, e.g. @@ -11,7 +10,6 @@ function(lokinet_add_library libname) enable_lto(${libname}) endfunction() - lokinet_add_library(lokinet-cryptography crypto/crypto.cpp crypto/encrypted_frame.cpp @@ -57,12 +55,12 @@ lokinet_add_library(lokinet-core ) lokinet_add_library(lokinet-rpc + rpc/endpoint_rpc.cpp rpc/json_binary_proxy.cpp rpc/json_conversions.cpp rpc/lokid_rpc_client.cpp rpc/rpc_request_parser.cpp rpc/rpc_server.cpp - rpc/endpoint_rpc.cpp ) lokinet_add_library(lokinet-wire @@ -78,12 +76,12 @@ lokinet_add_library(lokinet-utils util/bencode.cpp util/buffer.cpp util/file.cpp + util/logging/buffer.cpp util/mem.cpp util/str.cpp util/thread/threading.cpp util/thread/queue_manager.cpp util/time.cpp - util/logging/buffer.cpp ) add_dependencies(lokinet-utils genversion) @@ -91,10 +89,6 @@ add_dependencies(lokinet-utils genversion) # Addressing and event loop files used by lokinet-core and other libraries # needed by rpc/ link/ service/ config/ path/ dht/ lokinet_add_library(lokinet-time-place - pow.cpp # only intro_set - router_contact.cpp - router_id.cpp - router_version.cpp # to be deleted shortly ev/ev.cpp ev/libuv.cpp net/exit_info.cpp # only router_contact @@ -104,6 +98,10 @@ lokinet_add_library(lokinet-time-place net/ip_range.cpp net/net_int.cpp net/sock_addr.cpp + pow.cpp # only intro_set + router_contact.cpp + router_id.cpp + router_version.cpp # to be deleted shortly service/address.cpp service/convotag.cpp service/intro_set.cpp @@ -111,8 +109,8 @@ lokinet_add_library(lokinet-time-place # lokinet-platform holds all platform specific code lokinet_add_library(lokinet-platform - router/rc_lookup_handler.cpp net/interface_info.cpp + router/rc_lookup_handler.cpp vpn/packet_router.cpp vpn/platform.cpp ) @@ -153,18 +151,13 @@ endif() # lokinet-dns is the dns parsing and hooking library that we use to # parse modify and reconstitute dns wire proto, dns queries and RR -# should have no concept of dns caching, this is left as an implementation -# detail of dns resolvers (LATER: make separate lib for dns resolvers) -add_library(lokinet-dns-internal +lokinet_add_library(lokinet-dns + dns/message.cpp # dns/server dns/name.cpp # srv_data, question, rr dns/platform.cpp dns/question.cpp # message dns/rr.cpp dns/serialize.cpp -) - -lokinet_add_library(lokinet-dns - dns/message.cpp # dns/server dns/server.cpp # handlers/exit+tun and service/endpoint dns/srv_data.cpp ) @@ -180,9 +173,9 @@ endif() # nodedb data published to the network and versions of it stored locally lokinet_add_library(lokinet-nodedb bootstrap.cpp # config, router.hpp + net/traffic_policy.cpp # config, intro_set nodedb.cpp profiling.cpp # path, router, service::endpoint - net/traffic_policy.cpp # config, intro_set ) set(BOOTSTRAP_FALLBACKS) @@ -214,21 +207,19 @@ lokinet_add_library(lokinet-config # All path objects; link directly to lokinet-core lokinet_add_library(lokinet-path + messages/relay.cpp path/abstracthophandler.cpp - path/path_context.cpp path/path.cpp + path/path_context.cpp path/pathbuilder.cpp path/pathset.cpp path/transit_hop.cpp - messages/relay.cpp ) # Link libraries to their internals target_link_libraries(lokinet-core-utils PUBLIC lokinet-dns) target_link_libraries(lokinet-core PUBLIC lokinet-core-utils) -target_link_libraries(lokinet-dns PRIVATE lokinet-dns-internal) - # Link lokinet-dns to alternate libraries target_link_libraries(lokinet-dns PUBLIC lokinet-dns-platform) if (TARGET lokinet-dns-systemd) @@ -236,9 +227,8 @@ if (TARGET lokinet-dns-systemd) endif() target_link_libraries(lokinet-wire PUBLIC lokinet-time-place) -target_link_libraries(lokinet-dns-internal PUBLIC lokinet-utils) -target_link_libraries(lokinet-dns PUBLIC lokinet-cryptography lokinet-config) -target_link_libraries(lokinet-nodedb PUBLIC lokinet-cryptography) +target_link_libraries(lokinet-dns PUBLIC lokinet-utils lokinet-cryptography lokinet-config) +target_link_libraries(lokinet-nodedb PUBLIC lokinet-time-place lokinet-cryptography) target_link_libraries(lokinet-platform PUBLIC lokinet-cryptography) target_link_libraries(lokinet-rpc PUBLIC lokinet-wire) target_link_libraries(lokinet-time-place PUBLIC lokinet-utils lokinet-cryptography) @@ -277,11 +267,11 @@ target_link_libraries(lokinet-utils # cross linkage target_link_libraries(lokinet-core PUBLIC - lokinet-rpc - lokinet-wire + lokinet-cryptography lokinet-nodedb lokinet-path - lokinet-cryptography + lokinet-rpc + lokinet-wire ) target_link_libraries(lokinet-base INTERFACE oxenc::oxenc oxen::logging) @@ -292,7 +282,6 @@ target_link_libraries(lokinet-config PUBLIC oxenmq::oxenmq) target_link_libraries(lokinet-nodedb PUBLIC oxenmq::oxenmq) target_link_libraries(lokinet-path PUBLIC oxenmq::oxenmq) target_link_libraries(lokinet-time-place PUBLIC uvw) -# target_link_libraries(lokinet-platform PUBLIC oxenmq::oxenmq Threads::Threads base_libs uvw) target_link_libraries(lokinet-platform PUBLIC oxenmq::oxenmq Threads::Threads uvw) target_link_libraries(lokinet-cryptography PUBLIC sodium) target_link_libraries(lokinet-dns PUBLIC libunbound) diff --git a/llarp/android/ifaddrs.c b/llarp/android/ifaddrs.c index 8702feca83..af0a439e29 100644 --- a/llarp/android/ifaddrs.c +++ b/llarp/android/ifaddrs.c @@ -24,17 +24,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "ifaddrs.h" -#include -#include -#include #include -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include typedef struct NetlinkList { diff --git a/llarp/android/ifaddrs.h b/llarp/android/ifaddrs.h index 73d3d2877e..03a9fbe93e 100644 --- a/llarp/android/ifaddrs.h +++ b/llarp/android/ifaddrs.h @@ -23,8 +23,7 @@ * BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp */ -#ifndef _IFADDRS_H_ -#define _IFADDRS_H_ +#pragma once struct ifaddrs { @@ -53,5 +52,3 @@ getifaddrs(struct ifaddrs** ifap); extern void freeifaddrs(struct ifaddrs* ifa); __END_DECLS - -#endif diff --git a/llarp/apple/DNSTrampoline.h b/llarp/apple/DNSTrampoline.h index 117d567b21..e691caf750 100644 --- a/llarp/apple/DNSTrampoline.h +++ b/llarp/apple/DNSTrampoline.h @@ -1,6 +1,6 @@ #pragma once -#include #include +#include extern NSString* error_domain; diff --git a/llarp/apple/DNSTrampoline.m b/llarp/apple/DNSTrampoline.m index 9ef950c4e0..8ccbb1d2e3 100644 --- a/llarp/apple/DNSTrampoline.m +++ b/llarp/apple/DNSTrampoline.m @@ -1,4 +1,5 @@ #include "DNSTrampoline.h" + #include NSString* error_domain = @"org.lokinet"; diff --git a/llarp/apple/PacketTunnelProvider.m b/llarp/apple/PacketTunnelProvider.m index dfcf203117..1981b0b81c 100644 --- a/llarp/apple/PacketTunnelProvider.m +++ b/llarp/apple/PacketTunnelProvider.m @@ -1,8 +1,9 @@ -#include -#include #include "context_wrapper.h" #include "DNSTrampoline.h" +#include +#include + #define LLARP_APPLE_PACKET_BUF_SIZE 64 @interface LLARPPacketTunnel : NEPacketTunnelProvider diff --git a/llarp/apple/context.hpp b/llarp/apple/context.hpp index 4fc808874b..cc7db2996b 100644 --- a/llarp/apple/context.hpp +++ b/llarp/apple/context.hpp @@ -1,8 +1,9 @@ #pragma once -#include -#include "vpn_platform.hpp" #include "route_manager.hpp" +#include "vpn_platform.hpp" + +#include namespace llarp::apple { diff --git a/llarp/apple/context_wrapper.cpp b/llarp/apple/context_wrapper.cpp index e30c6c5d62..2cb727f601 100644 --- a/llarp/apple/context_wrapper.cpp +++ b/llarp/apple/context_wrapper.cpp @@ -1,17 +1,22 @@ -#include -#include -#include -#include +#include "context_wrapper.h" + +#include "context.hpp" +#include "vpn_interface.hpp" + #include #include +#include +#include #include -#include #include #include #include -#include "vpn_interface.hpp" -#include "context_wrapper.h" -#include "context.hpp" + +// #include + +#include +#include +#include namespace { diff --git a/llarp/apple/context_wrapper.h b/llarp/apple/context_wrapper.h index 1f09a46d35..a64df18c0a 100644 --- a/llarp/apple/context_wrapper.h +++ b/llarp/apple/context_wrapper.h @@ -8,8 +8,8 @@ extern "C" { #endif -#include #include +#include #include // Port (on localhost) for our DNS trampoline for bouncing DNS requests through the exit route diff --git a/llarp/apple/route_manager.cpp b/llarp/apple/route_manager.cpp index 5cfc2c0a4e..b1ac9bce29 100644 --- a/llarp/apple/route_manager.cpp +++ b/llarp/apple/route_manager.cpp @@ -1,7 +1,9 @@ #include "route_manager.hpp" + +#include #include #include -#include + #include namespace llarp::apple diff --git a/llarp/apple/route_manager.hpp b/llarp/apple/route_manager.hpp index e247b47554..cd3e418a13 100644 --- a/llarp/apple/route_manager.hpp +++ b/llarp/apple/route_manager.hpp @@ -1,8 +1,9 @@ #pragma once +#include "context_wrapper.h" + #include #include -#include "context_wrapper.h" namespace llarp::apple { diff --git a/llarp/apple/vpn_interface.cpp b/llarp/apple/vpn_interface.cpp index 3f128ad17b..03964d403a 100644 --- a/llarp/apple/vpn_interface.cpp +++ b/llarp/apple/vpn_interface.cpp @@ -1,6 +1,8 @@ #include "vpn_interface.hpp" + #include "context.hpp" + #include namespace llarp::apple diff --git a/llarp/apple/vpn_interface.hpp b/llarp/apple/vpn_interface.hpp index 787eb4ebbe..ee5dfc8dce 100644 --- a/llarp/apple/vpn_interface.hpp +++ b/llarp/apple/vpn_interface.hpp @@ -1,8 +1,9 @@ #pragma once #include -#include #include +#include + #include namespace llarp::apple diff --git a/llarp/apple/vpn_platform.cpp b/llarp/apple/vpn_platform.cpp index 1f94e6e6d0..7e05cbb050 100644 --- a/llarp/apple/vpn_platform.cpp +++ b/llarp/apple/vpn_platform.cpp @@ -1,4 +1,5 @@ #include "vpn_platform.hpp" + #include "context.hpp" namespace llarp::apple diff --git a/llarp/apple/vpn_platform.hpp b/llarp/apple/vpn_platform.hpp index 5cbe2858f3..1f5bb1ef65 100644 --- a/llarp/apple/vpn_platform.hpp +++ b/llarp/apple/vpn_platform.hpp @@ -1,8 +1,9 @@ #pragma once -#include -#include "vpn_interface.hpp" #include "route_manager.hpp" +#include "vpn_interface.hpp" + +#include namespace llarp::apple { diff --git a/llarp/bootstrap-fallbacks.cpp.in b/llarp/bootstrap-fallbacks.cpp.in index 5c81ea7166..baeb4be3a6 100644 --- a/llarp/bootstrap-fallbacks.cpp.in +++ b/llarp/bootstrap-fallbacks.cpp.in @@ -1,5 +1,5 @@ #include -#include "llarp/bootstrap.hpp" +#include namespace llarp { diff --git a/llarp/bootstrap.hpp b/llarp/bootstrap.hpp index 6c657a4b1a..e72e12fccf 100644 --- a/llarp/bootstrap.hpp +++ b/llarp/bootstrap.hpp @@ -1,11 +1,12 @@ #pragma once +#include "router_contact.hpp" + +#include + #include #include -#include "router_contact.hpp" -#include "llarp/util/fs.hpp" - namespace llarp { struct BootstrapList final : public std::set diff --git a/llarp/bootstrap_fallbacks.cpp b/llarp/bootstrap_fallbacks.cpp index 5be002098b..458444f639 100644 --- a/llarp/bootstrap_fallbacks.cpp +++ b/llarp/bootstrap_fallbacks.cpp @@ -1,5 +1,6 @@ +#include + #include -#include "llarp/bootstrap.hpp" namespace llarp { diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index 9df0d7c4cc..e28652d9db 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -1,19 +1,20 @@ #include "config.hpp" +#include "definition.hpp" +#include "ini.hpp" + #include #include #include -#include #include +#include #include +#include #include #include #include -#include -#include -#include "definition.hpp" -#include "ini.hpp" +#include namespace llarp { diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index ee357a3cf9..f91c131c2e 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -1,32 +1,33 @@ #pragma once -#include -#include +#include "definition.hpp" +#include "ini.hpp" + #include -#include -#include -#include -#include -#include #include +#include +#include #include -#include #include +#include +#include +#include +#include #include #include -#include -#include +#include +#include +#include + #include + #include #include #include #include #include +#include #include #include -#include - -#include "ini.hpp" -#include "definition.hpp" namespace llarp { diff --git a/llarp/config/definition.cpp b/llarp/config/definition.cpp index 76177603ce..b27e4b2e51 100644 --- a/llarp/config/definition.cpp +++ b/llarp/config/definition.cpp @@ -1,9 +1,10 @@ #include "definition.hpp" + #include +#include #include #include -#include namespace llarp { diff --git a/llarp/config/definition.hpp b/llarp/config/definition.hpp index c49b5161a8..2d0ed0818e 100644 --- a/llarp/config/definition.hpp +++ b/llarp/config/definition.hpp @@ -1,20 +1,22 @@ #pragma once -#include -#include #include +#include + +#include + +#include +#include #include -#include #include #include +#include #include #include #include +#include #include #include -#include -#include -#include namespace llarp { diff --git a/llarp/config/ini.cpp b/llarp/config/ini.cpp index b6fbb6166d..66b55dd4c5 100644 --- a/llarp/config/ini.cpp +++ b/llarp/config/ini.cpp @@ -1,7 +1,7 @@ #include "ini.hpp" -#include #include +#include #include #include diff --git a/llarp/config/ini.hpp b/llarp/config/ini.hpp index 3d72ee8cc6..bb22cda8c5 100644 --- a/llarp/config/ini.hpp +++ b/llarp/config/ini.hpp @@ -1,10 +1,11 @@ #pragma once #include -#include -#include + #include #include +#include +#include #include #include diff --git a/llarp/config/key_manager.cpp b/llarp/config/key_manager.cpp index 96b73fb794..3df6618473 100644 --- a/llarp/config/key_manager.cpp +++ b/llarp/config/key_manager.cpp @@ -1,10 +1,12 @@ #include "key_manager.hpp" -#include -#include #include "config.hpp" + #include #include +#include + +#include namespace llarp { diff --git a/llarp/config/key_manager.hpp b/llarp/config/key_manager.hpp index 060f13df92..20a45d0c9b 100644 --- a/llarp/config/key_manager.hpp +++ b/llarp/config/key_manager.hpp @@ -1,10 +1,11 @@ #pragma once +#include "config.hpp" + #include #include -#include -#include "config.hpp" +#include namespace llarp { diff --git a/llarp/consensus/reachability_testing.cpp b/llarp/consensus/reachability_testing.cpp index adaf82136d..a248f9cd7d 100644 --- a/llarp/consensus/reachability_testing.cpp +++ b/llarp/consensus/reachability_testing.cpp @@ -1,9 +1,9 @@ #include "reachability_testing.hpp" +#include #include #include -#include using std::chrono::steady_clock; diff --git a/llarp/consensus/reachability_testing.hpp b/llarp/consensus/reachability_testing.hpp index 8ac3636059..9ee79ef22d 100644 --- a/llarp/consensus/reachability_testing.hpp +++ b/llarp/consensus/reachability_testing.hpp @@ -1,7 +1,8 @@ #pragma once -#include #include +#include + #include #include #include diff --git a/llarp/constants/evloop.hpp b/llarp/constants/evloop.hpp deleted file mode 100644 index 4824f1b9c3..0000000000 --- a/llarp/constants/evloop.hpp +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -namespace llarp -{ - /// default queue length for logic jobs - constexpr std::size_t event_loop_queue_size = 1024; -} // namespace llarp diff --git a/llarp/constants/files.hpp b/llarp/constants/files.hpp index 6e0085121b..c6a3a4aa53 100644 --- a/llarp/constants/files.hpp +++ b/llarp/constants/files.hpp @@ -6,8 +6,8 @@ #include #ifndef _WIN32 -#include #include +#include #endif namespace llarp diff --git a/llarp/constants/link_layer.hpp b/llarp/constants/link_layer.hpp index 39eb384491..fabc0747ce 100644 --- a/llarp/constants/link_layer.hpp +++ b/llarp/constants/link_layer.hpp @@ -1,6 +1,6 @@ #pragma once -#include #include +#include #include diff --git a/llarp/constants/path.hpp b/llarp/constants/path.hpp index 9b066adb30..20851255f0 100644 --- a/llarp/constants/path.hpp +++ b/llarp/constants/path.hpp @@ -1,11 +1,11 @@ #pragma once +#include +#include + #include #include -#include -#include - namespace llarp::path { /// maximum path length diff --git a/llarp/constants/version.hpp b/llarp/constants/version.hpp index caa58b0af9..1bfd68d31a 100644 --- a/llarp/constants/version.hpp +++ b/llarp/constants/version.hpp @@ -1,7 +1,7 @@ #pragma once -#include #include +#include namespace llarp { diff --git a/llarp/context.cpp b/llarp/context.cpp index ec2377844d..be4f61d976 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -1,18 +1,18 @@ +#include "nodedb.hpp" + #include -#include -#include #include +#include #include #include #include #include #include -#include + #include +#include #include -#include "nodedb.hpp" - #if (__FreeBSD__) || (__OpenBSD__) || (__NetBSD__) #include #endif diff --git a/llarp/crypto/constants.hpp b/llarp/crypto/constants.hpp index 7f8eef90f3..32cb142e9c 100644 --- a/llarp/crypto/constants.hpp +++ b/llarp/crypto/constants.hpp @@ -1,9 +1,9 @@ #pragma once -#include - #include +#include + static constexpr uint32_t PUBKEYSIZE = 32; static constexpr uint32_t SECKEYSIZE = 64; static constexpr uint32_t NONCESIZE = 24; diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index 9ef4a3a420..81b9cd57df 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -1,15 +1,16 @@ #include "crypto.hpp" +#include #include +#include +#include #include -#include +#include #include +#include #include -#include -#include -#include #include -#include + #include #include #ifdef HAVE_CRYPT diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index 2aae6a7ec2..370b23e34a 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -1,18 +1,18 @@ #pragma once -#include -#include -#include - #include "constants.hpp" #include "types.hpp" +#include + +#include +#include + namespace llarp { /* TODO: - make uint8_t pointers const where needed - - */ namespace crypto diff --git a/llarp/crypto/encrypted.hpp b/llarp/crypto/encrypted.hpp index 0dbf772781..8522e2447c 100644 --- a/llarp/crypto/encrypted.hpp +++ b/llarp/crypto/encrypted.hpp @@ -6,8 +6,8 @@ #include #include -#include #include +#include namespace llarp { diff --git a/llarp/crypto/encrypted_frame.cpp b/llarp/crypto/encrypted_frame.cpp index 7171c5eb2a..64b0ccbd8b 100644 --- a/llarp/crypto/encrypted_frame.cpp +++ b/llarp/crypto/encrypted_frame.cpp @@ -1,9 +1,9 @@ #include "encrypted_frame.hpp" -#include - #include "crypto.hpp" +#include + namespace llarp { bool diff --git a/llarp/crypto/encrypted_frame.hpp b/llarp/crypto/encrypted_frame.hpp index 5c1c2ebea1..19a6ab1c2a 100644 --- a/llarp/crypto/encrypted_frame.hpp +++ b/llarp/crypto/encrypted_frame.hpp @@ -1,11 +1,12 @@ #pragma once +#include "encrypted.hpp" +#include "types.hpp" + #include #include -#include -#include "encrypted.hpp" -#include "types.hpp" +#include namespace llarp { diff --git a/llarp/crypto/types.cpp b/llarp/crypto/types.cpp index bf375eda73..30d4a3a9ad 100644 --- a/llarp/crypto/types.cpp +++ b/llarp/crypto/types.cpp @@ -2,7 +2,10 @@ #include #include + #include +#include +#include namespace llarp { diff --git a/llarp/crypto/types.hpp b/llarp/crypto/types.hpp index 92bdd64f90..e4188c35d4 100644 --- a/llarp/crypto/types.hpp +++ b/llarp/crypto/types.hpp @@ -1,16 +1,15 @@ #pragma once -#include +#include "constants.hpp" #include #include -#include #include +#include + #include #include -#include "constants.hpp" - namespace llarp { using SharedSecret = AlignedBuffer; diff --git a/llarp/dht/bucket.hpp b/llarp/dht/bucket.hpp index fd3e9ff35c..0f4c0fe09e 100644 --- a/llarp/dht/bucket.hpp +++ b/llarp/dht/bucket.hpp @@ -2,6 +2,7 @@ #include "kademlia.hpp" #include "key.hpp" + #include #include diff --git a/llarp/dht/context.cpp b/llarp/dht/context.cpp deleted file mode 100644 index bec9eda83e..0000000000 --- a/llarp/dht/context.cpp +++ /dev/null @@ -1,662 +0,0 @@ - -#include "explorenetworkjob.hpp" -#include "localrouterlookup.hpp" -#include "localserviceaddresslookup.hpp" -#include "localtaglookup.hpp" -#include "node.hpp" -#include "publishservicejob.hpp" -#include "recursiverouterlookup.hpp" -#include "serviceaddresslookup.hpp" -#include "taglookup.hpp" -#include -#include -#include -#include -#include -#include -#include - -namespace llarp::dht -{ - AbstractDHTMessageHandler::~AbstractDHTMessageHandler() = default; - - struct DHTMessageHandler final : public AbstractDHTMessageHandler - { - DHTMessageHandler(); - - ~DHTMessageHandler() override = default; - - util::StatusObject - ExtractStatus() const override; - - void - StoreRC(const RouterContact rc) const override - { - GetRouter()->rc_lookup_handler().check_rc(rc); - } - - // void - // LookupIntroSetRelayed( - // const Key_t& target, - // const Key_t& whoasked, - // uint64_t whoaskedTX, - // const Key_t& askpeer, - // uint64_t relayOrder, - // service::EncryptedIntroSetLookupHandler result = nullptr) override; - - // void - // LookupIntroSetDirect( - // const Key_t& target, - // const Key_t& whoasked, - // uint64_t whoaskedTX, - // const Key_t& askpeer, - // service::EncryptedIntroSetLookupHandler result = nullptr) override; - - /// on behalf of whoasked request router with public key target from dht - /// router with key askpeer - void - LookupRouterRecursive( - const RouterID& target, - const Key_t& whoasked, - uint64_t whoaskedTX, - const Key_t& askpeer, - RouterLookupHandler result = nullptr) override; - - bool - LookupRouter(const RouterID& target, RouterLookupHandler result) override - { - Key_t askpeer; - if (!_nodes->FindClosest(Key_t(target), askpeer)) - { - return false; - } - LookupRouterRecursive(target, OurKey(), 0, askpeer, result); - return true; - } - - bool - HasRouterLookup(const RouterID& target) const override - { - return pendingRouterLookups().HasLookupFor(target); - } - - /// issue dht lookup for router via askpeer and send reply to local path - void - LookupRouterForPath( - const RouterID& target, uint64_t txid, const PathID_t& path, const Key_t& askpeer) override; - - /// issue dht lookup for introset for addr via askpeer and send reply to - /// local path - void - LookupIntroSetForPath( - const Key_t& addr, - uint64_t txid, - const llarp::PathID_t& path, - const Key_t& askpeer, - uint64_t relayOrder) override; - - /// send a dht message to peer, if keepalive is true then keep the session - /// with that peer alive for 10 seconds - void - DHTSendTo(const RouterID& peer, AbstractDHTMessage* msg, bool keepalive = true) override; - - /// get routers closest to target excluding requester - bool - HandleExploritoryRouterLookup( - const Key_t& requester, - uint64_t txid, - const RouterID& target, - std::vector>& reply) override; - - /// handle rc lookup from requester for target - void - LookupRouterRelayed( - const Key_t& requester, - uint64_t txid, - const Key_t& target, - bool recursive, - std::vector>& replies) override; - - /// relay a dht message from a local path to the main network - bool - RelayRequestForPath(const llarp::PathID_t& localPath, const AbstractDHTMessage& msg) override; - - /// send introset to peer as R/S - void - PropagateLocalIntroSet( - const PathID_t& from, - uint64_t txid, - const service::EncryptedIntroSet& introset, - const Key_t& tellpeer, - uint64_t relayOrder) override; - - /// send introset to peer from source with S counter and excluding peers - void - PropagateIntroSetTo( - const Key_t& from, - uint64_t txid, - const service::EncryptedIntroSet& introset, - const Key_t& tellpeer, - uint64_t relayOrder) override; - - /// initialize dht context and explore every exploreInterval milliseconds - void - Init(const Key_t& us, Router* router) override; - - /// get localally stored introset by service address - std::optional - GetIntroSetByLocation(const Key_t& location) const override; - - void - handle_cleaner_timer(); - - /// explore dht for new routers - void - Explore(size_t N = 3); - - llarp::Router* router{nullptr}; - // for router contacts - std::unique_ptr> _nodes; - - // for introduction sets - std::unique_ptr> _services; - - Bucket* - services() override - { - return _services.get(); - } - - bool allowTransit{false}; - - bool& - AllowTransit() override - { - return allowTransit; - } - const bool& - AllowTransit() const override - { - return allowTransit; - } - - Bucket* - Nodes() const override - { - return _nodes.get(); - } - - void - PutRCNodeAsync(const RCNode& val) override - { - router->loop()->call([nodes = Nodes(), val] { nodes->PutNode(val); }); - } - - void - DelRCNodeAsync(const Key_t& val) override - { - router->loop()->call([nodes = Nodes(), val] { nodes->DelNode(val); }); - } - - const Key_t& - OurKey() const override - { - return ourKey; - } - - llarp::Router* - GetRouter() const override - { - return router; - } - - bool - GetRCFromNodeDB(const Key_t& k, llarp::RouterContact& rc) const override - { - if (const auto maybe = router->node_db()->Get(k.as_array()); maybe.has_value()) - { - rc = *maybe; - return true; - } - return false; - } - - PendingIntrosetLookups _pendingIntrosetLookups; - PendingRouterLookups _pendingRouterLookups; - PendingExploreLookups _pendingExploreLookups; - - PendingIntrosetLookups& - pendingIntrosetLookups() override - { - return _pendingIntrosetLookups; - } - - const PendingIntrosetLookups& - pendingIntrosetLookups() const override - { - return _pendingIntrosetLookups; - } - - PendingRouterLookups& - pendingRouterLookups() override - { - return _pendingRouterLookups; - } - - const PendingRouterLookups& - pendingRouterLookups() const override - { - return _pendingRouterLookups; - } - - PendingExploreLookups& - pendingExploreLookups() override - { - return _pendingExploreLookups; - } - - const PendingExploreLookups& - pendingExploreLookups() const override - { - return _pendingExploreLookups; - } - - uint64_t - NextID() - { - return ++ids; - } - - llarp_time_t - Now() const override; - - void - ExploreNetworkVia(const Key_t& peer) override; - - bool - handle_message( - const AbstractDHTMessage&, std::vector>&) override; - - private: - std::shared_ptr _timer_keepalive; - - void - CleanupTX(); - - uint64_t ids; - - Key_t ourKey; - }; - - DHTMessageHandler::DHTMessageHandler() - { - randombytes((byte_t*)&ids, sizeof(uint64_t)); - } - - void - DHTMessageHandler::Explore(size_t N) - { - // ask N random peers for new routers - llarp::LogDebug("Exploring network via ", N, " peers"); - std::set peers; - - if (_nodes->GetManyRandom(peers, N)) - { - for (const auto& peer : peers) - ExploreNetworkVia(peer); - } - else - llarp::LogError("failed to select ", N, " random nodes for exploration"); - } - - void - DHTMessageHandler::ExploreNetworkVia(const Key_t& askpeer) - { - uint64_t txid = ++ids; - const TXOwner peer(askpeer, txid); - const TXOwner whoasked(OurKey(), txid); - const RouterID K(askpeer.as_array()); - pendingExploreLookups().NewTX( - peer, whoasked, K, new ExploreNetworkJob(askpeer.as_array(), this)); - } - - void - DHTMessageHandler::handle_cleaner_timer() - { - // clean up transactions - CleanupTX(); - const llarp_time_t now = Now(); - - if (_nodes) - { - // expire router contacts in memory - auto& nodes = _nodes->nodes; - auto itr = nodes.begin(); - while (itr != nodes.end()) - { - if (itr->second.rc.IsExpired(now)) - { - itr = nodes.erase(itr); - } - else - ++itr; - } - } - - if (_services) - { - // expire intro sets - auto& nodes = _services->nodes; - auto itr = nodes.begin(); - while (itr != nodes.end()) - { - if (itr->second.introset.IsExpired(now)) - { - itr = nodes.erase(itr); - } - else - ++itr; - } - } - } - - void - DHTMessageHandler::LookupRouterRelayed( - const Key_t& requester, - uint64_t txid, - const Key_t& target, - bool recursive, - std::vector>& replies) - { - if (target == ourKey) - { - // we are the target, give them our RC - replies.emplace_back(new GotRouterMessage(requester, txid, {router->rc()}, false)); - return; - } - if (not GetRouter()->SessionToRouterAllowed(target.as_array())) - { - // explicitly not allowed - replies.emplace_back(new GotRouterMessage(requester, txid, {}, false)); - return; - } - const auto rc = GetRouter()->node_db()->FindClosestTo(target); - const Key_t next(rc.pubkey); - { - if (next == target) - { - // we know the target - if (rc.ExpiresSoon(llarp::time_now_ms())) - { - // ask target for their rc to keep it updated - LookupRouterRecursive(target.as_array(), requester, txid, next); - } - else - { - // send reply with rc we know of - replies.emplace_back(new GotRouterMessage(requester, txid, {rc}, false)); - } - } - else if (recursive) // are we doing a recursive lookup? - { - // is the next peer we ask closer to the target than us? - if ((next ^ target) < (ourKey ^ target)) - { - // yes it is closer, ask neighbour recursively - LookupRouterRecursive(target.as_array(), requester, txid, next); - } - else - { - // no we are closer to the target so tell requester it's not there - // so they switch to iterative lookup - replies.emplace_back(new GotRouterMessage(requester, txid, {}, false)); - } - } - else - { - // iterative lookup and we don't have it tell them who is closer - replies.emplace_back(new GotRouterMessage(requester, next, txid, false)); - } - } - } - - std::optional - DHTMessageHandler::GetIntroSetByLocation(const Key_t& key) const - { - auto itr = _services->nodes.find(key); - if (itr == _services->nodes.end()) - return {}; - return itr->second.introset; - } - - void - DHTMessageHandler::CleanupTX() - { - auto now = Now(); - llarp::LogTrace("DHT tick"); - - pendingRouterLookups().Expire(now); - _pendingIntrosetLookups.Expire(now); - pendingExploreLookups().Expire(now); - } - - util::StatusObject - DHTMessageHandler::ExtractStatus() const - { - util::StatusObject obj{ - {"pendingRouterLookups", pendingRouterLookups().ExtractStatus()}, - {"pendingIntrosetLookups", _pendingIntrosetLookups.ExtractStatus()}, - {"pendingExploreLookups", pendingExploreLookups().ExtractStatus()}, - {"nodes", _nodes->ExtractStatus()}, - {"services", _services->ExtractStatus()}, - {"ourKey", ourKey.ToHex()}}; - return obj; - } - - bool - DHTMessageHandler::handle_message( - const AbstractDHTMessage& msg, std::vector>& replies) - { - return msg.handle_message(*this, replies); - } - - void - DHTMessageHandler::Init(const Key_t& us, Router* r) - { - router = r; - ourKey = us; - _nodes = std::make_unique>(ourKey, llarp::randint); - _services = std::make_unique>(ourKey, llarp::randint); - llarp::LogDebug("initialize dht with key ", ourKey); - // start cleanup timer - _timer_keepalive = std::make_shared(0); - router->loop()->call_every(1s, _timer_keepalive, [this] { handle_cleaner_timer(); }); - } - - void - DHTMessageHandler::DHTSendTo(const RouterID& peer, AbstractDHTMessage* msg, bool) - { - router->SendToOrQueue(peer, msg); - auto now = Now(); - router->PersistSessionUntil(peer, now + 1min); - } - - // this function handles incoming DHT messages sent down a path by a client - // note that IMessage here is different than that found in the routing - // namespace. by the time this is called, we are inside - // llarp::routing::DHTMessage::HandleMessage() - bool - DHTMessageHandler::RelayRequestForPath(const llarp::PathID_t& id, const AbstractDHTMessage& msg) - { - routing::PathDHTMessage reply; - if (not handle_message(msg, reply.dht_msgs)) - return false; - if (not reply.dht_msgs.empty()) - { - auto path = router->path_context().GetByUpstream(router->pubkey(), id); - return path && path->SendRoutingMessage(reply, router); - } - return true; - } - - void - DHTMessageHandler::LookupIntroSetForPath( - const Key_t& addr, - uint64_t txid, - const llarp::PathID_t& path, - const Key_t& askpeer, - uint64_t relayOrder) - { - const TXOwner asker(OurKey(), txid); - const TXOwner peer(askpeer, ++ids); - _pendingIntrosetLookups.NewTX( - peer, - asker, - asker, - new LocalServiceAddressLookup(path, txid, relayOrder, addr, this, askpeer)); - } - - void - DHTMessageHandler::PropagateIntroSetTo( - const Key_t& from, - uint64_t txid, - const service::EncryptedIntroSet& introset, - const Key_t& tellpeer, - uint64_t relayOrder) - { - const TXOwner asker(from, txid); - const TXOwner peer(tellpeer, ++ids); - _pendingIntrosetLookups.NewTX( - peer, asker, asker, new PublishServiceJob(asker, introset, this, relayOrder)); - } - - void - DHTMessageHandler::PropagateLocalIntroSet( - const PathID_t& from, - uint64_t txid, - const service::EncryptedIntroSet& introset, - const Key_t& tellpeer, - uint64_t relayOrder) - { - const TXOwner asker(OurKey(), txid); - const TXOwner peer(tellpeer, ++ids); - _pendingIntrosetLookups.NewTX( - peer, - asker, - peer, - new LocalPublishServiceJob(peer, from, txid, introset, this, relayOrder)); - } - - void - DHTMessageHandler::LookupIntroSetRelayed( - const Key_t& addr, - const Key_t& whoasked, - uint64_t txid, - const Key_t& askpeer, - uint64_t relayOrder, - service::EncryptedIntroSetLookupHandler handler) - { - const TXOwner asker(whoasked, txid); - const TXOwner peer(askpeer, ++ids); - _pendingIntrosetLookups.NewTX( - peer, asker, asker, new ServiceAddressLookup(asker, addr, this, relayOrder, handler)); - } - - void - DHTMessageHandler::LookupIntroSetDirect( - const Key_t& addr, - const Key_t& whoasked, - uint64_t txid, - const Key_t& askpeer, - service::EncryptedIntroSetLookupHandler handler) - { - const TXOwner asker(whoasked, txid); - const TXOwner peer(askpeer, ++ids); - _pendingIntrosetLookups.NewTX( - peer, asker, asker, new ServiceAddressLookup(asker, addr, this, 0, handler), 1s); - } - - bool - DHTMessageHandler::HandleExploritoryRouterLookup( - const Key_t& requester, - uint64_t txid, - const RouterID& target, - std::vector>& reply) - { - std::vector closer; - const Key_t t(target.as_array()); - std::set foundRouters; - if (!_nodes) - return false; - - const size_t nodeCount = _nodes->size(); - if (nodeCount == 0) - { - llarp::LogError("cannot handle exploritory router lookup, no dht peers"); - return false; - } - llarp::LogDebug("We have ", _nodes->size(), " connected nodes into the DHT"); - // ourKey should never be in the connected list - // requester is likely in the connected list - // 4 or connection nodes (minus a potential requestor), whatever is less - if (!_nodes->GetManyNearExcluding( - t, foundRouters, std::min(nodeCount, size_t{4}), std::set{ourKey, requester})) - { - llarp::LogError( - "not enough dht nodes to handle exploritory router lookup, " - "have ", - nodeCount, - " dht peers"); - return false; - } - for (const auto& f : foundRouters) - { - const RouterID id = f.as_array(); - // discard shit routers - if (router->router_profiling().IsBadForConnect(id)) - continue; - closer.emplace_back(id); - } - llarp::LogDebug("Gave ", closer.size(), " routers for exploration"); - reply.emplace_back(new GotRouterMessage(txid, closer, false)); - return true; - } - - void - DHTMessageHandler::LookupRouterForPath( - const RouterID& target, uint64_t txid, const llarp::PathID_t& path, const Key_t& askpeer) - - { - const TXOwner peer(askpeer, ++ids); - const TXOwner whoasked(OurKey(), txid); - _pendingRouterLookups.NewTX( - peer, whoasked, target, new LocalRouterLookup(path, txid, target, this)); - } - - void - DHTMessageHandler::LookupRouterRecursive( - const RouterID& target, - const Key_t& whoasked, - uint64_t txid, - const Key_t& askpeer, - RouterLookupHandler handler) - { - const TXOwner asker(whoasked, txid); - const TXOwner peer(askpeer, ++ids); - _pendingRouterLookups.NewTX( - peer, asker, target, new RecursiveRouterLookup(asker, target, this, handler)); - } - - llarp_time_t - DHTMessageHandler::Now() const - { - return router->now(); - } - - std::unique_ptr - make_handler() - { - return std::make_unique(); - } - -} // namespace llarp::dht diff --git a/llarp/dht/dht.cpp b/llarp/dht/dht.cpp deleted file mode 100644 index ba8149feca..0000000000 --- a/llarp/dht/dht.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "dht.h" -#include - -// llarp_dht_context::llarp_dht_context(llarp::Router* router) -// { -// parent = router; -// impl = llarp::dht::make_handler(); -// } - -// struct llarp_dht_context* -// llarp_dht_context_new(llarp::Router* router) -// { -// return new llarp_dht_context(router); -// } - -// void -// llarp_dht_context_free(struct llarp_dht_context* ctx) -// { -// delete ctx; -// } - -// void -// __llarp_dht_remove_peer(struct llarp_dht_context* ctx, const byte_t* id) -// { -// ctx->impl->Nodes()->DelNode(llarp::dht::Key_t(id)); -// } - -// void -// llarp_dht_allow_transit(llarp_dht_context* ctx) -// { -// ctx->impl->AllowTransit() = true; -// } - -// void -// llarp_dht_context_start(struct llarp_dht_context* ctx, const byte_t* key) -// { -// ctx->impl->Init(llarp::dht::Key_t(key), ctx->parent); -// } - -void -llarp_dht_lookup_router(struct llarp_dht_context* ctx, struct llarp_router_lookup_job* job) -{ - job->dht = ctx; - job->found = false; - job->result.Clear(); - // llarp_rc_clear(&job->result); - llarp::LogError("implement me llarp_dht_lookup_router"); - /* - ctx->parent->logic->queue_job( - {job, &llarp::dht::Context::queue_router_lookup}); - */ -} diff --git a/llarp/dht/dht.h b/llarp/dht/dht.h deleted file mode 100644 index 618b113509..0000000000 --- a/llarp/dht/dht.h +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once - -#include -#include -#include - -/** - * dht.h - * - * DHT functions - */ - -struct llarp_dht_context; - -namespace llarp -{ - struct Router; -} - -/// allocator -struct llarp_dht_context* -llarp_dht_context_new(llarp::Router* parent); - -/// deallocator -void -llarp_dht_context_free(struct llarp_dht_context* dht); - -/// start dht context with our location in keyspace -void -llarp_dht_context_start(struct llarp_dht_context* ctx, const byte_t* key); - -// remove this? dns needs it atm -struct llarp_router_lookup_job; - -using llarp_router_lookup_handler = void (*)(struct llarp_router_lookup_job*); - -struct llarp_router_lookup_job -{ - /// can be anything but usually a class context for hook - void* user; - llarp_router_lookup_handler hook; - struct llarp_dht_context* dht; - llarp::PubKey target; - bool found; - // make sure you initialize addr and exits - llarp::RouterContact result; - bool iterative; -}; -// end dns requirement - -/// start allowing dht participation on a context -void -llarp_dht_allow_transit(struct llarp_dht_context* ctx); - -/// remove router from tracked dht peer list -/// internal function do not use -void -__llarp_dht_remove_peer(struct llarp_dht_context* ctx, const byte_t* id); - -void -llarp_dht_lookup_router(struct llarp_dht_context* ctx, struct llarp_router_lookup_job* job); diff --git a/llarp/dht/kademlia.hpp b/llarp/dht/kademlia.hpp index b2889ac6ad..776d8cb37e 100644 --- a/llarp/dht/kademlia.hpp +++ b/llarp/dht/kademlia.hpp @@ -1,6 +1,7 @@ #pragma once #include "key.hpp" + #include namespace llarp::dht diff --git a/llarp/dht/key.hpp b/llarp/dht/key.hpp index 006bd9ff52..97fa8162ed 100644 --- a/llarp/dht/key.hpp +++ b/llarp/dht/key.hpp @@ -1,7 +1,7 @@ #pragma once -#include #include +#include #include #include diff --git a/llarp/dht/node.hpp b/llarp/dht/node.hpp index 0012298707..0f2deecc23 100644 --- a/llarp/dht/node.hpp +++ b/llarp/dht/node.hpp @@ -1,8 +1,10 @@ #pragma once #include "key.hpp" + #include #include + #include namespace llarp::dht diff --git a/llarp/dht/tx.hpp b/llarp/dht/tx.hpp deleted file mode 100644 index b2c3ebc87a..0000000000 --- a/llarp/dht/tx.hpp +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef LLARP_DHT_TX -#define LLARP_DHT_TX - -#include "key.hpp" -#include "txowner.hpp" - -#include -#include - -#include -#include - -namespace llarp -{ - struct Router; - - namespace dht - { - template - struct TX - { - K target; - Router* router; - std::set peersAsked; - std::vector valuesFound; - TXOwner whoasked; - - TX(const TXOwner& asker, const K& k, Router* r) : target(k), router{r}, whoasked(asker) - {} - - virtual ~TX() = default; - - void - OnFound(const Key_t& askedPeer, const V& value); - - util::StatusObject - ExtractStatus() const - { - util::StatusObject obj{ - {"whoasked", whoasked.ExtractStatus()}, {"target", target.ExtractStatus()}}; - std::vector foundObjs; - std::transform( - valuesFound.begin(), - valuesFound.end(), - std::back_inserter(foundObjs), - [](const auto& item) -> util::StatusObject { return item.ExtractStatus(); }); - - obj["found"] = foundObjs; - std::vector asked; - std::transform( - peersAsked.begin(), - peersAsked.end(), - std::back_inserter(asked), - [](const auto& item) -> std::string { return item.ToString(); }); - obj["asked"] = asked; - return obj; - } - - virtual bool - Validate(const V& value) const = 0; - - virtual void - Start(const TXOwner& peer) = 0; - }; - - template - inline void - TX::OnFound(const Key_t& askedPeer, const V& value) - { - peersAsked.insert(askedPeer); - if (Validate(value)) - { - valuesFound.push_back(value); - } - } - } // namespace dht -} // namespace llarp - -#endif diff --git a/llarp/dht/txholder.hpp b/llarp/dht/txholder.hpp deleted file mode 100644 index c75effe710..0000000000 --- a/llarp/dht/txholder.hpp +++ /dev/null @@ -1,212 +0,0 @@ -#ifndef LLARP_DHT_TXHOLDER -#define LLARP_DHT_TXHOLDER - -#include "tx.hpp" -#include "txowner.hpp" -#include -#include - -#include -#include - -namespace llarp::dht -{ - template - struct TXHolder - { - using TXPtr = std::unique_ptr>; - // tx who are waiting for a reply for each key - std::unordered_multimap waiting; - // tx timesouts by key - std::unordered_map timeouts; - // maps remote peer with tx to handle reply from them - std::unordered_map tx; - - const TX* - GetPendingLookupFrom(const TXOwner& owner) const; - - util::StatusObject - ExtractStatus() const - { - util::StatusObject obj{}; - std::vector txObjs, timeoutsObjs, waitingObjs; - std::transform( - tx.begin(), - tx.end(), - std::back_inserter(txObjs), - [](const auto& item) -> util::StatusObject { - return util::StatusObject{ - {"owner", item.first.ExtractStatus()}, {"tx", item.second->ExtractStatus()}}; - }); - obj["tx"] = txObjs; - std::transform( - timeouts.begin(), - timeouts.end(), - std::back_inserter(timeoutsObjs), - [](const auto& item) -> util::StatusObject { - return util::StatusObject{ - {"time", to_json(item.second)}, {"target", item.first.ExtractStatus()}}; - }); - obj["timeouts"] = timeoutsObjs; - std::transform( - waiting.begin(), - waiting.end(), - std::back_inserter(waitingObjs), - [](const auto& item) -> util::StatusObject { - return util::StatusObject{ - {"target", item.first.ExtractStatus()}, {"whoasked", item.second.ExtractStatus()}}; - }); - obj["waiting"] = waitingObjs; - return obj; - } - - bool - HasLookupFor(const K& target) const - { - return timeouts.find(target) != timeouts.end(); - } - - bool - HasPendingLookupFrom(const TXOwner& owner) const - { - return GetPendingLookupFrom(owner) != nullptr; - } - - void - NewTX( - const TXOwner& askpeer, - const TXOwner& whoasked, - const K& k, - TX* t, - llarp_time_t requestTimeoutMS = 15s); - - /// mark tx as not fond - void - NotFound(const TXOwner& from, const std::unique_ptr& next); - - void - Found(const TXOwner& from, const K& k, const std::vector& values) - { - Inform(from, k, values, true); - } - - /// inform all watches for key of values found - void - Inform( - TXOwner from, - K key, - std::vector values, - bool sendreply = false, - bool removeTimeouts = true); - - void - Expire(llarp_time_t now); - }; - - template - const TX* - TXHolder::GetPendingLookupFrom(const TXOwner& owner) const - { - auto itr = tx.find(owner); - if (itr == tx.end()) - { - return nullptr; - } - - return itr->second.get(); - } - - template - void - TXHolder::NewTX( - const TXOwner& askpeer, - const TXOwner& whoasked, - const K& k, - TX* t, - llarp_time_t requestTimeoutMS) - { - (void)whoasked; - tx.emplace(askpeer, std::unique_ptr>(t)); - auto count = waiting.count(k); - waiting.emplace(k, askpeer); - - auto itr = timeouts.find(k); - if (itr == timeouts.end()) - { - timeouts.emplace(k, time_now_ms() + requestTimeoutMS); - } - if (count == 0) - { - t->Start(askpeer); - } - } - - template - void - TXHolder::NotFound(const TXOwner& from, const std::unique_ptr&) - { - auto txitr = tx.find(from); - if (txitr == tx.end()) - { - return; - } - Inform(from, txitr->second->target, {}, true, true); - } - - template - void - TXHolder::Inform( - TXOwner from, K key, std::vector values, bool sendreply, bool removeTimeouts) - { - auto range = waiting.equal_range(key); - auto itr = range.first; - while (itr != range.second) - { - auto txitr = tx.find(itr->second); - if (txitr != tx.end()) - { - for (const auto& value : values) - { - txitr->second->OnFound(from.node, value); - } - if (sendreply) - { - txitr->second->SendReply(); - tx.erase(txitr); - } - } - ++itr; - } - - if (sendreply) - { - waiting.erase(key); - } - - if (removeTimeouts) - { - timeouts.erase(key); - } - } - - template - void - TXHolder::Expire(llarp_time_t now) - { - auto itr = timeouts.begin(); - while (itr != timeouts.end()) - { - if (now >= itr->second) - { - Inform(TXOwner{}, itr->first, {}, true, false); - itr = timeouts.erase(itr); - } - else - { - ++itr; - } - } - } -} // namespace llarp::dht - -#endif diff --git a/llarp/dht/txowner.hpp b/llarp/dht/txowner.hpp deleted file mode 100644 index 0fb7b25196..0000000000 --- a/llarp/dht/txowner.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#pragma once - -#include "key.hpp" -#include -#include - -namespace llarp::dht -{ - struct TXOwner - { - Key_t node; - uint64_t txid = 0; - - TXOwner() = default; - TXOwner(const TXOwner&) = default; - TXOwner(TXOwner&&) = default; - - TXOwner& - operator=(const TXOwner&) = default; - - TXOwner(const Key_t& k, uint64_t id) : node(k), txid(id) - {} - - util::StatusObject - ExtractStatus() const - { - util::StatusObject obj{ - {"txid", txid}, - {"node", node.ToHex()}, - }; - return obj; - } - - bool - operator==(const TXOwner& other) const - { - return std::tie(txid, node) == std::tie(other.txid, other.node); - } - - bool - operator<(const TXOwner& other) const - { - return std::tie(txid, node) < std::tie(other.txid, other.node); - } - }; -} // namespace llarp::dht - -namespace std -{ - template <> - struct hash - { - std::size_t - operator()(const llarp::dht::TXOwner& o) const noexcept - { - std::size_t sz2; - memcpy(&sz2, o.node.data(), sizeof(std::size_t)); - return o.txid ^ (sz2 << 1); - } - }; -} // namespace std diff --git a/llarp/dns/message.cpp b/llarp/dns/message.cpp index d527b03dd3..a05f328570 100644 --- a/llarp/dns/message.cpp +++ b/llarp/dns/message.cpp @@ -1,13 +1,15 @@ #include "message.hpp" -#include -#include -#include -#include - #include "dns.hpp" #include "srv_data.hpp" +#include +#include + +#include + +#include + namespace llarp::dns { static auto logcat = log::Cat("dns"); diff --git a/llarp/dns/message.hpp b/llarp/dns/message.hpp index 6140d307c6..852f3408df 100644 --- a/llarp/dns/message.hpp +++ b/llarp/dns/message.hpp @@ -1,8 +1,8 @@ #pragma once -#include "serialize.hpp" -#include "rr.hpp" #include "question.hpp" +#include "rr.hpp" +#include "serialize.hpp" namespace llarp { diff --git a/llarp/dns/name.cpp b/llarp/dns/name.cpp index e78a8cf9d2..6741a38db1 100644 --- a/llarp/dns/name.cpp +++ b/llarp/dns/name.cpp @@ -1,8 +1,9 @@ #include "name.hpp" #include -#include #include +#include + #include namespace llarp::dns diff --git a/llarp/dns/name.hpp b/llarp/dns/name.hpp index 718ebb0fc2..deb4b344d0 100644 --- a/llarp/dns/name.hpp +++ b/llarp/dns/name.hpp @@ -2,8 +2,9 @@ #include #include -#include + #include +#include namespace llarp::dns { diff --git a/llarp/dns/nm_platform.hpp b/llarp/dns/nm_platform.hpp index 593cfaa28b..650e353652 100644 --- a/llarp/dns/nm_platform.hpp +++ b/llarp/dns/nm_platform.hpp @@ -2,6 +2,7 @@ #include "platform.hpp" #include + #include #include diff --git a/llarp/dns/platform.hpp b/llarp/dns/platform.hpp index e1db57ba18..55abd93b24 100644 --- a/llarp/dns/platform.hpp +++ b/llarp/dns/platform.hpp @@ -1,9 +1,10 @@ #pragma once #include #include -#include + #include #include +#include #ifndef _WIN32 #include diff --git a/llarp/dns/question.cpp b/llarp/dns/question.cpp index baa4c1d345..d7bd7b2104 100644 --- a/llarp/dns/question.cpp +++ b/llarp/dns/question.cpp @@ -1,9 +1,9 @@ #include "question.hpp" -#include - #include "dns.hpp" +#include + namespace llarp::dns { static auto logcat = log::Cat("dns"); diff --git a/llarp/dns/question.hpp b/llarp/dns/question.hpp index a5a1330e37..7bad74f513 100644 --- a/llarp/dns/question.hpp +++ b/llarp/dns/question.hpp @@ -1,7 +1,7 @@ #pragma once -#include "serialize.hpp" #include "name.hpp" +#include "serialize.hpp" #include diff --git a/llarp/dns/rr.hpp b/llarp/dns/rr.hpp index b1c0b152c9..ec19032faf 100644 --- a/llarp/dns/rr.hpp +++ b/llarp/dns/rr.hpp @@ -1,12 +1,13 @@ #pragma once +#include "name.hpp" +#include "serialize.hpp" + #include + #include #include -#include "name.hpp" -#include "serialize.hpp" - namespace llarp::dns { using RRClass_t = uint16_t; diff --git a/llarp/dns/sd_platform.hpp b/llarp/dns/sd_platform.hpp index 27db6d6fa5..d3d850eeeb 100644 --- a/llarp/dns/sd_platform.hpp +++ b/llarp/dns/sd_platform.hpp @@ -2,6 +2,7 @@ #include "platform.hpp" #include + #include namespace llarp::dns diff --git a/llarp/dns/serialize.hpp b/llarp/dns/serialize.hpp index 5ae8d15fc5..a75c447e5c 100644 --- a/llarp/dns/serialize.hpp +++ b/llarp/dns/serialize.hpp @@ -2,6 +2,7 @@ #include #include + #include namespace llarp::dns diff --git a/llarp/dns/server.cpp b/llarp/dns/server.cpp index 995f10a5d7..49deb212ab 100644 --- a/llarp/dns/server.cpp +++ b/llarp/dns/server.cpp @@ -1,19 +1,20 @@ #include "server.hpp" -#include +#include "nm_platform.hpp" +#include "sd_platform.hpp" + #include +#include #include + +#include #include +#include + +#include +#include #include #include -#include -#include - -#include "oxen/log.hpp" -#include "sd_platform.hpp" -#include "nm_platform.hpp" - -#include namespace llarp::dns { diff --git a/llarp/dns/server.hpp b/llarp/dns/server.hpp index d4baef55cd..dc2eec4734 100644 --- a/llarp/dns/server.hpp +++ b/llarp/dns/server.hpp @@ -1,14 +1,15 @@ #pragma once +#include "message.hpp" +#include "platform.hpp" + #include #include #include -#include #include -#include +#include -#include "message.hpp" -#include "platform.hpp" +#include namespace llarp::dns { diff --git a/llarp/dns/srv_data.cpp b/llarp/dns/srv_data.cpp index d5189856ad..695955b672 100644 --- a/llarp/dns/srv_data.cpp +++ b/llarp/dns/srv_data.cpp @@ -1,10 +1,10 @@ #include "srv_data.hpp" -#include - #include -#include #include +#include + +#include namespace llarp::dns { diff --git a/llarp/dns/srv_data.hpp b/llarp/dns/srv_data.hpp index 59b2603093..c1b864c3db 100644 --- a/llarp/dns/srv_data.hpp +++ b/llarp/dns/srv_data.hpp @@ -1,12 +1,13 @@ #pragma once -#include -#include - #include "dns.hpp" #include "name.hpp" #include "serialize.hpp" -#include "llarp/util/status.hpp" + +#include + +#include +#include namespace llarp::dns { diff --git a/llarp/endpoint_base.cpp b/llarp/endpoint_base.cpp index a8c6877660..0e74cdbc5e 100644 --- a/llarp/endpoint_base.cpp +++ b/llarp/endpoint_base.cpp @@ -1,6 +1,6 @@ #include "endpoint_base.hpp" -#include "llarp/util/algorithm.hpp" +#include namespace llarp { diff --git a/llarp/endpoint_base.hpp b/llarp/endpoint_base.hpp index a6629f7b4a..3c1773dad4 100644 --- a/llarp/endpoint_base.hpp +++ b/llarp/endpoint_base.hpp @@ -1,22 +1,24 @@ #pragma once +#include "router_id.hpp" + +#include +#include #include +#include +#include +#include + +#include #include + #include #include +#include +#include #include #include -#include #include -#include - -#include "llarp/service/address.hpp" -#include "llarp/service/convotag.hpp" -#include "llarp/service/protocol_type.hpp" -#include "router_id.hpp" -#include "llarp/ev/ev.hpp" -#include "llarp/dns/srv_data.hpp" -#include "oxenc/variant.h" namespace llarp { @@ -25,6 +27,12 @@ namespace llarp class Server; } + // TODO: add forward declaration of TunnelManager + // namespace link + // { + // class TunneLManager; + // } + class EndpointBase { std::unordered_set m_SRVRecords; diff --git a/llarp/ev/ev.cpp b/llarp/ev/ev.cpp index 04362f41b0..08b084a64b 100644 --- a/llarp/ev/ev.cpp +++ b/llarp/ev/ev.cpp @@ -1,9 +1,10 @@ #include "ev.hpp" +#include "libuv.hpp" + #include -#include -#include "libuv.hpp" +#include namespace llarp { diff --git a/llarp/ev/ev.hpp b/llarp/ev/ev.hpp index 329a49b289..33c5724d91 100644 --- a/llarp/ev/ev.hpp +++ b/llarp/ev/ev.hpp @@ -1,14 +1,16 @@ #pragma once +#include #include -#include #include -#include -#include +#include + +#include + #include #include -#include #include +#include #include using oxen::log::slns::source_location; @@ -20,6 +22,8 @@ namespace uvw namespace llarp { + constexpr std::size_t event_loop_queue_size = 1024; + struct SockAddr; struct UDPHandle; diff --git a/llarp/ev/libuv.cpp b/llarp/ev/libuv.cpp index e76e58611c..0961b9d4d2 100644 --- a/llarp/ev/libuv.cpp +++ b/llarp/ev/libuv.cpp @@ -3,12 +3,12 @@ #include #include +#include + +#include #include #include #include -#include - -#include namespace llarp::uv { diff --git a/llarp/ev/libuv.hpp b/llarp/ev/libuv.hpp index d83865de14..2d9cff0156 100644 --- a/llarp/ev/libuv.hpp +++ b/llarp/ev/libuv.hpp @@ -1,17 +1,16 @@ #pragma once -#include +#include "ev.hpp" +#include "udp_handle.hpp" + #include -#include -#include -#include -#include +#include + +// #include + #include #include #include -#include "ev.hpp" -#include "udp_handle.hpp" - namespace llarp::uv { class UVWakeup; diff --git a/llarp/ev/udp_handle.hpp b/llarp/ev/udp_handle.hpp index 9e8425cd5d..aaf50c9234 100644 --- a/llarp/ev/udp_handle.hpp +++ b/llarp/ev/udp_handle.hpp @@ -1,5 +1,5 @@ -#include "ev.hpp" #include "../util/buffer.hpp" +#include "ev.hpp" namespace llarp { diff --git a/llarp/exit/context.cpp b/llarp/exit/context.cpp index fdf0a3118e..aa3761cc98 100644 --- a/llarp/exit/context.cpp +++ b/llarp/exit/context.cpp @@ -1,4 +1,5 @@ #include "context.hpp" + #include #include diff --git a/llarp/exit/context.hpp b/llarp/exit/context.hpp index 923106ebde..31a9e766fe 100644 --- a/llarp/exit/context.hpp +++ b/llarp/exit/context.hpp @@ -1,10 +1,11 @@ #pragma once +#include "policy.hpp" + #include + #include #include -#include "policy.hpp" - namespace llarp::exit { /// owner of all the exit endpoints diff --git a/llarp/exit/endpoint.hpp b/llarp/exit/endpoint.hpp index 547e697abd..7405ce1f9b 100644 --- a/llarp/exit/endpoint.hpp +++ b/llarp/exit/endpoint.hpp @@ -5,6 +5,7 @@ #include #include #include + #include namespace llarp diff --git a/llarp/exit/policy.hpp b/llarp/exit/policy.hpp index 60b20d95ac..c45da613c5 100644 --- a/llarp/exit/policy.hpp +++ b/llarp/exit/policy.hpp @@ -1,8 +1,9 @@ #pragma once -#include #include +#include + namespace { static auto policy_cat = llarp::log::Cat("lokinet.policy"); diff --git a/llarp/exit/session.cpp b/llarp/exit/session.cpp index 6920c750c7..158b026510 100644 --- a/llarp/exit/session.cpp +++ b/llarp/exit/session.cpp @@ -2,9 +2,10 @@ #include #include -#include #include +#include #include + #include namespace llarp::exit diff --git a/llarp/exit/session.hpp b/llarp/exit/session.hpp index a95f2baf4c..4351517434 100644 --- a/llarp/exit/session.hpp +++ b/llarp/exit/session.hpp @@ -1,9 +1,10 @@ #pragma once -#include +#include #include #include -#include +#include + #include #include diff --git a/llarp/handlers/exit.cpp b/llarp/handlers/exit.cpp index 20578e5101..3702c3f2ae 100644 --- a/llarp/handlers/exit.cpp +++ b/llarp/handlers/exit.cpp @@ -3,9 +3,10 @@ #include #include #include -#include #include +#include #include + #include namespace llarp::handlers diff --git a/llarp/handlers/exit.hpp b/llarp/handlers/exit.hpp index 8354bdb93c..b1b97f3f45 100644 --- a/llarp/handlers/exit.hpp +++ b/llarp/handlers/exit.hpp @@ -1,10 +1,11 @@ #pragma once -#include +#include "tun.hpp" + #include -#include +#include -#include "tun.hpp" +#include namespace llarp { diff --git a/llarp/handlers/null.hpp b/llarp/handlers/null.hpp index ecf1f61fec..4f473c8519 100644 --- a/llarp/handlers/null.hpp +++ b/llarp/handlers/null.hpp @@ -1,10 +1,10 @@ #pragma once +#include #include +#include #include #include -#include -#include #include namespace llarp::handlers diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 80aca87ff8..468e138a74 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -1,26 +1,26 @@ +#include "tun.hpp" + #include #include #include - -#include "tun.hpp" #ifndef _WIN32 #include #endif +#include #include #include #include -#include +#include #include +#include +#include #include -#include #include #include +#include #include -#include -#include #include -#include namespace llarp::handlers { diff --git a/llarp/handlers/tun.hpp b/llarp/handlers/tun.hpp index 846e11dd24..f4241d9014 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -11,6 +11,7 @@ #include #include #include + #include #include #include diff --git a/llarp/link/connection.hpp b/llarp/link/connection.hpp index 69f88896bd..fe8b0961a3 100644 --- a/llarp/link/connection.hpp +++ b/llarp/link/connection.hpp @@ -1,7 +1,8 @@ #pragma once -#include #include +#include + #include namespace llarp::link diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index d9fe5583be..f3f5047955 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1,13 +1,14 @@ #include "link_manager.hpp" + #include "connection.hpp" #include "contacts.hpp" #include #include #include -#include -#include #include +#include +#include #include #include diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 6788447b87..d2b8cc8c91 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -1,19 +1,21 @@ #pragma once +#include "connection.hpp" + #include -#include +#include #include #include -#include #include -#include +#include #include #include -#include -#include -#include -#include "connection.hpp" +#include + +#include +#include +#include namespace { diff --git a/llarp/link/tunnel.cpp b/llarp/link/tunnel.cpp index 0c5fa5bb46..f873eed302 100644 --- a/llarp/link/tunnel.cpp +++ b/llarp/link/tunnel.cpp @@ -1,12 +1,14 @@ #include "tunnel.hpp" + +#include #include #include #include -#include #include #include #include -#include + +#include #include #include #include diff --git a/llarp/link/tunnel.hpp b/llarp/link/tunnel.hpp index 4d5abca8e5..0abd972846 100644 --- a/llarp/link/tunnel.hpp +++ b/llarp/link/tunnel.hpp @@ -3,13 +3,13 @@ #include #include -#include #include +#include #include #include -#include #include #include +#include // #include diff --git a/llarp/linux/sd_service_manager.cpp b/llarp/linux/sd_service_manager.cpp index 43d9ec47ed..cf9666754b 100644 --- a/llarp/linux/sd_service_manager.cpp +++ b/llarp/linux/sd_service_manager.cpp @@ -1,10 +1,11 @@ +#include +#include +#include #include #include + #include -#include -#include -#include namespace llarp::sys { diff --git a/llarp/lokinet_shared.cpp b/llarp/lokinet_shared.cpp index e933033253..9b8c64c4ef 100644 --- a/llarp/lokinet_shared.cpp +++ b/llarp/lokinet_shared.cpp @@ -1,22 +1,20 @@ -#include #include #include #include - -#include -#include #include #include - +#include +#include #include #include #include +#include #include -#include -#include #include +#include +#include #include #ifdef _WIN32 diff --git a/llarp/messages/link_message.hpp b/llarp/messages/link_message.hpp index 7a60b880d5..e05fa33b36 100644 --- a/llarp/messages/link_message.hpp +++ b/llarp/messages/link_message.hpp @@ -2,9 +2,9 @@ #include "common.hpp" +#include #include #include -#include #include @@ -60,10 +60,4 @@ namespace llarp "Error: Link messages should not encode directly to a bt list producer!"}; } }; - - struct AbstractDataMessage : public AbstractLinkMessage - { - using AbstractLinkMessage::AbstractLinkMessage; - }; - } // namespace llarp diff --git a/llarp/messages/relay.hpp b/llarp/messages/relay.hpp index 22cbb162fe..e6064e2f9b 100644 --- a/llarp/messages/relay.hpp +++ b/llarp/messages/relay.hpp @@ -1,11 +1,12 @@ #pragma once +#include "link_message.hpp" + #include #include #include -#include -#include "link_message.hpp" +#include namespace llarp { @@ -13,7 +14,7 @@ namespace llarp Data messages to be sent via quic datagrams */ - struct RelayUpstreamMessage final : public AbstractDataMessage + struct RelayUpstreamMessage final : public AbstractLinkMessage { Encrypted enc; TunnelNonce nonce; @@ -42,7 +43,7 @@ namespace llarp } }; - struct RelayDownstreamMessage final : public AbstractDataMessage + struct RelayDownstreamMessage final : public AbstractLinkMessage { Encrypted enc; TunnelNonce nonce; diff --git a/llarp/net/exit_info.cpp b/llarp/net/exit_info.cpp index 20b8cce983..69d297cca1 100644 --- a/llarp/net/exit_info.cpp +++ b/llarp/net/exit_info.cpp @@ -2,10 +2,11 @@ #include #endif +#include "exit_info.hpp" + #include -#include -#include "exit_info.hpp" +#include namespace llarp { diff --git a/llarp/net/exit_info.hpp b/llarp/net/exit_info.hpp index 0ea3fac34e..5c1c92736c 100644 --- a/llarp/net/exit_info.hpp +++ b/llarp/net/exit_info.hpp @@ -1,10 +1,11 @@ #pragma once +#include "ip_address.hpp" + #include #include -#include -#include "ip_address.hpp" +#include /** * exit_info.h diff --git a/llarp/net/interface_info.hpp b/llarp/net/interface_info.hpp index 107f7bf901..f720090dc9 100644 --- a/llarp/net/interface_info.hpp +++ b/llarp/net/interface_info.hpp @@ -1,12 +1,13 @@ #pragma once +#include "ip_range.hpp" + #include + #include #include #include -#include "ip_range.hpp" - namespace llarp::net { /// info about a network interface lokinet does not own diff --git a/llarp/net/ip.cpp b/llarp/net/ip.cpp index ed30a42de5..ef87da31b6 100644 --- a/llarp/net/ip.cpp +++ b/llarp/net/ip.cpp @@ -1,4 +1,5 @@ #include "ip.hpp" + #include namespace llarp::net diff --git a/llarp/net/ip_address.cpp b/llarp/net/ip_address.cpp index 741c0b3443..d37aee133b 100644 --- a/llarp/net/ip_address.cpp +++ b/llarp/net/ip_address.cpp @@ -1,4 +1,5 @@ #include "ip_address.hpp" + #include "ip_range.hpp" namespace llarp diff --git a/llarp/net/ip_address.hpp b/llarp/net/ip_address.hpp index 1730008fda..e4cf26f1bb 100644 --- a/llarp/net/ip_address.hpp +++ b/llarp/net/ip_address.hpp @@ -1,12 +1,13 @@ #pragma once +#include "net_int.hpp" +#include "sock_addr.hpp" + #include + #include -#include #include - -#include "sock_addr.hpp" -#include "net_int.hpp" +#include namespace llarp { diff --git a/llarp/net/ip_packet.cpp b/llarp/net/ip_packet.cpp index 2065e6929e..fc69d8c178 100644 --- a/llarp/net/ip_packet.cpp +++ b/llarp/net/ip_packet.cpp @@ -1,15 +1,16 @@ #include "ip_packet.hpp" +#include "ip.hpp" + #include #include #include - -#include "ip.hpp" #ifndef _WIN32 #include #endif #include + #include namespace llarp::net diff --git a/llarp/net/ip_packet.hpp b/llarp/net/ip_packet.hpp index f381873952..ad6e208e02 100644 --- a/llarp/net/ip_packet.hpp +++ b/llarp/net/ip_packet.hpp @@ -1,15 +1,17 @@ #pragma once -#include -#include +#include "net.hpp" + +// #include +#include #include #include -#include + +#include + #include #include -#include "net.hpp" - namespace llarp::net { struct ip_header_le diff --git a/llarp/net/ip_range.cpp b/llarp/net/ip_range.cpp index 23fe8b1c06..363b2c2e68 100644 --- a/llarp/net/ip_range.cpp +++ b/llarp/net/ip_range.cpp @@ -1,8 +1,8 @@ #include "ip_range.hpp" -#include "oxenc/bt_serialize.h" +#include -#include "llarp/util/bencode.h" +#include namespace llarp { diff --git a/llarp/net/ip_range.hpp b/llarp/net/ip_range.hpp index 8c5d7aaed6..0dcc5a6f79 100644 --- a/llarp/net/ip_range.hpp +++ b/llarp/net/ip_range.hpp @@ -1,19 +1,21 @@ #pragma once -#include +#include "ip.hpp" +#include "net_bits.hpp" + #include #include -#include #include +#include + +#include #include + #include #include #include #include -#include "ip.hpp" -#include "net_bits.hpp" - namespace { static auto net_cat = llarp::log::Cat("lokinet.net"); diff --git a/llarp/net/ip_range_map.hpp b/llarp/net/ip_range_map.hpp index d38bcf83ed..51083388ca 100644 --- a/llarp/net/ip_range_map.hpp +++ b/llarp/net/ip_range_map.hpp @@ -1,7 +1,9 @@ #pragma once #include "ip_range.hpp" + #include + #include #include diff --git a/llarp/net/net.h b/llarp/net/net.h index cc0a567415..bbc647ac96 100644 --- a/llarp/net/net.h +++ b/llarp/net/net.h @@ -1,6 +1,7 @@ #pragma once #if defined(_WIN32) || defined(__MINGW32__) #include + #include #include // because this shit is not defined for Windows NT reeeee diff --git a/llarp/net/net.hpp b/llarp/net/net.hpp index f215310296..0c4b50700d 100644 --- a/llarp/net/net.hpp +++ b/llarp/net/net.hpp @@ -1,26 +1,27 @@ #pragma once -#include "uint128.hpp" +#include "interface_info.hpp" #include "ip_address.hpp" -#include "net_int.hpp" -#include "net.h" #include "ip_range.hpp" -#include -#include +#include "net.h" +#include "net_int.hpp" +#include "uint128.hpp" -#include "interface_info.hpp" +#include +#include -#include #include // for itoa +#include #include // for addrinfo #ifndef _WIN32 -#include -#include #include +#include +#include #else #include + #include #include #endif diff --git a/llarp/net/net_int.cpp b/llarp/net/net_int.cpp index 2628200ec1..bfc0ceac48 100644 --- a/llarp/net/net_int.cpp +++ b/llarp/net/net_int.cpp @@ -1,10 +1,12 @@ #include "net_int.hpp" + #include "ip.hpp" -#include -#include #include +#include +#include + namespace llarp { namespace net diff --git a/llarp/net/net_int.hpp b/llarp/net/net_int.hpp index 447dc4e320..e703471128 100644 --- a/llarp/net/net_int.hpp +++ b/llarp/net/net_int.hpp @@ -2,25 +2,28 @@ // for addrinfo #ifndef _WIN32 -#include -#include #include +#include +#include #else #include + #include #define inet_aton(x, y) inet_pton(AF_INET, x, y) #endif +#include "net.h" +#include "uint128.hpp" + #include + #include + #include // for itoa #include #include -#include "net.h" -#include "uint128.hpp" - namespace llarp { template diff --git a/llarp/net/posix.cpp b/llarp/net/posix.cpp index e20243d202..5bf8c85f18 100644 --- a/llarp/net/posix.cpp +++ b/llarp/net/posix.cpp @@ -1,8 +1,8 @@ -#include - +#include "ip_range.hpp" #include "net.hpp" #include "net_if.hpp" -#include "ip_range.hpp" + +#include #ifdef ANDROID #include diff --git a/llarp/net/sock_addr.cpp b/llarp/net/sock_addr.cpp index 5f25830e01..288fba9a18 100644 --- a/llarp/net/sock_addr.cpp +++ b/llarp/net/sock_addr.cpp @@ -1,13 +1,14 @@ #include "sock_addr.hpp" -#include -#include -#include - -#include "ip_range.hpp" #include "ip.hpp" -#include "net_bits.hpp" +#include "ip_range.hpp" #include "net.hpp" +#include "net_bits.hpp" + +#include +#include + +#include namespace llarp { diff --git a/llarp/net/sock_addr.hpp b/llarp/net/sock_addr.hpp index b44d49f1cc..fe0db0f615 100644 --- a/llarp/net/sock_addr.hpp +++ b/llarp/net/sock_addr.hpp @@ -1,20 +1,23 @@ #pragma once #ifndef _WIN32 -#include #include +#include #else #include + #include #include #endif -#include +#include "net_int.hpp" + #include -#include -#include -#include "net_int.hpp" +#include + +#include +#include namespace llarp { diff --git a/llarp/net/traffic_policy.hpp b/llarp/net/traffic_policy.hpp index ebdaa539d9..b0f4e74c8b 100644 --- a/llarp/net/traffic_policy.hpp +++ b/llarp/net/traffic_policy.hpp @@ -1,11 +1,13 @@ #pragma once +#include "ip_packet.hpp" +#include "ip_range.hpp" + +#include + #include -#include -#include "ip_range.hpp" -#include "ip_packet.hpp" -#include "llarp/util/status.hpp" +#include namespace llarp::net { diff --git a/llarp/net/uint128.hpp b/llarp/net/uint128.hpp index dde7c83afc..c6534798ef 100644 --- a/llarp/net/uint128.hpp +++ b/llarp/net/uint128.hpp @@ -1,11 +1,11 @@ #pragma once +#include + +#include #include #include -#include #include -#include - namespace llarp { /// 128-bit unsigned integer. Does *not* support diff --git a/llarp/net/win32.cpp b/llarp/net/win32.cpp index 1bcaa86df4..b487988854 100644 --- a/llarp/net/win32.cpp +++ b/llarp/net/win32.cpp @@ -1,19 +1,18 @@ +#include "ip.hpp" +#include "ip_range.hpp" #include "net.hpp" - #include "net_if.hpp" -#include -#include -#include "ip.hpp" -#include "ip_range.hpp" +#include #include #include +#include #include -#include #include #include +#include #include namespace llarp::net diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index c12c2f7314..5ea66233e2 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -1,14 +1,14 @@ #include "nodedb.hpp" +#include "crypto/types.hpp" +#include "dht/kademlia.hpp" +#include "router_contact.hpp" +#include "util/time.hpp" + #include #include #include -#include "router_contact.hpp" -#include "crypto/types.hpp" -#include "util/time.hpp" -#include "dht/kademlia.hpp" - static const char skiplist_subdirs[] = "0123456789abcdef"; static const std::string RC_FILE_EXT = ".signed"; diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index 10eb836131..b81d896930 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -1,22 +1,23 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include - +#include "crypto/crypto.hpp" +#include "dht/key.hpp" #include "router_contact.hpp" #include "router_id.hpp" #include "util/common.hpp" #include "util/fs.hpp" -#include "dht/key.hpp" -#include "crypto/crypto.hpp" -#include "util/thread/threading.hpp" #include "util/thread/annotations.hpp" +#include "util/thread/threading.hpp" + +#include + +#include +#include +#include +#include +#include +#include +#include namespace llarp { diff --git a/llarp/path/abstracthophandler.cpp b/llarp/path/abstracthophandler.cpp index b4d88bccb5..1c53fd304c 100644 --- a/llarp/path/abstracthophandler.cpp +++ b/llarp/path/abstracthophandler.cpp @@ -1,4 +1,5 @@ #include "abstracthophandler.hpp" + #include namespace llarp::path diff --git a/llarp/path/abstracthophandler.hpp b/llarp/path/abstracthophandler.hpp index f600116711..0c9963bb97 100644 --- a/llarp/path/abstracthophandler.hpp +++ b/llarp/path/abstracthophandler.hpp @@ -1,12 +1,13 @@ #pragma once -#include -#include #include -#include +#include #include -#include +#include +#include + #include +#include struct llarp_buffer_t; diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 42aa214ab9..4af30f54fe 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -1,5 +1,9 @@ #pragma once +#include "abstracthophandler.hpp" +#include "path_types.hpp" +#include "pathset.hpp" + #include #include #include @@ -10,6 +14,7 @@ #include #include #include + #include #include #include @@ -18,10 +23,6 @@ #include #include -#include "abstracthophandler.hpp" -#include "path_types.hpp" -#include "pathset.hpp" - namespace llarp { struct Router; diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index ef4ebbe7a1..e7fd3364d1 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -1,6 +1,7 @@ -#include "path.hpp" #include "path_context.hpp" +#include "path.hpp" + #include namespace llarp::path diff --git a/llarp/path/path_context.hpp b/llarp/path/path_context.hpp index 88911ab8fe..cc2137ddec 100644 --- a/llarp/path/path_context.hpp +++ b/llarp/path/path_context.hpp @@ -1,18 +1,20 @@ #pragma once +#include "abstracthophandler.hpp" +#include "path_types.hpp" +#include "pathset.hpp" +#include "transit_hop.hpp" + #include +#include #include #include #include #include + #include #include -#include "abstracthophandler.hpp" -#include "path_types.hpp" -#include "pathset.hpp" -#include "transit_hop.hpp" - namespace llarp { struct Router; diff --git a/llarp/path/path_types.hpp b/llarp/path/path_types.hpp index 1a356e063c..374660e556 100644 --- a/llarp/path/path_types.hpp +++ b/llarp/path/path_types.hpp @@ -2,9 +2,9 @@ #include #include -#include #include #include +#include namespace { diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index e3d312c3c5..7b78ead31a 100644 --- a/llarp/path/pathbuilder.cpp +++ b/llarp/path/pathbuilder.cpp @@ -1,17 +1,17 @@ #include "pathbuilder.hpp" +#include "path.hpp" +#include "path_context.hpp" + #include #include #include #include #include -#include #include +#include #include -#include "path.hpp" -#include "path_context.hpp" - namespace llarp { namespace diff --git a/llarp/path/pathbuilder.hpp b/llarp/path/pathbuilder.hpp index 1886e57d21..480f7df6d9 100644 --- a/llarp/path/pathbuilder.hpp +++ b/llarp/path/pathbuilder.hpp @@ -1,8 +1,9 @@ #pragma once #include "pathset.hpp" -#include + #include +#include #include #include diff --git a/llarp/path/pathset.cpp b/llarp/path/pathset.cpp index df92ef7c12..f17baae56e 100644 --- a/llarp/path/pathset.cpp +++ b/llarp/path/pathset.cpp @@ -1,6 +1,7 @@ -#include "path.hpp" #include "pathset.hpp" +#include "path.hpp" + namespace llarp::path { PathSet::PathSet(size_t num) : numDesiredPaths(num) diff --git a/llarp/path/pathset.hpp b/llarp/path/pathset.hpp index 9c98281277..914c97da11 100644 --- a/llarp/path/pathset.hpp +++ b/llarp/path/pathset.hpp @@ -1,20 +1,21 @@ #pragma once +#include "path_types.hpp" + #include -#include #include #include +#include #include #include #include + #include #include #include #include #include -#include "path_types.hpp" - namespace std { template <> diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index a228516c70..76081d50ca 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -1,8 +1,8 @@ +#include "transit_hop.hpp" + #include #include -#include "transit_hop.hpp" - namespace llarp::path { std::string diff --git a/llarp/pow.cpp b/llarp/pow.cpp index b0ae278986..2051fbc7aa 100644 --- a/llarp/pow.cpp +++ b/llarp/pow.cpp @@ -1,9 +1,9 @@ #include "pow.hpp" -#include - #include "crypto/crypto.hpp" +#include + namespace llarp { PoW::~PoW() = default; diff --git a/llarp/profiling.cpp b/llarp/profiling.cpp index e1fcc9121f..3ae00f3872 100644 --- a/llarp/profiling.cpp +++ b/llarp/profiling.cpp @@ -1,10 +1,10 @@ #include "profiling.hpp" +#include "util/file.hpp" + #include #include -#include "util/file.hpp" - using oxenc::bt_dict_consumer; using oxenc::bt_dict_producer; diff --git a/llarp/profiling.hpp b/llarp/profiling.hpp index 4e4c7a8c44..b375ff7e57 100644 --- a/llarp/profiling.hpp +++ b/llarp/profiling.hpp @@ -1,12 +1,12 @@ #pragma once -#include - #include "path/path.hpp" #include "router_id.hpp" #include "util/bencode.hpp" -#include "util/thread/threading.hpp" #include "util/thread/annotations.hpp" +#include "util/thread/threading.hpp" + +#include namespace oxenc { diff --git a/llarp/router/rc_gossiper.hpp b/llarp/router/rc_gossiper.hpp index bd580646e1..3678f06326 100644 --- a/llarp/router/rc_gossiper.hpp +++ b/llarp/router/rc_gossiper.hpp @@ -1,9 +1,9 @@ #pragma once +#include #include #include -#include "llarp/router_id.hpp" namespace llarp { diff --git a/llarp/router/rc_lookup_handler.cpp b/llarp/router/rc_lookup_handler.cpp index ac705a88a5..e10684a79e 100644 --- a/llarp/router/rc_lookup_handler.cpp +++ b/llarp/router/rc_lookup_handler.cpp @@ -1,15 +1,17 @@ +#include "rc_lookup_handler.hpp" + +#include "router.hpp" + +#include #include #include -#include -#include +#include #include +#include #include -#include -#include -#include -#include "rc_lookup_handler.hpp" -#include "router.hpp" +#include +#include namespace llarp { diff --git a/llarp/router/rc_lookup_handler.hpp b/llarp/router/rc_lookup_handler.hpp index 5c1ea079fd..5d224f2f9f 100644 --- a/llarp/router/rc_lookup_handler.hpp +++ b/llarp/router/rc_lookup_handler.hpp @@ -2,11 +2,12 @@ #include #include + #include -#include +#include #include +#include #include -#include struct llarp_dht_context; diff --git a/llarp/router/route_poker.cpp b/llarp/router/route_poker.cpp index 5bb33a1334..76c948d1ca 100644 --- a/llarp/router/route_poker.cpp +++ b/llarp/router/route_poker.cpp @@ -1,9 +1,9 @@ #include "route_poker.hpp" -#include - #include "router.hpp" +#include + namespace llarp { static auto logcat = log::Cat("route-poker"); diff --git a/llarp/router/route_poker.hpp b/llarp/router/route_poker.hpp index c272a28830..bbc281f033 100644 --- a/llarp/router/route_poker.hpp +++ b/llarp/router/route_poker.hpp @@ -1,11 +1,13 @@ #pragma once #include -#include -#include -#include + +#include + #include #include +#include +#include namespace llarp { diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 7aad6ca2e9..1aa99d9a1f 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -1,6 +1,5 @@ #include "router.hpp" -#include #include #include #include @@ -10,15 +9,17 @@ #include #include #include +#include #include #include #include -#include + #include #include +#include +#include #include #include -#include #if defined(ANDROID) || defined(IOS) #include #endif @@ -28,6 +29,7 @@ #endif #include + #include static constexpr std::chrono::milliseconds ROUTER_TICK_INTERVAL = 250ms; diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index f622ccde4c..6354b37c62 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -1,8 +1,13 @@ #pragma once +#include "rc_gossiper.hpp" +#include "rc_lookup_handler.hpp" +#include "route_poker.hpp" + #include #include #include +#include #include #include #include @@ -12,31 +17,28 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include #include #include -#include + #include -#include + #include #include #include #include #include +#include #include #include -#include "rc_gossiper.hpp" -#include "rc_lookup_handler.hpp" -#include "route_poker.hpp" - /* TONUKE: - hidden_service_context diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index e5396af499..c87251adb8 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -1,14 +1,14 @@ #include "router_contact.hpp" -#include - #include "constants/version.hpp" #include "crypto/crypto.hpp" #include "net/net.hpp" #include "util/bencode.hpp" #include "util/buffer.hpp" -#include "util/time.hpp" #include "util/file.hpp" +#include "util/time.hpp" + +#include namespace llarp { diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index fc8a009251..7e8e1fdcef 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -1,20 +1,22 @@ #pragma once -#include -#include +#include "router_version.hpp" + +#include +#include +#include +#include +#include +#include +#include + #include +#include +#include + #include #include -#include "llarp/constants/version.hpp" -#include "llarp/crypto/types.hpp" -#include "llarp/net/exit_info.hpp" -#include "llarp/util/aligned.hpp" -#include "llarp/util/bencode.hpp" -#include "llarp/util/status.hpp" -#include "router_version.hpp" -#include "llarp/dns/srv_data.hpp" - #define MAX_RC_SIZE (1024) namespace oxenc diff --git a/llarp/router_id.cpp b/llarp/router_id.cpp index 9875251370..d8f1e15815 100644 --- a/llarp/router_id.cpp +++ b/llarp/router_id.cpp @@ -1,4 +1,5 @@ #include "router_id.hpp" + #include namespace llarp diff --git a/llarp/router_version.hpp b/llarp/router_version.hpp index d9fa722006..97e2a7bd40 100644 --- a/llarp/router_version.hpp +++ b/llarp/router_version.hpp @@ -1,12 +1,12 @@ #pragma once -#include - -#include "util/bencode.hpp" -#include "constants/version.hpp" #include "constants/proto.hpp" +#include "constants/version.hpp" +#include "util/bencode.hpp" #include "util/formattable.hpp" +#include + namespace { static auto llarp_cat = llarp::log::Cat("lokinet.llarp"); diff --git a/llarp/rpc/endpoint_rpc.hpp b/llarp/rpc/endpoint_rpc.hpp index 3663e3ac45..73cfd12709 100644 --- a/llarp/rpc/endpoint_rpc.hpp +++ b/llarp/rpc/endpoint_rpc.hpp @@ -2,6 +2,7 @@ #include #include + #include namespace llarp::service diff --git a/llarp/rpc/json_binary_proxy.cpp b/llarp/rpc/json_binary_proxy.cpp index cc766dc22f..2cbdcbbec9 100644 --- a/llarp/rpc/json_binary_proxy.cpp +++ b/llarp/rpc/json_binary_proxy.cpp @@ -1,6 +1,7 @@ #include "json_binary_proxy.hpp" -#include + #include +#include namespace llarp::rpc { diff --git a/llarp/rpc/json_binary_proxy.hpp b/llarp/rpc/json_binary_proxy.hpp index dc4800dfb1..08b3c4b8b3 100644 --- a/llarp/rpc/json_binary_proxy.hpp +++ b/llarp/rpc/json_binary_proxy.hpp @@ -1,7 +1,8 @@ #pragma once -#include #include + +#include #include using namespace std::literals; diff --git a/llarp/rpc/json_conversions.cpp b/llarp/rpc/json_conversions.cpp index d3e036468e..838d285f86 100644 --- a/llarp/rpc/json_conversions.cpp +++ b/llarp/rpc/json_conversions.cpp @@ -1,4 +1,5 @@ #include "json_conversions.hpp" + #include namespace llarp diff --git a/llarp/rpc/json_conversions.hpp b/llarp/rpc/json_conversions.hpp index 50d2426eb6..f4e98cccb9 100644 --- a/llarp/rpc/json_conversions.hpp +++ b/llarp/rpc/json_conversions.hpp @@ -1,9 +1,10 @@ #pragma once +#include "json_binary_proxy.hpp" + #include -#include -#include "json_binary_proxy.hpp" +#include namespace llarp { diff --git a/llarp/rpc/lokid_rpc_client.cpp b/llarp/rpc/lokid_rpc_client.cpp index 65c2df893b..dfbcb253f3 100644 --- a/llarp/rpc/lokid_rpc_client.cpp +++ b/llarp/rpc/lokid_rpc_client.cpp @@ -1,9 +1,11 @@ #include "lokid_rpc_client.hpp" -#include #include +#include + #include #include + #include namespace llarp::rpc diff --git a/llarp/rpc/lokid_rpc_client.hpp b/llarp/rpc/lokid_rpc_client.hpp index bc13e18ad2..ebd6f9e798 100644 --- a/llarp/rpc/lokid_rpc_client.hpp +++ b/llarp/rpc/lokid_rpc_client.hpp @@ -1,12 +1,13 @@ #pragma once -#include -#include -#include #include #include +#include #include +#include +#include + namespace llarp { struct Router; diff --git a/llarp/rpc/param_parser.hpp b/llarp/rpc/param_parser.hpp index 2347e297ae..4aaeb348eb 100644 --- a/llarp/rpc/param_parser.hpp +++ b/llarp/rpc/param_parser.hpp @@ -3,12 +3,14 @@ #include "json_binary_proxy.hpp" #include "json_bt.hpp" #include "json_conversions.hpp" -#include + #include +#include + +#include #include #include #include -#include namespace llarp::rpc { diff --git a/llarp/rpc/rpc_request.hpp b/llarp/rpc/rpc_request.hpp index 8801298c8c..ef63bb734e 100644 --- a/llarp/rpc/rpc_request.hpp +++ b/llarp/rpc/rpc_request.hpp @@ -1,16 +1,19 @@ #pragma once -#include "rpc_server.hpp" -#include "rpc_request_parser.hpp" +#include "json_bt.hpp" #include "rpc_request_decorators.hpp" #include "rpc_request_definitions.hpp" -#include "json_bt.hpp" -#include +#include "rpc_request_parser.hpp" +#include "rpc_server.hpp" + #include #include -#include -#include + #include +#include +#include + +#include namespace llarp::rpc { diff --git a/llarp/rpc/rpc_request_decorators.hpp b/llarp/rpc/rpc_request_decorators.hpp index 5973c06dcf..3093de930a 100644 --- a/llarp/rpc/rpc_request_decorators.hpp +++ b/llarp/rpc/rpc_request_decorators.hpp @@ -2,12 +2,15 @@ #include "json_binary_proxy.hpp" #include "json_bt.hpp" -#include -#include + #include -#include -#include + +#include #include +#include +#include + +#include namespace tools { diff --git a/llarp/rpc/rpc_request_definitions.hpp b/llarp/rpc/rpc_request_definitions.hpp index 01b4a8872d..0c6b434424 100644 --- a/llarp/rpc/rpc_request_definitions.hpp +++ b/llarp/rpc/rpc_request_definitions.hpp @@ -2,17 +2,18 @@ #include "rpc_request_decorators.hpp" +#include #include #include #include #include #include -#include -#include -#include -#include #include +#include +#include + +#include #include #include diff --git a/llarp/rpc/rpc_request_parser.cpp b/llarp/rpc/rpc_request_parser.cpp index 3cb40bffd2..92bafbf4f1 100644 --- a/llarp/rpc/rpc_request_parser.cpp +++ b/llarp/rpc/rpc_request_parser.cpp @@ -1,8 +1,9 @@ #include "rpc_request_parser.hpp" -#include "llarp/rpc/rpc_request_definitions.hpp" #include "param_parser.hpp" +#include + namespace llarp::rpc { using nlohmann::json; @@ -103,4 +104,4 @@ namespace llarp::rpc config.request.ini); } -} // namespace llarp::rpc \ No newline at end of file +} // namespace llarp::rpc diff --git a/llarp/rpc/rpc_request_parser.hpp b/llarp/rpc/rpc_request_parser.hpp index 788bad17d5..71ca0d0098 100644 --- a/llarp/rpc/rpc_request_parser.hpp +++ b/llarp/rpc/rpc_request_parser.hpp @@ -1,12 +1,14 @@ #pragma once +#include "rpc_request_definitions.hpp" + #include -#include -#include + #include -#include +#include +#include -#include "rpc_request_definitions.hpp" +#include namespace llarp::rpc { diff --git a/llarp/rpc/rpc_server.cpp b/llarp/rpc/rpc_server.cpp index 4b646914d0..9e7581e50d 100644 --- a/llarp/rpc/rpc_server.cpp +++ b/llarp/rpc/rpc_server.cpp @@ -1,4 +1,5 @@ #include "rpc_server.hpp" + #include "rpc_request.hpp" #include @@ -7,8 +8,8 @@ #include #include #include -#include #include +#include #include #include diff --git a/llarp/rpc/rpc_server.hpp b/llarp/rpc/rpc_server.hpp index 9be8962557..895b3120e4 100644 --- a/llarp/rpc/rpc_server.hpp +++ b/llarp/rpc/rpc_server.hpp @@ -1,18 +1,19 @@ #pragma once +#include "json_bt.hpp" +#include "rpc_request_definitions.hpp" + #include #include -#include -#include -#include #include +#include +#include +#include + #include #include -#include "rpc_request_definitions.hpp" -#include "json_bt.hpp" - namespace llarp { struct Router; diff --git a/llarp/service/address.cpp b/llarp/service/address.cpp index 704b193c9d..2f18907deb 100644 --- a/llarp/service/address.cpp +++ b/llarp/service/address.cpp @@ -1,6 +1,9 @@ #include "address.hpp" + #include + #include + #include namespace llarp::service diff --git a/llarp/service/address.hpp b/llarp/service/address.hpp index e65b4c6831..bef3365c49 100644 --- a/llarp/service/address.hpp +++ b/llarp/service/address.hpp @@ -6,10 +6,10 @@ #include #include +#include #include #include #include -#include namespace llarp { diff --git a/llarp/service/async_key_exchange.cpp b/llarp/service/async_key_exchange.cpp index fbb42423c0..d5d8bd1402 100644 --- a/llarp/service/async_key_exchange.cpp +++ b/llarp/service/async_key_exchange.cpp @@ -1,9 +1,11 @@ #include "async_key_exchange.hpp" + #include "endpoint.hpp" #include #include #include + #include namespace llarp::service diff --git a/llarp/service/async_key_exchange.hpp b/llarp/service/async_key_exchange.hpp index 3ab0b8f4e0..254818e347 100644 --- a/llarp/service/async_key_exchange.hpp +++ b/llarp/service/async_key_exchange.hpp @@ -1,10 +1,10 @@ #pragma once -#include - #include "identity.hpp" #include "protocol.hpp" +#include + namespace llarp::service { struct AsyncKeyExchange : public std::enable_shared_from_this diff --git a/llarp/service/auth.cpp b/llarp/service/auth.cpp index 71e2f1509a..b5a6c97e81 100644 --- a/llarp/service/auth.cpp +++ b/llarp/service/auth.cpp @@ -1,9 +1,10 @@ #include "auth.hpp" + #include "protocol.hpp" #include -#include #include +#include #include diff --git a/llarp/service/auth.hpp b/llarp/service/auth.hpp index 7f18e31049..85b7d0951c 100644 --- a/llarp/service/auth.hpp +++ b/llarp/service/auth.hpp @@ -1,10 +1,11 @@ #pragma once +#include "address.hpp" + #include + +#include #include #include -#include - -#include "address.hpp" namespace llarp { diff --git a/llarp/service/context.cpp b/llarp/service/context.cpp index abea6ca496..16b58afbfe 100644 --- a/llarp/service/context.cpp +++ b/llarp/service/context.cpp @@ -1,10 +1,11 @@ #include "context.hpp" +#include "endpoint.hpp" + #include #include -#include -#include "endpoint.hpp" +#include namespace llarp::service { diff --git a/llarp/service/context.hpp b/llarp/service/context.hpp index d975697d3e..cf459273ca 100644 --- a/llarp/service/context.hpp +++ b/llarp/service/context.hpp @@ -1,11 +1,12 @@ #pragma once +#include "endpoint.hpp" + +#include #include #include -#include -#include -#include "endpoint.hpp" +#include /* TODO: diff --git a/llarp/service/convotag.hpp b/llarp/service/convotag.hpp index 431d4546e5..e74ffca644 100644 --- a/llarp/service/convotag.hpp +++ b/llarp/service/convotag.hpp @@ -1,8 +1,8 @@ #pragma once -#include -#include #include +#include +#include namespace llarp::service { diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index ae124233d4..3b1a4dc443 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -1,30 +1,31 @@ #include "endpoint.hpp" +#include "auth.hpp" +#include "endpoint_state.hpp" +#include "endpoint_util.hpp" +#include "info.hpp" +#include "outbound_context.hpp" +#include "protocol.hpp" +#include "protocol_type.hpp" + #include #include #include #include #include #include -#include #include -#include +#include #include +#include #include #include + #include #include #include #include -#include "endpoint_state.hpp" -#include "endpoint_util.hpp" -#include "auth.hpp" -#include "outbound_context.hpp" -#include "protocol.hpp" -#include "info.hpp" -#include "protocol_type.hpp" - namespace llarp::service { static auto logcat = log::Cat("endpoint"); diff --git a/llarp/service/endpoint.hpp b/llarp/service/endpoint.hpp index b974fa4eb5..63bedc6d70 100644 --- a/llarp/service/endpoint.hpp +++ b/llarp/service/endpoint.hpp @@ -1,26 +1,24 @@ #pragma once +#include #include #include #include #include #include #include -#include -// --- begin kitchen sink headers ---- #include +#include +#include #include #include #include #include #include -#include -#include -#include -// ----- end kitchen sink headers ----- +#include +#include #include -#include -#include + #include #include #include diff --git a/llarp/service/endpoint_state.hpp b/llarp/service/endpoint_state.hpp index ba42a22bf4..cc57e4b8f2 100644 --- a/llarp/service/endpoint_state.hpp +++ b/llarp/service/endpoint_state.hpp @@ -1,22 +1,24 @@ #pragma once +#include "address.hpp" +#include "endpoint_types.hpp" +#include "lns_tracker.hpp" +#include "pendingbuffer.hpp" +#include "router_lookup_job.hpp" +#include "session.hpp" + #include #include #include #include + #include + #include #include #include #include -#include "address.hpp" -#include "pendingbuffer.hpp" -#include "router_lookup_job.hpp" -#include "session.hpp" -#include "endpoint_types.hpp" -#include "lns_tracker.hpp" - namespace llarp::service { struct EndpointState diff --git a/llarp/service/endpoint_types.hpp b/llarp/service/endpoint_types.hpp index 2999344744..3b191a2b32 100644 --- a/llarp/service/endpoint_types.hpp +++ b/llarp/service/endpoint_types.hpp @@ -3,6 +3,7 @@ #include "pendingbuffer.hpp" #include "router_lookup_job.hpp" #include "session.hpp" + #include #include diff --git a/llarp/service/identity.hpp b/llarp/service/identity.hpp index 9c53cba6f1..70b1919f3f 100644 --- a/llarp/service/identity.hpp +++ b/llarp/service/identity.hpp @@ -1,16 +1,17 @@ #pragma once +#include "info.hpp" +#include "intro_set.hpp" +#include "vanity.hpp" + #include #include #include #include + #include #include -#include "info.hpp" -#include "intro_set.hpp" -#include "vanity.hpp" - namespace llarp::service { // private keys diff --git a/llarp/service/info.cpp b/llarp/service/info.cpp index f45f5b93df..3c9a9f0247 100644 --- a/llarp/service/info.cpp +++ b/llarp/service/info.cpp @@ -1,9 +1,9 @@ #include "info.hpp" -#include - #include "address.hpp" +#include + namespace llarp::service { bool diff --git a/llarp/service/info.hpp b/llarp/service/info.hpp index 5e97e34ad3..893e1fe641 100644 --- a/llarp/service/info.hpp +++ b/llarp/service/info.hpp @@ -1,12 +1,14 @@ #pragma once -#include +#include "address.hpp" +#include "vanity.hpp" + #include #include -#include -#include "address.hpp" -#include "vanity.hpp" +#include + +#include namespace { diff --git a/llarp/service/intro.cpp b/llarp/service/intro.cpp index c239da5aba..5e25e6b62a 100644 --- a/llarp/service/intro.cpp +++ b/llarp/service/intro.cpp @@ -1,4 +1,5 @@ #include "intro.hpp" + #include namespace llarp::service diff --git a/llarp/service/intro.hpp b/llarp/service/intro.hpp index 0ec46b35d5..3c4326e360 100644 --- a/llarp/service/intro.hpp +++ b/llarp/service/intro.hpp @@ -1,10 +1,12 @@ #pragma once -#include #include #include #include #include + +#include + #include namespace diff --git a/llarp/service/intro_set.cpp b/llarp/service/intro_set.cpp index bc2db09daf..93cd5af30c 100644 --- a/llarp/service/intro_set.cpp +++ b/llarp/service/intro_set.cpp @@ -1,6 +1,7 @@ #include "intro_set.hpp" #include + #include namespace llarp::service diff --git a/llarp/service/intro_set.hpp b/llarp/service/intro_set.hpp index 352d98f2ce..de11118f87 100644 --- a/llarp/service/intro_set.hpp +++ b/llarp/service/intro_set.hpp @@ -1,24 +1,25 @@ #pragma once +#include "info.hpp" +#include "intro.hpp" +#include "protocol_type.hpp" +#include "tag.hpp" + #include -#include -#include -#include -#include #include #include #include -#include +#include +#include +#include +#include + #include #include #include +#include #include -#include "info.hpp" -#include "intro.hpp" -#include "tag.hpp" -#include "protocol_type.hpp" - namespace llarp::service { constexpr std::size_t MAX_INTROSET_SIZE = 4096; diff --git a/llarp/service/lns_tracker.hpp b/llarp/service/lns_tracker.hpp index 64fb1a3cdd..c1dab8a215 100644 --- a/llarp/service/lns_tracker.hpp +++ b/llarp/service/lns_tracker.hpp @@ -1,14 +1,16 @@ #pragma once +#include "address.hpp" + #include + #include + #include #include +#include #include #include -#include - -#include "address.hpp" namespace llarp::service { diff --git a/llarp/service/name.cpp b/llarp/service/name.cpp index 37c0afb1ef..45c76c512c 100644 --- a/llarp/service/name.cpp +++ b/llarp/service/name.cpp @@ -1,4 +1,5 @@ #include "name.hpp" + #include #include diff --git a/llarp/service/name.hpp b/llarp/service/name.hpp index 76e203b3c0..a34969f72e 100644 --- a/llarp/service/name.hpp +++ b/llarp/service/name.hpp @@ -1,8 +1,8 @@ #pragma once -#include - #include "address.hpp" +#include + namespace llarp::service { struct EncryptedName diff --git a/llarp/service/outbound_context.cpp b/llarp/service/outbound_context.cpp index 5588de1187..9c05379154 100644 --- a/llarp/service/outbound_context.cpp +++ b/llarp/service/outbound_context.cpp @@ -1,14 +1,15 @@ #include "outbound_context.hpp" -#include -#include -#include - #include "async_key_exchange.hpp" #include "endpoint.hpp" #include "endpoint_util.hpp" #include "protocol_type.hpp" +#include + +#include +#include + namespace llarp::service { bool diff --git a/llarp/service/outbound_context.hpp b/llarp/service/outbound_context.hpp index 802d6a9107..2b66715eea 100644 --- a/llarp/service/outbound_context.hpp +++ b/llarp/service/outbound_context.hpp @@ -4,6 +4,7 @@ #include #include #include + #include #include diff --git a/llarp/service/pendingbuffer.hpp b/llarp/service/pendingbuffer.hpp index 827b2fab10..f32e66cd37 100644 --- a/llarp/service/pendingbuffer.hpp +++ b/llarp/service/pendingbuffer.hpp @@ -1,7 +1,9 @@ #pragma once #include "protocol.hpp" + #include + #include namespace llarp::service diff --git a/llarp/service/protocol.cpp b/llarp/service/protocol.cpp index 1ec6783a62..755554a24b 100644 --- a/llarp/service/protocol.cpp +++ b/llarp/service/protocol.cpp @@ -1,11 +1,12 @@ #include "protocol.hpp" +#include "endpoint.hpp" + #include -#include #include -#include +#include -#include "endpoint.hpp" +#include namespace llarp::service { diff --git a/llarp/service/protocol.hpp b/llarp/service/protocol.hpp index bc85f0c285..d3d656e2a7 100644 --- a/llarp/service/protocol.hpp +++ b/llarp/service/protocol.hpp @@ -1,17 +1,19 @@ #pragma once +#include "identity.hpp" +#include "info.hpp" +#include "intro.hpp" +#include "protocol_type.hpp" + #include #include +#include +#include #include #include #include -#include -#include -#include "protocol_type.hpp" -#include "identity.hpp" -#include "info.hpp" -#include "intro.hpp" +#include struct llarp_threadpool; diff --git a/llarp/service/protocol_type.hpp b/llarp/service/protocol_type.hpp index 3864717be0..fc85b9e2cb 100644 --- a/llarp/service/protocol_type.hpp +++ b/llarp/service/protocol_type.hpp @@ -1,9 +1,9 @@ #pragma once -#include +#include +#include #include -#include namespace llarp::service { diff --git a/llarp/service/router_lookup_job.cpp b/llarp/service/router_lookup_job.cpp index 517baac700..3c988a73b4 100644 --- a/llarp/service/router_lookup_job.cpp +++ b/llarp/service/router_lookup_job.cpp @@ -1,6 +1,7 @@ #include "router_lookup_job.hpp" #include "endpoint.hpp" + #include namespace llarp diff --git a/llarp/service/session.hpp b/llarp/service/session.hpp index a811e2c4fa..b9d4b051eb 100644 --- a/llarp/service/session.hpp +++ b/llarp/service/session.hpp @@ -1,13 +1,13 @@ #pragma once +#include "info.hpp" +#include "intro.hpp" + #include #include #include #include -#include "info.hpp" -#include "intro.hpp" - namespace llarp::service { static constexpr auto SessionLifetime = path::DEFAULT_LIFETIME * 2; diff --git a/llarp/service/tag.hpp b/llarp/service/tag.hpp index 64a9493407..a4e3dba4eb 100644 --- a/llarp/service/tag.hpp +++ b/llarp/service/tag.hpp @@ -3,6 +3,7 @@ #include #include #include + #include namespace llarp diff --git a/llarp/simulation/sim_context.cpp b/llarp/simulation/sim_context.cpp index 329e8f8497..c36afdefa0 100644 --- a/llarp/simulation/sim_context.cpp +++ b/llarp/simulation/sim_context.cpp @@ -1,4 +1,5 @@ #include "sim_context.hpp" + #include namespace llarp diff --git a/llarp/util/aligned.hpp b/llarp/util/aligned.hpp index b28199d19d..f62485978c 100644 --- a/llarp/util/aligned.hpp +++ b/llarp/util/aligned.hpp @@ -1,11 +1,13 @@ #pragma once #include "bencode.h" -#include + #include +#include #include +#include #include #include #include @@ -13,7 +15,6 @@ #include #include #include -#include extern "C" { diff --git a/llarp/util/bencode.cpp b/llarp/util/bencode.cpp index 2b94c52fb6..6426e15dea 100644 --- a/llarp/util/bencode.cpp +++ b/llarp/util/bencode.cpp @@ -1,7 +1,7 @@ #include "bencode.hpp" -#include #include +#include bool bencode_read_integer(struct llarp_buffer_t* buffer, uint64_t* result) diff --git a/llarp/util/bencode.h b/llarp/util/bencode.h index 7770fc8ebd..b017da1102 100644 --- a/llarp/util/bencode.h +++ b/llarp/util/bencode.h @@ -1,12 +1,13 @@ #pragma once -#include -#include -#include - #include "buffer.hpp" #include "common.hpp" +#include + +#include +#include + /** * bencode.h * diff --git a/llarp/util/bencode.hpp b/llarp/util/bencode.hpp index f54f198891..aae0fe3b1e 100644 --- a/llarp/util/bencode.hpp +++ b/llarp/util/bencode.hpp @@ -1,16 +1,18 @@ #pragma once +#include "bencode.h" +#include "buffer.hpp" +#include "file.hpp" +#include "mem.hpp" + #include + #include -#include + #include +#include #include -#include "buffer.hpp" -#include "bencode.h" -#include "file.hpp" -#include "mem.hpp" - namespace llarp { static auto ben_cat = log::Cat("stupid.bencode"); diff --git a/llarp/util/bits.hpp b/llarp/util/bits.hpp index 5aae7e47c1..2a1240ecb2 100644 --- a/llarp/util/bits.hpp +++ b/llarp/util/bits.hpp @@ -1,12 +1,13 @@ #pragma once +#include +#include + #include #include +#include #include #include -#include -#include -#include namespace llarp { diff --git a/llarp/util/buffer.cpp b/llarp/util/buffer.cpp index 7dc3d747c4..1d2de0042a 100644 --- a/llarp/util/buffer.cpp +++ b/llarp/util/buffer.cpp @@ -1,4 +1,5 @@ #include "buffer.hpp" + #include #include diff --git a/llarp/util/buffer.hpp b/llarp/util/buffer.hpp index d9f87d8e7a..2cfa8f3a6f 100644 --- a/llarp/util/buffer.hpp +++ b/llarp/util/buffer.hpp @@ -1,20 +1,20 @@ #pragma once -#include +#include "common.hpp" +#include "mem.h" +#include "types.hpp" + +#include #include -#include #include #include #include -#include -#include +#include #include -#include #include - -#include "common.hpp" -#include "mem.h" -#include "types.hpp" +#include +#include +#include namespace llarp { diff --git a/llarp/util/decaying_hashset.hpp b/llarp/util/decaying_hashset.hpp index e7c0a0a72c..36bf4f1a94 100644 --- a/llarp/util/decaying_hashset.hpp +++ b/llarp/util/decaying_hashset.hpp @@ -1,6 +1,7 @@ #pragma once #include "time.hpp" + #include namespace llarp diff --git a/llarp/util/decaying_hashtable.hpp b/llarp/util/decaying_hashtable.hpp index 1a6b23953b..ea00092eba 100644 --- a/llarp/util/decaying_hashtable.hpp +++ b/llarp/util/decaying_hashtable.hpp @@ -1,6 +1,7 @@ #pragma once #include "time.hpp" + #include namespace llarp::util diff --git a/llarp/util/file.cpp b/llarp/util/file.cpp index a207b22884..ff929d0166 100644 --- a/llarp/util/file.cpp +++ b/llarp/util/file.cpp @@ -1,8 +1,10 @@ #include "file.hpp" + #include "formattable.hpp" #include "logging.hpp" #include + #include #include #include diff --git a/llarp/util/file.hpp b/llarp/util/file.hpp index d6cd9dfa48..a66b1555fa 100644 --- a/llarp/util/file.hpp +++ b/llarp/util/file.hpp @@ -1,11 +1,11 @@ #pragma once +#include "fs.hpp" + #include #include #include #include -#include "fs.hpp" - #ifndef _MSC_VER #include #endif diff --git a/llarp/util/formattable.hpp b/llarp/util/formattable.hpp index a2b1e8a37f..85fe3fb36e 100644 --- a/llarp/util/formattable.hpp +++ b/llarp/util/formattable.hpp @@ -1,6 +1,7 @@ #pragma once #include + #include // Formattable types can specialize this to true and will get automatic fmt formattering support via diff --git a/llarp/util/logging.hpp b/llarp/util/logging.hpp index 40f1dbaf1e..683233c689 100644 --- a/llarp/util/logging.hpp +++ b/llarp/util/logging.hpp @@ -2,13 +2,12 @@ // Header for making actual log statements such as llarp::log::Info and so on work. -#include -#include -#include - #include #include -#include "oxen/log/internal.hpp" + +#include +#include +#include namespace llarp { diff --git a/llarp/util/logging/buffer.hpp b/llarp/util/logging/buffer.hpp index a6c46cf361..ad8f98c8c4 100644 --- a/llarp/util/logging/buffer.hpp +++ b/llarp/util/logging/buffer.hpp @@ -2,10 +2,11 @@ #include #include -#include -#include + #include #include +#include +#include namespace llarp { diff --git a/llarp/util/logging/callback_sink.hpp b/llarp/util/logging/callback_sink.hpp index 9b5538562b..599a97e9e8 100644 --- a/llarp/util/logging/callback_sink.hpp +++ b/llarp/util/logging/callback_sink.hpp @@ -1,6 +1,7 @@ #include -#include #include +#include + #include namespace llarp::logging diff --git a/llarp/util/mem.cpp b/llarp/util/mem.cpp index 1fe7a389c0..66ab9e3579 100644 --- a/llarp/util/mem.cpp +++ b/llarp/util/mem.cpp @@ -1,5 +1,6 @@ #define NO_JEMALLOC #include "mem.h" + #include namespace llarp diff --git a/llarp/util/meta/memfn.hpp b/llarp/util/meta/memfn.hpp index 4ec196b8c2..b7a408560f 100644 --- a/llarp/util/meta/memfn.hpp +++ b/llarp/util/meta/memfn.hpp @@ -1,9 +1,9 @@ #ifndef LLARP_UTIL_MEMFN #define LLARP_UTIL_MEMFN +#include #include #include -#include namespace llarp::util { diff --git a/llarp/util/str.cpp b/llarp/util/str.cpp index 0270f63dc4..3fed7ea44e 100644 --- a/llarp/util/str.cpp +++ b/llarp/util/str.cpp @@ -4,9 +4,10 @@ #include #ifdef _WIN32 -#include -#include #include + +#include +#include #endif namespace llarp diff --git a/llarp/util/str.hpp b/llarp/util/str.hpp index 0c120cbc2c..0ea7838989 100644 --- a/llarp/util/str.hpp +++ b/llarp/util/str.hpp @@ -1,11 +1,12 @@ #pragma once #include -#include -#include + +#include #include #include -#include +#include +#include namespace llarp { diff --git a/llarp/util/thread/barrier.hpp b/llarp/util/thread/barrier.hpp index 369b2b3fa9..dabd5e5fcc 100644 --- a/llarp/util/thread/barrier.hpp +++ b/llarp/util/thread/barrier.hpp @@ -1,6 +1,6 @@ #pragma once -#include #include +#include namespace llarp { diff --git a/llarp/util/thread/queue.hpp b/llarp/util/thread/queue.hpp index 96e6c158e7..954abd3255 100644 --- a/llarp/util/thread/queue.hpp +++ b/llarp/util/thread/queue.hpp @@ -3,8 +3,8 @@ #include "queue_manager.hpp" #include "threading.hpp" -#include #include +#include #include namespace llarp diff --git a/llarp/util/thread/queue_manager.hpp b/llarp/util/thread/queue_manager.hpp index 6389d9e787..b572803eba 100644 --- a/llarp/util/thread/queue_manager.hpp +++ b/llarp/util/thread/queue_manager.hpp @@ -1,8 +1,8 @@ #pragma once -#include #include #include #include +#include #include #include #include diff --git a/llarp/util/thread/threading.cpp b/llarp/util/thread/threading.cpp index c61639366b..b62e41c348 100644 --- a/llarp/util/thread/threading.cpp +++ b/llarp/util/thread/threading.cpp @@ -1,6 +1,7 @@ #include "threading.hpp" #include + #include #ifdef POSIX diff --git a/llarp/util/thread/threading.hpp b/llarp/util/thread/threading.hpp index d50a630423..7fb31e4c3b 100644 --- a/llarp/util/thread/threading.hpp +++ b/llarp/util/thread/threading.hpp @@ -1,15 +1,14 @@ #pragma once -#include -#include -#include +#include "annotations.hpp" + #include -#include #include +#include +#include +#include #include -#include "annotations.hpp" - #if defined(WIN32) && !defined(__GNUC__) #include diff --git a/llarp/util/time.hpp b/llarp/util/time.hpp index 773083ba2d..2a312090dc 100644 --- a/llarp/util/time.hpp +++ b/llarp/util/time.hpp @@ -1,11 +1,12 @@ #pragma once -#include -#include +#include "types.hpp" + #include -#include +#include +#include -#include "types.hpp" +#include using namespace std::chrono_literals; diff --git a/llarp/util/types.hpp b/llarp/util/types.hpp index 1944bd9052..f0f4cf243b 100644 --- a/llarp/util/types.hpp +++ b/llarp/util/types.hpp @@ -1,9 +1,9 @@ #pragma once +#include + +#include #include #include -#include - -#include "oxen/log/format.hpp" using byte_t = uint8_t; using llarp_proto_version_t = std::uint8_t; diff --git a/llarp/vpn/android.hpp b/llarp/vpn/android.hpp index 1ab0abfb2f..402c91ada0 100644 --- a/llarp/vpn/android.hpp +++ b/llarp/vpn/android.hpp @@ -1,12 +1,13 @@ #pragma once -#include -#include - -#include "platform.hpp" #include "common.hpp" +#include "platform.hpp" + #include +#include +#include + namespace llarp::vpn { class AndroidInterface : public NetworkInterface diff --git a/llarp/vpn/common.hpp b/llarp/vpn/common.hpp index 8db9456361..715ae296ad 100644 --- a/llarp/vpn/common.hpp +++ b/llarp/vpn/common.hpp @@ -1,9 +1,14 @@ #pragma once -#include +#include #include #include +#include +#include + #include +#include +#include namespace llarp::vpn { diff --git a/llarp/vpn/egres_packet_router.hpp b/llarp/vpn/egres_packet_router.hpp index 8b074267d8..bc4a1fec6d 100644 --- a/llarp/vpn/egres_packet_router.hpp +++ b/llarp/vpn/egres_packet_router.hpp @@ -1,7 +1,8 @@ #pragma once -#include -#include #include +#include +#include + #include #include diff --git a/llarp/vpn/i_packet_io.hpp b/llarp/vpn/i_packet_io.hpp index 5789b193cd..2c29fd64c7 100644 --- a/llarp/vpn/i_packet_io.hpp +++ b/llarp/vpn/i_packet_io.hpp @@ -1,8 +1,9 @@ #pragma once -#include #include #include +#include + namespace llarp::vpn { class I_Packet_IO diff --git a/llarp/vpn/linux.hpp b/llarp/vpn/linux.hpp index 6283f3be82..6f734a9560 100644 --- a/llarp/vpn/linux.hpp +++ b/llarp/vpn/linux.hpp @@ -1,27 +1,26 @@ #pragma once -#include "platform.hpp" -#include -#include -#include -#include #include "common.hpp" -#include -#include +#include "platform.hpp" -#include -#include -#include +#include #include +#include +#include #include -#include +#include +#include +#include +#include +#include #include +#include +#include +#include -#include -#include - -#include +#include +#include namespace llarp::vpn { diff --git a/llarp/vpn/packet_intercept.hpp b/llarp/vpn/packet_intercept.hpp index eac310a246..3fb8e4b17e 100644 --- a/llarp/vpn/packet_intercept.hpp +++ b/llarp/vpn/packet_intercept.hpp @@ -1,7 +1,8 @@ #pragma once +#include + #include #include -#include namespace llarp::vpn { diff --git a/llarp/vpn/packet_router.hpp b/llarp/vpn/packet_router.hpp index 635df79251..41def5b339 100644 --- a/llarp/vpn/packet_router.hpp +++ b/llarp/vpn/packet_router.hpp @@ -1,6 +1,7 @@ #pragma once -#include #include +#include + #include #include diff --git a/llarp/vpn/platform.hpp b/llarp/vpn/platform.hpp index 62534d33c0..9294ed1222 100644 --- a/llarp/vpn/platform.hpp +++ b/llarp/vpn/platform.hpp @@ -1,12 +1,14 @@ #pragma once -#include +#include "i_packet_io.hpp" + #include +#include + #include -#include -#include +#include -#include "i_packet_io.hpp" +#include namespace llarp { diff --git a/llarp/vpn/win32.cpp b/llarp/vpn/win32.cpp index 9002314902..1e8dee467e 100644 --- a/llarp/vpn/win32.cpp +++ b/llarp/vpn/win32.cpp @@ -1,6 +1,8 @@ #include "win32.hpp" + #include #include + #include namespace llarp::win32 diff --git a/llarp/vpn/win32.hpp b/llarp/vpn/win32.hpp index a14852e79b..ac0f5e01a8 100644 --- a/llarp/vpn/win32.hpp +++ b/llarp/vpn/win32.hpp @@ -1,13 +1,15 @@ #pragma once -#include +#include "platform.hpp" + #include +#include #include + #include -#include -#include -#include "platform.hpp" +#include +#include namespace llarp::win32 { diff --git a/llarp/win32/dll.cpp b/llarp/win32/dll.cpp index 66071e9cbc..398dbe3d87 100644 --- a/llarp/win32/dll.cpp +++ b/llarp/win32/dll.cpp @@ -1,4 +1,5 @@ #include "dll.hpp" + #include #include diff --git a/llarp/win32/dll.hpp b/llarp/win32/dll.hpp index d99a653461..d385de18da 100644 --- a/llarp/win32/dll.hpp +++ b/llarp/win32/dll.hpp @@ -1,8 +1,10 @@ #pragma once -#include #include "exception.hpp" + #include +#include + namespace llarp::win32 { namespace detail diff --git a/llarp/win32/exception.cpp b/llarp/win32/exception.cpp index 4b74e0584e..240172db9d 100644 --- a/llarp/win32/exception.cpp +++ b/llarp/win32/exception.cpp @@ -1,6 +1,9 @@ -#include "windows.h" #include "exception.hpp" + +#include "windows.h" + #include + #include namespace llarp::win32 diff --git a/llarp/win32/exception.hpp b/llarp/win32/exception.hpp index 21c8b04159..871de8a065 100644 --- a/llarp/win32/exception.hpp +++ b/llarp/win32/exception.hpp @@ -1,7 +1,8 @@ #pragma once #include -#include + #include +#include namespace llarp::win32 { diff --git a/llarp/win32/exec.cpp b/llarp/win32/exec.cpp index 4f17b8f041..d0f4d5fe19 100644 --- a/llarp/win32/exec.cpp +++ b/llarp/win32/exec.cpp @@ -1,5 +1,7 @@ #include "exec.hpp" + #include "exception.hpp" + #include #include diff --git a/llarp/win32/exec.hpp b/llarp/win32/exec.hpp index f77e009dfb..337d0fc0d2 100644 --- a/llarp/win32/exec.hpp +++ b/llarp/win32/exec.hpp @@ -1,8 +1,10 @@ #pragma once +#include + #include + #include -#include namespace llarp::win32 { diff --git a/llarp/win32/guid.hpp b/llarp/win32/guid.hpp index 40e0cae095..06de11b1e0 100644 --- a/llarp/win32/guid.hpp +++ b/llarp/win32/guid.hpp @@ -1,7 +1,9 @@ #pragma once #include + #include + #include namespace llarp::win32 diff --git a/llarp/win32/service_manager.cpp b/llarp/win32/service_manager.cpp index 986b0c0244..df682e5186 100644 --- a/llarp/win32/service_manager.cpp +++ b/llarp/win32/service_manager.cpp @@ -1,10 +1,13 @@ -#include -#include +#include "service_manager.hpp" + #include #include -#include "service_manager.hpp" + #include +#include + #include +#include #include #include diff --git a/llarp/win32/service_manager.hpp b/llarp/win32/service_manager.hpp index 6896e69e05..37a8f54c6f 100644 --- a/llarp/win32/service_manager.hpp +++ b/llarp/win32/service_manager.hpp @@ -1,8 +1,9 @@ #pragma once -#include #include #include +#include + namespace llarp::sys { diff --git a/llarp/win32/win32_inet.c b/llarp/win32/win32_inet.c index 394923bb3b..8357947518 100644 --- a/llarp/win32/win32_inet.c +++ b/llarp/win32/win32_inet.c @@ -9,11 +9,12 @@ */ // these need to be in a specific order +#include + #include +#include #include -#include #include -#include const char* inet_ntop(int af, const void* src, char* dst, size_t size) diff --git a/llarp/win32/windivert.cpp b/llarp/win32/windivert.cpp index 48f5c27b54..ea8381f8e4 100644 --- a/llarp/win32/windivert.cpp +++ b/llarp/win32/windivert.cpp @@ -1,11 +1,16 @@ -#include -#include #include "windivert.hpp" + #include "dll.hpp" #include "handle.hpp" -#include + #include #include +#include + +#include + +#include + #include extern "C" { diff --git a/llarp/win32/windivert.hpp b/llarp/win32/windivert.hpp index af71acfeeb..7f92c1acd5 100644 --- a/llarp/win32/windivert.hpp +++ b/llarp/win32/windivert.hpp @@ -1,8 +1,10 @@ #pragma once +#include + +#include + #include #include -#include -#include namespace llarp::win32::WinDivert { diff --git a/llarp/win32/wintun.cpp b/llarp/win32/wintun.cpp index 10569a69e6..f2e8643a9e 100644 --- a/llarp/win32/wintun.cpp +++ b/llarp/win32/wintun.cpp @@ -3,19 +3,22 @@ extern "C" #include } -#include -#include "wintun.hpp" -#include "exception.hpp" #include "dll.hpp" +#include "exception.hpp" #include "guid.hpp" -#include -#include +#include "wintun.hpp" + #include +#include #include #include -#include #include +#include + +#include +#include + namespace llarp::win32 { namespace diff --git a/pybind/common.hpp b/pybind/common.hpp index 655dccf06c..367345f4ab 100644 --- a/pybind/common.hpp +++ b/pybind/common.hpp @@ -1,12 +1,12 @@ #pragma once +#include + +#include #include #include -#include #include -#include - namespace py = pybind11; namespace llarp diff --git a/pybind/llarp/config.cpp b/pybind/llarp/config.cpp index 8ca1a8da4c..1109f96bf7 100644 --- a/pybind/llarp/config.cpp +++ b/pybind/llarp/config.cpp @@ -1,6 +1,6 @@ -#include #include +#include #include namespace llarp diff --git a/pybind/llarp/context.cpp b/pybind/llarp/context.cpp index 9a1cf194ba..86f6aea54c 100644 --- a/pybind/llarp/context.cpp +++ b/pybind/llarp/context.cpp @@ -1,9 +1,10 @@ -#include #include -#include -#include #include +#include #include +#include + +#include namespace llarp { diff --git a/pybind/llarp/crypto/types.cpp b/pybind/llarp/crypto/types.cpp index c866791b7c..e2ac0e743f 100644 --- a/pybind/llarp/crypto/types.cpp +++ b/pybind/llarp/crypto/types.cpp @@ -1,4 +1,5 @@ #include + #include namespace llarp diff --git a/pybind/llarp/handlers/pyhandler.hpp b/pybind/llarp/handlers/pyhandler.hpp index db90076aff..20bc5587ff 100644 --- a/pybind/llarp/handlers/pyhandler.hpp +++ b/pybind/llarp/handlers/pyhandler.hpp @@ -1,9 +1,10 @@ #pragma once -#include #include +#include #include #include -#include + +#include namespace llarp { diff --git a/pybind/llarp/logger.cpp b/pybind/llarp/logger.cpp index 891847acf0..947ad1af71 100644 --- a/pybind/llarp/logger.cpp +++ b/pybind/llarp/logger.cpp @@ -1,6 +1,8 @@ +#include + #include + #include -#include namespace llarp { diff --git a/pybind/llarp/path/path_hop_config.cpp b/pybind/llarp/path/path_hop_config.cpp index 7a539e4c9a..b5e562db9b 100644 --- a/pybind/llarp/path/path_hop_config.cpp +++ b/pybind/llarp/path/path_hop_config.cpp @@ -1,4 +1,5 @@ #include + #include namespace llarp diff --git a/pybind/llarp/peerstats.cpp b/pybind/llarp/peerstats.cpp index 9ce84d13ac..6ced63bebb 100644 --- a/pybind/llarp/peerstats.cpp +++ b/pybind/llarp/peerstats.cpp @@ -1,8 +1,8 @@ -#include #include #include #include +#include #include namespace llarp diff --git a/pybind/llarp/router.cpp b/pybind/llarp/router.cpp index c32d51e9fd..edc9be78fb 100644 --- a/pybind/llarp/router.cpp +++ b/pybind/llarp/router.cpp @@ -1,8 +1,8 @@ -#include - #include #include +#include + namespace llarp { void diff --git a/pybind/llarp/router_contact.cpp b/pybind/llarp/router_contact.cpp index 0597a172dc..ab1048c3da 100644 --- a/pybind/llarp/router_contact.cpp +++ b/pybind/llarp/router_contact.cpp @@ -1,8 +1,8 @@ -#include +#include "common.hpp" #include +#include #include -#include "common.hpp" namespace llarp { diff --git a/pybind/llarp/router_id.cpp b/pybind/llarp/router_id.cpp index 1cb2c56b7a..d23d47937c 100644 --- a/pybind/llarp/router_id.cpp +++ b/pybind/llarp/router_id.cpp @@ -1,7 +1,7 @@ -#include - #include +#include + namespace llarp { void diff --git a/pybind/llarp/service/address.cpp b/pybind/llarp/service/address.cpp index 276911c08c..b3c10f84d1 100644 --- a/pybind/llarp/service/address.cpp +++ b/pybind/llarp/service/address.cpp @@ -1,6 +1,7 @@ -#include #include +#include + namespace llarp { namespace service diff --git a/pybind/llarp/tooling/router_event.cpp b/pybind/llarp/tooling/router_event.cpp index 73a110aaa9..edd1f226ac 100644 --- a/pybind/llarp/tooling/router_event.cpp +++ b/pybind/llarp/tooling/router_event.cpp @@ -1,14 +1,13 @@ -#include -#include - -#include +#include +#include #include #include -#include #include +#include +#include -#include -#include +#include +#include namespace tooling { diff --git a/pybind/llarp/tooling/router_hive.cpp b/pybind/llarp/tooling/router_hive.cpp index 0eabc7e334..e96b87895d 100644 --- a/pybind/llarp/tooling/router_hive.cpp +++ b/pybind/llarp/tooling/router_hive.cpp @@ -1,10 +1,10 @@ +#include +#include +#include + #include -#include #include - -#include -#include -#include +#include namespace tooling { diff --git a/pybind/module.cpp b/pybind/module.cpp index dc75ace23b..50b16ca0b0 100644 --- a/pybind/module.cpp +++ b/pybind/module.cpp @@ -1,4 +1,5 @@ #include "common.hpp" + #include PYBIND11_MODULE(pyllarp, m) From f21facfd3979b0847defb90d5375bff657c6fcbc Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Tue, 24 Oct 2023 14:54:20 -0300 Subject: [PATCH 069/312] Add format.sh detection of include problems --- contrib/format.sh | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/contrib/format.sh b/contrib/format.sh index d757554e01..a6e6c97d0a 100755 --- a/contrib/format.sh +++ b/contrib/format.sh @@ -4,12 +4,28 @@ cd "$(dirname $0)/../" +sources=($(find jni daemon llarp include pybind | grep -E '\.([hc](pp)?|m(m)?)$' | grep -v '#')) + +incl_pat='^(#include +)"(llarp|libntrup|oxen|oxenc|oxenmq|quic|CLI|cpr|nlohmann|ghc|fmt|spdlog|uvw?)([/.][^"]*)"' + if [ "$1" = "verify" ] ; then - if [ $($CLANG_FORMAT --output-replacements-xml $(find jni daemon llarp include pybind | grep -E '\.([hc](pp)?|m(m)?)$' | grep -v '#') | grep '' | wc -l) -ne 0 ] ; then + if [ $($CLANG_FORMAT --output-replacements-xml "${sources[@]}" | grep '' | wc -l) -ne 0 ] ; then exit 2 fi + + if grep --color -E "$incl_pat" "${sources[@]}"; then + exit 5 + fi else - $CLANG_FORMAT -i $(find jni daemon llarp include pybind | grep -E '\.([hc](pp)?|m(m)?)$' | grep -v '#') &> /dev/null + $CLANG_FORMAT -i "${sources[@]}" &> /dev/null + + perl -pi -e "s{$incl_pat}"'{$1<$2$3>}' "${sources[@]}" &> /dev/null +fi + +# Some includes just shouldn't exist anywhere, but need to be fixed manually: +if grep --color -E '^#include ([<"]external/|/dev/null) From 52b175772f2ae604cee99ac4c299be11d6455319 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Wed, 18 Oct 2023 16:24:26 -0300 Subject: [PATCH 070/312] Bring oxen-encoding back in as a submodule As long as it's loaded before oxen-mq or libquic, this should end up being the one that gets used in oxen-mq/libquic, and so we don't have to update those when we want something in a newer oxen-encoding. --- .gitmodules | 3 +++ external/CMakeLists.txt | 3 +++ external/oxen-encoding | 1 + 3 files changed, 7 insertions(+) create mode 160000 external/oxen-encoding diff --git a/.gitmodules b/.gitmodules index 73f0a79358..60d221105b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -35,3 +35,6 @@ [submodule "external/span-lite"] path = external/span-lite url = https://github.com/martinmoene/span-lite.git +[submodule "external/oxen-encoding"] + path = external/oxen-encoding + url = https://github.com/oxen-io/oxen-encoding.git diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 2b09d0ee5b..f901be4c34 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -26,7 +26,9 @@ if(SUBMODULE_CHECK) message(STATUS "Checking submodules") check_submodule(CLI11) check_submodule(cpr) + check_submodule(ghc-filesystem) check_submodule(nlohmann) + check_submodule(oxen-encoding) check_submodule(oxen-libquic) check_submodule(oxen-mq) check_submodule(pybind11) @@ -58,6 +60,7 @@ macro(system_or_submodule BIGNAME smallname pkgconf subdir) endif() endmacro() +system_or_submodule(OXENC oxenc liboxenc>=1.0.10 oxen-encoding) system_or_submodule(OXENMQ oxenmq liboxenmq>=1.2.14 oxen-mq) set(JSON_BuildTests OFF CACHE INTERNAL "") diff --git a/external/oxen-encoding b/external/oxen-encoding new file mode 160000 index 0000000000..a7de63756d --- /dev/null +++ b/external/oxen-encoding @@ -0,0 +1 @@ +Subproject commit a7de63756dcc5c31cb899a4b810e6434b1a7c01c From 3d44e58e34a1ce7fd263560afbda4e44f68daeaa Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Tue, 24 Oct 2023 17:33:40 -0300 Subject: [PATCH 071/312] Fix systemd linkage --- llarp/CMakeLists.txt | 5 +---- llarp/router_contact.cpp | 5 ++++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index 831836ce9f..f67243cf40 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -165,7 +165,7 @@ lokinet_add_library(lokinet-dns # platform specific bits and bobs for setting dns add_library(lokinet-dns-platform INTERFACE) if(WITH_SYSTEMD) - add_library(lokinet-dns-systemd STATIC dns/nm_platform.cpp dns/sd_platform.cpp) + lokinet_add_library(lokinet-dns-systemd dns/nm_platform.cpp dns/sd_platform.cpp) target_link_libraries(lokinet-dns-platform INTERFACE lokinet-dns-systemd) endif() @@ -222,9 +222,6 @@ target_link_libraries(lokinet-core PUBLIC lokinet-core-utils) # Link lokinet-dns to alternate libraries target_link_libraries(lokinet-dns PUBLIC lokinet-dns-platform) -if (TARGET lokinet-dns-systemd) - target_link_libraries(lokinet-dns PUBLIC lokinet-dns-systemd) -endif() target_link_libraries(lokinet-wire PUBLIC lokinet-time-place) target_link_libraries(lokinet-dns PUBLIC lokinet-utils lokinet-cryptography lokinet-config) diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index c87251adb8..d57866222a 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -228,7 +228,10 @@ namespace llarp bool decode_result = DecodeVersion_1(btlist); // advance the llarp_buffer_t since lokimq serialization is unaware of it. - buf->cur += btlist.current_buffer().data() - buf_view.data() + 1; + // 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; } From 57393ea740102ce612361be576a1413763b85253 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Tue, 24 Oct 2023 12:25:42 -0700 Subject: [PATCH 072/312] Review fixes - cleaned up include-what-you-use errors (mostly quoted includes) - misc fixes --- daemon/lokinet.cpp | 2 +- llarp/CMakeLists.txt | 1 - llarp/nodedb.cpp | 2 +- llarp/pow.cpp | 56 ------------------------------ llarp/pow.hpp | 48 ------------------------- llarp/router/rc_lookup_handler.cpp | 3 -- llarp/service/intro_set.cpp | 1 + llarp/service/intro_set.hpp | 1 - llarp/service/outbound_context.cpp | 2 +- llarp/service/outbound_context.hpp | 2 +- llarp/service/protocol.cpp | 3 +- llarp/vpn/android.hpp | 3 +- pybind/llarp/router.cpp | 4 +-- 13 files changed, 10 insertions(+), 118 deletions(-) delete mode 100644 llarp/pow.cpp delete mode 100644 llarp/pow.hpp diff --git a/daemon/lokinet.cpp b/daemon/lokinet.cpp index b3cb416c80..f439006693 100644 --- a/daemon/lokinet.cpp +++ b/daemon/lokinet.cpp @@ -639,7 +639,7 @@ main(int argc, char* argv[]) static const char* text = "Don't run lokinet in wine, aborting startup"; static const char* title = "Lokinet Wine Error"; MessageBoxA(NULL, text, title, MB_ICONHAND); - abort(); + std::abort(); } } diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index f67243cf40..06e4ac5b2d 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -98,7 +98,6 @@ lokinet_add_library(lokinet-time-place net/ip_range.cpp net/net_int.cpp net/sock_addr.cpp - pow.cpp # only intro_set router_contact.cpp router_id.cpp router_version.cpp # to be deleted shortly diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index 5ea66233e2..cc6d2a28be 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -238,7 +238,7 @@ namespace llarp size_t NodeDB::num_loaded() const { - return router.loop()->call_get([this]() -> size_t { return entries.size(); }); + return router.loop()->call_get([this]() { return entries.size(); }); } void diff --git a/llarp/pow.cpp b/llarp/pow.cpp deleted file mode 100644 index 2051fbc7aa..0000000000 --- a/llarp/pow.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "pow.hpp" - -#include "crypto/crypto.hpp" - -#include - -namespace llarp -{ - PoW::~PoW() = default; - - bool - PoW::decode_key(const llarp_buffer_t& /*k*/, llarp_buffer_t* /*val*/) - { - // TODO: implement me - return false; - } - - std::string - PoW::bt_encode() const - { - return ""s; - } - - bool - PoW::IsValid(llarp_time_t now) const - { - if (now - timestamp > extendedLifetime) - return false; - - ShortHash digest; - auto buf = bt_encode(); - - // hash - if (!crypto::shorthash(digest, reinterpret_cast(buf.data()), buf.size())) - return false; - // check bytes required - uint32_t required = std::floor(std::log(extendedLifetime.count())); - for (uint32_t idx = 0; idx < required; ++idx) - { - if (digest[idx]) - return false; - } - return true; - } - - std::string - PoW::ToString() const - { - return fmt::format( - "[PoW timestamp={} lifetime={} nonce={}]", - timestamp.count(), - extendedLifetime.count(), - nonce); - } - -} // namespace llarp diff --git a/llarp/pow.hpp b/llarp/pow.hpp deleted file mode 100644 index b41fb003ad..0000000000 --- a/llarp/pow.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include "router_id.hpp" -#include "util/buffer.hpp" - -namespace llarp -{ - /// proof of work - struct PoW - { - static constexpr size_t MaxSize = 128; - llarp_time_t timestamp = 0s; - llarp_time_t extendedLifetime = 0s; - AlignedBuffer<32> nonce; - uint64_t version = llarp::constants::proto_version; - - ~PoW(); - - bool - IsValid(llarp_time_t now) const; - - bool - decode_key(const llarp_buffer_t& k, llarp_buffer_t* val); - - std::string - bt_encode() const; - - bool - operator==(const PoW& other) const - { - return timestamp == other.timestamp && version == other.version - && extendedLifetime == other.extendedLifetime && nonce == other.nonce; - } - - bool - operator!=(const PoW& other) const - { - return !(*this == other); - } - - std::string - ToString() const; - }; - - template <> - constexpr inline bool IsToStringFormattable = true; - -} // namespace llarp diff --git a/llarp/router/rc_lookup_handler.cpp b/llarp/router/rc_lookup_handler.cpp index e10684a79e..8cb96b10d2 100644 --- a/llarp/router/rc_lookup_handler.cpp +++ b/llarp/router/rc_lookup_handler.cpp @@ -106,10 +106,7 @@ namespace llarp if (callback) callback(result.router_id(), result, true); else - { r.node_db()->put_rc_if_newer(result); - // r.connect_to(result); - } } else { diff --git a/llarp/service/intro_set.cpp b/llarp/service/intro_set.cpp index 93cd5af30c..602e79dd44 100644 --- a/llarp/service/intro_set.cpp +++ b/llarp/service/intro_set.cpp @@ -184,6 +184,7 @@ namespace llarp::service IntroSet::ExtractStatus() const { util::StatusObject obj{{"published", to_json(time_signed)}}; + // TODO: this // std::vector introsObjs; // std::transform( // intros.begin(), diff --git a/llarp/service/intro_set.hpp b/llarp/service/intro_set.hpp index de11118f87..3fdcf80b6b 100644 --- a/llarp/service/intro_set.hpp +++ b/llarp/service/intro_set.hpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include diff --git a/llarp/service/outbound_context.cpp b/llarp/service/outbound_context.cpp index 9c05379154..115394f577 100644 --- a/llarp/service/outbound_context.cpp +++ b/llarp/service/outbound_context.cpp @@ -489,7 +489,7 @@ namespace llarp::service } void - OutboundContext::Tick(std::chrono::milliseconds now) + OutboundContext::Tick(llarp_time_t now) { path::Builder::Tick(now); diff --git a/llarp/service/outbound_context.hpp b/llarp/service/outbound_context.hpp index 2b66715eea..d0381b0c7d 100644 --- a/llarp/service/outbound_context.hpp +++ b/llarp/service/outbound_context.hpp @@ -79,7 +79,7 @@ namespace llarp::service send_auth_async(std::function resultHandler); void - Tick(std::chrono::milliseconds now) override; + Tick(llarp_time_t now) override; util::StatusObject ExtractStatus() const; diff --git a/llarp/service/protocol.cpp b/llarp/service/protocol.cpp index 755554a24b..bcc2960efa 100644 --- a/llarp/service/protocol.cpp +++ b/llarp/service/protocol.cpp @@ -39,8 +39,7 @@ namespace llarp::service ProtocolMessage::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) { bool read = false; - // if (!BEncodeMaybeReadDictInt("a", proto, read, k, buf)) - // return false; + if (k.startswith("d")) { llarp_buffer_t strbuf; diff --git a/llarp/vpn/android.hpp b/llarp/vpn/android.hpp index 402c91ada0..88012c3be1 100644 --- a/llarp/vpn/android.hpp +++ b/llarp/vpn/android.hpp @@ -5,9 +5,10 @@ #include -#include #include +#include + namespace llarp::vpn { class AndroidInterface : public NetworkInterface diff --git a/pybind/llarp/router.cpp b/pybind/llarp/router.cpp index edc9be78fb..51543e8da5 100644 --- a/pybind/llarp/router.cpp +++ b/pybind/llarp/router.cpp @@ -1,8 +1,8 @@ +#include "common.hpp" + #include #include -#include - namespace llarp { void From 19f9a8f12292161725c4c2308ffbe2a729c69a40 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Wed, 25 Oct 2023 12:11:19 -0300 Subject: [PATCH 073/312] Temporarily disable building/running test suite --- .drone.jsonnet | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.jsonnet b/.drone.jsonnet index 71ca9109d7..979e641526 100644 --- a/.drone.jsonnet +++ b/.drone.jsonnet @@ -51,7 +51,7 @@ local debian_pipeline(name, local_mirror=true, extra_cmds=[], jobs=6, - tests=true, + tests=false, // FIXME TODO: temporary until test suite is fixed oxen_repo=false, allow_fail=false) = { kind: 'pipeline', From 5596ffd9d794ddbcf7c8839739d68d38d837f06f Mon Sep 17 00:00:00 2001 From: dr7ana Date: Wed, 25 Oct 2023 12:43:32 -0700 Subject: [PATCH 074/312] CI Fixes, squash --- llarp/apple/CMakeLists.txt | 6 +- llarp/link/link_manager.hpp | 2 +- llarp/messages/exit.hpp | 2 +- llarp/nodedb.hpp | 1 - llarp/path/path_context.hpp | 6 +- llarp/profiling.hpp | 30 +- llarp/router/rc_lookup_handler.hpp | 6 +- llarp/util/thread/annotations.hpp | 53 -- llarp/util/thread/queue.hpp | 847 ++++++++++++++--------------- llarp/util/thread/threading.hpp | 238 ++++---- 10 files changed, 553 insertions(+), 638 deletions(-) delete mode 100644 llarp/util/thread/annotations.hpp diff --git a/llarp/apple/CMakeLists.txt b/llarp/apple/CMakeLists.txt index 8dd561ef75..d1ae8b698c 100644 --- a/llarp/apple/CMakeLists.txt +++ b/llarp/apple/CMakeLists.txt @@ -11,7 +11,7 @@ find_library(FOUNDATION Foundation REQUIRED) find_library(NETEXT NetworkExtension REQUIRED) find_library(COREFOUNDATION CoreFoundation REQUIRED) -target_link_libraries(lokinet-util PUBLIC ${FOUNDATION}) +target_link_libraries(lokinet-base PUBLIC ${FOUNDATION}) target_sources(lokinet-platform PRIVATE vpn_platform.cpp vpn_interface.cpp route_manager.cpp context_wrapper.cpp) @@ -27,7 +27,7 @@ enable_lto(lokinet-extension) target_compile_options(lokinet-extension PRIVATE -fobjc-arc) if(MACOS_SYSTEM_EXTENSION) target_compile_definitions(lokinet-extension PRIVATE MACOS_SYSTEM_EXTENSION) - target_compile_definitions(lokinet-util PUBLIC MACOS_SYSTEM_EXTENSION) + target_compile_definitions(lokinet-base PUBLIC MACOS_SYSTEM_EXTENSION) else() target_link_options(lokinet-extension PRIVATE -e _NSExtensionMain) endif() @@ -41,7 +41,7 @@ else() endif() target_link_libraries(lokinet-extension PRIVATE - lokinet-amalgum + lokinet-core ${COREFOUNDATION} ${NETEXT}) diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index d2b8cc8c91..96e37de7fb 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -174,7 +174,7 @@ namespace llarp mutable util::Mutex m; // protects persisting_conns // sessions to persist -> timestamp to end persist at - std::unordered_map persisting_conns GUARDED_BY(_mutex); + std::unordered_map persisting_conns; // holds any messages we attempt to send while connections are establishing std::unordered_map pending_conn_msg_queue; diff --git a/llarp/messages/exit.hpp b/llarp/messages/exit.hpp index de53a01d7d..2244adf48b 100644 --- a/llarp/messages/exit.hpp +++ b/llarp/messages/exit.hpp @@ -7,7 +7,7 @@ namespace llarp /* TODO: - change these parameters to ustringviews and ustrings where needed after bumping oxenc - - nuke seq_no's + - change std::string sig(64, '\0') --> std::array sig */ namespace ObtainExitMessage diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index b81d896930..7717b5ff5e 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -6,7 +6,6 @@ #include "router_id.hpp" #include "util/common.hpp" #include "util/fs.hpp" -#include "util/thread/annotations.hpp" #include "util/thread/threading.hpp" #include diff --git a/llarp/path/path_context.hpp b/llarp/path/path_context.hpp index cc2137ddec..6efb0942d6 100644 --- a/llarp/path/path_context.hpp +++ b/llarp/path/path_context.hpp @@ -105,13 +105,13 @@ namespace llarp using Lock_t = util::NullLock; Mutex_t first; // protects second - TransitHopsMap_t second GUARDED_BY(first); + TransitHopsMap_t second; /// Invokes a callback for each transit path; visit must be invokable with a `const /// TransitHop_ptr&` argument. template void - ForEach(TransitHopVisitor&& visit) EXCLUDES(first) + ForEach(TransitHopVisitor&& visit) { Lock_t lock(first); for (const auto& item : second) @@ -125,7 +125,7 @@ namespace llarp struct SyncOwnedPathsMap_t { util::Mutex first; // protects second - OwnedPathsMap_t second GUARDED_BY(first); + OwnedPathsMap_t second; /// Invokes a callback for each owned path; visit must be invokable with a `const Path_ptr&` /// argument. diff --git a/llarp/profiling.hpp b/llarp/profiling.hpp index b375ff7e57..67441d0198 100644 --- a/llarp/profiling.hpp +++ b/llarp/profiling.hpp @@ -3,7 +3,6 @@ #include "path/path.hpp" #include "router_id.hpp" #include "util/bencode.hpp" -#include "util/thread/annotations.hpp" #include "util/thread/threading.hpp" #include @@ -68,46 +67,45 @@ namespace llarp /// generic variant bool - IsBad(const RouterID& r, uint64_t chances = profiling_chances) EXCLUDES(m_ProfilesMutex); + IsBad(const RouterID& r, uint64_t chances = profiling_chances); /// check if this router should have paths built over it bool - IsBadForPath(const RouterID& r, uint64_t chances = profiling_chances) EXCLUDES(m_ProfilesMutex); + IsBadForPath(const RouterID& r, uint64_t chances = profiling_chances); /// check if this router should be connected directly to bool - IsBadForConnect(const RouterID& r, uint64_t chances = profiling_chances) - EXCLUDES(m_ProfilesMutex); + IsBadForConnect(const RouterID& r, uint64_t chances = profiling_chances); void - MarkConnectTimeout(const RouterID& r) EXCLUDES(m_ProfilesMutex); + MarkConnectTimeout(const RouterID& r); void - MarkConnectSuccess(const RouterID& r) EXCLUDES(m_ProfilesMutex); + MarkConnectSuccess(const RouterID& r); void - MarkPathTimeout(path::Path* p) EXCLUDES(m_ProfilesMutex); + MarkPathTimeout(path::Path* p); void - MarkPathFail(path::Path* p) EXCLUDES(m_ProfilesMutex); + MarkPathFail(path::Path* p); void - MarkPathSuccess(path::Path* p) EXCLUDES(m_ProfilesMutex); + MarkPathSuccess(path::Path* p); void - MarkHopFail(const RouterID& r) EXCLUDES(m_ProfilesMutex); + MarkHopFail(const RouterID& r); void - ClearProfile(const RouterID& r) EXCLUDES(m_ProfilesMutex); + ClearProfile(const RouterID& r); void - Tick() EXCLUDES(m_ProfilesMutex); + Tick(); bool - Load(const fs::path fname) EXCLUDES(m_ProfilesMutex); + Load(const fs::path fname); bool - Save(const fs::path fname) EXCLUDES(m_ProfilesMutex); + Save(const fs::path fname); bool ShouldSave(llarp_time_t now) const; @@ -126,7 +124,7 @@ namespace llarp BDecode(oxenc::bt_dict_consumer dict); mutable util::Mutex m_ProfilesMutex; // protects m_Profiles - std::map m_Profiles GUARDED_BY(m_ProfilesMutex); + std::map m_Profiles; llarp_time_t m_LastSave = 0s; std::atomic m_DisableProfiling; }; diff --git a/llarp/router/rc_lookup_handler.hpp b/llarp/router/rc_lookup_handler.hpp index 5d224f2f9f..7802a25972 100644 --- a/llarp/router/rc_lookup_handler.hpp +++ b/llarp/router/rc_lookup_handler.hpp @@ -136,11 +136,11 @@ namespace llarp std::atomic isServiceNode = false; // whitelist = active routers - std::unordered_set router_whitelist GUARDED_BY(_mutex); + std::unordered_set router_whitelist; // greylist = fully funded, but decommissioned routers - std::unordered_set router_greylist GUARDED_BY(_mutex); + std::unordered_set router_greylist; // greenlist = registered but not fully-staked routers - std::unordered_set router_greenlist GUARDED_BY(_mutex); + std::unordered_set router_greenlist; }; } // namespace llarp diff --git a/llarp/util/thread/annotations.hpp b/llarp/util/thread/annotations.hpp deleted file mode 100644 index 5f6623e5a2..0000000000 --- a/llarp/util/thread/annotations.hpp +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once -#include - -// Clang thread safety analysis macros. Does nothing under non-clang compilers. - -// Enable thread safety attributes only with clang and libc++ (the latter -// because we are using stl mutexes, which don't have the required annotations -// under stdlibc++). The attributes can be safely erased when compiling with -// other compilers. -#if defined(__clang__) && defined(_LIBCPP_VERSION) && !defined(SWIG) -#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x)) -#else -#define THREAD_ANNOTATION_ATTRIBUTE__(x) // no-op -#endif - -#define CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(capability(x)) - -#define SCOPED_CAPABILITY THREAD_ANNOTATION_ATTRIBUTE__(scoped_lockable) - -#define GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(guarded_by(x)) - -#define PT_GUARDED_BY(x) THREAD_ANNOTATION_ATTRIBUTE__(pt_guarded_by(x)) - -#define ACQUIRED_BEFORE(...) THREAD_ANNOTATION_ATTRIBUTE__(acquired_before(__VA_ARGS__)) - -#define ACQUIRED_AFTER(...) THREAD_ANNOTATION_ATTRIBUTE__(acquired_after(__VA_ARGS__)) - -#define REQUIRES(...) THREAD_ANNOTATION_ATTRIBUTE__(requires_capability(__VA_ARGS__)) - -#define REQUIRES_SHARED(...) THREAD_ANNOTATION_ATTRIBUTE__(requires_shared_capability(__VA_ARGS__)) - -#define ACQUIRE(...) THREAD_ANNOTATION_ATTRIBUTE__(acquire_capability(__VA_ARGS__)) - -#define ACQUIRE_SHARED(...) THREAD_ANNOTATION_ATTRIBUTE__(acquire_shared_capability(__VA_ARGS__)) - -#define RELEASE(...) THREAD_ANNOTATION_ATTRIBUTE__(release_capability(__VA_ARGS__)) - -#define RELEASE_SHARED(...) THREAD_ANNOTATION_ATTRIBUTE__(release_shared_capability(__VA_ARGS__)) - -#define TRY_ACQUIRE(...) THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_capability(__VA_ARGS__)) - -#define TRY_ACQUIRE_SHARED(...) \ - THREAD_ANNOTATION_ATTRIBUTE__(try_acquire_shared_capability(__VA_ARGS__)) - -#define EXCLUDES(...) THREAD_ANNOTATION_ATTRIBUTE__(locks_excluded(__VA_ARGS__)) - -#define ASSERT_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(assert_capability(x)) - -#define ASSERT_SHARED_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(assert_shared_capability(x)) - -#define RETURN_CAPABILITY(x) THREAD_ANNOTATION_ATTRIBUTE__(lock_returned(x)) - -#define NO_THREAD_SAFETY_ANALYSIS THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis) diff --git a/llarp/util/thread/queue.hpp b/llarp/util/thread/queue.hpp index 954abd3255..af5701cd1a 100644 --- a/llarp/util/thread/queue.hpp +++ b/llarp/util/thread/queue.hpp @@ -7,556 +7,553 @@ #include #include -namespace llarp +namespace llarp::thread { - namespace thread + template + class QueuePushGuard; + template + class QueuePopGuard; + + template + class Queue { - template - class QueuePushGuard; - template - class QueuePopGuard; + // This class provides a thread-safe, lock-free, fixed-size queue. + public: + static constexpr size_t Alignment = 64; - template - class Queue - { - // This class provides a thread-safe, lock-free, fixed-size queue. - public: - static constexpr size_t Alignment = 64; + private: + Type* m_data; + const char m_dataPadding[Alignment - sizeof(Type*)]; - private: - Type* m_data; - const char m_dataPadding[Alignment - sizeof(Type*)]; + QueueManager m_manager; - QueueManager m_manager; + std::atomic m_waitingPoppers; + util::Semaphore m_popSemaphore; + const char m_popSemaphorePadding[(2u * Alignment) - sizeof(util::Semaphore)]; - std::atomic m_waitingPoppers; - util::Semaphore m_popSemaphore; - const char m_popSemaphorePadding[(2u * Alignment) - sizeof(util::Semaphore)]; + std::atomic m_waitingPushers; + util::Semaphore m_pushSemaphore; + const char m_pushSemaphorePadding[(2u * Alignment) - sizeof(util::Semaphore)]; - std::atomic m_waitingPushers; - util::Semaphore m_pushSemaphore; - const char m_pushSemaphorePadding[(2u * Alignment) - sizeof(util::Semaphore)]; + friend QueuePopGuard; + friend QueuePushGuard; - friend QueuePopGuard; - friend QueuePushGuard; + public: + explicit Queue(size_t capacity); - public: - explicit Queue(size_t capacity); + ~Queue(); - ~Queue(); + Queue(const Queue&) = delete; + Queue& + operator=(const Queue&) = delete; - Queue(const Queue&) = delete; - Queue& - operator=(const Queue&) = delete; + // Push back to the queue, blocking until space is available (if + // required). Will fail if the queue is disabled (or becomes disabled + // while waiting for space on the queue). + QueueReturn + pushBack(const Type& value); - // Push back to the queue, blocking until space is available (if - // required). Will fail if the queue is disabled (or becomes disabled - // while waiting for space on the queue). - QueueReturn - pushBack(const Type& value); + QueueReturn + pushBack(Type&& value); - QueueReturn - pushBack(Type&& value); + // Try to push back to the queue. Return false if the queue is full or + // disabled. + QueueReturn + tryPushBack(const Type& value); - // Try to push back to the queue. Return false if the queue is full or - // disabled. - QueueReturn - tryPushBack(const Type& value); + QueueReturn + tryPushBack(Type&& value); - QueueReturn - tryPushBack(Type&& value); + // Remove an element from the queue. Block until an element is available + Type + popFront(); - // Remove an element from the queue. Block until an element is available - Type - popFront(); + // Remove an element from the queue. Block until an element is available + // or until microseconds have elapsed + std::optional + popFrontWithTimeout(std::chrono::microseconds timeout); - // Remove an element from the queue. Block until an element is available - // or until microseconds have elapsed - std::optional - popFrontWithTimeout(std::chrono::microseconds timeout); + std::optional + tryPopFront(); - std::optional - tryPopFront(); + // Remove all elements from the queue. Note this is not atomic, and if + // other threads `pushBack` onto the queue during this call, the `size` of + // the queue is not guaranteed to be 0. + void + removeAll(); - // Remove all elements from the queue. Note this is not atomic, and if - // other threads `pushBack` onto the queue during this call, the `size` of - // the queue is not guaranteed to be 0. - void - removeAll(); + // Disable the queue. All push operations will fail "fast" (including + // blocked operations). Calling this method on a disabled queue has no + // effect. + void + disable(); - // Disable the queue. All push operations will fail "fast" (including - // blocked operations). Calling this method on a disabled queue has no - // effect. - void - disable(); + // Enable the queue. Calling this method on a disabled queue has no + // effect. + void + enable(); - // Enable the queue. Calling this method on a disabled queue has no - // effect. - void - enable(); + size_t + capacity() const; - size_t - capacity() const; + size_t + size() const; - size_t - size() const; + bool + enabled() const; - bool - enabled() const; + bool + full() const; - bool - full() const; + bool + empty() const; + }; + + // Provide a guard class to provide exception safety for pushing to a queue. + // On destruction, unless the `release` method has been called, will remove + // and destroy all elements from the queue, putting the queue into an empty + // state. + template + class QueuePushGuard + { + private: + Queue* m_queue; + uint32_t m_generation; + uint32_t m_index; - bool - empty() const; - }; + public: + QueuePushGuard(Queue& queue, uint32_t generation, uint32_t index) + : m_queue(&queue), m_generation(generation), m_index(index) + {} - // Provide a guard class to provide exception safety for pushing to a queue. - // On destruction, unless the `release` method has been called, will remove - // and destroy all elements from the queue, putting the queue into an empty - // state. - template - class QueuePushGuard - { - private: - Queue* m_queue; - uint32_t m_generation; - uint32_t m_index; - - public: - QueuePushGuard(Queue& queue, uint32_t generation, uint32_t index) - : m_queue(&queue), m_generation(generation), m_index(index) - {} - - ~QueuePushGuard(); - - void - release(); - }; - - // Provide a guard class to provide exception safety for popping from a - // queue. On destruction, this will pop the the given element from the - // queue. - template - class QueuePopGuard - { - private: - Queue& m_queue; - uint32_t m_generation; - uint32_t m_index; - - public: - QueuePopGuard(Queue& queue, uint32_t generation, uint32_t index) - : m_queue(queue), m_generation(generation), m_index(index) - {} - - ~QueuePopGuard(); - }; - - template - Queue::Queue(size_t capacity) - : m_data(nullptr) - , m_dataPadding() - , m_manager(capacity) - , m_waitingPoppers(0) - , m_popSemaphore(0) - , m_popSemaphorePadding() - , m_waitingPushers(0) - , m_pushSemaphore(0) - , m_pushSemaphorePadding() - { - m_data = static_cast(::operator new(capacity * sizeof(Type))); - } + ~QueuePushGuard(); - template - Queue::~Queue() - { - removeAll(); + void + release(); + }; + + // Provide a guard class to provide exception safety for popping from a + // queue. On destruction, this will pop the the given element from the + // queue. + template + class QueuePopGuard + { + private: + Queue& m_queue; + uint32_t m_generation; + uint32_t m_index; + + public: + QueuePopGuard(Queue& queue, uint32_t generation, uint32_t index) + : m_queue(queue), m_generation(generation), m_index(index) + {} + + ~QueuePopGuard(); + }; + + template + Queue::Queue(size_t capacity) + : m_data(nullptr) + , m_dataPadding() + , m_manager(capacity) + , m_waitingPoppers(0) + , m_popSemaphore(0) + , m_popSemaphorePadding() + , m_waitingPushers(0) + , m_pushSemaphore(0) + , m_pushSemaphorePadding() + { + m_data = static_cast(::operator new(capacity * sizeof(Type))); + } - // We have already deleted the queue members above, free as (void *) - ::operator delete(static_cast(m_data)); - } + template + Queue::~Queue() + { + removeAll(); - template - QueueReturn - Queue::tryPushBack(const Type& value) - { - uint32_t generation = 0; - uint32_t index = 0; + // We have already deleted the queue members above, free as (void *) + ::operator delete(static_cast(m_data)); + } - // Sync point A - // - // The next call writes with full sequential consistency to the push - // index, which guarantees that the relaxed read to the waiting poppers - // count sees any waiting poppers from Sync point B. + template + QueueReturn + Queue::tryPushBack(const Type& value) + { + uint32_t generation = 0; + uint32_t index = 0; - QueueReturn retVal = m_manager.reservePushIndex(generation, index); + // Sync point A + // + // The next call writes with full sequential consistency to the push + // index, which guarantees that the relaxed read to the waiting poppers + // count sees any waiting poppers from Sync point B. - if (retVal != QueueReturn::Success) - { - return retVal; - } + QueueReturn retVal = m_manager.reservePushIndex(generation, index); - // Copy into the array. If the copy constructor throws, the pushGuard will - // roll the reserve back. + if (retVal != QueueReturn::Success) + { + return retVal; + } - QueuePushGuard pushGuard(*this, generation, index); + // Copy into the array. If the copy constructor throws, the pushGuard will + // roll the reserve back. - // Construct in place. - ::new (&m_data[index]) Type(value); + QueuePushGuard pushGuard(*this, generation, index); - pushGuard.release(); + // Construct in place. + ::new (&m_data[index]) Type(value); - m_manager.commitPushIndex(generation, index); + pushGuard.release(); - if (m_waitingPoppers > 0) - { - m_popSemaphore.notify(); - } + m_manager.commitPushIndex(generation, index); - return QueueReturn::Success; + if (m_waitingPoppers > 0) + { + m_popSemaphore.notify(); } - template - QueueReturn - Queue::tryPushBack(Type&& value) - { - uint32_t generation = 0; - uint32_t index = 0; + return QueueReturn::Success; + } - // Sync point A - // - // The next call writes with full sequential consistency to the push - // index, which guarantees that the relaxed read to the waiting poppers - // count sees any waiting poppers from Sync point B. + template + QueueReturn + Queue::tryPushBack(Type&& value) + { + uint32_t generation = 0; + uint32_t index = 0; - QueueReturn retVal = m_manager.reservePushIndex(generation, index); + // Sync point A + // + // The next call writes with full sequential consistency to the push + // index, which guarantees that the relaxed read to the waiting poppers + // count sees any waiting poppers from Sync point B. - if (retVal != QueueReturn::Success) - { - return retVal; - } + QueueReturn retVal = m_manager.reservePushIndex(generation, index); - // Copy into the array. If the copy constructor throws, the pushGuard will - // roll the reserve back. + if (retVal != QueueReturn::Success) + { + return retVal; + } - QueuePushGuard pushGuard(*this, generation, index); + // Copy into the array. If the copy constructor throws, the pushGuard will + // roll the reserve back. - Type& dummy = value; + QueuePushGuard pushGuard(*this, generation, index); - // Construct in place. - ::new (&m_data[index]) Type(std::move(dummy)); + Type& dummy = value; - pushGuard.release(); + // Construct in place. + ::new (&m_data[index]) Type(std::move(dummy)); - m_manager.commitPushIndex(generation, index); + pushGuard.release(); - if (m_waitingPoppers > 0) - { - m_popSemaphore.notify(); - } + m_manager.commitPushIndex(generation, index); - return QueueReturn::Success; + if (m_waitingPoppers > 0) + { + m_popSemaphore.notify(); } - template - std::optional - Queue::tryPopFront() + return QueueReturn::Success; + } + + template + std::optional + Queue::tryPopFront() + { + uint32_t generation; + uint32_t index; + + // Sync Point C. + // + // The call to reservePopIndex writes with full *sequential* consistency, + // which guarantees the relaxed read to waiting poppers is synchronized + // with Sync Point D. + + QueueReturn retVal = m_manager.reservePopIndex(generation, index); + + if (retVal != QueueReturn::Success) { - uint32_t generation; - uint32_t index; + return {}; + } - // Sync Point C. - // - // The call to reservePopIndex writes with full *sequential* consistency, - // which guarantees the relaxed read to waiting poppers is synchronized - // with Sync Point D. + // Pop guard will (even if the move/copy constructor throws) + // - destroy the original object + // - update the queue + // - notify any waiting pushers - QueueReturn retVal = m_manager.reservePopIndex(generation, index); + QueuePopGuard popGuard(*this, generation, index); + return std::optional(std::move(m_data[index])); + } + + template + QueueReturn + Queue::pushBack(const Type& value) + { + for (;;) + { + QueueReturn retVal = tryPushBack(value); - if (retVal != QueueReturn::Success) + switch (retVal) { - return {}; + // Queue disabled. + case QueueReturn::QueueDisabled: + // We pushed the value back + case QueueReturn::Success: + return retVal; + default: + // continue on. + break; } - // Pop guard will (even if the move/copy constructor throws) - // - destroy the original object - // - update the queue - // - notify any waiting pushers + m_waitingPushers.fetch_add(1, std::memory_order_relaxed); - QueuePopGuard popGuard(*this, generation, index); - return std::optional(std::move(m_data[index])); - } + // Sync Point B. + // + // The call to `full` below loads the push index with full *sequential* + // consistency, which gives visibility of the change above to + // waiting pushers in Synchronisation Point B. - template - QueueReturn - Queue::pushBack(const Type& value) - { - for (;;) + if (full() && enabled()) { - QueueReturn retVal = tryPushBack(value); - - switch (retVal) - { - // Queue disabled. - case QueueReturn::QueueDisabled: - // We pushed the value back - case QueueReturn::Success: - return retVal; - default: - // continue on. - break; - } - - m_waitingPushers.fetch_add(1, std::memory_order_relaxed); - - // Sync Point B. - // - // The call to `full` below loads the push index with full *sequential* - // consistency, which gives visibility of the change above to - // waiting pushers in Synchronisation Point B. - - if (full() && enabled()) - { - m_pushSemaphore.wait(); - } - - m_waitingPushers.fetch_add(-1, std::memory_order_relaxed); + m_pushSemaphore.wait(); } + + m_waitingPushers.fetch_add(-1, std::memory_order_relaxed); } + } - template - QueueReturn - Queue::pushBack(Type&& value) + template + QueueReturn + Queue::pushBack(Type&& value) + { + for (;;) { - for (;;) + QueueReturn retVal = tryPushBack(std::move(value)); + + switch (retVal) { - QueueReturn retVal = tryPushBack(std::move(value)); - - switch (retVal) - { - // Queue disabled. - case QueueReturn::QueueDisabled: - // We pushed the value back - case QueueReturn::Success: - return retVal; - default: - // continue on. - break; - } - - m_waitingPushers.fetch_add(1, std::memory_order_relaxed); - - // Sync Point B. - // - // The call to `full` below loads the push index with full *sequential* - // consistency, which gives visibility of the change above to - // waiting pushers in Synchronisation Point C. - - if (full() && enabled()) - { - m_pushSemaphore.wait(); - } - - m_waitingPushers.fetch_add(-1, std::memory_order_relaxed); + // Queue disabled. + case QueueReturn::QueueDisabled: + // We pushed the value back + case QueueReturn::Success: + return retVal; + default: + // continue on. + break; } - } - template - Type - Queue::popFront() - { - uint32_t generation = 0; - uint32_t index = 0; - while (m_manager.reservePopIndex(generation, index) != QueueReturn::Success) - { - m_waitingPoppers.fetch_add(1, std::memory_order_relaxed); + m_waitingPushers.fetch_add(1, std::memory_order_relaxed); - if (empty()) - { - m_popSemaphore.wait(); - } + // Sync Point B. + // + // The call to `full` below loads the push index with full *sequential* + // consistency, which gives visibility of the change above to + // waiting pushers in Synchronisation Point C. - m_waitingPoppers.fetch_sub(1, std::memory_order_relaxed); + if (full() && enabled()) + { + m_pushSemaphore.wait(); } - QueuePopGuard popGuard(*this, generation, index); - return Type(std::move(m_data[index])); + m_waitingPushers.fetch_add(-1, std::memory_order_relaxed); } + } - template - std::optional - Queue::popFrontWithTimeout(std::chrono::microseconds timeout) + template + Type + Queue::popFront() + { + uint32_t generation = 0; + uint32_t index = 0; + while (m_manager.reservePopIndex(generation, index) != QueueReturn::Success) { - uint32_t generation = 0; - uint32_t index = 0; - bool secondTry = false; - bool success = false; - for (;;) + m_waitingPoppers.fetch_add(1, std::memory_order_relaxed); + + if (empty()) { - success = m_manager.reservePopIndex(generation, index) == QueueReturn::Success; + m_popSemaphore.wait(); + } - if (secondTry || success) - break; + m_waitingPoppers.fetch_sub(1, std::memory_order_relaxed); + } - m_waitingPoppers.fetch_add(1, std::memory_order_relaxed); + QueuePopGuard popGuard(*this, generation, index); + return Type(std::move(m_data[index])); + } - if (empty()) - { - m_popSemaphore.waitFor(timeout); - secondTry = true; - } + template + std::optional + Queue::popFrontWithTimeout(std::chrono::microseconds timeout) + { + uint32_t generation = 0; + uint32_t index = 0; + bool secondTry = false; + bool success = false; + for (;;) + { + success = m_manager.reservePopIndex(generation, index) == QueueReturn::Success; - m_waitingPoppers.fetch_sub(1, std::memory_order_relaxed); - } + if (secondTry || success) + break; - if (success) + m_waitingPoppers.fetch_add(1, std::memory_order_relaxed); + + if (empty()) { - QueuePopGuard popGuard(*this, generation, index); - return Type(std::move(m_data[index])); + m_popSemaphore.waitFor(timeout); + secondTry = true; } - return {}; + m_waitingPoppers.fetch_sub(1, std::memory_order_relaxed); } - template - void - Queue::removeAll() + if (success) { - size_t elemCount = size(); - - uint32_t poppedItems = 0; + QueuePopGuard popGuard(*this, generation, index); + return Type(std::move(m_data[index])); + } - while (poppedItems++ < elemCount) - { - uint32_t generation = 0; - uint32_t index = 0; + return {}; + } - if (m_manager.reservePopIndex(generation, index) != QueueReturn::Success) - { - break; - } + template + void + Queue::removeAll() + { + size_t elemCount = size(); - m_data[index].~Type(); - m_manager.commitPopIndex(generation, index); - } + uint32_t poppedItems = 0; - size_t wakeups = std::min(poppedItems, m_waitingPushers.load()); + while (poppedItems++ < elemCount) + { + uint32_t generation = 0; + uint32_t index = 0; - while (wakeups--) + if (m_manager.reservePopIndex(generation, index) != QueueReturn::Success) { - m_pushSemaphore.notify(); + break; } + + m_data[index].~Type(); + m_manager.commitPopIndex(generation, index); } - template - void - Queue::disable() + size_t wakeups = std::min(poppedItems, m_waitingPushers.load()); + + while (wakeups--) { - m_manager.disable(); + m_pushSemaphore.notify(); + } + } - uint32_t numWaiting = m_waitingPushers; + template + void + Queue::disable() + { + m_manager.disable(); - while (numWaiting--) - { - m_pushSemaphore.notify(); - } - } + uint32_t numWaiting = m_waitingPushers; - template - void - Queue::enable() + while (numWaiting--) { - m_manager.enable(); + m_pushSemaphore.notify(); } + } - template - size_t - Queue::capacity() const - { - return m_manager.capacity(); - } + template + void + Queue::enable() + { + m_manager.enable(); + } - template - size_t - Queue::size() const - { - return m_manager.size(); - } + template + size_t + Queue::capacity() const + { + return m_manager.capacity(); + } - template - bool - Queue::enabled() const - { - return m_manager.enabled(); - } + template + size_t + Queue::size() const + { + return m_manager.size(); + } - template - bool - Queue::full() const - { - return (capacity() <= size()); - } + template + bool + Queue::enabled() const + { + return m_manager.enabled(); + } - template - bool - Queue::empty() const - { - return (0 >= size()); - } + template + bool + Queue::full() const + { + return (capacity() <= size()); + } + + template + bool + Queue::empty() const + { + return (0 >= size()); + } - template - QueuePushGuard::~QueuePushGuard() + template + QueuePushGuard::~QueuePushGuard() + { + if (m_queue) { - if (m_queue) - { - // Thread currently has the cell at index/generation. Dispose of it. + // Thread currently has the cell at index/generation. Dispose of it. - uint32_t generation = 0; - uint32_t index = 0; + uint32_t generation = 0; + uint32_t index = 0; - // We should always have at least one item to pop. - size_t poppedItems = 1; + // We should always have at least one item to pop. + size_t poppedItems = 1; - while (m_queue->m_manager.reservePopForClear(generation, index, m_generation, m_index)) - { - m_queue->m_data[index].~Type(); + while (m_queue->m_manager.reservePopForClear(generation, index, m_generation, m_index)) + { + m_queue->m_data[index].~Type(); - poppedItems++; + poppedItems++; - m_queue->m_manager.commitPopIndex(generation, index); - } + m_queue->m_manager.commitPopIndex(generation, index); + } - // And release + // And release - m_queue->m_manager.abortPushIndexReservation(m_generation, m_index); + m_queue->m_manager.abortPushIndexReservation(m_generation, m_index); - while (poppedItems--) - { - m_queue->m_pushSemaphore.notify(); - } + while (poppedItems--) + { + m_queue->m_pushSemaphore.notify(); } } + } - template - void - QueuePushGuard::release() - { - m_queue = nullptr; - } + template + void + QueuePushGuard::release() + { + m_queue = nullptr; + } - template - QueuePopGuard::~QueuePopGuard() - { - m_queue.m_data[m_index].~Type(); - m_queue.m_manager.commitPopIndex(m_generation, m_index); + template + QueuePopGuard::~QueuePopGuard() + { + m_queue.m_data[m_index].~Type(); + m_queue.m_manager.commitPopIndex(m_generation, m_index); - // Notify a pusher - if (m_queue.m_waitingPushers > 0) - { - m_queue.m_pushSemaphore.notify(); - } + // Notify a pusher + if (m_queue.m_waitingPushers > 0) + { + m_queue.m_pushSemaphore.notify(); } + } - } // namespace thread -} // namespace llarp +} // namespace llarp::thread diff --git a/llarp/util/thread/threading.hpp b/llarp/util/thread/threading.hpp index 7fb31e4c3b..1f004bacb8 100644 --- a/llarp/util/thread/threading.hpp +++ b/llarp/util/thread/threading.hpp @@ -1,7 +1,5 @@ #pragma once -#include "annotations.hpp" - #include #include #include @@ -18,165 +16,141 @@ using pid_t = int; #include #endif -#ifdef TRACY_ENABLE -#include - -#define DECLARE_LOCK(type, var, ...) TracyLockable(type, var) -#else -#define DECLARE_LOCK(type, var, ...) type var __VA_ARGS__ -#endif - -namespace llarp +namespace llarp::util { - namespace util + /// a mutex that does nothing + /// + /// this exists to convert mutexes that were initially in use (but may no + /// longer be necessary) into no-op placeholders (except in debug mode + /// where they complain loudly when they are actually accessed across + /// different threads; see below). + /// + /// the idea is to "turn off" the mutexes and see where they are actually + /// needed. + struct NullMutex { - /// a mutex that does nothing - /// - /// this exists to convert mutexes that were initially in use (but may no - /// longer be necessary) into no-op placeholders (except in debug mode - /// where they complain loudly when they are actually accessed across - /// different threads; see below). - /// - /// the idea is to "turn off" the mutexes and see where they are actually - /// needed. - struct CAPABILITY("mutex") NullMutex - { #ifdef LOKINET_DEBUG - /// in debug mode, we implement lock() to enforce that any lock is only - /// used from a single thread. the point of this is to identify locks that - /// are actually needed by dying a painful death when used across threads - mutable std::optional m_id; - void - lock() const - { - if (!m_id) - { - m_id = std::this_thread::get_id(); - } - else if (*m_id != std::this_thread::get_id()) - { - std::cerr << "NullMutex " << this << " was used across threads: locked by " - << std::this_thread::get_id() << " and was previously locked by " << *m_id - << "\n"; - // if you're encountering this abort() call, you may have discovered a - // case where a NullMutex should be reverted to a "real mutex" - std::abort(); - } - } -#else - void - lock() const - {} -#endif - // Does nothing; once locked the mutex belongs to that thread forever - void - unlock() const - {} - }; - - /// a lock that does nothing - struct SCOPED_CAPABILITY NullLock + /// in debug mode, we implement lock() to enforce that any lock is only + /// used from a single thread. the point of this is to identify locks that + /// are actually needed by dying a painful death when used across threads + mutable std::optional m_id; + void + lock() const { - NullLock(NullMutex& mtx) ACQUIRE(mtx) + if (!m_id) { - mtx.lock(); + m_id = std::this_thread::get_id(); } - - ~NullLock() RELEASE() + else if (*m_id != std::this_thread::get_id()) { - (void)this; // trick clang-tidy + std::cerr << "NullMutex " << this << " was used across threads: locked by " + << std::this_thread::get_id() << " and was previously locked by " << *m_id + << "\n"; + // if you're encountering this abort() call, you may have discovered a + // case where a NullMutex should be reverted to a "real mutex" + std::abort(); } - }; - - /// Default mutex type, supporting shared and exclusive locks. - using Mutex = std::shared_timed_mutex; - - /// Basic RAII lock type for the default mutex type. - using Lock = std::lock_guard; + } +#else + void + lock() const + {} +#endif + // Does nothing; once locked the mutex belongs to that thread forever + void + unlock() const + {} + }; - /// Obtains multiple unique locks simultaneously and atomically. Returns a - /// tuple of all the held locks. - template - [[nodiscard]] auto - unique_locks(Mutex&... lockables) + /// a lock that does nothing + struct NullLock + { + NullLock(NullMutex& mtx) { - std::lock(lockables...); - return std::make_tuple(std::unique_lock{lockables, std::adopt_lock}...); + mtx.lock(); } - class Semaphore + ~NullLock() { - private: - std::mutex m_mutex; // protects m_count - size_t m_count GUARDED_BY(m_mutex); - std::condition_variable m_cv; + (void)this; // trick clang-tidy + } + }; - public: - Semaphore(size_t count) : m_count(count) - {} + /// Default mutex type, supporting shared and exclusive locks. + using Mutex = std::shared_timed_mutex; - void - notify() EXCLUDES(m_mutex) - { - { - std::lock_guard lock(m_mutex); - m_count++; - } - m_cv.notify_one(); - } + /// Basic RAII lock type for the default mutex type. + using Lock = std::lock_guard; - void - wait() EXCLUDES(m_mutex) - { - std::unique_lock lock{m_mutex}; - m_cv.wait(lock, [this] { return m_count > 0; }); - m_count--; - } + class Semaphore + { + private: + std::mutex m_mutex; // protects m_count + size_t m_count; + std::condition_variable m_cv; - bool - waitFor(std::chrono::microseconds timeout) EXCLUDES(m_mutex) - { - std::unique_lock lock{m_mutex}; - if (!m_cv.wait_for(lock, timeout, [this] { return m_count > 0; })) - return false; + public: + Semaphore(size_t count) : m_count(count) + {} - m_count--; - return true; + void + notify() + { + { + std::lock_guard lock(m_mutex); + m_count++; } - }; + m_cv.notify_one(); + } void - SetThreadName(const std::string& name); + wait() + { + std::unique_lock lock{m_mutex}; + m_cv.wait(lock, [this] { return m_count > 0; }); + m_count--; + } - inline pid_t - GetPid() + bool + waitFor(std::chrono::microseconds timeout) { + std::unique_lock lock{m_mutex}; + if (!m_cv.wait_for(lock, timeout, [this] { return m_count > 0; })) + return false; + + m_count--; + return true; + } + }; + + void + SetThreadName(const std::string& name); + + inline pid_t + GetPid() + { #ifdef WIN32 - return _getpid(); + return _getpid(); #else - return ::getpid(); + return ::getpid(); #endif - } + } - // type for detecting contention on a resource - struct ContentionKiller + // type for detecting contention on a resource + struct ContentionKiller + { + template + void + TryAccess(F visit) const { - template - void - TryAccess(F visit) const #if defined(LOKINET_DEBUG) - EXCLUDES(_access) + NullLock lock(_access); #endif - { -#if defined(LOKINET_DEBUG) - NullLock lock(_access); -#endif - visit(); - } + visit(); + } #if defined(LOKINET_DEBUG) - private: - mutable NullMutex _access; + private: + mutable NullMutex _access; #endif - }; - } // namespace util -} // namespace llarp + }; +} // namespace llarp::util From 127ac2c9aa37294b3d186688cd363c98d12d46d5 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Wed, 25 Oct 2023 12:54:12 -0700 Subject: [PATCH 075/312] windows fixes --- .clang-format | 6 ++++-- daemon/lokinet.cpp | 2 -- llarp/util/str.cpp | 3 ++- llarp/vpn/win32.hpp | 3 ++- llarp/win32/service_manager.cpp | 4 ---- llarp/win32/service_manager.hpp | 4 ++++ llarp/win32/win32_inet.c | 3 ++- 7 files changed, 14 insertions(+), 11 deletions(-) diff --git a/.clang-format b/.clang-format index ef24da8a0a..02f6e2e079 100644 --- a/.clang-format +++ b/.clang-format @@ -69,7 +69,9 @@ IncludeCategories: Priority: 3 - Regex: '' Priority: 4 - - Regex: '^<.*\.h(pp)?>$' + - Regex: '' Priority: 5 - - Regex: '(<)(.)+(>)' + - Regex: '^<.*\.h(pp)?>$' Priority: 6 + - Regex: '(<)(.)+(>)' + Priority: 7 diff --git a/daemon/lokinet.cpp b/daemon/lokinet.cpp index f439006693..3102110820 100644 --- a/daemon/lokinet.cpp +++ b/daemon/lokinet.cpp @@ -25,8 +25,6 @@ #ifdef _WIN32 #include - -#include #else #include #endif diff --git a/llarp/util/str.cpp b/llarp/util/str.cpp index 3fed7ea44e..79329d7561 100644 --- a/llarp/util/str.cpp +++ b/llarp/util/str.cpp @@ -6,8 +6,9 @@ #ifdef _WIN32 #include -#include #include + +#include #endif namespace llarp diff --git a/llarp/vpn/win32.hpp b/llarp/vpn/win32.hpp index ac0f5e01a8..799254cc6a 100644 --- a/llarp/vpn/win32.hpp +++ b/llarp/vpn/win32.hpp @@ -8,9 +8,10 @@ #include -#include #include +#include + namespace llarp::win32 { using namespace llarp::vpn; diff --git a/llarp/win32/service_manager.cpp b/llarp/win32/service_manager.cpp index df682e5186..6b3167514a 100644 --- a/llarp/win32/service_manager.cpp +++ b/llarp/win32/service_manager.cpp @@ -3,9 +3,6 @@ #include #include -#include -#include - #include #include #include @@ -18,7 +15,6 @@ namespace llarp::sys namespace { - std::optional to_win32_state(ServiceState st) { diff --git a/llarp/win32/service_manager.hpp b/llarp/win32/service_manager.hpp index 37a8f54c6f..425263382b 100644 --- a/llarp/win32/service_manager.hpp +++ b/llarp/win32/service_manager.hpp @@ -2,6 +2,10 @@ #include #include +#include + +#include + #include namespace llarp::sys diff --git a/llarp/win32/win32_inet.c b/llarp/win32/win32_inet.c index 8357947518..437e3a5326 100644 --- a/llarp/win32/win32_inet.c +++ b/llarp/win32/win32_inet.c @@ -11,10 +11,11 @@ // these need to be in a specific order #include +#include + #include #include #include -#include const char* inet_ntop(int af, const void* src, char* dst, size_t size) From acf494098a13ced34b3670019b781be3e81d7b2d Mon Sep 17 00:00:00 2001 From: dr7ana Date: Wed, 25 Oct 2023 12:58:47 -0700 Subject: [PATCH 076/312] squash --- llarp/apple/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llarp/apple/CMakeLists.txt b/llarp/apple/CMakeLists.txt index d1ae8b698c..3a96efefb9 100644 --- a/llarp/apple/CMakeLists.txt +++ b/llarp/apple/CMakeLists.txt @@ -11,7 +11,7 @@ find_library(FOUNDATION Foundation REQUIRED) find_library(NETEXT NetworkExtension REQUIRED) find_library(COREFOUNDATION CoreFoundation REQUIRED) -target_link_libraries(lokinet-base PUBLIC ${FOUNDATION}) +target_link_libraries(lokinet-base INTERFACE ${FOUNDATION}) target_sources(lokinet-platform PRIVATE vpn_platform.cpp vpn_interface.cpp route_manager.cpp context_wrapper.cpp) @@ -27,7 +27,7 @@ enable_lto(lokinet-extension) target_compile_options(lokinet-extension PRIVATE -fobjc-arc) if(MACOS_SYSTEM_EXTENSION) target_compile_definitions(lokinet-extension PRIVATE MACOS_SYSTEM_EXTENSION) - target_compile_definitions(lokinet-base PUBLIC MACOS_SYSTEM_EXTENSION) + target_compile_definitions(lokinet-base INTERFACE MACOS_SYSTEM_EXTENSION) else() target_link_options(lokinet-extension PRIVATE -e _NSExtensionMain) endif() From 6d6301daee048a70c1f88bcdf727e8a0608ec4f5 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Wed, 25 Oct 2023 17:00:51 -0300 Subject: [PATCH 077/312] Disable Router Hive & DEB builds They aren't useful right now. --- .drone.jsonnet | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.drone.jsonnet b/.drone.jsonnet index 979e641526..04b04baa22 100644 --- a/.drone.jsonnet +++ b/.drone.jsonnet @@ -460,6 +460,7 @@ local docs_pipeline(name, image, extra_cmds=[], allow_fail=false) = { ], jobs=4), + /* // integration tests debian_pipeline('Router Hive', docker_base + 'ubuntu-lts', @@ -471,6 +472,7 @@ local docs_pipeline(name, image, extra_cmds=[], allow_fail=false) = { deb_builder(docker_base + 'debian-bullseye-builder', 'bullseye', 'debian/bullseye'), deb_builder(docker_base + 'ubuntu-jammy-builder', 'jammy', 'ubuntu/jammy'), deb_builder(docker_base + 'debian-sid-builder', 'sid', 'debian/sid', arch='arm64'), + */ // Macos builds: mac_builder('macOS (Release)', extra_cmds=[ From b909f537fe44b03e11e39ac69511542f7ba8e91b Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Wed, 25 Oct 2023 17:14:54 -0300 Subject: [PATCH 078/312] Default libcrypt to whether or not we find it Also deliberately don't provide the function at all if we aren't compiled with libcrypt so that we can't link if we try to call it when not available. --- external/CMakeLists.txt | 5 ++++- llarp/crypto/crypto.cpp | 6 ++---- llarp/service/auth.cpp | 2 ++ 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index f901be4c34..e8eca96e47 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -139,7 +139,10 @@ endif() set(default_libcrypt OFF) if(LINUX AND NOT STATIC_LINK) - set(default_libcrypt ON) + pkg_check_modules(LIBCRYPT libcrypt IMPORTED_TARGET) + if(LIBCRYPTO_FOUND) + set(default_libcrypt ON) + endif() endif() if(MACOS) set(default_libcrypt ON) diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index 81b9cd57df..f8a61535a4 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -499,13 +499,11 @@ namespace llarp crypto_kem_keypair(d + PQ_SECRETKEYSIZE, d); } +#ifdef HAVE_CRYPT bool crypto::check_passwd_hash(std::string pwhash, std::string challenge) { - (void)pwhash; - (void)challenge; bool ret = false; -#ifdef HAVE_CRYPT auto pos = pwhash.find_last_of('$'); auto settings = pwhash.substr(0, pos); crypt_data data{}; @@ -514,9 +512,9 @@ namespace llarp ret = ptr == pwhash; } sodium_memzero(&data, sizeof(data)); -#endif return ret; } +#endif const byte_t* seckey_topublic(const SecretKey& sec) diff --git a/llarp/service/auth.cpp b/llarp/service/auth.cpp index b5a6c97e81..17fbda0cb7 100644 --- a/llarp/service/auth.cpp +++ b/llarp/service/auth.cpp @@ -125,7 +125,9 @@ namespace llarp::service case AuthFileType::eAuthFilePlain: return hash == challenge; case AuthFileType::eAuthFileHashes: +#ifdef HAVE_CRYPT return crypto::check_passwd_hash(std::move(hash), std::move(challenge)); +#endif default: return false; } From 57c471e7a2cca40946c4109998d41cbf893fa934 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Wed, 25 Oct 2023 17:18:16 -0300 Subject: [PATCH 079/312] Bump WinDivert to latest There are some bugfix releases, but also the upstream hash was wrong for the current release anyway (upstream changed it?). --- cmake/win32.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/win32.cmake b/cmake/win32.cmake index a8f977c284..e75074fb4f 100644 --- a/cmake/win32.cmake +++ b/cmake/win32.cmake @@ -25,11 +25,11 @@ set(WINTUN_SOURCE wintun-${WINTUN_VERSION}.zip) set(WINTUN_HASH SHA256=07c256185d6ee3652e09fa55c0b673e2624b565e02c4b9091c79ca7d2f24ef51 CACHE STRING "wintun source hash") -set(WINDIVERT_VERSION 2.2.0-A CACHE STRING "windivert version") +set(WINDIVERT_VERSION 2.2.2-A CACHE STRING "windivert version") set(WINDIVERT_MIRROR https://reqrypt.org/download CACHE STRING "windivert mirror(s)") set(WINDIVERT_SOURCE WinDivert-${WINDIVERT_VERSION}.zip) -set(WINDIVERT_HASH SHA256=2a7630aac0914746fbc565ac862fa096e3e54233883ac52d17c83107496b7a7f +set(WINDIVERT_HASH SHA512=92eb2ef98ced175d44de1cdb7c52f2ebc534b6a997926baeb83bfe94cba9287b438f796aff11f6163918bcdbc25bcd4e3383715f139f690d207ce219f846a345 CACHE STRING "windivert source hash") set(WINTUN_URL ${WINTUN_MIRROR}/${WINTUN_SOURCE} From c46c18ea30d4986909ee73c89cf884a888de7c59 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 26 Oct 2023 08:57:12 -0700 Subject: [PATCH 080/312] Bump libzmq static; remove patches --- cmake/StaticBuild.cmake | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/cmake/StaticBuild.cmake b/cmake/StaticBuild.cmake index d6663ed9fe..d6e6621bed 100644 --- a/cmake/StaticBuild.cmake +++ b/cmake/StaticBuild.cmake @@ -41,11 +41,11 @@ set(SODIUM_SOURCE libsodium-${SODIUM_VERSION}.tar.gz) set(SODIUM_HASH SHA512=17e8638e46d8f6f7d024fe5559eccf2b8baf23e143fadd472a7d29d228b186d86686a5e6920385fe2020729119a5f12f989c3a782afbd05a8db4819bb18666ef CACHE STRING "libsodium source hash") -set(ZMQ_VERSION 4.3.4 CACHE STRING "libzmq version") +set(ZMQ_VERSION 4.3.5 CACHE STRING "libzmq version") set(ZMQ_MIRROR ${LOCAL_MIRROR} https://github.com/zeromq/libzmq/releases/download/v${ZMQ_VERSION} CACHE STRING "libzmq mirror(s)") set(ZMQ_SOURCE zeromq-${ZMQ_VERSION}.tar.gz) -set(ZMQ_HASH SHA512=e198ef9f82d392754caadd547537666d4fba0afd7d027749b3adae450516bcf284d241d4616cad3cb4ad9af8c10373d456de92dc6d115b037941659f141e7c0e +set(ZMQ_HASH SHA512=a71d48aa977ad8941c1609947d8db2679fc7a951e4cd0c3a1127ae026d883c11bd4203cf315de87f95f5031aec459a731aec34e5ce5b667b8d0559b157952541 CACHE STRING "libzmq source hash") set(LIBUV_VERSION 1.44.2 CACHE STRING "libuv version") @@ -352,16 +352,9 @@ if(ARCH_TRIPLET MATCHES mingw) endif() endif() -if(CMAKE_CROSSCOMPILING AND ARCH_TRIPLET MATCHES mingw) - set(zmq_patch - PATCH_COMMAND ${PROJECT_SOURCE_DIR}/contrib/apply-patches.sh - ${PROJECT_SOURCE_DIR}/contrib/patches/libzmq-mingw-wepoll.patch - ${PROJECT_SOURCE_DIR}/contrib/patches/libzmq-mingw-unistd.patch) -endif() build_external(zmq DEPENDS sodium_external - ${zmq_patch} CONFIGURE_COMMAND ./configure ${cross_host} --prefix=${DEPS_DESTDIR} --enable-static --disable-shared --disable-curve-keygen --enable-curve --disable-drafts --disable-libunwind --with-libsodium --without-pgm --without-norm --without-vmci --without-docs --with-pic --disable-Werror --disable-libbsd ${zmq_extra} @@ -370,6 +363,7 @@ build_external(zmq ) add_static_target(libzmq zmq_external libzmq.a) + set(libzmq_link_libs "sodium") if(CMAKE_CROSSCOMPILING AND ARCH_TRIPLET MATCHES mingw) list(APPEND libzmq_link_libs iphlpapi) From 98583b8f58f35a08aaa79e7e942ee056474bd804 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 26 Oct 2023 09:20:49 -0700 Subject: [PATCH 081/312] Windows CI fixes - some weird function call business - string formatting - etc --- daemon/lokinet.cpp | 3 ++- llarp/util/str.cpp | 18 ++++++++++++++++++ llarp/util/str.hpp | 6 ++++++ llarp/vpn/win32.cpp | 4 +++- llarp/win32/guid.hpp | 9 ++++++--- 5 files changed, 35 insertions(+), 5 deletions(-) diff --git a/daemon/lokinet.cpp b/daemon/lokinet.cpp index 3102110820..b56227f404 100644 --- a/daemon/lokinet.cpp +++ b/daemon/lokinet.cpp @@ -275,7 +275,8 @@ namespace (MINIDUMP_TYPE)(MiniDumpWithFullMemory | MiniDumpWithFullMemoryInfo | MiniDumpWithHandleData | MiniDumpWithUnloadedModules | MiniDumpWithThreadInfo); const std::string fname = - "C:\\ProgramData\\lokinet\\crash-{}.dump"_format(llarp::time_now_ms().count()); + fmt::format("C:\\ProgramData\\lokinet\\crash-{}.dump", llarp::time_now_ms().count()); + HANDLE hDumpFile; SYSTEMTIME stLocalTime; GetLocalTime(&stLocalTime); diff --git a/llarp/util/str.cpp b/llarp/util/str.cpp index 79329d7561..84c4887309 100644 --- a/llarp/util/str.cpp +++ b/llarp/util/str.cpp @@ -95,4 +95,22 @@ namespace llarp ch = ch + ('a' - 'A'); return src; } + + std::wstring + to_wide(std::string data) + { + std::wstring buf; + buf.resize(data.size()); +#ifdef _WIN32 + // win32 specific codepath because balmer made windows so that man may suffer + if (MultiByteToWideChar(CP_UTF8, 0, data.c_str(), data.size(), buf.data(), buf.size()) == 0) + throw win32::error{GetLastError(), "failed to convert string to wide string"}; + +#else + // this dumb but probably works (i guess?) + std::transform( + data.begin(), data.end(), buf.begin(), [](const auto& ch) -> wchar_t { return ch; }); +#endif + return buf; + } } // namespace llarp diff --git a/llarp/util/str.hpp b/llarp/util/str.hpp index 0ea7838989..7f4085fc59 100644 --- a/llarp/util/str.hpp +++ b/llarp/util/str.hpp @@ -2,6 +2,7 @@ #include +#include #include #include #include @@ -96,4 +97,9 @@ namespace llarp std::string_view TrimWhitespace(std::string_view str); + + /// convert a "normal" string into a wide string + std::wstring + to_wide(std::string data); + } // namespace llarp diff --git a/llarp/vpn/win32.cpp b/llarp/vpn/win32.cpp index 1e8dee467e..9ca93a25dc 100644 --- a/llarp/vpn/win32.cpp +++ b/llarp/vpn/win32.cpp @@ -89,8 +89,10 @@ namespace llarp::win32 if (not range.Contains(ifaddr)) b = false; } + // TODO: FIXME if (b) - gateways.emplace(*iface.gateway); + throw std::runtime_error{"FIXME ALREADY"}; + // gateways.emplace(*iface.gateway); } return {gateways.begin(), gateways.end()}; } diff --git a/llarp/win32/guid.hpp b/llarp/win32/guid.hpp index 06de11b1e0..567a9586fb 100644 --- a/llarp/win32/guid.hpp +++ b/llarp/win32/guid.hpp @@ -15,12 +15,15 @@ namespace llarp::win32 MakeDeterministicGUID(Data data) { ShortHash h{}; - auto hash = [&h](auto data) { crypto::shorthash(h, data); }; + auto hash = [&h](uint8_t* d, size_t size) { crypto::shorthash(h, d, size); }; if constexpr (std::is_same_v) - hash(llarp_buffer_t{reinterpret_cast(data.data()), data.size()}); + hash(reinterpret_cast(data.data()), data.size()); else - hash(llarp_buffer_t{data}); + { + auto dat = llarp_buffer_t{data}; + hash(dat.base, dat.sz); + } GUID guid{}; std::copy_n( h.begin(), std::min(sizeof(GUID), sizeof(ShortHash)), reinterpret_cast(&guid)); From eb37796b650ee7f1f656ced3616c24eafbb3cc9a Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Thu, 26 Oct 2023 13:50:39 -0300 Subject: [PATCH 082/312] Bump oxen-mq for libzmq llvm static build fix --- external/oxen-mq | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/oxen-mq b/external/oxen-mq index 68b3420bad..a27961d787 160000 --- a/external/oxen-mq +++ b/external/oxen-mq @@ -1 +1 @@ -Subproject commit 68b3420bad5f0384f06d378b89ccdc06aba07465 +Subproject commit a27961d787c9065f2bf6da9d60d01dca2e125739 From cb2a2cf6e36ec93f840ab8ff8fb0d284247c9296 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 26 Oct 2023 12:22:49 -0700 Subject: [PATCH 083/312] Weird clang unused variable CI fix --- llarp/exit/session.cpp | 33 ++------------------------------- llarp/exit/session.hpp | 10 +++------- 2 files changed, 5 insertions(+), 38 deletions(-) diff --git a/llarp/exit/session.cpp b/llarp/exit/session.cpp index 158b026510..c6bdc009ba 100644 --- a/llarp/exit/session.cpp +++ b/llarp/exit/session.cpp @@ -20,11 +20,10 @@ namespace llarp::exit : llarp::path::Builder{r, numpaths, hoplen} , exit_router{routerId} , packet_write_func{std::move(writepkt)} - , _counter{0} , _last_use{r->now()} - , m_BundleRC{false} - , m_Parent{parent} + , _parent{parent} { + (void)_parent; crypto::identity_keygen(exit_key); } @@ -219,34 +218,6 @@ namespace llarp::exit return true; } - bool - BaseSession::QueueUpstreamTraffic(llarp::net::IPPacket, const size_t, service::ProtocolType) - { - // auto& queue = m_Upstream[pkt.size() / N]; - // queue overflow - // if (queue.size() >= MaxUpstreamQueueLength) - // return false; - // if (queue.size() == 0) - // { - // queue.emplace_back(); - // queue.back().protocol = t; - // return queue.back().PutBuffer(llarp_buffer_t{pkt}, _counter++); - // } - - // auto& back = queue.back(); - // // pack to nearest N - // if (back.Size() + pkt.size() > N) - // { - // queue.emplace_back(); - // queue.back().protocol = t; - // return queue.back().PutBuffer(llarp_buffer_t{pkt}, _counter++); - // } - // back.protocol = t; - // return back.PutBuffer(llarp_buffer_t{pkt}, _counter++); - - return true; - } - bool BaseSession::IsReady() const { diff --git a/llarp/exit/session.hpp b/llarp/exit/session.hpp index 4351517434..ac5da8f84a 100644 --- a/llarp/exit/session.hpp +++ b/llarp/exit/session.hpp @@ -81,10 +81,6 @@ namespace llarp void HandlePathBuilt(llarp::path::Path_ptr p) override; - bool - QueueUpstreamTraffic( - llarp::net::IPPacket pkt, const size_t packSize, service::ProtocolType t); - /// flush upstream to exit via paths bool FlushUpstream(); @@ -163,12 +159,12 @@ namespace llarp } }; - [[maybe_unused]] uint64_t _counter; + // uint64_t _counter; llarp_time_t _last_use; std::vector m_PendingCallbacks; - [[maybe_unused]] const bool m_BundleRC; - [[maybe_unused]] EndpointBase* const m_Parent; + // const bool _bundle_RC; + EndpointBase* const _parent; void CallPendingCallbacks(bool success); From 63b8fd49cc7f11c638a7336d19d06252ed8ac2da Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Thu, 26 Oct 2023 16:10:12 -0300 Subject: [PATCH 084/312] Don't export CC This was causing cmake to double-invoke ccache for compilation units, and broke oxen-mq's local zmq build for the same reason. --- .drone.jsonnet | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.drone.jsonnet b/.drone.jsonnet index 04b04baa22..698f0af22f 100644 --- a/.drone.jsonnet +++ b/.drone.jsonnet @@ -104,16 +104,15 @@ local local_gnutls(jobs=6, prefix='/usr/local') = [ apt_get_quiet + ' install -y curl ca-certificates', 'curl -sSL https://ftp.gnu.org/gnu/nettle/nettle-3.9.1.tar.gz | tar xfz -', 'curl -sSL https://www.gnupg.org/ftp/gcrypt/gnutls/v3.8/gnutls-3.8.0.tar.xz | tar xfJ -', - 'export CC="ccache gcc"', 'export PKG_CONFIG_PATH=' + prefix + '/lib/pkgconfig:' + prefix + '/lib64/pkgconfig', 'export LD_LIBRARY_PATH=' + prefix + '/lib:' + prefix + '/lib64', 'cd nettle-3.9.1', - './configure --prefix=' + prefix, + './configure --prefix=' + prefix + ' CC="ccache gcc"', 'make -j' + jobs, 'make install', 'cd ..', 'cd gnutls-3.8.0', - './configure --prefix=' + prefix + ' --with-included-libtasn1 --with-included-unistring --without-p11-kit --disable-libdane --disable-cxx --without-tpm --without-tpm2', + './configure --prefix=' + prefix + ' --with-included-libtasn1 --with-included-unistring --without-p11-kit --disable-libdane --disable-cxx --without-tpm --without-tpm2 CC="ccache gcc"', 'make -j' + jobs, 'make install', 'cd ..', From b3c3dcf33ac1ec0daf5d3bfe93dcbbf25607360f Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Thu, 26 Oct 2023 16:57:06 -0300 Subject: [PATCH 085/312] Bump armhf static build to bullseye Use backports for cmake because ngtcp2 needs 3.20+. --- .drone.jsonnet | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/.drone.jsonnet b/.drone.jsonnet index 698f0af22f..f70a2fbf35 100644 --- a/.drone.jsonnet +++ b/.drone.jsonnet @@ -38,6 +38,12 @@ local kitware_repo(distro) = [ 'eatmydata ' + apt_get_quiet + ' update', ]; +local debian_backports(distro, pkgs) = [ + 'echo "deb http://deb.debian.org/debian ' + distro + '-backports main" >/etc/apt/sources.list.d/' + distro + '-backports.list', + 'eatmydata ' + apt_get_quiet + ' update', + 'eatmydata ' + apt_get_quiet + ' install -y ' + std.join(' ', std.map(function(x) x + '/' + distro + '-backports', pkgs)), +]; + // Regular build on a debian-like system: local debian_pipeline(name, image, @@ -445,11 +451,11 @@ local docs_pipeline(name, image, extra_cmds=[], allow_fail=false) = { './contrib/ci/drone-static-upload.sh', ]), // Static armhf build (gets uploaded) - debian_pipeline('Static (buster armhf)', - docker_base + 'debian-buster/arm32v7', + debian_pipeline('Static (bullseye armhf)', + docker_base + 'debian-bullseye/arm32v7', arch='arm64', deps=['g++', 'python3-dev', 'automake', 'libtool'], - extra_setup=kitware_repo('bionic'), + extra_setup=debian_backports('bullseye', ['cmake']), cmake_extra='-DBUILD_STATIC_DEPS=ON -DBUILD_SHARED_LIBS=OFF -DSTATIC_LINK=ON ' + '-DCMAKE_CXX_FLAGS="-march=armv7-a+fp -Wno-psabi" -DCMAKE_C_FLAGS="-march=armv7-a+fp" ' + '-DNATIVE_BUILD=OFF -DWITH_SYSTEMD=OFF -DWITH_BOOTSTRAP=OFF', From 46482c03a6503ac0aeda4407da087f592d836c89 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Fri, 27 Oct 2023 11:34:18 -0300 Subject: [PATCH 086/312] Remove unused file --- cmake/static_link.cmake | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 cmake/static_link.cmake diff --git a/cmake/static_link.cmake b/cmake/static_link.cmake deleted file mode 100644 index 6dc602c259..0000000000 --- a/cmake/static_link.cmake +++ /dev/null @@ -1,7 +0,0 @@ -if(STATIC_LINK) - if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - link_libraries( -static-libstdc++ ) - else() - link_libraries( -static-libstdc++ -static-libgcc ) - endif() -endif() From c3641ab22c053c354367ffe740d78279ef4d63f5 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Thu, 26 Oct 2023 17:09:01 -0300 Subject: [PATCH 087/312] Turn off terrible new cmake 3.24+ default --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f50d4b313..4b707a0f50 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,11 @@ cmake_minimum_required(VERSION 3.13...3.24) # 3.13 is buster's version +# Cmake 3.24+ breaks extraction timestamps by default, hurray, but the option to not break +# timestamps fails in cmake <3.24, extra hurray! +if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.24) + cmake_policy(SET CMP0135 OLD) +endif() + set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Has to be set before `project()`, and ignored on non-macos: From ca5ed01b2c12e5f12414fb9fa4646db5a9bb2c04 Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Fri, 27 Oct 2023 12:49:58 -0300 Subject: [PATCH 088/312] Bump libquic to latest for static build fixes --- external/oxen-libquic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/oxen-libquic b/external/oxen-libquic index 33982d24a3..6ee6ed398d 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit 33982d24a380268933ebea33976ad806e5c4e4bb +Subproject commit 6ee6ed398d00043d862466a56279b5c502513bff From 431490fb8b432336a6bbaa3b77ef1e6f39306dda Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Fri, 27 Oct 2023 12:45:37 -0300 Subject: [PATCH 089/312] Give up for now --- .drone.jsonnet | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.drone.jsonnet b/.drone.jsonnet index f70a2fbf35..e69e53cbc5 100644 --- a/.drone.jsonnet +++ b/.drone.jsonnet @@ -451,7 +451,7 @@ local docs_pipeline(name, image, extra_cmds=[], allow_fail=false) = { './contrib/ci/drone-static-upload.sh', ]), // Static armhf build (gets uploaded) - debian_pipeline('Static (bullseye armhf)', + debian_pipeline('Static [FIXME] (bullseye armhf)', docker_base + 'debian-bullseye/arm32v7', arch='arm64', deps=['g++', 'python3-dev', 'automake', 'libtool'], @@ -463,6 +463,7 @@ local docs_pipeline(name, image, extra_cmds=[], allow_fail=false) = { './contrib/ci/drone-check-static-libs.sh', 'UPLOAD_OS=linux-armhf ./contrib/ci/drone-static-upload.sh', ], + allow_fail=true, // XXX FIXME: build currently fails! jobs=4), /* From 632f4ee70b10b2b0079375debd76e99d824ad705 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Tue, 31 Oct 2023 13:49:01 -0700 Subject: [PATCH 090/312] 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 4b707a0f50..8c3b407d82 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 e1ad9cb4dd..afdecec72a 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 b56227f404..67ac4a6711 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 06e4ac5b2d..cce2e29b5d 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 6247573223..f5a795ea0e 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 e28652d9db..64d473564e 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 66b55dd4c5..c740528190 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 3df6618473..3df244dea2 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 e072237058..60d3af6ae2 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 1bfd68d31a..f79b842e2c 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 be4f61d976..ab8ae70f98 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 f8a61535a4..7b6aa046ae 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 370b23e34a..1b5c9a2390 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 30d4a3a9ad..c7a141bbd3 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 e4188c35d4..a91192770f 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 776d8cb37e..6508898b47 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 0f2deecc23..36ac3e9d56 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 3702c3f2ae..008e12b26d 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 82c7b7b440..de184ea529 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 f3f5047955..e6515b7f42 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 96e37de7fb..66cde4bb71 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 e4885c620c..17bd63ba32 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 cabc2aa9da..7f816d61b8 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 cc6d2a28be..d3b7ee02ce 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 7717b5ff5e..17fe4ffbd6 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 75be48791b..e5760c1a21 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 7b78ead31a..ec4d3fa3d5 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 3ae00f3872..a8da6cec11 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 429a4b697d..a380a54b14 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 8cb96b10d2..4c26d748b1 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 76c948d1ca..b64ff9e9e7 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 1aa99d9a1f..885e3fcf56 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 6354b37c62..c20a3e57e4 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 d57866222a..01a9d5f643 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 7e8e1fdcef..d2a0f54a66 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 0000000000..275b3c64e7 --- /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 0000000000..f17100310d --- /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 273460f914..8a82f924d5 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 dfbcb253f3..c9390b3b7f 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 9e7581e50d..92a7d71b37 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 3b1a4dc443..7b54516128 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 3452146b5c..b6333dcd7c 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 bcc2960efa..6848e4698a 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 aae0fe3b1e..fcde4efbcb 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 ff929d0166..26b21d9874 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 a66b1555fa..82ff2bfbc2 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 From 68e67c881bf5ecf2d2d479e0df338004f2113f3f Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 2 Nov 2023 05:30:38 -0700 Subject: [PATCH 091/312] {Remote,Local}RC's - RemoteRC supplants most of the functionality throughout the code of RouterContact - Next step will be to sort out CI issues, then see if we can get rid of either LocalRC (and therefore RouterContact entirely) --- llarp/bootstrap-fallbacks.cpp.in | 13 ++- llarp/bootstrap.cpp | 71 ++++++------ llarp/bootstrap.hpp | 15 ++- llarp/bootstrap_fallbacks.cpp | 18 +-- llarp/config/config.cpp | 8 +- llarp/config/config.hpp | 2 +- llarp/config/key_manager.cpp | 4 +- llarp/context.cpp | 4 +- llarp/crypto/crypto.hpp | 3 +- llarp/crypto/types.cpp | 16 +-- llarp/crypto/types.hpp | 3 - llarp/exit/session.cpp | 6 +- llarp/exit/session.hpp | 2 +- llarp/handlers/exit.cpp | 28 +---- llarp/handlers/tun.cpp | 4 +- llarp/link/connection.cpp | 2 +- llarp/link/connection.hpp | 4 +- llarp/link/link_manager.cpp | 16 +-- llarp/link/link_manager.hpp | 14 +-- llarp/messages/path.hpp | 4 +- llarp/messages/relay.cpp | 4 +- llarp/nodedb.cpp | 46 ++++---- llarp/nodedb.hpp | 18 +-- llarp/path/path.cpp | 26 +++-- llarp/path/path.hpp | 2 +- llarp/path/path_types.hpp | 2 +- llarp/path/pathbuilder.cpp | 53 +++++---- llarp/path/pathbuilder.hpp | 8 +- llarp/path/pathset.hpp | 4 +- llarp/profiling.cpp | 2 +- llarp/router/rc_gossiper.cpp | 4 +- llarp/router/rc_gossiper.hpp | 6 +- llarp/router/rc_lookup_handler.cpp | 40 ++----- llarp/router/rc_lookup_handler.hpp | 13 +-- llarp/router/route_poker.cpp | 2 +- llarp/router/router.cpp | 168 +++++++++------------------- llarp/router/router.hpp | 33 ++---- llarp/router_contact.cpp | 71 +++++------- llarp/router_contact.hpp | 141 ++++++++++++++--------- llarp/router_contact_local.cpp | 60 +++++++--- llarp/router_contact_remote.cpp | 77 +++++++++---- llarp/rpc/lokid_rpc_client.cpp | 2 +- llarp/rpc/rpc_server.cpp | 4 +- llarp/service/endpoint.cpp | 15 +-- llarp/service/endpoint.hpp | 4 +- llarp/service/identity.cpp | 2 +- llarp/service/outbound_context.cpp | 2 +- llarp/service/outbound_context.hpp | 2 +- llarp/service/router_lookup_job.cpp | 13 +-- llarp/service/router_lookup_job.hpp | 49 ++++---- llarp/util/bencode.hpp | 2 +- llarp/util/file.cpp | 2 +- llarp/util/file.hpp | 6 +- 53 files changed, 532 insertions(+), 588 deletions(-) diff --git a/llarp/bootstrap-fallbacks.cpp.in b/llarp/bootstrap-fallbacks.cpp.in index baeb4be3a6..9cc96008fd 100644 --- a/llarp/bootstrap-fallbacks.cpp.in +++ b/llarp/bootstrap-fallbacks.cpp.in @@ -9,17 +9,18 @@ namespace llarp load_bootstrap_fallbacks() { std::unordered_map fallbacks; - using init_list = std::initializer_list>; - // clang-format off - for (const auto& [network, bootstrap] : init_list{ + + for (const auto& [network, bootstrap] : std::initializer_list>{ @BOOTSTRAP_FALLBACKS@ }) - // clang-format on { - llarp_buffer_t buf{bootstrap.data(), bootstrap.size()}; + if (network != RouterContact::ACTIVE_NETID) + continue; + auto& bsl = fallbacks[network]; - bsl.BDecode(&buf); + bsl.bt_decode(bootstrap); } + return fallbacks; } } // namespace llarp diff --git a/llarp/bootstrap.cpp b/llarp/bootstrap.cpp index f5a795ea0e..c51da6deea 100644 --- a/llarp/bootstrap.cpp +++ b/llarp/bootstrap.cpp @@ -6,66 +6,65 @@ namespace llarp { - void - BootstrapList::Clear() - { - clear(); - } - bool - BootstrapList::BDecode(llarp_buffer_t* buf) + BootstrapList::bt_decode(std::string_view buf) { - return bencode_read_list( - [&](llarp_buffer_t* b, bool more) -> bool { - if (more) - { - RouterContact rc{}; - if (not rc.BDecode(b)) - { - LogError("invalid rc in bootstrap list: ", llarp::buffer_printer{*b}); - return false; - } - emplace(std::move(rc)); - } - return true; - }, - buf); + try + { + oxenc::bt_list_consumer btlc{buf}; + + while (not btlc.is_finished()) + emplace(btlc.consume_dict_consumer()); + } + catch (...) + { + log::warning(logcat, "Unable to decode bootstrap RemoteRC"); + return false; + } + + return true; } - bool - BootstrapList::BEncode(llarp_buffer_t* buf) const + std::string_view + BootstrapList::bt_encode() const { - return BEncodeWriteList(begin(), end(), buf); + oxenc::bt_list_producer btlp{}; + + for (const auto& it : *this) + btlp.append(it.bt_encode()); + + return btlp.view(); } void - BootstrapList::AddFromFile(fs::path fpath) + BootstrapList::read_from_file(const fs::path& fpath) { bool isListFile = false; + + if (std::ifstream inf(fpath.c_str(), std::ios::binary); inf.is_open()) { - std::ifstream inf(fpath.c_str(), std::ios::binary); - if (inf.is_open()) - { - const char ch = inf.get(); - isListFile = ch == 'l'; - } + const char ch = inf.get(); + isListFile = ch == 'l'; } + if (isListFile) { - if (not BDecodeReadFile(fpath, *this)) + auto content = util::file_to_string(fpath); + + if (not bt_decode(content)) { throw std::runtime_error{fmt::format("failed to read bootstrap list file '{}'", fpath)}; } } else { - RouterContact rc; + RemoteRC rc; if (not rc.read(fpath)) { throw std::runtime_error{ - fmt::format("failed to decode bootstrap RC, file='{}', rc={}", fpath, rc)}; + fmt::format("failed to decode bootstrap RC, file='{}', rc={}", fpath, rc.to_string())}; } - this->insert(rc); + insert(rc); } } } // namespace llarp diff --git a/llarp/bootstrap.hpp b/llarp/bootstrap.hpp index e72e12fccf..11e8286d3a 100644 --- a/llarp/bootstrap.hpp +++ b/llarp/bootstrap.hpp @@ -9,19 +9,22 @@ namespace llarp { - struct BootstrapList final : public std::set + struct BootstrapList final : public std::set { bool - BDecode(llarp_buffer_t* buf); + bt_decode(std::string_view buf); - bool - BEncode(llarp_buffer_t* buf) const; + std::string_view + bt_encode() const; void - AddFromFile(fs::path fpath); + read_from_file(const fs::path& fpath); void - Clear(); + clear_list() + { + clear(); + } }; std::unordered_map diff --git a/llarp/bootstrap_fallbacks.cpp b/llarp/bootstrap_fallbacks.cpp index 458444f639..79f6f646f4 100644 --- a/llarp/bootstrap_fallbacks.cpp +++ b/llarp/bootstrap_fallbacks.cpp @@ -10,17 +10,19 @@ namespace llarp load_bootstrap_fallbacks() { std::unordered_map fallbacks; - using init_list = std::initializer_list>; - // clang-format off - for (const auto& [network, bootstrap] : init_list{ - // - }) - // clang-format on + + for (const auto& [network, bootstrap] : + std::initializer_list>{ + // + }) { - llarp_buffer_t buf{bootstrap.data(), bootstrap.size()}; + if (network != RouterContact::ACTIVE_NETID) + continue; + auto& bsl = fallbacks[network]; - bsl.BDecode(&buf); + bsl.bt_decode(bootstrap); } + return fallbacks; } } // namespace llarp diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index 64d473564e..c4d3035da5 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -64,9 +64,9 @@ namespace llarp + "' for mainnet, 'gamma' for testnet.", }, [this](std::string arg) { - if (arg.size() > NetID::size()) + if (arg.size() > NETID_SIZE) throw std::invalid_argument{ - fmt::format("netid is too long, max length is {}", NetID::size())}; + fmt::format("netid is too long, max length is {}", NETID_SIZE)}; m_netId = std::move(arg); }); @@ -1322,7 +1322,7 @@ namespace llarp } bool - PeerSelectionConfig::Acceptable(const std::set& rcs) const + PeerSelectionConfig::Acceptable(const std::set& rcs) const { if (m_UniqueHopsNetmaskSize == 0) return true; @@ -1530,7 +1530,7 @@ namespace llarp // open a filestream try { - util::dump_file(confFile, confStr); + util::buffer_to_file(confFile, confStr); } catch (const std::exception& e) { diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index f91c131c2e..9ee7f2e6bc 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -100,7 +100,7 @@ namespace llarp /// return true if this set of router contacts is acceptable against this config bool - Acceptable(const std::set& hops) const; + Acceptable(const std::set& hops) const; }; struct NetworkConfig diff --git a/llarp/config/key_manager.cpp b/llarp/config/key_manager.cpp index 3df244dea2..f5b05c0f8b 100644 --- a/llarp/config/key_manager.cpp +++ b/llarp/config/key_manager.cpp @@ -51,7 +51,7 @@ namespace llarp m_encKeyPath = deriveFile(our_enc_key_filename, config.router.m_encryptionKeyFile); m_transportKeyPath = deriveFile(our_transport_key_filename, config.router.m_transportKeyFile); - RouterContact rc; + RemoteRC rc; bool exists = rc.read(m_rcPath); if (not exists and not genIfAbsent) { @@ -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.verify_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 diff --git a/llarp/context.cpp b/llarp/context.cpp index ab8ae70f98..cffea417fd 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -19,8 +19,6 @@ namespace llarp { - static auto logcat = llarp::log::Cat("llarp-context"); - bool Context::CallSafe(std::function f) { @@ -163,7 +161,7 @@ namespace llarp #ifndef _WIN32 if (sig == SIGUSR1) { - if (router and not router->IsServiceNode()) + if (router and not router->is_service_node()) { LogInfo("SIGUSR1: resetting network state"); router->Thaw(); diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index 1b5c9a2390..dba97aeedf 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -67,8 +67,7 @@ namespace llarp 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*); diff --git a/llarp/crypto/types.cpp b/llarp/crypto/types.cpp index c7a141bbd3..092698e818 100644 --- a/llarp/crypto/types.cpp +++ b/llarp/crypto/types.cpp @@ -57,12 +57,6 @@ namespace llarp 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) { @@ -124,17 +118,13 @@ namespace llarp bool SecretKey::SaveToFile(const fs::path& fname) const { - std::string tmp(128, 0); - llarp_buffer_t buf(tmp); - if (!bt_encode(&buf)) - return false; + auto bte = bt_encode(); - tmp.resize(buf.cur - buf.base); try { - util::dump_file(fname, tmp); + util::buffer_to_file(fname, bte); } - catch (const std::exception&) + catch (const std::exception& e) { return false; } diff --git a/llarp/crypto/types.hpp b/llarp/crypto/types.hpp index a91192770f..6e723fae5c 100644 --- a/llarp/crypto/types.hpp +++ b/llarp/crypto/types.hpp @@ -50,9 +50,6 @@ namespace llarp bool operator==(const PubKey& lhs, const RouterID& rhs); - bool - operator==(const RouterID& lhs, const PubKey& rhs); - struct PrivateKey; /// Stores a sodium "secret key" value, which is actually the seed diff --git a/llarp/exit/session.cpp b/llarp/exit/session.cpp index c6bdc009ba..ecdafff65e 100644 --- a/llarp/exit/session.cpp +++ b/llarp/exit/session.cpp @@ -69,13 +69,13 @@ namespace llarp::exit snode_blacklist.insert(std::move(snode)); } - std::optional> + std::optional> BaseSession::GetHopsForBuild() { if (numHops == 1) { if (auto maybe = router->node_db()->get_rc(exit_router)) - return std::vector{*maybe}; + return std::vector{*maybe}; return std::nullopt; } @@ -292,7 +292,7 @@ namespace llarp::exit throw; } - RouterContact result{std::move(payload)}; + RemoteRC result{std::move(payload)}; r->node_db()->put_rc_if_newer(result); r->connect_to(result); } diff --git a/llarp/exit/session.hpp b/llarp/exit/session.hpp index ac5da8f84a..6410bc2be9 100644 --- a/llarp/exit/session.hpp +++ b/llarp/exit/session.hpp @@ -72,7 +72,7 @@ namespace llarp bool CheckPathDead(path::Path_ptr p, llarp_time_t dlt); - std::optional> + std::optional> GetHopsForBuild() override; bool diff --git a/llarp/handlers/exit.cpp b/llarp/handlers/exit.cpp index 008e12b26d..b9a46b1a80 100644 --- a/llarp/handlers/exit.cpp +++ b/llarp/handlers/exit.cpp @@ -578,33 +578,7 @@ namespace llarp::handlers void ExitEndpoint::SRVRecordsChanged() { - 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; - - // 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(); - - // for (auto& record : srvRecords) - // rc.srvRecords.emplace_back(record); - - // // set the verssion to 1 because we have srv records - // rc.version = 1; - return rc; - }); + // TODO: Investigate the usage or the term exit RE: service nodes acting as exits } std::optional diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 468e138a74..e530da4e0b 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -623,7 +623,7 @@ namespace llarp::handlers throw; } - r->node_db()->put_rc_if_newer(RouterContact{payload}); + r->node_db()->put_rc_if_newer(RemoteRC{payload}); msg.AddTXTReply(payload); } else @@ -658,7 +658,7 @@ namespace llarp::handlers } else if (subdomain == "netid") { - msg.AddTXTReply(fmt::format("netid={};", router()->rc().netID)); + msg.AddTXTReply(fmt::format("netid={};", RouterContact::ACTIVE_NETID)); } else { diff --git a/llarp/link/connection.cpp b/llarp/link/connection.cpp index 01aaa4fc89..dace3d2991 100644 --- a/llarp/link/connection.cpp +++ b/llarp/link/connection.cpp @@ -5,7 +5,7 @@ namespace llarp::link Connection::Connection( std::shared_ptr& c, std::shared_ptr& s, - const RouterContact& rc) + const RemoteRC& rc) : conn{c}, control_stream{s}, remote_rc{std::move(rc)} {} diff --git a/llarp/link/connection.hpp b/llarp/link/connection.hpp index fe8b0961a3..46aef93288 100644 --- a/llarp/link/connection.hpp +++ b/llarp/link/connection.hpp @@ -11,7 +11,7 @@ namespace llarp::link { std::shared_ptr conn; std::shared_ptr control_stream; - RouterContact remote_rc; + RemoteRC remote_rc; // one side of a connection will be responsible for some things, e.g. heartbeat bool inbound{false}; @@ -20,7 +20,7 @@ namespace llarp::link Connection( std::shared_ptr& c, std::shared_ptr& s, - const RouterContact& rc); + const RemoteRC& rc); }; } // namespace llarp::link diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index e6515b7f42..2e80cb603a 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -18,7 +18,7 @@ namespace llarp namespace link { std::shared_ptr - Endpoint::get_conn(const RouterContact& rc) const + Endpoint::get_conn(const RemoteRC& rc) const { if (auto itr = conns.find(rc.router_id()); itr != conns.end()) return itr->second; @@ -83,7 +83,7 @@ namespace llarp } bool - Endpoint::get_random_connection(RouterContact& router) const + Endpoint::get_random_connection(RemoteRC& router) const { if (const auto size = conns.size(); size) { @@ -301,7 +301,7 @@ namespace llarp // This function assumes the RC has already had its signature verified and connection is allowed. void - LinkManager::connect_to(const RouterContact& rc) + LinkManager::connect_to(const RemoteRC& rc) { if (auto conn = ep.get_conn(rc.router_id()); conn) { @@ -451,7 +451,7 @@ namespace llarp } bool - LinkManager::get_random_connected(RouterContact& router) const + LinkManager::get_random_connected(RemoteRC& router) const { return ep.get_random_connection(router); } @@ -487,7 +487,9 @@ namespace llarp do { - auto filter = [exclude](const auto& rc) -> bool { return exclude.count(rc.pubkey) == 0; }; + auto filter = [exclude](const auto& rc) -> bool { + return exclude.count(rc.router_id()) == 0; + }; if (auto maybe_other = node_db->GetRandom(filter)) { @@ -654,7 +656,7 @@ namespace llarp } else { - m.respond(serialize_response({{"RC", closest_rc.bt_encode()}})); + m.respond(serialize_response({{"RC", closest_rc.view()}})); } } else if (not is_iterative) @@ -720,7 +722,7 @@ namespace llarp if (m) { - _router.node_db()->put_rc_if_newer(RouterContact{payload}); + _router.node_db()->put_rc_if_newer(RemoteRC{payload}); } else { diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 66cde4bb71..d99e2facee 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -52,7 +52,8 @@ namespace llarp // TODO: see which of these is actually useful and delete the other std::shared_ptr - get_conn(const RouterContact&) const; + get_conn(const RemoteRC&) const; + std::shared_ptr get_conn(const RouterID&) const; @@ -66,12 +67,11 @@ namespace llarp num_connected(bool clients_only) const; bool - get_random_connection(RouterContact& router) const; + get_random_connection(RemoteRC& router) const; template bool - establish_connection( - const oxen::quic::Address& remote, const RouterContact& rc, Opt&&... opts); + establish_connection(const oxen::quic::Address& remote, const RemoteRC& rc, Opt&&... opts); void for_each_connection(std::function func); @@ -239,7 +239,7 @@ namespace llarp connect_to(const RouterID& router); void - connect_to(const RouterContact& rc); + connect_to(const RemoteRC& rc); void close_connection(RouterID rid); @@ -257,7 +257,7 @@ namespace llarp get_num_connected_clients() const; bool - get_random_connected(RouterContact& router) const; + get_random_connected(RemoteRC& router) const; void check_persisting_conns(llarp_time_t now); @@ -364,7 +364,7 @@ namespace llarp template bool Endpoint::establish_connection( - const oxen::quic::Address& remote, const RouterContact& rc, Opt&&... opts) + const oxen::quic::Address& remote, const RemoteRC& rc, Opt&&... opts) { try { diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index 17bd63ba32..ca10a0f84b 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.router_id(), 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.router_id(), 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 7f816d61b8..8bfab3a0b4 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.router_id(), 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.router_id(), pathid); if (path) { return path->HandleDownstream(llarp_buffer_t(enc), nonce, r); diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index d3b7ee02ce..a5955003d6 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -14,7 +14,7 @@ static const std::string RC_FILE_EXT = ".signed"; namespace llarp { - NodeDB::Entry::Entry(RouterContact value) : rc(std::move(value)), insertedAt(llarp::time_now_ms()) + NodeDB::Entry::Entry(RemoteRC value) : rc(std::move(value)), insertedAt(llarp::time_now_ms()) {} static void @@ -70,9 +70,11 @@ namespace llarp router.loop()->call([this]() { m_NextFlushAt += FlushInterval; // make copy of all rcs - std::vector copy; + std::vector copy; + for (const auto& item : entries) copy.push_back(item.second.rc); + // flush them to disk in one big job // TODO: split this up? idk maybe some day... disk([this, data = std::move(copy)]() { @@ -119,7 +121,7 @@ namespace llarp if (not(fs::is_regular_file(f) and f.extension() == RC_FILE_EXT)) return true; - RouterContact rc{}; + RemoteRC rc{}; if (not rc.read(f)) { @@ -137,7 +139,7 @@ namespace llarp // validate signature and purge entries with invalid signatures // load ones with valid signatures - if (rc.verify_signature()) // TODO: fix this after RouterContact -> RemoteRC + if (rc.verify()) entries.emplace(rc.router_id(), rc); else purge.emplace(f); @@ -175,10 +177,10 @@ namespace llarp [this, pk]() -> bool { return entries.find(pk) != entries.end(); }); } - std::optional + std::optional NodeDB::get_rc(RouterID pk) const { - return router.loop()->call_get([this, pk]() -> std::optional { + return router.loop()->call_get([this, pk]() -> std::optional { const auto itr = entries.find(pk); if (itr == entries.end()) @@ -219,11 +221,12 @@ namespace llarp } void - NodeDB::put_rc(RouterContact rc) + NodeDB::put_rc(RemoteRC rc) { router.loop()->call([this, rc]() { - entries.erase(rc.router_id()); - entries.emplace(rc.router_id(), rc); + const auto& rid = rc.router_id(); + entries.erase(rid); + entries.emplace(rid, rc); }); } @@ -234,7 +237,7 @@ namespace llarp } void - NodeDB::put_rc_if_newer(RouterContact rc) + NodeDB::put_rc_if_newer(RemoteRC rc) { router.loop()->call([this, rc]() { auto itr = entries.find(rc.router_id()); @@ -267,32 +270,31 @@ namespace llarp }); } - llarp::RouterContact + RemoteRC NodeDB::find_closest_to(llarp::dht::Key_t location) const { - return router.loop()->call_get([this, location]() { - llarp::RouterContact rc; + return router.loop()->call_get([this, location]() -> RemoteRC { + RemoteRC rc; const llarp::dht::XorMetric compare(location); + VisitAll([&rc, compare](const auto& otherRC) { - if (rc.router_id().IsZero()) + const auto& rid = rc.router_id(); + + if (rid.IsZero() || compare(dht::Key_t{otherRC.router_id()}, dht::Key_t{rid})) { rc = otherRC; return; } - if (compare( - llarp::dht::Key_t{otherRC.pubkey.as_array()}, - llarp::dht::Key_t{rc.router_id().as_array()})) - rc = otherRC; }); return rc; }); } - std::vector + std::vector NodeDB::find_many_closest_to(llarp::dht::Key_t location, uint32_t numRouters) const { - return router.loop()->call_get([this, location, numRouters]() { - std::vector all; + return router.loop()->call_get([this, location, numRouters]() -> std::vector { + std::vector all; all.reserve(entries.size()); for (auto& entry : entries) @@ -306,7 +308,7 @@ namespace llarp return compare(*a, *b); }); - std::vector closest; + std::vector closest; closest.reserve(numRouters); for (auto it = all.begin(); it != it_mid; ++it) closest.push_back(**it); diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index 17fe4ffbd6..7552fc6fd4 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -26,9 +26,9 @@ namespace llarp { struct Entry { - const RouterContact rc; + const RemoteRC rc; llarp_time_t insertedAt; - explicit Entry(RouterContact rc); + explicit Entry(RemoteRC rc); }; using NodeMap = std::unordered_map; @@ -73,11 +73,11 @@ namespace llarp Tick(llarp_time_t now); /// find the absolute closets router to a dht location - RouterContact + RemoteRC find_closest_to(dht::Key_t location) const; /// find many routers closest to dht key - std::vector + std::vector find_many_closest_to(dht::Key_t location, uint32_t numRouters) const; /// return true if we have an rc by its ident pubkey @@ -85,14 +85,14 @@ namespace llarp has_router(RouterID pk) const; /// maybe get an rc by its ident pubkey - std::optional + std::optional get_rc(RouterID pk) const; template - std::optional + std::optional GetRandom(Filter visit) const { - return router.loop()->call_get([visit]() -> std::optional { + return router.loop()->call_get([visit]() -> std::optional { std::vector entries; for (const auto& entry : entries) entries.push_back(entry); @@ -167,10 +167,10 @@ namespace llarp /// put this rc into the cache if it is not there or newer than the one there already void - put_rc_if_newer(RouterContact rc); + put_rc_if_newer(RemoteRC rc); /// unconditional put of rc into cache void - put_rc(RouterContact rc); + put_rc(RemoteRC rc); }; } // namespace llarp diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index e5760c1a21..3fb7ad8fac 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -10,7 +10,7 @@ namespace llarp::path { Path::Path( Router* rtr, - const std::vector& h, + const std::vector& h, std::weak_ptr pathset, PathRole startingRoles, std::string shortName) @@ -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._router_id; + 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._router_id; + return hops[hops.size() - 1].rc.router_id(); } PubKey Path::EndpointPubKey() const { - return hops[hops.size() - 1].rc._router_id; + 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._router_id == 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._router_id; + 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._router_id).ToString(); + hops_str += hop.rc.router_id().ToView(); } 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._router_id.ToHex()}, + {"router", rc.router_id().ToHex()}, {"txid", txID.ToHex()}, {"rxid", rxID.ToHex()}}; return obj; @@ -330,11 +330,13 @@ namespace llarp::path { if (auto parent = m_PathSet.lock()) { - std::vector newHops; + std::vector new_hops; + for (const auto& hop : hops) - newHops.emplace_back(hop.rc); + new_hops.emplace_back(hop.rc); + LogInfo(name(), " rebuilding on ", ShortName()); - parent->Build(newHops); + parent->Build(new_hops); } } diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 4af30f54fe..e427997eff 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -69,7 +69,7 @@ namespace llarp Path( Router* rtr, - const std::vector& routers, + const std::vector& routers, std::weak_ptr parent, PathRole startingRoles, std::string shortName); diff --git a/llarp/path/path_types.hpp b/llarp/path/path_types.hpp index 374660e556..47401033e6 100644 --- a/llarp/path/path_types.hpp +++ b/llarp/path/path_types.hpp @@ -26,7 +26,7 @@ namespace llarp /// path id PathID_t txID, rxID; // router contact of router - RouterContact rc; + RemoteRC rc; // temp public encryption key SecretKey commkey; /// shared secret at this hop diff --git a/llarp/path/pathbuilder.cpp b/llarp/path/pathbuilder.cpp index ec4d3fa3d5..2f831bf068 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.router_id(), 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.router_id(), framekey, outer_nonce)) { log::error(path_cat, "DH client failed during hop info encryption!"); throw std::runtime_error{"DH failed during hop info encryption"}; @@ -211,23 +211,25 @@ namespace llarp return obj; } - std::optional + std::optional Builder::SelectFirstHop(const std::set& exclude) const { - std::optional found = std::nullopt; + std::optional found = std::nullopt; router->for_each_connection([&](link::Connection& conn) { const auto& rc = conn.remote_rc; + const auto& rid = rc.router_id(); + #ifndef TESTNET - if (router->IsBootstrapNode(rc._pubkey)) + if (router->IsBootstrapNode(rid)) return; #endif - if (exclude.count(rc._pubkey)) + if (exclude.count(rid)) return; - if (BuildCooldownHit(rc._pubkey)) + if (BuildCooldownHit(rid)) return; - if (router->router_profiling().IsBadForPath(rc._pubkey)) + if (router->router_profiling().IsBadForPath(rid)) return; found = rc; @@ -235,15 +237,15 @@ namespace llarp return found; } - std::optional> + std::optional> Builder::GetHopsForBuild() { auto filter = [r = router](const auto& rc) -> bool { - return not r->router_profiling().IsBadForPath(rc.pubkey, 1); + return not r->router_profiling().IsBadForPath(rc.router_id(), 1); }; if (const auto maybe = router->node_db()->GetRandom(filter)) { - return GetHopsAlignedToForBuild(maybe->_pubkey); + return GetHopsAlignedToForBuild(maybe->router_id()); } return std::nullopt; } @@ -308,12 +310,12 @@ namespace llarp return buildIntervalLimit > MIN_PATH_BUILD_INTERVAL * 4; } - std::optional> + std::optional> Builder::GetHopsAlignedToForBuild(RouterID endpoint, const std::set& exclude) { const auto pathConfig = router->config()->paths; - std::vector hops; + std::vector hops; { const auto maybe = SelectFirstHop(exclude); if (not maybe.has_value()) @@ -324,7 +326,7 @@ namespace llarp hops.emplace_back(*maybe); }; - RouterContact endpointRC; + RemoteRC endpointRC; if (const auto maybe = router->node_db()->get_rc(endpoint)) { endpointRC = *maybe; @@ -341,19 +343,21 @@ namespace llarp else { auto filter = - [&hops, r = router, endpointRC, pathConfig, exclude](const auto& rc) -> bool { - if (exclude.count(rc.pubkey)) + [&hops, r = router, endpointRC, pathConfig, exclude](const RemoteRC& rc) -> bool { + const auto& rid = rc.router_id(); + + if (exclude.count(rid)) return false; - std::set hopsSet; + std::set hopsSet; hopsSet.insert(endpointRC); hopsSet.insert(hops.begin(), hops.end()); - if (r->router_profiling().IsBadForPath(rc.pubkey, 1)) + if (r->router_profiling().IsBadForPath(rid, 1)) return false; for (const auto& hop : hopsSet) { - if (hop._pubkey == rc.pubkey) + if (hop.router_id() == rid) return false; } @@ -362,7 +366,7 @@ namespace llarp if (not pathConfig.Acceptable(hopsSet)) return false; #endif - return rc.pubkey != endpointRC._pubkey; + return rc.router_id() != endpointRC.router_id(); }; if (const auto maybe = router->node_db()->GetRandom(filter)) @@ -393,7 +397,7 @@ namespace llarp } void - Builder::Build(std::vector hops, PathRole roles) + Builder::Build(std::vector hops, PathRole roles) { if (IsStopped()) { @@ -402,7 +406,7 @@ namespace llarp } lastBuild = llarp::time_now_ms(); - const RouterID edge{hops[0]._pubkey}; + const auto& edge = hops[0].router_id(); if (not router->pathbuild_limiter().Attempt(edge)) { @@ -429,7 +433,8 @@ 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.router_id() : path_hops[i + 1].rc.router_id(); PathBuildMessage::setup_hop_keys(path_hops[i], nextHop); auto frame_str = PathBuildMessage::serialize(path_hops[i]); @@ -533,7 +538,7 @@ namespace llarp DoPathBuildBackoff(); for (const auto& hop : p->hops) { - const RouterID target{hop.rc._pubkey}; + const auto& target = hop.rc.router_id(); // 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/path/pathbuilder.hpp b/llarp/path/pathbuilder.hpp index 480f7df6d9..35fbdb1dcf 100644 --- a/llarp/path/pathbuilder.hpp +++ b/llarp/path/pathbuilder.hpp @@ -115,17 +115,17 @@ namespace llarp::path bool BuildOneAlignedTo(const RouterID endpoint) override; - std::optional> + std::optional> GetHopsAlignedToForBuild(RouterID endpoint, const std::set& exclude = {}); void - Build(std::vector hops, PathRole roles = ePathRoleAny) override; + Build(std::vector hops, PathRole roles = ePathRoleAny) override; /// pick a first hop - std::optional + std::optional SelectFirstHop(const std::set& exclude = {}) const; - std::optional> + std::optional> GetHopsForBuild() override; void diff --git a/llarp/path/pathset.hpp b/llarp/path/pathset.hpp index 914c97da11..c228823acb 100644 --- a/llarp/path/pathset.hpp +++ b/llarp/path/pathset.hpp @@ -122,7 +122,7 @@ namespace llarp /// manual build on these hops virtual void - Build(std::vector hops, PathRole roles = ePathRoleAny) = 0; + Build(std::vector hops, PathRole roles = ePathRoleAny) = 0; /// tick owned paths virtual void @@ -252,7 +252,7 @@ namespace llarp virtual void send_packet_to_remote(std::string buf) = 0; - virtual std::optional> + virtual std::optional> GetHopsForBuild() = 0; void diff --git a/llarp/profiling.cpp b/llarp/profiling.cpp index a8da6cec11..ee0428c1e5 100644 --- a/llarp/profiling.cpp +++ b/llarp/profiling.cpp @@ -260,7 +260,7 @@ namespace llarp try { - util::dump_file(fpath, buf); + util::buffer_to_file(fpath, buf); } catch (const std::exception& e) { diff --git a/llarp/router/rc_gossiper.cpp b/llarp/router/rc_gossiper.cpp index a380a54b14..a5da35bd38 100644 --- a/llarp/router/rc_gossiper.cpp +++ b/llarp/router/rc_gossiper.cpp @@ -28,7 +28,7 @@ namespace llarp } bool - RCGossiper::IsOurRC(const RouterContact& rc) const + RCGossiper::IsOurRC(const LocalRC& rc) const { return rc.router_id() == rid; } @@ -64,7 +64,7 @@ namespace llarp } bool - RCGossiper::GossipRC(const RouterContact& rc) + RCGossiper::GossipRC(const LocalRC& rc) { // only distribute public routers if (not rc.is_public_router()) diff --git a/llarp/router/rc_gossiper.hpp b/llarp/router/rc_gossiper.hpp index 3678f06326..a0c72fc80b 100644 --- a/llarp/router/rc_gossiper.hpp +++ b/llarp/router/rc_gossiper.hpp @@ -12,7 +12,7 @@ namespace llarp /// The maximum number of peers we will flood a gossiped RC to when propagating an RC constexpr size_t MaxGossipPeers = 20; struct LinkManager; - struct RouterContact; + struct LocalRC; struct RCGossiper { @@ -23,7 +23,7 @@ namespace llarp ~RCGossiper() = default; bool - GossipRC(const RouterContact& rc); + GossipRC(const LocalRC& rc); void Decay(Time_t now); @@ -32,7 +32,7 @@ namespace llarp ShouldGossipOurRC(Time_t now) const; bool - IsOurRC(const RouterContact& rc) const; + IsOurRC(const LocalRC& rc) const; void Init(LinkManager*, const RouterID&, Router*); diff --git a/llarp/router/rc_lookup_handler.cpp b/llarp/router/rc_lookup_handler.cpp index 4c26d748b1..8723f1bbe6 100644 --- a/llarp/router/rc_lookup_handler.cpp +++ b/llarp/router/rc_lookup_handler.cpp @@ -66,7 +66,7 @@ namespace llarp void RCLookupHandler::get_rc(const RouterID& rid, RCRequestCallback callback, bool forceLookup) { - RouterContact remoteRC; + RemoteRC remoteRC; if (not forceLookup) { @@ -101,8 +101,7 @@ namespace llarp throw; } - // TODO: replace this with construction of RemoteRC - RouterContact result{std::move(payload)}; + RemoteRC result{std::move(payload)}; if (callback) callback(result.router_id(), result, true); @@ -203,7 +202,7 @@ namespace llarp } bool - RCLookupHandler::check_rc(const RouterContact& rc) const + RCLookupHandler::check_rc(const RemoteRC& rc) const { if (not is_session_allowed(rc.router_id())) { @@ -211,16 +210,16 @@ namespace llarp return false; } - if (not rc.verify(llarp::time_now_ms())) // TODO: fix this call after RouterContact -> RemoteRC + if (not rc.verify()) { - LogWarn("RC for ", RouterID(rc.router_id()), " is invalid"); + log::info(link_cat, "Invalid RC (rid: {})", rc.router_id()); return false; } // update nodedb if required if (rc.is_public_router()) { - LogDebug("Adding or updating RC for ", RouterID(rc.router_id()), " to nodedb and dht."); + log::info(link_cat, "Adding or updating RC (rid: {}) to nodeDB and DHT", rc.router_id()); node_db->put_rc_if_newer(rc); contacts->put_rc_node_async(rc); } @@ -249,29 +248,6 @@ namespace llarp }); } - bool - RCLookupHandler::check_renegotiate_valid(RouterContact newrc, RouterContact oldrc) - { - // mismatch of identity ? - if (newrc.router_id() != oldrc.router_id()) - return false; - - 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.router_id()})) - { - contacts->rc_nodes()->PutNode(newrc); - } - - // TODO: check for other places that need updating the RC - return true; - } - void RCLookupHandler::periodic_update(llarp_time_t now) { @@ -337,7 +313,7 @@ namespace llarp return; } // service nodes gossip, not explore - if (contacts->router()->IsServiceNode()) + if (contacts->router()->is_service_node()) return; // explore via every connected peer @@ -368,7 +344,7 @@ namespace llarp LinkManager* linkManager, service::Context* hiddenServiceContext, const std::unordered_set& strictConnectPubkeys, - const std::set& bootstrapRCList, + const std::set& bootstrapRCList, bool isServiceNode_arg) { contacts = c; diff --git a/llarp/router/rc_lookup_handler.hpp b/llarp/router/rc_lookup_handler.hpp index 7802a25972..f7b3f01f49 100644 --- a/llarp/router/rc_lookup_handler.hpp +++ b/llarp/router/rc_lookup_handler.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -24,7 +25,6 @@ namespace llarp struct Contacts; struct LinkManager; - struct RouterContact; enum class RCRequestResult { @@ -35,7 +35,7 @@ namespace llarp }; using RCRequestCallback = - std::function, bool success)>; + std::function, bool success)>; struct RCLookupHandler { @@ -80,14 +80,11 @@ namespace llarp is_registered(const RouterID& remote) const; bool - check_rc(const RouterContact& rc) const; + check_rc(const RemoteRC& rc) const; bool get_random_whitelist_router(RouterID& router) const; - bool - check_renegotiate_valid(RouterContact newrc, RouterContact oldrc); - void periodic_update(llarp_time_t now); @@ -106,7 +103,7 @@ namespace llarp LinkManager* linkManager, service::Context* hiddenServiceContext, const std::unordered_set& strictConnectPubkeys, - const std::set& bootstrapRCList, + const std::set& bootstrapRCList, bool isServiceNode_arg); std::unordered_set @@ -128,7 +125,7 @@ namespace llarp /// service nodes) std::unordered_set strict_connect_pubkeys; - std::set bootstrap_rc_list; + std::set bootstrap_rc_list; std::unordered_set boostrap_rid_list; // Now that all calls are made through the event loop, any access to these diff --git a/llarp/router/route_poker.cpp b/llarp/router/route_poker.cpp index b64ff9e9e7..782fd7d187 100644 --- a/llarp/router/route_poker.cpp +++ b/llarp/router/route_poker.cpp @@ -117,7 +117,7 @@ namespace llarp bool RoutePoker::is_enabled() const { - if (router.IsServiceNode()) + if (router.is_service_node()) return false; if (const auto& conf = router.config()) return conf->network.m_EnableRoutePoker; diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 885e3fcf56..1b88b6f435 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -199,7 +199,7 @@ namespace llarp void Router::Freeze() { - if (IsServiceNode()) + if (is_service_node()) return; for_each_connection( @@ -209,7 +209,7 @@ namespace llarp void Router::Thaw() { - if (IsServiceNode()) + if (is_service_node()) return; std::unordered_set peer_pubkeys; @@ -231,10 +231,10 @@ namespace llarp } void - Router::GossipRCIfNeeded(const RouterContact rc) + Router::GossipRCIfNeeded(const LocalRC rc) { /// if we are not a service node forget about gossip - if (not IsServiceNode()) + if (not is_service_node()) return; /// wait for random uptime if (std::chrono::milliseconds{Uptime()} < _randomStartDelay) @@ -245,7 +245,7 @@ namespace llarp bool Router::GetRandomGoodRouter(RouterID& router) { - if (IsServiceNode()) + if (is_service_node()) { return _rc_lookup_handler.get_random_whitelist_router(router); } @@ -271,7 +271,7 @@ namespace llarp } void - Router::connect_to(const RouterContact& rc) + Router::connect_to(const RemoteRC& rc) { _link_manager.connect_to(rc); } @@ -314,7 +314,7 @@ namespace llarp { _encryption = _key_manager->encryptionKey; - if (IsServiceNode()) + if (is_service_node()) { #if defined(ANDROID) || defined(IOS) LogError("running a service node on mobile device is not possible."); @@ -396,9 +396,9 @@ namespace llarp log::debug(logcat, "Configuring router"); - is_service_node = conf.router.m_isRelay; + _is_service_node = conf.router.m_isRelay; - if (is_service_node) + if (_is_service_node) { rpc_addr = oxenmq::address(conf.lokid.lokidRPCAddr); _rpc_client = std::make_shared(_lmq, weak_from_this()); @@ -417,9 +417,9 @@ namespace llarp _node_db = std::move(nodedb); log::debug( - logcat, is_service_node ? "Running as a relay (service node)" : "Running as a client"); + logcat, _is_service_node ? "Running as a relay (service node)" : "Running as a client"); - if (is_service_node) + if (_is_service_node) { _rpc_client->ConnectAsync(rpc_addr); } @@ -438,34 +438,10 @@ namespace llarp return true; } - /// called in disk worker thread - void - Router::HandleSaveRC() const - { - std::string fname = our_rc_file.string(); - router_contact.write(fname.c_str()); - } - bool - Router::SaveRC() + Router::is_service_node() const { - LogDebug("verify RC signature"); - if (!router_contact.verify(now())) // TODO: RouterContact -> RemoteRC - { - Dump(rc()); - LogError("RC is invalid, not saving"); - return false; - } - if (is_service_node) - _node_db->put_rc(router_contact); - queue_disk_io([&]() { HandleSaveRC(); }); - return true; - } - - bool - Router::IsServiceNode() const - { - return is_service_node; + return _is_service_node; } bool @@ -507,7 +483,7 @@ namespace llarp bool Router::have_snode_whitelist() const { - return IsServiceNode() and _rc_lookup_handler.has_received_whitelist(); + return is_service_node() and _rc_lookup_handler.has_received_whitelist(); } bool @@ -566,13 +542,13 @@ namespace llarp bool Router::update_rc() { - SecretKey nextOnionKey; - RouterContact nextRC = router_contact; - if (!nextRC.sign(identity())) // TODO: RouterContact -> LocalRC - return false; - router_contact = std::move(nextRC); - if (IsServiceNode()) - return SaveRC(); + router_contact.resign(); + if (is_service_node()) + { + _node_db->put_rc(router_contact.view()); + queue_disk_io([&]() { router_contact.write(our_rc_file); }); + } + return true; } @@ -626,12 +602,13 @@ namespace llarp auto& networkConfig = conf.network; - /// build a set of strictConnectPubkeys ( + /// build a set of strictConnectPubkeys std::unordered_set strictConnectPubkeys; + if (not networkConfig.m_strictConnect.empty()) { const auto& val = networkConfig.m_strictConnect; - if (IsServiceNode()) + if (is_service_node()) throw std::runtime_error("cannot use strict-connect option as service node"); if (val.size() < 2) throw std::runtime_error( @@ -660,7 +637,7 @@ namespace llarp for (const auto& router : configRouters) { log::debug(logcat, "Loading bootstrap router list from {}", defaultBootstrapFile); - bootstrap_rc_list.AddFromFile(router); + bootstrap_rc_list.read_from_file(router); } for (const auto& rc : conf.bootstrap.routers) @@ -668,37 +645,10 @@ namespace llarp bootstrap_rc_list.emplace(rc); } - // in case someone has an old bootstrap file and is trying to use a bootstrap - // that no longer exists - auto clearBadRCs = [this]() { - for (auto it = bootstrap_rc_list.begin(); it != bootstrap_rc_list.end();) - { - 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; - continue; - } - // we are in one of the above error cases that we warned about: - it = bootstrap_rc_list.erase(it); - } - }; - - clearBadRCs(); - if (bootstrap_rc_list.empty() and not conf.bootstrap.seednode) { auto fallbacks = llarp::load_bootstrap_fallbacks(); - if (auto itr = fallbacks.find(router_contact.netID.ToString()); itr != fallbacks.end()) - { - bootstrap_rc_list = itr->second; - log::debug( - logcat, "loaded {} default fallback bootstrap routers", bootstrap_rc_list.size()); - clearBadRCs(); - } + if (bootstrap_rc_list.empty() and not conf.bootstrap.seednode) { // empty after trying fallback, if set @@ -711,6 +661,24 @@ namespace llarp } } + // 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 boostrap 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); + } + if (conf.bootstrap.seednode) LogInfo("we are a seed node"); else @@ -727,10 +695,10 @@ namespace llarp &_hidden_service_context, strictConnectPubkeys, bootstrap_rc_list, - is_service_node); + _is_service_node); // FIXME: kludge for now, will be part of larger cleanup effort. - if (is_service_node) + if (_is_service_node) InitInboundLinks(); else InitOutboundLinks(); @@ -759,7 +727,7 @@ namespace llarp } // API config - if (not IsServiceNode()) + if (not is_service_node()) { hidden_service_context().AddEndpoint(conf); } @@ -767,19 +735,13 @@ namespace llarp return true; } - bool - Router::CheckRenegotiateValid(RouterContact newrc, RouterContact oldrc) - { - return _rc_lookup_handler.check_renegotiate_valid(newrc, oldrc); - } - bool Router::IsBootstrapNode(const RouterID r) const { return std::count_if( bootstrap_rc_list.begin(), bootstrap_rc_list.end(), - [r](const RouterContact& rc) -> bool { return rc.router_id() == r; }) + [r](const RemoteRC& rc) -> bool { return rc.router_id() == r; }) > 0; } @@ -797,7 +759,7 @@ namespace llarp LogInfo(node_db()->num_loaded(), " RCs loaded"); LogInfo(bootstrap_rc_list.size(), " bootstrap peers"); LogInfo(NumberOfConnectedRouters(), " router connections"); - if (IsServiceNode()) + if (is_service_node()) { LogInfo(NumberOfConnectedClients(), " client connections"); LogInfo(ToString(router_contact.age(now)), " since we last updated our RC"); @@ -814,7 +776,7 @@ namespace llarp std::string status; auto out = std::back_inserter(status); fmt::format_to(out, "v{}", fmt::join(llarp::LOKINET_VERSION, ".")); - if (IsServiceNode()) + if (is_service_node()) { fmt::format_to( out, @@ -890,7 +852,7 @@ namespace llarp _rc_lookup_handler.periodic_update(now); const bool has_whitelist = _rc_lookup_handler.has_received_whitelist(); - const bool is_snode = IsServiceNode(); + const bool is_snode = is_service_node(); const bool is_decommed = appears_decommed(); bool should_gossip = appears_funded(); @@ -916,7 +878,7 @@ namespace llarp GossipRCIfNeeded(router_contact); } // remove RCs for nodes that are no longer allowed by network policy - node_db()->RemoveIf([&](const RouterContact& rc) -> bool { + node_db()->RemoveIf([&](const RemoteRC& rc) -> bool { // don't purge bootstrap nodes from nodedb if (IsBootstrapNode(rc.router_id())) { @@ -1057,32 +1019,12 @@ namespace llarp _last_tick = llarp::time_now_ms(); } - void - Router::modify_rc(std::function(RouterContact)> modify) - { - if (auto maybe = modify(rc())) - { - router_contact = *maybe; - update_rc(); - _rcGossiper.GossipRC(rc()); - } - } - bool - Router::GetRandomConnectedRouter(RouterContact& result) const + Router::GetRandomConnectedRouter(RemoteRC& result) const { return _link_manager.get_random_connected(result); } - void - Router::HandleDHTLookupForExplore(RouterID /*remote*/, const std::vector& results) - { - for (const auto& rc : results) - { - _rc_lookup_handler.check_rc(rc); - } - } - void Router::set_router_whitelist( const std::vector& whitelist, @@ -1200,7 +1142,7 @@ namespace llarp _route_poker->start(); is_running.store(true); _started_at = now(); - if (IsServiceNode()) + if (is_service_node()) { // do service node testing if we are in service node whitelist mode _loop->call_every(consensus::REACHABILITY_TESTING_TIMER_INTERVAL, weak_from_this(), [this] { @@ -1428,7 +1370,7 @@ namespace llarp bool Router::HasClientExit() const { - if (IsServiceNode()) + if (is_service_node()) return false; const auto& ep = hidden_service_context().GetDefault(); return ep and ep->HasExit(); diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index c20a3e57e4..0abbf5dd28 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -85,7 +85,7 @@ namespace llarp // use file based logging? bool use_file_logging = false; // our router contact - RouterContact router_contact; + LocalRC router_contact; std::shared_ptr _lmq; path::BuildLimiter _pathbuild_limiter; std::shared_ptr loop_wakeup; @@ -94,7 +94,7 @@ namespace llarp std::atomic is_running; int _outbound_udp_socket = -1; - bool is_service_node = false; + bool _is_service_node = false; std::optional _ourAddress; oxen::quic::Address _local_addr; @@ -167,7 +167,7 @@ namespace llarp connect_to(const RouterID& rid); void - connect_to(const RouterContact& rc); + connect_to(const RemoteRC& rc); Contacts* contacts() const @@ -274,7 +274,7 @@ namespace llarp return paths; } - const RouterContact& + const LocalRC& rc() const { return router_contact; @@ -295,9 +295,6 @@ namespace llarp return _rc_lookup_handler.whitelist(); } - void - modify_rc(std::function(RouterContact)> modify); - void set_router_whitelist( const std::vector& whitelist, @@ -381,7 +378,7 @@ namespace llarp status_line(); void - GossipRCIfNeeded(const RouterContact rc); + GossipRCIfNeeded(const LocalRC rc); void InitInboundLinks(); @@ -402,7 +399,7 @@ namespace llarp /// return true if we are running in service node mode bool - IsServiceNode() const; + is_service_node() const; std::optional OxendErrorState() const; @@ -452,12 +449,6 @@ namespace llarp bool PathToRouterAllowed(const RouterID& router) const; - void - HandleSaveRC() const; - - bool - SaveRC(); - /// return true if we are a client with an exit configured bool HasClientExit() const; @@ -489,13 +480,6 @@ namespace llarp bool IsBootstrapNode(RouterID) const; - /// check if newRc matches oldRC and update local rc for this remote contact - /// if valid - /// returns true on valid and updated - /// returns false otherwise - bool - CheckRenegotiateValid(RouterContact newRc, RouterContact oldRC); - /// call internal router ticker void Tick(); @@ -525,10 +509,7 @@ namespace llarp NumberOfConnectedClients() const; bool - GetRandomConnectedRouter(RouterContact& result) const; - - void - HandleDHTLookupForExplore(RouterID remote, const std::vector& results); + GetRandomConnectedRouter(RemoteRC& result) const; bool HasSessionTo(const RouterID& remote) const; diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index 01a9d5f643..f7c1211fda 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -30,13 +30,13 @@ namespace llarp // } // } - std::string - RouterContact::bt_encode() const - { - oxenc::bt_dict_producer btdp; - bt_encode(btdp); - return std::move(btdp).str(); - } + // std::string + // RouterContact::bt_encode() const + // { + // oxenc::bt_dict_producer btdp; + // bt_encode(btdp); + // return std::move(btdp).str(); + // } void RouterContact::bt_load(oxenc::bt_dict_consumer& data) @@ -107,6 +107,23 @@ namespace llarp _router_version[i] = ver[i]; } + bool + RouterContact::write(const fs::path& fname) const + { + auto bte = bt_encode(); + + try + { + util::buffer_to_file(fname, bte.data(), bte.size()); + } + catch (const std::exception& e) + { + log::error(logcat, "Failed to write RC to {}: {}", fname, e.what()); + return false; + } + return true; + } + // std::string // RouterContact::bencode_signed_section() const // { @@ -208,7 +225,7 @@ namespace llarp (void)key; // TOFIX: fuck everything about llarp_buffer_t - + // if (!BEncodeMaybeReadDictEntry("a", addr, read, key, buf)) // return false; @@ -299,42 +316,4 @@ namespace llarp } return false; } - - bool - RouterContact::write(const fs::path& fname) const - { - std::array tmp; - llarp_buffer_t buf(tmp); - - auto bte = bt_encode(); - buf.write(bte.begin(), bte.end()); - - try - { - util::dump_file(fname, tmp.data(), buf.cur - buf.base); - } - catch (const std::exception& e) - { - log::error(logcat, "Failed to write RC to {}: {}", fname, e.what()); - return false; - } - return true; - } - - bool - RouterContact::read(const fs::path& fname) - { - std::array tmp; - llarp_buffer_t buf(tmp); - try - { - util::file_to_buffer(fname, tmp.data(), tmp.size()); - } - catch (const std::exception& e) - { - log::error(logcat, "Failed to read RC from {}: {}", fname, e.what()); - return false; - } - return BDecode(&buf); - } } // namespace llarp diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index d2a0f54a66..1d8f737b03 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -18,10 +18,10 @@ #include #include -namespace oxenc -{ - class bt_list_consumer; -} // namespace oxenc +// namespace oxenc +// { +// class bt_list_consumer; +// } // namespace oxenc /* - figure out where we do bt_encoding of RC's @@ -42,17 +42,20 @@ namespace llarp using rc_time = std::chrono::time_point; + static inline constexpr size_t NETID_SIZE{8}; + /// RouterContact struct RouterContact { static constexpr uint8_t RC_VERSION = 0; /// Constructs an empty RC - RouterContact() = default; - RouterContact(std::string) - { - log::error(logcat, "ERROR: SUPPLANT THIS CONSTRUCTOR"); - } + // RouterContact() = default; + + // RouterContact(std::string) + // { + // log::error(logcat, "ERROR: SUPPLANT THIS CONSTRUCTOR"); + // } // RouterContact(std::string buf); @@ -119,12 +122,19 @@ namespace llarp // Lokinet version at the time the RC was produced std::array _router_version; + // In both Remote and Local RC's, the entire bt-encoded payload given at construction is + // emplaced here. + // + // In a RemoteRC, this value will be held for the lifetime of the object + // s.t. it can be returned upon calls to ::bt_encode. + // In a LocalRC, this value will be supplanted any time a mutator is invoked, requiring + // the re-signing of the payload. + ustring _payload; + public: /// should we serialize the exit info? const static bool serializeExit = true; - ustring _signed_payload; - util::StatusObject extract_status() const; @@ -138,13 +148,16 @@ namespace llarp to_string() const { return fmt::format( - "[RC k={} updated={} v={} addr={}]", - _router_id, - _timestamp, - RC_VERSION, - _addr.to_string()); + "[RC k={} updated={} v={} addr={}]", + _router_id.ToView(), + _timestamp.time_since_epoch().count(), + RC_VERSION, + _addr.to_string()); } + bool + write(const fs::path& fname) 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 @@ -161,13 +174,11 @@ namespace llarp /// "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; - - virtual void - bt_encode(oxenc::bt_dict_producer& btdp) const + virtual ustring_view + bt_encode() const { - (void)btdp; + log::warning(logcat, "ERROR: SUPPLANT THIS METHOD"); + return {}; } bool @@ -190,7 +201,7 @@ namespace llarp } virtual void - clear() + clear() {} bool @@ -224,21 +235,13 @@ namespace llarp return _timestamp < other._timestamp; } - bool - read(const fs::path& fname); - - bool - write(const fs::path& fname) const; - bool is_obsolete_bootstrap() const; void bt_load(oxenc::bt_dict_consumer& data); - }; - /// 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 @@ -246,24 +249,35 @@ namespace llarp /// 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 + struct LocalRC final : public RouterContact { private: ustring _signature; - const SecretKey _secret_key; + // TODO: fix these parameters void - bt_sign(oxenc::bt_dict_consumer& btdc); - + bt_sign(oxenc::bt_dict_producer& btdp); + void - resign(); + bt_encode(oxenc::bt_dict_producer& btdp) const; public: - LocalRC(std::string payload, const SecretKey sk); + LocalRC() = default; + explicit LocalRC(std::string payload, const SecretKey sk); + ~LocalRC() = default; void - bt_encode(oxenc::bt_dict_producer& btdp) const override; + resign(); + + ustring_view + bt_encode() const override; + + ustring_view + view() const + { + return _payload; + } void clear() override @@ -289,22 +303,22 @@ namespace llarp void set_addr(oxen::quic::Address new_addr) { - resign(); _addr = std::move(new_addr); + resign(); } void set_addr6(oxen::quic::Address new_addr) { - resign(); _addr6 = std::move(new_addr); + resign(); } void set_router_id(RouterID rid) { - resign(); _router_id = std::move(rid); + resign(); } void @@ -328,24 +342,44 @@ namespace llarp } }; - /// 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 + struct RemoteRC final : public RouterContact { private: - // - + // TODO: fix these parameters void - bt_verify(oxenc::bt_dict_consumer& data, bool reject_expired = false); + bt_verify(oxenc::bt_dict_consumer& data, bool reject_expired = false) const; - public: - RemoteRC(std::string payload); + public: + RemoteRC() = default; + RemoteRC(std::string_view data) : RemoteRC{oxenc::bt_dict_consumer{data}} + {} + RemoteRC(ustring_view data) : RemoteRC{oxenc::bt_dict_consumer{data}} + { + _payload = data; + } + explicit RemoteRC(oxenc::bt_dict_consumer btdc); + ~RemoteRC() = default; + + ustring_view + bt_encode() const override + { + return _payload; + } + + std::string_view + view() const + { + return {reinterpret_cast(_payload.data()), _payload.size()}; + } + + bool + verify() const; + + bool + read(const fs::path& fname); - // TODO: this method could use oxenc's append_encoded - void - bt_encode(oxenc::bt_dict_producer& btdp) const override; - void clear() override { @@ -355,7 +389,6 @@ namespace llarp _timestamp = {}; _router_version.fill(0); } - }; template <> @@ -365,7 +398,7 @@ namespace llarp template <> constexpr inline bool IsToStringFormattable = true; - using RouterLookupHandler = std::function&)>; + using RouterLookupHandler = std::function&)>; } // namespace llarp namespace std diff --git a/llarp/router_contact_local.cpp b/llarp/router_contact_local.cpp index 275b3c64e7..71537692d6 100644 --- a/llarp/router_contact_local.cpp +++ b/llarp/router_contact_local.cpp @@ -11,8 +11,7 @@ namespace llarp { - LocalRC::LocalRC(std::string payload, const SecretKey sk) : - _secret_key{std::move(sk)} + LocalRC::LocalRC(std::string payload, const SecretKey sk) : _secret_key{std::move(sk)} { _router_id = llarp::seckey_to_pubkey(_secret_key); @@ -20,7 +19,27 @@ namespace llarp { oxenc::bt_dict_consumer btdc{payload}; bt_load(btdc); - bt_sign(btdc); + + btdc.require_signature("~", [this](ustring_view msg, ustring_view sig) { + if (sig.size() != 64) + throw std::runtime_error{"Invalid signature: not 64 bytes"}; + + if (is_expired(time_now_ms())) + throw std::runtime_error{"Unable to verify expired RemoteRC!"}; + + // TODO: revisit if this is needed; detail from previous implementation + const auto* net = net::Platform::Default_ptr(); + + if (net->IsBogon(addr().in4()) and BLOCK_BOGONS) + { + auto err = "Unable to verify expired RemoteRC!"; + log::info(logcat, err); + throw std::runtime_error{err}; + } + + if (not crypto::verify(router_id(), msg, sig)) + throw std::runtime_error{"Failed to verify RemoteRC"}; + }); } catch (const std::exception& e) { @@ -30,17 +49,29 @@ namespace llarp } void - LocalRC::bt_sign(oxenc::bt_dict_consumer& btdc) + LocalRC::bt_sign(oxenc::bt_dict_producer& btdp) { _signature.clear(); - btdc.require_signature("~", [&](ustring_view msg, ustring_view s) { - if (!crypto::sign(const_cast(s.data()), _secret_key, msg)) + btdp.append_signature("~", [this](ustring_view to_sign) { + std::array sig; + + if (!crypto::sign(const_cast(sig.data()), _secret_key, to_sign)) throw std::runtime_error{"Failed to sign RC"}; - _signature = s; - _signed_payload = msg; + _signature = {sig.data(), sig.size()}; + return sig; }); + + _payload = btdp.view(); + } + + ustring_view + LocalRC::bt_encode() const + { + oxenc::bt_dict_producer btdp; + bt_encode(btdp); + return btdp.view(); } void @@ -86,12 +117,12 @@ namespace llarp btdp.append( "v", std::string_view{reinterpret_cast(llarp::LOKINET_VERSION.data()), 3}); - btdp.append_signature("~", [&](ustring_view to_sign) { + btdp.append_signature("~", [this](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; }); } @@ -99,10 +130,9 @@ namespace llarp 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? + set_systime_timestamp(); + oxenc::bt_dict_producer btdp; + bt_encode(btdp); + bt_sign(btdp); } } // namespace llarp diff --git a/llarp/router_contact_remote.cpp b/llarp/router_contact_remote.cpp index f17100310d..8cb127d4c9 100644 --- a/llarp/router_contact_remote.cpp +++ b/llarp/router_contact_remote.cpp @@ -11,13 +11,32 @@ namespace llarp { - RemoteRC::RemoteRC(std::string payload) + RemoteRC::RemoteRC(oxenc::bt_dict_consumer btdc) { try { - oxenc::bt_dict_consumer btdc{payload}; bt_load(btdc); - bt_verify(btdc); + + btdc.require_signature("~", [this](ustring_view msg, ustring_view sig) { + if (sig.size() != 64) + throw std::runtime_error{"Invalid signature: not 64 bytes"}; + + if (is_expired(time_now_ms())) + throw std::runtime_error{"Unable to verify expired RemoteRC!"}; + + // TODO: revisit if this is needed; detail from previous implementation + const auto* net = net::Platform::Default_ptr(); + + if (net->IsBogon(addr().in4()) and BLOCK_BOGONS) + { + auto err = "Unable to verify expired RemoteRC!"; + log::info(logcat, err); + throw std::runtime_error{err}; + } + + if (not crypto::verify(router_id(), msg, sig)) + throw std::runtime_error{"Failed to verify RemoteRC"}; + }); } catch (const std::exception& e) { @@ -27,21 +46,7 @@ namespace llarp } 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) + RemoteRC::bt_verify(oxenc::bt_dict_consumer& data, bool reject_expired) const { data.require_signature("~", [this, reject_expired](ustring_view msg, ustring_view sig) { if (sig.size() != 64) @@ -62,8 +67,40 @@ namespace llarp if (not crypto::verify(router_id(), msg, sig)) throw std::runtime_error{"Failed to verify RemoteRC"}; - - _signed_payload = msg; }); } + + bool + RemoteRC::read(const fs::path& fname) + { + ustring buf; + buf.reserve(MAX_RC_SIZE); + + try + { + util::file_to_buffer(fname, buf.data(), MAX_RC_SIZE); + } + catch (const std::exception& e) + { + log::error(logcat, "Failed to read RC from {}: {}", fname, e.what()); + return false; + } + + oxenc::bt_dict_consumer btdc{buf}; + bt_load(btdc); + bt_verify(btdc); + + _payload = buf; + + return true; + } + + bool + RemoteRC::verify() const + { + oxenc::bt_dict_consumer btdc{_payload}; + bt_verify(btdc); + return true; + } + } // namespace llarp diff --git a/llarp/rpc/lokid_rpc_client.cpp b/llarp/rpc/lokid_rpc_client.cpp index c9390b3b7f..aa4e3f3ad1 100644 --- a/llarp/rpc/lokid_rpc_client.cpp +++ b/llarp/rpc/lokid_rpc_client.cpp @@ -51,7 +51,7 @@ namespace llarp::rpc { if (auto router = m_Router.lock()) { - if (not router->IsServiceNode()) + if (not router->is_service_node()) { throw std::runtime_error("we cannot talk to lokid while not a service node"); } diff --git a/llarp/rpc/rpc_server.cpp b/llarp/rpc/rpc_server.cpp index 92a7d71b37..598dd36f13 100644 --- a/llarp/rpc/rpc_server.cpp +++ b/llarp/rpc/rpc_server.cpp @@ -74,7 +74,7 @@ namespace llarp::rpc std::shared_ptr GetEndpointByName(Router& r, std::string name) { - if (r.IsServiceNode()) + if (r.is_service_node()) { return r.exitContext().GetExitEndpoint(name); } @@ -309,7 +309,7 @@ namespace llarp::rpc void RPCServer::invoke(LookupSnode& lookupsnode) { - if (not m_Router.IsServiceNode()) + if (not m_Router.is_service_node()) { SetJSONError("Not supported", lookupsnode.response); return; diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 7b54516128..83afaf9444 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -200,6 +200,7 @@ namespace llarp::service }); } + // TODO: revisit once SRVRecords are straightened out void Endpoint::LookupServiceAsync( std::string name, @@ -226,9 +227,9 @@ namespace llarp::service if (auto maybe_rc = nodedb->get_rc(router_id)) { - result = maybe_rc->srvRecords; // TODO: RouterContact has no SRV records + // result = maybe_rc->srvRecords; // TODO: RouterContact has no SRV records } - + resultHandler(std::move(result)); }; @@ -756,22 +757,22 @@ namespace llarp::service return now >= next_pub; } - std::optional> + std::optional> Endpoint::GetHopsForBuild() { std::unordered_set exclude; ForEachPath([&exclude](auto path) { exclude.insert(path->Endpoint()); }); const auto maybe = - router()->node_db()->GetRandom([exclude, r = router()](const auto& rc) -> bool { - return exclude.count(rc.pubkey) == 0 - and not r->router_profiling().IsBadForPath(rc.pubkey); + router()->node_db()->GetRandom([exclude, r = router()](const RemoteRC& rc) -> bool { + const auto& rid = rc.router_id(); + return exclude.count(rid) == 0 and not r->router_profiling().IsBadForPath(rid); }); if (not maybe.has_value()) return std::nullopt; return GetHopsForBuildWithEndpoint(maybe->router_id()); } - std::optional> + std::optional> Endpoint::GetHopsForBuildWithEndpoint(RouterID endpoint) { return path::Builder::GetHopsAlignedToForBuild(endpoint, SnodeBlacklist()); diff --git a/llarp/service/endpoint.hpp b/llarp/service/endpoint.hpp index 63bedc6d70..faa8b3f470 100644 --- a/llarp/service/endpoint.hpp +++ b/llarp/service/endpoint.hpp @@ -409,10 +409,10 @@ namespace llarp bool HasExit() const; - std::optional> + std::optional> GetHopsForBuild() override; - std::optional> + std::optional> GetHopsForBuildWithEndpoint(RouterID endpoint); void diff --git a/llarp/service/identity.cpp b/llarp/service/identity.cpp index b6333dcd7c..05c6763f75 100644 --- a/llarp/service/identity.cpp +++ b/llarp/service/identity.cpp @@ -97,7 +97,7 @@ namespace llarp::service // write try { - util::dump_file(fname, tmp.data(), sz); + util::buffer_to_file(fname, tmp.data(), sz); } catch (const std::exception& e) { diff --git a/llarp/service/outbound_context.cpp b/llarp/service/outbound_context.cpp index 115394f577..c67c995519 100644 --- a/llarp/service/outbound_context.cpp +++ b/llarp/service/outbound_context.cpp @@ -350,7 +350,7 @@ namespace llarp::service return false; } - std::optional> + std::optional> OutboundContext::GetHopsForBuild() { if (next_intro.router.IsZero()) diff --git a/llarp/service/outbound_context.hpp b/llarp/service/outbound_context.hpp index d0381b0c7d..8504efcd7f 100644 --- a/llarp/service/outbound_context.hpp +++ b/llarp/service/outbound_context.hpp @@ -152,7 +152,7 @@ namespace llarp::service void HandlePathBuildFailedAt(path::Path_ptr path, RouterID hop) override; - std::optional> + std::optional> GetHopsForBuild() override; std::string diff --git a/llarp/service/router_lookup_job.cpp b/llarp/service/router_lookup_job.cpp index 3c988a73b4..c08a139f24 100644 --- a/llarp/service/router_lookup_job.cpp +++ b/llarp/service/router_lookup_job.cpp @@ -4,13 +4,10 @@ #include -namespace llarp +namespace llarp::service { - namespace service - { - RouterLookupJob::RouterLookupJob(Endpoint* p, RouterLookupHandler h) - : handler(std::move(h)), txid(p->GenTXID()), started(p->Now()) - {} + RouterLookupJob::RouterLookupJob(Endpoint* p, RouterLookupHandler h) + : handler(std::move(h)), txid(p->GenTXID()), started(p->Now()) + {} - } // namespace service -} // namespace llarp +} // namespace llarp::service diff --git a/llarp/service/router_lookup_job.hpp b/llarp/service/router_lookup_job.hpp index 58228107b6..d9dce72467 100644 --- a/llarp/service/router_lookup_job.hpp +++ b/llarp/service/router_lookup_job.hpp @@ -2,34 +2,31 @@ #include -namespace llarp +namespace llarp::service { - namespace service - { - struct Endpoint; + struct Endpoint; - struct RouterLookupJob - { - RouterLookupJob(Endpoint* p, RouterLookupHandler h); + struct RouterLookupJob + { + RouterLookupJob(Endpoint* p, RouterLookupHandler h); - RouterLookupHandler handler; - uint64_t txid; - llarp_time_t started; + RouterLookupHandler handler; + uint64_t txid; + llarp_time_t started; - bool - IsExpired(llarp_time_t now) const - { - if (now < started) - return false; - return now - started > 30s; - } + bool + IsExpired(llarp_time_t now) const + { + if (now < started) + return false; + return now - started > 30s; + } - void - InformResult(std::vector result) - { - if (handler) - handler(result); - } - }; - } // namespace service -} // namespace llarp + void + InformResult(std::vector result) + { + if (handler) + handler(result); + } + }; +} // namespace llarp::service diff --git a/llarp/util/bencode.hpp b/llarp/util/bencode.hpp index fcde4efbcb..be616717ee 100644 --- a/llarp/util/bencode.hpp +++ b/llarp/util/bencode.hpp @@ -389,7 +389,7 @@ namespace llarp tmp.resize(buf.cur - buf.base); try { - util::dump_file(fpath, tmp); + util::buffer_to_file(fpath, tmp); } catch (const std::exception& e) { diff --git a/llarp/util/file.cpp b/llarp/util/file.cpp index 26b21d9874..9b482852ad 100644 --- a/llarp/util/file.cpp +++ b/llarp/util/file.cpp @@ -52,7 +52,7 @@ namespace llarp::util } void - dump_file(const fs::path& filename, std::string_view contents) + buffer_to_file(const fs::path& filename, std::string_view contents) { fs::ofstream out; out.exceptions(std::ifstream::failbit | std::ifstream::badbit); diff --git a/llarp/util/file.hpp b/llarp/util/file.hpp index 82ff2bfbc2..39c1406737 100644 --- a/llarp/util/file.hpp +++ b/llarp/util/file.hpp @@ -34,14 +34,14 @@ namespace llarp::util /// Dumps binary string contents to disk. The file is overwritten if it already exists. Throws /// on error. void - dump_file(const fs::path& filename, std::string_view contents); + buffer_to_file(const fs::path& filename, std::string_view contents); /// Same as above, but works via char-like buffer template = 0> inline void - dump_file(const fs::path& filename, const Char* buffer, size_t buffer_size) + buffer_to_file(const fs::path& filename, const Char* buffer, size_t buffer_size) { - return dump_file( + return buffer_to_file( filename, std::string_view{reinterpret_cast(buffer), buffer_size}); } From 0de50b176bb0a09e1f59d859960aaa7010fd0bca Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Thu, 2 Nov 2023 13:46:22 -0300 Subject: [PATCH 092/312] Untangle Endpoint::LookupServiceAsync - .snodes don't need to support SRV records, so remove that - untangle the mess of captured lambdas capturing other lambdas capturing other lambdas; we still need a chain of nested lambdas because we have a chain of callbacked events, but hiding the nesting by capturing them in other lambdas didn't improve anything. --- llarp/service/endpoint.cpp | 141 +++++++++++++------------------------ 1 file changed, 49 insertions(+), 92 deletions(-) diff --git a/llarp/service/endpoint.cpp b/llarp/service/endpoint.cpp index 83afaf9444..725f498e18 100644 --- a/llarp/service/endpoint.cpp +++ b/llarp/service/endpoint.cpp @@ -200,106 +200,63 @@ namespace llarp::service }); } - // TODO: revisit once SRVRecords are straightened out void Endpoint::LookupServiceAsync( std::string name, std::string service, std::function)> resultHandler) { - // handles when we aligned to a loki address - auto handleGotPathToService = [resultHandler, service, this](auto addr) { - // we can probably get this info before we have a path to them but we do this after we - // have a path so when we send the response back they can send shit to them immediately - const auto& container = _state->remote_sessions; - if (auto itr = container.find(addr); itr != container.end()) - { - // parse the stuff we need from this guy - resultHandler(itr->second->GetCurrentIntroSet().GetMatchingSRVRecords(service)); - return; - } - resultHandler({}); - }; - - // 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; // TODO: RouterContact has no SRV records - } - - resultHandler(std::move(result)); - }; - - // handles when we got a path to a remote thing - auto handleGotPathTo = [handleGotPathToService, handleResolvedSNodeName, resultHandler]( - auto maybe_tag, auto address) { - if (not maybe_tag) - { - resultHandler({}); - return; - } - - if (auto* addr = std::get_if
(&address)) - { - // .loki case - handleGotPathToService(*addr); - } - else if (auto* router_id = std::get_if(&address)) - { - // .snode case - handleResolvedSNodeName(*router_id); - } - else - { - // fallback case - // XXX: never should happen but we'll handle it anyways - resultHandler({}); - } - }; - - // handles when we know a long address of a remote resource - auto handleGotAddress = [resultHandler, handleGotPathTo, this](AddressVariant_t address) { - // we will attempt a build to whatever we looked up - const auto result = EnsurePathTo( - address, - [address, handleGotPathTo](auto maybe_tag) { handleGotPathTo(maybe_tag, address); }, - PathAlignmentTimeout()); - - // on path build start fail short circuit - if (not result) - resultHandler({}); - }; - - // look up this name async and start the entire chain of events - lookup_name(name, [handleGotAddress, resultHandler](oxen::quic::message m) mutable { - if (m) - { - std::string name; - try - { - oxenc::bt_dict_consumer btdc{m.body()}; - name = btdc.require("NAME"); - } - catch (...) - { - log::warning(link_cat, "Failed to parse find name response!"); - throw; - } + // A lookup goes through a chain of events: + // - see if the name is ONS, and if so resolve it to a ADDR.loki + // - once we've resolved to ADDR.loki then initiate a path to it + // - once we have a path, consult the remote's introset to pull out the SRV records + // If we fail along the way (e.g. it's a .snode, we can't build a path, or whatever else) then + // we invoke the resultHandler with an empty vector. + lookup_name( + name, [this, resultHandler, service = std::move(service)](oxen::quic::message m) mutable { + if (!m) + return resultHandler({}); - if (auto saddr = service::Address(); saddr.FromString(name)) - handleGotAddress(saddr); + std::string name; + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + name = btdc.require("NAME"); + } + catch (...) + { + log::warning(link_cat, "Failed to parse find name response!"); + throw; + } - if (auto rid = RouterID(); rid.FromString(name)) - handleGotAddress(rid); - } - else - { - resultHandler({}); - } - }); + auto saddr = service::Address(); + if (!saddr.FromString(name)) + return resultHandler({}); // Not a regular ADDR.loki so doesn't support SRV + + // initiate path build + const auto build_started = EnsurePathTo( + saddr, + [this, address = std::move(saddr), resultHandler, service = std::move(service)]( + auto maybe_tag) { + if (not maybe_tag) + return resultHandler({}); + + // we can probably get this info before we have a path to them but we do this after + // we have a path so when we send the DNS response back they can talk to them + // immediately + const auto& container = _state->remote_sessions; + if (auto itr = container.find(address); itr != container.end()) + // parse the stuff we need from this guy + resultHandler(itr->second->GetCurrentIntroSet().GetMatchingSRVRecords(service)); + else + resultHandler({}); + }, + PathAlignmentTimeout()); + + // on path build start fail short circuit + if (not build_started) + resultHandler({}); + }); } bool From 47bedfd8da9ee409a65670aa8845baa11af7fca2 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 2 Nov 2023 05:39:20 -0700 Subject: [PATCH 093/312] Review fixes + misc fixes --- llarp/CMakeLists.txt | 1 - llarp/bootstrap.cpp | 2 +- llarp/link/link_manager.cpp | 3 +- llarp/net/exit_info.cpp | 121 ---------------------------- llarp/net/exit_info.hpp | 51 ------------ llarp/router/rc_lookup_handler.cpp | 3 +- llarp/router/router.cpp | 124 ++++++++++++----------------- llarp/router/router.hpp | 5 +- llarp/router_contact.cpp | 22 +---- llarp/router_contact.hpp | 105 +++++++----------------- llarp/router_contact_local.cpp | 34 ++++---- llarp/service/identity.cpp | 54 ++++++++----- llarp/service/identity.hpp | 6 +- llarp/service/protocol.hpp | 6 -- llarp/util/bencode.hpp | 30 ++----- 15 files changed, 152 insertions(+), 415 deletions(-) delete mode 100644 llarp/net/exit_info.cpp delete mode 100644 llarp/net/exit_info.hpp diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index cce2e29b5d..9b6635cb9e 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -91,7 +91,6 @@ add_dependencies(lokinet-utils genversion) lokinet_add_library(lokinet-time-place ev/ev.cpp ev/libuv.cpp - net/exit_info.cpp # only router_contact net/ip.cpp net/ip_address.cpp net/ip_packet.cpp diff --git a/llarp/bootstrap.cpp b/llarp/bootstrap.cpp index c51da6deea..474052c304 100644 --- a/llarp/bootstrap.cpp +++ b/llarp/bootstrap.cpp @@ -31,7 +31,7 @@ namespace llarp oxenc::bt_list_producer btlp{}; for (const auto& it : *this) - btlp.append(it.bt_encode()); + btlp.append(it.view()); return btlp.view(); } diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 2e80cb603a..caa004a4ed 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -628,8 +628,7 @@ namespace llarp || local_rid == rid) continue; - neighbors += - rid.bt_encode(); // TODO: refactor to use reference to bt_dict_producer subdict + neighbors += rid.bt_encode(); } m.respond( diff --git a/llarp/net/exit_info.cpp b/llarp/net/exit_info.cpp deleted file mode 100644 index 69d297cca1..0000000000 --- a/llarp/net/exit_info.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef _WIN32 -#include -#endif - -#include "exit_info.hpp" - -#include - -#include - -namespace llarp -{ - bool - ExitInfo::bt_encode(llarp_buffer_t* buf) const - { - SockAddr exitaddr = ipAddress.createSockAddr(); - const auto* exitaddr6 = static_cast(exitaddr); - - SockAddr netmaskaddr = netmask.createSockAddr(); - const auto* netmaskaddr6 = static_cast(netmaskaddr); - - char tmp[128] = {0}; - if (!bencode_start_dict(buf)) - return false; - - if (!inet_ntop(AF_INET6, &exitaddr6->sin6_addr, tmp, sizeof(tmp))) - return false; - if (!BEncodeWriteDictString("a", std::string(tmp), buf)) - return false; - - if (!inet_ntop(AF_INET6, &netmaskaddr6->sin6_addr, tmp, sizeof(tmp))) - return false; - if (!BEncodeWriteDictString("b", std::string(tmp), buf)) - return false; - - if (!BEncodeWriteDictEntry("k", pubkey, buf)) - return false; - - if (!BEncodeWriteDictInt("v", version, buf)) - return false; - - return bencode_end(buf); - } - - static bool - bdecode_ip_string(llarp_buffer_t* buf, in6_addr& ip) - { - char tmp[128] = {0}; - llarp_buffer_t strbuf; - if (!bencode_read_string(buf, &strbuf)) - return false; - - if (strbuf.sz >= sizeof(tmp)) - return false; - - memcpy(tmp, strbuf.base, strbuf.sz); - tmp[strbuf.sz] = 0; - return inet_pton(AF_INET6, tmp, &ip.s6_addr[0]) == 1; - } - - bool - ExitInfo::decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf) - { - bool read = false; - if (!BEncodeMaybeReadDictEntry("k", pubkey, read, k, buf)) - return false; - if (!BEncodeMaybeReadDictInt("v", version, read, k, buf)) - return false; - if (k.startswith("a")) - { - in6_addr tmp; - if (not bdecode_ip_string(buf, tmp)) - return false; - - SockAddr addr(tmp); - ipAddress = IpAddress(addr); - return true; - } - if (k.startswith("b")) - { - in6_addr tmp; - if (not bdecode_ip_string(buf, tmp)) - return false; - SockAddr addr(tmp); - netmask = IpAddress(addr); - return true; - } - return read; - } - - std::string - ExitInfo::ToString() const - { - /* - // TODO: derive these from ipAdress - throw std::runtime_error("FIXME: need in6_addr and netmask from IpAddress"); - in6_addr address; - in6_addr netmask; - - Printer printer(stream, level, spaces); - - std::ostringstream ss; - char tmp[128] = {0}; - - if (inet_ntop(AF_INET6, (void*)&address, tmp, sizeof(tmp))) - ss << tmp; - else - return stream; - ss << std::string("/"); -#if defined(ANDROID) - snprintf(tmp, sizeof(tmp), "%zu", llarp::bits::count_array_bits(netmask.s6_addr)); - ss << tmp; -#else - ss << std::to_string(llarp::bits::count_array_bits(netmask.s6_addr)); -#endif - printer.printValue(ss.str()); - */ - return fmt::format("[Exit {}]", ipAddress.ToString()); - } - -} // namespace llarp diff --git a/llarp/net/exit_info.hpp b/llarp/net/exit_info.hpp deleted file mode 100644 index 5c1c92736c..0000000000 --- a/llarp/net/exit_info.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include "ip_address.hpp" - -#include -#include - -#include - -/** - * exit_info.h - * - * utilities for handling exits on the llarp network - */ - -/// Exit info model -namespace llarp -{ - /// deprecated don't use me , this is only for backwards compat - struct ExitInfo - { - IpAddress ipAddress; - IpAddress netmask; - PubKey pubkey; - uint64_t version = llarp::constants::proto_version; - - ExitInfo() = default; - - ExitInfo(const PubKey& pk, const IpAddress& address) : ipAddress(address), pubkey(pk) - {} - - bool - bt_encode(llarp_buffer_t* buf) const; - - bool - BDecode(llarp_buffer_t* buf) - { - return bencode_decode_dict(*this, buf); - } - - bool - decode_key(const llarp_buffer_t& k, llarp_buffer_t* buf); - - std::string - ToString() const; - }; - - template <> - constexpr inline bool IsToStringFormattable = true; - -} // namespace llarp diff --git a/llarp/router/rc_lookup_handler.cpp b/llarp/router/rc_lookup_handler.cpp index 8723f1bbe6..b284b9562e 100644 --- a/llarp/router/rc_lookup_handler.cpp +++ b/llarp/router/rc_lookup_handler.cpp @@ -278,7 +278,8 @@ namespace llarp { for (const auto& rc : bootstrap_rc_list) { - log::info(link_cat, "Doing explore via bootstrap node: {}", RouterID(rc.router_id())); + const auto& rid = rc.router_id(); + log::info(link_cat, "Doing explore via bootstrap node: {}", rid); // TODO: replace this concept // dht->ExploreNetworkVia(dht::Key_t{rc.pubkey}); diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 1b88b6f435..3c6e444148 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -539,15 +539,19 @@ namespace llarp return _link_manager.get_num_connected_clients(); } + void + Router::save_rc() + { + _node_db->put_rc(router_contact.view()); + queue_disk_io([&]() { router_contact.write(our_rc_file); }); + } + bool Router::update_rc() { router_contact.resign(); if (is_service_node()) - { - _node_db->put_rc(router_contact.view()); - queue_disk_io([&]() { router_contact.write(our_rc_file); }); - } + save_rc(); return true; } @@ -756,17 +760,24 @@ namespace llarp Router::report_stats() { const auto now = llarp::time_now_ms(); - LogInfo(node_db()->num_loaded(), " RCs loaded"); - LogInfo(bootstrap_rc_list.size(), " bootstrap peers"); - LogInfo(NumberOfConnectedRouters(), " router connections"); + log::info( + logcat, + "{} RCs loaded with {} bootstrap peers and {} router connections!", + node_db()->num_loaded(), + bootstrap_rc_list.size(), + NumberOfConnectedRouters()); + if (is_service_node()) { - LogInfo(NumberOfConnectedClients(), " client connections"); - LogInfo(ToString(router_contact.age(now)), " since we last updated our RC"); - LogInfo(ToString(router_contact.time_to_expiry(now)), " until our RC expires"); + log::info( + logcat, + "Local service node has {} client connections since last RC update ({} to expiry)", + NumberOfConnectedClients(), + router_contact.age(now), + router_contact.time_to_expiry(now)); } if (_last_stats_report > 0s) - LogInfo(ToString(now - _last_stats_report), " last reported stats"); + log::info(logcat, "Last reported stats time {}", now - _last_stats_report); _last_stats_report = now; } @@ -939,7 +950,7 @@ namespace llarp // mark peers as de-registered for (auto& peer : close_peers) - _link_manager.deregister_peer(std::move(peer)); + _link_manager.deregister_peer(peer); } _link_manager.check_persisting_conns(now); @@ -1049,83 +1060,48 @@ namespace llarp if (is_running || is_stopping) return false; - // TODO: replace all this logic with construction of LocalRC + router_contact = LocalRC::make(identity(), public_ip()); - /* // set public signing key - router_contact._router_id = seckey_topublic(identity()); - // set router version if service node - if (IsServiceNode()) + if (is_service_node() and not router_contact.is_public_router()) { - router_contact.routerVersion = - RouterVersion(llarp::LOKINET_VERSION, llarp::constants::proto_version); - } - - if (IsServiceNode() and not router_contact.is_public_router()) - { - LogError("we are configured as relay but have no reachable addresses"); - return false; - } - - // set public encryption key - router_contact.enckey = seckey_topublic(encryption()); - - LogInfo("Signing rc..."); - if (!router_contact.sign(identity())) - { - LogError("failed to sign rc"); - return false; - } - - if (IsServiceNode()) - { - if (!SaveRC()) + if (not router_contact.is_public_router()) { - LogError("failed to save RC"); + log::error(logcat, "Router is configured as relay but has no reachable addresses!"); return false; } - } - if (IsServiceNode()) - { - // initialize as service node - if (!InitServiceNode()) + save_rc(); + + if (not init_service_node()) { - LogError("Failed to initialize service node"); + log::error(logcat, "Router failed to initialize service node!"); return false; } + + log::info(logcat, "Router initialized as service node!"); const RouterID us = pubkey(); - LogInfo("initalized service node: ", us); - // init gossiper here _rcGossiper.Init(&_link_manager, us, this); // relays do not use profiling router_profiling().Disable(); } else { - // we are a client - // regenerate keys and resign rc before everything else + // we are a client, regenerate keys and resign rc before everything else crypto::identity_keygen(_identity); crypto::encryption_keygen(_encryption); - router_contact._router_id = seckey_topublic(identity()); - router_contact.enckey = seckey_topublic(encryption()); - if (!router_contact.sign(identity())) - { - LogError("failed to regenerate keys and sign RC"); - return false; - } - } */ + router_contact.set_router_id(seckey_to_pubkey(identity())); // resigns RC + } + + log::info(logcat, "Starting hidden service context..."); - LogInfo("starting hidden service context..."); if (!hidden_service_context().StartAll()) { - LogError("Failed to start hidden service context"); + log::error(logcat, "Failed to start hidden service context!"); return false; } - { - LogInfo("Loading nodedb from disk..."); - _node_db->load_from_disk(); - } + log::info(logcat, "Loading NodeDB from disk..."); + _node_db->load_from_disk(); _contacts = std::make_shared(llarp::dht::Key_t(pubkey()), *this); @@ -1133,15 +1109,16 @@ namespace llarp { node_db()->put_rc(rc); _contacts->rc_nodes()->PutNode(rc); - LogInfo("added bootstrap node ", RouterID{rc.router_id()}); + log::info(logcat, "Added bootstrap node (rid: {})", rc.router_id()); } - LogInfo("have ", _node_db->num_loaded(), " routers"); + log::info(logcat, "Router populated NodeDB with {} routers", _node_db->num_loaded()); _loop->call_every(ROUTER_TICK_INTERVAL, weak_from_this(), [this] { Tick(); }); _route_poker->start(); is_running.store(true); _started_at = now(); + if (is_service_node()) { // do service node testing if we are in service node whitelist mode @@ -1163,13 +1140,16 @@ namespace llarp { if (not SessionToRouterAllowed(router)) { - LogDebug( - router, - " is no longer a registered service node so we remove it from the testing list"); + log::debug( + logcat, + "{} is no longer a registered service node; dropping from test list", + router); router_testing.remove_node_from_failing(router); continue; } - LogDebug("Establishing session to ", router, " for SN testing"); + + log::debug(logcat, "Establishing session to {} for service node testing", router); + // try to make a session to this random router // this will do a dht lookup if needed _link_manager.connect_to(router); @@ -1346,7 +1326,7 @@ namespace llarp } bool - Router::InitServiceNode() + Router::init_service_node() { LogInfo("accepting transit traffic"); paths.AllowTransit(); diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 0abbf5dd28..9a29734775 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -147,6 +147,9 @@ namespace llarp void report_stats(); + void + save_rc(); + bool update_rc(); @@ -392,7 +395,7 @@ namespace llarp /// initialize us as a service node /// return true on success bool - InitServiceNode(); + init_service_node(); bool IsRunning() const; diff --git a/llarp/router_contact.cpp b/llarp/router_contact.cpp index f7c1211fda..68b8fcd90e 100644 --- a/llarp/router_contact.cpp +++ b/llarp/router_contact.cpp @@ -110,7 +110,7 @@ namespace llarp bool RouterContact::write(const fs::path& fname) const { - auto bte = bt_encode(); + auto bte = view(); try { @@ -124,26 +124,6 @@ namespace llarp return true; } - // std::string - // RouterContact::bencode_signed_section() const - // { - // oxenc::bt_dict_producer btdp; - - // btdp.append("4", _addr.to_string()); - - // if (_addr6) - // btdp.append("6", _addr6->to_string()); - - // if (ACTIVE_NETID != llarp::LOKINET_DEFAULT_NETID) - // btdp.append("i", ACTIVE_NETID); - - // 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::extract_status() const { diff --git a/llarp/router_contact.hpp b/llarp/router_contact.hpp index 1d8f737b03..f863bbd673 100644 --- a/llarp/router_contact.hpp +++ b/llarp/router_contact.hpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -18,24 +17,6 @@ #include #include -// 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 { static auto logcat = log::Cat("RC"); @@ -44,25 +25,28 @@ namespace llarp static inline constexpr size_t NETID_SIZE{8}; + /// 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" + /// RouterContact struct RouterContact { static constexpr uint8_t RC_VERSION = 0; - /// Constructs an empty RC - // RouterContact() = default; - - // RouterContact(std::string) - // { - // log::error(logcat, "ERROR: SUPPLANT THIS CONSTRUCTOR"); - // } - - // RouterContact(std::string buf); - - /// 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; - /// Unit tests disable this to allow private IP ranges in RCs, which normally get rejected. static inline bool BLOCK_BOGONS = true; @@ -85,6 +69,12 @@ namespace llarp /// changes i.e. just to push out a new confirmation of the details). static constexpr auto REPUBLISH = STALE / 2 - 5min; + ustring_view + view() const + { + return _payload; + } + /// Getters for private attributes const oxen::quic::Address& addr() const @@ -158,29 +148,6 @@ namespace llarp bool write(const fs::path& fname) 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" - virtual ustring_view - bt_encode() const - { - log::warning(logcat, "ERROR: SUPPLANT THIS METHOD"); - return {}; - } - bool operator==(const RouterContact& other) const { @@ -251,16 +218,20 @@ namespace llarp /// parameters and outputs a bt-serialized string struct LocalRC final : public RouterContact { + static LocalRC + make(const SecretKey secret, oxen::quic::Address local); + private: ustring _signature; - const SecretKey _secret_key; + SecretKey _secret_key; - // TODO: fix these parameters void bt_sign(oxenc::bt_dict_producer& btdp); void - bt_encode(oxenc::bt_dict_producer& btdp) const; + bt_encode(oxenc::bt_dict_producer& btdp); + + LocalRC(const SecretKey secret, oxen::quic::Address local); public: LocalRC() = default; @@ -270,15 +241,6 @@ namespace llarp void resign(); - ustring_view - bt_encode() const override; - - ustring_view - view() const - { - return _payload; - } - void clear() override { @@ -347,7 +309,6 @@ namespace llarp struct RemoteRC final : public RouterContact { private: - // TODO: fix these parameters void bt_verify(oxenc::bt_dict_consumer& data, bool reject_expired = false) const; @@ -362,12 +323,6 @@ namespace llarp explicit RemoteRC(oxenc::bt_dict_consumer btdc); ~RemoteRC() = default; - ustring_view - bt_encode() const override - { - return _payload; - } - std::string_view view() const { diff --git a/llarp/router_contact_local.cpp b/llarp/router_contact_local.cpp index 71537692d6..9b82551ccc 100644 --- a/llarp/router_contact_local.cpp +++ b/llarp/router_contact_local.cpp @@ -11,6 +11,21 @@ namespace llarp { + LocalRC + LocalRC::make(const SecretKey secret, oxen::quic::Address local) + { + return *new LocalRC{secret, local}; + } + + LocalRC::LocalRC(const SecretKey secret, oxen::quic::Address local) + : _secret_key{std::move(secret)} + { + _router_id = llarp::seckey_to_pubkey(_secret_key); + _addr = std::move(local); + _addr6.emplace(&_addr.in6()); + resign(); + } + LocalRC::LocalRC(std::string payload, const SecretKey sk) : _secret_key{std::move(sk)} { _router_id = llarp::seckey_to_pubkey(_secret_key); @@ -66,16 +81,8 @@ namespace llarp _payload = btdp.view(); } - ustring_view - LocalRC::bt_encode() const - { - oxenc::bt_dict_producer btdp; - bt_encode(btdp); - return btdp.view(); - } - void - LocalRC::bt_encode(oxenc::bt_dict_producer& btdp) const + LocalRC::bt_encode(oxenc::bt_dict_producer& btdp) { btdp.append("", RC_VERSION); @@ -117,14 +124,7 @@ namespace llarp btdp.append( "v", std::string_view{reinterpret_cast(llarp::LOKINET_VERSION.data()), 3}); - btdp.append_signature("~", [this](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; - }); + bt_sign(btdp); } void diff --git a/llarp/service/identity.cpp b/llarp/service/identity.cpp index 05c6763f75..892faa90b7 100644 --- a/llarp/service/identity.cpp +++ b/llarp/service/identity.cpp @@ -4,16 +4,32 @@ namespace llarp::service { - bool - Identity::BEncode(llarp_buffer_t* buf) const + std::string + Identity::bt_encode() const { - if (!bencode_start_dict(buf)) - return false; - if (!BEncodeWriteDictEntry("s", signkey, buf)) - return false; - if (!BEncodeWriteDictInt("v", version, buf)) - return false; - return bencode_end(buf); + oxenc::bt_dict_producer btdp; + + btdp.append("s", signkey.ToView()); + btdp.append("v", version); + + return std::move(btdp).str(); + } + + void + Identity::bt_decode(std::string buf) + { + try + { + oxenc::bt_dict_consumer btdc{buf}; + + signkey.from_string(btdc.require("s")); + version = btdc.require("v"); + } + catch (...) + { + log::warning(logcat, "Identity failed to parse bt-encoded contents!"); + throw; + } } bool @@ -74,7 +90,7 @@ namespace llarp::service // make sure we are empty Clear(); - std::array tmp; + std::string buf; // this can throw bool exists = fs::exists(fname); @@ -88,16 +104,15 @@ namespace llarp::service // check for file if (!exists) { - llarp_buffer_t buf{tmp}; // regen and encode RegenerateKeys(); - if (!BEncode(&buf)) - throw std::length_error("failed to encode new identity"); - const auto sz = buf.cur - buf.base; + + buf = bt_encode(); + // write try { - util::buffer_to_file(fname, tmp.data(), sz); + util::buffer_to_file(fname, buf.data(), buf.size()); } catch (const std::exception& e) { @@ -114,18 +129,15 @@ namespace llarp::service // read file try { - util::file_to_buffer(fname, tmp.data(), tmp.size()); + util::file_to_buffer(fname, buf.data(), buf.size()); } catch (const std::length_error&) { throw std::length_error{"service identity too big"}; } + // (don't catch io error exceptions) - { - llarp_buffer_t buf{tmp}; - if (!bencode_decode_dict(*this, &buf)) - throw std::length_error{"could not decode service identity"}; - } + bt_decode(buf); // ensure that the encryption key is set if (enckey.IsZero()) diff --git a/llarp/service/identity.hpp b/llarp/service/identity.hpp index 70b1919f3f..3a8a347492 100644 --- a/llarp/service/identity.hpp +++ b/llarp/service/identity.hpp @@ -31,8 +31,10 @@ namespace llarp::service void RegenerateKeys(); - bool - BEncode(llarp_buffer_t* buf) const; + std::string + bt_encode() const; + + void bt_decode(std::string); /// @param needBackup determines whether existing keys will be cycled void diff --git a/llarp/service/protocol.hpp b/llarp/service/protocol.hpp index d3d656e2a7..67e8ef91f1 100644 --- a/llarp/service/protocol.hpp +++ b/llarp/service/protocol.hpp @@ -130,12 +130,6 @@ namespace llarp std::string bt_encode() const; - bool - BDecode(llarp_buffer_t* buf) - { - return bencode_decode_dict(*this, buf); - } - void clear() { diff --git a/llarp/util/bencode.hpp b/llarp/util/bencode.hpp index be616717ee..16f08b9a86 100644 --- a/llarp/util/bencode.hpp +++ b/llarp/util/bencode.hpp @@ -17,16 +17,17 @@ namespace llarp { static auto ben_cat = log::Cat("stupid.bencode"); + template + T + decode_key(oxenc::bt_dict_consumer& btdp, const char* key) + { + return btdp.require(key); + } + template bool BEncodeReadList(List_t& result, llarp_buffer_t* buf); - inline bool - BEncodeWriteDictMsgType(llarp_buffer_t* buf, const char* k, const char* t) - { - return bencode_write_bytestring(buf, k, 1) && bencode_write_bytestring(buf, t, 1); - } - template bool BEncodeWriteDictString(const char* k, const Obj_t& str, llarp_buffer_t* buf) @@ -320,23 +321,6 @@ namespace llarp buffer); } - /// write an iterable container as a list - template - bool - BEncodeWriteSet(const Set_t& set, llarp_buffer_t* buffer) - { - if (not bencode_start_list(buffer)) - return false; - - for (const auto& item : set) - { - if (not item.bt_encode(buffer)) - return false; - } - - return bencode_end(buffer); - } - template bool BEncodeWriteDictList(const char* k, List_t& list, llarp_buffer_t* buf) From c149651d64b448ec675edbe248b9fd2e64d02426 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Fri, 3 Nov 2023 06:40:14 -0700 Subject: [PATCH 094/312] A soothing re-nomenclatura --- daemon/lokinet.cpp | 8 +- llarp/config/config.cpp | 522 ++++++++++++++++--------------- llarp/config/config.hpp | 199 ++++++------ llarp/config/definition.cpp | 197 ++++++------ llarp/config/definition.hpp | 232 +++++++------- llarp/config/ini.cpp | 105 ++++--- llarp/config/ini.hpp | 42 +-- llarp/config/key_manager.cpp | 12 +- llarp/context.cpp | 2 +- llarp/dns/server.cpp | 14 +- llarp/handlers/exit.cpp | 6 +- llarp/handlers/tun.cpp | 50 +-- llarp/path/pathbuilder.cpp | 2 +- llarp/router/route_poker.cpp | 4 +- llarp/router/router.cpp | 55 ++-- llarp/rpc/endpoint_rpc.cpp | 10 +- llarp/rpc/endpoint_rpc.hpp | 4 +- llarp/rpc/rpc_server.cpp | 8 +- llarp/service/auth.cpp | 84 ++--- llarp/service/auth.hpp | 46 +-- llarp/service/context.cpp | 2 +- llarp/service/endpoint.cpp | 22 +- llarp/service/endpoint_state.cpp | 10 +- 23 files changed, 823 insertions(+), 813 deletions(-) diff --git a/daemon/lokinet.cpp b/daemon/lokinet.cpp index 67ac4a6711..89b3d155ae 100644 --- a/daemon/lokinet.cpp +++ b/daemon/lokinet.cpp @@ -450,7 +450,7 @@ namespace { try { - llarp::ensureConfig(basedir, *configFile, options.overwrite, opts.isSNode); + llarp::ensure_config(basedir, *configFile, options.overwrite, opts.isSNode); } catch (std::exception& ex) { @@ -479,7 +479,7 @@ namespace { try { - llarp::ensureConfig( + llarp::ensure_config( llarp::GetDefaultDataDir(), llarp::GetDefaultConfigPath(), options.overwrite, @@ -562,7 +562,7 @@ namespace { conf = std::make_shared(llarp::GetDefaultDataDir()); } - if (not conf->Load(confFile, opts.isSNode)) + if (not conf->load(confFile, opts.isSNode)) { llarp::LogError("failed to parse configuration"); exit_code.set_value(1); @@ -570,7 +570,7 @@ namespace } // change cwd to dataDir to support relative paths in config - fs::current_path(conf->router.m_dataDir); + fs::current_path(conf->router.data_dir); ctx = std::make_shared(); ctx->Configure(std::move(conf)); diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index c4d3035da5..a586ee6804 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -41,21 +41,21 @@ namespace llarp } // namespace void - RouterConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params) + RouterConfig::define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params) { constexpr Default DefaultJobQueueSize{1024 * 8}; constexpr Default DefaultWorkerThreads{0}; constexpr Default DefaultBlockBogons{true}; - conf.defineOption( + conf.define_option( "router", "job-queue-size", DefaultJobQueueSize, Hidden, [this](int arg) { if (arg < 1024) throw std::invalid_argument("job-queue-size must be 1024 or greater"); - m_JobQueueSize = arg; + job_que_size = arg; }); - conf.defineOption( + conf.define_option( "router", "netid", Default{llarp::LOKINET_DEFAULT_NETID}, @@ -68,12 +68,12 @@ namespace llarp throw std::invalid_argument{ fmt::format("netid is too long, max length is {}", NETID_SIZE)}; - m_netId = std::move(arg); + net_id = std::move(arg); }); int minConnections = - (params.isRelay ? DefaultMinConnectionsForRouter : DefaultMinConnectionsForClient); - conf.defineOption( + (params.is_relay ? DefaultMinConnectionsForRouter : DefaultMinConnectionsForClient); + conf.define_option( "router", "min-connections", Default{minConnections}, @@ -85,12 +85,12 @@ namespace llarp throw std::invalid_argument{ fmt::format("min-connections must be >= {}", minConnections)}; - m_minConnectedRouters = arg; + min_connected_routers = arg; }); int maxConnections = - (params.isRelay ? DefaultMaxConnectionsForRouter : DefaultMaxConnectionsForClient); - conf.defineOption( + (params.is_relay ? DefaultMaxConnectionsForRouter : DefaultMaxConnectionsForClient); + conf.define_option( "router", "max-connections", Default{maxConnections}, @@ -102,15 +102,15 @@ namespace llarp throw std::invalid_argument{ fmt::format("max-connections must be >= {}", maxConnections)}; - m_maxConnectedRouters = arg; + max_connected_routers = arg; }); - conf.defineOption("router", "nickname", Deprecated); + conf.define_option("router", "nickname", Deprecated); - conf.defineOption( + conf.define_option( "router", "data-dir", - Default{params.defaultDataDir}, + Default{params.default_data_dir}, Comment{ "Optional directory for containing lokinet runtime data. This includes generated", "private keys.", @@ -122,10 +122,10 @@ namespace llarp throw std::runtime_error{ fmt::format("Specified [router]:data-dir {} does not exist", arg)}; - m_dataDir = std::move(arg); + data_dir = std::move(arg); }); - conf.defineOption( + conf.define_option( "router", "public-ip", RelayOnly, @@ -145,16 +145,16 @@ namespace llarp throw std::invalid_argument{ fmt::format("{} is not a publicly routable ip address", addr)}; - PublicIP = addr; + public_ip = addr; }); - conf.defineOption("router", "public-address", Hidden, [](std::string) { + conf.define_option("router", "public-address", Hidden, [](std::string) { throw std::invalid_argument{ "[router]:public-address option no longer supported, use [router]:public-ip and " "[router]:public-port instead"}; }); - conf.defineOption( + conf.define_option( "router", "public-port", RelayOnly, @@ -166,10 +166,10 @@ namespace llarp [this](int arg) { if (arg <= 0 || arg > std::numeric_limits::max()) throw std::invalid_argument("public-port must be >= 0 and <= 65536"); - PublicPort = ToNet(huint16_t{static_cast(arg)}); + public_port = ToNet(huint16_t{static_cast(arg)}); }); - conf.defineOption( + conf.define_option( "router", "worker-threads", DefaultWorkerThreads, @@ -183,56 +183,56 @@ namespace llarp if (arg < 0) throw std::invalid_argument("worker-threads must be >= 0"); - m_workerThreads = arg; + worker_threads = arg; }); // Hidden option because this isn't something that should ever be turned off occasionally when // doing dev/testing work. - conf.defineOption( - "router", "block-bogons", DefaultBlockBogons, Hidden, AssignmentAcceptor(m_blockBogons)); + conf.define_option( + "router", "block-bogons", DefaultBlockBogons, Hidden, assignment_acceptor(block_bogons)); constexpr auto relative_to_datadir = "An absolute path is used as-is, otherwise relative to 'data-dir'."; - conf.defineOption( + conf.define_option( "router", "contact-file", RelayOnly, Default{llarp::our_rc_filename}, - AssignmentAcceptor(m_routerContactFile), + assignment_acceptor(rc_file), Comment{ "Filename in which to store the router contact file", relative_to_datadir, }); - conf.defineOption( + conf.define_option( "router", "encryption-privkey", RelayOnly, Default{llarp::our_enc_key_filename}, - AssignmentAcceptor(m_encryptionKeyFile), + assignment_acceptor(enckey_file), Comment{ "Filename in which to store the encryption private key", relative_to_datadir, }); - conf.defineOption( + conf.define_option( "router", "ident-privkey", RelayOnly, Default{llarp::our_identity_filename}, - AssignmentAcceptor(m_identityKeyFile), + assignment_acceptor(idkey_file), Comment{ "Filename in which to store the identity private key", relative_to_datadir, }); - conf.defineOption( + conf.define_option( "router", "transport-privkey", RelayOnly, Default{llarp::our_transport_key_filename}, - AssignmentAcceptor(m_transportKeyFile), + assignment_acceptor(transkey_file), Comment{ "Filename in which to store the transport private key.", relative_to_datadir, @@ -241,18 +241,18 @@ namespace llarp // Deprecated options: // these weren't even ever used! - conf.defineOption("router", "max-routers", Deprecated); - conf.defineOption("router", "min-routers", Deprecated); + conf.define_option("router", "max-routers", Deprecated); + conf.define_option("router", "min-routers", Deprecated); // TODO: this may have been a synonym for [router]worker-threads - conf.defineOption("router", "threads", Deprecated); - conf.defineOption("router", "net-threads", Deprecated); + conf.define_option("router", "threads", Deprecated); + conf.define_option("router", "net-threads", Deprecated); - m_isRelay = params.isRelay; + is_relay = params.is_relay; } void - NetworkConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params) + NetworkConfig::define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params) { (void)params; @@ -263,26 +263,26 @@ namespace llarp static constexpr Default PathsDefault{6}; static constexpr Default IP6RangeDefault{"fd00::"}; - conf.defineOption( - "network", "type", Default{"tun"}, Hidden, AssignmentAcceptor(m_endpointType)); + conf.define_option( + "network", "type", Default{"tun"}, Hidden, assignment_acceptor(endpoint_type)); - conf.defineOption( + conf.define_option( "network", "save-profiles", SaveProfilesDefault, Hidden, - AssignmentAcceptor(m_saveProfiles)); + assignment_acceptor(save_profiles)); - conf.defineOption( + conf.define_option( "network", "profiling", ProfilingValueDefault, Hidden, - AssignmentAcceptor(m_enableProfiling)); + assignment_acceptor(enable_profiling)); - conf.defineOption("network", "profiles", Deprecated); + conf.define_option("network", "profiles", Deprecated); - conf.defineOption( + conf.define_option( "network", "strict-connect", ClientOnly, @@ -291,7 +291,7 @@ namespace llarp RouterID router; if (not router.FromString(value)) throw std::invalid_argument{"bad snode value: " + value}; - if (not m_strictConnect.insert(router).second) + if (not strict_connect.insert(router).second) throw std::invalid_argument{"duplicate strict connect snode: " + value}; }, Comment{ @@ -300,17 +300,17 @@ namespace llarp "first hop). This REQUIRES two or more nodes to be specified.", }); - conf.defineOption( + conf.define_option( "network", "keyfile", ClientOnly, - AssignmentAcceptor(m_keyfile), + assignment_acceptor(keyfile), Comment{ "The private key to persist address with. If not specified the address will be", "ephemeral.", }); - conf.defineOption( + conf.define_option( "network", "auth", ClientOnly, @@ -321,21 +321,21 @@ namespace llarp [this](std::string arg) { if (arg.empty()) return; - m_AuthType = service::ParseAuthType(arg); + auth_type = service::parse_auth_type(arg); }); - conf.defineOption( + conf.define_option( "network", "auth-lmq", ClientOnly, - AssignmentAcceptor(m_AuthUrl), + assignment_acceptor(auth_url), Comment{ "lmq endpoint to talk to for authenticating new sessions", "ipc:///var/lib/lokinet/auth.socket", "tcp://127.0.0.1:5555", }); - conf.defineOption( + conf.define_option( "network", "auth-lmq-method", ClientOnly, @@ -347,10 +347,10 @@ namespace llarp [this](std::string arg) { if (arg.empty()) return; - m_AuthMethod = std::move(arg); + auth_method = std::move(arg); }); - conf.defineOption( + conf.define_option( "network", "auth-whitelist", ClientOnly, @@ -362,10 +362,10 @@ namespace llarp service::Address addr; if (not addr.FromString(arg)) throw std::invalid_argument{fmt::format("bad loki address: {}", arg)}; - m_AuthWhitelist.emplace(std::move(addr)); + auth_whitelist.emplace(std::move(addr)); }); - conf.defineOption( + conf.define_option( "network", "auth-file", ClientOnly, @@ -378,9 +378,9 @@ namespace llarp if (not fs::exists(arg)) throw std::invalid_argument{ fmt::format("cannot load auth file {}: file does not exist", arg)}; - m_AuthFiles.emplace(std::move(arg)); + auth_files.emplace(std::move(arg)); }); - conf.defineOption( + conf.define_option( "network", "auth-file-type", ClientOnly, @@ -388,9 +388,11 @@ namespace llarp "How to interpret the contents of an auth file.", "Possible values: hashes, plaintext", }, - [this](std::string arg) { m_AuthFileType = service::ParseAuthFileType(std::move(arg)); }); + [this](std::string arg) { + auth_file_type = service::parse_auth_file_type(std::move(arg)); + }); - conf.defineOption( + conf.define_option( "network", "auth-static", ClientOnly, @@ -399,19 +401,19 @@ namespace llarp "Manually add a static auth code to accept for endpoint auth", "Can be provided multiple times", }, - [this](std::string arg) { m_AuthStaticTokens.emplace(std::move(arg)); }); + [this](std::string arg) { auth_static_tokens.emplace(std::move(arg)); }); - conf.defineOption( + conf.define_option( "network", "reachable", ClientOnly, ReachableDefault, - AssignmentAcceptor(m_reachable), + assignment_acceptor(is_reachable), Comment{ "Determines whether we will pubish our snapp's introset to the DHT.", }); - conf.defineOption( + conf.define_option( "network", "hops", HopsDefault, @@ -421,10 +423,10 @@ namespace llarp [this](int arg) { if (arg < 1 or arg > 8) throw std::invalid_argument("[endpoint]:hops must be >= 1 and <= 8"); - m_Hops = arg; + hops = arg; }); - conf.defineOption( + conf.define_option( "network", "paths", ClientOnly, @@ -435,21 +437,21 @@ namespace llarp [this](int arg) { if (arg < 3 or arg > 8) throw std::invalid_argument("[endpoint]:paths must be >= 3 and <= 8"); - m_Paths = arg; + paths = arg; }); - conf.defineOption( + conf.define_option( "network", "exit", ClientOnly, Default{false}, - AssignmentAcceptor(m_AllowExit), + assignment_acceptor(allow_exit), Comment{ "Whether or not we should act as an exit node. Beware that this increases demand", "on the server and may pose liability concerns. Enable at your own risk.", }); - conf.defineOption( + conf.define_option( "network", "owned-range", MultiValue, @@ -461,10 +463,10 @@ namespace llarp IPRange range; if (not range.FromString(arg)) throw std::invalid_argument{"bad ip range: '" + arg + "'"}; - m_OwnedRanges.insert(range); + owned_ranges.insert(range); }); - conf.defineOption( + conf.define_option( "network", "traffic-whitelist", MultiValue, @@ -482,14 +484,14 @@ namespace llarp "would allow TCP traffic on the standard smtp port (21).", }, [this](std::string arg) { - if (not m_TrafficPolicy) - m_TrafficPolicy = net::TrafficPolicy{}; + if (not traffic_policy) + traffic_policy = net::TrafficPolicy{}; // this will throw on error - m_TrafficPolicy->protocols.emplace(arg); + traffic_policy->protocols.emplace(arg); }); - conf.defineOption( + conf.define_option( "network", "exit-node", ClientOnly, @@ -524,7 +526,7 @@ namespace llarp if (service::is_valid_name(arg)) { - m_LNSExitMap.Insert(range, arg); + ons_exit_map.Insert(range, arg); return; } @@ -532,10 +534,10 @@ namespace llarp { throw std::invalid_argument{fmt::format("[network]:exit-node bad address: {}", arg)}; } - m_ExitMap.Insert(range, exit); + exit_map.Insert(range, exit); }); - conf.defineOption( + conf.define_option( "network", "exit-auth", ClientOnly, @@ -564,7 +566,7 @@ namespace llarp if (service::is_valid_name(exit_str)) { - m_LNSExitAuths.emplace(exit_str, auth); + ons_exit_auths.emplace(exit_str, auth); return; } @@ -572,10 +574,10 @@ namespace llarp { throw std::invalid_argument("[network]:exit-auth invalid exit address"); } - m_ExitAuths.emplace(exit, auth); + exit_auths.emplace(exit, auth); }); - conf.defineOption( + conf.define_option( "network", "auto-routing", ClientOnly, @@ -586,9 +588,9 @@ namespace llarp "operating system routes to route public internet traffic through the exit node.", "This is enabled by default, but can be disabled if advanced/manual exit routing", "configuration is desired."}, - AssignmentAcceptor(m_EnableRoutePoker)); + assignment_acceptor(enable_route_poker)); - conf.defineOption( + conf.define_option( "network", "blackhole-routes", ClientOnly, @@ -597,18 +599,18 @@ namespace llarp "Enable / disable route configuration blackholes.", "When enabled lokinet will drop IPv4 and IPv6 traffic (when in exit mode) that is not", "handled in the exit configuration. Enabled by default."}, - AssignmentAcceptor(m_BlackholeRoutes)); + assignment_acceptor(blackhole_routes)); - conf.defineOption( + conf.define_option( "network", "ifname", Comment{ "Interface name for lokinet traffic. If unset lokinet will look for a free name", "matching 'lokitunN', starting at N=0 (e.g. lokitun0, lokitun1, ...).", }, - AssignmentAcceptor(m_ifname)); + assignment_acceptor(if_name)); - conf.defineOption( + conf.define_option( "network", "ifaddr", Comment{ @@ -617,13 +619,13 @@ namespace llarp "lokinet will attempt to find an unused private range.", }, [this](std::string arg) { - if (not m_ifaddr.FromString(arg)) + if (not if_addr.FromString(arg)) { throw std::invalid_argument{fmt::format("[network]:ifaddr invalid value: '{}'", arg)}; } }); - conf.defineOption( + conf.define_option( "network", "ip6-range", ClientOnly, @@ -641,17 +643,17 @@ namespace llarp LogError( "!!! Disabling ipv6 tunneling when you have ipv6 routes WILL lead to " "de-anonymization as lokinet will no longer carry your ipv6 traffic !!!"); - m_baseV6Address = std::nullopt; + base_ipv6_addr = std::nullopt; return; } - m_baseV6Address = huint128_t{}; - if (not m_baseV6Address->FromString(arg)) + base_ipv6_addr = huint128_t{}; + if (not base_ipv6_addr->FromString(arg)) throw std::invalid_argument{ fmt::format("[network]:ip6-range invalid value: '{}'", arg)}; }); // TODO: could be useful for snodes in the future, but currently only implemented for clients: - conf.defineOption( + conf.define_option( "network", "mapaddr", ClientOnly, @@ -688,15 +690,15 @@ namespace llarp throw std::invalid_argument{ fmt::format("[endpoint]:mapaddr invalid addresss: {}", addrstr)}; } - if (m_mapAddrs.find(ip) != m_mapAddrs.end()) + if (map_addrs.find(ip) != map_addrs.end()) { throw std::invalid_argument{ fmt::format("[endpoint]:mapaddr ip already mapped: {}", ipstr)}; } - m_mapAddrs[ip] = addr; + map_addrs[ip] = addr; }); - conf.defineOption( + conf.define_option( "network", "blacklist-snode", ClientOnly, @@ -710,13 +712,13 @@ namespace llarp if (not id.FromString(arg)) throw std::invalid_argument{fmt::format("Invalid RouterID: {}", arg)}; - auto itr = m_snodeBlacklist.emplace(std::move(id)); + auto itr = snode_blacklist.emplace(std::move(id)); if (not itr.second) throw std::invalid_argument{fmt::format("Duplicate blacklist-snode: {}", arg)}; }); // TODO: support SRV records for routers, but for now client only - conf.defineOption( + conf.define_option( "network", "srv", ClientOnly, @@ -735,10 +737,10 @@ namespace llarp if (not newSRV.fromString(arg)) throw std::invalid_argument{fmt::format("Invalid SRV Record string: {}", arg)}; - m_SRVRecords.push_back(std::move(newSRV)); + srv_records.push_back(std::move(newSRV)); }); - conf.defineOption( + conf.define_option( "network", "path-alignment-timeout", ClientOnly, @@ -750,14 +752,14 @@ namespace llarp if (val <= 0) throw std::invalid_argument{ "invalid path alignment timeout: " + std::to_string(val) + " <= 0"}; - m_PathAlignmentTimeout = std::chrono::seconds{val}; + path_alignment_timeout = std::chrono::seconds{val}; }); - conf.defineOption( + conf.define_option( "network", "persist-addrmap-file", ClientOnly, - Default{fs::path{params.defaultDataDir / "addrmap.dat"}}, + Default{fs::path{params.default_data_dir / "addrmap.dat"}}, Comment{ "If given this specifies a file in which to record mapped local tunnel addresses so", "the same local address will be used for the same lokinet address on reboot. If this", @@ -767,15 +769,15 @@ namespace llarp [this](fs::path arg) { if (arg.empty()) throw std::invalid_argument("persist-addrmap-file cannot be empty"); - m_AddrMapPersistFile = arg; + addr_map_persist_file = arg; }); // Deprecated options: - conf.defineOption("network", "enabled", Deprecated); + conf.define_option("network", "enabled", Deprecated); } void - DnsConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params) + DnsConfig::define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params) { (void)params; @@ -797,9 +799,9 @@ namespace llarp // Default, but if we get any upstream (including upstream=, i.e. empty string) we clear it constexpr Default DefaultUpstreamDNS{"9.9.9.10:53"}; - m_upstreamDNS.emplace_back(DefaultUpstreamDNS.val); + upstream_dns.emplace_back(DefaultUpstreamDNS.val); - conf.defineOption( + conf.define_option( "dns", "upstream", MultiValue, @@ -810,18 +812,18 @@ namespace llarp [=, first = true](std::string arg) mutable { if (first) { - m_upstreamDNS.clear(); + upstream_dns.clear(); first = false; } if (not arg.empty()) { - auto& entry = m_upstreamDNS.emplace_back(std::move(arg)); + auto& entry = upstream_dns.emplace_back(std::move(arg)); if (not entry.getPort()) entry.setPort(53); } }); - conf.defineOption( + conf.define_option( "dns", "l3-intercept", Default{ @@ -829,9 +831,9 @@ namespace llarp or (platform::is_macos and not platform::is_apple_sysex)}, Comment{"Intercept all dns traffic (udp/53) going into our lokinet network interface " "instead of binding a local udp socket"}, - AssignmentAcceptor(m_raw_dns)); + assignment_acceptor(raw)); - conf.defineOption( + conf.define_option( "dns", "query-bind", #if defined(_WIN32) @@ -842,9 +844,9 @@ namespace llarp Comment{ "Address to bind to for sending upstream DNS requests.", }, - [this](std::string arg) { m_QueryBind = SockAddr{arg}; }); + [this](std::string arg) { query_bind = SockAddr{arg}; }); - conf.defineOption( + conf.define_option( "dns", "bind", DefaultDNSBind, @@ -858,10 +860,10 @@ namespace llarp // explicit :0 allowed if (not addr.getPort() and not ends_with(arg, ":0")) addr.setPort(53); - m_bind.emplace_back(addr); + bind_addr.emplace_back(addr); }); - conf.defineOption( + conf.define_option( "dns", "add-hosts", ClientOnly, @@ -872,11 +874,11 @@ namespace llarp if (not fs::exists(path)) throw std::invalid_argument{ fmt::format("cannot add hosts file {} as it does not exist", path)}; - m_hostfiles.emplace_back(std::move(path)); + hostfiles.emplace_back(std::move(path)); }); // Ignored option (used by the systemd service file to disable resolvconf configuration). - conf.defineOption( + conf.define_option( "dns", "no-resolvconf", ClientOnly, @@ -887,15 +889,15 @@ namespace llarp }); // forward the rest to libunbound - conf.addUndeclaredHandler("dns", [this](auto, std::string_view key, std::string_view val) { - m_ExtraOpts.emplace(key, val); + conf.add_undeclared_handler("dns", [this](auto, std::string_view key, std::string_view val) { + extra_opts.emplace(key, val); }); } void - LinksConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params) + LinksConfig::define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params) { - conf.addSectionComments( + conf.add_section_comments( "bind", { "This section allows specifying the IPs that lokinet uses for incoming and outgoing", @@ -910,7 +912,7 @@ namespace llarp static constexpr Default DefaultInboundPort{uint16_t{1090}}; static constexpr Default DefaultOutboundPort{uint16_t{0}}; - conf.defineOption( + conf.define_option( "bind", "public-ip", RelayOnly, @@ -921,9 +923,9 @@ namespace llarp }, [this](std::string_view arg) { SockAddr pubaddr{arg}; - PublicAddress = pubaddr.getIP(); + public_addr = pubaddr.getIP(); }); - conf.defineOption( + conf.define_option( "bind", "public-port", RelayOnly, @@ -932,7 +934,7 @@ namespace llarp "This is typically required only when incoming= is used to listen on an internal", "private range IP address/port that received traffic forwarded from the public IP.", }, - [this](uint16_t arg) { PublicPort = net::port_t::from_host(arg); }); + [this](uint16_t arg) { public_port = net::port_t::from_host(arg); }); auto parse_addr_for_link = [net_ptr]( const std::string& arg, net::port_t default_port, bool inbound) { @@ -970,7 +972,7 @@ namespace llarp return addr; }; - conf.defineOption( + conf.define_option( "bind", "inbound", RelayOnly, @@ -994,14 +996,14 @@ namespace llarp [this, parse_addr_for_link](const std::string& arg) { auto default_port = net::port_t::from_host(DefaultInboundPort.val); if (auto addr = parse_addr_for_link(arg, default_port, /*inbound=*/true)) - InboundListenAddrs.emplace_back(std::move(*addr)); + inbound_listen_addrs.emplace_back(std::move(*addr)); }); - conf.defineOption( + conf.define_option( "bind", "outbound", MultiValue, - params.isRelay ? Comment{ + params.is_relay ? Comment{ "IP and/or port to use for outbound socket connections to other lokinet routers.", "", "If no outbound bind IP is configured, or the 0.0.0.0 wildcard IP is given, then", @@ -1038,10 +1040,10 @@ namespace llarp auto addr = parse_addr_for_link(arg, default_port, /*inbound=*/false); if (not addr) addr = net_ptr->WildcardWithPort(default_port); - OutboundLinks.emplace_back(std::move(*addr)); + outbound_links.emplace_back(std::move(*addr)); }); - conf.addUndeclaredHandler( + conf.add_undeclared_handler( "bind", [this, net_ptr](std::string_view, std::string_view key, std::string_view val) { LogWarn( "using the [bind] section with *=/IP=/INTERFACE= is deprecated; use the inbound= " @@ -1059,7 +1061,7 @@ namespace llarp } else throw std::invalid_argument{fmt::format("invalid port value: '{}'", val)}; - OutboundLinks.emplace_back(std::move(*addr)); + outbound_links.emplace_back(std::move(*addr)); return; } // try as interface name first @@ -1082,16 +1084,16 @@ namespace llarp else throw std::invalid_argument{fmt::format("invalid port value: '{}'", val)}; - InboundListenAddrs.emplace_back(std::move(*addr)); + inbound_listen_addrs.emplace_back(std::move(*addr)); }); } void - ConnectConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params) + ConnectConfig::define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params) { (void)params; - conf.addUndeclaredHandler( + conf.add_undeclared_handler( "connect", [this](std::string_view section, std::string_view name, std::string_view value) { fs::path file{value.begin(), value.end()}; if (not fs::exists(file)) @@ -1107,7 +1109,7 @@ namespace llarp } void - ApiConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params) + ApiConfig::define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params) { constexpr std::array DefaultRPCBind{ Default{"tcp://127.0.0.1:1190"}, @@ -1116,16 +1118,16 @@ namespace llarp #endif }; - conf.defineOption( + conf.define_option( "api", "enabled", - Default{not params.isRelay}, - AssignmentAcceptor(m_enableRPCServer), + Default{not params.is_relay}, + assignment_acceptor(enable_rpc_server), Comment{ "Determines whether or not the LMQ JSON API is enabled. Defaults ", }); - conf.defineOption( + conf.define_option( "api", "bind", DefaultRPCBind, @@ -1133,34 +1135,34 @@ namespace llarp [this, first = true](std::string arg) mutable { if (first) { - m_rpcBindAddresses.clear(); + rpc_bind_addrs.clear(); first = false; } if (arg.find("://") == std::string::npos) { arg = "tcp://" + arg; } - m_rpcBindAddresses.emplace_back(arg); + rpc_bind_addrs.emplace_back(arg); }, Comment{ "IP addresses and ports to bind to.", "Recommend localhost-only for security purposes.", }); - conf.defineOption("api", "authkey", Deprecated); + conf.define_option("api", "authkey", Deprecated); // TODO: this was from pre-refactor: // TODO: add pubkey to whitelist } void - LokidConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params) + LokidConfig::define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params) { (void)params; - conf.defineOption("lokid", "enabled", RelayOnly, Deprecated); + conf.define_option("lokid", "enabled", RelayOnly, Deprecated); - conf.defineOption("lokid", "jsonrpc", RelayOnly, [](std::string arg) { + conf.define_option("lokid", "jsonrpc", RelayOnly, [](std::string arg) { if (arg.empty()) return; throw std::invalid_argument( @@ -1169,7 +1171,7 @@ namespace llarp "rpc=ipc:///var/lib/oxen/oxend.sock or rpc=ipc:///home/snode/.oxen/oxend.sock"); }); - conf.defineOption( + conf.define_option( "lokid", "rpc", RelayOnly, @@ -1183,28 +1185,28 @@ namespace llarp "but can use (non-default) TCP if oxend is configured that way:", " rpc=tcp://127.0.0.1:5678", }, - [this](std::string arg) { lokidRPCAddr = oxenmq::address(arg); }); + [this](std::string arg) { rpc_addr = oxenmq::address(arg); }); // Deprecated options: - conf.defineOption("lokid", "username", Deprecated); - conf.defineOption("lokid", "password", Deprecated); - conf.defineOption("lokid", "service-node-seed", Deprecated); + conf.define_option("lokid", "username", Deprecated); + conf.define_option("lokid", "password", Deprecated); + conf.define_option("lokid", "service-node-seed", Deprecated); } void - BootstrapConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params) + BootstrapConfig::define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params) { (void)params; - conf.defineOption( + conf.define_option( "bootstrap", "seed-node", Default{false}, Comment{"Whether or not to run as a seed node. We will not have any bootstrap routers " "configured."}, - AssignmentAcceptor(seednode)); + assignment_acceptor(seednode)); - conf.defineOption( + conf.define_option( "bootstrap", "add-node", MultiValue, @@ -1226,7 +1228,7 @@ namespace llarp } void - LoggingConfig::defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params) + LoggingConfig::define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params) { (void)params; @@ -1234,13 +1236,13 @@ namespace llarp platform::is_android or platform::is_apple ? "system" : "print"}; constexpr Default DefaultLogFile{""}; - const Default DefaultLogLevel{params.isRelay ? "warn" : "info"}; + const Default DefaultLogLevel{params.is_relay ? "warn" : "info"}; - conf.defineOption( + conf.define_option( "logging", "type", DefaultLogType, - [this](std::string arg) { m_logType = log::type_from_string(arg); }, + [this](std::string arg) { type = log::type_from_string(arg); }, Comment{ "Log type (format). Valid options are:", " print - print logs to standard output", @@ -1248,11 +1250,11 @@ namespace llarp " file - plaintext formatting to a file", }); - conf.defineOption( + conf.define_option( "logging", "level", DefaultLogLevel, - [this](std::string arg) { m_logLevel = log::level_from_string(arg); }, + [this](std::string arg) { level = log::level_from_string(arg); }, Comment{ "Minimum log level to print. Logging below this level will be ignored.", "Valid log levels, in ascending order, are:", @@ -1265,24 +1267,24 @@ namespace llarp " none", }); - conf.defineOption( + conf.define_option( "logging", "file", DefaultLogFile, - AssignmentAcceptor(m_logFile), + assignment_acceptor(file), Comment{ "When using type=file this is the output filename.", }); } void - PeerSelectionConfig::defineConfigOptions( + PeerSelectionConfig::define_config_options( ConfigDefinition& conf, const ConfigGenParameters& params) { (void)params; constexpr Default DefaultUniqueCIDR{32}; - conf.defineOption( + conf.define_option( "paths", "unique-range-size", DefaultUniqueCIDR, @@ -1290,13 +1292,13 @@ namespace llarp [=](int arg) { if (arg == 0) { - m_UniqueHopsNetmaskSize = arg; + unique_hop_netmask = arg; } else if (arg > 32 or arg < 4) { throw std::invalid_argument{"[paths]:unique-range-size must be between 4 and 32"}; } - m_UniqueHopsNetmaskSize = arg; + unique_hop_netmask = arg; }, Comment{ "Netmask for router path selection; each router must be from a distinct IPv4 subnet", @@ -1322,11 +1324,11 @@ namespace llarp } bool - PeerSelectionConfig::Acceptable(const std::set& rcs) const + PeerSelectionConfig::check_rcs(const std::set& rcs) const { - if (m_UniqueHopsNetmaskSize == 0) + if (unique_hop_netmask == 0) return true; - const auto netmask = netmask_ipv6_bits(96 + m_UniqueHopsNetmaskSize); + const auto netmask = netmask_ipv6_bits(96 + unique_hop_netmask); std::set seenRanges; for (const auto& hop : rcs) { @@ -1340,50 +1342,50 @@ namespace llarp } std::unique_ptr - Config::MakeGenParams() const + Config::make_gen_params() const { return std::make_unique(); } Config::Config(std::optional datadir) - : m_DataDir{datadir ? std::move(*datadir) : fs::current_path()} + : data_dir{datadir ? std::move(*datadir) : fs::current_path()} {} constexpr auto GetOverridesDir = [](auto datadir) -> fs::path { return datadir / "conf.d"; }; void - Config::Save() + Config::save() { - const auto overridesDir = GetOverridesDir(m_DataDir); + const auto overridesDir = GetOverridesDir(data_dir); if (not fs::exists(overridesDir)) fs::create_directory(overridesDir); - m_Parser.Save(); + parser.save(); } void - Config::Override(std::string section, std::string key, std::string value) + Config::override(std::string section, std::string key, std::string value) { - m_Parser.AddOverride(GetOverridesDir(m_DataDir) / "overrides.ini", section, key, value); + parser.add_override(GetOverridesDir(data_dir) / "overrides.ini", section, key, value); } void - Config::LoadOverrides(ConfigDefinition& conf) const + Config::load_overrides(ConfigDefinition& conf) const { ConfigParser parser; - const auto overridesDir = GetOverridesDir(m_DataDir); + const auto overridesDir = GetOverridesDir(data_dir); if (fs::exists(overridesDir)) { util::IterDir(overridesDir, [&](const fs::path& overrideFile) { if (overrideFile.extension() == ".ini") { ConfigParser parser; - if (not parser.LoadFile(overrideFile)) + if (not parser.load_file(overrideFile)) throw std::runtime_error{"cannot load '" + overrideFile.u8string() + "'"}; - parser.IterAll([&](std::string_view section, const SectionValues_t& values) { + parser.iter_all_sections([&](std::string_view section, const SectionValues& values) { for (const auto& pair : values) { - conf.addConfigValue(section, pair.first, pair.second); + conf.add_config_value(section, pair.first, pair.second); } }); } @@ -1393,44 +1395,44 @@ namespace llarp } void - Config::AddDefault(std::string section, std::string key, std::string val) + Config::add_default(std::string section, std::string key, std::string val) { - m_Additional.emplace_back(std::array{section, key, val}); + additional.emplace_back(std::array{section, key, val}); } bool - Config::LoadConfigData(std::string_view ini, std::optional filename, bool isRelay) + Config::load_config_data(std::string_view ini, std::optional filename, bool isRelay) { - auto params = MakeGenParams(); - params->isRelay = isRelay; - params->defaultDataDir = m_DataDir; + auto params = make_gen_params(); + params->is_relay = isRelay; + params->default_data_dir = data_dir; ConfigDefinition conf{isRelay}; - addBackwardsCompatibleConfigOptions(conf); - initializeConfig(conf, *params); + add_backcompat_opts(conf); + init_config(conf, *params); - for (const auto& item : m_Additional) + for (const auto& item : additional) { - conf.addConfigValue(item[0], item[1], item[2]); + conf.add_config_value(item[0], item[1], item[2]); } - m_Parser.Clear(); + parser.clear(); if (filename) - m_Parser.Filename(*filename); + parser.set_filename(*filename); else - m_Parser.Filename(fs::path{}); + parser.set_filename(fs::path{}); - if (not m_Parser.LoadFromStr(ini)) + if (not parser.load_from_str(ini)) return false; - m_Parser.IterAll([&](std::string_view section, const SectionValues_t& values) { + parser.iter_all_sections([&](std::string_view section, const SectionValues& values) { for (const auto& pair : values) { - conf.addConfigValue(section, pair.first, pair.second); + conf.add_config_value(section, pair.first, pair.second); } }); - LoadOverrides(conf); + load_overrides(conf); conf.process(); @@ -1438,7 +1440,7 @@ namespace llarp } bool - Config::Load(std::optional fname, bool isRelay) + Config::load(std::optional fname, bool isRelay) { std::string ini; if (fname) @@ -1452,52 +1454,52 @@ namespace llarp return false; } } - return LoadConfigData(ini, fname, isRelay); + return load_config_data(ini, fname, isRelay); } bool - Config::LoadString(std::string_view ini, bool isRelay) + Config::load_string(std::string_view ini, bool isRelay) { - return LoadConfigData(ini, std::nullopt, isRelay); + return load_config_data(ini, std::nullopt, isRelay); } bool - Config::LoadDefault(bool isRelay) + Config::load_default_config(bool isRelay) { - return LoadString("", isRelay); + return load_string("", isRelay); } void - Config::initializeConfig(ConfigDefinition& conf, const ConfigGenParameters& params) + Config::init_config(ConfigDefinition& conf, const ConfigGenParameters& params) { - router.defineConfigOptions(conf, params); - network.defineConfigOptions(conf, params); - paths.defineConfigOptions(conf, params); - connect.defineConfigOptions(conf, params); - dns.defineConfigOptions(conf, params); - links.defineConfigOptions(conf, params); - api.defineConfigOptions(conf, params); - lokid.defineConfigOptions(conf, params); - bootstrap.defineConfigOptions(conf, params); - logging.defineConfigOptions(conf, params); + router.define_config_options(conf, params); + network.define_config_options(conf, params); + paths.define_config_options(conf, params); + connect.define_config_options(conf, params); + dns.define_config_options(conf, params); + links.define_config_options(conf, params); + api.define_config_options(conf, params); + lokid.define_config_options(conf, params); + bootstrap.define_config_options(conf, params); + logging.define_config_options(conf, params); } void - Config::addBackwardsCompatibleConfigOptions(ConfigDefinition& conf) + Config::add_backcompat_opts(ConfigDefinition& conf) { // These config sections don't exist anymore: - conf.defineOption("system", "user", Deprecated); - conf.defineOption("system", "group", Deprecated); - conf.defineOption("system", "pidfile", Deprecated); + conf.define_option("system", "user", Deprecated); + conf.define_option("system", "group", Deprecated); + conf.define_option("system", "pidfile", Deprecated); - conf.defineOption("netdb", "dir", Deprecated); + conf.define_option("netdb", "dir", Deprecated); - conf.defineOption("metrics", "json-metrics-path", Deprecated); + conf.define_option("metrics", "json-metrics-path", Deprecated); } void - ensureConfig(fs::path dataDir, fs::path confFile, bool overwrite, bool asRouter) + ensure_config(fs::path dataDir, fs::path confFile, bool overwrite, bool asRouter) { // fail to overwrite if not instructed to do so if (fs::exists(confFile) && !overwrite) @@ -1523,9 +1525,9 @@ namespace llarp llarp::Config config{dataDir}; std::string confStr; if (asRouter) - confStr = config.generateBaseRouterConfig(); + confStr = config.generate_router_config_base(); else - confStr = config.generateBaseClientConfig(); + confStr = config.generate_client_config_base(); // open a filestream try @@ -1542,45 +1544,45 @@ namespace llarp } void - generateCommonConfigComments(ConfigDefinition& def) + generate_common_config_comments(ConfigDefinition& def) { // router - def.addSectionComments( + def.add_section_comments( "router", { "Configuration for routing activity.", }); // logging - def.addSectionComments( + def.add_section_comments( "logging", { "logging settings", }); // api - def.addSectionComments( + def.add_section_comments( "api", { "JSON API settings", }); // dns - def.addSectionComments( + def.add_section_comments( "dns", { "DNS configuration", }); // bootstrap - def.addSectionComments( + def.add_section_comments( "bootstrap", { "Configure nodes that will bootstrap us onto the network", }); // network - def.addSectionComments( + def.add_section_comments( "network", { "Network settings", @@ -1588,60 +1590,60 @@ namespace llarp } std::string - Config::generateBaseClientConfig() + Config::generate_client_config_base() { - auto params = MakeGenParams(); - params->isRelay = false; - params->defaultDataDir = m_DataDir; + auto params = make_gen_params(); + params->is_relay = false; + params->default_data_dir = data_dir; llarp::ConfigDefinition def{false}; - initializeConfig(def, *params); - generateCommonConfigComments(def); - def.addSectionComments( + init_config(def, *params); + generate_common_config_comments(def); + def.add_section_comments( "paths", { "path selection algorithm options", }); - def.addSectionComments( + def.add_section_comments( "network", { "Snapp settings", }); - return def.generateINIConfig(true); + return def.generate_ini_config(true); } std::string - Config::generateBaseRouterConfig() + Config::generate_router_config_base() { - auto params = MakeGenParams(); - params->isRelay = true; - params->defaultDataDir = m_DataDir; + auto params = make_gen_params(); + params->is_relay = true; + params->default_data_dir = data_dir; llarp::ConfigDefinition def{true}; - initializeConfig(def, *params); - generateCommonConfigComments(def); + init_config(def, *params); + generate_common_config_comments(def); // oxend - def.addSectionComments( + def.add_section_comments( "lokid", { "Settings for communicating with oxend", }); - return def.generateINIConfig(true); + return def.generate_ini_config(true); } std::shared_ptr - Config::EmbeddedConfig() + Config::make_embedded_config() { auto config = std::make_shared(); - config->Load(); - config->logging.m_logLevel = log::Level::off; - config->api.m_enableRPCServer = false; - config->network.m_endpointType = "null"; - config->network.m_saveProfiles = false; + config->load(); + config->logging.level = log::Level::off; + config->api.enable_rpc_server = false; + config->network.endpoint_type = "null"; + config->network.save_profiles = false; config->bootstrap.files.clear(); return config; } diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index 9ee7f2e6bc..ecee74bbfc 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -31,8 +31,8 @@ namespace llarp { - using SectionValues_t = llarp::ConfigParser::SectionValues_t; - using Config_impl_t = llarp::ConfigParser::Config_impl_t; + using SectionValues = llarp::ConfigParser::SectionValues; + using ConfigMap = llarp::ConfigParser::ConfigMap; // 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 @@ -45,8 +45,8 @@ namespace llarp ConfigGenParameters(const ConfigGenParameters&) = delete; ConfigGenParameters(ConfigGenParameters&&) = delete; - bool isRelay = false; - fs::path defaultDataDir; + bool is_relay = false; + fs::path default_data_dir; /// get network platform (virtual for unit test mocks) virtual const llarp::net::Platform* @@ -55,33 +55,33 @@ namespace llarp struct RouterConfig { - size_t m_minConnectedRouters = 0; - size_t m_maxConnectedRouters = 0; + size_t min_connected_routers = 0; + size_t max_connected_routers = 0; - std::string m_netId; + std::string net_id; - fs::path m_dataDir; + fs::path data_dir; - bool m_blockBogons = false; + bool block_bogons = false; - int m_workerThreads = -1; - int m_numNetThreads = -1; + int worker_threads = -1; + int net_threads = -1; - size_t m_JobQueueSize = 0; + size_t job_que_size = 0; - std::string m_routerContactFile; - std::string m_encryptionKeyFile; - std::string m_identityKeyFile; - std::string m_transportKeyFile; + std::string rc_file; + std::string enckey_file; + std::string idkey_file; + std::string transkey_file; - bool m_isRelay = false; + bool is_relay = false; /// deprecated - std::optional PublicIP; + std::optional public_ip; /// deprecated - std::optional PublicPort; + std::optional public_port; void - defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params); + define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); }; /// config for path hop selection @@ -90,91 +90,91 @@ namespace llarp /// in our hops what netmask will we use for unique ips for hops /// i.e. 32 for every hop unique ip, 24 unique /24 per hop, etc /// - int m_UniqueHopsNetmaskSize; + int unique_hop_netmask; /// set of countrys to exclude from path building (2 char country code) - std::unordered_set m_ExcludeCountries; + std::unordered_set exclude_countries; void - defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params); + define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); /// return true if this set of router contacts is acceptable against this config bool - Acceptable(const std::set& hops) const; + check_rcs(const std::set& hops) const; }; struct NetworkConfig { - std::optional m_enableProfiling; - bool m_saveProfiles; - std::set m_strictConnect; - std::string m_ifname; - IPRange m_ifaddr; + std::optional enable_profiling; + bool save_profiles; + std::set strict_connect; + std::string if_name; + IPRange if_addr; - std::optional m_keyfile; - std::string m_endpointType; - bool m_reachable = false; - std::optional m_Hops; - std::optional m_Paths; - bool m_AllowExit = false; - std::set m_snodeBlacklist; - net::IPRangeMap m_ExitMap; - net::IPRangeMap m_LNSExitMap; + std::optional keyfile; + std::string endpoint_type; + bool is_reachable = false; + std::optional hops; + std::optional paths; + bool allow_exit = false; + std::set snode_blacklist; + net::IPRangeMap exit_map; + net::IPRangeMap ons_exit_map; - std::unordered_map m_ExitAuths; - std::unordered_map m_LNSExitAuths; + std::unordered_map exit_auths; + std::unordered_map ons_exit_auths; - std::unordered_map m_mapAddrs; + std::unordered_map map_addrs; - service::AuthType m_AuthType = service::AuthType::eAuthTypeNone; - service::AuthFileType m_AuthFileType = service::AuthFileType::eAuthFileHashes; - std::optional m_AuthUrl; - std::optional m_AuthMethod; - std::unordered_set m_AuthWhitelist; - std::unordered_set m_AuthStaticTokens; - std::set m_AuthFiles; + service::AuthType auth_type = service::AuthType::NONE; + service::AuthFileType auth_file_type = service::AuthFileType::HASHES; + std::optional auth_url; + std::optional auth_method; + std::unordered_set auth_whitelist; + std::unordered_set auth_static_tokens; + std::set auth_files; - std::vector m_SRVRecords; + std::vector srv_records; - std::optional m_baseV6Address; + std::optional base_ipv6_addr; - std::set m_OwnedRanges; - std::optional m_TrafficPolicy; + std::set owned_ranges; + std::optional traffic_policy; - std::optional m_PathAlignmentTimeout; + std::optional path_alignment_timeout; - std::optional m_AddrMapPersistFile; + std::optional addr_map_persist_file; - bool m_EnableRoutePoker; - bool m_BlackholeRoutes; + bool enable_route_poker; + bool blackhole_routes; void - defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params); + define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); }; struct DnsConfig { - bool m_raw_dns; - std::vector m_bind; - std::vector m_upstreamDNS; - std::vector m_hostfiles; - std::optional m_QueryBind; + bool raw; + std::vector bind_addr; + std::vector upstream_dns; + std::vector hostfiles; + std::optional query_bind; - std::unordered_multimap m_ExtraOpts; + std::unordered_multimap extra_opts; void - defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params); + define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); }; struct LinksConfig { - std::optional PublicAddress; - std::optional PublicPort; - std::vector OutboundLinks; - std::vector InboundListenAddrs; + std::optional public_addr; + std::optional public_port; + std::vector outbound_links; + std::vector inbound_listen_addrs; void - defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params); + define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); }; struct ConnectConfig @@ -182,26 +182,26 @@ namespace llarp std::vector routers; void - defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params); + define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); }; // TODO: remove oxenmq from this header struct ApiConfig { - bool m_enableRPCServer = false; - std::vector m_rpcBindAddresses; + bool enable_rpc_server = false; + std::vector rpc_bind_addrs; void - defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params); + define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); }; struct LokidConfig { - fs::path ident_keyfile; - oxenmq::address lokidRPCAddr; + fs::path id_keyfile; + oxenmq::address rpc_addr; void - defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params); + define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); }; struct BootstrapConfig @@ -209,18 +209,19 @@ namespace llarp std::vector files; BootstrapList routers; bool seednode; + void - defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params); + define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); }; struct LoggingConfig { - log::Type m_logType = log::Type::Print; - log::Level m_logLevel = log::Level::off; - std::string m_logFile; + log::Type type = log::Type::Print; + log::Level level = log::Level::off; + std::string file; void - defineConfigOptions(ConfigDefinition& conf, const ConfigGenParameters& params); + define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); }; struct Config @@ -231,7 +232,7 @@ namespace llarp /// create generation params (virtual for unit test mock) virtual std::unique_ptr - MakeGenParams() const; + make_gen_params() const; RouterConfig router; NetworkConfig network; @@ -246,41 +247,41 @@ namespace llarp // Initialize config definition void - initializeConfig(ConfigDefinition& conf, const ConfigGenParameters& params); + init_config(ConfigDefinition& conf, const ConfigGenParameters& params); /// Insert config entries for backwards-compatibility (e.g. so that the config system will /// tolerate old values that are no longer accepted) /// /// @param conf is the config to modify void - addBackwardsCompatibleConfigOptions(ConfigDefinition& conf); + add_backcompat_opts(ConfigDefinition& conf); // Load a config from the given file if the config file is not provided LoadDefault is called bool - Load(std::optional fname = std::nullopt, bool isRelay = false); + load(std::optional fname = std::nullopt, bool isRelay = false); // Load a config from a string of ini, same effects as Config::Load bool - LoadString(std::string_view ini, bool isRelay = false); + load_string(std::string_view ini, bool isRelay = false); std::string - generateBaseClientConfig(); + generate_client_config_base(); std::string - generateBaseRouterConfig(); + generate_router_config_base(); void - Save(); + save(); void - Override(std::string section, std::string key, std::string value); + override(std::string section, std::string key, std::string value); void - AddDefault(std::string section, std::string key, std::string value); + add_default(std::string section, std::string key, std::string value); /// create a config with the default parameters for an embedded lokinet static std::shared_ptr - EmbeddedConfig(); + make_embedded_config(); private: /// Load (initialize) a default config. @@ -295,21 +296,21 @@ namespace llarp /// @param dataDir is a path representing a directory to be used as the data dir /// @return true on success, false otherwise bool - LoadDefault(bool isRelay); + load_default_config(bool isRelay); bool - LoadConfigData( + load_config_data( std::string_view ini, std::optional fname = std::nullopt, bool isRelay = false); void - LoadOverrides(ConfigDefinition& conf) const; + load_overrides(ConfigDefinition& conf) const; - std::vector> m_Additional; - ConfigParser m_Parser; - const fs::path m_DataDir; + std::vector> additional; + ConfigParser parser; + const fs::path data_dir; }; void - ensureConfig(fs::path dataDir, fs::path confFile, bool overwrite, bool asRouter); + ensure_config(fs::path dataDir, fs::path confFile, bool overwrite, bool asRouter); } // namespace llarp diff --git a/llarp/config/definition.cpp b/llarp/config/definition.cpp index b27e4b2e51..b4e1adac17 100644 --- a/llarp/config/definition.cpp +++ b/llarp/config/definition.cpp @@ -10,25 +10,24 @@ namespace llarp { template <> bool - OptionDefinition::fromString(const std::string& input) + OptionDefinition::from_string(const std::string& input) { if (input == "false" || input == "off" || input == "0" || input == "no") return false; - else if (input == "true" || input == "on" || input == "1" || input == "yes") + if (input == "true" || input == "on" || input == "1" || input == "yes") return true; - else - throw std::invalid_argument{fmt::format("{} is not a valid bool", input)}; + throw std::invalid_argument{fmt::format("{} is not a valid bool", input)}; } ConfigDefinition& - ConfigDefinition::defineOption(OptionDefinition_ptr def) + ConfigDefinition::define_option(std::unique_ptr def) { using namespace config; // If explicitly deprecated or is a {client,relay} option in a {relay,client} config then add a // dummy, warning option instead of this one. - if (def->deprecated || (relay ? def->clientOnly : def->relayOnly)) + if (def->deprecated || (relay ? def->clientOnly : def->relay_only)) { - return defineOption( + return define_option( def->section, def->name, MultiValue, @@ -46,36 +45,36 @@ namespace llarp }); } - auto [sectionItr, newSect] = m_definitions.try_emplace(def->section); + auto [sectionItr, newSect] = definitions.try_emplace(def->section); if (newSect) - m_sectionOrdering.push_back(def->section); + section_ordering.push_back(def->section); auto& section = sectionItr->first; - auto [it, added] = m_definitions[section].try_emplace(std::string{def->name}, std::move(def)); + auto [it, added] = definitions[section].try_emplace(std::string{def->name}, std::move(def)); if (!added) throw std::invalid_argument{ fmt::format("definition for [{}]:{} already exists", def->section, def->name)}; - m_definitionOrdering[section].push_back(it->first); + definition_ordering[section].push_back(it->first); if (!it->second->comments.empty()) - addOptionComments(section, it->first, std::move(it->second->comments)); + add_option_comments(section, it->first, std::move(it->second->comments)); return *this; } ConfigDefinition& - ConfigDefinition::addConfigValue( + ConfigDefinition::add_config_value( std::string_view section, std::string_view name, std::string_view value) { // see if we have an undeclared handler to fall back to in case section or section:name is // absent - auto undItr = m_undeclaredHandlers.find(std::string(section)); - bool haveUndeclaredHandler = (undItr != m_undeclaredHandlers.end()); + auto undItr = undeclared_handlers.find(std::string(section)); + bool haveUndeclaredHandler = (undItr != undeclared_handlers.end()); // get section, falling back to undeclared handler if needed - auto secItr = m_definitions.find(std::string(section)); - if (secItr == m_definitions.end()) + auto secItr = definitions.find(std::string(section)); + if (secItr == definitions.end()) { // fallback to undeclared handler if available if (not haveUndeclaredHandler) @@ -91,8 +90,8 @@ namespace llarp auto defItr = sectionDefinitions.find(std::string(name)); if (defItr != sectionDefinitions.end()) { - OptionDefinition_ptr& definition = defItr->second; - definition->parseValue(std::string(value)); + std::unique_ptr& definition = defItr->second; + definition->parse_value(std::string(value)); return *this; } @@ -105,63 +104,67 @@ namespace llarp } void - ConfigDefinition::addUndeclaredHandler(const std::string& section, UndeclaredValueHandler handler) + ConfigDefinition::add_undeclared_handler( + const std::string& section, UndeclaredValueHandler handler) { - auto itr = m_undeclaredHandlers.find(section); - if (itr != m_undeclaredHandlers.end()) + auto itr = undeclared_handlers.find(section); + if (itr != undeclared_handlers.end()) throw std::logic_error{fmt::format("section {} already has a handler", section)}; - m_undeclaredHandlers[section] = std::move(handler); + undeclared_handlers[section] = std::move(handler); } void - ConfigDefinition::removeUndeclaredHandler(const std::string& section) + ConfigDefinition::remove_undeclared_handler(const std::string& section) { - auto itr = m_undeclaredHandlers.find(section); - if (itr != m_undeclaredHandlers.end()) - m_undeclaredHandlers.erase(itr); + auto itr = undeclared_handlers.find(section); + if (itr != undeclared_handlers.end()) + undeclared_handlers.erase(itr); } void - ConfigDefinition::validateRequiredFields() + ConfigDefinition::validate_required_fields() { - visitSections([&](const std::string& section, const DefinitionMap&) { - visitDefinitions(section, [&](const std::string&, const OptionDefinition_ptr& def) { - if (def->required and def->getNumberFound() < 1) - { - throw std::invalid_argument{ - fmt::format("[{}]:{} is required but missing", section, def->name)}; - } - - // should be handled earlier in OptionDefinition::parseValue() - assert(def->getNumberFound() <= 1 or def->multiValued); - }); + visit_sections([&](const std::string& section, const DefinitionMap&) { + visit_definitions( + section, [&](const std::string&, const std::unique_ptr& def) { + if (def->required and def->get_number_found() < 1) + { + throw std::invalid_argument{ + fmt::format("[{}]:{} is required but missing", section, def->name)}; + } + + // should be handled earlier in OptionDefinition::parse_value() + assert(def->get_number_found() <= 1 or def->multi_valued); + }); }); } void - ConfigDefinition::acceptAllOptions() + ConfigDefinition::accept_all_options() { - visitSections([this](const std::string& section, const DefinitionMap&) { - visitDefinitions( - section, [](const std::string&, const OptionDefinition_ptr& def) { def->tryAccept(); }); + visit_sections([this](const std::string& section, const DefinitionMap&) { + visit_definitions( + section, [](const std::string&, const std::unique_ptr& def) { + def->try_accept(); + }); }); } void - ConfigDefinition::addSectionComments( + ConfigDefinition::add_section_comments( const std::string& section, std::vector comments) { - auto& sectionComments = m_sectionComments[section]; + auto& sectionComments = section_comments[section]; for (auto& c : comments) sectionComments.emplace_back(std::move(c)); } void - ConfigDefinition::addOptionComments( + ConfigDefinition::add_option_comments( const std::string& section, const std::string& name, std::vector comments) { - auto& defComments = m_definitionComments[section][name]; + auto& defComments = definition_comments[section][name]; if (defComments.empty()) defComments = std::move(comments); else @@ -172,48 +175,49 @@ namespace llarp } std::string - ConfigDefinition::generateINIConfig(bool useValues) + ConfigDefinition::generate_ini_config(bool useValues) { std::string ini; auto ini_append = std::back_inserter(ini); int sectionsVisited = 0; - visitSections([&](const std::string& section, const DefinitionMap&) { + visit_sections([&](const std::string& section, const DefinitionMap&) { std::string sect_str; auto sect_append = std::back_inserter(sect_str); - visitDefinitions(section, [&](const std::string& name, const OptionDefinition_ptr& def) { - bool has_comment = false; - // TODO: as above, this will create empty objects - // TODO: as above (but more important): this won't handle definitions with no entries - // (i.e. those handled by UndeclaredValueHandler's) - for (const std::string& comment : m_definitionComments[section][name]) - { - fmt::format_to(sect_append, "\n# {}", comment); - has_comment = true; - } - - if (useValues and def->getNumberFound() > 0) - { - for (const auto& val : def->valuesAsString()) - fmt::format_to(sect_append, "\n{}={}", name, val); - *sect_append = '\n'; - } - else if (not def->hidden) - { - if (auto defaults = def->defaultValuesAsString(); not defaults.empty()) - for (const auto& val : defaults) - fmt::format_to(sect_append, "\n{}{}={}", def->required ? "" : "#", name, val); - else - // We have no defaults so we append it as "#opt-name=" so that we show the option name, - // and make it simple to uncomment and edit to the desired value. - fmt::format_to(sect_append, "\n#{}=", name); - *sect_append = '\n'; - } - else if (has_comment) - *sect_append = '\n'; - }); + visit_definitions( + section, [&](const std::string& name, const std::unique_ptr& def) { + bool has_comment = false; + // TODO: as above, this will create empty objects + // TODO: as above (but more important): this won't handle definitions with no entries + // (i.e. those handled by UndeclaredValueHandler's) + for (const std::string& comment : definition_comments[section][name]) + { + fmt::format_to(sect_append, "\n# {}", comment); + has_comment = true; + } + + if (useValues and def->get_number_found() > 0) + { + for (const auto& val : def->values_as_string()) + fmt::format_to(sect_append, "\n{}={}", name, val); + *sect_append = '\n'; + } + else if (not def->hidden) + { + if (auto defaults = def->default_values_as_string(); not defaults.empty()) + for (const auto& val : defaults) + fmt::format_to(sect_append, "\n{}{}={}", def->required ? "" : "#", name, val); + else + // We have no defaults so we append it as "#opt-name=" so that we show the option + // name, and make it simple to uncomment and edit to the desired value. + fmt::format_to(sect_append, "\n#{}=", name); + *sect_append = '\n'; + } + else if (has_comment) + *sect_append = '\n'; + }); if (sect_str.empty()) return; // Skip sections with no options @@ -225,7 +229,7 @@ namespace llarp // TODO: this will create empty objects as a side effect of map's operator[] // TODO: this also won't handle sections which have no definition - for (const std::string& comment : m_sectionComments[section]) + for (const std::string& comment : section_comments[section]) { fmt::format_to(ini_append, "# {}\n", comment); } @@ -238,11 +242,12 @@ namespace llarp return ini; } - const OptionDefinition_ptr& - ConfigDefinition::lookupDefinitionOrThrow(std::string_view section, std::string_view name) const + const std::unique_ptr& + ConfigDefinition::lookup_definition_or_throw( + std::string_view section, std::string_view name) const { - const auto sectionItr = m_definitions.find(std::string(section)); - if (sectionItr == m_definitions.end()) + const auto sectionItr = definitions.find(std::string(section)); + if (sectionItr == definitions.end()) throw std::invalid_argument{fmt::format("No config section [{}]", section)}; auto& sectionDefinitions = sectionItr->second; @@ -254,28 +259,28 @@ namespace llarp return definitionItr->second; } - OptionDefinition_ptr& - ConfigDefinition::lookupDefinitionOrThrow(std::string_view section, std::string_view name) + std::unique_ptr& + ConfigDefinition::lookup_definition_or_throw(std::string_view section, std::string_view name) { - return const_cast( - const_cast(this)->lookupDefinitionOrThrow(section, name)); + return const_cast&>( + const_cast(this)->lookup_definition_or_throw(section, name)); } void - ConfigDefinition::visitSections(SectionVisitor visitor) const + ConfigDefinition::visit_sections(SectionVisitor visitor) const { - for (const std::string& section : m_sectionOrdering) + for (const std::string& section : section_ordering) { - const auto itr = m_definitions.find(section); - assert(itr != m_definitions.end()); + const auto itr = definitions.find(section); + assert(itr != definitions.end()); visitor(section, itr->second); } }; void - ConfigDefinition::visitDefinitions(const std::string& section, DefVisitor visitor) const + ConfigDefinition::visit_definitions(const std::string& section, DefVisitor visitor) const { - const auto& defs = m_definitions.at(section); - const auto& defOrdering = m_definitionOrdering.at(section); + const auto& defs = definitions.at(section); + const auto& defOrdering = definition_ordering.at(section); for (const std::string& name : defOrdering) { const auto itr = defs.find(name); diff --git a/llarp/config/definition.hpp b/llarp/config/definition.hpp index 2d0ed0818e..7b777f0563 100644 --- a/llarp/config/definition.hpp +++ b/llarp/config/definition.hpp @@ -22,42 +22,45 @@ namespace llarp { namespace config { - // Base class for the following option flag types - struct option_flag - {}; - - struct Required_t : option_flag - {}; - struct Hidden_t : option_flag - {}; - struct MultiValue_t : option_flag - {}; - struct RelayOnly_t : option_flag - {}; - struct ClientOnly_t : option_flag - {}; - struct Deprecated_t : option_flag - {}; + namespace flag + { + // Base class for the following option flag types + struct opt + {}; + + struct REQUIRED : opt + {}; + struct HIDDEN : opt + {}; + struct MULTIVALUE : opt + {}; + struct RELAYONLY : opt + {}; + struct CLIENTONLY : opt + {}; + struct DEPRECATED : opt + {}; + } // namespace flag /// Value to pass for an OptionDefinition to indicate that the option is required - inline constexpr Required_t Required{}; + inline constexpr flag::REQUIRED Required{}; /// Value to pass for an OptionDefinition to indicate that the option should be hidden from the /// generate config file if it is unset (and has no comment). Typically for deprecated, renamed /// options that still do something, and for internal dev options that aren't usefully exposed. /// (For do-nothing deprecated options use Deprecated instead). - inline constexpr Hidden_t Hidden{}; + inline constexpr flag::HIDDEN Hidden{}; /// Value to pass for an OptionDefinition to indicate that the option takes multiple values - inline constexpr MultiValue_t MultiValue{}; + inline constexpr flag::MULTIVALUE MultiValue{}; /// Value to pass for an option that should only be set for relay configs. If found in a client /// config it be ignored (but will produce a warning). - inline constexpr RelayOnly_t RelayOnly{}; + inline constexpr flag::RELAYONLY RelayOnly{}; /// Value to pass for an option that should only be set for client configs. If found in a relay /// config it will be ignored (but will produce a warning). - inline constexpr ClientOnly_t ClientOnly{}; + inline constexpr flag::CLIENTONLY ClientOnly{}; /// Value to pass for an option that is deprecated and does nothing and should be ignored (with /// a deprecation warning) if specified. Note that Deprecated implies Hidden, and that /// {client,relay}-only options in a {relay,client} config are also considered Deprecated. - inline constexpr Deprecated_t Deprecated{}; + inline constexpr flag::DEPRECATED Deprecated{}; /// Wrapper to specify a default value to an OptionDefinition template @@ -82,7 +85,7 @@ namespace llarp /// particular, a reference to a local variable may be problematic. template auto - AssignmentAcceptor(T& ref) + assignment_acceptor(T& ref) { return [&ref](T arg) { ref = std::move(arg); }; } @@ -106,7 +109,7 @@ namespace llarp constexpr bool is_default_array = is_default_array>; template - constexpr bool is_option = std::is_base_of_v> + constexpr bool is_option = std::is_base_of_v> or std::is_same_v or is_default