Ryan Tharp 6 years ago
commit efe86c2401

@ -7,8 +7,8 @@
"name": "(lldb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/lokinet",
"args": [],
"program": "${workspaceFolder}/build/testAll",
"args": ["--gtest_shuffle", "--gtest_filter=TestThreadPool*"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],

@ -1,74 +1,76 @@
{
"editor.formatOnSave": true,
"files.associations": {
"array": "cpp",
"limits": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"atomic": "cpp",
"*.tcc": "cpp",
"bitset": "cpp",
"chrono": "cpp",
"codecvt": "cpp",
"condition_variable": "cpp",
"cstdint": "cpp",
"deque": "cpp",
"list": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"exception": "cpp",
"filesystem": "cpp",
"string_view": "cpp",
"fstream": "cpp",
"functional": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"memory": "cpp",
"mutex": "cpp",
"optional": "cpp",
"ostream": "cpp",
"ratio": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"system_error": "cpp",
"thread": "cpp",
"cinttypes": "cpp",
"type_traits": "cpp",
"tuple": "cpp",
"typeindex": "cpp",
"typeinfo": "cpp",
"utility": "cpp",
"__config": "cpp",
"__nullptr": "cpp",
"algorithm": "cpp",
"io": "cpp",
"strstream": "cpp",
"numeric": "cpp",
"valarray": "cpp",
"*.ipp": "cpp",
"csignal": "cpp",
"future": "cpp",
"map": "cpp",
"vector": "cpp",
"new": "cpp",
"shared_mutex": "cpp",
"complex": "cpp",
"variant": "cpp",
"any": "cpp",
"tuntap.h": "c",
"hashtable": "cpp"
}
"editor.formatOnSave": true,
"files.associations": {
"array": "cpp",
"limits": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"atomic": "cpp",
"*.tcc": "cpp",
"bitset": "cpp",
"chrono": "cpp",
"codecvt": "cpp",
"condition_variable": "cpp",
"cstdint": "cpp",
"deque": "cpp",
"list": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"exception": "cpp",
"filesystem": "cpp",
"string_view": "cpp",
"fstream": "cpp",
"functional": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"memory": "cpp",
"mutex": "cpp",
"optional": "cpp",
"ostream": "cpp",
"ratio": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"system_error": "cpp",
"thread": "cpp",
"cinttypes": "cpp",
"type_traits": "cpp",
"tuple": "cpp",
"typeindex": "cpp",
"typeinfo": "cpp",
"utility": "cpp",
"__config": "cpp",
"__nullptr": "cpp",
"algorithm": "cpp",
"io": "cpp",
"strstream": "cpp",
"numeric": "cpp",
"valarray": "cpp",
"*.ipp": "cpp",
"csignal": "cpp",
"future": "cpp",
"map": "cpp",
"vector": "cpp",
"new": "cpp",
"shared_mutex": "cpp",
"complex": "cpp",
"variant": "cpp",
"any": "cpp",
"tuntap.h": "c",
"hashtable": "cpp",
"__mutex_base": "cpp",
"iterator": "cpp"
}
}

@ -6,7 +6,7 @@
{
"label": "build",
"type": "shell",
"command": "make -j8 JSONRPC=ON",
"command": "make -j8 JSONRPC=ON test",
"group": "build",
"problemMatcher": [
"$gcc"

@ -5,24 +5,11 @@ set(PROJECT_NAME lokinet)
project(${PROJECT_NAME} C CXX ASM)
option(USE_LIBABYSS "enable libabyss" )
option(USE_CXX17 "enable c++17 features" )
option(USE_AVX2 "enable avx2 code" )
# Require C++11
# or C++17 on win32
if (NOT WIN32)
if(USE_CXX17)
set(CMAKE_CXX_STANDARD 17)
else()
if(ANDROID)
set(CMAKE_CXX_STANDARD 17)
else()
set(CMAKE_CXX_STANDARD 11)
endif()
endif()
else()
set(CMAKE_CXX_STANDARD 17)
endif(NOT WIN32)
option(USE_NETNS "enable networking namespace support" )
# Require C++11
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
@ -35,19 +22,29 @@ add_compile_options(-Wvla)
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fpermissive>)
add_compile_options(-Wno-unused-function -Wno-deprecated-declarations -Wno-unknown-pragmas)
# gah, can't recall which -Wno flag is exclusive to clang
# -Wno-cast-function-type is GNU exclusive..i think
if (WOW64_CROSS_COMPILE OR WIN64_CROSS_COMPILE)
# dynamic linking does this all the time
if(CMAKE_HOST_WIN32)
add_compile_options(-Wno-cast-function-type)
endif()
if (USING_CLANG)
add_compile_options(-Wno-unused-command-line-argument -Wno-c++11-narrowing)
add_compile_options($<$<COMPILE_LANGUAGE:C>:-Wno-bad-function-cast>)
# because clang is insane enough to inline whole sections of the C++ library!
# May have been fixed in llvm-7.
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--allow-multiple-definition --rtlib=libgcc")
endif(USING_CLANG)
endif()
if(WIN32)
add_compile_options($<$<COMPILE_LANGUAGE:C>:-Wno-bad-function-cast>)
add_compile_options(-Wno-cast-function-type)
set(FS_LIB stdc++fs)
endif(WIN32)
if(DEBIAN)
add_definitions(-DDEBIAN)
endif()
@ -58,13 +55,19 @@ find_package(Threads REQUIRED)
if(STATIC_LINK)
add_compile_options(-static)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++ -static-libgcc -static" )
if(USING_CLANG)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libgcc -static -Wl,--whole-archive -Wl,--no-whole-archive")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libstdc++ -static-libgcc -static -Wl,--whole-archive -lpthread -Wl,--no-whole-archive" )
endif()
endif()
# This is now configurable in ini
#if(DNS_PORT)
# add_definitions(-DDNS_PORT=${DNS_PORT})
#endif()
if(USE_NETNS)
add_definitions(-DNETNS=1)
else()
add_definitions(-DNETNS=0)
endif()
if(SHADOW)
set(WITH_STATIC OFF)
@ -76,8 +79,10 @@ if(TESTNET)
add_definitions(-DTESTNET=1)
endif()
if(NOT DEBIAN)
set(OPTIMIZE_FLAGS -O3)
set(DEBUG_FLAGS -O0 -g3)
endif()
if(ASAN)
set(DEBUG_FLAGS "${DEBUG_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
@ -107,17 +112,18 @@ if(CMAKE_BUILD_TYPE MATCHES "[Dd][Ee][Bb][Uu][Gg]")
add_compile_options( ${DEBUG_FLAGS} )
endif()
if(NOT DEBIAN)
if(NOT ANDROID)
if (USE_AVX2)
set(CRYPTO_FLAGS -march=native)
set(CMAKE_ASM_FLAGS "-march=native ${CMAKE_ASM_FLAGS} $ENV{ASFLAGS}")
if (NOT USE_AVX2)
set(CRYPTO_FLAGS -march=core2 -mtune=native)
set(CMAKE_ASM_FLAGS "-march=core2")
else()
if(WIN32)
set(CRYPTO_FLAGS -march=core2)
set(CMAKE_ASM_FLAGS "-march=core2 ${CMAKE_ASM_FLAGS} $ENV{ASFLAGS}")
set(CRYPTO_FLAGS -march=haswell -mtune=native)
set(CMAKE_ASM_FLAGS "-march=haswell -mtune=native ${CMAKE_ASM_FLAGS} $ENV{ASFLAGS}")
endif()
endif()
endif()
if(RPI)
add_definitions(-DRPI)
set(WITH_STATIC ON)
@ -150,18 +156,18 @@ if(JEMALLOC)
set(MALLOC_LIB jemalloc)
endif()
if (WIN32)
set(FS_LIB stdc++fs)
endif(WIN32)
# FS_LIB should resolve to nothing on all other platforms
# it is only required on win32 -rick
set(LIBS Threads::Threads ${MALLOC_LIB} ${FS_LIB})
set(LIBS ${LIBS} ${MALLOC_LIB} ${FS_LIB})
if(ANDROID)
set(LIBS ${LIBS} log)
endif()
if(NOT USING_CLANG)
set(LIBS ${LIBS} Threads::Threads)
endif()
set(LIB lokinet)
set(SHARED_LIB ${LIB})
set(STATIC_LIB ${LIB}-static)
@ -267,6 +273,8 @@ set(LIB_PLATFORM_SRC
# for logic
llarp/timer.cpp
# for threading
llarp/queue_manager.cpp
llarp/thread_pool.cpp
llarp/threadpool.cpp
# for android shim
${ANDROID_PLATFORM_SRC}
@ -274,9 +282,6 @@ set(LIB_PLATFORM_SRC
${ISOLATE_PROC_SRC}
# tun
${LIBTUNTAP_SRC}
# win32 inline code
llarp/win32_inet.c
llarp/win32_intrnl.c
# c++17 compat code
${CXX_COMPAT_SRC}
)
@ -457,6 +462,17 @@ set(LIB_SRC
llarp/dht/got_intro.cpp
llarp/dht/got_router.cpp
llarp/dht/publish_intro.cpp
llarp/exit/close_exit.cpp
llarp/exit/context.cpp
llarp/exit/endpoint.cpp
llarp/exit/grant_exit.cpp
llarp/exit/update_exit.cpp
llarp/exit/obtain_exit.cpp
llarp/exit/policy.cpp
llarp/exit/reject_exit.cpp
llarp/exit/session.cpp
llarp/exit/transfer_traffic.cpp
llarp/handlers/exit.cpp
llarp/handlers/tun.cpp
llarp/link/curvecp.cpp
llarp/link/server.cpp
@ -493,15 +509,22 @@ set(DNS_SRC
set(TEST_SRC
test/main.cpp
test/alignedbuffer_unittest.cpp
test/base32_unittest.cpp
test/dht_unittest.cpp
test/encrypted_frame_unittest.cpp
test/exit_unittest.cpp
test/hiddenservice_unittest.cpp
test/traffic_transfer_unittest.cpp
test/obtain_exit_unittest.cpp
test/pq_unittest.cpp
test/net_unittest.cpp
test/test_dns_unit.cpp
test/test_dnsc_unit.cpp
test/test_dnsd_unit.cpp
test/test_llarp_queue.cpp
test/test_llarp_queue_manager.cpp
test/test_llarp_thread_pool.cpp
)

@ -5,7 +5,7 @@ SIGN = gpg --sign --detach
REPO := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
PREFIX ?= /usr/local
prefix = $(DESTDIR)/usr/local
CC ?= cc
CXX ?= c++
@ -46,16 +46,16 @@ GRADLE ?= gradle
JAVA_HOME ?= /usr/lib/jvm/default-java
JSONRPC ?= OFF
CXX17 ?= ON
AVX2 ?= ON
RPI ?= OFF
STATIC_LINK ?= OFF
NETNS ?= OFF
CLANG ?= OFF
CMAKE_GEN ?= Unix Makefiles
BUILD_ROOT = $(REPO)/build
CONFIG_CMD = $(shell /bin/echo -n "cd '$(BUILD_ROOT)' && " ; /bin/echo -n "cmake -G'$(CMAKE_GEN)' -DSTATIC_LINK=$(STATIC_LINK) -DUSE_AVX2=$(AVX2) -DUSE_CXX17=$(CXX17) -DUSE_LIBABYSS=$(JSONRPC) -DRPI=$(RPI) '$(REPO)'")
CONFIG_CMD = $(shell /bin/echo -n "cd '$(BUILD_ROOT)' && " ; /bin/echo -n "cmake -G'$(CMAKE_GEN)' -DUSING_CLANG=$(CLANG) -DSTATIC_LINK=$(STATIC_LINK) -DUSE_NETNS=$(NETNS) -DUSE_AVX2=$(AVX2) -DUSE_LIBABYSS=$(JSONRPC) -DRPI=$(RPI) '$(REPO)'")
SCAN_BUILD ?= scan-build
ANALYZE_CONFIG_CMD = $(shell /bin/echo -n "cd '$(BUILD_ROOT)' && " ; /bin/echo -n "$(SCAN_BUILD) cmake -DUSE_LIBABYSS=$(JSONRPC) '$(REPO)'")
@ -74,6 +74,7 @@ LINT_FILES = $(wildcard llarp/*.cpp)
LINT_CHECK = $(LINT_FILES:.cpp=.cpp-check)
clean:
rm -f $(TARGETS)
rm -rf $(BUILD_ROOT)
rm -f $(SHADOW_PLUGIN) $(SHADOW_CONFIG)
rm -f *.sig
@ -142,7 +143,9 @@ testnet:
python3 contrib/testnet/genconf.py --bin=$(TESTNET_EXE) --svc=$(TESTNET_SERVERS) --clients=$(TESTNET_CLIENTS) --dir=$(TESTNET_ROOT) --out $(TESTNET_CONF) --connect=4
LLARP_DEBUG=$(TESTNET_DEBUG) supervisord -n -d $(TESTNET_ROOT) -l $(TESTNET_LOG) -c $(TESTNET_CONF)
test: debug
$(TEST_EXE): debug
test: $(TEST_EXE)
$(TEST_EXE)
android-gradle-prepare:
@ -193,14 +196,26 @@ docker-debian:
docker-fedora:
docker build -f docker/fedora.Dockerfile .
install:
rm -f $(PREFIX)/bin/lokinet
cp $(EXE) $(PREFIX)/bin/lokinet
chmod 755 $(PREFIX)/bin/lokinet
$(SETCAP) $(PREFIX)/bin/lokinet || true
rm -f $(PREFIX)/bin/lokinet-bootstrap
cp $(REPO)/lokinet-bootstrap $(PREFIX)/bin/lokinet-bootstrap
chmod 755 $(PREFIX)/bin/lokinet-bootstrap
debian-configure:
mkdir -p '$(BUILD_ROOT)'
$(CONFIG_CMD) -DDEBIAN=ON -DRELEASE_MOTTO="$(shell cat $(REPO)/motto.txt)" -DCMAKE_BUILD_TYPE=Release
debian: debian-configure
$(MAKE) -C '$(BUILD_ROOT)'
cp $(EXE) lokinet
cp $(BUILD_ROOT)/rcutil lokinet-rcutil
debian-test:
$(TEST_EXE)
install-bins:
install -T $(EXE) $(prefix)/bin/lokinet
install -T $(REPO)/lokinet-bootstrap $(prefix)/bin/lokinet-bootstrap
install-setcap: install-bins
$(SETCAP) $(prefix)/bin/lokinet || true
install: install-setcap
fuzz-configure: clean
cmake -GNinja -DCMAKE_BUILD_TYPE=Fuzz -DCMAKE_C_COMPILER=afl-gcc -DCMAKE_CXX_COMPILER=afl-g++
@ -210,3 +225,5 @@ fuzz-build: fuzz-configure
fuzz: fuzz-build
$(EXE)
.PHONY: debian-install

@ -15,8 +15,13 @@ def jsonrpc(method, **args):
def main():
if len(sys.argv) == 2 and sys.argv[1] == 'config':
print("graph_title lokinet peers")
print("lokinet.peers.outbound Number of outbound lokinet peers")
print("lokinet.peers.inbound Number of inbound lokinet peers")
print("graph_vlabel peers")
print("graph_category network")
print("graph_info This graph shows the number of node to node sessions of this lokinet router")
print("lokinet.peers.outbound.info Number of outbound lokinet peers")
print("lokinet.peers.inbound.info Number of inbound lokinet peers")
print("lokinet.peers.outbound.label outbound peers")
print("lokinet.peers.inbound.label inbound peers")
else:
inbound = 0
outbound = 0
@ -30,8 +35,8 @@ def main():
except:
pass
print("lokinet.peers.outboud {}".format(outbound))
print("lokinet.peers.inboud {}".format(inbound))
print("lokinet.peers.outbound {}".format(outbound))
print("lokinet.peers.inbound {}".format(inbound))
if __name__ == '__main__':

@ -23,7 +23,12 @@
#include <tmmintrin.h>
#ifndef __amd64__
#ifdef __clang__
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse2")))
#else
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __target__("sse2")))
#endif
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtsi64_si128(long long __a)
{

@ -48,7 +48,7 @@ sodium_init(void)
{
return -1; /* LCOV_EXCL_LINE */
}
return 0;
return initialized ? 0 : -1;
}
#ifdef _WIN32

@ -9,7 +9,7 @@
#include "xmm6int/salsa20_xmm6int-sse2.h"
#include "xmm6int/salsa20_xmm6int-avx2.h"
static const crypto_stream_salsa20_implementation *implementation;
static crypto_stream_salsa20_implementation *implementation = NULL;
size_t
crypto_stream_salsa20_keybytes(void)
@ -33,6 +33,7 @@ int
crypto_stream_salsa20(unsigned char *c, unsigned long long clen,
const unsigned char *n, const unsigned char *k)
{
_crypto_stream_salsa20_pick_best_implementation();
return implementation->stream(c, clen, n, k);
}
@ -41,6 +42,7 @@ crypto_stream_salsa20_xor_ic(unsigned char *c, const unsigned char *m,
unsigned long long mlen, const unsigned char *n,
uint64_t ic, const unsigned char *k)
{
_crypto_stream_salsa20_pick_best_implementation();
return implementation->stream_xor_ic(c, m, mlen, n, ic, k);
}
@ -49,6 +51,7 @@ crypto_stream_salsa20_xor(unsigned char *c, const unsigned char *m,
unsigned long long mlen, const unsigned char *n,
const unsigned char *k)
{
_crypto_stream_salsa20_pick_best_implementation();
return implementation->stream_xor_ic(c, m, mlen, n, 0U, k);
}
@ -61,12 +64,8 @@ crypto_stream_salsa20_keygen(unsigned char k[crypto_stream_salsa20_KEYBYTES])
int
_crypto_stream_salsa20_pick_best_implementation(void)
{
#if __AVX2__ && __amd64__
implementation = &crypto_stream_salsa20_xmm6_implementation;
#else
implementation = &crypto_stream_salsa20_ref_implementation;
#endif
if(implementation)
return 0;
#if __AVX2__
if(sodium_runtime_has_avx2())
{
@ -81,5 +80,7 @@ _crypto_stream_salsa20_pick_best_implementation(void)
return 0;
}
#endif
if(implementation == NULL)
implementation = &crypto_stream_salsa20_ref_implementation;
return 0; /* LCOV_EXCL_LINE */
}

@ -8,7 +8,7 @@
#include <sodium/private/sse2_64_32.h>
#include <sodium/utils.h>
#if __AVX2__
#if __AVX2__ && __amd64__
#ifdef __GNUC__
#pragma GCC target("sse2")
@ -23,11 +23,18 @@
#include <tmmintrin.h>
#ifndef __amd64__
#define __DEFAULT_FN_ATTRS __attribute__((__always_inline__, __nodebug__, __target__("sse2")))
#ifdef __clang__
#define __DEFAULT_FN_ATTRS \
__attribute__((__always_inline__, __nodebug__, __target__("sse2")))
#else
#define __DEFAULT_FN_ATTRS \
__attribute__((__always_inline__, __target__("sse2")))
#endif
static __inline__ __m128i __DEFAULT_FN_ATTRS
_mm_cvtsi64_si128(long long __a)
{
return (__m128i){ __a, 0 };
return (__m128i){__a, 0};
}
#endif

@ -221,7 +221,12 @@ main(int argc, char *argv[])
struct sockaddr_in m_address;
int m_sockfd;
m_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
#ifndef _WIN32
m_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
#else
m_sockfd =
WSASocket(AF_INET, SOCK_DGRAM, 0, nullptr, 0, WSA_FLAG_OVERLAPPED);
#endif
m_address.sin_family = AF_INET;
m_address.sin_addr.s_addr = INADDR_ANY;
m_address.sin_port = htons(server_port);

@ -4,7 +4,7 @@
#include "logger.hpp"
#include <llarp/router_contact.hpp>
#include <llarp/time.h>
#include <llarp/time.hpp>
#include <fstream>
#include "buffer.hpp"
@ -14,9 +14,6 @@
#include "router.hpp"
#include <llarp/messages/dht.hpp>
//#include <llarp/dht/messages/findintro.hpp>
//#include <llarp/routing_endpoint.hpp>
//#include <llarp/crypt.hpp> // for llarp::pubkey
struct llarp_main *ctx = 0;
@ -391,7 +388,7 @@ main(int argc, char *argv[])
printf("Creating [%s]\n", rcfname);
// if we zero it out then
// set updated timestamp
rc.last_updated = llarp_time_now_ms();
rc.last_updated = llarp::time_now_ms();
// load longterm identity
llarp_crypto crypt;
llarp_crypto_init(&crypt);
@ -440,7 +437,7 @@ main(int argc, char *argv[])
// llarp_rc_read(rcfname, &rc);
// set updated timestamp
rc.last_updated = llarp_time_now_ms();
rc.last_updated = llarp::time_now_ms();
// load longterm identity
llarp_crypto crypt;
@ -492,7 +489,7 @@ main(int argc, char *argv[])
// llarp::LogInfo("Looking for string: ", rcfname);
llarp::PubKey binaryPK;
llarp::HexDecode(rcfname, binaryPK.data());
llarp::HexDecode(rcfname, binaryPK.data(), binaryPK.size());
llarp::LogInfo("Looking for binary: ", binaryPK);
llarp::RouterContact *rc = llarp_main_getDatabase(ctx, binaryPK.data());
@ -513,7 +510,7 @@ main(int argc, char *argv[])
llarp_main_setup(ctx);
llarp::PubKey binaryPK;
llarp::HexDecode(rcfname, binaryPK.data());
llarp::HexDecode(rcfname, binaryPK.data(), binaryPK.size());
llarp::LogInfo("Queueing job");
llarp_router_lookup_job *job = new llarp_router_lookup_job;
@ -584,7 +581,7 @@ main(int argc, char *argv[])
llarp::PubKey binaryPK;
// llarp::service::Address::FromString
llarp::HexDecode(rcfname, binaryPK.data());
llarp::HexDecode(rcfname, binaryPK.data(), binaryPK.size());
char tmp[(1 + 32) * 2] = {0};
std::string b32 = llarp::Base32Encode(binaryPK, tmp);
llarp::LogInfo("to base32 ", b32);

6
debian/rules vendored

@ -19,3 +19,9 @@ endif
override_dh_auto_build:
$(MAKE) debian
override_dh_auto_test:
$(MAKE) debian-test
override_dh_auto_install:
$(MAKE) debian-install

@ -526,7 +526,7 @@ variant 2, response, generated by the endpoint that recieved the request.
V: 0
}
obtain exit address message (OXAM)
obtain exit message (OXM)
sent to an exit router to obtain ip exit traffic context.
replies are sent down the path that messages originate from.
@ -544,24 +544,25 @@ replies are sent down the path that messages originate from.
Z: "<64 bytes signature using I>"
}
grant exit address messsage (GXAM)
grant exit messsage (GXM)
sent in response to an OXAM to grant an ip for exit traffic from an external
sent in response to an OXM to grant an ip for exit traffic from an external
ip address used for exit traffic.
{
A: "G",
S: uint64_sequence_number,
T: transaction_id_uint64,
Y: "<16 byte nonce>",
V: 0,
Z: "<64 bytes signature using router identity signing key>"
Z: "<64 bytes signature>"
}
any TITM recieved on the same path will be forwarded out to the internet if
OXAM.E is not 0, otherwise it is interpreted as service node traffic.
reject exit address message (RXAM)
reject exit message (RXM)
sent in response to an OXAM to indicate that exit traffic is not allowed or
was denied.
@ -573,14 +574,15 @@ was denied.
S: uint64_sequence_number,
T: transaction_id_uint64,
V: 0,
Z: "<64 bytes signature signed by router's signing key>"
Y: "<16 byte nonce>",
Z: "<64 bytes signature>"
}
discarded data fragment message (DDFM)
sent in reply to TDFM when we don't have a path locally or are doing network
congestion control. indcates a TDFM was discarded.
congestion control from a TITM.
{
A: "D",
@ -734,24 +736,25 @@ transfer data on a session previously made
transfer ip traffic message (TITM)
transfer ip traffic for exit
transfer ip traffic
{
A: "I",
S: uint64_sequence_number,
V: 0,
X: "<N bytes ip packet>",
Y: "<16 bytes nonce>",
Z: "<64 bytes signature using previously provided signing key>"
}
X is parsed as an IP packet and the source addresss is extracted.
Next we find the corrisponding signing key for a previously granted exit address
Next we find the corrisponding signing key for a previously granted address
and use it to validate the siganture of the entire message. If the signing key
cannot be found or the signature is invalid this message is dropped, otherwise
the X value is sent on the appropriate exit network interface.
the X value is sent on the appropriate network interface.
When we recieve an ip packet from the internet to an exit address, we put it
into a TITM, signed with the exit info's signing key and send it downstream the
into a TITM, signed with the router's signing key and send it downstream the
corrisponding path in an LRDM.
update exit path message (UXPM)
@ -761,37 +764,42 @@ should use the new path that this message came from.
{
A: "U",
R: "<16 bytes previous rx path id>",
P: "<16 bytes previous tx path id>",
S: uint64_sequence_number,
T: "<16 bytes previous tx path id>",
U: uint64_unique_id,
T: uint64_txid,
V: 0,
Y: "<16 bytes nonce>",
Z: "<64 bytes signature using previously provided signing key>"
}
update exit verify message (EXVM)
close exit path message (CXPM)
sent in reply to a UXPM to verify that the path handover was accepted
client sends a CXPM when the exit is no longer needed or by the exit if the
exit wants to close prematurely.
also sent by exit in reply to a CXPM to confirm close.
{
A: "V",
U: uint64_unique_id,
A: "C",
S: uint64_sequence_number,
V: 0,
Z: "<64 bytes signature from router's signing key>"
Y: "<16 bytes nonce>",
Z: "<64 bytes signature>"
}
close exit path message (CXPM)
update exit verify message (EXVM)
client sends a CXPM when the exit is no longer needed.
sent in reply to a UXPM to verify that the path handover was accepted
{
A: "C",
A: "V",
S: uint64_sequence_number,
T: transaction_id_uint64,
T: uint64_txid,
V: 0,
Z: "<64 bytes signagure using previously provided signing key>"
Y: "<16 bytes nonce>",
Z: "<64 bytes signature>"
}
DHT message holder message:
wrapper message for sending many dht messages down a path.

@ -2,9 +2,9 @@
#define LLARP_H_
#include <llarp/dht.h>
#include <llarp/ev.h>
#include <llarp/logic.h>
#include <llarp/logic.hpp>
#include <llarp/mem.h>
#include <llarp/version.h>
#include <llarp/version.hpp>
#ifdef __cplusplus
#include <llarp/service/address.hpp> // for service::address

@ -69,7 +69,7 @@ namespace llarp
bool
operator==(const AlignedBuffer& other) const
{
return memcmp(data(), other.data(), sz) == 0;
return memcmp(b, other.b, sz) == 0;
}
bool
@ -159,35 +159,35 @@ namespace llarp
byte_t*
data()
{
return &b[0];
return b;
}
const byte_t*
data() const
{
return &b[0];
return b;
}
Long_t*
data_l()
{
return &l[0];
return l;
}
const Long_t*
data_l() const
{
return &l[0];
return l;
}
operator const byte_t*() const
{
return &b[0];
return b;
}
operator byte_t*()
{
return &b[0];
return b;
}
bool
@ -221,9 +221,9 @@ namespace llarp
struct Hash
{
size_t
operator()(const AlignedBuffer& buf) const
operator()(const AlignedBuffer< sz, randomize, Long_t >& buf) const
{
return *buf.data_l();
return buf.l[0];
}
};

@ -1,8 +1,8 @@
#ifndef LLARP_BENCODE_H
#define LLARP_BENCODE_H
#include <llarp/buffer.h>
#include <llarp/common.h>
#include <llarp/proto.h>
#include <llarp/common.hpp>
#include <llarp/proto.hpp>
#include <stdbool.h>
#include <stdint.h>

@ -1,6 +1,6 @@
#ifndef LLARP_BUFFER_H_
#define LLARP_BUFFER_H_
#include <llarp/common.h>
#include <llarp/common.hpp>
#include <llarp/mem.h>
#include <stdbool.h>
#include <stdio.h>

@ -1,6 +1,6 @@
#ifndef LLARP_CODEL_QUEUE_HPP
#define LLARP_CODEL_QUEUE_HPP
#include <llarp/time.h>
#include <llarp/time.hpp>
#include <llarp/logger.hpp>
#include <llarp/mem.hpp>
#include <llarp/threading.hpp>
@ -29,14 +29,23 @@ namespace llarp
}
};
struct GetNowSyscall
{
llarp_time_t
operator()() const
{
return llarp::time_now_ms();
}
};
template < typename T, typename GetTime, typename PutTime, typename Compare,
typename Mutex_t = util::Mutex, typename Lock_t = util::Lock,
llarp_time_t dropMs = 5, llarp_time_t initialIntervalMs = 100,
size_t MaxSize = 1024 >
typename GetNow = GetNowSyscall, typename Mutex_t = util::Mutex,
typename Lock_t = util::Lock, llarp_time_t dropMs = 5,
llarp_time_t initialIntervalMs = 100, size_t MaxSize = 1024 >
struct CoDelQueue
{
CoDelQueue(const std::string& name, const PutTime& put)
: m_name(name), _putTime(put)
CoDelQueue(const std::string& name, const PutTime& put, const GetNow& now)
: m_name(name), _putTime(put), _getNow(now)
{
}
@ -96,11 +105,13 @@ namespace llarp
void
Process(Visit visitor, Filter f)
{
llarp_time_t lowest = 0xFFFFFFFFFFFFFFFFUL;
// auto start = llarp_time_now_ms();
llarp_time_t lowest = std::numeric_limits< llarp_time_t >::max();
if(_getNow() < nextTickAt)
return;
// llarp::LogInfo("CoDelQueue::Process - start at ", start);
Lock_t lock(m_QueueMutex);
auto start = firstPut;
if(m_QueueIdx == 1)
{
visitor(m_Queue[0]);
@ -129,7 +140,8 @@ namespace llarp
{
item->~T();
nextTickInterval += initialIntervalMs / std::sqrt(++dropNum);
firstPut = 0;
firstPut = 0;
nextTickAt = start + nextTickInterval;
return;
}
else
@ -141,18 +153,21 @@ namespace llarp
visitor(*item);
item->~T();
}
firstPut = 0;
firstPut = 0;
nextTickAt = start + nextTickInterval;
}
llarp_time_t firstPut = 0;
size_t dropNum = 0;
llarp_time_t nextTickInterval = initialIntervalMs;
llarp_time_t nextTickAt = 0;
Mutex_t m_QueueMutex;
size_t m_QueueIdx = 0;
T m_Queue[MaxSize];
std::string m_name;
GetTime _getTime;
PutTime _putTime;
GetNow _getNow;
}; // namespace util
} // namespace util
} // namespace llarp

@ -1,5 +1,5 @@
#ifndef LLARP_COMMON_H
#define LLARP_COMMON_H
#ifndef LLARP_COMMON_HPP
#define LLARP_COMMON_HPP
#ifdef __STRICT_ANSI__
#define INLINE __inline__
#else

@ -1,7 +1,7 @@
#ifndef LLARP_CRYPTO_H_
#define LLARP_CRYPTO_H_
#include <llarp/buffer.h>
#include <llarp/common.h>
#include <llarp/common.hpp>
#include <stdbool.h>
#include <stdint.h>

@ -1,5 +1,5 @@
#ifndef LLARP_DEFAULTS_H
#define LLARP_DEFAULTS_H
#ifndef LLARP_DEFAULTS_HPP
#define LLARP_DEFAULTS_HPP
#ifndef DEFAULT_RESOLVER_US
#define DEFAULT_RESOLVER_US "1.1.1.1"
@ -27,4 +27,4 @@
#endif
#endif
#endif
#endif

@ -61,7 +61,11 @@ namespace llarp
GetManyRandom(std::set< Key_t >& result, size_t N) const
{
if(nodes.size() < N)
{
llarp::LogWarn("Not enough dht nodes, have ", nodes.size(), " want ",
N);
return false;
}
if(nodes.size() == N)
{
for(const auto& node : nodes)

@ -2,13 +2,14 @@
#define LLARP_DHT_CONTEXT_HPP
#include <llarp/dht.h>
#include <llarp/router.h>
#include <llarp/dht/bucket.hpp>
#include <llarp/dht/key.hpp>
#include <llarp/dht/message.hpp>
#include <llarp/dht/messages/findintro.hpp>
#include <llarp/dht/node.hpp>
#include <llarp/router.h>
#include <llarp/service/IntroSet.hpp>
#include <llarp/time.hpp>
#include <set>
@ -302,7 +303,7 @@ namespace llarp
if(itr == timeouts.end())
{
timeouts.insert(
std::make_pair(k, llarp_time_now_ms() + requestTimeoutMS));
std::make_pair(k, time_now_ms() + requestTimeoutMS));
}
t->Start(askpeer);
}

@ -133,8 +133,8 @@ namespace llarp
int
char2int(char input);
void
HexDecode(const char* src, uint8_t* target);
bool
HexDecode(const char* src, uint8_t* target, size_t sz);
} // namespace llarp
#endif

@ -1,5 +1,5 @@
#ifndef LLARP_ENDIAN_H
#define LLARP_ENDIAN_H
#ifndef LLARP_ENDIAN_HPP
#define LLARP_ENDIAN_HPP
// adapted from libi2pd

@ -3,7 +3,6 @@
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
#ifndef ssize_t
#define ssize_t long
#endif
@ -15,7 +14,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <tuntap.h>
#include <llarp/time.h>
#include <llarp/time.hpp>
/**
* ev.h

@ -0,0 +1,6 @@
#ifndef LLARP_EXIT_HPP
#define LLARP_EXIT_HPP
#include <llarp/exit/context.hpp>
#include <llarp/exit/policy.hpp>
#include <llarp/exit/session.hpp>
#endif

@ -0,0 +1,54 @@
#ifndef LLARP_EXIT_CONTEXT_HPP
#define LLARP_EXIT_CONTEXT_HPP
#include <llarp/exit/policy.hpp>
#include <string>
#include <unordered_map>
#include <llarp/handlers/exit.hpp>
#include <llarp/router.h>
namespace llarp
{
namespace exit
{
/// owner of all the exit endpoints
struct Context
{
using Config_t = std::unordered_multimap< std::string, std::string >;
Context(llarp_router *r);
~Context();
void
Tick(llarp_time_t now);
void
ClearAllEndpoints();
bool
AddExitEndpoint(const std::string &name, const Config_t &config);
bool
ObtainNewExit(const llarp::PubKey &remote, const llarp::PathID_t &path,
bool permitInternet);
llarp::exit::Endpoint *
FindEndpointForPath(const llarp::PathID_t &path) const;
/// calculate (pk, tx, rx) for all exit traffic
using TrafficStats =
std::unordered_map< PubKey, std::pair< uint64_t, uint64_t >,
PubKey::Hash >;
void
CalculateExitTraffic(TrafficStats &stats);
private:
llarp_router *m_Router;
std::unordered_map< std::string,
std::unique_ptr< llarp::handlers::ExitEndpoint > >
m_Exits;
};
} // namespace exit
} // namespace llarp
#endif

@ -0,0 +1,100 @@
#ifndef LLARP_EXIT_ENDPOINT_HPP
#define LLARP_EXIT_ENDPOINT_HPP
#include <llarp/time.hpp>
#include <llarp/crypto.hpp>
#include <llarp/router.h>
#include <llarp/path.hpp>
namespace llarp
{
namespace handlers
{
// forward declare
struct ExitEndpoint;
} // namespace handlers
namespace exit
{
/// persistant exit state for 1 identity on the exit node
struct Endpoint
{
Endpoint(const llarp::PubKey& remoteIdent,
const llarp::PathID_t& beginPath, bool rewriteDst, huint32_t ip,
llarp::handlers::ExitEndpoint* parent);
~Endpoint();
/// close ourselves
void
Close();
/// return true if we are expired right now
bool
IsExpired(llarp_time_t now) const;
bool
ExpiresSoon(llarp_time_t now, llarp_time_t dlt = 5000) const;
/// tick ourself, reset tx/rx rates
void
Tick(llarp_time_t now);
/// handle traffic from service node / internet
bool
SendInboundTraffic(llarp_buffer_t buff);
/// send traffic to service node / internet
/// does ip rewrite here
bool
SendOutboundTraffic(llarp_buffer_t buf);
/// update local path id and cascade information to parent
/// return true if success
bool
UpdateLocalPath(const llarp::PathID_t& nextPath);
llarp::path::IHopHandler*
GetCurrentPath() const;
const llarp::PubKey&
PubKey() const
{
return m_remoteSignKey;
}
const llarp::PathID_t&
LocalPath() const
{
return m_CurrentPath;
}
uint64_t
TxRate() const
{
return m_TxRate;
}
uint64_t
RxRate() const
{
return m_RxRate;
}
huint32_t
LocalIP() const
{
return m_IP;
}
private:
llarp::handlers::ExitEndpoint* m_Parent;
llarp::PubKey m_remoteSignKey;
llarp::PathID_t m_CurrentPath;
llarp::huint32_t m_IP;
uint64_t m_TxRate, m_RxRate;
bool m_RewriteSource;
};
} // namespace exit
} // namespace llarp
#endif

@ -0,0 +1,26 @@
#ifndef LLARP_EXIT_POLICY_HPP
#define LLARP_EXIT_POLICY_HPP
#include <llarp/bencode.hpp>
namespace llarp
{
namespace exit
{
struct Policy final : public llarp::IBEncodeMessage
{
~Policy();
uint64_t proto;
uint64_t port;
uint64_t drop;
bool
DecodeKey(llarp_buffer_t k, llarp_buffer_t* val) override;
bool
BEncode(llarp_buffer_t* buf) const override;
};
} // namespace exit
} // namespace llarp
#endif

@ -0,0 +1,53 @@
#ifndef LLARP_EXIT_SESSION_HPP
#define LLARP_EXIT_SESSION_HPP
#include <llarp/pathbuilder.hpp>
#include <llarp/ip.hpp>
namespace llarp
{
namespace exit
{
/// a persisiting exit session with an exit router
struct BaseSession : public llarp::path::Builder
{
BaseSession(const llarp::RouterID& exitRouter,
std::function< bool(llarp_buffer_t) > writepkt,
llarp_router* r, size_t numpaths, size_t hoplen);
~BaseSession();
bool
SelectHop(llarp_nodedb* db, const RouterContact& prev, RouterContact& cur,
size_t hop, llarp::path::PathRole roles) override;
bool
ShouldBuildMore(llarp_time_t now) const override;
void
HandlePathBuilt(llarp::path::Path* p) override;
bool
SendUpstreamTraffic(llarp::net::IPv4Packet pkt);
protected:
llarp::RouterID m_ExitRouter;
std::function< bool(llarp_buffer_t) > m_WritePacket;
bool
HandleTrafficDrop(llarp::path::Path* p, const llarp::PathID_t& path,
uint64_t s);
bool
HandleGotExit(llarp::path::Path* p, llarp_time_t b);
bool
HandleTraffic(llarp::path::Path* p, llarp_buffer_t buf);
private:
llarp::SecretKey m_ExitIdentity;
};
} // namespace exit
} // namespace llarp
#endif

@ -2,7 +2,7 @@
#define LLARP_XI_HPP
#include <llarp/bencode.hpp>
#include <llarp/crypto.hpp>
#include <llarp/net.h>
#include <llarp/net.hpp>
#include <iostream>
#include <llarp/bits.hpp>
@ -21,6 +21,16 @@ namespace llarp
struct in6_addr netmask;
PubKey pubkey;
ExitInfo(const PubKey &pk, const nuint32_t &ipv4_exit) : IBEncodeMessage()
{
pubkey = pk;
memset(address.s6_addr, 0, 16);
address.s6_addr[11] = 0xff;
address.s6_addr[10] = 0xff;
memcpy(address.s6_addr + 12, &ipv4_exit, 4);
memset(netmask.s6_addr, 0xff, 16);
}
ExitInfo() : IBEncodeMessage()
{
}
@ -54,7 +64,7 @@ namespace llarp
return out;
out << std::string("/");
#if defined(ANDROID) || defined(RPI)
snprintf(tmp, sizeof(tmp), "%u",
snprintf(tmp, sizeof(tmp), "%lu",
llarp::bits::count_array_bits(xi.netmask.s6_addr));
return out << tmp;
#else

@ -0,0 +1,143 @@
#ifndef LLARP_HANDLERS_EXIT_HPP
#define LLARP_HANDLERS_EXIT_HPP
#include <llarp/handlers/tun.hpp>
#include <llarp/exit/endpoint.hpp>
#include <unordered_map>
namespace llarp
{
namespace handlers
{
struct ExitEndpoint
{
ExitEndpoint(const std::string& name, llarp_router* r);
~ExitEndpoint();
void
Tick(llarp_time_t now);
bool
SetOption(const std::string& k, const std::string& v);
std::string
Name() const;
bool
AllocateNewExit(const llarp::PubKey pk, const llarp::PathID_t& path,
bool permitInternet);
llarp::exit::Endpoint*
FindEndpointByPath(const llarp::PathID_t& path);
llarp::exit::Endpoint*
FindEndpointByIP(huint32_t ip);
bool
UpdateEndpointPath(const llarp::PubKey& remote,
const llarp::PathID_t& next);
/// handle ip packet from outside
void
OnInetPacket(llarp_buffer_t buf);
llarp_router*
Router();
llarp_crypto*
Crypto();
template < typename Stats >
void
CalculateTrafficStats(Stats& stats)
{
auto itr = m_ActiveExits.begin();
while(itr != m_ActiveExits.end())
{
stats[itr->first].first += itr->second->TxRate();
stats[itr->first].second += itr->second->RxRate();
++itr;
}
}
/// DO NOT CALL ME
void
DelEndpointInfo(const llarp::PathID_t& path);
/// DO NOT CALL ME
void
RemoveExit(const llarp::exit::Endpoint* ep);
bool
QueueOutboundTraffic(llarp_buffer_t buf);
/// sets up networking and starts traffic
bool
Start();
bool
HasLocalMappedAddrFor(const llarp::PubKey& pk) const;
huint32_t
GetIfAddr() const;
void
FlushInbound();
private:
huint32_t
GetIPForIdent(const llarp::PubKey pk);
huint32_t
AllocateNewAddress();
void
MarkIPActive(llarp::huint32_t ip);
void
KickIdentOffExit(const llarp::PubKey& pk);
llarp_router* m_Router;
bool m_ShouldInitTun;
std::string m_Name;
bool m_PermitExit;
std::unordered_map< llarp::PathID_t, llarp::PubKey,
llarp::PathID_t::Hash >
m_Paths;
std::unordered_multimap< llarp::PubKey,
std::unique_ptr< llarp::exit::Endpoint >,
llarp::PubKey::Hash >
m_ActiveExits;
using KeyMap_t = std::unordered_map< llarp::PubKey, llarp::huint32_t,
llarp::PubKey::Hash >;
KeyMap_t m_KeyToIP;
std::unordered_map< llarp::huint32_t, llarp::PubKey,
llarp::huint32_t::Hash >
m_IPToKey;
huint32_t m_IfAddr;
huint32_t m_HigestAddr;
huint32_t m_NextAddr;
std::unordered_map< llarp::huint32_t, llarp_time_t,
llarp::huint32_t::Hash >
m_IPActivity;
llarp_tun_io m_Tun;
using Pkt_t = llarp::net::IPv4Packet;
using PacketQueue_t =
llarp::util::CoDelQueue< Pkt_t, Pkt_t::GetTime, Pkt_t::PutTime,
Pkt_t::CompareOrder, Pkt_t::GetNow,
llarp::util::DummyMutex,
llarp::util::DummyLock, 5, 100, 1024 >;
/// internet to llarp packet queue
PacketQueue_t m_InetToNetwork;
};
} // namespace handlers
} // namespace llarp
#endif

@ -23,10 +23,10 @@ namespace llarp
TunEndpoint(const std::string& nickname, llarp_router* r);
~TunEndpoint();
bool
virtual bool
SetOption(const std::string& k, const std::string& v);
void
virtual void
Tick(llarp_time_t now);
void
@ -51,6 +51,17 @@ namespace llarp
bool
ProcessDataMessage(service::ProtocolMessage* msg);
/// queue outbound packet to the world
bool
QueueOutboundTraffic(llarp::net::IPv4Packet&& pkt);
/// get the local interface's address
huint32_t
GetIfAddr() const;
bool
HasLocalIP(const huint32_t& ip) const;
#ifndef WIN32
/// overrides Endpoint
bool
@ -80,24 +91,37 @@ namespace llarp
static void
handleTickTun(void* u);
/// get a service address for ip address
service::Address
ObtainAddrForIP(huint32_t ip);
/// get a key for ip address
template < typename Addr >
Addr
ObtainAddrForIP(huint32_t ip)
{
auto itr = m_IPToAddr.find(ip);
if(itr == m_IPToAddr.end())
{
// not found
Addr addr;
addr.Zero();
return addr;
}
// found
return itr->second.data();
}
bool
HasAddress(const service::Address& remote) const
HasAddress(const byte_t* addr) const
{
return m_AddrToIP.find(remote) != m_AddrToIP.end();
return m_AddrToIP.find(addr) != m_AddrToIP.end();
}
/// get ip address for service address unconditionally
/// get ip address for key unconditionally
huint32_t
ObtainIPForAddr(const service::Address& addr);
ObtainIPForAddr(const byte_t* addr);
protected:
typedef llarp::util::CoDelQueue<
net::IPv4Packet, net::IPv4Packet::GetTime, net::IPv4Packet::PutTime,
net::IPv4Packet::CompareOrder >
net::IPv4Packet::CompareOrder, net::IPv4Packet::GetNow >
PacketQueue_t;
/// queue for sending packets over the network from us
PacketQueue_t m_UserToNetworkPktQueue;
@ -115,10 +139,31 @@ namespace llarp
void
MarkIPActiveForever(huint32_t ip);
void
/// flush ip packets
virtual void
FlushSend();
/// maps ip to key (host byte order)
std::unordered_map< huint32_t, AlignedBuffer< 32 >, huint32_t::Hash >
m_IPToAddr;
/// maps key to ip (host byte order)
std::unordered_map< AlignedBuffer< 32 >, huint32_t,
AlignedBuffer< 32 >::Hash >
m_AddrToIP;
private:
bool
QueueInboundPacketForExit(llarp_buffer_t buf)
{
return m_NetworkToUserPktQueue.EmplaceIf(
[&](llarp::net::IPv4Packet& pkt) -> bool {
if(!pkt.Load(buf))
return false;
pkt.UpdateIPv4PacketOnDst(pkt.src(), m_OurIP);
return true;
});
}
#ifndef WIN32
/// handles setup, given value true on success and false on failure to set
/// up interface
@ -130,12 +175,6 @@ namespace llarp
/// for netns)
struct dotLokiLookup dll;
/// maps ip to service address (host byte order)
std::unordered_map< huint32_t, service::Address, huint32_t::Hash >
m_IPToAddr;
/// maps service address to ip (host byte order)
std::unordered_map< service::Address, huint32_t, service::Address::Hash >
m_AddrToIP;
/// maps ip address to timestamp last active
std::unordered_map< huint32_t, llarp_time_t, huint32_t::Hash >
m_IPActivity;

@ -1,7 +1,7 @@
#ifndef LLARP_IP_HPP
#define LLARP_IP_HPP
#include <llarp/buffer.h>
#include <llarp/time.h>
#include <llarp/time.hpp>
#include <llarp/net.hpp>
#include <llarp/ev.h>
@ -113,6 +113,19 @@ namespace llarp
}
};
struct GetNow
{
llarp_ev_loop* loop;
GetNow(llarp_ev_loop* evloop) : loop(evloop)
{
}
llarp_time_t
operator()() const
{
return llarp_ev_loop_time_now_ms(loop);
}
};
struct CompareOrder
{
bool

@ -7,8 +7,7 @@
#include <llarp/net.hpp>
#include <llarp/ev.h>
#include <llarp/link/session.hpp>
#include <llarp/logic.h>
#include <llarp/time.h>
#include <llarp/logic.hpp>
#include <list>
struct llarp_router;

@ -4,7 +4,7 @@
#include <llarp/crypto.hpp>
#include <llarp/net.hpp>
#include <llarp/router_contact.hpp>
#include <llarp/types.h>
#include <llarp/types.hpp>
#include <functional>
namespace llarp

@ -16,7 +16,6 @@
#endif
#ifdef RPI
#include <cstdio>
#include <llarp/time.h>
#endif
namespace llarp
@ -103,7 +102,7 @@ namespace llarp
{
#if defined(ANDROID) || defined(RPI)
(void)ts;
return out << llarp_time_now_ms();
return out << time_now_ms();
#else
auto now = llarp::Clock_t::to_time_t(llarp::Clock_t::now());
return out << std::put_time(std::localtime(&now), ts.format);

@ -1,8 +1,8 @@
#ifndef LLARP_LOGIC_H
#define LLARP_LOGIC_H
#ifndef LLARP_LOGIC_HPP
#define LLARP_LOGIC_HPP
#include <llarp/mem.h>
#include <llarp/threadpool.h>
#include <llarp/timer.h>
#include <llarp/timer.hpp>
struct llarp_logic
{

@ -11,5 +11,7 @@
#include <llarp/messages/relay_commit.hpp>
#include <llarp/messages/discard.hpp>
#include <llarp/messages/path_confirm.hpp>
#include <llarp/messages/exit.hpp>
#include <llarp/messages/transfer_traffic.hpp>
#endif

@ -0,0 +1,225 @@
#ifndef LLARP_MESSAGES_EXIT_HPP
#define LLARP_MESSAGES_EXIT_HPP
#include <llarp/routing/message.hpp>
#include <llarp/exit/policy.hpp>
#include <vector>
#include <llarp/crypto.hpp>
namespace llarp
{
namespace routing
{
struct ObtainExitMessage final : public IMessage
{
std::vector< llarp::exit::Policy > B;
uint64_t E;
llarp::PubKey I;
uint64_t T;
std::vector< llarp::exit::Policy > W;
llarp_time_t X;
llarp::Signature Z;
ObtainExitMessage() : IMessage()
{
}
~ObtainExitMessage()
{
}
ObtainExitMessage&
operator=(const ObtainExitMessage& other);
/// populates I and signs
bool
Sign(llarp_crypto* c, const llarp::SecretKey& sk);
bool
Verify(llarp_crypto* c) const;
bool
BEncode(llarp_buffer_t* buf) const override;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) override;
bool
HandleMessage(IMessageHandler* h, llarp_router* r) const override;
};
struct GrantExitMessage final : public IMessage
{
using Nonce_t = llarp::AlignedBuffer< 16 >;
uint64_t T;
Nonce_t Y;
llarp::Signature Z;
GrantExitMessage() : IMessage()
{
}
~GrantExitMessage()
{
}
GrantExitMessage&
operator=(const GrantExitMessage& other);
bool
BEncode(llarp_buffer_t* buf) const override;
bool
Sign(llarp_crypto* c, const llarp::SecretKey& sk);
bool
Verify(llarp_crypto* c, const llarp::PubKey& pk) const;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) override;
bool
HandleMessage(IMessageHandler* h, llarp_router* r) const override;
};
struct RejectExitMessage final : public IMessage
{
using Nonce_t = llarp::AlignedBuffer< 16 >;
uint64_t B;
std::vector< llarp::exit::Policy > R;
uint64_t T;
Nonce_t Y;
llarp::Signature Z;
RejectExitMessage() : IMessage()
{
}
~RejectExitMessage()
{
}
RejectExitMessage&
operator=(const RejectExitMessage& other);
bool
Sign(llarp_crypto* c, const llarp::SecretKey& sk);
bool
Verify(llarp_crypto* c, const llarp::PubKey& pk) const;
bool
BEncode(llarp_buffer_t* buf) const override;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) override;
bool
HandleMessage(IMessageHandler* h, llarp_router* r) const override;
};
struct UpdateExitVerifyMessage final : public IMessage
{
using Nonce_t = llarp::AlignedBuffer< 16 >;
uint64_t T;
Nonce_t Y;
llarp::Signature Z;
UpdateExitVerifyMessage() : IMessage()
{
}
~UpdateExitVerifyMessage()
{
}
UpdateExitVerifyMessage&
operator=(const UpdateExitVerifyMessage& other);
bool
Sign(llarp_crypto* c, const llarp::SecretKey& sk);
bool
Verify(llarp_crypto* c, const llarp::PubKey& pk) const;
bool
BEncode(llarp_buffer_t* buf) const override;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) override;
bool
HandleMessage(IMessageHandler* h, llarp_router* r) const override;
};
struct UpdateExitMessage final : public IMessage
{
using Nonce_t = llarp::AlignedBuffer< 16 >;
llarp::PathID_t P;
uint64_t T;
Nonce_t Y;
llarp::Signature Z;
UpdateExitMessage() : IMessage()
{
}
~UpdateExitMessage()
{
}
UpdateExitMessage&
operator=(const UpdateExitMessage& other);
bool
Sign(llarp_crypto* c, const llarp::SecretKey& sk);
bool
Verify(llarp_crypto* c, const llarp::PubKey& pk) const;
bool
BEncode(llarp_buffer_t* buf) const override;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) override;
bool
HandleMessage(IMessageHandler* h, llarp_router* r) const override;
};
struct CloseExitMessage final : public IMessage
{
using Nonce_t = llarp::AlignedBuffer< 16 >;
Nonce_t Y;
llarp::Signature Z;
CloseExitMessage() : IMessage()
{
}
~CloseExitMessage()
{
}
CloseExitMessage&
operator=(const CloseExitMessage& other);
bool
BEncode(llarp_buffer_t* buf) const override;
bool
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf) override;
bool
HandleMessage(IMessageHandler* h, llarp_router* r) const override;
bool
Sign(llarp_crypto* c, const llarp::SecretKey& sk);
bool
Verify(llarp_crypto* c, const llarp::PubKey& pk) const;
};
} // namespace routing
} // namespace llarp
#endif

@ -0,0 +1,44 @@
#ifndef LLARP_MESSAGES_TRANSFER_TRAFFIC_HPP
#define LLARP_MESSAGES_TRANSFER_TRAFFIC_HPP
#include <llarp/routing/message.hpp>
#include <llarp/crypto.hpp>
#include <vector>
namespace llarp
{
namespace routing
{
constexpr size_t MaxExitMTU = 1500;
struct TransferTrafficMessage final : public IMessage
{
using Nonce_t = AlignedBuffer< 16 >;
std::vector< byte_t > X;
Nonce_t Y;
llarp::Signature Z;
TransferTrafficMessage&
operator=(const TransferTrafficMessage& other);
bool
PutBuffer(llarp_buffer_t buf);
bool
Sign(llarp_crypto* c, const llarp::SecretKey& sk);
bool
Verify(llarp_crypto* c, const llarp::PubKey& pk) const;
bool
BEncode(llarp_buffer_t* buf) const override;
bool
DecodeKey(llarp_buffer_t k, llarp_buffer_t* val) override;
bool
HandleMessage(IMessageHandler* h, llarp_router* r) const override;
};
} // namespace routing
} // namespace llarp
#endif

@ -3,21 +3,6 @@
#if defined(_WIN32) || defined(__MINGW32__)
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
// because this shit is not defined for Windows NT reeeee
#ifdef __cplusplus
extern "C"
{
#endif
#if _WIN32_WINNT < 0x600
const char*
inet_ntop(int af, const void* src, char* dst, size_t size);
int
inet_pton(int af, const char* src, void* dst);
#endif
#ifdef __cplusplus
}
#endif
typedef unsigned short in_port_t;
typedef unsigned int in_addr_t;
#else

@ -19,7 +19,6 @@
#else
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
#define inet_aton(x, y) inet_pton(AF_INET, x, y)
#endif

@ -1,6 +1,6 @@
#ifndef LLARP_NODEDB_HPP
#define LLARP_NODEDB_HPP
#include <llarp/common.h>
#include <llarp/common.hpp>
#include <llarp/crypto.h>
#include <llarp/router_contact.hpp>
#include <llarp/router_id.hpp>
@ -144,6 +144,10 @@ struct llarp_async_load_rc
void
llarp_nodedb_async_load_rc(struct llarp_async_load_rc *job);
bool
llarp_nodedb_select_random_exit(struct llarp_nodedb *n,
llarp::RouterContact &rc);
bool
llarp_nodedb_select_random_hop(struct llarp_nodedb *n,
const llarp::RouterContact &prev,

@ -1,7 +1,7 @@
#ifndef LLARP_PATH_HPP
#define LLARP_PATH_HPP
#include <llarp/router.h>
#include <llarp/time.h>
#include <llarp/time.hpp>
#include <llarp/aligned.hpp>
#include <llarp/crypto.hpp>
#include <llarp/dht.hpp>
@ -104,9 +104,13 @@ namespace llarp
virtual bool
Expired(llarp_time_t now) const = 0;
virtual bool
ExpiresSoon(llarp_time_t now, llarp_time_t dlt) const = 0;
/// send routing message and increment sequence number
virtual bool
SendRoutingMessage(llarp::routing::IMessage* msg, llarp_router* r) = 0;
SendRoutingMessage(const llarp::routing::IMessage* msg,
llarp_router* r) = 0;
// handle data in upstream direction
virtual bool
@ -118,6 +122,12 @@ namespace llarp
HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y,
llarp_router* r) = 0;
uint64_t
NextSeqNo()
{
return m_SequenceNum++;
}
protected:
uint64_t m_SequenceNum = 0;
};
@ -155,11 +165,18 @@ namespace llarp
}
bool
Expired(llarp_time_t now) const;
Expired(llarp_time_t now) const override;
bool
ExpiresSoon(llarp_time_t now, llarp_time_t dlt) const override
{
return now >= ExpireTime() - dlt;
}
// send routing message when end of path
bool
SendRoutingMessage(llarp::routing::IMessage* msg, llarp_router* r);
SendRoutingMessage(const llarp::routing::IMessage* msg,
llarp_router* r) override;
// handle routing message when end of path
bool
@ -168,21 +185,50 @@ namespace llarp
bool
HandleDataDiscardMessage(const llarp::routing::DataDiscardMessage* msg,
llarp_router* r);
llarp_router* r) override;
bool
HandlePathConfirmMessage(const llarp::routing::PathConfirmMessage* msg,
llarp_router* r);
llarp_router* r) override;
bool
HandlePathTransferMessage(const llarp::routing::PathTransferMessage* msg,
llarp_router* r);
llarp_router* r) override;
bool
HandlePathLatencyMessage(const llarp::routing::PathLatencyMessage* msg,
llarp_router* r);
llarp_router* r) override;
bool
HandleObtainExitMessage(const llarp::routing::ObtainExitMessage* msg,
llarp_router* r) override;
bool
HandleUpdateExitVerifyMessage(
const llarp::routing::UpdateExitVerifyMessage* msg,
llarp_router* r) override;
bool
HandleTransferTrafficMessage(
const llarp::routing::TransferTrafficMessage* msg,
llarp_router* r) override;
bool
HandleUpdateExitMessage(const llarp::routing::UpdateExitMessage* msg,
llarp_router* r) override;
bool
HandleGrantExitMessage(const llarp::routing::GrantExitMessage* msg,
llarp_router* r) override;
bool
HandleRejectExitMessage(const llarp::routing::RejectExitMessage* msg,
llarp_router* r) override;
bool
HandleHiddenServiceFrame(__attribute__((unused))
const llarp::service::ProtocolFrame* frame)
HandleCloseExitMessage(const llarp::routing::CloseExitMessage* msg,
llarp_router* r) override;
bool
HandleHiddenServiceFrame(__attribute__((
unused)) const llarp::service::ProtocolFrame* frame) override
{
/// TODO: implement me
llarp::LogWarn("Got hidden service data on transit hop");
@ -193,15 +239,18 @@ namespace llarp
HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg);
bool
HandleDHTMessage(const llarp::dht::IMessage* msg, llarp_router* r);
HandleDHTMessage(const llarp::dht::IMessage* msg,
llarp_router* r) override;
// handle data in upstream direction
bool
HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y,
llarp_router* r) override;
// handle data in downstream direction
bool
HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y,
llarp_router* r) override;
};
/// configuration for a single hop when building a path
@ -238,6 +287,12 @@ namespace llarp
typedef std::vector< PathHopConfig > HopList;
typedef std::function< bool(Path*, const service::ProtocolFrame*) >
DataHandlerFunc;
typedef std::function< bool(Path*) > ExitUpdatedFunc;
typedef std::function< bool(Path*) > ExitClosedFunc;
typedef std::function< bool(Path*, llarp_buffer_t) >
ExitTrafficHandlerFunc;
/// (path, backoff) backoff is 0 on success
typedef std::function< bool(Path*, llarp_time_t) > ObtainedExitHandler;
HopList hops;
@ -246,13 +301,55 @@ namespace llarp
llarp::service::Introduction intro;
llarp_time_t buildStarted;
PathStatus _status;
Path(const std::vector< RouterContact >& routers, PathSet* parent);
Path(const std::vector< RouterContact >& routers, PathSet* parent,
PathRole startingRoles);
PathRole
Role() const
{
return _role;
}
void
MarkActive(llarp_time_t now)
{
m_LastRecvMessage = now;
}
bool
SupportsRoles(PathRole roles) const
{
return (_role & roles) == roles;
}
PathStatus
Status() const
{
return _status;
}
void
SetBuildResultHook(BuildResultHookFunc func);
void
SetExitTrafficHandler(ExitTrafficHandlerFunc handler)
{
m_ExitTrafficHandler = handler;
}
void
SetCloseExitFunc(ExitClosedFunc handler)
{
m_ExitClosed = handler;
}
void
SetUpdateExitFunc(ExitUpdatedFunc handler)
{
m_ExitUpdated = handler;
}
void
SetDataHandler(DataHandlerFunc func)
{
@ -281,49 +378,88 @@ namespace llarp
}
bool
Expired(llarp_time_t now) const;
ExpiresSoon(llarp_time_t now, llarp_time_t dlt = 5000) const override
{
return now >= (ExpireTime() - dlt);
}
bool
Expired(llarp_time_t now) const override;
void
Tick(llarp_time_t now, llarp_router* r);
bool
SendRoutingMessage(llarp::routing::IMessage* msg, llarp_router* r);
SendRoutingMessage(const llarp::routing::IMessage* msg,
llarp_router* r) override;
bool
HandleObtainExitMessage(const llarp::routing::ObtainExitMessage* msg,
llarp_router* r) override;
bool
HandleUpdateExitVerifyMessage(
const llarp::routing::UpdateExitVerifyMessage* msg,
llarp_router* r) override;
bool
HandleTransferTrafficMessage(
const llarp::routing::TransferTrafficMessage* msg,
llarp_router* r) override;
bool
HandleUpdateExitMessage(const llarp::routing::UpdateExitMessage* msg,
llarp_router* r) override;
bool
HandleCloseExitMessage(const llarp::routing::CloseExitMessage* msg,
llarp_router* r) override;
bool
HandleGrantExitMessage(const llarp::routing::GrantExitMessage* msg,
llarp_router* r) override;
bool
HandleRejectExitMessage(const llarp::routing::RejectExitMessage* msg,
llarp_router* r) override;
bool
HandleDataDiscardMessage(const llarp::routing::DataDiscardMessage* msg,
llarp_router* r);
llarp_router* r) override;
bool
HandlePathConfirmMessage(const llarp::routing::PathConfirmMessage* msg,
llarp_router* r);
llarp_router* r) override;
bool
HandlePathLatencyMessage(const llarp::routing::PathLatencyMessage* msg,
llarp_router* r);
llarp_router* r) override;
bool
HandlePathTransferMessage(const llarp::routing::PathTransferMessage* msg,
llarp_router* r);
llarp_router* r) override;
bool
HandleHiddenServiceFrame(const llarp::service::ProtocolFrame* frame);
HandleHiddenServiceFrame(
const llarp::service::ProtocolFrame* frame) override;
bool
HandleGotIntroMessage(const llarp::dht::GotIntroMessage* msg);
bool
HandleDHTMessage(const llarp::dht::IMessage* msg, llarp_router* r);
HandleDHTMessage(const llarp::dht::IMessage* msg,
llarp_router* r) override;
bool
HandleRoutingMessage(llarp_buffer_t buf, llarp_router* r);
// handle data in upstream direction
bool
HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
HandleUpstream(llarp_buffer_t X, const TunnelNonce& Y,
llarp_router* r) override;
// handle data in downstream direction
bool
HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y, llarp_router* r);
HandleDownstream(llarp_buffer_t X, const TunnelNonce& Y,
llarp_router* r) override;
bool
IsReady() const;
@ -348,17 +484,40 @@ namespace llarp
std::string
Name() const;
void
AddObtainExitHandler(ObtainedExitHandler handler)
{
m_ObtainedExitHooks.push_back(handler);
}
bool
SendExitRequest(const llarp::routing::ObtainExitMessage* msg,
llarp_router* r);
protected:
llarp::routing::InboundMessageParser m_InboundMessageParser;
private:
/// call obtained exit hooks
bool
InformExitResult(llarp_time_t b);
BuildResultHookFunc m_BuiltHook;
DataHandlerFunc m_DataHandler;
DropHandlerFunc m_DropHandler;
CheckForDeadFunc m_CheckForDead;
ExitUpdatedFunc m_ExitUpdated;
ExitClosedFunc m_ExitClosed;
ExitTrafficHandlerFunc m_ExitTrafficHandler;
std::vector< ObtainedExitHandler > m_ObtainedExitHooks;
llarp_time_t m_LastRecvMessage = 0;
llarp_time_t m_LastLatencyTestTime = 0;
uint64_t m_LastLatencyTestID = 0;
uint64_t m_UpdateExitTX = 0;
uint64_t m_CloseExitTX = 0;
uint64_t m_ExitObtainTX = 0;
PathStatus _status;
PathRole _role;
};
enum PathBuildStatus
@ -392,6 +551,7 @@ namespace llarp
void
AllowTransit();
void
RejectTransit();

@ -26,7 +26,7 @@ namespace llarp
virtual bool
SelectHop(llarp_nodedb* db, const RouterContact& prev, RouterContact& cur,
size_t hop);
size_t hop, PathRole roles);
virtual bool
ShouldBuildMore(llarp_time_t now) const;
@ -35,16 +35,18 @@ namespace llarp
Now() const;
void
BuildOne();
BuildOne(PathRole roles = ePathRoleAny);
void
Build(const std::vector< RouterContact >& hops);
Build(const std::vector< RouterContact >& hops,
PathRole roles = ePathRoleAny);
bool
SelectHops(llarp_nodedb* db, std::vector< RouterContact >& hops);
SelectHops(llarp_nodedb* db, std::vector< RouterContact >& hops,
PathRole roles = ePathRoleAny);
void
ManualRebuild(size_t N);
ManualRebuild(size_t N, PathRole roles = ePathRoleAny);
virtual const byte_t*
GetTunnelEncryptionSecretKey() const;

@ -1,6 +1,6 @@
#ifndef LLARP_PATHSET_HPP
#define LLARP_PATHSET_HPP
#include <llarp/time.h>
#include <llarp/time.hpp>
#include <functional>
#include <list>
#include <llarp/path_types.hpp>
@ -21,6 +21,7 @@ namespace llarp
namespace path
{
/// status of a path
enum PathStatus
{
ePathBuilding,
@ -28,6 +29,21 @@ namespace llarp
ePathTimeout,
ePathExpired
};
/// the role of this path can fuffill
using PathRole = int;
/// capable of any role
constexpr PathRole ePathRoleAny = 0;
/// outbound hs traffic capabale
constexpr PathRole ePathRoleOutboundHS = (1 << 0);
/// inbound hs traffic capable
constexpr PathRole ePathRoleInboundHS = (1 << 1);
/// exit traffic capable
constexpr PathRole ePathRoleExit = (1 << 2);
/// dht message capable
constexpr PathRole ePathRoleDHT = (1 << 3);
// forward declare
struct Path;
@ -63,9 +79,14 @@ namespace llarp
void
ExpirePaths(llarp_time_t now);
/// get the number of paths in this status
size_t
NumInStatus(PathStatus st) const;
/// get the number of paths that match the role that are available
size_t
AvailablePaths(PathRole role) const;
/// get time from event loop
virtual llarp_time_t
Now() const = 0;
@ -74,6 +95,14 @@ namespace llarp
virtual bool
ShouldBuildMore(llarp_time_t now) const;
/// return true if we need another path with the given path roles
virtual bool
ShouldBuildMoreForRoles(llarp_time_t now, PathRole roles) const;
/// return the minimum number of paths we want for given roles
virtual size_t
MinRequiredForRoles(PathRole roles) const;
/// return true if we should publish a new hidden service descriptor
virtual bool
ShouldPublishDescriptors(__attribute__((unused)) llarp_time_t now) const
@ -104,16 +133,19 @@ namespace llarp
}
Path*
GetEstablishedPathClosestTo(const RouterID& router) const;
GetEstablishedPathClosestTo(const RouterID& router,
PathRole roles = ePathRoleAny) const;
Path*
PickRandomEstablishedPath() const;
PickRandomEstablishedPath(PathRole roles = ePathRoleAny) const;
Path*
GetPathByRouter(const RouterID& router) const;
GetPathByRouter(const RouterID& router,
PathRole roles = ePathRoleAny) const;
Path*
GetNewestPathByRouter(const RouterID& router) const;
GetNewestPathByRouter(const RouterID& router,
PathRole roles = ePathRoleAny) const;
Path*
GetPathByID(const PathID_t& id) const;
@ -136,7 +168,7 @@ namespace llarp
virtual bool
SelectHop(llarp_nodedb* db, const RouterContact& prev, RouterContact& cur,
size_t hop) = 0;
size_t hop, PathRole roles) = 0;
protected:
size_t m_NumPaths;

@ -1,5 +1,5 @@
#ifndef LLARP_PROTO_H
#define LLARP_PROTO_H
#ifndef LLARP_PROTO_HPP
#define LLARP_PROTO_HPP
#ifndef LLARP_PROTO_VERSION
#define LLARP_PROTO_VERSION (0)

@ -2,7 +2,7 @@
#define LLARP_ROUTER_H_
#include <llarp/config.h>
#include <llarp/ev.h>
#include <llarp/logic.h>
#include <llarp/logic.hpp>
#include <llarp/threadpool.h>
#include <llarp/buffer.h>

@ -53,6 +53,12 @@ namespace llarp
void
Clear();
bool
IsExit() const
{
return exits.size() > 0;
}
bool
BDecode(llarp_buffer_t *buf) override
{

@ -7,8 +7,9 @@
#include <llarp/messages/path_confirm.hpp>
#include <llarp/messages/path_latency.hpp>
#include <llarp/messages/path_transfer.hpp>
#include <llarp/messages/exit.hpp>
#include <llarp/messages/transfer_traffic.hpp>
namespace llarp
{
@ -19,6 +20,32 @@ namespace llarp
// handles messages on the routing level
struct IMessageHandler
{
virtual bool
HandleObtainExitMessage(const ObtainExitMessage *msg,
llarp_router *r) = 0;
virtual bool
HandleGrantExitMessage(const GrantExitMessage *msg, llarp_router *r) = 0;
virtual bool
HandleRejectExitMessage(const RejectExitMessage *msg,
llarp_router *r) = 0;
virtual bool
HandleTransferTrafficMessage(const TransferTrafficMessage *msg,
llarp_router *r) = 0;
virtual bool
HandleUpdateExitMessage(const UpdateExitMessage *msg,
llarp_router *r) = 0;
virtual bool
HandleUpdateExitVerifyMessage(const UpdateExitVerifyMessage *msg,
llarp_router *r) = 0;
virtual bool
HandleCloseExitMessage(const CloseExitMessage *msg, llarp_router *r) = 0;
virtual bool
HandleDataDiscardMessage(const DataDiscardMessage *msg,
llarp_router *r) = 0;

@ -1,6 +1,6 @@
#ifndef LLARP_RPC_HPP
#define LLARP_RPC_HPP
#include <llarp/time.h>
#include <llarp/time.hpp>
#include <llarp/ev.h>
#include <string>
#include <functional>
@ -40,10 +40,10 @@ namespace llarp
bool
Start(const std::string& remote);
/// async test if a router is valid via jsonrpc
/// test if a router is valid
void
AsyncVerifyRouter(llarp::PubKey pkey,
std::function< void(llarp::PubKey, bool) > handler);
VerifyRouter(llarp::PubKey pkey,
std::function< void(llarp::PubKey, bool) > handler);
private:
CallerImpl* m_Impl;

@ -1,6 +1,6 @@
#ifndef LLARP_SERVICE_INTROSET_HPP
#define LLARP_SERVICE_INTROSET_HPP
#include <llarp/time.h>
#include <llarp/time.hpp>
#include <iostream>
#include <llarp/bencode.hpp>
#include <llarp/crypto.hpp>

@ -22,6 +22,11 @@ namespace llarp
Zero();
}
Address(const byte_t* buf)
{
memcpy(b, buf, 32);
}
Address(const Address& other)
{
memcpy(b, other.b, 32);

@ -18,7 +18,7 @@ namespace llarp
~Context();
void
Tick();
Tick(llarp_time_t now);
bool
hasEndpoints();

@ -7,6 +7,8 @@
#include <llarp/service/protocol.hpp>
#include <llarp/path.hpp>
#include <llarp/ev.h>
#include <llarp/net.hpp>
#include <llarp/exit/session.hpp>
// minimum time between interoset shifts
#ifndef MIN_SHIFT_INTERVAL
@ -78,7 +80,7 @@ namespace llarp
return false;
}
std::string
virtual std::string
Name() const;
bool
@ -108,15 +110,16 @@ namespace llarp
HasPathToService(const Address& remote) const;
virtual huint32_t
ObtainIPForAddr(__attribute__((unused))
const llarp::service::Address& remote)
ObtainIPForAddr(const byte_t * addr)
{
(void) addr;
return {0};
}
virtual bool
HasAddress(__attribute__((unused)) const Address& remote) const
HasAddress(const byte_t* addr) const
{
(void)addr;
return false;
}
@ -139,6 +142,9 @@ namespace llarp
return true;
}
bool
HandleDataMessage(const PathID_t&);
/// ensure that we know a router, looks up if it doesn't
void
EnsureRouterIsKnown(const RouterID& router);
@ -156,8 +162,7 @@ namespace llarp
HandlePathBuilt(path::Path* path);
bool
SendToOrQueue(const Address& remote, llarp_buffer_t payload,
ProtocolType t);
SendToOrQueue(const byte_t* addr, llarp_buffer_t payload, ProtocolType t);
struct PendingBuffer
{
@ -250,18 +255,18 @@ namespace llarp
/// update the current selected intro to be a new best introduction
/// return true if we have changed intros
bool
ShiftIntroduction();
ShiftIntroduction() override;
/// mark the current remote intro as bad
bool
MarkCurrentIntroBad(llarp_time_t now);
MarkCurrentIntroBad(llarp_time_t now) override;
/// return true if we are ready to send
bool
ReadyToSend() const;
bool
ShouldBuildMore(llarp_time_t now) const;
ShouldBuildMore(llarp_time_t now) const override;
/// tick internal state
/// return true to mark as dead
@ -276,21 +281,22 @@ namespace llarp
CheckPathIsDead(path::Path* p, llarp_time_t dlt);
void
AsyncGenIntro(llarp_buffer_t payload, ProtocolType t);
AsyncGenIntro(llarp_buffer_t payload, ProtocolType t) override;
/// issues a lookup to find the current intro set of the remote service
void
UpdateIntroSet(bool randomizePath);
UpdateIntroSet(bool randomizePath) override;
bool
BuildOneAlignedTo(const RouterID& remote);
void
HandlePathBuilt(path::Path* path);
HandlePathBuilt(path::Path* path) override;
bool
SelectHop(llarp_nodedb* db, const RouterContact& prev,
RouterContact& cur, size_t hop);
RouterContact& cur, size_t hop,
llarp::path::PathRole roles) override;
bool
HandleHiddenServiceFrame(path::Path* p, const ProtocolFrame* frame);
@ -328,14 +334,6 @@ namespace llarp
EnsurePathToService(const Address& remote, PathEnsureHook h,
uint64_t timeoutMS, bool lookupOnRandomPath = false);
virtual bool
HandleAuthenticatedDataFrom(__attribute__((unused)) const Address& remote,
__attribute__((unused)) llarp_buffer_t data)
{
/// TODO: imlement me
return true;
}
void
PutSenderFor(const ConvoTag& tag, const ServiceInfo& info);
@ -420,6 +418,7 @@ namespace llarp
protected:
IDataHandler* m_DataHandler = nullptr;
Identity m_Identity;
std::unique_ptr< llarp::exit::BaseSession > m_Exit;
private:
llarp_router* m_Router;

@ -1,6 +1,6 @@
#ifndef LLARP_SERVICE_PROTOCOL_HPP
#define LLARP_SERVICE_PROTOCOL_HPP
#include <llarp/time.h>
#include <llarp/time.hpp>
#include <llarp/bencode.hpp>
#include <llarp/crypto.hpp>
#include <llarp/encrypted.hpp>

@ -1,6 +1,6 @@
#ifndef LLARP_STRING_H
#define LLARP_STRING_H
#include <llarp/common.h>
#include <llarp/common.hpp>
#ifndef __FreeBSD__
#if !(__APPLE__ && __MACH__)

@ -15,6 +15,7 @@
#endif
#include <future>
#include <memory>
#include <cassert>
namespace llarp
{
@ -87,6 +88,115 @@ namespace llarp
}
};
class Semaphore
{
private:
std::mutex m_mutex;
std::condition_variable m_cv;
size_t m_count;
public:
Semaphore(size_t count) : m_count(count)
{
}
void
notify()
{
std::unique_lock< std::mutex > lock(m_mutex);
m_count++;
m_cv.notify_one();
}
void
wait()
{
std::unique_lock< std::mutex > lock(m_mutex);
m_cv.wait(lock, [this]() { return this->m_count > 0; });
m_count--;
}
template < typename Rep, typename Period >
bool
waitFor(const std::chrono::duration< Rep, Period >& period)
{
std::unique_lock< std::mutex > lock(m_mutex);
if(m_cv.wait_for(lock, period, [this]() { return this->m_count > 0; }))
{
m_count--;
return true;
}
return false;
}
};
class Barrier
{
private:
std::mutex mutex;
std::condition_variable cv;
const size_t numThreads;
size_t numThreadsWaiting; // number of threads to be woken
size_t sigCount; // number of times the barrier has been signalled
size_t numPending; // number of threads that have been signalled, but
// haven't woken.
public:
Barrier(size_t threadCount)
: numThreads(threadCount)
, numThreadsWaiting(0)
, sigCount(0)
, numPending(0)
{
}
~Barrier()
{
for(;;)
{
{
std::unique_lock< std::mutex > lock(mutex);
if(numPending == 0)
{
break;
}
}
std::this_thread::yield();
}
assert(numThreadsWaiting == 0);
}
void
wait()
{
std::unique_lock< std::mutex > lock(mutex);
size_t signalCount = sigCount;
if(++numThreadsWaiting == numThreads)
{
++sigCount;
numPending += numThreads - 1;
numThreadsWaiting = 0;
cv.notify_all();
}
else
{
cv.wait(lock, [this, signalCount]() {
return this->sigCount != signalCount;
});
--numPending;
}
}
};
} // namespace util
} // namespace llarp

@ -48,6 +48,8 @@ llarp_threadpool_tick(struct llarp_threadpool *tp);
void
llarp_threadpool_queue_job(struct llarp_threadpool *tp,
struct llarp_thread_job j);
void
llarp_threadpool_start(struct llarp_threadpool *tp);
void
llarp_threadpool_stop(struct llarp_threadpool *tp);

@ -1,8 +0,0 @@
#ifndef LLARP_TIME_H
#define LLARP_TIME_H
#include <llarp/types.h>
llarp_time_t
llarp_time_now_ms();
#endif

@ -1,11 +1,16 @@
#ifndef LLARP_TIME_HPP
#define LLARP_TIME_HPP
#include <llarp/types.hpp>
#include <chrono>
namespace llarp
{
typedef std::chrono::system_clock Clock_t;
}
using Clock_t = std::chrono::system_clock;
llarp_time_t
time_now_ms();
} // namespace llarp
#endif

@ -1,8 +1,9 @@
#ifndef LLARP_TIMER_H
#define LLARP_TIMER_H
#include <llarp/common.h>
#ifndef LLARP_TIMER_HPP
#define LLARP_TIMER_HPP
#include <llarp/common.hpp>
#include <llarp/threadpool.h>
#include <llarp/time.h>
#include <llarp/time.hpp>
/** called with userptr, original timeout, left */
typedef void (*llarp_timer_handler_func)(void *, uint64_t, uint64_t);

@ -1,9 +0,0 @@
#ifndef LLARP_TYPES_H
#define LLARP_TYPES_H
#include <stdint.h>
typedef uint8_t llarp_proto_version_t;
typedef uint64_t llarp_time_t;
typedef uint64_t llarp_seconds_t;
#endif

@ -0,0 +1,9 @@
#ifndef LLARP_TYPES_H
#define LLARP_TYPES_H
#include <cstdint>
using llarp_proto_version_t = std::uint8_t;
using llarp_time_t = std::uint64_t;
using llarp_seconds_t = std::uint64_t;
#endif

@ -1,5 +1,5 @@
#ifndef LLARP_VERSION_H
#define LLARP_VERSION_H
#ifndef LLARP_VERSION_HPP
#define LLARP_VERSION_HPP
#ifndef LLARP_VERSION_MAJ
#define LLARP_VERSION_MAJ "0"
@ -28,4 +28,5 @@
#ifndef LLARP_RELEASE_MOTTO
#define LLARP_RELEASE_MOTTO "(dev build)"
#endif
#endif

File diff suppressed because it is too large Load Diff

@ -2,12 +2,12 @@
#define __ABYSS_SERVER_HPP__
#include <llarp/ev.h>
#include <llarp/logic.h>
#include <llarp/time.h>
#include <llarp/logic.hpp>
#include <llarp/string_view.hpp>
#include <llarp/time.hpp>
#include <list>
#include <memory>
#include <string>
#include <llarp/string_view.hpp>
#include <abyss/json.hpp>
#include <unordered_map>

@ -1,6 +1,6 @@
#include <abyss/server.hpp>
#include <abyss/http.hpp>
#include <llarp/time.h>
#include <llarp/time.hpp>
#include <sstream>
#include <unordered_map>
#include <string>

@ -25,23 +25,8 @@
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
#include "libutp_inet_ntop.h"
// we already have our own definition of these
// -despair
#ifndef inet_ntop
namespace
{
extern "C"
{
const char *
inet_ntop(int af, const void *src, char *dst, size_t size);
int
inet_pton(int af, const char *src, void *dst);
}
} // namespace
#endif
//######################################################################
const char *
libutp::inet_ntop(int af, const void *src, char *dest, size_t length)

@ -1,5 +1,5 @@
#include <llarp/buffer.h>
#include <llarp/endian.h>
#include <llarp/endian.hpp>
#include <stdarg.h>
#include <stdio.h>

@ -1,6 +1,6 @@
#include "config.hpp"
#include <llarp/config.h>
#include <llarp/defaults.h>
#include <llarp/defaults.hpp>
#include <llarp/net.hpp>
#include "fs.hpp"
#include "ini.hpp"
@ -190,6 +190,13 @@ llarp_ensure_router_config(std::ofstream &f, std::string basepath)
f << "# network settings " << std::endl;
f << "[network]" << std::endl;
f << "profiles=" << basepath << "profiles.dat" << std::endl;
f << "ifaddr=10.105.0.1/16" << std::endl;
f << "ifname=lokitun0" << std::endl;
f << "enabled=true" << std::endl;
f << "exit=false" << std::endl;
f << "# exit-blacklist=tcp:25" << std::endl;
f << "# exit-whitelist=tcp:*" << std::endl;
f << "# exit-whitelist=udp:*" << std::endl;
f << std::endl;
f << "# ROUTERS ONLY: publish network interfaces for handling inbound traffic"
<< std::endl;

@ -679,6 +679,8 @@ namespace llarp
Key_t t(target.data());
std::set< Key_t > found;
// TODO: also load from nodedb
if(!nodes)
return false;
size_t nodeCount = nodes->Size();
if(nodeCount == 0)
{

@ -1,4 +1,4 @@
#include <llarp/endian.h>
#include <llarp/endian.hpp>
#include <llarp/dnsd.hpp> // for llarp_handle_dnsd_recvfrom, dnsc
#include <llarp/logger.hpp>

@ -231,19 +231,19 @@ ReverseHandlerIter(struct llarp::service::Context::endpoint_iter *endpointCfg)
llarp::LogDebug(searchIp, " vs ", checkIp);
llarp::IPRange range = llarp::iprange_ipv4(
stoi(tokensCheck[0]), stoi(tokensCheck[1]), stoi(tokensCheck[2]),
stoi(tokensCheck[3]), tunEndpoint->tunif.netmask); // create range
std::stoi(tokensCheck[0]), std::stoi(tokensCheck[1]), std::stoi(tokensCheck[2]),
std::stoi(tokensCheck[3]), tunEndpoint->tunif.netmask); // create range
// hack atm to work around limitations in ipaddr_ipv4_bits and llarp::IPRange
llarp::huint32_t searchIPv4_fixed = llarp::ipaddr_ipv4_bits(
stoi(tokensSearch[searchTokens - 6]),
stoi(tokensSearch[searchTokens - 5]),
stoi(tokensSearch[searchTokens - 4]),
stoi(tokensSearch[searchTokens - 3])); // create ip
std::stoi(tokensSearch[searchTokens - 6]),
std::stoi(tokensSearch[searchTokens - 5]),
std::stoi(tokensSearch[searchTokens - 4]),
std::stoi(tokensSearch[searchTokens - 3])); // create ip
llarp::huint32_t searchIPv4_search = llarp::ipaddr_ipv4_bits(
stoi(tokensSearch[searchTokens - 3]),
stoi(tokensSearch[searchTokens - 4]),
stoi(tokensSearch[searchTokens - 5]),
stoi(tokensSearch[searchTokens - 6])); // create ip
std::stoi(tokensSearch[searchTokens - 3]),
std::stoi(tokensSearch[searchTokens - 4]),
std::stoi(tokensSearch[searchTokens - 5]),
std::stoi(tokensSearch[searchTokens - 6])); // create ip
// bool inRange = range.Contains(searchAddr.xtohl());
bool inRange = range.Contains(searchIPv4_search);
@ -256,7 +256,8 @@ ReverseHandlerIter(struct llarp::service::Context::endpoint_iter *endpointCfg)
if(inRange)
{
llarp::service::Address addr =
tunEndpoint->ObtainAddrForIP(searchIPv4_fixed);
tunEndpoint->ObtainAddrForIP< llarp::service::Address >(
searchIPv4_fixed);
if(addr.IsZero())
{
write404_dnss_response((dnsd_question_request *)context->request);

@ -313,7 +313,7 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
request->question.name, " at ", std::to_string(pos));
*/
// castBuf += answer->name.length() + 4 + 4 + 4 + answer->rdLen;
if(pos > sz)
if((ssize_t)pos > sz)
{
llarp::LogWarn("Would read past end of dns packet. for ",
request->question.name);
@ -330,6 +330,12 @@ generic_handle_dnsc_recvfrom(dnsc_answer_request *request,
llarp::LogDebug("Read an addl RR for ",
request->question.name, " at ", std::to_string(pos));
*/
if((ssize_t)pos > sz)
{
llarp::LogWarn("Would read past end of dns packet. for ",
request->question.name);
break;
}
}
/*
@ -656,7 +662,7 @@ llarp_handle_dnsc_recvfrom(struct llarp_udp_io *const udp,
llarp::LogDebug("Header got client responses for id: ", hdr->id);
// if we sent this out, then there's an id
struct dns_tracker *tracker = (struct dns_tracker *)udp->user;
struct dns_tracker *tracker = (struct dns_tracker *)udp->user;
struct dnsc_answer_request *request = tracker->client_request[hdr->id].get();
// sometimes we'll get double responses
@ -747,7 +753,7 @@ void
llarp_host_resolved(dnsc_answer_request *const request)
{
dns_tracker *tracker = (dns_tracker *)request->context->tracker;
auto val = std::find_if(
auto val = std::find_if(
tracker->client_request.begin(), tracker->client_request.end(),
[request](
std::pair< const uint32_t, std::unique_ptr< dnsc_answer_request > >
@ -788,7 +794,7 @@ llarp_dnsc_init(struct dnsc_context *const dnsc,
llarp::LogInfo("DNSc adding relay ", dnsc_sockaddr);
dnsc->resolvers.push_back(dnsc_sockaddr);
dnsc->tracker = &dns_udp_tracker;
dnsc->logic = logic;
dnsc->logic = logic;
return true;
}

@ -15,13 +15,15 @@ namespace llarp
return 0;
}
void
HexDecode(const char* src, uint8_t* target)
bool
HexDecode(const char* src, uint8_t* target, size_t sz)
{
while(*src && src[1])
while(*src && src[1] && sz)
{
*(target++) = char2int(*src) * 16 + char2int(src[1]);
src += 2;
--sz;
}
return sz == 0;
}
} // namespace llarp

@ -1,5 +1,5 @@
#include <llarp/ev.h>
#include <llarp/logic.h>
#include <llarp/logic.hpp>
#include <llarp/string_view.hpp>
#include <stddef.h>
@ -34,7 +34,7 @@ llarp_ev_loop_alloc(struct llarp_ev_loop **ev)
#error no event loop subclass
#endif
(*ev)->init();
(*ev)->_now = llarp_time_now_ms();
(*ev)->_now = llarp::time_now_ms();
}
void
@ -49,7 +49,7 @@ llarp_ev_loop_run(struct llarp_ev_loop *ev, struct llarp_logic *logic)
{
while(ev->running())
{
ev->_now = llarp_time_now_ms();
ev->_now = llarp::time_now_ms();
ev->tick(EV_TICK_INTERVAL);
if(ev->running())
llarp_logic_tick(logic, ev->_now);
@ -64,7 +64,7 @@ llarp_ev_loop_run_single_process(struct llarp_ev_loop *ev,
{
while(ev->running())
{
ev->_now = llarp_time_now_ms();
ev->_now = llarp::time_now_ms();
ev->tick(EV_TICK_INTERVAL);
if(ev->running())
{
@ -95,7 +95,9 @@ llarp_ev_close_udp(struct llarp_udp_io *udp)
llarp_time_t
llarp_ev_loop_time_now_ms(struct llarp_ev_loop *loop)
{
return loop->_now;
if(loop)
return loop->_now;
return llarp::time_now_ms();
}
void

@ -141,20 +141,13 @@ namespace llarp
virtual ssize_t
do_write(void* data, size_t sz)
{
DWORD w;
// DWORD w;
if(std::holds_alternative< HANDLE >(fd))
{
WriteFile(std::get< HANDLE >(fd), data, sz, nullptr, &portfd[1]);
GetOverlappedResult(std::get< HANDLE >(fd), &portfd[1], &w, TRUE);
}
else
{
WriteFile((HANDLE)std::get< SOCKET >(fd), data, sz, nullptr,
&portfd[1]);
GetOverlappedResult((HANDLE)std::get< SOCKET >(fd), &portfd[1], &w,
TRUE);
}
return w;
return sz;
}
bool
@ -246,6 +239,7 @@ namespace llarp
}
/// reset errno
errno = 0;
SetLastError(0);
}
std::unique_ptr< LossyWriteQueue_t > m_LossyWriteQueue;
@ -288,6 +282,20 @@ namespace llarp
}
};
struct GetNow
{
llarp_ev_loop* loop;
GetNow(llarp_ev_loop* l) : loop(l)
{
}
llarp_time_t
operator()() const
{
return llarp_ev_loop_time_now_ms(loop);
}
};
struct PutTime
{
llarp_ev_loop* loop;
@ -311,10 +319,10 @@ namespace llarp
};
};
typedef llarp::util::CoDelQueue< WriteBuffer, WriteBuffer::GetTime,
WriteBuffer::PutTime, WriteBuffer::Compare,
llarp::util::NullMutex,
llarp::util::NullLock, 5, 100, 128 >
typedef llarp::util::CoDelQueue<
WriteBuffer, WriteBuffer::GetTime, WriteBuffer::PutTime,
WriteBuffer::Compare, WriteBuffer::GetNow, llarp::util::NullMutex,
llarp::util::NullLock, 5, 100, 1024 >
LossyWriteQueue_t;
typedef std::deque< WriteBuffer > LosslessWriteQueue_t;

@ -177,7 +177,7 @@ namespace llarp
llarp_tun_io* t;
device* tunif;
tun(llarp_tun_io* tio, llarp_ev_loop* l)
: ev_io(-1, new LossyWriteQueue_t("tun_write_queue", l))
: ev_io(-1, new LossyWriteQueue_t("tun_write_queue", l, l))
, t(tio)
, tunif(tuntap_init())

@ -8,7 +8,6 @@
#if __FreeBSD__ || __OpenBSD__ || __NetBSD__ || (__APPLE__ && __MACH__)
// kqueue / kevent
#include <sys/event.h>
#include <sys/time.h>
#include <fcntl.h>
#endif

@ -8,6 +8,10 @@
#include "ev.hpp"
#include "logger.hpp"
#ifdef sizeof
#undef sizeof
#endif
// TODO: convert all socket errno calls to WSAGetLastError(3),
// don't think winsock sets regular errno to this day
namespace llarp
@ -62,7 +66,7 @@ namespace llarp
{
socklen_t slen = sizeof(sockaddr_in);
if(_addr.ss_family == AF_UNIX)
slen = sizeof(sockaddr_un);
slen = 115;
else if(_addr.ss_family == AF_INET6)
slen = sizeof(sockaddr_in6);
int result =
@ -132,13 +136,14 @@ namespace llarp
virtual int
read(void* buf, size_t sz)
{
printf("read\n");
sockaddr_in6 src;
socklen_t slen = sizeof(src);
sockaddr* addr = (sockaddr*)&src;
unsigned long flags = 0;
WSABUF wbuf = {(u_long)sz, static_cast< char* >(buf)};
// WSARecvFrom
llarp::LogDebug("read ", sz, " bytes into socket");
llarp::LogDebug("read ", sz, " bytes from socket");
int ret = ::WSARecvFrom(std::get< SOCKET >(fd), &wbuf, 1, nullptr, &flags,
addr, &slen, &portfd[0], nullptr);
// 997 is the error code for queued ops
@ -155,6 +160,7 @@ namespace llarp
virtual int
sendto(const sockaddr* to, const void* data, size_t sz)
{
printf("sendto\n");
socklen_t slen;
WSABUF wbuf = {(u_long)sz, (char*)data};
switch(to->sa_family)
@ -242,7 +248,6 @@ namespace llarp
setup()
{
llarp::LogDebug("set ifname to ", t->ifname);
strncpy(tunif->if_name, t->ifname, IFNAMSIZ);
if(tuntap_start(tunif, TUNTAP_MODE_TUNNEL, 0) == -1)
{
@ -289,16 +294,10 @@ struct llarp_win32_loop : public llarp_ev_loop
tcp_connect(struct llarp_tcp_connecter* tcp, const sockaddr* remoteaddr)
{
// create socket
DWORD on = 1;
SOCKET fd = ::socket(remoteaddr->sa_family, SOCK_STREAM, 0);
SOCKET fd = WSASocket(remoteaddr->sa_family, SOCK_STREAM, 0, nullptr, 0,
WSA_FLAG_OVERLAPPED);
if(fd == INVALID_SOCKET)
return false;
// set non blocking
if(ioctlsocket(fd, FIONBIO, &on) == SOCKET_ERROR)
{
::closesocket(fd);
return false;
}
llarp::tcp_conn* conn = new llarp::tcp_conn(this, fd, remoteaddr, tcp);
add_ev(conn, true);
conn->connect();
@ -315,8 +314,8 @@ struct llarp_win32_loop : public llarp_ev_loop
llarp::ev_io*
bind_tcp(llarp_tcp_acceptor* tcp, const sockaddr* bindaddr)
{
DWORD on = 1;
SOCKET fd = ::socket(bindaddr->sa_family, SOCK_STREAM, 0);
SOCKET fd = WSASocket(bindaddr->sa_family, SOCK_STREAM, 0, nullptr, 0,
WSA_FLAG_OVERLAPPED);
if(fd == INVALID_SOCKET)
return nullptr;
socklen_t sz = sizeof(sockaddr_in);
@ -345,7 +344,6 @@ struct llarp_win32_loop : public llarp_ev_loop
llarp::ev_io* serv = new llarp::tcp_serv(this, fd, tcp);
tcp->impl = serv;
ioctlsocket(fd, FIONBIO, &on);
return serv;
}
@ -366,27 +364,31 @@ struct llarp_win32_loop : public llarp_ev_loop
tick(int ms)
{
OVERLAPPED_ENTRY events[1024];
ULONG numEvents = 0;
if(::GetQueuedCompletionStatusEx(iocpfd, events, 1024, &numEvents, ms,
false))
{
for(ULONG idx = 0; idx < numEvents; ++idx)
memset(&events, 0, sizeof(OVERLAPPED_ENTRY) * 1024);
ULONG result = 0;
::GetQueuedCompletionStatusEx(iocpfd, events, 1024, &result, ms, false);
ULONG idx = 0;
while(idx < result)
{
llarp::ev_io* ev =
reinterpret_cast< llarp::ev_io* >(events[idx].lpCompletionKey);
if(ev && events[idx].lpOverlapped)
{
llarp::ev_io* ev =
reinterpret_cast< llarp::ev_io* >(events[idx].lpCompletionKey);
if(ev)
auto amount =
std::min(EV_READ_BUF_SZ, events[idx].dwNumberOfBytesTransferred);
if(ev->write)
ev->flush_write_buffers(amount);
else
{
if(ev->write)
ev->flush_write();
auto amount =
std::min(EV_READ_BUF_SZ, events[idx].dwNumberOfBytesTransferred);
memcpy(readbuf, events[idx].lpOverlapped->Pointer, amount);
ev->read(readbuf, amount);
}
}
++idx;
}
tick_listeners();
return 0;
return result;
}
// ok apparently this isn't being used yet...
@ -444,8 +446,8 @@ struct llarp_win32_loop : public llarp_ev_loop
default:
return INVALID_SOCKET;
}
DWORD on = 1;
SOCKET fd = ::socket(addr->sa_family, SOCK_DGRAM, 0);
SOCKET fd = WSASocket(addr->sa_family, SOCK_DGRAM, 0, nullptr, 0,
WSA_FLAG_OVERLAPPED);
if(fd == INVALID_SOCKET)
{
perror("WSASocket()");
@ -475,7 +477,6 @@ struct llarp_win32_loop : public llarp_ev_loop
return INVALID_SOCKET;
}
llarp::LogDebug("socket fd is ", fd);
ioctlsocket(fd, FIONBIO, &on);
return fd;
}
@ -630,4 +631,4 @@ struct llarp_win32_loop : public llarp_ev_loop
}
};
#endif
#endif

@ -0,0 +1,85 @@
#include <llarp/messages/exit.hpp>
#include <llarp/routing/handler.hpp>
namespace llarp
{
namespace routing
{
bool
CloseExitMessage::BEncode(llarp_buffer_t* buf) const
{
if(!bencode_start_dict(buf))
return false;
if(!BEncodeWriteDictMsgType(buf, "A", "C"))
return false;
if(!BEncodeWriteDictInt("S", S, buf))
return false;
if(!BEncodeWriteDictInt("V", version, buf))
return false;
if(!BEncodeWriteDictEntry("Y", Y, buf))
return false;
if(!BEncodeWriteDictEntry("Z", Z, buf))
return false;
return bencode_end(buf);
}
bool
CloseExitMessage::DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf)
{
bool read = false;
if(!BEncodeMaybeReadDictInt("S", S, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("V", version, read, k, buf))
return false;
if(!BEncodeMaybeReadDictEntry("Y", Y, read, k, buf))
return false;
if(!BEncodeMaybeReadDictEntry("Z", Z, read, k, buf))
return false;
return read;
}
bool
CloseExitMessage::Verify(llarp_crypto* c, const llarp::PubKey& pk) const
{
byte_t tmp[512] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
CloseExitMessage copy;
copy = *this;
copy.Z.Zero();
if(!copy.BEncode(&buf))
return false;
buf.sz = buf.cur - buf.base;
return c->verify(pk, buf, Z);
}
bool
CloseExitMessage::Sign(llarp_crypto* c, const llarp::SecretKey& sk)
{
byte_t tmp[512] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
Z.Zero();
Y.Randomize();
if(!BEncode(&buf))
return false;
buf.sz = buf.cur - buf.base;
return c->sign(Z, sk, buf);
}
CloseExitMessage&
CloseExitMessage::operator=(const CloseExitMessage& other)
{
S = other.S;
version = other.version;
Y = other.Y;
Z = other.Z;
return *this;
}
bool
CloseExitMessage::HandleMessage(IMessageHandler* h, llarp_router* r) const
{
return h->HandleCloseExitMessage(this, r);
}
} // namespace routing
} // namespace llarp

@ -0,0 +1,97 @@
#include <llarp/exit/context.hpp>
namespace llarp
{
namespace exit
{
Context::Context(llarp_router* r) : m_Router(r)
{
}
Context::~Context()
{
}
void
Context::Tick(llarp_time_t now)
{
auto itr = m_Exits.begin();
while(itr != m_Exits.end())
{
itr->second->Tick(now);
++itr;
}
}
void
Context::CalculateExitTraffic(TrafficStats& stats)
{
auto itr = m_Exits.begin();
while(itr != m_Exits.end())
{
itr->second->CalculateTrafficStats(stats);
++itr;
}
}
llarp::exit::Endpoint*
Context::FindEndpointForPath(const llarp::PathID_t& path) const
{
auto itr = m_Exits.begin();
while(itr != m_Exits.end())
{
auto ep = itr->second->FindEndpointByPath(path);
if(ep)
return ep;
++itr;
}
return nullptr;
}
bool
Context::ObtainNewExit(const llarp::PubKey& pk, const llarp::PathID_t& path,
bool permitInternet)
{
auto itr = m_Exits.begin();
while(itr != m_Exits.end())
{
if(itr->second->AllocateNewExit(pk, path, permitInternet))
return true;
++itr;
}
return false;
}
bool
Context::AddExitEndpoint(const std::string& name, const Config_t& conf)
{
// check for duplicate exit by name
{
auto itr = m_Exits.find(name);
if(itr != m_Exits.end())
{
llarp::LogError("duplicate exit with name ", name);
return false;
}
}
std::unique_ptr< llarp::handlers::ExitEndpoint > endpoint;
// make new endpoint
endpoint.reset(new llarp::handlers::ExitEndpoint(name, m_Router));
// configure
{
auto itr = conf.begin();
while(itr != conf.end())
{
if(!endpoint->SetOption(itr->first, itr->second))
return false;
++itr;
}
}
// add endpoint
if(!endpoint->Start())
return false;
m_Exits.emplace(name, std::move(endpoint));
return true;
}
} // namespace exit
} // namespace llarp

@ -0,0 +1,127 @@
#include <llarp/exit/endpoint.hpp>
#include "router.hpp"
namespace llarp
{
namespace exit
{
Endpoint::Endpoint(const llarp::PubKey& remoteIdent,
const llarp::PathID_t& beginPath, bool rewriteIP,
huint32_t ip, llarp::handlers::ExitEndpoint* parent)
: m_Parent(parent)
, m_remoteSignKey(remoteIdent)
, m_CurrentPath(beginPath)
, m_IP(ip)
, m_RewriteSource(rewriteIP)
{
}
Endpoint::~Endpoint()
{
m_Parent->DelEndpointInfo(m_CurrentPath);
}
void
Endpoint::Close()
{
m_Parent->RemoveExit(this);
}
bool
Endpoint::UpdateLocalPath(const llarp::PathID_t& nextPath)
{
if(!m_Parent->UpdateEndpointPath(m_remoteSignKey, nextPath))
return false;
m_CurrentPath = nextPath;
return true;
}
void
Endpoint::Tick(llarp_time_t now)
{
(void)now;
m_RxRate = 0;
m_TxRate = 0;
}
bool
Endpoint::IsExpired(llarp_time_t now) const
{
auto path = GetCurrentPath();
if(path)
{
return path->Expired(now);
}
// if we don't have an underlying path we are considered expired
return true;
}
bool
Endpoint::ExpiresSoon(llarp_time_t now, llarp_time_t dlt) const
{
auto path = GetCurrentPath();
if(path)
return path->ExpiresSoon(now, dlt);
return true;
}
bool
Endpoint::SendOutboundTraffic(llarp_buffer_t buf)
{
llarp::net::IPv4Packet pkt;
if(!pkt.Load(buf))
return false;
huint32_t dst;
if(m_RewriteSource)
dst = m_Parent->GetIfAddr();
else
dst = pkt.dst();
pkt.UpdateIPv4PacketOnDst(m_IP, dst);
if(!m_Parent->QueueOutboundTraffic(pkt.Buffer()))
{
llarp::LogError("failed to queue outbound traffic");
return false;
}
m_TxRate += buf.sz;
return true;
}
bool
Endpoint::SendInboundTraffic(llarp_buffer_t buf)
{
auto path = GetCurrentPath();
if(path)
{
llarp::net::IPv4Packet pkt;
if(!pkt.Load(buf))
return false;
huint32_t src;
if(m_RewriteSource)
src = m_Parent->GetIfAddr();
else
src = pkt.src();
pkt.UpdateIPv4PacketOnDst(src, m_IP);
llarp::routing::TransferTrafficMessage msg;
if(!msg.PutBuffer(pkt.Buffer()))
return false;
msg.S = path->NextSeqNo();
if(!msg.Sign(m_Parent->Crypto(), m_Parent->Router()->identity))
return false;
if(!path->SendRoutingMessage(&msg, m_Parent->Router()))
return false;
m_RxRate += buf.sz;
return true;
}
return false;
}
llarp::path::IHopHandler*
Endpoint::GetCurrentPath() const
{
auto router = m_Parent->Router();
return router->paths.GetByUpstream(router->pubkey(), m_CurrentPath);
}
} // namespace exit
} // namespace llarp

@ -0,0 +1,90 @@
#include <llarp/messages/exit.hpp>
#include <llarp/routing/handler.hpp>
namespace llarp
{
namespace routing
{
bool
GrantExitMessage::BEncode(llarp_buffer_t* buf) const
{
if(!bencode_start_dict(buf))
return false;
if(!BEncodeWriteDictMsgType(buf, "A", "G"))
return false;
if(!BEncodeWriteDictInt("S", S, buf))
return false;
if(!BEncodeWriteDictInt("T", T, buf))
return false;
if(!BEncodeWriteDictInt("V", version, buf))
return false;
if(!BEncodeWriteDictEntry("Y", Y, buf))
return false;
if(!BEncodeWriteDictEntry("Z", Z, buf))
return false;
return bencode_end(buf);
}
bool
GrantExitMessage::DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf)
{
bool read = false;
if(!BEncodeMaybeReadDictInt("S", S, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("T", T, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("V", version, read, k, buf))
return false;
if(!BEncodeMaybeReadDictEntry("Y", Y, read, k, buf))
return false;
if(!BEncodeMaybeReadDictEntry("Z", Z, read, k, buf))
return false;
return read;
}
bool
GrantExitMessage::Verify(llarp_crypto* c, const llarp::PubKey& pk) const
{
byte_t tmp[512] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
GrantExitMessage copy;
copy = *this;
copy.Z.Zero();
if(!copy.BEncode(&buf))
return false;
buf.sz = buf.cur - buf.base;
return c->verify(pk, buf, Z);
}
bool
GrantExitMessage::Sign(llarp_crypto* c, const llarp::SecretKey& sk)
{
byte_t tmp[512] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
Z.Zero();
Y.Randomize();
if(!BEncode(&buf))
return false;
buf.sz = buf.cur - buf.base;
return c->sign(Z, sk, buf);
}
GrantExitMessage&
GrantExitMessage::operator=(const GrantExitMessage& other)
{
S = other.S;
T = other.T;
version = other.version;
Y = other.Y;
Z = other.Z;
return *this;
}
bool
GrantExitMessage::HandleMessage(IMessageHandler* h, llarp_router* r) const
{
return h->HandleGrantExitMessage(this, r);
}
} // namespace routing
} // namespace llarp

@ -0,0 +1,112 @@
#include <llarp/messages/exit.hpp>
#include <llarp/routing/handler.hpp>
#include <llarp/link_layer.hpp>
namespace llarp
{
namespace routing
{
ObtainExitMessage&
ObtainExitMessage::operator=(const ObtainExitMessage& other)
{
B = other.B;
E = other.E;
I = other.I;
T = other.T;
W = other.W;
X = other.X;
version = other.version;
S = other.S;
Z = other.Z;
return *this;
}
bool
ObtainExitMessage::Sign(llarp_crypto* c, const llarp::SecretKey& sk)
{
byte_t tmp[1024] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
I = llarp::seckey_topublic(sk);
Z.Zero();
if(!BEncode(&buf))
return false;
buf.sz = buf.cur - buf.base;
return c->sign(Z, sk, buf);
}
bool
ObtainExitMessage::Verify(llarp_crypto* c) const
{
byte_t tmp[1024] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
ObtainExitMessage copy;
copy = *this;
copy.Z.Zero();
if(!copy.BEncode(&buf))
return false;
// rewind buffer
buf.sz = buf.cur - buf.base;
return c->verify(I, buf, Z);
}
bool
ObtainExitMessage::BEncode(llarp_buffer_t* buf) const
{
if(!bencode_start_dict(buf))
return false;
if(!BEncodeWriteDictMsgType(buf, "A", "O"))
return false;
if(!BEncodeWriteDictArray("B", B, buf))
return false;
if(!BEncodeWriteDictInt("E", E, buf))
return false;
if(!BEncodeWriteDictEntry("I", I, buf))
return false;
if(!BEncodeWriteDictInt("S", S, buf))
return false;
if(!BEncodeWriteDictInt("T", T, buf))
return false;
if(!BEncodeWriteDictInt("V", version, buf))
return false;
if(!BEncodeWriteDictArray("W", W, buf))
return false;
if(!BEncodeWriteDictInt("X", X, buf))
return false;
if(!BEncodeWriteDictEntry("Z", Z, buf))
return false;
return bencode_end(buf);
}
bool
ObtainExitMessage::DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf)
{
bool read = false;
if(!BEncodeMaybeReadDictList("B", B, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("E", E, read, k, buf))
return false;
if(!BEncodeMaybeReadDictEntry("I", I, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("S", S, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("T", T, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("V", version, read, k, buf))
return false;
if(!BEncodeMaybeReadDictList("W", W, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("X", X, read, k, buf))
return false;
if(!BEncodeMaybeReadDictEntry("Z", Z, read, k, buf))
return false;
return read;
}
bool
ObtainExitMessage::HandleMessage(IMessageHandler* h, llarp_router* r) const
{
return h->HandleObtainExitMessage(this, r);
}
} // namespace routing
} // namespace llarp

@ -0,0 +1,43 @@
#include <llarp/exit/policy.hpp>
namespace llarp
{
namespace exit
{
Policy::~Policy()
{
}
bool
Policy::BEncode(llarp_buffer_t *buf) const
{
if(!bencode_start_dict(buf))
return false;
if(!BEncodeWriteDictInt("a", proto, buf))
return false;
if(!BEncodeWriteDictInt("b", port, buf))
return false;
if(!BEncodeWriteDictInt("d", drop, buf))
return false;
if(!BEncodeWriteDictInt("v", version, buf))
return false;
return bencode_end(buf);
}
bool
Policy::DecodeKey(llarp_buffer_t k, llarp_buffer_t *buf)
{
bool read = false;
if(!BEncodeMaybeReadDictInt("a", proto, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("b", port, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("d", drop, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("v", version, read, k, buf))
return false;
return read;
}
} // namespace exit
} // namespace llarp

@ -0,0 +1,100 @@
#include <llarp/messages/exit.hpp>
#include <llarp/routing/handler.hpp>
namespace llarp
{
namespace routing
{
bool
RejectExitMessage::BEncode(llarp_buffer_t* buf) const
{
if(!bencode_start_dict(buf))
return false;
if(!BEncodeWriteDictMsgType(buf, "A", "J"))
return false;
if(!BEncodeWriteDictInt("B", B, buf))
return false;
if(!BEncodeWriteDictList("R", R, buf))
return false;
if(!BEncodeWriteDictInt("S", S, buf))
return false;
if(!BEncodeWriteDictInt("T", T, buf))
return false;
if(!BEncodeWriteDictInt("V", version, buf))
return false;
if(!BEncodeWriteDictEntry("Y", Y, buf))
return false;
if(!BEncodeWriteDictEntry("Z", Z, buf))
return false;
return bencode_end(buf);
}
bool
RejectExitMessage::DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf)
{
bool read = false;
if(!BEncodeMaybeReadDictInt("B", B, read, k, buf))
return false;
if(!BEncodeMaybeReadDictList("R", R, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("S", S, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("T", T, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("V", version, read, k, buf))
return false;
if(!BEncodeMaybeReadDictEntry("Y", Y, read, k, buf))
return false;
if(!BEncodeMaybeReadDictEntry("Z", Z, read, k, buf))
return false;
return read;
}
RejectExitMessage&
RejectExitMessage::operator=(const RejectExitMessage& other)
{
B = other.B;
R = other.R;
S = other.S;
T = other.T;
version = other.version;
Y = other.Y;
Z = other.Z;
return *this;
}
bool
RejectExitMessage::Sign(llarp_crypto* c, const llarp::SecretKey& sk)
{
byte_t tmp[512] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
Z.Zero();
Y.Randomize();
if(!BEncode(&buf))
return false;
buf.sz = buf.cur - buf.base;
return c->sign(Z, sk, buf);
}
bool
RejectExitMessage::Verify(llarp_crypto* c, const llarp::PubKey& pk) const
{
byte_t tmp[512] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
RejectExitMessage copy;
copy = *this;
copy.Z.Zero();
if(!copy.BEncode(&buf))
return false;
buf.sz = buf.cur - buf.base;
return c->verify(pk, buf, Z);
}
bool
RejectExitMessage::HandleMessage(IMessageHandler* h, llarp_router* r) const
{
return h->HandleRejectExitMessage(this, r);
}
} // namespace routing
} // namespace llarp

@ -0,0 +1,113 @@
#include <llarp/exit/session.hpp>
#include "router.hpp"
namespace llarp
{
namespace exit
{
BaseSession::BaseSession(const llarp::RouterID& router,
std::function< bool(llarp_buffer_t) > writepkt,
llarp_router* r, size_t numpaths, size_t hoplen)
: llarp::path::Builder(r, r->dht, numpaths, hoplen)
, m_ExitRouter(router)
, m_WritePacket(writepkt)
{
r->crypto.identity_keygen(m_ExitIdentity);
}
BaseSession::~BaseSession()
{
}
bool
BaseSession::ShouldBuildMore(llarp_time_t now) const
{
return AvailablePaths(llarp::path::ePathRoleExit) == 0
|| path::Builder::ShouldBuildMore(now);
}
bool
BaseSession::SelectHop(llarp_nodedb* db, const RouterContact& prev,
RouterContact& cur, size_t hop,
llarp::path::PathRole roles)
{
if(hop == numHops - 1)
return llarp_nodedb_get_rc(db, m_ExitRouter, cur);
else
return path::Builder::SelectHop(db, prev, cur, hop, roles);
}
void
BaseSession::HandlePathBuilt(llarp::path::Path* p)
{
p->SetDropHandler(std::bind(&BaseSession::HandleTrafficDrop, this,
std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3));
p->SetExitTrafficHandler(std::bind(&BaseSession::HandleTraffic, this,
std::placeholders::_1,
std::placeholders::_2));
p->AddObtainExitHandler(std::bind(&BaseSession::HandleGotExit, this,
std::placeholders::_1,
std::placeholders::_2));
llarp::routing::ObtainExitMessage obtain;
obtain.S = p->NextSeqNo();
obtain.T = llarp_randint();
obtain.X = 0;
obtain.E = 1;
if(!obtain.Sign(&router->crypto, m_ExitIdentity))
{
llarp::LogError("Failed to sign exit request");
return;
}
if(p->SendExitRequest(&obtain, router))
llarp::LogInfo("asking ", m_ExitRouter, " for exit");
else
llarp::LogError("faild to send exit request");
}
bool
BaseSession::HandleGotExit(llarp::path::Path* p, llarp_time_t b)
{
if(b == 0)
{
llarp::LogInfo("obtained an exit via ", p->Endpoint());
}
return true;
}
bool
BaseSession::HandleTraffic(llarp::path::Path* p, llarp_buffer_t pkt)
{
(void)p;
if(m_WritePacket)
return m_WritePacket(pkt);
return false;
}
bool
BaseSession::HandleTrafficDrop(llarp::path::Path* p, const PathID_t& path,
uint64_t s)
{
(void)p;
llarp::LogError("dropped traffic on exit ", m_ExitRouter, " S=", s,
" P=", path);
return true;
}
bool
BaseSession::SendUpstreamTraffic(llarp::net::IPv4Packet pkt)
{
auto path = PickRandomEstablishedPath(llarp::path::ePathRoleExit);
if(!path)
return false;
llarp::routing::TransferTrafficMessage transfer;
transfer.S = path->NextSeqNo();
transfer.X.resize(pkt.sz);
memcpy(transfer.X.data(), pkt.buf, pkt.sz);
if(!transfer.Sign(&router->crypto, m_ExitIdentity))
return false;
return path->SendRoutingMessage(&transfer, router);
}
} // namespace exit
} // namespace llarp

@ -0,0 +1,118 @@
#include <llarp/messages/transfer_traffic.hpp>
#include <llarp/routing/handler.hpp>
namespace llarp
{
namespace routing
{
bool
TransferTrafficMessage::Sign(llarp_crypto* c, const llarp::SecretKey& k)
{
byte_t tmp[MaxExitMTU + 512] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
// zero out sig
Z.Zero();
// randomize nonce
Y.Randomize();
if(!BEncode(&buf))
return false;
// rewind buffer
buf.sz = buf.cur - buf.base;
return c->sign(Z, k, buf);
}
TransferTrafficMessage&
TransferTrafficMessage::operator=(const TransferTrafficMessage& other)
{
Z = other.Z;
Y = other.Y;
S = other.S;
version = other.version;
X = other.X;
return *this;
}
bool
TransferTrafficMessage::Verify(llarp_crypto* c,
const llarp::PubKey& pk) const
{
byte_t tmp[MaxExitMTU + 512] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
// make copy
TransferTrafficMessage copy;
copy = *this;
// zero copy's sig
copy.Z.Zero();
// encode
if(!copy.BEncode(&buf))
return false;
// rewind buffer
buf.sz = buf.cur - buf.base;
// verify signature
return c->verify(pk, buf, Z);
}
bool
TransferTrafficMessage::PutBuffer(llarp_buffer_t buf)
{
if(buf.sz > MaxExitMTU)
return false;
X.resize(buf.sz);
memcpy(X.data(), buf.base, buf.sz);
return true;
}
bool
TransferTrafficMessage::BEncode(llarp_buffer_t* buf) const
{
if(!bencode_start_dict(buf))
return false;
if(!BEncodeWriteDictMsgType(buf, "A", "I"))
return false;
if(!BEncodeWriteDictInt("S", S, buf))
return false;
if(!BEncodeWriteDictInt("V", version, buf))
return false;
if(!bencode_write_bytestring(buf, "X", 1))
return false;
if(!bencode_write_bytestring(buf, X.data(), X.size()))
return false;
if(!BEncodeWriteDictEntry("Y", Y, buf))
return false;
if(!BEncodeWriteDictEntry("Z", Z, buf))
return false;
return bencode_end(buf);
}
bool
TransferTrafficMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf)
{
bool read = false;
if(!BEncodeMaybeReadDictEntry("Z", Z, read, key, buf))
return false;
if(!BEncodeMaybeReadDictEntry("Y", Y, read, key, buf))
return false;
if(!BEncodeMaybeReadDictInt("S", S, read, key, buf))
return false;
if(!BEncodeMaybeReadDictInt("V", version, read, key, buf))
return false;
if(llarp_buffer_eq(key, "X"))
{
llarp_buffer_t strbuf;
if(!bencode_read_string(buf, &strbuf))
return false;
return PutBuffer(strbuf);
}
return read;
}
bool
TransferTrafficMessage::HandleMessage(IMessageHandler* h,
llarp_router* r) const
{
return h->HandleTransferTrafficMessage(this, r);
}
} // namespace routing
} // namespace llarp

@ -0,0 +1,127 @@
#include <llarp/messages/exit.hpp>
#include <llarp/routing/handler.hpp>
namespace llarp
{
namespace routing
{
bool
UpdateExitMessage::BEncode(llarp_buffer_t* buf) const
{
if(!bencode_start_dict(buf))
return false;
if(!BEncodeWriteDictMsgType(buf, "A", "V"))
return false;
if(!BEncodeWriteDictEntry("P", P, buf))
return false;
if(!BEncodeWriteDictInt("S", S, buf))
return false;
if(!BEncodeWriteDictInt("T", T, buf))
return false;
if(!BEncodeWriteDictInt("V", version, buf))
return false;
if(!BEncodeWriteDictEntry("Z", Z, buf))
return false;
return bencode_end(buf);
}
bool
UpdateExitMessage::DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf)
{
bool read = false;
if(!BEncodeMaybeReadDictInt("S", S, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("T", T, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("V", version, read, k, buf))
return false;
if(!BEncodeMaybeReadDictEntry("P", P, read, k, buf))
return false;
if(!BEncodeMaybeReadDictEntry("Z", Z, read, k, buf))
return false;
return read;
}
bool
UpdateExitMessage::Verify(llarp_crypto* c, const llarp::PubKey& pk) const
{
byte_t tmp[512] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
UpdateExitMessage copy;
copy = *this;
copy.Z.Zero();
if(!copy.BEncode(&buf))
return false;
buf.sz = buf.cur - buf.base;
return c->verify(pk, buf, Z);
}
UpdateExitMessage&
UpdateExitMessage::operator=(const UpdateExitMessage& other)
{
P = other.P;
S = other.S;
T = other.T;
version = other.version;
Y = other.Y;
Z = other.Z;
return *this;
}
bool
UpdateExitMessage::Sign(llarp_crypto* c, const llarp::SecretKey& sk)
{
byte_t tmp[512] = {0};
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
Y.Randomize();
if(!BEncode(&buf))
return false;
buf.sz = buf.cur - buf.base;
return c->sign(Z, sk, buf);
}
bool
UpdateExitMessage::HandleMessage(IMessageHandler* h, llarp_router* r) const
{
return h->HandleUpdateExitMessage(this, r);
}
bool
UpdateExitVerifyMessage::BEncode(llarp_buffer_t* buf) const
{
if(!bencode_start_dict(buf))
return false;
if(!BEncodeWriteDictMsgType(buf, "A", "V"))
return false;
if(!BEncodeWriteDictInt("S", S, buf))
return false;
if(!BEncodeWriteDictInt("T", T, buf))
return false;
if(!BEncodeWriteDictInt("V", version, buf))
return false;
return bencode_end(buf);
}
bool
UpdateExitVerifyMessage::DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf)
{
bool read = false;
if(!BEncodeMaybeReadDictInt("S", S, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("T", T, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("V", version, read, k, buf))
return false;
return read;
}
bool
UpdateExitVerifyMessage::HandleMessage(IMessageHandler* h,
llarp_router* r) const
{
return h->HandleUpdateExitVerifyMessage(this, r);
}
} // namespace routing
} // namespace llarp

@ -0,0 +1,355 @@
#include <llarp/handlers/exit.hpp>
#include "../str.hpp"
#include "../router.hpp"
#include <llarp/net.hpp>
#include <cassert>
namespace llarp
{
namespace handlers
{
static void
ExitHandlerRecvPkt(llarp_tun_io *tun, const void *pkt, ssize_t sz)
{
static_cast< ExitEndpoint * >(tun->user)->OnInetPacket(
llarp::InitBuffer(pkt, sz));
}
static void
ExitHandlerFlushInbound(llarp_tun_io *tun)
{
static_cast< ExitEndpoint * >(tun->user)->FlushInbound();
}
ExitEndpoint::ExitEndpoint(const std::string &name, llarp_router *r)
: m_Router(r)
, m_Name(name)
, m_Tun{{0}, 0, {0}, 0, 0, 0, 0, 0, 0}
, m_InetToNetwork(name + "_exit_rx", r->netloop, r->netloop)
{
m_Tun.user = this;
m_Tun.recvpkt = &ExitHandlerRecvPkt;
m_Tun.tick = &ExitHandlerFlushInbound;
m_ShouldInitTun = true;
}
ExitEndpoint::~ExitEndpoint()
{
}
void
ExitEndpoint::FlushInbound()
{
auto now = Router()->Now();
m_InetToNetwork.Process([&](Pkt_t &pkt) {
llarp::PubKey pk;
{
auto itr = m_IPToKey.find(pkt.dst());
if(itr == m_IPToKey.end())
{
// drop
llarp::LogWarn(Name(), " dropping packet, has no session at ",
pkt.dst());
return;
}
pk = itr->second;
}
llarp::exit::Endpoint *ep = nullptr;
auto range = m_ActiveExits.equal_range(pk);
auto itr = range.first;
uint64_t min = std::numeric_limits< uint64_t >::max();
/// pick path with lowest rx rate
while(itr != range.second)
{
if(ep == nullptr)
ep = itr->second.get();
else if(itr->second->RxRate() < min && !itr->second->ExpiresSoon(now))
{
min = ep->RxRate();
ep = itr->second.get();
}
++itr;
}
if(ep)
{
if(!ep->SendInboundTraffic(pkt.Buffer()))
{
llarp::LogWarn(Name(), " dropped inbound traffic for session ", pk);
}
}
});
}
bool
ExitEndpoint::Start()
{
if(m_ShouldInitTun)
return llarp_ev_add_tun(Router()->netloop, &m_Tun);
return true;
}
llarp_router *
ExitEndpoint::Router()
{
return m_Router;
}
llarp_crypto *
ExitEndpoint::Crypto()
{
return &m_Router->crypto;
}
huint32_t
ExitEndpoint::GetIfAddr() const
{
return m_IfAddr;
}
bool
ExitEndpoint::HasLocalMappedAddrFor(const llarp::PubKey &pk) const
{
return m_KeyToIP.find(pk) != m_KeyToIP.end();
}
huint32_t
ExitEndpoint::GetIPForIdent(const llarp::PubKey pk)
{
huint32_t found = {0};
if(!HasLocalMappedAddrFor(pk))
{
// allocate and map
found.h = AllocateNewAddress().h;
if(!m_KeyToIP.emplace(pk, found).second)
{
llarp::LogError(Name(), "failed to map ", pk, " to ", found);
return found;
}
if(!m_IPToKey.emplace(found, pk).second)
{
llarp::LogError(Name(), "failed to map ", found, " to ", pk);
return found;
}
if(HasLocalMappedAddrFor(pk))
llarp::LogInfo(Name(), " mapping ", pk, " to ", found);
else
llarp::LogError(Name(), "failed to map ", pk, " to ", found);
}
else
found.h = m_KeyToIP[pk].h;
MarkIPActive(found);
m_KeyToIP.rehash(0);
assert(HasLocalMappedAddrFor(pk));
return found;
}
huint32_t
ExitEndpoint::AllocateNewAddress()
{
if(m_NextAddr < m_HigestAddr)
return ++m_NextAddr;
// find oldest activity ip address
huint32_t found = {0};
llarp_time_t min = std::numeric_limits< llarp_time_t >::max();
auto itr = m_IPActivity.begin();
while(itr != m_IPActivity.end())
{
if(itr->second < min)
{
found.h = itr->first.h;
min = itr->second;
}
++itr;
}
// kick old ident off exit
// TODO: DoS
llarp::PubKey pk = m_IPToKey[found];
KickIdentOffExit(pk);
return found;
}
bool
ExitEndpoint::QueueOutboundTraffic(llarp_buffer_t buf)
{
return llarp_ev_tun_async_write(&m_Tun, buf.base, buf.sz);
}
void
ExitEndpoint::KickIdentOffExit(const llarp::PubKey &pk)
{
llarp::LogInfo(Name(), " kicking ", pk, " off exit");
huint32_t ip = m_KeyToIP[pk];
m_KeyToIP.erase(pk);
m_IPToKey.erase(ip);
auto range = m_ActiveExits.equal_range(pk);
auto exit_itr = range.first;
while(exit_itr != range.second)
exit_itr = m_ActiveExits.erase(exit_itr);
}
void
ExitEndpoint::MarkIPActive(llarp::huint32_t ip)
{
m_IPActivity[ip] = Router()->Now();
}
void
ExitEndpoint::OnInetPacket(llarp_buffer_t buf)
{
m_InetToNetwork.EmplaceIf(
[buf](Pkt_t &pkt) -> bool { return pkt.Load(buf); });
}
llarp::exit::Endpoint *
ExitEndpoint::FindEndpointByPath(const llarp::PathID_t &path)
{
llarp::exit::Endpoint *endpoint = nullptr;
llarp::PubKey pk;
{
auto itr = m_Paths.find(path);
if(itr == m_Paths.end())
return nullptr;
pk = itr->second;
}
{
auto itr = m_ActiveExits.find(pk);
if(itr != m_ActiveExits.end())
{
if(itr->second->PubKey() == pk)
endpoint = itr->second.get();
}
}
return endpoint;
}
bool
ExitEndpoint::UpdateEndpointPath(const llarp::PubKey &remote,
const llarp::PathID_t &next)
{
// check if already mapped
auto itr = m_Paths.find(next);
if(itr != m_Paths.end())
return false;
m_Paths.insert(std::make_pair(next, remote));
return true;
}
bool
ExitEndpoint::SetOption(const std::string &k, const std::string &v)
{
if(k == "type" && v == "null")
{
m_ShouldInitTun = false;
return true;
}
if(k == "exit")
{
m_PermitExit = IsTrueValue(v.c_str());
return true;
}
if(k == "ifaddr")
{
auto pos = v.find("/");
if(pos == std::string::npos)
{
llarp::LogError(Name(), " ifaddr is not a cidr: ", v);
return false;
}
std::string nmask_str = v.substr(1 + pos);
std::string host_str = v.substr(0, pos);
strncpy(m_Tun.ifaddr, host_str.c_str(), sizeof(m_Tun.ifaddr));
m_Tun.netmask = std::atoi(nmask_str.c_str());
llarp::Addr ifaddr(host_str);
m_IfAddr = ifaddr.xtohl();
m_NextAddr = m_IfAddr;
m_HigestAddr = m_IfAddr ^ (~llarp::netmask_ipv4_bits(m_Tun.netmask));
llarp::LogInfo(Name(), " set ifaddr range to ", m_Tun.ifaddr, "/",
m_Tun.netmask, " lo=", m_IfAddr, " hi=", m_HigestAddr);
}
if(k == "ifname")
{
strncpy(m_Tun.ifname, v.c_str(), sizeof(m_Tun.ifname));
llarp::LogInfo(Name(), " set ifname to ", m_Tun.ifname);
}
if(k == "exit-whitelist")
{
// add exit policy whitelist rule
// TODO: implement me
return true;
}
if(k == "exit-blacklist")
{
// add exit policy blacklist rule
// TODO: implement me
return true;
}
return true;
}
bool
ExitEndpoint::AllocateNewExit(const llarp::PubKey pk,
const llarp::PathID_t &path,
bool wantInternet)
{
if(wantInternet && !m_PermitExit)
return false;
huint32_t ip = GetIPForIdent(pk);
m_ActiveExits.insert(std::make_pair(
pk, new llarp::exit::Endpoint(pk, path, !wantInternet, ip, this)));
m_Paths[path] = pk;
return HasLocalMappedAddrFor(pk);
}
std::string
ExitEndpoint::Name() const
{
return m_Name;
}
void
ExitEndpoint::DelEndpointInfo(const llarp::PathID_t &path)
{
m_Paths.erase(path);
}
void
ExitEndpoint::RemoveExit(const llarp::exit::Endpoint *ep)
{
auto range = m_ActiveExits.equal_range(ep->PubKey());
auto itr = range.first;
while(itr != range.second)
{
if(itr->second->LocalPath() == ep->LocalPath())
{
itr = m_ActiveExits.erase(itr);
// now ep is gone af
return;
}
++itr;
}
}
void
ExitEndpoint::Tick(llarp_time_t now)
{
auto itr = m_ActiveExits.begin();
while(itr != m_ActiveExits.end())
{
if(itr->second->IsExpired(now))
{
itr = m_ActiveExits.erase(itr);
}
else
{
itr->second->Tick(now);
++itr;
}
}
}
} // namespace handlers
} // namespace llarp

@ -15,8 +15,8 @@ namespace llarp
{
TunEndpoint::TunEndpoint(const std::string &nickname, llarp_router *r)
: service::Endpoint(nickname, r)
, m_UserToNetworkPktQueue(nickname + "_sendq", r->netloop)
, m_NetworkToUserPktQueue(nickname + "_recvq", r->netloop)
, m_UserToNetworkPktQueue(nickname + "_sendq", r->netloop, r->netloop)
, m_NetworkToUserPktQueue(nickname + "_recvq", r->netloop, r->netloop)
{
tunif.user = this;
tunif.netmask = DefaultTunNetmask;
@ -33,13 +33,20 @@ namespace llarp
bool
TunEndpoint::SetOption(const std::string &k, const std::string &v)
{
if(k == "nameresolver")
if(k == "exit-node")
{
// we probably can set the property since the config will load before
// the relay is set up
// strncpy(tunif.ifname, v.c_str(), sizeof(tunif.ifname) - 1);
llarp::LogInfo(Name() + " would be setting DNS resolver to ", v);
return true;
llarp::RouterID exitRouter;
if(!HexDecode(v.c_str(), exitRouter, exitRouter.size()))
{
llarp::LogError(Name(), " bad exit router key: ", v);
return false;
}
m_Exit.reset(new llarp::exit::BaseSession(
exitRouter,
std::bind(&TunEndpoint::QueueInboundPacketForExit, this,
std::placeholders::_1),
router, m_NumPaths, numHops));
llarp::LogInfo(Name(), " using exit at ", exitRouter);
}
if(k == "local-dns")
{
@ -145,6 +152,20 @@ namespace llarp
return Endpoint::SetOption(k, v);
}
bool
TunEndpoint::HasLocalIP(const huint32_t &ip) const
{
return m_IPToAddr.find(ip) != m_IPToAddr.end();
}
bool
TunEndpoint::QueueOutboundTraffic(llarp::net::IPv4Packet &&pkt)
{
return m_NetworkToUserPktQueue.EmplaceIf(
[](llarp::net::IPv4Packet &) -> bool { return true; },
std::move(pkt));
}
bool
TunEndpoint::MapAddress(const service::Address &addr, huint32_t ip)
{
@ -152,13 +173,14 @@ namespace llarp
if(itr != m_IPToAddr.end())
{
// XXX is calling inet_ntoa safe in this context? it's MP-unsafe
llarp::LogWarn(ip, " already mapped to ", itr->second.ToString());
llarp::LogWarn(ip, " already mapped to ",
service::Address(itr->second).ToString());
return false;
}
llarp::LogInfo(Name() + " map ", addr.ToString(), " to ", ip);
m_IPToAddr.insert(std::make_pair(ip, addr));
m_AddrToIP.insert(std::make_pair(addr, ip));
m_IPToAddr.insert(std::make_pair(ip, addr.data()));
m_AddrToIP.insert(std::make_pair(addr.data(), ip));
MarkIPActiveForever(ip);
return true;
}
@ -265,9 +287,7 @@ namespace llarp
m_OurIP = lAddr.xtohl();
m_NextIP = m_OurIP;
auto xmask = netmask_ipv4_bits(tunif.netmask);
auto baseaddr = m_OurIP & xmask;
m_MaxIP = baseaddr | ~xmask;
m_MaxIP = m_OurIP ^ (~xmask);
llarp::LogInfo(Name(), " set ", tunif.ifname, " to have address ", lAddr);
llarp::LogInfo(Name(), " allocated up to ", m_MaxIP);
@ -327,7 +347,13 @@ namespace llarp
auto itr = m_IPToAddr.find(pkt.dst());
if(itr == m_IPToAddr.end())
{
llarp::LogWarn(Name(), " has no endpoint for ", pkt.dst());
if(m_Exit)
{
pkt.UpdateIPv4PacketOnDst({0}, pkt.dst());
m_Exit->SendUpstreamTraffic(std::move(pkt));
}
else
llarp::LogWarn(Name(), " has no endpoint for ", pkt.dst());
return true;
}
@ -335,7 +361,8 @@ namespace llarp
// this includes clearing IP addresses, recalculating checksums, etc
pkt.UpdateIPv4PacketOnSrc();
if(!SendToOrQueue(itr->second, pkt.Buffer(), service::eProtocolTraffic))
if(!SendToOrQueue(itr->second.data(), pkt.Buffer(),
service::eProtocolTraffic))
{
llarp::LogWarn(Name(), " did not flush packets");
}
@ -347,7 +374,7 @@ namespace llarp
TunEndpoint::ProcessDataMessage(service::ProtocolMessage *msg)
{
// llarp::LogInfo("got packet from ", msg->sender.Addr());
auto themIP = ObtainIPForAddr(msg->sender.Addr());
auto themIP = ObtainIPForAddr(msg->sender.Addr().data());
// llarp::LogInfo("themIP ", themIP);
auto usIP = m_OurIP;
auto buf = llarp::Buffer(msg->payload);
@ -380,30 +407,21 @@ namespace llarp
return true;
}
service::Address
TunEndpoint::ObtainAddrForIP(huint32_t ip)
huint32_t
TunEndpoint::GetIfAddr() const
{
auto itr = m_IPToAddr.find(ip);
if(itr == m_IPToAddr.end())
{
// not found
service::Address addr;
llarp::LogWarn(ip, " not found in tun map.");
return addr;
}
// found
return itr->second;
return m_OurIP;
}
huint32_t
TunEndpoint::ObtainIPForAddr(const service::Address &addr)
TunEndpoint::ObtainIPForAddr(const byte_t *a)
{
llarp_time_t now = Now();
huint32_t nextIP = {0};
AlignedBuffer< 32 > ident(a);
{
// previously allocated address
auto itr = m_AddrToIP.find(addr);
auto itr = m_AddrToIP.find(ident);
if(itr != m_AddrToIP.end())
{
// mark ip active
@ -421,9 +439,9 @@ namespace llarp
&& m_NextIP < m_MaxIP);
if(nextIP < m_MaxIP)
{
m_AddrToIP.insert(std::make_pair(addr, nextIP));
m_IPToAddr.insert(std::make_pair(nextIP, addr));
llarp::LogInfo(Name(), " mapped ", addr, " to ", nextIP);
m_AddrToIP[ident] = nextIP;
m_IPToAddr[nextIP] = ident;
llarp::LogInfo(Name(), " mapped ", ident, " to ", nextIP);
MarkIPActive(nextIP);
return nextIP;
}
@ -449,8 +467,8 @@ namespace llarp
++itr;
}
// remap address
m_IPToAddr[oldest.first] = addr;
m_AddrToIP[addr] = oldest.first;
m_IPToAddr[oldest.first] = ident;
m_AddrToIP[ident] = oldest.first;
nextIP = oldest.first;
// mark ip active

@ -1,4 +1,4 @@
#include <llarp/endian.h>
#include <llarp/endian.hpp>
#include <algorithm>
#include <llarp/ip.hpp>
#include "llarp/buffer.hpp"
@ -6,7 +6,6 @@
#ifndef _WIN32
#include <netinet/in.h>
#endif
#include <llarp/endian.h>
#include <map>
#include <algorithm>

@ -60,7 +60,10 @@ namespace llarp
++itr;
}
else
{
llarp::LogInfo("session to ", itr->second->GetPubKey(), " timed out");
itr = m_AuthedLinks.erase(itr);
}
}
}
{
@ -121,6 +124,7 @@ namespace llarp
llarp::AddressInfo to;
if(!PickAddress(rc, to))
return;
llarp::LogInfo("Try establish to ", rc.pubkey);
llarp::Addr addr(to);
auto s = NewOutboundSession(rc, to);
s->Start();
@ -164,6 +168,7 @@ namespace llarp
ILinkLayer::CloseSessionTo(const PubKey& remote)
{
Lock l(m_AuthedLinksMutex);
llarp::LogInfo("Closing all to ", remote);
auto range = m_AuthedLinks.equal_range(remote);
auto itr = range.first;
while(itr != range.second)

@ -3,7 +3,7 @@
#include <llarp/messages/link_intro.hpp>
#include <llarp/messages/discard.hpp>
#include <llarp/buffer.hpp>
#include <llarp/endian.h>
#include <llarp/endian.hpp>
#include <utp.h>
#include <cassert>
#include <tuple>
@ -17,7 +17,6 @@
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <wspiapi.h>
#endif
namespace llarp
@ -565,7 +564,7 @@ namespace llarp
SendKeepAlive = [&]() -> bool {
auto now = parent->now();
if(sendq.size() == 0 && state == eSessionReady && now > lastActive
&& now - lastActive > (sessionTimeout / 4))
&& now - lastActive > 5000)
{
DiscardMessage msg;
byte_t tmp[128] = {0};

@ -1,4 +1,4 @@
#if defined(RPI) || defined(ANDROID)
#if defined(RPI) || defined(ANDROID) || NETNS == 0
#else
#include <asm/types.h>

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

Loading…
Cancel
Save