Merge branch 'dev' into neuroci

pull/1051/head
Ryan Tharp 4 years ago committed by GitHub
commit 35fe1e8866
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

21
.gitmodules vendored

@ -0,0 +1,21 @@
[submodule "external/nlohmann"]
path = external/nlohmann
url = https://github.com/nlohmann/json.git
[submodule "external/googletest"]
path = external/googletest
url = https://github.com/google/googletest.git
[submodule "external/cxxopts"]
path = external/cxxopts
url = https://github.com/jarro2783/cxxopts.git
[submodule "external/ghc-filesystem"]
path = external/ghc-filesystem
url = https://github.com/gulrak/filesystem.git
[submodule "test/Catch2"]
path = test/Catch2
url = https://github.com/catchorg/Catch2
[submodule "external/optional-lite"]
path = external/optional-lite
url = https://github.com/martinmoene/optional-lite.git
[submodule "external/date"]
path = external/date
url = https://github.com/HowardHinnant/date.git

@ -1,4 +1,6 @@
language: cpp
dist: bionic
osx_image: xcode11.3
cache: ccache
@ -7,81 +9,103 @@ matrix:
include:
- name: "lint check"
os: linux
dist: xenial
compiler: gcc
env: MAKE_TARGET=format-verify PATH="/usr/lib/llvm-8/bin:$PATH"
addons:
apt:
sources:
- llvm-toolchain-xenial-8
- llvm-toolchain-bionic-8
packages:
- clang-format-8
- name: "make debug (linux/gcc)"
os: linux
dist: xenial
compiler: gcc
env: BUILD_TYPE=Debug IS_NOTIFICATION=1
addons: &core_apt_addons
apt:
packages:
- build-essential
- cmake
- curl
- git
- libcap-dev
- libcurl4-openssl-dev
- libuv1-dev
- ninja-build
- libsodium-dev
- name: "make release (linux/gcc)"
os: linux
compiler: gcc
env: BUILD_TYPE=Release
addons: *core_apt_addons
- name: "make release (old linux/gcc)"
os: linux
dist: xenial
compiler: gcc
env: BUILD_TYPE=Release
addons: *core_apt_addons
- name: "make debug (linux/clang)"
os: linux
dist: xenial
compiler: clang
env: BUILD_TYPE=Debug
addons: *core_apt_addons
- name: "make release (linux/clang)"
os: linux
dist: xenial
compiler: clang
env: BUILD_TYPE=Release
addons: *core_apt_addons
- name: "make debug (macOS/clang)"
os: osx
osx_image: xcode10.2
env: BUILD_TYPE=Debug PATH="/usr/local/opt/ccache/libexec:$PATH"
- name: "make release (macOS/clang)"
os: osx
osx_image: xcode10.2
env: BUILD_TYPE=Release PATH="/usr/local/opt/ccache/libexec:$PATH"
- name: "make release (linux/gcc/arm64)"
arch: arm64
compiler: gcc
env: BUILD_TYPE=Release
addons: *core_apt_addons
- name: "make release (linux/gcc/s390x)"
arch: s390x
compiler: gcc
env: BUILD_TYPE=Release
addons: *core_apt_addons
- name: "make release (linux/gcc/ppc64le)"
arch: ppc64le
compiler: gcc
env: BUILD_TYPE=Release
addons: *core_apt_addons
# - name: "make iOS"
# os: osx
# osx_image: xcode10.2
# env: MAKE_TARGET=ios PATH="/usr/local/opt/ccache/libexec:$PATH"
# - name: "make windows (macOS)"
# os: osx
# osx_image: xcode10.2
# env: MAKE_TARGET=windows PATH="/usr/local/opt/ccache/libexec:$PATH"
# - name: "make windows-release (macOS)"
# os: osx
# osx_image: xcode10.2
# env: MAKE_TARGET=windows-release PATH="/usr/local/opt/ccache/libexec:$PATH"
# - name: "make release (macOS beta/clang)"
# os: osx
# osx_image: xcode11
# env: BUILD_TYPE=Release PATH="/usr/local/opt/ccache/libexec:$PATH"
# - name: "address sanitizer"
# os: osx
# osx_image: xcode10.2
# env: BUILD_TYPE=Debug XSAN=address PATH="/usr/local/opt/ccache/libexec:$PATH" CC=/usr/local/opt/llvm/bin/clang CXX=/usr/local/opt/llvm/bin/clang++
# - name: "thread sanitizer"
# os: osx
# osx_image: xcode10.2
# env: BUILD_TYPE=Debug XSAN=thread PATH="/usr/local/opt/ccache/libexec:$PATH" CC=/usr/local/opt/llvm/bin/clang CXX=/usr/local/opt/llvm/bin/clang++
# - name: "undefined sanitizer"
# os: osx
# osx_image: xcode10.2
# env: BUILD_TYPE=Debug XSAN=undefined PATH="/usr/local/opt/ccache/libexec:$PATH" CC=/usr/local/opt/llvm/bin/clang CXX=/usr/local/opt/llvm/bin/clang++
- name: "memory sanitizer"
os: linux
dist: xenial
compiler: clang
env: BUILD_TYPE=Debug XSAN=memory
- name: "router docker image"
os: linux
dist: xenial
env: DOCKER_FILE=docker/router.Dockerfile
services: docker
# - name: "memory sanitizer"
# os: linux
# compiler: clang
# env: BUILD_TYPE=Debug XSAN=memory
# addons: *core_apt_addons
# - name: "router docker image"
# os: linux
# dist: xenial
# env: DOCKER_FILE=docker/router.Dockerfile
# services: docker
- name: "make windows docker image"
os: linux
dist: xenial
@ -92,49 +116,19 @@ matrix:
dist: xenial
env: DOCKER_FILE=docker/gcc-trunk.Dockerfile
services: docker
- name: "native windows debug"
os: windows
env: BUILD_TYPE=Debug
- name: "native windows release"
os: windows
env: BUILD_TYPE=Release
allow_failures:
- name: "make windows docker image"
os: linux
dist: xenial
env: DOCKER_FILE=docker/alpine-windows.Dockerfile
services: docker
- name: "native windows debug"
os: windows
env: BUILD_TYPE=Debug
- name: "native windows release"
os: windows
env: BUILD_TYPE=Release
# - name: "native windows debug"
# os: windows
# env: BUILD_TYPE=Debug
# - name: "native windows release"
# os: windows
# env: BUILD_TYPE=Release
# - os: linux
# dist: xenial
# env: DOCKER_FILE=docker/alpine-windows.Dockerfile
# services: docker
allow_failures:
- name: "make windows docker image"
- name: "native windows debug"
- name: "native windows release"
- name: "router docker image"
os: linux
dist: xenial
env: DOCKER_FILE=docker/router.Dockerfile
services: docker
- os: linux
dist: xenial
env: DOCKER_FILE=docker/gcc-trunk.Dockerfile
services: docker
# - os: osx
# osx_image: xcode10.2
# env: MAKE_TARGET=windows PATH="/usr/local/opt/ccache/libexec:$PATH"
# - os: osx
# osx_image: xcode10.2
# env: MAKE_TARGET=windows-release PATH="/usr/local/opt/ccache/libexec:$PATH"
- name: "gcc trunk"
- arch: ppc64le
env:
global:
@ -142,33 +136,14 @@ env:
- STATIC_LINK=OFF
addons:
apt:
packages:
- binutils-gold
- build-essential
- clang-format
- cmake
- curl
- docker-ce
- g++-mingw-w64
- g++-mingw-w64-x86-64
- gcc-mingw-w64-base
- git
- libcap-dev
- libcurl4-openssl-dev
- libuv1-dev
- mingw-w64 mingw-w64-common
- ninja-build
- libsodium-dev
homebrew:
update: true
packages:
- ccache
- cmake
- curl
- libuv
- llvm
- make
- mingw-w64
- ninja
- libsodium
@ -182,11 +157,11 @@ before_install:
script:
- if [ "$TRAVIS_OS_NAME" == "windows" ]; then
travis_wait cmd.exe /C '"C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" amd64 && make test';
cmd.exe /C '"C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" amd64 && make test';
elif [[ ! -z $DOCKER_FILE ]]; then
travis_wait docker build -f $DOCKER_FILE .;
docker build -f $DOCKER_FILE .;
else
travis_wait make DOWNLOAD_SODIUM=ON ${MAKE_TARGET:-test};
make DOWNLOAD_SODIUM=ON ${MAKE_TARGET:-test};
fi
after_script:

@ -27,8 +27,6 @@ option(WITH_COVERAGE "generate coverage data" OFF)
option(USE_SHELLHOOKS "enable shell hooks on compile time (dangerous)" OFF)
option(WARNINGS_AS_ERRORS "treat all warnings as errors. turn off for development, on for release" OFF)
option(TRACY_ROOT "include tracy profiler source" OFF)
option(VENDOR_LIBSODIUM "use vendored libsodium" OFF)
option(VENDOR_FILESYSTEM "use vendored fs::filesystem" ON)
option(WITH_TESTS "build unit tests" ON)
option(WITH_SYSTEMD "enable systemd integration for sd_notify" OFF)
@ -107,6 +105,7 @@ endif()
if(XSAN)
set(DEBUG_FLAGS ${DEBUG_FLAGS} "-fsanitize=${XSAN}" -fno-omit-frame-pointer)
set(OPTIMIZE_FLAGS "-O0")
message(STATUS "Doing a ${XSAN} sanitizer build")
endif(XSAN)
if(CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]")
@ -162,7 +161,11 @@ endif(WOW64_CROSS_COMPILE OR WIN64_CROSS_COMPILE)
if(DEBIAN)
add_definitions(-DDEBIAN)
elseif(NATIVE_BUILD)
set(CRYPTO_FLAGS -march=native -mtune=native)
if(CMAKE_SYSTEM_PROCESSOR STREQUAL ppc64le)
set(CRYPTO_FLAGS -mcpu=native -mtune=native)
else()
set(CRYPTO_FLAGS -march=native -mtune=native)
endif()
elseif(NOT NON_PC_TARGET)
if (USE_AVX2)
set(CRYPTO_FLAGS -march=haswell -mtune=haswell -mfpmath=sse)
@ -195,6 +198,8 @@ endif(USE_NETNS)
if(TESTNET)
add_definitions(-DTESTNET=1)
# 5 times slower than realtime
add_definitions(-DTESTNET_SPEED=5)
endif(TESTNET)
if(SHADOW)
@ -228,21 +233,42 @@ if(WITH_SYSTEMD)
set(SD_LIBS ${SD_LDFLAGS})
endif()
if(VENDOR_FILESYSTEM)
include_directories("${CMAKE_CURRENT_LIST_DIR}/vendor/ghc-filesystem/include")
add_definitions(-DLOKINET_USE_GHC_FILESYSTEM)
message(STATUS "Using vendored ghc::filesystem")
option(SUBMODULE_CHECK "Enables checking that vendored library submodules are up to date" ON)
if(SUBMODULE_CHECK)
find_package(Git)
if(GIT_FOUND)
function(check_submodule relative_path)
execute_process(COMMAND git rev-parse "HEAD" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${relative_path} OUTPUT_VARIABLE localHead)
execute_process(COMMAND git rev-parse "HEAD:${relative_path}" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE checkedHead)
string(COMPARE EQUAL "${localHead}" "${checkedHead}" upToDate)
if (upToDate)
message(STATUS "Submodule '${relative_path}' is up-to-date")
else()
message(FATAL_ERROR "Submodule '${relative_path}' is not up-to-date. Please update with\ngit submodule update --init --recursive\nor run cmake with -DSUBMODULE_CHECK=OFF")
endif()
endfunction ()
message(STATUS "Checking submodules")
check_submodule(external/nlohmann)
check_submodule(external/googletest)
check_submodule(external/cxxopts)
check_submodule(external/ghc-filesystem)
check_submodule(external/optional-lite)
check_submodule(external/date)
endif()
endif()
set(ABSEIL_DIR vendor/abseil-cpp)
include_directories(SYSTEM ${ABSEIL_DIR})
add_subdirectory(vendor/cxxopts)
add_subdirectory(vendor/nlohmann)
include_directories(SYSTEM vendor/cxxopts/include)
if(WITH_TESTS)
add_subdirectory(vendor/gtest)
add_subdirectory(external/googletest EXCLUDE_FROM_ALL)
endif()
add_subdirectory(${ABSEIL_DIR})
set(JSON_BuildTests OFF CACHE INTERNAL "")
add_subdirectory(external/nlohmann EXCLUDE_FROM_ALL)
add_subdirectory(external/cxxopts)
add_subdirectory(external/ghc-filesystem)
add_subdirectory(external/optional-lite)
add_subdirectory(external/date)
if(ANDROID)
list(APPEND LIBS log)

@ -54,6 +54,7 @@ TESTNET_ROOT=/tmp/lokinet_testnet_tmp
TESTNET_CONF=$(TESTNET_ROOT)/supervisor.conf
TESTNET_LOG=$(TESTNET_ROOT)/testnet.log
TESTNET_VENV=$(TESTNET_ROOT)/v
TESTNET_EXE=$(REPO)/lokinet-testnet
TESTNET_CLIENTS ?= 50
TESTNET_SERVERS ?= 50
@ -95,7 +96,7 @@ CROSS ?= OFF
SHARED_LIB ?= OFF
# enable generating coverage
COVERAGE ?= OFF
# allow downloading libsodium if >= 1.0.17 not installed
# allow downloading libsodium if >= 1.0.18 not installed
DOWNLOAD_SODIUM ?= OFF
COVERAGE_OUTDIR ?= "$(TMPDIR)/lokinet-coverage"
@ -120,7 +121,7 @@ SCAN_BUILD ?= scan-build
UNAME = $(shell which uname)
COMMON_CMAKE_OPTIONS = -DSTATIC_LINK_RUNTIME=$(STATIC_LINK) -DUSE_NETNS=$(NETNS) -DUSE_AVX2=$(AVX2) -DWITH_SHARED=$(SHARED_LIB) -DDOWNLOAD_SODIUM=$(DOWNLOAD_SODIUM) -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
COMMON_CMAKE_OPTIONS = -DSTATIC_LINK_RUNTIME=$(STATIC_LINK) -DUSE_NETNS=$(NETNS) -DUSE_AVX2=$(AVX2) -DWITH_SHARED=$(SHARED_LIB) -DDOWNLOAD_SODIUM=$(DOWNLOAD_SODIUM) -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DXSAN=$(XSAN)
ifeq ($(shell $(UNAME)),SunOS)
CONFIG_CMD = $(shell gecho -n "cd '$(BUILD_ROOT)' && " ; gecho -n "cmake -G'$(CMAKE_GEN)' -DCMAKE_CROSSCOMPILING=$(CROSS) -DUSE_SHELLHOOKS=$(SHELL_HOOKS) $(COMMON_CMAKE_OPTIONS) '$(REPO)'")
@ -133,9 +134,9 @@ else
CONFIG_CMD = $(shell /bin/echo -n "cd '$(BUILD_ROOT)' && " ; /bin/echo -n "cmake -G'$(CMAKE_GEN)' -DCMAKE_CROSSCOMPILING=$(CROSS) -DUSE_SHELLHOOKS=$(SHELL_HOOKS) -DTRACY_ROOT=$(TRACY_ROOT) $(COMMON_CMAKE_OPTIONS) '$(REPO)'")
CONFIG_CMD_WINDOWS = $(shell /bin/echo -n "cd '$(BUILD_ROOT)' && " ; /bin/echo -n "cmake -G'$(CMAKE_GEN)' -DCMAKE_CROSSCOMPILING=ON -DUSE_SHELLHOOKS=$(SHELL_HOOKS) $(COMMON_CMAKE_OPTIONS) '$(REPO)'")
ANALYZE_CONFIG_CMD = $(shell /bin/echo -n "cd '$(BUILD_ROOT)' && " ; /bin/echo -n "$(SCAN_BUILD) cmake -G'$(CMAKE_GEN)' -DCMAKE_CROSSCOMPILING=$(CROSS) -DXSAN=$(XSAN) $(COMMON_CMAKE_OPTIONS) '$(REPO)'")
ANALYZE_CONFIG_CMD = $(shell /bin/echo -n "cd '$(BUILD_ROOT)' && " ; /bin/echo -n "$(SCAN_BUILD) cmake -G'$(CMAKE_GEN)' -DCMAKE_CROSSCOMPILING=$(CROSS) $(COMMON_CMAKE_OPTIONS) '$(REPO)'")
COVERAGE_CONFIG_CMD = $(shell /bin/echo -n "cd '$(BUILD_ROOT)' && " ; /bin/echo -n "cmake -G'$(CMAKE_GEN)' -DCMAKE_CROSSCOMPILING=$(CROSS) -DWITH_COVERAGE=yes -DXSAN=$(XSAN) $(COMMON_CMAKE_OPTIONS) '$(REPO)'")
COVERAGE_CONFIG_CMD = $(shell /bin/echo -n "cd '$(BUILD_ROOT)' && " ; /bin/echo -n "cmake -G'$(CMAKE_GEN)' -DCMAKE_CROSSCOMPILING=$(CROSS) -DWITH_COVERAGE=yes $(COMMON_CMAKE_OPTIONS) '$(REPO)'")
endif
TARGETS = $(REPO)/lokinet
@ -178,6 +179,7 @@ release-compile: release-configure
$(TARGETS): release-compile
release: $(TARGETS)
make -C '$(BUILD_ROOT)' check
shadow-configure: clean
mkdir -p $(BUILD_ROOT)
@ -206,16 +208,26 @@ testnet-configure: testnet-clean
testnet-build: testnet-configure
$(MAKE) -C $(BUILD_ROOT)
testnet:
$(TESTNET_VENV):
$(PYTHON3) -m venv $(TESTNET_VENV) --system-site-packages
$(TESTNET_VENV)/bin/pip install -r $(REPO)/contrib/testnet/requirements.txt
testnet: $(TESTNET_VENV)
cp $(EXE) $(TESTNET_EXE)
mkdir -p $(TESTNET_ROOT)
$(PYTHON3) $(REPO)/contrib/testnet/genconf.py --bin=$(TESTNET_EXE) --svc=$(TESTNET_SERVERS) --clients=$(TESTNET_CLIENTS) --dir=$(TESTNET_ROOT) --out $(TESTNET_CONF) --ifname=$(TESTNET_IFNAME) --baseport=$(TESTNET_BASEPORT) --ip=$(TESTNET_IP) --netid=$(TESTNET_NETID)
$(PYTHON3) $(REPO)/contrib/testnet/genconf.py --bin=$(TESTNET_EXE) --svc=$(TESTNET_SERVERS) --clients=$(TESTNET_CLIENTS) --dir=$(TESTNET_ROOT) --out $(TESTNET_CONF) --ifname=$(TESTNET_IFNAME) --baseport=$(TESTNET_BASEPORT) --ip=$(TESTNET_IP) --netid=$(TESTNET_NETID) --lokid='$(TESTNET_VENV)/bin/python $(REPO)/contrib/testnet/lokid.py'
LLARP_DEBUG=$(TESTNET_DEBUG) supervisord -n -d $(TESTNET_ROOT) -l $(TESTNET_LOG) -c $(TESTNET_CONF)
$(TEST_EXE): debug
gtest: debug
test x$(CROSS) = xOFF && $(MAKE) -C $(BUILD_ROOT) rungtest || test x$(CROSS) = xON
catch: debug
test x$(CROSS) = xOFF && $(MAKE) -C $(BUILD_ROOT) catch || test x$(CROSS) = xON
check: debug
test x$(CROSS) = xOFF && $(MAKE) -C $(BUILD_ROOT) check || test x$(CROSS) = xON
test: $(TEST_EXE)
test x$(CROSS) = xOFF && $(TEST_EXE) || test x$(CROSS) = xON
test: check
static-configure: $(LIBUV_PREFIX) $(LIBCURL_PREFIX)
(test x$(TOOLCHAIN) = x && $(CONFIG_CMD) -DCMAKE_BUILD_TYPE=Release -DSTATIC_LINK=ON -DRELEASE_MOTTO="$(shell cat motto.txt)" -DCMAKE_C_FLAGS='$(CFLAGS)' -DCMAKE_CXX_FLAGS='$(CXXFLAGS)' -DLIBUV_ROOT='$(LIBUV_PREFIX)' -DLIBCURL_ROOT='$(LIBCURL_PREFIX)' ) || (test x$(TOOLCHAIN) != x && $(CONFIG_CMD) -DCMAKE_BUILD_TYPE=Release -DSTATIC_LINK=ON -DRELEASE_MOTTO="$(shell cat motto.txt)" -DCMAKE_C_FLAGS='$(CFLAGS)' -DCMAKE_CXX_FLAGS='$(CXXFLAGS)' -DLIBUV_ROOT='$(LIBUV_PREFIX)' -DLIBCURL_ROOT='$(LIBCURL_PREFIX)' -DCMAKE_TOOLCHAIN_FILE=$(TOOLCHAIN) -DNATIVE_BUILD=OFF )
@ -299,7 +311,7 @@ coverage-config: clean
coverage: coverage-config
$(MAKE) -C $(BUILD_ROOT)
test x$(CROSS) = xOFF && $(TEST_EXE) || true # continue even if tests fail
test x$(CROSS) = xOFF && $(MAKE) -C $(BUILD_ROOT) check || true # continue even if tests fail
mkdir -p "$(COVERAGE_OUTDIR)"
ifeq ($(CLANG),OFF)
gcovr -r . --branches --html --html-details -o "$(COVERAGE_OUTDIR)/lokinet.html"
@ -336,7 +348,7 @@ debian: debian-configure
cp $(EXE) lokinet
debian-test:
test x$(CROSS) = xOFF && $(TEST_EXE) || test x$(CROSS) = xON
test x$(CROSS) = xOFF && $(MAKE) -C $(BUILD_ROOT) check || test x$(CROSS) = xON
install:
DESTDIR=$(DESTDIR) $(MAKE) -C '$(BUILD_ROOT)' install

@ -1,296 +1,31 @@
set(LIBSODIUM_PREFIX ${CMAKE_BINARY_DIR}/libsodium)
set(LIBSODIUM_SRC ${LIBSODIUM_PREFIX}/libsodium-1.0.17)
set(LIBSODIUM_TARBALL ${LIBSODIUM_PREFIX}/libsodium-1.0.17.tar.gz)
set(LIBSODIUM_URL https://github.com/jedisct1/libsodium/releases/download/1.0.17/libsodium-1.0.17.tar.gz)
set(LIBSODIUM_URL https://github.com/jedisct1/libsodium/releases/download/1.0.18-RELEASE/libsodium-1.0.18.tar.gz https://download.libsodium.org/libsodium/releases/libsodium-1.0.18.tar.gz)
set(LIBSODIUM_HASH SHA512=17e8638e46d8f6f7d024fe5559eccf2b8baf23e143fadd472a7d29d228b186d86686a5e6920385fe2020729119a5f12f989c3a782afbd05a8db4819bb18666ef)
if(SODIUM_TARBALL_URL)
# make a build time override of the tarball url so we can fetch it if the original link goes away
set(LIBSODIUM_URL ${SODIUM_TARBALL_URL})
endif()
set(SODIUM_PRETEND_TO_BE_CONFIGURED ON)
file(DOWNLOAD
${LIBSODIUM_URL}
${LIBSODIUM_TARBALL}
EXPECTED_HASH SHA512=7cc9e4f11e656008ce9dff735acea95acbcb91ae4936de4d26f7798093766a77c373e9bd4a7b45b60ef8a11de6c55bc8dcac13bebf8c23c671d0536430501da1
SHOW_PROGRESS)
execute_process(COMMAND tar -xzf ${LIBSODIUM_TARBALL} -C ${LIBSODIUM_PREFIX})
if(WIN32)
message("patch -p0 -d ${LIBSODIUM_SRC} < ${CMAKE_SOURCE_DIR}/llarp/win32/libsodium-1.0.17-win32.patch")
execute_process(COMMAND "patch -p0 -d ${LIBSODIUM_SRC} < ${CMAKE_SOURCE_DIR}/llarp/win32/libsodium-1.0.17-win32.patch")
endif()
add_library(sodium_vendor
${LIBSODIUM_SRC}/src/libsodium/crypto_aead/aes256gcm/aesni/aead_aes256gcm_aesni.c
${LIBSODIUM_SRC}/src/libsodium/crypto_aead/chacha20poly1305/sodium/aead_chacha20poly1305.c
${LIBSODIUM_SRC}/src/libsodium/crypto_aead/xchacha20poly1305/sodium/aead_xchacha20poly1305.c
${LIBSODIUM_SRC}/src/libsodium/crypto_auth/crypto_auth.c
${LIBSODIUM_SRC}/src/libsodium/crypto_auth/hmacsha256/auth_hmacsha256.c
${LIBSODIUM_SRC}/src/libsodium/crypto_auth/hmacsha512/auth_hmacsha512.c
${LIBSODIUM_SRC}/src/libsodium/crypto_auth/hmacsha512256/auth_hmacsha512256.c
${LIBSODIUM_SRC}/src/libsodium/crypto_box/crypto_box.c
${LIBSODIUM_SRC}/src/libsodium/crypto_box/crypto_box_easy.c
${LIBSODIUM_SRC}/src/libsodium/crypto_box/crypto_box_seal.c
${LIBSODIUM_SRC}/src/libsodium/crypto_box/curve25519xsalsa20poly1305/box_curve25519xsalsa20poly1305.c
${LIBSODIUM_SRC}/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c
${LIBSODIUM_SRC}/src/libsodium/crypto_core/ed25519/ref10/fe_25_5/base.h
${LIBSODIUM_SRC}/src/libsodium/crypto_core/ed25519/ref10/fe_25_5/base2.h
${LIBSODIUM_SRC}/src/libsodium/crypto_core/ed25519/ref10/fe_25_5/constants.h
${LIBSODIUM_SRC}/src/libsodium/crypto_core/ed25519/ref10/fe_25_5/fe.h
${LIBSODIUM_SRC}/src/libsodium/crypto_core/ed25519/ref10/fe_51/base.h
${LIBSODIUM_SRC}/src/libsodium/crypto_core/ed25519/ref10/fe_51/base2.h
${LIBSODIUM_SRC}/src/libsodium/crypto_core/ed25519/ref10/fe_51/constants.h
${LIBSODIUM_SRC}/src/libsodium/crypto_core/ed25519/ref10/fe_51/fe.h
${LIBSODIUM_SRC}/src/libsodium/crypto_core/hchacha20/core_hchacha20.c
${LIBSODIUM_SRC}/src/libsodium/crypto_core/hsalsa20/core_hsalsa20.c
${LIBSODIUM_SRC}/src/libsodium/crypto_core/hsalsa20/ref2/core_hsalsa20_ref2.c
${LIBSODIUM_SRC}/src/libsodium/crypto_core/salsa/ref/core_salsa_ref.c
${LIBSODIUM_SRC}/src/libsodium/crypto_generichash/blake2b/generichash_blake2.c
${LIBSODIUM_SRC}/src/libsodium/crypto_generichash/blake2b/ref/blake2.h
${LIBSODIUM_SRC}/src/libsodium/crypto_generichash/blake2b/ref/blake2b-compress-avx2.c
${LIBSODIUM_SRC}/src/libsodium/crypto_generichash/blake2b/ref/blake2b-compress-avx2.h
${LIBSODIUM_SRC}/src/libsodium/crypto_generichash/blake2b/ref/blake2b-compress-ref.c
${LIBSODIUM_SRC}/src/libsodium/crypto_generichash/blake2b/ref/blake2b-compress-sse41.c
${LIBSODIUM_SRC}/src/libsodium/crypto_generichash/blake2b/ref/blake2b-compress-sse41.h
${LIBSODIUM_SRC}/src/libsodium/crypto_generichash/blake2b/ref/blake2b-compress-ssse3.c
${LIBSODIUM_SRC}/src/libsodium/crypto_generichash/blake2b/ref/blake2b-compress-ssse3.h
${LIBSODIUM_SRC}/src/libsodium/crypto_generichash/blake2b/ref/blake2b-load-avx2.h
${LIBSODIUM_SRC}/src/libsodium/crypto_generichash/blake2b/ref/blake2b-load-sse2.h
${LIBSODIUM_SRC}/src/libsodium/crypto_generichash/blake2b/ref/blake2b-load-sse41.h
${LIBSODIUM_SRC}/src/libsodium/crypto_generichash/blake2b/ref/blake2b-ref.c
${LIBSODIUM_SRC}/src/libsodium/crypto_generichash/blake2b/ref/generichash_blake2b.c
${LIBSODIUM_SRC}/src/libsodium/crypto_generichash/crypto_generichash.c
${LIBSODIUM_SRC}/src/libsodium/crypto_hash/crypto_hash.c
${LIBSODIUM_SRC}/src/libsodium/crypto_hash/sha256/cp/hash_sha256_cp.c
${LIBSODIUM_SRC}/src/libsodium/crypto_hash/sha256/hash_sha256.c
${LIBSODIUM_SRC}/src/libsodium/crypto_hash/sha512/cp/hash_sha512_cp.c
${LIBSODIUM_SRC}/src/libsodium/crypto_hash/sha512/hash_sha512.c
${LIBSODIUM_SRC}/src/libsodium/crypto_kdf/blake2b/kdf_blake2b.c
${LIBSODIUM_SRC}/src/libsodium/crypto_kdf/crypto_kdf.c
${LIBSODIUM_SRC}/src/libsodium/crypto_kx/crypto_kx.c
${LIBSODIUM_SRC}/src/libsodium/crypto_onetimeauth/crypto_onetimeauth.c
${LIBSODIUM_SRC}/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna.c
${LIBSODIUM_SRC}/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna.h
${LIBSODIUM_SRC}/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna32.h
${LIBSODIUM_SRC}/src/libsodium/crypto_onetimeauth/poly1305/donna/poly1305_donna64.h
${LIBSODIUM_SRC}/src/libsodium/crypto_onetimeauth/poly1305/onetimeauth_poly1305.c
${LIBSODIUM_SRC}/src/libsodium/crypto_onetimeauth/poly1305/onetimeauth_poly1305.h
${LIBSODIUM_SRC}/src/libsodium/crypto_onetimeauth/poly1305/sse2/poly1305_sse2.c
${LIBSODIUM_SRC}/src/libsodium/crypto_onetimeauth/poly1305/sse2/poly1305_sse2.h
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/argon2/argon2-core.c
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/argon2/argon2-core.h
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/argon2/argon2-encoding.c
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/argon2/argon2-encoding.h
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/argon2/argon2-fill-block-avx2.c
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/argon2/argon2-fill-block-avx512f.c
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/argon2/argon2-fill-block-ref.c
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/argon2/argon2-fill-block-ssse3.c
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/argon2/argon2.c
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/argon2/argon2.h
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/argon2/blake2b-long.c
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/argon2/blake2b-long.h
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/argon2/blamka-round-avx2.h
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/argon2/blamka-round-avx512f.h
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/argon2/blamka-round-ref.h
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/argon2/blamka-round-ssse3.h
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/argon2/pwhash_argon2i.c
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/argon2/pwhash_argon2id.c
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/crypto_pwhash.c
${LIBSODIUM_SRC}/src/libsodium/crypto_scalarmult/crypto_scalarmult.c
${LIBSODIUM_SRC}/src/libsodium/crypto_scalarmult/curve25519/ref10/x25519_ref10.c
${LIBSODIUM_SRC}/src/libsodium/crypto_scalarmult/curve25519/ref10/x25519_ref10.h
${LIBSODIUM_SRC}/src/libsodium/crypto_scalarmult/curve25519/sandy2x/consts_namespace.h
${LIBSODIUM_SRC}/src/libsodium/crypto_scalarmult/curve25519/sandy2x/curve25519_sandy2x.c
${LIBSODIUM_SRC}/src/libsodium/crypto_scalarmult/curve25519/sandy2x/curve25519_sandy2x.h
${LIBSODIUM_SRC}/src/libsodium/crypto_scalarmult/curve25519/sandy2x/fe.h
${LIBSODIUM_SRC}/src/libsodium/crypto_scalarmult/curve25519/sandy2x/fe51.h
${LIBSODIUM_SRC}/src/libsodium/crypto_scalarmult/curve25519/sandy2x/fe51_invert.c
${LIBSODIUM_SRC}/src/libsodium/crypto_scalarmult/curve25519/sandy2x/fe51_namespace.h
${LIBSODIUM_SRC}/src/libsodium/crypto_scalarmult/curve25519/sandy2x/fe_frombytes_sandy2x.c
${LIBSODIUM_SRC}/src/libsodium/crypto_scalarmult/curve25519/sandy2x/ladder.h
${LIBSODIUM_SRC}/src/libsodium/crypto_scalarmult/curve25519/sandy2x/ladder_base.h
${LIBSODIUM_SRC}/src/libsodium/crypto_scalarmult/curve25519/sandy2x/ladder_base_namespace.h
${LIBSODIUM_SRC}/src/libsodium/crypto_scalarmult/curve25519/sandy2x/ladder_namespace.h
${LIBSODIUM_SRC}/src/libsodium/crypto_scalarmult/curve25519/scalarmult_curve25519.c
${LIBSODIUM_SRC}/src/libsodium/crypto_scalarmult/curve25519/scalarmult_curve25519.h
${LIBSODIUM_SRC}/src/libsodium/crypto_secretbox/crypto_secretbox.c
${LIBSODIUM_SRC}/src/libsodium/crypto_secretbox/crypto_secretbox_easy.c
${LIBSODIUM_SRC}/src/libsodium/crypto_secretbox/xsalsa20poly1305/secretbox_xsalsa20poly1305.c
${LIBSODIUM_SRC}/src/libsodium/crypto_secretstream/xchacha20poly1305/secretstream_xchacha20poly1305.c
${LIBSODIUM_SRC}/src/libsodium/crypto_shorthash/crypto_shorthash.c
${LIBSODIUM_SRC}/src/libsodium/crypto_shorthash/siphash24/ref/shorthash_siphash24_ref.c
${LIBSODIUM_SRC}/src/libsodium/crypto_shorthash/siphash24/ref/shorthash_siphash_ref.h
${LIBSODIUM_SRC}/src/libsodium/crypto_shorthash/siphash24/shorthash_siphash24.c
${LIBSODIUM_SRC}/src/libsodium/crypto_sign/crypto_sign.c
${LIBSODIUM_SRC}/src/libsodium/crypto_sign/ed25519/ref10/keypair.c
${LIBSODIUM_SRC}/src/libsodium/crypto_sign/ed25519/ref10/open.c
${LIBSODIUM_SRC}/src/libsodium/crypto_sign/ed25519/ref10/sign.c
${LIBSODIUM_SRC}/src/libsodium/crypto_sign/ed25519/ref10/sign_ed25519_ref10.h
${LIBSODIUM_SRC}/src/libsodium/crypto_sign/ed25519/sign_ed25519.c
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-avx2.c
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-avx2.h
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-ssse3.c
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/chacha20/dolbeau/chacha20_dolbeau-ssse3.h
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/chacha20/dolbeau/u0.h
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/chacha20/dolbeau/u1.h
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/chacha20/dolbeau/u4.h
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/chacha20/dolbeau/u8.h
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/chacha20/ref/chacha20_ref.c
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/chacha20/ref/chacha20_ref.h
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/chacha20/stream_chacha20.c
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/chacha20/stream_chacha20.h
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/crypto_stream.c
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/salsa20/ref/salsa20_ref.c
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/salsa20/ref/salsa20_ref.h
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/salsa20/stream_salsa20.c
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/salsa20/stream_salsa20.h
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/salsa20/xmm6/salsa20_xmm6.c
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/salsa20/xmm6/salsa20_xmm6.h
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-avx2.c
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-avx2.h
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-sse2.c
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/salsa20/xmm6int/salsa20_xmm6int-sse2.h
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/salsa20/xmm6int/u0.h
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/salsa20/xmm6int/u1.h
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/salsa20/xmm6int/u4.h
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/salsa20/xmm6int/u8.h
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/xsalsa20/stream_xsalsa20.c
${LIBSODIUM_SRC}/src/libsodium/crypto_verify/sodium/verify.c
${LIBSODIUM_SRC}/src/libsodium/include/sodium.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/core.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_aead_aes256gcm.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_aead_chacha20poly1305.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_aead_xchacha20poly1305.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_auth.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_auth_hmacsha256.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_auth_hmacsha512.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_auth_hmacsha512256.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_box.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_box_curve25519xchacha20poly1305.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_box_curve25519xsalsa20poly1305.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_core_ed25519.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_core_hchacha20.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_core_hsalsa20.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_core_salsa20.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_core_salsa2012.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_core_salsa208.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_generichash.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_generichash_blake2b.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_hash.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_hash_sha256.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_hash_sha512.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_kdf.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_kdf_blake2b.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_kx.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_onetimeauth.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_onetimeauth_poly1305.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_pwhash.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_pwhash_argon2i.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_pwhash_argon2id.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_pwhash_scryptsalsa208sha256.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_scalarmult.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_scalarmult_curve25519.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_scalarmult_ed25519.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_secretbox.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_secretbox_xchacha20poly1305.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_secretbox_xsalsa20poly1305.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_secretstream_xchacha20poly1305.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_shorthash.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_shorthash_siphash24.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_sign.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_sign_ed25519.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_sign_edwards25519sha512batch.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_stream.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_stream_chacha20.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_stream_salsa20.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_stream_salsa2012.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_stream_salsa208.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_stream_xchacha20.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_stream_xsalsa20.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_verify_16.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_verify_32.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/crypto_verify_64.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/export.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/private/chacha20_ietf_ext.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/private/common.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/private/ed25519_ref10.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/private/ed25519_ref10_fe_25_5.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/private/ed25519_ref10_fe_51.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/private/implementations.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/private/mutex.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/private/sse2_64_32.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/randombytes.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/randombytes_nativeclient.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/randombytes_salsa20_random.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/randombytes_sysrandom.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/runtime.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/utils.h
${LIBSODIUM_SRC}/src/libsodium/include/sodium/version.h
${LIBSODIUM_SRC}/src/libsodium/randombytes/nativeclient/randombytes_nativeclient.c
${LIBSODIUM_SRC}/src/libsodium/randombytes/randombytes.c
${LIBSODIUM_SRC}/src/libsodium/randombytes/salsa20/randombytes_salsa20_random.c
${LIBSODIUM_SRC}/src/libsodium/randombytes/sysrandom/randombytes_sysrandom.c
${LIBSODIUM_SRC}/src/libsodium/sodium/codecs.c
${LIBSODIUM_SRC}/src/libsodium/sodium/core.c
${LIBSODIUM_SRC}/src/libsodium/sodium/runtime.c
${LIBSODIUM_SRC}/src/libsodium/sodium/utils.c
${LIBSODIUM_SRC}/src/libsodium/sodium/version.c
)
target_sources(sodium_vendor
PRIVATE
${LIBSODIUM_SRC}/src/libsodium/crypto_box/curve25519xchacha20poly1305/box_curve25519xchacha20poly1305.c
${LIBSODIUM_SRC}/src/libsodium/crypto_box/curve25519xchacha20poly1305/box_seal_curve25519xchacha20poly1305.c
${LIBSODIUM_SRC}/src/libsodium/crypto_core/ed25519/core_ed25519.c
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt-common.c
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/scryptsalsa208sha256/crypto_scrypt.h
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/scryptsalsa208sha256/nosse/pwhash_scryptsalsa208sha256_nosse.c
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.c
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/scryptsalsa208sha256/pbkdf2-sha256.h
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/scryptsalsa208sha256/pwhash_scryptsalsa208sha256.c
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/scryptsalsa208sha256/scrypt_platform.c
${LIBSODIUM_SRC}/src/libsodium/crypto_pwhash/scryptsalsa208sha256/sse/pwhash_scryptsalsa208sha256_sse.c
${LIBSODIUM_SRC}/src/libsodium/crypto_scalarmult/ed25519/ref10/scalarmult_ed25519_ref10.c
${LIBSODIUM_SRC}/src/libsodium/crypto_secretbox/xchacha20poly1305/secretbox_xchacha20poly1305.c
${LIBSODIUM_SRC}/src/libsodium/crypto_shorthash/siphash24/ref/shorthash_siphashx24_ref.c
${LIBSODIUM_SRC}/src/libsodium/crypto_shorthash/siphash24/shorthash_siphashx24.c
${LIBSODIUM_SRC}/src/libsodium/crypto_sign/ed25519/ref10/obsolete.c
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/salsa2012/ref/stream_salsa2012_ref.c
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/salsa2012/stream_salsa2012.c
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/salsa208/ref/stream_salsa208_ref.c
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/salsa208/stream_salsa208.c
${LIBSODIUM_SRC}/src/libsodium/crypto_stream/xchacha20/stream_xchacha20.c
)
set_target_properties(sodium_vendor
PROPERTIES
C_STANDARD 99
)
target_include_directories(sodium_vendor
PUBLIC
${LIBSODIUM_SRC}/src/libsodium/include
PRIVATE
${LIBSODIUM_SRC}/src/libsodium/include/sodium
)
target_compile_definitions(sodium_vendor
PUBLIC
$<$<NOT:$<BOOL:${BUILD_SHARED_LIBS}>>:SODIUM_STATIC>
$<$<BOOL:${SODIUM_MINIMAL}>:SODIUM_LIBRARY_MINIMAL>
PRIVATE
$<$<BOOL:${BUILD_SHARED_LIBS}>:SODIUM_DLL_EXPORT>
$<$<BOOL:${SODIUM_ENABLE_BLOCKING_RANDOM}>:USE_BLOCKING_RANDOM>
$<$<BOOL:${SODIUM_MINIMAL}>:MINIMAL>
$<$<BOOL:${SODIUM_PRETEND_TO_BE_CONFIGURED}>:CONFIGURED>
)
# Variables that need to be exported to version.h.in
set(VERSION_ORIG "${VERSION}") # an included module sets things in the calling scope :(
set(VERSION 1.0.17)
set(SODIUM_LIBRARY_VERSION_MAJOR 10)
set(SODIUM_LIBRARY_VERSION_MINOR 2)
file(MAKE_DIRECTORY ${LIBSODIUM_PREFIX}/include)
configure_file(
${LIBSODIUM_SRC}/src/libsodium/include/sodium/version.h.in
${LIBSODIUM_SRC}/src/libsodium/include/sodium/version.h
)
include(ExternalProject)
include(ProcessorCount)
ExternalProject_Add(libsodium_external
BUILD_IN_SOURCE ON
PREFIX ${LIBSODIUM_PREFIX}
URL ${LIBSODIUM_URL}
URL_HASH ${LIBSODIUM_HASH}
CONFIGURE_COMMAND ./configure --prefix=${LIBSODIUM_PREFIX} --enable-static --disable-shared
BUILD_COMMAND make -j${PROCESSOR_COUNT}
INSTALL_COMMAND ${MAKE}
BUILD_BYPRODUCTS ${LIBSODIUM_PREFIX}/lib/libsodium.a ${LIBSODIUM_PREFIX}/include
)
set(VERSION "${VERSION_ORIG}")
add_library(sodium_vendor STATIC IMPORTED GLOBAL)
add_dependencies(sodium_vendor libsodium_external)
set_target_properties(sodium_vendor PROPERTIES
IMPORTED_LOCATION ${LIBSODIUM_PREFIX}/lib/libsodium.a
INTERFACE_INCLUDE_DIRECTORIES ${LIBSODIUM_PREFIX}/include
)

@ -54,6 +54,9 @@ class Monitor:
y += 1
self.win.move(y, 1)
y += 1
self.win.addstr("[tx:\t{}]\t[rx:\t{}]".format(self.speedOf(path['txRateCurrent']), self.speedOf(path['rxRateCurrent'])))
self.win.move(y, 1)
y += 1
self.win.addstr("me -> ")
for hop in path["hops"]:
self.win.addstr(" {} ->".format(hop["router"][:4]))
@ -94,12 +97,12 @@ class Monitor:
self.win.addstr("paths: {}".format(len(paths)))
for path in paths:
y = self._render_path(y, path, "inbound")
for session in status["remoteSessions"]:
for session in (status["remoteSessions"] or []):
for path in session["paths"]:
y = self._render_path(
y, path, "[active] {}".format(session["currentConvoTag"])
)
for session in status["snodeSessions"]:
for session in (status["snodeSessions"] or []):
for path in session["paths"]:
y = self._render_path(y, path, "[snode]")
return y
@ -194,15 +197,17 @@ class Monitor:
for s in sessions:
y += 1
self.win.move(y, 1)
self.txrate += s["tx"]
self.rxrate += s["rx"]
self.txrate += s["txRateCurrent"]
self.rxrate += s["rxRateCurrent"]
self.win.addstr(
"{}\t[{}\ttx]\t[{}\trx]".format(
s["remoteAddr"], self.speedOf(s["tx"]), self.speedOf(s["rx"])
s["remoteAddr"], self.speedOf(s["txRateCurrent"]), self.speedOf(s["rxRateCurrent"])
)
)
if s["sendBacklog"] > 0:
self.win.addstr("[backlog {}]".format(s["sendBacklog"]))
if (s['txMsgs'] or 0) > 1:
self.win.addstr(" [out window:\t{}]".format(s['txMsgQueueSize']))
if (s['rxMsgs'] or 0) > 1:
self.win.addstr(" [in window:\t{}]".format(s['rxMsgQueueSize']))
return y
def display_dht(self, y, data):

@ -18,6 +18,7 @@ def clientNodeName(id): return 'client-node-%03d' % id
def main():
ap = AP()
ap.add_argument('--lokid', type=str, required=True)
ap.add_argument('--valgrind', type=bool, default=False)
ap.add_argument('--dir', type=str, default='testnet_tmp')
ap.add_argument('--svc', type=int, default=20,
@ -36,7 +37,7 @@ def main():
if args.valgrind:
exe = 'valgrind {}'.format(args.bin)
else:
exe = args.bin
exe = '{} -v'.format(args.bin)
basedir = os.path.abspath(args.dir)
for nodeid in range(args.svc):
@ -66,6 +67,12 @@ def main():
config['api'] = {
'enabled': 'false'
}
config['lokid'] = {
'enabled': 'true',
'username': 'svc-%03d' % nodeid,
'password': 'lokinet',
'jsonrpc': '127.0.0.1:5000'
}
d = os.path.join(args.dir, svcNodeName(nodeid))
if not os.path.exists(d):
os.mkdir(d)
@ -118,6 +125,13 @@ type=null
''')
with open(args.out, 'w') as f:
f.write('''[program:mock-lokid]
command = {} {}
autorestart = true
redirect_stderr=true
stdout_logfile={}/lokid.txt
stdout_logfile_maxbytes=0
'''.format(args.lokid, args.svc, args.dir))
f.write('''[program:svc-node]
directory = {}
command = {} daemon.ini

@ -0,0 +1,121 @@
#!/usr/bin/env python3
import os
from base64 import b64decode
from flask import Flask, jsonify, request, abort, Response, make_response
from nacl import signing
from nacl import encoding
class SVCNode:
"""
info on a service node
"""
def __init__(self):
self._seed = os.urandom(32)
self._ed25519_secret = signing.SigningKey(self._seed)
def seed(self):
"""
return hex seed
"""
return self._ed25519_secret.encode(encoding.HexEncoder).decode('ascii') + self.pubkey()
def pubkey(self):
"""
make hex public key
"""
return self._ed25519_secret.verify_key.encode(encoding.HexEncoder).decode('ascii')
def toJson(self):
"""
make the snode a json object for jsonrpc
"""
return {'pubkey_ed25519': self.pubkey(), 'active': True, 'funded': True}
class MockServer:
def __init__(self, numServiceNodes):
self.app = Flask('lokid-rpc-mock')
#self.app.config['SECRET_KEY'] = os.urandom(16)
# populate service nodes
self._serviceNodes = dict()
for n in range(numServiceNodes):
self.makeSNode("svc-%03d" % n)
self._handlers = {
'lokinet_ping': self._lokinet_ping,
'get_n_service_nodes' : self._get_n_service_nodes,
'get_service_node_privkey' : self._get_service_node_privkey
}
#digest = HTTPDigestAuth(realm='lokid')
@self.app.route('/json_rpc', methods=["POST"])
def _jsonRPC():
j = request.get_json()
method = j['method']
snode = None
if 'authorization' in request.headers:
user = b64decode(request.headers['authorization'][6:].encode('ascii')).decode('ascii').split(':')[0]
self.app.logger.error(user)
if len(user) > 0:
snode = self._serviceNodes[user]
result = self._handlers[method](snode)
if result:
resp = {'jsonrpc': '2.0', 'id': j['id'], 'result': result}
return jsonify(resp)
else:
r = make_response('nope', 401)
r.headers['www-authenticate'] = 'basic'
return r
def after(req):
req.content_type = "application/json"
return req
self.app.after_request(after)
def _get_n_service_nodes(self, our_snode):
return {
'block_hash' : 'mock',
'service_node_states' : self.getSNodeList()
}
def _get_service_node_privkey(self, our_snode):
if our_snode is None:
return None
return {
'service_node_ed25519_privkey': our_snode.seed()
}
def _lokinet_ping(self, snode):
return {
'status' : "OK"
}
def run(self):
"""
run mainloop and serve jsonrpc server
"""
self.app.run()
def makeSNode(self, name):
"""
make service node entry
"""
self._serviceNodes[name] = SVCNode()
def getSNodeList(self):
l = list()
for name in self._serviceNodes:
l.append(self._serviceNodes[name].toJson())
return l
def main():
import sys
serv = MockServer(int(sys.argv[1]))
serv.run()
if __name__ == '__main__':
main()

@ -66,19 +66,22 @@ target_link_libraries(${CRYPTOGRAPHY_LIB} PRIVATE cryptography_avx_lib)
option(DOWNLOAD_SODIUM "Allow libsodium to be downloaded and built locally if not found on the system" OFF)
find_package(Sodium 1.0.17)
# Allow -DDOWNLOAD_SODIUM=FORCE to download without even checking for a local libsodium
if(NOT DOWNLOAD_SODIUM STREQUAL "FORCE")
find_package(Sodium 1.0.18)
endif()
if(sodium_FOUND)
target_include_directories(${CRYPTOGRAPHY_LIB} PUBLIC ${sodium_INCLUDE_DIR})
target_include_directories(cryptography_avx_lib PUBLIC ${sodium_INCLUDE_DIR})
target_link_libraries(${CRYPTOGRAPHY_LIB} PUBLIC ${sodium_LIBRARY_RELEASE})
elseif(DOWNLOAD_SODIUM)
message(STATUS "Sodium >= 1.0.17 not found, but DOWNLOAD_SODIUM specified, so downloading it")
message(STATUS "Sodium >= 1.0.18 not found, but DOWNLOAD_SODIUM specified, so downloading it")
include(DownloadLibSodium)
target_link_libraries(${CRYPTOGRAPHY_LIB} PUBLIC sodium_vendor)
target_link_libraries(cryptography_avx_lib PUBLIC sodium_vendor)
else()
message(FATAL_ERROR "Could not find libsodium >= 1.0.17; either install it on your system or use -DDOWNLOAD_SODIUM=ON to download and build an internal copy")
message(FATAL_ERROR "Could not find libsodium >= 1.0.18; either install it on your system or use -DDOWNLOAD_SODIUM=ON to download and build an internal copy")
endif()
target_include_directories(${CRYPTOGRAPHY_LIB} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/libntrup/include")

@ -42,8 +42,8 @@ else()
target_link_directories(${EXE} PRIVATE /usr/local/lib)
target_link_directories(${CTL} PRIVATE /usr/local/lib)
endif()
target_link_libraries(${EXE} PUBLIC ${EXE_LIBS} ${LIBS})
target_link_libraries(${CTL} PUBLIC ${EXE_LIBS} ${LIBS})
target_link_libraries(${EXE} PUBLIC ${EXE_LIBS} ${LIBS} ${CRYPTOGRAPHY_LIB})
target_link_libraries(${CTL} PUBLIC ${EXE_LIBS} ${LIBS} ${CRYPTOGRAPHY_LIB})
if(CURL_FOUND)
target_include_directories(${CTL} PRIVATE ${CURL_INCLUDE_DIRS})

@ -3,7 +3,6 @@
#include <util/logging/logger.hpp>
#include <util/logging/ostream_logger.hpp>
#include <absl/synchronization/mutex.h>
#include <cxxopts.hpp>
#include <string>
#include <vector>
@ -110,10 +109,6 @@ namespace
int
main(int argc, char* argv[])
{
#ifdef LOKINET_DEBUG
absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
#endif
// clang-format off
cxxopts::Options options(
"lokinetctl",

@ -102,10 +102,6 @@ main(int argc, char *argv[])
// SetUnhandledExceptionFilter(win32_signal_handler);
#endif
#ifdef LOKINET_DEBUG
absl::SetMutexDeadlockDetectionMode(absl::OnDeadlockCycle::kAbort);
#endif
// clang-format off
cxxopts::Options options(
"lokinet",

@ -6,4 +6,4 @@ RUN apk update && \
WORKDIR /src/
COPY . /src/
RUN make windows-release NINJA=ninja STATIC_LINK=ON
RUN make windows-release NINJA=ninja STATIC_LINK=ON DOWNLOAD_SODIUM=ON

@ -9,6 +9,6 @@ COPY . /src/
RUN mkdir build && \
cd build && \
cmake .. -G Ninja -DDOWNLOAD_SODIUM=ON -DCMAKE_BUILD_TYPE=Release -DWARNINGS_AS_ERRORS=ON && \
cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DWARNINGS_AS_ERRORS=ON -DDOWNLOAD_SODIUM=ON && \
ninja -k0 && \
./test/testAll

@ -0,0 +1,94 @@
llarp's dht is a recusrive kademlia dht with optional request proxying via paths for requester anonymization.
dht is separated into 2 different networks, one for router contacts, one for introsets.
format for consesus propagation messages:
keys: A, H, K, N, O, T, U, V
concensus request messages
requester requests current table hash, H,N,O is set to zeros if not known
C -> S
{
A: "C",
H: "<32 byte last hash of consensus table>",
N: uint64_number_of_entries_to_request,
O: uint64_offset_in_table,
T: uint64_txid,
V: []
}
when H or N is set to zero from the requester, they are requesting the current consensus table's hash
consensus response message is as follows for a zero H or N value
S -> C
{
A: "C",
H: "<32 byte hash of current consensus table>",
N: uint64_number_of_entries_in_table,
T: uint64_txid,
U: uint64_ms_next_update_required,
V: [proto, major, minor, patch]
}
requester requests a part of the current table for hash H
N must be less than or equal to 512
C -> S
{
A: "C",
H: "<32 bytes current consensus table hash>",
N: 256,
O: 512,
T: uint64_txid,
V: []
}
consensus response message for routers 512 to 512 + 256
S -> C
{
A: "C",
H: "<32 bytes current concensus table hash>",
K: [list, of, N, pubkeys, from, request, starting, at, position, O],
T: uint64_txid,
V: [proto, major, minor, patch]
}
consensus table is a concatination of all public keys in lexigraphical order.
the hash function in use is 256 bit blake2
gossip RC message
broadcast style RC publish message. sent to all peers infrequently.
it is really an unwarrented GRCM, propagate to all peers.
{
A: "S",
R: [RC],
T: 0,
V: proto
}
replays are dropped using a decaying hashset or decaying bloom filter.
the introset dht has 3 message: GetIntroSet Message (GIM), PutIntroSet Message (PIM), FoundIntroSet Message (FIM)

1
external/cxxopts vendored

@ -0,0 +1 @@
Subproject commit 6fa46a748838d5544ff8e9ab058906ba2c4bc0f3

1
external/date vendored

@ -0,0 +1 @@
Subproject commit 9a0ee2542848ab8625984fc8cdbfb9b5414c0082

@ -0,0 +1 @@
Subproject commit e63a58c5bac94a3a75a7083f87bb092531407a92

@ -0,0 +1 @@
Subproject commit 703bd9caab50b139428cea1aaff9974ebee5742e

1
external/nlohmann vendored

@ -0,0 +1 @@
Subproject commit e7b3b40b5a95bc74b9a7f662830a27c49ffc01b4

@ -0,0 +1 @@
Subproject commit 3b79f4ee539d8f4c709a76b95a13564b6d9ae9cb

@ -23,38 +23,19 @@ namespace llarp
struct Config;
struct Crypto;
struct CryptoManager;
struct MetricsConfig;
struct RouterContact;
namespace thread
{
class ThreadPool;
}
namespace metrics
{
class DefaultManagerGuard;
class PublisherScheduler;
} // namespace metrics
namespace thread
{
class Scheduler;
}
struct Context
{
/// get context from main pointer
static Context *
Get(llarp_main *);
Context();
~Context();
// These come first, in this order.
// This ensures we get metric collection on shutdown
std::unique_ptr< thread::Scheduler > m_scheduler;
std::unique_ptr< metrics::DefaultManagerGuard > m_metricsManager;
std::unique_ptr< metrics::PublisherScheduler > m_metricsPublisher;
Context() = default;
std::unique_ptr< Crypto > crypto;
std::unique_ptr< CryptoManager > cryptoManager;
@ -123,9 +104,6 @@ namespace llarp
bool
ReloadConfig();
void
setupMetrics(const MetricsConfig &metricsConfig);
std::string configfile;
std::string pidfile;
std::unique_ptr< std::promise< void > > closeWaiter;

@ -7,7 +7,9 @@
#include <util/thread/logic.hpp>
#include <util/time.hpp>
#include <absl/types/optional.h>
#include <nlohmann/json.hpp>
#include <nonstd/optional.hpp>
#include <list>
#include <memory>
#include <string>
@ -27,7 +29,7 @@ namespace abyss
IRPCHandler(ConnImpl* impl);
virtual absl::optional< Response >
virtual Response
HandleJSONRPC(Method_t method, const Params& params) = 0;
virtual ~IRPCHandler();

@ -13,12 +13,11 @@ struct DemoHandler : public abyss::httpd::IRPCHandler
{
}
absl::optional< Response >
HandleJSONRPC(Method_t method,
ABSL_ATTRIBUTE_UNUSED const Params& params) override
nonstd::optional< Response >
HandleJSONRPC(Method_t method, const Params& /*params*/) override
{
llarp::LogInfo("method: ", method);
return Response::object();
return nonstd::make_optional(Response::object());
}
};

@ -77,7 +77,7 @@ namespace abyss
}
static void
OnTick(ABSL_ATTRIBUTE_UNUSED llarp_tcp_conn* conn)
OnTick(llarp_tcp_conn* /*conn*/)
{
}

@ -22,14 +22,13 @@ namespace abyss
auto itr = header.begin();
while(itr != header.end())
{
lowerHeader += ::tolower(*itr);
lowerHeader += std::tolower(*itr);
++itr;
}
if(ShouldProcessHeader(string_view(lowerHeader)))
if(ShouldProcessHeader(lowerHeader))
{
val = val.substr(val.find_first_not_of(' '));
Header.Headers.emplace(lowerHeader.c_str(),
llarp::string_view_string(val));
Header.Headers.emplace(lowerHeader.c_str(), val);
}
return true;
}

@ -184,15 +184,15 @@ namespace abyss
{
nlohmann::json response;
response["jsonrpc"] = "2.0";
response["id"] = m_Request["id"];
response["id"] = m_Request["id"].get< std::string >();
auto value = handler->HandleJSONRPC(
m_Request["method"].get< std::string >(),
m_Request["params"]);
if(value)
{
response["result"] = value.value();
return WriteResponseJSON(response);
}
if(!value.is_null())
response["result"] = std::move(value);
return WriteResponseJSON(response);
}
return WriteResponseSimple(500, "internal error", "text/plain",
"nope");

@ -4,59 +4,32 @@ set(LIB_UTIL_SRC
config/config.cpp
config/ini.cpp
config/key_manager.cpp
constants/defaults.cpp
constants/limits.cpp
constants/link_layer.cpp
constants/path.cpp
constants/proto.cpp
${CMAKE_CURRENT_BINARY_DIR}/constants/version.cpp
util/aligned.cpp
util/bencode.cpp
util/bits.cpp
util/buffer.cpp
util/codel.cpp
util/common.cpp
util/encode.cpp
util/endian.cpp
util/decaying_hashset.cpp
util/fs.cpp
util/json.cpp
util/logging/android_logger.cpp
util/logging/file_logger.cpp
util/logging/json_logger.cpp
util/logging/logger.cpp
util/logging/logger_internal.cpp
util/logging/loglevel.cpp
util/logging/ostream_logger.cpp
util/logging/syslog_logger.cpp
util/logging/win32_logger.cpp
util/lokinet_init.c
util/mem.cpp
util/meta/memfn_traits.cpp
util/meta/memfn.cpp
util/meta/object.cpp
util/meta/traits.cpp
util/meta/variant.cpp
util/metrics/core.cpp
util/metrics/json_publisher.cpp
util/metrics/metrics.cpp
util/metrics/metrictank_publisher.cpp
util/metrics/stream_publisher.cpp
util/metrics/types.cpp
util/printer.cpp
util/status.cpp
util/stopwatch.cpp
util/str.cpp
util/string_view.cpp
util/thread/logic.cpp
util/thread/queue_manager.cpp
util/thread/queue.cpp
util/thread/scheduler.cpp
util/thread/thread_pool.cpp
util/thread/threading.cpp
util/thread/threadpool.cpp
util/thread/timerqueue.cpp
util/time.cpp
util/types.cpp
)
add_library(${UTIL_LIB} STATIC ${LIB_UTIL_SRC})
@ -69,12 +42,12 @@ if(ANDROID)
endif()
target_link_libraries(${UTIL_LIB} PUBLIC ${CRYPTOGRAPHY_LIB} ${LOG_LIB} ${CURL_LIBRARIES})
target_link_libraries_system(${UTIL_LIB} absl::synchronization absl::hash absl::container nlohmann_json::nlohmann_json)
# cut back on fluff
if (NOT WIN32)
target_link_libraries_system(${UTIL_LIB} absl::optional absl::variant absl::strings)
endif(NOT WIN32)
target_link_libraries(${UTIL_LIB} PUBLIC
nlohmann_json::nlohmann_json
ghc_filesystem
optional-lite
date::date
)
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(ISOLATE_PROC_SRC linux/netns.cpp)
@ -121,34 +94,30 @@ if(WIN32)
target_link_libraries(${PLATFORM_LIB} PUBLIC iphlpapi)
endif()
set(DNSLIB_SRC
dns/dns.cpp
dns/message.cpp
dns/name.cpp
dns/query.cpp
dns/question.cpp
dns/rr.cpp
dns/serialize.cpp
dns/server.cpp
dns/string.cpp
)
set(CONSENSUS_SRC
consensus/table.cpp
)
set(LIB_SRC
${CONSENSUS_SRC}
${DNSLIB_SRC}
bootstrap.cpp
context.cpp
crypto/constants.cpp
crypto/crypto_libsodium.cpp
crypto/crypto_noop.cpp
crypto/crypto.cpp
crypto/encrypted_frame.cpp
crypto/encrypted.cpp
crypto/types.cpp
dht/bucket.cpp
dht/context.cpp
dht/dht.cpp
dht/explorenetworkjob.cpp
dht/kademlia.cpp
dht/key.cpp
dht/localtaglookup.cpp
dht/localrouterlookup.cpp
dht/localserviceaddresslookup.cpp
@ -158,21 +127,16 @@ set(LIB_SRC
dht/messages/gotintro.cpp
dht/messages/gotrouter.cpp
dht/messages/pubintro.cpp
dht/node.cpp
dht/publishservicejob.cpp
dht/recursiverouterlookup.cpp
dht/serviceaddresslookup.cpp
dht/taglookup.cpp
dht/tx.cpp
dht/txholder.cpp
dht/txowner.cpp
exit/context.cpp
exit/endpoint.cpp
exit/exit_messages.cpp
exit/policy.cpp
exit/session.cpp
handlers/exit.cpp
handlers/null.cpp
handlers/tun.cpp
hook/shell.cpp
iwp/iwp.cpp
@ -180,15 +144,11 @@ set(LIB_SRC
iwp/message_buffer.cpp
iwp/session.cpp
link/factory.cpp
link/i_link_manager.cpp
link/link_manager.cpp
link/server.cpp
link/session.cpp
messages/dht_immediate.cpp
messages/discard.cpp
messages/link_intro.cpp
messages/link_message_parser.cpp
messages/link_message.cpp
messages/relay.cpp
messages/relay_commit.cpp
messages/relay_status.cpp
@ -197,27 +157,22 @@ set(LIB_SRC
nodedb.cpp
path/ihophandler.cpp
path/path_context.cpp
path/path_types.cpp
path/path.cpp
path/pathbuilder.cpp
path/pathset.cpp
path/transit_hop.cpp
pow.cpp
profiling.cpp
router/abstractrouter.cpp
router/i_outbound_message_handler.cpp
router/outbound_message_handler.cpp
router/i_outbound_session_maker.cpp
router/outbound_session_maker.cpp
router/i_rc_lookup_handler.cpp
router/rc_lookup_handler.cpp
router/rc_gossiper.cpp
router/router.cpp
router_contact.cpp
router_id.cpp
router_version.cpp
routing/dht_message.cpp
routing/handler.cpp
routing/message_parser.cpp
routing/message.cpp
routing/path_confirm_message.cpp
routing/path_latency_message.cpp
routing/path_transfer_message.cpp
@ -230,7 +185,6 @@ set(LIB_SRC
service/endpoint_state.cpp
service/endpoint_util.cpp
service/endpoint.cpp
service/handler.cpp
service/hidden_service_address_lookup.cpp
service/identity.cpp
service/info.cpp
@ -238,14 +192,12 @@ set(LIB_SRC
service/intro.cpp
service/lookup.cpp
service/outbound_context.cpp
service/pendingbuffer.cpp
service/protocol.cpp
service/router_lookup_job.cpp
service/sendcontext.cpp
service/session.cpp
service/tag_lookup_job.cpp
service/tag.cpp
service/vanity.cpp
)
if(TESTNET)
set(LIB_SRC ${LIB_SRC} testnet.c)
@ -273,7 +225,7 @@ if(WITH_SHARED)
endif()
if (WARNINGS_AS_ERRORS)
set(WARN_FLAGS -Wall -Wextra -Wshadow -Werror)
set(WARN_FLAGS -Wall -Wextra -Werror)
target_compile_options(${UTIL_LIB} PUBLIC ${WARN_FLAGS})
target_compile_options(${PLATFORM_LIB} PUBLIC ${WARN_FLAGS})
target_compile_options(${STATIC_LIB} PUBLIC ${WARN_FLAGS})

@ -9,12 +9,9 @@
#include <util/logging/logger_syslog.hpp>
#include <util/logging/logger.hpp>
#include <util/mem.hpp>
#include <util/meta/memfn.hpp>
#include <util/str.hpp>
#include <util/lokinet_init.h>
#include <absl/strings/strip.h>
#include <cstdlib>
#include <fstream>
#include <ios>
@ -22,20 +19,66 @@
namespace llarp
{
const char *
lokinetEnv(string_view suffix)
{
std::string env;
env.reserve(8 + suffix.size());
env.append("LOKINET_"s);
env.append(suffix.begin(), suffix.end());
return std::getenv(env.c_str());
}
std::string
tostr(string_view val)
fromEnv(string_view val, string_view envNameSuffix)
{
if(const char *ptr = lokinetEnv(envNameSuffix))
return ptr;
return {val.begin(), val.end()};
}
int
fromEnv(const int &val, string_view envNameSuffix)
{
if(const char *ptr = lokinetEnv(envNameSuffix))
return std::atoi(ptr);
return val;
}
uint16_t
fromEnv(const uint16_t &val, string_view envNameSuffix)
{
if(const char *ptr = lokinetEnv(envNameSuffix))
return std::atoi(ptr);
return val;
}
size_t
fromEnv(const size_t &val, string_view envNameSuffix)
{
if(const char *ptr = lokinetEnv(envNameSuffix))
return std::atoll(ptr);
return val;
}
nonstd::optional< bool >
fromEnv(const nonstd::optional< bool > &val, string_view envNameSuffix)
{
if(const char *ptr = lokinetEnv(envNameSuffix))
return IsTrueValue(ptr);
return val;
}
int
svtoi(string_view val)
{
auto str = tostr(val);
return std::atoi(str.c_str());
return std::atoi(val.data());
}
absl::optional< bool >
nonstd::optional< bool >
setOptBool(string_view val)
{
if(IsTrueValue(val))
@ -63,14 +106,14 @@ namespace llarp
}
if(key == "default-protocol")
{
m_DefaultLinkProto = tostr(val);
m_DefaultLinkProto = val;
LogInfo("overriding default link protocol to '", val, "'");
}
if(key == "netid")
{
if(val.size() <= NetID::size())
{
m_netId = tostr(val);
m_netId = val;
LogInfo("setting netid to '", val, "'");
}
else
@ -98,29 +141,29 @@ namespace llarp
}
if(key == "nickname")
{
m_nickname = tostr(val);
m_nickname = val;
// set logger name here
LogContext::Instance().nodeName = nickname();
LogInfo("nickname set");
}
if(key == "encryption-privkey")
{
m_encryptionKeyfile = tostr(val);
m_encryptionKeyfile = val;
LogDebug("encryption key set to ", m_encryptionKeyfile);
}
if(key == "contact-file")
{
m_ourRcFile = tostr(val);
m_ourRcFile = val;
LogDebug("rc file set to ", m_ourRcFile);
}
if(key == "transport-privkey")
{
m_transportKeyfile = tostr(val);
m_transportKeyfile = val;
LogDebug("transport key set to ", m_transportKeyfile);
}
if((key == "identity-privkey" || key == "ident-privkey"))
{
m_identKeyfile = tostr(val);
m_identKeyfile = val;
LogDebug("identity key set to ", m_identKeyfile);
}
if(key == "public-address" || key == "public-ip")
@ -186,16 +229,16 @@ namespace llarp
}
else if(key == "profiles")
{
m_routerProfilesFile = tostr(val);
m_routerProfilesFile = val;
llarp::LogInfo("setting profiles to ", routerProfilesFile());
}
else if(key == "strict-connect")
{
m_strictConnect = tostr(val);
m_strictConnect = val;
}
else
{
m_netConfig.emplace(tostr(key), tostr(val));
m_netConfig.emplace(key, val);
}
}
@ -204,7 +247,7 @@ namespace llarp
{
if(key == "dir")
{
m_nodedbDir = tostr(val);
m_nodedbDir = val;
}
}
@ -214,12 +257,12 @@ namespace llarp
if(key == "upstream")
{
llarp::LogInfo("add upstream resolver ", val);
netConfig.emplace("upstream-dns", tostr(val));
netConfig.emplace("upstream-dns", val);
}
if(key == "bind")
{
llarp::LogInfo("set local dns to ", val);
netConfig.emplace("local-dns", tostr(val));
netConfig.emplace("local-dns", val);
}
}
@ -229,25 +272,21 @@ namespace llarp
uint16_t proto = 0;
std::unordered_set< std::string > parsed_opts;
std::string v = tostr(val);
std::string::size_type idx;
static constexpr char delimiter = ',';
do
{
idx = v.find_first_of(delimiter);
if(idx != std::string::npos)
idx = val.find_first_of(delimiter);
if(idx != string_view::npos)
{
std::string data = v.substr(0, idx);
absl::StripAsciiWhitespace(&data);
parsed_opts.emplace(std::move(data));
v = v.substr(idx + 1);
parsed_opts.insert(TrimWhitespace(val.substr(0, idx)));
val.remove_prefix(idx + 1);
}
else
{
absl::StripAsciiWhitespace(&v);
parsed_opts.insert(std::move(v));
parsed_opts.insert(TrimWhitespace(val));
}
} while(idx != std::string::npos);
} while(idx != string_view::npos);
std::unordered_set< std::string > opts;
/// for each option
for(const auto &item : parsed_opts)
@ -275,13 +314,12 @@ namespace llarp
}
else
{
m_InboundLinks.emplace_back(tostr(key), AF_INET, proto, std::move(opts));
m_InboundLinks.emplace_back(key, AF_INET, proto, std::move(opts));
}
}
void
ConnectConfig::fromSection(ABSL_ATTRIBUTE_UNUSED string_view key,
string_view val)
ConnectConfig::fromSection(string_view /*key*/, string_view val)
{
routers.emplace_back(val.begin(), val.end());
}
@ -289,7 +327,7 @@ namespace llarp
void
ServicesConfig::fromSection(string_view key, string_view val)
{
services.emplace_back(tostr(key), tostr(val));
services.emplace_back(key, val);
}
void
@ -297,37 +335,7 @@ namespace llarp
{
if(key == "pidfile")
{
pidfile = tostr(val);
}
}
void
MetricsConfig::fromSection(string_view key, string_view val)
{
if(key == "enable-metrics")
{
disableMetrics = IsFalseValue(val);
}
else if(key == "disable-metrics")
{
disableMetrics = IsTrueValue(val);
}
else if(key == "disable-metrics-log")
{
disableMetricLogs = IsTrueValue(val);
}
else if(key == "json-metrics-path")
{
jsonMetricsPath = tostr(val);
}
else if(key == "metric-tank-host")
{
metricTankHost = tostr(val);
}
else
{
// consume everything else as a metric tag
metricTags[tostr(key)] = tostr(val);
pidfile = val;
}
}
@ -340,7 +348,7 @@ namespace llarp
}
if(key == "bind")
{
m_rpcBindAddr = tostr(val);
m_rpcBindAddr = val;
}
if(key == "authkey")
{
@ -354,7 +362,7 @@ namespace llarp
if(key == "service-node-seed")
{
usingSNSeed = true;
ident_keyfile = tostr(val);
ident_keyfile = std::string{val};
}
if(key == "enabled")
{
@ -362,15 +370,15 @@ namespace llarp
}
if(key == "jsonrpc" || key == "addr")
{
lokidRPCAddr = tostr(val);
lokidRPCAddr = val;
}
if(key == "username")
{
lokidRPCUser = tostr(val);
lokidRPCUser = val;
}
if(key == "password")
{
lokidRPCPassword = tostr(val);
lokidRPCPassword = val;
}
}
@ -396,6 +404,18 @@ namespace llarp
LogContext::Instance().logStream = std::make_unique< SysLogStream >();
#endif
}
if(key == "level")
{
const auto maybe = LogLevelFromString(val);
if(not maybe.has_value())
{
LogError("bad log level: ", val);
return;
}
const LogLevel lvl = maybe.value();
LogContext::Instance().runtimeLevel = lvl;
LogInfo("Log level set to ", LogLevelToName(lvl));
}
if(key == "type" && val == "json")
{
m_LogJSON = true;
@ -403,7 +423,7 @@ namespace llarp
if(key == "file")
{
LogInfo("open log file: ", val);
std::string fname = tostr(val);
std::string fname = val;
FILE *const logfile = ::fopen(fname.c_str(), "a");
if(logfile)
{
@ -483,7 +503,6 @@ namespace llarp
links = find_section< LinksConfig >(parser, "bind");
services = find_section< ServicesConfig >(parser, "services");
system = find_section< SystemConfig >(parser, "system");
metrics = find_section< MetricsConfig >(parser, "metrics");
api = find_section< ApiConfig >(parser, "api");
lokid = find_section< LokidConfig >(parser, "lokid");
bootstrap = find_section< BootstrapConfig >(parser, "bootstrap");
@ -619,10 +638,6 @@ llarp_generic_ensure_config(std::ofstream &f, std::string basepath,
f << "# uncomment for syslog logging\n";
f << "#type=syslog\n";
// metrics
f << "[metrics]\n";
f << "json-metrics-path=" << basepath << "metrics.json\n";
f << "\n\n";
f << "# admin api\n";

@ -6,7 +6,6 @@
#include <util/fs.hpp>
#include <util/str.hpp>
#include <absl/strings/str_cat.h>
#include <cstdlib>
#include <functional>
#include <string>
@ -18,76 +17,19 @@ namespace llarp
{
struct ConfigParser;
template < typename Type >
Type
fromEnv(const Type& val, string_view envNameSuffix)
{
std::string envName = absl::StrCat("LOKINET_", envNameSuffix);
char* ptr = std::getenv(envName.c_str());
if(ptr)
{
return ptr;
}
return val;
}
template <>
inline int
fromEnv< int >(const int& val, string_view envNameSuffix)
{
std::string envName = absl::StrCat("LOKINET_", envNameSuffix);
const char* ptr = std::getenv(envName.c_str());
if(ptr)
{
return std::atoi(ptr);
}
return val;
}
template <>
inline uint16_t
fromEnv< uint16_t >(const uint16_t& val, string_view envNameSuffix)
{
std::string envName = absl::StrCat("LOKINET_", envNameSuffix);
const char* ptr = std::getenv(envName.c_str());
if(ptr)
{
return std::atoi(ptr);
}
return val;
}
template <>
inline size_t
fromEnv< size_t >(const size_t& val, string_view envNameSuffix)
{
std::string envName = absl::StrCat("LOKINET_", envNameSuffix);
const char* ptr = std::getenv(envName.c_str());
if(ptr)
{
return std::atoll(ptr);
}
return val;
}
template <>
inline absl::optional< bool >
fromEnv< absl::optional< bool > >(const absl::optional< bool >& val,
string_view envNameSuffix)
{
std::string envName = absl::StrCat("LOKINET_", envNameSuffix);
const char* ptr = std::getenv(envName.c_str());
if(ptr)
{
return IsTrueValue(ptr);
}
inline const char*
lokinetEnv(string_view suffix);
return val;
}
std::string
fromEnv(string_view val, string_view envNameSuffix);
int
fromEnv(const int& val, string_view envNameSuffix);
uint16_t
fromEnv(const uint16_t& val, string_view envNameSuffix);
size_t
fromEnv(const size_t& val, string_view envNameSuffix);
nonstd::optional< bool >
fromEnv(const nonstd::optional< bool >& val, string_view envNameSuffix);
class RouterConfig
{
@ -112,7 +54,7 @@ namespace llarp
// long term identity key
std::string m_identKeyfile = "identity.key";
absl::optional< bool > m_blockBogons;
nonstd::optional< bool > m_blockBogons;
bool m_publicOverride = false;
struct sockaddr_in m_ip4addr;
@ -142,7 +84,7 @@ namespace llarp
int workerThreads() const { return fromEnv(m_workerThreads, "WORKER_THREADS"); }
int numNetThreads() const { return fromEnv(m_numNetThreads, "NUM_NET_THREADS"); }
std::string defaultLinkProto() const { return fromEnv(m_DefaultLinkProto, "LINK_PROTO"); }
absl::optional< bool > blockBogons() const { return fromEnv(m_blockBogons, "BLOCK_BOGONS"); }
nonstd::optional< bool > blockBogons() const { return fromEnv(m_blockBogons, "BLOCK_BOGONS"); }
// clang-format on
void
@ -155,14 +97,14 @@ namespace llarp
using NetConfig = std::unordered_multimap< std::string, std::string >;
private:
absl::optional< bool > m_enableProfiling;
nonstd::optional< bool > m_enableProfiling;
std::string m_routerProfilesFile = "profiles.dat";
std::string m_strictConnect;
NetConfig m_netConfig;
public:
// clang-format off
absl::optional< bool > enableProfiling() const { return fromEnv(m_enableProfiling, "ENABLE_PROFILING"); }
nonstd::optional< bool > enableProfiling() const { return fromEnv(m_enableProfiling, "ENABLE_PROFILING"); }
std::string routerProfilesFile() const { return fromEnv(m_routerProfilesFile, "ROUTER_PROFILES_FILE"); }
std::string strictConnect() const { return fromEnv(m_strictConnect, "STRICT_CONNECT"); }
const NetConfig& netConfig() const { return m_netConfig; }
@ -244,18 +186,6 @@ namespace llarp
fromSection(string_view key, string_view val);
};
struct MetricsConfig
{
bool disableMetrics = true;
bool disableMetricLogs = true;
fs::path jsonMetricsPath;
std::string metricTankHost;
std::map< std::string, std::string > metricTags;
void
fromSection(string_view key, string_view val);
};
class ApiConfig
{
private:
@ -316,7 +246,6 @@ namespace llarp
LinksConfig links;
ServicesConfig services;
SystemConfig system;
MetricsConfig metrics;
ApiConfig api;
LokidConfig lokid;
BootstrapConfig bootstrap;

@ -53,7 +53,7 @@ namespace llarp
bool
ConfigParser::Parse()
{
std::list< String_t > lines;
std::list< string_view > lines;
{
auto itr = m_Data.begin();
// split into lines
@ -69,16 +69,16 @@ namespace llarp
}
}
String_t sectName;
string_view sectName;
size_t lineno = 0;
for(const auto& line : lines)
{
lineno++;
String_t realLine;
string_view realLine;
auto comment = line.find_first_of(';');
if(comment == String_t::npos)
if(comment == string_view::npos)
comment = line.find_first_of('#');
if(comment == String_t::npos)
if(comment == string_view::npos)
realLine = line;
else
realLine = line.substr(0, comment);
@ -89,8 +89,8 @@ namespace llarp
auto sectOpenPos = realLine.find_first_of('[');
auto sectClosPos = realLine.find_first_of(']');
auto kvDelim = realLine.find_first_of('=');
if(sectOpenPos != String_t::npos && sectClosPos != String_t::npos
&& kvDelim == String_t::npos)
if(sectOpenPos != string_view::npos && sectClosPos != string_view::npos
&& kvDelim == string_view::npos)
{
// section header
@ -104,13 +104,13 @@ namespace llarp
// set section name
sectName = realLine.substr(sectOpenPos, sectClosPos);
}
else if(kvDelim != String_t::npos)
else if(kvDelim != string_view::npos)
{
// key value pair
String_t::size_type k_start = 0;
String_t::size_type k_end = kvDelim;
String_t::size_type v_start = kvDelim + 1;
String_t::size_type v_end = realLine.size() - 1;
string_view::size_type k_start = 0;
string_view::size_type k_end = kvDelim;
string_view::size_type v_start = kvDelim + 1;
string_view::size_type v_end = realLine.size() - 1;
// clamp whitespaces
while(whitespace(realLine[k_start]) && k_start != kvDelim)
++k_start;
@ -122,8 +122,8 @@ namespace llarp
--v_end;
// sect.k = v
String_t k = realLine.substr(k_start, k_end - k_start);
String_t v = realLine.substr(v_start, 1 + (v_end - v_start));
string_view k = realLine.substr(k_start, k_end - k_start);
string_view v = realLine.substr(v_start, 1 + (v_end - v_start));
if(k.size() == 0 || v.size() == 0)
{
LogError(m_FileName, " invalid line (", lineno, "): '", line, "'");
@ -144,7 +144,7 @@ namespace llarp
void
ConfigParser::IterAll(
std::function< void(const String_t&, const Section_t&) > visit)
std::function< void(string_view, const Section_t&) > visit)
{
for(const auto& item : m_Config)
visit(item.first, item.second);

@ -12,11 +12,8 @@ namespace llarp
{
struct ConfigParser
{
using String_t = llarp::string_view;
using Section_t =
std::unordered_multimap< String_t, String_t, string_view_hash >;
using Config_impl_t =
std::unordered_map< String_t, Section_t, string_view_hash >;
using Section_t = std::unordered_multimap< std::string, std::string >;
using Config_impl_t = std::unordered_map< std::string, Section_t >;
/// clear parser
void
Clear();
@ -35,7 +32,7 @@ namespace llarp
/// iterate all sections and thier values
void
IterAll(std::function< void(const String_t&, const Section_t&) > visit);
IterAll(std::function< void(string_view, const Section_t&) > visit);
/// visit a section in config read only by name
/// return false if no section or value propagated from visitor

@ -0,0 +1,17 @@
#include <consensus/table.hpp>
#include <crypto/crypto.hpp>
namespace llarp
{
namespace consensus
{
ShortHash
Table::CalculateHash() const
{
ShortHash h;
const llarp_buffer_t buf(begin()->data(), size());
CryptoManager::instance()->shorthash(h, buf);
return h;
}
} // namespace consensus
} // namespace llarp

@ -0,0 +1,20 @@
#ifndef LLARP_CONSENSUS_TABLE_HPP
#define LLARP_CONSENSUS_TABLE_HPP
#include <crypto/types.hpp>
#include <vector>
namespace llarp
{
namespace consensus
{
/// consensus table
struct Table : public std::vector< RouterID >
{
ShortHash
CalculateHash() const;
};
} // namespace consensus
} // namespace llarp
#endif

@ -1 +0,0 @@
#include <constants/defaults.hpp>

@ -1 +0,0 @@
#include <constants/link_layer.hpp>

@ -1 +0,0 @@
#include <constants/path.hpp>

@ -1 +0,0 @@
#include <constants/proto.hpp>

@ -1,6 +1,8 @@
#include <constants/version.hpp>
#include <constants/version.h>
#include <constants/proto.hpp>
// clang-format off
#define LLARP_STRINGIFY2(val) #val
#define LLARP_STRINGIFY(val) LLARP_STRINGIFY2(val)
@ -10,6 +12,7 @@
namespace llarp
{
const std::array<uint16_t, 3> VERSION{{LLARP_VERSION_MAJ, LLARP_VERSION_MIN, LLARP_VERSION_PATCH}};
const std::array<uint64_t, 4> ROUTER_VERSION{{LLARP_PROTO_VERSION, LLARP_VERSION_MAJ, LLARP_VERSION_MIN, LLARP_VERSION_PATCH}};
const char* const VERSION_STR = LLARP_VERSION_STR;
const char* const VERSION_TAG = "@VERSIONTAG@";
const char* const VERSION_FULL = LLARP_NAME "-" LLARP_VERSION_STR "-@VERSIONTAG@";

@ -7,8 +7,8 @@
#define LLARP_NAME "lokinet"
#define LLARP_VERSION_MAJ 0
#define LLARP_VERSION_MIN 6
#define LLARP_VERSION_PATCH 3
#define LLARP_VERSION_MIN 7
#define LLARP_VERSION_PATCH 0
#define LLARP_DEFAULT_NETID "lokinet"

@ -6,10 +6,11 @@
namespace llarp
{
// Given a full lokinet version of: lokinet-1.2.3-abc these are:
extern const std::array< uint16_t, 3 > VERSION; // [1, 2, 3]
extern const char* const VERSION_STR; // "1.2.3"
extern const char* const VERSION_TAG; // "abc"
extern const char* const VERSION_FULL; // "lokinet-1.2.3-abc"
extern const std::array< uint16_t, 3 > VERSION; // [1, 2, 3]
extern const std::array< uint64_t, 4 > ROUTER_VERSION; // [proto, 1, 2, 3]
extern const char* const VERSION_STR; // "1.2.3"
extern const char* const VERSION_TAG; // "abc"
extern const char* const VERSION_FULL; // "lokinet-1.2.3-abc"
extern const char* const RELEASE_MOTTO;
extern const char* const DEFAULT_NETID;

@ -11,14 +11,7 @@
#include <router/router.hpp>
#include <service/context.hpp>
#include <util/logging/logger.h>
#include <util/meta/memfn.hpp>
#include <util/metrics/json_publisher.hpp>
#include <util/metrics/metrics.hpp>
#include <util/metrics/metrictank_publisher.hpp>
#include <util/metrics/stream_publisher.hpp>
#include <util/thread/scheduler.hpp>
#include <absl/strings/str_split.h>
#include <cxxopts.hpp>
#include <csignal>
@ -28,14 +21,6 @@
namespace llarp
{
Context::Context() = default;
Context::~Context()
{
if(m_scheduler)
m_scheduler->stop();
}
bool
Context::CallSafe(std::function< void(void) > f)
{
@ -73,90 +58,9 @@ namespace llarp
nodedb_dir = config->netdb.nodedbDir();
if(!config->metrics.disableMetrics)
{
auto &metricsConfig = config->metrics;
auto &tags = metricsConfig.metricTags;
tags["netid"] = config->router.netId();
tags["nickname"] = config->router.nickname();
setupMetrics(metricsConfig);
if(!config->metrics.disableMetricLogs)
{
m_metricsManager->instance()->addGlobalPublisher(
std::make_shared< metrics::StreamPublisher >(std::cerr));
}
}
return true;
}
void
Context::setupMetrics(const MetricsConfig &metricsConfig)
{
if(!m_scheduler)
{
m_scheduler = std::make_unique< thread::Scheduler >();
}
if(!m_metricsManager)
{
m_metricsManager = std::make_unique< metrics::DefaultManagerGuard >();
}
if(!m_metricsPublisher)
{
m_metricsPublisher = std::make_unique< metrics::PublisherScheduler >(
*m_scheduler, m_metricsManager->instance());
}
if(!metricsConfig.jsonMetricsPath.native().empty())
{
m_metricsManager->instance()->addGlobalPublisher(
std::make_shared< metrics::JsonPublisher >(
std::bind(&metrics::JsonPublisher::directoryPublisher,
std::placeholders::_1, metricsConfig.jsonMetricsPath)));
}
if(!metricsConfig.metricTankHost.empty())
{
if(std::getenv("LOKINET_ENABLE_METRIC_TANK"))
{
static std::string WARNING = R"(
__ ___ ____ _ _ ___ _ _ ____
\ \ / / \ | _ \| \ | |_ _| \ | |/ ___|
\ \ /\ / / _ \ | |_) | \| || || \| | | _
\ V V / ___ \| _ <| |\ || || |\ | |_| |
\_/\_/_/ \_\_| \_\_| \_|___|_| \_|\____|
This Lokinet session is not private!!
Sending connection metrics to metrictank!!
__ ___ ____ _ _ ___ _ _ ____
\ \ / / \ | _ \| \ | |_ _| \ | |/ ___|
\ \ /\ / / _ \ | |_) | \| || || \| | | _
\ V V / ___ \| _ <| |\ || || |\ | |_| |
\_/\_/_/ \_\_| \_\_| \_|___|_| \_|\____|
)";
std::cerr << WARNING << '\n';
std::pair< std::string, std::string > split =
absl::StrSplit(metricsConfig.metricTankHost, ':');
m_metricsManager->instance()->addGlobalPublisher(
std::make_shared< metrics::MetricTankPublisher >(
metricsConfig.metricTags, split.first, stoi(split.second)));
}
else
{
std::cerr << "metrictank host specified, but "
"LOKINET_ENABLE_METRIC_TANK not set, skipping\n";
}
}
m_metricsPublisher->setDefault(absl::Seconds(30));
m_scheduler->start();
}
void
Context::SetPIDFile(const std::string &fname)
{

@ -1 +0,0 @@
#include <crypto/constants.hpp>

@ -6,7 +6,6 @@
#include <util/buffer.hpp>
#include <absl/base/optimization.h>
#include <functional>
#include <cstdint>
@ -54,15 +53,29 @@ namespace llarp
/// blake2b 256 bit
virtual bool
shorthash(ShortHash &, const llarp_buffer_t &) = 0;
/// blake2s 256 bit hmac
/// blake2s 256 bit "hmac" (keyed hash)
virtual bool
hmac(byte_t *, const llarp_buffer_t &, const SharedSecret &) = 0;
/// ed25519 sign
virtual bool
sign(Signature &, const SecretKey &, const llarp_buffer_t &) = 0;
/// ed25519 sign (custom with derived keys)
virtual bool
sign(Signature &, const PrivateKey &, const llarp_buffer_t &) = 0;
/// ed25519 verify
virtual bool
verify(const PubKey &, const llarp_buffer_t &, const Signature &) = 0;
/// derive sub keys for public keys
virtual bool
derive_subkey(PubKey &, const PubKey &, uint64_t,
const AlignedBuffer< 32 > * = nullptr) = 0;
/// derive sub keys for private keys
virtual bool
derive_subkey_private(PrivateKey &, const SecretKey &, uint64_t,
const AlignedBuffer< 32 > * = nullptr) = 0;
/// seed to secretkey
virtual bool
seed_to_secretkey(llarp::SecretKey &, const llarp::IdentitySecret &) = 0;
@ -126,15 +139,17 @@ namespace llarp
}
static Crypto *
instance() ABSL_ATTRIBUTE_RETURNS_NONNULL
instance()
{
if(ABSL_PREDICT_TRUE(m_crypto))
{
#ifdef NDEBUG
return m_crypto;
#else
if(m_crypto)
return m_crypto;
}
assert(false && "Cryptomanager::instance() was undefined");
abort();
#endif
}
};

@ -2,10 +2,15 @@
#include <sodium/crypto_generichash.h>
#include <sodium/crypto_sign.h>
#include <sodium/crypto_scalarmult.h>
#include <sodium/crypto_scalarmult_ed25519.h>
#include <sodium/crypto_stream_xchacha20.h>
#include <sodium/crypto_core_ed25519.h>
#include <sodium/randombytes.h>
#include <sodium/utils.h>
#include <util/mem.hpp>
#include <util/endian.hpp>
#include <cassert>
#include <cstring>
extern "C"
{
@ -171,6 +176,51 @@ namespace llarp
!= -1;
}
bool
CryptoLibSodium::sign(Signature &sig, const PrivateKey &privkey,
const llarp_buffer_t &buf)
{
PubKey pubkey;
privkey.toPublic(pubkey);
crypto_hash_sha512_state hs;
unsigned char nonce[64];
unsigned char hram[64];
unsigned char mulres[32];
// r = H(s || M) where here s is pseudorandom bytes typically generated as
// part of hashing the seed (i.e. [a,s] = H(k)), but for derived
// PrivateKeys will come from a hash of the root key's s concatenated with
// the derivation hash.
crypto_hash_sha512_init(&hs);
crypto_hash_sha512_update(&hs, privkey.signingHash(), 32);
crypto_hash_sha512_update(&hs, buf.base, buf.sz);
crypto_hash_sha512_final(&hs, nonce);
crypto_core_ed25519_scalar_reduce(nonce, nonce);
// copy pubkey into sig to make (for now) sig = (R || A)
memmove(sig.data() + 32, pubkey.data(), 32);
// R = r * B
crypto_scalarmult_ed25519_base_noclamp(sig.data(), nonce);
// hram = H(R || A || M)
crypto_hash_sha512_init(&hs);
crypto_hash_sha512_update(&hs, sig.data(), 64);
crypto_hash_sha512_update(&hs, buf.base, buf.sz);
crypto_hash_sha512_final(&hs, hram);
// S = r + H(R || A || M) * s, so sig = (R || S)
crypto_core_ed25519_scalar_reduce(hram, hram);
crypto_core_ed25519_scalar_mul(mulres, hram, privkey.data());
crypto_core_ed25519_scalar_add(sig.data() + 32, mulres, nonce);
sodium_memzero(nonce, sizeof nonce);
return true;
}
bool
CryptoLibSodium::verify(const PubKey &pub, const llarp_buffer_t &buf,
const Signature &sig)
@ -180,16 +230,154 @@ namespace llarp
!= -1;
}
/// clamp a 32 byte ec point
static void
clamp_ed25519(byte_t *out)
{
out[0] &= 248;
out[31] &= 127;
out[31] |= 64;
}
template < typename K >
static K
clamp(const K &p)
{
K out = p;
clamp_ed25519(out);
return out;
}
template < typename K >
static bool
is_clamped(const K &key)
{
K other(key);
clamp_ed25519(other.data());
return other == key;
}
constexpr static char derived_key_hash_str[161] =
"just imagine what would happen if we all decided to understand. you "
"can't in the and by be or then before so just face it this text hurts "
"to read? lokinet yolo!";
template < typename K >
static bool make_scalar(AlignedBuffer< 32 > &out, const K &k, uint64_t i)
{
// b = BLIND-STRING || k || i
std::array< byte_t, 160 + K::SIZE + sizeof(uint64_t) > buf;
std::copy(derived_key_hash_str, derived_key_hash_str + 160, buf.begin());
std::copy(k.begin(), k.end(), buf.begin() + 160);
htole64buf(buf.data() + 160 + K::SIZE, i);
// n = H(b)
// h = make_point(n)
ShortHash n;
return -1
!= crypto_generichash_blake2b(n.data(), ShortHash::SIZE, buf.data(),
buf.size(), nullptr, 0)
&& -1 != crypto_core_ed25519_from_uniform(out.data(), n.data());
}
static AlignedBuffer< 32 > zero;
bool
CryptoLibSodium::derive_subkey(PubKey &out_pubkey,
const PubKey &root_pubkey, uint64_t key_n,
const AlignedBuffer< 32 > *hash)
{
// scalar h = H( BLIND-STRING || root_pubkey || key_n )
AlignedBuffer< 32 > h;
if(hash)
h = *hash;
else if(not make_scalar(h, root_pubkey, key_n))
{
LogError("cannot make scalar");
return false;
}
return 0
== crypto_scalarmult_ed25519(out_pubkey.data(), h.data(),
root_pubkey.data());
}
bool
CryptoLibSodium::derive_subkey_private(PrivateKey &out_key,
const SecretKey &root_key,
uint64_t key_n,
const AlignedBuffer< 32 > *hash)
{
// Derives a private subkey from a root key.
//
// The basic idea is:
//
// h = H( BLIND-STRING || A || key_n )
// a - private key
// A = aB - public key
// s - signing hash
// a' = ah - derived private key
// A' = a'B = (ah)B - derived public key
// s' = H(h || s) - derived signing hash
//
// libsodium throws some wrenches in the mechanics which are a nuisance,
// the biggest of which is that sodium's secret key is *not* `a`; rather
// it is the seed. If you want to get the private key (i.e. "a"), you
// need to SHA-512 hash it and then clamp that.
//
// This also makes signature verification harder: we can't just use
// sodium's sign function because it wants to be given the seed rather
// than the private key, and moreover we can't actually *get* the seed to
// make libsodium happy because we only have `ah` above; thus we
// reimplemented most of sodium's detached signing function but without
// the hash step.
//
// Lastly, for the signing hash s', we need some value that is both
// different from the root s but also unknowable from the public key
// (since otherwise `r` in the signing function would be known), so we
// generate it from a hash of `h` and the root key's (psuedorandom)
// signing hash, `s`.
//
const auto root_pubkey = root_key.toPublic();
AlignedBuffer< 32 > h;
if(hash)
h = *hash;
else if(not make_scalar(h, root_pubkey, key_n))
{
LogError("cannot make scalar");
return false;
}
h[0] &= 248;
h[31] &= 63;
h[31] |= 64;
PrivateKey a;
if(!root_key.toPrivate(a))
return false;
// a' = ha
crypto_core_ed25519_scalar_mul(out_key.data(), h.data(), a.data());
// s' = H(h || s)
std::array< byte_t, 64 > buf;
std::copy(h.begin(), h.end(), buf.begin());
std::copy(a.signingHash(), a.signingHash() + 32, buf.begin() + 32);
return -1
!= crypto_generichash_blake2b(out_key.signingHash(), 32, buf.data(),
buf.size(), nullptr, 0);
return true;
}
bool
CryptoLibSodium::seed_to_secretkey(llarp::SecretKey &secret,
const llarp::IdentitySecret &seed)
{
PubKey pk;
return crypto_sign_ed25519_seed_keypair(pk.data(), secret.data(),
return crypto_sign_ed25519_seed_keypair(secret.data() + 32, secret.data(),
seed.data())
!= -1;
}
void
CryptoLibSodium::randomize(const llarp_buffer_t &buff)
{
@ -212,6 +400,8 @@ namespace llarp
assert(pk == sk_pk);
(void)result;
(void)sk_pk;
// encryption_keygen(keys);
}
bool

@ -48,11 +48,27 @@ namespace llarp
/// ed25519 sign
bool
sign(Signature &, const SecretKey &, const llarp_buffer_t &) override;
/// ed25519 sign (custom with derived keys)
bool
sign(Signature &, const PrivateKey &, const llarp_buffer_t &) override;
/// ed25519 verify
bool
verify(const PubKey &, const llarp_buffer_t &,
const Signature &) override;
/// derive sub keys for public keys. hash is really only intended for
/// testing and overrides key_n if given.
bool
derive_subkey(PubKey &derived, const PubKey &root, uint64_t key_n,
const AlignedBuffer< 32 > *hash = nullptr) override;
/// derive sub keys for private keys. hash is really only intended for
/// testing and overrides key_n if given.
bool
derive_subkey_private(PrivateKey &derived, const SecretKey &root,
uint64_t key_n,
const AlignedBuffer< 32 > *hash = nullptr) override;
/// seed to secretkey
bool
seed_to_secretkey(llarp::SecretKey &,

@ -1 +0,0 @@
#include <crypto/crypto_noop.hpp>

@ -106,10 +106,16 @@ namespace llarp
}
bool
sign(Signature &sig, const SecretKey &key, const llarp_buffer_t &) override
sign(Signature &sig, const SecretKey &, const llarp_buffer_t &) override
{
static_assert(Signature::SIZE == SecretKey::SIZE, "");
std::copy(key.begin(), key.end(), sig.begin());
std::fill(sig.begin(), sig.end(), 0);
return true;
}
bool
sign(Signature &sig, const PrivateKey &, const llarp_buffer_t &) override
{
std::fill(sig.begin(), sig.end(), 0);
return true;
}

@ -1 +0,0 @@
#include <crypto/encrypted.hpp>

@ -7,6 +7,10 @@
#include <iterator>
#include <sodium/crypto_sign.h>
#include <sodium/crypto_sign_ed25519.h>
#include <sodium/crypto_scalarmult_ed25519.h>
namespace llarp
{
bool
@ -51,6 +55,39 @@ namespace llarp
return BDecode(&buf);
}
bool
SecretKey::Recalculate()
{
PrivateKey key;
PubKey pubkey;
if(!toPrivate(key) || !key.toPublic(pubkey))
return false;
std::memcpy(data() + 32, pubkey.data(), 32);
return true;
}
bool
SecretKey::toPrivate(PrivateKey& key) const
{
// Ed25519 calculates a 512-bit hash from the seed; the first half (clamped)
// is the private key; the second half is the hash that gets used in
// signing.
unsigned char h[crypto_hash_sha512_BYTES];
if(crypto_hash_sha512(h, data(), 32) < 0)
return false;
h[0] &= 248;
h[31] &= 63;
h[31] |= 64;
std::memcpy(key.data(), h, 64);
return true;
}
bool
PrivateKey::toPublic(PubKey& pubkey) const
{
return crypto_scalarmult_ed25519_base_noclamp(pubkey.data(), data()) != -1;
}
bool
SecretKey::SaveToFile(const char* fname) const
{
@ -94,25 +131,25 @@ namespace llarp
}
byte_t*
Signature::R()
Signature::Lo()
{
return data();
}
const byte_t*
Signature::R() const
Signature::Lo() const
{
return data();
}
byte_t*
Signature::C()
Signature::Hi()
{
return data() + 32;
}
const byte_t*
Signature::C() const
Signature::Hi() const
{
return data() + 32;
}

@ -16,9 +16,7 @@ namespace llarp
struct PubKey final : public AlignedBuffer< PUBKEYSIZE >
{
PubKey() : AlignedBuffer< SIZE >()
{
}
PubKey() = default;
explicit PubKey(const byte_t *ptr) : AlignedBuffer< SIZE >(ptr)
{
@ -76,16 +74,36 @@ namespace llarp
return lhs.as_array() == rhs.as_array();
}
struct PrivateKey;
/// Stores a sodium "secret key" value, which is actually the 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 SecretKey final : public AlignedBuffer< SECKEYSIZE >
{
SecretKey() : AlignedBuffer< SECKEYSIZE >()
SecretKey() = default;
explicit SecretKey(const byte_t *ptr) : AlignedBuffer< SECKEYSIZE >(ptr)
{
}
explicit SecretKey(const byte_t *ptr) : AlignedBuffer< SECKEYSIZE >(ptr)
// The full data
explicit SecretKey(const AlignedBuffer< SECKEYSIZE > &seed)
: AlignedBuffer< SECKEYSIZE >(seed)
{
}
// Just the seed, we recalculate the pubkey
explicit SecretKey(const AlignedBuffer< 32 > &seed)
{
std::copy(seed.begin(), seed.end(), begin());
Recalculate();
}
/// recalculate public component
bool
Recalculate();
std::ostream &
print(std::ostream &stream, int level, int spaces) const
{
@ -100,6 +118,11 @@ namespace llarp
return PubKey(data() + 32);
}
/// Computes the private key from the secret key (which is actually the
/// seed)
bool
toPrivate(PrivateKey &key) const;
bool
LoadFromFile(const char *fname);
@ -115,6 +138,61 @@ namespace llarp
return out << "[secretkey]";
}
/// 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 PrivateKey final : public AlignedBuffer< 64 >
{
PrivateKey() = default;
explicit PrivateKey(const byte_t *ptr) : AlignedBuffer< 64 >(ptr)
{
}
explicit PrivateKey(const AlignedBuffer< 64 > &key_and_hash)
: AlignedBuffer< 64 >(key_and_hash)
{
}
/// Returns a pointer to the beginning of the 32-byte hash which is used for
/// pseudorandomness when signing with this private key.
const byte_t *
signingHash() const
{
return data() + 32;
}
/// Returns a pointer to the beginning of the 32-byte hash which is used for
/// pseudorandomness when signing with this private key.
byte_t *
signingHash()
{
return data() + 32;
}
std::ostream &
print(std::ostream &stream, int level, int spaces) const
{
Printer printer(stream, level, spaces);
printer.printValue("privatekey");
return stream;
}
/// Computes the public key
bool
toPublic(PubKey &pubkey) const;
};
inline std::ostream &
operator<<(std::ostream &out, const PrivateKey &)
{
// return out << k.ToHex();
// make sure we never print out private keys
return out << "[privatekey]";
}
/// IdentitySecret is a secret key from a service node secret seed
struct IdentitySecret final : public AlignedBuffer< 32 >
{
@ -145,16 +223,16 @@ namespace llarp
struct Signature final : public AlignedBuffer< SIGSIZE >
{
byte_t *
R();
Hi();
const byte_t *
R() const;
Hi() const;
byte_t *
C();
Lo();
const byte_t *
C() const;
Lo() const;
};
using TunnelNonce = AlignedBuffer< TUNNONCESIZE >;

@ -1 +0,0 @@
#include <dht/bucket.hpp>

@ -208,6 +208,16 @@ namespace llarp
}
}
template < typename Visit_t >
void
ForEachNode(Visit_t visit)
{
for(const auto& item : nodes)
{
visit(item.second);
}
}
void
Clear()
{

@ -21,6 +21,7 @@
#include <nodedb.hpp>
#include <profiling.hpp>
#include <router/i_rc_lookup_handler.hpp>
#include <util/decaying_hashset.hpp>
#include <vector>
namespace llarp
@ -44,19 +45,17 @@ namespace llarp
GetRouter()->rcLookupHandler().CheckRC(rc);
}
/// on behalf of whoasked request introset for target from dht router with
/// key askpeer
void
LookupIntroSetRecursive(
const service::Address& target, const Key_t& whoasked,
uint64_t whoaskedTX, const Key_t& askpeer, uint64_t R,
service::IntroSetLookupHandler result = nullptr) override;
LookupIntroSetRelayed(
const Key_t& target, const Key_t& whoasked, uint64_t whoaskedTX,
const Key_t& askpeer, uint64_t relayOrder,
service::EncryptedIntroSetLookupHandler result = nullptr) override;
void
LookupIntroSetIterative(
const service::Address& target, const Key_t& whoasked,
uint64_t whoaskedTX, const Key_t& askpeer,
service::IntroSetLookupHandler result = nullptr) override;
LookupIntroSetDirect(
const Key_t& target, const Key_t& whoasked, uint64_t whoaskedTX,
const Key_t& askpeer,
service::EncryptedIntroSetLookupHandler result = nullptr) override;
/// on behalf of whoasked request router with public key target from dht
/// router with key askpeer
@ -83,19 +82,6 @@ namespace llarp
return pendingRouterLookups().HasLookupFor(target);
}
/// on behalf of whoasked request introsets with tag from dht router with
/// key askpeer with Recursion depth R
void
LookupTagRecursive(const service::Tag& tag, const Key_t& whoasked,
uint64_t whoaskedTX, const Key_t& askpeer,
uint64_t R) override;
/// issue dht lookup for tag via askpeer and send reply to local path
void
LookupTagForPath(const service::Tag& tag, uint64_t txid,
const llarp::PathID_t& path,
const Key_t& askpeer) override;
/// issue dht lookup for router via askpeer and send reply to local path
void
LookupRouterForPath(const RouterID& target, uint64_t txid,
@ -104,9 +90,9 @@ namespace llarp
/// issue dht lookup for introset for addr via askpeer and send reply to
/// local path
void
LookupIntroSetForPath(const service::Address& addr, uint64_t txid,
const llarp::PathID_t& path,
const Key_t& askpeer) override;
LookupIntroSetForPath(const Key_t& addr, uint64_t txid,
const llarp::PathID_t& path, const Key_t& askpeer,
uint64_t relayOrder) override;
/// send a dht message to peer, if keepalive is true then keep the session
/// with that peer alive for 10 seconds
@ -120,11 +106,6 @@ namespace llarp
const Key_t& requester, uint64_t txid, const RouterID& target,
std::vector< std::unique_ptr< IMessage > >& reply) override;
std::set< service::IntroSet >
FindRandomIntroSetsWithTagExcluding(
const service::Tag& tag, size_t max = 2,
const std::set< service::IntroSet >& excludes = {}) override;
/// handle rc lookup from requester for target
void
LookupRouterRelayed(
@ -139,10 +120,10 @@ namespace llarp
/// send introset to peer from source with S counter and excluding peers
void
PropagateIntroSetTo(const Key_t& source, uint64_t sourceTX,
const service::IntroSet& introset, const Key_t& peer,
uint64_t S,
const std::set< Key_t >& exclude) override;
PropagateIntroSetTo(const Key_t& from, uint64_t txid,
const service::EncryptedIntroSet& introset,
const Key_t& tellpeer, bool relayed,
uint64_t relayOrder);
/// initialize dht context and explore every exploreInterval milliseconds
void
@ -150,9 +131,8 @@ namespace llarp
llarp_time_t exploreInterval) override;
/// get localally stored introset by service address
const llarp::service::IntroSet*
GetIntroSetByServiceAddress(
const llarp::service::Address& addr) const override;
nonstd::optional< llarp::service::EncryptedIntroSet >
GetIntroSetByLocation(const Key_t& location) const override;
void
handle_cleaner_timer(uint64_t interval);
@ -228,11 +208,23 @@ namespace llarp
return router->nodedb()->Get(k.as_array(), rc);
}
void
FloodRCLater(const dht::Key_t from, const RouterContact rc) override;
PendingIntrosetLookups _pendingIntrosetLookups;
PendingTagLookups _pendingTagLookups;
PendingRouterLookups _pendingRouterLookups;
PendingExploreLookups _pendingExploreLookups;
using RCGossipReplayFilter_t = util::DecayingHashSet< RouterContact >;
RCGossipReplayFilter_t m_GossipReplayFilter;
using RCGossipList_t = std::unordered_multimap< RouterContact, RouterID,
RouterContact::Hash >;
/// list of RCs that we want to publish with who gave us the publish
RCGossipList_t m_GossipList;
PendingIntrosetLookups&
pendingIntrosetLookups() override
{
@ -245,18 +237,6 @@ namespace llarp
return _pendingIntrosetLookups;
}
PendingTagLookups&
pendingTagLookups() override
{
return _pendingTagLookups;
}
const PendingTagLookups&
pendingTagLookups() const override
{
return _pendingTagLookups;
}
PendingRouterLookups&
pendingRouterLookups() override
{
@ -305,7 +285,9 @@ namespace llarp
Key_t ourKey;
};
Context::Context()
static constexpr auto GossipFilterDecayInterval = std::chrono::minutes(30);
Context::Context() : m_GossipReplayFilter(GossipFilterDecayInterval)
{
randombytes((byte_t*)&ids, sizeof(uint64_t));
}
@ -355,18 +337,51 @@ namespace llarp
{
// clean up transactions
CleanupTX();
const llarp_time_t now = Now();
// flush pending floods
if(router->IsServiceNode())
{
std::unordered_set< RouterContact, RouterContact::Hash > keys;
for(const auto& item : m_GossipList)
{
// filter hit don't publish it at all
if(not m_GossipReplayFilter.Insert(item.first))
continue;
// skip if duplicate RC
if(not keys.emplace(item.first).second)
continue;
const auto& rc = item.first;
// build set of routers to not send to for this RC
std::set< RouterID > exclude = {rc.pubkey};
const auto range = m_GossipList.equal_range(rc);
auto itr = range.first;
while(itr != range.second)
{
exclude.emplace(itr->second);
++itr;
}
Nodes()->ForEachNode([self = this, rc, &exclude](const auto& node) {
const RouterID K(node.rc.pubkey);
if(exclude.find(K) == exclude.end())
self->DHTSendTo(K, new GotRouterMessage(rc));
});
}
}
// clear gossip list
m_GossipList.clear();
// decay gossip filter
m_GossipReplayFilter.Decay(now);
if(_services)
{
// expire intro sets
auto now = Now();
auto& nodes = _services->nodes;
auto itr = nodes.begin();
while(itr != nodes.end())
{
if(itr->second.introset.IsExpired(now))
{
llarp::LogDebug("introset expired ", itr->second.introset.A.Addr());
itr = nodes.erase(itr);
}
else
@ -376,53 +391,6 @@ namespace llarp
ScheduleCleanupTimer();
}
std::set< service::IntroSet >
Context::FindRandomIntroSetsWithTagExcluding(
const service::Tag& tag, size_t max,
const std::set< service::IntroSet >& exclude)
{
std::set< service::IntroSet > found;
auto& nodes = _services->nodes;
if(nodes.size() == 0)
{
return found;
}
auto itr = nodes.begin();
// start at random middle point
auto start = llarp::randint() % nodes.size();
std::advance(itr, start);
auto end = itr;
std::string tagname = tag.ToString();
while(itr != nodes.end())
{
if(itr->second.introset.topic.ToString() == tagname)
{
if(exclude.count(itr->second.introset) == 0)
{
found.insert(itr->second.introset);
if(found.size() == max)
return found;
}
}
++itr;
}
itr = nodes.begin();
while(itr != end)
{
if(itr->second.introset.topic.ToString() == tagname)
{
if(exclude.count(itr->second.introset) == 0)
{
found.insert(itr->second.introset);
if(found.size() == max)
return found;
}
}
++itr;
}
return found;
}
void
Context::LookupRouterRelayed(
const Key_t& requester, uint64_t txid, const Key_t& target,
@ -435,14 +403,29 @@ namespace llarp
new GotRouterMessage(requester, txid, {router->rc()}, false));
return;
}
Key_t next;
std::set< Key_t > excluding = {requester, ourKey};
if(_nodes->FindCloseExcluding(target, next, excluding))
if(not GetRouter()->ConnectionToRouterAllowed(target.as_array()))
{
// explicitly not allowed
replies.emplace_back(new GotRouterMessage(requester, txid, {}, false));
return;
}
const auto rc = GetRouter()->nodedb()->FindClosestTo(target);
const Key_t next(rc.pubkey);
{
if(next == target)
{
// we know it, ask them directly for their own RC to keep it updated
LookupRouterRecursive(target.as_array(), requester, txid, next);
// we know the target
if(rc.ExpiresSoon(llarp::time_now_ms()))
{
// ask target for their rc to keep it updated
LookupRouterRecursive(target.as_array(), requester, txid, next);
}
else
{
// send reply with rc we know of
replies.emplace_back(
new GotRouterMessage(requester, txid, {rc}, false));
}
}
else if(recursive) // are we doing a recursive lookup?
{
@ -467,22 +450,15 @@ namespace llarp
new GotRouterMessage(requester, next, txid, false));
}
}
else
{
// we don't know it and have no closer peers to ask
replies.emplace_back(new GotRouterMessage(requester, txid, {}, false));
}
}
const llarp::service::IntroSet*
Context::GetIntroSetByServiceAddress(
const llarp::service::Address& addr) const
nonstd::optional< llarp::service::EncryptedIntroSet >
Context::GetIntroSetByLocation(const Key_t& key) const
{
auto key = addr.ToKey();
auto itr = _services->nodes.find(key);
if(itr == _services->nodes.end())
return nullptr;
return &itr->second.introset;
return {};
return itr->second.introset;
}
void
@ -493,7 +469,6 @@ namespace llarp
pendingRouterLookups().Expire(now);
_pendingIntrosetLookups.Expire(now);
pendingTagLookups().Expire(now);
pendingExploreLookups().Expire(now);
}
@ -503,7 +478,6 @@ namespace llarp
util::StatusObject obj{
{"pendingRouterLookups", pendingRouterLookups().ExtractStatus()},
{"pendingIntrosetLookups", _pendingIntrosetLookups.ExtractStatus()},
{"pendingTagLookups", pendingTagLookups().ExtractStatus()},
{"pendingExploreLookups", pendingExploreLookups().ExtractStatus()},
{"nodes", _nodes->ExtractStatus()},
{"services", _services->ExtractStatus()},
@ -522,7 +496,7 @@ namespace llarp
llarp::LogDebug("initialize dht with key ", ourKey);
// start exploring
r->logic()->call_later(
router->logic()->call_later(
exploreInterval,
std::bind(&llarp::dht::Context::handle_explore_timer, this,
exploreInterval));
@ -554,7 +528,7 @@ namespace llarp
llarp::routing::DHTMessage reply;
if(!msg.HandleMessage(router->dht(), reply.M))
return false;
if(!reply.M.empty())
if(not reply.M.empty())
{
auto path = router->pathContext().GetByUpstream(router->pubkey(), id);
return path && path->SendRoutingMessage(reply, router);
@ -563,78 +537,65 @@ namespace llarp
}
void
Context::LookupIntroSetForPath(const service::Address& addr, uint64_t txid,
Context::LookupIntroSetForPath(const Key_t& addr, uint64_t txid,
const llarp::PathID_t& path,
const Key_t& askpeer)
const Key_t& askpeer, uint64_t relayOrder)
{
TXOwner asker(OurKey(), txid);
TXOwner peer(askpeer, ++ids);
_pendingIntrosetLookups.NewTX(
peer, asker, addr,
new LocalServiceAddressLookup(path, txid, addr, this, askpeer));
new LocalServiceAddressLookup(path, txid, relayOrder, addr, this,
askpeer));
}
void
Context::PropagateIntroSetTo(const Key_t& from, uint64_t txid,
const service::IntroSet& introset,
const Key_t& tellpeer, uint64_t S,
const std::set< Key_t >& exclude)
const service::EncryptedIntroSet& introset,
const Key_t& tellpeer, bool relayed,
uint64_t relayOrder)
{
TXOwner asker(from, txid);
TXOwner peer(tellpeer, ++ids);
service::Address addr = introset.A.Addr();
_pendingIntrosetLookups.NewTX(
peer, asker, addr,
new PublishServiceJob(asker, introset, this, S, exclude));
}
void
Context::LookupIntroSetRecursive(const service::Address& addr,
const Key_t& whoasked, uint64_t txid,
const Key_t& askpeer, uint64_t R,
service::IntroSetLookupHandler handler)
{
TXOwner asker(whoasked, txid);
TXOwner peer(askpeer, ++ids);
const Key_t addr(introset.derivedSigningKey);
_pendingIntrosetLookups.NewTX(
peer, asker, addr,
new ServiceAddressLookup(asker, addr, this, R, handler), (R * 2000));
new PublishServiceJob(asker, introset, this, relayed, relayOrder));
}
void
Context::LookupIntroSetIterative(const service::Address& addr,
const Key_t& whoasked, uint64_t txid,
const Key_t& askpeer,
service::IntroSetLookupHandler handler)
Context::LookupIntroSetRelayed(
const Key_t& addr, const Key_t& whoasked, uint64_t txid,
const Key_t& askpeer, uint64_t relayOrder,
service::EncryptedIntroSetLookupHandler handler)
{
TXOwner asker(whoasked, txid);
TXOwner peer(askpeer, ++ids);
_pendingIntrosetLookups.NewTX(
peer, asker, addr,
new ServiceAddressLookup(asker, addr, this, 0, handler), 1000);
new ServiceAddressLookup(asker, addr, this, relayOrder, handler));
}
void
Context::LookupTagRecursive(const service::Tag& tag, const Key_t& whoasked,
uint64_t whoaskedTX, const Key_t& askpeer,
uint64_t R)
Context::FloodRCLater(const dht::Key_t from, const RouterContact rc)
{
TXOwner asker(whoasked, whoaskedTX);
TXOwner peer(askpeer, ++ids);
_pendingTagLookups.NewTX(peer, asker, tag,
new TagLookup(asker, tag, this, R));
llarp::LogDebug("ask ", askpeer.SNode(), " for ", tag, " on behalf of ",
whoasked.SNode(), " R=", R);
// check valid rc
if(not router->rcLookupHandler().CheckRC(rc))
return;
m_GossipList.emplace(rc, from.as_array());
// TODO: don't publish our rc in next interval (based of whitelist size)
}
void
Context::LookupTagForPath(const service::Tag& tag, uint64_t txid,
const llarp::PathID_t& path, const Key_t& askpeer)
Context::LookupIntroSetDirect(
const Key_t& addr, const Key_t& whoasked, uint64_t txid,
const Key_t& askpeer, service::EncryptedIntroSetLookupHandler handler)
{
TXOwner asker(whoasked, txid);
TXOwner peer(askpeer, ++ids);
TXOwner whoasked(OurKey(), txid);
_pendingTagLookups.NewTX(peer, whoasked, tag,
new LocalTagLookup(path, txid, tag, this));
_pendingIntrosetLookups.NewTX(
peer, asker, addr,
new ServiceAddressLookup(asker, addr, this, 0, handler), 1000);
}
bool
@ -672,11 +633,11 @@ namespace llarp
}
for(const auto& f : foundRouters)
{
const RouterID r = f.as_array();
const RouterID id = f.as_array();
// discard shit routers
if(router->routerProfiling().IsBadForConnect(r))
if(router->routerProfiling().IsBadForConnect(id))
continue;
closer.emplace_back(r);
closer.emplace_back(id);
}
llarp::LogDebug("Gave ", closer.size(), " routers for exploration");
reply.emplace_back(new GotRouterMessage(txid, closer, false));

@ -26,10 +26,7 @@ namespace llarp
struct AbstractContext
{
using PendingIntrosetLookups =
TXHolder< service::Address, service::IntroSet,
service::Address::Hash >;
using PendingTagLookups =
TXHolder< service::Tag, service::IntroSet, service::Tag::Hash >;
TXHolder< Key_t, service::EncryptedIntroSet, Key_t::Hash >;
using PendingRouterLookups =
TXHolder< RouterID, RouterContact, RouterID::Hash >;
using PendingExploreLookups =
@ -45,50 +42,33 @@ namespace llarp
uint64_t whoaskedTX, const Key_t& askpeer,
RouterLookupHandler result = nullptr) = 0;
/// on behalf of whoasked request introset for target from dht router with
/// key askpeer
/// Ask a Service Node to perform an Introset lookup for us
virtual void
LookupIntroSetRecursive(const service::Address& target,
const Key_t& whoasked, uint64_t whoaskedTX,
const Key_t& askpeer, uint64_t R,
service::IntroSetLookupHandler result =
service::IntroSetLookupHandler()) = 0;
LookupIntroSetRelayed(const Key_t& target, const Key_t& whoasked,
uint64_t whoaskedTX, const Key_t& askpeer,
uint64_t relayOrder,
service::EncryptedIntroSetLookupHandler result =
service::EncryptedIntroSetLookupHandler()) = 0;
/// Directly as a Service Node for an Introset
virtual void
LookupIntroSetIterative(const service::Address& target,
const Key_t& whoasked, uint64_t whoaskedTX,
const Key_t& askpeer,
service::IntroSetLookupHandler result =
service::IntroSetLookupHandler()) = 0;
virtual std::set< service::IntroSet >
FindRandomIntroSetsWithTagExcluding(
const service::Tag& tag, size_t max = 2,
const std::set< service::IntroSet >& excludes = {}) = 0;
LookupIntroSetDirect(const Key_t& target, const Key_t& whoasked,
uint64_t whoaskedTX, const Key_t& askpeer,
service::EncryptedIntroSetLookupHandler result =
service::EncryptedIntroSetLookupHandler()) = 0;
virtual bool
HasRouterLookup(const RouterID& target) const = 0;
/// on behalf of whoasked request introsets with tag from dht router with
/// key askpeer with Recursion depth R
virtual void
LookupTagRecursive(const service::Tag& tag, const Key_t& whoasked,
uint64_t whoaskedTX, const Key_t& askpeer,
uint64_t R) = 0;
/// issue dht lookup for tag via askpeer and send reply to local path
virtual void
LookupTagForPath(const service::Tag& tag, uint64_t txid,
const PathID_t& path, const Key_t& askpeer) = 0;
/// issue dht lookup for router via askpeer and send reply to local path
virtual void
LookupRouterForPath(const RouterID& target, uint64_t txid,
const PathID_t& path, const Key_t& askpeer) = 0;
virtual void
LookupIntroSetForPath(const service::Address& addr, uint64_t txid,
const PathID_t& path, const Key_t& askpeer) = 0;
LookupIntroSetForPath(const Key_t& addr, uint64_t txid,
const PathID_t& path, const Key_t& askpeer,
uint64_t relayOrder) = 0;
virtual void
DHTSendTo(const RouterID& peer, IMessage* msg, bool keepalive = true) = 0;
@ -112,16 +92,16 @@ namespace llarp
/// send introset to peer from source with S counter and excluding peers
virtual void
PropagateIntroSetTo(const Key_t& source, uint64_t sourceTX,
const service::IntroSet& introset, const Key_t& peer,
uint64_t S, const std::set< Key_t >& exclude) = 0;
const service::EncryptedIntroSet& introset,
const Key_t& peer, bool relayed,
uint64_t relayOrder) = 0;
virtual void
Init(const Key_t& us, AbstractRouter* router,
llarp_time_t exploreInterval) = 0;
virtual const llarp::service::IntroSet*
GetIntroSetByServiceAddress(
const llarp::service::Address& addr) const = 0;
virtual nonstd::optional< llarp::service::EncryptedIntroSet >
GetIntroSetByLocation(const Key_t& location) const = 0;
virtual llarp_time_t
Now() const = 0;
@ -144,12 +124,6 @@ namespace llarp
virtual const PendingIntrosetLookups&
pendingIntrosetLookups() const = 0;
virtual PendingTagLookups&
pendingTagLookups() = 0;
virtual const PendingTagLookups&
pendingTagLookups() const = 0;
virtual PendingRouterLookups&
pendingRouterLookups() = 0;
@ -184,6 +158,10 @@ namespace llarp
virtual void
StoreRC(const RouterContact rc) const = 0;
/// flood rc to all peers later in a batch
virtual void
FloodRCLater(const dht::Key_t from, const RouterContact rc) = 0;
};
std::unique_ptr< AbstractContext >

@ -4,6 +4,8 @@
#include <dht/messages/findrouter.hpp>
#include <router/abstractrouter.hpp>
#include <nodedb.hpp>
namespace llarp
{
namespace dht
@ -24,6 +26,8 @@ namespace llarp
for(const auto &pk : valuesFound)
{
// lookup router
if(router and router->nodedb()->Has(pk))
continue;
parent->LookupRouter(
pk,
std::bind(&AbstractRouter::HandleDHTLookupForExplore, router, pk,

@ -1 +0,0 @@
#include <dht/kademlia.hpp>

@ -2,6 +2,7 @@
#define LLARP_DHT_KADEMLIA_HPP
#include <dht/key.hpp>
#include <router_contact.hpp>
namespace llarp
{
@ -20,6 +21,12 @@ namespace llarp
{
return (us ^ left) < (us ^ right);
}
bool
operator()(const RouterContact& left, const RouterContact& right) const
{
return (left.pubkey ^ us) < (right.pubkey ^ us);
}
};
} // namespace dht
} // namespace llarp

@ -1 +0,0 @@
#include <dht/key.hpp>

@ -12,10 +12,11 @@ namespace llarp
namespace dht
{
LocalServiceAddressLookup::LocalServiceAddressLookup(
const PathID_t &pathid, uint64_t txid, const service::Address &addr,
AbstractContext *ctx, __attribute__((unused)) const Key_t &askpeer)
: ServiceAddressLookup(TXOwner{ctx->OurKey(), txid}, addr, ctx, 5,
nullptr)
const PathID_t &pathid, uint64_t txid, uint64_t relayOrder,
const Key_t &addr, AbstractContext *ctx,
__attribute__((unused)) const Key_t &askpeer)
: ServiceAddressLookup(TXOwner{ctx->OurKey(), txid}, addr, ctx,
relayOrder, nullptr)
, localPath(pathid)
{
}
@ -36,7 +37,7 @@ namespace llarp
// pick newest if we have more than 1 result
if(valuesFound.size())
{
service::IntroSet found;
service::EncryptedIntroSet found;
for(const auto &introset : valuesFound)
{
if(found.OtherIsNewer(introset))

@ -14,7 +14,7 @@ namespace llarp
PathID_t localPath;
LocalServiceAddressLookup(const PathID_t &pathid, uint64_t txid,
const service::Address &addr,
uint64_t relayOrder, const Key_t &addr,
AbstractContext *ctx,
__attribute__((unused)) const Key_t &askpeer);

@ -47,7 +47,7 @@ namespace llarp
switch(*strbuf.base)
{
case 'F':
msg = std::make_unique< FindIntroMessage >(From, relayed);
msg = std::make_unique< FindIntroMessage >(From, relayed, 0);
break;
case 'R':
if(relayed)

@ -0,0 +1,28 @@
#ifndef LLARP_DHT_MESSAGES_CONSENSUS_HPP
#define LLARP_DHT_MESSAGES_CONSENSUS_HPP
#include <dht/message.hpp>
#include <router_version.hpp>
namespace llarp
{
namespace dht
{
struct ConsensusMessage
{
/// H
ShortHash m_Hash;
/// K
std::vector< RouterID > m_Keys;
/// N
uint64_t m_NumberOfEntries;
/// O
uint64_t m_EntryOffset;
/// T
uint64_t m_TxID;
/// U
llarp_time_t m_NextUpdateRequired;
/// V
RouterVersion m_RotuerVersion;
};
} // namespace dht
} // namespace llarp

@ -2,6 +2,8 @@
#include <dht/messages/findintro.hpp>
#include <dht/messages/gotintro.hpp>
#include <routing/message.hpp>
#include <router/abstractrouter.hpp>
#include <nodedb.hpp>
namespace llarp
{
@ -14,16 +16,16 @@ namespace llarp
{
bool read = false;
if(!BEncodeMaybeReadDictEntry("N", N, read, k, val))
if(!BEncodeMaybeReadDictEntry("N", tagName, read, k, val))
return false;
if(!BEncodeMaybeReadDictInt("R", R, read, k, val))
if(!BEncodeMaybeReadDictInt("O", relayOrder, read, k, val))
return false;
if(!BEncodeMaybeReadDictEntry("S", S, read, k, val))
if(!BEncodeMaybeReadDictEntry("S", location, read, k, val))
return false;
if(!BEncodeMaybeReadDictInt("T", T, read, k, val))
if(!BEncodeMaybeReadDictInt("T", txID, read, k, val))
return false;
if(!BEncodeMaybeVerifyVersion("V", version, LLARP_PROTO_VERSION, read, k,
@ -42,25 +44,27 @@ namespace llarp
// message id
if(!BEncodeWriteDictMsgType(buf, "A", "F"))
return false;
if(N.Empty())
if(tagName.Empty())
{
// recursion
if(!BEncodeWriteDictInt("R", R, buf))
// relay order
if(!BEncodeWriteDictInt("O", relayOrder, buf))
return false;
// service address
if(!BEncodeWriteDictEntry("S", S, buf))
if(!BEncodeWriteDictEntry("S", location, buf))
return false;
}
else
{
if(!BEncodeWriteDictEntry("N", N, buf))
if(!BEncodeWriteDictEntry("N", tagName, buf))
return false;
// recursion
if(!BEncodeWriteDictInt("R", R, buf))
// relay order
if(!BEncodeWriteDictInt("O", relayOrder, buf))
return false;
}
// txid
if(!BEncodeWriteDictInt("T", T, buf))
if(!BEncodeWriteDictInt("T", txID, buf))
return false;
// protocol version
if(!BEncodeWriteDictInt("V", LLARP_PROTO_VERSION, buf))
@ -73,121 +77,71 @@ namespace llarp
FindIntroMessage::HandleMessage(
llarp_dht_context* ctx, std::vector< IMessage::Ptr_t >& replies) const
{
if(R > 5)
{
llarp::LogError("R value too big, ", R, "> 5");
return false;
}
auto& dht = *ctx->impl;
if(dht.pendingIntrosetLookups().HasPendingLookupFrom(TXOwner{From, T}))
if(dht.pendingIntrosetLookups().HasPendingLookupFrom(TXOwner{From, txID}))
{
llarp::LogWarn("duplicate FIM from ", From, " txid=", T);
llarp::LogWarn("duplicate FIM from ", From, " txid=", txID);
return false;
}
Key_t peer;
std::set< Key_t > exclude = {dht.OurKey(), From};
if(N.Empty())
{
llarp::LogInfo("lookup ", S.ToString());
const auto introset = dht.GetIntroSetByServiceAddress(S);
if(introset)
{
service::IntroSet i = *introset;
replies.emplace_back(new GotIntroMessage({i}, T));
return true;
}
if(R == 0)
{
// we don't have it
Key_t target = S.ToKey();
Key_t closer;
// find closer peer
if(!dht.Nodes()->FindClosest(target, closer))
return false;
if(relayed)
dht.LookupIntroSetForPath(S, T, pathID, closer);
else
replies.emplace_back(new GotIntroMessage(From, closer, T));
return true;
}
Key_t us = dht.OurKey();
Key_t target = S.ToKey();
// we are recursive
if(dht.Nodes()->FindCloseExcluding(target, peer, exclude))
{
if(relayed)
dht.LookupIntroSetForPath(S, T, pathID, peer);
else
{
if((us ^ target) < (peer ^ target))
{
// we are not closer than our peer to the target so don't
// recurse farther
replies.emplace_back(new GotIntroMessage({}, T));
return true;
}
if(R > 0)
dht.LookupIntroSetRecursive(S, From, T, peer, R - 1);
else
dht.LookupIntroSetIterative(S, From, T, peer);
}
return true;
}
if(not tagName.Empty())
return false;
// no more closer peers
replies.emplace_back(new GotIntroMessage({}, T));
// bad request (request for zero-key)
if(location.IsZero())
{
// we dont got it
replies.emplace_back(new GotIntroMessage({}, txID));
return true;
}
// we are relaying this message for e.g. a client
if(relayed)
{
// tag lookup
if(dht.Nodes()->GetRandomNodeExcluding(peer, exclude))
uint32_t numDesired = 0;
if(relayOrder == 0)
numDesired = 2;
else if(relayOrder == 1)
numDesired = 4;
else
{
dht.LookupTagForPath(N, T, pathID, peer);
// TODO: consider forward-compatibility here
LogError("Error: relayOrder must be 0 or 1");
return false;
}
else
auto closestRCs =
dht.GetRouter()->nodedb()->FindClosestTo(location, numDesired);
// if relayOrder == 1, we want the 3rd and 4th closest, so remove the
// 1st and 2nd closest
if(relayOrder == 1)
{
// no more closer peers
replies.emplace_back(new GotIntroMessage({}, T));
return true;
auto itr = closestRCs.begin();
std::advance(itr, 2);
closestRCs.erase(closestRCs.begin(), itr);
}
for(const auto& entry : closestRCs)
{
Key_t peer = Key_t(entry.pubkey);
dht.LookupIntroSetForPath(location, txID, pathID, peer, 0);
}
}
else
{
if(R == 0)
// we should have this value if introset was propagated properly
const auto maybe = dht.GetIntroSetByLocation(location);
if(maybe.has_value())
{
// base case
auto introsets = dht.FindRandomIntroSetsWithTagExcluding(N, 2, {});
std::vector< service::IntroSet > reply;
for(const auto& introset : introsets)
{
reply.push_back(introset);
}
replies.emplace_back(new GotIntroMessage(reply, T));
return true;
}
if(R < 5)
{
// tag lookup
if(dht.Nodes()->GetRandomNodeExcluding(peer, exclude))
{
dht.LookupTagRecursive(N, From, T, peer, R - 1);
}
else
{
replies.emplace_back(new GotIntroMessage({}, T));
}
replies.emplace_back(new GotIntroMessage({maybe.value()}, txID));
}
else
{
// too big R value
replies.emplace_back(new GotIntroMessage({}, T));
LogWarn("Got FIM with relayed == false and we don't have entry");
replies.emplace_back(new GotIntroMessage({}, txID));
}
}
return true;
}
} // namespace dht

@ -12,37 +12,29 @@ namespace llarp
{
struct FindIntroMessage final : public IMessage
{
uint64_t R = 0;
llarp::service::Address S;
llarp::service::Tag N;
uint64_t T = 0;
bool relayed = false;
FindIntroMessage(const Key_t& from, bool relay) : IMessage(from)
Key_t location;
llarp::service::Tag tagName;
uint64_t txID = 0;
bool relayed = false;
uint64_t relayOrder = 0;
FindIntroMessage(const Key_t& from, bool relay, uint64_t order)
: IMessage(from)
{
relayed = relay;
relayed = relay;
relayOrder = order;
}
FindIntroMessage(const llarp::service::Tag& tag, uint64_t txid,
bool iterate = true)
: IMessage({}), N(tag), T(txid)
FindIntroMessage(const llarp::service::Tag& tag, uint64_t txid)
: IMessage({}), tagName(tag), txID(txid)
{
S.Zero();
if(iterate)
R = 0;
else
R = 1;
}
FindIntroMessage(uint64_t txid, const llarp::service::Address& addr,
bool iterate = true)
: IMessage({}), S(addr), T(txid)
explicit FindIntroMessage(uint64_t txid, const Key_t& addr,
uint64_t order)
: IMessage({}), location(addr), txID(txid), relayOrder(order)
{
N.Zero();
if(iterate)
R = 0;
else
R = 1;
tagName.Zero();
}
~FindIntroMessage() override;

@ -18,11 +18,12 @@ namespace llarp
{
auto &dht = *ctx->impl;
/// lookup for us, send an immeidate reply
Key_t us = dht.OurKey();
Key_t k{K};
if(K == us)
const Key_t us = dht.OurKey();
const Key_t k{targetKey};
if(k == us)
{
auto path = dht.GetRouter()->pathContext().GetByUpstream(K, pathID);
auto path =
dht.GetRouter()->pathContext().GetByUpstream(targetKey, pathID);
if(path)
{
replies.emplace_back(
@ -34,26 +35,22 @@ namespace llarp
Key_t peer;
// check if we know this in our nodedb first
RouterContact found;
if(!dht.GetRouter()->ConnectionToRouterAllowed(K))
if(not dht.GetRouter()->ConnectionToRouterAllowed(targetKey))
{
// explicitly disallowed by network
replies.emplace_back(new GotRouterMessage(k, txid, {}, false));
return true;
}
if(dht.GetRouter()->nodedb()->Get(K, found))
// check netdb
const auto rc = dht.GetRouter()->nodedb()->FindClosestTo(k);
if(rc.pubkey == targetKey)
{
replies.emplace_back(new GotRouterMessage(k, txid, {found}, false));
return true;
}
if((!dht.Nodes()->FindClosest(k, peer)) || peer == us)
{
// can't find any peers closer
replies.emplace_back(new GotRouterMessage(k, txid, {}, false));
replies.emplace_back(new GotRouterMessage(k, txid, {rc}, false));
return true;
}
peer = Key_t(rc.pubkey);
// lookup if we don't have it in our nodedb
dht.LookupRouterForPath(K, txid, pathID, peer);
dht.LookupRouterForPath(targetKey, txid, pathID, peer);
return true;
}
@ -86,7 +83,7 @@ namespace llarp
// key
if(!bencode_write_bytestring(buf, "K", 1))
return false;
if(!bencode_write_bytestring(buf, K.data(), K.size()))
if(!bencode_write_bytestring(buf, targetKey.data(), targetKey.size()))
return false;
// txid
@ -132,10 +129,10 @@ namespace llarp
{
if(!bencode_read_string(val, &strbuf))
return false;
if(strbuf.sz != K.size())
if(strbuf.sz != targetKey.size())
return false;
std::copy(strbuf.base, strbuf.base + K.SIZE, K.begin());
std::copy(strbuf.base, strbuf.base + targetKey.SIZE, targetKey.begin());
return true;
}
if(key == "T")
@ -167,26 +164,15 @@ namespace llarp
return false;
}
RouterContact found;
if(K.IsZero())
if(targetKey.IsZero())
{
llarp::LogError("invalid FRM from ", From, "K is zero");
llarp::LogError("invalid FRM from ", From, " key is zero");
return false;
}
const Key_t k(K);
const Key_t k(targetKey);
if(exploritory)
return dht.HandleExploritoryRouterLookup(From, txid, K, replies);
if(!dht.GetRouter()->ConnectionToRouterAllowed(K))
{
// explicitly disallowed by network
replies.emplace_back(new GotRouterMessage(k, txid, {}, false));
return true;
}
if(dht.GetRCFromNodeDB(k, found))
{
replies.emplace_back(new GotRouterMessage(k, txid, {found}, false));
return true;
}
return dht.HandleExploritoryRouterLookup(From, txid, targetKey,
replies);
dht.LookupRouterRelayed(From, txid, k, !iterative, replies);
return true;
}

@ -15,14 +15,14 @@ namespace llarp
// find by routerid
FindRouterMessage(uint64_t id, const RouterID& target)
: IMessage({}), K(target), txid(id)
: IMessage({}), targetKey(target), txid(id)
{
}
// exploritory
FindRouterMessage(uint64_t id) : IMessage({}), exploritory(true), txid(id)
{
K.Randomize();
targetKey.Randomize();
}
~FindRouterMessage() override;
@ -38,7 +38,7 @@ namespace llarp
llarp_dht_context* ctx,
std::vector< std::unique_ptr< IMessage > >& replies) const override;
RouterID K;
RouterID targetKey;
bool iterative = false;
bool exploritory = false;
uint64_t txid = 0;

@ -11,21 +11,20 @@ namespace llarp
{
namespace dht
{
GotIntroMessage::GotIntroMessage(std::vector< service::IntroSet > results,
uint64_t tx)
: IMessage({}), I(std::move(results)), T(tx)
GotIntroMessage::GotIntroMessage(
std::vector< service::EncryptedIntroSet > results, uint64_t tx)
: IMessage({}), found(std::move(results)), txid(tx)
{
}
bool
GotIntroMessage::HandleMessage(
llarp_dht_context *ctx,
ABSL_ATTRIBUTE_UNUSED std::vector< std::unique_ptr< IMessage > >
&replies) const
std::vector< std::unique_ptr< IMessage > > & /*replies*/) const
{
auto &dht = *ctx->impl;
for(const auto &introset : I)
for(const auto &introset : found)
{
if(!introset.Verify(dht.Now()))
{
@ -36,28 +35,24 @@ namespace llarp
return false;
}
}
TXOwner owner(From, T);
auto tagLookup = dht.pendingTagLookups().GetPendingLookupFrom(owner);
if(tagLookup)
{
dht.pendingTagLookups().Found(owner, tagLookup->target, I);
return true;
}
TXOwner owner(From, txid);
auto serviceLookup =
dht.pendingIntrosetLookups().GetPendingLookupFrom(owner);
if(serviceLookup)
{
if(I.size())
if(not found.empty())
{
dht.pendingIntrosetLookups().Found(owner, serviceLookup->target, I);
dht.pendingIntrosetLookups().Found(owner, serviceLookup->target,
found);
}
else
{
dht.pendingIntrosetLookups().NotFound(owner, K);
dht.pendingIntrosetLookups().NotFound(owner, nullptr);
}
return true;
}
LogError("no pending TX for GIM from ", From, " txid=", T);
LogError("no pending TX for GIM from ", From, " txid=", txid);
return false;
}
@ -84,17 +79,20 @@ namespace llarp
{
if(key == "I")
{
return BEncodeReadList(I, buf);
return BEncodeReadList(found, buf);
}
if(key == "K")
{
if(K) // duplicate key?
if(closer.has_value()) // duplicate key?
return false;
dht::Key_t K;
if(not K.BDecode(buf))
return false;
K = std::make_unique< dht::Key_t >();
return K->BDecode(buf);
closer = K;
return true;
}
bool read = false;
if(!BEncodeMaybeReadDictInt("T", T, read, key, buf))
if(!BEncodeMaybeReadDictInt("T", txid, read, key, buf))
return false;
if(!BEncodeMaybeReadDictInt("V", version, read, key, buf))
return false;
@ -108,14 +106,14 @@ namespace llarp
return false;
if(!BEncodeWriteDictMsgType(buf, "A", "G"))
return false;
if(!BEncodeWriteDictList("I", I, buf))
if(!BEncodeWriteDictList("I", found, buf))
return false;
if(K)
if(closer.has_value())
{
if(!BEncodeWriteDictEntry("K", *K.get(), buf))
if(!BEncodeWriteDictEntry("K", closer.value(), buf))
return false;
}
if(!BEncodeWriteDictInt("T", T, buf))
if(!BEncodeWriteDictInt("T", txid, buf))
return false;
if(!BEncodeWriteDictInt("V", version, buf))
return false;

@ -6,6 +6,7 @@
#include <util/copy_or_nullptr.hpp>
#include <vector>
#include <nonstd/optional.hpp>
namespace llarp
{
@ -15,11 +16,11 @@ namespace llarp
struct GotIntroMessage : public IMessage
{
/// the found introsets
std::vector< service::IntroSet > I;
std::vector< service::EncryptedIntroSet > found;
/// txid
uint64_t T = 0;
uint64_t txid = 0;
/// the key of a router closer in keyspace if iterative lookup
std::unique_ptr< Key_t > K;
nonstd::optional< Key_t > closer;
GotIntroMessage(const Key_t& from) : IMessage(from)
{
@ -27,21 +28,22 @@ namespace llarp
GotIntroMessage(const GotIntroMessage& other)
: IMessage(other.From)
, I(other.I)
, T(other.T)
, K(copy_or_nullptr(other.K))
, found(other.found)
, txid(other.txid)
, closer(other.closer)
{
version = other.version;
}
/// for iterative reply
GotIntroMessage(const Key_t& from, const Key_t& closer, uint64_t txid)
: IMessage(from), T(txid), K(new Key_t(closer))
GotIntroMessage(const Key_t& from, const Key_t& _closer, uint64_t _txid)
: IMessage(from), txid(_txid), closer(_closer)
{
}
/// for recursive reply
GotIntroMessage(std::vector< service::IntroSet > results, uint64_t txid);
GotIntroMessage(std::vector< service::EncryptedIntroSet > results,
uint64_t txid);
~GotIntroMessage() override = default;

@ -15,35 +15,35 @@ namespace llarp
bool
GotRouterMessage::BEncode(llarp_buffer_t *buf) const
{
if(!bencode_start_dict(buf))
if(not bencode_start_dict(buf))
return false;
// message type
if(!BEncodeWriteDictMsgType(buf, "A", "S"))
if(not BEncodeWriteDictMsgType(buf, "A", "S"))
return false;
if(K)
if(closerTarget)
{
if(!BEncodeWriteDictEntry("K", *K.get(), buf))
if(not BEncodeWriteDictEntry("K", *closerTarget, buf))
return false;
}
// near
if(N.size())
if(not nearKeys.empty())
{
if(!BEncodeWriteDictList("N", N, buf))
if(not BEncodeWriteDictList("N", nearKeys, buf))
return false;
}
if(!BEncodeWriteDictList("R", R, buf))
if(not BEncodeWriteDictList("R", foundRCs, buf))
return false;
// txid
if(!BEncodeWriteDictInt("T", txid, buf))
if(not BEncodeWriteDictInt("T", txid, buf))
return false;
// version
if(!BEncodeWriteDictInt("V", version, buf))
if(not BEncodeWriteDictInt("V", version, buf))
return false;
return bencode_end(buf);
@ -54,18 +54,18 @@ namespace llarp
{
if(key == "K")
{
if(K) // duplicate key?
if(closerTarget) // duplicate key?
return false;
K = std::make_unique< dht::Key_t >();
return K->BDecode(val);
closerTarget = std::make_unique< dht::Key_t >();
return closerTarget->BDecode(val);
}
if(key == "N")
{
return BEncodeReadList(N, val);
return BEncodeReadList(nearKeys, val);
}
if(key == "R")
{
return BEncodeReadList(R, val);
return BEncodeReadList(foundRCs, val);
}
if(key == "T")
{
@ -98,32 +98,36 @@ namespace llarp
if(dht.pendingExploreLookups().HasPendingLookupFrom(owner))
{
LogDebug("got ", N.size(), " results in GRM for explore");
if(N.size() == 0)
dht.pendingExploreLookups().NotFound(owner, K);
LogDebug("got ", nearKeys.size(), " results in GRM for explore");
if(nearKeys.empty())
dht.pendingExploreLookups().NotFound(owner, closerTarget);
else
{
dht.pendingExploreLookups().Found(owner, From.as_array(), N);
dht.pendingExploreLookups().Found(owner, From.as_array(), nearKeys);
}
return true;
}
// not explore lookup
if(dht.pendingRouterLookups().HasPendingLookupFrom(owner))
{
LogDebug("got ", R.size(), " results in GRM for lookup");
if(R.size() == 0)
dht.pendingRouterLookups().NotFound(owner, K);
else if(R[0].pubkey.IsZero())
LogDebug("got ", foundRCs.size(), " results in GRM for lookup");
if(foundRCs.empty())
dht.pendingRouterLookups().NotFound(owner, closerTarget);
else if(foundRCs[0].pubkey.IsZero())
return false;
else
dht.pendingRouterLookups().Found(owner, R[0].pubkey, R);
dht.pendingRouterLookups().Found(owner, foundRCs[0].pubkey, foundRCs);
return true;
}
// store if valid
for(const auto &rc : R)
for(const auto &rc : foundRCs)
{
if(not dht.GetRouter()->rcLookupHandler().CheckRC(rc))
return false;
if(txid == 0)
{
dht.GetRouter()->GossipRCIfNeeded(rc);
}
}
return true;
}

@ -1,6 +1,6 @@
#ifndef LLARP_DHT_MESSAGES_GOT_ROUTER_HPP
#define LLARP_DHT_MESSAGES_GOT_ROUTER_HPP
#include <constants/proto.hpp>
#include <dht/message.hpp>
#include <router_contact.hpp>
#include <util/copy_or_nullptr.hpp>
@ -20,27 +20,40 @@ namespace llarp
GotRouterMessage(const Key_t& from, uint64_t id,
const std::vector< RouterContact >& results,
bool tunneled)
: IMessage(from), R(results), txid(id), relayed(tunneled)
: IMessage(from), foundRCs(results), txid(id), relayed(tunneled)
{
}
GotRouterMessage(const Key_t& from, const Key_t& closer, uint64_t id,
bool tunneled)
: IMessage(from), K(new Key_t(closer)), txid(id), relayed(tunneled)
: IMessage(from)
, closerTarget(new Key_t(closer))
, txid(id)
, relayed(tunneled)
{
}
GotRouterMessage(uint64_t id, std::vector< RouterID > _near,
bool tunneled)
: IMessage({}), N(std::move(_near)), txid(id), relayed(tunneled)
: IMessage({})
, nearKeys(std::move(_near))
, txid(id)
, relayed(tunneled)
{
}
/// gossip message
GotRouterMessage(const RouterContact rc)
: IMessage({}), foundRCs({rc}), txid(0)
{
version = LLARP_PROTO_VERSION;
}
GotRouterMessage(const GotRouterMessage& other)
: IMessage(other.From)
, R(other.R)
, N(other.N)
, K(copy_or_nullptr(other.K))
, foundRCs(other.foundRCs)
, nearKeys(other.nearKeys)
, closerTarget(copy_or_nullptr(other.closerTarget))
, txid(other.txid)
, relayed(other.relayed)
{
@ -60,9 +73,9 @@ namespace llarp
llarp_dht_context* ctx,
std::vector< std::unique_ptr< IMessage > >& replies) const override;
std::vector< RouterContact > R;
std::vector< RouterID > N;
std::unique_ptr< Key_t > K;
std::vector< RouterContact > foundRCs;
std::vector< RouterID > nearKeys;
std::unique_ptr< Key_t > closerTarget;
uint64_t txid = 0;
bool relayed = false;
};

@ -5,33 +5,27 @@
#include <messages/dht_immediate.hpp>
#include <router/abstractrouter.hpp>
#include <routing/dht_message.hpp>
#include <nodedb.hpp>
namespace llarp
{
namespace dht
{
PublishIntroMessage::~PublishIntroMessage() = default;
const uint64_t PublishIntroMessage::MaxPropagationDepth = 5;
PublishIntroMessage::~PublishIntroMessage() = default;
bool
PublishIntroMessage::DecodeKey(const llarp_buffer_t &key,
llarp_buffer_t *val)
{
bool read = false;
if(key == "E")
{
return BEncodeReadList(E, val);
}
if(!BEncodeMaybeReadDictEntry("I", I, read, key, val))
if(!BEncodeMaybeReadDictEntry("I", introset, read, key, val))
return false;
if(!BEncodeMaybeReadDictInt("R", R, read, key, val))
if(!BEncodeMaybeReadDictInt("O", relayOrder, read, key, val))
return false;
uint64_t relayedInt = (relayed ? 1 : 0);
if(!BEncodeMaybeReadDictInt("R", relayedInt, read, key, val))
return false;
if(key == "S")
{
read = true;
hasS = true;
if(!bencode_read_integer(val, &S))
return false;
}
if(!BEncodeMaybeReadDictInt("T", txID, read, key, val))
return false;
if(!BEncodeMaybeReadDictInt("V", version, read, key, val))
@ -45,54 +39,102 @@ namespace llarp
std::vector< std::unique_ptr< IMessage > > &replies) const
{
auto now = ctx->impl->Now();
if(S > 5)
{
llarp::LogWarn("invalid S value ", S, " > 5");
return false;
}
auto &dht = *ctx->impl;
if(!I.Verify(now))
if(!introset.Verify(now))
{
llarp::LogWarn("invalid introset: ", I);
llarp::LogWarn("Received PublishIntroMessage with invalid introset: ",
introset);
// don't propogate or store
replies.emplace_back(new GotIntroMessage({}, txID));
return true;
}
if(I.W && !I.W->IsValid(now))
if(introset.IsExpired(now + llarp::service::MAX_INTROSET_TIME_DELTA))
{
llarp::LogWarn("proof of work not good enough for IntroSet");
// don't propogate or store
llarp::LogWarn("Received PublishIntroMessage with expired Introset: ",
introset);
replies.emplace_back(new GotIntroMessage({}, txID));
return true;
}
llarp::dht::Key_t addr;
if(!I.A.CalculateAddress(addr.as_array()))
{
llarp::LogWarn(
"failed to calculate hidden service address for PubIntro message");
return false;
}
now += llarp::service::MAX_INTROSET_TIME_DELTA;
if(I.IsExpired(now))
const llarp::dht::Key_t addr(introset.derivedSigningKey);
// identify closest 4 routers
auto closestRCs = dht.GetRouter()->nodedb()->FindClosestTo(addr, 4);
if(closestRCs.size() != 4)
{
// don't propogate or store
llarp::LogWarn("Received PublishIntroMessage but only know ",
closestRCs.size(), " nodes");
replies.emplace_back(new GotIntroMessage({}, txID));
return true;
}
dht.services()->PutNode(I);
replies.emplace_back(new GotIntroMessage({I}, txID));
Key_t peer;
std::set< Key_t > exclude;
for(const auto &e : E)
exclude.insert(e);
exclude.insert(From);
exclude.insert(dht.OurKey());
if(S && dht.Nodes()->FindCloseExcluding(addr, peer, exclude))
const auto &us = dht.OurKey();
// function to identify the closest 4 routers we know of for this introset
auto propagateToClosestFour = [&]() {
// grab 1st & 2nd if we are relayOrder == 0, 3rd & 4th otherwise
const auto &rc0 = (relayOrder == 0 ? closestRCs[0] : closestRCs[2]);
const auto &rc1 = (relayOrder == 0 ? closestRCs[1] : closestRCs[3]);
const Key_t peer0{rc0.pubkey};
const Key_t peer1{rc1.pubkey};
bool arePeer0 = (peer0 == us);
bool arePeer1 = (peer1 == us);
if(arePeer0 or arePeer1)
{
dht.services()->PutNode(introset);
replies.emplace_back(new GotIntroMessage({introset}, txID));
}
if(not arePeer0)
dht.PropagateIntroSetTo(From, txID, introset, peer0, false, 0);
if(not arePeer1)
dht.PropagateIntroSetTo(From, txID, introset, peer1, false, 0);
};
if(relayed)
{
dht.PropagateIntroSetTo(From, txID, I, peer, S - 1, exclude);
if(relayOrder > 1)
{
llarp::LogWarn(
"Received PublishIntroMessage with invalid relayOrder: ",
relayOrder);
replies.emplace_back(new GotIntroMessage({}, txID));
return true;
}
propagateToClosestFour();
}
else
{
bool found = false;
for(const auto &rc : closestRCs)
{
if(rc.pubkey == dht.OurKey())
{
found = true;
break;
}
}
if(found)
{
dht.services()->PutNode(introset);
replies.emplace_back(new GotIntroMessage({introset}, txID));
}
else
{
// TODO: ensure this can't create a loop (reintroduce depth?)
propagateToClosestFour();
}
}
return true;
}
@ -103,13 +145,11 @@ namespace llarp
return false;
if(!BEncodeWriteDictMsgType(buf, "A", "I"))
return false;
if(!BEncodeWriteDictList("E", E, buf))
return false;
if(!BEncodeWriteDictEntry("I", I, buf))
if(!BEncodeWriteDictEntry("I", introset, buf))
return false;
if(!BEncodeWriteDictInt("R", R, buf))
if(!BEncodeWriteDictInt("O", relayOrder, buf))
return false;
if(!BEncodeWriteDictInt("S", S, buf))
if(!BEncodeWriteDictInt("R", relayed, buf))
return false;
if(!BEncodeWriteDictInt("T", txID, buf))
return false;

@ -12,22 +12,23 @@ namespace llarp
{
struct PublishIntroMessage final : public IMessage
{
llarp::service::IntroSet I;
std::vector< Key_t > E;
uint64_t R = 0;
uint64_t S = 0;
uint64_t txID = 0;
bool hasS = false;
static const uint64_t MaxPropagationDepth;
llarp::service::EncryptedIntroSet introset;
bool relayed = false;
uint64_t relayOrder = 0;
uint64_t txID = 0;
PublishIntroMessage() : IMessage({})
{
}
PublishIntroMessage(const llarp::service::IntroSet& i, uint64_t tx,
uint64_t s, std::vector< Key_t > exclude = {})
: IMessage({}), E(std::move(exclude)), txID(tx)
PublishIntroMessage(const llarp::service::EncryptedIntroSet& introset_,
uint64_t tx, bool relayed_, uint64_t relayOrder_)
: IMessage({})
, introset(introset_)
, relayed(relayed_)
, relayOrder(relayOrder_)
, txID(tx)
{
I = i;
S = s;
}
~PublishIntroMessage() override;

@ -1 +0,0 @@
#include <dht/node.hpp>

@ -39,7 +39,7 @@ namespace llarp
struct ISNode
{
service::IntroSet introset;
service::EncryptedIntroSet introset;
Key_t ID;
@ -48,9 +48,9 @@ namespace llarp
ID.Zero();
}
ISNode(service::IntroSet other) : introset(std::move(other))
ISNode(service::EncryptedIntroSet other) : introset(std::move(other))
{
introset.A.CalculateAddress(ID.as_array());
ID = Key_t(introset.derivedSigningKey.as_array());
}
util::StatusObject
@ -62,7 +62,7 @@ namespace llarp
bool
operator<(const ISNode& other) const
{
return introset.T < other.introset.T;
return introset.signedAt < other.introset.signedAt;
}
};
} // namespace dht

@ -8,40 +8,36 @@ namespace llarp
{
namespace dht
{
PublishServiceJob::PublishServiceJob(const TXOwner &asker,
const service::IntroSet &introset,
AbstractContext *ctx, uint64_t s,
std::set< Key_t > exclude)
: TX< service::Address, service::IntroSet >(asker, introset.A.Addr(),
ctx)
, S(s)
, dontTell(std::move(exclude))
, I(introset)
PublishServiceJob::PublishServiceJob(
const TXOwner &asker, const service::EncryptedIntroSet &introset_,
AbstractContext *ctx, bool relayed_, uint64_t relayOrder_)
: TX< Key_t, service::EncryptedIntroSet >(
asker, Key_t{introset_.derivedSigningKey}, ctx)
, relayed(relayed_)
, relayOrder(relayOrder_)
, introset(introset_)
{
}
bool
PublishServiceJob::Validate(const service::IntroSet &introset) const
PublishServiceJob::Validate(const service::EncryptedIntroSet &value) const
{
if(I.A != introset.A)
if(value.derivedSigningKey != introset.derivedSigningKey)
{
llarp::LogWarn(
"publish introset acknowledgement acked a different service");
return false;
}
return true;
const llarp_time_t now = llarp::time_now_ms();
return value.Verify(now);
}
void
PublishServiceJob::Start(const TXOwner &peer)
{
std::vector< Key_t > exclude;
for(const auto &router : dontTell)
{
exclude.push_back(router);
}
parent->DHTSendTo(peer.node.as_array(),
new PublishIntroMessage(I, peer.txid, S, exclude));
parent->DHTSendTo(
peer.node.as_array(),
new PublishIntroMessage(introset, peer.txid, relayed, relayOrder));
}
} // namespace dht
} // namespace llarp

@ -12,18 +12,19 @@ namespace llarp
{
namespace dht
{
struct PublishServiceJob : public TX< service::Address, service::IntroSet >
struct PublishServiceJob : public TX< Key_t, service::EncryptedIntroSet >
{
uint64_t S;
std::set< Key_t > dontTell;
service::IntroSet I;
bool relayed;
uint64_t relayOrder;
service::EncryptedIntroSet introset;
PublishServiceJob(const TXOwner &asker, const service::IntroSet &introset,
AbstractContext *ctx, uint64_t s,
std::set< Key_t > exclude);
PublishServiceJob(const TXOwner &asker,
const service::EncryptedIntroSet &introset,
AbstractContext *ctx, bool relayed,
uint64_t relayOrder);
bool
Validate(const service::IntroSet &introset) const override;
Validate(const service::EncryptedIntroSet &introset) const override;
void
Start(const TXOwner &peer) override;

@ -46,7 +46,6 @@ namespace llarp
void
RecursiveRouterLookup::DoNextRequest(const Key_t &peer)
{
peersAsked.emplace(peer);
parent->LookupRouterRecursive(target, whoasked.node, whoasked.txid, peer,
resultHandler);
}
@ -54,7 +53,6 @@ namespace llarp
void
RecursiveRouterLookup::Start(const TXOwner &peer)
{
peersAsked.emplace(peer.node);
parent->DHTSendTo(peer.node.as_array(),
new FindRouterMessage(peer.txid, target));
}
@ -78,7 +76,7 @@ namespace llarp
{
resultHandler(valuesFound);
}
else if(whoasked.node != parent->OurKey())
if(whoasked.node != parent->OurKey())
{
parent->DHTSendTo(
whoasked.node.as_array(),

@ -10,25 +10,25 @@ namespace llarp
namespace dht
{
ServiceAddressLookup::ServiceAddressLookup(
const TXOwner &asker, const service::Address &addr,
AbstractContext *ctx, uint64_t r,
service::IntroSetLookupHandler handler)
: TX< service::Address, service::IntroSet >(asker, addr, ctx)
const TXOwner &asker, const Key_t &addr, AbstractContext *ctx,
uint32_t order, service::EncryptedIntroSetLookupHandler handler)
: TX< Key_t, service::EncryptedIntroSet >(asker, addr, ctx)
, handleResult(std::move(handler))
, R(r)
, relayOrder(order)
{
peersAsked.insert(ctx->OurKey());
}
bool
ServiceAddressLookup::Validate(const service::IntroSet &value) const
ServiceAddressLookup::Validate(
const service::EncryptedIntroSet &value) const
{
if(!value.Verify(parent->Now()))
{
llarp::LogWarn("Got invalid introset from service lookup");
return false;
}
if(value.A.Addr() != target)
if(value.derivedSigningKey != target)
{
llarp::LogWarn("got introset with wrong target from service lookup");
return false;
@ -40,11 +40,10 @@ namespace llarp
ServiceAddressLookup::GetNextPeer(Key_t &next,
const std::set< Key_t > &exclude)
{
Key_t k = target.ToKey();
const auto &nodes = parent->Nodes();
if(nodes)
{
return nodes->FindCloseExcluding(k, next, exclude);
return nodes->FindCloseExcluding(target, next, exclude);
}
return false;
@ -54,22 +53,14 @@ namespace llarp
ServiceAddressLookup::Start(const TXOwner &peer)
{
parent->DHTSendTo(peer.node.as_array(),
new FindIntroMessage(peer.txid, target, R));
new FindIntroMessage(peer.txid, target, relayOrder));
}
void
ServiceAddressLookup::DoNextRequest(const Key_t &ask)
{
if(R)
{
parent->LookupIntroSetRecursive(target, whoasked.node, whoasked.txid,
ask, R - 1);
}
else
{
parent->LookupIntroSetIterative(target, whoasked.node, whoasked.txid,
ask);
}
(void)ask;
// do nothing -- we handle propagating this explicitly
}
void
@ -78,7 +69,7 @@ namespace llarp
// get newest introset
if(valuesFound.size())
{
llarp::service::IntroSet found;
llarp::service::EncryptedIntroSet found;
for(const auto &introset : valuesFound)
{
if(found.OtherIsNewer(introset))

@ -12,18 +12,17 @@ namespace llarp
{
struct TXOwner;
struct ServiceAddressLookup
: public TX< service::Address, service::IntroSet >
struct ServiceAddressLookup : public TX< Key_t, service::EncryptedIntroSet >
{
service::IntroSetLookupHandler handleResult;
uint64_t R;
service::EncryptedIntroSetLookupHandler handleResult;
uint32_t relayOrder;
ServiceAddressLookup(const TXOwner &asker, const service::Address &addr,
AbstractContext *ctx, uint64_t r,
service::IntroSetLookupHandler handler);
ServiceAddressLookup(const TXOwner &asker, const Key_t &addr,
AbstractContext *ctx, uint32_t relayOrder,
service::EncryptedIntroSetLookupHandler handler);
bool
Validate(const service::IntroSet &value) const override;
Validate(const service::EncryptedIntroSet &value) const override;
bool
GetNextPeer(Key_t &next, const std::set< Key_t > &exclude) override;

@ -8,14 +8,16 @@ namespace llarp
namespace dht
{
bool
TagLookup::Validate(const service::IntroSet &introset) const
TagLookup::Validate(const service::EncryptedIntroSet &introset) const
{
if(!introset.Verify(parent->Now()))
{
llarp::LogWarn("got invalid introset from tag lookup");
return false;
}
if(introset.topic != target)
if(not introset.topic.has_value())
return false;
if(introset.topic.value() != target)
{
llarp::LogWarn("got introset with missmatched topic in tag lookup");
return false;
@ -27,26 +29,14 @@ namespace llarp
TagLookup::Start(const TXOwner &peer)
{
parent->DHTSendTo(peer.node.as_array(),
new FindIntroMessage(target, peer.txid, R));
new FindIntroMessage(target, peer.txid));
}
void
TagLookup::SendReply()
{
std::set< service::IntroSet > found(valuesFound.begin(),
valuesFound.end());
// collect our local values if we haven't hit a limit
if(found.size() < 2)
{
auto tags =
parent->FindRandomIntroSetsWithTagExcluding(target, 1, found);
std::copy(tags.begin(), tags.end(), std::inserter(found, found.end()));
}
std::vector< service::IntroSet > values(found.begin(), found.end());
parent->DHTSendTo(whoasked.node.as_array(),
new GotIntroMessage(values, whoasked.txid));
new GotIntroMessage({}, whoasked.txid));
}
} // namespace dht
} // namespace llarp

@ -9,17 +9,18 @@ namespace llarp
{
namespace dht
{
struct TagLookup : public TX< service::Tag, service::IntroSet >
struct TagLookup : public TX< service::Tag, service::EncryptedIntroSet >
{
uint64_t R;
uint64_t recursionDepth;
TagLookup(const TXOwner &asker, const service::Tag &tag,
AbstractContext *ctx, uint64_t r)
: TX< service::Tag, service::IntroSet >(asker, tag, ctx), R(r)
AbstractContext *ctx, uint64_t recursion)
: TX< service::Tag, service::EncryptedIntroSet >(asker, tag, ctx)
, recursionDepth(recursion)
{
}
bool
Validate(const service::IntroSet &introset) const override;
Validate(const service::EncryptedIntroSet &introset) const override;
void
Start(const TXOwner &peer) override;

@ -1 +0,0 @@
#include <dht/tx.hpp>

@ -1 +0,0 @@
#include <dht/txholder.hpp>

@ -131,7 +131,7 @@ namespace llarp
template < typename K, typename V, typename K_Hash >
void
TXHolder< K, V, K_Hash >::NotFound(const TXOwner& from,
const std::unique_ptr< Key_t >& next)
const std::unique_ptr< Key_t >&)
{
auto txitr = tx.find(from);
if(txitr == tx.end())

@ -1 +0,0 @@
#include <dht/txowner.hpp>

@ -1 +0,0 @@
#include <dns/dns.hpp>

@ -1 +0,0 @@
#include <dns/query.hpp>

@ -1 +0,0 @@
#include <dns/string.hpp>

@ -836,6 +836,9 @@ namespace libuv
{
if(m_Run)
{
#ifdef TESTNET_SPEED
ms *= TESTNET_SPEED;
#endif
uv_timer_start(m_TickTimer, &OnTickTimeout, ms, 0);
uv_run(&m_Impl, UV_RUN_ONCE);
}
@ -872,6 +875,9 @@ namespace libuv
Loop::call_after_delay(llarp_time_t delay_ms,
std::function< void(void) > callback)
{
#ifdef TESTNET_SPEED
delay_ms *= TESTNET_SPEED;
#endif
PendingTimer timer;
timer.delay_ms = delay_ms;
timer.callback = callback;

@ -161,7 +161,7 @@ namespace llarp
/// snode sessions we are talking to directly
SNodeSessions_t m_SNodeSessions;
std::unordered_map< huint128_t, PubKey, huint128_t::Hash > m_IPToKey;
std::unordered_map< huint128_t, PubKey > m_IPToKey;
huint128_t m_IfAddr;
huint128_t m_HigestAddr;
@ -169,8 +169,7 @@ namespace llarp
huint128_t m_NextAddr;
IPRange m_OurRange;
std::unordered_map< huint128_t, llarp_time_t, huint128_t::Hash >
m_IPActivity;
std::unordered_map< huint128_t, llarp_time_t > m_IPActivity;
llarp_tun_io m_Tun;

@ -1 +0,0 @@
#include <handlers/null.hpp>

@ -18,8 +18,6 @@
#include <util/str.hpp>
#include <absl/strings/ascii.h>
namespace llarp
{
namespace handlers
@ -111,6 +109,25 @@ namespace llarp
bool
TunEndpoint::SetOption(const std::string &k, const std::string &v)
{
if(k == "reachable")
{
if(IsFalseValue(v))
{
m_PublishIntroSet = false;
LogInfo(Name(), " setting to be not reachable by default");
}
else if(IsTrueValue(v))
{
m_PublishIntroSet = true;
LogInfo(Name(), " setting to be reachable by default");
}
else
{
LogError(Name(), " config option reachable = '", v,
"' does not make sense");
return false;
}
}
if(k == "isolate-network" && IsTrueValue(v.c_str()))
{
#if defined(__linux__)
@ -174,7 +191,7 @@ namespace llarp
{
routerStr = v;
}
absl::StripAsciiWhitespace(&routerStr);
routerStr = TrimWhitespace(routerStr);
if(!(exitRouter.FromString(routerStr)
|| HexDecode(routerStr.c_str(), exitRouter.begin(),
exitRouter.size())))
@ -473,7 +490,7 @@ namespace llarp
}
else
{
auto *replyMsg = new dns::Message(std::move(msg));
auto replyMsg = std::make_shared< dns::Message >(std::move(msg));
using service::Address;
using service::OutboundContext;
return EnsurePathToService(
@ -493,7 +510,7 @@ namespace llarp
}
else
{
auto *replyMsg = new dns::Message(std::move(msg));
auto replyMsg = std::make_shared< dns::Message >(std::move(msg));
return EnsurePathToSNode(
addr.as_array(),
[=](const RouterID &, exit::BaseSession_ptr s) {

@ -215,8 +215,7 @@ namespace llarp
FlushSend();
/// maps ip to key (host byte order)
std::unordered_map< huint128_t, AlignedBuffer< 32 >, huint128_t::Hash >
m_IPToAddr;
std::unordered_map< huint128_t, AlignedBuffer< 32 > > m_IPToAddr;
/// maps key to ip (host byte order)
std::unordered_map< AlignedBuffer< 32 >, huint128_t,
AlignedBuffer< 32 >::Hash >
@ -271,7 +270,8 @@ namespace llarp
template < typename Addr_t, typename Endpoint_t >
void
SendDNSReply(Addr_t addr, Endpoint_t ctx, dns::Message* query,
SendDNSReply(Addr_t addr, Endpoint_t ctx,
std::shared_ptr< dns::Message > query,
std::function< void(dns::Message) > reply, bool snode,
bool sendIPv6)
{
@ -283,14 +283,12 @@ namespace llarp
else
query->AddNXReply();
reply(*query);
delete query;
}
/// our dns resolver
std::shared_ptr< dns::Proxy > m_Resolver;
/// maps ip address to timestamp last active
std::unordered_map< huint128_t, llarp_time_t, huint128_t::Hash >
m_IPActivity;
std::unordered_map< huint128_t, llarp_time_t > m_IPActivity;
/// our ip address (host byte order)
huint128_t m_OurIP;
/// next ip address to allocate (host byte order)

@ -2,7 +2,6 @@
#include <iwp/linklayer.hpp>
#include <memory>
#include <router/abstractrouter.hpp>
#include <util/meta/memfn.hpp>
namespace llarp
{

@ -48,7 +48,7 @@ namespace llarp
bool isNewSession = false;
if(itr == m_AuthedAddrs.end())
{
ACQUIRE_LOCK(Lock_t lock, m_PendingMutex);
Lock_t lock(m_PendingMutex);
if(m_Pending.count(from) == 0)
{
if(not permitInbound)
@ -60,7 +60,7 @@ namespace llarp
}
else
{
ACQUIRE_LOCK(Lock_t lock, m_AuthedLinksMutex);
Lock_t lock(m_AuthedLinksMutex);
auto range = m_AuthedLinks.equal_range(itr->second);
session = range.first->second;
}

@ -196,6 +196,7 @@ namespace llarp
{
msg.FlushUnAcked(util::memFn(&Session::EncryptAndSend, this), now);
}
m_Stats.totalInFlightTX++;
LogDebug("send message ", msgid);
return true;
}
@ -298,15 +299,29 @@ namespace llarp
util::StatusObject
Session::ExtractStatus() const
{
return {{"tx", m_CurrentTX},
{"rx", m_CurrentRX},
{"state", m_State},
const auto now = m_Parent->Now();
return {{"txRateCurrent", m_Stats.currentRateTX},
{"rxRateCurrent", m_Stats.currentRateRX},
{"rxPktsRcvd", m_Stats.totalPacketsRX},
// leave 'tx' and 'rx' as duplicates of 'xRateCurrent' for compat
{"tx", m_Stats.currentRateTX},
{"rx", m_Stats.currentRateRX},
{"txPktsAcked", m_Stats.totalAckedTX},
{"txPktsDropped", m_Stats.totalDroppedTX},
{"txPktsInFlight", m_Stats.totalInFlightTX},
{"state", StateToString(m_State)},
{"inbound", m_Inbound},
{"replayFilter", m_ReplayFilter.size()},
{"txMsgs", m_TXMsgs.size()},
{"rxMsgs", m_RXMsgs.size()},
{"txMsgQueueSize", m_TXMsgs.size()},
{"rxMsgQueueSize", m_RXMsgs.size()},
{"remoteAddr", m_RemoteAddr.ToString()},
{"remoteRC", m_RemoteRC.ExtractStatus()}};
{"remoteRC", m_RemoteRC.ExtractStatus()},
{"created", m_CreatedAt},
{"uptime", (now - m_CreatedAt)}};
}
bool
@ -328,10 +343,10 @@ namespace llarp
void
Session::ResetRates()
{
m_CurrentTX = m_TXRate;
m_CurrentRX = m_RXRate;
m_RXRate = 0;
m_TXRate = 0;
m_Stats.currentRateTX = m_TXRate;
m_Stats.currentRateRX = m_RXRate;
m_RXRate = 0;
m_TXRate = 0;
}
void
@ -350,6 +365,9 @@ namespace llarp
{
if(itr->second.IsTimedOut(now))
{
m_Stats.totalDroppedTX++;
m_Stats.totalInFlightTX--;
LogWarn("Dropped unacked packet to ", m_RemoteAddr);
itr->second.InformTimeout();
itr = m_TXMsgs.erase(itr);
}
@ -661,6 +679,8 @@ namespace llarp
auto itr = m_TXMsgs.find(acked);
if(itr != m_TXMsgs.end())
{
m_Stats.totalAckedTX++;
m_Stats.totalInFlightTX--;
itr->second.Completed();
m_TXMsgs.erase(itr);
}
@ -751,8 +771,8 @@ namespace llarp
auto msg = std::move(itr->second);
const llarp_buffer_t buf(msg.m_Data);
m_Parent->HandleMessage(this, buf);
m_ReplayFilter.emplace(rxid, m_Parent->Now());
m_SendMACKs.emplace(rxid);
if(m_ReplayFilter.emplace(rxid, m_Parent->Now()).second)
m_SendMACKs.emplace(rxid);
m_RXMsgs.erase(rxid);
}
}
@ -805,8 +825,8 @@ namespace llarp
auto msg = std::move(itr->second);
const llarp_buffer_t buf(msg.m_Data);
m_Parent->HandleMessage(this, buf);
m_ReplayFilter.emplace(itr->first, m_Parent->Now());
m_SendMACKs.emplace(itr->first);
if(m_ReplayFilter.emplace(itr->first, m_Parent->Now()).second)
m_SendMACKs.emplace(itr->first);
}
else
{
@ -880,6 +900,9 @@ namespace llarp
Session::Recv_LL(ILinkSession::Packet_t data)
{
m_RXRate += data.size();
// TODO: differentiate between good and bad RX packets here
m_Stats.totalPacketsRX++;
switch(m_State)
{
case State::Initial:
@ -923,5 +946,25 @@ namespace llarp
}
return true;
}
std::string
Session::StateToString(State state)
{
switch(state)
{
case State::Initial:
return "Initial";
case State::Introduction:
return "Introduction";
case State::LinkIntro:
return "LinkIntro";
case State::Ready:
return "Ready";
case State::Closed:
return "Close";
default:
return "Invalid";
}
}
} // namespace iwp
} // namespace llarp

@ -123,6 +123,12 @@ namespace llarp
util::StatusObject
ExtractStatus() const override;
bool
IsInbound() const override
{
return m_Inbound;
}
private:
enum class State
{
@ -137,7 +143,24 @@ namespace llarp
/// we are closed now
Closed
};
static std::string
StateToString(State state);
State m_State;
struct Stats
{
// rate
uint64_t currentRateRX = 0;
uint64_t currentRateTX = 0;
uint64_t totalPacketsRX = 0;
uint64_t totalAckedTX = 0;
uint64_t totalDroppedTX = 0;
uint64_t totalInFlightTX = 0;
};
Stats m_Stats;
/// are we inbound session ?
const bool m_Inbound;
/// parent link layer
@ -159,12 +182,10 @@ namespace llarp
llarp_time_t m_LastTX = 0;
llarp_time_t m_LastRX = 0;
// accumulate for periodic rate calculation
uint64_t m_TXRate = 0;
uint64_t m_RXRate = 0;
uint64_t m_CurrentTX = 0;
uint64_t m_CurrentRX = 0;
llarp_time_t m_ResetRatesAt = 0;
uint64_t m_TXID = 0;

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save