From b636e3530411168a41ba1a3e676f2adb0280c4f8 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Wed, 2 Oct 2024 11:35:36 -0700 Subject: [PATCH 01/44] contact library, re-org --- CMakeLists.txt | 2 +- crypto/CMakeLists.txt | 66 -- crypto/libntrup/include/libntrup/ntru.h | 37 - crypto/libntrup/include/libntrup/ntru_api.h | 22 - crypto/libntrup/include/sodium/crypto_int16.h | 2 - crypto/libntrup/include/sodium/crypto_int32.h | 3 - crypto/libntrup/include/sodium/crypto_int64.h | 2 - crypto/libntrup/include/sodium/crypto_int8.h | 2 - crypto/libntrup/include/sodium/crypto_kem.h | 1 - .../libntrup/include/sodium/crypto_uint16.h | 2 - .../libntrup/include/sodium/crypto_uint32.h | 3 - crypto/libntrup/src/avx/api.h | 4 - crypto/libntrup/src/avx/dec.c | 73 -- crypto/libntrup/src/avx/enc.c | 52 -- crypto/libntrup/src/avx/implementors | 5 - crypto/libntrup/src/avx/int32_sort.c | 466 --------- crypto/libntrup/src/avx/int32_sort.h | 10 - crypto/libntrup/src/avx/keypair.c | 45 - crypto/libntrup/src/avx/mod3.h | 68 -- crypto/libntrup/src/avx/modq.h | 100 -- crypto/libntrup/src/avx/mult.c | 884 ------------------ crypto/libntrup/src/avx/params.h | 14 - crypto/libntrup/src/avx/r3.h | 18 - crypto/libntrup/src/avx/r3_recip.c | 221 ----- crypto/libntrup/src/avx/randomsmall.c | 18 - crypto/libntrup/src/avx/randomweightw.c | 22 - crypto/libntrup/src/avx/rq.c | 185 ---- crypto/libntrup/src/avx/rq.h | 39 - crypto/libntrup/src/avx/rq_mod3.c | 68 -- crypto/libntrup/src/avx/rq_recip3.c | 247 ----- crypto/libntrup/src/avx/rq_round3.c | 24 - crypto/libntrup/src/avx/rq_rounded.c | 297 ------ crypto/libntrup/src/avx/small.c | 54 -- crypto/libntrup/src/avx/small.h | 24 - crypto/libntrup/src/avx/swap.c | 37 - crypto/libntrup/src/avx/swap.h | 8 - crypto/libntrup/src/avx/weight.c | 34 - crypto/libntrup/src/files.txt | 32 - crypto/libntrup/src/noavx-stubs.c | 29 - crypto/libntrup/src/ntru.cpp | 75 -- crypto/libntrup/src/ref/README | 32 - crypto/libntrup/src/ref/api.h | 4 - crypto/libntrup/src/ref/dec.c | 75 -- crypto/libntrup/src/ref/enc.c | 49 - crypto/libntrup/src/ref/implementors | 5 - crypto/libntrup/src/ref/int32_sort.c | 40 - crypto/libntrup/src/ref/int32_sort.h | 10 - crypto/libntrup/src/ref/keypair.c | 41 - crypto/libntrup/src/ref/mod3.h | 68 -- crypto/libntrup/src/ref/modq.h | 101 -- crypto/libntrup/src/ref/params.h | 17 - crypto/libntrup/src/ref/r3.h | 14 - crypto/libntrup/src/ref/r3_mult.c | 35 - crypto/libntrup/src/ref/r3_recip.c | 151 --- crypto/libntrup/src/ref/random32.c | 28 - crypto/libntrup/src/ref/randomsmall.c | 16 - crypto/libntrup/src/ref/randomweightw.c | 21 - crypto/libntrup/src/ref/rq.c | 142 --- crypto/libntrup/src/ref/rq.h | 35 - crypto/libntrup/src/ref/rq_mult.c | 34 - crypto/libntrup/src/ref/rq_recip3.c | 151 --- crypto/libntrup/src/ref/rq_round3.c | 11 - crypto/libntrup/src/ref/rq_rounded.c | 111 --- crypto/libntrup/src/ref/small.c | 44 - crypto/libntrup/src/ref/small.h | 29 - crypto/libntrup/src/ref/swap.c | 21 - crypto/libntrup/src/ref/swap.h | 8 - .../crypto_kem/sntrup4591761/checksumbig | 1 - .../crypto_kem/sntrup4591761/checksumsmall | 1 - .../crypto_kem/sntrup4591761/description | 1 - .../crypto_kem/sntrup4591761/designers | 5 - docs/Doxyfile.in | 4 +- llarp/CMakeLists.txt | 18 +- llarp/address/address.hpp | 2 +- llarp/auth/auth.hpp | 2 +- llarp/bootstrap.hpp | 3 +- llarp/config/config.hpp | 2 +- llarp/consensus/reachability_testing.hpp | 2 +- llarp/{ => contact}/router_contact.cpp | 6 - llarp/{ => contact}/router_contact.hpp | 7 +- llarp/{ => contact}/router_contact_local.cpp | 6 - llarp/{ => contact}/router_contact_remote.cpp | 6 - llarp/{ => contact}/router_id.cpp | 0 llarp/{ => contact}/router_id.hpp | 3 +- llarp/crypto/constants.hpp | 7 - llarp/crypto/crypto.cpp | 29 +- llarp/crypto/crypto.hpp | 15 +- llarp/crypto/key_manager.hpp | 2 +- llarp/crypto/types.hpp | 4 - llarp/dht/kademlia.hpp | 2 +- llarp/dht/key.hpp | 2 +- llarp/dht/node.hpp | 2 +- llarp/endpoint_base.hpp | 3 +- llarp/handlers/session.cpp | 35 +- llarp/link/connection.hpp | 4 +- llarp/link/link_manager.cpp | 2 +- llarp/messages/common.hpp | 2 +- llarp/nodedb.cpp | 1 - llarp/nodedb.hpp | 4 +- llarp/path/path.cpp | 7 +- llarp/path/path_handler.cpp | 18 +- llarp/path/path_handler.hpp | 9 +- llarp/path/path_types.hpp | 2 +- llarp/path/transit_hop.hpp | 2 +- llarp/profiling.hpp | 2 +- llarp/router/router.hpp | 2 +- llarp/rpc/rpc_client.hpp | 2 +- llarp/service/identity.cpp | 6 - llarp/service/identity.hpp | 6 +- llarp/service/info.cpp | 12 +- llarp/service/info.hpp | 10 +- llarp/service/intro.cpp | 13 +- llarp/service/intro.hpp | 15 +- llarp/service/intro_set.cpp | 9 +- llarp/service/intro_set.hpp | 5 +- llarp/service/vanity.hpp | 16 - pybind/llarp/router_id.cpp | 2 +- 117 files changed, 110 insertions(+), 4799 deletions(-) delete mode 100644 crypto/CMakeLists.txt delete mode 100644 crypto/libntrup/include/libntrup/ntru.h delete mode 100644 crypto/libntrup/include/libntrup/ntru_api.h delete mode 100644 crypto/libntrup/include/sodium/crypto_int16.h delete mode 100644 crypto/libntrup/include/sodium/crypto_int32.h delete mode 100644 crypto/libntrup/include/sodium/crypto_int64.h delete mode 100644 crypto/libntrup/include/sodium/crypto_int8.h delete mode 100644 crypto/libntrup/include/sodium/crypto_kem.h delete mode 100644 crypto/libntrup/include/sodium/crypto_uint16.h delete mode 100644 crypto/libntrup/include/sodium/crypto_uint32.h delete mode 100644 crypto/libntrup/src/avx/api.h delete mode 100644 crypto/libntrup/src/avx/dec.c delete mode 100644 crypto/libntrup/src/avx/enc.c delete mode 100644 crypto/libntrup/src/avx/implementors delete mode 100644 crypto/libntrup/src/avx/int32_sort.c delete mode 100644 crypto/libntrup/src/avx/int32_sort.h delete mode 100644 crypto/libntrup/src/avx/keypair.c delete mode 100644 crypto/libntrup/src/avx/mod3.h delete mode 100644 crypto/libntrup/src/avx/modq.h delete mode 100644 crypto/libntrup/src/avx/mult.c delete mode 100644 crypto/libntrup/src/avx/params.h delete mode 100644 crypto/libntrup/src/avx/r3.h delete mode 100644 crypto/libntrup/src/avx/r3_recip.c delete mode 100644 crypto/libntrup/src/avx/randomsmall.c delete mode 100644 crypto/libntrup/src/avx/randomweightw.c delete mode 100644 crypto/libntrup/src/avx/rq.c delete mode 100644 crypto/libntrup/src/avx/rq.h delete mode 100644 crypto/libntrup/src/avx/rq_mod3.c delete mode 100644 crypto/libntrup/src/avx/rq_recip3.c delete mode 100644 crypto/libntrup/src/avx/rq_round3.c delete mode 100644 crypto/libntrup/src/avx/rq_rounded.c delete mode 100644 crypto/libntrup/src/avx/small.c delete mode 100644 crypto/libntrup/src/avx/small.h delete mode 100644 crypto/libntrup/src/avx/swap.c delete mode 100644 crypto/libntrup/src/avx/swap.h delete mode 100644 crypto/libntrup/src/avx/weight.c delete mode 100644 crypto/libntrup/src/files.txt delete mode 100644 crypto/libntrup/src/noavx-stubs.c delete mode 100644 crypto/libntrup/src/ntru.cpp delete mode 100644 crypto/libntrup/src/ref/README delete mode 100644 crypto/libntrup/src/ref/api.h delete mode 100644 crypto/libntrup/src/ref/dec.c delete mode 100644 crypto/libntrup/src/ref/enc.c delete mode 100644 crypto/libntrup/src/ref/implementors delete mode 100644 crypto/libntrup/src/ref/int32_sort.c delete mode 100644 crypto/libntrup/src/ref/int32_sort.h delete mode 100644 crypto/libntrup/src/ref/keypair.c delete mode 100644 crypto/libntrup/src/ref/mod3.h delete mode 100644 crypto/libntrup/src/ref/modq.h delete mode 100644 crypto/libntrup/src/ref/params.h delete mode 100644 crypto/libntrup/src/ref/r3.h delete mode 100644 crypto/libntrup/src/ref/r3_mult.c delete mode 100644 crypto/libntrup/src/ref/r3_recip.c delete mode 100644 crypto/libntrup/src/ref/random32.c delete mode 100644 crypto/libntrup/src/ref/randomsmall.c delete mode 100644 crypto/libntrup/src/ref/randomweightw.c delete mode 100644 crypto/libntrup/src/ref/rq.c delete mode 100644 crypto/libntrup/src/ref/rq.h delete mode 100644 crypto/libntrup/src/ref/rq_mult.c delete mode 100644 crypto/libntrup/src/ref/rq_recip3.c delete mode 100644 crypto/libntrup/src/ref/rq_round3.c delete mode 100644 crypto/libntrup/src/ref/rq_rounded.c delete mode 100644 crypto/libntrup/src/ref/small.c delete mode 100644 crypto/libntrup/src/ref/small.h delete mode 100644 crypto/libntrup/src/ref/swap.c delete mode 100644 crypto/libntrup/src/ref/swap.h delete mode 100644 crypto/ntruprime-20171206/crypto_kem/sntrup4591761/checksumbig delete mode 100644 crypto/ntruprime-20171206/crypto_kem/sntrup4591761/checksumsmall delete mode 100644 crypto/ntruprime-20171206/crypto_kem/sntrup4591761/description delete mode 100644 crypto/ntruprime-20171206/crypto_kem/sntrup4591761/designers rename llarp/{ => contact}/router_contact.cpp (97%) rename llarp/{ => contact}/router_contact.hpp (98%) rename llarp/{ => contact}/router_contact_local.cpp (94%) rename llarp/{ => contact}/router_contact_remote.cpp (89%) rename llarp/{ => contact}/router_id.cpp (100%) rename llarp/{ => contact}/router_id.hpp (97%) delete mode 100644 llarp/service/vanity.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 5bb6f298f6..5ee1217f63 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -301,7 +301,7 @@ if(WITH_HIVE) add_definitions(-DLOKINET_HIVE) endif() -add_subdirectory(crypto) +#add_subdirectory(crypto) add_subdirectory(llarp) if(BUILD_DAEMON) add_subdirectory(daemon) diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt deleted file mode 100644 index b39422f28b..0000000000 --- a/crypto/CMakeLists.txt +++ /dev/null @@ -1,66 +0,0 @@ - -add_library(lokinet-libntrup - STATIC - libntrup/src/ntru.cpp - libntrup/src/ref/randomsmall.c - libntrup/src/ref/swap.c - libntrup/src/ref/rq_round3.c - libntrup/src/ref/rq_recip3.c - libntrup/src/ref/small.c - libntrup/src/ref/rq_mult.c - libntrup/src/ref/randomweightw.c - libntrup/src/ref/random32.c - libntrup/src/ref/dec.c - libntrup/src/ref/r3_mult.c - libntrup/src/ref/r3_recip.c - libntrup/src/ref/keypair.c - libntrup/src/ref/rq_rounded.c - libntrup/src/ref/enc.c - libntrup/src/ref/int32_sort.c - libntrup/src/ref/rq.c -) - -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 -# general AVX2 enabled. -set(NTRU_AVX_SRC - libntrup/src/avx/randomsmall.c - libntrup/src/avx/weight.c - libntrup/src/avx/swap.c - libntrup/src/avx/rq_round3.c - libntrup/src/avx/rq_recip3.c - libntrup/src/avx/small.c - libntrup/src/avx/randomweightw.c - libntrup/src/avx/dec.c - libntrup/src/avx/r3_recip.c - libntrup/src/avx/keypair.c - libntrup/src/avx/rq_rounded.c - libntrup/src/avx/mult.c - libntrup/src/avx/enc.c - libntrup/src/avx/int32_sort.c - libntrup/src/avx/rq.c - libntrup/src/avx/rq_mod3.c -) - -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-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-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-libntrup) - -if (WARNINGS_AS_ERRORS) - target_compile_options(lokinet-libntrup PUBLIC -Wall -Wextra -Werror) -endif() - -target_link_libraries(lokinet-libntrup PUBLIC sodium) - diff --git a/crypto/libntrup/include/libntrup/ntru.h b/crypto/libntrup/include/libntrup/ntru.h deleted file mode 100644 index 390f06f0a7..0000000000 --- a/crypto/libntrup/include/libntrup/ntru.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef LIBNTRUP_NTRU_H -#define LIBNTRUP_NTRU_H -#ifdef __cplusplus -extern "C" -{ -#endif - -#include "ntru_api.h" - - void - ntru_init(int force_no_avx2); - - int - crypto_kem_enc(unsigned char *cstr, unsigned char *k, - const unsigned char *pk); - - int - crypto_kem_dec(unsigned char *k, const unsigned char *cstr, - const unsigned char *sk); - - int - crypto_kem_keypair(unsigned char *pk, unsigned char *sk); - -#define crypto_kem_SECRETKEYBYTES 1600 -#define crypto_kem_PUBLICKEYBYTES 1218 -#define crypto_kem_CIPHERTEXTBYTES 1047 - -#define NTRU_SECRETKEYBYTES CRYPTO_SECRETKEYBYTES -#define NTRU_PUBLICKEYBYTES CRYPTO_PUBLICKEYBYTES -#define NTRU_CIPHERTEXTBYTES CRYPTO_CIPHERTEXTBYTES - -#define CRYPTO_BYTES 32 - -#ifdef __cplusplus -} -#endif -#endif diff --git a/crypto/libntrup/include/libntrup/ntru_api.h b/crypto/libntrup/include/libntrup/ntru_api.h deleted file mode 100644 index 9753891d93..0000000000 --- a/crypto/libntrup/include/libntrup/ntru_api.h +++ /dev/null @@ -1,22 +0,0 @@ - -int -crypto_kem_enc_ref(unsigned char *cstr, unsigned char *k, - const unsigned char *pk); - -int -crypto_kem_dec_ref(unsigned char *k, const unsigned char *cstr, - const unsigned char *sk); - -int -crypto_kem_keypair_ref(unsigned char *pk, unsigned char *sk); - -int -crypto_kem_enc_avx2(unsigned char *cstr, unsigned char *k, - const unsigned char *pk); - -int -crypto_kem_dec_avx2(unsigned char *k, const unsigned char *cstr, - const unsigned char *sk); - -int -crypto_kem_keypair_avx2(unsigned char *pk, unsigned char *sk); diff --git a/crypto/libntrup/include/sodium/crypto_int16.h b/crypto/libntrup/include/sodium/crypto_int16.h deleted file mode 100644 index fd4e8f5c01..0000000000 --- a/crypto/libntrup/include/sodium/crypto_int16.h +++ /dev/null @@ -1,2 +0,0 @@ -#include -typedef int16_t crypto_int16; \ No newline at end of file diff --git a/crypto/libntrup/include/sodium/crypto_int32.h b/crypto/libntrup/include/sodium/crypto_int32.h deleted file mode 100644 index 9e5d7ff3ba..0000000000 --- a/crypto/libntrup/include/sodium/crypto_int32.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once -#include -typedef int32_t crypto_int32; diff --git a/crypto/libntrup/include/sodium/crypto_int64.h b/crypto/libntrup/include/sodium/crypto_int64.h deleted file mode 100644 index 0e87ad3a77..0000000000 --- a/crypto/libntrup/include/sodium/crypto_int64.h +++ /dev/null @@ -1,2 +0,0 @@ -#include -typedef int64_t crypto_int64; \ No newline at end of file diff --git a/crypto/libntrup/include/sodium/crypto_int8.h b/crypto/libntrup/include/sodium/crypto_int8.h deleted file mode 100644 index 1ad6096428..0000000000 --- a/crypto/libntrup/include/sodium/crypto_int8.h +++ /dev/null @@ -1,2 +0,0 @@ -#include -typedef int8_t crypto_int8; \ No newline at end of file diff --git a/crypto/libntrup/include/sodium/crypto_kem.h b/crypto/libntrup/include/sodium/crypto_kem.h deleted file mode 100644 index 8618072a3b..0000000000 --- a/crypto/libntrup/include/sodium/crypto_kem.h +++ /dev/null @@ -1 +0,0 @@ -#include \ No newline at end of file diff --git a/crypto/libntrup/include/sodium/crypto_uint16.h b/crypto/libntrup/include/sodium/crypto_uint16.h deleted file mode 100644 index 60eda75c45..0000000000 --- a/crypto/libntrup/include/sodium/crypto_uint16.h +++ /dev/null @@ -1,2 +0,0 @@ -#include -typedef uint16_t crypto_uint16; \ No newline at end of file diff --git a/crypto/libntrup/include/sodium/crypto_uint32.h b/crypto/libntrup/include/sodium/crypto_uint32.h deleted file mode 100644 index 0147a9867e..0000000000 --- a/crypto/libntrup/include/sodium/crypto_uint32.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once -#include -typedef uint32_t crypto_uint32; diff --git a/crypto/libntrup/src/avx/api.h b/crypto/libntrup/src/avx/api.h deleted file mode 100644 index 94d75538bc..0000000000 --- a/crypto/libntrup/src/avx/api.h +++ /dev/null @@ -1,4 +0,0 @@ -#define CRYPTO_SECRETKEYBYTES 1600 -#define CRYPTO_PUBLICKEYBYTES 1218 -#define CRYPTO_CIPHERTEXTBYTES 1047 -#define CRYPTO_BYTES 32 diff --git a/crypto/libntrup/src/avx/dec.c b/crypto/libntrup/src/avx/dec.c deleted file mode 100644 index bc189e9926..0000000000 --- a/crypto/libntrup/src/avx/dec.c +++ /dev/null @@ -1,73 +0,0 @@ -#ifdef KAT -#include -#endif -#include -#include -#include - -#include "params.h" -#include "small.h" -#include "mod3.h" -#include "rq.h" -#include "r3.h" - -#ifndef __AVX2__ -#error "This file requires compilation with AVX2 support" -#endif - -int -crypto_kem_dec_avx2(unsigned char *k, const unsigned char *cstr, - const unsigned char *sk) -{ - small f[768]; - modq h[768]; - small grecip[768]; - modq c[768]; - modq t[768]; - small t3[768]; - small r[768]; - modq hr[768]; - unsigned char rstr[small_encode_len]; - unsigned char hash[64]; - int i; - int result = 0; - - small_decode(f, sk); - small_decode(grecip, sk + small_encode_len); - rq_decode(h, sk + 2 * small_encode_len); - - rq_decoderounded(c, cstr + 32); - - rq_mult(t, c, f); - rq_mod3(t3, t); - - r3_mult(r, t3, grecip); - -#ifdef KAT - { - int j; - printf("decrypt r:"); - for(j = 0; j < p; ++j) - if(r[j] == 1) - printf(" +%d", j); - else if(r[j] == -1) - printf(" -%d", j); - printf("\n"); - } -#endif - - result |= r3_weightw_mask(r); - - rq_mult(hr, h, r); - rq_round3(hr, hr); - for(i = 0; i < p; ++i) - result |= modq_nonzero_mask(hr[i] - c[i]); - - small_encode(rstr, r); - crypto_hash_sha512(hash, rstr, sizeof rstr); - result |= crypto_verify_32(hash, cstr); - - for(i = 0; i < 32; ++i) - k[i] = (hash[32 + i] & ~result); - return result; -} diff --git a/crypto/libntrup/src/avx/enc.c b/crypto/libntrup/src/avx/enc.c deleted file mode 100644 index 85ac4d946b..0000000000 --- a/crypto/libntrup/src/avx/enc.c +++ /dev/null @@ -1,52 +0,0 @@ -#ifdef KAT -#include -#endif - -#include -#include "params.h" -#include "small.h" -#include "rq.h" -#include -#include - -#ifndef __AVX2__ -#error "This file requires compilation with AVX2 support" -#endif - -int -crypto_kem_enc_avx2(unsigned char *cstr, unsigned char *k, - const unsigned char *pk) -{ - small r[768]; - modq h[768]; - modq c[768]; - unsigned char rstr[small_encode_len]; - unsigned char hash[64]; - - small_random_weightw(r); - -#ifdef KAT - { - int i; - printf("encrypt r:"); - for(i = 0; i < p; ++i) - if(r[i] == 1) - printf(" +%d", i); - else if(r[i] == -1) - printf(" -%d", i); - printf("\n"); - } -#endif - - small_encode(rstr, r); - crypto_hash_sha512(hash, rstr, sizeof rstr); - - rq_decode(h, pk); - rq_mult(c, h, r); - - memcpy(k, hash + 32, 32); - memcpy(cstr, hash, 32); - rq_roundencode(cstr + 32, c); - - return 0; -} diff --git a/crypto/libntrup/src/avx/implementors b/crypto/libntrup/src/avx/implementors deleted file mode 100644 index 51ac31ea2e..0000000000 --- a/crypto/libntrup/src/avx/implementors +++ /dev/null @@ -1,5 +0,0 @@ -Alphabetical order: -Daniel J. Bernstein -Chitchanok Chuengsatiansup -Tanja Lange -Christine van Vredendaal diff --git a/crypto/libntrup/src/avx/int32_sort.c b/crypto/libntrup/src/avx/int32_sort.c deleted file mode 100644 index ea836d0b8c..0000000000 --- a/crypto/libntrup/src/avx/int32_sort.c +++ /dev/null @@ -1,466 +0,0 @@ -#ifdef __AVX2__ -#include "int32_sort.h" -#include - -typedef crypto_int32 int32; - -static inline void -minmax(int32 *x, int32 *y) -{ - __asm__("movl (%0),%%eax;movl (%1),%%ebx;cmpl %%ebx,%%eax;mov %%eax,%%edx;cmovg " - "%%ebx,%%eax;cmovg %%edx,%%ebx;movl %%eax,(%0);movl %%ebx,(%1)" - : - : "r"(x), "r"(y) - : "%eax", "%ebx", "%edx"); -} - -/* sort x0,x2; sort x1,x3; ... sort x13, x15 */ -static inline void -minmax02through1315(int32 *x) -{ - __m256i a = _mm256_loadu_si256((__m256i *)x); - __m256i b = _mm256_loadu_si256((__m256i *)(x + 8)); - __m256i c = _mm256_unpacklo_epi64(a, b); /* a01b01a45b45 */ - __m256i d = _mm256_unpackhi_epi64(a, b); /* a23b23a67b67 */ - __m256i g = _mm256_min_epi32(c, d); - __m256i h = _mm256_max_epi32(c, d); - a = _mm256_unpacklo_epi64(g, h); - b = _mm256_unpackhi_epi64(g, h); - _mm256_storeu_si256((__m256i *)x, a); - _mm256_storeu_si256((__m256i *)(x + 8), b); -} - -/* sort x0,x2; sort x1,x3; sort x4,x6; sort x5,x7 */ -static inline void -minmax02134657(int32 *x) -{ - __m256i a = _mm256_loadu_si256((__m256i *)x); - __m256i b = _mm256_shuffle_epi32(a, 0x4e); - __m256i c = _mm256_cmpgt_epi32(a, b); - c = _mm256_shuffle_epi32(c, 0x44); - __m256i abc = c & (a ^ b); - a ^= abc; - _mm256_storeu_si256((__m256i *)x, a); -} - -static void -multiminmax2plus2(int32 *x, int n) -{ - while(n >= 16) - { - minmax02through1315(x); - n -= 16; - x += 16; - } - if(n >= 8) - { - minmax02134657(x); - n -= 8; - x += 8; - } - if(n >= 4) - { - minmax(x, x + 2); - minmax(x + 1, x + 3); - n -= 4; - x += 4; - } - if(n > 0) - { - minmax(x, x + 2); - if(n > 1) - minmax(x + 1, x + 3); - } -} - -static void -multiminmax2plus6(int32 *x, int n) -{ - while(n >= 4) - { - minmax(x, x + 6); - minmax(x + 1, x + 7); - n -= 4; - x += 4; - } - if(n > 0) - { - minmax(x, x + 6); - if(n > 1) - minmax(x + 1, x + 7); - } -} - -static void -multiminmax2plus14(int32 *x, int n) -{ - while(n >= 8) - { - minmax(x, x + 14); - minmax(x + 1, x + 15); - minmax(x + 4, x + 18); - minmax(x + 5, x + 19); - n -= 8; - x += 8; - } - if(n >= 4) - { - minmax(x, x + 14); - minmax(x + 1, x + 15); - n -= 4; - x += 4; - } - if(n > 0) - { - minmax(x, x + 14); - if(n > 1) - minmax(x + 1, x + 15); - } -} - -/* sort x[i],y[i] for i in 0,1,4,5,8,9,12,13 */ -/* all of x0...x15 and y0...y15 must exist; no aliasing */ -static inline void -minmax0145891213(int32 *x, int32 *y) -{ - __m256i a01234567 = _mm256_loadu_si256((__m256i *)x); - __m256i a89101112131415 = _mm256_loadu_si256((__m256i *)(x + 8)); - __m256i b01234567 = _mm256_loadu_si256((__m256i *)y); - __m256i b89101112131415 = _mm256_loadu_si256((__m256i *)(y + 8)); - - __m256i a0189451213 = _mm256_unpacklo_epi64(a01234567, a89101112131415); - __m256i b0189451213 = _mm256_unpacklo_epi64(b01234567, b89101112131415); - __m256i c0189451213 = _mm256_min_epi32(a0189451213, b0189451213); - __m256i d0189451213 = _mm256_max_epi32(a0189451213, b0189451213); - - __m256i c01234567 = _mm256_blend_epi32(a01234567, c0189451213, 0x33); - __m256i d01234567 = _mm256_blend_epi32(b01234567, d0189451213, 0x33); - __m256i c89101112131415 = _mm256_unpackhi_epi64(c0189451213, a89101112131415); - __m256i d89101112131415 = _mm256_unpackhi_epi64(d0189451213, b89101112131415); - - _mm256_storeu_si256((__m256i *)x, c01234567); - _mm256_storeu_si256((__m256i *)(x + 8), c89101112131415); - _mm256_storeu_si256((__m256i *)y, d01234567); - _mm256_storeu_si256((__m256i *)(y + 8), d89101112131415); -} - -/* offset >= 30 */ -static void -multiminmax2plusmore(int32 *x, int n, int offset) -{ - while(n >= 16) - { - minmax0145891213(x, x + offset); - n -= 16; - x += 16; - } - if(n >= 8) - { - minmax(x, x + offset); - minmax(x + 1, x + 1 + offset); - minmax(x + 4, x + 4 + offset); - minmax(x + 5, x + 5 + offset); - n -= 8; - x += 8; - } - if(n >= 4) - { - minmax(x, x + offset); - minmax(x + 1, x + 1 + offset); - n -= 4; - x += 4; - } - if(n > 0) - { - minmax(x, x + offset); - if(n > 1) - minmax(x + 1, x + 1 + offset); - } -} - -/* sort x0,x1; ... sort x14, x15 */ -static inline void -minmax01through1415(int32 *x) -{ - __m256i a = _mm256_loadu_si256((__m256i *)x); - __m256i b = _mm256_loadu_si256((__m256i *)(x + 8)); - __m256i c = _mm256_unpacklo_epi32(a, b); /* ab0ab1ab4ab5 */ - __m256i d = _mm256_unpackhi_epi32(a, b); /* ab2ab3ab6ab7 */ - __m256i e = _mm256_unpacklo_epi32(c, d); /* a02b02a46b46 */ - __m256i f = _mm256_unpackhi_epi32(c, d); /* a13b13a57b57 */ - __m256i g = _mm256_min_epi32(e, f); /* a02b02a46b46 */ - __m256i h = _mm256_max_epi32(e, f); /* a13b13a57b57 */ - a = _mm256_unpacklo_epi32(g, h); - b = _mm256_unpackhi_epi32(g, h); - _mm256_storeu_si256((__m256i *)x, a); - _mm256_storeu_si256((__m256i *)(x + 8), b); -} - -/* sort x0,x1; sort x2,x3; sort x4,x5; sort x6,x7 */ -static inline void -minmax01234567(int32 *x) -{ - __m256i a = _mm256_loadu_si256((__m256i *)x); - __m256i b = _mm256_shuffle_epi32(a, 0xb1); - __m256i c = _mm256_cmpgt_epi32(a, b); - c = _mm256_shuffle_epi32(c, 0xa0); - __m256i abc = c & (a ^ b); - a ^= abc; - _mm256_storeu_si256((__m256i *)x, a); -} - -static void -multiminmax1plus1(int32 *x, int n) -{ - while(n >= 16) - { - minmax01through1415(x); - n -= 16; - x += 16; - } - if(n >= 8) - { - minmax01234567(x); - n -= 8; - x += 8; - } - if(n >= 4) - { - minmax(x, x + 1); - minmax(x + 2, x + 3); - n -= 4; - x += 4; - } - if(n >= 2) - { - minmax(x, x + 1); - n -= 2; - x += 2; - } - if(n > 0) - minmax(x, x + 1); -} - -static void -multiminmax1(int32 *x, int n, int offset) -{ - while(n >= 16) - { - minmax(x, x + offset); - minmax(x + 2, x + 2 + offset); - minmax(x + 4, x + 4 + offset); - minmax(x + 6, x + 6 + offset); - minmax(x + 8, x + 8 + offset); - minmax(x + 10, x + 10 + offset); - minmax(x + 12, x + 12 + offset); - minmax(x + 14, x + 14 + offset); - n -= 16; - x += 16; - } - if(n >= 8) - { - minmax(x, x + offset); - minmax(x + 2, x + 2 + offset); - minmax(x + 4, x + 4 + offset); - minmax(x + 6, x + 6 + offset); - n -= 8; - x += 8; - } - if(n >= 4) - { - minmax(x, x + offset); - minmax(x + 2, x + 2 + offset); - n -= 4; - x += 4; - } - if(n >= 2) - { - minmax(x, x + offset); - n -= 2; - x += 2; - } - if(n > 0) - minmax(x, x + offset); -} - -/* sort x[i],y[i] for i in 0,2,4,6,8,10,12,14 */ -/* all of x0...x15 and y0...y15 must exist; no aliasing */ -static inline void -minmax02468101214(int32 *x, int32 *y) -{ - __m256i a01234567 = _mm256_loadu_si256((__m256i *)x); - __m256i a89101112131415 = _mm256_loadu_si256((__m256i *)(x + 8)); - __m256i b01234567 = _mm256_loadu_si256((__m256i *)y); - __m256i b89101112131415 = _mm256_loadu_si256((__m256i *)(y + 8)); - - __m256i a0819412513 = _mm256_unpacklo_epi32(a01234567, a89101112131415); - __m256i a210311614715 = _mm256_unpackhi_epi32(a01234567, a89101112131415); - __m256i a02810461214 = _mm256_unpacklo_epi32(a0819412513, a210311614715); - __m256i a13911571315 = _mm256_unpackhi_epi32(a0819412513, a210311614715); - - __m256i b0819412513 = _mm256_unpacklo_epi32(b01234567, b89101112131415); - __m256i b210311614715 = _mm256_unpackhi_epi32(b01234567, b89101112131415); - __m256i b02810461214 = _mm256_unpacklo_epi32(b0819412513, b210311614715); - __m256i b13911571315 = _mm256_unpackhi_epi32(b0819412513, b210311614715); - - __m256i c02810461214 = _mm256_min_epi32(a02810461214, b02810461214); - __m256i d02810461214 = _mm256_max_epi32(a02810461214, b02810461214); - - __m256i c01234567 = _mm256_unpacklo_epi32(c02810461214, a13911571315); - __m256i c89101112131415 = _mm256_unpackhi_epi32(c02810461214, a13911571315); - __m256i d01234567 = _mm256_unpacklo_epi32(d02810461214, b13911571315); - __m256i d89101112131415 = _mm256_unpackhi_epi32(d02810461214, b13911571315); - - _mm256_storeu_si256((__m256i *)x, c01234567); - _mm256_storeu_si256((__m256i *)(x + 8), c89101112131415); - _mm256_storeu_si256((__m256i *)y, d01234567); - _mm256_storeu_si256((__m256i *)(y + 8), d89101112131415); -} - -/* assumes offset >= 31 */ -static void -multiminmax1plusmore(int32 *x, int n, int offset) -{ - while(n >= 16) - { - minmax02468101214(x, x + offset); - n -= 16; - x += 16; - } - if(n >= 8) - { - minmax(x, x + offset); - minmax(x + 2, x + 2 + offset); - minmax(x + 4, x + 4 + offset); - minmax(x + 6, x + 6 + offset); - n -= 8; - x += 8; - } - if(n >= 4) - { - minmax(x, x + offset); - minmax(x + 2, x + 2 + offset); - n -= 4; - x += 4; - } - if(n >= 2) - { - minmax(x, x + offset); - n -= 2; - x += 2; - } - if(n > 0) - minmax(x, x + offset); -} - -/* sort x0,y0; sort x1,y1; ...; sort x7,y7 */ -static inline void -minmax8(int32 *x, int32 *y) -{ - __m256i a = _mm256_loadu_si256((__m256i *)x); - __m256i b = _mm256_loadu_si256((__m256i *)y); - _mm256_storeu_si256((__m256i *)x, _mm256_min_epi32(a, b)); - _mm256_storeu_si256((__m256i *)y, _mm256_max_epi32(a, b)); -} - -/* assumes p >= 8; implies offset >= 8 */ -static void -multiminmax_atleast8(int p, int32 *x, int n, int offset) -{ - int i; - while(n >= 2 * p) - { - for(i = 0; i < p; i += 8) - minmax8(x + i, x + i + offset); - n -= 2 * p; - x += 2 * p; - } - for(i = 0; i + 8 <= n; i += 8) - { - if(i & p) - return; - minmax8(x + i, x + i + offset); - } - for(; i < n; ++i) - { - if(i & p) - return; - minmax(x + i, x + i + offset); - } -} - -/* sort x0,y0; sort x1,y1; sort x2,y2; sort x3,y3 */ -static inline void -minmax4(int32 *x, int32 *y) -{ - __m128i a = _mm_loadu_si128((__m128i *)x); - __m128i b = _mm_loadu_si128((__m128i *)y); - _mm_storeu_si128((__m128i *)x, _mm_min_epi32(a, b)); - _mm_storeu_si128((__m128i *)y, _mm_max_epi32(a, b)); -} - -static void -multiminmax4(int32 *x, int n, int offset) -{ - int i; - while(n >= 8) - { - minmax4(x, x + offset); - n -= 8; - x += 8; - } - if(n >= 4) - minmax4(x, x + offset); - else - for(i = 0; i < n; ++i) - minmax(x + i, x + i + offset); -} - -void -int32_sort(int32 *x, int n) -{ - int top, p, q; - - if(n < 2) - return; - top = 1; - while(top < n - top) - top += top; - - for(p = top; p >= 8; p >>= 1) - { - multiminmax_atleast8(p, x, n - p, p); - for(q = top; q > p; q >>= 1) - multiminmax_atleast8(p, x + p, n - q, q - p); - } - if(p >= 4) - { - multiminmax4(x, n - 4, 4); - for(q = top; q > 4; q >>= 1) - multiminmax4(x + 4, n - q, q - 4); - } - if(p >= 2) - { - multiminmax2plus2(x, n - 2); - for(q = top; q >= 32; q >>= 1) - multiminmax2plusmore(x + 2, n - q, q - 2); - if(q >= 16) - multiminmax2plus14(x + 2, n - 16); - if(q >= 8) - multiminmax2plus6(x + 2, n - 8); - if(q >= 4) - multiminmax2plus2(x + 2, n - 4); - } - multiminmax1plus1(x, n - 1); - for(q = top; q >= 32; q >>= 1) - multiminmax1plusmore(x + 1, n - q, q - 1); - if(q >= 16) - multiminmax1(x + 1, n - 16, 15); - if(q >= 8) - multiminmax1(x + 1, n - 8, 7); - if(q >= 4) - multiminmax1(x + 1, n - 4, 3); - if(q >= 2) - multiminmax1plus1(x + 1, n - 2); -} -#endif diff --git a/crypto/libntrup/src/avx/int32_sort.h b/crypto/libntrup/src/avx/int32_sort.h deleted file mode 100644 index ea0cb05e50..0000000000 --- a/crypto/libntrup/src/avx/int32_sort.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef int32_sort_h -#define int32_sort_h - -#include - -#define int32_sort crypto_kem_sntrup4591761_avx_int32_sort -extern void -int32_sort(crypto_int32 *, int); - -#endif diff --git a/crypto/libntrup/src/avx/keypair.c b/crypto/libntrup/src/avx/keypair.c deleted file mode 100644 index 32aed4ac0a..0000000000 --- a/crypto/libntrup/src/avx/keypair.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include "modq.h" -#include "params.h" -#include "r3.h" -#include "small.h" -#include "rq.h" -#include - -#if crypto_kem_PUBLICKEYBYTES != rq_encode_len -#error "crypto_kem_PUBLICKEYBYTES must match rq_encode_len" -#endif -#if crypto_kem_SECRETKEYBYTES != rq_encode_len + 2 * small_encode_len -#error \ - "crypto_kem_SECRETKEYBYTES must match rq_encode_len + 2 * small_encode_len" -#endif - -#ifndef __AVX2__ -#error "This file requires compilation with AVX2 support" -#endif - -int -crypto_kem_keypair_avx2(unsigned char *pk, unsigned char *sk) -{ - small g[768]; - small grecip[768]; - small f[768]; - modq f3recip[768]; - modq h[768]; - - do - small_random(g); - while(r3_recip(grecip, g) != 0); - - small_random_weightw(f); - rq_recip3(f3recip, f); - - rq_mult(h, f3recip, g); - - rq_encode(pk, h); - small_encode(sk, f); - small_encode(sk + small_encode_len, grecip); - memcpy(sk + 2 * small_encode_len, pk, rq_encode_len); - - return 0; -} diff --git a/crypto/libntrup/src/avx/mod3.h b/crypto/libntrup/src/avx/mod3.h deleted file mode 100644 index 97ec3b55fa..0000000000 --- a/crypto/libntrup/src/avx/mod3.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef mod3_h -#define mod3_h - -#include "small.h" -#include - -/* -1 if x is nonzero, 0 otherwise */ -static inline int -mod3_nonzero_mask(small x) -{ - return -x * x; -} - -/* input between -100000 and 100000 */ -/* output between -1 and 1 */ -static inline small -mod3_freeze(crypto_int32 a) -{ - a -= 3 * ((10923 * a) >> 15); - a -= 3 * ((89478485 * a + 134217728) >> 28); - return a; -} - -static inline small -mod3_minusproduct(small a, small b, small c) -{ - crypto_int32 A = a; - crypto_int32 B = b; - crypto_int32 C = c; - return mod3_freeze(A - B * C); -} - -static inline small -mod3_plusproduct(small a, small b, small c) -{ - crypto_int32 A = a; - crypto_int32 B = b; - crypto_int32 C = c; - return mod3_freeze(A + B * C); -} - -static inline small -mod3_product(small a, small b) -{ - return a * b; -} - -static inline small -mod3_sum(small a, small b) -{ - crypto_int32 A = a; - crypto_int32 B = b; - return mod3_freeze(A + B); -} - -static inline small -mod3_reciprocal(small a1) -{ - return a1; -} - -static inline small -mod3_quotient(small num, small den) -{ - return mod3_product(num, mod3_reciprocal(den)); -} - -#endif diff --git a/crypto/libntrup/src/avx/modq.h b/crypto/libntrup/src/avx/modq.h deleted file mode 100644 index ff64884c02..0000000000 --- a/crypto/libntrup/src/avx/modq.h +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef modq_h -#define modq_h - -#include -#include -#include - -typedef crypto_int16 modq; - -/* input between -9000000 and 9000000 */ -/* output between -2295 and 2295 */ -static inline modq -modq_freeze(crypto_int32 a) -{ - a -= 4591 * ((228 * a) >> 20); - a -= 4591 * ((58470 * a + 134217728) >> 28); - return a; -} - -static inline modq -modq_minusproduct(modq a, modq b, modq c) -{ - crypto_int32 A = a; - crypto_int32 B = b; - crypto_int32 C = c; - return modq_freeze(A - B * C); -} - -static inline modq -modq_plusproduct(modq a, modq b, modq c) -{ - crypto_int32 A = a; - crypto_int32 B = b; - crypto_int32 C = c; - return modq_freeze(A + B * C); -} - -static inline modq -modq_product(modq a, modq b) -{ - crypto_int32 A = a; - crypto_int32 B = b; - return modq_freeze(A * B); -} - -static inline modq -modq_square(modq a) -{ - crypto_int32 A = a; - return modq_freeze(A * A); -} - -static inline modq -modq_sum(modq a, modq b) -{ - crypto_int32 A = a; - crypto_int32 B = b; - return modq_freeze(A + B); -} - -static inline modq -modq_reciprocal(modq a1) -{ - modq a2 = modq_square(a1); - modq a3 = modq_product(a2, a1); - modq a4 = modq_square(a2); - modq a8 = modq_square(a4); - modq a16 = modq_square(a8); - modq a32 = modq_square(a16); - modq a35 = modq_product(a32, a3); - modq a70 = modq_square(a35); - modq a140 = modq_square(a70); - modq a143 = modq_product(a140, a3); - modq a286 = modq_square(a143); - modq a572 = modq_square(a286); - modq a1144 = modq_square(a572); - modq a1147 = modq_product(a1144, a3); - modq a2294 = modq_square(a1147); - modq a4588 = modq_square(a2294); - modq a4589 = modq_product(a4588, a1); - return a4589; -} - -static inline modq -modq_quotient(modq num, modq den) -{ - return modq_product(num, modq_reciprocal(den)); -} - -/* -1 if x is nonzero, 0 otherwise */ -static inline int -modq_nonzero_mask(modq x) -{ - crypto_int32 r = (crypto_uint16)x; - r = -r; - r >>= 30; - return r; -} - -#endif diff --git a/crypto/libntrup/src/avx/mult.c b/crypto/libntrup/src/avx/mult.c deleted file mode 100644 index 687acb46ac..0000000000 --- a/crypto/libntrup/src/avx/mult.c +++ /dev/null @@ -1,884 +0,0 @@ -#if __AVX2__ -#include -#include -#include "mod3.h" -#include "rq.h" -#include "r3.h" - -// 32-bit hosts: use compiler builtins and let compiler -// perform register allocation and/or spilling to core -// -// Confirmed working 3/10/18 -despair -// Less than 5% performance hit, -// all in register loads/stores to/from core -#ifndef __amd64__ -#define MULSTEP_gcc(j, h0, h1, h2, h3, h4) \ - gj = g[j]; \ - h0 += f0 * gj; \ - _mm256_storeu_ps((float *)&h[i + j], h0); \ - h1 += f1 * gj; \ - h2 += f2 * gj; \ - h3 += f3 * gj; \ - h4 += f4 * gj; \ - h0 = _mm256_loadu_ps((float *)&h[i + j + 5]); \ - h0 += f5 * gj; - -#define MULSTEP MULSTEP_gcc - -#define MULSTEP_noload(j, h0, h1, h2, h3, h4) \ - gj = g[j]; \ - h0 += gj * f0; \ - _mm256_storeu_ps((float *)&h[i + j], h0); \ - h1 += gj * f1; \ - h2 += gj * f2; \ - h3 += gj * f3; \ - h4 += gj * f4; \ - h0 = gj * f5; - -#define MULSTEP_fromzero(j, h0, h1, h2, h3, h4) \ - gj = g[j]; \ - h0 = gj * f0; \ - _mm256_storeu_ps((float *)&h[i + j], h0); \ - h1 = gj * f1; \ - h2 = gj * f2; \ - h3 = gj * f3; \ - h4 = gj * f4; \ - h0 = gj * f5; -#else -// 64-bit hosts: use inline asm as before -#define MULSTEP MULSTEP_asm -#define MULSTEP_asm(j, h0, h1, h2, h3, h4) \ - gj = g[j]; \ - __asm__( \ - "vfmadd231ps %5,%6,%0 \n\t" \ - "vmovups %0,%12 \n\t" \ - "vmovups %13,%0 \n\t" \ - "vfmadd231ps %5,%7,%1 \n\t" \ - "vfmadd231ps %5,%8,%2 \n\t" \ - "vfmadd231ps %5,%9,%3 \n\t" \ - "vfmadd231ps %5,%10,%4 \n\t" \ - "vfmadd231ps %5,%11,%0 \n\t" \ - : "+x"(h0), "+x"(h1), "+x"(h2), "+x"(h3), "+x"(h4) \ - : "x"(gj), "x"(f0), "x"(f1), "x"(f2), "x"(f3), "x"(f4), "x"(f5), \ - "m"(h[i + j]), "m"(h[i + j + 5])); - -#define MULSTEP_noload(j, h0, h1, h2, h3, h4) \ - gj = g[j]; \ - __asm__( \ - "vfmadd231ps %5,%6,%0 \n\t" \ - "vmovups %0,%12 \n\t" \ - "vfmadd231ps %5,%7,%1 \n\t" \ - "vfmadd231ps %5,%8,%2 \n\t" \ - "vfmadd231ps %5,%9,%3 \n\t" \ - "vfmadd231ps %5,%10,%4 \n\t" \ - "vmulps %5,%11,%0 \n\t" \ - : "+x"(h0), "+x"(h1), "+x"(h2), "+x"(h3), "+x"(h4) \ - : "x"(gj), "x"(f0), "x"(f1), "x"(f2), "x"(f3), "x"(f4), "x"(f5), \ - "m"(h[i + j])); - -#define MULSTEP_fromzero(j, h0, h1, h2, h3, h4) \ - gj = g[j]; \ - __asm__( \ - "vmulps %5,%6,%0 \n\t" \ - "vmovups %0,%12 \n\t" \ - "vmulps %5,%7,%1 \n\t" \ - "vmulps %5,%8,%2 \n\t" \ - "vmulps %5,%9,%3 \n\t" \ - "vmulps %5,%10,%4 \n\t" \ - "vmulps %5,%11,%0 \n\t" \ - : "=&x"(h0), "=&x"(h1), "=&x"(h2), "=&x"(h3), "=&x"(h4) \ - : "x"(gj), "x"(f0), "x"(f1), "x"(f2), "x"(f3), "x"(f4), "x"(f5), \ - "m"(h[i + j])); -#endif - -static inline __m128i -_mm_load_cvtepi8_epi16(const long long *x) -{ - __m128i result; - __asm__("vpmovsxbw %1, %0" : "=x"(result) : "m"(*x)); - return result; -} - -#define v0 _mm256_set1_epi32(0) -#define v0_128 _mm_set1_epi32(0) -#define v7 _mm256_set1_epi16(7) -#define v4591_16 _mm256_set1_epi16(4591) -#define v2296_16 _mm256_set1_epi16(2296) - -#define alpha_32 _mm256_set1_epi32(0x4b400000) -#define alpha_32_128 _mm_set1_epi32(0x4b400000) -#define alpha_float _mm256_set1_ps(12582912.0) - -#define v0_float _mm256_set1_ps(0) -#define v1_float _mm256_set1_ps(1) -#define vm1_float _mm256_set1_ps(-1) -#define vm4591_float _mm256_set1_ps(-4591) -#define recip4591_float \ - _mm256_set1_ps(0.00021781746896101067305597908952297974298) - -static inline __m256 -add(__m256 x, __m256 y) -{ - return x + y; -} - -static inline __m256 -fastadd(__m256 x, __m256 y) -{ - return _mm256_fmadd_ps(y, v1_float, x); -} - -static inline __m256 -fastsub(__m256 x, __m256 y) -{ - return _mm256_fmadd_ps(y, vm1_float, x); -} - -static inline __m256 -reduce(__m256 x) -{ - __m256 q = x * recip4591_float; - q = _mm256_round_ps(q, 8); - return _mm256_fmadd_ps(q, vm4591_float, x); -} - -static inline __m256i -squeeze(__m256i x) -{ - __m256i q = _mm256_mulhrs_epi16(x, v7); - q = _mm256_mullo_epi16(q, v4591_16); - return _mm256_sub_epi16(x, q); -} - -static inline __m256i -squeezeadd16(__m256i x, __m256i y) -{ - __m256i q; - x = _mm256_add_epi16(x, y); - q = _mm256_mulhrs_epi16(x, v7); - q = _mm256_mullo_epi16(q, v4591_16); - return _mm256_sub_epi16(x, q); -} - -static inline __m256i -freeze(__m256i x) -{ - __m256i mask, x2296, x4591; - x4591 = _mm256_add_epi16(x, v4591_16); - mask = _mm256_srai_epi16(x, 15); - x = _mm256_blendv_epi8(x, x4591, mask); - x2296 = _mm256_sub_epi16(x, v2296_16); - mask = _mm256_srai_epi16(x2296, 15); - x4591 = _mm256_sub_epi16(x, v4591_16); - x = _mm256_blendv_epi8(x4591, x, mask); - return x; -} - -/* 24*8*float32 f inputs between -10000 and 10000 */ -/* 24*8*float32 g inputs between -32 and 32 */ -/* 48*8*float32 h outputs between -7680000 and 7680000 */ -static void -mult24x8_float(__m256 h[48], const __m256 f[24], const __m256 g[24]) -{ - int i, j; - __m256 f0, f1, f2, f3, f4, f5, gj, h0, h1, h2, h3, h4; - - i = 0; - f0 = f[i]; - f1 = f[i + 1]; - f2 = f[i + 2]; - f3 = f[i + 3]; - f4 = f[i + 4]; - f5 = f[i + 5]; - MULSTEP_fromzero(0, h0, h1, h2, h3, h4); - for(j = 0; j < 20; j += 5) - { - MULSTEP_noload(j + 1, h1, h2, h3, h4, h0); - MULSTEP_noload(j + 2, h2, h3, h4, h0, h1); - MULSTEP_noload(j + 3, h3, h4, h0, h1, h2); - MULSTEP_noload(j + 4, h4, h0, h1, h2, h3); - MULSTEP_noload(j + 5, h0, h1, h2, h3, h4); - } - MULSTEP_noload(j + 1, h1, h2, h3, h4, h0); - MULSTEP_noload(j + 2, h2, h3, h4, h0, h1); - MULSTEP_noload(j + 3, h3, h4, h0, h1, h2); - - h[i + j + 4] = h4; - h[i + j + 5] = h0; - h[i + j + 6] = h1; - h[i + j + 7] = h2; - h[i + j + 8] = h3; - - for(i = 6; i < 24; i += 6) - { - f0 = f[i]; - f1 = f[i + 1]; - f2 = f[i + 2]; - f3 = f[i + 3]; - f4 = f[i + 4]; - f5 = f[i + 5]; - h0 = h[i]; - h1 = h[i + 1]; - h2 = h[i + 2]; - h3 = h[i + 3]; - h4 = h[i + 4]; - for(j = 0; j < 15; j += 5) - { - MULSTEP(j + 0, h0, h1, h2, h3, h4); - MULSTEP(j + 1, h1, h2, h3, h4, h0); - MULSTEP(j + 2, h2, h3, h4, h0, h1); - MULSTEP(j + 3, h3, h4, h0, h1, h2); - MULSTEP(j + 4, h4, h0, h1, h2, h3); - } - MULSTEP(j + 0, h0, h1, h2, h3, h4); - MULSTEP(j + 1, h1, h2, h3, h4, h0); - MULSTEP(j + 2, h2, h3, h4, h0, h1); - MULSTEP_noload(j + 3, h3, h4, h0, h1, h2); - MULSTEP_noload(j + 4, h4, h0, h1, h2, h3); - MULSTEP_noload(j + 5, h0, h1, h2, h3, h4); - MULSTEP_noload(j + 6, h1, h2, h3, h4, h0); - MULSTEP_noload(j + 7, h2, h3, h4, h0, h1); - MULSTEP_noload(j + 8, h3, h4, h0, h1, h2); - h[i + j + 9] = h4; - h[i + j + 10] = h0; - h[i + j + 11] = h1; - h[i + j + 12] = h2; - h[i + j + 13] = h3; - } - - h[47] = v0_float; -} - -/* 48*8*float32 f inputs between -5000 and 5000 */ -/* 48*8*float32 g inputs between -16 and 16 */ -/* 96*8*float32 h outputs between -3840000 and 3840000 */ -static void -mult48x8_float(__m256 h[96], const __m256 f[48], const __m256 g[48]) -{ - __m256 h01[48]; - __m256 g01[24]; - __m256 *f01 = h01 + 24; - int i; - - for(i = 24; i > 0;) - { - i -= 2; - f01[i] = f[i] + f[i + 24]; - g01[i] = g[i] + g[i + 24]; - f01[i + 1] = f[i + 1] + f[i + 1 + 24]; - g01[i + 1] = g[i + 1] + g[i + 1 + 24]; - } - - mult24x8_float(h, f, g); - mult24x8_float(h + 48, f + 24, g + 24); - mult24x8_float(h01, f01, g01); - - for(i = 0; i < 24; ++i) - { - __m256 h0i = h[i]; - __m256 h0itop = h[i + 24]; - __m256 h1i = h[i + 48]; - __m256 h1itop = h[i + 72]; - __m256 h01i = h01[i]; - __m256 h01itop = h01[i + 24]; - __m256 c = fastsub(h0itop, h1i); - h[i + 24] = c + fastsub(h01i, h0i); - h[i + 48] = fastsub(h01itop, h1itop) - c; - } -} - -/* 96*8*float32 f inputs between -2500 and 2500 */ -/* 96*8*float32 g inputs between -8 and 8 */ -/* 192*8*float32 h outputs between -1920000 and 1920000 */ -static void -mult96x8_float(__m256 h[192], const __m256 f[96], const __m256 g[96]) -{ - __m256 h01[96]; - __m256 g01[48]; - __m256 *f01 = h01 + 48; - int i; - - for(i = 48; i > 0;) - { - i -= 4; - f01[i] = f[i] + f[i + 48]; - g01[i] = g[i] + g[i + 48]; - f01[i + 1] = f[i + 1] + f[i + 1 + 48]; - g01[i + 1] = g[i + 1] + g[i + 1 + 48]; - f01[i + 2] = f[i + 2] + f[i + 2 + 48]; - g01[i + 2] = g[i + 2] + g[i + 2 + 48]; - f01[i + 3] = f[i + 3] + f[i + 3 + 48]; - g01[i + 3] = g[i + 3] + g[i + 3 + 48]; - } - - mult48x8_float(h, f, g); - mult48x8_float(h + 96, f + 48, g + 48); - mult48x8_float(h01, f01, g01); - - for(i = 0; i < 48; ++i) - { - __m256 h0i = h[i]; - __m256 h0itop = h[i + 48]; - __m256 h1i = h[i + 96]; - __m256 h1itop = h[i + 144]; - __m256 h01i = h01[i]; - __m256 h01itop = h01[i + 48]; - __m256 c = fastsub(h0itop, h1i); - h[i + 48] = c + fastsub(h01i, h0i); - h[i + 96] = fastsub(h01itop, h1itop) - c; - } -} - -/* 96*16*int16 f inputs between -2500 and 2500 */ -/* 96*(16*int8 stored in 32*int8) g inputs between -8 and 8 */ -/* 192*16*int16 h outputs between -2400 and 2400 */ -static void -mult96x16(__m256i * h, const __m256i * f, const __m256i * g) -{ - __m256 hfloat[192]; - __m256 gfloat[96]; - __m256 *ffloat = hfloat + 96; - int i, p; - - for(p = 0; p < 2; ++p) - { - for(i = 96; i > 0;) - { - i -= 2; - __m256i fi = - _mm256_cvtepi16_epi32(_mm_loadu_si128(p + (const __m128i *)&f[i])); - __m256i gi = _mm256_cvtepi16_epi32( - _mm_load_cvtepi8_epi16(p + (const long long *)&g[i])); - __m256 storage; - *(__m256i *)&storage = _mm256_add_epi32(fi, alpha_32); - ffloat[i] = storage - alpha_float; - *(__m256i *)&storage = _mm256_add_epi32(gi, alpha_32); - gfloat[i] = storage - alpha_float; - fi = _mm256_cvtepi16_epi32( - _mm_loadu_si128(p + (const __m128i *)&f[i + 1])); - gi = _mm256_cvtepi16_epi32( - _mm_load_cvtepi8_epi16(p + (const long long *)&g[i + 1])); - *(__m256i *)&storage = _mm256_add_epi32(fi, alpha_32); - ffloat[i + 1] = storage - alpha_float; - *(__m256i *)&storage = _mm256_add_epi32(gi, alpha_32); - gfloat[i + 1] = storage - alpha_float; - } - mult96x8_float(hfloat, ffloat, gfloat); - for(i = 192; i > 0;) - { - __m128i h0, h1; - i -= 4; - hfloat[i] = add(alpha_float, reduce(hfloat[i])); - hfloat[i + 1] = fastadd(alpha_float, reduce(hfloat[i + 1])); - hfloat[i + 2] = add(alpha_float, reduce(hfloat[i + 2])); - hfloat[i + 3] = fastadd(alpha_float, reduce(hfloat[i + 3])); - h0 = 0 [(__m128i *)&hfloat[i]]; - h0 = _mm_sub_epi32(h0, alpha_32_128); - h1 = 1 [(__m128i *)&hfloat[i]]; - h1 = _mm_sub_epi32(h1, alpha_32_128); - _mm_storeu_si128(p + (__m128i *)&h[i], _mm_packs_epi32(h0, h1)); - h0 = 0 [(__m128i *)&hfloat[i + 1]]; - h0 = _mm_sub_epi32(h0, alpha_32_128); - h1 = 1 [(__m128i *)&hfloat[i + 1]]; - h1 = _mm_sub_epi32(h1, alpha_32_128); - _mm_storeu_si128(p + (__m128i *)&h[i + 1], _mm_packs_epi32(h0, h1)); - h0 = 0 [(__m128i *)&hfloat[i + 2]]; - h0 = _mm_sub_epi32(h0, alpha_32_128); - h1 = 1 [(__m128i *)&hfloat[i + 2]]; - h1 = _mm_sub_epi32(h1, alpha_32_128); - _mm_storeu_si128(p + (__m128i *)&h[i + 2], _mm_packs_epi32(h0, h1)); - h0 = 0 [(__m128i *)&hfloat[i + 3]]; - h0 = _mm_sub_epi32(h0, alpha_32_128); - h1 = 1 [(__m128i *)&hfloat[i + 3]]; - h1 = _mm_sub_epi32(h1, alpha_32_128); - _mm_storeu_si128(p + (__m128i *)&h[i + 3], _mm_packs_epi32(h0, h1)); - } - } -} - -/* int16 i of output x[j] is int16 j of input x[i] */ -static void -transpose16(__m256i x[16]) -{ - static const int rev[4] = {0, 4, 2, 6}; - int i; - __m256i y[16]; - - for(i = 0; i < 16; i += 4) - { - __m256i a0 = x[i]; - __m256i a1 = x[i + 1]; - __m256i a2 = x[i + 2]; - __m256i a3 = x[i + 3]; - __m256i b0 = _mm256_unpacklo_epi16(a0, a1); - __m256i b1 = _mm256_unpackhi_epi16(a0, a1); - __m256i b2 = _mm256_unpacklo_epi16(a2, a3); - __m256i b3 = _mm256_unpackhi_epi16(a2, a3); - __m256i c0 = _mm256_unpacklo_epi32(b0, b2); - __m256i c2 = _mm256_unpackhi_epi32(b0, b2); - __m256i c1 = _mm256_unpacklo_epi32(b1, b3); - __m256i c3 = _mm256_unpackhi_epi32(b1, b3); - y[i] = c0; - y[i + 2] = c2; - y[i + 1] = c1; - y[i + 3] = c3; - } - for(i = 0; i < 4; ++i) - { - int r = rev[i]; - __m256i c0 = y[i]; - __m256i c4 = y[i + 4]; - __m256i c8 = y[i + 8]; - __m256i c12 = y[i + 12]; - __m256i d0 = _mm256_unpacklo_epi64(c0, c4); - __m256i d4 = _mm256_unpackhi_epi64(c0, c4); - __m256i d8 = _mm256_unpacklo_epi64(c8, c12); - __m256i d12 = _mm256_unpackhi_epi64(c8, c12); - __m256i e0 = _mm256_permute2x128_si256(d0, d8, 0x20); - __m256i e8 = _mm256_permute2x128_si256(d0, d8, 0x31); - __m256i e4 = _mm256_permute2x128_si256(d4, d12, 0x20); - __m256i e12 = _mm256_permute2x128_si256(d4, d12, 0x31); - x[r] = e0; - x[r + 8] = e8; - x[r + 1] = e4; - x[r + 9] = e12; - } -} - -/* byte i of output x[j] is byte j of input x[i] */ -static void -transpose32(__m256i x[32]) -{ - static const int rev[4] = {0, 8, 4, 12}; - int i; - __m256i y[32]; - - for(i = 0; i < 32; i += 4) - { - __m256i a0 = x[i]; - __m256i a1 = x[i + 1]; - __m256i a2 = x[i + 2]; - __m256i a3 = x[i + 3]; - __m256i b0 = _mm256_unpacklo_epi8(a0, a1); - __m256i b1 = _mm256_unpackhi_epi8(a0, a1); - __m256i b2 = _mm256_unpacklo_epi8(a2, a3); - __m256i b3 = _mm256_unpackhi_epi8(a2, a3); - __m256i c0 = _mm256_unpacklo_epi16(b0, b2); - __m256i c2 = _mm256_unpackhi_epi16(b0, b2); - __m256i c1 = _mm256_unpacklo_epi16(b1, b3); - __m256i c3 = _mm256_unpackhi_epi16(b1, b3); - y[i] = c0; - y[i + 2] = c2; - y[i + 1] = c1; - y[i + 3] = c3; - } - for(i = 0; i < 4; ++i) - { - int r = rev[i]; - __m256i c0 = y[i]; - __m256i c8 = y[i + 8]; - __m256i c16 = y[i + 16]; - __m256i c24 = y[i + 24]; - __m256i c4 = y[i + 4]; - __m256i c12 = y[i + 12]; - __m256i c20 = y[i + 20]; - __m256i c28 = y[i + 28]; - __m256i d0 = _mm256_unpacklo_epi32(c0, c4); - __m256i d4 = _mm256_unpackhi_epi32(c0, c4); - __m256i d8 = _mm256_unpacklo_epi32(c8, c12); - __m256i d12 = _mm256_unpackhi_epi32(c8, c12); - __m256i d16 = _mm256_unpacklo_epi32(c16, c20); - __m256i d20 = _mm256_unpackhi_epi32(c16, c20); - __m256i d24 = _mm256_unpacklo_epi32(c24, c28); - __m256i d28 = _mm256_unpackhi_epi32(c24, c28); - __m256i e0 = _mm256_unpacklo_epi64(d0, d8); - __m256i e8 = _mm256_unpackhi_epi64(d0, d8); - __m256i e16 = _mm256_unpacklo_epi64(d16, d24); - __m256i e24 = _mm256_unpackhi_epi64(d16, d24); - __m256i e4 = _mm256_unpacklo_epi64(d4, d12); - __m256i e12 = _mm256_unpackhi_epi64(d4, d12); - __m256i e20 = _mm256_unpacklo_epi64(d20, d28); - __m256i e28 = _mm256_unpackhi_epi64(d20, d28); - __m256i f0 = _mm256_permute2x128_si256(e0, e16, 0x20); - __m256i f16 = _mm256_permute2x128_si256(e0, e16, 0x31); - __m256i f8 = _mm256_permute2x128_si256(e8, e24, 0x20); - __m256i f24 = _mm256_permute2x128_si256(e8, e24, 0x31); - __m256i f4 = _mm256_permute2x128_si256(e4, e20, 0x20); - __m256i f20 = _mm256_permute2x128_si256(e4, e20, 0x31); - __m256i f12 = _mm256_permute2x128_si256(e12, e28, 0x20); - __m256i f28 = _mm256_permute2x128_si256(e12, e28, 0x31); - x[r] = f0; - x[r + 16] = f16; - x[r + 1] = f8; - x[r + 17] = f24; - x[r + 2] = f4; - x[r + 18] = f20; - x[r + 3] = f12; - x[r + 19] = f28; - } -} - -/* 48*16*int16 f inputs between -2295 and 2295 */ -/* 24*32*int8 g inputs between -1 and 1 */ -/* 96*16*int16 h outputs between -2295 and 2295 */ -static void -mult768_mix2_m256i(__m256i h[96], const __m256i f[48], const __m256i g[24]) -{ - __m256i hkara[24][16]; - __m256i gkara[3][32]; -#define fkara hkara - int i; - - for(i = 6; i-- > 0;) - { - __m256i f0, f1, f2, f3, f4, f5, f6, f7; - __m256i f01, f23, f45, f67; - __m256i f02, f46, f04, f26, f0426; - __m256i f13, f57, f15, f37, f1537; - __m256i f0213, f4657, f04261537, f0415, f2637; - - f0 = _mm256_loadu_si256(&f[i + 0]); - f1 = _mm256_loadu_si256(&f[i + 6]); - f2 = _mm256_loadu_si256(&f[i + 12]); - f3 = _mm256_loadu_si256(&f[i + 18]); - f4 = _mm256_loadu_si256(&f[i + 24]); - f5 = _mm256_loadu_si256(&f[i + 30]); - f6 = _mm256_loadu_si256(&f[i + 36]); - f7 = _mm256_loadu_si256(&f[i + 42]); - f01 = squeezeadd16(f0, f1); - fkara[i][8] = f01; - f23 = squeezeadd16(f2, f3); - fkara[i][9] = f23; - f45 = squeezeadd16(f4, f5); - fkara[i][10] = f45; - f67 = squeezeadd16(f6, f7); - fkara[i][11] = f67; - - fkara[i][0] = f0; - fkara[i][2] = f2; - fkara[i][4] = f4; - fkara[i][6] = f6; - - f02 = squeezeadd16(f0, f2); - fkara[i + 6][0] = f02; - f04 = squeezeadd16(f0, f4); - fkara[i + 6][6] = f04; - f46 = squeezeadd16(f4, f6); - fkara[i + 6][3] = f46; - f26 = squeezeadd16(f2, f6); - fkara[i + 6][8] = f26; - - fkara[i][1] = f1; - fkara[i][3] = f3; - fkara[i][5] = f5; - fkara[i][7] = f7; - - f13 = squeezeadd16(f1, f3); - fkara[i + 6][1] = f13; - f15 = squeezeadd16(f1, f5); - fkara[i + 6][7] = f15; - f57 = squeezeadd16(f5, f7); - fkara[i + 6][4] = f57; - f37 = squeezeadd16(f3, f7); - fkara[i + 6][9] = f37; - - f0426 = squeezeadd16(f04, f26); - fkara[i + 6][12] = f0426; - f1537 = squeezeadd16(f15, f37); - fkara[i + 6][13] = f1537; - f0213 = squeezeadd16(f02, f13); - fkara[i + 6][2] = f0213; - f4657 = squeezeadd16(f46, f57); - fkara[i + 6][5] = f4657; - f0415 = squeezeadd16(f04, f15); - fkara[i + 6][10] = f0415; - f2637 = squeezeadd16(f26, f37); - fkara[i + 6][11] = f2637; - f04261537 = squeezeadd16(f0426, f1537); - fkara[i + 6][14] = f04261537; - - fkara[i][12] = v0; - fkara[i][13] = v0; - fkara[i][14] = v0; - fkara[i][15] = v0; - fkara[i + 6][15] = v0; - } - - for(i = 3; i-- > 0;) - { - __m256i g0, g1, g2, g3, g4, g5, g6, g7; - __m256i g01, g23, g45, g67; - __m256i g02, g46, g04, g26, g0426; - __m256i g13, g57, g15, g37, g1537; - __m256i g0213, g4657, g04261537, g0415, g2637; - - g0 = _mm256_loadu_si256(&g[i + 0]); - g1 = _mm256_loadu_si256(&g[i + 3]); - g2 = _mm256_loadu_si256(&g[i + 6]); - g3 = _mm256_loadu_si256(&g[i + 9]); - g4 = _mm256_loadu_si256(&g[i + 12]); - g5 = _mm256_loadu_si256(&g[i + 15]); - g6 = _mm256_loadu_si256(&g[i + 18]); - g7 = _mm256_loadu_si256(&g[i + 21]); - g01 = _mm256_add_epi8(g0, g1); - gkara[i][8] = g01; - g23 = _mm256_add_epi8(g2, g3); - gkara[i][9] = g23; - g45 = _mm256_add_epi8(g4, g5); - gkara[i][10] = g45; - g67 = _mm256_add_epi8(g6, g7); - gkara[i][11] = g67; - - gkara[i][0] = g0; - gkara[i][2] = g2; - gkara[i][4] = g4; - gkara[i][6] = g6; - - g02 = _mm256_add_epi8(g0, g2); - gkara[i][16] = g02; - g04 = _mm256_add_epi8(g0, g4); - gkara[i][22] = g04; - g46 = _mm256_add_epi8(g4, g6); - gkara[i][19] = g46; - g26 = _mm256_add_epi8(g2, g6); - gkara[i][24] = g26; - - gkara[i][1] = g1; - gkara[i][3] = g3; - gkara[i][5] = g5; - gkara[i][7] = g7; - - g13 = _mm256_add_epi8(g1, g3); - gkara[i][17] = g13; - g15 = _mm256_add_epi8(g1, g5); - gkara[i][23] = g15; - g57 = _mm256_add_epi8(g5, g7); - gkara[i][20] = g57; - g37 = _mm256_add_epi8(g3, g7); - gkara[i][25] = g37; - - g0426 = _mm256_add_epi8(g04, g26); - gkara[i][28] = g0426; - g1537 = _mm256_add_epi8(g15, g37); - gkara[i][29] = g1537; - g0213 = _mm256_add_epi8(g02, g13); - gkara[i][18] = g0213; - g4657 = _mm256_add_epi8(g46, g57); - gkara[i][21] = g4657; - g0415 = _mm256_add_epi8(g04, g15); - gkara[i][26] = g0415; - g2637 = _mm256_add_epi8(g26, g37); - gkara[i][27] = g2637; - g04261537 = _mm256_add_epi8(g0426, g1537); - gkara[i][30] = g04261537; - - gkara[i][12] = v0; - gkara[i][13] = v0; - gkara[i][14] = v0; - gkara[i][15] = v0; - gkara[i][31] = v0; - } - - for(i = 12; i-- > 0;) - transpose16(fkara[i]); - for(i = 3; i-- > 0;) - transpose32(gkara[i]); - - mult96x16(hkara[12], fkara[6], (__m256i *)(1 + (__m128i *)gkara)); - mult96x16(hkara[0], fkara[0], gkara[0]); - - for(i = 24; i-- > 0;) - transpose16(hkara[i]); - - for(i = 6; i-- > 0;) - { - __m256i h0, h1, h2, h3, h4, h5, h6, h7, h8, h9; - __m256i h10, h11, h12, h13, h14, h15, h16, h17, h18, h19; - __m256i h20, h21, h22, h23; - __m256i h32, h33, h34, h35, h36, h37, h38, h39; - __m256i h40, h41, h42, h43, h44, h45, h46, h47, h48, h49; - __m256i h50, h51, h52, h53, h54, h55, h56, h57, h58, h59; - __m256i h60, h61; - __m256i c; - -#define COMBINE(h0, h1, h2, h3, x0, x1) \ - c = _mm256_sub_epi16(h1, h2); \ - h1 = _mm256_sub_epi16(_mm256_add_epi16(c, x0), h0); \ - h2 = _mm256_sub_epi16(x1, _mm256_add_epi16(c, h3)); \ - h1 = squeeze(h1); \ - h2 = squeeze(h2); - - h56 = hkara[i + 12][12]; - h57 = hkara[i + 18][12]; - h58 = hkara[i + 12][13]; - h59 = hkara[i + 18][13]; - h60 = hkara[i + 12][14]; - h61 = hkara[i + 18][14]; - COMBINE(h56, h57, h58, h59, h60, h61) - - h44 = hkara[i + 12][6]; - h45 = hkara[i + 18][6]; - h46 = hkara[i + 12][7]; - h47 = hkara[i + 18][7]; - h52 = hkara[i + 12][10]; - h53 = hkara[i + 18][10]; - COMBINE(h44, h45, h46, h47, h52, h53) - - h48 = hkara[i + 12][8]; - h49 = hkara[i + 18][8]; - h50 = hkara[i + 12][9]; - h51 = hkara[i + 18][9]; - h54 = hkara[i + 12][11]; - h55 = hkara[i + 18][11]; - COMBINE(h48, h49, h50, h51, h54, h55) - COMBINE(h44, h46, h48, h50, h56, h58) - COMBINE(h45, h47, h49, h51, h57, h59) - - h0 = hkara[i][0]; - h1 = hkara[i + 6][0]; - h2 = hkara[i][1]; - h3 = hkara[i + 6][1]; - h16 = hkara[i][8]; - h17 = hkara[i + 6][8]; - COMBINE(h0, h1, h2, h3, h16, h17) - - h4 = hkara[i][2]; - h5 = hkara[i + 6][2]; - h6 = hkara[i][3]; - h7 = hkara[i + 6][3]; - h18 = hkara[i][9]; - h19 = hkara[i + 6][9]; - COMBINE(h4, h5, h6, h7, h18, h19) - - h32 = hkara[i + 12][0]; - h33 = hkara[i + 18][0]; - h34 = hkara[i + 12][1]; - h35 = hkara[i + 18][1]; - h36 = hkara[i + 12][2]; - h37 = hkara[i + 18][2]; - COMBINE(h32, h33, h34, h35, h36, h37) - COMBINE(h1, h3, h5, h7, h33, h35) - COMBINE(h0, h2, h4, h6, h32, h34) - - h8 = hkara[i][4]; - h9 = hkara[i + 6][4]; - h10 = hkara[i][5]; - h11 = hkara[i + 6][5]; - h20 = hkara[i][10]; - h21 = hkara[i + 6][10]; - COMBINE(h8, h9, h10, h11, h20, h21) - - h12 = hkara[i][6]; - h13 = hkara[i + 6][6]; - h14 = hkara[i][7]; - h15 = hkara[i + 6][7]; - h22 = hkara[i][11]; - h23 = hkara[i + 6][11]; - COMBINE(h12, h13, h14, h15, h22, h23) - - h38 = hkara[i + 12][3]; - h39 = hkara[i + 18][3]; - h40 = hkara[i + 12][4]; - h41 = hkara[i + 18][4]; - h42 = hkara[i + 12][5]; - h43 = hkara[i + 18][5]; - COMBINE(h38, h39, h40, h41, h42, h43) - COMBINE(h8, h10, h12, h14, h38, h40) - COMBINE(h9, h11, h13, h15, h39, h41) - - COMBINE(h0, h4, h8, h12, h44, h48) - h0 = freeze(h0); - h4 = freeze(h4); - h8 = freeze(h8); - h12 = freeze(h12); - _mm256_storeu_si256(&h[i + 0], h0); - _mm256_storeu_si256(&h[i + 24], h4); - _mm256_storeu_si256(&h[i + 48], h8); - _mm256_storeu_si256(&h[i + 72], h12); - - COMBINE(h1, h5, h9, h13, h45, h49) - h1 = freeze(h1); - h5 = freeze(h5); - h9 = freeze(h9); - h13 = freeze(h13); - _mm256_storeu_si256(&h[i + 6], h1); - _mm256_storeu_si256(&h[i + 30], h5); - _mm256_storeu_si256(&h[i + 54], h9); - _mm256_storeu_si256(&h[i + 78], h13); - - COMBINE(h2, h6, h10, h14, h46, h50) - h2 = freeze(h2); - h6 = freeze(h6); - h10 = freeze(h10); - h14 = freeze(h14); - _mm256_storeu_si256(&h[i + 12], h2); - _mm256_storeu_si256(&h[i + 36], h6); - _mm256_storeu_si256(&h[i + 60], h10); - _mm256_storeu_si256(&h[i + 84], h14); - - COMBINE(h3, h7, h11, h15, h47, h51) - h3 = freeze(h3); - h7 = freeze(h7); - h11 = freeze(h11); - h15 = freeze(h15); - _mm256_storeu_si256(&h[i + 18], h3); - _mm256_storeu_si256(&h[i + 42], h7); - _mm256_storeu_si256(&h[i + 66], h11); - _mm256_storeu_si256(&h[i + 90], h15); - } -} - -#define p 761 - -/* 761 f inputs between -2295 and 2295 */ -/* 761 g inputs between -1 and 1 */ -/* 761 h outputs between -2295 and 2295 */ -void -rq_mult(modq *h, const modq *f, const small *g) -{ - __m256i fgvec[96]; - modq *fg; - int i; - - mult768_mix2_m256i(fgvec, (__m256i *)f, (__m256i *)g); - fg = (modq *)fgvec; - - h[0] = modq_freeze(fg[0] + fg[p]); - for(i = 1; i < 9; ++i) - h[i] = modq_freeze(fg[i] + fg[i + p - 1] + fg[i + p]); - for(i = 9; i < 761; i += 16) - { - __m256i fgi = _mm256_loadu_si256((__m256i *)&fg[i]); - __m256i fgip = _mm256_loadu_si256((__m256i *)&fg[i + p]); - __m256i fgip1 = _mm256_loadu_si256((__m256i *)&fg[i + p - 1]); - __m256i x = _mm256_add_epi16(fgi, _mm256_add_epi16(fgip, fgip1)); - x = freeze(squeeze(x)); - _mm256_storeu_si256((__m256i *)&h[i], x); - } - for(i = 761; i < 768; ++i) - h[i] = 0; -} - -void -r3_mult(small *h, const small *f, const small *g) -{ - __m256i fgvec[96]; - __m256i fvec[48]; - modq *fg; - int i; - - memset(fvec, 0, sizeof fvec); - - for(i = 0; i < 761; ++i) - i[(modq *)fvec] = f[i]; - - mult768_mix2_m256i(fgvec, fvec, (__m256i *)g); - fg = (modq *)fgvec; - - h[0] = mod3_freeze(fg[0] + fg[p]); - for(i = 1; i < p; ++i) - h[i] = mod3_freeze(fg[i] + fg[i + p - 1] + fg[i + p]); - for(i = p; i < 768; ++i) - h[i] = 0; -} -#endif diff --git a/crypto/libntrup/src/avx/params.h b/crypto/libntrup/src/avx/params.h deleted file mode 100644 index 655e6ec095..0000000000 --- a/crypto/libntrup/src/avx/params.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef params_h -#define params_h - -#define q 4591 -/* XXX: also built into modq in various ways */ - -#define qshift 2295 -#define p 761 -#define w 286 - -#define rq_encode_len 1218 -#define small_encode_len 191 - -#endif diff --git a/crypto/libntrup/src/avx/r3.h b/crypto/libntrup/src/avx/r3.h deleted file mode 100644 index aa0b036074..0000000000 --- a/crypto/libntrup/src/avx/r3.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef r3_h -#define r3_h - -#include "small.h" - -#define r3_mult crypto_kem_sntrup4591761_avx_r3_mult -extern void -r3_mult(small *, const small *, const small *); - -#define r3_recip crypto_kem_sntrup4591761_avx_r3_recip -extern int -r3_recip(small *, const small *); - -#define r3_weightw_mask crypto_kem_sntrup4591761_avx_r3_weightw_mask -extern int -r3_weightw_mask(const small *); - -#endif diff --git a/crypto/libntrup/src/avx/r3_recip.c b/crypto/libntrup/src/avx/r3_recip.c deleted file mode 100644 index 839bb2ce7f..0000000000 --- a/crypto/libntrup/src/avx/r3_recip.c +++ /dev/null @@ -1,221 +0,0 @@ -#if __AVX2__ -#include -#include "params.h" -#include "mod3.h" -#include "swap.h" -#include "r3.h" - -/* caller must ensure that x-y does not overflow */ -static int -smaller_mask(int x, int y) -{ - return (x - y) >> 31; -} - -static void -vectormod3_product(small *z, int len, const small *x, const small c) -{ - int i; - int minusmask = c; - int plusmask = -c; - __m256i minusvec, plusvec, zerovec; - - minusmask >>= 31; - plusmask >>= 31; - minusvec = _mm256_set1_epi32(minusmask); - plusvec = _mm256_set1_epi32(plusmask); - zerovec = _mm256_set1_epi32(0); - - while(len >= 32) - { - __m256i xi = _mm256_loadu_si256((__m256i *)x); - xi = (xi & plusvec) | (_mm256_sub_epi8(zerovec, xi) & minusvec); - _mm256_storeu_si256((__m256i *)z, xi); - x += 32; - z += 32; - len -= 32; - } - - for(i = 0; i < len; ++i) - z[i] = mod3_product(x[i], c); -} - -static void -vectormod3_minusproduct(small *z, int len, const small *x, const small *y, - const small c) -{ - int i; - int minusmask = c; - int plusmask = -c; - __m256i minusvec, plusvec, zerovec, twovec, fourvec; - - minusmask >>= 31; - plusmask >>= 31; - minusvec = _mm256_set1_epi32(minusmask); - plusvec = _mm256_set1_epi32(plusmask); - zerovec = _mm256_set1_epi32(0); - twovec = _mm256_set1_epi32(0x02020202); - fourvec = _mm256_set1_epi32(0x04040404); - - while(len >= 32) - { - __m256i xi = _mm256_loadu_si256((__m256i *)x); - __m256i yi = _mm256_loadu_si256((__m256i *)y); - __m256i r; - yi = (yi & plusvec) | (_mm256_sub_epi8(zerovec, yi) & minusvec); - xi = _mm256_sub_epi8(xi, yi); - - r = _mm256_add_epi8(xi, twovec); - r &= fourvec; - r = _mm256_srli_epi32(r, 2); - xi = _mm256_sub_epi8(xi, r); - r = _mm256_add_epi8(r, r); - xi = _mm256_sub_epi8(xi, r); - - r = _mm256_sub_epi8(twovec, xi); - r &= fourvec; - r = _mm256_srli_epi32(r, 2); - xi = _mm256_add_epi8(xi, r); - r = _mm256_add_epi8(r, r); - xi = _mm256_add_epi8(xi, r); - - _mm256_storeu_si256((__m256i *)z, xi); - x += 32; - y += 32; - z += 32; - len -= 32; - } - - for(i = 0; i < len; ++i) - z[i] = mod3_minusproduct(x[i], y[i], c); -} - -static void -vectormod3_shift(small *z, int len) -{ - int i; - while(len >= 33) - { - __m256i zi = _mm256_loadu_si256((__m256i *)(z + len - 33)); - _mm256_storeu_si256((__m256i *)(z + len - 32), zi); - len -= 32; - } - for(i = len - 1; i > 0; --i) - z[i] = z[i - 1]; - z[0] = 0; -} - -/* -r = s^(-1) mod m, returning 0, if s is invertible mod m -or returning -1 if s is not invertible mod m -r,s are polys of degree

= loops) - break; - - c = mod3_quotient(g[p], f[p]); - - vectormod3_minusproduct(g, 768, g, f, c); - vectormod3_shift(g, 769); - -#ifdef SIMPLER - vectormod3_minusproduct(v, 1536, v, u, c); - vectormod3_shift(v, 1537); -#else - if(loop < p) - { - vectormod3_minusproduct(v, loop + 1, v, u, c); - vectormod3_shift(v, loop + 2); - } - else - { - vectormod3_minusproduct(v + loop - p, p + 1, v + loop - p, u + loop - p, - c); - vectormod3_shift(v + loop - p, p + 2); - } -#endif - - e -= 1; - - ++loop; - - swapmask = smaller_mask(e, d) & mod3_nonzero_mask(g[p]); - swap(&e, &d, sizeof e, swapmask); - swap(f, g, (p + 1) * sizeof(small), swapmask); - -#ifdef SIMPLER - swap(u, v, 1536 * sizeof(small), swapmask); -#else - if(loop < p) - { - swap(u, v, (loop + 1) * sizeof(small), swapmask); - } - else - { - swap(u + loop - p, v + loop - p, (p + 1) * sizeof(small), swapmask); - } -#endif - } - - c = mod3_reciprocal(f[p]); - vectormod3_product(r, p, u + p, c); - for(i = p; i < 768; ++i) - r[i] = 0; - return smaller_mask(0, d); -} -#endif \ No newline at end of file diff --git a/crypto/libntrup/src/avx/randomsmall.c b/crypto/libntrup/src/avx/randomsmall.c deleted file mode 100644 index 7ebe5feb59..0000000000 --- a/crypto/libntrup/src/avx/randomsmall.c +++ /dev/null @@ -1,18 +0,0 @@ -#include "params.h" -#include -#include -#include "small.h" - -void -small_random(small *g) -{ - crypto_uint32 r[p]; - int i; - - randombytes((unsigned char *)r, sizeof r); - for(i = 0; i < p; ++i) - g[i] = (small)(((r[i] & 1073741823) * 3) >> 30) - 1; - /* bias is miniscule */ - for(i = p; i < 768; ++i) - g[i] = 0; -} diff --git a/crypto/libntrup/src/avx/randomweightw.c b/crypto/libntrup/src/avx/randomweightw.c deleted file mode 100644 index 888fb937c1..0000000000 --- a/crypto/libntrup/src/avx/randomweightw.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "params.h" -#include -#include "int32_sort.h" -#include "small.h" - -void -small_random_weightw(small *f) -{ - crypto_int32 r[p]; - int i; - - randombytes((unsigned char *)r, sizeof r); - for(i = 0; i < w; ++i) - r[i] &= -2; - for(i = w; i < p; ++i) - r[i] = (r[i] & -3) | 1; - int32_sort(r, p); - for(i = 0; i < p; ++i) - f[i] = ((small)(r[i] & 3)) - 1; - for(i = p; i < 768; ++i) - f[i] = 0; -} diff --git a/crypto/libntrup/src/avx/rq.c b/crypto/libntrup/src/avx/rq.c deleted file mode 100644 index a000e7d72f..0000000000 --- a/crypto/libntrup/src/avx/rq.c +++ /dev/null @@ -1,185 +0,0 @@ -#if __AVX2__ -#include -#include "params.h" -#include -#include -#include "rq.h" - -#define v2295_16 _mm256_set1_epi16(2295) -#define v2295_16_128 _mm_set1_epi16(2295) -#define alpha_top _mm256_set1_epi32(0x43380000) -#define alpha _mm256_set1_pd(6755399441055744.0) -#define alpha_64 _mm256_set1_epi64(0x4338000000000000) - -/* each reciprocal is rounded _up_ to nearest floating-point number */ -#define recip54 0.0185185185185185209599811884118025773204863071441650390625 -#define recip4591 \ - 0.000217817468961010681817447309782664888189174234867095947265625 -#define recip6144 \ - 0.0001627604166666666847367028747584072334575466811656951904296875 -#define recip331776 \ - 0.00000301408179012345704632478034235010255770248477347195148468017578125 -#define recip37748736 \ - 0.000000026490953233506946282623583451172610825352649044361896812915802001953125 - -#define broadcast(r) _mm256_set1_pd(r) -#define floor(x) _mm256_floor_pd(x) - -// 32-bit hosts only -#ifndef __amd64__ -#define _mm_extract_epi64(X, N) \ - (__extension__({ \ - __v2di __a = (__v2di)(X); \ - __a[N]; \ - })) -#endif - -void -rq_encode(unsigned char *c, const modq *f) -{ - crypto_int32 f0, f1, f2, f3, f4; - int i; - - for(i = 0; i < p / 5; ++i) - { - f0 = *f++ + qshift; - f1 = *f++ + qshift; - f2 = *f++ + qshift; - f3 = *f++ + qshift; - f4 = *f++ + qshift; - /* now want f0 + 6144*f1 + ... as a 64-bit integer */ - f1 *= 3; - f2 *= 9; - f3 *= 27; - f4 *= 81; - /* now want f0 + f1<<11 + f2<<22 + f3<<33 + f4<<44 */ - f0 += f1 << 11; - *c++ = f0; - f0 >>= 8; - *c++ = f0; - f0 >>= 8; - f0 += f2 << 6; - *c++ = f0; - f0 >>= 8; - *c++ = f0; - f0 >>= 8; - f0 += f3 << 1; - *c++ = f0; - f0 >>= 8; - f0 += f4 << 4; - *c++ = f0; - f0 >>= 8; - *c++ = f0; - f0 >>= 8; - *c++ = f0; - } - /* XXX: using p mod 5 = 1 */ - f0 = *f++ + qshift; - *c++ = f0; - f0 >>= 8; - *c++ = f0; -} - -void -rq_decode(modq *f, const unsigned char *c) -{ - crypto_uint32 c0, c1; - int i; - - for(i = 0; i < 152; i += 4) - { - __m256i abcd, ac, bd, abcd0, abcd1; - __m256d x0, x1, f4, f3, f2, f1, f0; - __m128i if4, if3, if2, if1, if0; - __m128i x01, x23, x02, x13, xab, xcd; - - /* f0 + f1*6144 + f2*6144^2 + f3*6144^3 + f4*6144^4 */ - /* = c0 + c1*256 + ... + c6*256^6 + c7*256^7 */ - /* with each f between 0 and 4590 */ - - /* could use _mm256_cvtepi32_pd instead; but beware uint32 */ - - abcd = _mm256_loadu_si256((__m256i *)c); /* a0 a1 b0 b1 c0 c1 d0 d1 */ - c += 32; - - ac = _mm256_unpacklo_epi32(abcd, alpha_top); /* a0 a1 c0 c1 */ - bd = _mm256_unpackhi_epi32(abcd, alpha_top); /* b0 b1 d0 d1 */ - abcd1 = _mm256_unpackhi_epi64(ac, bd); /* a1 b1 c1 d1 */ - abcd0 = _mm256_unpacklo_epi64(ac, bd); /* a0 b0 c0 d0 */ - x1 = *(__m256d *)&abcd1; - x0 = *(__m256d *)&abcd0; - - x1 -= alpha; - x0 -= alpha; - - /* x1 is [0,41] + [0,4590]*54 + f4*331776 */ - f4 = broadcast(recip331776) * x1; - f4 = floor(f4); - x1 -= broadcast(331776.0) * f4; - - /* x1 is [0,41] + f3*54 */ - f3 = broadcast(recip54) * x1; - f3 = floor(f3); - x1 -= broadcast(54.0) * f3; - - x0 += broadcast(4294967296.0) * x1; - - /* x0 is [0,4590] + [0,4590]*6144 + f2*6144^2 */ - f2 = broadcast(recip37748736) * x0; - f2 = floor(f2); - x0 -= broadcast(37748736.0) * f2; - - /* x0 is [0,4590] + f1*6144 */ - f1 = broadcast(recip6144) * x0; - f1 = floor(f1); - x0 -= broadcast(6144.0) * f1; - - f0 = x0; - - f4 -= broadcast(4591.0) * floor(broadcast(recip4591) * f4); - f3 -= broadcast(4591.0) * floor(broadcast(recip4591) * f3); - f2 -= broadcast(4591.0) * floor(broadcast(recip4591) * f2); - f1 -= broadcast(4591.0) * floor(broadcast(recip4591) * f1); - f0 -= broadcast(4591.0) * floor(broadcast(recip4591) * f0); - - if4 = _mm256_cvtpd_epi32(f4); /* a4 0 b4 0 c4 0 d4 0 */ - if3 = _mm256_cvtpd_epi32(f3); /* a3 0 b3 0 c3 0 d3 0 */ - if2 = _mm256_cvtpd_epi32(f2); /* a2 0 b2 0 c2 0 d2 0 */ - if1 = _mm256_cvtpd_epi32(f1); /* a1 0 b1 0 c1 0 d1 0 */ - if0 = _mm256_cvtpd_epi32(f0); /* a0 0 b0 0 c0 0 d0 0 */ - - if4 = _mm_sub_epi16(if4, v2295_16_128); - f[4] = _mm_extract_epi32(if4, 0); - f[9] = _mm_extract_epi32(if4, 1); - f[14] = _mm_extract_epi32(if4, 2); - f[19] = _mm_extract_epi32(if4, 3); - - x23 = _mm_packs_epi32(if2, if3); /* a2 b2 c2 d2 a3 b3 c3 d3 */ - x01 = _mm_packs_epi32(if0, if1); /* a0 b0 c0 d0 a1 b1 c1 d1 */ - x02 = _mm_unpacklo_epi16(x01, x23); /* a0 a2 b0 b2 c0 c2 d0 d2 */ - x13 = _mm_unpackhi_epi16(x01, x23); /* a1 a3 b1 b3 c1 c3 d1 d3 */ - xab = _mm_unpacklo_epi16(x02, x13); /* a0 a1 a2 a3 b0 b1 b2 b3 */ - xcd = _mm_unpackhi_epi16(x02, x13); /* c0 c1 c2 c3 d0 d1 d2 d3 */ - xab = _mm_sub_epi16(xab, v2295_16_128); - xcd = _mm_sub_epi16(xcd, v2295_16_128); - - *(crypto_int64 *)(f + 0) = _mm_extract_epi64(xab, 0); - *(crypto_int64 *)(f + 5) = _mm_extract_epi64(xab, 1); - *(crypto_int64 *)(f + 10) = _mm_extract_epi64(xcd, 0); - *(crypto_int64 *)(f + 15) = _mm_extract_epi64(xcd, 1); - f += 20; - } - - c0 = *c++; - c1 = *c++; - c0 += c1 << 8; - *f++ = modq_freeze(c0 + q - qshift); - *f++ = 0; - *f++ = 0; - *f++ = 0; - *f++ = 0; - *f++ = 0; - *f++ = 0; - *f++ = 0; -} -#endif diff --git a/crypto/libntrup/src/avx/rq.h b/crypto/libntrup/src/avx/rq.h deleted file mode 100644 index 0660af3507..0000000000 --- a/crypto/libntrup/src/avx/rq.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef rq_h -#define rq_h - -#include "modq.h" -#include "small.h" - -#define rq_encode crypto_kem_sntrup4591761_avx_rq_encode -extern void -rq_encode(unsigned char *, const modq *); - -#define rq_decode crypto_kem_sntrup4591761_avx_rq_decode -extern void -rq_decode(modq *, const unsigned char *); - -#define rq_roundencode crypto_kem_sntrup4591761_avx_rq_roundencode -extern void -rq_roundencode(unsigned char *, const modq *); - -#define rq_decoderounded crypto_kem_sntrup4591761_avx_rq_decoderounded -extern void -rq_decoderounded(modq *, const unsigned char *); - -#define rq_round3 crypto_kem_sntrup4591761_avx_rq_round3 -extern void -rq_round3(modq *, const modq *); - -#define rq_mod3 crypto_kem_sntrup4591761_avx_rq_mod3 -extern void -rq_mod3(small *, const modq *); - -#define rq_mult crypto_kem_sntrup4591761_avx_rq_mult -extern void -rq_mult(modq *, const modq *, const small *); - -#define rq_recip3 crypto_kem_sntrup4591761_avx_rq_recip3 -int -rq_recip3(modq *, const small *); - -#endif diff --git a/crypto/libntrup/src/avx/rq_mod3.c b/crypto/libntrup/src/avx/rq_mod3.c deleted file mode 100644 index 6a972acda0..0000000000 --- a/crypto/libntrup/src/avx/rq_mod3.c +++ /dev/null @@ -1,68 +0,0 @@ -#if __AVX2__ -#include -#include -#include "mod3.h" -#include "rq.h" - -#define v3 _mm256_set1_epi16(3) -#define v7 _mm256_set1_epi16(7) -#define v2296_16 _mm256_set1_epi16(2296) -#define v4591_16 _mm256_set1_epi16(4591) -#define v10923_16 _mm256_set1_epi16(10923) - -// 32-bit hosts only -#ifndef __amd64__ -#define _mm_extract_epi64(X, N) \ - (__extension__({ \ - __v2di __a = (__v2di)(X); \ - __a[N]; \ - })) -#endif - -static inline __m256i -squeeze(__m256i x) -{ - __m256i q = _mm256_mulhrs_epi16(x, v7); - q = _mm256_mullo_epi16(q, v4591_16); - return _mm256_sub_epi16(x, q); -} - -static inline __m256i -freeze(__m256i x) -{ - __m256i mask, x2296, x4591; - x4591 = _mm256_add_epi16(x, v4591_16); - mask = _mm256_srai_epi16(x, 15); - x = _mm256_blendv_epi8(x, x4591, mask); - x2296 = _mm256_sub_epi16(x, v2296_16); - mask = _mm256_srai_epi16(x2296, 15); - x4591 = _mm256_sub_epi16(x, v4591_16); - x = _mm256_blendv_epi8(x4591, x, mask); - return x; -} - -void -rq_mod3(small *g, const modq *f) -{ - int i; - - for(i = 0; i < 768; i += 16) - { - __m256i x = _mm256_loadu_si256((__m256i *)&f[i]); - __m256i q; - x = _mm256_mullo_epi16(x, v3); - x = squeeze(x); - x = freeze(x); - q = _mm256_mulhrs_epi16(x, v10923_16); - x = _mm256_sub_epi16(x, q); - q = _mm256_add_epi16(q, q); - x = _mm256_sub_epi16(x, q); /* g0 g1 ... g15 */ - x = _mm256_packs_epi16(x, - x); /* g0 ... g7 g0 ... g7 g8 ... g15 g8 ... g15 */ - 0 [(long long *)&g[i]] = - _mm_extract_epi64(_mm256_extracti128_si256(x, 0), 0); - 1 [(long long *)&g[i]] = - _mm_extract_epi64(_mm256_extracti128_si256(x, 1), 0); - } -} -#endif \ No newline at end of file diff --git a/crypto/libntrup/src/avx/rq_recip3.c b/crypto/libntrup/src/avx/rq_recip3.c deleted file mode 100644 index 5b4e96d6b9..0000000000 --- a/crypto/libntrup/src/avx/rq_recip3.c +++ /dev/null @@ -1,247 +0,0 @@ -#if __AVX2__ -#include -#include "params.h" -#include "swap.h" -#include "rq.h" - -#define v7 _mm256_set1_epi16(7) -#define v1827_16 _mm256_set1_epi16(1827) -#define v4591_16 _mm256_set1_epi16(4591) -#define v29234_16 _mm256_set1_epi16(29234) - -/* caller must ensure that x-y does not overflow */ -static int -smaller_mask(int x, int y) -{ - return (x - y) >> 31; -} - -static inline __m256i -product(__m256i x, __m256i y) -{ - __m256i lo, hi, r0, r1, t0, t1, t, s0, s1; - - lo = _mm256_mullo_epi16(x, y); - hi = _mm256_mulhi_epi16(x, y); - r0 = _mm256_unpacklo_epi16(lo, hi); - r1 = _mm256_unpackhi_epi16(lo, hi); - - t0 = _mm256_srai_epi32(r0, 16); - t1 = _mm256_srai_epi32(r1, 16); - t = _mm256_packs_epi32(t0, t1); - t = _mm256_mulhrs_epi16(t, v29234_16); - lo = _mm256_mullo_epi16(t, v4591_16); - hi = _mm256_mulhi_epi16(t, v4591_16); - s0 = _mm256_unpacklo_epi16(lo, hi); - s1 = _mm256_unpackhi_epi16(lo, hi); - s0 = _mm256_slli_epi32(s0, 4); - s1 = _mm256_slli_epi32(s1, 4); - r0 = _mm256_sub_epi32(r0, s0); - r1 = _mm256_sub_epi32(r1, s1); - - t0 = _mm256_srai_epi32(r0, 8); - t1 = _mm256_srai_epi32(r1, 8); - t = _mm256_packs_epi32(t0, t1); - t = _mm256_mulhrs_epi16(t, v1827_16); - lo = _mm256_mullo_epi16(t, v4591_16); - hi = _mm256_mulhi_epi16(t, v4591_16); - s0 = _mm256_unpacklo_epi16(lo, hi); - s1 = _mm256_unpackhi_epi16(lo, hi); - r0 = _mm256_sub_epi32(r0, s0); - r1 = _mm256_sub_epi32(r1, s1); - - x = _mm256_packs_epi32(r0, r1); - return x; -} - -static inline __m256i -minusproduct(__m256i x, __m256i y, __m256i z) -{ - __m256i t; - - x = _mm256_sub_epi16(x, product(y, z)); - t = _mm256_mulhrs_epi16(x, v7); - t = _mm256_mullo_epi16(t, v4591_16); - x = _mm256_sub_epi16(x, t); - return x; -} - -static void -vectormodq_product(modq *z, int len, const modq *x, const modq c) -{ - __m256i cvec = _mm256_set1_epi16(c); - while(len >= 16) - { - __m256i xi = _mm256_loadu_si256((__m256i *)x); - xi = product(xi, cvec); - _mm256_storeu_si256((__m256i *)z, xi); - x += 16; - z += 16; - len -= 16; - } - while(len > 0) - { - *z = modq_product(*x, c); - ++x; - ++z; - --len; - } -} - -static void -vectormodq_minusproduct(modq *z, int len, const modq *x, const modq *y, - const modq c) -{ - __m256i cvec = _mm256_set1_epi16(c); - while(len >= 16) - { - __m256i xi = _mm256_loadu_si256((__m256i *)x); - __m256i yi = _mm256_loadu_si256((__m256i *)y); - xi = minusproduct(xi, yi, cvec); - _mm256_storeu_si256((__m256i *)z, xi); - x += 16; - y += 16; - z += 16; - len -= 16; - } - while(len > 0) - { - *z = modq_minusproduct(*x, *y, c); - ++x; - ++y; - ++z; - --len; - } -} - -static void -vectormodq_shift(modq *z, int len) -{ - int i; - while(len >= 17) - { - __m256i zi = _mm256_loadu_si256((__m256i *)(z + len - 17)); - _mm256_storeu_si256((__m256i *)(z + len - 16), zi); - len -= 16; - } - for(i = len - 1; i > 0; --i) - z[i] = z[i - 1]; - z[0] = 0; -} - -/* -r = (3s)^(-1) mod m, returning 0, if s is invertible mod m -or returning -1 if s is not invertible mod m -r,s are polys of degree

= loops) - break; - - c = modq_quotient(g[p], f[p]); - - vectormodq_minusproduct(g, 768, g, f, c); - vectormodq_shift(g, 769); - -#ifdef SIMPLER - vectormodq_minusproduct(v, 1536, v, u, c); - vectormodq_shift(v, 1537); -#else - if(loop < p) - { - vectormodq_minusproduct(v, loop + 1, v, u, c); - vectormodq_shift(v, loop + 2); - } - else - { - vectormodq_minusproduct(v + loop - p, p + 1, v + loop - p, u + loop - p, - c); - vectormodq_shift(v + loop - p, p + 2); - } -#endif - - e -= 1; - - ++loop; - - swapmask = smaller_mask(e, d) & modq_nonzero_mask(g[p]); - swap(&e, &d, sizeof e, swapmask); - swap(f, g, 768 * sizeof(modq), swapmask); - -#ifdef SIMPLER - swap(u, v, 1536 * sizeof(modq), swapmask); -#else - if(loop < p) - { - swap(u, v, (loop + 1) * sizeof(modq), swapmask); - } - else - { - swap(u + loop - p, v + loop - p, (p + 1) * sizeof(modq), swapmask); - } -#endif - } - - c = modq_reciprocal(f[p]); - vectormodq_product(r, p, u + p, c); - for(i = 0; i < p; ++i) - r[i] = modq_freeze(r[i]); - for(i = p; i < 768; ++i) - r[i] = 0; - return smaller_mask(0, d); -} -#endif \ No newline at end of file diff --git a/crypto/libntrup/src/avx/rq_round3.c b/crypto/libntrup/src/avx/rq_round3.c deleted file mode 100644 index e6c6569b84..0000000000 --- a/crypto/libntrup/src/avx/rq_round3.c +++ /dev/null @@ -1,24 +0,0 @@ -#if __AVX2__ -#include -#include "params.h" -#include "rq.h" - -#define v3_16 _mm256_set1_epi16(3) -#define v10923_16 _mm256_set1_epi16(10923) - -void -rq_round3(modq *h, const modq *f) -{ - int i; - - for(i = 0; i < 768; i += 16) - { - __m256i x = _mm256_loadu_si256((__m256i *)&f[i]); - __m256i x2; - x = _mm256_mulhrs_epi16(x, v10923_16); - x2 = _mm256_add_epi16(x, x); - x = _mm256_add_epi16(x, x2); - _mm256_storeu_si256((__m256i *)&h[i], x); - } -} -#endif \ No newline at end of file diff --git a/crypto/libntrup/src/avx/rq_rounded.c b/crypto/libntrup/src/avx/rq_rounded.c deleted file mode 100644 index 512f597321..0000000000 --- a/crypto/libntrup/src/avx/rq_rounded.c +++ /dev/null @@ -1,297 +0,0 @@ -#if __AVX2__ -#include -#include "params.h" -#include -#include "rq.h" - -#define alpha_top _mm256_set1_epi32(0x43380000) -#define alpha _mm256_set1_pd(6755399441055744.0) -#define v10923_16 _mm256_set1_epi16(10923) -#define floor(x) _mm256_floor_pd(x) - -void -rq_roundencode(unsigned char *c, const modq *f) -{ - int i; - __m256i h[50]; - - for(i = 0; i < 208; i += 16) - { - __m256i a0, a1, a2, b0, b1, b2, c0, c1, c2, d0, d1, d2; - __m256i e0, e1, f0, f1, g0, g1; - a0 = _mm256_castsi128_si256(_mm_loadu_si128((__m128i *)&f[0])); - a1 = _mm256_castsi128_si256(_mm_loadu_si128((__m128i *)&f[8])); - a2 = _mm256_castsi128_si256(_mm_loadu_si128((__m128i *)&f[16])); - a0 = _mm256_inserti128_si256(a0, _mm_loadu_si128((__m128i *)&f[24]), 1); - a1 = _mm256_inserti128_si256(a1, _mm_loadu_si128((__m128i *)&f[32]), 1); - a2 = _mm256_inserti128_si256(a2, _mm_loadu_si128((__m128i *)&f[40]), 1); - f += 48; - - a0 = _mm256_mulhrs_epi16(a0, v10923_16); - a1 = _mm256_mulhrs_epi16(a1, v10923_16); - a2 = _mm256_mulhrs_epi16(a2, v10923_16); - - /* a0: a0 a1 a2 b0 b1 b2 c0 c1 and similar second half */ - /* a1: c2 d0 d1 d2 e0 e1 e2 f0 */ - /* a2: f1 f2 g0 g1 g2 h0 h1 h2 */ - - b1 = _mm256_blend_epi16(a2, a0, 0xf0); - b1 = _mm256_shuffle_epi32(b1, 0x4e); - b0 = _mm256_blend_epi16(a0, a1, 0xf0); - b2 = _mm256_blend_epi16(a1, a2, 0xf0); - /* XXX: use shufps instead? */ - - /* b0: a0 a1 a2 b0 e0 e1 e2 f0 */ - /* b1: b1 b2 c0 c1 f1 f2 g0 g1 */ - /* b2: c2 d0 d1 d2 g2 h0 h1 h2 */ - - c1 = _mm256_blend_epi16(b2, b0, 0xcc); - c1 = _mm256_shuffle_epi32(c1, 0xb1); - c0 = _mm256_blend_epi16(b0, b1, 0xcc); - c2 = _mm256_blend_epi16(b1, b2, 0xcc); - - /* c0: a0 a1 c0 c1 e0 e1 g0 g1 */ - /* c1: a2 b0 c2 d0 e2 f0 g2 h0 */ - /* c2: b1 b2 d1 d2 f1 f2 h1 h2 */ - - d1 = _mm256_blend_epi16(c2, c0, 0xaa); - d1 = _mm256_shufflelo_epi16(d1, 0xb1); - d1 = _mm256_shufflehi_epi16(d1, 0xb1); - d0 = _mm256_blend_epi16(c0, c1, 0xaa); - d2 = _mm256_blend_epi16(c1, c2, 0xaa); - - /* d0: a0 b0 c0 d0 e0 f0 g0 h0 */ - /* d1: a1 b1 c1 d1 e1 f1 g1 h1 */ - /* d2: a2 b2 c2 d2 e2 f2 g2 h2 */ - - d0 = _mm256_add_epi16(d0, _mm256_set1_epi16(765)); - d1 = _mm256_add_epi16(d1, _mm256_set1_epi16(765)); - d2 = _mm256_add_epi16(d2, _mm256_set1_epi16(765)); - /* want bytes of d0 + 1536*d1 + 1536*1536*d2 */ - - e0 = d0 & _mm256_set1_epi16(0xff); - d0 = _mm256_srli_epi16(d0, 8); - /* want e0, d0 + 6*d1 + 6*1536*d2 */ - - d1 = _mm256_mullo_epi16(d1, _mm256_set1_epi16(6)); - d0 = _mm256_add_epi16(d0, d1); - /* want e0, d0 + 6*1536*d2 */ - - e1 = _mm256_slli_epi16(d0, 8); - e0 = _mm256_add_epi16(e0, e1); - d0 = _mm256_srli_epi16(d0, 8); - /* want e0, d0 + 36*d2 */ - - d2 = _mm256_mullo_epi16(d2, _mm256_set1_epi16(36)); - e1 = _mm256_add_epi16(d0, d2); - /* want e0, e1 */ - - /* e0: out0 out1 out4 out5 out8 out9 ... */ - /* e1: out2 out3 out6 out7 out10 out11 ... */ - - f0 = _mm256_unpacklo_epi16(e0, e1); - f1 = _mm256_unpackhi_epi16(e0, e1); - - g0 = _mm256_permute2x128_si256(f0, f1, 0x20); - g1 = _mm256_permute2x128_si256(f0, f1, 0x31); - - _mm256_storeu_si256((__m256i *)c, g0); - _mm256_storeu_si256((__m256i *)(c + 32), g1); - c += 64; - } - - for(i = 0; i < 9; ++i) - { - __m256i x = _mm256_loadu_si256((__m256i *)&f[16 * i]); - _mm256_storeu_si256(&h[i], _mm256_mulhrs_epi16(x, v10923_16)); - } - f = (const modq *)h; - - for(i = 208; i < 253; ++i) - { - crypto_int32 f0, f1, f2; - f0 = *f++; - f1 = *f++; - f2 = *f++; - f0 += 1806037245; - f1 *= 3; - f2 *= 9; - f0 += f1 << 9; - f0 += f2 << 18; - *(crypto_int32 *)c = f0; - c += 4; - } - { - crypto_int32 f0, f1; - f0 = *f++; - f1 = *f++; - f0 += 1175805; - f1 *= 3; - f0 += f1 << 9; - *c++ = f0; - f0 >>= 8; - *c++ = f0; - f0 >>= 8; - *c++ = f0; - } -} - -void -rq_decoderounded(modq *f, const unsigned char *c) -{ - crypto_uint32 c0, c1, c2, c3; - crypto_uint32 f0, f1, f2; - int i; - - for(i = 0; i < 248; i += 8) - { - __m256i abcdefgh, todo[2]; - __m256d x, f2, f1, f0; - __m128i if2, if1, if0; - int j; - - abcdefgh = _mm256_loadu_si256((__m256i *)c); - c += 32; - - todo[0] = _mm256_unpacklo_epi32(abcdefgh, alpha_top); - todo[1] = _mm256_unpackhi_epi32(abcdefgh, alpha_top); - - for(j = 0; j < 2; ++j) - { - x = *(__m256d *)&todo[j]; - x -= alpha; - - /* x is f0 + f1*1536 + f2*1536^2 */ - /* with each f between 0 and 1530 */ - - f2 = - x - * _mm256_set1_pd( - 0.00000042385525173611114052197733521876177320564238470979034900665283203125); - f2 = floor(f2); - x -= f2 * _mm256_set1_pd(2359296.0); - - f1 = - x - * _mm256_set1_pd( - 0.00065104166666666673894681149903362893383018672466278076171875); - f1 = floor(f1); - x -= f1 * _mm256_set1_pd(1536.0); - - f0 = x; - - f2 -= - _mm256_set1_pd(1531.0) - * floor( - f2 - * _mm256_set1_pd( - 0.0006531678641410842804659875326933615724556148052215576171875)); - f1 -= - _mm256_set1_pd(1531.0) - * floor( - f1 - * _mm256_set1_pd( - 0.0006531678641410842804659875326933615724556148052215576171875)); - f0 -= - _mm256_set1_pd(1531.0) - * floor( - f0 - * _mm256_set1_pd( - 0.0006531678641410842804659875326933615724556148052215576171875)); - - f2 *= _mm256_set1_pd(3.0); - f2 -= _mm256_set1_pd(2295.0); - f1 *= _mm256_set1_pd(3.0); - f1 -= _mm256_set1_pd(2295.0); - f0 *= _mm256_set1_pd(3.0); - f0 -= _mm256_set1_pd(2295.0); - - if2 = _mm256_cvtpd_epi32(f2); /* a2 b2 e2 f2 */ - if1 = _mm256_cvtpd_epi32(f1); /* a1 b1 e1 f1 */ - if0 = _mm256_cvtpd_epi32(f0); /* a0 b0 e0 f0 */ - - f[6 * j + 0] = _mm_extract_epi32(if0, 0); - f[6 * j + 1] = _mm_extract_epi32(if1, 0); - f[6 * j + 2] = _mm_extract_epi32(if2, 0); - f[6 * j + 3] = _mm_extract_epi32(if0, 1); - f[6 * j + 4] = _mm_extract_epi32(if1, 1); - f[6 * j + 5] = _mm_extract_epi32(if2, 1); - - f[6 * j + 12] = _mm_extract_epi32(if0, 2); - f[6 * j + 13] = _mm_extract_epi32(if1, 2); - f[6 * j + 14] = _mm_extract_epi32(if2, 2); - f[6 * j + 15] = _mm_extract_epi32(if0, 3); - f[6 * j + 16] = _mm_extract_epi32(if1, 3); - f[6 * j + 17] = _mm_extract_epi32(if2, 3); - } - - f += 24; - } - - for(i = 248; i < 253; ++i) - { - c0 = *c++; - c1 = *c++; - c2 = *c++; - c3 = *c++; - - /* f0 + f1*1536 + f2*1536^2 */ - /* = c0 + c1*256 + c2*256^2 + c3*256^3 */ - /* with each f between 0 and 1530 */ - - /* f2 = (64/9)c3 + (1/36)c2 + (1/9216)c1 + (1/2359296)c0 - [0,0.99675] */ - /* claim: 2^21 f2 < x < 2^21(f2+1) */ - /* where x = 14913081*c3 + 58254*c2 + 228*(c1+2) */ - /* proof: x - 2^21 f2 = 456 - (8/9)c0 + (4/9)c1 - (2/9)c2 + (1/9)c3 + 2^21 - * [0,0.99675] */ - /* at least 456 - (8/9)255 - (2/9)255 > 0 */ - /* at most 456 + (4/9)255 + (1/9)255 + 2^21 0.99675 < 2^21 */ - f2 = (14913081 * c3 + 58254 * c2 + 228 * (c1 + 2)) >> 21; - - c2 += c3 << 8; - c2 -= (f2 * 9) << 2; - /* f0 + f1*1536 */ - /* = c0 + c1*256 + c2*256^2 */ - /* c2 <= 35 = floor((1530+1530*1536)/256^2) */ - /* f1 = (128/3)c2 + (1/6)c1 + (1/1536)c0 - (1/1536)f0 */ - /* claim: 2^21 f1 < x < 2^21(f1+1) */ - /* where x = 89478485*c2 + 349525*c1 + 1365*(c0+1) */ - /* proof: x - 2^21 f1 = 1365 - (1/3)c2 - (1/3)c1 - (1/3)c0 + (4096/3)f0 */ - /* at least 1365 - (1/3)35 - (1/3)255 - (1/3)255 > 0 */ - /* at most 1365 + (4096/3)1530 < 2^21 */ - f1 = (89478485 * c2 + 349525 * c1 + 1365 * (c0 + 1)) >> 21; - - c1 += c2 << 8; - c1 -= (f1 * 3) << 1; - - c0 += c1 << 8; - f0 = c0; - - *f++ = modq_freeze(f0 * 3 + q - qshift); - *f++ = modq_freeze(f1 * 3 + q - qshift); - *f++ = modq_freeze(f2 * 3 + q - qshift); - } - - c0 = *c++; - c1 = *c++; - c2 = *c++; - - f1 = (89478485 * c2 + 349525 * c1 + 1365 * (c0 + 1)) >> 21; - - c1 += c2 << 8; - c1 -= (f1 * 3) << 1; - - c0 += c1 << 8; - f0 = c0; - - *f++ = modq_freeze(f0 * 3 + q - qshift); - *f++ = modq_freeze(f1 * 3 + q - qshift); - *f++ = 0; - *f++ = 0; - *f++ = 0; - *f++ = 0; - *f++ = 0; - *f++ = 0; - *f++ = 0; -} -#endif diff --git a/crypto/libntrup/src/avx/small.c b/crypto/libntrup/src/avx/small.c deleted file mode 100644 index f296899607..0000000000 --- a/crypto/libntrup/src/avx/small.c +++ /dev/null @@ -1,54 +0,0 @@ -#if __AVX2__ -#include -#include "params.h" -#include "small.h" - -/* XXX: these functions rely on p mod 4 = 1 */ - -/* all coefficients in -1, 0, 1 */ -void -small_encode(unsigned char *c, const small *f) -{ - small c0; - int i; - - for(i = 0; i < p / 4; ++i) - { - c0 = *f++ + 1; - c0 += (*f++ + 1) << 2; - c0 += (*f++ + 1) << 4; - c0 += (*f++ + 1) << 6; - *c++ = c0; - } - c0 = *f++ + 1; - *c++ = c0; -} - -void -small_decode(small *f, const unsigned char *c) -{ - unsigned char c0; - int i; - - for(i = 0; i < p / 4; ++i) - { - c0 = *c++; - *f++ = ((small)(c0 & 3)) - 1; - c0 >>= 2; - *f++ = ((small)(c0 & 3)) - 1; - c0 >>= 2; - *f++ = ((small)(c0 & 3)) - 1; - c0 >>= 2; - *f++ = ((small)(c0 & 3)) - 1; - } - c0 = *c++; - *f++ = ((small)(c0 & 3)) - 1; - *f++ = 0; - *f++ = 0; - *f++ = 0; - *f++ = 0; - *f++ = 0; - *f++ = 0; - *f++ = 0; -} -#endif \ No newline at end of file diff --git a/crypto/libntrup/src/avx/small.h b/crypto/libntrup/src/avx/small.h deleted file mode 100644 index ca8f54bf1e..0000000000 --- a/crypto/libntrup/src/avx/small.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef small_h -#define small_h - -#include - -typedef crypto_int8 small; - -#define small_encode crypto_kem_sntrup4591761_avx_small_encode -extern void -small_encode(unsigned char *, const small *); - -#define small_decode crypto_kem_sntrup4591761_avx_small_decode -extern void -small_decode(small *, const unsigned char *); - -#define small_random crypto_kem_sntrup4591761_avx_small_random -extern void -small_random(small *); - -#define small_random_weightw crypto_kem_sntrup4591761_avx_small_random_weightw -extern void -small_random_weightw(small *); - -#endif diff --git a/crypto/libntrup/src/avx/swap.c b/crypto/libntrup/src/avx/swap.c deleted file mode 100644 index 569470639d..0000000000 --- a/crypto/libntrup/src/avx/swap.c +++ /dev/null @@ -1,37 +0,0 @@ -#if __AVX2__ -#include -#include "swap.h" - -void -swap(void *x, void *y, int bytes, int mask) -{ - char c = mask; - __m256i maskvec = _mm256_set1_epi32(mask); - - while(bytes >= 32) - { - __m256i xi = _mm256_loadu_si256(x); - __m256i yi = _mm256_loadu_si256(y); - __m256i xinew = _mm256_blendv_epi8(xi, yi, maskvec); - __m256i yinew = _mm256_blendv_epi8(yi, xi, maskvec); - _mm256_storeu_si256(x, xinew); - _mm256_storeu_si256(y, yinew); - x = 32 + (char *)x; - y = 32 + (char *)y; - bytes -= 32; - } - while(bytes > 0) - { - char xi = *(char *)x; - char yi = *(char *)y; - char t = c & (xi ^ yi); - xi ^= t; - yi ^= t; - *(char *)x = xi; - *(char *)y = yi; - ++x; - ++y; - --bytes; - } -} -#endif \ No newline at end of file diff --git a/crypto/libntrup/src/avx/swap.h b/crypto/libntrup/src/avx/swap.h deleted file mode 100644 index 1f56ccf1e0..0000000000 --- a/crypto/libntrup/src/avx/swap.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef swap_h -#define swap_h - -#define swap crypto_kem_sntrup4591761_avx_swap -extern void -swap(void *, void *, int, int); - -#endif diff --git a/crypto/libntrup/src/avx/weight.c b/crypto/libntrup/src/avx/weight.c deleted file mode 100644 index 9d22b10167..0000000000 --- a/crypto/libntrup/src/avx/weight.c +++ /dev/null @@ -1,34 +0,0 @@ -#if __AVX2__ -#include -#include "params.h" -#include "r3.h" -#include -#include - -int -r3_weightw_mask(const small *r) -{ - int weight; - int i; - __m256i tally = _mm256_set1_epi32(0); - - for(i = 0; i < 768; i += 16) - { - __m256i x = _mm256_cvtepi8_epi16(_mm_loadu_si128((__m128i *)&r[i])); - x &= _mm256_set1_epi32(0x00010001); - tally = _mm256_add_epi16(tally, x); - } - - tally = _mm256_hadd_epi16(tally, tally); - tally = _mm256_hadd_epi16(tally, tally); - tally = _mm256_hadd_epi16(tally, tally); - - weight = _mm_extract_epi16(_mm256_extracti128_si256(tally, 0), 0) - + _mm_extract_epi16(_mm256_extracti128_si256(tally, 1), 0); - - weight -= w; - - return (-(crypto_int32)(crypto_uint16)weight) >> 30; -} - -#endif diff --git a/crypto/libntrup/src/files.txt b/crypto/libntrup/src/files.txt deleted file mode 100644 index 6e10fee3d7..0000000000 --- a/crypto/libntrup/src/files.txt +++ /dev/null @@ -1,32 +0,0 @@ -crypto/libntrup/src/ref/randomsmall.c -crypto/libntrup/src/ref/swap.c -crypto/libntrup/src/ref/rq_round3.c -crypto/libntrup/src/ref/rq_recip3.c -crypto/libntrup/src/ref/small.c -crypto/libntrup/src/ref/rq_mult.c -crypto/libntrup/src/ref/randomweightw.c -crypto/libntrup/src/ref/random32.c -crypto/libntrup/src/ref/dec.c -crypto/libntrup/src/ref/r3_mult.c -crypto/libntrup/src/ref/r3_recip.c -crypto/libntrup/src/ref/keypair.c -crypto/libntrup/src/ref/rq_rounded.c -crypto/libntrup/src/ref/enc.c -crypto/libntrup/src/ref/int32_sort.c -crypto/libntrup/src/ref/rq.c -crypto/libntrup/src/avx/randomsmall.c -crypto/libntrup/src/avx/weight.c -crypto/libntrup/src/avx/swap.c -crypto/libntrup/src/avx/rq_round3.c -crypto/libntrup/src/avx/rq_recip3.c -crypto/libntrup/src/avx/small.c -crypto/libntrup/src/avx/randomweightw.c -crypto/libntrup/src/avx/dec.c -crypto/libntrup/src/avx/r3_recip.c -crypto/libntrup/src/avx/keypair.c -crypto/libntrup/src/avx/rq_rounded.c -crypto/libntrup/src/avx/mult.c -crypto/libntrup/src/avx/enc.c -crypto/libntrup/src/avx/int32_sort.c -crypto/libntrup/src/avx/rq.c -crypto/libntrup/src/avx/rq_mod3.c diff --git a/crypto/libntrup/src/noavx-stubs.c b/crypto/libntrup/src/noavx-stubs.c deleted file mode 100644 index 023354c40c..0000000000 --- a/crypto/libntrup/src/noavx-stubs.c +++ /dev/null @@ -1,29 +0,0 @@ -// Stubs for compilers/builds without avx2 support -// -int -crypto_kem_enc_avx2(unsigned char *cstr, unsigned char *k, - const unsigned char *pk) -{ - (void)(cstr); - (void)(k); - (void)(pk); - return -1; -} - -int -crypto_kem_dec_avx2(unsigned char *k, const unsigned char *cstr, - const unsigned char *sk) -{ - (void)(k); - (void)(sk); - (void)(cstr); - return -1; -} - -int -crypto_kem_keypair_avx2(unsigned char *pk, unsigned char *sk) -{ - (void)(pk); - (void)(sk); - return -1; -} diff --git a/crypto/libntrup/src/ntru.cpp b/crypto/libntrup/src/ntru.cpp deleted file mode 100644 index 44b95cd4ec..0000000000 --- a/crypto/libntrup/src/ntru.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include - -#ifdef __x86_64__ -#include -#include - -bool -supports_avx2() -{ - std::array< int, 4 > cpuinfo; - __cpuid(0, cpuinfo[0], cpuinfo[1], cpuinfo[2], cpuinfo[3]); - if (cpuinfo[0] < 7) - return false; - - __cpuid_count(7, 0, cpuinfo[0], cpuinfo[1], cpuinfo[2], cpuinfo[3]); - return cpuinfo[1] & (1 << 5); -} - -#else - -bool -supports_avx2() -{ - return false; -} - -#endif - -int (*__crypto_kem_enc)(unsigned char *cstr, unsigned char *k, - const unsigned char *pk); - -int (*__crypto_kem_dec)(unsigned char *k, const unsigned char *cstr, - const unsigned char *sk); - -int (*__crypto_kem_keypair)(unsigned char *pk, unsigned char *sk); - -extern "C" -{ - void - ntru_init(int force_no_avx2) - { - if(supports_avx2() && !force_no_avx2) - { - __crypto_kem_dec = &crypto_kem_dec_avx2; - __crypto_kem_enc = &crypto_kem_enc_avx2; - __crypto_kem_keypair = &crypto_kem_keypair_avx2; - } - else - { - __crypto_kem_dec = &crypto_kem_dec_ref; - __crypto_kem_enc = &crypto_kem_enc_ref; - __crypto_kem_keypair = &crypto_kem_keypair_ref; - } - } - - int - crypto_kem_enc(unsigned char *cstr, unsigned char *k, const unsigned char *pk) - { - return __crypto_kem_enc(cstr, k, pk); - } - - int - crypto_kem_dec(unsigned char *k, const unsigned char *cstr, - const unsigned char *sk) - { - return __crypto_kem_dec(k, cstr, sk); - } - - int - crypto_kem_keypair(unsigned char *pk, unsigned char *sk) - { - return __crypto_kem_keypair(pk, sk); - } -} diff --git a/crypto/libntrup/src/ref/README b/crypto/libntrup/src/ref/README deleted file mode 100644 index 30265ef710..0000000000 --- a/crypto/libntrup/src/ref/README +++ /dev/null @@ -1,32 +0,0 @@ -This is a reference implementation of Streamlined NTRU Prime 4591^761. -This implementation is designed primarily for clarity, subject to the -following constraints: - - * The implementation is written in C. The Sage implementation in the - NTRU Prime paper is considerably more concise (and compatible). - - * The implementation avoids data-dependent branches and array - indices. For example, conditional swaps are computed by arithmetic - rather than by branches. - - * The implementation avoids other C operations that often take - variable time. For example, divisions by 3 are computed via - multiplications and shifts. - -This implementation does _not_ sacrifice clarity for speed. - -This implementation has not yet been reviewed for correctness or for -constant-time behavior. It does pass various tests and has no known -bugs, but there are at least some platforms where multiplications take -variable time, and fixing this requires platform-specific effort; see -https://www.bearssl.org/ctmul.html and http://repository.tue.nl/800603. - -This implementation allows "benign malleability" of ciphertexts, as -defined in http://www.shoup.net/papers/iso-2_1.pdf. Specifically, each -32-bit ciphertext word encodes three integers between 0 and 1530; if -larger integers appear then they are silently reduced modulo 1531. -Similar comments apply to public keys. - -There is a separate "avx" implementation where similar comments apply, -except that "avx" _does_ sacrifice clarity for speed on CPUs with AVX2 -instructions. diff --git a/crypto/libntrup/src/ref/api.h b/crypto/libntrup/src/ref/api.h deleted file mode 100644 index 94d75538bc..0000000000 --- a/crypto/libntrup/src/ref/api.h +++ /dev/null @@ -1,4 +0,0 @@ -#define CRYPTO_SECRETKEYBYTES 1600 -#define CRYPTO_PUBLICKEYBYTES 1218 -#define CRYPTO_CIPHERTEXTBYTES 1047 -#define CRYPTO_BYTES 32 diff --git a/crypto/libntrup/src/ref/dec.c b/crypto/libntrup/src/ref/dec.c deleted file mode 100644 index c110465b2e..0000000000 --- a/crypto/libntrup/src/ref/dec.c +++ /dev/null @@ -1,75 +0,0 @@ -#ifdef KAT -#include -#endif -#include -#include -#include - -#include "params.h" -#include "small.h" -#include "mod3.h" -#include "rq.h" -#include "r3.h" - -int -crypto_kem_dec_ref(unsigned char *k, const unsigned char *cstr, - const unsigned char *sk) -{ - small f[p]; - modq h[p]; - small grecip[p]; - modq c[p]; - modq t[p]; - small t3[p]; - small r[p]; - modq hr[p]; - unsigned char rstr[small_encode_len]; - unsigned char hash[64]; - int i; - int result = 0; - int weight; - - small_decode(f, sk); - small_decode(grecip, sk + small_encode_len); - rq_decode(h, sk + 2 * small_encode_len); - - rq_decoderounded(c, cstr + 32); - - rq_mult(t, c, f); - for(i = 0; i < p; ++i) - t3[i] = mod3_freeze(modq_freeze(3 * t[i])); - - r3_mult(r, t3, grecip); - -#ifdef KAT - { - int j; - printf("decrypt r:"); - for(j = 0; j < p; ++j) - if(r[j] == 1) - printf(" +%d", j); - else if(r[j] == -1) - printf(" -%d", j); - printf("\n"); - } -#endif - - weight = 0; - for(i = 0; i < p; ++i) - weight += (1 & r[i]); - weight -= w; - result |= modq_nonzero_mask(weight); /* XXX: puts limit on p */ - - rq_mult(hr, h, r); - rq_round3(hr, hr); - for(i = 0; i < p; ++i) - result |= modq_nonzero_mask(hr[i] - c[i]); - - small_encode(rstr, r); - crypto_hash_sha512(hash, rstr, sizeof rstr); - result |= crypto_verify_32(hash, cstr); - - for(i = 0; i < 32; ++i) - k[i] = (hash[32 + i] & ~result); - return result; -} diff --git a/crypto/libntrup/src/ref/enc.c b/crypto/libntrup/src/ref/enc.c deleted file mode 100644 index ccebf73c6d..0000000000 --- a/crypto/libntrup/src/ref/enc.c +++ /dev/null @@ -1,49 +0,0 @@ -#ifdef KAT -#include -#endif - -#include -#include "params.h" -#include "small.h" -#include "rq.h" -#include -#include - -int -crypto_kem_enc_ref(unsigned char *cstr, unsigned char *k, - const unsigned char *pk) -{ - small r[p]; - modq h[p]; - modq c[p]; - unsigned char rstr[small_encode_len]; - unsigned char hash[64]; - - small_random_weightw(r); - -#ifdef KAT - { - int i; - printf("encrypt r:"); - for(i = 0; i < p; ++i) - if(r[i] == 1) - printf(" +%d", i); - else if(r[i] == -1) - printf(" -%d", i); - printf("\n"); - } -#endif - - small_encode(rstr, r); - crypto_hash_sha512(hash, rstr, sizeof rstr); - - rq_decode(h, pk); - rq_mult(c, h, r); - rq_round3(c, c); - - memcpy(k, hash + 32, 32); - memcpy(cstr, hash, 32); - rq_encoderounded(cstr + 32, c); - - return 0; -} diff --git a/crypto/libntrup/src/ref/implementors b/crypto/libntrup/src/ref/implementors deleted file mode 100644 index 51ac31ea2e..0000000000 --- a/crypto/libntrup/src/ref/implementors +++ /dev/null @@ -1,5 +0,0 @@ -Alphabetical order: -Daniel J. Bernstein -Chitchanok Chuengsatiansup -Tanja Lange -Christine van Vredendaal diff --git a/crypto/libntrup/src/ref/int32_sort.c b/crypto/libntrup/src/ref/int32_sort.c deleted file mode 100644 index 21d9cf2389..0000000000 --- a/crypto/libntrup/src/ref/int32_sort.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "int32_sort.h" -#include - -static void -minmax(crypto_int32 *x, crypto_int32 *y) -{ - crypto_uint32 xi = *x; - crypto_uint32 yi = *y; - crypto_uint32 xy = xi ^ yi; - crypto_uint32 c = yi - xi; - c ^= xy & (c ^ yi); - c >>= 31; - c = -c; - c &= xy; - *x = xi ^ c; - *y = yi ^ c; -} - -void -int32_sort(crypto_int32 *x, int n) -{ - int top, p, q, i; - - if(n < 2) - return; - top = 1; - while(top < n - top) - top += top; - - for(p = top; p > 0; p >>= 1) - { - for(i = 0; i < n - p; ++i) - if(!(i & p)) - minmax(x + i, x + i + p); - for(q = top; q > p; q >>= 1) - for(i = 0; i < n - q; ++i) - if(!(i & p)) - minmax(x + i + p, x + i + q); - } -} diff --git a/crypto/libntrup/src/ref/int32_sort.h b/crypto/libntrup/src/ref/int32_sort.h deleted file mode 100644 index 8639a146a0..0000000000 --- a/crypto/libntrup/src/ref/int32_sort.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef int32_sort_h -#define int32_sort_h - -#include - -#define int32_sort crypto_kem_sntrup4591761_ref_int32_sort -extern void -int32_sort(crypto_int32 *, int); - -#endif diff --git a/crypto/libntrup/src/ref/keypair.c b/crypto/libntrup/src/ref/keypair.c deleted file mode 100644 index 4e5d0522c7..0000000000 --- a/crypto/libntrup/src/ref/keypair.c +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include "modq.h" -#include "params.h" -#include "r3.h" -#include "small.h" -#include "rq.h" -#include - -#if crypto_kem_PUBLICKEYBYTES != rq_encode_len -#error "crypto_kem_PUBLICKEYBYTES must match rq_encode_len" -#endif -#if crypto_kem_SECRETKEYBYTES != rq_encode_len + 2 * small_encode_len -#error \ - "crypto_kem_SECRETKEYBYTES must match rq_encode_len + 2 * small_encode_len" -#endif - -int -crypto_kem_keypair_ref(unsigned char *pk, unsigned char *sk) -{ - small g[p]; - small grecip[p]; - small f[p]; - modq f3recip[p]; - modq h[p]; - - do - small_random(g); - while(r3_recip(grecip, g) != 0); - - small_random_weightw(f); - rq_recip3(f3recip, f); - - rq_mult(h, f3recip, g); - - rq_encode(pk, h); - small_encode(sk, f); - small_encode(sk + small_encode_len, grecip); - memcpy(sk + 2 * small_encode_len, pk, rq_encode_len); - - return 0; -} diff --git a/crypto/libntrup/src/ref/mod3.h b/crypto/libntrup/src/ref/mod3.h deleted file mode 100644 index 97ec3b55fa..0000000000 --- a/crypto/libntrup/src/ref/mod3.h +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef mod3_h -#define mod3_h - -#include "small.h" -#include - -/* -1 if x is nonzero, 0 otherwise */ -static inline int -mod3_nonzero_mask(small x) -{ - return -x * x; -} - -/* input between -100000 and 100000 */ -/* output between -1 and 1 */ -static inline small -mod3_freeze(crypto_int32 a) -{ - a -= 3 * ((10923 * a) >> 15); - a -= 3 * ((89478485 * a + 134217728) >> 28); - return a; -} - -static inline small -mod3_minusproduct(small a, small b, small c) -{ - crypto_int32 A = a; - crypto_int32 B = b; - crypto_int32 C = c; - return mod3_freeze(A - B * C); -} - -static inline small -mod3_plusproduct(small a, small b, small c) -{ - crypto_int32 A = a; - crypto_int32 B = b; - crypto_int32 C = c; - return mod3_freeze(A + B * C); -} - -static inline small -mod3_product(small a, small b) -{ - return a * b; -} - -static inline small -mod3_sum(small a, small b) -{ - crypto_int32 A = a; - crypto_int32 B = b; - return mod3_freeze(A + B); -} - -static inline small -mod3_reciprocal(small a1) -{ - return a1; -} - -static inline small -mod3_quotient(small num, small den) -{ - return mod3_product(num, mod3_reciprocal(den)); -} - -#endif diff --git a/crypto/libntrup/src/ref/modq.h b/crypto/libntrup/src/ref/modq.h deleted file mode 100644 index 6484a4f96a..0000000000 --- a/crypto/libntrup/src/ref/modq.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef modq_h -#define modq_h - -#include -#include -#include -#include - -typedef crypto_int16 modq; - -/* -1 if x is nonzero, 0 otherwise */ -static inline int -modq_nonzero_mask(modq x) -{ - crypto_int32 r = (crypto_uint16)x; - r = -r; - r >>= 30; - return r; -} - -/* input between -9000000 and 9000000 */ -/* output between -2295 and 2295 */ -static inline modq -modq_freeze(crypto_int32 a) -{ - a -= 4591 * ((228 * a) >> 20); - a -= 4591 * ((58470 * a + 134217728) >> 28); - return a; -} - -static inline modq -modq_minusproduct(modq a, modq b, modq c) -{ - crypto_int32 A = a; - crypto_int32 B = b; - crypto_int32 C = c; - return modq_freeze(A - B * C); -} - -static inline modq -modq_plusproduct(modq a, modq b, modq c) -{ - crypto_int32 A = a; - crypto_int32 B = b; - crypto_int32 C = c; - return modq_freeze(A + B * C); -} - -static inline modq -modq_product(modq a, modq b) -{ - crypto_int32 A = a; - crypto_int32 B = b; - return modq_freeze(A * B); -} - -static inline modq -modq_square(modq a) -{ - crypto_int32 A = a; - return modq_freeze(A * A); -} - -static inline modq -modq_sum(modq a, modq b) -{ - crypto_int32 A = a; - crypto_int32 B = b; - return modq_freeze(A + B); -} - -static inline modq -modq_reciprocal(modq a1) -{ - modq a2 = modq_square(a1); - modq a3 = modq_product(a2, a1); - modq a4 = modq_square(a2); - modq a8 = modq_square(a4); - modq a16 = modq_square(a8); - modq a32 = modq_square(a16); - modq a35 = modq_product(a32, a3); - modq a70 = modq_square(a35); - modq a140 = modq_square(a70); - modq a143 = modq_product(a140, a3); - modq a286 = modq_square(a143); - modq a572 = modq_square(a286); - modq a1144 = modq_square(a572); - modq a1147 = modq_product(a1144, a3); - modq a2294 = modq_square(a1147); - modq a4588 = modq_square(a2294); - modq a4589 = modq_product(a4588, a1); - return a4589; -} - -static inline modq -modq_quotient(modq num, modq den) -{ - return modq_product(num, modq_reciprocal(den)); -} - -#endif diff --git a/crypto/libntrup/src/ref/params.h b/crypto/libntrup/src/ref/params.h deleted file mode 100644 index c55d435e19..0000000000 --- a/crypto/libntrup/src/ref/params.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef params_h -#define params_h - -#define q 4591 -/* XXX: also built into modq in various ways */ - -#define qshift 2295 -#define p 761 -#ifdef _MSC_VER -#define LOOPS 2 * p + 1 -#endif -#define w 286 - -#define rq_encode_len 1218 -#define small_encode_len 191 - -#endif diff --git a/crypto/libntrup/src/ref/r3.h b/crypto/libntrup/src/ref/r3.h deleted file mode 100644 index 07a5fb4b96..0000000000 --- a/crypto/libntrup/src/ref/r3.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef r3_h -#define r3_h - -#include "small.h" - -#define r3_mult crypto_kem_sntrup4591761_ref_r3_mult -extern void -r3_mult(small *, const small *, const small *); - -#define r3_recip crypto_kem_sntrup4591761_ref_r3_recip -extern int -r3_recip(small *, const small *); - -#endif diff --git a/crypto/libntrup/src/ref/r3_mult.c b/crypto/libntrup/src/ref/r3_mult.c deleted file mode 100644 index 8569315b1c..0000000000 --- a/crypto/libntrup/src/ref/r3_mult.c +++ /dev/null @@ -1,35 +0,0 @@ -#include "params.h" -#include "mod3.h" -#include "r3.h" - -void -r3_mult(small *h, const small *f, const small *g) -{ - small fg[p + p - 1]; - small result; - int i, j; - - for(i = 0; i < p; ++i) - { - result = 0; - for(j = 0; j <= i; ++j) - result = mod3_plusproduct(result, f[j], g[i - j]); - fg[i] = result; - } - for(i = p; i < p + p - 1; ++i) - { - result = 0; - for(j = i - p + 1; j < p; ++j) - result = mod3_plusproduct(result, f[j], g[i - j]); - fg[i] = result; - } - - for(i = p + p - 2; i >= p; --i) - { - fg[i - p] = mod3_sum(fg[i - p], fg[i]); - fg[i - p + 1] = mod3_sum(fg[i - p + 1], fg[i]); - } - - for(i = 0; i < p; ++i) - h[i] = fg[i]; -} diff --git a/crypto/libntrup/src/ref/r3_recip.c b/crypto/libntrup/src/ref/r3_recip.c deleted file mode 100644 index 567c6a30c3..0000000000 --- a/crypto/libntrup/src/ref/r3_recip.c +++ /dev/null @@ -1,151 +0,0 @@ -#include "params.h" -#include "mod3.h" -#include "swap.h" -#include "r3.h" - -/* caller must ensure that x-y does not overflow */ -static int -smaller_mask(int x, int y) -{ - return (x - y) >> 31; -} - -static void -vectormod3_product(small *z, int len, const small *x, const small c) -{ - int i; - for(i = 0; i < len; ++i) - z[i] = mod3_product(x[i], c); -} - -static void -vectormod3_minusproduct(small *z, int len, const small *x, const small *y, - const small c) -{ - int i; - for(i = 0; i < len; ++i) - z[i] = mod3_minusproduct(x[i], y[i], c); -} - -static void -vectormod3_shift(small *z, int len) -{ - int i; - for(i = len - 1; i > 0; --i) - z[i] = z[i - 1]; - z[0] = 0; -} - -/* -r = s^(-1) mod m, returning 0, if s is invertible mod m -or returning -1 if s is not invertible mod m -r,s are polys of degree

= LOOPS) - break; - - c = mod3_quotient(g[p], f[p]); - - vectormod3_minusproduct(g, p + 1, g, f, c); - vectormod3_shift(g, p + 1); - -#ifdef SIMPLER - vectormod3_minusproduct(v, loops + 1, v, u, c); - vectormod3_shift(v, loops + 1); -#else - if(loop < p) - { - vectormod3_minusproduct(v, loop + 1, v, u, c); - vectormod3_shift(v, loop + 2); - } - else - { - vectormod3_minusproduct(v + loop - p, p + 1, v + loop - p, u + loop - p, - c); - vectormod3_shift(v + loop - p, p + 2); - } -#endif - - e -= 1; - - ++loop; - - swapmask = smaller_mask(e, d) & mod3_nonzero_mask(g[p]); - swap(&e, &d, sizeof e, swapmask); - swap(f, g, (p + 1) * sizeof(small), swapmask); - -#ifdef SIMPLER - swap(u, v, (loops + 1) * sizeof(small), swapmask); -#else - if(loop < p) - { - swap(u, v, (loop + 1) * sizeof(small), swapmask); - } - else - { - swap(u + loop - p, v + loop - p, (p + 1) * sizeof(small), swapmask); - } -#endif - } - - c = mod3_reciprocal(f[p]); - vectormod3_product(r, p, u + p, c); - return smaller_mask(0, d); -} diff --git a/crypto/libntrup/src/ref/random32.c b/crypto/libntrup/src/ref/random32.c deleted file mode 100644 index be1a764a7c..0000000000 --- a/crypto/libntrup/src/ref/random32.c +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include "small.h" - -#ifdef KAT -/* NIST KAT generator fails to provide chunk-independence */ -static unsigned char x[4 * 761]; -static long long pos = 4 * 761; -#endif - -crypto_int32 -small_random32(void) -{ -#ifdef KAT - if(pos == 4 * 761) - { - randombytes(x, sizeof x); - pos = 0; - } - pos += 4; - return x[pos - 4] + (x[pos - 3] << 8) + (x[pos - 2] << 16) - + (x[pos - 1] << 24); -#else - unsigned char x[4]; - randombytes(x, 4); - uint32_t x4 = x[3] << 24; - return x[0] + (x[1] << 8) + (x[2] << 16) + x4; -#endif -} diff --git a/crypto/libntrup/src/ref/randomsmall.c b/crypto/libntrup/src/ref/randomsmall.c deleted file mode 100644 index 1c417ff259..0000000000 --- a/crypto/libntrup/src/ref/randomsmall.c +++ /dev/null @@ -1,16 +0,0 @@ -#include "params.h" -#include -#include -#include "small.h" - -void -small_random(small *g) -{ - int i; - - for(i = 0; i < p; ++i) - { - crypto_uint32 r = small_random32(); - g[i] = (small)(((1073741823 & r) * 3) >> 30) - 1; - } -} diff --git a/crypto/libntrup/src/ref/randomweightw.c b/crypto/libntrup/src/ref/randomweightw.c deleted file mode 100644 index 75a0f0f36e..0000000000 --- a/crypto/libntrup/src/ref/randomweightw.c +++ /dev/null @@ -1,21 +0,0 @@ -#include "params.h" -#include -#include "int32_sort.h" -#include "small.h" - -void -small_random_weightw(small *f) -{ - crypto_int32 r[p]; - int i; - - for(i = 0; i < p; ++i) - r[i] = small_random32(); - for(i = 0; i < w; ++i) - r[i] &= -2; - for(i = w; i < p; ++i) - r[i] = (r[i] & -3) | 1; - int32_sort(r, p); - for(i = 0; i < p; ++i) - f[i] = ((small)(r[i] & 3)) - 1; -} diff --git a/crypto/libntrup/src/ref/rq.c b/crypto/libntrup/src/ref/rq.c deleted file mode 100644 index 36c21ed7d2..0000000000 --- a/crypto/libntrup/src/ref/rq.c +++ /dev/null @@ -1,142 +0,0 @@ -#include "params.h" -#include "rq.h" - -void -rq_encode(unsigned char *c, const modq *f) -{ - crypto_int32 f0, f1, f2, f3, f4; - int i; - - for(i = 0; i < p / 5; ++i) - { - f0 = *f++ + qshift; - f1 = *f++ + qshift; - f2 = *f++ + qshift; - f3 = *f++ + qshift; - f4 = *f++ + qshift; - /* now want f0 + 6144*f1 + ... as a 64-bit integer */ - f1 *= 3; - f2 *= 9; - f3 *= 27; - f4 *= 81; - /* now want f0 + f1<<11 + f2<<22 + f3<<33 + f4<<44 */ - f0 += f1 << 11; - *c++ = f0; - f0 >>= 8; - *c++ = f0; - f0 >>= 8; - f0 += f2 << 6; - *c++ = f0; - f0 >>= 8; - *c++ = f0; - f0 >>= 8; - f0 += f3 << 1; - *c++ = f0; - f0 >>= 8; - f0 += f4 << 4; - *c++ = f0; - f0 >>= 8; - *c++ = f0; - f0 >>= 8; - *c++ = f0; - } - /* XXX: using p mod 5 = 1 */ - f0 = *f++ + qshift; - *c++ = f0; - f0 >>= 8; - *c++ = f0; -} - -void -rq_decode(modq *f, const unsigned char *c) -{ - crypto_uint32 c0, c1, c2, c3, c4, c5, c6, c7; - crypto_uint32 f0, f1, f2, f3, f4; - int i; - - for(i = 0; i < p / 5; ++i) - { - c0 = *c++; - c1 = *c++; - c2 = *c++; - c3 = *c++; - c4 = *c++; - c5 = *c++; - c6 = *c++; - c7 = *c++; - - /* f0 + f1*6144 + f2*6144^2 + f3*6144^3 + f4*6144^4 */ - /* = c0 + c1*256 + ... + c6*256^6 + c7*256^7 */ - /* with each f between 0 and 4590 */ - - c6 += c7 << 8; - /* c6 <= 23241 = floor(4591*6144^4/2^48) */ - /* f4 = (16/81)c6 + (1/1296)(c5+[0,1]) - [0,0.75] */ - /* claim: 2^19 f4 < x < 2^19(f4+1) */ - /* where x = 103564 c6 + 405(c5+1) */ - /* proof: x - 2^19 f4 = (76/81)c6 + (37/81)c5 + 405 - (32768/81)[0,1] + - * 2^19[0,0.75] */ - /* at least 405 - 32768/81 > 0 */ - /* at most (76/81)23241 + (37/81)255 + 405 + 2^19 0.75 < 2^19 */ - f4 = (103564 * c6 + 405 * (c5 + 1)) >> 19; - - c5 += c6 << 8; - c5 -= (f4 * 81) << 4; - c4 += c5 << 8; - - /* f0 + f1*6144 + f2*6144^2 + f3*6144^3 */ - /* = c0 + c1*256 + c2*256^2 + c3*256^3 + c4*256^4 */ - /* c4 <= 247914 = floor(4591*6144^3/2^32) */ - /* f3 = (1/54)(c4+[0,1]) - [0,0.75] */ - /* claim: 2^19 f3 < x < 2^19(f3+1) */ - /* where x = 9709(c4+2) */ - /* proof: x - 2^19 f3 = 19418 - (1/27)c4 - (262144/27)[0,1] + 2^19[0,0.75] - */ - /* at least 19418 - 247914/27 - 262144/27 > 0 */ - /* at most 19418 + 2^19 0.75 < 2^19 */ - f3 = (9709 * (c4 + 2)) >> 19; - - c4 -= (f3 * 27) << 1; - c3 += c4 << 8; - /* f0 + f1*6144 + f2*6144^2 */ - /* = c0 + c1*256 + c2*256^2 + c3*256^3 */ - /* c3 <= 10329 = floor(4591*6144^2/2^24) */ - /* f2 = (4/9)c3 + (1/576)c2 + (1/147456)c1 + (1/37748736)c0 - [0,0.75] */ - /* claim: 2^19 f2 < x < 2^19(f2+1) */ - /* where x = 233017 c3 + 910(c2+2) */ - /* proof: x - 2^19 f2 = 1820 + (1/9)c3 - (2/9)c2 - (32/9)c1 - (1/72)c0 + - * 2^19[0,0.75] */ - /* at least 1820 - (2/9)255 - (32/9)255 - (1/72)255 > 0 */ - /* at most 1820 + (1/9)10329 + 2^19 0.75 < 2^19 */ - f2 = (233017 * c3 + 910 * (c2 + 2)) >> 19; - - c2 += c3 << 8; - c2 -= (f2 * 9) << 6; - c1 += c2 << 8; - /* f0 + f1*6144 */ - /* = c0 + c1*256 */ - /* c1 <= 110184 = floor(4591*6144/2^8) */ - /* f1 = (1/24)c1 + (1/6144)c0 - (1/6144)f0 */ - /* claim: 2^19 f1 < x < 2^19(f1+1) */ - /* where x = 21845(c1+2) + 85 c0 */ - /* proof: x - 2^19 f1 = 43690 - (1/3)c1 - (1/3)c0 + 2^19 [0,0.75] */ - /* at least 43690 - (1/3)110184 - (1/3)255 > 0 */ - /* at most 43690 + 2^19 0.75 < 2^19 */ - f1 = (21845 * (c1 + 2) + 85 * c0) >> 19; - - c1 -= (f1 * 3) << 3; - c0 += c1 << 8; - f0 = c0; - - *f++ = modq_freeze(f0 + q - qshift); - *f++ = modq_freeze(f1 + q - qshift); - *f++ = modq_freeze(f2 + q - qshift); - *f++ = modq_freeze(f3 + q - qshift); - *f++ = modq_freeze(f4 + q - qshift); - } - - c0 = *c++; - c1 = *c++; - c0 += c1 << 8; - *f++ = modq_freeze(c0 + q - qshift); -} diff --git a/crypto/libntrup/src/ref/rq.h b/crypto/libntrup/src/ref/rq.h deleted file mode 100644 index 69d800d95d..0000000000 --- a/crypto/libntrup/src/ref/rq.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef rq_h -#define rq_h - -#include "modq.h" -#include "small.h" - -#define rq_encode crypto_kem_sntrup4591761_ref_rq_encode -extern void -rq_encode(unsigned char *, const modq *); - -#define rq_decode crypto_kem_sntrup4591761_ref_rq_decode -extern void -rq_decode(modq *, const unsigned char *); - -#define rq_encoderounded crypto_kem_sntrup4591761_ref_rq_encoderounded -extern void -rq_encoderounded(unsigned char *, const modq *); - -#define rq_decoderounded crypto_kem_sntrup4591761_ref_rq_decoderounded -extern void -rq_decoderounded(modq *, const unsigned char *); - -#define rq_round3 crypto_kem_sntrup4591761_ref_rq_round -extern void -rq_round3(modq *, const modq *); - -#define rq_mult crypto_kem_sntrup4591761_ref_rq_mult -extern void -rq_mult(modq *, const modq *, const small *); - -#define rq_recip3 crypto_kem_sntrup4591761_ref_rq_recip3 -int -rq_recip3(modq *, const small *); - -#endif diff --git a/crypto/libntrup/src/ref/rq_mult.c b/crypto/libntrup/src/ref/rq_mult.c deleted file mode 100644 index e8be2f2cf1..0000000000 --- a/crypto/libntrup/src/ref/rq_mult.c +++ /dev/null @@ -1,34 +0,0 @@ -#include "params.h" -#include "rq.h" - -void -rq_mult(modq *h, const modq *f, const small *g) -{ - modq fg[p + p - 1]; - modq result; - int i, j; - - for(i = 0; i < p; ++i) - { - result = 0; - for(j = 0; j <= i; ++j) - result = modq_plusproduct(result, f[j], g[i - j]); - fg[i] = result; - } - for(i = p; i < p + p - 1; ++i) - { - result = 0; - for(j = i - p + 1; j < p; ++j) - result = modq_plusproduct(result, f[j], g[i - j]); - fg[i] = result; - } - - for(i = p + p - 2; i >= p; --i) - { - fg[i - p] = modq_sum(fg[i - p], fg[i]); - fg[i - p + 1] = modq_sum(fg[i - p + 1], fg[i]); - } - - for(i = 0; i < p; ++i) - h[i] = fg[i]; -} diff --git a/crypto/libntrup/src/ref/rq_recip3.c b/crypto/libntrup/src/ref/rq_recip3.c deleted file mode 100644 index 78e8c63d64..0000000000 --- a/crypto/libntrup/src/ref/rq_recip3.c +++ /dev/null @@ -1,151 +0,0 @@ -#include "params.h" -#include "swap.h" -#include "rq.h" - -/* caller must ensure that x-y does not overflow */ -static int -smaller_mask(int x, int y) -{ - return (x - y) >> 31; -} - -static void -vectormodq_product(modq *z, int len, const modq *x, const modq c) -{ - int i; - for(i = 0; i < len; ++i) - z[i] = modq_product(x[i], c); -} - -static void -vectormodq_minusproduct(modq *z, int len, const modq *x, const modq *y, - const modq c) -{ - int i; - for(i = 0; i < len; ++i) - z[i] = modq_minusproduct(x[i], y[i], c); -} - -static void -vectormodq_shift(modq *z, int len) -{ - int i; - for(i = len - 1; i > 0; --i) - z[i] = z[i - 1]; - z[0] = 0; -} - -/* -r = (3s)^(-1) mod m, returning 0, if s is invertible mod m -or returning -1 if s is not invertible mod m -r,s are polys of degree

= LOOPS) - break; - - c = modq_quotient(g[p], f[p]); - - vectormodq_minusproduct(g, p + 1, g, f, c); - vectormodq_shift(g, p + 1); - -#ifdef SIMPLER - vectormodq_minusproduct(v, loops + 1, v, u, c); - vectormodq_shift(v, loops + 1); -#else - if(loop < p) - { - vectormodq_minusproduct(v, loop + 1, v, u, c); - vectormodq_shift(v, loop + 2); - } - else - { - vectormodq_minusproduct(v + loop - p, p + 1, v + loop - p, u + loop - p, - c); - vectormodq_shift(v + loop - p, p + 2); - } -#endif - - e -= 1; - - ++loop; - - swapmask = smaller_mask(e, d) & modq_nonzero_mask(g[p]); - swap(&e, &d, sizeof e, swapmask); - swap(f, g, (p + 1) * sizeof(modq), swapmask); - -#ifdef SIMPLER - swap(u, v, (loops + 1) * sizeof(modq), swapmask); -#else - if(loop < p) - { - swap(u, v, (loop + 1) * sizeof(modq), swapmask); - } - else - { - swap(u + loop - p, v + loop - p, (p + 1) * sizeof(modq), swapmask); - } -#endif - } - - c = modq_reciprocal(f[p]); - vectormodq_product(r, p, u + p, c); - return smaller_mask(0, d); -} diff --git a/crypto/libntrup/src/ref/rq_round3.c b/crypto/libntrup/src/ref/rq_round3.c deleted file mode 100644 index 41853a30a1..0000000000 --- a/crypto/libntrup/src/ref/rq_round3.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "params.h" -#include "rq.h" - -void -rq_round3(modq *h, const modq *f) -{ - int i; - - for(i = 0; i < p; ++i) - h[i] = ((21846 * (f[i] + 2295) + 32768) >> 16) * 3 - 2295; -} diff --git a/crypto/libntrup/src/ref/rq_rounded.c b/crypto/libntrup/src/ref/rq_rounded.c deleted file mode 100644 index f524f3b3c6..0000000000 --- a/crypto/libntrup/src/ref/rq_rounded.c +++ /dev/null @@ -1,111 +0,0 @@ -#include "params.h" -#include -#include "rq.h" - -void -rq_encoderounded(unsigned char *c, const modq *f) -{ - crypto_int32 f0, f1, f2; - int i; - - for(i = 0; i < p / 3; ++i) - { - f0 = *f++ + qshift; - f1 = *f++ + qshift; - f2 = *f++ + qshift; - f0 = (21846 * f0) >> 16; - f1 = (21846 * f1) >> 16; - f2 = (21846 * f2) >> 16; - /* now want f0 + f1*1536 + f2*1536^2 as a 32-bit integer */ - f2 *= 3; - f1 += f2 << 9; - f1 *= 3; - f0 += f1 << 9; - *c++ = f0; - f0 >>= 8; - *c++ = f0; - f0 >>= 8; - *c++ = f0; - f0 >>= 8; - *c++ = f0; - } - /* XXX: using p mod 3 = 2 */ - f0 = *f++ + qshift; - f1 = *f++ + qshift; - f0 = (21846 * f0) >> 16; - f1 = (21846 * f1) >> 16; - f1 *= 3; - f0 += f1 << 9; - *c++ = f0; - f0 >>= 8; - *c++ = f0; - f0 >>= 8; - *c++ = f0; -} - -void -rq_decoderounded(modq *f, const unsigned char *c) -{ - crypto_uint32 c0, c1, c2, c3; - crypto_uint32 f0, f1, f2; - int i; - - for(i = 0; i < p / 3; ++i) - { - c0 = *c++; - c1 = *c++; - c2 = *c++; - c3 = *c++; - - /* f0 + f1*1536 + f2*1536^2 */ - /* = c0 + c1*256 + c2*256^2 + c3*256^3 */ - /* with each f between 0 and 1530 */ - - /* f2 = (64/9)c3 + (1/36)c2 + (1/9216)c1 + (1/2359296)c0 - [0,0.99675] */ - /* claim: 2^21 f2 < x < 2^21(f2+1) */ - /* where x = 14913081*c3 + 58254*c2 + 228*(c1+2) */ - /* proof: x - 2^21 f2 = 456 - (8/9)c0 + (4/9)c1 - (2/9)c2 + (1/9)c3 + 2^21 - * [0,0.99675] */ - /* at least 456 - (8/9)255 - (2/9)255 > 0 */ - /* at most 456 + (4/9)255 + (1/9)255 + 2^21 0.99675 < 2^21 */ - f2 = (14913081 * c3 + 58254 * c2 + 228 * (c1 + 2)) >> 21; - - c2 += c3 << 8; - c2 -= (f2 * 9) << 2; - /* f0 + f1*1536 */ - /* = c0 + c1*256 + c2*256^2 */ - /* c2 <= 35 = floor((1530+1530*1536)/256^2) */ - /* f1 = (128/3)c2 + (1/6)c1 + (1/1536)c0 - (1/1536)f0 */ - /* claim: 2^21 f1 < x < 2^21(f1+1) */ - /* where x = 89478485*c2 + 349525*c1 + 1365*(c0+1) */ - /* proof: x - 2^21 f1 = 1365 - (1/3)c2 - (1/3)c1 - (1/3)c0 + (4096/3)f0 */ - /* at least 1365 - (1/3)35 - (1/3)255 - (1/3)255 > 0 */ - /* at most 1365 + (4096/3)1530 < 2^21 */ - f1 = (89478485 * c2 + 349525 * c1 + 1365 * (c0 + 1)) >> 21; - - c1 += c2 << 8; - c1 -= (f1 * 3) << 1; - - c0 += c1 << 8; - f0 = c0; - - *f++ = modq_freeze(f0 * 3 + q - qshift); - *f++ = modq_freeze(f1 * 3 + q - qshift); - *f++ = modq_freeze(f2 * 3 + q - qshift); - } - - c0 = *c++; - c1 = *c++; - c2 = *c++; - - f1 = (89478485 * c2 + 349525 * c1 + 1365 * (c0 + 1)) >> 21; - - c1 += c2 << 8; - c1 -= (f1 * 3) << 1; - - c0 += c1 << 8; - f0 = c0; - - *f++ = modq_freeze(f0 * 3 + q - qshift); - *f++ = modq_freeze(f1 * 3 + q - qshift); -} diff --git a/crypto/libntrup/src/ref/small.c b/crypto/libntrup/src/ref/small.c deleted file mode 100644 index 209de23693..0000000000 --- a/crypto/libntrup/src/ref/small.c +++ /dev/null @@ -1,44 +0,0 @@ -#include "params.h" -#include "small.h" - -/* XXX: these functions rely on p mod 4 = 1 */ - -/* all coefficients in -1, 0, 1 */ -void -small_encode(unsigned char *c, const small *f) -{ - small c0; - int i; - - for(i = 0; i < p / 4; ++i) - { - c0 = *f++ + 1; - c0 += (*f++ + 1) << 2; - c0 += (*f++ + 1) << 4; - c0 += (*f++ + 1) << 6; - *c++ = c0; - } - c0 = *f++ + 1; - *c++ = c0; -} - -void -small_decode(small *f, const unsigned char *c) -{ - unsigned char c0; - int i; - - for(i = 0; i < p / 4; ++i) - { - c0 = *c++; - *f++ = ((small)(c0 & 3)) - 1; - c0 >>= 2; - *f++ = ((small)(c0 & 3)) - 1; - c0 >>= 2; - *f++ = ((small)(c0 & 3)) - 1; - c0 >>= 2; - *f++ = ((small)(c0 & 3)) - 1; - } - c0 = *c++; - *f++ = ((small)(c0 & 3)) - 1; -} diff --git a/crypto/libntrup/src/ref/small.h b/crypto/libntrup/src/ref/small.h deleted file mode 100644 index de58ef9d05..0000000000 --- a/crypto/libntrup/src/ref/small.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef small_h -#define small_h - -#include -#include - -typedef crypto_int8 small; - -#define small_encode crypto_kem_sntrup4591761_ref_small_encode -extern void -small_encode(unsigned char *, const small *); - -#define small_decode crypto_kem_sntrup4591761_ref_small_decode -extern void -small_decode(small *, const unsigned char *); - -#define small_random32 crypto_kem_sntrup4591761_ref_small_random32 -extern crypto_int32 -small_random32(void); - -#define small_random crypto_kem_sntrup4591761_ref_small_random -extern void -small_random(small *); - -#define small_random_weightw crypto_kem_sntrup4591761_ref_small_random_weightw -extern void -small_random_weightw(small *); - -#endif diff --git a/crypto/libntrup/src/ref/swap.c b/crypto/libntrup/src/ref/swap.c deleted file mode 100644 index 2051f1c5d8..0000000000 --- a/crypto/libntrup/src/ref/swap.c +++ /dev/null @@ -1,21 +0,0 @@ -#include "swap.h" - -void -swap(void *x, void *y, int bytes, int mask) -{ - int i; - char xi, yi, c, t; - - c = mask; - - for(i = 0; i < bytes; ++i) - { - xi = i[(char *)x]; - yi = i[(char *)y]; - t = c & (xi ^ yi); - xi ^= t; - yi ^= t; - i[(char *)x] = xi; - i[(char *)y] = yi; - } -} diff --git a/crypto/libntrup/src/ref/swap.h b/crypto/libntrup/src/ref/swap.h deleted file mode 100644 index 2c3f3a8a55..0000000000 --- a/crypto/libntrup/src/ref/swap.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef swap_h -#define swap_h - -#define swap crypto_kem_sntrup4591761_ref_swap -extern void -swap(void *, void *, int, int); - -#endif diff --git a/crypto/ntruprime-20171206/crypto_kem/sntrup4591761/checksumbig b/crypto/ntruprime-20171206/crypto_kem/sntrup4591761/checksumbig deleted file mode 100644 index a366c4e704..0000000000 --- a/crypto/ntruprime-20171206/crypto_kem/sntrup4591761/checksumbig +++ /dev/null @@ -1 +0,0 @@ -83705d49d3a8cb2e16028b86ea6bd44a969b51c2e5114ee02767cf2ddf1aac26 diff --git a/crypto/ntruprime-20171206/crypto_kem/sntrup4591761/checksumsmall b/crypto/ntruprime-20171206/crypto_kem/sntrup4591761/checksumsmall deleted file mode 100644 index d87bd217b8..0000000000 --- a/crypto/ntruprime-20171206/crypto_kem/sntrup4591761/checksumsmall +++ /dev/null @@ -1 +0,0 @@ -336647fe0ed2f6e0d4b15d05e68faec67a81312d769ad3cbee8e0f2de83c2dde diff --git a/crypto/ntruprime-20171206/crypto_kem/sntrup4591761/description b/crypto/ntruprime-20171206/crypto_kem/sntrup4591761/description deleted file mode 100644 index 7827a166d0..0000000000 --- a/crypto/ntruprime-20171206/crypto_kem/sntrup4591761/description +++ /dev/null @@ -1 +0,0 @@ -Streamlined NTRU Prime 4591^761 diff --git a/crypto/ntruprime-20171206/crypto_kem/sntrup4591761/designers b/crypto/ntruprime-20171206/crypto_kem/sntrup4591761/designers deleted file mode 100644 index 51ac31ea2e..0000000000 --- a/crypto/ntruprime-20171206/crypto_kem/sntrup4591761/designers +++ /dev/null @@ -1,5 +0,0 @@ -Alphabetical order: -Daniel J. Bernstein -Chitchanok Chuengsatiansup -Tanja Lange -Christine van Vredendaal diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in index 95afd645fb..4348e09953 100644 --- a/docs/Doxyfile.in +++ b/docs/Doxyfile.in @@ -8,7 +8,7 @@ ALIASES = "rst=\verbatim embed:rst" ALIASES += "endrst=\endverbatim" BUILTIN_STL_SUPPORT = YES INPUT = @lokinet_doc_sources_spaced@ -INCLUDE_PATH = @PROJECT_SOURCE_DIR@/include @PROJECT_SOURCE_DIR@/llarp @PROJECT_SOURCE_DIR@/crypto/libntrup/include @PROJECT_SOURCE_DIR@/external/ghc-filesystem/include/ +INCLUDE_PATH = @PROJECT_SOURCE_DIR@/include @PROJECT_SOURCE_DIR@/llarp @PROJECT_SOURCE_DIR@/external/ghc-filesystem/include/ RECURSIVE = YES CLANG_ASSISTED_PARSING = NO #CLANG_OPTIONS = -std=c++17 -Wno-pragma-once-outside-header @@ -17,4 +17,4 @@ HTML_OUTPUT = doxyhtml GENERATE_LATEX = NO GENERATE_XML = YES XML_OUTPUT = doxyxml -MACRO_EXPANSION = YES \ No newline at end of file +MACRO_EXPANSION = YES diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index 877b9215ac..75c88aa5ec 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -19,7 +19,7 @@ lokinet_add_library(lokinet-cryptography # Functional objects use by lokinet-core and other libraries # needed by vpn/ router/ rpc/ handlers/ net/ link/ lokinet_add_library(lokinet-core-utils - # endpoint_base.cpp +# endpoint_base.cpp auth/file_auth.cpp auth/rpc_auth.cpp @@ -72,7 +72,7 @@ lokinet_add_library(lokinet-utils ${CMAKE_CURRENT_BINARY_DIR}/constants/version.cpp util/buffer.cpp util/file.cpp -# util/logging/buffer.cpp +# util/logging/buffer.cpp util/mem.cpp util/str.cpp util/thread/threading.cpp @@ -82,6 +82,13 @@ lokinet_add_library(lokinet-utils add_dependencies(lokinet-utils genversion) +lokinet_add_library(lokinet-contact + contact/router_contact.cpp + contact/router_contact_local.cpp + contact/router_contact_remote.cpp + contact/router_id.cpp +) + # Addressing and event loop files used by lokinet-core and other libraries # needed by rpc/ link/ service/ config/ path/ dht/ lokinet_add_library(lokinet-addressing @@ -99,10 +106,6 @@ lokinet_add_library(lokinet-addressing net/ip.cpp net/net_int.cpp - router_contact.cpp # TODO: move these + router_id.cpp to lokinet-core-utils..? - router_contact_local.cpp - router_contact_remote.cpp - router_id.cpp router_version.cpp # to be deleted shortly service/tag.cpp @@ -224,7 +227,7 @@ target_link_libraries(lokinet-dns PUBLIC lokinet-utils lokinet-cryptography loki target_link_libraries(lokinet-nodedb PUBLIC lokinet-addressing lokinet-cryptography) target_link_libraries(lokinet-platform PUBLIC lokinet-cryptography) target_link_libraries(lokinet-rpc PUBLIC lokinet-wire) -target_link_libraries(lokinet-addressing PUBLIC lokinet-utils lokinet-cryptography) +target_link_libraries(lokinet-addressing PUBLIC lokinet-utils lokinet-cryptography lokinet-contact) target_link_libraries(lokinet-wire PUBLIC lokinet-cryptography) target_link_libraries(lokinet-config PUBLIC lokinet-cryptography) @@ -249,7 +252,6 @@ target_link_libraries(lokinet-core-utils target_link_libraries(lokinet-cryptography PUBLIC lokinet-libcrypt - lokinet-libntrup ) target_link_libraries(lokinet-utils diff --git a/llarp/address/address.hpp b/llarp/address/address.hpp index 3b54d178d1..92e12194d1 100644 --- a/llarp/address/address.hpp +++ b/llarp/address/address.hpp @@ -3,7 +3,7 @@ #include "keys.hpp" #include "utils.hpp" -#include +#include #include #include #include diff --git a/llarp/auth/auth.hpp b/llarp/auth/auth.hpp index 85b23cf7fe..86984d2965 100644 --- a/llarp/auth/auth.hpp +++ b/llarp/auth/auth.hpp @@ -3,8 +3,8 @@ #include "types.hpp" #include +#include #include -#include #include #include #include diff --git a/llarp/bootstrap.hpp b/llarp/bootstrap.hpp index 83f973676d..71c1cf9104 100644 --- a/llarp/bootstrap.hpp +++ b/llarp/bootstrap.hpp @@ -1,7 +1,6 @@ #pragma once -#include "router_contact.hpp" - +#include #include #include diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index 51e8aae3d1..96dc35465f 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -8,12 +8,12 @@ #include #include #include +#include #include #include #include #include #include -#include #include #include diff --git a/llarp/consensus/reachability_testing.hpp b/llarp/consensus/reachability_testing.hpp index 5bad910c31..0315ba0608 100644 --- a/llarp/consensus/reachability_testing.hpp +++ b/llarp/consensus/reachability_testing.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/llarp/router_contact.cpp b/llarp/contact/router_contact.cpp similarity index 97% rename from llarp/router_contact.cpp rename to llarp/contact/router_contact.cpp index d16230f778..8ca93e635d 100644 --- a/llarp/router_contact.cpp +++ b/llarp/contact/router_contact.cpp @@ -1,11 +1,5 @@ #include "router_contact.hpp" -#include "constants/version.hpp" -#include "crypto/crypto.hpp" -#include "net/net.hpp" -#include "util/buffer.hpp" -#include "util/file.hpp" - #include namespace llarp diff --git a/llarp/router_contact.hpp b/llarp/contact/router_contact.hpp similarity index 98% rename from llarp/router_contact.hpp rename to llarp/contact/router_contact.hpp index e90ff07088..8c686bd52a 100644 --- a/llarp/router_contact.hpp +++ b/llarp/contact/router_contact.hpp @@ -1,12 +1,15 @@ #pragma once #include "router_id.hpp" -#include "router_version.hpp" #include -#include +#include #include +#include +#include #include +#include +#include #include #include diff --git a/llarp/router_contact_local.cpp b/llarp/contact/router_contact_local.cpp similarity index 94% rename from llarp/router_contact_local.cpp rename to llarp/contact/router_contact_local.cpp index f8c4de51bb..710f594c77 100644 --- a/llarp/router_contact_local.cpp +++ b/llarp/contact/router_contact_local.cpp @@ -1,10 +1,4 @@ -#include "constants/version.hpp" -#include "crypto/crypto.hpp" -#include "net/net.hpp" #include "router_contact.hpp" -#include "util/buffer.hpp" -#include "util/file.hpp" -#include "util/time.hpp" #include diff --git a/llarp/router_contact_remote.cpp b/llarp/contact/router_contact_remote.cpp similarity index 89% rename from llarp/router_contact_remote.cpp rename to llarp/contact/router_contact_remote.cpp index f2fc2c6169..aac83fb6ea 100644 --- a/llarp/router_contact_remote.cpp +++ b/llarp/contact/router_contact_remote.cpp @@ -1,10 +1,4 @@ -#include "constants/version.hpp" -#include "crypto/crypto.hpp" -#include "net/net.hpp" #include "router_contact.hpp" -#include "util/buffer.hpp" -#include "util/file.hpp" -#include "util/time.hpp" #include diff --git a/llarp/router_id.cpp b/llarp/contact/router_id.cpp similarity index 100% rename from llarp/router_id.cpp rename to llarp/contact/router_id.cpp diff --git a/llarp/router_id.hpp b/llarp/contact/router_id.hpp similarity index 97% rename from llarp/router_id.hpp rename to llarp/contact/router_id.hpp index bc947b7632..a0318c92ce 100644 --- a/llarp/router_id.hpp +++ b/llarp/contact/router_id.hpp @@ -1,7 +1,6 @@ #pragma once -#include "address/keys.hpp" - +#include #include #include diff --git a/llarp/crypto/constants.hpp b/llarp/crypto/constants.hpp index 32cb142e9c..0e13e4381e 100644 --- a/llarp/crypto/constants.hpp +++ b/llarp/crypto/constants.hpp @@ -1,7 +1,5 @@ #pragma once -#include - #include static constexpr uint32_t PUBKEYSIZE = 32; @@ -15,8 +13,3 @@ static constexpr uint32_t SIGSIZE = 64; static constexpr uint32_t TUNNONCESIZE = 32; static constexpr uint32_t HMACSIZE = 32; static constexpr uint32_t PATHIDSIZE = 16; - -static constexpr uint32_t PQ_CIPHERTEXTSIZE = crypto_kem_CIPHERTEXTBYTES; -static constexpr uint32_t PQ_PUBKEYSIZE = crypto_kem_PUBLICKEYBYTES; -static constexpr uint32_t PQ_SECRETKEYSIZE = crypto_kem_SECRETKEYBYTES; -static constexpr uint32_t PQ_KEYPAIRSIZE = (PQ_SECRETKEYSIZE + PQ_PUBKEYSIZE); diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index 4e55af9a57..a116bead63 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -451,21 +451,6 @@ namespace llarp crypto_scalarmult_curve25519_base(d + 32, d); // expects xkey } - 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 uint8_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); - } - #ifdef HAVE_CRYPT bool crypto::check_passwd_hash(std::string pwhash, std::string challenge) { @@ -487,16 +472,6 @@ namespace llarp return sec.data() + 32; } - const uint8_t* pq_keypair_to_pubkey(const PQKeyPair& k) - { - return k.data() + PQ_SECRETKEYSIZE; - } - - const uint8_t* pq_keypair_to_seckey(const PQKeyPair& k) - { - return k.data(); - } - uint64_t randint() { uint64_t i; @@ -504,7 +479,7 @@ namespace llarp return i; } - // Called during static initialization to initialize libsodium and ntru. (The CSRNG return is + // Called during static initialization to initialize libsodium. (The CSRNG return is // not useful, but just here to get this called during static initialization of `csrng`). static CSRNG _initialize_crypto() { @@ -513,8 +488,6 @@ namespace llarp log::critical(logcat, "sodium_init() failed, unable to continue!"); std::abort(); } - char* avx2 = std::getenv("AVX2_FORCE_DISABLE"); - ntru_init(avx2 && avx2 == "1"sv); return CSRNG{}; } diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index 80d96f458a..b8a825c393 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -2,7 +2,7 @@ #include "types.hpp" -#include +#include #include #include @@ -101,15 +101,6 @@ namespace llarp /// generate encryption keypair void encryption_keygen(Ed25519SecretKey&); - /// generate post quantum encrytion key - void pqe_keygen(PQKeyPair&); - - /// post quantum decrypt (buffer, sharedkey_dst, sec) - bool pqe_decrypt(const PQCipherBlock&, SharedSecret&, const uint8_t*); - - /// post quantum encrypt (buffer, sharedkey_dst, pub) - bool pqe_encrypt(PQCipherBlock&, SharedSecret&, const PQPubKey&); - bool check_identity_privkey(const Ed25519SecretKey&); bool check_passwd_hash(std::string pwhash, std::string challenge); @@ -120,10 +111,6 @@ namespace llarp const uint8_t* seckey_to_pubkey(const Ed25519SecretKey& secret); - const uint8_t* pq_keypair_to_pubkey(const PQKeyPair& keypair); - - const uint8_t* pq_keypair_to_seckey(const PQKeyPair& keypair); - /// rng type that uses llarp::randint(), which is cryptographically secure struct CSRNG { diff --git a/llarp/crypto/key_manager.hpp b/llarp/crypto/key_manager.hpp index 067be56be0..5bb7a6ac35 100644 --- a/llarp/crypto/key_manager.hpp +++ b/llarp/crypto/key_manager.hpp @@ -2,7 +2,7 @@ #include "types.hpp" -#include +#include #include diff --git a/llarp/crypto/types.hpp b/llarp/crypto/types.hpp index 03671feded..23c271df2f 100644 --- a/llarp/crypto/types.hpp +++ b/llarp/crypto/types.hpp @@ -104,10 +104,6 @@ namespace llarp using TunnelNonce = AlignedBuffer; using SymmKey = AlignedBuffer<32>; // not used - using PQCipherBlock = AlignedBuffer; - using PQPubKey = AlignedBuffer; - using PQKeyPair = AlignedBuffer; - /// PKE(result, publickey, secretkey, nonce) using path_dh_func = bool (*)(SharedSecret&, const PubKey&, const Ed25519SecretKey&, const TunnelNonce&); } // namespace llarp diff --git a/llarp/dht/kademlia.hpp b/llarp/dht/kademlia.hpp index 8ce8d3e9de..e0d0d430a6 100644 --- a/llarp/dht/kademlia.hpp +++ b/llarp/dht/kademlia.hpp @@ -2,7 +2,7 @@ #include "key.hpp" -#include +#include namespace llarp::dht { diff --git a/llarp/dht/key.hpp b/llarp/dht/key.hpp index 53a12583d5..a682a93d41 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 986a3e66c9..9c8e5a9691 100644 --- a/llarp/dht/node.hpp +++ b/llarp/dht/node.hpp @@ -2,7 +2,7 @@ #include "key.hpp" -#include +#include #include #include diff --git a/llarp/endpoint_base.hpp b/llarp/endpoint_base.hpp index 48780e56f2..ab1839bbbb 100644 --- a/llarp/endpoint_base.hpp +++ b/llarp/endpoint_base.hpp @@ -1,7 +1,6 @@ #pragma once -#include "router_id.hpp" - +#include #include #include #include diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index fe925a6f54..28af64a168 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -292,15 +292,23 @@ namespace llarp::handlers const auto now = llarp::time_now_ms(); _last_introset_regen_attempt = now; - std::set path_intros; - - if (auto maybe_intros = get_path_intros_conditional([now](const service::Introduction& intro) -> bool { - return not intro.expires_soon(now, path::INTRO_STALE_THRESHOLD); - })) - { - path_intros.merge(*maybe_intros); - } - else + // service::IntroductionSet path_intros; + + // if (auto maybe_intros = get_path_intros_conditional([now](const service::Introduction& intro) -> bool { + // return not intro.expires_soon(path::INTRO_STALE_THRESHOLD, now); + // })) + // { + // path_intros.merge(*maybe_intros); + // } + // else + // { + // log::warning(logcat, "Failed to get enough valid path introductions to publish introset!"); + // return build_more(1); + // } + + service::intro_que _path_intros = get_recent_path_intros(); + + if (_path_intros.empty()) { log::warning(logcat, "Failed to get enough valid path introductions to publish introset!"); return build_more(1); @@ -326,15 +334,18 @@ namespace llarp::handlers auto& intros = _local_introset.intros; intros.clear(); - for (auto& intro : path_intros) + auto n_needed = num_paths_desired; + + while (--n_needed) { - if (intros.size() < num_paths_desired) - intros.emplace(std::move(intro)); + intros.emplace(_path_intros.top()); + _path_intros.pop(); } // We already check that path_intros is not empty, so we can assert here assert(not intros.empty()); + // TESTNET: TODO: change to key_manager method if (auto maybe_encrypted = _identity.encrypt_and_sign_introset(_local_introset, now)) { if (publish_introset(*maybe_encrypted)) diff --git a/llarp/link/connection.hpp b/llarp/link/connection.hpp index 7ff4678570..6fdcdf1c2c 100644 --- a/llarp/link/connection.hpp +++ b/llarp/link/connection.hpp @@ -1,7 +1,7 @@ #pragma once -#include -#include +#include +#include #include diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index fd21b9904d..34d10f7606 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -3,6 +3,7 @@ #include "connection.hpp" #include "contacts.hpp" +#include #include #include #include @@ -11,7 +12,6 @@ #include #include #include -#include #include #include diff --git a/llarp/messages/common.hpp b/llarp/messages/common.hpp index 9682a54b50..bfbe5b5aad 100644 --- a/llarp/messages/common.hpp +++ b/llarp/messages/common.hpp @@ -1,9 +1,9 @@ #pragma once +#include #include #include #include -#include #include #include #include diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index 99729713a3..e2ef4b9b23 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -4,7 +4,6 @@ #include "dht/kademlia.hpp" #include "link/link_manager.hpp" #include "messages/fetch.hpp" -#include "router_contact.hpp" #include "util/time.hpp" #include diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index 66f5560ad1..119bfb9ac1 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -1,10 +1,10 @@ #pragma once +#include "contact/router_contact.hpp" +#include "contact/router_id.hpp" #include "crypto/crypto.hpp" #include "dht/key.hpp" #include "router/router.hpp" -#include "router_contact.hpp" -#include "router_id.hpp" #include "util/common.hpp" #include "util/thread/threading.hpp" diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index ccae861410..776e9c59c5 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -232,10 +232,9 @@ namespace llarp::path bool Path::is_ready() const { - if (is_expired(llarp::time_now_ms())) - return false; - - return intro.latency > 0s && _established; + // if (is_expired(llarp::time_now_ms())) + // return false; + return _established; } RouterID Path::upstream_rid() diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index b185f5f59e..31e6a7dfff 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -251,10 +251,24 @@ namespace llarp::path } } - std::optional> PathHandler::get_path_intros_conditional( + service::intro_que PathHandler::get_recent_path_intros(std::chrono::milliseconds stale_threshold) const + { + Lock_t l{paths_mutex}; + service::intro_que ret{}; + + for (const auto& [_, p] : _paths) + { + if (p->is_ready() and not p->intro.expires_soon(stale_threshold)) + ret.push(p->intro); + } + + return ret; + } + + std::optional PathHandler::get_path_intros_conditional( std::function filter) const { - std::set intros; + service::IntroductionSet intros; Lock_t l{paths_mutex}; for (const auto& p : _paths) diff --git a/llarp/path/path_handler.hpp b/llarp/path/path_handler.hpp index c67f271ba1..248f2030a1 100644 --- a/llarp/path/path_handler.hpp +++ b/llarp/path/path_handler.hpp @@ -3,7 +3,7 @@ #include "path_types.hpp" #include -#include +#include #include #include #include @@ -106,7 +106,7 @@ namespace llarp /// flag for ::Stop() std::atomic _running; - size_t num_paths_desired; + const size_t num_paths_desired; BuildStats _build_stats; using Lock_t = util::NullLock; @@ -159,7 +159,10 @@ namespace llarp std::optional> get_path(const RouterID& router) const; - std::optional> get_path_intros_conditional( + service::intro_que get_recent_path_intros( + std::chrono::milliseconds stale_threshold = path::INTRO_STALE_THRESHOLD) const; + + std::optional get_path_intros_conditional( std::function filter) const; nlohmann::json ExtractStatus() const; diff --git a/llarp/path/path_types.hpp b/llarp/path/path_types.hpp index 1a248b6cca..4b50026f80 100644 --- a/llarp/path/path_types.hpp +++ b/llarp/path/path_types.hpp @@ -1,9 +1,9 @@ #pragma once #include +#include #include #include -#include #include namespace llarp diff --git a/llarp/path/transit_hop.hpp b/llarp/path/transit_hop.hpp index 989d1ba4ce..13da518f30 100644 --- a/llarp/path/transit_hop.hpp +++ b/llarp/path/transit_hop.hpp @@ -1,8 +1,8 @@ #pragma once #include +#include #include -#include #include #include diff --git a/llarp/profiling.hpp b/llarp/profiling.hpp index 447e859926..3edbaf8d17 100644 --- a/llarp/profiling.hpp +++ b/llarp/profiling.hpp @@ -1,7 +1,7 @@ #pragma once +#include "contact/router_id.hpp" #include "path/path.hpp" -#include "router_id.hpp" #include "util/thread/threading.hpp" #include diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 8b999926a6..46ebc019ec 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -5,13 +5,13 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include #include #include diff --git a/llarp/rpc/rpc_client.hpp b/llarp/rpc/rpc_client.hpp index df3b2cff75..1ba13ae2f2 100644 --- a/llarp/rpc/rpc_client.hpp +++ b/llarp/rpc/rpc_client.hpp @@ -1,8 +1,8 @@ #pragma once +#include #include #include -#include #include #include diff --git a/llarp/service/identity.cpp b/llarp/service/identity.cpp index 6cd2ee2316..61d780dd50 100644 --- a/llarp/service/identity.cpp +++ b/llarp/service/identity.cpp @@ -36,9 +36,7 @@ namespace llarp::service { _idkey.zero(); _enckey.zero(); - pq.zero(); derivedSignKey.zero(); - vanity.zero(); } void Identity::regenerate_keys() @@ -48,8 +46,6 @@ namespace llarp::service pub.update(seckey_to_pubkey(_idkey), seckey_to_pubkey(_enckey)); - crypto::pqe_keygen(pq); - if (not crypto::derive_subkey_private(derivedSignKey, _idkey, 1)) { throw std::runtime_error("failed to derive subkey"); @@ -83,8 +79,6 @@ namespace llarp::service encrypted.signed_at = now; // set service info i.address_keys = pub; - // set public encryption key - i.sntru_pubkey = pq_keypair_to_pubkey(pq); auto bte = i.bt_encode(); diff --git a/llarp/service/identity.hpp b/llarp/service/identity.hpp index 625ccaaeee..f59828153c 100644 --- a/llarp/service/identity.hpp +++ b/llarp/service/identity.hpp @@ -2,7 +2,6 @@ #include "info.hpp" #include "intro_set.hpp" -#include "vanity.hpp" #include #include @@ -19,9 +18,7 @@ namespace llarp::service Ed25519SecretKey _idkey; Ed25519SecretKey _enckey; Ed25519Hash derivedSignKey; - PQKeyPair pq; uint64_t version = llarp::constants::proto_version; - VanityNonce vanity; // public service info ServiceInfo pub; @@ -47,7 +44,6 @@ namespace llarp::service inline bool operator==(const Identity& lhs, const Identity& rhs) { - return std::tie(lhs._enckey, lhs._idkey, lhs.pq, lhs.version, lhs.vanity) - == std::tie(rhs._enckey, rhs._idkey, rhs.pq, rhs.version, rhs.vanity); + return std::tie(lhs._enckey, lhs._idkey, lhs.version) == std::tie(rhs._enckey, rhs._idkey, rhs.version); } } // namespace llarp::service diff --git a/llarp/service/info.cpp b/llarp/service/info.cpp index 6b5de46333..5053d030f9 100644 --- a/llarp/service/info.cpp +++ b/llarp/service/info.cpp @@ -11,14 +11,10 @@ namespace llarp::service return crypto::verify(signkey, buf, size, sig); } - bool ServiceInfo::update(const uint8_t* sign, const uint8_t* enc, const std::optional& nonce) + bool ServiceInfo::update(const uint8_t* sign, const uint8_t* enc) { signkey = sign; enckey = enc; - if (nonce) - { - vanity = *nonce; - } return update_address(); } @@ -29,7 +25,6 @@ namespace llarp::service { enckey.from_hex(btdc.require("e")); signkey.from_hex(btdc.require("s")); - vanity.from_string(btdc.require("x")); } catch (...) { @@ -61,9 +56,6 @@ namespace llarp::service { btdp.append("e", enckey.to_view()); btdp.append("s", signkey.to_view()); - - if (not vanity.is_zero()) - btdp.append("x", vanity.to_view()); } std::string ServiceInfo::name() const @@ -96,7 +88,7 @@ namespace llarp::service std::string ServiceInfo::to_string() const { - return fmt::format("[ServiceInfo e={} s={} v={} x={}]", enckey, signkey, version, vanity); + return "[ServiceInfo e={} s={} v={}]"_format(enckey, signkey, version); } } // namespace llarp::service diff --git a/llarp/service/info.hpp b/llarp/service/info.hpp index 98cbff9b87..ce8544d082 100644 --- a/llarp/service/info.hpp +++ b/llarp/service/info.hpp @@ -1,7 +1,5 @@ #pragma once -#include "vanity.hpp" - #include #include #include @@ -20,11 +18,8 @@ namespace llarp::service mutable NetworkAddress _cached_addr; public: - VanityNonce vanity; uint64_t version = llarp::constants::proto_version; - void randomize_vanity() { vanity.Randomize(); } - bool verify(uint8_t* buf, size_t size, const Signature& sig) const; const PubKey& encryption_pubkey() const @@ -35,12 +30,11 @@ namespace llarp::service return enckey; } - bool update(const uint8_t* sign, const uint8_t* enc, const std::optional& nonce = {}); + bool update(const uint8_t* sign, const uint8_t* enc); bool operator==(const ServiceInfo& other) const { - return enckey == other.enckey && signkey == other.signkey && version == other.version - && vanity == other.vanity; + return std::tie(enckey, version) == std::tie(other.enckey, other.version); } bool operator!=(const ServiceInfo& other) const { return !(*this == other); } diff --git a/llarp/service/intro.cpp b/llarp/service/intro.cpp index 4719ca5224..9464019259 100644 --- a/llarp/service/intro.cpp +++ b/llarp/service/intro.cpp @@ -12,7 +12,6 @@ namespace llarp::service {"router", pivot_router.ToHex()}, {"path", pivot_hop_id.ToHex()}, {"expiresAt", to_json(expiry)}, - {"latency", to_json(latency)}, {"version", uint64_t(version)}}; return obj; } @@ -24,7 +23,6 @@ namespace llarp::service oxenc::bt_dict_consumer btdc{std::move(buf)}; pivot_router.from_relay_address(btdc.require("k")); - latency = std::chrono::milliseconds{btdc.require("l")}; pivot_hop_id.from_string(btdc.require("p")); expiry = std::chrono::milliseconds{btdc.require("x")}; } @@ -52,7 +50,6 @@ namespace llarp::service try { subdict.append("k", pivot_router.to_view()); - subdict.append("l", latency.count()); subdict.append("p", pivot_hop_id.to_view()); subdict.append("x", expiry.count()); } @@ -85,8 +82,6 @@ namespace llarp::service try { pivot_router.from_string(btdc.require("k")); - latency = std::chrono::milliseconds{btdc.require("l")}; - pivot_hop_id.from_string(btdc.require("p")); expiry = std::chrono::milliseconds{btdc.require("x")}; } catch (...) @@ -100,19 +95,13 @@ namespace llarp::service { pivot_router.zero(); pivot_hop_id.zero(); - latency = 0s; expiry = 0s; } std::string Introduction::to_string() const { return fmt::format( - "[Intro k={} l={} p={} v={} x={}]", - RouterID{pivot_router}, - latency.count(), - pivot_hop_id, - version, - expiry.count()); + "[Intro k={} p={} v={} x={}]", RouterID{pivot_router}, pivot_hop_id, version, expiry.count()); } } // namespace llarp::service diff --git a/llarp/service/intro.hpp b/llarp/service/intro.hpp index a7fa5375a9..ea8041a95c 100644 --- a/llarp/service/intro.hpp +++ b/llarp/service/intro.hpp @@ -14,7 +14,6 @@ namespace llarp::service { RouterID pivot_router; HopID pivot_hop_id; - std::chrono::milliseconds latency = 0s; std::chrono::milliseconds expiry = 0s; uint64_t version = llarp::constants::proto_version; @@ -25,7 +24,9 @@ namespace llarp::service bool is_expired(std::chrono::milliseconds now) const { return now >= expiry; } - bool expires_soon(std::chrono::milliseconds now, std::chrono::milliseconds dlt = 30s) const + // TODO: get rid of this entirely, and use ::is_expired(...) + bool expires_soon( + std::chrono::milliseconds dlt = 30s, std::chrono::milliseconds now = llarp::time_now_ms()) const { return is_expired(now + dlt); } @@ -44,14 +45,14 @@ namespace llarp::service bool operator<(const Introduction& other) const { - return std::tie(expiry, pivot_hop_id, pivot_router, version, latency) - < std::tie(other.expiry, other.pivot_hop_id, other.pivot_router, other.version, other.latency); + return std::tie(expiry, pivot_hop_id, pivot_router, version) + < std::tie(other.expiry, other.pivot_hop_id, other.pivot_router, other.version); } bool operator==(const Introduction& other) const { - return std::tie(expiry, pivot_hop_id, pivot_router, version, latency) - == std::tie(other.expiry, other.pivot_hop_id, other.pivot_router, other.version, other.latency); + return std::tie(expiry, pivot_hop_id, pivot_router, version) + == std::tie(other.expiry, other.pivot_hop_id, other.pivot_router, other.version); } bool operator!=(const Introduction& other) const { return !(*this == other); } @@ -68,6 +69,8 @@ namespace llarp::service } }; + using intro_que = std::priority_queue, IntroExpiryComparator>; + using IntroductionSet = std::set; } // namespace llarp::service diff --git a/llarp/service/intro_set.cpp b/llarp/service/intro_set.cpp index 2b4499c91e..5cf7586d9f 100644 --- a/llarp/service/intro_set.cpp +++ b/llarp/service/intro_set.cpp @@ -278,8 +278,6 @@ namespace llarp::service } } - sntru_pubkey.from_string(btdc.require("k")); - if (auto maybe_supportedprotos = btdc.maybe("p"); maybe_supportedprotos) { oxenc::bt_list_consumer sublist{*maybe_supportedprotos}; @@ -343,8 +341,6 @@ namespace llarp::service i.bt_encode(sublist); } - btdp.append("k", sntru_pubkey.to_view()); - if (not supported_protocols.empty()) { auto sublist = btdp.append_list("p"); @@ -388,7 +384,7 @@ namespace llarp::service bool IntroSet::HasStaleIntros(std::chrono::milliseconds now, std::chrono::milliseconds delta) const { for (const auto& intro : intros) - if (intro.expires_soon(now, delta)) + if (intro.expires_soon(delta, now)) return true; return false; } @@ -448,10 +444,9 @@ namespace llarp::service std::string IntroSet::to_string() const { - return "[IntroSet addressKeys={} intros={{}} sntrupKey={} topic={} signedAt={} v={} sig={}]"_format( + return "[IntroSet addressKeys={} intros={{}} topic={} signedAt={} v={} sig={}]"_format( address_keys.to_string(), "{}"_format(fmt::join(intros, ",")), - sntru_pubkey, time_signed.count(), version, signature.to_view()); diff --git a/llarp/service/intro_set.hpp b/llarp/service/intro_set.hpp index ab0b71ee28..d6b7ebe2e8 100644 --- a/llarp/service/intro_set.hpp +++ b/llarp/service/intro_set.hpp @@ -26,7 +26,6 @@ namespace llarp::service { ServiceInfo address_keys; IntroductionSet intros; - PQPubKey sntru_pubkey; std::vector SRVs; std::chrono::milliseconds time_signed = 0s; @@ -83,8 +82,8 @@ namespace llarp::service inline bool operator==(const IntroSet& lhs, const IntroSet& rhs) { - return std::tie(lhs.address_keys, lhs.intros, lhs.sntru_pubkey, lhs.time_signed, lhs.version, lhs.signature) - == std::tie(rhs.address_keys, rhs.intros, rhs.sntru_pubkey, rhs.time_signed, rhs.version, rhs.signature); + return std::tie(lhs.address_keys, lhs.intros, lhs.time_signed, lhs.version, lhs.signature) + == std::tie(rhs.address_keys, rhs.intros, rhs.time_signed, rhs.version, rhs.signature); } inline bool operator!=(const IntroSet& lhs, const IntroSet& rhs) diff --git a/llarp/service/vanity.hpp b/llarp/service/vanity.hpp deleted file mode 100644 index 0599eef234..0000000000 --- a/llarp/service/vanity.hpp +++ /dev/null @@ -1,16 +0,0 @@ - -#ifndef LLARP_SERVICE_VANITY_HPP -#define LLARP_SERVICE_VANITY_HPP - -#include - -namespace llarp -{ - namespace service - { - /// hidden service address - - using VanityNonce = AlignedBuffer<16>; - } // namespace service -} // namespace llarp -#endif diff --git a/pybind/llarp/router_id.cpp b/pybind/llarp/router_id.cpp index ba896387be..2c9816fe8d 100644 --- a/pybind/llarp/router_id.cpp +++ b/pybind/llarp/router_id.cpp @@ -1,4 +1,4 @@ -#include +#include #include From d09655ab0ff6a8ddc133ff1454a64196096a7d10 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 10 Oct 2024 10:46:32 -0700 Subject: [PATCH 02/44] libquic bump --- external/oxen-libquic | 2 +- llarp/link/link_manager.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/external/oxen-libquic b/external/oxen-libquic index d837250265..f64ecf62f0 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit d83725026529c259395d2abc2d3e91840d67cdc6 +Subproject commit f64ecf62f00534fb09ef371322d276bc58549b9e diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 34d10f7606..459ab4d664 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -304,8 +304,7 @@ namespace llarp [this](oxen::quic::connection_interface& ci, uint64_t ec) { return on_conn_closed(ci, ec); }, [this](oxen::quic::dgram_interface&, bstring dgram) { handle_path_data_message(std::move(dgram)); }, is_service_node() ? alpns::SERVICE_INBOUND : alpns::CLIENT_INBOUND, - is_service_node() ? alpns::SERVICE_OUTBOUND : alpns::CLIENT_OUTBOUND, - oxen::quic::opt::disable_stateless_reset{}); + is_service_node() ? alpns::SERVICE_OUTBOUND : alpns::CLIENT_OUTBOUND); // While only service nodes accept inbound connections, clients must have this key verify // callback set. It will reject any attempted inbound connection to a lokinet client prior From 5d7ba88f7a1605fdd3b0a6e745a9ad941d622e46 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Mon, 21 Oct 2024 09:04:01 -0700 Subject: [PATCH 03/44] oxend rpc ping -> ticker --- llarp/router/router.cpp | 3 +-- llarp/rpc/rpc_client.cpp | 30 ++++++++++++------------------ llarp/rpc/rpc_client.hpp | 5 +++++ 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index fbf15dac5a..562858a6f8 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -198,6 +198,7 @@ namespace llarp if (is_service_node()) { + _rpc_client->start_pings(); _link_manager->start_tickers(); if (not _testing_disabled) @@ -277,8 +278,6 @@ namespace llarp { _key_manager->update_idkey(rpc_client()->obtain_identity_key()); log::warning(logcat, "Obtained lokid identity key: {}", _key_manager->router_id()); - - rpc_client()->start_pings(); break; } catch (const std::exception& e) diff --git a/llarp/rpc/rpc_client.cpp b/llarp/rpc/rpc_client.cpp index 2df2042328..705d9ca661 100644 --- a/llarp/rpc/rpc_client.cpp +++ b/llarp/rpc/rpc_client.cpp @@ -165,20 +165,20 @@ namespace llarp::rpc void RPCClient::start_pings() { - constexpr auto PingInterval = 30s; + log::trace(logcat, "{} called", __PRETTY_FUNCTION__); auto router = _router.lock(); if (not router) return; - auto makePingRequest = router->loop()->make_caller([self = shared_from_this()]() { + log::info(logcat, "Starting RPCClient ping ticker..."); + _ping_ticker = router->loop()->call_every(PING_INTERVAL, [this]() { // send a ping - PubKey pk{}; - auto r = self->_router.lock(); + auto r = _router.lock(); if (not r) return; // router has gone away, maybe shutting down? - pk = r->local_rid(); + auto pk = r->local_rid(); nlohmann::json payload = { {"pubkey_ed25519", oxenc::to_hex(pk.begin(), pk.end())}, @@ -187,33 +187,27 @@ namespace llarp::rpc if (auto err = r->OxendErrorState()) payload["error"] = *err; - self->request( + request( "admin.lokinet_ping", - [](bool success, std::vector data) { - (void)data; + [](bool success, std::vector /* data */) { log::debug(logcat, "Received response for ping. Successful: {}", success); }, payload.dump()); // subscribe to block updates - self->request("sub.block", [](bool success, std::vector data) { + request("sub.block", [](bool success, std::vector data) { if (data.empty() or not success) - { log::error(logcat, "Failed to subscribe to new blocks"); - return; - } - log::debug(logcat, "Subscribed to new blocks: {}", data[0]); + else + log::debug(logcat, "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->update_service_node_list(); + update_service_node_list(); }); - - // Fire one ping off right away to get things going. - makePingRequest(); - m_lokiMQ->add_timer(std::move(makePingRequest), PingInterval); } void RPCClient::handle_new_service_node_list(const nlohmann::json& j) diff --git a/llarp/rpc/rpc_client.hpp b/llarp/rpc/rpc_client.hpp index 1ba13ae2f2..259de9c563 100644 --- a/llarp/rpc/rpc_client.hpp +++ b/llarp/rpc/rpc_client.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -14,6 +15,8 @@ namespace llarp namespace rpc { + inline constexpr auto PING_INTERVAL{30s}; + /// The LokidRpcClient uses loki-mq to talk to make API requests to lokid. struct RPCClient : public std::enable_shared_from_this { @@ -64,6 +67,8 @@ namespace llarp // Handles notification of a new block void handle_new_block(oxenmq::Message& msg); + std::shared_ptr _ping_ticker; + std::optional m_Connection; std::shared_ptr m_lokiMQ; From d3e3e3ded59cada35d070a56df8089ef4c09cf4f Mon Sep 17 00:00:00 2001 From: dr7ana Date: Wed, 2 Oct 2024 11:35:36 -0700 Subject: [PATCH 04/44] (WIP, squash) contact library, re-org --- external/oxen-encoding | 2 +- external/oxen-libquic | 2 +- include/llarp.hpp | 2 +- llarp/CMakeLists.txt | 10 +- llarp/bootstrap-fallbacks.cpp.in | 2 +- llarp/bootstrap.cpp | 4 +- llarp/bootstrap.hpp | 2 +- llarp/bootstrap_fallbacks.cpp | 2 +- llarp/config/config.cpp | 2 +- llarp/config/config.hpp | 2 +- llarp/contact/client_contact.cpp | 108 +++++++ llarp/contact/client_contact.hpp | 83 +++++ llarp/contact/client_intro.cpp | 45 +++ llarp/contact/client_intro.hpp | 73 +++++ llarp/contact/relay_contact.cpp | 194 ++++++++++++ llarp/contact/relay_contact.hpp | 306 +++++++++++++++++++ llarp/contact/relay_contact_local.cpp | 97 ++++++ llarp/contact/relay_contact_remote.cpp | 59 ++++ llarp/contact/router_contact.cpp | 28 +- llarp/contact/router_contact.hpp | 44 +-- llarp/contact/router_contact_local.cpp | 4 + llarp/contact/router_contact_remote.cpp | 6 +- llarp/dht/kademlia.hpp | 4 +- llarp/dht/node.hpp | 6 +- llarp/dns/srv_data.cpp | 11 +- llarp/dns/srv_data.hpp | 5 +- llarp/handlers/session.cpp | 8 +- llarp/handlers/session.hpp | 13 +- llarp/handlers/tun.cpp | 2 +- llarp/link/connection.hpp | 2 +- llarp/link/contacts.cpp | 4 +- llarp/link/contacts.hpp | 4 +- llarp/link/link_manager.cpp | 2 +- llarp/lokinet_shared.cpp | 2 +- llarp/net/traffic_policy.cpp | 8 +- llarp/net/traffic_policy.hpp | 4 +- llarp/nodedb.cpp | 8 +- llarp/nodedb.hpp | 4 +- llarp/path/path_handler.cpp | 8 +- llarp/path/path_handler.hpp | 4 +- llarp/path/path_types.hpp | 2 +- llarp/router/router.cpp | 4 +- llarp/router/router.hpp | 2 +- llarp/service/identity.cpp | 4 +- llarp/service/identity.hpp | 2 +- llarp/service/intro.hpp | 4 +- llarp/service/intro_set.cpp | 50 ++- llarp/service/intro_set.hpp | 20 +- pybind/common.hpp | 2 +- pybind/llarp/config.cpp | 2 +- pybind/llarp/router_contact.cpp | 23 +- pybind/module.cpp | 2 +- test/crypto/test_llarp_key_manager.cpp | 2 +- test/nodedb/test_nodedb.cpp | 14 +- test/path/test_path.cpp | 2 +- test/peerstats/test_peer_db.cpp | 14 +- test/service/test_llarp_service_identity.cpp | 2 +- test/test_llarp_router_contact.cpp | 20 +- 58 files changed, 1166 insertions(+), 181 deletions(-) create mode 100644 llarp/contact/client_contact.cpp create mode 100644 llarp/contact/client_contact.hpp create mode 100644 llarp/contact/client_intro.cpp create mode 100644 llarp/contact/client_intro.hpp create mode 100644 llarp/contact/relay_contact.cpp create mode 100644 llarp/contact/relay_contact.hpp create mode 100644 llarp/contact/relay_contact_local.cpp create mode 100644 llarp/contact/relay_contact_remote.cpp diff --git a/external/oxen-encoding b/external/oxen-encoding index 7c8ab72db8..510e5259bd 160000 --- a/external/oxen-encoding +++ b/external/oxen-encoding @@ -1 +1 @@ -Subproject commit 7c8ab72db826f3d77f7fc2e58b029b1d2e67d52e +Subproject commit 510e5259bd639d28813fe6c940c33701233e994f diff --git a/external/oxen-libquic b/external/oxen-libquic index f64ecf62f0..d837250265 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit f64ecf62f00534fb09ef371322d276bc58549b9e +Subproject commit d83725026529c259395d2abc2d3e91840d67cdc6 diff --git a/include/llarp.hpp b/include/llarp.hpp index 8acbca2f48..7699dd9223 100644 --- a/include/llarp.hpp +++ b/include/llarp.hpp @@ -17,7 +17,7 @@ namespace llarp class EventLoop; struct Config; - struct RouterContact; + struct RelayContact; struct Config; struct Router; class NodeDB; diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index 75c88aa5ec..a2ab9c43eb 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -83,9 +83,13 @@ lokinet_add_library(lokinet-utils add_dependencies(lokinet-utils genversion) lokinet_add_library(lokinet-contact - contact/router_contact.cpp - contact/router_contact_local.cpp - contact/router_contact_remote.cpp + contact/client_contact.cpp + contact/client_intro.cpp + + contact/relay_contact.cpp + contact/relay_contact_local.cpp + contact/relay_contact_remote.cpp + contact/router_id.cpp ) diff --git a/llarp/bootstrap-fallbacks.cpp.in b/llarp/bootstrap-fallbacks.cpp.in index 51754db48f..71b657cf9a 100644 --- a/llarp/bootstrap-fallbacks.cpp.in +++ b/llarp/bootstrap-fallbacks.cpp.in @@ -12,7 +12,7 @@ namespace llarp @BOOTSTRAP_FALLBACKS@ }) { - if (network != RouterContact::ACTIVE_NETID) + if (network != RelayContact::ACTIVE_NETID) continue; auto& bsl = fallbacks[network]; diff --git a/llarp/bootstrap.cpp b/llarp/bootstrap.cpp index b6551f2c85..51d88a810b 100644 --- a/llarp/bootstrap.cpp +++ b/llarp/bootstrap.cpp @@ -111,7 +111,7 @@ namespace llarp for (auto itr = begin(); itr != end(); ++itr) { - if (RouterContact::is_obsolete(*itr)) + if (RelayContact::is_obsolete(*itr)) { log::debug(logcat, "Deleting obsolete BootstrapRC (rid:{})", itr->router_id()); itr = erase(itr); @@ -126,7 +126,7 @@ namespace llarp log::critical(logcat, "BootstrapRC list force loading fallbacks..."); auto fallbacks = llarp::load_bootstrap_fallbacks(); - if (auto itr = fallbacks.find(RouterContact::ACTIVE_NETID); itr != fallbacks.end()) + if (auto itr = fallbacks.find(RelayContact::ACTIVE_NETID); itr != fallbacks.end()) { log::debug(logcat, "Loading {} default fallback bootstrap router(s)!", itr->second.size()); log::critical(logcat, "Fallback bootstrap loaded: {}", itr->second.current()); diff --git a/llarp/bootstrap.hpp b/llarp/bootstrap.hpp index 71c1cf9104..4b444a38eb 100644 --- a/llarp/bootstrap.hpp +++ b/llarp/bootstrap.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/llarp/bootstrap_fallbacks.cpp b/llarp/bootstrap_fallbacks.cpp index 14dcf6d818..63eb1b9bce 100644 --- a/llarp/bootstrap_fallbacks.cpp +++ b/llarp/bootstrap_fallbacks.cpp @@ -12,7 +12,7 @@ namespace llarp // }) { - if (network != RouterContact::ACTIVE_NETID) + if (network != RelayContact::ACTIVE_NETID) continue; auto& bsl = fallbacks[network]; diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index 74527912d8..82b462a580 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -1313,7 +1313,7 @@ namespace llarp "add-node", MultiValue, Comment{ - "Specify a bootstrap file containing a list of signed RouterContacts of service " + "Specify a bootstrap file containing a list of signed RelayContacts of service " "nodes", "which can act as a bootstrap. Can be specified multiple times.", }, diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index 96dc35465f..1c8d037643 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/llarp/contact/client_contact.cpp b/llarp/contact/client_contact.cpp new file mode 100644 index 0000000000..e1bea0abd7 --- /dev/null +++ b/llarp/contact/client_contact.cpp @@ -0,0 +1,108 @@ +#include "client_contact.hpp" + +namespace llarp +{ + static auto logcat = log::Cat("client-intro"); + + ClientContact::ClientContact(std::string_view buf) + { + bt_decode(buf); + } + + std::string ClientContact::bt_encode() const + { + oxenc::bt_dict_producer btdp; + + btdp.append("a", pubkey.to_view()); + + if (exit_policy) + exit_policy->bt_encode(btdp.append_dict("e")); + + { + auto sublist = btdp.append_list("i"); + + for (auto& i : intros) + i.bt_encode(sublist.append_dict()); + } + + if (not supported_protos.empty()) + { + auto sublist = btdp.append_list("p"); + for (auto& p : supported_protos) + sublist.append(static_cast(p)); + } + + if (not SRVs.empty()) + { + auto sublist = btdp.append_list("s"); + for (auto& s : SRVs) + s.bt_encode(sublist.append_dict()); + } + + btdp.append("t", signed_at.count()); + btdp.append("~", signature.to_view()); + + return std::move(btdp).str(); + } + + bool ClientContact::bt_decode(std::string_view buf) + { + try + { + bt_decode(oxenc::bt_dict_consumer{buf}); + } + catch (const std::exception& e) + { + log::critical(logcat, "ClientContact deserialization failed: {}", e.what()); + return false; + } + + return true; + } + + void ClientContact::bt_decode(oxenc::bt_dict_consumer&& btdc) + { + pubkey.from_string(btdc.require("a")); + + if (auto maybe_subdict = btdc.maybe("e")) + { + exit_policy->bt_decode(oxenc::bt_dict_consumer{*maybe_subdict}); + } + + btdc.required("i"); + + { + auto sublist = btdc.consume_list_consumer(); + + while (not sublist.is_finished()) + intros.emplace(sublist.consume_string_view()); + } + + // check, since we only add "p" if supported_protos is not empty (TESTNET: DISCUSS: an ALL type makes sense?) + if (btdc.skip_until("p")) + { + auto sublist = btdc.consume_list_consumer(); + + while (not sublist.is_finished()) + supported_protos.push_back(service::ProtocolType{sublist.consume_integer()}); + } + + // ditto as above + if (btdc.skip_until("s")) + { + auto sublist = btdc.consume_list_consumer(); + + while (not sublist.is_finished()) + SRVs.emplace_back(sublist.consume_string_view()); + } + + signed_at = std::chrono::milliseconds{btdc.require("t")}; + signature.from_string(btdc.require("~")); + } + + bool ClientContact::is_expired(std::chrono::milliseconds now) const + { + // check the last intro to expire + return intros.rbegin()->is_expired(now); + } +} // namespace llarp diff --git a/llarp/contact/client_contact.hpp b/llarp/contact/client_contact.hpp new file mode 100644 index 0000000000..61de295451 --- /dev/null +++ b/llarp/contact/client_contact.hpp @@ -0,0 +1,83 @@ +#pragma once + +#include "client_intro.hpp" +#include "router_id.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +namespace llarp +{ + struct EncryptedClientContact; + + // TODO: add version to `` field to match RelayContact + + struct ClientContact + { + static constexpr uint8_t CC_VERSION{0}; + + ClientContact() = default; + ClientContact(std::string_view buf); + + PubKey pubkey; + + intro_set intros; + std::vector SRVs; + std::chrono::milliseconds signed_at{0s}; + + std::vector supported_protos; + + // In exit mode, we advertise our policy for accepted traffic and the corresponding ranges + std::optional exit_policy; + + Signature signature; + + bool is_expired(std::chrono::milliseconds now = llarp::time_now_ms()) const; + + std::string bt_encode() const; + + // Does not throw, returns true/false + bool bt_decode(std::string_view buf); + + protected: + // Throws if unsuccessful, must take BTDC in invocation + void bt_decode(oxenc::bt_dict_consumer&& btdc); + + public: + std::string to_string() const; + static constexpr bool to_string_formattable = true; + }; + + /** + EncryptedClientContact + "i" blinded local routerID + "n" nounce + "t" signing time + "x" same + "~" signature + */ + struct EncryptedClientContact + { + PubKey blinded_pubkey; + SymmNonce nonce; + std::chrono::milliseconds signed_at{0s}; + std::vector payload; + Signature sig; + }; +} // namespace llarp diff --git a/llarp/contact/client_intro.cpp b/llarp/contact/client_intro.cpp new file mode 100644 index 0000000000..4b098f7d0f --- /dev/null +++ b/llarp/contact/client_intro.cpp @@ -0,0 +1,45 @@ +#include "client_contact.hpp" + +namespace llarp +{ + static auto logcat = log::Cat("client-intro"); + + ClientIntro::ClientIntro(std::string_view buf) + { + bt_decode(buf); + } + + void ClientIntro::bt_encode(oxenc::bt_dict_producer&& subdict) const + { + subdict.append("k", pivot_rid.to_view()); + subdict.append("p", pivot_hid.to_view()); + subdict.append("x", expiry.count()); + } + + bool ClientIntro::bt_decode(std::string_view buf) + { + try + { + bt_decode(oxenc::bt_dict_consumer{buf}); + } + catch (const std::exception& e) + { + log::critical(logcat, "ClientIntro deserialization failed: {}", e.what()); + return false; + } + + return true; + } + + void ClientIntro::bt_decode(oxenc::bt_dict_consumer&& btdc) + { + pivot_rid.from_string(btdc.require("k")); + pivot_hid.from_string(btdc.require("p")); + expiry = std::chrono::milliseconds{btdc.require("x")}; + } + + std::string ClientIntro::to_string() const + { + return "[ ClientIntro pivot_rid={}, pivot_hid={}, expiry={} ]"_format(pivot_rid, pivot_hid, expiry.count()); + } +} // namespace llarp diff --git a/llarp/contact/client_intro.hpp b/llarp/contact/client_intro.hpp new file mode 100644 index 0000000000..9322352e20 --- /dev/null +++ b/llarp/contact/client_intro.hpp @@ -0,0 +1,73 @@ +#pragma once + +#include +#include + +#include + +#include +#include + +namespace llarp +{ + struct ClientIntro + { + RouterID pivot_rid; + HopID pivot_hid; + std::chrono::milliseconds expiry{0s}; + uint64_t version{llarp::constants::proto_version}; + + ClientIntro() = default; + ClientIntro(std::string_view buf); + + bool is_expired(std::chrono::milliseconds now = llarp::time_now_ms()) const { return now >= expiry; } + + void bt_encode(oxenc::bt_dict_producer&& subdict) const; + + // Does not throw, returns true/false + bool bt_decode(std::string_view buf); + + protected: + // Throws if unsuccessful, must take BTDC in invocation + void bt_decode(oxenc::bt_dict_consumer&& btdc); + + public: + auto operator<=>(const ClientIntro& other) const + { + return std::tie(pivot_rid, pivot_hid, expiry, version) + <=> std::tie(other.pivot_rid, other.pivot_hid, other.expiry, other.version); + } + + bool operator==(const ClientIntro& other) const { return (*this <=> other) == 0; } + + bool operator<(const ClientIntro& other) const + { + return std::tie(pivot_rid, pivot_hid, expiry, version) + < std::tie(other.pivot_rid, other.pivot_hid, other.expiry, other.version); + } + + std::string to_string() const; + static constexpr bool to_string_formattable = true; + }; + + struct ClientIntroComp + { + bool operator()(const ClientIntro& lhs, const ClientIntro& rhs) const { return lhs.expiry < rhs.expiry; } + }; + + using intro_queue = std::priority_queue, ClientIntroComp>; + using intro_set = std::set; + +} // namespace llarp + +namespace std +{ + template <> + struct hash + { + size_t operator()(const llarp::ClientIntro& i) const + { + return std::hash{}(i.pivot_rid) ^ std::hash{}(i.pivot_hid); + } + }; +} // namespace std diff --git a/llarp/contact/relay_contact.cpp b/llarp/contact/relay_contact.cpp new file mode 100644 index 0000000000..b57c14d1b3 --- /dev/null +++ b/llarp/contact/relay_contact.cpp @@ -0,0 +1,194 @@ +<<<<<<<< HEAD:llarp/contact/router_contact.cpp +#include "router_contact.hpp" +======== +#include "relay_contact.hpp" +>>>>>>>> a41903e54 ((WIP, squash) contact library, re-org):llarp/contact/relay_contact.cpp + +#include + +namespace llarp +{ + static auto logcat = log::Cat("relay-contact"); + + void RelayContact::bt_verify(oxenc::bt_dict_consumer& btdc, bool reject_expired) const + { + btdc.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 (reject_expired and is_expired(time_now_ms())) + throw std::runtime_error{"Rejecting expired RemoteRC!"}; + + if (not addr().is_public() and BLOCK_BOGONS) + { + auto err = "Unable to verify expired RemoteRC address!"; + 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 signature"}; + }); + + if (not btdc.is_finished()) + throw std::runtime_error{"RemoteRC has some fucked up shit at the end"}; + + btdc.finish(); + } + + void RelayContact::bt_load(oxenc::bt_dict_consumer& btdc) + { + if (int rc_ver = btdc.require(""); rc_ver != RC_VERSION) + throw std::runtime_error{"Invalid RC: do not know how to parse v{} RCs"_format(rc_ver)}; + + auto ipv4_port = btdc.require("4"); + + if (ipv4_port.size() != 6) + throw std::runtime_error{ + "Invalid RC address: expected 6-byte IPv4 IP/port, got {}"_format(ipv4_port.size())}; + + sockaddr_in s4; + s4.sin_family = AF_INET; + + std::memcpy(&s4.sin_addr.s_addr, ipv4_port.data(), 4); + std::memcpy(&s4.sin_port, ipv4_port.data() + 4, 2); + + _addr = oxen::quic::Address{&s4}; + + if (!_addr.is_public()) + throw std::runtime_error{"Invalid RC: IPv4 address is not a publicly routable IP"}; + + if (auto ipv6_port = btdc.maybe("6")) + { + 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; + + std::memcpy(&s6.sin6_addr.s6_addr, ipv6_port->data(), 16); + std::memcpy(&s6.sin6_port, ipv6_port->data() + 16, 2); + + _addr6.emplace(&s6); + if (!_addr6->is_public()) + throw std::runtime_error{"Invalid RC: IPv6 address is not a publicly routable IP"}; + } + else + { + _addr6.reset(); + } + + auto netid = btdc.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)}; + + auto pubkey = btdc.require("p"); + if (pubkey.size() != 32) + throw std::runtime_error{"Invalid RC pubkey: expected 32 bytes, got {}"_format(pubkey.size())}; + std::memcpy(_router_id.data(), pubkey.data(), 32); + + _timestamp = rc_time{std::chrono::seconds{btdc.require("t")}}; + + auto ver = btdc.require("v"); + + if (ver.size() != 3) + throw std::runtime_error{"Invalid RC router version: received {} bytes (!= 3)"_format(ver.size())}; + + for (int i = 0; i < 3; i++) + _router_version[i] = ver[i]; + } + + bool RelayContact::write(const fs::path& fname) const + { + auto bte = view(); + + 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; + } + + nlohmann::json RelayContact::extract_status() const + { + nlohmann::json obj{ + {"lastUpdated", _timestamp.time_since_epoch().count()}, + {"publicRouter", is_public_addressable()}, + {"identity", _router_id.to_string()}, + {"address", _addr.to_string()}}; + + // if (routerVersion) + // { + // obj["routerVersion"] = routerVersion->to_string(); + // } + // std::vector srv; + // for (const auto& record : srvRecords) + // { + // srv.emplace_back(record.ExtractStatus()); + // } + // obj["srvRecords"] = srv; + + return obj; + } + + bool RelayContact::is_public_addressable() const + { + if (_router_version.empty()) + return false; + + return _addr.is_addressable(); + } + + bool RelayContact::is_expired(std::chrono::milliseconds now) const + { + return age(now) >= _timestamp.time_since_epoch() + LIFETIME; + } + + std::chrono::milliseconds RelayContact::time_to_expiry(std::chrono::milliseconds now) const + { + const auto expiry = _timestamp.time_since_epoch() + LIFETIME; + return now < expiry ? expiry - now : 0s; + } + + std::chrono::milliseconds RelayContact::age(std::chrono::milliseconds now) const + { + auto delta = now - _timestamp.time_since_epoch(); + return delta > 0s ? delta : 0s; + } + + bool RelayContact::expires_within_delta(std::chrono::milliseconds now, std::chrono::milliseconds dlt) const + { + return time_to_expiry(now) <= dlt; + } + + static const std::set obsolete_bootstraps{ + "7a16ac0b85290bcf69b2f3b52456d7e989ac8913b4afbb980614e249a3723218"sv, + "e6b3a6fe5e32c379b64212c72232d65b0b88ddf9bbaed4997409d329f8519e0b"sv, + }; + + bool RelayContact::is_obsolete_bootstrap() const + { + for (const auto& k : obsolete_bootstraps) + { + if (_router_id.ToHex() == k) + return true; + } + return false; + } + + bool RelayContact::is_obsolete(const RelayContact& rc) + { + const auto& hex = rc._router_id.ToHex(); + + return obsolete_bootstraps.count(hex); + } +} // namespace llarp diff --git a/llarp/contact/relay_contact.hpp b/llarp/contact/relay_contact.hpp new file mode 100644 index 0000000000..5e349ae5f1 --- /dev/null +++ b/llarp/contact/relay_contact.hpp @@ -0,0 +1,306 @@ +#pragma once + +#include "router_id.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +namespace llarp +{ + inline static constexpr size_t NETID_SIZE{8}; + + /// On the wire we encode the data as a dict containing: + /// "" -- the RC format version, which must be == RelayContact::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 "testnet" for testnet). + /// "p" -- 32-byte router pubkey + /// "t" -- timestamp when this RC record was created (which also implicitly determines when it + /// goes stale and when it expires). + /// "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" + + /// RelayContact + struct RelayContact + { + static constexpr uint8_t RC_VERSION{0}; + + /// Unit tests disable this to allow private IP ranges in RCs, which normally get rejected. + inline static bool BLOCK_BOGONS{true}; + + inline static std::string ACTIVE_NETID{LOKINET_DEFAULT_NETID}; + + inline static constexpr size_t MAX_RC_SIZE{1024}; + + /// How long (from its signing time) before an RC is considered "stale". Relays republish + /// their RCs slightly more frequently than this so that ideally this won't happen. + static constexpr auto STALE_AGE{6h}; + + /// How long (from its signing time) before an RC becomes "outdated". Outdated records are + /// used (e.g. for path building) only if there are no newer records available, such as + /// might be the case when a client has been turned off for a while. + static constexpr auto OUTDATED_AGE{12h}; + + /// How long before an RC becomes invalid (and thus deleted). + static constexpr auto LIFETIME{30 * 24h}; + + ustring_view view() const { return _payload; } + + /// Getters for private attributes + const oxen::quic::Address& addr() const { return _addr; } + oxen::quic::Address addr() { return _addr; } + + const std::optional& addr6() const { return _addr6; } + + const RouterID& router_id() const { return _router_id; } + RouterID router_id() { return _router_id; } + + const rc_time& timestamp() const { return _timestamp; } + rc_time timestamp() { return _timestamp; } + + protected: + // advertised addresses + oxen::quic::Address _addr; // refactor all 15 uses to use addr() method + std::optional _addr6; // optional ipv6 + // public signing public key + RouterID _router_id; + + rc_time _timestamp{}; + + // 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? + static const bool serializeExit = true; + + nlohmann::json extract_status() const; + + nlohmann::json to_json() const { return extract_status(); } + + virtual std::string to_string() const + { + return "RC:['4'={} | 'i'='{}' | 'p'={} | 't'={} | v={}]"_format( + _addr.to_string(), ACTIVE_NETID, _router_id, _timestamp.time_since_epoch().count(), RC_VERSION); + } + + bool write(const fs::path& fname) const; + + auto operator<=>(const RelayContact& other) const + { + return std::tie(_router_id, _addr, _addr6, _timestamp, _router_version) + <=> std::tie(other._router_id, other._addr, other._addr6, other._timestamp, other._router_version); + } + + bool operator==(const RelayContact& other) const { return (*this <=> other) == 0; } + + bool operator<(const RelayContact& other) const { return _router_id < other._router_id; } + + virtual void clear() {} + + bool is_public_addressable() const; + + /// does this RC expire soon? default delta is 1 minute + bool expires_within_delta(std::chrono::milliseconds now, std::chrono::milliseconds dlt = 1min) const; + + /// returns true if this RC is expired and should be removed + bool is_expired(std::chrono::milliseconds now) const; + + /// returns time in ms until we expire or 0 if we have expired + std::chrono::milliseconds time_to_expiry(std::chrono::milliseconds now) const; + + /// get the age of this RC in ms + std::chrono::milliseconds age(std::chrono::milliseconds now) const; + + bool other_is_newer(const RelayContact& other) const { return _timestamp < other._timestamp; } + + bool is_obsolete_bootstrap() const; + + static bool is_obsolete(const RelayContact& rc); + + void bt_verify(oxenc::bt_dict_consumer& data, bool reject_expired = false) const; + + void bt_load(oxenc::bt_dict_consumer& data); + + static constexpr bool to_string_formattable = true; + }; + + struct RemoteRC; + + /// Extension of RelayContact used to store a local "RC," and inserts a RelayContact 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 final : public RelayContact + { + static LocalRC make(Ed25519SecretKey secret, oxen::quic::Address local); + + private: + ustring _signature; + Ed25519SecretKey _secret_key; + + void bt_sign(oxenc::bt_dict_producer& btdp); + + void bt_encode(oxenc::bt_dict_producer& btdp); + + LocalRC(Ed25519SecretKey secret, oxen::quic::Address local); + + public: + LocalRC() = default; + ~LocalRC() = default; + + RemoteRC to_remote(); + + void resign(); + + void clear() override + { + _addr = oxen::quic::Address{}; + _addr6.reset(); + _router_id.zero(); + _timestamp = {}; + _router_version.fill(0); + _signature.clear(); + } + + auto operator<=>(const LocalRC& other) const + { + return std::tie(_router_id, _addr, _addr6, _timestamp, _router_version, _signature) <=> std::tie( + other._router_id, + other._addr, + other._addr6, + other._timestamp, + other._router_version, + other._signature); + } + + bool operator==(const LocalRC& other) const { return (*this <=> other) == 0; } + + bool operator<(const LocalRC& other) const { return _router_id < other._router_id; } + + /// 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) + { + _addr = std::move(new_addr); + resign(); + } + + void set_addr6(oxen::quic::Address new_addr) + { + _addr6 = std::move(new_addr); + resign(); + } + + void set_router_id(RouterID rid) + { + _router_id = std::move(rid); + resign(); + } + + void set_timestamp(std::chrono::milliseconds 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(time_point_now()); } + }; + + /// Extension of RelayContact 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 final : public RelayContact + { + private: + // this ctor is private because it doesn't set ::_payload + explicit RemoteRC(oxenc::bt_dict_consumer btdc); + + public: + RemoteRC() = default; + explicit RemoteRC(std::string_view data) : RemoteRC{oxenc::bt_dict_consumer{data}} + { + _payload = {reinterpret_cast(data.data()), data.size()}; + } + explicit RemoteRC(ustring_view data) : RemoteRC{oxenc::bt_dict_consumer{data}} { _payload = data; } + ~RemoteRC() = default; + + std::string_view view() const { return {reinterpret_cast(_payload.data()), _payload.size()}; } + + bool verify() const; + + bool read(const fs::path& fname); + + void clear() override + { + _addr = oxen::quic::Address{}; + _addr6.reset(); + _router_id.zero(); + _timestamp = {}; + _router_version.fill(0); + } + + auto operator<=>(const RemoteRC& other) const + { + return std::tie(_router_id, _addr, _addr6, _timestamp, _router_version) + <=> std::tie(other._router_id, other._addr, other._addr6, other._timestamp, other._router_version); + } + + bool operator==(const RemoteRC& other) const { return (*this <=> other) == 0; } + + bool operator<(const RemoteRC& other) const { return _router_id < other._router_id; } + }; +} // namespace llarp + +namespace std +{ + template <> + struct hash + { + virtual size_t operator()(const llarp::RelayContact& r) const + { + return std::hash{}(r.router_id()); + } + }; + + template <> + struct hash : public hash + {}; + + template <> + struct hash final : public hash + {}; +} // namespace std diff --git a/llarp/contact/relay_contact_local.cpp b/llarp/contact/relay_contact_local.cpp new file mode 100644 index 0000000000..8539f0c173 --- /dev/null +++ b/llarp/contact/relay_contact_local.cpp @@ -0,0 +1,97 @@ +<<<<<<<< HEAD:llarp/contact/router_contact_local.cpp +#include "router_contact.hpp" +======== +#include "relay_contact.hpp" +>>>>>>>> a41903e54 ((WIP, squash) contact library, re-org):llarp/contact/relay_contact_local.cpp + +#include + +namespace llarp +{ + LocalRC LocalRC::make(Ed25519SecretKey secret, oxen::quic::Address local) + { + return *new LocalRC{std::move(secret), std::move(local)}; + } + + LocalRC::LocalRC(Ed25519SecretKey secret, oxen::quic::Address local) : _secret_key{std::move(secret)} + { + _router_id = seckey_to_pubkey(_secret_key); + _addr = std::move(local); + if (_addr.is_ipv6()) + _addr6.emplace(&_addr.in6()); + resign(); + } + + RemoteRC LocalRC::to_remote() + { + resign(); + return RemoteRC{view()}; + } + + void LocalRC::bt_sign(oxenc::bt_dict_producer& btdp) + { + _signature.clear(); + + 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 = {sig.data(), sig.size()}; + return sig; + }); + + _payload = ustring{btdp.view()}; + } + + void LocalRC::bt_encode(oxenc::bt_dict_producer& btdp) + { + 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.to_view()); + + 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}); + } + + void LocalRC::resign() + { + set_systime_timestamp(); + oxenc::bt_dict_producer btdp; + bt_encode(btdp); + bt_sign(btdp); + } +} // namespace llarp diff --git a/llarp/contact/relay_contact_remote.cpp b/llarp/contact/relay_contact_remote.cpp new file mode 100644 index 0000000000..7258657914 --- /dev/null +++ b/llarp/contact/relay_contact_remote.cpp @@ -0,0 +1,59 @@ +<<<<<<<< HEAD:llarp/contact/router_contact_remote.cpp +#include "router_contact.hpp" +======== +#include "relay_contact.hpp" +>>>>>>>> a41903e54 ((WIP, squash) contact library, re-org):llarp/contact/relay_contact_remote.cpp + +#include + +namespace llarp +{ + static auto logcat = log::Cat("relay-contact"); + + RemoteRC::RemoteRC(oxenc::bt_dict_consumer btdc) + { + try + { + bt_load(btdc); + bt_verify(btdc, /*reject_expired=*/true); + } + catch (const std::exception& e) + { + auto err = "Exception caught parsing RemoteRC: {}"_format(e.what()); + log::warning(logcat, "{}", err); + throw std::runtime_error{err}; + } + } + + bool RemoteRC::read(const fs::path& fname) + { + log::trace(logcat, "{} called", __PRETTY_FUNCTION__); + _payload.resize(MAX_RC_SIZE); + + try + { + auto nread = util::file_to_buffer(fname, _payload.data(), _payload.size()); + log::trace(logcat, "{}B read from file (path:{})!", nread, fname); + _payload.resize(nread); + + oxenc::bt_dict_consumer btdc{_payload}; + bt_load(btdc); + bt_verify(btdc); + } + catch (const std::exception& e) + { + log::warning(logcat, "Failed to read or validate RC from {}: {}", fname, e.what()); + return false; + } + + return true; + } + + bool RemoteRC::verify() const + { + oxenc::bt_dict_consumer btdc{_payload}; + bt_verify(btdc); + return true; + } + +} // namespace llarp diff --git a/llarp/contact/router_contact.cpp b/llarp/contact/router_contact.cpp index 8ca93e635d..b57c14d1b3 100644 --- a/llarp/contact/router_contact.cpp +++ b/llarp/contact/router_contact.cpp @@ -1,12 +1,16 @@ +<<<<<<<< HEAD:llarp/contact/router_contact.cpp #include "router_contact.hpp" +======== +#include "relay_contact.hpp" +>>>>>>>> a41903e54 ((WIP, squash) contact library, re-org):llarp/contact/relay_contact.cpp #include namespace llarp { - static auto logcat = log::Cat("RC"); + static auto logcat = log::Cat("relay-contact"); - void RouterContact::bt_verify(oxenc::bt_dict_consumer& btdc, bool reject_expired) const + void RelayContact::bt_verify(oxenc::bt_dict_consumer& btdc, bool reject_expired) const { btdc.require_signature("~", [this, reject_expired](ustring_view msg, ustring_view sig) { if (sig.size() != 64) @@ -32,7 +36,7 @@ namespace llarp btdc.finish(); } - void RouterContact::bt_load(oxenc::bt_dict_consumer& btdc) + void RelayContact::bt_load(oxenc::bt_dict_consumer& btdc) { if (int rc_ver = btdc.require(""); rc_ver != RC_VERSION) throw std::runtime_error{"Invalid RC: do not know how to parse v{} RCs"_format(rc_ver)}; @@ -98,7 +102,7 @@ namespace llarp _router_version[i] = ver[i]; } - bool RouterContact::write(const fs::path& fname) const + bool RelayContact::write(const fs::path& fname) const { auto bte = view(); @@ -114,7 +118,7 @@ namespace llarp return true; } - nlohmann::json RouterContact::extract_status() const + nlohmann::json RelayContact::extract_status() const { nlohmann::json obj{ {"lastUpdated", _timestamp.time_since_epoch().count()}, @@ -136,7 +140,7 @@ namespace llarp return obj; } - bool RouterContact::is_public_addressable() const + bool RelayContact::is_public_addressable() const { if (_router_version.empty()) return false; @@ -144,24 +148,24 @@ namespace llarp return _addr.is_addressable(); } - bool RouterContact::is_expired(std::chrono::milliseconds now) const + bool RelayContact::is_expired(std::chrono::milliseconds now) const { return age(now) >= _timestamp.time_since_epoch() + LIFETIME; } - std::chrono::milliseconds RouterContact::time_to_expiry(std::chrono::milliseconds now) const + std::chrono::milliseconds RelayContact::time_to_expiry(std::chrono::milliseconds now) const { const auto expiry = _timestamp.time_since_epoch() + LIFETIME; return now < expiry ? expiry - now : 0s; } - std::chrono::milliseconds RouterContact::age(std::chrono::milliseconds now) const + std::chrono::milliseconds RelayContact::age(std::chrono::milliseconds now) const { auto delta = now - _timestamp.time_since_epoch(); return delta > 0s ? delta : 0s; } - bool RouterContact::expires_within_delta(std::chrono::milliseconds now, std::chrono::milliseconds dlt) const + bool RelayContact::expires_within_delta(std::chrono::milliseconds now, std::chrono::milliseconds dlt) const { return time_to_expiry(now) <= dlt; } @@ -171,7 +175,7 @@ namespace llarp "e6b3a6fe5e32c379b64212c72232d65b0b88ddf9bbaed4997409d329f8519e0b"sv, }; - bool RouterContact::is_obsolete_bootstrap() const + bool RelayContact::is_obsolete_bootstrap() const { for (const auto& k : obsolete_bootstraps) { @@ -181,7 +185,7 @@ namespace llarp return false; } - bool RouterContact::is_obsolete(const RouterContact& rc) + bool RelayContact::is_obsolete(const RelayContact& rc) { const auto& hex = rc._router_id.ToHex(); diff --git a/llarp/contact/router_contact.hpp b/llarp/contact/router_contact.hpp index 8c686bd52a..5e349ae5f1 100644 --- a/llarp/contact/router_contact.hpp +++ b/llarp/contact/router_contact.hpp @@ -24,7 +24,7 @@ namespace llarp inline static 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 + /// "" -- the RC format version, which must be == RelayContact::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 @@ -40,29 +40,29 @@ namespace llarp /// 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 + /// RelayContact + struct RelayContact { - static constexpr uint8_t RC_VERSION = 0; + static constexpr uint8_t RC_VERSION{0}; /// Unit tests disable this to allow private IP ranges in RCs, which normally get rejected. - inline static bool BLOCK_BOGONS = true; + inline static bool BLOCK_BOGONS{true}; inline static std::string ACTIVE_NETID{LOKINET_DEFAULT_NETID}; - inline static constexpr size_t MAX_RC_SIZE = 1024; + inline static constexpr size_t MAX_RC_SIZE{1024}; /// How long (from its signing time) before an RC is considered "stale". Relays republish /// their RCs slightly more frequently than this so that ideally this won't happen. - static constexpr auto STALE_AGE = 6h; + static constexpr auto STALE_AGE{6h}; /// How long (from its signing time) before an RC becomes "outdated". Outdated records are /// used (e.g. for path building) only if there are no newer records available, such as /// might be the case when a client has been turned off for a while. - static constexpr auto OUTDATED_AGE = 12h; + static constexpr auto OUTDATED_AGE{12h}; /// How long before an RC becomes invalid (and thus deleted). - static constexpr auto LIFETIME = 30 * 24h; + static constexpr auto LIFETIME{30 * 24h}; ustring_view view() const { return _payload; } @@ -115,15 +115,15 @@ namespace llarp bool write(const fs::path& fname) const; - auto operator<=>(const RouterContact& other) const + auto operator<=>(const RelayContact& other) const { return std::tie(_router_id, _addr, _addr6, _timestamp, _router_version) <=> std::tie(other._router_id, other._addr, other._addr6, other._timestamp, other._router_version); } - bool operator==(const RouterContact& other) const { return (*this <=> other) == 0; } + bool operator==(const RelayContact& other) const { return (*this <=> other) == 0; } - bool operator<(const RouterContact& other) const { return _router_id < other._router_id; } + bool operator<(const RelayContact& other) const { return _router_id < other._router_id; } virtual void clear() {} @@ -141,11 +141,11 @@ namespace llarp /// get the age of this RC in ms std::chrono::milliseconds age(std::chrono::milliseconds now) const; - bool other_is_newer(const RouterContact& other) const { return _timestamp < other._timestamp; } + bool other_is_newer(const RelayContact& other) const { return _timestamp < other._timestamp; } bool is_obsolete_bootstrap() const; - static bool is_obsolete(const RouterContact& rc); + static bool is_obsolete(const RelayContact& rc); void bt_verify(oxenc::bt_dict_consumer& data, bool reject_expired = false) const; @@ -156,14 +156,14 @@ namespace llarp struct RemoteRC; - /// Extension of RouterContact used to store a local "RC," and inserts a RouterContact by + /// Extension of RelayContact used to store a local "RC," and inserts a RelayContact 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 final : public RouterContact + struct LocalRC final : public RelayContact { static LocalRC make(Ed25519SecretKey secret, oxen::quic::Address local); @@ -241,9 +241,9 @@ namespace llarp void set_systime_timestamp() { set_timestamp(time_point_now()); } }; - /// Extension of RouterContact used in a "read-only" fashion. Parses the incoming RC to query + /// Extension of RelayContact 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 final : public RouterContact + struct RemoteRC final : public RelayContact { private: // this ctor is private because it doesn't set ::_payload @@ -288,19 +288,19 @@ namespace llarp namespace std { template <> - struct hash + struct hash { - virtual size_t operator()(const llarp::RouterContact& r) const + virtual size_t operator()(const llarp::RelayContact& r) const { return std::hash{}(r.router_id()); } }; template <> - struct hash : public hash + struct hash : public hash {}; template <> - struct hash final : public hash + struct hash final : public hash {}; } // namespace std diff --git a/llarp/contact/router_contact_local.cpp b/llarp/contact/router_contact_local.cpp index 710f594c77..8539f0c173 100644 --- a/llarp/contact/router_contact_local.cpp +++ b/llarp/contact/router_contact_local.cpp @@ -1,4 +1,8 @@ +<<<<<<<< HEAD:llarp/contact/router_contact_local.cpp #include "router_contact.hpp" +======== +#include "relay_contact.hpp" +>>>>>>>> a41903e54 ((WIP, squash) contact library, re-org):llarp/contact/relay_contact_local.cpp #include diff --git a/llarp/contact/router_contact_remote.cpp b/llarp/contact/router_contact_remote.cpp index aac83fb6ea..7258657914 100644 --- a/llarp/contact/router_contact_remote.cpp +++ b/llarp/contact/router_contact_remote.cpp @@ -1,10 +1,14 @@ +<<<<<<<< HEAD:llarp/contact/router_contact_remote.cpp #include "router_contact.hpp" +======== +#include "relay_contact.hpp" +>>>>>>>> a41903e54 ((WIP, squash) contact library, re-org):llarp/contact/relay_contact_remote.cpp #include namespace llarp { - static auto logcat = log::Cat("RC"); + static auto logcat = log::Cat("relay-contact"); RemoteRC::RemoteRC(oxenc::bt_dict_consumer btdc) { diff --git a/llarp/dht/kademlia.hpp b/llarp/dht/kademlia.hpp index e0d0d430a6..c6d37abcbf 100644 --- a/llarp/dht/kademlia.hpp +++ b/llarp/dht/kademlia.hpp @@ -2,7 +2,7 @@ #include "key.hpp" -#include +#include namespace llarp::dht { @@ -14,7 +14,7 @@ namespace llarp::dht 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 + bool operator()(const RelayContact& left, const RelayContact& right) const { return (left.router_id() ^ us) < (right.router_id() ^ us); } diff --git a/llarp/dht/node.hpp b/llarp/dht/node.hpp index 9c8e5a9691..6f85a6b317 100644 --- a/llarp/dht/node.hpp +++ b/llarp/dht/node.hpp @@ -2,7 +2,7 @@ #include "key.hpp" -#include +#include #include #include @@ -11,12 +11,12 @@ namespace llarp::dht { struct RCNode { - RouterContact rc; + RelayContact rc; Key_t ID; RCNode() { ID.zero(); } - RCNode(const RouterContact& other) : rc(other), ID(other.router_id()) {} + RCNode(const RelayContact& other) : rc(other), ID(other.router_id()) {} nlohmann::json ExtractStatus() const { return rc.extract_status(); } diff --git a/llarp/dns/srv_data.cpp b/llarp/dns/srv_data.cpp index b714edc7f4..d9f77f4a80 100644 --- a/llarp/dns/srv_data.cpp +++ b/llarp/dns/srv_data.cpp @@ -19,7 +19,7 @@ namespace llarp::dns throw std::invalid_argument{"Invalid SRVData!"}; } - SRVData::SRVData(std::string bt) + SRVData::SRVData(std::string_view bt) { try { @@ -107,16 +107,19 @@ namespace llarp::dns return is_valid(); } - std::string SRVData::bt_encode() const + void SRVData::bt_encode(oxenc::bt_dict_producer&& btdp) const { - oxenc::bt_dict_producer btdp; - btdp.append("p", port); btdp.append("s", service_proto); btdp.append("t", target); btdp.append("u", priority); btdp.append("w", weight); + } + std::string SRVData::bt_encode() const + { + oxenc::bt_dict_producer btdp; + bt_encode(std::move(btdp)); return std::move(btdp).str(); } diff --git a/llarp/dns/srv_data.hpp b/llarp/dns/srv_data.hpp index 8091e583f8..0db5a81394 100644 --- a/llarp/dns/srv_data.hpp +++ b/llarp/dns/srv_data.hpp @@ -26,7 +26,7 @@ namespace llarp::dns { SRVData() = default; // SRVData constructor expecting a bt-encoded dictionary - explicit SRVData(std::string bt); + explicit SRVData(std::string_view bt); SRVData(std::string _proto, uint16_t _priority, uint16_t _weight, uint16_t _port, std::string _target); /* bind-like formatted string for SRV records in config file @@ -80,6 +80,9 @@ namespace llarp::dns bool operator!=(const SRVData& other) const { return !(*this == other); } + void bt_encode(oxenc::bt_dict_producer&& btdp) const; + + // TESTNET: TODO: remove this after refactoring IntroSet -> ClientContact std::string bt_encode() const; bool bt_decode(std::string buf); diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index 28af64a168..b6ad8600af 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -231,7 +231,7 @@ namespace llarp::handlers } void SessionEndpoint::lookup_intro( - RouterID remote, bool is_relayed, uint64_t order, std::function)> func) + RouterID remote, bool is_relayed, uint64_t order, std::function)> func) { if (auto maybe_intro = _router.contacts().get_decrypted_introset(remote)) { @@ -306,7 +306,7 @@ namespace llarp::handlers // return build_more(1); // } - service::intro_que _path_intros = get_recent_path_intros(); + service::intro_que_old _path_intros = get_recent_path_intros(); if (_path_intros.empty()) { @@ -494,7 +494,7 @@ namespace llarp::handlers } void SessionEndpoint::_make_session_path( - service::IntroductionSet intros, NetworkAddress remote, on_session_init_hook cb, bool is_exit) + service::IntroductionSet_old intros, NetworkAddress remote, on_session_init_hook cb, bool is_exit) { // we can recurse through this function as we remove the first pivot of the set of introductions every // invocation @@ -589,7 +589,7 @@ namespace llarp::handlers false, 0, [this, remote, hook = std::move(handler), is_exit, counter]( - std::optional intro) mutable { + std::optional intro) mutable { // already have a successful return if (*counter == 0) return; diff --git a/llarp/handlers/session.hpp b/llarp/handlers/session.hpp index 013dea25dd..9aecab5e03 100644 --- a/llarp/handlers/session.hpp +++ b/llarp/handlers/session.hpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -31,8 +32,10 @@ namespace llarp // - Directly pre-loaded from config address_map _range_map; - service::Identity _identity; // TODO: TESTNET: move responsibilities to KeyManager - service::IntroSet _local_introset; + ClientContact _local_cc; // TODO: TESTNET: replacement for service::Introset + + service::Identity _identity; // TODO: TESTNET: move responsibilities to KeyManager, delete + service::IntroSetOld _local_introset; // TODO: TESTNET: remove with CC impl std::chrono::milliseconds _last_introset_regen_attempt{0s}; @@ -84,7 +87,7 @@ namespace llarp oxen::quic::Address local_address() const { return _local_addr; } - const service::IntroSet& intro_set() const { return _local_introset; } + const service::IntroSetOld& intro_set() const { return _local_introset; } // get copy of all srv records std::set srv_records() const { return {_srv_records.begin(), _srv_records.end()}; } @@ -124,7 +127,7 @@ namespace llarp RouterID remote, bool is_relayed, uint64_t order, - std::function)> func); + std::function)> func); // resolves any config mappings that parsed ONS addresses to their pubkey network address void resolve_ons_mappings(); @@ -160,7 +163,7 @@ namespace llarp bool _initiate_session(NetworkAddress remote, on_session_init_hook cb, bool is_exit = false); void _make_session_path( - service::IntroductionSet intros, NetworkAddress remote, on_session_init_hook cb, bool is_exit); + service::IntroductionSet_old intros, NetworkAddress remote, on_session_init_hook cb, bool is_exit); void _make_session( NetworkAddress remote, std::shared_ptr path, on_session_init_hook cb, bool is_exit); diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index e4b8a34ae9..25b9e11a48 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -568,7 +568,7 @@ namespace llarp::handlers // } // else if (subdomain == "netid") // { - // msg.AddTXTReply(fmt::format("netid={};", RouterContact::ACTIVE_NETID)); + // msg.AddTXTReply(fmt::format("netid={};", RelayContact::ACTIVE_NETID)); // } // else // { diff --git a/llarp/link/connection.hpp b/llarp/link/connection.hpp index 6fdcdf1c2c..784baf9f9a 100644 --- a/llarp/link/connection.hpp +++ b/llarp/link/connection.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/llarp/link/contacts.cpp b/llarp/link/contacts.cpp index e3311fddde..68cd3914da 100644 --- a/llarp/link/contacts.cpp +++ b/llarp/link/contacts.cpp @@ -11,9 +11,9 @@ namespace llarp _introset_nodes = std::make_unique>(_local_key, llarp::randint); } - std::optional Contacts::get_decrypted_introset(RouterID remote) const + std::optional Contacts::get_decrypted_introset(RouterID remote) const { - std::optional ret = std::nullopt; + std::optional ret = std::nullopt; if (auto encrypted = get_encrypted_introset(dht::Key_t::derive_from_rid(remote)); auto intro = encrypted->decrypt(remote)) diff --git a/llarp/link/contacts.hpp b/llarp/link/contacts.hpp index 999302377f..40e6421dc5 100644 --- a/llarp/link/contacts.hpp +++ b/llarp/link/contacts.hpp @@ -9,7 +9,7 @@ namespace llarp /// 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 + /// router, like RelayContacts and introsets for example struct Contacts { private: @@ -24,7 +24,7 @@ namespace llarp public: explicit Contacts(Router& r); - std::optional get_decrypted_introset(RouterID remote) const; + std::optional get_decrypted_introset(RouterID remote) const; std::optional get_encrypted_introset(const dht::Key_t& key) const; diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 459ab4d664..a433d47be5 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -548,7 +548,7 @@ namespace llarp connect_to(*rc, std::move(on_open), std::move(on_close)); } else - log::warning(logcat, "Could not find RouterContact for connection to rid:{}", rid); + log::warning(logcat, "Could not find RelayContact for connection to rid:{}", rid); } void LinkManager::connect_and_send( diff --git a/llarp/lokinet_shared.cpp b/llarp/lokinet_shared.cpp index d4f3dcd9ad..75fad25cea 100644 --- a/llarp/lokinet_shared.cpp +++ b/llarp/lokinet_shared.cpp @@ -446,7 +446,7 @@ extern "C" } else { - llarp::RouterContact rc{}; + llarp::RelayContact rc{}; if (not rc.BDecode(&buf)) { oxen::log::error(logcat, "failed to decode signle RC: {}", llarp::buffer_printer{buf}); diff --git a/llarp/net/traffic_policy.cpp b/llarp/net/traffic_policy.cpp index 4ef4405986..c997b15e9f 100644 --- a/llarp/net/traffic_policy.cpp +++ b/llarp/net/traffic_policy.cpp @@ -165,7 +165,7 @@ namespace llarp::net } } - void TrafficPolicy::bt_decode(oxenc::bt_dict_consumer& btdc) + void TrafficPolicy::bt_decode(oxenc::bt_dict_consumer&& btdc) { try { @@ -200,7 +200,7 @@ namespace llarp::net } } - void TrafficPolicy::bt_encode(oxenc::bt_dict_producer& btdp) const + void TrafficPolicy::bt_encode(oxenc::bt_dict_producer&& btdp) const { try { @@ -226,9 +226,7 @@ namespace llarp::net { try { - oxenc::bt_dict_consumer btdc{buf}; - - bt_decode(btdc); + bt_decode(oxenc::bt_dict_consumer{buf}); } catch (const std::exception& e) { diff --git a/llarp/net/traffic_policy.hpp b/llarp/net/traffic_policy.hpp index 10ae4fae3c..4fd442481e 100644 --- a/llarp/net/traffic_policy.hpp +++ b/llarp/net/traffic_policy.hpp @@ -66,9 +66,9 @@ namespace llarp::net /// protocols that are explicity allowed std::set protocols; - void bt_encode(oxenc::bt_dict_producer& btdp) const; + void bt_encode(oxenc::bt_dict_producer&& btdp) const; - void bt_decode(oxenc::bt_dict_consumer& btdc); + void bt_decode(oxenc::bt_dict_consumer&& btdc); bool bt_decode(std::string_view buf); nlohmann::json ExtractStatus() const; diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index e2ef4b9b23..788b59ea54 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -410,7 +410,7 @@ namespace llarp for (const auto& [rid, rc] : rc_lookup) { - if (now - rc.timestamp() > RouterContact::OUTDATED_AGE) + if (now - rc.timestamp() > RelayContact::OUTDATED_AGE) needed.push_back(rid); } @@ -654,9 +654,9 @@ namespace llarp _rc_fetch_ticker->stop(); if (success) - log::info(logcat, "Client successfully completed RouterContact fetch!"); + log::info(logcat, "Client successfully completed RelayContact fetch!"); else - log::warning(logcat, "Client stopped RouterContact fetch without a sucessful response!"); + log::warning(logcat, "Client stopped RelayContact fetch without a sucessful response!"); } void NodeDB::stop_rid_fetch(bool success) @@ -990,7 +990,7 @@ namespace llarp { auto cutoff_time = time_point_now(); - cutoff_time -= _is_service_node ? RouterContact::OUTDATED_AGE : RouterContact::LIFETIME; + cutoff_time -= _is_service_node ? RelayContact::OUTDATED_AGE : RelayContact::LIFETIME; for (auto itr = rc_lookup.begin(); itr != rc_lookup.end();) { diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index 119bfb9ac1..8183f897de 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -1,6 +1,6 @@ #pragma once -#include "contact/router_contact.hpp" +#include "contact/relay_contact.hpp" #include "contact/router_id.hpp" #include "crypto/crypto.hpp" #include "dht/key.hpp" @@ -96,7 +96,7 @@ namespace llarp std::chrono::milliseconds _next_flush_time; - /******** RouterID/RouterContacts ********/ + /******** RouterID/RelayContacts ********/ using Lock_t = util::NullLock; mutable util::NullMutex nodedb_mutex; diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index 31e6a7dfff..6c19b0b5f7 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -251,10 +251,10 @@ namespace llarp::path } } - service::intro_que PathHandler::get_recent_path_intros(std::chrono::milliseconds stale_threshold) const + service::intro_que_old PathHandler::get_recent_path_intros(std::chrono::milliseconds stale_threshold) const { Lock_t l{paths_mutex}; - service::intro_que ret{}; + service::intro_que_old ret{}; for (const auto& [_, p] : _paths) { @@ -265,10 +265,10 @@ namespace llarp::path return ret; } - std::optional PathHandler::get_path_intros_conditional( + std::optional PathHandler::get_path_intros_conditional( std::function filter) const { - service::IntroductionSet intros; + service::IntroductionSet_old intros; Lock_t l{paths_mutex}; for (const auto& p : _paths) diff --git a/llarp/path/path_handler.hpp b/llarp/path/path_handler.hpp index 248f2030a1..a4ae7095dd 100644 --- a/llarp/path/path_handler.hpp +++ b/llarp/path/path_handler.hpp @@ -159,10 +159,10 @@ namespace llarp std::optional> get_path(const RouterID& router) const; - service::intro_que get_recent_path_intros( + service::intro_que_old get_recent_path_intros( std::chrono::milliseconds stale_threshold = path::INTRO_STALE_THRESHOLD) const; - std::optional get_path_intros_conditional( + std::optional get_path_intros_conditional( std::function filter) const; nlohmann::json ExtractStatus() const; diff --git a/llarp/path/path_types.hpp b/llarp/path/path_types.hpp index 4b50026f80..1956834300 100644 --- a/llarp/path/path_types.hpp +++ b/llarp/path/path_types.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include #include diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 562858a6f8..618d3e1ea9 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -416,7 +416,7 @@ namespace llarp throw std::runtime_error{"Could not find net interface on current platform!"}; } - RouterContact::BLOCK_BOGONS = conf.router.block_bogons; + RelayContact::BLOCK_BOGONS = conf.router.block_bogons; } void Router::process_netconfig() @@ -607,7 +607,7 @@ namespace llarp _testnet = netid == llarp::LOKINET_TESTNET_NETID; _testing_disabled = conf.lokid.disable_testing; - RouterContact::ACTIVE_NETID = netid; + RelayContact::ACTIVE_NETID = netid; if (_testing_disabled and not _testnet) throw std::runtime_error{"Error: reachability testing can only be disabled on testnet!"}; diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 46ebc019ec..0f174065d3 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/llarp/service/identity.cpp b/llarp/service/identity.cpp index 61d780dd50..bfaccc9a45 100644 --- a/llarp/service/identity.cpp +++ b/llarp/service/identity.cpp @@ -64,14 +64,14 @@ namespace llarp::service } std::optional Identity::encrypt_and_sign_introset( - const IntroSet& other_i, std::chrono::milliseconds now) const + const IntroSetOld& other_i, std::chrono::milliseconds now) const { EncryptedIntroSet encrypted; if (other_i.intros.empty()) return std::nullopt; - IntroSet i{other_i}; + IntroSetOld i{other_i}; encrypted.nonce.Randomize(); // set timestamp // TODO: round to nearest 1000 ms diff --git a/llarp/service/identity.hpp b/llarp/service/identity.hpp index f59828153c..fc71051a6b 100644 --- a/llarp/service/identity.hpp +++ b/llarp/service/identity.hpp @@ -34,7 +34,7 @@ namespace llarp::service path_dh_func dh, SharedSecret& sharedkey, const ServiceInfo& other, const KeyExchangeNonce& N) const; std::optional encrypt_and_sign_introset( - const IntroSet& i, std::chrono::milliseconds now) const; + const IntroSetOld& i, std::chrono::milliseconds now) const; bool Sign(Signature& sig, uint8_t* buf, size_t size) const; diff --git a/llarp/service/intro.hpp b/llarp/service/intro.hpp index ea8041a95c..e65dd65d13 100644 --- a/llarp/service/intro.hpp +++ b/llarp/service/intro.hpp @@ -69,9 +69,9 @@ namespace llarp::service } }; - using intro_que = std::priority_queue, IntroExpiryComparator>; + using intro_que_old = std::priority_queue, IntroExpiryComparator>; - using IntroductionSet = std::set; + using IntroductionSet_old = std::set; } // namespace llarp::service diff --git a/llarp/service/intro_set.cpp b/llarp/service/intro_set.cpp index 5cf7586d9f..beb6970a36 100644 --- a/llarp/service/intro_set.cpp +++ b/llarp/service/intro_set.cpp @@ -121,15 +121,15 @@ namespace llarp::service sig); } - std::optional EncryptedIntroSet::decrypt(const PubKey& root) const + std::optional EncryptedIntroSet::decrypt(const PubKey& root) const { - std::optional ret = std::nullopt; + std::optional ret = std::nullopt; SharedSecret k(root); std::string payload{reinterpret_cast(introset_payload.data()), introset_payload.size()}; if (crypto::xchacha20(reinterpret_cast(payload.data()), payload.size(), k, nonce)) - ret = IntroSet{payload}; + ret = IntroSetOld{payload}; return ret; } @@ -179,7 +179,7 @@ namespace llarp::service reinterpret_cast(sig.data())); } - nlohmann::json IntroSet::ExtractStatus() const + nlohmann::json IntroSetOld::ExtractStatus() const { nlohmann::json obj{{"published", to_json(time_signed)}}; // TODO: this @@ -214,7 +214,7 @@ namespace llarp::service return obj; } - IntroSet::IntroSet(std::string bt_payload) + IntroSetOld::IntroSetOld(std::string bt_payload) { try { @@ -227,7 +227,7 @@ namespace llarp::service } } - bool IntroSet::bt_decode(std::string_view buf) + bool IntroSetOld::bt_decode(std::string_view buf) { try { @@ -237,7 +237,7 @@ namespace llarp::service catch (const std::exception& e) { // DISCUSS: rethrow or print warning/return false...? - auto err = "IntroSet parsing exception: {}"_format(e.what()); + auto err = "IntroSetOld parsing exception: {}"_format(e.what()); log::warning(logcat, "{}", err); throw std::runtime_error{err}; } @@ -245,7 +245,7 @@ namespace llarp::service return true; } - void IntroSet::bt_decode(oxenc::bt_dict_consumer& btdc) + void IntroSetOld::bt_decode(oxenc::bt_dict_consumer& btdc) { try { @@ -254,15 +254,14 @@ namespace llarp::service if (key != "a") throw std::invalid_argument{ - "IntroSet received unexpected key (expected:'a', actual:{})"_format(key)}; + "IntroSetOld received unexpected key (expected:'a', actual:{})"_format(key)}; address_keys.bt_decode(subdict); } if (auto maybe_subdict = btdc.maybe("e"); maybe_subdict) { - oxenc::bt_dict_consumer subdict{*maybe_subdict}; - exit_policy->bt_decode(subdict); + exit_policy->bt_decode(oxenc::bt_dict_consumer{*maybe_subdict}); } { @@ -270,7 +269,7 @@ namespace llarp::service if (key != "i") throw std::invalid_argument{ - "IntroSet received unexpected key (expected:'i', actual:{})"_format(key)}; + "IntroSetOld received unexpected key (expected:'i', actual:{})"_format(key)}; while (not sublist.is_finished()) { @@ -313,12 +312,12 @@ namespace llarp::service } catch (...) { - log::critical(logcat, "IntroSet failed to decode bt payload!"); + log::critical(logcat, "IntroSetOld failed to decode bt payload!"); throw; } } - std::string IntroSet::bt_encode() const + std::string IntroSetOld::bt_encode() const { oxenc::bt_dict_producer btdp; @@ -331,8 +330,7 @@ namespace llarp::service if (exit_policy) { - auto subdict = btdp.append_dict("e"); - exit_policy->bt_encode(subdict); + exit_policy->bt_encode(btdp.append_dict("e")); } { @@ -367,13 +365,13 @@ namespace llarp::service } catch (...) { - log::critical(logcat, "Error: IntroSet failed to bt encode contents!"); + log::critical(logcat, "Error: IntroSetOld failed to bt encode contents!"); } return std::move(btdp).str(); } - bool IntroSet::HasExpiredIntros(std::chrono::milliseconds now) const + bool IntroSetOld::HasExpiredIntros(std::chrono::milliseconds now) const { for (const auto& intro : intros) if (now >= intro.expiry) @@ -381,7 +379,7 @@ namespace llarp::service return false; } - bool IntroSet::HasStaleIntros(std::chrono::milliseconds now, std::chrono::milliseconds delta) const + bool IntroSetOld::HasStaleIntros(std::chrono::milliseconds now, std::chrono::milliseconds delta) const { for (const auto& intro : intros) if (intro.expires_soon(delta, now)) @@ -389,12 +387,12 @@ namespace llarp::service return false; } - bool IntroSet::IsExpired(std::chrono::milliseconds now) const + bool IntroSetOld::IsExpired(std::chrono::milliseconds now) const { return GetNewestIntroExpiration() < now; } - std::vector IntroSet::GetMatchingSRVRecords(std::string_view service_proto) const + std::vector IntroSetOld::GetMatchingSRVRecords(std::string_view service_proto) const { std::vector records; @@ -409,9 +407,9 @@ namespace llarp::service return records; } - bool IntroSet::verify(std::chrono::milliseconds now) const + bool IntroSetOld::verify(std::chrono::milliseconds now) const { - IntroSet copy; + IntroSetOld copy; copy = *this; copy.signature.zero(); @@ -434,7 +432,7 @@ namespace llarp::service return not IsExpired(now); } - std::chrono::milliseconds IntroSet::GetNewestIntroExpiration() const + std::chrono::milliseconds IntroSetOld::GetNewestIntroExpiration() const { std::chrono::milliseconds maxTime = 0s; for (const auto& intro : intros) @@ -442,9 +440,9 @@ namespace llarp::service return maxTime; } - std::string IntroSet::to_string() const + std::string IntroSetOld::to_string() const { - return "[IntroSet addressKeys={} intros={{}} topic={} signedAt={} v={} sig={}]"_format( + return "[IntroSetOld addressKeys={} intros={{}} topic={} signedAt={} v={} sig={}]"_format( address_keys.to_string(), "{}"_format(fmt::join(intros, ",")), time_signed.count(), diff --git a/llarp/service/intro_set.hpp b/llarp/service/intro_set.hpp index d6b7ebe2e8..7d7dbacb6f 100644 --- a/llarp/service/intro_set.hpp +++ b/llarp/service/intro_set.hpp @@ -22,16 +22,16 @@ namespace llarp::service // 10 seconds clock skew permitted for introset expiration constexpr std::chrono::milliseconds MAX_INTROSET_TIME_DELTA = 10s; - struct IntroSet + struct IntroSetOld { ServiceInfo address_keys; - IntroductionSet intros; + IntroductionSet_old intros; std::vector SRVs; std::chrono::milliseconds time_signed = 0s; - IntroSet() = default; + IntroSetOld() = default; - explicit IntroSet(std::string bt_payload); + explicit IntroSetOld(std::string bt_payload); /// ethertypes we advertise that we speak std::vector supported_protocols; @@ -47,7 +47,7 @@ namespace llarp::service Signature signature; uint64_t version = llarp::constants::proto_version; - bool OtherIsNewer(const IntroSet& other) const { return time_signed < other.time_signed; } + bool OtherIsNewer(const IntroSetOld& other) const { return time_signed < other.time_signed; } std::string to_string() const; @@ -75,18 +75,18 @@ namespace llarp::service static constexpr bool to_string_formattable = true; }; - inline bool operator<(const IntroSet& lhs, const IntroSet& rhs) + inline bool operator<(const IntroSetOld& lhs, const IntroSetOld& rhs) { return lhs.address_keys < rhs.address_keys; } - inline bool operator==(const IntroSet& lhs, const IntroSet& rhs) + inline bool operator==(const IntroSetOld& lhs, const IntroSetOld& rhs) { return std::tie(lhs.address_keys, lhs.intros, lhs.time_signed, lhs.version, lhs.signature) == std::tie(rhs.address_keys, rhs.intros, rhs.time_signed, rhs.version, rhs.signature); } - inline bool operator!=(const IntroSet& lhs, const IntroSet& rhs) + inline bool operator!=(const IntroSetOld& lhs, const IntroSetOld& rhs) { return !(lhs == rhs); } @@ -138,7 +138,7 @@ namespace llarp::service nlohmann::json ExtractStatus() const; - std::optional decrypt(const PubKey& root) const; + std::optional decrypt(const PubKey& root) const; static constexpr bool to_string_formattable = true; }; @@ -159,6 +159,6 @@ namespace llarp::service } using EncryptedIntroSetLookupHandler = std::function&)>; - using IntroSetLookupHandler = std::function&)>; + using IntroSetLookupHandler = std::function&)>; } // namespace llarp::service diff --git a/pybind/common.hpp b/pybind/common.hpp index f2315357ce..9484ffef7d 100644 --- a/pybind/common.hpp +++ b/pybind/common.hpp @@ -21,7 +21,7 @@ namespace llarp void RouterID_Init(py::module& mod); - void RouterContact_Init(py::module& mod); + void RelayContact_Init(py::module& mod); void Config_Init(py::module& mod); diff --git a/pybind/llarp/config.cpp b/pybind/llarp/config.cpp index 1926902086..3cf00ba7e7 100644 --- a/pybind/llarp/config.cpp +++ b/pybind/llarp/config.cpp @@ -104,7 +104,7 @@ namespace llarp self.routers.clear(); for (const auto& arg : args) { - RouterContact rc{}; + RelayContact rc{}; if (rc.Read(arg)) self.routers.emplace(std::move(rc)); else diff --git a/pybind/llarp/router_contact.cpp b/pybind/llarp/router_contact.cpp index 84596f1ba9..806fa795db 100644 --- a/pybind/llarp/router_contact.cpp +++ b/pybind/llarp/router_contact.cpp @@ -1,29 +1,28 @@ #include "common.hpp" #include -#include +#include #include namespace llarp { - void RouterContact_Init(py::module& mod) + void RelayContact_Init(py::module& mod) { - py::class_(mod, "RouterContact") + py::class_(mod, "RelayContact") .def(py::init<>()) .def_property_readonly( - "routerID", - [](const RouterContact* const rc) -> llarp::RouterID { return llarp::RouterID(rc->pubkey); }) + "routerID", [](const RelayContact* const rc) -> llarp::RouterID { return llarp::RouterID(rc->pubkey); }) .def_property_readonly( "AsDHTKey", - [](const RouterContact* const rc) -> llarp::dht::Key_t { + [](const RelayContact* const rc) -> llarp::dht::Key_t { return llarp::dht::Key_t{rc->pubkey.as_array()}; }) - .def("ReadFile", &RouterContact::Read) - .def("WriteFile", &RouterContact::Write) - .def("ToString", &RouterContact::ToString) - .def("__str__", &RouterContact::ToString) - .def("__repr__", &RouterContact::ToString) - .def("Verify", [](const RouterContact* const rc) -> bool { + .def("ReadFile", &RelayContact::Read) + .def("WriteFile", &RelayContact::Write) + .def("ToString", &RelayContact::ToString) + .def("__str__", &RelayContact::ToString) + .def("__repr__", &RelayContact::ToString) + .def("Verify", [](const RelayContact* const rc) -> bool { const std::chrono::milliseconds now = llarp::time_now_ms(); return rc->Verify(now); }); diff --git a/pybind/module.cpp b/pybind/module.cpp index cbd07a4971..7d1749f484 100644 --- a/pybind/module.cpp +++ b/pybind/module.cpp @@ -11,7 +11,7 @@ PYBIND11_MODULE(pyllarp, m) llarp::PeerDb_Init(m); llarp::PeerStats_Init(m); llarp::RouterID_Init(m); - llarp::RouterContact_Init(m); + llarp::RelayContact_Init(m); llarp::CryptoTypes_Init(m); llarp::Context_Init(m); tooling::HiveContext_Init(m); diff --git a/test/crypto/test_llarp_key_manager.cpp b/test/crypto/test_llarp_key_manager.cpp index 31714e7870..d2780b301f 100644 --- a/test/crypto/test_llarp_key_manager.cpp +++ b/test/crypto/test_llarp_key_manager.cpp @@ -32,7 +32,7 @@ struct KeyManagerTest bool generateRcFile() { - RouterContact rc; + RelayContact rc; return rc.Write(our_rc_filename); } }; diff --git a/test/nodedb/test_nodedb.cpp b/test/nodedb/test_nodedb.cpp index 9286e345b3..29a5e2ee22 100644 --- a/test/nodedb/test_nodedb.cpp +++ b/test/nodedb/test_nodedb.cpp @@ -1,7 +1,7 @@ #include #include -#include +#include #include using llarp_nodedb = llarp::NodeDB; @@ -13,7 +13,7 @@ TEST_CASE("FindClosestTo returns correct number of elements", "[nodedb][dht]") constexpr uint64_t numRCs = 3; for (uint64_t i = 0; i < numRCs; ++i) { - llarp::RouterContact rc; + llarp::RelayContact rc; rc.pubkey[0] = i; nodeDB.Put(rc); } @@ -22,7 +22,7 @@ TEST_CASE("FindClosestTo returns correct number of elements", "[nodedb][dht]") llarp::dht::Key_t key; - std::vector results = nodeDB.FindManyClosestTo(key, 4); + std::vector results = nodeDB.FindManyClosestTo(key, 4); // we asked for more entries than nodedb had REQUIRE(numRCs == results.size()); @@ -33,15 +33,15 @@ TEST_CASE("FindClosestTo returns properly ordered set", "[nodedb][dht]") llarp_nodedb nodeDB{fs::current_path(), nullptr}; // insert some RCs: a < b < c - llarp::RouterContact a; + llarp::RelayContact a; a.pubkey[0] = 1; nodeDB.Put(a); - llarp::RouterContact b; + llarp::RelayContact b; b.pubkey[0] = 2; nodeDB.Put(b); - llarp::RouterContact c; + llarp::RelayContact c; c.pubkey[0] = 3; nodeDB.Put(c); @@ -49,7 +49,7 @@ TEST_CASE("FindClosestTo returns properly ordered set", "[nodedb][dht]") llarp::dht::Key_t key; - std::vector results = nodeDB.FindManyClosestTo(key, 2); + std::vector results = nodeDB.FindManyClosestTo(key, 2); REQUIRE(2 == results.size()); // we xor'ed with 0x0, so order should be a,b,c diff --git a/test/path/test_path.cpp b/test/path/test_path.cpp index d25a1c68e7..60d5f706be 100644 --- a/test/path/test_path.cpp +++ b/test/path/test_path.cpp @@ -4,7 +4,7 @@ using Path_t = llarp::path::Path; using Path_ptr = llarp::path::Path_ptr; using Set_t = llarp::path::Path::UniqueEndpointSet_t; -using RC_t = llarp::RouterContact; +using RC_t = llarp::RelayContact; static RC_t MakeHop(const char name) diff --git a/test/peerstats/test_peer_db.cpp b/test/peerstats/test_peer_db.cpp index c3ed14c791..51b1f193f0 100644 --- a/test/peerstats/test_peer_db.cpp +++ b/test/peerstats/test_peer_db.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include @@ -120,10 +120,10 @@ TEST_CASE("Test PeerDb handleGossipedRC", "[PeerDb]") { const llarp::RouterID id = llarp::test::makeBuf(0xCA); - auto rcLifetime = llarp::RouterContact::Lifetime; + auto rcLifetime = llarp::RelayContact::Lifetime; llarp_time_t now = 0s; - llarp::RouterContact rc; + llarp::RelayContact rc; rc.pubkey = llarp::PubKey(id); rc.last_updated = 10s; @@ -162,13 +162,13 @@ TEST_CASE("Test PeerDb handleGossipedRC expiry calcs", "[PeerDb]") // see comments in peer_db.cpp above PeerDb::handleGossipedRC() for some context around these // tests and esp. these numbers const llarp_time_t ref = 48h; - const llarp_time_t rcLifetime = llarp::RouterContact::Lifetime; + const llarp_time_t rcLifetime = llarp::RelayContact::Lifetime; // rc1, first rc received const llarp_time_t s1 = ref; const llarp_time_t r1 = s1 + 30s; const llarp_time_t e1 = s1 + rcLifetime; - llarp::RouterContact rc1; + llarp::RelayContact rc1; rc1.pubkey = llarp::PubKey(id); rc1.last_updated = s1; @@ -177,7 +177,7 @@ TEST_CASE("Test PeerDb handleGossipedRC expiry calcs", "[PeerDb]") const llarp_time_t s2 = s1 + 8h; const llarp_time_t r2 = s2 + 30s; // healthy recv time const llarp_time_t e2 = s2 + rcLifetime; - llarp::RouterContact rc2; + llarp::RelayContact rc2; rc2.pubkey = llarp::PubKey(id); rc2.last_updated = s2; @@ -185,7 +185,7 @@ TEST_CASE("Test PeerDb handleGossipedRC expiry calcs", "[PeerDb]") // received "unhealthily" (after rc2 expires) const llarp_time_t s3 = s2 + 8h; const llarp_time_t r3 = e2 + 1h; // received after e2 - llarp::RouterContact rc3; + llarp::RelayContact rc3; rc3.pubkey = llarp::PubKey(id); rc3.last_updated = s3; diff --git a/test/service/test_llarp_service_identity.cpp b/test/service/test_llarp_service_identity.cpp index 5d0bd42bec..1a2b29f166 100644 --- a/test/service/test_llarp_service_identity.cpp +++ b/test/service/test_llarp_service_identity.cpp @@ -194,7 +194,7 @@ TEST_CASE("Test sign and encrypt introset", "[crypto]") ident.RegenerateKeys(); service::Address addr; CHECK(ident.pub.CalculateAddress(addr.as_array())); - service::IntroSet introset; + service::IntroSetOld introset; auto now = time_now_ms(); introset.timestampSignedAt = now; while(introset.intros.size() < 10) diff --git a/test/test_llarp_router_contact.cpp b/test/test_llarp_router_contact.cpp index f3a7611e5d..6cd3db8965 100644 --- a/test/test_llarp_router_contact.cpp +++ b/test/test_llarp_router_contact.cpp @@ -1,16 +1,16 @@ #include #include -#include +#include #include #include namespace llarp { -TEST_CASE("RouterContact Sign and Verify", "[RC][RouterContact][signature][sign][verify]") +TEST_CASE("RelayContact Sign and Verify", "[RC][RelayContact][signature][sign][verify]") { - RouterContact rc; + RelayContact rc; SecretKey sign; crypto::identity_keygen(sign); @@ -25,9 +25,9 @@ TEST_CASE("RouterContact Sign and Verify", "[RC][RouterContact][signature][sign] REQUIRE(rc.Verify(time_now_ms())); } -TEST_CASE("RouterContact Decode Version 1", "[RC][RouterContact][V1]") +TEST_CASE("RelayContact Decode Version 1", "[RC][RelayContact][V1]") { - RouterContact rc; + RelayContact rc; SecretKey sign; crypto::identity_keygen(sign); @@ -50,7 +50,7 @@ TEST_CASE("RouterContact Decode Version 1", "[RC][RouterContact][V1]") encoded_llarp.sz = encoded_llarp.cur - encoded_llarp.base; encoded_llarp.cur = encoded_llarp.base; - RouterContact decoded_rc; + RelayContact decoded_rc; REQUIRE(decoded_rc.BDecode(&encoded_llarp)); @@ -59,9 +59,9 @@ TEST_CASE("RouterContact Decode Version 1", "[RC][RouterContact][V1]") REQUIRE(decoded_rc == rc); } -TEST_CASE("RouterContact Decode Mixed Versions", "[RC][RouterContact]") +TEST_CASE("RelayContact Decode Mixed Versions", "[RC][RelayContact]") { - RouterContact rc1, rc2, rc3, rc4; + RelayContact rc1, rc2, rc3, rc4; rc1.version = 0; rc2.version = 1; @@ -94,7 +94,7 @@ TEST_CASE("RouterContact Decode Mixed Versions", "[RC][RouterContact]") REQUIRE(rc3.Sign(sign3)); REQUIRE(rc4.Sign(sign4)); - std::vector rc_vec; + std::vector rc_vec; rc_vec.push_back(rc1); rc_vec.push_back(rc2); rc_vec.push_back(rc3); @@ -107,7 +107,7 @@ TEST_CASE("RouterContact Decode Mixed Versions", "[RC][RouterContact]") encoded_llarp.sz = encoded_llarp.cur - encoded_llarp.base; encoded_llarp.cur = encoded_llarp.base; - std::vector rc_vec_out; + std::vector rc_vec_out; BEncodeReadList(rc_vec_out, &encoded_llarp); From 1359ee36ec71fdcff29811e5059ef2c0a94de0a3 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 3 Oct 2024 13:24:32 -0700 Subject: [PATCH 05/44] ExitConfig struct added, backcompat, etc --- llarp/config/config.cpp | 176 +++++++++++++++++++++++++- llarp/config/config.hpp | 42 ++++-- llarp/contact/client_contact.cpp | 6 - llarp/contact/client_contact.hpp | 13 +- llarp/contact/relay_contact.cpp | 2 +- llarp/contact/relay_contact.hpp | 41 +++--- llarp/contact/relay_contact_local.cpp | 2 +- llarp/handlers/session.cpp | 7 +- llarp/handlers/session.hpp | 2 +- llarp/handlers/tun.hpp | 4 +- llarp/net/traffic_policy.cpp | 10 +- llarp/net/traffic_policy.hpp | 7 +- llarp/service/intro_set.hpp | 4 +- 13 files changed, 250 insertions(+), 66 deletions(-) diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index 82b462a580..01a5e3afe1 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -225,6 +225,147 @@ namespace llarp is_relay = params.is_relay; } + void ExitConfig::define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params) + { + (void)params; + + conf.define_option( + "exit", + "enable", + ClientOnly, + Default{false}, + assignment_acceptor(exit_enabled), + Comment{ + "Enable exit-node functionality for local lokinet instance.", + }); + + conf.define_option( + "exit", + "auth", + ClientOnly, + MultiValue, + Comment{ + "Specify an optional authentication token required to use a non-public exit node.", + "For example:", + " auth=myfavouriteexit.loki:abc", + "uses the authentication code `abc` whenever myfavouriteexit.loki is accessed.", + "Can be specified multiple times to store codes for different exit nodes.", + }, + [this](std::string arg) { + if (arg.empty()) + throw std::invalid_argument{"Empty argument passed to '[exit]:auth'"}; + + const auto pos = arg.find(":"); + + if (pos == std::string::npos) + { + throw std::invalid_argument( + "[exit]:auth invalid format, expects exit-address.loki:auth-token-goes-here"); + } + + const auto addr = arg.substr(0, pos); + auto auth = arg.substr(pos + 1); + + if (service::is_valid_ons(addr)) + { + ons_auth_tokens.emplace(std::move(addr), std::move(auth)); + } + else if (auto exit = NetworkAddress::from_network_addr(addr); exit->is_client()) + { + auth_tokens.emplace(std::move(*exit), std::move(auth)); + } + else + throw std::invalid_argument("[exit]:auth invalid exit address"); + }); + + conf.define_option( + "exit", + "policy", + MultiValue, + Comment{ + "Specifies the IP traffic accepted by the local exit node traffic policy. If any are", + "specified then only matched traffic will be allowed and all other traffic will be", + "dropped. Examples:", + " policy=tcp", + "would allow all TCP/IP packets (regardless of port);", + " policy=0x69", + "would allow IP traffic with IP protocol 0x69;", + " policy=udp/53", + "would allow UDP port 53; and", + " policy=tcp/smtp", + "would allow TCP traffic on the standard smtp port (21).", + }, + [this](std::string arg) { + // this will throw on error + exit_policy.protocols.emplace(arg); + }); + + conf.define_option( + "exit", + "reserved-range", + ClientOnly, + MultiValue, + Comment{ + "Reserve an ip range to use as an exit broker for a `.loki` address", + "Specify a `.loki` address and a reserved ip range to use as an exit broker.", + "Examples:", + " reserved-range=whatever.loki", + "would route all exit traffic through whatever.loki; and", + " reserved-range=stuff.loki:100.0.0.0/24", + "would route the IP range 100.0.0.0/24 through stuff.loki.", + "This option can be specified multiple times (to map different IP ranges).", + }, + [this](std::string arg) { + if (arg.empty()) + return; + + std::optional range; + + const auto pos = arg.find(":"); + + std::string input = (pos == std::string::npos) ? "0.0.0.0/0"s : arg.substr(pos + 1); + + range = IPRange::from_string(std::move(input)); + + if (not range.has_value()) + throw std::invalid_argument("[network]:exit-node invalid ip range for exit provided"); + + if (pos != std::string::npos) + arg = arg.substr(0, pos); + + if (service::is_valid_ons(arg)) + ons_ranges.emplace(std::move(arg), std::move(*range)); + else if (auto maybe_raddr = NetworkAddress::from_network_addr(arg); maybe_raddr) + ranges.emplace(std::move(*maybe_raddr), std::move(*range)); + else + throw std::invalid_argument{"[network]:exit-node bad address: {}"_format(arg)}; + }); + + conf.define_option( + "exit", + "routed-range", + MultiValue, + Comment{ + "Route local exit node traffic through the specified IP range. If omitted, the", + "default is ALL public ranges. Can be set to public to indicate that this exit", + "routes traffic to the public internet.", + "For example:", + " routed-range=10.0.0.0/16", + " routed-range=public", + "to advertise that this exit routes traffic to both the public internet, and to", + "10.0.x.y addresses.", + "", + "Note that this option does not automatically configure network routing; that", + "must be configured separately on the exit system to handle lokinet traffic.", + }, + [this](std::string arg) { + if (auto range = IPRange::from_string(arg)) + exit_policy.ranges.insert(std::move(*range)); + else + throw std::invalid_argument{"Bad IP range passed to routed-range:{}"_format(arg)}; + }); + } + void NetworkConfig::define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params) { (void)params; @@ -413,19 +554,27 @@ namespace llarp conf.define_option( "network", "exit", + Hidden, ClientOnly, Default{false}, - assignment_acceptor(allow_exit), + [this](bool arg) { + allow_exit = arg; + log::warning(logcat, "This option is deprecated! Use [exit]:enable instead!"); + }, Comment{ - "Whether or not we should act as an exit node. Beware that this increases demand", + "<< DEPRECATED -- use [exit]:enable instead >>\n", + "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.define_option( "network", "routed-range", + Hidden, MultiValue, Comment{ + "<< DEPRECATED -- use [exit]:routed-range instead >>\n", "When in exit mode announce one or more IP ranges that this exit node routes", "traffic for. If omitted, the default is all public ranges. Can be set to", "public to indicate that this exit routes traffic to the public internet.", @@ -439,8 +588,11 @@ namespace llarp "must be configured separately on the exit system to handle lokinet traffic.", }, [this](std::string arg) { + if (not traffic_policy) + traffic_policy = net::ExitPolicy{}; + if (auto range = IPRange::from_string(arg)) - _routed_ranges.insert(std::move(*range)); + traffic_policy->ranges.insert(std::move(*range)); else throw std::invalid_argument{"Bad IP range passed to routed-range:{}"_format(arg)}; }); @@ -448,8 +600,10 @@ namespace llarp conf.define_option( "network", "traffic-whitelist", + Hidden, MultiValue, Comment{ + "<< DEPRECATED -- use [exit]:policy instead >>\n", "Adds an IP traffic type whitelist; can be specified multiple times. If any are", "specified then only matched traffic will be allowed and all other traffic will be", "dropped. Examples:", @@ -464,7 +618,9 @@ namespace llarp }, [this](std::string arg) { if (not traffic_policy) - traffic_policy = net::TrafficPolicy{}; + traffic_policy = net::ExitPolicy{}; + + log::warning(logcat, "This option is deprecated! Use [exit]:policy instead!"); // this will throw on error traffic_policy->protocols.emplace(arg); @@ -473,9 +629,11 @@ namespace llarp conf.define_option( "network", "exit-node", + Hidden, ClientOnly, MultiValue, Comment{ + "<< DEPRECATED -- use [exit]:reserved-range instead >>\n", "Specify a `.loki` address and an ip range to use as an exit broker.", "Examples:", " exit-node=whatever.loki", @@ -488,6 +646,8 @@ namespace llarp if (arg.empty()) return; + log::warning(logcat, "This option is deprecated! Use [exit]:reserved-range instead!"); + std::optional range; const auto pos = arg.find(":"); @@ -514,9 +674,12 @@ namespace llarp "network", "exit-auth", ClientOnly, + Hidden, MultiValue, Comment{ - "Specify an optional authentication code required to use a non-public exit node.", + "<< DEPRECATED -- use [exit]:auth instead >>\n", + "Specify an optional authentication code required to use ", + "a non-public exit node.", "For example:", " exit-auth=myfavouriteexit.loki:abc", "uses the authentication code `abc` whenever myfavouriteexit.loki is accessed.", @@ -526,6 +689,8 @@ namespace llarp if (arg.empty()) throw std::invalid_argument{"Empty argument passed to 'exit-auth'"}; + log::warning(logcat, "This option is deprecated! Use [exit]:auth instead!"); + const auto pos = arg.find(":"); if (pos == std::string::npos) @@ -1547,6 +1712,7 @@ namespace llarp void Config::init_config(ConfigDefinition& conf, const ConfigGenParameters& params) { router.define_config_options(conf, params); + exit.define_config_options(conf, params); network.define_config_options(conf, params); paths.define_config_options(conf, params); dns.define_config_options(conf, params); diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index 1c8d037643..590a92387c 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -87,15 +87,33 @@ namespace llarp /// i.e. 32 for every hop unique ip, 24 unique /24 per hop, etc uint8_t unique_hop_netmask; - /// set of countrys to exclude from path building (2 char country code) - std::unordered_set exclude_countries; - void define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); /// return true if this set of router contacts is acceptable against this config bool check_rcs(const std::set& hops) const; }; + /// Config options related to exit node services + struct ExitConfig + { + bool exit_enabled{false}; + + // Used by RemoteHandler to provide auth tokens for remote exits + std::unordered_map auth_tokens; + std::unordered_map ons_auth_tokens; + + net::ExitPolicy exit_policy; + + // Remote client ONS exit addresses mapped to local IP ranges pending ONS address resolution + // Reserved local IP ranges mapped to remote client ONS addresses (pending ONS resolution) + std::unordered_map ons_ranges; + + // Reserved local IP ranges mapped to remote client exit addresses + std::unordered_map ranges; + + void define_config_options(ConfigDefinition& conf, const ConfigGenParameters& params); + }; + struct NetworkConfig { bool enable_profiling; @@ -108,16 +126,11 @@ namespace llarp std::optional paths; bool enable_ipv6{false}; - bool allow_exit{false}; bool is_reachable{false}; bool init_tun{true}; std::set snode_blacklist; - // Used by RemoteHandler to provide auth tokens for remote exits - std::unordered_map exit_auths; - std::unordered_map ons_exit_auths; - /* Auth specific config */ auth::AuthType auth_type = auth::AuthType::NONE; auth::AuthFileType auth_file_type = auth::AuthFileType::HASHES; @@ -133,8 +146,6 @@ namespace llarp std::vector srv_records; - std::optional traffic_policy; - std::optional path_alignment_timeout; /* TESTNET: Under modification */ @@ -163,14 +174,18 @@ namespace llarp // - when a session is created, check mapping when assigning IP's std::unordered_map _reserved_local_ips; + // TESTNET: moved into ExitConfig! + bool allow_exit{false}; + // Used by RemoteHandler to provide auth tokens for remote exits + std::unordered_map exit_auths; + std::unordered_map ons_exit_auths; + std::optional traffic_policy; // Remote client exit addresses mapped to local IP ranges std::unordered_map _exit_ranges; - // Remote client ONS exit addresses mapped to local IP ranges pending ONS address resolution std::unordered_map _ons_ranges; - // Used when in exit mode; pass down to LocalEndpoint - std::set _routed_ranges; + // std::set _routed_ranges; // moved into traffic_policy! bool enable_route_poker; bool blackhole_routes; @@ -261,6 +276,7 @@ namespace llarp virtual std::unique_ptr make_gen_params() const; RouterConfig router; + ExitConfig exit; NetworkConfig network; PeerSelectionConfig paths; DnsConfig dns; diff --git a/llarp/contact/client_contact.cpp b/llarp/contact/client_contact.cpp index e1bea0abd7..99d09da670 100644 --- a/llarp/contact/client_contact.cpp +++ b/llarp/contact/client_contact.cpp @@ -39,9 +39,6 @@ namespace llarp s.bt_encode(sublist.append_dict()); } - btdp.append("t", signed_at.count()); - btdp.append("~", signature.to_view()); - return std::move(btdp).str(); } @@ -95,9 +92,6 @@ namespace llarp while (not sublist.is_finished()) SRVs.emplace_back(sublist.consume_string_view()); } - - signed_at = std::chrono::milliseconds{btdc.require("t")}; - signature.from_string(btdc.require("~")); } bool ClientContact::is_expired(std::chrono::milliseconds now) const diff --git a/llarp/contact/client_contact.hpp b/llarp/contact/client_contact.hpp index 61de295451..94c71fa5f8 100644 --- a/llarp/contact/client_contact.hpp +++ b/llarp/contact/client_contact.hpp @@ -28,6 +28,17 @@ namespace llarp // TODO: add version to `` field to match RelayContact + /** ClientContact + + On the wire we encode the data as a dict containing: + - "" : the CC format version, which must be == ClientContact::VERSION to be parsed successfully + - "a" : public key of the remote client instance + - "i" : list of client introductions corresponding to the different pivots through which paths can be built + to the client instance + - "p" : supported protocols indicating the traffic accepted by the client instance; this indicates if the + client is embedded and therefore requires a tunneled connection + - "s" : SRV records for lokinet DNS lookup + */ struct ClientContact { static constexpr uint8_t CC_VERSION{0}; @@ -44,7 +55,7 @@ namespace llarp std::vector supported_protos; // In exit mode, we advertise our policy for accepted traffic and the corresponding ranges - std::optional exit_policy; + std::optional exit_policy; Signature signature; diff --git a/llarp/contact/relay_contact.cpp b/llarp/contact/relay_contact.cpp index b57c14d1b3..715924b57f 100644 --- a/llarp/contact/relay_contact.cpp +++ b/llarp/contact/relay_contact.cpp @@ -38,7 +38,7 @@ namespace llarp void RelayContact::bt_load(oxenc::bt_dict_consumer& btdc) { - if (int rc_ver = btdc.require(""); rc_ver != RC_VERSION) + if (int rc_ver = btdc.require(""); rc_ver != VERSION) throw std::runtime_error{"Invalid RC: do not know how to parse v{} RCs"_format(rc_ver)}; auto ipv4_port = btdc.require("4"); diff --git a/llarp/contact/relay_contact.hpp b/llarp/contact/relay_contact.hpp index 5e349ae5f1..314ab07445 100644 --- a/llarp/contact/relay_contact.hpp +++ b/llarp/contact/relay_contact.hpp @@ -23,27 +23,28 @@ namespace llarp { inline static constexpr size_t NETID_SIZE{8}; - /// On the wire we encode the data as a dict containing: - /// "" -- the RC format version, which must be == RelayContact::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 "testnet" for testnet). - /// "p" -- 32-byte router pubkey - /// "t" -- timestamp when this RC record was created (which also implicitly determines when it - /// goes stale and when it expires). - /// "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" - - /// RelayContact + /** RelayContact + On the wire we encode the data as a dict containing: + - "" : the RC format version, which must be == RelayContact::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 "testnet" for testnet). + - "p" : 32-byte router pubkey + - "t" : timestamp when this RC record was created (which also implicitly determines when it + goes stale and when it expires). + - "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" + + */ struct RelayContact { - static constexpr uint8_t RC_VERSION{0}; + static constexpr uint8_t VERSION{0}; /// Unit tests disable this to allow private IP ranges in RCs, which normally get rejected. inline static bool BLOCK_BOGONS{true}; @@ -110,7 +111,7 @@ namespace llarp virtual std::string to_string() const { return "RC:['4'={} | 'i'='{}' | 'p'={} | 't'={} | v={}]"_format( - _addr.to_string(), ACTIVE_NETID, _router_id, _timestamp.time_since_epoch().count(), RC_VERSION); + _addr.to_string(), ACTIVE_NETID, _router_id, _timestamp.time_since_epoch().count(), VERSION); } bool write(const fs::path& fname) const; diff --git a/llarp/contact/relay_contact_local.cpp b/llarp/contact/relay_contact_local.cpp index 8539f0c173..7686fd789c 100644 --- a/llarp/contact/relay_contact_local.cpp +++ b/llarp/contact/relay_contact_local.cpp @@ -47,7 +47,7 @@ namespace llarp void LocalRC::bt_encode(oxenc::bt_dict_producer& btdp) { - btdp.append("", RC_VERSION); + btdp.append("", VERSION); std::array buf; diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index b6ad8600af..dad9fb7aaf 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -57,14 +57,9 @@ namespace llarp::handlers { assert(not _is_snode_service); - if (not net_config._routed_ranges.empty()) - { - _routed_ranges.merge(net_config._routed_ranges); - _local_introset._routed_ranges = _routed_ranges; - } - _exit_policy = net_config.traffic_policy; _local_introset.exit_policy = _exit_policy; + _local_cc.exit_policy = _exit_policy; } if (not net_config.srv_records.empty()) diff --git a/llarp/handlers/session.hpp b/llarp/handlers/session.hpp index 9aecab5e03..1e7a292c16 100644 --- a/llarp/handlers/session.hpp +++ b/llarp/handlers/session.hpp @@ -64,7 +64,7 @@ namespace llarp std::set _routed_ranges; // formerly from LocalEndpoint // policies about traffic that we are willing to carry -- Exit mode only! - std::optional _exit_policy = std::nullopt; + std::optional _exit_policy = std::nullopt; public: SessionEndpoint(Router& r); diff --git a/llarp/handlers/tun.hpp b/llarp/handlers/tun.hpp index e64256bae5..43dfdd4200 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -58,7 +58,7 @@ namespace llarp::handlers std::shared_ptr _packet_router; - std::optional _traffic_policy = std::nullopt; + std::optional _traffic_policy = std::nullopt; /// a file to load / store the ephemeral address map to std::optional _persisting_addr_file = std::nullopt; @@ -128,7 +128,7 @@ namespace llarp::handlers bool has_if_addr() const { return true; } - std::optional get_traffic_policy() const { return _traffic_policy; } + std::optional get_traffic_policy() const { return _traffic_policy; } std::chrono::milliseconds get_path_alignment_timeout() const { return _path_alignment_timeout; } diff --git a/llarp/net/traffic_policy.cpp b/llarp/net/traffic_policy.cpp index c997b15e9f..cd84f89722 100644 --- a/llarp/net/traffic_policy.cpp +++ b/llarp/net/traffic_policy.cpp @@ -67,7 +67,7 @@ namespace llarp::net return pkt.header()->protocol == static_cast>(protocol); } - bool TrafficPolicy::allow_ip_traffic(const IPPacket& pkt) + bool ExitPolicy::allow_ip_traffic(const IPPacket& pkt) { if (protocols.empty() and ranges.empty()) return true; @@ -165,7 +165,7 @@ namespace llarp::net } } - void TrafficPolicy::bt_decode(oxenc::bt_dict_consumer&& btdc) + void ExitPolicy::bt_decode(oxenc::bt_dict_consumer&& btdc) { try { @@ -200,7 +200,7 @@ namespace llarp::net } } - void TrafficPolicy::bt_encode(oxenc::bt_dict_producer&& btdp) const + void ExitPolicy::bt_encode(oxenc::bt_dict_producer&& btdp) const { try { @@ -222,7 +222,7 @@ namespace llarp::net } } - bool TrafficPolicy::bt_decode(std::string_view buf) + bool ExitPolicy::bt_decode(std::string_view buf) { try { @@ -249,7 +249,7 @@ namespace llarp::net return status; } - nlohmann::json TrafficPolicy::ExtractStatus() const + nlohmann::json ExitPolicy::ExtractStatus() const { std::vector rangesStatus; std::transform(ranges.begin(), ranges.end(), std::back_inserter(rangesStatus), [](const auto& range) { diff --git a/llarp/net/traffic_policy.hpp b/llarp/net/traffic_policy.hpp index 4fd442481e..fd3bc15524 100644 --- a/llarp/net/traffic_policy.hpp +++ b/llarp/net/traffic_policy.hpp @@ -10,7 +10,6 @@ namespace llarp::net { // Copied over from llarp/net/ip_packet_old.hpp... - // TODO: do we fucking need this? enum class IPProtocol : uint8_t { ICMP = 0x01, @@ -57,8 +56,8 @@ namespace llarp::net explicit ProtocolInfo(std::string_view spec); }; - /// information about what traffic an endpoint will carry - struct TrafficPolicy + /// information about what exit traffic an endpoint will carry + struct ExitPolicy { /// ranges that are explicitly allowed std::set ranges; @@ -66,6 +65,8 @@ namespace llarp::net /// protocols that are explicity allowed std::set protocols; + bool empty() const { return ranges.empty() and protocols.empty(); } + void bt_encode(oxenc::bt_dict_producer&& btdp) const; void bt_decode(oxenc::bt_dict_consumer&& btdc); diff --git a/llarp/service/intro_set.hpp b/llarp/service/intro_set.hpp index 7d7dbacb6f..e875400804 100644 --- a/llarp/service/intro_set.hpp +++ b/llarp/service/intro_set.hpp @@ -37,12 +37,12 @@ namespace llarp::service 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 _routed_ranges; + std::set _routed_ranges; // TESTNET: TOFIX: Move into exit policy! /// 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 = std::nullopt; + std::optional exit_policy = std::nullopt; Signature signature; uint64_t version = llarp::constants::proto_version; From a5ccc9c262ea6cf5da4c214486ea8c139ed05621 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 10 Oct 2024 10:41:33 -0700 Subject: [PATCH 06/44] squash --- llarp/CMakeLists.txt | 4 +- llarp/config/config.cpp | 4 +- llarp/config/config.hpp | 2 +- llarp/contact/client_contact.cpp | 144 +++++++++++++++--- llarp/contact/client_contact.hpp | 112 +++++++++++--- llarp/contact/contactdb.cpp | 70 +++++++++ .../contacts.hpp => contact/contactdb.hpp} | 21 ++- llarp/contact/relay_contact.hpp | 15 +- llarp/crypto/crypto.cpp | 28 ++++ llarp/crypto/crypto.hpp | 2 + llarp/crypto/key_manager.cpp | 5 + llarp/crypto/key_manager.hpp | 10 ++ llarp/dht/bucket.hpp | 24 +-- llarp/dht/node.hpp | 19 ++- llarp/handlers/session.cpp | 101 +++++++----- llarp/handlers/session.hpp | 27 +++- llarp/link/contacts.cpp | 48 ------ llarp/link/link_manager.cpp | 61 ++++---- llarp/nodedb.cpp | 2 +- llarp/path/path.cpp | 6 +- llarp/path/path.hpp | 5 +- llarp/path/path_context.cpp | 20 +++ llarp/path/path_context.hpp | 3 + llarp/path/path_handler.cpp | 24 ++- llarp/path/path_handler.hpp | 4 +- llarp/router/router.cpp | 20 ++- llarp/router/router.hpp | 16 +- llarp/service/intro.hpp | 2 +- llarp/service/intro_set.cpp | 9 +- llarp/service/types.hpp | 24 +-- llarp/session/session.cpp | 2 +- 31 files changed, 588 insertions(+), 246 deletions(-) create mode 100644 llarp/contact/contactdb.cpp rename llarp/{link/contacts.hpp => contact/contactdb.hpp} (68%) delete mode 100644 llarp/link/contacts.cpp diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index a2ab9c43eb..f2a56e2734 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -62,7 +62,6 @@ lokinet_add_library(lokinet-rpc lokinet_add_library(lokinet-wire link/connection.cpp - link/contacts.cpp link/link_manager.cpp link/tunnel.cpp ) @@ -72,7 +71,6 @@ lokinet_add_library(lokinet-utils ${CMAKE_CURRENT_BINARY_DIR}/constants/version.cpp util/buffer.cpp util/file.cpp -# util/logging/buffer.cpp util/mem.cpp util/str.cpp util/thread/threading.cpp @@ -86,6 +84,8 @@ lokinet_add_library(lokinet-contact contact/client_contact.cpp contact/client_intro.cpp + contact/contactdb.cpp + contact/relay_contact.cpp contact/relay_contact_local.cpp contact/relay_contact_remote.cpp diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index 01a5e3afe1..e77a0d1bd2 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -521,7 +521,7 @@ namespace llarp ReachableDefault, assignment_acceptor(is_reachable), Comment{ - "Determines whether we will pubish our service's introset to the DHT.", + "Determines whether we will pubish our service's ClientContact to the DHT (client default: TRUE)", }); conf.define_option( @@ -884,7 +884,7 @@ namespace llarp if (not maybe_srv) throw std::invalid_argument{"Invalid SRV Record string: {}"_format(arg)}; - srv_records.push_back(std::move(*maybe_srv)); + srv_records.emplace(std::move(*maybe_srv)); }); conf.define_option( diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index 590a92387c..a55f491eb4 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -144,7 +144,7 @@ namespace llarp std::set auth_files; - std::vector srv_records; + std::unordered_set srv_records; std::optional path_alignment_timeout; diff --git a/llarp/contact/client_contact.cpp b/llarp/contact/client_contact.cpp index 99d09da670..a19df11e03 100644 --- a/llarp/contact/client_contact.cpp +++ b/llarp/contact/client_contact.cpp @@ -4,15 +4,64 @@ namespace llarp { static auto logcat = log::Cat("client-intro"); + ClientContact::ClientContact( + Ed25519Hash pk, + const std::unordered_set& srvs, + uint16_t proto_flags, + std::optional policy) + : derived_privatekey{std::move(pk)}, + SRVs{srvs.begin(), srvs.end()}, + protos{proto_flags}, + exit_policy{std::move(policy)} + {} + ClientContact::ClientContact(std::string_view buf) { bt_decode(buf); } - std::string ClientContact::bt_encode() const + ClientContact ClientContact::generate( + Ed25519Hash&& pk, + const std::unordered_set& srvs, + uint16_t proto_flags, + std::optional policy) + { + log::info(logcat, "Generating new ClientContact..."); + return ClientContact{std::move(pk), srvs, proto_flags, std::move(policy)}; + } + + void ClientContact::handle_updated_field(intro_set iset) + { + log::trace(logcat, "ClientContact storing updated ClientIntros..."); + if (iset.empty()) + throw std::invalid_argument{"Cannot publish ClientContact with no ClientIntros!"}; + intros = std::move(iset); + } + + void ClientContact::handle_updated_field(std::unordered_set srvs) + { + log::trace(logcat, "ClientContact storing updated SRVs..."); + SRVs = std::move(srvs); + } + + void ClientContact::handle_updated_field(uint16_t proto) + { + log::trace(logcat, "ClientContact storing new protocol types..."); + protos = proto; + } + + void ClientContact::_regenerate() + { + log::debug(logcat, "ClientContact regenerated with updated fields!"); + } + + void ClientContact::bt_encode(std::vector& buf) const { - oxenc::bt_dict_producer btdp; + bt_encode(oxenc::bt_dict_producer{reinterpret_cast(buf.data()), buf.size()}); + } + void ClientContact::bt_encode(oxenc::bt_dict_producer&& btdp) const + { btdp.append("a", pubkey.to_view()); if (exit_policy) @@ -25,12 +74,7 @@ namespace llarp i.bt_encode(sublist.append_dict()); } - if (not supported_protos.empty()) - { - auto sublist = btdp.append_list("p"); - for (auto& p : supported_protos) - sublist.append(static_cast(p)); - } + btdp.append("p", protos); if (not SRVs.empty()) { @@ -38,11 +82,9 @@ namespace llarp for (auto& s : SRVs) s.bt_encode(sublist.append_dict()); } - - return std::move(btdp).str(); } - bool ClientContact::bt_decode(std::string_view buf) + void ClientContact::bt_decode(std::string_view buf) { try { @@ -51,10 +93,8 @@ namespace llarp catch (const std::exception& e) { log::critical(logcat, "ClientContact deserialization failed: {}", e.what()); - return false; + throw; } - - return true; } void ClientContact::bt_decode(oxenc::bt_dict_consumer&& btdc) @@ -75,14 +115,7 @@ namespace llarp intros.emplace(sublist.consume_string_view()); } - // check, since we only add "p" if supported_protos is not empty (TESTNET: DISCUSS: an ALL type makes sense?) - if (btdc.skip_until("p")) - { - auto sublist = btdc.consume_list_consumer(); - - while (not sublist.is_finished()) - supported_protos.push_back(service::ProtocolType{sublist.consume_integer()}); - } + protos = btdc.require("p"); // ditto as above if (btdc.skip_until("s")) @@ -90,7 +123,7 @@ namespace llarp auto sublist = btdc.consume_list_consumer(); while (not sublist.is_finished()) - SRVs.emplace_back(sublist.consume_string_view()); + SRVs.emplace(sublist.consume_string_view()); } } @@ -99,4 +132,69 @@ namespace llarp // check the last intro to expire return intros.rbegin()->is_expired(now); } + + EncryptedClientContact ClientContact::encrypt_and_sign() + { + EncryptedClientContact enc{}; + + try + { + bt_encode(enc.encrypted); + + } + catch (const std::exception& e) + { + log::warning(logcat, "Exception encrypting and signing client contact: {}", e.what()); + } + + + return enc; + } + + EncryptedClientContact EncryptedClientContact::deserialize(std::string_view buf) + { + log::info(logcat, "Deserializing EncryptedClientContact..."); + return EncryptedClientContact{buf}; + } + + EncryptedClientContact::EncryptedClientContact(std::string_view buf) + { + bt_decode(oxenc::bt_dict_consumer{buf}); + } + + void EncryptedClientContact::bt_encode(oxenc::bt_dict_producer&& btdp) const + { + btdp.append("i", blinded_pubkey.to_view()); + btdp.append("n", nonce.to_view()); + btdp.append("t", signed_at.count()); + btdp.append("x", encrypted); + } + + /** EncryptedClientContact + "i" blinded local routerID + "n" nounce + "t" signing time + "x" encrypted payload + "~" signature + */ + void EncryptedClientContact::bt_decode(oxenc::bt_dict_consumer&& btdc) + { + try + { + blinded_pubkey.from_string(btdc.require("i")); + nonce.from_string(btdc.require("n")); + blinded_pubkey.from_string(btdc.require("i")); + encrypted = btdc.require>("x"); + } + catch (const std::exception& e) + { + log::critical(logcat, "EncryptedClientContact deserialization failed: {}", e.what()); + throw; + } + } + + bool EncryptedClientContact::is_expired(std::chrono::milliseconds now) const + { + return now >= signed_at + path::DEFAULT_LIFETIME; + } } // namespace llarp diff --git a/llarp/contact/client_contact.hpp b/llarp/contact/client_contact.hpp index 94c71fa5f8..e59ddaa65d 100644 --- a/llarp/contact/client_contact.hpp +++ b/llarp/contact/client_contact.hpp @@ -26,69 +26,147 @@ namespace llarp { struct EncryptedClientContact; - // TODO: add version to `` field to match RelayContact + namespace dht + { + struct CCNode; + } - /** ClientContact + namespace handlers + { + class SessionEndpoint; + } + enum protocol_flag : uint16_t + { + CONTROL = 1 << 0, + IPV4 = 1 << 1, + IPV6 = 1 << 2, + EXIT = 1 << 3, + AUTH = 1 << 4, + TCP2QUIC = 1 << 5, + }; + + /** ClientContact On the wire we encode the data as a dict containing: - "" : the CC format version, which must be == ClientContact::VERSION to be parsed successfully - "a" : public key of the remote client instance - "i" : list of client introductions corresponding to the different pivots through which paths can be built to the client instance - "p" : supported protocols indicating the traffic accepted by the client instance; this indicates if the - client is embedded and therefore requires a tunneled connection + client is embedded and therefore requires a tunneled connection. Serialized as a bitwise flag of + above protocol_flag enums - "s" : SRV records for lokinet DNS lookup */ struct ClientContact { - static constexpr uint8_t CC_VERSION{0}; + friend class handlers::SessionEndpoint; + inline static constexpr uint8_t CC_VERSION{0}; + inline static constexpr size_t MAX_CC_SIZE{4096}; + + protected: ClientContact() = default; ClientContact(std::string_view buf); + ClientContact( + Ed25519Hash pk, + const std::unordered_set& srvs, + uint16_t proto_flags, + std::optional policy = std::nullopt); + + static ClientContact generate( + Ed25519Hash&& pk, + const std::unordered_set& srvs, + uint16_t proto_flags, + std::optional policy = std::nullopt); + + EncryptedClientContact encrypt_and_sign(); + + template + void regenerate(intro_set iset, Opt&&... args) + { + handle_updated_field(std::forward(args)...); + regenerate(std::move(iset)); + } + + void regenerate(intro_set iset) + { + handle_updated_field(std::move(iset)); + _regenerate(); + } + + ~ClientContact() = default; + + Ed25519Hash derived_privatekey; + PubKey pubkey; intro_set intros; - std::vector SRVs; + std::unordered_set SRVs; std::chrono::milliseconds signed_at{0s}; - std::vector supported_protos; + uint16_t protos; // In exit mode, we advertise our policy for accepted traffic and the corresponding ranges std::optional exit_policy; - Signature signature; - bool is_expired(std::chrono::milliseconds now = llarp::time_now_ms()) const; - std::string bt_encode() const; + void bt_encode(std::vector& buf) const; - // Does not throw, returns true/false - bool bt_decode(std::string_view buf); + void bt_encode(oxenc::bt_dict_producer&& btdp) const; + + // Throws like a MF (for now) + void bt_decode(std::string_view buf); - protected: // Throws if unsuccessful, must take BTDC in invocation void bt_decode(oxenc::bt_dict_consumer&& btdc); + private: + void _regenerate(); + + void handle_updated_field(uint16_t p); + void handle_updated_field(intro_set iset); + void handle_updated_field(std::unordered_set srvs); + public: std::string to_string() const; static constexpr bool to_string_formattable = true; }; - /** - EncryptedClientContact + /** EncryptedClientContact "i" blinded local routerID "n" nounce "t" signing time - "x" same + "x" encrypted payload "~" signature - */ + */ struct EncryptedClientContact { + friend struct dht::CCNode; + friend struct ClientContact; + + protected: + EncryptedClientContact() : nonce{SymmNonce::make_random()}, encrypted(ClientContact::MAX_CC_SIZE) {} + + static EncryptedClientContact construct(); + + static EncryptedClientContact deserialize(std::string_view buf); + + // protected: + explicit EncryptedClientContact(std::string_view buf); + PubKey blinded_pubkey; SymmNonce nonce; std::chrono::milliseconds signed_at{0s}; - std::vector payload; + std::vector encrypted; Signature sig; + + void bt_encode(oxenc::bt_dict_producer&& btdp) const; + + void bt_decode(oxenc::bt_dict_consumer&& btdc); + + public: + bool is_expired(std::chrono::milliseconds now = time_now_ms()) const; }; } // namespace llarp diff --git a/llarp/contact/contactdb.cpp b/llarp/contact/contactdb.cpp new file mode 100644 index 0000000000..4d04945538 --- /dev/null +++ b/llarp/contact/contactdb.cpp @@ -0,0 +1,70 @@ +#include "contactdb.hpp" + +#include + +namespace llarp +{ + ContactDB::ContactDB(Router& r) : _router{r}, _local_key{dht::Key_t::derive_from_rid(r.local_rid())} + { + timer_keepalive = std::make_shared(0); + _introset_nodes = std::make_unique>(_local_key, llarp::randint); + } + + // std::optional ContactDB::get_decrypted_cc(RouterID remote) const + // { + // std::optional ret = std::nullopt; + + // (void)remote; + // // TESTNET: TODO: finish this after implementing CC encrypt/decrypt + + // return ret; + // } + + // std::optional ContactDB::get_encrypted_cc(const dht::Key_t& key) const + // { + // std::optional enc = std::nullopt; + + // auto& clientcontacts = _cc_nodes->nodes; + + // if (auto itr = clientcontacts.find(key); + // itr != clientcontacts.end() && not itr->second.client_contact.is_expired()) + // enc = itr->second.client_contact; + + // return enc; + // } + + std::optional ContactDB::get_decrypted_introset(RouterID remote) const + { + std::optional ret = std::nullopt; + + if (auto encrypted = get_encrypted_introset(dht::Key_t::derive_from_rid(remote)); + auto intro = encrypted->decrypt(remote)) + ret = *intro; + + return ret; + } + + std::optional ContactDB::get_encrypted_introset(const dht::Key_t& key) const + { + std::optional enc = std::nullopt; + + auto& introsets = _introset_nodes->nodes; + + if (auto itr = introsets.find(key); itr != introsets.end() && not itr->second.introset.is_expired()) + enc = itr->second.introset; + + return enc; + } + + nlohmann::json ContactDB::ExtractStatus() const + { + nlohmann::json obj{{"services", _introset_nodes->ExtractStatus()}, {"local_key", _local_key.ToHex()}}; + return obj; + } + + void ContactDB::put_intro(service::EncryptedIntroSet enc) + { + _introset_nodes->put_node(std::move(enc)); + } + +} // namespace llarp diff --git a/llarp/link/contacts.hpp b/llarp/contact/contactdb.hpp similarity index 68% rename from llarp/link/contacts.hpp rename to llarp/contact/contactdb.hpp index 40e6421dc5..aa0dcfc20a 100644 --- a/llarp/link/contacts.hpp +++ b/llarp/contact/contactdb.hpp @@ -7,13 +7,16 @@ 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 RelayContacts and introsets for example - struct Contacts + /** + ContactDB TODO: + - Store nearest-furthest expiry, trim + + */ + + /// This class mediates storage, retrieval, and functionality for ClientContacts + struct ContactDB { private: - // TODO: why was this a shared ptr in the original implementation? revisit this std::shared_ptr timer_keepalive; Router& _router; const dht::Key_t _local_key; @@ -21,8 +24,14 @@ namespace llarp // holds introsets for remote services std::unique_ptr> _introset_nodes; + // std::unique_ptr> _cc_nodes; + public: - explicit Contacts(Router& r); + explicit ContactDB(Router& r); + + // std::optional get_decrypted_cc(RouterID remote) const; + + // std::optional get_encrypted_cc(const dht::Key_t& key) const; std::optional get_decrypted_introset(RouterID remote) const; diff --git a/llarp/contact/relay_contact.hpp b/llarp/contact/relay_contact.hpp index 314ab07445..7cd317d867 100644 --- a/llarp/contact/relay_contact.hpp +++ b/llarp/contact/relay_contact.hpp @@ -40,11 +40,10 @@ 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" - */ struct RelayContact { - static constexpr uint8_t VERSION{0}; + inline static constexpr uint8_t VERSION{0}; /// Unit tests disable this to allow private IP ranges in RCs, which normally get rejected. inline static bool BLOCK_BOGONS{true}; @@ -55,15 +54,15 @@ namespace llarp /// How long (from its signing time) before an RC is considered "stale". Relays republish /// their RCs slightly more frequently than this so that ideally this won't happen. - static constexpr auto STALE_AGE{6h}; + inline static constexpr auto STALE_AGE{6h}; /// How long (from its signing time) before an RC becomes "outdated". Outdated records are /// used (e.g. for path building) only if there are no newer records available, such as /// might be the case when a client has been turned off for a while. - static constexpr auto OUTDATED_AGE{12h}; + inline static constexpr auto OUTDATED_AGE{12h}; /// How long before an RC becomes invalid (and thus deleted). - static constexpr auto LIFETIME{30 * 24h}; + inline static constexpr auto LIFETIME{30 * 24h}; ustring_view view() const { return _payload; } @@ -160,10 +159,6 @@ namespace llarp /// Extension of RelayContact used to store a local "RC," and inserts a RelayContact 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 final : public RelayContact { static LocalRC make(Ed25519SecretKey secret, oxen::quic::Address local); @@ -302,6 +297,6 @@ namespace std {}; template <> - struct hash final : public hash + struct hash : public hash {}; } // namespace std diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index a116bead63..483da479cb 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -413,6 +413,34 @@ namespace llarp return true; } + Ed25519Hash crypto::derive_private_subkey(const Ed25519SecretKey& root) + { + Ed25519Hash ret{}; + + AlignedBuffer<32> h; + + if (not make_scalar(h, root.to_pubkey(), 1)) + throw std::runtime_error{"Call to `make_scalar` failed in deriving private subkey!"}; + + h[0] &= 248; + h[31] &= 63; + h[31] |= 64; + + Ed25519Hash a = root.to_edhash(); + + // a' = ha + crypto_core_ed25519_scalar_mul(ret.data(), h.data(), a.data()); + + // s' = H(h || s) + std::array buf; + std::copy(h.begin(), h.end(), buf.begin()); + std::copy(a.signing_hash().begin(), a.signing_hash().end(), buf.begin() + 32); + if (crypto_generichash_blake2b(ret.signing_hash().data(), 32, buf.data(), buf.size(), nullptr, 0) == -1) + throw std::runtime_error{"Call to `crypto_generichash_blake2b` failed!"}; + + return ret; + } + void crypto::randomize(uint8_t* buf, size_t len) { randombytes(buf, len); diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index b8a825c393..1684e235ff 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -89,6 +89,8 @@ namespace llarp uint64_t key_n, const AlignedBuffer<32>* hash = nullptr); + Ed25519Hash derive_private_subkey(const Ed25519SecretKey& root); + /// randomize buffer void randomize(uint8_t* buf, size_t len); diff --git a/llarp/crypto/key_manager.cpp b/llarp/crypto/key_manager.cpp index 5655e51360..18ea13f292 100644 --- a/llarp/crypto/key_manager.cpp +++ b/llarp/crypto/key_manager.cpp @@ -73,4 +73,9 @@ namespace llarp public_key = seckey_to_pubkey(identity_key); log::info(logcat, "Relay key manager updated secret key; new public key: {}", public_key); } + + Ed25519Hash KeyManager::derive_subkey() const + { + return crypto::derive_private_subkey(identity_key); + } } // namespace llarp diff --git a/llarp/crypto/key_manager.hpp b/llarp/crypto/key_manager.hpp index 5bb7a6ac35..ab261150af 100644 --- a/llarp/crypto/key_manager.hpp +++ b/llarp/crypto/key_manager.hpp @@ -10,6 +10,11 @@ namespace llarp { struct Config; + namespace handlers + { + class SessionEndpoint; + } + // KeyManager manages the cryptographic keys stored on disk for the local // node. This includes private keys as well as the self-signed router contact // file (e.g. "self.signed"). @@ -23,6 +28,7 @@ namespace llarp struct KeyManager { friend struct Router; + friend class handlers::SessionEndpoint; private: KeyManager(const Config& config, bool is_relay); @@ -43,7 +49,11 @@ namespace llarp void update_idkey(Ed25519SecretKey&& newkey); + Ed25519Hash derive_subkey() const; + public: + // + const RouterID& router_id() const { return public_key; } }; diff --git a/llarp/dht/bucket.hpp b/llarp/dht/bucket.hpp index 133e86fad9..a4f53cd613 100644 --- a/llarp/dht/bucket.hpp +++ b/llarp/dht/bucket.hpp @@ -46,7 +46,7 @@ namespace llarp::dht } }; - bool GetRandomNodeExcluding(Key_t& result, const std::set& exclude) const + bool get_random_node_excluding(Key_t& result, const std::set& exclude) const { std::vector candidates; std::set_difference( @@ -65,7 +65,7 @@ namespace llarp::dht return true; } - bool FindClosest(const Key_t& target, Key_t& result) const + bool find_closest(const Key_t& target, Key_t& result) const { Key_t mindist; mindist.Fill(0xff); @@ -81,7 +81,7 @@ namespace llarp::dht return nodes.size() > 0; } - bool GetManyRandom(std::set& result, size_t N) const + bool get_n_random(std::set& result, size_t N) const { if (nodes.size() < N || nodes.empty()) { @@ -110,7 +110,7 @@ namespace llarp::dht return result.size() == expecting; } - bool FindCloseExcluding(const Key_t& target, Key_t& result, const std::set& exclude) const + bool get_nearest_excluding(const Key_t& target, Key_t& result, const std::set& exclude) const { Key_t maxdist; maxdist.Fill(0xff); @@ -133,7 +133,7 @@ namespace llarp::dht return mindist < maxdist; } - bool GetManyNearExcluding( + bool get_n_nearest_excluding( const Key_t& target, std::set& result, size_t N, const std::set& exclude) const { std::set s(exclude.begin(), exclude.end()); @@ -141,7 +141,7 @@ namespace llarp::dht Key_t peer; while (N--) { - if (!FindCloseExcluding(target, peer, s)) + if (!get_nearest_excluding(target, peer, s)) { return false; } @@ -151,7 +151,7 @@ namespace llarp::dht return true; } - void PutNode(const Val_t& val) + void put_node(const Val_t& val) { auto itr = nodes.find(val.ID); if (itr == nodes.end() || itr->second < val) @@ -160,7 +160,7 @@ namespace llarp::dht } } - void DelNode(const Key_t& key) + void delete_node(const Key_t& key) { auto itr = nodes.find(key); if (itr != nodes.end()) @@ -169,11 +169,11 @@ namespace llarp::dht } } - bool HasNode(const Key_t& key) const { return nodes.find(key) != nodes.end(); } + bool has_node(const Key_t& key) const { return nodes.find(key) != nodes.end(); } // remove all nodes who's key matches a predicate template - void RemoveIf(Predicate pred) + void delete_node_if(Predicate pred) { auto itr = nodes.begin(); while (itr != nodes.end()) @@ -186,7 +186,7 @@ namespace llarp::dht } template - void ForEachNode(Visit_t visit) + void for_each_node(Visit_t visit) { for (const auto& item : nodes) { @@ -194,7 +194,7 @@ namespace llarp::dht } } - void Clear() { nodes.clear(); } + void clear() { nodes.clear(); } BucketStorage_t nodes; Random_t random; diff --git a/llarp/dht/node.hpp b/llarp/dht/node.hpp index 6f85a6b317..265dd9502e 100644 --- a/llarp/dht/node.hpp +++ b/llarp/dht/node.hpp @@ -2,6 +2,7 @@ #include "key.hpp" +#include #include #include @@ -23,18 +24,26 @@ namespace llarp::dht bool operator<(const RCNode& other) const { return rc.timestamp() < other.rc.timestamp(); } }; + struct CCNode + { + EncryptedClientContact client_contact; + Key_t ID; + + CCNode() { ID.zero(); } + + CCNode(EncryptedClientContact other) : client_contact{std::move(other)}, ID{client_contact.blinded_pubkey} {} + + bool operator<(const CCNode& other) const { return client_contact.signed_at < other.client_contact.signed_at; } + }; + struct ISNode { service::EncryptedIntroSet introset; - Key_t ID; ISNode() { ID.zero(); } - ISNode(service::EncryptedIntroSet other) : introset(std::move(other)) - { - ID = Key_t(introset.derived_signing_key.as_array()); - } + ISNode(service::EncryptedIntroSet other) : introset(std::move(other)), ID{introset.derived_signing_key} {} nlohmann::json ExtractStatus() const { return introset.ExtractStatus(); } diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index dad9fb7aaf..2c167edc3a 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -1,6 +1,6 @@ #include "session.hpp" -#include +#include #include #include #include @@ -47,9 +47,6 @@ namespace llarp::handlers { auto net_config = _router.config()->network; - if (net_config.is_reachable) - should_publish_introset = true; - _is_exit_node = _router.is_exit_node(); _is_snode_service = _router.is_service_node(); @@ -58,12 +55,12 @@ namespace llarp::handlers assert(not _is_snode_service); _exit_policy = net_config.traffic_policy; - _local_introset.exit_policy = _exit_policy; - _local_cc.exit_policy = _exit_policy; + // _local_cc.exit_policy = _exit_policy; // TESTNET: } - if (not net_config.srv_records.empty()) - _local_introset.SRVs = std::move(net_config.srv_records); + if (not net_config.srv_records.empty()) // TESTNET: + _srv_records.merge(net_config.srv_records); + // _local_cc.SRVs = std::move(net_config.srv_records); if (use_tokens = not net_config.auth_static_tokens.empty(); use_tokens) _static_auth_tokens.merge(net_config.auth_static_tokens); @@ -88,6 +85,23 @@ namespace llarp::handlers { _auth_tokens.merge(net_config.exit_auths); } + + uint16_t protoflags = protocol_flag::TCP2QUIC; + + if (_router.using_tun_if()) + protoflags |= _is_v4 ? protocol_flag::IPV4 : protocol_flag::IPV6; + + if (_is_exit_node) + protoflags |= protocol_flag::EXIT; + + client_contact = + ClientContact::generate(_router.key_manager()->derive_subkey(), _srv_records, protoflags, _exit_policy); + + should_publish_cc = net_config.is_reachable; + + if (should_publish_cc) + { + } } void SessionEndpoint::build_more(size_t n) @@ -109,16 +123,25 @@ namespace llarp::handlers void SessionEndpoint::srv_records_changed() { - // TODO: Investigate the usage or the term exit RE: service nodes acting as exits - // ^^ lol - _local_introset.SRVs.clear(); + log::debug(logcat, "{} called", __PRETTY_FUNCTION__); + update_and_publish_localcc(get_current_client_intros(), _srv_records); + } - for (const auto& srv : srv_records()) + void SessionEndpoint::start_tickers() + { + if (should_publish_cc) { - _local_introset.SRVs.emplace_back(srv); + log::debug(logcat, "Starting ClientContact publish ticker..."); + _cc_publisher = _router.loop()->call_every( + path::DEFAULT_LIFETIME, + [this]() { + log::info(logcat, "Updating and publishing ClientContact..."); + update_and_publish_localcc(get_current_client_intros()); + }, + true); } - - regen_and_publish_introset(); + else + log::debug(logcat, "SessionEndpoint configured to NOT publish ClientContact..."); } void SessionEndpoint::resolve_ons_mappings() @@ -228,7 +251,7 @@ namespace llarp::handlers void SessionEndpoint::lookup_intro( RouterID remote, bool is_relayed, uint64_t order, std::function)> func) { - if (auto maybe_intro = _router.contacts().get_decrypted_introset(remote)) + if (auto maybe_intro = _router.contact_db().get_decrypted_introset(remote)) { log::debug(logcat, "Decrypted introset for remote (rid:{}) found locally~", remote); return func(std::move(maybe_intro)); @@ -237,12 +260,12 @@ namespace llarp::handlers log::debug(logcat, "Looking up introset for remote (rid:{})", remote); auto remote_key = dht::Key_t::derive_from_rid(remote); - auto response_handler = [this, remote, hook = std::move(func)](std::string response) { + auto response_handler = [this, remote, hook = std::move(func)](std::string response) mutable { if (auto encrypted = service::EncryptedIntroSet::construct(response); auto intro = encrypted->decrypt(remote)) { log::debug(logcat, "Storing introset for remote (rid:{})", remote); - _router.contacts().put_intro(std::move(*encrypted)); + _router.contact_db().put_intro(std::move(*encrypted)); return hook(std::move(intro)); } @@ -277,6 +300,29 @@ namespace llarp::handlers } } + void SessionEndpoint::_localcc_update_fail() + { + log::warning( + logcat, + "Failed to query enough client introductions from current paths! Building more paths to publish " + "introset"); + return build_more(1); + } + + void SessionEndpoint::update_and_publish_localcc(intro_set intros) + { + if (intros.empty()) + return _localcc_update_fail(); + client_contact.regenerate(std::move(intros)); + _update_and_publish_localcc(); + } + + void SessionEndpoint::_update_and_publish_localcc() + { + // TESTNET: TODO: encrypt and sign + + } + /** Introset publishing: - When a local service or exit node publishes an introset, it is also sent along the path currently used for that session @@ -285,21 +331,6 @@ namespace llarp::handlers void SessionEndpoint::regen_and_publish_introset() { const auto now = llarp::time_now_ms(); - _last_introset_regen_attempt = now; - - // service::IntroductionSet path_intros; - - // if (auto maybe_intros = get_path_intros_conditional([now](const service::Introduction& intro) -> bool { - // return not intro.expires_soon(path::INTRO_STALE_THRESHOLD, now); - // })) - // { - // path_intros.merge(*maybe_intros); - // } - // else - // { - // log::warning(logcat, "Failed to get enough valid path introductions to publish introset!"); - // return build_more(1); - // } service::intro_que_old _path_intros = get_recent_path_intros(); @@ -314,11 +345,11 @@ namespace llarp::handlers if (_router.using_tun_if()) { - intro_protos.push_back(_is_v4 ? service::ProtocolType::TrafficV4 : service::ProtocolType::TrafficV6); + intro_protos.push_back(_is_v4 ? service::ProtocolType::IPV4 : service::ProtocolType::IPV6); if (_is_exit_node) { - intro_protos.push_back(service::ProtocolType::Exit); + intro_protos.push_back(service::ProtocolType::EXIT); _local_introset.exit_policy = _exit_policy; _local_introset._routed_ranges = _routed_ranges; } diff --git a/llarp/handlers/session.hpp b/llarp/handlers/session.hpp index 1e7a292c16..c0395e9cd8 100644 --- a/llarp/handlers/session.hpp +++ b/llarp/handlers/session.hpp @@ -22,7 +22,7 @@ namespace llarp std::unordered_set _srv_records; - bool should_publish_introset{true}; + bool should_publish_cc{false}; session_map _sessions; @@ -32,12 +32,12 @@ namespace llarp // - Directly pre-loaded from config address_map _range_map; - ClientContact _local_cc; // TODO: TESTNET: replacement for service::Introset + ClientContact client_contact; // TODO: TESTNET: replacement for service::Introset service::Identity _identity; // TODO: TESTNET: move responsibilities to KeyManager, delete service::IntroSetOld _local_introset; // TODO: TESTNET: remove with CC impl - std::chrono::milliseconds _last_introset_regen_attempt{0s}; + std::shared_ptr _cc_publisher; // auth tokens for making outbound sessions std::unordered_map _auth_tokens; @@ -87,8 +87,6 @@ namespace llarp oxen::quic::Address local_address() const { return _local_addr; } - const service::IntroSetOld& intro_set() const { return _local_introset; } - // get copy of all srv records std::set srv_records() const { return {_srv_records.begin(), _srv_records.end()}; } @@ -106,6 +104,21 @@ namespace llarp void srv_records_changed(); + // This function can be called with the fields to be updated. ClientIntros are always passed, so there + // is no need to pass them to this function + template + void update_and_publish_localcc(intro_set intros, Opt&&... args) + { + if (intros.empty()) + return _localcc_update_fail(); + client_contact.regenerate(std::move(intros), std::forward(args)...); + _update_and_publish_localcc(); + } + + void update_and_publish_localcc(intro_set intros); + + void start_tickers(); + void regen_and_publish_introset(); bool publish_introset(const service::EncryptedIntroSet& introset); @@ -160,6 +173,10 @@ namespace llarp void unmap_range_by_name(const std::string& name); private: + void _localcc_update_fail(); + + void _update_and_publish_localcc(); + bool _initiate_session(NetworkAddress remote, on_session_init_hook cb, bool is_exit = false); void _make_session_path( diff --git a/llarp/link/contacts.cpp b/llarp/link/contacts.cpp deleted file mode 100644 index 68cd3914da..0000000000 --- a/llarp/link/contacts.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "contacts.hpp" - -#include -#include - -namespace llarp -{ - Contacts::Contacts(Router& r) : _router{r}, _local_key{dht::Key_t::derive_from_rid(r.local_rid())} - { - timer_keepalive = std::make_shared(0); - _introset_nodes = std::make_unique>(_local_key, llarp::randint); - } - - std::optional Contacts::get_decrypted_introset(RouterID remote) const - { - std::optional ret = std::nullopt; - - if (auto encrypted = get_encrypted_introset(dht::Key_t::derive_from_rid(remote)); - auto intro = encrypted->decrypt(remote)) - ret = *intro; - - return ret; - } - - std::optional Contacts::get_encrypted_introset(const dht::Key_t& key) const - { - std::optional enc = std::nullopt; - - auto& introsets = _introset_nodes->nodes; - - if (auto itr = introsets.find(key); itr != introsets.end() && not itr->second.introset.is_expired()) - enc = itr->second.introset; - - return enc; - } - - nlohmann::json Contacts::ExtractStatus() const - { - nlohmann::json obj{{"services", _introset_nodes->ExtractStatus()}, {"local_key", _local_key.ToHex()}}; - return obj; - } - - void Contacts::put_intro(service::EncryptedIntroSet enc) - { - _introset_nodes->PutNode(std::move(enc)); - } - -} // namespace llarp diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index a433d47be5..f5f52345f4 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1,8 +1,8 @@ #include "link_manager.hpp" #include "connection.hpp" -#include "contacts.hpp" +#include #include #include #include @@ -261,9 +261,9 @@ namespace llarp _router._gossip_interval, [this]() { log::critical(logcat, "Regenerating and gossiping RC..."); - _router.router_contact.resign(); + _router.relay_contact.resign(); _router.save_rc(); - gossip_rc(_router.local_rid(), _router.router_contact.to_remote()); + gossip_rc(_router.local_rid(), _router.relay_contact.to_remote()); }, true); } @@ -1191,7 +1191,7 @@ namespace llarp "Received PublishIntroMessage in which we are peer index {}.. storing introset", relay_order); - _router.contacts().put_intro(std::move(enc)); + _router.contact_db().put_intro(std::move(enc)); respond(messages::OK_RESPONSE); } else @@ -1228,7 +1228,7 @@ namespace llarp { log::info(logcat, "Received PublishIntroMessage for {}; we are candidate {}", addr, relay_order); - _router.contacts().put_intro(std::move(enc)); + _router.contact_db().put_intro(std::move(enc)); respond(messages::OK_RESPONSE); } else @@ -1355,7 +1355,7 @@ namespace llarp } else { - if (auto maybe_intro = _router.contacts().get_encrypted_introset(addr)) + if (auto maybe_intro = _router.contact_db().get_encrypted_introset(addr)) respond(serialize_response({{"INTROSET", maybe_intro->bt_encode()}})); else { @@ -1365,6 +1365,7 @@ namespace llarp } } + // TONUKE: void LinkManager::handle_find_intro_response(oxen::quic::message m) { if (m.timed_out) @@ -1373,32 +1374,32 @@ namespace llarp return; } - std::string payload; + // std::string payload; - try - { - oxenc::bt_dict_consumer btdc{m.body()}; - payload = btdc.require((m) ? "INTROSET" : messages::STATUS_KEY); - } - catch (const std::exception& e) - { - log::warning(logcat, "Exception: {}", e.what()); - return; - } + // try + // { + // oxenc::bt_dict_consumer btdc{m.body()}; + // payload = btdc.require((m) ? "INTROSET" : messages::STATUS_KEY); + // } + // catch (const std::exception& e) + // { + // log::warning(logcat, "Exception: {}", e.what()); + // return; + // } - // success case, neither timed out nor errored - if (m) - { - if (auto enc = service::EncryptedIntroSet::construct(payload)) - { - _router.contacts().put_intro(std::move(*enc)); - } - } - else - { - log::info(logcat, "FindIntroMessage failed with error: {}", payload); - // Do something smart here probably - } + // // success case, neither timed out nor errored + // if (m) + // { + // if (auto enc = service::EncryptedIntroSet::construct(payload)) + // { + // _router.contact_db().put_intro(std::move(*enc)); + // } + // } + // else + // { + // log::info(logcat, "FindIntroMessage failed with error: {}", payload); + // // Do something smart here probably + // } } void LinkManager::handle_path_build(oxen::quic::message m, const RouterID& from) diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index 788b59ea54..b262c590e6 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -725,7 +725,7 @@ namespace llarp _router.link_manager()->fetch_bootstrap_rcs( rc, BootstrapFetchMessage::serialize( - _is_service_node ? std::make_optional(_router.router_contact) : std::nullopt, num_needed), + _is_service_node ? std::make_optional(_router.relay_contact) : std::nullopt, num_needed), [this, src = source](oxen::quic::message m) mutable { log::info(logcat, "Received response to BootstrapRC fetch request..."); diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 776e9c59c5..e1aace4c87 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -43,8 +43,8 @@ namespace llarp::path } // initialize parts of the introduction - intro.pivot_router = hops[hsz - 1].rc.router_id(); - intro.pivot_hop_id = hops[hsz - 1].txID; + intro_old.pivot_router = hops[hsz - 1].rc.router_id(); + intro_old.pivot_hop_id = hops[hsz - 1].txID; } void Path::link_session(recv_session_dgram_cb cb) @@ -332,7 +332,7 @@ namespace llarp::path auto now = llarp::time_now_ms(); nlohmann::json obj{ - {"intro", intro.ExtractStatus()}, + {"intro", intro_old.ExtractStatus()}, {"lastRecvMsg", to_json(last_recv_msg)}, {"lastLatencyTest", to_json(last_latency_test)}, {"buildStarted", to_json(buildStarted)}, diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index f2b7ee84e5..a940c05092 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -3,6 +3,7 @@ #include "path_handler.hpp" #include +#include #include #include #include @@ -43,7 +44,9 @@ namespace llarp std::weak_ptr handler; - service::Introduction intro; + service::Introduction intro_old; + + ClientIntro intro; std::chrono::milliseconds buildStarted = 0s; diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index 78dbf67680..c8e882bbc2 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -48,6 +48,8 @@ namespace llarp::path void PathContext::drop_paths(std::vector> droplist) { + Lock_t l{paths_mutex}; + for (auto itr = droplist.begin(); itr != droplist.end();) { drop_path(*itr); @@ -55,8 +57,26 @@ namespace llarp::path } } + intro_set PathContext::get_recent_ccs() const + { + Lock_t l{paths_mutex}; + + intro_set intros; + auto now = llarp::time_now_ms(); + + for (auto& [_, p] : _path_map) + { + if (p->is_ready() and not p->intro.is_expired(now)) + intros.emplace(p->intro); + } + + return intros; + } + void PathContext::drop_path(const std::shared_ptr& path) { + Lock_t l{paths_mutex}; + if (auto itr = _path_map.find(path->upstream_rxid()); itr != _path_map.end()) _path_map.erase(itr); diff --git a/llarp/path/path_context.hpp b/llarp/path/path_context.hpp index 43be06a690..fc54a36bf9 100644 --- a/llarp/path/path_context.hpp +++ b/llarp/path/path_context.hpp @@ -4,6 +4,7 @@ #include "path_types.hpp" #include "transit_hop.hpp" +#include #include #include #include @@ -46,6 +47,8 @@ namespace llarp::path void drop_paths(std::vector> droplist); + intro_set get_recent_ccs() const; + private: const RouterID _local_rid; diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index 6c19b0b5f7..bfe31c09ea 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -251,6 +251,22 @@ namespace llarp::path } } + intro_set PathHandler::get_current_client_intros() const + { + Lock_t lock{paths_mutex}; + + intro_set intros{}; + auto now = llarp::time_now_ms(); + + for (const auto& [_, p] : _paths) + { + if (p->is_ready() and not p->intro.is_expired(now)) + intros.emplace(p->intro); + } + + return intros; + } + service::intro_que_old PathHandler::get_recent_path_intros(std::chrono::milliseconds stale_threshold) const { Lock_t l{paths_mutex}; @@ -258,8 +274,8 @@ namespace llarp::path for (const auto& [_, p] : _paths) { - if (p->is_ready() and not p->intro.expires_soon(stale_threshold)) - ret.push(p->intro); + if (p->is_ready() and not p->intro_old.expires_soon(stale_threshold)) + ret.push(p->intro_old); } return ret; @@ -273,9 +289,9 @@ namespace llarp::path for (const auto& p : _paths) { - if (p.second->is_ready() and filter(p.second->intro)) + if (p.second->is_ready() and filter(p.second->intro_old)) { - intros.insert(p.second->intro); + intros.insert(p.second->intro_old); } } diff --git a/llarp/path/path_handler.hpp b/llarp/path/path_handler.hpp index a4ae7095dd..4e953980a7 100644 --- a/llarp/path/path_handler.hpp +++ b/llarp/path/path_handler.hpp @@ -3,7 +3,7 @@ #include "path_types.hpp" #include -#include +#include #include #include #include @@ -159,6 +159,8 @@ namespace llarp std::optional> get_path(const RouterID& router) const; + intro_set get_current_client_intros() const; + service::intro_que_old get_recent_path_intros( std::chrono::milliseconds stale_threshold = path::INTRO_STALE_THRESHOLD) const; diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 618d3e1ea9..b4696c71d7 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -2,9 +2,8 @@ #include #include +#include #include -#include -#include #include #include #include @@ -219,16 +218,15 @@ namespace llarp } else { + _session_endpoint->start_tickers(); // Resolve needed ONS values now that we have the necessary things prefigured _session_endpoint->resolve_ons_mappings(); } } - bool Router::fully_meshed() const + bool Router::is_fully_meshed() const { - if (auto n_conns = num_router_connections(); n_conns) - return n_conns >= _node_db->num_rcs(); - return false; + return num_router_connections() >= _node_db->num_rcs(); } void Router::persist_connection_until(const RouterID& remote, std::chrono::milliseconds until) @@ -660,7 +658,7 @@ namespace llarp if (not ensure_identity()) throw std::runtime_error{"EnsureIdentity() failed"}; - router_contact = + relay_contact = LocalRC::make(identity(), _is_service_node and _public_address ? *_public_address : _listen_address); _path_context = std::make_shared(local_rid()); @@ -752,7 +750,7 @@ namespace llarp { // _node_db->put_rc(router_contact.view()); log::info(logcat, "Saving RC file to {}", our_rc_file); - queue_disk_io([&]() { router_contact.write(our_rc_file); }); + queue_disk_io([&]() { relay_contact.write(our_rc_file); }); } bool Router::is_bootstrap_node(const RouterID r) const @@ -780,7 +778,7 @@ namespace llarp log::critical(logcat, "Local {}: {}", is_service_node() ? "Service Node" : "Client", _stats_line()); - if (is_service_node() and fully_meshed()) + if (is_service_node() and is_fully_meshed()) { log::critical(logcat, "SERVICE NODE IS FULLY MESHED"); } @@ -964,7 +962,7 @@ namespace llarp if (is_service_node()) { - if (not router_contact.is_public_addressable()) + if (not relay_contact.is_public_addressable()) { log::error(logcat, "Router is configured as relay but has no reachable addresses!"); return false; @@ -987,7 +985,7 @@ namespace llarp } // This must be constructed AFTER router creates its LocalRC - _contacts = std::make_unique(*this); + _contact_db = std::make_unique(*this); log::debug(logcat, "Creating Router::Tick() repeating event..."); _loop_ticker = _loop->call_every( diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 0f174065d3..468f431e23 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -69,7 +69,7 @@ namespace llarp inline constexpr auto SERVICE_MANAGER_REPORT_INTERVAL{5s}; - struct Contacts; + struct ContactDB; struct Router : std::enable_shared_from_this { @@ -95,7 +95,7 @@ namespace llarp bool use_file_logging{false}; // our router contact - LocalRC router_contact; + LocalRC relay_contact; std::shared_ptr _lmq; path::BuildLimiter _pathbuild_limiter; @@ -132,7 +132,7 @@ namespace llarp std::shared_ptr _vpn; std::shared_ptr _path_context; - std::shared_ptr _contacts; + std::shared_ptr _contact_db; std::shared_ptr _node_db; std::shared_ptr _loop_ticker; @@ -201,7 +201,7 @@ namespace llarp public: void start(); - bool fully_meshed() const; + bool is_fully_meshed() const; bool using_tun_if() const { return _using_tun; } @@ -221,9 +221,9 @@ namespace llarp const std::shared_ptr& quic_tunnel() const { return _quic_tun; } - const Contacts& contacts() const { return *_contacts; } + const ContactDB& contacts() const { return *_contact_db; } - Contacts& contacts() { return *_contacts; } + ContactDB& contact_db() { return *_contact_db; } std::shared_ptr config() const { return _config; } @@ -241,7 +241,7 @@ namespace llarp const RouterID& router_id() const { return _key_manager->public_key; } - const RouterID& local_rid() const { return router_contact.router_id(); } + const RouterID& local_rid() const { return relay_contact.router_id(); } Profiling& router_profiling() { return _router_profiling; } @@ -255,7 +255,7 @@ namespace llarp const std::shared_ptr& path_context() const { return _path_context; } - const LocalRC& rc() const { return router_contact; } + const LocalRC& rc() const { return relay_contact; } oxen::quic::Address listen_addr() const; diff --git a/llarp/service/intro.hpp b/llarp/service/intro.hpp index e65dd65d13..b3c1c11eab 100644 --- a/llarp/service/intro.hpp +++ b/llarp/service/intro.hpp @@ -22,7 +22,7 @@ namespace llarp::service nlohmann::json ExtractStatus() const; - bool is_expired(std::chrono::milliseconds now) const { return now >= expiry; } + bool is_expired(std::chrono::milliseconds now = llarp::time_now_ms()) const { return now >= expiry; } // TODO: get rid of this entirely, and use ::is_expired(...) bool expires_soon( diff --git a/llarp/service/intro_set.cpp b/llarp/service/intro_set.cpp index beb6970a36..f7e61a53e8 100644 --- a/llarp/service/intro_set.cpp +++ b/llarp/service/intro_set.cpp @@ -112,13 +112,8 @@ namespace llarp::service std::string EncryptedIntroSet::to_string() const { - return fmt::format( - "[EncIntroSet d={} n={} s={} x=[{} bytes] z={}]", - derived_signing_key, - nonce, - signed_at.count(), - introset_payload.size(), - sig); + return "[EncIntroSet d={} n={} s={} x=[{} bytes] z={}]"_format( + derived_signing_key, nonce, signed_at.count(), introset_payload.size(), sig); } std::optional EncryptedIntroSet::decrypt(const PubKey& root) const diff --git a/llarp/service/types.hpp b/llarp/service/types.hpp index 92b71ebd05..6d025a9c40 100644 --- a/llarp/service/types.hpp +++ b/llarp/service/types.hpp @@ -38,23 +38,23 @@ namespace llarp // used when sending over the wire. enum class ProtocolType : uint64_t { - Control = 0UL, - TrafficV4 = 1UL, - TrafficV6 = 2UL, - Exit = 3UL, - Auth = 4UL, + CONTROL = 0UL, + IPV4 = 1UL, + IPV6 = 2UL, + EXIT = 3UL, + AUTH = 4UL, TCP2QUIC = 5UL, }; inline constexpr std::string_view to_string(ProtocolType t) { - return t == ProtocolType::Control ? "Control"sv - : t == ProtocolType::TrafficV4 ? "TrafficV4"sv - : t == ProtocolType::TrafficV6 ? "TrafficV6"sv - : t == ProtocolType::Exit ? "Exit"sv - : t == ProtocolType::Auth ? "Auth"sv - : t == ProtocolType::TCP2QUIC ? "TCP->QUIC"sv - : "(unknown-protocol-type)"sv; + return t == ProtocolType::CONTROL ? "Control"sv + : t == ProtocolType::IPV4 ? "TrafficV4"sv + : t == ProtocolType::IPV6 ? "TrafficV6"sv + : t == ProtocolType::EXIT ? "Exit"sv + : t == ProtocolType::AUTH ? "Auth"sv + : t == ProtocolType::TCP2QUIC ? "TCP->QUIC"sv + : "(unknown-protocol-type)"sv; } // namespace util diff --git a/llarp/session/session.cpp b/llarp/session/session.cpp index 1b3943e3e4..457f047956 100644 --- a/llarp/session/session.cpp +++ b/llarp/session/session.cpp @@ -56,7 +56,7 @@ namespace llarp::session _current_path = std::move(_new_path); - _current_hop_id = _current_path->intro.pivot_hop_id; + _current_hop_id = _current_path->intro_old.pivot_hop_id; if (_use_tun) _current_path->link_session([this](bstring data) { From da157f52c310e24e5904215a38fbf1387c966646 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Mon, 14 Oct 2024 07:53:21 -0700 Subject: [PATCH 07/44] oxenc vbump -> dr7ana/chartype-fix for const_spans From 827ff5bc9a5a4d59a5d385e566eb2f0d43a5e733 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Mon, 21 Oct 2024 07:08:37 -0700 Subject: [PATCH 08/44] clientcontact logic (squash) - unorganized amalgamation of cc logic - session-related logic still local --- llarp/address/address.hpp | 1 - llarp/contact/client_contact.cpp | 96 ++++++++---- llarp/contact/client_contact.hpp | 61 +++++--- llarp/contact/contactdb.cpp | 37 +++-- llarp/contact/contactdb.hpp | 9 +- llarp/contact/relay_contact.cpp | 6 +- llarp/contact/relay_contact_local.cpp | 4 - llarp/contact/relay_contact_remote.cpp | 4 - llarp/contact/router_contact.cpp | 194 ------------------------ llarp/contact/router_contact_local.cpp | 97 ------------ llarp/contact/router_contact_remote.cpp | 59 ------- llarp/crypto/crypto.cpp | 54 ++----- llarp/crypto/crypto.hpp | 11 +- llarp/crypto/key_manager.cpp | 15 +- llarp/crypto/key_manager.hpp | 5 +- llarp/crypto/types.cpp | 38 ++++- llarp/crypto/types.hpp | 41 ++--- llarp/handlers/session.cpp | 107 +++++++++++-- llarp/handlers/session.hpp | 9 ++ llarp/link/link_manager.cpp | 190 ++++++++++++++++++----- llarp/link/link_manager.hpp | 6 +- llarp/messages/dht.hpp | 103 +++++++++++++ llarp/path/path.cpp | 16 ++ llarp/path/path.hpp | 15 +- llarp/service/identity.hpp | 2 +- llarp/service/intro_set.cpp | 16 +- llarp/service/intro_set.hpp | 6 +- llarp/util/buffer.hpp | 10 +- 28 files changed, 628 insertions(+), 584 deletions(-) delete mode 100644 llarp/contact/router_contact.cpp delete mode 100644 llarp/contact/router_contact_local.cpp delete mode 100644 llarp/contact/router_contact_remote.cpp diff --git a/llarp/address/address.hpp b/llarp/address/address.hpp index 92e12194d1..465ad8b05c 100644 --- a/llarp/address/address.hpp +++ b/llarp/address/address.hpp @@ -80,7 +80,6 @@ namespace llarp std::string name() const { return _pubkey.to_string(); } std::string to_string() const { return name().append(_tld); } - static constexpr bool to_string_formattable{true}; }; diff --git a/llarp/contact/client_contact.cpp b/llarp/contact/client_contact.cpp index a19df11e03..d7ca939258 100644 --- a/llarp/contact/client_contact.cpp +++ b/llarp/contact/client_contact.cpp @@ -5,29 +5,32 @@ namespace llarp static auto logcat = log::Cat("client-intro"); ClientContact::ClientContact( - Ed25519Hash pk, + Ed25519PrivateData private_data, + PubKey pk, const std::unordered_set& srvs, uint16_t proto_flags, std::optional policy) - : derived_privatekey{std::move(pk)}, + : derived_privatekey{std::move(private_data)}, + pubkey{std::move(pk)}, SRVs{srvs.begin(), srvs.end()}, protos{proto_flags}, exit_policy{std::move(policy)} {} - ClientContact::ClientContact(std::string_view buf) + ClientContact::ClientContact(std::string&& buf) { - bt_decode(buf); + bt_decode(oxenc::bt_dict_consumer{std::move(buf)}); } ClientContact ClientContact::generate( - Ed25519Hash&& pk, + Ed25519PrivateData&& private_data, + PubKey&& pk, const std::unordered_set& srvs, uint16_t proto_flags, std::optional policy) { log::info(logcat, "Generating new ClientContact..."); - return ClientContact{std::move(pk), srvs, proto_flags, std::move(policy)}; + return ClientContact{std::move(private_data), std::move(pk), srvs, proto_flags, std::move(policy)}; } void ClientContact::handle_updated_field(intro_set iset) @@ -57,10 +60,10 @@ namespace llarp void ClientContact::bt_encode(std::vector& buf) const { - bt_encode(oxenc::bt_dict_producer{reinterpret_cast(buf.data()), buf.size()}); + buf.resize(bt_encode(oxenc::bt_dict_producer{reinterpret_cast(buf.data()), buf.size()})); } - void ClientContact::bt_encode(oxenc::bt_dict_producer&& btdp) const + size_t ClientContact::bt_encode(oxenc::bt_dict_producer&& btdp) const { btdp.append("a", pubkey.to_view()); @@ -82,21 +85,23 @@ namespace llarp for (auto& s : SRVs) s.bt_encode(sublist.append_dict()); } - } - void ClientContact::bt_decode(std::string_view buf) - { - try - { - bt_decode(oxenc::bt_dict_consumer{buf}); - } - catch (const std::exception& e) - { - log::critical(logcat, "ClientContact deserialization failed: {}", e.what()); - throw; - } + return btdp.view().size(); } + // void ClientContact::bt_decode(std::string_view buf) + // { + // try + // { + // bt_decode(oxenc::bt_dict_consumer{buf}); + // } + // catch (const std::exception& e) + // { + // log::critical(logcat, "ClientContact deserialization failed: {}", e.what()); + // throw; + // } + // } + void ClientContact::bt_decode(oxenc::bt_dict_consumer&& btdc) { pubkey.from_string(btdc.require("a")); @@ -117,7 +122,6 @@ namespace llarp protos = btdc.require("p"); - // ditto as above if (btdc.skip_until("s")) { auto sublist = btdc.consume_list_consumer(); @@ -133,20 +137,37 @@ namespace llarp return intros.rbegin()->is_expired(now); } - EncryptedClientContact ClientContact::encrypt_and_sign() + EncryptedClientContact ClientContact::encrypt_and_sign() const { EncryptedClientContact enc{}; - + try { + enc.blinded_pubkey = derived_privatekey.to_pubkey(); bt_encode(enc.encrypted); + if (not crypto::xchacha20(enc.encrypted.data(), enc.encrypted.size(), pubkey.data(), enc.nonce.data())) + throw std::runtime_error{"Failed to encrypt ClientContact bt-payload!"}; + + enc.signed_at = llarp::time_now_ms(); + + oxenc::bt_dict_producer btdp; + enc.bt_encode(btdp); + + auto view = btdp.view_for_signing(); + + if (not crypto::sign(enc.sig, derived_privatekey, view.data(), view.size())) + throw std::runtime_error{"Failed to sign EncryptedClientContact payload!"}; + + btdp.append("~", enc.sig.to_view()); + + enc._bt_payload = std::move(btdp).str(); } catch (const std::exception& e) { log::warning(logcat, "Exception encrypting and signing client contact: {}", e.what()); + throw; } - return enc; } @@ -157,12 +178,12 @@ namespace llarp return EncryptedClientContact{buf}; } - EncryptedClientContact::EncryptedClientContact(std::string_view buf) + EncryptedClientContact::EncryptedClientContact(std::string_view buf) : _bt_payload{buf} { - bt_decode(oxenc::bt_dict_consumer{buf}); + bt_decode(oxenc::bt_dict_consumer{_bt_payload}); } - void EncryptedClientContact::bt_encode(oxenc::bt_dict_producer&& btdp) const + void EncryptedClientContact::bt_encode(oxenc::bt_dict_producer& btdp) const { btdp.append("i", blinded_pubkey.to_view()); btdp.append("n", nonce.to_view()); @@ -193,6 +214,27 @@ namespace llarp } } + std::optional EncryptedClientContact::decrypt(const PubKey& root) + { + std::optional cc = std::nullopt; + std::string payload{_bt_payload}; + + if (crypto::xchacha20( + reinterpret_cast(payload.data()), payload.size(), root.data(), nonce.data())) + { + log::debug(logcat, "EncryptedClientContact decrypted successfully..."); + cc = ClientContact{std::move(payload)}; + } + + return cc; + } + + bool EncryptedClientContact::verify() const + { + return crypto::verify( + blinded_pubkey, reinterpret_cast(_bt_payload.data()), _bt_payload.size(), sig); + } + bool EncryptedClientContact::is_expired(std::chrono::milliseconds now) const { return now >= signed_at + path::DEFAULT_LIFETIME; diff --git a/llarp/contact/client_contact.hpp b/llarp/contact/client_contact.hpp index e59ddaa65d..913264470c 100644 --- a/llarp/contact/client_contact.hpp +++ b/llarp/contact/client_contact.hpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -46,41 +47,61 @@ namespace llarp TCP2QUIC = 1 << 5, }; + /** TODO: + - LocalCC + - holds the derived Ed25519PrivateData + - RemoteCC: + + */ + /** ClientContact On the wire we encode the data as a dict containing: - "" : the CC format version, which must be == ClientContact::VERSION to be parsed successfully - "a" : public key of the remote client instance + - "e" : (optional) exit policy containing sublists of accepted protocols and routed IP ranges - "i" : list of client introductions corresponding to the different pivots through which paths can be built to the client instance - "p" : supported protocols indicating the traffic accepted by the client instance; this indicates if the client is embedded and therefore requires a tunneled connection. Serialized as a bitwise flag of above protocol_flag enums - - "s" : SRV records for lokinet DNS lookup + - "s" : (optional) SRV records for lokinet DNS lookup */ struct ClientContact { + friend struct EncryptedClientContact; friend class handlers::SessionEndpoint; inline static constexpr uint8_t CC_VERSION{0}; inline static constexpr size_t MAX_CC_SIZE{4096}; + ~ClientContact() = default; + protected: ClientContact() = default; - ClientContact(std::string_view buf); + ClientContact(std::string&& buf); ClientContact( - Ed25519Hash pk, + Ed25519PrivateData private_data, + PubKey pk, const std::unordered_set& srvs, uint16_t proto_flags, std::optional policy = std::nullopt); + /** Parameters: + - `private_data` : derived private subkey data + - `pubkey` : master identity key pubkey + - `srvs` : SRV records (optional, can be empty) + - `proto_flags` : client-supported protocols + - `policy` : exit-related traffic policy (optional) + */ static ClientContact generate( - Ed25519Hash&& pk, + Ed25519PrivateData&& private_data, + PubKey&& pubkey, const std::unordered_set& srvs, uint16_t proto_flags, std::optional policy = std::nullopt); - EncryptedClientContact encrypt_and_sign(); + EncryptedClientContact encrypt_and_sign() const; template void regenerate(intro_set iset, Opt&&... args) @@ -95,9 +116,7 @@ namespace llarp _regenerate(); } - ~ClientContact() = default; - - Ed25519Hash derived_privatekey; + Ed25519PrivateData derived_privatekey; PubKey pubkey; @@ -114,7 +133,7 @@ namespace llarp void bt_encode(std::vector& buf) const; - void bt_encode(oxenc::bt_dict_producer&& btdp) const; + size_t bt_encode(oxenc::bt_dict_producer&& btdp) const; // Throws like a MF (for now) void bt_decode(std::string_view buf); @@ -135,38 +154,46 @@ namespace llarp }; /** EncryptedClientContact - "i" blinded local routerID + "i" blinded local PubKey (routerID) "n" nounce "t" signing time "x" encrypted payload - "~" signature + "~" signature (signed with blinded derived scalar `b`) */ struct EncryptedClientContact { friend struct dht::CCNode; friend struct ClientContact; - protected: EncryptedClientContact() : nonce{SymmNonce::make_random()}, encrypted(ClientContact::MAX_CC_SIZE) {} - static EncryptedClientContact construct(); - static EncryptedClientContact deserialize(std::string_view buf); - // protected: + protected: explicit EncryptedClientContact(std::string_view buf); PubKey blinded_pubkey; SymmNonce nonce; std::chrono::milliseconds signed_at{0s}; std::vector encrypted; - Signature sig; + Signature sig{}; - void bt_encode(oxenc::bt_dict_producer&& btdp) const; + std::string _bt_payload; + + // Does not encode signature, meant to be called prior to signing + void bt_encode(oxenc::bt_dict_producer& btdp) const; void bt_decode(oxenc::bt_dict_consumer&& btdc); public: + dht::Key_t key() const { return dht::Key_t{blinded_pubkey.data()}; } + + std::optional decrypt(const PubKey& root); + + std::string_view bt_payload() const { return _bt_payload; } + + bool verify() const; + bool is_expired(std::chrono::milliseconds now = time_now_ms()) const; }; } // namespace llarp diff --git a/llarp/contact/contactdb.cpp b/llarp/contact/contactdb.cpp index 4d04945538..4ea1e79927 100644 --- a/llarp/contact/contactdb.cpp +++ b/llarp/contact/contactdb.cpp @@ -10,28 +10,28 @@ namespace llarp _introset_nodes = std::make_unique>(_local_key, llarp::randint); } - // std::optional ContactDB::get_decrypted_cc(RouterID remote) const - // { - // std::optional ret = std::nullopt; + std::optional ContactDB::get_decrypted_cc(RouterID remote) const + { + std::optional ret = std::nullopt; - // (void)remote; - // // TESTNET: TODO: finish this after implementing CC encrypt/decrypt + if (auto enc = get_encrypted_cc(dht::Key_t::derive_from_rid(remote))) + ret = enc->decrypt(remote); - // return ret; - // } + return ret; + } - // std::optional ContactDB::get_encrypted_cc(const dht::Key_t& key) const - // { - // std::optional enc = std::nullopt; + std::optional ContactDB::get_encrypted_cc(const dht::Key_t& key) const + { + std::optional enc = std::nullopt; - // auto& clientcontacts = _cc_nodes->nodes; + auto& clientcontacts = _cc_nodes->nodes; - // if (auto itr = clientcontacts.find(key); - // itr != clientcontacts.end() && not itr->second.client_contact.is_expired()) - // enc = itr->second.client_contact; + if (auto itr = clientcontacts.find(key); + itr != clientcontacts.end() && not itr->second.client_contact.is_expired()) + enc = itr->second.client_contact; - // return enc; - // } + return enc; + } std::optional ContactDB::get_decrypted_introset(RouterID remote) const { @@ -67,4 +67,9 @@ namespace llarp _introset_nodes->put_node(std::move(enc)); } + void ContactDB::put_cc(EncryptedClientContact enc) + { + _cc_nodes->put_node(enc); + } + } // namespace llarp diff --git a/llarp/contact/contactdb.hpp b/llarp/contact/contactdb.hpp index aa0dcfc20a..c1bdaed57d 100644 --- a/llarp/contact/contactdb.hpp +++ b/llarp/contact/contactdb.hpp @@ -10,7 +10,6 @@ namespace llarp /** ContactDB TODO: - Store nearest-furthest expiry, trim - */ /// This class mediates storage, retrieval, and functionality for ClientContacts @@ -24,14 +23,14 @@ namespace llarp // holds introsets for remote services std::unique_ptr> _introset_nodes; - // std::unique_ptr> _cc_nodes; + std::unique_ptr> _cc_nodes; public: explicit ContactDB(Router& r); - // std::optional get_decrypted_cc(RouterID remote) const; + std::optional get_decrypted_cc(RouterID remote) const; - // std::optional get_encrypted_cc(const dht::Key_t& key) const; + std::optional get_encrypted_cc(const dht::Key_t& key) const; std::optional get_decrypted_introset(RouterID remote) const; @@ -41,6 +40,8 @@ namespace llarp void put_intro(service::EncryptedIntroSet enc); + void put_cc(EncryptedClientContact enc); + dht::Bucket* services() const { return _introset_nodes.get(); } Router* router() const { return &_router; } diff --git a/llarp/contact/relay_contact.cpp b/llarp/contact/relay_contact.cpp index 715924b57f..b4290d52ea 100644 --- a/llarp/contact/relay_contact.cpp +++ b/llarp/contact/relay_contact.cpp @@ -1,8 +1,4 @@ -<<<<<<<< HEAD:llarp/contact/router_contact.cpp -#include "router_contact.hpp" -======== #include "relay_contact.hpp" ->>>>>>>> a41903e54 ((WIP, squash) contact library, re-org):llarp/contact/relay_contact.cpp #include @@ -38,7 +34,7 @@ namespace llarp void RelayContact::bt_load(oxenc::bt_dict_consumer& btdc) { - if (int rc_ver = btdc.require(""); rc_ver != VERSION) + if (int rc_ver = btdc.require(""); rc_ver != RelayContact::VERSION) throw std::runtime_error{"Invalid RC: do not know how to parse v{} RCs"_format(rc_ver)}; auto ipv4_port = btdc.require("4"); diff --git a/llarp/contact/relay_contact_local.cpp b/llarp/contact/relay_contact_local.cpp index 7686fd789c..93f915346d 100644 --- a/llarp/contact/relay_contact_local.cpp +++ b/llarp/contact/relay_contact_local.cpp @@ -1,8 +1,4 @@ -<<<<<<<< HEAD:llarp/contact/router_contact_local.cpp -#include "router_contact.hpp" -======== #include "relay_contact.hpp" ->>>>>>>> a41903e54 ((WIP, squash) contact library, re-org):llarp/contact/relay_contact_local.cpp #include diff --git a/llarp/contact/relay_contact_remote.cpp b/llarp/contact/relay_contact_remote.cpp index 7258657914..632b00e05d 100644 --- a/llarp/contact/relay_contact_remote.cpp +++ b/llarp/contact/relay_contact_remote.cpp @@ -1,8 +1,4 @@ -<<<<<<<< HEAD:llarp/contact/router_contact_remote.cpp -#include "router_contact.hpp" -======== #include "relay_contact.hpp" ->>>>>>>> a41903e54 ((WIP, squash) contact library, re-org):llarp/contact/relay_contact_remote.cpp #include diff --git a/llarp/contact/router_contact.cpp b/llarp/contact/router_contact.cpp deleted file mode 100644 index b57c14d1b3..0000000000 --- a/llarp/contact/router_contact.cpp +++ /dev/null @@ -1,194 +0,0 @@ -<<<<<<<< HEAD:llarp/contact/router_contact.cpp -#include "router_contact.hpp" -======== -#include "relay_contact.hpp" ->>>>>>>> a41903e54 ((WIP, squash) contact library, re-org):llarp/contact/relay_contact.cpp - -#include - -namespace llarp -{ - static auto logcat = log::Cat("relay-contact"); - - void RelayContact::bt_verify(oxenc::bt_dict_consumer& btdc, bool reject_expired) const - { - btdc.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 (reject_expired and is_expired(time_now_ms())) - throw std::runtime_error{"Rejecting expired RemoteRC!"}; - - if (not addr().is_public() and BLOCK_BOGONS) - { - auto err = "Unable to verify expired RemoteRC address!"; - 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 signature"}; - }); - - if (not btdc.is_finished()) - throw std::runtime_error{"RemoteRC has some fucked up shit at the end"}; - - btdc.finish(); - } - - void RelayContact::bt_load(oxenc::bt_dict_consumer& btdc) - { - if (int rc_ver = btdc.require(""); rc_ver != RC_VERSION) - throw std::runtime_error{"Invalid RC: do not know how to parse v{} RCs"_format(rc_ver)}; - - auto ipv4_port = btdc.require("4"); - - if (ipv4_port.size() != 6) - throw std::runtime_error{ - "Invalid RC address: expected 6-byte IPv4 IP/port, got {}"_format(ipv4_port.size())}; - - sockaddr_in s4; - s4.sin_family = AF_INET; - - std::memcpy(&s4.sin_addr.s_addr, ipv4_port.data(), 4); - std::memcpy(&s4.sin_port, ipv4_port.data() + 4, 2); - - _addr = oxen::quic::Address{&s4}; - - if (!_addr.is_public()) - throw std::runtime_error{"Invalid RC: IPv4 address is not a publicly routable IP"}; - - if (auto ipv6_port = btdc.maybe("6")) - { - 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; - - std::memcpy(&s6.sin6_addr.s6_addr, ipv6_port->data(), 16); - std::memcpy(&s6.sin6_port, ipv6_port->data() + 16, 2); - - _addr6.emplace(&s6); - if (!_addr6->is_public()) - throw std::runtime_error{"Invalid RC: IPv6 address is not a publicly routable IP"}; - } - else - { - _addr6.reset(); - } - - auto netid = btdc.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)}; - - auto pubkey = btdc.require("p"); - if (pubkey.size() != 32) - throw std::runtime_error{"Invalid RC pubkey: expected 32 bytes, got {}"_format(pubkey.size())}; - std::memcpy(_router_id.data(), pubkey.data(), 32); - - _timestamp = rc_time{std::chrono::seconds{btdc.require("t")}}; - - auto ver = btdc.require("v"); - - if (ver.size() != 3) - throw std::runtime_error{"Invalid RC router version: received {} bytes (!= 3)"_format(ver.size())}; - - for (int i = 0; i < 3; i++) - _router_version[i] = ver[i]; - } - - bool RelayContact::write(const fs::path& fname) const - { - auto bte = view(); - - 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; - } - - nlohmann::json RelayContact::extract_status() const - { - nlohmann::json obj{ - {"lastUpdated", _timestamp.time_since_epoch().count()}, - {"publicRouter", is_public_addressable()}, - {"identity", _router_id.to_string()}, - {"address", _addr.to_string()}}; - - // if (routerVersion) - // { - // obj["routerVersion"] = routerVersion->to_string(); - // } - // std::vector srv; - // for (const auto& record : srvRecords) - // { - // srv.emplace_back(record.ExtractStatus()); - // } - // obj["srvRecords"] = srv; - - return obj; - } - - bool RelayContact::is_public_addressable() const - { - if (_router_version.empty()) - return false; - - return _addr.is_addressable(); - } - - bool RelayContact::is_expired(std::chrono::milliseconds now) const - { - return age(now) >= _timestamp.time_since_epoch() + LIFETIME; - } - - std::chrono::milliseconds RelayContact::time_to_expiry(std::chrono::milliseconds now) const - { - const auto expiry = _timestamp.time_since_epoch() + LIFETIME; - return now < expiry ? expiry - now : 0s; - } - - std::chrono::milliseconds RelayContact::age(std::chrono::milliseconds now) const - { - auto delta = now - _timestamp.time_since_epoch(); - return delta > 0s ? delta : 0s; - } - - bool RelayContact::expires_within_delta(std::chrono::milliseconds now, std::chrono::milliseconds dlt) const - { - return time_to_expiry(now) <= dlt; - } - - static const std::set obsolete_bootstraps{ - "7a16ac0b85290bcf69b2f3b52456d7e989ac8913b4afbb980614e249a3723218"sv, - "e6b3a6fe5e32c379b64212c72232d65b0b88ddf9bbaed4997409d329f8519e0b"sv, - }; - - bool RelayContact::is_obsolete_bootstrap() const - { - for (const auto& k : obsolete_bootstraps) - { - if (_router_id.ToHex() == k) - return true; - } - return false; - } - - bool RelayContact::is_obsolete(const RelayContact& rc) - { - const auto& hex = rc._router_id.ToHex(); - - return obsolete_bootstraps.count(hex); - } -} // namespace llarp diff --git a/llarp/contact/router_contact_local.cpp b/llarp/contact/router_contact_local.cpp deleted file mode 100644 index 8539f0c173..0000000000 --- a/llarp/contact/router_contact_local.cpp +++ /dev/null @@ -1,97 +0,0 @@ -<<<<<<<< HEAD:llarp/contact/router_contact_local.cpp -#include "router_contact.hpp" -======== -#include "relay_contact.hpp" ->>>>>>>> a41903e54 ((WIP, squash) contact library, re-org):llarp/contact/relay_contact_local.cpp - -#include - -namespace llarp -{ - LocalRC LocalRC::make(Ed25519SecretKey secret, oxen::quic::Address local) - { - return *new LocalRC{std::move(secret), std::move(local)}; - } - - LocalRC::LocalRC(Ed25519SecretKey secret, oxen::quic::Address local) : _secret_key{std::move(secret)} - { - _router_id = seckey_to_pubkey(_secret_key); - _addr = std::move(local); - if (_addr.is_ipv6()) - _addr6.emplace(&_addr.in6()); - resign(); - } - - RemoteRC LocalRC::to_remote() - { - resign(); - return RemoteRC{view()}; - } - - void LocalRC::bt_sign(oxenc::bt_dict_producer& btdp) - { - _signature.clear(); - - 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 = {sig.data(), sig.size()}; - return sig; - }); - - _payload = ustring{btdp.view()}; - } - - void LocalRC::bt_encode(oxenc::bt_dict_producer& btdp) - { - 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.to_view()); - - 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}); - } - - void LocalRC::resign() - { - set_systime_timestamp(); - oxenc::bt_dict_producer btdp; - bt_encode(btdp); - bt_sign(btdp); - } -} // namespace llarp diff --git a/llarp/contact/router_contact_remote.cpp b/llarp/contact/router_contact_remote.cpp deleted file mode 100644 index 7258657914..0000000000 --- a/llarp/contact/router_contact_remote.cpp +++ /dev/null @@ -1,59 +0,0 @@ -<<<<<<<< HEAD:llarp/contact/router_contact_remote.cpp -#include "router_contact.hpp" -======== -#include "relay_contact.hpp" ->>>>>>>> a41903e54 ((WIP, squash) contact library, re-org):llarp/contact/relay_contact_remote.cpp - -#include - -namespace llarp -{ - static auto logcat = log::Cat("relay-contact"); - - RemoteRC::RemoteRC(oxenc::bt_dict_consumer btdc) - { - try - { - bt_load(btdc); - bt_verify(btdc, /*reject_expired=*/true); - } - catch (const std::exception& e) - { - auto err = "Exception caught parsing RemoteRC: {}"_format(e.what()); - log::warning(logcat, "{}", err); - throw std::runtime_error{err}; - } - } - - bool RemoteRC::read(const fs::path& fname) - { - log::trace(logcat, "{} called", __PRETTY_FUNCTION__); - _payload.resize(MAX_RC_SIZE); - - try - { - auto nread = util::file_to_buffer(fname, _payload.data(), _payload.size()); - log::trace(logcat, "{}B read from file (path:{})!", nread, fname); - _payload.resize(nread); - - oxenc::bt_dict_consumer btdc{_payload}; - bt_load(btdc); - bt_verify(btdc); - } - catch (const std::exception& e) - { - log::warning(logcat, "Failed to read or validate RC from {}: {}", fname, e.what()); - return false; - } - - return true; - } - - bool RemoteRC::verify() const - { - oxenc::bt_dict_consumer btdc{_payload}; - bt_verify(btdc); - return true; - } - -} // namespace llarp diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index 483da479cb..76104c8f47 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -28,7 +28,7 @@ namespace llarp const PubKey& client_pk, const PubKey& server_pk, const uint8_t* themPub, - const Ed25519Hash& local_edhash) + const Ed25519PrivateData& local_edhash) { SharedSecret shared; crypto_generichash_state h; @@ -57,7 +57,7 @@ namespace llarp { SharedSecret dh_result; - if (dh(dh_result, sk.to_pubkey(), pk, pk.data(), sk.to_edhash())) + if (dh(dh_result, sk.to_pubkey(), pk, pk.data(), sk.to_eddata())) { return crypto_generichash_blake2b( shared.data(), shared.size(), n.data(), n.size(), dh_result.data(), dh_result.size()) @@ -72,7 +72,7 @@ namespace llarp { SharedSecret dh_result; - if (dh(dh_result, pk, sk.to_pubkey(), pk.data(), sk.to_edhash())) + if (dh(dh_result, pk, sk.to_pubkey(), pk.data(), sk.to_eddata())) { return crypto_generichash_blake2b( shared.data(), shared.size(), n.data(), n.size(), dh_result.data(), dh_result.size()) @@ -177,7 +177,7 @@ namespace llarp return crypto_sign_detached(sig, nullptr, buf.data(), buf.size(), sk.data()) != -1; } - bool crypto::sign(Signature& sig, const Ed25519Hash& privkey, uint8_t* buf, size_t size) + bool crypto::sign(Signature& sig, const Ed25519PrivateData& privkey, const uint8_t* buf, size_t size) { PubKey pubkey = privkey.to_pubkey(); @@ -225,7 +225,7 @@ namespace llarp : false; } - bool crypto::verify(const PubKey& pub, uint8_t* buf, size_t size, const Signature& sig) + bool crypto::verify(const PubKey& pub, const uint8_t* buf, size_t size, const Signature& sig) { return crypto_sign_verify_detached(sig.data(), buf, size, pub.data()) != -1; } @@ -237,11 +237,6 @@ namespace llarp : false; } - 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; - } - void crypto::derive_encrypt_outer_wrapping( const Ed25519SecretKey& shared_key, SharedSecret& secret, @@ -318,14 +313,13 @@ namespace llarp "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) + bool crypto::make_scalar(AlignedBuffer<32>& out, const PubKey& k, uint64_t i) { // b = BLIND-STRING || k || i - std::array buf; + 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); + oxenc::write_host_as_little(i, buf.data() + 160 + PubKey::SIZE); // n = H(b) // h = make_point(n) ShortHash n; @@ -352,7 +346,7 @@ namespace llarp } bool crypto::derive_subkey_private( - Ed25519Hash& out_key, const Ed25519SecretKey& root_key, uint64_t key_n, const AlignedBuffer<32>* hash) + Ed25519PrivateData& out_key, const Ed25519SecretKey& root_key, uint64_t key_n, const AlignedBuffer<32>* hash) { // Derives a private subkey from a root key. // @@ -399,7 +393,7 @@ namespace llarp h[31] &= 63; h[31] |= 64; - Ed25519Hash a = root_key.to_edhash(); + Ed25519PrivateData a = root_key.to_eddata(); // a' = ha crypto_core_ed25519_scalar_mul(out_key.data(), h.data(), a.data()); @@ -413,34 +407,6 @@ namespace llarp return true; } - Ed25519Hash crypto::derive_private_subkey(const Ed25519SecretKey& root) - { - Ed25519Hash ret{}; - - AlignedBuffer<32> h; - - if (not make_scalar(h, root.to_pubkey(), 1)) - throw std::runtime_error{"Call to `make_scalar` failed in deriving private subkey!"}; - - h[0] &= 248; - h[31] &= 63; - h[31] |= 64; - - Ed25519Hash a = root.to_edhash(); - - // a' = ha - crypto_core_ed25519_scalar_mul(ret.data(), h.data(), a.data()); - - // s' = H(h || s) - std::array buf; - std::copy(h.begin(), h.end(), buf.begin()); - std::copy(a.signing_hash().begin(), a.signing_hash().end(), buf.begin() + 32); - if (crypto_generichash_blake2b(ret.signing_hash().data(), 32, buf.data(), buf.size(), nullptr, 0) == -1) - throw std::runtime_error{"Call to `crypto_generichash_blake2b` failed!"}; - - return ret; - } - void crypto::randomize(uint8_t* buf, size_t len) { randombytes(buf, len); diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index 1684e235ff..efbcabbb16 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -52,13 +52,12 @@ namespace llarp bool sign(uint8_t* sig, const Ed25519SecretKey& sk, ustring_view buf); /// ed25519 sign (custom with derived keys) - bool sign(Signature&, const Ed25519Hash&, uint8_t* buf, size_t size); + bool sign(Signature&, const Ed25519PrivateData&, const 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(const PubKey&, const uint8_t*, size_t, const Signature&); bool verify(ustring_view, ustring_view, ustring_view); - bool verify(uint8_t*, uint8_t*, size_t, uint8_t*); /// Used in path-build and session initiation messages. Derives a shared secret key for symmetric DH, encrypting /// the given payload in-place. Will throw on failure of either the client DH derivation or the xchacha20 @@ -76,6 +75,8 @@ namespace llarp void derive_decrypt_outer_wrapping( const Ed25519SecretKey& local, const PubKey& remote, const SymmNonce& nonce, uspan encrypted); + bool make_scalar(AlignedBuffer<32>& out, const PubKey& k, uint64_t i); + /// derive sub keys for public keys. hash is really only intended for /// testing ands key_n if given. bool derive_subkey( @@ -84,13 +85,11 @@ namespace llarp /// derive sub keys for private keys. hash is really only intended for /// testing ands key_n if given. bool derive_subkey_private( - Ed25519Hash& derived, + Ed25519PrivateData& derived, const Ed25519SecretKey& root, uint64_t key_n, const AlignedBuffer<32>* hash = nullptr); - Ed25519Hash derive_private_subkey(const Ed25519SecretKey& root); - /// randomize buffer void randomize(uint8_t* buf, size_t len); diff --git a/llarp/crypto/key_manager.cpp b/llarp/crypto/key_manager.cpp index 18ea13f292..f7d330c630 100644 --- a/llarp/crypto/key_manager.cpp +++ b/llarp/crypto/key_manager.cpp @@ -1,6 +1,6 @@ #include "key_manager.hpp" -#include "crypto.hpp" +#include "types.hpp" #include #include @@ -39,9 +39,10 @@ namespace llarp crypto::identity_keygen(identity_key); } + identity_data = identity_key.to_eddata(); public_key = seckey_to_pubkey(identity_key); - log::info(logcat, "Client public key: {}", public_key); + log::info(logcat, "Client public key: {}", public_key); is_initialized = true; } else @@ -70,12 +71,18 @@ namespace llarp void KeyManager::update_idkey(Ed25519SecretKey&& newkey) { identity_key = std::move(newkey); + identity_data = identity_key.to_eddata(); public_key = seckey_to_pubkey(identity_key); log::info(logcat, "Relay key manager updated secret key; new public key: {}", public_key); } - Ed25519Hash KeyManager::derive_subkey() const + Ed25519PrivateData KeyManager::derive_subkey(uint64_t domain) const { - return crypto::derive_private_subkey(identity_key); + return identity_key.derive_private_subkey_data(domain); } + + // void KeyManager::encrypt(uint8_t* buf, size_t size) + // { + + // } } // namespace llarp diff --git a/llarp/crypto/key_manager.hpp b/llarp/crypto/key_manager.hpp index ab261150af..c81a6c0170 100644 --- a/llarp/crypto/key_manager.hpp +++ b/llarp/crypto/key_manager.hpp @@ -43,16 +43,17 @@ namespace llarp static std::shared_ptr make(const Config& config, bool is_relay); Ed25519SecretKey identity_key; + Ed25519PrivateData identity_data; RouterID public_key; fs::path rc_path; void update_idkey(Ed25519SecretKey&& newkey); - Ed25519Hash derive_subkey() const; + Ed25519PrivateData derive_subkey(uint64_t domain = 1) const; public: - // + void encrypt(uint8_t* buf, size_t size); const RouterID& router_id() const { return public_key; } }; diff --git a/llarp/crypto/types.cpp b/llarp/crypto/types.cpp index 7f5f22e0f1..f295e09af6 100644 --- a/llarp/crypto/types.cpp +++ b/llarp/crypto/types.cpp @@ -1,10 +1,13 @@ #include "types.hpp" #include +#include #include #include #include +#include +#include #include #include @@ -41,15 +44,15 @@ namespace llarp bool Ed25519SecretKey::recalculate() { log::trace(logcat, "{} called", __PRETTY_FUNCTION__); - Ed25519Hash key = to_edhash(); + Ed25519PrivateData key = to_eddata(); PubKey pubkey = key.to_pubkey(); std::memcpy(data() + 32, pubkey.data(), 32); return true; } - Ed25519Hash Ed25519SecretKey::to_edhash() const + Ed25519PrivateData Ed25519SecretKey::to_eddata() const { - Ed25519Hash k; + Ed25519PrivateData k; unsigned char h[crypto_hash_sha512_BYTES]; crypto_hash_sha512(h, data(), 32); h[0] &= 248; @@ -59,7 +62,34 @@ namespace llarp return k; } - PubKey Ed25519Hash::to_pubkey() const + Ed25519PrivateData Ed25519SecretKey::derive_private_subkey_data(uint64_t domain) const + { + Ed25519PrivateData ret{}; + + AlignedBuffer<32> h; + + if (not crypto::make_scalar(h, to_pubkey(), domain)) + throw std::runtime_error{"Call to `make_scalar` failed in deriving private subkey!"}; + + h[0] &= 248; + h[31] &= 63; + h[31] |= 64; + + auto a = to_eddata(); + + // a' = ha + crypto_core_ed25519_scalar_mul(ret.data(), h.data(), a.data()); + + // s' = H(h || s) + std::array buf; + std::copy(h.begin(), h.end(), buf.begin()); + std::copy(a.signing_hash().begin(), a.signing_hash().end(), buf.begin() + 32); + if (crypto_generichash_blake2b(ret.signing_hash().data(), 32, buf.data(), buf.size(), nullptr, 0) == -1) + throw std::runtime_error{"Call to `crypto_generichash_blake2b` failed!"}; + return ret; + } + + PubKey Ed25519PrivateData::to_pubkey() const { PubKey p; crypto_scalarmult_ed25519_base_noclamp(p.data(), data()); diff --git a/llarp/crypto/types.hpp b/llarp/crypto/types.hpp index 23c271df2f..777ff86d27 100644 --- a/llarp/crypto/types.hpp +++ b/llarp/crypto/types.hpp @@ -7,7 +7,6 @@ #include #include -#include namespace llarp { @@ -15,9 +14,9 @@ namespace llarp using KeyExchangeNonce = AlignedBuffer<32>; struct PubKey; - struct Ed25519Hash; + struct Ed25519PrivateData; - /// Stores a sodium "secret key" value, which is actually the seed + /// Stores a sodium "secret key" value, which is actually the Ed25519 seed /// concatenated with the public key. Note that the seed is *not* the private /// key value itself, but rather the seed from which it can be calculated. struct Ed25519SecretKey final : public AlignedBuffer @@ -39,42 +38,46 @@ namespace llarp /// recalculate public component bool recalculate(); - std::string_view to_string() const { return "[secretkey]"; } - PubKey to_pubkey() const; - Ed25519Hash to_edhash() const; + Ed25519PrivateData to_eddata() const; + + Ed25519PrivateData derive_private_subkey_data(uint64_t domain = 1) const; bool load_from_file(const fs::path& fname); bool write_to_file(const fs::path& fname) const; + + std::string_view to_string() const { return "[secretkey]"; } + static constexpr bool to_string_formattable{true}; }; - /// PrivateKey is similar to SecretKey except that it only stores the private - /// key value and a hash, unlike SecretKey which stores the seed from which - /// the private key and hash value are generated. This is primarily intended - /// for use with derived keys, where we can derive the private key but not the - /// seed. - struct Ed25519Hash final : public AlignedBuffer<64> + /// Ed25519PrivateData is similar to Ed25519SecretKey except that it only stores the + /// private scalar and a hash, unlike SecretKey which stores the seed from which + /// the private key and hash value are generated. + struct Ed25519PrivateData final : public AlignedBuffer<64> { - Ed25519Hash() = default; + friend struct Ed25519SecretKey; - explicit Ed25519Hash(const uint8_t* ptr) : AlignedBuffer<64>(ptr) {} + Ed25519PrivateData() = default; - explicit Ed25519Hash(const AlignedBuffer<64>& key_and_hash) : AlignedBuffer<64>(key_and_hash) {} + explicit Ed25519PrivateData(const uint8_t* ptr) : AlignedBuffer<64>(ptr) {} + + explicit Ed25519PrivateData(const AlignedBuffer<64>& key_and_hash) : AlignedBuffer<64>(key_and_hash) {} // Returns writeable access to the 32-byte Ed25519 Private Scalar uspan scalar() { return {data(), 32}; } // Returns readable access to the 32-byte Ed25519 Private Scalar - ustring_view scalar() const { return {data(), 32}; } + const_uspan scalar() const { return {data(), 32}; } // Returns writeable access to the 32-byte Ed25519 Signing Hash uspan signing_hash() { return {data() + 32, 32}; } // Returns readable access to the 32-byte Ed25519 Signing Hash - ustring_view signing_hash() const { return {data() + 32, 32}; } - - std::string_view to_string() const { return "[privatekey]"; } + const_uspan signing_hash() const { return {data() + 32, 32}; } PubKey to_pubkey() const; + + std::string_view to_string() const { return "[privatekey]"; } + static constexpr bool to_string_formattable{true}; }; using ShortHash = AlignedBuffer; diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index 2c167edc3a..0106cb55f9 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -94,13 +94,20 @@ namespace llarp::handlers if (_is_exit_node) protoflags |= protocol_flag::EXIT; - client_contact = - ClientContact::generate(_router.key_manager()->derive_subkey(), _srv_records, protoflags, _exit_policy); + auto& key_manager = _router.key_manager(); + + client_contact = ClientContact::generate( + key_manager->derive_subkey(), + key_manager->identity_data.to_pubkey(), + _srv_records, + protoflags, + _exit_policy); should_publish_cc = net_config.is_reachable; if (should_publish_cc) { + // } } @@ -248,17 +255,71 @@ namespace llarp::handlers } } + void SessionEndpoint::lookup_client_intro( + RouterID remote, bool is_relayed, uint64_t order, std::function)> func) + { + auto remote_key = dht::Key_t::derive_from_rid(remote); + + if (auto maybe_intro = _router.contact_db().get_decrypted_cc(remote)) + { + log::info(logcat, "Decrypted clientcontact for remote (rid: {}) found locally!", remote); + return func(std::move(maybe_intro)); + } + + log::debug(logcat, "Looking up clientcontact for remote (rid:{})", remote); + + auto response_handler = [this, remote, hook = std::move(func)](std::string response) mutable { + try + { + auto enc = EncryptedClientContact::deserialize(response); + + if (auto intro = enc.decrypt(remote)) + { + log::info(logcat, "Storing ClientContact for remote rid:{}", remote); + _router.contact_db().put_cc(std::move(enc)); + return hook(std::move(intro)); + } + + oxenc::bt_dict_consumer btdc{response}; + auto s = btdc.maybe(messages::STATUS_KEY); + + log::warning(logcat, "Call to `find_cc` failed -- status: {}", s.value_or("< NONE GIVEN >")); + } + catch (const std::exception& e) + { + log::warning(logcat, "Exception caught parsing FindClientContact response: {}", e.what()); + } + + hook(std::nullopt); + }; + + { + Lock_t l{paths_mutex}; + + for (const auto& [rid, path] : _paths) + { + log::debug( + logcat, + "Querying pivot (rid:{}) for clientcontact lookup target (rid:{})", + path->pivot_rid(), + remote); + path->find_client_contact(remote_key, is_relayed, order, response_handler); + } + } + } + void SessionEndpoint::lookup_intro( RouterID remote, bool is_relayed, uint64_t order, std::function)> func) { + auto remote_key = dht::Key_t::derive_from_rid(remote); + if (auto maybe_intro = _router.contact_db().get_decrypted_introset(remote)) { - log::debug(logcat, "Decrypted introset for remote (rid:{}) found locally~", remote); + log::debug(logcat, "Decrypted introset for remote (rid:{}) found locally", remote); return func(std::move(maybe_intro)); } log::debug(logcat, "Looking up introset for remote (rid:{})", remote); - auto remote_key = dht::Key_t::derive_from_rid(remote); auto response_handler = [this, remote, hook = std::move(func)](std::string response) mutable { if (auto encrypted = service::EncryptedIntroSet::construct(response); @@ -319,15 +380,25 @@ namespace llarp::handlers void SessionEndpoint::_update_and_publish_localcc() { - // TESTNET: TODO: encrypt and sign - + try + { + auto enc = client_contact.encrypt_and_sign(); + + if (publish_client_contact(enc)) + log::debug(logcat, "Successfully republished updated EncryptedClientContact!"); + else + log::warning(logcat, "Failed to republish updated EncryptedClientContact!"); + } + catch (const std::exception& e) + { + log::warning(logcat, "ClientContact encryption/signing exception: {}", e.what()); + } } /** Introset publishing: - When a local service or exit node publishes an introset, it is also sent along the path currently used for that session */ - // TODO: this void SessionEndpoint::regen_and_publish_introset() { const auto now = llarp::time_now_ms(); @@ -375,9 +446,7 @@ namespace llarp::handlers if (auto maybe_encrypted = _identity.encrypt_and_sign_introset(_local_introset, now)) { if (publish_introset(*maybe_encrypted)) - { log::debug(logcat, "Successfully republished encrypted introset"); - } else log::warning(logcat, "Failed to republish encrypted introset!"); } @@ -442,6 +511,24 @@ namespace llarp::handlers return ret; } + bool SessionEndpoint::publish_client_contact(const EncryptedClientContact& ecc) + { + bool ret{true}; + + { + Lock_t l{paths_mutex}; + + for (const auto& [rid, path] : _paths) + { + log::debug(logcat, "Publishing ClientContact to pivot {}", path->pivot_rid()); + + ret += path->publish_client_contact(ecc, true); + } + } + + return ret; + } + bool SessionEndpoint::publish_introset(const service::EncryptedIntroSet& introset) { bool ret{true}; @@ -609,6 +696,8 @@ namespace llarp::handlers auto counter = std::make_shared(path::DEFAULT_PATHS_HELD); + // TESTNET: TODO: + _router.loop()->call([this, remote, handler = std::move(cb), is_exit, counter]() mutable { lookup_intro( remote.router_id(), diff --git a/llarp/handlers/session.hpp b/llarp/handlers/session.hpp index c0395e9cd8..af00d062e8 100644 --- a/llarp/handlers/session.hpp +++ b/llarp/handlers/session.hpp @@ -121,6 +121,8 @@ namespace llarp void regen_and_publish_introset(); + bool publish_client_contact(const EncryptedClientContact& ecc); + bool publish_introset(const service::EncryptedIntroSet& introset); // SessionEndpoint can use either a whitelist or a static auth token list to validate incomininbg requests @@ -136,6 +138,13 @@ namespace llarp void lookup_remote_srv( std::string name, std::string service, std::function)> handler); + void lookup_client_intro( + RouterID remote, + bool is_relayed, + uint64_t order, + std::function)> func); + + // TESTNET: // TONUKE: void lookup_intro( RouterID remote, bool is_relayed, diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index f5f52345f4..f01787887e 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1128,6 +1128,100 @@ namespace llarp } } + void LinkManager::handle_publish_cc(std::string_view body, std::function respond) + { + EncryptedClientContact enc; + bool is_relayed; + uint64_t relay_order; + + try + { + std::tie(enc, relay_order, is_relayed) = PublishClientContact::deserialize(body); + } + catch (const std::exception& e) + { + log::warning(logcat, "Exception: {}", e.what()); + return respond(messages::ERROR_RESPONSE); + } + + if (enc.is_expired()) + { + log::warning(logcat, "Received expired EncryptedClientContact!"); + return respond(PublishClientContact::EXPIRED); + } + + if (not enc.verify()) + { + log::warning(logcat, "Received invalid EncryptedClientContact!"); + return respond(PublishClientContact::INVALID); + } + + auto dht_key = enc.key(); + auto local_rid = _router.router_id(); + + auto closest_rcs = _router.node_db()->find_many_closest_to(dht_key, path::DEFAULT_PATHS_HELD); + + if (closest_rcs.size() != path::DEFAULT_PATHS_HELD) + { + log::warning(logcat, "Received PublishClientContact message but only know {} nodes?", closest_rcs.size()); + return respond(PublishClientContact::INSUFFICIENT); + } + + if (is_relayed) + { + if (is_relayed >= path::DEFAULT_PATHS_HELD) + { + log::error(logcat, "Received PublishClientContact with invalid relay order: {}", relay_order); + return respond(PublishClientContact::INVALID_ORDER); + } + + log::debug(logcat, "Relaying EncryptedClientContact for {}", dht_key); + + const auto& peer_key = closest_rcs[relay_order].router_id(); + + if (peer_key == local_rid) + { + log::info( + logcat, + "Received PublishClientContact for which we are index {}... storing client contact...", + relay_order); + _router.contact_db().put_cc(std::move(enc)); + return respond(messages::OK_RESPONSE); + } + + log::info(logcat, "Received PublishClientContact; propagating to peer index {}...", relay_order); + + send_control_message( + peer_key, + "publish_cc", + PublishClientContact::serialize(std::move(enc), relay_order, is_relayed), + [respond = std::move(respond)](oxen::quic::message m) mutable { + if (m.timed_out) + return; // drop; requester will already have timed out + respond(m.body_str()); + }); + } + else + { + for (auto& rc : closest_rcs) + { + if (rc.router_id() == local_rid) + { + log::info( + logcat, + "Received PublishClientContact for {}; we are candidate {}; accepting...", + dht_key, + relay_order); + _router.contact_db().put_cc(std::move(enc)); + return respond(messages::OK_RESPONSE); + } + } + + log::warning(logcat, "Received non-relayed PublishClientContact from {}; we are not a candidate", dht_key); + } + } + + // TONUKE: this void LinkManager::handle_publish_intro(std::string_view body, std::function respond) { service::EncryptedIntroSet enc; @@ -1174,7 +1268,7 @@ namespace llarp { if (relay_order >= path::DEFAULT_PATHS_HELD) { - log::error(logcat, "Received PublishIntroMessage with invalide relay order: {}", relay_order); + log::error(logcat, "Received PublishIntroMessage with invalid relay order: {}", relay_order); respond(serialize_response({{messages::STATUS_KEY, PublishIntroMessage::INVALID_ORDER}})); return; } @@ -1235,57 +1329,69 @@ namespace llarp log::warning(logcat, "Received non-relayed PublishIntroMessage from {}; we are not the candidate", addr); } - // DISCUSS: I feel like ::handle_publish_intro_response should be the callback that handles the - // response to a relayed publish_intro (above line 1131-ish) - - void LinkManager::handle_publish_intro_response(oxen::quic::message m) + void LinkManager::handle_find_cc(std::string_view body, std::function respond) { - if (m.timed_out) - { - log::info(logcat, "PublishIntroMessage timed out!"); - return; - } - - std::string payload; + dht::Key_t dht_key; + bool is_relayed; + uint64_t relay_order; try { - oxenc::bt_dict_consumer btdc{m.body()}; - payload = btdc.require(messages::STATUS_KEY); + std::tie(dht_key, relay_order, is_relayed) = FindClientContact::deserialize(body); } catch (const std::exception& e) { log::warning(logcat, "Exception: {}", e.what()); - return; + return respond(messages::ERROR_RESPONSE); } - if (m) + auto local_rid = _router.router_id(); + + auto closest_rcs = _router.node_db()->find_many_closest_to(dht_key, path::DEFAULT_PATHS_HELD); + + if (closest_rcs.size() != path::DEFAULT_PATHS_HELD) { - // DISCUSS: not sure what to do on success of a publish intro command? + log::warning(logcat, "Received FindClientContact message but only know {} nodes?", closest_rcs.size()); + return respond(FindClientContact::INSUFFICIENT); } - else + + if (is_relayed) { - if (payload == "ERROR") + if (is_relayed >= path::DEFAULT_PATHS_HELD) { - log::info(logcat, "PublishIntroMessage failed with remote exception!"); - // Do something smart here probably - return; + log::error(logcat, "Received FindClientContact with invalid relay order: {}", relay_order); + return respond(FindClientContact::INVALID_ORDER); } - log::info(logcat, "PublishIntroMessage failed with error code: {}", payload); + log::debug(logcat, "Relaying FindClientContactMessage for {}", dht_key); - if (payload == PublishIntroMessage::INVALID_INTROSET) - { - } - else if (payload == PublishIntroMessage::EXPIRED) - { - } - else if (payload == PublishIntroMessage::INSUFFICIENT) - { - } - else if (payload == PublishIntroMessage::INVALID_ORDER) + const auto& peer_key = closest_rcs[relay_order].router_id(); + + send_control_message( + peer_key, + "find_cc", + FindClientContact::serialize(dht_key, relay_order, is_relayed), + [respond = std::move(respond)](oxen::quic::message m) mutable { + if (m) + log::info(logcat, "Relayed FindClientContact returned successful! Relaying response..."); + else if (m.timed_out) + log::info(logcat, "Relayed FindClientContact timed out! Relaying response..."); + else + log::info(logcat, "Relayed FindClientContact failed! Relaying response..."); + + respond(m.body_str()); + }); + } + else + { + if (auto maybe_cc = _router.contact_db().get_encrypted_cc(dht_key)) { + log::info(logcat, "Received non-relayed FindClientContact; returning local EncryptedClientContact..."); + return respond(FindClientContact::serialize_response(maybe_cc->bt_payload())); } + + log::warning(logcat, "Received non-relayed FindClientContact; no local EncryptedClientContact found..."); + return respond(FindClientContact::NOT_FOUND); } } @@ -1311,6 +1417,15 @@ namespace llarp const auto addr = dht::Key_t{location.data()}; + auto closest_rcs = _router.node_db()->find_many_closest_to(addr, path::DEFAULT_PATHS_HELD); + + if (closest_rcs.size() != path::DEFAULT_PATHS_HELD) + { + log::error(logcat, "Received FindIntroMessage but only know {} nodes", closest_rcs.size()); + respond(serialize_response({{messages::STATUS_KEY, FindIntroMessage::INSUFFICIENT_NODES}})); + return; + } + if (is_relayed) { if (relay_order >= path::DEFAULT_PATHS_HELD) @@ -1320,15 +1435,6 @@ namespace llarp return; } - auto closest_rcs = _router.node_db()->find_many_closest_to(addr, path::DEFAULT_PATHS_HELD); - - if (closest_rcs.size() != path::DEFAULT_PATHS_HELD) - { - log::error(logcat, "Received FindIntroMessage but only know {} nodes", closest_rcs.size()); - respond(serialize_response({{messages::STATUS_KEY, FindIntroMessage::INSUFFICIENT_NODES}})); - return; - } - log::info(logcat, "Relaying FindIntroMessage for {}", addr); const auto& peer_rc = closest_rcs[relay_order]; diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index dacbe34768..1e5d6680cd 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -257,6 +257,10 @@ namespace llarp void handle_find_intro(std::string_view body, std::function respond); // relay void handle_publish_intro(std::string_view body, std::function respond); // relay + // TESTNET: // NEW CLIENT_CONTACT HANDLERS + void handle_find_cc(std::string_view body, std::function respond); + void handle_publish_cc(std::string_view body, std::function respond); + // Path messages void handle_path_build(oxen::quic::message, const RouterID& from); // relay void handle_path_latency(oxen::quic::message); // relay @@ -294,7 +298,7 @@ namespace llarp // DHT responses void handle_resolve_ons_response(oxen::quic::message); void handle_find_intro_response(oxen::quic::message); - void handle_publish_intro_response(oxen::quic::message); + // void handle_publish_intro_response(oxen::quic::message); // Path responses void handle_path_latency_response(oxen::quic::message); diff --git a/llarp/messages/dht.hpp b/llarp/messages/dht.hpp index 4fa6a916b5..5ad370fb22 100644 --- a/llarp/messages/dht.hpp +++ b/llarp/messages/dht.hpp @@ -2,6 +2,7 @@ #include "common.hpp" +#include #include namespace llarp @@ -68,6 +69,108 @@ namespace llarp } } // namespace FindNameMessage + namespace FindClientContact + { + inline const auto NOT_FOUND = messages::serialize_response({{messages::STATUS_KEY, "NOT FOUND"}}); + inline const auto INSUFFICIENT = messages::serialize_response({{messages::STATUS_KEY, "INSUFFICIENT NODES"}}); + inline const auto INVALID_ORDER = messages::serialize_response({{messages::STATUS_KEY, "INVALID ORDER"}}); + + inline static std::string serialize(const dht::Key_t& location, uint64_t relay_order, bool is_relayed) + { + oxenc::bt_dict_producer btdp; + + try + { + btdp.append("c", location.to_view()); + btdp.append("o", relay_order); + btdp.append("r", is_relayed); + } + catch (...) + { + log::error(messages::logcat, "Error: failed to serialize PublishClientContact contents!"); + } + + return std::move(btdp).str(); + } + + inline static std::string serialize_response(std::string_view encrypted_payload) + { + return messages::serialize_response({{"ECC", encrypted_payload}}); + } + + inline static std::tuple deserialize(std::string_view buf) + { + dht::Key_t key; + bool is_relayed; + uint64_t relay_order; + + try + { + oxenc::bt_dict_consumer btdc{buf}; + key.from_string(btdc.require("c")); + is_relayed = btdc.require("o"); + relay_order = btdc.require("r"); + } + catch (const std::exception& e) + { + log::error( + messages::logcat, "Error: failed to deserialize PublishClientContact contents: {}", e.what()); + throw; + } + + return {key, relay_order, is_relayed}; + } + } // namespace FindClientContact + + namespace PublishClientContact + { + inline const auto INVALID = messages::serialize_response({{messages::STATUS_KEY, "INVALID CC"}}); + inline const auto EXPIRED = messages::serialize_response({{messages::STATUS_KEY, "EXPIRED CC"}}); + inline const auto INSUFFICIENT = messages::serialize_response({{messages::STATUS_KEY, "INSUFFICIENT NODES"}}); + inline const auto INVALID_ORDER = messages::serialize_response({{messages::STATUS_KEY, "INVALID ORDER"}}); + + inline static std::string serialize(const EncryptedClientContact& ecc, uint64_t relay_order, bool is_relayed) + { + oxenc::bt_dict_producer btdp; + + try + { + btdp.append("o", relay_order); + btdp.append("r", is_relayed); + btdp.append("x", ecc.bt_payload()); + } + catch (...) + { + log::error(messages::logcat, "Error: failed to serialize PublishClientContact contents!"); + } + + return std::move(btdp).str(); + } + + inline static std::tuple deserialize(std::string_view buf) + { + EncryptedClientContact ecc; + bool is_relayed; + uint64_t relay_order; + + try + { + oxenc::bt_dict_consumer btdc{buf}; + is_relayed = btdc.require("o"); + relay_order = btdc.require("r"); + ecc = EncryptedClientContact::deserialize(btdc.require("x")); + } + catch (const std::exception& e) + { + log::error( + messages::logcat, "Error: failed to deserialize PublishClientContact contents: {}", e.what()); + throw; + } + + return {std::move(ecc), relay_order, is_relayed}; + } + } // namespace PublishClientContact + namespace PublishIntroMessage { inline constexpr auto INVALID_INTROSET = "INVALID INTROSET"sv; diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index e1aace4c87..e0fd1674ef 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -114,6 +114,7 @@ namespace llarp::path "close_exit", CloseExitMessage::sign_and_serialize(sk, std::move(tx_id)), std::move(func)); } + // TESTNET: TONUKE: bool Path::find_intro( const dht::Key_t& location, bool is_relayed, uint64_t order, std::function func) { @@ -121,6 +122,7 @@ namespace llarp::path "find_intro", FindIntroMessage::serialize(location, is_relayed, order), std::move(func)); } + // TESTNET: TONUKE: bool Path::publish_intro( const service::EncryptedIntroSet& introset, bool is_relayed, @@ -131,6 +133,20 @@ namespace llarp::path "publish_intro", PublishIntroMessage::serialize(introset, is_relayed, order), std::move(func)); } + bool Path::find_client_contact( + const dht::Key_t& location, bool is_relayed, uint64_t order, std::function func) + { + return send_path_control_message( + "find_cc", FindClientContact::serialize(location, order, is_relayed), std::move(func)); + } + + bool Path::publish_client_contact( + const EncryptedClientContact& ecc, bool is_relayed, uint64_t order, std::function func) + { + return send_path_control_message( + "publish_cc", PublishClientContact::serialize(ecc, order, is_relayed), std::move(func)); + } + bool Path::resolve_ons(std::string name, std::function func) { return send_path_control_message("resolve_ons", FindNameMessage::serialize(std::move(name)), std::move(func)); diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index a940c05092..2f16d9a0a4 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -102,13 +102,24 @@ namespace llarp bool resolve_ons(std::string name, std::function func = nullptr); - bool find_intro( + bool find_client_contact( + const dht::Key_t& location, bool is_relayed, uint64_t order, std::function func); + + bool publish_client_contact( + const EncryptedClientContact& ecc, + bool is_relayed = false, + uint64_t order = 0, + std::function func = nullptr); + + // TESTNET: // TONUKE: + [[deprecated]] bool find_intro( const dht::Key_t& location, bool is_relayed = false, uint64_t order = 0, std::function func = nullptr); - bool publish_intro( + // TESTNET: // TONUKE: + [[deprecated]] bool publish_intro( const service::EncryptedIntroSet& introset, bool is_relayed = false, uint64_t order = 0, diff --git a/llarp/service/identity.hpp b/llarp/service/identity.hpp index fc71051a6b..5ca01085f7 100644 --- a/llarp/service/identity.hpp +++ b/llarp/service/identity.hpp @@ -17,7 +17,7 @@ namespace llarp::service { Ed25519SecretKey _idkey; Ed25519SecretKey _enckey; - Ed25519Hash derivedSignKey; + Ed25519PrivateData derivedSignKey; uint64_t version = llarp::constants::proto_version; // public service info diff --git a/llarp/service/intro_set.cpp b/llarp/service/intro_set.cpp index f7e61a53e8..5d72c9e7eb 100644 --- a/llarp/service/intro_set.cpp +++ b/llarp/service/intro_set.cpp @@ -134,7 +134,7 @@ namespace llarp::service return now >= signed_at + path::DEFAULT_LIFETIME; } - bool EncryptedIntroSet::sign(const Ed25519Hash& k) + bool EncryptedIntroSet::sign(const Ed25519PrivateData& k) { signed_at = llarp::time_now_ms(); derived_signing_key = k.to_pubkey(); @@ -160,20 +160,6 @@ namespace llarp::service return crypto::verify(derived_signing_key, reinterpret_cast(bte.data()), bte.size(), sig); } - bool EncryptedIntroSet::verify(uint8_t* introset, size_t introset_size, uint8_t* key, uint8_t* sig) - { - return crypto::verify(key, introset, introset_size, sig); - } - - bool EncryptedIntroSet::verify(std::string introset, std::string key, std::string sig) - { - return crypto::verify( - reinterpret_cast(key.data()), - reinterpret_cast(introset.data()), - introset.size(), - reinterpret_cast(sig.data())); - } - nlohmann::json IntroSetOld::ExtractStatus() const { nlohmann::json obj{{"published", to_json(time_signed)}}; diff --git a/llarp/service/intro_set.hpp b/llarp/service/intro_set.hpp index e875400804..fb433ad79f 100644 --- a/llarp/service/intro_set.hpp +++ b/llarp/service/intro_set.hpp @@ -114,7 +114,7 @@ namespace llarp::service std::string nonce, std::string sig); - bool sign(const Ed25519Hash& k); + bool sign(const Ed25519PrivateData& k); bool is_expired(std::chrono::milliseconds now = time_now_ms()) const; @@ -127,10 +127,6 @@ namespace llarp::service /// verify signature and timestamp bool verify() 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); - // this constructor will throw if ::bt_decode fails static std::optional construct(std::string bt); diff --git a/llarp/util/buffer.hpp b/llarp/util/buffer.hpp index 3478dc3008..97efd6bbb6 100644 --- a/llarp/util/buffer.hpp +++ b/llarp/util/buffer.hpp @@ -3,7 +3,7 @@ #include "common.hpp" #include "mem.h" -#include +#include #include #include @@ -21,10 +21,16 @@ namespace llarp { + using const_cspan = oxenc::cspan; + using const_uspan = oxenc::uspan; + using const_span = oxenc::bspan; + + using cspan = std::span; using uspan = std::span; + using bspan = std::span; + using ustring = std::basic_string; using ustring_view = std::basic_string_view; - using bspan = std::span; using bstring = std::basic_string; using bstring_view = std::basic_string_view; From d236b46a1006508880c23f43d86db4f12215400f Mon Sep 17 00:00:00 2001 From: dr7ana Date: Tue, 22 Oct 2024 15:25:57 -0700 Subject: [PATCH 09/44] who? never heard of em --- daemon/lokinet.cpp | 7 - llarp/CMakeLists.txt | 27 +- llarp/address/address.hpp | 4 +- llarp/apple/context_wrapper.cpp | 2 - llarp/auth/auth.hpp | 2 +- llarp/config/config.cpp | 15 +- llarp/config/config.hpp | 1 - llarp/contact/client_contact.cpp | 13 - llarp/contact/client_contact.hpp | 1 - llarp/contact/contactdb.cpp | 32 +- llarp/contact/contactdb.hpp | 11 - llarp/{address => contact}/keys.cpp | 0 llarp/{address => contact}/keys.hpp | 0 llarp/contact/router_id.hpp | 2 +- llarp/{service/name.cpp => contact/sns.cpp} | 26 +- llarp/contact/sns.hpp | 93 ++++ llarp/{service => contact}/tag.cpp | 14 - llarp/{service => contact}/tag.hpp | 4 - llarp/crypto/crypto.cpp | 2 +- llarp/crypto/types.cpp | 2 +- llarp/dht/node.hpp | 17 +- llarp/dns/message.cpp | 26 -- llarp/dns/message.hpp | 2 - llarp/dns/question.hpp | 2 - llarp/dns/rr.hpp | 2 - llarp/endpoint_base.hpp | 185 -------- llarp/ev/loop.hpp | 1 - llarp/handlers/session.cpp | 167 +------ llarp/handlers/session.hpp | 18 +- llarp/handlers/tun.cpp | 3 +- llarp/handlers/tun.hpp | 21 - llarp/link/link_manager.cpp | 267 +----------- llarp/link/link_manager.hpp | 13 +- llarp/messages/common.hpp | 2 +- llarp/messages/dht.hpp | 28 -- llarp/net/interface_info.cpp | 9 - llarp/net/interface_info.hpp | 30 -- llarp/net/ip.cpp | 27 -- llarp/net/ip.hpp | 30 -- llarp/net/net.hpp | 25 +- llarp/net/net_int.cpp | 150 ------- llarp/net/net_int.hpp | 207 --------- llarp/path/path.cpp | 35 +- llarp/path/path.hpp | 25 +- llarp/path/path_handler.cpp | 42 +- llarp/path/path_handler.hpp | 25 +- llarp/router/route_poker.hpp | 2 - llarp/rpc/rpc_client.cpp | 6 +- llarp/rpc/rpc_client.hpp | 4 +- llarp/rpc/rpc_request_parser.hpp | 1 - llarp/service/identity.cpp | 94 ---- llarp/service/identity.hpp | 49 --- llarp/service/info.cpp | 94 ---- llarp/service/info.hpp | 68 --- llarp/service/intro.cpp | 107 ----- llarp/service/intro.hpp | 88 ---- llarp/service/intro_set.cpp | 433 ------------------- llarp/service/intro_set.hpp | 160 ------- llarp/service/name.hpp | 96 ---- llarp/service/types.cpp | 145 ------- llarp/service/types.hpp | 123 ------ llarp/session/session.cpp | 2 +- llarp/session/session.hpp | 2 +- llarp/vpn/egres_packet_router.hpp | 1 - llarp/vpn/linux.hpp | 22 +- test/service/test_llarp_service_identity.cpp | 3 - 66 files changed, 215 insertions(+), 2902 deletions(-) rename llarp/{address => contact}/keys.cpp (100%) rename llarp/{address => contact}/keys.hpp (100%) rename llarp/{service/name.cpp => contact/sns.cpp} (69%) create mode 100644 llarp/contact/sns.hpp rename llarp/{service => contact}/tag.cpp (53%) rename llarp/{service => contact}/tag.hpp (84%) delete mode 100644 llarp/endpoint_base.hpp delete mode 100644 llarp/net/interface_info.cpp delete mode 100644 llarp/net/interface_info.hpp delete mode 100644 llarp/net/ip.cpp delete mode 100644 llarp/net/ip.hpp delete mode 100644 llarp/net/net_int.cpp delete mode 100644 llarp/net/net_int.hpp delete mode 100644 llarp/service/identity.cpp delete mode 100644 llarp/service/identity.hpp delete mode 100644 llarp/service/info.cpp delete mode 100644 llarp/service/info.hpp delete mode 100644 llarp/service/intro.cpp delete mode 100644 llarp/service/intro.hpp delete mode 100644 llarp/service/intro_set.cpp delete mode 100644 llarp/service/intro_set.hpp delete mode 100644 llarp/service/name.hpp delete mode 100644 llarp/service/types.cpp delete mode 100644 llarp/service/types.hpp diff --git a/daemon/lokinet.cpp b/daemon/lokinet.cpp index c731abc853..7397ae7b5a 100644 --- a/daemon/lokinet.cpp +++ b/daemon/lokinet.cpp @@ -1,11 +1,9 @@ #include #include // for ensure_config -// #include #include #include #include #include -// #include #include #include @@ -14,14 +12,9 @@ #include #include -// #include -// #include #include -// #include #include -// #include #include -// #include #ifdef _WIN32 #include diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index f2a56e2734..6be549e3b3 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -19,8 +19,6 @@ lokinet_add_library(lokinet-cryptography # Functional objects use by lokinet-core and other libraries # needed by vpn/ router/ rpc/ handlers/ net/ link/ lokinet_add_library(lokinet-core-utils -# endpoint_base.cpp - auth/file_auth.cpp auth/rpc_auth.cpp auth/session_auth.cpp @@ -28,12 +26,6 @@ lokinet_add_library(lokinet-core-utils handlers/session.cpp handlers/tun.cpp - service/identity.cpp - service/info.cpp - service/intro.cpp # path - service/intro_set.cpp - service/name.cpp - vpn/egres_packet_router.cpp ) @@ -46,8 +38,6 @@ lokinet_add_library(lokinet-core router/router.cpp router/route_poker.cpp - - service/types.cpp session/session.cpp ) @@ -86,20 +76,25 @@ lokinet_add_library(lokinet-contact contact/contactdb.cpp + contact/keys.cpp + contact/relay_contact.cpp contact/relay_contact_local.cpp contact/relay_contact_remote.cpp contact/router_id.cpp + + contact/sns.cpp + + contact/tag.cpp ) # Addressing and event loop files used by lokinet-core and other libraries -# needed by rpc/ link/ service/ config/ path/ dht/ +# needed by rpc/ link/ config/ path/ dht/ lokinet_add_library(lokinet-addressing address/address.cpp address/ip_packet.cpp address/ip_range.cpp - address/keys.cpp address/utils.cpp ev/loop.cpp @@ -107,17 +102,15 @@ lokinet_add_library(lokinet-addressing ev/types.cpp ev/udp.cpp - net/ip.cpp - net/net_int.cpp +# net/ip.cpp +# net/net_int.cpp router_version.cpp # to be deleted shortly - - service/tag.cpp ) # lokinet-platform holds all platform specific code lokinet_add_library(lokinet-platform - net/interface_info.cpp +# net/interface_info.cpp vpn/packet_router.cpp vpn/platform.cpp ) diff --git a/llarp/address/address.hpp b/llarp/address/address.hpp index 465ad8b05c..ea11ab1fd6 100644 --- a/llarp/address/address.hpp +++ b/llarp/address/address.hpp @@ -1,10 +1,10 @@ #pragma once -#include "keys.hpp" #include "utils.hpp" +#include #include -#include +#include #include #include diff --git a/llarp/apple/context_wrapper.cpp b/llarp/apple/context_wrapper.cpp index 5c5f846640..a6ffd41c90 100644 --- a/llarp/apple/context_wrapper.cpp +++ b/llarp/apple/context_wrapper.cpp @@ -10,8 +10,6 @@ #include #include -// #include - #include #include #include diff --git a/llarp/auth/auth.hpp b/llarp/auth/auth.hpp index 86984d2965..0426fbd712 100644 --- a/llarp/auth/auth.hpp +++ b/llarp/auth/auth.hpp @@ -4,8 +4,8 @@ #include #include +#include #include -#include #include #include #include diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index e77a0d1bd2..631f36b471 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -5,8 +5,7 @@ #include #include -#include -#include +#include #include #include @@ -266,7 +265,7 @@ namespace llarp const auto addr = arg.substr(0, pos); auto auth = arg.substr(pos + 1); - if (service::is_valid_ons(addr)) + if (is_valid_ons(addr)) { ons_auth_tokens.emplace(std::move(addr), std::move(auth)); } @@ -333,7 +332,7 @@ namespace llarp if (pos != std::string::npos) arg = arg.substr(0, pos); - if (service::is_valid_ons(arg)) + if (is_valid_ons(arg)) ons_ranges.emplace(std::move(arg), std::move(*range)); else if (auto maybe_raddr = NetworkAddress::from_network_addr(arg); maybe_raddr) ranges.emplace(std::move(*maybe_raddr), std::move(*range)); @@ -662,7 +661,7 @@ namespace llarp if (pos != std::string::npos) arg = arg.substr(0, pos); - if (service::is_valid_ons(arg)) + if (is_valid_ons(arg)) _ons_ranges.emplace(std::move(arg), std::move(*range)); else if (auto maybe_raddr = NetworkAddress::from_network_addr(arg); maybe_raddr) _exit_ranges.emplace(std::move(*maybe_raddr), std::move(*range)); @@ -702,7 +701,7 @@ namespace llarp const auto addr = arg.substr(0, pos); auto auth = arg.substr(pos + 1); - if (service::is_valid_ons(addr)) + if (is_valid_ons(addr)) { ons_exit_auths.emplace(std::move(addr), std::move(auth)); } @@ -826,7 +825,7 @@ namespace llarp auto addr_arg = arg.substr(0, pos); auto ip_arg = arg.substr(pos + 1); - if (service::is_valid_ons(addr_arg)) + if (is_valid_ons(addr_arg)) throw std::invalid_argument{"`mapaddr` cannot take an ONS entry: {}"_format(arg)}; if (auto maybe_raddr = NetworkAddress::from_network_addr(std::move(addr_arg)); maybe_raddr) @@ -998,7 +997,7 @@ namespace llarp continue; } - if (service::is_valid_ons(*arg)) + if (is_valid_ons(*arg)) { log::warning(logcat, "{}: {}", addrmap_errorstr, "cannot accept ONS names!"); continue; diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index a55f491eb4..6e9903bea2 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff --git a/llarp/contact/client_contact.cpp b/llarp/contact/client_contact.cpp index d7ca939258..991bf3893f 100644 --- a/llarp/contact/client_contact.cpp +++ b/llarp/contact/client_contact.cpp @@ -89,19 +89,6 @@ namespace llarp return btdp.view().size(); } - // void ClientContact::bt_decode(std::string_view buf) - // { - // try - // { - // bt_decode(oxenc::bt_dict_consumer{buf}); - // } - // catch (const std::exception& e) - // { - // log::critical(logcat, "ClientContact deserialization failed: {}", e.what()); - // throw; - // } - // } - void ClientContact::bt_decode(oxenc::bt_dict_consumer&& btdc) { pubkey.from_string(btdc.require("a")); diff --git a/llarp/contact/client_contact.hpp b/llarp/contact/client_contact.hpp index 913264470c..17d7143932 100644 --- a/llarp/contact/client_contact.hpp +++ b/llarp/contact/client_contact.hpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include diff --git a/llarp/contact/contactdb.cpp b/llarp/contact/contactdb.cpp index 4ea1e79927..e1d09a436f 100644 --- a/llarp/contact/contactdb.cpp +++ b/llarp/contact/contactdb.cpp @@ -7,7 +7,7 @@ namespace llarp ContactDB::ContactDB(Router& r) : _router{r}, _local_key{dht::Key_t::derive_from_rid(r.local_rid())} { timer_keepalive = std::make_shared(0); - _introset_nodes = std::make_unique>(_local_key, llarp::randint); + _cc_nodes = std::make_unique>(_local_key, llarp::randint); } std::optional ContactDB::get_decrypted_cc(RouterID remote) const @@ -33,40 +33,12 @@ namespace llarp return enc; } - std::optional ContactDB::get_decrypted_introset(RouterID remote) const - { - std::optional ret = std::nullopt; - - if (auto encrypted = get_encrypted_introset(dht::Key_t::derive_from_rid(remote)); - auto intro = encrypted->decrypt(remote)) - ret = *intro; - - return ret; - } - - std::optional ContactDB::get_encrypted_introset(const dht::Key_t& key) const - { - std::optional enc = std::nullopt; - - auto& introsets = _introset_nodes->nodes; - - if (auto itr = introsets.find(key); itr != introsets.end() && not itr->second.introset.is_expired()) - enc = itr->second.introset; - - return enc; - } - nlohmann::json ContactDB::ExtractStatus() const { - nlohmann::json obj{{"services", _introset_nodes->ExtractStatus()}, {"local_key", _local_key.ToHex()}}; + nlohmann::json obj{{"known_client_intros", _cc_nodes->ExtractStatus()}, {"local_key", _local_key.ToHex()}}; return obj; } - void ContactDB::put_intro(service::EncryptedIntroSet enc) - { - _introset_nodes->put_node(std::move(enc)); - } - void ContactDB::put_cc(EncryptedClientContact enc) { _cc_nodes->put_node(enc); diff --git a/llarp/contact/contactdb.hpp b/llarp/contact/contactdb.hpp index c1bdaed57d..16cbd8c78a 100644 --- a/llarp/contact/contactdb.hpp +++ b/llarp/contact/contactdb.hpp @@ -20,9 +20,6 @@ namespace llarp Router& _router; const dht::Key_t _local_key; - // holds introsets for remote services - std::unique_ptr> _introset_nodes; - std::unique_ptr> _cc_nodes; public: @@ -32,18 +29,10 @@ namespace llarp std::optional get_encrypted_cc(const dht::Key_t& key) const; - std::optional get_decrypted_introset(RouterID remote) const; - - std::optional get_encrypted_introset(const dht::Key_t& key) const; - nlohmann::json ExtractStatus() const; - void put_intro(service::EncryptedIntroSet enc); - void put_cc(EncryptedClientContact enc); - dht::Bucket* services() const { return _introset_nodes.get(); } - Router* router() const { return &_router; } }; diff --git a/llarp/address/keys.cpp b/llarp/contact/keys.cpp similarity index 100% rename from llarp/address/keys.cpp rename to llarp/contact/keys.cpp diff --git a/llarp/address/keys.hpp b/llarp/contact/keys.hpp similarity index 100% rename from llarp/address/keys.hpp rename to llarp/contact/keys.hpp diff --git a/llarp/contact/router_id.hpp b/llarp/contact/router_id.hpp index a0318c92ce..862511408d 100644 --- a/llarp/contact/router_id.hpp +++ b/llarp/contact/router_id.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include diff --git a/llarp/service/name.cpp b/llarp/contact/sns.cpp similarity index 69% rename from llarp/service/name.cpp rename to llarp/contact/sns.cpp index 2a23c5916e..b84f0eeaa8 100644 --- a/llarp/service/name.cpp +++ b/llarp/contact/sns.cpp @@ -1,21 +1,21 @@ -#include "name.hpp" +#include "sns.hpp" #include #include -namespace llarp::service +namespace llarp { static auto logcat = llarp::log::Cat("ONSRecord"); - std::optional EncryptedONSRecord::construct(std::string bt) + std::optional EncryptedSNSRecord::construct(std::string bt) { - if (EncryptedONSRecord ret; ret.bt_decode(std::move(bt))) + if (EncryptedSNSRecord ret; ret.bt_decode(std::move(bt))) return ret; return std::nullopt; } - EncryptedONSRecord::EncryptedONSRecord(std::string bt) + EncryptedSNSRecord::EncryptedSNSRecord(std::string bt) { try { @@ -25,11 +25,11 @@ namespace llarp::service } catch (const std::exception& e) { - log::warning(logcat, "EncryptedONSRecord exception: {}", e.what()); + log::warning(logcat, "EncryptedSNSRecord exception: {}", e.what()); } } - bool EncryptedONSRecord::bt_decode(oxenc::bt_dict_consumer& btdc) + bool EncryptedSNSRecord::bt_decode(oxenc::bt_dict_consumer& btdc) { try { @@ -40,12 +40,12 @@ namespace llarp::service } catch (...) { - log::warning(logcat, "EncryptedONSRecord exception"); + log::warning(logcat, "EncryptedSNSRecord exception"); throw; } } - bool EncryptedONSRecord::bt_decode(std::string bt) + bool EncryptedSNSRecord::bt_decode(std::string bt) { try { @@ -54,12 +54,12 @@ namespace llarp::service } catch (...) { - log::warning(logcat, "EncryptedONSRecord exception"); + log::warning(logcat, "EncryptedSNSRecord exception"); return false; } } - std::string EncryptedONSRecord::bt_encode() const + std::string EncryptedSNSRecord::bt_encode() const { oxenc::bt_dict_producer btdp; @@ -69,7 +69,7 @@ namespace llarp::service return std::move(btdp).str(); } - std::optional EncryptedONSRecord::decrypt(std::string_view ons_name) const + std::optional EncryptedSNSRecord::decrypt(std::string_view ons_name) const { std::optional ret = std::nullopt; @@ -84,4 +84,4 @@ namespace llarp::service return ret; } -} // namespace llarp::service +} // namespace llarp diff --git a/llarp/contact/sns.hpp b/llarp/contact/sns.hpp new file mode 100644 index 0000000000..9ef99cb9df --- /dev/null +++ b/llarp/contact/sns.hpp @@ -0,0 +1,93 @@ +#pragma once + +#include +#include + +#include + +namespace llarp +{ + struct NetworkAddress; + + /** Holds an entire ONS Record returned from a succfessful request to the `lookup_name` endpoint. + When transmitted over the wire back to the calling instance, it is bt-encoded and the ONS hash + ('ciphertext') is decrypted using the ons_name. + + bt-encoded keys: + 'c' : ciphertext + 'n' : nonce + */ + struct EncryptedSNSRecord + { + private: + explicit EncryptedSNSRecord(std::string bt); + bool bt_decode(oxenc::bt_dict_consumer& btdc); + + public: + SymmNonce nonce; + std::string ciphertext; + + EncryptedSNSRecord() = default; + + static std::optional construct(std::string bt); + + std::string bt_encode() const; + + bool bt_decode(std::string bt); + + std::optional decrypt(std::string_view ons_name) const; + }; + + /// check if an ons name complies with the registration rules + inline bool is_valid_ons(std::string_view ons_name) + { + // make sure it ends with .loki because no fucking shit right? + if (not ons_name.ends_with(".loki")) + return false; + + // strip off .loki suffix + ons_name.remove_suffix(5); + + // ensure chars are sane + for (const auto ch : ons_name) + { + if (ch == '-') + continue; + if (ch == '.') + continue; + if (ch >= 'a' and ch <= 'z') + continue; + if (ch >= '0' and ch <= '9') + continue; + return false; + } + + // split into domain parts + const auto parts = split(ons_name, "."); + + // get root domain + const auto primaryName = parts[parts.size() - 1]; + constexpr size_t MaxNameLen = 32; + constexpr size_t MaxPunycodeNameLen = 63; + + // check against lns name blacklist + if (primaryName == "localhost") + return false; + if (primaryName == "loki") + return false; + if (primaryName == "snode") + return false; + // check for dashes + if (primaryName.find("-") == std::string_view::npos) + return primaryName.size() <= MaxNameLen; + // check for dashes and end or beginning + if (*primaryName.begin() == '-' or *(primaryName.end() - 1) == '-') + return false; + // check for punycode name length + if (primaryName.size() > MaxPunycodeNameLen) + return false; + // check for xn-- + return (primaryName[2] == '-' and primaryName[3] == '-') ? (primaryName[0] == 'x' and primaryName[1] == 'n') + : true; + } +} // namespace llarp diff --git a/llarp/service/tag.cpp b/llarp/contact/tag.cpp similarity index 53% rename from llarp/service/tag.cpp rename to llarp/contact/tag.cpp index 93185ba514..3e45c88502 100644 --- a/llarp/service/tag.cpp +++ b/llarp/contact/tag.cpp @@ -15,18 +15,4 @@ namespace llarp::service /// ensure we are in the fc00 range llarp::AlignedBuffer<16>::operator[](0) = 0xfc; } - - sockaddr_in6 SessionTag::to_v6() const - { - sockaddr_in6 saddr{}; - saddr.sin6_family = AF_INET6; - std::copy_n(data(), size(), saddr.sin6_addr.s6_addr); - return saddr; - } - - void SessionTag::from_v6(sockaddr_in6 saddr) - { - std::copy_n(saddr.sin6_addr.s6_addr, size(), data()); - } - } // namespace llarp::service diff --git a/llarp/service/tag.hpp b/llarp/contact/tag.hpp similarity index 84% rename from llarp/service/tag.hpp rename to llarp/contact/tag.hpp index 7f2b70cba6..60d65cac03 100644 --- a/llarp/service/tag.hpp +++ b/llarp/contact/tag.hpp @@ -12,10 +12,6 @@ namespace llarp::service static SessionTag make_random(); void Randomize() override; - - // DISCUSS: TONUKE: maybe these...? - sockaddr_in6 to_v6() const; - void from_v6(sockaddr_in6 saddr); }; } // namespace llarp::service diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index 76104c8f47..10bc5a09be 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -1,6 +1,6 @@ #include "crypto.hpp" -#include +#include #include #include diff --git a/llarp/crypto/types.cpp b/llarp/crypto/types.cpp index f295e09af6..c53a2d0c20 100644 --- a/llarp/crypto/types.cpp +++ b/llarp/crypto/types.cpp @@ -1,6 +1,6 @@ #include "types.hpp" -#include +#include #include #include #include diff --git a/llarp/dht/node.hpp b/llarp/dht/node.hpp index 265dd9502e..2326d15cff 100644 --- a/llarp/dht/node.hpp +++ b/llarp/dht/node.hpp @@ -4,7 +4,6 @@ #include #include -#include #include @@ -33,20 +32,8 @@ namespace llarp::dht CCNode(EncryptedClientContact other) : client_contact{std::move(other)}, ID{client_contact.blinded_pubkey} {} - bool operator<(const CCNode& other) const { return client_contact.signed_at < other.client_contact.signed_at; } - }; - - struct ISNode - { - service::EncryptedIntroSet introset; - Key_t ID; + nlohmann::json ExtractStatus() const { return nlohmann::json{{"key", client_contact.key()}}; } - ISNode() { ID.zero(); } - - ISNode(service::EncryptedIntroSet other) : introset(std::move(other)), ID{introset.derived_signing_key} {} - - nlohmann::json ExtractStatus() const { return introset.ExtractStatus(); } - - bool operator<(const ISNode& other) const { return introset.signed_at < other.introset.signed_at; } + bool operator<(const CCNode& other) const { return client_contact.signed_at < other.client_contact.signed_at; } }; } // namespace llarp::dht diff --git a/llarp/dns/message.cpp b/llarp/dns/message.cpp index e9b21dd299..f0c4b18453 100644 --- a/llarp/dns/message.cpp +++ b/llarp/dns/message.cpp @@ -4,7 +4,6 @@ #include "srv_data.hpp" #include -#include #include #include @@ -178,31 +177,6 @@ namespace llarp::dns return setbits | flags_QR | flags_AA | flags_RA; } - void Message::add_IN_reply(llarp::huint128_t ip, bool isV6, RR_TTL_t ttl) - { - 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) - { - 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)); - } - } - void Message::add_reply(std::string name, RR_TTL_t ttl) { if (questions.size()) diff --git a/llarp/dns/message.hpp b/llarp/dns/message.hpp index 6e02538bdc..e489111edb 100644 --- a/llarp/dns/message.hpp +++ b/llarp/dns/message.hpp @@ -68,8 +68,6 @@ namespace llarp void add_CNAME_reply(std::string name, RR_TTL_t ttl = 1); - void add_IN_reply(llarp::huint128_t addr, bool isV6, RR_TTL_t ttl = 1); - void add_reply(std::string name, RR_TTL_t ttl = 1); void add_srv_reply(std::vector records, RR_TTL_t ttl = 1); diff --git a/llarp/dns/question.hpp b/llarp/dns/question.hpp index dbfa6f13ed..a087d2afb9 100644 --- a/llarp/dns/question.hpp +++ b/llarp/dns/question.hpp @@ -3,8 +3,6 @@ #include "name.hpp" #include "serialize.hpp" -#include - namespace llarp::dns { using QType_t = uint16_t; diff --git a/llarp/dns/rr.hpp b/llarp/dns/rr.hpp index 662500703f..be7e5488b0 100644 --- a/llarp/dns/rr.hpp +++ b/llarp/dns/rr.hpp @@ -3,8 +3,6 @@ #include "name.hpp" #include "serialize.hpp" -#include - #include #include diff --git a/llarp/endpoint_base.hpp b/llarp/endpoint_base.hpp deleted file mode 100644 index ab1839bbbb..0000000000 --- a/llarp/endpoint_base.hpp +++ /dev/null @@ -1,185 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace llarp -{ - namespace dns - { - class Server; - } - - /** TODO: - - add protected QUICTunnel accessor - */ - - template - class EndpointBase - { - protected: - std::unordered_set _srv_records; - - session_map _sessions; - - public: - bool should_publish_introset{true}; - - virtual ~EndpointBase() = default; - - std::shared_ptr get_session(const service::SessionTag& tag) const - { - return _sessions.get_session(tag); - } - - std::shared_ptr get_session(const net_addr_t& remote) const { return _sessions.get_session(remote); } - - /// add an srv record to this endpoint's descriptor - virtual void put_srv_record(dns::SRVData srv) - { - if (auto result = _srv_records.insert(std::move(srv)); result.second) - { - srv_records_changed(); - } - } - - /// get dns server if we have on on this endpoint - virtual std::shared_ptr DNS() const { return nullptr; }; - - /// called when srv data changes in some way - virtual void srv_records_changed() = 0; - - /// Removes one SRV record that returns true given a filter function. Returns true if one - /// SRV record was removed, false otherwise - bool delete_srv_record_conditional(std::function filter) - { - for (auto itr = _srv_records.begin(); itr != _srv_records.end(); ++itr) - { - if (filter(*itr)) - { - itr = _srv_records.erase(itr); - srv_records_changed(); - return true; - } - } - - return false; - } - - /// Removes up to `n` (or exactly `n` if the optional third parameter is passed true) SRV - /// records that return true given a filter function. Returns true if up to/exactly `n` were - /// removed (depending on the third parameter), false otherwise - bool delete_n_srv_records_conditional( - size_t n, std::function filter, bool exact = false) - - { - // `n` cannot be 0, or we have an insufficient amount of SRV records to return exactly `n` - if (n == 0 or (exact and _srv_records.size() < n)) - return false; - - bool notify{false}; - size_t num_deleted{0}; - std::unordered_set _copy{_srv_records}; - - for (auto itr = _copy.begin(); itr != _copy.end(); ++itr) - { - // `notify` - // - if (notify |= filter(*itr); notify) - { - num_deleted += 1; - itr = _copy.erase(itr); - - // We return early from the for-loop in one of two cases: - // 1) exact = true, num_deleted = n - // - Return true always - // 2) exact = false, num_deleted = n - // - Return true always - if (num_deleted == n) - { - _srv_records.swap(_copy); - srv_records_changed(); - return notify; - } - - continue; - } - } - - /** We only exit the for-loop in one of two cases: - 1) exact = true, num_deleted < n - - In this case, we return false always - 2) exact = false - - In this case, we return true if num_deleted > 0 - - (num_deleted > 0) iff (notify == true), so we can treat them as identical - - exact notify num_deleted < n num_deleted > 0 return - T T T T F - T F T F F - F T T T T - F F T F F - */ - - // Handles the first two rows of the above truth table - if (exact) - return false; - - // Handles the last two rows of the above truth table - if (notify ^= exact; notify) - { - _srv_records.swap(_copy); - srv_records_changed(); - } - - return notify; - } - - /// Removes all SRV records that return true given a filter function, indiscriminate of - /// number - bool delete_all_srv_records_conditional(std::function filter) - { - bool notify{false}; - - for (auto itr = _srv_records.begin(); itr != _srv_records.end(); ++itr) - { - if (notify |= filter(*itr); notify) - { - itr = _srv_records.erase(itr); - continue; - } - } - - if (notify) - srv_records_changed(); - - return notify; - } - - /// get copy of all srv records - std::set srv_records() const { return {_srv_records.begin(), _srv_records.end()}; } - - /// Gets the local address for the given endpoint, service or exit node - virtual oxen::quic::Address local_address() const = 0; - - virtual const std::shared_ptr& loop() = 0; - - // virtual void send_to(service::SessionTag tag, std::string payload) = 0; - }; - -} // namespace llarp diff --git a/llarp/ev/loop.hpp b/llarp/ev/loop.hpp index c9b1212acb..3d297508ac 100644 --- a/llarp/ev/loop.hpp +++ b/llarp/ev/loop.hpp @@ -3,7 +3,6 @@ #include "types.hpp" #include -#include #include #include #include diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index 0106cb55f9..d8a153e5cb 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -210,7 +210,7 @@ namespace llarp::handlers void SessionEndpoint::resolve_ons(std::string ons, std::function)> func) { - if (not service::is_valid_ons(ons)) + if (not is_valid_ons(ons)) { log::debug(logcat, "Invalid ONS name ({}) queried for lookup", ons); return func(std::nullopt); @@ -219,8 +219,7 @@ namespace llarp::handlers log::debug(logcat, "Looking up ONS name {}", ons); auto response_handler = [ons_name = ons, hook = std::move(func)](std::string response) { - if (auto record = service::EncryptedONSRecord::construct(response); - auto client_addr = record->decrypt(ons_name)) + if (auto record = EncryptedSNSRecord::construct(response); auto client_addr = record->decrypt(ons_name)) { return hook(std::move(client_addr)); } @@ -308,59 +307,6 @@ namespace llarp::handlers } } - void SessionEndpoint::lookup_intro( - RouterID remote, bool is_relayed, uint64_t order, std::function)> func) - { - auto remote_key = dht::Key_t::derive_from_rid(remote); - - if (auto maybe_intro = _router.contact_db().get_decrypted_introset(remote)) - { - log::debug(logcat, "Decrypted introset for remote (rid:{}) found locally", remote); - return func(std::move(maybe_intro)); - } - - log::debug(logcat, "Looking up introset for remote (rid:{})", remote); - - auto response_handler = [this, remote, hook = std::move(func)](std::string response) mutable { - if (auto encrypted = service::EncryptedIntroSet::construct(response); - auto intro = encrypted->decrypt(remote)) - { - log::debug(logcat, "Storing introset for remote (rid:{})", remote); - _router.contact_db().put_intro(std::move(*encrypted)); - return hook(std::move(intro)); - } - - std::optional status = std::nullopt; - - try - { - oxenc::bt_dict_consumer btdc{response}; - - if (auto s = btdc.maybe(messages::STATUS_KEY)) - status = s; - } - catch (...) - { - log::warning(logcat, "Exception caught parsing 'find_intro' response!"); - } - - log::warning(logcat, "Call to endpoint 'find_intro' failed -- status:{}", status.value_or("")); - hook(std::nullopt); - }; - - { - Lock_t l{paths_mutex}; - - for (const auto& [rid, path] : _paths) - { - log::info( - logcat, "Querying pivot (rid:{}) for introset lookup target (rid:{})", path->pivot_rid(), remote); - - path->find_intro(remote_key, is_relayed, order, response_handler); - } - } - } - void SessionEndpoint::_localcc_update_fail() { log::warning( @@ -395,65 +341,6 @@ namespace llarp::handlers } } - /** Introset publishing: - - When a local service or exit node publishes an introset, it is also sent along the path currently used - for that session - */ - void SessionEndpoint::regen_and_publish_introset() - { - const auto now = llarp::time_now_ms(); - - service::intro_que_old _path_intros = get_recent_path_intros(); - - if (_path_intros.empty()) - { - log::warning(logcat, "Failed to get enough valid path introductions to publish introset!"); - return build_more(1); - } - - auto& intro_protos = _local_introset.supported_protocols; - intro_protos.clear(); - - if (_router.using_tun_if()) - { - intro_protos.push_back(_is_v4 ? service::ProtocolType::IPV4 : service::ProtocolType::IPV6); - - if (_is_exit_node) - { - intro_protos.push_back(service::ProtocolType::EXIT); - _local_introset.exit_policy = _exit_policy; - _local_introset._routed_ranges = _routed_ranges; - } - } - - intro_protos.push_back(service::ProtocolType::TCP2QUIC); - - auto& intros = _local_introset.intros; - intros.clear(); - - auto n_needed = num_paths_desired; - - while (--n_needed) - { - intros.emplace(_path_intros.top()); - _path_intros.pop(); - } - - // We already check that path_intros is not empty, so we can assert here - assert(not intros.empty()); - - // TESTNET: TODO: change to key_manager method - if (auto maybe_encrypted = _identity.encrypt_and_sign_introset(_local_introset, now)) - { - if (publish_introset(*maybe_encrypted)) - log::debug(logcat, "Successfully republished encrypted introset"); - else - log::warning(logcat, "Failed to republish encrypted introset!"); - } - else - log::warning(logcat, "Failed to encrypt and sign introset!"); - } - bool SessionEndpoint::validate(const NetworkAddress& remote, std::optional maybe_auth) { bool ret{true}; @@ -529,24 +416,6 @@ namespace llarp::handlers return ret; } - bool SessionEndpoint::publish_introset(const service::EncryptedIntroSet& introset) - { - bool ret{true}; - - { - Lock_t l{paths_mutex}; - - for (const auto& [rid, path] : _paths) - { - log::debug(logcat, "Publishing introset to pivot {}", path->pivot_rid()); - - ret += path->publish_intro(introset, true); - } - } - - return ret; - } - std::optional SessionEndpoint::fetch_auth_token(const NetworkAddress& remote) const { std::optional ret = std::nullopt; @@ -607,7 +476,7 @@ namespace llarp::handlers } void SessionEndpoint::_make_session_path( - service::IntroductionSet_old intros, NetworkAddress remote, on_session_init_hook cb, bool is_exit) + intro_set intros, NetworkAddress remote, on_session_init_hook cb, bool is_exit) { // we can recurse through this function as we remove the first pivot of the set of introductions every // invocation @@ -619,14 +488,12 @@ namespace llarp::handlers } auto intro = intros.extract(intros.begin()).value(); - auto pivot = intro.pivot_router; + auto& pivot = intro.pivot_rid; - // DISCUSS: we don't share paths, but if every successful path-build is logged in PathContext, we are - // effectively sharing across all path-building objects...? - if (auto path_ptr = _router.path_context()->get_path(intro.pivot_hop_id)) + if (auto path = _router.path_context()->get_path(intro.pivot_hid)) { - log::info(logcat, "Found path to pivot (hopid: {}); initiating session!", intro.pivot_hop_id); - return _make_session(std::move(remote), std::move(path_ptr), std::move(cb), is_exit); + log::info(logcat, "Found path to pivot (hopid: {}); initiating session!", intro.pivot_hid); + return _make_session(std::move(remote), std::move(path), std::move(cb), is_exit); } log::info(logcat, "Initiating session path-build to remote:{} via pivot:{}", remote, pivot); @@ -694,31 +561,25 @@ namespace llarp::handlers if (is_exit and not remote.is_client()) throw std::runtime_error{"Cannot initiate exit session to remote service node!"}; - auto counter = std::make_shared(path::DEFAULT_PATHS_HELD); - - // TESTNET: TODO: + auto counter = std::make_shared(num_paths_desired); _router.loop()->call([this, remote, handler = std::move(cb), is_exit, counter]() mutable { - lookup_intro( + lookup_client_intro( remote.router_id(), false, 0, - [this, remote, hook = std::move(handler), is_exit, counter]( - std::optional intro) mutable { - // already have a successful return + [this, remote, hook = std::move(handler), is_exit, counter](std::optional cc) { if (*counter == 0) return; - if (intro) + if (cc) { *counter = 0; - log::info(logcat, "Session initiation returned successful 'lookup_intro'..."); - _make_session_path(std::move(intro->intros), remote, std::move(hook), is_exit); + log::info(logcat, "Session initiation returned successful 'lookup_client_intro'..."); + _make_session_path(std::move(cc->intros), remote, std::move(hook), is_exit); } else if (--*counter == 0) - { - log::warning(logcat, "Failed to initiate session at 'lookup_intro' (target:{})", remote); - } + log::warning(logcat, "Failed to initiate session at 'lookup_client_intro' (target:{})", remote); }); }); diff --git a/llarp/handlers/session.hpp b/llarp/handlers/session.hpp index af00d062e8..4b3dbeaadc 100644 --- a/llarp/handlers/session.hpp +++ b/llarp/handlers/session.hpp @@ -4,7 +4,6 @@ #include #include #include -#include #include namespace llarp @@ -34,9 +33,6 @@ namespace llarp ClientContact client_contact; // TODO: TESTNET: replacement for service::Introset - service::Identity _identity; // TODO: TESTNET: move responsibilities to KeyManager, delete - service::IntroSetOld _local_introset; // TODO: TESTNET: remove with CC impl - std::shared_ptr _cc_publisher; // auth tokens for making outbound sessions @@ -119,12 +115,8 @@ namespace llarp void start_tickers(); - void regen_and_publish_introset(); - bool publish_client_contact(const EncryptedClientContact& ecc); - bool publish_introset(const service::EncryptedIntroSet& introset); - // SessionEndpoint can use either a whitelist or a static auth token list to validate incomininbg requests // to initiate a session bool validate(const NetworkAddress& remote, std::optional maybe_auth = std::nullopt); @@ -144,13 +136,6 @@ namespace llarp uint64_t order, std::function)> func); - // TESTNET: // TONUKE: - void lookup_intro( - RouterID remote, - bool is_relayed, - uint64_t order, - std::function)> func); - // resolves any config mappings that parsed ONS addresses to their pubkey network address void resolve_ons_mappings(); @@ -188,8 +173,7 @@ namespace llarp bool _initiate_session(NetworkAddress remote, on_session_init_hook cb, bool is_exit = false); - void _make_session_path( - service::IntroductionSet_old intros, NetworkAddress remote, on_session_init_hook cb, bool is_exit); + void _make_session_path(intro_set intros, NetworkAddress remote, on_session_init_hook cb, bool is_exit); void _make_session( NetworkAddress remote, std::shared_ptr path, on_session_init_hook cb, bool is_exit); diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 25b9e11a48..895927baa9 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -9,13 +9,12 @@ #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 43dfdd4200..cdd38269c9 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -3,9 +3,7 @@ #include #include #include -#include #include -#include #include #include #include @@ -167,25 +165,6 @@ namespace llarp::handlers bool obtain_src_for_remote(const NetworkAddress& remote, ip_v& src, bool use_ipv4); void send_packet_to_net_if(IPPacket&& pkt); - - template - void send_dns_reply( - Addr_t addr, - Endpoint_t ctx, - std::shared_ptr query, - std::function reply, - bool sendIPv6) - { - if (ctx) - { - huint128_t ip = get_ip_for_addr(addr); - query->answers.clear(); - query->add_IN_reply(ip, sendIPv6); - } - else - query->add_nx_reply(); - reply(*query); - } }; } // namespace llarp::handlers diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index f01787887e..a70eb5fc1b 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1076,8 +1076,7 @@ namespace llarp _router.rpc_client()->lookup_ons_hash( name_hash, - [respond = - std::move(respond)]([[maybe_unused]] std::optional maybe_enc) mutable { + [respond = std::move(respond)]([[maybe_unused]] std::optional maybe_enc) mutable { if (maybe_enc) respond(maybe_enc->bt_encode()); else @@ -1085,49 +1084,6 @@ namespace llarp }); } - void LinkManager::handle_resolve_ons_response(oxen::quic::message m) - { - if (m.timed_out) - { - log::info(logcat, "FindNameMessage request timed out!"); - return; - } - - std::string payload; - - try - { - oxenc::bt_dict_consumer btdc{m.body()}; - payload = btdc.require(m ? "E" : messages::STATUS_KEY); - } - catch (const std::exception& e) - { - log::warning(logcat, "Exception: {}", e.what()); - return; - } - - if (m) - { - // TODO: wtf - } - else - { - if (payload == "ERROR") - { - log::info(logcat, "FindNameMessage failed with unkown error!"); - - // resend? - } - else if (payload == FindNameMessage::NOT_FOUND) - { - log::info(logcat, "FindNameMessage failed with unkown error!"); - // what to do here? - } - else - log::info(logcat, "FindNameMessage failed with unkown error!"); - } - } - void LinkManager::handle_publish_cc(std::string_view body, std::function respond) { EncryptedClientContact enc; @@ -1221,114 +1177,6 @@ namespace llarp } } - // TONUKE: this - void LinkManager::handle_publish_intro(std::string_view body, std::function respond) - { - service::EncryptedIntroSet enc; - std::string introset; - uint64_t is_relayed, relay_order; - - try - { - oxenc::bt_dict_consumer btdc_a{body}; - - introset = btdc_a.require("I"); - relay_order = btdc_a.require("O"); - is_relayed = btdc_a.require("R"); - - enc = *service::EncryptedIntroSet::construct(std::move(introset)); - } - catch (const std::exception& e) - { - log::warning(logcat, "Exception: {}", e.what()); - respond(messages::ERROR_RESPONSE); - return; - } - - const auto addr = dht::Key_t{reinterpret_cast(enc.derived_signing_key.data())}; - const auto local_key = _router.rc().router_id(); - - if (not enc.verify()) - { - log::error(logcat, "Received PublishIntroMessage with invalid introset: {}", introset); - respond(serialize_response({{messages::STATUS_KEY, PublishIntroMessage::INVALID_INTROSET}})); - return; - } - - auto closest_rcs = _router.node_db()->find_many_closest_to(addr, path::DEFAULT_PATHS_HELD); - - if (closest_rcs.size() != path::DEFAULT_PATHS_HELD) - { - log::error(logcat, "Received PublishIntroMessage but only know {} nodes", closest_rcs.size()); - respond(serialize_response({{messages::STATUS_KEY, PublishIntroMessage::INSUFFICIENT}})); - return; - } - - if (is_relayed) - { - if (relay_order >= path::DEFAULT_PATHS_HELD) - { - log::error(logcat, "Received PublishIntroMessage with invalid relay order: {}", relay_order); - respond(serialize_response({{messages::STATUS_KEY, PublishIntroMessage::INVALID_ORDER}})); - return; - } - - log::info(logcat, "Relaying PublishIntroMessage for {}", addr); - - const auto& peer_rc = closest_rcs[relay_order]; - const auto& peer_key = peer_rc.router_id(); - - if (peer_key == local_key) - { - log::info( - logcat, - "Received PublishIntroMessage in which we are peer index {}.. storing introset", - relay_order); - - _router.contact_db().put_intro(std::move(enc)); - respond(messages::OK_RESPONSE); - } - else - { - log::info(logcat, "Received PublishIntroMessage; propagating to peer index {}", relay_order); - - send_control_message( - peer_key, - "publish_intro", - PublishIntroMessage::serialize(enc, relay_order, is_relayed), - [respond = std::move(respond)](oxen::quic::message m) mutable { - if (m.timed_out) - return; // drop if timed out; requester will have timed out as well - respond(m.body_str()); - }); - } - - return; - } - - int rc_index = -1, index = 0; - - for (const auto& rc : closest_rcs) - { - if (rc.router_id() == local_key) - { - rc_index = index; - break; - } - ++index; - } - - if (rc_index >= 0) - { - log::info(logcat, "Received PublishIntroMessage for {}; we are candidate {}", addr, relay_order); - - _router.contact_db().put_intro(std::move(enc)); - respond(messages::OK_RESPONSE); - } - else - log::warning(logcat, "Received non-relayed PublishIntroMessage from {}; we are not the candidate", addr); - } - void LinkManager::handle_find_cc(std::string_view body, std::function respond) { dht::Key_t dht_key; @@ -1395,119 +1243,6 @@ namespace llarp } } - void LinkManager::handle_find_intro(std::string_view body, std::function respond) - { - ustring location; - uint64_t relay_order, is_relayed; - - try - { - oxenc::bt_dict_consumer btdc{body}; - - relay_order = btdc.require("O"); - is_relayed = btdc.require("R"); - location = btdc.require("S"); - } - catch (const std::exception& e) - { - log::warning(logcat, "Exception: {}", e.what()); - respond(messages::ERROR_RESPONSE); - return; - } - - const auto addr = dht::Key_t{location.data()}; - - auto closest_rcs = _router.node_db()->find_many_closest_to(addr, path::DEFAULT_PATHS_HELD); - - if (closest_rcs.size() != path::DEFAULT_PATHS_HELD) - { - log::error(logcat, "Received FindIntroMessage but only know {} nodes", closest_rcs.size()); - respond(serialize_response({{messages::STATUS_KEY, FindIntroMessage::INSUFFICIENT_NODES}})); - return; - } - - if (is_relayed) - { - if (relay_order >= path::DEFAULT_PATHS_HELD) - { - log::warning(logcat, "Received FindIntroMessage with invalid relay order: {}", relay_order); - respond(serialize_response({{messages::STATUS_KEY, FindIntroMessage::INVALID_ORDER}})); - return; - } - - log::info(logcat, "Relaying FindIntroMessage for {}", addr); - - const auto& peer_rc = closest_rcs[relay_order]; - const auto& peer_key = peer_rc.router_id(); - - send_control_message( - peer_key, - "find_intro", - FindIntroMessage::serialize(addr, is_relayed, relay_order), - [respond = std::move(respond)](oxen::quic::message relay_response) mutable { - if (relay_response) - log::info( - logcat, - "Relayed FindIntroMessage returned successful response; transmitting " - "to initial " - "requester"); - else if (relay_response.timed_out) - log::critical(logcat, "Relayed FindIntroMessage timed out! Notifying initial requester"); - else - log::critical(logcat, "Relayed FindIntroMessage failed! Notifying initial requester"); - - respond(relay_response.body_str()); - }); - } - else - { - if (auto maybe_intro = _router.contact_db().get_encrypted_introset(addr)) - respond(serialize_response({{"INTROSET", maybe_intro->bt_encode()}})); - else - { - log::warning(logcat, "Received FindIntroMessage with relayed == false and no local introset entry"); - respond(serialize_response({{messages::STATUS_KEY, FindIntroMessage::NOT_FOUND}})); - } - } - } - - // TONUKE: - void LinkManager::handle_find_intro_response(oxen::quic::message m) - { - if (m.timed_out) - { - log::info(logcat, "FindIntroMessage timed out!"); - return; - } - - // std::string payload; - - // try - // { - // oxenc::bt_dict_consumer btdc{m.body()}; - // payload = btdc.require((m) ? "INTROSET" : messages::STATUS_KEY); - // } - // catch (const std::exception& e) - // { - // log::warning(logcat, "Exception: {}", e.what()); - // return; - // } - - // // success case, neither timed out nor errored - // if (m) - // { - // if (auto enc = service::EncryptedIntroSet::construct(payload)) - // { - // _router.contact_db().put_intro(std::move(*enc)); - // } - // } - // else - // { - // log::info(logcat, "FindIntroMessage failed with error: {}", payload); - // // Do something smart here probably - // } - } - void LinkManager::handle_path_build(oxen::quic::message m, const RouterID& from) { if (!_router.path_context()->is_transit_allowed()) diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 1e5d6680cd..cb6c8be5d6 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -253,9 +253,7 @@ namespace llarp private: // DHT messages - void handle_resolve_ons(std::string_view body, std::function respond); // relay - void handle_find_intro(std::string_view body, std::function respond); // relay - void handle_publish_intro(std::string_view body, std::function respond); // relay + void handle_resolve_ons(std::string_view body, std::function respond); // relay // TESTNET: // NEW CLIENT_CONTACT HANDLERS void handle_find_cc(std::string_view body, std::function respond); @@ -287,19 +285,14 @@ namespace llarp void (LinkManager::*)(std::string_view body, std::function respond)> path_requests = { {"resolve_ons"sv, &LinkManager::handle_resolve_ons}, - {"publish_intro"sv, &LinkManager::handle_publish_intro}, - {"find_intro"sv, &LinkManager::handle_find_intro}}; + {"publish_intro"sv, &LinkManager::handle_publish_cc}, + {"find_intro"sv, &LinkManager::handle_find_cc}}; // Path relaying void handle_path_control(oxen::quic::message, const RouterID& from); void handle_inner_request(oxen::quic::message m, std::string payload, std::shared_ptr hop); - // DHT responses - void handle_resolve_ons_response(oxen::quic::message); - void handle_find_intro_response(oxen::quic::message); - // void handle_publish_intro_response(oxen::quic::message); - // Path responses void handle_path_latency_response(oxen::quic::message); void handle_path_transfer_response(oxen::quic::message); diff --git a/llarp/messages/common.hpp b/llarp/messages/common.hpp index bfbe5b5aad..48f37d01a2 100644 --- a/llarp/messages/common.hpp +++ b/llarp/messages/common.hpp @@ -1,10 +1,10 @@ #pragma once #include +#include #include #include #include -#include #include #include diff --git a/llarp/messages/dht.hpp b/llarp/messages/dht.hpp index 5ad370fb22..6c6e943d15 100644 --- a/llarp/messages/dht.hpp +++ b/llarp/messages/dht.hpp @@ -3,7 +3,6 @@ #include "common.hpp" #include -#include namespace llarp { @@ -170,31 +169,4 @@ namespace llarp return {std::move(ecc), relay_order, is_relayed}; } } // namespace PublishClientContact - - namespace PublishIntroMessage - { - inline constexpr auto INVALID_INTROSET = "INVALID INTROSET"sv; - inline constexpr auto EXPIRED = "EXPIRED INTROSET"sv; - inline constexpr auto INSUFFICIENT = "INSUFFICIENT NODES"sv; - inline constexpr auto INVALID_ORDER = "INVALID ORDER"sv; - - inline static std::string serialize( - const service::EncryptedIntroSet& introset, uint64_t relay_order, uint64_t is_relayed) - { - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("I", introset.bt_encode()); - btdp.append("O", relay_order); - btdp.append("R", is_relayed); - } - catch (...) - { - log::error(messages::logcat, "Error: FindNameMessage failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - } // namespace PublishIntroMessage } // namespace llarp diff --git a/llarp/net/interface_info.cpp b/llarp/net/interface_info.cpp deleted file mode 100644 index 542851deb1..0000000000 --- a/llarp/net/interface_info.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "interface_info.hpp" - -namespace llarp::net -{ - std::string InterfaceInfo::to_string() const - { - return fmt::format("{}[i={}; addrs={}]", name, index, fmt::join(addrs, ",")); - } -} // namespace llarp::net diff --git a/llarp/net/interface_info.hpp b/llarp/net/interface_info.hpp deleted file mode 100644 index b9d5488560..0000000000 --- a/llarp/net/interface_info.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include -#include - -#include -#include -#include - -namespace llarp::net -{ - /// info about a network interface lokinet does not own - struct InterfaceInfo - { - private: - public: - // TODO: is this needed? - /// a gateway we can use if it exists - std::optional _gateway; - - /// human readable name of interface - std::string name; - /// interface's index - int index; - /// the addresses owned by this interface - std::vector addrs; - - std::string to_string() const; - }; -} // namespace llarp::net diff --git a/llarp/net/ip.cpp b/llarp/net/ip.cpp deleted file mode 100644 index bd3609cd54..0000000000 --- a/llarp/net/ip.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "ip.hpp" - -#include - -namespace llarp::net -{ - huint128_t In6ToHUInt(in6_addr addr) - { - uint8_t* ptr = reinterpret_cast(addr.s6_addr); - uint128_t x{0}; - for (int i = 0; i < 16; i++) - { - x <<= 8; - x |= ptr[i]; - } - return huint128_t{x}; - } - - in6_addr HUIntToIn6(huint128_t x) - { - in6_addr addr; - auto i = ntoh128(x.h); - std::memcpy(&addr, &i, 16); - return addr; - } - -} // namespace llarp::net diff --git a/llarp/net/ip.hpp b/llarp/net/ip.hpp deleted file mode 100644 index 0638fd51fc..0000000000 --- a/llarp/net/ip.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "net_int.hpp" - -#include - -namespace llarp::net -{ - huint128_t In6ToHUInt(in6_addr addr); - - in6_addr HUIntToIn6(huint128_t x); - - constexpr huint128_t ExpandV4(huint32_t x) - { - return huint128_t{0x0000'ffff'0000'0000UL} | huint128_t{x.h}; - } - - constexpr huint128_t ExpandV4Lan(huint32_t x) - { - return huint128_t{uint128_t{0xfd00'0000'0000'0000UL, 0UL}} | huint128_t{x.h}; - } - - constexpr huint32_t TruncateV6(huint128_t x) - { - huint32_t ret = {0}; - ret.h = (uint32_t)(x.h & 0x0000'0000'ffff'ffffUL); - return ret; - } - -} // namespace llarp::net diff --git a/llarp/net/net.hpp b/llarp/net/net.hpp index 763d0c4ade..dea007acb7 100644 --- a/llarp/net/net.hpp +++ b/llarp/net/net.hpp @@ -1,8 +1,6 @@ #pragma once -#include "interface_info.hpp" #include "net.h" -#include "net_int.hpp" #include "uint128.hpp" #include @@ -44,6 +42,29 @@ namespace llarp namespace net { + + /// info about a network interface lokinet does not own + struct InterfaceInfo + { + private: + public: + // TODO: is this needed? + /// a gateway we can use if it exists + std::optional _gateway; + + /// human readable name of interface + std::string name; + /// interface's index + int index; + /// the addresses owned by this interface + std::vector addrs; + + std::string to_string() const + { + return "{} [ idx={}, addrs={}]"_format(name, index, fmt::join(addrs, ",")); + } + }; + struct if_info { explicit if_info(int _af = AF_INET) : af{_af} {} diff --git a/llarp/net/net_int.cpp b/llarp/net/net_int.cpp deleted file mode 100644 index 07b37ef6ea..0000000000 --- a/llarp/net/net_int.cpp +++ /dev/null @@ -1,150 +0,0 @@ -#include "net_int.hpp" - -#include "ip.hpp" - -#include - -#include -#include - -namespace llarp -{ - namespace net - { - huint16_t ToHost(port_t x) - { - return huint16_t{oxenc::big_to_host(x.n)}; - } - - huint32_t ToHost(ipv4addr_t x) - { - return huint32_t{oxenc::big_to_host(x.n)}; - } - - huint128_t ToHost(ipv6addr_t x) - { - return {ntoh128(x.n)}; - } - - port_t ToNet(huint16_t x) - { - return port_t{oxenc::host_to_big(x.h)}; - } - - ipv4addr_t ToNet(huint32_t x) - { - return ipv4addr_t{oxenc::host_to_big(x.h)}; - } - - ipv6addr_t ToNet(huint128_t x) - { - return ipv6addr_t{hton128(x.h)}; - } - } // namespace net - - template <> - void huint32_t::ToV6(V6Container& c) - { - c.resize(16); - std::fill(c.begin(), c.end(), 0); - oxenc::write_host_as_big(h, c.data() + 12); - c[11] = 0xff; - c[10] = 0xff; - } - - template <> - void huint128_t::ToV6(V6Container& c) - { - c.resize(16); - const in6_addr addr = net::HUIntToIn6(*this); - std::copy_n(addr.s6_addr, 16, c.begin()); - } - - template <> - std::string huint32_t::to_string() const - { - uint32_t n = htonl(h); - char tmp[INET_ADDRSTRLEN] = {0}; - if (!inet_ntop(AF_INET, (void*)&n, tmp, sizeof(tmp))) - return ""; - return tmp; - } - - template <> - std::string huint128_t::to_string() const - { - auto addr = ntoh128(h); - char tmp[INET6_ADDRSTRLEN] = {0}; - if (!inet_ntop(AF_INET6, (void*)&addr, tmp, sizeof(tmp))) - return ""; - return tmp; - } - - template <> - bool huint16_t::FromString(const std::string& str) - { - if (auto val = std::atoi(str.c_str()); val >= 0) - { - h = val; - return true; - } - else - return false; - } - - template <> - bool huint32_t::FromString(const std::string& str) - { - uint32_t n; - if (!inet_pton(AF_INET, str.c_str(), &n)) - return false; - h = ntohl(n); - return true; - } - - template <> - bool huint128_t::FromString(const std::string& str) - { - llarp::uint128_t i; - if (!inet_pton(AF_INET6, str.c_str(), &i)) - return false; - h = ntoh128(i); - return true; - } - - template <> - std::string nuint32_t::to_string() const - { - char tmp[INET_ADDRSTRLEN] = {0}; - if (!inet_ntop(AF_INET, (void*)&n, tmp, sizeof(tmp))) - return ""; - return tmp; - } - - template <> - std::string nuint128_t::to_string() const - { - char tmp[INET6_ADDRSTRLEN] = {0}; - if (!inet_ntop(AF_INET6, (void*)&n, tmp, sizeof(tmp))) - return ""; - return tmp; - } - - template <> - std::string huint16_t::to_string() const - { - return std::to_string(h); - } - - template <> - std::string nuint16_t::to_string() const - { - return std::to_string(ntohs(n)); - } - - std::string net::to_string(const ipaddr_t& ipaddr) - { - return std::visit([](const auto& ip) { return ip.to_string(); }, ipaddr); - } - -} // namespace llarp diff --git a/llarp/net/net_int.hpp b/llarp/net/net_int.hpp deleted file mode 100644 index 8170b890a0..0000000000 --- a/llarp/net/net_int.hpp +++ /dev/null @@ -1,207 +0,0 @@ -#pragma once - -// for addrinfo -#ifndef _WIN32 -#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 - -namespace llarp -{ - template - struct huint_t - { - UInt_t h; - - constexpr huint_t operator&(huint_t x) const { return huint_t{UInt_t{h & x.h}}; } - - constexpr huint_t operator|(huint_t x) const { return huint_t{UInt_t{h | x.h}}; } - - constexpr huint_t operator-(huint_t x) const { return huint_t{UInt_t{h - x.h}}; } - - constexpr huint_t operator+(huint_t x) const { return huint_t{UInt_t{h + x.h}}; } - - constexpr huint_t operator^(huint_t x) const { return huint_t{UInt_t{h ^ x.h}}; } - - constexpr huint_t operator~() const { return huint_t{UInt_t{~h}}; } - - constexpr huint_t operator<<(int n) const - { - UInt_t v{h}; - v <<= n; - return huint_t{v}; - } - - inline huint_t operator++() - { - ++h; - return *this; - } - - inline huint_t operator--() - { - --h; - return *this; - } - - constexpr bool operator<(huint_t x) const { return h < x.h; } - - constexpr bool operator!=(huint_t x) const { return h != x.h; } - - constexpr bool operator==(huint_t x) const { return h == x.h; } - - using V6Container = std::vector; - [[deprecated]] void ToV6(V6Container& c); - - std::string to_string() const; - - bool FromString(const std::string&); - }; - - using huint32_t = huint_t; - using huint16_t = huint_t; - using huint128_t = huint_t; - - template - struct nuint_t - { - UInt_t n = 0; - - constexpr nuint_t operator&(nuint_t x) const { return nuint_t{UInt_t(n & x.n)}; } - - constexpr nuint_t operator|(nuint_t x) const { return nuint_t{UInt_t(n | x.n)}; } - - constexpr nuint_t operator^(nuint_t x) const { return nuint_t{UInt_t(n ^ x.n)}; } - - constexpr nuint_t operator~() const { return nuint_t{UInt_t(~n)}; } - - inline nuint_t operator++() - { - ++n; - return *this; - } - inline nuint_t operator--() - { - --n; - return *this; - } - - constexpr bool operator<(nuint_t x) const { return n < x.n; } - - constexpr bool operator!=(nuint_t x) const { return n != x.n; } - - constexpr bool operator==(nuint_t x) const { return n == x.n; } - - using V6Container = std::vector; - [[deprecated]] void ToV6(V6Container& c); - - std::string to_string() const; - - bool FromString(const std::string& data) - { - huint_t x; - if (not x.FromString(data)) - return false; - *this = ToNet(x); - return true; - } - - inline static nuint_t from_string(const std::string& str) - { - nuint_t x{}; - if (not x.FromString(str)) - throw std::invalid_argument{fmt::format("{} is not a valid value", str)}; - return x; - } - - template - inline static nuint_t from_host(Args_t&&... args) - { - return ToNet(huint_t{std::forward(args)...}); - } - }; - - namespace net - { - /// hides the nuint types used with net_port_t / net_ipv4addr_t / net_ipv6addr_t - namespace - { - using n_uint16_t = llarp::nuint_t; - using n_uint32_t = llarp::nuint_t; - using n_uint128_t = llarp::nuint_t; - } // namespace - - using port_t = n_uint16_t; - using ipv4addr_t = n_uint32_t; - using flowlabel_t = n_uint32_t; - using ipv6addr_t = n_uint128_t; - using ipaddr_t = std::variant; - - std::string to_string(const ipaddr_t& ip); - - huint16_t ToHost(port_t); - huint32_t ToHost(ipv4addr_t); - huint128_t ToHost(ipv6addr_t); - - port_t ToNet(huint16_t); - ipv4addr_t ToNet(huint32_t); - ipv6addr_t ToNet(huint128_t); - - } // namespace net - - 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 ToNet( - llarp::huint_t x) - { - return llarp::net::ToNet(x); - } - - template - /* [[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 xhtonl(huint32_t x) - { - return ToNet(x); - } -} // namespace llarp - -namespace std -{ - template - struct hash> - { - size_t operator()(const llarp::nuint_t& x) const { return std::hash{}(x.n); } - }; - - template - struct hash> - { - size_t operator()(const llarp::huint_t& x) const { return std::hash{}(x.h); } - }; -} // namespace std diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index e0fd1674ef..f3e2eaa65d 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -5,7 +5,6 @@ #include #include #include -#include #include namespace llarp::path @@ -42,9 +41,9 @@ namespace llarp::path hops[idx].txID = hops[idx + 1].rxID; } - // initialize parts of the introduction - intro_old.pivot_router = hops[hsz - 1].rc.router_id(); - intro_old.pivot_hop_id = hops[hsz - 1].txID; + // initialize parts of the clientintro + intro.pivot_rid = hops[hsz - 1].rc.router_id(); + intro.pivot_hid = hops[hsz - 1].txID; } void Path::link_session(recv_session_dgram_cb cb) @@ -114,25 +113,6 @@ namespace llarp::path "close_exit", CloseExitMessage::sign_and_serialize(sk, std::move(tx_id)), std::move(func)); } - // TESTNET: TONUKE: - bool Path::find_intro( - const dht::Key_t& location, bool is_relayed, uint64_t order, std::function func) - { - return send_path_control_message( - "find_intro", FindIntroMessage::serialize(location, is_relayed, order), std::move(func)); - } - - // TESTNET: TONUKE: - bool Path::publish_intro( - const service::EncryptedIntroSet& introset, - bool is_relayed, - uint64_t order, - std::function func) - { - return send_path_control_message( - "publish_intro", PublishIntroMessage::serialize(introset, is_relayed, order), std::move(func)); - } - bool Path::find_client_contact( const dht::Key_t& location, bool is_relayed, uint64_t order, std::function func) { @@ -348,13 +328,9 @@ namespace llarp::path auto now = llarp::time_now_ms(); nlohmann::json obj{ - {"intro", intro_old.ExtractStatus()}, {"lastRecvMsg", to_json(last_recv_msg)}, {"lastLatencyTest", to_json(last_latency_test)}, - {"buildStarted", to_json(buildStarted)}, {"expired", is_expired(now)}, - {"expiresSoon", ExpiresSoon(now)}, - {"expiresAt", to_json(ExpireTime())}, {"ready", is_ready()}, // {"txRateCurrent", m_LastTXRate}, // {"rxRateCurrent", m_LastRXRate}, @@ -493,6 +469,11 @@ namespace llarp::path /// how long we wait for a path to become active again after it times out // constexpr auto PathReanimationTimeout = 45s; + void Path::set_established() + { + _established = true; + } + bool Path::is_expired(std::chrono::milliseconds now) const { (void)now; diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 2f16d9a0a4..682d209f8c 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -44,8 +44,6 @@ namespace llarp std::weak_ptr handler; - service::Introduction intro_old; - ClientIntro intro; std::chrono::milliseconds buildStarted = 0s; @@ -69,7 +67,7 @@ namespace llarp std::chrono::milliseconds LastRemoteActivityAt() const { return last_recv_msg; } - void set_established() { _established = true; } + void set_established(); void recv_path_data_message(bstring data); @@ -81,18 +79,13 @@ namespace llarp std::chrono::milliseconds ExpireTime() const { return buildStarted + hops[0].lifetime; } - bool ExpiresSoon(std::chrono::milliseconds now, std::chrono::milliseconds dlt = 5s) const - { - return now >= (ExpireTime() - dlt); - } - void enable_exit_traffic(); void mark_exit_closed(); bool update_exit(uint64_t tx_id); - bool is_expired(std::chrono::milliseconds now) const; + bool is_expired(std::chrono::milliseconds now = llarp::time_now_ms()) const; /// build a new path on the same set of hops as us /// regenerates keys @@ -111,20 +104,6 @@ namespace llarp uint64_t order = 0, std::function func = nullptr); - // TESTNET: // TONUKE: - [[deprecated]] bool find_intro( - const dht::Key_t& location, - bool is_relayed = false, - uint64_t order = 0, - std::function func = nullptr); - - // TESTNET: // TONUKE: - [[deprecated]] bool publish_intro( - const service::EncryptedIntroSet& introset, - bool is_relayed = false, - uint64_t order = 0, - std::function func = nullptr); - bool close_exit( const Ed25519SecretKey& sk, std::string tx_id, std::function func = nullptr); diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index bfe31c09ea..a6a4ea1b3d 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -182,7 +182,7 @@ namespace llarp::path void PathHandler::reset_path_state() { build_interval_limit = PATH_BUILD_RATE; - _last_build = 0s; + last_build = 0s; } // called within the scope of locked mutex @@ -267,40 +267,6 @@ namespace llarp::path return intros; } - service::intro_que_old PathHandler::get_recent_path_intros(std::chrono::milliseconds stale_threshold) const - { - Lock_t l{paths_mutex}; - service::intro_que_old ret{}; - - for (const auto& [_, p] : _paths) - { - if (p->is_ready() and not p->intro_old.expires_soon(stale_threshold)) - ret.push(p->intro_old); - } - - return ret; - } - - std::optional PathHandler::get_path_intros_conditional( - std::function filter) const - { - service::IntroductionSet_old intros; - Lock_t l{paths_mutex}; - - for (const auto& p : _paths) - { - if (p.second->is_ready() and filter(p.second->intro_old)) - { - intros.insert(p.second->intro_old); - } - } - - if (intros.empty()) - return std::nullopt; - - return intros; - } - void PathHandler::tick(std::chrono::milliseconds now) { log::trace(logcat, "{} called", __PRETTY_FUNCTION__); @@ -319,7 +285,7 @@ namespace llarp::path if (_build_stats.attempts > 50) { - if (_build_stats.SuccessRatio() <= BuildStats::MinGoodRatio && now - last_warn_time > 5s) + if (_build_stats.SuccessRatio() <= BuildStats::THRESHOLD && now - last_warn_time > 5s) { log::warning(logcat, "Low path build success: {}", _build_stats); last_warn_time = now; @@ -406,7 +372,7 @@ namespace llarp::path bool PathHandler::build_cooldown() const { - return llarp::time_now_ms() < _last_build + build_interval_limit; + return llarp::time_now_ms() < last_build + build_interval_limit; } size_t PathHandler::should_build_more() const @@ -532,7 +498,7 @@ namespace llarp::path return false; } - _last_build = llarp::time_now_ms(); + last_build = llarp::time_now_ms(); const auto& edge = hops[0].router_id(); const auto& terminus = hops.back().router_id(); diff --git a/llarp/path/path_handler.hpp b/llarp/path/path_handler.hpp index 4e953980a7..b8e5b22dd2 100644 --- a/llarp/path/path_handler.hpp +++ b/llarp/path/path_handler.hpp @@ -4,7 +4,6 @@ #include #include -#include #include #include #include @@ -60,13 +59,13 @@ namespace llarp /// Stats about all our path builds struct BuildStats { - static constexpr double MinGoodRatio = 0.25; + static constexpr double THRESHOLD{0.25}; - uint64_t attempts = 0; - uint64_t success = 0; - uint64_t build_fails = 0; // path build failures - uint64_t path_fails = 0; // path failures post-build - uint64_t timeouts = 0; + uint64_t attempts{}; + uint64_t success{}; + uint64_t build_fails{}; // path build failures + uint64_t path_fails{}; // path failures post-build + uint64_t timeouts{}; nlohmann::json ExtractStatus() const; @@ -92,7 +91,7 @@ namespace llarp struct PathHandler { private: - std::chrono::milliseconds last_warn_time = 0s; + std::chrono::milliseconds last_warn_time{0s}; std::unordered_map> path_cache; @@ -130,7 +129,7 @@ namespace llarp public: Router& _router; size_t num_hops; - std::chrono::milliseconds _last_build = 0s; + std::chrono::milliseconds last_build{0s}; std::chrono::milliseconds build_interval_limit = MIN_PATH_BUILD_INTERVAL; std::set snode_blacklist; @@ -161,11 +160,11 @@ namespace llarp intro_set get_current_client_intros() const; - service::intro_que_old get_recent_path_intros( - std::chrono::milliseconds stale_threshold = path::INTRO_STALE_THRESHOLD) const; + // service::intro_que_old get_recent_path_intros( + // std::chrono::milliseconds stale_threshold = path::INTRO_STALE_THRESHOLD) const; - std::optional get_path_intros_conditional( - std::function filter) const; + // std::optional get_path_intros_conditional( + // std::function filter) const; nlohmann::json ExtractStatus() const; diff --git a/llarp/router/route_poker.hpp b/llarp/router/route_poker.hpp index c99d32da79..f5ed1515dc 100644 --- a/llarp/router/route_poker.hpp +++ b/llarp/router/route_poker.hpp @@ -1,7 +1,5 @@ #pragma once -#include - #include #include diff --git a/llarp/rpc/rpc_client.cpp b/llarp/rpc/rpc_client.cpp index 705d9ca661..f51f3c08b9 100644 --- a/llarp/rpc/rpc_client.cpp +++ b/llarp/rpc/rpc_client.cpp @@ -332,19 +332,19 @@ namespace llarp::rpc } void RPCClient::lookup_ons_hash( - std::string namehash, std::function)> resultHandler) + std::string namehash, std::function)> resultHandler) { log::debug(logcat, "Looking Up ONS NameHash {}", namehash); const nlohmann::json req{{"type", 2}, {"name_hash", oxenc::to_hex(namehash)}}; request( "rpc.lns_resolve", [this, resultHandler](bool success, std::vector data) { - std::optional maybe = std::nullopt; + std::optional maybe = std::nullopt; if (success) { try { - service::EncryptedONSRecord result; + EncryptedSNSRecord result; const auto j = nlohmann::json::parse(data[1]); j.dump(); result.ciphertext = oxenc::from_hex(j["encrypted_value"].get()); diff --git a/llarp/rpc/rpc_client.hpp b/llarp/rpc/rpc_client.hpp index 259de9c563..370e864cf2 100644 --- a/llarp/rpc/rpc_client.hpp +++ b/llarp/rpc/rpc_client.hpp @@ -1,10 +1,10 @@ #pragma once #include +#include #include #include #include -#include #include #include @@ -33,7 +33,7 @@ namespace llarp uint64_t block_height() const { return _block_height; } void lookup_ons_hash( - std::string namehash, std::function)> resultHandler); + std::string namehash, std::function)> resultHandler); /// inform that if connected to a router successfully void inform_connection(RouterID router, bool success); diff --git a/llarp/rpc/rpc_request_parser.hpp b/llarp/rpc/rpc_request_parser.hpp index e6e3c4dccd..3c10fe2739 100644 --- a/llarp/rpc/rpc_request_parser.hpp +++ b/llarp/rpc/rpc_request_parser.hpp @@ -4,7 +4,6 @@ #include -// #include #include #include diff --git a/llarp/service/identity.cpp b/llarp/service/identity.cpp deleted file mode 100644 index bfaccc9a45..0000000000 --- a/llarp/service/identity.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include "identity.hpp" - -#include - -namespace llarp::service -{ - static auto logcat = log::Cat("Identity"); - - std::string Identity::bt_encode() const - { - oxenc::bt_dict_producer btdp; - - btdp.append("s", _idkey.to_view()); - btdp.append("v", version); - - return std::move(btdp).str(); - } - - void Identity::bt_decode(std::string buf) - { - try - { - oxenc::bt_dict_consumer btdc{buf}; - - _idkey.from_string(btdc.require("s")); - version = btdc.require("v"); - } - catch (...) - { - log::warning(logcat, "Identity failed to parse bt-encoded contents!"); - throw; - } - } - - void Identity::Clear() - { - _idkey.zero(); - _enckey.zero(); - derivedSignKey.zero(); - } - - void Identity::regenerate_keys() - { - crypto::identity_keygen(_idkey); - crypto::encryption_keygen(_enckey); - - pub.update(seckey_to_pubkey(_idkey), seckey_to_pubkey(_enckey)); - - if (not crypto::derive_subkey_private(derivedSignKey, _idkey, 1)) - { - 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.encryption_pubkey(), _enckey, N); - } - - bool Identity::Sign(Signature& sig, uint8_t* buf, size_t size) const - { - return crypto::sign(sig, _idkey, buf, size); - } - - std::optional Identity::encrypt_and_sign_introset( - const IntroSetOld& other_i, std::chrono::milliseconds now) const - { - EncryptedIntroSet encrypted; - - if (other_i.intros.empty()) - return std::nullopt; - - IntroSetOld i{other_i}; - encrypted.nonce.Randomize(); - // set timestamp - // TODO: round to nearest 1000 ms - i.time_signed = now; - encrypted.signed_at = now; - // set service info - i.address_keys = pub; - - auto bte = i.bt_encode(); - - const SharedSecret k{i.address_keys.address().pubkey()}; - crypto::xchacha20(reinterpret_cast(bte.data()), bte.size(), k, encrypted.nonce); - - std::memcpy(encrypted.introset_payload.data(), bte.data(), bte.size()); - - 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 deleted file mode 100644 index 5ca01085f7..0000000000 --- a/llarp/service/identity.hpp +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once - -#include "info.hpp" -#include "intro_set.hpp" - -#include -#include -#include - -#include -#include - -namespace llarp::service -{ - // private keys - struct Identity - { - Ed25519SecretKey _idkey; - Ed25519SecretKey _enckey; - Ed25519PrivateData derivedSignKey; - uint64_t version = llarp::constants::proto_version; - - // public service info - ServiceInfo pub; - - // regenerate secret keys - void regenerate_keys(); - - std::string bt_encode() const; - - void bt_decode(std::string); - - bool KeyExchange( - path_dh_func dh, SharedSecret& sharedkey, const ServiceInfo& other, const KeyExchangeNonce& N) const; - - std::optional encrypt_and_sign_introset( - const IntroSetOld& i, std::chrono::milliseconds now) const; - - bool Sign(Signature& sig, uint8_t* buf, size_t size) const; - - /// zero out all secret key members - void Clear(); - }; - - inline bool operator==(const Identity& lhs, const Identity& rhs) - { - return std::tie(lhs._enckey, lhs._idkey, lhs.version) == std::tie(rhs._enckey, rhs._idkey, rhs.version); - } -} // namespace llarp::service diff --git a/llarp/service/info.cpp b/llarp/service/info.cpp deleted file mode 100644 index 5053d030f9..0000000000 --- a/llarp/service/info.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include "info.hpp" - -#include - -namespace llarp::service -{ - static auto logcat = log::Cat("service_info"); - - bool ServiceInfo::verify(uint8_t* buf, size_t size, const Signature& sig) const - { - return crypto::verify(signkey, buf, size, sig); - } - - bool ServiceInfo::update(const uint8_t* sign, const uint8_t* enc) - { - signkey = sign; - enckey = enc; - - return update_address(); - } - - void ServiceInfo::bt_decode(oxenc::bt_dict_consumer& btdc) - { - try - { - enckey.from_hex(btdc.require("e")); - signkey.from_hex(btdc.require("s")); - } - catch (...) - { - log::critical(logcat, "ServiceInfo failed to populate with bt encoded contents"); - throw; - } - } - - bool ServiceInfo::bt_decode(std::string_view buf) - { - try - { - oxenc::bt_dict_consumer btdc{buf}; - - bt_decode(btdc); - } - catch (const std::exception& e) - { - // DISCUSS: rethrow or print warning/return false...? - auto err = "ServiceInfo parsing exception: {}"_format(e.what()); - log::warning(logcat, "{}", err); - throw std::runtime_error{err}; - } - - return true; - } - - void ServiceInfo::bt_encode(oxenc::bt_dict_producer& btdp) const - { - btdp.append("e", enckey.to_view()); - btdp.append("s", signkey.to_view()); - } - - std::string ServiceInfo::name() const - { - if (_cached_addr.is_empty()) - { - PubKey pk; - calculate_address(pk); - return pk.to_string(); - } - - return _cached_addr.to_string(); - } - - bool ServiceInfo::calculate_address(PubKey& data) const - { - data = PubKey{signkey.as_array()}; - return true; - } - - bool ServiceInfo::update_address() - { - if (_cached_addr.is_empty()) - { - return calculate_address(_cached_addr.pubkey()); - } - - return true; - } - - std::string ServiceInfo::to_string() const - { - return "[ServiceInfo e={} s={} v={}]"_format(enckey, signkey, version); - } - -} // namespace llarp::service diff --git a/llarp/service/info.hpp b/llarp/service/info.hpp deleted file mode 100644 index ce8544d082..0000000000 --- a/llarp/service/info.hpp +++ /dev/null @@ -1,68 +0,0 @@ -#pragma once - -#include -#include -#include - -#include - -#include - -namespace llarp::service -{ - struct ServiceInfo - { - private: - PubKey enckey; - PubKey signkey; - mutable NetworkAddress _cached_addr; - - public: - uint64_t version = llarp::constants::proto_version; - - bool verify(uint8_t* buf, size_t size, const Signature& sig) const; - - const PubKey& encryption_pubkey() const - { - if (_cached_addr.is_empty()) - calculate_address(_cached_addr.pubkey()); - - return enckey; - } - - bool update(const uint8_t* sign, const uint8_t* enc); - - bool operator==(const ServiceInfo& other) const - { - return std::tie(enckey, version) == std::tie(other.enckey, other.version); - } - - bool operator!=(const ServiceInfo& other) const { return !(*this == other); } - - bool operator<(const ServiceInfo& other) const { return address() < other.address(); } - - std::string to_string() const; - - /// .loki address - std::string name() const; - - bool update_address(); - - const NetworkAddress& address() const - { - if (_cached_addr.is_empty()) - calculate_address(_cached_addr.pubkey()); - - return _cached_addr; - } - - /// calculate our address - bool calculate_address(PubKey& data) const; - - bool bt_decode(std::string_view buf); - - void bt_decode(oxenc::bt_dict_consumer& btdc); - - void bt_encode(oxenc::bt_dict_producer& btdp) const; - }; -} // namespace llarp::service diff --git a/llarp/service/intro.cpp b/llarp/service/intro.cpp deleted file mode 100644 index 9464019259..0000000000 --- a/llarp/service/intro.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include "intro.hpp" - -#include - -namespace llarp::service -{ - static auto logcat = log::Cat("introduction"); - - nlohmann::json Introduction::ExtractStatus() const - { - nlohmann::json obj{ - {"router", pivot_router.ToHex()}, - {"path", pivot_hop_id.ToHex()}, - {"expiresAt", to_json(expiry)}, - {"version", uint64_t(version)}}; - return obj; - } - - Introduction::Introduction(std::string buf) - { - try - { - oxenc::bt_dict_consumer btdc{std::move(buf)}; - - pivot_router.from_relay_address(btdc.require("k")); - pivot_hop_id.from_string(btdc.require("p")); - expiry = std::chrono::milliseconds{btdc.require("x")}; - } - catch (...) - { - log::critical(logcat, "Error: Introduction failed to populate with bt encoded contents"); - } - } - - void Introduction::bt_encode(oxenc::bt_list_producer& btlp) const - { - try - { - auto subdict = btlp.append_dict(); - bt_encode(subdict); - } - catch (...) - { - log::critical(logcat, "Error: Introduction failed to bt encode contents!"); - } - } - - void Introduction::bt_encode(oxenc::bt_dict_producer& subdict) const - { - try - { - subdict.append("k", pivot_router.to_view()); - subdict.append("p", pivot_hop_id.to_view()); - subdict.append("x", expiry.count()); - } - catch (...) - { - log::critical(logcat, "Error: Introduction failed to bt encode contents!"); - } - } - - bool Introduction::bt_decode(std::string_view buf) - { - try - { - oxenc::bt_dict_consumer btdc{buf}; - bt_decode(btdc); - } - catch (const std::exception& e) - { - // DISCUSS: rethrow or print warning/return false...? - auto err = "Introduction parsing exception: {}"_format(e.what()); - log::warning(logcat, "{}", err); - throw std::runtime_error{err}; - } - - return true; - } - - void Introduction::bt_decode(oxenc::bt_dict_consumer& btdc) - { - try - { - pivot_router.from_string(btdc.require("k")); - expiry = std::chrono::milliseconds{btdc.require("x")}; - } - catch (...) - { - log::critical(logcat, "Introcuction failed to populate with bt encoded contents"); - throw; - } - } - - void Introduction::clear() - { - pivot_router.zero(); - pivot_hop_id.zero(); - expiry = 0s; - } - - std::string Introduction::to_string() const - { - return fmt::format( - "[Intro k={} p={} v={} x={}]", RouterID{pivot_router}, pivot_hop_id, version, expiry.count()); - } - -} // namespace llarp::service diff --git a/llarp/service/intro.hpp b/llarp/service/intro.hpp deleted file mode 100644 index b3c1c11eab..0000000000 --- a/llarp/service/intro.hpp +++ /dev/null @@ -1,88 +0,0 @@ -#pragma once - -#include -#include - -#include - -#include -#include - -namespace llarp::service -{ - struct Introduction - { - RouterID pivot_router; - HopID pivot_hop_id; - std::chrono::milliseconds expiry = 0s; - uint64_t version = llarp::constants::proto_version; - - Introduction() = default; - Introduction(std::string buf); - - nlohmann::json ExtractStatus() const; - - bool is_expired(std::chrono::milliseconds now = llarp::time_now_ms()) const { return now >= expiry; } - - // TODO: get rid of this entirely, and use ::is_expired(...) - bool expires_soon( - std::chrono::milliseconds dlt = 30s, std::chrono::milliseconds now = llarp::time_now_ms()) const - { - return is_expired(now + dlt); - } - - std::string to_string() const; - - void bt_encode(oxenc::bt_list_producer& btlp) const; - - void bt_encode(oxenc::bt_dict_producer& subdict) const; - - bool bt_decode(std::string_view buf); - - void bt_decode(oxenc::bt_dict_consumer& btdc); - - void clear(); - - bool operator<(const Introduction& other) const - { - return std::tie(expiry, pivot_hop_id, pivot_router, version) - < std::tie(other.expiry, other.pivot_hop_id, other.pivot_router, other.version); - } - - bool operator==(const Introduction& other) const - { - return std::tie(expiry, pivot_hop_id, pivot_router, version) - == std::tie(other.expiry, other.pivot_hop_id, other.pivot_router, other.version); - } - - bool operator!=(const Introduction& other) const { return !(*this == other); } - - static constexpr bool to_string_formattable = true; - }; - - /// comparator for introduction timestamp in order of nearest to furthest expiry time - struct IntroExpiryComparator - { - bool operator()(const Introduction& left, const Introduction& right) const - { - return left.expiry < right.expiry; - } - }; - - using intro_que_old = std::priority_queue, IntroExpiryComparator>; - - using IntroductionSet_old = std::set; - -} // namespace llarp::service - -namespace std -{ - template <> - struct hash - { - size_t operator()(const llarp::service::Introduction& i) const - { - return std::hash{}(i.pivot_router) ^ std::hash{}(i.pivot_hop_id); - } - }; -} // namespace std diff --git a/llarp/service/intro_set.cpp b/llarp/service/intro_set.cpp deleted file mode 100644 index 5d72c9e7eb..0000000000 --- a/llarp/service/intro_set.cpp +++ /dev/null @@ -1,433 +0,0 @@ -#include "intro_set.hpp" - -#include - -#include - -namespace llarp::service -{ - static auto logcat = log::Cat("EncIntro"); - - EncryptedIntroSet::EncryptedIntroSet( - std::string signing_key, - std::chrono::milliseconds signed_at, - std::string enc_payload, - std::string nonce, - std::string s) - : signed_at{signed_at}, - introset_payload{reinterpret_cast(enc_payload.data()), enc_payload.size()}, - nonce{reinterpret_cast(nonce.data())} - { - derived_signing_key.from_hex(signing_key); - sig.from_string(std::move(s)); - } - - EncryptedIntroSet::EncryptedIntroSet(std::string bt_payload) - { - try - { - oxenc::bt_dict_consumer btdc{bt_payload}; - bt_decode(btdc); - } - catch (...) - { - log::critical(logcat, "Error: EncryptedIntroSet failed to bt encode contents!"); - } - } - - nlohmann::json EncryptedIntroSet::ExtractStatus() const - { - const auto sz = introset_payload.size(); - return {{"location", derived_signing_key.to_string()}, {"signedAt", to_json(signed_at)}, {"size", sz}}; - } - - bool EncryptedIntroSet::bt_decode(std::string_view buf) - { - try - { - oxenc::bt_dict_consumer btdc{buf}; - return bt_decode(btdc); - } - catch (const std::exception& e) - { - // DISCUSS: rethrow or print warning/return false...? - auto err = "EncryptedIntroSet parsing exception: {}"_format(e.what()); - log::warning(logcat, "{}", err); - throw std::runtime_error{err}; - } - } - - bool EncryptedIntroSet::bt_decode(oxenc::bt_dict_consumer& btdc) - { - try - { - derived_signing_key.from_string(btdc.require("d")); - nonce.from_string(btdc.require("n")); - signed_at = std::chrono::milliseconds{btdc.require("s")}; - introset_payload = btdc.require("x"); - sig.from_string(btdc.require("z")); - - return true; - } - catch (...) - { - log::critical(logcat, "EncryptedIntroSet failed to decode bt payload!"); - throw; - } - } - - std::string EncryptedIntroSet::bt_encode() const - { - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("d", derived_signing_key.to_view()); - btdp.append("n", nonce.to_view()); - btdp.append("s", signed_at.count()); - btdp.append( - "x", std::string_view{reinterpret_cast(introset_payload.data()), introset_payload.size()}); - btdp.append("z", sig.to_view()); - } - catch (...) - { - log::critical(logcat, "Error: EncryptedIntroSet failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - - std::optional EncryptedIntroSet::construct(std::string bt) - { - if (EncryptedIntroSet ret; ret.bt_decode(std::move(bt))) - return ret; - - return std::nullopt; - } - - bool EncryptedIntroSet::other_is_newer(const EncryptedIntroSet& other) const - { - return signed_at < other.signed_at; - } - - std::string EncryptedIntroSet::to_string() const - { - return "[EncIntroSet d={} n={} s={} x=[{} bytes] z={}]"_format( - derived_signing_key, nonce, signed_at.count(), introset_payload.size(), sig); - } - - std::optional EncryptedIntroSet::decrypt(const PubKey& root) const - { - std::optional ret = std::nullopt; - - SharedSecret k(root); - std::string payload{reinterpret_cast(introset_payload.data()), introset_payload.size()}; - - if (crypto::xchacha20(reinterpret_cast(payload.data()), payload.size(), k, nonce)) - ret = IntroSetOld{payload}; - - return ret; - } - - bool EncryptedIntroSet::is_expired(std::chrono::milliseconds now) const - { - return now >= signed_at + path::DEFAULT_LIFETIME; - } - - bool EncryptedIntroSet::sign(const Ed25519PrivateData& k) - { - signed_at = llarp::time_now_ms(); - derived_signing_key = k.to_pubkey(); - sig.zero(); - auto bte = bt_encode(); - - if (not crypto::sign(sig, k, reinterpret_cast(bte.data()), bte.size())) - return false; - - log::debug(logcat, "Singed encrypted introset: {}", *this); - return true; - } - - bool EncryptedIntroSet::verify() const - { - if (is_expired()) - return false; - - EncryptedIntroSet copy(*this); - copy.sig.zero(); - - auto bte = copy.bt_encode(); - return crypto::verify(derived_signing_key, reinterpret_cast(bte.data()), bte.size(), sig); - } - - nlohmann::json IntroSetOld::ExtractStatus() const - { - nlohmann::json obj{{"published", to_json(time_signed)}}; - // TODO: this - // std::vector introsObjs; - // std::transform( - // intros.begin(), - // intros.end(), - // std::back_inserter(introsObjs), - // [](const auto& intro) -> nlohmann::json { return intro.ExtractStatus(); }); - // obj["intros"] = introsObjs; - // if (!topic.IsZero()) - // obj["topic"] = topic.to_string(); - - // std::vector protocols; - // std::transform( - // supported_protocols.begin(), - // supported_protocols.end(), - // std::back_inserter(protocols), - // [](const auto& proto) -> nlohmann::json { return service::to_string(proto); }); - // obj["protos"] = protocols; - // std::vector ranges; - // std::transform( - // owned_ranges.begin(), - // owned_ranges.end(), - // std::back_inserter(ranges), - // [](const auto& range) -> nlohmann::json { return range.to_string(); }); - - // obj["advertisedRanges"] = ranges; - // if (exit_policy) - // obj["exitPolicy"] = exit_policy->ExtractStatus(); - - return obj; - } - - IntroSetOld::IntroSetOld(std::string bt_payload) - { - try - { - oxenc::bt_dict_consumer btdc{bt_payload}; - bt_decode(btdc); - } - catch (...) - { - log::critical(logcat, "Error: EncryptedIntroSet failed to bt encode contents!"); - } - } - - bool IntroSetOld::bt_decode(std::string_view buf) - { - try - { - oxenc::bt_dict_consumer btdc{buf}; - bt_decode(btdc); - } - catch (const std::exception& e) - { - // DISCUSS: rethrow or print warning/return false...? - auto err = "IntroSetOld parsing exception: {}"_format(e.what()); - log::warning(logcat, "{}", err); - throw std::runtime_error{err}; - } - - return true; - } - - void IntroSetOld::bt_decode(oxenc::bt_dict_consumer& btdc) - { - try - { - { - auto [key, subdict] = btdc.next_dict_consumer(); - - if (key != "a") - throw std::invalid_argument{ - "IntroSetOld received unexpected key (expected:'a', actual:{})"_format(key)}; - - address_keys.bt_decode(subdict); - } - - if (auto maybe_subdict = btdc.maybe("e"); maybe_subdict) - { - exit_policy->bt_decode(oxenc::bt_dict_consumer{*maybe_subdict}); - } - - { - auto [key, sublist] = btdc.next_list_consumer(); - - if (key != "i") - throw std::invalid_argument{ - "IntroSetOld received unexpected key (expected:'i', actual:{})"_format(key)}; - - while (not sublist.is_finished()) - { - intros.insert(sublist.consume_string()); - } - } - - if (auto maybe_supportedprotos = btdc.maybe("p"); maybe_supportedprotos) - { - oxenc::bt_list_consumer sublist{*maybe_supportedprotos}; - - while (not sublist.is_finished()) - { - supported_protocols.push_back(ProtocolType{sublist.consume_integer()}); - } - } - - if (auto maybe_ownedranges = btdc.maybe("i"); maybe_ownedranges) - { - oxenc::bt_list_consumer sublist{*maybe_ownedranges}; - - while (not sublist.is_finished()) - { - _routed_ranges.emplace(sublist.consume_string()); - } - } - - if (auto maybe_srvs = btdc.maybe("s"); maybe_srvs) - { - oxenc::bt_list_consumer sublist{*maybe_srvs}; - - while (not sublist.is_finished()) - { - SRVs.emplace_back(sublist.consume_string()); - } - } - - time_signed = std::chrono::milliseconds{btdc.require("t")}; - signature.from_string(btdc.require("z")); - } - catch (...) - { - log::critical(logcat, "IntroSetOld failed to decode bt payload!"); - throw; - } - } - - std::string IntroSetOld::bt_encode() const - { - oxenc::bt_dict_producer btdp; - - try - { - { - auto subdict = btdp.append_dict("a"); - address_keys.bt_encode(subdict); - } - - if (exit_policy) - { - exit_policy->bt_encode(btdp.append_dict("e")); - } - - { - auto sublist = btdp.append_list("i"); - for (auto& i : intros) - i.bt_encode(sublist); - } - - if (not supported_protocols.empty()) - { - auto sublist = btdp.append_list("p"); - for (auto& p : supported_protocols) - sublist.append(static_cast(p)); - } - - if (not _routed_ranges.empty()) - { - auto sublist = btdp.append_list("r"); - for (auto& r : _routed_ranges) - r.bt_encode(sublist); - } - - if (not SRVs.empty()) - { - auto sublist = btdp.append_list("s"); - for (auto& s : SRVs) - sublist.append(s.bt_encode()); - } - - btdp.append("t", time_signed.count()); - btdp.append("z", signature.to_view()); - } - catch (...) - { - log::critical(logcat, "Error: IntroSetOld failed to bt encode contents!"); - } - - return std::move(btdp).str(); - } - - bool IntroSetOld::HasExpiredIntros(std::chrono::milliseconds now) const - { - for (const auto& intro : intros) - if (now >= intro.expiry) - return true; - return false; - } - - bool IntroSetOld::HasStaleIntros(std::chrono::milliseconds now, std::chrono::milliseconds delta) const - { - for (const auto& intro : intros) - if (intro.expires_soon(delta, now)) - return true; - return false; - } - - bool IntroSetOld::IsExpired(std::chrono::milliseconds now) const - { - return GetNewestIntroExpiration() < now; - } - - std::vector IntroSetOld::GetMatchingSRVRecords(std::string_view service_proto) const - { - std::vector records; - - for (const auto& srv : SRVs) - { - if (srv.service_proto == service_proto) - { - records.push_back(srv); - } - } - - return records; - } - - bool IntroSetOld::verify(std::chrono::milliseconds now) const - { - IntroSetOld copy; - copy = *this; - copy.signature.zero(); - - auto bte = copy.bt_encode(); - - if (!address_keys.verify(reinterpret_cast(bte.data()), bte.size(), signature)) - { - return false; - } - // valid timestamps - // add max clock skew - now += MAX_INTROSET_TIME_DELTA; - for (const auto& intro : intros) - { - if (intro.expiry > now && intro.expiry - now > path::DEFAULT_LIFETIME) - { - return false; - } - } - return not IsExpired(now); - } - - std::chrono::milliseconds IntroSetOld::GetNewestIntroExpiration() const - { - std::chrono::milliseconds maxTime = 0s; - for (const auto& intro : intros) - maxTime = std::max(intro.expiry, maxTime); - return maxTime; - } - - std::string IntroSetOld::to_string() const - { - return "[IntroSetOld addressKeys={} intros={{}} topic={} signedAt={} v={} sig={}]"_format( - address_keys.to_string(), - "{}"_format(fmt::join(intros, ",")), - time_signed.count(), - version, - signature.to_view()); - } -} // namespace llarp::service diff --git a/llarp/service/intro_set.hpp b/llarp/service/intro_set.hpp deleted file mode 100644 index fb433ad79f..0000000000 --- a/llarp/service/intro_set.hpp +++ /dev/null @@ -1,160 +0,0 @@ -#pragma once - -#include "info.hpp" -#include "intro.hpp" -#include "types.hpp" - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -namespace llarp::service -{ - constexpr std::size_t MAX_INTROSET_SIZE = 4096; - // 10 seconds clock skew permitted for introset expiration - constexpr std::chrono::milliseconds MAX_INTROSET_TIME_DELTA = 10s; - - struct IntroSetOld - { - ServiceInfo address_keys; - IntroductionSet_old intros; - std::vector SRVs; - std::chrono::milliseconds time_signed = 0s; - - IntroSetOld() = default; - - explicit IntroSetOld(std::string bt_payload); - - /// 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 _routed_ranges; // TESTNET: TOFIX: Move into exit policy! - - /// 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 = std::nullopt; - - Signature signature; - uint64_t version = llarp::constants::proto_version; - - bool OtherIsNewer(const IntroSetOld& other) const { return time_signed < other.time_signed; } - - std::string to_string() const; - - std::chrono::milliseconds GetNewestIntroExpiration() const; - - bool HasExpiredIntros(std::chrono::milliseconds now) const; - - /// return true if any of our intros expires soon given a delta - bool HasStaleIntros(std::chrono::milliseconds now, std::chrono::milliseconds delta) const; - - bool IsExpired(std::chrono::milliseconds now) const; - - std::vector GetMatchingSRVRecords(std::string_view service_proto) const; - - std::string bt_encode() const; - - bool bt_decode(std::string_view buf); - - void bt_decode(oxenc::bt_dict_consumer& btdc); - - bool verify(std::chrono::milliseconds now) const; - - nlohmann::json ExtractStatus() const; - - static constexpr bool to_string_formattable = true; - }; - - inline bool operator<(const IntroSetOld& lhs, const IntroSetOld& rhs) - { - return lhs.address_keys < rhs.address_keys; - } - - inline bool operator==(const IntroSetOld& lhs, const IntroSetOld& rhs) - { - return std::tie(lhs.address_keys, lhs.intros, lhs.time_signed, lhs.version, lhs.signature) - == std::tie(rhs.address_keys, rhs.intros, rhs.time_signed, rhs.version, rhs.signature); - } - - inline bool operator!=(const IntroSetOld& lhs, const IntroSetOld& rhs) - { - return !(lhs == rhs); - } - - /// public version of the introset that is encrypted - struct EncryptedIntroSet - { - private: - explicit EncryptedIntroSet(std::string bt_payload); - bool bt_decode(oxenc::bt_dict_consumer& btdc); - - public: - PubKey derived_signing_key; - std::chrono::milliseconds signed_at = 0s; - ustring introset_payload; - SymmNonce nonce; - 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 Ed25519PrivateData& k); - - bool is_expired(std::chrono::milliseconds now = time_now_ms()) const; - - std::string bt_encode() const; - - bool bt_decode(std::string_view buf); - - bool other_is_newer(const EncryptedIntroSet& other) const; - - /// verify signature and timestamp - bool verify() const; - - // this constructor will throw if ::bt_decode fails - static std::optional construct(std::string bt); - - std::string to_string() const; - - nlohmann::json ExtractStatus() const; - - std::optional decrypt(const PubKey& root) const; - static constexpr bool to_string_formattable = true; - }; - - inline bool operator<(const EncryptedIntroSet& lhs, const EncryptedIntroSet& rhs) - { - return lhs.derived_signing_key < rhs.derived_signing_key; - } - - inline bool operator==(const EncryptedIntroSet& lhs, const EncryptedIntroSet& rhs) - { - return std::tie(lhs.signed_at, lhs.derived_signing_key, lhs.nonce, lhs.sig) - == std::tie(rhs.signed_at, rhs.derived_signing_key, rhs.nonce, rhs.sig); - } - - inline bool operator!=(const EncryptedIntroSet& lhs, const EncryptedIntroSet& rhs) - { - return !(lhs == rhs); - } - - using EncryptedIntroSetLookupHandler = std::function&)>; - using IntroSetLookupHandler = std::function&)>; - -} // namespace llarp::service diff --git a/llarp/service/name.hpp b/llarp/service/name.hpp deleted file mode 100644 index c524af4231..0000000000 --- a/llarp/service/name.hpp +++ /dev/null @@ -1,96 +0,0 @@ -#pragma once - -#include -#include - -#include - -namespace llarp -{ - struct NetworkAddress; - - namespace service - { - /** Holds an entire ONS Record returned from a succfessful request to the `lookup_name` endpoint. - When transmitted over the wire back to the calling instance, it is bt-encoded and the ONS hash - ('ciphertext') is decrypted using the ons_name. - - bt-encoded keys: - 'c' : ciphertext - 'n' : nonce - */ - struct EncryptedONSRecord - { - private: - explicit EncryptedONSRecord(std::string bt); - bool bt_decode(oxenc::bt_dict_consumer& btdc); - - public: - SymmNonce nonce; - std::string ciphertext; - - EncryptedONSRecord() = default; - - static std::optional construct(std::string bt); - - std::string bt_encode() const; - - bool bt_decode(std::string bt); - - std::optional decrypt(std::string_view ons_name) const; - }; - - /// check if an ons name complies with the registration rules - inline bool is_valid_ons(std::string_view ons_name) - { - // make sure it ends with .loki because no fucking shit right? - if (not ons_name.ends_with(".loki")) - return false; - - // strip off .loki suffix - ons_name.remove_suffix(5); - - // ensure chars are sane - for (const auto ch : ons_name) - { - if (ch == '-') - continue; - if (ch == '.') - continue; - if (ch >= 'a' and ch <= 'z') - continue; - if (ch >= '0' and ch <= '9') - continue; - return false; - } - - // split into domain parts - const auto parts = split(ons_name, "."); - - // get root domain - const auto primaryName = parts[parts.size() - 1]; - constexpr size_t MaxNameLen = 32; - constexpr size_t MaxPunycodeNameLen = 63; - - // check against lns name blacklist - if (primaryName == "localhost") - return false; - if (primaryName == "loki") - return false; - if (primaryName == "snode") - return false; - // check for dashes - if (primaryName.find("-") == std::string_view::npos) - return primaryName.size() <= MaxNameLen; - // check for dashes and end or beginning - if (*primaryName.begin() == '-' or *(primaryName.end() - 1) == '-') - return false; - // check for punycode name length - if (primaryName.size() > MaxPunycodeNameLen) - return false; - // check for xn-- - return (primaryName[2] == '-' and primaryName[3] == '-') ? (primaryName[0] == 'x' and primaryName[1] == 'n') - : true; - } - } // namespace service -} // namespace llarp diff --git a/llarp/service/types.cpp b/llarp/service/types.cpp deleted file mode 100644 index 91148cb26b..0000000000 --- a/llarp/service/types.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include "types.hpp" - -#include - -namespace llarp::service::util -{ - // void ExpireSNodeSessions(std::chrono::milliseconds now, SNodeConnectionMap& sessions) - // { - // auto itr = sessions.begin(); - // while (itr != sessions.end()) - // { - // 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; - // } - // } - - // void DeregisterDeadSessions(std::chrono::milliseconds now, ConnectionMap& sessions) - // { - // auto itr = sessions.begin(); - // while (itr != sessions.end()) - // { - // if (itr->second->IsDone(now)) - // { - // itr = sessions.erase(itr); - // } - // else - // { - // ++itr; - // } - // } - // } - - // void TickRemoteSessions( - // std::chrono::milliseconds now, - // ConnectionMap& remoteSessions, - // ConnectionMap& deadSessions, - // std::unordered_map& sessions) - // { - // auto itr = remoteSessions.begin(); - // while (itr != remoteSessions.end()) - // { - // itr->second->Tick(now); - // if (itr->second->Pump(now)) - // { - // 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); - // } - // else - // { - // ++itr; - // } - // } - // for (auto& item : deadSessions) - // { - // item.second->Tick(now); - // } - // } - - // void ExpireConvoSessions( - // std::chrono::milliseconds now, std::unordered_map& sessions) - // { - // auto itr = sessions.begin(); - // while (itr != sessions.end()) - // { - // if (itr->second.IsExpired(now)) - // { - // LogInfo("Expire session T=", itr->first, " to ", itr->second.Addr()); - // itr = sessions.erase(itr); - // } - // else - // ++itr; - // } - // } - - // void StopRemoteSessions(ConnectionMap& remoteSessions) - // { - // for (auto& item : remoteSessions) - // { - // item.second->Stop(); - // } - // } - - // void StopSnodeSessions(SNodeConnectionMap& sessions) - // { - // for (auto& item : sessions) - // { - // item.second->Stop(); - // } - // } - - // bool HasPathToService(const Address& addr, const ConnectionMap& remoteSessions) - // { - // auto range = remoteSessions.equal_range(addr); - // auto itr = range.first; - // while (itr != range.second) - // { - // if (itr->second->ReadyToSend()) - // return true; - // ++itr; - // } - // return false; - // } - - // bool GetConvoTagsForService( - // const std::unordered_map& sessions, - // const Address& info, - // std::set& tags) - // { - // bool inserted = false; - // auto itr = sessions.begin(); - // while (itr != sessions.end()) - // { - // if (itr->second.remote.Addr() == info) - // { - // if (tags.emplace(itr->first).second) - // { - // inserted = true; - // } - // } - // ++itr; - // } - // return inserted; - // } -} // namespace llarp::service::util diff --git a/llarp/service/types.hpp b/llarp/service/types.hpp deleted file mode 100644 index 6d025a9c40..0000000000 --- a/llarp/service/types.hpp +++ /dev/null @@ -1,123 +0,0 @@ -#pragma once - -#include -#include - -#include -#include -#include -#include - -/** TODO: - - The commented functions are utilities for managing sessions to remote hidden services. They - need to be redefined with the correct parameters and called from service::Handler, as - service::Endpoint is for local hidden service management - - ^^ Is this still true...? -*/ - -using namespace std::literals; - -namespace llarp -{ - namespace session - { - struct OutboundSession; - } - namespace path - { - struct Path; - } - namespace routing - { - struct PathTransferMessage; - } - - namespace service - { - // Supported protocol types; the values are given explicitly because they are specifically - // used when sending over the wire. - enum class ProtocolType : uint64_t - { - CONTROL = 0UL, - IPV4 = 1UL, - IPV6 = 2UL, - EXIT = 3UL, - AUTH = 4UL, - TCP2QUIC = 5UL, - }; - - inline constexpr std::string_view to_string(ProtocolType t) - { - return t == ProtocolType::CONTROL ? "Control"sv - : t == ProtocolType::IPV4 ? "TrafficV4"sv - : t == ProtocolType::IPV6 ? "TrafficV6"sv - : t == ProtocolType::EXIT ? "Exit"sv - : t == ProtocolType::AUTH ? "Auth"sv - : t == ProtocolType::TCP2QUIC ? "TCP->QUIC"sv - : "(unknown-protocol-type)"sv; - } - - // namespace util - // { - // static void ExpireSNodeSessions(/* std::chrono::milliseconds now, SNodeConnectionMap& sessions */); - - // static void DeregisterDeadSessions(/* std::chrono::milliseconds now, ConnectionMap& sessions */); - - // static void TickRemoteSessions( - // /* std::chrono::milliseconds now, - // ConnectionMap& remoteSessions, - // ConnectionMap& deadSessions, - // std::unordered_map& sessions */); - - // static void ExpireConvoSessions( - // /* std::chrono::milliseconds now, std::unordered_map& sessions */); - - // static void StopRemoteSessions(/* ConnectionMap& remoteSessions */); - - // static void StopSnodeSessions(/* SNodeConnectionMap& sessions */); - - // static bool HasPathToService( - // /* const Address& addr, const ConnectionMap& remoteSessions */); - - // static bool GetConvoTagsForService( - // /* const std::unordered_map& sessions, - // const Address& addr, - // std::set& tags */); - // } // namespace util - - // template - // static std:: - // unordered_set, path::Endpoint_Hash, path::endpoint_comparator> - // GetManyPathsWithUniqueEndpoints( - // /* Endpoint_t* ep, - // size_t N, - // std::optional maybeLocation = std::nullopt, - // size_t tries = 10 */) - // { - // // std::unordered_set exclude; - // std::unordered_set, path::Endpoint_Hash, path::endpoint_comparator> - // paths; - // // do - // // { - // // --tries; - // // std::shared_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 diff --git a/llarp/session/session.cpp b/llarp/session/session.cpp index 457f047956..5fb380ce99 100644 --- a/llarp/session/session.cpp +++ b/llarp/session/session.cpp @@ -56,7 +56,7 @@ namespace llarp::session _current_path = std::move(_new_path); - _current_hop_id = _current_path->intro_old.pivot_hop_id; + _current_hop_id = _current_path->intro.pivot_hid; if (_use_tun) _current_path->link_session([this](bstring data) { diff --git a/llarp/session/session.hpp b/llarp/session/session.hpp index 71a9ae5a58..8db1de9d0c 100644 --- a/llarp/session/session.hpp +++ b/llarp/session/session.hpp @@ -3,9 +3,9 @@ #include #include #include +#include #include #include -#include #include diff --git a/llarp/vpn/egres_packet_router.hpp b/llarp/vpn/egres_packet_router.hpp index 1963eca553..98544d4cd1 100644 --- a/llarp/vpn/egres_packet_router.hpp +++ b/llarp/vpn/egres_packet_router.hpp @@ -2,7 +2,6 @@ #include #include -#include #include #include diff --git a/llarp/vpn/linux.hpp b/llarp/vpn/linux.hpp index 55c3ab3fc8..ca209bdddd 100644 --- a/llarp/vpn/linux.hpp +++ b/llarp/vpn/linux.hpp @@ -28,6 +28,8 @@ namespace llarp::vpn inline constexpr ipv4 ipv4_subnet{255, 255, 255, 255}; + inline constexpr std::array if_ipv6_addrs{ipv6{}, ipv6{0x4000}, ipv6{0x8000}, ipv6{0xc000}}; + struct in6_ifreq { in6_addr addr; @@ -219,20 +221,6 @@ namespace llarp::vpn auto in6 = v6.to_in6(); std::memcpy(&data, &in6, sizeof(in6_addr)); } - - _inet_addr(net::ipv4addr_t addr, size_t bits = 32) - { - family = AF_INET; - bitlen = bits; - std::memcpy(data, &addr.n, 4); - } - - _inet_addr(net::ipv6addr_t addr, size_t bits = 128) - { - family = AF_INET6; - bitlen = bits; - std::memcpy(data, &addr.n, 16); - } }; void make_blackhole(int cmd, int flags, int af) @@ -336,10 +324,10 @@ namespace llarp::vpn if (const auto maybe6 = Net().get_interface_ipv6_addr(info.ifname)) { const _inet_addr gateway6{*maybe6}; - for (const std::string str : {"::", "4000::", "8000::", "c000::"}) + + for (const auto& v6 : if_ipv6_addrs) { - const _inet_addr hole6{net::ipv6addr_t::from_string(str), 2}; - make_route(cmd, flags, hole6, gateway6, GatewayMode::eUpperDefault, info.index); + make_route(cmd, flags, _inet_addr{v6}, gateway6, GatewayMode::eUpperDefault, info.index); } } } diff --git a/test/service/test_llarp_service_identity.cpp b/test/service/test_llarp_service_identity.cpp index 1a2b29f166..bc819631cf 100644 --- a/test/service/test_llarp_service_identity.cpp +++ b/test/service/test_llarp_service_identity.cpp @@ -1,9 +1,6 @@ #include -#include #include #include -#include -#include #include #include From 1b14e7908aecb5b057878d4f87411ebb24e58638 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 24 Oct 2024 06:35:42 -0700 Subject: [PATCH 10/44] squash; kick le net --- external/oxen-libquic | 2 +- llarp/contact/client_contact.hpp | 8 ++------ llarp/dht/node.hpp | 2 +- llarp/handlers/session.cpp | 6 +++--- llarp/link/link_manager.cpp | 2 ++ llarp/link/link_manager.hpp | 4 ++-- 6 files changed, 11 insertions(+), 13 deletions(-) diff --git a/external/oxen-libquic b/external/oxen-libquic index d837250265..f64ecf62f0 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit d83725026529c259395d2abc2d3e91840d67cdc6 +Subproject commit f64ecf62f00534fb09ef371322d276bc58549b9e diff --git a/llarp/contact/client_contact.hpp b/llarp/contact/client_contact.hpp index 17d7143932..81c496443a 100644 --- a/llarp/contact/client_contact.hpp +++ b/llarp/contact/client_contact.hpp @@ -46,12 +46,8 @@ namespace llarp TCP2QUIC = 1 << 5, }; - /** TODO: - - LocalCC - - holds the derived Ed25519PrivateData - - RemoteCC: - - */ + // TESTNET: + inline static constexpr auto CC_PUBLISH_INTERVAL{5min}; /** ClientContact On the wire we encode the data as a dict containing: diff --git a/llarp/dht/node.hpp b/llarp/dht/node.hpp index 2326d15cff..4c9804c8b0 100644 --- a/llarp/dht/node.hpp +++ b/llarp/dht/node.hpp @@ -32,7 +32,7 @@ namespace llarp::dht CCNode(EncryptedClientContact other) : client_contact{std::move(other)}, ID{client_contact.blinded_pubkey} {} - nlohmann::json ExtractStatus() const { return nlohmann::json{{"key", client_contact.key()}}; } + nlohmann::json ExtractStatus() const { return nlohmann::json{{"key", client_contact.key().to_string()}}; } bool operator<(const CCNode& other) const { return client_contact.signed_at < other.client_contact.signed_at; } }; diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index d8a153e5cb..48bac59103 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -138,11 +138,11 @@ namespace llarp::handlers { if (should_publish_cc) { - log::debug(logcat, "Starting ClientContact publish ticker..."); + log::critical(logcat, "Starting ClientContact publish ticker..."); _cc_publisher = _router.loop()->call_every( - path::DEFAULT_LIFETIME, + CC_PUBLISH_INTERVAL, [this]() { - log::info(logcat, "Updating and publishing ClientContact..."); + log::critical(logcat, "Updating and publishing ClientContact..."); update_and_publish_localcc(get_current_client_intros()); }, true); diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index a70eb5fc1b..5c4316ea1a 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1086,6 +1086,8 @@ namespace llarp void LinkManager::handle_publish_cc(std::string_view body, std::function respond) { + log::critical(logcat, "Received request to publish client contact!"); + EncryptedClientContact enc; bool is_relayed; uint64_t relay_order; diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index cb6c8be5d6..f48248b2d9 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -285,8 +285,8 @@ namespace llarp void (LinkManager::*)(std::string_view body, std::function respond)> path_requests = { {"resolve_ons"sv, &LinkManager::handle_resolve_ons}, - {"publish_intro"sv, &LinkManager::handle_publish_cc}, - {"find_intro"sv, &LinkManager::handle_find_cc}}; + {"publish_cc"sv, &LinkManager::handle_publish_cc}, + {"find_cc"sv, &LinkManager::handle_find_cc}}; // Path relaying void handle_path_control(oxen::quic::message, const RouterID& from); From 0805844b3b9d057a88de5967366bd34c94257d50 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 24 Oct 2024 08:20:37 -0700 Subject: [PATCH 11/44] testnet kick --- llarp/contact/client_contact.cpp | 2 +- llarp/contact/client_contact.hpp | 2 +- llarp/handlers/session.cpp | 15 +++--- llarp/link/link_manager.cpp | 18 ++++--- llarp/path/path.cpp | 92 +++++--------------------------- llarp/path/path.hpp | 8 ++- llarp/path/path_context.cpp | 2 +- llarp/path/path_handler.cpp | 14 +++-- llarp/path/path_handler.hpp | 2 +- 9 files changed, 47 insertions(+), 108 deletions(-) diff --git a/llarp/contact/client_contact.cpp b/llarp/contact/client_contact.cpp index 991bf3893f..116d0a26f4 100644 --- a/llarp/contact/client_contact.cpp +++ b/llarp/contact/client_contact.cpp @@ -35,10 +35,10 @@ namespace llarp void ClientContact::handle_updated_field(intro_set iset) { - log::trace(logcat, "ClientContact storing updated ClientIntros..."); if (iset.empty()) throw std::invalid_argument{"Cannot publish ClientContact with no ClientIntros!"}; intros = std::move(iset); + log::debug(logcat, "ClientContact stored updated ClientIntros (n={})...", intros.size()); } void ClientContact::handle_updated_field(std::unordered_set srvs) diff --git a/llarp/contact/client_contact.hpp b/llarp/contact/client_contact.hpp index 81c496443a..98e90515c8 100644 --- a/llarp/contact/client_contact.hpp +++ b/llarp/contact/client_contact.hpp @@ -47,7 +47,7 @@ namespace llarp }; // TESTNET: - inline static constexpr auto CC_PUBLISH_INTERVAL{5min}; + inline static constexpr auto CC_PUBLISH_INTERVAL{1min}; /** ClientContact On the wire we encode the data as a dict containing: diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index 48bac59103..851f6516b9 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -55,12 +55,14 @@ namespace llarp::handlers assert(not _is_snode_service); _exit_policy = net_config.traffic_policy; - // _local_cc.exit_policy = _exit_policy; // TESTNET: + client_contact.exit_policy = _exit_policy; } - if (not net_config.srv_records.empty()) // TESTNET: + if (not net_config.srv_records.empty()) + { _srv_records.merge(net_config.srv_records); - // _local_cc.SRVs = std::move(net_config.srv_records); + client_contact.SRVs = _srv_records; + } if (use_tokens = not net_config.auth_static_tokens.empty(); use_tokens) _static_auth_tokens.merge(net_config.auth_static_tokens); @@ -104,11 +106,6 @@ namespace llarp::handlers _exit_policy); should_publish_cc = net_config.is_reachable; - - if (should_publish_cc) - { - // - } } void SessionEndpoint::build_more(size_t n) @@ -402,6 +399,8 @@ namespace llarp::handlers { bool ret{true}; + log::critical(logcat, "Publishing new EncryptedClientContact: {}", ecc.bt_payload()); + { Lock_t l{paths_mutex}; diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 5c4316ea1a..dbf831b73e 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -319,7 +319,7 @@ namespace llarp { if (alpn == alpns::C_ALPNS) { - log::critical(logcat, "{} node accepting client connection (remote ID:{})!", us, other); + log::critical(logcat, "{} accepting client connection (remote ID:{})!", us, other); ep->client_conns.emplace(other, nullptr); return true; } @@ -351,7 +351,7 @@ namespace llarp log::critical( logcat, - "{} node received inbound with ongoing outbound to remote " + "{} received inbound with ongoing outbound to remote " "(RID:{}); {}!", us, other, @@ -360,13 +360,12 @@ namespace llarp return defer_to_incoming; } - log::critical( - logcat, "{} node accepting inbound from registered remote (RID:{})", us, other); + log::critical(logcat, "{} accepting inbound from registered remote (RID:{})", us, other); } else log::critical( logcat, - "{} node was unable to confirm remote (RID:{}) is registered; " + "{} was unable to confirm remote (RID:{}) is registered; " "rejecting " "connection!", us, @@ -375,7 +374,7 @@ namespace llarp return result; } - log::critical(logcat, "{} node received unknown ALPN; rejecting connection!", us); + log::critical(logcat, "{} received unknown ALPN; rejecting connection!", us); return false; } @@ -1127,7 +1126,7 @@ namespace llarp if (is_relayed) { - if (is_relayed >= path::DEFAULT_PATHS_HELD) + if (relay_order >= path::DEFAULT_PATHS_HELD) { log::error(logcat, "Received PublishClientContact with invalid relay order: {}", relay_order); return respond(PublishClientContact::INVALID_ORDER); @@ -1207,7 +1206,7 @@ namespace llarp if (is_relayed) { - if (is_relayed >= path::DEFAULT_PATHS_HELD) + if (relay_order >= path::DEFAULT_PATHS_HELD) { log::error(logcat, "Received FindClientContact with invalid relay order: {}", relay_order); return respond(FindClientContact::INVALID_ORDER); @@ -1737,6 +1736,9 @@ namespace llarp if (not hop) return; + if (response.timed_out) + log::debug(logcat, "Path control message timed out!"); + ustring hop_id, nonce, payload; try diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index f3e2eaa65d..9541fa6c45 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -144,29 +144,22 @@ namespace llarp::path // _role &= ePathRoleExit; } - std::string Path::make_outer_payload(ustring_view payload, SymmNonce& nonce) + std::string Path::make_outer_payload(char* data, size_t len) { + auto nonce = SymmNonce::make_random(); // chacha and mutate nonce for each hop for (const auto& hop : hops) { - nonce = crypto::onion( - const_cast(payload.data()), payload.size(), hop.shared, nonce, hop.nonceXOR); + nonce = crypto::onion(reinterpret_cast(data), len, hop.shared, nonce, hop.nonceXOR); } - return Onion::serialize(nonce, upstream_txid(), payload); - } - - std::string Path::make_outer_payload(ustring_view payload) - { - auto nonce = SymmNonce::make_random(); - - return make_outer_payload(payload, nonce); + return Onion::serialize(nonce, upstream_txid(), {data, len}); } bool Path::send_path_data_message(std::string data) { auto payload = PathData::serialize(std::move(data), _router.local_rid()); - auto outer_payload = make_outer_payload(to_usv(payload)); + auto outer_payload = make_outer_payload(payload.data(), payload.size()); return _router.send_data_message(upstream_rid(), std::move(outer_payload)); } @@ -174,7 +167,7 @@ namespace llarp::path bool Path::send_path_control_message(std::string endpoint, std::string body, std::function func) { auto inner_payload = PathControl::serialize(std::move(endpoint), std::move(body)); - auto outer_payload = make_outer_payload(to_usv(inner_payload)); + auto outer_payload = make_outer_payload(inner_payload.data(), inner_payload.size()); return _router.send_control_message( upstream_rid(), @@ -332,9 +325,6 @@ namespace llarp::path {"lastLatencyTest", to_json(last_latency_test)}, {"expired", is_expired(now)}, {"ready", is_ready()}, - // {"txRateCurrent", m_LastTXRate}, - // {"rxRateCurrent", m_LastRXRate}, - // {"hasExit", SupportsAnyRoles(ePathRoleExit)} }; std::vector hopsObj; @@ -343,30 +333,6 @@ namespace llarp::path }); obj["hops"] = hopsObj; - // switch (_status) - // { - // case PathStatus::BUILDING: - // obj["status"] = "building"; - // break; - // case PathStatus::ESTABLISHED: - // obj["status"] = "established"; - // break; - // case PathStatus::TIMEOUT: - // obj["status"] = "timeout"; - // break; - // case PathStatus::EXPIRED: - // obj["status"] = "expired"; - // break; - // case PathStatus::FAILED: - // obj["status"] = "failed"; - // break; - // case PathStatus::IGNORE: - // obj["status"] = "ignored"; - // break; - // default: - // obj["status"] = "unknown"; - // break; - // } return obj; } @@ -408,6 +374,9 @@ namespace llarp::path void Path::Tick(std::chrono::milliseconds now) { + if (not is_ready()) + return; + if (is_expired(now)) return; @@ -471,25 +440,14 @@ namespace llarp::path void Path::set_established() { + log::info(logcat, "Path marked as successfully established!"); _established = true; + intro.expiry = llarp::time_now_ms() + path::DEFAULT_LIFETIME; } bool Path::is_expired(std::chrono::milliseconds now) const { - (void)now; - // if (_status == PathStatus::FAILED) - // return true; - // if (_status == PathStatus::BUILDING) - // return false; - // if (_status == PathStatus::TIMEOUT) - // { - // return now >= last_recv_msg + PathReanimationTimeout; - // } - // if (_status == PathStatus::ESTABLISHED or _status == PathStatus::IGNORE) - // { - // return now >= ExpireTime(); - // } - return true; + return intro.is_expired(now); } std::string Path::name() const @@ -497,32 +455,6 @@ namespace llarp::path return fmt::format("TX={} RX={}", upstream_txid().to_string(), upstream_rxid().to_string()); } - /* TODO: replace this with sending an onion-ed data message - bool Path::SendRoutingMessage(std::string payload, Router*) - { - std::string buf(MAX_LINK_MSG_SIZE / 2, '\0'); - buf.insert(0, payload); - - // make nonce - TunnelNonce N; - N.Randomize(); - - // pad smaller messages - if (payload.size() < PAD_SIZE) - { - // randomize padding - crypto::randbytes( - reinterpret_cast(buf.data()) + payload.size(), PAD_SIZE - - payload.size()); - } - log::debug(logcat, "Sending {}B routing message to {}", buf.size(), Endpoint()); - - // TODO: path relaying here - - return true; - } - */ - template static std::chrono::milliseconds computeLatency(const Samples_t& samps) { diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 682d209f8c..b135dffbda 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -44,9 +44,9 @@ namespace llarp std::weak_ptr handler; - ClientIntro intro; + ClientIntro intro{}; - std::chrono::milliseconds buildStarted = 0s; + std::chrono::milliseconds buildStarted{0s}; Path( Router& rtr, @@ -161,9 +161,7 @@ namespace llarp static constexpr bool to_string_formattable = true; private: - std::string make_outer_payload(ustring_view payload); - - std::string make_outer_payload(ustring_view payload, SymmNonce& nonce); + std::string make_outer_payload(char* data, size_t len); bool SendLatencyMessage(Router* r); diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index c8e882bbc2..56267f4af2 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -66,7 +66,7 @@ namespace llarp::path for (auto& [_, p] : _path_map) { - if (p->is_ready() and not p->intro.is_expired(now)) + if (p->is_ready() and not p->is_expired(now)) intros.emplace(p->intro); } diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index a6a4ea1b3d..48d4682304 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -169,7 +169,7 @@ namespace llarp::path size_t PathHandler::paths_at_time(std::chrono::milliseconds futureTime) const { size_t num = 0; - Lock_t l(paths_mutex); + Lock_t l{paths_mutex}; for (const auto& item : _paths) { @@ -188,11 +188,14 @@ namespace llarp::path // called within the scope of locked mutex void PathHandler::tick_paths() { + Lock_t l{paths_mutex}; + const auto now = llarp::time_now_ms(); - for (auto& item : _paths) + for (auto& [_, p] : _paths) { - item.second->Tick(now); + if (p) + p->Tick(now); } } @@ -468,6 +471,8 @@ namespace llarp::path bool PathHandler::build_path_to_random() { + Lock_t l(paths_mutex); + if (auto maybe_hops = get_hops_to_random()) { build(*maybe_hops); @@ -480,6 +485,8 @@ namespace llarp::path bool PathHandler::build_path_aligned_to_remote(const NetworkAddress& remote) { + Lock_t l(paths_mutex); + if (auto maybe_hops = aligned_hops_to_remote(remote.router_id())) { build(*maybe_hops); @@ -594,6 +601,7 @@ namespace llarp::path return _router.send_control_message(std::move(upstream), "path_build", std::move(payload), std::move(handler)); } + // called within the scope of a locked mutex void PathHandler::build(std::vector hops) { if (pre_build(hops); auto new_path = build1(hops)) diff --git a/llarp/path/path_handler.hpp b/llarp/path/path_handler.hpp index b8e5b22dd2..3b82e07212 100644 --- a/llarp/path/path_handler.hpp +++ b/llarp/path/path_handler.hpp @@ -33,7 +33,7 @@ namespace llarp inline constexpr size_t MAX_PATHS{32}; // default number of paths per PathHandler - inline constexpr size_t DEFAULT_PATHS_HELD{1}; + inline constexpr size_t DEFAULT_PATHS_HELD{4}; // forward declare struct Path; From de4843ca1c44eda1b73c945f17e10e5fcb820e38 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Fri, 25 Oct 2024 07:22:22 -0700 Subject: [PATCH 12/44] Refactored path message serialization - DRYing out message serialization across path message types --- external/oxen-libquic | 2 +- llarp/crypto/crypto.cpp | 7 +- llarp/crypto/crypto.hpp | 6 +- llarp/handlers/session.cpp | 8 +- llarp/link/link_manager.cpp | 356 ++++++++++++++++++------------------ llarp/messages/common.hpp | 74 ++------ llarp/messages/path.hpp | 352 ++++++++++++++++++----------------- llarp/messages/session.hpp | 3 +- llarp/path/path.cpp | 37 ++-- llarp/path/path.hpp | 4 +- llarp/path/path_context.cpp | 16 -- llarp/path/path_context.hpp | 2 - llarp/path/path_handler.cpp | 11 +- llarp/path/path_handler.hpp | 2 +- llarp/path/path_types.hpp | 6 +- llarp/path/transit_hop.cpp | 13 +- llarp/path/transit_hop.hpp | 12 +- llarp/router/router.cpp | 2 +- 18 files changed, 442 insertions(+), 471 deletions(-) diff --git a/external/oxen-libquic b/external/oxen-libquic index f64ecf62f0..b01fd9e349 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit f64ecf62f00534fb09ef371322d276bc58549b9e +Subproject commit b01fd9e349515034d2412eb3bc1e5784287caf95 diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index 10bc5a09be..da583b2d1d 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -262,9 +262,12 @@ namespace llarp } void crypto::derive_decrypt_outer_wrapping( - const Ed25519SecretKey& local_sk, const PubKey& remote, const SymmNonce& nonce, uspan encrypted) + const Ed25519SecretKey& local_sk, + SharedSecret& shared, + const PubKey& remote, + const SymmNonce& nonce, + uspan encrypted) { - SharedSecret shared; // derive shared secret using ephemeral pubkey and our secret key (and nonce) if (!crypto::dh_server(shared, remote, local_sk, nonce)) { diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index efbcabbb16..e0faaf3776 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -73,7 +73,11 @@ namespace llarp /// pubkey and the provided nonce. The encrypted payload is mutated in-place. Will throw on failure of either /// the server DH derivation or the xchacha20 payload mutation void derive_decrypt_outer_wrapping( - const Ed25519SecretKey& local, const PubKey& remote, const SymmNonce& nonce, uspan encrypted); + const Ed25519SecretKey& local, + SharedSecret& shared, + const PubKey& remote, + const SymmNonce& nonce, + uspan encrypted); bool make_scalar(AlignedBuffer<32>& out, const PubKey& k, uint64_t i); diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index 851f6516b9..66380c3ecb 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -36,6 +36,12 @@ namespace llarp::handlers _running = false; + if (_cc_publisher) + { + log::debug(logcat, "ClientContact publish ticker stopped!"); + _cc_publisher->stop(); + } + Lock_t l{paths_mutex}; _sessions.stop_sessions(send_close); @@ -145,7 +151,7 @@ namespace llarp::handlers true); } else - log::debug(logcat, "SessionEndpoint configured to NOT publish ClientContact..."); + log::info(logcat, "SessionEndpoint configured to NOT publish ClientContact..."); } void SessionEndpoint::resolve_ons_mappings() diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index dbf831b73e..73d6a23572 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -713,7 +713,7 @@ namespace llarp try { oxenc::bt_dict_consumer btdc{message}; - std::tie(hop_id_str, nonce, payload) = Onion::deserialize(btdc); + std::tie(hop_id_str, nonce, payload) = ONION::deserialize_hop(btdc); } catch (const std::exception& e) { @@ -739,7 +739,7 @@ namespace llarp try { oxenc::bt_dict_consumer btdc{payload}; - std::tie(sender, data) = PathData::deserialize(btdc); + std::tie(sender, data) = PATH::DATA::deserialize(btdc); if (auto session = _router.session_endpoint()->get_session(sender)) { @@ -763,7 +763,7 @@ namespace llarp const auto& next_id = hop_is_rx ? hop->txid() : hop->rxid(); const auto& next_router = hop_is_rx ? hop->upstream() : hop->downstream(); - std::string new_payload = Onion::serialize(symmnonce, next_id, payload); + std::string new_payload = ONION::serialize_hop(next_id.to_view(), symmnonce, payload); send_data_message(next_router, std::move(new_payload)); } @@ -1249,34 +1249,34 @@ namespace llarp if (!_router.path_context()->is_transit_allowed()) { log::warning(logcat, "got path build request when not permitting transit"); - m.respond(PathBuildMessage::NO_TRANSIT, true); + m.respond(PATH::BUILD::NO_TRANSIT, true); return; } try { - auto frames = Frames::deserialize(m.body()); + auto frames = ONION::deserialize_frames(m.body()); auto n_frames = frames.size(); if (n_frames != path::MAX_LEN) { log::info(logcat, "Path build message with wrong number of frames: {}", frames.size()); - return m.respond(PathBuildMessage::BAD_FRAMES, true); + return m.respond(PATH::BUILD::BAD_FRAMES, true); } log::trace(logcat, "Deserializing frame: {}", buffer_printer{frames.front()}); SymmNonce nonce; - PubKey remote_pk; ustring hop_payload; + SharedSecret shared; - std::tie(nonce, remote_pk, hop_payload) = - PathBuildMessage::deserialize_hop(oxenc::bt_dict_consumer{frames.front()}, _router.identity()); + std::tie(nonce, shared, hop_payload) = + PATH::BUILD::deserialize_hop(oxenc::bt_dict_consumer{frames.front()}, _router.identity()); log::trace(logcat, "Deserializing hop payload: {}", buffer_printer{hop_payload}); auto hop = path::TransitHop::deserialize_hop( - oxenc::bt_dict_consumer{hop_payload}, from, _router, remote_pk, nonce); + oxenc::bt_dict_consumer{hop_payload}, from, _router, std::move(shared)); hop->started = _router.now(); set_conn_persist(hop->downstream(), hop->expiry_time() + 10s); @@ -1321,7 +1321,7 @@ namespace llarp send_control_message( std::move(upstream), "path_build", - Frames::serialize(std::move(frames)), + ONION::serialize_frames(std::move(frames)), [this, transit_hop = std::move(hop), prev_message = std::move(m)](oxen::quic::message m) mutable { if (m) { @@ -1348,6 +1348,173 @@ namespace llarp } } + void LinkManager::handle_path_control(oxen::quic::message m, const RouterID& /* from */) + { + ustring nonce, hop_id_str, payload; + + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + std::tie(hop_id_str, nonce, payload) = ONION::deserialize_hop(btdc); + } + catch (const std::exception& e) + { + log::warning(logcat, "Exception: {}", e.what()); + return; + } + + auto symmnonce = SymmNonce{nonce.data()}; + HopID hopid{hop_id_str.data()}; + auto hop = _router.path_context()->get_transit_hop(hopid); + + // TODO: use "path_control" for both directions? If not, drop message on + // floor if we don't have the path_id in question; if we decide to make this + // bidirectional, will need to check if we have a Path with path_id. + if (not hop) + return; + + symmnonce = crypto::onion(payload.data(), payload.size(), hop->shared, symmnonce, hop->nonceXOR); + + // if terminal hop, payload should contain a request (e.g. "ons_resolve"); handle and respond. + if (hop->terminal_hop) + { + handle_inner_request( + std::move(m), + std::string{reinterpret_cast(payload.data()), payload.size()}, + std::move(hop)); + return; + } + + auto hop_is_rx = hop->rxid() == hopid; + + const auto& next_id = hop_is_rx ? hop->txid() : hop->rxid(); + const auto& next_router = hop_is_rx ? hop->upstream() : hop->downstream(); + + std::string new_payload = ONION::serialize_hop(next_id.to_view(), symmnonce, payload); + + send_control_message( + next_router, + "path_control"s, + std::move(new_payload), + [hop_weak = hop->weak_from_this(), hopid, prev_message = std::move(m)]( + oxen::quic::message response) mutable { + auto hop = hop_weak.lock(); + + if (not hop) + return; + + if (response.timed_out) + log::debug(logcat, "Path control message timed out!"); + + ustring hop_id, nonce, payload; + + try + { + oxenc::bt_dict_consumer btdc{response.body()}; + std::tie(hop_id, nonce, payload) = ONION::deserialize_hop(btdc); + } + catch (const std::exception& e) + { + log::warning(logcat, "Exception: {}", e.what()); + return; + } + + auto symmnonce = SymmNonce{nonce.data()}; + auto resp_payload = ONION::serialize_hop(hop_id, symmnonce, payload); + prev_message.respond(std::move(resp_payload), false); + }); + } + + void LinkManager::handle_inner_request( + oxen::quic::message m, std::string payload, std::shared_ptr hop) + { + std::string endpoint, body; + + try + { + oxenc::bt_dict_consumer btdc{payload}; + std::tie(endpoint, body) = PATH::CONTROL::deserialize(btdc); + } + catch (const std::exception& e) + { + log::warning(logcat, "Exception: {}", e.what()); + return; + } + + // If a handler exists for "method", call it; else drop request on the floor. + auto itr = path_requests.find(endpoint); + + if (itr == path_requests.end()) + { + log::info(logcat, "Received path control request \"{}\", which has no handler.", endpoint); + return; + } + + auto respond = [m = std::move(m), hop_weak = hop->weak_from_this()](std::string response) mutable { + auto hop = hop_weak.lock(); + if (not hop) + return; // transit hop gone, drop response + + auto n = SymmNonce::make_random(); + m.respond(ONION::serialize_hop(hop->rxid().to_view(), n, response), false); + }; + + std::invoke(itr->second, this, std::move(body), std::move(respond)); + } + + void LinkManager::handle_initiate_session(oxen::quic::message m) + { + if (not m) + { + log::info(logcat, "Initiate session message timed out!"); + return; + } + + NetworkAddress initiator; + service::SessionTag tag; + HopID pivot_txid; + bool use_tun; + std::optional maybe_auth = std::nullopt; + std::shared_ptr path_ptr; + + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + + std::tie(initiator, pivot_txid, tag, use_tun, maybe_auth) = + InitiateSession::decrypt_deserialize(btdc, _router.identity()); + + if (not _router.session_endpoint()->validate(initiator, maybe_auth)) + { + log::warning(logcat, "Failed to authenticate session initiation request from remote:{}", initiator); + return m.respond(InitiateSession::AUTH_DENIED, true); + } + + path_ptr = _router.path_context()->get_path(pivot_txid); + + if (not path_ptr) + { + log::warning(logcat, "Failed to find local path corresponding to session over pivot: {}", pivot_txid); + return m.respond(messages::ERROR_RESPONSE, true); + } + + if (_router.session_endpoint()->prefigure_session( + std::move(initiator), std::move(tag), std::move(path_ptr), use_tun)) + { + return m.respond(messages::OK_RESPONSE); + } + + log::warning(logcat, "Failed to configure InboundSession!"); + } + catch (const std::exception& e) + { + log::warning(logcat, "Exception: {}", e.what()); + } + + _router.path_context()->drop_path(path_ptr); + m.respond(messages::ERROR_RESPONSE, true); + } + void LinkManager::handle_path_latency(oxen::quic::message m) { try @@ -1681,173 +1848,6 @@ namespace llarp // path_ptr->mark_exit_closed(); } - void LinkManager::handle_path_control(oxen::quic::message m, const RouterID& /* from */) - { - ustring nonce, hop_id_str, payload; - - try - { - oxenc::bt_dict_consumer btdc{m.body()}; - std::tie(hop_id_str, nonce, payload) = Onion::deserialize(btdc); - } - catch (const std::exception& e) - { - log::warning(logcat, "Exception: {}", e.what()); - return; - } - - auto symmnonce = SymmNonce{nonce.data()}; - HopID hopid{hop_id_str.data()}; - auto hop = _router.path_context()->get_transit_hop(hopid); - - // TODO: use "path_control" for both directions? If not, drop message on - // floor if we don't have the path_id in question; if we decide to make this - // bidirectional, will need to check if we have a Path with path_id. - if (not hop) - return; - - symmnonce = crypto::onion(payload.data(), payload.size(), hop->shared, symmnonce, hop->nonceXOR); - - // if terminal hop, payload should contain a request (e.g. "ons_resolve"); handle and respond. - if (hop->terminal_hop) - { - handle_inner_request( - std::move(m), - std::string{reinterpret_cast(payload.data()), payload.size()}, - std::move(hop)); - return; - } - - auto hop_is_rx = hop->rxid() == hopid; - - const auto& next_id = hop_is_rx ? hop->txid() : hop->rxid(); - const auto& next_router = hop_is_rx ? hop->upstream() : hop->downstream(); - - std::string new_payload = Onion::serialize(symmnonce, next_id, payload); - - send_control_message( - next_router, - "path_control"s, - std::move(new_payload), - [hop_weak = hop->weak_from_this(), hopid, prev_message = std::move(m)]( - oxen::quic::message response) mutable { - auto hop = hop_weak.lock(); - - if (not hop) - return; - - if (response.timed_out) - log::debug(logcat, "Path control message timed out!"); - - ustring hop_id, nonce, payload; - - try - { - oxenc::bt_dict_consumer btdc{response.body()}; - std::tie(hop_id, nonce, payload) = Onion::deserialize(btdc); - } - catch (const std::exception& e) - { - log::warning(logcat, "Exception: {}", e.what()); - return; - } - - auto symmnonce = SymmNonce{nonce.data()}; - auto resp_payload = Onion::serialize(symmnonce, HopID{hop_id.data()}, payload); - prev_message.respond(std::move(resp_payload), false); - }); - } - - void LinkManager::handle_inner_request( - oxen::quic::message m, std::string payload, std::shared_ptr hop) - { - std::string endpoint, body; - - try - { - oxenc::bt_dict_consumer btdc{payload}; - std::tie(endpoint, body) = PathControl::deserialize(btdc); - } - catch (const std::exception& e) - { - log::warning(logcat, "Exception: {}", e.what()); - return; - } - - // If a handler exists for "method", call it; else drop request on the floor. - auto itr = path_requests.find(endpoint); - - if (itr == path_requests.end()) - { - log::info(logcat, "Received path control request \"{}\", which has no handler.", endpoint); - return; - } - - auto respond = [m = std::move(m), hop_weak = hop->weak_from_this()](std::string response) mutable { - auto hop = hop_weak.lock(); - if (not hop) - return; // transit hop gone, drop response - - auto n = SymmNonce::make_random(); - m.respond(Onion::serialize(n, hop->rxid(), response), false); - }; - - std::invoke(itr->second, this, std::move(body), std::move(respond)); - } - - void LinkManager::handle_initiate_session(oxen::quic::message m) - { - if (not m) - { - log::info(logcat, "Initiate session message timed out!"); - return; - } - - NetworkAddress initiator; - service::SessionTag tag; - HopID pivot_txid; - bool use_tun; - std::optional maybe_auth = std::nullopt; - std::shared_ptr path_ptr; - - try - { - oxenc::bt_dict_consumer btdc{m.body()}; - - std::tie(initiator, pivot_txid, tag, use_tun, maybe_auth) = - InitiateSession::decrypt_deserialize(btdc, _router.identity()); - - if (not _router.session_endpoint()->validate(initiator, maybe_auth)) - { - log::warning(logcat, "Failed to authenticate session initiation request from remote:{}", initiator); - return m.respond(InitiateSession::AUTH_DENIED, true); - } - - path_ptr = _router.path_context()->get_path(pivot_txid); - - if (not path_ptr) - { - log::warning(logcat, "Failed to find local path corresponding to session over pivot: {}", pivot_txid); - return m.respond(messages::ERROR_RESPONSE, true); - } - - if (_router.session_endpoint()->prefigure_session( - std::move(initiator), std::move(tag), std::move(path_ptr), use_tun)) - { - return m.respond(messages::OK_RESPONSE); - } - - log::warning(logcat, "Failed to configure InboundSession!"); - } - catch (const std::exception& e) - { - log::warning(logcat, "Exception: {}", e.what()); - } - - _router.path_context()->drop_path(path_ptr); - m.respond(messages::ERROR_RESPONSE, true); - } - void LinkManager::handle_convo_intro(oxen::quic::message m) { if (m.timed_out) diff --git a/llarp/messages/common.hpp b/llarp/messages/common.hpp index 48f37d01a2..386d29a3f1 100644 --- a/llarp/messages/common.hpp +++ b/llarp/messages/common.hpp @@ -10,68 +10,18 @@ #include -namespace llarp +namespace llarp::messages { - namespace messages - { - static auto logcat = log::Cat("messages"); - - inline std::string serialize_response(oxenc::bt_dict supplement = {}) - { - return oxenc::bt_serialize(supplement); - } - - // ideally STATUS is the first key in a bt-dict, so use a single, early ascii char - inline const auto STATUS_KEY = "!"s; - inline const auto TIMEOUT_RESPONSE = serialize_response({{STATUS_KEY, "TIMEOUT"}}); - inline const auto ERROR_RESPONSE = serialize_response({{STATUS_KEY, "ERROR"}}); - inline const auto OK_RESPONSE = serialize_response({{STATUS_KEY, "OK"}}); - } // namespace messages + static auto logcat = log::Cat("messages"); - namespace Onion + inline std::string serialize_response(oxenc::bt_dict supplement = {}) { - static auto logcat = llarp::log::Cat("onion"); - - /** Bt-encoded contents: - - 'h' : HopID of the next layer of the onion - - 'n' : Symmetric nonce used to encrypt the layer - - 'x' : Encrypted payload transmitted to next recipient - */ - inline static std::string serialize( - const SymmNonce& nonce, const HopID& hop_id, const std::string_view& payload) - { - oxenc::bt_dict_producer btdp; - btdp.append("h", hop_id.to_view()); - btdp.append("n", nonce.to_view()); - btdp.append("x", payload); - - return std::move(btdp).str(); - } - - inline static std::string serialize(const SymmNonce& nonce, const HopID& hop_id, const ustring_view& payload) - { - return serialize( - nonce, hop_id, std::string_view{reinterpret_cast(payload.data()), payload.size()}); - } - - inline static std::tuple deserialize(oxenc::bt_dict_consumer& btdc) - { - ustring hopid, nonce, payload; - - try - { - hopid = btdc.require("h"); - nonce = btdc.require("n"); - payload = btdc.require("x"); - } - catch (const std::exception& e) - { - log::warning(logcat, "Exception caught deserializing onion data:{}", e.what()); - throw; - } - - return {std::move(hopid), std::move(nonce), std::move(payload)}; - } - } // namespace Onion - -} // namespace llarp + return oxenc::bt_serialize(supplement); + } + + // ideally STATUS is the first key in a bt-dict, so use a single, early ascii char + inline const auto STATUS_KEY = "!"s; + inline const auto TIMEOUT_RESPONSE = serialize_response({{STATUS_KEY, "TIMEOUT"}}); + inline const auto ERROR_RESPONSE = serialize_response({{STATUS_KEY, "ERROR"}}); + inline const auto OK_RESPONSE = serialize_response({{STATUS_KEY, "OK"}}); +} // namespace llarp::messages diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index 1b5efa2435..155327763d 100644 --- a/llarp/messages/path.hpp +++ b/llarp/messages/path.hpp @@ -9,220 +9,244 @@ namespace llarp { using namespace oxenc::literals; - namespace Frames + namespace ONION { - static auto logcat = llarp::log::Cat("path-build-frames"); - - inline static std::string serialize(std::vector&& frames) + inline static std::string serialize_frames(std::vector&& frames) { return oxenc::bt_serialize(std::move(frames)); } - inline static std::vector deserialize(std::string_view&& buf) + inline static std::vector deserialize_frames(std::string_view&& buf) { return oxenc::bt_deserialize>(buf); } - } // namespace Frames - - namespace PathData - { - static auto logcat = llarp::log::Cat("path-data"); - /** Fields for transmitting Path Data: - - 'b' : request/command body - - 's' : RouterID of sender - NOTE: more fields may be added later as needed, hence the namespacing + /** Bt-encoded contents: + - 'k' : Next upstream HopID (path messages) OR shared pubkey (path builds) + - 'n' : Symmetric nonce used to encrypt the layer + - 'x' : Encrypted payload transmitted to next recipient */ - inline static std::string serialize(std::string body, const RouterID& local) + template + inline static std::string serialize_hop(K key, const SymmNonce& nonce, T encrypted) { oxenc::bt_dict_producer btdp; - btdp.append("b", body); - btdp.append("s", local.to_view()); - return std::move(btdp).str(); - } - - inline static std::tuple deserialize(oxenc::bt_dict_consumer& btdc) - { - RouterID remote; - bstring body; - - try - { - body = btdc.require("b"); - remote.from_string(btdc.require("s")); - auto sender = NetworkAddress::from_pubkey(remote, true); - - return {std::move(sender), std::move(body)}; - } - catch (const std::exception& e) - { - log::warning(logcat, "Exception caught deserializing path data:{}", e.what()); - throw; - } - } - } // namespace PathData + btdp.append("k", key); + btdp.append("n", nonce.to_view()); + btdp.append("x", encrypted); - namespace PathControl - { - static auto logcat = llarp::log::Cat("path-control"); - - /** Fields for transmitting Path Control: - - 'e' : request endpoint being invoked - - 'r' : request body - */ - inline static std::string serialize(std::string endpoint, std::string body) - { - oxenc::bt_dict_producer btdp; - btdp.append("e", endpoint); - btdp.append("r", body); return std::move(btdp).str(); } - inline static std::tuple deserialize(oxenc::bt_dict_consumer& btdc) + inline static std::tuple deserialize_hop(oxenc::bt_dict_consumer& btdc) { - std::string endpoint, body; + ustring hopid, nonce, payload; try { - endpoint = btdc.require("e"); - body = btdc.require("r"); + hopid = btdc.require("k"); + nonce = btdc.require("n"); + payload = btdc.require("x"); } catch (const std::exception& e) { - log::warning(logcat, "Exception caught deserializing path control:{}", e.what()); - throw; + throw std::runtime_error{"Exception caught deserializing onion data:{}"_format(e.what())}; } - return {std::move(endpoint), std::move(body)}; + return {std::move(hopid), std::move(nonce), std::move(payload)}; } - } // namespace PathControl + } // namespace ONION - namespace PathBuildMessage + namespace PATH { - static auto logcat = llarp::log::Cat("path-build"); - - inline constexpr auto bad_frames = "BAD_FRAMES"sv; - inline constexpr auto bad_crypto = "BAD_CRYPTO"sv; - inline constexpr auto no_transit = "NOT ALLOWING TRANSIT"sv; - inline constexpr auto bad_pathid = "BAD PATH ID"sv; - inline constexpr auto bad_lifetime = "BAD PATH LIFETIME (TOO LONG)"sv; - - inline const auto NO_TRANSIT = messages::serialize_response({{messages::STATUS_KEY, no_transit}}); - inline const auto BAD_LIFETIME = messages::serialize_response({{messages::STATUS_KEY, bad_lifetime}}); - inline const auto BAD_FRAMES = messages::serialize_response({{messages::STATUS_KEY, bad_frames}}); - inline const auto BAD_PATHID = messages::serialize_response({{messages::STATUS_KEY, bad_pathid}}); - inline const auto BAD_CRYPTO = messages::serialize_response({{messages::STATUS_KEY, bad_crypto}}); - - /** For each hop: - - Generate an Ed keypair for the hop (`shared_key`) - - Generate a symmetric nonce for subsequent DH - - Derive the shared secret (`hop.shared`) for DH key-exchange using the ED keypair, hop pubkey, and - symmetric nonce - - Encrypt the hop info in-place using `hop.shared` and the generated symmetric nonce from DH - - Generate the XOR nonce by hashing the symmetric key from DH (`hop.shared`) and truncating - - Bt-encoded contents: - - 'n' : symmetric nonce used for DH key-exchange - - 's' : shared pubkey used to derive symmetric key - - 'x' : encrypted payload - - 'l' : path lifetime - - 'r' : rxID (the path ID for messages going *to* the hop) - - 't' : txID (the path ID for messages coming *from* the client/path origin) - - 'u' : upstream hop RouterID - - All of these 'frames' are inserted sequentially into the list and padded with any needed dummy frames - */ - inline static std::string serialize_hop(path::PathHopConfig& hop) + namespace BUILD { - std::string hop_payload; - + static auto logcat = llarp::log::Cat("path-build"); + + inline constexpr auto bad_frames = "BAD_FRAMES"sv; + inline constexpr auto bad_crypto = "BAD_CRYPTO"sv; + inline constexpr auto no_transit = "NOT ALLOWING TRANSIT"sv; + inline constexpr auto bad_pathid = "BAD PATH ID"sv; + inline constexpr auto bad_lifetime = "BAD PATH LIFETIME (TOO LONG)"sv; + + inline const auto NO_TRANSIT = messages::serialize_response({{messages::STATUS_KEY, no_transit}}); + inline const auto BAD_LIFETIME = messages::serialize_response({{messages::STATUS_KEY, bad_lifetime}}); + inline const auto BAD_FRAMES = messages::serialize_response({{messages::STATUS_KEY, bad_frames}}); + inline const auto BAD_PATHID = messages::serialize_response({{messages::STATUS_KEY, bad_pathid}}); + inline const auto BAD_CRYPTO = messages::serialize_response({{messages::STATUS_KEY, bad_crypto}}); + + /** For each hop: + - Generate an Ed keypair for the hop (`shared_key`) + - Generate a symmetric nonce for subsequent DH + - Derive the shared secret (`hop.shared`) for DH key-exchange using the Ed keypair, hop pubkey, and + symmetric nonce + - Encrypt the hop info in-place using `hop.shared` and the generated symmetric nonce from DH + - Generate the XOR nonce by hashing the symmetric key from DH (`hop.shared`) and truncating + + Bt-encoded contents: + - 'k' : shared pubkey used to derive symmetric key + - 'n' : symmetric nonce used for DH key-exchange + - 'x' : encrypted payload + - 'l' : path lifetime + - 'r' : rxID (the path ID for messages going *to* the hop) + - 't' : txID (the path ID for messages coming *from* the client/path origin) + - 'u' : upstream hop RouterID + + All of these 'frames' are inserted sequentially into the list and padded with any needed dummy frames + */ + inline static std::string serialize_hop(path::PathHopConfig& hop) { - oxenc::bt_dict_producer btdp; + std::string hop_payload; - btdp.append("l", path::DEFAULT_LIFETIME.count()); - btdp.append("r", hop.rxID.to_view()); - btdp.append("t", hop.txID.to_view()); - btdp.append("u", hop.upstream.to_view()); + { + oxenc::bt_dict_producer btdp; - hop_payload = std::move(btdp).str(); - } + btdp.append("l", path::DEFAULT_LIFETIME.count()); + btdp.append("r", hop.rxID.to_view()); + btdp.append("t", hop.txID.to_view()); + btdp.append("u", hop.upstream.to_view()); - Ed25519SecretKey ephemeral_key; - crypto::identity_keygen(ephemeral_key); + hop_payload = std::move(btdp).str(); + } - hop.nonce = SymmNonce::make_random(); + Ed25519SecretKey ephemeral_key; + crypto::identity_keygen(ephemeral_key); - crypto::derive_encrypt_outer_wrapping( - ephemeral_key, hop.shared, hop.nonce, hop.rc.router_id(), to_uspan(hop_payload)); + hop.nonce = SymmNonce::make_random(); - // generate nonceXOR value self->hop->pathKey - ShortHash xor_hash; - crypto::shorthash(xor_hash, hop.shared.data(), hop.shared.size()); + crypto::derive_encrypt_outer_wrapping( + ephemeral_key, hop.shared, hop.nonce, hop.rc.router_id(), to_uspan(hop_payload)); - hop.nonceXOR = xor_hash.data(); // nonceXOR is 24 bytes, ShortHash is 32; this will truncate + // generate nonceXOR value self->hop->pathKey + ShortHash xor_hash; + crypto::shorthash(xor_hash, hop.shared.data(), hop.shared.size()); - log::trace( - logcat, - "Hop serialized; nonce: {}, remote router_id: {}, shared pk: {}, shared secret: {}, payload: {}", - hop.nonce.to_string(), - hop.rc.router_id().to_string(), - ephemeral_key.to_pubkey().to_string(), - hop.shared.to_string(), - buffer_printer{hop_payload}); + hop.nonceXOR = xor_hash.data(); // nonceXOR is 24 bytes, ShortHash is 32; this will truncate - oxenc::bt_dict_producer btdp; + log::trace( + logcat, + "Hop serialized; nonce: {}, remote router_id: {}, shared pk: {}, shared secret: {}, payload: {}", + hop.nonce.to_string(), + hop.rc.router_id().to_string(), + ephemeral_key.to_pubkey().to_string(), + hop.shared.to_string(), + buffer_printer{hop_payload}); - btdp.append("n", hop.nonce.to_view()); - btdp.append("s", ephemeral_key.to_pubkey().to_view()); - btdp.append("x", hop_payload); + return ONION::serialize_hop(ephemeral_key.to_pubkey().to_view(), hop.nonce, hop_payload); + } - return std::move(btdp).str(); - } + inline static std::tuple deserialize_hop( + oxenc::bt_dict_consumer&& btdc, const Ed25519SecretKey& local_sk) + { + SymmNonce nonce; + PubKey remote_pk; + ustring hop_payload; + SharedSecret shared; + + try + { + remote_pk.from_string(btdc.require("k")); + nonce.from_string(btdc.require("n")); + hop_payload = btdc.require("x"); + } + catch (const std::exception& e) + { + log::warning(logcat, "Exception caught deserializing hop dict:{}", e.what()); + throw; + } + + log::trace( + logcat, + "Hop deserialized; nonce: {}, remote pk: {}, payload: {}", + nonce.to_string(), + remote_pk.to_string(), + buffer_printer{hop_payload}); + + try + { + crypto::derive_decrypt_outer_wrapping(local_sk, shared, remote_pk, nonce, to_uspan(hop_payload)); + } + catch (...) + { + log::info(logcat, "Failed to derive and decrypt outer wrapping!"); + throw std::runtime_error{BAD_CRYPTO}; + } + + log::trace( + logcat, + "Hop decrypted; nonce: {}, remote pk: {}, payload: {}", + nonce.to_string(), + remote_pk.to_string(), + buffer_printer{hop_payload}); + + return {std::move(nonce), std::move(shared), std::move(hop_payload)}; + } + } // namespace BUILD - inline static std::tuple deserialize_hop( - oxenc::bt_dict_consumer&& btdc, const Ed25519SecretKey& local_sk) + namespace CONTROL { - SymmNonce nonce; - PubKey remote_pk; - ustring hop_payload; - - try + /** Fields for transmitting Path Control: + - 'e' : request endpoint being invoked + - 'r' : request body + */ + inline static std::string serialize(std::string endpoint, std::string body) { - nonce.from_string(btdc.require("n")); - remote_pk.from_string(btdc.require("s")); - hop_payload = btdc.require("x"); + oxenc::bt_dict_producer btdp; + btdp.append("e", endpoint); + btdp.append("r", body); + return std::move(btdp).str(); } - catch (const std::exception& e) + + inline static std::tuple deserialize(oxenc::bt_dict_consumer& btdc) { - log::warning(logcat, "Exception caught deserializing hop dict:{}", e.what()); - throw; + std::string endpoint, body; + + try + { + endpoint = btdc.require("e"); + body = btdc.require("r"); + } + catch (const std::exception& e) + { + throw std::runtime_error{"Exception caught deserializing path control:{}"_format(e.what())}; + } + + return {std::move(endpoint), std::move(body)}; } + } // namespace CONTROL - log::trace( - logcat, - "Hop deserialized; nonce: {}, remote pk: {}, payload: {}", - nonce.to_string(), - remote_pk.to_string(), - buffer_printer{hop_payload}); - - try + namespace DATA + { + /** Fields for transmitting Path Data: + - 'b' : request/command body + - 's' : RouterID of sender + NOTE: more fields may be added later as needed, hence the namespacing + */ + inline static std::string serialize(std::string body, const RouterID& local) { - crypto::derive_decrypt_outer_wrapping(local_sk, remote_pk, nonce, to_uspan(hop_payload)); + oxenc::bt_dict_producer btdp; + btdp.append("b", body); + btdp.append("s", local.to_view()); + return std::move(btdp).str(); } - catch (...) + + inline static std::tuple deserialize(oxenc::bt_dict_consumer& btdc) { - log::info(logcat, "Failed to derive and decrypt outer wrapping!"); - throw std::runtime_error{BAD_CRYPTO}; + RouterID remote; + bstring body; + + try + { + body = btdc.require("b"); + remote.from_string(btdc.require("s")); + auto sender = NetworkAddress::from_pubkey(remote, true); + + return {std::move(sender), std::move(body)}; + } + catch (const std::exception& e) + { + throw std::runtime_error{"Exception caught deserializing path data:{}"_format(e.what())}; + } } - - log::trace( - logcat, - "Hop decrypted; nonce: {}, remote pk: {}, payload: {}", - nonce.to_string(), - remote_pk.to_string(), - buffer_printer{hop_payload}); - - return {std::move(nonce), std::move(remote_pk), std::move(hop_payload)}; - } - } // namespace PathBuildMessage + } // namespace DATA + } // namespace PATH } // namespace llarp diff --git a/llarp/messages/session.hpp b/llarp/messages/session.hpp index 60db08131f..11a0049191 100644 --- a/llarp/messages/session.hpp +++ b/llarp/messages/session.hpp @@ -82,6 +82,7 @@ namespace llarp SymmNonce nonce; RouterID shared_pubkey; ustring payload; + SharedSecret shared; try { @@ -89,7 +90,7 @@ namespace llarp shared_pubkey = RouterID{btdc.require("s")}; payload = btdc.require("x"); - crypto::derive_decrypt_outer_wrapping(local, shared_pubkey, nonce, to_uspan(payload)); + crypto::derive_decrypt_outer_wrapping(local, shared, shared_pubkey, nonce, to_uspan(payload)); { RouterID remote; diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 9541fa6c45..cfc17f3f83 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -144,30 +144,39 @@ namespace llarp::path // _role &= ePathRoleExit; } - std::string Path::make_outer_payload(char* data, size_t len) + std::string Path::make_path_message(std::string&& inner_payload) { - auto nonce = SymmNonce::make_random(); - // chacha and mutate nonce for each hop - for (const auto& hop : hops) + int n_hops = static_cast(hops.size()); + std::string payload{std::move(inner_payload)}; + + // Working from final hop to hop 1, we onion encrypt the message payload with each + // hop's shared secret (this was derived via DH KEM in path building). The encrypted + // payload will then be bt-serialized, and then encrypted/serialized for the next hop. + for (int i = n_hops - 1; i >= 0; --i) { - nonce = crypto::onion(reinterpret_cast(data), len, hop.shared, nonce, hop.nonceXOR); + auto& hop = hops[i]; + + crypto::onion( + reinterpret_cast(payload.data()), payload.size(), hop.shared, hop.nonce, hop.nonceXOR); + + payload = ONION::serialize_hop(hop.upstream.to_view(), hop.nonce, payload); } - return Onion::serialize(nonce, upstream_txid(), {data, len}); + return payload; } bool Path::send_path_data_message(std::string data) { - auto payload = PathData::serialize(std::move(data), _router.local_rid()); - auto outer_payload = make_outer_payload(payload.data(), payload.size()); + auto inner_payload = PATH::DATA::serialize(std::move(data), _router.local_rid()); + auto outer_payload = make_path_message(std::move(inner_payload)); return _router.send_data_message(upstream_rid(), std::move(outer_payload)); } bool Path::send_path_control_message(std::string endpoint, std::string body, std::function func) { - auto inner_payload = PathControl::serialize(std::move(endpoint), std::move(body)); - auto outer_payload = make_outer_payload(inner_payload.data(), inner_payload.size()); + auto inner_payload = PATH::CONTROL::serialize(std::move(endpoint), std::move(body)); + auto outer_payload = make_path_message(std::move(inner_payload)); return _router.send_control_message( upstream_rid(), @@ -190,7 +199,7 @@ namespace llarp::path try { oxenc::bt_dict_consumer btdc{m.body()}; - std::tie(hop_id_str, symmnonce, payload) = Onion::deserialize(btdc); + std::tie(hop_id_str, symmnonce, payload) = ONION::deserialize_hop(btdc); } catch (const std::exception& e) { @@ -219,11 +228,9 @@ namespace llarp::path }); } - bool Path::is_ready() const + bool Path::is_ready(std::chrono::milliseconds now) const { - // if (is_expired(llarp::time_now_ms())) - // return false; - return _established; + return _established ? is_expired(now) : false; } RouterID Path::upstream_rid() diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index b135dffbda..70c5978652 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -126,7 +126,7 @@ namespace llarp bool send_path_data_message(std::string body); - bool is_ready() const; + bool is_ready(std::chrono::milliseconds now = llarp::time_now_ms()) const; RouterID upstream_rid(); const RouterID& upstream_rid() const; @@ -161,7 +161,7 @@ namespace llarp static constexpr bool to_string_formattable = true; private: - std::string make_outer_payload(char* data, size_t len); + std::string make_path_message(std::string&& payload); bool SendLatencyMessage(Router* r); diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index 56267f4af2..86cf03108f 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -57,22 +57,6 @@ namespace llarp::path } } - intro_set PathContext::get_recent_ccs() const - { - Lock_t l{paths_mutex}; - - intro_set intros; - auto now = llarp::time_now_ms(); - - for (auto& [_, p] : _path_map) - { - if (p->is_ready() and not p->is_expired(now)) - intros.emplace(p->intro); - } - - return intros; - } - void PathContext::drop_path(const std::shared_ptr& path) { Lock_t l{paths_mutex}; diff --git a/llarp/path/path_context.hpp b/llarp/path/path_context.hpp index fc54a36bf9..90321369de 100644 --- a/llarp/path/path_context.hpp +++ b/llarp/path/path_context.hpp @@ -47,8 +47,6 @@ namespace llarp::path void drop_paths(std::vector> droplist); - intro_set get_recent_ccs() const; - private: const RouterID _local_rid; diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index 48d4682304..10166002f4 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -263,7 +263,7 @@ namespace llarp::path for (const auto& [_, p] : _paths) { - if (p->is_ready() and not p->intro.is_expired(now)) + if (p and p->is_ready(now)) intros.emplace(p->intro); } @@ -350,7 +350,8 @@ namespace llarp::path for (auto& [_, p] : _paths) { - dissociate_hop_ids(p); + if (p) + dissociate_hop_ids(p); } _paths.clear(); @@ -555,13 +556,13 @@ namespace llarp::path // the same entity from knowing they are part of the same path // (unless they're adjacent in the path; nothing we can do about that obviously). - // i from n_hops downto 0 + // i from n_hops down to 0 for (int i = n_hops - 1; i >= 0; --i) { const auto& next_rid = i == n_hops - 1 ? path_hops[i].rc.router_id() : path_hops[i + 1].rc.router_id(); path_hops[i].upstream = next_rid; - frames[i] = PathBuildMessage::serialize_hop(path_hops[i]); + frames[i] = PATH::BUILD::serialize_hop(path_hops[i]); if (last_len and frames[i].size() != last_len) { @@ -593,7 +594,7 @@ namespace llarp::path _build_stats.attempts++; - return Frames::serialize(std::move(frames)); + return ONION::serialize_frames(std::move(frames)); } bool PathHandler::build3(RouterID upstream, std::string payload, std::function handler) diff --git a/llarp/path/path_handler.hpp b/llarp/path/path_handler.hpp index 3b82e07212..aca8398578 100644 --- a/llarp/path/path_handler.hpp +++ b/llarp/path/path_handler.hpp @@ -130,7 +130,7 @@ namespace llarp Router& _router; size_t num_hops; std::chrono::milliseconds last_build{0s}; - std::chrono::milliseconds build_interval_limit = MIN_PATH_BUILD_INTERVAL; + std::chrono::milliseconds build_interval_limit{MIN_PATH_BUILD_INTERVAL}; std::set snode_blacklist; diff --git a/llarp/path/path_types.hpp b/llarp/path/path_types.hpp index 1956834300..3f17d63b41 100644 --- a/llarp/path/path_types.hpp +++ b/llarp/path/path_types.hpp @@ -31,7 +31,7 @@ namespace llarp /// next hop's router id RouterID upstream; // lifetime - std::chrono::milliseconds lifetime = DEFAULT_LIFETIME; + std::chrono::milliseconds lifetime{DEFAULT_LIFETIME}; nlohmann::json ExtractStatus() const; @@ -51,8 +51,8 @@ namespace llarp }; // milliseconds waiting between builds on a path per router - static constexpr auto MIN_PATH_BUILD_INTERVAL = 500ms; - static constexpr auto PATH_BUILD_RATE = 100ms; + static constexpr auto MIN_PATH_BUILD_INTERVAL{500ms}; + static constexpr auto PATH_BUILD_RATE{100ms}; } // namespace path } // namespace llarp diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index dc46efd374..407808bd71 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -10,7 +10,7 @@ namespace llarp::path static auto logcat = log::Cat("transit-hop"); std::shared_ptr TransitHop::deserialize_hop( - oxenc::bt_dict_consumer&& btdc, const RouterID& src, Router& r, const PubKey& remote_pk, const SymmNonce& nonce) + oxenc::bt_dict_consumer&& btdc, const RouterID& src, Router& r, SharedSecret secret) { auto hop = std::make_shared(); @@ -28,19 +28,16 @@ namespace llarp::path } if (hop->rxid().is_zero() || hop->txid().is_zero()) - throw std::runtime_error{PathBuildMessage::BAD_PATHID}; + throw std::runtime_error{PATH::BUILD::BAD_PATHID}; if (hop->lifetime > path::DEFAULT_LIFETIME) - throw std::runtime_error{PathBuildMessage::BAD_LIFETIME}; + throw std::runtime_error{PATH::BUILD::BAD_LIFETIME}; hop->downstream() = src; + hop->shared = std::move(secret); if (r.path_context()->has_transit_hop(hop)) - throw std::runtime_error{PathBuildMessage::BAD_PATHID}; - - // TODO: get this from the first dh - if (!crypto::dh_server(hop->shared, remote_pk, r.identity(), nonce)) - throw std::runtime_error{PathBuildMessage::BAD_CRYPTO}; + throw std::runtime_error{PATH::BUILD::BAD_PATHID}; // generate hash of hop key for nonce mutation ShortHash xor_hash; diff --git a/llarp/path/transit_hop.hpp b/llarp/path/transit_hop.hpp index 13da518f30..d651c0903d 100644 --- a/llarp/path/transit_hop.hpp +++ b/llarp/path/transit_hop.hpp @@ -27,19 +27,15 @@ namespace llarp // This static factory function is used in path-build logic. The exceptions thrown are the exact response // bodies passed to message::respond(...) function static std::shared_ptr deserialize_hop( - oxenc::bt_dict_consumer&& btdc, - const RouterID& src, - Router& r, - const PubKey& remote_pk, - const SymmNonce& nonce); + oxenc::bt_dict_consumer&& btdc, const RouterID& src, Router& r, SharedSecret secret); SharedSecret shared; SymmNonce nonceXOR; - std::chrono::milliseconds started = 0s; + std::chrono::milliseconds started{0s}; // 10 minutes default - std::chrono::milliseconds lifetime = DEFAULT_LIFETIME; + std::chrono::milliseconds lifetime{DEFAULT_LIFETIME}; uint8_t version; - std::chrono::milliseconds _last_activity = 0s; + std::chrono::milliseconds _last_activity{0s}; bool terminal_hop{false}; RouterID& upstream() { return _upstream; } diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index b4696c71d7..951cff1a18 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -218,7 +218,7 @@ namespace llarp } else { - _session_endpoint->start_tickers(); + // _session_endpoint->start_tickers(); // Resolve needed ONS values now that we have the necessary things prefigured _session_endpoint->resolve_ons_mappings(); } From f8d625b515aba03e27cd4d460aac8a1ec5a89fc6 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Mon, 28 Oct 2024 07:46:52 -0700 Subject: [PATCH 13/44] path control serialization, smaller overall payload --- llarp/contact/client_contact.cpp | 11 +- llarp/handlers/session.cpp | 4 +- llarp/link/link_manager.cpp | 204 +++++++++++++++++-------------- llarp/link/link_manager.hpp | 2 +- llarp/messages/path.hpp | 48 +++++--- llarp/path/path.cpp | 61 ++++----- llarp/path/path.hpp | 2 +- llarp/router/router.cpp | 2 +- llarp/session/session.cpp | 2 + 9 files changed, 188 insertions(+), 148 deletions(-) diff --git a/llarp/contact/client_contact.cpp b/llarp/contact/client_contact.cpp index 116d0a26f4..81a1d8ea1c 100644 --- a/llarp/contact/client_contact.cpp +++ b/llarp/contact/client_contact.cpp @@ -141,12 +141,11 @@ namespace llarp oxenc::bt_dict_producer btdp; enc.bt_encode(btdp); - auto view = btdp.view_for_signing(); - - if (not crypto::sign(enc.sig, derived_privatekey, view.data(), view.size())) - throw std::runtime_error{"Failed to sign EncryptedClientContact payload!"}; - - btdp.append("~", enc.sig.to_view()); + btdp.append_signature("~", [&](ustring_view to_sign) { + if (not crypto::sign(enc.sig, derived_privatekey, to_sign.data(), to_sign.size())) + throw std::runtime_error{"Failed to sign EncryptedClientContact payload!"}; + return enc.sig.to_view(); + }); enc._bt_payload = std::move(btdp).str(); } diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index 66380c3ecb..29c06354a4 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -334,7 +334,7 @@ namespace llarp::handlers auto enc = client_contact.encrypt_and_sign(); if (publish_client_contact(enc)) - log::debug(logcat, "Successfully republished updated EncryptedClientContact!"); + log::info(logcat, "Successfully republished updated EncryptedClientContact!"); else log::warning(logcat, "Failed to republish updated EncryptedClientContact!"); } @@ -414,7 +414,7 @@ namespace llarp::handlers { log::debug(logcat, "Publishing ClientContact to pivot {}", path->pivot_rid()); - ret += path->publish_client_contact(ecc, true); + ret &= path->publish_client_contact(ecc, true); } } diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 73d6a23572..8152bf4b8c 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -706,69 +706,6 @@ namespace llarp log::warning(logcat, "NodeDB query for {} random RCs for connection returned none", num_conns); } - void LinkManager::handle_path_data_message(bstring message) - { - ustring nonce, hop_id_str, payload; - - try - { - oxenc::bt_dict_consumer btdc{message}; - std::tie(hop_id_str, nonce, payload) = ONION::deserialize_hop(btdc); - } - catch (const std::exception& e) - { - log::warning(logcat, "Exception: {}", e.what()); - return; - } - - auto symmnonce = SymmNonce{nonce.data()}; - HopID hopid{hop_id_str.data()}; - auto hop = _router.path_context()->get_transit_hop(hopid); - - if (not hop) - return; - - symmnonce = crypto::onion(payload.data(), payload.size(), hop->shared, symmnonce, hop->nonceXOR); - - // if terminal hop, pass to the correct path expecting to receive this message - if (hop->terminal_hop) - { - NetworkAddress sender; - bstring data; - - try - { - oxenc::bt_dict_consumer btdc{payload}; - std::tie(sender, data) = PATH::DATA::deserialize(btdc); - - if (auto session = _router.session_endpoint()->get_session(sender)) - { - session->recv_path_data_message(std::move(data)); - } - else - { - log::warning(logcat, "Could not find session (remote:{}) to relay path data message!", sender); - } - } - catch (const std::exception& e) - { - log::warning(logcat, "Exception: {}", e.what()); - } - } - else - { - // if not terminal hop, relay datagram onwards - auto hop_is_rx = hop->rxid() == hopid; - - const auto& next_id = hop_is_rx ? hop->txid() : hop->rxid(); - const auto& next_router = hop_is_rx ? hop->upstream() : hop->downstream(); - - std::string new_payload = ONION::serialize_hop(next_id.to_view(), symmnonce, payload); - - send_data_message(next_router, std::move(new_payload)); - } - } - void LinkManager::gossip_rc(const RouterID& last_sender, const RemoteRC& rc) { _router.loop()->call([this, last_sender, rc]() { @@ -1153,8 +1090,13 @@ namespace llarp "publish_cc", PublishClientContact::serialize(std::move(enc), relay_order, is_relayed), [respond = std::move(respond)](oxen::quic::message m) mutable { - if (m.timed_out) - return; // drop; requester will already have timed out + if (m) + log::info(logcat, "Relayed PublishClientContact returned successful! Relaying response..."); + else if (m.timed_out) + log::info(logcat, "Relayed PublishClientContact timed out! Relaying response..."); + else + log::info(logcat, "Relayed PublishClientContact failed! Relaying response..."); + respond(m.body_str()); }); } @@ -1350,81 +1292,154 @@ namespace llarp void LinkManager::handle_path_control(oxen::quic::message m, const RouterID& /* from */) { - ustring nonce, hop_id_str, payload; + HopID hop_id; + std::string payload; + SymmNonce nonce; try { - oxenc::bt_dict_consumer btdc{m.body()}; - std::tie(hop_id_str, nonce, payload) = ONION::deserialize_hop(btdc); + std::tie(hop_id, nonce, payload) = ONION::deserialize_hop(oxenc::bt_dict_consumer{m.body()}); } catch (const std::exception& e) { log::warning(logcat, "Exception: {}", e.what()); - return; + return m.respond(messages::ERROR_RESPONSE, true); } - auto symmnonce = SymmNonce{nonce.data()}; - HopID hopid{hop_id_str.data()}; - auto hop = _router.path_context()->get_transit_hop(hopid); + auto hop = _router.path_context()->get_transit_hop(hop_id); // TODO: use "path_control" for both directions? If not, drop message on // floor if we don't have the path_id in question; if we decide to make this // bidirectional, will need to check if we have a Path with path_id. if (not hop) - return; + { + log::warning(logcat, "Received path control with unknown next hop (ID: {})", hop_id); + return m.respond(messages::ERROR_RESPONSE, true); + } - symmnonce = crypto::onion(payload.data(), payload.size(), hop->shared, symmnonce, hop->nonceXOR); + nonce = crypto::onion( + reinterpret_cast(payload.data()), payload.size(), hop->shared, nonce, hop->nonceXOR); // if terminal hop, payload should contain a request (e.g. "ons_resolve"); handle and respond. if (hop->terminal_hop) { - handle_inner_request( - std::move(m), - std::string{reinterpret_cast(payload.data()), payload.size()}, - std::move(hop)); - return; + log::debug(logcat, "We are terminal hop for path request!"); + return handle_inner_request(std::move(m), std::move(payload), std::move(hop)); } - auto hop_is_rx = hop->rxid() == hopid; + auto hop_is_rx = hop->rxid() == hop_id; const auto& next_id = hop_is_rx ? hop->txid() : hop->rxid(); const auto& next_router = hop_is_rx ? hop->upstream() : hop->downstream(); - std::string new_payload = ONION::serialize_hop(next_id.to_view(), symmnonce, payload); + std::string new_payload = ONION::serialize_hop(next_id.to_view(), nonce, std::move(payload)); send_control_message( next_router, - "path_control"s, + "path_control", std::move(new_payload), - [hop_weak = hop->weak_from_this(), hopid, prev_message = std::move(m)]( + [hop_weak = hop->weak_from_this(), hop_id, prev_message = std::move(m)]( oxen::quic::message response) mutable { auto hop = hop_weak.lock(); if (not hop) - return; + { + log::warning(logcat, "Received response to path control message with non-existant TransitHop!"); + return prev_message.respond(messages::ERROR_RESPONSE, true); + } if (response.timed_out) - log::debug(logcat, "Path control message timed out!"); + { + log::info(logcat, "Path control message returned as time out!"); + return prev_message.respond(messages::TIMEOUT_RESPONSE, true); + } - ustring hop_id, nonce, payload; + HopID hop_id; + SymmNonce nonce; + std::string payload; try { - oxenc::bt_dict_consumer btdc{response.body()}; - std::tie(hop_id, nonce, payload) = ONION::deserialize_hop(btdc); + std::tie(hop_id, nonce, payload) = ONION::deserialize_hop(oxenc::bt_dict_consumer{response.body()}); } catch (const std::exception& e) { log::warning(logcat, "Exception: {}", e.what()); - return; + return prev_message.respond(messages::ERROR_RESPONSE, true); + ; } - auto symmnonce = SymmNonce{nonce.data()}; - auto resp_payload = ONION::serialize_hop(hop_id, symmnonce, payload); + auto resp_payload = ONION::serialize_hop(hop_id.to_view(), nonce, std::move(payload)); prev_message.respond(std::move(resp_payload), false); }); } + void LinkManager::handle_path_data_message(bstring message) + { + HopID hop_id; + std::string payload; + SymmNonce nonce; + + try + { + std::tie(hop_id, nonce, payload) = ONION::deserialize_hop(oxenc::bt_dict_consumer{message}); + } + catch (const std::exception& e) + { + log::warning(logcat, "Exception: {}", e.what()); + return; + } + + auto hop = _router.path_context()->get_transit_hop(hop_id); + + if (not hop) + { + log::warning(logcat, "Received path data with unknown next hop (ID: {})", hop_id); + return; + } + + nonce = crypto::onion( + reinterpret_cast(payload.data()), payload.size(), hop->shared, nonce, hop->nonceXOR); + + // if terminal hop, pass to the correct path expecting to receive this message + if (hop->terminal_hop) + { + NetworkAddress sender; + bstring data; + + try + { + oxenc::bt_dict_consumer btdc{payload}; + std::tie(sender, data) = PATH::DATA::deserialize(btdc); + + if (auto session = _router.session_endpoint()->get_session(sender)) + { + session->recv_path_data_message(std::move(data)); + } + else + { + log::warning(logcat, "Could not find session (remote:{}) to relay path data message!", sender); + } + } + catch (const std::exception& e) + { + log::warning(logcat, "Exception: {}", e.what()); + } + } + else + { + // if not terminal hop, relay datagram onwards + auto hop_is_rx = hop->rxid() == hop_id; + + const auto& next_id = hop_is_rx ? hop->txid() : hop->rxid(); + const auto& next_router = hop_is_rx ? hop->upstream() : hop->downstream(); + + std::string new_payload = ONION::serialize_hop(next_id.to_view(), nonce, std::move(payload)); + + send_data_message(next_router, std::move(new_payload)); + } + } + void LinkManager::handle_inner_request( oxen::quic::message m, std::string payload, std::shared_ptr hop) { @@ -1432,8 +1447,7 @@ namespace llarp try { - oxenc::bt_dict_consumer btdc{payload}; - std::tie(endpoint, body) = PATH::CONTROL::deserialize(btdc); + std::tie(endpoint, body) = PATH::CONTROL::deserialize(oxenc::bt_dict_consumer{payload}); } catch (const std::exception& e) { @@ -1446,10 +1460,12 @@ namespace llarp if (itr == path_requests.end()) { - log::info(logcat, "Received path control request \"{}\", which has no handler.", endpoint); + log::warning(logcat, "Received path control request `{}`, which has no handler.", endpoint); return; } + log::debug(logcat, "Received path control request `{}`", endpoint); + auto respond = [m = std::move(m), hop_weak = hop->weak_from_this()](std::string response) mutable { auto hop = hop_weak.lock(); if (not hop) diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index f48248b2d9..2685ebe52f 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -278,7 +278,7 @@ namespace llarp void handle_convo_intro(oxen::quic::message); // These requests come over a path (as a "path_control" request), - // may or may not need to make a request to another relay, + // we may or may not need to make a request to another relay, // then respond (onioned) back along the path. std::unordered_map< std::string_view, diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index 155327763d..b9d73af87d 100644 --- a/llarp/messages/path.hpp +++ b/llarp/messages/path.hpp @@ -37,6 +37,26 @@ namespace llarp return std::move(btdp).str(); } + inline static std::tuple deserialize_hop(oxenc::bt_dict_consumer&& btdc) + { + HopID hop_id; + std::string payload; + SymmNonce nonce; + + try + { + hop_id.from_string(btdc.require("k")); + nonce.from_string(btdc.require("n")); + payload = btdc.require("x"); + } + catch (const std::exception& e) + { + throw std::runtime_error{"Exception caught deserializing onion data:{}"_format(e.what())}; + } + + return {std::move(hop_id), std::move(nonce), std::move(payload)}; + } + inline static std::tuple deserialize_hop(oxenc::bt_dict_consumer& btdc) { ustring hopid, nonce, payload; @@ -186,46 +206,46 @@ namespace llarp { /** Fields for transmitting Path Control: - 'e' : request endpoint being invoked - - 'r' : request body + - 'p' : request payload */ - inline static std::string serialize(std::string endpoint, std::string body) + inline static std::string serialize(std::string endpoint, std::string payload) { oxenc::bt_dict_producer btdp; btdp.append("e", endpoint); - btdp.append("r", body); + btdp.append("p", payload); return std::move(btdp).str(); } - inline static std::tuple deserialize(oxenc::bt_dict_consumer& btdc) + inline static std::tuple deserialize(oxenc::bt_dict_consumer&& btdc) { - std::string endpoint, body; + std::string endpoint, payload; try { endpoint = btdc.require("e"); - body = btdc.require("r"); + payload = btdc.require("p"); } catch (const std::exception& e) { throw std::runtime_error{"Exception caught deserializing path control:{}"_format(e.what())}; } - return {std::move(endpoint), std::move(body)}; + return {std::move(endpoint), std::move(payload)}; } } // namespace CONTROL namespace DATA { /** Fields for transmitting Path Data: - - 'b' : request/command body - - 's' : RouterID of sender + - 'i' : RouterID of sender + - 'p' : request/command payload NOTE: more fields may be added later as needed, hence the namespacing */ - inline static std::string serialize(std::string body, const RouterID& local) + inline static std::string serialize(std::string payload, const RouterID& local) { oxenc::bt_dict_producer btdp; - btdp.append("b", body); - btdp.append("s", local.to_view()); + btdp.append("i", local.to_view()); + btdp.append("p", payload); return std::move(btdp).str(); } @@ -236,8 +256,8 @@ namespace llarp try { - body = btdc.require("b"); - remote.from_string(btdc.require("s")); + remote.from_string(btdc.require("i")); + body = btdc.require("p"); auto sender = NetworkAddress::from_pubkey(remote, true); return {std::move(sender), std::move(body)}; diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index cfc17f3f83..bc02746b32 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -144,25 +144,21 @@ namespace llarp::path // _role &= ePathRoleExit; } - std::string Path::make_path_message(std::string&& inner_payload) + std::string Path::make_path_message(std::string inner_payload) { - int n_hops = static_cast(hops.size()); - std::string payload{std::move(inner_payload)}; + auto nonce = SymmNonce::make_random(); - // Working from final hop to hop 1, we onion encrypt the message payload with each - // hop's shared secret (this was derived via DH KEM in path building). The encrypted - // payload will then be bt-serialized, and then encrypted/serialized for the next hop. - for (int i = n_hops - 1; i >= 0; --i) + for (const auto& hop : hops) { - auto& hop = hops[i]; - - crypto::onion( - reinterpret_cast(payload.data()), payload.size(), hop.shared, hop.nonce, hop.nonceXOR); - - payload = ONION::serialize_hop(hop.upstream.to_view(), hop.nonce, payload); + nonce = crypto::onion( + reinterpret_cast(inner_payload.data()), + inner_payload.size(), + hop.shared, + hop.nonce, + hop.nonce); } - return payload; + return ONION::serialize_hop(upstream_txid().to_view(), nonce, std::move(inner_payload)); } bool Path::send_path_data_message(std::string data) @@ -184,32 +180,41 @@ namespace llarp::path std::move(outer_payload), [response_cb = std::move(func), weak = weak_from_this()](oxen::quic::message m) mutable { auto self = weak.lock(); - // TODO: do we want to allow empty callback here? - if ((not self) or (not response_cb)) + if (not self) + { + log::warning(logcat, "Received response to path control message with non-existant path!"); return; + } - if (m.timed_out) + // TODO: DISCUSS: do we want to allow empty callback here? + if (not response_cb) { - response_cb(messages::TIMEOUT_RESPONSE); + log::warning(logcat, "Received response to path control message with no response callback!"); return; } - ustring hop_id_str, symmnonce, payload; + log::debug(logcat, "Received response to path control message..."); + + if (m.timed_out) + { + log::info(logcat, "Path control message returned as time out!"); + return response_cb(messages::TIMEOUT_RESPONSE); + } + + HopID hop_id; + SymmNonce nonce; + std::string payload; try { - oxenc::bt_dict_consumer btdc{m.body()}; - std::tie(hop_id_str, symmnonce, payload) = ONION::deserialize_hop(btdc); + std::tie(hop_id, nonce, payload) = ONION::deserialize_hop(oxenc::bt_dict_consumer{m.body()}); } catch (const std::exception& e) { log::warning(logcat, "Error parsing path control message response: {}", e.what()); - response_cb(messages::ERROR_RESPONSE); - return; + return response_cb(messages::ERROR_RESPONSE); } - SymmNonce nonce{symmnonce.data()}; - for (const auto& hop : self->hops) { nonce = crypto::onion( @@ -220,10 +225,8 @@ namespace llarp::path hop.nonceXOR); } - // TODO: should we do anything (even really simple) here to check if the decrypted - // response is sensible (e.g. is a bt dict)? Parsing and handling of the - // contents (errors or otherwise) is the currently responsibility of the - // callback. + // TODO: DISCUSS: + // Parsing and handling of the contents (errors, etc.) is the currently responsibility of the callback response_cb(std::string{reinterpret_cast(payload.data()), payload.size()}); }); } diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 70c5978652..1222534cf6 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -161,7 +161,7 @@ namespace llarp static constexpr bool to_string_formattable = true; private: - std::string make_path_message(std::string&& payload); + std::string make_path_message(std::string payload); bool SendLatencyMessage(Router* r); diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 951cff1a18..b4696c71d7 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -218,7 +218,7 @@ namespace llarp } else { - // _session_endpoint->start_tickers(); + _session_endpoint->start_tickers(); // Resolve needed ONS values now that we have the necessary things prefigured _session_endpoint->resolve_ons_mappings(); } diff --git a/llarp/session/session.cpp b/llarp/session/session.cpp index 5fb380ce99..87c76b1913 100644 --- a/llarp/session/session.cpp +++ b/llarp/session/session.cpp @@ -185,6 +185,7 @@ namespace llarp::session void OutboundSession::path_died(std::shared_ptr p) { + log::debug(logcat, "{} called", __PRETTY_FUNCTION__); p->rebuild(); } @@ -210,6 +211,7 @@ namespace llarp::session void OutboundSession::path_build_succeeded(std::shared_ptr p) { + log::debug(logcat, "{} called", __PRETTY_FUNCTION__); path::PathHandler::path_build_succeeded(p); // TODO: why the fuck did we used to do this here...? From bf02987ea977f6c3ef39fd8caf70809a1a94e03f Mon Sep 17 00:00:00 2001 From: dr7ana Date: Mon, 28 Oct 2024 13:39:03 -0700 Subject: [PATCH 14/44] path control handling --- llarp/bootstrap.cpp | 2 +- llarp/contact/client_contact.hpp | 2 +- llarp/handlers/session.cpp | 24 +++++- llarp/handlers/tun.cpp | 2 +- llarp/link/link_manager.cpp | 72 ++++++++++------ llarp/messages/path.hpp | 23 +---- llarp/path/path.cpp | 140 +++++++++++++++++-------------- llarp/path/path.hpp | 10 ++- llarp/path/path_context.cpp | 3 + llarp/path/path_handler.cpp | 22 ++--- llarp/path/path_handler.hpp | 3 - llarp/path/path_types.hpp | 7 ++ llarp/path/transit_hop.cpp | 16 +++- llarp/path/transit_hop.hpp | 9 +- 14 files changed, 196 insertions(+), 139 deletions(-) diff --git a/llarp/bootstrap.cpp b/llarp/bootstrap.cpp index 51d88a810b..f2ebfde023 100644 --- a/llarp/bootstrap.cpp +++ b/llarp/bootstrap.cpp @@ -156,7 +156,7 @@ namespace llarp if (not fs::exists(fpath)) { - log::critical(logcat, "Bootstrap RC file non-existant at path:{}", fpath); + log::critical(logcat, "Bootstrap RC file non-existent at path:{}", fpath); return result; } diff --git a/llarp/contact/client_contact.hpp b/llarp/contact/client_contact.hpp index 98e90515c8..0d2175d604 100644 --- a/llarp/contact/client_contact.hpp +++ b/llarp/contact/client_contact.hpp @@ -47,7 +47,7 @@ namespace llarp }; // TESTNET: - inline static constexpr auto CC_PUBLISH_INTERVAL{1min}; + inline static constexpr auto CC_PUBLISH_INTERVAL{30s}; /** ClientContact On the wire we encode the data as a dict containing: diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index 29c06354a4..c31adc53db 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -236,9 +236,9 @@ namespace llarp::handlers if (auto s = btdc.maybe(messages::STATUS_KEY)) status = s; } - catch (...) + catch (const std::exception& e) { - log::warning(logcat, "Exception caught parsing 'find_name' response!"); + log::warning(logcat, "Exception caught parsing 'find_name' response: {}", e.what()); } log::warning(logcat, "Call to endpoint 'lookup_name' failed -- status:{}", status.value_or("")); @@ -414,7 +414,25 @@ namespace llarp::handlers { log::debug(logcat, "Publishing ClientContact to pivot {}", path->pivot_rid()); - ret &= path->publish_client_contact(ecc, true); + ret &= path->publish_client_contact(ecc, true, 0, [](std::string response) { + log::info(logcat, "Received response to PublishClientContact..."); + + std::optional status = std::nullopt; + try + { + oxenc::bt_dict_consumer btdc{response}; + + if (auto s = btdc.maybe(messages::STATUS_KEY)) + status = s; + } + catch (const std::exception& e) + { + log::warning(logcat, "Exception: {}", e.what()); + } + + log::warning( + logcat, "Call to PublishClientContact failed -- status:{}", status.value_or("")); + }); } } diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 895927baa9..e7a278f4dc 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -382,7 +382,7 @@ namespace llarp::handlers auto pkt_hook = [this]() { for (auto pkt = _net_if->read_next_packet(); not pkt.empty(); pkt = _net_if->read_next_packet()) { - log::debug(logcat, "packet router receiving {}", pkt.info_line()); + log::trace(logcat, "packet router receiving {}", pkt.info_line()); _packet_router->handle_ip_packet(std::move(pkt)); } }; diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 8152bf4b8c..70b62d3ca5 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1292,6 +1292,8 @@ namespace llarp void LinkManager::handle_path_control(oxen::quic::message m, const RouterID& /* from */) { + log::debug(logcat, "{} called", __PRETTY_FUNCTION__); + HopID hop_id; std::string payload; SymmNonce nonce; @@ -1313,12 +1315,20 @@ namespace llarp // bidirectional, will need to check if we have a Path with path_id. if (not hop) { + // if (auto path = _router.path_context()->get_path(hop_id)) + // { + // log::info(logcat, "Received path control corresponding to known path!"); + // // + // } + log::warning(logcat, "Received path control with unknown next hop (ID: {})", hop_id); return m.respond(messages::ERROR_RESPONSE, true); } - nonce = crypto::onion( - reinterpret_cast(payload.data()), payload.size(), hop->shared, nonce, hop->nonceXOR); + auto onion_nonce = nonce ^ hop->nonceXOR; + + crypto::onion( + reinterpret_cast(payload.data()), payload.size(), hop->shared, onion_nonce, hop->nonceXOR); // if terminal hop, payload should contain a request (e.g. "ons_resolve"); handle and respond. if (hop->terminal_hop) @@ -1332,7 +1342,7 @@ namespace llarp const auto& next_id = hop_is_rx ? hop->txid() : hop->rxid(); const auto& next_router = hop_is_rx ? hop->upstream() : hop->downstream(); - std::string new_payload = ONION::serialize_hop(next_id.to_view(), nonce, std::move(payload)); + std::string new_payload = ONION::serialize_hop(next_id.to_view(), onion_nonce, std::move(payload)); send_control_message( next_router, @@ -1344,33 +1354,44 @@ namespace llarp if (not hop) { - log::warning(logcat, "Received response to path control message with non-existant TransitHop!"); + log::warning(logcat, "Received response to path control message with non-existent TransitHop!"); return prev_message.respond(messages::ERROR_RESPONSE, true); } - if (response.timed_out) + if (response) { - log::info(logcat, "Path control message returned as time out!"); - return prev_message.respond(messages::TIMEOUT_RESPONSE, true); + log::info(logcat, "Path control message returned successfully!"); + prev_message.respond(messages::OK_RESPONSE, false); } - - HopID hop_id; - SymmNonce nonce; - std::string payload; - - try + else if (response.timed_out) { - std::tie(hop_id, nonce, payload) = ONION::deserialize_hop(oxenc::bt_dict_consumer{response.body()}); + log::warning(logcat, "Path control message returned as time out!"); + prev_message.respond(messages::TIMEOUT_RESPONSE, true); } - catch (const std::exception& e) + else { - log::warning(logcat, "Exception: {}", e.what()); - return prev_message.respond(messages::ERROR_RESPONSE, true); - ; + log::warning(logcat, "Path control message returned as error!"); + prev_message.respond(messages::ERROR_RESPONSE, true); } - auto resp_payload = ONION::serialize_hop(hop_id.to_view(), nonce, std::move(payload)); - prev_message.respond(std::move(resp_payload), false); + // TODO: onion encrypt path message responses + // HopID hop_id; + // SymmNonce nonce; + // std::string payload; + + // try + // { + // std::tie(hop_id, nonce, payload) = + // ONION::deserialize_hop(oxenc::bt_dict_consumer{response.body()}); + // } + // catch (const std::exception& e) + // { + // log::warning(logcat, "Exception: {}; payload: {}", e.what(), buffer_printer{response.body()}); + // return prev_message.respond(messages::ERROR_RESPONSE, true); + // } + + // auto resp_payload = ONION::serialize_hop(hop_id.to_view(), nonce, std::move(payload)); + // prev_message.respond(std::move(resp_payload), false); }); } @@ -1451,8 +1472,8 @@ namespace llarp } catch (const std::exception& e) { - log::warning(logcat, "Exception: {}", e.what()); - return; + log::warning(logcat, "Exception: {}; Payload: {}", e.what(), buffer_printer{payload}); + return m.respond(messages::serialize_response({{messages::STATUS_KEY, e.what()}}), true); } // If a handler exists for "method", call it; else drop request on the floor. @@ -1471,8 +1492,11 @@ namespace llarp if (not hop) return; // transit hop gone, drop response - auto n = SymmNonce::make_random(); - m.respond(ONION::serialize_hop(hop->rxid().to_view(), n, response), false); + m.respond(std::move(response)); + + // TODO: onion encrypt path message responses + // auto n = SymmNonce::make_random(); + // m.respond(ONION::serialize_hop(hop->rxid().to_view(), n, response), false); }; std::invoke(itr->second, this, std::move(body), std::move(respond)); diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index b9d73af87d..e1ad9ef63f 100644 --- a/llarp/messages/path.hpp +++ b/llarp/messages/path.hpp @@ -51,29 +51,12 @@ namespace llarp } catch (const std::exception& e) { - throw std::runtime_error{"Exception caught deserializing onion data:{}"_format(e.what())}; + throw std::runtime_error{"Exception caught deserializing onion data: {}"_format(e.what())}; } return {std::move(hop_id), std::move(nonce), std::move(payload)}; } - inline static std::tuple deserialize_hop(oxenc::bt_dict_consumer& btdc) - { - ustring hopid, nonce, payload; - - try - { - hopid = btdc.require("k"); - nonce = btdc.require("n"); - payload = btdc.require("x"); - } - catch (const std::exception& e) - { - throw std::runtime_error{"Exception caught deserializing onion data:{}"_format(e.what())}; - } - - return {std::move(hopid), std::move(nonce), std::move(payload)}; - } } // namespace ONION namespace PATH @@ -170,7 +153,7 @@ namespace llarp } catch (const std::exception& e) { - log::warning(logcat, "Exception caught deserializing hop dict:{}", e.what()); + log::warning(logcat, "Exception caught deserializing hop dict: {}", e.what()); throw; } @@ -227,7 +210,7 @@ namespace llarp } catch (const std::exception& e) { - throw std::runtime_error{"Exception caught deserializing path control:{}"_format(e.what())}; + throw std::runtime_error{"Exception caught deserializing path control: {}"_format(e.what())}; } return {std::move(endpoint), std::move(payload)}; diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index bc02746b32..0cfc25ca95 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -7,6 +7,8 @@ #include #include +#include + namespace llarp::path { static auto logcat = log::Cat("path"); @@ -19,31 +21,34 @@ namespace llarp::path bool is_client) : handler{std::move(_handler)}, _router{rtr}, _is_session_path{is_session}, _is_client{is_client} { - hops.resize(_hops.size()); - size_t hsz = _hops.size(); + size_t n_hops = _hops.size(); + // transit_hops.resize(n_hops); + hops.resize(n_hops); - for (size_t idx = 0; idx < hsz; ++idx) + for (size_t idx = 0; idx < n_hops; ++idx) { + // transit_hops[idx] hops[idx].rc = _hops[idx]; - do - { - hops[idx].txID.Randomize(); - } while (hops[idx].txID.is_zero()); - - do - { - hops[idx].rxID.Randomize(); - } while (hops[idx].rxID.is_zero()); + hops[idx].txID = HopID::make_random(); + // transit_hops[idx]._txid = HopID::make_random(); + hops[idx].rxID = HopID::make_random(); + // transit_hops[idx]._rxid = HopID::make_random(); } - for (size_t idx = 0; idx < hsz - 1; ++idx) + for (size_t idx = 0; idx < n_hops - 1; ++idx) { + // transit_hops[idx]._txid = transit_hops[idx + 1]._rxid; hops[idx].txID = hops[idx + 1].rxID; } // initialize parts of the clientintro - intro.pivot_rid = hops[hsz - 1].rc.router_id(); - intro.pivot_hid = hops[hsz - 1].txID; + // intro.pivot_rid = transit_hops.back().rc.router_id(); + // intro.pivot_hid = transit_hops.back()._txid; + intro.pivot_rid = hops.back().rc.router_id(); + intro.pivot_hid = hops.back().txID; + + log::info( + logcat, "Path client intro holding pivot_rid ({}) and pivot_hid ({})", intro.pivot_rid, intro.pivot_hid); } void Path::link_session(recv_session_dgram_cb cb) @@ -75,8 +80,8 @@ namespace llarp::path bool Path::operator<(const Path& other) const { - auto& first_hop = hops[0]; - auto& other_first = other.hops[0]; + auto& first_hop = hops.front(); + auto& other_first = other.hops.front(); return std::tie(first_hop.txID, first_hop.rxID, first_hop.upstream) < std::tie(other_first.txID, other_first.rxID, other_first.upstream); } @@ -148,14 +153,14 @@ namespace llarp::path { auto nonce = SymmNonce::make_random(); - for (const auto& hop : hops) + for (const auto& hop : std::ranges::reverse_view(hops)) { nonce = crypto::onion( reinterpret_cast(inner_payload.data()), inner_payload.size(), hop.shared, - hop.nonce, - hop.nonce); + nonce, + hop.nonceXOR); } return ONION::serialize_hop(upstream_txid().to_view(), nonce, std::move(inner_payload)); @@ -182,7 +187,7 @@ namespace llarp::path auto self = weak.lock(); if (not self) { - log::warning(logcat, "Received response to path control message with non-existant path!"); + log::warning(logcat, "Received response to path control message with non-existent path!"); return; } @@ -193,77 +198,86 @@ namespace llarp::path return; } - log::debug(logcat, "Received response to path control message..."); - - if (m.timed_out) - { - log::info(logcat, "Path control message returned as time out!"); - return response_cb(messages::TIMEOUT_RESPONSE); - } - - HopID hop_id; - SymmNonce nonce; - std::string payload; - - try - { - std::tie(hop_id, nonce, payload) = ONION::deserialize_hop(oxenc::bt_dict_consumer{m.body()}); - } - catch (const std::exception& e) - { - log::warning(logcat, "Error parsing path control message response: {}", e.what()); - return response_cb(messages::ERROR_RESPONSE); - } - - for (const auto& hop : self->hops) - { - nonce = crypto::onion( - reinterpret_cast(payload.data()), - payload.size(), - hop.shared, - nonce, - hop.nonceXOR); - } - - // TODO: DISCUSS: - // Parsing and handling of the contents (errors, etc.) is the currently responsibility of the callback - response_cb(std::string{reinterpret_cast(payload.data()), payload.size()}); + log::debug(logcat, "Received response to path control message: {}", buffer_printer{m.body()}); + + if (m) + log::info(logcat, "Path control message returned successfully!"); + else if (m.timed_out) + log::warning(logcat, "Path control message returned as time out!"); + else + log::warning(logcat, "Path control message returned as error!"); + + return response_cb(m.body_str()); + + // TODO: onion encrypt path message responses + // HopID hop_id; + // SymmNonce nonce; + // std::string payload; + + // try + // { + // std::tie(hop_id, nonce, payload) = ONION::deserialize_hop(oxenc::bt_dict_consumer{m.body()}); + // } + // catch (const std::exception& e) + // { + // log::warning(logcat, "Exception parsing path control message response: {}", e.what()); + // return response_cb(messages::ERROR_RESPONSE); + // } + + // for (const auto& hop : self->hops) + // { + // nonce = crypto::onion( + // reinterpret_cast(payload.data()), + // payload.size(), + // hop.shared, + // nonce, + // hop.nonceXOR); + // } + + // // TODO: DISCUSS: + // // Parsing and handling of the contents (errors, etc.) is the currently responsibility of the + // callback response_cb(std::move(payload)); }); } bool Path::is_ready(std::chrono::milliseconds now) const { - return _established ? is_expired(now) : false; + return _established ? !is_expired(now) : false; + } + + PathHopConfig Path::upstream() + { + return hops.front(); } RouterID Path::upstream_rid() { - return hops[0].rc.router_id(); + return hops.front().rc.router_id(); } const RouterID& Path::upstream_rid() const { - return hops[0].rc.router_id(); + return hops.front().rc.router_id(); } HopID Path::upstream_txid() { - return hops[0].txID; + return hops.front().txID; } const HopID& Path::upstream_txid() const { - return hops[0].txID; + return hops.front().txID; } HopID Path::upstream_rxid() { - return hops[0].rxID; + return hops.front().rxID; } const HopID& Path::upstream_rxid() const { - return hops[0].rxID; + return hops.front().rxID; } RouterID Path::pivot_rid() diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 1222534cf6..51a85aa9f5 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -42,6 +42,8 @@ namespace llarp { std::vector hops; + // std::vector transit_hops; + std::weak_ptr handler; ClientIntro intro{}; @@ -128,6 +130,8 @@ namespace llarp bool is_ready(std::chrono::milliseconds now = llarp::time_now_ms()) const; + PathHopConfig upstream(); + RouterID upstream_rid(); const RouterID& upstream_rid() const; @@ -178,9 +182,9 @@ namespace llarp recv_session_dgram_cb _recv_dgram; - std::chrono::milliseconds last_recv_msg = 0s; - std::chrono::milliseconds last_latency_test = 0s; - uint64_t last_latency_test_id = 0; + std::chrono::milliseconds last_recv_msg{0s}; + std::chrono::milliseconds last_latency_test{0s}; + uint64_t last_latency_test_id{}; }; } // namespace path } // namespace llarp diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index 86cf03108f..5e027ff940 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -39,6 +39,9 @@ namespace llarp::path { Lock_t l{paths_mutex}; + // TESTNET: TODO: once PathHopConfig -> TransitHop, remove this association + put_transit_hop(TransitHop::from_hop_config(path->upstream())); + _path_map.emplace(path->upstream_rxid(), path); _path_map.emplace(path->upstream_txid(), path); diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index 10166002f4..84f2f37e10 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -166,19 +166,6 @@ namespace llarp::path return selected; } - size_t PathHandler::paths_at_time(std::chrono::milliseconds futureTime) const - { - size_t num = 0; - Lock_t l{paths_mutex}; - - for (const auto& item : _paths) - { - if (item.second->is_ready() && !item.second->is_expired(futureTime)) - ++num; - } - return num; - } - void PathHandler::reset_path_state() { build_interval_limit = PATH_BUILD_RATE; @@ -424,7 +411,6 @@ namespace llarp::path } RemoteRC remote_rc; - to_exclude.insert(remote_rc.router_id()); // we will manually add this last if (const auto maybe = _router.node_db()->get_rc(pivot)) { @@ -433,6 +419,8 @@ namespace llarp::path else return std::nullopt; + to_exclude.insert(remote_rc.router_id()); // we will manually add this last + // leave one extra spot for the terminal node auto hops_needed = num_hops - hops.size() - 1; @@ -508,7 +496,7 @@ namespace llarp::path last_build = llarp::time_now_ms(); const auto& edge = hops[0].router_id(); - const auto& terminus = hops.back().router_id(); + const auto& pivot = hops.back().router_id(); if (not _router.pathbuild_limiter().Attempt(edge)) { @@ -519,9 +507,9 @@ namespace llarp::path { Lock_t l{paths_mutex}; - if (auto [it, b] = _paths.try_emplace(terminus, nullptr); not b) + if (auto [it, b] = _paths.try_emplace(pivot, nullptr); not b) { - log::warning(logcat, "Pending build to {} already underway... aborting...", terminus); + log::warning(logcat, "Pending build to {} already underway... aborting...", pivot); return false; } } diff --git a/llarp/path/path_handler.hpp b/llarp/path/path_handler.hpp index aca8398578..52ca9fd25a 100644 --- a/llarp/path/path_handler.hpp +++ b/llarp/path/path_handler.hpp @@ -184,9 +184,6 @@ namespace llarp std::optional>> get_n_random_paths_conditional( size_t n, std::function)> filter, bool exact = false); - /// count the number of paths that will exist at this timestamp in future - size_t paths_at_time(std::chrono::milliseconds futureTime) const; - virtual void reset_path_state(); /// return true if we hit our soft limit for building paths too fast diff --git a/llarp/path/path_types.hpp b/llarp/path/path_types.hpp index 3f17d63b41..5a267a7481 100644 --- a/llarp/path/path_types.hpp +++ b/llarp/path/path_types.hpp @@ -11,6 +11,13 @@ namespace llarp struct HopID final : public AlignedBuffer { using AlignedBuffer::AlignedBuffer; + + static HopID make_random() + { + HopID h; + h.Randomize(); + return h; + } }; namespace path diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index 407808bd71..39d5d10420 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -9,6 +9,20 @@ namespace llarp::path { static auto logcat = log::Cat("transit-hop"); + std::shared_ptr TransitHop::from_hop_config(PathHopConfig hop_config) + { + auto hop = std::make_shared(); + + hop->_txid = {hop_config.txID}; + hop->_rxid = {hop_config.rxID}; + hop->_upstream = {hop_config.upstream}; + hop->shared = {hop_config.shared}; + hop->nonce = {hop_config.nonce}; + hop->nonceXOR = {hop_config.nonceXOR}; + + return hop; + } + std::shared_ptr TransitHop::deserialize_hop( oxenc::bt_dict_consumer&& btdc, const RouterID& src, Router& r, SharedSecret secret) { @@ -33,7 +47,7 @@ namespace llarp::path if (hop->lifetime > path::DEFAULT_LIFETIME) throw std::runtime_error{PATH::BUILD::BAD_LIFETIME}; - hop->downstream() = src; + hop->_downstream = src; hop->shared = std::move(secret); if (r.path_context()->has_transit_hop(hop)) diff --git a/llarp/path/transit_hop.hpp b/llarp/path/transit_hop.hpp index d651c0903d..eef2945878 100644 --- a/llarp/path/transit_hop.hpp +++ b/llarp/path/transit_hop.hpp @@ -10,18 +10,22 @@ namespace llarp { struct Router; + /** TODO: combine PathHopConfig into TransitHop + - Add RelayContact + */ + namespace path { struct TransitHop : std::enable_shared_from_this { - private: HopID _txid, _rxid; RouterID _upstream; RouterID _downstream; - public: TransitHop() = default; + static std::shared_ptr from_hop_config(PathHopConfig hop_config); + TransitHop(Router& r, const RouterID& src, ustring symmkey, ustring symmnonce); // This static factory function is used in path-build logic. The exceptions thrown are the exact response @@ -30,6 +34,7 @@ namespace llarp oxenc::bt_dict_consumer&& btdc, const RouterID& src, Router& r, SharedSecret secret); SharedSecret shared; + SymmNonce nonce; SymmNonce nonceXOR; std::chrono::milliseconds started{0s}; // 10 minutes default From 1c630f91b71a196ee8c330bd35d4d36779e07e75 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Tue, 29 Oct 2024 14:12:00 -0700 Subject: [PATCH 15/44] path message addressing to the right rxid --- llarp/contact/client_intro.hpp | 2 +- llarp/handlers/session.cpp | 10 +++++++--- llarp/link/link_manager.cpp | 22 +++++++++------------- llarp/messages/dht.hpp | 5 +++-- llarp/messages/path.hpp | 6 ++++-- llarp/path/path.cpp | 3 ++- llarp/path/path.hpp | 3 +-- 7 files changed, 27 insertions(+), 24 deletions(-) diff --git a/llarp/contact/client_intro.hpp b/llarp/contact/client_intro.hpp index 9322352e20..c0af73d4c8 100644 --- a/llarp/contact/client_intro.hpp +++ b/llarp/contact/client_intro.hpp @@ -13,7 +13,7 @@ namespace llarp struct ClientIntro { RouterID pivot_rid; - HopID pivot_hid; + HopID pivot_hid; // TXID at the pivot std::chrono::milliseconds expiry{0s}; uint64_t version{llarp::constants::proto_version}; diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index c31adc53db..ed7dfb139b 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -405,7 +405,7 @@ namespace llarp::handlers { bool ret{true}; - log::critical(logcat, "Publishing new EncryptedClientContact: {}", ecc.bt_payload()); + log::critical(logcat, "Publishing new EncryptedClientContact: {}", buffer_printer{ecc.bt_payload()}); { Lock_t l{paths_mutex}; @@ -430,8 +430,12 @@ namespace llarp::handlers log::warning(logcat, "Exception: {}", e.what()); } - log::warning( - logcat, "Call to PublishClientContact failed -- status:{}", status.value_or("")); + auto b = status.value_or("") == "SUCCESS"; + + log::critical( + logcat, + "Call to PublishClientContact {}", + b ? "SUCCEEDED" : "FAILED -- reason: {}"_format(status.value_or(""))); }); } } diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 70b62d3ca5..d47987695d 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1080,7 +1080,9 @@ namespace llarp "Received PublishClientContact for which we are index {}... storing client contact...", relay_order); _router.contact_db().put_cc(std::move(enc)); - return respond(messages::OK_RESPONSE); + // return respond(messages::OK_RESPONSE); + // TESTNET: + return respond(PublishClientContact::SUCCESS); } log::info(logcat, "Received PublishClientContact; propagating to peer index {}...", relay_order); @@ -1112,7 +1114,9 @@ namespace llarp dht_key, relay_order); _router.contact_db().put_cc(std::move(enc)); - return respond(messages::OK_RESPONSE); + // return respond(messages::OK_RESPONSE); + // TESTNET: + return respond(PublishClientContact::SUCCESS); } } @@ -1191,8 +1195,7 @@ namespace llarp if (!_router.path_context()->is_transit_allowed()) { log::warning(logcat, "got path build request when not permitting transit"); - m.respond(PATH::BUILD::NO_TRANSIT, true); - return; + return m.respond(PATH::BUILD::NO_TRANSIT, true); } try @@ -1359,20 +1362,13 @@ namespace llarp } if (response) - { log::info(logcat, "Path control message returned successfully!"); - prev_message.respond(messages::OK_RESPONSE, false); - } else if (response.timed_out) - { log::warning(logcat, "Path control message returned as time out!"); - prev_message.respond(messages::TIMEOUT_RESPONSE, true); - } else - { log::warning(logcat, "Path control message returned as error!"); - prev_message.respond(messages::ERROR_RESPONSE, true); - } + + prev_message.respond(response.body_str(), response.is_error()); // TODO: onion encrypt path message responses // HopID hop_id; diff --git a/llarp/messages/dht.hpp b/llarp/messages/dht.hpp index 6c6e943d15..7661d79b42 100644 --- a/llarp/messages/dht.hpp +++ b/llarp/messages/dht.hpp @@ -80,7 +80,7 @@ namespace llarp try { - btdp.append("c", location.to_view()); + btdp.append("k", location.to_view()); btdp.append("o", relay_order); btdp.append("r", is_relayed); } @@ -106,7 +106,7 @@ namespace llarp try { oxenc::bt_dict_consumer btdc{buf}; - key.from_string(btdc.require("c")); + key.from_string(btdc.require("k")); is_relayed = btdc.require("o"); relay_order = btdc.require("r"); } @@ -123,6 +123,7 @@ namespace llarp namespace PublishClientContact { + inline const auto SUCCESS = messages::serialize_response({{messages::STATUS_KEY, "SUCCESS"}}); inline const auto INVALID = messages::serialize_response({{messages::STATUS_KEY, "INVALID CC"}}); inline const auto EXPIRED = messages::serialize_response({{messages::STATUS_KEY, "EXPIRED CC"}}); inline const auto INSUFFICIENT = messages::serialize_response({{messages::STATUS_KEY, "INSUFFICIENT NODES"}}); diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index e1ad9ef63f..cb0e3c7f52 100644 --- a/llarp/messages/path.hpp +++ b/llarp/messages/path.hpp @@ -26,8 +26,10 @@ namespace llarp - 'n' : Symmetric nonce used to encrypt the layer - 'x' : Encrypted payload transmitted to next recipient */ - template - inline static std::string serialize_hop(K key, const SymmNonce& nonce, T encrypted) + // template + // inline static std::string serialize_hop(K key, const SymmNonce& nonce, T encrypted) + inline static std::string serialize_hop( + std::string_view key, const SymmNonce& nonce, std::string_view encrypted) { oxenc::bt_dict_producer btdp; btdp.append("k", key); diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 0cfc25ca95..dd9c1e9cf3 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -163,7 +163,8 @@ namespace llarp::path hop.nonceXOR); } - return ONION::serialize_hop(upstream_txid().to_view(), nonce, std::move(inner_payload)); + // TESTNET: upstream_txid -> upstream_rxid + return ONION::serialize_hop(upstream_rxid().to_view(), nonce, std::move(inner_payload)); } bool Path::send_path_data_message(std::string data) diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 51a85aa9f5..8089296ab8 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -63,8 +63,6 @@ namespace llarp nlohmann::json ExtractStatus() const; - std::string to_string() const; - std::string HopsString() const; std::chrono::milliseconds LastRemoteActivityAt() const { return last_recv_msg; } @@ -162,6 +160,7 @@ namespace llarp bool operator!=(const Path& other) const; + std::string to_string() const; static constexpr bool to_string_formattable = true; private: From 85642faa4aba3d458c283e7fda3a9aa2b40362df Mon Sep 17 00:00:00 2001 From: dr7ana Date: Wed, 30 Oct 2024 07:54:08 -0700 Subject: [PATCH 16/44] HopID changes, control message serialization, etc - path mapping fundamentally changed in path_handler and path_context to be correctly 1:1 with upstream RX - concepts of "is_relayed" and "relay_order" made redundant by relay full mesh --- llarp/contact/client_contact.cpp | 8 +++ llarp/contact/client_intro.cpp | 6 +- llarp/contact/client_intro.hpp | 12 ++-- llarp/dht/bucket.hpp | 18 ++++- llarp/dht/kademlia.hpp | 22 ------ llarp/handlers/session.cpp | 13 ++-- llarp/link/link_manager.cpp | 84 +++++++--------------- llarp/messages/dht.hpp | 39 ++--------- llarp/nodedb.cpp | 28 ++------ llarp/nodedb.hpp | 4 +- llarp/path/path.cpp | 13 ++-- llarp/path/path.hpp | 5 +- llarp/path/path_context.cpp | 30 -------- llarp/path/path_context.hpp | 5 +- llarp/path/path_handler.cpp | 117 +++++++++++++++---------------- llarp/path/path_handler.hpp | 18 ++--- llarp/path/path_types.hpp | 5 ++ llarp/path/transit_hop.cpp | 2 +- llarp/path/transit_hop.hpp | 1 - llarp/session/session.cpp | 2 +- llarp/session/session.hpp | 8 +-- 21 files changed, 158 insertions(+), 282 deletions(-) delete mode 100644 llarp/dht/kademlia.hpp diff --git a/llarp/contact/client_contact.cpp b/llarp/contact/client_contact.cpp index 81a1d8ea1c..a7eb52427e 100644 --- a/llarp/contact/client_contact.cpp +++ b/llarp/contact/client_contact.cpp @@ -65,6 +65,8 @@ namespace llarp size_t ClientContact::bt_encode(oxenc::bt_dict_producer&& btdp) const { + btdp.append("", ClientContact::CC_VERSION); + btdp.append("a", pubkey.to_view()); if (exit_policy) @@ -91,6 +93,12 @@ namespace llarp void ClientContact::bt_decode(oxenc::bt_dict_consumer&& btdc) { + auto version = btdc.require(""); + if (ClientContact::CC_VERSION != version) + throw std::runtime_error{ + "Deserialized ClientContact with incorrect version! (Received:{}, expected:{})"_format( + version, ClientContact::CC_VERSION)}; + pubkey.from_string(btdc.require("a")); if (auto maybe_subdict = btdc.maybe("e")) diff --git a/llarp/contact/client_intro.cpp b/llarp/contact/client_intro.cpp index 4b098f7d0f..e73b9f4895 100644 --- a/llarp/contact/client_intro.cpp +++ b/llarp/contact/client_intro.cpp @@ -12,7 +12,7 @@ namespace llarp void ClientIntro::bt_encode(oxenc::bt_dict_producer&& subdict) const { subdict.append("k", pivot_rid.to_view()); - subdict.append("p", pivot_hid.to_view()); + subdict.append("p", pivot_rxid.to_view()); subdict.append("x", expiry.count()); } @@ -34,12 +34,12 @@ namespace llarp void ClientIntro::bt_decode(oxenc::bt_dict_consumer&& btdc) { pivot_rid.from_string(btdc.require("k")); - pivot_hid.from_string(btdc.require("p")); + pivot_rxid.from_string(btdc.require("p")); expiry = std::chrono::milliseconds{btdc.require("x")}; } std::string ClientIntro::to_string() const { - return "[ ClientIntro pivot_rid={}, pivot_hid={}, expiry={} ]"_format(pivot_rid, pivot_hid, expiry.count()); + return "[ ClientIntro pivot_rid={}, pivot_hid={}, expiry={} ]"_format(pivot_rid, pivot_rxid, expiry.count()); } } // namespace llarp diff --git a/llarp/contact/client_intro.hpp b/llarp/contact/client_intro.hpp index c0af73d4c8..5ab92edebf 100644 --- a/llarp/contact/client_intro.hpp +++ b/llarp/contact/client_intro.hpp @@ -13,7 +13,7 @@ namespace llarp struct ClientIntro { RouterID pivot_rid; - HopID pivot_hid; // TXID at the pivot + HopID pivot_rxid; // RXID at the pivot std::chrono::milliseconds expiry{0s}; uint64_t version{llarp::constants::proto_version}; @@ -34,16 +34,16 @@ namespace llarp public: auto operator<=>(const ClientIntro& other) const { - return std::tie(pivot_rid, pivot_hid, expiry, version) - <=> std::tie(other.pivot_rid, other.pivot_hid, other.expiry, other.version); + return std::tie(pivot_rid, pivot_rxid, expiry, version) + <=> std::tie(other.pivot_rid, other.pivot_rxid, other.expiry, other.version); } bool operator==(const ClientIntro& other) const { return (*this <=> other) == 0; } bool operator<(const ClientIntro& other) const { - return std::tie(pivot_rid, pivot_hid, expiry, version) - < std::tie(other.pivot_rid, other.pivot_hid, other.expiry, other.version); + return std::tie(pivot_rid, pivot_rxid, expiry, version) + < std::tie(other.pivot_rid, other.pivot_rxid, other.expiry, other.version); } std::string to_string() const; @@ -67,7 +67,7 @@ namespace std { size_t operator()(const llarp::ClientIntro& i) const { - return std::hash{}(i.pivot_rid) ^ std::hash{}(i.pivot_hid); + return std::hash{}(i.pivot_rid) ^ std::hash{}(i.pivot_rxid); } }; } // namespace std diff --git a/llarp/dht/bucket.hpp b/llarp/dht/bucket.hpp index a4f53cd613..8663fb7527 100644 --- a/llarp/dht/bucket.hpp +++ b/llarp/dht/bucket.hpp @@ -1,8 +1,8 @@ #pragma once -#include "kademlia.hpp" #include "key.hpp" +#include #include #include @@ -13,6 +13,22 @@ namespace llarp::dht { static auto logcat = log::Cat("dht.bucket"); + struct XorMetric + { + const Key_t us; + + 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 RemoteRC& left, const RemoteRC& right) const + { + return (left.router_id() ^ us) < (right.router_id() ^ us); + } + }; + + using rc_set = std::set; + template struct Bucket { diff --git a/llarp/dht/kademlia.hpp b/llarp/dht/kademlia.hpp deleted file mode 100644 index c6d37abcbf..0000000000 --- a/llarp/dht/kademlia.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "key.hpp" - -#include - -namespace llarp::dht -{ - struct XorMetric - { - const Key_t us; - - 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 RelayContact& left, const RelayContact& right) const - { - return (left.router_id() ^ us) < (right.router_id() ^ us); - } - }; -} // namespace llarp::dht diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index ed7dfb139b..5dd29f098b 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -248,7 +248,7 @@ namespace llarp::handlers { Lock_t l{paths_mutex}; - for (const auto& [rid, path] : _paths) + for (const auto& [_, path] : _paths) { log::info(logcat, "Querying pivot:{} for name lookup (target: {})", path->pivot_rid(), ons); @@ -298,13 +298,14 @@ namespace llarp::handlers { Lock_t l{paths_mutex}; - for (const auto& [rid, path] : _paths) + for (const auto& [_, path] : _paths) { log::debug( logcat, "Querying pivot (rid:{}) for clientcontact lookup target (rid:{})", path->pivot_rid(), remote); + path->find_client_contact(remote_key, is_relayed, order, response_handler); } } @@ -410,11 +411,11 @@ namespace llarp::handlers { Lock_t l{paths_mutex}; - for (const auto& [rid, path] : _paths) + for (const auto& [_, path] : _paths) { log::debug(logcat, "Publishing ClientContact to pivot {}", path->pivot_rid()); - ret &= path->publish_client_contact(ecc, true, 0, [](std::string response) { + ret &= path->publish_client_contact(ecc, [](std::string response) { log::info(logcat, "Received response to PublishClientContact..."); std::optional status = std::nullopt; @@ -517,9 +518,9 @@ namespace llarp::handlers auto intro = intros.extract(intros.begin()).value(); auto& pivot = intro.pivot_rid; - if (auto path = _router.path_context()->get_path(intro.pivot_hid)) + if (auto path = _router.path_context()->get_path(intro.pivot_rxid)) { - log::info(logcat, "Found path to pivot (hopid: {}); initiating session!", intro.pivot_hid); + log::info(logcat, "Found path to pivot (hopid: {}); initiating session!", intro.pivot_rxid); return _make_session(std::move(remote), std::move(path), std::move(cb), is_exit); } diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index d47987695d..1c713b0beb 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -802,7 +802,7 @@ namespace llarp } catch (const std::exception& e) { - log::critical(logcat, "Exception handling bootstarp RC Fetch request (body:{}): {}", m.body(), e.what()); + log::critical(logcat, "Exception handling bootstrap RC Fetch request (body:{}): {}", m.body(), e.what()); m.respond(messages::ERROR_RESPONSE, true); return; } @@ -1025,12 +1025,10 @@ namespace llarp log::critical(logcat, "Received request to publish client contact!"); EncryptedClientContact enc; - bool is_relayed; - uint64_t relay_order; try { - std::tie(enc, relay_order, is_relayed) = PublishClientContact::deserialize(body); + enc = PublishClientContact::deserialize(body); } catch (const std::exception& e) { @@ -1055,73 +1053,39 @@ namespace llarp auto closest_rcs = _router.node_db()->find_many_closest_to(dht_key, path::DEFAULT_PATHS_HELD); - if (closest_rcs.size() != path::DEFAULT_PATHS_HELD) + for (const auto& rc : closest_rcs) { - log::warning(logcat, "Received PublishClientContact message but only know {} nodes?", closest_rcs.size()); - return respond(PublishClientContact::INSUFFICIENT); - } - - if (is_relayed) - { - if (relay_order >= path::DEFAULT_PATHS_HELD) - { - log::error(logcat, "Received PublishClientContact with invalid relay order: {}", relay_order); - return respond(PublishClientContact::INVALID_ORDER); - } - - log::debug(logcat, "Relaying EncryptedClientContact for {}", dht_key); - - const auto& peer_key = closest_rcs[relay_order].router_id(); - - if (peer_key == local_rid) + if (rc.router_id() == local_rid) { log::info( logcat, - "Received PublishClientContact for which we are index {}... storing client contact...", - relay_order); + "Received PublishClientContact (key: {}) for which we are a candidate; accepting...", + dht_key); _router.contact_db().put_cc(std::move(enc)); // return respond(messages::OK_RESPONSE); // TESTNET: return respond(PublishClientContact::SUCCESS); } + } - log::info(logcat, "Received PublishClientContact; propagating to peer index {}...", relay_order); + const auto& peer_key = closest_rcs.begin()->router_id(); - send_control_message( - peer_key, - "publish_cc", - PublishClientContact::serialize(std::move(enc), relay_order, is_relayed), - [respond = std::move(respond)](oxen::quic::message m) mutable { - if (m) - log::info(logcat, "Relayed PublishClientContact returned successful! Relaying response..."); - else if (m.timed_out) - log::info(logcat, "Relayed PublishClientContact timed out! Relaying response..."); - else - log::info(logcat, "Relayed PublishClientContact failed! Relaying response..."); + log::info(logcat, "Received PublishClientContact; propagating to peer (key: {})...", peer_key); - respond(m.body_str()); - }); - } - else - { - for (auto& rc : closest_rcs) - { - if (rc.router_id() == local_rid) - { - log::info( - logcat, - "Received PublishClientContact for {}; we are candidate {}; accepting...", - dht_key, - relay_order); - _router.contact_db().put_cc(std::move(enc)); - // return respond(messages::OK_RESPONSE); - // TESTNET: - return respond(PublishClientContact::SUCCESS); - } - } + send_control_message( + peer_key, + "publish_cc", + PublishClientContact::serialize(std::move(enc)), + [respond = std::move(respond)](oxen::quic::message m) mutable { + if (m) + log::info(logcat, "Relayed PublishClientContact returned successful! Relaying response..."); + else if (m.timed_out) + log::info(logcat, "Relayed PublishClientContact timed out! Relaying response..."); + else + log::info(logcat, "Relayed PublishClientContact failed! Relaying response..."); - log::warning(logcat, "Received non-relayed PublishClientContact from {}; we are not a candidate", dht_key); - } + respond(m.body_str()); + }); } void LinkManager::handle_find_cc(std::string_view body, std::function respond) @@ -1160,7 +1124,7 @@ namespace llarp log::debug(logcat, "Relaying FindClientContactMessage for {}", dht_key); - const auto& peer_key = closest_rcs[relay_order].router_id(); + const auto& peer_key = closest_rcs.begin()->router_id(); send_control_message( peer_key, @@ -1336,7 +1300,7 @@ namespace llarp // if terminal hop, payload should contain a request (e.g. "ons_resolve"); handle and respond. if (hop->terminal_hop) { - log::debug(logcat, "We are terminal hop for path request!"); + log::debug(logcat, "We are terminal hop for path request: {}", hop->to_string()); return handle_inner_request(std::move(m), std::move(payload), std::move(hop)); } diff --git a/llarp/messages/dht.hpp b/llarp/messages/dht.hpp index 7661d79b42..b8842fbf2f 100644 --- a/llarp/messages/dht.hpp +++ b/llarp/messages/dht.hpp @@ -129,45 +129,14 @@ namespace llarp inline const auto INSUFFICIENT = messages::serialize_response({{messages::STATUS_KEY, "INSUFFICIENT NODES"}}); inline const auto INVALID_ORDER = messages::serialize_response({{messages::STATUS_KEY, "INVALID ORDER"}}); - inline static std::string serialize(const EncryptedClientContact& ecc, uint64_t relay_order, bool is_relayed) + inline static std::string serialize(const EncryptedClientContact& ecc) { - oxenc::bt_dict_producer btdp; - - try - { - btdp.append("o", relay_order); - btdp.append("r", is_relayed); - btdp.append("x", ecc.bt_payload()); - } - catch (...) - { - log::error(messages::logcat, "Error: failed to serialize PublishClientContact contents!"); - } - - return std::move(btdp).str(); + return oxenc::bt_serialize(ecc.bt_payload()); } - inline static std::tuple deserialize(std::string_view buf) + inline static EncryptedClientContact deserialize(std::string_view buf) { - EncryptedClientContact ecc; - bool is_relayed; - uint64_t relay_order; - - try - { - oxenc::bt_dict_consumer btdc{buf}; - is_relayed = btdc.require("o"); - relay_order = btdc.require("r"); - ecc = EncryptedClientContact::deserialize(btdc.require("x")); - } - catch (const std::exception& e) - { - log::error( - messages::logcat, "Error: failed to deserialize PublishClientContact contents: {}", e.what()); - throw; - } - - return {std::move(ecc), relay_order, is_relayed}; + return EncryptedClientContact::deserialize(oxenc::bt_deserialize(buf)); } } // namespace PublishClientContact } // namespace llarp diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index b262c590e6..be5346f939 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -1,7 +1,6 @@ #include "nodedb.hpp" #include "crypto/types.hpp" -#include "dht/kademlia.hpp" #include "link/link_manager.hpp" #include "messages/fetch.hpp" #include "util/time.hpp" @@ -1092,30 +1091,13 @@ namespace llarp }); } - std::vector NodeDB::find_many_closest_to(llarp::dht::Key_t location, uint32_t numRouters) const + dht::rc_set NodeDB::find_many_closest_to(llarp::dht::Key_t location, uint32_t numRouters) const { - return _router.loop()->call_get([this, location, numRouters]() -> std::vector { - std::vector all; + return _router.loop()->call_get([this, location, numRouters]() -> dht::rc_set { + dht::rc_set ret{known_rcs.begin(), known_rcs.end(), dht::XorMetric{location}}; - all.reserve(known_rcs.size()); - - for (auto& entry : rc_lookup) - { - all.push_back(&entry.second); - } - - 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); - - return closest; + ret.erase(std::next(ret.begin(), numRouters), ret.end()); + return ret; }); } } // namespace llarp diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index 8183f897de..71980aeb26 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -3,7 +3,7 @@ #include "contact/relay_contact.hpp" #include "contact/router_id.hpp" #include "crypto/crypto.hpp" -#include "dht/key.hpp" +#include "dht/bucket.hpp" #include "router/router.hpp" #include "util/common.hpp" #include "util/thread/threading.hpp" @@ -316,7 +316,7 @@ namespace llarp RemoteRC find_closest_to(dht::Key_t location) const; /// find many routers closest to dht key - std::vector find_many_closest_to(dht::Key_t location, uint32_t numRouters) const; + dht::rc_set 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_rc(const RouterID& pk) const; diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index dd9c1e9cf3..1dd4cfe62a 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -41,14 +41,16 @@ namespace llarp::path hops[idx].txID = hops[idx + 1].rxID; } + // TODO: make pivot TXID = RXID + // initialize parts of the clientintro // intro.pivot_rid = transit_hops.back().rc.router_id(); // intro.pivot_hid = transit_hops.back()._txid; intro.pivot_rid = hops.back().rc.router_id(); - intro.pivot_hid = hops.back().txID; + intro.pivot_rxid = hops.back().rxID; log::info( - logcat, "Path client intro holding pivot_rid ({}) and pivot_hid ({})", intro.pivot_rid, intro.pivot_hid); + logcat, "Path client intro holding pivot_rid ({}) and pivot_rxid ({})", intro.pivot_rid, intro.pivot_rxid); } void Path::link_session(recv_session_dgram_cb cb) @@ -125,11 +127,9 @@ namespace llarp::path "find_cc", FindClientContact::serialize(location, order, is_relayed), std::move(func)); } - bool Path::publish_client_contact( - const EncryptedClientContact& ecc, bool is_relayed, uint64_t order, std::function func) + bool Path::publish_client_contact(const EncryptedClientContact& ecc, std::function func) { - return send_path_control_message( - "publish_cc", PublishClientContact::serialize(ecc, order, is_relayed), std::move(func)); + return send_path_control_message("publish_cc", PublishClientContact::serialize(ecc), std::move(func)); } bool Path::resolve_ons(std::string name, std::function func) @@ -163,7 +163,6 @@ namespace llarp::path hop.nonceXOR); } - // TESTNET: upstream_txid -> upstream_rxid return ONION::serialize_hop(upstream_rxid().to_view(), nonce, std::move(inner_payload)); } diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 8089296ab8..7a3d9af963 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -99,10 +99,7 @@ namespace llarp const dht::Key_t& location, bool is_relayed, uint64_t order, std::function func); bool publish_client_contact( - const EncryptedClientContact& ecc, - bool is_relayed = false, - uint64_t order = 0, - std::function func = nullptr); + const EncryptedClientContact& ecc, std::function func = nullptr); bool close_exit( const Ed25519SecretKey& sk, std::string tx_id, std::function func = nullptr); diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index 5e027ff940..806896d6ad 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -18,23 +18,6 @@ namespace llarp::path return _allow_transit; } - std::vector> PathContext::get_local_paths_to_remote(const RouterID& r) - { - Lock_t l{paths_mutex}; - - std::vector> found; - - for (const auto& [pathid, path] : _path_map) - { - if (path->upstream_txid() == pathid) - continue; - - if (path->pivot_rid() == r && path->is_ready()) - found.push_back(path); - } - return found; - } - void PathContext::add_path(std::shared_ptr path) { Lock_t l{paths_mutex}; @@ -43,10 +26,6 @@ namespace llarp::path put_transit_hop(TransitHop::from_hop_config(path->upstream())); _path_map.emplace(path->upstream_rxid(), path); - _path_map.emplace(path->upstream_txid(), path); - - _path_map.emplace(path->pivot_rxid(), path); - _path_map.emplace(path->pivot_txid(), path); } void PathContext::drop_paths(std::vector> droplist) @@ -66,15 +45,6 @@ namespace llarp::path if (auto itr = _path_map.find(path->upstream_rxid()); itr != _path_map.end()) _path_map.erase(itr); - - if (auto itr = _path_map.find(path->upstream_txid()); itr != _path_map.end()) - _path_map.erase(itr); - - if (auto itr = _path_map.find(path->pivot_rxid()); itr != _path_map.end()) - _path_map.erase(itr); - - if (auto itr = _path_map.find(path->pivot_txid()); itr != _path_map.end()) - _path_map.erase(itr); } bool PathContext::has_transit_hop(const std::shared_ptr& hop) diff --git a/llarp/path/path_context.hpp b/llarp/path/path_context.hpp index 90321369de..d09f86fb56 100644 --- a/llarp/path/path_context.hpp +++ b/llarp/path/path_context.hpp @@ -38,9 +38,6 @@ namespace llarp::path std::shared_ptr get_path_handler(const HopID& id); - /// get a set of all paths that we own who's endpoint is r - std::vector> get_local_paths_to_remote(const RouterID& r); - void add_path(std::shared_ptr p); void drop_path(const std::shared_ptr& p); @@ -57,7 +54,7 @@ namespace llarp::path /** TODO: - paths are not 1:1 with upstream RID - - paths are 1:1 with txid's + - paths are 1:1 with edge rxIDs */ std::unordered_map> _path_map; diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index 84f2f37e10..35e3579da0 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -65,19 +65,20 @@ namespace llarp::path log::debug(logcat, "Adding path..."); Lock_t l(paths_mutex); - _paths.insert_or_assign(p->pivot_rid(), p); - associate_hop_ids(p); + _paths.insert_or_assign(p->upstream_rxid(), p); + + // associate_hop_ids(p); _router.path_context()->add_path(p); } std::optional> PathHandler::get_random_path() { - std::optional>> t = std::nullopt; + auto p = std::make_optional>>(); - std::sample(_paths.begin(), _paths.end(), &t, 1, csrng); // TOFIX: TESTNET: + std::sample(_paths.begin(), _paths.end(), &*p, 1, csrng); - return t.has_value() ? std::make_optional(t->second) : std::nullopt; + return p.has_value() ? std::make_optional(p->second) : std::nullopt; } std::optional> PathHandler::get_path_conditional( @@ -118,9 +119,9 @@ namespace llarp::path for (size_t i = 0; i < n; ++i) { - std::pair> t; + std::pair> t; - std::sample(_paths.begin(), _paths.end(), &t, 1, csrng); // TOFIX: TESTNET: + std::sample(_paths.begin(), _paths.end(), &t, 1, csrng); selected->insert(selected->end(), t.second); } @@ -216,16 +217,7 @@ namespace llarp::path // called within the scope of locked mutex std::optional> PathHandler::get_path(HopID hid) const { - if (auto itr = _path_lookup.find(hid); itr != _path_lookup.end()) - return get_path(itr->second); - - return std::nullopt; - } - - // called within the scope of locked mutex - std::optional> PathHandler::get_path(const RouterID& rid) const - { - if (auto itr = _paths.find(rid); itr != _paths.end()) + if (auto itr = _paths.find(hid); itr != _paths.end()) return itr->second; return std::nullopt; @@ -333,13 +325,13 @@ namespace llarp::path _running = false; - Lock_t l{paths_mutex}; + // Lock_t l{paths_mutex}; - for (auto& [_, p] : _paths) - { - if (p) - dissociate_hop_ids(p); - } + // for (auto& [_, p] : _path_map) + // { + // if (p) + // dissociate_hop_ids(p); + // } _paths.clear(); @@ -496,7 +488,6 @@ namespace llarp::path last_build = llarp::time_now_ms(); const auto& edge = hops[0].router_id(); - const auto& pivot = hops.back().router_id(); if (not _router.pathbuild_limiter().Attempt(edge)) { @@ -504,16 +495,6 @@ namespace llarp::path return false; } - { - Lock_t l{paths_mutex}; - - if (auto [it, b] = _paths.try_emplace(pivot, nullptr); not b) - { - log::warning(logcat, "Pending build to {} already underway... aborting...", pivot); - return false; - } - } - return true; } @@ -521,6 +502,16 @@ namespace llarp::path { auto path = std::make_shared(_router, hops, get_weak()); + { + Lock_t l{paths_mutex}; + + if (auto [it, b] = _paths.try_emplace(path->upstream_rxid(), nullptr); not b) + { + log::warning(logcat, "Pending build to {} already underway... aborting...", path->upstream_rxid()); + return nullptr; + } + } + log::info(logcat, "Building path -> {} : {}", path->to_string(), path->HopsString()); return path; @@ -593,7 +584,11 @@ namespace llarp::path // called within the scope of a locked mutex void PathHandler::build(std::vector hops) { - if (pre_build(hops); auto new_path = build1(hops)) + // error message logs in function scope + if (not pre_build(hops)) + return; + + if (auto new_path = build1(hops)) { assert(new_path); @@ -632,29 +627,29 @@ namespace llarp::path m.body()); } - path_build_failed(pivot, std::move(new_path), m.timed_out); + path_build_failed(std::move(new_path), m.timed_out); })) { log::warning(logcat, "Error sending path_build control message"); - path_build_failed(pivot, new_path); + path_build_failed(new_path); } } } - void PathHandler::drop_path(const RouterID& remote) + void PathHandler::drop_path(const HopID& upstream_rxid) { Lock_t l{paths_mutex}; - if (auto itr = _paths.find(remote); itr != _paths.end()) + if (auto itr = _paths.find(upstream_rxid); itr != _paths.end()) _paths.erase(itr); } - void PathHandler::path_build_failed(const RouterID& remote, std::shared_ptr p, bool timeout) + void PathHandler::path_build_failed(std::shared_ptr p, bool timeout) { - if (not timeout) - dissociate_hop_ids(p); + // if (not timeout) + // dissociate_hop_ids(p); - drop_path(remote); + drop_path(p->upstream_rxid()); if (timeout) { @@ -690,23 +685,23 @@ namespace llarp::path _build_stats.path_fails++; } - void PathHandler::associate_hop_ids(std::shared_ptr& p) - { - for (auto& h : p->hops) - { - auto rid = p->pivot_rid(); - _path_lookup.emplace(h.rxID, rid); - _path_lookup.emplace(h.txID, rid); - } - } - - void PathHandler::dissociate_hop_ids(std::shared_ptr& p) - { - for (auto& h : p->hops) - { - _path_lookup.erase(h.txID); - _path_lookup.erase(h.rxID); - } - } + // void PathHandler::associate_hop_ids(std::shared_ptr& p) + // { + // for (auto& h : p->hops) + // { + // auto rid = p->pivot_rid(); + // _path_lookup.emplace(h.rxID, rid); + // _path_lookup.emplace(h.txID, rid); + // } + // } + + // void PathHandler::dissociate_hop_ids(std::shared_ptr& p) + // { + // for (auto& h : p->hops) + // { + // _path_lookup.erase(h.txID); + // _path_lookup.erase(h.rxID); + // } + // } } // namespace llarp::path diff --git a/llarp/path/path_handler.hpp b/llarp/path/path_handler.hpp index 52ca9fd25a..f6a3924173 100644 --- a/llarp/path/path_handler.hpp +++ b/llarp/path/path_handler.hpp @@ -97,10 +97,10 @@ namespace llarp void path_build_backoff(); - void associate_hop_ids(std::shared_ptr& p); + // void associate_hop_ids(std::shared_ptr& p); protected: - void dissociate_hop_ids(std::shared_ptr& p); + // void dissociate_hop_ids(std::shared_ptr& p); /// flag for ::Stop() std::atomic _running; @@ -112,17 +112,21 @@ namespace llarp mutable util::NullMutex paths_mutex; // TODO: make into templated map object - std::unordered_map _path_lookup; - std::unordered_map> _paths; + /** TESTNET: TODO: + - paths are 1:1 with edge rxid, NOT pivot routerID + */ + + // TESTNET: path mapping + std::unordered_map> _paths; /// return true if we hit our soft limit for building paths too fast on a first hop bool build_cooldown_hit(RouterID edge) const; - void drop_path(const RouterID& remote); + void drop_path(const HopID& remote); virtual void path_died(std::shared_ptr p); - void path_build_failed(const RouterID& remote, std::shared_ptr p, bool timeout = false); + void path_build_failed(std::shared_ptr p, bool timeout = false); virtual void path_build_succeeded(std::shared_ptr p); @@ -156,8 +160,6 @@ namespace llarp std::optional> get_path(HopID id) const; - std::optional> get_path(const RouterID& router) const; - intro_set get_current_client_intros() const; // service::intro_que_old get_recent_path_intros( diff --git a/llarp/path/path_types.hpp b/llarp/path/path_types.hpp index 5a267a7481..bd99ea8e0f 100644 --- a/llarp/path/path_types.hpp +++ b/llarp/path/path_types.hpp @@ -27,10 +27,15 @@ namespace llarp { /// path id HopID txID, rxID; + + // TESTNET: do not need the full RC, just the RouterID // router contact of router RemoteRC rc; + + // TESTNET: do not need to hold on to this nonce after path-building /// nonce for key exchange SymmNonce nonce; + /// shared secret at this hop SharedSecret shared; /// hash of shared secret used for nonce mutation diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index 39d5d10420..c73b8f0ceb 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -58,7 +58,7 @@ namespace llarp::path crypto::shorthash(xor_hash, hop->shared.data(), hop->shared.size()); hop->nonceXOR = xor_hash.data(); // nonceXOR is 24 bytes, ShortHash is 32; this will truncate - log::debug(logcat, "TransitHop data successfully deserialized"); + log::critical(logcat, "TransitHop data successfully deserialized: {}", hop->to_string()); return hop; } diff --git a/llarp/path/transit_hop.hpp b/llarp/path/transit_hop.hpp index eef2945878..c5dd0b69e9 100644 --- a/llarp/path/transit_hop.hpp +++ b/llarp/path/transit_hop.hpp @@ -11,7 +11,6 @@ namespace llarp struct Router; /** TODO: combine PathHopConfig into TransitHop - - Add RelayContact */ namespace path diff --git a/llarp/session/session.cpp b/llarp/session/session.cpp index 87c76b1913..03c26e5875 100644 --- a/llarp/session/session.cpp +++ b/llarp/session/session.cpp @@ -56,7 +56,7 @@ namespace llarp::session _current_path = std::move(_new_path); - _current_hop_id = _current_path->intro.pivot_hid; + _current_hop_id = _current_path->intro.pivot_rxid; if (_use_tun) _current_path->link_session([this](bstring data) { diff --git a/llarp/session/session.hpp b/llarp/session/session.hpp index 8db1de9d0c..320983fbc3 100644 --- a/llarp/session/session.hpp +++ b/llarp/session/session.hpp @@ -137,13 +137,7 @@ namespace llarp std::weak_ptr get_weak() override { return weak_from_this(); } - std::shared_ptr current_path() - { - if (auto itr = _paths.find(_remote.router_id()); itr != _paths.end()) - return itr->second; - - return nullptr; - } + std::shared_ptr current_path() { return _current_path; } void blacklist_snode(const RouterID& snode) override; From d0ef3e8c91668b68fbcb226972e15881ba84029a Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 31 Oct 2024 08:05:52 -0700 Subject: [PATCH 17/44] alas, hop unification! - TransitHop absorbed PathHopConfig, now only one object is consistently used to store path hop metadata --- llarp/constants/path.hpp | 6 +- llarp/handlers/session.cpp | 2 +- llarp/link/link_manager.cpp | 13 ++- llarp/messages/common.hpp | 1 - llarp/messages/path.hpp | 21 ++--- llarp/path/path.cpp | 157 +++++++++++++++++++++++------------- llarp/path/path.hpp | 29 +++---- llarp/path/path_context.cpp | 3 - llarp/path/path_handler.cpp | 90 +++++++-------------- llarp/path/path_handler.hpp | 25 +++--- llarp/path/path_types.hpp | 47 ----------- llarp/path/transit_hop.cpp | 65 +++++++-------- llarp/path/transit_hop.hpp | 64 ++++----------- llarp/profiling.cpp | 6 +- llarp/session/session.cpp | 4 +- 15 files changed, 220 insertions(+), 313 deletions(-) diff --git a/llarp/constants/path.hpp b/llarp/constants/path.hpp index bbf3acbd99..fc8147fdf1 100644 --- a/llarp/constants/path.hpp +++ b/llarp/constants/path.hpp @@ -14,7 +14,7 @@ namespace llarp::path /// 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; + constexpr std::chrono::milliseconds DEFAULT_LIFETIME{20min}; /// 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 @@ -30,6 +30,10 @@ namespace llarp::path /// after this many ms a path build times out constexpr auto BUILD_TIMEOUT = 10s; + constexpr auto MIN_PATH_BUILD_INTERVAL{500ms}; + + constexpr auto PATH_BUILD_RATE{100ms}; + /// measure latency every this interval ms constexpr auto LATENCY_INTERVAL = 20s; /// if a path is inactive for this amount of time it's dead diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index 5dd29f098b..da95fea730 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -539,7 +539,7 @@ namespace llarp::handlers auto path = std::make_shared(_router, std::move(hops), get_weak(), true, remote.is_client()); - log::info(logcat, "Building path -> {} : {}", path->to_string(), path->HopsString()); + log::info(logcat, "Building path -> {} : {}", path->to_string(), path->hop_string()); auto payload = build2(path); diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 1c713b0beb..ee12b4e2dc 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1187,14 +1187,17 @@ namespace llarp auto hop = path::TransitHop::deserialize_hop( oxenc::bt_dict_consumer{hop_payload}, from, _router, std::move(shared)); - hop->started = _router.now(); - set_conn_persist(hop->downstream(), hop->expiry_time() + 10s); - // we are terminal hop and everything is okay if (hop->upstream() == _router.local_rid()) { log::info(logcat, "We are the terminal hop; path build succeeded"); - hop->terminal_hop = true; + if (not hop->terminal_hop) + { + // TESTNET: remove this eventually + log::critical( + logcat, "DANIEL FIX THIS: Hop is terminal hop; constructor should have flipped this boolean"); + hop->terminal_hop = true; + } _router.path_context()->put_transit_hop(std::move(hop)); return m.respond(messages::OK_RESPONSE, false); } @@ -1304,6 +1307,8 @@ namespace llarp return handle_inner_request(std::move(m), std::move(payload), std::move(hop)); } + log::debug(logcat, "We are intermediate hop for path request: {}", hop->to_string()); + auto hop_is_rx = hop->rxid() == hop_id; const auto& next_id = hop_is_rx ? hop->txid() : hop->rxid(); diff --git a/llarp/messages/common.hpp b/llarp/messages/common.hpp index 386d29a3f1..3b854cf141 100644 --- a/llarp/messages/common.hpp +++ b/llarp/messages/common.hpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index cb0e3c7f52..32faf17943 100644 --- a/llarp/messages/path.hpp +++ b/llarp/messages/path.hpp @@ -3,6 +3,7 @@ #include "common.hpp" #include +#include #include namespace llarp @@ -91,27 +92,15 @@ namespace llarp - 'k' : shared pubkey used to derive symmetric key - 'n' : symmetric nonce used for DH key-exchange - 'x' : encrypted payload - - 'l' : path lifetime - 'r' : rxID (the path ID for messages going *to* the hop) - 't' : txID (the path ID for messages coming *from* the client/path origin) - 'u' : upstream hop RouterID All of these 'frames' are inserted sequentially into the list and padded with any needed dummy frames */ - inline static std::string serialize_hop(path::PathHopConfig& hop) + inline static std::string serialize_hop(path::TransitHop& hop) { - std::string hop_payload; - - { - oxenc::bt_dict_producer btdp; - - btdp.append("l", path::DEFAULT_LIFETIME.count()); - btdp.append("r", hop.rxID.to_view()); - btdp.append("t", hop.txID.to_view()); - btdp.append("u", hop.upstream.to_view()); - - hop_payload = std::move(btdp).str(); - } + std::string hop_payload = hop.bt_encode(); Ed25519SecretKey ephemeral_key; crypto::identity_keygen(ephemeral_key); @@ -119,7 +108,7 @@ namespace llarp hop.nonce = SymmNonce::make_random(); crypto::derive_encrypt_outer_wrapping( - ephemeral_key, hop.shared, hop.nonce, hop.rc.router_id(), to_uspan(hop_payload)); + ephemeral_key, hop.shared, hop.nonce, hop.router_id(), to_uspan(hop_payload)); // generate nonceXOR value self->hop->pathKey ShortHash xor_hash; @@ -131,7 +120,7 @@ namespace llarp logcat, "Hop serialized; nonce: {}, remote router_id: {}, shared pk: {}, shared secret: {}, payload: {}", hop.nonce.to_string(), - hop.rc.router_id().to_string(), + hop.router_id().to_string(), ephemeral_key.to_pubkey().to_string(), hop.shared.to_string(), buffer_printer{hop_payload}); diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 1dd4cfe62a..bc7801abde 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -20,36 +20,39 @@ namespace llarp::path bool is_session, bool is_client) : handler{std::move(_handler)}, _router{rtr}, _is_session_path{is_session}, _is_client{is_client} + { + populate_internals(_hops); + + log::info(logcat, "Path successfully constructed: {}", to_string()); + } + + void Path::populate_internals(const std::vector& _hops) { size_t n_hops = _hops.size(); - // transit_hops.resize(n_hops); hops.resize(n_hops); - for (size_t idx = 0; idx < n_hops; ++idx) + for (size_t i = 0; i < n_hops; ++i) { - // transit_hops[idx] - hops[idx].rc = _hops[idx]; - hops[idx].txID = HopID::make_random(); - // transit_hops[idx]._txid = HopID::make_random(); - hops[idx].rxID = HopID::make_random(); - // transit_hops[idx]._rxid = HopID::make_random(); + hops[i]._rid = _hops[i].router_id(); + hops[i]._txid = HopID::make_random(); + + // First hop RXID is unique, the rest are the previous hop TXID + hops[i]._rxid = i ? hops[i - 1]._txid : HopID::make_random(); + // First hop downstream is it's own RID, the rest are the previous hop RID + hops[i]._downstream = i ? hops[i - 1]._rid : hops[i]._rid; + // Last hop upstream is it's own RID, the rest are the next hop RID + hops[i]._upstream = i == n_hops - 1 ? hops[i]._rid : hops[i + 1]._rid; } - for (size_t idx = 0; idx < n_hops - 1; ++idx) - { - // transit_hops[idx]._txid = transit_hops[idx + 1]._rxid; - hops[idx].txID = hops[idx + 1].rxID; - } + hops.back().terminal_hop = true; - // TODO: make pivot TXID = RXID + log::info(logcat, "Path populated with hops: {}", hop_string()); // initialize parts of the clientintro - // intro.pivot_rid = transit_hops.back().rc.router_id(); - // intro.pivot_hid = transit_hops.back()._txid; - intro.pivot_rid = hops.back().rc.router_id(); - intro.pivot_rxid = hops.back().rxID; + intro.pivot_rid = hops.back().router_id(); + intro.pivot_rxid = hops.back()._rxid; - log::info( + log::debug( logcat, "Path client intro holding pivot_rid ({}) and pivot_rxid ({})", intro.pivot_rid, intro.pivot_rxid); } @@ -84,8 +87,8 @@ namespace llarp::path { auto& first_hop = hops.front(); auto& other_first = other.hops.front(); - return std::tie(first_hop.txID, first_hop.rxID, first_hop.upstream) - < std::tie(other_first.txID, other_first.rxID, other_first.upstream); + return std::tie(first_hop._txid, first_hop._rxid, first_hop._upstream) + < std::tie(other_first._txid, other_first._rxid, other_first._upstream); } bool Path::operator==(const Path& other) const @@ -245,78 +248,73 @@ namespace llarp::path return _established ? !is_expired(now) : false; } - PathHopConfig Path::upstream() - { - return hops.front(); - } - RouterID Path::upstream_rid() { - return hops.front().rc.router_id(); + return hops.front().router_id(); } const RouterID& Path::upstream_rid() const { - return hops.front().rc.router_id(); + return hops.front().router_id(); } HopID Path::upstream_txid() { - return hops.front().txID; + return hops.front().txid(); } const HopID& Path::upstream_txid() const { - return hops.front().txID; + return hops.front().txid(); } HopID Path::upstream_rxid() { - return hops.front().rxID; + return hops.front().rxid(); } const HopID& Path::upstream_rxid() const { - return hops.front().rxID; + return hops.front().rxid(); } RouterID Path::pivot_rid() { - return hops.back().rc.router_id(); + return hops.back().router_id(); } const RouterID& Path::pivot_rid() const { - return hops.back().rc.router_id(); + return hops.back().router_id(); } HopID Path::pivot_txid() { - return hops.back().txID; + return hops.back().txid(); } const HopID& Path::pivot_txid() const { - return hops.back().txID; + return hops.back().txid(); } HopID Path::pivot_rxid() { - return hops.back().rxID; + return hops.back().rxid(); } const HopID& Path::pivot_rxid() const { - return hops.back().rxID; + return hops.back().rxid(); } std::string Path::to_string() const { - return "RID:{} -- TX:{}/RX:{}"_format( + return "Path:[ Local RID:{} -- Edge TX:{}/RX:{} ]"_format( _router.local_rid().ShortString(), upstream_txid().to_string(), upstream_rxid().to_string()); } - std::string Path::HopsString() const + std::string Path::hop_string() const { std::string hops_str; hops_str.reserve(hops.size() * 62); // 52 for the pkey, 6 for .snode, 4 for the ' -> ' joiner @@ -324,22 +322,11 @@ namespace llarp::path { if (!hops.empty()) hops_str += " -> "; - hops_str += hop.rc.router_id().ShortString(); + hops_str += hop.router_id().ShortString(); } return hops_str; } - nlohmann::json PathHopConfig::ExtractStatus() const - { - nlohmann::json obj{ - {"ip", rc.addr().to_string()}, - {"lifetime", to_json(lifetime)}, - {"router", rc.router_id().ToHex()}, - {"txid", txID.ToHex()}, - {"rxid", rxID.ToHex()}}; - return obj; - } - nlohmann::json Path::ExtractStatus() const { auto now = llarp::time_now_ms(); @@ -364,13 +351,67 @@ namespace llarp::path { if (auto parent = handler.lock()) { - std::vector new_hops; - - for (const auto& hop : hops) - new_hops.emplace_back(hop.rc); + auto prev_upstream_rxid = upstream_rxid(); + + if (auto new_hops = parent->aligned_hops_to_remote(pivot_rid())) + { + populate_internals(*new_hops); + log::info(logcat, "{} rebuilding new path to pivot {}", name(), to_string()); + + auto self = shared_from_this(); + auto payload = parent->build2(self); + auto upstream = upstream_rid(); + + if (not parent->build3( + std::move(upstream), + std::move(payload), + [new_path = std::move(self), parent = parent, prev_rxid = prev_upstream_rxid]( + oxen::quic::message m) mutable { + if (m) + { + log::critical(logcat, "PATH ESTABLISHED: {}", new_path->hop_string()); + parent->drop_path(prev_rxid); + return parent->path_build_succeeded(std::move(new_path)); + } + + try + { + if (m.timed_out) + { + log::warning(logcat, "Path build request timed out!"); + } + else + { + oxenc::bt_dict_consumer d{m.body()}; + auto status = d.require(messages::STATUS_KEY); + log::warning(logcat, "Path build returned failure status: {}", status); + } + } + catch (const std::exception& e) + { + log::warning( + logcat, + "Exception caught parsing path build response: {}; input: {}", + e.what(), + m.body()); + } + + parent->path_build_failed(std::move(new_path), m.timed_out); + })) + { + log::warning(logcat, "Error sending path_build control message"); + } + } + else + { + log::warning(logcat, "Could not find new hops to rebuild path to pivot {}", to_string()); + } - log::info(logcat, "{} rebuilding on {}", name(), to_string()); - parent->build(new_hops); + parent->drop_path(prev_upstream_rxid); + } + else + { + log::warning(logcat, "Path ({}) died with no parent to rebuild!", to_string()); } } diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 7a3d9af963..dbd4946a13 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -1,6 +1,7 @@ #pragma once #include "path_handler.hpp" +#include "transit_hop.hpp" #include #include @@ -30,19 +31,16 @@ namespace llarp namespace path { - struct TransitHop; - struct PathHopConfig; - using recv_session_dgram_cb = std::function; - // TODO: replace vector of PathHopConfig with vector of TransitHops + /** TODO: + - we only need a vector of RID's for path-building, not RemoteRC's + */ /// A path we made struct Path : public std::enable_shared_from_this { - std::vector hops; - - // std::vector transit_hops; + std::vector hops; std::weak_ptr handler; @@ -63,7 +61,7 @@ namespace llarp nlohmann::json ExtractStatus() const; - std::string HopsString() const; + std::string hop_string() const; std::chrono::milliseconds LastRemoteActivityAt() const { return last_recv_msg; } @@ -77,8 +75,6 @@ namespace llarp bool is_linked() const { return _is_linked; } - std::chrono::milliseconds ExpireTime() const { return buildStarted + hops[0].lifetime; } - void enable_exit_traffic(); void mark_exit_closed(); @@ -87,8 +83,7 @@ namespace llarp bool is_expired(std::chrono::milliseconds now = llarp::time_now_ms()) const; - /// build a new path on the same set of hops as us - /// regenerates keys + /// build a new path to the same pivot, but with different hops void rebuild(); void Tick(std::chrono::milliseconds now); @@ -125,8 +120,6 @@ namespace llarp bool is_ready(std::chrono::milliseconds now = llarp::time_now_ms()) const; - PathHopConfig upstream(); - RouterID upstream_rid(); const RouterID& upstream_rid() const; @@ -163,6 +156,8 @@ namespace llarp private: std::string make_path_message(std::string payload); + void populate_internals(const std::vector& _hops); + bool SendLatencyMessage(Router* r); /// call obtained exit hooks @@ -194,11 +189,11 @@ namespace std { auto& first_hop = p.hops[0]; llarp::AlignedBuffer b; - std::memcpy(b.data(), first_hop.txID.data(), PATHIDSIZE); - std::memcpy(&b[PATHIDSIZE], first_hop.txID.data(), PATHIDSIZE); + std::memcpy(b.data(), first_hop._txid.data(), PATHIDSIZE); + std::memcpy(&b[PATHIDSIZE], first_hop._txid.data(), PATHIDSIZE); auto h = hash>{}(b); - return h ^ hash{}(first_hop.upstream); + return h ^ hash{}(first_hop._upstream); } }; } // namespace std diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index 806896d6ad..140da8590c 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -22,9 +22,6 @@ namespace llarp::path { Lock_t l{paths_mutex}; - // TESTNET: TODO: once PathHopConfig -> TransitHop, remove this association - put_transit_hop(TransitHop::from_hop_config(path->upstream())); - _path_map.emplace(path->upstream_rxid(), path); } diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index 35e3579da0..7b6f6ec961 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -464,11 +464,11 @@ namespace llarp::path return false; } - bool PathHandler::build_path_aligned_to_remote(const NetworkAddress& remote) + bool PathHandler::build_path_aligned_to_remote(const RouterID& remote) { Lock_t l(paths_mutex); - if (auto maybe_hops = aligned_hops_to_remote(remote.router_id())) + if (auto maybe_hops = aligned_hops_to_remote(remote)) { build(*maybe_hops); return true; @@ -512,12 +512,12 @@ namespace llarp::path } } - log::info(logcat, "Building path -> {} : {}", path->to_string(), path->HopsString()); + log::info(logcat, "Building path -> {} : {}", path->to_string(), path->hop_string()); return path; } - std::string PathHandler::build2(std::shared_ptr& path) + std::string PathHandler::build2(const std::shared_ptr& path) { std::vector frames(path::MAX_LEN); auto& path_hops = path->hops; @@ -538,8 +538,8 @@ namespace llarp::path // i from n_hops down to 0 for (int i = n_hops - 1; i >= 0; --i) { - const auto& next_rid = i == n_hops - 1 ? path_hops[i].rc.router_id() : path_hops[i + 1].rc.router_id(); - path_hops[i].upstream = next_rid; + const auto& next_rid = i == n_hops - 1 ? path_hops[i].router_id() : path_hops[i + 1].router_id(); + path_hops[i]._upstream = next_rid; frames[i] = PATH::BUILD::serialize_hop(path_hops[i]); @@ -593,42 +593,37 @@ namespace llarp::path assert(new_path); auto payload = build2(new_path); - auto pivot = new_path->pivot_rid(); auto upstream = new_path->upstream_rid(); - if (not build3( - std::move(upstream), std::move(payload), [this, new_path, pivot](oxen::quic::message m) mutable { - if (m) + if (not build3(std::move(upstream), std::move(payload), [this, new_path](oxen::quic::message m) mutable { + if (m) + { + log::critical(logcat, "PATH ESTABLISHED: {}", new_path->hop_string()); + return path_build_succeeded(std::move(new_path)); + } + + try + { + // TODO: inform failure (what this means needs revisiting, badly) + if (m.timed_out) { - log::critical(logcat, "PATH ESTABLISHED: {}", new_path->HopsString()); - return path_build_succeeded(std::move(new_path)); + log::warning(logcat, "Path build request timed out!"); } - - try - { - // TODO: inform failure (what this means needs revisiting, badly) - if (m.timed_out) - { - log::warning(logcat, "Path build request timed out!"); - } - else - { - oxenc::bt_dict_consumer d{m.body()}; - auto status = d.require(messages::STATUS_KEY); - log::warning(logcat, "Path build returned failure status: {}", status); - } - } - catch (const std::exception& e) + else { - log::warning( - logcat, - "Exception caught parsing path build response: {}; input: {}", - e.what(), - m.body()); + oxenc::bt_dict_consumer d{m.body()}; + auto status = d.require(messages::STATUS_KEY); + log::warning(logcat, "Path build returned failure status: {}", status); } - - path_build_failed(std::move(new_path), m.timed_out); - })) + } + catch (const std::exception& e) + { + log::warning( + logcat, "Exception caught parsing path build response: {}; input: {}", e.what(), m.body()); + } + + path_build_failed(std::move(new_path), m.timed_out); + })) { log::warning(logcat, "Error sending path_build control message"); path_build_failed(new_path); @@ -646,9 +641,6 @@ namespace llarp::path void PathHandler::path_build_failed(std::shared_ptr p, bool timeout) { - // if (not timeout) - // dissociate_hop_ids(p); - drop_path(p->upstream_rxid()); if (timeout) @@ -684,24 +676,4 @@ namespace llarp::path log::warning(logcat, "Path {} died post-build", p->to_string()); _build_stats.path_fails++; } - - // void PathHandler::associate_hop_ids(std::shared_ptr& p) - // { - // for (auto& h : p->hops) - // { - // auto rid = p->pivot_rid(); - // _path_lookup.emplace(h.rxID, rid); - // _path_lookup.emplace(h.txID, rid); - // } - // } - - // void PathHandler::dissociate_hop_ids(std::shared_ptr& p) - // { - // for (auto& h : p->hops) - // { - // _path_lookup.erase(h.txID); - // _path_lookup.erase(h.rxID); - // } - // } - } // namespace llarp::path diff --git a/llarp/path/path_handler.hpp b/llarp/path/path_handler.hpp index f6a3924173..af797f1d8e 100644 --- a/llarp/path/path_handler.hpp +++ b/llarp/path/path_handler.hpp @@ -90,6 +90,8 @@ namespace llarp struct PathHandler { + friend struct Path; + private: std::chrono::milliseconds last_warn_time{0s}; @@ -97,11 +99,7 @@ namespace llarp void path_build_backoff(); - // void associate_hop_ids(std::shared_ptr& p); - protected: - // void dissociate_hop_ids(std::shared_ptr& p); - /// flag for ::Stop() std::atomic _running; @@ -111,11 +109,6 @@ namespace llarp using Lock_t = util::NullLock; mutable util::NullMutex paths_mutex; - // TODO: make into templated map object - /** TESTNET: TODO: - - paths are 1:1 with edge rxid, NOT pivot routerID - */ - // TESTNET: path mapping std::unordered_map> _paths; @@ -215,18 +208,18 @@ namespace llarp bool build_path_to_random(); - bool build_path_aligned_to_remote(const NetworkAddress& remote); + bool build_path_aligned_to_remote(const RouterID& remote); std::optional> aligned_hops_to_remote( const RouterID& pivot, const std::set& exclude = {}); // The build logic is segmented into functions designed to be called sequentially. - // - pre_build() : This handles all checking of the vector of hops, verifying with buildlimiter, ensuring - // there is no ongoing path-build, etc + // - pre_build() : This handles all checking of the vector of hops, verifying with buildlimiter, etc // - build1() : This can be re-implemented by inheriting classes that want to pass different parameters to // the created path. This is useful ßin cases like Outbound Sessions, Paths are constructed with the // respective is_client and is_exit booleans set. Regardless, the implementation needs to return the - // created shared_ptr to be passed by reference to build2(...) and build3(...). + // created shared_ptr to be passed by reference to build2(...) and build3(...). The implementation MUST + // also check if the upstream rxid is already being used for a current path (very unlikely) // - build2() : This contains the bulk of the code that is identical across all instances of path building. // It returns the payload holding the encoded frames for each hop. // - build3() : Inheriting classes can pass their own response handler functions as the second parameter, @@ -235,16 +228,16 @@ namespace llarp // failures for that respective remote or not. // - build() : This function calls pre_build() + build{1,2,3}() in the correct order and is used for the // usual times that PathBuilder initiates a path build + void build(std::vector hops); + bool pre_build(std::vector& hops); virtual std::shared_ptr build1(std::vector& hops); - std::string build2(std::shared_ptr& path); + std::string build2(const std::shared_ptr& path); bool build3(RouterID upstream, std::string payload, std::function handler); - void build(std::vector hops); - void for_each_path(std::function&)> visit) const; /// pick a first hop diff --git a/llarp/path/path_types.hpp b/llarp/path/path_types.hpp index bd99ea8e0f..f26b501f74 100644 --- a/llarp/path/path_types.hpp +++ b/llarp/path/path_types.hpp @@ -19,53 +19,6 @@ namespace llarp return h; } }; - - namespace path - { - /// configuration for a single hop when building a path - struct PathHopConfig - { - /// path id - HopID txID, rxID; - - // TESTNET: do not need the full RC, just the RouterID - // router contact of router - RemoteRC rc; - - // TESTNET: do not need to hold on to this nonce after path-building - /// nonce for key exchange - SymmNonce nonce; - - /// shared secret at this hop - SharedSecret shared; - /// hash of shared secret used for nonce mutation - SymmNonce nonceXOR; - /// next hop's router id - RouterID upstream; - // lifetime - std::chrono::milliseconds lifetime{DEFAULT_LIFETIME}; - - nlohmann::json ExtractStatus() const; - - bool operator<(const PathHopConfig& other) const - { - return std::tie(txID, rxID, rc, upstream, lifetime) - < std::tie(other.txID, other.rxID, other.rc, other.upstream, other.lifetime); - } - - bool operator==(const PathHopConfig& other) const - { - return std::tie(txID, rxID, rc, upstream, lifetime) - == std::tie(other.txID, other.rxID, other.rc, other.upstream, other.lifetime); - } - - bool operator!=(const PathHopConfig& other) const { return not(*this == other); } - }; - - // 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/transit_hop.cpp b/llarp/path/transit_hop.cpp index c73b8f0ceb..b85f72da6e 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -9,20 +9,6 @@ namespace llarp::path { static auto logcat = log::Cat("transit-hop"); - std::shared_ptr TransitHop::from_hop_config(PathHopConfig hop_config) - { - auto hop = std::make_shared(); - - hop->_txid = {hop_config.txID}; - hop->_rxid = {hop_config.rxID}; - hop->_upstream = {hop_config.upstream}; - hop->shared = {hop_config.shared}; - hop->nonce = {hop_config.nonce}; - hop->nonceXOR = {hop_config.nonceXOR}; - - return hop; - } - std::shared_ptr TransitHop::deserialize_hop( oxenc::bt_dict_consumer&& btdc, const RouterID& src, Router& r, SharedSecret secret) { @@ -30,10 +16,7 @@ namespace llarp::path try { - hop->lifetime = btdc.require("l") * 1ms; - hop->_rxid.from_string(btdc.require("r")); - hop->_txid.from_string(btdc.require("t")); - hop->_upstream.from_string(btdc.require("u")); + hop->bt_decode(std::move(btdc)); } catch (const std::exception& e) { @@ -44,12 +27,12 @@ namespace llarp::path if (hop->rxid().is_zero() || hop->txid().is_zero()) throw std::runtime_error{PATH::BUILD::BAD_PATHID}; - if (hop->lifetime > path::DEFAULT_LIFETIME) - throw std::runtime_error{PATH::BUILD::BAD_LIFETIME}; - hop->_downstream = src; hop->shared = std::move(secret); + if (hop->_upstream == hop->_downstream) + hop->terminal_hop = true; + if (r.path_context()->has_transit_hop(hop)) throw std::runtime_error{PATH::BUILD::BAD_PATHID}; @@ -63,34 +46,40 @@ namespace llarp::path return hop; } - bool TransitHop::is_expired(std::chrono::milliseconds now) const + void TransitHop::bt_decode(oxenc::bt_dict_consumer&& btdc) { - return destroy || (now >= expiry_time()); + _rxid.from_string(btdc.require("r")); + _txid.from_string(btdc.require("t")); + _upstream.from_string(btdc.require("u")); + expiry = llarp::time_now_ms() + path::DEFAULT_LIFETIME; } - std::chrono::milliseconds TransitHop::expiry_time() const + std::string TransitHop::bt_encode() const { - return started + lifetime; - } + oxenc::bt_dict_producer btdp; - std::string TransitHop::to_string() const - { - return "[TransitHop: tx={} rx={} upstream={} downstream={} started={} lifetime={}"_format( - _txid, _rxid, _upstream, _downstream, started.count(), lifetime.count()); - } + btdp.append("r", _rxid.to_view()); + btdp.append("t", _txid.to_view()); + btdp.append("u", _upstream.to_view()); - void TransitHop::Stop() - { - // TODO: still need this concept? + return std::move(btdp).str(); } - void TransitHop::SetSelfDestruct() + nlohmann::json TransitHop::ExtractStatus() const { - destroy = true; + return { + {"rid", router_id().ToHex()}, + {"rxid", rxid().ToHex()}, + {"txid", txid().ToHex()}, + {"expiry", to_json(expiry)}, + {"txid", _txid.ToHex()}, + {"rxid", _rxid.ToHex()}}; } - void TransitHop::QueueDestroySelf(Router* r) + std::string TransitHop::to_string() const { - r->loop()->call([self = shared_from_this()] { self->SetSelfDestruct(); }); + return "TransitHop:[ tx={}, rx={}, upstream={}, downstream={}, expiry={} ]"_format( + _txid, _rxid, _upstream, _downstream, expiry.count()); } + } // namespace llarp::path diff --git a/llarp/path/transit_hop.hpp b/llarp/path/transit_hop.hpp index c5dd0b69e9..7ce1ce732d 100644 --- a/llarp/path/transit_hop.hpp +++ b/llarp/path/transit_hop.hpp @@ -10,58 +10,53 @@ namespace llarp { struct Router; - /** TODO: combine PathHopConfig into TransitHop - */ - namespace path { struct TransitHop : std::enable_shared_from_this { HopID _txid, _rxid; + RouterID _upstream; + RouterID _rid; RouterID _downstream; TransitHop() = default; - static std::shared_ptr from_hop_config(PathHopConfig hop_config); - - TransitHop(Router& r, const RouterID& src, ustring symmkey, ustring symmnonce); - // This static factory function is used in path-build logic. The exceptions thrown are the exact response // bodies passed to message::respond(...) function static std::shared_ptr deserialize_hop( oxenc::bt_dict_consumer&& btdc, const RouterID& src, Router& r, SharedSecret secret); SharedSecret shared; + SymmNonce nonce; SymmNonce nonceXOR; - std::chrono::milliseconds started{0s}; - // 10 minutes default - std::chrono::milliseconds lifetime{DEFAULT_LIFETIME}; + + std::chrono::milliseconds expiry{0s}; + uint8_t version; std::chrono::milliseconds _last_activity{0s}; bool terminal_hop{false}; - RouterID& upstream() { return _upstream; } + void bt_decode(oxenc::bt_dict_consumer&& btdc); - const RouterID& upstream() const { return _upstream; } + std::string bt_encode() const; + + RouterID router_id() { return _rid; } + const RouterID& router_id() const { return _rid; } - RouterID& downstream() { return _downstream; } + RouterID upstream() { return _upstream; } + const RouterID& upstream() const { return _upstream; } + RouterID downstream() { return _downstream; } const RouterID& downstream() const { return _downstream; } HopID rxid() { return _rxid; } - const HopID& rxid() const { return _rxid; } HopID txid() { return _txid; } - const HopID& txid() const { return _txid; } - void Stop(); - - bool destroy = false; - bool operator<(const TransitHop& other) const { return std::tie(_txid, _rxid, _upstream, _downstream) @@ -76,39 +71,14 @@ namespace llarp bool operator!=(const TransitHop& other) const { return !(*this == other); } - std::chrono::milliseconds expiry_time() const; - std::chrono::milliseconds last_activity() const { return _last_activity; } - std::string to_string() const; - - bool is_expired(std::chrono::milliseconds now) const; - - bool ExpiresSoon(std::chrono::milliseconds now, std::chrono::milliseconds dlt) const - { - return now >= expiry_time() - dlt; - } + bool is_expired(std::chrono::milliseconds now = llarp::time_now_ms()) const { return now >= expiry; }; - void QueueDestroySelf(Router* r); + nlohmann::json ExtractStatus() const; + std::string to_string() const; static constexpr bool to_string_formattable = true; - - private: - void SetSelfDestruct(); }; } // namespace path } // namespace llarp - -namespace std -{ - // template <> - // struct hash - // { - // std::size_t operator()(const llarp::path::TransitHopInfo& a) const - // { - // hash RHash{}; - // hash PHash{}; - // return RHash(a.upstream) ^ RHash(a.downstream) ^ PHash(a.txID) ^ PHash(a.rxID); - // } - // }; -} // namespace std diff --git a/llarp/profiling.cpp b/llarp/profiling.cpp index 85caaf2657..09e7b052d8 100644 --- a/llarp/profiling.cpp +++ b/llarp/profiling.cpp @@ -221,7 +221,7 @@ namespace llarp first = false; else { - auto& profile = _profiles[hop.rc.router_id()]; + auto& profile = _profiles[hop.router_id()]; profile.path_fail += 1; profile.last_update = llarp::time_now_ms(); } @@ -233,7 +233,7 @@ namespace llarp util::Lock lock{_m}; for (const auto& hop : p->hops) { - auto& profile = _profiles[hop.rc.router_id()]; + auto& profile = _profiles[hop.router_id()]; profile.path_timeout += 1; profile.last_update = llarp::time_now_ms(); } @@ -245,7 +245,7 @@ namespace llarp const auto sz = p->hops.size(); for (const auto& hop : p->hops) { - auto& profile = _profiles[hop.rc.router_id()]; + auto& profile = _profiles[hop.router_id()]; // redeem previous fails by halfing the fail count and setting timeout to zero profile.path_fail /= 2; profile.path_timeout = 0; diff --git a/llarp/session/session.cpp b/llarp/session/session.cpp index 03c26e5875..f52842d0b1 100644 --- a/llarp/session/session.cpp +++ b/llarp/session/session.cpp @@ -283,7 +283,7 @@ namespace llarp::session for (size_t i = 0; i < n; ++i) { - count += build_path_aligned_to_remote(_remote); + count += build_path_aligned_to_remote(_remote.router_id()); } if (count == n) @@ -296,7 +296,7 @@ namespace llarp::session { auto path = std::make_shared(_router, hops, get_weak(), true, _remote.is_client()); - log::info(logcat, "Building path -> {} : {}", path->to_string(), path->HopsString()); + log::info(logcat, "Building path -> {} : {}", path->to_string(), path->hop_string()); return path; } From ff8069f6143e0fed9ac0676941947b257242231b Mon Sep 17 00:00:00 2001 From: dr7ana Date: Mon, 4 Nov 2024 13:52:30 -0800 Subject: [PATCH 18/44] path request handling made same as other requests --- llarp/handlers/session.cpp | 35 +++++++------- llarp/link/link_manager.cpp | 92 +++++++++++++++++++++++++------------ llarp/link/link_manager.hpp | 23 ++++++---- llarp/messages/dht.hpp | 28 ++++++++++- llarp/nodedb.cpp | 1 - llarp/path/path.cpp | 79 ++++++++++++++++++++++++------- llarp/path/path.hpp | 35 ++++++++------ llarp/path/path_context.cpp | 7 +-- llarp/path/transit_hop.cpp | 8 ++-- llarp/profiling.cpp | 1 + llarp/profiling.hpp | 7 ++- llarp/router/router.hpp | 4 +- llarp/session/session.cpp | 2 +- 13 files changed, 220 insertions(+), 102 deletions(-) diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index da95fea730..f3c7e984e3 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -415,28 +415,29 @@ namespace llarp::handlers { log::debug(logcat, "Publishing ClientContact to pivot {}", path->pivot_rid()); - ret &= path->publish_client_contact(ecc, [](std::string response) { - log::info(logcat, "Received response to PublishClientContact..."); - - std::optional status = std::nullopt; - try + ret &= path->publish_client_contact2(ecc, [](oxen::quic::message m) { + if (m) { - oxenc::bt_dict_consumer btdc{response}; - - if (auto s = btdc.maybe(messages::STATUS_KEY)) - status = s; + log::critical(logcat, "Call to PublishClientContact succeeded!"); } - catch (const std::exception& e) + else { - log::warning(logcat, "Exception: {}", e.what()); - } + std::optional status = std::nullopt; + try + { + oxenc::bt_dict_consumer btdc{m.body()}; - auto b = status.value_or("") == "SUCCESS"; + if (auto s = btdc.maybe(messages::STATUS_KEY)) + status = s; + } + catch (const std::exception& e) + { + log::warning(logcat, "Exception: {}", e.what()); + } - log::critical( - logcat, - "Call to PublishClientContact {}", - b ? "SUCCEEDED" : "FAILED -- reason: {}"_format(status.value_or(""))); + log::critical( + logcat, "Call to PublishClientContact FAILED; reason: {}", status.value_or("")); + } }); } } diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index ee12b4e2dc..4f49772ed0 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -210,7 +210,7 @@ namespace llarp if (client_only) { - s->register_handler("session_init", [this](oxen::quic::message m) mutable { + s->register_handler("session_init"s, [this](oxen::quic::message m) mutable { _router.loop()->call([&, msg = std::move(m)]() mutable { handle_initiate_session(std::move(msg)); }); }); log::debug(logcat, "Registered all client-only BTStream commands!"); @@ -237,18 +237,23 @@ namespace llarp _router.loop()->call([&, msg = std::move(m)]() mutable { handle_gossip_rc(std::move(msg)); }); }); - for (auto& method : path_requests) - { - s->register_handler( - std::string{method.first}, [this, func = std::move(method.second)](oxen::quic::message m) mutable { - _router.loop()->call([&, msg = std::move(m), func = std::move(func)]() mutable { - auto body = msg.body_str(); - auto respond = [&, m = std::move(msg)](std::string response) mutable { - m.respond(std::move(response), m.is_error()); - }; - std::invoke(func, this, body, std::move(respond)); - }); + s->register_handler("publish_cc"s, [this](oxen::quic::message m) mutable { + _router.loop()->call([&, msg = std::move(m)]() mutable { handle_publish_cc(std::move(msg)); }); + }); + + for (auto& method : inner_requests) + { + s->register_handler(method.first, [this, func = std::move(method.second)](oxen::quic::message m) mutable { + _router.loop()->call([&, msg = std::move(m), func = std::move(func)]() mutable { + auto body = msg.body_str(); + auto respond = [&, m = std::move(msg)](std::string response) mutable { + // We only signal success using `messages::OK_RESPONSE` + auto is_error = response != messages::OK_RESPONSE; + m.respond(std::move(response), is_error); + }; + std::invoke(func, this, std::move(body), std::move(respond)); }); + }); } log::debug(logcat, "Registered all commands for connection to remote RID:{}", remote_rid); @@ -275,7 +280,7 @@ namespace llarp quic{std::make_unique()}, tls_creds{oxen::quic::GNUTLSCreds::make_from_ed_keys( {reinterpret_cast(_router.identity().data()), 32}, - {reinterpret_cast(_router.router_id().data()), 32})}, + {reinterpret_cast(_router.local_rid().data()), 32})}, ep{_router.loop()->template make_shared(startup_endpoint(), *this)}, is_stopping{false} {} @@ -993,7 +998,7 @@ namespace llarp m.respond(std::move(btdp).str()); } - void LinkManager::handle_resolve_ons(std::string_view body, std::function respond) + void LinkManager::handle_resolve_ons_inner(std::string body, std::function respond) { std::string name_hash; @@ -1020,7 +1025,38 @@ namespace llarp }); } - void LinkManager::handle_publish_cc(std::string_view body, std::function respond) + void LinkManager::handle_publish_cc(oxen::quic::message m) + { + log::critical(logcat, "Received request to publish client contact!"); + + EncryptedClientContact enc; + + try + { + enc = PublishClientContact::deserialize(oxenc::bt_dict_consumer{m.body()}); + } + catch (const std::exception& e) + { + log::warning(logcat, "Exception: {}", e.what()); + return m.respond(messages::ERROR_RESPONSE, true); + } + + if (enc.is_expired()) + { + log::warning(logcat, "Received expired EncryptedClientContact!"); + return m.respond(PublishClientContact::EXPIRED, true); + } + + if (not enc.verify()) + { + log::warning(logcat, "Received invalid EncryptedClientContact!"); + return m.respond(PublishClientContact::INVALID, true); + } + + // + } + + void LinkManager::handle_publish_cc_inner(std::string body, std::function respond) { log::critical(logcat, "Received request to publish client contact!"); @@ -1049,7 +1085,7 @@ namespace llarp } auto dht_key = enc.key(); - auto local_rid = _router.router_id(); + auto local_rid = _router.local_rid(); auto closest_rcs = _router.node_db()->find_many_closest_to(dht_key, path::DEFAULT_PATHS_HELD); @@ -1062,9 +1098,7 @@ namespace llarp "Received PublishClientContact (key: {}) for which we are a candidate; accepting...", dht_key); _router.contact_db().put_cc(std::move(enc)); - // return respond(messages::OK_RESPONSE); - // TESTNET: - return respond(PublishClientContact::SUCCESS); + return respond(messages::OK_RESPONSE); } } @@ -1088,7 +1122,7 @@ namespace llarp }); } - void LinkManager::handle_find_cc(std::string_view body, std::function respond) + void LinkManager::handle_find_cc_inner(std::string body, std::function respond) { dht::Key_t dht_key; bool is_relayed; @@ -1104,7 +1138,7 @@ namespace llarp return respond(messages::ERROR_RESPONSE); } - auto local_rid = _router.router_id(); + auto local_rid = _router.local_rid(); auto closest_rcs = _router.node_db()->find_many_closest_to(dht_key, path::DEFAULT_PATHS_HELD); @@ -1280,9 +1314,8 @@ namespace llarp auto hop = _router.path_context()->get_transit_hop(hop_id); - // TODO: use "path_control" for both directions? If not, drop message on - // floor if we don't have the path_id in question; if we decide to make this - // bidirectional, will need to check if we have a Path with path_id. + // TODO: when using path conrol messages for responses, check for the Path + // witht he corresponding ID, de-onion, etc if (not hop) { // if (auto path = _router.path_context()->get_path(hop_id)) @@ -1442,22 +1475,23 @@ namespace llarp } // If a handler exists for "method", call it; else drop request on the floor. - auto itr = path_requests.find(endpoint); + auto itr = inner_requests.find(endpoint); - if (itr == path_requests.end()) + if (itr == inner_requests.end()) { - log::warning(logcat, "Received path control request `{}`, which has no handler.", endpoint); + log::warning(logcat, "Received path control request (`{}`), which has no local handler!", endpoint); return; } - log::debug(logcat, "Received path control request `{}`", endpoint); + log::debug(logcat, "Received path control request: `{}`", endpoint); auto respond = [m = std::move(m), hop_weak = hop->weak_from_this()](std::string response) mutable { auto hop = hop_weak.lock(); if (not hop) return; // transit hop gone, drop response - m.respond(std::move(response)); + auto is_error = response != messages::OK_RESPONSE; + m.respond(std::move(response), is_error); // TODO: onion encrypt path message responses // auto n = SymmNonce::make_random(); diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 2685ebe52f..f52b00ea05 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -253,11 +253,13 @@ namespace llarp private: // DHT messages - void handle_resolve_ons(std::string_view body, std::function respond); // relay + void handle_resolve_ons_inner(std::string body, std::function respond); // relay // TESTNET: // NEW CLIENT_CONTACT HANDLERS - void handle_find_cc(std::string_view body, std::function respond); - void handle_publish_cc(std::string_view body, std::function respond); + void handle_find_cc(oxen::quic::message); + void handle_publish_cc(oxen::quic::message); + void handle_find_cc_inner(std::string body, std::function respond); + void handle_publish_cc_inner(std::string body, std::function respond); // Path messages void handle_path_build(oxen::quic::message, const RouterID& from); // relay @@ -277,16 +279,19 @@ namespace llarp // Misc void handle_convo_intro(oxen::quic::message); + std::unordered_map path_requests = { + {"publish_cc"sv, &LinkManager::handle_publish_cc}}; + // These requests come over a path (as a "path_control" request), // we may or may not need to make a request to another relay, // then respond (onioned) back along the path. std::unordered_map< - std::string_view, - void (LinkManager::*)(std::string_view body, std::function respond)> - path_requests = { - {"resolve_ons"sv, &LinkManager::handle_resolve_ons}, - {"publish_cc"sv, &LinkManager::handle_publish_cc}, - {"find_cc"sv, &LinkManager::handle_find_cc}}; + std::string, + void (LinkManager::*)(std::string body, std::function respond)> + inner_requests = { + {"resolve_ons_inner"s, &LinkManager::handle_resolve_ons_inner}, + {"publish_cc_inner"s, &LinkManager::handle_publish_cc_inner}, + {"find_cc_inner"s, &LinkManager::handle_find_cc_inner}}; // Path relaying void handle_path_control(oxen::quic::message, const RouterID& from); diff --git a/llarp/messages/dht.hpp b/llarp/messages/dht.hpp index b8842fbf2f..b157cc5327 100644 --- a/llarp/messages/dht.hpp +++ b/llarp/messages/dht.hpp @@ -123,15 +123,39 @@ namespace llarp namespace PublishClientContact { - inline const auto SUCCESS = messages::serialize_response({{messages::STATUS_KEY, "SUCCESS"}}); inline const auto INVALID = messages::serialize_response({{messages::STATUS_KEY, "INVALID CC"}}); inline const auto EXPIRED = messages::serialize_response({{messages::STATUS_KEY, "EXPIRED CC"}}); inline const auto INSUFFICIENT = messages::serialize_response({{messages::STATUS_KEY, "INSUFFICIENT NODES"}}); inline const auto INVALID_ORDER = messages::serialize_response({{messages::STATUS_KEY, "INVALID ORDER"}}); + /** Bt-encoded contents: + - 'x' : EncryptedClientContact + + Note: we are bt-encoding to leave space for future fields (ex: version) + */ inline static std::string serialize(const EncryptedClientContact& ecc) { - return oxenc::bt_serialize(ecc.bt_payload()); + oxenc::bt_dict_producer btdp; + + btdp.append("x", ecc.bt_payload()); + + return std::move(btdp).str(); + } + + inline static EncryptedClientContact deserialize(oxenc::bt_dict_consumer&& btdc) + { + EncryptedClientContact ecc; + + try + { + ecc = EncryptedClientContact::deserialize(btdc.require("x")); + } + catch (const std::exception& e) + { + throw std::runtime_error{"Exception caught deserializing EncryptedClientContact: {}"_format(e.what())}; + } + + return ecc; } inline static EncryptedClientContact deserialize(std::string_view buf) diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index be5346f939..663e8c944e 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -1095,7 +1095,6 @@ namespace llarp { return _router.loop()->call_get([this, location, numRouters]() -> dht::rc_set { dht::rc_set ret{known_rcs.begin(), known_rcs.end(), dht::XorMetric{location}}; - ret.erase(std::next(ret.begin(), numRouters), ret.end()); return ret; }); diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index bc7801abde..7bc0411c62 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -15,33 +15,58 @@ namespace llarp::path Path::Path( Router& rtr, - const std::vector& _hops, + const std::vector& hop_rcs, std::weak_ptr _handler, bool is_session, bool is_client) - : handler{std::move(_handler)}, _router{rtr}, _is_session_path{is_session}, _is_client{is_client} + : handler{std::move(_handler)}, + _router{rtr}, + _is_session_path{is_session}, + _is_client{is_client}, + num_hops{hop_rcs.size()} { - populate_internals(_hops); - + populate_internals(hop_rcs); log::info(logcat, "Path successfully constructed: {}", to_string()); } - void Path::populate_internals(const std::vector& _hops) + void Path::populate_internals(const std::vector& hop_rcs) { - size_t n_hops = _hops.size(); - hops.resize(n_hops); + hops.resize(num_hops); - for (size_t i = 0; i < n_hops; ++i) + for (size_t i = 0; i < num_hops; ++i) { - hops[i]._rid = _hops[i].router_id(); + hops[i]._rid = hop_rcs[i].router_id(); hops[i]._txid = HopID::make_random(); - // First hop RXID is unique, the rest are the previous hop TXID - hops[i]._rxid = i ? hops[i - 1]._txid : HopID::make_random(); - // First hop downstream is it's own RID, the rest are the previous hop RID - hops[i]._downstream = i ? hops[i - 1]._rid : hops[i]._rid; - // Last hop upstream is it's own RID, the rest are the next hop RID - hops[i]._upstream = i == n_hops - 1 ? hops[i]._rid : hops[i + 1]._rid; + /** Conditions: + - First hop RXID is unique, the rest are the previous hop TXID + - Last hop upstream is it's own RID, the rest are the next hop RID + - First hop downstream is client's RID, the rest are the previous hop RID + */ + + if (i == 0) + { + hops[i]._rxid = HopID::make_random(); + hops[i]._upstream = hop_rcs[i + 1].router_id(); + hops[i]._downstream = _router.local_rid(); + } + else if (i == num_hops - 1) + { + hops[i]._rxid = hops[i - 1]._txid; + hops[i]._upstream = hops[i]._rid; + hops[i]._downstream = hops[i - 1]._rid; + } + else + { + hops[i]._rxid = hops[i - 1]._txid; + hops[i]._upstream = hop_rcs[i + 1].router_id(); + hops[i]._downstream = hops[i - 1]._rid; + } + + // Conditions written as ternaries + // hops[i]._rxid = i ? hops[i - 1]._txid : HopID::make_random(); + // hops[i]._upstream = i == num_hops - 1 ? hops[i]._rid : hop_rcs[i + 1].router_id(); + // hops[i]._downstream = i ? hops[i - 1]._rid : _router.local_rid(); } hops.back().terminal_hop = true; @@ -130,9 +155,14 @@ namespace llarp::path "find_cc", FindClientContact::serialize(location, order, is_relayed), std::move(func)); } + bool Path::publish_client_contact2(const EncryptedClientContact& ecc, std::function func) + { + return send_path_control_message2("publish_cc", PublishClientContact::serialize(ecc), std::move(func)); + } + bool Path::publish_client_contact(const EncryptedClientContact& ecc, std::function func) { - return send_path_control_message("publish_cc", PublishClientContact::serialize(ecc), std::move(func)); + return send_path_control_message("publish_cc_inner", PublishClientContact::serialize(ecc), std::move(func)); } bool Path::resolve_ons(std::string name, std::function func) @@ -177,6 +207,15 @@ namespace llarp::path return _router.send_data_message(upstream_rid(), std::move(outer_payload)); } + bool Path::send_path_control_message2( + std::string endpoint, std::string body, std::function func) + { + auto inner_payload = PATH::CONTROL::serialize(std::move(endpoint), std::move(body)); + auto outer_payload = make_path_message(std::move(inner_payload)); + + return _router.send_control_message(upstream_rid(), "path_control", std::move(outer_payload), std::move(func)); + } + bool Path::send_path_control_message(std::string endpoint, std::string body, std::function func) { auto inner_payload = PATH::CONTROL::serialize(std::move(endpoint), std::move(body)); @@ -248,6 +287,14 @@ namespace llarp::path return _established ? !is_expired(now) : false; } + std::shared_ptr Path::get_parent() + { + if (auto parent = handler.lock()) + return parent; + + return nullptr; + } + RouterID Path::upstream_rid() { return hops.front().router_id(); diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index dbd4946a13..620eff9179 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -23,6 +23,7 @@ namespace llarp { struct Router; + struct Profiling; namespace service { @@ -40,13 +41,8 @@ namespace llarp /// A path we made struct Path : public std::enable_shared_from_this { - std::vector hops; - - std::weak_ptr handler; - - ClientIntro intro{}; - - std::chrono::milliseconds buildStarted{0s}; + friend struct PathHandler; + friend struct llarp::Profiling; Path( Router& rtr, @@ -55,6 +51,12 @@ namespace llarp bool is_session = false, bool is_client = false); + protected: + std::vector hops; + std::weak_ptr handler; + ClientIntro intro{}; + + public: std::shared_ptr get_self() { return shared_from_this(); } std::weak_ptr get_weak() { return weak_from_this(); } @@ -96,6 +98,9 @@ namespace llarp bool publish_client_contact( const EncryptedClientContact& ecc, std::function func = nullptr); + bool publish_client_contact2( + const EncryptedClientContact& ecc, std::function func); + bool close_exit( const Ed25519SecretKey& sk, std::string tx_id, std::function func = nullptr); @@ -116,10 +121,15 @@ namespace llarp bool send_path_control_message( std::string method, std::string body, std::function func = nullptr); + bool send_path_control_message2( + std::string method, std::string body, std::function func); + bool send_path_data_message(std::string body); bool is_ready(std::chrono::milliseconds now = llarp::time_now_ms()) const; + std::shared_ptr get_parent(); + RouterID upstream_rid(); const RouterID& upstream_rid() const; @@ -171,6 +181,8 @@ namespace llarp bool _is_session_path{false}; bool _is_client{false}; + const size_t num_hops; + recv_session_dgram_cb _recv_dgram; std::chrono::milliseconds last_recv_msg{0s}; @@ -187,13 +199,8 @@ namespace std { size_t operator()(const llarp::path::Path& p) const { - auto& first_hop = p.hops[0]; - llarp::AlignedBuffer b; - std::memcpy(b.data(), first_hop._txid.data(), PATHIDSIZE); - std::memcpy(&b[PATHIDSIZE], first_hop._txid.data(), PATHIDSIZE); - - auto h = hash>{}(b); - return h ^ hash{}(first_hop._upstream); + auto h = hash{}(p.upstream_txid()); + return h ^ hash{}(p.upstream_rid()); } }; } // namespace std diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index 140da8590c..1fc9db813d 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -96,11 +96,8 @@ namespace llarp::path { Lock_t l{paths_mutex}; - if (auto maybe_path = get_path(id); maybe_path) - { - if (auto parent = maybe_path->handler.lock()) - return parent; - } + if (auto maybe_path = get_path(id)) + return maybe_path->get_parent(); return nullptr; } diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index b85f72da6e..8515c20142 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -20,7 +20,7 @@ namespace llarp::path } catch (const std::exception& e) { - log::warning(logcat, "TransitHop caught bt parsing exception:{}", e.what()); + log::warning(logcat, "TransitHop caught bt parsing exception: {}", e.what()); throw std::runtime_error{messages::ERROR_RESPONSE}; } @@ -30,7 +30,7 @@ namespace llarp::path hop->_downstream = src; hop->shared = std::move(secret); - if (hop->_upstream == hop->_downstream) + if (hop->_upstream == r.local_rid()) hop->terminal_hop = true; if (r.path_context()->has_transit_hop(hop)) @@ -78,8 +78,8 @@ namespace llarp::path std::string TransitHop::to_string() const { - return "TransitHop:[ tx={}, rx={}, upstream={}, downstream={}, expiry={} ]"_format( - _txid, _rxid, _upstream, _downstream, expiry.count()); + return "TransitHop:[ terminal={}, tx={}, rx={}, upstream={}, downstream={}, expiry={} ]"_format( + terminal_hop, _txid, _rxid, _upstream, _downstream, expiry.count()); } } // namespace llarp::path diff --git a/llarp/profiling.cpp b/llarp/profiling.cpp index 09e7b052d8..7b287b6536 100644 --- a/llarp/profiling.cpp +++ b/llarp/profiling.cpp @@ -1,5 +1,6 @@ #include "profiling.hpp" +#include "path/path.hpp" #include "util/file.hpp" #include diff --git a/llarp/profiling.hpp b/llarp/profiling.hpp index 3edbaf8d17..41cef4cebe 100644 --- a/llarp/profiling.hpp +++ b/llarp/profiling.hpp @@ -1,7 +1,7 @@ #pragma once +#include "constants/proto.hpp" #include "contact/router_id.hpp" -#include "path/path.hpp" #include "util/thread/threading.hpp" #include @@ -14,6 +14,11 @@ namespace oxenc namespace llarp { + namespace path + { + struct Path; + } + struct RouterProfile { static constexpr size_t MaxSize = 256; diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 468f431e23..0e3dae4d5a 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -239,9 +239,7 @@ namespace llarp const Ed25519SecretKey& identity() const { return _key_manager->identity_key; } - const RouterID& router_id() const { return _key_manager->public_key; } - - const RouterID& local_rid() const { return relay_contact.router_id(); } + const RouterID& local_rid() const { return _key_manager->public_key; } Profiling& router_profiling() { return _router_profiling; } diff --git a/llarp/session/session.cpp b/llarp/session/session.cpp index f52842d0b1..6ed7b45541 100644 --- a/llarp/session/session.cpp +++ b/llarp/session/session.cpp @@ -56,7 +56,7 @@ namespace llarp::session _current_path = std::move(_new_path); - _current_hop_id = _current_path->intro.pivot_rxid; + _current_hop_id = _current_path->pivot_rxid(); if (_use_tun) _current_path->link_session([this](bstring data) { From 39fa3666ed71c453e0fc21540524d4244c585378 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Tue, 5 Nov 2024 08:07:02 -0800 Subject: [PATCH 19/44] Moved remaining path-requests to improved quic handler --- llarp/config/config.cpp | 12 +-- llarp/contact/contactdb.cpp | 5 +- llarp/contact/sns.cpp | 38 +------ llarp/contact/sns.hpp | 32 +++--- llarp/crypto/crypto.cpp | 12 ++- llarp/crypto/crypto.hpp | 6 +- llarp/dht/bucket.hpp | 2 +- llarp/dht/key.hpp | 8 +- llarp/dht/node.hpp | 8 +- llarp/handlers/session.cpp | 92 +++++++++------- llarp/handlers/session.hpp | 8 +- llarp/link/link_manager.cpp | 204 ++++++++++++------------------------ llarp/link/link_manager.hpp | 23 ++-- llarp/messages/dht.hpp | 170 ++++++++++++++++-------------- llarp/nodedb.cpp | 20 +--- llarp/path/path.cpp | 23 ++-- llarp/path/path.hpp | 13 ++- 17 files changed, 291 insertions(+), 385 deletions(-) diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index 631f36b471..5e58fcc4ac 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -265,7 +265,7 @@ namespace llarp const auto addr = arg.substr(0, pos); auto auth = arg.substr(pos + 1); - if (is_valid_ons(addr)) + if (is_valid_sns(addr)) { ons_auth_tokens.emplace(std::move(addr), std::move(auth)); } @@ -332,7 +332,7 @@ namespace llarp if (pos != std::string::npos) arg = arg.substr(0, pos); - if (is_valid_ons(arg)) + if (is_valid_sns(arg)) ons_ranges.emplace(std::move(arg), std::move(*range)); else if (auto maybe_raddr = NetworkAddress::from_network_addr(arg); maybe_raddr) ranges.emplace(std::move(*maybe_raddr), std::move(*range)); @@ -661,7 +661,7 @@ namespace llarp if (pos != std::string::npos) arg = arg.substr(0, pos); - if (is_valid_ons(arg)) + if (is_valid_sns(arg)) _ons_ranges.emplace(std::move(arg), std::move(*range)); else if (auto maybe_raddr = NetworkAddress::from_network_addr(arg); maybe_raddr) _exit_ranges.emplace(std::move(*maybe_raddr), std::move(*range)); @@ -701,7 +701,7 @@ namespace llarp const auto addr = arg.substr(0, pos); auto auth = arg.substr(pos + 1); - if (is_valid_ons(addr)) + if (is_valid_sns(addr)) { ons_exit_auths.emplace(std::move(addr), std::move(auth)); } @@ -825,7 +825,7 @@ namespace llarp auto addr_arg = arg.substr(0, pos); auto ip_arg = arg.substr(pos + 1); - if (is_valid_ons(addr_arg)) + if (is_valid_sns(addr_arg)) throw std::invalid_argument{"`mapaddr` cannot take an ONS entry: {}"_format(arg)}; if (auto maybe_raddr = NetworkAddress::from_network_addr(std::move(addr_arg)); maybe_raddr) @@ -997,7 +997,7 @@ namespace llarp continue; } - if (is_valid_ons(*arg)) + if (is_valid_sns(*arg)) { log::warning(logcat, "{}: {}", addrmap_errorstr, "cannot accept ONS names!"); continue; diff --git a/llarp/contact/contactdb.cpp b/llarp/contact/contactdb.cpp index e1d09a436f..39f8b71aaa 100644 --- a/llarp/contact/contactdb.cpp +++ b/llarp/contact/contactdb.cpp @@ -26,9 +26,8 @@ namespace llarp auto& clientcontacts = _cc_nodes->nodes; - if (auto itr = clientcontacts.find(key); - itr != clientcontacts.end() && not itr->second.client_contact.is_expired()) - enc = itr->second.client_contact; + if (auto itr = clientcontacts.find(key); itr != clientcontacts.end() && not itr->second.ecc.is_expired()) + enc = itr->second.ecc; return enc; } diff --git a/llarp/contact/sns.cpp b/llarp/contact/sns.cpp index b84f0eeaa8..30eb692538 100644 --- a/llarp/contact/sns.cpp +++ b/llarp/contact/sns.cpp @@ -7,36 +7,22 @@ namespace llarp { static auto logcat = llarp::log::Cat("ONSRecord"); - std::optional EncryptedSNSRecord::construct(std::string bt) + EncryptedSNSRecord EncryptedSNSRecord::deserialize(std::string_view bt) { - if (EncryptedSNSRecord ret; ret.bt_decode(std::move(bt))) - return ret; - - return std::nullopt; + return EncryptedSNSRecord{bt}; } - EncryptedSNSRecord::EncryptedSNSRecord(std::string bt) + EncryptedSNSRecord::EncryptedSNSRecord(std::string_view bt) : _bt_payload{bt} { - try - { - // The constructor calls the ::bt_decode() overload that re-throws any exception it hits - oxenc::bt_dict_consumer btdc{bt}; - bt_decode(btdc); - } - catch (const std::exception& e) - { - log::warning(logcat, "EncryptedSNSRecord exception: {}", e.what()); - } + bt_decode(oxenc::bt_dict_consumer{_bt_payload}); } - bool EncryptedSNSRecord::bt_decode(oxenc::bt_dict_consumer& btdc) + void EncryptedSNSRecord::bt_decode(oxenc::bt_dict_consumer&& btdc) { try { ciphertext = btdc.require("c"); nonce.from_string(btdc.require("n")); - - return true; } catch (...) { @@ -45,20 +31,6 @@ namespace llarp } } - bool EncryptedSNSRecord::bt_decode(std::string bt) - { - try - { - oxenc::bt_dict_consumer btdc{bt}; - return bt_decode(btdc); - } - catch (...) - { - log::warning(logcat, "EncryptedSNSRecord exception"); - return false; - } - } - std::string EncryptedSNSRecord::bt_encode() const { oxenc::bt_dict_producer btdp; diff --git a/llarp/contact/sns.hpp b/llarp/contact/sns.hpp index 9ef99cb9df..92fc72c393 100644 --- a/llarp/contact/sns.hpp +++ b/llarp/contact/sns.hpp @@ -9,9 +9,9 @@ namespace llarp { struct NetworkAddress; - /** Holds an entire ONS Record returned from a succfessful request to the `lookup_name` endpoint. - When transmitted over the wire back to the calling instance, it is bt-encoded and the ONS hash - ('ciphertext') is decrypted using the ons_name. + /** Holds an entire SNS Record returned from a succfessful request to the `lookup_name` endpoint. + When transmitted over the wire back to the calling instance, it is bt-encoded and the SNS hash + ('ciphertext') is decrypted using the sns_name. bt-encoded keys: 'c' : ciphertext @@ -20,8 +20,10 @@ namespace llarp struct EncryptedSNSRecord { private: - explicit EncryptedSNSRecord(std::string bt); - bool bt_decode(oxenc::bt_dict_consumer& btdc); + explicit EncryptedSNSRecord(std::string_view bt); + void bt_decode(oxenc::bt_dict_consumer&& btdc); + + std::string _bt_payload; public: SymmNonce nonce; @@ -29,27 +31,27 @@ namespace llarp EncryptedSNSRecord() = default; - static std::optional construct(std::string bt); + std::string_view bt_payload() const { return _bt_payload; } - std::string bt_encode() const; + static EncryptedSNSRecord deserialize(std::string_view bt); - bool bt_decode(std::string bt); + std::string bt_encode() const; - std::optional decrypt(std::string_view ons_name) const; + std::optional decrypt(std::string_view sns_name) const; }; - /// check if an ons name complies with the registration rules - inline bool is_valid_ons(std::string_view ons_name) + /// check if an sns name complies with the registration rules + inline bool is_valid_sns(std::string_view sns_name) { // make sure it ends with .loki because no fucking shit right? - if (not ons_name.ends_with(".loki")) + if (not sns_name.ends_with(".loki")) return false; // strip off .loki suffix - ons_name.remove_suffix(5); + sns_name.remove_suffix(5); // ensure chars are sane - for (const auto ch : ons_name) + for (const auto ch : sns_name) { if (ch == '-') continue; @@ -63,7 +65,7 @@ namespace llarp } // split into domain parts - const auto parts = split(ons_name, "."); + const auto parts = split(sns_name, "."); // get root domain const auto primaryName = parts[parts.size() - 1]; diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index da583b2d1d..532666a159 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -330,11 +330,15 @@ namespace llarp && -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) + uint8_t* derived, size_t derived_len, const PubKey& root_pubkey, uint64_t key_n, const AlignedBuffer<32>* hash) { + if (derived_len != PubKey::SIZE) + { + log::error(logcat, "Derived pubkey must be {}!", PubKey::SIZE); + return false; + } + // scalar h = H( BLIND-STRING || root_pubkey || key_n ) AlignedBuffer<32> h; if (hash) @@ -345,7 +349,7 @@ namespace llarp return false; } - return 0 == crypto_scalarmult_ed25519(out_pubkey.data(), h.data(), root_pubkey.data()); + return 0 == crypto_scalarmult_ed25519(derived, h.data(), root_pubkey.data()); } bool crypto::derive_subkey_private( diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index e0faaf3776..e614d25d9d 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -84,7 +84,11 @@ namespace llarp /// 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); + uint8_t* derived, + size_t derived_len, + 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. diff --git a/llarp/dht/bucket.hpp b/llarp/dht/bucket.hpp index 8663fb7527..55fed34894 100644 --- a/llarp/dht/bucket.hpp +++ b/llarp/dht/bucket.hpp @@ -17,7 +17,7 @@ namespace llarp::dht { const Key_t us; - XorMetric(const Key_t& ourKey) : us(ourKey) {} + XorMetric(Key_t ourKey) : us{std::move(ourKey)} {} bool operator()(const Key_t& left, const Key_t& right) const { return (us ^ left) < (us ^ right); } diff --git a/llarp/dht/key.hpp b/llarp/dht/key.hpp index a682a93d41..ec7056df5e 100644 --- a/llarp/dht/key.hpp +++ b/llarp/dht/key.hpp @@ -25,11 +25,11 @@ namespace llarp::dht std::string to_string() const { return oxenc::to_base32z(begin(), end()); } - static Key_t derive_from_rid(RouterID rid) + static Key_t derive_from_rid(PubKey root) { - PubKey pk; - crypto::derive_subkey(pk, PubKey{rid.data()}, 1); - return Key_t{pk.as_array()}; + Key_t derived; + crypto::derive_subkey(derived.data(), derived.size(), root, 1); + return derived; } Key_t operator^(const Key_t& other) const diff --git a/llarp/dht/node.hpp b/llarp/dht/node.hpp index 4c9804c8b0..441b50385a 100644 --- a/llarp/dht/node.hpp +++ b/llarp/dht/node.hpp @@ -25,15 +25,15 @@ namespace llarp::dht struct CCNode { - EncryptedClientContact client_contact; + EncryptedClientContact ecc; Key_t ID; CCNode() { ID.zero(); } - CCNode(EncryptedClientContact other) : client_contact{std::move(other)}, ID{client_contact.blinded_pubkey} {} + CCNode(EncryptedClientContact other) : ecc{std::move(other)}, ID{ecc.blinded_pubkey} {} - nlohmann::json ExtractStatus() const { return nlohmann::json{{"key", client_contact.key().to_string()}}; } + nlohmann::json ExtractStatus() const { return nlohmann::json{{"key", ecc.key().to_string()}}; } - bool operator<(const CCNode& other) const { return client_contact.signed_at < other.client_contact.signed_at; } + bool operator<(const CCNode& other) const { return ecc.signed_at < other.ecc.signed_at; } }; } // namespace llarp::dht diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index f3c7e984e3..28cbd9d06f 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -1,6 +1,7 @@ #include "session.hpp" #include +#include #include #include #include @@ -161,7 +162,7 @@ namespace llarp::handlers if (auto n_ons_ranges = ons_ranges.size(); n_ons_ranges > 0) { - log::info(logcat, "SessionEndpoint resolving {} ONS addresses mapped to IP ranges", n_ons_ranges); + log::info(logcat, "SessionEndpoint resolving {} SNS addresses mapped to IP ranges", n_ons_ranges); for (auto itr = ons_ranges.begin(); itr != ons_ranges.end();) { @@ -172,7 +173,7 @@ namespace llarp::handlers { log::debug( logcat, - "Successfully resolved ONS lookup for {} mapped to IPRange:{}", + "Successfully resolved SNS lookup for {} mapped to IPRange:{}", *maybe_addr, ip_range); _range_map.insert_or_assign(std::move(ip_range), std::move(*maybe_addr)); @@ -199,7 +200,7 @@ namespace llarp::handlers { log::debug( logcat, - "Successfully resolved ONS lookup for {} mapped to static auth token", + "Successfully resolved SNS lookup for {} mapped to static auth token", *maybe_addr); _auth_tokens.emplace(std::move(*maybe_addr), std::move(auth_token)); } @@ -211,37 +212,43 @@ namespace llarp::handlers } } - void SessionEndpoint::resolve_ons(std::string ons, std::function)> func) + void SessionEndpoint::resolve_ons(std::string sns, std::function)> func) { - if (not is_valid_ons(ons)) + if (not is_valid_sns(sns)) { - log::debug(logcat, "Invalid ONS name ({}) queried for lookup", ons); + log::debug(logcat, "Invalid SNS name ({}) queried for lookup", sns); return func(std::nullopt); } - log::debug(logcat, "Looking up ONS name {}", ons); + log::debug(logcat, "Looking up SNS name {}", sns); - auto response_handler = [ons_name = ons, hook = std::move(func)](std::string response) { - if (auto record = EncryptedSNSRecord::construct(response); auto client_addr = record->decrypt(ons_name)) + auto response_handler = [sns_name = sns, hook = std::move(func)](oxen::quic::message m) mutable { + try { - return hook(std::move(client_addr)); - } + if (m) + { + log::critical(logcat, "Call to ResolveSNS succeeded!"); - std::optional status = std::nullopt; + auto enc = ResolveSNS::deserialize_response(oxenc::bt_dict_consumer{m.body()}); - try - { - oxenc::bt_dict_consumer btdc{response}; + if (auto client_addr = enc.decrypt(sns_name)) + { + log::info( + logcat, + "Successfully decrypted SNS record (name: {}, address: {})", + sns_name, + client_addr->to_string()); + return hook(std::move(client_addr)); + } - if (auto s = btdc.maybe(messages::STATUS_KEY)) - status = s; + log::warning(logcat, "Failed to decrypt SNS record (name: {})", sns_name); + } } catch (const std::exception& e) { - log::warning(logcat, "Exception caught parsing 'find_name' response: {}", e.what()); + log::warning(logcat, "Exception: {}", e.what()); } - log::warning(logcat, "Call to endpoint 'lookup_name' failed -- status:{}", status.value_or("")); hook(std::nullopt); }; @@ -250,15 +257,14 @@ namespace llarp::handlers for (const auto& [_, path] : _paths) { - log::info(logcat, "Querying pivot:{} for name lookup (target: {})", path->pivot_rid(), ons); + log::info(logcat, "Querying pivot:{} for name lookup (target: {})", path->pivot_rid(), sns); - path->resolve_ons(ons, response_handler); + path->resolve_sns(sns, response_handler); } } } - void SessionEndpoint::lookup_client_intro( - RouterID remote, bool is_relayed, uint64_t order, std::function)> func) + void SessionEndpoint::lookup_client_intro(RouterID remote, std::function)> func) { auto remote_key = dht::Key_t::derive_from_rid(remote); @@ -270,26 +276,39 @@ namespace llarp::handlers log::debug(logcat, "Looking up clientcontact for remote (rid:{})", remote); - auto response_handler = [this, remote, hook = std::move(func)](std::string response) mutable { + auto response_handler = [this, remote, hook = std::move(func)](oxen::quic::message m) mutable { try { - auto enc = EncryptedClientContact::deserialize(response); - - if (auto intro = enc.decrypt(remote)) + if (m) { - log::info(logcat, "Storing ClientContact for remote rid:{}", remote); - _router.contact_db().put_cc(std::move(enc)); - return hook(std::move(intro)); + log::critical(logcat, "Call to FindClientContact succeeded!"); + + auto enc = FindClientContact::deserialize_response(oxenc::bt_dict_consumer{m.body()}); + + if (auto intro = enc.decrypt(remote)) + { + log::info(logcat, "Storing ClientContact for remote rid:{}", remote); + _router.contact_db().put_cc(std::move(enc)); + return hook(std::move(intro)); + } + + log::warning(logcat, "Failed to decrypt returned EncryptedClientContact!"); } + else + { + std::optional status = std::nullopt; + oxenc::bt_dict_consumer btdc{m.body()}; - oxenc::bt_dict_consumer btdc{response}; - auto s = btdc.maybe(messages::STATUS_KEY); + if (auto s = btdc.maybe(messages::STATUS_KEY)) + status = s; - log::warning(logcat, "Call to `find_cc` failed -- status: {}", s.value_or("< NONE GIVEN >")); + log::warning( + logcat, "Call to FindClientContact FAILED; reason: {}", status.value_or("")); + } } catch (const std::exception& e) { - log::warning(logcat, "Exception caught parsing FindClientContact response: {}", e.what()); + log::warning(logcat, "Exception: {}", e.what()); } hook(std::nullopt); @@ -306,7 +325,7 @@ namespace llarp::handlers path->pivot_rid(), remote); - path->find_client_contact(remote_key, is_relayed, order, response_handler); + path->find_client_contact(remote_key, response_handler); } } } @@ -460,6 +479,7 @@ namespace llarp::handlers { auto tag = service::SessionTag::make_random(); + // TESTNET: TODO: make this take a quic message type path->send_path_control_message( "session_init", InitiateSession::serialize_encrypt( @@ -595,8 +615,6 @@ namespace llarp::handlers _router.loop()->call([this, remote, handler = std::move(cb), is_exit, counter]() mutable { lookup_client_intro( remote.router_id(), - false, - 0, [this, remote, hook = std::move(handler), is_exit, counter](std::optional cc) { if (*counter == 0) return; diff --git a/llarp/handlers/session.hpp b/llarp/handlers/session.hpp index 4b3dbeaadc..15258d073f 100644 --- a/llarp/handlers/session.hpp +++ b/llarp/handlers/session.hpp @@ -124,17 +124,13 @@ namespace llarp bool prefigure_session( NetworkAddress initiator, service::SessionTag tag, std::shared_ptr path, bool use_tun); - // lookup ONS address to return "{pubkey}.loki" hidden service or exit node operated on a remote client + // lookup SNS address to return "{pubkey}.loki" hidden service or exit node operated on a remote client void resolve_ons(std::string name, std::function)> func = nullptr); void lookup_remote_srv( std::string name, std::string service, std::function)> handler); - void lookup_client_intro( - RouterID remote, - bool is_relayed, - uint64_t order, - std::function)> func); + void lookup_client_intro(RouterID remote, std::function)> func); // resolves any config mappings that parsed ONS addresses to their pubkey network address void resolve_ons_mappings(); diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 4f49772ed0..8e12ba3f60 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -241,20 +241,13 @@ namespace llarp _router.loop()->call([&, msg = std::move(m)]() mutable { handle_publish_cc(std::move(msg)); }); }); - for (auto& method : inner_requests) - { - s->register_handler(method.first, [this, func = std::move(method.second)](oxen::quic::message m) mutable { - _router.loop()->call([&, msg = std::move(m), func = std::move(func)]() mutable { - auto body = msg.body_str(); - auto respond = [&, m = std::move(msg)](std::string response) mutable { - // We only signal success using `messages::OK_RESPONSE` - auto is_error = response != messages::OK_RESPONSE; - m.respond(std::move(response), is_error); - }; - std::invoke(func, this, std::move(body), std::move(respond)); - }); - }); - } + s->register_handler("find_cc"s, [this](oxen::quic::message m) mutable { + _router.loop()->call([&, msg = std::move(m)]() mutable { handle_find_cc(std::move(msg)); }); + }); + + s->register_handler("resolve_sns"s, [this](oxen::quic::message m) mutable { + _router.loop()->call([&, msg = std::move(m)]() mutable { handle_resolve_sns(std::move(msg)); }); + }); log::debug(logcat, "Registered all commands for connection to remote RID:{}", remote_rid); } @@ -998,30 +991,32 @@ namespace llarp m.respond(std::move(btdp).str()); } - void LinkManager::handle_resolve_ons_inner(std::string body, std::function respond) + void LinkManager::handle_resolve_sns(oxen::quic::message m) { std::string name_hash; try { - oxenc::bt_dict_consumer btdp{body}; - - name_hash = btdp.require("H"); + name_hash = ResolveSNS::deserialize(oxenc::bt_dict_consumer{m.body()}); } catch (const std::exception& e) { log::warning(logcat, "Exception: {}", e.what()); - respond(messages::ERROR_RESPONSE); - return; + return m.respond(messages::ERROR_RESPONSE, true); } _router.rpc_client()->lookup_ons_hash( - name_hash, - [respond = std::move(respond)]([[maybe_unused]] std::optional maybe_enc) mutable { + name_hash, [prev_msg = std::move(m)](std::optional maybe_enc) mutable { if (maybe_enc) - respond(maybe_enc->bt_encode()); + { + log::info(logcat, "RPC lookup successfully returned encrypted SNS record!"); + prev_msg.respond(ResolveSNS::serialize_response(*maybe_enc)); + } else - respond(serialize_response({{messages::STATUS_KEY, FindNameMessage::NOT_FOUND}})); + { + log::warning(logcat, "RPC lookup could not find SNS registry!"); + prev_msg.respond(ResolveSNS::NOT_FOUND, true); + } }); } @@ -1053,37 +1048,6 @@ namespace llarp return m.respond(PublishClientContact::INVALID, true); } - // - } - - void LinkManager::handle_publish_cc_inner(std::string body, std::function respond) - { - log::critical(logcat, "Received request to publish client contact!"); - - EncryptedClientContact enc; - - try - { - enc = PublishClientContact::deserialize(body); - } - catch (const std::exception& e) - { - log::warning(logcat, "Exception: {}", e.what()); - return respond(messages::ERROR_RESPONSE); - } - - if (enc.is_expired()) - { - log::warning(logcat, "Received expired EncryptedClientContact!"); - return respond(PublishClientContact::EXPIRED); - } - - if (not enc.verify()) - { - log::warning(logcat, "Received invalid EncryptedClientContact!"); - return respond(PublishClientContact::INVALID); - } - auto dht_key = enc.key(); auto local_rid = _router.local_rid(); @@ -1098,7 +1062,7 @@ namespace llarp "Received PublishClientContact (key: {}) for which we are a candidate; accepting...", dht_key); _router.contact_db().put_cc(std::move(enc)); - return respond(messages::OK_RESPONSE); + return m.respond(messages::OK_RESPONSE); } } @@ -1110,82 +1074,63 @@ namespace llarp peer_key, "publish_cc", PublishClientContact::serialize(std::move(enc)), - [respond = std::move(respond)](oxen::quic::message m) mutable { - if (m) - log::info(logcat, "Relayed PublishClientContact returned successful! Relaying response..."); - else if (m.timed_out) - log::info(logcat, "Relayed PublishClientContact timed out! Relaying response..."); - else - log::info(logcat, "Relayed PublishClientContact failed! Relaying response..."); - - respond(m.body_str()); + [prev_msg = std::move(m)](oxen::quic::message msg) mutable { + log::info( + logcat, + "Relayed PublishClientContact {}! Relaying response...", + msg ? "succeeded" + : msg.timed_out ? "timed out" + : "failed"); + prev_msg.respond(msg.body_str(), msg.is_error()); }); } - void LinkManager::handle_find_cc_inner(std::string body, std::function respond) + void LinkManager::handle_find_cc(oxen::quic::message m) { dht::Key_t dht_key; - bool is_relayed; - uint64_t relay_order; try { - std::tie(dht_key, relay_order, is_relayed) = FindClientContact::deserialize(body); + dht_key = FindClientContact::deserialize(oxenc::bt_dict_consumer{m.body()}); } catch (const std::exception& e) { log::warning(logcat, "Exception: {}", e.what()); - return respond(messages::ERROR_RESPONSE); + return m.respond(messages::ERROR_RESPONSE, true); } - auto local_rid = _router.local_rid(); - - auto closest_rcs = _router.node_db()->find_many_closest_to(dht_key, path::DEFAULT_PATHS_HELD); - - if (closest_rcs.size() != path::DEFAULT_PATHS_HELD) + if (auto maybe_cc = _router.contact_db().get_encrypted_cc(dht_key)) { - log::warning(logcat, "Received FindClientContact message but only know {} nodes?", closest_rcs.size()); - return respond(FindClientContact::INSUFFICIENT); + log::info(logcat, "Received FindClientContact request; returning local EncryptedClientContact..."); + return m.respond(FindClientContact::serialize_response(*maybe_cc)); } - if (is_relayed) - { - if (relay_order >= path::DEFAULT_PATHS_HELD) - { - log::error(logcat, "Received FindClientContact with invalid relay order: {}", relay_order); - return respond(FindClientContact::INVALID_ORDER); - } - - log::debug(logcat, "Relaying FindClientContactMessage for {}", dht_key); - - const auto& peer_key = closest_rcs.begin()->router_id(); - - send_control_message( - peer_key, - "find_cc", - FindClientContact::serialize(dht_key, relay_order, is_relayed), - [respond = std::move(respond)](oxen::quic::message m) mutable { - if (m) - log::info(logcat, "Relayed FindClientContact returned successful! Relaying response..."); - else if (m.timed_out) - log::info(logcat, "Relayed FindClientContact timed out! Relaying response..."); - else - log::info(logcat, "Relayed FindClientContact failed! Relaying response..."); + auto closest_peer = _router.node_db()->find_closest_to(dht_key).router_id(); - respond(m.body_str()); - }); - } - else + if (closest_peer == _router.local_rid()) { - if (auto maybe_cc = _router.contact_db().get_encrypted_cc(dht_key)) - { - log::info(logcat, "Received non-relayed FindClientContact; returning local EncryptedClientContact..."); - return respond(FindClientContact::serialize_response(maybe_cc->bt_payload())); - } - - log::warning(logcat, "Received non-relayed FindClientContact; no local EncryptedClientContact found..."); - return respond(FindClientContact::NOT_FOUND); + log::warning( + logcat, + "We are closest peer for FindClientContact request (key: {}); no EncryptedClientContact found locally!", + dht_key); + return m.respond(FindClientContact::NOT_FOUND, true); } + + log::debug(logcat, "Relaying FindClientContactMessage for {}", dht_key); + + send_control_message( + closest_peer, + "find_cc"s, + FindClientContact::serialize(dht_key), + [prev_msg = std::move(m)](oxen::quic::message msg) mutable { + log::info( + logcat, + "Relayed FindClientContactMessage {}! Relaying response...", + msg ? "succeeded" + : msg.timed_out ? "timed out" + : "failed"); + prev_msg.respond(msg.body_str(), msg.is_error()); + }); } void LinkManager::handle_path_build(oxen::quic::message m, const RouterID& from) @@ -1315,7 +1260,7 @@ namespace llarp auto hop = _router.path_context()->get_transit_hop(hop_id); // TODO: when using path conrol messages for responses, check for the Path - // witht he corresponding ID, de-onion, etc + // with the corresponding ID, de-onion, etc if (not hop) { // if (auto path = _router.path_context()->get_path(hop_id)) @@ -1337,7 +1282,7 @@ namespace llarp if (hop->terminal_hop) { log::debug(logcat, "We are terminal hop for path request: {}", hop->to_string()); - return handle_inner_request(std::move(m), std::move(payload), std::move(hop)); + return handle_path_request(std::move(m), std::move(payload)); } log::debug(logcat, "We are intermediate hop for path request: {}", hop->to_string()); @@ -1459,8 +1404,7 @@ namespace llarp } } - void LinkManager::handle_inner_request( - oxen::quic::message m, std::string payload, std::shared_ptr hop) + void LinkManager::handle_path_request(oxen::quic::message m, std::string payload) { std::string endpoint, body; @@ -1474,31 +1418,13 @@ namespace llarp return m.respond(messages::serialize_response({{messages::STATUS_KEY, e.what()}}), true); } - // If a handler exists for "method", call it; else drop request on the floor. - auto itr = inner_requests.find(endpoint); - - if (itr == inner_requests.end()) + if (auto it = path_requests.find(endpoint); it != path_requests.end()) { - log::warning(logcat, "Received path control request (`{}`), which has no local handler!", endpoint); - return; + log::debug(logcat, "Received path control request (`{}`); invoking endpoint...", endpoint); + std::invoke(it->second, this, std::move(m)); } - - log::debug(logcat, "Received path control request: `{}`", endpoint); - - auto respond = [m = std::move(m), hop_weak = hop->weak_from_this()](std::string response) mutable { - auto hop = hop_weak.lock(); - if (not hop) - return; // transit hop gone, drop response - - auto is_error = response != messages::OK_RESPONSE; - m.respond(std::move(response), is_error); - - // TODO: onion encrypt path message responses - // auto n = SymmNonce::make_random(); - // m.respond(ONION::serialize_hop(hop->rxid().to_view(), n, response), false); - }; - - std::invoke(itr->second, this, std::move(body), std::move(respond)); + else + log::warning(logcat, "Received path control request (`{}`), which has no local handler!", endpoint); } void LinkManager::handle_initiate_session(oxen::quic::message m) diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index f52b00ea05..b0b7dd6be2 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -253,13 +253,10 @@ namespace llarp private: // DHT messages - void handle_resolve_ons_inner(std::string body, std::function respond); // relay - // TESTNET: // NEW CLIENT_CONTACT HANDLERS - void handle_find_cc(oxen::quic::message); void handle_publish_cc(oxen::quic::message); - void handle_find_cc_inner(std::string body, std::function respond); - void handle_publish_cc_inner(std::string body, std::function respond); + void handle_find_cc(oxen::quic::message); + void handle_resolve_sns(oxen::quic::message); // Path messages void handle_path_build(oxen::quic::message, const RouterID& from); // relay @@ -279,24 +276,18 @@ namespace llarp // Misc void handle_convo_intro(oxen::quic::message); - std::unordered_map path_requests = { - {"publish_cc"sv, &LinkManager::handle_publish_cc}}; - // These requests come over a path (as a "path_control" request), // we may or may not need to make a request to another relay, // then respond (onioned) back along the path. - std::unordered_map< - std::string, - void (LinkManager::*)(std::string body, std::function respond)> - inner_requests = { - {"resolve_ons_inner"s, &LinkManager::handle_resolve_ons_inner}, - {"publish_cc_inner"s, &LinkManager::handle_publish_cc_inner}, - {"find_cc_inner"s, &LinkManager::handle_find_cc_inner}}; + std::unordered_map path_requests = { + {"publish_cc"sv, &LinkManager::handle_publish_cc}, + {"find_cc"sv, &LinkManager::handle_find_cc}, + {"resolve_sns"sv, &LinkManager::handle_resolve_sns}}; // Path relaying void handle_path_control(oxen::quic::message, const RouterID& from); - void handle_inner_request(oxen::quic::message m, std::string payload, std::shared_ptr hop); + void handle_path_request(oxen::quic::message m, std::string payload); // Path responses void handle_path_latency_response(oxen::quic::message); diff --git a/llarp/messages/dht.hpp b/llarp/messages/dht.hpp index b157cc5327..9807605e7d 100644 --- a/llarp/messages/dht.hpp +++ b/llarp/messages/dht.hpp @@ -3,164 +3,178 @@ #include "common.hpp" #include +#include namespace llarp { - namespace FindIntroMessage + + namespace PublishClientContact { - inline constexpr auto NOT_FOUND = "NOT FOUND"sv; - inline constexpr auto INVALID_ORDER = "INVALID ORDER"sv; - inline constexpr auto INSUFFICIENT_NODES = "INSUFFICIENT NODES"sv; + inline const auto INVALID = messages::serialize_response({{messages::STATUS_KEY, "INVALID CC"}}); + inline const auto EXPIRED = messages::serialize_response({{messages::STATUS_KEY, "EXPIRED CC"}}); + inline const auto INSUFFICIENT = messages::serialize_response({{messages::STATUS_KEY, "INSUFFICIENT NODES"}}); + inline const auto INVALID_ORDER = messages::serialize_response({{messages::STATUS_KEY, "INVALID ORDER"}}); - inline static std::string serialize(const dht::Key_t& location, bool is_relayed, uint64_t order) + /** Bt-encoded contents: + - 'x' : EncryptedClientContact + + Note: we are bt-encoding to leave space for future fields (ex: version) + */ + inline static std::string serialize(const EncryptedClientContact& ecc) { oxenc::bt_dict_producer btdp; + btdp.append("x", ecc.bt_payload()); + + return std::move(btdp).str(); + } + + inline static EncryptedClientContact deserialize(oxenc::bt_dict_consumer&& btdc) + { + EncryptedClientContact ecc; + try { - btdp.append("O", order); - btdp.append("R", is_relayed ? 1 : 0); - btdp.append("S", location.to_view()); + ecc = EncryptedClientContact::deserialize(btdc.require("x")); } - catch (...) + catch (const std::exception& e) { - log::error(messages::logcat, "Error: FindIntroMessage failed to bt encode contents!"); + throw std::runtime_error{"Exception caught deserializing EncryptedClientContact: {}"_format(e.what())}; } - return std::move(btdp).str(); + return ecc; } - } // namespace FindIntroMessage + } // namespace PublishClientContact - namespace FindNameMessage + namespace FindClientContact { - inline constexpr auto NOT_FOUND = "NOT FOUND"sv; + inline const auto NOT_FOUND = messages::serialize_response({{messages::STATUS_KEY, "NOT FOUND"}}); + inline const auto INSUFFICIENT = messages::serialize_response({{messages::STATUS_KEY, "INSUFFICIENT NODES"}}); + inline const auto INVALID_ORDER = messages::serialize_response({{messages::STATUS_KEY, "INVALID ORDER"}}); + + /** Bt-encoded contents: + - 'k' : DHT key corresponding to client contact - inline static std::string serialize(std::string name_hash) + Note: we are bt-encoding to leave space for future fields (ex: version) + */ + inline static std::string serialize(const dht::Key_t& location) { oxenc::bt_dict_producer btdp; - try - { - btdp.append("H", std::move(name_hash)); - } - catch (...) - { - log::error(messages::logcat, "Error: FindNameMessage failed to bt encode contents!"); - } + btdp.append("k", location.to_view()); return std::move(btdp).str(); } - inline static std::string serialize_response(std::string encrypted_name) + inline static dht::Key_t deserialize(oxenc::bt_dict_consumer&& btdc) { - oxenc::bt_dict_producer btdp; + dht::Key_t key; try { - btdp.append("E", std::move(encrypted_name)); + key.from_string(btdc.require("k")); } - catch (...) + catch (const std::exception& e) { - log::error(messages::logcat, "Error: FindNameMessage failed to bt encode contents!"); + log::error(messages::logcat, "Error: failed to deserialize FindClientContact contents: {}", e.what()); + throw; } - return std::move(btdp).str(); + return key; } - } // namespace FindNameMessage - namespace FindClientContact - { - inline const auto NOT_FOUND = messages::serialize_response({{messages::STATUS_KEY, "NOT FOUND"}}); - inline const auto INSUFFICIENT = messages::serialize_response({{messages::STATUS_KEY, "INSUFFICIENT NODES"}}); - inline const auto INVALID_ORDER = messages::serialize_response({{messages::STATUS_KEY, "INVALID ORDER"}}); + /** Bt-encoded contents: + - 'x' : EncryptedClientContact - inline static std::string serialize(const dht::Key_t& location, uint64_t relay_order, bool is_relayed) + Note: we are bt-encoding to leave space for future fields (ex: version) + */ + inline static std::string serialize_response(const EncryptedClientContact& ecc) { oxenc::bt_dict_producer btdp; + btdp.append("x", ecc.bt_payload()); + + return std::move(btdp).str(); + } + + inline static EncryptedClientContact deserialize_response(oxenc::bt_dict_consumer&& btdc) + { + EncryptedClientContact ecc; + try { - btdp.append("k", location.to_view()); - btdp.append("o", relay_order); - btdp.append("r", is_relayed); + ecc = EncryptedClientContact::deserialize(btdc.require("x")); } - catch (...) + catch (const std::exception& e) { - log::error(messages::logcat, "Error: failed to serialize PublishClientContact contents!"); + throw std::runtime_error{"Exception caught deserializing EncryptedClientContact: {}"_format(e.what())}; } - return std::move(btdp).str(); + return ecc; } + } // namespace FindClientContact + + namespace ResolveSNS + { + inline const auto NOT_FOUND = messages::serialize_response({{messages::STATUS_KEY, "NOT FOUND"}}); - inline static std::string serialize_response(std::string_view encrypted_payload) + /** Bt-encoded contents: + - 's' : SNS name + + Note: we are bt-encoding to leave space for future fields (ex: version) + */ + inline static std::string serialize(std::string_view name_hash) { - return messages::serialize_response({{"ECC", encrypted_payload}}); + oxenc::bt_dict_producer btdp; + + btdp.append("s", name_hash); + + return std::move(btdp).str(); } - inline static std::tuple deserialize(std::string_view buf) + inline static std::string deserialize(oxenc::bt_dict_consumer&& btdc) { - dht::Key_t key; - bool is_relayed; - uint64_t relay_order; - try { - oxenc::bt_dict_consumer btdc{buf}; - key.from_string(btdc.require("k")); - is_relayed = btdc.require("o"); - relay_order = btdc.require("r"); + return btdc.require("s"); } catch (const std::exception& e) { - log::error( - messages::logcat, "Error: failed to deserialize PublishClientContact contents: {}", e.what()); + log::error(messages::logcat, "Error: failed to deserialize ResolveSNS contents: {}", e.what()); throw; } - - return {key, relay_order, is_relayed}; } - } // namespace FindClientContact - - namespace PublishClientContact - { - inline const auto INVALID = messages::serialize_response({{messages::STATUS_KEY, "INVALID CC"}}); - inline const auto EXPIRED = messages::serialize_response({{messages::STATUS_KEY, "EXPIRED CC"}}); - inline const auto INSUFFICIENT = messages::serialize_response({{messages::STATUS_KEY, "INSUFFICIENT NODES"}}); - inline const auto INVALID_ORDER = messages::serialize_response({{messages::STATUS_KEY, "INVALID ORDER"}}); /** Bt-encoded contents: - - 'x' : EncryptedClientContact + - 'x' : EncryptedSNSRecord Note: we are bt-encoding to leave space for future fields (ex: version) */ - inline static std::string serialize(const EncryptedClientContact& ecc) + inline static std::string serialize_response(const EncryptedSNSRecord& enc) { oxenc::bt_dict_producer btdp; - btdp.append("x", ecc.bt_payload()); + btdp.append("x", enc.bt_payload()); return std::move(btdp).str(); } - inline static EncryptedClientContact deserialize(oxenc::bt_dict_consumer&& btdc) + inline static EncryptedSNSRecord deserialize_response(oxenc::bt_dict_consumer&& btdc) { - EncryptedClientContact ecc; + EncryptedSNSRecord enc{}; try { - ecc = EncryptedClientContact::deserialize(btdc.require("x")); + enc = EncryptedSNSRecord::deserialize(btdc.require("x")); } catch (const std::exception& e) { - throw std::runtime_error{"Exception caught deserializing EncryptedClientContact: {}"_format(e.what())}; + log::error(messages::logcat, "Error: failed to deserialize ResolveSNS contents: {}", e.what()); + throw; } - return ecc; + return enc; } + } // namespace ResolveSNS - inline static EncryptedClientContact deserialize(std::string_view buf) - { - return EncryptedClientContact::deserialize(oxenc::bt_deserialize(buf)); - } - } // namespace PublishClientContact } // namespace llarp diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index 663e8c944e..467e35e239 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -1074,27 +1074,15 @@ namespace llarp RemoteRC NodeDB::find_closest_to(llarp::dht::Key_t location) const { - return _router.loop()->call_get([this, location]() -> RemoteRC { - RemoteRC rc{}; - const llarp::dht::XorMetric compare(location); - - visit_all([&rc, compare](const auto& otherRC) { - const auto& rid = rc.router_id(); - - if (rid.is_zero() || compare(dht::Key_t{otherRC.router_id()}, dht::Key_t{rid})) - { - rc = otherRC; - return; - } - }); - return rc; + return _router.loop()->call_get([this, compare = dht::XorMetric{location}]() -> RemoteRC { + return *std::ranges::min_element(known_rcs, compare); }); } dht::rc_set NodeDB::find_many_closest_to(llarp::dht::Key_t location, uint32_t numRouters) const { - return _router.loop()->call_get([this, location, numRouters]() -> dht::rc_set { - dht::rc_set ret{known_rcs.begin(), known_rcs.end(), dht::XorMetric{location}}; + return _router.loop()->call_get([this, compare = dht::XorMetric{location}, numRouters]() -> dht::rc_set { + dht::rc_set ret{known_rcs.begin(), known_rcs.end(), compare}; ret.erase(std::next(ret.begin(), numRouters), ret.end()); return ret; }); diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 7bc0411c62..4592328031 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -136,23 +136,21 @@ namespace llarp::path } bool Path::obtain_exit( - const Ed25519SecretKey& sk, uint64_t flag, std::string tx_id, std::function func) + const Ed25519SecretKey& sk, uint64_t flag, std::string tx_id, std::function func) { - return send_path_control_message( + return send_path_control_message2( "obtain_exit", ObtainExitMessage::sign_and_serialize(sk, flag, std::move(tx_id)), std::move(func)); } - bool Path::close_exit(const Ed25519SecretKey& sk, std::string tx_id, std::function func) + bool Path::close_exit(const Ed25519SecretKey& sk, std::string tx_id, std::function func) { - return send_path_control_message( + return send_path_control_message2( "close_exit", CloseExitMessage::sign_and_serialize(sk, std::move(tx_id)), std::move(func)); } - bool Path::find_client_contact( - const dht::Key_t& location, bool is_relayed, uint64_t order, std::function func) + bool Path::find_client_contact(const dht::Key_t& location, std::function func) { - return send_path_control_message( - "find_cc", FindClientContact::serialize(location, order, is_relayed), std::move(func)); + return send_path_control_message2("find_cc", FindClientContact::serialize(location), std::move(func)); } bool Path::publish_client_contact2(const EncryptedClientContact& ecc, std::function func) @@ -160,14 +158,9 @@ namespace llarp::path return send_path_control_message2("publish_cc", PublishClientContact::serialize(ecc), std::move(func)); } - bool Path::publish_client_contact(const EncryptedClientContact& ecc, std::function func) + bool Path::resolve_sns(std::string_view name, std::function func) { - return send_path_control_message("publish_cc_inner", PublishClientContact::serialize(ecc), std::move(func)); - } - - bool Path::resolve_ons(std::string name, std::function func) - { - return send_path_control_message("resolve_ons", FindNameMessage::serialize(std::move(name)), std::move(func)); + return send_path_control_message2("resolve_sns", ResolveSNS::serialize(name), std::move(func)); } void Path::enable_exit_traffic() diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 620eff9179..812cf44ead 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -90,25 +90,24 @@ namespace llarp void Tick(std::chrono::milliseconds now); - bool resolve_ons(std::string name, std::function func = nullptr); + bool resolve_sns(std::string_view name, std::function func); - bool find_client_contact( - const dht::Key_t& location, bool is_relayed, uint64_t order, std::function func); + bool find_client_contact(const dht::Key_t& location, std::function func); - bool publish_client_contact( - const EncryptedClientContact& ecc, std::function func = nullptr); + // bool publish_client_contact( + // const EncryptedClientContact& ecc, std::function func = nullptr); bool publish_client_contact2( const EncryptedClientContact& ecc, std::function func); bool close_exit( - const Ed25519SecretKey& sk, std::string tx_id, std::function func = nullptr); + const Ed25519SecretKey& sk, std::string tx_id, std::function = nullptr); bool obtain_exit( const Ed25519SecretKey& sk, uint64_t flag, std::string tx_id, - std::function func = nullptr); + std::function func); /// sends a control request along a path /// From 6f182b7339131bd0af10ce76f125bc36ec2ed894 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Tue, 5 Nov 2024 12:43:32 -0800 Subject: [PATCH 20/44] more efficient transit hop population, path etc --- llarp/contact/router_id.hpp | 4 ---- llarp/crypto/types.hpp | 8 -------- llarp/link/link_manager.cpp | 13 ++++--------- llarp/link/link_manager.hpp | 2 +- llarp/messages/common.hpp | 2 +- llarp/path/path.cpp | 6 +++--- llarp/path/path_context.cpp | 8 ++++---- llarp/path/path_context.hpp | 8 ++++---- llarp/path/path_handler.cpp | 22 ++++++++++++++++------ llarp/path/path_handler.hpp | 5 ++++- llarp/router/router.cpp | 31 ++++++++++++++++--------------- llarp/session/session.cpp | 2 +- 12 files changed, 54 insertions(+), 57 deletions(-) diff --git a/llarp/contact/router_id.hpp b/llarp/contact/router_id.hpp index 862511408d..5283945707 100644 --- a/llarp/contact/router_id.hpp +++ b/llarp/contact/router_id.hpp @@ -12,14 +12,10 @@ namespace llarp { static constexpr size_t SIZE = 32; - using Data = std::array; - RouterID() = default; RouterID(const uint8_t* buf) : PubKey(buf) {} - RouterID(const Data& data) : PubKey(data) {} - RouterID(ustring_view data) : PubKey(data.data()) {} RouterID(std::string_view data) : RouterID(to_usv(data)) {} diff --git a/llarp/crypto/types.hpp b/llarp/crypto/types.hpp index 777ff86d27..75b79c8b3c 100644 --- a/llarp/crypto/types.hpp +++ b/llarp/crypto/types.hpp @@ -11,7 +11,6 @@ namespace llarp { using SharedSecret = AlignedBuffer; - using KeyExchangeNonce = AlignedBuffer<32>; struct PubKey; struct Ed25519PrivateData; @@ -86,8 +85,6 @@ namespace llarp struct Signature final : public AlignedBuffer {}; - // using SymmNonce = AlignedBuffer; - struct SymmNonce final : public AlignedBuffer { using AlignedBuffer::AlignedBuffer; @@ -104,9 +101,4 @@ namespace llarp static SymmNonce make_random(); }; - using TunnelNonce = AlignedBuffer; - using SymmKey = AlignedBuffer<32>; // not used - - /// PKE(result, publickey, secretkey, nonce) - using path_dh_func = bool (*)(SharedSecret&, const PubKey&, const Ed25519SecretKey&, const TunnelNonce&); } // namespace llarp diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 8e12ba3f60..5731067b6e 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -682,7 +682,7 @@ namespace llarp return {}; } - void LinkManager::connect_to_random(size_t num_conns) + void LinkManager::connect_to_keep_alive(size_t num_conns) { auto filter = [this](const RemoteRC& rc) -> bool { const auto& rid = rc.router_id(); @@ -1218,7 +1218,8 @@ namespace llarp { log::info( logcat, - "Upstream returned successful path build response; locally storing Hop and relaying"); + "Upstream returned successful path build response; locally storing Hop ({}) and relaying", + transit_hop->to_string()); _router.path_context()->put_transit_hop(std::move(transit_hop)); return prev_message.respond(messages::OK_RESPONSE, false); } @@ -1259,16 +1260,10 @@ namespace llarp auto hop = _router.path_context()->get_transit_hop(hop_id); - // TODO: when using path conrol messages for responses, check for the Path + // TODO: when using path control messages for responses, check for the Path // with the corresponding ID, de-onion, etc if (not hop) { - // if (auto path = _router.path_context()->get_path(hop_id)) - // { - // log::info(logcat, "Received path control corresponding to known path!"); - // // - // } - log::warning(logcat, "Received path control with unknown next hop (ID: {})", hop_id); return m.respond(messages::ERROR_RESPONSE, true); } diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index b0b7dd6be2..0bc9c43341 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -246,7 +246,7 @@ namespace llarp // 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(size_t num_conns); + void connect_to_keep_alive(size_t num_conns); /// always maintain this many client connections to other routers int client_router_connections = 4; diff --git a/llarp/messages/common.hpp b/llarp/messages/common.hpp index 3b854cf141..12e29d48d9 100644 --- a/llarp/messages/common.hpp +++ b/llarp/messages/common.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 4592328031..76591c104c 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -35,15 +35,15 @@ namespace llarp::path for (size_t i = 0; i < num_hops; ++i) { - hops[i]._rid = hop_rcs[i].router_id(); - hops[i]._txid = HopID::make_random(); - /** Conditions: - First hop RXID is unique, the rest are the previous hop TXID - Last hop upstream is it's own RID, the rest are the next hop RID - First hop downstream is client's RID, the rest are the previous hop RID */ + hops[i]._rid = hop_rcs[i].router_id(); + hops[i]._txid = HopID::make_random(); + if (i == 0) { hops[i]._rxid = HopID::make_random(); diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index 1fc9db813d..b5e2bb3c7a 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -44,7 +44,7 @@ namespace llarp::path _path_map.erase(itr); } - bool PathContext::has_transit_hop(const std::shared_ptr& hop) + bool PathContext::has_transit_hop(const std::shared_ptr& hop) const { Lock_t l{paths_mutex}; @@ -59,7 +59,7 @@ namespace llarp::path _transit_hops.emplace(hop->txid(), hop); } - std::shared_ptr PathContext::get_transit_hop(const HopID& path_id) + std::shared_ptr PathContext::get_transit_hop(const HopID& path_id) const { Lock_t l{paths_mutex}; @@ -69,7 +69,7 @@ namespace llarp::path return nullptr; } - std::shared_ptr PathContext::get_path(const HopID& hop_id) + std::shared_ptr PathContext::get_path(const HopID& hop_id) const { Lock_t l{paths_mutex}; @@ -79,7 +79,7 @@ namespace llarp::path return nullptr; } - std::shared_ptr PathContext::get_path(const std::shared_ptr& hop) + std::shared_ptr PathContext::get_path(const std::shared_ptr& hop) const { Lock_t l{paths_mutex}; diff --git a/llarp/path/path_context.hpp b/llarp/path/path_context.hpp index d09f86fb56..b5b0366e0f 100644 --- a/llarp/path/path_context.hpp +++ b/llarp/path/path_context.hpp @@ -24,17 +24,17 @@ namespace llarp::path bool is_transit_allowed() const; - bool has_transit_hop(const std::shared_ptr& hop); + bool has_transit_hop(const std::shared_ptr& hop) const; void put_transit_hop(std::shared_ptr hop); - std::shared_ptr get_path(const std::shared_ptr& hop); + std::shared_ptr get_path(const std::shared_ptr& hop) const; - std::shared_ptr get_path(const HopID& hop_id); + std::shared_ptr get_path(const HopID& hop_id) const; std::shared_ptr get_path_for_transfer(const HopID& topath); - std::shared_ptr get_transit_hop(const HopID&); + std::shared_ptr get_transit_hop(const HopID&) const; std::shared_ptr get_path_handler(const HopID& id); diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index 7b6f6ec961..2cba675b0b 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -67,8 +67,6 @@ namespace llarp::path _paths.insert_or_assign(p->upstream_rxid(), p); - // associate_hop_ids(p); - _router.path_context()->add_path(p); } @@ -312,6 +310,18 @@ namespace llarp::path return found; } + size_t PathHandler::num_active_paths() const + { + Lock_t l(paths_mutex); + + size_t n{}; + + for (const auto& [_, p] : _paths) + n += (p != nullptr); + + return n; + } + size_t PathHandler::num_paths() const { Lock_t l(paths_mutex); @@ -345,7 +355,7 @@ namespace llarp::path bool PathHandler::should_remove() const { - return is_stopped() and num_paths() == 0; + return is_stopped() and num_active_paths() == 0; } bool PathHandler::build_cooldown_hit(RouterID edge) const @@ -521,7 +531,7 @@ namespace llarp::path { std::vector frames(path::MAX_LEN); auto& path_hops = path->hops; - int n_hops = static_cast(path_hops.size()); + int n_hops = static_cast(path->num_hops); size_t last_len{0}; // each hop will be able to read the outer part of its frame and decrypt @@ -538,8 +548,8 @@ namespace llarp::path // i from n_hops down to 0 for (int i = n_hops - 1; i >= 0; --i) { - const auto& next_rid = i == n_hops - 1 ? path_hops[i].router_id() : path_hops[i + 1].router_id(); - path_hops[i]._upstream = next_rid; + // const auto& next_rid = i == n_hops - 1 ? path_hops[i].router_id() : path_hops[i + 1].router_id(); + // path_hops[i]._upstream = next_rid; frames[i] = PATH::BUILD::serialize_hop(path_hops[i]); diff --git a/llarp/path/path_handler.hpp b/llarp/path/path_handler.hpp index af797f1d8e..8d6f52055f 100644 --- a/llarp/path/path_handler.hpp +++ b/llarp/path/path_handler.hpp @@ -184,7 +184,10 @@ namespace llarp /// return true if we hit our soft limit for building paths too fast bool build_cooldown() const; - /// get the number of paths in this status + /// get the number of ACTIVE paths in this status + size_t num_active_paths() const; + + /// get the number of ALL paths (both active and those being currently build) size_t num_paths() const; const BuildStats& build_stats() const { return _build_stats; } diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index b4696c71d7..ad48edbb1f 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -862,7 +862,7 @@ namespace llarp { log::critical( logcat, "Service Node connecting to {} random routers to achieve full mesh", FULL_MESH_ITERATION); - _link_manager->connect_to_random(FULL_MESH_ITERATION); + _link_manager->connect_to_keep_alive(FULL_MESH_ITERATION); } } @@ -883,27 +883,28 @@ namespace llarp return; } - _link_manager->check_persisting_conns(now); - - auto _num_router_conns = num_router_connections(); - - const auto& pinned_edges = _node_db->pinned_edges(); - const auto pinned_count = pinned_edges.size(); + // _link_manager->check_persisting_conns(now); - auto min_client_conns = - (pinned_count and MIN_CLIENT_ROUTER_CONNS > pinned_count) ? pinned_count : MIN_CLIENT_ROUTER_CONNS; + // TODO: make "use_pinned_edges" boolean to only connect to pinned edges + auto n_conns = num_router_connections(); + auto num_needed = MIN_CLIENT_ROUTER_CONNS - n_conns; // if we need more sessions to routers we shall connect out to others - if (_num_router_conns < min_client_conns) + if (num_needed) { - size_t needed = min_client_conns - _num_router_conns; log::critical( logcat, "Client connecting to {} random routers to keep alive (current:{}, needed:{})", - needed, - _num_router_conns, - min_client_conns); - _link_manager->connect_to_random(needed); + num_needed, + n_conns, + MIN_CLIENT_ROUTER_CONNS); + _link_manager->connect_to_keep_alive(num_needed); + + if (num_needed == MIN_CLIENT_ROUTER_CONNS) + { + log::info(logcat, "Client has 0 router connections currently; bypassing SessionEndpoint tick..."); + return; + } } _session_endpoint->tick(now); diff --git a/llarp/session/session.cpp b/llarp/session/session.cpp index 6ed7b45541..4ba764fce2 100644 --- a/llarp/session/session.cpp +++ b/llarp/session/session.cpp @@ -316,7 +316,7 @@ namespace llarp::session const size_t expect = (1 + (num_paths_desired / 2)); - return num_paths() >= expect; + return num_active_paths() >= expect; } bool OutboundSession::is_expired(std::chrono::milliseconds now) const From b01ef9a79d011ccbafb6a7aca60bc832e2f2f5fb Mon Sep 17 00:00:00 2001 From: dr7ana Date: Tue, 5 Nov 2024 13:41:11 -0800 Subject: [PATCH 21/44] Request handling, debugged hop-selection issues, strict-connect pinned edges, expiring - Cleaner handling of relayed vs path-requests - Relays expire transit_hops; constant lifetime reduced for testing - Abstracted reservoir sampling algorithm to use for better hop selection - Moved random to the correct place - strict-connect pinned edges require more efficient configuration of needed connections --- llarp/config/config.cpp | 13 +-- llarp/config/config.hpp | 6 +- llarp/constants/path.hpp | 5 +- llarp/contact/client_contact.cpp | 9 ++- llarp/contact/contactdb.cpp | 2 +- llarp/crypto/crypto.cpp | 9 +-- llarp/crypto/crypto.hpp | 13 +-- llarp/handlers/session.cpp | 12 +-- llarp/link/link_manager.cpp | 131 ++++++++++++++++++++++++++----- llarp/link/link_manager.hpp | 34 ++++---- llarp/messages/dht.hpp | 1 - llarp/messages/exit.hpp | 3 + llarp/nodedb.cpp | 64 +++------------ llarp/nodedb.hpp | 17 +++- llarp/path/path.hpp | 2 + llarp/path/path_context.cpp | 32 +++++++- llarp/path/path_context.hpp | 4 + llarp/path/path_handler.cpp | 68 ++++++++-------- llarp/profiling.cpp | 49 +++++++++--- llarp/profiling.hpp | 45 +++++++---- llarp/router/route_poker.cpp | 6 +- llarp/router/router.cpp | 123 ++++++++++++++++------------- llarp/router/router.hpp | 26 +++--- llarp/util/aligned.hpp | 16 ++-- llarp/util/concept.hpp | 3 + llarp/util/meta.hpp | 69 ++++++++++++++++ llarp/util/random.hpp | 33 ++++++++ 27 files changed, 523 insertions(+), 272 deletions(-) create mode 100644 llarp/util/meta.hpp create mode 100644 llarp/util/random.hpp diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index 5e58fcc4ac..4878d7d52c 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -72,15 +72,16 @@ namespace llarp net_id = std::move(arg); }); - conf.define_option( + conf.define_option( "router", "relay-connections", Default{CLIENT_ROUTER_CONNECTIONS}, ClientOnly, Comment{ "Minimum number of routers lokinet client will attempt to maintain connections to.", - }, - [=, this](int arg) { + "If [network]:strict-connect is defined, the number of client <-> router connections", + "maintained by a client will be at MOST the number of pinned edges"}, + [=, this](size_t arg) { if (arg < CLIENT_ROUTER_CONNECTIONS) throw std::invalid_argument{ "Client relay connections must be >= {}"_format(CLIENT_ROUTER_CONNECTIONS)}; @@ -392,9 +393,9 @@ namespace llarp [this](std::string value) { RouterID router; if (not router.from_relay_address(value)) - throw std::invalid_argument{"bad snode value: " + value}; - if (not strict_connect.insert(router).second) - throw std::invalid_argument{"duplicate strict connect snode: " + value}; + throw std::invalid_argument{"bad .snode pubkey: {}"_format(value)}; + if (not pinned_edges.insert(router).second) + throw std::invalid_argument{"duplicate strict connect .snode: {}"_format(value)}; }, Comment{ "Public keys of routers which will act as pinned first-hops. This may be used to", diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index 6e9903bea2..152c26bf6a 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -34,7 +34,7 @@ namespace llarp inline constexpr uint16_t DEFAULT_LISTEN_PORT{1090}; inline constexpr uint16_t DEFAULT_DNS_PORT{53}; - inline constexpr int CLIENT_ROUTER_CONNECTIONS = 4; + inline constexpr size_t CLIENT_ROUTER_CONNECTIONS{4}; // TODO: don't use these maps. they're sloppy and difficult to follow /// Small struct to gather all parameters needed for config generation to reduce the number of @@ -56,7 +56,7 @@ namespace llarp struct RouterConfig { - int client_router_connections{CLIENT_ROUTER_CONNECTIONS}; + size_t client_router_connections{CLIENT_ROUTER_CONNECTIONS}; std::string net_id; @@ -117,7 +117,7 @@ namespace llarp { bool enable_profiling; bool save_profiles; - std::set strict_connect; + std::set pinned_edges; std::optional keyfile; diff --git a/llarp/constants/path.hpp b/llarp/constants/path.hpp index fc8147fdf1..4b57dbd54e 100644 --- a/llarp/constants/path.hpp +++ b/llarp/constants/path.hpp @@ -13,8 +13,9 @@ namespace llarp::path 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}; + /// default path lifetime in ms; + // TESTNET: reduced value + constexpr std::chrono::milliseconds DEFAULT_LIFETIME{5min}; /// 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 diff --git a/llarp/contact/client_contact.cpp b/llarp/contact/client_contact.cpp index a7eb52427e..63b0e5315e 100644 --- a/llarp/contact/client_contact.cpp +++ b/llarp/contact/client_contact.cpp @@ -1,5 +1,7 @@ #include "client_contact.hpp" +#include + namespace llarp { static auto logcat = log::Cat("client-intro"); @@ -200,10 +202,15 @@ namespace llarp nonce.from_string(btdc.require("n")); blinded_pubkey.from_string(btdc.require("i")); encrypted = btdc.require>("x"); + sig.from_string(btdc.require("~")); } catch (const std::exception& e) { - log::critical(logcat, "EncryptedClientContact deserialization failed: {}", e.what()); + log::critical( + logcat, + "EncryptedClientContact deserialization failed: {} : payload: {}", + e.what(), + buffer_printer{_bt_payload}); throw; } } diff --git a/llarp/contact/contactdb.cpp b/llarp/contact/contactdb.cpp index 39f8b71aaa..6bc0e5582c 100644 --- a/llarp/contact/contactdb.cpp +++ b/llarp/contact/contactdb.cpp @@ -7,7 +7,7 @@ namespace llarp ContactDB::ContactDB(Router& r) : _router{r}, _local_key{dht::Key_t::derive_from_rid(r.local_rid())} { timer_keepalive = std::make_shared(0); - _cc_nodes = std::make_unique>(_local_key, llarp::randint); + _cc_nodes = std::make_unique>(_local_key, csrng); } std::optional ContactDB::get_decrypted_cc(RouterID remote) const diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index 532666a159..cf545bf1b4 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -1,6 +1,7 @@ #include "crypto.hpp" #include +#include #include #include @@ -473,13 +474,6 @@ namespace llarp return sec.data() + 32; } - uint64_t randint() - { - uint64_t i; - randombytes((uint8_t*)&i, sizeof(i)); - return i; - } - // Called during static initialization to initialize libsodium. (The CSRNG return is // not useful, but just here to get this called during static initialization of `csrng`). static CSRNG _initialize_crypto() @@ -494,5 +488,4 @@ namespace llarp } CSRNG csrng = _initialize_crypto(); - } // namespace llarp diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index e614d25d9d..4d0f3ad052 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -4,6 +4,7 @@ #include #include +#include #include @@ -121,17 +122,5 @@ namespace llarp const uint8_t* seckey_to_pubkey(const Ed25519SecretKey& secret); /// rng type that uses llarp::randint(), which is cryptographically secure - struct CSRNG - { - using result_type = uint64_t; - - static constexpr uint64_t 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/handlers/session.cpp b/llarp/handlers/session.cpp index 28cbd9d06f..fa7fc4fea3 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include namespace llarp::handlers @@ -118,13 +119,10 @@ namespace llarp::handlers void SessionEndpoint::build_more(size_t n) { size_t count{0}; - log::debug( - logcat, "SessionEndpoint building {} paths to random remotes (needed: {})", n, path::DEFAULT_PATHS_HELD); + log::debug(logcat, "SessionEndpoint building {} paths to random remotes (needed: {})", n, num_paths_desired); - for (size_t i = 0; i < n; ++i) - { + while (count < n) count += build_path_to_random(); - } if (count == n) log::debug(logcat, "SessionEndpoint successfully initiated {} path-builds", n); @@ -432,6 +430,10 @@ namespace llarp::handlers for (const auto& [_, path] : _paths) { + // If path-build is underway, don't use it + if (not path) + continue; + log::debug(logcat, "Publishing ClientContact to pivot {}", path->pivot_rid()); ret &= path->publish_client_contact2(ecc, [](oxen::quic::message m) { diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 5731067b6e..091c25f847 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -88,16 +88,18 @@ namespace llarp return link_manager.router().loop()->call_get([this, remote]() { return service_conns.count(remote); }); } - void Endpoint::for_each_connection(std::function hook) + void Endpoint::for_each_connection(std::function func) { - link_manager.router().loop()->call([this, func = std::move(hook)]() { - for (const auto& [rid, conn] : service_conns) - func(*conn); + link_manager.router().loop()->call([this, func = std::move(func)]() mutable { + for (auto& [rid, conn] : service_conns) + if (conn) + func(rid, *conn); if (_is_service_node) { - for (const auto& [rid, conn] : client_conns) - func(*conn); + for (auto& [rid, conn] : client_conns) + if (conn) + func(rid, *conn); } }); } @@ -143,17 +145,23 @@ namespace llarp return link_manager.router().loop()->call_get([this]() -> std::tuple { size_t in{0}, out{0}; - for (const auto& c : service_conns) + for (const auto& [_, c] : service_conns) { - if (c.second->is_inbound()) + if (not c) + continue; + + if (c->is_inbound()) ++in; else ++out; } - for (const auto& c : client_conns) + for (const auto& [_, c] : client_conns) { - if (c.second->is_inbound()) + if (not c) + continue; + + if (c->is_inbound()) ++in; else ++out; @@ -170,7 +178,14 @@ namespace llarp size_t Endpoint::num_router_conns() const { - return link_manager.router().loop()->call_get([this]() { return service_conns.size(); }); + return link_manager.router().loop()->call_get([this]() { + size_t n{}; + + for (const auto& [_, c] : service_conns) + n += (c != nullptr); + + return n; + }); } } // namespace link @@ -191,12 +206,24 @@ namespace llarp using messages::serialize_response; - void LinkManager::for_each_connection(std::function func) + std::set LinkManager::get_current_remotes() const + { + // invoke using Router method to wrap in call_get + std::set ret{}; + + for (auto& [rid, conn] : ep->service_conns) + if (conn) + ret.insert(rid); + + return ret; + } + + void LinkManager::for_each_connection(std::function func) { if (is_stopping) return; - return ep->for_each_connection(func); + return ep->for_each_connection(std::move(func)); } void LinkManager::register_commands( @@ -562,7 +589,7 @@ namespace llarp if (auto rv = ep->establish_and_send( KeyedAddress{router.to_view(), remote_addr}, - *rc, + router, std::move(endpoint), std::move(body), std::move(func)); @@ -593,7 +620,7 @@ namespace llarp auto remote_addr = rc.addr(); if (auto rv = ep->establish_connection( - KeyedAddress{rid.to_view(), remote_addr}, rc, std::move(on_open), std::move(on_close)); + KeyedAddress{rid.to_view(), remote_addr}, rid, std::move(on_open), std::move(on_close)); rv) { log::info(logcat, "Begun establishing connection to {}", remote_addr); @@ -693,6 +720,16 @@ namespace llarp return res; }; + std::optional> rcs = std::nullopt; + + if (node_db->strict_connect_enabled()) + { + assert(not _is_service_node); + + // TESTNET: TODO: if given strict-connects, fetch their RCs SPECIFICALLY in bootstrapping + log::warning(logcat, "FINISH STRICT CONNECT (SEE COMMENT)"); + } + if (auto maybe = node_db->get_n_random_rcs_conditional(num_conns, filter)) { std::vector& rcs = *maybe; @@ -991,6 +1028,40 @@ namespace llarp m.respond(std::move(btdp).str()); } + void LinkManager::_handle_resolve_sns(oxen::quic::message m, std::optional inner_body) + { + log::critical(logcat, "Received request to publish client contact!"); + + std::string name_hash; + + try + { + if (inner_body) + name_hash = ResolveSNS::deserialize(oxenc::bt_dict_consumer{*inner_body}); + else + name_hash = ResolveSNS::deserialize(oxenc::bt_dict_consumer{m.body()}); + } + catch (const std::exception& e) + { + log::warning(logcat, "Exception: {}", e.what()); + return m.respond(messages::ERROR_RESPONSE, true); + } + + _router.rpc_client()->lookup_ons_hash( + name_hash, [prev_msg = std::move(m)](std::optional maybe_enc) mutable { + if (maybe_enc) + { + log::info(logcat, "RPC lookup successfully returned encrypted SNS record!"); + prev_msg.respond(ResolveSNS::serialize_response(*maybe_enc)); + } + else + { + log::warning(logcat, "RPC lookup could not find SNS registry!"); + prev_msg.respond(ResolveSNS::NOT_FOUND, true); + } + }); + } + void LinkManager::handle_resolve_sns(oxen::quic::message m) { std::string name_hash; @@ -1020,7 +1091,7 @@ namespace llarp }); } - void LinkManager::handle_publish_cc(oxen::quic::message m) + void LinkManager::_handle_publish_cc(oxen::quic::message m, std::optional inner_body) { log::critical(logcat, "Received request to publish client contact!"); @@ -1028,11 +1099,14 @@ namespace llarp try { - enc = PublishClientContact::deserialize(oxenc::bt_dict_consumer{m.body()}); + if (inner_body) + enc = PublishClientContact::deserialize(oxenc::bt_dict_consumer{*inner_body}); + else + enc = PublishClientContact::deserialize(oxenc::bt_dict_consumer{m.body()}); } catch (const std::exception& e) { - log::warning(logcat, "Exception: {}", e.what()); + log::warning(logcat, "Exception: {}: payload: {}", e.what(), buffer_printer{m.body()}); return m.respond(messages::ERROR_RESPONSE, true); } @@ -1085,13 +1159,23 @@ namespace llarp }); } - void LinkManager::handle_find_cc(oxen::quic::message m) + void LinkManager::handle_publish_cc(oxen::quic::message m) + { + return _handle_publish_cc(std::move(m)); + } + + void LinkManager::_handle_find_cc(oxen::quic::message m, std::optional inner_body) { + log::critical(logcat, "Received request to find client contact!"); + dht::Key_t dht_key; try { - dht_key = FindClientContact::deserialize(oxenc::bt_dict_consumer{m.body()}); + if (inner_body) + dht_key = FindClientContact::deserialize(oxenc::bt_dict_consumer{*inner_body}); + else + dht_key = FindClientContact::deserialize(oxenc::bt_dict_consumer{m.body()}); } catch (const std::exception& e) { @@ -1133,6 +1217,11 @@ namespace llarp }); } + void LinkManager::handle_find_cc(oxen::quic::message m) + { + return _handle_find_cc(std::move(m)); + } + void LinkManager::handle_path_build(oxen::quic::message m, const RouterID& from) { if (!_router.path_context()->is_transit_allowed()) @@ -1416,7 +1505,7 @@ namespace llarp if (auto it = path_requests.find(endpoint); it != path_requests.end()) { log::debug(logcat, "Received path control request (`{}`); invoking endpoint...", endpoint); - std::invoke(it->second, this, std::move(m)); + std::invoke(it->second, this, std::move(m), std::move(body)); } else log::warning(logcat, "Received path control request (`{}`), which has no local handler!", endpoint); diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 0bc9c43341..7c321d710d 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -39,9 +39,6 @@ namespace llarp inline const keep_alive RELAY_KEEP_ALIVE{10s}; inline const keep_alive CLIENT_KEEP_ALIVE{10s}; - inline constexpr int MIN_CLIENT_ROUTER_CONNS{8}; - inline constexpr int MAX_CLIENT_ROUTER_CONNS{10}; - namespace alpns { inline const auto SN_ALPNS = "SERVICE_NODE"_us; @@ -93,18 +90,18 @@ namespace llarp size_t num_router_conns() const; template - bool establish_connection(KeyedAddress remote, RemoteRC rc, Opt&&... opts); + bool establish_connection(KeyedAddress remote, RouterID rid, Opt&&... opts); template bool establish_and_send( KeyedAddress remote, - RemoteRC rc, + RouterID rid, std::optional endpoint, std::string body, std::function func = nullptr, Opt&&... opts); - void for_each_connection(std::function func); + void for_each_connection(std::function func); void close_connection(RouterID rid); @@ -239,7 +236,9 @@ namespace llarp nlohmann::json extract_status() const; - void for_each_connection(std::function func); + std::set get_current_remotes() const; + + void for_each_connection(std::function func); // Attempts to connect to a number of random routers. // @@ -258,6 +257,11 @@ namespace llarp void handle_find_cc(oxen::quic::message); void handle_resolve_sns(oxen::quic::message); + // Inner handlers for relayed requests + void _handle_publish_cc(oxen::quic::message, std::optional = std::nullopt); + void _handle_find_cc(oxen::quic::message, std::optional = std::nullopt); + void _handle_resolve_sns(oxen::quic::message, std::optional = std::nullopt); + // Path messages void handle_path_build(oxen::quic::message, const RouterID& from); // relay void handle_path_latency(oxen::quic::message); // relay @@ -279,10 +283,11 @@ namespace llarp // These requests come over a path (as a "path_control" request), // we may or may not need to make a request to another relay, // then respond (onioned) back along the path. - std::unordered_map path_requests = { - {"publish_cc"sv, &LinkManager::handle_publish_cc}, - {"find_cc"sv, &LinkManager::handle_find_cc}, - {"resolve_sns"sv, &LinkManager::handle_resolve_sns}}; + std::unordered_map)> + path_requests = { + {"publish_cc"sv, &LinkManager::_handle_publish_cc}, + {"find_cc"sv, &LinkManager::_handle_find_cc}, + {"resolve_sns"sv, &LinkManager::_handle_resolve_sns}}; // Path relaying void handle_path_control(oxen::quic::message, const RouterID& from); @@ -306,7 +311,7 @@ namespace llarp template bool Endpoint::establish_and_send( KeyedAddress remote, - RemoteRC rc, + RouterID rid, std::optional ep, std::string body, std::function func, @@ -315,7 +320,6 @@ namespace llarp return link_manager.router().loop()->call_get([&]() { try { - const auto& rid = rc.router_id(); const auto& is_control = ep.has_value(); const auto us = _is_service_node ? "Relay"s : "Client"s; @@ -371,13 +375,11 @@ namespace llarp } template - bool Endpoint::establish_connection(KeyedAddress remote, RemoteRC rc, Opt&&... opts) + bool Endpoint::establish_connection(KeyedAddress remote, RouterID rid, Opt&&... opts) { return link_manager.router().loop()->call_get([&]() { try { - const auto& rid = rc.router_id(); - log::debug(logcat, "Establishing connection to RID:{}", rid); // add to service conns auto [itr, b] = service_conns.try_emplace(rid, nullptr); diff --git a/llarp/messages/dht.hpp b/llarp/messages/dht.hpp index 9807605e7d..45182e3948 100644 --- a/llarp/messages/dht.hpp +++ b/llarp/messages/dht.hpp @@ -7,7 +7,6 @@ namespace llarp { - namespace PublishClientContact { inline const auto INVALID = messages::serialize_response({{messages::STATUS_KEY, "INVALID CC"}}); diff --git a/llarp/messages/exit.hpp b/llarp/messages/exit.hpp index bfa5ce443b..f288fdf09f 100644 --- a/llarp/messages/exit.hpp +++ b/llarp/messages/exit.hpp @@ -2,6 +2,9 @@ #include "common.hpp" +#include +#include + namespace llarp { /* diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index 467e35e239..2e5737a477 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -3,6 +3,7 @@ #include "crypto/types.hpp" #include "link/link_manager.hpp" #include "messages/fetch.hpp" +#include "util/meta.hpp" #include "util/time.hpp" #include @@ -74,58 +75,13 @@ namespace llarp return rc; } - size_t i = 0; - std::optional res = std::nullopt; - - for (const auto& rc : known_rcs) - { - if (not hook(rc)) - continue; - - if (++i <= 1) - { - res = rc; - continue; - } - - size_t x = csrng() % (i + 1); - if (x <= 1) - res = rc; - } - - return res; + return meta::sample(known_rcs, std::move(hook)); } std::optional> NodeDB::get_n_random_rcs_conditional( - size_t n, std::function hook, bool exact) const + size_t n, std::function hook, bool exact, bool /* use_strict_connect */) const { - auto selected = std::make_optional>(); - selected->reserve(n); - - size_t i = 0; - - for (const auto& rc : known_rcs) - { - // ignore any RC's that do not pass the condition - if (not hook(rc)) - continue; - - // load the first n RC's that pass the condition into selected - if (++i <= n) - { - selected->push_back(rc); - continue; - } - - // replace selections with decreasing probability per iteration - size_t x = csrng() % (i + 1); - if (x < n) - (*selected)[x] = rc; - } - - if (selected->size() < (exact ? n : 1)) - selected.reset(); - return selected; + return meta::sample_n(known_rcs, std::move(hook), n, exact); } bool NodeDB::tick(std::chrono::milliseconds now) @@ -227,7 +183,7 @@ namespace llarp } // if we don't have the whitelist yet don't remove the entry - if (not _router.whitelist_received) + if (not _router.has_whitelist()) { log::debug(logcat, "Skipping check on {}: don't have whitelist yet", rc.router_id()); return false; @@ -419,7 +375,7 @@ namespace llarp void NodeDB::fetch_rcs() { - if (_router._is_stopping || not _router._is_running) + if (_router.is_stopping() || not _router.is_running()) { log::info(logcat, "NodeDB unable to continue RC fetch -- router is stopped!"); return stop_rc_fetch(false); @@ -492,7 +448,7 @@ namespace llarp void NodeDB::fetch_rids() { - if (_router._is_stopping || not _router._is_running) + if (_router.is_stopping() || not _router.is_running()) { log::info(logcat, "NodeDB unable to continue RouterID fetch -- router is stopped!"); return stop_rid_fetch(false); @@ -638,7 +594,7 @@ namespace llarp void NodeDB::configure() { - _is_service_node = _router._is_service_node; + _is_service_node = _router.is_service_node(); bootstrap_init(); load_from_disk(); @@ -708,7 +664,7 @@ namespace llarp { log::debug(logcat, "{} called", __PRETTY_FUNCTION__); - if (_router._is_stopping || not _router._is_running) + if (_router.is_stopping() || not _router.is_running()) { log::info(logcat, "NodeDB unable to continue bootstrap fetch -- router is stopped!"); return stop_bootstrap(false); @@ -724,7 +680,7 @@ namespace llarp _router.link_manager()->fetch_bootstrap_rcs( rc, BootstrapFetchMessage::serialize( - _is_service_node ? std::make_optional(_router.relay_contact) : std::nullopt, num_needed), + _is_service_node ? std::make_optional(_router.rc()) : std::nullopt, num_needed), [this, src = source](oxen::quic::message m) mutable { log::info(logcat, "Received response to BootstrapRC fetch request..."); diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index 71980aeb26..4110a6b2bc 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -88,13 +88,15 @@ namespace llarp class NodeDB { + friend struct Router; + Router& _router; const fs::path _root; // const std::function)> _disk_hook; - bool _is_service_node; + bool _is_service_node{false}; - std::chrono::milliseconds _next_flush_time; + std::chrono::milliseconds _next_flush_time{}; /******** RouterID/RelayContacts ********/ @@ -141,8 +143,13 @@ namespace llarp // All registered relays (service nodes) std::set _registered_routers; + // if populated from a config file, lists specific exclusively used as path first-hops std::set _pinned_edges; + + // if true, ONLY use pinned edges for first hop + bool _strict_connect{false}; + // source of "truth" for RC updating. This relay will also mediate requests to the // 8 selected active RID's for RID fetching RouterID fetch_source; @@ -195,6 +202,8 @@ namespace llarp rid_result_counters.clear(); } + bool strict_connect_enabled() const { return _strict_connect; } + void start_tickers(); void configure(); @@ -335,7 +344,7 @@ namespace llarp /** The following random conditional functions utilize a simple implementation of reservoir sampling to return either 1 or n random RC's using only one pass through the set of - RC's. + RC's. Pseudocode: - begin iterating through the set @@ -347,7 +356,7 @@ namespace llarp std::optional get_random_rc_conditional(std::function hook) const; std::optional> get_n_random_rcs_conditional( - size_t n, std::function hook, bool exact = false) const; + size_t n, std::function hook, bool exact = false, bool use_strict_connect = false) const; // Updates `current` to not contain any of the elements of `replace` and resamples (up to // `target_size`) from population to refill it. diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 812cf44ead..d63266fb6b 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -125,6 +125,8 @@ namespace llarp bool send_path_data_message(std::string body); + bool is_established() const { return _established; } + bool is_ready(std::chrono::milliseconds now = llarp::time_now_ms()) const; std::shared_ptr get_parent(); diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index b5e2bb3c7a..5517330ba1 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -6,6 +6,8 @@ namespace llarp::path { + static auto logcat = log::Cat("pathctx"); + PathContext::PathContext(RouterID local_rid) : _local_rid{std::move(local_rid)} {} void PathContext::allow_transit() @@ -36,14 +38,40 @@ namespace llarp::path } } - void PathContext::drop_path(const std::shared_ptr& path) + void PathContext::expire_hops(std::chrono::milliseconds now) { Lock_t l{paths_mutex}; - if (auto itr = _path_map.find(path->upstream_rxid()); itr != _path_map.end()) + size_t n = 0; + + for (auto itr = _transit_hops.begin(); itr != _transit_hops.end();) + { + if (itr->second->is_expired(now)) + { + itr = _transit_hops.erase(itr); + n += 1; + } + else + ++itr; + } + + if (n) + log::info(logcat, "{} expired TransitHops purged!", n); + } + + void PathContext::drop_path(const HopID& hop_id) + { + Lock_t l{paths_mutex}; + if (auto itr = _path_map.find(hop_id); itr != _path_map.end()) _path_map.erase(itr); } + void PathContext::drop_path(const std::shared_ptr& path) + { + Lock_t l{paths_mutex}; + drop_path(path->upstream_rxid()); + } + bool PathContext::has_transit_hop(const std::shared_ptr& hop) const { Lock_t l{paths_mutex}; diff --git a/llarp/path/path_context.hpp b/llarp/path/path_context.hpp index b5b0366e0f..26162438f5 100644 --- a/llarp/path/path_context.hpp +++ b/llarp/path/path_context.hpp @@ -40,10 +40,14 @@ namespace llarp::path void add_path(std::shared_ptr p); + void drop_path(const HopID& hop_id); + void drop_path(const std::shared_ptr& p); void drop_paths(std::vector> droplist); + void expire_hops(std::chrono::milliseconds now); + private: const RouterID _local_rid; diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index 2cba675b0b..81a6eb8d92 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -193,6 +194,8 @@ namespace llarp::path // called within the scope of locked mutex void PathHandler::expire_paths(std::chrono::milliseconds now) { + Lock_t lock{paths_mutex}; + if (_paths.size() == 0) return; @@ -200,7 +203,7 @@ namespace llarp::path for (auto itr = _paths.begin(); itr != _paths.end();) { - if (itr->second->is_expired(now)) + if (itr->second and itr->second->is_established() and itr->second->is_expired(now)) { droplist.push_back(std::move(itr->second)); itr = _paths.erase(itr); @@ -256,7 +259,7 @@ namespace llarp::path now = llarp::time_now_ms(); _router.pathbuild_limiter().Decay(now); - // expire_paths(now); + expire_paths(now); if (auto n = should_build_more(); n > 0) build_more(n); @@ -288,26 +291,27 @@ namespace llarp::path std::optional PathHandler::select_first_hop(const std::set& exclude) const { - std::optional found = std::nullopt; - _router.for_each_connection([&](link::Connection& conn) { - RouterID rid{conn.conn->remote_key()}; + std::set current_remotes; -#ifndef TESTNET - if (_router.is_bootstrap_node(rid)) - return; -#endif - if (exclude.count(rid)) - return; + if (_router.node_db()->strict_connect_enabled()) + current_remotes = _router.node_db()->pinned_edges(); + else + current_remotes = _router.get_current_remotes(); + std::function hook = [&](const RouterID& rid) { + if (exclude.count(rid)) + return false; if (build_cooldown_hit(rid)) - return; - + return false; + // always returns false on testnet builds if (_router.router_profiling().is_bad_for_path(rid)) - return; + return false; + return true; + }; + + auto edge = meta::sample(current_remotes, hook); - found = _router.node_db()->get_rc(rid); - }); - return found; + return edge ? _router.node_db()->get_rc(*edge) : std::nullopt; } size_t PathHandler::num_active_paths() const @@ -402,6 +406,8 @@ namespace llarp::path // make a copy here to reference rather than creating one in the lambda every iteration std::set to_exclude{exclude.begin(), exclude.end()}; + to_exclude.insert(pivot); + std::vector hops; if (auto maybe = select_first_hop(exclude)) @@ -412,42 +418,38 @@ namespace llarp::path return std::nullopt; } - RemoteRC remote_rc; + to_exclude.insert(hops.back().router_id()); - if (const auto maybe = _router.node_db()->get_rc(pivot)) + RemoteRC pivot_rc; + + if (auto maybe = _router.node_db()->get_rc(pivot)) { - remote_rc = *maybe; + pivot_rc = *maybe; } else return std::nullopt; - to_exclude.insert(remote_rc.router_id()); // we will manually add this last - // leave one extra spot for the terminal node auto hops_needed = num_hops - hops.size() - 1; auto filter = [&r = _router, &to_exclude](const RemoteRC& rc) -> bool { const auto& rid = rc.router_id(); - if (r.router_profiling().is_bad_for_path(rid, 1)) - to_exclude.insert(rid); - - if (to_exclude.count(rid)) + // if its already excluded, fail; (we want it added even on success) + if (not to_exclude.insert(rid).second) return false; - // add the rid on a success case so we don't select it again - to_exclude.insert(rid); + if (r.router_profiling().is_bad_for_path(rid, 1)) + return false; return true; }; - auto maybe_rcs = _router.node_db()->get_n_random_rcs_conditional(hops_needed, filter, true); - - if (maybe_rcs) + if (auto maybe_rcs = _router.node_db()->get_n_random_rcs_conditional(hops_needed, filter, true)) { auto& rcs = *maybe_rcs; hops.insert(hops.end(), rcs.begin(), rcs.end()); - hops.emplace_back(remote_rc); + hops.emplace_back(pivot_rc); #ifndef TESTNET if (not path_config.check_rcs({hops.begin(), hops.end()})) @@ -647,6 +649,8 @@ namespace llarp::path if (auto itr = _paths.find(upstream_rxid); itr != _paths.end()) _paths.erase(itr); + + _router.path_context()->drop_path(upstream_rxid); } void PathHandler::path_build_failed(std::shared_ptr p, bool timeout) diff --git a/llarp/profiling.cpp b/llarp/profiling.cpp index 7b287b6536..3931debf2d 100644 --- a/llarp/profiling.cpp +++ b/llarp/profiling.cpp @@ -1,6 +1,7 @@ #include "profiling.hpp" #include "path/path.hpp" +#include "router/router.hpp" #include "util/file.hpp" #include @@ -86,7 +87,7 @@ namespace llarp last_decay = llarp::time_now_ms(); } - void RouterProfile::Tick() + void RouterProfile::tick() { static constexpr auto updateInterval = 30s; const auto now = llarp::time_now_ms(); @@ -122,8 +123,6 @@ namespace llarp return checkIsGood(path_fail, path_success, chances); } - Profiling::Profiling() : _profiling_disabled(false) {} - void Profiling::disable() { _profiling_disabled.store(true); @@ -178,7 +177,7 @@ namespace llarp return; util::Lock lock(_m); for (auto& [rid, profile] : _profiles) - profile.Tick(); + profile.tick(); } void Profiling::connect_timeout(const RouterID& r) @@ -205,6 +204,9 @@ namespace llarp void Profiling::hop_fail(const RouterID& r) { + if (_profiling_disabled.load()) + return; + util::Lock lock{_m}; auto& profile = _profiles[r]; profile.path_fail += 1; @@ -213,6 +215,9 @@ namespace llarp void Profiling::path_fail(path::Path* p) { + if (_profiling_disabled.load()) + return; + util::Lock lock{_m}; bool first = true; for (const auto& hop : p->hops) @@ -231,6 +236,9 @@ namespace llarp void Profiling::path_timeout(path::Path* p) { + if (_profiling_disabled.load()) + return; + util::Lock lock{_m}; for (const auto& hop : p->hops) { @@ -242,6 +250,9 @@ namespace llarp void Profiling::path_success(path::Path* p) { + if (_profiling_disabled.load()) + return; + util::Lock lock{_m}; const auto sz = p->hops.size(); for (const auto& hop : p->hops) @@ -256,7 +267,25 @@ namespace llarp } } - bool Profiling::save(const fs::path fpath) + void Profiling::stop_save_ticker() + { + if (_disk_saver) + { + log::trace(logcat, "Stopping router profile disk saving"); + _disk_saver->stop(); + _disk_saver.reset(); + } + } + + void Profiling::start_save_ticker(Router& r) + { + _disk_saver = r.loop()->call_every(SAVE_INTERVAL, [this]() { + log::debug(logcat, "Writing router profiles to disk..."); + save_to_disk(); + }); + } + + bool Profiling::save_to_disk() { std::string buf; { @@ -277,11 +306,11 @@ namespace llarp try { - util::buffer_to_file(fpath, buf); + util::buffer_to_file(_profile_file, buf); } catch (const std::exception& e) { - log::warning(logcat, "Failed to save profiling data to {}: {}", fpath, e.what()); + log::warning(logcat, "Failed to save profiling data to {}: {}", _profile_file, e.what()); return false; } @@ -308,17 +337,17 @@ namespace llarp } } - bool Profiling::load(const fs::path fname) + bool Profiling::load_from_disk() { try { - std::string data = util::file_to_string(fname); + std::string data = util::file_to_string(_profile_file); util::Lock lock{_m}; BDecode(bt_dict_consumer{data}); } catch (const std::exception& e) { - log::warning(logcat, "failed to load router profiles from {}: {}", fname, e.what()); + log::warning(logcat, "failed to load router profiles from {}: {}", _profile_file, e.what()); return false; } _last_save = llarp::time_now_ms(); diff --git a/llarp/profiling.hpp b/llarp/profiling.hpp index 41cef4cebe..6851c328cb 100644 --- a/llarp/profiling.hpp +++ b/llarp/profiling.hpp @@ -2,6 +2,7 @@ #include "constants/proto.hpp" #include "contact/router_id.hpp" +#include "ev/types.hpp" #include "util/thread/threading.hpp" #include @@ -14,6 +15,8 @@ namespace oxenc namespace llarp { + struct Router; + namespace path { struct Path; @@ -21,14 +24,15 @@ namespace llarp struct RouterProfile { - static constexpr size_t MaxSize = 256; - uint64_t conn_timeout = 0; - uint64_t conn_success = 0; - uint64_t path_success = 0; - uint64_t path_fail = 0; - uint64_t path_timeout = 0; - std::chrono::milliseconds last_update = 0s; - std::chrono::milliseconds last_decay = 0s; + static constexpr size_t MaxSize{256}; + + uint64_t conn_timeout{}; + uint64_t conn_success{}; + uint64_t path_success{}; + uint64_t path_fail{}; + uint64_t path_timeout{}; + std::chrono::milliseconds last_update{0s}; + std::chrono::milliseconds last_decay{0s}; uint64_t version = llarp::constants::proto_version; RouterProfile() = default; @@ -50,14 +54,18 @@ namespace llarp void decay(); // rotate stats if timeout reached - void Tick(); + void tick(); }; struct Profiling { - Profiling(); + static constexpr std::chrono::milliseconds SAVE_INTERVAL{10min}; + + friend struct Router; + + Profiling() = default; - inline static const int profiling_chances = 4; + inline static const int profiling_chances{4}; /// generic variant bool is_bad(const RouterID& r, uint64_t chances = profiling_chances); @@ -84,9 +92,9 @@ namespace llarp void tick(); - bool load(const fs::path fname); + bool load_from_disk(); - bool save(const fs::path fname); + bool save_to_disk(); bool should_save(std::chrono::milliseconds now) const; @@ -97,14 +105,21 @@ namespace llarp bool is_enabled() const; private: + void start_save_ticker(Router& r); + + void stop_save_ticker(); + void BEncode(oxenc::bt_dict_producer& dict) const; void BDecode(oxenc::bt_dict_consumer dict); + std::shared_ptr _disk_saver; + mutable util::Mutex _m; + fs::path _profile_file; std::map _profiles; - std::chrono::milliseconds _last_save = 0s; - std::atomic _profiling_disabled; + std::chrono::milliseconds _last_save{0s}; + std::atomic _profiling_disabled{false}; }; } // namespace llarp diff --git a/llarp/router/route_poker.cpp b/llarp/router/route_poker.cpp index 02c58ee993..1701a3003c 100644 --- a/llarp/router/route_poker.cpp +++ b/llarp/router/route_poker.cpp @@ -196,7 +196,8 @@ namespace llarp route.add_blackhole(); // explicit route pokes for first hops - router.for_each_connection([this](link::Connection conn) { add_route(conn.conn->remote()); }); + router.for_each_connection( + [this](const RouterID&, link::Connection& conn) { add_route(conn.conn->remote()); }); add_route(router.link_manager()->local()); // add default route @@ -213,7 +214,8 @@ namespace llarp void RoutePoker::put_down() { // unpoke routes for first hops - router.for_each_connection([this](link::Connection conn) { delete_route(conn.conn->remote()); }); + router.for_each_connection( + [this](const RouterID&, link::Connection& conn) { delete_route(conn.conn->remote()); }); 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 ad48edbb1f..97174ddcac 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -245,9 +245,14 @@ namespace llarp return _link_manager->send_control_message(remote, std::move(ep), std::move(body), std::move(func)); } - void Router::for_each_connection(std::function func) + std::set Router::get_current_remotes() const { - return _link_manager->for_each_connection(func); + return _loop->call_get([this]() { return _link_manager->get_current_remotes(); }); + } + + void Router::for_each_connection(std::function func) + { + return _link_manager->for_each_connection(std::move(func)); } bool Router::ensure_identity() @@ -363,7 +368,7 @@ namespace llarp auto& conf = *_config; // Router config - client_router_connections = conf.router.client_router_connections; + min_client_outbounds = conf.router.client_router_connections; std::optional paddr = (conf.router.public_ip) ? conf.router.public_ip : (conf.links.public_addr) ? conf.links.public_addr @@ -529,50 +534,42 @@ namespace llarp } /// build a set of strictConnectPubkeys - if (not conf.strict_connect.empty()) + if (auto& conf_edges = conf.pinned_edges; not conf_edges.empty()) { - const auto& val = conf.strict_connect; - if (is_service_node()) throw std::runtime_error("cannot use strict-connect option as service node"); - if (val.size() < 2) + auto n_edges = conf_edges.size(); + if (n_edges < 2) throw std::runtime_error("Must specify more than one strict-connect router if using strict-connect"); - _node_db->pinned_edges().insert(val.begin(), val.end()); - log::debug(logcat, "{} strict-connect routers configured", val.size()); - } + _node_db->pinned_edges() = std::move(conf_edges); + _node_db->_strict_connect = true; - // profiling - _profile_file = _config->router.data_dir / "profiles.dat"; + log::info(logcat, "Local client configured to strictly use {} edge relays", n_edges); - // Network config - if (not _testnet and _config->network.enable_profiling) - { - log::debug(logcat, "Router profiling enabled"); - if (not fs::exists(_profile_file)) + if (min_client_outbounds > n_edges) { - log::debug(logcat, "No profiles file found at {}; skipping...", _profile_file); - } - else - { - log::debug(logcat, "Loading router profiles from {}", _profile_file); - _router_profiling.load(_profile_file); + min_client_outbounds = n_edges; + log::info( + logcat, + "Local client holds only {} strict-connect edge relays; adjusting minimum router connections " + "commensurately", + n_edges); } } else - { - _router_profiling.disable(); - log::debug(logcat, "Router profiling disabled"); - } + log::info( + logcat, "Local client configured to maintain {} router connections at minimum", min_client_outbounds); + + if (min_client_outbounds < 2) + throw std::runtime_error{"Client cannot be configured to have less than 2 outbound router connections!"}; } void Router::init_tun() { if (_tun = _loop->template make_shared(*this); _tun != nullptr) - { _tun->configure(); - } else throw std::runtime_error{"Failed to construct TunEndpoint API!"}; } @@ -711,24 +708,24 @@ namespace llarp return std::nullopt; } - bool Router::have_snode_whitelist() const + bool Router::has_whitelist() const { return whitelist_received; } bool Router::appears_decommed() const { - return _is_service_node and have_snode_whitelist() and node_db()->greylist().count(local_rid()); + return _is_service_node and has_whitelist() and node_db()->greylist().count(local_rid()); } bool Router::appears_funded() const { - return _is_service_node and have_snode_whitelist() and node_db()->is_connection_allowed(local_rid()); + return _is_service_node and has_whitelist() and node_db()->is_connection_allowed(local_rid()); } bool Router::appears_registered() const { - return _is_service_node and have_snode_whitelist() and node_db()->registered_routers().count(local_rid()); + return _is_service_node and has_whitelist() and node_db()->registered_routers().count(local_rid()); } bool Router::can_test_routers() const @@ -860,10 +857,12 @@ namespace llarp if (num_router_conns < num_rcs) { - log::critical( + log::debug( logcat, "Service Node connecting to {} random routers to achieve full mesh", FULL_MESH_ITERATION); _link_manager->connect_to_keep_alive(FULL_MESH_ITERATION); } + + _path_context->expire_hops(now); } void Router::_client_tick(std::chrono::milliseconds now) @@ -872,7 +871,7 @@ namespace llarp llarp::sys::service_manager->report_periodic_stats(); _pathbuild_limiter.Decay(now); - // _router_profiling.tick(); + _router_profiling.tick(); if (should_report_stats(now)) report_stats(); @@ -887,31 +886,30 @@ namespace llarp // TODO: make "use_pinned_edges" boolean to only connect to pinned edges auto n_conns = num_router_connections(); - auto num_needed = MIN_CLIENT_ROUTER_CONNS - n_conns; // if we need more sessions to routers we shall connect out to others - if (num_needed) + if (n_conns < min_client_outbounds) { + auto num_needed = min_client_outbounds - n_conns; + log::critical( logcat, "Client connecting to {} random routers to keep alive (current:{}, needed:{})", num_needed, n_conns, - MIN_CLIENT_ROUTER_CONNS); + min_client_outbounds); _link_manager->connect_to_keep_alive(num_needed); - if (num_needed == MIN_CLIENT_ROUTER_CONNS) + if (num_needed == min_client_outbounds - 1) // subtract bootstrap { - log::info(logcat, "Client has 0 router connections currently; bypassing SessionEndpoint tick..."); + log::info( + logcat, + "Client has 0 non-bootstrap router connections currently; bypassing SessionEndpoint tick..."); return; } } _session_endpoint->tick(now); - - // save profiles - if (_router_profiling.is_enabled() and _config->network.save_profiles and _router_profiling.should_save(now)) - queue_disk_io([&]() { _router_profiling.save(_profile_file); }); } void Router::tick() @@ -979,10 +977,32 @@ namespace llarp log::info(logcat, "Router initialized as service node!"); } + else if (not _testnet and _config->network.enable_profiling) + { + _router_profiling._profile_file = _config->router.data_dir / "profiles.dat"; + + log::debug(logcat, "Router profiling enabled"); + if (not fs::exists(_router_profiling._profile_file)) + { + log::debug(logcat, "No profiles file found at {}; skipping...", _router_profiling._profile_file); + } + else + { + log::debug(logcat, "Loading router profiles from {}", _router_profiling._profile_file); + _router_profiling.load_from_disk(); + } + + if (_config->network.save_profiles) + { + log::debug(logcat, "Router profile saving enabled"); + _router_profiling.start_save_ticker(*this); + } + } else { - // TESTNET: + _config->network.enable_profiling = false; _router_profiling.disable(); + log::info(logcat, "Router profiling disabled"); } // This must be constructed AFTER router creates its LocalRC @@ -1073,11 +1093,6 @@ namespace llarp return _is_running.load(); } - bool Router::is_running() const - { - return _is_running; - } - std::chrono::milliseconds Router::Uptime() const { const std::chrono::milliseconds _now = now(); @@ -1182,12 +1197,10 @@ namespace llarp _session_endpoint->stop(true); - _loop->call_later(200ms, [this] { cleanup(); }); - } + if (not _is_service_node) + _router_profiling.stop_save_ticker(); - uint32_t Router::NextPathBuildNumber() - { - return _path_build_count++; + _loop->call_later(200ms, [this] { cleanup(); }); } oxen::quic::Address Router::listen_addr() const diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 0e3dae4d5a..49decd8cb7 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -73,7 +73,7 @@ namespace llarp struct Router : std::enable_shared_from_this { - friend class NodeDB; + // friend class NodeDB; friend struct LinkManager; explicit Router( @@ -149,21 +149,15 @@ namespace llarp std::shared_ptr _config; - uint32_t _path_build_count{0}; - std::unique_ptr _rpc_server; - const std::chrono::milliseconds _random_start_delay{ - platform::is_simulation ? std::chrono::milliseconds{(llarp::randint() % 1250) + 2000} : 0s}; - std::shared_ptr _rpc_client; bool whitelist_received{false}; oxenmq::address rpc_addr; Profiling _router_profiling; - fs::path _profile_file; - int client_router_connections; + size_t min_client_outbounds{}; // should we be sending padded messages every interval? bool send_padding{false}; @@ -209,9 +203,11 @@ namespace llarp bool is_bootstrap_seed() const { return _bootstrap_seed; } - int required_num_client_conns() const { return client_router_connections; } + size_t client_outbounds_needed() const { return min_client_outbounds; } + + std::set get_current_remotes() const; - void for_each_connection(std::function func); + void for_each_connection(std::function func); const std::shared_ptr& tun_endpoint() const { return _tun; } @@ -282,7 +278,7 @@ namespace llarp /// Return true if we are operating as a service node and have received a service node /// whitelist - bool have_snode_whitelist() const; + bool has_whitelist() const; /// return true if we look like we are a decommissioned service node bool appears_decommed() const; @@ -301,7 +297,7 @@ namespace llarp std::chrono::milliseconds Uptime() const; - std::chrono::milliseconds _last_tick = 0s; + std::chrono::milliseconds _last_tick{0s}; std::function _router_close_cb; @@ -317,7 +313,9 @@ namespace llarp std::string status_line(); - bool is_running() const; + bool is_running() const { return _is_running; } + + bool is_stopping() const { return _is_stopping; } bool is_service_node() const; @@ -362,8 +360,6 @@ namespace llarp /// count the number of unique clients connected by pubkey size_t num_client_connections() const; - uint32_t NextPathBuildNumber(); - void teardown(); void cleanup(); diff --git a/llarp/util/aligned.hpp b/llarp/util/aligned.hpp index 6b3038a8ed..5b4caf5606 100644 --- a/llarp/util/aligned.hpp +++ b/llarp/util/aligned.hpp @@ -2,6 +2,7 @@ #include "formattable.hpp" #include "logging.hpp" +#include "random.hpp" #include #include @@ -17,8 +18,6 @@ extern "C" { - extern void randombytes(unsigned char* const ptr, unsigned long long sz); - extern int sodium_is_zero(const unsigned char* n, const size_t nlen); } namespace llarp @@ -298,8 +297,6 @@ namespace llarp static constexpr bool to_string_formattable = true; }; - // auto bt_printer::log_cat = log::Cat("bt_printer"); - } // namespace llarp namespace std @@ -309,9 +306,14 @@ namespace std { std::size_t operator()(const llarp::AlignedBuffer& buf) const noexcept { - std::size_t h = 0; - std::memcpy(&h, buf.data(), sizeof(std::size_t)); - return h; + if constexpr (alignof(llarp::AlignedBuffer) >= sizeof(size_t)) + return *reinterpret_cast(buf.data()); + else + { + std::size_t h{}; + std::memcpy(&h, buf.data(), sizeof(h)); + return h; + } } }; } // namespace std diff --git a/llarp/util/concept.hpp b/llarp/util/concept.hpp index add80bdbd3..9e1c698b86 100644 --- a/llarp/util/concept.hpp +++ b/llarp/util/concept.hpp @@ -8,6 +8,9 @@ namespace llarp::concepts template concept to_string_formattable = oxen::quic::concepts::ToStringFormattable; + template > + concept forward_iterable = std::forward_iterator; + #ifndef __cpp_lib_is_scoped_enum template struct is_scoped_enum_st : std::bool_constant < requires diff --git a/llarp/util/meta.hpp b/llarp/util/meta.hpp new file mode 100644 index 0000000000..d8516d78d2 --- /dev/null +++ b/llarp/util/meta.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include "concept.hpp" +#include "random.hpp" + +#include +#include + +namespace llarp::meta +{ + /** One-pass random selection algorithm + - https://en.wikipedia.org/wiki/Reservoir_sampling + */ + template ::value_type> + std::optional sample(const T& container, std::function hook) + { + size_t i = 0; + std::optional ret = std::nullopt; + + for (const auto& e : container) + { + if (not hook(e)) + continue; + + if (++i <= 1) + { + ret = e; + continue; + } + + size_t x = csrng() % (i + 1); + if (x <= 1) + ret = e; + } + + return ret; + } + + template ::value_type> + std::optional> sample_n( + const T& container, std::function hook, size_t n, bool exact = false) + { + auto ret = std::make_optional>(); + ret->reserve(n); + + size_t i = 0; + + for (const auto& e : container) + { + if (not hook(e)) + continue; + + if (++i <= n) + { + ret->emplace_back(e); + continue; + } + + size_t x = csrng() % (i + 1); + if (x < n) + (*ret)[x] = e; + } + + if (ret->size() < (exact ? n : 1)) + ret.reset(); + + return ret; + } +} // namespace llarp::meta diff --git a/llarp/util/random.hpp b/llarp/util/random.hpp new file mode 100644 index 0000000000..6a505a60a1 --- /dev/null +++ b/llarp/util/random.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "common.hpp" + +#include + +extern "C" +{ + extern void randombytes(unsigned char* const ptr, unsigned long long sz); +} + +namespace llarp +{ + struct CSRNG + { + using result_type = uint64_t; + + static constexpr uint64_t min() { return std::numeric_limits::min(); } + + static constexpr uint64_t max() { return std::numeric_limits::max(); } + + uint64_t randint() + { + uint64_t i; + randombytes((uint8_t*)&i, sizeof(i)); + return i; + } + + uint64_t operator()() { return randint(); } + }; + + extern CSRNG csrng; +} // namespace llarp From 80885fda5f1797b2bdfad3896da1970cc45c19dc Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 7 Nov 2024 08:47:47 -0800 Subject: [PATCH 22/44] fix make_scalar, call-safe, de-serialization error, etc --- llarp/contact/client_contact.cpp | 34 ++++- llarp/contact/relay_contact_local.cpp | 2 +- llarp/crypto/crypto.cpp | 90 ++---------- llarp/crypto/crypto.hpp | 17 +-- llarp/crypto/types.cpp | 9 +- llarp/handlers/session.cpp | 3 + llarp/handlers/tun.cpp | 194 ++++++++++++-------------- llarp/link/link_manager.cpp | 1 + llarp/nodedb.cpp | 24 +--- llarp/nodedb.hpp | 7 +- llarp/path/path_context.cpp | 29 ++-- llarp/path/path_context.hpp | 67 +++++---- llarp/path/path_handler.cpp | 6 +- llarp/router/router.cpp | 2 +- llarp/session/session.cpp | 4 +- llarp/session/session.hpp | 2 +- llarp/util/meta.hpp | 3 + 17 files changed, 203 insertions(+), 291 deletions(-) diff --git a/llarp/contact/client_contact.cpp b/llarp/contact/client_contact.cpp index 63b0e5315e..3bd34e3381 100644 --- a/llarp/contact/client_contact.cpp +++ b/llarp/contact/client_contact.cpp @@ -184,7 +184,7 @@ namespace llarp btdp.append("i", blinded_pubkey.to_view()); btdp.append("n", nonce.to_view()); btdp.append("t", signed_at.count()); - btdp.append("x", encrypted); + btdp.append("x", std::string_view{reinterpret_cast(encrypted.data()), encrypted.size()}); } /** EncryptedClientContact @@ -200,8 +200,13 @@ namespace llarp { blinded_pubkey.from_string(btdc.require("i")); nonce.from_string(btdc.require("n")); - blinded_pubkey.from_string(btdc.require("i")); - encrypted = btdc.require>("x"); + signed_at = std::chrono::milliseconds{btdc.require("t")}; + + // TESTNET: TOFIX: change this after oxenc span PR is merged + auto enc = btdc.require("x"); + encrypted.resize(enc.size()); + std::memcpy(encrypted.data(), enc.data(), enc.size()); + sig.from_string(btdc.require("~")); } catch (const std::exception& e) @@ -226,14 +231,33 @@ namespace llarp log::debug(logcat, "EncryptedClientContact decrypted successfully..."); cc = ClientContact{std::move(payload)}; } + else + log::warning(logcat, "Failed to decrypt EncryptedClientContact!"); return cc; } bool EncryptedClientContact::verify() const { - return crypto::verify( - blinded_pubkey, reinterpret_cast(_bt_payload.data()), _bt_payload.size(), sig); + try + { + oxenc::bt_dict_consumer btdc{_bt_payload}; + + btdc.require_signature("~", [this](ustring_view m, ustring_view s) { + if (s.size() != 64) + throw std::runtime_error{"Invalid signature: not 64 bytes"}; + + if (not crypto::verify(blinded_pubkey, m, s)) + throw std::runtime_error{"Failed to verify EncryptedClientContact signature!"}; + }); + } + catch (const std::exception& e) + { + log::warning(logcat, "Exception: {}", e.what()); + return false; + } + + return true; } bool EncryptedClientContact::is_expired(std::chrono::milliseconds now) const diff --git a/llarp/contact/relay_contact_local.cpp b/llarp/contact/relay_contact_local.cpp index 93f915346d..0eea550ce0 100644 --- a/llarp/contact/relay_contact_local.cpp +++ b/llarp/contact/relay_contact_local.cpp @@ -31,7 +31,7 @@ namespace llarp btdp.append_signature("~", [this](ustring_view to_sign) { std::array sig; - if (!crypto::sign(const_cast(sig.data()), _secret_key, to_sign)) + if (!crypto::sign(sig.data(), _secret_key, to_sign)) throw std::runtime_error{"Failed to sign RC"}; _signature = {sig.data(), sig.size()}; diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index cf545bf1b4..d0371ab242 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -317,22 +317,26 @@ namespace llarp "can't in the and by be or then before so just face it this text hurts " "to read? lokinet yolo!"; - bool crypto::make_scalar(AlignedBuffer<32>& out, const PubKey& k, uint64_t i) + std::array crypto::make_scalar(const PubKey& k, uint64_t domain) { // 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 + PubKey::SIZE); + oxenc::write_host_as_little(domain, buf.data() + 160 + PubKey::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()); + std::array n; + std::array out; + + crypto_generichash_blake2b(n.data(), n.size(), buf.data(), buf.size(), nullptr, 0); + crypto_core_ed25519_scalar_reduce(out.data(), n.data()); + + return out; } - bool crypto::derive_subkey( - uint8_t* derived, size_t derived_len, const PubKey& root_pubkey, uint64_t key_n, const AlignedBuffer<32>* hash) + bool crypto::derive_subkey(uint8_t* derived, size_t derived_len, const PubKey& root_pubkey, uint64_t key_n) { if (derived_len != PubKey::SIZE) { @@ -341,80 +345,10 @@ namespace llarp } // 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)) - { - log::error(logcat, "cannot make scalar"); - return false; - } - + std::array h = crypto::make_scalar(root_pubkey, key_n); return 0 == crypto_scalarmult_ed25519(derived, h.data(), root_pubkey.data()); } - bool crypto::derive_subkey_private( - Ed25519PrivateData& out_key, const Ed25519SecretKey& 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.to_pubkey(); - - AlignedBuffer<32> h; - if (hash) - h = *hash; - else if (not make_scalar(h, root_pubkey, key_n)) - { - log::error(logcat, "cannot make scalar"); - return false; - } - - h[0] &= 248; - h[31] &= 63; - h[31] |= 64; - - Ed25519PrivateData a = root_key.to_eddata(); - - // 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.signing_hash().begin(), a.signing_hash().end(), buf.begin() + 32); - return -1 != crypto_generichash_blake2b(out_key.signing_hash().data(), 32, buf.data(), buf.size(), nullptr, 0); - - return true; - } - void crypto::randomize(uint8_t* buf, size_t len) { randombytes(buf, len); diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index 4d0f3ad052..e94a833c5f 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -80,24 +80,11 @@ namespace llarp const SymmNonce& nonce, uspan encrypted); - bool make_scalar(AlignedBuffer<32>& out, const PubKey& k, uint64_t i); + std::array make_scalar(const PubKey& k, uint64_t domain); /// derive sub keys for public keys. hash is really only intended for /// testing ands key_n if given. - bool derive_subkey( - uint8_t* derived, - size_t derived_len, - 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( - Ed25519PrivateData& derived, - const Ed25519SecretKey& root, - uint64_t key_n, - const AlignedBuffer<32>* hash = nullptr); + bool derive_subkey(uint8_t* derived, size_t derived_len, const PubKey& root, uint64_t key_n); /// randomize buffer void randomize(uint8_t* buf, size_t len); diff --git a/llarp/crypto/types.cpp b/llarp/crypto/types.cpp index c53a2d0c20..bac0e96493 100644 --- a/llarp/crypto/types.cpp +++ b/llarp/crypto/types.cpp @@ -66,14 +66,7 @@ namespace llarp { Ed25519PrivateData ret{}; - AlignedBuffer<32> h; - - if (not crypto::make_scalar(h, to_pubkey(), domain)) - throw std::runtime_error{"Call to `make_scalar` failed in deriving private subkey!"}; - - h[0] &= 248; - h[31] &= 63; - h[31] |= 64; + std::array h = crypto::make_scalar(to_pubkey(), domain); auto a = to_eddata(); diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index fa7fc4fea3..0ca7da020f 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -351,6 +351,9 @@ namespace llarp::handlers { auto enc = client_contact.encrypt_and_sign(); + if (not enc.verify()) + log::critical(logcat, "COULD NOT VERIFY ENCRYPTEDCLIENTCONTACT"); + if (publish_client_contact(enc)) log::info(logcat, "Successfully republished updated EncryptedClientContact!"); else diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index e7a278f4dc..dc0869e00b 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -267,142 +267,124 @@ namespace llarp::handlers } } + /** DISCUSS: Can the auth objects be further simplified? + - In the original implementation, the AuthPolicy async logic was for the instance receiving the connection + request to execute its aynchronous logic and queue the authentication job + + Static Token Auth: + - In the re-designed auth paradigm, static tokens are either independantly coordinated with the exit/service + operator + - The session initiator will automatically include any static tokens that are either (A) loaded into the + config mapping or (B) passed to the lokinet-vpn cli utility + - As a result, the session initiator doesn't necessarily need an AuthPolicy object + + RPC Auth: + - Why can't the functionality of this be entirely subsumed by the RPCClient? + - If the config specifies the auth_type as RPC plus + */ void TunEndpoint::configure() { - log::debug(logcat, "{} called", __PRETTY_FUNCTION__); - auto& net_conf = _router.config()->network; - - /** DISCUSS: Can the auth objects be further simplified? - - In the original implementation, the AuthPolicy async logic was for the instance receiving the connection - request to execute its aynchronous logic and queue the authentication job - - Static Token Auth: - - In the re-designed auth paradigm, static tokens are either independantly coordinated with the exit/service - operator - - The session initiator will automatically include any static tokens that are either (A) loaded into the - config mapping or (B) passed to the lokinet-vpn cli utility - - As a result, the session initiator doesn't necessarily need an AuthPolicy object - - RPC Auth: - - Why can't the functionality of this be entirely subsumed by the RPCClient? - - If the config specifies the auth_type as RPC plus - - */ - // switch (net_conf.auth_type) - // { - // case auth::AuthType::WHITELIST: - // case auth::AuthType::OMQ: - // // The RPCAuthPolicy constructor will throw if auth_{endpoint,method} are empty - // _auth_policy = auth::make_auth_policy( - // router(), *net_conf.auth_endpoint, *net_conf.auth_method, router().lmq(), shared_from_this()); - - // std::static_pointer_cast(_auth_policy)->start(); - // break; - - // case auth::AuthType::FILE: - // _auth_policy = auth::make_auth_policy( - // router(), net_conf.auth_files, net_conf.auth_file_type); - // break; - - // case auth::AuthType::NONE: - // default: - // break; - // } + return _router.loop()->call_get([&]() { + log::debug(logcat, "{} called", __PRETTY_FUNCTION__); - _traffic_policy = net_conf.traffic_policy; - _base_ipv6_range = net_conf._base_ipv6_range; + auto& net_conf = _router.config()->network; - if (net_conf.path_alignment_timeout) - { - if (is_service_node()) - throw std::runtime_error{"Service nodes cannot specify path alignment timeout!"}; + _traffic_policy = net_conf.traffic_policy; + _base_ipv6_range = net_conf._base_ipv6_range; - _path_alignment_timeout = *net_conf.path_alignment_timeout; - } + if (net_conf.path_alignment_timeout) + { + if (is_service_node()) + throw std::runtime_error{"Service nodes cannot specify path alignment timeout!"}; + + _path_alignment_timeout = *net_conf.path_alignment_timeout; + } - _if_name = *net_conf._if_name; - _local_range = *net_conf._local_ip_range; - _local_addr = *net_conf._local_addr; - _local_base_ip = *net_conf._local_base_ip; + _if_name = *net_conf._if_name; + _local_range = *net_conf._local_ip_range; + _local_addr = *net_conf._local_addr; + _local_base_ip = *net_conf._local_base_ip; - ipv6_enabled = not _local_range.is_ipv4(); - if (ipv6_enabled and not net_conf.enable_ipv6) - throw std::runtime_error{"Config must explicitly enable IPv6 to use local range: {}"_format(_local_range)}; + ipv6_enabled = not _local_range.is_ipv4(); + if (ipv6_enabled and not net_conf.enable_ipv6) + throw std::runtime_error{ + "Config must explicitly enable IPv6 to use local range: {}"_format(_local_range)}; - _persisting_addr_file = net_conf.addr_map_persist_file; + _persisting_addr_file = net_conf.addr_map_persist_file; - if (not net_conf._reserved_local_ips.empty()) - { - for (auto& [remote, local] : net_conf._reserved_local_ips) + if (not net_conf._reserved_local_ips.empty()) { - _local_ip_mapping.insert_or_assign(local, remote); + for (auto& [remote, local] : net_conf._reserved_local_ips) + { + _local_ip_mapping.insert_or_assign(local, remote); + } } - } - log::debug(logcat, "Tun constructing IPRange iterator on local range: {}", _local_range); - _local_range_iterator = IPRangeIterator(_local_range); + log::debug(logcat, "Tun constructing IPRange iterator on local range: {}", _local_range); + _local_range_iterator = IPRangeIterator(_local_range); - _local_netaddr = NetworkAddress::from_pubkey(_router.local_rid(), not _router.is_service_node()); - _local_ip_mapping.insert_or_assign(_local_base_ip, std::move(_local_netaddr)); + _local_netaddr = NetworkAddress::from_pubkey(_router.local_rid(), not _router.is_service_node()); + _local_ip_mapping.insert_or_assign(_local_base_ip, std::move(_local_netaddr)); - vpn::InterfaceInfo info; - info.ifname = _if_name; - info.if_info = net_conf._if_info; - info.addrs.emplace_back(_local_range); + vpn::InterfaceInfo info; + info.ifname = _if_name; + info.if_info = net_conf._if_info; + info.addrs.emplace_back(_local_range); - if (net_conf.enable_ipv6 and _base_ipv6_range) - { - log::info(logcat, "{} using ipv6 range:{}", name(), *_base_ipv6_range); - info.addrs.emplace_back(*_base_ipv6_range); - } + if (net_conf.enable_ipv6 and _base_ipv6_range) + { + log::info(logcat, "{} using ipv6 range:{}", name(), *_base_ipv6_range); + info.addrs.emplace_back(*_base_ipv6_range); + } - log::debug(logcat, "{} setting up network...", name()); + log::debug(logcat, "{} setting up network...", name()); - _local_ipv6 = ipv6_enabled ? _local_addr : _local_addr.mapped_ipv4_as_ipv6(); + _local_ipv6 = ipv6_enabled ? _local_addr : _local_addr.mapped_ipv4_as_ipv6(); - if (ipv6_enabled) - { - if constexpr (not llarp::platform::is_apple) + if (ipv6_enabled) { - if (auto maybe = router().net().get_interface_ipv6_addr(_if_name)) + if constexpr (not llarp::platform::is_apple) { - _local_ipv6 = *maybe; + if (auto maybe = router().net().get_interface_ipv6_addr(_if_name)) + { + _local_ipv6 = *maybe; + } } } - } - log::info( - logcat, "{} has interface ipv4 address ({}) with ipv6 address ({})", name(), _local_addr, _local_ipv6); + log::info( + logcat, "{} has interface ipv4 address ({}) with ipv6 address ({})", name(), _local_addr, _local_ipv6); - _net_if = router().vpn_platform()->create_interface(std::move(info), &_router); - _if_name = _net_if->interface_info().ifname; + _net_if = router().vpn_platform()->create_interface(std::move(info), &_router); + _if_name = _net_if->interface_info().ifname; - log::info(logcat, "{} got network interface:{}", name(), _if_name); + log::info(logcat, "{} got network interface:{}", name(), _if_name); + + auto pkt_hook = [this]() { + for (auto pkt = _net_if->read_next_packet(); not pkt.empty(); pkt = _net_if->read_next_packet()) + { + log::trace(logcat, "packet router receiving {}", pkt.info_line()); + _packet_router->handle_ip_packet(std::move(pkt)); + } + }; - auto pkt_hook = [this]() { - for (auto pkt = _net_if->read_next_packet(); not pkt.empty(); pkt = _net_if->read_next_packet()) + if (_poller = router().loop()->add_network_interface(_net_if, std::move(pkt_hook)); not _poller) { - log::trace(logcat, "packet router receiving {}", pkt.info_line()); - _packet_router->handle_ip_packet(std::move(pkt)); + auto err = "{} failed to add network interface!"_format(name()); + log::error(logcat, "{}", err); + throw std::runtime_error{std::move(err)}; } - }; - if (_poller = router().loop()->add_network_interface(_net_if, std::move(pkt_hook)); not _poller) - { - auto err = "{} failed to add network interface!"_format(name()); - log::error(logcat, "{}", err); - throw std::runtime_error{std::move(err)}; - } - - // if (auto* quic = GetQUICTunnel()) - // { - // TODO: - // 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}}; + // }); + // } - setup_dns(); + setup_dns(); + }); } static bool is_random_snode(const dns::Message& msg) diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 091c25f847..bb34f64c8b 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1312,6 +1312,7 @@ namespace llarp _router.path_context()->put_transit_hop(std::move(transit_hop)); return prev_message.respond(messages::OK_RESPONSE, false); } + if (m.timed_out) log::info(logcat, "Upstream timed out on path build; relaying timeout"); else diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index 2e5737a477..ab0a5df136 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -210,10 +210,7 @@ namespace llarp bool NodeDB::want_rc(const RouterID& rid) const { - if (not _is_service_node) - return true; - - return known_rids.count(rid); + return known_rids.count(rid) and not rc_lookup.contains(rid); } void NodeDB::set_bootstrap_routers(BootstrapList& from_router) @@ -941,25 +938,6 @@ namespace llarp return std::nullopt; } - void NodeDB::remove_stale_rcs() - { - auto cutoff_time = time_point_now(); - - cutoff_time -= _is_service_node ? RelayContact::OUTDATED_AGE : RelayContact::LIFETIME; - - for (auto itr = rc_lookup.begin(); itr != rc_lookup.end();) - { - if (cutoff_time > itr->second.timestamp()) - { - log::info(logcat, "Pruning RC for {}, as it is too old to keep.", itr->first); - known_rcs.erase(itr->second); - itr = rc_lookup.erase(itr); - continue; - } - itr++; - } - } - bool NodeDB::put_rc(RemoteRC rc) { Lock_t l{nodedb_mutex}; diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index 4110a6b2bc..39fde5a1c0 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -168,6 +168,7 @@ namespace llarp _router.queue_disk_io(std::forward(f)); } + // Returns true iff the RID is known, but not the RC bool want_rc(const RouterID& rid) const; /// asynchronously remove the files for a set of rcs on disk given their public ident key @@ -460,12 +461,6 @@ namespace llarp } } - /// remove rcs that are older than we want to keep. For relays, this is when - /// they become "outdated" (i.e. 12hrs). Clients will hang on to them until - /// they are fully "expired" (i.e. 30 days), as the client may go offline for - /// some time and can still try to use those RCs to re-learn the network. - void remove_stale_rcs(); - /// put (or replace) the RC if we consider it valid (want_rc). returns true if put. bool put_rc(RemoteRC rc); diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index 5517330ba1..257dac7580 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -8,7 +8,7 @@ namespace llarp::path { static auto logcat = log::Cat("pathctx"); - PathContext::PathContext(RouterID local_rid) : _local_rid{std::move(local_rid)} {} + PathContext::PathContext(Router& r) : _r{r} {} void PathContext::allow_transit() { @@ -40,6 +40,9 @@ namespace llarp::path void PathContext::expire_hops(std::chrono::milliseconds now) { + _r.loop()->call_get([&]() { + + }); Lock_t l{paths_mutex}; size_t n = 0; @@ -89,32 +92,32 @@ namespace llarp::path std::shared_ptr PathContext::get_transit_hop(const HopID& path_id) const { - Lock_t l{paths_mutex}; + return _r.loop()->call_get([&]() -> std::shared_ptr { + if (auto itr = _transit_hops.find(path_id); itr != _transit_hops.end()) + return itr->second; - if (auto itr = _transit_hops.find(path_id); itr != _transit_hops.end()) - return itr->second; - - return nullptr; + return nullptr; + }); } std::shared_ptr PathContext::get_path(const HopID& hop_id) const { - Lock_t l{paths_mutex}; + return _r.loop()->call_get([&]() -> std::shared_ptr { + if (auto itr = _path_map.find(hop_id); itr != _path_map.end()) + return itr->second; - if (auto itr = _path_map.find(hop_id); itr != _path_map.end()) - return itr->second; - - return nullptr; + return nullptr; + }); } std::shared_ptr PathContext::get_path(const std::shared_ptr& hop) const { Lock_t l{paths_mutex}; - if (auto maybe_path = get_path(hop->rxid()); maybe_path) + if (auto maybe_path = get_path(hop->rxid())) return maybe_path; - if (auto maybe_path = get_path(hop->txid()); maybe_path) + if (auto maybe_path = get_path(hop->txid())) return maybe_path; return nullptr; diff --git a/llarp/path/path_context.hpp b/llarp/path/path_context.hpp index 26162438f5..1e253b08ae 100644 --- a/llarp/path/path_context.hpp +++ b/llarp/path/path_context.hpp @@ -12,57 +12,62 @@ #include #include -namespace llarp::path +namespace llarp { - struct PathContext + struct Router; + + namespace path { - explicit PathContext(RouterID local_rid); + struct PathContext + { + explicit PathContext(Router& r); - void allow_transit(); + void allow_transit(); - void reject_transit(); + void reject_transit(); - bool is_transit_allowed() const; + bool is_transit_allowed() const; - bool has_transit_hop(const std::shared_ptr& hop) const; + bool has_transit_hop(const std::shared_ptr& hop) const; - void put_transit_hop(std::shared_ptr hop); + void put_transit_hop(std::shared_ptr hop); - std::shared_ptr get_path(const std::shared_ptr& hop) const; + std::shared_ptr get_path(const std::shared_ptr& hop) const; - std::shared_ptr get_path(const HopID& hop_id) const; + std::shared_ptr get_path(const HopID& hop_id) const; - std::shared_ptr get_path_for_transfer(const HopID& topath); + std::shared_ptr get_path_for_transfer(const HopID& topath); - std::shared_ptr get_transit_hop(const HopID&) const; + std::shared_ptr get_transit_hop(const HopID&) const; - std::shared_ptr get_path_handler(const HopID& id); + std::shared_ptr get_path_handler(const HopID& id); - void add_path(std::shared_ptr p); + void add_path(std::shared_ptr p); - void drop_path(const HopID& hop_id); + void drop_path(const HopID& hop_id); - void drop_path(const std::shared_ptr& p); + void drop_path(const std::shared_ptr& p); - void drop_paths(std::vector> droplist); + void drop_paths(std::vector> droplist); - void expire_hops(std::chrono::milliseconds now); + void expire_hops(std::chrono::milliseconds now); - private: - const RouterID _local_rid; + private: + Router& _r; - using Lock_t = util::NullLock; - mutable util::NullMutex paths_mutex; + using Lock_t = util::NullLock; + mutable util::NullMutex paths_mutex; - std::unordered_map> _transit_hops; + std::unordered_map> _transit_hops; - /** TODO: - - paths are not 1:1 with upstream RID - - paths are 1:1 with edge rxIDs - */ + /** TODO: + - paths are not 1:1 with upstream RID + - paths are 1:1 with edge rxIDs + */ - std::unordered_map> _path_map; + std::unordered_map> _path_map; - bool _allow_transit{false}; - }; -} // namespace llarp::path + bool _allow_transit{false}; + }; + } // namespace path +} // namespace llarp diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index 81a6eb8d92..038e0b147b 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -212,7 +212,11 @@ namespace llarp::path ++itr; } - _router.path_context()->drop_paths(std::move(droplist)); + if (not droplist.empty()) + { + log::debug(logcat, "{} paths expired; giving path-ctx droplist", droplist.size()); + _router.path_context()->drop_paths(std::move(droplist)); + } } // called within the scope of locked mutex diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 97174ddcac..b317801041 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -658,7 +658,7 @@ namespace llarp relay_contact = LocalRC::make(identity(), _is_service_node and _public_address ? *_public_address : _listen_address); - _path_context = std::make_shared(local_rid()); + _path_context = std::make_shared(*this); _session_endpoint = std::make_shared(*this); _session_endpoint->configure(); diff --git a/llarp/session/session.cpp b/llarp/session/session.cpp index 4ba764fce2..23a70f7749 100644 --- a/llarp/session/session.cpp +++ b/llarp/session/session.cpp @@ -34,9 +34,9 @@ namespace llarp::session } bool BaseSession::send_path_control_message( - std::string method, std::string body, std::function func) + std::string method, std::string body, std::function func) { - return _current_path->send_path_control_message(std::move(method), std::move(body), std::move(func)); + return _current_path->send_path_control_message2(std::move(method), std::move(body), std::move(func)); } bool BaseSession::send_path_data_message(std::string data) diff --git a/llarp/session/session.hpp b/llarp/session/session.hpp index 320983fbc3..3664b25b5e 100644 --- a/llarp/session/session.hpp +++ b/llarp/session/session.hpp @@ -90,7 +90,7 @@ namespace llarp NetworkAddress remote() { return _remote; } bool send_path_control_message( - std::string method, std::string body, std::function func = nullptr); + std::string method, std::string body, std::function func); bool send_path_data_message(std::string data); diff --git a/llarp/util/meta.hpp b/llarp/util/meta.hpp index d8516d78d2..97edc31759 100644 --- a/llarp/util/meta.hpp +++ b/llarp/util/meta.hpp @@ -8,6 +8,9 @@ namespace llarp::meta { + /** Aggregated generalized algorithms for sort, selection, etc + */ + /** One-pass random selection algorithm - https://en.wikipedia.org/wiki/Reservoir_sampling */ From 7562253519e75e3b2b77bd044d8a0f5495676854 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 7 Nov 2024 13:48:40 -0800 Subject: [PATCH 23/44] path-mapping, storage, and fetching --- llarp/contact/client_contact.cpp | 19 +++-- llarp/contact/client_contact.hpp | 15 +++- llarp/contact/client_intro.cpp | 8 +- llarp/contact/client_intro.hpp | 1 + llarp/dns/srv_data.cpp | 10 +-- llarp/dns/srv_data.hpp | 18 ++--- llarp/handlers/session.cpp | 8 ++ llarp/link/connection.cpp | 5 +- llarp/link/connection.hpp | 17 ++-- llarp/link/link_manager.cpp | 95 ++++++++++++---------- llarp/link/link_manager.hpp | 2 +- llarp/messages/dht.hpp | 2 - llarp/net/traffic_policy.hpp | 14 ++++ llarp/path/path_context.cpp | 135 +++++++++++++++++-------------- llarp/path/path_context.hpp | 70 ++++++++-------- llarp/path/path_handler.cpp | 10 +-- llarp/router/router.cpp | 21 +++-- llarp/router/router.hpp | 1 + llarp/util/aligned.hpp | 4 +- 19 files changed, 260 insertions(+), 195 deletions(-) diff --git a/llarp/contact/client_contact.cpp b/llarp/contact/client_contact.cpp index 3bd34e3381..0ce984ba4c 100644 --- a/llarp/contact/client_contact.cpp +++ b/llarp/contact/client_contact.cpp @@ -21,7 +21,7 @@ namespace llarp ClientContact::ClientContact(std::string&& buf) { - bt_decode(oxenc::bt_dict_consumer{std::move(buf)}); + bt_decode(oxenc::bt_dict_consumer{buf}); } ClientContact ClientContact::generate( @@ -67,7 +67,7 @@ namespace llarp size_t ClientContact::bt_encode(oxenc::bt_dict_producer&& btdp) const { - btdp.append("", ClientContact::CC_VERSION); + btdp.append("", ClientContact::CC_VERSION); btdp.append("a", pubkey.to_view()); @@ -81,7 +81,7 @@ namespace llarp i.bt_encode(sublist.append_dict()); } - btdp.append("p", protos); + btdp.append("p", protos); if (not SRVs.empty()) { @@ -96,6 +96,7 @@ namespace llarp void ClientContact::bt_decode(oxenc::bt_dict_consumer&& btdc) { auto version = btdc.require(""); + if (ClientContact::CC_VERSION != version) throw std::runtime_error{ "Deserialized ClientContact with incorrect version! (Received:{}, expected:{})"_format( @@ -103,9 +104,9 @@ namespace llarp pubkey.from_string(btdc.require("a")); - if (auto maybe_subdict = btdc.maybe("e")) + if (btdc.skip_until("e")) { - exit_policy->bt_decode(oxenc::bt_dict_consumer{*maybe_subdict}); + exit_policy->bt_decode(btdc.consume_dict_consumer()); } btdc.required("i"); @@ -114,7 +115,7 @@ namespace llarp auto sublist = btdc.consume_list_consumer(); while (not sublist.is_finished()) - intros.emplace(sublist.consume_string_view()); + intros.emplace(sublist.consume_dict_consumer()); } protos = btdc.require("p"); @@ -124,7 +125,7 @@ namespace llarp auto sublist = btdc.consume_list_consumer(); while (not sublist.is_finished()) - SRVs.emplace(sublist.consume_string_view()); + SRVs.emplace(sublist.consume_dict_consumer()); } } @@ -223,7 +224,7 @@ namespace llarp std::optional EncryptedClientContact::decrypt(const PubKey& root) { std::optional cc = std::nullopt; - std::string payload{_bt_payload}; + std::string payload{reinterpret_cast(encrypted.data()), encrypted.size()}; if (crypto::xchacha20( reinterpret_cast(payload.data()), payload.size(), root.data(), nonce.data())) @@ -257,6 +258,8 @@ namespace llarp return false; } + log::info(logcat, "Successfully verified EncryptedClientContact!"); + return true; } diff --git a/llarp/contact/client_contact.hpp b/llarp/contact/client_contact.hpp index 0d2175d604..c93f3b6aae 100644 --- a/llarp/contact/client_contact.hpp +++ b/llarp/contact/client_contact.hpp @@ -117,7 +117,6 @@ namespace llarp intro_set intros; std::unordered_set SRVs; - std::chrono::milliseconds signed_at{0s}; uint16_t protos; @@ -144,6 +143,20 @@ namespace llarp void handle_updated_field(std::unordered_set srvs); public: + bool operator==(const ClientContact& other) const + { + return std::tie(derived_privatekey, pubkey, intros, SRVs, protos, exit_policy) + == std::tie( + other.derived_privatekey, + other.pubkey, + other.intros, + other.SRVs, + other.protos, + other.exit_policy); + } + + bool operator!=(const ClientContact& other) const { return !(*this == other); } + std::string to_string() const; static constexpr bool to_string_formattable = true; }; diff --git a/llarp/contact/client_intro.cpp b/llarp/contact/client_intro.cpp index e73b9f4895..d7c30e4b10 100644 --- a/llarp/contact/client_intro.cpp +++ b/llarp/contact/client_intro.cpp @@ -4,11 +4,13 @@ namespace llarp { static auto logcat = log::Cat("client-intro"); - ClientIntro::ClientIntro(std::string_view buf) + ClientIntro::ClientIntro(oxenc::bt_dict_consumer&& btdc) { - bt_decode(buf); + bt_decode(std::move(btdc)); } + ClientIntro::ClientIntro(std::string_view buf) : ClientIntro{oxenc::bt_dict_consumer{buf}} {} + void ClientIntro::bt_encode(oxenc::bt_dict_producer&& subdict) const { subdict.append("k", pivot_rid.to_view()); @@ -35,7 +37,7 @@ namespace llarp { pivot_rid.from_string(btdc.require("k")); pivot_rxid.from_string(btdc.require("p")); - expiry = std::chrono::milliseconds{btdc.require("x")}; + expiry = std::chrono::milliseconds{btdc.require("x")}; } std::string ClientIntro::to_string() const diff --git a/llarp/contact/client_intro.hpp b/llarp/contact/client_intro.hpp index 5ab92edebf..efefa75588 100644 --- a/llarp/contact/client_intro.hpp +++ b/llarp/contact/client_intro.hpp @@ -18,6 +18,7 @@ namespace llarp uint64_t version{llarp::constants::proto_version}; ClientIntro() = default; + ClientIntro(oxenc::bt_dict_consumer&&); ClientIntro(std::string_view buf); bool is_expired(std::chrono::milliseconds now = llarp::time_now_ms()) const { return now >= expiry; } diff --git a/llarp/dns/srv_data.cpp b/llarp/dns/srv_data.cpp index d9f77f4a80..f8db510b58 100644 --- a/llarp/dns/srv_data.cpp +++ b/llarp/dns/srv_data.cpp @@ -19,12 +19,11 @@ namespace llarp::dns throw std::invalid_argument{"Invalid SRVData!"}; } - SRVData::SRVData(std::string_view bt) + SRVData::SRVData(oxenc::bt_dict_consumer&& btdc) { try { - oxenc::bt_dict_consumer btdc{bt}; - bt_decode(btdc); + bt_decode(std::move(btdc)); } catch (const std::exception& e) { @@ -127,8 +126,7 @@ namespace llarp::dns { try { - oxenc::bt_dict_consumer btdc{buf}; - return bt_decode(btdc); + return bt_decode(oxenc::bt_dict_consumer{buf}); } catch (const std::exception& e) { @@ -137,7 +135,7 @@ namespace llarp::dns } } - bool SRVData::bt_decode(oxenc::bt_dict_consumer& btdc) + bool SRVData::bt_decode(oxenc::bt_dict_consumer&& btdc) { try { diff --git a/llarp/dns/srv_data.hpp b/llarp/dns/srv_data.hpp index 0db5a81394..136d71efaa 100644 --- a/llarp/dns/srv_data.hpp +++ b/llarp/dns/srv_data.hpp @@ -26,7 +26,7 @@ namespace llarp::dns { SRVData() = default; // SRVData constructor expecting a bt-encoded dictionary - explicit SRVData(std::string_view bt); + SRVData(oxenc::bt_dict_consumer&& btdc); SRVData(std::string _proto, uint16_t _priority, uint16_t _weight, uint16_t _port, std::string _target); /* bind-like formatted string for SRV records in config file @@ -65,21 +65,21 @@ namespace llarp::dns // but rather some sanity/safety checks bool is_valid() const; - /// so we can put SRVData in a std::set - bool operator<(const SRVData& other) const + auto operator<=>(const SRVData& other) const { return std::tie(service_proto, priority, weight, port, target) - < std::tie(other.service_proto, other.priority, other.weight, other.port, other.target); + <=> std::tie(other.service_proto, other.priority, other.weight, other.port, other.target); } - bool operator==(const SRVData& other) const + bool operator==(const SRVData& other) const { return (*this <=> other) == 0; } + + /// so we can put SRVData in a std::set + bool operator<(const SRVData& other) const { return std::tie(service_proto, priority, weight, port, target) - == std::tie(other.service_proto, other.priority, other.weight, other.port, other.target); + < std::tie(other.service_proto, other.priority, other.weight, other.port, other.target); } - bool operator!=(const SRVData& other) const { return !(*this == other); } - void bt_encode(oxenc::bt_dict_producer&& btdp) const; // TESTNET: TODO: remove this after refactoring IntroSet -> ClientContact @@ -90,7 +90,7 @@ namespace llarp::dns nlohmann::json ExtractStatus() const; private: - bool bt_decode(oxenc::bt_dict_consumer& btdc); + bool bt_decode(oxenc::bt_dict_consumer&& btdc); bool from_string(std::string_view srvString); }; diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index 0ca7da020f..a565720310 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -354,6 +354,14 @@ namespace llarp::handlers if (not enc.verify()) log::critical(logcat, "COULD NOT VERIFY ENCRYPTEDCLIENTCONTACT"); + if (auto decrypt = enc.decrypt(_router.local_rid())) + { + auto is_equal = client_contact == *decrypt; + log::critical(logcat, "Decrypted ClientContact is {}EQUAL to the original!", is_equal ? "" : "NOT "); + } + else + log::critical(logcat, "COULD NOT DECRYPT ENCRYPTEDCLIENTCONTACT"); + if (publish_client_contact(enc)) log::info(logcat, "Successfully republished updated EncryptedClientContact!"); else diff --git a/llarp/link/connection.cpp b/llarp/link/connection.cpp index 56fa54e8c8..b8aafa2f52 100644 --- a/llarp/link/connection.cpp +++ b/llarp/link/connection.cpp @@ -7,8 +7,9 @@ namespace llarp::link Connection::Connection( std::shared_ptr c, std::shared_ptr s, - bool is_relay) - : conn{std::move(c)}, control_stream{std::move(s)}, remote_is_relay{is_relay} + bool _is_relay, + bool _is_active) + : conn{std::move(c)}, control_stream{std::move(s)}, is_active{_is_active}, remote_is_relay{_is_relay} {} void Connection::close_quietly() diff --git a/llarp/link/connection.hpp b/llarp/link/connection.hpp index 784baf9f9a..8e3acbea3a 100644 --- a/llarp/link/connection.hpp +++ b/llarp/link/connection.hpp @@ -9,13 +9,16 @@ namespace llarp::link { struct Connection { - std::shared_ptr conn; - std::shared_ptr control_stream; - Connection( std::shared_ptr c, std::shared_ptr s, - bool is_relay = true); + bool _is_relay = true, + bool _is_active = false); + + std::shared_ptr conn; + std::shared_ptr control_stream; + + std::atomic is_active{false}; bool remote_is_relay{true}; @@ -27,8 +30,6 @@ namespace llarp::link /** TODO: - - add a boolean in this connection object - - do not continue to try to send things to the bootstarp until the connection - is actually established! - + - add a boolean in this connection object + - do not continue to try to send things to the bootstrap until the connection is actually established! */ diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index bb34f64c8b..22b824a288 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -69,8 +69,6 @@ namespace llarp return nullptr; }); - - return nullptr; } bool Endpoint::have_conn(const RouterID& remote) const @@ -182,7 +180,8 @@ namespace llarp size_t n{}; for (const auto& [_, c] : service_conns) - n += (c != nullptr); + if (c and c->is_active) + ++n; return n; }); @@ -212,7 +211,7 @@ namespace llarp std::set ret{}; for (auto& [rid, conn] : ep->service_conns) - if (conn) + if (conn and conn->is_active) ret.insert(rid); return ret; @@ -320,7 +319,7 @@ namespace llarp - stream constructor callback - will return a BTRequestStream on the first call to get_new_stream - bt stream construction contains a stream close callback that shuts down the - connection if the btstream closes unexpectedly + connection if the btstream closes unexpectedly */ auto e = quic->endpoint( _router.listen_addr(), @@ -353,7 +352,6 @@ namespace llarp { // verify as service node! bool result = node_db->registered_routers().count(other); - // result = true; // TESTNET: turn this off for non-local testing if (result) { @@ -374,7 +372,7 @@ namespace llarp itr->second = nullptr; } - log::critical( + log::debug( logcat, "{} received inbound with ongoing outbound to remote " "(RID:{}); {}!", @@ -385,10 +383,10 @@ namespace llarp return defer_to_incoming; } - log::critical(logcat, "{} accepting inbound from registered remote (RID:{})", us, other); + log::trace(logcat, "{} accepting inbound from registered remote (RID:{})", us, other); } else - log::critical( + log::info( logcat, "{} was unable to confirm remote (RID:{}) is registered; " "rejecting " @@ -400,13 +398,11 @@ namespace llarp } log::critical(logcat, "{} received unknown ALPN; rejecting connection!", us); - return false; } + else + log::critical(logcat, "Clients should not be validating inbound connections!"); - // TESTNET: change this to an error message later; just because someone tries to - // erroneously connect to a local lokinet client doesn't mean we should kill the - // program? - throw std::runtime_error{"Clients should not be validating inbound connections!"}; + return false; }); }); @@ -437,27 +433,25 @@ namespace llarp RouterID rid{ci.remote_key()}; auto control = make_control(ci, rid); + bool is_client_conn = false; - _router.loop()->call([&, ci_ptr = ci.shared_from_this(), bstream = std::move(control), rid]() { - bool is_client_conn = false; - if (auto it = ep->service_conns.find(rid); it != ep->service_conns.end()) - { - log::debug(logcat, "Configuring inbound connection from relay RID:{}", rid); - it->second = std::make_shared(std::move(ci_ptr), std::move(bstream)); - } - else if (auto it = ep->client_conns.find(rid); it != ep->client_conns.end()) - { - is_client_conn = true; - log::debug(logcat, "Configuring inbound connection from client RID:{}", rid.to_network_address(false)); - it->second = std::make_shared(std::move(ci_ptr), std::move(bstream), false); - } + if (auto it = ep->service_conns.find(rid); it != ep->service_conns.end()) + { + log::debug(logcat, "Configuring inbound connection from relay RID:{}", rid); + it->second = std::make_shared(ci.shared_from_this(), std::move(control), false, true); + } + else if (auto it = ep->client_conns.find(rid); it != ep->client_conns.end()) + { + is_client_conn = true; + log::debug(logcat, "Configuring inbound connection from client RID:{}", rid.to_network_address(false)); + it->second = std::make_shared(ci.shared_from_this(), std::move(control), false, true); + } - log::critical( - logcat, - "SERVICE NODE (RID:{}) ESTABLISHED CONNECTION TO RID:{}", - _router.local_rid(), - rid.to_network_address(!is_client_conn)); - }); + log::critical( + logcat, + "SERVICE NODE (RID:{}) ESTABLISHED CONNECTION TO RID:{}", + _router.local_rid(), + rid.to_network_address(!is_client_conn)); } void LinkManager::on_outbound_conn(oxen::quic::connection_interface& ci) @@ -465,10 +459,13 @@ namespace llarp RouterID rid{ci.remote_key()}; log::trace(logcat, "Outbound connection to {}", rid); - if (ep->have_service_conn(rid)) + if (auto conn = ep->get_service_conn(rid)) { - log::debug(logcat, "Fetched configured outbound connection to relay RID:{}", rid); + conn->is_active = true; + log::trace(logcat, "Fetched configured outbound connection to relay RID: {}", rid); } + else + log::warning(logcat, "Could not find outbound connection corresponding to RID: {}", rid); log::critical( logcat, @@ -481,13 +478,9 @@ namespace llarp void LinkManager::on_conn_open(oxen::quic::connection_interface& ci) { if (ci.is_inbound()) - { on_inbound_conn(ci); - } else - { on_outbound_conn(ci); - } } void LinkManager::on_conn_closed(oxen::quic::connection_interface& ci, uint64_t ec) @@ -498,16 +491,16 @@ namespace llarp if (auto s_itr = ep->service_conns.find(rid); s_itr != ep->service_conns.end()) { - log::critical(logcat, "Quic connection to relay RID:{} purged successfully", rid); + log::debug(logcat, "Quic connection to relay RID:{} purged successfully", rid); ep->service_conns.erase(s_itr); } else if (auto c_itr = ep->client_conns.find(rid); c_itr != ep->client_conns.end()) { - log::critical(logcat, "Quic connection to client RID:{} purged successfully", rid); + log::debug(logcat, "Quic connection to client RID:{} purged successfully", rid); ep->client_conns.erase(c_itr); } else - log::critical(logcat, "Nothing to purge for quic connection {}", ref_id); + log::trace(logcat, "Nothing to purge for quic connection {}", ref_id); }); } @@ -1122,6 +1115,15 @@ namespace llarp return m.respond(PublishClientContact::INVALID, true); } + // If the optional was nullopt, then this was a relay <-> relay request. As a result, we should NOT + // allow it to continue propagating + if (not inner_body) + { + log::critical(logcat, "Received relayed PublishClientContact request; accepting..."); + _router.contact_db().put_cc(std::move(enc)); + return m.respond(messages::OK_RESPONSE); + } + auto dht_key = enc.key(); auto local_rid = _router.local_rid(); @@ -1129,6 +1131,7 @@ namespace llarp for (const auto& rc : closest_rcs) { + log::debug(logcat, "Closest RCs to received ClientContact: {}", rc.router_id()); if (rc.router_id() == local_rid) { log::info( @@ -1142,6 +1145,10 @@ namespace llarp const auto& peer_key = closest_rcs.begin()->router_id(); + // TESTNET: testing this method + auto other_closest = _router.node_db()->find_closest_to(dht_key).router_id(); + log::info(logcat, "First-closest and closest are {}EQUAL", peer_key == other_closest ? "" : "NOT "); + log::info(logcat, "Received PublishClientContact; propagating to peer (key: {})...", peer_key); send_control_message( @@ -1152,9 +1159,10 @@ namespace llarp log::info( logcat, "Relayed PublishClientContact {}! Relaying response...", - msg ? "succeeded" + msg ? "SUCCEEDED" : msg.timed_out ? "timed out" : "failed"); + log::info(logcat, "Relayed PublishClientContact response: {}", buffer_printer{msg.body()}); prev_msg.respond(msg.body_str(), msg.is_error()); }); } @@ -1266,6 +1274,7 @@ namespace llarp logcat, "DANIEL FIX THIS: Hop is terminal hop; constructor should have flipped this boolean"); hop->terminal_hop = true; } + _router.path_context()->put_transit_hop(std::move(hop)); return m.respond(messages::OK_RESPONSE, false); } diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 7c321d710d..f764cf09ef 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -396,7 +396,7 @@ namespace llarp _is_service_node ? RELAY_KEEP_ALIVE : CLIENT_KEEP_ALIVE, std::forward(opts)...); - log::critical(logcat, "Created outbound connection with path: {}", conn_interface->path()); + log::trace(logcat, "Created outbound connection with path: {}", conn_interface->path()); auto control_stream = conn_interface->template open_stream( [](oxen::quic::Stream&, uint64_t error_code) { diff --git a/llarp/messages/dht.hpp b/llarp/messages/dht.hpp index 45182e3948..b65e27e03c 100644 --- a/llarp/messages/dht.hpp +++ b/llarp/messages/dht.hpp @@ -11,8 +11,6 @@ namespace llarp { inline const auto INVALID = messages::serialize_response({{messages::STATUS_KEY, "INVALID CC"}}); inline const auto EXPIRED = messages::serialize_response({{messages::STATUS_KEY, "EXPIRED CC"}}); - inline const auto INSUFFICIENT = messages::serialize_response({{messages::STATUS_KEY, "INSUFFICIENT NODES"}}); - inline const auto INVALID_ORDER = messages::serialize_response({{messages::STATUS_KEY, "INVALID ORDER"}}); /** Bt-encoded contents: - 'x' : EncryptedClientContact diff --git a/llarp/net/traffic_policy.hpp b/llarp/net/traffic_policy.hpp index fd3bc15524..653292e2e7 100644 --- a/llarp/net/traffic_policy.hpp +++ b/llarp/net/traffic_policy.hpp @@ -46,6 +46,13 @@ namespace llarp::net /// returns false otherwise bool matches_packet_proto(const IPPacket& pkt) const; + auto operator<=>(const ProtocolInfo& other) const + { + return std::tie(protocol, port) <=> std::tie(other.protocol, other.port); + } + + bool operator==(const ProtocolInfo& other) const { return (*this <=> other) == 0; } + bool operator<(const ProtocolInfo& other) const { return std::tie(protocol, port) < std::tie(other.protocol, other.port); @@ -74,6 +81,13 @@ namespace llarp::net bool bt_decode(std::string_view buf); nlohmann::json ExtractStatus() const; + auto operator<=>(const ExitPolicy& other) const + { + return std::tie(ranges, protocols) <=> std::tie(other.ranges, other.protocols); + } + + bool operator==(const ExitPolicy& other) const { return (*this <=> other) == 0; } + /// returns true if we allow the traffic in this ip packet /// returns false otherwise bool allow_ip_traffic(const IPPacket& pkt); diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index 257dac7580..8bd7a7602a 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -22,72 +22,70 @@ namespace llarp::path void PathContext::add_path(std::shared_ptr path) { - Lock_t l{paths_mutex}; - - _path_map.emplace(path->upstream_rxid(), path); + _r.loop()->call([&]() { _path_map.emplace(path->upstream_rxid(), path); }); } - void PathContext::drop_paths(std::vector> droplist) + void PathContext::drop_paths(std::vector droplist) { - Lock_t l{paths_mutex}; - - for (auto itr = droplist.begin(); itr != droplist.end();) - { - drop_path(*itr); - itr = droplist.erase(itr); - } + _r.loop()->call([&]() { + for (auto itr = droplist.begin(); itr != droplist.end();) + { + _drop_path(*itr); + itr = droplist.erase(itr); + } + }); } void PathContext::expire_hops(std::chrono::milliseconds now) { - _r.loop()->call_get([&]() { - - }); - Lock_t l{paths_mutex}; + _r.loop()->call([&]() { + size_t n = 0; - size_t n = 0; - - for (auto itr = _transit_hops.begin(); itr != _transit_hops.end();) - { - if (itr->second->is_expired(now)) + for (auto itr = _transit_hops.begin(); itr != _transit_hops.end();) { - itr = _transit_hops.erase(itr); - n += 1; + if (itr->second->is_expired(now)) + { + itr = _transit_hops.erase(itr); + n += 1; + } + else + ++itr; } - else - ++itr; - } - if (n) - log::info(logcat, "{} expired TransitHops purged!", n); + if (n) + log::info(logcat, "{} expired TransitHops purged!", n); + }); } void PathContext::drop_path(const HopID& hop_id) { - Lock_t l{paths_mutex}; - if (auto itr = _path_map.find(hop_id); itr != _path_map.end()) - _path_map.erase(itr); + _r.loop()->call([&]() { _drop_path(hop_id); }); } void PathContext::drop_path(const std::shared_ptr& path) { - Lock_t l{paths_mutex}; - drop_path(path->upstream_rxid()); + _r.loop()->call([&]() { drop_path(path->upstream_rxid()); }); } - bool PathContext::has_transit_hop(const std::shared_ptr& hop) const + std::tuple PathContext::path_ctx_stats() const { - Lock_t l{paths_mutex}; + return _r.loop()->call_get([&]() -> std::tuple { + return {_path_map.size(), _transit_hops.size()}; + }); + } - return _transit_hops.count(hop->rxid()) or _transit_hops.count(hop->txid()); + bool PathContext::has_transit_hop(const std::shared_ptr& hop) const + { + return _r.loop()->call_get( + [&]() { return _transit_hops.count(hop->rxid()) or _transit_hops.count(hop->txid()); }); } void PathContext::put_transit_hop(std::shared_ptr hop) { - Lock_t l{paths_mutex}; - - _transit_hops.emplace(hop->rxid(), hop); - _transit_hops.emplace(hop->txid(), hop); + _r.loop()->call([&]() { + _transit_hops.emplace(hop->rxid(), hop); + _transit_hops.emplace(hop->txid(), hop); + }); } std::shared_ptr PathContext::get_transit_hop(const HopID& path_id) const @@ -100,47 +98,60 @@ namespace llarp::path }); } - std::shared_ptr PathContext::get_path(const HopID& hop_id) const + void PathContext::_drop_path(const HopID& hop_id) { - return _r.loop()->call_get([&]() -> std::shared_ptr { - if (auto itr = _path_map.find(hop_id); itr != _path_map.end()) - return itr->second; + assert(_r.loop()->in_event_loop()); - return nullptr; - }); + if (auto itr = _path_map.find(hop_id); itr != _path_map.end()) + _path_map.erase(itr); } - std::shared_ptr PathContext::get_path(const std::shared_ptr& hop) const + std::shared_ptr PathContext::_get_path(const HopID& hop_id) const { - Lock_t l{paths_mutex}; - - if (auto maybe_path = get_path(hop->rxid())) - return maybe_path; + assert(_r.loop()->in_event_loop()); - if (auto maybe_path = get_path(hop->txid())) - return maybe_path; + if (auto itr = _path_map.find(hop_id); itr != _path_map.end()) + return itr->second; return nullptr; } - std::shared_ptr PathContext::get_path_handler(const HopID& id) + std::shared_ptr PathContext::get_path(const HopID& hop_id) const { - Lock_t l{paths_mutex}; + return _r.loop()->call_get([&]() -> std::shared_ptr { return _get_path(hop_id); }); + } - if (auto maybe_path = get_path(id)) - return maybe_path->get_parent(); + std::shared_ptr PathContext::get_path(const std::shared_ptr& hop) const + { + return _r.loop()->call_get([&]() -> std::shared_ptr { + if (auto maybe_path = _get_path(hop->rxid())) + return maybe_path; - return nullptr; + if (auto maybe_path = _get_path(hop->txid())) + return maybe_path; + + return nullptr; + }); } - std::shared_ptr PathContext::get_path_for_transfer(const HopID& id) + std::shared_ptr PathContext::get_path_handler(const HopID& id) { - Lock_t l{paths_mutex}; + return _r.loop()->call_get([&]() -> std::shared_ptr { + if (auto maybe_path = _get_path(id)) + return maybe_path->get_parent(); - if (auto itr = _transit_hops.find(id); itr != _transit_hops.end()) - return itr->second; + return nullptr; + }); + } - return nullptr; + std::shared_ptr PathContext::get_path_for_transfer(const HopID& id) + { + return _r.loop()->call_get([&]() -> std::shared_ptr { + if (auto itr = _transit_hops.find(id); itr != _transit_hops.end()) + return itr->second; + + return nullptr; + }); } } // namespace llarp::path diff --git a/llarp/path/path_context.hpp b/llarp/path/path_context.hpp index 1e253b08ae..6255749853 100644 --- a/llarp/path/path_context.hpp +++ b/llarp/path/path_context.hpp @@ -15,59 +15,63 @@ namespace llarp { struct Router; +} - namespace path +namespace llarp::path +{ + struct PathContext { - struct PathContext - { - explicit PathContext(Router& r); + explicit PathContext(Router& r); + + private: + Router& _r; + + using Lock_t = util::NullLock; + mutable util::NullMutex paths_mutex; - void allow_transit(); + // Paths are 1:1 with edge rxIDs + std::unordered_map> _path_map; - void reject_transit(); + std::unordered_map> _transit_hops; - bool is_transit_allowed() const; + bool _allow_transit{false}; - bool has_transit_hop(const std::shared_ptr& hop) const; + // internal unsafe methods + void _drop_path(const HopID& hop_id); - void put_transit_hop(std::shared_ptr hop); + std::shared_ptr _get_path(const HopID& hop_id) const; - std::shared_ptr get_path(const std::shared_ptr& hop) const; + public: + std::tuple path_ctx_stats() const; - std::shared_ptr get_path(const HopID& hop_id) const; + bool has_transit_hop(const std::shared_ptr& hop) const; - std::shared_ptr get_path_for_transfer(const HopID& topath); + void put_transit_hop(std::shared_ptr hop); - std::shared_ptr get_transit_hop(const HopID&) const; + std::shared_ptr get_path(const std::shared_ptr& hop) const; - std::shared_ptr get_path_handler(const HopID& id); + std::shared_ptr get_path(const HopID& hop_id) const; - void add_path(std::shared_ptr p); + std::shared_ptr get_path_for_transfer(const HopID& topath); - void drop_path(const HopID& hop_id); + std::shared_ptr get_transit_hop(const HopID&) const; - void drop_path(const std::shared_ptr& p); + std::shared_ptr get_path_handler(const HopID& id); - void drop_paths(std::vector> droplist); + void add_path(std::shared_ptr p); - void expire_hops(std::chrono::milliseconds now); + void drop_path(const HopID& hop_id); - private: - Router& _r; + void drop_path(const std::shared_ptr& p); - using Lock_t = util::NullLock; - mutable util::NullMutex paths_mutex; + void drop_paths(std::vector droplist); - std::unordered_map> _transit_hops; + void expire_hops(std::chrono::milliseconds now); - /** TODO: - - paths are not 1:1 with upstream RID - - paths are 1:1 with edge rxIDs - */ + void allow_transit(); - std::unordered_map> _path_map; + void reject_transit(); - bool _allow_transit{false}; - }; - } // namespace path -} // namespace llarp + bool is_transit_allowed() const; + }; +} // namespace llarp::path diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index 038e0b147b..9ec3168cf8 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -199,23 +199,23 @@ namespace llarp::path if (_paths.size() == 0) return; - std::vector> droplist; + std::vector to_drop; for (auto itr = _paths.begin(); itr != _paths.end();) { if (itr->second and itr->second->is_established() and itr->second->is_expired(now)) { - droplist.push_back(std::move(itr->second)); + to_drop.push_back(itr->second->upstream_rxid()); itr = _paths.erase(itr); } else ++itr; } - if (not droplist.empty()) + if (not to_drop.empty()) { - log::debug(logcat, "{} paths expired; giving path-ctx droplist", droplist.size()); - _router.path_context()->drop_paths(std::move(droplist)); + log::debug(logcat, "{} paths expired; giving path-ctx droplist", to_drop.size()); + _router.path_context()->drop_paths(std::move(to_drop)); } } diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index b317801041..a8e3520bdc 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -764,9 +764,10 @@ namespace llarp { auto [_in, _out, _relay, _client] = _link_manager->connection_stats(); auto [_rcs, _rids, _bstraps] = _node_db->db_stats(); + auto [_npaths, _nhops] = _path_context->path_ctx_stats(); - return "{} RCs, {} RIDs, {} bstraps, conns [{}:{} in:out, {}:{} relay:client]"_format( - _rcs, _rids, _bstraps, _in, _out, _relay, _client); + return "{} RCs, {} RIDs, {} bstraps, {} paths, {} hops, conns=[{}:{} in:out, {}:{} relay:client]"_format( + _rcs, _rids, _bstraps, _npaths, _nhops, _in, _out, _relay, _client); } void Router::report_stats() @@ -803,7 +804,6 @@ namespace llarp { log::trace(logcat, "{} called", __PRETTY_FUNCTION__); - // auto now_timepoint = std::chrono::system_clock::time_point(now); const auto& local = local_rid(); // TESTNET: @@ -876,19 +876,15 @@ namespace llarp if (should_report_stats(now)) report_stats(); - if (auto should_proceed = _node_db->tick(now); should_proceed == false) + if (not _node_db->tick(now)) { - log::debug(logcat, "Router awaiting NodeDB completion to proceed with ::tick() logic..."); + log::trace(logcat, "Router awaiting NodeDB completion to proceed with ::tick() logic..."); return; } - // _link_manager->check_persisting_conns(now); - // TODO: make "use_pinned_edges" boolean to only connect to pinned edges - auto n_conns = num_router_connections(); - // if we need more sessions to routers we shall connect out to others - if (n_conns < min_client_outbounds) + if (auto n_conns = num_router_connections(); n_conns < min_client_outbounds) { auto num_needed = min_client_outbounds - n_conns; @@ -908,8 +904,11 @@ namespace llarp return; } } + else + initial_client_connect_complete = true; - _session_endpoint->tick(now); + if (initial_client_connect_complete) + _session_endpoint->tick(now); } void Router::tick() diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 49decd8cb7..ce3fb1fd49 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -158,6 +158,7 @@ namespace llarp Profiling _router_profiling; size_t min_client_outbounds{}; + std::atomic initial_client_connect_complete{false}; // should we be sending padded messages every interval? bool send_padding{false}; diff --git a/llarp/util/aligned.hpp b/llarp/util/aligned.hpp index 5b4caf5606..9ac3909194 100644 --- a/llarp/util/aligned.hpp +++ b/llarp/util/aligned.hpp @@ -62,7 +62,9 @@ namespace llarp return ret; } - bool operator==(const AlignedBuffer& other) const { return _data == other._data; } + auto operator<=>(const AlignedBuffer& other) const { return _data <=> other._data; } + + bool operator==(const AlignedBuffer& other) const { return (*this <=> other) == 0; } bool operator!=(const AlignedBuffer& other) const { return _data != other._data; } From 48601ed3faa915e6acc5db88f49f60472e7c6f98 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Sun, 10 Nov 2024 13:53:48 -0800 Subject: [PATCH 24/44] client config - allow 1 pinned edge instead of 2 minimum - don't throw on bad addrmap.dat - client default accepted as 0.0.0.0:1090 --- llarp/bootstrap.cpp | 4 +- llarp/config/config.cpp | 7 ++- llarp/config/config.hpp | 5 +++ llarp/contact/relay_contact.cpp | 7 ++- llarp/contact/relay_contact.hpp | 18 +++++--- llarp/contact/relay_contact_remote.cpp | 4 +- llarp/dht/bucket.hpp | 12 ++++++ llarp/handlers/session.cpp | 8 +++- llarp/handlers/tun.cpp | 6 ++- llarp/handlers/tun.hpp | 3 +- llarp/link/link_manager.cpp | 42 ++++++++---------- llarp/link/link_manager.hpp | 4 +- llarp/messages/common.hpp | 1 + llarp/messages/path.hpp | 1 - llarp/nodedb.cpp | 33 ++++++++++---- llarp/nodedb.hpp | 12 +++--- llarp/path/path_handler.cpp | 12 ------ llarp/path/transit_hop.hpp | 3 +- llarp/router/router.cpp | 60 ++++++++++++++++---------- llarp/router/router.hpp | 2 +- 20 files changed, 148 insertions(+), 96 deletions(-) diff --git a/llarp/bootstrap.cpp b/llarp/bootstrap.cpp index f2ebfde023..283e028144 100644 --- a/llarp/bootstrap.cpp +++ b/llarp/bootstrap.cpp @@ -32,7 +32,7 @@ namespace llarp try { - ret &= emplace(buf).second; + ret &= emplace(buf, true).second; } catch (...) { @@ -55,7 +55,7 @@ namespace llarp oxenc::bt_list_consumer btlc{buf}; while (not btlc.is_finished()) - ret &= emplace(btlc.consume_dict_data()).second; + ret &= emplace(btlc.consume_dict_data(), true).second; } catch (const std::exception& e) { diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index 4878d7d52c..1ddce712d5 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -79,8 +79,8 @@ namespace llarp ClientOnly, Comment{ "Minimum number of routers lokinet client will attempt to maintain connections to.", - "If [network]:strict-connect is defined, the number of client <-> router connections", - "maintained by a client will be at MOST the number of pinned edges"}, + "If [network]:strict-connect is defined, the number of maintained client <-> router", + "connections set by [router]:relay-connections will be at MOST the number of pinned edges"}, [=, this](size_t arg) { if (arg < CLIENT_ROUTER_CONNECTIONS) throw std::invalid_argument{ @@ -556,7 +556,6 @@ namespace llarp "exit", Hidden, ClientOnly, - Default{false}, [this](bool arg) { allow_exit = arg; log::warning(logcat, "This option is deprecated! Use [exit]:enable instead!"); @@ -908,7 +907,6 @@ namespace llarp "network", "persist-addrmap-file", ClientOnly, - 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", @@ -956,6 +954,7 @@ namespace llarp log::warning(logcat, "{} {}", err, load_file ? "NOT FOUND" : "STALE"); } + if (not data.empty()) { std::string_view bdata{data.data(), data.size()}; diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index 152c26bf6a..f18953e382 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -33,6 +33,7 @@ namespace llarp using ConfigMap = llarp::ConfigParser::ConfigMap; inline constexpr uint16_t DEFAULT_LISTEN_PORT{1090}; + inline const oxen::quic::Address DEFAULT_CLIENT_LISTEN_ADDR{"0.0.0.0", DEFAULT_LISTEN_PORT}; inline constexpr uint16_t DEFAULT_DNS_PORT{53}; inline constexpr size_t CLIENT_ROUTER_CONNECTIONS{4}; @@ -92,6 +93,10 @@ namespace llarp bool check_rcs(const std::set& hops) const; }; + /** TODO: + - finalize supervenience of ExitConfig over deprecated config entries + */ + /// Config options related to exit node services struct ExitConfig { diff --git a/llarp/contact/relay_contact.cpp b/llarp/contact/relay_contact.cpp index b4290d52ea..b6c01aa8a2 100644 --- a/llarp/contact/relay_contact.cpp +++ b/llarp/contact/relay_contact.cpp @@ -144,9 +144,14 @@ namespace llarp return _addr.is_addressable(); } + bool RelayContact::is_outdated(std::chrono::milliseconds now) const + { + return now >= _timestamp.time_since_epoch() + OUTDATED_AGE; + } + bool RelayContact::is_expired(std::chrono::milliseconds now) const { - return age(now) >= _timestamp.time_since_epoch() + LIFETIME; + return now >= _timestamp.time_since_epoch() + LIFETIME; } std::chrono::milliseconds RelayContact::time_to_expiry(std::chrono::milliseconds now) const diff --git a/llarp/contact/relay_contact.hpp b/llarp/contact/relay_contact.hpp index 7cd317d867..23dc5221fa 100644 --- a/llarp/contact/relay_contact.hpp +++ b/llarp/contact/relay_contact.hpp @@ -52,10 +52,6 @@ namespace llarp inline static constexpr size_t MAX_RC_SIZE{1024}; - /// How long (from its signing time) before an RC is considered "stale". Relays republish - /// their RCs slightly more frequently than this so that ideally this won't happen. - inline static constexpr auto STALE_AGE{6h}; - /// How long (from its signing time) before an RC becomes "outdated". Outdated records are /// used (e.g. for path building) only if there are no newer records available, such as /// might be the case when a client has been turned off for a while. @@ -132,6 +128,9 @@ namespace llarp /// does this RC expire soon? default delta is 1 minute bool expires_within_delta(std::chrono::milliseconds now, std::chrono::milliseconds dlt = 1min) const; + /// returns true if this RC is outdated and should be fetched + bool is_outdated(std::chrono::milliseconds now = llarp::time_now_ms()) const; + /// returns true if this RC is expired and should be removed bool is_expired(std::chrono::milliseconds now) const; @@ -243,15 +242,20 @@ namespace llarp { private: // this ctor is private because it doesn't set ::_payload - explicit RemoteRC(oxenc::bt_dict_consumer btdc); + explicit RemoteRC(oxenc::bt_dict_consumer btdc, bool accept_expired = false); public: RemoteRC() = default; - explicit RemoteRC(std::string_view data) : RemoteRC{oxenc::bt_dict_consumer{data}} + explicit RemoteRC(std::string_view data, bool accept_expired = false) + : RemoteRC{oxenc::bt_dict_consumer{data}, accept_expired} { _payload = {reinterpret_cast(data.data()), data.size()}; } - explicit RemoteRC(ustring_view data) : RemoteRC{oxenc::bt_dict_consumer{data}} { _payload = data; } + explicit RemoteRC(ustring_view data, bool accept_expired = false) + : RemoteRC{oxenc::bt_dict_consumer{data}, accept_expired} + { + _payload = data; + } ~RemoteRC() = default; std::string_view view() const { return {reinterpret_cast(_payload.data()), _payload.size()}; } diff --git a/llarp/contact/relay_contact_remote.cpp b/llarp/contact/relay_contact_remote.cpp index 632b00e05d..5c31d95fac 100644 --- a/llarp/contact/relay_contact_remote.cpp +++ b/llarp/contact/relay_contact_remote.cpp @@ -6,12 +6,12 @@ namespace llarp { static auto logcat = log::Cat("relay-contact"); - RemoteRC::RemoteRC(oxenc::bt_dict_consumer btdc) + RemoteRC::RemoteRC(oxenc::bt_dict_consumer btdc, bool accept_expired) { try { bt_load(btdc); - bt_verify(btdc, /*reject_expired=*/true); + bt_verify(btdc, not accept_expired); } catch (const std::exception& e) { diff --git a/llarp/dht/bucket.hpp b/llarp/dht/bucket.hpp index 55fed34894..b31117500d 100644 --- a/llarp/dht/bucket.hpp +++ b/llarp/dht/bucket.hpp @@ -9,6 +9,12 @@ #include #include +namespace llarp::concepts +{ + template > + concept XOR_comparable = U::SIZE == PUBKEYSIZE && (std::same_as || std::same_as); +} + namespace llarp::dht { static auto logcat = log::Cat("dht.bucket"); @@ -25,6 +31,12 @@ namespace llarp::dht { return (left.router_id() ^ us) < (right.router_id() ^ us); } + + template + bool operator()(const T& left, const U& right) const + { + return (left ^ us) < (right < us); + } }; using rc_set = std::set; diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index a565720310..984d391eab 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -272,7 +272,7 @@ namespace llarp::handlers return func(std::move(maybe_intro)); } - log::debug(logcat, "Looking up clientcontact for remote (rid:{})", remote); + log::info(logcat, "Looking up clientcontact for remote (rid:{})", remote); auto response_handler = [this, remote, hook = std::move(func)](oxen::quic::message m) mutable { try @@ -554,7 +554,11 @@ namespace llarp::handlers if (auto path = _router.path_context()->get_path(intro.pivot_rxid)) { - log::info(logcat, "Found path to pivot (hopid: {}); initiating session!", intro.pivot_rxid); + log::info( + logcat, + "Found path to pivot (rid: {}, rx_id: {}); initiating session!", + intro.pivot_rid, + intro.pivot_rxid); return _make_session(std::move(remote), std::move(path), std::move(cb), is_exit); } diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index dc0869e00b..6445de3d3a 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -310,7 +310,11 @@ namespace llarp::handlers throw std::runtime_error{ "Config must explicitly enable IPv6 to use local range: {}"_format(_local_range)}; - _persisting_addr_file = net_conf.addr_map_persist_file; + if (net_conf.addr_map_persist_file) + { + _persisting_addr_file = net_conf.addr_map_persist_file; + persist_addrs = true; + } if (not net_conf._reserved_local_ips.empty()) { diff --git a/llarp/handlers/tun.hpp b/llarp/handlers/tun.hpp index cdd38269c9..94d1bd58c2 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -45,7 +45,7 @@ namespace llarp::handlers /// list of strict connect addresses for hooks // std::vector _strict_connect_addrs; /// use v6? - bool ipv6_enabled; + bool ipv6_enabled{}; std::string _if_name; @@ -60,6 +60,7 @@ namespace llarp::handlers /// a file to load / store the ephemeral address map to std::optional _persisting_addr_file = std::nullopt; + bool persist_addrs{false}; /// how long to wait for path alignment std::chrono::milliseconds _path_alignment_timeout{30s}; diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 22b824a288..4b3ec6bd75 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -174,13 +174,13 @@ namespace llarp return link_manager.router().loop()->call_get([this]() { return client_conns.size(); }); } - size_t Endpoint::num_router_conns() const + size_t Endpoint::num_router_conns(bool active_only) const { - return link_manager.router().loop()->call_get([this]() { + return link_manager.router().loop()->call_get([&]() { size_t n{}; for (const auto& [_, c] : service_conns) - if (c and c->is_active) + if (c and (active_only ? c->is_active.load() : true)) ++n; return n; @@ -193,9 +193,9 @@ namespace llarp return ep->connection_stats(); } - size_t LinkManager::get_num_connected_routers() const + size_t LinkManager::get_num_connected_routers(bool active_only) const { - return ep->num_router_conns(); + return ep->num_router_conns(active_only); } size_t LinkManager::get_num_connected_clients() const @@ -1128,11 +1128,18 @@ namespace llarp auto local_rid = _router.local_rid(); auto closest_rcs = _router.node_db()->find_many_closest_to(dht_key, path::DEFAULT_PATHS_HELD); + const auto& closest_peer = closest_rcs.begin()->router_id(); + + // TESTNET: testing this method + auto other_closest = _router.node_db()->find_closest_to(dht_key).router_id(); + log::info(logcat, "First-closest and closest are {}EQUAL", closest_peer == other_closest ? "" : "NOT "); for (const auto& rc : closest_rcs) { - log::debug(logcat, "Closest RCs to received ClientContact: {}", rc.router_id()); - if (rc.router_id() == local_rid) + auto& _rid = rc.router_id(); + + log::debug(logcat, "Closest RCs to received ClientContact: {}", _rid); + if (_rid == local_rid) { log::info( logcat, @@ -1143,16 +1150,10 @@ namespace llarp } } - const auto& peer_key = closest_rcs.begin()->router_id(); - - // TESTNET: testing this method - auto other_closest = _router.node_db()->find_closest_to(dht_key).router_id(); - log::info(logcat, "First-closest and closest are {}EQUAL", peer_key == other_closest ? "" : "NOT "); - - log::info(logcat, "Received PublishClientContact; propagating to peer (key: {})...", peer_key); + log::info(logcat, "Received PublishClientContact; propagating to closest peer (key: {})...", closest_peer); send_control_message( - peer_key, + closest_peer, "publish_cc", PublishClientContact::serialize(std::move(enc)), [prev_msg = std::move(m)](oxen::quic::message msg) mutable { @@ -1212,7 +1213,7 @@ namespace llarp send_control_message( closest_peer, - "find_cc"s, + "find_cc", FindClientContact::serialize(dht_key), [prev_msg = std::move(m)](oxen::quic::message msg) mutable { log::info( @@ -1221,6 +1222,7 @@ namespace llarp msg ? "succeeded" : msg.timed_out ? "timed out" : "failed"); + log::info(logcat, "Relayed FindClientContactMessage response: {}", buffer_printer{msg.body()}); prev_msg.respond(msg.body_str(), msg.is_error()); }); } @@ -1523,12 +1525,6 @@ namespace llarp void LinkManager::handle_initiate_session(oxen::quic::message m) { - if (not m) - { - log::info(logcat, "Initiate session message timed out!"); - return; - } - NetworkAddress initiator; service::SessionTag tag; HopID pivot_txid; @@ -1543,7 +1539,7 @@ namespace llarp std::tie(initiator, pivot_txid, tag, use_tun, maybe_auth) = InitiateSession::decrypt_deserialize(btdc, _router.identity()); - if (not _router.session_endpoint()->validate(initiator, maybe_auth)) + if (maybe_auth and not _router.session_endpoint()->validate(initiator, maybe_auth)) { log::warning(logcat, "Failed to authenticate session initiation request from remote:{}", initiator); return m.respond(InitiateSession::AUTH_DENIED, true); diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index f764cf09ef..ddb7457872 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -87,7 +87,7 @@ namespace llarp size_t num_client_conns() const; - size_t num_router_conns() const; + size_t num_router_conns(bool active_only = true) const; template bool establish_connection(KeyedAddress remote, RouterID rid, Opt&&... opts); @@ -226,7 +226,7 @@ namespace llarp std::tuple connection_stats() const; - size_t get_num_connected_routers() const; + size_t get_num_connected_routers(bool active_only = true) const; size_t get_num_connected_clients() const; diff --git a/llarp/messages/common.hpp b/llarp/messages/common.hpp index 12e29d48d9..93a2affe1b 100644 --- a/llarp/messages/common.hpp +++ b/llarp/messages/common.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index 32faf17943..41dd7e30ad 100644 --- a/llarp/messages/path.hpp +++ b/llarp/messages/path.hpp @@ -3,7 +3,6 @@ #include "common.hpp" #include -#include #include namespace llarp diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index ab0a5df136..ce598ab74b 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -84,7 +84,7 @@ namespace llarp return meta::sample_n(known_rcs, std::move(hook), n, exact); } - bool NodeDB::tick(std::chrono::milliseconds now) + bool NodeDB::tick([[maybe_unused]] std::chrono::milliseconds now) { if (_is_bootstrapping or _is_connecting_bstrap) { @@ -144,7 +144,8 @@ namespace llarp return false; } - purge_rcs(now); + // TODO: make this its own ticker + // purge_rcs(now); return true; } @@ -358,11 +359,10 @@ namespace llarp { return _router.loop()->call_get([this]() { std::vector needed; - const auto now = time_point_now(); for (const auto& [rid, rc] : rc_lookup) { - if (now - rc.timestamp() > RelayContact::OUTDATED_AGE) + if (rc.is_outdated()) needed.push_back(rid); } @@ -579,6 +579,9 @@ namespace llarp save_to_disk(); }); + _purge_ticker = _router.loop()->call_every( + 5min, [this]() { purge_rcs(); }, not _needs_bootstrap); + if (not _is_service_node) { // start these immediately if we do not need to bootstrap @@ -637,6 +640,12 @@ namespace llarp { log::info(logcat, "{} completed processing BootstrapRC fetch!", _is_service_node ? "Relay" : "Client"); + if (not _purge_ticker->is_running()) + { + log::debug(logcat, "{} activating NodeDB purge ticker", _is_service_node ? "Relay" : "Client"); + _purge_ticker->start(); + } + if (not _is_service_node) { if (not _rid_fetch_ticker->is_running()) @@ -907,11 +916,18 @@ namespace llarp if (_rc_fetch_ticker) { - log::debug(logcat, "NodeDB clearing rc fetch ticker..."); + log::debug(logcat, "NodeDB clearing RC fetch ticker..."); _rc_fetch_ticker->stop(); _rc_fetch_ticker.reset(); } + if (_purge_ticker) + { + log::debug(logcat, "NodeDB clearing purge ticker..."); + _purge_ticker->stop(); + _purge_ticker.reset(); + } + if (_flush_ticker) { log::debug(logcat, "NodeDB clearing flush ticker..."); @@ -1013,11 +1029,12 @@ namespace llarp }); } - dht::rc_set NodeDB::find_many_closest_to(llarp::dht::Key_t location, uint32_t numRouters) const + dht::rc_set NodeDB::find_many_closest_to(llarp::dht::Key_t location, uint32_t num_routers) const { - return _router.loop()->call_get([this, compare = dht::XorMetric{location}, numRouters]() -> dht::rc_set { + return _router.loop()->call_get([this, compare = dht::XorMetric{location}, num_routers]() -> dht::rc_set { dht::rc_set ret{known_rcs.begin(), known_rcs.end(), compare}; - ret.erase(std::next(ret.begin(), numRouters), ret.end()); + if (num_routers) + ret.erase(std::next(ret.begin(), num_routers), ret.end()); return ret; }); } diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index 39fde5a1c0..4af8ceac3e 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -62,6 +62,7 @@ namespace llarp // threshold amount of verifications to promote an unconfirmed rc/rid inline constexpr int CONFIRMATION_THRESHOLD{3}; + inline constexpr auto PURGE_INTERVAL{1min}; inline constexpr auto FLUSH_INTERVAL{15min}; template < @@ -188,6 +189,7 @@ namespace llarp std::shared_ptr _rid_fetch_ticker; std::shared_ptr _rc_fetch_ticker; + std::shared_ptr _purge_ticker; std::shared_ptr _flush_ticker; public: @@ -229,19 +231,19 @@ namespace llarp // TESTNET: new bootstrap/initial fetch functions void fetch_rcs(); void fetch_rids(); - void bootstrap(); // private + void bootstrap(); void stop_rid_fetch(bool success = true); void stop_rc_fetch(bool success = true); void rid_fetch_result(const RouterID& via); void rc_fetch_result(std::optional> result = std::nullopt); - void stop_bootstrap(bool success = true); // private + void stop_bootstrap(bool success = true); bool is_bootstrapping() const { return _is_bootstrapping; } bool needs_bootstrap() const { return _needs_bootstrap; } bool bootstrap_completed() const { return not(_is_bootstrapping or _needs_bootstrap); } bool is_bootstrap_node(RouterID rid) const; - void purge_rcs(std::chrono::milliseconds now); + void purge_rcs(std::chrono::milliseconds now = llarp::time_now_ms()); // Bootstrap fallback fetching // void fallback_to_bootstrap(); @@ -325,8 +327,8 @@ namespace llarp /// find the absolute closets router to a dht location RemoteRC find_closest_to(dht::Key_t location) const; - /// find many routers closest to dht key - dht::rc_set find_many_closest_to(dht::Key_t location, uint32_t numRouters) const; + /// find many routers closest to dht key; if num_routers = 0, return ALL routers + dht::rc_set find_many_closest_to(dht::Key_t location, uint32_t num_routers = 0) const; /// return true if we have an rc by its ident pubkey bool has_rc(const RouterID& pk) const; diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index 9ec3168cf8..a952f08dd4 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -342,15 +342,6 @@ namespace llarp::path log::trace(logcat, "{} called", __PRETTY_FUNCTION__); _running = false; - - // Lock_t l{paths_mutex}; - - // for (auto& [_, p] : _path_map) - // { - // if (p) - // dissociate_hop_ids(p); - // } - _paths.clear(); return true; @@ -554,9 +545,6 @@ namespace llarp::path // i from n_hops down to 0 for (int i = n_hops - 1; i >= 0; --i) { - // const auto& next_rid = i == n_hops - 1 ? path_hops[i].router_id() : path_hops[i + 1].router_id(); - // path_hops[i]._upstream = next_rid; - frames[i] = PATH::BUILD::serialize_hop(path_hops[i]); if (last_len and frames[i].size() != last_len) diff --git a/llarp/path/transit_hop.hpp b/llarp/path/transit_hop.hpp index 7ce1ce732d..eb5ba2cd44 100644 --- a/llarp/path/transit_hop.hpp +++ b/llarp/path/transit_hop.hpp @@ -1,8 +1,9 @@ #pragma once +#include "path_types.hpp" + #include #include -#include #include #include diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index a8e3520bdc..698d2aa194 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -380,10 +380,15 @@ namespace llarp if (pport.has_value() and not paddr.has_value()) throw std::runtime_error{"If public-port is specified, public-addr must be as well!"}; - if (conf.links.listen_addr) + if (conf.links.listen_addr or not _is_service_node) { - _listen_address = *conf.links.listen_addr; - log::critical(logcat, "Using listen address from link config: {}", _listen_address); + _listen_address = conf.links.listen_addr.value_or(DEFAULT_CLIENT_LISTEN_ADDR); + + log::critical( + logcat, + "Using {} listen address: {}", + conf.links.listen_addr ? "link config" : "default", + _listen_address); } else { @@ -416,7 +421,8 @@ namespace llarp if (auto maybe_addr = net().get_best_public_address(true, _port)) _public_address = std::move(*maybe_addr); else - throw std::runtime_error{"Could not find net interface on current platform!"}; + log::critical(logcat, "Could not find net interface on current platform!"); + // throw std::runtime_error{"Could not find net interface on current platform!"}; } RelayContact::BLOCK_BOGONS = conf.router.block_bogons; @@ -436,20 +442,13 @@ namespace llarp bool find_if_addr = true; - // If an ip range is set in the config, then the address and ip optionls are as well + // If an ip range is set in the config, then the address and ip optionals are as well if (not(conf._local_ip_range and !conf._local_addr->is_any_addr())) { - log::debug( - logcat, - "Finding free range for config values (range:{}, addr:{})", - conf._local_ip_range, - conf._local_addr); const auto maybe = net().find_free_range(ipv6_enabled); if (not maybe.has_value()) - { - throw std::runtime_error("cannot find free address range"); - } + throw std::runtime_error("cannot find free address range!"); _local_range = *maybe; _local_addr = _local_range.address(); @@ -533,19 +532,26 @@ namespace llarp } } - /// build a set of strictConnectPubkeys + // parse strict-connet pubkeys if (auto& conf_edges = conf.pinned_edges; not conf_edges.empty()) { if (is_service_node()) throw std::runtime_error("cannot use strict-connect option as service node"); auto n_edges = conf_edges.size(); - if (n_edges < 2) - throw std::runtime_error("Must specify more than one strict-connect router if using strict-connect"); + + // bad inputs throw in config parsing, so we should never have 0 pinned_edges + assert(n_edges); + + if (not n_edges) + throw std::runtime_error( + "Must specify at least ONE valid strict-connect relay if using [network]:strict-connect"); _node_db->pinned_edges() = std::move(conf_edges); _node_db->_strict_connect = true; + // TODO: load strict-connects as bootstraps as well + log::info(logcat, "Local client configured to strictly use {} edge relays", n_edges); if (min_client_outbounds > n_edges) @@ -562,8 +568,8 @@ namespace llarp log::info( logcat, "Local client configured to maintain {} router connections at minimum", min_client_outbounds); - if (min_client_outbounds < 2) - throw std::runtime_error{"Client cannot be configured to have less than 2 outbound router connections!"}; + if (not min_client_outbounds) + throw std::runtime_error{"Client must be configured to have at least 1 outbound router connection!"}; } void Router::init_tun() @@ -588,7 +594,9 @@ namespace llarp const auto& netid = conf.router.net_id; _is_service_node = conf.router.is_relay; - _is_exit_node = conf.network.allow_exit; + + // accept either config entry + _is_exit_node = conf.network.allow_exit || conf.exit.exit_enabled; if (_is_exit_node and _is_service_node) throw std::runtime_error{ @@ -642,7 +650,11 @@ namespace llarp process_routerconfig(); - log::critical(logcat, "public addr={}, listen addr={}", *_public_address, _listen_address); + log::critical( + logcat, + "public addr={}, listen addr={}", + _public_address ? _public_address->to_string() : "< NONE >", + _listen_address); // We process the relevant netconfig values (ip_range, address, and ip) here; in case the range or interface // is bad, we search for a free one and set it BACK into the config. Every subsequent object configuring @@ -733,9 +745,9 @@ namespace llarp return appears_funded() and not _testing_disabled; } - size_t Router::num_router_connections() const + size_t Router::num_router_connections(bool active_only) const { - return _link_manager->get_num_connected_routers(); + return _link_manager->get_num_connected_routers(active_only); } size_t Router::num_client_connections() const @@ -828,7 +840,8 @@ namespace llarp _link_manager->check_persisting_conns(now); const bool is_decommed = appears_decommed(); - auto num_router_conns = num_router_connections(); + // we want ALL router-connections, including in-progress connections because full-mesh + auto num_router_conns = num_router_connections(false); auto num_rcs = node_db()->num_rcs(); if (now >= _next_decomm_warning) @@ -886,6 +899,7 @@ namespace llarp // if we need more sessions to routers we shall connect out to others if (auto n_conns = num_router_connections(); n_conns < min_client_outbounds) { + // result could maybe be negative with this subtraction, so we HAVE to check nconns < min in the conditional auto num_needed = min_client_outbounds - n_conns; log::critical( diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index ce3fb1fd49..5c2243f9f8 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -356,7 +356,7 @@ namespace llarp std::chrono::milliseconds now() const { return llarp::time_now_ms(); } /// count the number of unique service nodes connected via pubkey - size_t num_router_connections() const; + size_t num_router_connections(bool active_only = true) const; /// count the number of unique clients connected by pubkey size_t num_client_connections() const; From 78ce7bdd91a6ffeaf97b67ed5492291f6e0a5e53 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Tue, 12 Nov 2024 12:37:11 -0800 Subject: [PATCH 25/44] request handling for sessions --- llarp/address/address.cpp | 2 +- llarp/address/address.hpp | 2 +- llarp/auth/auth.hpp | 4 +- llarp/contact/client_intro.cpp | 6 +- llarp/contact/client_intro.hpp | 13 +-- llarp/contact/tag.cpp | 4 +- llarp/contact/tag.hpp | 8 +- llarp/crypto/constants.hpp | 21 ++-- llarp/crypto/crypto.cpp | 9 +- llarp/crypto/crypto.hpp | 2 +- llarp/crypto/key_manager.cpp | 4 - llarp/crypto/key_manager.hpp | 6 -- llarp/crypto/types.hpp | 1 - llarp/handlers/session.cpp | 162 ++++++++++++++++++++++-------- llarp/handlers/session.hpp | 10 +- llarp/handlers/tun.cpp | 2 +- llarp/link/link_manager.cpp | 113 ++++++++++++--------- llarp/link/link_manager.hpp | 8 +- llarp/messages/path.hpp | 22 ++++- llarp/messages/session.hpp | 62 ++++++------ llarp/path/path.cpp | 174 ++++++--------------------------- llarp/path/path.hpp | 15 +-- llarp/path/path_context.cpp | 12 ++- llarp/path/path_handler.cpp | 32 +++--- llarp/path/path_handler.hpp | 8 +- llarp/router/router.cpp | 2 + llarp/session/map.hpp | 12 +-- llarp/session/session.cpp | 20 ++-- llarp/session/session.hpp | 22 ++--- 29 files changed, 379 insertions(+), 379 deletions(-) diff --git a/llarp/address/address.cpp b/llarp/address/address.cpp index 6a11496c68..3c8bbef313 100644 --- a/llarp/address/address.cpp +++ b/llarp/address/address.cpp @@ -6,7 +6,7 @@ namespace llarp { static auto logcat = log::Cat("address"); - std::optional NetworkAddress::from_network_addr(const std::string& arg) + std::optional NetworkAddress::from_network_addr(std::string_view arg) { std::optional ret = std::nullopt; diff --git a/llarp/address/address.hpp b/llarp/address/address.hpp index ea11ab1fd6..93c258dca3 100644 --- a/llarp/address/address.hpp +++ b/llarp/address/address.hpp @@ -60,7 +60,7 @@ namespace llarp // Will throw invalid_argument with bad input. Assumes that the network address terminates in either '.loki' // or '.snode' - static std::optional from_network_addr(const std::string& arg); + static std::optional from_network_addr(std::string_view arg); // Assumes that the pubkey passed is NOT terminated in either a '.loki' or '.snode' suffix static NetworkAddress from_pubkey(const RouterID& rid, bool is_client); diff --git a/llarp/auth/auth.hpp b/llarp/auth/auth.hpp index 0426fbd712..1a42f14d38 100644 --- a/llarp/auth/auth.hpp +++ b/llarp/auth/auth.hpp @@ -86,7 +86,7 @@ namespace llarp const std::set _files; const AuthFileType _type; mutable util::Mutex _m; - std::unordered_set _pending; + std::unordered_set _pending; /// returns an auth result for a auth info challange, opens every file until it finds a /// token matching it this is expected to be done in the IO thread AuthResult check_files(const AuthInfo& info) const; @@ -114,7 +114,7 @@ namespace llarp std::shared_ptr _omq; std::optional _omq_conn; - std::unordered_set _pending_sessions; + std::unordered_set _pending_sessions; }; } // namespace auth diff --git a/llarp/contact/client_intro.cpp b/llarp/contact/client_intro.cpp index d7c30e4b10..9c2b4f5064 100644 --- a/llarp/contact/client_intro.cpp +++ b/llarp/contact/client_intro.cpp @@ -14,7 +14,7 @@ namespace llarp void ClientIntro::bt_encode(oxenc::bt_dict_producer&& subdict) const { subdict.append("k", pivot_rid.to_view()); - subdict.append("p", pivot_rxid.to_view()); + subdict.append("p", pivot_txid.to_view()); subdict.append("x", expiry.count()); } @@ -36,12 +36,12 @@ namespace llarp void ClientIntro::bt_decode(oxenc::bt_dict_consumer&& btdc) { pivot_rid.from_string(btdc.require("k")); - pivot_rxid.from_string(btdc.require("p")); + pivot_txid.from_string(btdc.require("p")); expiry = std::chrono::milliseconds{btdc.require("x")}; } std::string ClientIntro::to_string() const { - return "[ ClientIntro pivot_rid={}, pivot_hid={}, expiry={} ]"_format(pivot_rid, pivot_rxid, expiry.count()); + return "[ ClientIntro pivot_rid={}, pivot_txid={}, expiry={} ]"_format(pivot_rid, pivot_txid, expiry.count()); } } // namespace llarp diff --git a/llarp/contact/client_intro.hpp b/llarp/contact/client_intro.hpp index efefa75588..b20e40cb89 100644 --- a/llarp/contact/client_intro.hpp +++ b/llarp/contact/client_intro.hpp @@ -13,7 +13,8 @@ namespace llarp struct ClientIntro { RouterID pivot_rid; - HopID pivot_rxid; // RXID at the pivot + + HopID pivot_txid; // TXID at the pivot std::chrono::milliseconds expiry{0s}; uint64_t version{llarp::constants::proto_version}; @@ -35,16 +36,16 @@ namespace llarp public: auto operator<=>(const ClientIntro& other) const { - return std::tie(pivot_rid, pivot_rxid, expiry, version) - <=> std::tie(other.pivot_rid, other.pivot_rxid, other.expiry, other.version); + return std::tie(pivot_rid, pivot_txid, expiry, version) + <=> std::tie(other.pivot_rid, other.pivot_txid, other.expiry, other.version); } bool operator==(const ClientIntro& other) const { return (*this <=> other) == 0; } bool operator<(const ClientIntro& other) const { - return std::tie(pivot_rid, pivot_rxid, expiry, version) - < std::tie(other.pivot_rid, other.pivot_rxid, other.expiry, other.version); + return std::tie(pivot_rid, pivot_txid, expiry, version) + < std::tie(other.pivot_rid, other.pivot_txid, other.expiry, other.version); } std::string to_string() const; @@ -68,7 +69,7 @@ namespace std { size_t operator()(const llarp::ClientIntro& i) const { - return std::hash{}(i.pivot_rid) ^ std::hash{}(i.pivot_rxid); + return std::hash{}(i.pivot_rid) ^ std::hash{}(i.pivot_txid); } }; } // namespace std diff --git a/llarp/contact/tag.cpp b/llarp/contact/tag.cpp index 3e45c88502..57dba3b9a9 100644 --- a/llarp/contact/tag.cpp +++ b/llarp/contact/tag.cpp @@ -1,6 +1,6 @@ #include "tag.hpp" -namespace llarp::service +namespace llarp { SessionTag SessionTag::make_random() { @@ -15,4 +15,4 @@ namespace llarp::service /// ensure we are in the fc00 range llarp::AlignedBuffer<16>::operator[](0) = 0xfc; } -} // namespace llarp::service +} // namespace llarp diff --git a/llarp/contact/tag.hpp b/llarp/contact/tag.hpp index 60d65cac03..fb111233f4 100644 --- a/llarp/contact/tag.hpp +++ b/llarp/contact/tag.hpp @@ -3,7 +3,7 @@ #include #include -namespace llarp::service +namespace llarp { struct SessionTag final : AlignedBuffer<16> { @@ -13,14 +13,14 @@ namespace llarp::service void Randomize() override; }; -} // namespace llarp::service +} // namespace llarp namespace std { template <> - struct hash + struct hash { - size_t operator()(const llarp::service::SessionTag& tag) const + size_t operator()(const llarp::SessionTag& tag) const { std::hash h{}; return h(std::string_view{reinterpret_cast(tag.data()), tag.size()}); diff --git a/llarp/crypto/constants.hpp b/llarp/crypto/constants.hpp index 0e13e4381e..23c786a03a 100644 --- a/llarp/crypto/constants.hpp +++ b/llarp/crypto/constants.hpp @@ -2,14 +2,13 @@ #include -static constexpr uint32_t PUBKEYSIZE = 32; -static constexpr uint32_t SECKEYSIZE = 64; -static constexpr uint32_t NONCESIZE = 24; -static constexpr uint32_t SHAREDKEYSIZE = 32; -static constexpr uint32_t HASHSIZE = 64; -static constexpr uint32_t SHORTHASHSIZE = 32; -static constexpr uint32_t HMACSECSIZE = 32; -static constexpr uint32_t SIGSIZE = 64; -static constexpr uint32_t TUNNONCESIZE = 32; -static constexpr uint32_t HMACSIZE = 32; -static constexpr uint32_t PATHIDSIZE = 16; +static constexpr uint32_t PATHIDSIZE{16}; +static constexpr uint32_t NONCESIZE{24}; +static constexpr uint32_t HMACSECSIZE{32}; +static constexpr uint32_t HMACSIZE{32}; +static constexpr uint32_t PUBKEYSIZE{32}; +static constexpr uint32_t SHAREDKEYSIZE{32}; +static constexpr uint32_t SHORTHASHSIZE{32}; +static constexpr uint32_t TUNNONCESIZE{32}; +static constexpr uint32_t SIGSIZE{64}; +static constexpr uint32_t SECKEYSIZE{64}; diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index d0371ab242..b14cc4b3f9 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -153,14 +153,9 @@ namespace llarp 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) + bool crypto::hmac(uint8_t* result, const 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; + return crypto_generichash_blake2b(result, HMACSIZE, buf, size, secret.data(), SharedSecret::SIZE) != -1; } bool crypto::sign(Signature& sig, const Ed25519SecretKey& secret, uint8_t* buf, size_t size) diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index e94a833c5f..39dcfb8ad1 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -43,7 +43,7 @@ namespace llarp bool shorthash(ShortHash&, uint8_t*, size_t size); /// blake2s 256 bit hmac - bool hmac(uint8_t*, uint8_t*, size_t, const SharedSecret&); + bool hmac(uint8_t*, const uint8_t*, size_t, const SharedSecret&); /// ed25519 sign bool sign(Signature&, const Ed25519SecretKey&, uint8_t* buf, size_t size); diff --git a/llarp/crypto/key_manager.cpp b/llarp/crypto/key_manager.cpp index f7d330c630..0eed8b9f23 100644 --- a/llarp/crypto/key_manager.cpp +++ b/llarp/crypto/key_manager.cpp @@ -81,8 +81,4 @@ namespace llarp return identity_key.derive_private_subkey_data(domain); } - // void KeyManager::encrypt(uint8_t* buf, size_t size) - // { - - // } } // namespace llarp diff --git a/llarp/crypto/key_manager.hpp b/llarp/crypto/key_manager.hpp index c81a6c0170..d443ce1c85 100644 --- a/llarp/crypto/key_manager.hpp +++ b/llarp/crypto/key_manager.hpp @@ -21,10 +21,6 @@ namespace llarp // // Keys are either read from disk if they exist and are valid (see below) or // are generated and written to disk. - // - // In addition, the KeyManager detects when the keys obsolete (e.g. as a - // result of a software upgrade) and backs up existing keys before writing - // out new ones. struct KeyManager { friend struct Router; @@ -53,8 +49,6 @@ namespace llarp Ed25519PrivateData derive_subkey(uint64_t domain = 1) const; public: - void encrypt(uint8_t* buf, size_t size); - const RouterID& router_id() const { return public_key; } }; diff --git a/llarp/crypto/types.hpp b/llarp/crypto/types.hpp index 75b79c8b3c..62759a36d5 100644 --- a/llarp/crypto/types.hpp +++ b/llarp/crypto/types.hpp @@ -80,7 +80,6 @@ namespace llarp }; using ShortHash = AlignedBuffer; - using LongHash = AlignedBuffer; struct Signature final : public AlignedBuffer {}; diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index 984d391eab..c5451bbf69 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -387,7 +387,7 @@ namespace llarp::handlers } bool SessionEndpoint::prefigure_session( - NetworkAddress initiator, service::SessionTag tag, std::shared_ptr path, bool use_tun) + NetworkAddress initiator, SessionTag tag, std::shared_ptr path, bool use_tun) { bool ret = true; assert(path->is_client_path()); @@ -442,12 +442,12 @@ namespace llarp::handlers for (const auto& [_, path] : _paths) { // If path-build is underway, don't use it - if (not path) + if (not path or not path->is_ready()) continue; log::debug(logcat, "Publishing ClientContact to pivot {}", path->pivot_rid()); - ret &= path->publish_client_contact2(ecc, [](oxen::quic::message m) { + ret &= path->publish_client_contact(ecc, [](oxen::quic::message m) { if (m) { log::critical(logcat, "Call to PublishClientContact succeeded!"); @@ -487,53 +487,128 @@ namespace llarp::handlers return ret; } + /** + + - 'k' : next HopID + - 'n' : symmetric nonce + - 'x' : encrypted payload + PATH MESSAGE ONION LAYER ('outer payload') + - 'e' : request endpoint ('path_control') + - 'p' : request payload + - 'k' : next HopID + - 'n' : symmetric nonce + - 'x' : encrypted payload + PIVOT RELAY LAYER ('intermediate payload') + - 'e' : request endpoint ('path_control') + - 'p' : request payload + - 'k' : remote client intro pivot txid, (NOT rx) + - 'n' : symmetric nonce + - 'x' : encrypted payload + REMOTE CLIENT LAYER ('inner payload') + - 'e' : request endpoint ('session_init') + - 'p' : request payload + - 'k' : shared pubkey used to derive symmetric key + - 'n' : symmetric nonce + - 'x' : encrypted payload + - 'i' : RouterID of initiator + - 'p' : HopID at the pivot taken from remote ClientIntro + - 's' : SessionTag for current session + - 't' : Use Tun interface (bool) + - 'u' : Authentication field + - bt-encoded dict, values TBD + */ + void SessionEndpoint::_make_session( - NetworkAddress remote, std::shared_ptr path, on_session_init_hook cb, bool is_exit) + NetworkAddress remote, + ClientIntro remote_intro, + std::shared_ptr path, + on_session_init_hook cb, + bool is_exit) { - auto tag = service::SessionTag::make_random(); + auto tag = SessionTag::make_random(); + + // internal payload for remote client + auto client_payload = InitiateSession::serialize_encrypt( + _router.local_rid(), + remote.router_id(), + tag, + remote_intro.pivot_txid, + fetch_auth_token(remote), + _router.using_tun_if()); + + auto inner_payload = PATH::CONTROL::serialize("session_init", std::move(client_payload)); + + // add path-control wrapping for pivot to relay to aligned path + auto& pivot = path->hops.back(); + auto onion_nonce = SymmNonce::make_random(); + crypto::onion( + reinterpret_cast(inner_payload.data()), + inner_payload.size(), + pivot.shared, + onion_nonce, + onion_nonce); + + auto pivot_payload = ONION::serialize_hop(remote_intro.pivot_txid.to_view(), onion_nonce, inner_payload); + + auto intermediate_payload = PATH::CONTROL::serialize("path_control", std::move(pivot_payload)); - // TESTNET: TODO: make this take a quic message type path->send_path_control_message( - "session_init", - InitiateSession::serialize_encrypt( - _router.local_rid(), - remote.router_id(), - tag, - path->pivot_txid(), - fetch_auth_token(remote), - _router.using_tun_if()), - [this, remote, tag, path, hook = std::move(cb), is_exit](std::string response) mutable { - if (response == messages::OK_RESPONSE) + "path_control", + std::move(intermediate_payload), + [this, remote, tag, path, hook = std::move(cb), is_exit](oxen::quic::message m) mutable { + if (m) { + log::critical(logcat, "Call to InitiateSession succeeded!"); + auto outbound = std::make_shared( remote, *this, std::move(path), std::move(tag), is_exit); auto [session, _] = _sessions.insert_or_assign(std::move(remote), std::move(outbound)); - auto msg = "SessionEndpoint successfully created and mapped InboundSession object!"; + log::info(logcat, "Outbound session to {} successfully created...", session->remote()); // TESTNET: if (session->using_tun()) { - log::info(logcat, "{} Instructing lokinet TUN device to create mapped route...", msg); + log::info(logcat, "Instructing lokinet TUN device to create mapped route..."); if (auto maybe_ip = _router.tun_endpoint()->map_session_to_local_ip(session->remote())) { log::info( logcat, "TUN device successfully routing session to remote: {}", session->remote()); - hook(*maybe_ip); - } - else - { - // TODO: if this fails, we should close the session + return hook(*maybe_ip); } + + log::critical( + logcat, + "Lokinet TUN failed to map route for session traffic to remote: {}", + session->remote()); + // TESTNET: TODO: CLOSE THIS BISH HERE } else { - log::info(logcat, "{} Starting TCP listener to route session traffic to backend...", msg); + log::info(logcat, "Starting TCP listener to route session traffic to backend..."); session->tcp_backend_listen(std::move(hook)); } } + else + { + std::optional status = std::nullopt; + try + { + oxenc::bt_dict_consumer btdc{m.body()}; + + if (auto s = btdc.maybe(messages::STATUS_KEY)) + status = s; + } + catch (const std::exception& e) + { + log::warning(logcat, "Exception: {}", e.what()); + } + + log::critical( + logcat, "Call to InitiateSession FAILED; reason: {}", status.value_or("")); + } }); } @@ -552,15 +627,16 @@ namespace llarp::handlers auto intro = intros.extract(intros.begin()).value(); auto& pivot = intro.pivot_rid; - if (auto path = _router.path_context()->get_path(intro.pivot_rxid)) - { - log::info( - logcat, - "Found path to pivot (rid: {}, rx_id: {}); initiating session!", - intro.pivot_rid, - intro.pivot_rxid); - return _make_session(std::move(remote), std::move(path), std::move(cb), is_exit); - } + // TOTHINK: why would we ever have a path keyed to remote client intro pivot txid? + // if (auto path = _router.path_context()->get_path(intro.pivot_txid)) + // { + // log::info( + // logcat, + // "Found path to pivot (rid: {}, tx_id: {}); initiating session!", + // intro.pivot_rid, + // intro.pivot_txid); + // return _make_session(std::move(remote), std::move(path), std::move(cb), is_exit); + // } log::info(logcat, "Initiating session path-build to remote:{} via pivot:{}", remote, pivot); @@ -580,17 +656,25 @@ namespace llarp::handlers log::info(logcat, "Building path -> {} : {}", path->to_string(), path->hop_string()); auto payload = build2(path); + auto upstream = path->upstream_rid(); if (not build3( - path->upstream_rid(), + std::move(upstream), std::move(payload), - [this, path, intros, remote, hook = std::move(cb), is_exit](oxen::quic::message m) mutable { + [this, + path = std::move(path), + remote_intro = std::move(intro), + intros = std::move(intros), + remote, + hook = std::move(cb), + is_exit](oxen::quic::message m) mutable { if (m) { // Do not call ::add_path() or ::path_build_succeeded() here; OutboundSession constructor will // take care of both path storage and logging in PathContext log::info(logcat, "Path build to remote:{} succeeded, initiating session!", remote); - return _make_session(std::move(remote), std::move(path), std::move(hook), is_exit); + return _make_session( + std::move(remote), std::move(remote_intro), std::move(path), std::move(hook), is_exit); } try @@ -618,7 +702,7 @@ namespace llarp::handlers _make_session_path(std::move(intros), std::move(remote), std::move(hook), is_exit); })) { - log::critical(logcat, "Error sending path_build control message for session initiation!"); + log::critical(logcat, "Error sending `path_build` control message for session initiation!"); } } @@ -639,11 +723,11 @@ namespace llarp::handlers if (cc) { *counter = 0; - log::info(logcat, "Session initiation returned successful 'lookup_client_intro'..."); + log::info(logcat, "Session initiation returned successful 'find_cc'..."); _make_session_path(std::move(cc->intros), remote, std::move(hook), is_exit); } else if (--*counter == 0) - log::warning(logcat, "Failed to initiate session at 'lookup_client_intro' (target:{})", remote); + log::warning(logcat, "Failed to initiate session at 'find_cc' (target:{})", remote); }); }); diff --git a/llarp/handlers/session.hpp b/llarp/handlers/session.hpp index 15258d073f..be9e6928cb 100644 --- a/llarp/handlers/session.hpp +++ b/llarp/handlers/session.hpp @@ -87,7 +87,7 @@ namespace llarp std::set srv_records() const { return {_srv_records.begin(), _srv_records.end()}; } template - std::shared_ptr get_session(const service::SessionTag& tag) const + std::shared_ptr get_session(const SessionTag& tag) const { return std::static_pointer_cast(_sessions.get_session(tag)); } @@ -122,7 +122,7 @@ namespace llarp bool validate(const NetworkAddress& remote, std::optional maybe_auth = std::nullopt); bool prefigure_session( - NetworkAddress initiator, service::SessionTag tag, std::shared_ptr path, bool use_tun); + NetworkAddress initiator, SessionTag tag, std::shared_ptr path, bool use_tun); // lookup SNS address to return "{pubkey}.loki" hidden service or exit node operated on a remote client void resolve_ons(std::string name, std::function)> func = nullptr); @@ -172,7 +172,11 @@ namespace llarp void _make_session_path(intro_set intros, NetworkAddress remote, on_session_init_hook cb, bool is_exit); void _make_session( - NetworkAddress remote, std::shared_ptr path, on_session_init_hook cb, bool is_exit); + NetworkAddress remote, + ClientIntro remote_intro, + std::shared_ptr path, + on_session_init_hook cb, + bool is_exit); }; } // namespace handlers diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 6445de3d3a..82513192ea 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -421,7 +421,7 @@ namespace llarp::handlers // [this, snode, msg, reply, isV6]( // const RouterID&, // std::shared_ptr s, - // [[maybe_unused]] service::SessionTag tag) { + // [[maybe_unused]] SessionTag tag) { // SendDNSReply(snode, s, msg, reply, isV6); // }); // }; diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 4b3ec6bd75..2ddc5056ea 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -230,8 +230,8 @@ namespace llarp { log::debug(logcat, "{} called", __PRETTY_FUNCTION__); - s->register_handler("path_control"s, [this, rid = remote_rid](oxen::quic::message m) mutable { - _router.loop()->call([&, msg = std::move(m)]() mutable { handle_path_control(std::move(msg), rid); }); + s->register_handler("path_control"s, [this](oxen::quic::message m) mutable { + _router.loop()->call([&, msg = std::move(m)]() mutable { handle_path_control(std::move(msg)); }); }); if (client_only) @@ -1057,31 +1057,7 @@ namespace llarp void LinkManager::handle_resolve_sns(oxen::quic::message m) { - std::string name_hash; - - try - { - name_hash = ResolveSNS::deserialize(oxenc::bt_dict_consumer{m.body()}); - } - catch (const std::exception& e) - { - log::warning(logcat, "Exception: {}", e.what()); - return m.respond(messages::ERROR_RESPONSE, true); - } - - _router.rpc_client()->lookup_ons_hash( - name_hash, [prev_msg = std::move(m)](std::optional maybe_enc) mutable { - if (maybe_enc) - { - log::info(logcat, "RPC lookup successfully returned encrypted SNS record!"); - prev_msg.respond(ResolveSNS::serialize_response(*maybe_enc)); - } - else - { - log::warning(logcat, "RPC lookup could not find SNS registry!"); - prev_msg.respond(ResolveSNS::NOT_FOUND, true); - } - }); + return _handle_resolve_sns(std::move(m)); } void LinkManager::_handle_publish_cc(oxen::quic::message m, std::optional inner_body) @@ -1341,7 +1317,7 @@ namespace llarp } } - void LinkManager::handle_path_control(oxen::quic::message m, const RouterID& /* from */) + void LinkManager::_handle_path_control(oxen::quic::message m, std::optional inner_body) { log::debug(logcat, "{} called", __PRETTY_FUNCTION__); @@ -1351,7 +1327,10 @@ namespace llarp try { - std::tie(hop_id, nonce, payload) = ONION::deserialize_hop(oxenc::bt_dict_consumer{m.body()}); + if (inner_body) + std::tie(hop_id, nonce, payload) = ONION::deserialize_hop(oxenc::bt_dict_consumer{*inner_body}); + else + std::tie(hop_id, nonce, payload) = ONION::deserialize_hop(oxenc::bt_dict_consumer{m.body()}); } catch (const std::exception& e) { @@ -1361,27 +1340,47 @@ namespace llarp auto hop = _router.path_context()->get_transit_hop(hop_id); - // TODO: when using path control messages for responses, check for the Path + // TODO: when using path control messages for responses/downstream messages, check for the Path // with the corresponding ID, de-onion, etc if (not hop) { - log::warning(logcat, "Received path control with unknown next hop (ID: {})", hop_id); - return m.respond(messages::ERROR_RESPONSE, true); + if (_is_service_node) + { + log::warning(logcat, "Received path control with unknown next hop (ID: {})", hop_id); + return m.respond(messages::ERROR_RESPONSE, true); + } + + if (auto path = _router.path_context()->get_path(hop_id)) + { + log::info(logcat, "Received path control for local client!"); + } } auto onion_nonce = nonce ^ hop->nonceXOR; - crypto::onion( - reinterpret_cast(payload.data()), payload.size(), hop->shared, onion_nonce, hop->nonceXOR); - - // if terminal hop, payload should contain a request (e.g. "ons_resolve"); handle and respond. - if (hop->terminal_hop) + // if we are relaying a path control (inner_body.has_value()), then we do NOT de-onion + if (inner_body) { - log::debug(logcat, "We are terminal hop for path request: {}", hop->to_string()); - return handle_path_request(std::move(m), std::move(payload)); + log::info(logcat, "We are pivot for relayed path request! Forwarding downstream ({})", hop->to_string()); } + else + { + crypto::onion( + reinterpret_cast(payload.data()), + payload.size(), + hop->shared, + onion_nonce, + hop->nonceXOR); - log::debug(logcat, "We are intermediate hop for path request: {}", hop->to_string()); + // if terminal hop, payload should contain a request (e.g. "ons_resolve"); handle and respond. + if (hop->terminal_hop) + { + log::debug(logcat, "We are terminal hop for path request: {}", hop->to_string()); + return handle_path_request(std::move(m), std::move(payload)); + } + + log::debug(logcat, "We are intermediate hop for path request: {}", hop->to_string()); + } auto hop_is_rx = hop->rxid() == hop_id; @@ -1434,6 +1433,11 @@ namespace llarp }); } + void LinkManager::handle_path_control(oxen::quic::message m) + { + return _handle_path_control(std::move(m)); + } + void LinkManager::handle_path_data_message(bstring message) { HopID hop_id; @@ -1519,14 +1523,20 @@ namespace llarp log::debug(logcat, "Received path control request (`{}`); invoking endpoint...", endpoint); std::invoke(it->second, this, std::move(m), std::move(body)); } + else if (endpoint == "path_control") + { + log::warning(logcat, "Path control should have been invoked in the last conditional!"); + log::debug(logcat, "Received path control relay request..."); + return _handle_path_control(std::move(m), std::move(body)); + } else log::warning(logcat, "Received path control request (`{}`), which has no local handler!", endpoint); } - void LinkManager::handle_initiate_session(oxen::quic::message m) + void LinkManager::_handle_initiate_session(oxen::quic::message m, std::optional inner_body) { NetworkAddress initiator; - service::SessionTag tag; + SessionTag tag; HopID pivot_txid; bool use_tun; std::optional maybe_auth = std::nullopt; @@ -1534,15 +1544,17 @@ namespace llarp try { - oxenc::bt_dict_consumer btdc{m.body()}; - - std::tie(initiator, pivot_txid, tag, use_tun, maybe_auth) = - InitiateSession::decrypt_deserialize(btdc, _router.identity()); + if (inner_body) + std::tie(initiator, pivot_txid, tag, use_tun, maybe_auth) = + InitiateSession::decrypt_deserialize(oxenc::bt_dict_consumer{*inner_body}, _router.identity()); + else + std::tie(initiator, pivot_txid, tag, use_tun, maybe_auth) = + InitiateSession::decrypt_deserialize(oxenc::bt_dict_consumer{m.body()}, _router.identity()); if (maybe_auth and not _router.session_endpoint()->validate(initiator, maybe_auth)) { log::warning(logcat, "Failed to authenticate session initiation request from remote:{}", initiator); - return m.respond(InitiateSession::AUTH_DENIED, true); + return m.respond(InitiateSession::AUTH_ERROR, true); } path_ptr = _router.path_context()->get_path(pivot_txid); @@ -1550,7 +1562,7 @@ namespace llarp if (not path_ptr) { log::warning(logcat, "Failed to find local path corresponding to session over pivot: {}", pivot_txid); - return m.respond(messages::ERROR_RESPONSE, true); + return m.respond(InitiateSession::BAD_PATH, true); } if (_router.session_endpoint()->prefigure_session( @@ -1570,6 +1582,11 @@ namespace llarp m.respond(messages::ERROR_RESPONSE, true); } + void LinkManager::handle_initiate_session(oxen::quic::message m) + { + return _handle_initiate_session(std::move(m)); + } + void LinkManager::handle_path_latency(oxen::quic::message m) { try diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index ddb7457872..5df56f8024 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -258,9 +258,11 @@ namespace llarp void handle_resolve_sns(oxen::quic::message); // Inner handlers for relayed requests + void _handle_path_control(oxen::quic::message, std::optional = std::nullopt); void _handle_publish_cc(oxen::quic::message, std::optional = std::nullopt); void _handle_find_cc(oxen::quic::message, std::optional = std::nullopt); void _handle_resolve_sns(oxen::quic::message, std::optional = std::nullopt); + void _handle_initiate_session(oxen::quic::message, std::optional = std::nullopt); // Path messages void handle_path_build(oxen::quic::message, const RouterID& from); // relay @@ -285,12 +287,14 @@ namespace llarp // then respond (onioned) back along the path. std::unordered_map)> path_requests = { + {"path_control"sv, &LinkManager::_handle_path_control}, {"publish_cc"sv, &LinkManager::_handle_publish_cc}, {"find_cc"sv, &LinkManager::_handle_find_cc}, - {"resolve_sns"sv, &LinkManager::_handle_resolve_sns}}; + {"resolve_sns"sv, &LinkManager::_handle_resolve_sns}, + {"session_init"sv, &LinkManager::_handle_initiate_session}}; // Path relaying - void handle_path_control(oxen::quic::message, const RouterID& from); + void handle_path_control(oxen::quic::message); void handle_path_request(oxen::quic::message m, std::string payload); diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index 41dd7e30ad..d27728f7b7 100644 --- a/llarp/messages/path.hpp +++ b/llarp/messages/path.hpp @@ -39,6 +39,26 @@ namespace llarp return std::move(btdp).str(); } + inline static std::tuple deserialize(oxenc::bt_dict_consumer&& btdc) + { + RouterID rid; + std::string payload; + SymmNonce nonce; + + try + { + rid.from_string(btdc.require("k")); + nonce.from_string(btdc.require("n")); + payload = btdc.require("x"); + } + catch (const std::exception& e) + { + throw std::runtime_error{"Exception caught deserializing onion data: {}"_format(e.what())}; + } + + return {std::move(rid), std::move(nonce), std::move(payload)}; + } + inline static std::tuple deserialize_hop(oxenc::bt_dict_consumer&& btdc) { HopID hop_id; @@ -109,7 +129,7 @@ namespace llarp crypto::derive_encrypt_outer_wrapping( ephemeral_key, hop.shared, hop.nonce, hop.router_id(), to_uspan(hop_payload)); - // generate nonceXOR value self->hop->pathKey + // generate nonceXOR value ShortHash xor_hash; crypto::shorthash(xor_hash, hop.shared.data(), hop.shared.size()); diff --git a/llarp/messages/session.hpp b/llarp/messages/session.hpp index 11a0049191..0d0e1a47d7 100644 --- a/llarp/messages/session.hpp +++ b/llarp/messages/session.hpp @@ -1,6 +1,6 @@ #pragma once -#include "common.hpp" +#include "path.hpp" #include #include @@ -9,11 +9,11 @@ namespace llarp { /** Fields for initiating sessions: + - 'k' : shared pubkey used to derive symmetric key - 'n' : symmetric nonce - - 's' : shared pubkey used to derive symmetric key - 'x' : encrypted payload - 'i' : RouterID of initiator - - 'p' : HopID at the pivot node of the newly constructed path + - 'p' : HopID at the pivot taken from remote ClientIntro - 's' : SessionTag for current session - 't' : Use Tun interface (bool) - 'u' : Authentication field @@ -23,14 +23,13 @@ namespace llarp { static auto logcat = llarp::log::Cat("session-init"); - inline constexpr auto auth_denied = "AUTH_DENIED"sv; - - inline const auto AUTH_DENIED = messages::serialize_response({{messages::STATUS_KEY, auth_denied}}); + inline const auto AUTH_ERROR = messages::serialize_response({{messages::STATUS_KEY, "AUTH ERROR"}}); + inline const auto BAD_PATH = messages::serialize_response({{messages::STATUS_KEY, "BAD PATH"}}); inline static std::string serialize_encrypt( const RouterID& local, const RouterID& remote, - service::SessionTag& tag, + SessionTag& tag, HopID pivot_txid, std::optional auth_token, bool use_tun) @@ -53,54 +52,57 @@ namespace llarp payload = std::move(btdp).str(); } - Ed25519SecretKey shared_key; - crypto::encryption_keygen(shared_key); + Ed25519SecretKey ephemeral_key; + crypto::identity_keygen(ephemeral_key); SharedSecret shared; auto nonce = SymmNonce::make_random(); - crypto::derive_encrypt_outer_wrapping(shared_key, shared, nonce, remote, to_uspan(payload)); - - oxenc::bt_dict_producer btdp; + crypto::derive_encrypt_outer_wrapping(ephemeral_key, shared, nonce, remote, to_uspan(payload)); - btdp.append("n", nonce.to_view()); - btdp.append("s", shared_key.to_pubkey().to_view()); - btdp.append("x", payload); - - return std::move(btdp).str(); + return ONION::serialize_hop(ephemeral_key.to_pubkey().to_view(), nonce, std::move(payload)); } - catch (...) + catch (const std::exception& e) { - log::error(messages::logcat, "Error: InitiateSessionMessage failed to bt encode contents"); + log::error(messages::logcat, "Exception caught encrypting session initiation message: {}", e.what()); throw; } }; - inline static std::tuple> - decrypt_deserialize(oxenc::bt_dict_consumer& btdc, const Ed25519SecretKey& local) + inline static std::tuple> + decrypt_deserialize(oxenc::bt_dict_consumer&& btdc, const Ed25519SecretKey& local) { SymmNonce nonce; - RouterID shared_pubkey; - ustring payload; + PubKey shared_pubkey; + std::string payload; SharedSecret shared; try { - nonce = SymmNonce::make(btdc.require("n")); - shared_pubkey = RouterID{btdc.require("s")}; - payload = btdc.require("x"); + std::tie(shared_pubkey, nonce, payload) = ONION::deserialize(std::move(btdc)); + } + catch (const std::exception& e) + { + log::warning(logcat, "Exception caught deserializing hop dict: {}", e.what()); + throw; + } + try + { crypto::derive_decrypt_outer_wrapping(local, shared, shared_pubkey, nonce, to_uspan(payload)); { - RouterID remote; - service::SessionTag tag; + NetworkAddress initiator; + SessionTag tag; HopID pivot_txid; bool use_tun; std::optional maybe_auth = std::nullopt; - remote.from_string(btdc.require("i")); - auto initiator = NetworkAddress::from_pubkey(remote, true); + if (auto maybe_remote = NetworkAddress::from_network_addr(btdc.require("i"))) + initiator = *maybe_remote; + else + throw std::runtime_error{"Invalid NetworkAddress!"}; + pivot_txid.from_string(btdc.require("p")); tag.from_string(btdc.require("s")); use_tun = btdc.require("t"); diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 76591c104c..1bea574097 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -39,6 +39,8 @@ namespace llarp::path - First hop RXID is unique, the rest are the previous hop TXID - Last hop upstream is it's own RID, the rest are the next hop RID - First hop downstream is client's RID, the rest are the previous hop RID + - Local hop RXID is random, TXID is first hop RXID + - Local hop upstream is first hop RID, downstream is local instance RID */ hops[i]._rid = hop_rcs[i].router_id(); @@ -71,14 +73,22 @@ namespace llarp::path hops.back().terminal_hop = true; + // _local_hop = std::make_shared(); + // _local_hop->_rid = _router.local_rid(); + // _local_hop->_upstream = hops.front()._rid; + // _local_hop->_downstream = _local_hop->_rid; + // _local_hop->_rxid = HopID::make_random(); + // _local_hop->_txid = hops.front()._rxid; + // _local_hop->terminal_hop = true; + log::info(logcat, "Path populated with hops: {}", hop_string()); // initialize parts of the clientintro intro.pivot_rid = hops.back().router_id(); - intro.pivot_rxid = hops.back()._rxid; + intro.pivot_txid = hops.back()._txid; log::debug( - logcat, "Path client intro holding pivot_rid ({}) and pivot_rxid ({})", intro.pivot_rid, intro.pivot_rxid); + logcat, "Path client intro holding pivot_rid ({}) and pivot_rxid ({})", intro.pivot_rid, intro.pivot_txid); } void Path::link_session(recv_session_dgram_cb cb) @@ -138,41 +148,39 @@ namespace llarp::path bool Path::obtain_exit( const Ed25519SecretKey& sk, uint64_t flag, std::string tx_id, std::function func) { - return send_path_control_message2( + return send_path_control_message( "obtain_exit", ObtainExitMessage::sign_and_serialize(sk, flag, std::move(tx_id)), std::move(func)); } bool Path::close_exit(const Ed25519SecretKey& sk, std::string tx_id, std::function func) { - return send_path_control_message2( + return send_path_control_message( "close_exit", CloseExitMessage::sign_and_serialize(sk, std::move(tx_id)), std::move(func)); } bool Path::find_client_contact(const dht::Key_t& location, std::function func) { - return send_path_control_message2("find_cc", FindClientContact::serialize(location), std::move(func)); + return send_path_control_message("find_cc", FindClientContact::serialize(location), std::move(func)); } - bool Path::publish_client_contact2(const EncryptedClientContact& ecc, std::function func) + bool Path::publish_client_contact(const EncryptedClientContact& ecc, std::function func) { - return send_path_control_message2("publish_cc", PublishClientContact::serialize(ecc), std::move(func)); + return send_path_control_message("publish_cc", PublishClientContact::serialize(ecc), std::move(func)); } bool Path::resolve_sns(std::string_view name, std::function func) { - return send_path_control_message2("resolve_sns", ResolveSNS::serialize(name), std::move(func)); + return send_path_control_message("resolve_sns", ResolveSNS::serialize(name), std::move(func)); } void Path::enable_exit_traffic() { log::info(logcat, "{} {} granted exit", name(), pivot_rid()); - // _role |= ePathRoleExit; } void Path::mark_exit_closed() { log::info(logcat, "{} hd its exit closed", name()); - // _role &= ePathRoleExit; } std::string Path::make_path_message(std::string inner_payload) @@ -200,7 +208,7 @@ namespace llarp::path return _router.send_data_message(upstream_rid(), std::move(outer_payload)); } - bool Path::send_path_control_message2( + bool Path::send_path_control_message( std::string endpoint, std::string body, std::function func) { auto inner_payload = PATH::CONTROL::serialize(std::move(endpoint), std::move(body)); @@ -209,72 +217,6 @@ namespace llarp::path return _router.send_control_message(upstream_rid(), "path_control", std::move(outer_payload), std::move(func)); } - bool Path::send_path_control_message(std::string endpoint, std::string body, std::function func) - { - auto inner_payload = PATH::CONTROL::serialize(std::move(endpoint), std::move(body)); - auto outer_payload = make_path_message(std::move(inner_payload)); - - return _router.send_control_message( - upstream_rid(), - "path_control", - std::move(outer_payload), - [response_cb = std::move(func), weak = weak_from_this()](oxen::quic::message m) mutable { - auto self = weak.lock(); - if (not self) - { - log::warning(logcat, "Received response to path control message with non-existent path!"); - return; - } - - // TODO: DISCUSS: do we want to allow empty callback here? - if (not response_cb) - { - log::warning(logcat, "Received response to path control message with no response callback!"); - return; - } - - log::debug(logcat, "Received response to path control message: {}", buffer_printer{m.body()}); - - if (m) - log::info(logcat, "Path control message returned successfully!"); - else if (m.timed_out) - log::warning(logcat, "Path control message returned as time out!"); - else - log::warning(logcat, "Path control message returned as error!"); - - return response_cb(m.body_str()); - - // TODO: onion encrypt path message responses - // HopID hop_id; - // SymmNonce nonce; - // std::string payload; - - // try - // { - // std::tie(hop_id, nonce, payload) = ONION::deserialize_hop(oxenc::bt_dict_consumer{m.body()}); - // } - // catch (const std::exception& e) - // { - // log::warning(logcat, "Exception parsing path control message response: {}", e.what()); - // return response_cb(messages::ERROR_RESPONSE); - // } - - // for (const auto& hop : self->hops) - // { - // nonce = crypto::onion( - // reinterpret_cast(payload.data()), - // payload.size(), - // hop.shared, - // nonce, - // hop.nonceXOR); - // } - - // // TODO: DISCUSS: - // // Parsing and handling of the contents (errors, etc.) is the currently responsibility of the - // callback response_cb(std::move(payload)); - }); - } - bool Path::is_ready(std::chrono::milliseconds now) const { return _established ? !is_expired(now) : false; @@ -288,6 +230,16 @@ namespace llarp::path return nullptr; } + // std::shared_ptr Path::local_hop() + // { + // return _local_hop; + // } + + // const std::shared_ptr& Path::local_hop() const + // { + // return _local_hop; + // } + RouterID Path::upstream_rid() { return hops.front().router_id(); @@ -387,74 +339,6 @@ namespace llarp::path return obj; } - void Path::rebuild() - { - if (auto parent = handler.lock()) - { - auto prev_upstream_rxid = upstream_rxid(); - - if (auto new_hops = parent->aligned_hops_to_remote(pivot_rid())) - { - populate_internals(*new_hops); - log::info(logcat, "{} rebuilding new path to pivot {}", name(), to_string()); - - auto self = shared_from_this(); - auto payload = parent->build2(self); - auto upstream = upstream_rid(); - - if (not parent->build3( - std::move(upstream), - std::move(payload), - [new_path = std::move(self), parent = parent, prev_rxid = prev_upstream_rxid]( - oxen::quic::message m) mutable { - if (m) - { - log::critical(logcat, "PATH ESTABLISHED: {}", new_path->hop_string()); - parent->drop_path(prev_rxid); - return parent->path_build_succeeded(std::move(new_path)); - } - - try - { - if (m.timed_out) - { - log::warning(logcat, "Path build request timed out!"); - } - else - { - oxenc::bt_dict_consumer d{m.body()}; - auto status = d.require(messages::STATUS_KEY); - log::warning(logcat, "Path build returned failure status: {}", status); - } - } - catch (const std::exception& e) - { - log::warning( - logcat, - "Exception caught parsing path build response: {}; input: {}", - e.what(), - m.body()); - } - - parent->path_build_failed(std::move(new_path), m.timed_out); - })) - { - log::warning(logcat, "Error sending path_build control message"); - } - } - else - { - log::warning(logcat, "Could not find new hops to rebuild path to pivot {}", to_string()); - } - - parent->drop_path(prev_upstream_rxid); - } - else - { - log::warning(logcat, "Path ({}) died with no parent to rebuild!", to_string()); - } - } - bool Path::SendLatencyMessage(Router*) { // const auto now = r->now(); diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index d63266fb6b..83d4dc6123 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -42,6 +42,7 @@ namespace llarp struct Path : public std::enable_shared_from_this { friend struct PathHandler; + friend class handlers::SessionEndpoint; friend struct llarp::Profiling; Path( @@ -52,7 +53,10 @@ namespace llarp bool is_client = false); protected: + // hops on constructed path std::vector hops; + // local hop info for onioned responses and session messages + // std::shared_ptr _local_hop{}; std::weak_ptr handler; ClientIntro intro{}; @@ -85,19 +89,13 @@ namespace llarp bool is_expired(std::chrono::milliseconds now = llarp::time_now_ms()) const; - /// build a new path to the same pivot, but with different hops - void rebuild(); - void Tick(std::chrono::milliseconds now); bool resolve_sns(std::string_view name, std::function func); bool find_client_contact(const dht::Key_t& location, std::function func); - // bool publish_client_contact( - // const EncryptedClientContact& ecc, std::function func = nullptr); - - bool publish_client_contact2( + bool publish_client_contact( const EncryptedClientContact& ecc, std::function func); bool close_exit( @@ -118,9 +116,6 @@ namespace llarp /// func is called with a bt-encoded response string (if applicable), and /// a timeout flag (if set, response string will be empty) bool send_path_control_message( - std::string method, std::string body, std::function func = nullptr); - - bool send_path_control_message2( std::string method, std::string body, std::function func); bool send_path_data_message(std::string body); diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index 8bd7a7602a..c5ed6df9fc 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -22,7 +22,10 @@ namespace llarp::path void PathContext::add_path(std::shared_ptr path) { - _r.loop()->call([&]() { _path_map.emplace(path->upstream_rxid(), path); }); + _r.loop()->call([&]() { + _path_map.emplace(path->upstream_rxid(), path); + _path_map.emplace(path->pivot_txid(), path); + }); } void PathContext::drop_paths(std::vector droplist) @@ -64,13 +67,16 @@ namespace llarp::path void PathContext::drop_path(const std::shared_ptr& path) { - _r.loop()->call([&]() { drop_path(path->upstream_rxid()); }); + _r.loop()->call([&]() { + _drop_path(path->upstream_rxid()); + _drop_path(path->pivot_txid()); + }); } std::tuple PathContext::path_ctx_stats() const { return _r.loop()->call_get([&]() -> std::tuple { - return {_path_map.size(), _transit_hops.size()}; + return {_path_map.size() / 2, _transit_hops.size() / 2}; }); } diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index a952f08dd4..6a41d82072 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -67,10 +67,24 @@ namespace llarp::path Lock_t l(paths_mutex); _paths.insert_or_assign(p->upstream_rxid(), p); + // _paths.insert_or_assign(p->pivot_txid(), p); _router.path_context()->add_path(p); } + void PathHandler::drop_path(const std::shared_ptr& p) + { + Lock_t l{paths_mutex}; + + if (auto itr = _paths.find(p->upstream_rxid()); itr != _paths.end()) + _paths.erase(itr); + + // if (auto itr = _paths.find(p->pivot_txid()); itr != _paths.end()) + // _paths.erase(itr); + + _router.path_context()->drop_path(p); + } + std::optional> PathHandler::get_random_path() { auto p = std::make_optional>>(); @@ -375,7 +389,9 @@ namespace llarp::path if (build_cooldown()) return {}; - return num_paths_desired - num_paths(); + auto n_paths = num_paths(); + + return num_paths_desired >= n_paths ? num_paths_desired - n_paths : 0; } std::optional> PathHandler::get_hops_to_random() @@ -635,19 +651,9 @@ namespace llarp::path } } - void PathHandler::drop_path(const HopID& upstream_rxid) - { - Lock_t l{paths_mutex}; - - if (auto itr = _paths.find(upstream_rxid); itr != _paths.end()) - _paths.erase(itr); - - _router.path_context()->drop_path(upstream_rxid); - } - void PathHandler::path_build_failed(std::shared_ptr p, bool timeout) { - drop_path(p->upstream_rxid()); + drop_path(p); if (timeout) { @@ -655,7 +661,7 @@ namespace llarp::path _build_stats.timeouts += 1; } else - _build_stats.build_fails -= 1; + _build_stats.build_fails += 1; path_build_backoff(); } diff --git a/llarp/path/path_handler.hpp b/llarp/path/path_handler.hpp index 8d6f52055f..33f7e3e888 100644 --- a/llarp/path/path_handler.hpp +++ b/llarp/path/path_handler.hpp @@ -115,7 +115,7 @@ namespace llarp /// return true if we hit our soft limit for building paths too fast on a first hop bool build_cooldown_hit(RouterID edge) const; - void drop_path(const HopID& remote); + void drop_path(const std::shared_ptr& p); virtual void path_died(std::shared_ptr p); @@ -155,12 +155,6 @@ namespace llarp intro_set get_current_client_intros() const; - // service::intro_que_old get_recent_path_intros( - // std::chrono::milliseconds stale_threshold = path::INTRO_STALE_THRESHOLD) const; - - // std::optional get_path_intros_conditional( - // std::function filter) const; - nlohmann::json ExtractStatus() const; virtual size_t should_build_more() const; diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 698d2aa194..5e47e72cf9 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -919,7 +919,9 @@ namespace llarp } } else + { initial_client_connect_complete = true; + } if (initial_client_connect_complete) _session_endpoint->tick(now); diff --git a/llarp/session/map.hpp b/llarp/session/map.hpp index 38f43ce19f..e2abd8b187 100644 --- a/llarp/session/map.hpp +++ b/llarp/session/map.hpp @@ -18,7 +18,7 @@ namespace llarp struct session_map { protected: - std::unordered_map _session_lookup; + std::unordered_map _session_lookup; std::unordered_map> _sessions; using Lock_t = util::NullLock; @@ -81,7 +81,7 @@ namespace llarp return {_2->second, b1 & b2}; } - std::optional get_remote(const service::SessionTag& tag) const + std::optional get_remote(const SessionTag& tag) const { Lock_t l{session_mutex}; @@ -105,7 +105,7 @@ namespace llarp return ret; } - std::shared_ptr get_session(const service::SessionTag& tag) const + std::shared_ptr get_session(const SessionTag& tag) const { Lock_t l{session_mutex}; @@ -117,7 +117,7 @@ namespace llarp return ret; } - void unmap(const service::SessionTag& tag) + void unmap(const SessionTag& tag) { Lock_t l{session_mutex}; @@ -147,7 +147,7 @@ namespace llarp } } - bool have_session(const service::SessionTag& tag) const + bool have_session(const SessionTag& tag) const { Lock_t l{session_mutex}; @@ -164,7 +164,7 @@ namespace llarp return _sessions.count(local); } - std::shared_ptr operator[](const service::SessionTag& tag) { return get_session(tag); } + std::shared_ptr operator[](const SessionTag& tag) { return get_session(tag); } std::shared_ptr operator[](const net_addr_t& local) { return get_session(local); } }; diff --git a/llarp/session/session.cpp b/llarp/session/session.cpp index 23a70f7749..e975714796 100644 --- a/llarp/session/session.cpp +++ b/llarp/session/session.cpp @@ -18,7 +18,7 @@ namespace llarp::session std::shared_ptr _p, handlers::SessionEndpoint& parent, NetworkAddress remote, - service::SessionTag _t, + SessionTag _t, bool use_tun, bool is_exit, bool is_outbound) @@ -36,7 +36,7 @@ namespace llarp::session bool BaseSession::send_path_control_message( std::string method, std::string body, std::function func) { - return _current_path->send_path_control_message2(std::move(method), std::move(body), std::move(func)); + return _current_path->send_path_control_message(std::move(method), std::move(body), std::move(func)); } bool BaseSession::send_path_data_message(std::string data) @@ -56,7 +56,7 @@ namespace llarp::session _current_path = std::move(_new_path); - _current_hop_id = _current_path->pivot_rxid(); + _pivot_txid = _current_path->pivot_rxid(); if (_use_tun) _current_path->link_session([this](bstring data) { @@ -154,7 +154,7 @@ namespace llarp::session NetworkAddress remote, handlers::SessionEndpoint& parent, std::shared_ptr path, - service::SessionTag _t, + SessionTag _t, bool is_exit) : PathHandler{parent._router, path::DEFAULT_PATHS_HELD}, BaseSession{ @@ -183,10 +183,10 @@ namespace llarp::session OutboundSession::~OutboundSession() = default; - void OutboundSession::path_died(std::shared_ptr p) + void OutboundSession::path_died([[maybe_unused]] std::shared_ptr p) { log::debug(logcat, "{} called", __PRETTY_FUNCTION__); - p->rebuild(); + // p->rebuild(); } nlohmann::json OutboundSession::ExtractStatus() const @@ -282,9 +282,7 @@ namespace llarp::session _remote); for (size_t i = 0; i < n; ++i) - { count += build_path_aligned_to_remote(_remote.router_id()); - } if (count == n) log::debug(logcat, "OutboundSession successfully initiated {} path-builds", n); @@ -311,7 +309,7 @@ namespace llarp::session bool OutboundSession::is_ready() const { - if (_current_hop_id.is_zero()) + if (_pivot_txid.is_zero()) return false; const size_t expect = (1 + (num_paths_desired / 2)); @@ -328,7 +326,7 @@ namespace llarp::session NetworkAddress remote, std::shared_ptr _path, handlers::SessionEndpoint& parent, - service::SessionTag _t, + SessionTag _t, bool use_tun) : BaseSession{ parent._router, @@ -345,7 +343,7 @@ namespace llarp::session "NetworkAddress and Path do not agree on InboundSession remote's identity (client vs server)!"}; } - void InboundSession::set_new_tag(const service::SessionTag& tag) + void InboundSession::set_new_tag(const SessionTag& tag) { _tag = tag; } diff --git a/llarp/session/session.hpp b/llarp/session/session.hpp index 3664b25b5e..e8eedcdddc 100644 --- a/llarp/session/session.hpp +++ b/llarp/session/session.hpp @@ -45,7 +45,7 @@ namespace llarp Router& _r; handlers::SessionEndpoint& _parent; - service::SessionTag _tag; + SessionTag _tag; NetworkAddress _remote; bool _use_tun; @@ -54,7 +54,7 @@ namespace llarp const bool _is_exit_session{false}; std::shared_ptr _current_path; - HopID _current_hop_id; + HopID _pivot_txid; // manually routed QUIC endpoint std::shared_ptr _ep; @@ -76,7 +76,7 @@ namespace llarp std::shared_ptr _p, handlers::SessionEndpoint& parent, NetworkAddress remote, - service::SessionTag _t, + SessionTag _t, bool use_tun, bool is_exit, bool is_outbound); @@ -104,9 +104,9 @@ namespace llarp bool using_tun() const { return _use_tun; } - service::SessionTag tag() { return _tag; } + SessionTag tag() { return _tag; } - const service::SessionTag& tag() const { return _tag; } + const SessionTag& tag() const { return _tag; } bool is_exit_session() const { return _is_exit_session; } }; @@ -120,7 +120,7 @@ namespace llarp NetworkAddress _remote, handlers::SessionEndpoint& parent, std::shared_ptr path, - service::SessionTag _t, + SessionTag _t, bool is_exit); ~OutboundSession() override; @@ -163,12 +163,12 @@ namespace llarp const RouterID& remote_endpoint() const { return _remote.router_id(); } - std::optional current_hop_id() const + std::optional current_pivot_txid() const { - if (_current_hop_id.is_zero()) + if (_pivot_txid.is_zero()) return std::nullopt; - return _current_hop_id; + return _pivot_txid; } bool is_expired(std::chrono::milliseconds now) const; @@ -180,12 +180,12 @@ namespace llarp NetworkAddress _remote, std::shared_ptr _path, handlers::SessionEndpoint& parent, - service::SessionTag _t, + SessionTag _t, bool use_tun); ~InboundSession() = default; - void set_new_tag(const service::SessionTag& tag); + void set_new_tag(const SessionTag& tag); }; } // namespace session From 17a2ec829b29407e04e1d67de9404c440dfec45a Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 14 Nov 2024 11:12:45 -0800 Subject: [PATCH 26/44] who actually even knows (squash) - do not use hops with the same /24 masked ip-address - RPC find_cc endpoint --- daemon/CMakeLists.txt | 3 +- llarp/CMakeLists.txt | 19 ++++--- llarp/config/config.cpp | 3 +- llarp/constants/path.hpp | 2 +- llarp/contact/client_contact.cpp | 6 ++ llarp/contact/client_intro.cpp | 2 +- llarp/contact/keys.hpp | 1 - llarp/contact/relay_contact.cpp | 16 ++---- llarp/contact/relay_contact.hpp | 2 + llarp/handlers/session.cpp | 14 +++++ llarp/handlers/tun.hpp | 1 - llarp/link/link_manager.hpp | 1 - llarp/nodedb.cpp | 14 ++--- llarp/nodedb.hpp | 13 ++--- llarp/path/path.cpp | 81 +-------------------------- llarp/path/path.hpp | 2 - llarp/path/path_handler.cpp | 81 +++++++++++++++++---------- llarp/path/transit_hop.hpp | 1 - llarp/router/router.cpp | 18 +++--- llarp/router/router.hpp | 2 +- llarp/rpc/rpc_request.hpp | 2 +- llarp/rpc/rpc_request_definitions.hpp | 19 +++++++ llarp/rpc/rpc_request_parser.cpp | 5 ++ llarp/rpc/rpc_request_parser.hpp | 1 + llarp/rpc/rpc_server.cpp | 79 +++++++++++++++++++------- llarp/rpc/rpc_server.hpp | 3 +- llarp/util/priority_queue.hpp | 11 ---- llarp/util/thread/queue.hpp | 2 +- 28 files changed, 205 insertions(+), 199 deletions(-) delete mode 100644 llarp/util/priority_queue.hpp diff --git a/daemon/CMakeLists.txt b/daemon/CMakeLists.txt index 772e665327..84b37d9894 100644 --- a/daemon/CMakeLists.txt +++ b/daemon/CMakeLists.txt @@ -59,8 +59,7 @@ 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-core hax_and_shims_for_cmake) + target_link_libraries(${exe} PUBLIC lokinet-base lokinet-core) if(STRIP_SYMBOLS) add_custom_command(TARGET ${exe} POST_BUILD diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index 6be549e3b3..e50647b601 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -212,18 +212,16 @@ lokinet_add_library(lokinet-path path/transit_hop.cpp ) -# Link libraries to their internals -target_link_libraries(lokinet-core-utils PUBLIC lokinet-dns) -target_link_libraries(lokinet-core PUBLIC lokinet-core-utils) - -# Link lokinet-dns to alternate libraries -target_link_libraries(lokinet-dns PUBLIC lokinet-dns-platform) +#target_link_libraries(lokinet-core PUBLIC lokinet-core-utils) +#target_link_libraries(lokinet-core-utils PUBLIC lokinet-dns) +#target_link_libraries(lokinet-dns PUBLIC lokinet-dns-platform) +#target_link_libraries(lokinet-dns PUBLIC lokinet-utils lokinet-cryptography lokinet-config lokinet-dns-platform) +# Link libraries to their internals target_link_libraries(lokinet-wire PUBLIC lokinet-addressing) -target_link_libraries(lokinet-dns PUBLIC lokinet-utils lokinet-cryptography lokinet-config) target_link_libraries(lokinet-nodedb PUBLIC lokinet-addressing lokinet-cryptography) target_link_libraries(lokinet-platform PUBLIC lokinet-cryptography) -target_link_libraries(lokinet-rpc PUBLIC lokinet-wire) +target_link_libraries(lokinet-rpc PUBLIC lokinet-wire lokinet-contact) target_link_libraries(lokinet-addressing PUBLIC lokinet-utils lokinet-cryptography lokinet-contact) target_link_libraries(lokinet-wire PUBLIC lokinet-cryptography) target_link_libraries(lokinet-config PUBLIC lokinet-cryptography) @@ -231,6 +229,9 @@ target_link_libraries(lokinet-config PUBLIC lokinet-cryptography) target_link_libraries(lokinet-dns PUBLIC lokinet-addressing + lokinet-cryptography + lokinet-config + lokinet-dns-platform ) target_link_libraries(lokinet-path @@ -240,6 +241,7 @@ target_link_libraries(lokinet-path target_link_libraries(lokinet-core-utils PUBLIC + lokinet-dns lokinet-config lokinet-platform lokinet-rpc @@ -259,6 +261,7 @@ target_link_libraries(lokinet-utils # cross linkage target_link_libraries(lokinet-core PUBLIC + lokinet-core-utils lokinet-cryptography lokinet-nodedb lokinet-path diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index 1ddce712d5..6345bef5c7 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -1544,7 +1544,8 @@ namespace llarp { (void)params; - constexpr Default DefaultUniqueCIDR{32}; + constexpr Default DefaultUniqueCIDR{24}; + conf.define_option( "paths", "unique-range-size", diff --git a/llarp/constants/path.hpp b/llarp/constants/path.hpp index 4b57dbd54e..7b2e1dbdcd 100644 --- a/llarp/constants/path.hpp +++ b/llarp/constants/path.hpp @@ -15,7 +15,7 @@ namespace llarp::path constexpr std::size_t PAD_SIZE = 128; /// default path lifetime in ms; // TESTNET: reduced value - constexpr std::chrono::milliseconds DEFAULT_LIFETIME{5min}; + constexpr std::chrono::milliseconds DEFAULT_LIFETIME{10min}; /// 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 diff --git a/llarp/contact/client_contact.cpp b/llarp/contact/client_contact.cpp index 0ce984ba4c..ab1ddb880e 100644 --- a/llarp/contact/client_contact.cpp +++ b/llarp/contact/client_contact.cpp @@ -169,6 +169,12 @@ namespace llarp return enc; } + std::string ClientContact::to_string() const + { + return "CC:['a'={} | 'e'={} | 'i'={{{}}} | 'p'={} | 's'={}]"_format( + pubkey, exit_policy.has_value(), fmt::join(intros, ","), protos, not SRVs.empty()); + } + EncryptedClientContact EncryptedClientContact::deserialize(std::string_view buf) { log::info(logcat, "Deserializing EncryptedClientContact..."); diff --git a/llarp/contact/client_intro.cpp b/llarp/contact/client_intro.cpp index 9c2b4f5064..41b64a3700 100644 --- a/llarp/contact/client_intro.cpp +++ b/llarp/contact/client_intro.cpp @@ -42,6 +42,6 @@ namespace llarp std::string ClientIntro::to_string() const { - return "[ ClientIntro pivot_rid={}, pivot_txid={}, expiry={} ]"_format(pivot_rid, pivot_txid, expiry.count()); + return "CI:['k'={} | 'p'={} | 'x'={}]"_format(pivot_rid, pivot_txid, expiry.count()); } } // namespace llarp diff --git a/llarp/contact/keys.hpp b/llarp/contact/keys.hpp index 36aa127dea..f0b7471a2a 100644 --- a/llarp/contact/keys.hpp +++ b/llarp/contact/keys.hpp @@ -7,7 +7,6 @@ /** TODO: - re-configure string_view and ustring_view methods after deprecating RouterID - */ namespace llarp diff --git a/llarp/contact/relay_contact.cpp b/llarp/contact/relay_contact.cpp index b6c01aa8a2..13a6b46438 100644 --- a/llarp/contact/relay_contact.cpp +++ b/llarp/contact/relay_contact.cpp @@ -122,17 +122,6 @@ namespace llarp {"identity", _router_id.to_string()}, {"address", _addr.to_string()}}; - // if (routerVersion) - // { - // obj["routerVersion"] = routerVersion->to_string(); - // } - // std::vector srv; - // for (const auto& record : srvRecords) - // { - // srv.emplace_back(record.ExtractStatus()); - // } - // obj["srvRecords"] = srv; - return obj; } @@ -144,6 +133,11 @@ namespace llarp return _addr.is_addressable(); } + bool RelayContact::has_ip_overlap(const RelayContact& other, uint8_t netmask) const + { + return (_addr.to_ipv4() / netmask).contains(other._addr.to_ipv4()); + } + bool RelayContact::is_outdated(std::chrono::milliseconds now) const { return now >= _timestamp.time_since_epoch() + OUTDATED_AGE; diff --git a/llarp/contact/relay_contact.hpp b/llarp/contact/relay_contact.hpp index 23dc5221fa..14f39b37bd 100644 --- a/llarp/contact/relay_contact.hpp +++ b/llarp/contact/relay_contact.hpp @@ -125,6 +125,8 @@ namespace llarp bool is_public_addressable() const; + bool has_ip_overlap(const RelayContact& other, uint8_t netmask) const; + /// does this RC expire soon? default delta is 1 minute bool expires_within_delta(std::chrono::milliseconds now, std::chrono::milliseconds dlt = 1min) const; diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index c5451bbf69..7fc08e0afc 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -22,6 +22,8 @@ namespace llarp::handlers return _router.loop(); } + // static std::atomic testnet_trigger = false; + void SessionEndpoint::tick(std::chrono::milliseconds now) { log::trace(logcat, "{} called", __PRETTY_FUNCTION__); @@ -30,6 +32,18 @@ namespace llarp::handlers _sessions.tick_outbounds(now); path::PathHandler::tick(now); + + // if (not testnet_trigger) + // { + // testnet_trigger = true; + // if (auto rclient = + // NetworkAddress::from_network_addr("4odrxxn5rekt99yb5jqksb3gncpb91s1ue56kpx58p3doen5cxey.loki"sv)) + // { + // initiate_remote_exit_session(*rclient, [](ip_v) { log::critical(logcat, "FUCK YEAH"); }); + // } + // else + // log::critical(logcat, "Failed to parse client netaddr!"); + // } } bool SessionEndpoint::stop(bool send_close) diff --git a/llarp/handlers/tun.hpp b/llarp/handlers/tun.hpp index 94d1bd58c2..36e24d2dc1 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 5df56f8024..d407dc26d4 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index ce598ab74b..58bf824576 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -144,8 +144,6 @@ namespace llarp return false; } - // TODO: make this its own ticker - // purge_rcs(now); return true; } @@ -153,7 +151,7 @@ namespace llarp { remove_if([&](const RemoteRC& rc) -> bool { // don't purge bootstrap nodes from nodedb - if (is_bootstrap_node(rc.router_id())) + if (is_bootstrap_node(rc)) { log::trace(logcat, "Not removing {}: is bootstrap node", rc.router_id()); return false; @@ -189,6 +187,7 @@ namespace llarp 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 @@ -198,6 +197,7 @@ namespace llarp log::debug(logcat, "Removing {}: not a valid router", rc.router_id()); return true; } + return false; }); @@ -429,7 +429,7 @@ namespace llarp if (process_fetched_rcs(*result)) { - log::info(logcat, "Accumulated RID's accepted by trust model"); + log::info(logcat, "Accumulated RC's accepted by trust model"); return stop_rc_fetch(true); } @@ -565,9 +565,9 @@ namespace llarp reselect_router_id_sources(fail_sources); } - bool NodeDB::is_bootstrap_node(RouterID rid) const + bool NodeDB::is_bootstrap_node(const RemoteRC& rc) const { - return has_bootstraps() ? _bootstraps.contains(rid) : false; + return has_bootstraps() ? _bootstraps.contains(rc) : false; } void NodeDB::start_tickers() @@ -580,7 +580,7 @@ namespace llarp }); _purge_ticker = _router.loop()->call_every( - 5min, [this]() { purge_rcs(); }, not _needs_bootstrap); + PURGE_INTERVAL, [this]() mutable { purge_rcs(); }, not _needs_bootstrap); if (not _is_service_node) { diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index 4af8ceac3e..fe0657d0b7 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -23,6 +23,8 @@ namespace llarp // TESTNET: the following constants have been shortened for testing purposes inline constexpr auto FETCH_INTERVAL{10min}; + inline constexpr auto PURGE_INTERVAL{5min}; + inline constexpr auto FLUSH_INTERVAL{15min}; /* RC Fetch Constants */ // fallback to bootstrap if we have less than this many RCs @@ -62,9 +64,6 @@ namespace llarp // threshold amount of verifications to promote an unconfirmed rc/rid inline constexpr int CONFIRMATION_THRESHOLD{3}; - inline constexpr auto PURGE_INTERVAL{1min}; - inline constexpr auto FLUSH_INTERVAL{15min}; - template < typename ID_t, std::enable_if_t || std::is_same_v, int> = 0> @@ -93,12 +92,9 @@ namespace llarp Router& _router; const fs::path _root; - // const std::function)> _disk_hook; bool _is_service_node{false}; - std::chrono::milliseconds _next_flush_time{}; - /******** RouterID/RelayContacts ********/ using Lock_t = util::NullLock; @@ -198,8 +194,7 @@ namespace llarp return std::make_shared(std::move(rootdir), r); } - explicit NodeDB(fs::path rootdir, Router* r) - : _router{*r}, _root{std::move(rootdir)}, _next_flush_time{time_now_ms() + FLUSH_INTERVAL} + explicit NodeDB(fs::path rootdir, Router* r) : _router{*r}, _root{std::move(rootdir)} { _ensure_skiplist(_root); rid_result_counters.clear(); @@ -242,7 +237,7 @@ namespace llarp bool is_bootstrapping() const { return _is_bootstrapping; } bool needs_bootstrap() const { return _needs_bootstrap; } bool bootstrap_completed() const { return not(_is_bootstrapping or _needs_bootstrap); } - bool is_bootstrap_node(RouterID rid) const; + bool is_bootstrap_node(const RemoteRC& rc) const; void purge_rcs(std::chrono::milliseconds now = llarp::time_now_ms()); // Bootstrap fallback fetching diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 1bea574097..725b8d1e51 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -230,16 +230,6 @@ namespace llarp::path return nullptr; } - // std::shared_ptr Path::local_hop() - // { - // return _local_hop; - // } - - // const std::shared_ptr& Path::local_hop() const - // { - // return _local_hop; - // } - RouterID Path::upstream_rid() { return hops.front().router_id(); @@ -339,22 +329,6 @@ namespace llarp::path return obj; } - bool 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) { // TODO: do we still want this concept? @@ -372,60 +346,7 @@ namespace llarp::path if (_is_linked) { } - - // m_LastRXRate = m_RXRate; - // m_LastTXRate = m_TXRate; - - // m_RXRate = 0; - // m_TXRate = 0; - - // if (_status == PathStatus::BUILDING) - // { - // if (buildStarted == 0s) - // return; - // if (now >= buildStarted) - // { - // const auto dlt = now - buildStarted; - // if (dlt >= path::BUILD_TIMEOUT) - // { - // LogWarn(name(), " waited for ", to_string(dlt), " and no path was built"); - // r->router_profiling().MarkPathFail(this); - // EnterState(PathStatus::EXPIRED, now); - // return; - // } - // } - // } - // check to see if this path is dead - // if (_status == PathStatus::ESTABLISHED) - // { - // auto dlt = now - last_latency_test; - // if (dlt > path::LATENCY_INTERVAL && last_latency_test_id == 0) - // { - // SendLatencyMessage(r); - // // latency test FEC - // r->loop()->call_later(2s, [self = shared_from_this(), r]() { - // if (self->last_latency_test_id) - // self->SendLatencyMessage(r); - // }); - // return; - // } - // dlt = now - last_recv_msg; - // if (dlt >= path::ALIVE_TIMEOUT) - // { - // LogWarn(name(), " waited for ", to_string(dlt), " and path looks dead"); - // r->router_profiling().MarkPathFail(this); - // EnterState(PathStatus::TIMEOUT, now); - // } - // } - // if (_status == PathStatus::IGNORE and now - last_recv_msg >= path::ALIVE_TIMEOUT) - // { - // // clean up this path as we dont use it anymore - // EnterState(PathStatus::EXPIRED, now); - // } - } - - /// how long we wait for a path to become active again after it times out - // constexpr auto PathReanimationTimeout = 45s; + } void Path::set_established() { diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 83d4dc6123..b11570c49e 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -164,8 +164,6 @@ namespace llarp void populate_internals(const std::vector& _hops); - bool SendLatencyMessage(Router* r); - /// call obtained exit hooks bool InformExitResult(std::chrono::milliseconds b); diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index 6a41d82072..b32d5ee4da 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -413,64 +413,87 @@ namespace llarp::path { log::trace(logcat, "{} called", __PRETTY_FUNCTION__); - const auto& path_config = _router.config()->paths; + assert(num_hops); - // make a copy here to reference rather than creating one in the lambda every iteration - std::set to_exclude{exclude.begin(), exclude.end()}; - to_exclude.insert(pivot); + auto hops_needed = num_hops; - std::vector hops; + std::vector hops{}; + RemoteRC pivot_rc{}; - if (auto maybe = select_first_hop(exclude)) - hops.push_back(*maybe); - else + if (auto maybe = _router.node_db()->get_rc(pivot)) { - log::warning(logcat, "No first hop candidate for aligned hops!"); - return std::nullopt; + // if we only need one hop, return + if (hops_needed == 1) + { + hops.emplace_back(std::move(*maybe)); + return hops; + } + + // leave space to add the pivot last + --hops_needed; + pivot_rc = *maybe; } + else + return std::nullopt; - to_exclude.insert(hops.back().router_id()); + auto netmask = _router.config()->paths.unique_hop_netmask; - RemoteRC pivot_rc; + // make a copy here to reference rather than creating one in the lambda every iteration + std::set to_exclude{exclude.begin(), exclude.end()}; + to_exclude.insert(pivot); - if (auto maybe = _router.node_db()->get_rc(pivot)) + if (auto maybe = select_first_hop(to_exclude)) { - pivot_rc = *maybe; + hops.push_back(*maybe); + --hops_needed; } else + { + log::warning(logcat, "No first hop candidate for aligned hops!"); return std::nullopt; + } - // leave one extra spot for the terminal node - auto hops_needed = num_hops - hops.size() - 1; + to_exclude.insert(hops.back().router_id()); - auto filter = [&r = _router, &to_exclude](const RemoteRC& rc) -> bool { + auto filter = [&](const RemoteRC& rc) -> bool { const auto& rid = rc.router_id(); // if its already excluded, fail; (we want it added even on success) if (not to_exclude.insert(rid).second) return false; - if (r.router_profiling().is_bad_for_path(rid, 1)) + if (_router.router_profiling().is_bad_for_path(rid, 1)) return false; - return true; + if (pivot_rc.has_ip_overlap(rc, netmask)) + return false; + + return not std::any_of(hops.begin(), hops.end(), [&](const RemoteRC& other) -> bool { + return other.has_ip_overlap(rc, netmask); + }); }; - if (auto maybe_rcs = _router.node_db()->get_n_random_rcs_conditional(hops_needed, filter, true)) + while (hops_needed) { - auto& rcs = *maybe_rcs; - hops.insert(hops.end(), rcs.begin(), rcs.end()); - hops.emplace_back(pivot_rc); - -#ifndef TESTNET - if (not path_config.check_rcs({hops.begin(), hops.end()})) + // do this 1 at a time so we can check for IP range overlap + if (auto maybe_rc = _router.node_db()->get_random_rc_conditional(filter)) + { + hops.emplace_back(std::move(*maybe_rc)); + } + else + { + log::warning( + logcat, "Failed to find RC for aligned path! (needed:{}, found:{})", num_hops, hops_needed); return std::nullopt; -#endif + } - return hops; + --hops_needed; } - return std::nullopt; + // add pivot rc last + hops.emplace_back(std::move(pivot_rc)); + + return hops; } bool PathHandler::build_path_to_random() diff --git a/llarp/path/transit_hop.hpp b/llarp/path/transit_hop.hpp index eb5ba2cd44..66c4d00366 100644 --- a/llarp/path/transit_hop.hpp +++ b/llarp/path/transit_hop.hpp @@ -5,7 +5,6 @@ #include #include #include -#include namespace llarp { diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 5e47e72cf9..51014d3d71 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -67,7 +67,6 @@ namespace llarp {"running", true}, {"numNodesKnown", _node_db->num_rcs()}, {"links", _link_manager->extract_status()}}; } - // TODO: investigate changes needed for libquic integration nlohmann::json Router::ExtractSummaryStatus() const { // if (!is_running) @@ -634,10 +633,11 @@ namespace llarp init_rpc(); + log::trace(logcat, "Starting OMQ server"); + _lmq->start(); + if (_is_service_node) { - log::trace(logcat, "Starting OMQ server"); - _lmq->start(); log::trace(logcat, "RPC client connecting to RPC bind address"); _rpc_client->connect_async(rpc_addr); } @@ -762,10 +762,10 @@ namespace llarp queue_disk_io([&]() { relay_contact.write(our_rc_file); }); } - bool Router::is_bootstrap_node(const RouterID r) const - { - return _node_db->is_bootstrap_node(r); - } + // bool Router::is_bootstrap_node(const RouterID r) const + // { + // return _node_db->is_bootstrap_node(r); + // } bool Router::should_report_stats(std::chrono::milliseconds now) const { @@ -794,7 +794,7 @@ namespace llarp } if (_last_stats_report > 0s) - log::info(logcat, "Last reported stats time {}", now - _last_stats_report); + log::trace(logcat, "Last reported stats time {}", now - _last_stats_report); _last_stats_report = now; @@ -919,9 +919,7 @@ namespace llarp } } else - { initial_client_connect_complete = true; - } if (initial_client_connect_complete) _session_endpoint->tick(now); diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 5c2243f9f8..0cc5519ca9 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -351,7 +351,7 @@ namespace llarp std::string body, std::function func = nullptr); - bool is_bootstrap_node(RouterID rid) const; + // bool is_bootstrap_node(RouterID rid) const; std::chrono::milliseconds now() const { return llarp::time_now_ms(); } diff --git a/llarp/rpc/rpc_request.hpp b/llarp/rpc/rpc_request.hpp index 7da29c8453..d1b96a0e63 100644 --- a/llarp/rpc/rpc_request.hpp +++ b/llarp/rpc/rpc_request.hpp @@ -60,7 +60,7 @@ namespace llarp::rpc if (not std::is_base_of_v) { - server.m_Router.loop()->call_soon(std::move(handler)); + server._router.loop()->call_soon(std::move(handler)); } else { diff --git a/llarp/rpc/rpc_request_definitions.hpp b/llarp/rpc/rpc_request_definitions.hpp index 4908392ec2..53d2bbcd4e 100644 --- a/llarp/rpc/rpc_request_definitions.hpp +++ b/llarp/rpc/rpc_request_definitions.hpp @@ -291,6 +291,24 @@ namespace llarp::rpc } request; }; + // RPC: find_cc + // Lookup client contact via path request + // + // Inputs: + // "pk" : client pubkey + // + // Returns: + // "cc" : client contact + struct FindCC : RPCRequest + { + static constexpr auto name = "find_cc"sv; + + struct request_parameterss + { + std::string pk; + } request; + }; + // List of all RPC request structs to allow compile-time enumeration of all supported types using rpc_request_types = tools::type_list< Halt, @@ -300,6 +318,7 @@ namespace llarp::rpc QuicConnect, // debug QuicListener, // debug LookupSnode, + FindCC, MapExit, ListExits, SwapExits, diff --git a/llarp/rpc/rpc_request_parser.cpp b/llarp/rpc/rpc_request_parser.cpp index 7eafc4cd83..0d5b6e45df 100644 --- a/llarp/rpc/rpc_request_parser.cpp +++ b/llarp/rpc/rpc_request_parser.cpp @@ -38,6 +38,11 @@ namespace llarp::rpc quiclistener.request.srvProto); } + void parse_request(FindCC& findcc, rpc_input input) + { + get_values(input, "pk", findcc.request.pk); + } + void parse_request(LookupSnode& lookupsnode, rpc_input input) { get_values(input, "routerID", lookupsnode.request.routerID); diff --git a/llarp/rpc/rpc_request_parser.hpp b/llarp/rpc/rpc_request_parser.hpp index 3c10fe2739..bc0b6c7a81 100644 --- a/llarp/rpc/rpc_request_parser.hpp +++ b/llarp/rpc/rpc_request_parser.hpp @@ -17,6 +17,7 @@ namespace llarp::rpc void parse_request(QuicConnect& quicconnect, rpc_input input); void parse_request(QuicListener& quiclistener, rpc_input input); + void parse_request(FindCC& findcc, rpc_input input); void parse_request(LookupSnode& lookupsnode, rpc_input input); void parse_request(MapExit& mapexit, rpc_input input); void parse_request(UnmapExit& unmapexit, rpc_input input); diff --git a/llarp/rpc/rpc_server.cpp b/llarp/rpc/rpc_server.cpp index d84a199a91..0a86ef2d7e 100644 --- a/llarp/rpc/rpc_server.cpp +++ b/llarp/rpc/rpc_server.cpp @@ -5,9 +5,11 @@ #include #include #include +#include #include #include #include +#include #include @@ -71,7 +73,7 @@ namespace llarp::rpc } RPCServer::RPCServer(LMQ_ptr lmq, Router& r) - : m_LMQ{std::move(lmq)}, m_Router(r), log_subs{*m_LMQ, llarp::logRingBuffer} + : m_LMQ{std::move(lmq)}, _router(r), log_subs{*m_LMQ, llarp::logRingBuffer} { // copied logic loop as placeholder for (const auto& addr : r.config()->api.rpc_bind_addrs) @@ -113,31 +115,31 @@ namespace llarp::rpc void RPCServer::invoke(Halt& halt) { - if (not m_Router.is_running()) + if (not _router.is_running()) { SetJSONError("Router is not running", halt.response); return; } SetJSONResponse("OK", halt.response); - m_Router.stop(); + _router.stop(); } void RPCServer::invoke(Version& version) { - nlohmann::json result{{"version", llarp::LOKINET_VERSION_FULL}, {"uptime", to_json(m_Router.Uptime())}}; + nlohmann::json result{{"version", llarp::LOKINET_VERSION_FULL}, {"uptime", to_json(_router.Uptime())}}; SetJSONResponse(result, version.response); } void RPCServer::invoke(Status& status) { - (m_Router.is_running()) ? SetJSONResponse(m_Router.ExtractStatus(), status.response) - : SetJSONError("Router is not yet ready", status.response); + (_router.is_running()) ? SetJSONResponse(_router.ExtractStatus(), status.response) + : SetJSONError("Router is not yet ready", status.response); } void RPCServer::invoke(GetStatus& getstatus) { - SetJSONResponse(m_Router.ExtractSummaryStatus(), getstatus.response); + SetJSONResponse(_router.ExtractSummaryStatus(), getstatus.response); } void RPCServer::invoke(QuicConnect& quicconnect) @@ -157,7 +159,7 @@ namespace llarp::rpc } // auto endpoint = - // (req.endpoint.empty()) ? GetEndpointByName(m_Router, "default") : GetEndpointByName(m_Router, + // (req.endpoint.empty()) ? GetEndpointByName(_router, "default") : GetEndpointByName(_router, // req.endpoint); // if (not endpoint) @@ -213,7 +215,7 @@ namespace llarp::rpc } // auto endpoint = - // (req.endpoint.empty()) ? GetEndpointByName(m_Router, "default") : GetEndpointByName(m_Router, + // (req.endpoint.empty()) ? GetEndpointByName(_router, "default") : GetEndpointByName(_router, // req.endpoint); // if (not endpoint) @@ -270,10 +272,49 @@ namespace llarp::rpc } } + void RPCServer::invoke(FindCC& findcc) + { + if (_router.is_service_node()) + { + SetJSONError("Not supported", findcc.response); + return; + } + + RouterID pk; + + if (findcc.request.pk.empty()) + { + SetJSONError("No pubkey provided!", findcc.response); + return; + } + + if (not pk.from_string(oxenc::from_base32z(findcc.request.pk))) + { + SetJSONError("Invalid pubkey provided: " + findcc.request.pk, findcc.response); + return; + } + + _router.loop()->call([&]() { + _router.session_endpoint()->lookup_client_intro(pk, [&](std::optional cc) { + if (cc) + { + auto cc_str = "{}"_format(*cc); + log::info(logcat, "RPC call to `find_cc` returned successfully: {}", cc_str); + SetJSONResponse(cc_str, findcc.response); + } + else + { + log::warning(logcat, "RPC call to `find_cc` failed!"); + SetJSONError("ERROR", findcc.response); + } + }); + }); + } + // TODO: fix this because it's bad void RPCServer::invoke(LookupSnode& lookupsnode) { - if (not m_Router.is_service_node()) + if (not _router.is_service_node()) { SetJSONError("Not supported", lookupsnode.response); return; @@ -292,8 +333,8 @@ namespace llarp::rpc return; } - // m_Router.loop()->call([&]() { - // auto endpoint = m_Router.exit_context().get_exit_endpoint("default"); + // _router.loop()->call([&]() { + // auto endpoint = _router.exit_context().get_exit_endpoint("default"); // if (endpoint == nullptr) // { @@ -323,7 +364,7 @@ namespace llarp::rpc exit_request.replier.emplace(mapexit.move()); // TODO: connect this to remote service session management (service::Handler) - // m_Router.hidden_service_context().GetDefault()->map_exit( + // _router.hidden_service_context().GetDefault()->map_exit( // mapexit.request.address, // mapexit.request.token, // mapexit.request.ip_range, @@ -338,13 +379,13 @@ namespace llarp::rpc void RPCServer::invoke(ListExits& listexits) { (void)listexits; - // if (not m_Router.hidden_service_context().hasEndpoints()) + // if (not _router.hidden_service_context().hasEndpoints()) // { // SetJSONError("No mapped endpoints found", listexits.response); // return; // } - // auto status = m_Router.hidden_service_context().GetDefault()->ExtractStatus()["exitMap"]; + // auto status = _router.hidden_service_context().GetDefault()->ExtractStatus()["exitMap"]; // SetJSONResponse((status.empty()) ? "No exits" : status, listexits.response); } @@ -354,7 +395,7 @@ namespace llarp::rpc try { // for (auto& ip : unmapexit.request.ip_range) - // m_Router.hidden_service_context().GetDefault()->UnmapExitRange(ip); + // _router.hidden_service_context().GetDefault()->UnmapExitRange(ip); } catch (std::exception& e) { @@ -375,7 +416,7 @@ namespace llarp::rpc (void)swapexits; // MapExit map_request; // UnmapExit unmap_request; - // auto endpoint = m_Router.hidden_service_context().GetDefault(); + // auto endpoint = _router.hidden_service_context().GetDefault(); // auto current_exits = endpoint->ExtractStatus()["exitMap"]; // if (current_exits.empty()) @@ -452,8 +493,8 @@ namespace llarp::rpc dns::Message msg{dns::Question{qname, qtype}}; - // auto endpoint = (dnsquery.request.endpoint.empty()) ? GetEndpointByName(m_Router, "default") - // : GetEndpointByName(m_Router, dnsquery.request.endpoint); + // auto endpoint = (dnsquery.request.endpoint.empty()) ? GetEndpointByName(_router, "default") + // : GetEndpointByName(_router, dnsquery.request.endpoint); // if (endpoint == nullptr) // { diff --git a/llarp/rpc/rpc_server.hpp b/llarp/rpc/rpc_server.hpp index 0a3da79657..76d28f44bb 100644 --- a/llarp/rpc/rpc_server.hpp +++ b/llarp/rpc/rpc_server.hpp @@ -92,6 +92,7 @@ namespace llarp::rpc void invoke(QuicConnect& quicconnect); void invoke(QuicListener& quiclistener); void invoke(LookupSnode& lookupsnode); + void invoke(FindCC& findcc); void invoke(MapExit& mapexit); void invoke(ListExits& listexits); void invoke(UnmapExit& unmapexit); @@ -100,7 +101,7 @@ namespace llarp::rpc void invoke(Config& config); LMQ_ptr m_LMQ; - Router& m_Router; + Router& _router; oxen::log::PubsubLogger log_subs; }; diff --git a/llarp/util/priority_queue.hpp b/llarp/util/priority_queue.hpp deleted file mode 100644 index cc87382a69..0000000000 --- a/llarp/util/priority_queue.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include -#include - -namespace llarp::util -{ - /// priority queue that uses operator > instead of operator < - template > - using ascending_priority_queue = std::priority_queue>; -} // namespace llarp::util diff --git a/llarp/util/thread/queue.hpp b/llarp/util/thread/queue.hpp index c627762b02..db2968e272 100644 --- a/llarp/util/thread/queue.hpp +++ b/llarp/util/thread/queue.hpp @@ -19,7 +19,7 @@ namespace llarp::thread { // This class provides a thread-safe, lock-free, fixed-size queue. public: - static constexpr size_t Alignment = 64; + static constexpr size_t Alignment{64}; private: Type* m_data; From 19460a483456fb3433e2ea1a92409cd499727fbe Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 14 Nov 2024 15:04:30 -0800 Subject: [PATCH 27/44] squash again --- llarp/contact/client_contact.cpp | 9 ++++++ llarp/contact/client_contact.hpp | 4 ++- llarp/contact/contactdb.cpp | 2 +- llarp/handlers/session.cpp | 23 ++++----------- llarp/link/link_manager.cpp | 50 ++++++++++++++++++++++---------- llarp/link/link_manager.hpp | 6 ++-- llarp/messages/dht.hpp | 2 +- llarp/nodedb.cpp | 2 +- llarp/path/path_context.cpp | 20 ++++++------- llarp/path/path_handler.cpp | 3 -- llarp/router/router.cpp | 2 +- 11 files changed, 68 insertions(+), 55 deletions(-) diff --git a/llarp/contact/client_contact.cpp b/llarp/contact/client_contact.cpp index ab1ddb880e..aaf6ce48e2 100644 --- a/llarp/contact/client_contact.cpp +++ b/llarp/contact/client_contact.cpp @@ -186,6 +186,15 @@ namespace llarp bt_decode(oxenc::bt_dict_consumer{_bt_payload}); } + std::string EncryptedClientContact::bt_encode() + { + oxenc::bt_dict_producer btdp; + bt_encode(btdp); + btdp.append("~", sig.to_view()); + _bt_payload = std::move(btdp).str(); + return _bt_payload; + } + void EncryptedClientContact::bt_encode(oxenc::bt_dict_producer& btdp) const { btdp.append("i", blinded_pubkey.to_view()); diff --git a/llarp/contact/client_contact.hpp b/llarp/contact/client_contact.hpp index c93f3b6aae..f01626dc21 100644 --- a/llarp/contact/client_contact.hpp +++ b/llarp/contact/client_contact.hpp @@ -173,7 +173,7 @@ namespace llarp friend struct dht::CCNode; friend struct ClientContact; - EncryptedClientContact() : nonce{SymmNonce::make_random()}, encrypted(ClientContact::MAX_CC_SIZE) {} + explicit EncryptedClientContact() : nonce{SymmNonce::make_random()}, encrypted(ClientContact::MAX_CC_SIZE) {} static EncryptedClientContact deserialize(std::string_view buf); @@ -193,6 +193,8 @@ namespace llarp void bt_decode(oxenc::bt_dict_consumer&& btdc); + std::string bt_encode(); + public: dht::Key_t key() const { return dht::Key_t{blinded_pubkey.data()}; } diff --git a/llarp/contact/contactdb.cpp b/llarp/contact/contactdb.cpp index 6bc0e5582c..be3e229498 100644 --- a/llarp/contact/contactdb.cpp +++ b/llarp/contact/contactdb.cpp @@ -40,7 +40,7 @@ namespace llarp void ContactDB::put_cc(EncryptedClientContact enc) { - _cc_nodes->put_node(enc); + _router.loop()->call([&]() { _cc_nodes->put_node(enc); }); } } // namespace llarp diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index 7fc08e0afc..99744b693f 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -22,8 +22,6 @@ namespace llarp::handlers return _router.loop(); } - // static std::atomic testnet_trigger = false; - void SessionEndpoint::tick(std::chrono::milliseconds now) { log::trace(logcat, "{} called", __PRETTY_FUNCTION__); @@ -32,18 +30,6 @@ namespace llarp::handlers _sessions.tick_outbounds(now); path::PathHandler::tick(now); - - // if (not testnet_trigger) - // { - // testnet_trigger = true; - // if (auto rclient = - // NetworkAddress::from_network_addr("4odrxxn5rekt99yb5jqksb3gncpb91s1ue56kpx58p3doen5cxey.loki"sv)) - // { - // initiate_remote_exit_session(*rclient, [](ip_v) { log::critical(logcat, "FUCK YEAH"); }); - // } - // else - // log::critical(logcat, "Failed to parse client netaddr!"); - // } } bool SessionEndpoint::stop(bool send_close) @@ -286,7 +272,7 @@ namespace llarp::handlers return func(std::move(maybe_intro)); } - log::info(logcat, "Looking up clientcontact for remote (rid:{})", remote); + log::info(logcat, "Looking up clientcontact for remote (rid:{})", remote.to_network_address(false)); auto response_handler = [this, remote, hook = std::move(func)](oxen::quic::message m) mutable { try @@ -331,6 +317,9 @@ namespace llarp::handlers for (const auto& [_, path] : _paths) { + if (not path or not path->is_ready()) + continue; + log::debug( logcat, "Querying pivot (rid:{}) for clientcontact lookup target (rid:{})", @@ -448,7 +437,7 @@ namespace llarp::handlers { bool ret{true}; - log::critical(logcat, "Publishing new EncryptedClientContact: {}", buffer_printer{ecc.bt_payload()}); + log::critical(logcat, "Publishing new EncryptedClientContact: {}", ecc.bt_payload()); { Lock_t l{paths_mutex}; @@ -737,7 +726,7 @@ namespace llarp::handlers if (cc) { *counter = 0; - log::info(logcat, "Session initiation returned successful 'find_cc'..."); + log::info(logcat, "Session initiation returned client contact: {}", cc->to_string()); _make_session_path(std::move(cc->intros), remote, std::move(hook), is_exit); } else if (--*counter == 0) diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 2ddc5056ea..cb7d34ea92 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -413,9 +413,9 @@ namespace llarp } std::shared_ptr LinkManager::make_control( - oxen::quic::connection_interface& ci, const RouterID& remote) + const std::shared_ptr& ci, const RouterID& remote) { - auto control_stream = ci.template queue_incoming_stream( + auto control_stream = ci->template queue_incoming_stream( [](oxen::quic::Stream&, uint64_t error_code) { log::warning(logcat, "BTRequestStream closed unexpectedly (ec:{})", error_code); }); @@ -427,10 +427,10 @@ namespace llarp return control_stream; } - void LinkManager::on_inbound_conn(oxen::quic::connection_interface& ci) + void LinkManager::on_inbound_conn(std::shared_ptr ci) { assert(_is_service_node); - RouterID rid{ci.remote_key()}; + RouterID rid{ci->remote_key()}; auto control = make_control(ci, rid); bool is_client_conn = false; @@ -438,13 +438,13 @@ namespace llarp if (auto it = ep->service_conns.find(rid); it != ep->service_conns.end()) { log::debug(logcat, "Configuring inbound connection from relay RID:{}", rid); - it->second = std::make_shared(ci.shared_from_this(), std::move(control), false, true); + it->second = std::make_shared(std::move(ci), std::move(control), false, true); } else if (auto it = ep->client_conns.find(rid); it != ep->client_conns.end()) { is_client_conn = true; log::debug(logcat, "Configuring inbound connection from client RID:{}", rid.to_network_address(false)); - it->second = std::make_shared(ci.shared_from_this(), std::move(control), false, true); + it->second = std::make_shared(std::move(ci), std::move(control), false, true); } log::critical( @@ -454,9 +454,8 @@ namespace llarp rid.to_network_address(!is_client_conn)); } - void LinkManager::on_outbound_conn(oxen::quic::connection_interface& ci) + void LinkManager::on_outbound_conn(RouterID rid) { - RouterID rid{ci.remote_key()}; log::trace(logcat, "Outbound connection to {}", rid); if (auto conn = ep->get_service_conn(rid)) @@ -475,12 +474,24 @@ namespace llarp rid); } - void LinkManager::on_conn_open(oxen::quic::connection_interface& ci) + void LinkManager::on_conn_open(oxen::quic::connection_interface& _ci) { - if (ci.is_inbound()) - on_inbound_conn(ci); - else - on_outbound_conn(ci); + log::debug(logcat, "{} called", __PRETTY_FUNCTION__); + + _router.loop()->call([this, wci = _ci.weak_from_this()]() { + auto ci = wci.lock(); + + if (not ci) + { + log::warning(logcat, "Connection died before connection open callback execution!"); + return; + } + + if (ci->is_inbound()) + on_inbound_conn(std::move(ci)); + else + on_outbound_conn(RouterID{ci->remote_key()}); + }); } void LinkManager::on_conn_closed(oxen::quic::connection_interface& ci, uint64_t ec) @@ -1171,7 +1182,14 @@ namespace llarp if (auto maybe_cc = _router.contact_db().get_encrypted_cc(dht_key)) { log::info(logcat, "Received FindClientContact request; returning local EncryptedClientContact..."); - return m.respond(FindClientContact::serialize_response(*maybe_cc)); + return m.respond(FindClientContact::serialize_response(std::move(*maybe_cc))); + } + // If the optional was nullopt, then this was a relay <-> relay request. As a result, we should NOT + // allow it to continue propagating + if (not inner_body) + { + log::critical(logcat, "Received relayed FindClientContact request; could not find locally, relaying error..."); + return m.respond(FindClientContact::NOT_FOUND, true); } auto closest_peer = _router.node_db()->find_closest_to(dht_key).router_id(); @@ -1185,7 +1203,7 @@ namespace llarp return m.respond(FindClientContact::NOT_FOUND, true); } - log::debug(logcat, "Relaying FindClientContactMessage for {}", dht_key); + log::debug(logcat, "Relaying FindClientContactMessage for {} to {}", dht_key, closest_peer); send_control_message( closest_peer, @@ -1195,7 +1213,7 @@ namespace llarp log::info( logcat, "Relayed FindClientContactMessage {}! Relaying response...", - msg ? "succeeded" + msg ? "SUCCEEDED" : msg.timed_out ? "timed out" : "failed"); log::info(logcat, "Relayed FindClientContactMessage response: {}", buffer_printer{msg.body()}); diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index d407dc26d4..c994f3854e 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -161,11 +161,11 @@ namespace llarp void handle_path_data_message(bstring dgram); std::shared_ptr make_control( - oxen::quic::connection_interface& ci, const RouterID& rid); + const std::shared_ptr& ci, const RouterID& rid); - void on_inbound_conn(oxen::quic::connection_interface& ci); + void on_inbound_conn(std::shared_ptr ci); - void on_outbound_conn(oxen::quic::connection_interface& ci); + void on_outbound_conn(RouterID id); void on_conn_open(oxen::quic::connection_interface& ci); diff --git a/llarp/messages/dht.hpp b/llarp/messages/dht.hpp index b65e27e03c..97ad64bb73 100644 --- a/llarp/messages/dht.hpp +++ b/llarp/messages/dht.hpp @@ -85,7 +85,7 @@ namespace llarp Note: we are bt-encoding to leave space for future fields (ex: version) */ - inline static std::string serialize_response(const EncryptedClientContact& ecc) + inline static std::string serialize_response(EncryptedClientContact ecc) { oxenc::bt_dict_producer btdp; diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index 58bf824576..1795057c68 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -295,7 +295,7 @@ namespace llarp for (const auto& [rid, count] : rid_result_counters) { - log::info(logcat, "RID: {}, Freq: {}", rid.ShortString(), count); + log::trace(logcat, "RID: {}, Freq: {}", rid.ShortString(), count); if (count >= MIN_RID_FETCH_FREQ) union_set.insert(rid); else diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index c5ed6df9fc..ee54a6578b 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -82,26 +82,24 @@ namespace llarp::path bool PathContext::has_transit_hop(const std::shared_ptr& hop) const { - return _r.loop()->call_get( - [&]() { return _transit_hops.count(hop->rxid()) or _transit_hops.count(hop->txid()); }); + assert(_r.loop()->in_event_loop()); + return _transit_hops.count(hop->rxid()) or _transit_hops.count(hop->txid()); } void PathContext::put_transit_hop(std::shared_ptr hop) { - _r.loop()->call([&]() { - _transit_hops.emplace(hop->rxid(), hop); - _transit_hops.emplace(hop->txid(), hop); - }); + assert(_r.loop()->in_event_loop()); + _transit_hops.emplace(hop->rxid(), hop); + _transit_hops.emplace(hop->txid(), hop); } std::shared_ptr PathContext::get_transit_hop(const HopID& path_id) const { - return _r.loop()->call_get([&]() -> std::shared_ptr { - if (auto itr = _transit_hops.find(path_id); itr != _transit_hops.end()) - return itr->second; + assert(_r.loop()->in_event_loop()); + if (auto itr = _transit_hops.find(path_id); itr != _transit_hops.end()) + return itr->second; - return nullptr; - }); + return nullptr; } void PathContext::_drop_path(const HopID& hop_id) diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index b32d5ee4da..a169b078f1 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -79,9 +79,6 @@ namespace llarp::path if (auto itr = _paths.find(p->upstream_rxid()); itr != _paths.end()) _paths.erase(itr); - // if (auto itr = _paths.find(p->pivot_txid()); itr != _paths.end()) - // _paths.erase(itr); - _router.path_context()->drop_path(p); } diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 51014d3d71..84442e135c 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -246,7 +246,7 @@ namespace llarp std::set Router::get_current_remotes() const { - return _loop->call_get([this]() { return _link_manager->get_current_remotes(); }); + return _link_manager->get_current_remotes(); } void Router::for_each_connection(std::function func) From acc6bf19bccf363455546cbc443444fcea645c67 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Mon, 18 Nov 2024 09:19:25 -0800 Subject: [PATCH 28/44] squash --- llarp/address/address.hpp | 4 +- llarp/contact/client_contact.cpp | 2 - llarp/contact/client_contact.hpp | 10 +-- llarp/contact/contactdb.cpp | 2 +- llarp/contact/keys.cpp | 3 +- llarp/crypto/crypto.cpp | 2 +- llarp/handlers/session.cpp | 131 ++++++++++++++++++++++--------- llarp/link/link_manager.cpp | 107 ++++++++++++++++--------- llarp/path/path_context.cpp | 64 +++++++-------- llarp/path/path_handler.cpp | 79 ++++++++++++++++++- llarp/path/path_handler.hpp | 5 ++ llarp/router/router.cpp | 2 +- 12 files changed, 286 insertions(+), 125 deletions(-) diff --git a/llarp/address/address.hpp b/llarp/address/address.hpp index 93c258dca3..c38101a67b 100644 --- a/llarp/address/address.hpp +++ b/llarp/address/address.hpp @@ -40,7 +40,9 @@ namespace llarp explicit NetworkAddress(std::string_view addr, std::string_view tld); // This private constructor expects NO '.snode' or '.loki' suffix - explicit NetworkAddress(RouterID rid, bool is_client) : _pubkey{std::move(rid)}, _is_client{is_client} {} + explicit NetworkAddress(RouterID rid, bool is_client) + : _pubkey{std::move(rid)}, _is_client{is_client}, _tld{_is_client ? TLD::LOKI : TLD::SNODE} + {} public: NetworkAddress() = default; diff --git a/llarp/contact/client_contact.cpp b/llarp/contact/client_contact.cpp index aaf6ce48e2..b310961804 100644 --- a/llarp/contact/client_contact.cpp +++ b/llarp/contact/client_contact.cpp @@ -105,9 +105,7 @@ namespace llarp pubkey.from_string(btdc.require("a")); if (btdc.skip_until("e")) - { exit_policy->bt_decode(btdc.consume_dict_consumer()); - } btdc.required("i"); diff --git a/llarp/contact/client_contact.hpp b/llarp/contact/client_contact.hpp index f01626dc21..e15a0c623a 100644 --- a/llarp/contact/client_contact.hpp +++ b/llarp/contact/client_contact.hpp @@ -145,14 +145,8 @@ namespace llarp public: bool operator==(const ClientContact& other) const { - return std::tie(derived_privatekey, pubkey, intros, SRVs, protos, exit_policy) - == std::tie( - other.derived_privatekey, - other.pubkey, - other.intros, - other.SRVs, - other.protos, - other.exit_policy); + return std::tie(pubkey, intros, SRVs, protos, exit_policy) + == std::tie(other.pubkey, other.intros, other.SRVs, other.protos, other.exit_policy); } bool operator!=(const ClientContact& other) const { return !(*this == other); } diff --git a/llarp/contact/contactdb.cpp b/llarp/contact/contactdb.cpp index be3e229498..6bc0e5582c 100644 --- a/llarp/contact/contactdb.cpp +++ b/llarp/contact/contactdb.cpp @@ -40,7 +40,7 @@ namespace llarp void ContactDB::put_cc(EncryptedClientContact enc) { - _router.loop()->call([&]() { _cc_nodes->put_node(enc); }); + _cc_nodes->put_node(enc); } } // namespace llarp diff --git a/llarp/contact/keys.cpp b/llarp/contact/keys.cpp index 1005244d12..68467b285b 100644 --- a/llarp/contact/keys.cpp +++ b/llarp/contact/keys.cpp @@ -1,5 +1,6 @@ #include "keys.hpp" +#include #include namespace llarp @@ -14,7 +15,7 @@ namespace llarp std::string PubKey::to_string() const { - return oxenc::to_hex(begin(), end()); + return oxenc::to_base32z(begin(), end()); } PubKey& PubKey::operator=(const uint8_t* ptr) diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index b14cc4b3f9..6df600a7ad 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -341,7 +341,7 @@ namespace llarp // scalar h = H( BLIND-STRING || root_pubkey || key_n ) std::array h = crypto::make_scalar(root_pubkey, key_n); - return 0 == crypto_scalarmult_ed25519(derived, h.data(), root_pubkey.data()); + return 0 == crypto_scalarmult_ed25519_noclamp(derived, h.data(), root_pubkey.data()); } void crypto::randomize(uint8_t* buf, size_t len) diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index 99744b693f..cb3be1e565 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -121,6 +121,10 @@ namespace llarp::handlers size_t count{0}; log::debug(logcat, "SessionEndpoint building {} paths to random remotes (needed: {})", n, num_paths_desired); + // TESTNET: ensure one path is built to pivot + RouterID pivot{oxenc::from_base32z("55fxrybf3jtausbnmxpgwcsz9t8qkf5pr8t5f4xyto4omjrkorpy")}; + count += build_path_aligned_to_remote(pivot); + while (count < n) count += build_path_to_random(); @@ -136,6 +140,8 @@ namespace llarp::handlers update_and_publish_localcc(get_current_client_intros(), _srv_records); } + static std::atomic testnet_trigger = false; + void SessionEndpoint::start_tickers() { if (should_publish_cc) @@ -148,6 +154,25 @@ namespace llarp::handlers update_and_publish_localcc(get_current_client_intros()); }, true); + + if (not testnet_trigger) + { + testnet_trigger = true; + + _router.loop()->call_later(15s, [this]() { + try + { + RouterID cpk{oxenc::from_base32z("mu44r4peshzwmcx5fcaj7eb6sdp9xbx5xw5iyc18hfg4q11zjfry")}; + log::info(logcat, "Beginning session init to client: {}", cpk.to_network_address(false)); + _initiate_session( + NetworkAddress::from_pubkey(cpk, true), [](ip_v) { log::critical(logcat, "FUCK YEAH"); }); + } + catch (const std::exception& e) + { + log::critical(logcat, "Failed to parse client netaddr: {}", e.what()); + } + }); + } } else log::info(logcat, "SessionEndpoint configured to NOT publish ClientContact..."); @@ -268,49 +293,62 @@ namespace llarp::handlers if (auto maybe_intro = _router.contact_db().get_decrypted_cc(remote)) { - log::info(logcat, "Decrypted clientcontact for remote (rid: {}) found locally!", remote); + log::info(logcat, "Decrypted ClientContact for remote (rid: {}) found locally!", remote); return func(std::move(maybe_intro)); } - log::info(logcat, "Looking up clientcontact for remote (rid:{})", remote.to_network_address(false)); + log::info( + logcat, + "Looking up ClientContact (key: {}) for remote (rid:{})", + remote_key, + remote.to_network_address(false)); - auto response_handler = [this, remote, hook = std::move(func)](oxen::quic::message m) mutable { - try - { - if (m) + auto ignore_remaining = std::make_shared(false); + + auto response_handler = + [this, remote, hook = std::move(func), ignore_remaining](oxen::quic::message m) mutable { + if (ignore_remaining->load()) + { + log::trace(logcat, "Dropping subsequent `find_cc` response (success: {})...", not m.is_error()); + return; + } + try { - log::critical(logcat, "Call to FindClientContact succeeded!"); + if (m) + { + log::critical(logcat, "Call to FindClientContact succeeded!"); - auto enc = FindClientContact::deserialize_response(oxenc::bt_dict_consumer{m.body()}); + auto enc = FindClientContact::deserialize_response(oxenc::bt_dict_consumer{m.body()}); - if (auto intro = enc.decrypt(remote)) - { - log::info(logcat, "Storing ClientContact for remote rid:{}", remote); - _router.contact_db().put_cc(std::move(enc)); - return hook(std::move(intro)); + if (auto intro = enc.decrypt(remote)) + { + log::info(logcat, "Storing ClientContact for remote rid:{}", remote); + _router.contact_db().put_cc(std::move(enc)); + ignore_remaining->store(true); + return hook(std::move(intro)); + } + + log::warning(logcat, "Failed to decrypt returned EncryptedClientContact!"); } + else + { + std::optional status = std::nullopt; + oxenc::bt_dict_consumer btdc{m.body()}; - log::warning(logcat, "Failed to decrypt returned EncryptedClientContact!"); + if (auto s = btdc.maybe(messages::STATUS_KEY)) + status = s; + + log::warning( + logcat, "Call to FindClientContact FAILED; reason: {}", status.value_or("")); + } } - else + catch (const std::exception& e) { - std::optional status = std::nullopt; - oxenc::bt_dict_consumer btdc{m.body()}; - - if (auto s = btdc.maybe(messages::STATUS_KEY)) - status = s; - - log::warning( - logcat, "Call to FindClientContact FAILED; reason: {}", status.value_or("")); + log::warning(logcat, "Exception: {}", e.what()); } - } - catch (const std::exception& e) - { - log::warning(logcat, "Exception: {}", e.what()); - } - hook(std::nullopt); - }; + hook(std::nullopt); + }; { Lock_t l{paths_mutex}; @@ -322,7 +360,7 @@ namespace llarp::handlers log::debug( logcat, - "Querying pivot (rid:{}) for clientcontact lookup target (rid:{})", + "Querying pivot (rid:{}) for ClientContact lookup target (rid:{})", path->pivot_rid(), remote); @@ -618,6 +656,7 @@ namespace llarp::handlers void SessionEndpoint::_make_session_path( intro_set intros, NetworkAddress remote, on_session_init_hook cb, bool is_exit) { + log::debug(logcat, "{} called", __PRETTY_FUNCTION__); // we can recurse through this function as we remove the first pivot of the set of introductions every // invocation if (intros.empty()) @@ -627,7 +666,28 @@ namespace llarp::handlers return; } - auto intro = intros.extract(intros.begin()).value(); + // TESTNET: + RouterID edge{oxenc::from_base32z("55fxrybf3jtausbnmxpgwcsz9t8qkf5pr8t5f4xyto4omjrkorpy")}; + bool using_hacky_bullshit{false}; + + ClientIntro intro; + + for (auto itr = intros.begin(); itr != intros.end(); ++itr) + { + log::debug(logcat, "itr->pivot_rid: {}", itr->pivot_rid); + if (itr->pivot_rid == edge) + { + using_hacky_bullshit = true; + intro = intros.extract(itr).value(); + break; + } + } + + if (not using_hacky_bullshit) + { + intro = intros.extract(intros.begin()).value(); + } + auto& pivot = intro.pivot_rid; // TOTHINK: why would we ever have a path keyed to remote client intro pivot txid? @@ -648,7 +708,7 @@ namespace llarp::handlers if (not maybe_hops) { log::error(logcat, "Failed to get hops for path-build to pivot:{}", pivot); - return; + return _make_session_path(std::move(intros), std::move(remote), std::move(cb), is_exit); } auto& hops = *maybe_hops; @@ -675,6 +735,7 @@ namespace llarp::handlers { // Do not call ::add_path() or ::path_build_succeeded() here; OutboundSession constructor will // take care of both path storage and logging in PathContext + log::critical(logcat, "PATH ESTABLISHED: {}", path->hop_string()); log::info(logcat, "Path build to remote:{} succeeded, initiating session!", remote); return _make_session( std::move(remote), std::move(remote_intro), std::move(path), std::move(hook), is_exit); @@ -719,7 +780,7 @@ namespace llarp::handlers _router.loop()->call([this, remote, handler = std::move(cb), is_exit, counter]() mutable { lookup_client_intro( remote.router_id(), - [this, remote, hook = std::move(handler), is_exit, counter](std::optional cc) { + [this, remote, hook = std::move(handler), is_exit, counter](std::optional cc) mutable { if (*counter == 0) return; @@ -730,7 +791,7 @@ namespace llarp::handlers _make_session_path(std::move(cc->intros), remote, std::move(hook), is_exit); } else if (--*counter == 0) - log::warning(logcat, "Failed to initiate session at 'find_cc' (target:{})", remote); + log::warning(logcat, "Failed to initiate session at 'find_cc' (target:{})", remote.router_id()); }); }); diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index cb7d34ea92..0f86407a98 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -57,18 +57,19 @@ namespace llarp std::shared_ptr Endpoint::get_conn(const RouterID& remote) const { - return link_manager.router().loop()->call_get([this, rid = remote]() -> std::shared_ptr { - if (auto itr = service_conns.find(rid); itr != service_conns.end()) - return itr->second; + if (auto itr = service_conns.find(remote); itr != service_conns.end()) + return itr->second; - if (_is_service_node) - { - if (auto itr = client_conns.find(rid); itr != client_conns.end()) - return itr->second; - } + if (_is_service_node) + { + if (auto itr = client_conns.find(remote); itr != client_conns.end()) + return itr->second; + } - return nullptr; - }); + return nullptr; + // return link_manager.router().loop()->call_get([this, rid = remote]() -> std::shared_ptr + // { + // }); } bool Endpoint::have_conn(const RouterID& remote) const @@ -1106,7 +1107,7 @@ namespace llarp // allow it to continue propagating if (not inner_body) { - log::critical(logcat, "Received relayed PublishClientContact request; accepting..."); + log::critical(logcat, "Received relayed PublishClientContact request (key: {}); accepting...", enc.key()); _router.contact_db().put_cc(std::move(enc)); return m.respond(messages::OK_RESPONSE); } @@ -1137,7 +1138,11 @@ namespace llarp } } - log::info(logcat, "Received PublishClientContact; propagating to closest peer (key: {})...", closest_peer); + log::info( + logcat, + "Received PublishClientContact (key: {}); propagating to closest peer (rid: {})...", + enc.key(), + closest_peer); send_control_message( closest_peer, @@ -1181,44 +1186,72 @@ namespace llarp if (auto maybe_cc = _router.contact_db().get_encrypted_cc(dht_key)) { - log::info(logcat, "Received FindClientContact request; returning local EncryptedClientContact..."); + log::info( + logcat, + "Received FindClientContact request (key: {}); returning local EncryptedClientContact...", + dht_key); return m.respond(FindClientContact::serialize_response(std::move(*maybe_cc))); } + // If the optional was nullopt, then this was a relay <-> relay request. As a result, we should NOT // allow it to continue propagating if (not inner_body) { - log::critical(logcat, "Received relayed FindClientContact request; could not find locally, relaying error..."); + log::critical( + logcat, + "Received relayed FindClientContact request (key: {}); could not find locally, relaying error...", + dht_key); return m.respond(FindClientContact::NOT_FOUND, true); } - auto closest_peer = _router.node_db()->find_closest_to(dht_key).router_id(); + auto local_rid = _router.local_rid(); + + auto closest_rcs = _router.node_db()->find_many_closest_to(dht_key, path::DEFAULT_PATHS_HELD); + auto n_closest = closest_rcs.size(); - if (closest_peer == _router.local_rid()) + for (const auto& rc : closest_rcs) { - log::warning( - logcat, - "We are closest peer for FindClientContact request (key: {}); no EncryptedClientContact found locally!", - dht_key); - return m.respond(FindClientContact::NOT_FOUND, true); + auto& _rid = rc.router_id(); + + if (_rid == local_rid) + { + log::warning( + logcat, + "We are closest peer for FindClientContact request (key: {}); no EncryptedClientContact found" + "locally!", + dht_key); + return m.respond(FindClientContact::NOT_FOUND, true); + } } - log::debug(logcat, "Relaying FindClientContactMessage for {} to {}", dht_key, closest_peer); + auto counter = std::make_shared(n_closest); - send_control_message( - closest_peer, - "find_cc", - FindClientContact::serialize(dht_key), - [prev_msg = std::move(m)](oxen::quic::message msg) mutable { - log::info( - logcat, - "Relayed FindClientContactMessage {}! Relaying response...", - msg ? "SUCCEEDED" - : msg.timed_out ? "timed out" - : "failed"); - log::info(logcat, "Relayed FindClientContactMessage response: {}", buffer_printer{msg.body()}); - prev_msg.respond(msg.body_str(), msg.is_error()); - }); + auto hook = [prev_msg = std::move(m), counter](oxen::quic::message msg) mutable { + if (*counter == 0) + return; + + if (msg) + { + *counter = 0; + log::info(logcat, "Relayed FindClientContact request SUCCEEDED! Relaying response..."); + log::info(logcat, "Relayed FindClientContact response: {}", buffer_printer{msg.body()}); + } + else if (--*counter == 0) + { + log::warning(logcat, "All FindClientContact requests FAILED! Relaying response..."); + } + else + return; + + prev_msg.respond(msg.body_str(), msg.is_error()); + }; + + log::info(logcat, "Relaying FindClientContactMessage (key: {}) to {} peers", dht_key, n_closest); + + for (const auto& rc : closest_rcs) + { + send_control_message(rc.router_id(), "find_cc", FindClientContact::serialize(dht_key), hook); + } } void LinkManager::handle_find_cc(oxen::quic::message m) @@ -1353,6 +1386,7 @@ namespace llarp catch (const std::exception& e) { log::warning(logcat, "Exception: {}", e.what()); + log::warning(logcat, "Payload: {}", inner_body ? buffer_printer{*inner_body} : buffer_printer{m.body()}); return m.respond(messages::ERROR_RESPONSE, true); } @@ -1596,7 +1630,6 @@ namespace llarp log::warning(logcat, "Exception: {}", e.what()); } - _router.path_context()->drop_path(path_ptr); m.respond(messages::ERROR_RESPONSE, true); } diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index ee54a6578b..85c1d596c5 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -22,42 +22,36 @@ namespace llarp::path void PathContext::add_path(std::shared_ptr path) { - _r.loop()->call([&]() { - _path_map.emplace(path->upstream_rxid(), path); - _path_map.emplace(path->pivot_txid(), path); - }); + _path_map.emplace(path->upstream_rxid(), path); + _path_map.emplace(path->pivot_txid(), path); } void PathContext::drop_paths(std::vector droplist) { - _r.loop()->call([&]() { - for (auto itr = droplist.begin(); itr != droplist.end();) - { - _drop_path(*itr); - itr = droplist.erase(itr); - } - }); + for (auto itr = droplist.begin(); itr != droplist.end();) + { + _drop_path(*itr); + itr = droplist.erase(itr); + } } void PathContext::expire_hops(std::chrono::milliseconds now) { - _r.loop()->call([&]() { - size_t n = 0; + size_t n = 0; - for (auto itr = _transit_hops.begin(); itr != _transit_hops.end();) + for (auto itr = _transit_hops.begin(); itr != _transit_hops.end();) + { + if (itr->second->is_expired(now)) { - if (itr->second->is_expired(now)) - { - itr = _transit_hops.erase(itr); - n += 1; - } - else - ++itr; + itr = _transit_hops.erase(itr); + n += 1; } + else + ++itr; + } - if (n) - log::info(logcat, "{} expired TransitHops purged!", n); - }); + if (n) + log::info(logcat, "{} expired TransitHops purged!", n); } void PathContext::drop_path(const HopID& hop_id) @@ -67,10 +61,8 @@ namespace llarp::path void PathContext::drop_path(const std::shared_ptr& path) { - _r.loop()->call([&]() { - _drop_path(path->upstream_rxid()); - _drop_path(path->pivot_txid()); - }); + _drop_path(path->upstream_rxid()); + _drop_path(path->pivot_txid()); } std::tuple PathContext::path_ctx_stats() const @@ -122,20 +114,20 @@ namespace llarp::path std::shared_ptr PathContext::get_path(const HopID& hop_id) const { - return _r.loop()->call_get([&]() -> std::shared_ptr { return _get_path(hop_id); }); + assert(_r.loop()->in_event_loop()); + return _get_path(hop_id); } std::shared_ptr PathContext::get_path(const std::shared_ptr& hop) const { - return _r.loop()->call_get([&]() -> std::shared_ptr { - if (auto maybe_path = _get_path(hop->rxid())) - return maybe_path; + assert(_r.loop()->in_event_loop()); + if (auto maybe_path = _get_path(hop->rxid())) + return maybe_path; - if (auto maybe_path = _get_path(hop->txid())) - return maybe_path; + if (auto maybe_path = _get_path(hop->txid())) + return maybe_path; - return nullptr; - }); + return nullptr; } std::shared_ptr PathContext::get_path_handler(const HopID& id) diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index a169b078f1..1fb40e3c9a 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -67,7 +67,6 @@ namespace llarp::path Lock_t l(paths_mutex); _paths.insert_or_assign(p->upstream_rxid(), p); - // _paths.insert_or_assign(p->pivot_txid(), p); _router.path_context()->add_path(p); } @@ -217,6 +216,7 @@ namespace llarp::path if (itr->second and itr->second->is_established() and itr->second->is_expired(now)) { to_drop.push_back(itr->second->upstream_rxid()); + to_drop.push_back(itr->second->pivot_txid()); itr = _paths.erase(itr); } else @@ -405,6 +405,73 @@ namespace llarp::path return std::nullopt; } + // std::optional> PathHandler::specific_hops_to_remote(std::vector specifgic) + // { + // log::trace(logcat, "{} called", __PRETTY_FUNCTION__); + + // assert(num_hops); + + // auto hops_needed = num_hops; + // std::vector hops{}; + + // } + + std::optional> PathHandler::aligned_hops_between(const RouterID& edge, const RouterID& pivot) + { + log::trace(logcat, "{} called", __PRETTY_FUNCTION__); + + assert(num_hops); + auto hops_needed = num_hops; + + if (hops_needed == 1) + { + log::error(logcat, "Stop using debug methods for stupid path structures"); + return std::nullopt; + } + + std::vector hops{}; + + RemoteRC pivot_rc{}; + + if (auto maybe = _router.node_db()->get_rc(pivot)) + { + // leave space to add the pivot last + --hops_needed; + pivot_rc = std::move(*maybe); + } + else + return std::nullopt; + + if (auto maybe = _router.node_db()->get_rc(edge)) + { + // leave space to add the pivot last + --hops_needed; + hops.emplace_back(std::move(*maybe)); + } + else + return std::nullopt; + + auto filter = [&](const RemoteRC& rc) -> bool { + const auto& rid = rc.router_id(); + + if (rid == edge || rid == pivot) + return false; + + return true; + }; + + if (auto maybe_rcs = _router.node_db()->get_n_random_rcs_conditional(hops_needed, filter)) + { + log::info(logcat, "Found {} RCs for aligned path (needed: {})", maybe_rcs->size(), hops_needed); + hops.insert(hops.end(), maybe_rcs->begin(), maybe_rcs->end()); + hops.emplace_back(std::move(pivot_rc)); + return hops; + } + + log::warning(logcat, "Failed to find RC for aligned path! (needed:{})", num_hops); + return std::nullopt; + } + std::optional> PathHandler::aligned_hops_to_remote( const RouterID& pivot, const std::set& exclude) { @@ -470,6 +537,8 @@ namespace llarp::path }); }; + log::debug(logcat, "First/last hop selected, {} hops remaining to select", hops_needed); + while (hops_needed) { // do this 1 at a time so we can check for IP range overlap @@ -480,7 +549,13 @@ namespace llarp::path else { log::warning( - logcat, "Failed to find RC for aligned path! (needed:{}, found:{})", num_hops, hops_needed); + logcat, "Failed to find RC for aligned path! (needed:{}, remaining:{})", num_hops, hops_needed); + + if (not hops.empty()) + { + for (auto& h : hops) + log::info(logcat, "{}", h); + } return std::nullopt; } diff --git a/llarp/path/path_handler.hpp b/llarp/path/path_handler.hpp index 33f7e3e888..630bba4749 100644 --- a/llarp/path/path_handler.hpp +++ b/llarp/path/path_handler.hpp @@ -207,6 +207,11 @@ namespace llarp bool build_path_aligned_to_remote(const RouterID& remote); + // TESTNET: testing methods + // std::optional> specific_hops_to_remote(std::vector hops); + + std::optional> aligned_hops_between(const RouterID& edge, const RouterID& pivot); + std::optional> aligned_hops_to_remote( const RouterID& pivot, const std::set& exclude = {}); diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 84442e135c..5a5e3c7a42 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -1100,7 +1100,7 @@ namespace llarp false); } - log::critical(logcat, "\n\n\tLOCAL INSTANCE ROUTER ID: {}\n", local_rid()); + log::critical(logcat, "\n\n\tLOCAL INSTANCE ROUTER ID: {}\n", local_rid().to_network_address(_is_service_node)); llarp::sys::service_manager->ready(); return _is_running.load(); From a1655281fdd22c0112d42aa4f879f553bc3a3c77 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Mon, 18 Nov 2024 16:15:40 -0800 Subject: [PATCH 29/44] squash again whatever --- llarp/handlers/session.cpp | 17 +++++++++-------- llarp/link/link_manager.cpp | 13 +++++++------ llarp/path/path_handler.cpp | 30 ++++++++++++++++++++++++------ 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index cb3be1e565..f1ea2ceb8a 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -162,7 +162,7 @@ namespace llarp::handlers _router.loop()->call_later(15s, [this]() { try { - RouterID cpk{oxenc::from_base32z("mu44r4peshzwmcx5fcaj7eb6sdp9xbx5xw5iyc18hfg4q11zjfry")}; + RouterID cpk{oxenc::from_base32z("dwdumrr58ce9hkabciq7q8e8f3o31is3gciw8zi4chdzrc5a6u4o")}; log::info(logcat, "Beginning session init to client: {}", cpk.to_network_address(false)); _initiate_session( NetworkAddress::from_pubkey(cpk, true), [](ip_v) { log::critical(logcat, "FUCK YEAH"); }); @@ -580,18 +580,19 @@ namespace llarp::handlers auto inner_payload = PATH::CONTROL::serialize("session_init", std::move(client_payload)); // add path-control wrapping for pivot to relay to aligned path - auto& pivot = path->hops.back(); + // auto& pivot = path->hops.back(); auto onion_nonce = SymmNonce::make_random(); - crypto::onion( - reinterpret_cast(inner_payload.data()), - inner_payload.size(), - pivot.shared, - onion_nonce, - onion_nonce); + // crypto::onion( + // reinterpret_cast(inner_payload.data()), + // inner_payload.size(), + // pivot.shared, + // onion_nonce, + // onion_nonce); auto pivot_payload = ONION::serialize_hop(remote_intro.pivot_txid.to_view(), onion_nonce, inner_payload); auto intermediate_payload = PATH::CONTROL::serialize("path_control", std::move(pivot_payload)); + // auto intermediate_payload = PATH::CONTROL::serialize("path_control", std::move(inner_payload)); path->send_path_control_message( "path_control", diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 0f86407a98..7da0a82b70 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1563,6 +1563,13 @@ namespace llarp try { std::tie(endpoint, body) = PATH::CONTROL::deserialize(oxenc::bt_dict_consumer{payload}); + + if (endpoint == "path_control") + { + log::info(logcat, "Received path control relay request; deserializing intermediate payload..."); + auto [_, i_body] = PATH::CONTROL::deserialize(oxenc::bt_dict_consumer{std::move(body)}); + return _handle_path_control(std::move(m), std::move(i_body)); + } } catch (const std::exception& e) { @@ -1575,12 +1582,6 @@ namespace llarp log::debug(logcat, "Received path control request (`{}`); invoking endpoint...", endpoint); std::invoke(it->second, this, std::move(m), std::move(body)); } - else if (endpoint == "path_control") - { - log::warning(logcat, "Path control should have been invoked in the last conditional!"); - log::debug(logcat, "Received path control relay request..."); - return _handle_path_control(std::move(m), std::move(body)); - } else log::warning(logcat, "Received path control request (`{}`), which has no local handler!", endpoint); } diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index 1fb40e3c9a..5eaec3ac41 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -505,10 +505,13 @@ namespace llarp::path // make a copy here to reference rather than creating one in the lambda every iteration std::set to_exclude{exclude.begin(), exclude.end()}; to_exclude.insert(pivot); + std::vector excluded_ranges{}; + excluded_ranges.emplace_back(pivot_rc.addr().to_ipv4() / netmask); if (auto maybe = select_first_hop(to_exclude)) { hops.push_back(*maybe); + excluded_ranges.emplace_back(maybe->addr().to_ipv4() / netmask); --hops_needed; } else @@ -521,6 +524,15 @@ namespace llarp::path auto filter = [&](const RemoteRC& rc) -> bool { const auto& rid = rc.router_id(); + auto v4 = rc.addr().to_ipv4(); + + for (auto& e : excluded_ranges) + { + if (e.contains(v4)) + return false; + } + + excluded_ranges.emplace_back(v4 / netmask); // if its already excluded, fail; (we want it added even on success) if (not to_exclude.insert(rid).second) @@ -529,16 +541,22 @@ namespace llarp::path if (_router.router_profiling().is_bad_for_path(rid, 1)) return false; - if (pivot_rc.has_ip_overlap(rc, netmask)) - return false; - - return not std::any_of(hops.begin(), hops.end(), [&](const RemoteRC& other) -> bool { - return other.has_ip_overlap(rc, netmask); - }); + return true; }; log::debug(logcat, "First/last hop selected, {} hops remaining to select", hops_needed); + if (auto maybe_hops = _router.node_db()->get_n_random_rcs_conditional(hops_needed, filter)) + { + log::info(logcat, "Found {} RCs for aligned path (needed: {})", maybe_hops->size(), hops_needed); + hops.insert(hops.end(), maybe_hops->begin(), maybe_hops->end()); + hops.emplace_back(std::move(pivot_rc)); + return hops; + } + + log::warning(logcat, "Failed to find {} RCs for aligned path to pivot: {}", hops_needed, pivot); + return std::nullopt; + while (hops_needed) { // do this 1 at a time so we can check for IP range overlap From a1fc8b5adb86b0df5edf0905580ab961a9b73d57 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Tue, 19 Nov 2024 14:22:32 -0800 Subject: [PATCH 30/44] yeehaw --- llarp/auth/session_auth.cpp | 2 +- llarp/crypto/crypto.cpp | 17 ++---- llarp/crypto/crypto.hpp | 13 ++-- llarp/crypto/key_manager.cpp | 2 +- llarp/crypto/types.cpp | 46 ++++++++++++++- llarp/crypto/types.hpp | 30 ++++++++++ llarp/handlers/session.cpp | 39 ++++++++---- llarp/handlers/session.hpp | 8 ++- llarp/link/link_manager.cpp | 97 ++++++++++++++++++------------ llarp/link/link_manager.hpp | 2 + llarp/messages/path.hpp | 111 +++++++++++++++++++++++------------ llarp/messages/session.hpp | 70 +++++++++++----------- llarp/path/path.cpp | 15 ++++- llarp/path/path.hpp | 10 +++- llarp/path/path_context.cpp | 14 ++++- llarp/path/path_context.hpp | 4 ++ llarp/path/path_handler.cpp | 18 +++--- llarp/path/transit_hop.cpp | 28 ++++----- llarp/path/transit_hop.hpp | 10 +--- llarp/session/session.cpp | 61 +++++++++---------- llarp/session/session.hpp | 19 +++--- 21 files changed, 390 insertions(+), 226 deletions(-) diff --git a/llarp/auth/session_auth.cpp b/llarp/auth/session_auth.cpp index 729ade273f..e170010f60 100644 --- a/llarp/auth/session_auth.cpp +++ b/llarp/auth/session_auth.cpp @@ -17,7 +17,7 @@ namespace llarp::auth if (_is_snode_service) _session_key = _router.identity(); else - crypto::identity_keygen(_session_key); + _session_key = crypto::generate_identity(); } std::optional SessionAuthPolicy::fetch_auth_token() diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index 6df600a7ad..43691c4c07 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -264,7 +264,7 @@ namespace llarp const SymmNonce& nonce, uspan encrypted) { - // derive shared secret using ephemeral pubkey and our secret key (and nonce) + // derive shared secret using shared secret and our secret key (and nonce) if (!crypto::dh_server(shared, remote, local_sk, nonce)) { auto err = "DH server failed during shared key derivation!"s; @@ -354,13 +354,15 @@ namespace llarp randombytes((unsigned char*)ptr, sz); } - void crypto::identity_keygen(Ed25519SecretKey& keys) + Ed25519SecretKey crypto::generate_identity() { + Ed25519SecretKey ret{}; PubKey pk; - int result = crypto_sign_ed25519_keypair(pk.data(), keys.data()); + int result = crypto_sign_ed25519_keypair(pk.data(), ret.data()); assert(result != -1); - const PubKey sk_pk = keys.to_pubkey(); + const PubKey sk_pk = ret.to_pubkey(); assert(pk == sk_pk); + return ret; } bool crypto::check_identity_privkey(const Ed25519SecretKey& keys) @@ -375,13 +377,6 @@ namespace llarp return keys.to_pubkey() == pk && sk == keys; } - void crypto::encryption_keygen(Ed25519SecretKey& keys) - { - auto d = keys.data(); - randbytes(d, 32); - crypto_scalarmult_curve25519_base(d + 32, d); // expects xkey - } - #ifdef HAVE_CRYPT bool crypto::check_passwd_hash(std::string pwhash, std::string challenge) { diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index 39dcfb8ad1..47c88f6e26 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -70,6 +70,13 @@ namespace llarp const RouterID& remote, uspan payload); + // void derive_encrypt_outer_wrapping( + // const Ed25519SecretKey& shared_key, + // SharedSecret& secret, + // const SymmNonce& nonce, + // const RouterID& remote, + // uspan payload); + /// Used in receiving path-build and session initiation messages. Derives a shared secret key using an ephemeral /// pubkey and the provided nonce. The encrypted payload is mutated in-place. Will throw on failure of either /// the server DH derivation or the xchacha20 payload mutation @@ -92,11 +99,7 @@ namespace llarp /// randomizer memory void randbytes(uint8_t*, size_t); - /// generate signing keypair - void identity_keygen(Ed25519SecretKey&); - - /// generate encryption keypair - void encryption_keygen(Ed25519SecretKey&); + Ed25519SecretKey generate_identity(); bool check_identity_privkey(const Ed25519SecretKey&); diff --git a/llarp/crypto/key_manager.cpp b/llarp/crypto/key_manager.cpp index 0eed8b9f23..7541a1fa44 100644 --- a/llarp/crypto/key_manager.cpp +++ b/llarp/crypto/key_manager.cpp @@ -36,7 +36,7 @@ namespace llarp else { log::debug(logcat, "Client generating identity key..."); - crypto::identity_keygen(identity_key); + identity_key = crypto::generate_identity(); } identity_data = identity_key.to_eddata(); diff --git a/llarp/crypto/types.cpp b/llarp/crypto/types.cpp index bac0e96493..3b4b6d20b6 100644 --- a/llarp/crypto/types.cpp +++ b/llarp/crypto/types.cpp @@ -1,6 +1,6 @@ #include "types.hpp" -#include +#include #include #include #include @@ -120,4 +120,48 @@ namespace llarp return n; } + shared_kx_data::shared_kx_data(Ed25519SecretKey&& sk) : ephemeral_key{std::move(sk)} + { + pubkey = ephemeral_key.to_pubkey(); + } + + void shared_kx_data::generate_xor() + { + ShortHash xhash; + crypto::shorthash(xhash, shared_secret.data(), shared_secret.size()); + xor_nonce = xhash.data(); // truncate 32 -> 24 + } + + shared_kx_data shared_kx_data::generate() + { + return shared_kx_data{crypto::generate_identity()}; + } + + // TESTNET: TODO: check if the libsodium functions ever actually fail... + + void shared_kx_data::client_dh(const RouterID& remote) + { + if (!crypto::dh_client(shared_secret, remote, ephemeral_key, nonce)) + throw std::runtime_error{"Client DH failed -- should this even ever happen?"}; + } + + void shared_kx_data::server_dh(const Ed25519SecretKey& local_sk) + { + if (!crypto::dh_server(shared_secret, pubkey, local_sk, nonce)) + throw std::runtime_error{"Server DH failed -- should this even ever happen?"}; + } + + void shared_kx_data::encrypt(uspan data) + { + if (!crypto::xchacha20(data.data(), data.size(), shared_secret, nonce)) + throw std::runtime_error{"xchacha20 encryption failed -- should this even ever happen?"}; + } + + // identical methods, separated for clarity of use/logging for now + void shared_kx_data::decrypt(uspan data) + { + if (!crypto::xchacha20(data.data(), data.size(), shared_secret, nonce)) + throw std::runtime_error{"xchacha20 decryption failed -- should this even ever happen?"}; + } + } // namespace llarp diff --git a/llarp/crypto/types.hpp b/llarp/crypto/types.hpp index 62759a36d5..5c7f235d91 100644 --- a/llarp/crypto/types.hpp +++ b/llarp/crypto/types.hpp @@ -3,6 +3,7 @@ #include "constants.hpp" #include +#include #include #include @@ -12,6 +13,7 @@ namespace llarp { using SharedSecret = AlignedBuffer; + struct RouterID; struct PubKey; struct Ed25519PrivateData; @@ -100,4 +102,32 @@ namespace llarp static SymmNonce make_random(); }; + /// Holds all the data used for symmetric DH key-exchange (ex: path-build, session-init, etc) + struct shared_kx_data + { + shared_kx_data() = default; + + private: + shared_kx_data(Ed25519SecretKey&& sk); + + public: + Ed25519SecretKey ephemeral_key; + PubKey pubkey{}; + SharedSecret shared_secret{}; + SymmNonce nonce{SymmNonce::make_random()}; + SymmNonce xor_nonce{SymmNonce::make_random()}; + + void generate_xor(); + + static shared_kx_data generate(); + + void client_dh(const RouterID& remote); + + void server_dh(const Ed25519SecretKey& local_sk); + + void encrypt(uspan data); + + void decrypt(uspan enc); + }; + } // namespace llarp diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index f1ea2ceb8a..a082899b70 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -162,7 +162,7 @@ namespace llarp::handlers _router.loop()->call_later(15s, [this]() { try { - RouterID cpk{oxenc::from_base32z("dwdumrr58ce9hkabciq7q8e8f3o31is3gciw8zi4chdzrc5a6u4o")}; + RouterID cpk{oxenc::from_base32z("4bfu94cyd5t1976qubcwc3nirarri34o4pxq865xrd4krcs8tzxo")}; log::info(logcat, "Beginning session init to client: {}", cpk.to_network_address(false)); _initiate_session( NetworkAddress::from_pubkey(cpk, true), [](ip_v) { log::critical(logcat, "FUCK YEAH"); }); @@ -428,13 +428,17 @@ namespace llarp::handlers } bool SessionEndpoint::prefigure_session( - NetworkAddress initiator, SessionTag tag, std::shared_ptr path, bool use_tun) + NetworkAddress initiator, + SessionTag tag, + std::shared_ptr path, + shared_kx_data kx_data, + bool use_tun) { bool ret = true; - assert(path->is_client_path()); + // assert(path->is_client_path()); - auto inbound = - std::make_shared(initiator, std::move(path), *this, std::move(tag), use_tun); + auto inbound = std::make_shared( + initiator, std::move(path), *this, std::move(tag), use_tun, std::move(kx_data)); auto [session, _] = _sessions.insert_or_assign(std::move(initiator), std::move(inbound)); @@ -557,19 +561,26 @@ namespace llarp::handlers - 't' : Use Tun interface (bool) - 'u' : Authentication field - bt-encoded dict, values TBD - */ + TODO: + - update logic: sessions to relays do not need a shared_kx_data type + - client <-> client rely on symmetric DH across aligned paths + - client <-> relay end at the pivot + */ void SessionEndpoint::_make_session( NetworkAddress remote, ClientIntro remote_intro, std::shared_ptr path, on_session_init_hook cb, - bool is_exit) + bool /* is_exit */) { auto tag = SessionTag::make_random(); + std::string inner_payload; + shared_kx_data kx_data; + // internal payload for remote client - auto client_payload = InitiateSession::serialize_encrypt( + std::tie(inner_payload, kx_data) = InitiateSession::serialize_encrypt( _router.local_rid(), remote.router_id(), tag, @@ -577,7 +588,7 @@ namespace llarp::handlers fetch_auth_token(remote), _router.using_tun_if()); - auto inner_payload = PATH::CONTROL::serialize("session_init", std::move(client_payload)); + log::trace(logcat, "inner payload: {}", buffer_printer{inner_payload}); // add path-control wrapping for pivot to relay to aligned path // auto& pivot = path->hops.back(); @@ -590,20 +601,23 @@ namespace llarp::handlers // onion_nonce); auto pivot_payload = ONION::serialize_hop(remote_intro.pivot_txid.to_view(), onion_nonce, inner_payload); + log::trace(logcat, "pivot payload: {}", buffer_printer{pivot_payload}); auto intermediate_payload = PATH::CONTROL::serialize("path_control", std::move(pivot_payload)); // auto intermediate_payload = PATH::CONTROL::serialize("path_control", std::move(inner_payload)); + log::trace(logcat, "intermediate payload: {}", buffer_printer{intermediate_payload}); path->send_path_control_message( "path_control", std::move(intermediate_payload), - [this, remote, tag, path, hook = std::move(cb), is_exit](oxen::quic::message m) mutable { + [this, remote, tag, path, hook = std::move(cb), session_keys = std::move(kx_data)]( + oxen::quic::message m) mutable { if (m) { log::critical(logcat, "Call to InitiateSession succeeded!"); auto outbound = std::make_shared( - remote, *this, std::move(path), std::move(tag), is_exit); + remote, *this, std::move(path), std::move(tag), std::move(session_keys)); auto [session, _] = _sessions.insert_or_assign(std::move(remote), std::move(outbound)); @@ -652,6 +666,7 @@ namespace llarp::handlers logcat, "Call to InitiateSession FAILED; reason: {}", status.value_or("")); } }); + log::info(logcat, "mesage sent..."); } void SessionEndpoint::_make_session_path( @@ -675,7 +690,7 @@ namespace llarp::handlers for (auto itr = intros.begin(); itr != intros.end(); ++itr) { - log::debug(logcat, "itr->pivot_rid: {}", itr->pivot_rid); + log::trace(logcat, "itr->pivot_rid: {}", itr->pivot_rid); if (itr->pivot_rid == edge) { using_hacky_bullshit = true; diff --git a/llarp/handlers/session.hpp b/llarp/handlers/session.hpp index be9e6928cb..e70255c066 100644 --- a/llarp/handlers/session.hpp +++ b/llarp/handlers/session.hpp @@ -31,7 +31,7 @@ namespace llarp // - Directly pre-loaded from config address_map _range_map; - ClientContact client_contact; // TODO: TESTNET: replacement for service::Introset + ClientContact client_contact; std::shared_ptr _cc_publisher; @@ -122,7 +122,11 @@ namespace llarp bool validate(const NetworkAddress& remote, std::optional maybe_auth = std::nullopt); bool prefigure_session( - NetworkAddress initiator, SessionTag tag, std::shared_ptr path, bool use_tun); + NetworkAddress initiator, + SessionTag tag, + std::shared_ptr path, + shared_kx_data kx_data, + bool use_tun); // lookup SNS address to return "{pubkey}.loki" hidden service or exit node operated on a remote client void resolve_ons(std::string name, std::function)> func = nullptr); diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 7da0a82b70..2bea82c8e7 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1280,17 +1280,7 @@ namespace llarp log::trace(logcat, "Deserializing frame: {}", buffer_printer{frames.front()}); - SymmNonce nonce; - ustring hop_payload; - SharedSecret shared; - - std::tie(nonce, shared, hop_payload) = - PATH::BUILD::deserialize_hop(oxenc::bt_dict_consumer{frames.front()}, _router.identity()); - - log::trace(logcat, "Deserializing hop payload: {}", buffer_printer{hop_payload}); - - auto hop = path::TransitHop::deserialize_hop( - oxenc::bt_dict_consumer{hop_payload}, from, _router, std::move(shared)); + auto hop = PATH::BUILD::deserialize_hop(oxenc::bt_dict_consumer{frames.front()}, _router, from); // we are terminal hop and everything is okay if (hop->upstream() == _router.local_rid()) @@ -1314,7 +1304,7 @@ namespace llarp // clear our frame, to be randomized after onion step and appended frames.back().clear(); - auto onion_nonce = nonce ^ hop->nonceXOR; + auto onion_nonce = hop->kx.nonce ^ hop->kx.xor_nonce; // (de-)onion each further frame using the established shared secret and // onion_nonce = nonce ^ nonceXOR @@ -1326,7 +1316,7 @@ namespace llarp crypto::onion( reinterpret_cast(frames[i].data()), frames[i].size(), - hop->shared, + hop->kx.shared_secret, onion_nonce, onion_nonce); } @@ -1356,7 +1346,7 @@ namespace llarp else log::info(logcat, "Upstream returned path build failure; relaying response"); - return prev_message.respond(m.body(), m.is_error()); + return prev_message.respond(m.body_str(), m.is_error()); }); } catch (const std::exception& e) @@ -1390,39 +1380,53 @@ namespace llarp return m.respond(messages::ERROR_RESPONSE, true); } - auto hop = _router.path_context()->get_transit_hop(hop_id); - - // TODO: when using path control messages for responses/downstream messages, check for the Path - // with the corresponding ID, de-onion, etc - if (not hop) + if (!_is_service_node) { - if (_is_service_node) + auto path = _router.path_context()->get_path(hop_id); + + if (not path) { - log::warning(logcat, "Received path control with unknown next hop (ID: {})", hop_id); + log::warning(logcat, "Client received path control with unknown rxID: {}", hop_id); return m.respond(messages::ERROR_RESPONSE, true); } - if (auto path = _router.path_context()->get_path(hop_id)) + log::info(logcat, "Received path control for local client: {}", buffer_printer{payload}); + + for (size_t i = 0; i < path->hops.size() - 1; ++i) { - log::info(logcat, "Received path control for local client!"); + auto& hop = path->hops[i]; + nonce = crypto::onion( + reinterpret_cast(payload.data()), + payload.size(), + hop.kx.shared_secret, + nonce, + hop.kx.xor_nonce); + + log::info(logcat, "xchacha20 -> {}", buffer_printer{payload}); } + + return handle_path_request(std::move(m), std::move(payload)); } - auto onion_nonce = nonce ^ hop->nonceXOR; + auto hop = _router.path_context()->get_transit_hop(hop_id); - // if we are relaying a path control (inner_body.has_value()), then we do NOT de-onion - if (inner_body) + if (not hop) { - log::info(logcat, "We are pivot for relayed path request! Forwarding downstream ({})", hop->to_string()); + log::warning(logcat, "Received path control with unknown next hop (ID: {})", hop_id); + return m.respond(messages::ERROR_RESPONSE, true); } - else + + auto onion_nonce = nonce ^ hop->kx.xor_nonce; + + // we only de-onion if we are NOT bridging a request over aligned paths + if (not inner_body.has_value()) { crypto::onion( reinterpret_cast(payload.data()), payload.size(), - hop->shared, + hop->kx.shared_secret, onion_nonce, - hop->nonceXOR); + hop->kx.xor_nonce); // if terminal hop, payload should contain a request (e.g. "ons_resolve"); handle and respond. if (hop->terminal_hop) @@ -1433,6 +1437,12 @@ namespace llarp log::debug(logcat, "We are intermediate hop for path request: {}", hop->to_string()); } + else + log::info( + logcat, + "We are bridge node for aligned path request ({})! Forwarding downstream: {}", + hop->to_string(), + buffer_printer{*inner_body}); auto hop_is_rx = hop->rxid() == hop_id; @@ -1476,8 +1486,9 @@ namespace llarp // } // catch (const std::exception& e) // { - // log::warning(logcat, "Exception: {}; payload: {}", e.what(), buffer_printer{response.body()}); - // return prev_message.respond(messages::ERROR_RESPONSE, true); + // log::warning(logcat, "Exception: {}; payload: {}", e.what(), + // buffer_printer{response.body()}); return prev_message.respond(messages::ERROR_RESPONSE, + // true); // } // auto resp_payload = ONION::serialize_hop(hop_id.to_view(), nonce, std::move(payload)); @@ -1515,7 +1526,11 @@ namespace llarp } nonce = crypto::onion( - reinterpret_cast(payload.data()), payload.size(), hop->shared, nonce, hop->nonceXOR); + reinterpret_cast(payload.data()), + payload.size(), + hop->kx.shared_secret, + nonce, + hop->kx.xor_nonce); // if terminal hop, pass to the correct path expecting to receive this message if (hop->terminal_hop) @@ -1564,7 +1579,7 @@ namespace llarp { std::tie(endpoint, body) = PATH::CONTROL::deserialize(oxenc::bt_dict_consumer{payload}); - if (endpoint == "path_control") + if (_is_service_node and endpoint == "path_control") { log::info(logcat, "Received path control relay request; deserializing intermediate payload..."); auto [_, i_body] = PATH::CONTROL::deserialize(oxenc::bt_dict_consumer{std::move(body)}); @@ -1588,20 +1603,23 @@ namespace llarp void LinkManager::_handle_initiate_session(oxen::quic::message m, std::optional inner_body) { + log::debug(logcat, "{} called", __PRETTY_FUNCTION__); + NetworkAddress initiator; SessionTag tag; HopID pivot_txid; bool use_tun; + shared_kx_data kx_data; std::optional maybe_auth = std::nullopt; std::shared_ptr path_ptr; try { if (inner_body) - std::tie(initiator, pivot_txid, tag, use_tun, maybe_auth) = + std::tie(kx_data, initiator, pivot_txid, tag, use_tun, maybe_auth) = InitiateSession::decrypt_deserialize(oxenc::bt_dict_consumer{*inner_body}, _router.identity()); else - std::tie(initiator, pivot_txid, tag, use_tun, maybe_auth) = + std::tie(kx_data, initiator, pivot_txid, tag, use_tun, maybe_auth) = InitiateSession::decrypt_deserialize(oxenc::bt_dict_consumer{m.body()}, _router.identity()); if (maybe_auth and not _router.session_endpoint()->validate(initiator, maybe_auth)) @@ -1614,13 +1632,14 @@ namespace llarp if (not path_ptr) { - log::warning(logcat, "Failed to find local path corresponding to session over pivot: {}", pivot_txid); + log::warning(logcat, "Failed to find local path for new inbound session over pivot: {}", pivot_txid); return m.respond(InitiateSession::BAD_PATH, true); } if (_router.session_endpoint()->prefigure_session( - std::move(initiator), std::move(tag), std::move(path_ptr), use_tun)) + std::move(initiator), std::move(tag), std::move(path_ptr), std::move(kx_data), use_tun)) { + log::critical(logcat, "InboundSession configured successfully!"); return m.respond(messages::OK_RESPONSE); } @@ -1634,8 +1653,10 @@ namespace llarp m.respond(messages::ERROR_RESPONSE, true); } + // TESTNET: pretty sure this isn't called ever -> do not register it void LinkManager::handle_initiate_session(oxen::quic::message m) { + log::critical(logcat, "{} called, LOOK AT WHY", __PRETTY_FUNCTION__); return _handle_initiate_session(std::move(m)); } diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index c994f3854e..157c55edac 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -295,6 +295,8 @@ namespace llarp // Path relaying void handle_path_control(oxen::quic::message); + void relay_path_request(oxen::quic::message m, std::string payload); + void handle_path_request(oxen::quic::message m, std::string payload); // Path responses diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index d27728f7b7..ee831c7725 100644 --- a/llarp/messages/path.hpp +++ b/llarp/messages/path.hpp @@ -3,6 +3,7 @@ #include "common.hpp" #include +#include #include namespace llarp @@ -11,6 +12,8 @@ namespace llarp namespace ONION { + static auto logcat = llarp::log::Cat("onion"); + inline static std::string serialize_frames(std::vector&& frames) { return oxenc::bt_serialize(std::move(frames)); @@ -39,6 +42,44 @@ namespace llarp return std::move(btdp).str(); } + inline static std::tuple deserialize_decrypt( + oxenc::bt_dict_consumer&& btdc, const Ed25519SecretKey& local_sk) + { + std::string payload; + shared_kx_data kx_data{}; + + try + { + kx_data.pubkey.from_string(btdc.require("k")); + kx_data.nonce.from_string(btdc.require("n")); + payload = btdc.require("x"); + } + catch (const std::exception& e) + { + log::warning(logcat, "Exception caught deserializing onion data: {}", e.what()); + throw std::runtime_error{messages::ERROR_RESPONSE}; + } + + log::info(logcat, "payload: {}", buffer_printer{payload}); + + try + { + kx_data.server_dh(local_sk); + kx_data.decrypt(to_uspan(payload)); + + log::info(logcat, "xchacha -> payload: {}", buffer_printer{payload}); + + kx_data.generate_xor(); + } + catch (const std::exception& e) + { + log::warning(logcat, "Failed to derive and decrypt outer wrapping!"); + throw std::runtime_error{messages::ERROR_RESPONSE}; + } + + return {std::move(payload), std::move(kx_data)}; + } + inline static std::tuple deserialize(oxenc::bt_dict_consumer&& btdc) { RouterID rid; @@ -121,45 +162,36 @@ namespace llarp { std::string hop_payload = hop.bt_encode(); - Ed25519SecretKey ephemeral_key; - crypto::identity_keygen(ephemeral_key); - - hop.nonce = SymmNonce::make_random(); - - crypto::derive_encrypt_outer_wrapping( - ephemeral_key, hop.shared, hop.nonce, hop.router_id(), to_uspan(hop_payload)); - + // client dh key derivation + hop.kx.client_dh(hop.router_id()); + // encrypt payload + hop.kx.encrypt(to_uspan(hop_payload)); // generate nonceXOR value - ShortHash xor_hash; - crypto::shorthash(xor_hash, hop.shared.data(), hop.shared.size()); - - hop.nonceXOR = xor_hash.data(); // nonceXOR is 24 bytes, ShortHash is 32; this will truncate + hop.kx.generate_xor(); log::trace( logcat, "Hop serialized; nonce: {}, remote router_id: {}, shared pk: {}, shared secret: {}, payload: {}", - hop.nonce.to_string(), + hop.kx.nonce.to_string(), hop.router_id().to_string(), - ephemeral_key.to_pubkey().to_string(), - hop.shared.to_string(), + hop.kx.pubkey.to_string(), + hop.kx.shared_secret.to_string(), buffer_printer{hop_payload}); - return ONION::serialize_hop(ephemeral_key.to_pubkey().to_view(), hop.nonce, hop_payload); + return ONION::serialize_hop(hop.kx.pubkey.to_view(), hop.kx.nonce, hop_payload); } - inline static std::tuple deserialize_hop( - oxenc::bt_dict_consumer&& btdc, const Ed25519SecretKey& local_sk) + inline static std::shared_ptr deserialize_hop( + oxenc::bt_dict_consumer&& btdc, Router& r, const RouterID& src) { - SymmNonce nonce; - PubKey remote_pk; - ustring hop_payload; - SharedSecret shared; + std::string payload; + auto hop = std::make_shared(); try { - remote_pk.from_string(btdc.require("k")); - nonce.from_string(btdc.require("n")); - hop_payload = btdc.require("x"); + hop->kx.pubkey.from_string(btdc.require("k")); + hop->kx.nonce.from_string(btdc.require("n")); + payload = btdc.require("x"); } catch (const std::exception& e) { @@ -170,13 +202,24 @@ namespace llarp log::trace( logcat, "Hop deserialized; nonce: {}, remote pk: {}, payload: {}", - nonce.to_string(), - remote_pk.to_string(), - buffer_printer{hop_payload}); + hop->kx.nonce.to_string(), + hop->kx.pubkey.to_string(), + buffer_printer{payload}); try { - crypto::derive_decrypt_outer_wrapping(local_sk, shared, remote_pk, nonce, to_uspan(hop_payload)); + hop->kx.server_dh(r.identity()); + hop->kx.decrypt(to_uspan(payload)); + hop->kx.generate_xor(); + + log::trace( + logcat, + "Hop decrypted; nonce: {}, remote pk: {}, payload: {}", + hop->kx.nonce.to_string(), + hop->kx.pubkey.to_string(), + buffer_printer{payload}); + + hop->deserialize(oxenc::bt_dict_consumer{std::move(payload)}, src, r); } catch (...) { @@ -184,14 +227,8 @@ namespace llarp throw std::runtime_error{BAD_CRYPTO}; } - log::trace( - logcat, - "Hop decrypted; nonce: {}, remote pk: {}, payload: {}", - nonce.to_string(), - remote_pk.to_string(), - buffer_printer{hop_payload}); - - return {std::move(nonce), std::move(shared), std::move(hop_payload)}; + log::critical(logcat, "TransitHop data successfully deserialized: {}", hop->to_string()); + return hop; } } // namespace BUILD diff --git a/llarp/messages/session.hpp b/llarp/messages/session.hpp index 0d0e1a47d7..9e72c681f2 100644 --- a/llarp/messages/session.hpp +++ b/llarp/messages/session.hpp @@ -26,7 +26,7 @@ namespace llarp inline const auto AUTH_ERROR = messages::serialize_response({{messages::STATUS_KEY, "AUTH ERROR"}}); inline const auto BAD_PATH = messages::serialize_response({{messages::STATUS_KEY, "BAD PATH"}}); - inline static std::string serialize_encrypt( + inline static std::tuple serialize_encrypt( const RouterID& local, const RouterID& remote, SessionTag& tag, @@ -45,22 +45,22 @@ namespace llarp btdp.append("p", pivot_txid.to_view()); btdp.append("s", tag.to_view()); btdp.append("t", use_tun); - // DISCUSS: this auth field + // TOTHINK: this auth field if (auth_token) btdp.append("u", *auth_token); payload = std::move(btdp).str(); } - Ed25519SecretKey ephemeral_key; - crypto::identity_keygen(ephemeral_key); + auto kx_data = shared_kx_data::generate(); - SharedSecret shared; - auto nonce = SymmNonce::make_random(); + kx_data.client_dh(remote); + kx_data.encrypt(to_uspan(payload)); + kx_data.generate_xor(); - crypto::derive_encrypt_outer_wrapping(ephemeral_key, shared, nonce, remote, to_uspan(payload)); + auto new_payload = ONION::serialize_hop(kx_data.pubkey.to_view(), kx_data.nonce, std::move(payload)); - return ONION::serialize_hop(ephemeral_key.to_pubkey().to_view(), nonce, std::move(payload)); + return {PATH::CONTROL::serialize("session_init", std::move(new_payload)), std::move(kx_data)}; } catch (const std::exception& e) { @@ -69,48 +69,50 @@ namespace llarp } }; - inline static std::tuple> - decrypt_deserialize(oxenc::bt_dict_consumer&& btdc, const Ed25519SecretKey& local) + inline static std::tuple> + decrypt_deserialize(oxenc::bt_dict_consumer&& outer_btdc, const Ed25519SecretKey& local) { SymmNonce nonce; PubKey shared_pubkey; std::string payload; SharedSecret shared; + shared_kx_data kx_data{}; try { - std::tie(shared_pubkey, nonce, payload) = ONION::deserialize(std::move(btdc)); + std::tie(payload, kx_data) = ONION::deserialize_decrypt(std::move(outer_btdc), local); } catch (const std::exception& e) { - log::warning(logcat, "Exception caught deserializing hop dict: {}", e.what()); + log::warning(logcat, "Exception caught deserializing/decrypting hop dict: {}", e.what()); throw; } try { - crypto::derive_decrypt_outer_wrapping(local, shared, shared_pubkey, nonce, to_uspan(payload)); - - { - NetworkAddress initiator; - SessionTag tag; - HopID pivot_txid; - bool use_tun; - std::optional maybe_auth = std::nullopt; - - if (auto maybe_remote = NetworkAddress::from_network_addr(btdc.require("i"))) - initiator = *maybe_remote; - else - throw std::runtime_error{"Invalid NetworkAddress!"}; - - pivot_txid.from_string(btdc.require("p")); - tag.from_string(btdc.require("s")); - use_tun = btdc.require("t"); - maybe_auth = btdc.maybe("u"); - - return { - std::move(initiator), std::move(pivot_txid), std::move(tag), use_tun, std::move(maybe_auth)}; - } + oxenc::bt_dict_consumer btdc{payload}; + + NetworkAddress initiator; + RouterID init_rid; + SessionTag tag; + HopID pivot_txid; + bool use_tun; + std::optional maybe_auth = std::nullopt; + + init_rid.from_string(btdc.require("i")); + initiator = NetworkAddress::from_pubkey(init_rid, true); + pivot_txid.from_string(btdc.require("p")); + tag.from_string(btdc.require("s")); + use_tun = btdc.require("t"); + maybe_auth = btdc.maybe("u"); + + return { + std::move(kx_data), + std::move(initiator), + std::move(pivot_txid), + std::move(tag), + use_tun, + std::move(maybe_auth)}; } catch (const std::exception& e) { diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 725b8d1e51..7faafe5a11 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -65,6 +65,9 @@ namespace llarp::path hops[i]._downstream = hops[i - 1]._rid; } + // generate dh kx components + hops[i].kx = shared_kx_data::generate(); + // Conditions written as ternaries // hops[i]._rxid = i ? hops[i - 1]._txid : HopID::make_random(); // hops[i]._upstream = i == num_hops - 1 ? hops[i]._rid : hop_rcs[i + 1].router_id(); @@ -81,7 +84,7 @@ namespace llarp::path // _local_hop->_txid = hops.front()._rxid; // _local_hop->terminal_hop = true; - log::info(logcat, "Path populated with hops: {}", hop_string()); + log::trace(logcat, "Path populated with hops: {}", hop_string()); // initialize parts of the clientintro intro.pivot_rid = hops.back().router_id(); @@ -94,6 +97,7 @@ namespace llarp::path void Path::link_session(recv_session_dgram_cb cb) { _recv_dgram = std::move(cb); + _is_linked = true; _is_session_path = true; } @@ -192,9 +196,9 @@ namespace llarp::path nonce = crypto::onion( reinterpret_cast(inner_payload.data()), inner_payload.size(), - hop.shared, + hop.kx.shared_secret, nonce, - hop.nonceXOR); + hop.kx.xor_nonce); } return ONION::serialize_hop(upstream_rxid().to_view(), nonce, std::move(inner_payload)); @@ -230,6 +234,11 @@ namespace llarp::path return nullptr; } + TransitHop Path::edge() const + { + return {hops.front()}; + } + RouterID Path::upstream_rid() { return hops.front().router_id(); diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index b11570c49e..7c8d03a71f 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -25,6 +25,11 @@ namespace llarp struct Router; struct Profiling; + // namespace link + // { + // struct LinkManager; + // } + namespace service { struct EncryptedIntroSet; @@ -44,6 +49,7 @@ namespace llarp friend struct PathHandler; friend class handlers::SessionEndpoint; friend struct llarp::Profiling; + friend struct LinkManager; Path( Router& rtr, @@ -52,7 +58,6 @@ namespace llarp bool is_session = false, bool is_client = false); - protected: // hops on constructed path std::vector hops; // local hop info for onioned responses and session messages @@ -60,7 +65,6 @@ namespace llarp std::weak_ptr handler; ClientIntro intro{}; - public: std::shared_ptr get_self() { return shared_from_this(); } std::weak_ptr get_weak() { return weak_from_this(); } @@ -126,6 +130,8 @@ namespace llarp std::shared_ptr get_parent(); + TransitHop edge() const; + RouterID upstream_rid(); const RouterID& upstream_rid() const; diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index 85c1d596c5..1982f92065 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -75,7 +75,13 @@ namespace llarp::path bool PathContext::has_transit_hop(const std::shared_ptr& hop) const { assert(_r.loop()->in_event_loop()); - return _transit_hops.count(hop->rxid()) or _transit_hops.count(hop->txid()); + return has_transit_hop(hop->rxid()) or has_transit_hop(hop->txid()); + } + + bool PathContext::has_transit_hop(const HopID& hop_id) const + { + assert(_r.loop()->in_event_loop()); + return _transit_hops.count(hop_id); } void PathContext::put_transit_hop(std::shared_ptr hop) @@ -118,6 +124,12 @@ namespace llarp::path return _get_path(hop_id); } + bool PathContext::has_path(const HopID& hop_id) const + { + assert(_r.loop()->in_event_loop()); + return _path_map.contains(hop_id); + } + std::shared_ptr PathContext::get_path(const std::shared_ptr& hop) const { assert(_r.loop()->in_event_loop()); diff --git a/llarp/path/path_context.hpp b/llarp/path/path_context.hpp index 6255749853..48a3311303 100644 --- a/llarp/path/path_context.hpp +++ b/llarp/path/path_context.hpp @@ -46,8 +46,12 @@ namespace llarp::path bool has_transit_hop(const std::shared_ptr& hop) const; + bool has_transit_hop(const HopID& hop_id) const; + void put_transit_hop(std::shared_ptr hop); + bool has_path(const HopID& hop_id) const; + std::shared_ptr get_path(const std::shared_ptr& hop) const; std::shared_ptr get_path(const HopID& hop_id) const; diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index 5eaec3ac41..2294ac4933 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -506,12 +506,12 @@ namespace llarp::path std::set to_exclude{exclude.begin(), exclude.end()}; to_exclude.insert(pivot); std::vector excluded_ranges{}; - excluded_ranges.emplace_back(pivot_rc.addr().to_ipv4() / netmask); + // excluded_ranges.emplace_back(pivot_rc.addr().to_ipv4() / netmask); if (auto maybe = select_first_hop(to_exclude)) { - hops.push_back(*maybe); - excluded_ranges.emplace_back(maybe->addr().to_ipv4() / netmask); + hops.emplace_back(std::move(*maybe)); + // excluded_ranges.emplace_back(hops.back().addr().to_ipv4() / netmask); --hops_needed; } else @@ -532,23 +532,23 @@ namespace llarp::path return false; } - excluded_ranges.emplace_back(v4 / netmask); - // if its already excluded, fail; (we want it added even on success) if (not to_exclude.insert(rid).second) return false; + excluded_ranges.emplace_back(v4 / netmask); + if (_router.router_profiling().is_bad_for_path(rid, 1)) return false; return true; }; - log::debug(logcat, "First/last hop selected, {} hops remaining to select", hops_needed); + log::trace(logcat, "First/last hop selected, {} hops remaining to select", hops_needed); if (auto maybe_hops = _router.node_db()->get_n_random_rcs_conditional(hops_needed, filter)) { - log::info(logcat, "Found {} RCs for aligned path (needed: {})", maybe_hops->size(), hops_needed); + log::trace(logcat, "Found {} RCs for aligned path (needed: {})", maybe_hops->size(), hops_needed); hops.insert(hops.end(), maybe_hops->begin(), maybe_hops->end()); hops.emplace_back(std::move(pivot_rc)); return hops; @@ -686,12 +686,12 @@ namespace llarp::path for (auto j = i + 1; j < n_hops; ++j) { - auto _onion_nonce = path_hops[i].nonce ^ path_hops[i].nonceXOR; + auto _onion_nonce = path_hops[i].kx.nonce ^ path_hops[i].kx.xor_nonce; crypto::onion( reinterpret_cast(frames[j].data()), frames[j].size(), - path_hops[i].shared, + path_hops[i].kx.shared_secret, _onion_nonce, _onion_nonce); } diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index 8515c20142..25145beb20 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -9,14 +9,11 @@ namespace llarp::path { static auto logcat = log::Cat("transit-hop"); - std::shared_ptr TransitHop::deserialize_hop( - oxenc::bt_dict_consumer&& btdc, const RouterID& src, Router& r, SharedSecret secret) + void TransitHop::deserialize(oxenc::bt_dict_consumer&& btdc, const RouterID& src, const Router& r) { - auto hop = std::make_shared(); - try { - hop->bt_decode(std::move(btdc)); + bt_decode(std::move(btdc)); } catch (const std::exception& e) { @@ -24,26 +21,21 @@ namespace llarp::path throw std::runtime_error{messages::ERROR_RESPONSE}; } - if (hop->rxid().is_zero() || hop->txid().is_zero()) + if (_rxid.is_zero() || _txid.is_zero()) throw std::runtime_error{PATH::BUILD::BAD_PATHID}; - hop->_downstream = src; - hop->shared = std::move(secret); + if (r.path_context()->has_transit_hop(_rxid) || r.path_context()->has_transit_hop(_txid)) + throw std::runtime_error{PATH::BUILD::BAD_PATHID}; - if (hop->_upstream == r.local_rid()) - hop->terminal_hop = true; + _downstream = src; - if (r.path_context()->has_transit_hop(hop)) - throw std::runtime_error{PATH::BUILD::BAD_PATHID}; + if (_upstream == r.local_rid()) + terminal_hop = true; // generate hash of hop key for nonce mutation - ShortHash xor_hash; - crypto::shorthash(xor_hash, hop->shared.data(), hop->shared.size()); - hop->nonceXOR = xor_hash.data(); // nonceXOR is 24 bytes, ShortHash is 32; this will truncate - - log::critical(logcat, "TransitHop data successfully deserialized: {}", hop->to_string()); + kx.generate_xor(); - return hop; + log::critical(logcat, "TransitHop data successfully deserialized: {}", to_string()); } void TransitHop::bt_decode(oxenc::bt_dict_consumer&& btdc) diff --git a/llarp/path/transit_hop.hpp b/llarp/path/transit_hop.hpp index 66c4d00366..54a13cacfe 100644 --- a/llarp/path/transit_hop.hpp +++ b/llarp/path/transit_hop.hpp @@ -22,15 +22,9 @@ namespace llarp TransitHop() = default; - // This static factory function is used in path-build logic. The exceptions thrown are the exact response - // bodies passed to message::respond(...) function - static std::shared_ptr deserialize_hop( - oxenc::bt_dict_consumer&& btdc, const RouterID& src, Router& r, SharedSecret secret); + void deserialize(oxenc::bt_dict_consumer&& btdc, const RouterID& src, const Router& r); - SharedSecret shared; - - SymmNonce nonce; - SymmNonce nonceXOR; + shared_kx_data kx{}; std::chrono::milliseconds expiry{0s}; diff --git a/llarp/session/session.cpp b/llarp/session/session.cpp index e975714796..57a1383e03 100644 --- a/llarp/session/session.cpp +++ b/llarp/session/session.cpp @@ -20,16 +20,19 @@ namespace llarp::session NetworkAddress remote, SessionTag _t, bool use_tun, - bool is_exit, - bool is_outbound) + bool is_outbound, + std::optional kx_data) : _r{r}, _parent{parent}, _tag{std::move(_t)}, _remote{std::move(remote)}, _use_tun{use_tun}, _is_outbound{is_outbound}, - _is_exit_session{is_exit} + _is_exit_session{kx_data.has_value()} { + if (kx_data.has_value()) + session_keys = std::move(*kx_data); + set_new_current_path(std::move(_p)); } @@ -146,7 +149,7 @@ namespace llarp::session _r.quic_tunnel()->creds(), [addr = *bind, hook = std::move(cb)](oxen::quic::connection_interface&) { hook(addr.to_ipv4()); }, [](oxen::quic::connection_interface&, uint64_t) { - // + // TESTNET: TODO: }); } @@ -155,7 +158,7 @@ namespace llarp::session handlers::SessionEndpoint& parent, std::shared_ptr path, SessionTag _t, - bool is_exit) + std::optional kx_data) : PathHandler{parent._router, path::DEFAULT_PATHS_HELD}, BaseSession{ _router, @@ -164,21 +167,16 @@ namespace llarp::session std::move(remote), std::move(_t), _router.using_tun_if(), - is_exit, - true}, - _last_use{_router.now()}, - _is_snode_session{not _remote.is_client()} + true, + std::move(kx_data)}, + _is_snode_session{not _remote.is_client()}, + _last_use{_router.now()} { // These can both be false but CANNOT both be true if (_is_exit_session and _is_snode_session) throw std::runtime_error{"Cannot create OutboundSession for a remote exit and remote service!"}; add_path(_current_path); - - if (_is_snode_session) - _session_key = _router.identity(); - else - crypto::identity_keygen(_session_key); } OutboundSession::~OutboundSession() = default; @@ -258,8 +256,11 @@ namespace llarp::session for (auto& [_, p] : _paths) { - log::debug(logcat, "Sending close message on path {}", p->to_string()); - send_path_close(p); + if (p and p->is_ready()) + { + log::debug(logcat, "Sending close message on path {}", p->to_string()); + // send_path_close(p); + } } }); @@ -275,11 +276,7 @@ namespace llarp::session { size_t count{0}; log::debug( - logcat, - "OutboundSession building {} paths (needed: {}) to remote:{}", - n, - path::DEFAULT_PATHS_HELD, - _remote); + logcat, "OutboundSession building {} paths (needed:{}) to remote:{}", n, path::DEFAULT_PATHS_HELD, _remote); for (size_t i = 0; i < n; ++i) count += build_path_aligned_to_remote(_remote.router_id()); @@ -301,10 +298,11 @@ namespace llarp::session void OutboundSession::send_path_close(std::shared_ptr p) { - if (p->close_exit(_session_key, p->upstream_txid().to_string())) - log::info(logcat, "Sent path close on path {}", p->to_string()); - else - log::warning(logcat, "Failed to send path close on path {}", p->to_string()); + (void)p; + // if (p->close_exit(_session_key, p->upstream_txid().to_string())) + // log::info(logcat, "Sent path close on path {}", p->to_string()); + // else + // log::warning(logcat, "Failed to send path close on path {}", p->to_string()); } bool OutboundSession::is_ready() const @@ -327,7 +325,8 @@ namespace llarp::session std::shared_ptr _path, handlers::SessionEndpoint& parent, SessionTag _t, - bool use_tun) + bool use_tun, + std::optional kx_data) : BaseSession{ parent._router, std::move(_path), @@ -335,13 +334,9 @@ namespace llarp::session std::move(remote), std::move(_t), use_tun, - parent.is_exit_node(), - false} - { - if (not _current_path->is_client_path() and _remote.is_client()) - throw std::runtime_error{ - "NetworkAddress and Path do not agree on InboundSession remote's identity (client vs server)!"}; - } + false, + std::move(kx_data)} + {} void InboundSession::set_new_tag(const SessionTag& tag) { diff --git a/llarp/session/session.hpp b/llarp/session/session.hpp index e8eedcdddc..24263a63bb 100644 --- a/llarp/session/session.hpp +++ b/llarp/session/session.hpp @@ -19,7 +19,7 @@ namespace llarp namespace link { class TunnelManager; - } + } // namespace link namespace handlers { @@ -31,7 +31,6 @@ namespace llarp - client to snode: - the traffic to the pivot is encrypted - the pivot is the terminus, so data doesn't need to be encrypted - - could set HopID to 0 to indicate */ namespace session @@ -48,6 +47,8 @@ namespace llarp SessionTag _tag; NetworkAddress _remote; + shared_kx_data session_keys{}; + bool _use_tun; bool _is_outbound; @@ -78,8 +79,8 @@ namespace llarp NetworkAddress remote, SessionTag _t, bool use_tun, - bool is_exit, - bool is_outbound); + bool is_outbound, + std::optional kx_data = std::nullopt); virtual ~BaseSession() = default; @@ -121,16 +122,13 @@ namespace llarp handlers::SessionEndpoint& parent, std::shared_ptr path, SessionTag _t, - bool is_exit); + std::optional kx_data = std::nullopt); ~OutboundSession() override; private: - Ed25519SecretKey _session_key; // DISCUSS: is this useful? - - std::chrono::milliseconds _last_use; - const bool _is_snode_session{false}; + std::chrono::milliseconds _last_use; public: std::shared_ptr get_self() override { return shared_from_this(); } @@ -181,7 +179,8 @@ namespace llarp std::shared_ptr _path, handlers::SessionEndpoint& parent, SessionTag _t, - bool use_tun); + bool use_tun, + std::optional kx_data = std::nullopt); ~InboundSession() = default; From e09df7dd2b998d03011095a1b9d547840f8202d5 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 5 Dec 2024 09:13:31 -0800 Subject: [PATCH 31/44] libquic bump dr7ana/0rtt --- external/oxen-libquic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/oxen-libquic b/external/oxen-libquic index b01fd9e349..929c15a633 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit b01fd9e349515034d2412eb3bc1e5784287caf95 +Subproject commit 929c15a6331773f769c566b2e7a16be01055eae8 From a3ae8970d2206e37fa8aa6d84410841a4db060fe Mon Sep 17 00:00:00 2001 From: Jason Rhinelander Date: Thu, 5 Dec 2024 13:30:31 -0400 Subject: [PATCH 32/44] Fix dangling view in addr/port parsing With this in the config: [bind] listen=144.76.164.202:1666 I was getting a failure during config parsing: Dec 04 16:00:21 fenrir lokinet[2480391]: [2024-12-04 20:00:21] [+0.000s] [config:critical|/home/testnet/lokinet/llarp/config/config.cpp:1232] Parsing input: 144.76.164.202:1666 Dec 04 16:00:21 fenrir lokinet[2480391]: [2024-12-04 20:00:21] [+0.000s] [config:critical|/home/testnet/lokinet/llarp/config/config.cpp:1234] Parsed input = Dec 04 16:00:21 fenrir lokinet[2480391]: [1B blob data] Dec 04 16:00:21 fenrir lokinet[2480391]: :1666 which turned out to be that we had a string view viewing a temporary std::string. This fixes it. Also removes a counterproductive `static` from inlined header methods around addr parsing. (Having a `static` free function forces a distinct copy of the function to exist for every compilation unit that uses the function *without* linkage of those functions, while plain `inline` still compiles separate copies where used, but allows the linker to deduplicate them when linking the final binary). --- llarp/address/utils.hpp | 14 +++++++------- llarp/config/config.cpp | 5 +++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/llarp/address/utils.hpp b/llarp/address/utils.hpp index 14c6fde7b4..227dd58ccc 100644 --- a/llarp/address/utils.hpp +++ b/llarp/address/utils.hpp @@ -40,7 +40,7 @@ namespace llarp namespace detail { // inline auto utilcat = log::Cat("addrutils"); - inline static std::optional parse_addr_string(std::string_view arg, std::string_view tld) + inline std::optional parse_addr_string(std::string_view arg, std::string_view tld) { std::optional ret = std::nullopt; @@ -61,22 +61,22 @@ namespace llarp return ret; }; - inline static std::pair parse_addr( - std::string_view addr, std::optional default_port) + inline std::pair parse_addr(std::string_view addr, std::optional default_port) { std::pair result; + auto &[host, port] = result; if (auto p = addr.find_last_not_of("0123456789"); p != std::string_view::npos && p + 2 <= addr.size() && addr[p] == ':') { - if (!parse_int(addr.substr(p + 1), result.second)) + if (!parse_int(addr.substr(p + 1), port)) throw std::invalid_argument{"Invalid address: could not parse port"}; addr.remove_suffix(addr.size() - p); } else if (default_port) { // log::critical(utilcat, "Setting default port for addr parse!"); - result.second = *default_port; + port = *default_port; } else { @@ -96,7 +96,7 @@ namespace llarp { if (auto q = addr.find_first_not_of("0123456789abcdef:."); q != std::string_view::npos) throw std::invalid_argument{"Invalid address: does not look like IPv4 or IPv6!"}; - else if (!had_sq_brackets) + if (!had_sq_brackets) throw std::invalid_argument{"Invalid address: IPv6 addresses require [...] square brackets"}; } @@ -106,7 +106,7 @@ namespace llarp // // addr = "::"; // } - result.first = addr; + host = addr; return result; } diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index 6345bef5c7..a27dea7f26 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -1223,7 +1223,8 @@ namespace llarp auto parse_addr_for_link = [net_ptr](const std::string& arg, bool& given_port_only) { std::optional maybe = std::nullopt; - std::string_view arg_v{arg}, host; + std::string_view arg_v{arg}; + std::string host; uint16_t p{}; if (auto pos = arg_v.find(':'); pos != arg_v.npos) @@ -1242,7 +1243,7 @@ namespace llarp maybe = net_ptr->get_best_public_address(true, p); } else - maybe = oxen::quic::Address{std::string{host}, p}; + maybe = oxen::quic::Address{host, p}; if (maybe and maybe->is_loopback()) throw std::invalid_argument{"{} is a loopback address"_format(arg)}; From 3e1089ad6ea2dc48f7f61361b8284084ad6c61f7 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 5 Dec 2024 10:38:07 -0800 Subject: [PATCH 33/44] 0rtt bump for stateless reset lifetimes, nodedb prune against whitelist --- external/CMakeLists.txt | 4 +--- external/oxen-libquic | 2 +- llarp/crypto/crypto.cpp | 3 ++- llarp/nodedb.cpp | 39 +++++++++------------------------------ llarp/nodedb.hpp | 22 +++------------------- llarp/router/router.cpp | 11 ++++------- llarp/router/router.hpp | 5 +---- llarp/rpc/rpc_client.cpp | 18 ++++++------------ 8 files changed, 27 insertions(+), 77 deletions(-) diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 59d18a9fe0..33ce97f481 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -73,7 +73,7 @@ add_library(libevent::threads ALIAS event_pthreads) add_library(libevent::extra ALIAS event_extra) -system_or_submodule(OXENC oxenc liboxenc>=1.0.10 oxen-encoding) +system_or_submodule(OXENC oxenc liboxenc>=1.1.0 oxen-encoding) system_or_submodule(OXENMQ oxenmq liboxenmq>=1.2.14 oxen-mq) @@ -103,8 +103,6 @@ endif() # we get oxen-logging from libquic; forcing submodule ensures fmt>10.0.0 -#set(OXEN_LOGGING_FMT_HEADER_ONLY ON CACHE INTERNAL "") -#set(OXEN_LOGGING_SPDLOG_HEADER_ONLY ON CACHE INTERNAL "") set(OXEN_LOGGING_FORCE_SUBMODULES ON CACHE INTERNAL "") add_subdirectory(oxen-libquic) diff --git a/external/oxen-libquic b/external/oxen-libquic index 929c15a633..59796bdfe3 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit 929c15a6331773f769c566b2e7a16be01055eae8 +Subproject commit 59796bdfe3c428643d69159b00e5f8140624b246 diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index 43691c4c07..e0c22ca200 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -358,9 +358,10 @@ namespace llarp { Ed25519SecretKey ret{}; PubKey pk; - int result = crypto_sign_ed25519_keypair(pk.data(), ret.data()); + [[maybe_unused]] int result = crypto_sign_ed25519_keypair(pk.data(), ret.data()); assert(result != -1); const PubKey sk_pk = ret.to_pubkey(); + (void)sk_pk; assert(pk == sk_pk); return ret; } diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index 1795057c68..4aa4cbb98b 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -753,46 +753,24 @@ namespace llarp }); } - void NodeDB::set_router_whitelist( - const std::vector& whitelist, - const std::vector& greylist, - const std::vector& greenlist) + void NodeDB::set_router_whitelist(const std::vector& whitelist) { - log::critical( - logcat, - "Oxend provided {}/{}/{} (white/gray/green) routers", - whitelist.size(), - greylist.size(), - greenlist.size()); + log::critical(logcat, "Oxend provided {} whitelisted routers", whitelist.size()); if (whitelist.empty()) return; _registered_routers.clear(); _registered_routers.insert(whitelist.begin(), whitelist.end()); - _registered_routers.insert(greylist.begin(), greylist.end()); - _registered_routers.insert(greenlist.begin(), greenlist.end()); - - _router_whitelist.clear(); - _router_whitelist.insert(whitelist.begin(), whitelist.end()); - _router_greylist.clear(); - _router_greylist.insert(greylist.begin(), greylist.end()); - _router_greenlist.clear(); - _router_greenlist.insert(greenlist.begin(), greenlist.end()); log::critical( - logcat, - "Service node holding {}:{} (whitelist:registered) after oxend integration", - _router_whitelist.size(), - _registered_routers.size()); + logcat, "Service node holding {} registered relays after oxend integration", _registered_routers.size()); } - std::optional NodeDB::get_random_whitelist_router() const + std::optional NodeDB::get_random_registered_router() const { - std::optional rand = std::nullopt; - - std::sample(_router_whitelist.begin(), _router_whitelist.end(), &*rand, 1, csrng); - return rand; + std::function hook = [](const auto&) -> bool { return true; }; + return meta::sample(_registered_routers, hook); } bool NodeDB::is_connection_allowed(const RouterID& remote) const @@ -801,10 +779,11 @@ namespace llarp { if (_pinned_edges.size() && _pinned_edges.count(remote) == 0 && not _bootstraps.contains(remote)) return false; + + return known_rids.count(remote); } - // TESTNET: make this check an updated registry - return known_rids.count(remote) or _registered_routers.count(remote); + return known_rids.count(remote) and _registered_routers.empty() ? true : _registered_routers.count(remote); } bool NodeDB::is_first_hop_allowed(const RouterID& remote) const diff --git a/llarp/nodedb.hpp b/llarp/nodedb.hpp index fe0657d0b7..d2849325df 100644 --- a/llarp/nodedb.hpp +++ b/llarp/nodedb.hpp @@ -128,16 +128,6 @@ namespace llarp BootstrapList _bootstraps{}; - /** RouterID lists // TODO: get rid of all these, replace with better decom/not staked - sets - - white: active routers - - gray: fully funded, but decommissioned routers - - green: registered, but not fully-staked routers - */ - std::set _router_whitelist{}; - std::set _router_greylist{}; - std::set _router_greenlist{}; - // All registered relays (service nodes) std::set _registered_routers; @@ -250,12 +240,9 @@ namespace llarp // variable ::known_rids bool reselect_router_id_sources(std::set specific); - void set_router_whitelist( - const std::vector& whitelist, - const std::vector& greylist, - const std::vector& greenlist); + void set_router_whitelist(const std::vector& whitelist); - std::optional get_random_whitelist_router() const; + std::optional get_random_registered_router() const; // client: // if pinned edges were specified, connections are allowed only to those and @@ -292,10 +279,6 @@ namespace llarp void set_bootstrap_routers(BootstrapList& from_router); - const std::set& whitelist() const { return _router_whitelist; } - - const std::set& greylist() const { return _router_greylist; } - std::set& registered_routers() { return _registered_routers; } const std::set& registered_routers() const { return _registered_routers; } @@ -401,6 +384,7 @@ namespace llarp if (visit(itr->second)) { removed.insert(itr->first); + known_rids.erase(itr->first); known_rcs.erase(itr->second); itr = rc_lookup.erase(itr); } diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 5a5e3c7a42..648f44721e 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -727,7 +727,7 @@ namespace llarp bool Router::appears_decommed() const { - return _is_service_node and has_whitelist() and node_db()->greylist().count(local_rid()); + return _is_service_node and has_whitelist() and not node_db()->registered_routers().count(local_rid()); } bool Router::appears_funded() const @@ -953,15 +953,12 @@ namespace llarp const std::set& Router::get_whitelist() const { - return _node_db->whitelist(); + return _node_db->registered_routers(); } - void Router::set_router_whitelist( - const std::vector& whitelist, - const std::vector& greylist, - const std::vector& unfundedlist) + void Router::set_router_whitelist(const std::vector& whitelist) { - node_db()->set_router_whitelist(whitelist, greylist, unfundedlist); + node_db()->set_router_whitelist(whitelist); whitelist_received = true; } diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 0cc5519ca9..24295afba7 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -260,10 +260,7 @@ namespace llarp const std::set& get_whitelist() const; - void set_router_whitelist( - const std::vector& whitelist, - const std::vector& greylist, - const std::vector& unfunded); + void set_router_whitelist(const std::vector& whitelist); template void queue_work(Callable&& func) diff --git a/llarp/rpc/rpc_client.cpp b/llarp/rpc/rpc_client.cpp index f51f3c08b9..66f03484a7 100644 --- a/llarp/rpc/rpc_client.cpp +++ b/llarp/rpc/rpc_client.cpp @@ -213,7 +213,7 @@ namespace llarp::rpc void RPCClient::handle_new_service_node_list(const nlohmann::json& j) { std::unordered_map keymap; - std::vector activeNodeList, decommNodeList, unfundedNodeList; + std::vector active_list; if (not j.is_array()) throw std::runtime_error{"Invalid service node list: expected array of service node states"}; @@ -229,10 +229,6 @@ namespace llarp::rpc 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; @@ -240,10 +236,11 @@ namespace llarp::rpc continue; keymap[rid] = pk; - (active ? activeNodeList : funded ? decommNodeList : unfundedNodeList).push_back(std::move(rid)); + if (active) + active_list.emplace_back(std::move(rid)); } - if (activeNodeList.empty()) + if (active_list.empty()) { log::warning(logcat, "Received empty service node list, ignoring."); return; @@ -254,14 +251,11 @@ namespace llarp::rpc { auto& loop = router->loop(); loop->call([this, - active = std::move(activeNodeList), - decomm = std::move(decommNodeList), - unfunded = std::move(unfundedNodeList), + active = std::move(active_list), keymap = std::move(keymap), router = std::move(router)]() mutable { _key_map = std::move(keymap); - - router->set_router_whitelist(active, decomm, unfunded); + router->set_router_whitelist(active); }); } else From 6d54176b5f271d21e8feb8a5b329509a05dea6d0 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Sat, 7 Dec 2024 11:25:49 -0800 Subject: [PATCH 34/44] datagramIO --- llarp/address/ip_packet.cpp | 63 +++++++++----------- llarp/address/ip_packet.hpp | 12 +--- llarp/dns/server.cpp | 2 +- llarp/dns/server.hpp | 2 +- llarp/handlers/session.cpp | 53 +++++++--------- llarp/handlers/tun.cpp | 2 + llarp/link/link_manager.cpp | 116 +++++++++++++++++++++++++----------- llarp/link/link_manager.hpp | 3 +- llarp/messages/path.hpp | 34 +++++++++-- llarp/session/session.cpp | 6 +- llarp/vpn/packet_router.cpp | 9 ++- 11 files changed, 183 insertions(+), 119 deletions(-) diff --git a/llarp/address/ip_packet.cpp b/llarp/address/ip_packet.cpp index 3d1ebbccb6..e28fa45937 100644 --- a/llarp/address/ip_packet.cpp +++ b/llarp/address/ip_packet.cpp @@ -3,6 +3,7 @@ #include "utils.hpp" #include +#include #include #include @@ -27,18 +28,14 @@ namespace llarp IPPacket::IPPacket(ustring_view data) : IPPacket{data.data(), data.size()} {} - IPPacket::IPPacket(std::vector data) : IPPacket{data.data(), data.size()} {} + IPPacket::IPPacket(std::vector&& data) : IPPacket{data.data(), data.size()} {} IPPacket::IPPacket(const uint8_t* buf, size_t len) { - if (len < MIN_PACKET_SIZE) - { - _buf.resize(0); - } - else + if (len >= MIN_PACKET_SIZE) { _buf.resize(len); - std::copy_n(buf, len, _buf.data()); + std::memcpy(_buf.data(), buf, len); } _init_internals(); @@ -65,7 +62,14 @@ namespace llarp _header = reinterpret_cast(data()); _v6_header = reinterpret_cast(data()); - _is_v4 = _header->protocol == uint8_t{4}; + if (_buf.empty()) + return; + + // log::trace(logcat, "ippkt header: {}", buffer_printer{_buf}); + // log::trace(logcat, "ippkt protocol: {}", _header->protocol); + // log::trace(logcat, "ippkt version: {}", _header->version); + + _is_v4 = _header->version == oxenc::host_to_big(uint8_t{4}); _is_udp = _header->protocol == uint8_t{17}; uint16_t src_port = @@ -76,20 +80,24 @@ namespace llarp if (_is_v4) { - auto src = in_addr{_header->src}; - auto dest = in_addr{_header->dest}; + auto srcv4 = ipv4{oxenc::big_to_host(_header->src)}; + auto dstv4 = ipv4{oxenc::big_to_host(_header->dest)}; + + log::trace(logcat, "srcv4={}:{}, dstv4={}:{}", srcv4, src_port, dstv4, dest_port); - _src_addr.set_addr(&src); - _dst_addr.set_addr(&dest); + _src_addr = oxen::quic::Address{srcv4, src_port}; + _dst_addr = oxen::quic::Address{dstv4, dest_port}; } else { - _src_addr.set_addr(&_v6_header->srcaddr); - _dst_addr.set_addr(&_v6_header->dstaddr); - } + auto srcv6 = ipv6{&_v6_header->srcaddr}; + auto dstv6 = ipv6{&_v6_header->dstaddr}; + + log::trace(logcat, "srcv6={}:{}, dstv6={}:{}", srcv6, src_port, dstv6, dest_port); - _src_addr.set_port(src_port); - _dst_addr.set_port(dest_port); + _src_addr = oxen::quic::Address{srcv6, src_port}; + _dst_addr = oxen::quic::Address{dstv6, dest_port}; + } } std::optional> IPPacket::l4_data() const @@ -283,7 +291,7 @@ namespace llarp itr += 2; // copy ip header and first 8 bytes of datagram for icmp rject - std::copy_n(data(), ip_hdr_sz + ICMP_HEADER_SIZE, itr); + std::memcpy(itr, _buf.data(), ip_hdr_sz + ICMP_HEADER_SIZE); itr += ip_hdr_sz + ICMP_HEADER_SIZE; // calculate checksum of ip header @@ -302,21 +310,6 @@ namespace llarp return NetworkPacket{oxen::quic::Path{_src_addr, _dst_addr}, bview()}; } - bool IPPacket::load(ustring_view data) - { - return load(data.data(), data.size()); - } - - bool IPPacket::load(std::string_view data) - { - return load(reinterpret_cast(data.data()), data.size()); - } - - bool IPPacket::load(std::vector data) - { - return load(data.data(), data.size()); - } - bool IPPacket::load(const uint8_t* buf, size_t len) { if (len < MIN_PACKET_SIZE) @@ -324,7 +317,7 @@ namespace llarp _buf.clear(); _buf.resize(len); - std::copy_n(buf, len, _buf.data()); + std::memcpy(_buf.data(), buf, len); _init_internals(); @@ -376,7 +369,7 @@ namespace llarp std::string IPPacket::info_line() const { - return "IPPacket (src:{}, dest:{}, size:{})"_format(_src_addr, _dst_addr, size()); + return "IPPacket:[src={} | dest={} | size={}]"_format(_src_addr, _dst_addr, size()); } } // namespace llarp diff --git a/llarp/address/ip_packet.hpp b/llarp/address/ip_packet.hpp index 3c49ef8819..b2f879bbbd 100644 --- a/llarp/address/ip_packet.hpp +++ b/llarp/address/ip_packet.hpp @@ -32,7 +32,7 @@ namespace llarp struct IPPacket { private: - std::vector _buf; + std::vector _buf{}; ip_header* _header{}; ipv6_header* _v6_header{}; @@ -40,7 +40,7 @@ namespace llarp oxen::quic::Address _src_addr{}; oxen::quic::Address _dst_addr{}; - bool _is_v4{false}; + bool _is_v4{true}; bool _is_udp{false}; void _init_internals(); @@ -50,7 +50,7 @@ namespace llarp explicit IPPacket(size_t sz); explicit IPPacket(bstring_view data); explicit IPPacket(ustring_view data); - explicit IPPacket(std::vector data); + explicit IPPacket(std::vector&& data); explicit IPPacket(const uint8_t* buf, size_t len); static IPPacket from_netpkt(NetworkPacket pkt); @@ -109,12 +109,6 @@ namespace llarp bool empty() const { return _buf.empty(); } - bool load(ustring_view data); - - bool load(std::string_view data); - - bool load(std::vector data); - bool load(const uint8_t* buf, size_t len); // takes posession of the data diff --git a/llarp/dns/server.cpp b/llarp/dns/server.cpp index 5d31e199c1..a917e82f0e 100644 --- a/llarp/dns/server.cpp +++ b/llarp/dns/server.cpp @@ -501,7 +501,7 @@ namespace llarp::dns if (parent_ptr) { parent_ptr->call( - [self = shared_from_this(), parent_ptr = std::move(parent_ptr), buf = std::move(data)] { + [self = shared_from_this(), parent_ptr = std::move(parent_ptr), buf = std::move(data)]() mutable { log::trace( logcat, "forwarding dns response from libunbound to userland (resolverAddr: {}, " diff --git a/llarp/dns/server.hpp b/llarp/dns/server.hpp index 830a433f86..89be074512 100644 --- a/llarp/dns/server.hpp +++ b/llarp/dns/server.hpp @@ -136,7 +136,7 @@ namespace llarp::dns : QueryJob_Base{query}, src{std::move(source)}, resolver{to_}, asker{from_} {} - void send_reply(std::vector buf) override { src->send_to(asker, resolver, IPPacket{buf}); } + void send_reply(std::vector buf) override { src->send_to(asker, resolver, IPPacket{std::move(buf)}); } }; /// handler of dns query hooking diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index a082899b70..b3454f81b0 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -140,7 +140,7 @@ namespace llarp::handlers update_and_publish_localcc(get_current_client_intros(), _srv_records); } - static std::atomic testnet_trigger = false; + // static std::atomic testnet_trigger = false; void SessionEndpoint::start_tickers() { @@ -155,24 +155,25 @@ namespace llarp::handlers }, true); - if (not testnet_trigger) - { - testnet_trigger = true; - - _router.loop()->call_later(15s, [this]() { - try - { - RouterID cpk{oxenc::from_base32z("4bfu94cyd5t1976qubcwc3nirarri34o4pxq865xrd4krcs8tzxo")}; - log::info(logcat, "Beginning session init to client: {}", cpk.to_network_address(false)); - _initiate_session( - NetworkAddress::from_pubkey(cpk, true), [](ip_v) { log::critical(logcat, "FUCK YEAH"); }); - } - catch (const std::exception& e) - { - log::critical(logcat, "Failed to parse client netaddr: {}", e.what()); - } - }); - } + // if (not testnet_trigger) + // { + // testnet_trigger = true; + + // _router.loop()->call_later(10s, [this]() { + // try + // { + // RouterID cpk{oxenc::from_base32z("bx13pza3snxgnccpbz1dpry6zsmspn718f9kyo9sipp3bdc848oy")}; + // log::info(logcat, "Beginning session init to client: {}", cpk.to_network_address(false)); + // _initiate_session( + // NetworkAddress::from_pubkey(cpk, true), [](ip_v) { log::critical(logcat, "FUCK YEAH"); + // }); + // } + // catch (const std::exception& e) + // { + // log::critical(logcat, "Failed to parse client netaddr: {}", e.what()); + // } + // }); + // } } else log::info(logcat, "SessionEndpoint configured to NOT publish ClientContact..."); @@ -590,21 +591,11 @@ namespace llarp::handlers log::trace(logcat, "inner payload: {}", buffer_printer{inner_payload}); - // add path-control wrapping for pivot to relay to aligned path - // auto& pivot = path->hops.back(); - auto onion_nonce = SymmNonce::make_random(); - // crypto::onion( - // reinterpret_cast(inner_payload.data()), - // inner_payload.size(), - // pivot.shared, - // onion_nonce, - // onion_nonce); - - auto pivot_payload = ONION::serialize_hop(remote_intro.pivot_txid.to_view(), onion_nonce, inner_payload); + auto pivot_payload = + ONION::serialize_hop(remote_intro.pivot_txid.to_view(), SymmNonce::make_random(), inner_payload); log::trace(logcat, "pivot payload: {}", buffer_printer{pivot_payload}); auto intermediate_payload = PATH::CONTROL::serialize("path_control", std::move(pivot_payload)); - // auto intermediate_payload = PATH::CONTROL::serialize("path_control", std::move(inner_payload)); log::trace(logcat, "intermediate payload: {}", buffer_printer{intermediate_payload}); path->send_path_control_message( diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 82513192ea..c7b7984b5e 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -965,6 +965,8 @@ namespace llarp::handlers auto pkt_is_ipv4 = pkt.is_ipv4(); + log::trace(logcat, "outbound packet is ipv{}", pkt_is_ipv4 ? "4" : "6"); + if (pkt_is_ipv4) { src = pkt.source_ipv4(); diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 2bea82c8e7..2d5ac13848 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -329,7 +329,8 @@ namespace llarp [this](oxen::quic::connection_interface& ci, uint64_t ec) { return on_conn_closed(ci, ec); }, [this](oxen::quic::dgram_interface&, bstring dgram) { handle_path_data_message(std::move(dgram)); }, is_service_node() ? alpns::SERVICE_INBOUND : alpns::CLIENT_INBOUND, - is_service_node() ? alpns::SERVICE_OUTBOUND : alpns::CLIENT_OUTBOUND); + is_service_node() ? alpns::SERVICE_OUTBOUND : alpns::CLIENT_OUTBOUND, + oxen::quic::opt::enable_datagrams{}); // While only service nodes accept inbound connections, clients must have this key verify // callback set. It will reject any attempted inbound connection to a lokinet client prior @@ -1392,9 +1393,9 @@ namespace llarp log::info(logcat, "Received path control for local client: {}", buffer_printer{payload}); - for (size_t i = 0; i < path->hops.size() - 1; ++i) + // TESTNET: + for (auto& hop : path->hops) { - auto& hop = path->hops[i]; nonce = crypto::onion( reinterpret_cast(payload.data()), payload.size(), @@ -1402,7 +1403,7 @@ namespace llarp nonce, hop.kx.xor_nonce); - log::info(logcat, "xchacha20 -> {}", buffer_printer{payload}); + log::trace(logcat, "xchacha20 -> {}", buffer_printer{payload}); } return handle_path_request(std::move(m), std::move(payload)); @@ -1418,16 +1419,15 @@ namespace llarp auto onion_nonce = nonce ^ hop->kx.xor_nonce; - // we only de-onion if we are NOT bridging a request over aligned paths + crypto::onion( + reinterpret_cast(payload.data()), + payload.size(), + hop->kx.shared_secret, + onion_nonce, + hop->kx.xor_nonce); + if (not inner_body.has_value()) { - crypto::onion( - reinterpret_cast(payload.data()), - payload.size(), - hop->kx.shared_secret, - onion_nonce, - hop->kx.xor_nonce); - // if terminal hop, payload should contain a request (e.g. "ons_resolve"); handle and respond. if (hop->terminal_hop) { @@ -1517,24 +1517,30 @@ namespace llarp return; } - auto hop = _router.path_context()->get_transit_hop(hop_id); - - if (not hop) + if (!_is_service_node) { - log::warning(logcat, "Received path data with unknown next hop (ID: {})", hop_id); - return; - } + auto path = _router.path_context()->get_path(hop_id); - nonce = crypto::onion( - reinterpret_cast(payload.data()), - payload.size(), - hop->kx.shared_secret, - nonce, - hop->kx.xor_nonce); + if (not path) + { + log::warning(logcat, "Client received path data with unknown rxID: {}", hop_id); + return; + } + + log::info(logcat, "Received path data for local client: {}", buffer_printer{payload}); + + for (auto& hop : path->hops) + { + nonce = crypto::onion( + reinterpret_cast(payload.data()), + payload.size(), + hop.kx.shared_secret, + nonce, + hop.kx.xor_nonce); + + log::trace(logcat, "xchacha20 -> {}", buffer_printer{payload}); + } - // if terminal hop, pass to the correct path expecting to receive this message - if (hop->terminal_hop) - { NetworkAddress sender; bstring data; @@ -1556,19 +1562,61 @@ namespace llarp { log::warning(logcat, "Exception: {}", e.what()); } + return; } - else + + auto hop = _router.path_context()->get_transit_hop(hop_id); + + if (not hop) + { + log::warning(logcat, "Received path data with unknown next hop (ID: {})", hop_id); + return; + } + + nonce = crypto::onion( + reinterpret_cast(payload.data()), + payload.size(), + hop->kx.shared_secret, + nonce, + hop->kx.xor_nonce); + + // if terminal hop, pass to the correct path expecting to receive this message + if (hop->terminal_hop) { - // if not terminal hop, relay datagram onwards - auto hop_is_rx = hop->rxid() == hop_id; + HopID hop_id; + std::string intermediate; - const auto& next_id = hop_is_rx ? hop->txid() : hop->rxid(); - const auto& next_router = hop_is_rx ? hop->upstream() : hop->downstream(); + try + { + std::tie(hop_id, intermediate) = PATH::DATA::deserialize_intermediate(oxenc::bt_dict_consumer{payload}); + } + catch (const std::exception& e) + { + log::warning(logcat, "Path data intermediate payload exception: {}", e.what()); + return; + } - std::string new_payload = ONION::serialize_hop(next_id.to_view(), nonce, std::move(payload)); + hop = _router.path_context()->get_transit_hop(hop_id); - send_data_message(next_router, std::move(new_payload)); + if (not hop) + { + log::warning(logcat, "We are bridge node for path data message with unknown rxID: {}", hop_id); + return; + } + + payload = std::move(intermediate); + log::debug(logcat, "Bridging path data message on hop: {}", hop->to_string()); } + + // if not terminal hop, relay datagram onwards + auto hop_is_rx = hop->rxid() == hop_id; + + const auto& next_id = hop_is_rx ? hop->txid() : hop->rxid(); + const auto& next_router = hop_is_rx ? hop->upstream() : hop->downstream(); + + std::string new_payload = ONION::serialize_hop(next_id.to_view(), nonce, std::move(payload)); + + send_data_message(next_router, std::move(new_payload)); } void LinkManager::handle_path_request(oxen::quic::message m, std::string payload) diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 157c55edac..2a554d224b 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -158,8 +158,6 @@ namespace llarp std::atomic is_stopping; - void handle_path_data_message(bstring dgram); - std::shared_ptr make_control( const std::shared_ptr& ci, const RouterID& rid); @@ -293,6 +291,7 @@ namespace llarp {"session_init"sv, &LinkManager::_handle_initiate_session}}; // Path relaying + void handle_path_data_message(bstring dgram); void handle_path_control(oxen::quic::message); void relay_path_request(oxen::quic::message m, std::string payload); diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index ee831c7725..1a62b343e6 100644 --- a/llarp/messages/path.hpp +++ b/llarp/messages/path.hpp @@ -268,7 +268,7 @@ namespace llarp { /** Fields for transmitting Path Data: - 'i' : RouterID of sender - - 'p' : request/command payload + - 'p' : messages payload NOTE: more fields may be added later as needed, hence the namespacing */ inline static std::string serialize(std::string payload, const RouterID& local) @@ -279,18 +279,44 @@ namespace llarp return std::move(btdp).str(); } + inline static std::string serialize_intermediate(std::string payload, const HopID& pivot_txid) + { + oxenc::bt_dict_producer btdp; + btdp.append("i", pivot_txid.to_view()); + btdp.append("p", payload); + return std::move(btdp).str(); + } + inline static std::tuple deserialize(oxenc::bt_dict_consumer& btdc) { RouterID remote; - bstring body; + bstring payload; try { remote.from_string(btdc.require("i")); - body = btdc.require("p"); + payload = btdc.require("p"); auto sender = NetworkAddress::from_pubkey(remote, true); - return {std::move(sender), std::move(body)}; + return {std::move(sender), std::move(payload)}; + } + catch (const std::exception& e) + { + throw std::runtime_error{"Exception caught deserializing path data:{}"_format(e.what())}; + } + } + + inline static std::tuple deserialize_intermediate(oxenc::bt_dict_consumer&& btdc) + { + HopID hop_id; + std::string payload; + + try + { + hop_id.from_string(btdc.require("i")); + payload = btdc.require("p"); + + return {std::move(hop_id), std::move(payload)}; } catch (const std::exception& e) { diff --git a/llarp/session/session.cpp b/llarp/session/session.cpp index 57a1383e03..7ce5fb6b28 100644 --- a/llarp/session/session.cpp +++ b/llarp/session/session.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -44,7 +45,10 @@ namespace llarp::session bool BaseSession::send_path_data_message(std::string data) { - return _current_path->send_path_data_message(std::move(data)); + auto inner_payload = PATH::DATA::serialize(std::move(data), _r.local_rid()); + auto intermediate_payload = + PATH::DATA::serialize_intermediate(std::move(inner_payload), _current_path->intro.pivot_txid); + return _r.send_data_message(_current_path->upstream_rid(), std::move(data)); } void BaseSession::recv_path_data_message(bstring body) diff --git a/llarp/vpn/packet_router.cpp b/llarp/vpn/packet_router.cpp index 817c0a4967..4c99e6e08b 100644 --- a/llarp/vpn/packet_router.cpp +++ b/llarp/vpn/packet_router.cpp @@ -1,7 +1,11 @@ #include "packet_router.hpp" +#include + namespace llarp::vpn { + static auto logcat = log::Cat("ip_packet"); + struct UDPPacketHandler : public Layer4Handler { ip_pkt_hook _base_handler; @@ -16,6 +20,7 @@ namespace llarp::vpn void handle_ip_packet(IPPacket pkt) override { + log::debug(logcat, "inbound pkt: ", pkt.info_line()); auto dstport = pkt.dest_port(); if (not dstport) @@ -38,8 +43,9 @@ namespace llarp::vpn explicit GenericLayer4Handler(ip_pkt_hook baseHandler) : _base_handler{std::move(baseHandler)} {} - void handle_ip_packet(IPPacket) override + void handle_ip_packet(IPPacket pkt) override { + log::debug(logcat, "inbound pkt: {}", pkt.info_line()); // TOFIX: // _base_handler(IPPacket::from_udp(std::move(pkt))); } @@ -49,6 +55,7 @@ namespace llarp::vpn void PacketRouter::handle_ip_packet(IPPacket pkt) { + log::debug(logcat, "inbound pkt: {}", pkt.info_line()); auto dest_port = pkt.dest_port(); if (not dest_port) From d8d794d8129ab2bfe8c327c61f9b471cca593832 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Mon, 9 Dec 2024 06:45:32 -0800 Subject: [PATCH 35/44] datagramio tweaking --- llarp/address/ip_packet.cpp | 17 +- llarp/address/ip_packet.hpp | 2 +- llarp/handlers/session.cpp | 39 ++--- llarp/handlers/tun.cpp | 8 +- llarp/link/link_manager.cpp | 298 ++++++++++++++++++++---------------- llarp/link/link_manager.hpp | 7 +- llarp/messages/path.hpp | 6 +- llarp/nodedb.cpp | 21 ++- llarp/path/path.cpp | 10 -- llarp/path/path.hpp | 6 +- llarp/path/transit_hop.cpp | 14 +- llarp/path/transit_hop.hpp | 2 + llarp/router/router.cpp | 8 +- llarp/router/router.hpp | 4 +- llarp/session/session.cpp | 20 ++- llarp/session/session.hpp | 8 +- 16 files changed, 260 insertions(+), 210 deletions(-) diff --git a/llarp/address/ip_packet.cpp b/llarp/address/ip_packet.cpp index e28fa45937..3ac0b77f94 100644 --- a/llarp/address/ip_packet.cpp +++ b/llarp/address/ip_packet.cpp @@ -305,9 +305,12 @@ namespace llarp return std::nullopt; } - NetworkPacket IPPacket::make_netpkt() + NetworkPacket IPPacket::make_netpkt() && { - return NetworkPacket{oxen::quic::Path{_src_addr, _dst_addr}, bview()}; + bstring data{}; + data.reserve(_buf.size()); + std::memcpy(data.data(), _buf.data(), _buf.size()); + return NetworkPacket{oxen::quic::Path{_src_addr, _dst_addr}, std::move(data)}; } bool IPPacket::load(const uint8_t* buf, size_t len) @@ -341,10 +344,7 @@ namespace llarp std::vector IPPacket::steal_buffer() && { - std::vector b; - b.resize(size()); - _buf.swap(b); - return b; + return std::move(_buf); } std::string IPPacket::steal_payload() && @@ -356,10 +356,7 @@ namespace llarp std::vector IPPacket::give_buffer() { - std::vector b; - b.resize(size()); - std::memcpy(b.data(), data(), size()); - return b; + return {_buf}; } std::string IPPacket::to_string() diff --git a/llarp/address/ip_packet.hpp b/llarp/address/ip_packet.hpp index b2f879bbbd..c3c87ee865 100644 --- a/llarp/address/ip_packet.hpp +++ b/llarp/address/ip_packet.hpp @@ -56,7 +56,7 @@ namespace llarp static IPPacket from_netpkt(NetworkPacket pkt); static std::optional from_buffer(const uint8_t* buf, size_t len); - NetworkPacket make_netpkt(); + NetworkPacket make_netpkt() &&; bool is_ipv4() const { return _is_v4; } diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index b3454f81b0..b92f2b6456 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -162,7 +162,7 @@ namespace llarp::handlers // _router.loop()->call_later(10s, [this]() { // try // { - // RouterID cpk{oxenc::from_base32z("bx13pza3snxgnccpbz1dpry6zsmspn718f9kyo9sipp3bdc848oy")}; + // RouterID cpk{oxenc::from_base32z("6e9wdnd4cj3j3rgc9ze8ctxqj4z976tmu8osbzwgabruabb4u1ky")}; // log::info(logcat, "Beginning session init to client: {}", cpk.to_network_address(false)); // _initiate_session( // NetworkAddress::from_pubkey(cpk, true), [](ip_v) { log::critical(logcat, "FUCK YEAH"); @@ -436,7 +436,6 @@ namespace llarp::handlers bool use_tun) { bool ret = true; - // assert(path->is_client_path()); auto inbound = std::make_shared( initiator, std::move(path), *this, std::move(tag), use_tun, std::move(kx_data)); @@ -463,7 +462,7 @@ namespace llarp::handlers else { // TODO: if this fails, we should close the session - log::warning(logcat, "TUN devcice failed to route session (remote: {}) to local ip", session->remote()); + log::warning(logcat, "TUN device failed to route session (remote: {}) to local ip", session->remote()); ret = false; } } @@ -491,7 +490,7 @@ namespace llarp::handlers if (not path or not path->is_ready()) continue; - log::debug(logcat, "Publishing ClientContact to pivot {}", path->pivot_rid()); + log::debug(logcat, "Publishing ClientContact on {}", path->hop_string()); ret &= path->publish_client_contact(ecc, [](oxen::quic::message m) { if (m) @@ -562,11 +561,6 @@ namespace llarp::handlers - 't' : Use Tun interface (bool) - 'u' : Authentication field - bt-encoded dict, values TBD - - TODO: - - update logic: sessions to relays do not need a shared_kx_data type - - client <-> client rely on symmetric DH across aligned paths - - client <-> relay end at the pivot */ void SessionEndpoint::_make_session( NetworkAddress remote, @@ -601,14 +595,24 @@ namespace llarp::handlers path->send_path_control_message( "path_control", std::move(intermediate_payload), - [this, remote, tag, path, hook = std::move(cb), session_keys = std::move(kx_data)]( - oxen::quic::message m) mutable { + [this, + remote, + tag, + path, + hook = std::move(cb), + session_keys = std::move(kx_data), + remote_intro = std::move(remote_intro)](oxen::quic::message m) mutable { if (m) { log::critical(logcat, "Call to InitiateSession succeeded!"); auto outbound = std::make_shared( - remote, *this, std::move(path), std::move(tag), std::move(session_keys)); + remote, + *this, + std::move(path), + std::move(tag), + std::move(session_keys), + std::move(remote_intro)); auto [session, _] = _sessions.insert_or_assign(std::move(remote), std::move(outbound)); @@ -697,17 +701,6 @@ namespace llarp::handlers auto& pivot = intro.pivot_rid; - // TOTHINK: why would we ever have a path keyed to remote client intro pivot txid? - // if (auto path = _router.path_context()->get_path(intro.pivot_txid)) - // { - // log::info( - // logcat, - // "Found path to pivot (rid: {}, tx_id: {}); initiating session!", - // intro.pivot_rid, - // intro.pivot_txid); - // return _make_session(std::move(remote), std::move(path), std::move(cb), is_exit); - // } - log::info(logcat, "Initiating session path-build to remote:{} via pivot:{}", remote, pivot); auto maybe_hops = aligned_hops_to_remote(pivot); diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index c7b7984b5e..bc8ec16dcc 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include namespace llarp::handlers @@ -995,7 +996,12 @@ namespace llarp::handlers if (auto session = _router.session_endpoint()->get_session(remote)) { - log::debug(logcat, "Dispatching outbound packet for session (remote: {})", remote); + log::debug( + logcat, + "Dispatching outbound {}B packet for session (remote: {}): {}", + pkt.size(), + remote, + buffer_printer{pkt.uview()}); session->send_path_data_message(std::move(pkt).steal_payload()); } else diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 2d5ac13848..64cd66d397 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -67,9 +67,6 @@ namespace llarp } return nullptr; - // return link_manager.router().loop()->call_get([this, rid = remote]() -> std::shared_ptr - // { - // }); } bool Endpoint::have_conn(const RouterID& remote) const @@ -282,15 +279,7 @@ namespace llarp void LinkManager::start_tickers() { log::debug(logcat, "Starting gossip ticker..."); - _gossip_ticker = _router.loop()->call_every( - _router._gossip_interval, - [this]() { - log::critical(logcat, "Regenerating and gossiping RC..."); - _router.relay_contact.resign(); - _router.save_rc(); - gossip_rc(_router.local_rid(), _router.relay_contact.to_remote()); - }, - true); + _gossip_ticker = _router.loop()->call_every(_router._gossip_interval, [this]() { regenerate_and_gossip_rc(); }); } LinkManager::LinkManager(Router& r) @@ -327,7 +316,7 @@ namespace llarp make_static_secret(_router.identity()), [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&, bstring dgram) { handle_path_data_message(std::move(dgram)); }, + [this](oxen::quic::dgram_interface&, bstring dgram) { return handle_path_data_message(std::move(dgram)); }, is_service_node() ? alpns::SERVICE_INBOUND : alpns::CLIENT_INBOUND, is_service_node() ? alpns::SERVICE_OUTBOUND : alpns::CLIENT_OUTBOUND, oxen::quic::opt::enable_datagrams{}); @@ -747,33 +736,38 @@ namespace llarp log::warning(logcat, "NodeDB query for {} random RCs for connection returned none", num_conns); } + void LinkManager::regenerate_and_gossip_rc() + { + log::info(logcat, "Regenerating and gossiping RC..."); + gossip_rc(_router.local_rid(), _router.relay_contact.to_remote()); + _router.save_rc(); + } + void LinkManager::gossip_rc(const RouterID& last_sender, const RemoteRC& rc) { - _router.loop()->call([this, last_sender, rc]() { - int count = 0; - const auto& gossip_src = rc.router_id(); + int count{}; + const auto& gossip_src = rc.router_id(); - for (auto& [rid, conn] : ep->service_conns) - { - // don't send back to the gossip source or the last sender - if (rid == gossip_src or rid == last_sender) - continue; - - send_control_message( - rid, "gossip_rc"s, GossipRCMessage::serialize(last_sender, rc), [](oxen::quic::message) { - log::trace(logcat, "PLACEHOLDER FOR GOSSIP RC RESPONSE HANDLER"); - }); - ++count; - } + for (auto& [rid, conn] : ep->service_conns) + { + if (not conn or not conn->is_active) + continue; - log::critical(logcat, "Dispatched {} GossipRC requests!", count); - }); + // don't send back to the gossip source or the last sender + if (rid == gossip_src or rid == last_sender) + continue; + + count += send_control_message( + rid, "gossip_rc"s, GossipRCMessage::serialize(last_sender, rc), [](oxen::quic::message) { + log::trace(logcat, "PLACEHOLDER FOR GOSSIP RC RESPONSE HANDLER"); + }); + } + + log::critical(logcat, "Dispatched {} GossipRC requests!", count); } void LinkManager::handle_gossip_rc(oxen::quic::message m) { - log::debug(logcat, "Handling GossipRC request..."); - // RemoteRC constructor wraps deserialization in a try/catch RemoteRC rc; RouterID src; @@ -792,13 +786,15 @@ namespace llarp return; } + log::trace(logcat, "Handling GossipRC request (sender:{}, rc:{})...", src, rc); + if (node_db->verify_store_gossip_rc(rc)) { - log::critical(logcat, "Received updated RC, forwarding to relay peers."); + log::info(logcat, "Received updated RC (rid:{}), forwarding to peers", rc.router_id()); gossip_rc(_router.local_rid(), rc); } else - log::debug(logcat, "Received known or old RC, not storing or forwarding."); + log::trace(logcat, "Received known or old RC, not storing or forwarding."); } // TODO: can probably use ::send_control_message instead. Need to discuss the potential @@ -1342,10 +1338,11 @@ namespace llarp return prev_message.respond(messages::OK_RESPONSE, false); } - if (m.timed_out) - log::info(logcat, "Upstream timed out on path build; relaying timeout"); - else - log::info(logcat, "Upstream returned path build failure; relaying response"); + log::info( + logcat, + "Upstream ({}) returned path build {}; relaying...", + transit_hop->upstream(), + m.timed_out ? "time out" : "failure"); return prev_message.respond(m.body_str(), m.is_error()); }); @@ -1393,7 +1390,6 @@ namespace llarp log::info(logcat, "Received path control for local client: {}", buffer_printer{payload}); - // TESTNET: for (auto& hop : path->hops) { nonce = crypto::onion( @@ -1444,15 +1440,18 @@ namespace llarp hop->to_string(), buffer_printer{*inner_body}); - auto hop_is_rx = hop->rxid() == hop_id; + auto next_ids = hop->next_id(hop_id); - const auto& next_id = hop_is_rx ? hop->txid() : hop->rxid(); - const auto& next_router = hop_is_rx ? hop->upstream() : hop->downstream(); + if (not next_ids) + { + log::error(logcat, "Failed to query hop ({}) for next ids (input: {})", hop->to_string(), hop_id); + return m.respond(messages::ERROR_RESPONSE, true); + } - std::string new_payload = ONION::serialize_hop(next_id.to_view(), onion_nonce, std::move(payload)); + std::string new_payload = ONION::serialize_hop(next_ids->second.to_view(), onion_nonce, std::move(payload)); send_control_message( - next_router, + next_ids->first, "path_control", std::move(new_payload), [hop_weak = hop->weak_from_this(), hop_id, prev_message = std::move(m)]( @@ -1501,122 +1500,161 @@ namespace llarp return _handle_path_control(std::move(m)); } - void LinkManager::handle_path_data_message(bstring message) + void LinkManager::handle_path_data_message(bstring data) { - HopID hop_id; - std::string payload; - SymmNonce nonce; - - try - { - std::tie(hop_id, nonce, payload) = ONION::deserialize_hop(oxenc::bt_dict_consumer{message}); - } - catch (const std::exception& e) - { - log::warning(logcat, "Exception: {}", e.what()); - return; - } - - if (!_is_service_node) - { - auto path = _router.path_context()->get_path(hop_id); + _router.loop()->call([this, message = std::move(data)]() { + HopID hop_id; + std::string payload; + SymmNonce nonce; - if (not path) + try + { + std::tie(hop_id, nonce, payload) = ONION::deserialize_hop(oxenc::bt_dict_consumer{message}); + } + catch (const std::exception& e) { - log::warning(logcat, "Client received path data with unknown rxID: {}", hop_id); + log::warning(logcat, "Exception: {}", e.what()); return; } - log::info(logcat, "Received path data for local client: {}", buffer_printer{payload}); - - for (auto& hop : path->hops) + if (!_is_service_node) { - nonce = crypto::onion( - reinterpret_cast(payload.data()), - payload.size(), - hop.kx.shared_secret, - nonce, - hop.kx.xor_nonce); + auto path = _router.path_context()->get_path(hop_id); - log::trace(logcat, "xchacha20 -> {}", buffer_printer{payload}); - } + if (not path) + { + log::warning(logcat, "Client received path data with unknown rxID: {}", hop_id); + return; + } - NetworkAddress sender; - bstring data; + log::info(logcat, "Received path data for local client: {}", buffer_printer{payload}); - try - { - oxenc::bt_dict_consumer btdc{payload}; - std::tie(sender, data) = PATH::DATA::deserialize(btdc); + for (auto& hop : path->hops) + { + nonce = crypto::onion( + reinterpret_cast(payload.data()), + payload.size(), + hop.kx.shared_secret, + nonce, + hop.kx.xor_nonce); + + log::debug(logcat, "xchacha20 -> {}", buffer_printer{payload}); + } + + NetworkAddress sender; + bstring data; - if (auto session = _router.session_endpoint()->get_session(sender)) + try { - session->recv_path_data_message(std::move(data)); + oxenc::bt_dict_consumer btdc{payload}; + std::tie(sender, data) = PATH::DATA::deserialize(btdc); + + if (auto session = _router.session_endpoint()->get_session(sender)) + { + session->recv_path_data_message(std::move(data)); + } + else + { + log::warning(logcat, "Could not find session (remote:{}) to relay path data message!", sender); + } } - else + catch (const std::exception& e) { - log::warning(logcat, "Could not find session (remote:{}) to relay path data message!", sender); + log::warning(logcat, "Exception: {}: {}", e.what(), buffer_printer{data}); } + return; } - catch (const std::exception& e) - { - log::warning(logcat, "Exception: {}", e.what()); - } - return; - } - auto hop = _router.path_context()->get_transit_hop(hop_id); + log::debug(logcat, "Received path data for local relay: {}", buffer_printer{payload}); - if (not hop) - { - log::warning(logcat, "Received path data with unknown next hop (ID: {})", hop_id); - return; - } + auto hop = _router.path_context()->get_transit_hop(hop_id); - nonce = crypto::onion( - reinterpret_cast(payload.data()), - payload.size(), - hop->kx.shared_secret, - nonce, - hop->kx.xor_nonce); - - // if terminal hop, pass to the correct path expecting to receive this message - if (hop->terminal_hop) - { - HopID hop_id; - std::string intermediate; - - try - { - std::tie(hop_id, intermediate) = PATH::DATA::deserialize_intermediate(oxenc::bt_dict_consumer{payload}); - } - catch (const std::exception& e) + if (not hop) { - log::warning(logcat, "Path data intermediate payload exception: {}", e.what()); + log::warning(logcat, "Received path data with unknown next hop (ID: {})", hop_id); return; } - hop = _router.path_context()->get_transit_hop(hop_id); + auto onion_nonce = nonce ^ hop->kx.xor_nonce; - if (not hop) + crypto::onion( + reinterpret_cast(payload.data()), + payload.size(), + hop->kx.shared_secret, + onion_nonce, + hop->kx.xor_nonce); + + std::optional> next_ids = std::nullopt; + std::string next_payload; + + // if terminal hop, pass to the correct path expecting to receive this message + if (hop->terminal_hop) { - log::warning(logcat, "We are bridge node for path data message with unknown rxID: {}", hop_id); - return; - } + log::debug( + logcat, "We are terminal hop for path data: {}: {}", hop->to_string(), buffer_printer{payload}); - payload = std::move(intermediate); - log::debug(logcat, "Bridging path data message on hop: {}", hop->to_string()); - } + HopID ihid; + std::string intermediate; + + try + { + std::tie(ihid, intermediate) = + PATH::DATA::deserialize_intermediate(oxenc::bt_dict_consumer{payload}); + } + catch (const std::exception& e) + { + log::warning( + logcat, "Path data intermediate payload exception: {}: {}", e.what(), buffer_printer{payload}); + return; + } + + log::debug(logcat, "Inbound path rxid:{}, outbound path txid:{}", hop_id, ihid); + + auto next_hop = _router.path_context()->get_transit_hop(ihid); - // if not terminal hop, relay datagram onwards - auto hop_is_rx = hop->rxid() == hop_id; + if (not next_hop) + { + log::warning(logcat, "We are bridge node for path data message with unknown txID: {}", ihid); + return; + } - const auto& next_id = hop_is_rx ? hop->txid() : hop->rxid(); - const auto& next_router = hop_is_rx ? hop->upstream() : hop->downstream(); + log::debug(logcat, "Bridging path data message on hop: {}", next_hop->to_string()); - std::string new_payload = ONION::serialize_hop(next_id.to_view(), nonce, std::move(payload)); + next_ids = next_hop->next_id(ihid); - send_data_message(next_router, std::move(new_payload)); + onion_nonce ^= next_hop->kx.xor_nonce; + + crypto::onion( + reinterpret_cast(intermediate.data()), + intermediate.size(), + next_hop->kx.shared_secret, + onion_nonce, + next_hop->kx.xor_nonce); + + if (not next_ids) + { + log::error( + logcat, "Failed to query hop ({}) for next ids (input: {})", next_hop->to_string(), hop_id); + return; + } + + next_payload = ONION::serialize_hop(next_ids->second.to_view(), onion_nonce, std::move(intermediate)); + } + else + { + next_ids = hop->next_id(hop_id); + + if (not next_ids) + { + log::error(logcat, "Failed to query hop ({}) for next ids (input: {})", hop->to_string(), hop_id); + return; + } + + next_payload = ONION::serialize_hop(next_ids->second.to_view(), onion_nonce, std::move(payload)); + } + + send_data_message(next_ids->first, std::move(next_payload)); + }); } void LinkManager::handle_path_request(oxen::quic::message m, std::string payload) diff --git a/llarp/link/link_manager.hpp b/llarp/link/link_manager.hpp index 2a554d224b..4656a792ab 100644 --- a/llarp/link/link_manager.hpp +++ b/llarp/link/link_manager.hpp @@ -179,6 +179,8 @@ namespace llarp const oxen::quic::Address& local() { return addr; } + void regenerate_and_gossip_rc(); + void gossip_rc(const RouterID& last_sender, const RemoteRC& rc); void handle_gossip_rc(oxen::quic::message m); @@ -346,7 +348,6 @@ namespace llarp _is_service_node ? RELAY_KEEP_ALIVE : CLIENT_KEEP_ALIVE, std::forward(opts)...); - // auto auto control_stream = conn_interface->template open_stream( [](oxen::quic::Stream&, uint64_t error_code) { log::warning(logcat, "BTRequestStream closed unexpectedly (ec:{})", error_code); @@ -365,7 +366,7 @@ namespace llarp : conn_interface->send_datagram(std::move(body)); itr->second = - std::make_shared(std::move(conn_interface), std::move(control_stream), true); + std::make_shared(std::move(conn_interface), std::move(control_stream)); log::info(logcat, "Outbound connection to RID:{} added to service conns...", rid); return true; @@ -410,7 +411,7 @@ namespace llarp link_manager.register_commands(control_stream, rid, not _is_service_node); itr->second = - std::make_shared(std::move(conn_interface), std::move(control_stream), true); + std::make_shared(std::move(conn_interface), std::move(control_stream)); log::info(logcat, "Outbound connection to RID:{} added to service conns...", rid); return true; diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index 1a62b343e6..69d5bac675 100644 --- a/llarp/messages/path.hpp +++ b/llarp/messages/path.hpp @@ -60,14 +60,14 @@ namespace llarp throw std::runtime_error{messages::ERROR_RESPONSE}; } - log::info(logcat, "payload: {}", buffer_printer{payload}); + log::trace(logcat, "payload: {}", buffer_printer{payload}); try { kx_data.server_dh(local_sk); kx_data.decrypt(to_uspan(payload)); - log::info(logcat, "xchacha -> payload: {}", buffer_printer{payload}); + log::trace(logcat, "xchacha -> payload: {}", buffer_printer{payload}); kx_data.generate_xor(); } @@ -227,7 +227,7 @@ namespace llarp throw std::runtime_error{BAD_CRYPTO}; } - log::critical(logcat, "TransitHop data successfully deserialized: {}", hop->to_string()); + log::trace(logcat, "TransitHop data successfully deserialized: {}", hop->to_string()); return hop; } } // namespace BUILD diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index 4aa4cbb98b..fcadfa5053 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -466,10 +466,6 @@ namespace llarp auto& src = fetch_source; - // TESTNET: - // rid_sources.emplace(oxenc::from_base32z("55fxrrdt9ggkra9yoi58gbespa13is1sqqrykdzjamgkxrq91tto")); - // auto& src = _bootstraps.current().router_id(); - for (const auto& target : rid_sources) { if (target == src) @@ -943,8 +939,18 @@ namespace llarp if (rid == _router.local_rid()) return false; - known_rcs.erase(rc); - rc_lookup.erase(rid); + // Use the rc_lookup RemoteRC to delete from known_rcs, as the differing timestamp between the old and new will + // result in set::insert not matching to the previous value + if (auto it = rc_lookup.find(rid); it != rc_lookup.end()) + { + known_rcs.erase(it->second); + rc_lookup.erase(it); + } + else + { + known_rcs.erase(rc); + rc_lookup.erase(rid); + } auto [itr, b] = known_rcs.insert(std::move(rc)); ret &= b; @@ -980,7 +986,8 @@ namespace llarp return false; } - return put_rc(rc); + put_rc(std::move(rc)); + return true; } void NodeDB::remove_many_from_disk_async(std::unordered_set remove) const diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 7faafe5a11..ec310cdfca 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -76,14 +76,6 @@ namespace llarp::path hops.back().terminal_hop = true; - // _local_hop = std::make_shared(); - // _local_hop->_rid = _router.local_rid(); - // _local_hop->_upstream = hops.front()._rid; - // _local_hop->_downstream = _local_hop->_rid; - // _local_hop->_rxid = HopID::make_random(); - // _local_hop->_txid = hops.front()._rxid; - // _local_hop->terminal_hop = true; - log::trace(logcat, "Path populated with hops: {}", hop_string()); // initialize parts of the clientintro @@ -208,7 +200,6 @@ namespace llarp::path { auto inner_payload = PATH::DATA::serialize(std::move(data), _router.local_rid()); auto outer_payload = make_path_message(std::move(inner_payload)); - return _router.send_data_message(upstream_rid(), std::move(outer_payload)); } @@ -217,7 +208,6 @@ namespace llarp::path { auto inner_payload = PATH::CONTROL::serialize(std::move(endpoint), std::move(body)); auto outer_payload = make_path_message(std::move(inner_payload)); - return _router.send_control_message(upstream_rid(), "path_control", std::move(outer_payload), std::move(func)); } diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 7c8d03a71f..78a87d3c25 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -124,6 +124,8 @@ namespace llarp bool send_path_data_message(std::string body); + std::string make_path_message(std::string payload); + bool is_established() const { return _established; } bool is_ready(std::chrono::milliseconds now = llarp::time_now_ms()) const; @@ -165,9 +167,7 @@ namespace llarp std::string to_string() const; static constexpr bool to_string_formattable = true; - private: - std::string make_path_message(std::string payload); - + protected: void populate_internals(const std::vector& _hops); /// call obtained exit hooks diff --git a/llarp/path/transit_hop.cpp b/llarp/path/transit_hop.cpp index 25145beb20..9f7879e1e3 100644 --- a/llarp/path/transit_hop.cpp +++ b/llarp/path/transit_hop.cpp @@ -35,7 +35,7 @@ namespace llarp::path // generate hash of hop key for nonce mutation kx.generate_xor(); - log::critical(logcat, "TransitHop data successfully deserialized: {}", to_string()); + log::trace(logcat, "TransitHop data successfully deserialized: {}", to_string()); } void TransitHop::bt_decode(oxenc::bt_dict_consumer&& btdc) @@ -57,6 +57,18 @@ namespace llarp::path return std::move(btdp).str(); } + std::optional> TransitHop::next_id(const HopID& h) const + { + std::optional> ret = std::nullopt; + + if (h == _rxid) + ret = {_upstream, _txid}; + else if (h == _txid) + ret = {_downstream, _rxid}; + + return ret; + } + nlohmann::json TransitHop::ExtractStatus() const { return { diff --git a/llarp/path/transit_hop.hpp b/llarp/path/transit_hop.hpp index 54a13cacfe..07d82b24a5 100644 --- a/llarp/path/transit_hop.hpp +++ b/llarp/path/transit_hop.hpp @@ -51,6 +51,8 @@ namespace llarp HopID txid() { return _txid; } const HopID& txid() const { return _txid; } + std::optional> next_id(const HopID& h) const; + bool operator<(const TransitHop& other) const { return std::tie(_txid, _rxid, _upstream, _downstream) diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 648f44721e..436c3b16d9 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -687,7 +687,7 @@ namespace llarp // All relays have TUN if (_using_tun = conf.network.init_tun; _using_tun) { - log::critical(logcat, "Initializing virtual TUN device..."); + log::debug(logcat, "Initializing virtual TUN device..."); init_tun(); } @@ -757,16 +757,10 @@ namespace llarp void Router::save_rc() { - // _node_db->put_rc(router_contact.view()); log::info(logcat, "Saving RC file to {}", our_rc_file); queue_disk_io([&]() { relay_contact.write(our_rc_file); }); } - // bool Router::is_bootstrap_node(const RouterID r) const - // { - // return _node_db->is_bootstrap_node(r); - // } - bool Router::should_report_stats(std::chrono::milliseconds now) const { return now - _last_stats_report > REPORT_STATS_INTERVAL; diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 24295afba7..02b29d3979 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -52,8 +52,8 @@ namespace llarp // inline constexpr size_t INTROSET_STORAGE_REDUNDANCY{(INTROSET_RELAY_REDUNDANCY * INTROSET_REQS_PER_RELAY)}; // TESTNET: these constants are shortened for testing purposes - inline constexpr std::chrono::milliseconds TESTNET_GOSSIP_INTERVAL{10min}; - inline constexpr std::chrono::milliseconds RC_UPDATE_INTERVAL{10min}; + inline constexpr std::chrono::milliseconds TESTNET_GOSSIP_INTERVAL{5min}; + inline constexpr std::chrono::milliseconds RC_UPDATE_INTERVAL{5min}; inline constexpr std::chrono::milliseconds INITIAL_ATTEMPT_INTERVAL{30s}; // as we advance towards full mesh, we try to connect to this number per tick inline constexpr int FULL_MESH_ITERATION{1}; diff --git a/llarp/session/session.cpp b/llarp/session/session.cpp index 7ce5fb6b28..02d6b1864d 100644 --- a/llarp/session/session.cpp +++ b/llarp/session/session.cpp @@ -22,7 +22,8 @@ namespace llarp::session SessionTag _t, bool use_tun, bool is_outbound, - std::optional kx_data) + std::optional kx_data, + std::optional _remote_intro) : _r{r}, _parent{parent}, _tag{std::move(_t)}, @@ -33,6 +34,8 @@ namespace llarp::session { if (kx_data.has_value()) session_keys = std::move(*kx_data); + if (_remote_intro.has_value()) + remote_intro = std::move(*_remote_intro); set_new_current_path(std::move(_p)); } @@ -45,10 +48,12 @@ namespace llarp::session bool BaseSession::send_path_data_message(std::string data) { + // session_keys.encrypt(to_uspan(data)); auto inner_payload = PATH::DATA::serialize(std::move(data), _r.local_rid()); auto intermediate_payload = - PATH::DATA::serialize_intermediate(std::move(inner_payload), _current_path->intro.pivot_txid); - return _r.send_data_message(_current_path->upstream_rid(), std::move(data)); + PATH::DATA::serialize_intermediate(std::move(inner_payload), remote_intro.pivot_txid); + return _r.send_data_message( + _current_path->upstream_rid(), _current_path->make_path_message(std::move(intermediate_payload))); } void BaseSession::recv_path_data_message(bstring body) @@ -62,8 +67,7 @@ namespace llarp::session _current_path->unlink_session(); _current_path = std::move(_new_path); - - _pivot_txid = _current_path->pivot_rxid(); + _pivot_txid = _current_path->pivot_txid(); if (_use_tun) _current_path->link_session([this](bstring data) { @@ -162,7 +166,8 @@ namespace llarp::session handlers::SessionEndpoint& parent, std::shared_ptr path, SessionTag _t, - std::optional kx_data) + std::optional kx_data, + std::optional remote_intro) : PathHandler{parent._router, path::DEFAULT_PATHS_HELD}, BaseSession{ _router, @@ -172,7 +177,8 @@ namespace llarp::session std::move(_t), _router.using_tun_if(), true, - std::move(kx_data)}, + std::move(kx_data), + std::move(remote_intro)}, _is_snode_session{not _remote.is_client()}, _last_use{_router.now()} { diff --git a/llarp/session/session.hpp b/llarp/session/session.hpp index 24263a63bb..71eac6c511 100644 --- a/llarp/session/session.hpp +++ b/llarp/session/session.hpp @@ -49,6 +49,8 @@ namespace llarp shared_kx_data session_keys{}; + ClientIntro remote_intro; + bool _use_tun; bool _is_outbound; @@ -80,7 +82,8 @@ namespace llarp SessionTag _t, bool use_tun, bool is_outbound, - std::optional kx_data = std::nullopt); + std::optional kx_data = std::nullopt, + std::optional remote_intro = std::nullopt); virtual ~BaseSession() = default; @@ -122,7 +125,8 @@ namespace llarp handlers::SessionEndpoint& parent, std::shared_ptr path, SessionTag _t, - std::optional kx_data = std::nullopt); + std::optional kx_data = std::nullopt, + std::optional remote_intro = std::nullopt); ~OutboundSession() override; From 2db462de9cec700ada50dbdf44fe1087ba3e9365 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Wed, 11 Dec 2024 07:23:08 -0800 Subject: [PATCH 36/44] client data message routing --- llarp/address/ip_packet.cpp | 17 ++++++----- llarp/address/ip_range.cpp | 3 +- llarp/address/utils.hpp | 28 ++++++++----------- llarp/config/config.cpp | 7 ++--- llarp/handlers/session.cpp | 4 +-- llarp/handlers/tun.cpp | 56 +++++++++++++++++-------------------- llarp/handlers/tun.hpp | 6 ++-- llarp/link/link_manager.cpp | 25 ++++++++--------- llarp/messages/path.hpp | 2 +- llarp/net/net.hpp | 3 -- llarp/net/posix.cpp | 2 +- llarp/router/router.cpp | 6 ++-- llarp/session/session.cpp | 4 +-- llarp/vpn/linux.hpp | 2 +- llarp/vpn/packet_router.cpp | 6 ++-- 15 files changed, 77 insertions(+), 94 deletions(-) diff --git a/llarp/address/ip_packet.cpp b/llarp/address/ip_packet.cpp index 3ac0b77f94..d1d19ba815 100644 --- a/llarp/address/ip_packet.cpp +++ b/llarp/address/ip_packet.cpp @@ -57,6 +57,9 @@ namespace llarp return ret; } + static const auto v4_header_version = oxenc::host_to_big(uint8_t{4}); + static const auto udp_header_proto = oxenc::host_to_big(uint8_t{17}); + void IPPacket::_init_internals() { _header = reinterpret_cast(data()); @@ -65,12 +68,8 @@ namespace llarp if (_buf.empty()) return; - // log::trace(logcat, "ippkt header: {}", buffer_printer{_buf}); - // log::trace(logcat, "ippkt protocol: {}", _header->protocol); - // log::trace(logcat, "ippkt version: {}", _header->version); - - _is_v4 = _header->version == oxenc::host_to_big(uint8_t{4}); - _is_udp = _header->protocol == uint8_t{17}; + _is_v4 = _header->version == v4_header_version; + _is_udp = _header->protocol == udp_header_proto; uint16_t src_port = (_is_udp) ? *reinterpret_cast(data() + (static_cast(_header->header_len) * 4)) : 0; @@ -126,8 +125,8 @@ namespace llarp std::basic_string_view head_u16s{reinterpret_cast(_header), sizeof(ip_header)}; // set new IP addresses - _header->src = src.addr; - _header->dest = dst.addr; + _header->src = oxenc::host_to_big(src.addr); + _header->dest = oxenc::host_to_big(dst.addr); switch (_header->protocol) { @@ -290,7 +289,7 @@ namespace llarp oxenc::write_host_as_big(1500, itr); itr += 2; - // copy ip header and first 8 bytes of datagram for icmp rject + // copy ip header and first 8 bytes of datagram for icmp reject std::memcpy(itr, _buf.data(), ip_hdr_sz + ICMP_HEADER_SIZE); itr += ip_hdr_sz + ICMP_HEADER_SIZE; diff --git a/llarp/address/ip_range.cpp b/llarp/address/ip_range.cpp index c47069af65..5ae5d47e53 100644 --- a/llarp/address/ip_range.cpp +++ b/llarp/address/ip_range.cpp @@ -91,6 +91,7 @@ namespace llarp for (const auto& e : excluding) if (e == range) return false; + log::debug(logcat, "{}", std::get(range).base); return true; }; @@ -109,7 +110,7 @@ namespace llarp { for (size_t n = 0; n < num_ipv6_private; ++n) { - if (auto v6 = ipv6(0xfd2e, 0x6c6f, 0x6b69, n) / 64; filter(v6)) + if (auto v6 = ipv6(0xfd2e, 0x6c6f, 0x6b69, n, 0x0000, 0x0000, 0x0000, 0x0001) / 64; filter(v6)) return v6; } } diff --git a/llarp/address/utils.hpp b/llarp/address/utils.hpp index 227dd58ccc..df5c2f995a 100644 --- a/llarp/address/utils.hpp +++ b/llarp/address/utils.hpp @@ -61,27 +61,29 @@ namespace llarp return ret; }; + inline constexpr auto DIGITS = "0123456789"sv; + inline constexpr auto PDIGITS = "0123456789."sv; + inline constexpr auto ALDIGITS = "0123456789abcdef:."sv; + inline std::pair parse_addr(std::string_view addr, std::optional default_port) { std::pair result; auto &[host, port] = result; - if (auto p = addr.find_last_not_of("0123456789"); + if (auto p = addr.find_last_not_of(DIGITS); p != std::string_view::npos && p + 2 <= addr.size() && addr[p] == ':') { if (!parse_int(addr.substr(p + 1), port)) throw std::invalid_argument{"Invalid address: could not parse port"}; addr.remove_suffix(addr.size() - p); } - else if (default_port) + else if (default_port.has_value()) // use ::has_value() in case default_port is set but is == 0 { - // log::critical(utilcat, "Setting default port for addr parse!"); port = *default_port; } else - { - throw std::invalid_argument{"Invalid address: no port was specified and there is no default"}; - } + throw std::invalid_argument{ + "Invalid address: argument contains no port and no default was specified (input:{})"_format(addr)}; bool had_sq_brackets = false; @@ -92,20 +94,14 @@ namespace llarp had_sq_brackets = true; } - if (auto p = addr.find_first_not_of("0123456789."); p != std::string_view::npos) + if (auto p = addr.find_first_not_of(PDIGITS); p != std::string_view::npos) { - if (auto q = addr.find_first_not_of("0123456789abcdef:."); q != std::string_view::npos) + if (auto q = addr.find_first_not_of(ALDIGITS); q != std::string_view::npos) throw std::invalid_argument{"Invalid address: does not look like IPv4 or IPv6!"}; if (!had_sq_brackets) throw std::invalid_argument{"Invalid address: IPv6 addresses require [...] square brackets"}; } - // if (addr.empty()) - // { - // log::critical(utilcat, "addr is empty, tough titties buddy"); // TESTNET: remove this log please - // // addr = "::"; - // } - host = addr; return result; } @@ -117,10 +113,10 @@ namespace llarp std::array ret{}; for (size_t n = 16; n < 32; ++n) - ret[n - 16] = ipv4(172, n, 0, 0) / 16; + ret[n - 16] = ipv4(172, n, 0, 1) / 16; for (size_t n = 0; n < 256; ++n) - ret[n + 16] = ipv4(10, n, 0, 0) / 16; + ret[n + 16] = ipv4(10, n, 0, 1) / 16; return ret; } diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index a27dea7f26..ad5e45b33a 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -1230,15 +1230,12 @@ namespace llarp if (auto pos = arg_v.find(':'); pos != arg_v.npos) { // host = arg_v.substr(0, pos); - log::critical(logcat, "Parsing input: {}", arg); std::tie(host, p) = detail::parse_addr(arg_v, DEFAULT_LISTEN_PORT); - log::critical(logcat, "Parsed input = {}:{}", host, p); } if (host.empty()) { - log::critical( - logcat, "Host value empty, port:{}{}", p, p == DEFAULT_LISTEN_PORT ? "(DEFAULT PORT)" : ""); + log::debug(logcat, "Host value empty, port:{}{}", p, p == DEFAULT_LISTEN_PORT ? "(DEFAULT PORT)" : ""); given_port_only = p != DEFAULT_LISTEN_PORT; maybe = net_ptr->get_best_public_address(true, p); } @@ -1248,7 +1245,7 @@ namespace llarp if (maybe and maybe->is_loopback()) throw std::invalid_argument{"{} is a loopback address"_format(arg)}; - log::critical(logcat, "parsed address: {}", *maybe); + log::trace(logcat, "parsed address: {}", *maybe); return maybe; }; diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index b92f2b6456..c3383527de 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -159,10 +159,10 @@ namespace llarp::handlers // { // testnet_trigger = true; - // _router.loop()->call_later(10s, [this]() { + // _router.loop()->call_later(5s, [this]() { // try // { - // RouterID cpk{oxenc::from_base32z("6e9wdnd4cj3j3rgc9ze8ctxqj4z976tmu8osbzwgabruabb4u1ky")}; + // RouterID cpk{oxenc::from_base32z("mprqiu67f4gr8hb4zx8kuuqmxanmct4b6fp1nkeeruhxx9tqwc7y")}; // log::info(logcat, "Beginning session init to client: {}", cpk.to_network_address(false)); // _initiate_session( // NetworkAddress::from_pubkey(cpk, true), [](ip_v) { log::critical(logcat, "FUCK YEAH"); diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index bc8ec16dcc..93b4d4c3fa 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -960,13 +960,14 @@ namespace llarp::handlers } } + // handles an outbound packet going OUT to the network void TunEndpoint::handle_outbound_packet(IPPacket pkt) { ip_v src, dest; auto pkt_is_ipv4 = pkt.is_ipv4(); - log::trace(logcat, "outbound packet is ipv{}", pkt_is_ipv4 ? "4" : "6"); + log::debug(logcat, "outbound packet: {}", pkt.info_line()); if (pkt_is_ipv4) { @@ -979,6 +980,8 @@ namespace llarp::handlers dest = pkt.dest_ipv6(); } + log::debug(logcat, "src:{}, dest:{}", src, dest); + if constexpr (llarp::platform::is_apple) { if (ip_equals_address(dest, _local_addr, pkt_is_ipv4)) @@ -1005,45 +1008,30 @@ namespace llarp::handlers session->send_path_data_message(std::move(pkt).steal_payload()); } else - log::warning(logcat, "Could not find session (remote: {}) for outbound packet!", remote); + log::info(logcat, "Could not find session (remote: {}) for outbound packet!", remote); } else log::debug(logcat, "Could not find remote for route {}", pkt.info_line()); } - bool TunEndpoint::obtain_src_for_remote(const NetworkAddress& remote, ip_v& src, bool use_ipv4) + std::optional TunEndpoint::obtain_src_for_remote(const NetworkAddress& remote, bool use_ipv4) { - // we are receiving traffic from a session to a local exit node if (auto maybe_src = _local_ip_mapping.get_local_from_remote(remote)) { if (std::holds_alternative(*maybe_src)) { if (use_ipv4) - src = *maybe_src; - else - { - auto quicaddr = oxen::quic::Address{std::get(*maybe_src)}; - src = quicaddr.to_ipv6(); - } - } - else - { - if (use_ipv4) - { - auto quicaddr = oxen::quic::Address{std::get(*maybe_src)}; - src = quicaddr.to_ipv4(); - } - else - src = *maybe_src; + return *maybe_src; + return oxen::quic::Address{std::get(*maybe_src)}.to_ipv6(); } - } - else - { - log::critical(logcat, "Unable to find local IP for inbound packet from remote: {}", remote); - return false; + + if (use_ipv4) + return oxen::quic::Address{std::get(*maybe_src)}.to_ipv4(); + return *maybe_src; } - return true; + log::warning(logcat, "Unable to find src IP for inbound packet from remote: {}", remote); + return std::nullopt; } void TunEndpoint::send_packet_to_net_if(IPPacket&& pkt) @@ -1058,9 +1046,11 @@ namespace llarp::handlers else pkt.update_ipv6_address(std::get(src), std::get(dest)); + log::debug(logcat, "Rewritten packet: {}: {}", pkt.info_line(), buffer_printer{pkt.uview()}); send_packet_to_net_if(std::move(pkt)); } + // handles an inbound packet coming IN from the network bool TunEndpoint::handle_inbound_packet( IPPacket pkt, NetworkAddress remote, bool is_exit_session, bool is_outbound_session) { @@ -1070,6 +1060,7 @@ namespace llarp::handlers if (is_exit_session and is_outbound_session) { + log::debug(logcat, "inbound exit session pkt: {}", pkt.info_line()); // we are receiving traffic from a session to a remote exit node if (pkt_is_ipv4) { @@ -1088,13 +1079,12 @@ namespace llarp::handlers if (not maybe_remote) { - log::critical( - logcat, "Could not find mapping of local IP (ip:{}) for session to remote: {}", src, remote); + log::info(logcat, "Could not find mapping of local IP (ip:{}) for session to remote: {}", src, remote); return false; } if (*maybe_remote != remote) { - log::critical( + log::info( logcat, "Internal mapping of local IP (ip:{}, remote:{}) did not match inbound packet from remote: {}", src, @@ -1107,6 +1097,7 @@ namespace llarp::handlers { if (is_exit_session and not is_outbound_session) { + log::debug(logcat, "inbound exit session pkt: {}", pkt.info_line()); // we are receiving traffic from a session to a local exit node if (not is_allowing_traffic(pkt)) return false; @@ -1118,6 +1109,7 @@ namespace llarp::handlers } else { + log::debug(logcat, "inbound service session pkt: {}", pkt.info_line()); // we are receiving hidden service traffic if (pkt_is_ipv4) dest = _local_addr.to_ipv4(); @@ -1125,10 +1117,14 @@ namespace llarp::handlers dest = _local_ipv6.to_ipv6(); } - if (not obtain_src_for_remote(remote, src, pkt_is_ipv4)) + if (auto maybe_src = obtain_src_for_remote(remote, pkt_is_ipv4)) + src = std::move(*maybe_src); + else return false; } + log::debug(logcat, "src:{}, dest:{}", src, dest); + rewrite_and_send_packet(std::move(pkt), src, dest); return true; diff --git a/llarp/handlers/tun.hpp b/llarp/handlers/tun.hpp index 36e24d2dc1..a0952ee1fd 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -108,12 +108,12 @@ namespace llarp::handlers void setup_dns(); // INPROGRESS: new API - // Handles an outbound packet going out INTO the network + // Handles an outbound packet going OUT to the network void handle_outbound_packet(IPPacket pkt); void rewrite_and_send_packet(IPPacket&& pkt, ip_v src, ip_v dest); - // Handle an inbound packet coming in FROM the network + // Handles an inbound packet coming IN from the network bool handle_inbound_packet(IPPacket pkt, NetworkAddress remote, bool is_exit_session, bool is_outbound_session); // Upon session creation, SessionHandler will instruct TunEndpoint to requisition a private IP through which to @@ -162,7 +162,7 @@ namespace llarp::handlers private: std::optional get_next_local_ip(); - bool obtain_src_for_remote(const NetworkAddress& remote, ip_v& src, bool use_ipv4); + std::optional obtain_src_for_remote(const NetworkAddress& remote, bool use_ipv4); void send_packet_to_net_if(IPPacket&& pkt); }; diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 64cd66d397..a79f86e965 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1527,8 +1527,6 @@ namespace llarp return; } - log::info(logcat, "Received path data for local client: {}", buffer_printer{payload}); - for (auto& hop : path->hops) { nonce = crypto::onion( @@ -1537,17 +1535,16 @@ namespace llarp hop.kx.shared_secret, nonce, hop.kx.xor_nonce); - - log::debug(logcat, "xchacha20 -> {}", buffer_printer{payload}); } + log::info(logcat, "Received path data for local client: {}", buffer_printer{payload}); + NetworkAddress sender; bstring data; try { - oxenc::bt_dict_consumer btdc{payload}; - std::tie(sender, data) = PATH::DATA::deserialize(btdc); + std::tie(sender, data) = PATH::DATA::deserialize(oxenc::bt_dict_consumer{payload}); if (auto session = _router.session_endpoint()->get_session(sender)) { @@ -1560,13 +1557,11 @@ namespace llarp } catch (const std::exception& e) { - log::warning(logcat, "Exception: {}: {}", e.what(), buffer_printer{data}); + log::warning(logcat, "Exception: {}: {}", e.what(), buffer_printer{payload}); } return; } - log::debug(logcat, "Received path data for local relay: {}", buffer_printer{payload}); - auto hop = _router.path_context()->get_transit_hop(hop_id); if (not hop) @@ -1587,12 +1582,16 @@ namespace llarp std::optional> next_ids = std::nullopt; std::string next_payload; + log::debug( + logcat, + "We are {} hop for path data: {}: {}", + hop->terminal_hop ? "terminal" : "intermediate", + hop->to_string(), + buffer_printer{payload}); + // if terminal hop, pass to the correct path expecting to receive this message if (hop->terminal_hop) { - log::debug( - logcat, "We are terminal hop for path data: {}: {}", hop->to_string(), buffer_printer{payload}); - HopID ihid; std::string intermediate; @@ -1618,7 +1617,7 @@ namespace llarp return; } - log::debug(logcat, "Bridging path data message on hop: {}", next_hop->to_string()); + log::debug(logcat, "Bridging path data message to hop: {}", next_hop->to_string()); next_ids = next_hop->next_id(ihid); diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index 69d5bac675..ddda730de8 100644 --- a/llarp/messages/path.hpp +++ b/llarp/messages/path.hpp @@ -287,7 +287,7 @@ namespace llarp return std::move(btdp).str(); } - inline static std::tuple deserialize(oxenc::bt_dict_consumer& btdc) + inline static std::tuple deserialize(oxenc::bt_dict_consumer&& btdc) { RouterID remote; bstring payload; diff --git a/llarp/net/net.hpp b/llarp/net/net.hpp index dea007acb7..4a6bdee6dc 100644 --- a/llarp/net/net.hpp +++ b/llarp/net/net.hpp @@ -42,12 +42,9 @@ namespace llarp namespace net { - /// info about a network interface lokinet does not own struct InterfaceInfo { - private: - public: // TODO: is this needed? /// a gateway we can use if it exists std::optional _gateway; diff --git a/llarp/net/posix.cpp b/llarp/net/posix.cpp index 0e341e1931..9bbcc65e19 100644 --- a/llarp/net/posix.cpp +++ b/llarp/net/posix.cpp @@ -92,7 +92,7 @@ namespace llarp::net oxen::quic::Address addr{i->ifa_addr}; auto nma = reinterpret_cast(i->ifa_netmask)->sin_addr.s_addr; auto m = std::popcount(nma); - log::trace( + log::debug( logcat, "Adding {} {} (mask={}) to current ranges", addr.is_ipv4() ? "ipv4" : "ipv6", addr, m); current_ranges.emplace_back(std::move(addr), std::move(m)); } diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 436c3b16d9..00bcfa257c 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -551,12 +551,12 @@ namespace llarp // TODO: load strict-connects as bootstraps as well - log::info(logcat, "Local client configured to strictly use {} edge relays", n_edges); + log::debug(logcat, "Local client configured to strictly use {} edge relays", n_edges); if (min_client_outbounds > n_edges) { min_client_outbounds = n_edges; - log::info( + log::debug( logcat, "Local client holds only {} strict-connect edge relays; adjusting minimum router connections " "commensurately", @@ -564,7 +564,7 @@ namespace llarp } } else - log::info( + log::debug( logcat, "Local client configured to maintain {} router connections at minimum", min_client_outbounds); if (not min_client_outbounds) diff --git a/llarp/session/session.cpp b/llarp/session/session.cpp index 02d6b1864d..91ab487dee 100644 --- a/llarp/session/session.cpp +++ b/llarp/session/session.cpp @@ -29,8 +29,7 @@ namespace llarp::session _tag{std::move(_t)}, _remote{std::move(remote)}, _use_tun{use_tun}, - _is_outbound{is_outbound}, - _is_exit_session{kx_data.has_value()} + _is_outbound{is_outbound} { if (kx_data.has_value()) session_keys = std::move(*kx_data); @@ -48,7 +47,6 @@ namespace llarp::session bool BaseSession::send_path_data_message(std::string data) { - // session_keys.encrypt(to_uspan(data)); auto inner_payload = PATH::DATA::serialize(std::move(data), _r.local_rid()); auto intermediate_payload = PATH::DATA::serialize_intermediate(std::move(inner_payload), remote_intro.pivot_txid); diff --git a/llarp/vpn/linux.hpp b/llarp/vpn/linux.hpp index ca209bdddd..1feb8904ae 100644 --- a/llarp/vpn/linux.hpp +++ b/llarp/vpn/linux.hpp @@ -84,7 +84,7 @@ namespace llarp::vpn control.ioctl(SIOCSIFADDR, &ifr); auto subnet_mask = (ipv4_subnet / range.mask()).base; - log::trace(logcat, "IP Range:{}, subnet mask: {}", range, subnet_mask); + log::debug(logcat, "IP Range:{}, subnet mask: {}", range, subnet_mask); ((sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr = oxenc::load_host_to_big(&subnet_mask.addr); diff --git a/llarp/vpn/packet_router.cpp b/llarp/vpn/packet_router.cpp index 4c99e6e08b..b34ba55f13 100644 --- a/llarp/vpn/packet_router.cpp +++ b/llarp/vpn/packet_router.cpp @@ -20,7 +20,7 @@ namespace llarp::vpn void handle_ip_packet(IPPacket pkt) override { - log::debug(logcat, "inbound pkt: ", pkt.info_line()); + log::debug(logcat, "udp pkt: ", pkt.info_line()); auto dstport = pkt.dest_port(); if (not dstport) @@ -45,7 +45,7 @@ namespace llarp::vpn void handle_ip_packet(IPPacket pkt) override { - log::debug(logcat, "inbound pkt: {}", pkt.info_line()); + log::debug(logcat, "l4 pkt: {}", pkt.info_line()); // TOFIX: // _base_handler(IPPacket::from_udp(std::move(pkt))); } @@ -55,7 +55,7 @@ namespace llarp::vpn void PacketRouter::handle_ip_packet(IPPacket pkt) { - log::debug(logcat, "inbound pkt: {}", pkt.info_line()); + log::debug(logcat, "ip pkt: {}", pkt.info_line()); auto dest_port = pkt.dest_port(); if (not dest_port) From 73c06dec1c07e54eda48fbe0c139bee7cda39425 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Wed, 11 Dec 2024 07:28:13 -0800 Subject: [PATCH 37/44] libquic bump for ip range/net types --- external/oxen-libquic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/oxen-libquic b/external/oxen-libquic index 59796bdfe3..a23573d6cf 160000 --- a/external/oxen-libquic +++ b/external/oxen-libquic @@ -1 +1 @@ -Subproject commit 59796bdfe3c428643d69159b00e5f8140624b246 +Subproject commit a23573d6cf37f1021debbfeaf0db0cac44e89c4e From b1711f3e8bc3c7bd2c26dcd16737b4c42430cf8e Mon Sep 17 00:00:00 2001 From: dr7ana Date: Fri, 13 Dec 2024 10:47:09 -0800 Subject: [PATCH 38/44] squash --- llarp/address/ip_range.cpp | 38 +++-- llarp/address/ip_range.hpp | 58 +++++--- llarp/address/types.hpp | 10 +- llarp/address/utils.hpp | 8 +- llarp/config/config.hpp | 1 + llarp/ev/types.cpp | 14 +- llarp/ev/types.hpp | 4 +- llarp/handlers/session.cpp | 20 ++- llarp/handlers/session.hpp | 1 + llarp/handlers/tun.cpp | 10 +- llarp/handlers/tun.hpp | 2 +- llarp/link/link_manager.cpp | 25 ++-- llarp/messages/session.hpp | 23 +-- llarp/net/net.hpp | 7 +- llarp/net/traffic_policy.cpp | 1 + llarp/net/uint128.hpp | 269 ----------------------------------- llarp/nodedb.cpp | 12 +- llarp/path/path.cpp | 2 +- llarp/path/path_handler.cpp | 4 +- llarp/router/route_poker.cpp | 42 +++--- llarp/router/route_poker.hpp | 12 +- llarp/router/router.cpp | 2 + llarp/session/session.cpp | 20 +-- llarp/session/session.hpp | 12 +- llarp/vpn/linux.hpp | 67 +++++---- llarp/vpn/platform.hpp | 2 +- 26 files changed, 232 insertions(+), 434 deletions(-) delete mode 100644 llarp/net/uint128.hpp diff --git a/llarp/address/ip_range.cpp b/llarp/address/ip_range.cpp index 5ae5d47e53..0dd9506bb7 100644 --- a/llarp/address/ip_range.cpp +++ b/llarp/address/ip_range.cpp @@ -8,15 +8,15 @@ namespace llarp { if (_is_ipv4) { - _base_ip = _addr.to_ipv4().to_base(_mask); - _ip_range = ipv4_range{std::get(_base_ip), _mask}; - _max_ip = std::get(_ip_range).max_ip(); + _ip_net = _addr.to_ipv4() % _mask; + _base_ip = _ipv4_range().ip; + _max_ip = _ipv4_net().max_ip(); } else { - _base_ip = _addr.to_ipv6().to_base(_mask); - _ip_range = ipv6_range{std::get(_base_ip), _mask}; - _max_ip = std::get(_ip_range).max_ip(); + _ip_net = _addr.to_ipv6() % _mask; + _base_ip = _ipv6_range().ip; + _max_ip = _ipv6_net().max_ip(); } } @@ -82,16 +82,34 @@ namespace llarp return is_ipv4() ? _contains(std::get(other)) : _contains(std::get(other)); } + bool IPRange::contains(const ip_net_v& other) const + { + if (is_ipv4() ^ std::holds_alternative(other)) + return false; + + return is_ipv4() ? _contains(std::get(other).to_range().ip) + : _contains(std::get(other).to_range().ip); + } + + ip_v IPRange::net_ip() const + { + if (is_ipv4()) + return _ipv4_net().ip; + return _ipv6_net().ip; + } + std::optional IPRange::find_private_range(const std::list& excluding, bool ipv6_enabled) { if (excluding.empty()) return std::nullopt; - auto filter = [&excluding](const ip_range_v& range) -> bool { + auto filter = [&excluding](const ip_net_v& range) -> bool { for (const auto& e : excluding) - if (e == range) + { + if (e.contains(range)) return false; - log::debug(logcat, "{}", std::get(range).base); + } + log::trace(logcat, "{}", std::get(range).ip); return true; }; @@ -110,7 +128,7 @@ namespace llarp { for (size_t n = 0; n < num_ipv6_private; ++n) { - if (auto v6 = ipv6(0xfd2e, 0x6c6f, 0x6b69, n, 0x0000, 0x0000, 0x0000, 0x0001) / 64; filter(v6)) + if (auto v6 = ipv6(0xfd2e, 0x6c6f, 0x6b69, n, 0x0000, 0x0000, 0x0000, 0x0001) % 64; filter(v6)) return v6; } } diff --git a/llarp/address/ip_range.hpp b/llarp/address/ip_range.hpp index 101b01545c..fa3162f53e 100644 --- a/llarp/address/ip_range.hpp +++ b/llarp/address/ip_range.hpp @@ -14,12 +14,13 @@ namespace llarp struct IPRange { private: + ip_net_v _ip_net; + oxen::quic::Address _addr; uint8_t _mask; bool _is_ipv4; ip_v _base_ip; - ip_range_v _ip_range; ip_v _max_ip; void _init_ip(); @@ -29,10 +30,13 @@ namespace llarp bool _contains(const ipv6& other) const; // getters to DRY out variant access - ipv4_range& _ipv4_range() { return std::get(_ip_range); } - const ipv4_range& _ipv4_range() const { return std::get(_ip_range); } - ipv6_range& _ipv6_range() { return std::get(_ip_range); } - const ipv6_range& _ipv6_range() const { return std::get(_ip_range); } + ipv4_net& _ipv4_net() { return std::get(_ip_net); } + const ipv4_net& _ipv4_net() const { return std::get(_ip_net); } + ipv4_range _ipv4_range() const { return _ipv4_net().to_range(); } + + ipv6_net& _ipv6_net() { return std::get(_ip_net); } + const ipv6_net& _ipv6_net() const { return std::get(_ip_net); } + ipv6_range _ipv6_range() const { return _ipv6_net().to_range(); } public: IPRange() : IPRange{oxen::quic::Address{}, 0} {} @@ -44,21 +48,21 @@ namespace llarp _init_ip(); } - IPRange(const ipv4_range& ipv4) - : _addr{ipv4.base}, - _mask{ipv4.mask}, + IPRange(const ipv4_net& ipv4) + : _ip_net{ipv4}, + _addr{_ipv4_net().ip}, + _mask{_ipv4_net().mask}, _is_ipv4{true}, - _base_ip{ipv4.base}, - _ip_range{ipv4}, - _max_ip{ipv4.max_ip()} + _base_ip{_ipv4_range().ip}, + _max_ip{_ipv4_net().max_ip()} {} - IPRange(const ipv6_range& ipv6) - : _addr{ipv6.base}, + IPRange(const ipv6_net& ipv6) + : _ip_net{ipv6}, + _addr{ipv6.ip}, _mask{ipv6.mask}, _is_ipv4{false}, - _base_ip{ipv6.base}, - _ip_range{ipv6}, + _base_ip{ipv6.ip.to_base(_mask)}, _max_ip{ipv6.max_ip()} {} @@ -67,16 +71,19 @@ namespace llarp void bt_encode(oxenc::bt_list_producer& btlp) const { btlp.append(to_string()); } - std::string to_string() const { return is_ipv4() ? _ipv4_range().to_string() : _ipv6_range().to_string(); } + std::string to_string() const { return is_ipv4() ? _ipv4_net().to_string() : _ipv6_net().to_string(); } static std::optional from_string(std::string arg); bool contains(const IPRange& other) const; bool contains(const ip_v& other) const; + bool contains(const ip_net_v& other) const; bool is_ipv4() const { return _is_ipv4; } - ip_range_v get_ip_range() const { return _ip_range; } + ip_net_v get_ip_net() const { return _ip_net; } + + ip_v net_ip() const; ip_v base_ip() const { return _base_ip; } @@ -85,6 +92,11 @@ namespace llarp const uint8_t& mask() const { return _mask; } uint8_t mask() { return _mask; } + oxen::quic::Address base_address() const + { + return is_ipv4() ? oxen::quic::Address{_ipv4_range().ip} : oxen::quic::Address{_ipv6_range().ip}; + } + const oxen::quic::Address& address() const { return _addr; } oxen::quic::Address address() { return _addr; } @@ -98,12 +110,12 @@ namespace llarp return std::tie(_addr, _mask) == std::tie(other._addr, other._mask); } - bool operator==(const ip_range_v& other) const + bool operator==(const ip_net_v& other) const { - if (_is_ipv4 and std::holds_alternative(other)) - return _ipv4_range() == std::get(other); - if (not _is_ipv4 and std::holds_alternative(other)) - return _ipv6_range() == std::get(other); + if (_is_ipv4 and std::holds_alternative(other)) + return _ipv4_net() == std::get(other); + if (not _is_ipv4 and std::holds_alternative(other)) + return _ipv6_net() == std::get(other); return false; } @@ -165,7 +177,7 @@ namespace llarp IPRangeIterator() = default; IPRangeIterator(const IPRange& range) - : _ip_range{range}, _is_ipv4{range.is_ipv4()}, _current_ip{range.base_ip()}, _max_ip{range.max_ip()} + : _ip_range{range}, _is_ipv4{range.is_ipv4()}, _current_ip{range.net_ip()}, _max_ip{range.max_ip()} {} // Returns the next ip address in the iterating range; returns std::nullopt if range is exhausted diff --git a/llarp/address/types.hpp b/llarp/address/types.hpp index 3120423559..e7469084e2 100644 --- a/llarp/address/types.hpp +++ b/llarp/address/types.hpp @@ -9,9 +9,11 @@ namespace llarp using ipv4 = oxen::quic::ipv4; using ipv6 = oxen::quic::ipv6; using ip_v = std::variant; - using ipv4_range = oxen::quic::ipv4_net; - using ipv6_range = oxen::quic::ipv6_net; - using ip_range_v = std::variant; + using ipv4_range = oxen::quic::ipv4_range; + using ipv6_range = oxen::quic::ipv6_range; + using ipv4_net = oxen::quic::ipv4_net; + using ipv6_net = oxen::quic::ipv6_net; + using ip_net_v = std::variant; namespace concepts { @@ -19,7 +21,7 @@ namespace llarp concept IPType = std::is_same_v || std::is_same_v; template - concept IPRangeType = std::is_same_v || std::is_same_v; + concept IPRangeType = std::is_same_v || std::is_same_v; } // namespace concepts using KeyedAddress = oxen::quic::RemoteAddress; diff --git a/llarp/address/utils.hpp b/llarp/address/utils.hpp index df5c2f995a..62f9af20c4 100644 --- a/llarp/address/utils.hpp +++ b/llarp/address/utils.hpp @@ -108,15 +108,15 @@ namespace llarp inline constexpr size_t num_ipv4_private{272}; - inline constexpr std::array generate_private_ipv4() + inline constexpr std::array generate_private_ipv4() { - std::array ret{}; + std::array ret{}; for (size_t n = 16; n < 32; ++n) - ret[n - 16] = ipv4(172, n, 0, 1) / 16; + ret[n - 16] = ipv4(172, n, 0, 1) % 16; for (size_t n = 0; n < 256; ++n) - ret[n + 16] = ipv4(10, n, 0, 1) / 16; + ret[n + 16] = ipv4(10, n, 0, 1) % 16; return ret; } diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index f18953e382..485d16c446 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -191,6 +191,7 @@ namespace llarp // Used when in exit mode; pass down to LocalEndpoint // std::set _routed_ranges; // moved into traffic_policy! + // TESTNET: move into ExitConfig! bool enable_route_poker; bool blackhole_routes; diff --git a/llarp/ev/types.cpp b/llarp/ev/types.cpp index af5ff1be02..cd3b807115 100644 --- a/llarp/ev/types.cpp +++ b/llarp/ev/types.cpp @@ -92,7 +92,7 @@ namespace llarp } log::info(logcat, "EventTrigger resuming callback iteration..."); - self->begin(); + self->start(); } catch (const std::exception& e) { @@ -103,7 +103,7 @@ namespace llarp if (start_immediately) { - auto rv = begin(); + auto rv = start(); log::debug(logcat, "EventTrigger started {}successfully!", rv ? "" : "un"); } } @@ -134,7 +134,7 @@ namespace llarp event_add(ev.get(), &_null_tv); } - bool EventTrigger::halt() + bool EventTrigger::stop() { _is_cooling_down = false; _is_iterating = false; @@ -147,7 +147,7 @@ namespace llarp return ret; } - bool EventTrigger::begin() + bool EventTrigger::start() { _is_cooling_down = false; _is_iterating = true; @@ -197,20 +197,20 @@ namespace llarp }, this)); - log::debug(logcat, "Linux poller configured to watch FD: {}", fd); + log::debug(logcat, "Linux poller configured to watch FD {}", fd); } bool LinuxPoller::start() { auto rv = event_add(ev.get(), nullptr) == 0; - log::info(logcat, "Linux poller {} watching FD: {}", rv ? "successfully began" : "failed to start", fd); + log::info(logcat, "Linux poller {} watching FD {}", rv ? "successfully began" : "failed to start", fd); return rv; } bool LinuxPoller::stop() { auto rv = event_del(ev.get()); - log::info(logcat, "Linux poller {} watching FD: {}", rv ? "successfully stopped" : "failed to stop", fd); + log::info(logcat, "Linux poller {} watching FD {}", rv ? "successfully stopped" : "failed to stop", fd); return rv; } } // namespace llarp diff --git a/llarp/ev/types.hpp b/llarp/ev/types.hpp index 6638a063ef..558678086b 100644 --- a/llarp/ev/types.hpp +++ b/llarp/ev/types.hpp @@ -62,10 +62,10 @@ namespace llarp ~EventTrigger(); // Resumes iterative execution after successfully cooling down or being signalled to stop by the callback - bool begin(); + bool start(); // Called by the passed callback to signal that the iterative invocation should STOP - bool halt(); + bool stop(); private: // Invokes the function `f`, incrementing `::current` up to `n` before cooling down diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index c3383527de..7699bf2538 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -162,7 +162,7 @@ namespace llarp::handlers // _router.loop()->call_later(5s, [this]() { // try // { - // RouterID cpk{oxenc::from_base32z("mprqiu67f4gr8hb4zx8kuuqmxanmct4b6fp1nkeeruhxx9tqwc7y")}; + // RouterID cpk{oxenc::from_base32z("p3thqq8toyidz3ssos7tx6xhsje3zfdkmpdw43gtb8cz7a96yedo")}; // log::info(logcat, "Beginning session init to client: {}", cpk.to_network_address(false)); // _initiate_session( // NetworkAddress::from_pubkey(cpk, true), [](ip_v) { log::critical(logcat, "FUCK YEAH"); @@ -431,6 +431,7 @@ namespace llarp::handlers bool SessionEndpoint::prefigure_session( NetworkAddress initiator, SessionTag tag, + HopID remote_pivot_txid, std::shared_ptr path, shared_kx_data kx_data, bool use_tun) @@ -438,7 +439,13 @@ namespace llarp::handlers bool ret = true; auto inbound = std::make_shared( - initiator, std::move(path), *this, std::move(tag), use_tun, std::move(kx_data)); + initiator, + std::move(path), + *this, + std::move(remote_pivot_txid), + std::move(tag), + use_tun, + std::move(kx_data)); auto [session, _] = _sessions.insert_or_assign(std::move(initiator), std::move(inbound)); @@ -578,6 +585,7 @@ namespace llarp::handlers std::tie(inner_payload, kx_data) = InitiateSession::serialize_encrypt( _router.local_rid(), remote.router_id(), + path->pivot_txid(), tag, remote_intro.pivot_txid, fetch_auth_token(remote), @@ -599,9 +607,9 @@ namespace llarp::handlers remote, tag, path, + remote_pivot_txid = remote_intro.pivot_txid, hook = std::move(cb), - session_keys = std::move(kx_data), - remote_intro = std::move(remote_intro)](oxen::quic::message m) mutable { + session_keys = std::move(kx_data)](oxen::quic::message m) mutable { if (m) { log::critical(logcat, "Call to InitiateSession succeeded!"); @@ -610,9 +618,9 @@ namespace llarp::handlers remote, *this, std::move(path), + std::move(remote_pivot_txid), std::move(tag), - std::move(session_keys), - std::move(remote_intro)); + std::move(session_keys)); auto [session, _] = _sessions.insert_or_assign(std::move(remote), std::move(outbound)); diff --git a/llarp/handlers/session.hpp b/llarp/handlers/session.hpp index e70255c066..01d18c6225 100644 --- a/llarp/handlers/session.hpp +++ b/llarp/handlers/session.hpp @@ -124,6 +124,7 @@ namespace llarp bool prefigure_session( NetworkAddress initiator, SessionTag tag, + HopID remote_pivot_txid, std::shared_ptr path, shared_kx_data kx_data, bool use_tun); diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 93b4d4c3fa..48b92f6a2b 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -286,7 +286,7 @@ namespace llarp::handlers void TunEndpoint::configure() { return _router.loop()->call_get([&]() { - log::debug(logcat, "{} called", __PRETTY_FUNCTION__); + log::trace(logcat, "{} called", __PRETTY_FUNCTION__); auto& net_conf = _router.config()->network; @@ -329,7 +329,7 @@ namespace llarp::handlers _local_range_iterator = IPRangeIterator(_local_range); _local_netaddr = NetworkAddress::from_pubkey(_router.local_rid(), not _router.is_service_node()); - _local_ip_mapping.insert_or_assign(_local_base_ip, std::move(_local_netaddr)); + _local_ip_mapping.insert_or_assign(_local_range.net_ip(), std::move(_local_netaddr)); vpn::InterfaceInfo info; info.ifname = _if_name; @@ -365,7 +365,7 @@ namespace llarp::handlers log::info(logcat, "{} got network interface:{}", name(), _if_name); - auto pkt_hook = [this]() { + auto pkt_hook = [this]() mutable { for (auto pkt = _net_if->read_next_packet(); not pkt.empty(); pkt = _net_if->read_next_packet()) { log::trace(logcat, "packet router receiving {}", pkt.info_line()); @@ -1034,9 +1034,9 @@ namespace llarp::handlers return std::nullopt; } - void TunEndpoint::send_packet_to_net_if(IPPacket&& pkt) + void TunEndpoint::send_packet_to_net_if(IPPacket pkt) { - _router.loop()->call([this, pkt = std::move(pkt)]() { _net_if->write_packet(std::move(pkt)); }); + _router.loop()->call([this, pkt = std::move(pkt)]() mutable { _net_if->write_packet(std::move(pkt)); }); } void TunEndpoint::rewrite_and_send_packet(IPPacket&& pkt, ip_v src, ip_v dest) diff --git a/llarp/handlers/tun.hpp b/llarp/handlers/tun.hpp index a0952ee1fd..f86676aa45 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -164,7 +164,7 @@ namespace llarp::handlers std::optional obtain_src_for_remote(const NetworkAddress& remote, bool use_ipv4); - void send_packet_to_net_if(IPPacket&& pkt); + void send_packet_to_net_if(IPPacket pkt); }; } // namespace llarp::handlers diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index a79f86e965..4be414e10a 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1582,7 +1582,7 @@ namespace llarp std::optional> next_ids = std::nullopt; std::string next_payload; - log::debug( + log::trace( logcat, "We are {} hop for path data: {}: {}", hop->terminal_hop ? "terminal" : "intermediate", @@ -1607,7 +1607,7 @@ namespace llarp return; } - log::debug(logcat, "Inbound path rxid:{}, outbound path txid:{}", hop_id, ihid); + log::trace(logcat, "Inbound path rxid:{}, outbound path txid:{}", hop_id, ihid); auto next_hop = _router.path_context()->get_transit_hop(ihid); @@ -1617,7 +1617,7 @@ namespace llarp return; } - log::debug(logcat, "Bridging path data message to hop: {}", next_hop->to_string()); + log::trace(logcat, "Bridging path data message to hop: {}", next_hop->to_string()); next_ids = next_hop->next_id(ihid); @@ -1692,7 +1692,8 @@ namespace llarp NetworkAddress initiator; SessionTag tag; - HopID pivot_txid; + HopID remote_pivot_txid; + HopID local_pivot_txid; bool use_tun; shared_kx_data kx_data; std::optional maybe_auth = std::nullopt; @@ -1701,10 +1702,10 @@ namespace llarp try { if (inner_body) - std::tie(kx_data, initiator, pivot_txid, tag, use_tun, maybe_auth) = + std::tie(kx_data, initiator, local_pivot_txid, tag, remote_pivot_txid, use_tun, maybe_auth) = InitiateSession::decrypt_deserialize(oxenc::bt_dict_consumer{*inner_body}, _router.identity()); else - std::tie(kx_data, initiator, pivot_txid, tag, use_tun, maybe_auth) = + std::tie(kx_data, initiator, local_pivot_txid, tag, remote_pivot_txid, use_tun, maybe_auth) = InitiateSession::decrypt_deserialize(oxenc::bt_dict_consumer{m.body()}, _router.identity()); if (maybe_auth and not _router.session_endpoint()->validate(initiator, maybe_auth)) @@ -1713,16 +1714,22 @@ namespace llarp return m.respond(InitiateSession::AUTH_ERROR, true); } - path_ptr = _router.path_context()->get_path(pivot_txid); + path_ptr = _router.path_context()->get_path(local_pivot_txid); if (not path_ptr) { - log::warning(logcat, "Failed to find local path for new inbound session over pivot: {}", pivot_txid); + log::warning( + logcat, "Failed to find local path for new inbound session over pivot: {}", local_pivot_txid); return m.respond(InitiateSession::BAD_PATH, true); } if (_router.session_endpoint()->prefigure_session( - std::move(initiator), std::move(tag), std::move(path_ptr), std::move(kx_data), use_tun)) + std::move(initiator), + std::move(tag), + std::move(remote_pivot_txid), + std::move(path_ptr), + std::move(kx_data), + use_tun)) { log::critical(logcat, "InboundSession configured successfully!"); return m.respond(messages::OK_RESPONSE); diff --git a/llarp/messages/session.hpp b/llarp/messages/session.hpp index 9e72c681f2..83b8351cce 100644 --- a/llarp/messages/session.hpp +++ b/llarp/messages/session.hpp @@ -13,7 +13,8 @@ namespace llarp - 'n' : symmetric nonce - 'x' : encrypted payload - 'i' : RouterID of initiator - - 'p' : HopID at the pivot taken from remote ClientIntro + - 'p' : HopID at the pivot taken from local ClientIntro + - 'r' : HopID at the pivot taken from remote's ClientIntro - 's' : SessionTag for current session - 't' : Use Tun interface (bool) - 'u' : Authentication field @@ -29,8 +30,9 @@ namespace llarp inline static std::tuple serialize_encrypt( const RouterID& local, const RouterID& remote, + HopID local_pivot_txid, SessionTag& tag, - HopID pivot_txid, + HopID remote_pivot_txid, std::optional auth_token, bool use_tun) { @@ -42,7 +44,8 @@ namespace llarp oxenc::bt_dict_producer btdp; btdp.append("i", local.to_view()); - btdp.append("p", pivot_txid.to_view()); + btdp.append("p", local_pivot_txid.to_view()); + btdp.append("r", remote_pivot_txid.to_view()); btdp.append("s", tag.to_view()); btdp.append("t", use_tun); // TOTHINK: this auth field @@ -69,8 +72,9 @@ namespace llarp } }; - inline static std::tuple> - decrypt_deserialize(oxenc::bt_dict_consumer&& outer_btdc, const Ed25519SecretKey& local) + inline static std:: + tuple> + decrypt_deserialize(oxenc::bt_dict_consumer&& outer_btdc, const Ed25519SecretKey& local) { SymmNonce nonce; PubKey shared_pubkey; @@ -95,13 +99,15 @@ namespace llarp NetworkAddress initiator; RouterID init_rid; SessionTag tag; - HopID pivot_txid; + HopID remote_pivot_txid; + HopID local_pivot_txid; bool use_tun; std::optional maybe_auth = std::nullopt; init_rid.from_string(btdc.require("i")); initiator = NetworkAddress::from_pubkey(init_rid, true); - pivot_txid.from_string(btdc.require("p")); + remote_pivot_txid.from_string(btdc.require("p")); + local_pivot_txid.from_string(btdc.require("r")); tag.from_string(btdc.require("s")); use_tun = btdc.require("t"); maybe_auth = btdc.maybe("u"); @@ -109,8 +115,9 @@ namespace llarp return { std::move(kx_data), std::move(initiator), - std::move(pivot_txid), + std::move(local_pivot_txid), std::move(tag), + std::move(remote_pivot_txid), use_tun, std::move(maybe_auth)}; } diff --git a/llarp/net/net.hpp b/llarp/net/net.hpp index 4a6bdee6dc..8e6156c88a 100644 --- a/llarp/net/net.hpp +++ b/llarp/net/net.hpp @@ -1,7 +1,6 @@ #pragma once #include "net.h" -#include "uint128.hpp" #include #include @@ -47,7 +46,7 @@ namespace llarp { // TODO: is this needed? /// a gateway we can use if it exists - std::optional _gateway; + std::optional _gateway; /// human readable name of interface std::string name; @@ -70,9 +69,9 @@ namespace llarp std::optional if_name = std::nullopt; std::optional if_addr = std::nullopt; std::optional if_netmask = std::nullopt; - std::optional if_index = std::nullopt; + std::optional if_index = std::nullopt; - operator bool() const { return if_name and if_addr /* and if_netmask */ and if_index; } + operator bool() const { return if_name and if_addr; } }; /// network platform (all methods virtual so it can be mocked by unit tests) diff --git a/llarp/net/traffic_policy.cpp b/llarp/net/traffic_policy.cpp index cd84f89722..5cbd8b8083 100644 --- a/llarp/net/traffic_policy.cpp +++ b/llarp/net/traffic_policy.cpp @@ -69,6 +69,7 @@ namespace llarp::net bool ExitPolicy::allow_ip_traffic(const IPPacket& pkt) { + log::debug(logcat, "{} called", __PRETTY_FUNCTION__); if (protocols.empty() and ranges.empty()) return true; diff --git a/llarp/net/uint128.hpp b/llarp/net/uint128.hpp deleted file mode 100644 index 7c94aa0cc4..0000000000 --- a/llarp/net/uint128.hpp +++ /dev/null @@ -1,269 +0,0 @@ -#pragma once -#include - -#include -#include -#include -#include - -namespace llarp -{ - /// 128-bit unsigned integer. Does *not* support - /// multiplication/division/modulus. - struct uint128_t - { - // Swap order on little/big endian so that the first byte of the struct is - // always most significant on big endian and least significant on little - // endian. -#ifdef __BIG_ENDIAN__ - uint64_t upper, lower; -#else - uint64_t lower, upper; -#endif - - // Initializes with 0s - constexpr uint128_t() : uint128_t{0, 0} {} - - // Initializes with least-significant value - constexpr uint128_t(uint64_t lower) : uint128_t{0, lower} {} - - // Initializes with upper and lower values - constexpr uint128_t(uint64_t upper, uint64_t lower) - // clang-format off -#ifdef __BIG_ENDIAN__ - : upper{upper}, lower{lower} -#else - : lower{lower}, upper{upper} -#endif - // clang-format on - {} - - constexpr uint128_t(const uint128_t&) = default; - constexpr uint128_t(uint128_t&&) = default; - constexpr uint128_t& operator=(const uint128_t&) = default; - constexpr uint128_t& operator=(uint128_t&&) = default; - - // bitwise and - constexpr uint128_t& operator&=(const uint128_t& o) - { - upper &= o.upper; - lower &= o.lower; - return *this; - } - constexpr uint128_t operator&(const uint128_t& o) const - { - uint128_t result = *this; - result &= o; - return result; - } - - // bitwise or - constexpr uint128_t& operator|=(const uint128_t& o) - { - upper |= o.upper; - lower |= o.lower; - return *this; - } - constexpr uint128_t operator|(const uint128_t& o) const - { - uint128_t result = *this; - result |= o; - return result; - } - - // bitwise xor - constexpr uint128_t& operator^=(const uint128_t& o) - { - upper ^= o.upper; - lower ^= o.lower; - return *this; - } - constexpr uint128_t operator^(const uint128_t& o) const - { - uint128_t result = *this; - result ^= o; - return result; - } - - // bitwise not - constexpr uint128_t operator~() const { return {~upper, ~lower}; } - - // bool: true if any bit set - explicit constexpr operator bool() const { return static_cast(lower) || static_cast(upper); } - - // Casting to basic unsigned int types: casts away upper bits - explicit constexpr operator uint8_t() const { return static_cast(lower); } - explicit constexpr operator uint16_t() const { return static_cast(lower); } - explicit constexpr operator uint32_t() const { return static_cast(lower); } - explicit constexpr operator uint64_t() const { return lower; } - - constexpr bool operator==(const uint128_t& b) const { return lower == b.lower && upper == b.upper; } - - constexpr bool operator!=(const uint128_t& b) const { return lower != b.lower || upper != b.upper; } - - constexpr bool operator<(const uint128_t& b) const - { - return std::tie(upper, lower) < std::tie(b.upper, b.lower); - } - - constexpr bool operator<=(const uint128_t& b) const - { - return std::tie(upper, lower) <= std::tie(b.upper, b.lower); - } - - constexpr bool operator>(const uint128_t& b) const - { - return std::tie(upper, lower) > std::tie(b.upper, b.lower); - } - - constexpr bool operator>=(const uint128_t& b) const - { - return std::tie(upper, lower) >= std::tie(b.upper, b.lower); - } - - constexpr uint128_t& operator++() - { - if (++lower == 0) - ++upper; - return *this; - } - - constexpr uint128_t operator++(int) - { - auto copy = *this; - ++*this; - return copy; - } - - constexpr uint128_t& operator+=(const uint128_t& b) - { - lower += b.lower; - if (lower < b.lower) - ++upper; - upper += b.upper; - return *this; - } - constexpr uint128_t operator+(const uint128_t& b) const - { - uint128_t result = *this; - result += b; - return result; - } - - constexpr uint128_t& operator-=(const uint128_t& b) - { - if (b.lower > lower) - --upper; - lower -= b.lower; - upper -= b.upper; - return *this; - } - constexpr uint128_t operator-(const uint128_t& b) const - { - uint128_t result = *this; - result -= b; - return result; - } - - constexpr uint128_t& operator<<=(uint64_t shift) - { - if (shift == 0) - { - } - else if (shift < 64) - { - upper = upper << shift | (lower >> (64 - shift)); - lower <<= shift; - } - else if (shift == 64) - { - upper = lower; - lower = 0; - } - else if (shift < 128) - { - upper = lower << (shift - 64); - lower = 0; - } - else - { - upper = lower = 0; - } - return *this; - } - constexpr uint128_t operator<<(uint64_t shift) const - { - uint128_t result = *this; - result <<= shift; - return result; - } - - constexpr uint128_t& operator>>=(uint64_t shift) - { - if (shift == 0) - { - } - else if (shift < 64) - { - lower = lower >> shift | upper << (64 - shift); - upper >>= shift; - } - else if (shift == 64) - { - lower = upper; - upper = 0; - } - else if (shift < 128) - { - lower = upper >> (shift - 64); - upper = 0; - } - else - { - upper = lower = 0; - } - return *this; - } - - constexpr uint128_t operator>>(uint64_t shift) const - { - uint128_t result = *this; - result >>= shift; - return result; - } - }; - - static_assert(sizeof(uint128_t) == 16, "uint128_t has unexpected size (padding?)"); - -} // namespace llarp - -namespace std -{ - // Hash function for uint128_t - template <> - struct hash - { - size_t operator()(const llarp::uint128_t& i) const - { - size_t h = std::hash()(i.lower); - h ^= std::hash()(i.upper) + 0x9e3779b9 + (h << 6) + (h >> 2); - return h; - } - }; -} // namespace std - -inline llarp::uint128_t ntoh128(llarp::uint128_t i) -{ -#ifdef __BIG_ENDIAN__ - return i; -#else - const auto loSwapped = oxenc::big_to_host(i.lower); - const auto hiSwapped = oxenc::big_to_host(i.upper); - return {/*upper=*/loSwapped, /*lower=*/hiSwapped}; -#endif -} - -inline llarp::uint128_t hton128(llarp::uint128_t i) -{ - return ntoh128(i); // Same bit flipping as n-to-h -} diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index fcadfa5053..7e922fca10 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -138,7 +138,7 @@ namespace llarp _is_service_node ? "Relay" : "Client", num_rcs(), MIN_ACTIVE_RCS); - _bootstrap_handler->begin(); + _bootstrap_handler->start(); } return false; @@ -149,6 +149,12 @@ namespace llarp void NodeDB::purge_rcs(std::chrono::milliseconds now) { + if (_router.is_stopping() || not _router.is_running()) + { + log::debug(logcat, "NodeDB unable to continue NodeDB purge -- router is stopped!"); + return; + } + remove_if([&](const RemoteRC& rc) -> bool { // don't purge bootstrap nodes from nodedb if (is_bootstrap_node(rc)) @@ -630,7 +636,7 @@ namespace llarp _is_bootstrapping = false; // this function is only called in success or lokinet shutdown, so we will never need bootstrapping _needs_bootstrap = false; - _bootstrap_handler->halt(); + _bootstrap_handler->stop(); if (success) { @@ -878,7 +884,7 @@ namespace llarp if (_bootstrap_handler) { log::debug(logcat, "NodeDB clearing bootstrap handler..."); - _bootstrap_handler->halt(); + _bootstrap_handler->stop(); _bootstrap_handler.reset(); } diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index ec310cdfca..64709f922a 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -83,7 +83,7 @@ namespace llarp::path intro.pivot_txid = hops.back()._txid; log::debug( - logcat, "Path client intro holding pivot_rid ({}) and pivot_rxid ({})", intro.pivot_rid, intro.pivot_txid); + logcat, "Path client intro holding pivot_rid ({}) and pivot_txid ({})", intro.pivot_rid, intro.pivot_txid); } void Path::link_session(recv_session_dgram_cb cb) diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index 2294ac4933..5eed77defa 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -505,7 +505,7 @@ namespace llarp::path // make a copy here to reference rather than creating one in the lambda every iteration std::set to_exclude{exclude.begin(), exclude.end()}; to_exclude.insert(pivot); - std::vector excluded_ranges{}; + std::vector excluded_ranges{}; // excluded_ranges.emplace_back(pivot_rc.addr().to_ipv4() / netmask); if (auto maybe = select_first_hop(to_exclude)) @@ -536,7 +536,7 @@ namespace llarp::path if (not to_exclude.insert(rid).second) return false; - excluded_ranges.emplace_back(v4 / netmask); + excluded_ranges.emplace_back(v4 % netmask); if (_router.router_profiling().is_bad_for_path(rid, 1)) return false; diff --git a/llarp/router/route_poker.cpp b/llarp/router/route_poker.cpp index 1701a3003c..1bc7162313 100644 --- a/llarp/router/route_poker.cpp +++ b/llarp/router/route_poker.cpp @@ -8,9 +8,11 @@ namespace llarp { static auto logcat = log::Cat("route_poker"); + RoutePoker::RoutePoker(Router& r) : _router{r} {} + void RoutePoker::add_route(oxen::quic::Address ip) { - if (not is_up) + if (not _is_up) return; bool has_existing = poked_routes.count(ip); @@ -38,7 +40,7 @@ namespace llarp { if (ip.is_set() and gateway.is_set() and is_enabled()) { - vpn::AbstractRouteManager& route = router.vpn_platform()->RouteManager(); + vpn::AbstractRouteManager& route = _router.vpn_platform()->RouteManager(); route.delete_route(ip, gateway); } } @@ -47,7 +49,7 @@ namespace llarp { if (ip.is_set() and gateway.is_set() and is_enabled()) { - vpn::AbstractRouteManager& route = router.vpn_platform()->RouteManager(); + vpn::AbstractRouteManager& route = _router.vpn_platform()->RouteManager(); route.add_route(ip, gateway); } } @@ -65,7 +67,10 @@ namespace llarp void RoutePoker::start() { if (not is_enabled()) + { + log::info(logcat, "Route poker is NOT enabled for this lokinet instance!"); return; + } // router.loop()->call_every(100ms, weak_from_this(), [self = weak_from_this()]() { // if (auto ptr = self.lock()) @@ -96,10 +101,10 @@ namespace llarp RoutePoker::~RoutePoker() { - if (not router.vpn_platform()) + if (not _router.vpn_platform()) return; - auto& route = router.vpn_platform()->RouteManager(); + auto& route = _router.vpn_platform()->RouteManager(); for (const auto& [ip, gateway] : poked_routes) { if (gateway.is_set() and ip.is_set()) @@ -108,16 +113,6 @@ namespace llarp route.delete_blackhole(); } - bool RoutePoker::is_enabled() const - { - if (router.is_service_node()) - return false; - if (const auto& conf = router.config()) - return conf->network.enable_route_poker; - - throw std::runtime_error{"Attempting to use RoutePoker with router with no config set"}; - } - void RoutePoker::update() { // // ensure we have an endpoint @@ -173,8 +168,9 @@ namespace llarp void RoutePoker::put_up() { - bool was_up = is_up; - is_up = true; + bool was_up = _is_up; + _is_up = true; + if (not was_up) { if (not is_enabled()) @@ -189,17 +185,17 @@ namespace llarp { log::info(logcat, "RoutePoker coming up; poking routes"); - vpn::AbstractRouteManager& route = router.vpn_platform()->RouteManager(); + vpn::AbstractRouteManager& route = _router.vpn_platform()->RouteManager(); // black hole all routes if enabled - if (router.config()->network.blackhole_routes) + if (_router.config()->network.blackhole_routes) route.add_blackhole(); // explicit route pokes for first hops - router.for_each_connection( + _router.for_each_connection( [this](const RouterID&, link::Connection& conn) { add_route(conn.conn->remote()); }); - add_route(router.link_manager()->local()); + add_route(_router.link_manager()->local()); // add default route // const auto ep = router.hidden_service_context().GetDefault(); // if (auto* vpn = ep->GetVPNInterface()) @@ -214,9 +210,9 @@ namespace llarp void RoutePoker::put_down() { // unpoke routes for first hops - router.for_each_connection( + _router.for_each_connection( [this](const RouterID&, link::Connection& conn) { delete_route(conn.conn->remote()); }); - if (is_enabled() and is_up) + if (is_enabled() and _is_up) { // vpn::AbstractRouteManager& route = router.vpn_platform()->RouteManager(); // const auto ep = router.hidden_service_context().GetDefault(); diff --git a/llarp/router/route_poker.hpp b/llarp/router/route_poker.hpp index f5ed1515dc..860b448396 100644 --- a/llarp/router/route_poker.hpp +++ b/llarp/router/route_poker.hpp @@ -13,7 +13,7 @@ namespace llarp struct RoutePoker : public std::enable_shared_from_this { - RoutePoker(Router& r) : router{r} {} + RoutePoker(Router& r); void add_route(oxen::quic::Address ip); @@ -33,11 +33,11 @@ namespace llarp /// pass in if we are using exit node mode right now as a bool void set_dns_mode(bool /// using_exit_mode) const; + bool is_enabled() const { return _is_enabled; } + private: void update(); - bool is_enabled() const; - void delete_all_routes(); void disable_all_routes(); @@ -49,10 +49,10 @@ namespace llarp void disable_route(oxen::quic::Address ip, oxen::quic::Address gateway); std::unordered_map poked_routes; - std::optional current_gateway; - Router& router; - bool is_up{false}; + Router& _router; + bool _is_up{false}; + bool _is_enabled{false}; }; } // namespace llarp diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 00bcfa257c..809c601280 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -1016,6 +1016,8 @@ namespace llarp _loop_ticker = _loop->call_every( ROUTER_TICK_INTERVAL, [this] { tick(); }, false, true); + // _route_poker->start(); + _systemd_ticker = _loop->call_every( SERVICE_MANAGER_REPORT_INTERVAL, []() { sys::service_manager->report_periodic_stats(); }, false, true); diff --git a/llarp/session/session.cpp b/llarp/session/session.cpp index 91ab487dee..a72dfd883e 100644 --- a/llarp/session/session.cpp +++ b/llarp/session/session.cpp @@ -19,22 +19,21 @@ namespace llarp::session std::shared_ptr _p, handlers::SessionEndpoint& parent, NetworkAddress remote, + HopID remote_pivot_txid, SessionTag _t, bool use_tun, bool is_outbound, - std::optional kx_data, - std::optional _remote_intro) + std::optional kx_data) : _r{r}, _parent{parent}, _tag{std::move(_t)}, _remote{std::move(remote)}, + _remote_pivot_txid{std::move(remote_pivot_txid)}, _use_tun{use_tun}, _is_outbound{is_outbound} { if (kx_data.has_value()) session_keys = std::move(*kx_data); - if (_remote_intro.has_value()) - remote_intro = std::move(*_remote_intro); set_new_current_path(std::move(_p)); } @@ -48,8 +47,7 @@ namespace llarp::session bool BaseSession::send_path_data_message(std::string data) { auto inner_payload = PATH::DATA::serialize(std::move(data), _r.local_rid()); - auto intermediate_payload = - PATH::DATA::serialize_intermediate(std::move(inner_payload), remote_intro.pivot_txid); + auto intermediate_payload = PATH::DATA::serialize_intermediate(std::move(inner_payload), _remote_pivot_txid); return _r.send_data_message( _current_path->upstream_rid(), _current_path->make_path_message(std::move(intermediate_payload))); } @@ -163,20 +161,20 @@ namespace llarp::session NetworkAddress remote, handlers::SessionEndpoint& parent, std::shared_ptr path, + HopID remote_pivot_txid, SessionTag _t, - std::optional kx_data, - std::optional remote_intro) + std::optional kx_data) : PathHandler{parent._router, path::DEFAULT_PATHS_HELD}, BaseSession{ _router, std::move(path), parent, std::move(remote), + std::move(remote_pivot_txid), std::move(_t), _router.using_tun_if(), true, - std::move(kx_data), - std::move(remote_intro)}, + std::move(kx_data)}, _is_snode_session{not _remote.is_client()}, _last_use{_router.now()} { @@ -332,6 +330,7 @@ namespace llarp::session NetworkAddress remote, std::shared_ptr _path, handlers::SessionEndpoint& parent, + HopID remote_pivot_txid, SessionTag _t, bool use_tun, std::optional kx_data) @@ -340,6 +339,7 @@ namespace llarp::session std::move(_path), parent, std::move(remote), + std::move(remote_pivot_txid), std::move(_t), use_tun, false, diff --git a/llarp/session/session.hpp b/llarp/session/session.hpp index 71eac6c511..0a5f521130 100644 --- a/llarp/session/session.hpp +++ b/llarp/session/session.hpp @@ -49,7 +49,8 @@ namespace llarp shared_kx_data session_keys{}; - ClientIntro remote_intro; + // used for bridging data messages across aligned paths + HopID _remote_pivot_txid; bool _use_tun; bool _is_outbound; @@ -79,11 +80,11 @@ namespace llarp std::shared_ptr _p, handlers::SessionEndpoint& parent, NetworkAddress remote, + HopID remote_pivot_txid, SessionTag _t, bool use_tun, bool is_outbound, - std::optional kx_data = std::nullopt, - std::optional remote_intro = std::nullopt); + std::optional kx_data = std::nullopt); virtual ~BaseSession() = default; @@ -124,9 +125,9 @@ namespace llarp NetworkAddress _remote, handlers::SessionEndpoint& parent, std::shared_ptr path, + HopID remote_pivot_txid, SessionTag _t, - std::optional kx_data = std::nullopt, - std::optional remote_intro = std::nullopt); + std::optional kx_data = std::nullopt); ~OutboundSession() override; @@ -182,6 +183,7 @@ namespace llarp NetworkAddress _remote, std::shared_ptr _path, handlers::SessionEndpoint& parent, + HopID remote_pivot_txid, SessionTag _t, bool use_tun, std::optional kx_data = std::nullopt); diff --git a/llarp/vpn/linux.hpp b/llarp/vpn/linux.hpp index 1feb8904ae..f6103f095e 100644 --- a/llarp/vpn/linux.hpp +++ b/llarp/vpn/linux.hpp @@ -45,24 +45,25 @@ namespace llarp::vpn LinuxInterface(InterfaceInfo info) : NetworkInterface{std::move(info)}, _fd{::open("/dev/net/tun", O_RDWR)} { if (_fd == -1) - throw std::runtime_error("cannot open /dev/net/tun " + std::string{strerror(errno)}); + throw std::runtime_error("cannot open /dev/net/tun {}"_format(strerror(errno))); if (fcntl(_fd, F_SETFL, O_NONBLOCK) == -1) - throw std::runtime_error{"Failed to set Linux interface fd non-block!s"}; + throw std::runtime_error{"Failed to set `O_NONBLOCK` on Linux interface FD!"}; ifreq ifr{}; in6_ifreq ifr6{}; ifr.ifr_flags = IFF_TUN | IFF_NO_PI; - std::copy_n(_info.ifname.c_str(), std::min(_info.ifname.size(), sizeof(ifr.ifr_name)), ifr.ifr_name); + std::memcpy( + ifr.ifr_name, _info.ifname.c_str(), std::min(_info.ifname.size(), static_cast(IFNAMSIZ))); if (::ioctl(_fd, TUNSETIFF, &ifr) == -1) - throw std::runtime_error("cannot set interface name: " + std::string{strerror(errno)}); + throw std::runtime_error("cannot set interface name: {}"_format(strerror(errno))); IOCTL control{AF_INET}; control.ioctl(SIOCGIFFLAGS, &ifr); - const int flags = ifr.ifr_flags; + short int flags = ifr.ifr_flags; control.ioctl(SIOCGIFINDEX, &ifr); _info.index = ifr.ifr_ifindex; @@ -83,7 +84,7 @@ namespace llarp::vpn control.ioctl(SIOCSIFADDR, &ifr); - auto subnet_mask = (ipv4_subnet / range.mask()).base; + auto subnet_mask = (ipv4_subnet / range.mask()).ip; log::debug(logcat, "IP Range:{}, subnet mask: {}", range, subnet_mask); ((sockaddr_in*)&ifr.ifr_netmask)->sin_addr.s_addr = @@ -111,7 +112,7 @@ namespace llarp::vpn } } - ifr.ifr_flags = static_cast(flags | IFF_UP | IFF_NO_PI); + ifr.ifr_flags = static_cast(flags | IFF_UP); control.ioctl(SIOCSIFFLAGS, &ifr); } @@ -121,6 +122,7 @@ namespace llarp::vpn IPPacket read_next_packet() override { + log::trace(logcat, "{} called", __PRETTY_FUNCTION__); std::vector buf; buf.resize(MAX_PACKET_SIZE); const auto sz = read(_fd, buf.data(), buf.capacity()); @@ -135,13 +137,13 @@ namespace llarp::vpn } buf.resize(sz); - return IPPacket{std::move(buf)}; } bool write_packet(IPPacket pkt) override { const auto sz = write(_fd, pkt.data(), pkt.size()); + log::trace(logcat, "{} bytes written to fd {}", sz, _fd); if (sz <= 0) return false; return sz == static_cast(pkt.size()); @@ -190,37 +192,40 @@ namespace llarp::vpn /* Helper structure for ip address data and attributes */ struct _inet_addr { - unsigned char family; - unsigned char bitlen; - unsigned char data[sizeof(struct in6_addr)]; - - _inet_addr() = default; - - _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(ipv4 v4) + private: + void _init_internals(const ipv4& v4) { family = AF_INET; bitlen = 32; - - auto bigly = oxenc::host_to_big(v4.addr); - inet_ntop(AF_INET, &bigly, reinterpret_cast(data), sizeof(struct in6_addr)); + oxenc::write_host_as_big(v4.addr, &data); } - _inet_addr(ipv6 v6) + void _init_internals(const ipv6& v6) { family = AF_INET6; bitlen = 128; auto in6 = v6.to_in6(); std::memcpy(&data, &in6, sizeof(in6_addr)); } + + public: + unsigned char family; + unsigned char bitlen; + unsigned char data[sizeof(struct in6_addr)]; + + _inet_addr() = default; + + _inet_addr(oxen::quic::Address addr) + { + if (addr.is_ipv4()) + _init_internals(addr.to_ipv4()); + else + _init_internals(addr.to_ipv6()); + } + + _inet_addr(ipv4 v4) { _init_internals(v4); } + + _inet_addr(ipv6 v6) { _init_internals(v6); } }; void make_blackhole(int cmd, int flags, int af) @@ -237,12 +242,12 @@ namespace llarp::vpn nl_request.r.rtm_scope = RT_SCOPE_UNIVERSE; if (af == AF_INET) { - uint32_t addr{}; - nl_request.AddData(RTA_DST, &addr, sizeof(addr)); + ipv4 addr{}; + nl_request.AddData(RTA_DST, &addr.addr, sizeof(addr.addr)); } else { - uint128_t addr{}; + std::array addr{}; nl_request.AddData(RTA_DST, &addr, sizeof(addr)); } send(fd, &nl_request, sizeof(nl_request), 0); diff --git a/llarp/vpn/platform.hpp b/llarp/vpn/platform.hpp index 4b79670767..c8540abf18 100644 --- a/llarp/vpn/platform.hpp +++ b/llarp/vpn/platform.hpp @@ -32,7 +32,7 @@ namespace llarp::vpn } }; - struct InterfaceInfo + struct [[deprecated("Use net::if_info instead!")]] InterfaceInfo { std::string ifname; unsigned int index; From 74a64bbb7eacd96e4f300573065f0eb8cf730861 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Sun, 15 Dec 2024 09:49:33 -0800 Subject: [PATCH 39/44] squash --- llarp/address/ip_headers.hpp | 67 ++++++++++++++++++++ llarp/address/ip_packet.cpp | 17 +++--- llarp/address/ip_packet.hpp | 1 + llarp/address/types.hpp | 68 ++++----------------- llarp/address/utils.cpp | 115 ++++++++++++++++++++++++++++------- llarp/address/utils.hpp | 22 +++++++ llarp/handlers/session.cpp | 39 ++++++------ llarp/link/link_manager.cpp | 2 +- llarp/router/router.cpp | 2 +- llarp/vpn/linux.hpp | 4 +- 10 files changed, 224 insertions(+), 113 deletions(-) create mode 100644 llarp/address/ip_headers.hpp diff --git a/llarp/address/ip_headers.hpp b/llarp/address/ip_headers.hpp new file mode 100644 index 0000000000..918d8ff004 --- /dev/null +++ b/llarp/address/ip_headers.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include "utils.hpp" + +namespace llarp +{ + struct ip_header + { +#if __BYTE_ORDER == __LITTLE_ENDIAN + uint8_t header_len : 4; + uint8_t version : 4; +#else + uint8_t version : 4; + uint8_t header_len : 4; +#endif + uint8_t service_type; + uint16_t total_len; + uint16_t id; + uint16_t frag_off; // fragmentation offset + uint8_t ttl; + uint8_t protocol; + uint16_t checksum; + uint32_t src; + uint32_t dest; + }; + + static_assert(sizeof(ip_header) == 20); + + enum class TCPFLAG : uint8_t + { + FIN = 0x01, + SYN = 0x02, + RST = 0x04, + PUSH = 0x08, + ACK = 0x10, + URG = 0x20 + }; + + struct tcp_header + { + uint16_t src; + uint16_t dest; + uint32_t seqno; // sequence number + uint32_t ack; // ack number +#if __BYTE_ORDER == __LITTLE_ENDIAN + uint8_t xx; // unused + uint8_t data_off; // data offset +#else + uint8_t data_off; // data offset + uint8_t xx; // unused + +#endif + uint8_t flags; + uint16_t window; + uint16_t checksum; + uint16_t urg_ptr; // urgent ptr + }; + + struct udphdr + { + uint16_t src; + uint16_t dest; + uint16_t len; // datagram length + uint16_t checksum; + }; + +} // namespace llarp diff --git a/llarp/address/ip_packet.cpp b/llarp/address/ip_packet.cpp index d1d19ba815..1f1e0d99d7 100644 --- a/llarp/address/ip_packet.cpp +++ b/llarp/address/ip_packet.cpp @@ -89,8 +89,8 @@ namespace llarp } else { - auto srcv6 = ipv6{&_v6_header->srcaddr}; - auto dstv6 = ipv6{&_v6_header->dstaddr}; + auto srcv6 = ipv6{&_v6_header->src}; + auto dstv6 = ipv6{&_v6_header->dest}; log::trace(logcat, "srcv6={}:{}, dstv6={}:{}", srcv6, src_port, dstv6, dest_port); @@ -123,7 +123,6 @@ namespace llarp { log::debug(logcat, "Setting new source ({}) and destination ({}) IPs", src, dst); - std::basic_string_view head_u16s{reinterpret_cast(_header), sizeof(ip_header)}; // set new IP addresses _header->src = oxenc::host_to_big(src.addr); _header->dest = oxenc::host_to_big(dst.addr); @@ -142,9 +141,7 @@ namespace llarp break; } - // IPv4 checksum - auto v4chk = (uint16_t*)&(_header->checksum); - *v4chk = checksum_ipv4(_header, _header->header_len); + _header->checksum = checksum_ipv4(_header, _header->header_len); _init_internals(); } @@ -165,8 +162,8 @@ namespace llarp } // IPv6 address - hdr->srcaddr = src.to_in6(); - hdr->dstaddr = dst.to_in6(); + hdr->src = src.to_in6(); + hdr->dest = dst.to_in6(); // TODO IPv6 header options auto* pld = data() + ihs; @@ -226,7 +223,7 @@ namespace llarp chksumoff = 16; [[fallthrough]]; case 33: // DCCP - chksum = tcp_checksum_ipv6(&hdr->srcaddr, &hdr->dstaddr, hdr->payload_len, 0); + chksum = tcp_checksum_ipv6(&hdr->src, &hdr->dest, hdr->payload_len, 0); // ones-complement addition fo 0xFFff is 0; this is verboten if (chksum == 0xFFff) @@ -237,7 +234,7 @@ namespace llarp break; case 17: // UDP case 136: // UDP-Lite - same checksum place, same 0->0xFFff condition - chksum = udp_checksum_ipv6(&hdr->srcaddr, &hdr->dstaddr, hdr->payload_len, 0); + chksum = udp_checksum_ipv6(&hdr->src, &hdr->dest, hdr->payload_len, 0); _is_udp = true; break; default: diff --git a/llarp/address/ip_packet.hpp b/llarp/address/ip_packet.hpp index c3c87ee865..efa4f2c7d3 100644 --- a/llarp/address/ip_packet.hpp +++ b/llarp/address/ip_packet.hpp @@ -1,5 +1,6 @@ #pragma once +#include "ip_headers.hpp" #include "types.hpp" #include diff --git a/llarp/address/types.hpp b/llarp/address/types.hpp index e7469084e2..e08412ce42 100644 --- a/llarp/address/types.hpp +++ b/llarp/address/types.hpp @@ -48,75 +48,29 @@ namespace llarp "Failed to compare ip variant in desired {} scheme!"_format(compare_v4 ? "ipv4" : "ipv6")}; } - struct ip_header_le - { - uint8_t header_len : 4; - uint8_t version : 4; - uint8_t service_type; - uint16_t total_len; - uint16_t id; - uint16_t frag_off; - uint8_t ttl; - uint8_t protocol; - uint16_t checksum; - uint32_t src; - uint32_t dest; - }; - - struct ip_header_be - { - uint8_t version : 4; - uint8_t header_len : 4; - uint8_t service_type; - uint16_t total_len; - uint16_t id; - uint16_t frag_off; - uint8_t ttl; - uint8_t protocol; - uint16_t checksum; - uint32_t src; - uint32_t dest; - }; - - using ip_header = std::conditional_t; - - static_assert(sizeof(ip_header) == 20); - - struct ipv6_header_preamble_le - { - unsigned char pad_small : 4; - unsigned char version : 4; - uint8_t pad[3]; - }; - - struct ipv6_header_preamble_be - { - unsigned char version : 4; - unsigned char pad_small : 4; - uint8_t pad[3]; - }; - - using ipv6_header_preamble = - std::conditional_t; - - static_assert(sizeof(ipv6_header_preamble) == 4); - struct ipv6_header { union { - ipv6_header_preamble preamble; +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned char pad_small : 4; + unsigned char version : 4; +#else + unsigned char version : 4; + unsigned char pad_small : 4; +#endif + uint8_t pad[3]; uint32_t flowlabel; } preamble; uint16_t payload_len; uint8_t protocol; uint8_t hoplimit; - in6_addr srcaddr; - in6_addr dstaddr; + in6_addr src; + in6_addr dest; /// Returns the flowlabel (stored in network order) in HOST ORDER - uint32_t set_flowlabel() const { return ntohl(preamble.flowlabel & htonl(ipv6_flowlabel_mask)); } + uint32_t get_flowlabel() const { return ntohl(preamble.flowlabel & htonl(ipv6_flowlabel_mask)); } /// Sets a flowlabel in network order. Takes in a label in HOST ORDER void set_flowlabel(uint32_t label) diff --git a/llarp/address/utils.cpp b/llarp/address/utils.cpp index a0aa2152ed..f49b8a0de0 100644 --- a/llarp/address/utils.cpp +++ b/llarp/address/utils.cpp @@ -1,8 +1,63 @@ #include "utils.hpp" +#include "ip_headers.hpp" + namespace llarp { - static auto logcat = log::Cat("Address-utils"); + static auto logcat = log::Cat("address-utils"); + + namespace utils + { + // constexpr auto IP_CSUM_OFF = offsetof(struct ip_header, checksum); + // constexpr auto IP_DST_OFF = offsetof(struct ip_header, dest); + // constexpr auto IP_SRC_OFF = offsetof(struct ip_header, src); + // constexpr auto IP_PROTO_OFF = offsetof(struct ip_header, protocol); + // constexpr auto TCP_CSUM_OFF = offsetof(struct tcp_header, checksum); + // constexpr auto UDP_CSUM_OFF = offsetof(struct tcp_header, checksum); + // constexpr auto IS_PSEUDO = 0x10; + + static constexpr uint32_t add_u32(uint32_t x) + { + return uint32_t{x & 0xFFff} + uint32_t{x >> 16}; + } + + uint16_t ip_checksum(const uint8_t *buf, size_t sz) + { + uint32_t sum{}; + + while (sz > 1) + { + sum += *reinterpret_cast(buf); + sz -= sizeof(uint16_t); + buf += sizeof(uint16_t); + } + if (sz != 0) + sum += *reinterpret_cast(buf); + + sum = (sum & 0xFFff) + (sum >> 16); + sum += sum >> 16; + + return static_cast((~sum) & 0xFFff); + } + + uint16_t ipv4_checksum_diff(uint16_t old_sum, ipv4 old_src, ipv4 old_dest, ipv4 new_src, ipv4 new_dest) + { + uint32_t sum = oxenc::host_to_big(old_sum); + } + + } // namespace utils + + uint16_t csum_add(uint16_t csum, uint16_t rhs) + { + uint32_t res = csum, other = rhs; + res += other; + return static_cast(res + (res < other)); + } + + uint16_t csum_sub(uint16_t csum, uint16_t rhs) + { + return csum_add(csum, ~rhs); + } uint16_t from_32_to_16(uint32_t x) { @@ -21,6 +76,7 @@ namespace llarp x = (x & 0xffffffff) + (x >> 32); return x; } + uint16_t fold_csum(uint32_t csum) { auto sum = csum; @@ -29,15 +85,20 @@ namespace llarp return static_cast(~sum); } - uint32_t ipv4_checksum_magic(const uint8_t *buf, uint16_t len) + uint32_t ipv4_checksum_magic(const uint8_t *buf, int len) { - uint16_t odd{1}, result{0}; + int odd{1}; + uint16_t result{0}; odd &= (unsigned long)buf; if (odd) { - result += oxenc::little_endian ? (*buf << 8) : *buf; + if constexpr (oxenc::little_endian) + result += (*buf << 8); + else + result = *buf; + --len; ++buf; } @@ -54,8 +115,8 @@ namespace llarp if (len >= 4) { const unsigned char *end = buf + ((unsigned)len & ~3); - unsigned int carry = 0; + do { unsigned int w = *(unsigned int *)buf; @@ -87,52 +148,62 @@ namespace llarp return result; } + uint16_t checksum_partial(const void *header, uint8_t header_len, uint16_t old_sum) + { + uint16_t result = ipv4_checksum_magic(reinterpret_cast(header), header_len); + + if (result += old_sum; old_sum > result) + result += 1; + + return result; + } + uint16_t checksum_ipv4(const void *header, uint8_t header_len) { - return ~ipv4_checksum_magic(static_cast(header), header_len * 4); + return ~ipv4_checksum_magic(reinterpret_cast(header), header_len * 4); } uint32_t tcpudp_checksum_ipv4(uint32_t src, uint32_t dest, uint32_t len, uint8_t proto, uint32_t sum) { - auto _sum = static_cast(sum); + auto csum = static_cast(sum); - _sum += src; - _sum += dest; + csum += src; + csum += dest; - _sum += oxenc::big_endian ? proto + len : (proto + len) << 8; + csum += oxenc::big_endian ? proto + len : (proto + len) << 8; - return from_64_to_32(_sum); + return from_64_to_32(csum); } uint16_t ipv6_checksum_magic( - const struct in6_addr *saddr, const struct in6_addr *daddr, uint32_t len, uint8_t proto, uint32_t csum) + const struct in6_addr *saddr, const struct in6_addr *daddr, uint32_t len, uint8_t proto, uint32_t sum) { - uint32_t sum = csum; + uint32_t csum = sum; for (size_t i = 0; i < 4; ++i) { auto val = static_cast(saddr->s6_addr32[i]); - sum += val; - sum += (sum < val); + csum += val; + csum += (csum < val); } for (size_t i = 0; i < 4; ++i) { auto val = static_cast(daddr->s6_addr32[i]); - sum += val; - sum += (sum < val); + csum += val; + csum += (csum < val); } uint32_t ulen = htonl(len); uint32_t uproto = htonl(proto); - sum += ulen; - sum += (sum < ulen); + csum += ulen; + csum += (csum < ulen); - sum += uproto; - sum += (sum < uproto); + csum += uproto; + csum += (csum < uproto); - return fold_csum(sum); + return fold_csum(csum); } uint32_t tcp_checksum_ipv6(const struct in6_addr *saddr, const struct in6_addr *daddr, uint32_t len, uint32_t csum) diff --git a/llarp/address/utils.hpp b/llarp/address/utils.hpp index 62f9af20c4..695b038fe3 100644 --- a/llarp/address/utils.hpp +++ b/llarp/address/utils.hpp @@ -29,6 +29,28 @@ namespace llarp static std::set allowed = {SNODE, LOKI}; } // namespace TLD + namespace utils + { + + uint16_t ip_checksum(const uint8_t *buf, size_t sz); + + // Parameters: + // - old_sum : old checksum (NETWORK order!) + // - old_{src,dest} : old src and dest IP's (stored internally in HOST order!) + // - new_{src,dest} : new src and dest IP's (stored internally in HOST order!) + // + // Returns: + // - uint16_t : new checksum (NETWORK order!) + uint16_t ipv4_checksum_diff(uint16_t old_sum, ipv4 old_src, ipv4 old_dest, ipv4 new_src, ipv4 new_dest); + + void ipv4_tcp_checksum_diff(); + void ipv4_udp_checksum_diff(); + + uint16_t ipv6_checksum_diff(); + } // namespace utils + + uint16_t checksum_partial(const void *header, uint8_t header_len, uint16_t sum); + uint16_t checksum_ipv4(const void *header, uint8_t header_len); uint32_t tcpudp_checksum_ipv4(uint32_t src, uint32_t dest, uint32_t len, uint8_t proto, uint32_t sum); diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index 7699bf2538..fefb46df0d 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -140,7 +140,7 @@ namespace llarp::handlers update_and_publish_localcc(get_current_client_intros(), _srv_records); } - // static std::atomic testnet_trigger = false; + static std::atomic testnet_trigger = false; void SessionEndpoint::start_tickers() { @@ -155,25 +155,24 @@ namespace llarp::handlers }, true); - // if (not testnet_trigger) - // { - // testnet_trigger = true; - - // _router.loop()->call_later(5s, [this]() { - // try - // { - // RouterID cpk{oxenc::from_base32z("p3thqq8toyidz3ssos7tx6xhsje3zfdkmpdw43gtb8cz7a96yedo")}; - // log::info(logcat, "Beginning session init to client: {}", cpk.to_network_address(false)); - // _initiate_session( - // NetworkAddress::from_pubkey(cpk, true), [](ip_v) { log::critical(logcat, "FUCK YEAH"); - // }); - // } - // catch (const std::exception& e) - // { - // log::critical(logcat, "Failed to parse client netaddr: {}", e.what()); - // } - // }); - // } + if (not testnet_trigger) + { + testnet_trigger = true; + + _router.loop()->call_later(5s, [this]() { + try + { + RouterID cpk{oxenc::from_base32z("ccaocb1w9hqspyeog3xfipb1cubnc93bze7bhtruwp1qy7mhkseo")}; + log::info(logcat, "Beginning session init to client: {}", cpk.to_network_address(false)); + _initiate_session( + NetworkAddress::from_pubkey(cpk, true), [](ip_v) { log::critical(logcat, "FUCK YEAH"); }); + } + catch (const std::exception& e) + { + log::critical(logcat, "Failed to parse client netaddr: {}", e.what()); + } + }); + } } else log::info(logcat, "SessionEndpoint configured to NOT publish ClientContact..."); diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 4be414e10a..95e93d3848 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -1502,7 +1502,7 @@ namespace llarp void LinkManager::handle_path_data_message(bstring data) { - _router.loop()->call([this, message = std::move(data)]() { + _router.loop()->call([this, message = std::move(data)]() mutable { HopID hop_id; std::string payload; SymmNonce nonce; diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index 809c601280..b055e277b0 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -1014,7 +1014,7 @@ namespace llarp log::debug(logcat, "Creating Router::Tick() repeating event..."); _loop_ticker = _loop->call_every( - ROUTER_TICK_INTERVAL, [this] { tick(); }, false, true); + ROUTER_TICK_INTERVAL, [this] { tick(); }, false); // _route_poker->start(); diff --git a/llarp/vpn/linux.hpp b/llarp/vpn/linux.hpp index f6103f095e..db511a68a0 100644 --- a/llarp/vpn/linux.hpp +++ b/llarp/vpn/linux.hpp @@ -122,10 +122,10 @@ namespace llarp::vpn IPPacket read_next_packet() override { - log::trace(logcat, "{} called", __PRETTY_FUNCTION__); std::vector buf; buf.resize(MAX_PACKET_SIZE); const auto sz = read(_fd, buf.data(), buf.capacity()); + log::debug(logcat, "{} bytes read from fd {} (err?:{})", sz, _fd, strerror(errno)); if (sz < 0) { if (errno == EAGAIN or errno == EWOULDBLOCK) @@ -143,7 +143,7 @@ namespace llarp::vpn bool write_packet(IPPacket pkt) override { const auto sz = write(_fd, pkt.data(), pkt.size()); - log::trace(logcat, "{} bytes written to fd {}", sz, _fd); + log::debug(logcat, "{} bytes written to fd {} (err?:{})", sz, _fd, strerror(errno)); if (sz <= 0) return false; return sz == static_cast(pkt.size()); From 208eed6395f4755c4c12f60ba85a569ccb8594e4 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Mon, 13 Jan 2025 06:39:15 -0800 Subject: [PATCH 40/44] big reorg, more commits to come --- .clang-format | 2 +- llarp/CMakeLists.txt | 39 +--- llarp/address/address.cpp | 20 +- llarp/address/address.hpp | 1 - llarp/address/ip_headers.hpp | 67 ------ llarp/address/ip_range.cpp | 10 +- llarp/address/ip_range.hpp | 2 - llarp/address/types.hpp | 58 ----- llarp/address/utils.cpp | 234 ++++--------------- llarp/address/utils.hpp | 92 +------- llarp/android/ifaddrs.c | 5 +- llarp/apple/PacketTunnelProvider.m | 5 +- llarp/apple/context_wrapper.cpp | 2 +- llarp/apple/vpn_interface.cpp | 5 +- llarp/auth/auth.hpp | 1 - llarp/auth/session_auth.cpp | 5 +- llarp/bootstrap.cpp | 5 +- llarp/config/config.cpp | 5 +- llarp/config/config.hpp | 2 +- llarp/config/ini.cpp | 5 +- llarp/consensus/reachability_testing.cpp | 10 +- llarp/constants/files.hpp | 15 +- llarp/contact/client_contact.cpp | 10 +- llarp/contact/client_contact.hpp | 14 +- llarp/contact/client_intro.cpp | 5 +- llarp/contact/contactdb.cpp | 5 +- llarp/contact/keys.cpp | 20 +- llarp/contact/keys.hpp | 1 - llarp/contact/router_id.hpp | 5 +- llarp/contact/sns.cpp | 5 +- llarp/context.cpp | 15 +- llarp/crypto/crypto.cpp | 15 +- llarp/crypto/types.cpp | 10 +- llarp/dns/message.cpp | 17 +- llarp/dns/platform.cpp | 5 +- llarp/dns/question.cpp | 5 +- llarp/dns/server.cpp | 10 +- llarp/dns/server.hpp | 3 +- llarp/ev/loop.cpp | 5 +- llarp/ev/loop.hpp | 2 +- llarp/ev/tcp.cpp | 2 +- llarp/ev/udp.cpp | 5 +- llarp/handlers/session.cpp | 72 +++--- llarp/handlers/tun.cpp | 67 ++---- llarp/handlers/tun.hpp | 3 +- llarp/link/link_manager.cpp | 79 ++----- llarp/link/tunnel.cpp | 10 +- llarp/lokinet_shared.cpp | 5 +- llarp/messages/common.hpp | 5 +- llarp/net/ip_headers.hpp | 124 ++++++++++ llarp/{address => net}/ip_packet.cpp | 141 ++++++----- llarp/{address => net}/ip_packet.hpp | 19 +- llarp/net/net.hpp | 30 +-- llarp/net/{traffic_policy.cpp => policy.cpp} | 90 +++---- llarp/net/policy.hpp | 123 ++++++++++ llarp/net/posix.cpp | 5 +- llarp/net/traffic_policy.hpp | 95 -------- llarp/net/utils.cpp | 139 +++++++++++ llarp/net/utils.hpp | 55 +++++ llarp/net/win32.cpp | 7 +- llarp/nodedb.cpp | 30 +-- llarp/path/path.cpp | 90 ++----- llarp/path/path.hpp | 9 - llarp/path/path_context.cpp | 10 +- llarp/path/path_handler.cpp | 40 +--- llarp/profiling.cpp | 15 +- llarp/router/router.cpp | 50 +--- llarp/router_version.cpp | 10 +- llarp/rpc/json_conversions.cpp | 5 +- llarp/rpc/param_parser.hpp | 5 +- llarp/rpc/rpc_request_parser.cpp | 5 +- llarp/rpc/rpc_server.cpp | 2 +- llarp/rpc/rpc_server.hpp | 5 +- llarp/session/session.cpp | 15 +- llarp/session/session.hpp | 2 +- llarp/simulation/sim_context.cpp | 5 +- llarp/util/buffer.cpp | 30 +-- llarp/util/buffer.hpp | 5 +- llarp/util/concept.hpp | 34 --- llarp/util/formattable.hpp | 41 +--- llarp/util/meta.hpp | 130 +++++++---- llarp/util/thread/queue_manager.cpp | 55 +---- llarp/util/time.cpp | 20 +- llarp/vpn/egres_packet_router.hpp | 2 +- llarp/vpn/linux.hpp | 4 +- llarp/vpn/packet_io.hpp | 2 +- llarp/vpn/packet_router.cpp | 19 +- llarp/vpn/packet_router.hpp | 7 +- llarp/vpn/platform.cpp | 5 +- llarp/vpn/platform.hpp | 2 +- llarp/win32/exec.cpp | 10 +- llarp/win32/service_manager.cpp | 5 +- pybind/llarp/config.cpp | 5 +- 93 files changed, 966 insertions(+), 1526 deletions(-) delete mode 100644 llarp/address/ip_headers.hpp create mode 100644 llarp/net/ip_headers.hpp rename llarp/{address => net}/ip_packet.cpp (69%) rename llarp/{address => net}/ip_packet.hpp (94%) rename llarp/net/{traffic_policy.cpp => policy.cpp} (75%) create mode 100644 llarp/net/policy.hpp delete mode 100644 llarp/net/traffic_policy.hpp create mode 100644 llarp/net/utils.cpp create mode 100644 llarp/net/utils.hpp delete mode 100644 llarp/util/concept.hpp diff --git a/.clang-format b/.clang-format index 3f5427ffb5..3c029071f0 100644 --- a/.clang-format +++ b/.clang-format @@ -50,7 +50,7 @@ NamespaceIndentation: All # shorties AllowShortBlocksOnASingleLine: 'false' AllowShortCaseLabelsOnASingleLine: 'false' -AllowShortFunctionsOnASingleLine: Inline +AllowShortFunctionsOnASingleLine: All AllowShortIfStatementsOnASingleLine: 'false' AllowShortLoopsOnASingleLine: 'false' diff --git a/llarp/CMakeLists.txt b/llarp/CMakeLists.txt index e50647b601..2e62b6cdeb 100644 --- a/llarp/CMakeLists.txt +++ b/llarp/CMakeLists.txt @@ -73,27 +73,27 @@ add_dependencies(lokinet-utils genversion) lokinet_add_library(lokinet-contact contact/client_contact.cpp contact/client_intro.cpp - contact/contactdb.cpp - contact/keys.cpp - contact/relay_contact.cpp contact/relay_contact_local.cpp contact/relay_contact_remote.cpp - contact/router_id.cpp - contact/sns.cpp - contact/tag.cpp ) +# Network interface files used for mediating ip traffic +lokinet_add_library(lokinet-ip + net/ip_packet.cpp + net/policy.cpp + net/utils.cpp +) + # Addressing and event loop files used by lokinet-core and other libraries # needed by rpc/ link/ config/ path/ dht/ lokinet_add_library(lokinet-addressing address/address.cpp - address/ip_packet.cpp address/ip_range.cpp address/utils.cpp @@ -102,15 +102,11 @@ lokinet_add_library(lokinet-addressing ev/types.cpp ev/udp.cpp -# net/ip.cpp -# net/net_int.cpp - router_version.cpp # to be deleted shortly ) # lokinet-platform holds all platform specific code lokinet_add_library(lokinet-platform -# net/interface_info.cpp vpn/packet_router.cpp vpn/platform.cpp ) @@ -173,7 +169,6 @@ 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 ) @@ -212,17 +207,12 @@ lokinet_add_library(lokinet-path path/transit_hop.cpp ) -#target_link_libraries(lokinet-core PUBLIC lokinet-core-utils) -#target_link_libraries(lokinet-core-utils PUBLIC lokinet-dns) -#target_link_libraries(lokinet-dns PUBLIC lokinet-dns-platform) -#target_link_libraries(lokinet-dns PUBLIC lokinet-utils lokinet-cryptography lokinet-config lokinet-dns-platform) - # Link libraries to their internals target_link_libraries(lokinet-wire PUBLIC lokinet-addressing) target_link_libraries(lokinet-nodedb PUBLIC lokinet-addressing lokinet-cryptography) -target_link_libraries(lokinet-platform PUBLIC lokinet-cryptography) +target_link_libraries(lokinet-platform PUBLIC lokinet-cryptography lokinet-ip) target_link_libraries(lokinet-rpc PUBLIC lokinet-wire lokinet-contact) -target_link_libraries(lokinet-addressing PUBLIC lokinet-utils lokinet-cryptography lokinet-contact) +target_link_libraries(lokinet-addressing PUBLIC lokinet-utils lokinet-cryptography lokinet-contact lokinet-ip) target_link_libraries(lokinet-wire PUBLIC lokinet-cryptography) target_link_libraries(lokinet-config PUBLIC lokinet-cryptography) @@ -289,17 +279,6 @@ target_link_libraries(lokinet-base ) -# 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) -# target_link_libraries(lokinet-path PUBLIC oxenmq::oxenmq) -# target_link_libraries(lokinet-platform PUBLIC oxenmq::oxenmq Threads::Threads) -# 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) diff --git a/llarp/address/address.cpp b/llarp/address/address.cpp index 3c8bbef313..0e1a092e49 100644 --- a/llarp/address/address.cpp +++ b/llarp/address/address.cpp @@ -47,10 +47,7 @@ namespace llarp return std::tie(_pubkey, _is_client) == std::tie(other._pubkey, other._is_client); } - bool NetworkAddress::operator!=(const NetworkAddress& other) const - { - return !(*this == other); - } + bool NetworkAddress::operator!=(const NetworkAddress& other) const { return !(*this == other); } std::optional RelayAddress::from_relay_addr(std::string arg) { @@ -73,18 +70,9 @@ namespace llarp throw std::invalid_argument{"Invalid pubkey passed to RelayAddress constructor: {}"_format(arg)}; } - bool RelayAddress::operator<(const RelayAddress& other) const - { - return _pubkey < other._pubkey; - } + bool RelayAddress::operator<(const RelayAddress& other) const { return _pubkey < other._pubkey; } - bool RelayAddress::operator==(const RelayAddress& other) const - { - return _pubkey == other._pubkey; - } + bool RelayAddress::operator==(const RelayAddress& other) const { return _pubkey == other._pubkey; } - bool RelayAddress::operator!=(const RelayAddress& other) const - { - return !(*this == other); - } + bool RelayAddress::operator!=(const RelayAddress& other) const { return !(*this == other); } } // namespace llarp diff --git a/llarp/address/address.hpp b/llarp/address/address.hpp index c38101a67b..4d1acf7724 100644 --- a/llarp/address/address.hpp +++ b/llarp/address/address.hpp @@ -6,7 +6,6 @@ #include #include #include -#include #include diff --git a/llarp/address/ip_headers.hpp b/llarp/address/ip_headers.hpp deleted file mode 100644 index 918d8ff004..0000000000 --- a/llarp/address/ip_headers.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once - -#include "utils.hpp" - -namespace llarp -{ - struct ip_header - { -#if __BYTE_ORDER == __LITTLE_ENDIAN - uint8_t header_len : 4; - uint8_t version : 4; -#else - uint8_t version : 4; - uint8_t header_len : 4; -#endif - uint8_t service_type; - uint16_t total_len; - uint16_t id; - uint16_t frag_off; // fragmentation offset - uint8_t ttl; - uint8_t protocol; - uint16_t checksum; - uint32_t src; - uint32_t dest; - }; - - static_assert(sizeof(ip_header) == 20); - - enum class TCPFLAG : uint8_t - { - FIN = 0x01, - SYN = 0x02, - RST = 0x04, - PUSH = 0x08, - ACK = 0x10, - URG = 0x20 - }; - - struct tcp_header - { - uint16_t src; - uint16_t dest; - uint32_t seqno; // sequence number - uint32_t ack; // ack number -#if __BYTE_ORDER == __LITTLE_ENDIAN - uint8_t xx; // unused - uint8_t data_off; // data offset -#else - uint8_t data_off; // data offset - uint8_t xx; // unused - -#endif - uint8_t flags; - uint16_t window; - uint16_t checksum; - uint16_t urg_ptr; // urgent ptr - }; - - struct udphdr - { - uint16_t src; - uint16_t dest; - uint16_t len; // datagram length - uint16_t checksum; - }; - -} // namespace llarp diff --git a/llarp/address/ip_range.cpp b/llarp/address/ip_range.cpp index 0dd9506bb7..f26604f8b3 100644 --- a/llarp/address/ip_range.cpp +++ b/llarp/address/ip_range.cpp @@ -64,15 +64,9 @@ namespace llarp return _contains(std::get(other.base_ip())); } - bool IPRange::_contains(const ipv4& other) const - { - return _ipv4_range().contains(other); - } + bool IPRange::_contains(const ipv4& other) const { return _ipv4_range().contains(other); } - bool IPRange::_contains(const ipv6& other) const - { - return _ipv6_range().contains(other); - } + bool IPRange::_contains(const ipv6& other) const { return _ipv6_range().contains(other); } bool IPRange::contains(const ip_v& other) const { diff --git a/llarp/address/ip_range.hpp b/llarp/address/ip_range.hpp index fa3162f53e..55e9bd4736 100644 --- a/llarp/address/ip_range.hpp +++ b/llarp/address/ip_range.hpp @@ -2,8 +2,6 @@ #include "utils.hpp" -#include - #include namespace llarp diff --git a/llarp/address/types.hpp b/llarp/address/types.hpp index e08412ce42..350167f9fc 100644 --- a/llarp/address/types.hpp +++ b/llarp/address/types.hpp @@ -25,64 +25,6 @@ namespace llarp } // namespace concepts using KeyedAddress = oxen::quic::RemoteAddress; - - inline constexpr uint32_t ipv6_flowlabel_mask = 0b0000'0000'0000'1111'1111'1111'1111'1111; - - inline constexpr size_t ICMP_HEADER_SIZE{8}; - - // Compares the given ip variant against a quic address - // Returns: - // - true : ip == address - // - false : ip != address - // Error: - // - throws : ip and address are mismatched ipv4 vs ipv6 - inline bool ip_equals_address(const ip_v& ip, const oxen::quic::Address& addr, bool compare_v4) - { - if (compare_v4 and std::holds_alternative(ip)) - return std::get(ip) == addr.to_ipv4(); - - if (not compare_v4 and std::holds_alternative(ip)) - return std::get(ip) == addr.to_ipv6(); - - throw std::invalid_argument{ - "Failed to compare ip variant in desired {} scheme!"_format(compare_v4 ? "ipv4" : "ipv6")}; - } - - struct ipv6_header - { - union - { -#if __BYTE_ORDER == __LITTLE_ENDIAN - unsigned char pad_small : 4; - unsigned char version : 4; -#else - unsigned char version : 4; - unsigned char pad_small : 4; -#endif - uint8_t pad[3]; - uint32_t flowlabel; - } preamble; - - uint16_t payload_len; - uint8_t protocol; - uint8_t hoplimit; - in6_addr src; - in6_addr dest; - - /// Returns the flowlabel (stored in network order) in HOST ORDER - uint32_t get_flowlabel() const { return ntohl(preamble.flowlabel & htonl(ipv6_flowlabel_mask)); } - - /// Sets a flowlabel in network order. Takes in a label in HOST ORDER - void set_flowlabel(uint32_t label) - { - // the ipv6 flow label is the last 20 bits in the first 32 bits of the header - preamble.flowlabel = - (htonl(ipv6_flowlabel_mask) & htonl(label)) | (preamble.flowlabel & htonl(~ipv6_flowlabel_mask)); - } - }; - - static_assert(sizeof(ipv6_header) == 40); - } // namespace llarp namespace std diff --git a/llarp/address/utils.cpp b/llarp/address/utils.cpp index f49b8a0de0..be4cae5975 100644 --- a/llarp/address/utils.cpp +++ b/llarp/address/utils.cpp @@ -1,219 +1,71 @@ #include "utils.hpp" -#include "ip_headers.hpp" - namespace llarp { static auto logcat = log::Cat("address-utils"); - namespace utils + namespace detail { - // constexpr auto IP_CSUM_OFF = offsetof(struct ip_header, checksum); - // constexpr auto IP_DST_OFF = offsetof(struct ip_header, dest); - // constexpr auto IP_SRC_OFF = offsetof(struct ip_header, src); - // constexpr auto IP_PROTO_OFF = offsetof(struct ip_header, protocol); - // constexpr auto TCP_CSUM_OFF = offsetof(struct tcp_header, checksum); - // constexpr auto UDP_CSUM_OFF = offsetof(struct tcp_header, checksum); - // constexpr auto IS_PSEUDO = 0x10; - - static constexpr uint32_t add_u32(uint32_t x) - { - return uint32_t{x & 0xFFff} + uint32_t{x >> 16}; - } - - uint16_t ip_checksum(const uint8_t *buf, size_t sz) + std::optional parse_addr_string(std::string_view arg, std::string_view tld) { - uint32_t sum{}; + std::optional ret = std::nullopt; - while (sz > 1) + if (auto pos = arg.find_first_of('.'); pos != std::string_view::npos) { - sum += *reinterpret_cast(buf); - sz -= sizeof(uint16_t); - buf += sizeof(uint16_t); - } - if (sz != 0) - sum += *reinterpret_cast(buf); - - sum = (sum & 0xFFff) + (sum >> 16); - sum += sum >> 16; - - return static_cast((~sum) & 0xFFff); - } - - uint16_t ipv4_checksum_diff(uint16_t old_sum, ipv4 old_src, ipv4 old_dest, ipv4 new_src, ipv4 new_dest) - { - uint32_t sum = oxenc::host_to_big(old_sum); - } - - } // namespace utils - - uint16_t csum_add(uint16_t csum, uint16_t rhs) - { - uint32_t res = csum, other = rhs; - res += other; - return static_cast(res + (res < other)); - } - - uint16_t csum_sub(uint16_t csum, uint16_t rhs) - { - return csum_add(csum, ~rhs); - } - - uint16_t from_32_to_16(uint32_t x) - { - /* add up 16-bit and 16-bit for 16+c bit */ - x = (x & 0xffff) + (x >> 16); - /* add up carry.. */ - x = (x & 0xffff) + (x >> 16); - return x; - } - - uint32_t from_64_to_32(uint64_t x) - { - /* add up 32-bit and 32-bit for 32+c bit */ - x = (x & 0xffffffff) + (x >> 32); - /* add up carry.. */ - x = (x & 0xffffffff) + (x >> 32); - return x; - } + auto _prefix = arg.substr(0, pos); + // check the pubkey prefix is the right length + if (_prefix.length() != PUBKEYSIZE) + return ret; - uint16_t fold_csum(uint32_t csum) - { - auto sum = csum; - sum = (sum & 0xffff) + (sum >> 16); - sum = (sum & 0xffff) + (sum >> 16); - return static_cast(~sum); - } + // verify the tld is allowed + auto _tld = arg.substr(pos); - uint32_t ipv4_checksum_magic(const uint8_t *buf, int len) - { - int odd{1}; - uint16_t result{0}; + if (_tld == tld and TLD::allowed.count(_tld)) + ret = _prefix; + } - odd &= (unsigned long)buf; + return ret; + }; - if (odd) + std::pair parse_addr(std::string_view addr, std::optional default_port) { - if constexpr (oxenc::little_endian) - result += (*buf << 8); - else - result = *buf; - - --len; - ++buf; - } + std::pair result; + auto &[host, port] = result; - if (len >= 2) - { - if (2 & (unsigned long)buf) + if (auto p = addr.find_last_not_of(DIGITS); + p != std::string_view::npos && p + 2 <= addr.size() && addr[p] == ':') { - result += *(unsigned short *)buf; - len -= 2; - buf += 2; + if (!parse_int(addr.substr(p + 1), port)) + throw std::invalid_argument{"Invalid address: could not parse port"}; + addr.remove_suffix(addr.size() - p); } - - if (len >= 4) + else if (default_port.has_value()) // use ::has_value() in case default_port is set but is == 0 { - const unsigned char *end = buf + ((unsigned)len & ~3); - unsigned int carry = 0; + port = *default_port; + } + else + throw std::invalid_argument{ + "Invalid address: argument contains no port and no default was specified (input:{})"_format(addr)}; - do - { - unsigned int w = *(unsigned int *)buf; - buf += 4; - result += carry; - result += w; - carry = (w > result); - } while (buf < end); + bool had_sq_brackets = false; - result += carry; - result = (result & 0xffff) + (result >> 16); + if (!addr.empty() && addr.front() == '[' && addr.back() == ']') + { + addr.remove_prefix(1); + addr.remove_suffix(1); + had_sq_brackets = true; } - if (len & 2) + if (auto p = addr.find_first_not_of(PDIGITS); p != std::string_view::npos) { - result += *(unsigned short *)buf; - buf += 2; + if (auto q = addr.find_first_not_of(ALDIGITS); q != std::string_view::npos) + throw std::invalid_argument{"Invalid address: does not look like IPv4 or IPv6!"}; + if (!had_sq_brackets) + throw std::invalid_argument{"Invalid address: IPv6 addresses require [...] square brackets"}; } - } - - if (len & 1) - result += oxenc::little_endian ? *buf : (*buf << 8); - - result = from_32_to_16(result); - - if (odd) - result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); - - return result; - } - - uint16_t checksum_partial(const void *header, uint8_t header_len, uint16_t old_sum) - { - uint16_t result = ipv4_checksum_magic(reinterpret_cast(header), header_len); - - if (result += old_sum; old_sum > result) - result += 1; - - return result; - } - - uint16_t checksum_ipv4(const void *header, uint8_t header_len) - { - return ~ipv4_checksum_magic(reinterpret_cast(header), header_len * 4); - } - - uint32_t tcpudp_checksum_ipv4(uint32_t src, uint32_t dest, uint32_t len, uint8_t proto, uint32_t sum) - { - auto csum = static_cast(sum); - - csum += src; - csum += dest; - - csum += oxenc::big_endian ? proto + len : (proto + len) << 8; - - return from_64_to_32(csum); - } - uint16_t ipv6_checksum_magic( - const struct in6_addr *saddr, const struct in6_addr *daddr, uint32_t len, uint8_t proto, uint32_t sum) - { - uint32_t csum = sum; - - for (size_t i = 0; i < 4; ++i) - { - auto val = static_cast(saddr->s6_addr32[i]); - csum += val; - csum += (csum < val); - } - - for (size_t i = 0; i < 4; ++i) - { - auto val = static_cast(daddr->s6_addr32[i]); - csum += val; - csum += (csum < val); + host = addr; + return result; } - - uint32_t ulen = htonl(len); - uint32_t uproto = htonl(proto); - - csum += ulen; - csum += (csum < ulen); - - csum += uproto; - csum += (csum < uproto); - - return fold_csum(csum); - } - - uint32_t tcp_checksum_ipv6(const struct in6_addr *saddr, const struct in6_addr *daddr, uint32_t len, uint32_t csum) - { - return ~ipv6_checksum_magic(saddr, daddr, len, IPPROTO_TCP, csum); - } - - uint32_t udp_checksum_ipv6(const struct in6_addr *saddr, const struct in6_addr *daddr, uint32_t len, uint32_t csum) - { - return ~ipv6_checksum_magic(saddr, daddr, len, IPPROTO_UDP, csum); - } - + } // namespace detail } // namespace llarp diff --git a/llarp/address/utils.hpp b/llarp/address/utils.hpp index 695b038fe3..d78994a5fd 100644 --- a/llarp/address/utils.hpp +++ b/llarp/address/utils.hpp @@ -29,104 +29,16 @@ namespace llarp static std::set allowed = {SNODE, LOKI}; } // namespace TLD - namespace utils - { - - uint16_t ip_checksum(const uint8_t *buf, size_t sz); - - // Parameters: - // - old_sum : old checksum (NETWORK order!) - // - old_{src,dest} : old src and dest IP's (stored internally in HOST order!) - // - new_{src,dest} : new src and dest IP's (stored internally in HOST order!) - // - // Returns: - // - uint16_t : new checksum (NETWORK order!) - uint16_t ipv4_checksum_diff(uint16_t old_sum, ipv4 old_src, ipv4 old_dest, ipv4 new_src, ipv4 new_dest); - - void ipv4_tcp_checksum_diff(); - void ipv4_udp_checksum_diff(); - - uint16_t ipv6_checksum_diff(); - } // namespace utils - - uint16_t checksum_partial(const void *header, uint8_t header_len, uint16_t sum); - - uint16_t checksum_ipv4(const void *header, uint8_t header_len); - - uint32_t tcpudp_checksum_ipv4(uint32_t src, uint32_t dest, uint32_t len, uint8_t proto, uint32_t sum); - - uint32_t tcp_checksum_ipv6(const struct in6_addr *saddr, const struct in6_addr *daddr, uint32_t len, uint32_t csum); - - uint32_t udp_checksum_ipv6(const struct in6_addr *saddr, const struct in6_addr *daddr, uint32_t len, uint32_t csum); - namespace detail { // inline auto utilcat = log::Cat("addrutils"); - inline std::optional parse_addr_string(std::string_view arg, std::string_view tld) - { - std::optional ret = std::nullopt; - - if (auto pos = arg.find_first_of('.'); pos != std::string_view::npos) - { - auto _prefix = arg.substr(0, pos); - // check the pubkey prefix is the right length - if (_prefix.length() != PUBKEYSIZE) - return ret; - - // verify the tld is allowed - auto _tld = arg.substr(pos); - - if (_tld == tld and TLD::allowed.count(_tld)) - ret = _prefix; - } - - return ret; - }; + std::optional parse_addr_string(std::string_view arg, std::string_view tld); inline constexpr auto DIGITS = "0123456789"sv; inline constexpr auto PDIGITS = "0123456789."sv; inline constexpr auto ALDIGITS = "0123456789abcdef:."sv; - inline std::pair parse_addr(std::string_view addr, std::optional default_port) - { - std::pair result; - auto &[host, port] = result; - - if (auto p = addr.find_last_not_of(DIGITS); - p != std::string_view::npos && p + 2 <= addr.size() && addr[p] == ':') - { - if (!parse_int(addr.substr(p + 1), port)) - throw std::invalid_argument{"Invalid address: could not parse port"}; - addr.remove_suffix(addr.size() - p); - } - else if (default_port.has_value()) // use ::has_value() in case default_port is set but is == 0 - { - port = *default_port; - } - else - throw std::invalid_argument{ - "Invalid address: argument contains no port and no default was specified (input:{})"_format(addr)}; - - bool had_sq_brackets = false; - - if (!addr.empty() && addr.front() == '[' && addr.back() == ']') - { - addr.remove_prefix(1); - addr.remove_suffix(1); - had_sq_brackets = true; - } - - if (auto p = addr.find_first_not_of(PDIGITS); p != std::string_view::npos) - { - if (auto q = addr.find_first_not_of(ALDIGITS); q != std::string_view::npos) - throw std::invalid_argument{"Invalid address: does not look like IPv4 or IPv6!"}; - if (!had_sq_brackets) - throw std::invalid_argument{"Invalid address: IPv6 addresses require [...] square brackets"}; - } - - host = addr; - return result; - } + std::pair parse_addr(std::string_view addr, std::optional default_port); inline constexpr size_t num_ipv4_private{272}; diff --git a/llarp/android/ifaddrs.c b/llarp/android/ifaddrs.c index 31784383d4..bbd78c55e6 100644 --- a/llarp/android/ifaddrs.c +++ b/llarp/android/ifaddrs.c @@ -237,10 +237,7 @@ static NetlinkList* getResultList(int p_socket, int p_request) return l_list; } -static size_t maxSize(size_t a, size_t b) -{ - return (a > b ? a : b); -} +static size_t maxSize(size_t a, size_t b) { return (a > b ? a : b); } static size_t calcAddrLen(sa_family_t p_family, int p_dataSize) { diff --git a/llarp/apple/PacketTunnelProvider.m b/llarp/apple/PacketTunnelProvider.m index 629f980143..0916a5aa58 100644 --- a/llarp/apple/PacketTunnelProvider.m +++ b/llarp/apple/PacketTunnelProvider.m @@ -32,10 +32,7 @@ - (void)updateNetworkSettings; @end -static void nslogger(const char* msg) -{ - NSLog(@"%s", msg); -} +static void nslogger(const char* msg) { NSLog(@"%s", msg); } static void packet_writer(int af, const void* data, size_t size, void* ctx) { diff --git a/llarp/apple/context_wrapper.cpp b/llarp/apple/context_wrapper.cpp index a6ffd41c90..37ea1b1a35 100644 --- a/llarp/apple/context_wrapper.cpp +++ b/llarp/apple/context_wrapper.cpp @@ -3,9 +3,9 @@ #include "context.hpp" #include "vpn_interface.hpp" -#include #include #include +#include #include #include #include diff --git a/llarp/apple/vpn_interface.cpp b/llarp/apple/vpn_interface.cpp index 4ffa535650..31d0ce2b59 100644 --- a/llarp/apple/vpn_interface.cpp +++ b/llarp/apple/vpn_interface.cpp @@ -31,10 +31,7 @@ namespace llarp::apple // } - int VPNInterface::PollFD() const - { - return -1; - } + int VPNInterface::PollFD() const { return -1; } IPPacket VPNInterface::read_next_packet() { diff --git a/llarp/auth/auth.hpp b/llarp/auth/auth.hpp index 1a42f14d38..e22142be77 100644 --- a/llarp/auth/auth.hpp +++ b/llarp/auth/auth.hpp @@ -6,7 +6,6 @@ #include #include #include -#include #include #include diff --git a/llarp/auth/session_auth.cpp b/llarp/auth/session_auth.cpp index e170010f60..03406091ee 100644 --- a/llarp/auth/session_auth.cpp +++ b/llarp/auth/session_auth.cpp @@ -31,9 +31,6 @@ namespace llarp::auth return ret; } - bool SessionAuthPolicy::load_identity_from_file(const char* fname) - { - return _session_key.load_from_file(fname); - } + bool SessionAuthPolicy::load_identity_from_file(const char* fname) { return _session_key.load_from_file(fname); } } // namespace llarp::auth diff --git a/llarp/bootstrap.cpp b/llarp/bootstrap.cpp index 283e028144..9d68264b22 100644 --- a/llarp/bootstrap.cpp +++ b/llarp/bootstrap.cpp @@ -78,10 +78,7 @@ namespace llarp return false; } - bool BootstrapList::contains(const RemoteRC& rc) const - { - return count(rc); - } + bool BootstrapList::contains(const RemoteRC& rc) const { return count(rc); } std::string_view BootstrapList::bt_encode() const { diff --git a/llarp/config/config.cpp b/llarp/config/config.cpp index ad5e45b33a..8cee0faa70 100644 --- a/llarp/config/config.cpp +++ b/llarp/config/config.cpp @@ -1702,10 +1702,7 @@ namespace llarp return load_config_data(ini, std::nullopt, isRelay); } - bool Config::load_default_config(bool isRelay) - { - return load_string("", isRelay); - } + bool Config::load_default_config(bool isRelay) { return load_string("", isRelay); } void Config::init_config(ConfigDefinition& conf, const ConfigGenParameters& params) { diff --git a/llarp/config/config.hpp b/llarp/config/config.hpp index 485d16c446..5aae2b004e 100644 --- a/llarp/config/config.hpp +++ b/llarp/config/config.hpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include diff --git a/llarp/config/ini.cpp b/llarp/config/ini.cpp index f1eb69e74d..4659ec8ded 100644 --- a/llarp/config/ini.cpp +++ b/llarp/config/ini.cpp @@ -50,10 +50,7 @@ namespace llarp _data.clear(); } - static bool whitespace(char ch) - { - return std::isspace(static_cast(ch)) != 0; - } + static bool whitespace(char ch) { return std::isspace(static_cast(ch)) != 0; } /// Differs from Parse() as ParseAll() does NOT skip comments /// ParseAll() is only used by RPC endpoint 'config' for diff --git a/llarp/consensus/reachability_testing.cpp b/llarp/consensus/reachability_testing.cpp index 8234f45b5f..39ef7e95e8 100644 --- a/llarp/consensus/reachability_testing.cpp +++ b/llarp/consensus/reachability_testing.cpp @@ -56,10 +56,7 @@ namespace llarp::consensus check_incoming_tests_impl("lokinet", now, startup, last); } - void reachability_testing::incoming_ping(const time_point_t& now) - { - last.last_test = now; - } + void reachability_testing::incoming_ping(const time_point_t& now) { last.last_test = now; } std::optional reachability_testing::next_random(Router* router, const time_point_t& now, bool requeue) { @@ -138,9 +135,6 @@ namespace llarp::consensus failing_queue.emplace(pk, steady_clock::now() + next_test_in, previous_failures + 1); } - void reachability_testing::remove_node_from_failing(const RouterID& pk) - { - failing.erase(pk); - } + void reachability_testing::remove_node_from_failing(const RouterID& pk) { failing.erase(pk); } } // namespace llarp::consensus diff --git a/llarp/constants/files.hpp b/llarp/constants/files.hpp index 1feaca200a..4da3883682 100644 --- a/llarp/constants/files.hpp +++ b/llarp/constants/files.hpp @@ -39,19 +39,10 @@ namespace llarp return "C:\\ProgramData\\Lokinet"; } - inline fs::path GetDefaultConfigFilename() - { - return "lokinet.ini"; - } + inline fs::path GetDefaultConfigFilename() { return "lokinet.ini"; } - inline fs::path GetDefaultConfigPath() - { - return GetDefaultDataDir() / GetDefaultConfigFilename(); - } + inline fs::path GetDefaultConfigPath() { return GetDefaultDataDir() / GetDefaultConfigFilename(); } - inline fs::path GetDefaultBootstrap() - { - return GetDefaultDataDir() / "bootstrap.signed"; - } + inline fs::path GetDefaultBootstrap() { return GetDefaultDataDir() / "bootstrap.signed"; } } // namespace llarp diff --git a/llarp/contact/client_contact.cpp b/llarp/contact/client_contact.cpp index b310961804..07111faddb 100644 --- a/llarp/contact/client_contact.cpp +++ b/llarp/contact/client_contact.cpp @@ -19,10 +19,7 @@ namespace llarp exit_policy{std::move(policy)} {} - ClientContact::ClientContact(std::string&& buf) - { - bt_decode(oxenc::bt_dict_consumer{buf}); - } + ClientContact::ClientContact(std::string&& buf) { bt_decode(oxenc::bt_dict_consumer{buf}); } ClientContact ClientContact::generate( Ed25519PrivateData&& private_data, @@ -55,10 +52,7 @@ namespace llarp protos = proto; } - void ClientContact::_regenerate() - { - log::debug(logcat, "ClientContact regenerated with updated fields!"); - } + void ClientContact::_regenerate() { log::debug(logcat, "ClientContact regenerated with updated fields!"); } void ClientContact::bt_encode(std::vector& buf) const { diff --git a/llarp/contact/client_contact.hpp b/llarp/contact/client_contact.hpp index e15a0c623a..7b3a63faa1 100644 --- a/llarp/contact/client_contact.hpp +++ b/llarp/contact/client_contact.hpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include @@ -36,16 +36,6 @@ namespace llarp class SessionEndpoint; } - enum protocol_flag : uint16_t - { - CONTROL = 1 << 0, - IPV4 = 1 << 1, - IPV6 = 1 << 2, - EXIT = 1 << 3, - AUTH = 1 << 4, - TCP2QUIC = 1 << 5, - }; - // TESTNET: inline static constexpr auto CC_PUBLISH_INTERVAL{30s}; @@ -58,7 +48,7 @@ namespace llarp to the client instance - "p" : supported protocols indicating the traffic accepted by the client instance; this indicates if the client is embedded and therefore requires a tunneled connection. Serialized as a bitwise flag of - above protocol_flag enums + protocol_flag enums (llarp/net/policy.hpp) - "s" : (optional) SRV records for lokinet DNS lookup */ struct ClientContact diff --git a/llarp/contact/client_intro.cpp b/llarp/contact/client_intro.cpp index 41b64a3700..87b73e0205 100644 --- a/llarp/contact/client_intro.cpp +++ b/llarp/contact/client_intro.cpp @@ -4,10 +4,7 @@ namespace llarp { static auto logcat = log::Cat("client-intro"); - ClientIntro::ClientIntro(oxenc::bt_dict_consumer&& btdc) - { - bt_decode(std::move(btdc)); - } + ClientIntro::ClientIntro(oxenc::bt_dict_consumer&& btdc) { bt_decode(std::move(btdc)); } ClientIntro::ClientIntro(std::string_view buf) : ClientIntro{oxenc::bt_dict_consumer{buf}} {} diff --git a/llarp/contact/contactdb.cpp b/llarp/contact/contactdb.cpp index 6bc0e5582c..be47f0bd1c 100644 --- a/llarp/contact/contactdb.cpp +++ b/llarp/contact/contactdb.cpp @@ -38,9 +38,6 @@ namespace llarp return obj; } - void ContactDB::put_cc(EncryptedClientContact enc) - { - _cc_nodes->put_node(enc); - } + void ContactDB::put_cc(EncryptedClientContact enc) { _cc_nodes->put_node(enc); } } // namespace llarp diff --git a/llarp/contact/keys.cpp b/llarp/contact/keys.cpp index 68467b285b..d7a347d4f1 100644 --- a/llarp/contact/keys.cpp +++ b/llarp/contact/keys.cpp @@ -13,10 +13,7 @@ namespace llarp return true; } - std::string PubKey::to_string() const - { - return oxenc::to_base32z(begin(), end()); - } + std::string PubKey::to_string() const { return oxenc::to_base32z(begin(), end()); } PubKey& PubKey::operator=(const uint8_t* ptr) { @@ -30,18 +27,9 @@ namespace llarp return *this; } - bool PubKey::operator<(const PubKey& other) const - { - return as_array() < other.as_array(); - } + bool PubKey::operator<(const PubKey& other) const { return as_array() < other.as_array(); } - bool PubKey::operator==(const PubKey& other) const - { - return as_array() == other.as_array(); - } + bool PubKey::operator==(const PubKey& other) const { return as_array() == other.as_array(); } - bool PubKey::operator!=(const PubKey& other) const - { - return !(*this == other); - } + bool PubKey::operator!=(const PubKey& other) const { return !(*this == other); } } // namespace llarp diff --git a/llarp/contact/keys.hpp b/llarp/contact/keys.hpp index f0b7471a2a..92ab9516fb 100644 --- a/llarp/contact/keys.hpp +++ b/llarp/contact/keys.hpp @@ -3,7 +3,6 @@ #include #include #include -#include /** TODO: - re-configure string_view and ustring_view methods after deprecating RouterID diff --git a/llarp/contact/router_id.hpp b/llarp/contact/router_id.hpp index 5283945707..b029271dfd 100644 --- a/llarp/contact/router_id.hpp +++ b/llarp/contact/router_id.hpp @@ -40,10 +40,7 @@ namespace llarp } }; - inline bool operator==(const RouterID& lhs, const RouterID& rhs) - { - return lhs.as_array() == rhs.as_array(); - } + inline bool operator==(const RouterID& lhs, const RouterID& rhs) { return lhs.as_array() == rhs.as_array(); } } // namespace llarp namespace std diff --git a/llarp/contact/sns.cpp b/llarp/contact/sns.cpp index 30eb692538..64162f14f6 100644 --- a/llarp/contact/sns.cpp +++ b/llarp/contact/sns.cpp @@ -7,10 +7,7 @@ namespace llarp { static auto logcat = llarp::log::Cat("ONSRecord"); - EncryptedSNSRecord EncryptedSNSRecord::deserialize(std::string_view bt) - { - return EncryptedSNSRecord{bt}; - } + EncryptedSNSRecord EncryptedSNSRecord::deserialize(std::string_view bt) { return EncryptedSNSRecord{bt}; } EncryptedSNSRecord::EncryptedSNSRecord(std::string_view bt) : _bt_payload{bt} { diff --git a/llarp/context.cpp b/llarp/context.cpp index d111543d47..8b81db2fa7 100644 --- a/llarp/context.cpp +++ b/llarp/context.cpp @@ -39,15 +39,9 @@ namespace llarp config = std::move(conf); } - bool Context::is_up() const - { - return router && router->is_running(); - } + bool Context::is_up() const { return router && router->is_running(); } - bool Context::looks_alive() const - { - return router && router->looks_alive(); - } + bool Context::looks_alive() const { return router && router->looks_alive(); } void Context::setup(const RuntimeOptions& opts) { @@ -127,10 +121,7 @@ namespace llarp close_waiter = std::make_unique>(); } - bool Context::is_stopping() const - { - return close_waiter.operator bool(); - } + bool Context::is_stopping() const { return close_waiter.operator bool(); } void Context::wait() { diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index e0c22ca200..dc2d96d3a5 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -344,15 +344,9 @@ namespace llarp return 0 == crypto_scalarmult_ed25519_noclamp(derived, h.data(), root_pubkey.data()); } - void crypto::randomize(uint8_t* buf, size_t len) - { - randombytes(buf, len); - } + void crypto::randomize(uint8_t* buf, size_t len) { randombytes(buf, len); } - void crypto::randbytes(uint8_t* ptr, size_t sz) - { - randombytes((unsigned char*)ptr, sz); - } + void crypto::randbytes(uint8_t* ptr, size_t sz) { randombytes((unsigned char*)ptr, sz); } Ed25519SecretKey crypto::generate_identity() { @@ -394,10 +388,7 @@ namespace llarp } #endif - const uint8_t* seckey_to_pubkey(const Ed25519SecretKey& sec) - { - return sec.data() + 32; - } + const uint8_t* seckey_to_pubkey(const Ed25519SecretKey& sec) { return sec.data() + 32; } // Called during static initialization to initialize libsodium. (The CSRNG return is // not useful, but just here to get this called during static initialization of `csrng`). diff --git a/llarp/crypto/types.cpp b/llarp/crypto/types.cpp index 3b4b6d20b6..6246a88d38 100644 --- a/llarp/crypto/types.cpp +++ b/llarp/crypto/types.cpp @@ -15,10 +15,7 @@ namespace llarp { static auto logcat = log::Cat("cryptoutils"); - PubKey Ed25519SecretKey::to_pubkey() const - { - return PubKey(data() + 32); - } + PubKey Ed25519SecretKey::to_pubkey() const { return PubKey(data() + 32); } bool Ed25519SecretKey::load_from_file(const fs::path& fname) { @@ -132,10 +129,7 @@ namespace llarp xor_nonce = xhash.data(); // truncate 32 -> 24 } - shared_kx_data shared_kx_data::generate() - { - return shared_kx_data{crypto::generate_identity()}; - } + shared_kx_data shared_kx_data::generate() { return shared_kx_data{crypto::generate_identity()}; } // TESTNET: TODO: check if the libsodium functions ever actually fail... diff --git a/llarp/dns/message.cpp b/llarp/dns/message.cpp index f0c4b18453..22a7caba69 100644 --- a/llarp/dns/message.cpp +++ b/llarp/dns/message.cpp @@ -3,7 +3,7 @@ #include "dns.hpp" #include "srv_data.hpp" -#include +#include #include #include @@ -54,10 +54,7 @@ namespace llarp::dns return true; } - nlohmann::json MessageHeader::ToJSON() const - { - return nlohmann::json{}; - } + nlohmann::json MessageHeader::ToJSON() const { return nlohmann::json{}; } Message::Message(Message&& other) : hdr_id(std::move(other.hdr_id)), @@ -85,10 +82,7 @@ namespace llarp::dns additional.resize(size_t(hdr._ar_count)); } - Message::Message(const Question& question) : hdr_id{0}, hdr_fields{} - { - questions.emplace_back(question); - } + Message::Message(const Question& question) : hdr_id{0}, hdr_fields{} { questions.emplace_back(question); } bool Message::Encode(llarp_buffer_t* buf) const { @@ -172,10 +166,7 @@ namespace llarp::dns } } - static constexpr uint16_t reply_flags(uint16_t setbits) - { - return setbits | flags_QR | flags_AA | flags_RA; - } + static constexpr uint16_t reply_flags(uint16_t setbits) { return setbits | flags_QR | flags_AA | flags_RA; } void Message::add_reply(std::string name, RR_TTL_t ttl) { diff --git a/llarp/dns/platform.cpp b/llarp/dns/platform.cpp index 4ecc1c916f..bc16de54f0 100644 --- a/llarp/dns/platform.cpp +++ b/llarp/dns/platform.cpp @@ -2,10 +2,7 @@ namespace llarp::dns { - void Multi_Platform::add_impl(std::unique_ptr impl) - { - m_Impls.emplace_back(std::move(impl)); - } + void Multi_Platform::add_impl(std::unique_ptr impl) { m_Impls.emplace_back(std::move(impl)); } void Multi_Platform::set_resolver(unsigned int index, oxen::quic::Address dns, bool global) { diff --git a/llarp/dns/question.cpp b/llarp/dns/question.cpp index 6c7e4ea195..b04e14201f 100644 --- a/llarp/dns/question.cpp +++ b/llarp/dns/question.cpp @@ -93,10 +93,7 @@ namespace llarp::dns 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 { diff --git a/llarp/dns/server.cpp b/llarp/dns/server.cpp index a917e82f0e..c43a93148c 100644 --- a/llarp/dns/server.cpp +++ b/llarp/dns/server.cpp @@ -597,10 +597,7 @@ namespace llarp::dns return std::nullopt; } - void Server::add_resolver(std::weak_ptr resolver) - { - _resolvers.insert(resolver); - } + void Server::add_resolver(std::weak_ptr resolver) { _resolvers.insert(resolver); } void Server::add_resolver(std::shared_ptr resolver) { @@ -608,10 +605,7 @@ namespace llarp::dns add_resolver(std::weak_ptr{resolver}); } - void Server::add_packet_source(std::weak_ptr pkt) - { - _packet_sources.push_back(pkt); - } + void Server::add_packet_source(std::weak_ptr pkt) { _packet_sources.push_back(pkt); } void Server::add_packet_source(std::shared_ptr pkt) { diff --git a/llarp/dns/server.hpp b/llarp/dns/server.hpp index 89be074512..471cf2c211 100644 --- a/llarp/dns/server.hpp +++ b/llarp/dns/server.hpp @@ -3,10 +3,9 @@ #include "message.hpp" #include "platform.hpp" -#include #include #include -#include +#include #include #include diff --git a/llarp/ev/loop.cpp b/llarp/ev/loop.cpp index 723387c039..839deba878 100644 --- a/llarp/ev/loop.cpp +++ b/llarp/ev/loop.cpp @@ -6,10 +6,7 @@ namespace llarp { static auto logcat = log::Cat("EventLoop"); - std::shared_ptr EventLoop::make() - { - return std::shared_ptr{new EventLoop{}}; - } + std::shared_ptr EventLoop::make() { return std::shared_ptr{new EventLoop{}}; } EventLoop::EventLoop() : _loop{std::make_shared()} {} diff --git a/llarp/ev/loop.hpp b/llarp/ev/loop.hpp index 3d297508ac..153b3efe5d 100644 --- a/llarp/ev/loop.hpp +++ b/llarp/ev/loop.hpp @@ -2,7 +2,7 @@ #include "types.hpp" -#include +#include #include #include #include diff --git a/llarp/ev/tcp.cpp b/llarp/ev/tcp.cpp index 31c818c15e..25279e1ed3 100644 --- a/llarp/ev/tcp.cpp +++ b/llarp/ev/tcp.cpp @@ -1,6 +1,6 @@ #include "tcp.hpp" -#include +#include #include namespace llarp diff --git a/llarp/ev/udp.cpp b/llarp/ev/udp.cpp index 182450cb9d..413d4433e3 100644 --- a/llarp/ev/udp.cpp +++ b/llarp/ev/udp.cpp @@ -18,10 +18,7 @@ namespace llarp _local = socket->address(); } - UDPHandle::~UDPHandle() - { - socket.reset(); - } + UDPHandle::~UDPHandle() { socket.reset(); } io_result UDPHandle::_send_impl( const oxen::quic::Path& path, std::byte* buf, size_t size, uint8_t ecn, size_t& n_pkts) diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index fefb46df0d..ab59cde7a6 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -17,10 +17,7 @@ namespace llarp::handlers _is_snode_service{_router.is_service_node()} {} - const std::shared_ptr& SessionEndpoint::loop() - { - return _router.loop(); - } + const std::shared_ptr& SessionEndpoint::loop() { return _router.loop(); } void SessionEndpoint::tick(std::chrono::milliseconds now) { @@ -96,13 +93,13 @@ namespace llarp::handlers _auth_tokens.merge(net_config.exit_auths); } - uint16_t protoflags = protocol_flag::TCP2QUIC; + uint16_t protoflags = meta::to_underlying(protocol_flag::TCP2QUIC); if (_router.using_tun_if()) - protoflags |= _is_v4 ? protocol_flag::IPV4 : protocol_flag::IPV6; + protoflags |= meta::to_underlying(_is_v4 ? protocol_flag::IPV4 : protocol_flag::IPV6); if (_is_exit_node) - protoflags |= protocol_flag::EXIT; + protoflags |= meta::to_underlying(protocol_flag::EXIT); auto& key_manager = _router.key_manager(); @@ -140,7 +137,7 @@ namespace llarp::handlers update_and_publish_localcc(get_current_client_intros(), _srv_records); } - static std::atomic testnet_trigger = false; + // static std::atomic testnet_trigger = false; void SessionEndpoint::start_tickers() { @@ -155,24 +152,25 @@ namespace llarp::handlers }, true); - if (not testnet_trigger) - { - testnet_trigger = true; - - _router.loop()->call_later(5s, [this]() { - try - { - RouterID cpk{oxenc::from_base32z("ccaocb1w9hqspyeog3xfipb1cubnc93bze7bhtruwp1qy7mhkseo")}; - log::info(logcat, "Beginning session init to client: {}", cpk.to_network_address(false)); - _initiate_session( - NetworkAddress::from_pubkey(cpk, true), [](ip_v) { log::critical(logcat, "FUCK YEAH"); }); - } - catch (const std::exception& e) - { - log::critical(logcat, "Failed to parse client netaddr: {}", e.what()); - } - }); - } + // if (not testnet_trigger) + // { + // testnet_trigger = true; + + // _router.loop()->call_later(5s, [this]() { + // try + // { + // RouterID cpk{oxenc::from_base32z("4g96taie3et7dbkumk5x6rycskaxxsgjeiunpe61469z1gsbfkuo")}; + // log::info(logcat, "Beginning session init to client: {}", cpk.to_network_address(false)); + // _initiate_session( + // NetworkAddress::from_pubkey(cpk, true), [](ip_v) { log::critical(logcat, "FUCK YEAH"); + // }); + // } + // catch (const std::exception& e) + // { + // log::critical(logcat, "Failed to parse client netaddr: {}", e.what()); + // } + // }); + // } } else log::info(logcat, "SessionEndpoint configured to NOT publish ClientContact..."); @@ -485,7 +483,7 @@ namespace llarp::handlers { bool ret{true}; - log::critical(logcat, "Publishing new EncryptedClientContact: {}", ecc.bt_payload()); + log::trace(logcat, "Publishing new EncryptedClientContact: {}", ecc.bt_payload()); { Lock_t l{paths_mutex}; @@ -810,29 +808,17 @@ namespace llarp::handlers _address_map.insert_or_assign(std::move(local), std::move(remote)); } - void SessionEndpoint::unmap_local_addr_by_remote(const NetworkAddress& remote) - { - _address_map.unmap(remote); - } + void SessionEndpoint::unmap_local_addr_by_remote(const NetworkAddress& remote) { _address_map.unmap(remote); } - void SessionEndpoint::unmap_remote_by_name(const std::string& name) - { - _address_map.unmap(name); - } + void SessionEndpoint::unmap_remote_by_name(const std::string& name) { _address_map.unmap(name); } void SessionEndpoint::map_remote_to_local_range(NetworkAddress remote, IPRange range) { _range_map.insert_or_assign(std::move(range), std::move(remote)); } - void SessionEndpoint::unmap_local_range_by_remote(const NetworkAddress& remote) - { - _range_map.unmap(remote); - } + void SessionEndpoint::unmap_local_range_by_remote(const NetworkAddress& remote) { _range_map.unmap(remote); } - void SessionEndpoint::unmap_range_by_name(const std::string& name) - { - _range_map.unmap(name); - } + void SessionEndpoint::unmap_range_by_name(const std::string& name) { _range_map.unmap(name); } } // namespace llarp::handlers diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 48b92f6a2b..661132ce8a 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -392,15 +391,9 @@ namespace llarp::handlers }); } - static bool is_random_snode(const dns::Message& msg) - { - return msg.questions[0].IsName("random.snode"); - } + 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 bool is_localhost_loki(const dns::Message& msg) { return msg.questions[0].IsLocalhost(); } static dns::Message& clear_dns_message(dns::Message& msg) { @@ -793,10 +786,7 @@ namespace llarp::handlers return true; } - bool TunEndpoint::supports_ipv6() const - { - return ipv6_enabled; - } + bool TunEndpoint::supports_ipv6() const { return ipv6_enabled; } // FIXME: pass in which question it should be addressing bool TunEndpoint::should_hook_dns_message(const dns::Message& msg) const @@ -828,20 +818,11 @@ namespace llarp::handlers return false; } - std::string TunEndpoint::get_if_name() const - { - return _if_name; - } + std::string TunEndpoint::get_if_name() const { return _if_name; } - bool TunEndpoint::is_service_node() const - { - return _router.is_service_node(); - } + bool TunEndpoint::is_service_node() const { return _router.is_service_node(); } - bool TunEndpoint::is_exit_node() const - { - return _router.is_exit_node(); - } + bool TunEndpoint::is_exit_node() const { return _router.is_exit_node(); } bool TunEndpoint::stop() { @@ -960,14 +941,13 @@ namespace llarp::handlers } } - // handles an outbound packet going OUT to the network + // handles an outbound packet going OUT from user -> network void TunEndpoint::handle_outbound_packet(IPPacket pkt) { ip_v src, dest; - auto pkt_is_ipv4 = pkt.is_ipv4(); - log::debug(logcat, "outbound packet: {}", pkt.info_line()); + log::trace(logcat, "outbound packet: {}: {}", pkt.info_line(), buffer_printer{pkt.uview()}); if (pkt_is_ipv4) { @@ -980,7 +960,7 @@ namespace llarp::handlers dest = pkt.dest_ipv6(); } - log::debug(logcat, "src:{}, dest:{}", src, dest); + log::trace(logcat, "src:{}, dest:{}", src, dest); if constexpr (llarp::platform::is_apple) { @@ -999,12 +979,7 @@ namespace llarp::handlers if (auto session = _router.session_endpoint()->get_session(remote)) { - log::debug( - logcat, - "Dispatching outbound {}B packet for session (remote: {}): {}", - pkt.size(), - remote, - buffer_printer{pkt.uview()}); + log::info(logcat, "Dispatching outbound {}B packet for session (remote: {})", pkt.size(), remote); session->send_path_data_message(std::move(pkt).steal_payload()); } else @@ -1046,11 +1021,11 @@ namespace llarp::handlers else pkt.update_ipv6_address(std::get(src), std::get(dest)); - log::debug(logcat, "Rewritten packet: {}: {}", pkt.info_line(), buffer_printer{pkt.uview()}); + log::trace(logcat, "Rewritten packet: {}: {}", pkt.info_line(), buffer_printer{pkt.uview()}); send_packet_to_net_if(std::move(pkt)); } - // handles an inbound packet coming IN from the network + // handles an inbound packet coming IN from network -> user bool TunEndpoint::handle_inbound_packet( IPPacket pkt, NetworkAddress remote, bool is_exit_session, bool is_outbound_session) { @@ -1060,7 +1035,7 @@ namespace llarp::handlers if (is_exit_session and is_outbound_session) { - log::debug(logcat, "inbound exit session pkt: {}", pkt.info_line()); + log::info(logcat, "inbound exit session pkt: {}", pkt.info_line()); // we are receiving traffic from a session to a remote exit node if (pkt_is_ipv4) { @@ -1097,7 +1072,7 @@ namespace llarp::handlers { if (is_exit_session and not is_outbound_session) { - log::debug(logcat, "inbound exit session pkt: {}", pkt.info_line()); + log::info(logcat, "inbound exit session pkt: {}", pkt.info_line()); // we are receiving traffic from a session to a local exit node if (not is_allowing_traffic(pkt)) return false; @@ -1109,7 +1084,7 @@ namespace llarp::handlers } else { - log::debug(logcat, "inbound service session pkt: {}", pkt.info_line()); + log::info(logcat, "inbound service session pkt: {}", pkt.info_line()); // we are receiving hidden service traffic if (pkt_is_ipv4) dest = _local_addr.to_ipv4(); @@ -1123,7 +1098,7 @@ namespace llarp::handlers return false; } - log::debug(logcat, "src:{}, dest:{}", src, dest); + log::trace(logcat, "src:{}, dest:{}", src, dest); rewrite_and_send_packet(std::move(pkt), src, dest); @@ -1139,10 +1114,7 @@ namespace llarp::handlers bool TunEndpoint::is_allowing_traffic(const IPPacket& pkt) const { - if (auto exitPolicy = get_traffic_policy()) - return exitPolicy->allow_ip_traffic(pkt); - - return true; + return _traffic_policy ? _traffic_policy->allow_ip_traffic(pkt) : true; } bool TunEndpoint::has_mapping_to_remote(const NetworkAddress& addr) const @@ -1155,10 +1127,7 @@ namespace llarp::handlers return _local_ip_mapping.get_local_from_remote(addr); } - oxen::quic::Address TunEndpoint::get_if_addr() const - { - return _local_addr; - } + oxen::quic::Address TunEndpoint::get_if_addr() const { return _local_addr; } TunEndpoint::~TunEndpoint() = default; diff --git a/llarp/handlers/tun.hpp b/llarp/handlers/tun.hpp index f86676aa45..81abff2d5e 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -1,9 +1,8 @@ #pragma once -#include #include #include -#include +#include #include #include #include diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 95e93d3848..9f09d4a2f9 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -186,20 +186,11 @@ namespace llarp } } // namespace link - std::tuple LinkManager::connection_stats() const - { - return ep->connection_stats(); - } + std::tuple LinkManager::connection_stats() const { return ep->connection_stats(); } - size_t LinkManager::get_num_connected_routers(bool active_only) const - { - return ep->num_router_conns(active_only); - } + size_t LinkManager::get_num_connected_routers(bool active_only) const { return ep->num_router_conns(active_only); } - size_t LinkManager::get_num_connected_clients() const - { - return ep->num_client_conns(); - } + size_t LinkManager::get_num_connected_clients() const { return ep->num_client_conns(); } using messages::serialize_response; @@ -555,10 +546,7 @@ namespace llarp return false; } - void LinkManager::close_connection(RouterID rid) - { - return ep->close_connection(rid); - } + void LinkManager::close_connection(RouterID rid) { return ep->close_connection(rid); } void LinkManager::test_reachability(const RouterID& rid, conn_open_hook on_open, conn_closed_hook on_close) { @@ -624,20 +612,11 @@ namespace llarp log::warning(logcat, "Failed to begin establishing connection to {}", remote_addr); } - bool LinkManager::have_connection_to(const RouterID& remote) const - { - return ep->have_conn(remote); - } + bool LinkManager::have_connection_to(const RouterID& remote) const { return ep->have_conn(remote); } - bool LinkManager::have_service_connection_to(const RouterID& remote) const - { - return ep->have_service_conn(remote); - } + bool LinkManager::have_service_connection_to(const RouterID& remote) const { return ep->have_service_conn(remote); } - bool LinkManager::have_client_connection_to(const RouterID& remote) const - { - return ep->have_client_conn(remote); - } + bool LinkManager::have_client_connection_to(const RouterID& remote) const { return ep->have_client_conn(remote); } void LinkManager::close_all_links() { @@ -686,10 +665,7 @@ namespace llarp } } - bool LinkManager::is_service_node() const - { - return _is_service_node; - } + bool LinkManager::is_service_node() const { return _is_service_node; } // TODO: this? perhaps no longer necessary in the same way? void LinkManager::check_persisting_conns(std::chrono::milliseconds) @@ -699,10 +675,7 @@ namespace llarp } // TODO: this - nlohmann::json LinkManager::extract_status() const - { - return {}; - } + nlohmann::json LinkManager::extract_status() const { return {}; } void LinkManager::connect_to_keep_alive(size_t num_conns) { @@ -1032,7 +1005,7 @@ namespace llarp void LinkManager::_handle_resolve_sns(oxen::quic::message m, std::optional inner_body) { - log::critical(logcat, "Received request to publish client contact!"); + log::trace(logcat, "Received request to publish client contact!"); std::string name_hash; @@ -1064,14 +1037,11 @@ namespace llarp }); } - void LinkManager::handle_resolve_sns(oxen::quic::message m) - { - return _handle_resolve_sns(std::move(m)); - } + void LinkManager::handle_resolve_sns(oxen::quic::message m) { return _handle_resolve_sns(std::move(m)); } void LinkManager::_handle_publish_cc(oxen::quic::message m, std::optional inner_body) { - log::critical(logcat, "Received request to publish client contact!"); + log::trace(logcat, "Received request to publish client contact!"); EncryptedClientContact enc; @@ -1157,14 +1127,11 @@ namespace llarp }); } - void LinkManager::handle_publish_cc(oxen::quic::message m) - { - return _handle_publish_cc(std::move(m)); - } + void LinkManager::handle_publish_cc(oxen::quic::message m) { return _handle_publish_cc(std::move(m)); } void LinkManager::_handle_find_cc(oxen::quic::message m, std::optional inner_body) { - log::critical(logcat, "Received request to find client contact!"); + log::trace(logcat, "Received request to find client contact!"); dht::Key_t dht_key; @@ -1251,10 +1218,7 @@ namespace llarp } } - void LinkManager::handle_find_cc(oxen::quic::message m) - { - return _handle_find_cc(std::move(m)); - } + void LinkManager::handle_find_cc(oxen::quic::message m) { return _handle_find_cc(std::move(m)); } void LinkManager::handle_path_build(oxen::quic::message m, const RouterID& from) { @@ -1358,7 +1322,7 @@ namespace llarp void LinkManager::_handle_path_control(oxen::quic::message m, std::optional inner_body) { - log::debug(logcat, "{} called", __PRETTY_FUNCTION__); + log::trace(logcat, "{} called", __PRETTY_FUNCTION__); HopID hop_id; std::string payload; @@ -1495,10 +1459,7 @@ namespace llarp }); } - void LinkManager::handle_path_control(oxen::quic::message m) - { - return _handle_path_control(std::move(m)); - } + void LinkManager::handle_path_control(oxen::quic::message m) { return _handle_path_control(std::move(m)); } void LinkManager::handle_path_data_message(bstring data) { @@ -1537,7 +1498,7 @@ namespace llarp hop.kx.xor_nonce); } - log::info(logcat, "Received path data for local client: {}", buffer_printer{payload}); + log::trace(logcat, "Received path data for local client: {}", buffer_printer{payload}); NetworkAddress sender; bstring data; @@ -1688,7 +1649,7 @@ namespace llarp void LinkManager::_handle_initiate_session(oxen::quic::message m, std::optional inner_body) { - log::debug(logcat, "{} called", __PRETTY_FUNCTION__); + log::trace(logcat, "{} called", __PRETTY_FUNCTION__); NetworkAddress initiator; SessionTag tag; @@ -1731,7 +1692,7 @@ namespace llarp std::move(kx_data), use_tun)) { - log::critical(logcat, "InboundSession configured successfully!"); + log::debug(logcat, "InboundSession configured successfully!"); return m.respond(messages::OK_RESPONSE); } diff --git a/llarp/link/tunnel.cpp b/llarp/link/tunnel.cpp index 913005385d..2b97ec11ee 100644 --- a/llarp/link/tunnel.cpp +++ b/llarp/link/tunnel.cpp @@ -12,14 +12,8 @@ namespace llarp _tls_creds{oxen::quic::GNUTLSCreds::make_from_ed_keys(TUNNEL_SEED, TUNNEL_PUBKEY)} {} - std::shared_ptr QUICTunnel::make(Router& r) - { - return r.loop()->template make_shared(r); - } + std::shared_ptr QUICTunnel::make(Router& r) { return r.loop()->template make_shared(r); } - uint16_t QUICTunnel::listen() - { - return {}; - } + uint16_t QUICTunnel::listen() { return {}; } } // namespace llarp diff --git a/llarp/lokinet_shared.cpp b/llarp/lokinet_shared.cpp index 75fad25cea..2a1d41b96c 100644 --- a/llarp/lokinet_shared.cpp +++ b/llarp/lokinet_shared.cpp @@ -459,10 +459,7 @@ extern "C" return 0; } - struct lokinet_context* EXPORT lokinet_context_new() - { - return new lokinet_context{}; - } + struct lokinet_context* EXPORT lokinet_context_new() { return new lokinet_context{}; } void EXPORT lokinet_context_free(struct lokinet_context* ctx) { diff --git a/llarp/messages/common.hpp b/llarp/messages/common.hpp index 93a2affe1b..9426909a5f 100644 --- a/llarp/messages/common.hpp +++ b/llarp/messages/common.hpp @@ -14,10 +14,7 @@ namespace llarp::messages { static auto logcat = log::Cat("messages"); - inline std::string serialize_response(oxenc::bt_dict supplement = {}) - { - return oxenc::bt_serialize(supplement); - } + inline std::string serialize_response(oxenc::bt_dict supplement = {}) { return oxenc::bt_serialize(supplement); } // ideally STATUS is the first key in a bt-dict, so use a single, early ascii char inline const auto STATUS_KEY = "!"s; diff --git a/llarp/net/ip_headers.hpp b/llarp/net/ip_headers.hpp new file mode 100644 index 0000000000..33d6d315a0 --- /dev/null +++ b/llarp/net/ip_headers.hpp @@ -0,0 +1,124 @@ +#pragma once + +#include "utils.hpp" + +namespace llarp +{ + struct ip_header + { +#if __BYTE_ORDER == __LITTLE_ENDIAN + uint8_t header_len : 4; + uint8_t version : 4; +#else + uint8_t version : 4; + uint8_t header_len : 4; +#endif + uint8_t service_type; + uint16_t total_len; // entire packet size + uint16_t id; + uint16_t frag_off; // fragmentation offset + uint8_t ttl; + uint8_t protocol; + uint16_t checksum; + uint32_t src; + uint32_t dest; + }; + + static_assert(sizeof(ip_header) == 20); + + struct ipv6_header2 + { +#if __BYTE_ORDER == __LITTLE_ENDIAN + uint32_t flow_label : 20; + uint8_t traffic_class; + uint8_t version : 4; +#else + uint8_t version : 4; + uint8_t traffic_class : 8; + uint32_t flow_label : 20; +#endif + // uint16_t pload_len; // payload length + // uint8_t nxt_hdr; // next header (protocol) + // uint8_t hop_limit; + // in6_addr src; + // in6_addr dest; + }; + + // static_assert(sizeof(ipv6_header2) == 40); + + struct ipv6_header + { + union + { +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned char pad_small : 4; + unsigned char version : 4; +#else + unsigned char version : 4; + unsigned char pad_small : 4; +#endif + uint8_t pad[3]; + uint32_t flowlabel; + } preamble; + + uint16_t payload_len; + uint8_t protocol; + uint8_t hoplimit; + in6_addr src; + in6_addr dest; + + /// Returns the flowlabel (stored in network order) in HOST ORDER + uint32_t get_flowlabel() const { return ntohl(preamble.flowlabel & htonl(ipv6_flowlabel_mask)); } + + /// Sets a flowlabel in network order. Takes in a label in HOST ORDER + void set_flowlabel(uint32_t label) + { + // the ipv6 flow label is the last 20 bits in the first 32 bits of the header + preamble.flowlabel = + (htonl(ipv6_flowlabel_mask) & htonl(label)) | (preamble.flowlabel & htonl(~ipv6_flowlabel_mask)); + } + }; + + static_assert(sizeof(ipv6_header) == 40); + + /** TODO: for mobile ipv6, implement ipv6 routing headers + */ + + enum class TCPFLAG : uint8_t + { + FIN = 0x01, + SYN = 0x02, + RST = 0x04, + PUSH = 0x08, + ACK = 0x10, + URG = 0x20 + }; + + struct tcp_header + { + uint16_t src; // src addr or port + uint16_t dest; // dst addr or port + uint32_t seqno; // sequence number + uint32_t ack; // ack number +#if __BYTE_ORDER == __LITTLE_ENDIAN + uint8_t xx : 4; // unused/reserved + uint8_t data_off : 4; // data offset +#else + uint8_t data_off : 4; // data offset + uint8_t xx : 4; // unused/reserved +#endif + uint8_t flags; + uint16_t window; + uint16_t checksum; + uint16_t urg_ptr; // urgent ptr + }; + + struct udp_header + { + uint16_t src; + uint16_t dest; + uint16_t len; // datagram length + uint16_t checksum; + }; + +} // namespace llarp diff --git a/llarp/address/ip_packet.cpp b/llarp/net/ip_packet.cpp similarity index 69% rename from llarp/address/ip_packet.cpp rename to llarp/net/ip_packet.cpp index 1f1e0d99d7..4eba4ca3d3 100644 --- a/llarp/address/ip_packet.cpp +++ b/llarp/net/ip_packet.cpp @@ -1,6 +1,6 @@ #include "ip_packet.hpp" -#include "utils.hpp" +#include "net.hpp" #include #include @@ -15,6 +15,16 @@ namespace llarp { static auto logcat = log::Cat("ip_packet"); + // constexpr auto IP_CSUM_OFF = offsetof(struct ip_header, checksum); + // constexpr auto IP_DST_OFF = offsetof(struct ip_header, dest); + // constexpr auto IP_SRC_OFF = offsetof(struct ip_header, src); + // constexpr auto IP_PROTO_OFF = offsetof(struct ip_header, protocol); + // constexpr auto TCP_DATA_OFF = oxenc::host_to_big(0xF0000000); + constexpr auto TCP_CSUM_OFF = offsetof(struct tcp_header, checksum); + constexpr auto UDP_CSUM_OFF = offsetof(struct udp_header, checksum); + // auto TCP_DATA_OFFSET = htonl(0xF0000000); + // constexpr auto IS_PSEUDO = 0x10; + IPPacket::IPPacket(size_t sz) { if (sz and sz < MIN_PACKET_SIZE) @@ -57,19 +67,20 @@ namespace llarp return ret; } - static const auto v4_header_version = oxenc::host_to_big(uint8_t{4}); - static const auto udp_header_proto = oxenc::host_to_big(uint8_t{17}); + static const auto v4_header_version = oxenc::host_to_big(4); void IPPacket::_init_internals() { _header = reinterpret_cast(data()); _v6_header = reinterpret_cast(data()); + _proto = net::IPProtocol{_header->protocol}; + if (_buf.empty()) return; _is_v4 = _header->version == v4_header_version; - _is_udp = _header->protocol == udp_header_proto; + _is_udp = _proto == net::IPProtocol::UDP; uint16_t src_port = (_is_udp) ? *reinterpret_cast(data() + (static_cast(_header->header_len) * 4)) : 0; @@ -104,9 +115,7 @@ namespace llarp size_t hdr_sz = 0; if (_header->protocol == 0x11) - { hdr_sz = 8; - } else return std::nullopt; @@ -121,29 +130,55 @@ namespace llarp void IPPacket::update_ipv4_address(ipv4 src, ipv4 dst) { - log::debug(logcat, "Setting new source ({}) and destination ({}) IPs", src, dst); + log::trace(logcat, "Setting new source ({}) and destination ({}) IPs", src, dst); - // set new IP addresses - _header->src = oxenc::host_to_big(src.addr); - _header->dest = oxenc::host_to_big(dst.addr); - - switch (_header->protocol) + if (auto ihs = size_t(_header->header_len * 4); ihs <= size()) { - case 6: // TCP - case 17: // UDP - case 136: // UDP-Lite - same checksum place, same 0->0xFFff condition - case 33: // DCCP - _header->checksum = tcpudp_checksum_ipv4( - _header->src, _header->dest, _header->header_len, _header->protocol, _header->checksum); - break; - default: - // do nothing - break; + auto* payload = data() + ihs; + auto payload_size = size() - ihs; + auto frag_off = size_t(oxenc::big_to_host(_header->frag_off) & 0x1Fff) * 8; + + switch (_header->protocol) + { + case 6: // TCP + if (frag_off <= TCP_CSUM_OFF || payload_size >= TCP_CSUM_OFF - frag_off + 2) + { + auto* tcp_hdr = reinterpret_cast(payload); + tcp_hdr->checksum = + utils::ipv4_tcp_checksum_diff(tcp_hdr->checksum, _header->src, _header->dest, src, dst); + } + break; + case 17: // UDP + case 136: // UDP-Lite - same checksum place, same 0->0xFFff condition + if (frag_off <= UDP_CSUM_OFF || payload_size >= UDP_CSUM_OFF + 2) + { + auto* udp_hdr = reinterpret_cast(payload); + udp_hdr->checksum = + utils::ipv4_udp_checksum_diff(udp_hdr->checksum, _header->src, _header->dest, src, dst); + } + break; + case 33: // DCCP + if (frag_off <= UDP_CSUM_OFF || payload_size >= UDP_CSUM_OFF - frag_off + 2) + { + auto* tcp_hdr = reinterpret_cast(payload); + tcp_hdr->checksum = + utils::ipv4_tcp_checksum_diff(tcp_hdr->checksum, _header->src, _header->dest, src, dst); + } + break; + default: + // do nothing + break; + } } - _header->checksum = checksum_ipv4(_header, _header->header_len); + _header->checksum = utils::ipv4_checksum_diff(_header->checksum, _header->src, _header->dest, src, dst); - _init_internals(); + // set new IP addresses + _header->src = oxenc::host_to_big(src.addr); + _header->dest = oxenc::host_to_big(dst.addr); + + _src_addr.set_addr(reinterpret_cast(&_header->src)); + _dst_addr.set_addr(reinterpret_cast(&_header->dest)); } void IPPacket::update_ipv6_address(ipv6 src, ipv6 dst, std::optional flowlabel) @@ -224,7 +259,6 @@ namespace llarp [[fallthrough]]; case 33: // DCCP chksum = tcp_checksum_ipv6(&hdr->src, &hdr->dest, hdr->payload_len, 0); - // ones-complement addition fo 0xFFff is 0; this is verboten if (chksum == 0xFFff) chksum = 0x0000; @@ -254,22 +288,22 @@ namespace llarp if (is_ipv4()) { auto ip_hdr_sz = _header->header_len * 4; - auto pkt_size = (ICMP_HEADER_SIZE + ip_hdr_sz) * 2; - - IPPacket pkt{static_cast(pkt_size)}; - - _header->version = 4; - _header->header_len = 0x05; - _header->service_type = 0; - _header->checksum = 0; - _header->total_len = ntohs(pkt_size); - _header->src = _header->dest; - _header->dest = _header->src; - _header->protocol = 1; // ICMP - _header->ttl = _header->ttl; - _header->frag_off = htons(0b0100000000000000); - - uint16_t* checksum; + size_t pkt_size = (ICMP_HEADER_SIZE + ip_hdr_sz) * 2; + + IPPacket pkt{pkt_size}; + auto* pkt_header = pkt.header(); + + pkt_header->version = 4; + pkt_header->header_len = 0x05; + pkt_header->service_type = 0; + pkt_header->checksum = 0; + pkt_header->total_len = ntohs(pkt_size); + pkt_header->src = _header->dest; + pkt_header->dest = _header->src; + pkt_header->protocol = 1; // ICMP + pkt_header->ttl = pkt_header->ttl; + pkt_header->frag_off = htons(0b0100000000000000); + uint8_t* itr = pkt.data() + ip_hdr_sz; uint8_t* icmp_begin = itr; // type 'destination unreachable' *itr++ = 3; @@ -279,7 +313,7 @@ namespace llarp // checksum + unused oxenc::write_host_as_big(0, itr); - checksum = (uint16_t*)itr; + auto* checksum = (uint16_t*)itr; itr += 4; // next hop mtu is ignored but let's put something here anyways just in case tm @@ -291,13 +325,13 @@ namespace llarp itr += ip_hdr_sz + ICMP_HEADER_SIZE; // calculate checksum of ip header - _header->checksum = checksum_ipv4(_header, _header->header_len); - const auto icmp_size = std::distance(icmp_begin, itr); + pkt_header->checksum = utils::ip_checksum(_buf.data(), ip_hdr_sz); // calculate icmp checksum - *checksum = checksum_ipv4(icmp_begin, icmp_size); + *checksum = utils::ip_checksum(icmp_begin, std::distance(icmp_begin, itr)); return pkt; } + return std::nullopt; } @@ -305,7 +339,7 @@ namespace llarp { bstring data{}; data.reserve(_buf.size()); - std::memcpy(data.data(), _buf.data(), _buf.size()); + std::memmove(data.data(), _buf.data(), _buf.size()); return NetworkPacket{oxen::quic::Path{_src_addr, _dst_addr}, std::move(data)}; } @@ -338,10 +372,7 @@ namespace llarp return true; } - std::vector IPPacket::steal_buffer() && - { - return std::move(_buf); - } + std::vector IPPacket::steal_buffer() && { return std::move(_buf); } std::string IPPacket::steal_payload() && { @@ -350,15 +381,9 @@ namespace llarp return ret; } - std::vector IPPacket::give_buffer() - { - return {_buf}; - } + std::vector IPPacket::give_buffer() { return {_buf}; } - std::string IPPacket::to_string() - { - return {reinterpret_cast(data()), size()}; - } + std::string IPPacket::to_string() { return {reinterpret_cast(data()), size()}; } std::string IPPacket::info_line() const { diff --git a/llarp/address/ip_packet.hpp b/llarp/net/ip_packet.hpp similarity index 94% rename from llarp/address/ip_packet.hpp rename to llarp/net/ip_packet.hpp index efa4f2c7d3..0e4789797a 100644 --- a/llarp/address/ip_packet.hpp +++ b/llarp/net/ip_packet.hpp @@ -1,7 +1,7 @@ #pragma once #include "ip_headers.hpp" -#include "types.hpp" +#include "policy.hpp" #include #include @@ -44,6 +44,8 @@ namespace llarp bool _is_v4{true}; bool _is_udp{false}; + net::IPProtocol _proto; + void _init_internals(); public: @@ -59,20 +61,25 @@ namespace llarp NetworkPacket make_netpkt() &&; + // TESTNET: debug methods + // uint16_t checksum() const { return _is_v4 ? header()->checksum : 0; } + bool is_ipv4() const { return _is_v4; } + net::IPProtocol protocol() const { return _proto; } + const oxen::quic::Address& source() const { return _src_addr; } uint16_t source_port() { return source().port(); } - const oxen::quic::Address& destination() const { return _dst_addr; } - - uint16_t dest_port() { return destination().port(); } - ipv4 source_ipv4() { return _src_addr.to_ipv4(); } ipv6 source_ipv6() { return _src_addr.to_ipv6(); } + const oxen::quic::Address& destination() const { return _dst_addr; } + + uint16_t dest_port() { return destination().port(); } + ipv4 dest_ipv4() const { return _dst_addr.to_ipv4(); } ipv6 dest_ipv6() const { return _dst_addr.to_ipv6(); } @@ -104,8 +111,6 @@ namespace llarp const uint8_t* data() const { return _buf.data(); } - const uint8_t* protocol() const { return _is_v4 ? &header()->protocol : &v6_header()->protocol; } - size_t size() const { return _buf.size(); } bool empty() const { return _buf.empty(); } diff --git a/llarp/net/net.hpp b/llarp/net/net.hpp index 8e6156c88a..64c886a972 100644 --- a/llarp/net/net.hpp +++ b/llarp/net/net.hpp @@ -29,15 +29,9 @@ namespace llarp { - inline int cmp(const in_addr& a, const in_addr& b) - { - return memcmp(&a, &b, sizeof(in_addr)); - } + inline int cmp(const in_addr& a, const in_addr& b) { return memcmp(&a, &b, sizeof(in_addr)); } - inline int cmp(const in6_addr& a, const in6_addr& b) - { - return memcmp(&a, &b, sizeof(in6_addr)); - } + inline int cmp(const in6_addr& a, const in6_addr& b) { return memcmp(&a, &b, sizeof(in6_addr)); } namespace net { @@ -144,15 +138,9 @@ namespace llarp } // namespace llarp -inline bool operator==(const in_addr& a, const in_addr& b) -{ - return llarp::cmp(a, b) == 0; -} +inline bool operator==(const in_addr& a, const in_addr& b) { return llarp::cmp(a, b) == 0; } -inline bool operator==(const in6_addr& a, const in6_addr& b) -{ - return llarp::cmp(a, b) == 0; -} +inline bool operator==(const in6_addr& a, const in6_addr& b) { return llarp::cmp(a, b) == 0; } inline bool operator==(const sockaddr_in& a, const sockaddr_in& b) { @@ -179,15 +167,9 @@ inline bool operator==(const sockaddr& a, const sockaddr& b) } } -inline bool operator<(const in_addr& a, const in_addr& b) -{ - return llarp::cmp(a, b) < 0; -} +inline bool operator<(const in_addr& a, const in_addr& b) { return llarp::cmp(a, b) < 0; } -inline bool operator<(const in6_addr& a, const in6_addr& b) -{ - return llarp::cmp(a, b) < 0; -} +inline bool operator<(const in6_addr& a, const in6_addr& b) { return llarp::cmp(a, b) < 0; } inline bool operator<(const sockaddr_in6& a, const sockaddr_in6& b) { diff --git a/llarp/net/traffic_policy.cpp b/llarp/net/policy.cpp similarity index 75% rename from llarp/net/traffic_policy.cpp rename to llarp/net/policy.cpp index 5cbd8b8083..a9f97b4b29 100644 --- a/llarp/net/traffic_policy.cpp +++ b/llarp/net/policy.cpp @@ -1,4 +1,6 @@ -#include "traffic_policy.hpp" +#include "policy.hpp" + +#include "ip_packet.hpp" #include #include @@ -8,25 +10,24 @@ namespace llarp::net static auto logcat = log::Cat("TrafficPolicy"); // Two functions copied over from llarp/net/ip_packet_old.hpp - std::string IPProtocolName(IPProtocol proto) + static std::string ip_proto_str(IPProtocol proto) { - if (const auto* ent = ::getprotobynumber(static_cast(proto))) + if (const auto* ent = ::getprotobynumber(meta::to_underlying(proto))) { return ent->p_name; } - throw std::invalid_argument{ - "cannot determine protocol name for ip proto '" + std::to_string(static_cast(proto)) + "'"}; + throw std::invalid_argument{"Cannot determine protocol name for IP Protocol: {}"_format(proto)}; } - IPProtocol ParseIPProtocol(std::string data) + static IPProtocol parse_ip_proto(std::string data) { if (const auto* ent = ::getprotobyname(data.c_str())) { return static_cast(ent->p_proto); } - if (starts_with(data, "0x")) + if (data.starts_with("0x")) { if (const int intVal = std::stoi(data.substr(2), nullptr, 16); intVal > 0) return static_cast(intVal); @@ -38,13 +39,13 @@ namespace llarp::net ProtocolInfo::ProtocolInfo(std::string_view data) { const auto parts = split(data, "/"); - protocol = ParseIPProtocol(std::string{parts[0]}); + proto = parse_ip_proto(std::string{parts[0]}); if (parts.size() == 2) { uint16_t port_host{}; std::string portStr{parts[1]}; - std::string protoName = IPProtocolName(protocol); + std::string protoName = ip_proto_str(proto); if (const auto* serv = ::getservbyname(portStr.c_str(), protoName.c_str())) { @@ -62,12 +63,9 @@ namespace llarp::net port = std::nullopt; } - bool ProtocolInfo::matches_packet_proto(const IPPacket& pkt) const - { - return pkt.header()->protocol == static_cast>(protocol); - } + bool ProtocolInfo::matches_packet_proto(const IPPacket& pkt) const { return pkt.protocol() == proto; } - bool ExitPolicy::allow_ip_traffic(const IPPacket& pkt) + bool ExitPolicy::allow_ip_traffic(const IPPacket& pkt) const { log::debug(logcat, "{} called", __PRETTY_FUNCTION__); if (protocols.empty() and ranges.empty()) @@ -104,7 +102,7 @@ namespace llarp::net { try { - protocol = IPProtocol{btlc.consume_integer()}; + proto = IPProtocol{btlc.consume_integer()}; if (not btlc.is_finished()) port = btlc.consume_integer(); @@ -120,8 +118,6 @@ namespace llarp::net { port = std::nullopt; - std::vector vals; - try { oxenc::bt_list_consumer btlc{buf}; @@ -143,8 +139,10 @@ namespace llarp::net { try { - btlp.append(static_cast(protocol)); - btlp.append(port.value_or(0)); + btlp.append(meta::to_underlying(proto)); + + if (port.has_value()) + btlp.append(*port); } catch (...) { @@ -157,8 +155,10 @@ namespace llarp::net try { oxenc::bt_list_consumer btlc{std::move(buf)}; - protocol = static_cast(btlc.consume_integer()); - port = btlc.consume_integer(); + proto = IPProtocol{btlc.consume_integer()}; + + if (not btlc.is_finished()) + port = btlc.consume_integer(); } catch (...) { @@ -240,29 +240,29 @@ namespace llarp::net return true; } - nlohmann::json ProtocolInfo::ExtractStatus() const - { - nlohmann::json status{ - {"protocol", static_cast(protocol)}, - }; - if (port) - status["port"] = *port; - return status; - } - - nlohmann::json ExitPolicy::ExtractStatus() const - { - std::vector rangesStatus; - std::transform(ranges.begin(), ranges.end(), std::back_inserter(rangesStatus), [](const auto& range) { - return range.to_string(); - }); - - std::vector protosStatus; - std::transform(protocols.begin(), protocols.end(), std::back_inserter(protosStatus), [](const auto& proto) { - return proto.ExtractStatus(); - }); - - return nlohmann::json{{"ranges", rangesStatus}, {"protocols", protosStatus}}; - } + // nlohmann::json ProtocolInfo::ExtractStatus() const + // { + // nlohmann::json status{ + // {"protocol", static_cast(protocol)}, + // }; + // if (port) + // status["port"] = *port; + // return status; + // } + + // nlohmann::json ExitProtocol::ExtractStatus() const + // { + // std::vector rangesStatus; + // std::transform(ranges.begin(), ranges.end(), std::back_inserter(rangesStatus), [](const auto& range) { + // return range.to_string(); + // }); + + // std::vector protosStatus; + // std::transform(protocols.begin(), protocols.end(), std::back_inserter(protosStatus), [](const auto& proto) { + // return proto.ExtractStatus(); + // }); + + // return nlohmann::json{{"ranges", rangesStatus}, {"protocols", protosStatus}}; + // } } // namespace llarp::net diff --git a/llarp/net/policy.hpp b/llarp/net/policy.hpp new file mode 100644 index 0000000000..1b987dbd81 --- /dev/null +++ b/llarp/net/policy.hpp @@ -0,0 +1,123 @@ +#pragma once + +#include "net.hpp" + +#include + +#include + +#include + +namespace llarp +{ + struct IPPacket; + + enum class protocol_flag : uint16_t + { + CONTROL = 1 << 0, + IPV4 = 1 << 1, + IPV6 = 1 << 2, + EXIT = 1 << 3, + AUTH = 1 << 4, + TCP2QUIC = 1 << 5, + }; + + struct ip_protocol + { + enum class type : uint8_t + { + ICMP = 0x01, + IGMP = 0x02, + IPIP = 0x04, + TCP = 0x06, + UDP = 0x11, + GRE = 0x2F, + ICMP6 = 0x3A, + OSPF = 0x59, + PGM = 0x71, + }; + }; + + namespace net + { + enum class IPProtocol : uint8_t + { + ICMP = 0x01, + IGMP = 0x02, + IPIP = 0x04, + TCP = 0x06, + UDP = 0x11, + GRE = 0x2F, + ICMP6 = 0x3A, + OSPF = 0x59, + PGM = 0x71, + }; + + /// information about an IP protocol + struct ProtocolInfo + { + /// ip protocol byte of this protocol + IPProtocol proto; + + /// the layer 3 port IN HOST ORDER FFS + std::optional port{std::nullopt}; + + ProtocolInfo(std::string buf); + + void bt_encode(oxenc::bt_list_producer& btlp) const; + + void bt_decode(oxenc::bt_list_consumer& btlc); + + bool bt_decode(std::string_view buf); + + /// returns true if an ip packet looks like it matches this protocol info + /// returns false otherwise + bool matches_packet_proto(const IPPacket& pkt) const; + + auto operator<=>(const ProtocolInfo& other) const + { + return std::tie(proto, port) <=> std::tie(other.proto, other.port); + } + + bool operator==(const ProtocolInfo& other) const { return (*this <=> other) == 0; } + + bool operator<(const ProtocolInfo& other) const + { + return std::tie(proto, port) < std::tie(other.proto, other.port); + } + + ProtocolInfo() = default; + + explicit ProtocolInfo(std::string_view spec); + }; + + /// information about what exit traffic an endpoint will carry + struct ExitPolicy + { + /// ranges that are explicitly allowed + std::set ranges; + + /// protocols that are explicity allowed + std::set protocols; + + bool empty() const { return ranges.empty() and protocols.empty(); } + + void bt_encode(oxenc::bt_dict_producer&& btdp) const; + + void bt_decode(oxenc::bt_dict_consumer&& btdc); + + bool bt_decode(std::string_view buf); + + auto operator<=>(const ExitPolicy& other) const + { + return std::tie(ranges, protocols) <=> std::tie(other.ranges, other.protocols); + } + + bool operator==(const ExitPolicy& other) const { return (*this <=> other) == 0; } + + /// returns true if we allow the traffic in this ip packet + /// returns false otherwise + bool allow_ip_traffic(const IPPacket& pkt) const; + }; + } // namespace net +} // namespace llarp diff --git a/llarp/net/posix.cpp b/llarp/net/posix.cpp index 9bbcc65e19..e491688e50 100644 --- a/llarp/net/posix.cpp +++ b/llarp/net/posix.cpp @@ -287,8 +287,5 @@ namespace llarp::net const Platform_Impl g_plat{}; - const Platform* Platform::Default_ptr() - { - return &g_plat; - } + const Platform* Platform::Default_ptr() { return &g_plat; } } // namespace llarp::net diff --git a/llarp/net/traffic_policy.hpp b/llarp/net/traffic_policy.hpp deleted file mode 100644 index 653292e2e7..0000000000 --- a/llarp/net/traffic_policy.hpp +++ /dev/null @@ -1,95 +0,0 @@ -#pragma once - -#include -#include - -#include - -#include - -namespace llarp::net -{ - // Copied over from llarp/net/ip_packet_old.hpp... - enum class IPProtocol : uint8_t - { - ICMP = 0x01, - IGMP = 0x02, - IPIP = 0x04, - TCP = 0x06, - UDP = 0x11, - GRE = 0x2F, - ICMP6 = 0x3A, - OSFP = 0x59, - PGM = 0x71, - }; - - /// information about an IP protocol - struct ProtocolInfo - { - /// ip protocol byte of this protocol - IPProtocol protocol; - - /// the layer 3 port IN HOST ORDER FFS - std::optional port; - - ProtocolInfo(std::string buf); - - void bt_encode(oxenc::bt_list_producer& btlp) const; - - void bt_decode(oxenc::bt_list_consumer& btlc); - - bool bt_decode(std::string_view buf); - - nlohmann::json ExtractStatus() const; - - /// returns true if an ip packet looks like it matches this protocol info - /// returns false otherwise - bool matches_packet_proto(const IPPacket& pkt) const; - - auto operator<=>(const ProtocolInfo& other) const - { - return std::tie(protocol, port) <=> std::tie(other.protocol, other.port); - } - - bool operator==(const ProtocolInfo& other) const { return (*this <=> other) == 0; } - - bool operator<(const ProtocolInfo& other) const - { - return std::tie(protocol, port) < std::tie(other.protocol, other.port); - } - - ProtocolInfo() = default; - - explicit ProtocolInfo(std::string_view spec); - }; - - /// information about what exit traffic an endpoint will carry - struct ExitPolicy - { - /// ranges that are explicitly allowed - std::set ranges; - - /// protocols that are explicity allowed - std::set protocols; - - bool empty() const { return ranges.empty() and protocols.empty(); } - - void bt_encode(oxenc::bt_dict_producer&& btdp) const; - - void bt_decode(oxenc::bt_dict_consumer&& btdc); - - bool bt_decode(std::string_view buf); - nlohmann::json ExtractStatus() const; - - auto operator<=>(const ExitPolicy& other) const - { - return std::tie(ranges, protocols) <=> std::tie(other.ranges, other.protocols); - } - - bool operator==(const ExitPolicy& other) const { return (*this <=> other) == 0; } - - /// returns true if we allow the traffic in this ip packet - /// returns false otherwise - bool allow_ip_traffic(const IPPacket& pkt); - }; -} // namespace llarp::net diff --git a/llarp/net/utils.cpp b/llarp/net/utils.cpp new file mode 100644 index 0000000000..e5ffcae6f5 --- /dev/null +++ b/llarp/net/utils.cpp @@ -0,0 +1,139 @@ +#include "utils.hpp" + +namespace llarp +{ + namespace utils + { + static constexpr uint32_t add_u32(uint32_t x) { return uint32_t{x & 0xFFff} + uint32_t{x >> 16}; } + static constexpr uint32_t add_u32(ipv4 x) { return add_u32(oxenc::host_to_big(x.addr)); } + + static constexpr uint32_t sub_u32(uint32_t x) { return add_u32(~x); } + static constexpr uint32_t sub_u32(ipv4 x) { return sub_u32(oxenc::host_to_big(x.addr)); } + + uint16_t ip_checksum(const uint8_t *buf, size_t sz) + { + uint32_t sum = 0; + + while (sz > 1) + { + sum += *(uint16_t *)(buf); + sz -= sizeof(uint16_t); + buf += sizeof(uint16_t); + } + + if (sz != 0) + { + uint16_t x = 0; + *(uint8_t *)&x = *buf; + sum += x; + } + + sum = (sum & 0xFFff) + (sum >> 16); + sum += sum >> 16; + + return uint16_t((~sum) & 0xFFff); + } + + uint16_t ipv4_checksum_diff(uint16_t old_sum, uint32_t old_src, uint32_t old_dest, ipv4 new_src, ipv4 new_dest) + { + uint32_t sum = old_sum + add_u32(old_src) + add_u32(old_dest) + sub_u32(new_src) + sub_u32(new_dest); + + sum = (sum & 0xFFff) + (sum >> 16); + sum += sum >> 16; + + return uint16_t(sum & 0xFFff); + } + + uint16_t ipv4_tcp_checksum_diff( + uint16_t old_sum, uint32_t old_src, uint32_t old_dest, ipv4 new_src, ipv4 new_dest) + { + auto new_sum = ipv4_checksum_diff(old_sum, old_src, old_dest, new_src, new_dest); + return new_sum == 0xFFff ? 0x0000 : new_sum; + } + + uint16_t ipv4_udp_checksum_diff( + uint16_t old_sum, uint32_t old_src, uint32_t old_dest, ipv4 new_src, ipv4 new_dest) + { + if (old_sum == 0x0000) + return old_sum; + + return ipv4_checksum_diff(old_sum, old_src, old_dest, new_src, new_dest); + } + } // namespace utils + + uint16_t csum_add(uint16_t csum, uint16_t rhs) + { + uint32_t res = csum, other = rhs; + res += other; + return static_cast(res + (res < other)); + } + + uint16_t csum_sub(uint16_t csum, uint16_t rhs) { return csum_add(csum, ~rhs); } + + uint16_t from_32_to_16(uint32_t x) + { + /* add up 16-bit and 16-bit for 16+c bit */ + x = (x & 0xffff) + (x >> 16); + /* add up carry.. */ + x = (x & 0xffff) + (x >> 16); + return x; + } + + uint32_t from_64_to_32(uint64_t x) + { + /* add up 32-bit and 32-bit for 32+c bit */ + x = (x & 0xffffffff) + (x >> 32); + /* add up carry.. */ + x = (x & 0xffffffff) + (x >> 32); + return x; + } + + uint16_t fold_csum(uint32_t csum) + { + auto sum = csum; + sum = (sum & 0xffff) + (sum >> 16); + sum = (sum & 0xffff) + (sum >> 16); + return static_cast(~sum); + } + + uint16_t ipv6_checksum_magic( + const struct in6_addr *saddr, const struct in6_addr *daddr, uint32_t len, uint8_t proto, uint32_t sum) + { + uint32_t csum = sum; + + for (size_t i = 0; i < 4; ++i) + { + auto val = static_cast(saddr->s6_addr32[i]); + csum += val; + csum += (csum < val); + } + + for (size_t i = 0; i < 4; ++i) + { + auto val = static_cast(daddr->s6_addr32[i]); + csum += val; + csum += (csum < val); + } + + uint32_t ulen = htonl(len); + uint32_t uproto = htonl(proto); + + csum += ulen; + csum += (csum < ulen); + + csum += uproto; + csum += (csum < uproto); + + return fold_csum(csum); + } + + uint32_t tcp_checksum_ipv6(const struct in6_addr *saddr, const struct in6_addr *daddr, uint32_t len, uint32_t csum) + { + return ~ipv6_checksum_magic(saddr, daddr, len, IPPROTO_TCP, csum); + } + + uint32_t udp_checksum_ipv6(const struct in6_addr *saddr, const struct in6_addr *daddr, uint32_t len, uint32_t csum) + { + return ~ipv6_checksum_magic(saddr, daddr, len, IPPROTO_UDP, csum); + } +} // namespace llarp diff --git a/llarp/net/utils.hpp b/llarp/net/utils.hpp new file mode 100644 index 0000000000..8846da5f7d --- /dev/null +++ b/llarp/net/utils.hpp @@ -0,0 +1,55 @@ +#pragma once + +#include + +namespace llarp +{ + inline constexpr uint32_t ipv6_flowlabel_mask = 0b0000'0000'0000'1111'1111'1111'1111'1111; + + inline constexpr size_t ICMP_HEADER_SIZE{8}; + + // Compares the given ip variant against a quic address + // Returns: + // - true : ip == address + // - false : ip != address + // Error: + // - throws : ip and address are mismatched ipv4 vs ipv6 + inline bool ip_equals_address(const ip_v &ip, const oxen::quic::Address &addr, bool compare_v4) + { + if (compare_v4 and std::holds_alternative(ip)) + return std::get(ip) == addr.to_ipv4(); + + if (not compare_v4 and std::holds_alternative(ip)) + return std::get(ip) == addr.to_ipv6(); + + throw std::invalid_argument{ + "Failed to compare ip variant in desired {} scheme!"_format(compare_v4 ? "ipv4" : "ipv6")}; + } + + namespace utils + { + uint16_t ip_checksum(const uint8_t *buf, size_t sz); + + // Parameters: + // - old_sum : old checksum (NETWORK order!) + // - old_{src,dest} : old src and dest IP's (stored internally in HOST order!) + // - new_{src,dest} : new src and dest IP's (stored internally in HOST order!) + // + // Returns: + // - uint16_t : new checksum (NETWORK order!) + uint16_t ipv4_checksum_diff(uint16_t old_sum, uint32_t old_src, uint32_t old_dest, ipv4 new_src, ipv4 new_dest); + + uint16_t ipv4_tcp_checksum_diff( + uint16_t old_sum, uint32_t old_src, uint32_t old_dest, ipv4 new_src, ipv4 new_dest); + + uint16_t ipv4_udp_checksum_diff( + uint16_t old_sum, uint32_t old_src, uint32_t old_dest, ipv4 new_src, ipv4 new_dest); + + uint16_t ipv6_checksum_diff(); + } // namespace utils + + uint32_t tcp_checksum_ipv6(const struct in6_addr *saddr, const struct in6_addr *daddr, uint32_t len, uint32_t csum); + + uint32_t udp_checksum_ipv6(const struct in6_addr *saddr, const struct in6_addr *daddr, uint32_t len, uint32_t csum); + +} // namespace llarp diff --git a/llarp/net/win32.cpp b/llarp/net/win32.cpp index b670058f24..b11b73fdf0 100644 --- a/llarp/net/win32.cpp +++ b/llarp/net/win32.cpp @@ -1,5 +1,3 @@ -#include "ip.hpp" -#include "ip_range.hpp" #include "net.hpp" #include "net_if.hpp" @@ -196,8 +194,5 @@ namespace llarp::net const Platform_Impl g_plat{}; - const Platform* Platform::Default_ptr() - { - return &g_plat; - } + const Platform* Platform::Default_ptr() { return &g_plat; } } // namespace llarp::net diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index 7e922fca10..ecc4cb2dac 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -33,10 +33,7 @@ namespace llarp throw std::runtime_error{fmt::format("nodedb {} is not a directory", nodedbDir)}; } - std::tuple NodeDB::db_stats() const - { - return {num_rcs(), num_rids(), num_bootstraps()}; - } + std::tuple NodeDB::db_stats() const { return {num_rcs(), num_rids(), num_bootstraps()}; } std::optional NodeDB::get_rc_by_rid(const RouterID& rid) { @@ -215,10 +212,7 @@ namespace llarp return "{}/{}{}"_format(_root.c_str(), pubkey.to_string(), RC_FILE_EXT); } - bool NodeDB::want_rc(const RouterID& rid) const - { - return known_rids.count(rid) and not rc_lookup.contains(rid); - } + bool NodeDB::want_rc(const RouterID& rid) const { return known_rids.count(rid) and not rc_lookup.contains(rid); } void NodeDB::set_bootstrap_routers(BootstrapList& from_router) { @@ -917,15 +911,9 @@ namespace llarp } } - bool NodeDB::has_rc(const RemoteRC& rc) const - { - return known_rcs.count(rc); - } + bool NodeDB::has_rc(const RemoteRC& rc) const { return known_rcs.count(rc); } - bool NodeDB::has_rc(const RouterID& pk) const - { - return rc_lookup.count(pk); - } + bool NodeDB::has_rc(const RouterID& pk) const { return rc_lookup.count(pk); } std::optional NodeDB::get_rc(const RouterID& pk) const { @@ -966,15 +954,9 @@ namespace llarp return ret; } - size_t NodeDB::num_rcs() const - { - return known_rcs.size(); - } + size_t NodeDB::num_rcs() const { return known_rcs.size(); } - size_t NodeDB::num_rids() const - { - return known_rids.size(); - } + size_t NodeDB::num_rids() const { return known_rids.size(); } bool NodeDB::verify_store_gossip_rc(const RemoteRC& rc) { diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 64709f922a..9fe5e115df 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -136,10 +136,7 @@ namespace llarp::path return ret; } - bool Path::operator!=(const Path& other) const - { - return not(*this == other); - } + bool Path::operator!=(const Path& other) const { return not(*this == other); } bool Path::obtain_exit( const Ed25519SecretKey& sk, uint64_t flag, std::string tx_id, std::function func) @@ -169,15 +166,9 @@ namespace llarp::path return send_path_control_message("resolve_sns", ResolveSNS::serialize(name), std::move(func)); } - void Path::enable_exit_traffic() - { - log::info(logcat, "{} {} granted exit", name(), pivot_rid()); - } + void Path::enable_exit_traffic() { log::info(logcat, "{} {} granted exit", name(), pivot_rid()); } - void Path::mark_exit_closed() - { - log::info(logcat, "{} hd its exit closed", name()); - } + void Path::mark_exit_closed() { log::info(logcat, "{} hd its exit closed", name()); } std::string Path::make_path_message(std::string inner_payload) { @@ -211,10 +202,7 @@ namespace llarp::path return _router.send_control_message(upstream_rid(), "path_control", std::move(outer_payload), std::move(func)); } - bool Path::is_ready(std::chrono::milliseconds now) const - { - return _established ? !is_expired(now) : false; - } + bool Path::is_ready(std::chrono::milliseconds now) const { return _established ? !is_expired(now) : false; } std::shared_ptr Path::get_parent() { @@ -224,70 +212,31 @@ namespace llarp::path return nullptr; } - TransitHop Path::edge() const - { - return {hops.front()}; - } + TransitHop Path::edge() const { return {hops.front()}; } - RouterID Path::upstream_rid() - { - return hops.front().router_id(); - } + RouterID Path::upstream_rid() { return hops.front().router_id(); } - const RouterID& Path::upstream_rid() const - { - return hops.front().router_id(); - } + const RouterID& Path::upstream_rid() const { return hops.front().router_id(); } - HopID Path::upstream_txid() - { - return hops.front().txid(); - } + HopID Path::upstream_txid() { return hops.front().txid(); } - const HopID& Path::upstream_txid() const - { - return hops.front().txid(); - } + const HopID& Path::upstream_txid() const { return hops.front().txid(); } - HopID Path::upstream_rxid() - { - return hops.front().rxid(); - } + HopID Path::upstream_rxid() { return hops.front().rxid(); } - const HopID& Path::upstream_rxid() const - { - return hops.front().rxid(); - } + const HopID& Path::upstream_rxid() const { return hops.front().rxid(); } - RouterID Path::pivot_rid() - { - return hops.back().router_id(); - } + RouterID Path::pivot_rid() { return hops.back().router_id(); } - const RouterID& Path::pivot_rid() const - { - return hops.back().router_id(); - } + const RouterID& Path::pivot_rid() const { return hops.back().router_id(); } - HopID Path::pivot_txid() - { - return hops.back().txid(); - } + HopID Path::pivot_txid() { return hops.back().txid(); } - const HopID& Path::pivot_txid() const - { - return hops.back().txid(); - } + const HopID& Path::pivot_txid() const { return hops.back().txid(); } - HopID Path::pivot_rxid() - { - return hops.back().rxid(); - } + HopID Path::pivot_rxid() { return hops.back().rxid(); } - const HopID& Path::pivot_rxid() const - { - return hops.back().rxid(); - } + const HopID& Path::pivot_rxid() const { return hops.back().rxid(); } std::string Path::to_string() const { @@ -354,10 +303,7 @@ namespace llarp::path intro.expiry = llarp::time_now_ms() + path::DEFAULT_LIFETIME; } - bool Path::is_expired(std::chrono::milliseconds now) const - { - return intro.is_expired(now); - } + bool Path::is_expired(std::chrono::milliseconds now) const { return intro.is_expired(now); } std::string Path::name() const { diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index 78a87d3c25..fa678f4d97 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -25,11 +25,6 @@ namespace llarp struct Router; struct Profiling; - // namespace link - // { - // struct LinkManager; - // } - namespace service { struct EncryptedIntroSet; @@ -39,10 +34,6 @@ namespace llarp { using recv_session_dgram_cb = std::function; - /** TODO: - - we only need a vector of RID's for path-building, not RemoteRC's - */ - /// A path we made struct Path : public std::enable_shared_from_this { diff --git a/llarp/path/path_context.cpp b/llarp/path/path_context.cpp index 1982f92065..de894892a4 100644 --- a/llarp/path/path_context.cpp +++ b/llarp/path/path_context.cpp @@ -10,15 +10,9 @@ namespace llarp::path PathContext::PathContext(Router& r) : _r{r} {} - void PathContext::allow_transit() - { - _allow_transit = true; - } + void PathContext::allow_transit() { _allow_transit = true; } - bool PathContext::is_transit_allowed() const - { - return _allow_transit; - } + bool PathContext::is_transit_allowed() const { return _allow_transit; } void PathContext::add_path(std::shared_ptr path) { diff --git a/llarp/path/path_handler.cpp b/llarp/path/path_handler.cpp index 5eed77defa..710fa9c255 100644 --- a/llarp/path/path_handler.cpp +++ b/llarp/path/path_handler.cpp @@ -18,20 +18,11 @@ namespace llarp::path { static auto logcat = log::Cat("pathhandler"); - bool BuildLimiter::Attempt(const RouterID& router) - { - return _edge_limiter.Insert(router); - } + bool BuildLimiter::Attempt(const RouterID& router) { return _edge_limiter.Insert(router); } - void BuildLimiter::Decay(std::chrono::milliseconds now) - { - _edge_limiter.Decay(now); - } + void BuildLimiter::Decay(std::chrono::milliseconds now) { _edge_limiter.Decay(now); } - bool BuildLimiter::Limited(const RouterID& router) const - { - return _edge_limiter.Contains(router); - } + bool BuildLimiter::Limited(const RouterID& router) const { return _edge_limiter.Contains(router); } nlohmann::json BuildStats::ExtractStatus() const { @@ -196,10 +187,7 @@ namespace llarp::path } } - std::chrono::milliseconds PathHandler::now() const - { - return _router.now(); - } + std::chrono::milliseconds PathHandler::now() const { return _router.now(); } // called within the scope of locked mutex void PathHandler::expire_paths(std::chrono::milliseconds now) @@ -358,25 +346,13 @@ namespace llarp::path return true; } - bool PathHandler::is_stopped() const - { - return !_running.load(); - } + bool PathHandler::is_stopped() const { return !_running.load(); } - bool PathHandler::should_remove() const - { - return is_stopped() and num_active_paths() == 0; - } + bool PathHandler::should_remove() const { return is_stopped() and num_active_paths() == 0; } - bool PathHandler::build_cooldown_hit(RouterID edge) const - { - return _router.pathbuild_limiter().Limited(edge); - } + bool PathHandler::build_cooldown_hit(RouterID edge) const { return _router.pathbuild_limiter().Limited(edge); } - bool PathHandler::build_cooldown() const - { - return llarp::time_now_ms() < last_build + build_interval_limit; - } + bool PathHandler::build_cooldown() const { return llarp::time_now_ms() < last_build + build_interval_limit; } size_t PathHandler::should_build_more() const { diff --git a/llarp/profiling.cpp b/llarp/profiling.cpp index 3931debf2d..957f31e8fb 100644 --- a/llarp/profiling.cpp +++ b/llarp/profiling.cpp @@ -123,20 +123,11 @@ namespace llarp return checkIsGood(path_fail, path_success, chances); } - void Profiling::disable() - { - _profiling_disabled.store(true); - } + void Profiling::disable() { _profiling_disabled.store(true); } - void Profiling::enable() - { - _profiling_disabled.store(false); - } + void Profiling::enable() { _profiling_disabled.store(false); } - bool Profiling::is_enabled() const - { - return not _profiling_disabled.load(); - } + bool Profiling::is_enabled() const { return not _profiling_disabled.load(); } bool Profiling::is_bad_for_connect(const RouterID& r, uint64_t chances) { diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index b055e277b0..86a2be9193 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -223,10 +223,7 @@ namespace llarp } } - bool Router::is_fully_meshed() const - { - return num_router_connections() >= _node_db->num_rcs(); - } + bool Router::is_fully_meshed() const { return num_router_connections() >= _node_db->num_rcs(); } void Router::persist_connection_until(const RouterID& remote, std::chrono::milliseconds until) { @@ -244,10 +241,7 @@ namespace llarp return _link_manager->send_control_message(remote, std::move(ep), std::move(body), std::move(func)); } - std::set Router::get_current_remotes() const - { - return _link_manager->get_current_remotes(); - } + std::set Router::get_current_remotes() const { return _link_manager->get_current_remotes(); } void Router::for_each_connection(std::function func) { @@ -695,15 +689,9 @@ namespace llarp }); } - bool Router::is_service_node() const - { - return _is_service_node; - } + bool Router::is_service_node() const { return _is_service_node; } - bool Router::is_exit_node() const - { - return _is_exit_node; - } + bool Router::is_exit_node() const { return _is_exit_node; } bool Router::insufficient_peers() const { @@ -720,10 +708,7 @@ namespace llarp return std::nullopt; } - bool Router::has_whitelist() const - { - return whitelist_received; - } + bool Router::has_whitelist() const { return whitelist_received; } bool Router::appears_decommed() const { @@ -740,20 +725,14 @@ namespace llarp return _is_service_node and has_whitelist() and node_db()->registered_routers().count(local_rid()); } - bool Router::can_test_routers() const - { - return appears_funded() and not _testing_disabled; - } + bool Router::can_test_routers() const { return appears_funded() and not _testing_disabled; } size_t Router::num_router_connections(bool active_only) const { return _link_manager->get_num_connected_routers(active_only); } - size_t Router::num_client_connections() const - { - return _link_manager->get_num_connected_clients(); - } + size_t Router::num_client_connections() const { return _link_manager->get_num_connected_clients(); } void Router::save_rc() { @@ -945,10 +924,7 @@ namespace llarp _last_tick = llarp::time_now_ms(); } - const std::set& Router::get_whitelist() const - { - return _node_db->registered_routers(); - } + const std::set& Router::get_whitelist() const { return _node_db->registered_routers(); } void Router::set_router_whitelist(const std::vector& whitelist) { @@ -1209,14 +1185,8 @@ namespace llarp _loop->call_later(200ms, [this] { cleanup(); }); } - oxen::quic::Address Router::listen_addr() const - { - return _listen_address; - } + oxen::quic::Address Router::listen_addr() const { return _listen_address; } - const llarp::net::Platform& Router::net() const - { - return *llarp::net::Platform::Default_ptr(); - } + const llarp::net::Platform& Router::net() const { return *llarp::net::Platform::Default_ptr(); } } // namespace llarp diff --git a/llarp/router_version.cpp b/llarp/router_version.cpp index 2d882b2b2f..b43cdc60c7 100644 --- a/llarp/router_version.cpp +++ b/llarp/router_version.cpp @@ -15,10 +15,7 @@ namespace llarp : _version(router), _proto(proto) {} - bool RouterVersion::is_compatible_with(const RouterVersion& other) const - { - return _proto == other._proto; - } + bool RouterVersion::is_compatible_with(const RouterVersion& other) const { return _proto == other._proto; } std::string RouterVersion::bt_encode() const { @@ -46,10 +43,7 @@ namespace llarp assert(is_empty()); } - bool RouterVersion::is_empty() const - { - return *this == emptyRouterVersion; - } + bool RouterVersion::is_empty() const { return *this == emptyRouterVersion; } bool RouterVersion::bt_decode(std::string_view buf) { diff --git a/llarp/rpc/json_conversions.cpp b/llarp/rpc/json_conversions.cpp index 68fcd5f52c..cc4fa16c20 100644 --- a/llarp/rpc/json_conversions.cpp +++ b/llarp/rpc/json_conversions.cpp @@ -6,10 +6,7 @@ namespace llarp { static auto logcat = log::Cat("RPC-conversions"); - void to_json(nlohmann::json& j, const IPRange& ipr) - { - j = ipr.to_string(); - } + void to_json(nlohmann::json& j, const IPRange& ipr) { j = ipr.to_string(); } void from_json(const nlohmann::json& j, IPRange& ipr) { diff --git a/llarp/rpc/param_parser.hpp b/llarp/rpc/param_parser.hpp index 401c4f9c1b..e557394eb2 100644 --- a/llarp/rpc/param_parser.hpp +++ b/llarp/rpc/param_parser.hpp @@ -94,10 +94,7 @@ namespace llarp::rpc // false if it advanced beyond the requested name. This is exactly the same as // `d.skip_until(name)`, but is here so we can also overload an equivalent function for json // iteration. - inline bool skip_until(oxenc::bt_dict_consumer& d, std::string_view name) - { - return d.skip_until(name); - } + inline bool skip_until(oxenc::bt_dict_consumer& d, std::string_view name) { return d.skip_until(name); } // Equivalent to the above but for a json object iterator. inline bool skip_until(json_range& it_range, std::string_view name) { diff --git a/llarp/rpc/rpc_request_parser.cpp b/llarp/rpc/rpc_request_parser.cpp index 0d5b6e45df..3d08eed0a8 100644 --- a/llarp/rpc/rpc_request_parser.cpp +++ b/llarp/rpc/rpc_request_parser.cpp @@ -38,10 +38,7 @@ namespace llarp::rpc quiclistener.request.srvProto); } - void parse_request(FindCC& findcc, rpc_input input) - { - get_values(input, "pk", findcc.request.pk); - } + void parse_request(FindCC& findcc, rpc_input input) { get_values(input, "pk", findcc.request.pk); } void parse_request(LookupSnode& lookupsnode, rpc_input input) { diff --git a/llarp/rpc/rpc_server.cpp b/llarp/rpc/rpc_server.cpp index 0a86ef2d7e..913a473a7f 100644 --- a/llarp/rpc/rpc_server.cpp +++ b/llarp/rpc/rpc_server.cpp @@ -532,7 +532,7 @@ namespace llarp::rpc return; } - if (not ends_with(config.request.filename, ".ini")) + if (config.request.filename.ends_with(".ini")) { SetJSONError("Must append '.ini' to filename", config.response); return; diff --git a/llarp/rpc/rpc_server.hpp b/llarp/rpc/rpc_server.hpp index 76d28f44bb..003a2a1b2a 100644 --- a/llarp/rpc/rpc_server.hpp +++ b/llarp/rpc/rpc_server.hpp @@ -70,10 +70,7 @@ namespace llarp::rpc j["result"] = result; } - inline void SetJSONError(std::string_view msg, json& j) - { - j["error"] = msg; - } + inline void SetJSONError(std::string_view msg, json& j) { j["error"] = msg; } class RPCServer { diff --git a/llarp/session/session.cpp b/llarp/session/session.cpp index a72dfd883e..842c530fde 100644 --- a/llarp/session/session.cpp +++ b/llarp/session/session.cpp @@ -52,10 +52,7 @@ namespace llarp::session _current_path->upstream_rid(), _current_path->make_path_message(std::move(intermediate_payload))); } - void BaseSession::recv_path_data_message(bstring body) - { - _current_path->recv_path_data_message(std::move(body)); - } + void BaseSession::recv_path_data_message(bstring body) { _current_path->recv_path_data_message(std::move(body)); } void BaseSession::set_new_current_path(std::shared_ptr _new_path) { @@ -203,10 +200,7 @@ namespace llarp::session return obj; } - void OutboundSession::blacklist_snode(const RouterID& snode) - { - (void)snode; - } + void OutboundSession::blacklist_snode(const RouterID& snode) { (void)snode; } bool OutboundSession::is_path_dead(std::shared_ptr, std::chrono::milliseconds dlt) { @@ -346,8 +340,5 @@ namespace llarp::session std::move(kx_data)} {} - void InboundSession::set_new_tag(const SessionTag& tag) - { - _tag = tag; - } + void InboundSession::set_new_tag(const SessionTag& tag) { _tag = tag; } } // namespace llarp::session diff --git a/llarp/session/session.hpp b/llarp/session/session.hpp index 0a5f521130..67c08eed24 100644 --- a/llarp/session/session.hpp +++ b/llarp/session/session.hpp @@ -1,10 +1,10 @@ #pragma once #include -#include #include #include #include +#include #include #include diff --git a/llarp/simulation/sim_context.cpp b/llarp/simulation/sim_context.cpp index c0de6c0d33..a98a74e30e 100644 --- a/llarp/simulation/sim_context.cpp +++ b/llarp/simulation/sim_context.cpp @@ -20,9 +20,6 @@ namespace llarp return itr->second; } - void Simulation::DelNode(const std::string& name) - { - m_Nodes.erase(name); - } + void Simulation::DelNode(const std::string& name) { m_Nodes.erase(name); } } // namespace simulate } // namespace llarp diff --git a/llarp/util/buffer.cpp b/llarp/util/buffer.cpp index 744b34aa3e..c5e084c85a 100644 --- a/llarp/util/buffer.cpp +++ b/llarp/util/buffer.cpp @@ -45,35 +45,17 @@ namespace } // namespace -bool llarp_buffer_t::put_uint16(uint16_t i) -{ - return put(*this, i); -} +bool llarp_buffer_t::put_uint16(uint16_t i) { return put(*this, i); } -bool llarp_buffer_t::put_uint64(uint64_t i) -{ - return put(*this, i); -} +bool llarp_buffer_t::put_uint64(uint64_t i) { return put(*this, i); } -bool llarp_buffer_t::put_uint32(uint32_t i) -{ - return put(*this, i); -} +bool llarp_buffer_t::put_uint32(uint32_t i) { return put(*this, i); } -bool llarp_buffer_t::read_uint16(uint16_t& i) -{ - return read(*this, i); -} +bool llarp_buffer_t::read_uint16(uint16_t& i) { return read(*this, i); } -bool llarp_buffer_t::read_uint32(uint32_t& i) -{ - return read(*this, i); -} +bool llarp_buffer_t::read_uint32(uint32_t& i) { return read(*this, i); } -bool llarp_buffer_t::read_uint64(uint64_t& i) -{ - return read(*this, i); -} +bool llarp_buffer_t::read_uint64(uint64_t& i) { return read(*this, i); } size_t llarp_buffer_t::read_until(char c_delim, uint8_t* result, size_t resultsize) { diff --git a/llarp/util/buffer.hpp b/llarp/util/buffer.hpp index 97efd6bbb6..27a0b4b095 100644 --- a/llarp/util/buffer.hpp +++ b/llarp/util/buffer.hpp @@ -83,10 +83,7 @@ namespace llarp } // 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()}; - } + inline ustring_view to_usv(std::string_view v) { return {reinterpret_cast(v.data()), v.size()}; } template inline uspan to_uspan(std::basic_string& v) diff --git a/llarp/util/concept.hpp b/llarp/util/concept.hpp deleted file mode 100644 index 9e1c698b86..0000000000 --- a/llarp/util/concept.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once - -#include - -namespace llarp::concepts -{ - // Types can opt-in to being fmt-formattable by ensuring they have a ::to_string() method defined - template - concept to_string_formattable = oxen::quic::concepts::ToStringFormattable; - - template > - concept forward_iterable = std::forward_iterator; - -#ifndef __cpp_lib_is_scoped_enum - template - struct is_scoped_enum_st : std::bool_constant < requires - { - requires std::is_enum_v; - requires not std::is_convertible_v>; - } > {}; - - template - inline constexpr bool is_scoped_enum_v = is_scoped_enum_st::value; -#endif - - template - concept is_scoped_enum = -#ifdef __cpp_lib_is_scoped_enum - std::is_scoped_enum_v; -#else - is_scoped_enum_v; -#endif - -} // namespace llarp::concepts diff --git a/llarp/util/formattable.hpp b/llarp/util/formattable.hpp index dbd5cf8ba6..c4314d5038 100644 --- a/llarp/util/formattable.hpp +++ b/llarp/util/formattable.hpp @@ -1,8 +1,9 @@ #pragma once -#include "concept.hpp" +#include "meta.hpp" #include +#include #include @@ -10,6 +11,14 @@ namespace llarp { using namespace std::literals; using namespace oxen::log::literals; + + namespace concepts + { + // Types can opt-in to being fmt-formattable by ensuring they have a ::to_string() method defined + template + concept to_string_formattable = oxen::quic::concepts::ToStringFormattable; + } // namespace concepts + } // namespace llarp #if !defined(USE_GHC_FILESYSTEM) && FMT_VERSION >= 80102 @@ -88,7 +97,7 @@ namespace fmt namespace fmt { - template + template struct formatter : formatter { template @@ -97,32 +106,4 @@ namespace fmt return formatter::format(to_string(val), ctx); } }; - - // template T> - // struct formatter, char> : formatter - // { - // template - // auto format(const std::optional& opt, FormatContext& ctx) - // { - // if (opt) - // { - // return formatter::format(*opt, ctx); - // } - // return format_to(ctx.out(), "[-nullopt-]"); - // } - // }; - - // template - // struct formatter, char> : formatter - // { - // template - // auto format(const std::optional& opt, FormatContext& ctx) - // { - // if (opt) - // { - // return formatter::format(opt->to_string(), ctx); - // } - // return format_to(ctx.out(), "[-nullopt-]"); - // } - // }; } // namespace fmt diff --git a/llarp/util/meta.hpp b/llarp/util/meta.hpp index 97edc31759..bb2e0f0051 100644 --- a/llarp/util/meta.hpp +++ b/llarp/util/meta.hpp @@ -1,72 +1,106 @@ #pragma once -#include "concept.hpp" #include "random.hpp" #include #include -namespace llarp::meta +namespace llarp { - /** Aggregated generalized algorithms for sort, selection, etc - */ + namespace concepts + { + template > + concept forward_iterable = std::forward_iterator; + + template + concept scoped_enum = +#ifdef __cpp_lib_scoped_enum + std::is_scoped_enum_v; +#else + std::is_enum_v && !std::is_convertible_v>; +#endif + } // namespace concepts - /** One-pass random selection algorithm - - https://en.wikipedia.org/wiki/Reservoir_sampling + /** Namespace meta: + Aggregates functional implementations utilized across broadly different contexts. */ - template ::value_type> - std::optional sample(const T& container, std::function hook) + namespace meta { - size_t i = 0; - std::optional ret = std::nullopt; - - for (const auto& e : container) + inline namespace enums { - if (not hook(e)) - continue; - - if (++i <= 1) + // __cpp_lib_to_underlying is a C++23 feature + template >> + requires std::is_enum_v + inline constexpr U to_underlying(T e) { - ret = e; - continue; + return static_cast(e); } + } // namespace enums - size_t x = csrng() % (i + 1); - if (x <= 1) - ret = e; - } + /** Aggregated generalized algorithms for sort, selection, etc + */ + inline namespace sampling + { + /** One-pass random selection algorithm + - https://en.wikipedia.org/wiki/Reservoir_sampling + */ + template ::value_type> + std::optional sample(const T& container, std::function hook) + { + size_t i = 0; + std::optional ret = std::nullopt; - return ret; - } + for (const auto& e : container) + { + if (not hook(e)) + continue; - template ::value_type> - std::optional> sample_n( - const T& container, std::function hook, size_t n, bool exact = false) - { - auto ret = std::make_optional>(); - ret->reserve(n); + if (++i <= 1) + { + ret = e; + continue; + } - size_t i = 0; + size_t x = csrng() % (i + 1); + if (x <= 1) + ret = e; + } - for (const auto& e : container) - { - if (not hook(e)) - continue; + return ret; + } - if (++i <= n) + template ::value_type> + std::optional> sample_n( + const T& container, std::function hook, size_t n, bool exact = false) { - ret->emplace_back(e); - continue; - } + auto ret = std::make_optional>(); + ret->reserve(n); + + size_t i = 0; + + for (const auto& e : container) + { + if (not hook(e)) + continue; - size_t x = csrng() % (i + 1); - if (x < n) - (*ret)[x] = e; - } + if (++i <= n) + { + ret->emplace_back(e); + continue; + } + + size_t x = csrng() % (i + 1); + if (x < n) + (*ret)[x] = e; + } + + if (ret->size() < (exact ? n : 1)) + ret.reset(); + + return ret; + } + } // namespace sampling - if (ret->size() < (exact ? n : 1)) - ret.reset(); + } // namespace meta - return ret; - } -} // namespace llarp::meta +} // namespace llarp diff --git a/llarp/util/thread/queue_manager.cpp b/llarp/util/thread/queue_manager.cpp index a290318515..4d1dd383e6 100644 --- a/llarp/util/thread/queue_manager.cpp +++ b/llarp/util/thread/queue_manager.cpp @@ -32,50 +32,26 @@ namespace llarp::thread // Max number of combinations of index and generations. static constexpr uint32_t NUM_COMBINED_INDEXES = DISABLED_STATE_MASK; - bool isDisabledFlagSet(uint32_t encodedIndex) - { - return (encodedIndex & DISABLED_STATE_MASK); - } + bool isDisabledFlagSet(uint32_t encodedIndex) { return (encodedIndex & DISABLED_STATE_MASK); } - uint32_t discardDisabledFlag(uint32_t encodedIndex) - { - return (encodedIndex & ~DISABLED_STATE_MASK); - } + uint32_t discardDisabledFlag(uint32_t encodedIndex) { return (encodedIndex & ~DISABLED_STATE_MASK); } uint32_t encodeElement(uint32_t generation, ElementState state) { return (generation << GENERATION_COUNT_SHIFT) | to_underlying(state); } - uint32_t decodeGenerationFromElementState(uint32_t state) - { - return state >> GENERATION_COUNT_SHIFT; - } + uint32_t decodeGenerationFromElementState(uint32_t state) { return state >> GENERATION_COUNT_SHIFT; } - ElementState decodeStateFromElementState(uint32_t state) - { - return ElementState(state & ELEMENT_STATE_MASK); - } + ElementState decodeStateFromElementState(uint32_t state) { return ElementState(state & ELEMENT_STATE_MASK); } - QueueManager::AtomicIndex& QueueManager::pushIndex() - { - return m_pushIndex; - } + QueueManager::AtomicIndex& QueueManager::pushIndex() { return m_pushIndex; } - QueueManager::AtomicIndex& QueueManager::popIndex() - { - return m_popIndex; - } + QueueManager::AtomicIndex& QueueManager::popIndex() { return m_popIndex; } - const QueueManager::AtomicIndex& QueueManager::pushIndex() const - { - return m_pushIndex; - } + const QueueManager::AtomicIndex& QueueManager::pushIndex() const { return m_pushIndex; } - const QueueManager::AtomicIndex& QueueManager::popIndex() const - { - return m_popIndex; - } + const QueueManager::AtomicIndex& QueueManager::popIndex() const { return m_popIndex; } uint32_t QueueManager::nextCombinedIndex(uint32_t index) const { @@ -97,10 +73,7 @@ namespace llarp::thread return generation + 1; } - size_t QueueManager::capacity() const - { - return m_capacity; - } + size_t QueueManager::capacity() const { return m_capacity; } int32_t QueueManager::circularDifference(uint32_t startingValue, uint32_t subtractValue, uint32_t modulo) { @@ -148,10 +121,7 @@ namespace llarp::thread } } - QueueManager::~QueueManager() - { - delete[] m_states; - } + QueueManager::~QueueManager() { delete[] m_states; } QueueReturn QueueManager::reservePushIndex(uint32_t& generation, uint32_t& index) { @@ -503,8 +473,5 @@ namespace llarp::thread return 0; } - bool QueueManager::enabled() const - { - return !isDisabledFlagSet(pushIndex().load()); - } + bool QueueManager::enabled() const { return !isDisabledFlagSet(pushIndex().load()); } } // namespace llarp::thread diff --git a/llarp/util/time.cpp b/llarp/util/time.cpp index b35bc369d0..682601fae7 100644 --- a/llarp/util/time.cpp +++ b/llarp/util/time.cpp @@ -15,20 +15,11 @@ namespace llarp static const auto started_at_steady = std::chrono::steady_clock::now(); } // namespace - std::chrono::steady_clock::time_point get_time() - { - return std::chrono::steady_clock::now(); - } + std::chrono::steady_clock::time_point get_time() { return std::chrono::steady_clock::now(); } - std::chrono::nanoseconds get_timestamp() - { - return std::chrono::steady_clock::now().time_since_epoch(); - } + std::chrono::nanoseconds get_timestamp() { return std::chrono::steady_clock::now().time_since_epoch(); } - uint64_t to_milliseconds(std::chrono::milliseconds ms) - { - return ms.count(); - } + uint64_t to_milliseconds(std::chrono::milliseconds ms) { return ms.count(); } /// get our uptime in ms std::chrono::milliseconds uptime() @@ -51,10 +42,7 @@ namespace llarp return t + time_since_epoch(started_at_system); } - nlohmann::json to_json(const std::chrono::milliseconds& t) - { - return to_milliseconds(t); - } + nlohmann::json to_json(const std::chrono::milliseconds& t) { return to_milliseconds(t); } static auto extract_h_m_s_ms(const std::chrono::milliseconds& dur) { diff --git a/llarp/vpn/egres_packet_router.hpp b/llarp/vpn/egres_packet_router.hpp index 98544d4cd1..5b986c7b6d 100644 --- a/llarp/vpn/egres_packet_router.hpp +++ b/llarp/vpn/egres_packet_router.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include #include #include diff --git a/llarp/vpn/linux.hpp b/llarp/vpn/linux.hpp index db511a68a0..d2c7b6d1f7 100644 --- a/llarp/vpn/linux.hpp +++ b/llarp/vpn/linux.hpp @@ -125,7 +125,7 @@ namespace llarp::vpn std::vector buf; buf.resize(MAX_PACKET_SIZE); const auto sz = read(_fd, buf.data(), buf.capacity()); - log::debug(logcat, "{} bytes read from fd {} (err?:{})", sz, _fd, strerror(errno)); + // log::trace(logcat, "{} bytes read from fd {} (err?:{})", sz, _fd, strerror(errno)); if (sz < 0) { if (errno == EAGAIN or errno == EWOULDBLOCK) @@ -143,7 +143,7 @@ namespace llarp::vpn bool write_packet(IPPacket pkt) override { const auto sz = write(_fd, pkt.data(), pkt.size()); - log::debug(logcat, "{} bytes written to fd {} (err?:{})", sz, _fd, strerror(errno)); + // log::trace(logcat, "{} bytes written to fd {} (err?:{})", sz, _fd, strerror(errno)); if (sz <= 0) return false; return sz == static_cast(pkt.size()); diff --git a/llarp/vpn/packet_io.hpp b/llarp/vpn/packet_io.hpp index b88256750e..4191760646 100644 --- a/llarp/vpn/packet_io.hpp +++ b/llarp/vpn/packet_io.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include diff --git a/llarp/vpn/packet_router.cpp b/llarp/vpn/packet_router.cpp index b34ba55f13..111d93be03 100644 --- a/llarp/vpn/packet_router.cpp +++ b/llarp/vpn/packet_router.cpp @@ -20,7 +20,7 @@ namespace llarp::vpn void handle_ip_packet(IPPacket pkt) override { - log::debug(logcat, "udp pkt: ", pkt.info_line()); + log::trace(logcat, "udp pkt: ", pkt.info_line()); auto dstport = pkt.dest_port(); if (not dstport) @@ -45,7 +45,7 @@ namespace llarp::vpn void handle_ip_packet(IPPacket pkt) override { - log::debug(logcat, "l4 pkt: {}", pkt.info_line()); + log::critical(logcat, "(FIXME) l4 pkt: {}", pkt.info_line()); // TOFIX: // _base_handler(IPPacket::from_udp(std::move(pkt))); } @@ -55,14 +55,15 @@ namespace llarp::vpn void PacketRouter::handle_ip_packet(IPPacket pkt) { - log::debug(logcat, "ip pkt: {}", pkt.info_line()); + if (pkt.is_ipv4()) + log::trace(logcat, "ipv4 pkt: {}", pkt.info_line()); auto dest_port = pkt.dest_port(); if (not dest_port) return _handler(std::move(pkt)); auto proto = pkt.protocol(); - if (const auto itr = _ip_proto_handler.find(*proto); itr != _ip_proto_handler.end()) + if (const auto itr = _ip_proto_handler.find(proto); itr != _ip_proto_handler.end()) itr->second->handle_ip_packet(std::move(pkt)); else _handler(std::move(pkt)); @@ -70,16 +71,14 @@ namespace llarp::vpn void PacketRouter::add_udp_handler(uint16_t localport, ip_pkt_hook func) { - constexpr uint8_t udp_proto = 0x11; - - if (_ip_proto_handler.find(udp_proto) == _ip_proto_handler.end()) + if (_ip_proto_handler.find(net::IPProtocol::UDP) == _ip_proto_handler.end()) { - _ip_proto_handler.emplace(udp_proto, std::make_unique(_handler)); + _ip_proto_handler.emplace(net::IPProtocol::UDP, std::make_unique(_handler)); } - _ip_proto_handler[udp_proto]->add_sub_handler(localport, func); + _ip_proto_handler[net::IPProtocol::UDP]->add_sub_handler(localport, func); } - void PacketRouter::add_ip_proto_handler(uint8_t proto, ip_pkt_hook func) + void PacketRouter::add_ip_proto_handler(net::IPProtocol proto, ip_pkt_hook func) { _ip_proto_handler[proto] = std::make_unique(std::move(func)); } diff --git a/llarp/vpn/packet_router.hpp b/llarp/vpn/packet_router.hpp index 9836f5ee79..8fd03c8435 100644 --- a/llarp/vpn/packet_router.hpp +++ b/llarp/vpn/packet_router.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include @@ -12,7 +12,8 @@ namespace llarp::vpn class PacketRouter { ip_pkt_hook _handler; - std::unordered_map> _ip_proto_handler; + // std::unordered_map> _ip_proto_handler; + std::unordered_map> _ip_proto_handler; public: /// baseHandler will be called if no other handlers matches a packet @@ -22,7 +23,7 @@ namespace llarp::vpn void handle_ip_packet(IPPacket pkt); /// add a non udp packet handler using ip protocol proto - void add_ip_proto_handler(uint8_t proto, ip_pkt_hook func); + void add_ip_proto_handler(net::IPProtocol proto, ip_pkt_hook func); /// helper that adds a udp packet handler for UDP destined for localport void add_udp_handler(uint16_t port, ip_pkt_hook func); diff --git a/llarp/vpn/platform.cpp b/llarp/vpn/platform.cpp index 12f6f2763b..73e80d13b9 100644 --- a/llarp/vpn/platform.cpp +++ b/llarp/vpn/platform.cpp @@ -14,10 +14,7 @@ namespace llarp::vpn { - const llarp::net::Platform* AbstractRouteManager::net_ptr() const - { - return llarp::net::Platform::Default_ptr(); - } + const llarp::net::Platform* AbstractRouteManager::net_ptr() const { return llarp::net::Platform::Default_ptr(); } std::shared_ptr MakeNativePlatform(llarp::Context* ctx) { diff --git a/llarp/vpn/platform.hpp b/llarp/vpn/platform.hpp index c8540abf18..c4214fa278 100644 --- a/llarp/vpn/platform.hpp +++ b/llarp/vpn/platform.hpp @@ -2,8 +2,8 @@ #include "packet_io.hpp" -#include #include +#include #include #include diff --git a/llarp/win32/exec.cpp b/llarp/win32/exec.cpp index 7560518491..4a9c859f0d 100644 --- a/llarp/win32/exec.cpp +++ b/llarp/win32/exec.cpp @@ -25,10 +25,7 @@ namespace llarp::win32 } // namespace - void Exec(std::string exe, std::string args) - { - OneShotExec{exe, args}; - } + void Exec(std::string exe, std::string args) { OneShotExec{exe, args}; } OneShotExec::OneShotExec(std::string cmd, std::chrono::milliseconds timeout) : _si{}, _pi{}, _timeout{static_cast(timeout.count())} @@ -49,8 +46,5 @@ namespace llarp::win32 : OneShotExec{fmt::format("{}\\{} {}", SystemExeDir(), cmd, args), timeout} {} - DeferExec::~DeferExec() - { - OneShotExec{std::move(_exe), std::move(_args), std::move(_timeout)}; - } + DeferExec::~DeferExec() { OneShotExec{std::move(_exe), std::move(_args), std::move(_timeout)}; } } // namespace llarp::win32 diff --git a/llarp/win32/service_manager.cpp b/llarp/win32/service_manager.cpp index e7cbfda297..1877970daa 100644 --- a/llarp/win32/service_manager.cpp +++ b/llarp/win32/service_manager.cpp @@ -33,10 +33,7 @@ namespace llarp::sys } } // namespace - SVC_Manager::SVC_Manager() - { - _status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - } + SVC_Manager::SVC_Manager() { _status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; } void SVC_Manager::system_changed_our_state(ServiceState st) { diff --git a/pybind/llarp/config.cpp b/pybind/llarp/config.cpp index 3cf00ba7e7..5d2c034cc0 100644 --- a/pybind/llarp/config.cpp +++ b/pybind/llarp/config.cpp @@ -5,10 +5,7 @@ namespace llarp { - void in_addr_set(in_addr* addr, const char* str) - { - inet_aton(str, addr); - } + void in_addr_set(in_addr* addr, const char* str) { inet_aton(str, addr); } void Config_Init(py::module& mod) { From f603ecb109aeae9ce8058d7d4e5c7dd83ae87517 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Mon, 13 Jan 2025 06:57:28 -0800 Subject: [PATCH 41/44] dropme: once oxenc constexpr is merged --- llarp/net/utils.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/llarp/net/utils.cpp b/llarp/net/utils.cpp index e5ffcae6f5..04a433b8a8 100644 --- a/llarp/net/utils.cpp +++ b/llarp/net/utils.cpp @@ -5,10 +5,12 @@ namespace llarp namespace utils { static constexpr uint32_t add_u32(uint32_t x) { return uint32_t{x & 0xFFff} + uint32_t{x >> 16}; } - static constexpr uint32_t add_u32(ipv4 x) { return add_u32(oxenc::host_to_big(x.addr)); } + // static constexpr uint32_t add_u32(ipv4 x) { return add_u32(oxenc::host_to_big(x.addr)); } + static uint32_t add_u32(ipv4 x) { return add_u32(oxenc::host_to_big(x.addr)); } static constexpr uint32_t sub_u32(uint32_t x) { return add_u32(~x); } - static constexpr uint32_t sub_u32(ipv4 x) { return sub_u32(oxenc::host_to_big(x.addr)); } + // static constexpr uint32_t sub_u32(ipv4 x) { return sub_u32(oxenc::host_to_big(x.addr)); } + static uint32_t sub_u32(ipv4 x) { return sub_u32(oxenc::host_to_big(x.addr)); } uint16_t ip_checksum(const uint8_t *buf, size_t sz) { From 2033d6bb8f3ed4cf92708c342fb234c44dc53d65 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Tue, 14 Jan 2025 14:19:24 -0800 Subject: [PATCH 42/44] squash --- llarp/contact/relay_contact_remote.cpp | 4 +- llarp/contact/tag.hpp | 2 +- llarp/crypto/crypto.cpp | 4 +- llarp/crypto/crypto.hpp | 4 +- llarp/crypto/types.cpp | 4 +- llarp/crypto/types.hpp | 12 +-- llarp/dns/message.cpp | 2 +- llarp/dns/message.hpp | 4 +- llarp/dns/question.hpp | 2 +- llarp/dns/rr.hpp | 2 +- llarp/dns/serialize.hpp | 2 +- llarp/dns/server.hpp | 2 +- llarp/handlers/session.cpp | 45 +++++----- llarp/handlers/tun.cpp | 8 +- llarp/handlers/tun.hpp | 13 +-- llarp/link/link_manager.cpp | 5 +- llarp/messages/exit.hpp | 4 +- llarp/net/ip_headers.hpp | 47 ++++++----- llarp/net/ip_packet.cpp | 7 +- llarp/net/ip_packet.hpp | 5 +- llarp/net/policy.cpp | 110 +++++++++---------------- llarp/net/policy.hpp | 41 +++++++-- llarp/util/buffer.hpp | 57 ++----------- llarp/vpn/packet_router.cpp | 20 +++-- llarp/vpn/packet_router.hpp | 2 +- 25 files changed, 181 insertions(+), 227 deletions(-) diff --git a/llarp/contact/relay_contact_remote.cpp b/llarp/contact/relay_contact_remote.cpp index 5c31d95fac..6bffe3541f 100644 --- a/llarp/contact/relay_contact_remote.cpp +++ b/llarp/contact/relay_contact_remote.cpp @@ -32,7 +32,7 @@ namespace llarp log::trace(logcat, "{}B read from file (path:{})!", nread, fname); _payload.resize(nread); - oxenc::bt_dict_consumer btdc{_payload}; + oxenc::bt_dict_consumer btdc{ustring_view{_payload}}; bt_load(btdc); bt_verify(btdc); } @@ -47,7 +47,7 @@ namespace llarp bool RemoteRC::verify() const { - oxenc::bt_dict_consumer btdc{_payload}; + oxenc::bt_dict_consumer btdc{ustring_view{_payload}}; bt_verify(btdc); return true; } diff --git a/llarp/contact/tag.hpp b/llarp/contact/tag.hpp index fb111233f4..ce071ce52d 100644 --- a/llarp/contact/tag.hpp +++ b/llarp/contact/tag.hpp @@ -1,6 +1,6 @@ #pragma once -#include +// #include #include namespace llarp diff --git a/llarp/crypto/crypto.cpp b/llarp/crypto/crypto.cpp index dc2d96d3a5..89843b6dfd 100644 --- a/llarp/crypto/crypto.cpp +++ b/llarp/crypto/crypto.cpp @@ -238,7 +238,7 @@ namespace llarp SharedSecret& secret, const SymmNonce& nonce, const RouterID& remote, - uspan payload) + std::span payload) { // derive shared key if (!crypto::dh_client(secret, remote, shared_key, nonce)) @@ -262,7 +262,7 @@ namespace llarp SharedSecret& shared, const PubKey& remote, const SymmNonce& nonce, - uspan encrypted) + std::span encrypted) { // derive shared secret using shared secret and our secret key (and nonce) if (!crypto::dh_server(shared, remote, local_sk, nonce)) diff --git a/llarp/crypto/crypto.hpp b/llarp/crypto/crypto.hpp index 47c88f6e26..5a35ffc396 100644 --- a/llarp/crypto/crypto.hpp +++ b/llarp/crypto/crypto.hpp @@ -68,7 +68,7 @@ namespace llarp SharedSecret& secret, const SymmNonce& nonce, const RouterID& remote, - uspan payload); + std::span payload); // void derive_encrypt_outer_wrapping( // const Ed25519SecretKey& shared_key, @@ -85,7 +85,7 @@ namespace llarp SharedSecret& shared, const PubKey& remote, const SymmNonce& nonce, - uspan encrypted); + std::span encrypted); std::array make_scalar(const PubKey& k, uint64_t domain); diff --git a/llarp/crypto/types.cpp b/llarp/crypto/types.cpp index 6246a88d38..80cd8ab916 100644 --- a/llarp/crypto/types.cpp +++ b/llarp/crypto/types.cpp @@ -145,14 +145,14 @@ namespace llarp throw std::runtime_error{"Server DH failed -- should this even ever happen?"}; } - void shared_kx_data::encrypt(uspan data) + void shared_kx_data::encrypt(std::span data) { if (!crypto::xchacha20(data.data(), data.size(), shared_secret, nonce)) throw std::runtime_error{"xchacha20 encryption failed -- should this even ever happen?"}; } // identical methods, separated for clarity of use/logging for now - void shared_kx_data::decrypt(uspan data) + void shared_kx_data::decrypt(std::span data) { if (!crypto::xchacha20(data.data(), data.size(), shared_secret, nonce)) throw std::runtime_error{"xchacha20 decryption failed -- should this even ever happen?"}; diff --git a/llarp/crypto/types.hpp b/llarp/crypto/types.hpp index 5c7f235d91..382c891af9 100644 --- a/llarp/crypto/types.hpp +++ b/llarp/crypto/types.hpp @@ -67,13 +67,13 @@ namespace llarp explicit Ed25519PrivateData(const AlignedBuffer<64>& key_and_hash) : AlignedBuffer<64>(key_and_hash) {} // Returns writeable access to the 32-byte Ed25519 Private Scalar - uspan scalar() { return {data(), 32}; } + std::span scalar() { return {data(), 32}; } // Returns readable access to the 32-byte Ed25519 Private Scalar - const_uspan scalar() const { return {data(), 32}; } + uspan scalar() const { return {data(), 32}; } // Returns writeable access to the 32-byte Ed25519 Signing Hash - uspan signing_hash() { return {data() + 32, 32}; } + std::span signing_hash() { return {data() + 32, 32}; } // Returns readable access to the 32-byte Ed25519 Signing Hash - const_uspan signing_hash() const { return {data() + 32, 32}; } + uspan signing_hash() const { return {data() + 32, 32}; } PubKey to_pubkey() const; @@ -125,9 +125,9 @@ namespace llarp void server_dh(const Ed25519SecretKey& local_sk); - void encrypt(uspan data); + void encrypt(std::span data); - void decrypt(uspan enc); + void decrypt(std::span enc); }; } // namespace llarp diff --git a/llarp/dns/message.cpp b/llarp/dns/message.cpp index 22a7caba69..2f48e0937f 100644 --- a/llarp/dns/message.cpp +++ b/llarp/dns/message.cpp @@ -46,7 +46,7 @@ namespace llarp::dns return true; } - bool MessageHeader::decode(std::span b) + bool MessageHeader::decode(std::span b) { std::memcpy(_data.data(), b.data(), sizeof(_data)); for (auto& d : _data) diff --git a/llarp/dns/message.hpp b/llarp/dns/message.hpp index e489111edb..7492d8836b 100644 --- a/llarp/dns/message.hpp +++ b/llarp/dns/message.hpp @@ -39,7 +39,7 @@ namespace llarp bool Decode(llarp_buffer_t* buf) override; - bool decode(std::span b) override; + bool decode(std::span b) override; nlohmann::json ToJSON() const override; @@ -80,7 +80,7 @@ namespace llarp bool Decode(llarp_buffer_t* buf) override; - bool decode(std::span /* b */) override { return {}; }; // TODO: + bool decode(std::span /* b */) override { return {}; }; // TODO: // Wrapper around Encode that encodes into a new buffer and returns it std::vector to_buffer() const; diff --git a/llarp/dns/question.hpp b/llarp/dns/question.hpp index a087d2afb9..43bb674efd 100644 --- a/llarp/dns/question.hpp +++ b/llarp/dns/question.hpp @@ -21,7 +21,7 @@ namespace llarp::dns bool Decode(llarp_buffer_t* buf) override; - bool decode(std::span /* b */) override { return {}; } + bool decode(std::span /* b */) override { return {}; } std::string to_string() const; diff --git a/llarp/dns/rr.hpp b/llarp/dns/rr.hpp index be7e5488b0..e2b3e2e8af 100644 --- a/llarp/dns/rr.hpp +++ b/llarp/dns/rr.hpp @@ -25,7 +25,7 @@ namespace llarp::dns bool Decode(llarp_buffer_t* buf) override; - bool decode(std::span /* b */) override { return {}; }; + bool decode(std::span /* b */) override { return {}; }; nlohmann::json ToJSON() const override; diff --git a/llarp/dns/serialize.hpp b/llarp/dns/serialize.hpp index 5020d2b2bf..d6505b0115 100644 --- a/llarp/dns/serialize.hpp +++ b/llarp/dns/serialize.hpp @@ -19,7 +19,7 @@ namespace llarp::dns /// decode entity from buffer virtual bool Decode(llarp_buffer_t* buf) = 0; - virtual bool decode(std::span b) = 0; + virtual bool decode(std::span b) = 0; /// convert this whatever into json virtual nlohmann::json ToJSON() const = 0; diff --git a/llarp/dns/server.hpp b/llarp/dns/server.hpp index 471cf2c211..f06d68b16d 100644 --- a/llarp/dns/server.hpp +++ b/llarp/dns/server.hpp @@ -56,7 +56,7 @@ namespace llarp::dns virtual void send_to( const oxen::quic::Address& to, const oxen::quic::Address& from, std::vector data) const { - send_to(to, from, IPPacket{data.data(), data.size()}); + send_to(to, from, IPPacket{std::move(data)}); } /// stop reading packets and end operation diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index ab59cde7a6..e561a0b10c 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -137,7 +137,7 @@ namespace llarp::handlers update_and_publish_localcc(get_current_client_intros(), _srv_records); } - // static std::atomic testnet_trigger = false; + static std::atomic testnet_trigger = false; void SessionEndpoint::start_tickers() { @@ -152,25 +152,24 @@ namespace llarp::handlers }, true); - // if (not testnet_trigger) - // { - // testnet_trigger = true; - - // _router.loop()->call_later(5s, [this]() { - // try - // { - // RouterID cpk{oxenc::from_base32z("4g96taie3et7dbkumk5x6rycskaxxsgjeiunpe61469z1gsbfkuo")}; - // log::info(logcat, "Beginning session init to client: {}", cpk.to_network_address(false)); - // _initiate_session( - // NetworkAddress::from_pubkey(cpk, true), [](ip_v) { log::critical(logcat, "FUCK YEAH"); - // }); - // } - // catch (const std::exception& e) - // { - // log::critical(logcat, "Failed to parse client netaddr: {}", e.what()); - // } - // }); - // } + if (not testnet_trigger) + { + testnet_trigger = true; + + _router.loop()->call_later(5s, [this]() { + try + { + RouterID cpk{oxenc::from_base32z("acit6x8kwxdehpkzrpunw5nb8mf4w5u8tn3ojmxit9rpnhhhp81y")}; + log::info(logcat, "Beginning session init to client: {}", cpk.to_network_address(false)); + _initiate_session( + NetworkAddress::from_pubkey(cpk, true), [](ip_v) { log::critical(logcat, "FUCK YEAH"); }); + } + catch (const std::exception& e) + { + log::critical(logcat, "Failed to parse client netaddr: {}", e.what()); + } + }); + } } else log::info(logcat, "SessionEndpoint configured to NOT publish ClientContact..."); @@ -630,7 +629,11 @@ namespace llarp::handlers if (auto maybe_ip = _router.tun_endpoint()->map_session_to_local_ip(session->remote())) { log::info( - logcat, "TUN device successfully routing session to remote: {}", session->remote()); + logcat, + "TUN device successfully routing session (remote: {}) via local ip: {}", + session->remote(), + std::holds_alternative(*maybe_ip) ? std::get(*maybe_ip).to_string() + : std::get(*maybe_ip).to_string()); return hook(*maybe_ip); } diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index 661132ce8a..c2d60e7c1f 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -289,7 +289,7 @@ namespace llarp::handlers auto& net_conf = _router.config()->network; - _traffic_policy = net_conf.traffic_policy; + _exit_policy = net_conf.traffic_policy; _base_ipv6_range = net_conf._base_ipv6_range; if (net_conf.path_alignment_timeout) @@ -947,7 +947,7 @@ namespace llarp::handlers ip_v src, dest; auto pkt_is_ipv4 = pkt.is_ipv4(); - log::trace(logcat, "outbound packet: {}: {}", pkt.info_line(), buffer_printer{pkt.uview()}); + log::debug(logcat, "outbound packet: {}: {}", pkt.info_line(), buffer_printer{pkt.uview()}); if (pkt_is_ipv4) { @@ -1074,7 +1074,7 @@ namespace llarp::handlers { log::info(logcat, "inbound exit session pkt: {}", pkt.info_line()); // we are receiving traffic from a session to a local exit node - if (not is_allowing_traffic(pkt)) + if (not _exit_policy->allow_ip_traffic(pkt)) return false; if (pkt_is_ipv4) @@ -1114,7 +1114,7 @@ namespace llarp::handlers bool TunEndpoint::is_allowing_traffic(const IPPacket& pkt) const { - return _traffic_policy ? _traffic_policy->allow_ip_traffic(pkt) : true; + return _exit_policy ? _exit_policy->allow_ip_traffic(pkt) : true; } bool TunEndpoint::has_mapping_to_remote(const NetworkAddress& addr) const diff --git a/llarp/handlers/tun.hpp b/llarp/handlers/tun.hpp index 81abff2d5e..f33d4f090b 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -54,7 +54,7 @@ namespace llarp::handlers std::shared_ptr _packet_router; - std::optional _traffic_policy = std::nullopt; + std::optional _exit_policy = std::nullopt; /// a file to load / store the ephemeral address map to std::optional _persisting_addr_file = std::nullopt; @@ -125,7 +125,7 @@ namespace llarp::handlers bool has_if_addr() const { return true; } - std::optional get_traffic_policy() const { return _traffic_policy; } + std::optional get_traffic_policy() const { return _exit_policy; } std::chrono::milliseconds get_path_alignment_timeout() const { return _path_alignment_timeout; } @@ -144,15 +144,6 @@ namespace llarp::handlers void start_poller(); - // protected: - struct WritePacket - { - uint64_t seqno; - IPPacket pkt; - - bool operator>(const WritePacket& other) const { return seqno > other.seqno; } - }; - // Stores assigned IP's for each session in/out of this lokinet instance // - Reserved local addresses is directly pre-loaded from config // - Persisting address map is directly pre-loaded from config diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 9f09d4a2f9..e21ba885be 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -24,7 +24,7 @@ namespace llarp { static auto logcat = llarp::log::Cat("lquic"); - static constexpr auto static_shared_key = "Lokinet static shared secret key"_usv; + static constexpr auto static_shared_key = "Lokinet static shared secret key"_usp; static static_secret make_static_secret(const Ed25519SecretKey& sk) { @@ -1470,7 +1470,8 @@ namespace llarp try { - std::tie(hop_id, nonce, payload) = ONION::deserialize_hop(oxenc::bt_dict_consumer{message}); + std::tie(hop_id, nonce, payload) = + ONION::deserialize_hop(oxenc::bt_dict_consumer{bstring_view{message}}); } catch (const std::exception& e) { diff --git a/llarp/messages/exit.hpp b/llarp/messages/exit.hpp index f288fdf09f..f911b501f3 100644 --- a/llarp/messages/exit.hpp +++ b/llarp/messages/exit.hpp @@ -9,9 +9,7 @@ namespace llarp { /* TODO: - - ADD PUBKEY FIELD OR AT LEAST SEE WHY LINKMANAGER::HANDLE_OBTAIN_EXIT() LOOKS FOR ONE - - - change these parameters to ustringviews and ustrings where needed after bumping oxenc + - change these parameters to uspans where needed after bumping oxenc - change std::string sig(64, '\0') --> std::array sig */ diff --git a/llarp/net/ip_headers.hpp b/llarp/net/ip_headers.hpp index 33d6d315a0..3e77adc906 100644 --- a/llarp/net/ip_headers.hpp +++ b/llarp/net/ip_headers.hpp @@ -2,6 +2,8 @@ #include "utils.hpp" +#include + namespace llarp { struct ip_header @@ -26,25 +28,32 @@ namespace llarp static_assert(sizeof(ip_header) == 20); - struct ipv6_header2 - { -#if __BYTE_ORDER == __LITTLE_ENDIAN - uint32_t flow_label : 20; - uint8_t traffic_class; - uint8_t version : 4; -#else - uint8_t version : 4; - uint8_t traffic_class : 8; - uint32_t flow_label : 20; -#endif - // uint16_t pload_len; // payload length - // uint8_t nxt_hdr; // next header (protocol) - // uint8_t hop_limit; - // in6_addr src; - // in6_addr dest; - }; + // TODO: WIP + // struct ipv6_header2 + // { + // private: + // std::array preamble; + + // // #if __BYTE_ORDER == __LITTLE_ENDIAN + // // uint32_t flow_label : 20; + // // uint8_t traffic_class; + // // uint8_t version : 4; + // // #else + // // uint8_t version : 4; + // // uint8_t traffic_class : 8; + // // uint32_t flow_label : 20; + // // #endif + // uint16_t pload_len; // payload length + // uint8_t nxt_hdr; // next header (protocol) + // uint8_t hop_limit; + // in6_addr src; + // in6_addr dest; + + // public: + + // }; - // static_assert(sizeof(ipv6_header2) == 40); + // static_assert(sizeof(ipv6_header2) == 40); struct ipv6_header { @@ -68,7 +77,7 @@ namespace llarp in6_addr dest; /// Returns the flowlabel (stored in network order) in HOST ORDER - uint32_t get_flowlabel() const { return ntohl(preamble.flowlabel & htonl(ipv6_flowlabel_mask)); } + uint32_t get_flowlabel() const { return oxenc::big_to_host(preamble.flowlabel & htonl(ipv6_flowlabel_mask)); } /// Sets a flowlabel in network order. Takes in a label in HOST ORDER void set_flowlabel(uint32_t label) diff --git a/llarp/net/ip_packet.cpp b/llarp/net/ip_packet.cpp index 4eba4ca3d3..8d7006de92 100644 --- a/llarp/net/ip_packet.cpp +++ b/llarp/net/ip_packet.cpp @@ -36,8 +36,6 @@ namespace llarp IPPacket::IPPacket(bstring_view data) : IPPacket{reinterpret_cast(data.data()), data.size()} {} - IPPacket::IPPacket(ustring_view data) : IPPacket{data.data(), data.size()} {} - IPPacket::IPPacket(std::vector&& data) : IPPacket{data.data(), data.size()} {} IPPacket::IPPacket(const uint8_t* buf, size_t len) @@ -383,11 +381,12 @@ namespace llarp std::vector IPPacket::give_buffer() { return {_buf}; } - std::string IPPacket::to_string() { return {reinterpret_cast(data()), size()}; } + std::string IPPacket::to_string() const { return {reinterpret_cast(data()), size()}; } std::string IPPacket::info_line() const { - return "IPPacket:[src={} | dest={} | size={}]"_format(_src_addr, _dst_addr, size()); + return "IPPacket:[type={} | src={} | dest={} | size={}]"_format( + ip_protocol_name(_proto), _src_addr, _dst_addr, size()); } } // namespace llarp diff --git a/llarp/net/ip_packet.hpp b/llarp/net/ip_packet.hpp index 0e4789797a..52fc5b51b9 100644 --- a/llarp/net/ip_packet.hpp +++ b/llarp/net/ip_packet.hpp @@ -44,7 +44,7 @@ namespace llarp bool _is_v4{true}; bool _is_udp{false}; - net::IPProtocol _proto; + net::IPProtocol _proto{}; void _init_internals(); @@ -52,7 +52,6 @@ namespace llarp IPPacket() : IPPacket{size_t{0}} {} explicit IPPacket(size_t sz); explicit IPPacket(bstring_view data); - explicit IPPacket(ustring_view data); explicit IPPacket(std::vector&& data); explicit IPPacket(const uint8_t* buf, size_t len); @@ -134,7 +133,7 @@ namespace llarp ustring_view uview() const { return {data(), size()}; } - std::string to_string(); + std::string to_string() const; std::string info_line() const; }; diff --git a/llarp/net/policy.cpp b/llarp/net/policy.cpp index a9f97b4b29..59514a92c6 100644 --- a/llarp/net/policy.cpp +++ b/llarp/net/policy.cpp @@ -33,41 +33,43 @@ namespace llarp::net return static_cast(intVal); } - throw std::invalid_argument{"no such ip protocol: '" + data + "'"}; + throw std::invalid_argument{"Call to ::getprotobyname failed for input: {}"_format(data)}; } - ProtocolInfo::ProtocolInfo(std::string_view data) - { - const auto parts = split(data, "/"); - proto = parse_ip_proto(std::string{parts[0]}); - if (parts.size() == 2) - { - uint16_t port_host{}; - - std::string portStr{parts[1]}; - std::string protoName = ip_proto_str(proto); - - if (const auto* serv = ::getservbyname(portStr.c_str(), protoName.c_str())) - { - port_host = serv->s_port; - } - else if (const auto port_int = std::stoi(portStr); port_int > 0) - { - port_host = port_int; - } - else - throw std::invalid_argument{"invalid port in protocol info: " + portStr}; - port = port_host; - } - else - port = std::nullopt; - } + // ProtocolInfo::ProtocolInfo(std::string_view data) + // { + // const auto parts = split(data, "/"); + // proto = parse_ip_proto(std::string{parts[0]}); + // if (parts.size() == 2) + // { + // uint16_t port_host{}; + + // std::string portStr{parts[1]}; + // std::string protoName = ip_proto_str(proto); + + // if (const auto* serv = ::getservbyname(portStr.c_str(), protoName.c_str())) + // { + // port_host = serv->s_port; + // } + // else if (const auto port_int = std::stoi(portStr); port_int > 0) + // { + // port_host = port_int; + // } + // else + // throw std::invalid_argument{"Invalid port in protocol info: {}"_format(portStr)}; + + // port = port_host; + // } + // else + // port = std::nullopt; + // } bool ProtocolInfo::matches_packet_proto(const IPPacket& pkt) const { return pkt.protocol() == proto; } bool ExitPolicy::allow_ip_traffic(const IPPacket& pkt) const { - log::debug(logcat, "{} called", __PRETTY_FUNCTION__); + log::trace(logcat, "{} called", __PRETTY_FUNCTION__); + if (protocols.empty() and ranges.empty()) return true; @@ -77,22 +79,18 @@ namespace llarp::net return true; } - ipv4 v4 = pkt.dest_ipv4(); - ipv6 v6 = pkt.dest_ipv6(); auto is_ipv4 = pkt.is_ipv4(); + ip_v pkt_ip; + + if (is_ipv4) + pkt_ip = pkt.dest_ipv4(); + else + pkt_ip = pkt.dest_ipv6(); for (const auto& range : ranges) { - if (is_ipv4) - { - if (range.contains(v4)) - return true; - } - else - { - if (range.contains(v6)) - return true; - } + if (range.contains(pkt_ip)) + return true; } return false; @@ -150,11 +148,11 @@ namespace llarp::net } } - ProtocolInfo::ProtocolInfo(std::string buf) + ProtocolInfo::ProtocolInfo(std::string_view buf) { try { - oxenc::bt_list_consumer btlc{std::move(buf)}; + oxenc::bt_list_consumer btlc{buf}; proto = IPProtocol{btlc.consume_integer()}; if (not btlc.is_finished()) @@ -178,7 +176,7 @@ namespace llarp::net while (not sublist.is_finished()) { - protocols.emplace(sublist.consume_string()); + protocols.emplace(sublist.consume_string_view()); } } @@ -239,30 +237,4 @@ namespace llarp::net return true; } - - // nlohmann::json ProtocolInfo::ExtractStatus() const - // { - // nlohmann::json status{ - // {"protocol", static_cast(protocol)}, - // }; - // if (port) - // status["port"] = *port; - // return status; - // } - - // nlohmann::json ExitProtocol::ExtractStatus() const - // { - // std::vector rangesStatus; - // std::transform(ranges.begin(), ranges.end(), std::back_inserter(rangesStatus), [](const auto& range) { - // return range.to_string(); - // }); - - // std::vector protosStatus; - // std::transform(protocols.begin(), protocols.end(), std::back_inserter(protosStatus), [](const auto& proto) { - // return proto.ExtractStatus(); - // }); - - // return nlohmann::json{{"ranges", rangesStatus}, {"protocols", protosStatus}}; - // } - } // namespace llarp::net diff --git a/llarp/net/policy.hpp b/llarp/net/policy.hpp index 1b987dbd81..dc7321c02c 100644 --- a/llarp/net/policy.hpp +++ b/llarp/net/policy.hpp @@ -22,6 +22,7 @@ namespace llarp TCP2QUIC = 1 << 5, }; + // TODO: WIP implementation struct ip_protocol { enum class type : uint8_t @@ -53,6 +54,33 @@ namespace llarp PGM = 0x71, }; + inline constexpr auto ip_protocol_name(IPProtocol p) + { + switch (p) + { + case IPProtocol::ICMP: + return "ICMP"sv; + case IPProtocol::IGMP: + return "IGMP"sv; + case IPProtocol::IPIP: + return "IPIP"sv; + case IPProtocol::TCP: + return "TCP"sv; + case IPProtocol::UDP: + return "UDP"sv; + case IPProtocol::GRE: + return "GRE"sv; + case IPProtocol::ICMP6: + return "ICMP6"sv; + case IPProtocol::OSPF: + return "OSPF"sv; + case IPProtocol::PGM: + return "PGM"sv; + default: + return ""sv; + } + } + /// information about an IP protocol struct ProtocolInfo { @@ -62,7 +90,8 @@ namespace llarp /// the layer 3 port IN HOST ORDER FFS std::optional port{std::nullopt}; - ProtocolInfo(std::string buf); + ProtocolInfo() = default; + ProtocolInfo(std::string_view buf); void bt_encode(oxenc::bt_list_producer& btlp) const; @@ -70,8 +99,7 @@ namespace llarp bool bt_decode(std::string_view buf); - /// returns true if an ip packet looks like it matches this protocol info - /// returns false otherwise + // Compares packet protocol with protocol info bool matches_packet_proto(const IPPacket& pkt) const; auto operator<=>(const ProtocolInfo& other) const @@ -86,9 +114,7 @@ namespace llarp return std::tie(proto, port) < std::tie(other.proto, other.port); } - ProtocolInfo() = default; - - explicit ProtocolInfo(std::string_view spec); + // explicit ProtocolInfo(std::string_view spec); }; /// information about what exit traffic an endpoint will carry @@ -115,8 +141,7 @@ namespace llarp bool operator==(const ExitPolicy& other) const { return (*this <=> other) == 0; } - /// returns true if we allow the traffic in this ip packet - /// returns false otherwise + // Verifies if IPPacket traffic is allowed; return true/false bool allow_ip_traffic(const IPPacket& pkt) const; }; } // namespace net diff --git a/llarp/util/buffer.hpp b/llarp/util/buffer.hpp index 27a0b4b095..ba0b98dd11 100644 --- a/llarp/util/buffer.hpp +++ b/llarp/util/buffer.hpp @@ -21,74 +21,27 @@ namespace llarp { - using const_cspan = oxenc::cspan; - using const_uspan = oxenc::uspan; - using const_span = oxenc::bspan; - - using cspan = std::span; - using uspan = std::span; - using bspan = std::span; + using cspan = oxenc::const_span; + using uspan = oxenc::const_span; + using span = oxenc::const_span; using ustring = std::basic_string; using ustring_view = std::basic_string_view; using bstring = std::basic_string; using bstring_view = std::basic_string_view; - namespace detail - { - template - struct bsv_literal - { - consteval bsv_literal(const char (&s)[N]) - { - for (size_t i = 0; i < N; i++) - str[i] = static_cast(s[i]); - } - std::byte str[N]; // we keep the null on the end, in case you pass .data() to a C func - using size = std::integral_constant; - }; - template - struct usv_literal - { - consteval usv_literal(const char (&s)[N]) - { - for (size_t i = 0; i < N; i++) - str[i] = static_cast(s[i]); - } - unsigned char str[N]; // we keep the null on the end, in case you pass .data() to a C func - using size = std::integral_constant; - }; - } // namespace detail - inline ustring operator""_us(const char* str, size_t len) noexcept { return {reinterpret_cast(str), len}; } - template - constexpr ustring_view operator""_usv() noexcept - { - return {UStr.str, decltype(UStr)::size::value}; - } - - template - constexpr bstring_view operator""_bsv() - { - return {BStr.str, decltype(BStr)::size::value}; - } - - inline bstring operator""_bs(const char* str, size_t len) noexcept - { - return {reinterpret_cast(str), len}; - } - // 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()}; } template - inline uspan to_uspan(std::basic_string& v) + inline std::span to_uspan(std::basic_string& v) { - return uspan{reinterpret_cast(v.data()), v.size()}; + return std::span{reinterpret_cast(v.data()), v.size()}; } } // namespace llarp diff --git a/llarp/vpn/packet_router.cpp b/llarp/vpn/packet_router.cpp index 111d93be03..37b2d62993 100644 --- a/llarp/vpn/packet_router.cpp +++ b/llarp/vpn/packet_router.cpp @@ -4,7 +4,7 @@ namespace llarp::vpn { - static auto logcat = log::Cat("ip_packet"); + static auto logcat = log::Cat("packet_router"); struct UDPPacketHandler : public Layer4Handler { @@ -16,6 +16,7 @@ namespace llarp::vpn void add_sub_handler(uint16_t localport, ip_pkt_hook handler) override { _port_mapped_handlers.emplace(localport, std::move(handler)); + log::debug(logcat, "UDP packet sub-handler registered for local port {}", localport); } void handle_ip_packet(IPPacket pkt) override @@ -53,7 +54,7 @@ namespace llarp::vpn PacketRouter::PacketRouter(ip_pkt_hook baseHandler) : _handler{std::move(baseHandler)} {} - void PacketRouter::handle_ip_packet(IPPacket pkt) + void PacketRouter::handle_ip_packet(IPPacket pkt) const { if (pkt.is_ipv4()) log::trace(logcat, "ipv4 pkt: {}", pkt.info_line()); @@ -63,7 +64,7 @@ namespace llarp::vpn return _handler(std::move(pkt)); auto proto = pkt.protocol(); - if (const auto itr = _ip_proto_handler.find(proto); itr != _ip_proto_handler.end()) + if (auto itr = _ip_proto_handler.find(proto); itr != _ip_proto_handler.end()) itr->second->handle_ip_packet(std::move(pkt)); else _handler(std::move(pkt)); @@ -71,11 +72,14 @@ namespace llarp::vpn void PacketRouter::add_udp_handler(uint16_t localport, ip_pkt_hook func) { - if (_ip_proto_handler.find(net::IPProtocol::UDP) == _ip_proto_handler.end()) - { - _ip_proto_handler.emplace(net::IPProtocol::UDP, std::make_unique(_handler)); - } - _ip_proto_handler[net::IPProtocol::UDP]->add_sub_handler(localport, func); + auto [it, b] = _ip_proto_handler.try_emplace(net::IPProtocol::UDP, nullptr); + + if (b) + it->second = std::make_unique(_handler); + else + log::info(logcat, "Packet router already holds registered UDP packet handler!"); + + it->second->add_sub_handler(localport, std::move(func)); } void PacketRouter::add_ip_proto_handler(net::IPProtocol proto, ip_pkt_hook func) diff --git a/llarp/vpn/packet_router.hpp b/llarp/vpn/packet_router.hpp index 8fd03c8435..9c6dfec2de 100644 --- a/llarp/vpn/packet_router.hpp +++ b/llarp/vpn/packet_router.hpp @@ -20,7 +20,7 @@ namespace llarp::vpn explicit PacketRouter(ip_pkt_hook baseHandler); /// feed in an ip packet for handling - void handle_ip_packet(IPPacket pkt); + void handle_ip_packet(IPPacket pkt) const; /// add a non udp packet handler using ip protocol proto void add_ip_proto_handler(net::IPProtocol proto, ip_pkt_hook func); From 1b3a405b5d05acf01b245aff21f0c0ee15977ff4 Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 16 Jan 2025 08:18:54 -0800 Subject: [PATCH 43/44] new session tags, many:1 on paths, etc --- llarp/address/ip_range.hpp | 2 +- llarp/address/types.hpp | 6 +- llarp/auth/auth.hpp | 4 +- llarp/contact/client_contact.cpp | 6 +- llarp/contact/client_contact.hpp | 9 +- llarp/contact/client_intro.hpp | 2 +- llarp/contact/relay_contact.hpp | 2 +- llarp/contact/tag.cpp | 37 ++++-- llarp/contact/tag.hpp | 36 ++++-- llarp/dns/srv_data.hpp | 2 +- llarp/handlers/session.cpp | 56 ++++----- llarp/handlers/session.hpp | 4 +- llarp/handlers/tun.cpp | 193 +++++++++++++++++++++---------- llarp/handlers/tun.hpp | 10 +- llarp/link/link_manager.cpp | 13 +-- llarp/messages/path.hpp | 33 +++++- llarp/messages/session.hpp | 12 +- llarp/net/ip_packet.cpp | 18 +-- llarp/net/ip_packet.hpp | 3 +- llarp/net/policy.hpp | 22 ++-- llarp/net/utils.cpp | 16 +++ llarp/net/utils.hpp | 18 +-- llarp/path/path.cpp | 35 +++--- llarp/path/path.hpp | 17 ++- llarp/path/path_handler.hpp | 2 +- llarp/session/map.hpp | 18 +-- llarp/session/session.cpp | 44 ++++--- llarp/session/session.hpp | 21 ++-- 28 files changed, 411 insertions(+), 230 deletions(-) diff --git a/llarp/address/ip_range.hpp b/llarp/address/ip_range.hpp index 55e9bd4736..b5ec3caa71 100644 --- a/llarp/address/ip_range.hpp +++ b/llarp/address/ip_range.hpp @@ -222,7 +222,7 @@ namespace std template <> struct hash { - size_t operator()(const llarp::IPRange& r) const + size_t operator()(const llarp::IPRange& r) const noexcept { size_t h; diff --git a/llarp/address/types.hpp b/llarp/address/types.hpp index 350167f9fc..58f94fb281 100644 --- a/llarp/address/types.hpp +++ b/llarp/address/types.hpp @@ -32,13 +32,13 @@ namespace std template <> struct hash { - size_t operator()(const llarp::ipv4& obj) const { return hash{}(obj.addr); } + size_t operator()(const llarp::ipv4& obj) const noexcept { return hash{}(obj.addr); } }; template <> struct hash { - size_t operator()(const llarp::ipv6& obj) const + size_t operator()(const llarp::ipv6& obj) const noexcept { auto h = hash{}(obj.hi); h ^= hash{}(obj.lo) + oxen::quic::inverse_golden_ratio + (h << 6) + (h >> 2); @@ -49,7 +49,7 @@ namespace std template <> struct hash { - size_t operator()(const llarp::ip_v& obj) const + size_t operator()(const llarp::ip_v& obj) const noexcept { if (auto maybe_v4 = std::get_if(&obj)) return hash{}(*maybe_v4); diff --git a/llarp/auth/auth.hpp b/llarp/auth/auth.hpp index e22142be77..fddde53027 100644 --- a/llarp/auth/auth.hpp +++ b/llarp/auth/auth.hpp @@ -85,7 +85,7 @@ namespace llarp const std::set _files; const AuthFileType _type; mutable util::Mutex _m; - std::unordered_set _pending; + std::unordered_set _pending; /// returns an auth result for a auth info challange, opens every file until it finds a /// token matching it this is expected to be done in the IO thread AuthResult check_files(const AuthInfo& info) const; @@ -113,7 +113,7 @@ namespace llarp std::shared_ptr _omq; std::optional _omq_conn; - std::unordered_set _pending_sessions; + std::unordered_set _pending_sessions; }; } // namespace auth diff --git a/llarp/contact/client_contact.cpp b/llarp/contact/client_contact.cpp index 07111faddb..caf49b32db 100644 --- a/llarp/contact/client_contact.cpp +++ b/llarp/contact/client_contact.cpp @@ -10,7 +10,7 @@ namespace llarp Ed25519PrivateData private_data, PubKey pk, const std::unordered_set& srvs, - uint16_t proto_flags, + uint8_t proto_flags, std::optional policy) : derived_privatekey{std::move(private_data)}, pubkey{std::move(pk)}, @@ -25,7 +25,7 @@ namespace llarp Ed25519PrivateData&& private_data, PubKey&& pk, const std::unordered_set& srvs, - uint16_t proto_flags, + uint8_t proto_flags, std::optional policy) { log::info(logcat, "Generating new ClientContact..."); @@ -121,6 +121,8 @@ namespace llarp } } + session_tag ClientContact::generate_session_tag() const { return session_tag::make(protos & proto_mask); } + bool ClientContact::is_expired(std::chrono::milliseconds now) const { // check the last intro to expire diff --git a/llarp/contact/client_contact.hpp b/llarp/contact/client_contact.hpp index 7b3a63faa1..2a58f800a2 100644 --- a/llarp/contact/client_contact.hpp +++ b/llarp/contact/client_contact.hpp @@ -2,6 +2,7 @@ #include "client_intro.hpp" #include "router_id.hpp" +#include "tag.hpp" #include #include @@ -69,7 +70,7 @@ namespace llarp Ed25519PrivateData private_data, PubKey pk, const std::unordered_set& srvs, - uint16_t proto_flags, + uint8_t proto_flags, std::optional policy = std::nullopt); /** Parameters: @@ -83,7 +84,7 @@ namespace llarp Ed25519PrivateData&& private_data, PubKey&& pubkey, const std::unordered_set& srvs, - uint16_t proto_flags, + uint8_t proto_flags, std::optional policy = std::nullopt); EncryptedClientContact encrypt_and_sign() const; @@ -108,7 +109,7 @@ namespace llarp intro_set intros; std::unordered_set SRVs; - uint16_t protos; + uint8_t protos; // In exit mode, we advertise our policy for accepted traffic and the corresponding ranges std::optional exit_policy; @@ -125,6 +126,8 @@ namespace llarp // Throws if unsuccessful, must take BTDC in invocation void bt_decode(oxenc::bt_dict_consumer&& btdc); + session_tag generate_session_tag() const; + private: void _regenerate(); diff --git a/llarp/contact/client_intro.hpp b/llarp/contact/client_intro.hpp index b20e40cb89..d701de913e 100644 --- a/llarp/contact/client_intro.hpp +++ b/llarp/contact/client_intro.hpp @@ -67,7 +67,7 @@ namespace std template <> struct hash { - size_t operator()(const llarp::ClientIntro& i) const + size_t operator()(const llarp::ClientIntro& i) const noexcept { return std::hash{}(i.pivot_rid) ^ std::hash{}(i.pivot_txid); } diff --git a/llarp/contact/relay_contact.hpp b/llarp/contact/relay_contact.hpp index 14f39b37bd..2b6d87b334 100644 --- a/llarp/contact/relay_contact.hpp +++ b/llarp/contact/relay_contact.hpp @@ -292,7 +292,7 @@ namespace std template <> struct hash { - virtual size_t operator()(const llarp::RelayContact& r) const + virtual size_t operator()(const llarp::RelayContact& r) const noexcept { return std::hash{}(r.router_id()); } diff --git a/llarp/contact/tag.cpp b/llarp/contact/tag.cpp index 57dba3b9a9..6704ba2239 100644 --- a/llarp/contact/tag.cpp +++ b/llarp/contact/tag.cpp @@ -1,18 +1,39 @@ #include "tag.hpp" +#include +#include + namespace llarp { - SessionTag SessionTag::make_random() + static auto logcat = log::Cat("session-tag"); + + session_tag::session_tag(uint8_t protocol) + { + randombytes(buf.data(), SIZE); + std::memcpy(buf.data(), &protocol, sizeof(uint8_t)); + log::debug(logcat, "new session tag generated: {}", buffer_printer{buf}); + } + + session_tag session_tag::make(uint8_t protocol) { return session_tag{protocol}; } + + std::tuple session_tag::proto_bits() const { - SessionTag t; - t.Randomize(); - return t; + auto& p = buf[0]; + return {p & meta::to_underlying(protocol_flag::EXIT), p & meta::to_underlying(protocol_flag::TCP2QUIC)}; } - void SessionTag::Randomize() + void session_tag::read(std::string_view data) { - llarp::AlignedBuffer<16>::Randomize(); - /// ensure we are in the fc00 range - llarp::AlignedBuffer<16>::operator[](0) = 0xfc; + if (data.size() != SIZE) + throw std::invalid_argument{ + "Buffer size mismatch (received: {}, expected: {}) reading in session tag!"_format(data.size(), SIZE)}; + + std::memcpy(buf.data(), data.data(), data.size()); } + + std::string_view session_tag::view() const { return {reinterpret_cast(buf.data()), buf.size()}; } + + uspan session_tag::span() const { return buf; } + + std::string session_tag::to_string() const { return {reinterpret_cast(buf.data()), buf.size()}; } } // namespace llarp diff --git a/llarp/contact/tag.hpp b/llarp/contact/tag.hpp index ce071ce52d..5bcde2a384 100644 --- a/llarp/contact/tag.hpp +++ b/llarp/contact/tag.hpp @@ -2,28 +2,48 @@ // #include #include +#include namespace llarp { - struct SessionTag final : AlignedBuffer<16> + struct alignas(uint64_t) session_tag { - using AlignedBuffer<16>::AlignedBuffer; + static constexpr size_t SIZE{8}; - static SessionTag make_random(); + std::array buf; - void Randomize() override; + session_tag() = default; + + private: + session_tag(uint8_t protocol); + + public: + static session_tag make(uint8_t protocol); + + std::tuple proto_bits() const; + + void read(std::string_view buf); + + std::string_view view() const; + uspan span() const; + + auto operator<=>(const session_tag& other) const { return buf <=> other.buf; } + bool operator==(const session_tag& other) const { return (*this <=> other) == 0; } + + std::string to_string() const; + static constexpr bool to_string_formattable = true; }; + } // namespace llarp namespace std { template <> - struct hash + struct hash { - size_t operator()(const llarp::SessionTag& tag) const + size_t operator()(const llarp::session_tag& tag) const noexcept { - std::hash h{}; - return h(std::string_view{reinterpret_cast(tag.data()), tag.size()}); + return std::hash{}(tag.view()); } }; } // namespace std diff --git a/llarp/dns/srv_data.hpp b/llarp/dns/srv_data.hpp index 136d71efaa..27bcc557c0 100644 --- a/llarp/dns/srv_data.hpp +++ b/llarp/dns/srv_data.hpp @@ -101,7 +101,7 @@ namespace std template <> struct hash { - size_t operator()(const llarp::dns::SRVData& data) const + size_t operator()(const llarp::dns::SRVData& data) const noexcept { const std::hash h_str{}; const std::hash h_port{}; diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index e561a0b10c..f7b5246a5f 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -93,10 +93,13 @@ namespace llarp::handlers _auth_tokens.merge(net_config.exit_auths); } - uint16_t protoflags = meta::to_underlying(protocol_flag::TCP2QUIC); - + // always accept ipv4 (currently) + uint8_t protoflags = meta::to_underlying(protocol_flag::IPV4); + if (!_is_v4) + protoflags |= meta::to_underlying(protocol_flag::IPV6); + // if we are a full client, we accept standard and tunneled (tcp2quic) traffic if (_router.using_tun_if()) - protoflags |= meta::to_underlying(_is_v4 ? protocol_flag::IPV4 : protocol_flag::IPV6); + protoflags |= meta::to_underlying(protocol_flag::TCP2QUIC); if (_is_exit_node) protoflags |= meta::to_underlying(protocol_flag::EXIT); @@ -137,7 +140,7 @@ namespace llarp::handlers update_and_publish_localcc(get_current_client_intros(), _srv_records); } - static std::atomic testnet_trigger = false; + // static std::atomic testnet_trigger = false; void SessionEndpoint::start_tickers() { @@ -152,24 +155,25 @@ namespace llarp::handlers }, true); - if (not testnet_trigger) - { - testnet_trigger = true; - - _router.loop()->call_later(5s, [this]() { - try - { - RouterID cpk{oxenc::from_base32z("acit6x8kwxdehpkzrpunw5nb8mf4w5u8tn3ojmxit9rpnhhhp81y")}; - log::info(logcat, "Beginning session init to client: {}", cpk.to_network_address(false)); - _initiate_session( - NetworkAddress::from_pubkey(cpk, true), [](ip_v) { log::critical(logcat, "FUCK YEAH"); }); - } - catch (const std::exception& e) - { - log::critical(logcat, "Failed to parse client netaddr: {}", e.what()); - } - }); - } + // if (not testnet_trigger) + // { + // testnet_trigger = true; + + // _router.loop()->call_later(5s, [this]() { + // try + // { + // RouterID cpk{oxenc::from_base32z("fs4kczh5ypnq7cd3sf4qxceqjhmznkhgauutwhf8a5rpzr9cnaky")}; + // log::info(logcat, "Beginning session init to client: {}", cpk.to_network_address(false)); + // _initiate_session( + // NetworkAddress::from_pubkey(cpk, true), [](ip_v) { log::critical(logcat, "FUCK YEAH"); + // }); + // } + // catch (const std::exception& e) + // { + // log::critical(logcat, "Failed to parse client netaddr: {}", e.what()); + // } + // }); + // } } else log::info(logcat, "SessionEndpoint configured to NOT publish ClientContact..."); @@ -426,7 +430,7 @@ namespace llarp::handlers bool SessionEndpoint::prefigure_session( NetworkAddress initiator, - SessionTag tag, + session_tag tag, HopID remote_pivot_txid, std::shared_ptr path, shared_kx_data kx_data, @@ -560,7 +564,7 @@ namespace llarp::handlers - 'x' : encrypted payload - 'i' : RouterID of initiator - 'p' : HopID at the pivot taken from remote ClientIntro - - 's' : SessionTag for current session + - 's' : session_tag for current session - 't' : Use Tun interface (bool) - 'u' : Authentication field - bt-encoded dict, values TBD @@ -572,7 +576,7 @@ namespace llarp::handlers on_session_init_hook cb, bool /* is_exit */) { - auto tag = SessionTag::make_random(); + auto tag = client_contact.generate_session_tag(); std::string inner_payload; shared_kx_data kx_data; @@ -601,7 +605,7 @@ namespace llarp::handlers std::move(intermediate_payload), [this, remote, - tag, + tag = std::move(tag), path, remote_pivot_txid = remote_intro.pivot_txid, hook = std::move(cb), diff --git a/llarp/handlers/session.hpp b/llarp/handlers/session.hpp index 01d18c6225..d5e697a630 100644 --- a/llarp/handlers/session.hpp +++ b/llarp/handlers/session.hpp @@ -87,7 +87,7 @@ namespace llarp std::set srv_records() const { return {_srv_records.begin(), _srv_records.end()}; } template - std::shared_ptr get_session(const SessionTag& tag) const + std::shared_ptr get_session(const session_tag& tag) const { return std::static_pointer_cast(_sessions.get_session(tag)); } @@ -123,7 +123,7 @@ namespace llarp bool prefigure_session( NetworkAddress initiator, - SessionTag tag, + session_tag tag, HopID remote_pivot_txid, std::shared_ptr path, shared_kx_data kx_data, diff --git a/llarp/handlers/tun.cpp b/llarp/handlers/tun.cpp index c2d60e7c1f..adef0537cf 100644 --- a/llarp/handlers/tun.cpp +++ b/llarp/handlers/tun.cpp @@ -415,7 +415,7 @@ namespace llarp::handlers // [this, snode, msg, reply, isV6]( // const RouterID&, // std::shared_ptr s, - // [[maybe_unused]] SessionTag tag) { + // [[maybe_unused]] session_tag tag) { // SendDNSReply(snode, s, msg, reply, isV6); // }); // }; @@ -965,10 +965,7 @@ namespace llarp::handlers if constexpr (llarp::platform::is_apple) { if (ip_equals_address(dest, _local_addr, pkt_is_ipv4)) - { - rewrite_and_send_packet(std::move(pkt), src, dest); - return; - } + return rewrite_and_send_packet(std::move(pkt), std::move(src), std::move(dest)); } // we pass `dest` because that is our local private IP on the outgoing IPPacket @@ -979,14 +976,25 @@ namespace llarp::handlers if (auto session = _router.session_endpoint()->get_session(remote)) { - log::info(logcat, "Dispatching outbound {}B packet for session (remote: {})", pkt.size(), remote); + log::info( + logcat, + "Dispatching outbound {}B packet for session (remote: {}): {}", + pkt.size(), + remote, + pkt.info_line()); session->send_path_data_message(std::move(pkt).steal_payload()); } else log::info(logcat, "Could not find session (remote: {}) for outbound packet!", remote); } else - log::debug(logcat, "Could not find remote for route {}", pkt.info_line()); + { + log::critical(logcat, "Could not find remote for route {}", pkt.info_line()); + + // make ICMP unreachable + if (auto icmp = pkt.make_icmp_unreachable()) + rewrite_and_send_packet(std::move(*icmp), std::move(src), std::move(dest)); + } } std::optional TunEndpoint::obtain_src_for_remote(const NetworkAddress& remote, bool use_ipv4) @@ -1025,86 +1033,155 @@ namespace llarp::handlers send_packet_to_net_if(std::move(pkt)); } - // handles an inbound packet coming IN from network -> user - bool TunEndpoint::handle_inbound_packet( - IPPacket pkt, NetworkAddress remote, bool is_exit_session, bool is_outbound_session) + void TunEndpoint::handle_inbound_packet(IPPacket pkt, session_tag tag, NetworkAddress remote) { ip_v src, dest; - auto pkt_is_ipv4 = pkt.is_ipv4(); - if (is_exit_session and is_outbound_session) - { - log::info(logcat, "inbound exit session pkt: {}", pkt.info_line()); - // we are receiving traffic from a session to a remote exit node - if (pkt_is_ipv4) - { - src = pkt.source_ipv4(); - dest = _local_addr.to_ipv4(); - } - else - { - src = pkt.source_ipv6(); - dest = _local_ipv6.to_ipv6(); - } - - assert(remote.is_client()); + auto [is_exit_pkt, is_tunneled_pkt] = tag.proto_bits(); - auto maybe_remote = _local_ip_mapping.get_remote_from_local(src); + if (is_tunneled_pkt) + { + log::critical(logcat, "Dropping tcp2quic pkt"); + // TODO: pass to tunnel + // TODO: also finish quic tunnel + // TODO: route this even earlier - if (not maybe_remote) - { - log::info(logcat, "Could not find mapping of local IP (ip:{}) for session to remote: {}", src, remote); - return false; - } - if (*maybe_remote != remote) - { - log::info( - logcat, - "Internal mapping of local IP (ip:{}, remote:{}) did not match inbound packet from remote: {}", - src, - *maybe_remote, - remote); - return false; - } + return; } - else + + if (is_exit_pkt) { - if (is_exit_session and not is_outbound_session) + if (is_exit_node()) // traffic to local exit node { - log::info(logcat, "inbound exit session pkt: {}", pkt.info_line()); - // we are receiving traffic from a session to a local exit node + log::info(logcat, "inbound exit pkt for local exit node: {}", pkt.info_line()); + if (not _exit_policy->allow_ip_traffic(pkt)) - return false; + { + log::warning(logcat, "Invalid pkt proto ({}) for local exit", pkt.protocol()); + return; + } if (pkt_is_ipv4) dest = pkt.dest_ipv4(); else dest = pkt.dest_ipv6(); } - else + else // traffic to remote exit node { - log::info(logcat, "inbound service session pkt: {}", pkt.info_line()); - // we are receiving hidden service traffic + log::info(logcat, "inbound exit pkt from remote exit node: {}", pkt.info_line()); + if (pkt_is_ipv4) + { + src = pkt.source_ipv4(); dest = _local_addr.to_ipv4(); + } else - dest = _local_ipv6.to_ipv6(); + { + src = pkt.source_ipv6(); + dest = _local_addr.to_ipv6(); + } } + } + else + { + log::info(logcat, "inbound session pkt: {}", pkt.info_line()); - if (auto maybe_src = obtain_src_for_remote(remote, pkt_is_ipv4)) - src = std::move(*maybe_src); + if (pkt_is_ipv4) + dest = _local_addr.to_ipv4(); else - return false; + dest = _local_addr.to_ipv6(); } - log::trace(logcat, "src:{}, dest:{}", src, dest); + if (auto maybe_src = obtain_src_for_remote(remote, pkt_is_ipv4)) + src = std::move(*maybe_src); + else + return; + log::trace(logcat, "src:{}, dest:{}", src, dest); rewrite_and_send_packet(std::move(pkt), src, dest); - - return true; } + // handles an inbound packet coming IN from network -> user + // bool TunEndpoint::handle_inbound_packet( + // IPPacket pkt, NetworkAddress remote, bool is_exit_session, bool is_outbound_session) + // { + // ip_v src, dest; + + // auto pkt_is_ipv4 = pkt.is_ipv4(); + + // if (is_exit_session and is_outbound_session) + // { + // log::info(logcat, "inbound exit session pkt: {}", pkt.info_line()); + // // we are receiving traffic from a session to a remote exit node + // if (pkt_is_ipv4) + // { + // src = pkt.source_ipv4(); + // dest = _local_addr.to_ipv4(); + // } + // else + // { + // src = pkt.source_ipv6(); + // dest = _local_ipv6.to_ipv6(); + // } + + // assert(remote.is_client()); + + // auto maybe_remote = _local_ip_mapping.get_remote_from_local(src); + + // if (not maybe_remote) + // { + // log::info(logcat, "Could not find mapping of local IP (ip:{}) for session to remote: {}", src, + // remote); return false; + // } + // if (*maybe_remote != remote) + // { + // log::info( + // logcat, + // "Internal mapping of local IP (ip:{}, remote:{}) did not match inbound packet from remote: {}", + // src, + // *maybe_remote, + // remote); + // return false; + // } + // } + // else + // { + // if (is_exit_session and not is_outbound_session) + // { + // log::info(logcat, "inbound exit session pkt: {}", pkt.info_line()); + // // we are receiving traffic from a session to a local exit node + // if (not _exit_policy->allow_ip_traffic(pkt)) + // return false; + + // if (pkt_is_ipv4) + // dest = pkt.dest_ipv4(); + // else + // dest = pkt.dest_ipv6(); + // } + // else + // { + // log::info(logcat, "inbound service session pkt: {}", pkt.info_line()); + // // we are receiving hidden service traffic + // if (pkt_is_ipv4) + // dest = _local_addr.to_ipv4(); + // else + // dest = _local_ipv6.to_ipv6(); + // } + + // if (auto maybe_src = obtain_src_for_remote(remote, pkt_is_ipv4)) + // src = std::move(*maybe_src); + // else + // return false; + // } + + // log::trace(logcat, "src:{}, dest:{}", src, dest); + + // rewrite_and_send_packet(std::move(pkt), src, dest); + + // return true; + // } + void TunEndpoint::start_poller() { if (not _poller->start()) diff --git a/llarp/handlers/tun.hpp b/llarp/handlers/tun.hpp index f33d4f090b..951078f31c 100644 --- a/llarp/handlers/tun.hpp +++ b/llarp/handlers/tun.hpp @@ -112,8 +112,12 @@ namespace llarp::handlers void rewrite_and_send_packet(IPPacket&& pkt, ip_v src, ip_v dest); + // TESTNET: TODO: new inbound packet handling logic + void handle_inbound_packet(IPPacket pkt, session_tag tag, NetworkAddress remote); + // Handles an inbound packet coming IN from the network - bool handle_inbound_packet(IPPacket pkt, NetworkAddress remote, bool is_exit_session, bool is_outbound_session); + // bool handle_inbound_packet(IPPacket pkt, NetworkAddress remote, bool is_exit_session, bool + // is_outbound_session); // Upon session creation, SessionHandler will instruct TunEndpoint to requisition a private IP through which to // route session traffic @@ -125,7 +129,7 @@ namespace llarp::handlers bool has_if_addr() const { return true; } - std::optional get_traffic_policy() const { return _exit_policy; } + std::optional get_exit_policy() const { return _exit_policy; } std::chrono::milliseconds get_path_alignment_timeout() const { return _path_alignment_timeout; } @@ -145,7 +149,7 @@ namespace llarp::handlers void start_poller(); // Stores assigned IP's for each session in/out of this lokinet instance - // - Reserved local addresses is directly pre-loaded from config + // - Reserved local addresses are directly pre-loaded from config // - Persisting address map is directly pre-loaded from config address_map _local_ip_mapping; diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index e21ba885be..7e6629ed72 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -310,7 +310,7 @@ namespace llarp [this](oxen::quic::dgram_interface&, bstring dgram) { return handle_path_data_message(std::move(dgram)); }, is_service_node() ? alpns::SERVICE_INBOUND : alpns::CLIENT_INBOUND, is_service_node() ? alpns::SERVICE_OUTBOUND : alpns::CLIENT_OUTBOUND, - oxen::quic::opt::enable_datagrams{}); + oxen::quic::opt::enable_datagrams{/* oxen::quic::Splitting::ACTIVE */}); // While only service nodes accept inbound connections, clients must have this key verify // callback set. It will reject any attempted inbound connection to a lokinet client prior @@ -1501,20 +1501,17 @@ namespace llarp log::trace(logcat, "Received path data for local client: {}", buffer_printer{payload}); - NetworkAddress sender; - bstring data; - try { - std::tie(sender, data) = PATH::DATA::deserialize(oxenc::bt_dict_consumer{payload}); + auto [tag, data] = PATH::DATA::deserialize_inner(std::move(payload)); - if (auto session = _router.session_endpoint()->get_session(sender)) + if (auto session = _router.session_endpoint()->get_session(tag)) { session->recv_path_data_message(std::move(data)); } else { - log::warning(logcat, "Could not find session (remote:{}) to relay path data message!", sender); + log::warning(logcat, "Could not find session (tag:{}) to relay path data message!", tag); } } catch (const std::exception& e) @@ -1653,7 +1650,7 @@ namespace llarp log::trace(logcat, "{} called", __PRETTY_FUNCTION__); NetworkAddress initiator; - SessionTag tag; + session_tag tag; HopID remote_pivot_txid; HopID local_pivot_txid; bool use_tun; diff --git a/llarp/messages/path.hpp b/llarp/messages/path.hpp index ddda730de8..6c1b37ccf4 100644 --- a/llarp/messages/path.hpp +++ b/llarp/messages/path.hpp @@ -287,6 +287,13 @@ namespace llarp return std::move(btdp).str(); } + inline static std::string serialize_inner(std::string body, session_tag tag) + { + std::string payload{tag.view()}; + payload.append(body); + return payload; + } + inline static std::tuple deserialize(oxenc::bt_dict_consumer&& btdc) { RouterID remote; @@ -302,7 +309,8 @@ namespace llarp } catch (const std::exception& e) { - throw std::runtime_error{"Exception caught deserializing path data:{}"_format(e.what())}; + throw std::runtime_error{ + "Exception caught deserializing outer datagram payload: {}"_format(e.what())}; } } @@ -320,7 +328,28 @@ namespace llarp } catch (const std::exception& e) { - throw std::runtime_error{"Exception caught deserializing path data:{}"_format(e.what())}; + throw std::runtime_error{ + "Exception caught deserializing intermediate datagram payload: {}"_format(e.what())}; + } + } + + inline static std::tuple> deserialize_inner(std::string&& payload) + { + session_tag t{}; + std::vector body{}; + + try + { + t.read({payload.data(), session_tag::SIZE}); + body.resize(payload.size() - session_tag::SIZE); + std::memmove(body.data(), payload.data() + session_tag::SIZE, payload.size() - session_tag::SIZE); + + return {std::move(t), std::move(body)}; + } + catch (const std::exception& e) + { + throw std::runtime_error{ + "Exception caught deserializing inner datagram payload: {}"_format(e.what())}; } } } // namespace DATA diff --git a/llarp/messages/session.hpp b/llarp/messages/session.hpp index 83b8351cce..cedcca9409 100644 --- a/llarp/messages/session.hpp +++ b/llarp/messages/session.hpp @@ -15,7 +15,7 @@ namespace llarp - 'i' : RouterID of initiator - 'p' : HopID at the pivot taken from local ClientIntro - 'r' : HopID at the pivot taken from remote's ClientIntro - - 's' : SessionTag for current session + - 's' : session_tag for current session - 't' : Use Tun interface (bool) - 'u' : Authentication field - bt-encoded dict, values TBD @@ -31,7 +31,7 @@ namespace llarp const RouterID& local, const RouterID& remote, HopID local_pivot_txid, - SessionTag& tag, + session_tag& tag, HopID remote_pivot_txid, std::optional auth_token, bool use_tun) @@ -46,7 +46,7 @@ namespace llarp btdp.append("i", local.to_view()); btdp.append("p", local_pivot_txid.to_view()); btdp.append("r", remote_pivot_txid.to_view()); - btdp.append("s", tag.to_view()); + btdp.append("s", tag.view()); btdp.append("t", use_tun); // TOTHINK: this auth field if (auth_token) @@ -73,7 +73,7 @@ namespace llarp }; inline static std:: - tuple> + tuple> decrypt_deserialize(oxenc::bt_dict_consumer&& outer_btdc, const Ed25519SecretKey& local) { SymmNonce nonce; @@ -98,7 +98,7 @@ namespace llarp NetworkAddress initiator; RouterID init_rid; - SessionTag tag; + session_tag tag; HopID remote_pivot_txid; HopID local_pivot_txid; bool use_tun; @@ -108,7 +108,7 @@ namespace llarp initiator = NetworkAddress::from_pubkey(init_rid, true); remote_pivot_txid.from_string(btdc.require("p")); local_pivot_txid.from_string(btdc.require("r")); - tag.from_string(btdc.require("s")); + tag.read(btdc.require("s")); use_tun = btdc.require("t"); maybe_auth = btdc.maybe("u"); diff --git a/llarp/net/ip_packet.cpp b/llarp/net/ip_packet.cpp index 8d7006de92..e323190ad8 100644 --- a/llarp/net/ip_packet.cpp +++ b/llarp/net/ip_packet.cpp @@ -78,11 +78,11 @@ namespace llarp return; _is_v4 = _header->version == v4_header_version; - _is_udp = _proto == net::IPProtocol::UDP; + auto keep_port = _proto == net::IPProtocol::UDP || _proto == net::IPProtocol::TCP; uint16_t src_port = - (_is_udp) ? *reinterpret_cast(data() + (static_cast(_header->header_len) * 4)) : 0; - uint16_t dest_port = (_is_udp) + (keep_port) ? *reinterpret_cast(data() + (static_cast(_header->header_len) * 4)) : 0; + uint16_t dest_port = (keep_port) ? *reinterpret_cast(data() + (static_cast(_header->header_len) * 4) + 2) : 0; @@ -250,6 +250,8 @@ namespace llarp uint16_t chksumoff{0}; uint16_t chksum{0}; + bool is_udp = false; + switch (nextproto) { case 6: // TCP @@ -262,25 +264,25 @@ namespace llarp chksum = 0x0000; chksumoff = chksumoff == 16 ? 16 : 6; - _is_udp = false; break; case 17: // UDP case 136: // UDP-Lite - same checksum place, same 0->0xFFff condition chksum = udp_checksum_ipv6(&hdr->src, &hdr->dest, hdr->payload_len, 0); - _is_udp = true; + is_udp = true; break; default: // do nothing break; } - auto check = _is_udp ? (uint16_t*)(pld + 6) : (uint16_t*)(pld + chksumoff - fragoff); + auto check = is_udp ? (uint16_t*)(pld + 6) : (uint16_t*)(pld + chksumoff - fragoff); *check = chksum; _init_internals(); } + // TODO: make a compile-time ICMP template with configurable fields std::optional IPPacket::make_icmp_unreachable() const { if (is_ipv4()) @@ -300,7 +302,7 @@ namespace llarp pkt_header->dest = _header->src; pkt_header->protocol = 1; // ICMP pkt_header->ttl = pkt_header->ttl; - pkt_header->frag_off = htons(0b0100000000000000); + pkt_header->frag_off = oxenc::host_to_big(0b0100000000000000); uint8_t* itr = pkt.data() + ip_hdr_sz; uint8_t* icmp_begin = itr; // type 'destination unreachable' @@ -327,6 +329,8 @@ namespace llarp // calculate icmp checksum *checksum = utils::ip_checksum(icmp_begin, std::distance(icmp_begin, itr)); + + log::debug(logcat, "ICMP unreachable pkt configured"); return pkt; } diff --git a/llarp/net/ip_packet.hpp b/llarp/net/ip_packet.hpp index 52fc5b51b9..da146d2472 100644 --- a/llarp/net/ip_packet.hpp +++ b/llarp/net/ip_packet.hpp @@ -42,13 +42,14 @@ namespace llarp oxen::quic::Address _dst_addr{}; bool _is_v4{true}; - bool _is_udp{false}; net::IPProtocol _proto{}; void _init_internals(); public: + // TESTNET: TODO: after merging libquic retyping for libc++19, revise these constructors + IPPacket() : IPPacket{size_t{0}} {} explicit IPPacket(size_t sz); explicit IPPacket(bstring_view data); diff --git a/llarp/net/policy.hpp b/llarp/net/policy.hpp index dc7321c02c..818c3c0089 100644 --- a/llarp/net/policy.hpp +++ b/llarp/net/policy.hpp @@ -12,14 +12,22 @@ namespace llarp { struct IPPacket; - enum class protocol_flag : uint16_t + inline constexpr uint8_t proto_mask{0b0000'0011}; + + /** protocol_flag + - When negotiating sessions and advertising client contacts, all flags can be used + - When prepended to a datagram, only 2 bits are needed for 4 configurations + - host, standard = 00 + - host, tcp2quic = 01 + - exit, standard = 10 + - exit, tcp2quic = 11 + */ + enum class protocol_flag : uint8_t { - CONTROL = 1 << 0, - IPV4 = 1 << 1, - IPV6 = 1 << 2, - EXIT = 1 << 3, - AUTH = 1 << 4, - TCP2QUIC = 1 << 5, + EXIT = 1 << 0, + TCP2QUIC = 1 << 1, + IPV4 = 1 << 2, + IPV6 = 1 << 3, }; // TODO: WIP implementation diff --git a/llarp/net/utils.cpp b/llarp/net/utils.cpp index 04a433b8a8..b7bed3c244 100644 --- a/llarp/net/utils.cpp +++ b/llarp/net/utils.cpp @@ -1,7 +1,23 @@ #include "utils.hpp" +#include + namespace llarp { + static auto logcat = log::Cat("net-utils"); + + bool ip_equals_address(const ip_v &ip, const oxen::quic::Address &addr, bool compare_v4) + { + if (compare_v4 and std::holds_alternative(ip)) + return std::get(ip) == addr.to_ipv4(); + + if (not compare_v4 and std::holds_alternative(ip)) + return std::get(ip) == addr.to_ipv6(); + + log::warning(logcat, "Failed to compare ip variant in desired ipv{} scheme!", compare_v4 ? "4" : "6"); + return false; + } + namespace utils { static constexpr uint32_t add_u32(uint32_t x) { return uint32_t{x & 0xFFff} + uint32_t{x >> 16}; } diff --git a/llarp/net/utils.hpp b/llarp/net/utils.hpp index 8846da5f7d..c98c60aaab 100644 --- a/llarp/net/utils.hpp +++ b/llarp/net/utils.hpp @@ -11,20 +11,10 @@ namespace llarp // Compares the given ip variant against a quic address // Returns: // - true : ip == address - // - false : ip != address - // Error: - // - throws : ip and address are mismatched ipv4 vs ipv6 - inline bool ip_equals_address(const ip_v &ip, const oxen::quic::Address &addr, bool compare_v4) - { - if (compare_v4 and std::holds_alternative(ip)) - return std::get(ip) == addr.to_ipv4(); - - if (not compare_v4 and std::holds_alternative(ip)) - return std::get(ip) == addr.to_ipv6(); - - throw std::invalid_argument{ - "Failed to compare ip variant in desired {} scheme!"_format(compare_v4 ? "ipv4" : "ipv6")}; - } + // - false : + // - ip != address + // - ip and address are mismatched ipv4 vs ipv6 + bool ip_equals_address(const ip_v &ip, const oxen::quic::Address &addr, bool compare_v4); namespace utils { diff --git a/llarp/path/path.cpp b/llarp/path/path.cpp index 9fe5e115df..31cf9f4559 100644 --- a/llarp/path/path.cpp +++ b/llarp/path/path.cpp @@ -86,33 +86,28 @@ namespace llarp::path logcat, "Path client intro holding pivot_rid ({}) and pivot_txid ({})", intro.pivot_rid, intro.pivot_txid); } - void Path::link_session(recv_session_dgram_cb cb) + void Path::link_session(session_tag t) { - _recv_dgram = std::move(cb); - _is_linked = true; + _linked_sessions.insert(t); + log::critical(logcat, "Current path has {} linked sessions!", _linked_sessions.size()); _is_session_path = true; } - bool Path::unlink_session() + bool Path::unlink_session(session_tag t) { - if (_is_linked) - { - _is_linked = false; - _recv_dgram = nullptr; - return true; - } - - log::warning(logcat, "Path is not currently linked to an ongoing session!"); - return false; + auto n = _linked_sessions.erase(t); + _is_session_path = not _linked_sessions.empty(); + log::critical(logcat, "Current path has {} linked sessions!", _linked_sessions.size()); + return n != 0; } - void Path::recv_path_data_message(bstring data) - { - if (_recv_dgram) - _recv_dgram(std::move(data)); - else - throw std::runtime_error{"Path does not have hook to receive datagrams!"}; - } + // void Path::recv_path_data_message(bstring data) + // { + // if (_recv_dgram) + // _recv_dgram(std::move(data)); + // else + // throw std::runtime_error{"Path does not have hook to receive datagrams!"}; + // } bool Path::operator<(const Path& other) const { diff --git a/llarp/path/path.hpp b/llarp/path/path.hpp index fa678f4d97..605236338d 100644 --- a/llarp/path/path.hpp +++ b/llarp/path/path.hpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -32,8 +33,6 @@ namespace llarp namespace path { - using recv_session_dgram_cb = std::function; - /// A path we made struct Path : public std::enable_shared_from_this { @@ -68,13 +67,13 @@ namespace llarp void set_established(); - void recv_path_data_message(bstring data); + // void recv_path_data_message(bstring data); - void link_session(recv_session_dgram_cb cb); + void link_session(session_tag t); - bool unlink_session(); + bool unlink_session(session_tag t); - bool is_linked() const { return _is_linked; } + bool is_linked() const { return not _linked_sessions.empty(); } void enable_exit_traffic(); @@ -145,8 +144,6 @@ namespace llarp std::string name() const; - bool is_session_path() const { return _is_session_path; } - bool is_client_path() const { return _is_client; } bool operator<(const Path& other) const; @@ -174,7 +171,7 @@ namespace llarp const size_t num_hops; - recv_session_dgram_cb _recv_dgram; + std::unordered_set _linked_sessions; std::chrono::milliseconds last_recv_msg{0s}; std::chrono::milliseconds last_latency_test{0s}; @@ -188,7 +185,7 @@ namespace std template <> struct hash { - size_t operator()(const llarp::path::Path& p) const + size_t operator()(const llarp::path::Path& p) const noexcept { auto h = hash{}(p.upstream_txid()); return h ^ hash{}(p.upstream_rid()); diff --git a/llarp/path/path_handler.hpp b/llarp/path/path_handler.hpp index 630bba4749..63db6e3795 100644 --- a/llarp/path/path_handler.hpp +++ b/llarp/path/path_handler.hpp @@ -16,7 +16,7 @@ namespace std template <> struct hash> { - size_t operator()(const std::pair& i) const + size_t operator()(const std::pair& i) const noexcept { return hash{}(i.first) ^ hash{}(i.second); } diff --git a/llarp/session/map.hpp b/llarp/session/map.hpp index e2abd8b187..d72fc2adcf 100644 --- a/llarp/session/map.hpp +++ b/llarp/session/map.hpp @@ -7,6 +7,8 @@ namespace llarp { + // TESTNET: TODO: revisit this later; if we never need NetworkAddr as a key, just use tag + /** This class will accept any types satisfying the concepts SessionType and NetworkAddrType NetworkAddrType: must be inherited from NetworkAddress SessionType: must be inherited from BaseSession @@ -18,7 +20,7 @@ namespace llarp struct session_map { protected: - std::unordered_map _session_lookup; + std::unordered_map _session_lookup; std::unordered_map> _sessions; using Lock_t = util::NullLock; @@ -81,7 +83,7 @@ namespace llarp return {_2->second, b1 & b2}; } - std::optional get_remote(const SessionTag& tag) const + std::optional get_remote(const session_tag& tag) const { Lock_t l{session_mutex}; @@ -105,19 +107,19 @@ namespace llarp return ret; } - std::shared_ptr get_session(const SessionTag& tag) const + std::shared_ptr get_session(const session_tag& tag) const { Lock_t l{session_mutex}; std::shared_ptr ret = nullptr; - if (auto itr = get_remote(tag); itr != std::nullopt) - ret = get_session(itr->second); + if (auto remote = get_remote(tag); remote != std::nullopt) + ret = get_session(*remote); return ret; } - void unmap(const SessionTag& tag) + void unmap(const session_tag& tag) { Lock_t l{session_mutex}; @@ -147,7 +149,7 @@ namespace llarp } } - bool have_session(const SessionTag& tag) const + bool have_session(const session_tag& tag) const { Lock_t l{session_mutex}; @@ -164,7 +166,7 @@ namespace llarp return _sessions.count(local); } - std::shared_ptr operator[](const SessionTag& tag) { return get_session(tag); } + std::shared_ptr operator[](const session_tag& tag) { return get_session(tag); } std::shared_ptr operator[](const net_addr_t& local) { return get_session(local); } }; diff --git a/llarp/session/session.cpp b/llarp/session/session.cpp index 842c530fde..0a0ca7c460 100644 --- a/llarp/session/session.cpp +++ b/llarp/session/session.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include @@ -20,7 +19,7 @@ namespace llarp::session handlers::SessionEndpoint& parent, NetworkAddress remote, HopID remote_pivot_txid, - SessionTag _t, + session_tag _t, bool use_tun, bool is_outbound, std::optional kx_data) @@ -35,6 +34,16 @@ namespace llarp::session if (kx_data.has_value()) session_keys = std::move(*kx_data); + if (_use_tun) + _recv_dgram = [this](std::vector data) { + _r.tun_endpoint()->handle_inbound_packet(IPPacket{std::move(data)}, _tag, _remote); + }; + else + _recv_dgram = [this](std::vector data) { + _ep->manually_receive_packet( + NetworkPacket{oxen::quic::Path{}, bstring{reinterpret_cast(data.data()), data.size()}}); + }; + set_new_current_path(std::move(_p)); } @@ -46,31 +55,29 @@ namespace llarp::session bool BaseSession::send_path_data_message(std::string data) { - auto inner_payload = PATH::DATA::serialize(std::move(data), _r.local_rid()); + auto inner_payload = PATH::DATA::serialize_inner(std::move(data), _tag); auto intermediate_payload = PATH::DATA::serialize_intermediate(std::move(inner_payload), _remote_pivot_txid); return _r.send_data_message( _current_path->upstream_rid(), _current_path->make_path_message(std::move(intermediate_payload))); } - void BaseSession::recv_path_data_message(bstring body) { _current_path->recv_path_data_message(std::move(body)); } + void BaseSession::recv_path_data_message(std::vector data) + { + if (_recv_dgram) + _recv_dgram(std::move(data)); + else + throw std::runtime_error{"Session does not have hook to receive datagrams!"}; + } void BaseSession::set_new_current_path(std::shared_ptr _new_path) { if (_current_path) - _current_path->unlink_session(); + _current_path->unlink_session(_tag); _current_path = std::move(_new_path); _pivot_txid = _current_path->pivot_txid(); - if (_use_tun) - _current_path->link_session([this](bstring data) { - _r.tun_endpoint()->handle_inbound_packet( - IPPacket{std::move(data)}, _remote, _is_exit_session, _is_outbound); - }); - else - _current_path->link_session([this](bstring data) { - _ep->manually_receive_packet(NetworkPacket{oxen::quic::Path{}, std::move(data)}); - }); + _current_path->link_session(_tag); assert(_current_path->is_linked()); } @@ -79,8 +86,7 @@ namespace llarp::session { _ep = _r.quic_tunnel()->net()->endpoint( LOCALHOST_BLANK, oxen::quic::opt::manual_routing{[this](const oxen::quic::Path&, bstring_view data) { - _current_path->send_path_data_message( - std::string{reinterpret_cast(data.data()), data.size()}); + send_path_data_message(std::string{reinterpret_cast(data.data()), data.size()}); }}); } @@ -159,7 +165,7 @@ namespace llarp::session handlers::SessionEndpoint& parent, std::shared_ptr path, HopID remote_pivot_txid, - SessionTag _t, + session_tag _t, std::optional kx_data) : PathHandler{parent._router, path::DEFAULT_PATHS_HELD}, BaseSession{ @@ -325,7 +331,7 @@ namespace llarp::session std::shared_ptr _path, handlers::SessionEndpoint& parent, HopID remote_pivot_txid, - SessionTag _t, + session_tag _t, bool use_tun, std::optional kx_data) : BaseSession{ @@ -340,5 +346,5 @@ namespace llarp::session std::move(kx_data)} {} - void InboundSession::set_new_tag(const SessionTag& tag) { _tag = tag; } + void InboundSession::set_new_tag(const session_tag& tag) { _tag = tag; } } // namespace llarp::session diff --git a/llarp/session/session.hpp b/llarp/session/session.hpp index 67c08eed24..42d266e4dd 100644 --- a/llarp/session/session.hpp +++ b/llarp/session/session.hpp @@ -15,6 +15,7 @@ namespace llarp { using on_session_init_hook = std::function; + using recv_session_dgram_cb = std::function)>; namespace link { @@ -44,7 +45,7 @@ namespace llarp Router& _r; handlers::SessionEndpoint& _parent; - SessionTag _tag; + session_tag _tag; NetworkAddress _remote; shared_kx_data session_keys{}; @@ -60,6 +61,8 @@ namespace llarp std::shared_ptr _current_path; HopID _pivot_txid; + recv_session_dgram_cb _recv_dgram; + // manually routed QUIC endpoint std::shared_ptr _ep; @@ -81,7 +84,7 @@ namespace llarp handlers::SessionEndpoint& parent, NetworkAddress remote, HopID remote_pivot_txid, - SessionTag _t, + session_tag _t, bool use_tun, bool is_outbound, std::optional kx_data = std::nullopt); @@ -99,7 +102,9 @@ namespace llarp bool send_path_data_message(std::string data); - void recv_path_data_message(bstring data); + void recv_path_data_message(std::vector data); + + // void recv_path_data_message(bstring data); void set_new_current_path(std::shared_ptr _new_path); @@ -109,9 +114,9 @@ namespace llarp bool using_tun() const { return _use_tun; } - SessionTag tag() { return _tag; } + session_tag tag() { return _tag; } - const SessionTag& tag() const { return _tag; } + const session_tag& tag() const { return _tag; } bool is_exit_session() const { return _is_exit_session; } }; @@ -126,7 +131,7 @@ namespace llarp handlers::SessionEndpoint& parent, std::shared_ptr path, HopID remote_pivot_txid, - SessionTag _t, + session_tag _t, std::optional kx_data = std::nullopt); ~OutboundSession() override; @@ -184,13 +189,13 @@ namespace llarp std::shared_ptr _path, handlers::SessionEndpoint& parent, HopID remote_pivot_txid, - SessionTag _t, + session_tag _t, bool use_tun, std::optional kx_data = std::nullopt); ~InboundSession() = default; - void set_new_tag(const SessionTag& tag); + void set_new_tag(const session_tag& tag); }; } // namespace session From b3ca8c08264581360bd891812d8ba5c9ae87052a Mon Sep 17 00:00:00 2001 From: dr7ana Date: Thu, 16 Jan 2025 08:28:44 -0800 Subject: [PATCH 44/44] testing dgram split on testnet --- llarp/handlers/session.cpp | 2 +- llarp/link/link_manager.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/llarp/handlers/session.cpp b/llarp/handlers/session.cpp index f7b5246a5f..2df55bd8ec 100644 --- a/llarp/handlers/session.cpp +++ b/llarp/handlers/session.cpp @@ -162,7 +162,7 @@ namespace llarp::handlers // _router.loop()->call_later(5s, [this]() { // try // { - // RouterID cpk{oxenc::from_base32z("fs4kczh5ypnq7cd3sf4qxceqjhmznkhgauutwhf8a5rpzr9cnaky")}; + // RouterID cpk{oxenc::from_base32z("xr8qpu9pu4qp4nhooiktfuyrwmgkut4ud3kqsf9tscwa8rtzuzhy")}; // log::info(logcat, "Beginning session init to client: {}", cpk.to_network_address(false)); // _initiate_session( // NetworkAddress::from_pubkey(cpk, true), [](ip_v) { log::critical(logcat, "FUCK YEAH"); diff --git a/llarp/link/link_manager.cpp b/llarp/link/link_manager.cpp index 7e6629ed72..99170d0f71 100644 --- a/llarp/link/link_manager.cpp +++ b/llarp/link/link_manager.cpp @@ -310,7 +310,7 @@ namespace llarp [this](oxen::quic::dgram_interface&, bstring dgram) { return handle_path_data_message(std::move(dgram)); }, is_service_node() ? alpns::SERVICE_INBOUND : alpns::CLIENT_INBOUND, is_service_node() ? alpns::SERVICE_OUTBOUND : alpns::CLIENT_OUTBOUND, - oxen::quic::opt::enable_datagrams{/* oxen::quic::Splitting::ACTIVE */}); + oxen::quic::opt::enable_datagrams{oxen::quic::Splitting::ACTIVE}); // While only service nodes accept inbound connections, clients must have this key verify // callback set. It will reject any attempted inbound connection to a lokinet client prior