Compare commits

..

1 Commits

Author SHA1 Message Date
R4SAS
3ab5ac66b6 modulize client protocols
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-05-03 17:20:19 +03:00
126 changed files with 4556 additions and 9408 deletions

View File

@@ -1,32 +0,0 @@
name: Build Debian packages
on: [push, pull_request]
jobs:
build:
name: ${{ matrix.dist }}
runs-on: ubuntu-latest
strategy:
matrix:
dist: ['buster', 'bullseye', 'bookworm']
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: change debian changelog
run: |
sudo apt-get update
sudo apt-get install devscripts
debchange -v "`git describe --tags`-${{ matrix.dist }}" -b -M --distribution ${{ matrix.dist }} "trunk build"
- uses: jtdor/build-deb-action@v1
with:
docker-image: debian:${{ matrix.dist }}-slim
buildpackage-opts: --build=binary --no-sign
- uses: actions/upload-artifact@v3
with:
name: i2pd_${{ matrix.dist }}
path: debian/artifacts/i2pd_*.deb
- uses: actions/upload-artifact@v3
with:
name: i2pd-dbgsym_${{ matrix.dist }}
path: debian/artifacts/i2pd-dbgsym_*.deb

View File

@@ -4,25 +4,18 @@ on: [push, pull_request]
jobs:
build:
runs-on: macos-12
runs-on: macos-10.15
name: with UPnP
steps:
- uses: actions/checkout@v2
- name: Test in FreeBSD
id: test
uses: vmactions/freebsd-vm@v0.3.0
uses: vmactions/freebsd-vm@v0.1.5
with:
usesh: true
mem: 2048
sync: rsync
copyback: true
prepare: pkg install -y devel/cmake devel/gmake devel/boost-libs security/openssl net/miniupnpc
prepare: pkg install -y devel/cmake devel/gmake devel/boost-libs security/openssl net/miniupnpc
run: |
cd build
cmake -DWITH_UPNP=ON -DCMAKE_BUILD_TYPE=Release .
gmake -j2
- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: i2pd-freebsd
path: build/i2pd

View File

@@ -38,3 +38,51 @@ jobs:
cd build
cmake -DWITH_UPNP=${{ matrix.with_upnp }} .
make -j3
build-deb-stretch:
name: Build package for stretch
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: change debian changelog
run: |
sudo apt-get update
sudo apt-get install devscripts
debchange -v "`git describe --tags`-stretch" -b -M --distribution stretch "trunk build"
- uses: singingwolfboy/build-dpkg-stretch@v1
id: build
with:
args: --unsigned-source --unsigned-changes -b
- uses: actions/upload-artifact@v1
with:
name: ${{ steps.build.outputs.filename }}
path: ${{ steps.build.outputs.filename }}
- uses: actions/upload-artifact@v1
with:
name: ${{ steps.build.outputs.filename-dbgsym }}
path: ${{ steps.build.outputs.filename-dbgsym }}
build-deb-buster:
name: Build package for buster
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: change debian changelog
run: |
sudo apt-get update
sudo apt-get install devscripts
debchange -v "`git describe --tags`-buster" -b -M --distribution buster "trunk build"
- uses: singingwolfboy/build-dpkg-buster@v1
id: build
with:
args: --unsigned-source --unsigned-changes -b
- uses: actions/upload-artifact@v1
with:
name: ${{ steps.build.outputs.filename }}
path: ${{ steps.build.outputs.filename }}
- uses: actions/upload-artifact@v1
with:
name: ${{ steps.build.outputs.filename-dbgsym }}
path: ${{ steps.build.outputs.filename-dbgsym }}

View File

@@ -1,140 +1,63 @@
name: Build containers
on:
push:
branches:
- openssl
- docker
tags:
- '*'
on: [push]
jobs:
build:
docker:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
strategy:
matrix:
include: [
{ platform: 'linux/amd64', archname: 'amd64' },
{ platform: 'linux/386', archname: 'i386' },
{ platform: 'linux/arm64', archname: 'arm64' },
{ platform: 'linux/arm/v7', archname: 'armv7' },
]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
uses: docker/setup-buildx-action@v1
- name: Login to DockerHub
uses: docker/login-action@v2
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container registry
uses: docker/login-action@v2
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build container for ${{ matrix.archname }}
uses: docker/build-push-action@v3
- name: Build and push trunk container
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
uses: docker/build-push-action@v2
with:
context: ./contrib/docker
file: ./contrib/docker/Dockerfile
platforms: ${{ matrix.platform }}
platforms: linux/amd64,linux/386,linux/arm64,linux/arm/v7
push: true
tags: |
purplei2p/i2pd:latest-${{ matrix.archname }}
ghcr.io/purplei2p/i2pd:latest-${{ matrix.archname }}
purplei2p/i2pd:latest
ghcr.io/purplei2p/i2pd:latest
push:
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
needs: build
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create and push latest manifest image to Docker Hub
uses: Noelware/docker-manifest-action@master
with:
base-image: purplei2p/i2pd:latest
extra-images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7
push: true
- name: Create and push latest manifest image to GHCR
uses: Noelware/docker-manifest-action@master
with:
base-image: ghcr.io/purplei2p/i2pd:latest
extra-images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7
push: true
- name: Store release version to env
- name: Set env
if: ${{ startsWith(github.ref, 'refs/tags/') }}
run: echo "RELEASE_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV
- name: Create and push release manifest image to Docker Hub
- name: Build and push release container
if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
uses: docker/build-push-action@v2
with:
base-image: purplei2p/i2pd:latest-release
extra-images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7
push: true
- name: Create and push release manifest image to GHCR
if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
base-image: ghcr.io/purplei2p/i2pd:latest-release
extra-images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7
push: true
- name: Create and push versioned manifest image to Docker Hub
if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
base-image: purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
extra-images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7
push: true
- name: Create and push versioned manifest image to GHCR
if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
base-image: ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
extra-images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7
context: ./contrib/docker
file: ./contrib/docker/Dockerfile
platforms: linux/amd64,linux/386,linux/arm64,linux/arm/v7
push: true
tags: |
purplei2p/i2pd:latest
purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
ghcr.io/purplei2p/i2pd:latest
ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}

View File

@@ -1,100 +1,6 @@
# for this file format description,
# see https://github.com/olivierlacan/keep-a-changelog
## [2.44.0] - 2022-11-20
### Added
- SSL connection for server I2P tunnels
- Localization to Italian and Spanish
- SSU2 through SOCKS5 UDP proxy
- Reload tunnels through web console
- SSU2 send immediate ack request flag
- SSU2 send and verify path challenge
- Configurable ssu2.mtu4 and ssu2.mtu6
### Changed
- SSU2 is enbaled and SSU is disabled by default
- Separate network status and error
- Random selection between NTCP2 and SSU2 priority
- Added notbob.i2p to jump services
- Remove DoNotTrack flag from HTTP Request header
- Skip addresshelper page if destination was not changed
- SSU2 allow different ports from RelayReponse and HolePunch
- SSU2 resend PeerTest msg 1 and msg 2
- SSU2 Send Retry instead SessionCreated if clock skew detected
### Fixed
- Long HTTP headers for HTTP proxy and HTTP server tunnel
- SSU2 resends and resend limits
- Crash at startup if addressbook is disabled
- NTCP2 ipv6 connection through SOCKS5 proxy
- SSU2 SessionRequest with zero token
- SSU2 MTU less than 1280
- SSU2 port=1
- Incorrect addresses from network interfaces
- Definitions for Darwin PPC; do not use pthread_setname_np
## [2.43.0] - 2022-08-22
### Added
- Complete SSU2 implementation
- Localization to Chinese
- Send RouterInfo update for long live sessions
- Explicit ipv6 ranges of known tunnel brokers for MTU detection
- Always send "Connection: close" and strip out Keep-Alive for server HTTP tunnel
- Show ports for all transports in web console
- Translation of webconsole site title
- Support for Windows ProgramData path when running as service
- Ability to turn off address book
- Handle signals TSTP and CONT to stop and resume network
### Changed
- Case insensitive headers for server HTTP tunnel
- Do not show 'Address registration' line if LeaseSet is encrypted
- SSU2 transports have higher priority than SSU
- Disable ElGamal precalculated table if no SSU
- Deprecate limits.ntcpsoft, limits.ntcphard and limits.ntcpthreads config options
- SSU2 is enabled and SSU is disabled by default for new installations
### Fixed
- Typo with Referer header name in HTTP proxy
- Can't handle garlic message from an exploratory tunnel
- Incorrect encryption key for exploratory lookup reply
- Bound checks issues in LeaseSets code
- MTU detection on Windows
- Crash on stop of active server tunnel
- Send datagram to wrong destination in SAM
- Incorrect static key in RouterInfo if the keys were regenerated
- Duplicated sessions in BOB
## [2.42.1] - 2022-05-24
### Fixed
- Incorrect jump link in HTTP Proxy
## [2.42.0] - 2022-05-22
### Added
- Preliminary SSU2 implementation
- Tunnel length variance
- Localization to French
- Daily cleanup of obsolete peer profiles
- Ordered jump services list in HTTP proxy
- Win32 service
- Show port for local non-published SSU addresses in web console
### Changed
- Maximum RouterInfo length increased to 3K
- Skip unknown addresses in RouterInfo
- Don't pick own router for peer test
- Reseeds list
- Internal numeric id for families
- Use ipv6 preference only when netinet headers not used
- Close stream if delete requested
- Remove version from title in web console
- Drop MESHNET build option
- Set data path before initialization
- Don't show registration block in web console if token is not provided
### Fixed
- Encrypted LeaseSet for EdDSA signature
- Clients tunnels are not built if clock is not synced on start
- Incorrect processing of i2cp.dontPublishLeaseSet param
- UDP tunnels reload
- Build for LibreSSL 3.5.2
- Race condition in short tunnel build message
- Race condition in local RouterInfo buffer allocation
## [2.41.0] - 2022-02-20
### Added
- Clock syncronization through SSU
@@ -441,7 +347,7 @@
### Added
- Client auth flag for b33 address
### Changed
- Remove incoming NTCP2 session from pending list when established
- Remove incoming NTCP2 session from pending list when established
- Handle errors for NTCP2 SessionConfrimed send
### Fixed
- Failure to start on Windows XP
@@ -745,7 +651,7 @@
### Added
- Datagram i2p tunnels
- Unique local addresses for server tunnels
- Configurable list of reseed servers and initial addressbook
- Configurable list of reseed servers and initial addressbook
- Configurable netid
- Initial iOS support

View File

@@ -4,7 +4,7 @@ SYS := $(shell $(CXX) -dumpmachine)
ifneq (, $(findstring darwin, $(SYS)))
SHARED_SUFFIX = dylib
else ifneq (, $(findstring mingw, $(SYS))$(findstring windows-gnu, $(SYS))$(findstring cygwin, $(SYS)))
else ifneq (, $(findstring mingw, $(SYS))$(findstring cygwin, $(SYS)))
SHARED_SUFFIX = dll
else
SHARED_SUFFIX = so
@@ -40,6 +40,12 @@ USE_GIT_VERSION := $(or $(USE_GIT_VERSION),no)
# for MacOS only, waiting for "1", not "yes"
HOMEBREW := $(or $(HOMEBREW),0)
# Client protocols
USE_I2PC := $(or $(USE_I2PC),yes)
USE_I2CP := $(or $(USE_I2CP),yes)
USE_SAM := $(or $(USE_SAM),yes)
USE_BOB := $(or $(USE_BOB),yes)
ifeq ($(DEBUG),yes)
CXX_DEBUG = -g
else
@@ -47,6 +53,19 @@ else
LD_DEBUG = -s
endif
ifeq ($(USE_I2PC),yes)
NEEDED_CXXFLAGS += -DWITH_I2PC
endif
ifeq ($(USE_I2CP),yes)
NEEDED_CXXFLAGS += -DWITH_I2CP
endif
ifeq ($(USE_SAM),yes)
NEEDED_CXXFLAGS += -DWITH_SAM
endif
ifeq ($(USE_BOB),yes)
NEEDED_CXXFLAGS += -DWITH_BOB
endif
ifneq (, $(findstring darwin, $(SYS)))
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
ifeq ($(HOMEBREW),1)
@@ -60,7 +79,7 @@ else ifneq (, $(findstring linux, $(SYS))$(findstring gnu, $(SYS)))
else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS)))
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
include Makefile.bsd
else ifneq (, $(findstring mingw, $(SYS))$(findstring windows-gnu, $(SYS))$(findstring cygwin, $(SYS)))
else ifneq (, $(findstring mingw, $(SYS))$(findstring cygwin, $(SYS)))
DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32App.cpp Win32/Win32Service.cpp Win32/Win32NetState.cpp
include Makefile.mingw
else # not supported
@@ -72,7 +91,7 @@ ifeq ($(USE_GIT_VERSION),yes)
NEEDED_CXXFLAGS += -DGITVER=\"$(GIT_VERSION)\"
endif
NEEDED_CXXFLAGS += -MMD -MP -I$(LIB_SRC_DIR) -I$(LIB_CLIENT_SRC_DIR) -I$(LANG_SRC_DIR) -DOPENSSL_SUPPRESS_DEPRECATED
NEEDED_CXXFLAGS += -MMD -MP -I$(LIB_SRC_DIR) -I$(LIB_CLIENT_SRC_DIR) -I$(LANG_SRC_DIR)
LIB_OBJS += $(patsubst %.cpp,obj/%.o,$(LIB_SRC))
LIB_CLIENT_OBJS += $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC))

View File

@@ -39,18 +39,13 @@ ifeq ($(USE_AESNI),yes)
endif
install: all
install -d ${PREFIX}/bin
install -m 755 ${I2PD} ${PREFIX}/bin
install -d ${PREFIX}/etc ${PREFIX}/etc/i2pd ${PREFIX}/etc/i2pd/tunnels.conf.d
install -d ${PREFIX}/bin ${PREFIX}/etc/i2pd ${PREFIX}/etc/i2pd/tunnels.conf.d ${PREFIX}/share/doc/i2pd ${PREFIX}/share/i2pd ${PREFIX}/share/man/man1 ${PREFIX}/var/lib/i2pd
install -m 755 ${I2PD} ${PREFIX}/bin/
install -m 644 contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/etc/i2pd
install -d ${PREFIX}/share ${PREFIX}/share/doc ${PREFIX}/share/doc/i2pd
install -m 644 ChangeLog LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/share/doc/i2pd
install -d ${PREFIX}/share/i2pd
@cp -R contrib/certificates ${PREFIX}/share/i2pd/
install -d ${PREFIX}/share/man ${PREFIX}/share/man/man1
install -m 644 ChangeLog LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/share/doc/i2pd
@gzip -kf debian/i2pd.1 && install debian/i2pd.1.gz ${PREFIX}/share/man/man1
install -d ${PREFIX}/var ${PREFIX}/var/lib ${PREFIX}/var/lib/i2pd
@ln -sf ${PREFIX}/share/i2pd/certificates ${PREFIX}/var/lib/i2pd/certificates
@ln -sf ${PREFIX}/share/i2pd/certificates ${PREFIX}/var/lib/i2pd/
@ln -sf ${PREFIX}/etc/i2pd/tunnels.conf.d ${PREFIX}/var/lib/i2pd/tunnels.d
@ln -sf ${PREFIX}/etc/i2pd/i2pd.conf ${PREFIX}/var/lib/i2pd/i2pd.conf
@ln -sf ${PREFIX}/etc/i2pd/subscriptions.txt ${PREFIX}/var/lib/i2pd/subscriptions.txt

View File

@@ -64,18 +64,13 @@ endif
endif
install: all
install -d ${PREFIX}/bin
install -m 755 ${I2PD} ${PREFIX}/bin
install -d ${PREFIX}/etc ${PREFIX}/etc/i2pd ${PREFIX}/etc/i2pd/tunnels.conf.d
install -d ${PREFIX}/bin ${PREFIX}/etc ${PREFIX}/etc/i2pd ${PREFIX}/etc/i2pd/tunnels.conf.d ${PREFIX}/usr ${PREFIX}/usr/share ${PREFIX}/usr/share/doc/i2pd ${PREFIX}/usr/share/i2pd ${PREFIX}/usr/share/man ${PREFIX}/usr/share/man/man1 ${PREFIX}/var/lib ${PREFIX}/var/lib/i2pd
install -m 755 ${I2PD} ${PREFIX}/bin/
install -m 644 contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/etc/i2pd
install -d ${PREFIX}/share ${PREFIX}/share/doc ${PREFIX}/share/doc/i2pd
install -m 644 ChangeLog LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/share/doc/i2pd
install -d ${PREFIX}/share/i2pd
@cp -R contrib/certificates ${PREFIX}/share/i2pd/
install -d ${PREFIX}/share/man ${PREFIX}/share/man/man1
@gzip -kf debian/i2pd.1 && install debian/i2pd.1.gz ${PREFIX}/share/man/man1
install -d ${PREFIX}/var ${PREFIX}/var/lib ${PREFIX}/var/lib/i2pd
@ln -sf ${PREFIX}/share/i2pd/certificates ${PREFIX}/var/lib/i2pd/certificates
@cp -R contrib/certificates ${PREFIX}/usr/share/i2pd/
install -m 644 ChangeLog LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/usr/share/doc/i2pd
@gzip -kf debian/i2pd.1 && install debian/i2pd.1.gz ${PREFIX}/usr/share/man/man1
@ln -sf ${PREFIX}/usr/share/i2pd/certificates ${PREFIX}/var/lib/i2pd/
@ln -sf ${PREFIX}/etc/i2pd/tunnels.conf.d ${PREFIX}/var/lib/i2pd/tunnels.d
@ln -sf ${PREFIX}/etc/i2pd/i2pd.conf ${PREFIX}/var/lib/i2pd/i2pd.conf
@ln -sf ${PREFIX}/etc/i2pd/subscriptions.txt ${PREFIX}/var/lib/i2pd/subscriptions.txt

View File

@@ -3,11 +3,19 @@ USE_WIN32_APP := yes
WINDRES = windres
CXXFLAGS := $(CXX_DEBUG) -fPIC -msse
CXXFLAGS := $(CXX_DEBUG) -DWIN32_LEAN_AND_MEAN -fPIC -msse
INCFLAGS = -I$(DAEMON_SRC_DIR) -IWin32
LDFLAGS := ${LD_DEBUG} -static
NEEDED_CXXFLAGS += -std=c++17 -DWIN32_LEAN_AND_MEAN
# detect proper flag for c++11 support by compilers
CXXVER := $(shell $(CXX) -dumpversion)
ifeq ($(shell expr match ${CXXVER} "[4]\.[7-9]\|4\.1[0-9]\|[5-6]"),4) # gcc 4.7 - 6
NEEDED_CXXFLAGS += -std=c++11
else ifeq ($(shell expr match ${CXXVER} "[1,7-9]"),1) # gcc >= 7
NEEDED_CXXFLAGS += -std=c++17
else # not supported
$(error Compiler too old)
endif
# Boost libraries suffix
BOOST_SUFFIX = -mt

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2020, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -154,23 +154,25 @@ namespace win32
case eRouterStatusUnknown: s << "Unk"; break;
case eRouterStatusProxy: s << "Proxy"; break;
case eRouterStatusMesh: s << "Mesh"; break;
default: s << "Unk";
};
if (i2p::context.GetError () != eRouterErrorNone)
{
switch (i2p::context.GetError ())
case eRouterStatusError:
{
case eRouterErrorClockSkew:
s << " - Clock skew";
s << "Err";
switch (i2p::context.GetError ())
{
case eRouterErrorClockSkew:
s << " - Clock skew";
break;
case eRouterErrorOffline:
s << " - Offline";
break;
case eRouterErrorSymmetricNAT:
s << " - Symmetric NAT";
break;
default: ;
}
break;
case eRouterErrorOffline:
s << " - Offline";
break;
case eRouterErrorSymmetricNAT:
s << " - Symmetric NAT";
break;
default: ;
}
default: s << "Unk";
}
}

View File

@@ -17,13 +17,12 @@ option(WITH_LIBRARY "Build library" ON)
option(WITH_BINARY "Build binary" ON)
option(WITH_STATIC "Static build" OFF)
option(WITH_UPNP "Include support for UPnP client" OFF)
option(WITH_GIT_VERSION "Use git commit info as version" OFF)
option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF)
option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF)
# paths
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules")
set(CMAKE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..")
set(CMAKE_SOURCE_DIR "..")
#Handle paths nicely
include(GNUInstallDirs)
@@ -85,7 +84,6 @@ set(DAEMON_SRC
"${DAEMON_SRC_DIR}/Daemon.cpp"
"${DAEMON_SRC_DIR}/HTTPServer.cpp"
"${DAEMON_SRC_DIR}/I2PControl.cpp"
"${DAEMON_SRC_DIR}/I2PControlHandlers.cpp"
"${DAEMON_SRC_DIR}/i2pd.cpp"
"${DAEMON_SRC_DIR}/UPnP.cpp"
)
@@ -94,12 +92,6 @@ if(WITH_UPNP)
add_definitions(-DUSE_UPNP)
endif()
if(WITH_GIT_VERSION)
include(GetGitRevisionDescription)
git_describe(GIT_VERSION)
add_definitions(-DGITVER="${GIT_VERSION}")
endif()
if(APPLE)
add_definitions(-DMAC_OSX)
endif()
@@ -172,21 +164,25 @@ if(WITH_THREADSANITIZER)
endif()
# Enable usage of STD's Atomic instead of Boost's on PowerPC
# For more information refer to https://github.com/PurpleI2P/i2pd/issues/1726#issuecomment-1306335111
if(ARCHITECTURE MATCHES "ppc")
add_definitions(-DBOOST_SP_USE_STD_ATOMIC)
endif()
# libraries
# TODO: once CMake 3.1+ becomes mainstream, see e.g. http://stackoverflow.com/a/29871891/673826
# use imported Threads::Threads instead
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
if(IOS)
set(CMAKE_THREAD_LIBS_INIT "-lpthread")
set(CMAKE_HAVE_THREADS_LIBRARY 1)
set(CMAKE_USE_WIN32_THREADS_INIT 0)
set(CMAKE_USE_PTHREADS_INIT 1)
else()
find_package(Threads REQUIRED)
endif()
if(THREADS_HAVE_PTHREAD_ARG) # compile time flag
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
endif()
if(WITH_STATIC)
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_STATIC_RUNTIME ON)
set(OPENSSL_USE_STATIC_LIBS ON)
set(BUILD_SHARED_LIBS OFF)
if(${CMAKE_CXX_COMPILER} MATCHES ".*-openwrt-.*")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
@@ -201,6 +197,8 @@ else()
add_definitions(-DBOOST_SYSTEM_DYN_LINK -DBOOST_FILESYSTEM_DYN_LINK -DBOOST_PROGRAM_OPTIONS_DYN_LINK -DBOOST_DATE_TIME_DYN_LINK -DBOOST_REGEX_DYN_LINK)
endif()
target_link_libraries(libi2pdclient libi2pd libi2pdlang)
find_package(Boost COMPONENTS system filesystem program_options date_time REQUIRED)
if(NOT DEFINED Boost_INCLUDE_DIRS)
message(SEND_ERROR "Boost is not found, or your boost version was below 1.46. Please download Boost!")
@@ -212,7 +210,7 @@ if(NOT DEFINED OPENSSL_INCLUDE_DIR)
endif()
if(OPENSSL_VERSION VERSION_GREATER_EQUAL "3.0.0")
add_definitions(-DOPENSSL_SUPPRESS_DEPRECATED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations")
endif()
if(WITH_UPNP)
@@ -249,7 +247,6 @@ message(STATUS " LIBRARY : ${WITH_LIBRARY}")
message(STATUS " BINARY : ${WITH_BINARY}")
message(STATUS " STATIC BUILD : ${WITH_STATIC}")
message(STATUS " UPnP : ${WITH_UPNP}")
message(STATUS " GIT VERSION : ${WITH_GIT_VERSION}")
message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}")
message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}")
message(STATUS "---------------------------------------")
@@ -265,17 +262,23 @@ if(WITH_BINARY)
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-z relro -z now")
endif()
if(WITH_UPNP)
set(UPNP_LIB ${MINIUPNPC_LIBRARY})
endif()
# FindBoost pulls pthread for thread which is broken for static linking at least on Ubuntu 15.04
list(GET Boost_LIBRARIES -1 LAST_Boost_LIBRARIES)
if(${LAST_Boost_LIBRARIES} MATCHES ".*pthread.*")
list(REMOVE_AT Boost_LIBRARIES -1)
endif()
if(WITH_STATIC)
set(DL_LIB ${CMAKE_DL_LIBS})
endif()
target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang ${DL_LIB} ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto ${MINIUPNPC_LIBRARY} ZLIB::ZLIB Threads::Threads ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES})
target_link_libraries(libi2pd ${Boost_LIBRARIES} ${ZLIB_LIBRARY})
target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${UPNP_LIB} ${ZLIB_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${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}")

View File

@@ -52,28 +52,22 @@ REM converting configuration files to DOS format (make usable in Windows Notepad
%xSH% "unix2dos contrib/i2pd.conf contrib/tunnels.conf contrib/tunnels.d/* contrib/webconsole/style.css" >> build\build.log 2>&1
REM Prepare binary signing command if signing key and password provided
if defined SIGN (
echo Signing enabled
for %%X in (signtool.exe) do (set xSIGNTOOL=%%~$PATH:X)
if not defined xSIGNTOOL (
if not defined SIGNTOOL (
echo Error: Can't find signtool. Please provide path to binary using SIGNTOOL variable.
exit /b 1
) else (
set "xSIGNTOOL=%SIGNTOOL%"
)
)
if defined SIGNKEY (
set "xSIGNKEYOPTS=/f ^"%SIGNKEY%^""
)
if defined SIGNKEY (
if defined SIGNPASS (
set "xSIGNPASSOPTS=/p ^"%SIGNPASS%^""
)
echo Signing options found
set "xSIGNOPTS=sign /tr http://timestamp.digicert.com /td sha256 /fd sha256 %xSIGNKEYOPTS% %xSIGNPASSOPTS%"
for %%X in (signtool.exe) do (set xSIGNTOOL=%%~$PATH:X)
if not defined xSIGNTOOL (
if not defined SIGNTOOL (
echo Error: Can't find signtool. Please provide path to binary using SIGNTOOL variable.
exit /b 1
) else (
set "xSIGNTOOL=%SIGNTOOL%"
)
)
set "xSIGNOPTS=sign /tr http://timestamp.digicert.com /td sha256 /fd sha256 /f ^"%SIGNKEY%^" /p ^"%SIGNPASS%^""
)
)
REM starting building

View File

@@ -1,284 +0,0 @@
# - Returns a version string from Git
#
# These functions force a re-configure on each git commit so that you can
# trust the values of the variables in your build system.
#
# get_git_head_revision(<refspecvar> <hashvar> [ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR])
#
# Returns the refspec and sha hash of the current head revision
#
# git_describe(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe on the source tree, and adjusting
# the output so that it tests false if an error occurs.
#
# git_describe_working_tree(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe on the working tree (--dirty option),
# and adjusting the output so that it tests false if an error occurs.
#
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
#
# Returns the results of git describe --exact-match on the source tree,
# and adjusting the output so that it tests false if there was no exact
# matching tag.
#
# git_local_changes(<var>)
#
# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes.
# Uses the return code of "git diff-index --quiet HEAD --".
# Does not regard untracked files.
#
# Requires CMake 2.6 or newer (uses the 'function' command)
#
# Original Author:
# 2009-2020 Ryan Pavlik <ryan.pavlik@gmail.com> <abiryan@ryand.net>
# http://academic.cleardefinition.com
#
# Copyright 2009-2013, Iowa State University.
# Copyright 2013-2020, Ryan Pavlik
# Copyright 2013-2020, Contributors
# SPDX-License-Identifier: BSL-1.0
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
if(__get_git_revision_description)
return()
endif()
set(__get_git_revision_description YES)
# We must run the following at "include" time, not at function call time,
# to find the path to this module rather than the path to a calling list file
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
# Function _git_find_closest_git_dir finds the next closest .git directory
# that is part of any directory in the path defined by _start_dir.
# The result is returned in the parent scope variable whose name is passed
# as variable _git_dir_var. If no .git directory can be found, the
# function returns an empty string via _git_dir_var.
#
# Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and
# neither foo nor bar contain a file/directory .git. This wil return
# C:/bla/.git
#
function(_git_find_closest_git_dir _start_dir _git_dir_var)
set(cur_dir "${_start_dir}")
set(git_dir "${_start_dir}/.git")
while(NOT EXISTS "${git_dir}")
# .git dir not found, search parent directories
set(git_previous_parent "${cur_dir}")
get_filename_component(cur_dir "${cur_dir}" DIRECTORY)
if(cur_dir STREQUAL git_previous_parent)
# We have reached the root directory, we are not in git
set(${_git_dir_var}
""
PARENT_SCOPE)
return()
endif()
set(git_dir "${cur_dir}/.git")
endwhile()
set(${_git_dir_var}
"${git_dir}"
PARENT_SCOPE)
endfunction()
function(get_git_head_revision _refspecvar _hashvar)
_git_find_closest_git_dir("${CMAKE_CURRENT_SOURCE_DIR}" GIT_DIR)
if("${ARGN}" STREQUAL "ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR")
set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR TRUE)
else()
set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR FALSE)
endif()
if(NOT "${GIT_DIR}" STREQUAL "")
file(RELATIVE_PATH _relative_to_source_dir "${CMAKE_SOURCE_DIR}"
"${GIT_DIR}")
if("${_relative_to_source_dir}" MATCHES "[.][.]" AND NOT ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR)
# We've gone above the CMake root dir.
set(GIT_DIR "")
endif()
endif()
if("${GIT_DIR}" STREQUAL "")
set(${_refspecvar}
"GITDIR-NOTFOUND"
PARENT_SCOPE)
set(${_hashvar}
"GITDIR-NOTFOUND"
PARENT_SCOPE)
return()
endif()
# Check if the current source dir is a git submodule or a worktree.
# In both cases .git is a file instead of a directory.
#
if(NOT IS_DIRECTORY ${GIT_DIR})
# The following git command will return a non empty string that
# points to the super project working tree if the current
# source dir is inside a git submodule.
# Otherwise the command will return an empty string.
#
execute_process(
COMMAND "${GIT_EXECUTABLE}" rev-parse
--show-superproject-working-tree
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT "${out}" STREQUAL "")
# If out is empty, GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a submodule
file(READ ${GIT_DIR} submodule)
string(REGEX REPLACE "gitdir: (.*)$" "\\1" GIT_DIR_RELATIVE
${submodule})
string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE)
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE}
ABSOLUTE)
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
else()
# GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a worktree
file(READ ${GIT_DIR} worktree_ref)
# The .git directory contains a path to the worktree information directory
# inside the parent git repo of the worktree.
#
string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir
${worktree_ref})
string(STRIP ${git_worktree_dir} git_worktree_dir)
_git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR)
set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD")
endif()
else()
set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD")
endif()
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
if(NOT EXISTS "${GIT_DATA}")
file(MAKE_DIRECTORY "${GIT_DATA}")
endif()
if(NOT EXISTS "${HEAD_SOURCE_FILE}")
return()
endif()
set(HEAD_FILE "${GIT_DATA}/HEAD")
configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY)
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
"${GIT_DATA}/grabRef.cmake" @ONLY)
include("${GIT_DATA}/grabRef.cmake")
set(${_refspecvar}
"${HEAD_REF}"
PARENT_SCOPE)
set(${_hashvar}
"${HEAD_HASH}"
PARENT_SCOPE)
endfunction()
function(git_describe _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
get_git_head_revision(refspec hash)
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
if(NOT hash)
set(${_var}
"HEAD-HASH-NOTFOUND"
PARENT_SCOPE)
return()
endif()
# TODO sanitize
#if((${ARGN}" MATCHES "&&") OR
# (ARGN MATCHES "||") OR
# (ARGN MATCHES "\\;"))
# message("Please report the following error to the project!")
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
#endif()
#message(STATUS "Arguments to execute_process: ${ARGN}")
execute_process(
COMMAND "${GIT_EXECUTABLE}" describe --tags --always ${hash} ${ARGN}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
set(${_var}
"${out}"
PARENT_SCOPE)
endfunction()
function(git_describe_working_tree _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" describe --dirty ${ARGN}
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(NOT res EQUAL 0)
set(out "${out}-${res}-NOTFOUND")
endif()
set(${_var}
"${out}"
PARENT_SCOPE)
endfunction()
function(git_get_exact_tag _var)
git_describe(out --exact-match ${ARGN})
set(${_var}
"${out}"
PARENT_SCOPE)
endfunction()
function(git_local_changes _var)
if(NOT GIT_FOUND)
find_package(Git QUIET)
endif()
get_git_head_revision(refspec hash)
if(NOT GIT_FOUND)
set(${_var}
"GIT-NOTFOUND"
PARENT_SCOPE)
return()
endif()
if(NOT hash)
set(${_var}
"HEAD-HASH-NOTFOUND"
PARENT_SCOPE)
return()
endif()
execute_process(
COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD --
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
RESULT_VARIABLE res
OUTPUT_VARIABLE out
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
if(res EQUAL 0)
set(${_var}
"CLEAN"
PARENT_SCOPE)
else()
set(${_var}
"DIRTY"
PARENT_SCOPE)
endif()
endfunction()

View File

@@ -1,43 +0,0 @@
#
# Internal file for GetGitRevisionDescription.cmake
#
# Requires CMake 2.6 or newer (uses the 'function' command)
#
# Original Author:
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
# http://academic.cleardefinition.com
# Iowa State University HCI Graduate Program/VRAC
#
# Copyright 2009-2012, Iowa State University
# Copyright 2011-2015, Contributors
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
# SPDX-License-Identifier: BSL-1.0
set(HEAD_HASH)
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
if(HEAD_CONTENTS MATCHES "ref")
# named branch
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
else()
configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY)
file(READ "@GIT_DATA@/packed-refs" PACKED_REFS)
if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}")
set(HEAD_HASH "${CMAKE_MATCH_1}")
endif()
endif()
else()
# detached HEAD
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
endif()
if(NOT HEAD_HASH)
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
string(STRIP "${HEAD_HASH}" HEAD_HASH)
endif()

View File

@@ -61,7 +61,7 @@ set(archdetect_c_code "
#else
#error cmake_ARCH mips
#endif
#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) || defined(__POWERPC__) \\
#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \\
|| defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \\
|| defined(_M_MPPC) || defined(_M_PPC)
#if defined(__ppc64__) || defined(__powerpc64__) || defined(__64BIT__)

View File

@@ -1,18 +1,5 @@
#
# Copyright (c) 2017-2022, The PurpleI2P Project
#
# This file is part of Purple i2pd project and licensed under BSD3
#
# See full license text in LICENSE file at top of project tree
#
FROM alpine:latest
LABEL authors="Mikal Villa <mikal@sigterm.no>, Darknet Villain <supervillain@riseup.net>"
LABEL maintainer="R4SAS <r4sas@i2pmail.org>"
LABEL org.opencontainers.image.source=https://github.com/PurpleI2P/i2pd
LABEL org.opencontainers.image.documentation=https://i2pd.readthedocs.io/en/latest/
LABEL org.opencontainers.image.licenses=BSD3
LABEL authors "Mikal Villa <mikal@sigterm.no>, Darknet Villain <supervillain@riseup.net>"
# Expose git branch, tag and URL variables as arguments
ARG GIT_BRANCH="openssl"
@@ -24,28 +11,27 @@ ENV REPO_URL=${REPO_URL}
ENV I2PD_HOME="/home/i2pd"
ENV DATA_DIR="${I2PD_HOME}/data"
ENV DEFAULT_ARGS=" --datadir=$DATA_DIR"
ENV DEFAULT_ARGS=" --datadir=$DATA_DIR --reseed.verify=true --upnp.enabled=false --http.enabled=true --http.address=0.0.0.0 --httpproxy.enabled=true --httpproxy.address=0.0.0.0 --socksproxy.enabled=true --socksproxy.address=0.0.0.0 --sam.enabled=true --sam.address=0.0.0.0"
RUN mkdir -p "$I2PD_HOME" "$DATA_DIR" \
&& adduser -S -h "$I2PD_HOME" i2pd \
&& chown -R i2pd:nobody "$I2PD_HOME"
# 1. Building binary
# 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.
# 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 update \
&& apk --no-cache --virtual build-dependendencies add make gcc g++ libtool zlib-dev boost-dev build-base openssl-dev openssl miniupnpc-dev git \
&& mkdir -p /tmp/build \
&& cd /tmp/build && git clone -b ${GIT_BRANCH} ${REPO_URL} \
&& cd i2pd \
&& if [ -n "${GIT_TAG}" ]; then git checkout tags/${GIT_TAG}; fi \
&& make -j$(nproc) USE_UPNP=yes \
&& make USE_UPNP=yes \
&& cp -R contrib/certificates /i2pd_certificates \
&& mkdir -p /usr/local/bin \
&& mv i2pd /usr/local/bin \
@@ -59,9 +45,6 @@ RUN apk update \
# 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 miniupnpc musl-utils libstdc++
# 3. Copy preconfigured config file and entrypoint
COPY i2pd-docker.conf "$I2PD_HOME/i2pd.conf"
RUN chown i2pd:nobody "$I2PD_HOME/i2pd.conf"
COPY entrypoint.sh /entrypoint.sh
RUN chmod a+x /entrypoint.sh

View File

@@ -1,52 +0,0 @@
## Preconfigured i2pd configuration file for a Docker container
## See https://i2pd.readthedocs.io/en/latest/user-guide/configuration/
## for more options you can use in this file.
## Note that for exposing ports outside of container you need to bind all services to 0.0.0.0
log = file
loglevel = none
ipv4 = true
ipv6 = false
# bandwidth = L
# notransit = false
# floodfill = false
[ntcp2]
enabled = true
published = true
[ssu2]
enabled = true
published = true
[http]
enabled = true
address = 0.0.0.0
port = 7070
[httpproxy]
enabled = true
address = 0.0.0.0
port = 4444
[socksproxy]
enabled = true
address = 0.0.0.0
port = 4447
[sam]
enabled = true
address = 0.0.0.0
port = 7656
[upnp]
enabled = false
[reseed]
verify = true
[limits]
# transittunnels = 2500

View File

@@ -1,13 +1,13 @@
# i2pd
# Copyright (C) 2021-2022 PurpleI2P team
# Copyright (C) 2021 PurpleI2P team
# This file is distributed under the same license as the i2pd package.
# R4SAS <r4sas@i2pmail.org>, 2021-2022.
# R4SAS <r4sas@i2pmail.org>, 2021.
#
msgid ""
msgstr ""
"Project-Id-Version: i2pd\n"
"Report-Msgid-Bugs-To: https://github.com/PurpleI2P/i2pd/issues\n"
"POT-Creation-Date: 2022-07-26 21:22\n"
"POT-Creation-Date: 2021-08-06 17:12\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@@ -18,712 +18,706 @@ msgstr ""
"X-Poedit-SearchPath-0: daemon/HTTPServer.cpp\n"
"X-Poedit-SearchPath-1: libi2pd_client/HTTPProxy.cpp\n"
#: daemon/HTTPServer.cpp:108
#: daemon/HTTPServer.cpp:177
msgid "day"
msgid_plural "days"
msgstr[0] ""
msgstr[1] ""
#: daemon/HTTPServer.cpp:112
#: daemon/HTTPServer.cpp:181
msgid "hour"
msgid_plural "hours"
msgstr[0] ""
msgstr[1] ""
#: daemon/HTTPServer.cpp:116
#: daemon/HTTPServer.cpp:185
msgid "minute"
msgid_plural "minutes"
msgstr[0] ""
msgstr[1] ""
#: daemon/HTTPServer.cpp:119
#: daemon/HTTPServer.cpp:188
msgid "second"
msgid_plural "seconds"
msgstr[0] ""
msgstr[1] ""
#. tr: Kibibit
#: daemon/HTTPServer.cpp:127 daemon/HTTPServer.cpp:155
#: daemon/HTTPServer.cpp:196 daemon/HTTPServer.cpp:224
msgid "KiB"
msgstr ""
#. tr: Mebibit
#: daemon/HTTPServer.cpp:129
#: daemon/HTTPServer.cpp:198
msgid "MiB"
msgstr ""
#. tr: Gibibit
#: daemon/HTTPServer.cpp:131
#: daemon/HTTPServer.cpp:200
msgid "GiB"
msgstr ""
#: daemon/HTTPServer.cpp:148
#: daemon/HTTPServer.cpp:217
msgid "building"
msgstr ""
#: daemon/HTTPServer.cpp:149
#: daemon/HTTPServer.cpp:218
msgid "failed"
msgstr ""
#: daemon/HTTPServer.cpp:150
#: daemon/HTTPServer.cpp:219
msgid "expiring"
msgstr ""
#: daemon/HTTPServer.cpp:151
#: daemon/HTTPServer.cpp:220
msgid "established"
msgstr ""
#: daemon/HTTPServer.cpp:152
#: daemon/HTTPServer.cpp:221
msgid "unknown"
msgstr ""
#: daemon/HTTPServer.cpp:154
#: daemon/HTTPServer.cpp:223
msgid "exploratory"
msgstr ""
#. tr: Webconsole page title
#: daemon/HTTPServer.cpp:185
msgid "Purple I2P Webconsole"
msgstr ""
#: daemon/HTTPServer.cpp:190
#: daemon/HTTPServer.cpp:259
msgid "<b>i2pd</b> webconsole"
msgstr ""
#: daemon/HTTPServer.cpp:193
#: daemon/HTTPServer.cpp:262
msgid "Main page"
msgstr ""
#: daemon/HTTPServer.cpp:194 daemon/HTTPServer.cpp:700
#: daemon/HTTPServer.cpp:263 daemon/HTTPServer.cpp:725
msgid "Router commands"
msgstr ""
#: daemon/HTTPServer.cpp:195 daemon/HTTPServer.cpp:382
#: daemon/HTTPServer.cpp:394
#: daemon/HTTPServer.cpp:264 daemon/HTTPServer.cpp:448
#: daemon/HTTPServer.cpp:460
msgid "Local Destinations"
msgstr ""
#: daemon/HTTPServer.cpp:197 daemon/HTTPServer.cpp:352
#: daemon/HTTPServer.cpp:438 daemon/HTTPServer.cpp:444
#: daemon/HTTPServer.cpp:597 daemon/HTTPServer.cpp:640
#: daemon/HTTPServer.cpp:644
#: daemon/HTTPServer.cpp:266 daemon/HTTPServer.cpp:418
#: daemon/HTTPServer.cpp:504 daemon/HTTPServer.cpp:510
#: daemon/HTTPServer.cpp:641 daemon/HTTPServer.cpp:684
#: daemon/HTTPServer.cpp:688
msgid "LeaseSets"
msgstr ""
#: daemon/HTTPServer.cpp:199 daemon/HTTPServer.cpp:650
#: daemon/HTTPServer.cpp:268 daemon/HTTPServer.cpp:694
msgid "Tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:201 daemon/HTTPServer.cpp:359
#: daemon/HTTPServer.cpp:770 daemon/HTTPServer.cpp:786
#: daemon/HTTPServer.cpp:269 daemon/HTTPServer.cpp:425
#: daemon/HTTPServer.cpp:787 daemon/HTTPServer.cpp:803
msgid "Transit Tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:203 daemon/HTTPServer.cpp:839
#: daemon/HTTPServer.cpp:270 daemon/HTTPServer.cpp:852
msgid "Transports"
msgstr ""
#: daemon/HTTPServer.cpp:204
#: daemon/HTTPServer.cpp:271
msgid "I2P tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:206 daemon/HTTPServer.cpp:908
#: daemon/HTTPServer.cpp:918
#: daemon/HTTPServer.cpp:273 daemon/HTTPServer.cpp:914
#: daemon/HTTPServer.cpp:924
msgid "SAM sessions"
msgstr ""
#: daemon/HTTPServer.cpp:222 daemon/HTTPServer.cpp:1302
#: daemon/HTTPServer.cpp:1305 daemon/HTTPServer.cpp:1308
#: daemon/HTTPServer.cpp:1322 daemon/HTTPServer.cpp:1367
#: daemon/HTTPServer.cpp:1370 daemon/HTTPServer.cpp:1373
#: daemon/HTTPServer.cpp:289 daemon/HTTPServer.cpp:1306
#: daemon/HTTPServer.cpp:1309 daemon/HTTPServer.cpp:1312
#: daemon/HTTPServer.cpp:1326 daemon/HTTPServer.cpp:1371
#: daemon/HTTPServer.cpp:1374 daemon/HTTPServer.cpp:1377
msgid "ERROR"
msgstr ""
#: daemon/HTTPServer.cpp:229
#: daemon/HTTPServer.cpp:296
msgid "OK"
msgstr ""
#: daemon/HTTPServer.cpp:230
#: daemon/HTTPServer.cpp:297
msgid "Testing"
msgstr ""
#: daemon/HTTPServer.cpp:231
#: daemon/HTTPServer.cpp:298
msgid "Firewalled"
msgstr ""
#: daemon/HTTPServer.cpp:232 daemon/HTTPServer.cpp:253
#: daemon/HTTPServer.cpp:325
#: daemon/HTTPServer.cpp:299 daemon/HTTPServer.cpp:320
#: daemon/HTTPServer.cpp:406
msgid "Unknown"
msgstr ""
#: daemon/HTTPServer.cpp:233 daemon/HTTPServer.cpp:369
#: daemon/HTTPServer.cpp:370 daemon/HTTPServer.cpp:976
#: daemon/HTTPServer.cpp:985
#: daemon/HTTPServer.cpp:300 daemon/HTTPServer.cpp:435
#: daemon/HTTPServer.cpp:436 daemon/HTTPServer.cpp:982
#: daemon/HTTPServer.cpp:991
msgid "Proxy"
msgstr ""
#: daemon/HTTPServer.cpp:234
#: daemon/HTTPServer.cpp:301
msgid "Mesh"
msgstr ""
#: daemon/HTTPServer.cpp:237
#: daemon/HTTPServer.cpp:304
msgid "Error"
msgstr ""
#: daemon/HTTPServer.cpp:241
#: daemon/HTTPServer.cpp:308
msgid "Clock skew"
msgstr ""
#: daemon/HTTPServer.cpp:244
#: daemon/HTTPServer.cpp:311
msgid "Offline"
msgstr ""
#: daemon/HTTPServer.cpp:247
#: daemon/HTTPServer.cpp:314
msgid "Symmetric NAT"
msgstr ""
#: daemon/HTTPServer.cpp:259
#: daemon/HTTPServer.cpp:326
msgid "Uptime"
msgstr ""
#: daemon/HTTPServer.cpp:262
#: daemon/HTTPServer.cpp:329
msgid "Network status"
msgstr ""
#: daemon/HTTPServer.cpp:267
#: daemon/HTTPServer.cpp:334
msgid "Network status v6"
msgstr ""
#: daemon/HTTPServer.cpp:273 daemon/HTTPServer.cpp:280
#: daemon/HTTPServer.cpp:340 daemon/HTTPServer.cpp:347
msgid "Stopping in"
msgstr ""
#: daemon/HTTPServer.cpp:287
#: daemon/HTTPServer.cpp:354
msgid "Family"
msgstr ""
#: daemon/HTTPServer.cpp:288
#: daemon/HTTPServer.cpp:355
msgid "Tunnel creation success rate"
msgstr ""
#: daemon/HTTPServer.cpp:289
#: daemon/HTTPServer.cpp:356
msgid "Received"
msgstr ""
#. tr: Kibibit/s
#: daemon/HTTPServer.cpp:291 daemon/HTTPServer.cpp:294
#: daemon/HTTPServer.cpp:297
#: daemon/HTTPServer.cpp:358 daemon/HTTPServer.cpp:361
#: daemon/HTTPServer.cpp:364
msgid "KiB/s"
msgstr ""
#: daemon/HTTPServer.cpp:292
#: daemon/HTTPServer.cpp:359
msgid "Sent"
msgstr ""
#: daemon/HTTPServer.cpp:295
#: daemon/HTTPServer.cpp:362
msgid "Transit"
msgstr ""
#: daemon/HTTPServer.cpp:298
#: daemon/HTTPServer.cpp:365
msgid "Data path"
msgstr ""
#: daemon/HTTPServer.cpp:301
#: daemon/HTTPServer.cpp:368
msgid "Hidden content. Press on text to see."
msgstr ""
#: daemon/HTTPServer.cpp:304
#: daemon/HTTPServer.cpp:371
msgid "Router Ident"
msgstr ""
#: daemon/HTTPServer.cpp:306
#: daemon/HTTPServer.cpp:373
msgid "Router Family"
msgstr ""
#: daemon/HTTPServer.cpp:307
#: daemon/HTTPServer.cpp:374
msgid "Router Caps"
msgstr ""
#: daemon/HTTPServer.cpp:308
#: daemon/HTTPServer.cpp:375
msgid "Version"
msgstr ""
#: daemon/HTTPServer.cpp:309
#: daemon/HTTPServer.cpp:376
msgid "Our external address"
msgstr ""
#: daemon/HTTPServer.cpp:337
#: daemon/HTTPServer.cpp:384
msgid "supported"
msgstr ""
#: daemon/HTTPServer.cpp:350
#: daemon/HTTPServer.cpp:416
msgid "Routers"
msgstr ""
#: daemon/HTTPServer.cpp:351
#: daemon/HTTPServer.cpp:417
msgid "Floodfills"
msgstr ""
#: daemon/HTTPServer.cpp:358 daemon/HTTPServer.cpp:962
#: daemon/HTTPServer.cpp:424 daemon/HTTPServer.cpp:968
msgid "Client Tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:368
#: daemon/HTTPServer.cpp:434
msgid "Services"
msgstr ""
#: daemon/HTTPServer.cpp:369 daemon/HTTPServer.cpp:370
#: daemon/HTTPServer.cpp:371 daemon/HTTPServer.cpp:372
#: daemon/HTTPServer.cpp:373 daemon/HTTPServer.cpp:374
#: daemon/HTTPServer.cpp:435 daemon/HTTPServer.cpp:436
#: daemon/HTTPServer.cpp:437 daemon/HTTPServer.cpp:438
#: daemon/HTTPServer.cpp:439 daemon/HTTPServer.cpp:440
msgid "Enabled"
msgstr ""
#: daemon/HTTPServer.cpp:369 daemon/HTTPServer.cpp:370
#: daemon/HTTPServer.cpp:371 daemon/HTTPServer.cpp:372
#: daemon/HTTPServer.cpp:373 daemon/HTTPServer.cpp:374
#: daemon/HTTPServer.cpp:435 daemon/HTTPServer.cpp:436
#: daemon/HTTPServer.cpp:437 daemon/HTTPServer.cpp:438
#: daemon/HTTPServer.cpp:439 daemon/HTTPServer.cpp:440
msgid "Disabled"
msgstr ""
#: daemon/HTTPServer.cpp:417
#: daemon/HTTPServer.cpp:483
msgid "Encrypted B33 address"
msgstr ""
#: daemon/HTTPServer.cpp:426
#: daemon/HTTPServer.cpp:492
msgid "Address registration line"
msgstr ""
#: daemon/HTTPServer.cpp:431
#: daemon/HTTPServer.cpp:497
msgid "Domain"
msgstr ""
#: daemon/HTTPServer.cpp:432
#: daemon/HTTPServer.cpp:498
msgid "Generate"
msgstr ""
#: daemon/HTTPServer.cpp:433
#: daemon/HTTPServer.cpp:499
msgid ""
"<b>Note:</b> result string can be used only for registering 2LD domains "
"(example.i2p). For registering subdomains please use i2pd-tools."
msgstr ""
#: daemon/HTTPServer.cpp:439
#: daemon/HTTPServer.cpp:505
msgid "Address"
msgstr ""
#: daemon/HTTPServer.cpp:439
#: daemon/HTTPServer.cpp:505
msgid "Type"
msgstr ""
#: daemon/HTTPServer.cpp:439
#: daemon/HTTPServer.cpp:505
msgid "EncType"
msgstr ""
#: daemon/HTTPServer.cpp:449 daemon/HTTPServer.cpp:655
#: daemon/HTTPServer.cpp:515 daemon/HTTPServer.cpp:699
msgid "Inbound tunnels"
msgstr ""
#. tr: Milliseconds
#: daemon/HTTPServer.cpp:464 daemon/HTTPServer.cpp:484
#: daemon/HTTPServer.cpp:669 daemon/HTTPServer.cpp:689
#: daemon/HTTPServer.cpp:520 daemon/HTTPServer.cpp:530
#: daemon/HTTPServer.cpp:704 daemon/HTTPServer.cpp:714
msgid "ms"
msgstr ""
#: daemon/HTTPServer.cpp:469 daemon/HTTPServer.cpp:674
#: daemon/HTTPServer.cpp:525 daemon/HTTPServer.cpp:709
msgid "Outbound tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:491
#: daemon/HTTPServer.cpp:537
msgid "Tags"
msgstr ""
#: daemon/HTTPServer.cpp:491
#: daemon/HTTPServer.cpp:537
msgid "Incoming"
msgstr ""
#: daemon/HTTPServer.cpp:498 daemon/HTTPServer.cpp:501
#: daemon/HTTPServer.cpp:544 daemon/HTTPServer.cpp:547
msgid "Outgoing"
msgstr ""
#: daemon/HTTPServer.cpp:499 daemon/HTTPServer.cpp:515
#: daemon/HTTPServer.cpp:545 daemon/HTTPServer.cpp:561
msgid "Destination"
msgstr ""
#: daemon/HTTPServer.cpp:499
#: daemon/HTTPServer.cpp:545
msgid "Amount"
msgstr ""
#: daemon/HTTPServer.cpp:506
#: daemon/HTTPServer.cpp:552
msgid "Incoming Tags"
msgstr ""
#: daemon/HTTPServer.cpp:514 daemon/HTTPServer.cpp:517
#: daemon/HTTPServer.cpp:560 daemon/HTTPServer.cpp:563
msgid "Tags sessions"
msgstr ""
#: daemon/HTTPServer.cpp:515
#: daemon/HTTPServer.cpp:561
msgid "Status"
msgstr ""
#: daemon/HTTPServer.cpp:524 daemon/HTTPServer.cpp:582
#: daemon/HTTPServer.cpp:570 daemon/HTTPServer.cpp:626
msgid "Local Destination"
msgstr ""
#: daemon/HTTPServer.cpp:535 daemon/HTTPServer.cpp:941
#: daemon/HTTPServer.cpp:580 daemon/HTTPServer.cpp:947
msgid "Streams"
msgstr ""
#: daemon/HTTPServer.cpp:558
#: daemon/HTTPServer.cpp:602
msgid "Close stream"
msgstr ""
#: daemon/HTTPServer.cpp:587
#: daemon/HTTPServer.cpp:631
msgid "I2CP session not found"
msgstr ""
#: daemon/HTTPServer.cpp:590
#: daemon/HTTPServer.cpp:634
msgid "I2CP is not enabled"
msgstr ""
#: daemon/HTTPServer.cpp:616
#: daemon/HTTPServer.cpp:660
msgid "Invalid"
msgstr ""
#: daemon/HTTPServer.cpp:619
#: daemon/HTTPServer.cpp:663
msgid "Store type"
msgstr ""
#: daemon/HTTPServer.cpp:620
#: daemon/HTTPServer.cpp:664
msgid "Expires"
msgstr ""
#: daemon/HTTPServer.cpp:625
#: daemon/HTTPServer.cpp:669
msgid "Non Expired Leases"
msgstr ""
#: daemon/HTTPServer.cpp:628
#: daemon/HTTPServer.cpp:672
msgid "Gateway"
msgstr ""
#: daemon/HTTPServer.cpp:629
#: daemon/HTTPServer.cpp:673
msgid "TunnelID"
msgstr ""
#: daemon/HTTPServer.cpp:630
#: daemon/HTTPServer.cpp:674
msgid "EndDate"
msgstr ""
#: daemon/HTTPServer.cpp:640
#: daemon/HTTPServer.cpp:684
msgid "not floodfill"
msgstr ""
#: daemon/HTTPServer.cpp:651
#: daemon/HTTPServer.cpp:695
msgid "Queue size"
msgstr ""
#: daemon/HTTPServer.cpp:701
#: daemon/HTTPServer.cpp:726
msgid "Run peer test"
msgstr ""
#: daemon/HTTPServer.cpp:706
#: daemon/HTTPServer.cpp:731
msgid "Decline transit tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:708
#: daemon/HTTPServer.cpp:733
msgid "Accept transit tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:712 daemon/HTTPServer.cpp:717
#: daemon/HTTPServer.cpp:737 daemon/HTTPServer.cpp:742
msgid "Cancel graceful shutdown"
msgstr ""
#: daemon/HTTPServer.cpp:714 daemon/HTTPServer.cpp:719
#: daemon/HTTPServer.cpp:739 daemon/HTTPServer.cpp:744
msgid "Start graceful shutdown"
msgstr ""
#: daemon/HTTPServer.cpp:722
#: daemon/HTTPServer.cpp:747
msgid "Force shutdown"
msgstr ""
#: daemon/HTTPServer.cpp:723
#: daemon/HTTPServer.cpp:748
msgid "Reload external CSS styles"
msgstr ""
#: daemon/HTTPServer.cpp:726
#: daemon/HTTPServer.cpp:751
msgid ""
"<b>Note:</b> any action done here are not persistent and not changes your "
"config files."
msgstr ""
#: daemon/HTTPServer.cpp:728
#: daemon/HTTPServer.cpp:753
msgid "Logging level"
msgstr ""
#: daemon/HTTPServer.cpp:736
#: daemon/HTTPServer.cpp:761
msgid "Transit tunnels limit"
msgstr ""
#: daemon/HTTPServer.cpp:741 daemon/HTTPServer.cpp:760
#: daemon/HTTPServer.cpp:766 daemon/HTTPServer.cpp:778
msgid "Change"
msgstr ""
#: daemon/HTTPServer.cpp:748
#: daemon/HTTPServer.cpp:770
msgid "Change language"
msgstr ""
#: daemon/HTTPServer.cpp:786
#: daemon/HTTPServer.cpp:803
msgid "no transit tunnels currently built"
msgstr ""
#: daemon/HTTPServer.cpp:902 daemon/HTTPServer.cpp:925
#: daemon/HTTPServer.cpp:908 daemon/HTTPServer.cpp:931
msgid "SAM disabled"
msgstr ""
#: daemon/HTTPServer.cpp:918
#: daemon/HTTPServer.cpp:924
msgid "no sessions currently running"
msgstr ""
#: daemon/HTTPServer.cpp:931
#: daemon/HTTPServer.cpp:937
msgid "SAM session not found"
msgstr ""
#: daemon/HTTPServer.cpp:936
#: daemon/HTTPServer.cpp:942
msgid "SAM Session"
msgstr ""
#: daemon/HTTPServer.cpp:993
#: daemon/HTTPServer.cpp:999
msgid "Server Tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:1009
#: daemon/HTTPServer.cpp:1015
msgid "Client Forwards"
msgstr ""
#: daemon/HTTPServer.cpp:1023
#: daemon/HTTPServer.cpp:1029
msgid "Server Forwards"
msgstr ""
#: daemon/HTTPServer.cpp:1223
#: daemon/HTTPServer.cpp:1227
msgid "Unknown page"
msgstr ""
#: daemon/HTTPServer.cpp:1242
#: daemon/HTTPServer.cpp:1246
msgid "Invalid token"
msgstr ""
#: daemon/HTTPServer.cpp:1300 daemon/HTTPServer.cpp:1357
#: daemon/HTTPServer.cpp:1397
#: daemon/HTTPServer.cpp:1304 daemon/HTTPServer.cpp:1361
#: daemon/HTTPServer.cpp:1401
msgid "SUCCESS"
msgstr ""
#: daemon/HTTPServer.cpp:1300
#: daemon/HTTPServer.cpp:1304
msgid "Stream closed"
msgstr ""
#: daemon/HTTPServer.cpp:1302
#: daemon/HTTPServer.cpp:1306
msgid "Stream not found or already was closed"
msgstr ""
#: daemon/HTTPServer.cpp:1305
#: daemon/HTTPServer.cpp:1309
msgid "Destination not found"
msgstr ""
#: daemon/HTTPServer.cpp:1308
#: daemon/HTTPServer.cpp:1312
msgid "StreamID can't be null"
msgstr ""
#: daemon/HTTPServer.cpp:1310 daemon/HTTPServer.cpp:1375
#: daemon/HTTPServer.cpp:1314 daemon/HTTPServer.cpp:1379
msgid "Return to destination page"
msgstr ""
#: daemon/HTTPServer.cpp:1311 daemon/HTTPServer.cpp:1324
#: daemon/HTTPServer.cpp:1399
#: daemon/HTTPServer.cpp:1315 daemon/HTTPServer.cpp:1328
#: daemon/HTTPServer.cpp:1403
msgid "You will be redirected in 5 seconds"
msgstr ""
#: daemon/HTTPServer.cpp:1322
#: daemon/HTTPServer.cpp:1326
msgid "Transit tunnels count must not exceed 65535"
msgstr ""
#: daemon/HTTPServer.cpp:1323 daemon/HTTPServer.cpp:1398
#: daemon/HTTPServer.cpp:1327 daemon/HTTPServer.cpp:1402
msgid "Back to commands list"
msgstr ""
#: daemon/HTTPServer.cpp:1359
#: daemon/HTTPServer.cpp:1363
msgid "Register at reg.i2p"
msgstr ""
#: daemon/HTTPServer.cpp:1360
#: daemon/HTTPServer.cpp:1364
msgid "Description"
msgstr ""
#: daemon/HTTPServer.cpp:1360
#: daemon/HTTPServer.cpp:1364
msgid "A bit information about service on domain"
msgstr ""
#: daemon/HTTPServer.cpp:1361
#: daemon/HTTPServer.cpp:1365
msgid "Submit"
msgstr ""
#: daemon/HTTPServer.cpp:1367
#: daemon/HTTPServer.cpp:1371
msgid "Domain can't end with .b32.i2p"
msgstr ""
#: daemon/HTTPServer.cpp:1370
#: daemon/HTTPServer.cpp:1374
msgid "Domain must end with .i2p"
msgstr ""
#: daemon/HTTPServer.cpp:1373
#: daemon/HTTPServer.cpp:1377
msgid "Such destination is not found"
msgstr ""
#: daemon/HTTPServer.cpp:1393
#: daemon/HTTPServer.cpp:1397
msgid "Unknown command"
msgstr ""
#: daemon/HTTPServer.cpp:1397
#: daemon/HTTPServer.cpp:1401
msgid "Command accepted"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:163
#: libi2pd_client/HTTPProxy.cpp:157
msgid "Proxy error"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:171
#: libi2pd_client/HTTPProxy.cpp:165
msgid "Proxy info"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:179
#: libi2pd_client/HTTPProxy.cpp:173
msgid "Proxy error: Host not found"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:180
#: libi2pd_client/HTTPProxy.cpp:174
msgid "Remote host not found in router's addressbook"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:181
#: libi2pd_client/HTTPProxy.cpp:175
msgid "You may try to find this host on jump services below"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:282 libi2pd_client/HTTPProxy.cpp:297
#: libi2pd_client/HTTPProxy.cpp:331 libi2pd_client/HTTPProxy.cpp:372
#: libi2pd_client/HTTPProxy.cpp:273 libi2pd_client/HTTPProxy.cpp:288
#: libi2pd_client/HTTPProxy.cpp:322 libi2pd_client/HTTPProxy.cpp:365
msgid "Invalid request"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:282
#: libi2pd_client/HTTPProxy.cpp:273
msgid "Proxy unable to parse your request"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:297
#: libi2pd_client/HTTPProxy.cpp:288
msgid "addresshelper is not supported"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:306 libi2pd_client/HTTPProxy.cpp:315
#: libi2pd_client/HTTPProxy.cpp:392
#: libi2pd_client/HTTPProxy.cpp:297 libi2pd_client/HTTPProxy.cpp:306
#: libi2pd_client/HTTPProxy.cpp:385
msgid "Host"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:306
#: libi2pd_client/HTTPProxy.cpp:297
msgid "added to router's addressbook from helper"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:307
#: libi2pd_client/HTTPProxy.cpp:298
msgid "Click here to proceed:"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:307 libi2pd_client/HTTPProxy.cpp:317
#: libi2pd_client/HTTPProxy.cpp:298 libi2pd_client/HTTPProxy.cpp:308
msgid "Continue"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:308 libi2pd_client/HTTPProxy.cpp:318
#: libi2pd_client/HTTPProxy.cpp:299 libi2pd_client/HTTPProxy.cpp:309
msgid "Addresshelper found"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:315
#: libi2pd_client/HTTPProxy.cpp:306
msgid "already in router's addressbook"
msgstr ""
#. tr: The "record" means addressbook's record. That message appears when domain was already added to addressbook, but helper link is opened for it.
#: libi2pd_client/HTTPProxy.cpp:316
#: libi2pd_client/HTTPProxy.cpp:307
msgid "Click here to update record:"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:331
#: libi2pd_client/HTTPProxy.cpp:322
msgid "invalid request uri"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:372
#: libi2pd_client/HTTPProxy.cpp:365
msgid "Can't detect destination host from request"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:389 libi2pd_client/HTTPProxy.cpp:393
#: libi2pd_client/HTTPProxy.cpp:382 libi2pd_client/HTTPProxy.cpp:386
msgid "Outproxy failure"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:389
#: libi2pd_client/HTTPProxy.cpp:382
msgid "bad outproxy settings"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:392
#: libi2pd_client/HTTPProxy.cpp:385
msgid "not inside I2P network, but outproxy is not enabled"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:482
#: libi2pd_client/HTTPProxy.cpp:474
msgid "unknown outproxy url"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:490
#: libi2pd_client/HTTPProxy.cpp:480
msgid "cannot resolve upstream proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:498
#: libi2pd_client/HTTPProxy.cpp:488
msgid "hostname too long"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:525
#: libi2pd_client/HTTPProxy.cpp:515
msgid "cannot connect to upstream socks proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:531
#: libi2pd_client/HTTPProxy.cpp:521
msgid "Cannot negotiate with socks proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:573
#: libi2pd_client/HTTPProxy.cpp:563
msgid "CONNECT error"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:573
#: libi2pd_client/HTTPProxy.cpp:563
msgid "Failed to Connect"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:584 libi2pd_client/HTTPProxy.cpp:610
#: libi2pd_client/HTTPProxy.cpp:574 libi2pd_client/HTTPProxy.cpp:600
msgid "socks proxy error"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:592
#: libi2pd_client/HTTPProxy.cpp:582
msgid "failed to send request to upstream"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:613
#: libi2pd_client/HTTPProxy.cpp:603
msgid "No Reply From socks proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:620
#: libi2pd_client/HTTPProxy.cpp:610
msgid "cannot connect"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:620
#: libi2pd_client/HTTPProxy.cpp:610
msgid "http out proxy not implemented"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:621
#: libi2pd_client/HTTPProxy.cpp:611
msgid "cannot connect to upstream http proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:654
#: libi2pd_client/HTTPProxy.cpp:644
msgid "Host is down"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:654
#: libi2pd_client/HTTPProxy.cpp:644
msgid ""
"Can't create connection to requested host, it may be down. Please try again "
"later."

View File

@@ -9,8 +9,8 @@ Regex for transforming gettext translations to our format:
---
```
in: msgid\ \"(.*)\"\nmsgid_plural\ \"(.*)\"\nmsgstr\[0\]\ \"(.*)\"\n(msgstr\[1\]\ \"(.*)\"\n)?(msgstr\[2\]\ \"(.*)\"\n)?(msgstr\[3\]\ \"(.*)\"\n)?(msgstr\[4\]\ \"(.*)\"\n)?(msgstr\[5\]\ \"(.*)\"\n)?
out: #{"$2", {"$3", "$5", "$7", "$9", "$11"}},\n
in: msgid\ \"(.*)\"\nmsgid_plural\ \"(.*)\"\nmsgstr\[0\]\ \"(.*)\"\nmsgstr\[1\]\ \"(.*)\"\n(msgstr\[2\]\ \"(.*)\"\n)?(msgstr\[3\]\ \"(.*)\"\n)?(msgstr\[4\]\ \"(.*)\"\n)?(msgstr\[5\]\ \"(.*)\"\n)?
out: #{"$2", {"$3", "$4", "$6", "$8", "$10"}},\n
```
```

View File

@@ -75,8 +75,8 @@ ipv4 = true
## Enable communication through ipv6
ipv6 = false
## Enable SSU transport
ssu = false
## Enable SSU transport (default = true)
# ssu = true
## Bandwidth configuration
## L limit bandwidth to 32KBs/sec, O - to 256KBs/sec, P - to 2048KBs/sec,
@@ -96,22 +96,6 @@ ssu = false
## Note: that mode uses much more network connections and CPU!
# floodfill = true
[ntcp2]
## Enable NTCP2 transport (default = true)
# enabled = true
## Publish address in RouterInfo (default = true)
# published = true
## Port for incoming connections (default is global port option value)
# port = 4567
[ssu2]
## Enable SSU2 transport
# enabled = true
## Publish address in RouterInfo
# published = true
## Port for incoming connections (default is global port option value or port + 1 if SSU is enabled)
# port = 4567
[http]
## Web Console settings
## Uncomment and set to 'false' to disable Web Console
@@ -126,8 +110,8 @@ port = 7070
# user = i2pd
# pass = changeme
## Select webconsole language
## Currently supported english (default), afrikaans, armenian, chinese, french,
## german, italian, russian, spanish, turkmen, ukrainian and uzbek languages
## Currently supported english (default), afrikaans, armenian, german, russian,
## turkmen, ukrainian and uzbek languages
# lang = english
[httpproxy]

View File

@@ -1,7 +1,7 @@
%define git_hash %(git rev-parse HEAD | cut -c -7)
Name: i2pd-git
Version: 2.44.0
Version: 2.41.0
Release: git%{git_hash}%{?dist}
Summary: I2P router written in C++
Conflicts: i2pd
@@ -62,7 +62,9 @@ pushd redhat-linux-build
%endif
%if 0%{?fedora} >= 35
%if 0%{?fedora} < 37
pushd redhat-linux-build
%endif
%else
%if 0%{?fedora} >= 33
pushd %{_target_platform}
@@ -80,8 +82,10 @@ popd
%endif
%if 0%{?fedora} >= 33
%if 0%{?fedora} < 37
popd
%endif
%endif
%if 0%{?mageia} > 7
popd
@@ -95,7 +99,9 @@ pushd redhat-linux-build
%endif
%if 0%{?fedora} >= 35
%if 0%{?fedora} < 37
pushd redhat-linux-build
%endif
%else
%if 0%{?fedora} >= 33
pushd %{_target_platform}
@@ -158,18 +164,6 @@ getent passwd i2pd >/dev/null || \
%changelog
* Sun Nov 20 2022 orignal <orignal@i2pmail.org> - 2.44.0
- update to 2.44.0
* Mon Aug 22 2022 orignal <orignal@i2pmail.org> - 2.43.0
- update to 2.43.0
* Tue May 24 2022 r4sas <r4sas@i2pmail.org> - 2.42.1
- update to 2.42.1
* Sun May 22 2022 orignal <orignal@i2pmail.org> - 2.42.0
- update to 2.42.0
* Sun Feb 20 2022 r4sas <r4sas@i2pmail.org> - 2.41.0
- update to 2.41.0
- fixed build on Fedora Copr over openssl trunk code

View File

@@ -1,5 +1,5 @@
Name: i2pd
Version: 2.44.0
Version: 2.41.0
Release: 1%{?dist}
Summary: I2P router written in C++
Conflicts: i2pd-git
@@ -59,7 +59,9 @@ pushd redhat-linux-build
%endif
%if 0%{?fedora} >= 35
%if 0%{?fedora} < 37
pushd redhat-linux-build
%endif
%else
%if 0%{?fedora} >= 33
pushd %{_target_platform}
@@ -77,8 +79,10 @@ popd
%endif
%if 0%{?fedora} >= 33
%if 0%{?fedora} < 37
popd
%endif
%endif
%if 0%{?mageia} > 7
popd
@@ -92,7 +96,9 @@ pushd redhat-linux-build
%endif
%if 0%{?fedora} >= 35
%if 0%{?fedora} < 37
pushd redhat-linux-build
%endif
%else
%if 0%{?fedora} >= 33
pushd %{_target_platform}
@@ -155,18 +161,6 @@ getent passwd i2pd >/dev/null || \
%changelog
* Sun Nov 20 2022 orignal <orignal@i2pmail.org> - 2.44.0
- update to 2.44.0
* Mon Aug 22 2022 orignal <orignal@i2pmail.org> - 2.43.0
- update to 2.43.0
* Tue May 24 2022 r4sas <r4sas@i2pmail.org> - 2.42.1
- update to 2.42.1
* Sun May 22 2022 orignal <orignal@i2pmail.org> - 2.42.0
- update to 2.42.0
* Sun Feb 20 2022 r4sas <r4sas@i2pmail.org> - 2.41.0
- update to 2.41.0

View File

@@ -26,11 +26,14 @@
#include "Streaming.h"
#include "Destination.h"
#include "HTTPServer.h"
#ifdef WITH_I2PC
#include "I2PControl.h"
#endif
#include "ClientContext.h"
#include "Crypto.h"
#include "UPnP.h"
#include "Timestamp.h"
#include "util.h"
#include "I18N.h"
namespace i2p
@@ -44,7 +47,9 @@ namespace util
~Daemon_Singleton_Private() {};
std::unique_ptr<i2p::http::HTTPServer> httpServer;
#ifdef WITH_I2PC
std::unique_ptr<i2p::client::I2PControlService> m_I2PControlService;
#endif
std::unique_ptr<i2p::transport::UPnP> UPnP;
std::unique_ptr<i2p::util::NTPTimeSync> m_NTPSync;
};
@@ -57,7 +62,9 @@ namespace util
bool Daemon_Singleton::IsService () const
{
bool service = false;
#ifndef _WIN32
i2p::config::GetOption("service", service);
#endif
return service;
}
@@ -76,7 +83,7 @@ namespace util
i2p::config::Init();
i2p::config::ParseCmdline(argc, argv);
std::string config; i2p::config::GetOption("conf", config);
std::string config; i2p::config::GetOption("conf", config);
std::string datadir;
if(DaemonDataDir != "") {
datadir = DaemonDataDir;
@@ -108,9 +115,9 @@ namespace util
certsdir = i2p::fs::GetCertsDir();
std::string logs = ""; i2p::config::GetOption("log", logs);
std::string logfile = ""; i2p::config::GetOption("logfile", logfile);
std::string loglevel = ""; i2p::config::GetOption("loglevel", loglevel);
std::string logs = ""; i2p::config::GetOption("log", logs);
std::string logfile = ""; i2p::config::GetOption("logfile", logfile);
std::string loglevel = ""; i2p::config::GetOption("loglevel", loglevel);
bool logclftime; i2p::config::GetOption("logclftime", logclftime);
/* setup logging */
@@ -152,19 +159,116 @@ namespace util
bool aesni; i2p::config::GetOption("cpuext.aesni", aesni);
bool avx; i2p::config::GetOption("cpuext.avx", avx);
bool forceCpuExt; i2p::config::GetOption("cpuext.force", forceCpuExt);
bool ssu; i2p::config::GetOption("ssu", ssu);
if (!ssu && i2p::config::IsDefault ("precomputation.elgamal"))
precomputation = false; // we don't elgamal table if no ssu, unless it's specified explicitly
i2p::crypto::InitCrypto (precomputation, aesni, avx, forceCpuExt);
i2p::transport::InitAddressFromIface (); // get address4/6 from interfaces
int netID; i2p::config::GetOption("netid", netID);
i2p::context.SetNetID (netID);
i2p::context.Init ();
i2p::transport::InitTransports ();
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
// ifname -> address
std::string ifname; i2p::config::GetOption("ifname", ifname);
if (ipv4 && i2p::config::IsDefault ("address4"))
{
std::string ifname4; i2p::config::GetOption("ifname4", ifname4);
if (!ifname4.empty ())
i2p::config::SetOption ("address4", i2p::util::net::GetInterfaceAddress(ifname4, false).to_string ()); // v4
else if (!ifname.empty ())
i2p::config::SetOption ("address4", i2p::util::net::GetInterfaceAddress(ifname, false).to_string ()); // v4
}
if (ipv6 && i2p::config::IsDefault ("address6"))
{
std::string ifname6; i2p::config::GetOption("ifname6", ifname6);
if (!ifname6.empty ())
i2p::config::SetOption ("address6", i2p::util::net::GetInterfaceAddress(ifname6, true).to_string ()); // v6
else if (!ifname.empty ())
i2p::config::SetOption ("address6", i2p::util::net::GetInterfaceAddress(ifname, true).to_string ()); // v6
}
bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
boost::asio::ip::address_v6 yggaddr;
if (ygg)
{
std::string yggaddress; i2p::config::GetOption ("meshnets.yggaddress", yggaddress);
if (!yggaddress.empty ())
{
yggaddr = boost::asio::ip::address_v6::from_string (yggaddress);
if (yggaddr.is_unspecified () || !i2p::util::net::IsYggdrasilAddress (yggaddr) ||
!i2p::util::net::IsLocalAddress (yggaddr))
{
LogPrint(eLogWarning, "Daemon: Can't find Yggdrasil address ", yggaddress);
ygg = false;
}
}
else
{
yggaddr = i2p::util::net::GetYggdrasilAddress ();
if (yggaddr.is_unspecified ())
{
LogPrint(eLogWarning, "Daemon: Yggdrasil is not running. Disabled");
ygg = false;
}
}
}
uint16_t port; i2p::config::GetOption("port", port);
if (!i2p::config::IsDefault("port"))
{
LogPrint(eLogInfo, "Daemon: Accepting incoming connections at port ", port);
i2p::context.UpdatePort (port);
}
i2p::context.SetSupportsV6 (ipv6);
i2p::context.SetSupportsV4 (ipv4);
i2p::context.SetSupportsMesh (ygg, yggaddr);
i2p::context.RemoveNTCPAddress (!ipv6); // TODO: remove later
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
if (ntcp2)
{
bool published; i2p::config::GetOption("ntcp2.published", published);
if (published)
{
std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy);
if (!ntcp2proxy.empty ()) published = false;
}
if (published)
{
uint16_t ntcp2port; i2p::config::GetOption("ntcp2.port", ntcp2port);
if (!ntcp2port) ntcp2port = port; // use standard port
i2p::context.PublishNTCP2Address (ntcp2port, true, ipv4, ipv6, false); // publish
if (ipv6)
{
std::string ipv6Addr; i2p::config::GetOption("ntcp2.addressv6", ipv6Addr);
auto addr = boost::asio::ip::address_v6::from_string (ipv6Addr);
if (!addr.is_unspecified () && addr != boost::asio::ip::address_v6::any ())
i2p::context.UpdateNTCP2V6Address (addr); // set ipv6 address if configured
}
}
else
i2p::context.PublishNTCP2Address (port, false, ipv4, ipv6, false); // unpublish
}
if (ygg)
{
i2p::context.PublishNTCP2Address (port, true, false, false, true);
i2p::context.UpdateNTCP2V6Address (yggaddr);
if (!ipv4 && !ipv6)
i2p::context.SetStatus (eRouterStatusMesh);
}
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
if (ssu2)
{
bool published; i2p::config::GetOption("ssu2.published", published);
if (published)
{
uint16_t ssu2port; i2p::config::GetOption("ssu2.port", ssu2port);
i2p::context.PublishSSU2Address (ssu2port, true, ipv4, ipv6); // publish
}
else
i2p::context.PublishSSU2Address (0, false, ipv4, ipv6); // unpublish
}
bool transit; i2p::config::GetOption("notransit", transit);
i2p::context.SetAcceptsTunnels (!transit);
uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);
@@ -306,7 +410,7 @@ namespace util
i2p::transport::transports.SetCheckReserved(checkInReserved);
i2p::transport::transports.Start(ntcp2, ssu, ssu2);
if (i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundSSU2() || i2p::transport::transports.IsBoundNTCP2())
if (i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
LogPrint(eLogInfo, "Daemon: Transports started");
else
{
@@ -341,6 +445,7 @@ namespace util
LogPrint(eLogInfo, "Daemon: Starting Client");
i2p::client::context.Start ();
#ifdef WITH_I2PC
// I2P Control Protocol
bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol);
if (i2pcontrol) {
@@ -358,6 +463,7 @@ namespace util
ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ());
}
}
#endif
return true;
}
@@ -390,12 +496,14 @@ namespace util
d.httpServer->Stop();
d.httpServer = nullptr;
}
#ifdef WITH_I2PC
if (d.m_I2PControlService)
{
LogPrint(eLogInfo, "Daemon: Stopping I2PControl");
d.m_I2PControlService->Stop ();
d.m_I2PControlService = nullptr;
}
#endif
i2p::crypto::TerminateCrypto ();
i2p::log::Logger().Stop();

View File

@@ -68,9 +68,13 @@ namespace http {
const char HTTP_PAGE_TRANSPORTS[] = "transports";
const char HTTP_PAGE_LOCAL_DESTINATIONS[] = "local_destinations";
const char HTTP_PAGE_LOCAL_DESTINATION[] = "local_destination";
#ifdef WITH_I2CP
const char HTTP_PAGE_I2CP_LOCAL_DESTINATION[] = "i2cp_local_destination";
#endif
#ifdef WITH_SAM
const char HTTP_PAGE_SAM_SESSIONS[] = "sam_sessions";
const char HTTP_PAGE_SAM_SESSION[] = "sam_session";
#endif
const char HTTP_PAGE_I2P_TUNNELS[] = "i2p_tunnels";
const char HTTP_PAGE_COMMANDS[] = "commands";
const char HTTP_PAGE_LEASESETS[] = "leasesets";
@@ -80,14 +84,16 @@ namespace http {
const char HTTP_COMMAND_SHUTDOWN_CANCEL[] = "shutdown_cancel";
const char HTTP_COMMAND_SHUTDOWN_NOW[] = "terminate";
const char HTTP_COMMAND_RUN_PEER_TEST[] = "run_peer_test";
const char HTTP_COMMAND_RELOAD_TUNNELS_CONFIG[] = "reload_tunnels_config";
const char HTTP_COMMAND_RELOAD_CONFIG[] = "reload_config";
const char HTTP_COMMAND_LOGLEVEL[] = "set_loglevel";
const char HTTP_COMMAND_KILLSTREAM[] = "closestream";
const char HTTP_COMMAND_LIMITTRANSIT[] = "limittransit";
const char HTTP_COMMAND_GET_REG_STRING[] = "get_reg_string";
const char HTTP_COMMAND_SETLANGUAGE[] = "setlanguage";
const char HTTP_COMMAND_RELOAD_CSS[] = "reload_css";
#ifdef WITH_SAM
const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
#endif
const char HTTP_PARAM_ADDRESS[] = "address";
static std::string ConvertTime (uint64_t time)
@@ -182,7 +188,7 @@ namespace http {
" <meta charset=\"UTF-8\">\r\n"
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n"
" <link rel=\"shortcut icon\" href=\"" << itoopieFavicon << "\">\r\n"
" <title>" << tr(/* tr: Webconsole page title */ "Purple I2P Webconsole") << "</title>\r\n";
" <title>Purple I2P Webconsole</title>\r\n";
GetStyles(s);
s <<
"</head>\r\n"
@@ -202,8 +208,10 @@ namespace http {
s <<
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSPORTS << "\">" << tr ("Transports") << "</a><br>\r\n"
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_I2P_TUNNELS << "\">" << tr("I2P tunnels") << "</a><br>\r\n";
#ifdef WITH_SAM
if (i2p::client::context.GetSAMBridge ())
s << " <a href=\"" << webroot << "?page=" << HTTP_PAGE_SAM_SESSIONS << "\">" << tr("SAM sessions") << "</a><br>\r\n";
#endif
s <<
"</div>\r\n"
"<div class=\"content\">";
@@ -222,7 +230,7 @@ namespace http {
s << "<b>" << tr("ERROR") << ":</b>&nbsp;" << string << "<br>\r\n";
}
static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, RouterError error)
static void ShowNetworkStatus (std::stringstream& s, RouterStatus status)
{
switch (status)
{
@@ -232,24 +240,25 @@ namespace http {
case eRouterStatusUnknown: s << tr("Unknown"); break;
case eRouterStatusProxy: s << tr("Proxy"); break;
case eRouterStatusMesh: s << tr("Mesh"); break;
default: s << tr("Unknown");
}
if (error != eRouterErrorNone)
{
s << "<br>";
switch (error)
case eRouterStatusError:
{
case eRouterErrorClockSkew:
s << " - " << tr("Clock skew");
s << tr("Error");
switch (i2p::context.GetError ())
{
case eRouterErrorClockSkew:
s << " - " << tr("Clock skew");
break;
case eRouterErrorOffline:
s << " - " << tr("Offline");
break;
case eRouterErrorSymmetricNAT:
s << " - " << tr("Symmetric NAT");
break;
default: ;
}
break;
case eRouterErrorOffline:
s << " - " << tr("Offline");
break;
case eRouterErrorSymmetricNAT:
s << " - " << tr("Symmetric NAT");
break;
default: ;
}
default: s << tr("Unknown");
}
}
@@ -259,12 +268,12 @@ namespace http {
ShowUptime(s, i2p::context.GetUptime ());
s << "<br>\r\n";
s << "<b>" << tr("Network status") << ":</b> ";
ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetError ());
ShowNetworkStatus (s, i2p::context.GetStatus ());
s << "<br>\r\n";
if (i2p::context.SupportsV6 ())
{
s << "<b>" << tr("Network status v6") << ":</b> ";
ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetErrorV6 ());
ShowNetworkStatus (s, i2p::context.GetStatusV6 ());
s << "<br>\r\n";
}
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
@@ -323,9 +332,9 @@ namespace http {
default:
s << tr("Unknown");
}
if (address->IsV6 ())
if (address->IsV6 ())
{
if (address->IsV4 ()) s << "v4";
if (address->IsV4 ()) s << "v4";
s << "v6";
}
s << "</td>\r\n";
@@ -360,17 +369,25 @@ namespace http {
if (outputFormat==OutputFormatEnum::forWebConsole) {
bool httpproxy = i2p::client::context.GetHttpProxy () ? true : false;
bool socksproxy = i2p::client::context.GetSocksProxy () ? true : false;
bool bob = i2p::client::context.GetBOBCommandChannel () ? true : false;
bool sam = i2p::client::context.GetSAMBridge () ? true : false;
bool i2cp = i2p::client::context.GetI2CPServer () ? true : false;
bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol);
s << "<table class=\"services\"><caption>" << tr("Services") << "</caption><tbody>\r\n";
s << "<tr><td>" << "HTTP " << tr("Proxy") << "</td><td class='" << (httpproxy ? "enabled" : "disabled") << "'>" << (httpproxy ? tr("Enabled") : tr("Disabled")) << "</td></tr>\r\n";
s << "<tr><td>" << "SOCKS " << tr("Proxy") << "</td><td class='" << (socksproxy ? "enabled" : "disabled") << "'>" << (socksproxy ? tr("Enabled") : tr("Disabled")) << "</td></tr>\r\n";
#ifdef WITH_BOB
bool bob = i2p::client::context.GetBOBCommandChannel () ? true : false;
s << "<tr><td>" << "BOB" << "</td><td class='" << (bob ? "enabled" : "disabled") << "'>" << (bob ? tr("Enabled") : tr("Disabled")) << "</td></tr>\r\n";
#endif
#ifdef WITH_SAM
bool sam = i2p::client::context.GetSAMBridge () ? true : false;
s << "<tr><td>" << "SAM" << "</td><td class='" << (sam ? "enabled" : "disabled") << "'>" << (sam ? tr("Enabled") : tr("Disabled")) << "</td></tr>\r\n";
#endif
#ifdef WITH_I2CP
bool i2cp = i2p::client::context.GetI2CPServer () ? true : false;
s << "<tr><td>" << "I2CP" << "</td><td class='" << (i2cp ? "enabled" : "disabled") << "'>" << (i2cp ? tr("Enabled") : tr("Disabled")) << "</td></tr>\r\n";
#endif
#ifdef WITH_I2PC
bool i2pcontrol; i2p::config::GetOption("i2pcontrol.enabled", i2pcontrol);
s << "<tr><td>" << "I2PControl" << "</td><td class='" << (i2pcontrol ? "enabled" : "disabled") << "'>" << (i2pcontrol ? tr("Enabled") : tr("Disabled")) << "</td></tr>\r\n";
#endif
s << "</tbody></table>\r\n";
}
}
@@ -387,6 +404,7 @@ namespace http {
}
s << "</div>\r\n";
#ifdef WITH_I2CP
auto i2cpServer = i2p::client::context.GetI2CPServer ();
if (i2cpServer && !(i2cpServer->GetSessions ().empty ()))
{
@@ -404,6 +422,7 @@ namespace http {
}
s << "</div>\r\n";
}
#endif
}
static void ShowLeaseSetDestination (std::stringstream& s, std::shared_ptr<const i2p::client::LeaseSetDestination> dest, uint32_t token)
@@ -418,7 +437,7 @@ namespace http {
s << "</div>\r\n</div>\r\n";
}
if (dest->IsPublic() && token && !dest->IsEncryptedLeaseSet ())
if (dest->IsPublic() && token)
{
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
auto base32 = dest->GetIdentHash ().ToBase32 ();
@@ -530,21 +549,19 @@ namespace http {
ShowLeaseSetDestination (s, dest, token);
// Print table with streams information
s << "<table>\r\n<caption>"
<< tr("Streams")
<< "</caption>\r\n<thead>\r\n<tr>"
<< "<th style=\"width:25px;\">StreamID</th>"
<< "<th style=\"width:5px;\" \\>" // Stream closing button column
<< "<th class=\"streamdest\">Destination</th>"
<< "<th>Sent</th>"
<< "<th>Received</th>"
<< "<th>Out</th>"
<< "<th>In</th>"
<< "<th>Buf</th>"
<< "<th>RTT</th>"
<< "<th>Window</th>"
<< "<th>Status</th>"
<< "</tr>\r\n</thead>\r\n<tbody class=\"tableitem\">\r\n";
s << "<table>\r\n<caption>" << tr("Streams") << "</caption>\r\n<thead>\r\n<tr>";
s << "<th style=\"width:25px;\">StreamID</th>";
s << "<th style=\"width:5px;\" \\>"; // Stream closing button column
s << "<th class=\"streamdest\">Destination</th>";
s << "<th>Sent</th>";
s << "<th>Received</th>";
s << "<th>Out</th>";
s << "<th>In</th>";
s << "<th>Buf</th>";
s << "<th>RTT</th>";
s << "<th>Window</th>";
s << "<th>Status</th>";
s << "</tr>\r\n</thead>\r\n<tbody class=\"tableitem\">\r\n";
for (const auto& it: dest->GetAllStreams ())
{
@@ -573,6 +590,7 @@ namespace http {
}
}
#ifdef WITH_I2CP
void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id)
{
auto i2cpServer = i2p::client::context.GetI2CPServer ();
@@ -588,6 +606,7 @@ namespace http {
else
ShowError(s, tr("I2CP is not enabled"));
}
#endif
void ShowLeasesSets(std::stringstream& s)
{
@@ -698,7 +717,8 @@ namespace http {
s << "<b>" << tr("Router commands") << "</b><br>\r\n<br>\r\n<div class=\"commands\">\r\n";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_RUN_PEER_TEST << "&token=" << token << "\">" << tr("Run peer test") << "</a><br>\r\n";
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_RELOAD_TUNNELS_CONFIG << "&token=" << token << "\">" << tr("Reload tunnels configuration") << "</a><br>\r\n";
// s << " <a href=\"/?cmd=" << HTTP_COMMAND_RELOAD_CONFIG << "\">Reload config</a><br>\r\n";
if (i2p::context.AcceptsTunnels ())
s << " <a href=\"" << webroot << "?cmd=" << HTTP_COMMAND_DISABLE_TRANSIT << "&token=" << token << "\">" << tr("Decline transit tunnels") << "</a><br>\r\n";
@@ -739,25 +759,17 @@ namespace http {
s << " <button type=\"submit\">" << tr("Change") << "</button>\r\n";
s << "</form>\r\n<br>\r\n";
// get current used language
std::string currLang = i2p::client::context.GetLanguage ()->GetLanguage();
s << "<b>"
<< tr("Change language")
<< "</b><br>\r\n"
<< "<form method=\"get\" action=\"" << webroot << "\">\r\n"
<< " <input type=\"hidden\" name=\"cmd\" value=\"" << HTTP_COMMAND_SETLANGUAGE << "\">\r\n"
<< " <input type=\"hidden\" name=\"token\" value=\"" << token << "\">\r\n"
<< " <select name=\"lang\" id=\"lang\">\r\n";
std::string currLang = i2p::client::context.GetLanguage ()->GetLanguage(); // get current used language
s << "<b>" << tr("Change language") << "</b><br>\r\n";
s << "<form method=\"get\" action=\"" << webroot << "\">\r\n";
s << " <input type=\"hidden\" name=\"cmd\" value=\"" << HTTP_COMMAND_SETLANGUAGE << "\">\r\n";
s << " <input type=\"hidden\" name=\"token\" value=\"" << token << "\">\r\n";
s << " <select name=\"lang\" id=\"lang\">\r\n";
for (const auto& it: i2p::i18n::languages)
s << " <option value=\"" << it.first << "\"" << ((it.first.compare(currLang) == 0) ? " selected" : "") << ">" << it.second.LocaleName << "</option>\r\n";
s << " </select>\r\n"
<< " <button type=\"submit\">"
<< tr("Change")
<< "</button>\r\n"
<< "</form>\r\n<br>\r\n";
s << " </select>\r\n";
s << " <button type=\"submit\">" << tr("Change") << "</button>\r\n";
s << "</form>\r\n<br>\r\n";
}
@@ -791,30 +803,25 @@ namespace http {
std::stringstream tmp_s, tmp_s6; uint16_t cnt = 0, cnt6 = 0;
for (const auto& it: sessions )
{
auto endpoint = it.second->GetRemoteEndpoint ();
if (it.second && it.second->IsEstablished () && endpoint.address ().is_v4 ())
if (it.second && it.second->IsEstablished () && !it.second->GetRemoteEndpoint ().address ().is_v6 ())
{
tmp_s << "<div class=\"listitem\">\r\n";
if (it.second->IsOutgoing ()) tmp_s << " &#8658; ";
tmp_s << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": "
<< endpoint.address ().to_string () << ":" << endpoint.port ();
<< it.second->GetRemoteEndpoint ().address ().to_string ();
if (!it.second->IsOutgoing ()) tmp_s << " &#8658; ";
tmp_s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
if (it.second->GetRelayTag ())
tmp_s << " [itag:" << it.second->GetRelayTag () << "]";
tmp_s << "</div>\r\n" << std::endl;
cnt++;
}
if (it.second && it.second->IsEstablished () && endpoint.address ().is_v6 ())
if (it.second && it.second->IsEstablished () && it.second->GetRemoteEndpoint ().address ().is_v6 ())
{
tmp_s6 << "<div class=\"listitem\">\r\n";
if (it.second->IsOutgoing ()) tmp_s6 << " &#8658; ";
tmp_s6 << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": "
<< "[" << endpoint.address ().to_string () << "]:" << endpoint.port ();
<< "[" << it.second->GetRemoteEndpoint ().address ().to_string () << "]";
if (!it.second->IsOutgoing ()) tmp_s6 << " &#8658; ";
tmp_s6 << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
if (it.second->GetRelayTag ())
tmp_s6 << " [itag:" << it.second->GetRelayTag () << "]";
tmp_s6 << "</div>\r\n" << std::endl;
cnt6++;
}
@@ -892,6 +899,7 @@ namespace http {
}
}
#ifdef WITH_SAM
void ShowSAMSessions (std::stringstream& s)
{
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
@@ -954,6 +962,7 @@ namespace http {
}
s << "</div>\r\n";
}
#endif
void ShowI2PTunnels (std::stringstream& s)
{
@@ -1207,12 +1216,16 @@ namespace http {
uint32_t token = CreateToken ();
ShowLocalDestination (s, params["b32"], token);
}
#ifdef WITH_I2CP
else if (page == HTTP_PAGE_I2CP_LOCAL_DESTINATION)
ShowI2CPLocalDestination (s, params["i2cp_id"]);
#endif
#ifdef WITH_SAM
else if (page == HTTP_PAGE_SAM_SESSIONS)
ShowSAMSessions (s);
else if (page == HTTP_PAGE_SAM_SESSION)
ShowSAMSession (s, params["sam_id"]);
#endif
else if (page == HTTP_PAGE_I2P_TUNNELS)
ShowI2PTunnels (s);
else if (page == HTTP_PAGE_LEASESETS)
@@ -1245,7 +1258,7 @@ namespace http {
std::string cmd = params["cmd"];
if (cmd == HTTP_COMMAND_RUN_PEER_TEST)
i2p::transport::transports.PeerTest ();
else if (cmd == HTTP_COMMAND_RELOAD_TUNNELS_CONFIG)
else if (cmd == HTTP_COMMAND_RELOAD_CONFIG)
i2p::client::context.ReloadConfig ();
else if (cmd == HTTP_COMMAND_ENABLE_TRANSIT)
i2p::context.SetAcceptsTunnels (true);

View File

@@ -95,11 +95,15 @@ namespace http
void ShowTunnels (std::stringstream& s);
void ShowTransitTunnels (std::stringstream& s);
void ShowTransports (std::stringstream& s);
void ShowSAMSessions (std::stringstream& s);
void ShowI2PTunnels (std::stringstream& s);
void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token);
#ifdef WITH_SAM
void ShowSAMSessions (std::stringstream& s);
void ShowSAMSession (std::stringstream& s, const std::string& id);
#endif
#ifdef WITH_I2CP
void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id);
#endif
} // http
} // i2p

View File

@@ -6,6 +6,8 @@
* See full license text in LICENSE file at top of project tree
*/
#ifdef WITH_I2PC
#include <stdio.h>
#include <sstream>
#include <openssl/x509.h>
@@ -14,17 +16,25 @@
// Use global placeholders from boost introduced when local_time.hpp is loaded
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include <boost/lexical_cast.hpp>
#include <boost/date_time/local_time/local_time.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/lexical_cast.hpp>
#include "Crypto.h"
#include "FS.h"
#include "Log.h"
#include "Config.h"
#include "NetDb.hpp"
#include "Tunnel.h"
#include "RouterContext.h"
#include "Daemon.h"
#include "Tunnel.h"
#include "Timestamp.h"
#include "Transports.h"
#include "version.h"
#include "util.h"
#include "ClientContext.h"
#include "I2PControl.h"
namespace i2p
@@ -58,21 +68,53 @@ namespace client
m_SSLContext.use_private_key_file (i2pcp_key, boost::asio::ssl::context::pem);
// handlers
m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler;
m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler;
m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler;
m_MethodHandlers["RouterInfo"] = &I2PControlHandlers::RouterInfoHandler;
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
m_MethodHandlers["NetworkSetting"] = &I2PControlHandlers::NetworkSettingHandler;
m_MethodHandlers["ClientServicesInfo"] = &I2PControlHandlers::ClientServicesInfoHandler;
m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler;
m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler;
m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler;
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
// I2PControl
m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler;
// RouterInfo
m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler;
m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler;
m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler;
m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler;
m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler;
m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlService::InboundBandwidth1S;
m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
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;
m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes;
m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes;
// RouterManager
m_RouterManagerHandlers["Reseed"] = &I2PControlService::ReseedHandler;
m_RouterManagerHandlers["Shutdown"] = &I2PControlService::ShutdownHandler;
m_RouterManagerHandlers["ShutdownGraceful"] = &I2PControlService::ShutdownGracefulHandler;
// NetworkSetting
m_NetworkSettingHandlers["i2p.router.net.bw.in"] = &I2PControlService::InboundBandwidthLimit;
m_NetworkSettingHandlers["i2p.router.net.bw.out"] = &I2PControlService::OutboundBandwidthLimit;
// ClientServicesInfo
m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler;
m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler;
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
#ifdef WITH_SAM
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
#endif
#ifdef WITH_BOB
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
#endif
#ifdef WITH_I2CP
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
#endif
}
I2PControlService::~I2PControlService ()
@@ -133,7 +175,7 @@ namespace client
Accept ();
if (ecode) {
LogPrint (eLogError, "I2PControl: Accept error: ", ecode.message ());
LogPrint (eLogError, "I2PControl: Accept error: ", ecode.message ());
return;
}
LogPrint (eLogDebug, "I2PControl: New request from ", socket->lowest_layer ().remote_endpoint ());
@@ -246,6 +288,37 @@ namespace client
}
}
void I2PControlService::InsertParam (std::ostringstream& ss, const std::string& name, int value) const
{
ss << "\"" << name << "\":" << value;
}
void I2PControlService::InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value, bool quotes) const
{
ss << "\"" << name << "\":";
if (value.length () > 0)
{
if (quotes)
ss << "\"" << value << "\"";
else
ss << value;
}
else
ss << "null";
}
void I2PControlService::InsertParam (std::ostringstream& ss, const std::string& name, double value) const
{
ss << "\"" << name << "\":" << std::fixed << std::setprecision(2) << value;
}
void I2PControlService::InsertParam (std::ostringstream& ss, const std::string& name, const boost::property_tree::ptree& value) const
{
std::ostringstream buf;
boost::property_tree::write_json (buf, value, false);
ss << "\"" << name << "\":" << buf.str();
}
void I2PControlService::SendResponse (std::shared_ptr<ssl_socket> socket,
std::shared_ptr<I2PControlBuffer> buf, std::ostringstream& response, bool isHtml)
{
@@ -280,8 +353,7 @@ namespace client
}
}
// handlers
// handlers
void I2PControlService::AuthenticateHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
{
int api = params.get<int> ("API");
@@ -306,8 +378,7 @@ namespace client
}
// I2PControl
// I2PControl
void I2PControlService::I2PControlHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
{
for (auto& it: params)
@@ -331,6 +402,91 @@ namespace client
m_Tokens.clear ();
}
// RouterInfo
void I2PControlService::RouterInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
{
bool first = true;
for (auto it = params.begin (); it != params.end (); it++)
{
LogPrint (eLogDebug, "I2PControl: RouterInfo request: ", it->first);
auto it1 = m_RouterInfoHandlers.find (it->first);
if (it1 != m_RouterInfoHandlers.end ())
{
if (!first) results << ",";
else first = false;
(this->*(it1->second))(results);
}
else
LogPrint (eLogError, "I2PControl: RouterInfo unknown request ", it->first);
}
}
void I2PControlService::UptimeHandler (std::ostringstream& results)
{
InsertParam (results, "i2p.router.uptime", std::to_string (i2p::context.GetUptime ()*1000LL), false);
}
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");
}
void I2PControlService::NetDbKnownPeersHandler (std::ostringstream& results)
{
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 ());
}
void I2PControlService::NetStatusHandler (std::ostringstream& results)
{
InsertParam (results, "i2p.router.net.status", (int)i2p::context.GetStatus ());
}
void I2PControlService::TunnelsParticipatingHandler (std::ostringstream& results)
{
int transit = i2p::tunnel::tunnels.GetTransitTunnels ().size ();
InsertParam (results, "i2p.router.net.tunnels.participating", transit);
}
void I2PControlService::TunnelsSuccessRateHandler (std::ostringstream& results)
{
int rate = i2p::tunnel::tunnels.GetTunnelCreationSuccessRate ();
InsertParam (results, "i2p.router.net.tunnels.successrate", rate);
}
void I2PControlService::InboundBandwidth1S (std::ostringstream& results)
{
double bw = i2p::transport::transports.GetInBandwidth ();
InsertParam (results, "i2p.router.net.bw.inbound.1s", bw);
}
void I2PControlService::OutboundBandwidth1S (std::ostringstream& results)
{
double bw = i2p::transport::transports.GetOutBandwidth ();
InsertParam (results, "i2p.router.net.bw.outbound.1s", bw);
}
void I2PControlService::NetTotalReceivedBytes (std::ostringstream& results)
{
InsertParam (results, "i2p.router.net.total.received.bytes", (double)i2p::transport::transports.GetTotalReceivedBytes ());
}
void I2PControlService::NetTotalSentBytes (std::ostringstream& results)
{
InsertParam (results, "i2p.router.net.total.sent.bytes", (double)i2p::transport::transports.GetTotalSentBytes ());
}
// RouterManager
@@ -382,6 +538,37 @@ namespace client
i2p::data::netdb.Reseed ();
}
// network setting
void I2PControlService::NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
{
for (auto it = params.begin (); it != params.end (); it++)
{
LogPrint (eLogDebug, "I2PControl: NetworkSetting request: ", it->first);
auto it1 = m_NetworkSettingHandlers.find (it->first);
if (it1 != m_NetworkSettingHandlers.end ()) {
if (it != params.begin ()) results << ",";
(this->*(it1->second))(it->second.data (), results);
} else
LogPrint (eLogError, "I2PControl: NetworkSetting unknown request: ", it->first);
}
}
void I2PControlService::InboundBandwidthLimit (const std::string& value, std::ostringstream& results)
{
if (value != "null")
i2p::context.SetBandwidth (std::atoi(value.c_str()));
int bw = i2p::context.GetBandwidthLimit();
InsertParam (results, "i2p.router.net.bw.in", bw);
}
void I2PControlService::OutboundBandwidthLimit (const std::string& value, std::ostringstream& results)
{
if (value != "null")
i2p::context.SetBandwidth (std::atoi(value.c_str()));
int bw = i2p::context.GetBandwidthLimit();
InsertParam (results, "i2p.router.net.bw.out", bw);
}
// certificate
void I2PControlService::CreateCertificate (const char *crt_path, const char *key_path)
{
@@ -430,5 +617,184 @@ namespace client
}
EVP_PKEY_free (pkey);
}
// ClientServicesInfo
void I2PControlService::ClientServicesInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
{
for (auto it = params.begin (); it != params.end (); it++)
{
LogPrint (eLogDebug, "I2PControl: ClientServicesInfo request: ", it->first);
auto it1 = m_ClientServicesInfoHandlers.find (it->first);
if (it1 != m_ClientServicesInfoHandlers.end ())
{
if (it != params.begin ()) results << ",";
(this->*(it1->second))(results);
}
else
LogPrint (eLogError, "I2PControl: ClientServicesInfo unknown request ", it->first);
}
}
void I2PControlService::I2PTunnelInfoHandler (std::ostringstream& results)
{
boost::property_tree::ptree pt;
boost::property_tree::ptree client_tunnels, server_tunnels;
for (auto& it: i2p::client::context.GetClientTunnels ())
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
boost::property_tree::ptree ct;
ct.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
client_tunnels.add_child(it.second->GetName (), ct);
}
auto& serverTunnels = i2p::client::context.GetServerTunnels ();
if (!serverTunnels.empty ()) {
for (auto& it: serverTunnels)
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
boost::property_tree::ptree st;
st.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
st.put("port", it.second->GetLocalPort ());
server_tunnels.add_child(it.second->GetName (), st);
}
}
auto& clientForwards = i2p::client::context.GetClientForwards ();
if (!clientForwards.empty ())
{
for (auto& it: clientForwards)
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
boost::property_tree::ptree ct;
ct.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
client_tunnels.add_child(it.second->GetName (), ct);
}
}
auto& serverForwards = i2p::client::context.GetServerForwards ();
if (!serverForwards.empty ())
{
for (auto& it: serverForwards)
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
boost::property_tree::ptree st;
st.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
server_tunnels.add_child(it.second->GetName (), st);
}
}
pt.add_child("client", client_tunnels);
pt.add_child("server", server_tunnels);
InsertParam (results, "I2PTunnel", pt);
}
void I2PControlService::HTTPProxyInfoHandler (std::ostringstream& results)
{
boost::property_tree::ptree pt;
auto httpProxy = i2p::client::context.GetHttpProxy ();
if (httpProxy)
{
auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash();
pt.put("enabled", true);
pt.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
}
else
pt.put("enabled", false);
InsertParam (results, "HTTPProxy", pt);
}
void I2PControlService::SOCKSInfoHandler (std::ostringstream& results)
{
boost::property_tree::ptree pt;
auto socksProxy = i2p::client::context.GetSocksProxy ();
if (socksProxy)
{
auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash();
pt.put("enabled", true);
pt.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
}
else
pt.put("enabled", false);
InsertParam (results, "SOCKS", pt);
}
#ifdef WITH_SAM
void I2PControlService::SAMInfoHandler (std::ostringstream& results)
{
boost::property_tree::ptree pt;
auto sam = i2p::client::context.GetSAMBridge ();
if (sam)
{
pt.put("enabled", true);
boost::property_tree::ptree sam_sessions;
for (auto& it: sam->GetSessions ())
{
boost::property_tree::ptree sam_session, sam_session_sockets;
auto& name = it.second->GetLocalDestination ()->GetNickname ();
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
sam_session.put("name", name);
sam_session.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
for (const auto& socket: sam->ListSockets(it.first))
{
boost::property_tree::ptree stream;
stream.put("type", socket->GetSocketType ());
stream.put("peer", socket->GetSocket ().remote_endpoint());
sam_session_sockets.push_back(std::make_pair("", stream));
}
sam_session.add_child("sockets", sam_session_sockets);
sam_sessions.add_child(it.first, sam_session);
}
pt.add_child("sessions", sam_sessions);
}
else
pt.put("enabled", false);
InsertParam (results, "SAM", pt);
}
#endif // WITH_SAM
#ifdef WITH_BOB
void I2PControlService::BOBInfoHandler (std::ostringstream& results)
{
boost::property_tree::ptree pt;
auto bob = i2p::client::context.GetBOBCommandChannel ();
if (bob)
{
/* TODO more info */
pt.put("enabled", true);
}
else
pt.put("enabled", false);
InsertParam (results, "BOB", pt);
}
#endif // WITH_BOB
#ifdef WITH_I2CP
void I2PControlService::I2CPInfoHandler (std::ostringstream& results)
{
boost::property_tree::ptree pt;
auto i2cp = i2p::client::context.GetI2CPServer ();
if (i2cp)
{
/* TODO more info */
pt.put("enabled", true);
}
else
pt.put("enabled", false);
InsertParam (results, "I2CP", pt);
}
#endif // WITH_I2CP
}
}
#endif // WITH_I2PC

View File

@@ -6,6 +6,8 @@
* See full license text in LICENSE file at top of project tree
*/
#ifdef WITH_I2PC
#ifndef I2P_CONTROL_H__
#define I2P_CONTROL_H__
@@ -20,7 +22,6 @@
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/property_tree/ptree.hpp>
#include "I2PControlHandlers.h"
namespace i2p
{
@@ -33,7 +34,7 @@ namespace client
const char I2P_CONTROL_CERTIFICATE_COMMON_NAME[] = "i2pd.i2pcontrol";
const char I2P_CONTROL_CERTIFICATE_ORGANIZATION[] = "Purple I2P";
class I2PControlService: public I2PControlHandlers
class I2PControlService
{
typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;
@@ -64,24 +65,67 @@ namespace client
private:
void InsertParam (std::ostringstream& ss, const std::string& name, int value) const;
void InsertParam (std::ostringstream& ss, const std::string& name, double value) const;
void InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value, bool quotes = true) const;
void InsertParam (std::ostringstream& ss, const std::string& name, const boost::property_tree::ptree& value) const;
// methods
typedef void (I2PControlService::*MethodHandler)(const boost::property_tree::ptree& params, std::ostringstream& results);
void AuthenticateHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
void EchoHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
void I2PControlHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
void RouterInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
void RouterManagerHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
void NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
void ClientServicesInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
// I2PControl
typedef void (I2PControlService::*I2PControlRequestHandler)(const std::string& value);
void PasswordHandler (const std::string& value);
// RouterInfo
typedef void (I2PControlService::*RouterInfoRequestHandler)(std::ostringstream& results);
void UptimeHandler (std::ostringstream& results);
void VersionHandler (std::ostringstream& results);
void StatusHandler (std::ostringstream& results);
void NetDbKnownPeersHandler (std::ostringstream& results);
void NetDbActivePeersHandler (std::ostringstream& results);
void NetStatusHandler (std::ostringstream& results);
void TunnelsParticipatingHandler (std::ostringstream& results);
void TunnelsSuccessRateHandler (std::ostringstream& results);
void InboundBandwidth1S (std::ostringstream& results);
void OutboundBandwidth1S (std::ostringstream& results);
void NetTotalReceivedBytes (std::ostringstream& results);
void NetTotalSentBytes (std::ostringstream& results);
// RouterManager
typedef void (I2PControlService::*RouterManagerRequestHandler)(std::ostringstream& results);
void ShutdownHandler (std::ostringstream& results);
void ShutdownGracefulHandler (std::ostringstream& results);
void ReseedHandler (std::ostringstream& results);
// NetworkSetting
typedef void (I2PControlService::*NetworkSettingRequestHandler)(const std::string& value, std::ostringstream& results);
void InboundBandwidthLimit (const std::string& value, std::ostringstream& results);
void OutboundBandwidthLimit (const std::string& value, std::ostringstream& results);
// ClientServicesInfo
typedef void (I2PControlService::*ClientServicesInfoRequestHandler)(std::ostringstream& results);
void I2PTunnelInfoHandler (std::ostringstream& results);
void HTTPProxyInfoHandler (std::ostringstream& results);
void SOCKSInfoHandler (std::ostringstream& results);
#ifdef WITH_SAM
void SAMInfoHandler (std::ostringstream& results);
#endif
#ifdef WITH_BOB
void BOBInfoHandler (std::ostringstream& results);
#endif
#ifdef WITH_I2CP
void I2CPInfoHandler (std::ostringstream& results);
#endif
private:
std::string m_Password;
@@ -96,9 +140,13 @@ namespace client
std::map<std::string, MethodHandler> m_MethodHandlers;
std::map<std::string, I2PControlRequestHandler> m_I2PControlHandlers;
std::map<std::string, RouterInfoRequestHandler> m_RouterInfoHandlers;
std::map<std::string, RouterManagerRequestHandler> m_RouterManagerHandlers;
std::map<std::string, NetworkSettingRequestHandler> m_NetworkSettingHandlers;
std::map<std::string, ClientServicesInfoRequestHandler> m_ClientServicesInfoHandlers;
};
}
}
#endif
#endif // WITH_I2PC

View File

@@ -1,376 +0,0 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#include <iomanip>
#define BOOST_BIND_GLOBAL_PLACEHOLDERS
#include <boost/lexical_cast.hpp>
#include <boost/property_tree/json_parser.hpp>
#include "Log.h"
#include "RouterContext.h"
#include "NetDb.hpp"
#include "Tunnel.h"
#include "Transports.h"
#include "version.h"
#include "ClientContext.h"
#include "I2PControlHandlers.h"
namespace i2p
{
namespace client
{
I2PControlHandlers::I2PControlHandlers ()
{
// RouterInfo
m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlHandlers::UptimeHandler;
m_RouterInfoHandlers["i2p.router.version"] = &I2PControlHandlers::VersionHandler;
m_RouterInfoHandlers["i2p.router.status"] = &I2PControlHandlers::StatusHandler;
m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlHandlers::NetDbKnownPeersHandler;
m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlHandlers::NetDbActivePeersHandler;
m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlHandlers::InboundBandwidth1S;
m_RouterInfoHandlers["i2p.router.net.bw.outbound.1s"] = &I2PControlHandlers::OutboundBandwidth1S;
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlHandlers::NetStatusHandler;
m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlHandlers::TunnelsParticipatingHandler;
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] = &I2PControlHandlers::TunnelsSuccessRateHandler;
m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlHandlers::NetTotalReceivedBytes;
m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlHandlers::NetTotalSentBytes;
// NetworkSetting
m_NetworkSettingHandlers["i2p.router.net.bw.in"] = &I2PControlHandlers::InboundBandwidthLimit;
m_NetworkSettingHandlers["i2p.router.net.bw.out"] = &I2PControlHandlers::OutboundBandwidthLimit;
// ClientServicesInfo
m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlHandlers::I2PTunnelInfoHandler;
m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlHandlers::HTTPProxyInfoHandler;
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlHandlers::SOCKSInfoHandler;
m_ClientServicesInfoHandlers["SAM"] = &I2PControlHandlers::SAMInfoHandler;
m_ClientServicesInfoHandlers["BOB"] = &I2PControlHandlers::BOBInfoHandler;
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlHandlers::I2CPInfoHandler;
}
void I2PControlHandlers::InsertParam (std::ostringstream& ss, const std::string& name, int value) const
{
ss << "\"" << name << "\":" << value;
}
void I2PControlHandlers::InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value, bool quotes) const
{
ss << "\"" << name << "\":";
if (value.length () > 0)
{
if (quotes)
ss << "\"" << value << "\"";
else
ss << value;
}
else
ss << "null";
}
void I2PControlHandlers::InsertParam (std::ostringstream& ss, const std::string& name, double value) const
{
ss << "\"" << name << "\":" << std::fixed << std::setprecision(2) << value;
}
void I2PControlHandlers::InsertParam (std::ostringstream& ss, const std::string& name, const boost::property_tree::ptree& value) const
{
std::ostringstream buf;
boost::property_tree::write_json (buf, value, false);
ss << "\"" << name << "\":" << buf.str();
}
// RouterInfo
void I2PControlHandlers::RouterInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
{
bool first = true;
for (auto it = params.begin (); it != params.end (); it++)
{
LogPrint (eLogDebug, "I2PControl: RouterInfo request: ", it->first);
auto it1 = m_RouterInfoHandlers.find (it->first);
if (it1 != m_RouterInfoHandlers.end ())
{
if (!first) results << ",";
else first = false;
(this->*(it1->second))(results);
}
else
LogPrint (eLogError, "I2PControl: RouterInfo unknown request ", it->first);
}
}
void I2PControlHandlers::UptimeHandler (std::ostringstream& results)
{
InsertParam (results, "i2p.router.uptime", std::to_string (i2p::context.GetUptime ()*1000LL), false);
}
void I2PControlHandlers::VersionHandler (std::ostringstream& results)
{
InsertParam (results, "i2p.router.version", VERSION);
}
void I2PControlHandlers::StatusHandler (std::ostringstream& results)
{
auto dest = i2p::client::context.GetSharedLocalDestination ();
InsertParam (results, "i2p.router.status", (dest && dest->IsReady ()) ? "1" : "0");
}
void I2PControlHandlers::NetDbKnownPeersHandler (std::ostringstream& results)
{
InsertParam (results, "i2p.router.netdb.knownpeers", i2p::data::netdb.GetNumRouters ());
}
void I2PControlHandlers::NetDbActivePeersHandler (std::ostringstream& results)
{
InsertParam (results, "i2p.router.netdb.activepeers", (int)i2p::transport::transports.GetPeers ().size ());
}
void I2PControlHandlers::NetStatusHandler (std::ostringstream& results)
{
InsertParam (results, "i2p.router.net.status", (int)i2p::context.GetStatus ());
}
void I2PControlHandlers::TunnelsParticipatingHandler (std::ostringstream& results)
{
int transit = i2p::tunnel::tunnels.GetTransitTunnels ().size ();
InsertParam (results, "i2p.router.net.tunnels.participating", transit);
}
void I2PControlHandlers::TunnelsSuccessRateHandler (std::ostringstream& results)
{
int rate = i2p::tunnel::tunnels.GetTunnelCreationSuccessRate ();
InsertParam (results, "i2p.router.net.tunnels.successrate", rate);
}
void I2PControlHandlers::InboundBandwidth1S (std::ostringstream& results)
{
double bw = i2p::transport::transports.GetInBandwidth ();
InsertParam (results, "i2p.router.net.bw.inbound.1s", bw);
}
void I2PControlHandlers::OutboundBandwidth1S (std::ostringstream& results)
{
double bw = i2p::transport::transports.GetOutBandwidth ();
InsertParam (results, "i2p.router.net.bw.outbound.1s", bw);
}
void I2PControlHandlers::NetTotalReceivedBytes (std::ostringstream& results)
{
InsertParam (results, "i2p.router.net.total.received.bytes", (double)i2p::transport::transports.GetTotalReceivedBytes ());
}
void I2PControlHandlers::NetTotalSentBytes (std::ostringstream& results)
{
InsertParam (results, "i2p.router.net.total.sent.bytes", (double)i2p::transport::transports.GetTotalSentBytes ());
}
// network setting
void I2PControlHandlers::NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
{
for (auto it = params.begin (); it != params.end (); it++)
{
LogPrint (eLogDebug, "I2PControl: NetworkSetting request: ", it->first);
auto it1 = m_NetworkSettingHandlers.find (it->first);
if (it1 != m_NetworkSettingHandlers.end ()) {
if (it != params.begin ()) results << ",";
(this->*(it1->second))(it->second.data (), results);
} else
LogPrint (eLogError, "I2PControl: NetworkSetting unknown request: ", it->first);
}
}
void I2PControlHandlers::InboundBandwidthLimit (const std::string& value, std::ostringstream& results)
{
if (value != "null")
i2p::context.SetBandwidth (std::atoi(value.c_str()));
int bw = i2p::context.GetBandwidthLimit();
InsertParam (results, "i2p.router.net.bw.in", bw);
}
void I2PControlHandlers::OutboundBandwidthLimit (const std::string& value, std::ostringstream& results)
{
if (value != "null")
i2p::context.SetBandwidth (std::atoi(value.c_str()));
int bw = i2p::context.GetBandwidthLimit();
InsertParam (results, "i2p.router.net.bw.out", bw);
}
// ClientServicesInfo
void I2PControlHandlers::ClientServicesInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
{
for (auto it = params.begin (); it != params.end (); it++)
{
LogPrint (eLogDebug, "I2PControl: ClientServicesInfo request: ", it->first);
auto it1 = m_ClientServicesInfoHandlers.find (it->first);
if (it1 != m_ClientServicesInfoHandlers.end ())
{
if (it != params.begin ()) results << ",";
(this->*(it1->second))(results);
}
else
LogPrint (eLogError, "I2PControl: ClientServicesInfo unknown request ", it->first);
}
}
void I2PControlHandlers::I2PTunnelInfoHandler (std::ostringstream& results)
{
boost::property_tree::ptree pt;
boost::property_tree::ptree client_tunnels, server_tunnels;
for (auto& it: i2p::client::context.GetClientTunnels ())
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
boost::property_tree::ptree ct;
ct.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
client_tunnels.add_child(it.second->GetName (), ct);
}
auto& serverTunnels = i2p::client::context.GetServerTunnels ();
if (!serverTunnels.empty ()) {
for (auto& it: serverTunnels)
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
boost::property_tree::ptree st;
st.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
st.put("port", it.second->GetLocalPort ());
server_tunnels.add_child(it.second->GetName (), st);
}
}
auto& clientForwards = i2p::client::context.GetClientForwards ();
if (!clientForwards.empty ())
{
for (auto& it: clientForwards)
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
boost::property_tree::ptree ct;
ct.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
client_tunnels.add_child(it.second->GetName (), ct);
}
}
auto& serverForwards = i2p::client::context.GetServerForwards ();
if (!serverForwards.empty ())
{
for (auto& it: serverForwards)
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
boost::property_tree::ptree st;
st.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
server_tunnels.add_child(it.second->GetName (), st);
}
}
pt.add_child("client", client_tunnels);
pt.add_child("server", server_tunnels);
InsertParam (results, "I2PTunnel", pt);
}
void I2PControlHandlers::HTTPProxyInfoHandler (std::ostringstream& results)
{
boost::property_tree::ptree pt;
auto httpProxy = i2p::client::context.GetHttpProxy ();
if (httpProxy)
{
auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash();
pt.put("enabled", true);
pt.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
}
else
pt.put("enabled", false);
InsertParam (results, "HTTPProxy", pt);
}
void I2PControlHandlers::SOCKSInfoHandler (std::ostringstream& results)
{
boost::property_tree::ptree pt;
auto socksProxy = i2p::client::context.GetSocksProxy ();
if (socksProxy)
{
auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash();
pt.put("enabled", true);
pt.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
}
else
pt.put("enabled", false);
InsertParam (results, "SOCKS", pt);
}
void I2PControlHandlers::SAMInfoHandler (std::ostringstream& results)
{
boost::property_tree::ptree pt;
auto sam = i2p::client::context.GetSAMBridge ();
if (sam)
{
pt.put("enabled", true);
boost::property_tree::ptree sam_sessions;
for (auto& it: sam->GetSessions ())
{
boost::property_tree::ptree sam_session, sam_session_sockets;
auto& name = it.second->GetLocalDestination ()->GetNickname ();
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
sam_session.put("name", name);
sam_session.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
for (const auto& socket: sam->ListSockets(it.first))
{
boost::property_tree::ptree stream;
stream.put("type", socket->GetSocketType ());
stream.put("peer", socket->GetSocket ().remote_endpoint());
sam_session_sockets.push_back(std::make_pair("", stream));
}
sam_session.add_child("sockets", sam_session_sockets);
sam_sessions.add_child(it.first, sam_session);
}
pt.add_child("sessions", sam_sessions);
}
else
pt.put("enabled", false);
InsertParam (results, "SAM", pt);
}
void I2PControlHandlers::BOBInfoHandler (std::ostringstream& results)
{
boost::property_tree::ptree pt;
auto bob = i2p::client::context.GetBOBCommandChannel ();
if (bob)
{
/* TODO more info */
pt.put("enabled", true);
}
else
pt.put("enabled", false);
InsertParam (results, "BOB", pt);
}
void I2PControlHandlers::I2CPInfoHandler (std::ostringstream& results)
{
boost::property_tree::ptree pt;
auto i2cp = i2p::client::context.GetI2CPServer ();
if (i2cp)
{
/* TODO more info */
pt.put("enabled", true);
}
else
pt.put("enabled", false);
InsertParam (results, "I2CP", pt);
}
}
}

View File

@@ -1,80 +0,0 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#ifndef I2P_CONTROL_HANDLERS_H__
#define I2P_CONTROL_HANDLERS_H__
#include <sstream>
#include <map>
#include <string>
#include <boost/property_tree/ptree.hpp>
namespace i2p
{
namespace client
{
class I2PControlHandlers
{
public:
I2PControlHandlers ();
// methods
// TODO: make protected
void RouterInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
void NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
void ClientServicesInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
protected:
void InsertParam (std::ostringstream& ss, const std::string& name, int value) const;
void InsertParam (std::ostringstream& ss, const std::string& name, double value) const;
void InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value, bool quotes = true) const;
void InsertParam (std::ostringstream& ss, const std::string& name, const boost::property_tree::ptree& value) const;
private:
// RouterInfo
typedef void (I2PControlHandlers::*RouterInfoRequestHandler)(std::ostringstream& results);
void UptimeHandler (std::ostringstream& results);
void VersionHandler (std::ostringstream& results);
void StatusHandler (std::ostringstream& results);
void NetDbKnownPeersHandler (std::ostringstream& results);
void NetDbActivePeersHandler (std::ostringstream& results);
void NetStatusHandler (std::ostringstream& results);
void TunnelsParticipatingHandler (std::ostringstream& results);
void TunnelsSuccessRateHandler (std::ostringstream& results);
void InboundBandwidth1S (std::ostringstream& results);
void OutboundBandwidth1S (std::ostringstream& results);
void NetTotalReceivedBytes (std::ostringstream& results);
void NetTotalSentBytes (std::ostringstream& results);
// NetworkSetting
typedef void (I2PControlHandlers::*NetworkSettingRequestHandler)(const std::string& value, std::ostringstream& results);
void InboundBandwidthLimit (const std::string& value, std::ostringstream& results);
void OutboundBandwidthLimit (const std::string& value, std::ostringstream& results);
// ClientServicesInfo
typedef void (I2PControlHandlers::*ClientServicesInfoRequestHandler)(std::ostringstream& results);
void I2PTunnelInfoHandler (std::ostringstream& results);
void HTTPProxyInfoHandler (std::ostringstream& results);
void SOCKSInfoHandler (std::ostringstream& results);
void SAMInfoHandler (std::ostringstream& results);
void BOBInfoHandler (std::ostringstream& results);
void I2CPInfoHandler (std::ostringstream& results);
private:
std::map<std::string, RouterInfoRequestHandler> m_RouterInfoHandlers;
std::map<std::string, NetworkSettingRequestHandler> m_NetworkSettingHandlers;
std::map<std::string, ClientServicesInfoRequestHandler> m_ClientServicesInfoHandlers;
};
}
}
#endif

View File

@@ -93,7 +93,7 @@ namespace transport
#endif
isError = err != UPNPDISCOVER_SUCCESS;
#else // MINIUPNPC_API_VERSION >= 8
#else // MINIUPNPC_API_VERSION >= 8
err = 0;
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
isError = m_Devlist == NULL;

View File

@@ -51,7 +51,7 @@ namespace transport
private:
void Discover ();
int CheckMapping (const char* port, const char* type);
int CheckMapping (const char* port, const char* type);
void PortMapping ();
void TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
void CloseMapping ();
@@ -80,7 +80,7 @@ namespace transport
}
}
#else // USE_UPNP
#else // USE_UPNP
namespace i2p {
namespace transport {
/* class stub */

View File

@@ -24,7 +24,6 @@
#include "Tunnel.h"
#include "RouterContext.h"
#include "ClientContext.h"
#include "Transports.h"
void handle_signal(int sig)
{
@@ -55,14 +54,6 @@ void handle_signal(int sig)
case SIGPIPE:
LogPrint(eLogInfo, "SIGPIPE received");
break;
case SIGTSTP:
LogPrint(eLogInfo, "Daemon: Got SIGTSTP, disconnecting from network...");
i2p::transport::transports.SetOnline(false);
break;
case SIGCONT:
LogPrint(eLogInfo, "Daemon: Got SIGCONT, restoring connection to network...");
i2p::transport::transports.SetOnline(true);
break;
}
}
@@ -180,9 +171,6 @@ namespace i2p
}
gracefulShutdownInterval = 0; // not specified
// handle signal TSTP
bool handleTSTP; i2p::config::GetOption("unix.handle_sigtstp", handleTSTP);
// Signal handler
struct sigaction sa;
sa.sa_handler = handle_signal;
@@ -194,11 +182,6 @@ namespace i2p
sigaction(SIGTERM, &sa, 0);
sigaction(SIGINT, &sa, 0);
sigaction(SIGPIPE, &sa, 0);
if (handleTSTP)
{
sigaction(SIGTSTP, &sa, 0);
sigaction(SIGCONT, &sa, 0);
}
return Daemon_Singleton::start();
}

25
debian/changelog vendored
View File

@@ -1,28 +1,3 @@
i2pd (2.44.0-1) unstable; urgency=medium
* updated to version 2.44.0/0.9.56
-- orignal <orignal@i2pmail.org> Sun, 20 Nov 2022 19:00:00 +0000
i2pd (2.43.0-1) unstable; urgency=medium
* updated to version 2.43.0/0.9.55
-- orignal <orignal@i2pmail.org> Mon, 22 Aug 2022 16:00:00 +0000
i2pd (2.42.1-1) unstable; urgency=medium
* updated to version 2.42.1/0.9.54
* remove -O3 optimization flag
-- r4sas <r4sas@i2pmail.org> Tue, 24 May 2022 12:00:00 +0000
i2pd (2.42.0-1) unstable; urgency=medium
* updated to version 2.42.0/0.9.54
-- orignal <orignal@i2pmail.org> Sun, 22 May 2022 16:00:00 +0000
i2pd (2.41.0-1) unstable; urgency=medium
* updated to version 2.41.0/0.9.53

7
debian/rules vendored
View File

@@ -1,12 +1,17 @@
#!/usr/bin/make -f
#export DH_VERBOSE=1
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
include /usr/share/dpkg/architecture.mk
export DEB_CXXFLAGS_MAINT_APPEND = -Wall -pedantic
export DEB_CXXFLAGS_MAINT_APPEND = -Wall -pedantic -O3
export DEB_LDFLAGS_MAINT_APPEND =
%:
dh $@ --parallel

View File

@@ -1,217 +0,0 @@
/*
* Copyright (c) 2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#include <map>
#include <vector>
#include <string>
#include <memory>
#include "I18N.h"
// Simplified Chinese localization file
// This is an example translation file without strings in it.
namespace i2p
{
namespace i18n
{
namespace chinese // language namespace
{
// language name in lowercase
static std::string language = "chinese";
// See for language plural forms here:
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
static int plural (int n) {
return 0;
}
static std::map<std::string, std::string> strings
{
{"KiB", "KiB"},
{"MiB", "MiB"},
{"GiB", "GiB"},
{"building", "正在构建"},
{"failed", "连接失败"},
{"expiring", "即将过期"},
{"established", "连接成功"},
{"unknown", "未知"},
{"exploratory", "探索"},
{"Purple I2P Webconsole", "Purple I2P 网页控制台"},
{"<b>i2pd</b> webconsole", "<b>i2pd</b> 网页控制台"},
{"Main page", "主页"},
{"Router commands", "路由命令"},
{"Local Destinations", "本地目标"},
{"LeaseSets", "租契集"},
{"Tunnels", "隧道"},
{"Transit Tunnels", "中转隧道"},
{"Transports", "传输"},
{"I2P tunnels", "I2P 隧道"},
{"SAM sessions", "SAM 会话"},
{"ERROR", "错误"},
{"OK", "良好"},
{"Testing", "测试中"},
{"Firewalled", "受到防火墙限制"},
{"Unknown", "未知"},
{"Proxy", "代理"},
{"Mesh", "Mesh组网"},
{"Error", "错误"},
{"Clock skew", "时钟偏移"},
{"Offline", "离线"},
{"Symmetric NAT", "对称 NAT"},
{"Uptime", "运行时间"},
{"Network status", "IPv4 网络状态"},
{"Network status v6", "IPv6 网络状态"},
{"Stopping in", "距停止还有:"},
{"Family", "家族"},
{"Tunnel creation success rate", "隧道创建成功率"},
{"Received", "已接收"},
{"KiB/s", "KiB/s"},
{"Sent", "已发送"},
{"Transit", "中转"},
{"Data path", "数据文件路径"},
{"Hidden content. Press on text to see.", "隐藏内容 请点击此处查看。"},
{"Router Ident", "路由身份"},
{"Router Family", "路由器家族"},
{"Router Caps", "路由器类型"},
{"Version", "版本"},
{"Our external address", "外部地址"},
{"supported", "支持"},
{"Routers", "路由节点"},
{"Floodfills", "洪泛节点"},
{"Client Tunnels", "客户端隧道"},
{"Services", "服务"},
{"Enabled", "启用"},
{"Disabled", "禁用"},
{"Encrypted B33 address", "加密的 B33 地址"},
{"Address registration line", "地址域名注册"},
{"Domain", "域名"},
{"Generate", "生成"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>注意:</b> 结果字符串只能用于注册次级域名(例如example.i2p)。若需注册子域名,请使用 i2pd-tools。"},
{"Address", "地址"},
{"Type", "类型"},
{"EncType", "加密类型"},
{"Inbound tunnels", "入站隧道"},
{"ms", "毫秒"},
{"Outbound tunnels", "出站隧道"},
{"Tags", "标签"},
{"Incoming", "传入"},
{"Outgoing", "传出"},
{"Destination", "目标"},
{"Amount", "数量"},
{"Incoming Tags", "传入标签"},
{"Tags sessions", "标签会话"},
{"Status", "状态"},
{"Local Destination", "本地目标"},
{"Streams", ""},
{"Close stream", "断开流"},
{"I2CP session not found", "未找到 I2CP 会话"},
{"I2CP is not enabled", "I2CP 未启用"},
{"Invalid", "无效"},
{"Store type", "存储类型"},
{"Expires", "过期时间"},
{"Non Expired Leases", "未到期的租约"},
{"Gateway", "网关"},
{"TunnelID", "隧道 ID"},
{"EndDate", "结束日期"},
{"not floodfill", "非洪泛"},
{"Queue size", "队列大小"},
{"Run peer test", "运行节点测试"},
{"Decline transit tunnels", "拒绝中转隧道"},
{"Accept transit tunnels", "允许中转隧道"},
{"Cancel graceful shutdown", "取消平滑关闭"},
{"Start graceful shutdown", "平滑关闭"},
{"Force shutdown", "强制停止"},
{"Reload external CSS styles", "重载外部 CSS 样式"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>注意:</b> 此处完成的任何操作都不是永久的,不会更改您的配置文件。"},
{"Logging level", "日志记录级别"},
{"Transit tunnels limit", "中转隧道限制"},
{"Change", "修改"},
{"Change language", "更改语言"},
{"no transit tunnels currently built", "目前未构建中转隧道"},
{"SAM disabled", "SAM 已禁用"},
{"no sessions currently running", "没有正在运行的会话"},
{"SAM session not found", "未找到 SAM 会话"},
{"SAM Session", "SAM 会话"},
{"Server Tunnels", "服务器隧道"},
{"Client Forwards", "客户端转发"},
{"Server Forwards", "服务器转发"},
{"Unknown page", "未知页面"},
{"Invalid token", "无效令牌"},
{"SUCCESS", "成功"},
{"Stream closed", "流已关闭"},
{"Stream not found or already was closed", "流未找到或已关闭"},
{"Destination not found", "找不到目标"},
{"StreamID can't be null", "StreamID 不能为空"},
{"Return to destination page", "返回目标页面"},
{"You will be redirected in 5 seconds", "您将在5秒内被重定向"},
{"Transit tunnels count must not exceed 65535", "中转隧道数量不能超过 65535"},
{"Back to commands list", "返回命令列表"},
{"Register at reg.i2p", "在 reg.i2p 注册域名"},
{"Description", "描述"},
{"A bit information about service on domain", "在此域名上运行的服务的一些信息"},
{"Submit", "提交"},
{"Domain can't end with .b32.i2p", "域名不能以 .b32.i2p 结尾"},
{"Domain must end with .i2p", "域名必须以 .i2p 结尾"},
{"Such destination is not found", "找不到此目标"},
{"Unknown command", "未知指令"},
{"Command accepted", "已接受指令"},
{"Proxy error", "代理错误"},
{"Proxy info", "代理信息"},
{"Proxy error: Host not found", "代理错误:未找到主机"},
{"Remote host not found in router's addressbook", "在路由地址簿中未找到远程主机"},
{"You may try to find this host on jump services below", "您可以尝试在下方的跳转服务中找到该主机"},
{"Invalid request", "无效请求"},
{"Proxy unable to parse your request", "代理无法解析您的请求"},
{"addresshelper is not supported", "不支持地址助手"},
{"Host", "主机"},
{"added to router's addressbook from helper", "将此地址从地址助手添加到路由地址簿"},
{"Click here to proceed:", "点击此处继续:"},
{"Continue", "继续"},
{"Addresshelper found", "已找到地址助手"},
{"already in router's addressbook", "已在路由地址簿中"},
{"Click here to update record:", "点击此处更新地址簿记录"},
{"invalid request uri", "无效的 URL 请求"},
{"Can't detect destination host from request", "无法从请求中检测到目标主机"},
{"Outproxy failure", "出口代理故障"},
{"bad outproxy settings", "错误的出口代理设置"},
{"not inside I2P network, but outproxy is not enabled", "该地址不在 I2P 网络内,但未启用出口代理"},
{"unknown outproxy url", "未知的出口代理地址"},
{"cannot resolve upstream proxy", "无法解析上游代理"},
{"hostname too long", "主机名过长"},
{"cannot connect to upstream socks proxy", "无法连接到上游 socks 代理"},
{"Cannot negotiate with socks proxy", "无法与 socks 代理协商"},
{"CONNECT error", "连接错误"},
{"Failed to Connect", "连接失败"},
{"socks proxy error", "socks 代理错误"},
{"failed to send request to upstream", "向上游发送请求失败"},
{"No Reply From socks proxy", "没有来自 socks 代理的回复"},
{"cannot connect", "无法连接"},
{"http out proxy not implemented", "http 出口代理未实现"},
{"cannot connect to upstream http proxy", "无法连接到上游 http 代理"},
{"Host is down", "主机已关闭"},
{"Can't create connection to requested host, it may be down. Please try again later.", "无法创建到目标主机的连接。主机可能已下线,请稍后再试。"},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {""}},
{"hours", {""}},
{"minutes", {""}},
{"seconds", {""}},
{"", {""}},
};
std::shared_ptr<const i2p::i18n::Locale> GetLocale()
{
return std::make_shared<i2p::i18n::Locale>(language, strings, plurals, [] (int n)->int { return plural(n); });
}
} // language
} // i18n
} // i2p

View File

@@ -1,211 +0,0 @@
/*
* Copyright (c) 2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#include <map>
#include <vector>
#include <string>
#include <memory>
#include "I18N.h"
// French localization file
namespace i2p
{
namespace i18n
{
namespace french // language namespace
{
// language name in lowercase
static std::string language = "french";
// See for language plural forms here:
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
static int plural (int n) {
return n != 1 ? 1 : 0;
}
static std::map<std::string, std::string> strings
{
{"KiB", "Kio"},
{"MiB", "Mio"},
{"GiB", "Gio"},
{"building", "En construction"},
{"failed", "échoué"},
{"expiring", "expiré"},
{"established", "établi"},
{"unknown", "inconnu"},
{"exploratory", "exploratoire"},
{"Purple I2P Webconsole", "Console web Purple I2P"},
{"<b>i2pd</b> webconsole", "Console web <b>i2pd</b>"},
{"Main page", "Page principale"},
{"Router commands", "Commandes du routeur"},
{"Local Destinations", "Destinations locales"},
{"LeaseSets", "Jeu de baux"},
{"Tunnels", "Tunnels"},
{"Transit Tunnels", "Tunnels transitoires"},
{"Transports", "Transports"},
{"I2P tunnels", "Tunnels I2P"},
{"SAM sessions", "Sessions SAM"},
{"ERROR", "ERREUR"},
{"OK", "OK"},
{"Testing", "Test en cours"},
{"Firewalled", "Derrière un pare-feu"},
{"Unknown", "Inconnu"},
{"Proxy", "Proxy"},
{"Mesh", "Maillé"},
{"Error", "Erreur"},
{"Clock skew", "Horloge décalée"},
{"Offline", "Hors ligne"},
{"Symmetric NAT", "NAT symétrique"},
{"Uptime", "Temps de fonctionnement"},
{"Network status", "État du réseau"},
{"Network status v6", "État du réseau v6"},
{"Stopping in", "Arrêt dans"},
{"Family", "Famille"},
{"Tunnel creation success rate", "Taux de succès de création de tunnels"},
{"Received", "Reçu"},
{"KiB/s", "kio/s"},
{"Sent", "Envoyé"},
{"Transit", "Transité"},
{"Data path", "Emplacement des données"},
{"Hidden content. Press on text to see.", "Contenu caché. Cliquez sur le texte pour afficher."},
{"Router Ident", "Identifiant du routeur"},
{"Router Family", "Famille du routeur"},
{"Router Caps", "Limiteurs du routeur"},
{"Version", "Version"},
{"Our external address", "Notre adresse externe"},
{"supported", "supporté"},
{"Routers", "Routeurs"},
{"Client Tunnels", "Tunnels clients"},
{"Services", "Services"},
{"Enabled", "Activé"},
{"Disabled", "Désactivé"},
{"Encrypted B33 address", "Adresse B33 chiffrée"},
{"Address registration line", "Ligne d'inscription de l'adresse"},
{"Domain", "Domaine"},
{"Generate", "Générer"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Note:</b> La chaîne résultante peut seulement être utilisée pour enregistrer les domaines 2LD (exemple.i2p). Pour enregistrer des sous-domaines, veuillez utiliser i2pd-tools."},
{"Address", "Adresse"},
{"Type", "Type"},
{"Inbound tunnels", "Tunnels entrants"},
{"ms", "ms"},
{"Outbound tunnels", "Tunnels sortants"},
{"Tags", "Balises"},
{"Incoming", "Entrant"},
{"Outgoing", "Sortant"},
{"Destination", "Destination"},
{"Amount", "Quantité"},
{"Incoming Tags", "Balises entrantes"},
{"Tags sessions", "Sessions des balises"},
{"Status", "Statut"},
{"Local Destination", "Destination locale"},
{"Streams", "Flux"},
{"Close stream", "Fermer le flux"},
{"I2CP session not found", "Session I2CP introuvable"},
{"I2CP is not enabled", "I2CP est désactivé"},
{"Invalid", "Invalide"},
{"Store type", "Type de stockage"},
{"Expires", "Expire"},
{"Non Expired Leases", "Baux non expirés"},
{"Gateway", "Passerelle"},
{"TunnelID", "ID du tunnel"},
{"EndDate", "Date de fin"},
{"Queue size", "Longueur de la file"},
{"Run peer test", "Lancer test des pairs"},
{"Decline transit tunnels", "Refuser les tunnels transitoires"},
{"Accept transit tunnels", "Accepter les tunnels transitoires"},
{"Cancel graceful shutdown", "Annuler l'arrêt gracieux"},
{"Start graceful shutdown", "Démarrer l'arrêt gracieux"},
{"Force shutdown", "Forcer l'arrêt"},
{"Reload external CSS styles", "Rafraîchir les styles CSS externes"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Note:</b> Toute action effectuée ici n'est pas permanente et ne modifie pas vos fichiers de configuration."},
{"Logging level", "Niveau de journalisation"},
{"Transit tunnels limit", "Limite sur les tunnels transitoires"},
{"Change", "Changer"},
{"Change language", "Changer la langue"},
{"no transit tunnels currently built", "aucun tunnel transitoire présentement établi"},
{"SAM disabled", "SAM désactivé"},
{"no sessions currently running", "aucune session présentement en cours"},
{"SAM session not found", "session SAM introuvable"},
{"SAM Session", "Session SAM"},
{"Server Tunnels", "Tunnels serveurs"},
{"Unknown page", "Page inconnue"},
{"Invalid token", "Jeton invalide"},
{"SUCCESS", "SUCCÈS"},
{"Stream closed", "Flux fermé"},
{"Stream not found or already was closed", "Flux introuvable ou déjà fermé"},
{"Destination not found", "Destination introuvable"},
{"StreamID can't be null", "StreamID ne peut pas être vide"},
{"Return to destination page", "Retourner à la page de destination"},
{"You will be redirected in 5 seconds", "Vous allez être redirigé dans cinq secondes"},
{"Transit tunnels count must not exceed 65535", "Le nombre de tunnels transitoires ne doit pas dépasser 65535"},
{"Back to commands list", "Retour à la liste des commandes"},
{"Register at reg.i2p", "Inscription à reg.i2p"},
{"Description", "Description"},
{"A bit information about service on domain", "Un peu d'information à propos des services disponibles dans le domaine"},
{"Submit", "Soumettre"},
{"Domain can't end with .b32.i2p", "Le domaine ne peut pas terminer par .b32.i2p"},
{"Domain must end with .i2p", "Le domaine doit terminer par .i2p"},
{"Such destination is not found", "Cette destination est introuvable"},
{"Unknown command", "Commande inconnue"},
{"Command accepted", "Commande acceptée"},
{"Proxy error", "Erreur de proxy"},
{"Proxy info", "Information sur le proxy"},
{"Proxy error: Host not found", "Erreur de proxy: Hôte introuvable"},
{"Remote host not found in router's addressbook", "Hôte distant introuvable dans le carnet d'adresse du routeur"},
{"You may try to find this host on jump services below", "Vous pouvez essayer de trouver cet hôte sur des services de redirection ci-dessous"},
{"Invalid request", "Requête invalide"},
{"Proxy unable to parse your request", "Proxy incapable de comprendre votre requête"},
{"addresshelper is not supported", "Assistant d'adresse non supporté"},
{"Host", "Hôte"},
{"added to router's addressbook from helper", "Ajouté au carnet d'adresse du routeur par l'assistant"},
{"Click here to proceed:", "Cliquez ici pour continuer:"},
{"Continue", "Continuer"},
{"Addresshelper found", "Assistant d'adresse trouvé"},
{"already in router's addressbook", "déjà dans le carnet d'adresses du routeur"},
{"Click here to update record:", "Cliquez ici pour mettre à jour le carnet d'adresse:"},
{"invalid request uri", "uri de la requête invalide"},
{"Can't detect destination host from request", "Impossible de détecter l'hôte de destination à partir de la requête"},
{"Outproxy failure", "Échec de proxy de sortie"},
{"bad outproxy settings", "Mauvaise configuration du proxy de sortie"},
{"not inside I2P network, but outproxy is not enabled", "pas dans le réseau I2P, mais le proxy de sortie n'est pas activé"},
{"unknown outproxy url", "URL du proxy de sortie inconnu"},
{"cannot resolve upstream proxy", "impossible de résoudre l'adresse du proxy en amont"},
{"hostname too long", "nom d'hôte trop long"},
{"cannot connect to upstream socks proxy", "impossible de se connecter au proxy socks en amont"},
{"Cannot negotiate with socks proxy", "Impossible de négocier avec le proxy socks"},
{"CONNECT error", "Erreur de connexion"},
{"Failed to Connect", "Échec de connexion"},
{"socks proxy error", "Erreur de proxy socks"},
{"failed to send request to upstream", "Erreur lors de l'envoie de la requête en amont"},
{"No Reply From socks proxy", "Pas de réponse du proxy socks"},
{"cannot connect", "impossible de connecter"},
{"http out proxy not implemented", "Proxy de sortie HTTP non implémenté"},
{"cannot connect to upstream http proxy", "impossible de se connecter au proxy HTTP en amont"},
{"Host is down", "Hôte hors service"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Impossible d'établir une connexion avec l'hôte, il est peut-être hors service. Veuillez réessayer plus tard."},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"jour", "jours"}},
{"hours", {"heure", "heures"}},
{"minutes", {"minute", "minutes"}},
{"seconds", {"seconde", "secondes"}},
{"", {"", ""}},
};
std::shared_ptr<const i2p::i18n::Locale> GetLocale()
{
return std::make_shared<i2p::i18n::Locale>(language, strings, plurals, [] (int n)->int { return plural(n); });
}
} // language
} // i18n
} // i2p

View File

@@ -36,15 +36,14 @@ namespace german // language namespace
{"GiB", "GiB"},
{"building", "In Bau"},
{"failed", "fehlgeschlagen"},
{"expiring", "läuft ab"},
{"expiring", "läuft ab in"},
{"established", "hergestellt"},
{"unknown", "Unbekannt"},
{"exploratory", "erforschend"},
{"Purple I2P Webconsole", "Purple I2P-Webkonsole"},
{"<b>i2pd</b> webconsole", "<b>i2pd</b>-Webkonsole"},
{"exploratory", "erforschende"},
{"<b>i2pd</b> webconsole", "<b>i2pd</b> Webkonsole"},
{"Main page", "Startseite"},
{"Router commands", "Routerbefehle"},
{"Local Destinations", "Lokale Ziele"},
{"Router commands", "Router Befehle"},
{"Local Destinations", "Lokale Destination"},
{"LeaseSets", "LeaseSets"},
{"Tunnels", "Tunnel"},
{"Transit Tunnels", "Transittunnel"},
@@ -54,7 +53,7 @@ namespace german // language namespace
{"ERROR", "FEHLER"},
{"OK", "OK"},
{"Testing", "Testen"},
{"Firewalled", "Hinter einer Firewall"},
{"Firewalled", "Hinter eine Firewall"},
{"Unknown", "Unbekannt"},
{"Proxy", "Proxy"},
{"Mesh", "Mesh"},
@@ -82,15 +81,15 @@ namespace german // language namespace
{"supported", "unterstützt"},
{"Routers", "Router"},
{"Floodfills", "Floodfills"},
{"Client Tunnels", "Clienttunnel"},
{"Client Tunnels", "Klienttunnel"},
{"Services", "Services"},
{"Enabled", "Aktiviert"},
{"Disabled", "Deaktiviert"},
{"Encrypted B33 address", "Verschlüsselte B33-Adresse"},
{"Address registration line", "Adressregistrierungszeile"},
{"Encrypted B33 address", "Verschlüsselte B33 Adresse"},
{"Address registration line", "Adresseregistrierungszeile"},
{"Domain", "Domain"},
{"Generate", "Generieren"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Hinweis:</b> Der resultierende String kann nur für die Registrierung einer 2LD-Domain (beispiel.i2p) benutzt werden. Für die Registrierung von Subdomains kann i2pd-tools verwendet werden."},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Hinweis:</b> Der resultierende String kann nur für die Registrierung einer 2LD Domain (beispiel.i2p) benutzt werden. Für die Registrierung von Subdomains kann i2pd-tools verwendet werden."},
{"Address", "Adresse"},
{"Type", "Typ"},
{"EncType", "Verschlüsselungstyp"},
@@ -100,15 +99,15 @@ namespace german // language namespace
{"Tags", "Tags"},
{"Incoming", "Eingehend"},
{"Outgoing", "Ausgehend"},
{"Destination", "Ziel"},
{"Destination", "Destination"},
{"Amount", "Anzahl"},
{"Incoming Tags", "Eingehende Tags"},
{"Tags sessions", "Tags-Sitzungen"},
{"Tags sessions", "Tags Sitzungen"},
{"Status", "Status"},
{"Local Destination", "Lokales Ziel"},
{"Local Destination", "Lokale Destination"},
{"Streams", "Streams"},
{"Close stream", "Stream schließen"},
{"I2CP session not found", "I2CP-Sitzung nicht gefunden"},
{"I2CP session not found", "I2CP Sitzung nicht gefunden"},
{"I2CP is not enabled", "I2CP ist nicht aktiviert"},
{"Invalid", "Ungültig"},
{"Store type", "Speichertyp"},
@@ -118,67 +117,67 @@ namespace german // language namespace
{"TunnelID", "TunnelID"},
{"EndDate", "Enddatum"},
{"not floodfill", "kein Floodfill"},
{"Queue size", "Größe der Warteschlange"},
{"Run peer test", "Peer-Test durchführen"},
{"Queue size", "Warteschlangengröße"},
{"Run peer test", "Peer-Test ausführen"},
{"Decline transit tunnels", "Transittunnel ablehnen"},
{"Accept transit tunnels", "Transittunnel akzeptieren"},
{"Cancel graceful shutdown", "Beende das kontrollierte Herunterfahren"},
{"Cancel graceful shutdown", "Beende das kontrollierte herunterfahren"},
{"Start graceful shutdown", "Starte das kontrollierte Herunterfahren"},
{"Force shutdown", "Herunterfahren erzwingen"},
{"Reload external CSS styles", "Lade externe CSS-Stile neu"},
{"Reload external CSS styles", "Lade externe CSS-Styles neu"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Hinweis:</b> Alle hier durchgeführten Aktionen sind nicht dauerhaft und ändern die Konfigurationsdateien nicht."},
{"Logging level", "Protokollierungslevel"},
{"Transit tunnels limit", "Limit für Transittunnel"},
{"Change", "Ändern"},
{"Change", "Verändern"},
{"Change language", "Sprache ändern"},
{"no transit tunnels currently built", "derzeit keine Transittunnel aufgebaut"},
{"SAM disabled", "SAM deaktiviert"},
{"no sessions currently running", "Derzeit keine laufenden Sitzungen"},
{"SAM session not found", "SAM-Sitzung nicht gefunden"},
{"SAM Session", "SAM-Sitzung"},
{"SAM session not found", "SAM Sitzung nicht gefunden"},
{"SAM Session", "SAM Sitzung"},
{"Server Tunnels", "Servertunnel"},
{"Client Forwards", "Client-Weiterleitungen"},
{"Client Forwards", "Klient-Weiterleitungen"},
{"Server Forwards", "Server-Weiterleitungen"},
{"Unknown page", "Unbekannte Seite"},
{"Invalid token", "Ungültiger Token"},
{"SUCCESS", "ERFOLGREICH"},
{"Stream closed", "Stream geschlossen"},
{"Stream not found or already was closed", "Stream nicht gefunden oder bereits geschlossen"},
{"Destination not found", "Ziel nicht gefunden"},
{"Destination not found", "Destination nicht gefunden"},
{"StreamID can't be null", "StreamID kann nicht null sein"},
{"Return to destination page", "Zurück zur Ziel-Seite"},
{"Return to destination page", "Zurück zur Destination-Seite"},
{"You will be redirected in 5 seconds", "Du wirst in 5 Sekunden weitergeleitet"},
{"Transit tunnels count must not exceed 65535", "Es darf maximal 65535 Transittunnel geben"},
{"Back to commands list", "Zurück zur Befehlsliste"},
{"Back to commands list", "Zurück zur Kommandoliste"},
{"Register at reg.i2p", "Auf reg.i2p registrieren"},
{"Description", "Beschreibung"},
{"A bit information about service on domain", "Ein paar Informationen über den Service auf der Domain"},
{"Submit", "Absenden"},
{"Domain can't end with .b32.i2p", "Domain kann nicht auf .b32.i2p enden"},
{"Domain must end with .i2p", "Domain muss auf .i2p enden"},
{"Such destination is not found", "Ein solches Ziel konnte nicht gefunden werden"},
{"A bit information about service on domain", "Ein bisschen Informationen über den Service auf der Domain"},
{"Submit", "Einreichen"},
{"Domain can't end with .b32.i2p", "Domain kann nicht mit .b32.i2p enden"},
{"Domain must end with .i2p", "Domain muss mit .i2p enden"},
{"Such destination is not found", "Eine solche Destination konnte nicht gefunden werden"},
{"Unknown command", "Unbekannter Befehl"},
{"Command accepted", "Befehl akzeptiert"},
{"Proxy error", "Proxy-Fehler"},
{"Proxy info", "Proxy-Info"},
{"Proxy error: Host not found", "Proxy-Fehler: Host nicht gefunden"},
{"Remote host not found in router's addressbook", "Remote-Host nicht im Router-Adressbuch gefunden"},
{"You may try to find this host on jump services below", "Vielleicht kannst du diesen Host auf einem der nachfolgenden Jump-Services finden"},
{"Remote host not found in router's addressbook", "Remote-Host nicht im Router Adressbuch gefunden"},
{"You may try to find this host on jump services below", "Vielleicht kannst du diesen Host auf einen der Jump-Services unten finden"},
{"Invalid request", "Ungültige Anfrage"},
{"Proxy unable to parse your request", "Proxy konnte die Anfrage nicht verarbeiten"},
{"addresshelper is not supported", "Addresshelfer wird nicht unterstützt"},
{"Proxy unable to parse your request", "Proxy konnte die Anfrage nicht interpretieren"},
{"addresshelper is not supported", "addresshelper wird nicht unterstützt"},
{"Host", "Host"},
{"added to router's addressbook from helper", "vom Helfer zum Router-Adressbuch hinzugefügt"},
{"added to router's addressbook from helper", "vom Helfer zum Router Adressbuch hinzugefügt"},
{"Click here to proceed:", "Klicke hier um fortzufahren:"},
{"Continue", "Fortsetzen"},
{"Addresshelper found", "Adresshelfer gefunden"},
{"already in router's addressbook", "bereits im Adressbuch des Routers"},
{"Click here to update record:", "Klicke hier, um den Eintrag zu aktualisieren:"},
{"invalid request uri", "ungültige Anfrage-URI"},
{"Can't detect destination host from request", "Kann den Ziel-Host von der Anfrage nicht erkennen"},
{"Can't detect destination host from request", "Kann Anhand der Anfrage den Destination-Host nicht erkennen"},
{"Outproxy failure", "Outproxy-Fehler"},
{"bad outproxy settings", "ungültige Outproxy-Einstellungen"},
{"not inside I2P network, but outproxy is not enabled", "außerhalb des I2P-Netzwerks, aber Outproxy ist nicht aktiviert"},
{"not inside I2P network, but outproxy is not enabled", "nicht innerhalb des I2P-Netzwerks, aber Outproxy ist nicht aktiviert"},
{"unknown outproxy url", "unbekannte Outproxy-URL"},
{"cannot resolve upstream proxy", "kann den Upstream-Proxy nicht auflösen"},
{"hostname too long", "Hostname zu lang"},
@@ -193,7 +192,7 @@ namespace german // language namespace
{"http out proxy not implemented", "HTTP-Outproxy nicht implementiert"},
{"cannot connect to upstream http proxy", "Kann nicht zu Upstream-HTTP-Proxy verbinden"},
{"Host is down", "Host ist offline"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Konnte keine Verbindung zum angefragten Host aufbauen, vielleicht ist er offline. Versuche es später noch mal."},
{"Can't create connection to requested host, it may be down. Please try again later.", "Konnte keine Verbindung zum angefragten Host aufbaunen, vielleicht ist es offline. Versuche es später noch einmal."},
{"", ""},
};

View File

@@ -73,13 +73,9 @@ namespace i18n
// Add localization here with language name as namespace
namespace afrikaans { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace armenian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace chinese { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace english { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace french { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace german { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace italian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace russian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace spanish { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace turkmen { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace ukrainian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace uzbek { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
@@ -90,16 +86,12 @@ namespace i18n
static std::map<std::string, langData> languages
{
{ "afrikaans", {"Afrikaans", "af", i2p::i18n::afrikaans::GetLocale} },
{ "armenian", {"hայերէն", "hy", i2p::i18n::armenian::GetLocale} },
{ "chinese", {"简体字", "zh-CN", i2p::i18n::chinese::GetLocale} },
{ "armenian", {"հայերէն", "hy", i2p::i18n::armenian::GetLocale} },
{ "english", {"English", "en", i2p::i18n::english::GetLocale} },
{ "french", {"Français", "fr", i2p::i18n::french::GetLocale} },
{ "german", {"Deutsch", "de", i2p::i18n::german::GetLocale} },
{ "italian", {"Italiano", "it", i2p::i18n::italian::GetLocale} },
{ "russian", {"Русский язык", "ru", i2p::i18n::russian::GetLocale} },
{ "spanish", {"Español", "es", i2p::i18n::spanish::GetLocale} },
{ "turkmen", {"Türkmen dili", "tk", i2p::i18n::turkmen::GetLocale} },
{ "ukrainian", {"Украї́нська мо́ва", "uk", i2p::i18n::ukrainian::GetLocale} },
{ "russian", {"русский язык", "ru", i2p::i18n::russian::GetLocale} },
{ "turkmen", {"türkmen dili", "tk", i2p::i18n::turkmen::GetLocale} },
{ "ukrainian", {"украї́нська мо́ва", "uk", i2p::i18n::ukrainian::GetLocale} },
{ "uzbek", {"Oʻzbek", "uz", i2p::i18n::uzbek::GetLocale} },
};

View File

@@ -1,216 +0,0 @@
/*
* Copyright (c) 2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#include <map>
#include <vector>
#include <string>
#include <memory>
#include "I18N.h"
// Italian localization file
namespace i2p
{
namespace i18n
{
namespace italian // language namespace
{
// language name in lowercase
static std::string language = "italian";
// See for language plural forms here:
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
static int plural (int n) {
return n != 1 ? 1 : 0;
}
static std::map<std::string, std::string> strings
{
{"KiB", "KiB"},
{"MiB", "MiB"},
{"GiB", "GiB"},
{"building", "in costruzione"},
{"failed", "fallito"},
{"expiring", "in scadenza"},
{"established", "stabilita"},
{"unknown", "sconosciuto"},
{"exploratory", "esplorativo"},
{"Purple I2P Webconsole", "Terminale web Purple I2P"},
{"<b>i2pd</b> webconsole", "Terminal web <b>i2pd</b>"},
{"Main page", "Pagina principale"},
{"Router commands", "Comandi router"},
{"Local Destinations", "Destinazioni locali"},
{"LeaseSets", "LeaseSets"},
{"Tunnels", "Tunnel"},
{"Transit Tunnels", "Tunnel di transito"},
{"Transports", "Trasporti"},
{"I2P tunnels", "Tunnel I2P"},
{"SAM sessions", "Sessioni SAM"},
{"ERROR", "ERRORE"},
{"OK", "OK"},
{"Testing", "Testando"},
{"Firewalled", "Protetto da firewall"},
{"Unknown", "Sconosciuto"},
{"Proxy", "Proxy"},
{"Mesh", "Mesh"},
{"Error", "Errore"},
{"Clock skew", "Orologio disallineato"},
{"Offline", "Disconnesso"},
{"Symmetric NAT", "NAT simmetrico"},
{"Uptime", "In funzione da"},
{"Network status", "Stato della rete"},
{"Network status v6", "Stato della rete v6"},
{"Stopping in", "Arresto in"},
{"Family", "Famiglia"},
{"Tunnel creation success rate", "Percentuale di tunnel creati con successo"},
{"Received", "Ricevuti"},
{"KiB/s", "KiB/s"},
{"Sent", "Inviati"},
{"Transit", "Transitati"},
{"Data path", "Percorso dati"},
{"Hidden content. Press on text to see.", "Contenuto nascosto. Premi sul testo per vedere."},
{"Router Ident", "Identificativo del router"},
{"Router Family", "Famiglia del router"},
{"Router Caps", "Limiti del router"},
{"Version", "Versione"},
{"Our external address", "Il nostro indirizzo esterno"},
{"supported", "supportato"},
{"Routers", "Router"},
{"Floodfills", "Floodfill"},
{"Client Tunnels", "Tunnel client"},
{"Services", "Servizi"},
{"Enabled", "Abilitato"},
{"Disabled", "Disabilitato"},
{"Encrypted B33 address", "Indirizzo criptato B33"},
{"Address registration line", "Linea di registrazione indirizzo"},
{"Domain", "Dominio"},
{"Generate", "Genera"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Nota:</b> la stringa risultante può essere utilizzata solo per registrare domini 2LD (example.i2p). Per registrare i sottodomini, si prega di utilizzare i2pd-tools."},
{"Address", "Indirizzo"},
{"Type", "Tipologia"},
{"EncType", "Tipo di crittografia"},
{"Inbound tunnels", "Tunnel in entrata"},
{"ms", "ms"},
{"Outbound tunnels", "Tunnel in uscita"},
{"Tags", "Tag"},
{"Incoming", "In entrata"},
{"Outgoing", "In uscita"},
{"Destination", "Destinazione"},
{"Amount", "Quantità"},
{"Incoming Tags", "Tag in entrata"},
{"Tags sessions", "Sessioni dei tag"},
{"Status", "Stato"},
{"Local Destination", "Destinazione locale"},
{"Streams", "Flussi"},
{"Close stream", "Interrompi il flusso"},
{"I2CP session not found", "Sessione I2CP non trovata"},
{"I2CP is not enabled", "I2CP non è abilitato"},
{"Invalid", "Invalido"},
{"Store type", "Tipologia di archivio"},
{"Expires", "Scade"},
{"Non Expired Leases", "Lease non scaduti"},
{"Gateway", "Gateway"},
{"TunnelID", "TunnelID"},
{"EndDate", "Data di fine"},
{"not floodfill", "no floodfill"},
{"Queue size", "Dimensione della coda"},
{"Run peer test", "Esegui il test dei peer"},
{"Decline transit tunnels", "Rifiuta tunnel di transito"},
{"Accept transit tunnels", "Accetta tunnel di transito"},
{"Cancel graceful shutdown", "Annulla l'interruzione controllata"},
{"Start graceful shutdown", "Avvia l'interruzione controllata"},
{"Force shutdown", "Forza l'arresto"},
{"Reload external CSS styles", "Ricarica gli stili CSS esterni"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Nota:</b> qualsiasi azione effettuata qui non è persistente e non modifica i file di configurazione."},
{"Logging level", "Livello di log"},
{"Transit tunnels limit", "Limite di tunnel di transito"},
{"Change", "Modifica"},
{"Change language", "Modifica linguaggio"},
{"no transit tunnels currently built", "Attualmente non ci sono tunnel di transito instaurati"},
{"SAM disabled", "SAM disabilitato"},
{"no sessions currently running", "Attualmente non ci sono sessioni attive"},
{"SAM session not found", "Sessione SAM non trovata"},
{"SAM Session", "Sessione SAM"},
{"Server Tunnels", "Tunnel server"},
{"Client Forwards", "Client di inoltro"},
{"Server Forwards", "Server di inoltro"},
{"Unknown page", "Pagina sconosciuta"},
{"Invalid token", "Token non valido"},
{"SUCCESS", "SUCCESSO"},
{"Stream closed", "Flusso terminato"},
{"Stream not found or already was closed", "Il flusso non è stato trovato oppure è già stato terminato"},
{"Destination not found", "Destinazione non trovata"},
{"StreamID can't be null", "Lo StreamID non può essere null"},
{"Return to destination page", "Ritorna alla pagina di destinazione"},
{"You will be redirected in 5 seconds", "Verrai reindirizzato in 5 secondi"},
{"Transit tunnels count must not exceed 65535", "Il numero di tunnel di transito non può superare i 65535"},
{"Back to commands list", "Ritorna alla lista dei comandi"},
{"Register at reg.i2p", "Registra a reg.i2p"},
{"Description", "Descrizione"},
{"A bit information about service on domain", "Alcune informazioni riguardo il servizio sul dominio"},
{"Submit", "Invia"},
{"Domain can't end with .b32.i2p", "I domini non possono terminare con .b32.i2p"},
{"Domain must end with .i2p", "I domini devono terminare con .i2p"},
{"Such destination is not found", "Questa destinazione non è stata trovata"},
{"Unknown command", "Comando sconosciuto"},
{"Command accepted", "Comando accettato"},
{"Proxy error", "Errore del proxy"},
{"Proxy info", "Informazioni del proxy"},
{"Proxy error: Host not found", "Errore del proxy: Host non trovato"},
{"Remote host not found in router's addressbook", "L'host remoto non è stato trovato nella rubrica del router"},
{"You may try to find this host on jump services below", "Si può provare a trovare questo host sui servizi di salto qui sotto"},
{"Invalid request", "Richiesta non valida"},
{"Proxy unable to parse your request", "Il proxy non è in grado di elaborare la tua richiesta"},
{"addresshelper is not supported", "addresshelper non è supportato"},
{"Host", "Host"},
{"added to router's addressbook from helper", "aggiunto alla rubrica tramite l'helper"},
{"Click here to proceed:", "Clicca qui per procedere:"},
{"Continue", "Continua"},
{"Addresshelper found", "Addresshelper trovato"},
{"already in router's addressbook", "già presente nella rubrica del router"},
{"Click here to update record:", "Clicca qui per aggiornare l'elemento:"},
{"invalid request uri", "uri della richiesta non valido"},
{"Can't detect destination host from request", "Impossibile determinare l'host di destinazione dalla richiesta"},
{"Outproxy failure", "Fallimento del proxy di uscita"},
{"bad outproxy settings", "impostazioni errate del proxy di uscita"},
{"not inside I2P network, but outproxy is not enabled", "non all'interno della rete I2P, ma il proxy di uscita non è abilitato"},
{"unknown outproxy url", "url del proxy di uscita sconosciuto"},
{"cannot resolve upstream proxy", "impossibile identificare il flusso a monte del proxy"},
{"hostname too long", "il nome dell'host è troppo lungo"},
{"cannot connect to upstream socks proxy", "impossibile connettersi al flusso a monte del proxy socks"},
{"Cannot negotiate with socks proxy", "Impossibile negoziare con il proxy socks"},
{"CONNECT error", "Errore di connessione"},
{"Failed to Connect", "Connessione fallita"},
{"socks proxy error", "errore del proxy socks"},
{"failed to send request to upstream", "invio della richiesta a monte non riuscito"},
{"No Reply From socks proxy", "Nessuna risposta dal proxy socks"},
{"cannot connect", "impossibile connettersi"},
{"http out proxy not implemented", "proxy http di uscita non implementato"},
{"cannot connect to upstream http proxy", "impossibile connettersi al proxy http a monte"},
{"Host is down", "L'host è offline"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Impossibile creare la connessione all'host richiesto, probabilmente è offline. Riprova più tardi."},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"giorno", "giorni"}},
{"hours", {"ora", "ore"}},
{"minutes", {"minuto", "minuti"}},
{"seconds", {"secondo", "secondi"}},
{"", {"", ""}},
};
std::shared_ptr<const i2p::i18n::Locale> GetLocale()
{
return std::make_shared<i2p::i18n::Locale>(language, strings, plurals, [] (int n)->int { return plural(n); });
}
} // language
} // i18n
} // i2p

View File

@@ -1,216 +0,0 @@
/*
* Copyright (c) 2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#include <map>
#include <vector>
#include <string>
#include <memory>
#include "I18N.h"
// Spanish localization file
namespace i2p
{
namespace i18n
{
namespace spanish // language namespace
{
// language name in lowercase
static std::string language = "spanish";
// See for language plural forms here:
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
static int plural (int n) {
return n != 1 ? 1 : 0;
}
static std::map<std::string, std::string> strings
{
{"KiB", "KiB"},
{"MiB", "MiB"},
{"GiB", "GiB"},
{"building", "pendiente"},
{"failed", "fallido"},
{"expiring", "expiró"},
{"established", "establecido"},
{"unknown", "desconocido"},
{"exploratory", "exploratorio"},
{"Purple I2P Webconsole", "Consola web de Purple I2P"},
{"<b>i2pd</b> webconsole", "Consola web de <b>i2pd</b>"},
{"Main page", "Inicio"},
{"Router commands", "Comandos de enrutador"},
{"Local Destinations", "Destinos locales"},
{"LeaseSets", "LeaseSets"},
{"Tunnels", "Túneles"},
{"Transit Tunnels", "Túneles de Tránsito"},
{"Transports", "Transportes"},
{"I2P tunnels", "Túneles I2P"},
{"SAM sessions", "Sesiones SAM"},
{"ERROR", "ERROR"},
{"OK", "VALE"},
{"Testing", "Probando"},
{"Firewalled", "Con cortafuegos"},
{"Unknown", "Desconocido"},
{"Proxy", "Proxy"},
{"Mesh", "Malla"},
{"Error", "Error"},
{"Clock skew", "Reloj desfasado"},
{"Offline", "Desconectado"},
{"Symmetric NAT", "NAT simétrico"},
{"Uptime", "Tiempo en línea"},
{"Network status", "Estado de red"},
{"Network status v6", "Estado de red v6"},
{"Stopping in", "Parando en"},
{"Family", "Familia"},
{"Tunnel creation success rate", "Tasa de éxito de creación de túneles"},
{"Received", "Recibido"},
{"KiB/s", "KiB/s"},
{"Sent", "Enviado"},
{"Transit", "Tránsito"},
{"Data path", "Ruta de datos"},
{"Hidden content. Press on text to see.", "Contenido oculto. Presione para ver."},
{"Router Ident", "Ident del Enrutador"},
{"Router Family", "Familia de enrutador"},
{"Router Caps", "Atributos del Enrutador"},
{"Version", "Versión"},
{"Our external address", "Nuestra dirección externa"},
{"supported", "soportado"},
{"Routers", "Enrutadores"},
{"Floodfills", "Inundaciones"},
{"Client Tunnels", "Túneles de cliente"},
{"Services", "Servicios"},
{"Enabled", "Activado"},
{"Disabled", "Desactivado"},
{"Encrypted B33 address", "Dirección encriptada B33"},
{"Address registration line", "Línea para registrar direcciones"},
{"Domain", "Dominio"},
{"Generate", "Generar"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Nota:</b> la cadena resultante solo se puede usar para registrar dominios 2LD (ejemplo.i2p). Para registrar subdominios, por favor utilice i2pd-tools."},
{"Address", "Dirección"},
{"Type", "Tipo"},
{"EncType", "TipoEncrip"},
{"Inbound tunnels", "Túneles entrantes"},
{"ms", "ms"},
{"Outbound tunnels", "Túneles salientes"},
{"Tags", "Etiquetas"},
{"Incoming", "Entrante"},
{"Outgoing", "Saliente"},
{"Destination", "Destino"},
{"Amount", "Cantidad"},
{"Incoming Tags", "Etiquetas entrantes"},
{"Tags sessions", "Sesiones de etiquetas"},
{"Status", "Estado"},
{"Local Destination", "Destino Local"},
{"Streams", "Flujos"},
{"Close stream", "Cerrar flujo"},
{"I2CP session not found", "Sesión I2CP no encontrada"},
{"I2CP is not enabled", "I2CP no está activado"},
{"Invalid", "Inválido"},
{"Store type", "Tipo de almacenamiento"},
{"Expires", "Caduca"},
{"Non Expired Leases", "Sesiones No Expiradas"},
{"Gateway", "Puerta de enlace"},
{"TunnelID", "TunnelID"},
{"EndDate", "FechaVenc"},
{"not floodfill", "no inundado"},
{"Queue size", "Tamaño de cola"},
{"Run peer test", "Ejecutar prueba de par"},
{"Decline transit tunnels", "Rechazar túneles de tránsito"},
{"Accept transit tunnels", "Aceptar túneles de tránsito"},
{"Cancel graceful shutdown", "Cancelar apagado con gracia"},
{"Start graceful shutdown", "Iniciar apagado con gracia"},
{"Force shutdown", "Forzar apagado"},
{"Reload external CSS styles", "Recargar estilos CSS externos"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Nota:</b> cualquier acción hecha aquí no es persistente y no cambia tus archivos de configuración."},
{"Logging level", "Nivel de registro de errores"},
{"Transit tunnels limit", "Límite de túneles de tránsito"},
{"Change", "Cambiar"},
{"Change language", "Cambiar idioma"},
{"no transit tunnels currently built", "no hay túneles de tránsito actualmente construidos"},
{"SAM disabled", "SAM desactivado"},
{"no sessions currently running", "no hay sesiones ejecutándose ahora"},
{"SAM session not found", "Sesión SAM no encontrada"},
{"SAM Session", "Sesión SAM"},
{"Server Tunnels", "Túneles de Servidor"},
{"Client Forwards", "Redirecciones de Cliente"},
{"Server Forwards", "Redirecciones de Servidor"},
{"Unknown page", "Página desconocida"},
{"Invalid token", "Token inválido"},
{"SUCCESS", "ÉXITO"},
{"Stream closed", "Transmisión cerrada"},
{"Stream not found or already was closed", "No se encontró la transmisión o ya se cerró"},
{"Destination not found", "Destino no encontrado"},
{"StreamID can't be null", "StreamID no puede ser nulo"},
{"Return to destination page", "Volver a la página de destino"},
{"You will be redirected in 5 seconds", "Serás redirigido en 5 segundos"},
{"Transit tunnels count must not exceed 65535", "La cantidad de túneles de tránsito no puede exceder 65535"},
{"Back to commands list", "Volver a lista de comandos"},
{"Register at reg.i2p", "Registrar en reg.i2p"},
{"Description", "Descripción"},
{"A bit information about service on domain", "Un poco de información sobre el servicio en el dominio"},
{"Submit", "Enviar"},
{"Domain can't end with .b32.i2p", "El dominio no puede terminar con .b32.i2p"},
{"Domain must end with .i2p", "El dominio debe terminar con .i2p"},
{"Such destination is not found", "No se encontró el destino"},
{"Unknown command", "Comando desconocido"},
{"Command accepted", "Comando aceptado"},
{"Proxy error", "Error de proxy"},
{"Proxy info", "Información del proxy"},
{"Proxy error: Host not found", "Error de proxy: Host no encontrado"},
{"Remote host not found in router's addressbook", "Servidor remoto no encontrado en la libreta de direcciones del enrutador"},
{"You may try to find this host on jump services below", "Puede intentar encontrar este dominio en los siguientes servicios de salto"},
{"Invalid request", "Solicitud inválida"},
{"Proxy unable to parse your request", "Proxy no puede procesar su solicitud"},
{"addresshelper is not supported", "ayudante de dirección no soportado"},
{"Host", "Dominio"},
{"added to router's addressbook from helper", "añadido a la libreta de direcciones desde el ayudante"},
{"Click here to proceed:", "Haga clic aquí para continuar:"},
{"Continue", "Continuar"},
{"Addresshelper found", "Se encontró ayudante de dirección"},
{"already in router's addressbook", "ya se encontró en libreta de direcciones"},
{"Click here to update record:", "Haga clic aquí para actualizar el registro:"},
{"invalid request uri", "uri de solicitud inválida"},
{"Can't detect destination host from request", "No se puede detectar el host de destino de la solicitud"},
{"Outproxy failure", "Fallo en el proxy saliente"},
{"bad outproxy settings", "configuración de outproxy incorrecta"},
{"not inside I2P network, but outproxy is not enabled", "no está dentro de la red I2P, pero el proxy de salida no está activado"},
{"unknown outproxy url", "url de proxy outproxy desconocido"},
{"cannot resolve upstream proxy", "no se puede resolver el proxy de upstream"},
{"hostname too long", "nombre de dominio muy largo"},
{"cannot connect to upstream socks proxy", "no se puede conectar al proxy socks principal"},
{"Cannot negotiate with socks proxy", "No se puede negociar con el proxy socks"},
{"CONNECT error", "Error de CONNECT"},
{"Failed to Connect", "Error al Conectar"},
{"socks proxy error", "error de proxy socks"},
{"failed to send request to upstream", "no se pudo enviar petición al principal"},
{"No Reply From socks proxy", "Sin respuesta del proxy socks"},
{"cannot connect", "no se puede conectar"},
{"http out proxy not implemented", "proxy externo http no implementado"},
{"cannot connect to upstream http proxy", "no se puede conectar al proxy http principal"},
{"Host is down", "Servidor caído"},
{"Can't create connection to requested host, it may be down. Please try again later.", "No se puede crear la conexión al servidor solicitado, puede estar caído. Intente de nuevo más tarde."},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"days", {"día", "días"}},
{"hours", {"hora", "horas"}},
{"minutes", {"minuto", "minutos"}},
{"seconds", {"segundo", "segundos"}},
{"", {"", ""}},
};
std::shared_ptr<const i2p::i18n::Locale> GetLocale()
{
return std::make_shared<i2p::i18n::Locale>(language, strings, plurals, [] (int n)->int { return plural(n); });
}
} // language
} // i18n
} // i2p

View File

@@ -24,8 +24,8 @@ namespace data {
size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen);
/**
* Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes
*/
Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes
*/
size_t Base64EncodingBufferSize(const size_t input_size);
std::string ToBase64Standard (const std::string& in); // using standard table, for Proxy-Authorization

View File

@@ -99,7 +99,7 @@ namespace data
static size_t BlindECDSA (i2p::data::SigningKeyType sigType, const uint8_t * key, const uint8_t * seed, Fn blind, Args&&...args)
// blind is BlindEncodedPublicKeyECDSA or BlindEncodedPrivateKeyECDSA
{
size_t publicKeyLength = 0;
size_t publicKeyLength = 0;
EC_GROUP * group = nullptr;
switch (sigType)
{
@@ -147,8 +147,8 @@ namespace data
memcpy (m_PublicKey.data (), identity->GetSigningPublicKeyBuffer (), len);
m_SigType = identity->GetSigningKeyType ();
if (m_SigType == i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519)
m_BlindedSigType = i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519; // 7 -> 11
else
m_BlindedSigType = i2p::data::SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519; // 7 -> 11
else
m_BlindedSigType = m_SigType;
}

View File

@@ -28,8 +28,8 @@ namespace data
const uint8_t * GetPublicKey () const { return m_PublicKey.data (); };
size_t GetPublicKeyLen () const { return m_PublicKey.size (); };
SigningKeyType GetSigType () const { return m_SigType; };
SigningKeyType GetBlindedSigType () const { return m_BlindedSigType; };
SigningKeyType GetSigType () const { return m_SigType; };
SigningKeyType GetBlindedSigType () const { return m_BlindedSigType; };
bool IsValid () const { return GetSigType (); }; // signature type 0 means invalid
void GetSubcredential (const uint8_t * blinded, size_t len, uint8_t * subcredential) const; // 32 bytes

View File

@@ -64,7 +64,7 @@ namespace config {
("bandwidth", value<std::string>()->default_value(""), "Transit traffic bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000)")
("share", value<int>()->default_value(100), "Limit of transit traffic from max bandwidth in percents. (default: 100)")
("ntcp", bool_switch()->default_value(false), "Ignored. Always false")
("ssu", bool_switch()->default_value(false), "Enable SSU transport (default: disabled)")
("ssu", bool_switch()->default_value(true), "Enable SSU transport (default: enabled)")
("ntcpproxy", value<std::string>()->default_value(""), "Ignored")
#ifdef _WIN32
("svcctl", value<std::string>()->default_value(""), "Ignored")
@@ -78,9 +78,9 @@ namespace config {
("limits.coresize", value<uint32_t>()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)")
("limits.openfiles", value<uint16_t>()->default_value(0), "Maximum number of open files (0 - use system default)")
("limits.transittunnels", value<uint16_t>()->default_value(2500), "Maximum active transit sessions (default:2500)")
("limits.ntcpsoft", value<uint16_t>()->default_value(0), "Ignored")
("limits.ntcphard", value<uint16_t>()->default_value(0), "Ignored")
("limits.ntcpthreads", value<uint16_t>()->default_value(1), "Ignored")
("limits.ntcpsoft", value<uint16_t>()->default_value(0), "Threshold to start probabilistic backoff with ntcp sessions (default: use system limit)")
("limits.ntcphard", value<uint16_t>()->default_value(0), "Maximum number of ntcp sessions (default: use system limit)")
("limits.ntcpthreads", value<uint16_t>()->default_value(1), "Maximum number of threads used by NTCP DH worker (default: 1)")
;
options_description httpserver("HTTP Server options");
@@ -230,7 +230,6 @@ namespace config {
options_description addressbook("AddressBook options");
addressbook.add_options()
("addressbook.enabled", value<bool>()->default_value(true), "Enable address book lookups and subscritions (default: enabled)")
("addressbook.defaulturl", value<std::string>()->default_value(
"http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/hosts.txt"
), "AddressBook subscription URL for initial setup")
@@ -273,15 +272,12 @@ namespace config {
;
options_description ssu2("SSU2 Options");
ssu2.add_options()
("ssu2.enabled", value<bool>()->default_value(true), "Enable SSU2 (default: enabled)")
("ssu2.published", value<bool>()->default_value(true), "Publish SSU2 (default: enabled)")
ntcp2.add_options()
("ssu2.enabled", value<bool>()->default_value(false), "Enable SSU2 (default: disabled)")
("ssu2.published", value<bool>()->default_value(false), "Publish SSU2 (default: disabled)")
("ssu2.port", value<uint16_t>()->default_value(0), "Port to listen for incoming SSU2 packets (default: auto)")
("ssu2.mtu4", value<uint16_t>()->default_value(0), "MTU for ipv4 address (default: detect)")
("ssu2.mtu6", value<uint16_t>()->default_value(0), "MTU for ipv6 address (default: detect)")
("ssu2.proxy", value<std::string>()->default_value(""), "Socks5 proxy URL for SSU2 transport")
;
options_description nettime("Time sync options");
nettime.add_options()
("nettime.enabled", value<bool>()->default_value(false), "Disable time sync (default: disabled)")
@@ -314,13 +310,6 @@ namespace config {
("meshnets.yggaddress", value<std::string>()->default_value(""), "Yggdrasil address to publish")
;
#ifdef __linux__
options_description unix_specific("UNIX-specific options");
unix_specific.add_options()
("unix.handle_sigtstp", bool_switch()->default_value(false), "Handle SIGTSTP and SIGCONT signals (default: disabled)")
;
#endif
m_OptionsDesc
.add(general)
.add(limits)
@@ -344,9 +333,6 @@ namespace config {
.add(persist)
.add(cpuext)
.add(meshnets)
#ifdef __linux__
.add(unix_specific)
#endif
;
}

View File

@@ -29,16 +29,16 @@ namespace config {
extern boost::program_options::variables_map m_Options;
/**
* @brief Initialize list of acceptable parameters
* @brief Initialize list of acceptable parameters
*
* Should be called before any Parse* functions.
*/
void Init();
/**
* @brief Parse cmdline parameters, and show help if requested
* @param argc Cmdline arguments count, should be passed from main().
* @param argv Cmdline parameters array, should be passed from main()
* @brief Parse cmdline parameters, and show help if requested
* @param argc Cmdline arguments count, should be passed from main().
* @param argv Cmdline parameters array, should be passed from main()
*
* If --help is given in parameters, shows its list with description
* and terminates the program with exitcode 0.
@@ -52,8 +52,8 @@ namespace config {
void ParseCmdline(int argc, char* argv[], bool ignoreUnknown = false);
/**
* @brief Load and parse given config file
* @param path Path to config file
* @brief Load and parse given config file
* @param path Path to config file
*
* If error occurred when opening file path is points to,
* we show the error message and terminate program.
@@ -67,14 +67,14 @@ namespace config {
void ParseConfig(const std::string& path);
/**
* @brief Used to combine options from cmdline, config and default values
* @brief Used to combine options from cmdline, config and default values
*/
void Finalize();
/**
* @brief Accessor to parameters by name
* @param name Name of the requested parameter
* @param value Variable where to store option
* @brief Accessor to parameters by name
* @param name Name of the requested parameter
* @param value Variable where to store option
* @return this function returns false if parameter not found
*
* Example: uint16_t port; GetOption("sam.port", port);
@@ -98,9 +98,9 @@ namespace config {
bool GetOptionAsAny(const std::string& name, boost::any& value);
/**
* @brief Set value of given parameter
* @param name Name of settable parameter
* @param value New parameter value
* @brief Set value of given parameter
* @param name Name of settable parameter
* @param value New parameter value
* @return true if value set up successful, false otherwise
*
* Example: uint16_t port = 2827; SetOption("bob.port", port);
@@ -116,8 +116,8 @@ namespace config {
}
/**
* @brief Check is value explicitly given or default
* @param name Name of checked parameter
* @brief Check is value explicitly given or default
* @param name Name of checked parameter
* @return true if value set to default, false otherwise
*/
bool IsDefault(const char *name);

View File

@@ -1313,8 +1313,8 @@ namespace crypto
for (const auto& it: bufs)
SHA256_Update (&ctx, it.first, it.second);
SHA256_Final (m_H, &ctx);
}
}
void NoiseSymmetricState::MixKey (const uint8_t * sharedSecret)
{
HKDF (m_CK, sharedSecret, 32, "", m_CK);
@@ -1330,7 +1330,7 @@ namespace crypto
SHA256_Init (&ctx);
SHA256_Update (&ctx, hh, 32);
SHA256_Update (&ctx, pub, 32);
SHA256_Final (state.m_H, &ctx); // h = MixHash(pub) = SHA256(hh || pub)
SHA256_Final (state.m_H, &ctx); // h = MixHash(pub) = SHA256(hh || pub)
}
void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub)
@@ -1368,12 +1368,12 @@ namespace crypto
}; // SHA256 ("Noise_XKchaobfse+hs1+hs2+hs3_25519_ChaChaPoly_SHA256")
static const uint8_t hh[32] =
{
0xdc, 0x85, 0xe6, 0xaf, 0x7b, 0x02, 0x65, 0x0c, 0xf1, 0xf9, 0x0d, 0x71, 0xfb, 0xc6, 0xd4, 0x53,
0xdc, 0x85, 0xe6, 0xaf, 0x7b, 0x02, 0x65, 0x0c, 0xf1, 0xf9, 0x0d, 0x71, 0xfb, 0xc6, 0xd4, 0x53,
0xa7, 0xcf, 0x6d, 0xbf, 0xbd, 0x52, 0x5e, 0xa5, 0xb5, 0x79, 0x1c, 0x47, 0xb3, 0x5e, 0xbc, 0x33
}; // SHA256 (protocolNameHash)
InitNoiseState (state, protocolNameHash, hh, pub);
}
void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub)
{
static const uint8_t protocolNameHash[32] =

View File

@@ -29,25 +29,23 @@
#include "CPU.h"
// recognize openssl version and features
#if (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER >= 0x3050200fL)) // LibreSSL 3.5.2 and above
# define LEGACY_OPENSSL 0
#elif ((OPENSSL_VERSION_NUMBER < 0x010100000) || defined(LIBRESSL_VERSION_NUMBER)) // 1.0.2 and below or LibreSSL
# define LEGACY_OPENSSL 1
# define X509_getm_notBefore X509_get_notBefore
# define X509_getm_notAfter X509_get_notAfter
#if ((OPENSSL_VERSION_NUMBER < 0x010100000) || defined(LIBRESSL_VERSION_NUMBER)) // 1.0.2 and below or LibreSSL
# define LEGACY_OPENSSL 1
# define X509_getm_notBefore X509_get_notBefore
# define X509_getm_notAfter X509_get_notAfter
#else
# define LEGACY_OPENSSL 0
# if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
# define OPENSSL_HKDF 1
# define OPENSSL_EDDSA 1
# define OPENSSL_X25519 1
# if (OPENSSL_VERSION_NUMBER != 0x030000000) // 3.0.0, regression in SipHash
# define OPENSSL_SIPHASH 1
# define LEGACY_OPENSSL 0
# if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
# define OPENSSL_HKDF 1
# define OPENSSL_EDDSA 1
# define OPENSSL_X25519 1
# if (OPENSSL_VERSION_NUMBER < 0x030000000) // 3.0.0, regression in SipHash
# define OPENSSL_SIPHASH 1
# endif
# endif
# if !defined OPENSSL_NO_CHACHA && !defined OPENSSL_NO_POLY1305 // some builds might not include them
# define OPENSSL_AEAD_CHACHA20_POLY1305 1
# endif
# endif
# if !defined OPENSSL_NO_CHACHA && !defined OPENSSL_NO_POLY1305 // some builds might not include them
# define OPENSSL_AEAD_CHACHA20_POLY1305 1
# endif
#endif
namespace i2p
@@ -385,7 +383,7 @@ 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)
{

View File

@@ -324,7 +324,7 @@ namespace datagram
auto path = m_RoutingSession->GetSharedRoutingPath();
if (path && m_RoutingSession->IsRatchets () &&
m_LastUse > m_RoutingSession->GetLastActivityTimestamp ()*1000 + DATAGRAM_SESSION_PATH_TIMEOUT)
m_LastUse > m_RoutingSession->GetLastActivityTimestamp ()*1000 + DATAGRAM_SESSION_PATH_TIMEOUT)
{
m_RoutingSession->SetSharedRoutingPath (nullptr);
path = nullptr;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -15,7 +15,6 @@
#include <map>
#include <vector>
#include "Base.h"
#include "Gzip.h"
#include "Identity.h"
#include "LeaseSet.h"
#include "I2NPProtocol.h"

View File

@@ -13,6 +13,7 @@
#include <vector>
#include <boost/algorithm/string.hpp>
#include "Crypto.h"
#include "Config.h"
#include "Log.h"
#include "FS.h"
#include "Timestamp.h"
@@ -35,7 +36,7 @@ namespace client
int outLen = DEFAULT_OUTBOUND_TUNNEL_LENGTH;
int outQty = DEFAULT_OUTBOUND_TUNNELS_QUANTITY;
int inVar = DEFAULT_INBOUND_TUNNELS_LENGTH_VARIANCE;
int outVar = DEFAULT_OUTBOUND_TUNNELS_LENGTH_VARIANCE;
int outVar = DEFAULT_OUTBOUND_TUNNELS_LENGTH_VARIANCE;
int numTags = DEFAULT_TAGS_TO_SEND;
std::shared_ptr<std::vector<i2p::data::IdentHash> > explicitPeers;
try
@@ -93,7 +94,9 @@ namespace client
if (it != params->end ())
{
// oveeride isPublic
m_IsPublic = (it->second != "true");
bool dontpublish = false;
i2p::config::GetOption (it->second, dontpublish);
m_IsPublic = !dontpublish;
}
it = params->find (I2CP_PARAM_LEASESET_TYPE);
if (it != params->end ())
@@ -350,8 +353,8 @@ namespace client
{
s->AddECIESx25519Key (data.k, data.t);
});
}
}
void LeaseSetDestination::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
{
m_Service.post (std::bind (&LeaseSetDestination::HandleGarlicMessage, shared_from_this (), msg));
@@ -417,7 +420,7 @@ namespace client
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
auto it = m_RemoteLeaseSets.find (key);
if (it != m_RemoteLeaseSets.end () &&
it->second->GetStoreType () == buf[DATABASE_STORE_TYPE_OFFSET]) // update only if same type
it->second->GetStoreType () == buf[DATABASE_STORE_TYPE_OFFSET]) // update only if same type
{
leaseSet = it->second;
if (leaseSet->IsNewer (buf + offset, len - offset))
@@ -587,7 +590,7 @@ namespace client
LogPrint (eLogError, "Destination: Can't publish LeaseSet, no more floodfills found");
m_ExcludedFloodfills.clear ();
return;
}
}
auto outbound = m_Pool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false));
auto inbound = m_Pool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true));
if (!outbound || !inbound)
@@ -599,22 +602,22 @@ namespace client
{
outbound = m_Pool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false));
if (outbound)
{
{
inbound = m_Pool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true));
if (!inbound)
LogPrint (eLogError, "Destination: Can't publish LeaseSet. No inbound tunnels");
}
}
else
LogPrint (eLogError, "Destination: Can't publish LeaseSet. No outbound tunnels");
}
}
else
LogPrint (eLogError, "Destination: Can't publish LeaseSet, no more floodfills found");
if (!floodfill || !outbound || !inbound)
{
m_ExcludedFloodfills.clear ();
return;
}
}
}
}
m_ExcludedFloodfills.insert (floodfill->GetIdentHash ());
LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ());
RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4);
@@ -951,7 +954,7 @@ namespace client
for (auto& it: encryptionKeyTypes)
{
auto encryptionKey = new EncryptionKey (it);
if (IsPublic ())
if (isPublic)
PersistTemporaryKeys (encryptionKey, isSingleKey);
else
encryptionKey->GenerateKeys ();
@@ -966,7 +969,7 @@ namespace client
m_StandardEncryptionKey.reset (encryptionKey);
}
if (IsPublic ())
if (isPublic)
LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created");
try
@@ -979,7 +982,7 @@ namespace client
m_StreamingAckDelay = std::stoi(it->second);
it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS);
if (it != params->end ())
m_IsStreamingAnswerPings = (it->second == "true");
i2p::config::GetOption (it->second, m_IsStreamingAnswerPings);
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
{
@@ -1096,13 +1099,7 @@ namespace client
}
auto leaseSet = FindLeaseSet (dest);
if (leaseSet)
{
auto stream = CreateStream (leaseSet, port);
GetService ().post ([streamRequestComplete, stream]()
{
streamRequestComplete(stream);
});
}
streamRequestComplete(CreateStream (leaseSet, port));
else
{
auto s = GetSharedFromThis ();
@@ -1135,35 +1132,6 @@ namespace client
});
}
template<typename Dest>
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStreamSync (const Dest& dest, int port)
{
std::shared_ptr<i2p::stream::Stream> stream;
std::condition_variable streamRequestComplete;
std::mutex streamRequestCompleteMutex;
std::unique_lock<std::mutex> l(streamRequestCompleteMutex);
CreateStream (
[&streamRequestComplete, &streamRequestCompleteMutex, &stream](std::shared_ptr<i2p::stream::Stream> s)
{
stream = s;
std::unique_lock<std::mutex> l(streamRequestCompleteMutex);
streamRequestComplete.notify_all ();
},
dest, port);
streamRequestComplete.wait (l);
return stream;
}
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (const i2p::data::IdentHash& dest, int port)
{
return CreateStreamSync (dest, port);
}
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port)
{
return CreateStreamSync (dest, port);
}
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, int port)
{
if (m_StreamingDestination)

View File

@@ -247,8 +247,6 @@ namespace client
// following methods operate with default streaming destination
void CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port = 0);
void CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port = 0);
std::shared_ptr<i2p::stream::Stream> CreateStream (const i2p::data::IdentHash& dest, int port = 0); // sync
std::shared_ptr<i2p::stream::Stream> CreateStream (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port = 0); // sync
std::shared_ptr<i2p::stream::Stream> CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, int port = 0);
void SendPing (const i2p::data::IdentHash& to);
void SendPing (std::shared_ptr<const i2p::data::BlindedPublicKey> to);
@@ -284,9 +282,6 @@ namespace client
void PersistTemporaryKeys (EncryptionKey * keys, bool isSingleKey);
void ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params);
template<typename Dest>
std::shared_ptr<i2p::stream::Stream> CreateStreamSync (const Dest& dest, int port);
private:
i2p::data::PrivateKeys m_Keys;
@@ -324,5 +319,4 @@ namespace client
}
}
#endif

View File

@@ -212,7 +212,7 @@ namespace garlic
uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only
std::shared_ptr<i2p::crypto::X25519Keys> m_EphemeralKeys;
SessionState m_State = eSessionStateNew;
uint64_t m_SessionCreatedTimestamp = 0, m_LastActivityTimestamp = 0, // incoming (in seconds)
uint64_t m_SessionCreatedTimestamp = 0, m_LastActivityTimestamp = 0, // incoming (in seconds)
m_LastSentTimestamp = 0; // in milliseconds
std::shared_ptr<RatchetTagSet> m_SendTagset, m_NSRSendTagset;
std::unique_ptr<i2p::data::IdentHash> m_Destination;// TODO: might not need it
@@ -229,7 +229,7 @@ namespace garlic
{
return m_Destination ? *m_Destination : i2p::data::IdentHash ();
}
};
};
// single session for all incoming messages
class RouterIncomingRatchetSession: public ECIESX25519AEADRatchetSession

View File

@@ -33,7 +33,7 @@ namespace crypto
BN_add (l, l, tmp);
BN_sub_word (two_252_2, 2); // 2^252 - 2
// -121665*inv(121666)
// -121665*inv(121666)
d = BN_new ();
BN_set_word (tmp, 121666);
BN_mod_inverse (tmp, tmp, q, ctx);
@@ -61,7 +61,7 @@ namespace crypto
BN_mod (By, By, q, ctx); // % q
// precalculate Bi256 table
Bi256Carry = { Bx, By }; // B
Bi256Carry = { Bx, By }; // B
for (int i = 0; i < 32; i++)
{
Bi256[i][0] = Bi256Carry; // first point
@@ -215,7 +215,7 @@ namespace crypto
if (!t1) { t1 = BN_CTX_get (ctx); BN_mul (t1, p1.x, p1.y, ctx); }
if (!t2) { t2 = BN_CTX_get (ctx); BN_mul (t2, p2.x, p2.y, ctx); }
BN_mul (t3, t1, t2, ctx);
BN_mul (t3, t3, d, ctx); // C = d*t1*t2
BN_mul (t3, t3, d, ctx); // C = d*t1*t2
if (p1.z)
{
@@ -264,9 +264,9 @@ namespace crypto
else
{
BN_mul (t2, p.x, p.y, ctx); // t = x*y
BN_sqr (t2, t2, ctx); // t2 = t^2
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
else
@@ -349,7 +349,7 @@ namespace crypto
BN_mod_inverse (y, p.z, q, ctx);
BN_mod_mul (x, p.x, y, q, ctx); // x = x/z
BN_mod_mul (y, p.y, y, q, ctx); // y = y/z
return EDDSAPoint{x, y};
return EDDSAPoint{x, y};
}
else
return EDDSAPoint{BN_dup (p.x), BN_dup (p.y)};
@@ -506,13 +506,13 @@ namespace crypto
std::swap (z2, z3);
}
BN_mod_inverse (z2, z2, q, ctx);
BIGNUM * res = BN_new (); // not from ctx
BIGNUM * res = BN_new (); // not from ctx
BN_mod_mul(res, x2, z2, q, ctx);
BN_CTX_end (ctx);
return res;
}
void Ed25519::ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const
void Ed25519::ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const
{
BIGNUM * p1 = DecodeBN<32> (p);
uint8_t k[32];
@@ -524,7 +524,7 @@ namespace crypto
BN_free (p1); BN_free (n); BN_free (q1);
}
void Ed25519::ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const
void Ed25519::ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const
{
BIGNUM *p1 = BN_new (); BN_set_word (p1, 9);
uint8_t k[32];

View File

@@ -85,8 +85,8 @@ namespace crypto
EDDSAPoint DecodePublicKey (const uint8_t * buf, BN_CTX * ctx) const;
void EncodePublicKey (const EDDSAPoint& publicKey, uint8_t * buf, BN_CTX * ctx) const;
#if !OPENSSL_X25519
void ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const; // p is point, e is number for x25519
void ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const;
void ScalarMul (const uint8_t * p, const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const; // p is point, e is number for x25519
void ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const;
#endif
void BlindPublicKey (const uint8_t * pub, const uint8_t * seed, uint8_t * blinded); // for encrypted LeaseSet2, pub - 32, seed - 64, blinded - 32
void BlindPrivateKey (const uint8_t * priv, const uint8_t * seed, uint8_t * blindedPriv, uint8_t * blindedPub); // for encrypted LeaseSet2, pub - 32, seed - 64, blinded - 32

View File

@@ -189,7 +189,7 @@ namespace crypto
// assume a < p, so don't check for a % p = 0, but a = 0 only
if (BN_is_zero(a)) return 0;
BIGNUM * r = BN_CTX_get (ctx);
BN_mod_exp (r, a, p12, p, ctx); // r = a^((p-1)/2) mod p
BN_mod_exp (r, a, p12, p, ctx); // r = a^((p-1)/2) mod p
if (BN_is_word(r, 1))
return 1;
else if (BN_is_zero(r))

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2020, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -60,38 +60,10 @@ namespace fs {
}
void DetectDataDir(const std::string & cmdline_param, bool isService) {
// with 'datadir' option
if (cmdline_param != "") {
dataDir = cmdline_param;
return;
}
#if !defined(MAC_OSX) && !defined(ANDROID)
// with 'service' option
if (isService) {
#ifdef _WIN32
wchar_t commonAppData[MAX_PATH];
if(SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, 0, commonAppData) != S_OK)
{
#ifdef WIN32_APP
MessageBox(NULL, TEXT("Unable to get common AppData path!"), TEXT("I2Pd: error"), MB_ICONERROR | MB_OK);
#else
fprintf(stderr, "Error: Unable to get common AppData path!");
#endif
exit(1);
}
else
{
dataDir = boost::filesystem::wpath(commonAppData).string() + "\\" + appName;
}
#else
dataDir = "/var/lib/" + appName;
#endif
return;
}
#endif
// detect directory as usual
#ifdef _WIN32
wchar_t localAppData[MAX_PATH];
@@ -145,10 +117,12 @@ namespace fs {
dataDir = std::string (ext) + "/" + appName;
return;
}
#endif // ANDROID
// use /home/user/.i2pd or /tmp/i2pd
#endif
// otherwise use /data/files
char *home = getenv("HOME");
if (home != NULL && strlen(home) > 0) {
if (isService) {
dataDir = "/var/lib/" + appName;
} else if (home != NULL && strlen(home) > 0) {
dataDir = std::string(home) + "/." + appName;
} else {
dataDir = "/tmp/" + appName;

View File

@@ -83,8 +83,8 @@ namespace fs {
/**
* @brief Set datadir either from cmdline option or using autodetection
* @param cmdline_param Value of cmdline parameter --datadir=<something>
* @param isService Value of cmdline parameter --service
* @param cmdline_param Value of cmdline parameter --datadir=<something>
* @param isService Value of cmdline parameter --service
*
* Examples of autodetected paths:
*
@@ -93,11 +93,11 @@ namespace fs {
* Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/
* Unix: /var/lib/i2pd/ (system=1) >> ~/.i2pd/ or /tmp/i2pd/
*/
void DetectDataDir(const std::string & cmdline_datadir, bool isService = false);
void DetectDataDir(const std::string & cmdline_datadir, bool isService = false);
/**
* @brief Set certsdir either from cmdline option or using autodetection
* @param cmdline_param Value of cmdline parameter --certsdir=<something>
* @param cmdline_param Value of cmdline parameter --certsdir=<something>
*
* Examples of autodetected paths:
*
@@ -106,7 +106,7 @@ namespace fs {
* Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/certificates
* Unix: /var/lib/i2pd/certificates (system=1) >> ~/.i2pd/ or /tmp/i2pd/certificates
*/
void SetCertsDir(const std::string & cmdline_certsdir);
void SetCertsDir(const std::string & cmdline_certsdir);
/**
* @brief Create subdirectories inside datadir
@@ -115,7 +115,7 @@ namespace fs {
/**
* @brief Get list of files in directory
* @param path Path to directory
* @param path Path to directory
* @param files Vector to store found files
* @return true on success and false if directory not exists
*/

View File

@@ -148,8 +148,8 @@ namespace data
if (it != m_SigningKeys.end ())
return it->second.second;
return 0;
}
}
std::string CreateFamilySignature (const std::string& family, const IdentHash& ident)
{
auto filename = i2p::fs::DataDirPath("family", (family + ".key"));

View File

@@ -293,14 +293,14 @@ namespace garlic
size_t size = 0;
if (isDestination)
{
buf[size] = eGarlicDeliveryTypeDestination << 5;// delivery instructions flag destination
buf[size] = eGarlicDeliveryTypeDestination << 5;// delivery instructions flag destination
size++;
memcpy (buf + size, m_Destination->GetIdentHash (), 32);
size += 32;
}
else
{
buf[size] = 0;// delivery instructions flag local
buf[size] = 0;// delivery instructions flag local
size++;
}
@@ -487,8 +487,8 @@ namespace garlic
void GarlicDestination::SubmitECIESx25519Key (const uint8_t * key, uint64_t tag)
{
AddECIESx25519Key (key, tag);
}
}
void GarlicDestination::HandleGarlicMessage (std::shared_ptr<I2NPMessage> msg)
{
uint8_t * buf = msg->GetPayload ();
@@ -744,7 +744,7 @@ namespace garlic
LogPrint (eLogError, "Garlic: Message is too short");
break;
}
buf += GetI2NPMessageLength (buf, len - offset); // I2NP
buf += GetI2NPMessageLength (buf, len - offset); // I2NP
buf += 4; // CloveID
buf += 8; // Date
buf += 3; // Certificate
@@ -1024,7 +1024,7 @@ namespace garlic
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
for (auto it: files)
if (ts >= i2p::fs::GetLastUpdateTime (it) + INCOMING_TAGS_EXPIRATION_TIMEOUT)
i2p::fs::Remove (it);
i2p::fs::Remove (it);
}
void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len)

View File

@@ -96,7 +96,7 @@ namespace crypto
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);
GetXY (C, x, nullptr); // Cx
GetXY (C, x, nullptr); // Cx
BN_mod (x, x, q, ctx); // Cx % q
bool ret = !BN_cmp (x, r); // Cx = r ?
EC_POINT_free (C);
@@ -111,8 +111,8 @@ namespace crypto
BN_CTX * ctx = BN_CTX_new ();
BN_CTX_start (ctx);
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 * 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);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -135,7 +135,6 @@ namespace http
? url.substr(pos_p, std::string::npos)
: url.substr(pos_p, pos_c - pos_p);
/* stoi throws exception on failure, we don't need it */
port = 0;
for (char c : port_str) {
if (c < '0' || c > '9')
return false;
@@ -280,7 +279,7 @@ namespace http
method = tokens[0];
uri = tokens[1];
version = tokens[2];
expect = HEADER_LINE;
expect = HEADER_LINE;
}
else
{
@@ -364,7 +363,7 @@ namespace http
return false; /* no header */
if (it->second.find("gzip") != std::string::npos)
return true; /* gotcha! */
if (includingI2PGzip && it->second.find("x-i2p-gzip") != std::string::npos)
if (includingI2PGzip && it->second.find("x-i2p-gzip") != std::string::npos)
return true;
return false;
}
@@ -410,7 +409,7 @@ namespace http
/* all ok */
version = tokens[0];
status = tokens[2];
expect = HEADER_LINE;
expect = HEADER_LINE;
} else {
std::string line = str.substr(pos, eol - pos);
auto p = parse_header_line(line);
@@ -461,7 +460,7 @@ namespace http
case 304: ptr = "Not Modified"; break;
case 307: ptr = "Temporary Redirect"; break;
/* client error */
case 400: ptr = "Bad Request"; break;
case 400: ptr = "Bad Request"; break;
case 401: ptr = "Unauthorized"; break;
case 403: ptr = "Forbidden"; break;
case 404: ptr = "Not Found"; break;
@@ -472,7 +471,7 @@ namespace http
case 502: ptr = "Bad Gateway"; break;
case 503: ptr = "Not Implemented"; break;
case 504: ptr = "Gateway Timeout"; break;
default: ptr = "Unknown Status"; break;
default: ptr = "Unknown Status"; break;
}
return ptr;
}

View File

@@ -161,7 +161,7 @@ namespace http
/**
* @brief Merge HTTP response content with Transfer-Encoding: chunked
* @param in Input stream
* @param in Input stream
* @param out Output stream
* @return true on success, false otherwise
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -171,7 +171,7 @@ namespace i2p
std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest,
const std::set<i2p::data::IdentHash>& excludedFloodfills,
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel, const uint8_t * replyKey,
const uint8_t * replyTag, bool replyECIES)
const uint8_t * replyTag, bool replyECIES)
{
int cnt = excludedFloodfills.size ();
auto m = cnt > 7 ? NewI2NPMessage () : NewI2NPShortMessage ();
@@ -244,7 +244,7 @@ namespace i2p
}
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::RouterInfo> router,
uint32_t replyToken, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel)
uint32_t replyToken, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel)
{
if (!router) // we send own RouterInfo
router = context.GetSharedRouterInfo ();
@@ -629,7 +629,7 @@ namespace i2p
// we send it to reply tunnel
transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
CreateTunnelGatewayMsg (bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
i2p::garlic::WrapECIESX25519Message (replyMsg, noiseState.m_CK + 32, tag)));
i2p::garlic::WrapECIESX25519Message (replyMsg, noiseState.m_CK + 32, tag)));
}
else
{
@@ -802,8 +802,13 @@ namespace i2p
break;
case eI2NPGarlic:
{
if (msg->from && msg->from->GetTunnelPool ())
msg->from->GetTunnelPool ()->ProcessGarlicMessage (msg);
if (msg->from)
{
if (msg->from->GetTunnelPool ())
msg->from->GetTunnelPool ()->ProcessGarlicMessage (msg);
else
LogPrint (eLogInfo, "I2NP: Local destination for garlic doesn't exist anymore");
}
else
i2p::context.ProcessGarlicMessage (msg);
break;

View File

@@ -150,7 +150,7 @@ namespace tunnel
std::shared_ptr<i2p::tunnel::InboundTunnel> from;
I2NPMessage (): buf (nullptr),len (I2NP_HEADER_SIZE + 2),
offset(2), maxLen (0), from (nullptr) {}; // reserve 2 bytes for NTCP header
offset(2), maxLen (0), from (nullptr) {}; // reserve 2 bytes for NTCP header
// header accessors
uint8_t * GetHeader () { return GetBuffer (); };
@@ -274,8 +274,8 @@ namespace tunnel
uint32_t replyTunnelID, bool exploratory = false, std::set<i2p::data::IdentHash> * excludedPeers = nullptr);
std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest,
const std::set<i2p::data::IdentHash>& excludedFloodfills,
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel,
const uint8_t * replyKey, const uint8_t * replyTag, bool replyECIES = false);
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel,
const uint8_t * replyKey, const uint8_t * replyTag, bool replyECIES = false);
std::shared_ptr<I2NPMessage> CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, std::vector<i2p::data::IdentHash> routers);
std::shared_ptr<I2NPMessage> CreateDatabaseStoreMsg (std::shared_ptr<const i2p::data::RouterInfo> router = nullptr, uint32_t replyToken = 0, std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel = nullptr);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2020, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -49,30 +49,13 @@ namespace data
IdentityEx::IdentityEx(const uint8_t * publicKey, const uint8_t * signingKey, SigningKeyType type, CryptoKeyType cryptoType)
{
/*uint8_t randomPaddingBlock[32];
RAND_bytes (randomPaddingBlock, 32);*/
if (cryptoType == CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
{
/*memcpy (m_StandardIdentity.publicKey, publicKey ? publicKey : randomPaddingBlock, 32);
for (int i = 0; i < 7; i++) // 224 bytes
memcpy (m_StandardIdentity.publicKey + 32*(i + 1), randomPaddingBlock, 32);*/
if (publicKey)
{
memcpy (m_StandardIdentity.publicKey, publicKey, 32);
RAND_bytes (m_StandardIdentity.publicKey + 32, 224);
}
else
RAND_bytes (m_StandardIdentity.publicKey, 256);
memcpy (m_StandardIdentity.publicKey, publicKey, 32);
RAND_bytes (m_StandardIdentity.publicKey + 32, 224);
}
else
{
if (publicKey)
memcpy (m_StandardIdentity.publicKey, publicKey, 256);
else
RAND_bytes (m_StandardIdentity.publicKey, 256);
/*for (int i = 0; i < 8; i++) // 256 bytes
memcpy (m_StandardIdentity.publicKey + 32*i, randomPaddingBlock, 32);*/
}
memcpy (m_StandardIdentity.publicKey, publicKey, 256);
if (type != SIGNING_KEY_TYPE_DSA_SHA1)
{
size_t excessLen = 0;
@@ -81,7 +64,7 @@ namespace data
{
case SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
{
size_t padding = 128 - i2p::crypto::ECDSAP256_KEY_LENGTH; // 64 = 128 - 64
size_t padding = 128 - i2p::crypto::ECDSAP256_KEY_LENGTH; // 64 = 128 - 64
RAND_bytes (m_StandardIdentity.signingKey, padding);
memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::ECDSAP256_KEY_LENGTH);
break;
@@ -110,9 +93,7 @@ namespace data
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
{
size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32
/*for (int i = 0; i < 3; i++) // 96 bytes
memcpy (m_StandardIdentity.signingKey + 32*i, randomPaddingBlock, 32);*/
RAND_bytes (m_StandardIdentity.signingKey, 96);
RAND_bytes (m_StandardIdentity.signingKey, padding);
memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH);
break;
}
@@ -714,7 +695,7 @@ namespace data
return nullptr;
}
PrivateKeys PrivateKeys::CreateRandomKeys (SigningKeyType type, CryptoKeyType cryptoType, bool isDestination)
PrivateKeys PrivateKeys::CreateRandomKeys (SigningKeyType type, CryptoKeyType cryptoType)
{
if (type != SIGNING_KEY_TYPE_DSA_SHA1)
{
@@ -724,12 +705,9 @@ namespace data
GenerateSigningKeyPair (type, keys.m_SigningPrivateKey, signingPublicKey);
// encryption
uint8_t publicKey[256];
if (isDestination)
RAND_bytes (keys.m_PrivateKey, 256);
else
GenerateCryptoKeyPair (cryptoType, keys.m_PrivateKey, publicKey);
GenerateCryptoKeyPair (cryptoType, keys.m_PrivateKey, publicKey);
// identity
keys.m_Public = std::make_shared<IdentityEx> (isDestination ? nullptr : publicKey, signingPublicKey, type, cryptoType);
keys.m_Public = std::make_shared<IdentityEx> (publicKey, signingPublicKey, type, cryptoType);
keys.CreateSigner ();
return keys;
@@ -810,7 +788,7 @@ namespace data
keys.m_OfflineSignature.resize (pubKeyLen + m_Public->GetSignatureLen () + 6);
htobe32buf (keys.m_OfflineSignature.data (), expires); // expires
htobe16buf (keys.m_OfflineSignature.data () + 4, type); // type
GenerateSigningKeyPair (type, keys.m_SigningPrivateKey, keys.m_OfflineSignature.data () + 6); // public key
GenerateSigningKeyPair (type, keys.m_SigningPrivateKey, keys.m_OfflineSignature.data () + 6); // public key
Sign (keys.m_OfflineSignature.data (), pubKeyLen + 6, keys.m_OfflineSignature.data () + 6 + pubKeyLen); // signature
// recreate signer
keys.m_Signer = nullptr;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -120,7 +120,7 @@ namespace data
CryptoKeyType GetCryptoKeyType () const;
void DropVerifier () const; // to save memory
bool operator == (const IdentityEx & other) const { return GetIdentHash() == other.GetIdentHash(); }
bool operator == (const IdentityEx & other) const { return GetIdentHash() == other.GetIdentHash(); }
void RecalculateIdentHash(uint8_t * buff=nullptr);
static i2p::crypto::Verifier * CreateVerifier (SigningKeyType keyType);
@@ -171,7 +171,7 @@ namespace data
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> CreateDecryptor (const uint8_t * key) const;
static std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> CreateDecryptor (CryptoKeyType cryptoType, const uint8_t * key);
static PrivateKeys CreateRandomKeys (SigningKeyType type = SIGNING_KEY_TYPE_DSA_SHA1, CryptoKeyType cryptoType = CRYPTO_KEY_TYPE_ELGAMAL, bool isDestination = false);
static PrivateKeys CreateRandomKeys (SigningKeyType type = SIGNING_KEY_TYPE_DSA_SHA1, CryptoKeyType cryptoType = CRYPTO_KEY_TYPE_ELGAMAL);
static void GenerateSigningKeyPair (SigningKeyType type, uint8_t * priv, uint8_t * pub);
static void GenerateCryptoKeyPair (CryptoKeyType type, uint8_t * priv, uint8_t * pub); // priv and pub are 256 bytes long
static i2p::crypto::Signer * CreateSigner (SigningKeyType keyType, const uint8_t * priv);
@@ -222,7 +222,7 @@ namespace data
RoutingDestination () {};
virtual ~RoutingDestination () {};
virtual std::shared_ptr<const IdentityEx> GetIdentity () const = 0;
virtual std::shared_ptr<const IdentityEx> GetIdentity () const = 0;
virtual void Encrypt (const uint8_t * data, uint8_t * encrypted) const = 0; // encrypt data for
virtual bool IsDestination () const = 0; // for garlic

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -59,9 +59,9 @@ namespace data
if (readIdentity || !m_Identity)
m_Identity = std::make_shared<IdentityEx>(m_Buffer, m_BufferLen);
size_t size = m_Identity->GetFullLen ();
if (size + 256 > m_BufferLen)
if (size > m_BufferLen)
{
LogPrint (eLogError, "LeaseSet: Identity length ", int(size), " exceeds buffer size ", int(m_BufferLen));
LogPrint (eLogError, "LeaseSet: Identity length ", size, " exceeds buffer size ", m_BufferLen);
m_IsValid = false;
return;
}
@@ -74,7 +74,7 @@ namespace data
size += m_Identity->GetSigningPublicKeyLen (); // unused signing key
if (size + 1 > m_BufferLen)
{
LogPrint (eLogError, "LeaseSet: ", int(size), " exceeds buffer size ", int(m_BufferLen));
LogPrint (eLogError, "LeaseSet: ", size, " exceeds buffer size ", m_BufferLen);
m_IsValid = false;
return;
}
@@ -89,7 +89,7 @@ namespace data
}
if (size + num*LEASE_SIZE > m_BufferLen)
{
LogPrint (eLogError, "LeaseSet: ", int(size), " exceeds buffer size ", int(m_BufferLen));
LogPrint (eLogError, "LeaseSet: ", size, " exceeds buffer size ", m_BufferLen);
m_IsValid = false;
return;
}
@@ -125,7 +125,7 @@ namespace data
auto signedSize = leases - m_Buffer;
if (signedSize + m_Identity->GetSignatureLen () > m_BufferLen)
{
LogPrint (eLogError, "LeaseSet: Signature exceeds buffer size ", int(m_BufferLen));
LogPrint (eLogError, "LeaseSet: Signature exceeds buffer size ", m_BufferLen);
m_IsValid = false;
}
else if (!m_Identity->Verify (m_Buffer, signedSize, leases))
@@ -172,7 +172,7 @@ namespace data
m_ExpirationTime = lease.endDate;
if (m_StoreLeases)
{
auto ret = m_Leases.insert (i2p::data::netdb.NewLease (lease));
auto ret = m_Leases.insert (std::make_shared<Lease>(lease));
if (!ret.second) (*ret.first)->endDate = lease.endDate; // update existing
(*ret.first)->isUpdated = true;
}
@@ -274,7 +274,7 @@ namespace data
{
if (len <= m_BufferLen) m_BufferLen = len;
else
LogPrint (eLogError, "LeaseSet2: Actual buffer size ", int(len) , " exceeds full buffer size ", int(m_BufferLen));
LogPrint (eLogError, "LeaseSet2: Actual buffer size ", len , " exceeds full buffer size ", m_BufferLen);
}
LeaseSet2::LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases, CryptoKeyType preferredCrypto):
@@ -320,7 +320,7 @@ namespace data
else
identity = GetIdentity ();
size_t offset = identity->GetFullLen ();
if (offset + 8 > len) return;
if (offset + 8 >= len) return;
m_PublishedTimestamp = bufbe32toh (buf + offset); offset += 4; // published timestamp (seconds)
uint16_t expires = bufbe16toh (buf + offset); offset += 2; // expires (seconds)
SetExpirationTime ((m_PublishedTimestamp + expires)*1000LL); // in milliseconds
@@ -364,10 +364,6 @@ namespace data
SetIsValid (verified);
}
offset += m_TransientVerifier ? m_TransientVerifier->GetSignatureLen () : identity->GetSignatureLen ();
if (offset > len) {
LogPrint (eLogWarning, "LeaseSet2: short buffer: wanted ", int(offset), "bytes, have ", int(len));
return;
}
SetBufferLen (offset);
}
@@ -392,17 +388,17 @@ namespace data
// properties
uint16_t propertiesLen = bufbe16toh (buf + offset); offset += 2;
offset += propertiesLen; // skip for now. TODO: implement properties
if (offset + 1 >= len) return 0;
// key sections
CryptoKeyType preferredKeyType = m_EncryptionType;
bool preferredKeyFound = false;
if (offset + 1 > len) return 0;
int numKeySections = buf[offset]; offset++;
for (int i = 0; i < numKeySections; i++)
{
if (offset + 4 > len) return 0;
uint16_t keyType = bufbe16toh (buf + offset); offset += 2; // encryption key type
if (offset + 2 >= len) return 0;
uint16_t encryptionKeyLen = bufbe16toh (buf + offset); offset += 2;
if (offset + encryptionKeyLen > len) return 0;
if (offset + encryptionKeyLen >= len) return 0;
if (IsStoreLeases () && !preferredKeyFound) // create encryptor with leases only
{
// we pick first valid key if preferred not found
@@ -417,7 +413,7 @@ namespace data
offset += encryptionKeyLen;
}
// leases
if (offset + 1 > len) return 0;
if (offset + 1 >= len) return 0;
int numLeases = buf[offset]; offset++;
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
if (IsStoreLeases ())
@@ -436,8 +432,7 @@ namespace data
}
else
offset += numLeases*LEASE2_SIZE; // 40 bytes per lease
return (offset > len ? 0 : offset);
return offset;
}
size_t LeaseSet2::ReadMetaLS2TypeSpecificPart (const uint8_t * buf, size_t len)
@@ -447,18 +442,18 @@ namespace data
uint16_t propertiesLen = bufbe16toh (buf + offset); offset += 2;
offset += propertiesLen; // skip for now. TODO: implement properties
// entries
if (offset + 1 > len) return 0;
if (offset + 1 >= len) return 0;
int numEntries = buf[offset]; offset++;
for (int i = 0; i < numEntries; i++)
{
if (offset + LEASE2_SIZE > len) return 0;
if (offset + 40 >= len) return 0;
offset += 32; // hash
offset += 3; // flags
offset += 1; // cost
offset += 4; // expires
}
// revocations
if (offset + 1 > len) return 0;
if (offset + 1 >= len) return 0;
int numRevocations = buf[offset]; offset++;
for (int i = 0; i < numRevocations; i++)
{
@@ -587,7 +582,7 @@ namespace data
// helper for ExtractClientAuthData
static inline bool GetAuthCookie (const uint8_t * authClients, int numClients, const uint8_t * okm, uint8_t * authCookie)
{
// try to find clientCookie_i for clientID_i = okm[44:51]
// try to find clientCookie_i for clientID_i = okm[44:51]
for (int i = 0; i < numClients; i++)
{
if (!memcmp (okm + 44, authClients + i*40, 8)) // clientID_i
@@ -611,7 +606,7 @@ namespace data
{
const uint8_t * ephemeralPublicKey = buf + offset; offset += 32; // ephemeralPublicKey
uint16_t numClients = bufbe16toh (buf + offset); offset += 2; // clients
const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients
const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients
if (offset > len)
{
LogPrint (eLogError, "LeaseSet2: Too many clients ", numClients, " in DH auth data");
@@ -637,7 +632,7 @@ namespace data
{
const uint8_t * authSalt = buf + offset; offset += 32; // authSalt
uint16_t numClients = bufbe16toh (buf + offset); offset += 2; // clients
const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients
const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients
if (offset > len)
{
LogPrint (eLogError, "LeaseSet2: Too many clients ", numClients, " in PSK auth data");
@@ -742,7 +737,7 @@ namespace data
htobe64buf (m_Buffer + offset, ts);
offset += 8; // end date
}
// we don't sign it yet. must be signed later on
// we don't sign it yet. must be signed later on
}
LocalLeaseSet::LocalLeaseSet (std::shared_ptr<const IdentityEx> identity, const uint8_t * buf, size_t len):
@@ -1000,7 +995,7 @@ namespace data
ek.GenerateKeys (); // esk and epk
memcpy (authData, ek.GetPublicKey (), 32); authData += 32; // epk
htobe16buf (authData, authKeys->size ()); authData += 2; // num clients
uint8_t authInput[100]; // sharedSecret || cpk_i || subcredential || publishedTimestamp
uint8_t authInput[100]; // sharedSecret || cpk_i || subcredential || publishedTimestamp
memcpy (authInput + 64, subcredential, 36);
for (auto& it: *authKeys)
{

View File

@@ -128,8 +128,8 @@ namespace data
};
/**
* validate lease set buffer signature and extract expiration timestamp
* @returns true if the leaseset is well formed and signature is valid
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);

View File

@@ -46,7 +46,7 @@ namespace log {
#ifndef _WIN32
/**
* @brief Maps our log levels to syslog one
* @brief Maps our log levels to syslog one
* @return syslog priority LOG_*, as defined in syslog.h
*/
static inline int GetSyslogPrio (enum LogLevel l) {
@@ -113,11 +113,11 @@ namespace log {
std::string str_tolower(std::string s) {
std::transform(s.begin(), s.end(), s.begin(),
// static_cast<int(*)(int)>(std::tolower) // wrong
// [](int c){ return std::tolower(c); } // wrong
// [](char c){ return std::tolower(c); } // wrong
[](unsigned char c){ return std::tolower(c); } // correct
);
// static_cast<int(*)(int)>(std::tolower) // wrong
// [](int c){ return std::tolower(c); } // wrong
// [](char c){ return std::tolower(c); } // wrong
[](unsigned char c){ return std::tolower(c); } // correct
);
return s;
}
@@ -170,7 +170,7 @@ namespace log {
break;
case eLogStdout:
default:
std::cout << TimeAsString(msg->timestamp)
std::cout << TimeAsString(msg->timestamp)
<< "@" << short_tid
<< "/" << LogMsgColors[msg->level] << g_LogLevelStr[msg->level] << LogMsgColors[eNumLogLevels]
<< " - " << msg->text << std::endl;

View File

@@ -52,7 +52,7 @@ namespace log {
{
private:
enum LogType m_Destination;
enum LogType m_Destination;
enum LogLevel m_MinLevel;
std::shared_ptr<std::ostream> m_LogStream;
std::string m_Logfile;
@@ -75,7 +75,7 @@ namespace log {
/**
* @brief Makes formatted string from unix timestamp
* @param ts Second since epoch
* @param ts Second since epoch
*
* This function internally caches the result for last provided value
*/
@@ -86,52 +86,52 @@ namespace log {
Log ();
~Log ();
LogType GetLogType () { return m_Destination; };
LogType GetLogType () { return m_Destination; };
LogLevel GetLogLevel () { return m_MinLevel; };
void Start ();
void Stop ();
/**
* @brief Sets minimal allowed level for log messages
* @param level String with wanted minimal msg level
* @brief Sets minimal allowed level for log messages
* @param level String with wanted minimal msg level
*/
void SetLogLevel (const std::string& level);
void SetLogLevel (const std::string& level);
/**
* @brief Sets log destination to logfile
* @param path Path to logfile
* @param path Path to logfile
*/
void SendTo (const std::string &path);
/**
* @brief Sets log destination to given output stream
* @param os Output stream
* @param os Output stream
*/
void SendTo (std::shared_ptr<std::ostream> os);
/**
* @brief Sets format for timestamps in log
* @param format String with timestamp format
* @brief Sets format for timestamps in log
* @param format String with timestamp format
*/
void SetTimeFormat (std::string format) { m_TimeFormat = format; };
#ifndef _WIN32
/**
* @brief Sets log destination to syslog
* @param name Wanted program name
* @param name Wanted program name
* @param facility Wanted log category
*/
void SendTo (const char *name, int facility);
#endif
/**
* @brief Format log message and write to output stream/syslog
* @param msg Pointer to processed message
* @brief Format log message and write to output stream/syslog
* @param msg Pointer to processed message
*/
void Append(std::shared_ptr<i2p::log::LogMsg> &);
/** @brief Reopen log file */
/** @brief Reopen log file */
void Reopen();
};
@@ -144,8 +144,8 @@ namespace log {
*/
struct LogMsg {
std::time_t timestamp;
std::string text; /**< message text as single string */
LogLevel level; /**< message level */
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, std::string&& txt): timestamp(ts), text(std::move(txt)), level(lvl) {}
@@ -153,7 +153,7 @@ namespace log {
Log & Logger();
typedef std::function<void (const std::string&)> ThrowFunction;
typedef std::function<void (const std::string&)> ThrowFunction;
ThrowFunction GetThrowFunction ();
void SetThrowFunction (ThrowFunction f);
} // log

View File

@@ -66,7 +66,7 @@ namespace transport
{
MixHash (sessionRequest + 32, 32); // encrypted payload
int paddingLength = sessionRequestLen - 64;
int paddingLength = sessionRequestLen - 64;
if (paddingLength > 0)
MixHash (sessionRequest + 64, paddingLength);
MixHash (epub, 32);
@@ -130,7 +130,7 @@ namespace transport
// m3p2Len
auto bufLen = i2p::context.GetRouterInfo ().GetBufferLen ();
m3p2Len = bufLen + 4 + 16; // (RI header + RI + MAC for now) TODO: implement options
htobe16buf (options + 4, m3p2Len);
htobe16buf (options + 4, m3p2Len);
// fill m3p2 payload (RouterInfo block)
m_SessionConfirmedBuffer = new uint8_t[m3p2Len + 48]; // m3p1 is 48 bytes
uint8_t * m3p2 = m_SessionConfirmedBuffer + 48;
@@ -231,11 +231,11 @@ namespace transport
auto ts = i2p::util::GetSecondsSinceEpoch ();
uint32_t tsA = bufbe32toh (options + 8);
if (tsA < ts - NTCP2_CLOCK_SKEW || tsA > ts + NTCP2_CLOCK_SKEW)
{
{
LogPrint (eLogWarning, "NTCP2: SessionRequest time difference ", (int)(ts - tsA), " exceeds clock skew");
clockSkew = true;
// we send SessionCreate to let Alice know our time and then close session
}
}
}
else
{
@@ -320,7 +320,7 @@ namespace transport
}
NTCP2Session::NTCP2Session (NTCP2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter,
std::shared_ptr<const i2p::data::RouterInfo::Address> addr):
std::shared_ptr<const i2p::data::RouterInfo::Address> addr):
TransportSession (in_RemoteRouter, NTCP2_ESTABLISH_TIMEOUT),
m_Server (server), m_Socket (m_Server.GetService ()),
m_IsEstablished (false), m_IsTerminated (false),
@@ -418,7 +418,7 @@ namespace transport
void NTCP2Session::DeleteNextReceiveBuffer (uint64_t ts)
{
if (m_NextReceivedBuffer && !m_IsReceiving &&
ts > m_LastActivityTimestamp + NTCP2_RECEIVE_BUFFER_DELETION_TIMEOUT)
ts > m_LastActivityTimestamp + NTCP2_RECEIVE_BUFFER_DELETION_TIMEOUT)
{
delete[] m_NextReceivedBuffer;
m_NextReceivedBuffer = nullptr;
@@ -484,9 +484,9 @@ namespace transport
if (clockSkew)
{
// we don't care about padding, send SessionCreated and close session
SendSessionCreated ();
SendSessionCreated ();
m_Server.GetService ().post (std::bind (&NTCP2Session::Terminate, shared_from_this ()));
}
}
else if (paddingLen > 0)
{
if (paddingLen <= NTCP2_SESSION_REQUEST_MAX_SIZE - 64) // session request is 287 bytes max
@@ -496,7 +496,7 @@ namespace transport
}
else
{
LogPrint (eLogWarning, "NTCP2: SessionRequest padding length ", (int)paddingLen, " is too long");
LogPrint (eLogWarning, "NTCP2: SessionRequest padding length ", (int)paddingLen, " is too long");
Terminate ();
}
}
@@ -549,7 +549,7 @@ namespace transport
}
else
{
LogPrint (eLogWarning, "NTCP2: SessionCreated padding length ", (int)paddingLen, " is too long");
LogPrint (eLogWarning, "NTCP2: SessionCreated padding length ", (int)paddingLen, " is too long");
Terminate ();
}
}
@@ -1126,11 +1126,11 @@ namespace transport
{
if (!m_SendKey ||
#if OPENSSL_SIPHASH
!m_SendMDCtx
!m_SendMDCtx
#else
!m_SendSipKey
!m_SendSipKey
#endif
) return;
) return;
m_NextSendBuffer = new uint8_t[49]; // 49 = 12 bytes message + 16 bytes MAC + 2 bytes size + up to 19 padding block
// termination block
m_NextSendBuffer[2] = eNTCP2BlkTermination;
@@ -1164,20 +1164,20 @@ namespace transport
else if (m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE)
{
LogPrint (eLogWarning, "NTCP2: Outgoing messages queue size to ",
GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE);
GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE);
Terminate ();
}
}
void NTCP2Session::SendLocalRouterInfo (bool update)
void NTCP2Session::SendLocalRouterInfo ()
{
if (update || !IsOutgoing ()) // we send it in SessionConfirmed for ougoing session
if (!IsOutgoing ()) // we send it in SessionConfirmed
m_Server.GetService ().post (std::bind (&NTCP2Session::SendRouterInfo, shared_from_this ()));
}
NTCP2Server::NTCP2Server ():
RunnableServiceWithWork ("NTCP2"), m_TerminationTimer (GetService ()),
m_ProxyType(eNoProxy), m_Resolver(GetService ())
m_ProxyType(eNoProxy), m_Resolver(GetService ())
{
}
@@ -1558,7 +1558,7 @@ namespace transport
case eSocksProxy:
{
// TODO: support username/password auth etc
static const uint8_t buff[3] = {SOCKS5_VER, 0x01, 0x00};
static const uint8_t buff[3] = {0x05, 0x01, 0x00};
boost::asio::async_write(conn->GetSocket(), boost::asio::buffer(buff, 3), boost::asio::transfer_all(),
[] (const boost::system::error_code & ec, std::size_t transferred)
{
@@ -1672,21 +1672,21 @@ namespace transport
size_t sz = 6; // header + port
auto buff = std::make_shared<std::vector<int8_t> >(256);
auto readbuff = std::make_shared<std::vector<int8_t> >(256);
(*buff)[0] = SOCKS5_VER;
(*buff)[1] = SOCKS5_CMD_CONNECT;
(*buff)[0] = 0x05;
(*buff)[1] = 0x01;
(*buff)[2] = 0x00;
auto& ep = conn->GetRemoteEndpoint ();
if(ep.address ().is_v4 ())
{
(*buff)[3] = SOCKS5_ATYP_IPV4;
(*buff)[3] = 0x01;
auto addrbytes = ep.address ().to_v4().to_bytes();
sz += 4;
memcpy(buff->data () + 4, addrbytes.data(), 4);
}
else if (ep.address ().is_v6 ())
{
(*buff)[3] = SOCKS5_ATYP_IPV6;
(*buff)[3] = 0x04;
auto addrbytes = ep.address ().to_v6().to_bytes();
sz += 16;
memcpy(buff->data () + 4, addrbytes.data(), 16);
@@ -1708,24 +1708,22 @@ namespace transport
}
});
boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff->data (), SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE), // read min reply size
boost::asio::transfer_all(),
boost::asio::async_read(conn->GetSocket(), boost::asio::buffer(readbuff->data (), 10),
[timer, conn, sz, readbuff](const boost::system::error_code & e, std::size_t transferred)
{
if (e)
LogPrint(eLogError, "NTCP2: SOCKS proxy read error ", e.message());
else if (!(*readbuff)[1]) // succeeded
if(e)
{
boost::system::error_code ec;
size_t moreBytes = conn->GetSocket ().available(ec);
if (moreBytes) // read remaining portion of reply if ipv6 received
boost::asio::read (conn->GetSocket (), boost::asio::buffer(readbuff->data (), moreBytes), boost::asio::transfer_all (), ec);
timer->cancel();
conn->ClientLogin();
return;
LogPrint(eLogError, "NTCP2: SOCKS proxy read error ", e.message());
}
else if(transferred == sz)
{
if((*readbuff)[1] == 0x00)
{
timer->cancel();
conn->ClientLogin();
return;
}
}
else
LogPrint(eLogError, "NTCP2: Proxy reply error ", (int)(*readbuff)[1]);
timer->cancel();
conn->Terminate();
});

View File

@@ -148,7 +148,7 @@ namespace transport
void ClientLogin (); // Alice
void ServerLogin (); // Bob
void SendLocalRouterInfo (bool update); // after handshake or by update
void SendLocalRouterInfo (); // after handshake
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
private:

View File

@@ -107,10 +107,7 @@ namespace data
{
i2p::util::SetThreadName("NetDB");
uint64_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0;
uint64_t lastProfilesCleanup = i2p::util::GetSecondsSinceEpoch ();
int16_t profilesCleanupVariance = 0;
uint32_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0;
while (m_IsRunning)
{
try
@@ -158,7 +155,6 @@ namespace data
m_Requests.ManageRequests ();
lastManageRequest = ts;
}
if (ts - lastSave >= 60) // save routers, manage leasesets and validate subscriptions every minute
{
if (lastSave)
@@ -168,20 +164,12 @@ namespace data
}
lastSave = ts;
}
if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT)
{
i2p::context.CleanupDestination ();
lastDestinationCleanup = ts;
}
if (ts - lastProfilesCleanup >= (uint64_t)(i2p::data::PEER_PROFILE_AUTOCLEAN_TIMEOUT + profilesCleanupVariance))
{
DeleteObsoleteProfiles ();
lastProfilesCleanup = ts;
profilesCleanupVariance = (rand () % (2 * i2p::data::PEER_PROFILE_AUTOCLEAN_VARIANCE) - i2p::data::PEER_PROFILE_AUTOCLEAN_VARIANCE);
}
// publish
if (!m_HiddenMode && i2p::transport::transports.IsOnline ())
{
@@ -207,7 +195,6 @@ namespace data
lastPublish = ts;
}
}
if (ts - lastExploratory >= 30) // exploratory every 30 seconds
{
auto numRouters = m_RouterInfos.size ();
@@ -240,10 +227,11 @@ namespace data
m_HiddenMode = hide;
}
std::shared_ptr<const RouterInfo> NetDb::AddRouterInfo (const uint8_t * buf, int len)
bool NetDb::AddRouterInfo (const uint8_t * buf, int len)
{
bool updated;
return AddRouterInfo (buf, len, updated);
AddRouterInfo (buf, len, updated);
return updated;
}
std::shared_ptr<const RouterInfo> NetDb::AddRouterInfo (const uint8_t * buf, int len, bool& updated)
@@ -271,10 +259,7 @@ namespace data
if (r->IsNewer (buf, len))
{
bool wasFloodfill = r->IsFloodfill ();
{
std::unique_lock<std::mutex> l(m_RouterInfosMutex);
r->Update (buf, len);
}
r->Update (buf, len);
LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64());
if (wasFloodfill != r->IsFloodfill ()) // if floodfill status updated
{
@@ -438,15 +423,12 @@ namespace data
// try reseeding from floodfill first if specified
std::string riPath;
if(i2p::config::GetOption("reseed.floodfill", riPath))
{
if(i2p::config::GetOption("reseed.floodfill", riPath)) {
auto ri = std::make_shared<RouterInfo>(riPath);
if (ri->IsFloodfill())
{
if (ri->IsFloodfill()) {
const uint8_t * riData = ri->GetBuffer();
int riLen = ri->GetBufferLen();
if (!i2p::data::netdb.AddRouterInfo(riData, riLen))
{
if(!i2p::data::netdb.AddRouterInfo(riData, riLen)) {
// bad router info
LogPrint(eLogError, "NetDb: Bad router info");
return;
@@ -494,7 +476,7 @@ namespace data
{
auto r = std::make_shared<RouterInfo>(path);
if (r->GetRouterIdentity () && !r->IsUnreachable () && r->HasValidAddresses () &&
ts < r->GetTimestamp () + 24*60*60*NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT*1000LL)
ts < r->GetTimestamp () + 24*60*60*NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT*1000LL)
{
r->DeleteBuffer ();
if (m_RouterInfos.emplace (r->GetIdentHash (), r).second)
@@ -625,11 +607,10 @@ namespace data
}
// make router reachable back if too few routers or floodfills
if (it.second->IsUnreachable () && (total - deletedCount < NETDB_MIN_ROUTERS ||
(it.second->IsFloodfill () && totalFloodfills - deletedFloodfillsCount < NETDB_MIN_FLOODFILLS)))
(it.second->IsFloodfill () && totalFloodfills - deletedFloodfillsCount < NETDB_MIN_FLOODFILLS)))
it.second->SetUnreachable (false);
// find & mark expired routers
if (!it.second->IsReachable () && (it.second->GetCompatibleTransports (true) & (RouterInfo::eSSUV4 | RouterInfo::eSSU2V4)))
// non-reachable router, but reachable by ipv4 SSU or SSU2 means introducers
if (!it.second->IsReachable () && it.second->IsSSU (false))
{
if (ts > it.second->GetTimestamp () + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT*1000LL)
// RouterInfo expires after 1 hour if uses introducer
@@ -649,7 +630,7 @@ namespace data
} // m_RouterInfos iteration
m_RouterInfoBuffersPool.CleanUpMt ();
if (updatedCount > 0)
LogPrint (eLogInfo, "NetDb: Saved ", updatedCount, " new/updated routers");
if (deletedCount > 0)
@@ -678,7 +659,7 @@ namespace data
else
++it;
}
}
}
}
void NetDb::RequestDestination (const IdentHash& destination, RequestedDestination::RequestComplete requestComplete, bool direct)
@@ -694,7 +675,7 @@ namespace data
if (floodfill)
{
if (direct && !floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) &&
!i2p::transport::transports.IsConnected (floodfill->GetIdentHash ()))
!i2p::transport::transports.IsConnected (floodfill->GetIdentHash ()))
direct = false; // floodfill can't be reached directly
if (direct)
transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ()));
@@ -946,9 +927,9 @@ namespace data
}
uint16_t numExcluded = bufbe16toh (excluded);
excluded += 2;
if (numExcluded > 512 || (excluded - buf) + numExcluded*32 > (int)msg->GetPayloadLength ())
if (numExcluded > 512)
{
LogPrint (eLogWarning, "NetDb: Number of excluded peers", numExcluded, " is too much");
LogPrint (eLogWarning, "NetDb: Number of excluded peers", numExcluded, " exceeds 512");
return;
}
@@ -957,11 +938,10 @@ namespace data
{
LogPrint (eLogInfo, "NetDb: Exploratory close to ", key, " ", numExcluded, " excluded");
std::set<IdentHash> excludedRouters;
const uint8_t * excluded_ident = excluded;
for (int i = 0; i < numExcluded; i++)
{
excludedRouters.insert (excluded_ident);
excluded_ident += 32;
excludedRouters.insert (excluded);
excluded += 32;
}
std::vector<IdentHash> routers;
for (int i = 0; i < 3; i++)
@@ -978,13 +958,14 @@ namespace data
else
{
if (lookupType == DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP ||
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)
{
auto router = FindRouter (ident);
if (router)
{
LogPrint (eLogDebug, "NetDb: Requested RouterInfo ", key, " found");
PopulateRouterInfoBuffer (router);
if (!router->GetBuffer ())
router->LoadBuffer (m_Storage.Path (router->GetIdentHashBase64 ()));
if (router->GetBuffer ())
replyMsg = CreateDatabaseStoreMsg (router);
}
@@ -1019,7 +1000,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)
@@ -1142,7 +1123,7 @@ namespace data
m_PublishExcluded.insert (floodfill->GetIdentHash ());
m_PublishReplyToken = replyToken;
if (floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) || // are we able to connect?
i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) // already connected ?
i2p::transport::transports.IsConnected (floodfill->GetIdentHash ())) // already connected ?
// send directly
transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken));
else
@@ -1209,16 +1190,6 @@ namespace data
});
}
std::shared_ptr<const RouterInfo> NetDb::GetRandomSSU2PeerTestRouter (bool v4, const std::set<IdentHash>& excluded) const
{
return GetRandomRouter (
[v4, &excluded](std::shared_ptr<const RouterInfo> router)->bool
{
return !router->IsHidden () && router->IsECIES () &&
router->IsSSU2PeerTesting (v4) && !excluded.count (router->GetIdentHash ());
});
}
std::shared_ptr<const RouterInfo> NetDb::GetRandomSSUV6Router () const
{
return GetRandomRouter (
@@ -1238,16 +1209,6 @@ namespace data
});
}
std::shared_ptr<const RouterInfo> NetDb::GetRandomSSU2Introducer (bool v4, const std::set<IdentHash>& excluded) const
{
return GetRandomRouter (
[v4, &excluded](std::shared_ptr<const RouterInfo> router)->bool
{
return !router->IsHidden () && router->IsSSU2Introducer (v4) &&
!excluded.count (router->GetIdentHash ());
});
}
std::shared_ptr<const RouterInfo> NetDb::GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const
{
return GetRandomRouter (
@@ -1403,7 +1364,7 @@ namespace data
return res;
}
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouterInFamily (FamilyID fam) const
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouterInFamily (FamilyID fam) const
{
return GetRandomRouter(
[fam](std::shared_ptr<const RouterInfo> router)->bool
@@ -1448,13 +1409,6 @@ namespace data
else
++it;
}
m_LeasesPool.CleanUpMt ();
}
void NetDb::PopulateRouterInfoBuffer (std::shared_ptr<RouterInfo> r)
{
if (!r || r->GetBuffer ()) return;
r->LoadBuffer (m_Storage.Path (r->GetIdentHashBase64 ()));
}
}
}

View File

@@ -69,7 +69,7 @@ namespace data
void Start ();
void Stop ();
std::shared_ptr<const RouterInfo> AddRouterInfo (const uint8_t * buf, int len);
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);
bool AddLeaseSet2 (const IdentHash& ident, const uint8_t * buf, int len, uint8_t storeType);
@@ -90,10 +90,8 @@ namespace data
std::shared_ptr<const RouterInfo> GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const;
std::shared_ptr<const RouterInfo> GetHighBandwidthRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const;
std::shared_ptr<const RouterInfo> GetRandomPeerTestRouter (bool v4, const std::set<IdentHash>& excluded) const;
std::shared_ptr<const RouterInfo> GetRandomSSU2PeerTestRouter (bool v4, const std::set<IdentHash>& excluded) const;
std::shared_ptr<const RouterInfo> GetRandomSSUV6Router () const; // TODO: change to v6 peer test later
std::shared_ptr<const RouterInfo> GetRandomIntroducer (bool v4, const std::set<IdentHash>& excluded) const;
std::shared_ptr<const RouterInfo> GetRandomSSU2Introducer (bool v4, const std::set<IdentHash>& excluded) const;
std::shared_ptr<const RouterInfo> GetClosestFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
std::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num,
std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
@@ -125,9 +123,7 @@ namespace data
void ClearRouterInfos () { m_RouterInfos.clear (); };
std::shared_ptr<RouterInfo::Buffer> NewRouterInfoBuffer () { return m_RouterInfoBuffersPool.AcquireSharedMt (); };
void PopulateRouterInfoBuffer (std::shared_ptr<RouterInfo> r);
std::shared_ptr<Lease> NewLease (const Lease& lease) { return m_LeasesPool.AcquireSharedMt (lease); };
uint32_t GetPublishReplyToken () const { return m_PublishReplyToken; };
private:
@@ -183,7 +179,6 @@ namespace data
uint32_t m_PublishReplyToken = 0;
i2p::util::MemoryPoolMt<RouterInfo::Buffer> m_RouterInfoBuffersPool;
i2p::util::MemoryPoolMt<Lease> m_LeasesPool;
};
extern NetDb netdb;

View File

@@ -60,7 +60,7 @@ namespace data
void Start ();
void Stop ();
std::shared_ptr<RequestedDestination> CreateRequest (const IdentHash& destination, bool isExploratory, RequestedDestination::RequestComplete requestComplete = nullptr);
std::shared_ptr<RequestedDestination> CreateRequest (const IdentHash& destination, bool isExploratory, RequestedDestination::RequestComplete requestComplete = nullptr);
void RequestComplete (const IdentHash& ident, std::shared_ptr<RouterInfo> r);
std::shared_ptr<RequestedDestination> FindRequest (const IdentHash& ident) const;
void ManageRequests ();

View File

@@ -1,12 +1,11 @@
/**
* This code is licensed under the MCGSI Public License
* Copyright 2018 Jeff Becker
*
*Kovri go write your own code
*
*/
#include "Poly1305.h"
/**
This code is licensed under the MCGSI Public License
Copyright 2018 Jeff Becker
Kovri go write your own code
*/
#if !OPENSSL_AEAD_CHACHA20_POLY1305
namespace i2p

View File

@@ -5,7 +5,6 @@
* Kovri go write your own code
*
*/
#ifndef LIBI2PD_POLY1305_H
#define LIBI2PD_POLY1305_H
#include <cstdint>

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2020, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -29,8 +29,6 @@ namespace data
const char PEER_PROFILE_USAGE_REJECTED[] = "rejected";
const int PEER_PROFILE_EXPIRATION_TIMEOUT = 72; // in hours (3 days)
const int PEER_PROFILE_AUTOCLEAN_TIMEOUT = 24 * 3600; // in seconds (1 day)
const int PEER_PROFILE_AUTOCLEAN_VARIANCE = 3 * 3600; // in seconds (3 hours)
class RouterProfile
{

View File

@@ -28,7 +28,7 @@ namespace util
void Put (Element e)
{
std::unique_lock<std::mutex> l(m_QueueMutex);
std::unique_lock<std::mutex> l(m_QueueMutex);
m_Queue.push (std::move(e));
m_NonEmpty.notify_one ();
}
@@ -38,7 +38,7 @@ namespace util
{
if (!vec.empty ())
{
std::unique_lock<std::mutex> l(m_QueueMutex);
std::unique_lock<std::mutex> l(m_QueueMutex);
for (const auto& it: vec)
m_Queue.push (std::move(it));
m_NonEmpty.notify_one ();

View File

@@ -187,31 +187,31 @@ namespace data
}
s.seekg (1, std::ios::cur); // su3 file format version
SigningKeyType signatureType;
s.read ((char *)&signatureType, 2); // signature type
s.read ((char *)&signatureType, 2); // signature type
signatureType = be16toh (signatureType);
uint16_t signatureLength;
s.read ((char *)&signatureLength, 2); // signature length
s.read ((char *)&signatureLength, 2); // signature length
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
if (fileType != 0x00) // zip file
s.read ((char *)&fileType, 1); // file type
if (fileType != 0x00) // zip file
{
LogPrint (eLogError, "Reseed: Can't handle file type ", (int)fileType);
return 0;
}
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);
@@ -688,7 +688,7 @@ namespace data
{
boost::asio::ip::tcp::endpoint ep = *it;
if ((ep.address ().is_v4 () && i2p::context.SupportsV4 ()) ||
(ep.address ().is_v6 () && i2p::context.SupportsV6 ()))
(ep.address ().is_v6 () && i2p::context.SupportsV6 ()))
{
s.lowest_layer().connect (ep, ecode);
if (!ecode)

View File

@@ -29,7 +29,7 @@ namespace i2p
RouterContext::RouterContext ():
m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false),
m_ShareRatio (100), m_Status (eRouterStatusUnknown), m_StatusV6 (eRouterStatusUnknown),
m_Error (eRouterErrorNone), m_ErrorV6 (eRouterErrorNone), m_NetID (I2PD_NET_ID)
m_Error (eRouterErrorNone), m_NetID (I2PD_NET_ID)
{
}
@@ -60,14 +60,18 @@ namespace i2p
i2p::data::LocalRouterInfo routerInfo;
routerInfo.SetRouterIdentity (GetIdentity ());
uint16_t port; i2p::config::GetOption("port", port);
if (!port) port = SelectRandomPort ();
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
bool ssu; i2p::config::GetOption("ssu", ssu);
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
bool nat; i2p::config::GetOption("nat", nat);
if (!port)
{
port = rand () % (30777 - 9111) + 9111; // I2P network ports range
if (port == 9150) port = 9151; // Tor browser
}
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
bool ssu; i2p::config::GetOption("ssu", ssu);
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
bool nat; i2p::config::GetOption("nat", nat);
if ((ntcp2 || ygg) && !m_NTCP2Keys)
NewNTCP2Keys ();
@@ -117,17 +121,13 @@ namespace i2p
if (ssu2)
{
if (ssu2Published)
{
uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port);
if (!ssu2Port) ssu2Port = ssu ? (port + 1) : port;
routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v4::from_string (host), ssu2Port);
}
routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v4::from_string (host), port);
else
{
{
addressCaps |= i2p::data::RouterInfo::AddressCaps::eV4;
routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro);
}
}
}
}
}
if (ipv6)
{
@@ -166,18 +166,14 @@ namespace i2p
if (ssu2)
{
if (ssu2Published)
{
uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port);
if (!ssu2Port) ssu2Port = ssu ? (port + 1) : port;
routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v6::from_string (host), ssu2Port);
}
routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address_v6::from_string (host), port);
else
{
{
if (!ipv4) // no other ssu2 addresses yet
routerInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro);
addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6;
}
}
}
}
}
if (ygg)
{
@@ -196,13 +192,6 @@ namespace i2p
m_RouterInfo.Update (routerInfo.GetBuffer (), routerInfo.GetBufferLen ());
}
uint16_t RouterContext::SelectRandomPort () const
{
uint16_t port = rand () % (30777 - 9111) + 9111; // I2P network ports range
if (port == 9150) port = 9151; // Tor browser
return port;
}
void RouterContext::UpdateRouterInfo ()
{
m_RouterInfo.CreateBuffer (m_Keys);
@@ -235,14 +224,7 @@ namespace i2p
std::ofstream fk (i2p::fs::DataDirPath (SSU2_KEYS), std::ofstream::binary | std::ofstream::out);
fk.write ((char *)m_SSU2Keys.get (), sizeof (SSU2PrivateKeys));
}
bool RouterContext::IsSSU2Only () const
{
auto transports = m_RouterInfo.GetCompatibleTransports (false);
return (transports & (i2p::data::RouterInfo::eSSU2V4 | i2p::data::RouterInfo::eSSU2V6)) &&
!(transports & (i2p::data::RouterInfo::eSSUV4 | i2p::data::RouterInfo::eSSUV6));
}
void RouterContext::SetStatus (RouterStatus status)
{
if (status != m_Status)
@@ -263,18 +245,11 @@ namespace i2p
}
}
void RouterContext::SetStatusSSU2 (RouterStatus status)
{
if (IsSSU2Only ())
SetStatus (status);
}
void RouterContext::SetStatusV6 (RouterStatus status)
{
if (status != m_StatusV6)
{
m_StatusV6 = status;
m_ErrorV6 = eRouterErrorNone;
switch (m_StatusV6)
{
case eRouterStatusOK:
@@ -289,18 +264,12 @@ namespace i2p
}
}
void RouterContext::SetStatusV6SSU2 (RouterStatus status)
{
if (IsSSU2Only ())
SetStatusV6 (status);
}
void RouterContext::UpdatePort (int port)
{
bool updated = false;
for (auto& address : m_RouterInfo.GetAddresses ())
{
if (address->port != port && (address->transportStyle == i2p::data::RouterInfo::eTransportSSU || IsSSU2Only ()))
if (!address->IsNTCP2 () && !address->IsSSU2 () && address->port != port)
{
address->port = port;
updated = true;
@@ -328,7 +297,12 @@ namespace i2p
}
if (isAddr)
{
if (!port && !address->port) port = SelectRandomPort ();
if (!port && !address->port)
{
// select random port only if address's port is not set
port = rand () % (30777 - 9111) + 9111; // I2P network ports range
if (port == 9150) port = 9151; // Tor browser
}
if (port) address->port = port;
address->published = publish;
memcpy (address->i, m_NTCP2Keys->iv, 16);
@@ -339,28 +313,23 @@ namespace i2p
if (updated)
UpdateRouterInfo ();
}
void RouterContext::UpdateNTCP2Address (bool enable)
{
auto& addresses = m_RouterInfo.GetAddresses ();
bool found = false, updated = false;
for (auto it = addresses.begin (); it != addresses.end ();)
for (auto it = addresses.begin (); it != addresses.end (); ++it)
{
if ((*it)->IsNTCP2 ())
{
found = true;
if (enable)
if (!enable)
{
(*it)->s = m_NTCP2Keys->staticPublicKey;
memcpy ((*it)->i, m_NTCP2Keys->iv, 16);
it++;
addresses.erase (it);
updated= true;
}
else
it = addresses.erase (it);
updated = true;
break;
}
else
it++;
}
if (enable && !found)
{
@@ -373,114 +342,81 @@ namespace i2p
void RouterContext::PublishSSU2Address (int port, bool publish, bool v4, bool v6)
{
if (!m_SSU2Keys) return;
int newPort = 0;
if (!port)
{
for (const auto& address : m_RouterInfo.GetAddresses ())
if (address->port)
{
newPort = address->port;
break;
}
if (!newPort) newPort = SelectRandomPort ();
}
if (!m_SSU2Keys || (publish && !port)) return;
bool updated = false;
for (auto& address : m_RouterInfo.GetAddresses ())
{
if (address->IsSSU2 () && (!address->port || address->port != port || address->published != publish) &&
if (address->IsSSU2 () && (address->port != port || address->published != publish) &&
((v4 && address->IsV4 ()) || (v6 && address->IsV6 ())))
{
if (port) address->port = port;
else if (!address->port) address->port = newPort;
address->port = port;
address->published = publish;
if (publish)
address->caps |= (i2p::data::RouterInfo::eSSUIntroducer | i2p::data::RouterInfo::eSSUTesting);
address->caps |= i2p::data::RouterInfo::eSSUIntroducer;
else
address->caps &= ~(i2p::data::RouterInfo::eSSUIntroducer | i2p::data::RouterInfo::eSSUTesting);
address->caps &= ~i2p::data::RouterInfo::eSSUIntroducer;
updated = true;
}
}
if (updated)
UpdateRouterInfo ();
}
}
void RouterContext::UpdateSSU2Address (bool enable)
{
auto& addresses = m_RouterInfo.GetAddresses ();
bool found = false, updated = false;
for (auto it = addresses.begin (); it != addresses.end ();)
for (auto it = addresses.begin (); it != addresses.end (); ++it)
{
if ((*it)->IsSSU2 ())
{
found = true;
if (enable)
if (!enable)
{
(*it)->s = m_SSU2Keys->staticPublicKey;
(*it)->i = m_SSU2Keys->intro;
it++;
addresses.erase (it);
updated= true;
}
else
it = addresses.erase (it);
updated = true;
break;
}
else
it++;
}
if (enable && !found)
{
uint8_t addressCaps = 0;
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
bool published; i2p::config::GetOption("ntcp2.published", published);
if (published)
{
if (ipv4) m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::AddressCaps::eV4);
if (ipv6) m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::AddressCaps::eV6);
}
else
{
uint8_t addressCaps = 0;
if (ipv4) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV4;
if (ipv6) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6;
m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addressCaps);
}
if (ipv4) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV4;
if (ipv6) addressCaps |= i2p::data::RouterInfo::AddressCaps::eV6;
m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, addressCaps);
updated = true;
}
if (updated)
UpdateRouterInfo ();
}
void RouterContext::UpdateAddress (const boost::asio::ip::address& host)
{
bool updated = false;
for (auto& address : m_RouterInfo.GetAddresses ())
{
if (address->host != host && address->IsCompatible (host) &&
!i2p::util::net::IsYggdrasilAddress (address->host))
!i2p::util::net::IsYggdrasilAddress (address->host))
{
// update host
address->host = host;
updated = true;
}
if (host.is_v6 () && address->IsV6 () && address->ssu &&
(!address->ssu->mtu || updated) && m_StatusV6 != eRouterStatusProxy)
{
// update MTU
auto mtu = i2p::util::net::GetMTU (host);
if (mtu)
if (host.is_v6 () && address->transportStyle == i2p::data::RouterInfo::eTransportSSU)
{
LogPrint (eLogDebug, "Router: Our v6 MTU=", mtu);
int maxMTU = i2p::util::net::GetMaxMTU (host.to_v6 ());
if (mtu > maxMTU)
// update MTU
auto mtu = i2p::util::net::GetMTU (host);
if (mtu)
{
mtu = maxMTU;
LogPrint(eLogWarning, "Router: MTU dropped to upper limit of ", maxMTU, " bytes");
LogPrint (eLogDebug, "Router: Our v6 MTU=", mtu);
if (mtu > 1472) { // TODO: magic constant
mtu = 1472;
LogPrint(eLogWarning, "Router: MTU dropped to upper limit of 1472 bytes");
}
if (address->ssu) address->ssu->mtu = mtu;
}
if (mtu && !address->IsSSU2 ()) // SSU1
mtu = (mtu >> 4) << 4; // round to multiple of 16
address->ssu->mtu = mtu;
updated = true;
}
updated = true;
}
}
auto ts = i2p::util::GetSecondsSinceEpoch ();
@@ -502,37 +438,6 @@ namespace i2p
UpdateRouterInfo ();
}
bool RouterContext::AddSSU2Introducer (const i2p::data::RouterInfo::Introducer& introducer, bool v4)
{
if (!IsSSU2Only ()) return false;
bool ret = m_RouterInfo.AddSSU2Introducer (introducer, v4);
if (ret)
UpdateRouterInfo ();
return ret;
}
void RouterContext::RemoveSSU2Introducer (const i2p::data::IdentHash& h, bool v4)
{
if (!IsSSU2Only ()) return;
if (m_RouterInfo.RemoveSSU2Introducer (h, v4))
UpdateRouterInfo ();
}
void RouterContext::ClearSSU2Introducers (bool v4)
{
bool updated = false;
auto& addresses = m_RouterInfo.GetAddresses ();
for (auto& addr : addresses)
if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())) &&
addr->ssu && !addr->ssu->introducers.empty ())
{
addr->ssu->introducers.clear ();
updated = true;
}
if (updated)
UpdateRouterInfo ();
}
void RouterContext::SetFloodfill (bool floodfill)
{
m_IsFloodfill = floodfill;
@@ -633,7 +538,6 @@ namespace i2p
void RouterContext::RemoveNTCPAddress (bool v4only)
{
bool updated = false;
auto& addresses = m_RouterInfo.GetAddresses ();
for (auto it = addresses.begin (); it != addresses.end ();)
{
@@ -641,38 +545,11 @@ namespace i2p
(!v4only || (*it)->host.is_v4 ()))
{
it = addresses.erase (it);
updated = true;
if (v4only) break; // otherwise might be more than one address
}
else
++it;
}
if (updated)
m_RouterInfo.UpdateSupportedTransports ();
}
void RouterContext::RemoveSSUAddress ()
{
bool updated = false;
auto& addresses = m_RouterInfo.GetAddresses ();
for (auto it = addresses.begin (); it != addresses.end ();)
{
if ((*it)->transportStyle == i2p::data::RouterInfo::eTransportSSU)
{
it = addresses.erase (it);
updated = true;
}
else
++it;
}
if (updated)
m_RouterInfo.UpdateSupportedTransports ();
}
void RouterContext::SetUnreachableSSU2 (bool v4, bool v6)
{
if (IsSSU2Only ())
SetUnreachable (v4, v6);
}
void RouterContext::SetUnreachable (bool v4, bool v6)
@@ -691,8 +568,7 @@ namespace i2p
// delete previous introducers
auto& addresses = m_RouterInfo.GetAddresses ();
for (auto& addr : addresses)
if (addr->ssu && (!addr->IsSSU2 () || IsSSU2Only ()) &&
((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
if (addr->ssu && !addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
{
addr->published = false;
addr->caps &= ~i2p::data::RouterInfo::eSSUIntroducer; // can't be introducer
@@ -722,19 +598,14 @@ namespace i2p
}
uint16_t port = 0;
// delete previous introducers
bool isSSU2Published = IsSSU2Only (); // TODO
if (isSSU2Published)
i2p::config::GetOption ("ssu2.published", isSSU2Published);
auto& addresses = m_RouterInfo.GetAddresses ();
for (auto& addr : addresses)
if (addr->ssu && (!addr->IsSSU2 () || isSSU2Published) &&
((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
if (addr->ssu && !addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (v6 && addr->IsV6 ())))
{
addr->published = true;
addr->caps |= i2p::data::RouterInfo::eSSUIntroducer;
addr->ssu->introducers.clear ();
if (addr->port && (!addr->IsSSU2 () || IsSSU2Only ()))
port = addr->port;
port = addr->port;
}
// publish NTCP2
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
@@ -772,26 +643,25 @@ namespace i2p
break;
case i2p::data::RouterInfo::eTransportNTCP:
foundNTCP2 = true;
break;
break;
case i2p::data::RouterInfo::eTransportSSU2:
foundSSU2 = true;
break;
break;
default: ;
}
}
}
port = addr->port;
}
if (!port)
{
i2p::config::GetOption("port", port);
if (!port) port = SelectRandomPort ();
}
if (!port) i2p::config::GetOption("port", port);
// SSU
bool ssu; i2p::config::GetOption("ssu", ssu);
if (!foundSSU && ssu)
if (!foundSSU)
{
std::string host = "::1"; // TODO: read host
m_RouterInfo.AddSSUAddress (host.c_str (), port, nullptr);
bool ssu; i2p::config::GetOption("ssu", ssu);
if (ssu)
{
std::string host = "::1"; // TODO: read host
m_RouterInfo.AddSSUAddress (host.c_str (), port, nullptr);
}
}
// NTCP2
if (!foundNTCP2)
@@ -820,18 +690,17 @@ namespace i2p
{
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
if (ssu2)
{
{
bool ssu2Published; i2p::config::GetOption("ssu2.published", ssu2Published);
if (ssu2Published)
{
uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port);
if (!ssu2Port) ssu2Port = ssu ? (port + 1) : port;
m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address::from_string ("::1"), ssu2Port);
}
}
else
m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::eV6);
}
}
}
}
m_RouterInfo.EnableV6 ();
}
else
@@ -862,25 +731,23 @@ namespace i2p
break;
case i2p::data::RouterInfo::eTransportNTCP:
foundNTCP2 = true;
break;
break;
case i2p::data::RouterInfo::eTransportSSU2:
foundSSU2 = true;
break;
break;
default: ;
}
}
}
if (addr->port) port = addr->port;
}
if (!port)
{
i2p::config::GetOption("port", port);
if (!port) port = SelectRandomPort ();
}
if (!port) i2p::config::GetOption("port", port);
// SSU
bool ssu; i2p::config::GetOption("ssu", ssu);
if (!foundSSU && ssu)
m_RouterInfo.AddSSUAddress (host.c_str (), port, nullptr);
if (!foundSSU)
{
bool ssu; i2p::config::GetOption("ssu", ssu);
if (ssu)
m_RouterInfo.AddSSUAddress (host.c_str (), port, nullptr);
}
// NTCP2
if (!foundNTCP2)
{
@@ -908,13 +775,12 @@ namespace i2p
if (ssu2Published)
{
uint16_t ssu2Port; i2p::config::GetOption ("ssu2.port", ssu2Port);
if (!ssu2Port) ssu2Port = ssu ? (port + 1) : port;
m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, boost::asio::ip::address::from_string ("127.0.0.1"), ssu2Port);
}
}
else
m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::eV4);
}
}
m_RouterInfo.AddSSU2Address (m_SSU2Keys->staticPublicKey, m_SSU2Keys->intro, i2p::data::RouterInfo::eV6);
}
}
m_RouterInfo.EnableV4 ();
}
else
@@ -949,43 +815,6 @@ namespace i2p
UpdateRouterInfo ();
}
void RouterContext::SetMTU (int mtu, bool v4)
{
if (mtu < 1280 || mtu > 1500) return;
auto& addresses = m_RouterInfo.GetAddresses ();
for (auto& addr: addresses)
{
if (addr->ssu && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
{
if (!addr->IsSSU2 ()) // SSU1
{
// round to multiple of 16
if (v4)
{
if (mtu > 1484) mtu = 1484;
else
{
mtu -= 12;
mtu = (mtu >> 4) << 4;
mtu += 12;
}
}
else
{
if (mtu > 1488) mtu = 1488;
else
mtu = (mtu >> 4) << 4;
}
}
if (mtu)
{
addr->ssu->mtu = mtu;
LogPrint (eLogDebug, "Router: MTU for ", v4 ? "ipv4" : "ipv6", " address ", addr->host.to_string(), " is set to ", mtu);
}
}
}
}
void RouterContext::UpdateNTCP2V6Address (const boost::asio::ip::address& host)
{
bool isYgg = i2p::util::net::IsYggdrasilAddress (host);
@@ -1054,7 +883,7 @@ namespace i2p
}
std::shared_ptr<const i2p::data::IdentityEx> oldIdentity;
if (m_Keys.GetPublic ()->GetSigningKeyType () == i2p::data::SIGNING_KEY_TYPE_DSA_SHA1 ||
m_Keys.GetPublic ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL)
m_Keys.GetPublic ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL)
{
// update keys
LogPrint (eLogInfo, "Router: router keys are obsolete. Creating new");
@@ -1106,7 +935,7 @@ namespace i2p
UpdateNTCP2Address (true); // enable NTCP2
}
else
UpdateNTCP2Address (false); // disable NTCP2
UpdateNTCP2Address (false); // disable NTCP2
// read SSU2
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
@@ -1131,7 +960,7 @@ namespace i2p
}
else
UpdateSSU2Address (false); // disable SSU2
return true;
}
@@ -1274,5 +1103,5 @@ namespace i2p
delete x;
}
return *m_SSU2StaticKeys;
}
}
}

View File

@@ -37,9 +37,10 @@ namespace garlic
eRouterStatusOK = 0,
eRouterStatusTesting = 1,
eRouterStatusFirewalled = 2,
eRouterStatusUnknown = 3,
eRouterStatusProxy = 4,
eRouterStatusMesh = 5
eRouterStatusError = 3,
eRouterStatusUnknown = 4,
eRouterStatusProxy = 5,
eRouterStatusMesh = 6
};
enum RouterError
@@ -67,7 +68,7 @@ namespace garlic
uint8_t staticPrivateKey[32];
uint8_t intro[32];
};
public:
RouterContext ();
@@ -85,7 +86,7 @@ namespace garlic
return std::shared_ptr<i2p::garlic::GarlicDestination> (this,
[](i2p::garlic::GarlicDestination *) {});
}
const uint8_t * GetNTCP2StaticPublicKey () const { return m_NTCP2Keys ? m_NTCP2Keys->staticPublicKey : nullptr; };
const uint8_t * GetNTCP2StaticPrivateKey () const { return m_NTCP2Keys ? m_NTCP2Keys->staticPrivateKey : nullptr; };
const uint8_t * GetNTCP2IV () const { return m_NTCP2Keys ? m_NTCP2Keys->iv : nullptr; };
@@ -95,21 +96,17 @@ namespace garlic
const uint8_t * GetSSU2StaticPrivateKey () const { return m_SSU2Keys ? m_SSU2Keys->staticPrivateKey : nullptr; };
const uint8_t * GetSSU2IntroKey () const { return m_SSU2Keys ? m_SSU2Keys->intro : nullptr; };
i2p::crypto::X25519Keys& GetSSU2StaticKeys ();
uint32_t GetUptime () const; // in seconds
uint64_t GetLastUpdateTime () const { return m_LastUpdateTime; };
uint64_t GetBandwidthLimit () const { return m_BandwidthLimit; };
uint64_t GetTransitBandwidthLimit () const { return (m_BandwidthLimit*m_ShareRatio)/100LL; };
RouterStatus GetStatus () const { return m_Status; };
void SetStatus (RouterStatus status);
void SetStatusSSU2 (RouterStatus status);
RouterError GetError () const { return m_Error; };
void SetError (RouterError error) { m_Error = error; };
void SetError (RouterError error) { m_Status = eRouterStatusError; m_Error = error; };
RouterStatus GetStatusV6 () const { return m_StatusV6; };
void SetStatusV6 (RouterStatus status);
void SetStatusV6SSU2 (RouterStatus status);
RouterError GetErrorV6 () const { return m_ErrorV6; };
void SetErrorV6 (RouterError error) { m_ErrorV6 = error; };
int GetNetID () const { return m_NetID; };
void SetNetID (int netID) { m_NetID = netID; };
bool DecryptTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data);
@@ -122,15 +119,10 @@ namespace garlic
void PublishSSU2Address (int port, bool publish, bool v4, bool v6);
void UpdateSSU2Address (bool enable);
void RemoveNTCPAddress (bool v4only = true); // delete NTCP address for older routers. TODO: remove later
void RemoveSSUAddress (); // delete SSU address for older routers
bool AddIntroducer (const i2p::data::RouterInfo::Introducer& introducer);
void RemoveIntroducer (const boost::asio::ip::udp::endpoint& e);
bool AddSSU2Introducer (const i2p::data::RouterInfo::Introducer& introducer, bool v4);
void RemoveSSU2Introducer (const i2p::data::IdentHash& h, bool v4);
void ClearSSU2Introducers (bool v4);
bool IsUnreachable () const;
void SetUnreachable (bool v4, bool v6);
void SetUnreachableSSU2 (bool v4, bool v6);
void SetReachable (bool v4, bool v6);
bool IsFloodfill () const { return m_IsFloodfill; };
void SetFloodfill (bool floodfill);
@@ -147,7 +139,6 @@ namespace garlic
void SetSupportsV6 (bool supportsV6);
void SetSupportsV4 (bool supportsV4);
void SetSupportsMesh (bool supportsmesh, const boost::asio::ip::address_v6& host);
void SetMTU (int mtu, bool v4);
i2p::crypto::NoiseSymmetricState& GetCurrentNoiseState () { return m_CurrentNoiseState; };
void UpdateNTCP2V6Address (const boost::asio::ip::address& host); // called from Daemon. TODO: remove
@@ -182,10 +173,8 @@ namespace garlic
void UpdateRouterInfo ();
void NewNTCP2Keys ();
void NewSSU2Keys ();
bool IsSSU2Only () const; // SSU2 and no SSU
bool Load ();
void SaveKeys ();
uint16_t SelectRandomPort () const;
bool DecryptECIESTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data, size_t clearTextSize);
@@ -201,7 +190,7 @@ namespace garlic
uint64_t m_BandwidthLimit; // allowed bandwidth
int m_ShareRatio;
RouterStatus m_Status, m_StatusV6;
RouterError m_Error, m_ErrorV6;
RouterError m_Error;
int m_NetID;
std::mutex m_GarlicMutex;
std::unique_ptr<NTCP2PrivateKeys> m_NTCP2Keys;

View File

@@ -33,16 +33,16 @@ namespace data
{
if (len > size ()) len = size ();
memcpy (data (), buf, len);
}
}
RouterInfo::RouterInfo (): m_Buffer (nullptr)
{
m_Addresses = boost::make_shared<Addresses>(); // create empty list
}
RouterInfo::RouterInfo (const std::string& fullPath):
m_FamilyID (0), m_IsUpdated (false), m_IsUnreachable (false),
m_SupportedTransports (0),m_ReachableTransports (0),
m_FamilyID (0), m_IsUpdated (false), m_IsUnreachable (false),
m_SupportedTransports (0),m_ReachableTransports (0),
m_Caps (0), m_Version (0)
{
m_Addresses = boost::make_shared<Addresses>(); // create empty list
@@ -51,8 +51,8 @@ namespace data
}
RouterInfo::RouterInfo (std::shared_ptr<Buffer>&& buf, size_t len):
m_FamilyID (0), m_IsUpdated (true), m_IsUnreachable (false),
m_SupportedTransports (0), m_ReachableTransports (0),
m_FamilyID (0), m_IsUpdated (true), m_IsUnreachable (false),
m_SupportedTransports (0), m_ReachableTransports (0),
m_Caps (0), m_Version (0)
{
if (len <= MAX_RI_BUFFER_SIZE)
@@ -68,12 +68,12 @@ namespace data
m_Buffer = nullptr;
m_IsUnreachable = true;
}
}
}
RouterInfo::RouterInfo (const uint8_t * buf, size_t len):
RouterInfo (std::make_shared<Buffer> (buf, len), len)
{
}
}
RouterInfo::~RouterInfo ()
{
@@ -160,7 +160,7 @@ namespace data
{
m_IsUnreachable = true;
return;
}
}
m_RouterIdentity = std::make_shared<IdentityEx>(m_Buffer->data (), m_BufferLen);
size_t identityLen = m_RouterIdentity->GetFullLen ();
if (identityLen >= m_BufferLen)
@@ -241,7 +241,7 @@ namespace data
// skip unknown address
s.seekg (size, std::ios_base::cur);
if (s) continue; else return;
}
}
while (r < size)
{
char key[255], value[255];
@@ -257,38 +257,20 @@ namespace data
if (!ecode && !address->host.is_unspecified ()) isHost = true;
}
else if (!strcmp (key, "port"))
{
try
{
address->port = boost::lexical_cast<int>(value);
}
catch (std::exception& ex)
{
LogPrint (eLogWarning, "RouterInfo: 'port' exception ", ex.what ());
}
}
address->port = boost::lexical_cast<int>(value);
else if (!strcmp (key, "mtu"))
{
if (address->ssu)
{
try
{
address->ssu->mtu = boost::lexical_cast<int>(value);
}
catch (std::exception& ex)
{
LogPrint (eLogWarning, "RouterInfo: 'mtu' exception ", ex.what ());
}
}
address->ssu->mtu = boost::lexical_cast<int>(value);
else
LogPrint (eLogWarning, "RouterInfo: Unexpected field 'mtu' for NTCP2");
LogPrint (eLogWarning, "RouterInfo: Unexpected field 'mtu' for NTCP");
}
else if (!strcmp (key, "key"))
{
if (address->ssu)
isIntroKey = (Base64ToByteStream (value, strlen (value), address->i, 32) == 32);
else
LogPrint (eLogWarning, "RouterInfo: Unexpected field 'key' for NTCP2");
LogPrint (eLogWarning, "RouterInfo: Unexpected field 'key' for NTCP");
}
else if (!strcmp (key, "caps"))
address->caps = ExtractAddressCaps (value);
@@ -306,7 +288,7 @@ namespace data
}
else if (address->IsSSU2 ())
Base64ToByteStream (value, strlen (value), address->i, 32);
else
else
Base64ToByteStream (value, strlen (value), iV2, 32);
}
else if (!strcmp (key, "v"))
@@ -315,7 +297,7 @@ namespace data
isV2 = true;
else
LogPrint (eLogWarning, "RouterInfo: Unexpected value ", value, " for v");
}
}
else if (key[0] == 'i')
{
// introducers
@@ -345,40 +327,13 @@ namespace data
introducer.iHost = boost::asio::ip::address::from_string (value, ecode);
}
else if (!strcmp (key, "iport"))
{
try
{
introducer.iPort = boost::lexical_cast<int>(value);
}
catch (std::exception& ex)
{
LogPrint (eLogWarning, "RouterInfo: 'iport' exception ", ex.what ());
}
}
introducer.iPort = boost::lexical_cast<int>(value);
else if (!strcmp (key, "itag"))
{
try
{
introducer.iTag = boost::lexical_cast<uint32_t>(value);
}
catch (std::exception& ex)
{
LogPrint (eLogWarning, "RouterInfo: 'itag' exception ", ex.what ());
}
}
introducer.iTag = boost::lexical_cast<uint32_t>(value);
else if (!strcmp (key, "ikey") || !strcmp (key, "ih"))
Base64ToByteStream (value, strlen (value), introducer.iKey, 32);
else if (!strcmp (key, "iexp"))
{
try
{
introducer.iExp = boost::lexical_cast<uint32_t>(value);
}
catch (std::exception& ex)
{
LogPrint (eLogWarning, "RouterInfo: 'iexp' exception ", ex.what ());
}
}
introducer.iExp = boost::lexical_cast<uint32_t>(value);
}
if (!s) return;
}
@@ -389,7 +344,7 @@ namespace data
if (isHost)
{
if (address->host.is_v6 ())
supportedTransports |= (i2p::util::net::IsYggdrasilAddress (address->host) ? eNTCP2V6Mesh : eNTCP2V6);
supportedTransports |= (i2p::util::net::IsYggdrasilAddress (address->host) ? eNTCP2V6Mesh : eNTCP2V6);
else
supportedTransports |= eNTCP2V4;
m_ReachableTransports |= supportedTransports;
@@ -411,7 +366,7 @@ namespace data
if (isIntroKey)
{
if (isHost)
supportedTransports |= address->host.is_v4 () ? eSSUV4 : eSSUV6;
supportedTransports |= address->host.is_v4 () ? eSSUV4 : eSSUV6;
else if (address->caps & AddressCaps::eV6)
{
supportedTransports |= eSSUV6;
@@ -428,13 +383,10 @@ namespace data
{
if (!it.iExp) it.iExp = m_Timestamp/1000 + NETDB_INTRODUCEE_EXPIRATION_TIMEOUT;
if (ts <= it.iExp && it.iPort > 0 &&
((it.iHost.is_v4 () && address->IsV4 ()) || (it.iHost.is_v6 () && address->IsV6 ())))
((it.iHost.is_v4 () && address->IsV4 ()) || (it.iHost.is_v6 () && address->IsV6 ())))
numValid++;
else
{
it.iPort = 0;
if (isV2) numValid++;
}
}
if (numValid)
m_ReachableTransports |= supportedTransports;
@@ -456,54 +408,29 @@ namespace data
{
if (address->host.is_v4 ()) m_ReachableTransports |= eSSU2V4;
if (address->host.is_v6 ()) m_ReachableTransports |= eSSU2V6;
}
if (address->transportStyle == eTransportSSU2)
{
if (address->port) address->published = true;
if (address->ssu && !address->ssu->introducers.empty ())
{
// exclude invalid introducers
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
int numValid = 0;
for (auto& it: address->ssu->introducers)
{
if (it.iTag && ts <= it.iExp)
numValid++;
else
it.iTag = 0;
}
if (numValid)
m_ReachableTransports |= supportedTransports;
else
address->ssu->introducers.resize (0);
}
}
else
{
// create additional SSU2 address. TODO: remove later
auto ssu2addr = std::make_shared<Address> ();
ssu2addr->transportStyle = eTransportSSU2;
ssu2addr->host = address->host; ssu2addr->port = address->port;
ssu2addr->s = address->s; ssu2addr->i = iV2;
ssu2addr->date = address->date; ssu2addr->caps = address->caps;
ssu2addr->published = address->published;
ssu2addr->ssu.reset (new SSUExt ()); ssu2addr->ssu->mtu = address->ssu->mtu;
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
if (!address->ssu->introducers.empty ())
{
for (const auto& introducer: address->ssu->introducers)
if (!introducer.iPort && introducer.iHost.is_unspecified () && ts < introducer.iExp) // SSU2
ssu2addr->ssu->introducers.push_back (introducer);
if (!ssu2addr->ssu->introducers.empty ())
m_ReachableTransports |= supportedTransports;
}
addresses->push_back(ssu2addr);
}
}
if (supportedTransports)
}
}
if (supportedTransports)
{
if (!(m_SupportedTransports & supportedTransports)) // avoid duplicates
{
addresses->push_back(address);
if (address->transportStyle == eTransportSSU && isV2)
{
// create additional SSU2 address. TODO: remove later
auto ssu2addr = std::make_shared<Address> ();
ssu2addr->transportStyle = eTransportSSU2;
ssu2addr->host = address->host; ssu2addr->port = address->port;
ssu2addr->s = address->s; ssu2addr->i = iV2;
ssu2addr->date = address->date; ssu2addr->caps = address->caps;
ssu2addr->published = address->published;
ssu2addr->ssu.reset (new SSUExt ()); ssu2addr->ssu->mtu = address->ssu->mtu;
for (const auto& introducer: address->ssu->introducers)
if (!introducer.iPort) // SSU2
ssu2addr->ssu->introducers.push_back (introducer);
addresses->push_back(ssu2addr);
}
}
m_SupportedTransports |= supportedTransports;
}
}
@@ -556,10 +483,10 @@ namespace data
{
isNetId = true;
if (atoi (value) != i2p::context.GetNetID ())
{
{
LogPrint (eLogError, "RouterInfo: Unexpected ", ROUTER_INFO_PROPERTY_NETID, "=", value);
m_IsUnreachable = true;
}
}
}
// family
else if (!strcmp (key, ROUTER_INFO_PROPERTY_FAMILY))
@@ -571,7 +498,7 @@ namespace data
{
if (netdb.GetFamilies ().VerifyFamily (family, GetIdentHash (), value))
m_FamilyID = netdb.GetFamilies ().GetFamilyID (family);
else
else
LogPrint (eLogWarning, "RouterInfo: Family ", family, " signature verification failed");
}
@@ -753,7 +680,6 @@ namespace data
{
auto addr = std::make_shared<Address>();
addr->transportStyle = eTransportSSU2;
addr->port = 0;
addr->caps = caps;
addr->date = 0;
addr->ssu.reset (new SSUExt ());
@@ -763,7 +689,7 @@ namespace data
if (addr->IsV4 ()) m_SupportedTransports |= eSSU2V4;
if (addr->IsV6 ()) m_SupportedTransports |= eSSU2V6;
m_Addresses->push_back(std::move(addr));
}
}
void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey,
const boost::asio::ip::address& host, int port)
@@ -773,31 +699,31 @@ namespace data
addr->host = host;
addr->port = port;
addr->published = true;
addr->caps = i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer; // BC;
addr->caps = 0;
addr->date = 0;
addr->ssu.reset (new SSUExt ());
addr->ssu->mtu = 0;
memcpy (addr->s, staticKey, 32);
memcpy (addr->i, introKey, 32);
if (addr->IsV4 ())
{
{
m_SupportedTransports |= eSSU2V4;
m_ReachableTransports |= eSSU2V4;
}
}
if (addr->IsV6 ())
{
{
m_SupportedTransports |= eSSU2V6;
m_ReachableTransports |= eSSU2V6;
}
}
m_Addresses->push_back(std::move(addr));
}
}
bool RouterInfo::AddIntroducer (const Introducer& introducer)
{
for (auto& addr : *m_Addresses)
{
if (addr->transportStyle == eTransportSSU &&
((addr->IsV4 () && introducer.iHost.is_v4 ()) || (addr->IsV6 () && introducer.iHost.is_v6 ())))
((addr->IsV4 () && introducer.iHost.is_v4 ()) || (addr->IsV6 () && introducer.iHost.is_v6 ())))
{
for (auto& intro: addr->ssu->introducers)
if (intro.iTag == introducer.iTag) return false; // already presented
@@ -814,7 +740,7 @@ namespace data
for (auto& addr: *m_Addresses)
{
if (addr->transportStyle == eTransportSSU &&
((addr->IsV4 () && e.address ().is_v4 ()) || (addr->IsV6 () && e.address ().is_v6 ())))
((addr->IsV4 () && e.address ().is_v4 ()) || (addr->IsV6 () && e.address ().is_v6 ())))
{
for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it)
if (boost::asio::ip::udp::endpoint (it->iHost, it->iPort) == e)
@@ -968,8 +894,8 @@ namespace data
{
return (address->transportStyle == eTransportSSU2) && address->IsV4();
});
}
}
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2V6Address () const
{
return GetAddress (
@@ -977,23 +903,8 @@ namespace data
{
return (address->transportStyle == eTransportSSU2) && address->IsV6();
});
}
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2Address (bool v4) const
{
if (v4)
{
if (m_SupportedTransports & eSSU2V4)
return GetSSU2V4Address ();
}
else
{
if (m_SupportedTransports & eSSU2V6)
return GetSSU2V6Address ();
}
return nullptr;
}
}
template<typename Filter>
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetAddress (Filter filter) const
{
@@ -1025,11 +936,10 @@ namespace data
return GetAddress (
[key, isV6](std::shared_ptr<const RouterInfo::Address> address)->bool
{
return address->IsSSU2 () && !memcmp (address->s, key, 32) &&
((isV6 && address->IsV6 ()) || (!isV6 && address->IsV4 ()));
return address->IsSSU2 () && !memcmp (address->s, key, 32) && address->IsV6 () == isV6;
});
}
std::shared_ptr<const RouterInfo::Address> RouterInfo::GetPublishedNTCP2V4Address () const
{
return GetAddress (
@@ -1090,17 +1000,6 @@ namespace data
});
}
bool RouterInfo::IsSSU2PeerTesting (bool v4) const
{
if (!(m_SupportedTransports & (v4 ? eSSU2V4 : eSSU2V6))) return false;
return (bool)GetAddress (
[v4](std::shared_ptr<const RouterInfo::Address> address)->bool
{
return (address->IsSSU2 ()) && address->IsPeerTesting () &&
((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && address->IsReachableSSU ();
});
}
bool RouterInfo::IsIntroducer (bool v4) const
{
if (!(m_SupportedTransports & (v4 ? eSSUV4 : eSSUV6))) return false;
@@ -1112,17 +1011,6 @@ namespace data
});
}
bool RouterInfo::IsSSU2Introducer (bool v4) const
{
if (!(m_SupportedTransports & (v4 ? eSSU2V4 : eSSU2V6))) return false;
return (bool)GetAddress (
[v4](std::shared_ptr<const RouterInfo::Address> address)->bool
{
return (address->IsSSU2 ()) && address->IsIntroducer () &&
((v4 && address->IsV4 ()) || (!v4 && address->IsV6 ())) && !address->host.is_unspecified ();
});
}
void RouterInfo::SetUnreachableAddressesTransportCaps (uint8_t transports)
{
for (auto& addr: *m_Addresses)
@@ -1143,28 +1031,20 @@ namespace data
for (const auto& addr: *m_Addresses)
{
uint8_t transports = 0;
switch (addr->transportStyle)
if (addr->transportStyle == eTransportNTCP)
{
case eTransportNTCP:
if (addr->IsV4 ()) transports |= eNTCP2V4;
if (addr->IsV6 ())
transports |= (i2p::util::net::IsYggdrasilAddress (addr->host) ? eNTCP2V6Mesh : eNTCP2V6);
if (addr->IsPublishedNTCP2 ())
m_ReachableTransports |= transports;
break;
case eTransportSSU:
if (addr->IsV4 ()) transports |= eSSUV4;
if (addr->IsV6 ()) transports |= eSSUV6;
if (addr->IsReachableSSU ())
m_ReachableTransports |= transports;
break;
case eTransportSSU2:
if (addr->IsV4 ()) transports |= eSSU2V4;
if (addr->IsV6 ()) transports |= eSSU2V6;
if (addr->IsReachableSSU ())
m_ReachableTransports |= transports;
break;
default: ;
if (addr->IsV4 ()) transports |= eNTCP2V4;
if (addr->IsV6 ())
transports |= (i2p::util::net::IsYggdrasilAddress (addr->host) ? eNTCP2V6Mesh : eNTCP2V6);
if (addr->IsPublishedNTCP2 ())
m_ReachableTransports |= transports;
}
else if (addr->transportStyle == eTransportSSU)
{
if (addr->IsV4 ()) transports |= eSSUV4;
if (addr->IsV6 ()) transports |= eSSUV6;
if (addr->IsReachableSSU ())
m_ReachableTransports |= transports;
}
m_SupportedTransports |= transports;
}
@@ -1177,17 +1057,17 @@ namespace data
if (len > m_Buffer->size ()) len = m_Buffer->size ();
memcpy (m_Buffer->data (), buf, len);
m_BufferLen = len;
}
}
std::shared_ptr<RouterInfo::Buffer> RouterInfo::NewBuffer () const
{
return netdb.NewRouterInfoBuffer ();
}
}
void RouterInfo::RefreshTimestamp ()
{
m_Timestamp = i2p::util::GetMillisecondsSinceEpoch ();
}
m_Timestamp = i2p::util::GetMillisecondsSinceEpoch ();
}
void LocalRouterInfo::CreateBuffer (const PrivateKeys& privateKeys)
{
@@ -1208,13 +1088,13 @@ namespace data
}
else
LogPrint (eLogError, "RouterInfo: Our RouterInfo is too long ", len + signatureLen);
}
}
void LocalRouterInfo::UpdateCaps (uint8_t caps)
{
SetCaps (caps);
UpdateCapsProperty ();
}
}
void LocalRouterInfo::UpdateCapsProperty ()
{
@@ -1273,7 +1153,7 @@ namespace data
{
WriteString ("NTCP2", s);
if (address.IsPublishedNTCP2 () && !address.host.is_unspecified () && address.port)
isPublished = true;
isPublished = true;
else
{
WriteString ("caps", properties);
@@ -1332,13 +1212,12 @@ namespace data
// caps
std::string caps;
if (address.published)
{
{
isPublished = true;
if (address.IsPeerTesting ()) caps += CAPS_FLAG_SSU_TESTING;
if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU_INTRODUCER;
}
}
else
{
{
if (address.IsV4 ()) caps += CAPS_FLAG_V4;
if (address.IsV6 ()) caps += CAPS_FLAG_V6;
if (caps.empty ()) caps += CAPS_FLAG_V4;
@@ -1349,12 +1228,12 @@ namespace data
properties << '=';
WriteString (caps, properties);
properties << ';';
}
}
}
}
else
WriteString ("", s);
if (isPublished && !address.host.is_unspecified ())
if (isPublished)
{
WriteString ("host", properties);
properties << '=';
@@ -1386,7 +1265,7 @@ namespace data
i++;
}
if (address.transportStyle == eTransportSSU)
{
{
i = 0;
for (const auto& introducer: address.ssu->introducers)
{
@@ -1396,13 +1275,13 @@ namespace data
properties << ';';
i++;
}
}
}
i = 0;
for (const auto& introducer: address.ssu->introducers)
{
if (address.IsSSU2 ())
WriteString ("ih" + boost::lexical_cast<std::string>(i), properties);
else
else
WriteString ("ikey" + boost::lexical_cast<std::string>(i), properties);
properties << '=';
char value[64];
@@ -1423,7 +1302,7 @@ namespace data
properties << ';';
i++;
}
}
}
i = 0;
for (const auto& introducer: address.ssu->introducers)
{
@@ -1447,7 +1326,7 @@ namespace data
properties << ';';
}
if (address.transportStyle == eTransportSSU || address.IsSSU2 ())
{
{
// write mtu
if (address.ssu && address.ssu->mtu)
{
@@ -1457,7 +1336,7 @@ namespace data
properties << ';';
}
}
if ((isPublished || (address.ssu && !address.IsSSU2 ())) && address.port)
if (isPublished || (address.ssu && !address.IsSSU2 ()))
{
WriteString ("port", properties);
properties << '=';
@@ -1494,7 +1373,7 @@ namespace data
uint16_t size = htobe16 (properties.str ().size ());
s.write ((char *)&size, sizeof (size));
s.write (properties.str ().c_str (), properties.str ().size ());
}
}
void LocalRouterInfo::SetProperty (const std::string& key, const std::string& value)
{
@@ -1512,53 +1391,18 @@ namespace data
if (it != m_Properties.end ())
return it->second;
return "";
}
}
void LocalRouterInfo::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);
}
}
std::shared_ptr<RouterInfo::Buffer> LocalRouterInfo::NewBuffer () const
{
return std::make_shared<Buffer> ();
}
bool LocalRouterInfo::AddSSU2Introducer (const Introducer& introducer, bool v4)
{
for (auto& addr : GetAddresses ())
{
if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
{
for (auto& intro: addr->ssu->introducers)
if (intro.iTag == introducer.iTag) return false; // already presented
addr->ssu->introducers.push_back (introducer);
SetReachableTransports (GetReachableTransports () | ((addr->IsV4 () ? eSSU2V4 : eSSU2V6)));
return true;
}
}
return false;
}
bool LocalRouterInfo::RemoveSSU2Introducer (const IdentHash& h, bool v4)
{
for (auto& addr: GetAddresses ())
{
if (addr->IsSSU2 () && ((v4 && addr->IsV4 ()) || (!v4 && addr->IsV6 ())))
{
for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it)
if (h == it->iKey)
{
addr->ssu->introducers.erase (it);
if (addr->ssu->introducers.empty ())
SetReachableTransports (GetReachableTransports () & ~(addr->IsV4 () ? eSSU2V4 : eSSU2V6));
return true;
}
}
}
return false;
}
}
}
}

View File

@@ -56,7 +56,7 @@ namespace data
const uint8_t COST_SSU_DIRECT = 9;
const uint8_t COST_SSU_THROUGH_INTRODUCERS = 11;
const uint8_t COST_SSU2_NON_PUBLISHED = 15;
const size_t MAX_RI_BUFFER_SIZE = 3072; // if RouterInfo exceeds 3K we consider it as malformed, might extend later
class RouterInfo: public RoutingDestination
{
@@ -146,11 +146,11 @@ namespace data
return !(*this == other);
}
bool IsNTCP2 () const { return transportStyle == eTransportNTCP; };
bool IsSSU2 () const { return transportStyle == eTransportSSU2; };
bool IsNTCP2 () const { return transportStyle == eTransportNTCP; };
bool IsSSU2 () const { return transportStyle == eTransportSSU2; };
bool IsPublishedNTCP2 () const { return IsNTCP2 () && published; };
bool IsReachableSSU () const { return (bool)ssu && (published || UsesIntroducer ()); };
bool UsesIntroducer () const { return (bool)ssu && !ssu->introducers.empty (); };
bool UsesIntroducer () const { return (bool)ssu && !ssu->introducers.empty (); };
bool IsIntroducer () const { return caps & eSSUIntroducer; };
bool IsPeerTesting () const { return caps & eSSUTesting; };
@@ -166,7 +166,7 @@ namespace data
Buffer () = default;
Buffer (const uint8_t * buf, size_t len);
};
typedef std::vector<std::shared_ptr<Address> > Addresses;
RouterInfo (const std::string& fullPath);
@@ -181,7 +181,7 @@ namespace data
std::string GetIdentHashBase64 () const { return GetIdentHash ().ToBase64 (); };
uint64_t GetTimestamp () const { return m_Timestamp; };
int GetVersion () const { return m_Version; };
virtual void SetProperty (const std::string& key, const std::string& value) {};
virtual void SetProperty (const std::string& key, const std::string& value) {};
virtual void ClearProperties () {};
Addresses& GetAddresses () { return *m_Addresses; }; // should be called for local RI only, otherwise must return shared_ptr
std::shared_ptr<const Address> GetNTCP2AddressWithStaticKey (const uint8_t * key) const;
@@ -193,7 +193,6 @@ namespace data
std::shared_ptr<const Address> GetYggdrasilAddress () const;
std::shared_ptr<const Address> GetSSU2V4Address () const;
std::shared_ptr<const Address> GetSSU2V6Address () const;
std::shared_ptr<const Address> GetSSU2Address (bool v4) const;
void AddSSUAddress (const char * host, int port, const uint8_t * key, int mtu = 0);
void AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv,
@@ -233,9 +232,7 @@ namespace data
bool IsExtraBandwidth () const { return m_Caps & RouterInfo::eExtraBandwidth; };
bool IsEligibleFloodfill () const;
bool IsPeerTesting (bool v4) const;
bool IsSSU2PeerTesting (bool v4) const;
bool IsIntroducer (bool v4) const;
bool IsSSU2Introducer (bool v4) const;
uint8_t GetCaps () const { return m_Caps; };
void SetCaps (uint8_t caps) { m_Caps = caps; };
@@ -275,9 +272,7 @@ namespace data
void SetBufferLen (size_t len) { m_BufferLen = len; };
void RefreshTimestamp ();
const Addresses& GetAddresses () const { return *m_Addresses; };
CompatibleTransports GetReachableTransports () const { return m_ReachableTransports; };
void SetReachableTransports (CompatibleTransports transports) { m_ReachableTransports = transports; };
private:
bool LoadFile (const std::string& fullPath);
@@ -290,7 +285,7 @@ namespace data
template<typename Filter>
std::shared_ptr<const Address> GetAddress (Filter filter) const;
virtual std::shared_ptr<Buffer> NewBuffer () const;
private:
FamilyID m_FamilyID;
@@ -314,25 +309,22 @@ namespace data
void CreateBuffer (const PrivateKeys& privateKeys);
void UpdateCaps (uint8_t caps);
void SetProperty (const std::string& key, const std::string& value) override;
void DeleteProperty (const std::string& key);
std::string GetProperty (const std::string& key) const;
void SetProperty (const std::string& key, const std::string& value) override;
void DeleteProperty (const std::string& key);
std::string GetProperty (const std::string& key) const;
void ClearProperties () override { m_Properties.clear (); };
bool AddSSU2Introducer (const Introducer& introducer, bool v4);
bool RemoveSSU2Introducer (const IdentHash& h, bool v4);
private:
void WriteToStream (std::ostream& s) const;
void UpdateCapsProperty ();
void WriteString (const std::string& str, std::ostream& s) const;
std::shared_ptr<Buffer> NewBuffer () const override;
private:
std::map<std::string, std::string> m_Properties;
};
std::map<std::string, std::string> m_Properties;
};
}
}

View File

@@ -273,14 +273,14 @@ namespace transport
void SSUServer::HandleReceivedFrom (const boost::system::error_code& ecode, std::size_t bytes_transferred, SSUPacket * packet)
{
if (!ecode
|| ecode == boost::asio::error::connection_refused
|| ecode == boost::asio::error::connection_reset
|| ecode == boost::asio::error::network_unreachable
|| ecode == boost::asio::error::host_unreachable
|| ecode == boost::asio::error::connection_refused
|| ecode == boost::asio::error::connection_reset
|| ecode == boost::asio::error::network_unreachable
|| ecode == boost::asio::error::host_unreachable
#ifdef _WIN32 // windows can throw WinAPI error, which is not handled by ASIO
|| ecode.value() == boost::winapi::ERROR_CONNECTION_REFUSED_
|| ecode.value() == boost::winapi::ERROR_NETWORK_UNREACHABLE_
|| ecode.value() == boost::winapi::ERROR_HOST_UNREACHABLE_
|| ecode.value() == boost::winapi::ERROR_CONNECTION_REFUSED_
|| ecode.value() == boost::winapi::ERROR_NETWORK_UNREACHABLE_
|| ecode.value() == boost::winapi::ERROR_HOST_UNREACHABLE_
#endif
)
// just try continue reading when received ICMP response otherwise socket can crash,
@@ -332,14 +332,14 @@ namespace transport
void SSUServer::HandleReceivedFromV6 (const boost::system::error_code& ecode, std::size_t bytes_transferred, SSUPacket * packet)
{
if (!ecode
|| ecode == boost::asio::error::connection_refused
|| ecode == boost::asio::error::connection_reset
|| ecode == boost::asio::error::network_unreachable
|| ecode == boost::asio::error::host_unreachable
|| ecode == boost::asio::error::connection_refused
|| ecode == boost::asio::error::connection_reset
|| ecode == boost::asio::error::network_unreachable
|| ecode == boost::asio::error::host_unreachable
#ifdef _WIN32 // windows can throw WinAPI error, which is not handled by ASIO
|| ecode.value() == boost::winapi::ERROR_CONNECTION_REFUSED_
|| ecode.value() == boost::winapi::ERROR_NETWORK_UNREACHABLE_
|| ecode.value() == boost::winapi::ERROR_HOST_UNREACHABLE_
|| ecode.value() == boost::winapi::ERROR_CONNECTION_REFUSED_
|| ecode.value() == boost::winapi::ERROR_NETWORK_UNREACHABLE_
|| ecode.value() == boost::winapi::ERROR_HOST_UNREACHABLE_
#endif
)
// just try continue reading when received ICMP response otherwise socket can crash,
@@ -582,7 +582,7 @@ namespace transport
"] through introducer ", introducer->iHost, ":", introducer->iPort);
session->WaitForIntroduction ();
if ((address->host.is_v4 () && i2p::context.GetStatus () == eRouterStatusFirewalled) ||
(address->host.is_v6 () && i2p::context.GetStatusV6 () == eRouterStatusFirewalled))
(address->host.is_v6 () && i2p::context.GetStatusV6 () == eRouterStatusFirewalled))
{
uint8_t buf[1];
Send (buf, 0, remoteEndpoint); // send HolePunch
@@ -676,7 +676,7 @@ namespace transport
for (const auto& s : sessions)
{
if (s.second->GetRelayTag () && s.second->GetState () == eSessionStateEstablished &&
ts < s.second->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_EXPIRATION)
ts < s.second->GetCreationTime () + SSU_TO_INTRODUCER_SESSION_EXPIRATION)
ret.push_back (s.second);
else if (s.second->GetRemoteIdentity ())
excluded.insert (s.second->GetRemoteIdentity ()->GetIdentHash ());

File diff suppressed because it is too large Load Diff

View File

@@ -9,35 +9,237 @@
#ifndef SSU2_H__
#define SSU2_H__
#include <memory>
#include <functional>
#include <map>
#include <set>
#include <unordered_map>
#include "util.h"
#include "SSU2Session.h"
#include <boost/asio.hpp>
#include "Crypto.h"
#include "RouterInfo.h"
#include "TransportSession.h"
namespace i2p
{
namespace transport
{
const int SSU2_TERMINATION_CHECK_TIMEOUT = 30; // in seconds
const int SSU2_RESEND_CHECK_TIMEOUT = 400; // in milliseconds
const int SSU2_RESEND_CHECK_TIMEOUT_VARIANCE = 100; // in milliseconds
const int SSU2_RESEND_CHECK_MORE_TIMEOUT = 10; // in milliseconds
const size_t SSU2_MAX_RESEND_PACKETS = 128; // packets to resend at the time
const int SSU2_CONNECT_TIMEOUT = 5; // 5 seconds
const int SSU2_TERMINATION_TIMEOUT = 330; // 5.5 minutes
const int SSU2_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds
const int SSU2_TOKEN_EXPIRATION_TIMEOUT = 9; // in seconds
const int SSU2_RELAY_NONCE_EXPIRATION_TIMEOUT = 10; // in seconds
const size_t SSU2_SOCKET_RECEIVE_BUFFER_SIZE = 0x1FFFF; // 128K
const size_t SSU2_SOCKET_SEND_BUFFER_SIZE = 0x1FFFF; // 128K
const size_t SSU2_MAX_NUM_INTRODUCERS = 3;
const int SSU2_TO_INTRODUCER_SESSION_DURATION = 3600; // 1 hour
const int SSU2_TO_INTRODUCER_SESSION_EXPIRATION = 4800; // 80 minutes
const int SSU2_KEEP_ALIVE_INTERVAL = 30; // in seconds
const int SSU2_PROXY_CONNECT_RETRY_TIMEOUT = 30; // in seconds
const size_t SSU2_MTU = 1488;
const size_t SSU2_MAX_PAYLOAD_SIZE = SSU2_MTU - 32;
const int SSU2_RESEND_INTERVAL = 3; // in seconds
const int SSU2_MAX_NUM_RESENDS = 5;
const int SSU2_INCOMPLETE_MESSAGES_CLEANUP_TIMEOUT = 30; // in seconds
const size_t SSU2_MAX_WINDOW_SIZE = 128; // in packets
class SSU2Server: private i2p::util::RunnableServiceWithWork
enum SSU2MessageType
{
eSSU2SessionRequest = 0,
eSSU2SessionCreated = 1,
eSSU2SessionConfirmed = 2,
eSSU2Data = 6,
eSSU2Retry = 9,
eSSU2TokenRequest = 10
};
enum SSU2BlockType
{
eSSU2BlkDateTime = 0,
eSSU2BlkOptions, // 1
eSSU2BlkRouterInfo, // 2
eSSU2BlkI2NPMessage, // 3
eSSU2BlkFirstFragment, // 4
eSSU2BlkFollowOnFragment, // 5
eSSU2BlkTermination, // 6
eSSU2BlkRelayRequest, // 7
eSSU2BlkRelayResponse, // 8
eSSU2BlkRelayIntro, // 9
eSSU2BlkPeerTest, // 10
eSSU2BlkNextNonce, // 11
eSSU2BlkAck, // 12
eSSU2BlkAddress, // 13
eSSU2BlkIntroKey, // 14
eSSU2BlkRelayTagRequest, // 15
eSSU2BlkRelayTag, // 16
eSSU2BlkNewToken, // 17
eSSU2BlkPathChallenge, // 18
eSSU2BlkPathResponse, // 19
eSSU2BlkFirstPacketNumber, // 20
eSSU2BlkPadding = 254
};
enum SSU2SessionState
{
eSSU2SessionStateUnknown,
eSSU2SessionStateIntroduced,
eSSU2SessionStateEstablished,
eSSU2SessionStateTerminated,
eSSU2SessionStateFailed
};
struct SSU2IncompleteMessage
{
struct Fragment
{
uint8_t buf[SSU2_MTU];
size_t len;
bool isLast;
};
std::shared_ptr<I2NPMessage> msg;
int nextFragmentNum;
uint32_t lastFragmentInsertTime; // in seconds
std::map<int, std::shared_ptr<Fragment> > outOfSequenceFragments;
};
// RouterInfo flags
const uint8_t SSU2_ROUTER_INFO_FLAG_REQUEST_FLOOD = 0x01;
const uint8_t SSU2_ROUTER_INFO_FLAG_GZIP = 0x02;
class SSU2Server;
class SSU2Session: public TransportSession, public std::enable_shared_from_this<SSU2Session>
{
union Header
{
uint64_t ll[2];
uint8_t buf[16];
struct
{
uint64_t connID;
uint32_t packetNum;
uint8_t type;
uint8_t flags[3];
} h;
};
struct SentPacket
{
uint8_t payload[SSU2_MAX_PAYLOAD_SIZE];
size_t payloadSize = 0;
uint32_t nextResendTime; // in seconds
int numResends = 0;
};
struct SessionConfirmedFragment
{
Header header;
uint8_t payload[SSU2_MAX_PAYLOAD_SIZE];
size_t payloadSize;
};
typedef std::function<void ()> OnEstablished;
public:
SSU2Session (SSU2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter = nullptr,
std::shared_ptr<const i2p::data::RouterInfo::Address> addr = nullptr);
~SSU2Session ();
void SetRemoteEndpoint (const boost::asio::ip::udp::endpoint& ep) { m_RemoteEndpoint = ep; };
const boost::asio::ip::udp::endpoint& GetRemoteEndpoint () const { return m_RemoteEndpoint; };
void SetOnEstablished (OnEstablished e) { m_OnEstablished = e; };
void Connect ();
bool Introduce (std::shared_ptr<SSU2Session> session, uint32_t relayTag);
void Terminate ();
void TerminateByTimeout ();
void CleanUp (uint64_t ts);
void FlushData ();
void Done () override;
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) override;
void Resend (uint64_t ts);
bool IsEstablished () const { return m_State == eSSU2SessionStateEstablished; };
uint64_t GetConnID () const { return m_SourceConnID; };
SSU2SessionState GetState () const { return m_State; };
void SetState (SSU2SessionState state) { m_State = state; };
bool ProcessFirstIncomingMessage (uint64_t connID, uint8_t * buf, size_t len);
bool ProcessSessionCreated (uint8_t * buf, size_t len);
bool ProcessSessionConfirmed (uint8_t * buf, size_t len);
bool ProcessRetry (uint8_t * buf, size_t len);
void ProcessData (uint8_t * buf, size_t len);
private:
void Established ();
void PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs);
bool SendQueue ();
void SendFragmentedMessage (std::shared_ptr<I2NPMessage> msg);
void ProcessSessionRequest (Header& header, uint8_t * buf, size_t len);
void ProcessTokenRequest (Header& header, uint8_t * buf, size_t len);
void SendSessionRequest (uint64_t token = 0);
void SendSessionCreated (const uint8_t * X);
void SendSessionConfirmed (const uint8_t * Y);
void KDFDataPhase (uint8_t * keydata_ab, uint8_t * keydata_ba);
void SendTokenRequest ();
void SendRetry ();
uint32_t SendData (const uint8_t * buf, size_t len); // returns packet num
void SendQuickAck ();
void SendTermination ();
void HandlePayload (const uint8_t * buf, size_t len);
void HandleAck (const uint8_t * buf, size_t len);
void HandleAckRange (uint32_t firstPacketNum, uint32_t lastPacketNum);
bool ExtractEndpoint (const uint8_t * buf, size_t size, boost::asio::ip::udp::endpoint& ep);
size_t CreateEndpoint (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep);
std::shared_ptr<const i2p::data::RouterInfo> ExtractRouterInfo (const uint8_t * buf, size_t size);
void CreateNonce (uint64_t seqn, uint8_t * nonce);
bool UpdateReceivePacketNum (uint32_t packetNum); // for Ack, returns false if duplicate
void HandleFirstFragment (const uint8_t * buf, size_t len);
void HandleFollowOnFragment (const uint8_t * buf, size_t len);
bool ConcatOutOfSequenceFragments (std::shared_ptr<SSU2IncompleteMessage> m); // true if message complete
void HandleRelayRequest (const uint8_t * buf, size_t len);
void HandleRelayIntro (const uint8_t * buf, size_t len);
void HandleRelayResponse (const uint8_t * buf, size_t len);
size_t CreateAddressBlock (const boost::asio::ip::udp::endpoint& ep, uint8_t * buf, size_t len);
size_t CreateAckBlock (uint8_t * buf, size_t len);
size_t CreatePaddingBlock (uint8_t * buf, size_t len, size_t minSize = 0);
size_t CreateI2NPBlock (uint8_t * buf, size_t len, std::shared_ptr<I2NPMessage>&& msg);
size_t CreateFirstFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr<I2NPMessage> msg);
size_t CreateFollowOnFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr<I2NPMessage> msg, uint8_t& fragmentNum, uint32_t msgID);
size_t CreateRelayIntroBlock (uint8_t * buf, size_t len, const uint8_t * introData, size_t introDataLen);
size_t CreateRelayResponseBlock (uint8_t * buf, size_t len, uint32_t nonce); // Charlie
private:
SSU2Server& m_Server;
std::shared_ptr<i2p::crypto::X25519Keys> m_EphemeralKeys;
std::unique_ptr<i2p::crypto::NoiseSymmetricState> m_NoiseState;
std::unique_ptr<SessionConfirmedFragment> m_SessionConfirmedFragment1; // for Bob if applicable
std::shared_ptr<const i2p::data::RouterInfo::Address> m_Address;
boost::asio::ip::udp::endpoint m_RemoteEndpoint;
uint64_t m_DestConnID, m_SourceConnID;
SSU2SessionState m_State;
uint8_t m_KeyDataSend[64], m_KeyDataReceive[64];
uint32_t m_SendPacketNum, m_ReceivePacketNum;
std::set<uint32_t> m_OutOfSequencePackets; // packet nums > receive packet num
std::map<uint32_t, std::shared_ptr<SentPacket> > m_SentPackets; // packetNum -> packet
std::map<uint32_t, std::shared_ptr<SSU2IncompleteMessage> > m_IncompleteMessages; // I2NP
std::map<uint32_t, std::pair <std::shared_ptr<SSU2Session>, uint64_t > > m_RelaySessions; // nonce->(Alice, timestamp) for Bob or nonce->(Charlie, timestamp) for Alice
std::list<std::shared_ptr<I2NPMessage> > m_SendQueue;
i2p::I2NPMessagesHandler m_Handler;
bool m_IsDataReceived;
size_t m_WindowSize;
uint32_t m_RelayTag; // between Bob and Charlie
OnEstablished m_OnEstablished; // callback from Established
};
class SSU2Server: private i2p::util::RunnableServiceWithWork
{
struct Packet
{
uint8_t buf[SSU2_MAX_PACKET_SIZE];
uint8_t buf[SSU2_MTU];
size_t len;
boost::asio::ip::udp::endpoint from;
};
};
class ReceiveService: public i2p::util::RunnableService
{
@@ -47,8 +249,8 @@ namespace transport
boost::asio::io_service& GetService () { return GetIOService (); };
void Start () { StartIOService (); };
void Stop () { StopIOService (); };
};
};
public:
SSU2Server ();
@@ -57,51 +259,34 @@ namespace transport
void Start ();
void Stop ();
boost::asio::io_service& GetService () { return GetIOService (); };
void SetLocalAddress (const boost::asio::ip::address& localAddress);
bool SetProxy (const std::string& address, uint16_t port);
bool UsesProxy () const { return m_IsThroughProxy; };
bool IsSupported (const boost::asio::ip::address& addr) const;
uint16_t GetPort (bool v4) const;
bool IsSyncClockFromPeers () const { return m_IsSyncClockFromPeers; };
void AddSession (std::shared_ptr<SSU2Session> session);
void RemoveSession (uint64_t connID);
void AddSessionByRouterHash (std::shared_ptr<SSU2Session> session);
bool AddPendingOutgoingSession (std::shared_ptr<SSU2Session> session);
void RemovePendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep);
std::shared_ptr<SSU2Session> FindSession (const i2p::data::IdentHash& ident) const;
std::shared_ptr<SSU2Session> FindPendingOutgoingSession (const boost::asio::ip::udp::endpoint& ep) const;
std::shared_ptr<SSU2Session> GetRandomSession (i2p::data::RouterInfo::CompatibleTransports remoteTransports,
const i2p::data::IdentHash& excluded) const;
void AddPendingOutgoingSession (std::shared_ptr<SSU2Session> session);
void AddRelay (uint32_t tag, std::shared_ptr<SSU2Session> relay);
void RemoveRelay (uint32_t tag);
void RemoveRelay (uint32_t tag);
std::shared_ptr<SSU2Session> FindRelaySession (uint32_t tag);
void Send (const uint8_t * header, size_t headerLen, const uint8_t * payload, size_t payloadLen,
void Send (const uint8_t * header, size_t headerLen, const uint8_t * payload, size_t payloadLen,
const boost::asio::ip::udp::endpoint& to);
void Send (const uint8_t * header, size_t headerLen, const uint8_t * headerX, size_t headerXLen,
void Send (const uint8_t * header, size_t headerLen, const uint8_t * headerX, size_t headerXLen,
const uint8_t * payload, size_t payloadLen, const boost::asio::ip::udp::endpoint& to);
void SendHolePunch (const boost::asio::ip::udp::endpoint& to);
bool CreateSession (std::shared_ptr<const i2p::data::RouterInfo> router,
std::shared_ptr<const i2p::data::RouterInfo::Address> address, bool peerTest = false);
bool StartPeerTest (std::shared_ptr<const i2p::data::RouterInfo> router, bool v4);
std::shared_ptr<const i2p::data::RouterInfo::Address> address);
void UpdateOutgoingToken (const boost::asio::ip::udp::endpoint& ep, uint64_t token, uint32_t exp);
uint64_t FindOutgoingToken (const boost::asio::ip::udp::endpoint& ep) const;
uint64_t GetIncomingToken (const boost::asio::ip::udp::endpoint& ep);
std::pair<uint64_t, uint32_t> NewIncomingToken (const boost::asio::ip::udp::endpoint& ep);
void RescheduleIntroducersUpdateTimer ();
void RescheduleIntroducersUpdateTimerV6 ();
i2p::util::MemoryPool<SSU2SentPacket>& GetSentPacketsPool () { return m_SentPacketsPool; };
private:
boost::asio::ip::udp::socket& OpenSocket (const boost::asio::ip::udp::endpoint& localEndpoint);
void Receive (boost::asio::ip::udp::socket& socket);
void HandleReceivedFrom (const boost::system::error_code& ecode, size_t bytes_transferred,
void HandleReceivedFrom (const boost::system::error_code& ecode, size_t bytes_transferred,
Packet * packet, boost::asio::ip::udp::socket& socket);
void HandleReceivedPacket (Packet * packet);
void HandleReceivedPackets (std::vector<Packet *> packets);
@@ -110,60 +295,30 @@ namespace transport
void ScheduleTermination ();
void HandleTerminationTimer (const boost::system::error_code& ecode);
void ScheduleResend (bool more);
void ScheduleResend ();
void HandleResendTimer (const boost::system::error_code& ecode);
void ConnectThroughIntroducer (std::shared_ptr<SSU2Session> session);
std::list<std::shared_ptr<SSU2Session> > FindIntroducers (int maxNumIntroducers,
bool v4, const std::set<i2p::data::IdentHash>& excluded) const;
void UpdateIntroducers (bool v4);
void ScheduleIntroducersUpdateTimer ();
void HandleIntroducersUpdateTimer (const boost::system::error_code& ecode, bool v4);
void ScheduleIntroducersUpdateTimerV6 ();
void SendThroughProxy (const uint8_t * header, size_t headerLen, const uint8_t * headerX, size_t headerXLen,
const uint8_t * payload, size_t payloadLen, const boost::asio::ip::udp::endpoint& to);
void ProcessNextPacketFromProxy (uint8_t * buf, size_t len);
void ConnectToProxy ();
void ReconnectToProxy ();
void HandshakeWithProxy ();
void ReadHandshakeWithProxyReply ();
void SendUDPAssociateRequest ();
void ReadUDPAssociateReply ();
void ReadUDPAssociateSocket (); // handle if closed by peer
void ConnectThroughIntroducer (std::shared_ptr<const i2p::data::RouterInfo> router,
std::shared_ptr<const i2p::data::RouterInfo::Address> address);
private:
ReceiveService m_ReceiveService;
ReceiveService m_ReceiveService;
boost::asio::ip::udp::socket m_SocketV4, m_SocketV6;
boost::asio::ip::address m_AddressV4, m_AddressV6;
std::unordered_map<uint64_t, std::shared_ptr<SSU2Session> > m_Sessions;
std::unordered_map<i2p::data::IdentHash, std::shared_ptr<SSU2Session> > m_SessionsByRouterHash;
std::map<i2p::data::IdentHash, std::shared_ptr<SSU2Session> > m_SessionsByRouterHash;
std::map<boost::asio::ip::udp::endpoint, std::shared_ptr<SSU2Session> > m_PendingOutgoingSessions;
std::map<boost::asio::ip::udp::endpoint, std::pair<uint64_t, uint32_t> > m_IncomingTokens, m_OutgoingTokens; // remote endpoint -> (token, expires in seconds)
std::map<uint32_t, std::shared_ptr<SSU2Session> > m_Relays; // we are introducer, relay tag -> session
std::list<i2p::data::IdentHash> m_Introducers, m_IntroducersV6; // introducers we are connected to
std::map<uint32_t, std::shared_ptr<SSU2Session> > m_Relays; // we are introducer, relay tag -> session
i2p::util::MemoryPoolMt<Packet> m_PacketsPool;
i2p::util::MemoryPool<SSU2SentPacket> m_SentPacketsPool;
boost::asio::deadline_timer m_TerminationTimer, m_ResendTimer,
m_IntroducersUpdateTimer, m_IntroducersUpdateTimerV6;
boost::asio::deadline_timer m_TerminationTimer, m_ResendTimer;
std::shared_ptr<SSU2Session> m_LastSession;
bool m_IsPublished; // if we maintain introducers
bool m_IsSyncClockFromPeers;
// proxy
bool m_IsThroughProxy;
uint8_t m_UDPRequestHeader[SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE];
std::unique_ptr<boost::asio::ip::tcp::endpoint> m_ProxyEndpoint;
std::unique_ptr<boost::asio::ip::tcp::socket> m_UDPAssociateSocket;
std::unique_ptr<boost::asio::ip::udp::endpoint> m_ProxyRelayEndpoint;
std::unique_ptr<boost::asio::deadline_timer> m_ProxyConnectRetryTimer;
public:
// for HTTP/I2PControl
const decltype(m_Sessions)& GetSSU2Sessions () const { return m_Sessions; };
};
const decltype(m_Sessions)& GetSSU2Sessions () const { return m_Sessions; };
};
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,364 +0,0 @@
/*
* Copyright (c) 2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#ifndef SSU2_SESSION_H__
#define SSU2_SESSION_H__
#include <memory>
#include <functional>
#include <map>
#include <set>
#include <list>
#include <boost/asio.hpp>
#include "Crypto.h"
#include "RouterInfo.h"
#include "RouterContext.h"
#include "TransportSession.h"
namespace i2p
{
namespace transport
{
const int SSU2_CONNECT_TIMEOUT = 5; // 5 seconds
const int SSU2_TERMINATION_TIMEOUT = 330; // 5.5 minutes
const int SSU2_CLOCK_SKEW = 60; // in seconds
const int SSU2_CLOCK_THRESHOLD = 15; // in seconds, if more we should adjust
const int SSU2_TOKEN_EXPIRATION_TIMEOUT = 9; // for Retry message, in seconds
const int SSU2_NEXT_TOKEN_EXPIRATION_TIMEOUT = 52*60; // for next token block, in seconds
const int SSU2_TOKEN_EXPIRATION_THRESHOLD = 2; // in seconds
const int SSU2_RELAY_NONCE_EXPIRATION_TIMEOUT = 10; // in seconds
const int SSU2_PEER_TEST_EXPIRATION_TIMEOUT = 60; // 60 seconds
const size_t SSU2_MAX_PACKET_SIZE = 1500;
const size_t SSU2_MIN_PACKET_SIZE = 1280;
const int SSU2_HANDSHAKE_RESEND_INTERVAL = 1000; // in millseconds
const int SSU2_RESEND_INTERVAL = 300; // in milliseconds
const int SSU2_MAX_NUM_RESENDS = 5;
const int SSU2_INCOMPLETE_MESSAGES_CLEANUP_TIMEOUT = 30; // in seconds
const size_t SSU2_MIN_WINDOW_SIZE = 16; // in packets
const size_t SSU2_MAX_WINDOW_SIZE = 256; // in packets
const size_t SSU2_MIN_RTO = 100; // in milliseconds
const size_t SSU2_MAX_RTO = 2500; // in milliseconds
const float SSU2_kAPPA = 1.8;
const size_t SSU2_MAX_OUTGOING_QUEUE_SIZE = 500; // in messages
const int SSU2_MAX_NUM_ACK_RANGES = 32; // to send
const uint8_t SSU2_MAX_NUM_FRAGMENTS = 64;
// flags
const uint8_t SSU2_FLAG_IMMEDIATE_ACK_REQUESTED = 0x01;
enum SSU2MessageType
{
eSSU2SessionRequest = 0,
eSSU2SessionCreated = 1,
eSSU2SessionConfirmed = 2,
eSSU2Data = 6,
eSSU2PeerTest = 7,
eSSU2Retry = 9,
eSSU2TokenRequest = 10,
eSSU2HolePunch = 11
};
enum SSU2BlockType
{
eSSU2BlkDateTime = 0,
eSSU2BlkOptions, // 1
eSSU2BlkRouterInfo, // 2
eSSU2BlkI2NPMessage, // 3
eSSU2BlkFirstFragment, // 4
eSSU2BlkFollowOnFragment, // 5
eSSU2BlkTermination, // 6
eSSU2BlkRelayRequest, // 7
eSSU2BlkRelayResponse, // 8
eSSU2BlkRelayIntro, // 9
eSSU2BlkPeerTest, // 10
eSSU2BlkNextNonce, // 11
eSSU2BlkAck, // 12
eSSU2BlkAddress, // 13
eSSU2BlkIntroKey, // 14
eSSU2BlkRelayTagRequest, // 15
eSSU2BlkRelayTag, // 16
eSSU2BlkNewToken, // 17
eSSU2BlkPathChallenge, // 18
eSSU2BlkPathResponse, // 19
eSSU2BlkFirstPacketNumber, // 20
eSSU2BlkPadding = 254
};
enum SSU2SessionState
{
eSSU2SessionStateUnknown,
eSSU2SessionStateTokenReceived,
eSSU2SessionStateSessionRequestSent,
eSSU2SessionStateSessionRequestReceived,
eSSU2SessionStateSessionCreatedSent,
eSSU2SessionStateSessionCreatedReceived,
eSSU2SessionStateSessionConfirmedSent,
eSSU2SessionStateEstablished,
eSSU2SessionStateClosing,
eSSU2SessionStateTerminated,
eSSU2SessionStateFailed,
eSSU2SessionStateIntroduced,
eSSU2SessionStatePeerTest,
eSSU2SessionStatePeerTestReceived, // 5 before 4
eSSU2SessionStateTokenRequestReceived
};
enum SSU2PeerTestCode
{
eSSU2PeerTestCodeAccept = 0,
eSSU2PeerTestCodeBobReasonUnspecified = 1,
eSSU2PeerTestCodeBobNoCharlieAvailable = 2,
eSSU2PeerTestCodeBobLimitExceeded = 3,
eSSU2PeerTestCodeBobSignatureFailure = 4,
eSSU2PeerTestCodeCharlieReasonUnspecified = 64,
eSSU2PeerTestCodeCharlieUnsupportedAddress = 65,
eSSU2PeerTestCodeCharlieLimitExceeded = 66,
eSSU2PeerTestCodeCharlieSignatureFailure = 67,
eSSU2PeerTestCodeCharlieAliceIsAlreadyConnected = 68,
eSSU2PeerTestCodeCharlieAliceIsBanned = 69,
eSSU2PeerTestCodeCharlieAliceIsUnknown = 70,
eSSU2PeerTestCodeUnspecified = 128
};
enum SSU2RelayResponseCode
{
eSSU2RelayResponseCodeAccept = 0,
eSSU2RelayResponseCodeBobRelayTagNotFound = 5,
eSSU2RelayResponseCodeCharlieUnsupportedAddress = 65,
eSSU2RelayResponseCodeCharlieSignatureFailure = 67,
eSSU2RelayResponseCodeCharlieAliceIsUnknown = 70
};
enum SSU2TerminationReason
{
eSSU2TerminationReasonNormalClose = 0,
eSSU2TerminationReasonTerminationReceived = 1,
eSSU2TerminationReasonIdleTimeout = 2,
eSSU2TerminationReasonRouterShutdown = 3,
eSSU2TerminationReasonDataPhaseAEADFailure= 4,
eSSU2TerminationReasonIncompatibleOptions = 5,
eSSU2TerminationReasonTncompatibleSignatureType = 6,
eSSU2TerminationReasonClockSkew = 7,
eSSU2TerminationPaddingViolation = 8,
eSSU2TerminationReasonAEADFramingError = 9,
eSSU2TerminationReasonPayloadFormatError = 10,
eSSU2TerminationReasonSessionRequestError = 11,
eSSU2TerminationReasonSessionCreatedError = 12,
eSSU2TerminationReasonSessionConfirmedError = 13,
eSSU2TerminationReasonTimeout = 14,
eSSU2TerminationReasonRouterInfoSignatureVerificationFail = 15,
eSSU2TerminationReasonInvalidS = 16,
eSSU2TerminationReasonBanned = 17,
eSSU2TerminationReasonBadToken = 18,
eSSU2TerminationReasonConnectionLimits = 19,
eSSU2TerminationReasonIncompatibleVersion = 20,
eSSU2TerminationReasonWrongNetID = 21,
eSSU2TerminationReasonReplacedByNewSession = 22
};
struct SSU2IncompleteMessage
{
struct Fragment
{
uint8_t buf[SSU2_MAX_PACKET_SIZE];
size_t len;
bool isLast;
};
std::shared_ptr<I2NPMessage> msg;
int nextFragmentNum;
uint32_t lastFragmentInsertTime; // in seconds
std::map<int, std::shared_ptr<Fragment> > outOfSequenceFragments;
void AttachNextFragment (const uint8_t * fragment, size_t fragmentSize);
};
struct SSU2SentPacket
{
uint8_t payload[SSU2_MAX_PACKET_SIZE];
size_t payloadSize = 0;
uint64_t sendTime; // in milliseconds
int numResends = 0;
};
// RouterInfo flags
const uint8_t SSU2_ROUTER_INFO_FLAG_REQUEST_FLOOD = 0x01;
const uint8_t SSU2_ROUTER_INFO_FLAG_GZIP = 0x02;
class SSU2Server;
class SSU2Session: public TransportSession, public std::enable_shared_from_this<SSU2Session>
{
union Header
{
uint64_t ll[2];
uint8_t buf[16];
struct
{
uint64_t connID;
uint32_t packetNum;
uint8_t type;
uint8_t flags[3];
} h;
};
struct HandshakePacket
{
Header header;
uint8_t headerX[48]; // part1 for SessionConfirmed
uint8_t payload[SSU2_MAX_PACKET_SIZE*2];
size_t payloadSize = 0;
uint64_t sendTime = 0; // in milliseconds
bool isSecondFragment = false; // for SessionConfirmed
};
typedef std::function<void ()> OnEstablished;
public:
SSU2Session (SSU2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter = nullptr,
std::shared_ptr<const i2p::data::RouterInfo::Address> addr = nullptr);
~SSU2Session ();
void SetRemoteEndpoint (const boost::asio::ip::udp::endpoint& ep) { m_RemoteEndpoint = ep; };
const boost::asio::ip::udp::endpoint& GetRemoteEndpoint () const { return m_RemoteEndpoint; };
i2p::data::RouterInfo::CompatibleTransports GetRemoteTransports () const { return m_RemoteTransports; };
std::shared_ptr<const i2p::data::RouterInfo::Address> GetAddress () const { return m_Address; };
void SetOnEstablished (OnEstablished e) { m_OnEstablished = e; };
OnEstablished GetOnEstablished () const { return m_OnEstablished; };
void Connect ();
bool Introduce (std::shared_ptr<SSU2Session> session, uint32_t relayTag);
void WaitForIntroduction ();
void SendPeerTest (); // Alice, Data message
void SendKeepAlive ();
void RequestTermination (SSU2TerminationReason reason);
void CleanUp (uint64_t ts);
void FlushData ();
void Done () override;
void SendLocalRouterInfo (bool update) override;
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) override;
uint32_t GetRelayTag () const override { return m_RelayTag; };
size_t Resend (uint64_t ts); // return number or resent packets
bool IsEstablished () const { return m_State == eSSU2SessionStateEstablished; };
uint64_t GetConnID () const { return m_SourceConnID; };
SSU2SessionState GetState () const { return m_State; };
void SetState (SSU2SessionState state) { m_State = state; };
bool ProcessFirstIncomingMessage (uint64_t connID, uint8_t * buf, size_t len);
bool ProcessSessionCreated (uint8_t * buf, size_t len);
bool ProcessSessionConfirmed (uint8_t * buf, size_t len);
bool ProcessRetry (uint8_t * buf, size_t len);
bool ProcessHolePunch (uint8_t * buf, size_t len);
bool ProcessPeerTest (uint8_t * buf, size_t len);
void ProcessData (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& from);
private:
void Terminate ();
void Established ();
void ScheduleConnectTimer ();
void HandleConnectTimer (const boost::system::error_code& ecode);
void PostI2NPMessages (std::vector<std::shared_ptr<I2NPMessage> > msgs);
bool SendQueue (); // returns true if ack block was sent
bool SendFragmentedMessage (std::shared_ptr<I2NPMessage> msg);
void ResendHandshakePacket ();
void ConnectAfterIntroduction ();
void ProcessSessionRequest (Header& header, uint8_t * buf, size_t len);
void ProcessTokenRequest (Header& header, uint8_t * buf, size_t len);
void SendSessionRequest (uint64_t token = 0);
void SendSessionCreated (const uint8_t * X);
void SendSessionConfirmed (const uint8_t * Y);
void KDFDataPhase (uint8_t * keydata_ab, uint8_t * keydata_ba);
void SendTokenRequest ();
void SendRetry ();
uint32_t SendData (const uint8_t * buf, size_t len, uint8_t flags = 0); // returns packet num
void SendQuickAck ();
void SendTermination ();
void SendHolePunch (uint32_t nonce, const boost::asio::ip::udp::endpoint& ep, const uint8_t * introKey, uint64_t token);
void SendPeerTest (uint8_t msg, const uint8_t * signedData, size_t signedDataLen, const uint8_t * introKey); // PeerTest message
void SendPathResponse (const uint8_t * data, size_t len);
void SendPathChallenge ();
void HandlePayload (const uint8_t * buf, size_t len);
void HandleDateTime (const uint8_t * buf, size_t len);
void HandleAck (const uint8_t * buf, size_t len);
void HandleAckRange (uint32_t firstPacketNum, uint32_t lastPacketNum, uint64_t ts);
void HandleAddress (const uint8_t * buf, size_t len);
bool ExtractEndpoint (const uint8_t * buf, size_t size, boost::asio::ip::udp::endpoint& ep);
size_t CreateEndpoint (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep);
std::shared_ptr<const i2p::data::RouterInfo::Address> FindLocalAddress () const;
void AdjustMaxPayloadSize ();
RouterStatus GetRouterStatus () const;
void SetRouterStatus (RouterStatus status) const;
std::shared_ptr<const i2p::data::RouterInfo> ExtractRouterInfo (const uint8_t * buf, size_t size);
void CreateNonce (uint64_t seqn, uint8_t * nonce);
bool UpdateReceivePacketNum (uint32_t packetNum); // for Ack, returns false if duplicate
void HandleFirstFragment (const uint8_t * buf, size_t len);
void HandleFollowOnFragment (const uint8_t * buf, size_t len);
bool ConcatOutOfSequenceFragments (std::shared_ptr<SSU2IncompleteMessage> m); // true if message complete
void HandleRelayRequest (const uint8_t * buf, size_t len);
void HandleRelayIntro (const uint8_t * buf, size_t len);
void HandleRelayResponse (const uint8_t * buf, size_t len);
void HandlePeerTest (const uint8_t * buf, size_t len);
size_t CreateAddressBlock (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& ep);
size_t CreateRouterInfoBlock (uint8_t * buf, size_t len, std::shared_ptr<const i2p::data::RouterInfo> r);
size_t CreateAckBlock (uint8_t * buf, size_t len);
size_t CreatePaddingBlock (uint8_t * buf, size_t len, size_t minSize = 0);
size_t CreateI2NPBlock (uint8_t * buf, size_t len, std::shared_ptr<I2NPMessage>&& msg);
size_t CreateFirstFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr<I2NPMessage> msg);
size_t CreateFollowOnFragmentBlock (uint8_t * buf, size_t len, std::shared_ptr<I2NPMessage> msg, uint8_t& fragmentNum, uint32_t msgID);
size_t CreateRelayIntroBlock (uint8_t * buf, size_t len, const uint8_t * introData, size_t introDataLen);
size_t CreateRelayResponseBlock (uint8_t * buf, size_t len, SSU2RelayResponseCode code, uint32_t nonce, uint64_t token, bool v4);
size_t CreatePeerTestBlock (uint8_t * buf, size_t len, uint8_t msg, SSU2PeerTestCode code, const uint8_t * routerHash, const uint8_t * signedData, size_t signedDataLen);
size_t CreatePeerTestBlock (uint8_t * buf, size_t len, uint32_t nonce); // Alice
size_t CreateTerminationBlock (uint8_t * buf, size_t len);
private:
SSU2Server& m_Server;
std::shared_ptr<i2p::crypto::X25519Keys> m_EphemeralKeys;
std::unique_ptr<i2p::crypto::NoiseSymmetricState> m_NoiseState;
std::unique_ptr<HandshakePacket> m_SessionConfirmedFragment; // for Bob if applicable or second fragment for Alice
std::unique_ptr<HandshakePacket> m_SentHandshakePacket; // SessionRequest, SessionCreated or SessionConfirmed
std::shared_ptr<const i2p::data::RouterInfo::Address> m_Address;
boost::asio::ip::udp::endpoint m_RemoteEndpoint;
i2p::data::RouterInfo::CompatibleTransports m_RemoteTransports; // for peer tests
uint64_t m_DestConnID, m_SourceConnID;
SSU2SessionState m_State;
uint8_t m_KeyDataSend[64], m_KeyDataReceive[64];
uint32_t m_SendPacketNum, m_ReceivePacketNum;
std::set<uint32_t> m_OutOfSequencePackets; // packet nums > receive packet num
std::map<uint32_t, std::shared_ptr<SSU2SentPacket> > m_SentPackets; // packetNum -> packet
std::map<uint32_t, std::shared_ptr<SSU2IncompleteMessage> > m_IncompleteMessages; // I2NP
std::map<uint32_t, std::pair <std::shared_ptr<SSU2Session>, uint64_t > > m_RelaySessions; // nonce->(Alice, timestamp) for Bob or nonce->(Charlie, timestamp) for Alice
std::map<uint32_t, std::pair <std::shared_ptr<SSU2Session>, uint64_t > > m_PeerTests; // same as for relay sessions
std::list<std::shared_ptr<I2NPMessage> > m_SendQueue;
i2p::I2NPMessagesHandler m_Handler;
bool m_IsDataReceived;
size_t m_WindowSize, m_RTT, m_RTO;
uint32_t m_RelayTag; // between Bob and Charlie
OnEstablished m_OnEstablished; // callback from Established
boost::asio::deadline_timer m_ConnectTimer;
SSU2TerminationReason m_TerminationReason;
size_t m_MaxPayloadSize;
std::unique_ptr<i2p::data::IdentHash> m_PathChallenge;
};
inline uint64_t CreateHeaderMask (const uint8_t * kh, const uint8_t * nonce)
{
uint64_t data = 0;
i2p::crypto::ChaCha20 ((uint8_t *)&data, 8, kh, nonce, (uint8_t *)&data);
return data;
}
}
}
#endif

View File

@@ -171,7 +171,7 @@ namespace transport
return;
}
// find message with msgID
// find message with msgID
auto it = m_IncompleteMessages.find (msgID);
if (it == m_IncompleteMessages.end ())
{
@@ -318,7 +318,7 @@ namespace transport
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 ();

View File

@@ -19,14 +19,17 @@
#include "I2NPProtocol.h"
#include "Identity.h"
#include "RouterInfo.h"
#include "TransportSession.h"
namespace i2p
{
namespace transport
{
const size_t SSU_MTU_V4 = 1484;
const size_t SSU_MTU_V6 = 1488;
const size_t IPV4_HEADER_SIZE = 20;
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
const int RESEND_INTERVAL = 3; // in seconds

View File

@@ -41,6 +41,7 @@ namespace transport
i2p::context.GetRouterInfo ().GetSSUAddress (true);
if (address) m_IntroKey = address->i;
}
m_CreationTime = i2p::util::GetSecondsSinceEpoch ();
}
SSUSession::~SSUSession ()
@@ -295,8 +296,8 @@ namespace transport
{
LogPrint (eLogWarning, "SSU: Clock adjusted by ", -offset, " seconds");
i2p::util::AdjustTimeOffset (-offset);
}
}
}
}
else if (std::abs (offset) > SSU_CLOCK_SKEW)
{
LogPrint (eLogError, "SSU: Clock skew detected ", offset, ". Check your clock");
@@ -387,11 +388,11 @@ namespace transport
// fill extended options, 3 bytes extended options don't change message size
bool isV4 = m_RemoteEndpoint.address ().is_v4 ();
if ((isV4 && i2p::context.GetStatus () == eRouterStatusOK) ||
(!isV4 && i2p::context.GetStatusV6 () == eRouterStatusOK)) // we don't need relays
(!isV4 && i2p::context.GetStatusV6 () == 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
*payload = 2; payload++; // 1 byte length
uint16_t flags = 0; // clear EXTENDED_OPTIONS_FLAG_REQUEST_RELAY_TAG
htobe16buf (payload, flags);
payload += 2;
@@ -719,8 +720,8 @@ namespace transport
if (i2p::context.GetStatus () == eRouterStatusTesting)
i2p::context.SetError (eRouterErrorSymmetricNAT);
}
else if (i2p::context.GetError () == eRouterErrorSymmetricNAT)
i2p::context.SetError (eRouterErrorNone);
else if (i2p::context.GetStatus () == eRouterStatusError && i2p::context.GetError () == eRouterErrorSymmetricNAT)
i2p::context.SetStatus (eRouterStatusTesting);
}
uint32_t nonce = bufbe32toh (buf);
buf += 4; // nonce
@@ -1019,7 +1020,7 @@ namespace transport
for (auto it = m_RelayRequests.begin (); it != m_RelayRequests.end ();)
{
if (ts > it->second.second + SSU_CONNECT_TIMEOUT)
it = m_RelayRequests.erase (it);
it = m_RelayRequests.erase (it);
else
++it;
}

View File

@@ -103,6 +103,8 @@ namespace transport
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 SetCreationTime (uint32_t ts) { m_CreationTime = ts; }; // for introducers
void FlushData ();
void CleanUp (uint64_t ts);
@@ -165,6 +167,7 @@ namespace transport
i2p::crypto::AESKey m_SessionKey;
i2p::crypto::MACKey m_MacKey;
i2p::data::RouterInfo::IntroKey m_IntroKey;
uint32_t m_CreationTime; // seconds since epoch
SSUData m_Data;
bool m_IsDataReceived;
std::unique_ptr<SignedData> m_SignedData; // we need it for SessionConfirmed only

View File

@@ -130,7 +130,7 @@ namespace crypto
else
{
size_t l = 64;
uint8_t sig[64]; // temporary buffer for signature. openssl issue #7232
uint8_t sig[64]; // temporary buffer for signature. openssl issue #7232
EVP_DigestSign (m_MDCtx, sig, &l, buf, len);
memcpy (signature, sig, 64);
}

View File

@@ -474,29 +474,6 @@ namespace stream
Close (); // check is all outgoing messages have been sent and we can send close
}
size_t Stream::Receive (uint8_t * buf, size_t len, int timeout)
{
if (!len) return 0;
size_t ret = 0;
std::condition_variable newDataReceived;
std::mutex newDataReceivedMutex;
std::unique_lock<std::mutex> l(newDataReceivedMutex);
AsyncReceive (boost::asio::buffer (buf, len),
[&ret, &newDataReceived, &newDataReceivedMutex](const boost::system::error_code& ecode, std::size_t bytes_transferred)
{
if (ecode == boost::asio::error::timed_out)
ret = 0;
else
ret = bytes_transferred;
std::unique_lock<std::mutex> l(newDataReceivedMutex);
newDataReceived.notify_all ();
},
timeout);
if (newDataReceived.wait_for (l, std::chrono::seconds (timeout)) == std::cv_status::timeout)
ret = 0;
return ret;
}
size_t Stream::Send (const uint8_t * buf, size_t len)
{
AsyncSend (buf, len, nullptr);
@@ -752,7 +729,7 @@ namespace stream
Terminate ();
break;
default:
LogPrint (eLogWarning, "Streaming: Unexpected stream status=", (int)m_Status, " for sSID=", m_SendStreamID);
LogPrint (eLogWarning, "Streaming: Unexpected stream status ", (int)m_Status, "sSID=", m_SendStreamID);
};
}
@@ -878,7 +855,7 @@ namespace stream
for (const auto& it: packets)
{
auto msg = m_RoutingSession->WrapSingleMessage (m_LocalDestination.CreateDataMessage (
it->GetBuffer (), it->GetLength (), m_Port, !m_RoutingSession->IsRatchets (), it->IsSYN ()));
it->GetBuffer (), it->GetLength (), m_Port, !m_RoutingSession->IsRatchets ()));
msgs.push_back (i2p::tunnel::TunnelMessageBlock
{
i2p::tunnel::eDeliveryTypeTunnel,
@@ -1108,6 +1085,8 @@ namespace stream
m_Owner (owner), m_LocalPort (localPort), m_Gzip (gzip),
m_PendingIncomingTimer (m_Owner->GetService ())
{
if (m_Gzip)
m_Deflator.reset (new i2p::data::GzipDeflator);
}
StreamingDestination::~StreamingDestination ()
@@ -1270,7 +1249,7 @@ namespace stream
return s;
}
void StreamingDestination::SendPing (std::shared_ptr<const i2p::data::LeaseSet> remote)
void StreamingDestination::SendPing (std::shared_ptr<const i2p::data::LeaseSet> remote)
{
auto s = std::make_shared<Stream> (m_Owner->GetService (), *this, remote, 0);
s->SendPing ();
@@ -1298,7 +1277,7 @@ namespace stream
{
m_PacketsPool.CleanUp ();
m_I2NPMsgsPool.CleanUp ();
}
}
}
bool StreamingDestination::DeleteStream (uint32_t recvStreamID)
@@ -1306,13 +1285,7 @@ namespace stream
auto it = m_Streams.find (recvStreamID);
if (it == m_Streams.end ())
return false;
auto s = it->second;
m_Owner->GetService ().post ([this, s] ()
{
s->Close (); // try to send FIN
s->Terminate (false);
DeleteStream (s);
});
DeleteStream (it->second);
return true;
}
@@ -1362,26 +1335,6 @@ namespace stream
acceptor (stream);
}
std::shared_ptr<Stream> StreamingDestination::AcceptStream (int timeout)
{
std::shared_ptr<i2p::stream::Stream> stream;
std::condition_variable streamAccept;
std::mutex streamAcceptMutex;
std::unique_lock<std::mutex> l(streamAcceptMutex);
AcceptOnce (
[&streamAccept, &streamAcceptMutex, &stream](std::shared_ptr<i2p::stream::Stream> s)
{
stream = s;
std::unique_lock<std::mutex> l(streamAcceptMutex);
streamAccept.notify_all ();
});
if (timeout)
streamAccept.wait_for (l, std::chrono::seconds (timeout));
else
streamAccept.wait (l);
return stream;
}
void StreamingDestination::HandlePendingIncomingTimer (const boost::system::error_code& ecode)
{
if (ecode != boost::asio::error::operation_aborted)
@@ -1406,7 +1359,7 @@ namespace stream
}
std::shared_ptr<I2NPMessage> StreamingDestination::CreateDataMessage (
const uint8_t * payload, size_t len, uint16_t toPort, bool checksum, bool gzip)
const uint8_t * payload, size_t len, uint16_t toPort, bool checksum)
{
size_t size;
auto msg = m_I2NPMsgsPool.AcquireShared ();
@@ -1414,8 +1367,8 @@ namespace stream
buf += 4; // reserve for lengthlength
msg->len += 4;
if (m_Gzip || gzip)
size = m_Deflator.Deflate (payload, len, buf, msg->maxLen - msg->len);
if (m_Gzip && m_Deflator)
size = m_Deflator->Deflate (payload, len, buf, msg->maxLen - msg->len);
else
size = i2p::data::GzipNoCompression (payload, len, buf, msg->maxLen - msg->len);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -185,8 +185,7 @@ namespace stream
template<typename Buffer, typename ReceiveHandler>
void AsyncReceive (const Buffer& buffer, ReceiveHandler handler, int timeout = 0);
size_t ReadSome (uint8_t * buf, size_t len) { return ConcatenatePackets (buf, len); };
size_t Receive (uint8_t * buf, size_t len, int timeout);
void AsyncClose() { m_Service.post(std::bind(&Stream::Close, shared_from_this())); };
/** only call close from destination thread, use Stream::AsyncClose for other threads */
@@ -279,14 +278,13 @@ namespace stream
bool IsAcceptorSet () const { return m_Acceptor != nullptr; };
void AcceptOnce (const Acceptor& acceptor);
void AcceptOnceAcceptor (std::shared_ptr<Stream> stream, Acceptor acceptor, Acceptor prev);
std::shared_ptr<Stream> AcceptStream (int timeout = 0); // sync
std::shared_ptr<i2p::client::ClientDestination> GetOwner () const { return m_Owner; };
void SetOwner (std::shared_ptr<i2p::client::ClientDestination> owner) { m_Owner = owner; };
uint16_t GetLocalPort () const { return m_LocalPort; };
void HandleDataMessagePayload (const uint8_t * buf, size_t len);
std::shared_ptr<I2NPMessage> CreateDataMessage (const uint8_t * payload, size_t len, uint16_t toPort, bool checksum = true, bool gzip = false);
std::shared_ptr<I2NPMessage> CreateDataMessage (const uint8_t * payload, size_t len, uint16_t toPort, bool checksum = true);
Packet * NewPacket () { return m_PacketsPool.Acquire(); }
void DeletePacket (Packet * p) { return m_PacketsPool.Release(p); }
@@ -317,7 +315,7 @@ namespace stream
public:
i2p::data::GzipInflator m_Inflator;
i2p::data::GzipDeflator m_Deflator;
std::unique_ptr<i2p::data::GzipDeflator> m_Deflator;
// for HTTP only
const decltype(m_Streams)& GetStreams () const { return m_Streams; };
@@ -338,10 +336,11 @@ namespace stream
int t = (timeout > MAX_RECEIVE_TIMEOUT) ? MAX_RECEIVE_TIMEOUT : timeout;
s->m_ReceiveTimer.expires_from_now (boost::posix_time::seconds(t));
int left = timeout - t;
s->m_ReceiveTimer.async_wait (
[s, buffer, handler, left](const boost::system::error_code & ec)
auto self = s->shared_from_this();
self->m_ReceiveTimer.async_wait (
[self, buffer, handler, left](const boost::system::error_code & ec)
{
s->HandleReceiveTimer(ec, buffer, handler, left);
self->HandleReceiveTimer(ec, buffer, handler, left);
});
}
});

View File

@@ -254,6 +254,6 @@ namespace util
void AdjustTimeOffset (int64_t offset)
{
g_TimeOffset += offset;
}
}
}
}

View File

@@ -27,7 +27,7 @@ namespace util
void GetCurrentDate (char * date); // returns date as YYYYMMDD string, 9 bytes
void GetDateString (uint64_t timestamp, char * date); // timestap is seconds since epoch, returns date as YYYYMMDD string, 9 bytes
void AdjustTimeOffset (int64_t offset); // in seconds from current
class NTPTimeSync
{
public:

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2022, The PurpleI2P Project
* Copyright (c) 2013-2020, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@@ -24,10 +24,6 @@ namespace i2p
{
namespace transport
{
const size_t IPV4_HEADER_SIZE = 20;
const size_t IPV6_HEADER_SIZE = 40;
const size_t UDP_HEADER_SIZE = 8;
class SignedData
{
public:
@@ -37,12 +33,6 @@ namespace transport
{
m_Stream << other.m_Stream.rdbuf ();
}
void Reset ()
{
m_Stream.str("");
}
void Insert (const uint8_t * buf, size_t len)
{
m_Stream.write ((char *)buf, len);
@@ -79,7 +69,6 @@ namespace transport
{
if (router)
m_RemoteIdentity = router->GetRouterIdentity ();
m_CreationTime = m_LastActivityTimestamp;
}
virtual ~TransportSession () {};
@@ -107,11 +96,7 @@ namespace transport
bool IsTerminationTimeoutExpired (uint64_t ts) const
{ return ts >= m_LastActivityTimestamp + GetTerminationTimeout (); };
uint32_t GetCreationTime () const { return m_CreationTime; };
void SetCreationTime (uint32_t ts) { m_CreationTime = ts; }; // for introducers
virtual uint32_t GetRelayTag () const { return 0; };
virtual void SendLocalRouterInfo (bool update = false) { SendI2NPMessages ({ CreateDatabaseStoreMsg () }); };
virtual void SendLocalRouterInfo () { SendI2NPMessages ({ CreateDatabaseStoreMsg () }); };
virtual void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs) = 0;
protected:
@@ -122,17 +107,7 @@ namespace transport
bool m_IsOutgoing;
int m_TerminationTimeout;
uint64_t m_LastActivityTimestamp;
uint32_t m_CreationTime; // seconds since epoch
};
// SOCKS5 proxy
const uint8_t SOCKS5_VER = 0x05;
const uint8_t SOCKS5_CMD_CONNECT = 0x01;
const uint8_t SOCKS5_CMD_UDP_ASSOCIATE = 0x03;
const uint8_t SOCKS5_ATYP_IPV4 = 0x01;
const uint8_t SOCKS5_ATYP_IPV6 = 0x04;
const size_t SOCKS5_UDP_IPV4_REQUEST_HEADER_SIZE = 10;
const size_t SOCKS5_UDP_IPV6_REQUEST_HEADER_SIZE = 22;
}
}

View File

@@ -167,8 +167,6 @@ namespace transport
m_PeerTestTimer = new boost::asio::deadline_timer (*m_Service);
}
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
i2p::config::GetOption("nat", m_IsNAT);
m_X25519KeysPairSupplier.Start ();
m_IsRunning = true;
@@ -192,8 +190,6 @@ namespace transport
m_NTCP2Server->UseProxy(proxytype, proxyurl.host, proxyurl.port, proxyurl.user, proxyurl.pass);
i2p::context.SetStatus (eRouterStatusProxy);
if (ipv6)
i2p::context.SetStatusV6 (eRouterStatusProxy);
}
else
LogPrint(eLogError, "Transports: Unsupported NTCP2 proxy URL ", ntcp2proxy);
@@ -222,29 +218,10 @@ namespace transport
}
}
// create SSU2 server
if (enableSSU2)
{
m_SSU2Server = new SSU2Server ();
std::string ssu2proxy; i2p::config::GetOption("ssu2.proxy", ssu2proxy);
if (!ssu2proxy.empty())
{
if (proxyurl.parse (ssu2proxy) && proxyurl.schema == "socks")
{
if (m_SSU2Server->SetProxy (proxyurl.host, proxyurl.port))
{
i2p::context.SetStatus (eRouterStatusProxy);
if (ipv6)
i2p::context.SetStatusV6 (eRouterStatusProxy);
}
else
LogPrint(eLogError, "Transports: Can't set SSU2 proxy ", ssu2proxy);
}
else
LogPrint(eLogError, "Transports: Invalid SSU2 proxy URL ", ssu2proxy);
}
}
if (enableSSU2) m_SSU2Server = new SSU2Server ();
// bind to interfaces
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
if (ipv4)
{
std::string address; i2p::config::GetOption("address4", address);
@@ -256,22 +233,11 @@ namespace transport
{
if (m_NTCP2Server) m_NTCP2Server->SetLocalAddress (addr);
if (m_SSUServer) m_SSUServer->SetLocalAddress (addr);
if (m_SSU2Server) m_SSU2Server->SetLocalAddress (addr);
}
}
if (enableSSU2)
{
uint16_t mtu; i2p::config::GetOption ("ssu2.mtu4", mtu);
if (mtu)
{
if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE;
if (mtu > (int)SSU2_MAX_PACKET_SIZE) mtu = SSU2_MAX_PACKET_SIZE;
i2p::context.SetMTU (mtu, true);
}
}
}
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
if (ipv6)
{
std::string address; i2p::config::GetOption("address6", address);
@@ -283,20 +249,8 @@ namespace transport
{
if (m_NTCP2Server) m_NTCP2Server->SetLocalAddress (addr);
if (m_SSUServer) m_SSUServer->SetLocalAddress (addr);
if (m_SSU2Server) m_SSU2Server->SetLocalAddress (addr);
}
}
if (enableSSU2)
{
uint16_t mtu; i2p::config::GetOption ("ssu2.mtu6", mtu);
if (mtu)
{
if (mtu < (int)SSU2_MIN_PACKET_SIZE) mtu = SSU2_MIN_PACKET_SIZE;
if (mtu > (int)SSU2_MAX_PACKET_SIZE) mtu = SSU2_MAX_PACKET_SIZE;
i2p::context.SetMTU (mtu, false);
}
}
}
bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
@@ -314,7 +268,6 @@ namespace transport
// start servers
if (m_NTCP2Server) m_NTCP2Server->Start ();
if (m_SSU2Server) m_SSU2Server->Start ();
if (m_SSUServer)
{
LogPrint (eLogInfo, "Transports: Start listening UDP port ", ssuPort);
@@ -329,9 +282,10 @@ namespace transport
delete m_SSUServer;
m_SSUServer = nullptr;
}
if (m_SSUServer) DetectExternalIP ();
}
if (m_SSUServer || m_SSU2Server) DetectExternalIP ();
if (m_SSU2Server) m_SSU2Server->Start ();
m_PeerCleanupTimer->expires_from_now (boost::posix_time::seconds(5*SESSION_CREATION_TIMEOUT));
m_PeerCleanupTimer->async_wait (std::bind (&Transports::HandlePeerCleanupTimer, this, std::placeholders::_1));
@@ -353,14 +307,14 @@ namespace transport
delete m_SSUServer;
m_SSUServer = nullptr;
}
if (m_SSU2Server)
{
m_SSU2Server->Stop ();
delete m_SSU2Server;
m_SSU2Server = nullptr;
}
if (m_NTCP2Server)
{
m_NTCP2Server->Stop ();
@@ -459,9 +413,9 @@ namespace transport
auto r = netdb.FindRouter (ident);
if (r && (r->IsUnreachable () || !r->IsReachableFrom (i2p::context.GetRouterInfo ()))) return; // router found but non-reachable
{
auto ts = i2p::util::GetSecondsSinceEpoch ();
std::unique_lock<std::mutex> l(m_PeersMutex);
it = m_Peers.insert (std::pair<i2p::data::IdentHash, Peer>(ident, {r, ts})).first;
it = m_Peers.insert (std::pair<i2p::data::IdentHash, Peer>(ident, { 0, r, {},
i2p::util::GetSecondsSinceEpoch (), {} })).first;
}
connected = ConnectToPeer (ident, it->second);
}
@@ -496,81 +450,127 @@ namespace transport
peer.router = netdb.FindRouter (ident); // try to get new one from netdb
if (peer.router) // we have RI already
{
if (peer.priority.empty ())
SetPriority (peer);
while (peer.numAttempts < (int)peer.priority.size ())
if (peer.numAttempts < 2) // NTCP2, 0 - ipv6, 1- ipv4
{
auto tr = peer.priority[peer.numAttempts];
peer.numAttempts++;
switch (tr)
if (m_NTCP2Server) // we support NTCP2
{
case i2p::data::RouterInfo::eNTCP2V4:
case i2p::data::RouterInfo::eNTCP2V6:
std::shared_ptr<const RouterInfo::Address> address;
if (!peer.numAttempts) // NTCP2 ipv6
{
if (!m_NTCP2Server) continue;
std::shared_ptr<const RouterInfo::Address> address = (tr == i2p::data::RouterInfo::eNTCP2V6) ?
peer.router->GetPublishedNTCP2V6Address () : peer.router->GetPublishedNTCP2V4Address ();
if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host))
address = nullptr;
if (address)
if (context.GetRouterInfo ().IsNTCP2V6 () && peer.router->IsReachableBy (RouterInfo::eNTCP2V6))
{
auto s = std::make_shared<NTCP2Session> (*m_NTCP2Server, peer.router, address);
if( m_NTCP2Server->UsingProxy())
m_NTCP2Server->ConnectWithProxy(s);
else
m_NTCP2Server->Connect (s);
return true;
address = peer.router->GetPublishedNTCP2V6Address ();
if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host))
address = nullptr;
}
break;
peer.numAttempts++;
}
case i2p::data::RouterInfo::eSSU2V4:
case i2p::data::RouterInfo::eSSU2V6:
if (!address && peer.numAttempts == 1) // NTCP2 ipv4
{
if (!m_SSU2Server) continue;
std::shared_ptr<const RouterInfo::Address> address = (tr == i2p::data::RouterInfo::eSSU2V6) ?
peer.router->GetSSU2V6Address () : peer.router->GetSSU2V4Address ();
if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host))
address = nullptr;
if (address && address->IsReachableSSU ())
if (context.GetRouterInfo ().IsNTCP2 (true) && peer.router->IsReachableBy (RouterInfo::eNTCP2V4))
{
if (m_SSU2Server->CreateSession (peer.router, address))
return true;
address = peer.router->GetPublishedNTCP2V4Address ();
if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host))
address = nullptr;
}
break;
peer.numAttempts++;
}
case i2p::data::RouterInfo::eSSUV4:
case i2p::data::RouterInfo::eSSUV6:
if (address)
{
if (!m_SSUServer) continue;
std::shared_ptr<const RouterInfo::Address> address = (tr == i2p::data::RouterInfo::eSSUV6) ?
peer.router->GetSSUV6Address () : peer.router->GetSSUAddress (true);
if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host))
address = nullptr;
if (address && address->IsReachableSSU ())
{
if (m_SSUServer->CreateSession (peer.router, address))
return true;
}
break;
}
case i2p::data::RouterInfo::eNTCP2V6Mesh:
{
if (!m_NTCP2Server) continue;
auto address = peer.router->GetYggdrasilAddress ();
if (address)
{
auto s = std::make_shared<NTCP2Session> (*m_NTCP2Server, peer.router, address);
auto s = std::make_shared<NTCP2Session> (*m_NTCP2Server, peer.router, address);
if( m_NTCP2Server->UsingProxy())
m_NTCP2Server->ConnectWithProxy(s);
else
m_NTCP2Server->Connect (s);
return true;
}
break;
return true;
}
}
else
peer.numAttempts = 2; // switch to SSU
}
if (peer.numAttempts == 2 || peer.numAttempts == 3) // SSU
{
if (m_SSUServer)
{
std::shared_ptr<const RouterInfo::Address> address;
if (peer.numAttempts == 2) // SSU ipv6
{
if (context.GetRouterInfo ().IsSSUV6 () && peer.router->IsReachableBy (RouterInfo::eSSUV6))
{
address = peer.router->GetSSUV6Address ();
if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host))
address = nullptr;
}
peer.numAttempts++;
}
if (!address && peer.numAttempts == 3) // SSU ipv4
{
if (context.GetRouterInfo ().IsSSU (true) && peer.router->IsReachableBy (RouterInfo::eSSUV4))
{
address = peer.router->GetSSUAddress (true);
if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host))
address = nullptr;
}
peer.numAttempts++;
}
if (address && address->IsReachableSSU ())
{
if (m_SSUServer->CreateSession (peer.router, address))
return true;
}
}
else
peer.numAttempts += 2; // switch to Mesh
}
if (peer.numAttempts == 4) // Mesh
{
peer.numAttempts++;
if (m_NTCP2Server && context.GetRouterInfo ().IsMesh () && peer.router->IsMesh ())
{
auto address = peer.router->GetYggdrasilAddress ();
if (address)
{
auto s = std::make_shared<NTCP2Session> (*m_NTCP2Server, peer.router, address);
m_NTCP2Server->Connect (s);
return true;
}
default:
LogPrint (eLogError, "Transports: Unknown transport ", (int)tr);
}
}
LogPrint (eLogInfo, "Transports: No compatible addresses available");
if (peer.numAttempts == 5 || peer.numAttempts == 6) // SSU2
{
if (m_SSU2Server)
{
std::shared_ptr<const RouterInfo::Address> address;
if (peer.numAttempts == 5) // SSU2 ipv6
{
if (context.GetRouterInfo ().IsSSU2V6 () && peer.router->IsReachableBy (RouterInfo::eSSU2V6))
{
address = peer.router->GetSSU2V6Address ();
if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host))
address = nullptr;
}
peer.numAttempts++;
}
if (!address && peer.numAttempts == 6) // SSU2 ipv4
{
if (context.GetRouterInfo ().IsSSU2V4 () && peer.router->IsReachableBy (RouterInfo::eSSU2V4))
{
address = peer.router->GetSSU2V4Address ();
if (address && m_CheckReserved && i2p::util::net::IsInReservedRange(address->host))
address = nullptr;
}
peer.numAttempts++;
}
if (address && address->IsReachableSSU ())
{
if (m_SSU2Server->CreateSession (peer.router, address))
return true;
}
}
else
peer.numAttempts += 2;
}
LogPrint (eLogInfo, "Transports: No compatble NTCP2 or SSU addresses available");
i2p::data::netdb.SetUnreachable (ident, true); // we are here because all connection attempts failed
peer.Done ();
std::unique_lock<std::mutex> l(m_PeersMutex);
@@ -586,41 +586,6 @@ namespace transport
return true;
}
void Transports::SetPriority (Peer& peer) const
{
static const std::vector<i2p::data::RouterInfo::SupportedTransports>
ntcp2Priority =
{
i2p::data::RouterInfo::eNTCP2V6,
i2p::data::RouterInfo::eNTCP2V4,
i2p::data::RouterInfo::eSSU2V6,
i2p::data::RouterInfo::eSSU2V4,
i2p::data::RouterInfo::eNTCP2V6Mesh,
i2p::data::RouterInfo::eSSUV6,
i2p::data::RouterInfo::eSSUV4
},
ssu2Priority =
{
i2p::data::RouterInfo::eSSU2V6,
i2p::data::RouterInfo::eSSU2V4,
i2p::data::RouterInfo::eNTCP2V6,
i2p::data::RouterInfo::eNTCP2V4,
i2p::data::RouterInfo::eNTCP2V6Mesh,
i2p::data::RouterInfo::eSSUV6,
i2p::data::RouterInfo::eSSUV4
};
if (!peer.router) return;
auto compatibleTransports = context.GetRouterInfo ().GetCompatibleTransports (false) &
peer.router->GetCompatibleTransports (true);
peer.numAttempts = 0;
peer.priority.clear ();
bool ssu2 = rand () & 1;
const auto& priority = ssu2 ? ssu2Priority : ntcp2Priority;
for (auto transport: priority)
if (transport & compatibleTransports)
peer.priority.push_back (transport);
}
void Transports::RequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, const i2p::data::IdentHash& ident)
{
m_Service->post (std::bind (&Transports::HandleRequestComplete, this, r, ident));
@@ -654,111 +619,68 @@ namespace transport
i2p::context.SetStatus (eRouterStatusOK);
return;
}
if (m_SSUServer || m_SSU2Server)
if (m_SSUServer)
PeerTest ();
else
LogPrint (eLogWarning, "Transports: Can't detect external IP. SSU or SSU2 is not available");
LogPrint (eLogError, "Transports: Can't detect external IP. SSU is not available");
}
void Transports::PeerTest (bool ipv4, bool ipv6)
{
if (RoutesRestricted() || (!m_SSUServer && !m_SSU2Server)) return;
if (RoutesRestricted() || !m_SSUServer) return;
if (ipv4 && i2p::context.SupportsV4 ())
{
LogPrint (eLogInfo, "Transports: Started peer test IPv4");
std::set<i2p::data::IdentHash> excluded;
excluded.insert (i2p::context.GetIdentHash ()); // don't pick own router
if (m_SSUServer)
bool statusChanged = false;
for (int i = 0; i < 5; i++)
{
bool statusChanged = false;
for (int i = 0; i < 5; i++)
auto router = i2p::data::netdb.GetRandomPeerTestRouter (true, excluded); // v4
if (router)
{
auto router = i2p::data::netdb.GetRandomPeerTestRouter (true, excluded); // v4
if (router)
auto addr = router->GetSSUAddress (true); // ipv4
if (addr && !i2p::util::net::IsInReservedRange(addr->host))
{
auto addr = router->GetSSUAddress (true); // ipv4
if (addr && !i2p::util::net::IsInReservedRange(addr->host))
if (!statusChanged)
{
if (!statusChanged)
{
statusChanged = true;
i2p::context.SetStatus (eRouterStatusTesting); // first time only
}
m_SSUServer->CreateSession (router, addr, true); // peer test v4
statusChanged = true;
i2p::context.SetStatus (eRouterStatusTesting); // first time only
}
excluded.insert (router->GetIdentHash ());
}
}
if (!statusChanged)
LogPrint (eLogWarning, "Transports: Can't find routers for peer test IPv4");
}
// SSU2
if (m_SSU2Server && !m_SSU2Server->UsesProxy ())
{
excluded.clear ();
excluded.insert (i2p::context.GetIdentHash ());
int numTests = m_SSUServer ? 3 : 5;
for (int i = 0; i < numTests; i++)
{
auto router = i2p::data::netdb.GetRandomSSU2PeerTestRouter (true, excluded); // v4
if (router)
{
if (i2p::context.GetStatus () != eRouterStatusTesting)
i2p::context.SetStatusSSU2 (eRouterStatusTesting);
m_SSU2Server->StartPeerTest (router, true);
excluded.insert (router->GetIdentHash ());
m_SSUServer->CreateSession (router, addr, true); // peer test v4
}
excluded.insert (router->GetIdentHash ());
}
}
if (!statusChanged)
LogPrint (eLogWarning, "Transports: Can't find routers for peer test IPv4");
}
if (ipv6 && i2p::context.SupportsV6 ())
{
LogPrint (eLogInfo, "Transports: Started peer test IPv6");
std::set<i2p::data::IdentHash> excluded;
excluded.insert (i2p::context.GetIdentHash ()); // don't pick own router
if (m_SSUServer)
bool statusChanged = false;
for (int i = 0; i < 5; i++)
{
bool statusChanged = false;
for (int i = 0; i < 5; i++)
auto router = i2p::data::netdb.GetRandomPeerTestRouter (false, excluded); // v6
if (router)
{
auto router = i2p::data::netdb.GetRandomPeerTestRouter (false, excluded); // v6
if (router)
auto addr = router->GetSSUV6Address ();
if (addr && !i2p::util::net::IsInReservedRange(addr->host))
{
auto addr = router->GetSSUV6Address ();
if (addr && !i2p::util::net::IsInReservedRange(addr->host))
if (!statusChanged)
{
if (!statusChanged)
{
statusChanged = true;
i2p::context.SetStatusV6 (eRouterStatusTesting); // first time only
}
m_SSUServer->CreateSession (router, addr, true); // peer test v6
statusChanged = true;
i2p::context.SetStatusV6 (eRouterStatusTesting); // first time only
}
excluded.insert (router->GetIdentHash ());
}
}
if (!statusChanged)
LogPrint (eLogWarning, "Transports: Can't find routers for peer test IPv6");
}
// SSU2
if (m_SSU2Server && !m_SSU2Server->UsesProxy ())
{
excluded.clear ();
excluded.insert (i2p::context.GetIdentHash ());
int numTests = m_SSUServer ? 3 : 5;
for (int i = 0; i < numTests; i++)
{
auto router = i2p::data::netdb.GetRandomSSU2PeerTestRouter (false, excluded); // v6
if (router)
{
if (i2p::context.GetStatusV6 () != eRouterStatusTesting)
i2p::context.SetStatusV6SSU2 (eRouterStatusTesting);
m_SSU2Server->StartPeerTest (router, false);
excluded.insert (router->GetIdentHash ());
m_SSUServer->CreateSession (router, addr, true); // peer test v6
}
excluded.insert (router->GetIdentHash ());
}
}
if (!statusChanged)
LogPrint (eLogWarning, "Transports: Can't find routers for peer test IPv6");
}
}
@@ -809,9 +731,8 @@ namespace transport
return;
}
session->SendI2NPMessages ({ CreateDatabaseStoreMsg () }); // send DatabaseStore
auto ts = i2p::util::GetSecondsSinceEpoch ();
std::unique_lock<std::mutex> l(m_PeersMutex);
m_Peers.insert (std::make_pair (ident, Peer{ nullptr, ts }));
std::unique_lock<std::mutex> l(m_PeersMutex);
m_Peers.insert (std::make_pair (ident, Peer{ 0, nullptr, { session }, i2p::util::GetSecondsSinceEpoch (), {} }));
}
});
}
@@ -872,17 +793,7 @@ namespace transport
it = m_Peers.erase (it);
}
else
{
if (ts > it->second.nextRouterInfoUpdateTime)
{
auto session = it->second.sessions.front ();
if (session)
session->SendLocalRouterInfo (true);
it->second.nextRouterInfoUpdateTime = ts + PEER_ROUTER_INFO_UPDATE_INTERVAL +
rand () % PEER_ROUTER_INFO_UPDATE_INTERVAL_VARIANCE;
}
++it;
}
}
UpdateBandwidth (); // TODO: use separate timer(s) for it
bool ipv4Testing = i2p::context.GetStatus () == eRouterStatusTesting;
@@ -918,18 +829,18 @@ namespace transport
}
return i2p::data::netdb.FindRouter (ident);
}
void Transports::RestrictRoutesToFamilies(const std::set<std::string>& families)
{
std::lock_guard<std::mutex> lock(m_FamilyMutex);
m_TrustedFamilies.clear();
for (auto fam : families)
{
{
boost::to_lower (fam);
auto id = i2p::data::netdb.GetFamilies ().GetFamilyID (fam);
if (id)
if (id)
m_TrustedFamilies.push_back (id);
}
}
}
void Transports::RestrictRoutesToRouters(std::set<i2p::data::IdentHash> routers)
@@ -1008,122 +919,5 @@ namespace transport
i2p::context.SetError (eRouterErrorOffline);
}
}
void InitAddressFromIface ()
{
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
// ifname -> address
std::string ifname; i2p::config::GetOption("ifname", ifname);
if (ipv4 && i2p::config::IsDefault ("address4"))
{
std::string ifname4; i2p::config::GetOption("ifname4", ifname4);
if (!ifname4.empty ())
i2p::config::SetOption ("address4", i2p::util::net::GetInterfaceAddress(ifname4, false).to_string ()); // v4
else if (!ifname.empty ())
i2p::config::SetOption ("address4", i2p::util::net::GetInterfaceAddress(ifname, false).to_string ()); // v4
}
if (ipv6 && i2p::config::IsDefault ("address6"))
{
std::string ifname6; i2p::config::GetOption("ifname6", ifname6);
if (!ifname6.empty ())
i2p::config::SetOption ("address6", i2p::util::net::GetInterfaceAddress(ifname6, true).to_string ()); // v6
else if (!ifname.empty ())
i2p::config::SetOption ("address6", i2p::util::net::GetInterfaceAddress(ifname, true).to_string ()); // v6
}
}
void InitTransports ()
{
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
bool ygg; i2p::config::GetOption("meshnets.yggdrasil", ygg);
uint16_t port; i2p::config::GetOption("port", port);
boost::asio::ip::address_v6 yggaddr;
if (ygg)
{
std::string yggaddress; i2p::config::GetOption ("meshnets.yggaddress", yggaddress);
if (!yggaddress.empty ())
{
yggaddr = boost::asio::ip::address_v6::from_string (yggaddress);
if (yggaddr.is_unspecified () || !i2p::util::net::IsYggdrasilAddress (yggaddr) ||
!i2p::util::net::IsLocalAddress (yggaddr))
{
LogPrint(eLogWarning, "Transports: Can't find Yggdrasil address ", yggaddress);
ygg = false;
}
}
else
{
yggaddr = i2p::util::net::GetYggdrasilAddress ();
if (yggaddr.is_unspecified ())
{
LogPrint(eLogWarning, "Transports: Yggdrasil is not running. Disabled");
ygg = false;
}
}
}
if (!i2p::config::IsDefault("port"))
{
LogPrint(eLogInfo, "Transports: Accepting incoming connections at port ", port);
i2p::context.UpdatePort (port);
}
i2p::context.SetSupportsV6 (ipv6);
i2p::context.SetSupportsV4 (ipv4);
i2p::context.SetSupportsMesh (ygg, yggaddr);
i2p::context.RemoveNTCPAddress (!ipv6); // TODO: remove later
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
if (ntcp2)
{
bool published; i2p::config::GetOption("ntcp2.published", published);
if (published)
{
std::string ntcp2proxy; i2p::config::GetOption("ntcp2.proxy", ntcp2proxy);
if (!ntcp2proxy.empty ()) published = false;
}
if (published)
{
uint16_t ntcp2port; i2p::config::GetOption("ntcp2.port", ntcp2port);
if (!ntcp2port) ntcp2port = port; // use standard port
i2p::context.PublishNTCP2Address (ntcp2port, true, ipv4, ipv6, false); // publish
if (ipv6)
{
std::string ipv6Addr; i2p::config::GetOption("ntcp2.addressv6", ipv6Addr);
auto addr = boost::asio::ip::address_v6::from_string (ipv6Addr);
if (!addr.is_unspecified () && addr != boost::asio::ip::address_v6::any ())
i2p::context.UpdateNTCP2V6Address (addr); // set ipv6 address if configured
}
}
else
i2p::context.PublishNTCP2Address (port, false, ipv4, ipv6, false); // unpublish
}
if (ygg)
{
i2p::context.PublishNTCP2Address (port, true, false, false, true);
i2p::context.UpdateNTCP2V6Address (yggaddr);
if (!ipv4 && !ipv6)
i2p::context.SetStatus (eRouterStatusMesh);
}
bool ssu; i2p::config::GetOption("ssu", ssu);
if (!ssu) i2p::context.RemoveSSUAddress (); // TODO: remove later
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
if (ssu2 && i2p::config::IsDefault ("ssu2.enabled") && !ipv4 && !ipv6)
ssu2 = false; // don't enable ssu2 for yggdrasil only router
if (ssu2)
{
uint16_t ssu2port; i2p::config::GetOption("ssu2.port", ssu2port);
if (!ssu2port && port) ssu2port = ssu ? (port + 1) : port;
bool published; i2p::config::GetOption("ssu2.published", published);
if (published)
i2p::context.PublishSSU2Address (ssu2port, true, ipv4, ipv6); // publish
else
i2p::context.PublishSSU2Address (ssu2port, false, ipv4, ipv6); // unpublish
}
}
}
}

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