diff --git a/ChangeLog b/ChangeLog index 2ff1af50..2468f808 100644 --- a/ChangeLog +++ b/ChangeLog @@ -37,7 +37,7 @@ ## [2.15.0] - 2017-08-17 ### Added -- QT GUI +- QT GUI - Ability to add and remove I2P tunnels without restart - Ability to disable SOCKS outproxy option ### Changed @@ -81,7 +81,7 @@ - Some stats in a main window for Windows version ### Changed - Reseed servers list -- MTU of 1488 for ipv6 +- MTU of 1488 for ipv6 - Android and Mac OS X versions use OpenSSL 1.1 - New logo for Android ### Fixed @@ -111,7 +111,7 @@ ## [2.10.2] - 2016-12-04 ### Fixed - Fixes UPnP discovery bug, producing excessive CPU usage -- Fixes sudden SSU thread stop for Windows. +- Fixes sudden SSU thread stop for Windows. ## [2.10.1] - 2016-11-07 ### Fixed diff --git a/Dockerfile b/Dockerfile index 229d0d53..4931a709 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,13 +13,13 @@ RUN mkdir /user && adduser -S -h /user i2pd && chown -R i2pd:nobody /user # -# Each RUN is a layer, adding the dependencies and building i2pd in one layer takes around 8-900Mb, so to keep the +# Each RUN is a layer, adding the dependencies and building i2pd in one layer takes around 8-900Mb, so to keep the # image under 20mb we need to remove all the build dependencies in the same "RUN" / layer. # -# 1. install deps, clone and build. -# 2. strip binaries. -# 3. Purge all dependencies and other unrelated packages, including build directory. +# 1. install deps, clone and build. +# 2. strip binaries. +# 3. Purge all dependencies and other unrelated packages, including build directory. RUN apk --no-cache --virtual build-dependendencies add make gcc g++ libtool boost-dev build-base openssl-dev openssl git \ && mkdir -p /tmp/build \ && cd /tmp/build && git clone -b ${GIT_BRANCH} https://github.com/PurpleI2P/i2pd.git \ diff --git a/Makefile b/Makefile index a8514826..460b16e4 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,9 @@ -UNAME := $(shell uname -s) +SYS := $(shell $(CXX) -dumpmachine) SHLIB := libi2pd.so ARLIB := libi2pd.a SHLIB_CLIENT := libi2pdclient.so ARLIB_CLIENT := libi2pdclient.a -I2PD := i2pd +I2PD := i2pd GREP := grep DEPS := obj/make.dep @@ -23,22 +23,24 @@ ifeq ($(WEBSOCKETS),1) NEEDED_CXXFLAGS += -DWITH_EVENTS endif -ifeq ($(UNAME),Darwin) +ifneq (, $(findstring darwin, $(SYS))) DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp ifeq ($(HOMEBREW),1) include Makefile.homebrew else include Makefile.osx endif -else ifeq ($(shell echo $(UNAME) | $(GREP) -Ec '(Free|Open)BSD'),1) +else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS))) DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp include Makefile.bsd -else ifeq ($(UNAME),Linux) +else ifneq (, $(findstring linux, $(SYS))) DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp include Makefile.linux -else +else ifneq (, $(findstring mingw, $(SYS))$(findstring cygwin, $(SYS))) DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32Service.cpp Win32/Win32App.cpp include Makefile.mingw +else # not supported +$(error Not supported platform) endif ifeq ($(USE_MESHNET),yes) diff --git a/Makefile.bsd b/Makefile.bsd index d6871f07..f2293540 100644 --- a/Makefile.bsd +++ b/Makefile.bsd @@ -1,5 +1,5 @@ CXX = clang++ -CXXFLAGS = -O2 +CXXFLAGS ?= -g -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misleading-indentation ## NOTE: NEEDED_CXXFLAGS is here so that custom CXXFLAGS can be specified at build time ## **without** overwriting the CXXFLAGS which we need in order to build. ## For example, when adding 'hardening flags' to the build diff --git a/Makefile.homebrew b/Makefile.homebrew index 287dea05..b3105c56 100644 --- a/Makefile.homebrew +++ b/Makefile.homebrew @@ -4,7 +4,7 @@ BOOSTROOT = ${BREWROOT}/opt/boost SSLROOT = ${BREWROOT}/opt/libressl UPNPROOT = ${BREWROOT}/opt/miniupnpc CXXFLAGS = -g -Wall -std=c++11 -DMAC_OSX -Wno-overloaded-virtual -INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include +INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include ifndef TRAVIS CXX = clang++ diff --git a/Makefile.linux b/Makefile.linux index eec1e2cc..4a82591a 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -12,7 +12,7 @@ INCFLAGS ?= # detect proper flag for c++11 support by compilers CXXVER := $(shell $(CXX) -dumpversion) ifeq ($(shell expr match $(CXX) 'clang'),5) - NEEDED_CXXFLAGS += -std=c++11 + NEEDED_CXXFLAGS += -std=c++11 else ifeq ($(shell expr match ${CXXVER} "4\.[0-9][0-9]"),4) # gcc >= 4.10 NEEDED_CXXFLAGS += -std=c++11 else ifeq ($(shell expr match ${CXXVER} "4\.[7-9]"),3) # >= 4.7 @@ -24,7 +24,7 @@ else ifeq ($(shell expr match ${CXXVER} "[5-7]\.[0-9]"),3) # gcc >= 5.0 else ifeq ($(shell expr match ${CXXVER} "7"),1) # gcc 7 ubuntu NEEDED_CXXFLAGS += -std=c++11 else # not supported - $(error Compiler too old) +$(error Compiler too old) endif NEEDED_CXXFLAGS += -fPIC diff --git a/Makefile.osx b/Makefile.osx index f6a0847d..8bbf37f0 100644 --- a/Makefile.osx +++ b/Makefile.osx @@ -1,7 +1,7 @@ CXX = clang++ CXXFLAGS = -Os -Wall -std=c++11 -DMAC_OSX #CXXFLAGS = -g -O2 -Wall -std=c++11 -INCFLAGS = -I/usr/local/include +INCFLAGS = -I/usr/local/include LDFLAGS = -Wl,-rpath,/usr/local/lib -L/usr/local/lib ifeq ($(USE_STATIC),yes) diff --git a/README.md b/README.md index d5d7ceb9..546cea64 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,13 @@ i2pd i2pd (I2P Daemon) is a full-featured C++ implementation of I2P client. -I2P (Invisible Internet Protocol) is a universal anonymous network layer. +I2P (Invisible Internet Protocol) is a universal anonymous network layer. All communications over I2P are anonymous and end-to-end encrypted, participants -don't reveal their real IP addresses. +don't reveal their real IP addresses. -I2P client is a software used for building and using anonymous I2P -networks. Such networks are commonly used for anonymous peer-to-peer -applications (filesharing, cryptocurrencies) and anonymous client-server +I2P client is a software used for building and using anonymous I2P +networks. Such networks are commonly used for anonymous peer-to-peer +applications (filesharing, cryptocurrencies) and anonymous client-server applications (websites, instant messengers, chat-servers). I2P allows people from all around the world to communicate and share information @@ -38,9 +38,9 @@ Resources Installing ---------- -The easiest way to install i2pd is by using -[precompiled binaries](https://github.com/PurpleI2P/i2pd/releases/latest). -See [documentation](https://i2pd.readthedocs.io/en/latest/) for how to build +The easiest way to install i2pd is by using +[precompiled binaries](https://github.com/PurpleI2P/i2pd/releases/latest). +See [documentation](https://i2pd.readthedocs.io/en/latest/) for how to build i2pd from source on your OS. @@ -58,25 +58,25 @@ Build instructions: * Windows - [![Build status](https://ci.appveyor.com/api/projects/status/1908qe4p48ff1x23?svg=true)](https://ci.appveyor.com/project/PurpleI2P/i2pd) * Mac OS X - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd) * FreeBSD -* Android +* Android * iOS Using i2pd ---------- -See [documentation](https://i2pd.readthedocs.io/en/latest/user-guide/run/) and +See [documentation](https://i2pd.readthedocs.io/en/latest/user-guide/run/) and [example config file](https://github.com/PurpleI2P/i2pd/blob/openssl/contrib/i2pd.conf). Donations --------- -BTC: 1K7Ds6KUeR8ya287UC4rYTjvC96vXyZbDY -ZEC: t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ -DASH: Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF -LTC: LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59 -DOGE: DNXLQKziRPAsD9H3DFNjk4fLQrdaSX893Y -ANC: AQJYweYYUqM1nVfLqfoSMpUMfzxvS4Xd7z -GST: GbD2JSQHBHCKLa9WTHmigJRpyFgmBj4woG +BTC: 1K7Ds6KUeR8ya287UC4rYTjvC96vXyZbDY +ZEC: t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ +DASH: Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF +LTC: LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59 +DOGE: DNXLQKziRPAsD9H3DFNjk4fLQrdaSX893Y +ANC: AQJYweYYUqM1nVfLqfoSMpUMfzxvS4Xd7z +GST: GbD2JSQHBHCKLa9WTHmigJRpyFgmBj4woG License ------- diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index f175c0da..1f9d3b91 100755 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -23,4 +23,4 @@ - + diff --git a/android/res/menu/options_main.xml b/android/res/menu/options_main.xml index 388dfd83..f66caa2a 100644 --- a/android/res/menu/options_main.xml +++ b/android/res/menu/options_main.xml @@ -1,7 +1,7 @@ - +#include +std::atomic x; +std::atomic y; +int main() { + return x + y; +} +" ${varname}) + set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) +endfunction(check_cxx_atomics) + +check_cxx_atomics(LIBCXX_HAVE_CXX_ATOMICS_WITHOUT_LIB) +check_library_exists(atomic __atomic_fetch_add_8 "" LIBCXX_HAS_ATOMIC_LIB) +# If not, check if the library exists, and atomics work with it. +if(NOT LIBCXX_HAVE_CXX_ATOMICS_WITHOUT_LIB) + if(LIBCXX_HAS_ATOMIC_LIB) + list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") + check_cxx_atomics(LIBCXX_HAVE_CXX_ATOMICS_WITH_LIB) + if (NOT LIBCXX_HAVE_CXX_ATOMICS_WITH_LIB) + message(WARNING "Host compiler must support std::atomic!") + endif() + else() + message(WARNING "Host compiler appears to require libatomic, but cannot find it.") + endif() +endif() diff --git a/build/cmake_modules/FindMiniUPnPc.cmake b/build/cmake_modules/FindMiniUPnPc.cmake index 6a5d4220..17731912 100644 --- a/build/cmake_modules/FindMiniUPnPc.cmake +++ b/build/cmake_modules/FindMiniUPnPc.cmake @@ -24,5 +24,5 @@ else() endif() mark_as_advanced(MINIUPNPC_INCLUDE_DIR MINIUPNPC_LIBRARY) - + endif() diff --git a/build/cmake_modules/TargetArch.cmake b/build/cmake_modules/TargetArch.cmake new file mode 100644 index 00000000..3761e4df --- /dev/null +++ b/build/cmake_modules/TargetArch.cmake @@ -0,0 +1,134 @@ +# Based on the Qt 5 processor detection code, so should be very accurate +# https://qt.gitorious.org/qt/qtbase/blobs/master/src/corelib/global/qprocessordetection.h +# Currently handles arm (v5, v6, v7), x86 (32/64), ia64, and ppc (32/64) + +# Regarding POWER/PowerPC, just as is noted in the Qt source, +# "There are many more known variants/revisions that we do not handle/detect." + +set(archdetect_c_code " +#if defined(__arm__) || defined(__TARGET_ARCH_ARM) + #if defined(__ARM_ARCH_7__) \\ + || defined(__ARM_ARCH_7A__) \\ + || defined(__ARM_ARCH_7R__) \\ + || defined(__ARM_ARCH_7M__) \\ + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 7) + #error cmake_ARCH armv7 + #elif defined(__ARM_ARCH_6__) \\ + || defined(__ARM_ARCH_6J__) \\ + || defined(__ARM_ARCH_6T2__) \\ + || defined(__ARM_ARCH_6Z__) \\ + || defined(__ARM_ARCH_6K__) \\ + || defined(__ARM_ARCH_6ZK__) \\ + || defined(__ARM_ARCH_6M__) \\ + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 6) + #error cmake_ARCH armv6 + #elif defined(__ARM_ARCH_5TEJ__) \\ + || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 5) + #error cmake_ARCH armv5 + #else + #error cmake_ARCH arm + #endif +#elif defined(__i386) || defined(__i386__) || defined(_M_IX86) + #error cmake_ARCH i386 +#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) + #error cmake_ARCH x86_64 +#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64) + #error cmake_ARCH ia64 +#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \\ + || defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \\ + || defined(_M_MPPC) || defined(_M_PPC) + #if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__) + #error cmake_ARCH ppc64 + #else + #error cmake_ARCH ppc + #endif +#endif + +#error cmake_ARCH unknown +") + +# Set ppc_support to TRUE before including this file or ppc and ppc64 +# will be treated as invalid architectures since they are no longer supported by Apple + +function(target_architecture output_var) + if(APPLE AND CMAKE_OSX_ARCHITECTURES) + # On OS X we use CMAKE_OSX_ARCHITECTURES *if* it was set + # First let's normalize the order of the values + + # Note that it's not possible to compile PowerPC applications if you are using + # the OS X SDK version 10.6 or later - you'll need 10.4/10.5 for that, so we + # disable it by default + # See this page for more information: + # http://stackoverflow.com/questions/5333490/how-can-we-restore-ppc-ppc64-as-well-as-full-10-4-10-5-sdk-support-to-xcode-4 + + # Architecture defaults to i386 or ppc on OS X 10.5 and earlier, depending on the CPU type detected at runtime. + # On OS X 10.6+ the default is x86_64 if the CPU supports it, i386 otherwise. + + foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES}) + if("${osx_arch}" STREQUAL "ppc" AND ppc_support) + set(osx_arch_ppc TRUE) + elseif("${osx_arch}" STREQUAL "i386") + set(osx_arch_i386 TRUE) + elseif("${osx_arch}" STREQUAL "x86_64") + set(osx_arch_x86_64 TRUE) + elseif("${osx_arch}" STREQUAL "ppc64" AND ppc_support) + set(osx_arch_ppc64 TRUE) + else() + message(FATAL_ERROR "Invalid OS X arch name: ${osx_arch}") + endif() + endforeach() + + # Now add all the architectures in our normalized order + if(osx_arch_ppc) + list(APPEND ARCH ppc) + endif() + + if(osx_arch_i386) + list(APPEND ARCH i386) + endif() + + if(osx_arch_x86_64) + list(APPEND ARCH x86_64) + endif() + + if(osx_arch_ppc64) + list(APPEND ARCH ppc64) + endif() + else() + file(WRITE "${CMAKE_BINARY_DIR}/arch.c" "${archdetect_c_code}") + + enable_language(C) + + # Detect the architecture in a rather creative way... + # This compiles a small C program which is a series of ifdefs that selects a + # particular #error preprocessor directive whose message string contains the + # target architecture. The program will always fail to compile (both because + # file is not a valid C program, and obviously because of the presence of the + # #error preprocessor directives... but by exploiting the preprocessor in this + # way, we can detect the correct target architecture even when cross-compiling, + # since the program itself never needs to be run (only the compiler/preprocessor) + try_run( + run_result_unused + compile_result_unused + "${CMAKE_BINARY_DIR}" + "${CMAKE_BINARY_DIR}/arch.c" + COMPILE_OUTPUT_VARIABLE ARCH + CMAKE_FLAGS CMAKE_OSX_ARCHITECTURES=${CMAKE_OSX_ARCHITECTURES} + ) + + # Parse the architecture name from the compiler output + string(REGEX MATCH "cmake_ARCH ([a-zA-Z0-9_]+)" ARCH "${ARCH}") + + # Get rid of the value marker leaving just the architecture name + string(REPLACE "cmake_ARCH " "" ARCH "${ARCH}") + + # If we are compiling with an unknown architecture this variable should + # already be set to "unknown" but in the case that it's empty (i.e. due + # to a typo in the code), then set it to unknown + if (NOT ARCH) + set(ARCH unknown) + endif() + endif() + + set(${output_var} "${ARCH}" PARENT_SCOPE) +endfunction() diff --git a/build/docker/old-ubuntu-based/Dockerfile b/build/docker/old-ubuntu-based/Dockerfile index 751fe956..3faddf2e 100644 --- a/build/docker/old-ubuntu-based/Dockerfile +++ b/build/docker/old-ubuntu-based/Dockerfile @@ -5,7 +5,7 @@ RUN apt-get update && apt-get install -y libboost-dev libboost-filesystem-dev \ libssl-dev git build-essential RUN git clone https://github.com/PurpleI2P/i2pd.git -WORKDIR /i2pd +WORKDIR /i2pd RUN make CMD ./i2pd diff --git a/contrib/apparmor/usr.sbin.i2pd b/contrib/apparmor/usr.sbin.i2pd index ab6c8b44..f0dea839 100644 --- a/contrib/apparmor/usr.sbin.i2pd +++ b/contrib/apparmor/usr.sbin.i2pd @@ -1,4 +1,4 @@ -# Basic profile for i2pd +# Basic profile for i2pd # Should work without modifications with Ubuntu/Debian packages # Author: Darknet Villain # diff --git a/contrib/certificates/reseed/hottuna_at_mail.i2p.crt b/contrib/certificates/reseed/hottuna_at_mail.i2p.crt deleted file mode 100644 index d0ff7c33..00000000 --- a/contrib/certificates/reseed/hottuna_at_mail.i2p.crt +++ /dev/null @@ -1,33 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFxzCCA6+gAwIBAgIQZfqn0yiJL3dGgCjeOeWS6DANBgkqhkiG9w0BAQsFADBw -MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK -ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UEAwwQ -aG90dHVuYUBtYWlsLmkycDAeFw0xNjExMDkwMzE1MzJaFw0yNjExMDkwMzE1MzJa -MHAxCzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgxHjAcBgNV -BAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRkwFwYDVQQD -DBBob3R0dW5hQG1haWwuaTJwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC -AgEA21Bfgcc9VVH4l2u1YvYlTw2OPUyQb16X2IOW0PzdsUO5W78Loueu974BkiKi -84lQZanLr0OwEopdfutGc6gegSLmwaWx5YCG5uwpLOPkDiObfX+nptH6As/B1cn+ -mzejYdVKRnWd7EtHW0iseSsILBK1YbGw4AGpXJ8k18DJSzUt2+spOkpBW6XqectN -8y2JDSTns8yiNxietVeRN/clolDXT9ZwWHkd+QMHTKhgl3Uz1knOffU0L9l4ij4E -oFgPfQo8NL63kLM24hF1hM/At7XvE4iOlObFwPXE+H5EGZpT5+A7Oezepvd/VMzM -tCJ49hM0OlR393tKFONye5GCYeSDJGdPEB6+rBptpRrlch63tG9ktpCRrg2wQWgC -e3aOE1xVRrmwiTZ+jpfsOCbZrrSA/C4Bmp6AfGchyHuDGGkRU/FJwa1YLJe0dkWG -ITLWeh4zeVuAS5mctdv9NQ5wflSGz9S8HjsPBS5+CDOFHh4cexXRG3ITfk6aLhuY -KTMlkIO4SHKmnwAvy1sFlsqj6PbfVjpHPLg625fdNxBpe57TLxtIdBB3C7ccQSRW -+UG6Cmbcmh80PbsSR132NLMlzLhbaOjxeCWWJRo6cLuHBptAFMNwqsXt8xVf9M0N -NdJoKUmblyvjnq0N8aMEqtQ1uGMTaCB39cutHQq+reD/uzsCAwEAAaNdMFswDgYD -VR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNV -HRMBAf8EBTADAQH/MBkGA1UdDgQSBBBob3R0dW5hQG1haWwuaTJwMA0GCSqGSIb3 -DQEBCwUAA4ICAQCibFV8t4pajP176u3jx31x1kgqX6Nd+0YFARPZQjq99kUyoZer -GyHGsMWgM281RxiZkveHxR7Hm7pEd1nkhG3rm+d7GdJ2p2hujr9xUvl0zEqAAqtm -lkYI6uJ13WBjFc9/QuRIdeIeSUN+eazSXNg2nJhoV4pF9n2Q2xDc9dH4GWO93cMX -JPKVGujT3s0b7LWsEguZBPdaPW7wwZd902Cg/M5fE1hZQ8/SIAGUtylb/ZilVeTS -spxWP1gX3NT1SSvv0s6oL7eADCgtggWaMxEjZhi6WMnPUeeFY8X+6trkTlnF9+r/ -HiVvvzQKrPPtB3j1xfQCAF6gUKN4iY+2AOExv4rl/l+JJbPhpd/FuvD8AVkLMZ8X -uPe0Ew2xv30cc8JjGDzQvoSpBmVTra4f+xqH+w8UEmxnx97Ye2aUCtnPykACnFte -oT97K5052B1zq+4fu4xaHZnEzPYVK5POzOufNLPgciJsWrR5GDWtHd+ht/ZD37+b -+j1BXpeBWUBQgluFv+lNMVNPJxc2OMELR1EtEwXD7mTuuUEtF5Pi63IerQ5LzD3G -KBvXhMB0XhpE6WG6pBwAvkGf5zVv/CxClJH4BQbdZwj9HYddfEQlPl0z/XFR2M0+ -9/8nBfGSPYIt6KeHBCeyQWTdE9gqSzMwTMFsennXmaT8gyc7eKqKF6adqw== ------END CERTIFICATE----- diff --git a/contrib/certificates/router/killyourtv_at_mail.i2p.crt b/contrib/certificates/router/killyourtv_at_mail.i2p.crt deleted file mode 100644 index 597f455f..00000000 --- a/contrib/certificates/router/killyourtv_at_mail.i2p.crt +++ /dev/null @@ -1,32 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFhTCCA22gAwIBAgIELuRWgDANBgkqhkiG9w0BAQ0FADBzMQswCQYDVQQGEwJY -WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt -b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEcMBoGA1UEAwwTa2lsbHlvdXJ0dkBt -YWlsLmkycDAeFw0xMzEwMDYyMTM5MzFaFw0yMzEwMDYyMTM5MzFaMHMxCzAJBgNV -BAYTAlhYMQswCQYDVQQIEwJYWDELMAkGA1UEBxMCWFgxHjAcBgNVBAoTFUkyUCBB -bm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRwwGgYDVQQDDBNraWxseW91 -cnR2QG1haWwuaTJwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAig3u -niLWm0y/TFJtciHgmWUt20FOdQrxkiSZ87G8xjuGfq7TbGIiVDn7pQZcHidpq+Dk -47sm+Swqhb4psSijj0AXUEVKlV39jF5IZE+VUgmEtMqQbnBkWudaTJPWcEe9T/Kd -8Oz2jgsnrD/EGVTMKBBjt/gk8VqTWvpCdCF1GhqcCeUTFHzjhN9jtoRCaJ2DClpO -Px+86+d3s9PqUFo8gcD/dbbyJCMqUCMBLtIy/Ooouxb9cfWtXfyOlphU+enmdvuA -0BDewb9pOJg2/kVd9/9moDWcBGChLOlfSlxpDwyUtcclcpvwnG7c6o4or6gqLeOf -AbCpse623utV7fWlFWG7M4AQ/2emhhe4YoMJQnflydzV8bPRJxRTeW1j/9UfpvLT -nO5LHp0oBXE0GqAPjxuAr+r5IDXFbkKYNjK5oWQB/Ul3LkexulYdCzHWbGd1Ja5b -sbiOy6t/hH6G8DD75HYb+PQZaNZWBv90EyOq1JDSUPw6nxVbhiBldi3ipc8/1X51 -FbzBqJ+QO1XKrKqxWxBKoTekuy38KRzsmkSCpY+WJ9f0gLOKtxzVO2HNNqqVFGQf -RGIbrNA0JSRQ1fgelccfrcRIXIZ3B8Tk/wxCIzCY6Yvg2jezz2xJkVdqOUsznS2v -+xJe67PYIAeMVtcfO4kmuCvyIYhsUEpob2n/5lkCAwEAAaMhMB8wHQYDVR0OBBYE -FCLneov6QMtvra5FSoSLhdymi++rMA0GCSqGSIb3DQEBDQUAA4ICAQAIcqbiwjdQ -M9VlGBiHe5eVsL6OM9zfRqR1wnRg4Q6ce65XDfEOYleBWaaNJA4BdykcA4fkUN1h -M2D9FDQScsyPTOuzJ6o75TYh0JOtF51yCi9iuemcosxAwsm90ZXGuMDfDYeyND5c -PAkWfyCP+jwLYbNo/hkNqyv+XWHXPQmT2adRnPXINVUQuBxVPC//C9wv2uDYWhgS -f8M425VPp4/R/uks9mlzTx08DwacvouD0YOC+HZE4sWq+2smgeBInMiyr/THYzl+ -baMtYgVs8IKUD2gtjfXZoaQNg3eq5SedSf/5F0S/LCdu9/ccQ8CzSEoVTiQFtO78 -SaU37xai8+QTSVpPuINigxCoXmkubBd+voEmWRcBd/XB5L+u+MFU/jXyyBj2BXVj -6agqVzY53KVYt23/63QliAUWyxT+ns9gRxVN1jrMhHdiDwsdT4NbzHxg1Su4eiHv -C/wjD3Dga0BRTEGylpHZGzb1U1rZRHM3ho3f1QkmRPPLcBUMTyUTxJm+GEeuhPvp -+TBf3Kg/YkdpnEMlagqcyHuIrf3m8Z/pTmpOIbekJWbbA7tluvWbMWw2ARB7dUOE -fHYVISh0DTw2oVXxM82/q8XXHnhEXv2nW3K40x1VabxUN+sF4M/7YA8nJqwsPJei -749STYJRfZXdIe69M9zpM5unxENAsiPJgQ== ------END CERTIFICATE----- diff --git a/contrib/certificates/router/str4d_at_mail.i2p.crt b/contrib/certificates/router/str4d_at_mail.i2p.crt deleted file mode 100644 index b01c7e32..00000000 --- a/contrib/certificates/router/str4d_at_mail.i2p.crt +++ /dev/null @@ -1,32 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFezCCA2OgAwIBAgIEHLJfZzANBgkqhkiG9w0BAQ0FADBuMQswCQYDVQQGEwJY -WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt -b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEXMBUGA1UEAwwOc3RyNGRAbWFpbC5p -MnAwHhcNMTMxMDI2MTExODQxWhcNMjMxMDI2MTExODQxWjBuMQswCQYDVQQGEwJY -WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt -b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEXMBUGA1UEAwwOc3RyNGRAbWFpbC5p -MnAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvw0vTay1IPOgxvwe8 -yt5jGakha20kw9qDb6zbEL87EWEkeOzdu7iUC69lkxVP9Ws8EbLtkeMf/CXg6CC1 -e+w8WpOHj5prOsiOlrIO+2I1tKMaMUuJDX2wK4I5ZSw/Kieimh9xqOBZknDmtwjw -2HPW8rpxMqrScaGAP6sQD8Gh4XKKkLogfxYPzF8NnC6O8vBkFKVU2WSVZ0jPAQfv -6luPdA+5lES+5UPWr9Yhv/CX4siGKUTxchqJRf2VU4o5BzzXae4asVA/NY7lKgEw -eDDufbm0mRFWP4mbmXRlODuJ8GMnJbMQkNcAvZUnUcvpSTnGnIvxyxtXP5P6ic8V -3b9HV2eIsbfO1xrgyr6/9qgGpXcdDJejhvNg6fZgQeO40bOGQYwV8bNvsNQHqnZl -KsVhsMQkOubMxcHTBadcifi8PmdeJ5hxyyqJmyrwkmg2ijnN521M6YkoBzl+8VAi -zLmqKZfvN5t+pb9PZ3U3jHfkeIEwDRYRAOsvVqch5+ZfSv8x/Te6o15zDKPJQtWK -ty42GV1vERw30oSZQdrRRy/+4+HSRs3/Zb368OdAbcr+f/xPvwceYGWPeNNIoZ/x -xkIQE3xgEK+eJyPM9McjlCAezZZclT7fWfiEYNJAiS3fGALi+a+cGYWWULxCXpz+ -y397OHhZBhnh7D9K8aPePB8tCwIDAQABoyEwHzAdBgNVHQ4EFgQUezvGHq3h1gbC -Hs2LLVoll5fIUWMwDQYJKoZIhvcNAQENBQADggIBAF7SG1WBcE1r5eyTp/BLFZfG -iPtvqu+B1L2HutPum/Xf8A5fxR4kcKAKpVdu6vnDzCRAsAC9YvyETgAzI2nfVgLk -l9YZ31tSi6qxnMsQsV5o9lt/q2Rvsf2Zi/Ir8AlWtvnP8YG0Aj/8AG8MyhMLaIdj -M2FuakPs8RqEjoJL9dTOC9VTQpNTwBH9guP9UalWYwlkaXDzMoyO4nswT/GpCpg8 -4m4RO6grzdsEIamD/PCBM5f/vq+y08GaqfXpX9+8CbaX3tdzd3x48wPphmdpkptk -aRELIpLJZiK+Mos7W+0ZS8SHxGDIosjqVsgbZPmk12+VBcVgLOr8W1D7osS4OY59 -2GMUVV/GhoDh8wR/Td5wpZlcPE0NWmljjVg9+1E8ePAyMZy+U1KCiMlRVdRy518O -dOzzUUQGqGQHosRrH0ypS3MGbMLmbuWFRiz7q/3mUmW2xikH9I1t/6ZMNUvh+IWL -kGAaEf2JIv/D8+QsC0Un1W09DgvYz7qmKSeHhBixlLe68vgXtz/Fa+rRMsmPrueo -4wk/u/VyILo0BJP860APJMZbm+DPfGhV9DF9L5Gx9+d/BlduBVGHc+AQSWbU70dS -eH4/rgUYRikWlgwUxjY8/QQTlfx5xl28tG0xdO9libN22z7UwTGfm48BQIdrTyER -hqQ7usTy3oaWD85MbJ0q ------END CERTIFICATE----- diff --git a/contrib/certificates/router/zzz_at_mail.i2p.crt b/contrib/certificates/router/zzz_at_mail.i2p.crt deleted file mode 100644 index 2d6fcba6..00000000 --- a/contrib/certificates/router/zzz_at_mail.i2p.crt +++ /dev/null @@ -1,32 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFdzCCA1+gAwIBAgIEcwrwsjANBgkqhkiG9w0BAQ0FADBsMQswCQYDVQQGEwJY -WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt -b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEVMBMGA1UEAwwMenp6QG1haWwuaTJw -MB4XDTEzMDkzMDE3NDEyNVoXDTIzMDkzMDE3NDEyNVowbDELMAkGA1UEBhMCWFgx -CzAJBgNVBAgTAlhYMQswCQYDVQQHEwJYWDEeMBwGA1UEChMVSTJQIEFub255bW91 -cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxFTATBgNVBAMMDHp6ekBtYWlsLmkycDCC -AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJV4ptvhlfrcize9/ARz4lUy -iLtLMSvSST1BdZjLJTwus05EUs0oiqnv9qXYIWGRB97aKlAmqSxsn4ZgBttCgmev -IkuiZ8kbdqI5YaT98yKW5P2Prt9p9cPbnz5/qjwZ5L9W+k/Itx7bv2pkNEP0NLYo -NrgHHTb1hsyRxc0lfPYk2BwsIi8hIWBHNrRpR41EWFXfqPcdsxS8cQhxVj4zLG/R -aMm4H8T+V1R1Khl4R4qqRgXBP305xqqRoawHmZ/S9/RkF0Ji6IYwBq9iWthWol6W -sMDn1xhZk9765fk+ohAC2XWuGSFCr02JOILRV3x/8OUxT1GYgYjc7FfyWIekg/pZ -yotlhL2I3SMWOH3PdG58iDY121hq/LsSKM9aP20rwtvssnw+8Aex01YDkI3bM6yO -HNi+tRojaJcJciBWv6cuiFKvQdxj/mOhOr0u0lHLlJ4jqES8uvVJkS7X/C4BB7ra -bJYQgumZMYvVQJFIjo8vZxMXue53o65FRidvAUT29ay54UTiL7jRV9w1wHnzLapU -xT1v7kWpWJcZ1zzC8coJjW+6ijkk38cVLb80u1Q4kEbmP2rDxw6jRvmqg6DcCKjK -oqDt+XQ6P5grxAxLT+VMfB404WHHwNs6BB841//4ZnXvy3msMONY/5y0fsblURgh -IS2UG1TAjR+x7+XikGx9AgMBAAGjITAfMB0GA1UdDgQWBBSvx/fCCP8UeHwjN65p -EoHjgRfiIzANBgkqhkiG9w0BAQ0FAAOCAgEAYgVE1Aa/Ok5k+Jvujbx72bktRWXo -Y4UfbWH/426VdgqXt3n9XtJUNM2oI4ODwITM4O15SyXQTLJhnvJz5ELcJV8nqviZ -RjK2HNX1BW7IEta3tacCvVnjzZ265kCT59uW+qmd+5PiaAYI5lYUn8P6pe+6neSa -HW6ecXCrdxJetSYfUUuKeV6YHpdzfjtZClLmwl91sJUBKcjK+Q9G/cE6HnwcDH1s -uXr7SgkBt/qc/OlNuu4fnTqUA58TAumdq9cD+eLBilDFrux1HsUZMuBUp64x5oPi -gme+3VewsczfFEtrxaG6+l6UA40Lerdx9XECZcDCcFsK6MS1uQ2HYjsyZcWnNT3l -6eDNUbjrllwxDdRAk0cbWiMuc21CFq/1v2QMXk88EiBjEajqzyXUPmKzwFhit6pr -5kfjfXNq+pxQSCoaqjpzVKjb3CqMhSlC8cLgrPw6HEgGnjCy4cTLFHlVmD64M778 -tj6rE7CntcmUi8GKmZKyaMyUo3QQUcrjO5IQ4+3iGUgMkZuujyjrZiOJbvircPmK -4IQEXzJ/G00upqtqKstRybaWSbJ/k6iuturtA2n8MJiCBjhLy8dtTgDbFaDaNF7F -NHeqQjIJDLhYDy6mi4gya3A0ort777Inl/rWYLo067pYM+EWDw66GdpbEIB0Bp71 -pwvcQcjIzbUzEK0= ------END CERTIFICATE----- diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index 7c3edf24..5ca03f4c 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -17,13 +17,13 @@ RUN mkdir -p "$I2PD_HOME" "$DATA_DIR" \ && chown -R i2pd:nobody "$I2PD_HOME" # -# Each RUN is a layer, adding the dependencies and building i2pd in one layer takes around 8-900Mb, so to keep the +# Each RUN is a layer, adding the dependencies and building i2pd in one layer takes around 8-900Mb, so to keep the # image under 20mb we need to remove all the build dependencies in the same "RUN" / layer. # -# 1. install deps, clone and build. -# 2. strip binaries. -# 3. Purge all dependencies and other unrelated packages, including build directory. +# 1. install deps, clone and build. +# 2. strip binaries. +# 3. Purge all dependencies and other unrelated packages, including build directory. RUN apk --no-cache --virtual build-dependendencies add make gcc g++ libtool boost-dev build-base openssl-dev openssl git \ && mkdir -p /tmp/build \ && cd /tmp/build && git clone -b ${GIT_BRANCH} ${REPO_URL} \ diff --git a/contrib/i2pd.conf b/contrib/i2pd.conf index d9fe951b..c87a2c0b 100644 --- a/contrib/i2pd.conf +++ b/contrib/i2pd.conf @@ -54,7 +54,7 @@ ipv4 = true ipv6 = false ## Network interface to bind to -# ifname = +# ifname = ## Enable NTCP transport (default = true) # ntcp = true @@ -88,18 +88,18 @@ ipv6 = false [upnp] ## Enable or disable UPnP: automatic port forwarding (enabled by default in WINDOWS, ANDROID) -# enabled = false +# enabled = false ## Name i2pd appears in UPnP forwardings list (default = I2Pd) # name = I2Pd [reseed] -## Enable or disable reseed data verification. +## Enable or disable reseed data verification. verify = true ## URLs to request reseed data from, separated by comma ## Default: "mainline" I2P Network reseeds # urls = https://reseed.i2p-projekt.de/,https://i2p.mooo.com/netDb/,https://netdb.i2p2.no/ -## Path to local reseed data file (.su3) for manual reseeding +## Path to local reseed data file (.su3) for manual reseeding # file = /path/to/i2pseeds.su3 ## or HTTPS URL to reseed from # file = https://legit-website.com/i2pseeds.su3 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 5eb78e34..0b6fa463 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -48,7 +48,7 @@ using dedicated user's permissions. %build cd build -%if 0%{?rhel} == 7 +%if 0%{?rhel} == 7 %cmake3 \ -DWITH_LIBRARY=OFF \ -DWITH_UPNP=ON \ @@ -133,7 +133,7 @@ getent passwd i2pd >/dev/null || \ - Fixed QT GUI issues * Thu Aug 17 2017 orignal - 2.15.0 -- Added QT GUI +- Added QT GUI - Added ability add and remove I2P tunnels without restart - Added ability to disable SOCKS outproxy option - Changed strip-out Accept-* hedaers in HTTP proxy diff --git a/daemon/Daemon.cpp b/daemon/Daemon.cpp index 658bf011..54146d5d 100644 --- a/daemon/Daemon.cpp +++ b/daemon/Daemon.cpp @@ -123,7 +123,7 @@ namespace i2p LogPrint(eLogInfo, "AESNI enabled"); #endif #if defined(__AVX__) - LogPrint(eLogInfo, "AVX enabled"); + LogPrint(eLogInfo, "AVX enabled"); #endif LogPrint(eLogDebug, "FS: main config file: ", config); LogPrint(eLogDebug, "FS: data directory: ", datadir); diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 5faa8b7f..017bc8a4 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -505,7 +505,7 @@ namespace http { s << " Graceful shutdown
\r\n"; #endif s << " Force shutdown
\r\n"; - + s << "
\r\nLogging level
\r\n"; s << " [none] "; s << " [error] "; diff --git a/daemon/HTTPServer.h b/daemon/HTTPServer.h index ec718532..f1ca10fc 100644 --- a/daemon/HTTPServer.h +++ b/daemon/HTTPServer.h @@ -10,12 +10,12 @@ #include #include "HTTP.h" -namespace i2p +namespace i2p { -namespace http +namespace http { - const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192; - const int TOKEN_EXPIRATION_TIMEOUT = 30; // in seconds + const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192; + const int TOKEN_EXPIRATION_TIMEOUT = 30; // in seconds class HTTPConnection: public std::enable_shared_from_this { @@ -23,7 +23,7 @@ namespace http HTTPConnection (std::shared_ptr socket); void Receive (); - + private: void HandleReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred); @@ -63,11 +63,11 @@ namespace http private: void Run (); - void Accept (); + void Accept (); void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr newSocket); void CreateConnection(std::shared_ptr newSocket); - + private: bool m_IsRunning; diff --git a/daemon/I2PControl.cpp b/daemon/I2PControl.cpp index 7ba6ebea..494ea026 100644 --- a/daemon/I2PControl.cpp +++ b/daemon/I2PControl.cpp @@ -67,7 +67,7 @@ namespace client m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler; // I2PControl - m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler; + m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler; // RouterInfo m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler; @@ -80,13 +80,13 @@ namespace client m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler; m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler; m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] = -&I2PControlService::TunnelsSuccessRateHandler; +&I2PControlService::TunnelsSuccessRateHandler; m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes; m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes; - // RouterManager + // RouterManager m_RouterManagerHandlers["Reseed"] = &I2PControlService::ReseedHandler; - m_RouterManagerHandlers["Shutdown"] = &I2PControlService::ShutdownHandler; + m_RouterManagerHandlers["Shutdown"] = &I2PControlService::ShutdownHandler; m_RouterManagerHandlers["ShutdownGraceful"] = &I2PControlService::ShutdownGracefulHandler; // NetworkSetting @@ -133,8 +133,8 @@ namespace client m_Service.run (); } catch (std::exception& ex) { LogPrint (eLogError, "I2PControl: runtime exception: ", ex.what ()); - } - } + } + } } void I2PControlService::Accept () @@ -160,7 +160,7 @@ namespace client void I2PControlService::Handshake (std::shared_ptr socket) { socket->async_handshake(boost::asio::ssl::stream_base::server, - std::bind( &I2PControlService::HandleHandshake, this, std::placeholders::_1, socket)); + std::bind( &I2PControlService::HandleHandshake, this, std::placeholders::_1, socket)); } void I2PControlService::HandleHandshake (const boost::system::error_code& ecode, std::shared_ptr socket) @@ -168,7 +168,7 @@ namespace client if (ecode) { LogPrint (eLogError, "I2PControl: handshake error: ", ecode.message ()); return; - } + } //std::this_thread::sleep_for (std::chrono::milliseconds(5)); ReadRequest (socket); } @@ -187,15 +187,15 @@ namespace client } void I2PControlService::HandleRequestReceived (const boost::system::error_code& ecode, - size_t bytes_transferred, std::shared_ptr socket, + size_t bytes_transferred, std::shared_ptr socket, std::shared_ptr buf) { - if (ecode) + if (ecode) { LogPrint (eLogError, "I2PControl: read error: ", ecode.message ()); return; - } - else + } + else { bool isHtml = !memcmp (buf->data (), "POST", 4); try @@ -243,8 +243,8 @@ namespace client response << "{\"id\":" << id << ",\"result\":{"; (this->*(it->second))(pt.get_child ("params"), response); response << "},\"jsonrpc\":\"2.0\"}"; - } - else + } + else { LogPrint (eLogWarning, "I2PControl: unknown method ", method); response << "{\"id\":null,\"error\":"; @@ -337,9 +337,9 @@ namespace client InsertParam (results, "API", api); results << ","; std::string token = boost::lexical_cast(i2p::util::GetSecondsSinceEpoch ()); - m_Tokens.insert (token); + m_Tokens.insert (token); InsertParam (results, "Token", token); - } + } void I2PControlService::EchoHandler (const boost::property_tree::ptree& params, std::ostringstream& results) { @@ -364,7 +364,7 @@ namespace client } else LogPrint (eLogError, "I2PControl: I2PControl unknown request: ", it.first); - } + } } void I2PControlService::PasswordHandler (const std::string& value) @@ -394,28 +394,28 @@ namespace client void I2PControlService::UptimeHandler (std::ostringstream& results) { - InsertParam (results, "i2p.router.uptime", (int)i2p::context.GetUptime ()*1000); + InsertParam (results, "i2p.router.uptime", (int)i2p::context.GetUptime ()*1000); } void I2PControlService::VersionHandler (std::ostringstream& results) { InsertParam (results, "i2p.router.version", VERSION); - } + } void I2PControlService::StatusHandler (std::ostringstream& results) { auto dest = i2p::client::context.GetSharedLocalDestination (); - InsertParam (results, "i2p.router.status", (dest && dest->IsReady ()) ? "1" : "0"); + InsertParam (results, "i2p.router.status", (dest && dest->IsReady ()) ? "1" : "0"); } void I2PControlService::NetDbKnownPeersHandler (std::ostringstream& results) { - InsertParam (results, "i2p.router.netdb.knownpeers", i2p::data::netdb.GetNumRouters ()); + InsertParam (results, "i2p.router.netdb.knownpeers", i2p::data::netdb.GetNumRouters ()); } void I2PControlService::NetDbActivePeersHandler (std::ostringstream& results) { - InsertParam (results, "i2p.router.netdb.activepeers", (int)i2p::transport::transports.GetPeers ().size ()); + InsertParam (results, "i2p.router.netdb.activepeers", (int)i2p::transport::transports.GetPeers ().size ()); } void I2PControlService::NetStatusHandler (std::ostringstream& results) @@ -463,11 +463,11 @@ namespace client { for (auto it = params.begin (); it != params.end (); it++) { - if (it != params.begin ()) results << ","; + if (it != params.begin ()) results << ","; LogPrint (eLogDebug, "I2PControl: RouterManager request: ", it->first); auto it1 = m_RouterManagerHandlers.find (it->first); if (it1 != m_RouterManagerHandlers.end ()) { - (this->*(it1->second))(results); + (this->*(it1->second))(results); } else LogPrint (eLogError, "I2PControl: RouterManager unknown request: ", it->first); } @@ -516,7 +516,7 @@ namespace client auto it1 = m_NetworkSettingHandlers.find (it->first); if (it1 != m_NetworkSettingHandlers.end ()) { if (it != params.begin ()) results << ","; - (this->*(it1->second))(it->second.data (), results); + (this->*(it1->second))(it->second.data (), results); } else LogPrint (eLogError, "I2PControl: NetworkSetting unknown request: ", it->first); } @@ -538,7 +538,7 @@ namespace client InsertParam (results, "i2p.router.net.bw.out", bw); } - // certificate + // certificate void I2PControlService::CreateCertificate (const char *crt_path, const char *key_path) { FILE *f = NULL; diff --git a/daemon/I2PControl.h b/daemon/I2PControl.h index 5d81c8f6..a7ed1eab 100644 --- a/daemon/I2PControl.h +++ b/daemon/I2PControl.h @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include namespace i2p diff --git a/daemon/UPnP.h b/daemon/UPnP.h index 7d67fdbf..5313a1c4 100644 --- a/daemon/UPnP.h +++ b/daemon/UPnP.h @@ -42,13 +42,13 @@ namespace transport std::string GetProto (std::shared_ptr address); private: - + bool m_IsRunning; std::unique_ptr m_Thread; - std::condition_variable m_Started; - std::mutex m_StartedMutex; + std::condition_variable m_Started; + std::mutex m_StartedMutex; boost::asio::io_service m_Service; - boost::asio::deadline_timer m_Timer; + boost::asio::deadline_timer m_Timer; struct UPNPUrls m_upnpUrls; struct IGDdatas m_upnpData; diff --git a/daemon/UnixDaemon.cpp b/daemon/UnixDaemon.cpp index f282f2d4..075aa7d8 100644 --- a/daemon/UnixDaemon.cpp +++ b/daemon/UnixDaemon.cpp @@ -163,7 +163,7 @@ namespace i2p sigaction(SIGABRT, &sa, 0); sigaction(SIGTERM, &sa, 0); sigaction(SIGINT, &sa, 0); - sigaction(SIGPIPE, &sa, 0); + sigaction(SIGPIPE, &sa, 0); return Daemon_Singleton::start(); } diff --git a/debian/changelog b/debian/changelog index c07926f3..94105535 100644 --- a/debian/changelog +++ b/debian/changelog @@ -62,7 +62,7 @@ i2pd (2.10.0-1) unstable; urgency=low * updated to version 2.10.0/0.9.27 * reseed.verify set to true by default - + -- orignal Sun, 16 Oct 2016 13:55:40 +0000 i2pd (2.9.0-1) unstable; urgency=low @@ -73,7 +73,7 @@ i2pd (2.9.0-1) unstable; urgency=low * removed all port assigments in services files * fixed logrotate * subscriptions.txt and tunnels.conf taken from docs folder - + -- orignal Fri, 12 Aug 2016 14:25:40 +0000 i2pd (2.7.0-1) unstable; urgency=low diff --git a/debian/i2pd.default b/debian/i2pd.default index 5ac311c3..bd1d073f 100644 --- a/debian/i2pd.default +++ b/debian/i2pd.default @@ -7,5 +7,5 @@ I2PD_ENABLED="yes" # see possible switches in /usr/share/doc/i2pd/configuration.md.gz DAEMON_OPTS="" -# If you have problems with hunging i2pd, you can try enable this +# If you have problems with hunging i2pd, you can try enable this ulimit -n 4096 diff --git a/debian/patches/01-tune-build-opts.patch b/debian/patches/01-tune-build-opts.patch index 4420d387..2dff9e09 100644 --- a/debian/patches/01-tune-build-opts.patch +++ b/debian/patches/01-tune-build-opts.patch @@ -1,12 +1,11 @@ diff --git a/Makefile b/Makefile index bdadfe0..2f71eec 100644 - --- a/Makefile +++ b/Makefile @@ -9,10 +9,10 @@ DEPS := obj/make.dep - + include filelist.mk - + -USE_AESNI := yes +USE_AESNI := no -USE_AVX := yes diff --git a/libi2pd/Base.cpp b/libi2pd/Base.cpp index 35aae437..09f04c05 100644 --- a/libi2pd/Base.cpp +++ b/libi2pd/Base.cpp @@ -43,8 +43,8 @@ namespace data const char * GetBase64SubstitutionTable () { return T64; - } - + } + /* * Reverse Substitution Table (built in run time) */ @@ -53,10 +53,10 @@ namespace data static int isFirstTime = 1; /* - * Padding + * Padding */ - static char P64 = '='; + static char P64 = '='; /* * @@ -68,11 +68,11 @@ namespace data */ size_t /* Number of bytes in the encoded buffer */ - ByteStreamToBase64 ( + ByteStreamToBase64 ( const uint8_t * InBuffer, /* Input buffer, binary data */ - size_t InCount, /* Number of bytes in the input buffer */ + size_t InCount, /* Number of bytes in the input buffer */ char * OutBuffer, /* output buffer */ - size_t len /* length of output buffer */ + size_t len /* length of output buffer */ ) { @@ -80,9 +80,9 @@ namespace data unsigned char * pd; unsigned char acc_1; unsigned char acc_2; - int i; - int n; - int m; + int i; + int n; + int m; size_t outCount; ps = (unsigned char *)InBuffer; @@ -96,7 +96,7 @@ namespace data pd = (unsigned char *)OutBuffer; for ( i = 0; i>= 2; /* base64 digit #1 */ *pd++ = T64[acc_1]; acc_1 = *ps++; @@ -109,7 +109,7 @@ namespace data *pd++ = T64[acc_1]; acc_2 &= 0x3f; /* base64 digit #4 */ *pd++ = T64[acc_2]; - } + } if ( m == 1 ){ acc_1 = *ps++; acc_2 = (acc_1<<4)&0x3f; /* base64 digit #2 */ @@ -122,7 +122,7 @@ namespace data } else if ( m == 2 ){ acc_1 = *ps++; - acc_2 = (acc_1<<4)&0x3f; + acc_2 = (acc_1<<4)&0x3f; acc_1 >>= 2; /* base64 digit #1 */ *pd++ = T64[acc_1]; acc_1 = *ps++; @@ -133,7 +133,7 @@ namespace data *pd++ = T64[acc_1]; *pd++ = P64; } - + return outCount; } @@ -148,10 +148,10 @@ namespace data */ size_t /* Number of output bytes */ - Base64ToByteStream ( + Base64ToByteStream ( const char * InBuffer, /* BASE64 encoded buffer */ size_t InCount, /* Number of input bytes */ - uint8_t * OutBuffer, /* output buffer length */ + uint8_t * OutBuffer, /* output buffer length */ size_t len /* length of output buffer */ ) { @@ -159,28 +159,28 @@ namespace data unsigned char * pd; unsigned char acc_1; unsigned char acc_2; - int i; - int n; - int m; + int i; + int n; + int m; size_t outCount; if (isFirstTime) iT64Build(); n = InCount/4; m = InCount%4; - if (InCount && !m) + if (InCount && !m) outCount = 3*n; else { outCount = 0; return 0; } - + ps = (unsigned char *)(InBuffer + InCount - 1); while ( *ps-- == P64 ) outCount--; ps = (unsigned char *)InBuffer; - + if (outCount > len) return -1; pd = OutBuffer; - auto endOfOutBuffer = OutBuffer + outCount; + auto endOfOutBuffer = OutBuffer + outCount; for ( i = 0; i < n; i++ ){ acc_1 = iT64[*ps++]; acc_2 = iT64[*ps++]; @@ -193,7 +193,7 @@ namespace data acc_1 = iT64[*ps++]; acc_2 |= acc_1 >> 2; *pd++ = acc_2; - if (pd >= endOfOutBuffer) break; + if (pd >= endOfOutBuffer) break; acc_2 = iT64[*ps++]; acc_2 |= acc_1 << 6; @@ -203,13 +203,13 @@ namespace data return outCount; } - size_t Base64EncodingBufferSize (const size_t input_size) + size_t Base64EncodingBufferSize (const size_t input_size) { auto d = div (input_size, 3); if (d.rem) d.quot++; return 4*d.quot; } - + /* * * iT64 @@ -228,20 +228,20 @@ namespace data iT64[(int)P64] = 0; } - size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen) + size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen) { int tmp = 0, bits = 0; size_t ret = 0; for (size_t i = 0; i < len; i++) { - char ch = inBuf[i]; + char ch = inBuf[i]; if (ch >= '2' && ch <= '7') // digit ch = (ch - '2') + 26; // 26 means a-z else if (ch >= 'a' && ch <= 'z') ch = ch - 'a'; // a = 0 else return 0; // unexpected character - + tmp |= ch; bits += 5; if (bits >= 8) @@ -261,23 +261,23 @@ namespace data size_t ret = 0, pos = 1; int bits = 8, tmp = inBuf[0]; while (ret < outLen && (bits > 0 || pos < len)) - { + { if (bits < 5) { if (pos < len) { tmp <<= 8; - tmp |= inBuf[pos] & 0xFF; + tmp |= inBuf[pos] & 0xFF; pos++; - bits += 8; + bits += 8; } else // last byte { tmp <<= (5 - bits); - bits = 5; + bits = 5; } - } - + } + bits -= 5; int ind = (tmp >> bits) & 0x1F; outBuf[ret] = (ind < 26) ? (ind + 'a') : ((ind - 26) + '2'); diff --git a/libi2pd/Base.h b/libi2pd/Base.h index 66192d1b..bc92376f 100644 --- a/libi2pd/Base.h +++ b/libi2pd/Base.h @@ -10,8 +10,8 @@ namespace data { size_t ByteStreamToBase64 (const uint8_t * InBuffer, size_t InCount, char * OutBuffer, size_t len); size_t Base64ToByteStream (const char * InBuffer, size_t InCount, uint8_t * OutBuffer, size_t len ); const char * GetBase32SubstitutionTable (); - const char * GetBase64SubstitutionTable (); - + const char * GetBase64SubstitutionTable (); + size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen); size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen); diff --git a/libi2pd/Config.h b/libi2pd/Config.h index c920c6fe..0bbcd5b1 100644 --- a/libi2pd/Config.h +++ b/libi2pd/Config.h @@ -79,10 +79,10 @@ namespace config { } template - bool GetOption(const std::string& name, T& value) + bool GetOption(const std::string& name, T& value) { return GetOption (name.c_str (), value); - } + } bool GetOptionAsAny(const char *name, boost::any& value); bool GetOptionAsAny(const std::string& name, boost::any& value); diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index fd0ef4bd..6109529d 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -22,7 +22,7 @@ namespace crypto 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD, 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45, 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, - 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, + 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED, 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D, 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F, diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 2b1bf6a0..e495d2e6 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -24,7 +24,7 @@ namespace crypto bool bn2buf (const BIGNUM * bn, uint8_t * buf, size_t len); // DSA - DSA * CreateDSA (); + DSA * CreateDSA (); // RSA const BIGNUM * GetRSAE (); @@ -33,20 +33,20 @@ namespace crypto class DHKeys { public: - + DHKeys (); ~DHKeys (); void GenerateKeys (); const uint8_t * GetPublicKey () const { return m_PublicKey; }; void Agree (const uint8_t * pub, uint8_t * shared); - + private: DH * m_DH; uint8_t m_PublicKey[256]; - }; - + }; + // ElGamal void ElGamalEncrypt (const uint8_t * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding = false); bool ElGamalDecrypt (const uint8_t * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding = false); @@ -54,15 +54,15 @@ namespace crypto // ECIES void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx); // 222 bytes data, 514 bytes encrypted - bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx); + bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx); void GenerateECIESKeyPair (const EC_GROUP * curve, BIGNUM *& priv, EC_POINT *& pub); - + // HMAC - typedef i2p::data::Tag<32> MACKey; + typedef i2p::data::Tag<32> MACKey; void HMACMD5Digest (uint8_t * msg, size_t len, const MACKey& key, uint8_t * digest); // AES - struct ChipherBlock + struct ChipherBlock { uint8_t buf[16]; @@ -71,40 +71,40 @@ namespace crypto #if defined(__AVX__) // AVX __asm__ ( - "vmovups (%[buf]), %%xmm0 \n" - "vmovups (%[other]), %%xmm1 \n" + "vmovups (%[buf]), %%xmm0 \n" + "vmovups (%[other]), %%xmm1 \n" "vxorps %%xmm0, %%xmm1, %%xmm0 \n" - "vmovups %%xmm0, (%[buf]) \n" - : - : [buf]"r"(buf), [other]"r"(other.buf) + "vmovups %%xmm0, (%[buf]) \n" + : + : [buf]"r"(buf), [other]"r"(other.buf) : "%xmm0", "%xmm1", "memory" - ); + ); #elif defined(__SSE__) // SSE __asm__ ( - "movups (%[buf]), %%xmm0 \n" - "movups (%[other]), %%xmm1 \n" + "movups (%[buf]), %%xmm0 \n" + "movups (%[other]), %%xmm1 \n" "pxor %%xmm1, %%xmm0 \n" "movups %%xmm0, (%[buf]) \n" - : - : [buf]"r"(buf), [other]"r"(other.buf) + : + : [buf]"r"(buf), [other]"r"(other.buf) : "%xmm0", "%xmm1", "memory" - ); + ); #else // TODO: implement it better for (int i = 0; i < 16; i++) buf[i] ^= other.buf[i]; #endif - } + } }; typedef i2p::data::Tag<32> AESKey; - + template class AESAlignedBuffer // 16 bytes alignment { public: - + AESAlignedBuffer () { m_Buf = m_UnalignedBuffer; @@ -112,22 +112,22 @@ namespace crypto if (rem) m_Buf += (16 - rem); } - + operator uint8_t * () { return m_Buf; }; operator const uint8_t * () const { return m_Buf; }; ChipherBlock * GetChipherBlock () { return (ChipherBlock *)m_Buf; }; const ChipherBlock * GetChipherBlock () const { return (const ChipherBlock *)m_Buf; }; - + private: uint8_t m_UnalignedBuffer[sz + 15]; // up to 15 bytes alignment uint8_t * m_Buf; - }; + }; #ifdef AESNI class ECBCryptoAESNI - { + { public: uint8_t * GetKeySchedule () { return m_KeySchedule; }; @@ -135,27 +135,27 @@ namespace crypto protected: void ExpandKey (const AESKey& key); - + private: AESAlignedBuffer<240> m_KeySchedule; // 14 rounds for AES-256, 240 bytes - }; + }; class ECBEncryptionAESNI: public ECBCryptoAESNI { public: - + void SetKey (const AESKey& key) { ExpandKey (key); }; - void Encrypt (const ChipherBlock * in, ChipherBlock * out); - }; + void Encrypt (const ChipherBlock * in, ChipherBlock * out); + }; class ECBDecryptionAESNI: public ECBCryptoAESNI { public: - + void SetKey (const AESKey& key); - void Decrypt (const ChipherBlock * in, ChipherBlock * out); - }; + void Decrypt (const ChipherBlock * in, ChipherBlock * out); + }; typedef ECBEncryptionAESNI ECBEncryption; typedef ECBDecryptionAESNI ECBDecryption; @@ -165,46 +165,46 @@ namespace crypto class ECBEncryption { public: - - void SetKey (const AESKey& key) - { + + void SetKey (const AESKey& key) + { AES_set_encrypt_key (key, 256, &m_Key); } void Encrypt (const ChipherBlock * in, ChipherBlock * out) { AES_encrypt (in->buf, out->buf, &m_Key); - } + } private: AES_KEY m_Key; - }; + }; class ECBDecryption { public: - - void SetKey (const AESKey& key) - { - AES_set_decrypt_key (key, 256, &m_Key); + + void SetKey (const AESKey& key) + { + AES_set_decrypt_key (key, 256, &m_Key); } void Decrypt (const ChipherBlock * in, ChipherBlock * out) { AES_decrypt (in->buf, out->buf, &m_Key); - } + } private: AES_KEY m_Key; - }; + }; -#endif +#endif class CBCEncryption { public: - + CBCEncryption () { memset ((uint8_t *)m_LastBlock, 0, 16); }; void SetKey (const AESKey& key) { m_ECBEncryption.SetKey (key); }; // 32 bytes @@ -217,14 +217,14 @@ namespace crypto private: AESAlignedBuffer<16> m_LastBlock; - + ECBEncryption m_ECBEncryption; }; class CBCDecryption { public: - + CBCDecryption () { memset ((uint8_t *)m_IV, 0, 16); }; void SetKey (const AESKey& key) { m_ECBDecryption.SetKey (key); }; // 32 bytes @@ -238,7 +238,7 @@ namespace crypto AESAlignedBuffer<16> m_IV; ECBDecryption m_ECBDecryption; - }; + }; class TunnelEncryption // with double IV encryption { @@ -248,9 +248,9 @@ namespace crypto { m_LayerEncryption.SetKey (layerKey); m_IVEncryption.SetKey (ivKey); - } + } - void Encrypt (const uint8_t * in, uint8_t * out); // 1024 bytes (16 IV + 1008 data) + void Encrypt (const uint8_t * in, uint8_t * out); // 1024 bytes (16 IV + 1008 data) private: @@ -270,9 +270,9 @@ namespace crypto { m_LayerDecryption.SetKey (layerKey); m_IVDecryption.SetKey (ivKey); - } + } - void Decrypt (const uint8_t * in, uint8_t * out); // 1024 bytes (16 IV + 1008 data) + void Decrypt (const uint8_t * in, uint8_t * out); // 1024 bytes (16 IV + 1008 data) private: @@ -282,72 +282,72 @@ namespace crypto #else CBCDecryption m_LayerDecryption; #endif - }; - + }; + void InitCrypto (bool precomputation); void TerminateCrypto (); -} -} +} +} // take care about openssl version #include #if (OPENSSL_VERSION_NUMBER < 0x010100000) || defined(LIBRESSL_VERSION_NUMBER) // 1.1.0 or LibreSSL // define getters and setters introduced in 1.1.0 -inline int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) - { +inline int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) + { if (d->p) BN_free (d->p); if (d->q) BN_free (d->q); if (d->g) BN_free (d->g); - d->p = p; d->q = q; d->g = g; return 1; + d->p = p; d->q = q; d->g = g; return 1; } -inline int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) - { +inline int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) + { if (d->pub_key) BN_free (d->pub_key); if (d->priv_key) BN_free (d->priv_key); - d->pub_key = pub_key; d->priv_key = priv_key; return 1; - } -inline void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key) + d->pub_key = pub_key; d->priv_key = priv_key; return 1; + } +inline void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key) { *pub_key = d->pub_key; *priv_key = d->priv_key; } -inline int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) - { +inline int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) + { if (sig->r) BN_free (sig->r); if (sig->s) BN_free (sig->s); - sig->r = r; sig->s = s; return 1; + sig->r = r; sig->s = s; return 1; } -inline void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) +inline void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) { *pr = sig->r; *ps = sig->s; } inline int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) - { + { if (sig->r) BN_free (sig->r); if (sig->s) BN_free (sig->s); - sig->r = r; sig->s = s; return 1; + sig->r = r; sig->s = s; return 1; } inline void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) { *pr = sig->r; *ps = sig->s; } -inline int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) +inline int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) { if (r->n) BN_free (r->n); if (r->e) BN_free (r->e); if (r->d) BN_free (r->d); - r->n = n; r->e = e; r->d = d; return 1; + r->n = n; r->e = e; r->d = d; return 1; } inline void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) { *n = r->n; *e = r->e; *d = r->d; } inline int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) - { + { if (dh->p) BN_free (dh->p); if (dh->q) BN_free (dh->q); if (dh->g) BN_free (dh->g); - dh->p = p; dh->q = q; dh->g = g; return 1; + dh->p = p; dh->q = q; dh->g = g; return 1; } inline int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) - { - if (dh->pub_key) BN_free (dh->pub_key); + { + if (dh->pub_key) BN_free (dh->pub_key); if (dh->priv_key) BN_free (dh->priv_key); - dh->pub_key = pub_key; dh->priv_key = priv_key; return 1; + dh->pub_key = pub_key; dh->priv_key = priv_key; return 1; } inline void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key) { *pub_key = dh->pub_key; *priv_key = dh->priv_key; } diff --git a/libi2pd/CryptoKey.cpp b/libi2pd/CryptoKey.cpp index b1adf2f0..4be230f7 100644 --- a/libi2pd/CryptoKey.cpp +++ b/libi2pd/CryptoKey.cpp @@ -72,7 +72,7 @@ namespace crypto void CreateECIESP256RandomKeys (uint8_t * priv, uint8_t * pub) { EC_GROUP * curve = EC_GROUP_new_by_curve_name (NID_X9_62_prime256v1); - EC_POINT * p = nullptr; + EC_POINT * p = nullptr; BIGNUM * key = nullptr; GenerateECIESKeyPair (curve, key, p); bn2buf (key, priv, 32); @@ -81,11 +81,11 @@ namespace crypto BIGNUM * x = BN_new (), * y = BN_new (); EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, NULL); bn2buf (x, pub, 32); - bn2buf (y, pub + 32, 32); + bn2buf (y, pub + 32, 32); RAND_bytes (pub + 64, 192); - EC_POINT_free (p); + EC_POINT_free (p); BN_free (x); BN_free (y); - EC_GROUP_free (curve); + EC_GROUP_free (curve); } ECIESGOSTR3410Encryptor::ECIESGOSTR3410Encryptor (const uint8_t * pub) @@ -131,7 +131,7 @@ namespace crypto void CreateECIESGOSTR3410RandomKeys (uint8_t * priv, uint8_t * pub) { auto& curve = GetGOSTR3410Curve (eGOSTR3410CryptoProA); - EC_POINT * p = nullptr; + EC_POINT * p = nullptr; BIGNUM * key = nullptr; GenerateECIESKeyPair (curve->GetGroup (), key, p); bn2buf (key, priv, 32); @@ -140,9 +140,9 @@ namespace crypto BIGNUM * x = BN_new (), * y = BN_new (); EC_POINT_get_affine_coordinates_GFp (curve->GetGroup (), p, x, y, NULL); bn2buf (x, pub, 32); - bn2buf (y, pub + 32, 32); + bn2buf (y, pub + 32, 32); RAND_bytes (pub + 64, 192); - EC_POINT_free (p); + EC_POINT_free (p); BN_free (x); BN_free (y); } diff --git a/libi2pd/CryptoKey.h b/libi2pd/CryptoKey.h index a2cfdd87..ece86eb0 100644 --- a/libi2pd/CryptoKey.h +++ b/libi2pd/CryptoKey.h @@ -8,15 +8,15 @@ namespace i2p { namespace crypto { - class CryptoKeyEncryptor + class CryptoKeyEncryptor { public: virtual ~CryptoKeyEncryptor () {}; virtual void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) = 0; // 222 bytes data, 512 bytes encrypted - }; + }; - class CryptoKeyDecryptor + class CryptoKeyDecryptor { public: @@ -30,7 +30,7 @@ namespace crypto public: ElGamalEncryptor (const uint8_t * pub); - void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx); + void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx); private: @@ -42,7 +42,7 @@ namespace crypto public: ElGamalDecryptor (const uint8_t * priv); - bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx); + bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx); private: @@ -51,13 +51,13 @@ namespace crypto // ECIES P256 - class ECIESP256Encryptor: public CryptoKeyEncryptor + class ECIESP256Encryptor: public CryptoKeyEncryptor { public: ECIESP256Encryptor (const uint8_t * pub); ~ECIESP256Encryptor (); - void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx); + void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx); private: @@ -72,7 +72,7 @@ namespace crypto ECIESP256Decryptor (const uint8_t * priv); ~ECIESP256Decryptor (); - bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx); + bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx); private: @@ -80,17 +80,17 @@ namespace crypto BIGNUM * m_PrivateKey; }; - void CreateECIESP256RandomKeys (uint8_t * priv, uint8_t * pub); + void CreateECIESP256RandomKeys (uint8_t * priv, uint8_t * pub); // ECIES GOST R 34.10 - class ECIESGOSTR3410Encryptor: public CryptoKeyEncryptor + class ECIESGOSTR3410Encryptor: public CryptoKeyEncryptor { public: ECIESGOSTR3410Encryptor (const uint8_t * pub); ~ECIESGOSTR3410Encryptor (); - void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx); + void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx); private: @@ -104,7 +104,7 @@ namespace crypto ECIESGOSTR3410Decryptor (const uint8_t * priv); ~ECIESGOSTR3410Decryptor (); - bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx); + bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx); private: diff --git a/libi2pd/Datagram.cpp b/libi2pd/Datagram.cpp index 2af26771..ed87a054 100644 --- a/libi2pd/Datagram.cpp +++ b/libi2pd/Datagram.cpp @@ -11,20 +11,20 @@ namespace i2p { namespace datagram { - DatagramDestination::DatagramDestination (std::shared_ptr owner): + DatagramDestination::DatagramDestination (std::shared_ptr owner): m_Owner (owner.get()), m_Receiver (nullptr) { m_Identity.FromBase64 (owner->GetIdentity()->ToBase64()); } - + DatagramDestination::~DatagramDestination () { m_Sessions.clear(); } void DatagramDestination::SendDatagramTo(const uint8_t * payload, size_t len, const i2p::data::IdentHash & identity, uint16_t fromPort, uint16_t toPort) - { + { auto owner = m_Owner; std::vector v(MAX_DATAGRAM_SIZE); uint8_t * buf = v.data(); @@ -33,11 +33,11 @@ namespace datagram auto signatureLen = m_Identity.GetSignatureLen (); uint8_t * buf1 = signature + signatureLen; size_t headerLen = identityLen + signatureLen; - - memcpy (buf1, payload, len); + + memcpy (buf1, payload, len); if (m_Identity.GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1) { - uint8_t hash[32]; + uint8_t hash[32]; SHA256(buf1, len, hash); owner->Sign (hash, 32, signature); } @@ -63,10 +63,10 @@ namespace datagram uint8_t hash[32]; SHA256(buf + headerLen, len - headerLen, hash); verified = identity.Verify (hash, 32, signature); - } - else + } + else verified = identity.Verify (buf + headerLen, len - headerLen, signature); - + if (verified) { auto h = identity.GetIdentHash(); @@ -79,7 +79,7 @@ namespace datagram LogPrint (eLogWarning, "DatagramDestination: no receiver for port ", toPort); } else - LogPrint (eLogWarning, "Datagram signature verification failed"); + LogPrint (eLogWarning, "Datagram signature verification failed"); } DatagramDestination::Receiver DatagramDestination::FindReceiver(uint16_t port) @@ -113,24 +113,24 @@ namespace datagram { htobe32buf (msg->GetPayload (), size); // length htobe16buf (buf + 4, fromPort); // source port - htobe16buf (buf + 6, toPort); // destination port + htobe16buf (buf + 6, toPort); // destination port buf[9] = i2p::client::PROTOCOL_TYPE_DATAGRAM; // datagram protocol - msg->len += size + 4; + msg->len += size + 4; msg->FillI2NPMessageHeader (eI2NPData); - } + } else msg = nullptr; return msg; } void DatagramDestination::CleanUp () - { + { if (m_Sessions.empty ()) return; auto now = i2p::util::GetMillisecondsSinceEpoch(); LogPrint(eLogDebug, "DatagramDestination: clean up sessions"); std::unique_lock lock(m_SessionsMutex); // for each session ... - for (auto it = m_Sessions.begin (); it != m_Sessions.end (); ) + for (auto it = m_Sessions.begin (); it != m_Sessions.end (); ) { // check if expired if (now - it->second->LastActivity() >= DATAGRAM_SESSION_MAX_IDLE) @@ -143,7 +143,7 @@ namespace datagram it++; } } - + std::shared_ptr DatagramDestination::ObtainSession(const i2p::data::IdentHash & identity) { std::shared_ptr session = nullptr; @@ -169,7 +169,7 @@ namespace datagram } return nullptr; } - + DatagramSession::DatagramSession(i2p::client::ClientDestination * localDestination, const i2p::data::IdentHash & remoteIdent) : m_LocalDestination(localDestination), @@ -203,7 +203,7 @@ namespace datagram { if(!m_RoutingSession) return DatagramSession::Info(nullptr, nullptr, m_LastUse); - + auto routingPath = m_RoutingSession->GetSharedRoutingPath(); if (!routingPath) return DatagramSession::Info(nullptr, nullptr, m_LastUse); @@ -318,7 +318,7 @@ namespace datagram m_RoutingSession->SetSharedRoutingPath(path); } return path; - + } void DatagramSession::HandleLeaseSetUpdated(std::shared_ptr ls) diff --git a/libi2pd/Datagram.h b/libi2pd/Datagram.h index b72d3840..039417ea 100644 --- a/libi2pd/Datagram.h +++ b/libi2pd/Datagram.h @@ -106,7 +106,7 @@ namespace datagram DatagramDestination (std::shared_ptr owner); ~DatagramDestination (); - void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0); + void SendDatagramTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash & ident, uint16_t fromPort = 0, uint16_t toPort = 0); void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void SetReceiver (const Receiver& receiver) { m_Receiver = receiver; }; diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 0c3a1512..33eff029 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -24,9 +24,9 @@ namespace client int outQty = DEFAULT_OUTBOUND_TUNNELS_QUANTITY; int numTags = DEFAULT_TAGS_TO_SEND; std::shared_ptr > explicitPeers; - try + try { - if (params) + if (params) { auto it = params->find (I2CP_PARAM_INBOUND_TUNNEL_LENGTH); if (it != params->end ()) @@ -59,10 +59,16 @@ namespace client } } it = params->find (I2CP_PARAM_INBOUND_NICKNAME); - if (it != params->end ()) m_Nickname = it->second; // otherwise we set deafult nickname in Start when we know local address + if (it != params->end ()) m_Nickname = it->second; + else // try outbound + { + it = params->find (I2CP_PARAM_OUTBOUND_NICKNAME); + if (it != params->end ()) m_Nickname = it->second; + // otherwise we set deafult nickname in Start when we know local address + } } - } - catch (std::exception & ex) + } + catch (std::exception & ex) { LogPrint(eLogError, "Destination: unable to parse parameters for destination: ", ex.what()); } @@ -486,7 +492,7 @@ namespace client m_PublishReplyToken = 0; if (GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL) { - LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again"); + LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again"); Publish (); } else @@ -497,7 +503,7 @@ namespace client m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT)); m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, shared_from_this (), std::placeholders::_1)); - + } } } @@ -722,14 +728,14 @@ namespace client if (isPublic) PersistTemporaryKeys (); else - i2p::data::PrivateKeys::GenerateCryptoKeyPair(GetIdentity ()->GetCryptoKeyType (), + i2p::data::PrivateKeys::GenerateCryptoKeyPair(GetIdentity ()->GetCryptoKeyType (), m_EncryptionPrivateKey, m_EncryptionPublicKey); - m_Decryptor = m_Keys.CreateDecryptor (m_EncryptionPrivateKey); + m_Decryptor = m_Keys.CreateDecryptor (m_EncryptionPrivateKey); if (isPublic) LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created"); // extract streaming params - if (params) + if (params) { auto it = params->find (I2CP_PARAM_STREAMING_INITIAL_ACK_DELAY); if (it != params->end ()) @@ -774,7 +780,7 @@ namespace client delete m_DatagramDestination; m_DatagramDestination = nullptr; } - return true; + return true; } else return false; @@ -950,7 +956,7 @@ namespace client } LogPrint (eLogInfo, "Destination: Creating new temporary keys for address ", ident, ".b32.i2p"); - i2p::data::PrivateKeys::GenerateCryptoKeyPair(GetIdentity ()->GetCryptoKeyType (), + i2p::data::PrivateKeys::GenerateCryptoKeyPair(GetIdentity ()->GetCryptoKeyType (), m_EncryptionPrivateKey, m_EncryptionPublicKey); std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out); diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index d3122b3b..6f37e768 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -51,6 +51,7 @@ namespace client const char I2CP_PARAM_TAGS_TO_SEND[] = "crypto.tagsToSend"; const int DEFAULT_TAGS_TO_SEND = 40; const char I2CP_PARAM_INBOUND_NICKNAME[] = "inbound.nickname"; + const char I2CP_PARAM_OUTBOUND_NICKNAME[] = "outbound.nickname"; // latency const char I2CP_PARAM_MIN_TUNNEL_LATENCY[] = "latency.min"; @@ -189,9 +190,9 @@ namespace client void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); }; // ref counter - int Acquire () { return ++m_RefCounter; }; + int Acquire () { return ++m_RefCounter; }; int Release () { return --m_RefCounter; }; - int GetRefCounter () const { return m_RefCounter; }; + int GetRefCounter () const { return m_RefCounter; }; // streaming std::shared_ptr CreateStreamingDestination (int port, bool gzip = true); // additional @@ -238,7 +239,7 @@ namespace client int m_StreamingAckDelay; std::shared_ptr m_StreamingDestination; // default std::map > m_StreamingDestinationsByPorts; - i2p::datagram::DatagramDestination * m_DatagramDestination; + i2p::datagram::DatagramDestination * m_DatagramDestination; int m_RefCounter; // how many clients(tunnels) use this destination boost::asio::deadline_timer m_ReadyChecker; diff --git a/libi2pd/Event.cpp b/libi2pd/Event.cpp index 4bc6d594..9c75f95b 100644 --- a/libi2pd/Event.cpp +++ b/libi2pd/Event.cpp @@ -30,7 +30,7 @@ namespace i2p } m_collected[key].Val += val; } - + void EventCore::PumpCollected(EventListener * listener) { std::unique_lock lock(m_collect_mutex); diff --git a/libi2pd/Event.h b/libi2pd/Event.h index a9f97df2..a8b46a4b 100644 --- a/libi2pd/Event.h +++ b/libi2pd/Event.h @@ -29,7 +29,7 @@ namespace i2p void CollectEvent(const std::string & type, const std::string & ident, uint64_t val); void SetListener(EventListener * l); void PumpCollected(EventListener * l); - + private: std::mutex m_collect_mutex; struct CollectedEvent @@ -41,7 +41,7 @@ namespace i2p std::map m_collected; EventListener * m_listener = nullptr; }; -#ifdef WITH_EVENTS +#ifdef WITH_EVENTS extern EventCore core; #endif } diff --git a/libi2pd/FS.cpp b/libi2pd/FS.cpp index bceda568..21fb103b 100644 --- a/libi2pd/FS.cpp +++ b/libi2pd/FS.cpp @@ -68,7 +68,7 @@ namespace fs { #else /* other unix */ #if defined(ANDROID) const char * ext = getenv("EXTERNAL_STORAGE"); - if (!ext) ext = "/sdcard"; + if (!ext) ext = "/sdcard"; if (boost::filesystem::exists(ext)) { dataDir = std::string (ext) + "/" + appName; @@ -96,7 +96,7 @@ namespace fs { boost::filesystem::create_directory(destinations); std::string tags = DataDirPath("tags"); if (!boost::filesystem::exists(tags)) - boost::filesystem::create_directory(tags); + boost::filesystem::create_directory(tags); else i2p::garlic::CleanUpTagsFiles (); @@ -123,12 +123,12 @@ namespace fs { } uint32_t GetLastUpdateTime (const std::string & path) - { + { if (!boost::filesystem::exists(path)) return 0; boost::system::error_code ec; auto t = boost::filesystem::last_write_time (path, ec); return ec ? 0 : t; - } + } bool Remove(const std::string & path) { if (!boost::filesystem::exists(path)) @@ -136,7 +136,7 @@ namespace fs { return boost::filesystem::remove(path); } - bool CreateDirectory (const std::string& path) + bool CreateDirectory (const std::string& path) { if (boost::filesystem::exists(path) && boost::filesystem::is_directory (boost::filesystem::status (path))) return true; diff --git a/libi2pd/FS.h b/libi2pd/FS.h index cb9b632d..87364fea 100644 --- a/libi2pd/FS.h +++ b/libi2pd/FS.h @@ -97,7 +97,7 @@ namespace fs { * @param files Vector to store found files * @return true on success and false if directory not exists */ - bool ReadDir(const std::string & path, std::vector & files); + bool ReadDir(const std::string & path, std::vector & files); /** * @brief Remove file with given path @@ -113,9 +113,9 @@ namespace fs { */ bool Exists(const std::string & path); - uint32_t GetLastUpdateTime (const std::string & path); // seconds since epoch - - bool CreateDirectory (const std::string& path); + uint32_t GetLastUpdateTime (const std::string & path); // seconds since epoch + + bool CreateDirectory (const std::string& path); template void _ExpandPath(std::stringstream & path, T c) { @@ -153,7 +153,7 @@ namespace fs { _ExpandPath(s, filenames...); return s.str(); - } + } } // fs } // i2p diff --git a/libi2pd/Family.cpp b/libi2pd/Family.cpp index fb3b19a6..3fb5d862 100644 --- a/libi2pd/Family.cpp +++ b/libi2pd/Family.cpp @@ -21,24 +21,24 @@ namespace data void Families::LoadCertificate (const std::string& filename) { SSL_CTX * ctx = SSL_CTX_new (TLS_method ()); - int ret = SSL_CTX_use_certificate_file (ctx, filename.c_str (), SSL_FILETYPE_PEM); + int ret = SSL_CTX_use_certificate_file (ctx, filename.c_str (), SSL_FILETYPE_PEM); if (ret) - { + { SSL * ssl = SSL_new (ctx); X509 * cert = SSL_get_certificate (ssl); if (cert) - { + { std::shared_ptr verifier; // extract issuer name char name[100]; X509_NAME_oneline (X509_get_issuer_name(cert), name, 100); char * cn = strstr (name, "CN="); if (cn) - { + { cn += 3; char * family = strstr (cn, ".family"); if (family) family[0] = 0; - } + } auto pkey = X509_get_pubkey (cert); int keyType = EVP_PKEY_base_id (pkey); switch (keyType) @@ -65,7 +65,7 @@ namespace data i2p::crypto::bn2buf (y, signingKey + 32, 32); BN_free (x); BN_free (y); verifier = std::make_shared(signingKey); - } + } else LogPrint (eLogWarning, "Family: elliptic curve ", curve, " is not supported"); } @@ -79,12 +79,12 @@ namespace data EVP_PKEY_free (pkey); if (verifier && cn) m_SigningKeys[cn] = verifier; - } - SSL_free (ssl); - } + } + SSL_free (ssl); + } else LogPrint (eLogError, "Family: Can't open certificate file ", filename); - SSL_CTX_free (ctx); + SSL_CTX_free (ctx); } void Families::LoadCertificates () @@ -105,11 +105,11 @@ namespace data } LoadCertificate (file); numCertificates++; - } + } LogPrint (eLogInfo, "Family: ", numCertificates, " certificates loaded"); } - bool Families::VerifyFamily (const std::string& family, const IdentHash& ident, + bool Families::VerifyFamily (const std::string& family, const IdentHash& ident, const char * signature, const char * key) { uint8_t buf[50], signatureBuf[64]; @@ -118,12 +118,12 @@ namespace data { LogPrint (eLogError, "Family: ", family, " is too long"); return false; - } + } memcpy (buf, family.c_str (), len); memcpy (buf + len, (const uint8_t *)ident, 32); - len += 32; - Base64ToByteStream (signature, signatureLen, signatureBuf, 64); + len += 32; + Base64ToByteStream (signature, signatureLen, signatureBuf, 64); auto it = m_SigningKeys.find (family); if (it != m_SigningKeys.end ()) return it->second->Verify (buf, len, signatureBuf); @@ -136,7 +136,7 @@ namespace data auto filename = i2p::fs::DataDirPath("family", (family + ".key")); std::string sig; SSL_CTX * ctx = SSL_CTX_new (TLS_method ()); - int ret = SSL_CTX_use_PrivateKey_file (ctx, filename.c_str (), SSL_FILETYPE_PEM); + int ret = SSL_CTX_use_PrivateKey_file (ctx, filename.c_str (), SSL_FILETYPE_PEM); if (ret) { SSL * ssl = SSL_new (ctx); @@ -167,15 +167,15 @@ namespace data } else LogPrint (eLogWarning, "Family: elliptic curve ", curve, " is not supported"); - } - } - SSL_free (ssl); - } + } + } + SSL_free (ssl); + } else LogPrint (eLogError, "Family: Can't open keys file: ", filename); - SSL_CTX_free (ctx); + SSL_CTX_free (ctx); return sig; - } + } } } diff --git a/libi2pd/Family.h b/libi2pd/Family.h index 42a37292..a1b5a789 100644 --- a/libi2pd/Family.h +++ b/libi2pd/Family.h @@ -18,7 +18,7 @@ namespace data Families (); ~Families (); void LoadCertificates (); - bool VerifyFamily (const std::string& family, const IdentHash& ident, + bool VerifyFamily (const std::string& family, const IdentHash& ident, const char * signature, const char * key = nullptr); private: @@ -28,7 +28,7 @@ namespace data private: std::map > m_SigningKeys; - }; + }; std::string CreateFamilySignature (const std::string& family, const IdentHash& ident); // return base64 signature of empty string in case of failure diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 3212da01..59089072 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -17,16 +17,16 @@ namespace i2p { namespace garlic { - GarlicRoutingSession::GarlicRoutingSession (GarlicDestination * owner, + GarlicRoutingSession::GarlicRoutingSession (GarlicDestination * owner, std::shared_ptr destination, int numTags, bool attachLeaseSet): - m_Owner (owner), m_Destination (destination), m_NumTags (numTags), + m_Owner (owner), m_Destination (destination), m_NumTags (numTags), m_LeaseSetUpdateStatus (attachLeaseSet ? eLeaseSetUpdated : eLeaseSetDoNotSend), m_LeaseSetUpdateMsgID (0) { // create new session tags and session key RAND_bytes (m_SessionKey, 32); m_Encryption.SetKey (m_SessionKey); - } + } GarlicRoutingSession::GarlicRoutingSession (const uint8_t * sessionKey, const SessionTag& sessionTag): m_Owner (nullptr), m_NumTags (1), m_LeaseSetUpdateStatus (eLeaseSetDoNotSend), m_LeaseSetUpdateMsgID (0) @@ -35,10 +35,10 @@ namespace garlic m_Encryption.SetKey (m_SessionKey); m_SessionTags.push_back (sessionTag); m_SessionTags.back ().creationTime = i2p::util::GetSecondsSinceEpoch (); - } + } GarlicRoutingSession::~GarlicRoutingSession () - { + { } std::shared_ptr GarlicRoutingSession::GetSharedRoutingPath () @@ -53,56 +53,56 @@ namespace garlic if (m_SharedRoutingPath) m_SharedRoutingPath->numTimesUsed++; return m_SharedRoutingPath; } - + void GarlicRoutingSession::SetSharedRoutingPath (std::shared_ptr path) - { - if (path && path->outboundTunnel && path->remoteLease) - { + { + if (path && path->outboundTunnel && path->remoteLease) + { path->updateTime = i2p::util::GetSecondsSinceEpoch (); path->numTimesUsed = 0; - } + } else path = nullptr; m_SharedRoutingPath = path; } - + GarlicRoutingSession::UnconfirmedTags * GarlicRoutingSession::GenerateSessionTags () { auto tags = new UnconfirmedTags (m_NumTags); - tags->tagsCreationTime = i2p::util::GetSecondsSinceEpoch (); + tags->tagsCreationTime = i2p::util::GetSecondsSinceEpoch (); for (int i = 0; i < m_NumTags; i++) { RAND_bytes (tags->sessionTags[i], 32); tags->sessionTags[i].creationTime = tags->tagsCreationTime; - } - return tags; + } + return tags; } void GarlicRoutingSession::MessageConfirmed (uint32_t msgID) { TagsConfirmed (msgID); if (msgID == m_LeaseSetUpdateMsgID) - { + { m_LeaseSetUpdateStatus = eLeaseSetUpToDate; m_LeaseSetUpdateMsgID = 0; LogPrint (eLogInfo, "Garlic: LeaseSet update confirmed"); - } + } else CleanupExpiredTags (); - } - - void GarlicRoutingSession::TagsConfirmed (uint32_t msgID) - { + } + + void GarlicRoutingSession::TagsConfirmed (uint32_t msgID) + { uint32_t ts = i2p::util::GetSecondsSinceEpoch (); auto it = m_UnconfirmedTagsMsgs.find (msgID); if (it != m_UnconfirmedTagsMsgs.end ()) { auto& tags = it->second; if (ts < tags->tagsCreationTime + OUTGOING_TAGS_EXPIRATION_TIMEOUT) - { + { for (int i = 0; i < tags->numTags; i++) m_SessionTags.push_back (tags->sessionTags[i]); - } + } m_UnconfirmedTagsMsgs.erase (it); } } @@ -114,7 +114,7 @@ namespace garlic { if (ts >= it->creationTime + OUTGOING_TAGS_EXPIRATION_TIMEOUT) it = m_SessionTags.erase (it); - else + else ++it; } CleanupUnconfirmedTags (); @@ -123,9 +123,9 @@ namespace garlic if (m_Owner) m_Owner->RemoveDeliveryStatusSession (m_LeaseSetUpdateMsgID); m_LeaseSetUpdateMsgID = 0; - } + } return !m_SessionTags.empty () || !m_UnconfirmedTagsMsgs.empty (); - } + } bool GarlicRoutingSession::CleanupUnconfirmedTags () { @@ -140,10 +140,10 @@ namespace garlic m_Owner->RemoveDeliveryStatusSession (it->first); it = m_UnconfirmedTagsMsgs.erase (it); ret = true; - } + } else ++it; - } + } return ret; } @@ -155,10 +155,10 @@ namespace garlic uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length // find non-expired tag - bool tagFound = false; - SessionTag tag; + bool tagFound = false; + SessionTag tag; if (m_NumTags > 0) - { + { uint32_t ts = i2p::util::GetSecondsSinceEpoch (); while (!m_SessionTags.empty ()) { @@ -168,11 +168,11 @@ namespace garlic m_SessionTags.pop_front (); // use same tag only once tagFound = true; break; - } + } else m_SessionTags.pop_front (); // remove expired tag } - } + } // create message if (!tagFound) // new session { @@ -184,34 +184,34 @@ namespace garlic } // create ElGamal block ElGamalBlock elGamal; - memcpy (elGamal.sessionKey, m_SessionKey, 32); + memcpy (elGamal.sessionKey, m_SessionKey, 32); RAND_bytes (elGamal.preIV, 32); // Pre-IV uint8_t iv[32]; // IV is first 16 bytes - SHA256(elGamal.preIV, 32, iv); + SHA256(elGamal.preIV, 32, iv); BN_CTX * ctx = BN_CTX_new (); - m_Destination->Encrypt ((uint8_t *)&elGamal, buf, ctx); - BN_CTX_free (ctx); + m_Destination->Encrypt ((uint8_t *)&elGamal, buf, ctx); + BN_CTX_free (ctx); m_Encryption.SetIV (iv); buf += 514; - len += 514; + len += 514; } else // existing session - { + { // session tag - memcpy (buf, tag, 32); + memcpy (buf, tag, 32); uint8_t iv[32]; // IV is first 16 bytes SHA256(tag, 32, iv); m_Encryption.SetIV (iv); buf += 32; - len += 32; - } + len += 32; + } // AES block len += CreateAESBlock (buf, msg); htobe32buf (m->GetPayload (), len); m->len += len + 4; m->FillI2NPMessageHeader (eI2NPGarlic); return m; - } + } size_t GarlicRoutingSession::CreateAESBlock (uint8_t * buf, std::shared_ptr msg) { @@ -221,13 +221,13 @@ namespace garlic htobuf16 (buf, newTags ? htobe16 (newTags->numTags) : 0); // tag count blockSize += 2; if (newTags) // session tags recreated - { + { for (int i = 0; i < newTags->numTags; i++) { memcpy (buf + blockSize, newTags->sessionTags[i], 32); // tags blockSize += 32; } - } + } uint32_t * payloadSize = (uint32_t *)(buf + blockSize); blockSize += 4; uint8_t * payloadHash = buf + blockSize; @@ -243,7 +243,7 @@ namespace garlic blockSize += (16-rem); //padding m_Encryption.Encrypt(buf, blockSize, buf); return blockSize; - } + } size_t GarlicRoutingSession::CreateGarlicPayload (uint8_t * payload, std::shared_ptr msg, UnconfirmedTags * newTags) { @@ -256,7 +256,7 @@ namespace garlic size++; if (m_Owner) - { + { // resubmit non-confirmed LeaseSet if (m_LeaseSetUpdateStatus == eLeaseSetSubmitted && ts > m_LeaseSetSubmissionTime + LEASET_CONFIRMATION_TIMEOUT) { @@ -267,7 +267,7 @@ namespace garlic // attach DeviveryStatus if necessary if (newTags || m_LeaseSetUpdateStatus == eLeaseSetUpdated) // new tags created or leaseset updated { - // clove is DeliveryStatus + // clove is DeliveryStatus auto cloveSize = CreateDeliveryStatusClove (payload + size, msgID); if (cloveSize > 0) // successive? { @@ -278,14 +278,14 @@ namespace garlic newTags->msgID = msgID; m_UnconfirmedTagsMsgs.insert (std::make_pair(msgID, std::unique_ptr(newTags))); newTags = nullptr; // got acquired - } + } m_Owner->DeliveryStatusSent (shared_from_this (), msgID); } else LogPrint (eLogWarning, "Garlic: DeliveryStatus clove was not created"); - } + } // attach LeaseSet - if (m_LeaseSetUpdateStatus == eLeaseSetUpdated) + if (m_LeaseSetUpdateStatus == eLeaseSetUpdated) { if (m_LeaseSetUpdateMsgID) m_Owner->RemoveDeliveryStatusSession (m_LeaseSetUpdateMsgID); // remove previous m_LeaseSetUpdateStatus = eLeaseSetSubmitted; @@ -293,25 +293,25 @@ namespace garlic m_LeaseSetSubmissionTime = ts; // clove if our leaseSet must be attached auto leaseSet = CreateDatabaseStoreMsg (m_Owner->GetLeaseSet ()); - size += CreateGarlicClove (payload + size, leaseSet, false); + size += CreateGarlicClove (payload + size, leaseSet, false); (*numCloves)++; } - } + } if (msg) // clove message ifself if presented - { + { size += CreateGarlicClove (payload + size, msg, m_Destination ? m_Destination->IsDestination () : false); (*numCloves)++; - } + } memset (payload + size, 0, 3); // certificate of message size += 3; htobe32buf (payload + size, msgID); // MessageID size += 4; htobe64buf (payload + size, ts + 8000); // Expiration of message, 8 sec size += 8; - - if (newTags) delete newTags; // not acquired, delete + + if (newTags) delete newTags; // not acquired, delete return size; - } + } size_t GarlicRoutingSession::CreateGarlicClove (uint8_t * buf, std::shared_ptr msg, bool isDestination) { @@ -323,13 +323,13 @@ namespace garlic size++; memcpy (buf + size, m_Destination->GetIdentHash (), 32); size += 32; - } - else - { + } + else + { buf[size] = 0;// delivery instructions flag local size++; } - + memcpy (buf + size, msg->GetBuffer (), msg->GetLength ()); size += msg->GetLength (); uint32_t cloveID; @@ -341,34 +341,34 @@ namespace garlic memset (buf + size, 0, 3); // certificate of clove size += 3; return size; - } + } size_t GarlicRoutingSession::CreateDeliveryStatusClove (uint8_t * buf, uint32_t msgID) - { + { size_t size = 0; if (m_Owner) { auto inboundTunnel = m_Owner->GetTunnelPool ()->GetNextInboundTunnel (); if (inboundTunnel) - { + { buf[size] = eGarlicDeliveryTypeTunnel << 5; // delivery instructions flag tunnel size++; - // hash and tunnelID sequence is reversed for Garlic + // hash and tunnelID sequence is reversed for Garlic memcpy (buf + size, inboundTunnel->GetNextIdentHash (), 32); // To Hash size += 32; htobe32buf (buf + size, inboundTunnel->GetNextTunnelID ()); // tunnelID - size += 4; - // create msg + size += 4; + // create msg auto msg = CreateDeliveryStatusMsg (msgID); if (m_Owner) { - //encrypt + //encrypt uint8_t key[32], tag[32]; - RAND_bytes (key, 32); // random session key + RAND_bytes (key, 32); // random session key RAND_bytes (tag, 32); // random session tag m_Owner->SubmitSessionKey (key, tag); GarlicRoutingSession garlic (key, tag); - msg = garlic.WrapSingleMessage (msg); + msg = garlic.WrapSingleMessage (msg); } memcpy (buf + size, msg->GetBuffer (), msg->GetLength ()); size += msg->GetLength (); @@ -383,7 +383,7 @@ namespace garlic memset (buf + size, 0, 3); // certificate of clove size += 3; } - else + else LogPrint (eLogError, "Garlic: No inbound tunnels in the pool for DeliveryStatus"); } else @@ -395,19 +395,19 @@ namespace garlic GarlicDestination::GarlicDestination (): m_NumTags (32) // 32 tags by default { m_Ctx = BN_CTX_new (); - } - + } + GarlicDestination::~GarlicDestination () { BN_CTX_free (m_Ctx); } void GarlicDestination::CleanUp () - { + { m_Sessions.clear (); m_DeliveryStatusSessions.clear (); m_Tags.clear (); - } + } void GarlicDestination::AddSessionKey (const uint8_t * key, const uint8_t * tag) { if (key) @@ -417,7 +417,7 @@ namespace garlic } } - bool GarlicDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag) + bool GarlicDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag) { AddSessionKey (key, tag); return true; @@ -431,22 +431,22 @@ namespace garlic { LogPrint (eLogWarning, "Garlic: message length ", length, " exceeds I2NP message length ", msg->GetLength ()); return; - } + } buf += 4; // length auto it = m_Tags.find (SessionTag(buf)); if (it != m_Tags.end ()) { // tag found. Use AES auto decryption = it->second; - m_Tags.erase (it); // tag might be used only once + m_Tags.erase (it); // tag might be used only once if (length >= 32) - { + { uint8_t iv[32]; // IV is first 16 bytes SHA256(buf, 32, iv); decryption->SetIV (iv); decryption->Decrypt (buf + 32, length - 32, buf + 32); HandleAESBlock (buf + 32, length - 32, decryption, msg->from); - } + } else LogPrint (eLogWarning, "Garlic: message length ", length, " is less than 32 bytes"); } @@ -455,35 +455,35 @@ namespace garlic // tag not found. Use ElGamal ElGamalBlock elGamal; if (length >= 514 && Decrypt (buf, (uint8_t *)&elGamal, m_Ctx)) - { + { auto decryption = std::make_shared(elGamal.sessionKey); uint8_t iv[32]; // IV is first 16 bytes - SHA256(elGamal.preIV, 32, iv); + SHA256(elGamal.preIV, 32, iv); decryption->SetIV (iv); decryption->Decrypt(buf + 514, length - 514, buf + 514); HandleAESBlock (buf + 514, length - 514, decryption, msg->from); - } + } else LogPrint (eLogError, "Garlic: Failed to decrypt message"); } - } + } void GarlicDestination::HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr decryption, std::shared_ptr from) { uint16_t tagCount = bufbe16toh (buf); - buf += 2; len -= 2; + buf += 2; len -= 2; if (tagCount > 0) - { - if (tagCount*32 > len) + { + if (tagCount*32 > len) { LogPrint (eLogError, "Garlic: Tag count ", tagCount, " exceeds length ", len); return ; - } + } uint32_t ts = i2p::util::GetSecondsSinceEpoch (); for (int i = 0; i < tagCount; i++) - m_Tags[SessionTag(buf + i*32, ts)] = decryption; - } + m_Tags[SessionTag(buf + i*32, ts)] = decryption; + } buf += tagCount*32; len -= tagCount*32; uint32_t payloadSize = bufbe32toh (buf); @@ -491,10 +491,10 @@ namespace garlic { LogPrint (eLogError, "Garlic: Unexpected payload size ", payloadSize); return; - } + } buf += 4; uint8_t * payloadHash = buf; - buf += 32;// payload hash. + buf += 32;// payload hash. if (*buf) // session key? buf += 32; // new session key buf++; // flag @@ -506,9 +506,9 @@ namespace garlic { LogPrint (eLogError, "Garlic: wrong payload hash"); return; - } + } HandleGarlicPayload (buf, payloadSize, from); - } + } void GarlicDestination::HandleGarlicPayload (uint8_t * buf, size_t len, std::shared_ptr from) { @@ -530,8 +530,8 @@ namespace garlic { // TODO: implement LogPrint (eLogWarning, "Garlic: clove encrypted"); - buf += 32; - } + buf += 32; + } ptrdiff_t offset = buf - buf1; GarlicDeliveryType deliveryType = (GarlicDeliveryType)((flag >> 5) & 0x03); switch (deliveryType) @@ -542,27 +542,27 @@ namespace garlic { LogPrint (eLogError, "Garlic: message is too short"); break; - } + } HandleI2NPMessage (buf, len - offset, from); - break; - case eGarlicDeliveryTypeDestination: + break; + case eGarlicDeliveryTypeDestination: LogPrint (eLogDebug, "Garlic: type destination"); buf += 32; // destination. check it later or for multiple destinations - offset = buf1 - buf; + offset = buf - buf1; if (offset > (int)len) { LogPrint (eLogError, "Garlic: message is too short"); break; - } - HandleI2NPMessage (buf, len - offset, from); + } + HandleI2NPMessage (buf, len - offset, from); break; case eGarlicDeliveryTypeTunnel: - { + { LogPrint (eLogDebug, "Garlic: type tunnel"); // gwHash and gwTunnel sequence is reverted uint8_t * gwHash = buf; buf += 32; - offset = buf1 - buf; + offset = buf - buf1; if (offset + 4 > (int)len) { LogPrint (eLogError, "Garlic: message is too short"); @@ -591,7 +591,7 @@ namespace garlic { uint8_t * ident = buf; buf += 32; - offset = buf1 - buf; + offset = buf - buf1; if (!from) // received directly { if (offset > (int)len) @@ -604,7 +604,7 @@ namespace garlic } else LogPrint (eLogWarning, "Garlic: type router for inbound tunnels not supported"); - break; + break; } default: LogPrint (eLogWarning, "Garlic: unknown delivery type ", (int)deliveryType); @@ -618,28 +618,28 @@ namespace garlic buf += 4; // CloveID buf += 8; // Date buf += 3; // Certificate - offset = buf1 - buf; + offset = buf - buf1; if (offset > (int)len) { LogPrint (eLogError, "Garlic: clove is too long"); break; - } + } len -= offset; - } - } - - std::shared_ptr GarlicDestination::WrapMessage (std::shared_ptr destination, - std::shared_ptr msg, bool attachLeaseSet) + } + } + + std::shared_ptr GarlicDestination::WrapMessage (std::shared_ptr destination, + std::shared_ptr msg, bool attachLeaseSet) { - auto session = GetRoutingSession (destination, attachLeaseSet); - return session->WrapSingleMessage (msg); + auto session = GetRoutingSession (destination, attachLeaseSet); + return session->WrapSingleMessage (msg); } std::shared_ptr GarlicDestination::GetRoutingSession ( std::shared_ptr destination, bool attachLeaseSet) { GarlicRoutingSessionPtr session; - { + { std::unique_lock l(m_SessionsMutex); auto it = m_Sessions.find (destination->GetIdentHash ()); if (it != m_Sessions.end ()) @@ -647,14 +647,14 @@ namespace garlic } if (!session) { - session = std::make_shared (this, destination, + session = std::make_shared (this, destination, attachLeaseSet ? m_NumTags : 4, attachLeaseSet); // specified num tags for connections and 4 for LS requests std::unique_lock l(m_SessionsMutex); m_Sessions[destination->GetIdentHash ()] = session; - } + } return session; - } - + } + void GarlicDestination::CleanupExpiredTags () { // incoming @@ -666,7 +666,7 @@ namespace garlic { numExpiredTags++; it = m_Tags.erase (it); - } + } else ++it; } @@ -690,7 +690,7 @@ namespace garlic } } // delivery status sessions - { + { std::unique_lock l(m_DeliveryStatusSessionsMutex); for (auto it = m_DeliveryStatusSessions.begin (); it != m_DeliveryStatusSessions.end (); ) { @@ -699,7 +699,7 @@ namespace garlic else ++it; } - } + } } void GarlicDestination::RemoveDeliveryStatusSession (uint32_t msgID) @@ -756,7 +756,7 @@ namespace garlic if (m_Tags.empty ()) return; std::string ident = GetIdentHash().ToBase32(); std::string path = i2p::fs::DataDirPath("tags", (ident + ".tags")); - std::ofstream f (path, std::ofstream::binary | std::ofstream::out | std::ofstream::trunc); + std::ofstream f (path, std::ofstream::binary | std::ofstream::out | std::ofstream::trunc); uint32_t ts = i2p::util::GetSecondsSinceEpoch (); // 4 bytes timestamp, 32 bytes tag, 32 bytes key for (auto it: m_Tags) @@ -766,7 +766,7 @@ namespace garlic f.write ((char *)&it.first.creationTime, 4); f.write ((char *)it.first.data (), 32); f.write ((char *)it.second->GetKey ().data (), 32); - } + } } } @@ -775,11 +775,11 @@ namespace garlic std::string ident = GetIdentHash().ToBase32(); std::string path = i2p::fs::DataDirPath("tags", (ident + ".tags")); uint32_t ts = i2p::util::GetSecondsSinceEpoch (); - if (ts < i2p::fs::GetLastUpdateTime (path) + INCOMING_TAGS_EXPIRATION_TIMEOUT) + if (ts < i2p::fs::GetLastUpdateTime (path) + INCOMING_TAGS_EXPIRATION_TIMEOUT) { // might contain non-expired tags std::ifstream f (path, std::ifstream::binary); - if (f) + if (f) { std::map > keys; // 4 bytes timestamp, 32 bytes tag, 32 bytes key @@ -794,7 +794,7 @@ namespace garlic f.read ((char *)key, 32); } else - f.seekg (64, std::ios::cur); // skip + f.seekg (64, std::ios::cur); // skip if (f.eof ()) break; std::shared_ptr decryption; @@ -805,21 +805,21 @@ namespace garlic decryption = std::make_shared(key); m_Tags.insert (std::make_pair (SessionTag (tag, ts), decryption)); } - if (!m_Tags.empty ()) - LogPrint (eLogInfo, m_Tags.size (), " loaded for ", ident); + if (!m_Tags.empty ()) + LogPrint (eLogInfo, m_Tags.size (), " loaded for ", ident); } } - i2p::fs::Remove (path); + i2p::fs::Remove (path); } void CleanUpTagsFiles () { - std::vector files; + std::vector files; i2p::fs::ReadDir (i2p::fs::DataDirPath("tags"), files); uint32_t ts = i2p::util::GetSecondsSinceEpoch (); for (auto it: files) if (ts >= i2p::fs::GetLastUpdateTime (it) + INCOMING_TAGS_EXPIRATION_TIMEOUT) i2p::fs::Remove (it); } -} +} } diff --git a/libi2pd/Garlic.h b/libi2pd/Garlic.h index b78b89f9..c5236c90 100644 --- a/libi2pd/Garlic.h +++ b/libi2pd/Garlic.h @@ -17,46 +17,46 @@ namespace i2p { namespace tunnel -{ +{ class OutboundTunnel; } - + namespace garlic { - - enum GarlicDeliveryType - { - eGarlicDeliveryTypeLocal = 0, + + enum GarlicDeliveryType + { + eGarlicDeliveryTypeLocal = 0, eGarlicDeliveryTypeDestination = 1, - eGarlicDeliveryTypeRouter = 2, + eGarlicDeliveryTypeRouter = 2, eGarlicDeliveryTypeTunnel = 3 - }; + }; struct ElGamalBlock { uint8_t sessionKey[32]; uint8_t preIV[32]; uint8_t padding[158]; - }; + }; - const int INCOMING_TAGS_EXPIRATION_TIMEOUT = 960; // 16 minutes + const int INCOMING_TAGS_EXPIRATION_TIMEOUT = 960; // 16 minutes const int OUTGOING_TAGS_EXPIRATION_TIMEOUT = 720; // 12 minutes - const int OUTGOING_TAGS_CONFIRMATION_TIMEOUT = 10; // 10 seconds + const int OUTGOING_TAGS_CONFIRMATION_TIMEOUT = 10; // 10 seconds const int LEASET_CONFIRMATION_TIMEOUT = 4000; // in milliseconds - const int ROUTING_PATH_EXPIRATION_TIMEOUT = 30; // 30 seconds - const int ROUTING_PATH_MAX_NUM_TIMES_USED = 100; // how many times might be used - - struct SessionTag: public i2p::data::Tag<32> + const int ROUTING_PATH_EXPIRATION_TIMEOUT = 30; // 30 seconds + const int ROUTING_PATH_MAX_NUM_TIMES_USED = 100; // how many times might be used + + struct SessionTag: public i2p::data::Tag<32> { SessionTag (const uint8_t * buf, uint32_t ts = 0): Tag<32>(buf), creationTime (ts) {}; SessionTag () = default; SessionTag (const SessionTag& ) = default; SessionTag& operator= (const SessionTag& ) = default; #ifndef _WIN32 - SessionTag (SessionTag&& ) = default; - SessionTag& operator= (SessionTag&& ) = default; + SessionTag (SessionTag&& ) = default; + SessionTag& operator= (SessionTag&& ) = default; #endif - uint32_t creationTime; // seconds since epoch + uint32_t creationTime; // seconds since epoch }; // AESDecryption is associated with session tags and store key @@ -67,7 +67,7 @@ namespace garlic AESDecryption (const uint8_t * key): m_Key (key) { SetKey (key); - } + } const i2p::crypto::AESKey& GetKey () const { return m_Key; }; private: @@ -81,8 +81,8 @@ namespace garlic std::shared_ptr remoteLease; int rtt; // RTT uint32_t updateTime; // seconds since epoch - int numTimesUsed; - }; + int numTimesUsed; + }; class GarlicDestination; class GarlicRoutingSession: public std::enable_shared_from_this @@ -94,7 +94,7 @@ namespace garlic eLeaseSetSubmitted, eLeaseSetDoNotSend }; - + struct UnconfirmedTags { UnconfirmedTags (int n): numTags (n), tagsCreationTime (0) { sessionTags = new SessionTag[numTags]; }; @@ -107,23 +107,23 @@ namespace garlic public: - GarlicRoutingSession (GarlicDestination * owner, std::shared_ptr destination, + GarlicRoutingSession (GarlicDestination * owner, std::shared_ptr destination, int numTags, bool attachLeaseSet); GarlicRoutingSession (const uint8_t * sessionKey, const SessionTag& sessionTag); // one time encryption ~GarlicRoutingSession (); std::shared_ptr WrapSingleMessage (std::shared_ptr msg); void MessageConfirmed (uint32_t msgID); - bool CleanupExpiredTags (); // returns true if something left + bool CleanupExpiredTags (); // returns true if something left bool CleanupUnconfirmedTags (); // returns true if something has been deleted - void SetLeaseSetUpdated () - { - if (m_LeaseSetUpdateStatus != eLeaseSetDoNotSend) m_LeaseSetUpdateStatus = eLeaseSetUpdated; + void SetLeaseSetUpdated () + { + if (m_LeaseSetUpdateStatus != eLeaseSetDoNotSend) m_LeaseSetUpdateStatus = eLeaseSetUpdated; }; bool IsLeaseSetNonConfirmed () const { return m_LeaseSetUpdateStatus == eLeaseSetSubmitted; }; bool IsLeaseSetUpdated () const { return m_LeaseSetUpdateStatus == eLeaseSetUpdated; }; - uint64_t GetLeaseSetSubmissionTime () const { return m_LeaseSetSubmissionTime; } - + uint64_t GetLeaseSetSubmissionTime () const { return m_LeaseSetSubmissionTime; } + std::shared_ptr GetSharedRoutingPath (); void SetSharedRoutingPath (std::shared_ptr path); @@ -144,26 +144,26 @@ namespace garlic GarlicDestination * m_Owner; std::shared_ptr m_Destination; - + i2p::crypto::AESKey m_SessionKey; std::list m_SessionTags; int m_NumTags; - std::map > m_UnconfirmedTagsMsgs; // msgID->tags - + std::map > m_UnconfirmedTagsMsgs; // msgID->tags + LeaseSetUpdateStatus m_LeaseSetUpdateStatus; uint32_t m_LeaseSetUpdateMsgID; uint64_t m_LeaseSetSubmissionTime; // in milliseconds - + i2p::crypto::CBCEncryption m_Encryption; std::shared_ptr m_SharedRoutingPath; - + public: // for HTTP only size_t GetNumOutgoingTags () const { return m_SessionTags.size (); }; - }; + }; //using GarlicRoutingSessionPtr = std::shared_ptr; - typedef std::shared_ptr GarlicRoutingSessionPtr; // TODO: replace to using after switch to 4.8 + typedef std::shared_ptr GarlicRoutingSessionPtr; // TODO: replace to using after switch to 4.8 class GarlicDestination: public i2p::data::LocalDestination { @@ -173,36 +173,36 @@ namespace garlic ~GarlicDestination (); void CleanUp (); - void SetNumTags (int numTags) { m_NumTags = numTags; }; - std::shared_ptr GetRoutingSession (std::shared_ptr destination, bool attachLeaseSet); + void SetNumTags (int numTags) { m_NumTags = numTags; }; + std::shared_ptr GetRoutingSession (std::shared_ptr destination, bool attachLeaseSet); void CleanupExpiredTags (); void RemoveDeliveryStatusSession (uint32_t msgID); - std::shared_ptr WrapMessage (std::shared_ptr destination, + std::shared_ptr WrapMessage (std::shared_ptr destination, std::shared_ptr msg, bool attachLeaseSet = false); void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID); - + virtual void ProcessGarlicMessage (std::shared_ptr msg); - virtual void ProcessDeliveryStatusMessage (std::shared_ptr msg); + virtual void ProcessDeliveryStatusMessage (std::shared_ptr msg); virtual void SetLeaseSetUpdated (); - + virtual std::shared_ptr GetLeaseSet () = 0; // TODO virtual std::shared_ptr GetTunnelPool () const = 0; virtual void HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from) = 0; - + protected: void HandleGarlicMessage (std::shared_ptr msg); - void HandleDeliveryStatusMessage (std::shared_ptr msg); + void HandleDeliveryStatusMessage (std::shared_ptr msg); void SaveTags (); - void LoadTags (); + void LoadTags (); private: - void HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr decryption, + void HandleAESBlock (uint8_t * buf, size_t len, std::shared_ptr decryption, std::shared_ptr from); void HandleGarlicPayload (uint8_t * buf, size_t len, std::shared_ptr from); @@ -218,17 +218,17 @@ namespace garlic // DeliveryStatus std::mutex m_DeliveryStatusSessionsMutex; std::map m_DeliveryStatusSessions; // msgID -> session - + public: // for HTTP only - size_t GetNumIncomingTags () const { return m_Tags.size (); } + size_t GetNumIncomingTags () const { return m_Tags.size (); } const decltype(m_Sessions)& GetSessions () const { return m_Sessions; }; }; void CleanUpTagsFiles (); - -} + +} } #endif diff --git a/libi2pd/Gost.cpp b/libi2pd/Gost.cpp index 8663289a..5773fe15 100644 --- a/libi2pd/Gost.cpp +++ b/libi2pd/Gost.cpp @@ -28,7 +28,7 @@ namespace crypto GOSTR3410Curve::~GOSTR3410Curve () { EC_GROUP_free (m_Group); - } + } EC_POINT * GOSTR3410Curve::MulP (const BIGNUM * n) const { @@ -81,12 +81,12 @@ namespace crypto BN_mod_inverse (h, h, q, ctx); // 1/h mod q BIGNUM * z1 = BN_CTX_get (ctx); BN_mod_mul (z1, s, h, q, ctx); // z1 = s/h - BIGNUM * z2 = BN_CTX_get (ctx); + BIGNUM * z2 = BN_CTX_get (ctx); BN_sub (z2, q, r); // z2 = -r BN_mod_mul (z2, z2, h, q, ctx); // z2 = -r/h EC_POINT * C = EC_POINT_new (m_Group); EC_POINT_mul (m_Group, C, z1, pub, z2, ctx); // z1*P + z2*pub - BIGNUM * x = BN_CTX_get (ctx); + BIGNUM * x = BN_CTX_get (ctx); GetXY (C, x, nullptr); // Cx BN_mod (x, x, q, ctx); // Cx % q bool ret = !BN_cmp (x, r); // Cx = r ? @@ -94,9 +94,9 @@ namespace crypto BN_CTX_end (ctx); BN_CTX_free (ctx); return ret; - } + } - EC_POINT * GOSTR3410Curve::RecoverPublicKey (const BIGNUM * digest, const BIGNUM * r, const BIGNUM * s, bool isNegativeY) const + EC_POINT * GOSTR3410Curve::RecoverPublicKey (const BIGNUM * digest, const BIGNUM * r, const BIGNUM * s, bool isNegativeY) const { // s*P = r*Q + h*C BN_CTX * ctx = BN_CTX_new (); @@ -104,7 +104,7 @@ namespace crypto EC_POINT * C = EC_POINT_new (m_Group); // C = k*P = (rx, ry) EC_POINT * Q = nullptr; if (EC_POINT_set_compressed_coordinates_GFp (m_Group, C, r, isNegativeY ? 1 : 0, ctx)) - { + { EC_POINT * S = EC_POINT_new (m_Group); // S = s*P EC_POINT_mul (m_Group, S, s, nullptr, nullptr, ctx); BIGNUM * q = BN_CTX_get (ctx); @@ -112,28 +112,28 @@ namespace crypto BIGNUM * h = BN_CTX_get (ctx); BN_mod (h, digest, q, ctx); // h = digest % q BN_sub (h, q, h); // h = -h - EC_POINT * H = EC_POINT_new (m_Group); + EC_POINT * H = EC_POINT_new (m_Group); EC_POINT_mul (m_Group, H, nullptr, C, h, ctx); // -h*C EC_POINT_add (m_Group, C, S, H, ctx); // s*P - h*C EC_POINT_free (H); EC_POINT_free (S); BIGNUM * r1 = BN_CTX_get (ctx); BN_mod_inverse (r1, r, q, ctx); - Q = EC_POINT_new (m_Group); - EC_POINT_mul (m_Group, Q, nullptr, C, r1, ctx); // (s*P - h*C)/r - } + Q = EC_POINT_new (m_Group); + EC_POINT_mul (m_Group, Q, nullptr, C, r1, ctx); // (s*P - h*C)/r + } EC_POINT_free (C); BN_CTX_end (ctx); BN_CTX_free (ctx); return Q; - } - + } + static GOSTR3410Curve * CreateGOSTR3410Curve (GOSTR3410ParamSet paramSet) { - // a, b, p, q, x, y - static const char * params[eGOSTR3410NumParamSets][6] = + // a, b, p, q, x, y + static const char * params[eGOSTR3410NumParamSets][6] = { - { + { "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD94", "A6", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD97", @@ -147,10 +147,10 @@ namespace crypto "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC7", "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27E69532F48D89116FF22B8D4E0560609B4B38ABFAD2B85DCACDB1411F10B275", "3", - "7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921DF1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4" + "7503CFE87A836AE3A61B8816E25450E6CE5E1C93ACF1ABC1778064FDCBEFA921DF1626BE4FD036E93D75E6A50E3A41E98028FE5FC235F5B889A589CB5215F2A4" } // tc26-2012-paramSetA-512 - }; - + }; + BIGNUM * a = nullptr, * b = nullptr, * p = nullptr, * q =nullptr, * x = nullptr, * y = nullptr; BN_hex2bn(&a, params[paramSet][0]); BN_hex2bn(&b, params[paramSet][1]); @@ -161,25 +161,25 @@ namespace crypto auto curve = new GOSTR3410Curve (a, b, p, q, x, y); BN_free (a); BN_free (b); BN_free (p); BN_free (q); BN_free (x); BN_free (y); return curve; - } + } static std::array, eGOSTR3410NumParamSets> g_GOSTR3410Curves; std::unique_ptr& GetGOSTR3410Curve (GOSTR3410ParamSet paramSet) { if (!g_GOSTR3410Curves[paramSet]) { - auto c = CreateGOSTR3410Curve (paramSet); + auto c = CreateGOSTR3410Curve (paramSet); if (!g_GOSTR3410Curves[paramSet]) // make sure it was not created already g_GOSTR3410Curves[paramSet].reset (c); else delete c; - } - return g_GOSTR3410Curves[paramSet]; + } + return g_GOSTR3410Curves[paramSet]; } // ГОСТ 34.11-2012 - static const uint64_t T0[256] = + static const uint64_t T0[256] = { 0xE6F87E5C5B711FD0, 0x258377800924FA16, 0xC849E07E852EA4A8, 0x5B4686A18F06C16A, 0x0B32E9A2D77B416E, 0xABDA37A467815C66, 0xF61796A81A686676, 0xF5DC0B706391954B, @@ -246,7 +246,7 @@ namespace crypto 0x92BDE697D67F3422, 0xC78933E10514BC61, 0xE1C1D9B975C9B54A, 0xD2266160CF1BCD80, 0x9A4492ED78FD8671, 0xB3CCAB2A881A9793, 0x72CEBF667FE1D088, 0xD6D45B5D985A9427 }; - static const uint64_t T1[256] = + static const uint64_t T1[256] = { 0xC811A8058C3F55DE, 0x65F5B43196B50619, 0xF74F96B1D6706E43, 0x859D1E8BCB43D336, 0x5AAB8A85CCFA3D84, 0xF9C7BF99C295FCFD, 0xA21FD5A1DE4B630F, 0xCDB3EF763B8B456D, @@ -313,7 +313,7 @@ namespace crypto 0x57B69E77B57354A0, 0x3969441D8097D0B4, 0x3330CAFBF3E2F0CF, 0xE28E77DDE0BE8CC3, 0x62B12E259C494F46, 0xA6CE726FB9DBD1CA, 0x41E242C1EED14DBA, 0x76032FF47AA30FB0 }; - static const uint64_t T2[256] = + static const uint64_t T2[256] = { 0x45B268A93ACDE4CC, 0xAF7F0BE884549D08, 0x048354B3C1468263, 0x925435C2C80EFED2, 0xEE4E37F27FDFFBA7, 0x167A33920C60F14D, 0xFB123B52EA03E584, 0x4A0CAB53FDBB9007, @@ -380,7 +380,7 @@ namespace crypto 0xF9DD11850420A43B, 0x4BE5BEB68A243ED6, 0x5584255F19C8D65D, 0x3B67404E633FA006, 0xA68DB6766C472A1F, 0xF78AC79AB4C97E21, 0xC353442E1080AAEC, 0x9A4F9DB95782E714 }; - static const uint64_t T3[256] = + static const uint64_t T3[256] = { 0x05BA7BC82C9B3220, 0x31A54665F8B65E4F, 0xB1B651F77547F4D4, 0x8BFA0D857BA46682, 0x85A96C5AA16A98BB, 0x990FAEF908EB79C9, 0xA15E37A247F4A62D, 0x76857DCD5D27741E, @@ -447,7 +447,7 @@ namespace crypto 0x77059157F359DC47, 0x1D262E3907FF492B, 0xFB582233E59AC557, 0xDDB2BCE242F8B673, 0x2577B76248E096CF, 0x6F99C4A6D83DA74C, 0xC1147E41EB795701, 0xF48BAF76912A9337 }; - static const uint64_t T4[256] = + static const uint64_t T4[256] = { 0x3EF29D249B2C0A19, 0xE9E16322B6F8622F, 0x5536994047757F7A, 0x9F4D56D5A47B0B33, 0x822567466AA1174C, 0xB8F5057DEB082FB2, 0xCC48C10BF4475F53, 0x373088D4275DEC3A, @@ -514,7 +514,7 @@ namespace crypto 0x6853032B59F3EE6E, 0x65B3E9C4FF073AAA, 0x772AC3399AE5EBEC, 0x87816E97F842A75B, 0x110E2DB2E0484A4B, 0x331277CB3DD8DEDD, 0xBD510CAC79EB9FA5, 0x352179552A91F5C7 }; - static const uint64_t T5[256] = + static const uint64_t T5[256] = { 0x8AB0A96846E06A6D, 0x43C7E80B4BF0B33A, 0x08C9B3546B161EE5, 0x39F1C235EBA990BE, 0xC1BEF2376606C7B2, 0x2C209233614569AA, 0xEB01523B6FC3289A, 0x946953AB935ACEDD, @@ -581,7 +581,7 @@ namespace crypto 0xEFEB8511D4C82766, 0x961CB6BE40D147A3, 0xAAB35F25F7B812DE, 0x76154E407044329D, 0x513D76B64E570693, 0xF3479AC7D2F90AA8, 0x9B8B2E4477079C85, 0x297EB99D3D85AC69 }; - static const uint64_t T6[256] = + static const uint64_t T6[256] = { 0x7E37E62DFC7D40C3, 0x776F25A4EE939E5B, 0xE045C850DD8FB5AD, 0x86ED5BA711FF1952, 0xE91D0BD9CF616B35, 0x37E0AB256E408FFB, 0x9607F6C031025A7A, 0x0B02F5E116D23C9D, @@ -648,7 +648,7 @@ namespace crypto 0xE6AB92E8D1CB8EA2, 0x3354C7F5663856F1, 0xD93EE170AF7BAE4D, 0x616BD27BC22AE67C, 0x92B39A10397A8370, 0xABC8B3304B8E9890, 0xBF967287630B02B2, 0x5B67D607B6FC6E15 }; - static uint64_t T7[256] = + static uint64_t T7[256] = { 0xD031C397CE553FE6, 0x16BA5B01B006B525, 0xA89BADE6296E70C8, 0x6A1F525D77D3435B, 0x6E103570573DFA0B, 0x660EFB2A17FC95AB, 0x76327A9E97634BF6, 0x4BAD9D6462458BF5, @@ -716,59 +716,59 @@ namespace crypto 0x717E7067AF4F499A, 0x938290A9ECD1DBB3, 0x88E3B293344DD172, 0x2734158C250FA3D6 }; - static const uint64_t C_[12][8] = + static const uint64_t C_[12][8] = { { 0xe9daca1eda5b08b1, 0x1f7c65c0812fcbeb, 0x16d0452e43766a2f, 0xfcc485758db84e71, 0x0169679291e07c4b, 0x15d360a4082a42a2, 0x234d74cc36747605, 0x0745a6f2596580dd - }, + }, { 0x1a2f9da98ab5a36f, 0xd7b5700f469de34f, 0x982b230a72eafef3, 0x3101b5160f5ed561, 0x5899d6126b17b59a, 0xcaa70adbc261b55c, 0x56cdcbd71ba2dd55, 0xb79bb121700479e6 - }, + }, { 0xc72fce2bacdc74f5, 0x35843d6a28fc390a, 0x8b1f9c525f5ef106, 0x7b7b29b11475eaf2, 0xb19e3590e40fe2d3, 0x09db6260373ac9c1, 0x31db7a8643f4b6c2, 0xb20aba0af5961e99 - }, + }, { 0xd26615e8b3df1fef, 0xdde4715da0e148f9, 0x7d3c5c337e858e48, 0x3f355e68ad1c729d, 0x75d603ed822cd7a9, 0xbe0352933313b7d8, 0xf137e893a1ea5334, 0x2ed1e384bcbe0c22 - }, + }, { 0x994747adac6bea4b, 0x6323a96c0c413f9a, 0x4a1086161f1c157f, 0xbdff0f80d7359e35, 0xa3f53a254717cdbf, 0x161a2723b700ffdf, 0xf563eaa97ea2567a, 0x57fe6c7cfd581760 - }, + }, { 0xd9d33a1daeae4fae, 0xc039307a3bc3a46f, 0x6ca44251f9c4662d, 0xc68ef09ab49a7f18, 0xb4b79a1cb7a6facf, 0xb6c6bec2661ff20a, 0x354f903672c571bf, 0x6e7d64467a4068fa - }, + }, { 0xecc5aaee160ec7f4, 0x540924bffe86ac51, 0xc987bfe6c7c69e39, 0xc9937a19333e47d3, 0x372c822dc5ab9209, 0x04054a2883694706, 0xf34a3ca24c451735, 0x93d4143a4d568688 - }, + }, { 0xa7c9934d425b1f9b, 0x41416e0c02aae703, 0x1ede369c71f8b74e, 0x9ac4db4d3b44b489, 0x90069b92cb2b89f4, 0x2fc4a5d12b8dd169, 0xd9a8515935c2ac36, 0x1ee702bfd40d7fa4 - }, + }, { 0x9b223116545a8f37, 0xde5f16ecd89a4c94, 0x244289251b3a7d3a, 0x84090de0b755d93c, 0xb1ceb2db0b440a80, 0x549c07a69a8a2b7b, 0x602a1fcb92dc380e, 0xdb5a238351446172 - }, + }, { 0x526f0580a6debeab, 0xf3f3e4b248e52a38, 0xdb788aff1ce74189, 0x0361331b8ae1ff1f, 0x4b3369af0267e79f, 0xf452763b306c1e7a, 0xc3b63b15d1fa9836, 0xed9c4598fbc7b474 - }, + }, { 0xfb89c8efd09ecd7b, 0x94fe5a63cdc60230, 0x6107abebbb6bfad8, 0x7966841421800120, 0xcab948eaef711d8a, 0x986e477d1dcdbaef, 0x5dd86fc04a59a2de, 0x1b2df381cda4ca6b - }, + }, { 0xba3116f167e78e37, 0x7ab14904b08013d2, 0x771ddfbc323ca4cd, 0x9b9f2130d41220f8, 0x86cc91189def805d, 0x5228e188aaa41de7, 0x991bb2d9d517f4fa, 0x20d71bf14a92bc48 } }; - + union GOST3411Block // 8 bytes aligned { uint8_t buf[64]; @@ -780,15 +780,15 @@ namespace crypto for (int i = 0; i < 8; i++) ret.ll[i] = ll[i]^other.ll[i]; return ret; - } - + } + GOST3411Block operator^(const uint64_t * other) const { GOST3411Block ret; for (int i = 0; i < 8; i++) ret.ll[i] = ll[i]^other[i]; return ret; - } + } GOST3411Block operator+(const GOST3411Block& other) const { @@ -799,7 +799,7 @@ namespace crypto uint16_t sum = buf[i] + other.buf[i] + carry; ret.buf[i] = sum; carry = sum >> 8; - } + } return ret; } @@ -807,17 +807,17 @@ namespace crypto { for (int i = 63; i >= 0; i--) { - if (!c) return; + if (!c) return; c += buf[i]; buf[i] = c; - c >>= 8; + c >>= 8; } } void F () { uint64_t res[8]; - for (int b=0; b<8; b++) + for (int b=0; b<8; b++) { uint64_t r; r = T0[buf[b+56]]; @@ -843,11 +843,11 @@ namespace crypto k = k^C_[i]; k.F (); res = k^res; - } + } return res; - } + } }; - + static GOST3411Block gN (const GOST3411Block& N, const GOST3411Block& h, const GOST3411Block& m) { GOST3411Block res = N ^ h; @@ -855,12 +855,12 @@ namespace crypto res = res.E (m); res = res^h; res = res^m; - return res; - } + return res; + } static void H (const uint8_t * iv, const uint8_t * buf, size_t len, uint8_t * digest) { - // stage 1 + // stage 1 GOST3411Block h, N, s, m; memcpy (h.buf, iv, 64); memset (N.buf, 0, 64); @@ -885,15 +885,15 @@ namespace crypto memcpy (m.buf + padding, buf, l); h = gN (N, h, m); - N.Add (l*8); + N.Add (l*8); s = m + s; - + GOST3411Block N0; memset (N0.buf, 0, 64); h = gN (N0, h, N); h = gN (N0, h, s); - - memcpy (digest, h.buf, 64); + + memcpy (digest, h.buf, 64); } void GOSTR3411_2012_256 (const uint8_t * buf, size_t len, uint8_t * digest) @@ -919,7 +919,7 @@ namespace crypto size_t len; bool is512; }; - + GOSTR3411_2012_CTX * GOSTR3411_2012_CTX_new () { return new GOSTR3411_2012_CTX; @@ -949,7 +949,7 @@ namespace crypto size_t l = 64 - ctx->len; if (len < l) l = len; for (size_t i = 0; i < l; i++) - ctx->m.buf[ctx->len + i] = buf[l-i-1]; // invert + ctx->m.buf[ctx->len + i] = buf[l-i-1]; // invert ctx->len += l; len -= l; buf += l; ctx->h = gN (ctx->N, ctx->h, ctx->m); @@ -959,7 +959,7 @@ namespace crypto while (len >= 64) { for (size_t i = 0; i < 64; i++) - ctx->m.buf[i] = buf[63-i]; // invert + ctx->m.buf[i] = buf[63-i]; // invert len -= 64; buf += 64; ctx->h = gN (ctx->N, ctx->h, ctx->m); ctx->N.Add (512); @@ -975,7 +975,7 @@ namespace crypto void GOSTR3411_2012_CTX_Finish (uint8_t * digest, GOSTR3411_2012_CTX * ctx) { - GOST3411Block m; + GOST3411Block m; size_t padding = 64 - ctx->len; if (padding) { @@ -985,14 +985,14 @@ namespace crypto memcpy (m.buf + padding, ctx->m.buf, ctx->len); ctx->h = gN (ctx->N, ctx->h, m); - ctx->N.Add (ctx->len*8); + ctx->N.Add (ctx->len*8); ctx->s = m + ctx->s; - + GOST3411Block N0; memset (N0.buf, 0, 64); ctx->h = gN (N0, ctx->h, ctx->N); ctx->h = gN (N0, ctx->h, ctx->s); - + size_t sz = ctx->is512 ? 64 : 32; for (size_t i = 0; i < sz; i++) digest[i] = ctx->h.buf[sz - i - 1]; diff --git a/libi2pd/Gost.h b/libi2pd/Gost.h index 66e8bbe8..30386104 100644 --- a/libi2pd/Gost.h +++ b/libi2pd/Gost.h @@ -10,25 +10,25 @@ namespace crypto { // ГОСТ Р 34.10 - + enum GOSTR3410ParamSet { eGOSTR3410CryptoProA = 0, // 1.2.643.2.2.35.1 // XchA = A, XchB = C //eGOSTR3410CryptoProXchA, // 1.2.643.2.2.36.0 - //eGOSTR3410CryptoProXchB, // 1.2.643.2.2.36.1 + //eGOSTR3410CryptoProXchB, // 1.2.643.2.2.36.1 eGOSTR3410TC26A512, // 1.2.643.7.1.2.1.2.1 eGOSTR3410NumParamSets - }; - + }; + class GOSTR3410Curve { public: GOSTR3410Curve (BIGNUM * a, BIGNUM * b, BIGNUM * p, BIGNUM * q, BIGNUM * x, BIGNUM * y); - ~GOSTR3410Curve (); + ~GOSTR3410Curve (); - size_t GetKeyLen () const { return m_KeyLen; }; + size_t GetKeyLen () const { return m_KeyLen; }; const EC_GROUP * GetGroup () const { return m_Group; }; EC_POINT * MulP (const BIGNUM * n) const; bool GetXY (const EC_POINT * p, BIGNUM * x, BIGNUM * y) const; @@ -36,7 +36,7 @@ namespace crypto void Sign (const BIGNUM * priv, const BIGNUM * digest, BIGNUM * r, BIGNUM * s); bool Verify (const EC_POINT * pub, const BIGNUM * digest, const BIGNUM * r, const BIGNUM * s); EC_POINT * RecoverPublicKey (const BIGNUM * digest, const BIGNUM * r, const BIGNUM * s, bool isNegativeY = false) const; - + private: EC_GROUP * m_Group; @@ -47,14 +47,14 @@ namespace crypto // Big Endian void GOSTR3411_2012_256 (const uint8_t * buf, size_t len, uint8_t * digest); - void GOSTR3411_2012_512 (const uint8_t * buf, size_t len, uint8_t * digest); + void GOSTR3411_2012_512 (const uint8_t * buf, size_t len, uint8_t * digest); // Little Endian struct GOSTR3411_2012_CTX; GOSTR3411_2012_CTX * GOSTR3411_2012_CTX_new (); void GOSTR3411_2012_CTX_Init (GOSTR3411_2012_CTX * ctx, bool is512 = true); void GOSTR3411_2012_CTX_Update (const uint8_t * buf, size_t len, GOSTR3411_2012_CTX * ctx); - void GOSTR3411_2012_CTX_Finish (uint8_t * digest, GOSTR3411_2012_CTX * ctx); + void GOSTR3411_2012_CTX_Finish (uint8_t * digest, GOSTR3411_2012_CTX * ctx); void GOSTR3411_2012_CTX_free (GOSTR3411_2012_CTX * ctx); } } diff --git a/libi2pd/Gzip.cpp b/libi2pd/Gzip.cpp index db991283..1c06e941 100644 --- a/libi2pd/Gzip.cpp +++ b/libi2pd/Gzip.cpp @@ -12,9 +12,9 @@ #include "Log.h" #include "Gzip.h" -namespace i2p +namespace i2p { -namespace data +namespace data { const size_t GZIP_CHUNK_SIZE = 16384; @@ -38,7 +38,7 @@ namespace data m_Inflator.next_out = out; m_Inflator.avail_out = outLen; int err; - if ((err = inflate (&m_Inflator, Z_NO_FLUSH)) == Z_STREAM_END) + if ((err = inflate (&m_Inflator, Z_NO_FLUSH)) == Z_STREAM_END) return outLen - m_Inflator.avail_out; // else LogPrint (eLogError, "Gzip: Inflate error ", err); @@ -52,19 +52,19 @@ namespace data m_Inflator.next_in = const_cast(in); m_Inflator.avail_in = inLen; int ret; - do + do { m_Inflator.next_out = out; m_Inflator.avail_out = GZIP_CHUNK_SIZE; ret = inflate (&m_Inflator, Z_NO_FLUSH); - if (ret < 0) + if (ret < 0) { inflateEnd (&m_Inflator); os.setstate(std::ios_base::failbit); break; } os.write ((char *)out, GZIP_CHUNK_SIZE - m_Inflator.avail_out); - } + } while (!m_Inflator.avail_out); // more data to read delete[] out; } @@ -105,7 +105,7 @@ namespace data m_Deflator.next_out = out; m_Deflator.avail_out = outLen; int err; - if ((err = deflate (&m_Deflator, Z_FINISH)) == Z_STREAM_END) + if ((err = deflate (&m_Deflator, Z_FINISH)) == Z_STREAM_END) return outLen - m_Deflator.avail_out; // else LogPrint (eLogError, "Gzip: Deflate error ", err); diff --git a/libi2pd/HTTP.cpp b/libi2pd/HTTP.cpp index c81b1a07..24e55457 100644 --- a/libi2pd/HTTP.cpp +++ b/libi2pd/HTTP.cpp @@ -44,7 +44,7 @@ namespace http { } } - static std::pair parse_header_line(const std::string& line) + static std::pair parse_header_line(const std::string& line) { std::size_t pos = 0; std::size_t len = 2; /* strlen(": ") */ @@ -251,14 +251,14 @@ namespace http { uri = tokens[1]; version = tokens[2]; expect = HEADER_LINE; - } - else + } + else { std::string line = str.substr(pos, eol - pos); auto p = parse_header_line(line); if (p.first.length () > 0) headers.push_back (p); - else + else return -1; } pos = eol + strlen(CRLF); @@ -268,11 +268,11 @@ namespace http { return eoh + strlen(HTTP_EOH); } - void HTTPReq::write(std::ostream & o) + void HTTPReq::write(std::ostream & o) { o << method << " " << uri << " " << version << CRLF; - for (auto & h : headers) - o << h.first << ": " << h.second << CRLF; + for (auto & h : headers) + o << h.first << ": " << h.second << CRLF; o << CRLF; } @@ -284,7 +284,7 @@ namespace http { } void HTTPReq::AddHeader (const std::string& name, const std::string& value) - { + { headers.push_back (std::make_pair(name, value)); } @@ -295,28 +295,28 @@ namespace http { { it.second = value; break; - } - } - + } + } + void HTTPReq::RemoveHeader (const std::string& name, const std::string& exempt) { for (auto it = headers.begin (); it != headers.end ();) { - if (!it->first.compare(0, name.length (), name) && it->first != exempt) + if (!it->first.compare(0, name.length (), name) && it->first != exempt) it = headers.erase (it); else it++; - } - } + } + } - std::string HTTPReq::GetHeader (const std::string& name) const + std::string HTTPReq::GetHeader (const std::string& name) const { for (auto& it : headers) if (it.first == name) - return it.second; + return it.second; return ""; - } - + } + bool HTTPRes::is_chunked() const { auto it = headers.find("Transfer-Encoding"); @@ -335,10 +335,10 @@ namespace http { if (it->second.find("gzip") != std::string::npos) return true; /* gotcha! */ if (includingI2PGzip && it->second.find("x-i2p-gzip") != std::string::npos) - return true; + return true; return false; } - + long int HTTPMsg::content_length() const { unsigned long int length = 0; @@ -385,8 +385,8 @@ namespace http { std::string line = str.substr(pos, eol - pos); auto p = parse_header_line(line); if (p.first.length () > 0) - headers.insert (p); - else + headers.insert (p); + else return -1; } pos = eol + strlen(CRLF); diff --git a/libi2pd/HTTP.h b/libi2pd/HTTP.h index 272f2f44..837faf01 100644 --- a/libi2pd/HTTP.h +++ b/libi2pd/HTTP.h @@ -16,16 +16,16 @@ #include #include -namespace i2p +namespace i2p { -namespace http +namespace http { const char CRLF[] = "\r\n"; /**< HTTP line terminator */ const char HTTP_EOH[] = "\r\n\r\n"; /**< HTTP end-of-headers mark */ extern const std::vector HTTP_METHODS; /**< list of valid HTTP methods */ extern const std::vector HTTP_VERSIONS; /**< list of valid HTTP versions */ - struct URL + struct URL { std::string schema; std::string user; @@ -63,7 +63,7 @@ namespace http bool is_i2p() const; }; - struct HTTPMsg + struct HTTPMsg { std::map headers; @@ -75,9 +75,9 @@ namespace http long int content_length() const; }; - struct HTTPReq + struct HTTPReq { - std::list > headers; + std::list > headers; std::string version; std::string method; std::string uri; @@ -97,10 +97,10 @@ namespace http void write(std::ostream & o); void AddHeader (const std::string& name, const std::string& value); - void UpdateHeader (const std::string& name, const std::string& value); + void UpdateHeader (const std::string& name, const std::string& value); void RemoveHeader (const std::string& name, const std::string& exempt); // remove all headers starting with name, but exempt void RemoveHeader (const std::string& name) { RemoveHeader (name, ""); }; - std::string GetHeader (const std::string& name) const; + std::string GetHeader (const std::string& name) const; }; struct HTTPRes : HTTPMsg { diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 5719a1b0..9bb7dfd1 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -21,7 +21,7 @@ namespace i2p { return std::make_shared >(); } - + std::shared_ptr NewI2NPShortMessage () { return std::make_shared >(); @@ -32,38 +32,38 @@ namespace i2p auto msg = new I2NPMessageBuffer(); // reserved for alignment and NTCP 16 + 6 + 12 msg->Align (12); return std::shared_ptr(msg); - } - + } + std::shared_ptr NewI2NPMessage (size_t len) { return (len < I2NP_MAX_SHORT_MESSAGE_SIZE/2) ? NewI2NPShortMessage () : NewI2NPMessage (); - } + } void I2NPMessage::FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID) { SetTypeID (msgType); if (!replyMsgID) RAND_bytes ((uint8_t *)&replyMsgID, 4); - SetMsgID (replyMsgID); - SetExpiration (i2p::util::GetMillisecondsSinceEpoch () + I2NP_MESSAGE_EXPIRATION_TIMEOUT); + SetMsgID (replyMsgID); + SetExpiration (i2p::util::GetMillisecondsSinceEpoch () + I2NP_MESSAGE_EXPIRATION_TIMEOUT); UpdateSize (); UpdateChks (); - } - + } + void I2NPMessage::RenewI2NPMessageHeader () { uint32_t msgID; RAND_bytes ((uint8_t *)&msgID, 4); SetMsgID (msgID); - SetExpiration (i2p::util::GetMillisecondsSinceEpoch () + I2NP_MESSAGE_EXPIRATION_TIMEOUT); + SetExpiration (i2p::util::GetMillisecondsSinceEpoch () + I2NP_MESSAGE_EXPIRATION_TIMEOUT); } bool I2NPMessage::IsExpired () const { auto ts = i2p::util::GetMillisecondsSinceEpoch (); - auto exp = GetExpiration (); + auto exp = GetExpiration (); return (ts > exp + I2NP_MESSAGE_CLOCK_SKEW) || (ts < exp - 3*I2NP_MESSAGE_CLOCK_SKEW); // check if expired or too far in future - } - + } + std::shared_ptr CreateI2NPMessage (I2NPMessageType msgType, const uint8_t * buf, size_t len, uint32_t replyMsgID) { auto msg = NewI2NPMessage (len); @@ -71,7 +71,7 @@ namespace i2p LogPrint (eLogError, "I2NP: message length ", len, " exceeds max length ", msg->maxLen); msg->FillI2NPMessageHeader (msgType, replyMsgID); return msg; - } + } std::shared_ptr CreateI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from) { @@ -85,7 +85,7 @@ namespace i2p else LogPrint (eLogError, "I2NP: message length ", len, " exceeds max length"); return msg; - } + } std::shared_ptr CopyI2NPMessage (std::shared_ptr msg) { @@ -94,8 +94,8 @@ namespace i2p newMsg->offset = msg->offset; *newMsg = *msg; return newMsg; - } - + } + std::shared_ptr CreateDeliveryStatusMsg (uint32_t msgID) { auto m = NewI2NPShortMessage (); @@ -109,14 +109,14 @@ namespace i2p { RAND_bytes ((uint8_t *)&msgID, 4); htobe32buf (buf + DELIVERY_STATUS_MSGID_OFFSET, msgID); - htobe64buf (buf + DELIVERY_STATUS_TIMESTAMP_OFFSET, i2p::context.GetNetID ()); - } + htobe64buf (buf + DELIVERY_STATUS_TIMESTAMP_OFFSET, i2p::context.GetNetID ()); + } m->len += DELIVERY_STATUS_SIZE; m->FillI2NPMessageHeader (eI2NPDeliveryStatus); return m; } - std::shared_ptr CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from, + std::shared_ptr CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from, uint32_t replyTunnelID, bool exploratory, std::set * excludedPeers) { auto m = excludedPeers ? NewI2NPMessage () : NewI2NPShortMessage (); @@ -125,7 +125,7 @@ namespace i2p buf += 32; memcpy (buf, from, 32); // from buf += 32; - uint8_t flag = exploratory ? DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP : DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP; + uint8_t flag = exploratory ? DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP : DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP; if (replyTunnelID) { *buf = flag | DATABASE_LOOKUP_DELIVERY_FLAG; // set delivery flag @@ -133,11 +133,11 @@ namespace i2p buf += 5; } else - { + { *buf = flag; // flag buf++; - } - + } + if (excludedPeers) { int cnt = excludedPeers->size (); @@ -147,21 +147,21 @@ namespace i2p { memcpy (buf, it, 32); buf += 32; - } + } } else - { + { // nothing to exclude htobuf16 (buf, 0); buf += 2; - } - - m->len += (buf - m->GetPayload ()); - m->FillI2NPMessageHeader (eI2NPDatabaseLookup); - return m; - } + } - std::shared_ptr CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest, + m->len += (buf - m->GetPayload ()); + m->FillI2NPMessageHeader (eI2NPDatabaseLookup); + return m; + } + + std::shared_ptr CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest, const std::set& excludedFloodfills, std::shared_ptr replyTunnel, const uint8_t * replyKey, const uint8_t * replyTag) { @@ -176,7 +176,7 @@ namespace i2p buf ++; htobe32buf (buf, replyTunnel->GetNextTunnelID ()); // reply tunnel ID buf += 4; - + // excluded htobe16buf (buf, cnt); buf += 2; @@ -187,19 +187,19 @@ namespace i2p memcpy (buf, it, 32); buf += 32; } - } + } // encryption memcpy (buf, replyKey, 32); buf[32] = uint8_t( 1 ); // 1 tag memcpy (buf + 33, replyTag, 32); buf += 65; - m->len += (buf - m->GetPayload ()); + m->len += (buf - m->GetPayload ()); m->FillI2NPMessageHeader (eI2NPDatabaseLookup); - return m; - } + return m; + } - std::shared_ptr CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, + std::shared_ptr CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, std::vector routers) { auto m = NewI2NPShortMessage (); @@ -207,27 +207,27 @@ namespace i2p size_t len = 0; memcpy (buf, ident, 32); len += 32; - buf[len] = routers.size (); + buf[len] = routers.size (); len++; for (const auto& it: routers) { memcpy (buf + len, it, 32); len += 32; - } + } memcpy (buf + len, i2p::context.GetRouterInfo ().GetIdentHash (), 32); - len += 32; + len += 32; m->len += len; m->FillI2NPMessageHeader (eI2NPDatabaseSearchReply); - return m; - } - + return m; + } + std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr router, uint32_t replyToken) { if (!router) // we send own RouterInfo router = context.GetSharedRouterInfo (); auto m = NewI2NPShortMessage (); - uint8_t * payload = m->GetPayload (); + uint8_t * payload = m->GetPayload (); memcpy (payload + DATABASE_STORE_KEY_OFFSET, router->GetIdentHash (), 32); payload[DATABASE_STORE_TYPE_OFFSET] = 0; // RouterInfo @@ -239,7 +239,7 @@ namespace i2p buf += 4; memcpy (buf, router->GetIdentHash (), 32); buf += 32; - } + } uint8_t * sizePtr = buf; buf += 2; @@ -247,22 +247,22 @@ namespace i2p i2p::data::GzipDeflator deflator; size_t size = deflator.Deflate (router->GetBuffer (), router->GetBufferLen (), buf, m->maxLen -m->len); if (size) - { + { htobe16buf (sizePtr, size); // size m->len += size; - } + } else m = nullptr; if (m) m->FillI2NPMessageHeader (eI2NPDatabaseStore); return m; - } + } std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet) { if (!leaseSet) return nullptr; auto m = NewI2NPShortMessage (); - uint8_t * payload = m->GetPayload (); + uint8_t * payload = m->GetPayload (); memcpy (payload + DATABASE_STORE_KEY_OFFSET, leaseSet->GetIdentHash (), 32); payload[DATABASE_STORE_TYPE_OFFSET] = 1; // LeaseSet htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); @@ -278,7 +278,7 @@ namespace i2p { if (!leaseSet) return nullptr; auto m = NewI2NPShortMessage (); - uint8_t * payload = m->GetPayload (); + uint8_t * payload = m->GetPayload (); memcpy (payload + DATABASE_STORE_KEY_OFFSET, leaseSet->GetIdentHash (), 32); payload[DATABASE_STORE_TYPE_OFFSET] = 1; // LeaseSet htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, replyToken); @@ -306,8 +306,8 @@ namespace i2p { if (!msg || msg->GetTypeID () != eI2NPDatabaseStore) return false; return !msg->GetPayload ()[DATABASE_STORE_TYPE_OFFSET]; // 0- RouterInfo - } - + } + static uint16_t g_MaxNumTransitTunnels = DEFAULT_MAX_NUM_TRANSIT_TUNNELS; // TODO: void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels) { @@ -321,37 +321,37 @@ namespace i2p bool HandleBuildRequestRecords (int num, uint8_t * records, uint8_t * clearText) { for (int i = 0; i < num; i++) - { + { uint8_t * record = records + i*TUNNEL_BUILD_RECORD_SIZE; if (!memcmp (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)i2p::context.GetRouterInfo ().GetIdentHash (), 16)) - { + { LogPrint (eLogDebug, "I2NP: Build request record ", i, " is ours"); BN_CTX * ctx = BN_CTX_new (); i2p::crypto::ElGamalDecrypt (i2p::context.GetPrivateKeys ().GetPrivateKey () , record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText, ctx); BN_CTX_free (ctx); - // replace record to reply - if (i2p::context.AcceptsTunnels () && + // replace record to reply + if (i2p::context.AcceptsTunnels () && i2p::tunnel::tunnels.GetTransitTunnels ().size () <= g_MaxNumTransitTunnels && !i2p::transport::transports.IsBandwidthExceeded () && !i2p::transport::transports.IsTransitBandwidthExceeded ()) - { + { auto transitTunnel = i2p::tunnel::CreateTransitTunnel ( - bufbe32toh (clearText + BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET), - clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, + bufbe32toh (clearText + BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET), + clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), - clearText + BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET, - clearText + BUILD_REQUEST_RECORD_IV_KEY_OFFSET, - clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x80, + clearText + BUILD_REQUEST_RECORD_LAYER_KEY_OFFSET, + clearText + BUILD_REQUEST_RECORD_IV_KEY_OFFSET, + clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x80, clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET ] & 0x40); i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel); record[BUILD_RESPONSE_RECORD_RET_OFFSET] = 0; } else record[BUILD_RESPONSE_RECORD_RET_OFFSET] = 30; // always reject with bandwidth reason (30) - + //TODO: fill filler SHA256 (record + BUILD_RESPONSE_RECORD_PADDING_OFFSET, BUILD_RESPONSE_RECORD_PADDING_SIZE + 1, // + 1 byte of ret - record + BUILD_RESPONSE_RECORD_HASH_OFFSET); + record + BUILD_RESPONSE_RECORD_HASH_OFFSET); // encrypt reply i2p::crypto::CBCEncryption encryption; for (int j = 0; j < num; j++) @@ -359,23 +359,23 @@ namespace i2p encryption.SetKey (clearText + BUILD_REQUEST_RECORD_REPLY_KEY_OFFSET); encryption.SetIV (clearText + BUILD_REQUEST_RECORD_REPLY_IV_OFFSET); uint8_t * reply = records + j*TUNNEL_BUILD_RECORD_SIZE; - encryption.Encrypt(reply, TUNNEL_BUILD_RECORD_SIZE, reply); + encryption.Encrypt(reply, TUNNEL_BUILD_RECORD_SIZE, reply); } return true; - } - } + } + } return false; } void HandleVariableTunnelBuildMsg (uint32_t replyMsgID, uint8_t * buf, size_t len) - { + { int num = buf[0]; LogPrint (eLogDebug, "I2NP: VariableTunnelBuild ", num, " records"); if (len < num*BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE + 1) { LogPrint (eLogError, "VaribleTunnelBuild message of ", num, " records is too short ", len); return; - } + } auto tunnel = i2p::tunnel::tunnels.GetPendingInboundTunnel (replyMsgID); if (tunnel) @@ -385,34 +385,34 @@ namespace i2p if (tunnel->HandleTunnelBuildResponse (buf, len)) { LogPrint (eLogInfo, "I2NP: Inbound tunnel ", tunnel->GetTunnelID (), " has been created"); - tunnel->SetState (i2p::tunnel::eTunnelStateEstablished); + tunnel->SetState (i2p::tunnel::eTunnelStateEstablished); i2p::tunnel::tunnels.AddInboundTunnel (tunnel); } else { LogPrint (eLogInfo, "I2NP: Inbound tunnel ", tunnel->GetTunnelID (), " has been declined"); - tunnel->SetState (i2p::tunnel::eTunnelStateBuildFailed); + tunnel->SetState (i2p::tunnel::eTunnelStateBuildFailed); } } else { - uint8_t clearText[BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE]; + uint8_t clearText[BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE]; if (HandleBuildRequestRecords (num, buf + 1, clearText)) { if (clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x40) // we are endpoint of outboud tunnel { - // so we send it to reply tunnel - transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, + // so we send it to reply tunnel + transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), - eI2NPVariableTunnelBuildReply, buf, len, - bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); - } - else - transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, - CreateI2NPMessage (eI2NPVariableTunnelBuild, buf, len, + eI2NPVariableTunnelBuildReply, buf, len, + bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); + } + else + transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, + CreateI2NPMessage (eI2NPVariableTunnelBuild, buf, len, bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); - } - } + } + } } void HandleTunnelBuildMsg (uint8_t * buf, size_t len) @@ -421,51 +421,51 @@ namespace i2p { LogPrint (eLogError, "TunnelBuild message is too short ", len); return; - } - uint8_t clearText[BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE]; + } + uint8_t clearText[BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE]; if (HandleBuildRequestRecords (NUM_TUNNEL_BUILD_RECORDS, buf, clearText)) { if (clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] & 0x40) // we are endpoint of outbound tunnel { - // so we send it to reply tunnel - transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, + // so we send it to reply tunnel + transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, CreateTunnelGatewayMsg (bufbe32toh (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET), - eI2NPTunnelBuildReply, buf, len, - bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); - } - else - transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, - CreateI2NPMessage (eI2NPTunnelBuild, buf, len, + eI2NPTunnelBuildReply, buf, len, + bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); + } + else + transports.SendMessage (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, + CreateI2NPMessage (eI2NPTunnelBuild, buf, len, bufbe32toh (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET))); - } + } } void HandleVariableTunnelBuildReplyMsg (uint32_t replyMsgID, uint8_t * buf, size_t len) - { + { int num = buf[0]; LogPrint (eLogDebug, "I2NP: VariableTunnelBuildReplyMsg of ", num, " records replyMsgID=", replyMsgID); if (len < num*BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE + 1) { LogPrint (eLogError, "VaribleTunnelBuildReply message of ", num, " records is too short ", len); return; - } - + } + auto tunnel = i2p::tunnel::tunnels.GetPendingOutboundTunnel (replyMsgID); if (tunnel) - { + { // reply for outbound tunnel if (tunnel->HandleTunnelBuildResponse (buf, len)) - { + { LogPrint (eLogInfo, "I2NP: Outbound tunnel ", tunnel->GetTunnelID (), " has been created"); - tunnel->SetState (i2p::tunnel::eTunnelStateEstablished); + tunnel->SetState (i2p::tunnel::eTunnelStateEstablished); i2p::tunnel::tunnels.AddOutboundTunnel (tunnel); - } + } else { LogPrint (eLogInfo, "I2NP: Outbound tunnel ", tunnel->GetTunnelID (), " has been declined"); - tunnel->SetState (i2p::tunnel::eTunnelStateBuildFailed); + tunnel->SetState (i2p::tunnel::eTunnelStateBuildFailed); } - } + } else LogPrint (eLogWarning, "I2NP: Pending tunnel for message ", replyMsgID, " not found"); } @@ -474,12 +474,12 @@ namespace i2p std::shared_ptr CreateTunnelDataMsg (const uint8_t * buf) { auto msg = NewI2NPTunnelMessage (); - msg->Concat (buf, i2p::tunnel::TUNNEL_DATA_MSG_SIZE); + msg->Concat (buf, i2p::tunnel::TUNNEL_DATA_MSG_SIZE); msg->FillI2NPMessageHeader (eI2NPTunnelData); return msg; - } + } - std::shared_ptr CreateTunnelDataMsg (uint32_t tunnelID, const uint8_t * payload) + std::shared_ptr CreateTunnelDataMsg (uint32_t tunnelID, const uint8_t * payload) { auto msg = NewI2NPTunnelMessage (); htobe32buf (msg->GetPayload (), tunnelID); @@ -487,15 +487,15 @@ namespace i2p msg->Concat (payload, i2p::tunnel::TUNNEL_DATA_MSG_SIZE - 4); msg->FillI2NPMessageHeader (eI2NPTunnelData); return msg; - } + } std::shared_ptr CreateEmptyTunnelDataMsg () { auto msg = NewI2NPTunnelMessage (); - msg->len += i2p::tunnel::TUNNEL_DATA_MSG_SIZE; + msg->len += i2p::tunnel::TUNNEL_DATA_MSG_SIZE; return msg; - } - + } + std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, const uint8_t * buf, size_t len) { auto msg = NewI2NPMessage (len); @@ -504,10 +504,10 @@ namespace i2p htobe16buf (payload + TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET, len); msg->len += TUNNEL_GATEWAY_HEADER_SIZE; if (msg->Concat (buf, len) < len) - LogPrint (eLogError, "I2NP: tunnel gateway buffer overflow ", msg->maxLen); + LogPrint (eLogError, "I2NP: tunnel gateway buffer overflow ", msg->maxLen); msg->FillI2NPMessageHeader (eI2NPTunnelGateway); return msg; - } + } std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, std::shared_ptr msg) { @@ -520,14 +520,14 @@ namespace i2p htobe16buf (payload + TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET, len); msg->offset -= (I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE); msg->len = msg->offset + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE +len; - msg->FillI2NPMessageHeader (eI2NPTunnelGateway); + msg->FillI2NPMessageHeader (eI2NPTunnelGateway); return msg; } else - return CreateTunnelGatewayMsg (tunnelID, msg->GetBuffer (), msg->GetLength ()); + return CreateTunnelGatewayMsg (tunnelID, msg->GetBuffer (), msg->GetLength ()); } - std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, I2NPMessageType msgType, + std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, I2NPMessageType msgType, const uint8_t * buf, size_t len, uint32_t replyMsgID) { auto msg = NewI2NPMessage (len); @@ -544,7 +544,7 @@ namespace i2p htobe16buf (payload + TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET, len); msg->FillI2NPMessageHeader (eI2NPTunnelGateway); // gateway message return msg; - } + } size_t GetI2NPMessageLength (const uint8_t * msg, size_t len) { @@ -552,25 +552,25 @@ namespace i2p { LogPrint (eLogError, "I2NP: message length ", len, " is smaller than header"); return len; - } + } auto l = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET) + I2NP_HEADER_SIZE; if (l > len) { LogPrint (eLogError, "I2NP: message length ", l, " exceeds buffer length ", len); l = len; - } + } return l; - } - + } + void HandleI2NPMessage (uint8_t * msg, size_t len) { if (len < I2NP_HEADER_SIZE) { LogPrint (eLogError, "I2NP: message length ", len, " is smaller than header"); return; - } + } uint8_t typeID = msg[I2NP_HEADER_TYPEID_OFFSET]; - uint32_t msgID = bufbe32toh (msg + I2NP_HEADER_MSGID_OFFSET); + uint32_t msgID = bufbe32toh (msg + I2NP_HEADER_MSGID_OFFSET); LogPrint (eLogDebug, "I2NP: msg received len=", len,", type=", (int)typeID, ", msgID=", (unsigned int)msgID); uint8_t * buf = msg + I2NP_HEADER_SIZE; auto size = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET); @@ -581,35 +581,35 @@ namespace i2p size = len; } switch (typeID) - { + { case eI2NPVariableTunnelBuild: HandleVariableTunnelBuildMsg (msgID, buf, size); - break; + break; case eI2NPVariableTunnelBuildReply: HandleVariableTunnelBuildReplyMsg (msgID, buf, size); - break; + break; case eI2NPTunnelBuild: HandleTunnelBuildMsg (buf, size); - break; + break; case eI2NPTunnelBuildReply: // TODO: - break; + break; default: LogPrint (eLogWarning, "I2NP: Unexpected message ", (int)typeID); - } + } } void HandleI2NPMessage (std::shared_ptr msg) { if (msg) - { + { uint8_t typeID = msg->GetTypeID (); LogPrint (eLogDebug, "I2NP: Handling message with type ", (int)typeID); switch (typeID) - { + { case eI2NPTunnelData: i2p::tunnel::tunnels.PostTunnelData (msg); - break; + break; case eI2NPTunnelGateway: i2p::tunnel::tunnels.PostTunnelData (msg); break; @@ -623,7 +623,7 @@ namespace i2p LogPrint (eLogInfo, "I2NP: Local destination for garlic doesn't exist anymore"); } else - i2p::context.ProcessGarlicMessage (msg); + i2p::context.ProcessGarlicMessage (msg); break; } case eI2NPDatabaseStore: @@ -638,55 +638,55 @@ namespace i2p msg->from->GetTunnelPool ()->ProcessDeliveryStatus (msg); else i2p::context.ProcessDeliveryStatusMessage (msg); - break; + break; } - case eI2NPVariableTunnelBuild: + case eI2NPVariableTunnelBuild: case eI2NPVariableTunnelBuildReply: case eI2NPTunnelBuild: - case eI2NPTunnelBuildReply: + case eI2NPTunnelBuildReply: // forward to tunnel thread i2p::tunnel::tunnels.PostTunnelData (msg); - break; + break; default: HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ()); - } - } - } + } + } + } I2NPMessagesHandler::~I2NPMessagesHandler () { Flush (); } - + void I2NPMessagesHandler::PutNextMessage (std::shared_ptr msg) { if (msg) { switch (msg->GetTypeID ()) - { + { case eI2NPTunnelData: m_TunnelMsgs.push_back (msg); break; - case eI2NPTunnelGateway: + case eI2NPTunnelGateway: m_TunnelGatewayMsgs.push_back (msg); - break; + break; default: HandleI2NPMessage (msg); - } - } + } + } } - + void I2NPMessagesHandler::Flush () { if (!m_TunnelMsgs.empty ()) - { + { i2p::tunnel::tunnels.PostTunnelData (m_TunnelMsgs); m_TunnelMsgs.clear (); - } + } if (!m_TunnelGatewayMsgs.empty ()) - { + { i2p::tunnel::tunnels.PostTunnelData (m_TunnelGatewayMsgs); m_TunnelGatewayMsgs.clear (); - } - } + } + } } diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index 3f36b0a8..f394d284 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -12,7 +12,7 @@ #include "LeaseSet.h" namespace i2p -{ +{ // I2NP header const size_t I2NP_HEADER_TYPEID_OFFSET = 0; const size_t I2NP_HEADER_MSGID_OFFSET = I2NP_HEADER_TYPEID_OFFSET + 1; @@ -25,13 +25,13 @@ namespace i2p const size_t I2NP_SHORT_HEADER_TYPEID_OFFSET = 0; const size_t I2NP_SHORT_HEADER_EXPIRATION_OFFSET = I2NP_SHORT_HEADER_TYPEID_OFFSET + 1; const size_t I2NP_SHORT_HEADER_SIZE = I2NP_SHORT_HEADER_EXPIRATION_OFFSET + 4; - + // Tunnel Gateway header const size_t TUNNEL_GATEWAY_HEADER_TUNNELID_OFFSET = 0; const size_t TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET = TUNNEL_GATEWAY_HEADER_TUNNELID_OFFSET + 4; const size_t TUNNEL_GATEWAY_HEADER_SIZE = TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET + 2; - // DeliveryStatus + // DeliveryStatus const size_t DELIVERY_STATUS_MSGID_OFFSET = 0; const size_t DELIVERY_STATUS_TIMESTAMP_OFFSET = DELIVERY_STATUS_MSGID_OFFSET + 4; const size_t DELIVERY_STATUS_SIZE = DELIVERY_STATUS_TIMESTAMP_OFFSET + 8; @@ -42,7 +42,7 @@ namespace i2p const size_t DATABASE_STORE_REPLY_TOKEN_OFFSET = DATABASE_STORE_TYPE_OFFSET + 1; const size_t DATABASE_STORE_HEADER_SIZE = DATABASE_STORE_REPLY_TOKEN_OFFSET + 4; - // TunnelBuild + // TunnelBuild const size_t TUNNEL_BUILD_RECORD_SIZE = 528; //BuildRequestRecordClearText @@ -59,11 +59,11 @@ namespace i2p const size_t BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET = BUILD_REQUEST_RECORD_REQUEST_TIME_OFFSET + 4; const size_t BUILD_REQUEST_RECORD_PADDING_OFFSET = BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET + 4; const size_t BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE = 222; - - // BuildRequestRecordEncrypted + + // BuildRequestRecordEncrypted const size_t BUILD_REQUEST_RECORD_TO_PEER_OFFSET = 0; const size_t BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET = BUILD_REQUEST_RECORD_TO_PEER_OFFSET + 16; - + // BuildResponseRecord const size_t BUILD_RESPONSE_RECORD_HASH_OFFSET = 0; const size_t BUILD_RESPONSE_RECORD_PADDING_OFFSET = 32; @@ -83,40 +83,40 @@ namespace i2p eI2NPTunnelBuild = 21, eI2NPTunnelBuildReply = 22, eI2NPVariableTunnelBuild = 23, - eI2NPVariableTunnelBuildReply = 24 - }; + eI2NPVariableTunnelBuildReply = 24 + }; - const int NUM_TUNNEL_BUILD_RECORDS = 8; + const int NUM_TUNNEL_BUILD_RECORDS = 8; // DatabaseLookup flags const uint8_t DATABASE_LOOKUP_DELIVERY_FLAG = 0x01; - const uint8_t DATABASE_LOOKUP_ENCRYPTION_FLAG = 0x02; + const uint8_t DATABASE_LOOKUP_ENCRYPTION_FLAG = 0x02; const uint8_t DATABASE_LOOKUP_TYPE_FLAGS_MASK = 0x0C; const uint8_t DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP = 0; const uint8_t DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP = 0x04; // 0100 - const uint8_t DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP = 0x08; // 1000 + const uint8_t DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP = 0x08; // 1000 const uint8_t DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP = 0x0C; // 1100 namespace tunnel -{ +{ class InboundTunnel; class TunnelPool; } - const size_t I2NP_MAX_MESSAGE_SIZE = 32768; - const size_t I2NP_MAX_SHORT_MESSAGE_SIZE = 4096; + const size_t I2NP_MAX_MESSAGE_SIZE = 32768; + const size_t I2NP_MAX_SHORT_MESSAGE_SIZE = 4096; const unsigned int I2NP_MESSAGE_EXPIRATION_TIMEOUT = 8000; // in milliseconds (as initial RTT) - const unsigned int I2NP_MESSAGE_CLOCK_SKEW = 60*1000; // 1 minute in milliseconds + const unsigned int I2NP_MESSAGE_CLOCK_SKEW = 60*1000; // 1 minute in milliseconds struct I2NPMessage - { - uint8_t * buf; + { + uint8_t * buf; size_t len, offset, maxLen; std::shared_ptr from; - - I2NPMessage (): buf (nullptr),len (I2NP_HEADER_SIZE + 2), + + I2NPMessage (): buf (nullptr),len (I2NP_HEADER_SIZE + 2), offset(2), maxLen (0), from (nullptr) {}; // reserve 2 bytes for NTCP header - + // header accessors uint8_t * GetHeader () { return GetBuffer (); }; const uint8_t * GetHeader () const { return GetBuffer (); }; @@ -128,24 +128,24 @@ namespace tunnel uint64_t GetExpiration () const { return bufbe64toh (GetHeader () + I2NP_HEADER_EXPIRATION_OFFSET); }; void SetSize (uint16_t size) { htobe16buf (GetHeader () + I2NP_HEADER_SIZE_OFFSET, size); }; uint16_t GetSize () const { return bufbe16toh (GetHeader () + I2NP_HEADER_SIZE_OFFSET); }; - void UpdateSize () { SetSize (GetPayloadLength ()); }; + void UpdateSize () { SetSize (GetPayloadLength ()); }; void SetChks (uint8_t chks) { GetHeader ()[I2NP_HEADER_CHKS_OFFSET] = chks; }; - void UpdateChks () + void UpdateChks () { uint8_t hash[32]; SHA256(GetPayload (), GetPayloadLength (), hash); GetHeader ()[I2NP_HEADER_CHKS_OFFSET] = hash[0]; - } - + } + // payload uint8_t * GetPayload () { return GetBuffer () + I2NP_HEADER_SIZE; }; const uint8_t * GetPayload () const { return GetBuffer () + I2NP_HEADER_SIZE; }; uint8_t * GetBuffer () { return buf + offset; }; const uint8_t * GetBuffer () const { return buf + offset; }; - size_t GetLength () const { return len - offset; }; - size_t GetPayloadLength () const { return GetLength () - I2NP_HEADER_SIZE; }; - - void Align (size_t alignment) + size_t GetLength () const { return len - offset; }; + size_t GetPayloadLength () const { return GetLength () - I2NP_HEADER_SIZE; }; + + void Align (size_t alignment) { if (len + alignment > maxLen) return; size_t rem = ((size_t)GetBuffer ()) % alignment; @@ -153,7 +153,7 @@ namespace tunnel { offset += (alignment - rem); len += (alignment - rem); - } + } } size_t Concat (const uint8_t * buf1, size_t len1) @@ -171,10 +171,10 @@ namespace tunnel len = offset + other.GetLength (); from = other.from; return *this; - } - + } + // for SSU only - uint8_t * GetSSUHeader () { return buf + offset + I2NP_HEADER_SIZE - I2NP_SHORT_HEADER_SIZE; }; + uint8_t * GetSSUHeader () { return buf + offset + I2NP_HEADER_SIZE - I2NP_SHORT_HEADER_SIZE; }; void FromSSU (uint32_t msgID) // we have received SSU message and convert it to regular { const uint8_t * ssu = GetSSUHeader (); @@ -193,12 +193,12 @@ namespace tunnel htobe32buf (ssu + I2NP_SHORT_HEADER_EXPIRATION_OFFSET, bufbe64toh (header + I2NP_HEADER_EXPIRATION_OFFSET)/1000LL); len = offset + I2NP_SHORT_HEADER_SIZE + bufbe16toh (header + I2NP_HEADER_SIZE_OFFSET); return bufbe32toh (header + I2NP_HEADER_MSGID_OFFSET); - } + } void FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID = 0); void RenewI2NPMessageHeader (); bool IsExpired () const; - }; + }; template struct I2NPMessageBuffer: public I2NPMessage @@ -211,35 +211,35 @@ namespace tunnel std::shared_ptr NewI2NPShortMessage (); std::shared_ptr NewI2NPTunnelMessage (); std::shared_ptr NewI2NPMessage (size_t len); - - std::shared_ptr CreateI2NPMessage (I2NPMessageType msgType, const uint8_t * buf, size_t len, uint32_t replyMsgID = 0); + + std::shared_ptr CreateI2NPMessage (I2NPMessageType msgType, const uint8_t * buf, size_t len, uint32_t replyMsgID = 0); std::shared_ptr CreateI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from = nullptr); std::shared_ptr CopyI2NPMessage (std::shared_ptr msg); std::shared_ptr CreateDeliveryStatusMsg (uint32_t msgID); - std::shared_ptr CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from, + std::shared_ptr CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from, uint32_t replyTunnelID, bool exploratory = false, std::set * excludedPeers = nullptr); - std::shared_ptr CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest, + std::shared_ptr CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest, const std::set& excludedFloodfills, std::shared_ptr replyTunnel, const uint8_t * replyKey, const uint8_t * replyTag); std::shared_ptr CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, std::vector routers); - + std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr router = nullptr, uint32_t replyToken = 0); std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet); // for floodfill only - std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet, uint32_t replyToken = 0, std::shared_ptr replyTunnel = nullptr); - bool IsRouterInfoMsg (std::shared_ptr msg); + std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet, uint32_t replyToken = 0, std::shared_ptr replyTunnel = nullptr); + bool IsRouterInfoMsg (std::shared_ptr msg); bool HandleBuildRequestRecords (int num, uint8_t * records, uint8_t * clearText); void HandleVariableTunnelBuildMsg (uint32_t replyMsgID, uint8_t * buf, size_t len); void HandleVariableTunnelBuildReplyMsg (uint32_t replyMsgID, uint8_t * buf, size_t len); - void HandleTunnelBuildMsg (uint8_t * buf, size_t len); + void HandleTunnelBuildMsg (uint8_t * buf, size_t len); - std::shared_ptr CreateTunnelDataMsg (const uint8_t * buf); - std::shared_ptr CreateTunnelDataMsg (uint32_t tunnelID, const uint8_t * payload); + std::shared_ptr CreateTunnelDataMsg (const uint8_t * buf); + std::shared_ptr CreateTunnelDataMsg (uint32_t tunnelID, const uint8_t * payload); std::shared_ptr CreateEmptyTunnelDataMsg (); - + std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, const uint8_t * buf, size_t len); - std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, I2NPMessageType msgType, + std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, I2NPMessageType msgType, const uint8_t * buf, size_t len, uint32_t replyMsgID = 0); std::shared_ptr CreateTunnelGatewayMsg (uint32_t tunnelID, std::shared_ptr msg); @@ -254,7 +254,7 @@ namespace tunnel ~I2NPMessagesHandler (); void PutNextMessage (std::shared_ptr msg); void Flush (); - + private: std::vector > m_TunnelMsgs, m_TunnelGatewayMsgs; @@ -262,6 +262,6 @@ namespace tunnel const uint16_t DEFAULT_MAX_NUM_TRANSIT_TUNNELS = 2500; void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels); -} +} #endif diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index 23f32bc8..3fcd16ad 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -41,7 +41,7 @@ namespace data IdentityEx::IdentityEx(const uint8_t * publicKey, const uint8_t * signingKey, SigningKeyType type, CryptoKeyType cryptoType): m_IsVerifierCreated (false) - { + { memcpy (m_StandardIdentity.publicKey, publicKey, 256); // publicKey in awlays assumed 256 regardless actual size, padding must be taken care of if (type != SIGNING_KEY_TYPE_DSA_SHA1) { @@ -450,7 +450,7 @@ namespace data std::shared_ptr IdentityEx::CreateEncryptor (const uint8_t * key) const { - if (!key) key = GetEncryptionPublicKey (); // use publicKey + if (!key) key = GetEncryptionPublicKey (); // use publicKey switch (GetCryptoKeyType ()) { case CRYPTO_KEY_TYPE_ELGAMAL: @@ -542,7 +542,7 @@ namespace data void PrivateKeys::Sign (const uint8_t * buf, int len, uint8_t * signature) const { if (!m_Signer) - CreateSigner(); + CreateSigner(); m_Signer->Sign (buf, len, signature); } @@ -596,12 +596,12 @@ namespace data std::shared_ptr PrivateKeys::CreateDecryptor (const uint8_t * key) const { - if (!key) key = m_PrivateKey; // use privateKey + if (!key) key = m_PrivateKey; // use privateKey return CreateDecryptor (m_Public->GetCryptoKeyType (), key); } std::shared_ptr PrivateKeys::CreateDecryptor (CryptoKeyType cryptoType, const uint8_t * key) - { + { if (!key) return nullptr; switch (cryptoType) { @@ -618,7 +618,7 @@ namespace data default: LogPrint (eLogError, "Identity: Unknown crypto key type ", (int)cryptoType); }; - return nullptr; + return nullptr; } PrivateKeys PrivateKeys::CreateRandomKeys (SigningKeyType type, CryptoKeyType cryptoType) @@ -643,7 +643,7 @@ namespace data case SIGNING_KEY_TYPE_RSA_SHA384_3072: case SIGNING_KEY_TYPE_RSA_SHA512_4096: LogPrint (eLogWarning, "Identity: RSA signature type is not supported. Create EdDSA"); - // no break here + // no break here case SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519: i2p::crypto::CreateEDDSA25519RandomKeys (keys.m_SigningPrivateKey, signingPublicKey); break; @@ -685,7 +685,7 @@ namespace data break; default: LogPrint (eLogError, "Identity: Crypto key type ", (int)type, " is not supported"); - } + } } Keys CreateRandomKeys () diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index 53ab4a7c..584e6475 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -91,12 +91,12 @@ namespace data size_t ToBuffer (uint8_t * buf, size_t len) const; size_t FromBase64(const std::string& s); std::string ToBase64 () const; - const Identity& GetStandardIdentity () const { return m_StandardIdentity; }; + const Identity& GetStandardIdentity () const { return m_StandardIdentity; }; const IdentHash& GetIdentHash () const { return m_IdentHash; }; - const uint8_t * GetEncryptionPublicKey () const { return m_StandardIdentity.publicKey; }; - uint8_t * GetEncryptionPublicKeyBuffer () { return m_StandardIdentity.publicKey; }; - std::shared_ptr CreateEncryptor (const uint8_t * key) const; + const uint8_t * GetEncryptionPublicKey () const { return m_StandardIdentity.publicKey; }; + uint8_t * GetEncryptionPublicKeyBuffer () { return m_StandardIdentity.publicKey; }; + std::shared_ptr CreateEncryptor (const uint8_t * key) const; size_t GetFullLen () const { return m_ExtendedLen + DEFAULT_IDENTITY_SIZE; }; size_t GetSigningPublicKeyLen () const; size_t GetSigningPrivateKeyLen () const; @@ -141,7 +141,7 @@ namespace data const uint8_t * GetPrivateKey () const { return m_PrivateKey; }; const uint8_t * GetSigningPrivateKey () const { return m_SigningPrivateKey; }; uint8_t * GetPadding(); - void RecalculateIdentHash(uint8_t * buf=nullptr) { m_Public->RecalculateIdentHash(buf); } + void RecalculateIdentHash(uint8_t * buf=nullptr) { m_Public->RecalculateIdentHash(buf); } void Sign (const uint8_t * buf, int len, uint8_t * signature) const; size_t GetFullLen () const { return m_Public->GetFullLen () + 256 + m_Public->GetSigningPrivateKeyLen (); }; diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index d2709a97..d1a70ba5 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -11,7 +11,7 @@ namespace i2p { namespace data { - + LeaseSet::LeaseSet (const uint8_t * buf, size_t len, bool storeLeases): m_IsValid (true), m_StoreLeases (storeLeases), m_ExpirationTime (0) { @@ -22,13 +22,13 @@ namespace data } void LeaseSet::Update (const uint8_t * buf, size_t len) - { + { if (len > m_BufferLen) { auto oldBuffer = m_Buffer; m_Buffer = new uint8_t[len]; delete[] oldBuffer; - } + } memcpy (m_Buffer, buf, len); m_BufferLen = len; ReadFromBuffer (false); @@ -38,10 +38,10 @@ namespace data { m_StoreLeases = true; ReadFromBuffer (false); - } - - void LeaseSet::ReadFromBuffer (bool readIdentity) - { + } + + void LeaseSet::ReadFromBuffer (bool readIdentity) + { if (readIdentity || !m_Identity) m_Identity = std::make_shared(m_Buffer, m_BufferLen); size_t size = m_Identity->GetFullLen (); @@ -58,17 +58,17 @@ namespace data size++; // num LogPrint (eLogDebug, "LeaseSet: read num=", (int)num); if (!num || num > MAX_NUM_LEASES) - { + { LogPrint (eLogError, "LeaseSet: incorrect number of leases", (int)num); m_IsValid = false; return; - } + } // reset existing leases if (m_StoreLeases) for (auto& it: m_Leases) it->isUpdated = false; - else + else m_Leases.clear (); // process leases @@ -82,14 +82,14 @@ namespace data leases += 32; // gateway lease.tunnelID = bufbe32toh (leases); leases += 4; // tunnel ID - lease.endDate = bufbe64toh (leases); + lease.endDate = bufbe64toh (leases); leases += 8; // end date if (ts < lease.endDate + LEASE_ENDDATE_THRESHOLD) - { + { if (lease.endDate > m_ExpirationTime) m_ExpirationTime = lease.endDate; if (m_StoreLeases) - { + { auto ret = m_Leases.insert (std::make_shared(lease)); if (!ret.second) (*ret.first)->endDate = lease.endDate; // update existing (*ret.first)->isUpdated = true; @@ -100,28 +100,28 @@ namespace data LogPrint (eLogInfo, "LeaseSet: Lease's tunnel gateway not found, requesting"); netdb.RequestDestination (lease.tunnelGateway); } - } + } } else LogPrint (eLogWarning, "LeaseSet: Lease is expired already "); - } + } if (!m_ExpirationTime) { LogPrint (eLogWarning, "LeaseSet: all leases are expired. Dropped"); m_IsValid = false; return; - } + } m_ExpirationTime += LEASE_ENDDATE_THRESHOLD; - // delete old leases + // delete old leases if (m_StoreLeases) - { + { for (auto it = m_Leases.begin (); it != m_Leases.end ();) - { + { if (!(*it)->isUpdated) { (*it)->endDate = 0; // somebody might still hold it m_Leases.erase (it++); - } + } else ++it; } @@ -133,9 +133,9 @@ namespace data LogPrint (eLogWarning, "LeaseSet: verification failed"); m_IsValid = false; } - } + } - uint64_t LeaseSet::ExtractTimestamp (const uint8_t * buf, size_t len) const + uint64_t LeaseSet::ExtractTimestamp (const uint8_t * buf, size_t len) const { if (!m_Identity) return 0; size_t size = m_Identity->GetFullLen (); @@ -150,18 +150,18 @@ namespace data for (int i = 0; i < num; i++) { size += 36; // gateway (32) + tunnelId(4) - auto endDate = bufbe64toh (buf + size); + auto endDate = bufbe64toh (buf + size); size += 8; // end date if (!timestamp || endDate < timestamp) timestamp = endDate; - } + } return timestamp; - } + } bool LeaseSet::IsNewer (const uint8_t * buf, size_t len) const { return ExtractTimestamp (buf, len) > ExtractTimestamp (m_Buffer, m_BufferLen); - } + } bool LeaseSet::ExpiresSoon(const uint64_t dlt, const uint64_t fudge) const { @@ -175,7 +175,7 @@ namespace data { return GetNonExpiredLeasesExcluding( [] (const Lease & l) -> bool { return false; }, withThreshold); } - + const std::vector > LeaseSet::GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold) const { auto ts = i2p::util::GetMillisecondsSinceEpoch (); @@ -189,17 +189,17 @@ namespace data endDate -= LEASE_ENDDATE_THRESHOLD; if (ts < endDate && !exclude(*it)) leases.push_back (it); - } - return leases; - } + } + return leases; + } bool LeaseSet::HasExpiredLeases () const - { + { auto ts = i2p::util::GetMillisecondsSinceEpoch (); for (const auto& it: m_Leases) if (ts >= it->endDate) return true; return false; - } + } bool LeaseSet::IsExpired () const { @@ -222,15 +222,15 @@ namespace data if (num > MAX_NUM_LEASES) num = MAX_NUM_LEASES; // identity auto signingKeyLen = m_Identity->GetSigningPublicKeyLen (); - m_BufferLen = m_Identity->GetFullLen () + 256 + signingKeyLen + 1 + num*LEASE_SIZE + m_Identity->GetSignatureLen (); - m_Buffer = new uint8_t[m_BufferLen]; + m_BufferLen = m_Identity->GetFullLen () + 256 + signingKeyLen + 1 + num*LEASE_SIZE + m_Identity->GetSignatureLen (); + m_Buffer = new uint8_t[m_BufferLen]; auto offset = m_Identity->ToBuffer (m_Buffer, m_BufferLen); memcpy (m_Buffer + offset, encryptionPublicKey, 256); offset += 256; memset (m_Buffer + offset, 0, signingKeyLen); offset += signingKeyLen; // num leases - m_Buffer[offset] = num; + m_Buffer[offset] = num; offset++; // leases m_Leases = m_Buffer + offset; @@ -257,13 +257,13 @@ namespace data { m_BufferLen = len; m_Buffer = new uint8_t[m_BufferLen]; - memcpy (m_Buffer, buf, len); + memcpy (m_Buffer, buf, len); } bool LocalLeaseSet::IsExpired () const { auto ts = i2p::util::GetMillisecondsSinceEpoch (); return ts > m_ExpirationTime; - } -} -} + } +} +} diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 5a4202ee..c7d2066e 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -14,11 +14,11 @@ namespace i2p namespace tunnel { - class InboundTunnel; + class InboundTunnel; } namespace data -{ +{ const int LEASE_ENDDATE_THRESHOLD = 51000; // in milliseconds struct Lease { @@ -33,24 +33,24 @@ namespace data if (endDate < expire) return true; return (endDate - expire) < t; } - }; + }; struct LeaseCmp { bool operator() (std::shared_ptr l1, std::shared_ptr l2) const - { + { if (l1->tunnelID != l2->tunnelID) - return l1->tunnelID < l2->tunnelID; + return l1->tunnelID < l2->tunnelID; else - return l1->tunnelGateway < l2->tunnelGateway; + return l1->tunnelGateway < l2->tunnelGateway; }; - }; + }; typedef std::function LeaseInspectFunc; - + const size_t MAX_LS_BUFFER_SIZE = 3072; const size_t LEASE_SIZE = 44; // 32 + 4 + 8 - const uint8_t MAX_NUM_LEASES = 16; + const uint8_t MAX_NUM_LEASES = 16; class LeaseSet: public RoutingDestination { public: @@ -59,10 +59,10 @@ namespace data ~LeaseSet () { delete[] m_Buffer; }; void Update (const uint8_t * buf, size_t len); bool IsNewer (const uint8_t * buf, size_t len) const; - void PopulateLeases (); // from buffer + void PopulateLeases (); // from buffer const uint8_t * GetBuffer () const { return m_Buffer; }; - size_t GetBufferLen () const { return m_BufferLen; }; + size_t GetBufferLen () const { return m_BufferLen; }; bool IsValid () const { return m_IsValid; }; const std::vector > GetNonExpiredLeases (bool withThreshold = true) const; const std::vector > GetNonExpiredLeasesExcluding (LeaseInspectFunc exclude, bool withThreshold = true) const; @@ -71,8 +71,8 @@ namespace data bool IsEmpty () const { return m_Leases.empty (); }; uint64_t GetExpirationTime () const { return m_ExpirationTime; }; bool ExpiresSoon(const uint64_t dlt=1000 * 5, const uint64_t fudge = 0) const ; - bool operator== (const LeaseSet& other) const - { return m_BufferLen == other.m_BufferLen && !memcmp (m_Buffer, other.m_Buffer, m_BufferLen); }; + bool operator== (const LeaseSet& other) const + { return m_BufferLen == other.m_BufferLen && !memcmp (m_Buffer, other.m_Buffer, m_BufferLen); }; // implements RoutingDestination std::shared_ptr GetIdentity () const { return m_Identity; }; @@ -83,7 +83,7 @@ namespace data void ReadFromBuffer (bool readIdentity = true); uint64_t ExtractTimestamp (const uint8_t * buf, size_t len) const; // min expiration time - + private: bool m_IsValid, m_StoreLeases; // we don't need to store leases for floodfill @@ -93,7 +93,7 @@ namespace data uint8_t m_EncryptionKey[256]; uint8_t * m_Buffer; size_t m_BufferLen; - }; + }; class LocalLeaseSet { @@ -104,27 +104,27 @@ namespace data ~LocalLeaseSet () { delete[] m_Buffer; }; const uint8_t * GetBuffer () const { return m_Buffer; }; - uint8_t * GetSignature () { return m_Buffer + m_BufferLen - GetSignatureLen (); }; - size_t GetBufferLen () const { return m_BufferLen; }; + uint8_t * GetSignature () { return m_Buffer + m_BufferLen - GetSignatureLen (); }; + size_t GetBufferLen () const { return m_BufferLen; }; size_t GetSignatureLen () const { return m_Identity->GetSignatureLen (); }; - uint8_t * GetLeases () { return m_Leases; }; - + uint8_t * GetLeases () { return m_Leases; }; + const IdentHash& GetIdentHash () const { return m_Identity->GetIdentHash (); }; bool IsExpired () const; uint64_t GetExpirationTime () const { return m_ExpirationTime; }; void SetExpirationTime (uint64_t expirationTime) { m_ExpirationTime = expirationTime; }; - bool operator== (const LeaseSet& other) const - { return m_BufferLen == other.GetBufferLen () && !memcmp (other.GetBuffer (), other.GetBuffer (), m_BufferLen); }; + bool operator== (const LeaseSet& other) const + { return m_BufferLen == other.GetBufferLen () && !memcmp (other.GetBuffer (), other.GetBuffer (), m_BufferLen); }; private: - + uint64_t m_ExpirationTime; // in milliseconds std::shared_ptr m_Identity; uint8_t * m_Buffer, * m_Leases; size_t m_BufferLen; - }; -} -} + }; +} +} #endif diff --git a/libi2pd/Log.h b/libi2pd/Log.h index 74b4dc01..b11c6763 100644 --- a/libi2pd/Log.h +++ b/libi2pd/Log.h @@ -44,7 +44,7 @@ enum LogType { namespace i2p { namespace log { - + struct LogMsg; /* forward declaration */ class Log @@ -146,7 +146,7 @@ namespace log { std::string text; /**< message text as single string */ LogLevel level; /**< message level */ std::thread::id tid; /**< id of thread that generated message */ - + LogMsg (LogLevel lvl, std::time_t ts, const std::string & txt): timestamp(ts), text(txt), level(lvl) {}; }; @@ -185,7 +185,7 @@ void LogPrint (LogLevel level, TArgs&&... args) noexcept std::stringstream ss(""); LogPrint (ss, std::forward(args)...); - + auto msg = std::make_shared(level, std::time(nullptr), ss.str()); msg->tid = std::this_thread::get_id(); log.Append(msg); diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 47baaac7..0215c570 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -22,18 +22,18 @@ using namespace i2p::transport; namespace i2p { namespace data -{ +{ NetDb netdb; NetDb::NetDb (): m_IsRunning (false), m_Thread (nullptr), m_Reseeder (nullptr), m_Storage("netDb", "r", "routerInfo-", "dat"), m_FloodfillBootstrap(nullptr), m_HiddenMode(false) { } - + NetDb::~NetDb () { - Stop (); + Stop (); delete m_Reseeder; - } + } void NetDb::Start () { @@ -50,46 +50,46 @@ namespace data m_IsRunning = true; m_Thread = new std::thread (std::bind (&NetDb::Run, this)); } - + void NetDb::Stop () { if (m_IsRunning) - { + { for (auto& it: m_RouterInfos) it.second->SaveProfile (); DeleteObsoleteProfiles (); m_RouterInfos.clear (); m_Floodfills.clear (); if (m_Thread) - { + { m_IsRunning = false; m_Queue.WakeUp (); - m_Thread->join (); + m_Thread->join (); delete m_Thread; m_Thread = 0; } m_LeaseSets.clear(); m_Requests.Stop (); } - } - + } + void NetDb::Run () { uint32_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0; while (m_IsRunning) - { + { try - { + { auto msg = m_Queue.GetNextWithTimeout (15000); // 15 sec if (msg) - { - int numMsgs = 0; + { + int numMsgs = 0; while (msg) { LogPrint(eLogDebug, "NetDb: got request with type ", (int) msg->GetTypeID ()); - switch (msg->GetTypeID ()) + switch (msg->GetTypeID ()) { - case eI2NPDatabaseStore: + case eI2NPDatabaseStore: HandleDatabaseStoreMsg (msg); break; case eI2NPDatabaseSearchReply: @@ -97,16 +97,16 @@ namespace data break; case eI2NPDatabaseLookup: HandleDatabaseLookupMsg (msg); - break; + break; default: // WTF? LogPrint (eLogError, "NetDb: unexpected message type ", (int) msg->GetTypeID ()); //i2p::HandleI2NPMessage (msg); - } + } if (numMsgs > 100) break; msg = m_Queue.Get (); numMsgs++; - } - } + } + } if (!m_IsRunning) break; uint64_t ts = i2p::util::GetSecondsSinceEpoch (); @@ -114,29 +114,29 @@ namespace data { m_Requests.ManageRequests (); lastManageRequest = ts; - } + } if (ts - lastSave >= 60) // save routers, manage leasesets and validate subscriptions every minute { if (lastSave) { SaveUpdated (); ManageLeaseSets (); - } + } lastSave = ts; } - if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT) + if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT) { i2p::context.CleanupDestination (); lastDestinationCleanup = ts; } - - if (ts - lastPublish >= NETDB_PUBLISH_INTERVAL && !m_HiddenMode) // publish + + if (ts - lastPublish >= NETDB_PUBLISH_INTERVAL && !m_HiddenMode) // publish { Publish (); lastPublish = ts; - } + } if (ts - lastExploratory >= 30) // exploratory every 30 seconds - { + { auto numRouters = m_RouterInfos.size (); if (numRouters == 0) { @@ -145,29 +145,29 @@ namespace data else // we have peers now m_FloodfillBootstrap = nullptr; if (numRouters < 2500 || ts - lastExploratory >= 90) - { + { numRouters = 800/numRouters; if (numRouters < 1) numRouters = 1; - if (numRouters > 9) numRouters = 9; + if (numRouters > 9) numRouters = 9; m_Requests.ManageRequests (); if(!m_HiddenMode) Explore (numRouters); lastExploratory = ts; - } - } + } + } } catch (std::exception& ex) { LogPrint (eLogError, "NetDb: runtime exception: ", ex.what ()); - } - } - } - + } + } + } + bool NetDb::AddRouterInfo (const uint8_t * buf, int len) { IdentityEx identity; if (identity.FromBuffer (buf, len)) - return AddRouterInfo (identity.GetIdentHash (), buf, len); + return AddRouterInfo (identity.GetIdentHash (), buf, len); return false; } @@ -175,10 +175,10 @@ namespace data // TODO: remove reachable addresses from router info m_HiddenMode = hide; } - + bool NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len) - { - bool updated = true; + { + bool updated = true; auto r = FindRouter (ident); if (r) { @@ -193,9 +193,9 @@ namespace data LogPrint (eLogDebug, "NetDb: RouterInfo is older: ", ident.ToBase64()); updated = false; } - } - else - { + } + else + { r = std::make_shared (buf, len); if (!r->IsUnreachable ()) { @@ -218,14 +218,14 @@ namespace data LogPrint (eLogWarning, "NetDb: Duplicated RouterInfo ", ident.ToBase64()); updated = false; } - } + } else updated = false; - } + } // take care about requested destination m_Requests.RequestComplete (ident, r); return updated; - } + } bool NetDb::AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, std::shared_ptr from) @@ -233,30 +233,30 @@ namespace data std::unique_lock lock(m_LeaseSetsMutex); bool updated = false; if (!from) // unsolicited LS must be received directly - { + { auto it = m_LeaseSets.find(ident); if (it != m_LeaseSets.end ()) { if (it->second->IsNewer (buf, len)) { - it->second->Update (buf, len); + it->second->Update (buf, len); if (it->second->IsValid ()) { LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); - updated = true; + updated = true; } else { LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase32()); m_LeaseSets.erase (it); - } + } } else LogPrint (eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase32()); } else - { - auto leaseSet = std::make_shared (buf, len, false); // we don't need leases in netdb + { + auto leaseSet = std::make_shared (buf, len, false); // we don't need leases in netdb if (leaseSet->IsValid ()) { LogPrint (eLogInfo, "NetDb: LeaseSet added: ", ident.ToBase32()); @@ -265,10 +265,10 @@ namespace data } else LogPrint (eLogError, "NetDb: new LeaseSet validation failed: ", ident.ToBase32()); - } - } + } + } return updated; - } + } std::shared_ptr NetDb::FindRouter (const IdentHash& ident) const { @@ -294,8 +294,8 @@ namespace data { auto router = FindRouter (ident); return router ? router->GetProfile () : nullptr; - } - + } + void NetDb::SetUnreachable (const IdentHash& ident, bool unreachable) { auto it = m_RouterInfos.find (ident); @@ -306,7 +306,7 @@ namespace data void NetDb::Reseed () { if (!m_Reseeder) - { + { m_Reseeder = new Reseeder (); m_Reseeder->LoadCertificates (); // we need certificates for SU3 verification } @@ -341,7 +341,7 @@ namespace data i2p::data::IdentHash ourIdent = i2p::context.GetIdentHash(); i2p::data::IdentHash ih = ri.GetIdentHash(); i2p::data::IdentHash randomIdent; - + // make floodfill lookups while(numFloodfills > 0) { randomIdent.Randomize(); @@ -349,7 +349,7 @@ namespace data requests.push_back(msg); numFloodfills --; } - + // make regular router lookups while(numRouters > 0) { randomIdent.Randomize(); @@ -357,7 +357,7 @@ namespace data requests.push_back(msg); numRouters --; } - + // send them off i2p::transport::transports.SendMessages(ih, requests); } @@ -373,8 +373,8 @@ namespace data m_RouterInfos[r->GetIdentHash ()] = r; if (r->IsFloodfill () && r->IsReachable ()) // floodfill must be reachable m_Floodfills.push_back (r); - } - else + } + else { LogPrint(eLogWarning, "NetDb: RI from ", path, " is invalid. Delete"); i2p::fs::Remove(path); @@ -449,12 +449,12 @@ namespace data } return visited; } - + void NetDb::Load () { // make sure we cleanup netDb from previous attempts - m_RouterInfos.clear (); - m_Floodfills.clear (); + m_RouterInfos.clear (); + m_Floodfills.clear (); m_LastLoad = i2p::util::GetSecondsSinceEpoch(); std::vector files; @@ -463,25 +463,25 @@ namespace data LoadRouterInfo(path); LogPrint (eLogInfo, "NetDb: ", m_RouterInfos.size(), " routers loaded (", m_Floodfills.size (), " floodfils)"); - } + } void NetDb::SaveUpdated () - { + { int updatedCount = 0, deletedCount = 0; auto total = m_RouterInfos.size (); - uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL; + uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL; uint64_t ts = i2p::util::GetMillisecondsSinceEpoch(); - // routers don't expire if less than 90 or uptime is less than 1 hour - bool checkForExpiration = total > NETDB_MIN_ROUTERS && ts > (i2p::context.GetStartupTime () + 600)*1000LL; // 10 minutes - if (checkForExpiration && ts > (i2p::context.GetStartupTime () + 3600)*1000LL) // 1 hour + // routers don't expire if less than 90 or uptime is less than 1 hour + bool checkForExpiration = total > NETDB_MIN_ROUTERS && ts > (i2p::context.GetStartupTime () + 600)*1000LL; // 10 minutes + if (checkForExpiration && ts > (i2p::context.GetStartupTime () + 3600)*1000LL) // 1 hour expirationTimeout = i2p::context.IsFloodfill () ? NETDB_FLOODFILL_EXPIRATION_TIMEOUT*1000LL : - NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total; + NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total; for (auto& it: m_RouterInfos) - { + { std::string ident = it.second->GetIdentHashBase64(); std::string path = m_Storage.Path(ident); - if (it.second->IsUpdated ()) + if (it.second->IsUpdated ()) { it.second->SaveToFile (path); it.second->SetUpdated (false); @@ -493,14 +493,14 @@ namespace data // find & mark expired routers if (it.second->UsesIntroducer ()) { - if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL) + if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL) // RouterInfo expires after 1 hour if uses introducer it.second->SetUnreachable (true); } - else if (checkForExpiration && ts > it.second->GetTimestamp () + expirationTimeout) + else if (checkForExpiration && ts > it.second->GetTimestamp () + expirationTimeout) it.second->SetUnreachable (true); - if (it.second->IsUnreachable ()) + if (it.second->IsUnreachable ()) { // delete RI file m_Storage.Remove(ident); @@ -508,7 +508,7 @@ namespace data if (total - deletedCount < NETDB_MIN_ROUTERS) checkForExpiration = false; } } // m_RouterInfos iteration - + if (updatedCount > 0) LogPrint (eLogInfo, "NetDb: saved ", updatedCount, " new/updated routers"); if (deletedCount > 0) @@ -519,15 +519,15 @@ namespace data std::unique_lock l(m_RouterInfosMutex); for (auto it = m_RouterInfos.begin (); it != m_RouterInfos.end ();) { - if (it->second->IsUnreachable ()) + if (it->second->IsUnreachable ()) { it->second->SaveProfile (); it = m_RouterInfos.erase (it); continue; - } + } ++it; } - } + } // clean up expired floodfiils { std::unique_lock l(m_FloodfillsMutex); @@ -536,7 +536,7 @@ namespace data it = m_Floodfills.erase (it); else ++it; - } + } } } @@ -546,49 +546,49 @@ namespace data if (!dest) { LogPrint (eLogWarning, "NetDb: destination ", destination.ToBase64(), " is requested already"); - return; + return; } auto floodfill = GetClosestFloodfill (destination, dest->GetExcludedPeers ()); if (floodfill) - transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ())); + transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ())); else { LogPrint (eLogError, "NetDb: ", destination.ToBase64(), " destination requested, but no floodfills found"); m_Requests.RequestComplete (destination, nullptr); - } - } + } + } void NetDb::RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete) { - + auto dest = m_Requests.CreateRequest (destination, exploritory, requestComplete); // non-exploratory if (!dest) { LogPrint (eLogWarning, "NetDb: destination ", destination.ToBase64(), " is requested already"); - return; + return; } LogPrint(eLogInfo, "NetDb: destination ", destination.ToBase64(), " being requested directly from ", from.ToBase64()); // direct - transports.SendMessage (from, dest->CreateRequestMessage (nullptr, nullptr)); - } - - + transports.SendMessage (from, dest->CreateRequestMessage (nullptr, nullptr)); + } + + void NetDb::HandleDatabaseStoreMsg (std::shared_ptr m) - { + { const uint8_t * buf = m->GetPayload (); - size_t len = m->GetSize (); + size_t len = m->GetSize (); IdentHash ident (buf + DATABASE_STORE_KEY_OFFSET); if (ident.IsZero ()) { LogPrint (eLogDebug, "NetDb: database store with zero ident, dropped"); return; - } + } uint32_t replyToken = bufbe32toh (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET); size_t offset = DATABASE_STORE_HEADER_SIZE; if (replyToken) { - auto deliveryStatus = CreateDeliveryStatusMsg (replyToken); + auto deliveryStatus = CreateDeliveryStatusMsg (replyToken); uint32_t tunnelID = bufbe32toh (buf + offset); offset += 4; if (!tunnelID) // send response directly @@ -601,23 +601,23 @@ namespace data outbound->SendTunnelDataMsg (buf + offset, tunnelID, deliveryStatus); else LogPrint (eLogWarning, "NetDb: no outbound tunnels for DatabaseStore reply found"); - } + } offset += 32; } - // we must send reply back before this check + // we must send reply back before this check if (ident == i2p::context.GetIdentHash ()) { LogPrint (eLogDebug, "NetDb: database store with own RouterInfo received, dropped"); return; } - size_t payloadOffset = offset; + size_t payloadOffset = offset; bool updated = false; if (buf[DATABASE_STORE_TYPE_OFFSET]) // type { LogPrint (eLogDebug, "NetDb: store request: LeaseSet for ", ident.ToBase32()); updated = AddLeaseSet (ident, buf + offset, len - offset, m->from); - } + } else { LogPrint (eLogDebug, "NetDb: store request: RouterInfo"); @@ -627,35 +627,35 @@ namespace data { LogPrint (eLogError, "NetDb: invalid RouterInfo length ", (int)size); return; - } + } uint8_t uncompressed[2048]; size_t uncompressedSize = m_Inflator.Inflate (buf + offset, size, uncompressed, 2048); if (uncompressedSize && uncompressedSize < 2048) updated = AddRouterInfo (ident, uncompressed, uncompressedSize); else - { + { LogPrint (eLogInfo, "NetDb: decompression failed ", uncompressedSize); return; - } - } + } + } if (replyToken && context.IsFloodfill () && updated) { // flood updated auto floodMsg = NewI2NPShortMessage (); - uint8_t * payload = floodMsg->GetPayload (); + uint8_t * payload = floodMsg->GetPayload (); memcpy (payload, buf, 33); // key + type htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); // zero reply token size_t msgLen = len - payloadOffset; floodMsg->len += DATABASE_STORE_HEADER_SIZE + msgLen; if (floodMsg->len < floodMsg->maxLen) - { + { memcpy (payload + DATABASE_STORE_HEADER_SIZE, buf + payloadOffset, msgLen); - floodMsg->FillI2NPMessageHeader (eI2NPDatabaseStore); + floodMsg->FillI2NPMessageHeader (eI2NPDatabaseStore); std::set excluded; excluded.insert (i2p::context.GetIdentHash ()); // don't flood to itself excluded.insert (ident); // don't flood back - for (int i = 0; i < 3; i++) + for (int i = 0; i < 3; i++) { auto floodfill = GetClosestFloodfill (ident, excluded); if (floodfill) @@ -667,12 +667,12 @@ namespace data } else break; - } - } + } + } else LogPrint (eLogError, "NetDb: Database store message is too long ", floodMsg->len); - } - } + } + } void NetDb::HandleDatabaseSearchReplyMsg (std::shared_ptr msg) { @@ -683,12 +683,12 @@ namespace data int num = buf[32]; // num LogPrint (eLogDebug, "NetDb: DatabaseSearchReply for ", key, " num=", num); IdentHash ident (buf); - auto dest = m_Requests.FindRequest (ident); + auto dest = m_Requests.FindRequest (ident); if (dest) - { + { bool deleteDest = true; if (num > 0) - { + { auto pool = i2p::tunnel::tunnels.GetExploratoryPool (); auto outbound = pool ? pool->GetNextOutboundTunnel () : nullptr; auto inbound = pool ? pool->GetNextInboundTunnel () : nullptr; @@ -700,36 +700,36 @@ namespace data std::vector msgs; auto count = dest->GetExcludedPeers ().size (); if (count < 7) - { + { auto nextFloodfill = GetClosestFloodfill (dest->GetDestination (), dest->GetExcludedPeers ()); if (nextFloodfill) - { - // tell floodfill about us - msgs.push_back (i2p::tunnel::TunnelMessageBlock - { + { + // tell floodfill about us + msgs.push_back (i2p::tunnel::TunnelMessageBlock + { i2p::tunnel::eDeliveryTypeRouter, nextFloodfill->GetIdentHash (), 0, - CreateDatabaseStoreMsg () - }); - + CreateDatabaseStoreMsg () + }); + // request destination LogPrint (eLogDebug, "NetDb: Try ", key, " at ", count, " floodfill ", nextFloodfill->GetIdentHash ().ToBase64 ()); auto msg = dest->CreateRequestMessage (nextFloodfill, inbound); - msgs.push_back (i2p::tunnel::TunnelMessageBlock - { + msgs.push_back (i2p::tunnel::TunnelMessageBlock + { i2p::tunnel::eDeliveryTypeRouter, nextFloodfill->GetIdentHash (), 0, msg }); deleteDest = false; - } + } } else LogPrint (eLogWarning, "NetDb: ", key, " was not found on ", count, " floodfills"); if (msgs.size () > 0) - outbound->SendTunnelDataMsg (msgs); - } - } + outbound->SendTunnelDataMsg (msgs); + } + } if (deleteDest) // no more requests for the destinationation. delete it @@ -751,9 +751,9 @@ namespace data peerHash[l1] = 0; LogPrint (eLogDebug, "NetDb: ", i, ": ", peerHash); - auto r = FindRouter (router); - if (!r || i2p::util::GetMillisecondsSinceEpoch () > r->GetTimestamp () + 3600*1000LL) - { + auto r = FindRouter (router); + if (!r || i2p::util::GetMillisecondsSinceEpoch () > r->GetTimestamp () + 3600*1000LL) + { // router with ident not found or too old (1 hour) LogPrint (eLogDebug, "NetDb: found new/outdated router. Requesting RouterInfo ..."); if(m_FloodfillBootstrap) @@ -763,9 +763,9 @@ namespace data } else LogPrint (eLogDebug, "NetDb: [:|||:]"); - } - } - + } + } + void NetDb::HandleDatabaseLookupMsg (std::shared_ptr msg) { const uint8_t * buf = msg->GetPayload (); @@ -774,7 +774,7 @@ namespace data { LogPrint (eLogError, "NetDb: DatabaseLookup for zero ident. Ignored"); return; - } + } char key[48]; int l = i2p::data::ByteStreamToBase64 (buf, 32, key, 48); key[l] = 0; @@ -782,24 +782,24 @@ namespace data IdentHash replyIdent(buf + 32); uint8_t flag = buf[64]; - + LogPrint (eLogDebug, "NetDb: DatabaseLookup for ", key, " received flags=", (int)flag); uint8_t lookupType = flag & DATABASE_LOOKUP_TYPE_FLAGS_MASK; - const uint8_t * excluded = buf + 65; + const uint8_t * excluded = buf + 65; uint32_t replyTunnelID = 0; if (flag & DATABASE_LOOKUP_DELIVERY_FLAG) //reply to tunnel { replyTunnelID = bufbe32toh (excluded); excluded += 4; } - uint16_t numExcluded = bufbe16toh (excluded); + uint16_t numExcluded = bufbe16toh (excluded); excluded += 2; if (numExcluded > 512) { LogPrint (eLogWarning, "NetDb: number of excluded peers", numExcluded, " exceeds 512"); return; - } - + } + std::shared_ptr replyMsg; if (lookupType == DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP) { @@ -809,34 +809,34 @@ namespace data { excludedRouters.insert (excluded); excluded += 32; - } + } std::vector routers; for (int i = 0; i < 3; i++) { auto r = GetClosestNonFloodfill (ident, excludedRouters); if (r) - { + { routers.push_back (r->GetIdentHash ()); excludedRouters.insert (r->GetIdentHash ()); - } - } + } + } replyMsg = CreateDatabaseSearchReply (ident, routers); - } + } else - { + { if (lookupType == DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP || lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP) - { + { auto router = FindRouter (ident); if (router) { LogPrint (eLogDebug, "NetDb: requested RouterInfo ", key, " found"); router->LoadBuffer (); - if (router->GetBuffer ()) + if (router->GetBuffer ()) replyMsg = CreateDatabaseStoreMsg (router); } } - + if (!replyMsg && (lookupType == DATABASE_LOOKUP_TYPE_LEASESET_LOOKUP || lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)) { @@ -852,9 +852,9 @@ namespace data replyMsg = CreateDatabaseStoreMsg (leaseSet); } } - + if (!replyMsg) - { + { std::set excludedRouters; const uint8_t * exclude_ident = excluded; for (int i = 0; i < numExcluded; i++) @@ -866,11 +866,11 @@ namespace data if (closestFloodfills.empty ()) LogPrint (eLogWarning, "NetDb: Requested ", key, " not found, ", numExcluded, " peers excluded"); replyMsg = CreateDatabaseSearchReply (ident, closestFloodfills); - } } - excluded += numExcluded * 32; + } + excluded += numExcluded * 32; if (replyMsg) - { + { if (replyTunnelID) { // encryption might be used though tunnel only @@ -887,7 +887,7 @@ namespace data } else LogPrint(eLogWarning, "NetDb: encrypted reply requested but no tags provided"); - } + } auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool (); auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr; if (outbound) @@ -898,124 +898,124 @@ namespace data else transports.SendMessage (replyIdent, replyMsg); } - } + } void NetDb::Explore (int numDestinations) - { + { // new requests auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool (); auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr; auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel () : nullptr; bool throughTunnels = outbound && inbound; - + uint8_t randomHash[32]; std::vector msgs; LogPrint (eLogInfo, "NetDb: exploring new ", numDestinations, " routers ..."); for (int i = 0; i < numDestinations; i++) - { + { RAND_bytes (randomHash, 32); auto dest = m_Requests.CreateRequest (randomHash, true); // exploratory if (!dest) - { + { LogPrint (eLogWarning, "NetDb: exploratory destination is requested already"); - return; - } + return; + } auto floodfill = GetClosestFloodfill (randomHash, dest->GetExcludedPeers ()); - if (floodfill) - { + if (floodfill) + { if (i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) throughTunnels = false; if (throughTunnels) - { - msgs.push_back (i2p::tunnel::TunnelMessageBlock - { + { + msgs.push_back (i2p::tunnel::TunnelMessageBlock + { i2p::tunnel::eDeliveryTypeRouter, floodfill->GetIdentHash (), 0, - CreateDatabaseStoreMsg () // tell floodfill about us - }); - msgs.push_back (i2p::tunnel::TunnelMessageBlock - { + CreateDatabaseStoreMsg () // tell floodfill about us + }); + msgs.push_back (i2p::tunnel::TunnelMessageBlock + { i2p::tunnel::eDeliveryTypeRouter, - floodfill->GetIdentHash (), 0, + floodfill->GetIdentHash (), 0, dest->CreateRequestMessage (floodfill, inbound) // explore - }); - } + }); + } else i2p::transport::transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ())); - } + } else m_Requests.RequestComplete (randomHash, nullptr); - } + } if (throughTunnels && msgs.size () > 0) - outbound->SendTunnelDataMsg (msgs); - } + outbound->SendTunnelDataMsg (msgs); + } void NetDb::Publish () { i2p::context.UpdateStats (); // for floodfill std::set excluded; // TODO: fill up later for (int i = 0; i < 2; i++) - { + { auto floodfill = GetClosestFloodfill (i2p::context.GetRouterInfo ().GetIdentHash (), excluded); if (floodfill) { uint32_t replyToken; RAND_bytes ((uint8_t *)&replyToken, 4); LogPrint (eLogInfo, "NetDb: Publishing our RouterInfo to ", i2p::data::GetIdentHashAbbreviation(floodfill->GetIdentHash ()), ". reply token=", replyToken); - transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken)); + transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken)); excluded.insert (floodfill->GetIdentHash ()); } - } - } + } + } std::shared_ptr NetDb::GetRandomRouter () const { return GetRandomRouter ( - [](std::shared_ptr router)->bool - { - return !router->IsHidden (); + [](std::shared_ptr router)->bool + { + return !router->IsHidden (); }); - } - + } + std::shared_ptr NetDb::GetRandomRouter (std::shared_ptr compatibleWith) const { return GetRandomRouter ( - [compatibleWith](std::shared_ptr router)->bool - { - return !router->IsHidden () && router != compatibleWith && - router->IsCompatible (*compatibleWith); + [compatibleWith](std::shared_ptr router)->bool + { + return !router->IsHidden () && router != compatibleWith && + router->IsCompatible (*compatibleWith); }); - } + } std::shared_ptr NetDb::GetRandomPeerTestRouter (bool v4only) const { return GetRandomRouter ( - [v4only](std::shared_ptr router)->bool - { - return !router->IsHidden () && router->IsPeerTesting () && router->IsSSU (v4only); + [v4only](std::shared_ptr router)->bool + { + return !router->IsHidden () && router->IsPeerTesting () && router->IsSSU (v4only); }); } std::shared_ptr NetDb::GetRandomIntroducer () const { return GetRandomRouter ( - [](std::shared_ptr router)->bool - { - return !router->IsHidden () && router->IsIntroducer (); + [](std::shared_ptr router)->bool + { + return !router->IsHidden () && router->IsIntroducer (); }); - } - + } + std::shared_ptr NetDb::GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith) const { return GetRandomRouter ( - [compatibleWith](std::shared_ptr router)->bool - { + [compatibleWith](std::shared_ptr router)->bool + { return !router->IsHidden () && router != compatibleWith && - router->IsCompatible (*compatibleWith) && + router->IsCompatible (*compatibleWith) && (router->GetCaps () & RouterInfo::eHighBandwidth); }); - } - + } + template std::shared_ptr NetDb::GetRandomRouter (Filter filter) const { @@ -1023,31 +1023,31 @@ namespace data return 0; uint32_t ind = rand () % m_RouterInfos.size (); for (int j = 0; j < 2; j++) - { + { uint32_t i = 0; std::unique_lock l(m_RouterInfosMutex); for (const auto& it: m_RouterInfos) - { + { if (i >= ind) - { + { if (!it.second->IsUnreachable () && filter (it.second)) return it.second; - } - else + } + else i++; } // we couldn't find anything, try second pass ind = 0; - } + } return nullptr; // seems we have too few routers - } - + } + void NetDb::PostI2NPMsg (std::shared_ptr msg) { - if (msg) m_Queue.Put (msg); - } + if (msg) m_Queue.Put (msg); + } - std::shared_ptr NetDb::GetClosestFloodfill (const IdentHash& destination, + std::shared_ptr NetDb::GetClosestFloodfill (const IdentHash& destination, const std::set& excluded, bool closeThanUsOnly) const { std::shared_ptr r; @@ -1055,23 +1055,23 @@ namespace data IdentHash destKey = CreateRoutingKey (destination); if (closeThanUsOnly) minMetric = destKey ^ i2p::context.GetIdentHash (); - else + else minMetric.SetMax (); std::unique_lock l(m_FloodfillsMutex); for (const auto& it: m_Floodfills) - { + { if (!it->IsUnreachable ()) - { + { XORMetric m = destKey ^ it->GetIdentHash (); if (m < minMetric && !excluded.count (it->GetIdentHash ())) { minMetric = m; r = it; } - } - } + } + } return r; - } + } std::vector NetDb::GetClosestFloodfills (const IdentHash& destination, size_t num, std::set& excluded, bool closeThanUsOnly) const @@ -1092,7 +1092,7 @@ namespace data for (const auto& it: m_Floodfills) { if (!it->IsUnreachable ()) - { + { XORMetric m = destKey ^ it->GetIdentHash (); if (closeThanUsOnly && ourMetric < m) continue; if (sorted.size () < num) @@ -1106,22 +1106,22 @@ namespace data } } - std::vector res; - size_t i = 0; + std::vector res; + size_t i = 0; for (const auto& it: sorted) { if (i < num) { const auto& ident = it.r->GetIdentHash (); if (!excluded.count (ident)) - { + { res.push_back (ident); i++; } } else break; - } + } return res; } @@ -1132,8 +1132,8 @@ namespace data return router->IsFamily(fam); }); } - - std::shared_ptr NetDb::GetClosestNonFloodfill (const IdentHash& destination, + + std::shared_ptr NetDb::GetClosestNonFloodfill (const IdentHash& destination, const std::set& excluded) const { std::shared_ptr r; @@ -1142,31 +1142,31 @@ namespace data minMetric.SetMax (); // must be called from NetDb thread only for (const auto& it: m_RouterInfos) - { + { if (!it.second->IsFloodfill ()) - { + { XORMetric m = destKey ^ it.first; if (m < minMetric && !excluded.count (it.first)) { minMetric = m; r = it.second; } - } - } + } + } return r; - } - + } + void NetDb::ManageLeaseSets () { auto ts = i2p::util::GetMillisecondsSinceEpoch (); for (auto it = m_LeaseSets.begin (); it != m_LeaseSets.end ();) { - if (ts > it->second->GetExpirationTime () - LEASE_ENDDATE_THRESHOLD) + if (ts > it->second->GetExpirationTime () - LEASE_ENDDATE_THRESHOLD) { LogPrint (eLogInfo, "NetDb: LeaseSet ", it->second->GetIdentHash ().ToBase64 (), " expired"); it = m_LeaseSets.erase (it); - } - else + } + else ++it; } } diff --git a/libi2pd/NetDb.hpp b/libi2pd/NetDb.hpp index a5cec84f..18377b4f 100644 --- a/libi2pd/NetDb.hpp +++ b/libi2pd/NetDb.hpp @@ -25,7 +25,7 @@ namespace i2p { namespace data -{ +{ const int NETDB_MIN_ROUTERS = 90; const int NETDB_FLOODFILL_EXPIRATION_TIMEOUT = 60*60; // 1 hour, in seconds const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65*60; @@ -37,11 +37,11 @@ namespace data typedef std::function)> LeaseSetVisitor; /** function for visiting a router info we have locally */ - typedef std::function)> RouterInfoVisitor; + typedef std::function)> RouterInfoVisitor; /** function for visiting a router info and determining if we want to use it */ typedef std::function)> RouterInfoFilter; - + class NetDb { public: @@ -51,7 +51,7 @@ namespace data void Start (); void Stop (); - + bool AddRouterInfo (const uint8_t * buf, int len); bool AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len); bool AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, std::shared_ptr from); @@ -59,12 +59,12 @@ namespace data std::shared_ptr FindLeaseSet (const IdentHash& destination) const; std::shared_ptr FindRouterProfile (const IdentHash& ident) const; - void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr); - void RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete = nullptr); - + void RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete = nullptr); + void RequestDestinationFrom (const IdentHash& destination, const IdentHash & from, bool exploritory, RequestedDestination::RequestComplete requestComplete = nullptr); + void HandleDatabaseStoreMsg (std::shared_ptr msg); void HandleDatabaseSearchReplyMsg (std::shared_ptr msg); - void HandleDatabaseLookupMsg (std::shared_ptr msg); + void HandleDatabaseLookupMsg (std::shared_ptr msg); std::shared_ptr GetRandomRouter () const; std::shared_ptr GetRandomRouter (std::shared_ptr compatibleWith) const; @@ -76,13 +76,13 @@ namespace data std::set& excluded, bool closeThanUsOnly = false) const; std::shared_ptr GetClosestNonFloodfill (const IdentHash& destination, const std::set& excluded) const; std::shared_ptr GetRandomRouterInFamily(const std::string & fam) const; - void SetUnreachable (const IdentHash& ident, bool unreachable); + void SetUnreachable (const IdentHash& ident, bool unreachable); void PostI2NPMsg (std::shared_ptr msg); /** set hidden mode, aka don't publish our RI to netdb and don't explore */ - void SetHidden(bool hide); - + void SetHidden(bool hide); + void Reseed (); Families& GetFamilies () { return m_Families; }; @@ -108,28 +108,28 @@ namespace data bool LoadRouterInfo (const std::string & path); void SaveUpdated (); void Run (); // exploratory thread - void Explore (int numDestinations); + void Explore (int numDestinations); void Publish (); void ManageLeaseSets (); void ManageRequests (); void ReseedFromFloodfill(const RouterInfo & ri, int numRouters=40, int numFloodfills=20); - + template - std::shared_ptr GetRandomRouter (Filter filter) const; - + std::shared_ptr GetRandomRouter (Filter filter) const; + private: - + mutable std::mutex m_LeaseSetsMutex; std::map > m_LeaseSets; mutable std::mutex m_RouterInfosMutex; std::map > m_RouterInfos; mutable std::mutex m_FloodfillsMutex; std::list > m_Floodfills; - + bool m_IsRunning; uint64_t m_LastLoad; - std::thread * m_Thread; + std::thread * m_Thread; i2p::util::Queue > m_Queue; // of I2NPDatabaseStoreMsg GzipInflator m_Inflator; @@ -137,12 +137,12 @@ namespace data Families m_Families; i2p::fs::HashedStorage m_Storage; - friend class NetDbRequests; + friend class NetDbRequests; NetDbRequests m_Requests; /** router info we are bootstrapping from or nullptr if we are not currently doing that*/ std::shared_ptr m_FloodfillBootstrap; - + /** true if in hidden mode */ bool m_HiddenMode; diff --git a/libi2pd/NetDbRequests.cpp b/libi2pd/NetDbRequests.cpp index 2fe2c229..f1853124 100644 --- a/libi2pd/NetDbRequests.cpp +++ b/libi2pd/NetDbRequests.cpp @@ -13,8 +13,8 @@ namespace data { std::shared_ptr msg; if(replyTunnel) - msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination, - replyTunnel->GetNextIdentHash (), replyTunnel->GetNextTunnelID (), m_IsExploratory, + msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination, + replyTunnel->GetNextIdentHash (), replyTunnel->GetNextTunnelID (), m_IsExploratory, &m_ExcludedPeers); else msg = i2p::CreateRouterInfoDatabaseLookupMsg(m_Destination, i2p::context.GetIdentHash(), 0, m_IsExploratory, &m_ExcludedPeers); @@ -22,22 +22,22 @@ namespace data m_ExcludedPeers.insert (router->GetIdentHash ()); m_CreationTime = i2p::util::GetSecondsSinceEpoch (); return msg; - } + } std::shared_ptr RequestedDestination::CreateRequestMessage (const IdentHash& floodfill) { - auto msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination, + auto msg = i2p::CreateRouterInfoDatabaseLookupMsg (m_Destination, i2p::context.GetRouterInfo ().GetIdentHash () , 0, false, &m_ExcludedPeers); m_ExcludedPeers.insert (floodfill); m_CreationTime = i2p::util::GetSecondsSinceEpoch (); return msg; - } + } void RequestedDestination::ClearExcludedPeers () { m_ExcludedPeers.clear (); - } - + } + void RequestedDestination::Success (std::shared_ptr r) { if (m_RequestComplete) @@ -69,15 +69,15 @@ namespace data std::shared_ptr NetDbRequests::CreateRequest (const IdentHash& destination, bool isExploratory, RequestedDestination::RequestComplete requestComplete) { // request RouterInfo directly - auto dest = std::make_shared (destination, isExploratory); + auto dest = std::make_shared (destination, isExploratory); dest->SetRequestComplete (requestComplete); { std::unique_lock l(m_RequestedDestinationsMutex); if (!m_RequestedDestinations.insert (std::make_pair (destination, dest)).second) // not inserted - return nullptr; + return nullptr; } return dest; - } + } void NetDbRequests::RequestComplete (const IdentHash& ident, std::shared_ptr r) { @@ -86,18 +86,18 @@ namespace data std::unique_lock l(m_RequestedDestinationsMutex); auto it = m_RequestedDestinations.find (ident); if (it != m_RequestedDestinations.end ()) - { + { request = it->second; m_RequestedDestinations.erase (it); - } - } + } + } if (request) { if (r) request->Success (r); else request->Fail (); - } + } } std::shared_ptr NetDbRequests::FindRequest (const IdentHash& ident) const @@ -107,12 +107,12 @@ namespace data if (it != m_RequestedDestinations.end ()) return it->second; return nullptr; - } + } void NetDbRequests::ManageRequests () { - uint64_t ts = i2p::util::GetSecondsSinceEpoch (); - std::unique_lock l(m_RequestedDestinationsMutex); + uint64_t ts = i2p::util::GetSecondsSinceEpoch (); + std::unique_lock l(m_RequestedDestinationsMutex); for (auto it = m_RequestedDestinations.begin (); it != m_RequestedDestinations.end ();) { auto& dest = it->second; @@ -126,7 +126,7 @@ namespace data { auto pool = i2p::tunnel::tunnels.GetExploratoryPool (); auto outbound = pool->GetNextOutboundTunnel (); - auto inbound = pool->GetNextInboundTunnel (); + auto inbound = pool->GetNextInboundTunnel (); auto nextFloodfill = netdb.GetClosestFloodfill (dest->GetDestination (), dest->GetExcludedPeers ()); if (nextFloodfill && outbound && inbound) outbound->SendTunnelDataMsg (nextFloodfill->GetIdentHash (), 0, @@ -138,15 +138,15 @@ namespace data if (!outbound) LogPrint (eLogWarning, "NetDbReq: No outbound tunnels"); if (!nextFloodfill) LogPrint (eLogWarning, "NetDbReq: No more floodfills"); } - } + } else { if (!dest->IsExploratory ()) LogPrint (eLogWarning, "NetDbReq: ", dest->GetDestination ().ToBase64 (), " not found after 7 attempts"); done = true; - } - } - } + } + } + } else // delete obsolete request done = true; @@ -154,7 +154,7 @@ namespace data it = m_RequestedDestinations.erase (it); else ++it; - } + } } } } diff --git a/libi2pd/NetDbRequests.h b/libi2pd/NetDbRequests.h index debf1273..7a7a55ab 100644 --- a/libi2pd/NetDbRequests.h +++ b/libi2pd/NetDbRequests.h @@ -12,14 +12,14 @@ namespace i2p namespace data { class RequestedDestination - { + { public: typedef std::function)> RequestComplete; RequestedDestination (const IdentHash& destination, bool isExploratory = false): m_Destination (destination), m_IsExploratory (isExploratory), m_CreationTime (0) {}; - ~RequestedDestination () { if (m_RequestComplete) m_RequestComplete (nullptr); }; + ~RequestedDestination () { if (m_RequestComplete) m_RequestComplete (nullptr); }; const IdentHash& GetDestination () const { return m_Destination; }; int GetNumExcludedPeers () const { return m_ExcludedPeers.size (); }; @@ -30,12 +30,12 @@ namespace data uint64_t GetCreationTime () const { return m_CreationTime; }; std::shared_ptr CreateRequestMessage (std::shared_ptr, std::shared_ptr replyTunnel); std::shared_ptr CreateRequestMessage (const IdentHash& floodfill); - + void SetRequestComplete (const RequestComplete& requestComplete) { m_RequestComplete = requestComplete; }; bool IsRequestComplete () const { return m_RequestComplete != nullptr; }; void Success (std::shared_ptr r); void Fail (); - + private: IdentHash m_Destination; @@ -43,7 +43,7 @@ namespace data std::set m_ExcludedPeers; uint64_t m_CreationTime; RequestComplete m_RequestComplete; - }; + }; class NetDbRequests { diff --git a/libi2pd/Profiling.cpp b/libi2pd/Profiling.cpp index 34e0681f..3840eb32 100644 --- a/libi2pd/Profiling.cpp +++ b/libi2pd/Profiling.cpp @@ -15,20 +15,20 @@ namespace data RouterProfile::RouterProfile (): m_LastUpdateTime (boost::posix_time::second_clock::local_time()), m_NumTunnelsAgreed (0), m_NumTunnelsDeclined (0), m_NumTunnelsNonReplied (0), - m_NumTimesTaken (0), m_NumTimesRejected (0) + m_NumTimesTaken (0), m_NumTimesRejected (0) { } boost::posix_time::ptime RouterProfile::GetTime () const { return boost::posix_time::second_clock::local_time(); - } - + } + void RouterProfile::UpdateTime () { m_LastUpdateTime = GetTime (); - } - + } + void RouterProfile::Save (const IdentHash& identHash) { // fill sections @@ -63,57 +63,57 @@ namespace data std::string path = m_ProfilesStorage.Path(ident); boost::property_tree::ptree pt; - if (!i2p::fs::Exists(path)) + if (!i2p::fs::Exists(path)) { LogPrint(eLogWarning, "Profiling: no profile yet for ", ident); return; } - try + try { boost::property_tree::read_ini (path, pt); - } catch (std::exception& ex) + } catch (std::exception& ex) { /* boost exception verbose enough */ LogPrint (eLogError, "Profiling: ", ex.what ()); return; } - try + try { auto t = pt.get (PEER_PROFILE_LAST_UPDATE_TIME, ""); if (t.length () > 0) m_LastUpdateTime = boost::posix_time::time_from_string (t); - if ((GetTime () - m_LastUpdateTime).hours () < PEER_PROFILE_EXPIRATION_TIMEOUT) + if ((GetTime () - m_LastUpdateTime).hours () < PEER_PROFILE_EXPIRATION_TIMEOUT) { - try - { + try + { // read participations auto participations = pt.get_child (PEER_PROFILE_SECTION_PARTICIPATION); m_NumTunnelsAgreed = participations.get (PEER_PROFILE_PARTICIPATION_AGREED, 0); m_NumTunnelsDeclined = participations.get (PEER_PROFILE_PARTICIPATION_DECLINED, 0); m_NumTunnelsNonReplied = participations.get (PEER_PROFILE_PARTICIPATION_NON_REPLIED, 0); - } - catch (boost::property_tree::ptree_bad_path& ex) + } + catch (boost::property_tree::ptree_bad_path& ex) { LogPrint (eLogWarning, "Profiling: Missing section ", PEER_PROFILE_SECTION_PARTICIPATION, " in profile for ", ident); - } - try + } + try { // read usage auto usage = pt.get_child (PEER_PROFILE_SECTION_USAGE); m_NumTimesTaken = usage.get (PEER_PROFILE_USAGE_TAKEN, 0); m_NumTimesRejected = usage.get (PEER_PROFILE_USAGE_REJECTED, 0); - } - catch (boost::property_tree::ptree_bad_path& ex) + } + catch (boost::property_tree::ptree_bad_path& ex) { LogPrint (eLogWarning, "Missing section ", PEER_PROFILE_SECTION_USAGE, " in profile for ", ident); } - } - else + } + else *this = RouterProfile (); - } - catch (std::exception& ex) + } + catch (std::exception& ex) { LogPrint (eLogError, "Profiling: Can't read profile ", ident, " :", ex.what ()); } @@ -126,46 +126,46 @@ namespace data m_NumTunnelsDeclined++; else m_NumTunnelsAgreed++; - } + } void RouterProfile::TunnelNonReplied () { m_NumTunnelsNonReplied++; UpdateTime (); - } + } bool RouterProfile::IsLowPartcipationRate () const { return 4*m_NumTunnelsAgreed < m_NumTunnelsDeclined; // < 20% rate - } + } bool RouterProfile::IsLowReplyRate () const { auto total = m_NumTunnelsAgreed + m_NumTunnelsDeclined; return m_NumTunnelsNonReplied > 10*(total + 1); - } - + } + bool RouterProfile::IsBad () - { + { auto isBad = IsAlwaysDeclining () || IsLowPartcipationRate () /*|| IsLowReplyRate ()*/; - if (isBad && m_NumTimesRejected > 10*(m_NumTimesTaken + 1)) + if (isBad && m_NumTimesRejected > 10*(m_NumTimesTaken + 1)) { // reset profile m_NumTunnelsAgreed = 0; m_NumTunnelsDeclined = 0; m_NumTunnelsNonReplied = 0; isBad = false; - } + } if (isBad) m_NumTimesRejected++; else m_NumTimesTaken++; - return isBad; + return isBad; } - + std::shared_ptr GetRouterProfile (const IdentHash& identHash) { auto profile = std::make_shared (); profile->Load (identHash); // if possible return profile; - } + } void InitProfilesStorage () { @@ -191,5 +191,5 @@ namespace data } } } -} -} +} +} diff --git a/libi2pd/Profiling.h b/libi2pd/Profiling.h index 34ed4f72..4ba6702f 100644 --- a/libi2pd/Profiling.h +++ b/libi2pd/Profiling.h @@ -8,32 +8,32 @@ namespace i2p { namespace data -{ +{ // sections const char PEER_PROFILE_SECTION_PARTICIPATION[] = "participation"; const char PEER_PROFILE_SECTION_USAGE[] = "usage"; - // params + // params const char PEER_PROFILE_LAST_UPDATE_TIME[] = "lastupdatetime"; const char PEER_PROFILE_PARTICIPATION_AGREED[] = "agreed"; const char PEER_PROFILE_PARTICIPATION_DECLINED[] = "declined"; - const char PEER_PROFILE_PARTICIPATION_NON_REPLIED[] = "nonreplied"; + const char PEER_PROFILE_PARTICIPATION_NON_REPLIED[] = "nonreplied"; const char PEER_PROFILE_USAGE_TAKEN[] = "taken"; const char PEER_PROFILE_USAGE_REJECTED[] = "rejected"; const int PEER_PROFILE_EXPIRATION_TIMEOUT = 72; // in hours (3 days) - + class RouterProfile { public: RouterProfile (); RouterProfile& operator= (const RouterProfile& ) = default; - + void Save (const IdentHash& identHash); void Load (const IdentHash& identHash); bool IsBad (); - + void TunnelBuildResponse (uint8_t ret); void TunnelNonReplied (); @@ -45,23 +45,23 @@ namespace data bool IsAlwaysDeclining () const { return !m_NumTunnelsAgreed && m_NumTunnelsDeclined >= 5; }; bool IsLowPartcipationRate () const; bool IsLowReplyRate () const; - - private: + + private: boost::posix_time::ptime m_LastUpdateTime; // participation uint32_t m_NumTunnelsAgreed; - uint32_t m_NumTunnelsDeclined; + uint32_t m_NumTunnelsDeclined; uint32_t m_NumTunnelsNonReplied; // usage uint32_t m_NumTimesTaken; - uint32_t m_NumTimesRejected; - }; + uint32_t m_NumTimesRejected; + }; - std::shared_ptr GetRouterProfile (const IdentHash& identHash); + std::shared_ptr GetRouterProfile (const IdentHash& identHash); void InitProfilesStorage (); void DeleteObsoleteProfiles (); -} -} +} +} #endif diff --git a/libi2pd/Queue.h b/libi2pd/Queue.h index 9e95b2a5..d701e4b8 100644 --- a/libi2pd/Queue.h +++ b/libi2pd/Queue.h @@ -15,7 +15,7 @@ namespace util { template class Queue - { + { public: void Put (Element e) @@ -29,14 +29,14 @@ namespace util void Put (const Container& vec) { if (!vec.empty ()) - { + { std::unique_lock l(m_QueueMutex); for (const auto& it: vec) - m_Queue.push (it); + m_Queue.push (it); m_NonEmpty.notify_one (); - } + } } - + Element GetNext () { std::unique_lock l(m_QueueMutex); @@ -45,7 +45,7 @@ namespace util { m_NonEmpty.wait (l); el = GetNonThreadSafe (); - } + } return el; } @@ -57,7 +57,7 @@ namespace util { m_NonEmpty.wait_for (l, std::chrono::milliseconds (usec)); el = GetNonThreadSafe (); - } + } return el; } @@ -73,17 +73,17 @@ namespace util return m_NonEmpty.wait_for (l, std::chrono::seconds (sec) + std::chrono::milliseconds (usec)) != std::cv_status::timeout; } - bool IsEmpty () - { + bool IsEmpty () + { std::unique_lock l(m_QueueMutex); return m_Queue.empty (); } - int GetSize () + int GetSize () { std::unique_lock l(m_QueueMutex); return m_Queue.size (); - } + } void WakeUp () { m_NonEmpty.notify_all (); }; @@ -91,14 +91,14 @@ namespace util { std::unique_lock l(m_QueueMutex); return GetNonThreadSafe (); - } + } Element Peek () { std::unique_lock l(m_QueueMutex); return GetNonThreadSafe (true); - } - + } + private: Element GetNonThreadSafe (bool peek = false) @@ -109,17 +109,17 @@ namespace util if (!peek) m_Queue.pop (); return el; - } + } return nullptr; - } - + } + private: std::queue m_Queue; std::mutex m_QueueMutex; std::condition_variable m_NonEmpty; - }; -} -} + }; +} +} #endif diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp index 12888cef..4a2f8055 100644 --- a/libi2pd/Reseed.cpp +++ b/libi2pd/Reseed.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include #include @@ -23,7 +23,7 @@ namespace i2p { namespace data { - + Reseeder::Reseeder() { } @@ -114,11 +114,11 @@ namespace data return 0; } } - + int Reseeder::ProcessSU3File (const char * filename) { std::ifstream s(filename, std::ifstream::binary); - if (s.is_open ()) + if (s.is_open ()) return ProcessSU3Stream (s); else { @@ -130,21 +130,21 @@ namespace data int Reseeder::ProcessZIPFile (const char * filename) { std::ifstream s(filename, std::ifstream::binary); - if (s.is_open ()) - { + if (s.is_open ()) + { s.seekg (0, std::ios::end); auto len = s.tellg (); s.seekg (0, std::ios::beg); return ProcessZIPStream (s, len); - } + } else { LogPrint (eLogError, "Reseed: Can't open file ", filename); return 0; } - } - - const char SU3_MAGIC_NUMBER[]="I2Psu3"; + } + + const char SU3_MAGIC_NUMBER[]="I2Psu3"; int Reseeder::ProcessSU3Stream (std::istream& s) { char magicNumber[7]; @@ -153,7 +153,7 @@ namespace data { LogPrint (eLogError, "Reseed: Unexpected SU3 magic number"); return 0; - } + } s.seekg (1, std::ios::cur); // su3 file format version SigningKeyType signatureType; s.read ((char *)&signatureType, 2); // signature type @@ -163,16 +163,16 @@ namespace data signatureLength = be16toh (signatureLength); s.seekg (1, std::ios::cur); // unused uint8_t versionLength; - s.read ((char *)&versionLength, 1); // version length + s.read ((char *)&versionLength, 1); // version length s.seekg (1, std::ios::cur); // unused uint8_t signerIDLength; - s.read ((char *)&signerIDLength, 1); // signer ID length + s.read ((char *)&signerIDLength, 1); // signer ID length uint64_t contentLength; - s.read ((char *)&contentLength, 8); // content length + s.read ((char *)&contentLength, 8); // content length contentLength = be64toh (contentLength); s.seekg (1, std::ios::cur); // unused uint8_t fileType; - s.read ((char *)&fileType, 1); // file type + s.read ((char *)&fileType, 1); // file type if (fileType != 0x00) // zip file { LogPrint (eLogError, "Reseed: Can't handle file type ", (int)fileType); @@ -180,7 +180,7 @@ namespace data } s.seekg (1, std::ios::cur); // unused uint8_t contentType; - s.read ((char *)&contentType, 1); // content type + s.read ((char *)&contentType, 1); // content type if (contentType != 0x03) // reseed data { LogPrint (eLogError, "Reseed: Unexpected content type ", (int)contentType); @@ -192,10 +192,10 @@ namespace data char signerID[256]; s.read (signerID, signerIDLength); // signerID signerID[signerIDLength] = 0; - + bool verify; i2p::config::GetOption("reseed.verify", verify); if (verify) - { + { //try to verify signature auto it = m_SigningKeys.find (signerID); if (it != m_SigningKeys.end ()) @@ -220,7 +220,7 @@ namespace data BIGNUM * s = BN_new (), * n = BN_new (); BN_bin2bn (signature, signatureLength, s); BN_bin2bn (it->second, i2p::crypto::RSASHA5124096_KEY_LENGTH, n); - BN_mod_exp (s, s, i2p::crypto::GetRSAE (), n, bnctx); // s = s^e mod n + BN_mod_exp (s, s, i2p::crypto::GetRSAE (), n, bnctx); // s = s^e mod n uint8_t * enSigBuf = new uint8_t[signatureLength]; i2p::crypto::bn2buf (s, enSigBuf, signatureLength); // digest is right aligned @@ -232,8 +232,8 @@ namespace data delete[] enSigBuf; BN_free (s); BN_free (n); BN_CTX_free (bnctx); - } - + } + delete[] signature; delete[] tbs; s.seekg (pos, std::ios::beg); @@ -249,21 +249,21 @@ namespace data { LogPrint (eLogError, "Reseed: SU3 verification failed"); return 0; - } + } // handle content return ProcessZIPStream (s, contentLength); } const uint32_t ZIP_HEADER_SIGNATURE = 0x04034B50; - const uint32_t ZIP_CENTRAL_DIRECTORY_HEADER_SIGNATURE = 0x02014B50; + const uint32_t ZIP_CENTRAL_DIRECTORY_HEADER_SIGNATURE = 0x02014B50; const uint16_t ZIP_BIT_FLAG_DATA_DESCRIPTOR = 0x0008; int Reseeder::ProcessZIPStream (std::istream& s, uint64_t contentLength) - { + { int numFiles = 0; size_t contentPos = s.tellg (); while (!s.eof ()) - { + { uint32_t signature; s.read ((char *)&signature, 4); signature = le32toh (signature); @@ -272,22 +272,22 @@ namespace data // next local file s.seekg (2, std::ios::cur); // version uint16_t bitFlag; - s.read ((char *)&bitFlag, 2); + s.read ((char *)&bitFlag, 2); bitFlag = le16toh (bitFlag); uint16_t compressionMethod; - s.read ((char *)&compressionMethod, 2); + s.read ((char *)&compressionMethod, 2); compressionMethod = le16toh (compressionMethod); s.seekg (4, std::ios::cur); // skip fields we don't care about - uint32_t compressedSize, uncompressedSize; + uint32_t compressedSize, uncompressedSize; uint32_t crc_32; s.read ((char *)&crc_32, 4); crc_32 = le32toh (crc_32); - s.read ((char *)&compressedSize, 4); - compressedSize = le32toh (compressedSize); + s.read ((char *)&compressedSize, 4); + compressedSize = le32toh (compressedSize); s.read ((char *)&uncompressedSize, 4); - uncompressedSize = le32toh (uncompressedSize); - uint16_t fileNameLength, extraFieldLength; - s.read ((char *)&fileNameLength, 2); + uncompressedSize = le32toh (uncompressedSize); + uint16_t fileNameLength, extraFieldLength; + s.read ((char *)&fileNameLength, 2); fileNameLength = le16toh (fileNameLength); if ( fileNameLength > 255 ) { // too big @@ -308,13 +308,13 @@ namespace data { LogPrint (eLogError, "Reseed: SU3 archive data descriptor not found"); return numFiles; - } - s.read ((char *)&crc_32, 4); + } + s.read ((char *)&crc_32, 4); crc_32 = le32toh (crc_32); - s.read ((char *)&compressedSize, 4); + s.read ((char *)&compressedSize, 4); compressedSize = le32toh (compressedSize) + 4; // ??? we must consider signature as part of compressed data s.read ((char *)&uncompressedSize, 4); - uncompressedSize = le32toh (uncompressedSize); + uncompressedSize = le32toh (uncompressedSize); // now we know compressed and uncompressed size s.seekg (pos, std::ios::beg); // back to compressed data @@ -325,8 +325,8 @@ namespace data { LogPrint (eLogWarning, "Reseed: Unexpected size 0. Skipped"); continue; - } - + } + uint8_t * compressed = new uint8_t[compressedSize]; s.read ((char *)compressed, compressedSize); if (compressionMethod) // we assume Deflate @@ -338,29 +338,29 @@ namespace data inflator.next_in = compressed; inflator.avail_in = compressedSize; inflator.next_out = uncompressed; - inflator.avail_out = uncompressedSize; + inflator.avail_out = uncompressedSize; int err; if ((err = inflate (&inflator, Z_SYNC_FLUSH)) >= 0) - { + { uncompressedSize -= inflator.avail_out; if (crc32 (0, uncompressed, uncompressedSize) == crc_32) { i2p::data::netdb.AddRouterInfo (uncompressed, uncompressedSize); numFiles++; - } + } else LogPrint (eLogError, "Reseed: CRC32 verification failed"); - } + } else LogPrint (eLogError, "Reseed: SU3 decompression error ", err); - delete[] uncompressed; + delete[] uncompressed; inflateEnd (&inflator); } else // no compression { i2p::data::netdb.AddRouterInfo (compressed, compressedSize); numFiles++; - } + } delete[] compressed; if (bitFlag & ZIP_BIT_FLAG_DATA_DESCRIPTOR) s.seekg (12, std::ios::cur); // skip data descriptor section if presented (12 = 16 - 4) @@ -406,15 +406,15 @@ namespace data return numFiles; } - const uint8_t ZIP_DATA_DESCRIPTOR_SIGNATURE[] = { 0x50, 0x4B, 0x07, 0x08 }; + const uint8_t ZIP_DATA_DESCRIPTOR_SIGNATURE[] = { 0x50, 0x4B, 0x07, 0x08 }; bool Reseeder::FindZipDataDescriptor (std::istream& s) { - size_t nextInd = 0; + size_t nextInd = 0; while (!s.eof ()) { uint8_t nextByte; s.read ((char *)&nextByte, 1); - if (nextByte == ZIP_DATA_DESCRIPTOR_SIGNATURE[nextInd]) + if (nextByte == ZIP_DATA_DESCRIPTOR_SIGNATURE[nextInd]) { nextInd++; if (nextInd >= sizeof (ZIP_DATA_DESCRIPTOR_SIGNATURE)) @@ -429,24 +429,24 @@ namespace data void Reseeder::LoadCertificate (const std::string& filename) { SSL_CTX * ctx = SSL_CTX_new (TLS_method ()); - int ret = SSL_CTX_use_certificate_file (ctx, filename.c_str (), SSL_FILETYPE_PEM); + int ret = SSL_CTX_use_certificate_file (ctx, filename.c_str (), SSL_FILETYPE_PEM); if (ret) - { + { SSL * ssl = SSL_new (ctx); X509 * cert = SSL_get_certificate (ssl); // verify if (cert) - { + { // extract issuer name char name[100]; X509_NAME_oneline (X509_get_issuer_name(cert), name, 100); char * cn = strstr (name, "CN="); if (cn) - { + { cn += 3; char * terminator = strchr (cn, '/'); if (terminator) terminator[0] = 0; - } + } // extract RSA key (we need n only, e = 65537) RSA * key = EVP_PKEY_get0_RSA (X509_get_pubkey (cert)); const BIGNUM * n, * e, * d; @@ -457,12 +457,12 @@ namespace data m_SigningKeys[cn] = value; else LogPrint (eLogError, "Reseed: Can't find CN field in ", filename); - } - SSL_free (ssl); - } + } + SSL_free (ssl); + } else LogPrint (eLogError, "Reseed: Can't open certificate file ", filename); - SSL_CTX_free (ctx); + SSL_CTX_free (ctx); } void Reseeder::LoadCertificates () @@ -483,9 +483,9 @@ namespace data } LoadCertificate (file); numCertificates++; - } + } LogPrint (eLogInfo, "Reseed: ", numCertificates, " certificates loaded"); - } + } std::string Reseeder::HttpsRequest (const std::string& address) { diff --git a/libi2pd/Reseed.h b/libi2pd/Reseed.h index 6b09f911..a69969bf 100644 --- a/libi2pd/Reseed.h +++ b/libi2pd/Reseed.h @@ -15,10 +15,10 @@ namespace data class Reseeder { - typedef Tag<512> PublicKey; - + typedef Tag<512> PublicKey; + public: - + Reseeder(); ~Reseeder(); void Bootstrap (); @@ -28,19 +28,19 @@ namespace data int ProcessZIPFile (const char * filename); void LoadCertificates (); - + private: void LoadCertificate (const std::string& filename); - - int ProcessSU3Stream (std::istream& s); - int ProcessZIPStream (std::istream& s, uint64_t contentLength); - + + int ProcessSU3Stream (std::istream& s); + int ProcessZIPStream (std::istream& s, uint64_t contentLength); + bool FindZipDataDescriptor (std::istream& s); - + std::string HttpsRequest (const std::string& address); - private: + private: std::map m_SigningKeys; }; diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 80a03abf..38fe3224 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -28,7 +28,7 @@ namespace i2p m_StartupTime = i2p::util::GetSecondsSinceEpoch (); if (!Load ()) CreateNewRouter (); - m_Decryptor = m_Keys.CreateDecryptor (nullptr); + m_Decryptor = m_Keys.CreateDecryptor (nullptr); UpdateRouterInfo (); } @@ -204,7 +204,7 @@ namespace i2p } } - void RouterContext::SetBandwidth (char L) + void RouterContext::SetBandwidth (char L) { uint32_t limit = 0; enum { low, high, extra, unlim } type = high; diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index f587e0a5..ef23af25 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -13,7 +13,7 @@ namespace i2p { const char ROUTER_INFO[] = "router.info"; - const char ROUTER_KEYS[] = "router.keys"; + const char ROUTER_KEYS[] = "router.keys"; const int ROUTER_INFO_UPDATE_INTERVAL = 1800; // 30 minutes enum RouterStatus @@ -21,16 +21,16 @@ namespace i2p eRouterStatusOK = 0, eRouterStatusTesting = 1, eRouterStatusFirewalled = 2, - eRouterStatusError = 3 - }; + eRouterStatusError = 3 + }; enum RouterError { eRouterErrorNone = 0, eRouterErrorClockSkew = 1 - }; - - class RouterContext: public i2p::garlic::GarlicDestination + }; + + class RouterContext: public i2p::garlic::GarlicDestination { public: @@ -39,17 +39,17 @@ namespace i2p const i2p::data::PrivateKeys& GetPrivateKeys () const { return m_Keys; }; i2p::data::RouterInfo& GetRouterInfo () { return m_RouterInfo; }; - std::shared_ptr GetSharedRouterInfo () const - { - return std::shared_ptr (&m_RouterInfo, + std::shared_ptr GetSharedRouterInfo () const + { + return std::shared_ptr (&m_RouterInfo, [](const i2p::data::RouterInfo *) {}); } - std::shared_ptr GetSharedDestination () + std::shared_ptr GetSharedDestination () { - return std::shared_ptr (this, + return std::shared_ptr (this, [](i2p::garlic::GarlicDestination *) {}); - } - + } + uint32_t GetUptime () const; uint32_t GetStartupTime () const { return m_StartupTime; }; uint64_t GetLastUpdateTime () const { return m_LastUpdateTime; }; @@ -60,17 +60,17 @@ namespace i2p RouterError GetError () const { return m_Error; }; void SetError (RouterError error) { m_Status = eRouterStatusError; m_Error = error; }; int GetNetID () const { return m_NetID; }; - void SetNetID (int netID) { m_NetID = netID; }; + void SetNetID (int netID) { m_NetID = netID; }; void UpdatePort (int port); // called from Daemon void UpdateAddress (const boost::asio::ip::address& host); // called from SSU or Daemon bool AddIntroducer (const i2p::data::RouterInfo::Introducer& introducer); void RemoveIntroducer (const boost::asio::ip::udp::endpoint& e); bool IsUnreachable () const; - void SetUnreachable (); + void SetUnreachable (); void SetReachable (); - bool IsFloodfill () const { return m_IsFloodfill; }; - void SetFloodfill (bool floodfill); + bool IsFloodfill () const { return m_IsFloodfill; }; + void SetFloodfill (bool floodfill); void SetFamily (const std::string& family); std::string GetFamily () const; void SetBandwidth (int limit); /* in kilobytes */ @@ -83,14 +83,14 @@ namespace i2p void SetSupportsV6 (bool supportsV6); void SetSupportsV4 (bool supportsV4); - void UpdateNTCPV6Address (const boost::asio::ip::address& host); // called from NTCP session - void UpdateStats (); + void UpdateNTCPV6Address (const boost::asio::ip::address& host); // called from NTCP session + void UpdateStats (); void CleanupDestination (); // garlic destination // implements LocalDestination std::shared_ptr GetIdentity () const { return m_Keys.GetPublic (); }; bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const; - void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); }; + void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); }; void SetLeaseSetUpdated () {}; // implements GarlicDestination @@ -100,8 +100,8 @@ namespace i2p // override GarlicDestination void ProcessGarlicMessage (std::shared_ptr msg); - void ProcessDeliveryStatusMessage (std::shared_ptr msg); - + void ProcessDeliveryStatusMessage (std::shared_ptr msg); + private: void CreateNewRouter (); @@ -109,11 +109,11 @@ namespace i2p void UpdateRouterInfo (); bool Load (); void SaveKeys (); - + private: i2p::data::RouterInfo m_RouterInfo; - i2p::data::PrivateKeys m_Keys; + i2p::data::PrivateKeys m_Keys; std::shared_ptr m_Decryptor; uint64_t m_LastUpdateTime; bool m_AcceptsTunnels, m_IsFloodfill; @@ -127,6 +127,6 @@ namespace i2p }; extern RouterContext context; -} +} #endif diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 642373f2..e9c2a384 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -19,20 +19,20 @@ namespace i2p { namespace data -{ - RouterInfo::RouterInfo (): m_Buffer (nullptr) - { +{ + RouterInfo::RouterInfo (): m_Buffer (nullptr) + { m_Addresses = boost::make_shared(); // create empty list } - + RouterInfo::RouterInfo (const std::string& fullPath): - m_FullPath (fullPath), m_IsUpdated (false), m_IsUnreachable (false), + m_FullPath (fullPath), m_IsUpdated (false), m_IsUnreachable (false), m_SupportedTransports (0), m_Caps (0) { m_Addresses = boost::make_shared(); // create empty list m_Buffer = new uint8_t[MAX_RI_BUFFER_SIZE]; ReadFromFile (); - } + } RouterInfo::RouterInfo (const uint8_t * buf, int len): m_IsUpdated (true), m_IsUnreachable (false), m_SupportedTransports (0), m_Caps (0) @@ -42,13 +42,13 @@ namespace data memcpy (m_Buffer, buf, len); m_BufferLen = len; ReadFromBuffer (true); - } + } RouterInfo::~RouterInfo () { delete[] m_Buffer; - } - + } + void RouterInfo::Update (const uint8_t * buf, int len) { // verify signature since we have indentity already @@ -63,35 +63,35 @@ namespace data // don't clean up m_Addresses, it will be replaced in ReadFromStream m_Properties.clear (); // copy buffer - if (!m_Buffer) + if (!m_Buffer) m_Buffer = new uint8_t[MAX_RI_BUFFER_SIZE]; memcpy (m_Buffer, buf, len); m_BufferLen = len; // skip identity size_t identityLen = m_RouterIdentity->GetFullLen (); - // read new RI + // read new RI std::stringstream str (std::string ((char *)m_Buffer + identityLen, m_BufferLen - identityLen)); ReadFromStream (str); // don't delete buffer until saved to the file } else - { + { LogPrint (eLogError, "RouterInfo: signature verification failed"); m_IsUnreachable = true; } - } - + } + void RouterInfo::SetRouterIdentity (std::shared_ptr identity) - { + { m_RouterIdentity = identity; m_Timestamp = i2p::util::GetMillisecondsSinceEpoch (); } - + bool RouterInfo::LoadFile () { std::ifstream s(m_FullPath, std::ifstream::binary); - if (s.is_open ()) - { + if (s.is_open ()) + { s.seekg (0,std::ios::end); m_BufferLen = s.tellg (); if (m_BufferLen < 40 || m_BufferLen > MAX_RI_BUFFER_SIZE) @@ -103,22 +103,22 @@ namespace data if (!m_Buffer) m_Buffer = new uint8_t[MAX_RI_BUFFER_SIZE]; s.read((char *)m_Buffer, m_BufferLen); - } + } else { LogPrint (eLogError, "RouterInfo: Can't open file ", m_FullPath); - return false; + return false; } return true; - } + } void RouterInfo::ReadFromFile () { if (LoadFile ()) - ReadFromBuffer (false); + ReadFromBuffer (false); else - m_IsUnreachable = true; - } + m_IsUnreachable = true; + } void RouterInfo::ReadFromBuffer (bool verifySignature) { @@ -131,7 +131,7 @@ namespace data return; } if (verifySignature) - { + { // reject RSA signatures if (m_RouterIdentity->IsRSA ()) { @@ -140,15 +140,15 @@ namespace data return; } // verify signature - int l = m_BufferLen - m_RouterIdentity->GetSignatureLen (); + int l = m_BufferLen - m_RouterIdentity->GetSignatureLen (); if (l < 0 || !m_RouterIdentity->Verify ((uint8_t *)m_Buffer, l, (uint8_t *)m_Buffer + l)) - { + { LogPrint (eLogError, "RouterInfo: signature verification failed"); m_IsUnreachable = true; return; } m_RouterIdentity->DropVerifier (); - } + } // parse RI std::stringstream str; str.write ((const char *)m_Buffer + identityLen, m_BufferLen - identityLen); @@ -158,17 +158,17 @@ namespace data LogPrint (eLogError, "RouterInfo: malformed message"); m_IsUnreachable = true; } - - } - + + } + void RouterInfo::ReadFromStream (std::istream& s) { s.read ((char *)&m_Timestamp, sizeof (m_Timestamp)); m_Timestamp = be64toh (m_Timestamp); // read addresses - auto addresses = boost::make_shared(); + auto addresses = boost::make_shared(); uint8_t numAddresses; - s.read ((char *)&numAddresses, sizeof (numAddresses)); if (!s) return; + s.read ((char *)&numAddresses, sizeof (numAddresses)); if (!s) return; bool introducers = false; for (int i = 0; i < numAddresses; i++) { @@ -181,11 +181,11 @@ namespace data if (!strcmp (transportStyle, "NTCP")) address->transportStyle = eTransportNTCP; else if (!strcmp (transportStyle, "SSU")) - { + { address->transportStyle = eTransportSSU; address->ssu.reset (new SSUExt ()); address->ssu->mtu = 0; - } + } else address->transportStyle = eTransportUnknown; address->port = 0; @@ -197,35 +197,35 @@ namespace data char key[255], value[255]; r += ReadString (key, 255, s); s.seekg (1, std::ios_base::cur); r++; // = - r += ReadString (value, 255, s); + r += ReadString (value, 255, s); s.seekg (1, std::ios_base::cur); r++; // ; if (!s) return; if (!strcmp (key, "host")) - { + { boost::system::error_code ecode; address->host = boost::asio::ip::address::from_string (value, ecode); if (ecode) - { + { if (address->transportStyle == eTransportNTCP) { supportedTransports |= eNTCPV4; // TODO: address->addressString = value; } else - { + { supportedTransports |= eSSUV4; // TODO: address->addressString = value; - } - } + } + } else { // add supported protocol if (address->host.is_v4 ()) - supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV4 : eSSUV4; + supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV4 : eSSUV4; else supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV6 : eSSUV6; - } - } + } + } else if (!strcmp (key, "port")) address->port = boost::lexical_cast(value); else if (!strcmp (key, "mtu")) @@ -234,21 +234,21 @@ namespace data address->ssu->mtu = boost::lexical_cast(value); else LogPrint (eLogWarning, "RouterInfo: Unexpected field 'mtu' for NTCP"); - } + } else if (!strcmp (key, "key")) - { + { if (address->ssu) Base64ToByteStream (value, strlen (value), address->ssu->key, 32); else LogPrint (eLogWarning, "RouterInfo: Unexpected field 'key' for NTCP"); - } + } else if (!strcmp (key, "caps")) ExtractCaps (value); else if (key[0] == 'i') - { + { // introducers introducers = true; - size_t l = strlen(key); + size_t l = strlen(key); unsigned char index = key[l-1] - '0'; // TODO: key[l-1] = 0; if (index > 9) @@ -257,13 +257,13 @@ namespace data if (s) continue; else return; } if (index >= address->ssu->introducers.size ()) - address->ssu->introducers.resize (index + 1); + address->ssu->introducers.resize (index + 1); Introducer& introducer = address->ssu->introducers.at (index); if (!strcmp (key, "ihost")) { boost::system::error_code ecode; introducer.iHost = boost::asio::ip::address::from_string (value, ecode); - } + } else if (!strcmp (key, "iport")) introducer.iPort = boost::lexical_cast(value); else if (!strcmp (key, "itag")) @@ -274,19 +274,19 @@ namespace data introducer.iExp = boost::lexical_cast(value); } if (!s) return; - } + } if (introducers) supportedTransports |= eSSUV4; // in case if host is not presented if (supportedTransports) { addresses->push_back(address); m_SupportedTransports |= supportedTransports; } - } -#if (BOOST_VERSION >= 105300) + } +#if (BOOST_VERSION >= 105300) boost::atomic_store (&m_Addresses, addresses); #else m_Addresses = addresses; // race condition -#endif +#endif // read peers uint8_t numPeers; s.read ((char *)&numPeers, sizeof (numPeers)); if (!s) return; @@ -297,23 +297,23 @@ namespace data size = be16toh (size); while (r < size) { - char key[255], value[255]; + char key[255], value[255]; r += ReadString (key, 255, s); s.seekg (1, std::ios_base::cur); r++; // = - r += ReadString (value, 255, s); + r += ReadString (value, 255, s); s.seekg (1, std::ios_base::cur); r++; // ; if (!s) return; m_Properties[key] = value; - - // extract caps + + // extract caps if (!strcmp (key, "caps")) ExtractCaps (value); // check netId else if (!strcmp (key, ROUTER_INFO_PROPERTY_NETID) && atoi (value) != i2p::context.GetNetID ()) { LogPrint (eLogError, "RouterInfo: Unexpected ", ROUTER_INFO_PROPERTY_NETID, "=", value); - m_IsUnreachable = true; - } + m_IsUnreachable = true; + } // family else if (!strcmp (key, ROUTER_INFO_PROPERTY_FAMILY)) { @@ -327,10 +327,10 @@ namespace data LogPrint (eLogWarning, "RouterInfo: family signature verification failed"); m_Family.clear (); } - } + } if (!s) return; - } + } if (!m_SupportedTransports || !m_Addresses->size() || (UsesIntroducer () && !introducers)) SetUnreachable (true); @@ -358,56 +358,56 @@ namespace data case CAPS_FLAG_EXTRA_BANDWIDTH1: case CAPS_FLAG_EXTRA_BANDWIDTH2: m_Caps |= Caps::eExtraBandwidth; - break; + break; case CAPS_FLAG_HIDDEN: m_Caps |= Caps::eHidden; - break; + break; case CAPS_FLAG_REACHABLE: m_Caps |= Caps::eReachable; break; case CAPS_FLAG_UNREACHABLE: m_Caps |= Caps::eUnreachable; - break; + break; case CAPS_FLAG_SSU_TESTING: m_Caps |= Caps::eSSUTesting; - break; + break; case CAPS_FLAG_SSU_INTRODUCER: m_Caps |= Caps::eSSUIntroducer; - break; + break; default: ; - } + } cap++; } } void RouterInfo::UpdateCapsProperty () - { + { std::string caps; - if (m_Caps & eFloodfill) + if (m_Caps & eFloodfill) { if (m_Caps & eExtraBandwidth) caps += (m_Caps & eHighBandwidth) ? CAPS_FLAG_EXTRA_BANDWIDTH2 : // 'X' CAPS_FLAG_EXTRA_BANDWIDTH1; // 'P' caps += CAPS_FLAG_HIGH_BANDWIDTH3; // 'O' - caps += CAPS_FLAG_FLOODFILL; // floodfill - } - else + caps += CAPS_FLAG_FLOODFILL; // floodfill + } + else { - if (m_Caps & eExtraBandwidth) - { + if (m_Caps & eExtraBandwidth) + { caps += (m_Caps & eHighBandwidth) ? CAPS_FLAG_EXTRA_BANDWIDTH2 /* 'X' */ : CAPS_FLAG_EXTRA_BANDWIDTH1; /*'P' */ caps += CAPS_FLAG_HIGH_BANDWIDTH3; // 'O' } - else - caps += (m_Caps & eHighBandwidth) ? CAPS_FLAG_HIGH_BANDWIDTH3 /* 'O' */: CAPS_FLAG_LOW_BANDWIDTH2 /* 'L' */; // bandwidth - } + else + caps += (m_Caps & eHighBandwidth) ? CAPS_FLAG_HIGH_BANDWIDTH3 /* 'O' */: CAPS_FLAG_LOW_BANDWIDTH2 /* 'L' */; // bandwidth + } if (m_Caps & eHidden) caps += CAPS_FLAG_HIDDEN; // hidden if (m_Caps & eReachable) caps += CAPS_FLAG_REACHABLE; // reachable if (m_Caps & eUnreachable) caps += CAPS_FLAG_UNREACHABLE; // unreachable SetProperty ("caps", caps); } - + void RouterInfo::WriteToStream (std::ostream& s) const { uint64_t ts = htobe64 (m_Timestamp); @@ -425,7 +425,7 @@ namespace data if (address.transportStyle == eTransportNTCP) WriteString ("NTCP", s); else if (address.transportStyle == eTransportSSU) - { + { WriteString ("SSU", s); // caps WriteString ("caps", properties); @@ -435,7 +435,7 @@ namespace data if (IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER; WriteString (caps, properties); properties << ';'; - } + } else WriteString ("", s); @@ -447,7 +447,7 @@ namespace data { // write introducers if any if (address.ssu->introducers.size () > 0) - { + { int i = 0; for (const auto& introducer: address.ssu->introducers) { @@ -456,7 +456,7 @@ namespace data WriteString (introducer.iHost.to_string (), properties); properties << ';'; i++; - } + } i = 0; for (const auto& introducer: address.ssu->introducers) { @@ -468,7 +468,7 @@ namespace data WriteString (value, properties); properties << ';'; i++; - } + } i = 0; for (const auto& introducer: address.ssu->introducers) { @@ -477,7 +477,7 @@ namespace data WriteString (boost::lexical_cast(introducer.iPort), properties); properties << ';'; i++; - } + } i = 0; for (const auto& introducer: address.ssu->introducers) { @@ -486,7 +486,7 @@ namespace data WriteString (boost::lexical_cast(introducer.iTag), properties); properties << ';'; i++; - } + } i = 0; for (const auto& introducer: address.ssu->introducers) { @@ -498,8 +498,8 @@ namespace data properties << ';'; } i++; - } - } + } + } // write intro key WriteString ("key", properties); properties << '='; @@ -515,17 +515,17 @@ namespace data properties << '='; WriteString (boost::lexical_cast(address.ssu->mtu), properties); properties << ';'; - } - } + } + } WriteString ("port", properties); properties << '='; WriteString (boost::lexical_cast(address.port), properties); properties << ';'; - + uint16_t size = htobe16 (properties.str ().size ()); s.write ((char *)&size, sizeof (size)); s.write (properties.str ().c_str (), properties.str ().size ()); - } + } // peers uint8_t numPeers = 0; @@ -539,18 +539,18 @@ namespace data properties << '='; WriteString (p.second, properties); properties << ';'; - } + } uint16_t size = htobe16 (properties.str ().size ()); s.write ((char *)&size, sizeof (size)); s.write (properties.str ().c_str (), properties.str ().size ()); - } + } bool RouterInfo::IsNewer (const uint8_t * buf, size_t len) const { if (!m_RouterIdentity) return false; size_t size = m_RouterIdentity->GetFullLen (); if (size + 8 > len) return false; - return bufbe64toh (buf + size) > m_Timestamp; + return bufbe64toh (buf + size) > m_Timestamp; } const uint8_t * RouterInfo::LoadBuffer () @@ -559,8 +559,8 @@ namespace data { if (LoadFile ()) LogPrint (eLogDebug, "RouterInfo: Buffer for ", GetIdentHashAbbreviation (GetIdentHash ()), " loaded from file"); - } - return m_Buffer; + } + return m_Buffer; } void RouterInfo::CreateBuffer (const PrivateKeys& privateKeys) @@ -569,7 +569,7 @@ namespace data std::stringstream s; uint8_t ident[1024]; auto identLen = privateKeys.GetPublic ()->ToBuffer (ident, 1024); - s.write ((char *)ident, identLen); + s.write ((char *)ident, identLen); WriteToStream (s); m_BufferLen = s.str ().size (); if (!m_Buffer) @@ -578,7 +578,7 @@ namespace data // signature privateKeys.Sign ((uint8_t *)m_Buffer, m_BufferLen, (uint8_t *)m_Buffer + m_BufferLen); m_BufferLen += privateKeys.GetPublic ()->GetSignatureLen (); - } + } bool RouterInfo::SaveToFile (const std::string& fullPath) { @@ -595,13 +595,13 @@ namespace data f.write ((char *)m_Buffer, m_BufferLen); return true; } - + size_t RouterInfo::ReadString (char * str, size_t len, std::istream& s) const { uint8_t l; s.read ((char *)&l, 1); if (l < len) - { + { s.read (str, l); if (!s) l = 0; // failed, return empty string str[l] = 0; @@ -611,16 +611,16 @@ namespace data LogPrint (eLogWarning, "RouterInfo: string length ", (int)l, " exceeds buffer size ", len); s.seekg (l, std::ios::cur); // skip str[0] = 0; - } + } return l+1; - } + } void RouterInfo::WriteString (const std::string& str, std::ostream& s) const { uint8_t len = str.size (); s.write ((char *)&len, 1); s.write (str.c_str (), len); - } + } void RouterInfo::AddNTCPAddress (const char * host, int port) { @@ -634,7 +634,7 @@ namespace data if (*it == *addr) return; m_SupportedTransports |= addr->host.is_v6 () ? eNTCPV6 : eNTCPV4; m_Addresses->push_back(std::move(addr)); - } + } void RouterInfo::AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu) { @@ -645,7 +645,7 @@ namespace data addr->cost = 10; // NTCP should have priority over SSU addr->date = 0; addr->ssu.reset (new SSUExt ()); - addr->ssu->mtu = mtu; + addr->ssu->mtu = mtu; memcpy (addr->ssu->key, key, 32); for (const auto& it: *m_Addresses) // don't insert same address twice if (*it == *addr) return; @@ -654,37 +654,37 @@ namespace data m_Caps |= eSSUTesting; m_Caps |= eSSUIntroducer; - } + } bool RouterInfo::AddIntroducer (const Introducer& introducer) { for (auto& addr : *m_Addresses) { if (addr->transportStyle == eTransportSSU && addr->host.is_v4 ()) - { + { for (auto& intro: addr->ssu->introducers) if (intro.iTag == introducer.iTag) return false; // already presented addr->ssu->introducers.push_back (introducer); return true; - } - } + } + } return false; - } + } bool RouterInfo::RemoveIntroducer (const boost::asio::ip::udp::endpoint& e) - { + { for (auto& addr: *m_Addresses) { if (addr->transportStyle == eTransportSSU && addr->host.is_v4 ()) - { + { for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it) - if ( boost::asio::ip::udp::endpoint (it->iHost, it->iPort) == e) + if ( boost::asio::ip::udp::endpoint (it->iHost, it->iPort) == e) { addr->ssu->introducers.erase (it); return true; } - } - } + } + } return false; } @@ -693,39 +693,39 @@ namespace data m_Caps = caps; UpdateCapsProperty (); } - + void RouterInfo::SetCaps (const char * caps) { SetProperty ("caps", caps); m_Caps = 0; ExtractCaps (caps); - } - + } + void RouterInfo::SetProperty (const std::string& key, const std::string& value) { m_Properties[key] = value; - } + } void RouterInfo::DeleteProperty (const std::string& key) { m_Properties.erase (key); } - std::string RouterInfo::GetProperty (const std::string& key) const + std::string RouterInfo::GetProperty (const std::string& key) const { auto it = m_Properties.find (key); if (it != m_Properties.end ()) return it->second; return ""; - } - + } + bool RouterInfo::IsNTCP (bool v4only) const { if (v4only) return m_SupportedTransports & eNTCPV4; else return m_SupportedTransports & (eNTCPV4 | eNTCPV6); - } + } bool RouterInfo::IsSSU (bool v4only) const { @@ -744,7 +744,7 @@ namespace data { return m_SupportedTransports & (eNTCPV4 | eSSUV4); } - + void RouterInfo::EnableV6 () { if (!IsV6 ()) @@ -756,13 +756,13 @@ namespace data if (!IsV4 ()) m_SupportedTransports |= eNTCPV4 | eSSUV4; } - - + + void RouterInfo::DisableV6 () - { + { if (IsV6 ()) - { - m_SupportedTransports &= ~(eNTCPV6 | eSSUV6); + { + m_SupportedTransports &= ~(eNTCPV6 | eSSUV6); for (auto it = m_Addresses->begin (); it != m_Addresses->end ();) { auto addr = *it; @@ -770,15 +770,15 @@ namespace data it = m_Addresses->erase (it); else ++it; - } - } + } + } } void RouterInfo::DisableV4 () - { + { if (IsV4 ()) - { - m_SupportedTransports &= ~(eNTCPV4 | eSSUV4); + { + m_SupportedTransports &= ~(eNTCPV4 | eSSUV4); for (auto it = m_Addresses->begin (); it != m_Addresses->end ();) { auto addr = *it; @@ -786,55 +786,55 @@ namespace data it = m_Addresses->erase (it); else ++it; - } - } + } + } } - - + + bool RouterInfo::UsesIntroducer () const { return m_Caps & Caps::eUnreachable; // non-reachable - } - + } + std::shared_ptr RouterInfo::GetNTCPAddress (bool v4only) const { return GetAddress (eTransportNTCP, v4only); - } + } - std::shared_ptr RouterInfo::GetSSUAddress (bool v4only) const + std::shared_ptr RouterInfo::GetSSUAddress (bool v4only) const { return GetAddress (eTransportSSU, v4only); - } + } - std::shared_ptr RouterInfo::GetSSUV6Address () const + std::shared_ptr RouterInfo::GetSSUV6Address () const { return GetAddress (eTransportSSU, false, true); - } - + } + std::shared_ptr RouterInfo::GetAddress (TransportStyle s, bool v4only, bool v6only) const { #if (BOOST_VERSION >= 105300) auto addresses = boost::atomic_load (&m_Addresses); -#else +#else auto addresses = m_Addresses; -#endif +#endif for (const auto& address : *addresses) { if (address->transportStyle == s) - { + { if ((!v4only || address->host.is_v4 ()) && (!v6only || address->host.is_v6 ())) return address; - } - } + } + } return nullptr; - } + } - std::shared_ptr RouterInfo::GetProfile () const + std::shared_ptr RouterInfo::GetProfile () const { if (!m_Profile) m_Profile = GetRouterProfile (GetIdentHash ()); return m_Profile; - } + } void RouterInfo::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const { diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 97c0f7b2..09e2c015 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include "Identity.h" #include "Profiling.h" @@ -17,15 +17,15 @@ namespace i2p namespace data { const char ROUTER_INFO_PROPERTY_LEASESETS[] = "netdb.knownLeaseSets"; - const char ROUTER_INFO_PROPERTY_ROUTERS[] = "netdb.knownRouters"; + const char ROUTER_INFO_PROPERTY_ROUTERS[] = "netdb.knownRouters"; const char ROUTER_INFO_PROPERTY_NETID[] = "netId"; - const char ROUTER_INFO_PROPERTY_FAMILY[] = "family"; + const char ROUTER_INFO_PROPERTY_FAMILY[] = "family"; const char ROUTER_INFO_PROPERTY_FAMILY_SIG[] = "family.sig"; - + const char CAPS_FLAG_FLOODFILL = 'f'; const char CAPS_FLAG_HIDDEN = 'H'; const char CAPS_FLAG_REACHABLE = 'R'; - const char CAPS_FLAG_UNREACHABLE = 'U'; + const char CAPS_FLAG_UNREACHABLE = 'U'; /* bandwidth flags */ const char CAPS_FLAG_LOW_BANDWIDTH1 = 'K'; /* < 12 KBps */ const char CAPS_FLAG_LOW_BANDWIDTH2 = 'L'; /* 12-48 KBps */ @@ -34,7 +34,7 @@ namespace data const char CAPS_FLAG_HIGH_BANDWIDTH3 = 'O'; /* 128-256 KBps */ const char CAPS_FLAG_EXTRA_BANDWIDTH1 = 'P'; /* 256-2000 KBps */ const char CAPS_FLAG_EXTRA_BANDWIDTH2 = 'X'; /* > 2000 KBps */ - + const char CAPS_FLAG_SSU_TESTING = 'B'; const char CAPS_FLAG_SSU_INTRODUCER = 'C'; @@ -44,13 +44,13 @@ namespace data public: enum SupportedTranports - { + { eNTCPV4 = 0x01, eNTCPV6 = 0x02, eSSUV4 = 0x04, eSSUV6 = 0x08 }; - + enum Caps { eFloodfill = 0x01, @@ -71,7 +71,7 @@ namespace data }; typedef Tag<32> IntroKey; // should be castable to MacKey and AESKey - struct Introducer + struct Introducer { Introducer (): iExp (0) {}; boost::asio::ip::address iHost; @@ -85,9 +85,9 @@ namespace data { int mtu; IntroKey key; // intro key for SSU - std::vector introducers; + std::vector introducers; }; - + struct Address { TransportStyle transportStyle; @@ -98,23 +98,23 @@ namespace data uint8_t cost; std::unique_ptr ssu; // not null for SSU - bool IsCompatible (const boost::asio::ip::address& other) const + bool IsCompatible (const boost::asio::ip::address& other) const { return (host.is_v4 () && other.is_v4 ()) || (host.is_v6 () && other.is_v6 ()); - } + } bool operator==(const Address& other) const { return transportStyle == other.transportStyle && host == other.host && port == other.port; - } + } bool operator!=(const Address& other) const { return !(*this == other); - } + } }; - typedef std::list > Addresses; + typedef std::list > Addresses; RouterInfo (); RouterInfo (const std::string& fullPath); @@ -122,7 +122,7 @@ namespace data RouterInfo& operator=(const RouterInfo& ) = default; RouterInfo (const uint8_t * buf, int len); ~RouterInfo (); - + std::shared_ptr GetRouterIdentity () const { return m_RouterIdentity; }; void SetRouterIdentity (std::shared_ptr identity); std::string GetIdentHashBase64 () const { return GetIdentHash ().ToBase64 (); }; @@ -131,7 +131,7 @@ namespace data std::shared_ptr GetNTCPAddress (bool v4only = true) const; std::shared_ptr GetSSUAddress (bool v4only = true) const; std::shared_ptr GetSSUV6Address () const; - + void AddNTCPAddress (const char * host, int port); void AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu = 0); bool AddIntroducer (const Introducer& introducer); @@ -156,37 +156,37 @@ namespace data bool IsPeerTesting () const { return m_Caps & eSSUTesting; }; bool IsHidden () const { return m_Caps & eHidden; }; bool IsHighBandwidth () const { return m_Caps & RouterInfo::eHighBandwidth; }; - bool IsExtraBandwidth () const { return m_Caps & RouterInfo::eExtraBandwidth; }; - - uint8_t GetCaps () const { return m_Caps; }; + bool IsExtraBandwidth () const { return m_Caps & RouterInfo::eExtraBandwidth; }; + + uint8_t GetCaps () const { return m_Caps; }; void SetCaps (uint8_t caps); void SetCaps (const char * caps); - void SetUnreachable (bool unreachable) { m_IsUnreachable = unreachable; }; + void SetUnreachable (bool unreachable) { m_IsUnreachable = unreachable; }; bool IsUnreachable () const { return m_IsUnreachable; }; const uint8_t * GetBuffer () const { return m_Buffer; }; const uint8_t * LoadBuffer (); // load if necessary - int GetBufferLen () const { return m_BufferLen; }; + int GetBufferLen () const { return m_BufferLen; }; void CreateBuffer (const PrivateKeys& privateKeys); bool IsUpdated () const { return m_IsUpdated; }; - void SetUpdated (bool updated) { m_IsUpdated = updated; }; + void SetUpdated (bool updated) { m_IsUpdated = updated; }; bool SaveToFile (const std::string& fullPath); std::shared_ptr GetProfile () const; void SaveProfile () { if (m_Profile) m_Profile->Save (GetIdentHash ()); }; - + void Update (const uint8_t * buf, int len); void DeleteBuffer () { delete[] m_Buffer; m_Buffer = nullptr; }; - bool IsNewer (const uint8_t * buf, size_t len) const; + bool IsNewer (const uint8_t * buf, size_t len) const; + + /** return true if we are in a router family and the signature is valid */ + bool IsFamily(const std::string & fam) const; - /** return true if we are in a router family and the signature is valid */ - bool IsFamily(const std::string & fam) const; - // implements RoutingDestination std::shared_ptr GetIdentity () const { return m_RouterIdentity; }; - void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const; + void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) const; bool IsDestination () const { return false; }; @@ -201,7 +201,7 @@ namespace data void WriteString (const std::string& str, std::ostream& s) const; void ExtractCaps (const char * value); std::shared_ptr GetAddress (TransportStyle s, bool v4only, bool v6only = false) const; - void UpdateCapsProperty (); + void UpdateCapsProperty (); private: @@ -210,13 +210,13 @@ namespace data uint8_t * m_Buffer; size_t m_BufferLen; uint64_t m_Timestamp; - boost::shared_ptr m_Addresses; // TODO: use std::shared_ptr and std::atomic_store for gcc >= 4.9 + boost::shared_ptr m_Addresses; // TODO: use std::shared_ptr and std::atomic_store for gcc >= 4.9 std::map m_Properties; bool m_IsUpdated, m_IsUnreachable; uint8_t m_SupportedTransports, m_Caps; mutable std::shared_ptr m_Profile; - }; -} + }; +} } #endif diff --git a/libi2pd/SSU.cpp b/libi2pd/SSU.cpp index d8688442..2197552c 100644 --- a/libi2pd/SSU.cpp +++ b/libi2pd/SSU.cpp @@ -13,32 +13,32 @@ namespace transport SSUServer::SSUServer (const boost::asio::ip::address & addr, int port): m_OnlyV6(true), m_IsRunning(false), - m_Thread (nullptr), m_ThreadV6 (nullptr), m_ReceiversThread (nullptr), - m_ReceiversThreadV6 (nullptr), m_Work (m_Service), m_WorkV6 (m_ServiceV6), + m_Thread (nullptr), m_ThreadV6 (nullptr), m_ReceiversThread (nullptr), + m_ReceiversThreadV6 (nullptr), m_Work (m_Service), m_WorkV6 (m_ServiceV6), m_ReceiversWork (m_ReceiversService), m_ReceiversWorkV6 (m_ReceiversServiceV6), - m_EndpointV6 (addr, port), m_Socket (m_ReceiversService, m_Endpoint), - m_SocketV6 (m_ReceiversServiceV6), m_IntroducersUpdateTimer (m_Service), - m_PeerTestsCleanupTimer (m_Service), m_TerminationTimer (m_Service), - m_TerminationTimerV6 (m_ServiceV6) + m_EndpointV6 (addr, port), m_Socket (m_ReceiversService, m_Endpoint), + m_SocketV6 (m_ReceiversServiceV6), m_IntroducersUpdateTimer (m_Service), + m_PeerTestsCleanupTimer (m_Service), m_TerminationTimer (m_Service), + m_TerminationTimerV6 (m_ServiceV6) { OpenSocketV6 (); } - + SSUServer::SSUServer (int port): m_OnlyV6(false), m_IsRunning(false), m_Thread (nullptr), m_ThreadV6 (nullptr), m_ReceiversThread (nullptr), - m_ReceiversThreadV6 (nullptr), m_Work (m_Service), m_WorkV6 (m_ServiceV6), + m_ReceiversThreadV6 (nullptr), m_Work (m_Service), m_WorkV6 (m_ServiceV6), m_ReceiversWork (m_ReceiversService), m_ReceiversWorkV6 (m_ReceiversServiceV6), - m_Endpoint (boost::asio::ip::udp::v4 (), port), m_EndpointV6 (boost::asio::ip::udp::v6 (), port), - m_Socket (m_ReceiversService), m_SocketV6 (m_ReceiversServiceV6), + m_Endpoint (boost::asio::ip::udp::v4 (), port), m_EndpointV6 (boost::asio::ip::udp::v6 (), port), + m_Socket (m_ReceiversService), m_SocketV6 (m_ReceiversServiceV6), m_IntroducersUpdateTimer (m_Service), m_PeerTestsCleanupTimer (m_Service), - m_TerminationTimer (m_Service), m_TerminationTimerV6 (m_ServiceV6) + m_TerminationTimer (m_Service), m_TerminationTimerV6 (m_ServiceV6) { OpenSocket (); if (context.SupportsV6 ()) OpenSocketV6 (); } - + SSUServer::~SSUServer () { } @@ -46,11 +46,11 @@ namespace transport void SSUServer::OpenSocket () { m_Socket.open (boost::asio::ip::udp::v4()); - m_Socket.set_option (boost::asio::socket_base::receive_buffer_size (SSU_SOCKET_RECEIVE_BUFFER_SIZE)); + m_Socket.set_option (boost::asio::socket_base::receive_buffer_size (SSU_SOCKET_RECEIVE_BUFFER_SIZE)); m_Socket.set_option (boost::asio::socket_base::send_buffer_size (SSU_SOCKET_SEND_BUFFER_SIZE)); m_Socket.bind (m_Endpoint); } - + void SSUServer::OpenSocketV6 () { m_SocketV6.open (boost::asio::ip::udp::v6()); @@ -58,8 +58,8 @@ namespace transport m_SocketV6.set_option (boost::asio::socket_base::receive_buffer_size (SSU_SOCKET_RECEIVE_BUFFER_SIZE)); m_SocketV6.set_option (boost::asio::socket_base::send_buffer_size (SSU_SOCKET_SEND_BUFFER_SIZE)); m_SocketV6.bind (m_EndpointV6); - } - + } + void SSUServer::Start () { m_IsRunning = true; @@ -68,16 +68,16 @@ namespace transport m_ReceiversThread = new std::thread (std::bind (&SSUServer::RunReceivers, this)); m_Thread = new std::thread (std::bind (&SSUServer::Run, this)); m_ReceiversService.post (std::bind (&SSUServer::Receive, this)); - ScheduleTermination (); + ScheduleTermination (); } if (context.SupportsV6 ()) - { + { m_ReceiversThreadV6 = new std::thread (std::bind (&SSUServer::RunReceiversV6, this)); m_ThreadV6 = new std::thread (std::bind (&SSUServer::RunV6, this)); - m_ReceiversServiceV6.post (std::bind (&SSUServer::ReceiveV6, this)); - ScheduleTerminationV6 (); + m_ReceiversServiceV6.post (std::bind (&SSUServer::ReceiveV6, this)); + ScheduleTerminationV6 (); } - SchedulePeerTestsCleanupTimer (); + SchedulePeerTestsCleanupTimer (); ScheduleIntroducersUpdateTimer (); // wait for 30 seconds and decide if we need introducers } @@ -86,7 +86,7 @@ namespace transport DeleteAllSessions (); m_IsRunning = false; m_TerminationTimer.cancel (); - m_TerminationTimerV6.cancel (); + m_TerminationTimerV6.cancel (); m_Service.stop (); m_Socket.close (); m_ServiceV6.stop (); @@ -94,135 +94,135 @@ namespace transport m_ReceiversService.stop (); m_ReceiversServiceV6.stop (); if (m_ReceiversThread) - { - m_ReceiversThread->join (); + { + m_ReceiversThread->join (); delete m_ReceiversThread; m_ReceiversThread = nullptr; } if (m_Thread) - { - m_Thread->join (); + { + m_Thread->join (); delete m_Thread; m_Thread = nullptr; } if (m_ReceiversThreadV6) - { - m_ReceiversThreadV6->join (); + { + m_ReceiversThreadV6->join (); delete m_ReceiversThreadV6; m_ReceiversThreadV6 = nullptr; } if (m_ThreadV6) - { - m_ThreadV6->join (); + { + m_ThreadV6->join (); delete m_ThreadV6; m_ThreadV6 = nullptr; } } - void SSUServer::Run () - { + void SSUServer::Run () + { while (m_IsRunning) { try - { + { m_Service.run (); } catch (std::exception& ex) { LogPrint (eLogError, "SSU: server runtime exception: ", ex.what ()); - } - } + } + } } - void SSUServer::RunV6 () - { + void SSUServer::RunV6 () + { while (m_IsRunning) { try - { + { m_ServiceV6.run (); } catch (std::exception& ex) { LogPrint (eLogError, "SSU: v6 server runtime exception: ", ex.what ()); - } - } - } + } + } + } - void SSUServer::RunReceivers () - { + void SSUServer::RunReceivers () + { while (m_IsRunning) { try - { + { m_ReceiversService.run (); } catch (std::exception& ex) { LogPrint (eLogError, "SSU: receivers runtime exception: ", ex.what ()); - } - } - } - - void SSUServer::RunReceiversV6 () - { + } + } + } + + void SSUServer::RunReceiversV6 () + { while (m_IsRunning) { try - { + { m_ReceiversServiceV6.run (); } catch (std::exception& ex) { LogPrint (eLogError, "SSU: v6 receivers runtime exception: ", ex.what ()); - } - } - } + } + } + } void SSUServer::AddRelay (uint32_t tag, std::shared_ptr relay) { m_Relays[tag] = relay; - } + } void SSUServer::RemoveRelay (uint32_t tag) { m_Relays.erase (tag); - } - + } + std::shared_ptr SSUServer::FindRelaySession (uint32_t tag) { auto it = m_Relays.find (tag); if (it != m_Relays.end ()) - { + { if (it->second->GetState () == eSessionStateEstablished) return it->second; else - m_Relays.erase (it); - } + m_Relays.erase (it); + } return nullptr; } void SSUServer::Send (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to) { - if (to.protocol () == boost::asio::ip::udp::v4()) + if (to.protocol () == boost::asio::ip::udp::v4()) m_Socket.send_to (boost::asio::buffer (buf, len), to); else m_SocketV6.send_to (boost::asio::buffer (buf, len), to); - } + } void SSUServer::Receive () { SSUPacket * packet = new SSUPacket (); m_Socket.async_receive_from (boost::asio::buffer (packet->buf, SSU_MTU_V4), packet->from, - std::bind (&SSUServer::HandleReceivedFrom, this, std::placeholders::_1, std::placeholders::_2, packet)); + std::bind (&SSUServer::HandleReceivedFrom, this, std::placeholders::_1, std::placeholders::_2, packet)); } void SSUServer::ReceiveV6 () { SSUPacket * packet = new SSUPacket (); m_SocketV6.async_receive_from (boost::asio::buffer (packet->buf, SSU_MTU_V6), packet->from, - std::bind (&SSUServer::HandleReceivedFromV6, this, std::placeholders::_1, std::placeholders::_2, packet)); - } + std::bind (&SSUServer::HandleReceivedFromV6, this, std::placeholders::_1, std::placeholders::_2, packet)); + } void SSUServer::HandleReceivedFrom (const boost::system::error_code& ecode, std::size_t bytes_transferred, SSUPacket * packet) { @@ -235,13 +235,13 @@ namespace transport boost::system::error_code ec; size_t moreBytes = m_Socket.available(ec); if (!ec) - { + { while (moreBytes && packets.size () < 25) { packet = new SSUPacket (); packet->len = m_Socket.receive_from (boost::asio::buffer (packet->buf, SSU_MTU_V4), packet->from, 0, ec); if (!ec) - { + { packets.push_back (packet); moreBytes = m_Socket.available(ec); if (ec) break; @@ -251,15 +251,15 @@ namespace transport LogPrint (eLogError, "SSU: receive_from error: ", ec.message ()); delete packet; break; - } + } } - } + } m_Service.post (std::bind (&SSUServer::HandleReceivedPackets, this, packets, &m_Sessions)); Receive (); } else - { + { delete packet; if (ecode != boost::asio::error::operation_aborted) { @@ -268,7 +268,7 @@ namespace transport OpenSocket (); Receive (); } - } + } } void SSUServer::HandleReceivedFromV6 (const boost::system::error_code& ecode, std::size_t bytes_transferred, SSUPacket * packet) @@ -298,15 +298,15 @@ namespace transport LogPrint (eLogError, "SSU: v6 receive_from error: ", ec.message ()); delete packet; break; - } + } } } - + m_ServiceV6.post (std::bind (&SSUServer::HandleReceivedPackets, this, packets, &m_SessionsV6)); ReceiveV6 (); } else - { + { delete packet; if (ecode != boost::asio::error::operation_aborted) { @@ -315,17 +315,17 @@ namespace transport OpenSocketV6 (); ReceiveV6 (); } - } + } } - void SSUServer::HandleReceivedPackets (std::vector packets, + void SSUServer::HandleReceivedPackets (std::vector packets, std::map > * sessions) { - std::shared_ptr session; + std::shared_ptr session; for (auto& packet: packets) { try - { + { if (!session || session->GetRemoteEndpoint () != packet->from) // we received packet for other session than previous { if (session) session->FlushData (); @@ -341,13 +341,13 @@ namespace transport } } session->ProcessNextMessage (packet->buf, packet->len, packet->from); - } + } catch (std::exception& ex) { LogPrint (eLogError, "SSU: HandleReceivedPackets ", ex.what ()); if (session) session->FlushData (); session = nullptr; - } + } delete packet; } if (session) session->FlushData (); @@ -357,26 +357,26 @@ namespace transport { if (!router) return nullptr; auto address = router->GetSSUAddress (true); // v4 only - if (!address) return nullptr; + if (!address) return nullptr; auto session = FindSession (boost::asio::ip::udp::endpoint (address->host, address->port)); if (session || !context.SupportsV6 ()) return session; // try v6 - address = router->GetSSUV6Address (); + address = router->GetSSUV6Address (); if (!address) return nullptr; return FindSession (boost::asio::ip::udp::endpoint (address->host, address->port)); - } + } std::shared_ptr SSUServer::FindSession (const boost::asio::ip::udp::endpoint& e) const { - auto& sessions = e.address ().is_v6 () ? m_SessionsV6 : m_Sessions; + auto& sessions = e.address ().is_v6 () ? m_SessionsV6 : m_Sessions; auto it = sessions.find (e); if (it != sessions.end ()) return it->second; else return nullptr; } - + void SSUServer::CreateSession (std::shared_ptr router, bool peerTest, bool v4only) { auto address = router->GetSSUAddress (v4only || !context.SupportsV6 ()); @@ -385,7 +385,7 @@ namespace transport else LogPrint (eLogWarning, "SSU: Router ", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), " doesn't have SSU address"); } - + void SSUServer::CreateSession (std::shared_ptr router, const boost::asio::ip::address& addr, int port, bool peerTest) { @@ -403,27 +403,27 @@ namespace transport } void SSUServer::CreateDirectSession (std::shared_ptr router, boost::asio::ip::udp::endpoint remoteEndpoint, bool peerTest) - { - auto& sessions = remoteEndpoint.address ().is_v6 () ? m_SessionsV6 : m_Sessions; + { + auto& sessions = remoteEndpoint.address ().is_v6 () ? m_SessionsV6 : m_Sessions; auto it = sessions.find (remoteEndpoint); if (it != sessions.end ()) - { + { auto session = it->second; if (peerTest && session->GetState () == eSessionStateEstablished) session->SendPeerTest (); - } + } else { - // otherwise create new session + // otherwise create new session auto session = std::make_shared (*this, remoteEndpoint, router, peerTest); sessions[remoteEndpoint] = session; - // connect + // connect LogPrint (eLogDebug, "SSU: Creating new session to [", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), "] ", remoteEndpoint.address ().to_string (), ":", remoteEndpoint.port ()); session->Connect (); } } - + void SSUServer::CreateSessionThroughIntroducer (std::shared_ptr router, bool peerTest) { if (router && router->UsesIntroducer ()) @@ -435,13 +435,13 @@ namespace transport auto it = m_Sessions.find (remoteEndpoint); // check if session is presented already if (it != m_Sessions.end ()) - { + { auto session = it->second; if (peerTest && session->GetState () == eSessionStateEstablished) session->SendPeerTest (); - return; - } - // create new session + return; + } + // create new session int numIntroducers = address->ssu->introducers.size (); if (numIntroducers > 0) { @@ -455,52 +455,52 @@ namespace transport if (intr->iExp > 0 && ts > intr->iExp) continue; // skip expired introducer boost::asio::ip::udp::endpoint ep (intr->iHost, intr->iPort); if (ep.address ().is_v4 ()) // ipv4 only - { + { if (!introducer) introducer = intr; // we pick first one for now - it = m_Sessions.find (ep); + it = m_Sessions.find (ep); if (it != m_Sessions.end ()) { introducerSession = it->second; - break; - } + break; + } } } if (!introducer) { LogPrint (eLogWarning, "SSU: Can't connect to unreachable router and no ipv4 non-expired introducers presented"); return; - } + } - if (introducerSession) // session found + if (introducerSession) // session found LogPrint (eLogWarning, "SSU: Session to introducer already exists"); else // create new { LogPrint (eLogDebug, "SSU: Creating new session to introducer ", introducer->iHost); boost::asio::ip::udp::endpoint introducerEndpoint (introducer->iHost, introducer->iPort); introducerSession = std::make_shared (*this, introducerEndpoint, router); - m_Sessions[introducerEndpoint] = introducerSession; + m_Sessions[introducerEndpoint] = introducerSession; } -#if BOOST_VERSION >= 104900 +#if BOOST_VERSION >= 104900 if (!address->host.is_unspecified () && address->port) #endif { - // create session + // create session auto session = std::make_shared (*this, remoteEndpoint, router, peerTest); m_Sessions[remoteEndpoint] = session; // introduce LogPrint (eLogInfo, "SSU: Introduce new session to [", i2p::data::GetIdentHashAbbreviation (router->GetIdentHash ()), "] through introducer ", introducer->iHost, ":", introducer->iPort); - session->WaitForIntroduction (); + session->WaitForIntroduction (); if (i2p::context.GetRouterInfo ().UsesIntroducer ()) // if we are unreachable { uint8_t buf[1]; Send (buf, 0, remoteEndpoint); // send HolePunch - } + } } introducerSession->Introduce (*introducer, router); } - else + else LogPrint (eLogWarning, "SSU: Can't connect to unreachable router and no introducers present"); } else @@ -518,8 +518,8 @@ namespace transport m_SessionsV6.erase (ep); else m_Sessions.erase (ep); - } - } + } + } void SSUServer::DeleteAllSessions () { @@ -543,15 +543,15 @@ namespace transport auto ind = rand () % filteredSessions.size (); return filteredSessions[ind]; } - return nullptr; + return nullptr; } std::shared_ptr SSUServer::GetRandomEstablishedV4Session (std::shared_ptr excluded) // v4 only { return GetRandomV4Session ( - [excluded](std::shared_ptr session)->bool - { - return session->GetState () == eSessionStateEstablished && session != excluded; + [excluded](std::shared_ptr session)->bool + { + return session->GetState () == eSessionStateEstablished && session != excluded; } ); } @@ -567,15 +567,15 @@ namespace transport auto ind = rand () % filteredSessions.size (); return filteredSessions[ind]; } - return nullptr; + return nullptr; } std::shared_ptr SSUServer::GetRandomEstablishedV6Session (std::shared_ptr excluded) // v6 only { return GetRandomV6Session ( - [excluded](std::shared_ptr session)->bool - { - return session->GetState () == eSessionStateEstablished && session != excluded; + [excluded](std::shared_ptr session)->bool + { + return session->GetState () == eSessionStateEstablished && session != excluded; } ); } @@ -587,18 +587,18 @@ namespace transport for (int i = 0; i < maxNumIntroducers; i++) { auto session = GetRandomV4Session ( - [&ret, ts](std::shared_ptr session)->bool - { + [&ret, ts](std::shared_ptr session)->bool + { return session->GetRelayTag () && !ret.count (session.get ()) && session->GetState () == eSessionStateEstablished && - ts < session->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_DURATION; + ts < session->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_DURATION; } - ); + ); if (session) { ret.insert (session.get ()); break; - } + } } return ret; } @@ -607,7 +607,7 @@ namespace transport { m_IntroducersUpdateTimer.expires_from_now (boost::posix_time::seconds(SSU_KEEP_ALIVE_INTERVAL)); m_IntroducersUpdateTimer.async_wait (std::bind (&SSUServer::HandleIntroducersUpdateTimer, - this, std::placeholders::_1)); + this, std::placeholders::_1)); } void SSUServer::HandleIntroducersUpdateTimer (const boost::system::error_code& ecode) @@ -620,7 +620,7 @@ namespace transport // we still don't know if we need introducers ScheduleIntroducersUpdateTimer (); return; - } + } if (i2p::context.GetStatus () == eRouterStatusOK) return; // we don't need introducers anymore // we are firewalled if (!i2p::context.IsUnreachable ()) i2p::context.SetUnreachable (); @@ -628,7 +628,7 @@ namespace transport size_t numIntroducers = 0; uint32_t ts = i2p::util::GetSecondsSinceEpoch (); for (const auto& it : m_Introducers) - { + { auto session = FindSession (it); if (session && ts < session->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_DURATION) { @@ -636,7 +636,7 @@ namespace transport newList.push_back (it); numIntroducers++; } - else + else i2p::context.RemoveIntroducer (it); } @@ -658,16 +658,16 @@ namespace transport if (newList.size () >= SSU_MAX_NUM_INTRODUCERS) break; } } - } + } m_Introducers = newList; if (m_Introducers.size () < SSU_MAX_NUM_INTRODUCERS) { auto introducer = i2p::data::netdb.GetRandomIntroducer (); if (introducer) CreateSession (introducer); - } + } ScheduleIntroducersUpdateTimer (); - } + } } void SSUServer::NewPeerTest (uint32_t nonce, PeerTestParticipant role, std::shared_ptr session) @@ -682,7 +682,7 @@ namespace transport return it->second.role; else return ePeerTestParticipantUnknown; - } + } std::shared_ptr SSUServer::GetPeerTestSession (uint32_t nonce) { @@ -698,26 +698,26 @@ namespace transport auto it = m_PeerTests.find (nonce); if (it != m_PeerTests.end ()) it->second.role = role; - } - + } + void SSUServer::RemovePeerTest (uint32_t nonce) { m_PeerTests.erase (nonce); - } + } void SSUServer::SchedulePeerTestsCleanupTimer () { m_PeerTestsCleanupTimer.expires_from_now (boost::posix_time::seconds(SSU_PEER_TEST_TIMEOUT)); m_PeerTestsCleanupTimer.async_wait (std::bind (&SSUServer::HandlePeerTestsCleanupTimer, - this, std::placeholders::_1)); + this, std::placeholders::_1)); } void SSUServer::HandlePeerTestsCleanupTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) { - int numDeleted = 0; - uint64_t ts = i2p::util::GetMillisecondsSinceEpoch (); + int numDeleted = 0; + uint64_t ts = i2p::util::GetMillisecondsSinceEpoch (); for (auto it = m_PeerTests.begin (); it != m_PeerTests.end ();) { if (ts > it->second.creationTime + SSU_PEER_TEST_TIMEOUT*1000LL) @@ -744,21 +744,21 @@ namespace transport void SSUServer::HandleTerminationTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) - { + { auto ts = i2p::util::GetSecondsSinceEpoch (); for (auto& it: m_Sessions) - if (it.second->IsTerminationTimeoutExpired (ts)) + if (it.second->IsTerminationTimeoutExpired (ts)) { auto session = it.second; - m_Service.post ([session] - { + m_Service.post ([session] + { LogPrint (eLogWarning, "SSU: no activity with ", session->GetRemoteEndpoint (), " for ", session->GetTerminationTimeout (), " seconds"); session->Failed (); - }); + }); } - ScheduleTermination (); - } - } + ScheduleTermination (); + } + } void SSUServer::ScheduleTerminationV6 () { @@ -770,21 +770,21 @@ namespace transport void SSUServer::HandleTerminationTimerV6 (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) - { + { auto ts = i2p::util::GetSecondsSinceEpoch (); for (auto& it: m_SessionsV6) - if (it.second->IsTerminationTimeoutExpired (ts)) + if (it.second->IsTerminationTimeoutExpired (ts)) { auto session = it.second; - m_ServiceV6.post ([session] - { + m_ServiceV6.post ([session] + { LogPrint (eLogWarning, "SSU: no activity with ", session->GetRemoteEndpoint (), " for ", session->GetTerminationTimeout (), " seconds"); session->Failed (); - }); + }); } - ScheduleTerminationV6 (); - } - } + ScheduleTerminationV6 (); + } + } } } diff --git a/libi2pd/SSU.h b/libi2pd/SSU.h index ee49c6a4..10e5ec06 100644 --- a/libi2pd/SSU.h +++ b/libi2pd/SSU.h @@ -20,8 +20,8 @@ namespace i2p { namespace transport { - const int SSU_KEEP_ALIVE_INTERVAL = 30; // 30 seconds - const int SSU_PEER_TEST_TIMEOUT = 60; // 60 seconds + const int SSU_KEEP_ALIVE_INTERVAL = 30; // 30 seconds + const int SSU_PEER_TEST_TIMEOUT = 60; // 60 seconds const int SSU_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour const int SSU_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds const size_t SSU_MAX_NUM_INTRODUCERS = 3; @@ -33,8 +33,8 @@ namespace transport i2p::crypto::AESAlignedBuffer buf; // max MTU + iv + size boost::asio::ip::udp::endpoint from; size_t len; - }; - + }; + class SSUServer { public: @@ -45,7 +45,7 @@ namespace transport void Start (); void Stop (); void CreateSession (std::shared_ptr router, bool peerTest = false, bool v4only = false); - void CreateSession (std::shared_ptr router, + void CreateSession (std::shared_ptr router, const boost::asio::ip::address& addr, int port, bool peerTest = false); void CreateDirectSession (std::shared_ptr router, boost::asio::ip::udp::endpoint remoteEndpoint, bool peerTest); std::shared_ptr FindSession (std::shared_ptr router) const; @@ -53,11 +53,11 @@ namespace transport std::shared_ptr GetRandomEstablishedV4Session (std::shared_ptr excluded); std::shared_ptr GetRandomEstablishedV6Session (std::shared_ptr excluded); void DeleteSession (std::shared_ptr session); - void DeleteAllSessions (); + void DeleteAllSessions (); boost::asio::io_service& GetService () { return m_Service; }; boost::asio::io_service& GetServiceV6 () { return m_ServiceV6; }; - const boost::asio::ip::udp::endpoint& GetEndpoint () const { return m_Endpoint; }; + const boost::asio::ip::udp::endpoint& GetEndpoint () const { return m_Endpoint; }; void Send (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& to); void AddRelay (uint32_t tag, std::shared_ptr relay); void RemoveRelay (uint32_t tag); @@ -68,7 +68,7 @@ namespace transport std::shared_ptr GetPeerTestSession (uint32_t nonce); void UpdatePeerTest (uint32_t nonce, PeerTestParticipant role); void RemovePeerTest (uint32_t nonce); - + private: void OpenSocket (); @@ -84,13 +84,13 @@ namespace transport void HandleReceivedPackets (std::vector packets, std::map >* sessions); - void CreateSessionThroughIntroducer (std::shared_ptr router, bool peerTest = false); + void CreateSessionThroughIntroducer (std::shared_ptr router, bool peerTest = false); template std::shared_ptr GetRandomV4Session (Filter filter); template - std::shared_ptr GetRandomV6Session (Filter filter); + std::shared_ptr GetRandomV6Session (Filter filter); - std::set FindIntroducers (int maxNumIntroducers); + std::set FindIntroducers (int maxNumIntroducers); void ScheduleIntroducersUpdateTimer (); void HandleIntroducersUpdateTimer (const boost::system::error_code& ecode); @@ -111,10 +111,10 @@ namespace transport PeerTestParticipant role; std::shared_ptr session; // for Bob to Alice }; - - bool m_OnlyV6; + + bool m_OnlyV6; bool m_IsRunning; - std::thread * m_Thread, * m_ThreadV6, * m_ReceiversThread, * m_ReceiversThreadV6; + std::thread * m_Thread, * m_ThreadV6, * m_ReceiversThread, * m_ReceiversThreadV6; boost::asio::io_service m_Service, m_ServiceV6, m_ReceiversService, m_ReceiversServiceV6; boost::asio::io_service::work m_Work, m_WorkV6, m_ReceiversWork, m_ReceiversWorkV6; boost::asio::ip::udp::endpoint m_Endpoint, m_EndpointV6; @@ -125,7 +125,7 @@ namespace transport std::map > m_Sessions, m_SessionsV6; std::map > m_Relays; // we are introducer std::map m_PeerTests; // nonce -> creation time in milliseconds - + public: // for HTTP only const decltype(m_Sessions)& GetSessions () const { return m_Sessions; }; diff --git a/libi2pd/SSUData.cpp b/libi2pd/SSUData.cpp index 67394d98..d789e70e 100644 --- a/libi2pd/SSUData.cpp +++ b/libi2pd/SSUData.cpp @@ -28,9 +28,9 @@ namespace transport } SSUData::SSUData (SSUSession& session): - m_Session (session), m_ResendTimer (session.GetService ()), - m_IncompleteMessagesCleanupTimer (session.GetService ()), - m_MaxPacketSize (session.IsV6 () ? SSU_V6_MAX_PACKET_SIZE : SSU_V4_MAX_PACKET_SIZE), + m_Session (session), m_ResendTimer (session.GetService ()), + m_IncompleteMessagesCleanupTimer (session.GetService ()), + m_MaxPacketSize (session.IsV6 () ? SSU_V6_MAX_PACKET_SIZE : SSU_V4_MAX_PACKET_SIZE), m_PacketSize (m_MaxPacketSize), m_LastMessageReceivedTime (0) { } @@ -42,8 +42,8 @@ namespace transport void SSUData::Start () { ScheduleIncompleteMessagesCleanup (); - } - + } + void SSUData::Stop () { m_ResendTimer.cancel (); @@ -51,8 +51,8 @@ namespace transport m_IncompleteMessages.clear (); m_SentMessages.clear (); m_ReceivedMessages.clear (); - } - + } + void SSUData::AdjustPacketSize (std::shared_ptr remoteRouter) { if (!remoteRouter) return; @@ -72,16 +72,16 @@ namespace transport LogPrint (eLogDebug, "SSU: MTU=", ssuAddress->ssu->mtu, " packet size=", m_PacketSize); } else - { + { LogPrint (eLogWarning, "SSU: Unexpected MTU ", ssuAddress->ssu->mtu); m_PacketSize = m_MaxPacketSize; - } - } + } + } } void SSUData::UpdatePacketSize (const i2p::data::IdentHash& remoteIdent) { - auto routerInfo = i2p::data::netdb.FindRouter (remoteIdent); + auto routerInfo = i2p::data::netdb.FindRouter (remoteIdent); if (routerInfo) AdjustPacketSize (routerInfo); } @@ -91,11 +91,11 @@ namespace transport auto it = m_SentMessages.find (msgID); if (it != m_SentMessages.end ()) { - m_SentMessages.erase (it); + m_SentMessages.erase (it); if (m_SentMessages.empty ()) m_ResendTimer.cancel (); } - } + } void SSUData::ProcessAcks (uint8_t *& buf, uint8_t flag) { @@ -117,7 +117,7 @@ namespace transport { uint32_t msgID = bufbe32toh (buf); buf += 4; // msgID - auto it = m_SentMessages.find (msgID); + auto it = m_SentMessages.find (msgID); // process individual Ack bitfields bool isNonLast = false; int fragment = 0; @@ -127,26 +127,26 @@ namespace transport isNonLast = bitfield & 0x80; bitfield &= 0x7F; // clear MSB if (bitfield && it != m_SentMessages.end ()) - { - int numSentFragments = it->second->fragments.size (); + { + int numSentFragments = it->second->fragments.size (); // process bits uint8_t mask = 0x01; for (int j = 0; j < 7; j++) - { + { if (bitfield & mask) { if (fragment < numSentFragments) it->second->fragments[fragment].reset (nullptr); - } + } fragment++; mask <<= 1; } - } + } buf++; } - while (isNonLast); - } - } + while (isNonLast); + } + } } void SSUData::ProcessFragments (uint8_t * buf) @@ -154,7 +154,7 @@ namespace transport uint8_t numFragments = *buf; // number of fragments buf++; for (int i = 0; i < numFragments; i++) - { + { uint32_t msgID = bufbe32toh (buf); // message ID buf += 4; uint8_t frag[4] = {0}; @@ -162,8 +162,8 @@ namespace transport buf += 3; uint32_t fragmentInfo = bufbe32toh (frag); // fragment info uint16_t fragmentSize = fragmentInfo & 0x3FFF; // bits 0 - 13 - bool isLast = fragmentInfo & 0x010000; // bit 16 - uint8_t fragmentNum = fragmentInfo >> 17; // bits 23 - 17 + bool isLast = fragmentInfo & 0x010000; // bit 16 + uint8_t fragmentNum = fragmentInfo >> 17; // bits 23 - 17 if (fragmentSize >= SSU_V4_MAX_PACKET_SIZE) { LogPrint (eLogError, "SSU: Fragment size ", fragmentSize, " exceeds max SSU packet size"); @@ -172,12 +172,12 @@ namespace transport // find message with msgID auto it = m_IncompleteMessages.find (msgID); - if (it == m_IncompleteMessages.end ()) + if (it == m_IncompleteMessages.end ()) { // create new message auto msg = NewI2NPShortMessage (); msg->len -= I2NP_SHORT_HEADER_SIZE; - it = m_IncompleteMessages.insert (std::make_pair (msgID, + it = m_IncompleteMessages.insert (std::make_pair (msgID, std::unique_ptr(new IncompleteMessage (msg)))).first; } std::unique_ptr& incompleteMessage = it->second; @@ -204,10 +204,10 @@ namespace transport } if (isLast) LogPrint (eLogDebug, "SSU: Message ", msgID, " complete"); - } - } + } + } else - { + { if (fragmentNum < incompleteMessage->nextFragmentNum) // duplicate fragment LogPrint (eLogWarning, "SSU: Duplicate fragment ", (int)fragmentNum, " of message ", msgID, ", ignored"); @@ -218,28 +218,28 @@ namespace transport auto savedFragment = new Fragment (fragmentNum, buf, fragmentSize, isLast); if (incompleteMessage->savedFragments.insert (std::unique_ptr(savedFragment)).second) incompleteMessage->lastFragmentInsertTime = i2p::util::GetSecondsSinceEpoch (); - else + else LogPrint (eLogWarning, "SSU: Fragment ", (int)fragmentNum, " of message ", msgID, " already saved"); } isLast = false; - } + } if (isLast) { // delete incomplete message auto msg = incompleteMessage->msg; incompleteMessage->msg = nullptr; - m_IncompleteMessages.erase (msgID); + m_IncompleteMessages.erase (msgID); // process message SendMsgAck (msgID); msg->FromSSU (msgID); if (m_Session.GetState () == eSessionStateEstablished) { if (!m_ReceivedMessages.count (msgID)) - { + { m_ReceivedMessages.insert (msgID); m_LastMessageReceivedTime = i2p::util::GetSecondsSinceEpoch (); - if (!msg->IsExpired ()) + if (!msg->IsExpired ()) { #ifdef WITH_EVENTS QueueIntEvent("transport.recvmsg", m_Session.GetIdentHashBase64(), 1); @@ -248,10 +248,10 @@ namespace transport } else LogPrint (eLogDebug, "SSU: message expired"); - } + } else LogPrint (eLogWarning, "SSU: Message ", msgID, " already received"); - } + } else { // we expect DeliveryStatus @@ -259,22 +259,22 @@ namespace transport { LogPrint (eLogDebug, "SSU: session established"); m_Session.Established (); - } + } else LogPrint (eLogError, "SSU: unexpected message ", (int)msg->GetTypeID ()); - } - } + } + } else - SendFragmentAck (msgID, fragmentNum); + SendFragmentAck (msgID, fragmentNum); buf += fragmentSize; - } + } } void SSUData::FlushReceivedMessage () { m_Handler.Flush (); - } - + } + void SSUData::ProcessMessage (uint8_t * buf, size_t len) { //uint8_t * start = buf; @@ -303,25 +303,25 @@ namespace transport { LogPrint (eLogWarning, "SSU: message ", msgID, " already sent"); return; - } + } if (m_SentMessages.empty ()) // schedule resend at first message only ScheduleResend (); - - auto ret = m_SentMessages.insert (std::make_pair (msgID, std::unique_ptr(new SentMessage))); + + auto ret = m_SentMessages.insert (std::make_pair (msgID, std::unique_ptr(new SentMessage))); std::unique_ptr& sentMessage = ret.first->second; - if (ret.second) + if (ret.second) { sentMessage->nextResendTime = i2p::util::GetSecondsSinceEpoch () + RESEND_INTERVAL; sentMessage->numResends = 0; - } + } auto& fragments = sentMessage->fragments; - size_t payloadSize = m_PacketSize - sizeof (SSUHeader) - 9; // 9 = flag + #frg(1) + messageID(4) + frag info (3) + size_t payloadSize = m_PacketSize - sizeof (SSUHeader) - 9; // 9 = flag + #frg(1) + messageID(4) + frag info (3) size_t len = msg->GetLength (); uint8_t * msgBuf = msg->GetSSUHeader (); uint32_t fragmentNum = 0; while (len > 0) - { + { Fragment * fragment = new Fragment; fragment->fragmentNum = fragmentNum; uint8_t * buf = fragment->buf; @@ -337,39 +337,39 @@ namespace transport uint32_t fragmentInfo = (fragmentNum << 17); if (isLast) fragmentInfo |= 0x010000; - + fragmentInfo |= size; fragmentInfo = htobe32 (fragmentInfo); memcpy (payload, (uint8_t *)(&fragmentInfo) + 1, 3); payload += 3; memcpy (payload, msgBuf, size); - + size += payload - buf; if (size & 0x0F) // make sure 16 bytes boundary size = ((size >> 4) + 1) << 4; // (/16 + 1)*16 - fragment->len = size; + fragment->len = size; fragments.push_back (std::unique_ptr (fragment)); - + // encrypt message with session key m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, size); try - { + { m_Session.Send (buf, size); } catch (boost::system::system_error& ec) { LogPrint (eLogWarning, "SSU: Can't send data fragment ", ec.what ()); - } + } if (!isLast) - { + { len -= payloadSize; msgBuf += payloadSize; - } + } else len = 0; fragmentNum++; - } - } + } + } void SSUData::SendMsgAck (uint32_t msgID) { @@ -398,27 +398,27 @@ namespace transport uint8_t buf[64 + 18] = {0}; uint8_t * payload = buf + sizeof (SSUHeader); *payload = DATA_FLAG_ACK_BITFIELDS_INCLUDED; // flag - payload++; + payload++; *payload = 1; // number of ACK bitfields payload++; // one ack - *(uint32_t *)(payload) = htobe32 (msgID); // msgID + *(uint32_t *)(payload) = htobe32 (msgID); // msgID payload += 4; div_t d = div (fragmentNum, 7); memset (payload, 0x80, d.quot); // 0x80 means non-last - payload += d.quot; + payload += d.quot; *payload = 0x01 << d.rem; // set corresponding bit payload++; *payload = 0; // number of fragments - size_t len = d.quot < 4 ? 48 : 64; // 48 = 37 + 7 + 4 (3+1) + size_t len = d.quot < 4 ? 48 : 64; // 48 = 37 + 7 + 4 (3+1) // encrypt message with session key m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, len); m_Session.Send (buf, len); - } + } void SSUData::ScheduleResend() - { + { m_ResendTimer.cancel (); m_ResendTimer.expires_from_now (boost::posix_time::seconds(RESEND_INTERVAL)); auto s = m_Session.shared_from_this(); @@ -435,7 +435,7 @@ namespace transport for (auto it = m_SentMessages.begin (); it != m_SentMessages.end ();) { if (ts >= it->second->nextResendTime) - { + { if (it->second->numResends < MAX_NUM_RESENDS) { for (auto& f: it->second->fragments) @@ -455,13 +455,13 @@ namespace transport it->second->numResends++; it->second->nextResendTime += it->second->numResends*RESEND_INTERVAL; ++it; - } + } else { LogPrint (eLogInfo, "SSU: message has not been ACKed after ", MAX_NUM_RESENDS, " attempts, deleted"); it = m_SentMessages.erase (it); - } - } + } + } else ++it; } @@ -472,9 +472,9 @@ namespace transport { LogPrint (eLogError, "SSU: resend window exceeds max size. Session terminated"); m_Session.Close (); - } - } - } + } + } + } void SSUData::ScheduleIncompleteMessagesCleanup () { @@ -484,7 +484,7 @@ namespace transport m_IncompleteMessagesCleanupTimer.async_wait ([s](const boost::system::error_code& ecode) { s->m_Data.HandleIncompleteMessagesCleanupTimer (ecode); }); } - + void SSUData::HandleIncompleteMessagesCleanupTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) @@ -496,18 +496,18 @@ namespace transport { LogPrint (eLogWarning, "SSU: message ", it->first, " was not completed in ", INCOMPLETE_MESSAGES_CLEANUP_TIMEOUT, " seconds, deleted"); it = m_IncompleteMessages.erase (it); - } + } else ++it; - } + } // decay if (m_ReceivedMessages.size () > MAX_NUM_RECEIVED_MESSAGES || i2p::util::GetSecondsSinceEpoch () > m_LastMessageReceivedTime + DECAY_INTERVAL) m_ReceivedMessages.clear (); - + ScheduleIncompleteMessagesCleanup (); - } - } + } + } } } diff --git a/libi2pd/SSUData.h b/libi2pd/SSUData.h index 8f625fe1..fbd167bf 100644 --- a/libi2pd/SSUData.h +++ b/libi2pd/SSUData.h @@ -24,7 +24,7 @@ namespace transport const size_t SSU_MTU_V6 = 1488; #endif const size_t IPV4_HEADER_SIZE = 20; - const size_t IPV6_HEADER_SIZE = 40; + const size_t IPV6_HEADER_SIZE = 40; const size_t UDP_HEADER_SIZE = 8; const size_t SSU_V4_MAX_PACKET_SIZE = SSU_MTU_V4 - IPV4_HEADER_SIZE - UDP_HEADER_SIZE; // 1456 const size_t SSU_V6_MAX_PACKET_SIZE = SSU_MTU_V6 - IPV6_HEADER_SIZE - UDP_HEADER_SIZE; // 1440 @@ -40,7 +40,7 @@ namespace transport const uint8_t DATA_FLAG_REQUEST_PREVIOUS_ACKS = 0x08; const uint8_t DATA_FLAG_EXPLICIT_CONGESTION_NOTIFICATION = 0x10; const uint8_t DATA_FLAG_ACK_BITFIELDS_INCLUDED = 0x40; - const uint8_t DATA_FLAG_EXPLICIT_ACKS_INCLUDED = 0x80; + const uint8_t DATA_FLAG_EXPLICIT_ACKS_INCLUDED = 0x80; struct Fragment { @@ -50,27 +50,27 @@ namespace transport uint8_t buf[SSU_V4_MAX_PACKET_SIZE + 18]; // use biggest Fragment () = default; - Fragment (int n, const uint8_t * b, int l, bool last): - fragmentNum (n), len (l), isLast (last) { memcpy (buf, b, len); }; - }; + Fragment (int n, const uint8_t * b, int l, bool last): + fragmentNum (n), len (l), isLast (last) { memcpy (buf, b, len); }; + }; struct FragmentCmp { bool operator() (const std::unique_ptr& f1, const std::unique_ptr& f2) const - { - return f1->fragmentNum < f2->fragmentNum; + { + return f1->fragmentNum < f2->fragmentNum; }; - }; - + }; + struct IncompleteMessage { std::shared_ptr msg; - int nextFragmentNum; + int nextFragmentNum; uint32_t lastFragmentInsertTime; // in seconds std::set, FragmentCmp> savedFragments; - + IncompleteMessage (std::shared_ptr m): msg (m), nextFragmentNum (0), lastFragmentInsertTime (0) {}; - void AttachNextFragment (const uint8_t * fragment, size_t fragmentSize); + void AttachNextFragment (const uint8_t * fragment, size_t fragmentSize); }; struct SentMessage @@ -78,24 +78,24 @@ namespace transport std::vector > fragments; uint32_t nextResendTime; // in seconds int numResends; - }; - + }; + class SSUSession; class SSUData { public: - SSUData (SSUSession& session); + SSUData (SSUSession& session); ~SSUData (); void Start (); - void Stop (); - + void Stop (); + void ProcessMessage (uint8_t * buf, size_t len); void FlushReceivedMessage (); void Send (std::shared_ptr msg); - void AdjustPacketSize (std::shared_ptr remoteRouter); + void AdjustPacketSize (std::shared_ptr remoteRouter); void UpdatePacketSize (const i2p::data::IdentHash& remoteIdent); private: @@ -104,16 +104,16 @@ namespace transport void SendFragmentAck (uint32_t msgID, int fragmentNum); void ProcessAcks (uint8_t *& buf, uint8_t flag); void ProcessFragments (uint8_t * buf); - void ProcessSentMessageAck (uint32_t msgID); + void ProcessSentMessageAck (uint32_t msgID); void ScheduleResend (); - void HandleResendTimer (const boost::system::error_code& ecode); + void HandleResendTimer (const boost::system::error_code& ecode); void ScheduleIncompleteMessagesCleanup (); - void HandleIncompleteMessagesCleanupTimer (const boost::system::error_code& ecode); - - - private: + void HandleIncompleteMessagesCleanupTimer (const boost::system::error_code& ecode); + + + private: SSUSession& m_Session; std::map > m_IncompleteMessages; @@ -123,7 +123,7 @@ namespace transport int m_MaxPacketSize, m_PacketSize; i2p::I2NPMessagesHandler m_Handler; uint32_t m_LastMessageReceivedTime; // in second - }; + }; } } diff --git a/libi2pd/SSUSession.cpp b/libi2pd/SSUSession.cpp index b7493814..2a8cd2d5 100644 --- a/libi2pd/SSUSession.cpp +++ b/libi2pd/SSUSession.cpp @@ -13,12 +13,12 @@ namespace i2p namespace transport { SSUSession::SSUSession (SSUServer& server, boost::asio::ip::udp::endpoint& remoteEndpoint, - std::shared_ptr router, bool peerTest ): - TransportSession (router, SSU_TERMINATION_TIMEOUT), - m_Server (server), m_RemoteEndpoint (remoteEndpoint), m_ConnectTimer (GetService ()), - m_IsPeerTest (peerTest),m_State (eSessionStateUnknown), m_IsSessionKey (false), + std::shared_ptr router, bool peerTest ): + TransportSession (router, SSU_TERMINATION_TIMEOUT), + m_Server (server), m_RemoteEndpoint (remoteEndpoint), m_ConnectTimer (GetService ()), + m_IsPeerTest (peerTest),m_State (eSessionStateUnknown), m_IsSessionKey (false), m_RelayTag (0), m_SentRelayTag (0), m_Data (*this), m_IsDataReceived (false) - { + { if (router) { // we are client @@ -36,14 +36,14 @@ namespace transport } SSUSession::~SSUSession () - { - } - - boost::asio::io_service& SSUSession::GetService () - { - return IsV6 () ? m_Server.GetServiceV6 () : m_Server.GetService (); + { } - + + boost::asio::io_service& SSUSession::GetService () + { + return IsV6 () ? m_Server.GetServiceV6 () : m_Server.GetService (); + } + void SSUSession::CreateAESandMacKey (const uint8_t * pubKey) { uint8_t sharedKey[256]; @@ -55,14 +55,14 @@ namespace transport sessionKey[0] = 0; memcpy (sessionKey + 1, sharedKey, 31); memcpy (macKey, sharedKey + 31, 32); - } + } else if (sharedKey[0]) { memcpy (sessionKey, sharedKey, 32); memcpy (macKey, sharedKey + 32, 32); - } + } else - { + { // find first non-zero byte uint8_t * nonZero = sharedKey + 1; while (!*nonZero) @@ -72,16 +72,16 @@ namespace transport { LogPrint (eLogWarning, "SSU: first 32 bytes of shared key is all zeros. Ignored"); return; - } + } } - + memcpy (sessionKey, nonZero, 32); SHA256(nonZero, 64 - (nonZero - sharedKey), macKey); } m_IsSessionKey = true; m_SessionKeyEncryption.SetKey (m_SessionKey); m_SessionKeyDecryption.SetKey (m_SessionKey); - } + } void SSUSession::ProcessNextMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint) { @@ -96,40 +96,40 @@ namespace transport } else { - if (!len) return; // ignore zero-length packets + if (!len) return; // ignore zero-length packets if (m_State == eSessionStateEstablished) - m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); - + m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); + if (m_IsSessionKey && Validate (buf, len, m_MacKey)) // try session key first - DecryptSessionKey (buf, len); - else + DecryptSessionKey (buf, len); + else { - if (m_State == eSessionStateEstablished) Reset (); // new session key required + if (m_State == eSessionStateEstablished) Reset (); // new session key required // try intro key depending on side if (Validate (buf, len, m_IntroKey)) Decrypt (buf, len, m_IntroKey); else - { + { // try own intro key auto address = i2p::context.GetRouterInfo ().GetSSUAddress (false); if (!address) { LogPrint (eLogInfo, "SSU is not supported"); return; - } + } if (Validate (buf, len, address->ssu->key)) Decrypt (buf, len, address->ssu->key); else { LogPrint (eLogWarning, "SSU: MAC verification failed ", len, " bytes from ", senderEndpoint); - m_Server.DeleteSession (shared_from_this ()); + m_Server.DeleteSession (shared_from_this ()); return; - } - } - } + } + } + } // successfully decrypted ProcessMessage (buf, len, senderEndpoint); - } + } } size_t SSUSession::GetSSUHeaderSize (const uint8_t * buf) const @@ -158,14 +158,14 @@ namespace transport ProcessData (buf + headerSize, len - headerSize); break; case PAYLOAD_TYPE_SESSION_REQUEST: - ProcessSessionRequest (buf, len, senderEndpoint); // buf with header + ProcessSessionRequest (buf, len, senderEndpoint); // buf with header break; case PAYLOAD_TYPE_SESSION_CREATED: ProcessSessionCreated (buf, len); // buf with header break; case PAYLOAD_TYPE_SESSION_CONFIRMED: ProcessSessionConfirmed (buf, len); // buf with header - break; + break; case PAYLOAD_TYPE_PEER_TEST: LogPrint (eLogDebug, "SSU: peer test received"); ProcessPeerTest (buf + headerSize, len - headerSize, senderEndpoint); @@ -173,9 +173,9 @@ namespace transport case PAYLOAD_TYPE_SESSION_DESTROYED: { LogPrint (eLogDebug, "SSU: session destroy received"); - m_Server.DeleteSession (shared_from_this ()); + m_Server.DeleteSession (shared_from_this ()); break; - } + } case PAYLOAD_TYPE_RELAY_RESPONSE: ProcessRelayResponse (buf + headerSize, len - headerSize); if (m_State != eSessionStateEstablished) @@ -197,7 +197,7 @@ namespace transport void SSUSession::ProcessSessionRequest (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint) { LogPrint (eLogDebug, "SSU message: session request"); - bool sendRelayTag = true; + bool sendRelayTag = true; auto headerSize = sizeof (SSUHeader); if (((SSUHeader *)buf)->IsExtendedOptions ()) { @@ -206,14 +206,14 @@ namespace transport if (extendedOptionsLen >= 3) // options are presented { uint16_t flags = bufbe16toh (buf + headerSize); - sendRelayTag = flags & EXTENDED_OPTIONS_FLAG_REQUEST_RELAY_TAG; + sendRelayTag = flags & EXTENDED_OPTIONS_FLAG_REQUEST_RELAY_TAG; } headerSize += extendedOptionsLen; - } + } if (headerSize >= len) { LogPrint (eLogError, "Session reaquest header size ", headerSize, " exceeds packet length ", len); - return; + return; } m_RemoteEndpoint = senderEndpoint; if (!m_DHKeysPair) @@ -232,14 +232,14 @@ namespace transport LogPrint (eLogDebug, "SSU message: session created"); m_ConnectTimer.cancel (); // connect timer - SignedData s; // x,y, our IP, our port, remote IP, remote port, relayTag, signed on time - auto headerSize = GetSSUHeaderSize (buf); + SignedData s; // x,y, our IP, our port, remote IP, remote port, relayTag, signed on time + auto headerSize = GetSSUHeaderSize (buf); if (headerSize >= len) { LogPrint (eLogError, "Session created header size ", headerSize, " exceeds packet length ", len); - return; - } - uint8_t * payload = buf + headerSize; + return; + } + uint8_t * payload = buf + headerSize; uint8_t * y = payload; CreateAESandMacKey (y); s.Insert (m_DHKeysPair->GetPublicKey (), 256); // x @@ -250,18 +250,18 @@ namespace transport uint8_t * ourAddress = payload; boost::asio::ip::address ourIP; if (addressSize == 4) // v4 - { + { boost::asio::ip::address_v4::bytes_type bytes; memcpy (bytes.data (), ourAddress, 4); ourIP = boost::asio::ip::address_v4 (bytes); - } + } else // v6 { boost::asio::ip::address_v6::bytes_type bytes; memcpy (bytes.data (), ourAddress, 16); ourIP = boost::asio::ip::address_v6 (bytes); - } - s.Insert (ourAddress, addressSize); // our IP + } + s.Insert (ourAddress, addressSize); // our IP payload += addressSize; // address uint16_t ourPort = bufbe16toh (payload); s.Insert (payload, 2); // our port @@ -271,19 +271,19 @@ namespace transport else s.Insert (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), 16); // remote IP v6 s.Insert (htobe16 (m_RemoteEndpoint.port ())); // remote port - s.Insert (payload, 8); // relayTag and signed on time + s.Insert (payload, 8); // relayTag and signed on time m_RelayTag = bufbe32toh (payload); payload += 4; // relayTag if (i2p::context.GetStatus () == eRouterStatusTesting) - { + { auto ts = i2p::util::GetSecondsSinceEpoch (); uint32_t signedOnTime = bufbe32toh(payload); if (signedOnTime < ts - SSU_CLOCK_SKEW || signedOnTime > ts + SSU_CLOCK_SKEW) { - LogPrint (eLogError, "SSU: clock skew detected ", (int)ts - signedOnTime, ". Check your clock"); + LogPrint (eLogError, "SSU: clock skew detected ", (int)ts - signedOnTime, ". Check your clock"); i2p::context.SetError (eRouterErrorClockSkew); } - } + } payload += 4; // signed on time // decrypt signature size_t signatureLen = m_RemoteIdentity->GetSignatureLen (); @@ -304,34 +304,34 @@ namespace transport LogPrint (eLogError, "SSU: message 'created' signature verification failed"); Failed (); } - } + } void SSUSession::ProcessSessionConfirmed (const uint8_t * buf, size_t len) { - LogPrint (eLogDebug, "SSU: Session confirmed received"); - auto headerSize = GetSSUHeaderSize (buf); + LogPrint (eLogDebug, "SSU: Session confirmed received"); + auto headerSize = GetSSUHeaderSize (buf); if (headerSize >= len) { LogPrint (eLogError, "SSU: Session confirmed header size ", len, " exceeds packet length ", len); - return; - } + return; + } const uint8_t * payload = buf + headerSize; payload++; // identity fragment info - uint16_t identitySize = bufbe16toh (payload); + uint16_t identitySize = bufbe16toh (payload); payload += 2; // size of identity fragment auto identity = std::make_shared (payload, identitySize); auto existing = i2p::data::netdb.FindRouter (identity->GetIdentHash ()); // check if exists already SetRemoteIdentity (existing ? existing->GetRouterIdentity () : identity); m_Data.UpdatePacketSize (m_RemoteIdentity->GetIdentHash ()); - payload += identitySize; // identity + payload += identitySize; // identity auto ts = i2p::util::GetSecondsSinceEpoch (); - uint32_t signedOnTime = bufbe32toh(payload); + uint32_t signedOnTime = bufbe32toh(payload); if (signedOnTime < ts - SSU_CLOCK_SKEW || signedOnTime > ts + SSU_CLOCK_SKEW) { - LogPrint (eLogError, "SSU message 'confirmed' time difference ", (int)ts - signedOnTime, " exceeds clock skew"); + LogPrint (eLogError, "SSU message 'confirmed' time difference ", (int)ts - signedOnTime, " exceeds clock skew"); Failed (); return; - } + } if (m_SignedData) m_SignedData->Insert (payload, 4); // insert Alice's signed on time payload += 4; // signed-on time @@ -345,7 +345,7 @@ namespace transport m_Data.Send (CreateDeliveryStatusMsg (0)); Established (); } - else + else { LogPrint (eLogError, "SSU message 'confirmed' signature verification failed"); Failed (); @@ -353,33 +353,33 @@ namespace transport } void SSUSession::SendSessionRequest () - { + { uint8_t buf[320 + 18] = {0}; // 304 bytes for ipv4, 320 for ipv6 uint8_t * payload = buf + sizeof (SSUHeader); uint8_t flag = 0; // fill extended options, 3 bytes extended options don't change message size if (i2p::context.GetStatus () == eRouterStatusOK) // we don't need relays - { + { // tell out peer to now assign relay tag flag = SSU_HEADER_EXTENDED_OPTIONS_INCLUDED; *payload = 2; payload++; // 1 byte length uint16_t flags = 0; // clear EXTENDED_OPTIONS_FLAG_REQUEST_RELAY_TAG - htobe16buf (payload, flags); + htobe16buf (payload, flags); payload += 2; - } + } // fill payload memcpy (payload, m_DHKeysPair->GetPublicKey (), 256); // x bool isV4 = m_RemoteEndpoint.address ().is_v4 (); if (isV4) { - payload[256] = 4; - memcpy (payload + 257, m_RemoteEndpoint.address ().to_v4 ().to_bytes ().data(), 4); + payload[256] = 4; + memcpy (payload + 257, m_RemoteEndpoint.address ().to_v4 ().to_bytes ().data(), 4); } else { - payload[256] = 16; - memcpy (payload + 257, m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data(), 16); - } + payload[256] = 16; + memcpy (payload + 257, m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data(), 16); + } // encrypt and send uint8_t iv[16]; RAND_bytes (iv, 16); // random iv @@ -395,7 +395,7 @@ namespace transport LogPrint (eLogInfo, "SSU is not supported"); return; } - + uint8_t buf[96 + 18] = {0}; uint8_t * payload = buf + sizeof (SSUHeader); htobe32buf (payload, introducer.iTag); @@ -405,17 +405,17 @@ namespace transport htobuf16(payload, 0); // port = 0 payload += 2; *payload = 0; // challenge - payload++; + payload++; memcpy (payload, (const uint8_t *)address->ssu->key, 32); payload += 32; - htobe32buf (payload, nonce); // nonce + htobe32buf (payload, nonce); // nonce uint8_t iv[16]; RAND_bytes (iv, 16); // random iv if (m_State == eSessionStateEstablished) FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_REQUEST, buf, 96, m_SessionKey, iv, m_MacKey); else - FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_REQUEST, buf, 96, introducer.iKey, iv, introducer.iKey); + FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_REQUEST, buf, 96, introducer.iKey, iv, introducer.iKey); m_Server.Send (buf, 96, m_RemoteEndpoint); } @@ -428,7 +428,7 @@ namespace transport LogPrint (eLogInfo, "SSU is not supported"); return; } - SignedData s; // x,y, remote IP, remote port, our IP, our port, relayTag, signed on time + SignedData s; // x,y, remote IP, remote port, our IP, our port, relayTag, signed on time s.Insert (x, 256); // x uint8_t buf[384 + 18] = {0}; @@ -441,7 +441,7 @@ namespace transport // ipv4 *payload = 4; payload++; - memcpy (payload, m_RemoteEndpoint.address ().to_v4 ().to_bytes ().data(), 4); + memcpy (payload, m_RemoteEndpoint.address ().to_v4 ().to_bytes ().data(), 4); s.Insert (payload, 4); // remote endpoint IP V4 payload += 4; } @@ -450,7 +450,7 @@ namespace transport // ipv6 *payload = 16; payload++; - memcpy (payload, m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data(), 16); + memcpy (payload, m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data(), 16); s.Insert (payload, 16); // remote endpoint IP V6 payload += 16; } @@ -467,20 +467,20 @@ namespace transport RAND_bytes((uint8_t *)&m_SentRelayTag, 4); if (!m_SentRelayTag) m_SentRelayTag = 1; } - htobe32buf (payload, m_SentRelayTag); - payload += 4; // relay tag + htobe32buf (payload, m_SentRelayTag); + payload += 4; // relay tag htobe32buf (payload, i2p::util::GetSecondsSinceEpoch ()); // signed on time payload += 4; - s.Insert (payload - 8, 4); // relayTag + s.Insert (payload - 8, 4); // relayTag // we have to store this signed data for session confirmed - // same data but signed on time, it will Alice's there - m_SignedData = std::unique_ptr(new SignedData (s)); - s.Insert (payload - 4, 4); // BOB's signed on time + // same data but signed on time, it will Alice's there + m_SignedData = std::unique_ptr(new SignedData (s)); + s.Insert (payload - 4, 4); // BOB's signed on time s.Sign (i2p::context.GetPrivateKeys (), payload); // DSA signature uint8_t iv[16]; RAND_bytes (iv, 16); // random iv - // encrypt signature and padding with newly created session key + // encrypt signature and padding with newly created session key size_t signatureLen = i2p::context.GetIdentity ()->GetSignatureLen (); size_t paddingSize = signatureLen & 0x0F; // %16 if (paddingSize > 0) @@ -493,9 +493,9 @@ namespace transport m_SessionKeyEncryption.Encrypt (payload, signatureLen, payload); payload += signatureLen; size_t msgLen = payload - buf; - + // encrypt message with intro key - FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_CREATED, buf, msgLen, m_IntroKey, iv, m_IntroKey); + FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_CREATED, buf, msgLen, m_IntroKey, iv, m_IntroKey); Send (buf, msgLen); } @@ -518,21 +518,21 @@ namespace transport if (paddingSize > 0) paddingSize = 16 - paddingSize; RAND_bytes(payload, paddingSize); // fill padding with random payload += paddingSize; // padding size - // signature - SignedData s; // x,y, our IP, our port, remote IP, remote port, relayTag, our signed on time + // signature + SignedData s; // x,y, our IP, our port, remote IP, remote port, relayTag, our signed on time s.Insert (m_DHKeysPair->GetPublicKey (), 256); // x s.Insert (y, 256); // y s.Insert (ourAddress, ourAddressLen); // our address/port as seem by party if (m_RemoteEndpoint.address ().is_v4 ()) s.Insert (m_RemoteEndpoint.address ().to_v4 ().to_bytes ().data (), 4); // remote IP V4 else - s.Insert (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), 16); // remote IP V6 + s.Insert (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), 16); // remote IP V6 s.Insert (htobe16 (m_RemoteEndpoint.port ())); // remote port s.Insert (htobe32 (m_RelayTag)); // relay tag s.Insert (htobe32 (signedOnTime)); // signed on time - s.Sign (i2p::context.GetPrivateKeys (), payload); // DSA signature + s.Sign (i2p::context.GetPrivateKeys (), payload); // DSA signature payload += signatureLen; - + size_t msgLen = payload - buf; uint8_t iv[16]; RAND_bytes (iv, 16); // random iv @@ -547,7 +547,7 @@ namespace transport auto session = m_Server.FindRelaySession (relayTag); if (session) { - buf += 4; // relay tag + buf += 4; // relay tag uint8_t size = *buf; buf++; // size buf += size; // address @@ -560,7 +560,7 @@ namespace transport uint32_t nonce = bufbe32toh (buf); SendRelayResponse (nonce, from, introKey, session->m_RemoteEndpoint); SendRelayIntro (session, from); - } + } } void SSUSession::SendRelayResponse (uint32_t nonce, const boost::asio::ip::udp::endpoint& from, @@ -577,7 +577,7 @@ namespace transport *payload = 4; payload++; // size htobe32buf (payload, to.address ().to_v4 ().to_ulong ()); // Charlie's IP - payload += 4; // address + payload += 4; // address htobe16buf (payload, to.port ()); // Charlie's port payload += 2; // port // Alice @@ -587,25 +587,25 @@ namespace transport *payload = 4; payload++; // size memcpy (payload, from.address ().to_v4 ().to_bytes ().data (), 4); // Alice's IP V4 - payload += 4; // address + payload += 4; // address } else { *payload = 16; payload++; // size memcpy (payload, from.address ().to_v6 ().to_bytes ().data (), 16); // Alice's IP V6 - payload += 16; // address + payload += 16; // address } htobe16buf (payload, from.port ()); // Alice's port payload += 2; // port - htobe32buf (payload, nonce); + htobe32buf (payload, nonce); if (m_State == eSessionStateEstablished) - { + { // encrypt with session key FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_RESPONSE, buf, isV4 ? 64 : 80); Send (buf, isV4 ? 64 : 80); - } + } else { // ecrypt with Alice's intro key @@ -613,45 +613,45 @@ namespace transport RAND_bytes (iv, 16); // random iv FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_RESPONSE, buf, isV4 ? 64 : 80, introKey, iv, introKey); m_Server.Send (buf, isV4 ? 64 : 80, from); - } + } LogPrint (eLogDebug, "SSU: relay response sent"); - } + } void SSUSession::SendRelayIntro (std::shared_ptr session, const boost::asio::ip::udp::endpoint& from) { - if (!session) return; + if (!session) return; // Alice's address always v4 if (!from.address ().is_v4 ()) { LogPrint (eLogWarning, "SSU: Alice's IP must be v4"); return; - } + } uint8_t buf[48 + 18] = {0}; uint8_t * payload = buf + sizeof (SSUHeader); *payload = 4; payload++; // size htobe32buf (payload, from.address ().to_v4 ().to_ulong ()); // Alice's IP - payload += 4; // address + payload += 4; // address htobe16buf (payload, from.port ()); // Alice's port payload += 2; // port - *payload = 0; // challenge size + *payload = 0; // challenge size uint8_t iv[16]; RAND_bytes (iv, 16); // random iv FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_INTRO, buf, 48, session->m_SessionKey, iv, session->m_MacKey); m_Server.Send (buf, 48, session->m_RemoteEndpoint); LogPrint (eLogDebug, "SSU: relay intro sent"); } - + void SSUSession::ProcessRelayResponse (const uint8_t * buf, size_t len) { - LogPrint (eLogDebug, "SSU message: Relay response received"); - uint8_t remoteSize = *buf; + LogPrint (eLogDebug, "SSU message: Relay response received"); + uint8_t remoteSize = *buf; buf++; // remote size boost::asio::ip::address_v4 remoteIP (bufbe32toh (buf)); buf += remoteSize; // remote address uint16_t remotePort = bufbe16toh (buf); buf += 2; // remote port - uint8_t ourSize = *buf; + uint8_t ourSize = *buf; buf++; // our size boost::asio::ip::address ourIP; if (ourSize == 4) @@ -675,7 +675,7 @@ namespace transport buf += 4; // nonce auto it = m_RelayRequests.find (nonce); if (it != m_RelayRequests.end ()) - { + { // check if we are waiting for introduction boost::asio::ip::udp::endpoint remoteEndpoint (remoteIP, remotePort); if (!m_Server.FindSession (remoteEndpoint)) @@ -686,10 +686,10 @@ namespace transport if (i2p::context.GetRouterInfo ().UsesIntroducer ()) // if we are unreachable m_Server.Send (buf, 0, remoteEndpoint); // send HolePunch m_Server.CreateDirectSession (it->second, remoteEndpoint, false); - } + } // delete request m_RelayRequests.erase (it); - } + } else LogPrint (eLogError, "SSU: Unsolicited RelayResponse, nonce=", nonce); } @@ -708,11 +708,11 @@ namespace transport } else LogPrint (eLogWarning, "SSU: Address size ", size, " is not supported"); - } + } - void SSUSession::FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, + void SSUSession::FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey, const uint8_t * iv, const i2p::crypto::MACKey& macKey, uint8_t flag) - { + { if (len < sizeof (SSUHeader)) { LogPrint (eLogError, "SSU: Unexpected packet length ", len); @@ -753,18 +753,18 @@ namespace transport memcpy (buf + len, header->iv, 16); htobe16buf (buf + len + 16, encryptedLen); i2p::crypto::HMACMD5Digest (encrypted, encryptedLen + 18, m_MacKey, header->mac); - } - + } + void SSUSession::Decrypt (uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey) { if (len < sizeof (SSUHeader)) { LogPrint (eLogError, "SSU: Unexpected packet length ", len); return; - } + } SSUHeader * header = (SSUHeader *)buf; uint8_t * encrypted = &header->flag; - uint16_t encryptedLen = len - (encrypted - buf); + uint16_t encryptedLen = len - (encrypted - buf); i2p::crypto::CBCDecryption decryption; decryption.SetKey (aesKey); decryption.SetIV (header->iv); @@ -777,24 +777,24 @@ namespace transport { LogPrint (eLogError, "SSU: Unexpected packet length ", len); return; - } + } SSUHeader * header = (SSUHeader *)buf; uint8_t * encrypted = &header->flag; - uint16_t encryptedLen = len - (encrypted - buf); + uint16_t encryptedLen = len - (encrypted - buf); if (encryptedLen > 0) - { + { m_SessionKeyDecryption.SetIV (header->iv); m_SessionKeyDecryption.Decrypt (encrypted, encryptedLen, encrypted); - } - } - + } + } + bool SSUSession::Validate (uint8_t * buf, size_t len, const i2p::crypto::MACKey& macKey) { if (len < sizeof (SSUHeader)) { LogPrint (eLogError, "SSU: Unexpected packet length ", len); return false; - } + } SSUHeader * header = (SSUHeader *)buf; uint8_t * encrypted = &header->flag; uint16_t encryptedLen = len - (encrypted - buf); @@ -809,12 +809,12 @@ namespace transport void SSUSession::Connect () { if (m_State == eSessionStateUnknown) - { + { // set connect timer ScheduleConnectTimer (); m_DHKeysPair = transports.GetNextDHKeysPair (); SendSessionRequest (); - } + } } void SSUSession::WaitForConnect () @@ -830,7 +830,7 @@ namespace transport m_ConnectTimer.cancel (); m_ConnectTimer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT)); m_ConnectTimer.async_wait (std::bind (&SSUSession::HandleConnectTimer, - shared_from_this (), std::placeholders::_1)); + shared_from_this (), std::placeholders::_1)); } void SSUSession::HandleConnectTimer (const boost::system::error_code& ecode) @@ -840,14 +840,14 @@ namespace transport // timeout expired LogPrint (eLogWarning, "SSU: session with ", m_RemoteEndpoint, " was not established after ", SSU_CONNECT_TIMEOUT, " seconds"); Failed (); - } - } - + } + } + void SSUSession::Introduce (const i2p::data::RouterInfo::Introducer& introducer, std::shared_ptr to) { if (m_State == eSessionStateUnknown) - { + { // set connect timer m_ConnectTimer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT)); m_ConnectTimer.async_wait (std::bind (&SSUSession::HandleConnectTimer, @@ -865,7 +865,7 @@ namespace transport // set connect timer m_ConnectTimer.expires_from_now (boost::posix_time::seconds(SSU_CONNECT_TIMEOUT)); m_ConnectTimer.async_wait (std::bind (&SSUSession::HandleConnectTimer, - shared_from_this (), std::placeholders::_1)); + shared_from_this (), std::placeholders::_1)); } void SSUSession::Close () @@ -873,7 +873,7 @@ namespace transport SendSessionDestroyed (); Reset (); m_State = eSessionStateClosed; - } + } void SSUSession::Reset () { @@ -882,10 +882,10 @@ namespace transport m_Data.Stop (); m_ConnectTimer.cancel (); if (m_SentRelayTag) - { + { m_Server.RemoveRelay (m_SentRelayTag); // relay tag is not valid anymore m_SentRelayTag = 0; - } + } m_DHKeysPair = nullptr; m_SignedData = nullptr; m_IsSessionKey = false; @@ -908,20 +908,20 @@ namespace transport if (m_SentRelayTag) m_Server.AddRelay (m_SentRelayTag, shared_from_this ()); m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); - } + } void SSUSession::Failed () { if (m_State != eSessionStateFailed) - { + { m_State = eSessionStateFailed; - m_Server.DeleteSession (shared_from_this ()); - } - } + m_Server.DeleteSession (shared_from_this ()); + } + } void SSUSession::SendI2NPMessages (const std::vector >& msgs) { - GetService ().post (std::bind (&SSUSession::PostI2NPMessages, shared_from_this (), msgs)); + GetService ().post (std::bind (&SSUSession::PostI2NPMessages, shared_from_this (), msgs)); } void SSUSession::PostI2NPMessages (std::vector > msgs) @@ -931,7 +931,7 @@ namespace transport for (const auto& it: msgs) if (it) m_Data.Send (it); } - } + } void SSUSession::ProcessData (uint8_t * buf, size_t len) { @@ -942,29 +942,29 @@ namespace transport void SSUSession::FlushData () { if (m_IsDataReceived) - { + { m_Data.FlushReceivedMessage (); m_IsDataReceived = false; - } + } } void SSUSession::ProcessPeerTest (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint) { uint32_t nonce = bufbe32toh (buf); // 4 bytes - uint8_t size = buf[4]; // 1 byte + uint8_t size = buf[4]; // 1 byte const uint8_t * address = buf + 5; // big endian, size bytes uint16_t port = buf16toh(buf + size + 5); // big endian, 2 bytes const uint8_t * introKey = buf + size + 7; - if (port && (size != 4) && (size != 16)) + if (port && (size != 4) && (size != 16)) { LogPrint (eLogWarning, "SSU: Address of ", size, " bytes not supported"); return; - } + } switch (m_Server.GetPeerTestParticipant (nonce)) - { - // existing test + { + // existing test case ePeerTestParticipantAlice1: - { + { if (m_Server.GetPeerTestSession (nonce) == shared_from_this ()) // Alice-Bob { LogPrint (eLogDebug, "SSU: peer test from Bob. We are Alice"); @@ -981,7 +981,7 @@ namespace transport SendPeerTest (nonce, senderEndpoint.address (), senderEndpoint.port (), introKey, true, false); // to Charlie } break; - } + } case ePeerTestParticipantAlice2: { if (m_Server.GetPeerTestSession (nonce) == shared_from_this ()) // Alice-Bob @@ -994,8 +994,8 @@ namespace transport m_Server.RemovePeerTest (nonce); } break; - } - case ePeerTestParticipantBob: + } + case ePeerTestParticipantBob: { LogPrint (eLogDebug, "SSU: peer test from Charlie. We are Bob"); auto session = m_Server.GetPeerTestSession (nonce); // session with Alice from PeerTest @@ -1005,13 +1005,13 @@ namespace transport break; } case ePeerTestParticipantCharlie: - { + { LogPrint (eLogDebug, "SSU: peer test from Alice. We are Charlie"); SendPeerTest (nonce, senderEndpoint.address (), senderEndpoint.port (), introKey); // to Alice with her actual address m_Server.RemovePeerTest (nonce); // nonce has been used break; } - // test not found + // test not found case ePeerTestParticipantUnknown: { if (m_State == eSessionStateEstablished) @@ -1034,7 +1034,7 @@ namespace transport boost::asio::ip::address_v6::bytes_type bytes; memcpy (bytes.data (), address, 16); addr = boost::asio::ip::address_v6 (bytes); - } + } SendPeerTest (nonce, addr, be16toh (port), introKey); // to Alice with her address received from Bob } else @@ -1044,26 +1044,26 @@ namespace transport if (session) { m_Server.NewPeerTest (nonce, ePeerTestParticipantBob, shared_from_this ()); - session->SendPeerTest (nonce, senderEndpoint.address (), senderEndpoint.port (), introKey, false); // to Charlie with Alice's actual address - } + session->SendPeerTest (nonce, senderEndpoint.address (), senderEndpoint.port (), introKey, false); // to Charlie with Alice's actual address + } } } else LogPrint (eLogError, "SSU: unexpected peer test"); } - } + } } - - void SSUSession::SendPeerTest (uint32_t nonce, const boost::asio::ip::address& address, uint16_t port, + + void SSUSession::SendPeerTest (uint32_t nonce, const boost::asio::ip::address& address, uint16_t port, const uint8_t * introKey, bool toAddress, bool sendAddress) // toAddress is true for Alice<->Chalie communications only - // sendAddress is false if message comes from Alice + // sendAddress is false if message comes from Alice { uint8_t buf[80 + 18] = {0}; uint8_t iv[16]; uint8_t * payload = buf + sizeof (SSUHeader); htobe32buf (payload, nonce); - payload += 4; // nonce + payload += 4; // nonce // address and port if (sendAddress) { @@ -1075,11 +1075,11 @@ namespace transport else if (address.is_v6 ()) { *payload = 16; - memcpy (payload + 1, address.to_v6 ().to_bytes ().data (), 16); // our IP V6 + memcpy (payload + 1, address.to_v6 ().to_bytes ().data (), 16); // our IP V6 } else *payload = 0; - payload += (payload[0] + 1); + payload += (payload[0] + 1); } else { @@ -1096,27 +1096,27 @@ namespace transport if (addr) memcpy (payload, addr->ssu->key, 32); // intro key else - LogPrint (eLogInfo, "SSU is not supported. Can't send peer test"); - } - else + LogPrint (eLogInfo, "SSU is not supported. Can't send peer test"); + } + else memcpy (payload, introKey, 32); // intro key - // send + // send RAND_bytes (iv, 16); // random iv if (toAddress) - { + { // encrypt message with specified intro key FillHeaderAndEncrypt (PAYLOAD_TYPE_PEER_TEST, buf, 80, introKey, iv, introKey); boost::asio::ip::udp::endpoint e (address, port); m_Server.Send (buf, 80, e); - } + } else { // encrypt message with session key FillHeaderAndEncrypt (PAYLOAD_TYPE_PEER_TEST, buf, 80); Send (buf, 80); } - } + } void SSUSession::SendPeerTest () { @@ -1134,23 +1134,23 @@ namespace transport m_IsPeerTest = false; m_Server.NewPeerTest (nonce, ePeerTestParticipantAlice1, shared_from_this ()); SendPeerTest (nonce, boost::asio::ip::address(), 0, address->ssu->key, false, false); // address and port always zero for Alice - } + } void SSUSession::SendKeepAlive () { if (m_State == eSessionStateEstablished) - { + { uint8_t buf[48 + 18] = {0}; uint8_t * payload = buf + sizeof (SSUHeader); *payload = 0; // flags payload++; - *payload = 0; // num fragments + *payload = 0; // num fragments // encrypt message with session key FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, 48); Send (buf, 48); LogPrint (eLogDebug, "SSU: keep-alive sent"); m_LastActivityTimestamp = i2p::util::GetSecondsSinceEpoch (); - } + } } void SSUSession::SendSessionDestroyed () @@ -1170,31 +1170,31 @@ namespace transport } LogPrint (eLogDebug, "SSU: session destroyed sent"); } - } + } void SSUSession::Send (uint8_t type, const uint8_t * payload, size_t len) { uint8_t buf[SSU_MTU_V4 + 18] = {0}; - size_t msgSize = len + sizeof (SSUHeader); + size_t msgSize = len + sizeof (SSUHeader); size_t paddingSize = msgSize & 0x0F; // %16 if (paddingSize > 0) msgSize += (16 - paddingSize); if (msgSize > SSU_MTU_V4) { LogPrint (eLogWarning, "SSU: payload size ", msgSize, " exceeds MTU"); return; - } + } memcpy (buf + sizeof (SSUHeader), payload, len); // encrypt message with session key FillHeaderAndEncrypt (type, buf, msgSize); Send (buf, msgSize); - } + } void SSUSession::Send (const uint8_t * buf, size_t size) { m_NumSentBytes += size; i2p::transport::transports.UpdateSentBytes (size); m_Server.Send (buf, size, m_RemoteEndpoint); - } + } } } diff --git a/libi2pd/SSUSession.h b/libi2pd/SSUSession.h index af13c645..8247c420 100644 --- a/libi2pd/SSUSession.h +++ b/libi2pd/SSUSession.h @@ -19,15 +19,15 @@ namespace transport uint8_t mac[16]; uint8_t iv[16]; uint8_t flag; - uint8_t time[4]; + uint8_t time[4]; uint8_t GetPayloadType () const { return flag >> 4; }; - bool IsExtendedOptions () const { return flag & SSU_HEADER_EXTENDED_OPTIONS_INCLUDED; }; + bool IsExtendedOptions () const { return flag & SSU_HEADER_EXTENDED_OPTIONS_INCLUDED; }; }; const int SSU_CONNECT_TIMEOUT = 5; // 5 seconds const int SSU_TERMINATION_TIMEOUT = 330; // 5.5 minutes - const int SSU_CLOCK_SKEW = 60; // in seconds + const int SSU_CLOCK_SKEW = 60; // in seconds // payload types (4 bits) const uint8_t PAYLOAD_TYPE_SESSION_REQUEST = 0; @@ -45,12 +45,12 @@ namespace transport enum SessionState { - eSessionStateUnknown, + eSessionStateUnknown, eSessionStateIntroduced, eSessionStateEstablished, eSessionStateClosed, eSessionStateFailed - }; + }; enum PeerTestParticipant { @@ -60,7 +60,7 @@ namespace transport ePeerTestParticipantBob, ePeerTestParticipantCharlie }; - + class SSUServer; class SSUSession: public TransportSession, public std::enable_shared_from_this { @@ -68,12 +68,12 @@ namespace transport SSUSession (SSUServer& server, boost::asio::ip::udp::endpoint& remoteEndpoint, std::shared_ptr router = nullptr, bool peerTest = false); - void ProcessNextMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); + void ProcessNextMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); ~SSUSession (); - + void Connect (); void WaitForConnect (); - void Introduce (const i2p::data::RouterInfo::Introducer& introducer, + void Introduce (const i2p::data::RouterInfo::Introducer& introducer, std::shared_ptr to); // Alice to Charlie void WaitForIntroduction (); void Close (); @@ -82,23 +82,23 @@ namespace transport boost::asio::ip::udp::endpoint& GetRemoteEndpoint () { return m_RemoteEndpoint; }; bool IsV6 () const { return m_RemoteEndpoint.address ().is_v6 (); }; void SendI2NPMessages (const std::vector >& msgs); - void SendPeerTest (); // Alice + void SendPeerTest (); // Alice SessionState GetState () const { return m_State; }; size_t GetNumSentBytes () const { return m_NumSentBytes; }; size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; - - void SendKeepAlive (); - uint32_t GetRelayTag () const { return m_RelayTag; }; + + void SendKeepAlive (); + uint32_t GetRelayTag () const { return m_RelayTag; }; const i2p::data::RouterInfo::IntroKey& GetIntroKey () const { return m_IntroKey; }; uint32_t GetCreationTime () const { return m_CreationTime; }; void FlushData (); - + private: boost::asio::io_service& GetService (); - void CreateAESandMacKey (const uint8_t * pubKey); + void CreateAESandMacKey (const uint8_t * pubKey); size_t GetSSUHeaderSize (const uint8_t * buf) const; void PostI2NPMessages (std::vector > msgs); void ProcessMessage (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); // call for established session @@ -119,23 +119,23 @@ namespace transport void ScheduleConnectTimer (); void HandleConnectTimer (const boost::system::error_code& ecode); void ProcessPeerTest (const uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& senderEndpoint); - void SendPeerTest (uint32_t nonce, const boost::asio::ip::address& address, uint16_t port, const uint8_t * introKey, bool toAddress = true, bool sendAddress = true); - void ProcessData (uint8_t * buf, size_t len); + void SendPeerTest (uint32_t nonce, const boost::asio::ip::address& address, uint16_t port, const uint8_t * introKey, bool toAddress = true, bool sendAddress = true); + void ProcessData (uint8_t * buf, size_t len); void SendSessionDestroyed (); void Send (uint8_t type, const uint8_t * payload, size_t len); // with session key - void Send (const uint8_t * buf, size_t size); - - void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey, + void Send (const uint8_t * buf, size_t size); + + void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey, const uint8_t * iv, const i2p::crypto::MACKey& macKey, uint8_t flag = 0); - void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len); // with session key + void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len); // with session key void Decrypt (uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey); void DecryptSessionKey (uint8_t * buf, size_t len); - bool Validate (uint8_t * buf, size_t len, const i2p::crypto::MACKey& macKey); + bool Validate (uint8_t * buf, size_t len, const i2p::crypto::MACKey& macKey); void Reset (); - + private: - + friend class SSUData; // TODO: change in later SSUServer& m_Server; boost::asio::ip::udp::endpoint m_RemoteEndpoint; diff --git a/libi2pd/Signature.cpp b/libi2pd/Signature.cpp index c5c2419b..aded9bc8 100644 --- a/libi2pd/Signature.cpp +++ b/libi2pd/Signature.cpp @@ -16,24 +16,24 @@ namespace crypto BIGNUM * tmp = BN_new (); q = BN_new (); - // 2^255-19 - BN_set_bit (q, 255); // 2^255 + // 2^255-19 + BN_set_bit (q, 255); // 2^255 BN_sub_word (q, 19); - + l = BN_new (); // 2^252 + 27742317777372353535851937790883648493 BN_set_bit (l, 252); two_252_2 = BN_dup (l); BN_dec2bn (&tmp, "27742317777372353535851937790883648493"); - BN_add (l, l, tmp); - BN_sub_word (two_252_2, 2); // 2^252 - 2 + BN_add (l, l, tmp); + BN_sub_word (two_252_2, 2); // 2^252 - 2 // -121665*inv(121666) d = BN_new (); BN_set_word (tmp, 121666); - BN_mod_inverse (tmp, tmp, q, ctx); + BN_mod_inverse (tmp, tmp, q, ctx); BN_set_word (d, 121665); - BN_set_negative (d, 1); + BN_set_negative (d, 1); BN_mul (d, d, tmp, ctx); // 2^((q-1)/4) @@ -41,20 +41,20 @@ namespace crypto BN_free (tmp); tmp = BN_dup (q); BN_sub_word (tmp, 1); - BN_div_word (tmp, 4); + BN_div_word (tmp, 4); BN_set_word (I, 2); BN_mod_exp (I, I, tmp, q, ctx); - BN_free (tmp); - - // 4*inv(5) - BIGNUM * By = BN_new (); + BN_free (tmp); + + // 4*inv(5) + BIGNUM * By = BN_new (); BN_set_word (By, 5); - BN_mod_inverse (By, By, q, ctx); + BN_mod_inverse (By, By, q, ctx); BN_mul_word (By, 4); - BIGNUM * Bx = RecoverX (By, ctx); + BIGNUM * Bx = RecoverX (By, ctx); BN_mod (Bx, Bx, q, ctx); // % q - BN_mod (By, By, q, ctx); // % q - + BN_mod (By, By, q, ctx); // % q + // precalculate Bi256 table Bi256Carry = { Bx, By }; // B for (int i = 0; i < 32; i++) @@ -70,7 +70,7 @@ namespace crypto BN_CTX_free (ctx); } - Ed25519 (const Ed25519& other): q (BN_dup (other.q)), l (BN_dup (other.l)), + Ed25519 (const Ed25519& other): q (BN_dup (other.q)), l (BN_dup (other.l)), d (BN_dup (other.d)), I (BN_dup (other.I)), two_252_2 (BN_dup (other.two_252_2)), Bi256Carry (other.Bi256Carry) { @@ -106,9 +106,9 @@ namespace crypto bool Verify (const EDDSAPoint& publicKey, const uint8_t * digest, const uint8_t * signature) const { - BN_CTX * ctx = BN_CTX_new (); + BN_CTX * ctx = BN_CTX_new (); BIGNUM * h = DecodeBN<64> (digest); - // signature 0..31 - R, 32..63 - S + // signature 0..31 - R, 32..63 - S // B*S = R + PK*h => R = B*S - PK*h // we don't decode R, but encode (B*S - PK*h) auto Bs = MulB (signature + EDDSA25519_SIGNATURE_LENGTH/2, ctx); // B*S; @@ -117,14 +117,14 @@ namespace crypto uint8_t diff[32]; EncodePoint (Normalize (Sum (Bs, -PKh, ctx), ctx), diff); // Bs - PKh encoded bool passed = !memcmp (signature, diff, 32); // R - BN_free (h); + BN_free (h); BN_CTX_free (ctx); if (!passed) LogPrint (eLogError, "25519 signature verification failed"); - return passed; + return passed; } - void Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len, + void Sign (const uint8_t * expandedPrivateKey, const uint8_t * publicKeyEncoded, const uint8_t * buf, size_t len, uint8_t * signature) const { BN_CTX * bnCtx = BN_CTX_new (); @@ -138,14 +138,14 @@ namespace crypto BIGNUM * r = DecodeBN<32> (digest); // DecodeBN<64> (digest); // for test vectors // calculate R uint8_t R[EDDSA25519_SIGNATURE_LENGTH/2]; // we must use separate buffer because signature might be inside buf - EncodePoint (Normalize (MulB (digest, bnCtx), bnCtx), R); // EncodePoint (Mul (B, r, bnCtx), R); // for test vectors + EncodePoint (Normalize (MulB (digest, bnCtx), bnCtx), R); // EncodePoint (Mul (B, r, bnCtx), R); // for test vectors // calculate S SHA512_Init (&ctx); SHA512_Update (&ctx, R, EDDSA25519_SIGNATURE_LENGTH/2); // R SHA512_Update (&ctx, publicKeyEncoded, EDDSA25519_PUBLIC_KEY_LENGTH); // public key SHA512_Update (&ctx, buf, len); // data SHA512_Final (digest, &ctx); - BIGNUM * h = DecodeBN<64> (digest); + BIGNUM * h = DecodeBN<64> (digest); // S = (r + h*a) % l BIGNUM * a = DecodeBN (expandedPrivateKey); // left half of expanded key BN_mod_mul (h, h, a, l, bnCtx); // %l @@ -156,7 +156,7 @@ namespace crypto BN_CTX_free (bnCtx); } - private: + private: EDDSAPoint Sum (const EDDSAPoint& p1, const EDDSAPoint& p2, BN_CTX * ctx) const { @@ -165,9 +165,9 @@ namespace crypto // z3 = (z1*z2-d*t1*t2)*(z1*z2+d*t1*t2) // t3 = (y1*y2+x1*x2)*(x1*y2+y1*x2) BIGNUM * x3 = BN_new (), * y3 = BN_new (), * z3 = BN_new (), * t3 = BN_new (); - - BN_mul (x3, p1.x, p2.x, ctx); // A = x1*x2 - BN_mul (y3, p1.y, p2.y, ctx); // B = y1*y2 + + BN_mul (x3, p1.x, p2.x, ctx); // A = x1*x2 + BN_mul (y3, p1.y, p2.y, ctx); // B = y1*y2 BN_CTX_start (ctx); BIGNUM * t1 = p1.t, * t2 = p2.t; @@ -189,10 +189,10 @@ namespace crypto BN_copy (z3, p2.z); // D = z2 else BN_one (z3); // D = 1 - } + } BIGNUM * E = BN_CTX_get (ctx), * F = BN_CTX_get (ctx), * G = BN_CTX_get (ctx), * H = BN_CTX_get (ctx); - BN_add (E, p1.x, p1.y); + BN_add (E, p1.x, p1.y); BN_add (F, p2.x, p2.y); BN_mul (E, E, F, ctx); // (x1 + y1)*(x2 + y2) BN_sub (E, E, x3); @@ -202,9 +202,9 @@ namespace crypto BN_add (H, y3, x3); // H = B + A BN_mod_mul (x3, E, F, q, ctx); // x3 = E*F - BN_mod_mul (y3, G, H, q, ctx); // y3 = G*H - BN_mod_mul (z3, F, G, q, ctx); // z3 = F*G - BN_mod_mul (t3, E, H, q, ctx); // t3 = E*H + BN_mod_mul (y3, G, H, q, ctx); // y3 = G*H + BN_mod_mul (z3, F, G, q, ctx); // z3 = F*G + BN_mod_mul (t3, E, H, q, ctx); // t3 = E*H BN_CTX_end (ctx); @@ -215,40 +215,40 @@ namespace crypto { BN_CTX_start (ctx); BIGNUM * x2 = BN_CTX_get (ctx), * y2 = BN_CTX_get (ctx), * z2 = BN_CTX_get (ctx), * t2 = BN_CTX_get (ctx); - - BN_sqr (x2, p.x, ctx); // x2 = A = x^2 - BN_sqr (y2, p.y, ctx); // y2 = B = y^2 + + BN_sqr (x2, p.x, ctx); // x2 = A = x^2 + BN_sqr (y2, p.y, ctx); // y2 = B = y^2 if (p.t) BN_sqr (t2, p.t, ctx); // t2 = t^2 else { BN_mul (t2, p.x, p.y, ctx); // t = x*y BN_sqr (t2, t2, ctx); // t2 = t^2 - } - BN_mul (t2, t2, d, ctx); // t2 = C = d*t^2 + } + BN_mul (t2, t2, d, ctx); // t2 = C = d*t^2 if (p.z) - BN_sqr (z2, p.z, ctx); // z2 = D = z^2 + BN_sqr (z2, p.z, ctx); // z2 = D = z^2 else BN_one (z2); // z2 = 1 BIGNUM * E = BN_CTX_get (ctx), * F = BN_CTX_get (ctx), * G = BN_CTX_get (ctx), * H = BN_CTX_get (ctx); // E = (x+y)*(x+y)-A-B = x^2+y^2+2xy-A-B = 2xy BN_mul (E, p.x, p.y, ctx); - BN_lshift1 (E, E); // E =2*x*y + BN_lshift1 (E, E); // E =2*x*y BN_sub (F, z2, t2); // F = D - C - BN_add (G, z2, t2); // G = D + C + BN_add (G, z2, t2); // G = D + C BN_add (H, y2, x2); // H = B + A BN_mod_mul (p.x, E, F, q, ctx); // x2 = E*F - BN_mod_mul (p.y, G, H, q, ctx); // y2 = G*H + BN_mod_mul (p.y, G, H, q, ctx); // y2 = G*H if (!p.z) p.z = BN_new (); - BN_mod_mul (p.z, F, G, q, ctx); // z2 = F*G + BN_mod_mul (p.z, F, G, q, ctx); // z2 = F*G if (!p.t) p.t = BN_new (); - BN_mod_mul (p.t, E, H, q, ctx); // t2 = E*H + BN_mod_mul (p.t, E, H, q, ctx); // t2 = E*H BN_CTX_end (ctx); } - + EDDSAPoint Mul (const EDDSAPoint& p, const BIGNUM * e, BN_CTX * ctx) const { BIGNUM * zero = BN_new (), * one = BN_new (); @@ -262,10 +262,10 @@ namespace crypto Double (res, ctx); if (BN_is_bit_set (e, i)) res = Sum (res, p, ctx); } - } + } return res; - } - + } + EDDSAPoint MulB (const uint8_t * e, BN_CTX * ctx) const // B*e, e is 32 bytes Little Endian { BIGNUM * zero = BN_new (), * one = BN_new (); @@ -275,15 +275,15 @@ namespace crypto for (int i = 0; i < 32; i++) { uint8_t x = e[i]; - if (carry) - { - if (x < 255) - { - x++; + if (carry) + { + if (x < 255) + { + x++; carry = false; - } - else - x = 0; + } + else + x = 0; } if (x > 0) { @@ -293,7 +293,7 @@ namespace crypto { res = Sum (res, -Bi256[i][255-x], ctx); // -Bi[256-x] carry = true; - } + } } } if (carry) res = Sum (res, Bi256Carry, ctx); @@ -320,9 +320,9 @@ namespace crypto BIGNUM * x2 = BN_CTX_get (ctx), * y2 = BN_CTX_get (ctx), * tmp = BN_CTX_get (ctx); BN_sqr (x2, p.x, ctx); // x^2 BN_sqr (y2, p.y, ctx); // y^2 - // y^2 - x^2 - 1 - d*x^2*y^2 + // y^2 - x^2 - 1 - d*x^2*y^2 BN_mul (tmp, d, x2, ctx); - BN_mul (tmp, tmp, y2, ctx); + BN_mul (tmp, tmp, y2, ctx); BN_sub (tmp, y2, tmp); BN_sub (tmp, tmp, x2); BN_sub_word (tmp, 1); @@ -330,25 +330,25 @@ namespace crypto bool ret = BN_is_zero (tmp); BN_CTX_end (ctx); return ret; - } + } BIGNUM * RecoverX (const BIGNUM * y, BN_CTX * ctx) const { BN_CTX_start (ctx); BIGNUM * y2 = BN_CTX_get (ctx), * xx = BN_CTX_get (ctx); BN_sqr (y2, y, ctx); // y^2 - // xx = (y^2 -1)*inv(d*y^2 +1) + // xx = (y^2 -1)*inv(d*y^2 +1) BN_mul (xx, d, y2, ctx); BN_add_word (xx, 1); BN_mod_inverse (xx, xx, q, ctx); BN_sub_word (y2, 1); BN_mul (xx, y2, xx, ctx); - // x = srqt(xx) = xx^(2^252-2) + // x = srqt(xx) = xx^(2^252-2) BIGNUM * x = BN_new (); BN_mod_exp (x, xx, two_252_2, q, ctx); - // check (x^2 -xx) % q + // check (x^2 -xx) % q BN_sqr (y2, x, ctx); - BN_mod_sub (y2, y2, xx, q, ctx); + BN_mod_sub (y2, y2, xx, q, ctx); if (!BN_is_zero (y2)) BN_mod_mul (x, x, I, q, ctx); if (BN_is_odd (x)) @@ -373,18 +373,18 @@ namespace crypto BN_bin2bn (buf1, EDDSA25519_PUBLIC_KEY_LENGTH, y); BIGNUM * x = RecoverX (y, ctx); if (BN_is_bit_set (x, 0) != isHighestBitSet) - BN_sub (x, q, x); // x = q - x - BIGNUM * z = BN_new (), * t = BN_new (); + BN_sub (x, q, x); // x = q - x + BIGNUM * z = BN_new (), * t = BN_new (); BN_one (z); BN_mod_mul (t, x, y, q, ctx); // pre-calculate t EDDSAPoint p {x, y, z, t}; - if (!IsOnCurve (p, ctx)) + if (!IsOnCurve (p, ctx)) LogPrint (eLogError, "Decoded point is not on 25519"); return p; } - + void EncodePoint (const EDDSAPoint& p, uint8_t * buf) const { - EncodeBN (p.y, buf,EDDSA25519_PUBLIC_KEY_LENGTH); + EncodeBN (p.y, buf,EDDSA25519_PUBLIC_KEY_LENGTH); if (BN_is_bit_set (p.x, 0)) // highest bit buf[EDDSA25519_PUBLIC_KEY_LENGTH - 1] |= 0x80; // set highest bit } @@ -413,12 +413,12 @@ namespace crypto uint8_t tmp = buf[i]; buf[i] = buf[len -1 - i]; buf[len -1 - i] = tmp; - } + } } private: - - BIGNUM * q, * l, * d, * I; + + BIGNUM * q, * l, * d, * I; // transient values BIGNUM * two_252_2; // 2^252-2 EDDSAPoint Bi256[32][128]; // per byte, Bi256[i][j] = (256+j+1)^i*B, we don't store zeroes @@ -437,14 +437,14 @@ namespace crypto g_Ed25519.reset (c); else delete c; - } - return g_Ed25519; - } - + } + return g_Ed25519; + } + EDDSA25519Verifier::EDDSA25519Verifier (const uint8_t * signingKey) { - memcpy (m_PublicKeyEncoded, signingKey, EDDSA25519_PUBLIC_KEY_LENGTH); + memcpy (m_PublicKeyEncoded, signingKey, EDDSA25519_PUBLIC_KEY_LENGTH); BN_CTX * ctx = BN_CTX_new (); m_PublicKey = GetEd25519 ()->DecodePublicKey (m_PublicKeyEncoded, ctx); BN_CTX_free (ctx); @@ -457,40 +457,40 @@ namespace crypto SHA512_Init (&ctx); SHA512_Update (&ctx, signature, EDDSA25519_SIGNATURE_LENGTH/2); // R SHA512_Update (&ctx, m_PublicKeyEncoded, EDDSA25519_PUBLIC_KEY_LENGTH); // public key - SHA512_Update (&ctx, buf, len); // data + SHA512_Update (&ctx, buf, len); // data SHA512_Final (digest, &ctx); - + return GetEd25519 ()->Verify (m_PublicKey, digest, signature); } EDDSA25519Signer::EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey) - { + { // expand key SHA512 (signingPrivateKey, EDDSA25519_PRIVATE_KEY_LENGTH, m_ExpandedPrivateKey); - m_ExpandedPrivateKey[0] &= 0xF8; // drop last 3 bits + m_ExpandedPrivateKey[0] &= 0xF8; // drop last 3 bits m_ExpandedPrivateKey[EDDSA25519_PRIVATE_KEY_LENGTH - 1] &= 0x3F; // drop first 2 bits m_ExpandedPrivateKey[EDDSA25519_PRIVATE_KEY_LENGTH - 1] |= 0x40; // set second bit - + // generate and encode public key - BN_CTX * ctx = BN_CTX_new (); + BN_CTX * ctx = BN_CTX_new (); auto publicKey = GetEd25519 ()->GeneratePublicKey (m_ExpandedPrivateKey, ctx); - GetEd25519 ()->EncodePublicKey (publicKey, m_PublicKeyEncoded, ctx); - + GetEd25519 ()->EncodePublicKey (publicKey, m_PublicKeyEncoded, ctx); + if (signingPublicKey && memcmp (m_PublicKeyEncoded, signingPublicKey, EDDSA25519_PUBLIC_KEY_LENGTH)) { // keys don't match, it means older key with 0x1F LogPrint (eLogWarning, "Older EdDSA key detected"); - m_ExpandedPrivateKey[EDDSA25519_PRIVATE_KEY_LENGTH - 1] &= 0xDF; // drop third bit + m_ExpandedPrivateKey[EDDSA25519_PRIVATE_KEY_LENGTH - 1] &= 0xDF; // drop third bit publicKey = GetEd25519 ()->GeneratePublicKey (m_ExpandedPrivateKey, ctx); - GetEd25519 ()->EncodePublicKey (publicKey, m_PublicKeyEncoded, ctx); + GetEd25519 ()->EncodePublicKey (publicKey, m_PublicKeyEncoded, ctx); } BN_CTX_free (ctx); - } - + } + void EDDSA25519Signer::Sign (const uint8_t * buf, int len, uint8_t * signature) const { GetEd25519 ()->Sign (m_ExpandedPrivateKey, m_PublicKeyEncoded, buf, len, signature); - } + } } } diff --git a/libi2pd/Signature.h b/libi2pd/Signature.h index 531fdfdf..1e7db9f7 100644 --- a/libi2pd/Signature.h +++ b/libi2pd/Signature.h @@ -18,7 +18,7 @@ namespace crypto class Verifier { public: - + virtual ~Verifier () {}; virtual bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const = 0; virtual size_t GetPublicKeyLen () const = 0; @@ -30,12 +30,12 @@ namespace crypto { public: - virtual ~Signer () {}; - virtual void Sign (const uint8_t * buf, int len, uint8_t * signature) const = 0; + virtual ~Signer () {}; + virtual void Sign (const uint8_t * buf, int len, uint8_t * signature) const = 0; }; const size_t DSA_PUBLIC_KEY_LENGTH = 128; - const size_t DSA_SIGNATURE_LENGTH = 40; + const size_t DSA_SIGNATURE_LENGTH = 40; const size_t DSA_PRIVATE_KEY_LENGTH = DSA_SIGNATURE_LENGTH/2; class DSAVerifier: public Verifier { @@ -51,7 +51,7 @@ namespace crypto { DSA_free (m_PublicKey); } - + bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { // calculate SHA1 digest @@ -64,11 +64,11 @@ namespace crypto int ret = DSA_do_verify (digest, 20, sig, m_PublicKey); DSA_SIG_free(sig); return ret; - } + } size_t GetPublicKeyLen () const { return DSA_PUBLIC_KEY_LENGTH; }; size_t GetSignatureLen () const { return DSA_SIGNATURE_LENGTH; }; - + private: DSA * m_PublicKey; @@ -89,7 +89,7 @@ namespace crypto { DSA_free (m_PrivateKey); } - + void Sign (const uint8_t * buf, int len, uint8_t * signature) const { uint8_t digest[20]; @@ -115,21 +115,21 @@ namespace crypto DSA_get0_key(dsa, &pub_key, &priv_key); bn2buf (priv_key, signingPrivateKey, DSA_PRIVATE_KEY_LENGTH); bn2buf (pub_key, signingPublicKey, DSA_PUBLIC_KEY_LENGTH); - DSA_free (dsa); - } + DSA_free (dsa); + } struct SHA256Hash - { + { static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest) { SHA256 (buf, len, digest); } enum { hashLen = 32 }; - }; + }; struct SHA384Hash - { + { static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest) { SHA384 (buf, len, digest); @@ -139,7 +139,7 @@ namespace crypto }; struct SHA512Hash - { + { static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest) { SHA512 (buf, len, digest); @@ -147,10 +147,10 @@ namespace crypto enum { hashLen = 64 }; }; - + template class ECDSAVerifier: public Verifier - { + { public: ECDSAVerifier (const uint8_t * signingKey) @@ -166,7 +166,7 @@ namespace crypto { EC_KEY_free (m_PublicKey); } - + bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { uint8_t digest[Hash::hashLen]; @@ -179,12 +179,12 @@ namespace crypto int ret = ECDSA_do_verify (digest, Hash::hashLen, sig, m_PublicKey); ECDSA_SIG_free(sig); return ret; - } - + } + size_t GetPublicKeyLen () const { return keyLen; }; size_t GetSignatureLen () const { return keyLen; }; // signature length = key length - + private: EC_KEY * m_PublicKey; @@ -198,14 +198,14 @@ namespace crypto ECDSASigner (const uint8_t * signingPrivateKey) { m_PrivateKey = EC_KEY_new_by_curve_name (curve); - EC_KEY_set_private_key (m_PrivateKey, BN_bin2bn (signingPrivateKey, keyLen/2, NULL)); + EC_KEY_set_private_key (m_PrivateKey, BN_bin2bn (signingPrivateKey, keyLen/2, NULL)); } ~ECDSASigner () { EC_KEY_free (m_PrivateKey); } - + void Sign (const uint8_t * buf, int len, uint8_t * signature) const { uint8_t digest[Hash::hashLen]; @@ -235,18 +235,18 @@ namespace crypto bn2buf (x, signingPublicKey, keyLen/2); bn2buf (y, signingPublicKey + keyLen/2, keyLen/2); BN_free (x); BN_free (y); - EC_KEY_free (signingKey); + EC_KEY_free (signingKey); } // ECDSA_SHA256_P256 - const size_t ECDSAP256_KEY_LENGTH = 64; + const size_t ECDSAP256_KEY_LENGTH = 64; typedef ECDSAVerifier ECDSAP256Verifier; typedef ECDSASigner ECDSAP256Signer; inline void CreateECDSAP256RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey) { CreateECDSARandomKeys (NID_X9_62_prime256v1, ECDSAP256_KEY_LENGTH, signingPrivateKey, signingPublicKey); - } + } // ECDSA_SHA384_P384 const size_t ECDSAP384_KEY_LENGTH = 96; @@ -256,7 +256,7 @@ namespace crypto inline void CreateECDSAP384RandomKeys (uint8_t * signingPrivateKey, uint8_t * signingPublicKey) { CreateECDSARandomKeys (NID_secp384r1, ECDSAP384_KEY_LENGTH, signingPrivateKey, signingPublicKey); - } + } // ECDSA_SHA512_P521 const size_t ECDSAP521_KEY_LENGTH = 132; @@ -269,7 +269,7 @@ namespace crypto } // RSA - template + template class RSAVerifier: public Verifier { public: @@ -284,23 +284,23 @@ namespace crypto { RSA_free (m_PublicKey); } - - bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const + + bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { uint8_t digest[Hash::hashLen]; Hash::CalculateHash (buf, len, digest); return RSA_verify (type, digest, Hash::hashLen, signature, GetSignatureLen (), m_PublicKey); } size_t GetPublicKeyLen () const { return keyLen; } - size_t GetSignatureLen () const { return keyLen; } + size_t GetSignatureLen () const { return keyLen; } size_t GetPrivateKeyLen () const { return GetSignatureLen ()*2; }; private: - - RSA * m_PublicKey; - }; - + RSA * m_PublicKey; + }; + + template class RSASigner: public Signer { @@ -317,7 +317,7 @@ namespace crypto { RSA_free (m_PrivateKey); } - + void Sign (const uint8_t * buf, int len, uint8_t * signature) const { uint8_t digest[Hash::hashLen]; @@ -325,11 +325,11 @@ namespace crypto unsigned int signatureLen = keyLen; RSA_sign (type, digest, Hash::hashLen, signature, &signatureLen, m_PrivateKey); } - + private: RSA * m_PrivateKey; - }; + }; inline void CreateRSARandomKeys (size_t publicKeyLen, uint8_t * signingPrivateKey, uint8_t * signingPublicKey) { @@ -337,14 +337,14 @@ namespace crypto BIGNUM * e = BN_dup (GetRSAE ()); // make it non-const RSA_generate_key_ex (rsa, publicKeyLen*8, e, NULL); const BIGNUM * n, * d, * e1; - RSA_get0_key (rsa, &n, &e1, &d); + RSA_get0_key (rsa, &n, &e1, &d); bn2buf (n, signingPrivateKey, publicKeyLen); bn2buf (d, signingPrivateKey + publicKeyLen, publicKeyLen); bn2buf (n, signingPublicKey, publicKeyLen); BN_free (e); // this e is not assigned to rsa->e RSA_free (rsa); - } - + } + // RSA_SHA256_2048 const size_t RSASHA2562048_KEY_LENGTH = 256; typedef RSAVerifier RSASHA2562048Verifier; @@ -353,7 +353,7 @@ namespace crypto // RSA_SHA384_3072 const size_t RSASHA3843072_KEY_LENGTH = 384; typedef RSAVerifier RSASHA3843072Verifier; - typedef RSASigner RSASHA3843072Signer; + typedef RSASigner RSASHA3843072Signer; // RSA_SHA512_4096 const size_t RSASHA5124096_KEY_LENGTH = 512; @@ -379,7 +379,7 @@ namespace crypto {} ~EDDSAPoint () { BN_free (x); BN_free (y); BN_free(z); BN_free(t); } - EDDSAPoint& operator=(EDDSAPoint&& other) + EDDSAPoint& operator=(EDDSAPoint&& other) { if (this != &other) { @@ -389,9 +389,9 @@ namespace crypto BN_free (t); t = other.t; other.t = nullptr; } return *this; - } + } - EDDSAPoint& operator=(const EDDSAPoint& other) + EDDSAPoint& operator=(const EDDSAPoint& other) { if (this != &other) { @@ -412,11 +412,11 @@ namespace crypto if (t) { t1 = BN_dup (t); BN_set_negative (t1, !BN_is_negative (t)); }; return EDDSAPoint {x1, y1, z1, t1}; } - }; + }; const size_t EDDSA25519_PUBLIC_KEY_LENGTH = 32; const size_t EDDSA25519_SIGNATURE_LENGTH = 64; - const size_t EDDSA25519_PRIVATE_KEY_LENGTH = 32; + const size_t EDDSA25519_PRIVATE_KEY_LENGTH = 32; class EDDSA25519Verifier: public Verifier { public: @@ -429,7 +429,7 @@ namespace crypto private: - EDDSAPoint m_PublicKey; + EDDSAPoint m_PublicKey; uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH]; }; @@ -437,14 +437,14 @@ namespace crypto { public: - EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey = nullptr); - // we pass signingPublicKey to check if it matches private key - void Sign (const uint8_t * buf, int len, uint8_t * signature) const; + EDDSA25519Signer (const uint8_t * signingPrivateKey, const uint8_t * signingPublicKey = nullptr); + // we pass signingPublicKey to check if it matches private key + void Sign (const uint8_t * buf, int len, uint8_t * signature) const; const uint8_t * GetPublicKey () const { return m_PublicKeyEncoded; }; - + private: - uint8_t m_ExpandedPrivateKey[64]; + uint8_t m_ExpandedPrivateKey[64]; uint8_t m_PublicKeyEncoded[EDDSA25519_PUBLIC_KEY_LENGTH]; }; @@ -456,22 +456,22 @@ namespace crypto } - // ГОСТ Р 34.11 + // ГОСТ Р 34.11 struct GOSTR3411_256_Hash - { + { static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest) { - GOSTR3411_2012_256 (buf, len, digest); + GOSTR3411_2012_256 (buf, len, digest); } enum { hashLen = 32 }; }; struct GOSTR3411_512_Hash - { + { static void CalculateHash (const uint8_t * buf, size_t len, uint8_t * digest) { - GOSTR3411_2012_512 (buf, len, digest); + GOSTR3411_2012_512 (buf, len, digest); } enum { hashLen = 64 }; @@ -487,7 +487,7 @@ namespace crypto public: enum { keyLen = Hash::hashLen }; - + GOSTR3410Verifier (GOSTR3410ParamSet paramSet, const uint8_t * signingKey): m_ParamSet (paramSet) { @@ -497,7 +497,7 @@ namespace crypto BN_free (x); BN_free (y); } ~GOSTR3410Verifier () { EC_POINT_free (m_PublicKey); } - + bool Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const { uint8_t digest[Hash::hashLen]; @@ -506,7 +506,7 @@ namespace crypto BIGNUM * r = BN_bin2bn (signature, GetSignatureLen ()/2, NULL); BIGNUM * s = BN_bin2bn (signature + GetSignatureLen ()/2, GetSignatureLen ()/2, NULL); bool ret = GetGOSTR3410Curve (m_ParamSet)->Verify (m_PublicKey, d, r, s); - BN_free (d); BN_free (r); BN_free (s); + BN_free (d); BN_free (r); BN_free (s); return ret; } @@ -517,7 +517,7 @@ namespace crypto GOSTR3410ParamSet m_ParamSet; EC_POINT * m_PublicKey; - }; + }; template class GOSTR3410Signer: public Signer @@ -525,11 +525,11 @@ namespace crypto public: enum { keyLen = Hash::hashLen }; - + GOSTR3410Signer (GOSTR3410ParamSet paramSet, const uint8_t * signingPrivateKey): m_ParamSet (paramSet) - { - m_PrivateKey = BN_bin2bn (signingPrivateKey, keyLen, nullptr); + { + m_PrivateKey = BN_bin2bn (signingPrivateKey, keyLen, nullptr); } ~GOSTR3410Signer () { BN_free (m_PrivateKey); } @@ -537,19 +537,19 @@ namespace crypto { uint8_t digest[Hash::hashLen]; Hash::CalculateHash (buf, len, digest); - BIGNUM * d = BN_bin2bn (digest, Hash::hashLen, nullptr); + BIGNUM * d = BN_bin2bn (digest, Hash::hashLen, nullptr); BIGNUM * r = BN_new (), * s = BN_new (); GetGOSTR3410Curve (m_ParamSet)->Sign (m_PrivateKey, d, r, s); bn2buf (r, signature, keyLen); bn2buf (s, signature + keyLen, keyLen); BN_free (d); BN_free (r); BN_free (s); } - + private: GOSTR3410ParamSet m_ParamSet; BIGNUM * m_PrivateKey; - }; + }; inline void CreateGOSTR3410RandomKeys (GOSTR3410ParamSet paramSet, uint8_t * signingPrivateKey, uint8_t * signingPublicKey) { @@ -557,7 +557,7 @@ namespace crypto auto keyLen = curve->GetKeyLen (); RAND_bytes (signingPrivateKey, keyLen); BIGNUM * priv = BN_bin2bn (signingPrivateKey, keyLen, nullptr); - + auto pub = curve->MulP (priv); BN_free (priv); BIGNUM * x = BN_new (), * y = BN_new (); @@ -565,7 +565,7 @@ namespace crypto EC_POINT_free (pub); bn2buf (x, signingPublicKey, keyLen); bn2buf (y, signingPublicKey + keyLen, keyLen); - BN_free (x); BN_free (y); + BN_free (x); BN_free (y); } typedef GOSTR3410Verifier GOSTR3410_256_Verifier; diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 16ccf555..37d9d2c4 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -12,11 +12,11 @@ namespace i2p namespace stream { void SendBufferQueue::Add (const uint8_t * buf, size_t len, SendHandler handler) - { + { m_Buffers.push_back (std::make_shared(buf, len, handler)); m_Size += len; } - + size_t SendBufferQueue::Get (uint8_t * buf, size_t len) { size_t offset = 0; @@ -30,7 +30,7 @@ namespace stream memcpy (buf + offset, nextBuffer->GetRemaningBuffer (), rem); offset += rem; m_Buffers.pop_front (); // delete it - } + } else { // partially @@ -38,23 +38,23 @@ namespace stream memcpy (buf + offset, nextBuffer->GetRemaningBuffer (), len - offset); nextBuffer->offset += (len - offset); offset = len; // break - } - } + } + } m_Size -= offset; return offset; - } + } - void SendBufferQueue::CleanUp () - { + void SendBufferQueue::CleanUp () + { if (!m_Buffers.empty ()) - { + { for (auto it: m_Buffers) it->Cancel (); - m_Buffers.clear (); + m_Buffers.clear (); m_Size = 0; - } + } } - + Stream::Stream (boost::asio::io_service& service, StreamingDestination& local, std::shared_ptr remote, int port): m_Service (service), m_SendStreamID (0), m_SequenceNumber (0), m_LastReceivedSequenceNumber (-1), @@ -100,7 +100,7 @@ namespace stream { std::unique_lock l(m_SendBufferMutex); m_SendBuffer.CleanUp (); - } + } while (!m_ReceiveQueue.empty ()) { auto packet = m_ReceiveQueue.front (); @@ -1108,7 +1108,7 @@ namespace stream } else // we must save old acceptor and set it back { - m_Acceptor = std::bind (&StreamingDestination::AcceptOnceAcceptor, this, + m_Acceptor = std::bind (&StreamingDestination::AcceptOnceAcceptor, this, std::placeholders::_1, acceptor, m_Acceptor); } }); @@ -1118,8 +1118,8 @@ namespace stream { m_Acceptor = prev; acceptor (stream); - } - + } + void StreamingDestination::HandlePendingIncomingTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 025ceb63..202ff73f 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -41,40 +41,40 @@ namespace stream const size_t STREAMING_MTU = 1730; const size_t MAX_PACKET_SIZE = 4096; - const size_t COMPRESSION_THRESHOLD_SIZE = 66; - const int MAX_NUM_RESEND_ATTEMPTS = 6; + const size_t COMPRESSION_THRESHOLD_SIZE = 66; + const int MAX_NUM_RESEND_ATTEMPTS = 6; const int WINDOW_SIZE = 6; // in messages const int MIN_WINDOW_SIZE = 1; - const int MAX_WINDOW_SIZE = 128; + const int MAX_WINDOW_SIZE = 128; const int INITIAL_RTT = 8000; // in milliseconds const int INITIAL_RTO = 9000; // in milliseconds const int SYN_TIMEOUT = 200; // how long we wait for SYN after follow-on, in milliseconds const size_t MAX_PENDING_INCOMING_BACKLOG = 128; const int PENDING_INCOMING_TIMEOUT = 10; // in seconds - const int MAX_RECEIVE_TIMEOUT = 30; // in seconds + const int MAX_RECEIVE_TIMEOUT = 30; // in seconds /** i2cp option for limiting inbound stremaing connections */ const char I2CP_PARAM_STREAMING_MAX_CONNS_PER_MIN[] = "maxconns"; /** default maximum connections attempts per minute per destination */ const uint32_t DEFAULT_MAX_CONNS_PER_MIN = 600; - /** + /** * max banned destinations per local destination * TODO: make configurable */ const uint16_t MAX_BANNED_CONNS = 9999; - /** + /** * length of a ban in ms - * TODO: make configurable + * TODO: make configurable */ const uint64_t DEFAULT_BAN_INTERVAL = 60 * 60 * 1000; - + struct Packet { size_t len, offset; - uint8_t buf[MAX_PACKET_SIZE]; + uint8_t buf[MAX_PACKET_SIZE]; uint64_t sendTime; - + Packet (): len (0), offset (0), sendTime (0) {}; uint8_t * GetBuffer () { return buf + offset; }; size_t GetLength () const { return len - offset; }; @@ -93,15 +93,15 @@ namespace stream bool IsSYN () const { return GetFlags () & PACKET_FLAG_SYNCHRONIZE; }; bool IsNoAck () const { return GetFlags () & PACKET_FLAG_NO_ACK; }; - }; + }; struct PacketCmp { bool operator() (const Packet * p1, const Packet * p2) const - { - return p1->GetSeqn () < p2->GetSeqn (); + { + return p1->GetSeqn () < p2->GetSeqn (); }; - }; + }; typedef std::function SendHandler; struct SendBuffer @@ -115,16 +115,16 @@ namespace stream { buf = new uint8_t[len]; memcpy (buf, b, len); - } + } ~SendBuffer () { delete[] buf; if (handler) handler(boost::system::error_code ()); - } + } size_t GetRemainingSize () const { return len - offset; }; - const uint8_t * GetRemaningBuffer () const { return buf + offset; }; + const uint8_t * GetRemaningBuffer () const { return buf + offset; }; void Cancel () { if (handler) handler (boost::asio::error::make_error_code (boost::asio::error::operation_aborted)); handler = nullptr; }; - }; + }; class SendBufferQueue { @@ -133,18 +133,18 @@ namespace stream SendBufferQueue (): m_Size (0) {}; ~SendBufferQueue () { CleanUp (); }; - void Add (const uint8_t * buf, size_t len, SendHandler handler); - size_t Get (uint8_t * buf, size_t len); + void Add (const uint8_t * buf, size_t len, SendHandler handler); + size_t Get (uint8_t * buf, size_t len); size_t GetSize () const { return m_Size; }; bool IsEmpty () const { return m_Buffers.empty (); }; void CleanUp (); - - private: + + private: std::list > m_Buffers; size_t m_Size; - }; - + }; + enum StreamStatus { eStreamStatusNew = 0, @@ -152,16 +152,16 @@ namespace stream eStreamStatusReset, eStreamStatusClosing, eStreamStatusClosed - }; - + }; + class StreamingDestination; class Stream: public std::enable_shared_from_this - { + { public: - Stream (boost::asio::io_service& service, StreamingDestination& local, + Stream (boost::asio::io_service& service, StreamingDestination& local, std::shared_ptr remote, int port = 0); // outgoing - Stream (boost::asio::io_service& service, StreamingDestination& local); // incoming + Stream (boost::asio::io_service& service, StreamingDestination& local); // incoming ~Stream (); uint32_t GetSendStreamID () const { return m_SendStreamID; }; @@ -172,15 +172,15 @@ namespace stream bool IsEstablished () const { return m_SendStreamID; }; StreamStatus GetStatus () const { return m_Status; }; StreamingDestination& GetLocalDestination () { return m_LocalDestination; }; - + void HandleNextPacket (Packet * packet); size_t Send (const uint8_t * buf, size_t len); void AsyncSend (const uint8_t * buf, size_t len, SendHandler handler); - + template void AsyncReceive (const Buffer& buffer, ReceiveHandler handler, int timeout = 0); size_t ReadSome (uint8_t * buf, size_t len) { return ConcatenatePackets (buf, len); }; - + void Close (); void Cancel () { m_ReceiveTimer.cancel (); }; @@ -194,11 +194,11 @@ namespace stream /** don't call me */ void Terminate (); - + private: void CleanUp (); - + void SendBuffer (); void SendQuickAck (); void SendClose (); @@ -212,14 +212,14 @@ namespace stream size_t ConcatenatePackets (uint8_t * buf, size_t len); void UpdateCurrentRemoteLease (bool expired = false); - + template void HandleReceiveTimer (const boost::system::error_code& ecode, const Buffer& buffer, ReceiveHandler handler, int remainingTimeout); - + void ScheduleResend (); void HandleResendTimer (const boost::system::error_code& ecode); void HandleAckSendTimer (const boost::system::error_code& ecode); - + private: boost::asio::io_service& m_Service; @@ -254,16 +254,16 @@ namespace stream typedef std::function)> Acceptor; StreamingDestination (std::shared_ptr owner, uint16_t localPort = 0, bool gzip = true); - ~StreamingDestination (); + ~StreamingDestination (); void Start (); void Stop (); std::shared_ptr CreateNewOutgoingStream (std::shared_ptr remote, int port = 0); - void DeleteStream (std::shared_ptr stream); + void DeleteStream (std::shared_ptr stream); void SetAcceptor (const Acceptor& acceptor); void ResetAcceptor (); - bool IsAcceptorSet () const { return m_Acceptor != nullptr; }; + bool IsAcceptorSet () const { return m_Acceptor != nullptr; }; void AcceptOnce (const Acceptor& acceptor); std::shared_ptr GetOwner () const { return m_Owner; }; @@ -278,11 +278,11 @@ namespace stream Packet * NewPacket () { return m_PacketsPool.Acquire (); } void DeletePacket (Packet * p) { m_PacketsPool.Release (p); } - - private: + + private: void AcceptOnceAcceptor (std::shared_ptr stream, Acceptor acceptor, Acceptor prev); - + void HandleNextPacket (Packet * packet); std::shared_ptr CreateNewIncomingStream (); void HandlePendingIncomingTimer (const boost::system::error_code& ecode); @@ -293,7 +293,7 @@ namespace stream bool DropNewStream(const i2p::data::IdentHash & ident); void ScheduleConnTrack(); - + private: std::shared_ptr m_Owner; @@ -306,7 +306,7 @@ namespace stream std::list > m_PendingIncomingStreams; boost::asio::deadline_timer m_PendingIncomingTimer; std::map > m_SavedPackets; // receiveStreamID->packets, arrived before SYN - + std::mutex m_ConnsMutex; /** how many connections per minute did each identity have */ std::map m_Conns; @@ -318,15 +318,15 @@ namespace stream i2p::util::MemoryPool m_PacketsPool; bool m_EnableDrop; - + public: i2p::data::GzipInflator m_Inflator; i2p::data::GzipDeflator m_Deflator; - + // for HTTP only const decltype(m_Streams)& GetStreams () const { return m_Streams; }; - }; + }; //------------------------------------------------- @@ -336,7 +336,7 @@ namespace stream auto s = shared_from_this(); m_Service.post ([=](void) { - if (!m_ReceiveQueue.empty () || m_Status == eStreamStatusReset) + if (!s->m_ReceiveQueue.empty () || s->m_Status == eStreamStatusReset) s->HandleReceiveTimer (boost::asio::error::make_error_code (boost::asio::error::operation_aborted), buffer, handler, 0); else { @@ -345,7 +345,7 @@ namespace stream s->m_ReceiveTimer.async_wait ([=](const boost::system::error_code& ecode) { s->HandleReceiveTimer (ecode, buffer, handler, timeout - t); }); } - }); + }); } template @@ -355,27 +355,27 @@ namespace stream if (received > 0) handler (boost::system::error_code (), received); else if (ecode == boost::asio::error::operation_aborted) - { - // timeout not expired + { + // timeout not expired if (m_Status == eStreamStatusReset) handler (boost::asio::error::make_error_code (boost::asio::error::connection_reset), 0); else - handler (boost::asio::error::make_error_code (boost::asio::error::operation_aborted), 0); - } + handler (boost::asio::error::make_error_code (boost::asio::error::operation_aborted), 0); + } else - { + { // timeout expired if (remainingTimeout <= 0) handler (boost::asio::error::make_error_code (boost::asio::error::timed_out), received); else - { + { // itermediate iterrupt SendUpdatedLeaseSet (); // send our leaseset if applicable - AsyncReceive (buffer, handler, remainingTimeout); - } - } + AsyncReceive (buffer, handler, remainingTimeout); + } + } } -} -} +} +} #endif diff --git a/libi2pd/Tag.h b/libi2pd/Tag.h index 3977fd29..03e3bc06 100644 --- a/libi2pd/Tag.h +++ b/libi2pd/Tag.h @@ -56,7 +56,7 @@ public: { RAND_bytes(m_Buf, sz); } - + std::string ToBase64 () const { char str[sz*2]; diff --git a/libi2pd/Timestamp.cpp b/libi2pd/Timestamp.cpp index 3131fb6a..9e9b4e63 100644 --- a/libi2pd/Timestamp.cpp +++ b/libi2pd/Timestamp.cpp @@ -40,7 +40,7 @@ namespace util int i = 0; while (!socket.available() && i < 10) // 10 seconds max { - std::this_thread::sleep_for (std::chrono::seconds(1)); + std::this_thread::sleep_for (std::chrono::seconds(1)); i++; } if (socket.available ()) diff --git a/libi2pd/Timestamp.h b/libi2pd/Timestamp.h index d48cb164..cddc6518 100644 --- a/libi2pd/Timestamp.h +++ b/libi2pd/Timestamp.h @@ -11,19 +11,19 @@ namespace util inline uint64_t GetMillisecondsSinceEpoch () { return std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count (); + std::chrono::system_clock::now().time_since_epoch()).count (); } inline uint32_t GetHoursSinceEpoch () { return std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count (); + std::chrono::system_clock::now().time_since_epoch()).count (); } inline uint64_t GetSecondsSinceEpoch () { return std::chrono::duration_cast( - std::chrono::system_clock::now().time_since_epoch()).count (); + std::chrono::system_clock::now().time_since_epoch()).count (); } } } diff --git a/libi2pd/TransitTunnel.cpp b/libi2pd/TransitTunnel.cpp index bcba4d60..1adc4178 100644 --- a/libi2pd/TransitTunnel.cpp +++ b/libi2pd/TransitTunnel.cpp @@ -10,58 +10,58 @@ namespace i2p { namespace tunnel -{ - TransitTunnel::TransitTunnel (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, - const uint8_t * layerKey,const uint8_t * ivKey): +{ + TransitTunnel::TransitTunnel (uint32_t receiveTunnelID, + const uint8_t * nextIdent, uint32_t nextTunnelID, + const uint8_t * layerKey,const uint8_t * ivKey): TunnelBase (receiveTunnelID, nextTunnelID, nextIdent) - { + { m_Encryption.SetKeys (layerKey, ivKey); - } + } void TransitTunnel::EncryptTunnelMsg (std::shared_ptr in, std::shared_ptr out) - { - m_Encryption.Encrypt (in->GetPayload () + 4, out->GetPayload () + 4); + { + m_Encryption.Encrypt (in->GetPayload () + 4, out->GetPayload () + 4); i2p::transport::transports.UpdateTotalTransitTransmittedBytes (TUNNEL_DATA_MSG_SIZE); - } + } TransitTunnelParticipant::~TransitTunnelParticipant () { - } - + } + void TransitTunnelParticipant::HandleTunnelDataMsg (std::shared_ptr tunnelMsg) { auto newMsg = CreateEmptyTunnelDataMsg (); EncryptTunnelMsg (tunnelMsg, newMsg); - + m_NumTransmittedBytes += tunnelMsg->GetLength (); htobe32buf (newMsg->GetPayload (), GetNextTunnelID ()); - newMsg->FillI2NPMessageHeader (eI2NPTunnelData); + newMsg->FillI2NPMessageHeader (eI2NPTunnelData); m_TunnelDataMsgs.push_back (newMsg); } void TransitTunnelParticipant::FlushTunnelDataMsgs () { if (!m_TunnelDataMsgs.empty ()) - { + { auto num = m_TunnelDataMsgs.size (); if (num > 1) LogPrint (eLogDebug, "TransitTunnel: ", GetTunnelID (), "->", GetNextTunnelID (), " ", num); i2p::transport::transports.SendMessages (GetNextIdentHash (), m_TunnelDataMsgs); m_TunnelDataMsgs.clear (); - } - } - + } + } + void TransitTunnel::SendTunnelDataMsg (std::shared_ptr msg) - { + { LogPrint (eLogError, "TransitTunnel: We are not a gateway for ", GetTunnelID ()); - } + } void TransitTunnel::HandleTunnelDataMsg (std::shared_ptr tunnelMsg) { LogPrint (eLogError, "TransitTunnel: Incoming tunnel message is not supported ", GetTunnelID ()); - } - + } + void TransitTunnelGateway::SendTunnelDataMsg (std::shared_ptr msg) { TunnelMessageBlock block; @@ -69,43 +69,43 @@ namespace tunnel block.data = msg; std::unique_lock l(m_SendMutex); m_Gateway.PutTunnelDataMsg (block); - } + } void TransitTunnelGateway::FlushTunnelDataMsgs () { std::unique_lock l(m_SendMutex); m_Gateway.SendBuffer (); - } - + } + void TransitTunnelEndpoint::HandleTunnelDataMsg (std::shared_ptr tunnelMsg) { auto newMsg = CreateEmptyTunnelDataMsg (); EncryptTunnelMsg (tunnelMsg, newMsg); - + LogPrint (eLogDebug, "TransitTunnel: handle msg for endpoint ", GetTunnelID ()); - m_Endpoint.HandleDecryptedTunnelDataMsg (newMsg); + m_Endpoint.HandleDecryptedTunnelDataMsg (newMsg); } - + std::shared_ptr CreateTransitTunnel (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, - const uint8_t * layerKey,const uint8_t * ivKey, + const uint8_t * nextIdent, uint32_t nextTunnelID, + const uint8_t * layerKey,const uint8_t * ivKey, bool isGateway, bool isEndpoint) { if (isEndpoint) - { + { LogPrint (eLogDebug, "TransitTunnel: endpoint ", receiveTunnelID, " created"); return std::make_shared (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey); - } + } else if (isGateway) - { + { LogPrint (eLogInfo, "TransitTunnel: gateway ", receiveTunnelID, " created"); return std::make_shared (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey); - } - else - { + } + else + { LogPrint (eLogDebug, "TransitTunnel: ", receiveTunnelID, "->", nextTunnelID, " created"); return std::make_shared (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey); - } - } + } + } } } diff --git a/libi2pd/TransitTunnel.h b/libi2pd/TransitTunnel.h index eec244ce..5b891dc3 100644 --- a/libi2pd/TransitTunnel.h +++ b/libi2pd/TransitTunnel.h @@ -14,34 +14,34 @@ namespace i2p { namespace tunnel -{ - class TransitTunnel: public TunnelBase +{ + class TransitTunnel: public TunnelBase { public: TransitTunnel (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, - const uint8_t * layerKey,const uint8_t * ivKey); - + const uint8_t * nextIdent, uint32_t nextTunnelID, + const uint8_t * layerKey,const uint8_t * ivKey); + virtual size_t GetNumTransmittedBytes () const { return 0; }; // implements TunnelBase void SendTunnelDataMsg (std::shared_ptr msg); void HandleTunnelDataMsg (std::shared_ptr tunnelMsg); - void EncryptTunnelMsg (std::shared_ptr in, std::shared_ptr out); + void EncryptTunnelMsg (std::shared_ptr in, std::shared_ptr out); private: - + i2p::crypto::TunnelEncryption m_Encryption; - }; + }; class TransitTunnelParticipant: public TransitTunnel { public: TransitTunnelParticipant (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, - const uint8_t * layerKey,const uint8_t * ivKey): - TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, + const uint8_t * nextIdent, uint32_t nextTunnelID, + const uint8_t * layerKey,const uint8_t * ivKey): + TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey), m_NumTransmittedBytes (0) {}; ~TransitTunnelParticipant (); @@ -53,51 +53,51 @@ namespace tunnel size_t m_NumTransmittedBytes; std::vector > m_TunnelDataMsgs; - }; - + }; + class TransitTunnelGateway: public TransitTunnel { public: TransitTunnelGateway (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, - const uint8_t * layerKey,const uint8_t * ivKey): - TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, + const uint8_t * nextIdent, uint32_t nextTunnelID, + const uint8_t * layerKey,const uint8_t * ivKey): + TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey), m_Gateway(this) {}; void SendTunnelDataMsg (std::shared_ptr msg); void FlushTunnelDataMsgs (); size_t GetNumTransmittedBytes () const { return m_Gateway.GetNumSentBytes (); }; - + private: std::mutex m_SendMutex; TunnelGateway m_Gateway; - }; + }; class TransitTunnelEndpoint: public TransitTunnel { public: TransitTunnelEndpoint (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, - const uint8_t * layerKey,const uint8_t * ivKey): + const uint8_t * nextIdent, uint32_t nextTunnelID, + const uint8_t * layerKey,const uint8_t * ivKey): TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, layerKey, ivKey), m_Endpoint (false) {}; // transit endpoint is always outbound void Cleanup () { m_Endpoint.Cleanup (); } - + void HandleTunnelDataMsg (std::shared_ptr tunnelMsg); size_t GetNumTransmittedBytes () const { return m_Endpoint.GetNumReceivedBytes (); } - + private: TunnelEndpoint m_Endpoint; }; - + std::shared_ptr CreateTransitTunnel (uint32_t receiveTunnelID, - const uint8_t * nextIdent, uint32_t nextTunnelID, - const uint8_t * layerKey,const uint8_t * ivKey, + const uint8_t * nextIdent, uint32_t nextTunnelID, + const uint8_t * layerKey,const uint8_t * ivKey, bool isGateway, bool isEndpoint); } } diff --git a/libi2pd/TransportSession.h b/libi2pd/TransportSession.h index 5950fb06..62bed352 100644 --- a/libi2pd/TransportSession.h +++ b/libi2pd/TransportSession.h @@ -20,42 +20,42 @@ namespace transport public: SignedData () {} - SignedData (const SignedData& other) + SignedData (const SignedData& other) { m_Stream << other.m_Stream.rdbuf (); - } - void Insert (const uint8_t * buf, size_t len) - { - m_Stream.write ((char *)buf, len); - } + } + void Insert (const uint8_t * buf, size_t len) + { + m_Stream.write ((char *)buf, len); + } template void Insert (T t) { - m_Stream.write ((char *)&t, sizeof (T)); + m_Stream.write ((char *)&t, sizeof (T)); } bool Verify (std::shared_ptr ident, const uint8_t * signature) const { - return ident->Verify ((const uint8_t *)m_Stream.str ().c_str (), m_Stream.str ().size (), signature); + return ident->Verify ((const uint8_t *)m_Stream.str ().c_str (), m_Stream.str ().size (), signature); } void Sign (const i2p::data::PrivateKeys& keys, uint8_t * signature) const { - keys.Sign ((const uint8_t *)m_Stream.str ().c_str (), m_Stream.str ().size (), signature); - } + keys.Sign ((const uint8_t *)m_Stream.str ().c_str (), m_Stream.str ().size (), signature); + } private: - + std::stringstream m_Stream; - }; + }; class TransportSession { public: - TransportSession (std::shared_ptr router, int terminationTimeout): - m_DHKeysPair (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0), m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout), + TransportSession (std::shared_ptr router, int terminationTimeout): + m_DHKeysPair (nullptr), m_NumSentBytes (0), m_NumReceivedBytes (0), m_IsOutgoing (router), m_TerminationTimeout (terminationTimeout), m_LastActivityTimestamp (i2p::util::GetSecondsSinceEpoch ()) { if (router) @@ -66,30 +66,30 @@ namespace transport virtual void Done () = 0; std::string GetIdentHashBase64() const { return m_RemoteIdentity ? m_RemoteIdentity->GetIdentHash().ToBase64() : ""; } - + std::shared_ptr GetRemoteIdentity () { return m_RemoteIdentity; }; void SetRemoteIdentity (std::shared_ptr ident) { m_RemoteIdentity = ident; }; - + size_t GetNumSentBytes () const { return m_NumSentBytes; }; size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; bool IsOutgoing () const { return m_IsOutgoing; }; - + int GetTerminationTimeout () const { return m_TerminationTimeout; }; - void SetTerminationTimeout (int terminationTimeout) { m_TerminationTimeout = terminationTimeout; }; - bool IsTerminationTimeoutExpired (uint64_t ts) const - { return ts >= m_LastActivityTimestamp + GetTerminationTimeout (); }; + void SetTerminationTimeout (int terminationTimeout) { m_TerminationTimeout = terminationTimeout; }; + bool IsTerminationTimeoutExpired (uint64_t ts) const + { return ts >= m_LastActivityTimestamp + GetTerminationTimeout (); }; virtual void SendI2NPMessages (const std::vector >& msgs) = 0; - + protected: - std::shared_ptr m_RemoteIdentity; + std::shared_ptr m_RemoteIdentity; std::shared_ptr m_DHKeysPair; // X - for client and Y - for server size_t m_NumSentBytes, m_NumReceivedBytes; bool m_IsOutgoing; int m_TerminationTimeout; uint64_t m_LastActivityTimestamp; - }; + }; } } diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index 982d0945..6dcbe56d 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -119,7 +119,7 @@ namespace transport m_Work (nullptr), m_PeerCleanupTimer (nullptr), m_PeerTestTimer (nullptr), m_NTCPServer (nullptr), m_SSUServer (nullptr), m_DHKeysPairSupplier (5), // 5 pre-generated keys m_TotalSentBytes(0), m_TotalReceivedBytes(0), m_TotalTransitTransmittedBytes (0), - m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth(0), + m_InBandwidth (0), m_OutBandwidth (0), m_TransitBandwidth(0), m_LastInBandwidthUpdateBytes (0), m_LastOutBandwidthUpdateBytes (0), m_LastTransitBandwidthUpdateBytes (0), m_LastBandwidthUpdateTime (0) { @@ -144,7 +144,7 @@ namespace transport m_Service = new boost::asio::io_service (); m_Work = new boost::asio::io_service::work (*m_Service); m_PeerCleanupTimer = new boost::asio::deadline_timer (*m_Service); - m_PeerTestTimer = new boost::asio::deadline_timer (*m_Service); + m_PeerTestTimer = new boost::asio::deadline_timer (*m_Service); } i2p::config::GetOption("nat", m_IsNAT); @@ -623,7 +623,7 @@ namespace transport void Transports::DetectExternalIP () { if (RoutesRestricted()) - { + { LogPrint(eLogInfo, "Transports: restricted routes enabled, not detecting ip"); i2p::context.SetStatus (eRouterStatusOK); return; diff --git a/libi2pd/Transports.h b/libi2pd/Transports.h index d60a6d23..d4410cb3 100644 --- a/libi2pd/Transports.h +++ b/libi2pd/Transports.h @@ -136,10 +136,10 @@ namespace transport void NTCPResolve (const std::string& addr, const i2p::data::IdentHash& ident); void HandleNTCPResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it, - i2p::data::IdentHash ident, std::shared_ptr resolver); + i2p::data::IdentHash ident, std::shared_ptr resolver); void SSUResolve (const std::string& addr, const i2p::data::IdentHash& ident); void HandleSSUResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it, - i2p::data::IdentHash ident, std::shared_ptr resolver); + i2p::data::IdentHash ident, std::shared_ptr resolver); void UpdateBandwidth (); void DetectExternalIP (); diff --git a/libi2pd/Tunnel.cpp b/libi2pd/Tunnel.cpp index 6ae1e119..e2c12b83 100644 --- a/libi2pd/Tunnel.cpp +++ b/libi2pd/Tunnel.cpp @@ -2,7 +2,7 @@ #include "I2PEndian.h" #include #include -#include +#include #include "Crypto.h" #include "RouterContext.h" #include "Log.h" @@ -20,8 +20,8 @@ namespace i2p { namespace tunnel -{ - Tunnel::Tunnel (std::shared_ptr config): +{ + Tunnel::Tunnel (std::shared_ptr config): TunnelBase (config->GetTunnelID (), config->GetNextTunnelID (), config->GetNextIdentHash ()), m_Config (config), m_Pool (nullptr), m_State (eTunnelStatePending), m_IsRecreated (false), m_Latency (0) @@ -38,7 +38,7 @@ namespace tunnel std::string peers = i2p::context.GetIdentity()->GetIdentHash().ToBase64(); #endif auto numHops = m_Config->GetNumHops (); - int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : numHops; + int numRecords = numHops <= STANDARD_NUM_RECORDS ? STANDARD_NUM_RECORDS : numHops; auto msg = NewI2NPShortMessage (); *msg->GetPayload () = numRecords; msg->len += numRecords*TUNNEL_BUILD_RECORD_SIZE + 1; @@ -48,20 +48,20 @@ namespace tunnel std::random_shuffle (recordIndicies.begin(), recordIndicies.end()); // create real records - uint8_t * records = msg->GetPayload () + 1; + uint8_t * records = msg->GetPayload () + 1; TunnelHopConfig * hop = m_Config->GetFirstHop (); int i = 0; BN_CTX * ctx = BN_CTX_new (); while (hop) { uint32_t msgID; - if (hop->next) // we set replyMsgID for last hop only + if (hop->next) // we set replyMsgID for last hop only RAND_bytes ((uint8_t *)&msgID, 4); else msgID = replyMsgID; int idx = recordIndicies[i]; - hop->CreateBuildRequestRecord (records + idx*TUNNEL_BUILD_RECORD_SIZE, msgID, ctx); - hop->recordIndex = idx; + hop->CreateBuildRequestRecord (records + idx*TUNNEL_BUILD_RECORD_SIZE, msgID, ctx); + hop->recordIndex = idx; i++; #ifdef WITH_EVENTS peers += ":" + hop->ident->GetIdentHash().ToBase64(); @@ -76,7 +76,7 @@ namespace tunnel for (int i = numHops; i < numRecords; i++) { int idx = recordIndicies[i]; - RAND_bytes (records + idx*TUNNEL_BUILD_RECORD_SIZE, TUNNEL_BUILD_RECORD_SIZE); + RAND_bytes (records + idx*TUNNEL_BUILD_RECORD_SIZE, TUNNEL_BUILD_RECORD_SIZE); } // decrypt real records @@ -110,7 +110,7 @@ namespace tunnel LogPrint (eLogDebug, "Tunnel: TunnelBuildResponse ", (int)msg[0], " records."); i2p::crypto::CBCDecryption decryption; - TunnelHopConfig * hop = m_Config->GetLastHop (); + TunnelHopConfig * hop = m_Config->GetLastHop (); while (hop) { decryption.SetKey (hop->replyKey); @@ -142,12 +142,12 @@ namespace tunnel auto profile = i2p::data::netdb.FindRouterProfile (hop->ident->GetIdentHash ()); if (profile) profile->TunnelBuildResponse (ret); - if (ret) + if (ret) // if any of participants declined the tunnel is not established - established = false; + established = false; hop = hop->next; } - if (established) + if (established) { // create tunnel decryptions from layer and iv keys in reverse order hop = m_Config->GetLastHop (); @@ -170,7 +170,7 @@ namespace tunnel auto latency = GetMeanLatency(); return latency >= lower && latency <= upper; } - + void Tunnel::EncryptTunnelMsg (std::shared_ptr in, std::shared_ptr out) { const uint8_t * inPayload = in->GetPayload () + 4; @@ -178,7 +178,7 @@ namespace tunnel for (auto& it: m_Hops) { it->decryption.Decrypt (inPayload, outPayload); - inPayload = outPayload; + inPayload = outPayload; } } @@ -210,11 +210,11 @@ namespace tunnel EmitTunnelEvent("tunnel.state", this, state); #endif } - + void Tunnel::PrintHops (std::stringstream& s) const { - // hops are in inverted order, we must print in direct order + // hops are in inverted order, we must print in direct order for (auto it = m_Hops.rbegin (); it != m_Hops.rend (); it++) { s << " ⇒ "; @@ -354,7 +354,7 @@ namespace tunnel { return GetPendingTunnel (replyMsgID, m_PendingInboundTunnels); } - + std::shared_ptr Tunnels::GetPendingOutboundTunnel (uint32_t replyMsgID) { return GetPendingTunnel (replyMsgID, m_PendingOutboundTunnels); @@ -374,7 +374,7 @@ namespace tunnel std::shared_ptr Tunnels::GetNextInboundTunnel () { - std::shared_ptr tunnel; + std::shared_ptr tunnel; size_t minReceived = 0; for (const auto& it : m_InboundTunnels) { @@ -405,7 +405,7 @@ namespace tunnel return tunnel; } - std::shared_ptr Tunnels::CreateTunnelPool (int numInboundHops, + std::shared_ptr Tunnels::CreateTunnelPool (int numInboundHops, int numOutboundHops, int numInboundTunnels, int numOutboundTunnels) { auto pool = std::make_shared (numInboundHops, numOutboundHops, numInboundTunnels, numOutboundTunnels); @@ -434,7 +434,7 @@ namespace tunnel pool->DetachTunnels (); } } - + void Tunnels::AddTransitTunnel (std::shared_ptr tunnel) { if (m_Tunnels.emplace (tunnel->GetTunnelID (), tunnel).second) @@ -455,7 +455,7 @@ namespace tunnel m_Queue.WakeUp (); if (m_Thread) { - m_Thread->join (); + m_Thread->join (); delete m_Thread; m_Thread = 0; } @@ -484,11 +484,11 @@ namespace tunnel case eI2NPTunnelData: case eI2NPTunnelGateway: { - tunnelID = bufbe32toh (msg->GetPayload ()); + tunnelID = bufbe32toh (msg->GetPayload ()); if (tunnelID == prevTunnelID) tunnel = prevTunnel; else if (prevTunnel) - prevTunnel->FlushTunnelDataMsgs (); + prevTunnel->FlushTunnelDataMsgs (); if (!tunnel) tunnel = GetTunnel (tunnelID); @@ -561,9 +561,9 @@ namespace tunnel LogPrint (eLogDebug, "Tunnel: gateway of ", (int) len, " bytes for tunnel ", tunnel->GetTunnelID (), ", msg type ", (int)typeID); if (IsRouterInfoMsg (msg) || typeID == eI2NPDatabaseSearchReply) - // transit DatabaseStore my contain new/updated RI + // transit DatabaseStore my contain new/updated RI // or DatabaseSearchReply with new routers - i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg)); + i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg)); tunnel->SendTunnelDataMsg (msg); } @@ -593,7 +593,7 @@ namespace tunnel auto pool = tunnel->GetTunnelPool(); switch (tunnel->GetState ()) { - case eTunnelStatePending: + case eTunnelStatePending: if (ts > tunnel->GetCreationTime () + TUNNEL_CREATION_TIMEOUT) { LogPrint (eLogDebug, "Tunnel: pending build request ", it->first, " timeout, deleted"); @@ -632,7 +632,7 @@ namespace tunnel #endif // for i2lua if(pool) pool->OnTunnelBuildResult(tunnel, eBuildResultRejected); - + it = pendingTunnels.erase (it); m_NumFailedTunnelCreations++; break; @@ -664,7 +664,7 @@ namespace tunnel // we don't have outbound tunnels in m_Tunnels it = m_OutboundTunnels.erase (it); } - else + else { if (tunnel->IsEstablished ()) { @@ -683,7 +683,7 @@ namespace tunnel } } - if (m_OutboundTunnels.size () < 3) + if (m_OutboundTunnels.size () < 3) { // trying to create one more oubound tunnel auto inboundTunnel = GetNextInboundTunnel (); @@ -715,7 +715,7 @@ namespace tunnel m_Tunnels.erase (tunnel->GetTunnelID ()); it = m_InboundTunnels.erase (it); } - else + else { if (tunnel->IsEstablished ()) { @@ -748,13 +748,13 @@ namespace tunnel int obLen; i2p::config::GetOption("exploratory.outbound.length", obLen); int ibNum; i2p::config::GetOption("exploratory.inbound.quantity", ibNum); int obNum; i2p::config::GetOption("exploratory.outbound.quantity", obNum); - m_ExploratoryPool = CreateTunnelPool (ibLen, obLen, ibNum, obNum); + m_ExploratoryPool = CreateTunnelPool (ibLen, obLen, ibNum, obNum); m_ExploratoryPool->SetLocalDestination (i2p::context.GetSharedDestination ()); } return; } - if (m_OutboundTunnels.empty () || m_InboundTunnels.size () < 3) + if (m_OutboundTunnels.empty () || m_InboundTunnels.size () < 3) { // trying to create one more inbound tunnel auto router = i2p::transport::transports.RoutesRestricted() ? @@ -783,7 +783,7 @@ namespace tunnel m_Tunnels.erase (tunnel->GetTunnelID ()); it = m_TransitTunnels.erase (it); } - else + else { tunnel->Cleanup (); it++; @@ -820,14 +820,14 @@ namespace tunnel auto newTunnel = std::make_shared (config); uint32_t replyMsgID; RAND_bytes ((uint8_t *)&replyMsgID, 4); - AddPendingTunnel (replyMsgID, newTunnel); + AddPendingTunnel (replyMsgID, newTunnel); newTunnel->Build (replyMsgID, outboundTunnel); return newTunnel; } std::shared_ptr Tunnels::CreateInboundTunnel (std::shared_ptr config, std::shared_ptr outboundTunnel) { - if (config) + if (config) return CreateTunnel(config, outboundTunnel); else return CreateZeroHopsInboundTunnel (); @@ -843,12 +843,12 @@ namespace tunnel void Tunnels::AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr tunnel) { - m_PendingInboundTunnels[replyMsgID] = tunnel; + m_PendingInboundTunnels[replyMsgID] = tunnel; } void Tunnels::AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr tunnel) { - m_PendingOutboundTunnels[replyMsgID] = tunnel; + m_PendingOutboundTunnels[replyMsgID] = tunnel; } void Tunnels::AddOutboundTunnel (std::shared_ptr newTunnel) @@ -872,7 +872,7 @@ namespace tunnel { // build symmetric outbound tunnel CreateTunnel (std::make_shared(newTunnel->GetInvertedPeers (), - newTunnel->GetNextTunnelID (), newTunnel->GetNextIdentHash ()), + newTunnel->GetNextTunnelID (), newTunnel->GetNextIdentHash ()), GetNextOutboundTunnel ()); } else diff --git a/libi2pd/Tunnel.h b/libi2pd/Tunnel.h index 0c90c36c..38beccaa 100644 --- a/libi2pd/Tunnel.h +++ b/libi2pd/Tunnel.h @@ -36,7 +36,7 @@ namespace tunnel (void) t; #endif } - + template static void EmitTunnelEvent(const std::string & ev, TunnelT * t, const T & val) { @@ -46,7 +46,7 @@ namespace tunnel (void) ev; (void) t; (void) val; -#endif +#endif } template @@ -58,13 +58,13 @@ namespace tunnel (void) ev; (void) t; (void) val; -#endif +#endif } - - const int TUNNEL_EXPIRATION_TIMEOUT = 660; // 11 minutes - const int TUNNEL_EXPIRATION_THRESHOLD = 60; // 1 minute - const int TUNNEL_RECREATION_THRESHOLD = 90; // 1.5 minutes + + const int TUNNEL_EXPIRATION_TIMEOUT = 660; // 11 minutes + const int TUNNEL_EXPIRATION_THRESHOLD = 60; // 1 minute + const int TUNNEL_RECREATION_THRESHOLD = 90; // 1.5 minutes const int TUNNEL_CREATION_TIMEOUT = 30; // 30 seconds const int STANDARD_NUM_RECORDS = 5; // in VariableTunnelBuild message @@ -77,8 +77,8 @@ namespace tunnel eTunnelStateTestFailed, eTunnelStateFailed, eTunnelStateExpiring - }; - + }; + class OutboundTunnel; class InboundTunnel; class Tunnel: public TunnelBase @@ -87,18 +87,18 @@ namespace tunnel { std::shared_ptr ident; i2p::crypto::TunnelDecryption decryption; - }; - + }; + public: Tunnel (std::shared_ptr config); ~Tunnel (); void Build (uint32_t replyMsgID, std::shared_ptr outboundTunnel = nullptr); - + std::shared_ptr GetTunnelConfig () const { return m_Config; } - std::vector > GetPeers () const; - std::vector > GetInvertedPeers () const; + std::vector > GetPeers () const; + std::vector > GetInvertedPeers () const; TunnelState GetState () const { return m_State; }; void SetState (TunnelState state); bool IsEstablished () const { return m_State == eTunnelStateEstablished; }; @@ -106,17 +106,17 @@ namespace tunnel bool IsRecreated () const { return m_IsRecreated; }; void SetIsRecreated () { m_IsRecreated = true; }; virtual bool IsInbound() const = 0; - + std::shared_ptr GetTunnelPool () const { return m_Pool; }; - void SetTunnelPool (std::shared_ptr pool) { m_Pool = pool; }; - + void SetTunnelPool (std::shared_ptr pool) { m_Pool = pool; }; + bool HandleTunnelBuildResponse (uint8_t * msg, size_t len); virtual void Print (std::stringstream&) const {}; - + // implements TunnelBase void SendTunnelDataMsg (std::shared_ptr msg); - void EncryptTunnelMsg (std::shared_ptr in, std::shared_ptr out); + void EncryptTunnelMsg (std::shared_ptr in, std::shared_ptr out); /** @brief add latency sample */ void AddLatencySample(const uint64_t ms) { m_Latency = (m_Latency + ms) >> 1; } @@ -124,12 +124,12 @@ namespace tunnel uint64_t GetMeanLatency() const { return m_Latency; } /** @brief return true if this tunnel's latency fits in range [lowerbound, upperbound] */ bool LatencyFitsRange(uint64_t lowerbound, uint64_t upperbound) const; - + bool LatencyIsKnown() const { return m_Latency > 0; } protected: void PrintHops (std::stringstream& s) const; - + private: std::shared_ptr m_Config; @@ -138,30 +138,30 @@ namespace tunnel TunnelState m_State; bool m_IsRecreated; uint64_t m_Latency; // in milliseconds - }; + }; - class OutboundTunnel: public Tunnel + class OutboundTunnel: public Tunnel { public: - OutboundTunnel (std::shared_ptr config): + OutboundTunnel (std::shared_ptr config): Tunnel (config), m_Gateway (this), m_EndpointIdentHash (config->GetLastIdentHash ()) {}; void SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, std::shared_ptr msg); virtual void SendTunnelDataMsg (const std::vector& msgs); // multiple messages - const i2p::data::IdentHash& GetEndpointIdentHash () const { return m_EndpointIdentHash; }; + const i2p::data::IdentHash& GetEndpointIdentHash () const { return m_EndpointIdentHash; }; virtual size_t GetNumSentBytes () const { return m_Gateway.GetNumSentBytes (); }; void Print (std::stringstream& s) const; - + // implements TunnelBase void HandleTunnelDataMsg (std::shared_ptr tunnelMsg); bool IsInbound() const { return false; } - + private: std::mutex m_SendMutex; - TunnelGateway m_Gateway; + TunnelGateway m_Gateway; i2p::data::IdentHash m_EndpointIdentHash; }; @@ -176,27 +176,27 @@ namespace tunnel bool IsInbound() const { return true; } // override TunnelBase - void Cleanup () { m_Endpoint.Cleanup (); }; + void Cleanup () { m_Endpoint.Cleanup (); }; private: - TunnelEndpoint m_Endpoint; - }; - + TunnelEndpoint m_Endpoint; + }; + class ZeroHopsInboundTunnel: public InboundTunnel { public: ZeroHopsInboundTunnel (); - void SendTunnelDataMsg (std::shared_ptr msg); + void SendTunnelDataMsg (std::shared_ptr msg); void Print (std::stringstream& s) const; size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; - + private: size_t m_NumReceivedBytes; - }; - + }; + class ZeroHopsOutboundTunnel: public OutboundTunnel { public: @@ -205,23 +205,23 @@ namespace tunnel void SendTunnelDataMsg (const std::vector& msgs); void Print (std::stringstream& s) const; size_t GetNumSentBytes () const { return m_NumSentBytes; }; - + private: size_t m_NumSentBytes; - }; + }; class Tunnels - { + { public: Tunnels (); ~Tunnels (); void Start (); - void Stop (); - - std::shared_ptr GetPendingInboundTunnel (uint32_t replyMsgID); - std::shared_ptr GetPendingOutboundTunnel (uint32_t replyMsgID); + void Stop (); + + std::shared_ptr GetPendingInboundTunnel (uint32_t replyMsgID); + std::shared_ptr GetPendingOutboundTunnel (uint32_t replyMsgID); std::shared_ptr GetNextInboundTunnel (); std::shared_ptr GetNextOutboundTunnel (); std::shared_ptr GetExploratoryPool () const { return m_ExploratoryPool; }; @@ -236,22 +236,22 @@ namespace tunnel void PostTunnelData (const std::vector >& msgs); void AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr tunnel); void AddPendingTunnel (uint32_t replyMsgID, std::shared_ptr tunnel); - std::shared_ptr CreateTunnelPool (int numInboundHops, + std::shared_ptr CreateTunnelPool (int numInboundHops, int numOuboundHops, int numInboundTunnels, int numOutboundTunnels); void DeleteTunnelPool (std::shared_ptr pool); void StopTunnelPool (std::shared_ptr pool); - + private: - + template std::shared_ptr CreateTunnel (std::shared_ptr config, std::shared_ptr outboundTunnel = nullptr); template - std::shared_ptr GetPendingTunnel (uint32_t replyMsgID, const std::map >& pendingTunnels); + std::shared_ptr GetPendingTunnel (uint32_t replyMsgID, const std::map >& pendingTunnels); void HandleTunnelGatewayMsg (std::shared_ptr tunnel, std::shared_ptr msg); - void Run (); + void Run (); void ManageTunnels (); void ManageOutboundTunnels (); void ManageInboundTunnels (); @@ -260,14 +260,14 @@ namespace tunnel template void ManagePendingTunnels (PendingTunnels& pendingTunnels); void ManageTunnelPools (); - + std::shared_ptr CreateZeroHopsInboundTunnel (); - std::shared_ptr CreateZeroHopsOutboundTunnel (); + std::shared_ptr CreateZeroHopsOutboundTunnel (); private: bool m_IsRunning; - std::thread * m_Thread; + std::thread * m_Thread; std::map > m_PendingInboundTunnels; // by replyMsgID std::map > m_PendingOutboundTunnels; // by replyMsgID std::list > m_InboundTunnels; @@ -292,17 +292,17 @@ namespace tunnel size_t CountTransitTunnels() const; size_t CountInboundTunnels() const; size_t CountOutboundTunnels() const; - + int GetQueueSize () { return m_Queue.GetSize (); }; int GetTunnelCreationSuccessRate () const // in percents - { + { int totalNum = m_NumSuccesiveTunnelCreations + m_NumFailedTunnelCreations; return totalNum ? m_NumSuccesiveTunnelCreations*100/totalNum : 0; - } - }; + } + }; extern Tunnels tunnels; -} +} } #endif diff --git a/libi2pd/TunnelBase.h b/libi2pd/TunnelBase.h index 770badf8..8b7fb408 100644 --- a/libi2pd/TunnelBase.h +++ b/libi2pd/TunnelBase.h @@ -14,17 +14,17 @@ namespace tunnel const size_t TUNNEL_DATA_MSG_SIZE = 1028; const size_t TUNNEL_DATA_ENCRYPTED_SIZE = 1008; const size_t TUNNEL_DATA_MAX_PAYLOAD_SIZE = 1003; - - enum TunnelDeliveryType - { - eDeliveryTypeLocal = 0, + + enum TunnelDeliveryType + { + eDeliveryTypeLocal = 0, eDeliveryTypeTunnel = 1, eDeliveryTypeRouter = 2 - }; + }; struct TunnelMessageBlock { TunnelDeliveryType deliveryType; - i2p::data::IdentHash hash; + i2p::data::IdentHash hash; uint32_t tunnelID; std::shared_ptr data; }; @@ -33,12 +33,12 @@ namespace tunnel { public: - TunnelBase (uint32_t tunnelID, uint32_t nextTunnelID, i2p::data::IdentHash nextIdent): + TunnelBase (uint32_t tunnelID, uint32_t nextTunnelID, i2p::data::IdentHash nextIdent): m_TunnelID (tunnelID), m_NextTunnelID (nextTunnelID), m_NextIdent (nextIdent), m_CreationTime (i2p::util::GetSecondsSinceEpoch ()) {}; virtual ~TunnelBase () {}; virtual void Cleanup () {}; - + virtual void HandleTunnelDataMsg (std::shared_ptr tunnelMsg) = 0; virtual void SendTunnelDataMsg (std::shared_ptr msg) = 0; virtual void FlushTunnelDataMsgs () {}; @@ -49,24 +49,24 @@ namespace tunnel uint32_t GetCreationTime () const { return m_CreationTime; }; void SetCreationTime (uint32_t t) { m_CreationTime = t; }; - + private: uint32_t m_TunnelID, m_NextTunnelID; i2p::data::IdentHash m_NextIdent; uint32_t m_CreationTime; // seconds since epoch - }; + }; struct TunnelCreationTimeCmp { bool operator() (std::shared_ptr t1, std::shared_ptr t2) const - { + { if (t1->GetCreationTime () != t2->GetCreationTime ()) - return t1->GetCreationTime () > t2->GetCreationTime (); + return t1->GetCreationTime () > t2->GetCreationTime (); else return t1 < t2; }; - }; + }; } } diff --git a/libi2pd/TunnelConfig.h b/libi2pd/TunnelConfig.h index 10e980ad..7267fc30 100644 --- a/libi2pd/TunnelConfig.h +++ b/libi2pd/TunnelConfig.h @@ -23,11 +23,11 @@ namespace tunnel uint8_t ivKey[32]; uint8_t replyKey[32]; uint8_t replyIV[16]; - bool isGateway, isEndpoint; - + bool isGateway, isEndpoint; + TunnelHopConfig * next, * prev; int recordIndex; // record # in tunnel build message - + TunnelHopConfig (std::shared_ptr r) { RAND_bytes (layerKey, 32); @@ -37,20 +37,20 @@ namespace tunnel RAND_bytes ((uint8_t *)&tunnelID, 4); isGateway = true; isEndpoint = true; - ident = r; - //nextRouter = nullptr; + ident = r; + //nextRouter = nullptr; nextTunnelID = 0; next = nullptr; prev = nullptr; - } + } void SetNextIdent (const i2p::data::IdentHash& ident) { nextIdent = ident; isEndpoint = false; RAND_bytes ((uint8_t *)&nextTunnelID, 4); - } + } void SetReplyHop (uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent) { @@ -58,35 +58,35 @@ namespace tunnel nextTunnelID = replyTunnelID; isEndpoint = true; } - + void SetNext (TunnelHopConfig * n) { next = n; if (next) - { + { next->prev = this; next->isGateway = false; isEndpoint = false; nextIdent = next->ident->GetIdentHash (); nextTunnelID = next->tunnelID; - } + } } void SetPrev (TunnelHopConfig * p) { prev = p; - if (prev) - { + if (prev) + { prev->next = this; prev->isEndpoint = false; isGateway = false; - } + } } void CreateBuildRequestRecord (uint8_t * record, uint32_t replyMsgID, BN_CTX * ctx) const { uint8_t clearText[BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE]; - htobe32buf (clearText + BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET, tunnelID); + htobe32buf (clearText + BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET, tunnelID); memcpy (clearText + BUILD_REQUEST_RECORD_OUR_IDENT_OFFSET, ident->GetIdentHash (), 32); htobe32buf (clearText + BUILD_REQUEST_RECORD_NEXT_TUNNEL_OFFSET, nextTunnelID); memcpy (clearText + BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, nextIdent, 32); @@ -98,44 +98,44 @@ namespace tunnel if (isGateway) flag |= 0x80; if (isEndpoint) flag |= 0x40; clearText[BUILD_REQUEST_RECORD_FLAG_OFFSET] = flag; - htobe32buf (clearText + BUILD_REQUEST_RECORD_REQUEST_TIME_OFFSET, i2p::util::GetHoursSinceEpoch ()); - htobe32buf (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET, replyMsgID); + htobe32buf (clearText + BUILD_REQUEST_RECORD_REQUEST_TIME_OFFSET, i2p::util::GetHoursSinceEpoch ()); + htobe32buf (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET, replyMsgID); RAND_bytes (clearText + BUILD_REQUEST_RECORD_PADDING_OFFSET, BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE - BUILD_REQUEST_RECORD_PADDING_OFFSET); i2p::crypto::ElGamalEncrypt (ident->GetEncryptionPublicKey (), clearText, record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, ctx); memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)ident->GetIdentHash (), 16); - } - }; + } + }; class TunnelConfig { - public: - + public: + TunnelConfig (std::vector > peers) // inbound { CreatePeers (peers); m_LastHop->SetNextIdent (i2p::context.GetIdentHash ()); } - TunnelConfig (std::vector > peers, + TunnelConfig (std::vector > peers, uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent) // outbound { CreatePeers (peers); m_FirstHop->isGateway = false; m_LastHop->SetReplyHop (replyTunnelID, replyIdent); } - + ~TunnelConfig () { TunnelHopConfig * hop = m_FirstHop; - + while (hop) { auto tmp = hop; hop = hop->next; delete tmp; - } + } } - + TunnelHopConfig * GetFirstHop () const { return m_FirstHop; @@ -149,63 +149,63 @@ namespace tunnel int GetNumHops () const { int num = 0; - TunnelHopConfig * hop = m_FirstHop; + TunnelHopConfig * hop = m_FirstHop; while (hop) { num++; hop = hop->next; - } + } return num; } bool IsEmpty () const { return !m_FirstHop; - } + } virtual bool IsInbound () const { return m_FirstHop->isGateway; } - virtual uint32_t GetTunnelID () const - { + virtual uint32_t GetTunnelID () const + { if (!m_FirstHop) return 0; - return IsInbound () ? m_LastHop->nextTunnelID : m_FirstHop->tunnelID; + return IsInbound () ? m_LastHop->nextTunnelID : m_FirstHop->tunnelID; } - virtual uint32_t GetNextTunnelID () const - { + virtual uint32_t GetNextTunnelID () const + { if (!m_FirstHop) return 0; - return m_FirstHop->tunnelID; + return m_FirstHop->tunnelID; } - virtual const i2p::data::IdentHash& GetNextIdentHash () const - { - return m_FirstHop->ident->GetIdentHash (); - } + virtual const i2p::data::IdentHash& GetNextIdentHash () const + { + return m_FirstHop->ident->GetIdentHash (); + } + + virtual const i2p::data::IdentHash& GetLastIdentHash () const + { + return m_LastHop->ident->GetIdentHash (); + } - virtual const i2p::data::IdentHash& GetLastIdentHash () const - { - return m_LastHop->ident->GetIdentHash (); - } - std::vector > GetPeers () const { std::vector > peers; - TunnelHopConfig * hop = m_FirstHop; + TunnelHopConfig * hop = m_FirstHop; while (hop) { peers.push_back (hop->ident); hop = hop->next; - } + } return peers; } - + protected: // this constructor can't be called from outside TunnelConfig (): m_FirstHop (nullptr), m_LastHop (nullptr) { } - + private: template @@ -217,13 +217,13 @@ namespace tunnel auto hop = new TunnelHopConfig (it); if (prev) prev->SetNext (hop); - else + else m_FirstHop = hop; prev = hop; - } + } m_LastHop = prev; } - + private: TunnelHopConfig * m_FirstHop, * m_LastHop; @@ -235,7 +235,7 @@ namespace tunnel ZeroHopsTunnelConfig () { RAND_bytes ((uint8_t *)&m_TunnelID, 4);}; - bool IsInbound () const { return true; }; // TODO: + bool IsInbound () const { return true; }; // TODO: uint32_t GetTunnelID () const { return m_TunnelID; }; uint32_t GetNextTunnelID () const { return m_TunnelID; }; const i2p::data::IdentHash& GetNextIdentHash () const { return i2p::context.GetIdentHash (); }; @@ -243,10 +243,10 @@ namespace tunnel private: - - uint32_t m_TunnelID; - }; -} -} + + uint32_t m_TunnelID; + }; +} +} #endif diff --git a/libi2pd/TunnelEndpoint.cpp b/libi2pd/TunnelEndpoint.cpp index aec53e66..324d5315 100644 --- a/libi2pd/TunnelEndpoint.cpp +++ b/libi2pd/TunnelEndpoint.cpp @@ -15,16 +15,16 @@ namespace tunnel { TunnelEndpoint::~TunnelEndpoint () { - } - + } + void TunnelEndpoint::HandleDecryptedTunnelDataMsg (std::shared_ptr msg) { m_NumReceivedBytes += TUNNEL_DATA_MSG_SIZE; - + uint8_t * decrypted = msg->GetPayload () + 20; // 4 + 16 uint8_t * zero = (uint8_t *)memchr (decrypted + 4, 0, TUNNEL_DATA_ENCRYPTED_SIZE - 4); // witout 4-byte checksum if (zero) - { + { uint8_t * fragment = zero + 1; // verify checksum memcpy (msg->GetPayload () + TUNNEL_DATA_MSG_SIZE, msg->GetPayload () + 4, 16); // copy iv to the end @@ -34,58 +34,58 @@ namespace tunnel { LogPrint (eLogError, "TunnelMessage: checksum verification failed"); return; - } + } // process fragments while (fragment < decrypted + TUNNEL_DATA_ENCRYPTED_SIZE) { uint8_t flag = fragment[0]; fragment++; - - bool isFollowOnFragment = flag & 0x80, isLastFragment = true; + + bool isFollowOnFragment = flag & 0x80, isLastFragment = true; uint32_t msgID = 0; int fragmentNum = 0; TunnelMessageBlockEx m; if (!isFollowOnFragment) - { + { // first fragment - + m.deliveryType = (TunnelDeliveryType)((flag >> 5) & 0x03); switch (m.deliveryType) { case eDeliveryTypeLocal: // 0 break; - case eDeliveryTypeTunnel: // 1 + case eDeliveryTypeTunnel: // 1 m.tunnelID = bufbe32toh (fragment); fragment += 4; // tunnelID m.hash = i2p::data::IdentHash (fragment); fragment += 32; // hash break; case eDeliveryTypeRouter: // 2 - m.hash = i2p::data::IdentHash (fragment); + m.hash = i2p::data::IdentHash (fragment); fragment += 32; // to hash break; default: ; - } + } bool isFragmented = flag & 0x08; if (isFragmented) { // Message ID - msgID = bufbe32toh (fragment); + msgID = bufbe32toh (fragment); fragment += 4; isLastFragment = false; - } + } } else { // follow on - msgID = bufbe32toh (fragment); // MessageID - fragment += 4; + msgID = bufbe32toh (fragment); // MessageID + fragment += 4; fragmentNum = (flag >> 1) & 0x3F; // 6 bits isLastFragment = flag & 0x01; - } - + } + uint16_t size = bufbe16toh (fragment); fragment += 2; @@ -106,7 +106,7 @@ namespace tunnel } else m.data = msg; - + if (!isFollowOnFragment && isLastFragment) HandleNextMessage (m); else @@ -127,18 +127,18 @@ namespace tunnel { m.nextFragmentNum = fragmentNum; HandleFollowOnFragment (msgID, isLastFragment, m); - } + } } - else + else LogPrint (eLogError, "TunnelMessage: Message is fragmented, but msgID is not presented"); - } - + } + fragment += size; - } - } + } + } else LogPrint (eLogError, "TunnelMessage: zero not found"); - } + } void TunnelEndpoint::HandleFollowOnFragment (uint32_t msgID, bool isLastFragment, const TunnelMessageBlockEx& m) { @@ -151,7 +151,7 @@ namespace tunnel if (m.nextFragmentNum == msg.nextFragmentNum) { if (msg.data->len + size < I2NP_MAX_MESSAGE_SIZE) // check if message is not too long - { + { if (msg.data->len + size > msg.data->maxLen) { // LogPrint (eLogWarning, "TunnelMessage: I2NP message size ", msg.data->maxLen, " is not enough"); @@ -164,14 +164,14 @@ namespace tunnel if (isLastFragment) { // message complete - HandleNextMessage (msg); - m_IncompleteMessages.erase (it); - } + HandleNextMessage (msg); + m_IncompleteMessages.erase (it); + } else - { + { msg.nextFragmentNum++; HandleOutOfSequenceFragments (msgID, msg); - } + } } else { @@ -180,31 +180,31 @@ namespace tunnel } } else - { + { LogPrint (eLogWarning, "TunnelMessage: Unexpected fragment ", (int)m.nextFragmentNum, " instead ", (int)msg.nextFragmentNum, " of message ", msgID, ", saved"); AddOutOfSequenceFragment (msgID, m.nextFragmentNum, isLastFragment, m.data); } } else - { + { LogPrint (eLogWarning, "TunnelMessage: First fragment of message ", msgID, " not found, saved"); AddOutOfSequenceFragment (msgID, m.nextFragmentNum, isLastFragment, m.data); - } - } + } + } void TunnelEndpoint::AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, std::shared_ptr data) { if (!m_OutOfSequenceFragments.insert ({{msgID, fragmentNum}, {isLastFragment, data, i2p::util::GetMillisecondsSinceEpoch () }}).second) LogPrint (eLogInfo, "TunnelMessage: duplicate out-of-sequence fragment ", fragmentNum, " of message ", msgID); - } + } void TunnelEndpoint::HandleOutOfSequenceFragments (uint32_t msgID, TunnelMessageBlockEx& msg) { - while (ConcatNextOutOfSequenceFragment (msgID, msg)) + while (ConcatNextOutOfSequenceFragment (msgID, msg)) { if (!msg.nextFragmentNum) // message complete { - HandleNextMessage (msg); + HandleNextMessage (msg); m_IncompleteMessages.erase (msgID); break; } @@ -215,7 +215,7 @@ namespace tunnel { auto it = m_OutOfSequenceFragments.find ({msgID, msg.nextFragmentNum}); if (it != m_OutOfSequenceFragments.end ()) - { + { LogPrint (eLogDebug, "TunnelMessage: Out-of-sequence fragment ", (int)msg.nextFragmentNum, " of message ", msgID, " found"); size_t size = it->second.data->GetLength (); if (msg.data->len + size > msg.data->maxLen) @@ -233,21 +233,21 @@ namespace tunnel else msg.nextFragmentNum++; m_OutOfSequenceFragments.erase (it); - return true; - } + return true; + } return false; - } - + } + void TunnelEndpoint::HandleNextMessage (const TunnelMessageBlock& msg) { if (!m_IsInbound && msg.data->IsExpired ()) { LogPrint (eLogInfo, "TunnelMessage: message expired"); return; - } + } uint8_t typeID = msg.data->GetTypeID (); LogPrint (eLogDebug, "TunnelMessage: handle fragment of ", msg.data->GetLength (), " bytes, msg type ", (int)typeID); - // catch RI or reply with new list of routers + // catch RI or reply with new list of routers if ((IsRouterInfoMsg (msg.data) || typeID == eI2NPDatabaseSearchReply) && !m_IsInbound && msg.deliveryType != eDeliveryTypeLocal) i2p::data::netdb.PostI2NPMsg (CopyI2NPMessage (msg.data)); @@ -263,15 +263,15 @@ namespace tunnel else LogPrint (eLogError, "TunnelMessage: Delivery type 'tunnel' arrived from an inbound tunnel, dropped"); break; - case eDeliveryTypeRouter: + case eDeliveryTypeRouter: if (!m_IsInbound) // outbound transit tunnel i2p::transport::transports.SendMessage (msg.hash, msg.data); - else // we shouldn't send this message. possible leakage + else // we shouldn't send this message. possible leakage LogPrint (eLogError, "TunnelMessage: Delivery type 'router' arrived from an inbound tunnel, dropped"); break; default: LogPrint (eLogError, "TunnelMessage: Unknown delivery type ", (int)msg.deliveryType); - }; + }; } void TunnelEndpoint::Cleanup () @@ -293,6 +293,6 @@ namespace tunnel else ++it; } - } -} + } +} } diff --git a/libi2pd/TunnelEndpoint.h b/libi2pd/TunnelEndpoint.h index e13ced34..c2ffe53d 100644 --- a/libi2pd/TunnelEndpoint.h +++ b/libi2pd/TunnelEndpoint.h @@ -12,26 +12,26 @@ namespace i2p namespace tunnel { class TunnelEndpoint - { + { struct TunnelMessageBlockEx: public TunnelMessageBlock { uint64_t receiveTime; // milliseconds since epoch uint8_t nextFragmentNum; - }; + }; struct Fragment { bool isLastFragment; std::shared_ptr data; uint64_t receiveTime; // milliseconds since epoch - }; - + }; + public: TunnelEndpoint (bool isInbound): m_IsInbound (isInbound), m_NumReceivedBytes (0) {}; ~TunnelEndpoint (); size_t GetNumReceivedBytes () const { return m_NumReceivedBytes; }; - void Cleanup (); + void Cleanup (); void HandleDecryptedTunnelDataMsg (std::shared_ptr msg); @@ -42,16 +42,16 @@ namespace tunnel void AddOutOfSequenceFragment (uint32_t msgID, uint8_t fragmentNum, bool isLastFragment, std::shared_ptr data); bool ConcatNextOutOfSequenceFragment (uint32_t msgID, TunnelMessageBlockEx& msg); // true if something added - void HandleOutOfSequenceFragments (uint32_t msgID, TunnelMessageBlockEx& msg); + void HandleOutOfSequenceFragments (uint32_t msgID, TunnelMessageBlockEx& msg); - private: + private: std::map m_IncompleteMessages; std::map, Fragment> m_OutOfSequenceFragments; // (msgID, fragment#)->fragment bool m_IsInbound; size_t m_NumReceivedBytes; - }; -} + }; +} } #endif diff --git a/libi2pd/TunnelGateway.cpp b/libi2pd/TunnelGateway.cpp index f8c5d031..e6bfdd84 100644 --- a/libi2pd/TunnelGateway.cpp +++ b/libi2pd/TunnelGateway.cpp @@ -10,8 +10,8 @@ namespace i2p { namespace tunnel { - TunnelGatewayBuffer::TunnelGatewayBuffer (): - m_CurrentTunnelDataMsg (nullptr), m_RemainingSize (0) + TunnelGatewayBuffer::TunnelGatewayBuffer (): + m_CurrentTunnelDataMsg (nullptr), m_RemainingSize (0) { RAND_bytes (m_NonZeroRandomBuffer, TUNNEL_DATA_MAX_PAYLOAD_SIZE); for (size_t i = 0; i < TUNNEL_DATA_MAX_PAYLOAD_SIZE; i++) @@ -21,31 +21,31 @@ namespace tunnel TunnelGatewayBuffer::~TunnelGatewayBuffer () { ClearTunnelDataMsgs (); - } - + } + void TunnelGatewayBuffer::PutI2NPMsg (const TunnelMessageBlock& block) { bool messageCreated = false; if (!m_CurrentTunnelDataMsg) - { + { CreateCurrentTunnelDataMessage (); messageCreated = true; - } + } // create delivery instructions uint8_t di[43]; // max delivery instruction length is 43 for tunnel size_t diLen = 1;// flag if (block.deliveryType != eDeliveryTypeLocal) // tunnel or router - { + { if (block.deliveryType == eDeliveryTypeTunnel) { htobe32buf (di + diLen, block.tunnelID); diLen += 4; // tunnelID } - + memcpy (di + diLen, block.hash, 32); diLen += 32; //len - } + } di[0] = block.deliveryType << 5; // set delivery type // create fragments @@ -62,21 +62,21 @@ namespace tunnel m_RemainingSize -= diLen + msg->GetLength (); if (!m_RemainingSize) CompleteCurrentTunnelDataMessage (); - } + } else { if (!messageCreated) // check if we should complete previous message - { + { size_t numFollowOnFragments = fullMsgLen / TUNNEL_DATA_MAX_PAYLOAD_SIZE; // length of bytes don't fit full tunnel message // every follow-on fragment adds 7 bytes - size_t nonFit = (fullMsgLen + numFollowOnFragments*7) % TUNNEL_DATA_MAX_PAYLOAD_SIZE; + size_t nonFit = (fullMsgLen + numFollowOnFragments*7) % TUNNEL_DATA_MAX_PAYLOAD_SIZE; if (!nonFit || nonFit > m_RemainingSize) { CompleteCurrentTunnelDataMessage (); CreateCurrentTunnelDataMessage (); - } - } + } + } if (diLen + 6 <= m_RemainingSize) { // delivery instructions fit @@ -97,16 +97,16 @@ namespace tunnel // follow on fragments int fragmentNumber = 1; while (size < msg->GetLength ()) - { + { CreateCurrentTunnelDataMessage (); uint8_t * buf = m_CurrentTunnelDataMsg->GetBuffer (); buf[0] = 0x80 | (fragmentNumber << 1); // frag bool isLastFragment = false; size_t s = msg->GetLength () - size; if (s > TUNNEL_DATA_MAX_PAYLOAD_SIZE - 7) // 7 follow on instructions - s = TUNNEL_DATA_MAX_PAYLOAD_SIZE - 7; + s = TUNNEL_DATA_MAX_PAYLOAD_SIZE - 7; else // last fragment - { + { buf[0] |= 0x01; isLastFragment = true; } @@ -119,7 +119,7 @@ namespace tunnel if(m_RemainingSize < (s+7)) { LogPrint (eLogError, "TunnelGateway: remaining size overflow: ", m_RemainingSize, " < ", s+7); } else { - m_RemainingSize -= s+7; + m_RemainingSize -= s+7; if (m_RemainingSize == 0) CompleteCurrentTunnelDataMessage (); } @@ -129,17 +129,17 @@ namespace tunnel size += s; fragmentNumber++; } - } + } else { // delivery instructions don't fit. Create new message CompleteCurrentTunnelDataMessage (); PutI2NPMsg (block); // don't delete msg because it's taken care inside - } - } + } + } } - + void TunnelGatewayBuffer::ClearTunnelDataMsgs () { m_TunnelDataMsgs.clear (); @@ -155,49 +155,49 @@ namespace tunnel m_CurrentTunnelDataMsg->offset += TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE; m_CurrentTunnelDataMsg->len = m_CurrentTunnelDataMsg->offset; m_RemainingSize = TUNNEL_DATA_MAX_PAYLOAD_SIZE; - } - + } + void TunnelGatewayBuffer::CompleteCurrentTunnelDataMessage () { if (!m_CurrentTunnelDataMsg) return; uint8_t * payload = m_CurrentTunnelDataMsg->GetBuffer (); size_t size = m_CurrentTunnelDataMsg->len - m_CurrentTunnelDataMsg->offset; - + m_CurrentTunnelDataMsg->offset = m_CurrentTunnelDataMsg->len - TUNNEL_DATA_MSG_SIZE - I2NP_HEADER_SIZE; uint8_t * buf = m_CurrentTunnelDataMsg->GetPayload (); - RAND_bytes (buf + 4, 16); // original IV - memcpy (payload + size, buf + 4, 16); // copy IV for checksum + RAND_bytes (buf + 4, 16); // original IV + memcpy (payload + size, buf + 4, 16); // copy IV for checksum uint8_t hash[32]; SHA256(payload, size+16, hash); - memcpy (buf+20, hash, 4); // checksum - payload[-1] = 0; // zero - ptrdiff_t paddingSize = payload - buf - 25; // 25 = 24 + 1 + memcpy (buf+20, hash, 4); // checksum + payload[-1] = 0; // zero + ptrdiff_t paddingSize = payload - buf - 25; // 25 = 24 + 1 if (paddingSize > 0) { - // non-zero padding + // non-zero padding auto randomOffset = rand () % (TUNNEL_DATA_MAX_PAYLOAD_SIZE - paddingSize + 1); - memcpy (buf + 24, m_NonZeroRandomBuffer + randomOffset, paddingSize); + memcpy (buf + 24, m_NonZeroRandomBuffer + randomOffset, paddingSize); } // we can't fill message header yet because encryption is required m_TunnelDataMsgs.push_back (m_CurrentTunnelDataMsg); m_CurrentTunnelDataMsg = nullptr; - } + } void TunnelGateway::SendTunnelDataMsg (const TunnelMessageBlock& block) { if (block.data) - { + { PutTunnelDataMsg (block); SendBuffer (); - } - } + } + } void TunnelGateway::PutTunnelDataMsg (const TunnelMessageBlock& block) { if (block.data) m_Buffer.PutI2NPMsg (block); - } + } void TunnelGateway::SendBuffer () { @@ -205,17 +205,17 @@ namespace tunnel std::vector > newTunnelMsgs; const auto& tunnelDataMsgs = m_Buffer.GetTunnelDataMsgs (); for (auto& tunnelMsg : tunnelDataMsgs) - { + { auto newMsg = CreateEmptyTunnelDataMsg (); - m_Tunnel->EncryptTunnelMsg (tunnelMsg, newMsg); + m_Tunnel->EncryptTunnelMsg (tunnelMsg, newMsg); htobe32buf (newMsg->GetPayload (), m_Tunnel->GetNextTunnelID ()); - newMsg->FillI2NPMessageHeader (eI2NPTunnelData); + newMsg->FillI2NPMessageHeader (eI2NPTunnelData); newTunnelMsgs.push_back (newMsg); m_NumSentBytes += TUNNEL_DATA_MSG_SIZE; - } + } m_Buffer.ClearTunnelDataMsgs (); i2p::transport::transports.SendMessages (m_Tunnel->GetNextIdentHash (), newTunnelMsgs); - } -} -} + } +} +} diff --git a/libi2pd/TunnelGateway.h b/libi2pd/TunnelGateway.h index 3642874c..7959b57b 100644 --- a/libi2pd/TunnelGateway.h +++ b/libi2pd/TunnelGateway.h @@ -16,7 +16,7 @@ namespace tunnel public: TunnelGatewayBuffer (); ~TunnelGatewayBuffer (); - void PutI2NPMsg (const TunnelMessageBlock& block); + void PutI2NPMsg (const TunnelMessageBlock& block); const std::vector >& GetTunnelDataMsgs () const { return m_TunnelDataMsgs; }; void ClearTunnelDataMsgs (); void CompleteCurrentTunnelDataMessage (); @@ -24,14 +24,14 @@ namespace tunnel private: void CreateCurrentTunnelDataMessage (); - + private: std::vector > m_TunnelDataMsgs; std::shared_ptr m_CurrentTunnelDataMsg; size_t m_RemainingSize; uint8_t m_NonZeroRandomBuffer[TUNNEL_DATA_MAX_PAYLOAD_SIZE]; - }; + }; class TunnelGateway { @@ -39,18 +39,18 @@ namespace tunnel TunnelGateway (TunnelBase * tunnel): m_Tunnel (tunnel), m_NumSentBytes (0) {}; - void SendTunnelDataMsg (const TunnelMessageBlock& block); + void SendTunnelDataMsg (const TunnelMessageBlock& block); void PutTunnelDataMsg (const TunnelMessageBlock& block); - void SendBuffer (); + void SendBuffer (); size_t GetNumSentBytes () const { return m_NumSentBytes; }; - + private: TunnelBase * m_Tunnel; TunnelGatewayBuffer m_Buffer; size_t m_NumSentBytes; - }; -} -} + }; +} +} #endif diff --git a/libi2pd/TunnelPool.cpp b/libi2pd/TunnelPool.cpp index a3592708..52736fa0 100644 --- a/libi2pd/TunnelPool.cpp +++ b/libi2pd/TunnelPool.cpp @@ -298,13 +298,13 @@ namespace tunnel } if (!failed) { - uint32_t msgID; + uint32_t msgID; RAND_bytes ((uint8_t *)&msgID, 4); { std::unique_lock l(m_TestsMutex); - m_Tests[msgID] = std::make_pair (*it1, *it2); + m_Tests[msgID] = std::make_pair (*it1, *it2); } - (*it1)->SendTunnelDataMsg ((*it2)->GetNextIdentHash (), (*it2)->GetNextTunnelID (), + (*it1)->SendTunnelDataMsg ((*it2)->GetNextIdentHash (), (*it2)->GetNextTunnelID (), CreateDeliveryStatusMsg (msgID)); ++it1; ++it2; } diff --git a/libi2pd/api.cpp b/libi2pd/api.cpp index 022280f8..415118ff 100644 --- a/libi2pd/api.cpp +++ b/libi2pd/api.cpp @@ -28,23 +28,23 @@ namespace api i2p::fs::DetectDataDir(datadir, false); i2p::fs::Init(); -#if defined(__x86_64__) +#if defined(__x86_64__) i2p::crypto::InitCrypto (false); #else i2p::crypto::InitCrypto (true); -#endif +#endif int netID; i2p::config::GetOption("netid", netID); i2p::context.SetNetID (netID); - i2p::context.Init (); + i2p::context.Init (); } void TerminateI2P () { i2p::crypto::TerminateCrypto (); - } - + } + void StartI2P (std::shared_ptr logStream) { if (logStream) @@ -75,8 +75,8 @@ namespace api void RunPeerTest () { i2p::transport::transports.PeerTest (); - } - + } + std::shared_ptr CreateLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params) { @@ -119,8 +119,8 @@ namespace api else { RequestLeaseSet (dest, remote); - return nullptr; - } + return nullptr; + } } void AcceptStream (std::shared_ptr dest, const i2p::stream::StreamingDestination::Acceptor& acceptor) diff --git a/libi2pd/api.h b/libi2pd/api.h index c010d82f..f64590d1 100644 --- a/libi2pd/api.h +++ b/libi2pd/api.h @@ -11,18 +11,18 @@ namespace i2p { namespace api { - // initialization start and stop + // initialization start and stop void InitI2P (int argc, char* argv[], const char * appName); void TerminateI2P (); void StartI2P (std::shared_ptr logStream = nullptr); // write system log to logStream, if not specified to .log in application's folder void StopI2P (); void RunPeerTest (); // should be called after UPnP - + // destinations std::shared_ptr CreateLocalDestination (const i2p::data::PrivateKeys& keys, bool isPublic = true, - const std::map * params = nullptr); - std::shared_ptr CreateLocalDestination (bool isPublic = false, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256, + const std::map * params = nullptr); + std::shared_ptr CreateLocalDestination (bool isPublic = false, i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256, const std::map * params = nullptr); // transient destinations usually not published void DestroyLocalDestination (std::shared_ptr dest); diff --git a/libi2pd/util.cpp b/libi2pd/util.cpp index 5cc1fdb5..1395c2e6 100644 --- a/libi2pd/util.cpp +++ b/libi2pd/util.cpp @@ -8,7 +8,7 @@ #ifdef WIN32 #include #include -#include +#include #include #include #include @@ -167,7 +167,7 @@ namespace net } int GetMTUWindows(const boost::asio::ip::address& localAddress, int fallback) - { + { #ifdef UNICODE string localAddress_temporary = localAddress.to_string(); wstring localAddressUniversal(localAddress_temporary.begin(), localAddress_temporary.end()); @@ -181,7 +181,7 @@ namespace net return GetMTUWindowsIpv4(inputAddress, fallback); } else if(localAddress.is_v6()) { sockaddr_in6 inputAddress; - inet_pton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); + inet_pton(AF_INET6, localAddressUniversal.c_str(), &(inputAddress.sin6_addr)); return GetMTUWindowsIpv6(inputAddress, fallback); } else { LogPrint(eLogError, "NetIface: GetMTU(): address family is not supported"); @@ -193,27 +193,27 @@ namespace net int GetMTUUnix(const boost::asio::ip::address& localAddress, int fallback) { ifaddrs* ifaddr, *ifa = nullptr; - if(getifaddrs(&ifaddr) == -1) + if(getifaddrs(&ifaddr) == -1) { LogPrint(eLogError, "NetIface: Can't call getifaddrs(): ", strerror(errno)); return fallback; } int family = 0; - // look for interface matching local address - for(ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) + // look for interface matching local address + for(ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) { if(!ifa->ifa_addr) continue; family = ifa->ifa_addr->sa_family; - if(family == AF_INET && localAddress.is_v4()) + if(family == AF_INET && localAddress.is_v4()) { sockaddr_in* sa = (sockaddr_in*) ifa->ifa_addr; if(!memcmp(&sa->sin_addr, localAddress.to_v4().to_bytes().data(), 4)) break; // address matches - } - else if(family == AF_INET6 && localAddress.is_v6()) + } + else if(family == AF_INET6 && localAddress.is_v6()) { sockaddr_in6* sa = (sockaddr_in6*) ifa->ifa_addr; if(!memcmp(&sa->sin6_addr, localAddress.to_v6().to_bytes().data(), 16)) @@ -221,28 +221,28 @@ namespace net } } int mtu = fallback; - if(ifa && family) + if(ifa && family) { // interface found? int fd = socket(family, SOCK_DGRAM, 0); - if(fd > 0) + if(fd > 0) { ifreq ifr; strncpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ); // set interface for query - if(ioctl(fd, SIOCGIFMTU, &ifr) >= 0) + if(ioctl(fd, SIOCGIFMTU, &ifr) >= 0) mtu = ifr.ifr_mtu; // MTU else LogPrint (eLogError, "NetIface: Failed to run ioctl: ", strerror(errno)); close(fd); - } + } else LogPrint(eLogError, "NetIface: Failed to create datagram socket"); - } - else + } + else LogPrint(eLogWarning, "NetIface: interface for local address", localAddress.to_string(), " not found"); freeifaddrs(ifaddr); return mtu; - } + } #endif // WIN32 int GetMTU(const boost::asio::ip::address& localAddress) @@ -256,7 +256,7 @@ namespace net #endif return fallback; } - + const boost::asio::ip::address GetInterfaceAddress(const std::string & ifname, bool ipv6) { #ifdef WIN32 @@ -299,9 +299,9 @@ namespace net LogPrint(eLogWarning, "NetIface: cannot find ipv4 address for interface ", ifname); } return boost::asio::ip::address::from_string(fallback); - + #endif } -} +} } // util } // i2p diff --git a/libi2pd/util.h b/libi2pd/util.h index 813af0fb..e31e7b3f 100644 --- a/libi2pd/util.h +++ b/libi2pd/util.h @@ -38,15 +38,15 @@ namespace util public: MemoryPool (): m_Head (nullptr) {} - ~MemoryPool () - { - while (m_Head) + ~MemoryPool () + { + while (m_Head) { auto tmp = m_Head; m_Head = static_cast(*(void * *)m_Head); // next delete tmp; } - } + } template T * Acquire (TArgs&&... args) @@ -65,7 +65,7 @@ namespace util if (!t) return; t->~T (); *(void * *)t = m_Head; // next - m_Head = t; + m_Head = t; } template @@ -74,7 +74,7 @@ namespace util return std::unique_ptr >(Acquire (std::forward(args)...), std::bind (&MemoryPool::Release, this, std::placeholders::_1)); } - + template std::shared_ptr AcquireShared (TArgs&&... args) { @@ -85,7 +85,7 @@ namespace util protected: T * m_Head; - }; + }; template class MemoryPoolMt: public MemoryPool @@ -104,19 +104,19 @@ namespace util void ReleaseMt (T * t) { std::lock_guard l(m_Mutex); - this->Release (t); + this->Release (t); } templateclass C, typename... R> - void ReleaseMt(const C& c) + void ReleaseMt(const C& c) { std::lock_guard l(m_Mutex); for (auto& it: c) this->Release (it); - } + } private: - + std::mutex m_Mutex; }; diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index b40fadf6..4dfeeb53 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.cpp @@ -383,9 +383,9 @@ namespace client { it->second = ident->GetIdentHash (); m_Storage->AddAddress (ident); - LogPrint (eLogInfo, "Addressbook: updated host: ", name); + LogPrint (eLogInfo, "Addressbook: updated host: ", name); } - } + } else { m_Addresses.insert (std::make_pair (name, ident->GetIdentHash ())); @@ -720,7 +720,7 @@ namespace client i2p::http::HTTPReq req; req.AddHeader("Host", dest_host); req.AddHeader("User-Agent", "Wget/1.11.4"); - req.AddHeader("X-Accept-Encoding", "x-i2p-gzip;q=1.0, identity;q=0.5, deflate;q=0, gzip;q=0, *;q=0\r\n"); + req.AddHeader("X-Accept-Encoding", "x-i2p-gzip;q=1.0, identity;q=0.5, deflate;q=0, gzip;q=0, *;q=0"); req.AddHeader("Connection", "close"); if (!m_Etag.empty()) req.AddHeader("If-None-Match", m_Etag); diff --git a/libi2pd_client/AddressBook.h b/libi2pd_client/AddressBook.h index a1cb3def..3feb2ece 100644 --- a/libi2pd_client/AddressBook.h +++ b/libi2pd_client/AddressBook.h @@ -18,15 +18,15 @@ namespace i2p { namespace client { - const int INITIAL_SUBSCRIPTION_UPDATE_TIMEOUT = 3; // in minutes - const int INITIAL_SUBSCRIPTION_RETRY_TIMEOUT = 1; // in minutes - const int CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT = 720; // in minutes (12 hours) - const int CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT = 5; // in minutes + const int INITIAL_SUBSCRIPTION_UPDATE_TIMEOUT = 3; // in minutes + const int INITIAL_SUBSCRIPTION_RETRY_TIMEOUT = 1; // in minutes + const int CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT = 720; // in minutes (12 hours) + const int CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT = 5; // in minutes const int SUBSCRIPTION_REQUEST_TIMEOUT = 60; //in second - const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53; + const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53; const uint16_t ADDRESS_RESPONSE_DATAGRAM_PORT = 54; - + inline std::string GetB32Address(const i2p::data::IdentHash& ident) { return ident.ToBase32().append(".b32.i2p"); } class AddressBookStorage // interface for storage @@ -34,10 +34,10 @@ namespace client public: virtual ~AddressBookStorage () {}; - virtual std::shared_ptr GetAddress (const i2p::data::IdentHash& ident) const = 0; + virtual std::shared_ptr GetAddress (const i2p::data::IdentHash& ident) const = 0; virtual void AddAddress (std::shared_ptr address) = 0; virtual void RemoveAddress (const i2p::data::IdentHash& ident) = 0; - + virtual bool Init () = 0; virtual int Load (std::map& addresses) = 0; virtual int LoadLocal (std::map& addresses) = 0; @@ -45,7 +45,7 @@ namespace client virtual void SaveEtag (const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified) = 0; virtual bool GetEtag (const i2p::data::IdentHash& subscription, std::string& etag, std::string& lastModified) = 0; - }; + }; class AddressBookSubscription; class AddressResolver; @@ -77,7 +77,7 @@ namespace client void StartSubscriptions (); void StopSubscriptions (); - + void LoadHosts (); void LoadSubscriptions (); void LoadLocal (); @@ -87,8 +87,8 @@ namespace client void StartLookups (); void StopLookups (); void HandleLookupResponse (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); - - private: + + private: std::mutex m_AddressBookMutex; std::map m_Addresses; @@ -112,7 +112,7 @@ namespace client private: bool MakeRequest (); - + private: AddressBook& m_Book; diff --git a/libi2pd_client/BOB.cpp b/libi2pd_client/BOB.cpp index 6f2782df..2a18c8ba 100644 --- a/libi2pd_client/BOB.cpp +++ b/libi2pd_client/BOB.cpp @@ -8,7 +8,7 @@ namespace i2p { namespace client { - BOBI2PInboundTunnel::BOBI2PInboundTunnel (const boost::asio::ip::tcp::endpoint& ep, std::shared_ptr localDestination): + BOBI2PInboundTunnel::BOBI2PInboundTunnel (const boost::asio::ip::tcp::endpoint& ep, std::shared_ptr localDestination): BOBI2PTunnel (localDestination), m_Acceptor (localDestination->GetService (), ep) { } @@ -36,13 +36,13 @@ namespace client receiver->socket = std::make_shared (GetService ()); m_Acceptor.async_accept (*receiver->socket, std::bind (&BOBI2PInboundTunnel::HandleAccept, this, std::placeholders::_1, receiver)); - } + } void BOBI2PInboundTunnel::HandleAccept (const boost::system::error_code& ecode, std::shared_ptr receiver) { if (!ecode) { - Accept (); + Accept (); ReceiveAddress (receiver); } } @@ -50,12 +50,12 @@ namespace client void BOBI2PInboundTunnel::ReceiveAddress (std::shared_ptr receiver) { receiver->socket->async_read_some (boost::asio::buffer( - receiver->buffer + receiver->bufferOffset, - BOB_COMMAND_BUFFER_SIZE - receiver->bufferOffset), - std::bind(&BOBI2PInboundTunnel::HandleReceivedAddress, this, + receiver->buffer + receiver->bufferOffset, + BOB_COMMAND_BUFFER_SIZE - receiver->bufferOffset), + std::bind(&BOBI2PInboundTunnel::HandleReceivedAddress, this, std::placeholders::_1, std::placeholders::_2, receiver)); } - + void BOBI2PInboundTunnel::HandleReceivedAddress (const boost::system::error_code& ecode, std::size_t bytes_transferred, std::shared_ptr receiver) { @@ -69,11 +69,11 @@ namespace client if (eol) { *eol = 0; - if (eol != receiver->buffer && eol[-1] == '\r') eol[-1] = 0; // workaround for Transmission, it sends '\r\n' terminated address + if (eol != receiver->buffer && eol[-1] == '\r') eol[-1] = 0; // workaround for Transmission, it sends '\r\n' terminated address receiver->data = (uint8_t *)eol + 1; receiver->dataLen = receiver->bufferOffset - (eol - receiver->buffer + 1); i2p::data::IdentHash ident; - if (!context.GetAddressBook ().GetIdentHash (receiver->buffer, ident)) + if (!context.GetAddressBook ().GetIdentHash (receiver->buffer, ident)) { LogPrint (eLogError, "BOB: address ", receiver->buffer, " not found"); return; @@ -82,7 +82,7 @@ namespace client if (leaseSet) CreateConnection (receiver, leaseSet); else - GetLocalDestination ()->RequestDestination (ident, + GetLocalDestination ()->RequestDestination (ident, std::bind (&BOBI2PInboundTunnel::HandleDestinationRequestComplete, this, std::placeholders::_1, receiver)); } @@ -92,7 +92,7 @@ namespace client ReceiveAddress (receiver); else LogPrint (eLogError, "BOB: missing inbound address"); - } + } } } @@ -102,7 +102,7 @@ namespace client CreateConnection (receiver, leaseSet); else LogPrint (eLogError, "BOB: LeaseSet for inbound destination not found"); - } + } void BOBI2PInboundTunnel::CreateConnection (std::shared_ptr receiver, std::shared_ptr leaseSet) { @@ -112,12 +112,12 @@ namespace client connection->I2PConnect (receiver->data, receiver->dataLen); } - BOBI2POutboundTunnel::BOBI2POutboundTunnel (const std::string& address, int port, + BOBI2POutboundTunnel::BOBI2POutboundTunnel (const std::string& address, int port, std::shared_ptr localDestination, bool quiet): BOBI2PTunnel (localDestination), m_Endpoint (boost::asio::ip::address::from_string (address), port), m_IsQuiet (quiet) { } - + void BOBI2POutboundTunnel::Start () { Accept (); @@ -126,11 +126,11 @@ namespace client void BOBI2POutboundTunnel::Stop () { ClearHandlers (); - } + } void BOBI2POutboundTunnel::Accept () { - auto localDestination = GetLocalDestination (); + auto localDestination = GetLocalDestination (); if (localDestination) localDestination->AcceptStreams (std::bind (&BOBI2POutboundTunnel::HandleAccept, this, std::placeholders::_1)); else @@ -140,54 +140,54 @@ namespace client void BOBI2POutboundTunnel::HandleAccept (std::shared_ptr stream) { if (stream) - { + { auto conn = std::make_shared (this, stream, std::make_shared (GetService ()), m_Endpoint, m_IsQuiet); AddHandler (conn); conn->Connect (); - } + } } BOBDestination::BOBDestination (std::shared_ptr localDestination): - m_LocalDestination (localDestination), + m_LocalDestination (localDestination), m_OutboundTunnel (nullptr), m_InboundTunnel (nullptr) { } - + BOBDestination::~BOBDestination () { delete m_OutboundTunnel; delete m_InboundTunnel; i2p::client::context.DeleteLocalDestination (m_LocalDestination); - } + } void BOBDestination::Start () { if (m_OutboundTunnel) m_OutboundTunnel->Start (); if (m_InboundTunnel) m_InboundTunnel->Start (); } - + void BOBDestination::Stop () - { + { StopTunnels (); m_LocalDestination->Stop (); - } + } void BOBDestination::StopTunnels () { if (m_OutboundTunnel) - { + { m_OutboundTunnel->Stop (); delete m_OutboundTunnel; m_OutboundTunnel = nullptr; - } + } if (m_InboundTunnel) - { + { m_InboundTunnel->Stop (); delete m_InboundTunnel; m_InboundTunnel = nullptr; - } - } - + } + } + void BOBDestination::CreateInboundTunnel (int port, const std::string& address) { if (!m_InboundTunnel) @@ -200,21 +200,21 @@ namespace client if (!ec) ep.address (addr); else - LogPrint (eLogError, "BOB: ", ec.message ()); - } + LogPrint (eLogError, "BOB: ", ec.message ()); + } m_InboundTunnel = new BOBI2PInboundTunnel (ep, m_LocalDestination); } } - + void BOBDestination::CreateOutboundTunnel (const std::string& address, int port, bool quiet) { if (!m_OutboundTunnel) m_OutboundTunnel = new BOBI2POutboundTunnel (address, port, m_LocalDestination, quiet); - } - - BOBCommandSession::BOBCommandSession (BOBCommandChannel& owner): + } + + BOBCommandSession::BOBCommandSession (BOBCommandChannel& owner): m_Owner (owner), m_Socket (m_Owner.GetService ()), - m_ReceiveBufferOffset (0), m_IsOpen (true), m_IsQuiet (false), m_IsActive (false), + m_ReceiveBufferOffset (0), m_IsOpen (true), m_IsQuiet (false), m_IsActive (false), m_InPort (0), m_OutPort (0), m_CurrentDestination (nullptr) { } @@ -226,13 +226,13 @@ namespace client void BOBCommandSession::Terminate () { m_Socket.close (); - m_IsOpen = false; + m_IsOpen = false; } void BOBCommandSession::Receive () { - m_Socket.async_read_some (boost::asio::buffer(m_ReceiveBuffer + m_ReceiveBufferOffset, BOB_COMMAND_BUFFER_SIZE - m_ReceiveBufferOffset), - std::bind(&BOBCommandSession::HandleReceived, shared_from_this (), + m_Socket.async_read_some (boost::asio::buffer(m_ReceiveBuffer + m_ReceiveBufferOffset, BOB_COMMAND_BUFFER_SIZE - m_ReceiveBufferOffset), + std::bind(&BOBCommandSession::HandleReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } @@ -243,29 +243,29 @@ namespace client LogPrint (eLogError, "BOB: command channel read error: ", ecode.message ()); if (ecode != boost::asio::error::operation_aborted) Terminate (); - } + } else - { - size_t size = m_ReceiveBufferOffset + bytes_transferred; + { + size_t size = m_ReceiveBufferOffset + bytes_transferred; m_ReceiveBuffer[size] = 0; char * eol = strchr (m_ReceiveBuffer, '\n'); if (eol) { *eol = 0; char * operand = strchr (m_ReceiveBuffer, ' '); - if (operand) - { + if (operand) + { *operand = 0; operand++; - } - else + } + else operand = eol; // process command auto& handlers = m_Owner.GetCommandHandlers (); auto it = handlers.find (m_ReceiveBuffer); if (it != handlers.end ()) (this->*(it->second))(operand, eol - operand); - else + else { LogPrint (eLogError, "BOB: unknown command ", m_ReceiveBuffer); SendReplyError ("unknown command"); @@ -283,15 +283,15 @@ namespace client LogPrint (eLogError, "BOB: Malformed input of the command channel"); Terminate (); } - } + } } } void BOBCommandSession::Send (size_t len) { - boost::asio::async_write (m_Socket, boost::asio::buffer (m_SendBuffer, len), + boost::asio::async_write (m_Socket, boost::asio::buffer (m_SendBuffer, len), boost::asio::transfer_all (), - std::bind(&BOBCommandSession::HandleSent, shared_from_this (), + std::bind(&BOBCommandSession::HandleSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } @@ -308,7 +308,7 @@ namespace client if (m_IsOpen) Receive (); else - Terminate (); + Terminate (); } } @@ -316,7 +316,7 @@ namespace client { #ifdef _MSC_VER size_t len = sprintf_s (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_REPLY_OK, msg); -#else +#else size_t len = snprintf (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_REPLY_OK, msg); #endif Send (len); @@ -326,12 +326,12 @@ namespace client { #ifdef _MSC_VER size_t len = sprintf_s (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_REPLY_ERROR, msg); -#else +#else size_t len = snprintf (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_REPLY_ERROR, msg); #endif - Send (len); + Send (len); } - + void BOBCommandSession::SendVersion () { size_t len = strlen (BOB_VERSION); @@ -343,12 +343,12 @@ namespace client { #ifdef _MSC_VER size_t len = sprintf_s (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_DATA, nickname); -#else +#else size_t len = snprintf (m_SendBuffer, BOB_COMMAND_BUFFER_SIZE, BOB_DATA, nickname); #endif - Send (len); + Send (len); } - + void BOBCommandSession::ZapCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: zap"); @@ -368,21 +368,21 @@ namespace client if (m_IsActive) { SendReplyError ("tunnel is active"); - return; + return; } if (!m_CurrentDestination) - { + { m_CurrentDestination = new BOBDestination (i2p::client::context.CreateNewLocalDestination (m_Keys, true, &m_Options)); m_Owner.AddDestination (m_Nickname, m_CurrentDestination); - } + } if (m_InPort) m_CurrentDestination->CreateInboundTunnel (m_InPort, m_Address); if (m_OutPort && !m_Address.empty ()) m_CurrentDestination->CreateOutboundTunnel (m_Address, m_OutPort, m_IsQuiet); - m_CurrentDestination->Start (); + m_CurrentDestination->Start (); SendReplyOK ("Tunnel starting"); m_IsActive = true; - } + } void BOBCommandSession::StopCommandHandler (const char * operand, size_t len) { @@ -401,8 +401,8 @@ namespace client else SendReplyError ("tunnel not found"); m_IsActive = false; - } - + } + void BOBCommandSession::SetNickCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: setnick ", operand); @@ -410,30 +410,30 @@ namespace client std::string msg ("Nickname set to "); msg += m_Nickname; SendReplyOK (msg.c_str ()); - } + } void BOBCommandSession::GetNickCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: getnick ", operand); - m_CurrentDestination = m_Owner.FindDestination (operand); + m_CurrentDestination = m_Owner.FindDestination (operand); if (m_CurrentDestination) { m_Keys = m_CurrentDestination->GetKeys (); m_Nickname = operand; } if (m_Nickname == operand) - { + { std::string msg ("Nickname set to "); msg += m_Nickname; SendReplyOK (msg.c_str ()); - } + } else - SendReplyError ("no nickname has been set"); - } + SendReplyError ("no nickname has been set"); + } void BOBCommandSession::NewkeysCommandHandler (const char * operand, size_t len) { - LogPrint (eLogDebug, "BOB: newkeys"); + LogPrint (eLogDebug, "BOB: newkeys"); i2p::data::SigningKeyType signatureType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1; i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; if (*operand) @@ -441,23 +441,23 @@ namespace client try { char * operand1 = (char *)strchr (operand, ' '); - if (operand1) + if (operand1) { *operand1 = 0; operand1++; cryptoType = std::stoi(operand1); } - signatureType = std::stoi(operand); + signatureType = std::stoi(operand); } catch (std::invalid_argument& ex) { LogPrint (eLogWarning, "BOB: newkeys ", ex.what ()); } - } - - + } + + m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (signatureType, cryptoType); SendReplyOK (m_Keys.GetPublic ()->ToBase64 ().c_str ()); - } + } void BOBCommandSession::SetkeysCommandHandler (const char * operand, size_t len) { @@ -467,9 +467,9 @@ namespace client else SendReplyError ("invalid keys"); } - + void BOBCommandSession::GetkeysCommandHandler (const char * operand, size_t len) - { + { LogPrint (eLogDebug, "BOB: getkeys"); if (m_Keys.GetPublic ()) // keys are set ? SendReplyOK (m_Keys.ToBase64 ().c_str ()); @@ -484,15 +484,15 @@ namespace client SendReplyOK (m_Keys.GetPublic ()->ToBase64 ().c_str ()); else SendReplyError ("keys are not set"); - } - + } + void BOBCommandSession::OuthostCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: outhost ", operand); m_Address = operand; SendReplyOK ("outhost set"); } - + void BOBCommandSession::OutportCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: outport ", operand); @@ -501,7 +501,7 @@ namespace client SendReplyOK ("outbound port set"); else SendReplyError ("port out of range"); - } + } void BOBCommandSession::InhostCommandHandler (const char * operand, size_t len) { @@ -509,7 +509,7 @@ namespace client m_Address = operand; SendReplyOK ("inhost set"); } - + void BOBCommandSession::InportCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: inport ", operand); @@ -518,7 +518,7 @@ namespace client SendReplyOK ("inbound port set"); else SendReplyError ("port out of range"); - } + } void BOBCommandSession::QuietCommandHandler (const char * operand, size_t len) { @@ -535,17 +535,17 @@ namespace client } else SendReplyError ("no nickname has been set"); - } - + } + void BOBCommandSession::LookupCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: lookup ", operand); i2p::data::IdentHash ident; - if (!context.GetAddressBook ().GetIdentHash (operand, ident)) + if (!context.GetAddressBook ().GetIdentHash (operand, ident)) { SendReplyError ("Address Not found"); return; - } + } auto localDestination = m_CurrentDestination ? m_CurrentDestination->GetLocalDestination () : i2p::client::context.GetSharedLocalDestination (); auto leaseSet = localDestination->FindLeaseSet (ident); if (leaseSet) @@ -553,14 +553,14 @@ namespace client else { auto s = shared_from_this (); - localDestination->RequestDestination (ident, + localDestination->RequestDestination (ident, [s](std::shared_ptr ls) { if (ls) s->SendReplyOK (ls->GetIdentity ()->ToBase64 ().c_str ()); - else + else s->SendReplyError ("LeaseSet Not found"); - } + } ); } } @@ -571,7 +571,7 @@ namespace client m_Owner.DeleteDestination (m_Nickname); m_Nickname = ""; SendReplyOK ("cleared"); - } + } void BOBCommandSession::ListCommandHandler (const char * operand, size_t len) { @@ -580,26 +580,26 @@ namespace client for (const auto& it: destinations) SendData (it.first.c_str ()); SendReplyOK ("Listing done"); - } + } void BOBCommandSession::OptionCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: option ", operand); const char * value = strchr (operand, '='); if (value) - { + { std::string msg ("option "); *(const_cast(value)) = 0; - m_Options[operand] = value + 1; + m_Options[operand] = value + 1; msg += operand; *(const_cast(value)) = '='; msg += " set to "; - msg += value; + msg += value; SendReplyOK (msg.c_str ()); - } + } else SendReplyError ("malformed"); - } + } void BOBCommandSession::StatusCommandHandler (const char * operand, size_t len) { @@ -609,37 +609,37 @@ namespace client std::stringstream s; s << "DATA"; s << " NICKNAME: "; s << m_Nickname; if (m_CurrentDestination) - { + { if (m_CurrentDestination->GetLocalDestination ()->IsReady ()) s << " STARTING: false RUNNING: true STOPPING: false"; else s << " STARTING: true RUNNING: false STOPPING: false"; - } + } else s << " STARTING: false RUNNING: false STOPPING: false"; s << " KEYS: true"; s << " QUIET: "; s << (m_IsQuiet ? "true":"false"); if (m_InPort) - { + { s << " INPORT: " << m_InPort; s << " INHOST: " << (m_Address.length () > 0 ? m_Address : "127.0.0.1"); - } + } if (m_OutPort) - { + { s << " OUTPORT: " << m_OutPort; s << " OUTHOST: " << (m_Address.length () > 0 ? m_Address : "127.0.0.1"); - } + } SendReplyOK (s.str().c_str()); } else - SendReplyError ("no nickname has been set"); - } - + SendReplyError ("no nickname has been set"); + } + BOBCommandChannel::BOBCommandChannel (const std::string& address, int port): m_IsRunning (false), m_Thread (nullptr), m_Acceptor (m_Service, boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(address), port)) { // command -> handler - m_CommandHandlers[BOB_COMMAND_ZAP] = &BOBCommandSession::ZapCommandHandler; + m_CommandHandlers[BOB_COMMAND_ZAP] = &BOBCommandSession::ZapCommandHandler; m_CommandHandlers[BOB_COMMAND_QUIT] = &BOBCommandSession::QuitCommandHandler; m_CommandHandlers[BOB_COMMAND_START] = &BOBCommandSession::StartCommandHandler; m_CommandHandlers[BOB_COMMAND_STOP] = &BOBCommandSession::StopCommandHandler; @@ -680,35 +680,35 @@ namespace client m_IsRunning = false; for (auto& it: m_Destinations) it.second->Stop (); - m_Acceptor.cancel (); + m_Acceptor.cancel (); m_Service.stop (); if (m_Thread) - { - m_Thread->join (); + { + m_Thread->join (); delete m_Thread; m_Thread = nullptr; - } + } } - - void BOBCommandChannel::Run () - { + + void BOBCommandChannel::Run () + { while (m_IsRunning) { try - { + { m_Service.run (); } catch (std::exception& ex) { LogPrint (eLogError, "BOB: runtime exception: ", ex.what ()); - } - } + } + } } void BOBCommandChannel::AddDestination (const std::string& name, BOBDestination * dest) { m_Destinations[name] = dest; - } + } void BOBCommandChannel::DeleteDestination (const std::string& name) { @@ -718,17 +718,17 @@ namespace client it->second->Stop (); delete it->second; m_Destinations.erase (it); - } - } - + } + } + BOBDestination * BOBCommandChannel::FindDestination (const std::string& name) { auto it = m_Destinations.find (name); if (it != m_Destinations.end ()) return it->second; - return nullptr; + return nullptr; } - + void BOBCommandChannel::Accept () { auto newSession = std::make_shared (*this); @@ -744,7 +744,7 @@ namespace client if (!ecode) { LogPrint (eLogInfo, "BOB: New command connection from ", session->GetSocket ().remote_endpoint ()); - session->SendVersion (); + session->SendVersion (); } else LogPrint (eLogError, "BOB: accept error: ", ecode.message ()); diff --git a/libi2pd_client/BOB.h b/libi2pd_client/BOB.h index bd29dafd..a2a24164 100644 --- a/libi2pd_client/BOB.h +++ b/libi2pd_client/BOB.h @@ -20,25 +20,25 @@ namespace client const char BOB_COMMAND_ZAP[] = "zap"; const char BOB_COMMAND_QUIT[] = "quit"; const char BOB_COMMAND_START[] = "start"; - const char BOB_COMMAND_STOP[] = "stop"; + const char BOB_COMMAND_STOP[] = "stop"; const char BOB_COMMAND_SETNICK[] = "setnick"; - const char BOB_COMMAND_GETNICK[] = "getnick"; + const char BOB_COMMAND_GETNICK[] = "getnick"; const char BOB_COMMAND_NEWKEYS[] = "newkeys"; const char BOB_COMMAND_GETKEYS[] = "getkeys"; const char BOB_COMMAND_SETKEYS[] = "setkeys"; const char BOB_COMMAND_GETDEST[] = "getdest"; - const char BOB_COMMAND_OUTHOST[] = "outhost"; + const char BOB_COMMAND_OUTHOST[] = "outhost"; const char BOB_COMMAND_OUTPORT[] = "outport"; - const char BOB_COMMAND_INHOST[] = "inhost"; + const char BOB_COMMAND_INHOST[] = "inhost"; const char BOB_COMMAND_INPORT[] = "inport"; const char BOB_COMMAND_QUIET[] = "quiet"; - const char BOB_COMMAND_LOOKUP[] = "lookup"; + const char BOB_COMMAND_LOOKUP[] = "lookup"; const char BOB_COMMAND_CLEAR[] = "clear"; const char BOB_COMMAND_LIST[] = "list"; const char BOB_COMMAND_OPTION[] = "option"; - const char BOB_COMMAND_STATUS[] = "status"; - - const char BOB_VERSION[] = "BOB 00.00.10\nOK\n"; + const char BOB_COMMAND_STATUS[] = "status"; + + const char BOB_VERSION[] = "BOB 00.00.10\nOK\n"; const char BOB_REPLY_OK[] = "OK %s\n"; const char BOB_REPLY_ERROR[] = "ERROR %s\n"; const char BOB_DATA[] = "NICKNAME %s\n"; @@ -47,13 +47,13 @@ namespace client { public: - BOBI2PTunnel (std::shared_ptr localDestination): + BOBI2PTunnel (std::shared_ptr localDestination): I2PService (localDestination) {}; virtual void Start () {}; - virtual void Stop () {}; - }; - + virtual void Stop () {}; + }; + class BOBI2PInboundTunnel: public BOBI2PTunnel { struct AddressReceiver @@ -61,11 +61,11 @@ namespace client std::shared_ptr socket; char buffer[BOB_COMMAND_BUFFER_SIZE + 1]; // for destination base64 address uint8_t * data; // pointer to buffer - size_t dataLen, bufferOffset; + size_t dataLen, bufferOffset; AddressReceiver (): data (nullptr), dataLen (0), bufferOffset (0) {}; - }; - + }; + public: BOBI2PInboundTunnel (const boost::asio::ip::tcp::endpoint& ep, std::shared_ptr localDestination); @@ -89,14 +89,14 @@ namespace client private: - boost::asio::ip::tcp::acceptor m_Acceptor; + boost::asio::ip::tcp::acceptor m_Acceptor; }; class BOBI2POutboundTunnel: public BOBI2PTunnel { public: - BOBI2POutboundTunnel (const std::string& address, int port, std::shared_ptr localDestination, bool quiet); + BOBI2POutboundTunnel (const std::string& address, int port, std::shared_ptr localDestination, bool quiet); void Start (); void Stop (); @@ -110,8 +110,8 @@ namespace client private: - boost::asio::ip::tcp::endpoint m_Endpoint; - bool m_IsQuiet; + boost::asio::ip::tcp::endpoint m_Endpoint; + bool m_IsQuiet; }; @@ -129,21 +129,21 @@ namespace client void CreateOutboundTunnel (const std::string& address, int port, bool quiet); const i2p::data::PrivateKeys& GetKeys () const { return m_LocalDestination->GetPrivateKeys (); }; std::shared_ptr GetLocalDestination () const { return m_LocalDestination; }; - - private: + + private: std::shared_ptr m_LocalDestination; BOBI2POutboundTunnel * m_OutboundTunnel; BOBI2PInboundTunnel * m_InboundTunnel; - }; - + }; + class BOBCommandChannel; class BOBCommandSession: public std::enable_shared_from_this { public: BOBCommandSession (BOBCommandChannel& owner); - ~BOBCommandSession (); + ~BOBCommandSession (); void Terminate (); boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; }; @@ -163,14 +163,14 @@ namespace client void OuthostCommandHandler (const char * operand, size_t len); void OutportCommandHandler (const char * operand, size_t len); void InhostCommandHandler (const char * operand, size_t len); - void InportCommandHandler (const char * operand, size_t len); - void QuietCommandHandler (const char * operand, size_t len); + void InportCommandHandler (const char * operand, size_t len); + void QuietCommandHandler (const char * operand, size_t len); void LookupCommandHandler (const char * operand, size_t len); void ClearCommandHandler (const char * operand, size_t len); void ListCommandHandler (const char * operand, size_t len); void OptionCommandHandler (const char * operand, size_t len); void StatusCommandHandler (const char * operand, size_t len); - + private: void Receive (); @@ -192,7 +192,7 @@ namespace client std::string m_Nickname, m_Address; int m_InPort, m_OutPort; i2p::data::PrivateKeys m_Keys; - std::map m_Options; + std::map m_Options; BOBDestination * m_CurrentDestination; }; typedef void (BOBCommandSession::*BOBCommandHandler)(const char * operand, size_t len); @@ -211,7 +211,7 @@ namespace client void AddDestination (const std::string& name, BOBDestination * dest); void DeleteDestination (const std::string& name); BOBDestination * FindDestination (const std::string& name); - + private: void Run (); @@ -221,7 +221,7 @@ namespace client private: bool m_IsRunning; - std::thread * m_Thread; + std::thread * m_Thread; boost::asio::io_service m_Service; boost::asio::ip::tcp::acceptor m_Acceptor; std::map m_Destinations; @@ -231,7 +231,7 @@ namespace client const decltype(m_CommandHandlers)& GetCommandHandlers () const { return m_CommandHandlers; }; const decltype(m_Destinations)& GetDestinations () const { return m_Destinations; }; - }; + }; } } diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index db3a129d..41b8615a 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -108,7 +108,7 @@ namespace client try { m_SocksProxy = new i2p::proxy::SOCKSProxy("SOCKS", socksProxyAddr, socksProxyPort, - socksOutProxy, socksOutProxyAddr, socksOutProxyPort, localDestination); + socksOutProxy, socksOutProxyAddr, socksOutProxyPort, localDestination); m_SocksProxy->Start(); } catch (std::exception& e) @@ -158,7 +158,7 @@ namespace client try { m_I2CPServer = new I2CPServer (i2cpAddr, i2cpPort); - m_I2CPServer->Start (); + m_I2CPServer->Start (); } catch (std::exception& e) { @@ -235,7 +235,7 @@ namespace client LogPrint(eLogInfo, "Clients: stopping AddressBook"); m_AddressBook.Stop (); - { + { std::lock_guard lock(m_ForwardsMutex); m_ServerForwards.clear(); m_ClientForwards.clear(); @@ -281,7 +281,7 @@ namespace client } } - bool ClientContext::LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, + bool ClientContext::LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, i2p::data::SigningKeyType sigType, i2p::data::CryptoKeyType cryptoType) { if (filename == "transient") @@ -350,7 +350,7 @@ namespace client } std::shared_ptr ClientContext::CreateNewLocalDestination (bool isPublic, - i2p::data::SigningKeyType sigType, i2p::data::CryptoKeyType cryptoType, + i2p::data::SigningKeyType sigType, i2p::data::CryptoKeyType cryptoType, const std::map * params) { i2p::data::PrivateKeys keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType, cryptoType); @@ -448,7 +448,7 @@ namespace client if (i2p::config::GetOption(prefix + I2CP_PARAM_MIN_TUNNEL_LATENCY, value)) options[I2CP_PARAM_MIN_TUNNEL_LATENCY] = value; if (i2p::config::GetOption(prefix + I2CP_PARAM_MAX_TUNNEL_LATENCY, value)) - options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = value; + options[I2CP_PARAM_MAX_TUNNEL_LATENCY] = value; } void ClientContext::ReadTunnels () @@ -653,11 +653,11 @@ namespace client I2PServerTunnel * serverTunnel; if (type == I2P_TUNNELS_SECTION_TYPE_HTTP) - serverTunnel = new I2PServerTunnelHTTP (name, host, port, localDestination, hostOverride, inPort, gzip); - else if (type == I2P_TUNNELS_SECTION_TYPE_IRC) - serverTunnel = new I2PServerTunnelIRC (name, host, port, localDestination, webircpass, inPort, gzip); + serverTunnel = new I2PServerTunnelHTTP (name, host, port, localDestination, hostOverride, inPort, gzip); + else if (type == I2P_TUNNELS_SECTION_TYPE_IRC) + serverTunnel = new I2PServerTunnelIRC (name, host, port, localDestination, webircpass, inPort, gzip); else // regular server tunnel by default - serverTunnel = new I2PServerTunnel (name, host, port, localDestination, inPort, gzip); + serverTunnel = new I2PServerTunnel (name, host, port, localDestination, inPort, gzip); LogPrint(eLogInfo, "Clients: Set Max Conns To ", maxConns); serverTunnel->SetMaxConnsPerMinute(maxConns); @@ -665,7 +665,7 @@ namespace client { LogPrint(eLogInfo, "Clients: disabling loopback address mapping"); serverTunnel->SetUniqueLocal(isUniqueLocal); - } + } if (accessList.length () > 0) { diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index 9b65ef32..8f7143bb 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -73,8 +73,8 @@ namespace client std::shared_ptr CreateNewMatchedTunnelDestination(const i2p::data::PrivateKeys &keys, const std::string & name, const std::map * params = nullptr); void DeleteLocalDestination (std::shared_ptr destination); std::shared_ptr FindLocalDestination (const i2p::data::IdentHash& destination) const; - bool LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, - i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256, + bool LoadPrivateKeys (i2p::data::PrivateKeys& keys, const std::string& filename, + i2p::data::SigningKeyType sigType = i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256, i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL); AddressBook& GetAddressBook () { return m_AddressBook; }; diff --git a/libi2pd_client/I2CP.cpp b/libi2pd_client/I2CP.cpp index f98b1af3..371456ee 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -23,8 +23,8 @@ namespace i2p namespace client { - I2CPDestination::I2CPDestination (std::shared_ptr owner, std::shared_ptr identity, bool isPublic, const std::map& params): - LeaseSetDestination (isPublic, ¶ms), m_Owner (owner), m_Identity (identity) + I2CPDestination::I2CPDestination (std::shared_ptr owner, std::shared_ptr identity, bool isPublic, const std::map& params): + LeaseSetDestination (isPublic, ¶ms), m_Owner (owner), m_Identity (identity) { } @@ -39,7 +39,7 @@ namespace client if (m_Decryptor) return m_Decryptor->Decrypt (encrypted, data, ctx); else - LogPrint (eLogError, "I2CP: decryptor is not set"); + LogPrint (eLogError, "I2CP: decryptor is not set"); return false; } @@ -50,7 +50,7 @@ namespace client m_Owner->SendMessagePayloadMessage (buf + 4, length); } - void I2CPDestination::CreateNewLeaseSet (std::vector > tunnels) + void I2CPDestination::CreateNewLeaseSet (std::vector > tunnels) { i2p::data::LocalLeaseSet ls (m_Identity, m_EncryptionPrivateKey, tunnels); // we don't care about encryption key m_LeaseSetExpirationTime = ls.GetExpirationTime (); @@ -58,23 +58,23 @@ namespace client leases[-1] = tunnels.size (); htobe16buf (leases - 3, m_Owner->GetSessionID ()); size_t l = 2/*sessionID*/ + 1/*num leases*/ + i2p::data::LEASE_SIZE*tunnels.size (); - m_Owner->SendI2CPMessage (I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE, leases - 3, l); + m_Owner->SendI2CPMessage (I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE, leases - 3, l); } - + void I2CPDestination::LeaseSetCreated (const uint8_t * buf, size_t len) { auto ls = new i2p::data::LocalLeaseSet (m_Identity, buf, len); ls->SetExpirationTime (m_LeaseSetExpirationTime); SetLeaseSet (ls); } - + void I2CPDestination::SendMsgTo (const uint8_t * payload, size_t len, const i2p::data::IdentHash& ident, uint32_t nonce) { auto msg = NewI2NPMessage (); uint8_t * buf = msg->GetPayload (); htobe32buf (buf, len); memcpy (buf + 4, payload, len); - msg->len += len + 4; + msg->len += len + 4; msg->FillI2NPMessageHeader (eI2NPData); auto s = GetSharedFromThis (); auto remote = FindLeaseSet (ident); @@ -85,7 +85,7 @@ namespace client { bool sent = s->SendMsg (msg, remote); s->m_Owner->SendMessageStatusMessage (nonce, sent ? eI2CPMessageStatusGuaranteedSuccess : eI2CPMessageStatusGuaranteedFailure); - }); + }); } else { @@ -93,7 +93,7 @@ namespace client [s, msg, nonce](std::shared_ptr ls) { if (ls) - { + { bool sent = s->SendMsg (msg, ls); s->m_Owner->SendMessageStatusMessage (nonce, sent ? eI2CPMessageStatusGuaranteedSuccess : eI2CPMessageStatusGuaranteedFailure); } @@ -104,8 +104,8 @@ namespace client } bool I2CPDestination::SendMsg (std::shared_ptr msg, std::shared_ptr remote) - { - auto remoteSession = GetRoutingSession (remote, true); + { + auto remoteSession = GetRoutingSession (remote, true); if (!remoteSession) { LogPrint (eLogError, "I2CP: Failed to create remote session"); @@ -113,7 +113,7 @@ namespace client } auto path = remoteSession->GetSharedRoutingPath (); std::shared_ptr outboundTunnel; - std::shared_ptr remoteLease; + std::shared_ptr remoteLease; if (path) { if (!remoteSession->CleanupUnconfirmedTags ()) // no stuck tags @@ -128,27 +128,27 @@ namespace client { outboundTunnel = GetTunnelPool ()->GetNextOutboundTunnel (); auto leases = remote->GetNonExpiredLeases (); - if (!leases.empty ()) + if (!leases.empty ()) remoteLease = leases[rand () % leases.size ()]; if (remoteLease && outboundTunnel) remoteSession->SetSharedRoutingPath (std::make_shared ( i2p::garlic::GarlicRoutingPath{outboundTunnel, remoteLease, 10000, 0, 0})); // 10 secs RTT else remoteSession->SetSharedRoutingPath (nullptr); - } + } if (remoteLease && outboundTunnel) { - std::vector msgs; + std::vector msgs; auto garlic = remoteSession->WrapSingleMessage (msg); - msgs.push_back (i2p::tunnel::TunnelMessageBlock - { + msgs.push_back (i2p::tunnel::TunnelMessageBlock + { i2p::tunnel::eDeliveryTypeTunnel, remoteLease->tunnelGateway, remoteLease->tunnelID, garlic }); outboundTunnel->SendTunnelDataMsg (msgs); return true; - } + } else { if (outboundTunnel) @@ -156,7 +156,7 @@ namespace client else LogPrint (eLogWarning, "I2CP: Failed to send message. No outbound tunnels"); return false; - } + } } I2CPSession::I2CPSession (I2CPServer& owner, std::shared_ptr socket): @@ -164,7 +164,7 @@ namespace client m_SessionID (0xFFFF), m_MessageID (0), m_IsSendAccepted (true) { } - + I2CPSession::~I2CPSession () { delete[] m_Payload; @@ -184,8 +184,8 @@ namespace client { if (m_Socket) { - auto s = shared_from_this (); - m_Socket->async_read_some (boost::asio::buffer (m_Header, 1), + auto s = shared_from_this (); + m_Socket->async_read_some (boost::asio::buffer (m_Header, 1), [s](const boost::system::error_code& ecode, std::size_t bytes_transferred) { if (!ecode && bytes_transferred > 0 && s->m_Header[0] == I2CP_PROTOCOL_BYTE) @@ -239,7 +239,7 @@ namespace client HandleMessage (); delete[] m_Payload; m_Payload = nullptr; - m_PayloadLen = 0; + m_PayloadLen = 0; ReceiveHeader (); // next message } } @@ -273,16 +273,16 @@ namespace client { auto socket = m_Socket; if (socket) - { + { auto l = len + I2CP_HEADER_SIZE; uint8_t * buf = new uint8_t[l]; htobe32buf (buf + I2CP_HEADER_LENGTH_OFFSET, len); buf[I2CP_HEADER_TYPE_OFFSET] = type; memcpy (buf + I2CP_HEADER_SIZE, payload, len); boost::asio::async_write (*socket, boost::asio::buffer (buf, l), boost::asio::transfer_all (), - std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), - std::placeholders::_1, std::placeholders::_2, buf)); - } + std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), + std::placeholders::_1, std::placeholders::_2, buf)); + } else LogPrint (eLogError, "I2CP: Can't write to the socket"); } @@ -307,7 +307,7 @@ namespace client if (l + 1 >= len) l = len - 1; if (l > 255) l = 255; // 1 byte max buf[0] = l; - memcpy (buf + 1, str.c_str (), l); + memcpy (buf + 1, str.c_str (), l); return l + 1; } @@ -319,20 +319,20 @@ namespace client { std::string param = ExtractString (buf + offset, len - offset); offset += param.length () + 1; - if (buf[offset] != '=') + if (buf[offset] != '=') { LogPrint (eLogWarning, "I2CP: Unexpected character ", buf[offset], " instead '=' after ", param); - break; - } + break; + } offset++; std::string value = ExtractString (buf + offset, len - offset); offset += value.length () + 1; - if (buf[offset] != ';') + if (buf[offset] != ';') { LogPrint (eLogWarning, "I2CP: Unexpected character ", buf[offset], " instead ';' after ", value); - break; - } + break; + } offset++; mapping.insert (std::make_pair (param, value)); } @@ -349,7 +349,7 @@ namespace client htobe64buf (payload, ts); // echo vesrion back PutString (payload + 8, l - 8, version); - SendI2CPMessage (I2CP_SET_DATE_MESSAGE, payload, l); + SendI2CPMessage (I2CP_SET_DATE_MESSAGE, payload, l); delete[] payload; } @@ -361,26 +361,26 @@ namespace client size_t offset = identity->FromBuffer (buf, len); if (!offset) { - LogPrint (eLogError, "I2CP: create session maformed identity"); + LogPrint (eLogError, "I2CP: create session maformed identity"); SendSessionStatusMessage (3); // invalid return; - } + } uint16_t optionsSize = bufbe16toh (buf + offset); offset += 2; if (optionsSize > len - offset) { - LogPrint (eLogError, "I2CP: options size ", optionsSize, "exceeds message size"); + LogPrint (eLogError, "I2CP: options size ", optionsSize, "exceeds message size"); SendSessionStatusMessage (3); // invalid return; } std::map params; - ExtractMapping (buf + offset, optionsSize, params); + ExtractMapping (buf + offset, optionsSize, params); offset += optionsSize; // options if (params[I2CP_PARAM_MESSAGE_RELIABILITY] == "none") m_IsSendAccepted = false; offset += 8; // date if (identity->Verify (buf, offset, buf + offset)) // signature - { + { bool isPublic = true; if (params[I2CP_PARAM_DONT_PUBLISH_LEASESET] == "true") isPublic = false; if (!m_Destination) @@ -388,17 +388,17 @@ namespace client m_Destination = std::make_shared(shared_from_this (), identity, isPublic, params); SendSessionStatusMessage (1); // created LogPrint (eLogDebug, "I2CP: session ", m_SessionID, " created"); - m_Destination->Start (); + m_Destination->Start (); } else { - LogPrint (eLogError, "I2CP: session already exists"); + LogPrint (eLogError, "I2CP: session already exists"); SendSessionStatusMessage (4); // refused } } else { - LogPrint (eLogError, "I2CP: create session signature verification falied"); + LogPrint (eLogError, "I2CP: create session signature verification falied"); SendSessionStatusMessage (3); // invalid } } @@ -418,14 +418,14 @@ namespace client { // TODO: implement actual reconfiguration SendSessionStatusMessage (2); // updated - } + } void I2CPSession::SendSessionStatusMessage (uint8_t status) { uint8_t buf[3]; htobe16buf (buf, m_SessionID); buf[2] = status; - SendI2CPMessage (I2CP_SESSION_STATUS_MESSAGE, buf, 3); + SendI2CPMessage (I2CP_SESSION_STATUS_MESSAGE, buf, 3); } void I2CPSession::SendMessageStatusMessage (uint32_t nonce, I2CPMessageStatus status) @@ -436,8 +436,8 @@ namespace client htobe32buf (buf + 2, m_MessageID++); buf[6] = (uint8_t)status; memset (buf + 7, 0, 4); // size - htobe32buf (buf + 11, nonce); - SendI2CPMessage (I2CP_MESSAGE_STATUS_MESSAGE, buf, 15); + htobe32buf (buf + 11, nonce); + SendI2CPMessage (I2CP_MESSAGE_STATUS_MESSAGE, buf, 15); } void I2CPSession::CreateLeaseSetMessageHandler (const uint8_t * buf, size_t len) @@ -450,13 +450,13 @@ namespace client { offset += i2p::crypto::DSA_PRIVATE_KEY_LENGTH; // skip signing private key // we always assume this field as 20 bytes (DSA) regardless actual size - // instead of - //offset += m_Destination->GetIdentity ()->GetSigningPrivateKeyLen (); + // instead of + //offset += m_Destination->GetIdentity ()->GetSigningPrivateKeyLen (); m_Destination->SetEncryptionPrivateKey (buf + offset); offset += 256; m_Destination->LeaseSetCreated (buf + offset, len - offset); } - } + } else LogPrint (eLogError, "I2CP: unexpected sessionID ", sessionID); } @@ -476,28 +476,28 @@ namespace client offset += identsize; uint32_t payloadLen = bufbe32toh (buf + offset); if (payloadLen + offset <= len) - { + { offset += 4; uint32_t nonce = bufbe32toh (buf + offset + payloadLen); - if (m_IsSendAccepted) - SendMessageStatusMessage (nonce, eI2CPMessageStatusAccepted); // accepted + if (m_IsSendAccepted) + SendMessageStatusMessage (nonce, eI2CPMessageStatusAccepted); // accepted m_Destination->SendMsgTo (buf + offset, payloadLen, identity.GetIdentHash (), nonce); } - else - LogPrint(eLogError, "I2CP: cannot send message, too big"); - } - else - LogPrint(eLogError, "I2CP: invalid identity"); - } - } + else + LogPrint(eLogError, "I2CP: cannot send message, too big"); + } + else + LogPrint(eLogError, "I2CP: invalid identity"); + } + } else LogPrint (eLogError, "I2CP: unexpected sessionID ", sessionID); } void I2CPSession::SendMessageExpiresMessageHandler (const uint8_t * buf, size_t len) { - SendMessageMessageHandler (buf, len - 8); // ignore flags(2) and expiration(6) - } + SendMessageMessageHandler (buf, len - 8); // ignore flags(2) and expiration(6) + } void I2CPSession::HostLookupMessageHandler (const uint8_t * buf, size_t len) { @@ -507,7 +507,7 @@ namespace client uint32_t requestID = bufbe32toh (buf + 2); //uint32_t timeout = bufbe32toh (buf + 6); i2p::data::IdentHash ident; - switch (buf[10]) + switch (buf[10]) { case 0: // hash ident = i2p::data::IdentHash (buf + 11); @@ -521,7 +521,7 @@ namespace client SendHostReplyMessage (requestID, nullptr); return; } - break; + break; } default: LogPrint (eLogError, "I2CP: request type ", (int)buf[10], " is not supported"); @@ -530,7 +530,7 @@ namespace client } std::shared_ptr destination = m_Destination; - if(!destination) destination = i2p::client::context.GetSharedLocalDestination (); + if(!destination) destination = i2p::client::context.GetSharedLocalDestination (); if (destination) { auto ls = destination->FindLeaseSet (ident); @@ -544,11 +544,11 @@ namespace client { s->SendHostReplyMessage (requestID, leaseSet ? leaseSet->GetIdentity () : nullptr); }); - } + } } else SendHostReplyMessage (requestID, nullptr); - } + } else LogPrint (eLogError, "I2CP: unexpected sessionID ", sessionID); } @@ -563,7 +563,7 @@ namespace client htobe32buf (buf + 2, requestID); buf[6] = 0; // result code identity->ToBuffer (buf + 7, l - 7); - SendI2CPMessage (I2CP_HOST_REPLY_MESSAGE, buf, l); + SendI2CPMessage (I2CP_HOST_REPLY_MESSAGE, buf, l); delete[] buf; } else @@ -572,8 +572,8 @@ namespace client htobe16buf (buf, m_SessionID); htobe32buf (buf + 2, requestID); buf[6] = 1; // result code - SendI2CPMessage (I2CP_HOST_REPLY_MESSAGE, buf, 7); - } + SendI2CPMessage (I2CP_HOST_REPLY_MESSAGE, buf, 7); + } } void I2CPSession::DestLookupMessageHandler (const uint8_t * buf, size_t len) @@ -582,7 +582,7 @@ namespace client { auto ls = m_Destination->FindLeaseSet (buf); if (ls) - { + { auto l = ls->GetIdentity ()->GetFullLen (); uint8_t * identBuf = new uint8_t[l]; ls->GetIdentity ()->ToBuffer (identBuf, l); @@ -610,8 +610,8 @@ namespace client } } else - SendI2CPMessage (I2CP_DEST_REPLY_MESSAGE, buf, 32); - } + SendI2CPMessage (I2CP_DEST_REPLY_MESSAGE, buf, 32); + } void I2CPSession::GetBandwidthLimitsMessageHandler (const uint8_t * buf, size_t len) { @@ -631,16 +631,16 @@ namespace client buf[I2CP_HEADER_TYPE_OFFSET] = I2CP_MESSAGE_PAYLOAD_MESSAGE; htobe16buf (buf + I2CP_HEADER_SIZE, m_SessionID); htobe32buf (buf + I2CP_HEADER_SIZE + 2, m_MessageID++); - htobe32buf (buf + I2CP_HEADER_SIZE + 6, len); + htobe32buf (buf + I2CP_HEADER_SIZE + 6, len); memcpy (buf + I2CP_HEADER_SIZE + 10, payload, len); boost::asio::async_write (*m_Socket, boost::asio::buffer (buf, l), boost::asio::transfer_all (), - std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), - std::placeholders::_1, std::placeholders::_2, buf)); + std::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), + std::placeholders::_1, std::placeholders::_2, buf)); } I2CPServer::I2CPServer (const std::string& interface, int port): m_IsRunning (false), m_Thread (nullptr), - m_Acceptor (m_Service, + m_Acceptor (m_Service, #ifdef ANDROID I2CPSession::proto::endpoint(std::string (1, '\0') + interface)) // leading 0 for abstract address #else @@ -654,10 +654,10 @@ namespace client m_MessagesHandlers[I2CP_RECONFIGURE_SESSION_MESSAGE] = &I2CPSession::ReconfigureSessionMessageHandler; m_MessagesHandlers[I2CP_CREATE_LEASESET_MESSAGE] = &I2CPSession::CreateLeaseSetMessageHandler; m_MessagesHandlers[I2CP_SEND_MESSAGE_MESSAGE] = &I2CPSession::SendMessageMessageHandler; - m_MessagesHandlers[I2CP_SEND_MESSAGE_EXPIRES_MESSAGE] = &I2CPSession::SendMessageExpiresMessageHandler; + m_MessagesHandlers[I2CP_SEND_MESSAGE_EXPIRES_MESSAGE] = &I2CPSession::SendMessageExpiresMessageHandler; m_MessagesHandlers[I2CP_HOST_LOOKUP_MESSAGE] = &I2CPSession::HostLookupMessageHandler; - m_MessagesHandlers[I2CP_DEST_LOOKUP_MESSAGE] = &I2CPSession::DestLookupMessageHandler; - m_MessagesHandlers[I2CP_GET_BANDWIDTH_LIMITS_MESSAGE] = &I2CPSession::GetBandwidthLimitsMessageHandler; + m_MessagesHandlers[I2CP_DEST_LOOKUP_MESSAGE] = &I2CPSession::DestLookupMessageHandler; + m_MessagesHandlers[I2CP_GET_BANDWIDTH_LIMITS_MESSAGE] = &I2CPSession::GetBandwidthLimitsMessageHandler; } I2CPServer::~I2CPServer () @@ -682,26 +682,26 @@ namespace client m_Sessions.clear (); m_Service.stop (); if (m_Thread) - { - m_Thread->join (); + { + m_Thread->join (); delete m_Thread; m_Thread = nullptr; - } + } } - void I2CPServer::Run () - { + void I2CPServer::Run () + { while (m_IsRunning) { try - { + { m_Service.run (); } catch (std::exception& ex) { LogPrint (eLogError, "I2CP: runtime exception: ", ex.what ()); - } - } + } + } } void I2CPServer::Accept () @@ -719,7 +719,7 @@ namespace client boost::system::error_code ec; auto ep = socket->remote_endpoint (ec); if (!ec) - { + { LogPrint (eLogDebug, "I2CP: new connection from ", ep); auto session = std::make_shared(*this, socket); session->Start (); @@ -738,17 +738,17 @@ namespace client { if (!session) return false; if (!m_Sessions.insert({session->GetSessionID (), session}).second) - { + { LogPrint (eLogError, "I2CP: duplicate session id ", session->GetSessionID ()); return false; - } + } return true; } void I2CPServer::RemoveSession (uint16_t sessionID) { m_Sessions.erase (sessionID); - } + } } } diff --git a/libi2pd_client/I2CP.h b/libi2pd_client/I2CP.h index 8c4f8ff0..657c72c1 100644 --- a/libi2pd_client/I2CP.h +++ b/libi2pd_client/I2CP.h @@ -26,25 +26,25 @@ namespace client const size_t I2CP_HEADER_LENGTH_OFFSET = 0; const size_t I2CP_HEADER_TYPE_OFFSET = I2CP_HEADER_LENGTH_OFFSET + 4; - const size_t I2CP_HEADER_SIZE = I2CP_HEADER_TYPE_OFFSET + 1; + const size_t I2CP_HEADER_SIZE = I2CP_HEADER_TYPE_OFFSET + 1; const uint8_t I2CP_GET_DATE_MESSAGE = 32; const uint8_t I2CP_SET_DATE_MESSAGE = 33; const uint8_t I2CP_CREATE_SESSION_MESSAGE = 1; - const uint8_t I2CP_RECONFIGURE_SESSION_MESSAGE = 2; - const uint8_t I2CP_SESSION_STATUS_MESSAGE = 20; + const uint8_t I2CP_RECONFIGURE_SESSION_MESSAGE = 2; + const uint8_t I2CP_SESSION_STATUS_MESSAGE = 20; const uint8_t I2CP_DESTROY_SESSION_MESSAGE = 3; const uint8_t I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE = 37; - const uint8_t I2CP_CREATE_LEASESET_MESSAGE = 4; + const uint8_t I2CP_CREATE_LEASESET_MESSAGE = 4; const uint8_t I2CP_SEND_MESSAGE_MESSAGE = 5; - const uint8_t I2CP_SEND_MESSAGE_EXPIRES_MESSAGE = 36; + const uint8_t I2CP_SEND_MESSAGE_EXPIRES_MESSAGE = 36; const uint8_t I2CP_MESSAGE_PAYLOAD_MESSAGE = 31; - const uint8_t I2CP_MESSAGE_STATUS_MESSAGE = 22; + const uint8_t I2CP_MESSAGE_STATUS_MESSAGE = 22; const uint8_t I2CP_HOST_LOOKUP_MESSAGE = 38; - const uint8_t I2CP_HOST_REPLY_MESSAGE = 39; + const uint8_t I2CP_HOST_REPLY_MESSAGE = 39; const uint8_t I2CP_DEST_LOOKUP_MESSAGE = 34; - const uint8_t I2CP_DEST_REPLY_MESSAGE = 35; - const uint8_t I2CP_GET_BANDWIDTH_LIMITS_MESSAGE = 8; + const uint8_t I2CP_DEST_REPLY_MESSAGE = 35; + const uint8_t I2CP_GET_BANDWIDTH_LIMITS_MESSAGE = 8; const uint8_t I2CP_BANDWIDTH_LIMITS_MESSAGE = 23; enum I2CPMessageStatus @@ -56,8 +56,8 @@ namespace client }; // params - const char I2CP_PARAM_DONT_PUBLISH_LEASESET[] = "i2cp.dontPublishLeaseSet"; - const char I2CP_PARAM_MESSAGE_RELIABILITY[] = "i2cp.messageReliability"; + const char I2CP_PARAM_DONT_PUBLISH_LEASESET[] = "i2cp.dontPublishLeaseSet"; + const char I2CP_PARAM_MESSAGE_RELIABILITY[] = "i2cp.messageReliability"; class I2CPSession; class I2CPDestination: public LeaseSetDestination @@ -83,7 +83,7 @@ namespace client private: std::shared_ptr GetSharedFromThis () - { return std::static_pointer_cast(shared_from_this ()); } + { return std::static_pointer_cast(shared_from_this ()); } bool SendMsg (std::shared_ptr msg, std::shared_ptr remote); private: @@ -100,11 +100,11 @@ namespace client { public: -#ifdef ANDROID +#ifdef ANDROID typedef boost::asio::local::stream_protocol proto; #else typedef boost::asio::ip::tcp proto; -#endif +#endif I2CPSession (I2CPServer& owner, std::shared_ptr socket); @@ -115,9 +115,9 @@ namespace client uint16_t GetSessionID () const { return m_SessionID; }; std::shared_ptr GetDestination () const { return m_Destination; }; - // called from I2CPDestination + // called from I2CPDestination void SendI2CPMessage (uint8_t type, const uint8_t * payload, size_t len); - void SendMessagePayloadMessage (const uint8_t * payload, size_t len); + void SendMessagePayloadMessage (const uint8_t * payload, size_t len); void SendMessageStatusMessage (uint32_t nonce, I2CPMessageStatus status); // message handlers @@ -133,7 +133,7 @@ namespace client void GetBandwidthLimitsMessageHandler (const uint8_t * buf, size_t len); private: - + void ReadProtocolByte (); void ReceiveHeader (); void HandleReceivedHeader (const boost::system::error_code& ecode, std::size_t bytes_transferred); @@ -141,7 +141,7 @@ namespace client void HandleReceivedPayload (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleMessage (); void Terminate (); - + void HandleI2CPMessageSent (const boost::system::error_code& ecode, std::size_t bytes_transferred, const uint8_t * buf); std::string ExtractString (const uint8_t * buf, size_t len); size_t PutString (uint8_t * buf, size_t len, const std::string& str); @@ -163,14 +163,14 @@ namespace client bool m_IsSendAccepted; }; typedef void (I2CPSession::*I2CPMessageHandler)(const uint8_t * buf, size_t len); - + class I2CPServer { public: I2CPServer (const std::string& interface, int port); ~I2CPServer (); - + void Start (); void Stop (); boost::asio::io_service& GetService () { return m_Service; }; @@ -187,12 +187,12 @@ namespace client void HandleAccept(const boost::system::error_code& ecode, std::shared_ptr socket); private: - + I2CPMessageHandler m_MessagesHandlers[256]; std::map > m_Sessions; bool m_IsRunning; - std::thread * m_Thread; + std::thread * m_Thread; boost::asio::io_service m_Service; I2CPSession::proto::acceptor m_Acceptor; @@ -202,7 +202,7 @@ namespace client // for HTTP const decltype(m_Sessions)& GetSessions () const { return m_Sessions; }; - }; + }; } } diff --git a/libi2pd_client/I2PService.h b/libi2pd_client/I2PService.h index fd5e8999..ecfd5bc5 100644 --- a/libi2pd_client/I2PService.h +++ b/libi2pd_client/I2PService.h @@ -14,7 +14,7 @@ namespace i2p namespace client { class I2PServiceHandler; - class I2PService : std::enable_shared_from_this + class I2PService : public std::enable_shared_from_this { public: typedef std::function ReadyCallback; @@ -42,11 +42,11 @@ namespace client inline std::shared_ptr GetLocalDestination () { return m_LocalDestination; } inline std::shared_ptr GetLocalDestination () const { return m_LocalDestination; } - inline void SetLocalDestination (std::shared_ptr dest) - { + inline void SetLocalDestination (std::shared_ptr dest) + { if (m_LocalDestination) m_LocalDestination->Release (); if (dest) dest->Acquire (); - m_LocalDestination = dest; + m_LocalDestination = dest; } void CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port = 0); void CreateStream(StreamRequestComplete complete, const i2p::data::IdentHash & ident, int port); diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 8117a755..975cc4ce 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -93,7 +93,7 @@ namespace client MapToLoopback(m_Socket, ident); } #endif - m_Socket->async_connect (m_RemoteEndpoint, std::bind (&I2PTunnelConnection::HandleConnect, + m_Socket->async_connect (m_RemoteEndpoint, std::bind (&I2PTunnelConnection::HandleConnect, shared_from_this (), std::placeholders::_1)); } } diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 140140fc..57767e77 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -25,7 +25,7 @@ namespace client SAMSocket::~SAMSocket () { Terminate ("~SAMSocket()"); - } + } void SAMSocket::CloseStream (const char* reason) { @@ -34,13 +34,13 @@ namespace client { m_Stream->Close (); m_Stream.reset (); - } - } - + } + } + void SAMSocket::Terminate (const char* reason) { CloseStream (reason); - + switch (m_SocketType) { case eSAMSocketTypeSession: @@ -217,7 +217,7 @@ namespace client if (!strcmp (m_Buffer, SAM_SESSION_CREATE)) ProcessSessionCreate (separator + 1, bytes_transferred - (separator - m_Buffer) - 1); else if (!strcmp (m_Buffer, SAM_STREAM_CONNECT)) - ProcessStreamConnect (separator + 1, bytes_transferred - (separator - m_Buffer) - 1, bytes_transferred - (eol - m_Buffer) - 1); + ProcessStreamConnect (separator + 1, bytes_transferred - (separator - m_Buffer) - 1, bytes_transferred - (eol - m_Buffer) - 1); else if (!strcmp (m_Buffer, SAM_STREAM_ACCEPT)) ProcessStreamAccept (separator + 1, bytes_transferred - (separator - m_Buffer) - 1); else if (!strcmp (m_Buffer, SAM_DEST_GENERATE)) @@ -375,11 +375,11 @@ namespace client if (m_Session) { if (rem > 0) // handle follow on data - { + { memmove (m_Buffer, buf + len + 1, rem); // buf is a pointer to m_Buffer's content - m_BufferOffset = rem; + m_BufferOffset = rem; } - else + else m_BufferOffset = 0; auto dest = std::make_shared (); @@ -442,7 +442,7 @@ namespace client m_Session->AddSocket (shared_from_this ()); if (!m_Session->localDestination->IsAcceptingStreams ()) { - m_IsAccepting = true; + m_IsAccepting = true; m_Session->localDestination->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1)); } SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); @@ -638,7 +638,7 @@ namespace client { if (!ecode) s->Receive (); - else + else s->m_Owner.GetService ().post ([s] { s->Terminate ("AsyncSend failed"); }); }); } @@ -664,11 +664,11 @@ namespace client if (len > 0) // still some data { boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, len), - std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1)); + std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1)); } else // no more data Terminate ("no more data"); - } + } } } @@ -681,7 +681,7 @@ namespace client { if (bytes_transferred > 0) boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, bytes_transferred), - std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1)); // postpone termination + std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1)); // postpone termination else { auto s = shared_from_this (); @@ -692,13 +692,13 @@ namespace client { auto s = shared_from_this (); m_Owner.GetService ().post ([s] { s->Terminate ("stream read error (op aborted)"); }); - } + } } else { if (m_SocketType != eSAMSocketTypeTerminated) // check for possible race condition with Terminate() boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, bytes_transferred), - std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1)); + std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1)); } } @@ -915,7 +915,7 @@ namespace client { // extract signature type i2p::data::SigningKeyType signatureType = i2p::data::SIGNING_KEY_TYPE_DSA_SHA1; - i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; + i2p::data::CryptoKeyType cryptoType = i2p::data::CRYPTO_KEY_TYPE_ELGAMAL; if (params) { auto it = params->find (SAM_PARAM_SIGNATURE_TYPE); diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index f2c84e3c..3cbe0447 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -80,7 +80,7 @@ namespace client public: SAMSocket (SAMBridge& owner); - ~SAMSocket (); + ~SAMSocket (); void CloseStream (const char* reason); // TODO: implement it better boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; }; @@ -133,7 +133,7 @@ namespace client SAMSocketType m_SocketType; std::string m_ID; // nickname bool m_IsSilent; - bool m_IsAccepting; // for eSAMSocketTypeAcceptor only + bool m_IsAccepting; // for eSAMSocketTypeAcceptor only std::shared_ptr m_Stream; std::shared_ptr m_Session; }; diff --git a/libi2pd_client/SOCKS.cpp b/libi2pd_client/SOCKS.cpp index 631d3e5c..ddf4bbe9 100644 --- a/libi2pd_client/SOCKS.cpp +++ b/libi2pd_client/SOCKS.cpp @@ -22,8 +22,8 @@ namespace proxy static const size_t SOCKS_FORWARDER_BUFFER_SIZE = 8192; static const size_t SOCKS_UPSTREAM_SOCKS4A_REPLY_SIZE = 8; - - struct SOCKSDnsAddress + + struct SOCKSDnsAddress { uint8_t size; char value[max_socks_hostname_size]; @@ -38,10 +38,10 @@ namespace proxy }; class SOCKSServer; - class SOCKSHandler: public i2p::client::I2PServiceHandler, public std::enable_shared_from_this + class SOCKSHandler: public i2p::client::I2PServiceHandler, public std::enable_shared_from_this { private: - enum state + enum state { GET_SOCKSV, GET_COMMAND, @@ -62,20 +62,20 @@ namespace proxy UPSTREAM_CONNECT, UPSTREAM_HANDSHAKE }; - enum authMethods + enum authMethods { AUTH_NONE = 0, //No authentication, skip to next step AUTH_GSSAPI = 1, //GSSAPI authentication AUTH_USERPASSWD = 2, //Username and password AUTH_UNACCEPTABLE = 0xff //No acceptable method found }; - enum addrTypes + enum addrTypes { ADDR_IPV4 = 1, //IPv4 address (4 octets) ADDR_DNS = 3, // DNS name (up to 255 octets) ADDR_IPV6 = 4 //IPV6 address (16 octets) }; - enum errTypes + enum errTypes { SOCKS5_OK = 0, // No error for SOCKS5 SOCKS5_GEN_FAIL = 1, // General server failure @@ -91,18 +91,18 @@ namespace proxy SOCKS4_IDENTD_MISSING = 92, // Couldn't connect to the identd server SOCKS4_IDENTD_DIFFER = 93 // The ID reported by the application and by identd differ }; - enum cmdTypes + enum cmdTypes { CMD_CONNECT = 1, // TCP Connect CMD_BIND = 2, // TCP Bind CMD_UDP = 3 // UDP associate }; - enum socksVersions + enum socksVersions { SOCKS4 = 4, // SOCKS4 SOCKS5 = 5 // SOCKS5 }; - union address + union address { uint32_t ip; SOCKSDnsAddress dns; @@ -138,7 +138,7 @@ namespace proxy boost::asio::ip::tcp::resolver::iterator itr); void HandleUpstreamResolved(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr); - + boost::asio::ip::tcp::resolver m_proxy_resolver; uint8_t m_sock_buff[socks_buffer_size]; std::shared_ptr m_sock, m_upstreamSock; @@ -163,7 +163,7 @@ namespace proxy const bool m_UseUpstreamProxy; // do we want to use the upstream proxy for non i2p addresses? const std::string m_UpstreamProxyAddress; const uint16_t m_UpstreamProxyPort; - + public: SOCKSHandler(SOCKSServer * parent, std::shared_ptr sock, const std::string & upstreamAddr, const uint16_t upstreamPort, const bool useUpstream) : I2PServiceHandler(parent), @@ -172,13 +172,13 @@ namespace proxy m_authchosen(AUTH_UNACCEPTABLE), m_addrtype(ADDR_IPV4), m_UseUpstreamProxy(useUpstream), m_UpstreamProxyAddress(upstreamAddr), - m_UpstreamProxyPort(upstreamPort) + m_UpstreamProxyPort(upstreamPort) { m_address.ip = 0; EnterState(GET_SOCKSV); } - + ~SOCKSHandler() { Terminate(); } void Handle() { AsyncSockRead(); } }; - + void SOCKSHandler::AsyncSockRead() { LogPrint(eLogDebug, "SOCKS: async sock read"); @@ -191,10 +191,10 @@ namespace proxy } } - void SOCKSHandler::Terminate() + void SOCKSHandler::Terminate() { if (Kill()) return; - if (m_sock) + if (m_sock) { LogPrint(eLogDebug, "SOCKS: closing socket"); m_sock->close(); @@ -206,7 +206,7 @@ namespace proxy m_upstreamSock->close(); m_upstreamSock = nullptr; } - if (m_stream) + if (m_stream) { LogPrint(eLogDebug, "SOCKS: closing stream"); m_stream.reset (); @@ -232,7 +232,7 @@ namespace proxy m_response[1] = error; //Response code m_response[2] = '\x00'; //RSV m_response[3] = type; //Address type - switch (type) + switch (type) { case ADDR_IPV4: size = 10; @@ -288,14 +288,14 @@ namespace proxy m_response[0] = '\x05'; //Version m_response[1] = m_authchosen; //Response code boost::asio::const_buffers_1 response(m_response,2); - if (m_authchosen == AUTH_UNACCEPTABLE) + if (m_authchosen == AUTH_UNACCEPTABLE) { LogPrint(eLogWarning, "SOCKS: v5 authentication negotiation failed"); boost::asio::async_write(*m_sock, response, std::bind(&SOCKSHandler::SentSocksFailed, shared_from_this(), std::placeholders::_1)); return false; - } - else + } + else { LogPrint(eLogDebug, "SOCKS: v5 choosing authentication method: ", m_authchosen); boost::asio::async_write(*m_sock, response, std::bind(&SOCKSHandler::SentSocksResponse, @@ -309,7 +309,7 @@ namespace proxy { boost::asio::const_buffers_1 response(nullptr,0); assert(error != SOCKS4_OK && error != SOCKS5_OK); - switch (m_socksv) + switch (m_socksv) { case SOCKS4: LogPrint(eLogWarning, "SOCKS: v4 request failed: ", error); @@ -329,7 +329,7 @@ namespace proxy { boost::asio::const_buffers_1 response(nullptr,0); //TODO: this should depend on things like the command type and callbacks may change - switch (m_socksv) + switch (m_socksv) { case SOCKS4: LogPrint(eLogInfo, "SOCKS: v4 connection success"); @@ -348,7 +348,7 @@ namespace proxy } void SOCKSHandler::EnterState(SOCKSHandler::state nstate, uint8_t parseleft) { - switch (nstate) + switch (nstate) { case GET_PORT: parseleft = 2; break; case GET_IPV4: m_addrtype = ADDR_IPV4; m_address.ip = 0; parseleft = 4; break; @@ -362,9 +362,9 @@ namespace proxy m_state = nstate; } - bool SOCKSHandler::ValidateSOCKSRequest() + bool SOCKSHandler::ValidateSOCKSRequest() { - if ( m_cmd != CMD_CONNECT ) + if ( m_cmd != CMD_CONNECT ) { //TODO: we need to support binds and other shit! LogPrint(eLogError, "SOCKS: unsupported command: ", m_cmd); @@ -372,9 +372,9 @@ namespace proxy return false; } //TODO: we may want to support other address types! - if ( m_addrtype != ADDR_DNS ) + if ( m_addrtype != ADDR_DNS ) { - switch (m_socksv) + switch (m_socksv) { case SOCKS5: LogPrint(eLogError, "SOCKS: v5 unsupported address type: ", m_addrtype); @@ -392,13 +392,13 @@ namespace proxy bool SOCKSHandler::HandleData(uint8_t *sock_buff, std::size_t len) { assert(len); // This should always be called with a least a byte left to parse - while (len > 0) + while (len > 0) { - switch (m_state) + switch (m_state) { case GET_SOCKSV: m_socksv = (SOCKSHandler::socksVersions) *sock_buff; - switch (*sock_buff) + switch (*sock_buff) { case SOCKS4: EnterState(GET_COMMAND); //Initialize the parser at the right position @@ -419,14 +419,14 @@ namespace proxy m_parseleft --; if (*sock_buff == AUTH_NONE) m_authchosen = AUTH_NONE; - if ( m_parseleft == 0 ) + if ( m_parseleft == 0 ) { if (!Socks5ChooseAuth()) return false; EnterState(GET5_REQUESTV); } break; case GET_COMMAND: - switch (*sock_buff) + switch (*sock_buff) { case CMD_CONNECT: case CMD_BIND: @@ -439,7 +439,7 @@ namespace proxy return false; } m_cmd = (SOCKSHandler::cmdTypes)*sock_buff; - switch (m_socksv) + switch (m_socksv) { case SOCKS5: EnterState(GET5_GETRSV); break; case SOCKS4: EnterState(GET_PORT); break; @@ -448,9 +448,9 @@ namespace proxy case GET_PORT: m_port = (m_port << 8)|((uint16_t)*sock_buff); m_parseleft--; - if (m_parseleft == 0) + if (m_parseleft == 0) { - switch (m_socksv) + switch (m_socksv) { case SOCKS5: EnterState(READY); break; case SOCKS4: EnterState(GET_IPV4); break; @@ -460,9 +460,9 @@ namespace proxy case GET_IPV4: m_address.ip = (m_address.ip << 8)|((uint32_t)*sock_buff); m_parseleft--; - if (m_parseleft == 0) + if (m_parseleft == 0) { - switch (m_socksv) + switch (m_socksv) { case SOCKS5: EnterState(GET_PORT); break; case SOCKS4: EnterState(GET4_IDENT); m_4aip = m_address.ip; break; @@ -470,7 +470,7 @@ namespace proxy } break; case GET4_IDENT: - if (!*sock_buff) + if (!*sock_buff) { if( m_4aip == 0 || m_4aip > 255 ) EnterState(READY); @@ -479,12 +479,12 @@ namespace proxy } break; case GET4A_HOST: - if (!*sock_buff) + if (!*sock_buff) { EnterState(READY); break; } - if (m_address.dns.size >= max_socks_hostname_size) + if (m_address.dns.size >= max_socks_hostname_size) { LogPrint(eLogError, "SOCKS: v4a req failed: destination is too large"); SocksRequestFailed(SOCKS4_FAIL); @@ -493,7 +493,7 @@ namespace proxy m_address.dns.push_back(*sock_buff); break; case GET5_REQUESTV: - if (*sock_buff != SOCKS5) + if (*sock_buff != SOCKS5) { LogPrint(eLogError,"SOCKS: v5 rejected unknown request version: ", ((int)*sock_buff)); SocksRequestFailed(SOCKS5_GEN_FAIL); @@ -502,7 +502,7 @@ namespace proxy EnterState(GET_COMMAND); break; case GET5_GETRSV: - if ( *sock_buff != 0 ) + if ( *sock_buff != 0 ) { LogPrint(eLogError, "SOCKS: v5 unknown reserved field: ", ((int)*sock_buff)); SocksRequestFailed(SOCKS5_GEN_FAIL); @@ -511,7 +511,7 @@ namespace proxy EnterState(GET5_GETADDRTYPE); break; case GET5_GETADDRTYPE: - switch (*sock_buff) + switch (*sock_buff) { case ADDR_IPV4: EnterState(GET_IPV4); break; case ADDR_IPV6: EnterState(GET5_IPV6); break; @@ -542,7 +542,7 @@ namespace proxy } sock_buff++; len--; - if (m_state == READY) + if (m_state == READY) { m_remaining_data_len = len; m_remaining_data = sock_buff; @@ -555,16 +555,16 @@ namespace proxy void SOCKSHandler::HandleSockRecv(const boost::system::error_code & ecode, std::size_t len) { LogPrint(eLogDebug, "SOCKS: received ", len, " bytes"); - if(ecode) + if(ecode) { LogPrint(eLogWarning, "SOCKS: recv got error: ", ecode); Terminate(); return; } - if (HandleData(m_sock_buff, len)) + if (HandleData(m_sock_buff, len)) { - if (m_state == READY) + if (m_state == READY) { const std::string addr = m_address.dns.ToString(); LogPrint(eLogInfo, "SOCKS: requested ", addr, ":" , m_port); @@ -578,10 +578,10 @@ namespace proxy // forward it to upstream proxy ForwardSOCKS(); } else { - // no upstream proxy + // no upstream proxy SocksRequestFailed(SOCKS5_ADDR_UNSUP); } - } + } else AsyncSockRead(); } @@ -596,7 +596,7 @@ namespace proxy void SOCKSHandler::SentSocksDone(const boost::system::error_code & ecode) { - if (!ecode) + if (!ecode) { if (Kill()) return; LogPrint (eLogInfo, "SOCKS: new I2PTunnel connection"); @@ -614,7 +614,7 @@ namespace proxy void SOCKSHandler::SentSocksResponse(const boost::system::error_code & ecode) { - if (ecode) + if (ecode) { LogPrint (eLogError, "SOCKS: closing socket after sending reply because: ", ecode.message ()); Terminate(); @@ -623,18 +623,18 @@ namespace proxy void SOCKSHandler::HandleStreamRequestComplete (std::shared_ptr stream) { - if (stream) + if (stream) { m_stream = stream; SocksRequestSuccess(); - } - else + } + else { LogPrint (eLogError, "SOCKS: error when creating the stream, check the previous warnings for more info"); SocksRequestFailed(SOCKS5_HOST_UNREACH); } } - + void SOCKSHandler::ForwardSOCKS() { LogPrint(eLogInfo, "SOCKS: forwarding to upstream"); @@ -656,7 +656,7 @@ namespace proxy SocksRequestFailed(SOCKS5_GEN_FAIL); } } - + void SOCKSHandler::HandleUpstreamSockRecv(const boost::system::error_code & ecode, std::size_t bytes_transfered) { if (ecode) { @@ -675,7 +675,7 @@ namespace proxy { LogPrint(eLogInfo, "SOCKS: upstream success"); boost::asio::const_buffers_1 response(nullptr, 0); - switch (m_socksv) + switch (m_socksv) { case SOCKS4: LogPrint(eLogInfo, "SOCKS: v4 connection success"); @@ -694,9 +694,9 @@ namespace proxy GetOwner()->AddHandler(forwarder); forwarder->Start(); Terminate(); - + } - + void SOCKSHandler::HandleUpstreamData(uint8_t * dataptr, std::size_t len) { if (m_state == UPSTREAM_HANDSHAKE) { @@ -726,7 +726,7 @@ namespace proxy LogPrint(eLogError, "SOCKS: invalid state reading from upstream: ", (int) m_state); } } - + void SOCKSHandler::SendUpstreamRequest() { LogPrint(eLogInfo, "SOCKS: negotiating with upstream proxy"); @@ -739,7 +739,7 @@ namespace proxy LogPrint(eLogError, "SOCKS: no upstream socket to send handshake to"); } } - + void SOCKSHandler::HandleUpstreamConnected(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr) { if (ecode) { @@ -750,7 +750,7 @@ namespace proxy LogPrint(eLogInfo, "SOCKS: connected to upstream proxy"); SendUpstreamRequest(); } - + void SOCKSHandler::HandleUpstreamResolved(const boost::system::error_code & ecode, boost::asio::ip::tcp::resolver::iterator itr) { if (ecode) { @@ -768,9 +768,9 @@ namespace proxy shared_from_this(), std::placeholders::_1, std::placeholders::_2)); } - SOCKSServer::SOCKSServer(const std::string& name, const std::string& address, int port, - bool outEnable, const std::string& outAddress, uint16_t outPort, - std::shared_ptr localDestination) : + SOCKSServer::SOCKSServer(const std::string& name, const std::string& address, int port, + bool outEnable, const std::string& outAddress, uint16_t outPort, + std::shared_ptr localDestination) : TCPIPAcceptor (address, port, localDestination ? localDestination : i2p::client::context.GetSharedLocalDestination ()), m_Name (name) { m_UseUpstreamProxy = false; diff --git a/libi2pd_client/WebSocks.cpp b/libi2pd_client/WebSocks.cpp index b6faa711..0b8062d3 100644 --- a/libi2pd_client/WebSocks.cpp +++ b/libi2pd_client/WebSocks.cpp @@ -285,7 +285,7 @@ namespace client } else { // forward data LogPrint(eLogDebug, "websocks recv ", n); - + std::string str((char*)m_RecvBuf, n); auto conn = m_Parent->GetConn(m_Conn); if(!conn) { @@ -295,7 +295,7 @@ namespace client } conn->send(str); AsyncRecv(); - + } } @@ -339,7 +339,7 @@ namespace client EnterState(eWSCFailConnect); } } - + virtual void GotMessage(const websocketpp::connection_hdl & conn, WebSocksServerImpl::message_ptr msg) { (void) conn; diff --git a/libi2pd_client/Websocket.h b/libi2pd_client/Websocket.h index 2ddca38f..3a754e49 100644 --- a/libi2pd_client/Websocket.h +++ b/libi2pd_client/Websocket.h @@ -7,7 +7,7 @@ namespace i2p { class WebsocketServerImpl; - + class WebsocketServer { public: @@ -18,7 +18,7 @@ namespace i2p void Stop(); EventListener * ToListener(); - + private: WebsocketServerImpl * m_impl; }; diff --git a/qt/i2pd_qt/DaemonQT.cpp b/qt/i2pd_qt/DaemonQT.cpp index 582ad0f3..dd7c892d 100644 --- a/qt/i2pd_qt/DaemonQT.cpp +++ b/qt/i2pd_qt/DaemonQT.cpp @@ -15,7 +15,7 @@ namespace qt { } - void Worker::startDaemon() + void Worker::startDaemon() { qDebug("Performing daemon start..."); //try{ @@ -28,7 +28,7 @@ namespace qt emit resultReady(true, QObject::tr("Error: unknown exception")); }*/ } - void Worker::restartDaemon() + void Worker::restartDaemon() { qDebug("Performing daemon restart..."); //try{ @@ -55,7 +55,7 @@ namespace qt } Controller::Controller(DaemonQTImpl& daemon): - m_Daemon (daemon) + m_Daemon (daemon) { Worker *worker = new Worker (m_Daemon); worker->moveToThread(&workerThread); @@ -66,7 +66,7 @@ namespace qt connect(worker, &Worker::resultReady, this, &Controller::handleResults); workerThread.start(); } - Controller::~Controller() + Controller::~Controller() { qDebug("Closing and waiting for daemon worker thread..."); workerThread.quit(); @@ -79,7 +79,7 @@ namespace qt qDebug("Stopped the daemon."); } } - + DaemonQTImpl::DaemonQTImpl (): mutex(nullptr), m_IsRunning(nullptr), m_RunningChangedCallback(nullptr) { @@ -119,7 +119,7 @@ namespace qt start(); } - void DaemonQTImpl::setRunningCallback(runningChangedCallback cb) + void DaemonQTImpl::setRunningCallback(runningChangedCallback cb) { m_RunningChangedCallback = cb; } @@ -132,7 +132,7 @@ namespace qt void DaemonQTImpl::setRunning(bool newValue) { bool oldValue = m_IsRunning; - if(oldValue!=newValue) + if(oldValue!=newValue) { m_IsRunning = newValue; if(m_RunningChangedCallback) diff --git a/qt/i2pd_qt/DaemonQT.h b/qt/i2pd_qt/DaemonQT.h index fc874f34..d0add0e3 100644 --- a/qt/i2pd_qt/DaemonQT.h +++ b/qt/i2pd_qt/DaemonQT.h @@ -15,7 +15,7 @@ namespace qt public: DaemonQTImpl (); - ~DaemonQTImpl (); + ~DaemonQTImpl (); typedef void (*runningChangedCallback)(); @@ -45,11 +45,11 @@ namespace qt Q_OBJECT public: - Worker (DaemonQTImpl& daemon); + Worker (DaemonQTImpl& daemon); private: - DaemonQTImpl& m_Daemon; + DaemonQTImpl& m_Daemon; public slots: void startDaemon(); @@ -58,7 +58,7 @@ namespace qt signals: void resultReady(bool failed, QString failureMessage); - }; + }; class Controller : public QObject { @@ -68,7 +68,7 @@ namespace qt Controller(DaemonQTImpl& daemon); ~Controller(); private: - DaemonQTImpl& m_Daemon; + DaemonQTImpl& m_Daemon; public slots: void handleResults(bool failed, QString failureMessage){ diff --git a/qt/i2pd_qt/android/src/org/purplei2p/i2pd/I2PDMainActivity.java b/qt/i2pd_qt/android/src/org/purplei2p/i2pd/I2PDMainActivity.java index 23b32312..aea50bf6 100644 --- a/qt/i2pd_qt/android/src/org/purplei2p/i2pd/I2PDMainActivity.java +++ b/qt/i2pd_qt/android/src/org/purplei2p/i2pd/I2PDMainActivity.java @@ -23,7 +23,7 @@ public class I2PDMainActivity extends QtActivity public void onCreate(Bundle savedInstanceState) { I2PDMainActivity.setInstance(this); super.onCreate(savedInstanceState); - + //set the app be foreground (do not unload when RAM needed) doBindService(); } @@ -45,8 +45,8 @@ public class I2PDMainActivity extends QtActivity private static void setInstance(I2PDMainActivity instance) { I2PDMainActivity.instance = instance; } - - + + // private LocalService mBoundService; @@ -82,7 +82,7 @@ public class I2PDMainActivity extends QtActivity // class name because we want a specific service implementation that // we know will be running in our own process (and thus won't be // supporting component replacement by other applications). - bindService(new Intent(this, + bindService(new Intent(this, LocalService.class), mConnection, Context.BIND_AUTO_CREATE); mIsBound = true; } diff --git a/qt/i2pd_qt/android/src/org/purplei2p/i2pd/LocalService.java b/qt/i2pd_qt/android/src/org/purplei2p/i2pd/LocalService.java index 4c158c08..e2901504 100644 --- a/qt/i2pd_qt/android/src/org/purplei2p/i2pd/LocalService.java +++ b/qt/i2pd_qt/android/src/org/purplei2p/i2pd/LocalService.java @@ -35,8 +35,8 @@ public class LocalService extends Service { // Display a notification about us starting. We put an icon in the status bar. showNotification(); - - + + } @Override diff --git a/qt/i2pd_qt/docs/patch_openssl_so_libs.html b/qt/i2pd_qt/docs/patch_openssl_so_libs.html index 0fb7d540..bc886abc 100644 --- a/qt/i2pd_qt/docs/patch_openssl_so_libs.html +++ b/qt/i2pd_qt/docs/patch_openssl_so_libs.html @@ -4,7 +4,7 @@

OpenSSL под Android в Qt - +

Запись от Wyn размещена 18.01.2016 в 18:22
Метки android, openssl, qt

Мини-руководство по тому, как быстро скомпилировать OpenSSL для Android и связать его с проектом Qt.
Для Linux.

Вначале действия полностью идентичны "расово-верному" руководству по компилянию OpenSSL для Android:
diff --git a/qt/i2pd_qt/mainwindow.cpp b/qt/i2pd_qt/mainwindow.cpp index e9e95ce1..fc1e5985 100644 --- a/qt/i2pd_qt/mainwindow.cpp +++ b/qt/i2pd_qt/mainwindow.cpp @@ -233,16 +233,16 @@ MainWindow::MainWindow(QWidget *parent) : initCheckBox( OPTION("upnp","enabled",[]{return "true";}), uiSettings->enableUPnPCheckBox); initStringBox( OPTION("upnp","name",[]{return "I2Pd";}), uiSettings->upnpNameLineEdit); - + initCheckBox( OPTION("precomputation","elgamal",[]{return "false";}), uiSettings->useElGamalPrecomputedTablesCheckBox); - + initCheckBox( OPTION("reseed","verify",[]{return "";}), uiSettings->reseedVerifyCheckBox); initFileChooser( OPTION("reseed","file",[]{return "";}), uiSettings->reseedFileLineEdit, uiSettings->reseedFileBrowsePushButton); initStringBox( OPTION("reseed","urls",[]{return "";}), uiSettings->reseedURLsLineEdit); - + initStringBox( OPTION("addressbook","defaulturl",[]{return "";}), uiSettings->addressbookDefaultURLLineEdit); initStringBox( OPTION("addressbook","subscriptions",[]{return "";}), uiSettings->addressbookSubscriptionsURLslineEdit); - + initUInt16Box( OPTION("limits","transittunnels",[]{return "2500";}), uiSettings->maxNumOfTransitTunnelsLineEdit, tr("maxNumberOfTransitTunnels")); initUInt16Box( OPTION("limits","openfiles",[]{return "0";}), uiSettings->maxNumOfOpenFilesLineEdit, tr("maxNumberOfOpenFiles")); initUInt32Box( OPTION("limits","coresize",[]{return "0";}), uiSettings->coreFileMaxSizeNumberLineEdit, tr("coreFileMaxSize"));