From 9cc4e8d03a4b365e2410f7003efa0d89290abcd0 Mon Sep 17 00:00:00 2001 From: yangfl Date: Fri, 5 Jan 2018 18:37:32 +0800 Subject: [PATCH 001/119] Makefile: get target platform from compiler --- Makefile | 14 ++++++++------ Makefile.bsd | 2 +- Makefile.linux | 4 ++-- 3 files changed, 11 insertions(+), 9 deletions(-) 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.linux b/Makefile.linux index eec1e2cc..e628b63c 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -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 @@ -44,7 +44,7 @@ ifeq ($(USE_STATIC),yes) LDLIBS += -lpthread -static-libstdc++ -static-libgcc -lrt -ldl USE_AESNI := no else - LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread + LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread -latomic endif # UPNP Support (miniupnpc 1.5 and higher) From e3238ff75ce150042f794af3666de9b4d0fa7af0 Mon Sep 17 00:00:00 2001 From: yangfl Date: Fri, 5 Jan 2018 21:20:31 +0800 Subject: [PATCH 002/119] CMakeLists: autodetect libatomic --- build/CMakeLists.txt | 28 ++++++------ build/cmake_modules/CheckLibcxxAtomic.cmake | 47 +++++++++++++++++++++ 2 files changed, 60 insertions(+), 15 deletions(-) create mode 100644 build/cmake_modules/CheckLibcxxAtomic.cmake diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index a251963d..4d462700 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -83,7 +83,7 @@ if (WITH_WEBSOCKETS) find_package(websocketpp REQUIRED) endif () -if (CMAKE_SYSTEM_NAME STREQUAL "Windows" OR MSYS) +if (WIN32 OR MSYS) list (APPEND LIBI2PD_SRC "${CMAKE_SOURCE_DIR}/I2PEndian.cpp") endif () @@ -194,20 +194,14 @@ if (WITH_HARDENING AND MSVC) endif () # compiler flags customization (by system) -if (CMAKE_SYSTEM_NAME STREQUAL "Linux") +if (UNIX) list (APPEND DAEMON_SRC "${DAEMON_SRC_DIR}/UnixDaemon.cpp") - # "'sleep_for' is not a member of 'std::this_thread'" in gcc 4.7/4.8 - add_definitions( "-D_GLIBCXX_USE_NANOSLEEP=1" ) -elseif (CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") - list (APPEND DAEMON_SRC "${DAEMON_SRC_DIR}/UnixDaemon.cpp") - # "'sleep_for' is not a member of 'std::this_thread'" in gcc 4.7/4.8 - add_definitions( "-D_GLIBCXX_USE_NANOSLEEP=1" ) -elseif (CMAKE_SYSTEM_NAME STREQUAL "Darwin") - list (APPEND DAEMON_SRC "${DAEMON_SRC_DIR}/UnixDaemon.cpp") - elseif (CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") - list (APPEND DAEMON_SRC "${DAEMON_SRC_DIR}/UnixDaemon.cpp") - elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows" OR MSYS) - list (APPEND DAEMON_SRC "${CMAKE_SOURCE_DIR}/Win32/DaemonWin32.cpp") + if (NOT (CMAKE_SYSTEM_NAME STREQUAL "OpenBSD" OR APPLE)) + # "'sleep_for' is not a member of 'std::this_thread'" in gcc 4.7/4.8 + add_definitions( "-D_GLIBCXX_USE_NANOSLEEP=1" ) + endif () +elseif (WIN32 OR MSYS) + list (APPEND DAEMON_SRC "${CMAKE_SOURCE_DIR}/Win32/DaemonWin32.cpp") if (WITH_GUI) list (APPEND DAEMON_SRC "${CMAKE_SOURCE_DIR}/Win32/Win32App.cpp") set_source_files_properties("${CMAKE_SOURCE_DIR}/Win32/DaemonWin32.cpp" @@ -263,6 +257,8 @@ if(THREADS_HAVE_PTHREAD_ARG) # compile time flag set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") endif() +include(CheckLibcxxAtomic) + if (WITH_STATIC) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_RUNTIME ON) @@ -370,11 +366,13 @@ if (NOT ZLIB_FOUND ) if (NOT WITH_STATIC) set ( ZLIB_LIBRARY debug zlibd optimized zlib CACHE STRING "zlib libraries" FORCE) endif () + link_directories(${CMAKE_CURRENT_BINARY_DIR}/zlib/lib) +else() + link_directories(${ZLIB_ROOT}/lib) endif () if (WITH_STATIC AND (MSVC OR MSYS)) set ( ZLIB_LIBRARY debug zlibstaticd optimized zlibstatic CACHE STRING "zlib libraries" FORCE) endif () -link_directories(${CMAKE_CURRENT_BINARY_DIR}/zlib/lib ${ZLIB_ROOT}/lib) # load includes include_directories( SYSTEM ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ) diff --git a/build/cmake_modules/CheckLibcxxAtomic.cmake b/build/cmake_modules/CheckLibcxxAtomic.cmake new file mode 100644 index 00000000..a7ae667a --- /dev/null +++ b/build/cmake_modules/CheckLibcxxAtomic.cmake @@ -0,0 +1,47 @@ +INCLUDE(CheckCXXSourceCompiles) + +# Sometimes linking against libatomic is required for atomic ops, if +# the platform doesn't support lock-free atomics. +# +# We could modify LLVM's CheckAtomic module and have it check for 64-bit +# atomics instead. However, we would like to avoid careless uses of 64-bit +# atomics inside LLVM over time on 32-bit platforms. + +function(check_cxx_atomics varname) + set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + set(CMAKE_REQUIRED_FLAGS "-nodefaultlibs -std=c++11 -nostdinc++ -isystem ${LIBCXX_SOURCE_DIR}/include") + if (${LIBCXX_GCC_TOOLCHAIN}) + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} --gcc-toolchain=${LIBCXX_GCC_TOOLCHAIN}") + endif() + if (CMAKE_C_FLAGS MATCHES -fsanitize OR CMAKE_CXX_FLAGS MATCHES -fsanitize) + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize=all") + endif() + if (CMAKE_C_FLAGS MATCHES -fsanitize-coverage OR CMAKE_CXX_FLAGS MATCHES -fsanitize-coverage) + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters") + endif() + check_cxx_source_compiles(" +#include +#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() From 46f62e1af952a5c0d9e4940c0f59604d40197c7c Mon Sep 17 00:00:00 2001 From: yangfl Date: Sat, 6 Jan 2018 11:48:51 +0800 Subject: [PATCH 003/119] remove trailing whitespaces --- ChangeLog | 6 +- Dockerfile | 8 +- Makefile.homebrew | 2 +- Makefile.linux | 2 +- Makefile.osx | 2 +- README.md | 34 +- android/AndroidManifest.xml | 2 +- android/res/menu/options_main.xml | 4 +- .../org/purplei2p/i2pd/DaemonSingleton.java | 28 +- .../org/purplei2p/i2pd/ForegroundService.java | 4 +- android/src/org/purplei2p/i2pd/I2PD.java | 20 +- android/src/org/purplei2p/i2pd/I2PD_JNI.java | 4 +- build/cmake_modules/FindMiniUPnPc.cmake | 2 +- build/docker/old-ubuntu-based/Dockerfile | 2 +- contrib/apparmor/usr.sbin.i2pd | 2 +- contrib/docker/Dockerfile | 8 +- contrib/i2pd.conf | 8 +- contrib/rpm/i2pd.spec | 4 +- daemon/Daemon.cpp | 2 +- daemon/HTTPServer.cpp | 2 +- daemon/HTTPServer.h | 12 +- daemon/I2PControl.cpp | 48 +- daemon/I2PControl.h | 2 +- daemon/UPnP.h | 8 +- daemon/UnixDaemon.cpp | 2 +- debian/changelog | 4 +- debian/i2pd.default | 2 +- debian/patches/01-tune-build-opts.patch | 5 +- libi2pd/Base.cpp | 64 +-- libi2pd/Base.h | 4 +- libi2pd/Config.h | 4 +- libi2pd/Crypto.h | 160 +++--- libi2pd/CryptoKey.cpp | 14 +- libi2pd/CryptoKey.h | 24 +- libi2pd/Datagram.cpp | 38 +- libi2pd/Destination.cpp | 26 +- libi2pd/Destination.h | 4 +- libi2pd/Event.cpp | 2 +- libi2pd/Event.h | 4 +- libi2pd/FS.cpp | 6 +- libi2pd/FS.h | 10 +- libi2pd/Family.cpp | 44 +- libi2pd/Family.h | 4 +- libi2pd/Garlic.cpp | 258 +++++----- libi2pd/Garlic.h | 100 ++-- libi2pd/Gost.cpp | 134 ++--- libi2pd/Gost.h | 18 +- libi2pd/Gzip.cpp | 14 +- libi2pd/HTTP.cpp | 42 +- libi2pd/HTTP.h | 16 +- libi2pd/I2NPProtocol.cpp | 302 +++++------ libi2pd/I2NPProtocol.h | 98 ++-- libi2pd/Identity.cpp | 14 +- libi2pd/Identity.h | 2 +- libi2pd/LeaseSet.cpp | 76 +-- libi2pd/LeaseSet.h | 50 +- libi2pd/Log.h | 6 +- libi2pd/NetDb.cpp | 474 +++++++++--------- libi2pd/NetDb.hpp | 40 +- libi2pd/NetDbRequests.cpp | 46 +- libi2pd/NetDbRequests.h | 10 +- libi2pd/Profiling.cpp | 70 +-- libi2pd/Profiling.h | 28 +- libi2pd/Queue.h | 40 +- libi2pd/Reseed.cpp | 118 ++--- libi2pd/Reseed.h | 20 +- libi2pd/RouterContext.cpp | 4 +- libi2pd/RouterContext.h | 50 +- libi2pd/RouterInfo.cpp | 312 ++++++------ libi2pd/RouterInfo.h | 64 +-- libi2pd/SSU.cpp | 300 +++++------ libi2pd/SSU.h | 30 +- libi2pd/SSUData.cpp | 158 +++--- libi2pd/SSUData.h | 50 +- libi2pd/SSUSession.cpp | 370 +++++++------- libi2pd/SSUSession.h | 48 +- libi2pd/Signature.cpp | 180 +++---- libi2pd/Signature.h | 138 ++--- libi2pd/Streaming.cpp | 32 +- libi2pd/Streaming.h | 120 ++--- libi2pd/Tag.h | 2 +- libi2pd/Timestamp.cpp | 2 +- libi2pd/TransitTunnel.cpp | 74 +-- libi2pd/TransitTunnel.h | 44 +- libi2pd/TransportSession.h | 46 +- libi2pd/Tunnel.cpp | 78 +-- libi2pd/Tunnel.h | 112 ++--- libi2pd/TunnelBase.h | 26 +- libi2pd/TunnelConfig.h | 112 ++--- libi2pd/TunnelEndpoint.cpp | 100 ++-- libi2pd/TunnelEndpoint.h | 18 +- libi2pd/TunnelGateway.cpp | 88 ++-- libi2pd/TunnelGateway.h | 18 +- libi2pd/api.cpp | 18 +- libi2pd/api.h | 8 +- libi2pd/util.cpp | 38 +- libi2pd/util.h | 22 +- libi2pd_client/AddressBook.cpp | 4 +- libi2pd_client/AddressBook.h | 26 +- libi2pd_client/BOB.cpp | 256 +++++----- libi2pd_client/BOB.h | 62 +-- libi2pd_client/ClientContext.cpp | 4 +- libi2pd_client/ClientContext.h | 4 +- libi2pd_client/I2CP.cpp | 174 +++---- libi2pd_client/I2CP.h | 46 +- libi2pd_client/I2PService.h | 6 +- libi2pd_client/SAM.cpp | 28 +- libi2pd_client/SAM.h | 4 +- libi2pd_client/SOCKS.cpp | 134 ++--- libi2pd_client/WebSocks.cpp | 6 +- libi2pd_client/Websocket.h | 4 +- qt/i2pd_qt/DaemonQT.cpp | 14 +- qt/i2pd_qt/DaemonQT.h | 10 +- .../org/purplei2p/i2pd/I2PDMainActivity.java | 8 +- .../src/org/purplei2p/i2pd/LocalService.java | 4 +- qt/i2pd_qt/docs/patch_openssl_so_libs.html | 2 +- qt/i2pd_qt/mainwindow.cpp | 8 +- 117 files changed, 3039 insertions(+), 3040 deletions(-) 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.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 e628b63c..22d02af3 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 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 @@ - # 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..467522cf 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); @@ -67,7 +67,7 @@ namespace http 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..be668183 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 () @@ -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); } @@ -190,12 +190,12 @@ namespace client 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..bb7cda90 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,7 +261,7 @@ 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) @@ -276,8 +276,8 @@ namespace data tmp <<= (5 - bits); 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.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/Destination.cpp b/libi2pd/Destination.cpp index cb42e480..5742cbd4 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,16 +59,16 @@ namespace client } } it = params->find (I2CP_PARAM_INBOUND_NICKNAME); - if (it != params->end ()) m_Nickname = it->second; + 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; + 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()); } @@ -492,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 @@ -503,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)); - + } } } @@ -728,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 ()) @@ -956,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 17daecb5..2ca0b7a6 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -190,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 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..117f86d0 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; @@ -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)) 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 93c1acbe..b268baf2 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,7 +123,7 @@ namespace garlic if (m_Owner) m_Owner->RemoveDeliveryStatusSession (m_LeaseSetUpdateMsgID); m_LeaseSetUpdateMsgID = 0; - } + } return !m_SessionTags.empty () || !m_UnconfirmedTagsMsgs.empty (); } @@ -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,10 +542,10 @@ 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 = buf - buf1; @@ -553,11 +553,11 @@ namespace garlic { 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; @@ -591,7 +591,7 @@ namespace garlic { uint8_t * ident = buf; buf += 32; - offset = buf - buf1; + 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); @@ -623,23 +623,23 @@ namespace garlic { 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..9ae88d4a 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,10 +268,10 @@ 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) + 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..d7679fd5 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: @@ -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..21ad1e9b 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -96,7 +96,7 @@ namespace data 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; + 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; diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index d2709a97..f715304e 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,9 +189,9 @@ namespace data endDate -= LEASE_ENDDATE_THRESHOLD; if (ts < endDate && !exclude(*it)) leases.push_back (it); - } - return leases; - } + } + return leases; + } bool LeaseSet::HasExpiredLeases () const { @@ -199,7 +199,7 @@ namespace data 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..172a5078 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..3fc7701e 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,31 +627,31 @@ 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 @@ -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++) @@ -868,9 +868,9 @@ namespace data 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..b119fc26 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..411c8095 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; - + // 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..e7b62e48 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 } @@ -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 (); @@ -362,21 +362,21 @@ namespace transport 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)) { 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)) { 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..dcc28325 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,11 +72,11 @@ 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) @@ -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..0ef31b10 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 93cf2a9f..887f21c2 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; }; - }; + }; //------------------------------------------------- @@ -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/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..4dbeb3b5 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 * nextIdent, uint32_t nextTunnelID, const uint8_t * layerKey,const uint8_t * ivKey): - TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, + 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 * nextIdent, uint32_t nextTunnelID, const uint8_t * layerKey,const uint8_t * ivKey): - TransitTunnel (receiveTunnelID, nextIdent, nextTunnelID, + 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 * 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/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..b07adf53 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..eb922360 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,21 +34,21 @@ 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) { @@ -61,31 +61,31 @@ namespace tunnel 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/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..7bcd1331 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 ())); 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..5ad49ac5 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -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") @@ -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 () 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..9c87cf0e 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,10 +476,10 @@ 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) + if (m_IsSendAccepted) SendMessageStatusMessage (nonce, eI2CPMessageStatusAccepted); // accepted m_Destination->SendMsgTo (buf + offset, payloadLen, identity.GetIdentHash (), nonce); } @@ -488,16 +488,16 @@ namespace client } 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..1054a63c 100644 --- a/libi2pd_client/I2PService.h +++ b/libi2pd_client/I2PService.h @@ -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/SAM.cpp b/libi2pd_client/SAM.cpp index 140140fc..13728eba 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"); }); }); } @@ -668,7 +668,7 @@ namespace client } else // no more data Terminate ("no more data"); - } + } } } @@ -692,7 +692,7 @@ namespace client { auto s = shared_from_this (); m_Owner.GetService ().post ([s] { s->Terminate ("stream read error (op aborted)"); }); - } + } } else { @@ -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")); From d41fabbc9fdcb324ecab7796775398a6f78219fc Mon Sep 17 00:00:00 2001 From: unknown542a Date: Sat, 6 Jan 2018 23:59:22 +0300 Subject: [PATCH 004/119] netDB and certificates in internal storage --- .../src/org/purplei2p/i2pd/Decompress.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 android/src/org/purplei2p/i2pd/Decompress.java diff --git a/android/src/org/purplei2p/i2pd/Decompress.java b/android/src/org/purplei2p/i2pd/Decompress.java new file mode 100644 index 00000000..917abc7c --- /dev/null +++ b/android/src/org/purplei2p/i2pd/Decompress.java @@ -0,0 +1,83 @@ +package org.purplei2p.i2pd; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import android.content.Context; +import android.util.Log; + +public class Decompress { + private static final int BUFFER_SIZE = 1024 * 10; + private static final String TAG = "Decompress"; + + public static void unzipFromAssets(Context context, String zipFile, String destination) { + try { + if (destination == null || destination.length() == 0) + destination = context.getFilesDir().getAbsolutePath(); + InputStream stream = context.getAssets().open(zipFile); + unzip(stream, destination); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static void unzip(String zipFile, String location) { + try { + FileInputStream fin = new FileInputStream(zipFile); + unzip(fin, location); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + + } + + public static void unzip(InputStream stream, String destination) { + dirChecker(destination, ""); + byte[] buffer = new byte[BUFFER_SIZE]; + try { + ZipInputStream zin = new ZipInputStream(stream); + ZipEntry ze = null; + + while ((ze = zin.getNextEntry()) != null) { + Log.v(TAG, "Unzipping " + ze.getName()); + + if (ze.isDirectory()) { + dirChecker(destination, ze.getName()); + } else { + File f = new File(destination + ze.getName()); + if (!f.exists()) { + FileOutputStream fout = new FileOutputStream(destination + ze.getName()); + int count; + while ((count = zin.read(buffer)) != -1) { + fout.write(buffer, 0, count); + } + zin.closeEntry(); + fout.close(); + } + } + + } + zin.close(); + } catch (Exception e) { + Log.e(TAG, "unzip", e); + } + + } + + private static void dirChecker(String destination, String dir) { + File f = new File(destination + dir); + + if (!f.isDirectory()) { + boolean success = f.mkdirs(); + if (!success) { + Log.w(TAG, "Failed to create folder " + f.getName()); + } + } + } +} From 81d7a832c098d21df939eea2e2d74312c1ba8232 Mon Sep 17 00:00:00 2001 From: unknown542a Date: Sun, 7 Jan 2018 00:08:07 +0300 Subject: [PATCH 005/119] netDB and certificates in internal storage --- android/.gitignore | 6 ++- android/build.gradle | 47 +++++++++++++++--------- android/jni/DaemonAndroid.cpp | 5 +-- android/jni/DaemonAndroid.h | 2 +- android/jni/i2pd_android.cpp | 11 +++++- android/src/org/purplei2p/i2pd/I2PD.java | 12 +++++- 6 files changed, 59 insertions(+), 24 deletions(-) diff --git a/android/.gitignore b/android/.gitignore index d9fa5a57..7e166aa6 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -5,4 +5,8 @@ ant.properties local.properties build.sh bin -log* \ No newline at end of file +log* +.gradle* +build +assets +gradle-app.setting diff --git a/android/build.gradle b/android/build.gradle index a88403fd..b69967ef 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,26 +8,32 @@ buildscript { } } +task clean(type: Delete,overwrite: true) { + delete 'build' + delete 'assets' +} + apply plugin: 'com.android.application' android { - compileSdkVersion 25 - buildToolsVersion "25.0.2" - defaultConfig { - applicationId "org.purplei2p.i2pd" - targetSdkVersion 25 - minSdkVersion 14 - versionCode 1 - versionName "2.17.1" - } + compileSdkVersion 25 + buildToolsVersion "25.0.0" + defaultConfig { + applicationId "org.purplei2p.i2pd" + targetSdkVersion 25 + minSdkVersion 14 + versionCode 1 + versionName "2.17.2b" + } sourceSets { main { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = ['src'] - res.srcDirs = ['res'] - jniLibs.srcDirs = ['libs'] - } + res.srcDirs = ['res'] + jniLibs.srcDirs = ['libs'] + assets.srcDirs = ['assets'] } + } signingConfigs { orignal { storeFile file("i2pdapk.jks") @@ -37,11 +43,18 @@ android { } } buildTypes { - release { - minifyEnabled false - signingConfig signingConfigs.orignal - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt' - } + release { + minifyEnabled false + signingConfig signingConfigs.orignal + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt' + } } } +task zipCerts(type: Zip) { + archiveName 'certificates.zip' + destinationDir file('assets') + from (files('../contrib/certificates')) +} + +preBuild.dependsOn zipCerts diff --git a/android/jni/DaemonAndroid.cpp b/android/jni/DaemonAndroid.cpp index 75584740..9865ac79 100644 --- a/android/jni/DaemonAndroid.cpp +++ b/android/jni/DaemonAndroid.cpp @@ -126,12 +126,11 @@ namespace android } */ static DaemonAndroidImpl daemon; - static char* argv[1]={strdup("tmp")}; /** * returns error details if failed * returns "ok" if daemon initialized and started okay */ - std::string start(/*int argc, char* argv[]*/) + std::string start(int argc, char* argv[]) { try { @@ -139,7 +138,7 @@ namespace android { //Log.d(TAG"Initialising the daemon..."); - bool daemonInitSuccess = daemon.init(1,argv); + bool daemonInitSuccess = daemon.init(argc,argv); if(!daemonInitSuccess) { //QMessageBox::critical(0, "Error", "Daemon init failed"); diff --git a/android/jni/DaemonAndroid.h b/android/jni/DaemonAndroid.h index 9cc8219b..81031936 100644 --- a/android/jni/DaemonAndroid.h +++ b/android/jni/DaemonAndroid.h @@ -37,7 +37,7 @@ namespace android * returns "ok" if daemon init failed * returns errinfo if daemon initialized and started okay */ - std::string start(); + std::string start(int argc, char* argv[]); // stops the daemon void stop(); diff --git a/android/jni/i2pd_android.cpp b/android/jni/i2pd_android.cpp index 8791c90b..b4bfa6e6 100755 --- a/android/jni/i2pd_android.cpp +++ b/android/jni/i2pd_android.cpp @@ -45,7 +45,16 @@ JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon (JNIEnv * env, jclass clazz) { - return env->NewStringUTF(i2p::android::start().c_str()); + + int argc=5; + static char* argv[]={ + "i2pd", "--service", "--daemon", + "--conf=/sdcard/i2pd/i2pd.conf", + "--tunconf=/sdcard/i2pd/tunnels.conf", + "--datadir=/data/data/org.purplei2p.i2pd/app_data/" + }; + + return env->NewStringUTF(i2p::android::start(argc,argv).c_str()); } JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon diff --git a/android/src/org/purplei2p/i2pd/I2PD.java b/android/src/org/purplei2p/i2pd/I2PD.java index 86b877ac..869cf570 100755 --- a/android/src/org/purplei2p/i2pd/I2PD.java +++ b/android/src/org/purplei2p/i2pd/I2PD.java @@ -2,6 +2,13 @@ package org.purplei2p.i2pd; import java.io.PrintWriter; import java.io.StringWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + import java.util.Timer; import java.util.TimerTask; @@ -26,7 +33,7 @@ public class I2PD extends Activity { private TextView textView; private final DaemonSingleton daemon = DaemonSingleton.getInstance(); - + private DaemonSingleton.StateUpdateListener daemonStateUpdatedListener = new DaemonSingleton.StateUpdateListener() { @@ -58,6 +65,9 @@ public class I2PD extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + //install certs every time + Decompress.unzipFromAssets(this, "certificates.zip", "/data/data/org.purplei2p.i2pd/app_data/"); + textView = new TextView(this); setContentView(textView); DaemonSingleton.getInstance().addStateChangeListener(daemonStateUpdatedListener); From 8864cbf80ad50146757985b6b36a5aaa94aa91ff Mon Sep 17 00:00:00 2001 From: unlnown542a Date: Sun, 7 Jan 2018 00:40:17 +0300 Subject: [PATCH 006/119] return to strdup() when filling argv[] for i2p::android::start(argc,argv).c_str() --- android/build.gradle | 2 +- android/jni/i2pd_android.cpp | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index b69967ef..fb2fe8c6 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -23,7 +23,7 @@ android { targetSdkVersion 25 minSdkVersion 14 versionCode 1 - versionName "2.17.2b" + versionName "2.17.2c" } sourceSets { main { diff --git a/android/jni/i2pd_android.cpp b/android/jni/i2pd_android.cpp index b4bfa6e6..ac1e2b70 100755 --- a/android/jni/i2pd_android.cpp +++ b/android/jni/i2pd_android.cpp @@ -46,13 +46,14 @@ JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon (JNIEnv * env, jclass clazz) { - int argc=5; - static char* argv[]={ - "i2pd", "--service", "--daemon", - "--conf=/sdcard/i2pd/i2pd.conf", - "--tunconf=/sdcard/i2pd/tunnels.conf", - "--datadir=/data/data/org.purplei2p.i2pd/app_data/" - }; + int argc=5; + static char* argv[]={ + strdup("i2pd"), + strdup("--conf=/sdcard/i2pd/i2pd.conf"), + strdup("--tunconf=/sdcard/i2pd/tunnels.conf"), + strdup("--datadir=/data/data/org.purplei2p.i2pd/app_data/"), + strdup("--service"), strdup("--daemon") + }; return env->NewStringUTF(i2p::android::start(argc,argv).c_str()); } From cf5081d300051b7c188ff39aacadad29d492900e Mon Sep 17 00:00:00 2001 From: unlnown542a Date: Sun, 7 Jan 2018 19:30:32 +0300 Subject: [PATCH 007/119] fixed creating certificates.zip when target zip did not include the directory certificates, so they were bein unpacked into datadir. Added entryCompression ZipEntryCompression.STORED since final APK is being compressed as well. Put all custom tasks under android plugin definitions --- android/build.gradle | 22 ++++++++++++---------- android/gradle.properties | 1 + 2 files changed, 13 insertions(+), 10 deletions(-) create mode 100644 android/gradle.properties diff --git a/android/build.gradle b/android/build.gradle index fb2fe8c6..fcbb47ec 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,11 +8,6 @@ buildscript { } } -task clean(type: Delete,overwrite: true) { - delete 'build' - delete 'assets' -} - apply plugin: 'com.android.application' android { @@ -23,7 +18,7 @@ android { targetSdkVersion 25 minSdkVersion 14 versionCode 1 - versionName "2.17.2c" + versionName "2.17.2e" } sourceSets { main { @@ -51,10 +46,17 @@ android { } } -task zipCerts(type: Zip) { - archiveName 'certificates.zip' +task zipCerts(type:Zip) { + from (files('../contrib/')) + include 'certificates/**/*.crt' destinationDir file('assets') - from (files('../contrib/certificates')) + archiveName 'certificates.zip' + entryCompression ZipEntryCompression.STORED +} +preBuild.dependsOn zipCerts + +task clean(type: Delete,overwrite: true) { + delete 'build' + delete 'assets' } -preBuild.dependsOn zipCerts diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 00000000..e32ec00b --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 From e630b8f8a8077aac4eece7495e8e92b8517906f0 Mon Sep 17 00:00:00 2001 From: Peter Jankuliak Date: Fri, 12 Jan 2018 11:04:12 +0100 Subject: [PATCH 008/119] Inherit _publicly_ from shared_from_this in I2PService --- libi2pd_client/I2PService.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd_client/I2PService.h b/libi2pd_client/I2PService.h index fd5e8999..ebe2164c 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; From 50ba52756fee9bfc0c33a6c4979477865db2385c Mon Sep 17 00:00:00 2001 From: yangfl Date: Sat, 6 Jan 2018 12:01:44 +0800 Subject: [PATCH 009/119] fix mixing tabs and spaces --- daemon/HTTPServer.h | 2 +- daemon/I2PControl.cpp | 4 ++-- libi2pd/Base.cpp | 6 +++--- libi2pd/Crypto.cpp | 2 +- libi2pd/Datagram.h | 2 +- libi2pd/Destination.cpp | 2 +- libi2pd/Destination.h | 2 +- libi2pd/FS.cpp | 4 ++-- libi2pd/Garlic.cpp | 2 +- libi2pd/HTTP.cpp | 2 +- libi2pd/Identity.cpp | 2 +- libi2pd/Identity.h | 8 ++++---- libi2pd/LeaseSet.cpp | 4 ++-- libi2pd/LeaseSet.h | 2 +- libi2pd/NetDb.cpp | 4 ++-- libi2pd/RouterInfo.cpp | 2 +- libi2pd/RouterInfo.h | 4 ++-- libi2pd/SSU.cpp | 8 ++++---- libi2pd/SSUData.cpp | 2 +- libi2pd/SSUData.h | 2 +- libi2pd/Streaming.h | 2 +- libi2pd/Timestamp.h | 6 +++--- libi2pd/TransitTunnel.h | 18 +++++++++--------- libi2pd/Transports.cpp | 6 +++--- libi2pd/Transports.h | 4 ++-- libi2pd/TunnelBase.h | 2 +- libi2pd/TunnelEndpoint.cpp | 2 +- libi2pd/TunnelPool.cpp | 6 +++--- libi2pd_client/ClientContext.cpp | 18 +++++++++--------- libi2pd_client/I2CP.cpp | 16 ++++++++-------- libi2pd_client/I2PTunnel.cpp | 2 +- libi2pd_client/SAM.cpp | 6 +++--- 32 files changed, 77 insertions(+), 77 deletions(-) diff --git a/daemon/HTTPServer.h b/daemon/HTTPServer.h index 467522cf..f1ca10fc 100644 --- a/daemon/HTTPServer.h +++ b/daemon/HTTPServer.h @@ -63,7 +63,7 @@ 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); diff --git a/daemon/I2PControl.cpp b/daemon/I2PControl.cpp index be668183..494ea026 100644 --- a/daemon/I2PControl.cpp +++ b/daemon/I2PControl.cpp @@ -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) @@ -187,7 +187,7 @@ 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) diff --git a/libi2pd/Base.cpp b/libi2pd/Base.cpp index bb7cda90..09f04c05 100644 --- a/libi2pd/Base.cpp +++ b/libi2pd/Base.cpp @@ -267,14 +267,14 @@ namespace data 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; } } 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/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 5742cbd4..33eff029 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -780,7 +780,7 @@ namespace client delete m_DatagramDestination; m_DatagramDestination = nullptr; } - return true; + return true; } else return false; diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 2ca0b7a6..6f37e768 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -239,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/FS.cpp b/libi2pd/FS.cpp index 117f86d0..21fb103b 100644 --- a/libi2pd/FS.cpp +++ b/libi2pd/FS.cpp @@ -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 (); @@ -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/Garlic.cpp b/libi2pd/Garlic.cpp index b268baf2..59089072 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -125,7 +125,7 @@ namespace garlic m_LeaseSetUpdateMsgID = 0; } return !m_SessionTags.empty () || !m_UnconfirmedTagsMsgs.empty (); - } + } bool GarlicRoutingSession::CleanupUnconfirmedTags () { diff --git a/libi2pd/HTTP.cpp b/libi2pd/HTTP.cpp index 9ae88d4a..24e55457 100644 --- a/libi2pd/HTTP.cpp +++ b/libi2pd/HTTP.cpp @@ -272,7 +272,7 @@ namespace http { { o << method << " " << uri << " " << version << CRLF; for (auto & h : headers) - o << h.first << ": " << h.second << CRLF; + o << h.first << ": " << h.second << CRLF; o << CRLF; } diff --git a/libi2pd/Identity.cpp b/libi2pd/Identity.cpp index d7679fd5..3fcd16ad 100644 --- a/libi2pd/Identity.cpp +++ b/libi2pd/Identity.cpp @@ -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); } diff --git a/libi2pd/Identity.h b/libi2pd/Identity.h index 21ad1e9b..584e6475 100644 --- a/libi2pd/Identity.h +++ b/libi2pd/Identity.h @@ -91,11 +91,11 @@ 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; }; + 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; @@ -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 f715304e..d1a70ba5 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -194,12 +194,12 @@ namespace data } 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 { diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 172a5078..c7d2066e 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -38,7 +38,7 @@ namespace data struct LeaseCmp { bool operator() (std::shared_ptr l1, std::shared_ptr l2) const - { + { if (l1->tunnelID != l2->tunnelID) return l1->tunnelID < l2->tunnelID; else diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 3fc7701e..0215c570 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -655,7 +655,7 @@ namespace data 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) @@ -866,7 +866,7 @@ namespace data if (closestFloodfills.empty ()) LogPrint (eLogWarning, "NetDb: Requested ", key, " not found, ", numExcluded, " peers excluded"); replyMsg = CreateDatabaseSearchReply (ident, closestFloodfills); - } + } } excluded += numExcluded * 32; if (replyMsg) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index b119fc26..e9c2a384 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -224,7 +224,7 @@ namespace data supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV4 : eSSUV4; else supportedTransports |= (address->transportStyle == eTransportNTCP) ? eNTCPV6 : eSSUV6; - } + } } else if (!strcmp (key, "port")) address->port = boost::lexical_cast(value); diff --git a/libi2pd/RouterInfo.h b/libi2pd/RouterInfo.h index 411c8095..09e2c015 100644 --- a/libi2pd/RouterInfo.h +++ b/libi2pd/RouterInfo.h @@ -181,8 +181,8 @@ namespace data void DeleteBuffer () { delete[] m_Buffer; m_Buffer = nullptr; }; 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; }; diff --git a/libi2pd/SSU.cpp b/libi2pd/SSU.cpp index e7b62e48..2197552c 100644 --- a/libi2pd/SSU.cpp +++ b/libi2pd/SSU.cpp @@ -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 (); @@ -357,7 +357,7 @@ 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; @@ -747,7 +747,7 @@ namespace transport { 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] @@ -773,7 +773,7 @@ namespace transport { 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] diff --git a/libi2pd/SSUData.cpp b/libi2pd/SSUData.cpp index dcc28325..d789e70e 100644 --- a/libi2pd/SSUData.cpp +++ b/libi2pd/SSUData.cpp @@ -81,7 +81,7 @@ namespace transport 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); } diff --git a/libi2pd/SSUData.h b/libi2pd/SSUData.h index 0ef31b10..fbd167bf 100644 --- a/libi2pd/SSUData.h +++ b/libi2pd/SSUData.h @@ -57,7 +57,7 @@ namespace transport struct FragmentCmp { bool operator() (const std::unique_ptr& f1, const std::unique_ptr& f2) const - { + { return f1->fragmentNum < f2->fragmentNum; }; }; diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 887f21c2..202ff73f 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -98,7 +98,7 @@ namespace stream struct PacketCmp { bool operator() (const Packet * p1, const Packet * p2) const - { + { return p1->GetSeqn () < p2->GetSeqn (); }; }; 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.h b/libi2pd/TransitTunnel.h index 4dbeb3b5..5b891dc3 100644 --- a/libi2pd/TransitTunnel.h +++ b/libi2pd/TransitTunnel.h @@ -20,8 +20,8 @@ namespace tunnel 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; }; @@ -39,8 +39,8 @@ namespace tunnel public: TransitTunnelParticipant (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_NumTransmittedBytes (0) {}; ~TransitTunnelParticipant (); @@ -60,8 +60,8 @@ namespace tunnel public: TransitTunnelGateway (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_Gateway(this) {}; @@ -80,8 +80,8 @@ namespace tunnel 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 @@ -97,7 +97,7 @@ namespace tunnel 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 * layerKey,const uint8_t * ivKey, bool isGateway, bool isEndpoint); } } 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/TunnelBase.h b/libi2pd/TunnelBase.h index b07adf53..8b7fb408 100644 --- a/libi2pd/TunnelBase.h +++ b/libi2pd/TunnelBase.h @@ -60,7 +60,7 @@ namespace tunnel struct TunnelCreationTimeCmp { bool operator() (std::shared_ptr t1, std::shared_ptr t2) const - { + { if (t1->GetCreationTime () != t2->GetCreationTime ()) return t1->GetCreationTime () > t2->GetCreationTime (); else diff --git a/libi2pd/TunnelEndpoint.cpp b/libi2pd/TunnelEndpoint.cpp index eb922360..324d5315 100644 --- a/libi2pd/TunnelEndpoint.cpp +++ b/libi2pd/TunnelEndpoint.cpp @@ -54,7 +54,7 @@ namespace tunnel { case eDeliveryTypeLocal: // 0 break; - case eDeliveryTypeTunnel: // 1 + case eDeliveryTypeTunnel: // 1 m.tunnelID = bufbe32toh (fragment); fragment += 4; // tunnelID m.hash = i2p::data::IdentHash (fragment); 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_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 5ad49ac5..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(); @@ -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); @@ -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/I2CP.cpp b/libi2pd_client/I2CP.cpp index 9c87cf0e..371456ee 100644 --- a/libi2pd_client/I2CP.cpp +++ b/libi2pd_client/I2CP.cpp @@ -280,7 +280,7 @@ namespace client 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::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, buf)); } else @@ -480,14 +480,14 @@ namespace client offset += 4; uint32_t nonce = bufbe32toh (buf + offset + payloadLen); if (m_IsSendAccepted) - SendMessageStatusMessage (nonce, eI2CPMessageStatusAccepted); // accepted + 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 @@ -634,7 +634,7 @@ namespace client 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::bind(&I2CPSession::HandleI2CPMessageSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, buf)); } 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 13728eba..57767e77 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -664,7 +664,7 @@ 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 (); @@ -698,7 +698,7 @@ namespace client { 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)); } } From 207212557ebb5a2b63f1037d0b3a61d89b4f2b5f Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Mon, 15 Jan 2018 08:19:57 -0500 Subject: [PATCH 010/119] fix sam race conditions --- libi2pd/Streaming.h | 21 +-- libi2pd_client/SAM.cpp | 320 ++++++++++++++++++++++++++--------------- libi2pd_client/SAM.h | 22 +-- 3 files changed, 227 insertions(+), 136 deletions(-) diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 93cf2a9f..a9e5dcdd 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -69,7 +69,7 @@ namespace stream */ const uint64_t DEFAULT_BAN_INTERVAL = 60 * 60 * 1000; - struct Packet + struct Packet { size_t len, offset; uint8_t buf[MAX_PACKET_SIZE]; @@ -276,8 +276,8 @@ namespace stream /** set max connections per minute per destination */ void SetMaxConnsPerMinute(const uint32_t conns); - Packet * NewPacket () { return m_PacketsPool.Acquire (); } - void DeletePacket (Packet * p) { m_PacketsPool.Release (p); } + Packet * NewPacket () { return new Packet; } + void DeletePacket (Packet * p) { delete p; } private: @@ -316,7 +316,7 @@ namespace stream std::vector m_Banned; uint64_t m_LastBanClear; - i2p::util::MemoryPool m_PacketsPool; + //i2p::util::MemoryPool m_PacketsPool; bool m_EnableDrop; public: @@ -334,16 +334,21 @@ namespace stream void Stream::AsyncReceive (const Buffer& buffer, ReceiveHandler handler, int timeout) { auto s = shared_from_this(); - m_Service.post ([=](void) + m_Service.post ([s, buffer, handler, timeout](void) { 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 { - int t = (timeout > MAX_RECEIVE_TIMEOUT) ? MAX_RECEIVE_TIMEOUT : timeout; + int t = (timeout > MAX_RECEIVE_TIMEOUT) ? MAX_RECEIVE_TIMEOUT : timeout; s->m_ReceiveTimer.expires_from_now (boost::posix_time::seconds(t)); - s->m_ReceiveTimer.async_wait ([=](const boost::system::error_code& ecode) - { s->HandleReceiveTimer (ecode, buffer, handler, timeout - t); }); + int left = timeout - t; + auto self = s->shared_from_this(); + self->m_ReceiveTimer.async_wait ( + [self, buffer, handler, left](const boost::system::error_code & ec) + { + self->HandleReceiveTimer(ec, buffer, handler, left); + }); } }); } diff --git a/libi2pd_client/SAM.cpp b/libi2pd_client/SAM.cpp index 140140fc..4ea6b61b 100644 --- a/libi2pd_client/SAM.cpp +++ b/libi2pd_client/SAM.cpp @@ -15,31 +15,22 @@ namespace i2p { namespace client { - SAMSocket::SAMSocket (SAMBridge& owner): - m_Owner (owner), m_Socket (m_Owner.GetService ()), m_Timer (m_Owner.GetService ()), - m_BufferOffset (0), m_SocketType (eSAMSocketTypeUnknown), m_IsSilent (false), - m_IsAccepting (false), m_Stream (nullptr), m_Session (nullptr) + SAMSocket::SAMSocket (SAMBridge& owner, std::shared_ptr socket): + m_Owner (owner), m_Socket(socket), m_Timer (m_Owner.GetService ()), + m_BufferOffset (0), + m_SocketType (eSAMSocketTypeUnknown), m_IsSilent (false), + m_IsAccepting (false), m_Stream (nullptr) { } SAMSocket::~SAMSocket () { - Terminate ("~SAMSocket()"); - } - - void SAMSocket::CloseStream (const char* reason) - { - LogPrint (eLogDebug, "SAMSocket::CloseStream, reason: ", reason); - if (m_Stream) + if(m_Stream) { m_Stream->Close (); m_Stream.reset (); - } - } - - void SAMSocket::Terminate (const char* reason) - { - CloseStream (reason); + } + auto Session = m_Owner.FindSession(m_ID); switch (m_SocketType) { @@ -48,17 +39,17 @@ namespace client break; case eSAMSocketTypeStream: { - if (m_Session) - m_Session->DelSocket (shared_from_this ()); + if (Session) + Session->DelSocket (this); break; } case eSAMSocketTypeAcceptor: { - if (m_Session) + if (Session) { - m_Session->DelSocket (shared_from_this ()); - if (m_IsAccepting && m_Session->localDestination) - m_Session->localDestination->StopAcceptingStreams (); + Session->DelSocket (this); + if (m_IsAccepting && Session->localDestination) + Session->localDestination->StopAcceptingStreams (); } break; } @@ -66,15 +57,54 @@ namespace client ; } m_SocketType = eSAMSocketTypeTerminated; - if (m_Socket.is_open()) m_Socket.close (); - m_Session = nullptr; + if (m_Socket && m_Socket->is_open()) m_Socket->close (); + m_Socket.reset (); + } + + void SAMSocket::Terminate (const char* reason) + { + if(m_Stream) + { + m_Stream->Close (); + m_Stream.reset (); + } + auto Session = m_Owner.FindSession(m_ID); + + switch (m_SocketType) + { + case eSAMSocketTypeSession: + m_Owner.CloseSession (m_ID); + break; + case eSAMSocketTypeStream: + { + if (Session) + Session->DelSocket (this); + break; + } + case eSAMSocketTypeAcceptor: + { + if (Session) + { + Session->DelSocket (this); + if (m_IsAccepting && Session->localDestination) + Session->localDestination->StopAcceptingStreams (); + } + break; + } + default: + ; + } + m_SocketType = eSAMSocketTypeTerminated; + if (m_Socket && m_Socket->is_open()) m_Socket->close (); + m_Socket.reset (); } void SAMSocket::ReceiveHandshake () { - m_Socket.async_read_some (boost::asio::buffer(m_Buffer, SAM_SOCKET_BUFFER_SIZE), - std::bind(&SAMSocket::HandleHandshakeReceived, shared_from_this (), - std::placeholders::_1, std::placeholders::_2)); + if(m_Socket) + m_Socket->async_read_some (boost::asio::buffer(m_Buffer, SAM_SOCKET_BUFFER_SIZE), + std::bind(&SAMSocket::HandleHandshakeReceived, shared_from_this (), + std::placeholders::_1, std::placeholders::_2)); } void SAMSocket::HandleHandshakeReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) @@ -121,7 +151,7 @@ namespace client #else size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, version.c_str ()); #endif - boost::asio::async_write (m_Socket, boost::asio::buffer (m_Buffer, l), boost::asio::transfer_all (), + boost::asio::async_write (*m_Socket, boost::asio::buffer (m_Buffer, l), boost::asio::transfer_all (), std::bind(&SAMSocket::HandleHandshakeReplySent, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } @@ -144,9 +174,9 @@ namespace client if (ecode != boost::asio::error::operation_aborted) Terminate ("SAM: handshake reply send error"); } - else + else if(m_Socket) { - m_Socket.async_read_some (boost::asio::buffer(m_Buffer, SAM_SOCKET_BUFFER_SIZE), + m_Socket->async_read_some (boost::asio::buffer(m_Buffer, SAM_SOCKET_BUFFER_SIZE), std::bind(&SAMSocket::HandleMessage, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } @@ -157,7 +187,7 @@ namespace client LogPrint (eLogDebug, "SAMSocket::SendMessageReply, close=",close?"true":"false", " reason: ", msg); if (!m_IsSilent) - boost::asio::async_write (m_Socket, boost::asio::buffer (msg, len), boost::asio::transfer_all (), + boost::asio::async_write (*m_Socket, boost::asio::buffer (msg, len), boost::asio::transfer_all (), std::bind(&SAMSocket::HandleMessageReplySent, shared_from_this (), std::placeholders::_1, std::placeholders::_2, close)); else @@ -306,19 +336,19 @@ namespace client } // create destination - m_Session = m_Owner.CreateSession (id, destination == SAM_VALUE_TRANSIENT ? "" : destination, ¶ms); - if (m_Session) + auto session = m_Owner.CreateSession (id, destination == SAM_VALUE_TRANSIENT ? "" : destination, ¶ms); + if (session) { m_SocketType = eSAMSocketTypeSession; if (style == SAM_VALUE_DATAGRAM) { - m_Session->UDPEndpoint = forward; - auto dest = m_Session->localDestination->CreateDatagramDestination (); + session->UDPEndpoint = forward; + auto dest = session->localDestination->CreateDatagramDestination (); dest->SetReceiver (std::bind (&SAMSocket::HandleI2PDatagramReceive, shared_from_this (), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5)); } - if (m_Session->localDestination->IsReady ()) + if (session->localDestination->IsReady ()) SendSessionCreateReplyOk (); else { @@ -335,30 +365,38 @@ namespace client { if (ecode != boost::asio::error::operation_aborted) { - if (m_Session->localDestination->IsReady ()) - SendSessionCreateReplyOk (); - else + auto session = m_Owner.FindSession(m_ID); + if(session) { - m_Timer.expires_from_now (boost::posix_time::seconds(SAM_SESSION_READINESS_CHECK_INTERVAL)); - m_Timer.async_wait (std::bind (&SAMSocket::HandleSessionReadinessCheckTimer, - shared_from_this (), std::placeholders::_1)); + if (session->localDestination->IsReady ()) + SendSessionCreateReplyOk (); + else + { + m_Timer.expires_from_now (boost::posix_time::seconds(SAM_SESSION_READINESS_CHECK_INTERVAL)); + m_Timer.async_wait (std::bind (&SAMSocket::HandleSessionReadinessCheckTimer, + shared_from_this (), std::placeholders::_1)); + } } } } void SAMSocket::SendSessionCreateReplyOk () { - uint8_t buf[1024]; - char priv[1024]; - size_t l = m_Session->localDestination->GetPrivateKeys ().ToBuffer (buf, 1024); - size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, priv, 1024); - priv[l1] = 0; + auto session = m_Owner.FindSession(m_ID); + if (session) + { + uint8_t buf[1024]; + char priv[1024]; + size_t l = session->localDestination->GetPrivateKeys ().ToBuffer (buf, 1024); + size_t l1 = i2p::data::ByteStreamToBase64 (buf, l, priv, 1024); + priv[l1] = 0; #ifdef _MSC_VER - size_t l2 = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv); + size_t l2 = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv); #else - size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv); + size_t l2 = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_SESSION_CREATE_REPLY_OK, priv); #endif - SendMessageReply (m_Buffer, l2, false); + SendMessageReply (m_Buffer, l2, false); + } } void SAMSocket::ProcessStreamConnect (char * buf, size_t len, size_t rem) @@ -371,8 +409,8 @@ namespace client std::string& silent = params[SAM_PARAM_SILENT]; if (silent == SAM_VALUE_TRUE) m_IsSilent = true; m_ID = id; - m_Session = m_Owner.FindSession (id); - if (m_Session) + auto session = m_Owner.FindSession (id); + if (session) { if (rem > 0) // handle follow on data { @@ -387,12 +425,12 @@ namespace client if (l > 0) { context.GetAddressBook().InsertAddress(dest); - auto leaseSet = m_Session->localDestination->FindLeaseSet(dest->GetIdentHash()); + auto leaseSet = session->localDestination->FindLeaseSet(dest->GetIdentHash()); if (leaseSet) Connect(leaseSet); else { - m_Session->localDestination->RequestDestination(dest->GetIdentHash(), + session->localDestination->RequestDestination(dest->GetIdentHash(), std::bind(&SAMSocket::HandleConnectLeaseSetRequestComplete, shared_from_this(), std::placeholders::_1)); } @@ -406,13 +444,17 @@ namespace client void SAMSocket::Connect (std::shared_ptr remote) { - m_SocketType = eSAMSocketTypeStream; - m_Session->AddSocket (shared_from_this ()); - m_Stream = m_Session->localDestination->CreateStream (remote); - m_Stream->Send ((uint8_t *)m_Buffer, m_BufferOffset); // connect and send - m_BufferOffset = 0; - I2PReceive (); - SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + auto session = m_Owner.FindSession(m_ID); + if(session) + { + m_SocketType = eSAMSocketTypeStream; + session->AddSocket (shared_from_this ()); + m_Stream = session->localDestination->CreateStream (remote); + m_Stream->Send ((uint8_t *)m_Buffer, m_BufferOffset); // connect and send + m_BufferOffset = 0; + I2PReceive (); + SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); + } } void SAMSocket::HandleConnectLeaseSetRequestComplete (std::shared_ptr leaseSet) @@ -435,15 +477,15 @@ namespace client std::string& silent = params[SAM_PARAM_SILENT]; if (silent == SAM_VALUE_TRUE) m_IsSilent = true; m_ID = id; - m_Session = m_Owner.FindSession (id); - if (m_Session) + auto session = m_Owner.FindSession (id); + if (session) { m_SocketType = eSAMSocketTypeAcceptor; - m_Session->AddSocket (shared_from_this ()); - if (!m_Session->localDestination->IsAcceptingStreams ()) + session->AddSocket (shared_from_this ()); + if (!session->localDestination->IsAcceptingStreams ()) { m_IsAccepting = true; - m_Session->localDestination->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1)); + session->localDestination->AcceptOnce (std::bind (&SAMSocket::HandleI2PAccept, shared_from_this (), std::placeholders::_1)); } SendMessageReply (SAM_STREAM_STATUS_OK, strlen(SAM_STREAM_STATUS_OK), false); } @@ -459,9 +501,10 @@ namespace client size_t size = std::stoi(params[SAM_PARAM_SIZE]), offset = data - buf; if (offset + size <= len) { - if (m_Session) + auto session = m_Owner.FindSession(m_ID); + if (session) { - auto d = m_Session->localDestination->GetDatagramDestination (); + auto d = session->localDestination->GetDatagramDestination (); if (d) { i2p::data::IdentityEx dest; @@ -516,7 +559,8 @@ namespace client std::string& name = params[SAM_PARAM_NAME]; std::shared_ptr identity; i2p::data::IdentHash ident; - auto dest = m_Session == nullptr ? context.GetSharedLocalDestination() : m_Session->localDestination; + auto session = m_Owner.FindSession(m_ID); + auto dest = session == nullptr ? context.GetSharedLocalDestination() : session->localDestination; if (name == "ME") SendNamingLookupReply (dest->GetIdentity ()); else if ((identity = context.GetAddressBook ().GetAddress (name)) != nullptr) @@ -612,16 +656,18 @@ namespace client LogPrint (eLogError, "SAM: Buffer is full, terminate"); Terminate ("Buffer is full"); return; - } - m_Socket.async_read_some (boost::asio::buffer(m_Buffer + m_BufferOffset, SAM_SOCKET_BUFFER_SIZE - m_BufferOffset), - std::bind((m_SocketType == eSAMSocketTypeStream) ? &SAMSocket::HandleReceived : &SAMSocket::HandleMessage, - shared_from_this (), std::placeholders::_1, std::placeholders::_2)); + } else if (m_Socket) + m_Socket->async_read_some (boost::asio::buffer(m_Buffer + m_BufferOffset, SAM_SOCKET_BUFFER_SIZE - m_BufferOffset), + std::bind((m_SocketType == eSAMSocketTypeStream) ? &SAMSocket::HandleReceived : &SAMSocket::HandleMessage, + shared_from_this (), std::placeholders::_1, std::placeholders::_2)); + else + LogPrint(eLogError, "SAM: receive with no native socket"); } void SAMSocket::HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) { if (ecode) - { + { LogPrint (eLogError, "SAM: read error: ", ecode.message ()); if (ecode != boost::asio::error::operation_aborted) Terminate ("read error"); @@ -637,7 +683,7 @@ namespace client [s](const boost::system::error_code& ecode) { if (!ecode) - s->Receive (); + s->m_Owner.GetService ().post ([s] { s->Receive (); }); else s->m_Owner.GetService ().post ([s] { s->Terminate ("AsyncSend failed"); }); }); @@ -650,21 +696,21 @@ namespace client if (m_Stream) { if (m_Stream->GetStatus () == i2p::stream::eStreamStatusNew || - m_Stream->GetStatus () == i2p::stream::eStreamStatusOpen) // regular + m_Stream->GetStatus () == i2p::stream::eStreamStatusOpen) // regular { m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE), - std::bind (&SAMSocket::HandleI2PReceive, shared_from_this (), + std::bind (&SAMSocket::HandleI2PReceive, shared_from_this(), std::placeholders::_1, std::placeholders::_2), - SAM_SOCKET_CONNECTION_MAX_IDLE); + SAM_SOCKET_CONNECTION_MAX_IDLE); } else // closed by peer { + uint8_t * buff = new uint8_t[SAM_SOCKET_BUFFER_SIZE]; // get remaning data - auto len = m_Stream->ReadSome (m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE); + auto len = m_Stream->ReadSome (buff, SAM_SOCKET_BUFFER_SIZE); 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)); + WriteI2PDataImmediate(buff, len); } else // no more data Terminate ("no more data"); @@ -672,6 +718,30 @@ namespace client } } + void SAMSocket::WriteI2PDataImmediate(uint8_t * buff, size_t sz) + { + if(m_Socket) + boost::asio::async_write ( + *m_Socket, + boost::asio::buffer (buff, sz), + boost::asio::transfer_all(), + std::bind (&SAMSocket::HandleWriteI2PDataImmediate, shared_from_this (), std::placeholders::_1, buff)); // postpone termination + else + LogPrint(eLogError, "SAM: no native socket"); + } + + void SAMSocket::HandleWriteI2PDataImmediate(const boost::system::error_code & ec, uint8_t * buff) + { + delete [] buff; + } + + void SAMSocket::WriteI2PData(size_t sz) + { + uint8_t * sendbuff = new uint8_t[sz]; + memcpy(sendbuff, m_StreamBuffer, sz); + WriteI2PDataImmediate(sendbuff, sz); + } + void SAMSocket::HandleI2PReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred) { if (ecode) @@ -680,8 +750,9 @@ namespace client if (ecode != boost::asio::error::operation_aborted) { 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 + { + WriteI2PData(bytes_transferred); + } else { auto s = shared_from_this (); @@ -696,13 +767,18 @@ namespace client } 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)); + if (m_SocketType != eSAMSocketTypeTerminated) + { + if (bytes_transferred > 0) + { + WriteI2PData(bytes_transferred); + } + I2PReceive(); + } } } - void SAMSocket::HandleWriteI2PData (const boost::system::error_code& ecode) + void SAMSocket::HandleWriteI2PData (const boost::system::error_code& ecode, size_t bytes_transferred) { if (ecode) { @@ -711,7 +787,9 @@ namespace client Terminate ("socket write error at HandleWriteI2PData"); } else + { I2PReceive (); + } } void SAMSocket::HandleI2PAccept (std::shared_ptr stream) @@ -760,39 +838,42 @@ namespace client { LogPrint (eLogDebug, "SAM: datagram received ", len); auto base64 = from.ToBase64 (); - auto ep = m_Session->UDPEndpoint; - if (ep) + auto session = m_Owner.FindSession(m_ID); + if(session) { - // udp forward enabled - size_t bsz = base64.size(); - size_t sz = bsz + 1 + len; - // build datagram body - uint8_t * data = new uint8_t[sz]; - // Destination - memcpy(data, base64.c_str(), bsz); - // linefeed - data[bsz] = '\n'; - // Payload - memcpy(data+bsz+1, buf, len); - // send to remote endpoint - m_Owner.SendTo(data, sz, ep); - delete [] data; - } - else - { -#ifdef _MSC_VER - size_t l = sprintf_s ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len); -#else - size_t l = snprintf ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len); -#endif - if (len < SAM_SOCKET_BUFFER_SIZE - l) + auto ep = session->UDPEndpoint; + if (ep) { - memcpy (m_StreamBuffer + l, buf, len); - boost::asio::async_write (m_Socket, boost::asio::buffer (m_StreamBuffer, len + l), - std::bind (&SAMSocket::HandleWriteI2PData, shared_from_this (), std::placeholders::_1)); + // udp forward enabled + size_t bsz = base64.size(); + size_t sz = bsz + 1 + len; + // build datagram body + uint8_t * data = new uint8_t[sz]; + // Destination + memcpy(data, base64.c_str(), bsz); + // linefeed + data[bsz] = '\n'; + // Payload + memcpy(data+bsz+1, buf, len); + // send to remote endpoint + m_Owner.SendTo(data, sz, ep); + delete [] data; } else - LogPrint (eLogWarning, "SAM: received datagram size ", len," exceeds buffer"); + { +#ifdef _MSC_VER + size_t l = sprintf_s ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len); +#else + size_t l = snprintf ((char *)m_StreamBuffer, SAM_SOCKET_BUFFER_SIZE, SAM_DATAGRAM_RECEIVED, base64.c_str (), (long unsigned int)len); +#endif + if (len < SAM_SOCKET_BUFFER_SIZE - l) + { + memcpy (m_StreamBuffer + l, buf, len); + WriteI2PData(len + l); + } + else + LogPrint (eLogWarning, "SAM: received datagram size ", len," exceeds buffer"); + } } } @@ -875,8 +956,9 @@ namespace client void SAMBridge::Accept () { - auto newSocket = std::make_shared (*this); - m_Acceptor.async_accept (newSocket->GetSocket (), std::bind (&SAMBridge::HandleAccept, this, + auto native = std::make_shared(m_Service); + auto newSocket = std::make_shared (*this, native); + m_Acceptor.async_accept (*native, std::bind (&SAMBridge::HandleAccept, this, std::placeholders::_1, newSocket)); } diff --git a/libi2pd_client/SAM.h b/libi2pd_client/SAM.h index f2c84e3c..9282fe1d 100644 --- a/libi2pd_client/SAM.h +++ b/libi2pd_client/SAM.h @@ -79,11 +79,11 @@ namespace client { public: - SAMSocket (SAMBridge& owner); + typedef boost::asio::ip::tcp::socket Socket_t; + SAMSocket (SAMBridge& owner, std::shared_ptr socket); ~SAMSocket (); - void CloseStream (const char* reason); // TODO: implement it better - boost::asio::ip::tcp::socket& GetSocket () { return m_Socket; }; + boost::asio::ip::tcp::socket& GetSocket () { return *m_Socket; }; void ReceiveHandshake (); void SetSocketType (SAMSocketType socketType) { m_SocketType = socketType; }; SAMSocketType GetSocketType () const { return m_SocketType; }; @@ -103,7 +103,7 @@ namespace client void I2PReceive (); void HandleI2PReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred); void HandleI2PAccept (std::shared_ptr stream); - void HandleWriteI2PData (const boost::system::error_code& ecode); + void HandleWriteI2PData (const boost::system::error_code& ecode, size_t sz); void HandleI2PDatagramReceive (const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len); void ProcessSessionCreate (char * buf, size_t len); @@ -122,10 +122,15 @@ namespace client void HandleSessionReadinessCheckTimer (const boost::system::error_code& ecode); void SendSessionCreateReplyOk (); + void WriteI2PData(size_t sz); + void WriteI2PDataImmediate(uint8_t * ptr, size_t sz); + + void HandleWriteI2PDataImmediate(const boost::system::error_code & ec, uint8_t * buff); + private: SAMBridge& m_Owner; - boost::asio::ip::tcp::socket m_Socket; + std::shared_ptr m_Socket; boost::asio::deadline_timer m_Timer; char m_Buffer[SAM_SOCKET_BUFFER_SIZE + 1]; size_t m_BufferOffset; @@ -135,7 +140,6 @@ namespace client bool m_IsSilent; bool m_IsAccepting; // for eSAMSocketTypeAcceptor only std::shared_ptr m_Stream; - std::shared_ptr m_Session; }; struct SAMSession @@ -146,15 +150,15 @@ namespace client std::mutex m_SocketsMutex; /** safely add a socket to this session */ - void AddSocket(const std::shared_ptr & sock) { + void AddSocket(std::shared_ptr sock) { std::lock_guard lock(m_SocketsMutex); m_Sockets.push_back(sock); } /** safely remove a socket from this session */ - void DelSocket(const std::shared_ptr & sock) { + void DelSocket(SAMSocket * sock) { std::lock_guard lock(m_SocketsMutex); - m_Sockets.remove(sock); + m_Sockets.remove_if([sock](const std::shared_ptr s) -> bool { return s.get() == sock; }); } /** get a list holding a copy of all sam sockets from this session */ From 6bf823fb15f38d4430a7bb0052e81075d8cc280a Mon Sep 17 00:00:00 2001 From: K1773R Date: Mon, 15 Jan 2018 16:30:01 +0100 Subject: [PATCH 011/119] removed \r\n in header builder which was redundant and caused the further headers to be ignored --- libi2pd_client/AddressBook.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index 7bcd1331..4dfeeb53 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.cpp @@ -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); From 951f8972c78de0850143118eac0926eb5f32144a Mon Sep 17 00:00:00 2001 From: yangfl Date: Thu, 11 Jan 2018 13:48:09 +0800 Subject: [PATCH 012/119] replace non-working CheckLibcxxAtomic --- build/CMakeLists.txt | 10 +- build/cmake_modules/CheckAtomic.cmake | 106 ++++++++++++++++++++ build/cmake_modules/CheckLibcxxAtomic.cmake | 47 --------- 3 files changed, 108 insertions(+), 55 deletions(-) create mode 100644 build/cmake_modules/CheckAtomic.cmake delete mode 100644 build/cmake_modules/CheckLibcxxAtomic.cmake diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 4d462700..bc80423a 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -257,8 +257,6 @@ if(THREADS_HAVE_PTHREAD_ARG) # compile time flag set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") endif() -include(CheckLibcxxAtomic) - if (WITH_STATIC) set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_RUNTIME ON) @@ -384,11 +382,7 @@ if (WITH_MESHNET) message(WARNING "This build will NOT work on mainline i2p") endif() -if (ARCHITECTURE MATCHES "arm") - set(ATOMIC_LIB -latomic) -else() - set(ATMOIC_LIB "") -endif() +include(CheckAtomic) # show summary @@ -457,7 +451,7 @@ if (WITH_BINARY) if (WITH_STATIC) set(DL_LIB ${CMAKE_DL_LIBS}) endif() - target_link_libraries( "${PROJECT_NAME}" libi2pd i2pdclient ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MINGW_EXTRA} ${DL_LIB} ${ATOMIC_LIB}) + target_link_libraries( "${PROJECT_NAME}" libi2pd i2pdclient ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MINGW_EXTRA} ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES}) install(TARGETS "${PROJECT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Runtime) set (APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}") diff --git a/build/cmake_modules/CheckAtomic.cmake b/build/cmake_modules/CheckAtomic.cmake new file mode 100644 index 00000000..b8296a1c --- /dev/null +++ b/build/cmake_modules/CheckAtomic.cmake @@ -0,0 +1,106 @@ +# atomic builtins are required for threading support. + +INCLUDE(CheckCXXSourceCompiles) + +# Sometimes linking against libatomic is required for atomic ops, if +# the platform doesn't support lock-free atomics. + +function(check_working_cxx_atomics varname) + set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + set(CMAKE_REQUIRED_FLAGS "-std=c++11") + CHECK_CXX_SOURCE_COMPILES(" +#include +std::atomic x; +int main() { + return x; +} +" ${varname}) + set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) +endfunction(check_working_cxx_atomics) + +function(check_working_cxx_atomics64 varname) + set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + set(CMAKE_REQUIRED_FLAGS "-std=c++11 ${CMAKE_REQUIRED_FLAGS}") + CHECK_CXX_SOURCE_COMPILES(" +#include +#include +std::atomic x (0); +int main() { + uint64_t i = x.load(std::memory_order_relaxed); + return 0; +} +" ${varname}) + set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) +endfunction(check_working_cxx_atomics64) + + +# This isn't necessary on MSVC, so avoid command-line switch annoyance +# by only running on GCC-like hosts. +if (LLVM_COMPILER_IS_GCC_COMPATIBLE) + # First check if atomics work without the library. + check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB) + # If not, check if the library exists, and atomics work with it. + if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB) + check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC) + if( HAVE_LIBATOMIC ) + list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") + check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB) + if (NOT HAVE_CXX_ATOMICS_WITH_LIB) + message(FATAL_ERROR "Host compiler must support std::atomic!") + endif() + else() + message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.") + endif() + endif() +endif() + +# Check for 64 bit atomic operations. +if(MSVC) + set(HAVE_CXX_ATOMICS64_WITHOUT_LIB True) +else() + check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB) +endif() + +# If not, check if the library exists, and atomics work with it. +if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) + check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64) + if(HAVE_CXX_LIBATOMICS64) + list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") + check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB) + if (NOT HAVE_CXX_ATOMICS64_WITH_LIB) + message(FATAL_ERROR "Host compiler must support std::atomic!") + endif() + else() + message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.") + endif() +endif() + +## TODO: This define is only used for the legacy atomic operations in +## llvm's Atomic.h, which should be replaced. Other code simply +## assumes C++11 works. +CHECK_CXX_SOURCE_COMPILES(" +#ifdef _MSC_VER +#include /* Workaround for PR19898. */ +#include +#endif +int main() { +#ifdef _MSC_VER + volatile LONG val = 1; + MemoryBarrier(); + InterlockedCompareExchange(&val, 0, 1); + InterlockedIncrement(&val); + InterlockedDecrement(&val); +#else + volatile unsigned long val = 1; + __sync_synchronize(); + __sync_val_compare_and_swap(&val, 1, 0); + __sync_add_and_fetch(&val, 1); + __sync_sub_and_fetch(&val, 1); +#endif + return 0; + } +" LLVM_HAS_ATOMICS) + +if( NOT LLVM_HAS_ATOMICS ) + message(STATUS "Warning: LLVM will be built thread-unsafe because atomic builtins are missing") +endif() diff --git a/build/cmake_modules/CheckLibcxxAtomic.cmake b/build/cmake_modules/CheckLibcxxAtomic.cmake deleted file mode 100644 index a7ae667a..00000000 --- a/build/cmake_modules/CheckLibcxxAtomic.cmake +++ /dev/null @@ -1,47 +0,0 @@ -INCLUDE(CheckCXXSourceCompiles) - -# Sometimes linking against libatomic is required for atomic ops, if -# the platform doesn't support lock-free atomics. -# -# We could modify LLVM's CheckAtomic module and have it check for 64-bit -# atomics instead. However, we would like to avoid careless uses of 64-bit -# atomics inside LLVM over time on 32-bit platforms. - -function(check_cxx_atomics varname) - set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) - set(CMAKE_REQUIRED_FLAGS "-nodefaultlibs -std=c++11 -nostdinc++ -isystem ${LIBCXX_SOURCE_DIR}/include") - if (${LIBCXX_GCC_TOOLCHAIN}) - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} --gcc-toolchain=${LIBCXX_GCC_TOOLCHAIN}") - endif() - if (CMAKE_C_FLAGS MATCHES -fsanitize OR CMAKE_CXX_FLAGS MATCHES -fsanitize) - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize=all") - endif() - if (CMAKE_C_FLAGS MATCHES -fsanitize-coverage OR CMAKE_CXX_FLAGS MATCHES -fsanitize-coverage) - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize-coverage=edge,trace-cmp,indirect-calls,8bit-counters") - endif() - check_cxx_source_compiles(" -#include -#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() From bc72800fef9aa42bef305bb6700da167c5ba00fe Mon Sep 17 00:00:00 2001 From: unlnown542a Date: Wed, 17 Jan 2018 20:58:56 +0300 Subject: [PATCH 013/119] moved hard code into java side and successfully passed back to native --- android/jni/i2pd_android.cpp | 29 ++++++++++++------- android/jni/org_purplei2p_i2pd_I2PD_JNI.h | 2 +- .../org/purplei2p/i2pd/DaemonSingleton.java | 11 ++++++- android/src/org/purplei2p/i2pd/I2PD_JNI.java | 2 +- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/android/jni/i2pd_android.cpp b/android/jni/i2pd_android.cpp index ac1e2b70..5a8d8eaf 100755 --- a/android/jni/i2pd_android.cpp +++ b/android/jni/i2pd_android.cpp @@ -44,18 +44,27 @@ JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith } JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon - (JNIEnv * env, jclass clazz) { + (JNIEnv * env, jclass clazz, jobjectArray args) { + int argc = env->GetArrayLength(args); + typedef char *pchar; + pchar* argv = new pchar[argc]; + for (int i = 0; i < argc; i++) { + jstring arg = (jstring) env->GetObjectArrayElement(args, i); + const char *argStr = env->GetStringUTFChars(arg, 0); + size_t len = strlen(argStr); + argv[i] = new char[len + 1]; + strcpy(argv[i], argStr); + env->ReleaseStringUTFChars(arg, argStr); + } - int argc=5; - static char* argv[]={ - strdup("i2pd"), - strdup("--conf=/sdcard/i2pd/i2pd.conf"), - strdup("--tunconf=/sdcard/i2pd/tunnels.conf"), - strdup("--datadir=/data/data/org.purplei2p.i2pd/app_data/"), - strdup("--service"), strdup("--daemon") - }; + const char* result = i2p::android::start(argc,argv).c_str(); + + for (int i = 0; i < argc; i++) { + delete [] argv[i]; + } + delete [] argv; - return env->NewStringUTF(i2p::android::start(argc,argv).c_str()); + return env->NewStringUTF(result); } JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon diff --git a/android/jni/org_purplei2p_i2pd_I2PD_JNI.h b/android/jni/org_purplei2p_i2pd_I2PD_JNI.h index 04923d22..484b3230 100644 --- a/android/jni/org_purplei2p_i2pd_I2PD_JNI.h +++ b/android/jni/org_purplei2p_i2pd_I2PD_JNI.h @@ -16,7 +16,7 @@ JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith (JNIEnv *, jclass); JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon - (JNIEnv *, jclass); + (JNIEnv *, jclass, jobjectArray args); JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon (JNIEnv *, jclass); diff --git a/android/src/org/purplei2p/i2pd/DaemonSingleton.java b/android/src/org/purplei2p/i2pd/DaemonSingleton.java index e1ebc269..e95e0df1 100644 --- a/android/src/org/purplei2p/i2pd/DaemonSingleton.java +++ b/android/src/org/purplei2p/i2pd/DaemonSingleton.java @@ -62,7 +62,16 @@ public class DaemonSingleton { } try { synchronized (DaemonSingleton.this) { - daemonStartResult = I2PD_JNI.startDaemon(); + String args[] = { + "i2pd", + "--conf=/sdcard/i2pd/i2pd.conf", + "--tunconf=/sdcard/i2pd/tunnels.conf", + "--datadir=/data/data/org.purplei2p.i2pd/app_data/", + "--service", + "--daemon" + }; + + daemonStartResult = I2PD_JNI.startDaemon(args); if("ok".equals(daemonStartResult)){ state=State.startedOkay; setStartedOkay(true); diff --git a/android/src/org/purplei2p/i2pd/I2PD_JNI.java b/android/src/org/purplei2p/i2pd/I2PD_JNI.java index 5a3addbf..bfdf8967 100644 --- a/android/src/org/purplei2p/i2pd/I2PD_JNI.java +++ b/android/src/org/purplei2p/i2pd/I2PD_JNI.java @@ -6,7 +6,7 @@ public class I2PD_JNI { * returns error info if failed * returns "ok" if daemon initialized and started okay */ - public static native String startDaemon(); + public static native String startDaemon(String args[]); //should only be called after startDaemon() success public static native void stopDaemon(); From 0bd4db4cc795d968e1f24fa81d95179d3fdf394a Mon Sep 17 00:00:00 2001 From: unlnown542a Date: Thu, 18 Jan 2018 16:41:02 +0300 Subject: [PATCH 014/119] less lines --- android/jni/i2pd_android.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/android/jni/i2pd_android.cpp b/android/jni/i2pd_android.cpp index 5a8d8eaf..19f78a8d 100755 --- a/android/jni/i2pd_android.cpp +++ b/android/jni/i2pd_android.cpp @@ -56,14 +56,11 @@ JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon strcpy(argv[i], argStr); env->ReleaseStringUTFChars(arg, argStr); } - const char* result = i2p::android::start(argc,argv).c_str(); - for (int i = 0; i < argc; i++) { delete [] argv[i]; } delete [] argv; - return env->NewStringUTF(result); } From 4c6988e3bc9ebd1d34e0b5faa50748c75a160c8b Mon Sep 17 00:00:00 2001 From: unlnown542a Date: Thu, 18 Jan 2018 19:35:37 +0300 Subject: [PATCH 015/119] code cleanup --- android/build.gradle | 5 +++++ android/gradle.properties | 2 +- .../src/org/purplei2p/i2pd/DaemonSingleton.java | 17 ++++++++--------- .../org/purplei2p/i2pd/ForegroundService.java | 13 +++++++++++-- android/src/org/purplei2p/i2pd/I2PD.java | 2 +- 5 files changed, 26 insertions(+), 13 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index fcbb47ec..46d0d057 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -46,6 +46,11 @@ android { } } +tasks.withType(JavaCompile) { + options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation' + options.deprecation = true +} + task zipCerts(type:Zip) { from (files('../contrib/')) include 'certificates/**/*.crt' diff --git a/android/gradle.properties b/android/gradle.properties index e32ec00b..d8894a70 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1 +1 @@ -org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +org.gradle.jvmargs=-Xmx2048M -XX:MaxPermSize=256M -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 diff --git a/android/src/org/purplei2p/i2pd/DaemonSingleton.java b/android/src/org/purplei2p/i2pd/DaemonSingleton.java index e95e0df1..031a7ef1 100644 --- a/android/src/org/purplei2p/i2pd/DaemonSingleton.java +++ b/android/src/org/purplei2p/i2pd/DaemonSingleton.java @@ -38,7 +38,7 @@ public class DaemonSingleton { public State getState() { return state; } - public synchronized void start() { + public synchronized void start(final String confDir, final String dataDir) { if(state != State.uninitialized)return; state = State.starting; fireStateUpdate(); @@ -62,14 +62,13 @@ public class DaemonSingleton { } try { synchronized (DaemonSingleton.this) { - String args[] = { - "i2pd", - "--conf=/sdcard/i2pd/i2pd.conf", - "--tunconf=/sdcard/i2pd/tunnels.conf", - "--datadir=/data/data/org.purplei2p.i2pd/app_data/", - "--service", - "--daemon" - }; + + String args[] = new String[] { + "i2pd", "--service", "--daemon", + "--datadir=" + dataDir, + "--conf=" + confDir + "/i2pd.conf", + "--tunconf=" + confDir + "/tunnels.conf" + }; daemonStartResult = I2PD_JNI.startDaemon(args); if("ok".equals(daemonStartResult)){ diff --git a/android/src/org/purplei2p/i2pd/ForegroundService.java b/android/src/org/purplei2p/i2pd/ForegroundService.java index d25d0a88..645d0dca 100644 --- a/android/src/org/purplei2p/i2pd/ForegroundService.java +++ b/android/src/org/purplei2p/i2pd/ForegroundService.java @@ -5,6 +5,8 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; +import android.content.Context; +import android.os.Environment; import android.os.Binder; import android.os.IBinder; import android.util.Log; @@ -28,13 +30,20 @@ public class ForegroundService extends Service { } } + private String dataDir; + private String confDir; + @Override public void onCreate() { notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); + dataDir = this.getDir("data", Context.MODE_PRIVATE).toString(); + confDir = Environment.getExternalStoragePublicDirectory("i2pd").toString(); // Display a notification about us starting. We put an icon in the status bar. showNotification(); - daemon.start(); + + Log.i("ForegroundService", "About to start daemon with dataDir: " + dataDir + ", confDir: " + confDir); + daemon.start(confDir, dataDir); // Tell the user we started. Toast.makeText(this, R.string.i2pd_service_started, Toast.LENGTH_SHORT).show(); } @@ -42,7 +51,7 @@ public class ForegroundService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("ForegroundService", "Received start id " + startId + ": " + intent); - daemon.start(); + daemon.start(confDir, dataDir); return START_STICKY; } diff --git a/android/src/org/purplei2p/i2pd/I2PD.java b/android/src/org/purplei2p/i2pd/I2PD.java index 869cf570..b9d8d037 100755 --- a/android/src/org/purplei2p/i2pd/I2PD.java +++ b/android/src/org/purplei2p/i2pd/I2PD.java @@ -66,7 +66,7 @@ public class I2PD extends Activity { super.onCreate(savedInstanceState); //install certs every time - Decompress.unzipFromAssets(this, "certificates.zip", "/data/data/org.purplei2p.i2pd/app_data/"); + Decompress.unzipFromAssets(this, "certificates.zip", this.getDir("data", Context.MODE_PRIVATE).toString() + "/" ); textView = new TextView(this); setContentView(textView); From b3b38015c28a3b7e052023f116c0ca99c170ab9c Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 20 Jan 2018 07:31:05 -0500 Subject: [PATCH 016/119] check max buffer size in Stream::Send --- libi2pd/Streaming.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 37d9d2c4..9942d8e2 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -378,9 +378,15 @@ namespace stream size_t Stream::Send (const uint8_t * buf, size_t len) { - // TODO: check max buffer size + size_t sent = len; + while(len > MAX_PACKET_SIZE) + { + AsyncSend (buf, MAX_PACKET_SIZE, nullptr); + buf += MAX_PACKET_SIZE; + len -= MAX_PACKET_SIZE; + } AsyncSend (buf, len, nullptr); - return len; + return sent; } void Stream::AsyncSend (const uint8_t * buf, size_t len, SendHandler handler) From b486d1cd27a699fa6e358dc8e11e4bdd7f054313 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 20 Jan 2018 12:07:57 -0500 Subject: [PATCH 017/119] rollback non buildable under x64 --- Makefile.linux | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile.linux b/Makefile.linux index 22d02af3..4a82591a 100644 --- a/Makefile.linux +++ b/Makefile.linux @@ -44,7 +44,7 @@ ifeq ($(USE_STATIC),yes) LDLIBS += -lpthread -static-libstdc++ -static-libgcc -lrt -ldl USE_AESNI := no else - LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread -latomic + LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread endif # UPNP Support (miniupnpc 1.5 and higher) From 06020b8f544ae09734992a47c95597e9998629c2 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 20 Jan 2018 13:06:08 -0500 Subject: [PATCH 018/119] re-enable packet pool --- libi2pd/Streaming.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd/Streaming.h b/libi2pd/Streaming.h index 9410df9d..a114844d 100644 --- a/libi2pd/Streaming.h +++ b/libi2pd/Streaming.h @@ -276,8 +276,8 @@ namespace stream /** set max connections per minute per destination */ void SetMaxConnsPerMinute(const uint32_t conns); - Packet * NewPacket () { return new Packet; } - void DeletePacket (Packet * p) { delete p; } + Packet * NewPacket () { return m_PacketsPool.Acquire(); } + void DeletePacket (Packet * p) { return m_PacketsPool.Release(p); } void AcceptOnceAcceptor (std::shared_ptr stream, Acceptor acceptor, Acceptor prev); @@ -315,7 +315,7 @@ namespace stream std::vector m_Banned; uint64_t m_LastBanClear; - //i2p::util::MemoryPool m_PacketsPool; + i2p::util::MemoryPool m_PacketsPool; bool m_EnableDrop; public: From f537e7b2c698f1902e042c1183a85f5738e75718 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 21 Jan 2018 08:09:01 -0500 Subject: [PATCH 019/119] removed unused cert --- .../reseed/hottuna_at_mail.i2p.crt | 33 ------------------- 1 file changed, 33 deletions(-) delete mode 100644 contrib/certificates/reseed/hottuna_at_mail.i2p.crt 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----- From 914566ece079e25130b51a94d803043d2eba50f5 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 21 Jan 2018 10:27:41 -0500 Subject: [PATCH 020/119] removed unused Java router certificates --- .../router/killyourtv_at_mail.i2p.crt | 32 ------------------- .../certificates/router/str4d_at_mail.i2p.crt | 32 ------------------- .../certificates/router/zzz_at_mail.i2p.crt | 32 ------------------- 3 files changed, 96 deletions(-) delete mode 100644 contrib/certificates/router/killyourtv_at_mail.i2p.crt delete mode 100644 contrib/certificates/router/str4d_at_mail.i2p.crt delete mode 100644 contrib/certificates/router/zzz_at_mail.i2p.crt 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----- From 42d3770b1492331e6840bbf9f2f7fbc0d1cd66c0 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 21 Jan 2018 11:28:16 -0500 Subject: [PATCH 021/119] fixed layout --- README.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 546cea64..4d8bf108 100644 --- a/README.md +++ b/README.md @@ -3,27 +3,27 @@ i2pd [Русская версия](https://github.com/PurpleI2P/i2pd_docs_ru/blob/master/README.md) -i2pd (I2P Daemon) is a full-featured C++ implementation of I2P client. +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 -applications (websites, instant messengers, chat-servers). +applications (websites, instant messengers, chat-servers). I2P allows people from all around the world to communicate and share information -without restrictions. +without restrictions. Features -------- -* Distributed anonymous networking framework -* End-to-end encrypted communications -* Small footprint, simple dependencies, fast performance -* Rich set of APIs for developers of secure applications +* Distributed anonymous networking framework +* End-to-end encrypted communications +* Small footprint, simple dependencies, fast performance +* Rich set of APIs for developers of secure applications Resources --------- @@ -41,7 +41,7 @@ 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 -i2pd from source on your OS. +i2pd from source on your OS. Build instructions: @@ -70,16 +70,16 @@ See [documentation](https://i2pd.readthedocs.io/en/latest/user-guide/run/) and 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 ------- This project is licensed under the BSD 3-clause license, which can be found in the file -LICENSE in the root of the project source code. +LICENSE in the root of the project source code. From 347a2c215001f888f047c3fe26834477dec15567 Mon Sep 17 00:00:00 2001 From: unlnown542a Date: Mon, 22 Jan 2018 01:30:21 +0300 Subject: [PATCH 022/119] fixing conflicts --- android/.gitignore | 6 +- android/build.gradle | 54 ++++++++---- android/jni/DaemonAndroid.cpp | 5 +- android/jni/DaemonAndroid.h | 2 +- android/jni/i2pd_android.cpp | 20 ++++- android/jni/org_purplei2p_i2pd_I2PD_JNI.h | 2 +- .../org/purplei2p/i2pd/DaemonSingleton.java | 39 +++++---- .../src/org/purplei2p/i2pd/Decompress.java | 83 +++++++++++++++++++ .../org/purplei2p/i2pd/ForegroundService.java | 17 +++- android/src/org/purplei2p/i2pd/I2PD.java | 26 ++++-- android/src/org/purplei2p/i2pd/I2PD_JNI.java | 6 +- 11 files changed, 205 insertions(+), 55 deletions(-) create mode 100644 android/src/org/purplei2p/i2pd/Decompress.java diff --git a/android/.gitignore b/android/.gitignore index d9fa5a57..7e166aa6 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -5,4 +5,8 @@ ant.properties local.properties build.sh bin -log* \ No newline at end of file +log* +.gradle* +build +assets +gradle-app.setting diff --git a/android/build.gradle b/android/build.gradle index a88403fd..46d0d057 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -11,23 +11,24 @@ buildscript { apply plugin: 'com.android.application' android { - compileSdkVersion 25 - buildToolsVersion "25.0.2" - defaultConfig { - applicationId "org.purplei2p.i2pd" - targetSdkVersion 25 - minSdkVersion 14 - versionCode 1 - versionName "2.17.1" - } + compileSdkVersion 25 + buildToolsVersion "25.0.0" + defaultConfig { + applicationId "org.purplei2p.i2pd" + targetSdkVersion 25 + minSdkVersion 14 + versionCode 1 + versionName "2.17.2e" + } sourceSets { main { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = ['src'] - res.srcDirs = ['res'] - jniLibs.srcDirs = ['libs'] - } + res.srcDirs = ['res'] + jniLibs.srcDirs = ['libs'] + assets.srcDirs = ['assets'] } + } signingConfigs { orignal { storeFile file("i2pdapk.jks") @@ -37,11 +38,30 @@ android { } } buildTypes { - release { - minifyEnabled false - signingConfig signingConfigs.orignal - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt' - } + release { + minifyEnabled false + signingConfig signingConfigs.orignal + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt' + } } } +tasks.withType(JavaCompile) { + options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation' + options.deprecation = true +} + +task zipCerts(type:Zip) { + from (files('../contrib/')) + include 'certificates/**/*.crt' + destinationDir file('assets') + archiveName 'certificates.zip' + entryCompression ZipEntryCompression.STORED +} +preBuild.dependsOn zipCerts + +task clean(type: Delete,overwrite: true) { + delete 'build' + delete 'assets' +} + diff --git a/android/jni/DaemonAndroid.cpp b/android/jni/DaemonAndroid.cpp index 75584740..9865ac79 100644 --- a/android/jni/DaemonAndroid.cpp +++ b/android/jni/DaemonAndroid.cpp @@ -126,12 +126,11 @@ namespace android } */ static DaemonAndroidImpl daemon; - static char* argv[1]={strdup("tmp")}; /** * returns error details if failed * returns "ok" if daemon initialized and started okay */ - std::string start(/*int argc, char* argv[]*/) + std::string start(int argc, char* argv[]) { try { @@ -139,7 +138,7 @@ namespace android { //Log.d(TAG"Initialising the daemon..."); - bool daemonInitSuccess = daemon.init(1,argv); + bool daemonInitSuccess = daemon.init(argc,argv); if(!daemonInitSuccess) { //QMessageBox::critical(0, "Error", "Daemon init failed"); diff --git a/android/jni/DaemonAndroid.h b/android/jni/DaemonAndroid.h index 9cc8219b..81031936 100644 --- a/android/jni/DaemonAndroid.h +++ b/android/jni/DaemonAndroid.h @@ -37,7 +37,7 @@ namespace android * returns "ok" if daemon init failed * returns errinfo if daemon initialized and started okay */ - std::string start(); + std::string start(int argc, char* argv[]); // stops the daemon void stop(); diff --git a/android/jni/i2pd_android.cpp b/android/jni/i2pd_android.cpp index 8791c90b..1079a252 100755 --- a/android/jni/i2pd_android.cpp +++ b/android/jni/i2pd_android.cpp @@ -44,8 +44,24 @@ JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith } JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon - (JNIEnv * env, jclass clazz) { - return env->NewStringUTF(i2p::android::start().c_str()); + (JNIEnv * env, jclass clazz, jobjectArray args) { + int argc = env->GetArrayLength(args); + typedef char *pchar; + pchar* argv = new pchar[argc]; + for (int i = 0; i < argc; i++) { + jstring arg = (jstring) env->GetObjectArrayElement(args, i); + const char *argStr = env->GetStringUTFChars(arg, 0); + size_t len = strlen(argStr); + argv[i] = new char[len + 1]; + strcpy(argv[i], argStr); + env->ReleaseStringUTFChars(arg, argStr); + } + const char* result = i2p::android::start(argc,argv).c_str(); + for (int i = 0; i < argc; i++) { + delete [] argv[i]; + } + delete [] argv; + return env->NewStringUTF(result); } JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon diff --git a/android/jni/org_purplei2p_i2pd_I2PD_JNI.h b/android/jni/org_purplei2p_i2pd_I2PD_JNI.h index 04923d22..484b3230 100644 --- a/android/jni/org_purplei2p_i2pd_I2PD_JNI.h +++ b/android/jni/org_purplei2p_i2pd_I2PD_JNI.h @@ -16,7 +16,7 @@ JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith (JNIEnv *, jclass); JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon - (JNIEnv *, jclass); + (JNIEnv *, jclass, jobjectArray args); JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon (JNIEnv *, jclass); diff --git a/android/src/org/purplei2p/i2pd/DaemonSingleton.java b/android/src/org/purplei2p/i2pd/DaemonSingleton.java index 65afd0f5..beff0c39 100644 --- a/android/src/org/purplei2p/i2pd/DaemonSingleton.java +++ b/android/src/org/purplei2p/i2pd/DaemonSingleton.java @@ -14,10 +14,10 @@ public class DaemonSingleton { public static DaemonSingleton getInstance() { return instance; } - + public synchronized void addStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.add(listener); } public synchronized void removeStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.remove(listener); } - + public synchronized void stopAcceptingTunnels() { if(isStartedOkay()){ state=State.gracefulShutdownInProgress; @@ -25,20 +25,21 @@ public class DaemonSingleton { I2PD_JNI.stopAcceptingTunnels(); } } - + public void onNetworkStateChange(boolean isConnected) { I2PD_JNI.onNetworkStateChanged(isConnected); } - + private boolean startedOkay; public static enum State {uninitialized,starting,jniLibraryLoaded,startedOkay,startFailed,gracefulShutdownInProgress}; - + private State state = State.uninitialized; - + public State getState() { return state; } + + public synchronized void start(final String confDir, final String dataDir) { - public synchronized void start() { if(state != State.uninitialized)return; state = State.starting; fireStateUpdate(); @@ -62,7 +63,15 @@ public class DaemonSingleton { } try { synchronized (DaemonSingleton.this) { - daemonStartResult = I2PD_JNI.startDaemon(); + + String args[] = new String[] { + "i2pd", "--service", "--daemon", + "--datadir=" + dataDir, + "--conf=" + confDir + "/i2pd.conf", + "--tunconf=" + confDir + "/tunnels.conf" + }; + + daemonStartResult = I2PD_JNI.startDaemon(args); if("ok".equals(daemonStartResult)){ state=State.startedOkay; setStartedOkay(true); @@ -76,9 +85,9 @@ public class DaemonSingleton { fireStateUpdate(); } return; - } + } } - + }, "i2pdDaemonStart").start(); } private Throwable lastThrowable; @@ -87,10 +96,10 @@ public class DaemonSingleton { private synchronized void fireStateUpdate() { Log.i(TAG, "daemon state change: "+state); for(StateUpdateListener listener : stateUpdateListeners) { - try { - listener.daemonStateUpdate(); - } catch (Throwable tr) { - Log.e(TAG, "exception in listener ignored", tr); + try { + listener.daemonStateUpdate(); + } catch (Throwable tr) { + Log.e(TAG, "exception in listener ignored", tr); } } } @@ -102,7 +111,7 @@ public class DaemonSingleton { public String getDaemonStartResult() { return daemonStartResult; } - + private final Object startedOkayLock = new Object(); public boolean isStartedOkay() { diff --git a/android/src/org/purplei2p/i2pd/Decompress.java b/android/src/org/purplei2p/i2pd/Decompress.java new file mode 100644 index 00000000..917abc7c --- /dev/null +++ b/android/src/org/purplei2p/i2pd/Decompress.java @@ -0,0 +1,83 @@ +package org.purplei2p.i2pd; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import android.content.Context; +import android.util.Log; + +public class Decompress { + private static final int BUFFER_SIZE = 1024 * 10; + private static final String TAG = "Decompress"; + + public static void unzipFromAssets(Context context, String zipFile, String destination) { + try { + if (destination == null || destination.length() == 0) + destination = context.getFilesDir().getAbsolutePath(); + InputStream stream = context.getAssets().open(zipFile); + unzip(stream, destination); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static void unzip(String zipFile, String location) { + try { + FileInputStream fin = new FileInputStream(zipFile); + unzip(fin, location); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + + } + + public static void unzip(InputStream stream, String destination) { + dirChecker(destination, ""); + byte[] buffer = new byte[BUFFER_SIZE]; + try { + ZipInputStream zin = new ZipInputStream(stream); + ZipEntry ze = null; + + while ((ze = zin.getNextEntry()) != null) { + Log.v(TAG, "Unzipping " + ze.getName()); + + if (ze.isDirectory()) { + dirChecker(destination, ze.getName()); + } else { + File f = new File(destination + ze.getName()); + if (!f.exists()) { + FileOutputStream fout = new FileOutputStream(destination + ze.getName()); + int count; + while ((count = zin.read(buffer)) != -1) { + fout.write(buffer, 0, count); + } + zin.closeEntry(); + fout.close(); + } + } + + } + zin.close(); + } catch (Exception e) { + Log.e(TAG, "unzip", e); + } + + } + + private static void dirChecker(String destination, String dir) { + File f = new File(destination + dir); + + if (!f.isDirectory()) { + boolean success = f.mkdirs(); + if (!success) { + Log.w(TAG, "Failed to create folder " + f.getName()); + } + } + } +} diff --git a/android/src/org/purplei2p/i2pd/ForegroundService.java b/android/src/org/purplei2p/i2pd/ForegroundService.java index bfd650c8..645d0dca 100644 --- a/android/src/org/purplei2p/i2pd/ForegroundService.java +++ b/android/src/org/purplei2p/i2pd/ForegroundService.java @@ -5,6 +5,8 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; +import android.content.Context; +import android.os.Environment; import android.os.Binder; import android.os.IBinder; import android.util.Log; @@ -28,13 +30,20 @@ public class ForegroundService extends Service { } } + private String dataDir; + private String confDir; + @Override public void onCreate() { notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); + dataDir = this.getDir("data", Context.MODE_PRIVATE).toString(); + confDir = Environment.getExternalStoragePublicDirectory("i2pd").toString(); // Display a notification about us starting. We put an icon in the status bar. showNotification(); - daemon.start(); + + Log.i("ForegroundService", "About to start daemon with dataDir: " + dataDir + ", confDir: " + confDir); + daemon.start(confDir, dataDir); // Tell the user we started. Toast.makeText(this, R.string.i2pd_service_started, Toast.LENGTH_SHORT).show(); } @@ -42,7 +51,7 @@ public class ForegroundService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("ForegroundService", "Received start id " + startId + ": " + intent); - daemon.start(); + daemon.start(confDir, dataDir); return START_STICKY; } @@ -50,7 +59,7 @@ public class ForegroundService extends Service { public void onDestroy() { // Cancel the persistent notification. notificationManager.cancel(NOTIFICATION); - + stopForeground(true); // Tell the user we stopped. @@ -91,7 +100,7 @@ public class ForegroundService extends Service { //mNM.notify(NOTIFICATION, notification); startForeground(NOTIFICATION, notification); } - + private final DaemonSingleton daemon = DaemonSingleton.getInstance(); } diff --git a/android/src/org/purplei2p/i2pd/I2PD.java b/android/src/org/purplei2p/i2pd/I2PD.java index a2494b2b..d66a0174 100755 --- a/android/src/org/purplei2p/i2pd/I2PD.java +++ b/android/src/org/purplei2p/i2pd/I2PD.java @@ -2,6 +2,13 @@ package org.purplei2p.i2pd; import java.io.PrintWriter; import java.io.StringWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + import java.util.Timer; import java.util.TimerTask; @@ -24,12 +31,12 @@ public class I2PD extends Activity { private static final String TAG = "i2pd"; private TextView textView; - + private final DaemonSingleton daemon = DaemonSingleton.getInstance(); private DaemonSingleton.StateUpdateListener daemonStateUpdatedListener = new DaemonSingleton.StateUpdateListener() { - + @Override public void daemonStateUpdate() { runOnUiThread(new Runnable(){ @@ -53,11 +60,14 @@ public class I2PD extends Activity { }); } }; - + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + //install certs every time + Decompress.unzipFromAssets(this, "certificates.zip", this.getDir("data", Context.MODE_PRIVATE).toString() + "/" ); + textView = new TextView(this); setContentView(textView); DaemonSingleton.getInstance().addStateChangeListener(daemonStateUpdatedListener); @@ -123,7 +133,7 @@ public class I2PD extends Activity { } }; - + private boolean mIsBound; private void doBindService() { @@ -147,7 +157,7 @@ public class I2PD extends Activity { @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. - getMenuInflater().inflate(R.menu.options_main, menu); + getMenuInflater().inflate(R.menu.options_main, menu); return true; } @@ -216,9 +226,9 @@ public class I2PD extends Activity { @Override public void run() { - quit(); + quit(); } - + }, 10*60*1000/*milliseconds*/); }else{ quit(); @@ -227,7 +237,7 @@ public class I2PD extends Activity { Log.e(TAG,"",tr); } } - + },"gracQuitInit").start(); } diff --git a/android/src/org/purplei2p/i2pd/I2PD_JNI.java b/android/src/org/purplei2p/i2pd/I2PD_JNI.java index f965d471..bfdf8967 100644 --- a/android/src/org/purplei2p/i2pd/I2PD_JNI.java +++ b/android/src/org/purplei2p/i2pd/I2PD_JNI.java @@ -6,12 +6,12 @@ public class I2PD_JNI { * returns error info if failed * returns "ok" if daemon initialized and started okay */ - public static native String startDaemon(); + public static native String startDaemon(String args[]); //should only be called after startDaemon() success public static native void stopDaemon(); - + public static native void stopAcceptingTunnels(); - + public static native void onNetworkStateChanged(boolean isConnected); public static void loadLibraries() { From 626ed720a6b3483746f1b9321617783d409a821e Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 22 Jan 2018 12:59:34 -0500 Subject: [PATCH 023/119] Revert " Fixes for #1024 , #1018 #1064 " --- android/.gitignore | 6 +- android/build.gradle | 54 ++++-------- android/gradle.properties | 1 - android/jni/DaemonAndroid.cpp | 5 +- android/jni/DaemonAndroid.h | 2 +- android/jni/i2pd_android.cpp | 20 +---- android/jni/org_purplei2p_i2pd_I2PD_JNI.h | 2 +- .../org/purplei2p/i2pd/DaemonSingleton.java | 43 ++++------ .../src/org/purplei2p/i2pd/Decompress.java | 83 ------------------- .../org/purplei2p/i2pd/ForegroundService.java | 17 +--- android/src/org/purplei2p/i2pd/I2PD.java | 26 ++---- android/src/org/purplei2p/i2pd/I2PD_JNI.java | 6 +- 12 files changed, 57 insertions(+), 208 deletions(-) delete mode 100644 android/gradle.properties delete mode 100644 android/src/org/purplei2p/i2pd/Decompress.java diff --git a/android/.gitignore b/android/.gitignore index 7e166aa6..d9fa5a57 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -5,8 +5,4 @@ ant.properties local.properties build.sh bin -log* -.gradle* -build -assets -gradle-app.setting +log* \ No newline at end of file diff --git a/android/build.gradle b/android/build.gradle index 46d0d057..a88403fd 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -11,24 +11,23 @@ buildscript { apply plugin: 'com.android.application' android { - compileSdkVersion 25 - buildToolsVersion "25.0.0" - defaultConfig { - applicationId "org.purplei2p.i2pd" - targetSdkVersion 25 - minSdkVersion 14 - versionCode 1 - versionName "2.17.2e" - } + compileSdkVersion 25 + buildToolsVersion "25.0.2" + defaultConfig { + applicationId "org.purplei2p.i2pd" + targetSdkVersion 25 + minSdkVersion 14 + versionCode 1 + versionName "2.17.1" + } sourceSets { main { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = ['src'] - res.srcDirs = ['res'] - jniLibs.srcDirs = ['libs'] - assets.srcDirs = ['assets'] + res.srcDirs = ['res'] + jniLibs.srcDirs = ['libs'] + } } - } signingConfigs { orignal { storeFile file("i2pdapk.jks") @@ -38,30 +37,11 @@ android { } } buildTypes { - release { - minifyEnabled false - signingConfig signingConfigs.orignal - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt' - } + release { + minifyEnabled false + signingConfig signingConfigs.orignal + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt' + } } } -tasks.withType(JavaCompile) { - options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation' - options.deprecation = true -} - -task zipCerts(type:Zip) { - from (files('../contrib/')) - include 'certificates/**/*.crt' - destinationDir file('assets') - archiveName 'certificates.zip' - entryCompression ZipEntryCompression.STORED -} -preBuild.dependsOn zipCerts - -task clean(type: Delete,overwrite: true) { - delete 'build' - delete 'assets' -} - diff --git a/android/gradle.properties b/android/gradle.properties deleted file mode 100644 index d8894a70..00000000 --- a/android/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -org.gradle.jvmargs=-Xmx2048M -XX:MaxPermSize=256M -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 diff --git a/android/jni/DaemonAndroid.cpp b/android/jni/DaemonAndroid.cpp index 9865ac79..75584740 100644 --- a/android/jni/DaemonAndroid.cpp +++ b/android/jni/DaemonAndroid.cpp @@ -126,11 +126,12 @@ namespace android } */ static DaemonAndroidImpl daemon; + static char* argv[1]={strdup("tmp")}; /** * returns error details if failed * returns "ok" if daemon initialized and started okay */ - std::string start(int argc, char* argv[]) + std::string start(/*int argc, char* argv[]*/) { try { @@ -138,7 +139,7 @@ namespace android { //Log.d(TAG"Initialising the daemon..."); - bool daemonInitSuccess = daemon.init(argc,argv); + bool daemonInitSuccess = daemon.init(1,argv); if(!daemonInitSuccess) { //QMessageBox::critical(0, "Error", "Daemon init failed"); diff --git a/android/jni/DaemonAndroid.h b/android/jni/DaemonAndroid.h index 81031936..9cc8219b 100644 --- a/android/jni/DaemonAndroid.h +++ b/android/jni/DaemonAndroid.h @@ -37,7 +37,7 @@ namespace android * returns "ok" if daemon init failed * returns errinfo if daemon initialized and started okay */ - std::string start(int argc, char* argv[]); + std::string start(); // stops the daemon void stop(); diff --git a/android/jni/i2pd_android.cpp b/android/jni/i2pd_android.cpp index 1079a252..8791c90b 100755 --- a/android/jni/i2pd_android.cpp +++ b/android/jni/i2pd_android.cpp @@ -44,24 +44,8 @@ JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith } JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon - (JNIEnv * env, jclass clazz, jobjectArray args) { - int argc = env->GetArrayLength(args); - typedef char *pchar; - pchar* argv = new pchar[argc]; - for (int i = 0; i < argc; i++) { - jstring arg = (jstring) env->GetObjectArrayElement(args, i); - const char *argStr = env->GetStringUTFChars(arg, 0); - size_t len = strlen(argStr); - argv[i] = new char[len + 1]; - strcpy(argv[i], argStr); - env->ReleaseStringUTFChars(arg, argStr); - } - const char* result = i2p::android::start(argc,argv).c_str(); - for (int i = 0; i < argc; i++) { - delete [] argv[i]; - } - delete [] argv; - return env->NewStringUTF(result); + (JNIEnv * env, jclass clazz) { + return env->NewStringUTF(i2p::android::start().c_str()); } JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon diff --git a/android/jni/org_purplei2p_i2pd_I2PD_JNI.h b/android/jni/org_purplei2p_i2pd_I2PD_JNI.h index 484b3230..04923d22 100644 --- a/android/jni/org_purplei2p_i2pd_I2PD_JNI.h +++ b/android/jni/org_purplei2p_i2pd_I2PD_JNI.h @@ -16,7 +16,7 @@ JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_getABICompiledWith (JNIEnv *, jclass); JNIEXPORT jstring JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_startDaemon - (JNIEnv *, jclass, jobjectArray args); + (JNIEnv *, jclass); JNIEXPORT void JNICALL Java_org_purplei2p_i2pd_I2PD_1JNI_stopDaemon (JNIEnv *, jclass); diff --git a/android/src/org/purplei2p/i2pd/DaemonSingleton.java b/android/src/org/purplei2p/i2pd/DaemonSingleton.java index beff0c39..65afd0f5 100644 --- a/android/src/org/purplei2p/i2pd/DaemonSingleton.java +++ b/android/src/org/purplei2p/i2pd/DaemonSingleton.java @@ -14,10 +14,10 @@ public class DaemonSingleton { public static DaemonSingleton getInstance() { return instance; } - + public synchronized void addStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.add(listener); } public synchronized void removeStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.remove(listener); } - + public synchronized void stopAcceptingTunnels() { if(isStartedOkay()){ state=State.gracefulShutdownInProgress; @@ -25,21 +25,20 @@ public class DaemonSingleton { I2PD_JNI.stopAcceptingTunnels(); } } - + public void onNetworkStateChange(boolean isConnected) { I2PD_JNI.onNetworkStateChanged(isConnected); } - + private boolean startedOkay; public static enum State {uninitialized,starting,jniLibraryLoaded,startedOkay,startFailed,gracefulShutdownInProgress}; - - private State state = State.uninitialized; - - public State getState() { return state; } - - public synchronized void start(final String confDir, final String dataDir) { + private State state = State.uninitialized; + + public State getState() { return state; } + + public synchronized void start() { if(state != State.uninitialized)return; state = State.starting; fireStateUpdate(); @@ -63,15 +62,7 @@ public class DaemonSingleton { } try { synchronized (DaemonSingleton.this) { - - String args[] = new String[] { - "i2pd", "--service", "--daemon", - "--datadir=" + dataDir, - "--conf=" + confDir + "/i2pd.conf", - "--tunconf=" + confDir + "/tunnels.conf" - }; - - daemonStartResult = I2PD_JNI.startDaemon(args); + daemonStartResult = I2PD_JNI.startDaemon(); if("ok".equals(daemonStartResult)){ state=State.startedOkay; setStartedOkay(true); @@ -85,9 +76,9 @@ public class DaemonSingleton { fireStateUpdate(); } return; - } + } } - + }, "i2pdDaemonStart").start(); } private Throwable lastThrowable; @@ -96,10 +87,10 @@ public class DaemonSingleton { private synchronized void fireStateUpdate() { Log.i(TAG, "daemon state change: "+state); for(StateUpdateListener listener : stateUpdateListeners) { - try { - listener.daemonStateUpdate(); - } catch (Throwable tr) { - Log.e(TAG, "exception in listener ignored", tr); + try { + listener.daemonStateUpdate(); + } catch (Throwable tr) { + Log.e(TAG, "exception in listener ignored", tr); } } } @@ -111,7 +102,7 @@ public class DaemonSingleton { public String getDaemonStartResult() { return daemonStartResult; } - + private final Object startedOkayLock = new Object(); public boolean isStartedOkay() { diff --git a/android/src/org/purplei2p/i2pd/Decompress.java b/android/src/org/purplei2p/i2pd/Decompress.java deleted file mode 100644 index 917abc7c..00000000 --- a/android/src/org/purplei2p/i2pd/Decompress.java +++ /dev/null @@ -1,83 +0,0 @@ -package org.purplei2p.i2pd; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -import android.content.Context; -import android.util.Log; - -public class Decompress { - private static final int BUFFER_SIZE = 1024 * 10; - private static final String TAG = "Decompress"; - - public static void unzipFromAssets(Context context, String zipFile, String destination) { - try { - if (destination == null || destination.length() == 0) - destination = context.getFilesDir().getAbsolutePath(); - InputStream stream = context.getAssets().open(zipFile); - unzip(stream, destination); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public static void unzip(String zipFile, String location) { - try { - FileInputStream fin = new FileInputStream(zipFile); - unzip(fin, location); - } catch (FileNotFoundException e) { - e.printStackTrace(); - } - - } - - public static void unzip(InputStream stream, String destination) { - dirChecker(destination, ""); - byte[] buffer = new byte[BUFFER_SIZE]; - try { - ZipInputStream zin = new ZipInputStream(stream); - ZipEntry ze = null; - - while ((ze = zin.getNextEntry()) != null) { - Log.v(TAG, "Unzipping " + ze.getName()); - - if (ze.isDirectory()) { - dirChecker(destination, ze.getName()); - } else { - File f = new File(destination + ze.getName()); - if (!f.exists()) { - FileOutputStream fout = new FileOutputStream(destination + ze.getName()); - int count; - while ((count = zin.read(buffer)) != -1) { - fout.write(buffer, 0, count); - } - zin.closeEntry(); - fout.close(); - } - } - - } - zin.close(); - } catch (Exception e) { - Log.e(TAG, "unzip", e); - } - - } - - private static void dirChecker(String destination, String dir) { - File f = new File(destination + dir); - - if (!f.isDirectory()) { - boolean success = f.mkdirs(); - if (!success) { - Log.w(TAG, "Failed to create folder " + f.getName()); - } - } - } -} diff --git a/android/src/org/purplei2p/i2pd/ForegroundService.java b/android/src/org/purplei2p/i2pd/ForegroundService.java index 645d0dca..bfd650c8 100644 --- a/android/src/org/purplei2p/i2pd/ForegroundService.java +++ b/android/src/org/purplei2p/i2pd/ForegroundService.java @@ -5,8 +5,6 @@ import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; import android.content.Intent; -import android.content.Context; -import android.os.Environment; import android.os.Binder; import android.os.IBinder; import android.util.Log; @@ -30,20 +28,13 @@ public class ForegroundService extends Service { } } - private String dataDir; - private String confDir; - @Override public void onCreate() { notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); - dataDir = this.getDir("data", Context.MODE_PRIVATE).toString(); - confDir = Environment.getExternalStoragePublicDirectory("i2pd").toString(); // Display a notification about us starting. We put an icon in the status bar. showNotification(); - - Log.i("ForegroundService", "About to start daemon with dataDir: " + dataDir + ", confDir: " + confDir); - daemon.start(confDir, dataDir); + daemon.start(); // Tell the user we started. Toast.makeText(this, R.string.i2pd_service_started, Toast.LENGTH_SHORT).show(); } @@ -51,7 +42,7 @@ public class ForegroundService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("ForegroundService", "Received start id " + startId + ": " + intent); - daemon.start(confDir, dataDir); + daemon.start(); return START_STICKY; } @@ -59,7 +50,7 @@ public class ForegroundService extends Service { public void onDestroy() { // Cancel the persistent notification. notificationManager.cancel(NOTIFICATION); - + stopForeground(true); // Tell the user we stopped. @@ -100,7 +91,7 @@ public class ForegroundService extends Service { //mNM.notify(NOTIFICATION, notification); startForeground(NOTIFICATION, notification); } - + private final DaemonSingleton daemon = DaemonSingleton.getInstance(); } diff --git a/android/src/org/purplei2p/i2pd/I2PD.java b/android/src/org/purplei2p/i2pd/I2PD.java index d66a0174..a2494b2b 100755 --- a/android/src/org/purplei2p/i2pd/I2PD.java +++ b/android/src/org/purplei2p/i2pd/I2PD.java @@ -2,13 +2,6 @@ package org.purplei2p.i2pd; import java.io.PrintWriter; import java.io.StringWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; - import java.util.Timer; import java.util.TimerTask; @@ -31,12 +24,12 @@ public class I2PD extends Activity { private static final String TAG = "i2pd"; private TextView textView; - + private final DaemonSingleton daemon = DaemonSingleton.getInstance(); private DaemonSingleton.StateUpdateListener daemonStateUpdatedListener = new DaemonSingleton.StateUpdateListener() { - + @Override public void daemonStateUpdate() { runOnUiThread(new Runnable(){ @@ -60,14 +53,11 @@ public class I2PD extends Activity { }); } }; - + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - //install certs every time - Decompress.unzipFromAssets(this, "certificates.zip", this.getDir("data", Context.MODE_PRIVATE).toString() + "/" ); - textView = new TextView(this); setContentView(textView); DaemonSingleton.getInstance().addStateChangeListener(daemonStateUpdatedListener); @@ -133,7 +123,7 @@ public class I2PD extends Activity { } }; - + private boolean mIsBound; private void doBindService() { @@ -157,7 +147,7 @@ public class I2PD extends Activity { @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. - getMenuInflater().inflate(R.menu.options_main, menu); + getMenuInflater().inflate(R.menu.options_main, menu); return true; } @@ -226,9 +216,9 @@ public class I2PD extends Activity { @Override public void run() { - quit(); + quit(); } - + }, 10*60*1000/*milliseconds*/); }else{ quit(); @@ -237,7 +227,7 @@ public class I2PD extends Activity { Log.e(TAG,"",tr); } } - + },"gracQuitInit").start(); } diff --git a/android/src/org/purplei2p/i2pd/I2PD_JNI.java b/android/src/org/purplei2p/i2pd/I2PD_JNI.java index bfdf8967..f965d471 100644 --- a/android/src/org/purplei2p/i2pd/I2PD_JNI.java +++ b/android/src/org/purplei2p/i2pd/I2PD_JNI.java @@ -6,12 +6,12 @@ public class I2PD_JNI { * returns error info if failed * returns "ok" if daemon initialized and started okay */ - public static native String startDaemon(String args[]); + public static native String startDaemon(); //should only be called after startDaemon() success public static native void stopDaemon(); - + public static native void stopAcceptingTunnels(); - + public static native void onNetworkStateChanged(boolean isConnected); public static void loadLibraries() { From 4ee364640d85eb2966217e526ff12ee674d27e82 Mon Sep 17 00:00:00 2001 From: Darknet Villain Date: Mon, 22 Jan 2018 13:55:12 -0500 Subject: [PATCH 024/119] Update rpm spec and systemd unit --- contrib/rpm/i2pd.service | 23 +++++++++++++++++------ contrib/rpm/i2pd.spec | 18 ++++++++++++++---- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/contrib/rpm/i2pd.service b/contrib/rpm/i2pd.service index b14af025..89562ff5 100644 --- a/contrib/rpm/i2pd.service +++ b/contrib/rpm/i2pd.service @@ -1,16 +1,27 @@ [Unit] -Description=I2P router +Description=I2P Router written in C++ After=network.target [Service] User=i2pd Group=i2pd +RuntimeDirectory=i2pd +RuntimeDirectoryMode=0700 Type=simple -ExecStart=/usr/bin/i2pd --service -PIDFile=/var/lib/i2pd/i2pd.pid -Restart=always -PrivateTmp=true +ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service +ExecReload=/bin/kill -HUP $MAINPID +PIDFile=/var/run/i2pd/i2pd.pid +### Uncomment, if auto restart needed +#Restart=on-failure + +### Use SIGINT for graceful stop daemon. +# i2pd stops accepting new tunnels and waits ~10 min while old ones do not die. +KillSignal=SIGINT +TimeoutStopSec=10m + +# If you have problems with hunging i2pd, you can try enable this +#LimitNOFILE=4096 +PrivateDevices=yes [Install] WantedBy=multi-user.target - diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 0b6fa463..f0f7a9a7 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -68,9 +68,15 @@ make %{?_smp_mflags} %install cd build chrpath -d i2pd -install -D -m 755 i2pd %{buildroot}%{_bindir}/i2pd +install -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd +install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf +install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf +install -d -m 755 %{buildroot}/%{_datadir}/i2pd +%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates install -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}/%{_unitdir}/i2pd.service install -d -m 700 %{buildroot}/%{_sharedstatedir}/i2pd +install -d -m 700 %{buildroot}/%{_localstatedir}/log/i2pd +ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/%{name}/certificates %pre systemd @@ -94,12 +100,16 @@ getent passwd i2pd >/dev/null || \ %files %doc LICENSE README.md -%_bindir/i2pd +%{_sbindir}/i2pd +%{_datadir}/i2pd/certificates +%config(noreplace) %{_sysconfdir}/i2pd/* %files systemd -/%_unitdir/i2pd.service -%dir %attr(0700,i2pd,i2pd) %_sharedstatedir/i2pd +/%{_unitdir}/i2pd.service +%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd +%dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd +%{_sharedstatedir}/i2pd/certificates %changelog From c730839989d3d00d70c649226ecf92530985fba0 Mon Sep 17 00:00:00 2001 From: Veggie Monster Date: Mon, 22 Jan 2018 20:47:31 -0500 Subject: [PATCH 025/119] the change allows when an TCPIPAcceptor is constructed by setting port = 0, the random port chosen by asio can be retrieved using TCPIPAcceptor::GetLocalEndpoint().port() --- libi2pd_client/I2PService.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libi2pd_client/I2PService.cpp b/libi2pd_client/I2PService.cpp index 6fd5d763..21e1fdfa 100644 --- a/libi2pd_client/I2PService.cpp +++ b/libi2pd_client/I2PService.cpp @@ -280,6 +280,8 @@ namespace client void TCPIPAcceptor::Start () { m_Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService (), m_LocalEndpoint)); + //update the local end point in case port has been set zero and got updated now + m_LocalEndpoint = m_Acceptor->local_endpoint(); m_Acceptor->listen (); Accept (); } From c7db9010ad36cbe11d503de186a23bf746b3e3af Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 23 Jan 2018 11:01:50 -0500 Subject: [PATCH 026/119] fixed #1047. Return EXIT_FAILURE --- daemon/i2pd.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/daemon/i2pd.cpp b/daemon/i2pd.cpp index 589274f5..8718ad0c 100644 --- a/daemon/i2pd.cpp +++ b/daemon/i2pd.cpp @@ -22,6 +22,8 @@ int main( int argc, char* argv[] ) { if (Daemon.start()) Daemon.run (); + else + return EXIT_FAILURE; Daemon.stop(); } return EXIT_SUCCESS; From 85fa728d41b8449bad0d6f288cd5693a60bc1917 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 23 Jan 2018 14:40:05 -0500 Subject: [PATCH 027/119] change shared local destination upon reload --- libi2pd_client/ClientContext.cpp | 20 +++++++++++++------- libi2pd_client/ClientContext.h | 2 ++ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 41b8615a..d8aa10d8 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -36,13 +36,7 @@ namespace client void ClientContext::Start () { if (!m_SharedLocalDestination) - { - m_SharedLocalDestination = CreateNewLocalDestination (); // non-public, DSA - m_SharedLocalDestination->Acquire (); - m_Destinations[m_SharedLocalDestination->GetIdentity ()->GetIdentHash ()] = m_SharedLocalDestination; - m_SharedLocalDestination->Start (); - } - + CreateNewSharedLocalDestination (); m_AddressBook.Start (); @@ -267,6 +261,10 @@ namespace client // delete not updated tunnels (not in config anymore) VisitTunnels ([](I2PService * s)->bool { return s->isUpdated; }); + // change shared local destination + m_SharedLocalDestination->Release (); + CreateNewSharedLocalDestination (); + // delete unused destinations std::unique_lock l(m_DestinationsMutex); for (auto it = m_Destinations.begin (); it != m_Destinations.end ();) @@ -407,6 +405,14 @@ namespace client return localDestination; } + void ClientContext::CreateNewSharedLocalDestination () + { + m_SharedLocalDestination = CreateNewLocalDestination (); // non-public, DSA + m_SharedLocalDestination->Acquire (); + m_Destinations[m_SharedLocalDestination->GetIdentity ()->GetIdentHash ()] = m_SharedLocalDestination; + m_SharedLocalDestination->Start (); + } + std::shared_ptr ClientContext::FindLocalDestination (const i2p::data::IdentHash& destination) const { auto it = m_Destinations.find (destination); diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index 8f7143bb..2d5d140f 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -99,6 +99,8 @@ namespace client template void VisitTunnels (Visitor v); // Visitor: (I2PService *) -> bool, true means retain + void CreateNewSharedLocalDestination (); + private: std::mutex m_DestinationsMutex; From 162bd592f8d4816e51d5a9700f588d27c07d778f Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 23 Jan 2018 15:13:43 -0500 Subject: [PATCH 028/119] recreate http and socks proxy upon reload --- libi2pd_client/ClientContext.cpp | 168 ++++++++++++++++++------------- libi2pd_client/ClientContext.h | 2 + 2 files changed, 101 insertions(+), 69 deletions(-) diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index d8aa10d8..fb8fff97 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -35,81 +35,18 @@ namespace client void ClientContext::Start () { + // shared local destination if (!m_SharedLocalDestination) CreateNewSharedLocalDestination (); + // addressbook m_AddressBook.Start (); - std::shared_ptr localDestination; - bool httproxy; i2p::config::GetOption("httpproxy.enabled", httproxy); - if (httproxy) - { - std::string httpProxyKeys; i2p::config::GetOption("httpproxy.keys", httpProxyKeys); - std::string httpProxyAddr; i2p::config::GetOption("httpproxy.address", httpProxyAddr); - uint16_t httpProxyPort; i2p::config::GetOption("httpproxy.port", httpProxyPort); - i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType); - std::string httpOutProxyURL; i2p::config::GetOption("httpproxy.outproxy", httpOutProxyURL); - LogPrint(eLogInfo, "Clients: starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort); - if (httpProxyKeys.length () > 0) - { - i2p::data::PrivateKeys keys; - if(LoadPrivateKeys (keys, httpProxyKeys, sigType)) - { - std::map params; - ReadI2CPOptionsFromConfig ("httpproxy.", params); - localDestination = CreateNewLocalDestination (keys, false, ¶ms); - localDestination->Acquire (); - } - else - LogPrint(eLogError, "Clients: failed to load HTTP Proxy key"); - } - try - { - m_HttpProxy = new i2p::proxy::HTTPProxy("HTTP Proxy", httpProxyAddr, httpProxyPort, httpOutProxyURL, localDestination); - m_HttpProxy->Start(); - } - catch (std::exception& e) - { - LogPrint(eLogError, "Clients: Exception in HTTP Proxy: ", e.what()); - } - } + // HTTP proxy + ReadHttpProxy (); - localDestination = nullptr; - bool socksproxy; i2p::config::GetOption("socksproxy.enabled", socksproxy); - if (socksproxy) - { - std::string socksProxyKeys; i2p::config::GetOption("socksproxy.keys", socksProxyKeys); - std::string socksProxyAddr; i2p::config::GetOption("socksproxy.address", socksProxyAddr); - uint16_t socksProxyPort; i2p::config::GetOption("socksproxy.port", socksProxyPort); - bool socksOutProxy; i2p::config::GetOption("socksproxy.outproxy.enabled", socksOutProxy); - std::string socksOutProxyAddr; i2p::config::GetOption("socksproxy.outproxy", socksOutProxyAddr); - uint16_t socksOutProxyPort; i2p::config::GetOption("socksproxy.outproxyport", socksOutProxyPort); - i2p::data::SigningKeyType sigType; i2p::config::GetOption("socksproxy.signaturetype", sigType); - LogPrint(eLogInfo, "Clients: starting SOCKS Proxy at ", socksProxyAddr, ":", socksProxyPort); - if (socksProxyKeys.length () > 0) - { - i2p::data::PrivateKeys keys; - if (LoadPrivateKeys (keys, socksProxyKeys, sigType)) - { - std::map params; - ReadI2CPOptionsFromConfig ("socksproxy.", params); - localDestination = CreateNewLocalDestination (keys, false, ¶ms); - localDestination->Acquire (); - } - else - LogPrint(eLogError, "Clients: failed to load SOCKS Proxy key"); - } - try - { - m_SocksProxy = new i2p::proxy::SOCKSProxy("SOCKS", socksProxyAddr, socksProxyPort, - socksOutProxy, socksOutProxyAddr, socksOutProxyPort, localDestination); - m_SocksProxy->Start(); - } - catch (std::exception& e) - { - LogPrint(eLogError, "Clients: Exception in SOCKS Proxy: ", e.what()); - } - } + // SOCKS proxy + ReadSocksProxy (); // I2P tunnels ReadTunnels (); @@ -265,6 +202,22 @@ namespace client m_SharedLocalDestination->Release (); CreateNewSharedLocalDestination (); + // recreate HTTP proxy + if (m_HttpProxy) + { + m_HttpProxy->Stop (); + m_HttpProxy = nullptr; + } + ReadHttpProxy (); + + // recreate SOCKS proxy + if (m_SocksProxy) + { + m_SocksProxy->Stop (); + m_SocksProxy = nullptr; + } + ReadSocksProxy (); + // delete unused destinations std::unique_lock l(m_DestinationsMutex); for (auto it = m_Destinations.begin (); it != m_Destinations.end ();) @@ -722,6 +675,83 @@ namespace client LogPrint (eLogInfo, "Clients: ", numServerTunnels, " I2P server tunnels created"); } + void ClientContext::ReadHttpProxy () + { + std::shared_ptr localDestination; + bool httproxy; i2p::config::GetOption("httpproxy.enabled", httproxy); + if (httproxy) + { + std::string httpProxyKeys; i2p::config::GetOption("httpproxy.keys", httpProxyKeys); + std::string httpProxyAddr; i2p::config::GetOption("httpproxy.address", httpProxyAddr); + uint16_t httpProxyPort; i2p::config::GetOption("httpproxy.port", httpProxyPort); + i2p::data::SigningKeyType sigType; i2p::config::GetOption("httpproxy.signaturetype", sigType); + std::string httpOutProxyURL; i2p::config::GetOption("httpproxy.outproxy", httpOutProxyURL); + LogPrint(eLogInfo, "Clients: starting HTTP Proxy at ", httpProxyAddr, ":", httpProxyPort); + if (httpProxyKeys.length () > 0) + { + i2p::data::PrivateKeys keys; + if(LoadPrivateKeys (keys, httpProxyKeys, sigType)) + { + std::map params; + ReadI2CPOptionsFromConfig ("httpproxy.", params); + localDestination = CreateNewLocalDestination (keys, false, ¶ms); + localDestination->Acquire (); + } + else + LogPrint(eLogError, "Clients: failed to load HTTP Proxy key"); + } + try + { + m_HttpProxy = new i2p::proxy::HTTPProxy("HTTP Proxy", httpProxyAddr, httpProxyPort, httpOutProxyURL, localDestination); + m_HttpProxy->Start(); + } + catch (std::exception& e) + { + LogPrint(eLogError, "Clients: Exception in HTTP Proxy: ", e.what()); + } + } + } + + void ClientContext::ReadSocksProxy () + { + std::shared_ptr localDestination; + bool socksproxy; i2p::config::GetOption("socksproxy.enabled", socksproxy); + if (socksproxy) + { + std::string socksProxyKeys; i2p::config::GetOption("socksproxy.keys", socksProxyKeys); + std::string socksProxyAddr; i2p::config::GetOption("socksproxy.address", socksProxyAddr); + uint16_t socksProxyPort; i2p::config::GetOption("socksproxy.port", socksProxyPort); + bool socksOutProxy; i2p::config::GetOption("socksproxy.outproxy.enabled", socksOutProxy); + std::string socksOutProxyAddr; i2p::config::GetOption("socksproxy.outproxy", socksOutProxyAddr); + uint16_t socksOutProxyPort; i2p::config::GetOption("socksproxy.outproxyport", socksOutProxyPort); + i2p::data::SigningKeyType sigType; i2p::config::GetOption("socksproxy.signaturetype", sigType); + LogPrint(eLogInfo, "Clients: starting SOCKS Proxy at ", socksProxyAddr, ":", socksProxyPort); + if (socksProxyKeys.length () > 0) + { + i2p::data::PrivateKeys keys; + if (LoadPrivateKeys (keys, socksProxyKeys, sigType)) + { + std::map params; + ReadI2CPOptionsFromConfig ("socksproxy.", params); + localDestination = CreateNewLocalDestination (keys, false, ¶ms); + localDestination->Acquire (); + } + else + LogPrint(eLogError, "Clients: failed to load SOCKS Proxy key"); + } + try + { + m_SocksProxy = new i2p::proxy::SOCKSProxy("SOCKS", socksProxyAddr, socksProxyPort, + socksOutProxy, socksOutProxyAddr, socksOutProxyPort, localDestination); + m_SocksProxy->Start(); + } + catch (std::exception& e) + { + LogPrint(eLogError, "Clients: Exception in SOCKS Proxy: ", e.what()); + } + } + } + void ClientContext::ScheduleCleanupUDP() { if (m_CleanupUDPTimer) diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index 2d5d140f..922d7acc 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -87,6 +87,8 @@ namespace client private: void ReadTunnels (); + void ReadHttpProxy (); + void ReadSocksProxy (); template std::string GetI2CPOption (const Section& section, const std::string& name, const Type& value) const; template From ddd25f09459e34b77898206aa09ad88320141c24 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 23 Jan 2018 15:50:28 -0500 Subject: [PATCH 029/119] limit number of retries for subscriptions --- libi2pd_client/AddressBook.cpp | 8 ++++++-- libi2pd_client/AddressBook.h | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index 4dfeeb53..4b563ac0 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.cpp @@ -207,7 +207,7 @@ namespace client //--------------------------------------------------------------------- AddressBook::AddressBook (): m_Storage(nullptr), m_IsLoaded (false), m_IsDownloading (false), - m_DefaultSubscription (nullptr), m_SubscriptionsUpdateTimer (nullptr) + m_NumRetries (0), m_DefaultSubscription (nullptr), m_SubscriptionsUpdateTimer (nullptr) { } @@ -486,9 +486,13 @@ namespace client void AddressBook::DownloadComplete (bool success, const i2p::data::IdentHash& subscription, const std::string& etag, const std::string& lastModified) { m_IsDownloading = false; - int nextUpdateTimeout = CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT; + m_NumRetries++; + int nextUpdateTimeout = m_NumRetries*CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT; + if (m_NumRetries > CONTINIOUS_SUBSCRIPTION_MAX_NUM_RETRIES || nextUpdateTimeout > CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT) + nextUpdateTimeout = CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT; if (success) { + m_NumRetries = 0; if (m_DefaultSubscription) m_DefaultSubscription = nullptr; if (m_IsLoaded) nextUpdateTimeout = CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT; diff --git a/libi2pd_client/AddressBook.h b/libi2pd_client/AddressBook.h index 3feb2ece..2d4475cb 100644 --- a/libi2pd_client/AddressBook.h +++ b/libi2pd_client/AddressBook.h @@ -22,6 +22,7 @@ namespace client 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 CONTINIOUS_SUBSCRIPTION_MAX_NUM_RETRIES = 10; // then update timeout const int SUBSCRIPTION_REQUEST_TIMEOUT = 60; //in second const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53; @@ -97,6 +98,7 @@ namespace client std::map m_Lookups; // nonce -> address AddressBookStorage * m_Storage; volatile bool m_IsLoaded, m_IsDownloading; + int m_NumRetries; std::vector > m_Subscriptions; std::shared_ptr m_DefaultSubscription; // in case if we don't know any addresses yet boost::asio::deadline_timer * m_SubscriptionsUpdateTimer; From 0bb0adbf3eb3fa58fa2b1e9d7713e9c4a1d0fd29 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Wed, 24 Jan 2018 15:34:32 +0300 Subject: [PATCH 030/119] fix addressbook fetch timeout --- libi2pd_client/AddressBook.cpp | 4 ++-- libi2pd_client/AddressBook.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libi2pd_client/AddressBook.cpp b/libi2pd_client/AddressBook.cpp index 4b563ac0..f29ecee3 100644 --- a/libi2pd_client/AddressBook.cpp +++ b/libi2pd_client/AddressBook.cpp @@ -696,7 +696,7 @@ namespace client std::unique_lock l(newDataReceivedMutex); i2p::client::context.GetSharedLocalDestination ()->RequestDestination (m_Ident, [&newDataReceived, &leaseSet, &newDataReceivedMutex](std::shared_ptr ls) - { + { leaseSet = ls; std::unique_lock l1(newDataReceivedMutex); newDataReceived.notify_all (); @@ -753,7 +753,7 @@ namespace client end = true; newDataReceived.notify_all (); }, - 30); // wait for 30 seconds + SUBSCRIPTION_REQUEST_TIMEOUT); std::unique_lock l(newDataReceivedMutex); if (newDataReceived.wait_for (l, std::chrono::seconds (SUBSCRIPTION_REQUEST_TIMEOUT)) == std::cv_status::timeout) { diff --git a/libi2pd_client/AddressBook.h b/libi2pd_client/AddressBook.h index 2d4475cb..19257eca 100644 --- a/libi2pd_client/AddressBook.h +++ b/libi2pd_client/AddressBook.h @@ -23,7 +23,7 @@ namespace client const int CONTINIOUS_SUBSCRIPTION_UPDATE_TIMEOUT = 720; // in minutes (12 hours) const int CONTINIOUS_SUBSCRIPTION_RETRY_TIMEOUT = 5; // in minutes const int CONTINIOUS_SUBSCRIPTION_MAX_NUM_RETRIES = 10; // then update timeout - const int SUBSCRIPTION_REQUEST_TIMEOUT = 60; //in second + const int SUBSCRIPTION_REQUEST_TIMEOUT = 120; //in second const uint16_t ADDRESS_RESOLVER_DATAGRAM_PORT = 53; const uint16_t ADDRESS_RESPONSE_DATAGRAM_PORT = 54; From e070ce4e3493dd06c9572f7b79e3bbfb2cf30d34 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 24 Jan 2018 09:35:24 -0500 Subject: [PATCH 031/119] check for valid LS before updating --- libi2pd/NetDb.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 0215c570..afe2fdde 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -237,19 +237,17 @@ namespace data auto it = m_LeaseSets.find(ident); if (it != m_LeaseSets.end ()) { - if (it->second->IsNewer (buf, len)) + /* make sure LS is valid before updating */ + LeaseSet ls(buf, len, false); + if(!ls.IsValid()) + { + LogPrint(eLogInfo, "NetDb: Updated LeaseSet is Invalid: ", ident.ToBase32()); + } + else if (it->second->IsNewer (buf, len)) { it->second->Update (buf, len); - if (it->second->IsValid ()) - { - LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); - updated = true; - } - else - { - LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase32()); - m_LeaseSets.erase (it); - } + LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); + updated = true; } else LogPrint (eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase32()); From 3820b51960c5532aa53f29607f82866b92ff9c8b Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 24 Jan 2018 09:44:55 -0500 Subject: [PATCH 032/119] Revert "check for valid LS before updating" This reverts commit e070ce4e3493dd06c9572f7b79e3bbfb2cf30d34. --- libi2pd/NetDb.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index afe2fdde..0215c570 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -237,17 +237,19 @@ namespace data auto it = m_LeaseSets.find(ident); if (it != m_LeaseSets.end ()) { - /* make sure LS is valid before updating */ - LeaseSet ls(buf, len, false); - if(!ls.IsValid()) - { - LogPrint(eLogInfo, "NetDb: Updated LeaseSet is Invalid: ", ident.ToBase32()); - } - else if (it->second->IsNewer (buf, len)) + if (it->second->IsNewer (buf, len)) { it->second->Update (buf, len); - LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); - updated = true; + if (it->second->IsValid ()) + { + LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); + updated = true; + } + else + { + LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase32()); + m_LeaseSets.erase (it); + } } else LogPrint (eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase32()); From 4a77a030338a8bc8f41617f3466cafcb551ecf06 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 24 Jan 2018 10:16:51 -0500 Subject: [PATCH 033/119] * Add LeaseSetBufferValidate which checks lease validity and extracts timestamp * check for leases with LeaseSetBufferValidate before update in floodfill code as to prevent malicous nodes removing good LS --- libi2pd/LeaseSet.cpp | 34 ++++++++++++++++++++++++++++++++++ libi2pd/LeaseSet.h | 6 ++++++ libi2pd/NetDb.cpp | 14 ++++++-------- 3 files changed, 46 insertions(+), 8 deletions(-) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index d1a70ba5..02fdafb6 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -265,5 +265,39 @@ namespace data auto ts = i2p::util::GetMillisecondsSinceEpoch (); return ts > m_ExpirationTime; } + + bool LeaseSetBufferValidate(const uint8_t * ptr, size_t sz, uint64_t & expires) + { + IdentityEx ident(ptr, sz); + size_t size = ident.GetFullLen (); + if (size > sz) + { + LogPrint (eLogError, "LeaseSet: identity length ", size, " exceeds buffer size ", sz); + return false; + } + // encryption key + size += 256; + // signing key (unused) + size += ident.GetSigningPublicKeyLen (); + uint8_t numLeases = ptr[size]; + ++size; + if (!numLeases || numLeases > MAX_NUM_LEASES) + { + LogPrint (eLogError, "LeaseSet: incorrect number of leases", (int)numLeases); + return false; + } + const uint8_t * leases = ptr + size; + expires = 0; + /** find lease with the max expiration timestamp */ + for (int i = 0; i < numLeases; i++) + { + leases += 36; // gateway + tunnel ID + uint64_t endDate = bufbe64toh (leases); + leases += 8; // end date + if(endDate > expires) + expires = endDate; + } + return ident.Verify(ptr, leases - ptr, leases); + } } } diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index c7d2066e..4c2903aa 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -95,6 +95,12 @@ namespace data size_t m_BufferLen; }; + /** + validate lease set buffer signature and extract expiration timestamp + @returns true if the leaseset is well formed and signature is valid + */ + bool LeaseSetBufferValidate(const uint8_t * ptr, size_t sz, uint64_t & expires); + class LocalLeaseSet { public: diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 0215c570..b5e20628 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -237,22 +237,20 @@ namespace data auto it = m_LeaseSets.find(ident); if (it != m_LeaseSets.end ()) { - if (it->second->IsNewer (buf, len)) + uint64_t expires; + if(LeaseSetBufferValidate(buf, len, expires)) { - it->second->Update (buf, len); - if (it->second->IsValid ()) + if(it->second->GetExpirationTime() < expires) { + it->second->Update (buf, len); LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); updated = true; } else - { - LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase32()); - m_LeaseSets.erase (it); - } + LogPrint(eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase32()); } else - LogPrint (eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase32()); + LogPrint(eLogError, "NetDb: LeaseSet is invalid: ", ident.ToBase32()); } else { From 3ac86db0380274261666f7a047ac696190dc9245 Mon Sep 17 00:00:00 2001 From: Darknet Villain Date: Wed, 24 Jan 2018 12:48:05 -0500 Subject: [PATCH 034/119] Fix Docker image error --- contrib/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index 5ca03f4c..e7e60f37 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -35,7 +35,7 @@ RUN apk --no-cache --virtual build-dependendencies add make gcc g++ libtool boos && mv i2pd /usr/local/bin \ && cd /usr/local/bin \ && strip i2pd \ - && rm -fr /tmp/build && apk --purge del build-dependendencies build-base fortify-headers boost-dev zlib-dev openssl-dev \ + && rm -fr /tmp/build && apk --no-cache --purge del build-dependendencies build-base fortify-headers boost-dev zlib-dev openssl-dev \ boost-python3 python3 gdbm boost-unit_test_framework boost-python linux-headers boost-prg_exec_monitor \ boost-serialization boost-signals boost-wave boost-wserialization boost-math boost-graph boost-regex git pcre \ libtool g++ gcc pkgconfig From f4a2dda94e9adc36b3078c6f0d2829df93102c37 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 25 Jan 2018 08:49:30 -0500 Subject: [PATCH 035/119] try streaming race condition fix --- libi2pd/Streaming.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libi2pd/Streaming.cpp b/libi2pd/Streaming.cpp index 9942d8e2..91acc9d0 100644 --- a/libi2pd/Streaming.cpp +++ b/libi2pd/Streaming.cpp @@ -578,7 +578,9 @@ namespace stream if (m_SentPackets.empty () && m_SendBuffer.IsEmpty ()) // nothing to send { m_Status = eStreamStatusClosed; - SendClose (); + // close could be called from another thread so do SendClose from the destination thread + // this is so m_LocalDestination.NewPacket () does not trigger a race condition + m_Service.post(std::bind(&Stream::SendClose, shared_from_this())); } break; case eStreamStatusClosed: From b1c701085b5bf9115b06b3c1d84ba48dab9b0f18 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 25 Jan 2018 10:09:34 -0500 Subject: [PATCH 036/119] don't verify signature twice --- libi2pd/LeaseSet.cpp | 6 +++--- libi2pd/LeaseSet.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index 02fdafb6..497a562f 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -31,7 +31,7 @@ namespace data } memcpy (m_Buffer, buf, len); m_BufferLen = len; - ReadFromBuffer (false); + ReadFromBuffer (false, false); // we assume signature is verified already } void LeaseSet::PopulateLeases () @@ -40,7 +40,7 @@ namespace data ReadFromBuffer (false); } - void LeaseSet::ReadFromBuffer (bool readIdentity) + void LeaseSet::ReadFromBuffer (bool readIdentity, bool verifySignature) { if (readIdentity || !m_Identity) m_Identity = std::make_shared(m_Buffer, m_BufferLen); @@ -128,7 +128,7 @@ namespace data } // verify - if (!m_Identity->Verify (m_Buffer, leases - m_Buffer, leases)) + if (verifySignature && !m_Identity->Verify (m_Buffer, leases - m_Buffer, leases)) { LogPrint (eLogWarning, "LeaseSet: verification failed"); m_IsValid = false; diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 4c2903aa..9839361e 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -81,7 +81,7 @@ namespace data private: - void ReadFromBuffer (bool readIdentity = true); + void ReadFromBuffer (bool readIdentity = true, bool verifySignature = true); uint64_t ExtractTimestamp (const uint8_t * buf, size_t len) const; // min expiration time private: From 7db2e9dc4af0f5486cb2e556dd663cffc347a0d5 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 25 Jan 2018 10:32:08 -0500 Subject: [PATCH 037/119] don't verify signature twice --- libi2pd/LeaseSet.cpp | 4 ++-- libi2pd/LeaseSet.h | 2 +- libi2pd/NetDb.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index 497a562f..f2355930 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -21,7 +21,7 @@ namespace data ReadFromBuffer (); } - void LeaseSet::Update (const uint8_t * buf, size_t len) + void LeaseSet::Update (const uint8_t * buf, size_t len, bool verifySignature) { if (len > m_BufferLen) { @@ -31,7 +31,7 @@ namespace data } memcpy (m_Buffer, buf, len); m_BufferLen = len; - ReadFromBuffer (false, false); // we assume signature is verified already + ReadFromBuffer (false, verifySignature); } void LeaseSet::PopulateLeases () diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 9839361e..391a3b79 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -57,7 +57,7 @@ namespace data LeaseSet (const uint8_t * buf, size_t len, bool storeLeases = true); ~LeaseSet () { delete[] m_Buffer; }; - void Update (const uint8_t * buf, size_t len); + void Update (const uint8_t * buf, size_t len, bool verifySignature = true); bool IsNewer (const uint8_t * buf, size_t len) const; void PopulateLeases (); // from buffer diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index b5e20628..b136dfd5 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -242,7 +242,7 @@ namespace data { if(it->second->GetExpirationTime() < expires) { - it->second->Update (buf, len); + it->second->Update (buf, len, false); // signature is verified already LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase32()); updated = true; } From e1527dc137623029461bd12fb4030e04baf984df Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 26 Jan 2018 14:07:51 -0500 Subject: [PATCH 038/119] update LeaseSet if a tunnel was deleted --- libi2pd/LeaseSet.cpp | 7 ++++--- libi2pd/LeaseSet.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index f2355930..e763912f 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -135,7 +135,7 @@ namespace data } } - uint64_t LeaseSet::ExtractTimestamp (const uint8_t * buf, size_t len) const + uint64_t LeaseSet::ExtractTimestamp (const uint8_t * buf, size_t len, uint8_t& num) const { if (!m_Identity) return 0; size_t size = m_Identity->GetFullLen (); @@ -143,7 +143,7 @@ namespace data size += 256; // encryption key size += m_Identity->GetSigningPublicKeyLen (); // unused signing key if (size > len) return 0; - uint8_t num = buf[size]; + num = buf[size]; size++; // num if (size + num*LEASE_SIZE > len) return 0; uint64_t timestamp= 0 ; @@ -160,7 +160,8 @@ namespace data bool LeaseSet::IsNewer (const uint8_t * buf, size_t len) const { - return ExtractTimestamp (buf, len) > ExtractTimestamp (m_Buffer, m_BufferLen); + uint8_t num1, num2; + return ExtractTimestamp (buf, len, num2) > ExtractTimestamp (m_Buffer, m_BufferLen, num1) || num2 < num1; // some lease might be deleted } bool LeaseSet::ExpiresSoon(const uint64_t dlt, const uint64_t fudge) const diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 391a3b79..69b4e2fc 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -82,7 +82,7 @@ namespace data private: void ReadFromBuffer (bool readIdentity = true, bool verifySignature = true); - uint64_t ExtractTimestamp (const uint8_t * buf, size_t len) const; // min expiration time + uint64_t ExtractTimestamp (const uint8_t * buf, size_t len, uint8_t& num) const; // returns max expiration time, num is number of leases private: From 8c2de4973cbf00623fabcef801a90af971b1f9bb Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 26 Jan 2018 14:33:06 -0500 Subject: [PATCH 039/119] rollback --- libi2pd/LeaseSet.cpp | 7 +++---- libi2pd/LeaseSet.h | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index e763912f..f2355930 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -135,7 +135,7 @@ namespace data } } - uint64_t LeaseSet::ExtractTimestamp (const uint8_t * buf, size_t len, uint8_t& num) const + uint64_t LeaseSet::ExtractTimestamp (const uint8_t * buf, size_t len) const { if (!m_Identity) return 0; size_t size = m_Identity->GetFullLen (); @@ -143,7 +143,7 @@ namespace data size += 256; // encryption key size += m_Identity->GetSigningPublicKeyLen (); // unused signing key if (size > len) return 0; - num = buf[size]; + uint8_t num = buf[size]; size++; // num if (size + num*LEASE_SIZE > len) return 0; uint64_t timestamp= 0 ; @@ -160,8 +160,7 @@ namespace data bool LeaseSet::IsNewer (const uint8_t * buf, size_t len) const { - uint8_t num1, num2; - return ExtractTimestamp (buf, len, num2) > ExtractTimestamp (m_Buffer, m_BufferLen, num1) || num2 < num1; // some lease might be deleted + return ExtractTimestamp (buf, len) > ExtractTimestamp (m_Buffer, m_BufferLen); } bool LeaseSet::ExpiresSoon(const uint64_t dlt, const uint64_t fudge) const diff --git a/libi2pd/LeaseSet.h b/libi2pd/LeaseSet.h index 69b4e2fc..fa24df2f 100644 --- a/libi2pd/LeaseSet.h +++ b/libi2pd/LeaseSet.h @@ -82,7 +82,7 @@ namespace data private: void ReadFromBuffer (bool readIdentity = true, bool verifySignature = true); - uint64_t ExtractTimestamp (const uint8_t * buf, size_t len, uint8_t& num) const; // returns max expiration time, num is number of leases + uint64_t ExtractTimestamp (const uint8_t * buf, size_t len) const; // returns max expiration time private: From dfbefee4771d17da3d95f72ef369fabd9b7649ab Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 26 Jan 2018 14:34:05 -0500 Subject: [PATCH 040/119] graceful shutdown complete if no transit tunnels anymore --- daemon/UnixDaemon.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/daemon/UnixDaemon.cpp b/daemon/UnixDaemon.cpp index 075aa7d8..a9c48fee 100644 --- a/daemon/UnixDaemon.cpp +++ b/daemon/UnixDaemon.cpp @@ -13,6 +13,7 @@ #include "Config.h" #include "FS.h" #include "Log.h" +#include "Tunnel.h" #include "RouterContext.h" #include "ClientContext.h" @@ -163,7 +164,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(); } @@ -183,7 +184,7 @@ namespace i2p if (gracefulShutdownInterval) { gracefulShutdownInterval--; // - 1 second - if (gracefulShutdownInterval <= 0) + if (gracefulShutdownInterval <= 0 || i2p::tunnel::tunnels.CountTransitTunnels() <= 0) { LogPrint(eLogInfo, "Graceful shutdown"); return; From b00ff43be753687c48a7f835fc2c53a93ede31f4 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 26 Jan 2018 19:52:11 -0500 Subject: [PATCH 041/119] Update README.md --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4d8bf108..40948b34 100644 --- a/README.md +++ b/README.md @@ -70,12 +70,11 @@ See [documentation](https://i2pd.readthedocs.io/en/latest/user-guide/run/) and Donations --------- -BTC: 1K7Ds6KUeR8ya287UC4rYTjvC96vXyZbDY -ZEC: t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ -DASH: Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF +BTC: 3MDoGJW9TLMTCDGrR9bLgWXfm6sjmgy86f LTC: LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59 -DOGE: DNXLQKziRPAsD9H3DFNjk4fLQrdaSX893Y -ANC: AQJYweYYUqM1nVfLqfoSMpUMfzxvS4Xd7z +ETH: 0x9e5bac70d20d1079ceaa111127f4fb3bccce379d +DASH: Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF +ZEC: t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ GST: GbD2JSQHBHCKLa9WTHmigJRpyFgmBj4woG License From 6ee279d83ee538ce1afb8bde1a6a6e2d77f10a6f Mon Sep 17 00:00:00 2001 From: Darknet Villain Date: Sat, 27 Jan 2018 10:54:03 -0500 Subject: [PATCH 042/119] [rpm] Merge i2pd-systemd with i2pd package + changelog --- contrib/rpm/i2pd.spec | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index f0f7a9a7..23e0b32d 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -4,6 +4,7 @@ Name: i2pd Version: 2.17.0 Release: %{build_timestamp}git%{?dist} Summary: I2P router written in C++ +Obsoletes: %{name}-systemd License: BSD URL: https://github.com/PurpleI2P/i2pd @@ -23,25 +24,12 @@ BuildRequires: openssl-devel BuildRequires: miniupnpc-devel BuildRequires: systemd-units -%description -C++ implementation of I2P. - - -%package systemd -Summary: Files to run I2P router under systemd -Requires: i2pd Requires: systemd Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd -Obsoletes: %{name}-daemon - -%description systemd +%description C++ implementation of I2P. -This package contains systemd unit file to run i2pd as a system service -using dedicated user's permissions. - - %prep %setup -q @@ -79,22 +67,22 @@ install -d -m 700 %{buildroot}/%{_localstatedir}/log/i2pd ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/%{name}/certificates -%pre systemd +%pre getent group i2pd >/dev/null || %{_sbindir}/groupadd -r i2pd getent passwd i2pd >/dev/null || \ %{_sbindir}/useradd -r -g i2pd -s %{_sbindir}/nologin \ -d %{_sharedstatedir}/i2pd -c 'I2P Service' i2pd -%post systemd +%post %systemd_post i2pd.service -%preun systemd +%preun %systemd_preun i2pd.service -%postun systemd +%postun %systemd_postun_with_restart i2pd.service @@ -103,9 +91,6 @@ getent passwd i2pd >/dev/null || \ %{_sbindir}/i2pd %{_datadir}/i2pd/certificates %config(noreplace) %{_sysconfdir}/i2pd/* - - -%files systemd /%{_unitdir}/i2pd.service %dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd %dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd @@ -113,6 +98,10 @@ getent passwd i2pd >/dev/null || \ %changelog +* Sat Jan 27 2018 l-n-s - 2.17.0-1 +- Added certificates and default configuration files +- Merge i2pd with i2pd-systemd package + * Mon Dec 04 2017 orignal - 2.17.0 - Added reseed through HTTP and SOCKS proxy - Added show status of client services through web console From 20b4f6b24d9d17c0829f4d1997391debb529cfd8 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 29 Jan 2018 03:47:43 +0300 Subject: [PATCH 043/119] update apparmor profile --- contrib/apparmor/usr.sbin.i2pd | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/contrib/apparmor/usr.sbin.i2pd b/contrib/apparmor/usr.sbin.i2pd index f0dea839..109ab4b1 100644 --- a/contrib/apparmor/usr.sbin.i2pd +++ b/contrib/apparmor/usr.sbin.i2pd @@ -21,10 +21,11 @@ # path specific (feel free to modify if you have another paths) /etc/i2pd/** r, + /run/i2pd/i2pd.pid rw, /var/lib/i2pd/** rw, - /var/log/i2pd.log w, + /var/log/i2pd/i2pd.log w, /var/run/i2pd/i2pd.pid rw, /usr/sbin/i2pd mr, - + /usr/share/i2pd/** r, } From 6272e15b47830c601f07102a8ff4aed9290707b2 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 29 Jan 2018 04:13:33 +0300 Subject: [PATCH 044/119] add users homedir to profile --- contrib/apparmor/usr.sbin.i2pd | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contrib/apparmor/usr.sbin.i2pd b/contrib/apparmor/usr.sbin.i2pd index 109ab4b1..80d73996 100644 --- a/contrib/apparmor/usr.sbin.i2pd +++ b/contrib/apparmor/usr.sbin.i2pd @@ -28,4 +28,6 @@ /usr/sbin/i2pd mr, /usr/share/i2pd/** r, + # user homedir (if started not by init.d or systemd) + owner /home/*/.i2pd/** rw, } From 95d8887ab02bb8ca4ed628efd29cd9b20e257b6c Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 30 Jan 2018 17:30:01 +0300 Subject: [PATCH 045/119] update profile --- contrib/apparmor/usr.sbin.i2pd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contrib/apparmor/usr.sbin.i2pd b/contrib/apparmor/usr.sbin.i2pd index 80d73996..4349e07b 100644 --- a/contrib/apparmor/usr.sbin.i2pd +++ b/contrib/apparmor/usr.sbin.i2pd @@ -29,5 +29,6 @@ /usr/share/i2pd/** r, # user homedir (if started not by init.d or systemd) - owner /home/*/.i2pd/** rw, + owner @{HOME}/.i2pd/ rw, + owner @{HOME}/.i2pd/** rwk, } From 3426906a4ffb09c8bf2bddb42d57c0e4d3a4e8a9 Mon Sep 17 00:00:00 2001 From: Darknet Villain Date: Tue, 30 Jan 2018 10:03:53 -0500 Subject: [PATCH 046/119] [rpm] Fix changelogs to comply with guidelines, add tunconf key to systemd package --- contrib/rpm/i2pd.service | 2 +- contrib/rpm/i2pd.spec | 70 ++++++---------------------------------- 2 files changed, 10 insertions(+), 62 deletions(-) diff --git a/contrib/rpm/i2pd.service b/contrib/rpm/i2pd.service index 89562ff5..ec5949ff 100644 --- a/contrib/rpm/i2pd.service +++ b/contrib/rpm/i2pd.service @@ -8,7 +8,7 @@ Group=i2pd RuntimeDirectory=i2pd RuntimeDirectoryMode=0700 Type=simple -ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service +ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service ExecReload=/bin/kill -HUP $MAINPID PIDFile=/var/run/i2pd/i2pd.pid ### Uncomment, if auto restart needed diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 23e0b32d..2efe8838 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -98,83 +98,31 @@ getent passwd i2pd >/dev/null || \ %changelog -* Sat Jan 27 2018 l-n-s - 2.17.0-1 +* Sat Jan 30 2018 l-n-s - 2.17.0-1 - Added certificates and default configuration files - Merge i2pd with i2pd-systemd package +- Fixed package changelogs to comply with guidelines * Mon Dec 04 2017 orignal - 2.17.0 -- Added reseed through HTTP and SOCKS proxy -- Added show status of client services through web console -- Added change log level through web connsole -- Added transient keys for tunnels -- Added i2p.streaming.initialAckDelay parameter -- Added CRYPTO_TYPE for SAM destination -- Added signature and crypto type for newkeys BOB command -- Changed - correct publication of ECIES destinations -- Changed - disable RSA signatures completely -- Fixed CVE-2017-17066 -- Fixed possible buffer overflow for RSA-4096 -- Fixed shutdown from web console for Windows -- Fixed web console page layout +- update to 2.17.0 * Mon Nov 13 2017 orignal - 2.16.0 -- Added https and "Connect" method for HTTP proxy -- Added outproxy for HTTP proxy -- Added initial support of ECIES crypto -- Added NTCP soft and hard descriptors limits -- Added support full timestamps in logs -- Changed faster implmentation of GOST R 34.11 hash -- Changed reject routers with RSA signtures -- Changed reload config and shudown from Windows GUI -- Changed update tunnels address(destination) without restart -- Fixed BOB crashes if destination is not set -- Fixed correct SAM tunnel name -- Fixed QT GUI issues +- update to 2.16.0 * Thu Aug 17 2017 orignal - 2.15.0 -- 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 -- Changed peer test if nat=false -- Changed separate output of NTCP and SSU sessions in Transports tab -- Fixed handle lines with comments in hosts.txt file for address book -- Fixed run router with empty netdb for testnet -- Fixed skip expired introducers by iexp +- update to 2.15.0 * Thu Jun 01 2017 orignal - 2.14.0 -- Added transit traffic bandwidth limitation -- Added NTCP connections through HTTP and SOCKS proxies -- Added ability to disable address helper for HTTP proxy -- Changed reseed servers list +- update to 2.14.0 * Thu Apr 06 2017 orignal - 2.13.0 -- Added persist local destination's tags -- Added GOST signature types 9 and 10 -- Added exploratory tunnels configuration -- Changed reseed servers list -- Changed inactive NTCP sockets get closed faster -- Changed some EdDSA speed up -- Fixed multiple acceptors for SAM -- Fixed follow on data after STREAM CREATE for SAM -- Fixed memory leaks +- update to 2.13.0 * Tue Feb 14 2017 orignal - 2.12.0 -- Additional HTTP and SOCKS proxy tunnels -- Reseed from ZIP archive -- 'X' bandwidth code -- Reduced memory and file descriptors usage +- update to 2.12.0 * Mon Dec 19 2016 orignal - 2.11.0 -- Full support of zero-hops tunnels -- Tunnel configuration for HTTP and SOCKS proxy -- Websockets support -- Multiple acceptors for SAM destination -- Routing path for UDP tunnels -- Reseed through a floodfill -- Use AVX instructions for DHT and HMAC if applicable -- Fixed UPnP discovery bug, producing excessive CPU usage -- Handle multiple lookups of the same LeaseSet correctly +- update to 2.11.0 * Thu Oct 20 2016 Anatolii Vorona - 2.10.0-3 - add support C7 From 32d300248e0e7fa1f25874890db952e545275364 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 30 Jan 2018 18:09:26 +0300 Subject: [PATCH 047/119] update building stuff --- build/build_mingw.cmd | 1 + debian/compat | 2 +- debian/control | 4 ++-- debian/copyright | 44 +++++++++++++++++++++++++++++++++++----- debian/lintian-overrides | 2 ++ 5 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 debian/lintian-overrides diff --git a/build/build_mingw.cmd b/build/build_mingw.cmd index 6763b63e..cc6a15fa 100644 --- a/build/build_mingw.cmd +++ b/build/build_mingw.cmd @@ -58,6 +58,7 @@ pause exit /b 0 :BUILDING +%xSH% "make clean" >> nul echo Building i2pd %tag% for win%bitness%: echo Build AVX+AESNI... %xSH% "make USE_UPNP=yes USE_AVX=1 USE_AESNI=1 -j%threads% && zip -r9 build/i2pd_%tag%_win%bitness%_mingw_avx_aesni.zip i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates && make clean" > build/build_win%bitness%_avx_aesni.log 2>&1 diff --git a/debian/compat b/debian/compat index ec635144..f11c82a4 100644 --- a/debian/compat +++ b/debian/compat @@ -1 +1 @@ -9 +9 \ No newline at end of file diff --git a/debian/control b/debian/control index 808cdda9..7bd18ebb 100644 --- a/debian/control +++ b/debian/control @@ -2,11 +2,11 @@ Source: i2pd Section: net Priority: optional Maintainer: R4SAS -Build-Depends: debhelper (>= 9), dpkg-dev (>= 1.16.1~), gcc (>= 4.7) | clang (>= 3.3), libboost-system-dev (>= 1.46), libboost-date-time-dev, libboost-filesystem-dev, libboost-program-options-dev, libminiupnpc-dev, libssl-dev, zlib1g-dev, dh-apparmor +Build-Depends: debhelper (>= 9), dpkg-dev (>= 1.16.1~), gcc (>= 4.7) | clang (>= 3.3), libboost-system-dev (>= 1.46), libboost-date-time-dev (>= 1.46), libboost-filesystem-dev (>= 1.46), libboost-program-options-dev (>= 1.46), libminiupnpc-dev, libssl-dev, zlib1g-dev, dh-apparmor Standards-Version: 3.9.6 Homepage: http://i2pd.website/ Vcs-Git: git://github.com/PurpleI2P/i2pd.git -Vcs-Browser: https://github.com/PurpleI2P/i2pd.git +Vcs-Browser: https://github.com/PurpleI2P/i2pd Package: i2pd Architecture: any diff --git a/debian/copyright b/debian/copyright index 6aeefebf..3c513020 100644 --- a/debian/copyright +++ b/debian/copyright @@ -4,6 +4,22 @@ Source: https://github.com/PurpleI2P Files: * Copyright: 2013-2017 PurpleI2P +License: BSD-3-clause + +Files: qt/i2pd_qt/android/src/org/kde/necessitas/ministro/IMinistro.aidl + qt/i2pd_qt/android/src/org/kde/necessitas/ministro/IMinistroCallback.aidl + qt/i2pd_qt/android/src/org/qtproject/qt5/android/bindings/QtActivity.java + qt/i2pd_qt/android/src/org/qtproject/qt5/android/bindings/QtApplication.java +Copyright: 2011-2013 BogDan Vatra +License: BSD-2-Clause + +Files: debian/* +Copyright: 2013-2015 Kill Your TV + 2014-2016 hagen + 2016-2017 R4SAS + 2017-2018 Yangfl +License: GPL-2+ + License: BSD-3-clause Copyright (c) 2013-2017, The PurpleI2P Project . @@ -33,11 +49,29 @@ License: BSD-3-clause TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Files: debian/* -Copyright: 2016-2017 R4SAS - 2014-2016 hagen - 2013-2015 Kill Your TV -License: GPL-2.0+ +License: BSD-2-Clause + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + . + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE HOLDERS OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +License: GPL-2+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or diff --git a/debian/lintian-overrides b/debian/lintian-overrides new file mode 100644 index 00000000..af3d61c6 --- /dev/null +++ b/debian/lintian-overrides @@ -0,0 +1,2 @@ +# GPL come from debian/ +i2pd: possible-gpl-code-linked-with-openssl \ No newline at end of file From 13d174c09c37a8e5eadf4c57f61390675619030c Mon Sep 17 00:00:00 2001 From: R4SAS Date: Tue, 30 Jan 2018 18:14:54 +0300 Subject: [PATCH 048/119] add tunconf in systemctl service file --- contrib/debian/i2pd.service | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contrib/debian/i2pd.service b/contrib/debian/i2pd.service index 89562ff5..37f26f14 100644 --- a/contrib/debian/i2pd.service +++ b/contrib/debian/i2pd.service @@ -8,7 +8,7 @@ Group=i2pd RuntimeDirectory=i2pd RuntimeDirectoryMode=0700 Type=simple -ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service +ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service ExecReload=/bin/kill -HUP $MAINPID PIDFile=/var/run/i2pd/i2pd.pid ### Uncomment, if auto restart needed @@ -19,7 +19,7 @@ PIDFile=/var/run/i2pd/i2pd.pid KillSignal=SIGINT TimeoutStopSec=10m -# If you have problems with hunging i2pd, you can try enable this +# If you have problems with hanging i2pd, you can try enable this #LimitNOFILE=4096 PrivateDevices=yes From 49014342098c97ab05a3b36de4a0e45be8a8696d Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 30 Jan 2018 10:41:35 -0500 Subject: [PATCH 049/119] 2.18.0 --- ChangeLog | 17 +++++++++++++++++ Win32/installer.iss | 2 +- android/AndroidManifest.xml | 2 +- appveyor.yml | 2 +- contrib/rpm/i2pd.spec | 7 +++++-- debian/changelog | 6 ++++++ libi2pd/version.h | 4 ++-- qt/i2pd_qt/android/AndroidManifest.xml | 2 +- 8 files changed, 34 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2468f808..d2bfe7bf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,23 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.18.0] - 2018-01-30 +### Added +- Show tunnel nicknames for I2CP destination in WebUI +- Re-create HTTP and SOCKS proxy by tunnel reload +- Graceful shutdown as soon as no more transit tunnels +### Changed +- Regenerate shared local destination by tunnel reload +- Use transient local destination by default if not specified +- Return correct code if pid file can't be created +- Timing and number of attempts for adressbook requests +- Certificates list +### Fixed +- Malformed addressbook subsctiption request +- Build with boost 1.66 +- Few race conditions for SAM +- Check LeaseSet's signature before update + ## [2.17.0] - 2017-12-04 ### Added - Reseed through HTTP and SOCKS proxy diff --git a/Win32/installer.iss b/Win32/installer.iss index 03b0842b..15ce4372 100644 --- a/Win32/installer.iss +++ b/Win32/installer.iss @@ -1,5 +1,5 @@ #define I2Pd_AppName "i2pd" -#define I2Pd_ver "2.17.0" +#define I2Pd_ver "2.18.0" #define I2Pd_Publisher "PurpleI2P" [Setup] diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 1f9d3b91..3ae952b3 100755 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -2,7 +2,7 @@ diff --git a/appveyor.yml b/appveyor.yml index 6c0470d1..ac632141 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.17.{build} +version: 2.18.{build} pull_requests: do_not_increment_build_number: true branches: diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 2efe8838..316be961 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,7 +1,7 @@ %define build_timestamp %(date +"%Y%m%d") Name: i2pd -Version: 2.17.0 +Version: 2.18.0 Release: %{build_timestamp}git%{?dist} Summary: I2P router written in C++ Obsoletes: %{name}-systemd @@ -98,7 +98,10 @@ getent passwd i2pd >/dev/null || \ %changelog -* Sat Jan 30 2018 l-n-s - 2.17.0-1 +* Tue Jan 30 2018 orignal > - 2.18.0 +- update to 2.18.0 + +* Sat Jan 27 2018 l-n-s - 2.17.0-1 - Added certificates and default configuration files - Merge i2pd with i2pd-systemd package - Fixed package changelogs to comply with guidelines diff --git a/debian/changelog b/debian/changelog index 94105535..5f298646 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.18.0-1) unstable; urgency=low + + * updated to version 2.18.0/0.9.38 + + -- orignal Tue, 30 Jan 2018 16:00:00 +0000 + i2pd (2.17.0-1) unstable; urgency=low * updated to version 2.17.0/0.9.32 diff --git a/libi2pd/version.h b/libi2pd/version.h index b443ea6f..36e7eb6e 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -7,7 +7,7 @@ #define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 17 +#define I2PD_VERSION_MINOR 18 #define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO) @@ -21,7 +21,7 @@ #define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MINOR 9 -#define I2P_VERSION_MICRO 32 +#define I2P_VERSION_MICRO 33 #define I2P_VERSION_PATCH 0 #define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) diff --git a/qt/i2pd_qt/android/AndroidManifest.xml b/qt/i2pd_qt/android/AndroidManifest.xml index 20061963..56b37e6a 100644 --- a/qt/i2pd_qt/android/AndroidManifest.xml +++ b/qt/i2pd_qt/android/AndroidManifest.xml @@ -1,5 +1,5 @@ - + From b6e75e9c5ad6c981419ca376625d78de7b4c0355 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 30 Jan 2018 11:14:29 -0500 Subject: [PATCH 050/119] Update changelog --- debian/changelog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 5f298646..afddc797 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,6 @@ i2pd (2.18.0-1) unstable; urgency=low - * updated to version 2.18.0/0.9.38 + * updated to version 2.18.0/0.9.33 -- orignal Tue, 30 Jan 2018 16:00:00 +0000 From fca2693488823f5b02f770eb2fa08e1ed9461327 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 1 Feb 2018 01:12:06 +0300 Subject: [PATCH 051/119] add centos/fedora build status --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 40948b34..67b82ceb 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ Build instructions: * GNU/Linux x86/x64 - [![Build Status](https://travis-ci.org/PurpleI2P/i2pd.svg?branch=openssl)](https://travis-ci.org/PurpleI2P/i2pd) * 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) +* CentOS / Fedora - [![Build Status](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/status_image/last_build.png)](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/) * FreeBSD * Android * iOS From 180730f9cf3138f347f764e598a5880652197d25 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Thu, 1 Feb 2018 19:37:38 +0300 Subject: [PATCH 052/119] fix rpm spec's (#1084) * added spec for git package * fixed double slashes * changed versioning for stable builds --- contrib/rpm/i2pd-git.spec | 103 ++++++++++++++++++++++++++++++++++++++ contrib/rpm/i2pd.spec | 22 ++++---- 2 files changed, 116 insertions(+), 9 deletions(-) create mode 100644 contrib/rpm/i2pd-git.spec diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec new file mode 100644 index 00000000..2bde7289 --- /dev/null +++ b/contrib/rpm/i2pd-git.spec @@ -0,0 +1,103 @@ +%define git_hash %(git rev-parse HEAD | cut -c -7) + +Name: i2pd-git +Version: 2.18.0 +Release: %{git_hash}.git%{?dist} +Summary: I2P router written in C++ +Obsoletes: %{name}-systemd +Conflicts: i2pd + +License: BSD +URL: https://github.com/PurpleI2P/i2pd +Source0: https://github.com/PurpleI2P/i2pd/archive/openssl/i2pd-openssl.tar.gz + +%if 0%{?rhel} == 7 +BuildRequires: cmake3 +%else +BuildRequires: cmake +%endif + +BuildRequires: chrpath +BuildRequires: gcc-c++ +BuildRequires: zlib-devel +BuildRequires: boost-devel +BuildRequires: openssl-devel +BuildRequires: miniupnpc-devel +BuildRequires: systemd-units + +Requires: systemd +Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd + +%description +C++ implementation of I2P. + +%prep +%setup -q + + +%build +cd build +%if 0%{?rhel} == 7 +%cmake3 \ + -DWITH_LIBRARY=OFF \ + -DWITH_UPNP=ON \ + -DWITH_HARDENING=ON \ + -DBUILD_SHARED_LIBS:BOOL=OFF +%else +%cmake \ + -DWITH_LIBRARY=OFF \ + -DWITH_UPNP=ON \ + -DWITH_HARDENING=ON \ + -DBUILD_SHARED_LIBS:BOOL=OFF +%endif + +make %{?_smp_mflags} + + +%install +cd build +chrpath -d i2pd +install -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd +install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf +install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf +install -d -m 755 %{buildroot}%{_datadir}/i2pd +%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates +install -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}%{_unitdir}/i2pd.service +install -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd +install -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd +ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates + + +%pre +getent group i2pd >/dev/null || %{_sbindir}/groupadd -r i2pd +getent passwd i2pd >/dev/null || \ + %{_sbindir}/useradd -r -g i2pd -s %{_sbindir}/nologin \ + -d %{_sharedstatedir}/i2pd -c 'I2P Service' i2pd + + +%post +%systemd_post i2pd.service + + +%preun +%systemd_preun i2pd.service + + +%postun +%systemd_postun_with_restart i2pd.service + + +%files +%doc LICENSE README.md +%{_sbindir}/i2pd +%{_datadir}/i2pd/certificates +%config(noreplace) %{_sysconfdir}/i2pd/* +/%{_unitdir}/i2pd.service +%dir %attr(0700,i2pd,i2pd) %{_localstatedir}/log/i2pd +%dir %attr(0700,i2pd,i2pd) %{_sharedstatedir}/i2pd +%{_sharedstatedir}/i2pd/certificates + + +%changelog +* Thu Feb 01 2018 r4sas - 2.18.0 +- Initial i2pd-git based on i2pd 2.18.0-1 spec \ No newline at end of file diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 316be961..ba4e3890 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,10 +1,9 @@ -%define build_timestamp %(date +"%Y%m%d") - Name: i2pd Version: 2.18.0 -Release: %{build_timestamp}git%{?dist} +Release: 1%{?dist} Summary: I2P router written in C++ Obsoletes: %{name}-systemd +Conflicts: i2pd-git License: BSD URL: https://github.com/PurpleI2P/i2pd @@ -59,12 +58,12 @@ chrpath -d i2pd install -D -m 755 i2pd %{buildroot}%{_sbindir}/i2pd install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf install -D -m 755 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf -install -d -m 755 %{buildroot}/%{_datadir}/i2pd +install -d -m 755 %{buildroot}%{_datadir}/i2pd %{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates -install -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}/%{_unitdir}/i2pd.service -install -d -m 700 %{buildroot}/%{_sharedstatedir}/i2pd -install -d -m 700 %{buildroot}/%{_localstatedir}/log/i2pd -ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/%{name}/certificates +install -D -m 644 %{_builddir}/%{name}-%{version}/contrib/rpm/i2pd.service %{buildroot}%{_unitdir}/i2pd.service +install -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd +install -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd +ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates %pre @@ -98,7 +97,12 @@ getent passwd i2pd >/dev/null || \ %changelog -* Tue Jan 30 2018 orignal > - 2.18.0 +* Thu Feb 01 2018 r4sas - 2.18.0-1 +- Added to conflicts i2pd-git package +- Fixed release versioning +- Fixed paths with double slashes + +* Tue Jan 30 2018 orignal - 2.18.0 - update to 2.18.0 * Sat Jan 27 2018 l-n-s - 2.17.0-1 From 80567312ed83c0221b6adac9f61919d312f4149b Mon Sep 17 00:00:00 2001 From: BOPOHA Date: Thu, 1 Feb 2018 22:11:14 +0100 Subject: [PATCH 053/119] i2pd.spec delete obsoletes tag https://github.com/PurpleI2P/i2pd/pull/1084#issuecomment-362215861 ``` Resolving Dependencies --> Running transaction check ---> Package i2pd.x86_64 0:2.17.0-20171206git.el7.centos will be updated ---> Package i2pd.x86_64 0:2.18.0-1.el7.centos will be obsoleting ---> Package i2pd-systemd.x86_64 0:2.17.0-20171206git.el7.centos will be obsoleted --> Finished Dependency Resolution Dependencies Resolved ========================================================================== Package Arch Version Repository Size ========================================================================== Installing: i2pd x86_64 2.18.0-1.el7.centos vorona-i2pd 915 k replacing i2pd-systemd.x86_64 2.17.0-20171206git.el7.centos Transaction Summary ========================================================================== Install 1 Package Total download size: 915 k Is this ok [y/d/N]: ``` @l-n-s thx, obsoletes tag is unneeded in next release) --- contrib/rpm/i2pd.spec | 1 - 1 file changed, 1 deletion(-) diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index ba4e3890..469740ce 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -2,7 +2,6 @@ Name: i2pd Version: 2.18.0 Release: 1%{?dist} Summary: I2P router written in C++ -Obsoletes: %{name}-systemd Conflicts: i2pd-git License: BSD From ce57a130fc885d342f8e6f1354d3b9f59af26bc5 Mon Sep 17 00:00:00 2001 From: BOPOHA Date: Thu, 1 Feb 2018 23:21:20 +0100 Subject: [PATCH 054/119] systemd issue in centos 7 Not working pre-create pid-file dir (/run/i2pd). It fixed with one of this ways: > PermissionsStartOnly=True or > ExecStartPre=/bin/mkdir -p -m 0700 /var/run/i2pd > ExecStartPre=/bin/chown i2pd: /var/run/i2pd First way is prefer because RuntimeDirectory's options already used. --- contrib/rpm/i2pd.service | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/rpm/i2pd.service b/contrib/rpm/i2pd.service index ec5949ff..8a9c9584 100644 --- a/contrib/rpm/i2pd.service +++ b/contrib/rpm/i2pd.service @@ -5,6 +5,7 @@ After=network.target [Service] User=i2pd Group=i2pd +PermissionsStartOnly=True RuntimeDirectory=i2pd RuntimeDirectoryMode=0700 Type=simple From fbb99911285c46931e543409ac6149f86141efdb Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 2 Feb 2018 10:35:07 +0300 Subject: [PATCH 055/119] remove obsoletes tag for rpm git package --- contrib/rpm/i2pd-git.spec | 1 - 1 file changed, 1 deletion(-) diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index 2bde7289..b2be3b9f 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -4,7 +4,6 @@ Name: i2pd-git Version: 2.18.0 Release: %{git_hash}.git%{?dist} Summary: I2P router written in C++ -Obsoletes: %{name}-systemd Conflicts: i2pd License: BSD From 4f84d687e413f5945bd12861187ea5af9dd950ec Mon Sep 17 00:00:00 2001 From: yangfl Date: Sat, 3 Feb 2018 02:27:22 +0800 Subject: [PATCH 056/119] add endian detection for glibc --- libi2pd/I2PEndian.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/I2PEndian.h b/libi2pd/I2PEndian.h index e5271233..d08e90cb 100644 --- a/libi2pd/I2PEndian.h +++ b/libi2pd/I2PEndian.h @@ -5,7 +5,7 @@ #if defined(__FreeBSD__) #include -#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) +#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__GLIBC__) #include #elif defined(__APPLE__) && defined(__MACH__) From 319d748639e870d34700ebcdc9c44a9c7d65a932 Mon Sep 17 00:00:00 2001 From: yangfl Date: Sat, 3 Feb 2018 02:29:28 +0800 Subject: [PATCH 057/119] i2pd.service: do not block system shutdown for 10 min --- contrib/debian/i2pd.service | 28 +--------------------------- contrib/i2pd.service | 29 +++++++++++++++++++++++++++++ contrib/rpm/i2pd.service | 29 +---------------------------- 3 files changed, 31 insertions(+), 55 deletions(-) mode change 100644 => 120000 contrib/debian/i2pd.service create mode 100644 contrib/i2pd.service mode change 100644 => 120000 contrib/rpm/i2pd.service diff --git a/contrib/debian/i2pd.service b/contrib/debian/i2pd.service deleted file mode 100644 index 37f26f14..00000000 --- a/contrib/debian/i2pd.service +++ /dev/null @@ -1,27 +0,0 @@ -[Unit] -Description=I2P Router written in C++ -After=network.target - -[Service] -User=i2pd -Group=i2pd -RuntimeDirectory=i2pd -RuntimeDirectoryMode=0700 -Type=simple -ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service -ExecReload=/bin/kill -HUP $MAINPID -PIDFile=/var/run/i2pd/i2pd.pid -### Uncomment, if auto restart needed -#Restart=on-failure - -### Use SIGINT for graceful stop daemon. -# i2pd stops accepting new tunnels and waits ~10 min while old ones do not die. -KillSignal=SIGINT -TimeoutStopSec=10m - -# If you have problems with hanging i2pd, you can try enable this -#LimitNOFILE=4096 -PrivateDevices=yes - -[Install] -WantedBy=multi-user.target diff --git a/contrib/debian/i2pd.service b/contrib/debian/i2pd.service new file mode 120000 index 00000000..ca477e3b --- /dev/null +++ b/contrib/debian/i2pd.service @@ -0,0 +1 @@ +../i2pd.service \ No newline at end of file diff --git a/contrib/i2pd.service b/contrib/i2pd.service new file mode 100644 index 00000000..5ed31d41 --- /dev/null +++ b/contrib/i2pd.service @@ -0,0 +1,29 @@ +[Unit] +Description=I2P Router written in C++ +Documentation=man:i2pd(1) https://i2pd.readthedocs.io/en/latest/ +After=network.target + +[Service] +User=i2pd +Group=i2pd +RuntimeDirectory=i2pd +RuntimeDirectoryMode=0700 +Type=simple +ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service +ExecReload=/bin/kill -HUP $MAINPID +PIDFile=/var/run/i2pd/i2pd.pid +### Uncomment, if auto restart needed +#Restart=on-failure + +KillSignal=SIGQUIT +# If you have the patience waiting 10 min on restarting/stopping it, uncomment this. +# i2pd stops accepting new tunnels and waits ~10 min while old ones do not die. +#KillSignal=SIGINT +#TimeoutStopSec=10m + +# If you have problems with hanging i2pd, you can try enable this +#LimitNOFILE=4096 +PrivateDevices=yes + +[Install] +WantedBy=multi-user.target diff --git a/contrib/rpm/i2pd.service b/contrib/rpm/i2pd.service deleted file mode 100644 index 8a9c9584..00000000 --- a/contrib/rpm/i2pd.service +++ /dev/null @@ -1,28 +0,0 @@ -[Unit] -Description=I2P Router written in C++ -After=network.target - -[Service] -User=i2pd -Group=i2pd -PermissionsStartOnly=True -RuntimeDirectory=i2pd -RuntimeDirectoryMode=0700 -Type=simple -ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service -ExecReload=/bin/kill -HUP $MAINPID -PIDFile=/var/run/i2pd/i2pd.pid -### Uncomment, if auto restart needed -#Restart=on-failure - -### Use SIGINT for graceful stop daemon. -# i2pd stops accepting new tunnels and waits ~10 min while old ones do not die. -KillSignal=SIGINT -TimeoutStopSec=10m - -# If you have problems with hunging i2pd, you can try enable this -#LimitNOFILE=4096 -PrivateDevices=yes - -[Install] -WantedBy=multi-user.target diff --git a/contrib/rpm/i2pd.service b/contrib/rpm/i2pd.service new file mode 120000 index 00000000..ca477e3b --- /dev/null +++ b/contrib/rpm/i2pd.service @@ -0,0 +1 @@ +../i2pd.service \ No newline at end of file From 87f2eefd35585dbfab375cf62b9e16b670ebecf1 Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Sat, 3 Feb 2018 19:55:32 +0800 Subject: [PATCH 058/119] quit features replaced by stop --- .../org/purplei2p/i2pd/DaemonSingleton.java | 6 +- .../org/purplei2p/i2pd/ForegroundService.java | 2 +- .../i2pd/{I2PD.java => I2PDActivity.java} | 56 ++++++++----------- 3 files changed, 29 insertions(+), 35 deletions(-) rename android/src/org/purplei2p/i2pd/{I2PD.java => I2PDActivity.java} (85%) diff --git a/android/src/org/purplei2p/i2pd/DaemonSingleton.java b/android/src/org/purplei2p/i2pd/DaemonSingleton.java index 65afd0f5..64568f83 100644 --- a/android/src/org/purplei2p/i2pd/DaemonSingleton.java +++ b/android/src/org/purplei2p/i2pd/DaemonSingleton.java @@ -32,7 +32,7 @@ public class DaemonSingleton { private boolean startedOkay; - public static enum State {uninitialized,starting,jniLibraryLoaded,startedOkay,startFailed,gracefulShutdownInProgress}; + public static enum State {uninitialized,starting,jniLibraryLoaded,startedOkay,startFailed,gracefulShutdownInProgress,stopped}; private State state = State.uninitialized; @@ -121,6 +121,10 @@ public class DaemonSingleton { if(isStartedOkay()){ try {I2PD_JNI.stopDaemon();}catch(Throwable tr){Log.e(TAG, "", tr);} setStartedOkay(false); + synchronized (DaemonSingleton.this) { + state = State.stopped; + fireStateUpdate(); + } } } } diff --git a/android/src/org/purplei2p/i2pd/ForegroundService.java b/android/src/org/purplei2p/i2pd/ForegroundService.java index bfd650c8..74761b07 100644 --- a/android/src/org/purplei2p/i2pd/ForegroundService.java +++ b/android/src/org/purplei2p/i2pd/ForegroundService.java @@ -75,7 +75,7 @@ public class ForegroundService extends Service { // The PendingIntent to launch our activity if the user selects this notification PendingIntent contentIntent = PendingIntent.getActivity(this, 0, - new Intent(this, I2PD.class), 0); + new Intent(this, I2PDActivity.class), 0); // Set the info for the views that show in the notification panel. Notification notification = new Notification.Builder(this) diff --git a/android/src/org/purplei2p/i2pd/I2PD.java b/android/src/org/purplei2p/i2pd/I2PDActivity.java similarity index 85% rename from android/src/org/purplei2p/i2pd/I2PD.java rename to android/src/org/purplei2p/i2pd/I2PDActivity.java index a2494b2b..36e992b3 100755 --- a/android/src/org/purplei2p/i2pd/I2PD.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -5,13 +5,11 @@ import java.io.StringWriter; import java.util.Timer; import java.util.TimerTask; -import android.annotation.SuppressLint; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.util.Log; @@ -20,7 +18,7 @@ import android.view.MenuItem; import android.widget.TextView; import android.widget.Toast; -public class I2PD extends Activity { +public class I2PDActivity extends Activity { private static final String TAG = "i2pd"; private TextView textView; @@ -81,11 +79,11 @@ public class I2PD extends Activity { gracefulQuitTimer.cancel(); setGracefulQuitTimer(null); } - try{ - doUnbindService(); - }catch(Throwable tr){ - Log.e(TAG, "", tr); - } +// try{ +// doUnbindService(); +// }catch(Throwable tr){ +// Log.e(TAG, "", tr); +// } } private CharSequence throwableToString(Throwable tr) { @@ -126,7 +124,8 @@ public class I2PD extends Activity { private boolean mIsBound; - private void doBindService() { + private synchronized void doBindService() { + if(mIsBound)return; // Establish a connection with the service. We use an explicit // class name because we want a specific service implementation that // we know will be running in our own process (and thus won't be @@ -159,48 +158,39 @@ public class I2PD extends Activity { int id = item.getItemId(); switch(id){ - case R.id.action_quit: - quit(); + case R.id.action_stop: + i2pdStop(); return true; - case R.id.action_graceful_quit: - gracefulQuit(); + case R.id.action_graceful_stop: + i2pdGracefulStop(); return true; } return super.onOptionsItemSelected(item); } - @SuppressLint("NewApi") - private void quit() { - try { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - finishAndRemoveTask(); - } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - finishAffinity(); - } else { - //moveTaskToBack(true); - finish(); - } - }catch (Throwable tr) { - Log.e(TAG, "", tr); - } + private void i2pdStop() { try{ daemon.stopDaemon(); }catch (Throwable tr) { Log.e(TAG, "", tr); } - System.exit(0); } private Timer gracefulQuitTimer; private final Object gracefulQuitTimerLock = new Object(); - private void gracefulQuit() { + private synchronized void i2pdGracefulStop() { + if(daemon.getState()==DaemonSingleton.State.stopped){ + Toast.makeText(this, R.string.already_stopped, + Toast.LENGTH_SHORT).show(); + return; + } if(getGracefulQuitTimer()!=null){ - Toast.makeText(this, R.string.graceful_quit_is_already_in_progress, + Toast.makeText(this, R.string.graceful_stop_is_already_in_progress, Toast.LENGTH_SHORT).show(); return; } - Toast.makeText(this, R.string.graceful_quit_is_in_progress, + Toast.makeText(this, R.string.graceful_stop_is_in_progress, Toast.LENGTH_SHORT).show(); new Thread(new Runnable(){ @@ -216,12 +206,12 @@ public class I2PD extends Activity { @Override public void run() { - quit(); + i2pdStop(); } }, 10*60*1000/*milliseconds*/); }else{ - quit(); + i2pdStop(); } } catch(Throwable tr) { Log.e(TAG,"",tr); From 1d0791dbf53f84881b8478f6265aa33b588e7014 Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Sat, 3 Feb 2018 19:56:17 +0800 Subject: [PATCH 059/119] quit features replaced by stop - more --- android/res/menu/options_main.xml | 10 +++++----- android/res/values/strings.xml | 9 +++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/android/res/menu/options_main.xml b/android/res/menu/options_main.xml index f66caa2a..aef67c51 100644 --- a/android/res/menu/options_main.xml +++ b/android/res/menu/options_main.xml @@ -2,15 +2,15 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" - tools:context=".I2PD"> + tools:context=".I2PDActivity">
diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml index 0b8bef38..c147a808 100755 --- a/android/res/values/strings.xml +++ b/android/res/values/strings.xml @@ -4,8 +4,9 @@ i2pd started i2pd service started i2pd service stopped - Quit - Graceful Quit - Graceful quit is already in progress - Graceful quit is in progress + Stop + Graceful Stop + Graceful stop is already in progress + Graceful stop is in progress + Already stopped From b88b82a85c9a22d668c84f3fd4ce4509722e9d8d Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Sat, 3 Feb 2018 19:57:21 +0800 Subject: [PATCH 060/119] quit features replaced by stop - more 2 --- android/AndroidManifest.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 3ae952b3..95fff3ff 100755 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -1,20 +1,20 @@ + android:versionName="2.18.0"> - + - From eb3f703b46e895169e7eda5dcd5a677f00b265ef Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Sat, 3 Feb 2018 19:58:09 +0800 Subject: [PATCH 061/119] gradle upgraded; i2pd version name updated --- android/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/android/build.gradle b/android/build.gradle index a88403fd..821dbc16 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -4,7 +4,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.1.2' + classpath 'com.android.tools.build:gradle:2.3.3' } } @@ -18,7 +18,7 @@ android { targetSdkVersion 25 minSdkVersion 14 versionCode 1 - versionName "2.17.1" + versionName "2.18.0" } sourceSets { main { From 21c35f770b26ebf00f94365769bab74753fa06d1 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sat, 3 Feb 2018 13:46:22 -0500 Subject: [PATCH 062/119] fix federoa rawhide build with gcc 8 --- libi2pd/TunnelBase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/TunnelBase.h b/libi2pd/TunnelBase.h index 8b7fb408..97fb2b51 100644 --- a/libi2pd/TunnelBase.h +++ b/libi2pd/TunnelBase.h @@ -59,7 +59,7 @@ namespace tunnel struct TunnelCreationTimeCmp { - bool operator() (std::shared_ptr t1, std::shared_ptr t2) const + bool operator() (const std::shared_ptr & t1, const std::shared_ptr & t2) const { if (t1->GetCreationTime () != t2->GetCreationTime ()) return t1->GetCreationTime () > t2->GetCreationTime (); From 4af0caa50639c9c080034b2ea8239eb7e06f0ba3 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 5 Feb 2018 05:07:26 +0300 Subject: [PATCH 063/119] fix build on GCC 8.0.1 https://bugzilla.redhat.com/show_bug.cgi?id=1541688 --- libi2pd/TunnelBase.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libi2pd/TunnelBase.h b/libi2pd/TunnelBase.h index 97fb2b51..dce3debe 100644 --- a/libi2pd/TunnelBase.h +++ b/libi2pd/TunnelBase.h @@ -59,7 +59,8 @@ namespace tunnel struct TunnelCreationTimeCmp { - bool operator() (const std::shared_ptr & t1, const std::shared_ptr & t2) const + template + bool operator() (const std::shared_ptr & t1, const std::shared_ptr & t2) const { if (t1->GetCreationTime () != t2->GetCreationTime ()) return t1->GetCreationTime () > t2->GetCreationTime (); From f3488be7afcb261502fa95639894193e5204e3a8 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Mon, 5 Feb 2018 05:52:12 +0300 Subject: [PATCH 064/119] update rpm, increase release version for Fedora and CentOS --- contrib/rpm/i2pd-git.spec | 2 +- contrib/rpm/i2pd.spec | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index b2be3b9f..6e02779d 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -2,7 +2,7 @@ Name: i2pd-git Version: 2.18.0 -Release: %{git_hash}.git%{?dist} +Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 469740ce..22c31192 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,6 +1,6 @@ Name: i2pd Version: 2.18.0 -Release: 1%{?dist} +Release: 2%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -96,6 +96,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Mon Feb 05 2018 r4sas - 2.18.0-2 +- Fixed blocking system shutdown for 10 minutes (#1089) + * Thu Feb 01 2018 r4sas - 2.18.0-1 - Added to conflicts i2pd-git package - Fixed release versioning From 5a657cff892fd8075a77d32556f5d1999fd6bf7a Mon Sep 17 00:00:00 2001 From: l-n-s Date: Sun, 4 Feb 2018 23:44:49 -0500 Subject: [PATCH 065/119] Remove broken Dockerfile and it's entrypoint --- Dockerfile | 54 --------------------------------------------------- entrypoint.sh | 24 ----------------------- 2 files changed, 78 deletions(-) delete mode 100644 Dockerfile delete mode 100644 entrypoint.sh diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 4931a709..00000000 --- a/Dockerfile +++ /dev/null @@ -1,54 +0,0 @@ -FROM alpine:latest - -MAINTAINER Mikal Villa - -ENV GIT_BRANCH="master" -ENV I2PD_PREFIX="/opt/i2pd-${GIT_BRANCH}" -ENV PATH=${I2PD_PREFIX}/bin:$PATH - -ENV GOSU_VERSION=1.7 -ENV GOSU_SHASUM="34049cfc713e8b74b90d6de49690fa601dc040021980812b2f1f691534be8a50 /usr/local/bin/gosu" - -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 -# 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. -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 \ - && cd i2pd \ - && make -j4 \ - && mkdir -p ${I2PD_PREFIX}/bin \ - && mv i2pd ${I2PD_PREFIX}/bin/ \ - && cd ${I2PD_PREFIX}/bin \ - && strip i2pd \ - && rm -fr /tmp/build && apk --purge del build-dependendencies build-base fortify-headers boost-dev zlib-dev openssl-dev \ - boost-python3 python3 gdbm boost-unit_test_framework boost-python linux-headers boost-prg_exec_monitor \ - boost-serialization boost-signals boost-wave boost-wserialization boost-math boost-graph boost-regex git pcre \ - libtool g++ gcc pkgconfig - -# 2. Adding required libraries to run i2pd to ensure it will run. -RUN apk --no-cache add boost-filesystem boost-system boost-program_options boost-date_time boost-thread boost-iostreams openssl musl-utils libstdc++ - -# Gosu is a replacement for su/sudo in docker and not a backdoor :) See https://github.com/tianon/gosu -RUN wget -O /usr/local/bin/gosu https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-amd64 \ - && echo "${GOSU_SHASUM}" | sha256sum -c && chmod +x /usr/local/bin/gosu - -COPY entrypoint.sh /entrypoint.sh - -RUN chmod a+x /entrypoint.sh -RUN echo "export PATH=${PATH}" >> /etc/profile - -VOLUME [ "/var/lib/i2pd" ] - -EXPOSE 7070 4444 4447 7656 2827 7654 7650 - -ENTRYPOINT [ "/entrypoint.sh" ] - diff --git a/entrypoint.sh b/entrypoint.sh deleted file mode 100644 index 24a415aa..00000000 --- a/entrypoint.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh - -ARGS="" -if [ "${ENABLE_IPV6}" != "" ]; then - ARGS="${ARGS} –ipv6" -fi - -if [ "${LOGLEVEL}" != "" ]; then - ARGS="${ARGS} –loglevel=${LOGLEVEL}" -fi - -if [ "${ENABLE_AUTH}" != "" ]; then - ARGS="${ARGS} –http.auth" -fi - - -# To make ports exposeable -DEFAULT_ARGS=" –http.address=0.0.0.0 –httpproxy.address=0.0.0.0 -socksproxy.address=0.0.0.0 –sam.address=0.0.0.0 –bob.address=0.0.0.0 –i2cp.address=0.0.0.0 –i2pcontrol.port=0.0.0.0 –upnp.enabled=false -service " - -mkdir -p /var/lib/i2pd && chown -R i2pd:nobody /var/lib/i2pd && chmod u+rw /var/lib/i2pd - -gosu i2pd i2pd $DEFAULT_ARGS $ARGS - - From e77037c2b83d1dc446bf2130effa0861f75d58e6 Mon Sep 17 00:00:00 2001 From: orignal Date: Mon, 5 Feb 2018 11:13:25 -0500 Subject: [PATCH 066/119] fixed warning --- libi2pd/TunnelBase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/TunnelBase.h b/libi2pd/TunnelBase.h index dce3debe..53782ae3 100644 --- a/libi2pd/TunnelBase.h +++ b/libi2pd/TunnelBase.h @@ -66,7 +66,7 @@ namespace tunnel return t1->GetCreationTime () > t2->GetCreationTime (); else return t1 < t2; - }; + } }; } } From 62d9a47c3d60cb5cf224f0159135ef02c3568cc3 Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Wed, 7 Feb 2018 18:23:05 +0800 Subject: [PATCH 067/119] android work 1 --- .../org/purplei2p/i2pd/DaemonSingleton.java | 58 ++++++-------- .../org/purplei2p/i2pd/ForegroundService.java | 8 +- .../src/org/purplei2p/i2pd/I2PDActivity.java | 79 +++++++++---------- 3 files changed, 63 insertions(+), 82 deletions(-) diff --git a/android/src/org/purplei2p/i2pd/DaemonSingleton.java b/android/src/org/purplei2p/i2pd/DaemonSingleton.java index 64568f83..cba29a18 100644 --- a/android/src/org/purplei2p/i2pd/DaemonSingleton.java +++ b/android/src/org/purplei2p/i2pd/DaemonSingleton.java @@ -8,8 +8,8 @@ import android.util.Log; public class DaemonSingleton { private static final String TAG="i2pd"; private static final DaemonSingleton instance = new DaemonSingleton(); - public static interface StateUpdateListener { void daemonStateUpdate(); } - private final Set stateUpdateListeners = new HashSet(); + public interface StateUpdateListener { void daemonStateUpdate(); } + private final Set stateUpdateListeners = new HashSet<>(); public static DaemonSingleton getInstance() { return instance; @@ -18,63 +18,54 @@ public class DaemonSingleton { public synchronized void addStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.add(listener); } public synchronized void removeStateChangeListener(StateUpdateListener listener) { stateUpdateListeners.remove(listener); } + private synchronized void setState(State newState) { + if(newState==null)throw new NullPointerException(); + State oldState = state; + if(oldState==null)throw new NullPointerException(); + if(oldState.equals(newState))return; + state=newState; + fireStateUpdate1(); + } public synchronized void stopAcceptingTunnels() { if(isStartedOkay()){ - state=State.gracefulShutdownInProgress; - fireStateUpdate(); + setState(State.gracefulShutdownInProgress); I2PD_JNI.stopAcceptingTunnels(); } } - public void onNetworkStateChange(boolean isConnected) { - I2PD_JNI.onNetworkStateChanged(isConnected); - } + private volatile boolean startedOkay; - private boolean startedOkay; + public enum State {uninitialized,starting,jniLibraryLoaded,startedOkay,startFailed,gracefulShutdownInProgress,stopped}; - public static enum State {uninitialized,starting,jniLibraryLoaded,startedOkay,startFailed,gracefulShutdownInProgress,stopped}; - - private State state = State.uninitialized; + private volatile State state = State.uninitialized; public State getState() { return state; } - public synchronized void start() { - if(state != State.uninitialized)return; - state = State.starting; - fireStateUpdate(); + { + setState(State.starting); new Thread(new Runnable(){ @Override public void run() { try { I2PD_JNI.loadLibraries(); - synchronized (DaemonSingleton.this) { - state = State.jniLibraryLoaded; - fireStateUpdate(); - } + setState(State.jniLibraryLoaded); } catch (Throwable tr) { lastThrowable=tr; - synchronized (DaemonSingleton.this) { - state = State.startFailed; - fireStateUpdate(); - } + setState(State.startFailed); return; } try { synchronized (DaemonSingleton.this) { daemonStartResult = I2PD_JNI.startDaemon(); if("ok".equals(daemonStartResult)){ - state=State.startedOkay; + setState(State.startedOkay); setStartedOkay(true); - }else state=State.startFailed; - fireStateUpdate(); + }else setState(State.startFailed); } } catch (Throwable tr) { lastThrowable=tr; - synchronized (DaemonSingleton.this) { - state = State.startFailed; - fireStateUpdate(); - } + setState(State.startFailed); return; } } @@ -84,7 +75,7 @@ public class DaemonSingleton { private Throwable lastThrowable; private String daemonStartResult="N/A"; - private synchronized void fireStateUpdate() { + private void fireStateUpdate1() { Log.i(TAG, "daemon state change: "+state); for(StateUpdateListener listener : stateUpdateListeners) { try { @@ -121,10 +112,7 @@ public class DaemonSingleton { if(isStartedOkay()){ try {I2PD_JNI.stopDaemon();}catch(Throwable tr){Log.e(TAG, "", tr);} setStartedOkay(false); - synchronized (DaemonSingleton.this) { - state = State.stopped; - fireStateUpdate(); - } + setState(State.stopped); } } } diff --git a/android/src/org/purplei2p/i2pd/ForegroundService.java b/android/src/org/purplei2p/i2pd/ForegroundService.java index 74761b07..07254439 100644 --- a/android/src/org/purplei2p/i2pd/ForegroundService.java +++ b/android/src/org/purplei2p/i2pd/ForegroundService.java @@ -34,15 +34,13 @@ public class ForegroundService extends Service { // Display a notification about us starting. We put an icon in the status bar. showNotification(); - daemon.start(); // Tell the user we started. - Toast.makeText(this, R.string.i2pd_service_started, Toast.LENGTH_SHORT).show(); +// Toast.makeText(this, R.string.i2pd_service_started, Toast.LENGTH_SHORT).show(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("ForegroundService", "Received start id " + startId + ": " + intent); - daemon.start(); return START_STICKY; } @@ -54,7 +52,7 @@ public class ForegroundService extends Service { stopForeground(true); // Tell the user we stopped. - Toast.makeText(this, R.string.i2pd_service_stopped, Toast.LENGTH_SHORT).show(); +// Toast.makeText(this, R.string.i2pd_service_stopped, Toast.LENGTH_SHORT).show(); } @Override @@ -92,6 +90,6 @@ public class ForegroundService extends Service { startForeground(NOTIFICATION, notification); } - private final DaemonSingleton daemon = DaemonSingleton.getInstance(); + private static final DaemonSingleton daemon = DaemonSingleton.getInstance(); } diff --git a/android/src/org/purplei2p/i2pd/I2PDActivity.java b/android/src/org/purplei2p/i2pd/I2PDActivity.java index 36e992b3..64316112 100755 --- a/android/src/org/purplei2p/i2pd/I2PDActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -23,9 +23,9 @@ public class I2PDActivity extends Activity { private TextView textView; - private final DaemonSingleton daemon = DaemonSingleton.getInstance(); + private static final DaemonSingleton daemon = DaemonSingleton.getInstance(); - private DaemonSingleton.StateUpdateListener daemonStateUpdatedListener = + private final DaemonSingleton.StateUpdateListener daemonStateUpdatedListener = new DaemonSingleton.StateUpdateListener() { @Override @@ -58,7 +58,7 @@ public class I2PDActivity extends Activity { textView = new TextView(this); setContentView(textView); - DaemonSingleton.getInstance().addStateChangeListener(daemonStateUpdatedListener); + daemon.addStateChangeListener(daemonStateUpdatedListener); daemonStateUpdatedListener.daemonStateUpdate(); //set the app be foreground @@ -68,22 +68,18 @@ public class I2PDActivity extends Activity { @Override protected void onDestroy() { super.onDestroy(); - localDestroy(); - } - - private void localDestroy() { - textView = null; - DaemonSingleton.getInstance().removeStateChangeListener(daemonStateUpdatedListener); - Timer gracefulQuitTimer = getGracefulQuitTimer(); - if(gracefulQuitTimer!=null) { - gracefulQuitTimer.cancel(); - setGracefulQuitTimer(null); + textView = null; + daemon.removeStateChangeListener(daemonStateUpdatedListener); + Timer gracefulQuitTimer = getGracefulQuitTimer(); + if(gracefulQuitTimer!=null) { + gracefulQuitTimer.cancel(); + setGracefulQuitTimer(null); + } + try{ + doUnbindService(); + }catch(Throwable tr){ + Log.e(TAG, "", tr); } -// try{ -// doUnbindService(); -// }catch(Throwable tr){ -// Log.e(TAG, "", tr); -// } } private CharSequence throwableToString(Throwable tr) { @@ -122,24 +118,27 @@ public class I2PDActivity extends Activity { }; - private boolean mIsBound; + private static volatile boolean mIsBound; - private synchronized void doBindService() { - if(mIsBound)return; - // Establish a connection with the service. We use an explicit - // 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, - ForegroundService.class), mConnection, Context.BIND_AUTO_CREATE); - mIsBound = true; + private void doBindService() { + synchronized (I2PDActivity.class) { + if (mIsBound) return; + // Establish a connection with the service. We use an explicit + // 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, ForegroundService.class), mConnection, Context.BIND_AUTO_CREATE); + mIsBound = true; + } } private void doUnbindService() { - if (mIsBound) { - // Detach our existing connection. - unbindService(mConnection); - mIsBound = false; + synchronized (I2PDActivity.class) { + if (mIsBound) { + // Detach our existing connection. + unbindService(mConnection); + mIsBound = false; + } } } @@ -177,9 +176,9 @@ public class I2PDActivity extends Activity { } } - private Timer gracefulQuitTimer; - private final Object gracefulQuitTimerLock = new Object(); - private synchronized void i2pdGracefulStop() { + private volatile Timer gracefulQuitTimer; + + private void i2pdGracefulStop() { if(daemon.getState()==DaemonSingleton.State.stopped){ Toast.makeText(this, R.string.already_stopped, Toast.LENGTH_SHORT).show(); @@ -218,18 +217,14 @@ public class I2PDActivity extends Activity { } } - },"gracQuitInit").start(); + },"gracInit").start(); } private Timer getGracefulQuitTimer() { - synchronized (gracefulQuitTimerLock) { - return gracefulQuitTimer; - } + return gracefulQuitTimer; } private void setGracefulQuitTimer(Timer gracefulQuitTimer) { - synchronized (gracefulQuitTimerLock) { - this.gracefulQuitTimer = gracefulQuitTimer; - } + this.gracefulQuitTimer = gracefulQuitTimer; } } From 0994211a48a77329282f0deeec4e37b67ffcd120 Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Wed, 7 Feb 2018 18:24:51 +0800 Subject: [PATCH 068/119] android gitignore --- android/.gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/android/.gitignore b/android/.gitignore index d9fa5a57..efb83e7b 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -5,4 +5,5 @@ ant.properties local.properties build.sh bin -log* \ No newline at end of file +log* +.gradle android.iml build gradle gradlew gradlew.bat From 1b56d66fc80147e0e91b6774ef63bfa81e05aa48 Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Wed, 7 Feb 2018 18:25:36 +0800 Subject: [PATCH 069/119] android gitignore --- android/.gitignore | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/android/.gitignore b/android/.gitignore index efb83e7b..90cd315e 100644 --- a/android/.gitignore +++ b/android/.gitignore @@ -6,4 +6,10 @@ local.properties build.sh bin log* -.gradle android.iml build gradle gradlew gradlew.bat +.gradle +android.iml +build +gradle +gradlew +gradlew.bat + From 33735b343d1205d5d4ead28d537146ba66e94334 Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Wed, 7 Feb 2018 19:24:43 +0800 Subject: [PATCH 070/119] fixes 1094; fixes grac stop --- android/res/values/strings.xml | 11 ++- .../org/purplei2p/i2pd/DaemonSingleton.java | 20 ++++- .../org/purplei2p/i2pd/ForegroundService.java | 40 ++++++++-- .../src/org/purplei2p/i2pd/I2PDActivity.java | 73 ++++++++++++++----- 4 files changed, 118 insertions(+), 26 deletions(-) diff --git a/android/res/values/strings.xml b/android/res/values/strings.xml index c147a808..1421b261 100755 --- a/android/res/values/strings.xml +++ b/android/res/values/strings.xml @@ -1,12 +1,17 @@ i2pd - i2pd started - i2pd service started - i2pd service stopped Stop Graceful Stop Graceful stop is already in progress Graceful stop is in progress Already stopped + i2pd initializing + i2pd is starting + i2pd: loaded JNI libraries + i2pd started + i2pd start failed + i2pd: graceful shutdown in progress + i2pd has stopped + remaining diff --git a/android/src/org/purplei2p/i2pd/DaemonSingleton.java b/android/src/org/purplei2p/i2pd/DaemonSingleton.java index cba29a18..4f3e62f7 100644 --- a/android/src/org/purplei2p/i2pd/DaemonSingleton.java +++ b/android/src/org/purplei2p/i2pd/DaemonSingleton.java @@ -35,7 +35,25 @@ public class DaemonSingleton { private volatile boolean startedOkay; - public enum State {uninitialized,starting,jniLibraryLoaded,startedOkay,startFailed,gracefulShutdownInProgress,stopped}; + public enum State { + uninitialized(R.string.uninitialized), + starting(R.string.starting), + jniLibraryLoaded(R.string.jniLibraryLoaded), + startedOkay(R.string.startedOkay), + startFailed(R.string.startFailed), + gracefulShutdownInProgress(R.string.gracefulShutdownInProgress), + stopped(R.string.stopped); + + State(int statusStringResourceId) { + this.statusStringResourceId = statusStringResourceId; + } + + private final int statusStringResourceId; + + public int getStatusStringResourceId() { + return statusStringResourceId; + } + }; private volatile State state = State.uninitialized; diff --git a/android/src/org/purplei2p/i2pd/ForegroundService.java b/android/src/org/purplei2p/i2pd/ForegroundService.java index 07254439..6116b982 100644 --- a/android/src/org/purplei2p/i2pd/ForegroundService.java +++ b/android/src/org/purplei2p/i2pd/ForegroundService.java @@ -11,11 +11,32 @@ import android.util.Log; import android.widget.Toast; public class ForegroundService extends Service { + private static final String TAG="FgService"; + + private volatile boolean shown; + + private final DaemonSingleton.StateUpdateListener daemonStateUpdatedListener = + new DaemonSingleton.StateUpdateListener() { + + @Override + public void daemonStateUpdate() { + try { + synchronized (ForegroundService.this) { + if (shown) cancelNotification(); + showNotification(); + } + } catch (Throwable tr) { + Log.e(TAG,"error ignored",tr); + } + } + }; + + private NotificationManager notificationManager; // Unique Identification Number for the Notification. // We use it on Notification start, and to cancel it. - private int NOTIFICATION = R.string.i2pd_started; + private int NOTIFICATION = 1; /** * Class for clients to access. Because we know this service always @@ -32,8 +53,10 @@ public class ForegroundService extends Service { public void onCreate() { notificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); - // Display a notification about us starting. We put an icon in the status bar. - showNotification(); + synchronized (this) { + DaemonSingleton.getInstance().addStateChangeListener(daemonStateUpdatedListener); + if (!shown) daemonStateUpdatedListener.daemonStateUpdate(); + } // Tell the user we started. // Toast.makeText(this, R.string.i2pd_service_started, Toast.LENGTH_SHORT).show(); } @@ -46,6 +69,11 @@ public class ForegroundService extends Service { @Override public void onDestroy() { + DaemonSingleton.getInstance().removeStateChangeListener(daemonStateUpdatedListener); + cancelNotification(); + } + + private synchronized void cancelNotification() { // Cancel the persistent notification. notificationManager.cancel(NOTIFICATION); @@ -53,6 +81,7 @@ public class ForegroundService extends Service { // Tell the user we stopped. // Toast.makeText(this, R.string.i2pd_service_stopped, Toast.LENGTH_SHORT).show(); + shown=false; } @Override @@ -67,9 +96,9 @@ public class ForegroundService extends Service { /** * Show a notification while this service is running. */ - private void showNotification() { + private synchronized void showNotification() { // In this sample, we'll use the same text for the ticker and the expanded notification - CharSequence text = getText(R.string.i2pd_started); + CharSequence text = getText(DaemonSingleton.getInstance().getState().getStatusStringResourceId()); // The PendingIntent to launch our activity if the user selects this notification PendingIntent contentIntent = PendingIntent.getActivity(this, 0, @@ -88,6 +117,7 @@ public class ForegroundService extends Service { // Send the notification. //mNM.notify(NOTIFICATION, notification); startForeground(NOTIFICATION, notification); + shown=true; } private static final DaemonSingleton daemon = DaemonSingleton.getInstance(); diff --git a/android/src/org/purplei2p/i2pd/I2PDActivity.java b/android/src/org/purplei2p/i2pd/I2PDActivity.java index 64316112..af0c8000 100755 --- a/android/src/org/purplei2p/i2pd/I2PDActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -19,9 +19,10 @@ import android.widget.TextView; import android.widget.Toast; public class I2PDActivity extends Activity { - private static final String TAG = "i2pd"; + private static final String TAG = "i2pdActvt"; + public static final int GRACEFUL_DELAY_MILLIS = 10 * 60 * 1000; - private TextView textView; + private TextView textView; private static final DaemonSingleton daemon = DaemonSingleton.getInstance(); @@ -42,8 +43,11 @@ public class I2PDActivity extends Activity { return; } DaemonSingleton.State state = daemon.getState(); - textView.setText(String.valueOf(state)+ - (DaemonSingleton.State.startFailed.equals(state)?": "+daemon.getDaemonStartResult():"")); + textView.setText( + String.valueOf(state)+ + (DaemonSingleton.State.startFailed.equals(state)?": "+daemon.getDaemonStartResult():"")+ + (DaemonSingleton.State.gracefulShutdownInProgress.equals(state)?": "+formatGraceTimeRemaining()+" "+getText(R.string.remaining):"") + ); } catch (Throwable tr) { Log.e(TAG,"error ignored",tr); } @@ -51,6 +55,18 @@ public class I2PDActivity extends Activity { }); } }; + private volatile long graceStartedMillis; + private final Object graceStartedMillis_LOCK=new Object(); + + private String formatGraceTimeRemaining() { + long remainingSeconds; + synchronized (graceStartedMillis_LOCK){ + remainingSeconds=Math.round(Math.max(0,graceStartedMillis+GRACEFUL_DELAY_MILLIS-System.currentTimeMillis())/1000.0D); + } + long remainingMinutes=(long)Math.floor(remainingSeconds/60.0D); + long remSec=remainingSeconds-remainingMinutes*60; + return remainingMinutes+":"+(remSec/10)+remSec%10; + } @Override public void onCreate(Bundle savedInstanceState) { @@ -70,11 +86,7 @@ public class I2PDActivity extends Activity { super.onDestroy(); textView = null; daemon.removeStateChangeListener(daemonStateUpdatedListener); - Timer gracefulQuitTimer = getGracefulQuitTimer(); - if(gracefulQuitTimer!=null) { - gracefulQuitTimer.cancel(); - setGracefulQuitTimer(null); - } + cancelGracefulStop(); try{ doUnbindService(); }catch(Throwable tr){ @@ -82,7 +94,15 @@ public class I2PDActivity extends Activity { } } - private CharSequence throwableToString(Throwable tr) { + private void cancelGracefulStop() { + Timer gracefulQuitTimer = getGracefulQuitTimer(); + if(gracefulQuitTimer!=null) { + gracefulQuitTimer.cancel(); + setGracefulQuitTimer(null); + } + } + + private CharSequence throwableToString(Throwable tr) { StringWriter sw = new StringWriter(8192); PrintWriter pw = new PrintWriter(sw); tr.printStackTrace(pw); @@ -169,11 +189,20 @@ public class I2PDActivity extends Activity { } private void i2pdStop() { - try{ - daemon.stopDaemon(); - }catch (Throwable tr) { - Log.e(TAG, "", tr); - } + cancelGracefulStop(); + new Thread(new Runnable(){ + + @Override + public void run() { + Log.d(TAG, "stopping"); + try{ + daemon.stopDaemon(); + }catch (Throwable tr) { + Log.e(TAG, "", tr); + } + } + + },"stop").start(); } private volatile Timer gracefulQuitTimer; @@ -199,8 +228,11 @@ public class I2PDActivity extends Activity { Log.d(TAG, "grac stopping"); if(daemon.isStartedOkay()) { daemon.stopAcceptingTunnels(); - Timer gracefulQuitTimer = new Timer(true); + final Timer gracefulQuitTimer = new Timer(true); setGracefulQuitTimer(gracefulQuitTimer); + synchronized (graceStartedMillis_LOCK) { + graceStartedMillis = System.currentTimeMillis(); + } gracefulQuitTimer.schedule(new TimerTask(){ @Override @@ -208,7 +240,14 @@ public class I2PDActivity extends Activity { i2pdStop(); } - }, 10*60*1000/*milliseconds*/); + }, GRACEFUL_DELAY_MILLIS); + final TimerTask tickerTask = new TimerTask() { + @Override + public void run() { + daemonStateUpdatedListener.daemonStateUpdate(); + } + }; + gracefulQuitTimer.scheduleAtFixedRate(tickerTask,0/*start delay*/,1000/*millis period*/); }else{ i2pdStop(); } From 56f6e57118a58bc2d7c2a6ab73b6ad627bbb036a Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Wed, 7 Feb 2018 19:54:19 +0800 Subject: [PATCH 071/119] fixes grac stop --- .../src/org/purplei2p/i2pd/I2PDActivity.java | 70 ++++++++++++------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/android/src/org/purplei2p/i2pd/I2PDActivity.java b/android/src/org/purplei2p/i2pd/I2PDActivity.java index af0c8000..840e0bfa 100755 --- a/android/src/org/purplei2p/i2pd/I2PDActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -20,7 +20,7 @@ import android.widget.Toast; public class I2PDActivity extends Activity { private static final String TAG = "i2pdActvt"; - public static final int GRACEFUL_DELAY_MILLIS = 10 * 60 * 1000; + public static final int GRACEFUL_DELAY_MILLIS = 120 * 1000; private TextView textView; @@ -55,10 +55,10 @@ public class I2PDActivity extends Activity { }); } }; - private volatile long graceStartedMillis; - private final Object graceStartedMillis_LOCK=new Object(); + private static volatile long graceStartedMillis; + private static final Object graceStartedMillis_LOCK=new Object(); - private String formatGraceTimeRemaining() { + private static String formatGraceTimeRemaining() { long remainingSeconds; synchronized (graceStartedMillis_LOCK){ remainingSeconds=Math.round(Math.max(0,graceStartedMillis+GRACEFUL_DELAY_MILLIS-System.currentTimeMillis())/1000.0D); @@ -79,6 +79,15 @@ public class I2PDActivity extends Activity { //set the app be foreground doBindService(); + + final Timer gracefulQuitTimer = getGracefulQuitTimer(); + if(gracefulQuitTimer!=null){ + long gracefulStopAtMillis; + synchronized (graceStartedMillis_LOCK) { + gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS; + } + rescheduleGraceStop(gracefulQuitTimer, gracefulStopAtMillis); + } } @Override @@ -86,7 +95,7 @@ public class I2PDActivity extends Activity { super.onDestroy(); textView = null; daemon.removeStateChangeListener(daemonStateUpdatedListener); - cancelGracefulStop(); + //cancelGracefulStop(); try{ doUnbindService(); }catch(Throwable tr){ @@ -94,7 +103,7 @@ public class I2PDActivity extends Activity { } } - private void cancelGracefulStop() { + private static void cancelGracefulStop() { Timer gracefulQuitTimer = getGracefulQuitTimer(); if(gracefulQuitTimer!=null) { gracefulQuitTimer.cancel(); @@ -205,7 +214,7 @@ public class I2PDActivity extends Activity { },"stop").start(); } - private volatile Timer gracefulQuitTimer; + private static volatile Timer gracefulQuitTimer; private void i2pdGracefulStop() { if(daemon.getState()==DaemonSingleton.State.stopped){ @@ -228,26 +237,12 @@ public class I2PDActivity extends Activity { Log.d(TAG, "grac stopping"); if(daemon.isStartedOkay()) { daemon.stopAcceptingTunnels(); - final Timer gracefulQuitTimer = new Timer(true); - setGracefulQuitTimer(gracefulQuitTimer); + long gracefulStopAtMillis; synchronized (graceStartedMillis_LOCK) { graceStartedMillis = System.currentTimeMillis(); + gracefulStopAtMillis = graceStartedMillis + GRACEFUL_DELAY_MILLIS; } - gracefulQuitTimer.schedule(new TimerTask(){ - - @Override - public void run() { - i2pdStop(); - } - - }, GRACEFUL_DELAY_MILLIS); - final TimerTask tickerTask = new TimerTask() { - @Override - public void run() { - daemonStateUpdatedListener.daemonStateUpdate(); - } - }; - gracefulQuitTimer.scheduleAtFixedRate(tickerTask,0/*start delay*/,1000/*millis period*/); + rescheduleGraceStop(null,gracefulStopAtMillis); }else{ i2pdStop(); } @@ -259,11 +254,32 @@ public class I2PDActivity extends Activity { },"gracInit").start(); } - private Timer getGracefulQuitTimer() { + private void rescheduleGraceStop(Timer gracefulQuitTimerOld, long gracefulStopAtMillis) { + if(gracefulQuitTimerOld!=null)gracefulQuitTimerOld.cancel(); + final Timer gracefulQuitTimer = new Timer(true); + setGracefulQuitTimer(gracefulQuitTimer); + gracefulQuitTimer.schedule(new TimerTask(){ + + @Override + public void run() { + i2pdStop(); + } + + }, Math.max(0,gracefulStopAtMillis-System.currentTimeMillis())); + final TimerTask tickerTask = new TimerTask() { + @Override + public void run() { + daemonStateUpdatedListener.daemonStateUpdate(); + } + }; + gracefulQuitTimer.scheduleAtFixedRate(tickerTask,0/*start delay*/,1000/*millis period*/); + } + + private static Timer getGracefulQuitTimer() { return gracefulQuitTimer; } - private void setGracefulQuitTimer(Timer gracefulQuitTimer) { - this.gracefulQuitTimer = gracefulQuitTimer; + private static void setGracefulQuitTimer(Timer gracefulQuitTimer) { + I2PDActivity.gracefulQuitTimer = gracefulQuitTimer; } } From ac495da5fe6c8e688329bab0142392e56fe51dac Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Wed, 7 Feb 2018 19:56:44 +0800 Subject: [PATCH 072/119] fixes grac stop --- android/src/org/purplei2p/i2pd/I2PDActivity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/src/org/purplei2p/i2pd/I2PDActivity.java b/android/src/org/purplei2p/i2pd/I2PDActivity.java index 840e0bfa..99672eb7 100755 --- a/android/src/org/purplei2p/i2pd/I2PDActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -20,7 +20,7 @@ import android.widget.Toast; public class I2PDActivity extends Activity { private static final String TAG = "i2pdActvt"; - public static final int GRACEFUL_DELAY_MILLIS = 120 * 1000; + public static final int GRACEFUL_DELAY_MILLIS = 10 * 60 * 1000; private TextView textView; From badb837b46b299419ac1d3091d0bbebdcb90be33 Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Wed, 7 Feb 2018 23:20:50 +0800 Subject: [PATCH 073/119] fixed #1088 --- android/AndroidManifest.xml | 10 +- android/build.gradle | 22 +++- android/res/layout/activity_perms_asker.xml | 27 ++++ android/res/values/template-dimens.xml | 16 +++ .../src/org/purplei2p/i2pd/I2PDActivity.java | 3 +- .../i2pd/I2PDPermsAskerActivity.java | 121 ++++++++++++++++++ 6 files changed, 190 insertions(+), 9 deletions(-) create mode 100644 android/res/layout/activity_perms_asker.xml create mode 100644 android/res/values/template-dimens.xml create mode 100644 android/src/org/purplei2p/i2pd/I2PDPermsAskerActivity.java diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 95fff3ff..df817b82 100755 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -6,21 +6,21 @@ android:versionName="2.18.0"> - - - + + + - + + diff --git a/android/build.gradle b/android/build.gradle index 821dbc16..750ae008 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,15 +1,31 @@ buildscript { repositories { - mavenCentral() - jcenter() + mavenCentral() + jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:2.3.3' } } apply plugin: 'com.android.application' +repositories { + jcenter() + maven { + url 'https://maven.google.com' + } +} + +dependencies { +// compile "com.android.support:support-v4:26.1.0" +// compile "com.android.support:support-v13:26.1.0" +// compile "com.android.support:cardview-v7:26.1.0" +// compile "com.android.support:appcompat-v7:26.1.0" + compile 'com.android.support:support-v4:25.3.1' + compile 'com.android.support:design:25.3.1' +} + android { compileSdkVersion 25 buildToolsVersion "25.0.2" diff --git a/android/res/layout/activity_perms_asker.xml b/android/res/layout/activity_perms_asker.xml new file mode 100644 index 00000000..d2d12cb6 --- /dev/null +++ b/android/res/layout/activity_perms_asker.xml @@ -0,0 +1,27 @@ + + + + +