mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-24 22:37:16 +01:00
commit
d5e1d56fde
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/build/build_mingw.cmd eol=crlf
|
5
.github/workflows/build-freebsd.yml
vendored
5
.github/workflows/build-freebsd.yml
vendored
|
@ -4,15 +4,16 @@ on: [push, pull_request]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: macos-latest
|
runs-on: macos-10.15
|
||||||
name: with UPnP
|
name: with UPnP
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Test in FreeBSD
|
- name: Test in FreeBSD
|
||||||
id: test
|
id: test
|
||||||
uses: vmactions/freebsd-vm@v0.1.4
|
uses: vmactions/freebsd-vm@v0.1.5
|
||||||
with:
|
with:
|
||||||
usesh: true
|
usesh: true
|
||||||
|
mem: 2048
|
||||||
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: |
|
run: |
|
||||||
cd build
|
cd build
|
||||||
|
|
50
.github/workflows/build-windows.yml
vendored
50
.github/workflows/build-windows.yml
vendored
|
@ -8,14 +8,15 @@ defaults:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Building for ${{ matrix.arch }}
|
name: Building using ${{ matrix.arch }} toolchain
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: true
|
fail-fast: true
|
||||||
matrix:
|
matrix:
|
||||||
include: [
|
include: [
|
||||||
{ msystem: MINGW64, arch: x86_64 },
|
{ msystem: UCRT64, arch: ucrt-x86_64, arch_short: x64-ucrt },
|
||||||
{ msystem: MINGW32, arch: i686 }
|
{ msystem: MINGW64, arch: x86_64, arch_short: x64 },
|
||||||
|
{ msystem: MINGW32, arch: i686, arch_short: x86 }
|
||||||
]
|
]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
|
@ -25,11 +26,50 @@ jobs:
|
||||||
msystem: ${{ matrix.msystem }}
|
msystem: ${{ matrix.msystem }}
|
||||||
install: base-devel mingw-w64-${{ matrix.arch }}-gcc mingw-w64-${{ matrix.arch }}-boost mingw-w64-${{ matrix.arch }}-openssl mingw-w64-${{ matrix.arch }}-miniupnpc
|
install: base-devel mingw-w64-${{ matrix.arch }}-gcc mingw-w64-${{ matrix.arch }}-boost mingw-w64-${{ matrix.arch }}-openssl mingw-w64-${{ matrix.arch }}-miniupnpc
|
||||||
update: true
|
update: true
|
||||||
- name: build application
|
- name: Build application
|
||||||
run: |
|
run: |
|
||||||
mkdir -p obj/Win32 obj/libi2pd obj/libi2pd_client obj/daemon
|
mkdir -p obj/Win32 obj/libi2pd obj/libi2pd_client obj/daemon
|
||||||
make USE_UPNP=yes DEBUG=no -j3
|
make USE_UPNP=yes DEBUG=no USE_GIT_VERSION=yes -j3
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
|
name: i2pd-${{ matrix.arch_short }}.exe
|
||||||
|
path: i2pd.exe
|
||||||
|
build-xp:
|
||||||
|
name: Building for Windows XP
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Setup MSYS2
|
||||||
|
uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
msystem: MINGW32
|
||||||
|
install: base-devel git mingw-w64-i686-gcc mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-miniupnpc
|
||||||
|
update: true
|
||||||
|
- name: Build WinXP-capable CRT packages
|
||||||
|
run: |
|
||||||
|
git clone https://github.com/msys2/MINGW-packages
|
||||||
|
pushd MINGW-packages
|
||||||
|
pushd mingw-w64-headers-git
|
||||||
|
sed -i 's/0x601/0x501/' PKGBUILD
|
||||||
|
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm
|
||||||
|
pacman --noconfirm -U mingw-w64-i686-headers-git-*-any.pkg.tar.zst
|
||||||
|
popd
|
||||||
|
pushd mingw-w64-crt-git
|
||||||
|
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm
|
||||||
|
pacman --noconfirm -U mingw-w64-i686-crt-git-*-any.pkg.tar.zst
|
||||||
|
popd
|
||||||
|
pushd mingw-w64-winpthreads-git
|
||||||
|
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm
|
||||||
|
pacman --noconfirm -U mingw-w64-i686-libwinpthread-git-*-any.pkg.tar.zst mingw-w64-i686-winpthreads-git-*-any.pkg.tar.zst
|
||||||
|
popd
|
||||||
|
popd
|
||||||
|
- name: Build application
|
||||||
|
run: |
|
||||||
|
mkdir -p obj/Win32 obj/libi2pd obj/libi2pd_client obj/daemon
|
||||||
|
make USE_UPNP=yes DEBUG=no USE_GIT_VERSION=yes USE_WINXP_FLAGS=yes -j3
|
||||||
|
- name: Upload artifacts
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: i2pd-xp.exe
|
||||||
path: i2pd.exe
|
path: i2pd.exe
|
||||||
|
|
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
|
@ -49,7 +49,7 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install devscripts
|
sudo apt-get install devscripts
|
||||||
debchange -v "`git describe --tags`-stretch" -M --distribution stretch "trunk build"
|
debchange -v "`git describe --tags`-stretch" -b -M --distribution stretch "trunk build"
|
||||||
- uses: singingwolfboy/build-dpkg-stretch@v1
|
- uses: singingwolfboy/build-dpkg-stretch@v1
|
||||||
id: build
|
id: build
|
||||||
with:
|
with:
|
||||||
|
@ -73,7 +73,7 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install devscripts
|
sudo apt-get install devscripts
|
||||||
debchange -v "`git describe --tags`-buster" -M --distribution buster "trunk build"
|
debchange -v "`git describe --tags`-buster" -b -M --distribution buster "trunk build"
|
||||||
- uses: singingwolfboy/build-dpkg-buster@v1
|
- uses: singingwolfboy/build-dpkg-buster@v1
|
||||||
id: build
|
id: build
|
||||||
with:
|
with:
|
||||||
|
|
9
.github/workflows/docker.yml
vendored
9
.github/workflows/docker.yml
vendored
|
@ -1,6 +1,11 @@
|
||||||
name: Build containers
|
name: Build containers
|
||||||
|
|
||||||
on: [push]
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- openssl
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker:
|
docker:
|
||||||
|
@ -58,6 +63,8 @@ jobs:
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
purplei2p/i2pd:latest
|
purplei2p/i2pd:latest
|
||||||
|
purplei2p/i2pd:latest-release
|
||||||
purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
|
purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
|
||||||
ghcr.io/purplei2p/i2pd:latest
|
ghcr.io/purplei2p/i2pd:latest
|
||||||
|
ghcr.io/purplei2p/i2pd:latest-release
|
||||||
ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
|
ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
|
||||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -260,6 +260,7 @@ docs/generated
|
||||||
build/Makefile
|
build/Makefile
|
||||||
|
|
||||||
# debian stuff
|
# debian stuff
|
||||||
|
debian/i2pd.1.gz
|
||||||
.pc/
|
.pc/
|
||||||
|
|
||||||
# qt
|
# qt
|
||||||
|
|
89
ChangeLog
89
ChangeLog
|
@ -1,6 +1,95 @@
|
||||||
# for this file format description,
|
# for this file format description,
|
||||||
# see https://github.com/olivierlacan/keep-a-changelog
|
# see https://github.com/olivierlacan/keep-a-changelog
|
||||||
|
|
||||||
|
## [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
|
||||||
|
- Drop routers older than 6 months on start
|
||||||
|
- Localization to German
|
||||||
|
- Don't send streaming ack too frequently
|
||||||
|
- Select compatible outbound tunnel for I2CP messages
|
||||||
|
- Restart webconsole's acceptor in case of exception
|
||||||
|
### Changed
|
||||||
|
- Use builtin bitswap for endian on windows
|
||||||
|
- Send SessionCreated before connection close if clock skew
|
||||||
|
- Try another floodfill for publishing if no compatible tunnels found
|
||||||
|
- Reduce memory usage for RouterInfo structures
|
||||||
|
- Avoid duplicated addresses in RouterInfo. Check presence of netId and version
|
||||||
|
- Use TCP/IP sockets for I2CP on Android instead local sockets
|
||||||
|
- Return uptime as integer in I2PControl
|
||||||
|
- Reseed servers list/cerificates
|
||||||
|
- Webconsole's dark style colors
|
||||||
|
### Fixed
|
||||||
|
- Attempt to use Yggdrasil on start on Android
|
||||||
|
- Attempts to send peer tests to itself
|
||||||
|
- Severe packets drop in SSU
|
||||||
|
- Crash on tunnel tests
|
||||||
|
- Loading addressbook subscriptions from config
|
||||||
|
- Multiple I2CP session to the same destination
|
||||||
|
- Build on Apple Silicon
|
||||||
|
|
||||||
|
## [2.40.0] - 2021-11-29
|
||||||
|
### Added
|
||||||
|
- Keep alive parameter for client tunnels
|
||||||
|
- Support openssl 3.0.0
|
||||||
|
- Localization to Armenian
|
||||||
|
- Show git commit info in version
|
||||||
|
- Windows menu item for opening datadir
|
||||||
|
- Reseed if too few floodfills
|
||||||
|
- Don't publish old and replacing tunnel in LeaseSet
|
||||||
|
- Webconsole light/dark theme depending on system settings (via CSS)
|
||||||
|
### Changed
|
||||||
|
- Set gzip compression to false by default
|
||||||
|
- Build tunnel through ECIES routers only
|
||||||
|
- Removed ElGamal support for tunnels
|
||||||
|
- Moved webconsole resources to separate file
|
||||||
|
- Pick tunnels with compatible transport with another tunnel of floodfill
|
||||||
|
- Use common cleanup timer for all SSU sessions
|
||||||
|
- Reduced memory usage
|
||||||
|
- Reseed servers list
|
||||||
|
- i18n code called from ClientContext
|
||||||
|
### Fixed
|
||||||
|
- Tunnels reload
|
||||||
|
- Some typos in log messages
|
||||||
|
- Cleanup relay requests table
|
||||||
|
- Server tunnel is not published
|
||||||
|
- Build on GNU/Hurd. Disable pthread_setname_np
|
||||||
|
- Crash when incorrect sigtype used with blinding
|
||||||
|
|
||||||
## [2.39.0] - 2021-08-23
|
## [2.39.0] - 2021-08-23
|
||||||
### Added
|
### Added
|
||||||
- Short tunnel build messages
|
- Short tunnel build messages
|
||||||
|
|
30
Makefile
30
Makefile
|
@ -1,8 +1,10 @@
|
||||||
|
.DEFAULT_GOAL := all
|
||||||
|
|
||||||
SYS := $(shell $(CXX) -dumpmachine)
|
SYS := $(shell $(CXX) -dumpmachine)
|
||||||
|
|
||||||
ifneq (, $(findstring darwin, $(SYS)))
|
ifneq (, $(findstring darwin, $(SYS)))
|
||||||
SHARED_SUFFIX = dylib
|
SHARED_SUFFIX = dylib
|
||||||
else ifneq (, $(findstring mingw, $(SYS))$(findstring cygwin, $(SYS)))
|
else ifneq (, $(findstring mingw, $(SYS))$(findstring windows-gnu, $(SYS))$(findstring cygwin, $(SYS)))
|
||||||
SHARED_SUFFIX = dll
|
SHARED_SUFFIX = dll
|
||||||
else
|
else
|
||||||
SHARED_SUFFIX = so
|
SHARED_SUFFIX = so
|
||||||
|
@ -27,11 +29,16 @@ DAEMON_SRC_DIR := daemon
|
||||||
# import source files lists
|
# import source files lists
|
||||||
include filelist.mk
|
include filelist.mk
|
||||||
|
|
||||||
USE_AESNI := $(or $(USE_AESNI),yes)
|
USE_AESNI := $(or $(USE_AESNI),yes)
|
||||||
USE_STATIC := $(or $(USE_STATIC),no)
|
USE_STATIC := $(or $(USE_STATIC),no)
|
||||||
USE_MESHNET := $(or $(USE_MESHNET),no)
|
USE_UPNP := $(or $(USE_UPNP),no)
|
||||||
USE_UPNP := $(or $(USE_UPNP),no)
|
DEBUG := $(or $(DEBUG),yes)
|
||||||
DEBUG := $(or $(DEBUG),yes)
|
|
||||||
|
# for debugging purposes only, when commit hash needed in trunk builds in i2pd version string
|
||||||
|
USE_GIT_VERSION := $(or $(USE_GIT_VERSION),no)
|
||||||
|
|
||||||
|
# for MacOS only, waiting for "1", not "yes"
|
||||||
|
HOMEBREW := $(or $(HOMEBREW),0)
|
||||||
|
|
||||||
ifeq ($(DEBUG),yes)
|
ifeq ($(DEBUG),yes)
|
||||||
CXX_DEBUG = -g
|
CXX_DEBUG = -g
|
||||||
|
@ -53,18 +60,19 @@ else ifneq (, $(findstring linux, $(SYS))$(findstring gnu, $(SYS)))
|
||||||
else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS)))
|
else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS)))
|
||||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
||||||
include Makefile.bsd
|
include Makefile.bsd
|
||||||
else ifneq (, $(findstring mingw, $(SYS))$(findstring cygwin, $(SYS)))
|
else ifneq (, $(findstring mingw, $(SYS))$(findstring windows-gnu, $(SYS))$(findstring cygwin, $(SYS)))
|
||||||
DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32App.cpp Win32/Win32NetState.cpp
|
DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32App.cpp Win32/Win32Service.cpp Win32/Win32NetState.cpp
|
||||||
include Makefile.mingw
|
include Makefile.mingw
|
||||||
else # not supported
|
else # not supported
|
||||||
$(error Not supported platform)
|
$(error Not supported platform)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(USE_MESHNET),yes)
|
ifeq ($(USE_GIT_VERSION),yes)
|
||||||
NEEDED_CXXFLAGS += -DMESHNET
|
GIT_VERSION := $(shell git describe --tags)
|
||||||
|
NEEDED_CXXFLAGS += -DGITVER=\"$(GIT_VERSION)\"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
NEEDED_CXXFLAGS += -MMD -MP -I$(LIB_SRC_DIR) -I$(LIB_CLIENT_SRC_DIR) -I$(LANG_SRC_DIR)
|
NEEDED_CXXFLAGS += -MMD -MP -I$(LIB_SRC_DIR) -I$(LIB_CLIENT_SRC_DIR) -I$(LANG_SRC_DIR) -DOPENSSL_SUPPRESS_DEPRECATED
|
||||||
|
|
||||||
LIB_OBJS += $(patsubst %.cpp,obj/%.o,$(LIB_SRC))
|
LIB_OBJS += $(patsubst %.cpp,obj/%.o,$(LIB_SRC))
|
||||||
LIB_CLIENT_OBJS += $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC))
|
LIB_CLIENT_OBJS += $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC))
|
||||||
|
|
|
@ -39,13 +39,19 @@ ifeq ($(USE_AESNI),yes)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
install: all
|
install: all
|
||||||
install -d ${PREFIX}/bin ${PREFIX}/etc/i2pd ${PREFIX}/share/doc/i2pd ${PREFIX}/share/i2pd ${PREFIX}/share/man/man1 ${PREFIX}/var/lib/i2pd
|
install -d ${PREFIX}/bin
|
||||||
install -m 755 ${I2PD} ${PREFIX}/bin/
|
install -m 755 ${I2PD} ${PREFIX}/bin
|
||||||
|
install -d ${PREFIX}/etc ${PREFIX}/etc/i2pd ${PREFIX}/etc/i2pd/tunnels.conf.d
|
||||||
install -m 644 contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/etc/i2pd
|
install -m 644 contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/etc/i2pd
|
||||||
@cp -R contrib/certificates ${PREFIX}/share/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 -m 644 ChangeLog LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/share/doc/i2pd
|
||||||
@gzip debian/i2pd.1 && install debian/i2pd.1.gz ${PREFIX}/share/man/man1
|
install -d ${PREFIX}/share/i2pd
|
||||||
@ln -sf ${PREFIX}/share/i2pd/certificates ${PREFIX}/var/lib/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
|
||||||
|
@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/i2pd.conf ${PREFIX}/var/lib/i2pd/i2pd.conf
|
||||||
@ln -sf ${PREFIX}/etc/i2pd/subscriptions.txt ${PREFIX}/var/lib/i2pd/subscriptions.txt
|
@ln -sf ${PREFIX}/etc/i2pd/subscriptions.txt ${PREFIX}/var/lib/i2pd/subscriptions.txt
|
||||||
@ln -sf ${PREFIX}/etc/i2pd/tunnels.conf ${PREFIX}/var/lib/i2pd/tunnels.conf
|
@ln -sf ${PREFIX}/etc/i2pd/tunnels.conf ${PREFIX}/var/lib/i2pd/tunnels.conf
|
||||||
|
|
|
@ -62,3 +62,21 @@ ifneq (, $(findstring i386, $(SYS))$(findstring i686, $(SYS))$(findstring x86_64
|
||||||
NEEDED_CXXFLAGS += -D__AES__ -maes
|
NEEDED_CXXFLAGS += -D__AES__ -maes
|
||||||
endif
|
endif
|
||||||
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 -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
|
||||||
|
@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
|
||||||
|
@ln -sf ${PREFIX}/etc/i2pd/tunnels.conf ${PREFIX}/var/lib/i2pd/tunnels.conf
|
||||||
|
|
|
@ -3,19 +3,11 @@ USE_WIN32_APP := yes
|
||||||
|
|
||||||
WINDRES = windres
|
WINDRES = windres
|
||||||
|
|
||||||
CXXFLAGS := $(CXX_DEBUG) -DWIN32_LEAN_AND_MEAN -fPIC -msse
|
CXXFLAGS := $(CXX_DEBUG) -fPIC -msse
|
||||||
INCFLAGS = -I$(DAEMON_SRC_DIR) -IWin32
|
INCFLAGS = -I$(DAEMON_SRC_DIR) -IWin32
|
||||||
LDFLAGS := ${LD_DEBUG} -static
|
LDFLAGS := ${LD_DEBUG} -static
|
||||||
|
|
||||||
# detect proper flag for c++11 support by compilers
|
NEEDED_CXXFLAGS += -std=c++17 -DWIN32_LEAN_AND_MEAN
|
||||||
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 libraries suffix
|
||||||
BOOST_SUFFIX = -mt
|
BOOST_SUFFIX = -mt
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -14,6 +14,7 @@
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
#include "Win32Service.h"
|
||||||
#ifdef WIN32_APP
|
#ifdef WIN32_APP
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "Win32App.h"
|
#include "Win32App.h"
|
||||||
|
@ -39,6 +40,19 @@ namespace util
|
||||||
|
|
||||||
if (!Daemon_Singleton::init(argc, argv))
|
if (!Daemon_Singleton::init(argc, argv))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (isDaemon)
|
||||||
|
{
|
||||||
|
LogPrint(eLogDebug, "Daemon: running as service");
|
||||||
|
I2PService service((PSTR)SERVICE_NAME);
|
||||||
|
if (!I2PService::Run(service))
|
||||||
|
{
|
||||||
|
LogPrint(eLogError, "Daemon: Service failed to run w/err 0x%08lx\n", GetLastError());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ BEGIN
|
||||||
VALUE "FileDescription", "C++ I2P daemon"
|
VALUE "FileDescription", "C++ I2P daemon"
|
||||||
VALUE "FileVersion", I2PD_VERSION
|
VALUE "FileVersion", I2PD_VERSION
|
||||||
VALUE "InternalName", CODENAME
|
VALUE "InternalName", CODENAME
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2013-2020, The PurpleI2P Project"
|
VALUE "LegalCopyright", "Copyright (C) 2013-2022, The PurpleI2P Project"
|
||||||
VALUE "OriginalFilename", "i2pd"
|
VALUE "OriginalFilename", "i2pd"
|
||||||
VALUE "ProductName", "Purple I2P"
|
VALUE "ProductName", "Purple I2P"
|
||||||
VALUE "ProductVersion", I2P_VERSION
|
VALUE "ProductVersion", I2P_VERSION
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#define ID_RELOAD 2006
|
#define ID_RELOAD 2006
|
||||||
#define ID_ACCEPT_TRANSIT 2007
|
#define ID_ACCEPT_TRANSIT 2007
|
||||||
#define ID_DECLINE_TRANSIT 2008
|
#define ID_DECLINE_TRANSIT 2008
|
||||||
|
#define ID_DATADIR 2009
|
||||||
|
|
||||||
#define ID_TRAY_ICON 2050
|
#define ID_TRAY_ICON 2050
|
||||||
#define WM_TRAYICON (WM_USER + 1)
|
#define WM_TRAYICON (WM_USER + 1)
|
||||||
|
@ -49,7 +50,8 @@ namespace win32
|
||||||
{
|
{
|
||||||
HMENU hPopup = CreatePopupMenu();
|
HMENU hPopup = CreatePopupMenu();
|
||||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_CONSOLE, "Open &console");
|
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_CONSOLE, "Open &console");
|
||||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_APP, "Show app");
|
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_DATADIR, "Open &datadir");
|
||||||
|
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_APP, "&Show app");
|
||||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_ABOUT, "&About...");
|
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_STRING, ID_ABOUT, "&About...");
|
||||||
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
|
InsertMenu (hPopup, -1, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
|
||||||
if(!i2p::context.AcceptsTunnels())
|
if(!i2p::context.AcceptsTunnels())
|
||||||
|
@ -303,6 +305,12 @@ namespace win32
|
||||||
SetTimer(hWnd, FRAME_UPDATE_TIMER, 3000, NULL);
|
SetTimer(hWnd, FRAME_UPDATE_TIMER, 3000, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
case ID_DATADIR:
|
||||||
|
{
|
||||||
|
std::string datadir(i2p::fs::GetUTF8DataDir());
|
||||||
|
ShellExecute(NULL, "explore", datadir.c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ void SubscribeToEvents()
|
||||||
Result = pNetworkListManager->IsConnectedToInternet(&IsConnect);
|
Result = pNetworkListManager->IsConnectedToInternet(&IsConnect);
|
||||||
if (SUCCEEDED(Result)) {
|
if (SUCCEEDED(Result)) {
|
||||||
i2p::transport::transports.SetOnline (true);
|
i2p::transport::transports.SetOnline (true);
|
||||||
LogPrint(eLogInfo, "NetState: current state: ", IsConnect == VARIANT_TRUE ? "connected" : "disconnected");
|
LogPrint(eLogInfo, "NetState: Current state: ", IsConnect == VARIANT_TRUE ? "connected" : "disconnected");
|
||||||
}
|
}
|
||||||
|
|
||||||
Result = pNetworkListManager->QueryInterface(IID_IConnectionPointContainer, (void **)&pCPContainer);
|
Result = pNetworkListManager->QueryInterface(IID_IConnectionPointContainer, (void **)&pCPContainer);
|
||||||
|
@ -79,7 +79,7 @@ void UnSubscribeFromEvents()
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "NetState: received exception: ", ex.what ());
|
LogPrint (eLogError, "NetState: Received exception: ", ex.what ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
283
Win32/Win32Service.cpp
Normal file
283
Win32/Win32Service.cpp
Normal file
|
@ -0,0 +1,283 @@
|
||||||
|
/*
|
||||||
|
* 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 "Win32Service.h"
|
||||||
|
#include <assert.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "Daemon.h"
|
||||||
|
#include "Log.h"
|
||||||
|
|
||||||
|
I2PService *I2PService::s_service = NULL;
|
||||||
|
|
||||||
|
BOOL I2PService::isService()
|
||||||
|
{
|
||||||
|
BOOL bIsService = FALSE;
|
||||||
|
HWINSTA hWinStation = GetProcessWindowStation();
|
||||||
|
if (hWinStation != NULL)
|
||||||
|
{
|
||||||
|
USEROBJECTFLAGS uof = { 0 };
|
||||||
|
if (GetUserObjectInformation(hWinStation, UOI_FLAGS, &uof, sizeof(USEROBJECTFLAGS), NULL) && ((uof.dwFlags & WSF_VISIBLE) == 0))
|
||||||
|
{
|
||||||
|
bIsService = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bIsService;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL I2PService::Run(I2PService &service)
|
||||||
|
{
|
||||||
|
s_service = &service;
|
||||||
|
SERVICE_TABLE_ENTRY serviceTable[] =
|
||||||
|
{
|
||||||
|
{ service.m_name, ServiceMain },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
return StartServiceCtrlDispatcher(serviceTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WINAPI I2PService::ServiceMain(DWORD dwArgc, PSTR *pszArgv)
|
||||||
|
{
|
||||||
|
assert(s_service != NULL);
|
||||||
|
s_service->m_statusHandle = RegisterServiceCtrlHandler(
|
||||||
|
s_service->m_name, ServiceCtrlHandler);
|
||||||
|
if (s_service->m_statusHandle == NULL)
|
||||||
|
{
|
||||||
|
throw GetLastError();
|
||||||
|
}
|
||||||
|
s_service->Start(dwArgc, pszArgv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WINAPI I2PService::ServiceCtrlHandler(DWORD dwCtrl)
|
||||||
|
{
|
||||||
|
switch (dwCtrl)
|
||||||
|
{
|
||||||
|
case SERVICE_CONTROL_STOP: s_service->Stop(); break;
|
||||||
|
case SERVICE_CONTROL_PAUSE: s_service->Pause(); break;
|
||||||
|
case SERVICE_CONTROL_CONTINUE: s_service->Continue(); break;
|
||||||
|
case SERVICE_CONTROL_SHUTDOWN: s_service->Shutdown(); break;
|
||||||
|
case SERVICE_CONTROL_INTERROGATE: break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
I2PService::I2PService(PSTR pszServiceName,
|
||||||
|
BOOL fCanStop,
|
||||||
|
BOOL fCanShutdown,
|
||||||
|
BOOL fCanPauseContinue)
|
||||||
|
{
|
||||||
|
m_name = (pszServiceName == NULL) ? (PSTR)"" : pszServiceName;
|
||||||
|
m_statusHandle = NULL;
|
||||||
|
m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
||||||
|
m_status.dwCurrentState = SERVICE_START_PENDING;
|
||||||
|
|
||||||
|
DWORD dwControlsAccepted = 0;
|
||||||
|
if (fCanStop)
|
||||||
|
dwControlsAccepted |= SERVICE_ACCEPT_STOP;
|
||||||
|
if (fCanShutdown)
|
||||||
|
dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN;
|
||||||
|
if (fCanPauseContinue)
|
||||||
|
dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;
|
||||||
|
|
||||||
|
m_status.dwControlsAccepted = dwControlsAccepted;
|
||||||
|
m_status.dwWin32ExitCode = NO_ERROR;
|
||||||
|
m_status.dwServiceSpecificExitCode = 0;
|
||||||
|
m_status.dwCheckPoint = 0;
|
||||||
|
m_status.dwWaitHint = 0;
|
||||||
|
m_fStopping = FALSE;
|
||||||
|
// Create a manual-reset event that is not signaled at first to indicate
|
||||||
|
// the stopped signal of the service.
|
||||||
|
m_hStoppedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
|
if (m_hStoppedEvent == NULL)
|
||||||
|
{
|
||||||
|
throw GetLastError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
I2PService::~I2PService(void)
|
||||||
|
{
|
||||||
|
if (m_hStoppedEvent)
|
||||||
|
{
|
||||||
|
CloseHandle(m_hStoppedEvent);
|
||||||
|
m_hStoppedEvent = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2PService::Start(DWORD dwArgc, PSTR *pszArgv)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SetServiceStatus(SERVICE_START_PENDING);
|
||||||
|
OnStart(dwArgc, pszArgv);
|
||||||
|
SetServiceStatus(SERVICE_RUNNING);
|
||||||
|
}
|
||||||
|
catch (DWORD dwError)
|
||||||
|
{
|
||||||
|
LogPrint(eLogError, "Win32Service: Start error: ", dwError);
|
||||||
|
SetServiceStatus(SERVICE_STOPPED, dwError);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
LogPrint(eLogError, "Win32Service: failed to start: ", EVENTLOG_ERROR_TYPE);
|
||||||
|
SetServiceStatus(SERVICE_STOPPED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2PService::OnStart(DWORD dwArgc, PSTR *pszArgv)
|
||||||
|
{
|
||||||
|
LogPrint(eLogInfo, "Win32Service: in OnStart (", EVENTLOG_INFORMATION_TYPE, ")");
|
||||||
|
Daemon.start();
|
||||||
|
_worker = new std::thread(std::bind(&I2PService::WorkerThread, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2PService::WorkerThread()
|
||||||
|
{
|
||||||
|
while (!m_fStopping)
|
||||||
|
{
|
||||||
|
::Sleep(1000); // Simulate some lengthy operations.
|
||||||
|
}
|
||||||
|
// Signal the stopped event.
|
||||||
|
SetEvent(m_hStoppedEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2PService::Stop()
|
||||||
|
{
|
||||||
|
DWORD dwOriginalState = m_status.dwCurrentState;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SetServiceStatus(SERVICE_STOP_PENDING);
|
||||||
|
OnStop();
|
||||||
|
SetServiceStatus(SERVICE_STOPPED);
|
||||||
|
}
|
||||||
|
catch (DWORD dwError)
|
||||||
|
{
|
||||||
|
LogPrint(eLogInfo, "Win32Service: Stop error: ", dwError);
|
||||||
|
SetServiceStatus(dwOriginalState);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
LogPrint(eLogError, "Win32Service: Failed to stop: ", EVENTLOG_ERROR_TYPE);
|
||||||
|
SetServiceStatus(dwOriginalState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2PService::OnStop()
|
||||||
|
{
|
||||||
|
// Log a service stop message to the Application log.
|
||||||
|
LogPrint(eLogInfo, "Win32Service: in OnStop (", EVENTLOG_INFORMATION_TYPE, ")");
|
||||||
|
Daemon.stop();
|
||||||
|
m_fStopping = TRUE;
|
||||||
|
if (WaitForSingleObject(m_hStoppedEvent, INFINITE) != WAIT_OBJECT_0)
|
||||||
|
{
|
||||||
|
throw GetLastError();
|
||||||
|
}
|
||||||
|
_worker->join();
|
||||||
|
delete _worker;
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2PService::Pause()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SetServiceStatus(SERVICE_PAUSE_PENDING);
|
||||||
|
OnPause();
|
||||||
|
SetServiceStatus(SERVICE_PAUSED);
|
||||||
|
}
|
||||||
|
catch (DWORD dwError)
|
||||||
|
{
|
||||||
|
LogPrint(eLogError, "Win32Service: Pause error: ", dwError);
|
||||||
|
SetServiceStatus(SERVICE_RUNNING);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
LogPrint(eLogError, "Win32Service: Failed to pause: ", EVENTLOG_ERROR_TYPE);
|
||||||
|
SetServiceStatus(SERVICE_RUNNING);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2PService::OnPause()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2PService::Continue()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SetServiceStatus(SERVICE_CONTINUE_PENDING);
|
||||||
|
OnContinue();
|
||||||
|
SetServiceStatus(SERVICE_RUNNING);
|
||||||
|
}
|
||||||
|
catch (DWORD dwError)
|
||||||
|
{
|
||||||
|
LogPrint(eLogError, "Win32Service: Continue error: ", dwError);
|
||||||
|
SetServiceStatus(SERVICE_PAUSED);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
LogPrint(eLogError, "Win32Service: Failed to resume: ", EVENTLOG_ERROR_TYPE);
|
||||||
|
SetServiceStatus(SERVICE_PAUSED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2PService::OnContinue()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2PService::Shutdown()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
OnShutdown();
|
||||||
|
SetServiceStatus(SERVICE_STOPPED);
|
||||||
|
}
|
||||||
|
catch (DWORD dwError)
|
||||||
|
{
|
||||||
|
LogPrint(eLogError, "Win32Service: Shutdown error: ", dwError);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
LogPrint(eLogError, "Win32Service: Failed to shut down: ", EVENTLOG_ERROR_TYPE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2PService::OnShutdown()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2PService::SetServiceStatus(DWORD dwCurrentState,
|
||||||
|
DWORD dwWin32ExitCode,
|
||||||
|
DWORD dwWaitHint)
|
||||||
|
{
|
||||||
|
static DWORD dwCheckPoint = 1;
|
||||||
|
m_status.dwCurrentState = dwCurrentState;
|
||||||
|
m_status.dwWin32ExitCode = dwWin32ExitCode;
|
||||||
|
m_status.dwWaitHint = dwWaitHint;
|
||||||
|
m_status.dwCheckPoint =
|
||||||
|
((dwCurrentState == SERVICE_RUNNING) ||
|
||||||
|
(dwCurrentState == SERVICE_STOPPED)) ?
|
||||||
|
0 : dwCheckPoint++;
|
||||||
|
|
||||||
|
::SetServiceStatus(m_statusHandle, &m_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
//*****************************************************************************
|
||||||
|
|
||||||
|
void FreeHandles(SC_HANDLE schSCManager, SC_HANDLE schService)
|
||||||
|
{
|
||||||
|
if (schSCManager)
|
||||||
|
{
|
||||||
|
CloseServiceHandle(schSCManager);
|
||||||
|
schSCManager = NULL;
|
||||||
|
}
|
||||||
|
if (schService)
|
||||||
|
{
|
||||||
|
CloseServiceHandle(schService);
|
||||||
|
schService = NULL;
|
||||||
|
}
|
||||||
|
}
|
63
Win32/Win32Service.h
Normal file
63
Win32/Win32Service.h
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
* 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 WIN_32_SERVICE_H__
|
||||||
|
#define WIN_32_SERVICE_H__
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#define SERVICE_NAME "i2pdService"
|
||||||
|
|
||||||
|
class I2PService
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
I2PService(PSTR pszServiceName,
|
||||||
|
BOOL fCanStop = TRUE,
|
||||||
|
BOOL fCanShutdown = TRUE,
|
||||||
|
BOOL fCanPauseContinue = FALSE);
|
||||||
|
|
||||||
|
virtual ~I2PService(void);
|
||||||
|
|
||||||
|
static BOOL isService();
|
||||||
|
static BOOL Run(I2PService &service);
|
||||||
|
void Stop();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
virtual void OnStart(DWORD dwArgc, PSTR *pszArgv);
|
||||||
|
virtual void OnStop();
|
||||||
|
virtual void OnPause();
|
||||||
|
virtual void OnContinue();
|
||||||
|
virtual void OnShutdown();
|
||||||
|
void SetServiceStatus(DWORD dwCurrentState,
|
||||||
|
DWORD dwWin32ExitCode = NO_ERROR,
|
||||||
|
DWORD dwWaitHint = 0);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv);
|
||||||
|
static void WINAPI ServiceCtrlHandler(DWORD dwCtrl);
|
||||||
|
void WorkerThread();
|
||||||
|
void Start(DWORD dwArgc, PSTR *pszArgv);
|
||||||
|
void Pause();
|
||||||
|
void Continue();
|
||||||
|
void Shutdown();
|
||||||
|
static I2PService* s_service;
|
||||||
|
PSTR m_name;
|
||||||
|
SERVICE_STATUS m_status;
|
||||||
|
SERVICE_STATUS_HANDLE m_statusHandle;
|
||||||
|
|
||||||
|
BOOL m_fStopping;
|
||||||
|
HANDLE m_hStoppedEvent;
|
||||||
|
|
||||||
|
std::thread* _worker;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WIN_32_SERVICE_H__
|
|
@ -1,6 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 2.8.12)
|
cmake_minimum_required(VERSION 3.7)
|
||||||
# this addresses CMP0059 with CMake > 3.3 for PCH flags
|
cmake_policy(VERSION 3.7)
|
||||||
cmake_policy(VERSION 2.8.12)
|
|
||||||
project("i2pd")
|
project("i2pd")
|
||||||
|
|
||||||
# for debugging
|
# for debugging
|
||||||
|
@ -18,14 +17,13 @@ option(WITH_LIBRARY "Build library" ON)
|
||||||
option(WITH_BINARY "Build binary" ON)
|
option(WITH_BINARY "Build binary" ON)
|
||||||
option(WITH_STATIC "Static build" OFF)
|
option(WITH_STATIC "Static build" OFF)
|
||||||
option(WITH_UPNP "Include support for UPnP client" OFF)
|
option(WITH_UPNP "Include support for UPnP client" OFF)
|
||||||
option(WITH_PCH "Use precompiled header" OFF)
|
option(WITH_GIT_VERSION "Use git commit info as version" OFF)
|
||||||
option(WITH_MESHNET "Build for cjdns test network" OFF)
|
|
||||||
option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF)
|
option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF)
|
||||||
option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF)
|
option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF)
|
||||||
|
|
||||||
# paths
|
# paths
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules")
|
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules")
|
||||||
set(CMAKE_SOURCE_DIR "..")
|
set(CMAKE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
||||||
|
|
||||||
#Handle paths nicely
|
#Handle paths nicely
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
@ -91,14 +89,20 @@ set(DAEMON_SRC
|
||||||
"${DAEMON_SRC_DIR}/UPnP.cpp"
|
"${DAEMON_SRC_DIR}/UPnP.cpp"
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WITH_MESHNET)
|
|
||||||
add_definitions(-DMESHNET)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WITH_UPNP)
|
if(WITH_UPNP)
|
||||||
add_definitions(-DUSE_UPNP)
|
add_definitions(-DUSE_UPNP)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_GIT_VERSION)
|
||||||
|
include(GetGitRevisionDescription)
|
||||||
|
git_describe(GIT_VERSION)
|
||||||
|
add_definitions(-DGITVER="${GIT_VERSION}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
add_definitions(-DMAC_OSX)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch -Wno-unused-parameter")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch -Wno-unused-parameter")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic")
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic")
|
||||||
# TODO: The following is incompatible with static build and enabled hardening for OpenWRT.
|
# TODO: The following is incompatible with static build and enabled hardening for OpenWRT.
|
||||||
|
@ -168,24 +172,13 @@ endif()
|
||||||
|
|
||||||
|
|
||||||
# libraries
|
# 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)
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
if(IOS)
|
find_package(Threads REQUIRED)
|
||||||
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)
|
if(WITH_STATIC)
|
||||||
set(Boost_USE_STATIC_LIBS ON)
|
set(Boost_USE_STATIC_LIBS ON)
|
||||||
set(Boost_USE_STATIC_RUNTIME ON)
|
set(Boost_USE_STATIC_RUNTIME ON)
|
||||||
|
set(OPENSSL_USE_STATIC_LIBS ON)
|
||||||
set(BUILD_SHARED_LIBS OFF)
|
set(BUILD_SHARED_LIBS OFF)
|
||||||
if(${CMAKE_CXX_COMPILER} MATCHES ".*-openwrt-.*")
|
if(${CMAKE_CXX_COMPILER} MATCHES ".*-openwrt-.*")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
||||||
|
@ -200,23 +193,6 @@ 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)
|
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()
|
endif()
|
||||||
|
|
||||||
if(WITH_PCH)
|
|
||||||
include_directories(BEFORE ${CMAKE_BINARY_DIR})
|
|
||||||
add_library(stdafx STATIC "${LIBI2PD_SRC_DIR}/stdafx.cpp")
|
|
||||||
string(TOUPPER ${CMAKE_BUILD_TYPE} BTU)
|
|
||||||
get_directory_property(DEFS DEFINITIONS)
|
|
||||||
string(REPLACE " " ";" FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_${BTU}} ${DEFS}")
|
|
||||||
add_custom_command(TARGET stdafx PRE_BUILD
|
|
||||||
COMMAND ${CMAKE_CXX_COMPILER} ${FLAGS} -c ${CMAKE_CURRENT_SOURCE_DIR}/../libi2pd/stdafx.h -o ${CMAKE_BINARY_DIR}/stdafx.h.gch
|
|
||||||
)
|
|
||||||
target_compile_options(libi2pd PRIVATE -include libi2pd/stdafx.h)
|
|
||||||
target_compile_options(libi2pdclient PRIVATE -include libi2pd/stdafx.h)
|
|
||||||
target_compile_options(libi2pdlang PRIVATE -include libi2pd/stdafx.h)
|
|
||||||
target_link_libraries(libi2pd stdafx)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
target_link_libraries(libi2pdclient libi2pd libi2pdlang)
|
|
||||||
|
|
||||||
find_package(Boost COMPONENTS system filesystem program_options date_time REQUIRED)
|
find_package(Boost COMPONENTS system filesystem program_options date_time REQUIRED)
|
||||||
if(NOT DEFINED Boost_INCLUDE_DIRS)
|
if(NOT DEFINED Boost_INCLUDE_DIRS)
|
||||||
message(SEND_ERROR "Boost is not found, or your boost version was below 1.46. Please download Boost!")
|
message(SEND_ERROR "Boost is not found, or your boost version was below 1.46. Please download Boost!")
|
||||||
|
@ -227,6 +203,10 @@ if(NOT DEFINED OPENSSL_INCLUDE_DIR)
|
||||||
message(SEND_ERROR "Could not find OpenSSL. Please download and install it first!")
|
message(SEND_ERROR "Could not find OpenSSL. Please download and install it first!")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(OPENSSL_VERSION VERSION_GREATER_EQUAL "3.0.0")
|
||||||
|
add_definitions(-DOPENSSL_SUPPRESS_DEPRECATED)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(WITH_UPNP)
|
if(WITH_UPNP)
|
||||||
find_package(MiniUPnPc REQUIRED)
|
find_package(MiniUPnPc REQUIRED)
|
||||||
if(NOT MINIUPNPC_FOUND)
|
if(NOT MINIUPNPC_FOUND)
|
||||||
|
@ -244,15 +224,7 @@ endif()
|
||||||
# load includes
|
# load includes
|
||||||
include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR})
|
include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR})
|
||||||
|
|
||||||
# warn if for meshnet
|
include(CheckAtomic)
|
||||||
if(WITH_MESHNET)
|
|
||||||
message(STATUS "Building for testnet")
|
|
||||||
message(WARNING "This build will NOT work on mainline i2p")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT MSYS)
|
|
||||||
include(CheckAtomic)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# show summary
|
# show summary
|
||||||
message(STATUS "---------------------------------------")
|
message(STATUS "---------------------------------------")
|
||||||
|
@ -269,8 +241,7 @@ message(STATUS " LIBRARY : ${WITH_LIBRARY}")
|
||||||
message(STATUS " BINARY : ${WITH_BINARY}")
|
message(STATUS " BINARY : ${WITH_BINARY}")
|
||||||
message(STATUS " STATIC BUILD : ${WITH_STATIC}")
|
message(STATUS " STATIC BUILD : ${WITH_STATIC}")
|
||||||
message(STATUS " UPnP : ${WITH_UPNP}")
|
message(STATUS " UPnP : ${WITH_UPNP}")
|
||||||
message(STATUS " PCH : ${WITH_PCH}")
|
message(STATUS " GIT VERSION : ${WITH_GIT_VERSION}")
|
||||||
message(STATUS " MESHNET : ${WITH_MESHNET}")
|
|
||||||
message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}")
|
message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}")
|
||||||
message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}")
|
message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}")
|
||||||
message(STATUS "---------------------------------------")
|
message(STATUS "---------------------------------------")
|
||||||
|
@ -282,31 +253,21 @@ if(WITH_BINARY)
|
||||||
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-static")
|
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-static")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WITH_PCH)
|
|
||||||
target_compile_options("${PROJECT_NAME}" PRIVATE -include libi2pd/stdafx.h)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(WITH_HARDENING AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
if(WITH_HARDENING AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-z relro -z now")
|
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-z relro -z now")
|
||||||
endif()
|
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
|
# 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)
|
list(GET Boost_LIBRARIES -1 LAST_Boost_LIBRARIES)
|
||||||
if(${LAST_Boost_LIBRARIES} MATCHES ".*pthread.*")
|
if(${LAST_Boost_LIBRARIES} MATCHES ".*pthread.*")
|
||||||
list(REMOVE_AT Boost_LIBRARIES -1)
|
list(REMOVE_AT Boost_LIBRARIES -1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
if(WITH_STATIC)
|
if(WITH_STATIC)
|
||||||
set(DL_LIB ${CMAKE_DL_LIBS})
|
set(DL_LIB ${CMAKE_DL_LIBS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(libi2pd ${Boost_LIBRARIES} ${ZLIB_LIBRARY})
|
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("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${UPNP_LIB} ${ZLIB_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MINGW_EXTRA} ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES})
|
|
||||||
|
|
||||||
install(TARGETS "${PROJECT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Runtime)
|
install(TARGETS "${PROJECT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Runtime)
|
||||||
set(APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
|
set(APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
|
||||||
|
|
|
@ -2,26 +2,25 @@
|
||||||
setlocal enableextensions enabledelayedexpansion
|
setlocal enableextensions enabledelayedexpansion
|
||||||
title Building i2pd
|
title Building i2pd
|
||||||
|
|
||||||
REM Copyright (c) 2013-2020, The PurpleI2P Project
|
REM Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
REM This file is part of Purple i2pd project and licensed under BSD3
|
REM This file is part of Purple i2pd project and licensed under BSD3
|
||||||
REM See full license text in LICENSE file at top of project tree
|
REM See full license text in LICENSE file at top of project tree
|
||||||
|
|
||||||
REM To use that script, you must have installed in your MSYS installation these packages:
|
REM To use that script, you must have installed in your MSYS installation these packages:
|
||||||
REM Base: git make zip
|
REM Base: git make zip
|
||||||
REM x86_64: mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-gcc
|
REM UCRT64: mingw-w64-ucrt-x86_64-boost mingw-w64-ucrt-x86_64-openssl mingw-w64-ucrt-x86_64-gcc
|
||||||
REM i686: mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-gcc
|
REM MINGW32: mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-gcc
|
||||||
|
|
||||||
REM setting up variables for MSYS
|
REM setting up variables for MSYS
|
||||||
REM Note: if you installed MSYS64 to different path, edit WD variable (only C:\msys64 needed to edit)!
|
REM Note: if you installed MSYS64 to different path, edit WD variable (only C:\msys64 needed to edit)
|
||||||
set "WD=C:\msys64\usr\bin\"
|
|
||||||
set MSYS2_PATH_TYPE=inherit
|
set MSYS2_PATH_TYPE=inherit
|
||||||
set CHERE_INVOKING=enabled_from_arguments
|
set CHERE_INVOKING=enabled_from_arguments
|
||||||
REM set MSYSTEM=MSYS
|
|
||||||
set MSYSTEM=MINGW32
|
set MSYSTEM=MINGW32
|
||||||
|
|
||||||
|
set "WD=C:\msys64\usr\bin\"
|
||||||
set "xSH=%WD%bash -lc"
|
set "xSH=%WD%bash -lc"
|
||||||
|
|
||||||
set "FILELIST=i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates contrib/tunnels.d"
|
set "FILELIST=i2pd.exe README.txt contrib/i2pd.conf contrib/tunnels.conf contrib/certificates contrib/tunnels.d contrib/webconsole"
|
||||||
|
|
||||||
REM detecting number of processors
|
REM detecting number of processors
|
||||||
set /a threads=%NUMBER_OF_PROCESSORS%
|
set /a threads=%NUMBER_OF_PROCESSORS%
|
||||||
|
@ -34,38 +33,73 @@ del /S build_*.log >> nul 2>&1
|
||||||
|
|
||||||
echo Receiving latest commit and cleaning up...
|
echo Receiving latest commit and cleaning up...
|
||||||
%xSH% "git checkout contrib/* && git pull && make clean" > build\build.log 2>&1
|
%xSH% "git checkout contrib/* && git pull && make clean" > build\build.log 2>&1
|
||||||
echo.
|
|
||||||
|
|
||||||
REM set to variable current commit hash
|
REM set to variable current commit hash
|
||||||
FOR /F "usebackq" %%a IN (`%xSH% 'git describe --tags'`) DO (
|
for /F "usebackq" %%a in (`%xSH% "git describe --tags"`) DO (
|
||||||
set tag=%%a
|
set tag=%%a
|
||||||
)
|
)
|
||||||
|
|
||||||
|
REM set to variable latest released tag
|
||||||
|
for /F "usebackq" %%b in (`%xSH% "git describe --abbrev=0"`) DO (
|
||||||
|
set reltag=%%b
|
||||||
|
)
|
||||||
|
|
||||||
|
echo Preparing configuration files and README for packaging...
|
||||||
|
|
||||||
%xSH% "echo To use configs and certificates, move all files and certificates folder from contrib directory here. > README.txt" >> nul
|
%xSH% "echo To use configs and certificates, move all files and certificates folder from contrib directory here. > README.txt" >> nul
|
||||||
|
|
||||||
REM converting configuration files to DOS format (usable in default notepad)
|
REM converting configuration files to DOS format (make usable in Windows Notepad)
|
||||||
%xSH% "unix2dos contrib/i2pd.conf contrib/tunnels.conf contrib/tunnels.d/*" >> build\build.log 2>&1
|
%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 SIGNPASS (
|
||||||
|
set "xSIGNPASSOPTS=/p ^"%SIGNPASS%^""
|
||||||
|
)
|
||||||
|
|
||||||
|
set "xSIGNOPTS=sign /tr http://timestamp.digicert.com /td sha256 /fd sha256 %xSIGNKEYOPTS% %xSIGNPASSOPTS%"
|
||||||
|
)
|
||||||
|
|
||||||
REM starting building
|
REM starting building
|
||||||
set MSYSTEM=MINGW32
|
set MSYSTEM=MINGW32
|
||||||
set bitness=32
|
set bitness=32
|
||||||
call :BUILDING
|
call :BUILDING
|
||||||
|
|
||||||
set MSYSTEM=MINGW64
|
set MSYSTEM=UCRT64
|
||||||
set bitness=64
|
set bitness=64
|
||||||
call :BUILDING
|
call :BUILDING
|
||||||
|
|
||||||
REM building for WinXP
|
REM build for Windows XP
|
||||||
set "WD=C:\msys64-xp\usr\bin\"
|
if exist C:\msys64-xp\ ( call :BUILDING_XP )
|
||||||
set MSYSTEM=MINGW32
|
|
||||||
set bitness=32
|
|
||||||
set "xSH=%WD%bash -lc"
|
|
||||||
call :BUILDING_XP
|
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
REM compile installer
|
REM compile installer
|
||||||
C:\PROGRA~2\INNOSE~1\ISCC.exe /dI2Pd_TextVer="%tag%" /dI2Pd_Ver="%tag%.0" build\win_installer.iss >> build\build.log 2>&1
|
echo Building installer...
|
||||||
|
C:\PROGRA~2\INNOSE~1\ISCC.exe /dI2Pd_TextVer="%tag%" /dI2Pd_Ver="%reltag%.0" build\win_installer.iss >> build\build.log 2>&1
|
||||||
|
|
||||||
|
REM Sign binary
|
||||||
|
if defined xSIGNOPTS (
|
||||||
|
"%xSIGNTOOL%" %xSIGNOPTS% build\setup_i2pd_v%tag%.exe
|
||||||
|
)
|
||||||
|
|
||||||
|
%xSH% "git checkout contrib/*" >> build\build.log 2>&1
|
||||||
del README.txt i2pd_x32.exe i2pd_x64.exe i2pd_xp.exe >> nul
|
del README.txt i2pd_x32.exe i2pd_x64.exe i2pd_xp.exe >> nul
|
||||||
|
|
||||||
echo Build complete...
|
echo Build complete...
|
||||||
|
@ -74,13 +108,42 @@ exit /b 0
|
||||||
|
|
||||||
:BUILDING
|
:BUILDING
|
||||||
%xSH% "make clean" >> nul
|
%xSH% "make clean" >> nul
|
||||||
echo Building i2pd %tag% for win%bitness%
|
echo Building i2pd %tag% for win%bitness%...
|
||||||
%xSH% "make DEBUG=no USE_UPNP=yes -j%threads% && cp i2pd.exe i2pd_x%bitness%.exe && zip -r9 build/i2pd_%tag%_win%bitness%_mingw.zip %FILELIST% && make clean" > build\build_win%bitness%_%tag%.log 2>&1
|
REM Build i2pd
|
||||||
|
%xSH% "make DEBUG=no USE_UPNP=yes -j%threads%" > build\build_win%bitness%_%tag%.log 2>&1
|
||||||
|
|
||||||
|
REM Sign binary
|
||||||
|
if defined xSIGNOPTS (
|
||||||
|
"%xSIGNTOOL%" %xSIGNOPTS% i2pd.exe
|
||||||
|
)
|
||||||
|
|
||||||
|
REM Copy binary for installer and create distribution archive
|
||||||
|
%xSH% "cp i2pd.exe i2pd_x%bitness%.exe && zip -r9 build/i2pd_%tag%_win%bitness%_mingw.zip %FILELIST%" >> build\build_win%bitness%_%tag%.log 2>&1
|
||||||
|
|
||||||
|
REM Clean work directory
|
||||||
|
%xSH% "make clean" >> build\build_win%bitness%_%tag%.log 2>&1
|
||||||
goto EOF
|
goto EOF
|
||||||
|
|
||||||
:BUILDING_XP
|
:BUILDING_XP
|
||||||
|
set MSYSTEM=MINGW32
|
||||||
|
set bitness=32
|
||||||
|
set "WD=C:\msys64-xp\usr\bin\"
|
||||||
|
set "xSH=%WD%bash -lc"
|
||||||
|
|
||||||
%xSH% "make clean" >> nul
|
%xSH% "make clean" >> nul
|
||||||
echo Building i2pd %tag% for winxp
|
echo Building i2pd %tag% for winxp...
|
||||||
%xSH% "make DEBUG=no USE_UPNP=yes USE_WINXP_FLAGS=yes -j%threads% && cp i2pd.exe i2pd_xp.exe && zip -r9 build/i2pd_%tag%_winxp_mingw.zip %FILELIST% && make clean" > build\build_winxp_%tag%.log 2>&1
|
%xSH% "make DEBUG=no USE_UPNP=yes USE_WINXP_FLAGS=yes -j%threads%" > build\build_winxp_%tag%.log 2>&1
|
||||||
|
|
||||||
|
REM Sign binary
|
||||||
|
if defined xSIGNOPTS (
|
||||||
|
"%xSIGNTOOL%" %xSIGNOPTS% i2pd.exe
|
||||||
|
)
|
||||||
|
|
||||||
|
REM Copy binary for installer and create distribution archive
|
||||||
|
%xSH% "cp i2pd.exe i2pd_xp.exe && zip -r9 build/i2pd_%tag%_winxp_mingw.zip %FILELIST%" >> build\build_winxp_%tag%.log 2>&1
|
||||||
|
|
||||||
|
REM Clean work directory
|
||||||
|
%xSH% "make clean" >> build\build_winxp_%tag%.log 2>&1
|
||||||
|
goto EOF
|
||||||
|
|
||||||
:EOF
|
:EOF
|
284
build/cmake_modules/GetGitRevisionDescription.cmake
Normal file
284
build/cmake_modules/GetGitRevisionDescription.cmake
Normal file
|
@ -0,0 +1,284 @@
|
||||||
|
# - 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()
|
43
build/cmake_modules/GetGitRevisionDescription.cmake.in
Normal file
43
build/cmake_modules/GetGitRevisionDescription.cmake.in
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#
|
||||||
|
# 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()
|
|
@ -1,16 +1,30 @@
|
||||||
|
# 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
|
||||||
|
|
||||||
# Based on the Qt 5 processor detection code, so should be very accurate
|
# Based on the Qt 5 processor detection code, so should be very accurate
|
||||||
# https://qt.gitorious.org/qt/qtbase/blobs/master/src/corelib/global/qprocessordetection.h
|
# https://github.com/qt/qtbase/blob/dev/src/corelib/global/qprocessordetection.h
|
||||||
# Currently handles arm (v5, v6, v7), x86 (32/64), ia64, and ppc (32/64)
|
# Currently handles arm (v5, v6, v7, v8), x86 (32/64), ia64, mips (32/64, mipsel, mips64el) and ppc (32/64)
|
||||||
|
|
||||||
# Regarding POWER/PowerPC, just as is noted in the Qt source,
|
# Regarding POWER/PowerPC, just as is noted in the Qt source,
|
||||||
# "There are many more known variants/revisions that we do not handle/detect."
|
# "There are many more known variants/revisions that we do not handle/detect."
|
||||||
|
|
||||||
set(archdetect_c_code "
|
set(archdetect_c_code "
|
||||||
#if defined(__arm__) || defined(__TARGET_ARCH_ARM)
|
#if defined(__arm__) || defined(__TARGET_ARCH_ARM)|| defined(_M_ARM) || defined(_M_ARM64) || defined(__aarch64__) || defined(__ARM64__)
|
||||||
|
#if defined(__ARM64_ARCH_8__) \\
|
||||||
|
|| defined(__aarch64__) \\
|
||||||
|
|| defined(__ARMv8__) \\
|
||||||
|
|| defined(__ARMv8_A__) \\
|
||||||
|
|| defined(_M_ARM64) \\
|
||||||
|
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 8)
|
||||||
|
#error cmake_ARCH arm64
|
||||||
#if defined(__ARM_ARCH_7__) \\
|
#if defined(__ARM_ARCH_7__) \\
|
||||||
|| defined(__ARM_ARCH_7A__) \\
|
|| defined(__ARM_ARCH_7A__) \\
|
||||||
|| defined(__ARM_ARCH_7R__) \\
|
|| defined(__ARM_ARCH_7R__) \\
|
||||||
|| defined(__ARM_ARCH_7M__) \\
|
|| defined(__ARM_ARCH_7M__) \\
|
||||||
|
|| defined(__ARM_ARCH_7S__) \\
|
||||||
|
|| defined(_ARM_ARCH_7) \\
|
||||||
|
|| defined(__CORE_CORTEXA__) \\
|
||||||
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 7)
|
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 7)
|
||||||
#error cmake_ARCH armv7
|
#error cmake_ARCH armv7
|
||||||
#elif defined(__ARM_ARCH_6__) \\
|
#elif defined(__ARM_ARCH_6__) \\
|
||||||
|
@ -23,6 +37,7 @@ set(archdetect_c_code "
|
||||||
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 6)
|
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 6)
|
||||||
#error cmake_ARCH armv6
|
#error cmake_ARCH armv6
|
||||||
#elif defined(__ARM_ARCH_5TEJ__) \\
|
#elif defined(__ARM_ARCH_5TEJ__) \\
|
||||||
|
|| defined(__ARM_ARCH_5TE__) \\
|
||||||
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 5)
|
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 5)
|
||||||
#error cmake_ARCH armv5
|
#error cmake_ARCH armv5
|
||||||
#else
|
#else
|
||||||
|
@ -34,6 +49,18 @@ set(archdetect_c_code "
|
||||||
#error cmake_ARCH x86_64
|
#error cmake_ARCH x86_64
|
||||||
#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
|
#elif defined(__ia64) || defined(__ia64__) || defined(_M_IA64)
|
||||||
#error cmake_ARCH ia64
|
#error cmake_ARCH ia64
|
||||||
|
#elif defined(__mips) || defined(__mips__) || defined(_M_MRX000)
|
||||||
|
#if defined(_MIPS_ARCH_MIPS64) || defined(__mips64)
|
||||||
|
#if defined(__MIPSEL__)
|
||||||
|
#error cmake_ARCH mips64el
|
||||||
|
#else
|
||||||
|
#error cmake_ARCH mips64
|
||||||
|
#endif
|
||||||
|
#elif defined(__MIPSEL__)
|
||||||
|
#error cmake_ARCH mipsel
|
||||||
|
#else
|
||||||
|
#error cmake_ARCH mips
|
||||||
|
#endif
|
||||||
#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \\
|
#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__) \\
|
||||||
|| defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \\
|
|| defined(_ARCH_COM) || defined(_ARCH_PWR) || defined(_ARCH_PPC) \\
|
||||||
|| defined(_M_MPPC) || defined(_M_PPC)
|
|| defined(_M_MPPC) || defined(_M_PPC)
|
||||||
|
@ -47,7 +74,7 @@ set(archdetect_c_code "
|
||||||
#error cmake_ARCH unknown
|
#error cmake_ARCH unknown
|
||||||
")
|
")
|
||||||
|
|
||||||
# Set ppc_support to TRUE before including this file or ppc and ppc64
|
# Set ppc_support to TRUE before including this file on ppc and ppc64
|
||||||
# will be treated as invalid architectures since they are no longer supported by Apple
|
# will be treated as invalid architectures since they are no longer supported by Apple
|
||||||
|
|
||||||
function(target_architecture output_var)
|
function(target_architecture output_var)
|
||||||
|
@ -67,12 +94,14 @@ function(target_architecture output_var)
|
||||||
foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES})
|
foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES})
|
||||||
if("${osx_arch}" STREQUAL "ppc" AND ppc_support)
|
if("${osx_arch}" STREQUAL "ppc" AND ppc_support)
|
||||||
set(osx_arch_ppc TRUE)
|
set(osx_arch_ppc TRUE)
|
||||||
|
elseif("${osx_arch}" STREQUAL "ppc64" AND ppc_support)
|
||||||
|
set(osx_arch_ppc64 TRUE)
|
||||||
elseif("${osx_arch}" STREQUAL "i386")
|
elseif("${osx_arch}" STREQUAL "i386")
|
||||||
set(osx_arch_i386 TRUE)
|
set(osx_arch_i386 TRUE)
|
||||||
elseif("${osx_arch}" STREQUAL "x86_64")
|
elseif("${osx_arch}" STREQUAL "x86_64")
|
||||||
set(osx_arch_x86_64 TRUE)
|
set(osx_arch_x86_64 TRUE)
|
||||||
elseif("${osx_arch}" STREQUAL "ppc64" AND ppc_support)
|
elseif("${osx_arch}" STREQUAL "arm64")
|
||||||
set(osx_arch_ppc64 TRUE)
|
set(osx_arch_arm64 TRUE)
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "Invalid OS X arch name: ${osx_arch}")
|
message(FATAL_ERROR "Invalid OS X arch name: ${osx_arch}")
|
||||||
endif()
|
endif()
|
||||||
|
@ -83,6 +112,10 @@ function(target_architecture output_var)
|
||||||
list(APPEND ARCH ppc)
|
list(APPEND ARCH ppc)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(osx_arch_ppc64)
|
||||||
|
list(APPEND ARCH ppc64)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(osx_arch_i386)
|
if(osx_arch_i386)
|
||||||
list(APPEND ARCH i386)
|
list(APPEND ARCH i386)
|
||||||
endif()
|
endif()
|
||||||
|
@ -91,8 +124,8 @@ function(target_architecture output_var)
|
||||||
list(APPEND ARCH x86_64)
|
list(APPEND ARCH x86_64)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(osx_arch_ppc64)
|
if(osx_arch_arm64)
|
||||||
list(APPEND ARCH ppc64)
|
list(APPEND ARCH arm64)
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
file(WRITE "${CMAKE_BINARY_DIR}/arch.c" "${archdetect_c_code}")
|
file(WRITE "${CMAKE_BINARY_DIR}/arch.c" "${archdetect_c_code}")
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
#define I2Pd_AppName "i2pd"
|
#define I2Pd_AppName "i2pd"
|
||||||
#define I2Pd_Publisher "PurpleI2P"
|
#define I2Pd_Publisher "PurpleI2P"
|
||||||
; Get application version from compiled binary
|
|
||||||
; Disabled to use definition from command line
|
|
||||||
;#define I2Pd_ver GetFileVersionString(AddBackslash(SourcePath) + "..\i2pd_x64.exe")
|
|
||||||
|
|
||||||
[Setup]
|
[Setup]
|
||||||
AppName={#I2Pd_AppName}
|
AppName={#I2Pd_AppName}
|
||||||
|
@ -27,7 +24,7 @@ ExtraDiskSpaceRequired=15
|
||||||
|
|
||||||
AppID={{621A23E0-3CF4-4BD6-97BC-4835EA5206A2}
|
AppID={{621A23E0-3CF4-4BD6-97BC-4835EA5206A2}
|
||||||
AppVerName={#I2Pd_AppName}
|
AppVerName={#I2Pd_AppName}
|
||||||
AppCopyright=Copyright (c) 2013-2020, The PurpleI2P Project
|
AppCopyright=Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
AppPublisherURL=http://i2pd.website/
|
AppPublisherURL=http://i2pd.website/
|
||||||
AppSupportURL=https://github.com/PurpleI2P/i2pd/issues
|
AppSupportURL=https://github.com/PurpleI2P/i2pd/issues
|
||||||
AppUpdatesURL=https://github.com/PurpleI2P/i2pd/releases
|
AppUpdatesURL=https://github.com/PurpleI2P/i2pd/releases
|
||||||
|
@ -47,6 +44,7 @@ Source: ..\contrib\subscriptions.txt; DestDir: {userappdata}\i2pd; Flags: onlyif
|
||||||
Source: ..\contrib\tunnels.conf; DestDir: {userappdata}\i2pd; Flags: onlyifdoesntexist
|
Source: ..\contrib\tunnels.conf; DestDir: {userappdata}\i2pd; Flags: onlyifdoesntexist
|
||||||
Source: ..\contrib\certificates\*; DestDir: {userappdata}\i2pd\certificates; Flags: onlyifdoesntexist recursesubdirs createallsubdirs
|
Source: ..\contrib\certificates\*; DestDir: {userappdata}\i2pd\certificates; Flags: onlyifdoesntexist recursesubdirs createallsubdirs
|
||||||
Source: ..\contrib\tunnels.d\*; DestDir: {userappdata}\i2pd\tunnels.d; Flags: onlyifdoesntexist recursesubdirs createallsubdirs
|
Source: ..\contrib\tunnels.d\*; DestDir: {userappdata}\i2pd\tunnels.d; Flags: onlyifdoesntexist recursesubdirs createallsubdirs
|
||||||
|
Source: ..\contrib\webconsole\*; DestDir: {userappdata}\i2pd\webconsole; Flags: onlyifdoesntexist recursesubdirs createallsubdirs
|
||||||
|
|
||||||
[Icons]
|
[Icons]
|
||||||
Name: {group}\I2Pd; Filename: {app}\i2pd.exe
|
Name: {group}\I2Pd; Filename: {app}\i2pd.exe
|
||||||
|
|
18
contrib/android_binary_only/.gitignore
vendored
18
contrib/android_binary_only/.gitignore
vendored
|
@ -1,18 +0,0 @@
|
||||||
gen
|
|
||||||
tests
|
|
||||||
bin
|
|
||||||
libs
|
|
||||||
log*
|
|
||||||
obj
|
|
||||||
.gradle
|
|
||||||
.idea
|
|
||||||
.externalNativeBuild
|
|
||||||
ant.properties
|
|
||||||
local.properties
|
|
||||||
build.sh
|
|
||||||
android.iml
|
|
||||||
build
|
|
||||||
gradle
|
|
||||||
gradlew
|
|
||||||
gradlew.bat
|
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
LOCAL_PATH := $(call my-dir)
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := i2pd
|
|
||||||
LOCAL_CPP_FEATURES := rtti exceptions
|
|
||||||
LOCAL_C_INCLUDES += $(IFADDRS_PATH) $(LIB_SRC_PATH) $(LIB_CLIENT_SRC_PATH) $(DAEMON_SRC_PATH)
|
|
||||||
LOCAL_STATIC_LIBRARIES := \
|
|
||||||
boost_system \
|
|
||||||
boost_date_time \
|
|
||||||
boost_filesystem \
|
|
||||||
boost_program_options \
|
|
||||||
crypto ssl \
|
|
||||||
miniupnpc
|
|
||||||
LOCAL_LDLIBS := -lz
|
|
||||||
|
|
||||||
LOCAL_SRC_FILES := $(IFADDRS_PATH)/ifaddrs.c \
|
|
||||||
$(wildcard $(LIB_SRC_PATH)/*.cpp)\
|
|
||||||
$(wildcard $(LIB_CLIENT_SRC_PATH)/*.cpp)\
|
|
||||||
$(DAEMON_SRC_PATH)/UnixDaemon.cpp \
|
|
||||||
$(DAEMON_SRC_PATH)/Daemon.cpp \
|
|
||||||
$(DAEMON_SRC_PATH)/UPnP.cpp \
|
|
||||||
$(DAEMON_SRC_PATH)/HTTPServer.cpp \
|
|
||||||
$(DAEMON_SRC_PATH)/I2PControl.cpp \
|
|
||||||
$(DAEMON_SRC_PATH)/i2pd.cpp
|
|
||||||
include $(BUILD_EXECUTABLE)
|
|
||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := boost_system
|
|
||||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_system.a
|
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
|
|
||||||
include $(PREBUILT_STATIC_LIBRARY)
|
|
||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := boost_date_time
|
|
||||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_date_time.a
|
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
|
|
||||||
include $(PREBUILT_STATIC_LIBRARY)
|
|
||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := boost_filesystem
|
|
||||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_filesystem.a
|
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
|
|
||||||
include $(PREBUILT_STATIC_LIBRARY)
|
|
||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := boost_program_options
|
|
||||||
LOCAL_SRC_FILES := $(BOOST_PATH)/boost-1_72_0/$(TARGET_ARCH_ABI)/lib/libboost_program_options.a
|
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(BOOST_PATH)/boost-1_72_0/include
|
|
||||||
include $(PREBUILT_STATIC_LIBRARY)
|
|
||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := crypto
|
|
||||||
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/$(TARGET_ARCH_ABI)/lib/libcrypto.a
|
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/include
|
|
||||||
include $(PREBUILT_STATIC_LIBRARY)
|
|
||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := ssl
|
|
||||||
LOCAL_SRC_FILES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/$(TARGET_ARCH_ABI)/lib/libssl.a
|
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(OPENSSL_PATH)/openssl-1.1.1a-clang/include
|
|
||||||
LOCAL_STATIC_LIBRARIES := crypto
|
|
||||||
include $(PREBUILT_STATIC_LIBRARY)
|
|
||||||
|
|
||||||
LOCAL_PATH := $(call my-dir)
|
|
||||||
include $(CLEAR_VARS)
|
|
||||||
LOCAL_MODULE := miniupnpc
|
|
||||||
LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnpc-2.1/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a
|
|
||||||
LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnpc-2.1/include
|
|
||||||
include $(PREBUILT_STATIC_LIBRARY)
|
|
|
@ -1,40 +0,0 @@
|
||||||
APP_ABI := all
|
|
||||||
#APP_ABI += x86
|
|
||||||
#APP_ABI += x86_64
|
|
||||||
#APP_ABI += armeabi-v7a
|
|
||||||
#APP_ABI += arm64-v8a
|
|
||||||
#can be android-3 but will fail for x86 since arch-x86 is not present at ndkroot/platforms/android-3/ . libz is taken from there.
|
|
||||||
APP_PLATFORM := android-14
|
|
||||||
|
|
||||||
NDK_TOOLCHAIN_VERSION := clang
|
|
||||||
APP_STL := c++_static
|
|
||||||
|
|
||||||
# Enable c++17 extensions in source code
|
|
||||||
APP_CPPFLAGS += -std=c++17 -fvisibility=default -fPIE
|
|
||||||
|
|
||||||
APP_CPPFLAGS += -DANDROID_BINARY -DANDROID -D__ANDROID__ -DUSE_UPNP
|
|
||||||
APP_LDFLAGS += -rdynamic -fPIE -pie
|
|
||||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
|
||||||
APP_CPPFLAGS += -DANDROID_ARM7A
|
|
||||||
endif
|
|
||||||
|
|
||||||
# Forcing debug optimization. Use `ndk-build NDK_DEBUG=1` instead.
|
|
||||||
#APP_OPTIM := debug
|
|
||||||
|
|
||||||
# git clone https://github.com/PurpleI2P/Boost-for-Android-Prebuilt.git -b boost-1_72_0
|
|
||||||
# git clone https://github.com/PurpleI2P/OpenSSL-for-Android-Prebuilt.git
|
|
||||||
# git clone https://github.com/PurpleI2P/MiniUPnP-for-Android-Prebuilt.git
|
|
||||||
# git clone https://github.com/PurpleI2P/android-ifaddrs.git
|
|
||||||
# change to your own
|
|
||||||
I2PD_LIBS_PATH = /path/to/libraries
|
|
||||||
BOOST_PATH = $(I2PD_LIBS_PATH)/Boost-for-Android-Prebuilt
|
|
||||||
OPENSSL_PATH = $(I2PD_LIBS_PATH)/OpenSSL-for-Android-Prebuilt
|
|
||||||
MINIUPNP_PATH = $(I2PD_LIBS_PATH)/MiniUPnP-for-Android-Prebuilt
|
|
||||||
IFADDRS_PATH = $(I2PD_LIBS_PATH)/android-ifaddrs
|
|
||||||
|
|
||||||
# don't change me
|
|
||||||
I2PD_SRC_PATH = $(PWD)/../..
|
|
||||||
|
|
||||||
LIB_SRC_PATH = $(I2PD_SRC_PATH)/libi2pd
|
|
||||||
LIB_CLIENT_SRC_PATH = $(I2PD_SRC_PATH)/libi2pd_client
|
|
||||||
DAEMON_SRC_PATH = $(I2PD_SRC_PATH)/daemon
|
|
2
contrib/android_binary_pack/.gitignore
vendored
2
contrib/android_binary_pack/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
||||||
archive
|
|
||||||
i2pd_*_android_binary.zip
|
|
|
@ -1,48 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Copyright (c) 2013-2020, 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
|
|
||||||
|
|
||||||
GITDESC=$(git describe --tags)
|
|
||||||
|
|
||||||
declare -A ABILIST=(
|
|
||||||
["armeabi-v7a"]="armv7l"
|
|
||||||
["arm64-v8a"]="aarch64"
|
|
||||||
["x86"]="x86"
|
|
||||||
["x86_64"]="x86_64"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Remove old files and archives
|
|
||||||
if [ -d archive ]; then
|
|
||||||
rm -r archive
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f ../i2pd_*_android_binary.zip ]; then
|
|
||||||
rm i2pd_*_android_binary.zip
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Prepare files for package
|
|
||||||
mkdir archive
|
|
||||||
|
|
||||||
for ABI in "${!ABILIST[@]}"; do
|
|
||||||
if [ -f ../android_binary_only/libs/${ABI}/i2pd ]; then
|
|
||||||
cp ../android_binary_only/libs/${ABI}/i2pd archive/i2pd-${ABILIST[$ABI]}
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
cp i2pd archive/i2pd
|
|
||||||
cp -rH ../android/assets/certificates archive/
|
|
||||||
cp -rH ../android/assets/tunnels.conf.d archive/
|
|
||||||
cp -H ../android/assets/i2pd.conf archive/
|
|
||||||
cp -H ../android/assets/tunnels.conf archive/
|
|
||||||
|
|
||||||
# Compress files
|
|
||||||
cd archive
|
|
||||||
zip -r6 ../i2pd_${GITDESC}_android_binary.zip .
|
|
||||||
|
|
||||||
# Remove temporary folder
|
|
||||||
cd ..
|
|
||||||
rm -r archive
|
|
|
@ -1,33 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Copyright (c) 2013-2020, 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
|
|
||||||
#
|
|
||||||
# That script written for use with Termux.
|
|
||||||
|
|
||||||
# https://stackoverflow.com/a/246128
|
|
||||||
SOURCE="${0}"
|
|
||||||
while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
|
|
||||||
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
|
|
||||||
SOURCE="$(readlink "$SOURCE")"
|
|
||||||
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
|
|
||||||
done
|
|
||||||
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
|
|
||||||
|
|
||||||
arch=$(uname -m)
|
|
||||||
|
|
||||||
screenfind=$(which screen)
|
|
||||||
if [ -z $screenfind ]; then
|
|
||||||
echo "Can't find 'screen' installed. That script needs it!";
|
|
||||||
exit 1;
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z i2pd-$arch ]; then
|
|
||||||
echo "Can't find i2pd binary for your archtecture.";
|
|
||||||
exit 1;
|
|
||||||
fi
|
|
||||||
|
|
||||||
screen -AmdS i2pd ./i2pd-$arch --datadir=$DIR
|
|
14
contrib/certificates/family/stormycloud.crt
Normal file
14
contrib/certificates/family/stormycloud.crt
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIICKDCCAc6gAwIBAgIUcPHZXtYSqGNRCD6z8gp79WUFtI0wCgYIKoZIzj0EAwIw
|
||||||
|
gZMxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEPMA0GA1UEBwwGQXVzdGlu
|
||||||
|
MRgwFgYDVQQKDA9TdG9ybXlDbG91ZCBJbmMxIzAhBgNVBAMMGnN0b3JteWNsb3Vk
|
||||||
|
LmZhbWlseS5pMnAubmV0MSQwIgYJKoZIhvcNAQkBFhVhZG1pbkBzdG9ybXljbG91
|
||||||
|
ZC5vcmcwHhcNMjIwMzE5MTU1MjU2WhcNMzIwMzE2MTU1MjU2WjCBkzELMAkGA1UE
|
||||||
|
BhMCVVMxDjAMBgNVBAgMBVRleGFzMQ8wDQYDVQQHDAZBdXN0aW4xGDAWBgNVBAoM
|
||||||
|
D1N0b3JteUNsb3VkIEluYzEjMCEGA1UEAwwac3Rvcm15Y2xvdWQuZmFtaWx5Lmky
|
||||||
|
cC5uZXQxJDAiBgkqhkiG9w0BCQEWFWFkbWluQHN0b3JteWNsb3VkLm9yZzBZMBMG
|
||||||
|
ByqGSM49AgEGCCqGSM49AwEHA0IABFUli0hvJEmowNjJVjbKEIWBJhqe973S4VdL
|
||||||
|
cJuA5yY3dC4Y998abWEox7/Y1BhnBbpJuiodA341bXKkLMXQy/kwCgYIKoZIzj0E
|
||||||
|
AwIDSAAwRQIgD12F/TfY3iV1/WDF7BSKgbD5g2MfELUIy1dtUlJQuJUCIQD69mZw
|
||||||
|
V1Z9j2x0ZsuirS3i6AMfVyTDj0RFS3U1jeHzIQ==
|
||||||
|
-----END CERTIFICATE-----
|
33
contrib/certificates/reseed/echelon3_at_mail.i2p.crt
Normal file
33
contrib/certificates/reseed/echelon3_at_mail.i2p.crt
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFyzCCA7OgAwIBAgIRALWNWsnQ0Vmn/99iCNT7cdQwDQYJKoZIhvcNAQELBQAw
|
||||||
|
cTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE
|
||||||
|
ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGjAYBgNVBAMM
|
||||||
|
EWVjaGVsb24zQG1haWwuaTJwMB4XDTIxMTEyOTE5MzU1OVoXDTMxMTEyOTE5MzU1
|
||||||
|
OVowcTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwG
|
||||||
|
A1UEChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGjAYBgNV
|
||||||
|
BAMMEWVjaGVsb24zQG1haWwuaTJwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
|
||||||
|
CgKCAgEA3pccNiQWJUS1t3QHK7rBCNKAsM2dz4szN3+3SrDy1w+rOrK8Vt5aypPU
|
||||||
|
QYUQwG+odjEPacuoRtO/W14KJl5yAI3eQS+X/cYDXmxvfm4zx5JRumYptXwJD57G
|
||||||
|
rlPHnFvk8R+Hvh+/UyqgSAZ9ZaKjEzYK4AtbYEXtopaM4U2VYN8xKjvKyWlhPdxo
|
||||||
|
kI3//qcTlSqGHHeHrkItLG1LubM1EnPu+9zI2WN2zBBRcm8ZtWqHoqFJ1zgJr/49
|
||||||
|
nMK8Lnb3I54ctva8x5+gsSk4dbG/mMsOIZekFqYJJs3+u9w5fmOYI7v9GlQr7UhE
|
||||||
|
G3MwjJ5Cj1LmLVlz/4LApZrDSd2JvwIUdGL3UW8+blaTeCPKIRvmsTeRxo1gORMF
|
||||||
|
ZH0dg39722lK7ScwOlOUX9ggzRUlYCmvnjQJZGJEUoP68QxjlQfkXZyffmMfvm6K
|
||||||
|
V6mcZ5aHMGO1lYAl40kWNJ0jGpmxJqTDhNFDEKr0TlRGVxXGWzObEOrcJ8ysRMc1
|
||||||
|
x6oXQhh79HXZcKwhZaXLx23ZvVoTfhRm4JH0SSP6XqQm35j4NI1SllEsDns29wU3
|
||||||
|
Re4wOWJCCYlPG3CtY32CinwQRoVgtiJk18W8+Pxw7sBFq8sL5L0Z+5bB6nTkBfV6
|
||||||
|
7OrZGWL0i344zQE0e3yIsLih+5Wyqw6RSSMysenl3alnUB9EvE0CAwEAAaNeMFww
|
||||||
|
DgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAP
|
||||||
|
BgNVHRMBAf8EBTADAQH/MBoGA1UdDgQTBBFlY2hlbG9uM0BtYWlsLmkycDANBgkq
|
||||||
|
hkiG9w0BAQsFAAOCAgEAaUMnMYtNFBl9dFON6e4EjYo53Wknj61uIVO11dvLqjnh
|
||||||
|
7X6guPML+GgNZsPQGLu7Bqw4hVgy/cV5AlFc7SXOhzpaYo1ycpjg3Ws1VK2wrk7+
|
||||||
|
4bvUThNcS1KZVFDdRE62549rYNfYNfPxXvccOTW9meTCC1kLHerh65ySDr9J02O6
|
||||||
|
o5Mf685PgBasBH6dlosOLTtee2gRLNFcAluQYKerawS1gDys5239UNHPCqTgO+Od
|
||||||
|
FiKfl48OIOzPGLKEf4lXC+lkwZElewShrHhzd8aGueedTi0UHOtQuY7ocsofqXc8
|
||||||
|
OnyT/y2X6wn/YkzviKgfxYDSI7FJiUgXCPcT0jUNmuwR168yL5BfzoQmrCvlOOQg
|
||||||
|
P7ibdBJ6UkL8pRpv/SYpvaX/kf4agYtwh5IL9FzNCwNu54ZC6JilLUhYAU38Eolq
|
||||||
|
OZ/cGiMoSFQIeBPvB3cdsqEud9W4P+MqN5A76fMzdVV77lGsIS1eCGMceR3CjOiF
|
||||||
|
6SdAskcBZWhFiRNQweC0iv57/nPCeTCuNAqbZSHd7zC1AKhNmmsKSJUJQCGijcce
|
||||||
|
P8Gl0AFfZneN2bVEFvJ/zd71pD8ll1Gkju16bfdWn0V4NRaxFiXNr2bL+ah9blud
|
||||||
|
EXOomE3R6ow1QZk+Gnpy3wh9jfwlrJuFoANvHnv4WREbdjwr//71XjBri5p1wPE=
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -1,32 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIFfzCCA2egAwIBAgIESg3kkzANBgkqhkiG9w0BAQ0FADBwMQswCQYDVQQGEwJY
|
|
||||||
WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt
|
|
||||||
b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UEAwwQZWNoZWxvbkBtYWls
|
|
||||||
LmkycDAeFw0xNDA3MzExNjQ3MDJaFw0yNDA3MzAxNjQ3MDJaMHAxCzAJBgNVBAYT
|
|
||||||
AlhYMQswCQYDVQQIEwJYWDELMAkGA1UEBxMCWFgxHjAcBgNVBAoTFUkyUCBBbm9u
|
|
||||||
eW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRkwFwYDVQQDDBBlY2hlbG9uQG1h
|
|
||||||
aWwuaTJwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAmcEgLwwhzLNe
|
|
||||||
XLOMSrhwB8hWpOhfjo4s6S/wjBtjjUc8nI3D0hSn3HY26p0rvcvNEWexPUpPULmC
|
|
||||||
exGkU463nu7PiFONiORI1eJAiUFHibRiaA7Wboyo38pO73KirwjG07Y+Ua0jp+HS
|
|
||||||
+4FQ/I/9H/bPplReTOU/6hmRbgQ69U8nE68HzZHQxP68yVJ2rPHSXMPhF4R1h0G1
|
|
||||||
1mCAT+TgTsnwHNGF77XHJnY4/M4e2cgycEZjZow36C3t2mNDVkMgF19QQeb9WmLR
|
|
||||||
zREn3nq9BJqHpUkn9yWw0kKXTZSds+7UxESfzf3BzK0+hky2fh5H+qbYAo2lz4yj
|
|
||||||
81MXTAu+4RRkg4DBLlF+2dkclhwQLxxzvkRC6tPkn5i33Yltg7EfzA9IoQ05potJ
|
|
||||||
I+iOcF+aStfFgFj9u3B5UkcF4P0cH1QD3c6BK4hIezQYqRoPly1gHqg+XdwjG/dr
|
|
||||||
4as7HA9FTz3p2E8nClpIC1x3hfgwAdfd29aeBxO1WW/z99iMF7TBAF+u5T86XEW1
|
|
||||||
WpknqCbTli36yJ8a5fPWxZHrryBRJT5yLxejjFeadtutBSwljiVFq+Y38VqwFivq
|
|
||||||
VLiBt7IxAsZ8iilgfnnnAvBH6chWfSKb4H7kB4TJvDiV96QmmvoEaWYNHZozMhyK
|
|
||||||
tO3b5w+xqbJXyCLA3Q75jD0km76hjcECAwEAAaMhMB8wHQYDVR0OBBYEFAHQcAam
|
|
||||||
QRS/EUhuCSr9pB4Ux0rYMA0GCSqGSIb3DQEBDQUAA4ICAQBq1+1QLmgLAjrTg3tb
|
|
||||||
4XKgAVICQRoBDNUEobQg3pYeUX9eFNya2RxNljuvYpwT80ilGMPOXcjddmr5ngiK
|
|
||||||
dbGRcuuJk9MPEHtPaPT3+JJlvKQ3B3g2wva2Wz2OAyLZUGQs389K4nTbwh4QF0n2
|
|
||||||
aHFL8BHiD62hiKnCoNaW4ZovUNNvOxo9lMyAiaFU2gqQNcdad8hP9EAllbvbxDx9
|
|
||||||
Tjww2UbwQUIHS9rna4Tlu+f0hDXTWIutc2A51W2fJCb7L3+lYO7Wv55ND/WtryLZ
|
|
||||||
XpMp27+MpuEnN3kQmz/l9R0hIJsWc/x9GQkjm5wEaIZEyTtenqwRKGmVCtAj0Pgv
|
|
||||||
jn1L3/lWmrNq+OZHb/QeyfKtA3nXfQKVmT98ewQiK/S5i1xIAXCJPytOD887b/o1
|
|
||||||
cdurTmCiZMwgiQ+HLJqCg3MDa5mvKqRkRdZXfE6aQWEcSbpAhpV15R17q7L+Fg0W
|
|
||||||
shLSNucxyGNU8PjiC/nOmqfqUiPiMltJjPmscxBLim8foyxjakC4+6N6m+Jzgznj
|
|
||||||
PocBehFAfKYj66XEwzIBN7Z2uuXoYH9YptkocFjTzvchcryVulDWZ4FWxreUMhpM
|
|
||||||
4oyjjhSB4tB9clXlwMqg577q3D6Ms0zLTqsztyPN3zr6jGev3jpVq7Q1GOlciHPv
|
|
||||||
JNJOWTH/Vas1W6XlwGcOOAARTQ==
|
|
||||||
-----END CERTIFICATE-----
|
|
32
contrib/certificates/reseed/hiduser0_at_mail.i2p.crt
Normal file
32
contrib/certificates/reseed/hiduser0_at_mail.i2p.crt
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFgTCCA2mgAwIBAgIETWAY1DANBgkqhkiG9w0BAQ0FADBxMQswCQYDVQQGEwJY
|
||||||
|
WDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMR4wHAYDVQQKDBVJMlAgQW5vbnlt
|
||||||
|
b3VzIE5ldHdvcmsxDDAKBgNVBAsMA0kyUDEaMBgGA1UEAwwRaGlkdXNlcjBAbWFp
|
||||||
|
bC5pMnAwHhcNMjExMjEzMTU0MDI3WhcNMzExMjExMTU0MDI3WjBxMQswCQYDVQQG
|
||||||
|
EwJYWDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMR4wHAYDVQQKDBVJMlAgQW5v
|
||||||
|
bnltb3VzIE5ldHdvcmsxDDAKBgNVBAsMA0kyUDEaMBgGA1UEAwwRaGlkdXNlcjBA
|
||||||
|
bWFpbC5pMnAwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXnjJ8UQ0f
|
||||||
|
lHHpfPMiHofBPSuL4sbOJY6fOXwPhSg/h6THh9DS/ZWmJXQ3qRD0glDVtv4/Dr/9
|
||||||
|
ldGQ5eltF9iCFXCQlMEy2HjQrBKq0nsl7RpYK12cyMaod0kkzCUk9ITLi9CmHM3Z
|
||||||
|
gQZcmG8TWjFEpDR+idx/QkQt2pcO4vzWlDit3Vh4ivnbX5jGQHbsVjQEMQWxr+pX
|
||||||
|
dsS+YQpjZ6RBmrooGTPO8QDOOeYLAn0lCjmffc/kzIH9E/p4/O0rOpyhVYbdxUD1
|
||||||
|
5wkqN9l4yrtxmORG/PudnRQQ0r4TUq8vsxfGY0Euo9IbhgXF2Parel1ZhDxB1WZV
|
||||||
|
VwWtgLIh9jGA1UMa8SYKnEfp8LWNZ3b3mUUnZb3kMrLk6jGYRWNsHmamhd4mC7AZ
|
||||||
|
qf/8lOkEIw3bPd3YguCDRVcLui5BwIEZmqXg8uoESxfO/sW3pBrN/8M7MkTex9kN
|
||||||
|
vjitGDDXvenK27qmNgZxbBlX72yTSfys7XTYTLnxZC8AwdAo2Wz9Z6HhGiPonf2h
|
||||||
|
vZkc9ZxuE0jFIrsbJra4X7iyjXgi4vV4ARNg/9Ft6F4/OIbECgeDcBQqq4TlT2bZ
|
||||||
|
EfWVrBbqXoj5vNsLigIkd+AyUNwPYEcB5IFSiiOh98pC7BH3pg0m8U5YBjxe1i+9
|
||||||
|
EQOOG0Qtx+JigXZHu6bGE0Twy9zy+UzoKQIDAQABoyEwHzAdBgNVHQ4EFgQUGK1b
|
||||||
|
0DkL6aLalcfBc/Uj/SF08C0wDQYJKoZIhvcNAQENBQADggIBAMpXM82bJDpH1TlH
|
||||||
|
TvhU3Z7nfZdvEhOQfujaFUYiuNripuEKcFGn948+DvAG0FUN+uNlJoqOVs8D7InD
|
||||||
|
gWlA9zpqw5Cl5Hij/Wns9QbXuAHJeA23fVUoaM2A6v9ifcIQ1A+rDuRQAo6/64KW
|
||||||
|
ChTg2e99RBpfGOyqgeh7tLLe0lPPekVpKHFuXabokaKRDuBcVHcUL4tWXe3dcyqa
|
||||||
|
Ej/PJrrS+nWL0EGZ4q80CEd2LPuDzPxNGCJt/R7ZfadENWajcgcXGceh1QBzozrB
|
||||||
|
SL/Ya6wF9SrsB7V/r5wX0LM4ZdDaLWbtmUe5Op0h/ZMH25Sa8xAXVz+O9L6sWSoO
|
||||||
|
FaiYTOvAiyyPz+nsxKa3xYryDHno7eKSt+hGOcaurhxbdZaEFY/CegEc73tCt9xK
|
||||||
|
e9qF8O/WkDLmixuErw3f5en4IfzGR7p3lJAwW/8WD8C6HS39h/eE7dVZNaWgtQnZ
|
||||||
|
SgGjgZMTJqTcQ3aZmfuCZefxGFok8w6AIkdbnd1pdMBRjYu8aXgl2hQSB9ZADDE9
|
||||||
|
R5d3rXi0PkSFLIvsNjVa5KXrZk/tB0Hpfmepq7CufBqjP/LG9TieRoXzLYUKFF74
|
||||||
|
QRwjP+y7AJ+VDUTpY1NV1P+k+2raubU2bOnLF3zL5DtyoyieGPhyeMMvp0fRIxdg
|
||||||
|
bSl5VHgPXHNM8mcnndMAuzvl7jEK
|
||||||
|
-----END CERTIFICATE-----
|
34
contrib/certificates/reseed/i2p-reseed_at_mk16.de.crt
Normal file
34
contrib/certificates/reseed/i2p-reseed_at_mk16.de.crt
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFzTCCA7WgAwIBAgIQeUqFi0fHNQopg6BZlBLhVzANBgkqhkiG9w0BAQsFADBy
|
||||||
|
MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK
|
||||||
|
ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEbMBkGA1UEAwwS
|
||||||
|
aTJwLXJlc2VlZEBtazE2LmRlMB4XDTIyMDIwNTE3MzkzM1oXDTMyMDIwNTE3Mzkz
|
||||||
|
M1owcjELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwG
|
||||||
|
A1UEChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGzAZBgNV
|
||||||
|
BAMMEmkycC1yZXNlZWRAbWsxNi5kZTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC
|
||||||
|
AgoCggIBAMYxs2D2xpN/8blGawvAlU9DemHIxApOEwaLNfh8aAvqEdB41NTqcx4U
|
||||||
|
H8VchSormCfkCvezuMHO+K2HX7ihEZ1v6tbr6aX6hY9UZUyDDYsKmJoB1oKEhddv
|
||||||
|
5UYfcWPE2eSykdFsWgTQD6Z+cRQWHEoCzb7qc+Jrw6KcnHMD0VrmBrEQPzTBxMHW
|
||||||
|
4HC97PVkSLJTDArnS6ZiX4IbWRPw/mbpJT6EoVZo8J/it0pdn/X4KodEXDcnEMSe
|
||||||
|
VRulfZH/nSmOOvKhoHPckmgz/u66BlnuSYXEIB0KfDIcAlSYiPDxGnAemTozJYXA
|
||||||
|
UVMeFMs+YE5wiPgzzu+vpC31xtZLq0gyaCfgEi1P9j2ES/8pH3Gw6W2OH4kBx+jO
|
||||||
|
TBsfI+ph6qFZ3WWT23MRVyl3ATuI/GHdczTxD9JaOn74lLI+Hnu8wXnyztVWkTMB
|
||||||
|
4sAnzjdeHkvNDyQ10vSaN0HnGfg6zuAuUSqFQujFF8Vg8ZCcsh8GouWfzYDvi9mj
|
||||||
|
9pfxx8v6UCC719I4J9CgFjWnn2Hqez3fO8fFulY61VPyCCZp4gKWbI2SIQP/n5gz
|
||||||
|
ecYJRrJoem+rYfEQ/fwxROsvm3fCO4D6dt7ILRuX286GDIw2qSvP1zZVAioMwSj3
|
||||||
|
9CAjKLwD/BhTRiMOlpaVv6IWqjtevbiaIKvbHTnoxvkGsDqe3gJhAgMBAAGjXzBd
|
||||||
|
MA4GA1UdDwEB/wQEAwIChDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEw
|
||||||
|
DwYDVR0TAQH/BAUwAwEB/zAbBgNVHQ4EFAQSaTJwLXJlc2VlZEBtazE2LmRlMA0G
|
||||||
|
CSqGSIb3DQEBCwUAA4ICAQAb+x6XpJdjpVYw2bvWIUbatQJwq0YaEW5W61xGLgIG
|
||||||
|
a37oll3YZbSY9Vk+N1cE0f61L3ya4Ioz6zlH/MO2zUG/dEk8vqdgIPUYJvyF7wwF
|
||||||
|
w3/G4VMaDKOJx4bAZNmaiRFGYNhCOhCnZx6uZGrLNIJ2Dc+mflrGmGwYphtXVV3e
|
||||||
|
Iv+ki3gSRgfXuMfKi4B5bLPnz7XDe4TSmwZZSRac4ly4KqmZUyntqbilRxaGTej3
|
||||||
|
VYJ1tac8yppyk5N3VopMQNmBarNZG16wSOTD7CtKgn382jgRW8cR7BMeqhORivp0
|
||||||
|
ZnPJFhzh4uthdlPdXXo6lxfvZjfiwlDPytvEu2QBz3urTgopGqRLcTBnLucWg9li
|
||||||
|
OSy9z7hNEnIN3iIJJAwI1wBdDa7K0h3PFBbIUa7X2ybn81VeNSfO25Lo8YTZEKsc
|
||||||
|
wcThJrNV6qOQv8rM/7aXugi6+VzPlCR+18iKRbebCnlqGR2dT1zFtj3negtOkrjo
|
||||||
|
LH4H6VUr3q2Ie56IubS2hUKiUkDm0ckP3Vum35GGntyEAzl6uyog0hJFOJb3aq30
|
||||||
|
YQLzyVEOz8NnA+32oMRzJJdDxQ7pqG5fgq7EF4d++YSgEfdVXxvfgXQ6m3jAyC7Z
|
||||||
|
p/gX4rlxNsjeGU3Ds51wkmhH4IB1aSQr52PE6RaBhhh3SmADEv6S/3eGvE4F4MN5
|
||||||
|
2Q==
|
||||||
|
-----END CERTIFICATE-----
|
33
contrib/certificates/reseed/rambler_at_mail.i2p.crt
Normal file
33
contrib/certificates/reseed/rambler_at_mail.i2p.crt
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFxzCCA6+gAwIBAgIQfKAV7rmoWA8jWpLfMtDQqzANBgkqhkiG9w0BAQsFADBw
|
||||||
|
MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK
|
||||||
|
ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEZMBcGA1UEAwwQ
|
||||||
|
cmFtYmxlckBtYWlsLmkycDAeFw0yMTExMDYwNzEwMzJaFw0zMTExMDYwNzEwMzJa
|
||||||
|
MHAxCzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgxHjAcBgNV
|
||||||
|
BAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRkwFwYDVQQD
|
||||||
|
DBByYW1ibGVyQG1haWwuaTJwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC
|
||||||
|
AgEAz4vQlIdjY56uqkFKWld9Oy3E8+06Ag9fUzBVleS2bdJfaFtmEa8xz6Pep7Bb
|
||||||
|
zJK0Q9t2CW7/xqIWuspWlYn5EYAS7BFiNOX70KX4PMpltj3C4Dpxpjll9LdydU2k
|
||||||
|
FquCflXNJESnBDdd0qDRMboMf4c9lTz0mTLwAtzInLwHGDrbxEiQ/YqPgPJreOXQ
|
||||||
|
anhjkpxJcgpLR+9od8EdLNKbShVWEeSBnYp0FcjnZKOb9KC2gjqP0sWdzlw3i1hh
|
||||||
|
CB38A7a03Q4yUcmxCw4ktM60d/2jCZ+G7KHwcbkfxDjl85r0UgEzgfF7LuIuxxmA
|
||||||
|
MNLH1eAACnLTl42O72EHdtD9VWWwZF2NuFgAzT3MEFnMKDk+OqZOeZQOEgkIfrNP
|
||||||
|
O5XYMYxHSWCf/dmSq36ZJwhC40k2S9ArS8BQNY8NvwZG5CSGDU52FKaHzFn6EwLE
|
||||||
|
4CpsrptUX2itXLaFUiNMw6I+eSgTO7x+gpahZVqpdRSQXmpE0xA5jP/DwPyt3ZVe
|
||||||
|
/4q4kn3imcSCxBP5NQHWfVszsruRkh9np4R0xVlT8UCwJmY8Yg8zwJG5UddTAck5
|
||||||
|
JavDsaXgWMwcZ/qQboZKlH/iAdQnbkte8Yd5GL5nmTeS+vwuluwmA/y9kUzSUhk+
|
||||||
|
86kA0eRJ1+e2HdA1/UOTRmyIoIeQ5/fhELMXzhksLcpMGTUCAwEAAaNdMFswDgYD
|
||||||
|
VR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNV
|
||||||
|
HRMBAf8EBTADAQH/MBkGA1UdDgQSBBByYW1ibGVyQG1haWwuaTJwMA0GCSqGSIb3
|
||||||
|
DQEBCwUAA4ICAQAxRdSTZGEblnNeVuRoEQq/a/6q4egFaOkzXCPKEnDzB5yvm83g
|
||||||
|
35ImquGFZkgaoc5qUAHVeBwOQrWgUI4xHPofnbM2VsgEUMz6h3ovobPNkN3+lRT5
|
||||||
|
30krd0y+A/Q895EHDu0lyf3BHMmtCWiKWQBttuc0dnmoLCRsQxgy+kYJCS/81jCM
|
||||||
|
4KNnyrtc6a/czqSq758CncjP2nErVucendsguQoA5JUw53YJ4FYHG/f9tYEkhm9C
|
||||||
|
D6u7L3vTUcMRUrRxSiJyNixH36nEwpM6DNHiPNc+CFKZ/Zx449R1GjcpDhTrXnWP
|
||||||
|
2H1r3cyKEM8a76VUEs2GQCaaglOR4N1goyqgYEjScf+/4VmARL3VUzfP8Oub70rM
|
||||||
|
t1fip5QD/4VDQuA/9C9g5Rr2nJ3K2jVnpSSKnBYFYf5z9RZdTOVXjXaEi72lWxpk
|
||||||
|
mjgK6c5EFOJxYoCaTbKX9Kz9ZIWVOVMrgHWwA/wDW+Qk5zgP9Ysau65xIp9P1RdB
|
||||||
|
qHgR5BcIrNky9RD8cIzxzMPCSMVgnf0eLFuHmG8uUl/xHHVRprf0pd7DYkQ44HWN
|
||||||
|
Z/g/gg3DaJdH7vvkShzgjt4iZrmOCHQIKkSGFRYZf0/Mpn6mgK9+grtO9osVgAQr
|
||||||
|
LBO+5LIxV/S5bcrzWQLOiMABTd2X/0PTOjuXpfinZ3rDSUiNFPq5kLLSlA==
|
||||||
|
-----END CERTIFICATE-----
|
|
@ -81,7 +81,9 @@ ipv6 = false
|
||||||
## Bandwidth configuration
|
## Bandwidth configuration
|
||||||
## L limit bandwidth to 32KBs/sec, O - to 256KBs/sec, P - to 2048KBs/sec,
|
## L limit bandwidth to 32KBs/sec, O - to 256KBs/sec, P - to 2048KBs/sec,
|
||||||
## X - unlimited
|
## X - unlimited
|
||||||
## Default is X for floodfill, L for regular node
|
## Default is L (regular node) and X if floodfill mode enabled. If you want to
|
||||||
|
## share more bandwidth without floodfill mode, uncomment that line and adjust
|
||||||
|
## value to your possibilities
|
||||||
# bandwidth = L
|
# bandwidth = L
|
||||||
## Max % of bandwidth limit for transit. 0-100. 100 by default
|
## Max % of bandwidth limit for transit. 0-100. 100 by default
|
||||||
# share = 100
|
# share = 100
|
||||||
|
@ -108,7 +110,8 @@ port = 7070
|
||||||
# user = i2pd
|
# user = i2pd
|
||||||
# pass = changeme
|
# pass = changeme
|
||||||
## Select webconsole language
|
## Select webconsole language
|
||||||
## Currently supported english (default), afrikaans, russian, turkmen, ukrainian and uzbek languages
|
## Currently supported english (default), afrikaans, armenian, french, german,
|
||||||
|
## russian, turkmen, ukrainian and uzbek languages
|
||||||
# lang = english
|
# lang = english
|
||||||
|
|
||||||
[httpproxy]
|
[httpproxy]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
%define git_hash %(git rev-parse HEAD | cut -c -7)
|
%define git_hash %(git rev-parse HEAD | cut -c -7)
|
||||||
|
|
||||||
Name: i2pd-git
|
Name: i2pd-git
|
||||||
Version: 2.39.0
|
Version: 2.42.1
|
||||||
Release: git%{git_hash}%{?dist}
|
Release: git%{git_hash}%{?dist}
|
||||||
Summary: I2P router written in C++
|
Summary: I2P router written in C++
|
||||||
Conflicts: i2pd
|
Conflicts: i2pd
|
||||||
|
@ -32,7 +32,7 @@ Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd
|
||||||
C++ implementation of I2P.
|
C++ implementation of I2P.
|
||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -q
|
%setup -q -n i2pd-openssl
|
||||||
|
|
||||||
|
|
||||||
%build
|
%build
|
||||||
|
@ -57,8 +57,14 @@ cd build
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
|
||||||
%if 0%{?fedora} >= 35
|
%if 0%{?rhel} == 9
|
||||||
pushd redhat-linux-build
|
pushd redhat-linux-build
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%if 0%{?fedora} >= 35
|
||||||
|
%if 0%{?fedora} < 37
|
||||||
|
pushd redhat-linux-build
|
||||||
|
%endif
|
||||||
%else
|
%else
|
||||||
%if 0%{?fedora} >= 33
|
%if 0%{?fedora} >= 33
|
||||||
pushd %{_target_platform}
|
pushd %{_target_platform}
|
||||||
|
@ -71,10 +77,16 @@ pushd build
|
||||||
|
|
||||||
make %{?_smp_mflags}
|
make %{?_smp_mflags}
|
||||||
|
|
||||||
%if 0%{?fedora} >= 33
|
%if 0%{?rhel} == 9
|
||||||
popd
|
popd
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
%if 0%{?fedora} >= 33
|
||||||
|
%if 0%{?fedora} < 37
|
||||||
|
popd
|
||||||
|
%endif
|
||||||
|
%endif
|
||||||
|
|
||||||
%if 0%{?mageia} > 7
|
%if 0%{?mageia} > 7
|
||||||
popd
|
popd
|
||||||
%endif
|
%endif
|
||||||
|
@ -82,8 +94,14 @@ popd
|
||||||
%install
|
%install
|
||||||
pushd build
|
pushd build
|
||||||
|
|
||||||
%if 0%{?fedora} >= 35
|
%if 0%{?rhel} == 9
|
||||||
pushd redhat-linux-build
|
pushd redhat-linux-build
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%if 0%{?fedora} >= 35
|
||||||
|
%if 0%{?fedora} < 37
|
||||||
|
pushd redhat-linux-build
|
||||||
|
%endif
|
||||||
%else
|
%else
|
||||||
%if 0%{?fedora} >= 33
|
%if 0%{?fedora} >= 33
|
||||||
pushd %{_target_platform}
|
pushd %{_target_platform}
|
||||||
|
@ -99,14 +117,14 @@ chrpath -d i2pd
|
||||||
%{__install} -d -m 755 %{buildroot}%{_datadir}/i2pd
|
%{__install} -d -m 755 %{buildroot}%{_datadir}/i2pd
|
||||||
%{__install} -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd
|
%{__install} -d -m 700 %{buildroot}%{_sharedstatedir}/i2pd
|
||||||
%{__install} -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd
|
%{__install} -d -m 700 %{buildroot}%{_localstatedir}/log/i2pd
|
||||||
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf
|
%{__install} -D -m 644 %{_builddir}/i2pd-openssl/contrib/i2pd.conf %{buildroot}%{_sysconfdir}/i2pd/i2pd.conf
|
||||||
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/subscriptions.txt %{buildroot}%{_sysconfdir}/i2pd/subscriptions.txt
|
%{__install} -D -m 644 %{_builddir}/i2pd-openssl/contrib/subscriptions.txt %{buildroot}%{_sysconfdir}/i2pd/subscriptions.txt
|
||||||
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf
|
%{__install} -D -m 644 %{_builddir}/i2pd-openssl/contrib/tunnels.conf %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf
|
||||||
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/i2pd.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/i2pd
|
%{__install} -D -m 644 %{_builddir}/i2pd-openssl/contrib/i2pd.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/i2pd
|
||||||
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/contrib/i2pd.service %{buildroot}%{_unitdir}/i2pd.service
|
%{__install} -D -m 644 %{_builddir}/i2pd-openssl/contrib/i2pd.service %{buildroot}%{_unitdir}/i2pd.service
|
||||||
%{__install} -D -m 644 %{_builddir}/%{name}-%{version}/debian/i2pd.1 %{buildroot}%{_mandir}/man1/i2pd.1
|
%{__install} -D -m 644 %{_builddir}/i2pd-openssl/debian/i2pd.1 %{buildroot}%{_mandir}/man1/i2pd.1
|
||||||
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates
|
%{__cp} -r %{_builddir}/i2pd-openssl/contrib/certificates/ %{buildroot}%{_datadir}/i2pd/certificates
|
||||||
%{__cp} -r %{_builddir}/%{name}-%{version}/contrib/tunnels.d/ %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d
|
%{__cp} -r %{_builddir}/i2pd-openssl/contrib/tunnels.d/ %{buildroot}%{_sysconfdir}/i2pd/tunnels.conf.d
|
||||||
ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates
|
ln -s %{_datadir}/%{name}/certificates %{buildroot}%{_sharedstatedir}/i2pd/certificates
|
||||||
|
|
||||||
|
|
||||||
|
@ -146,7 +164,20 @@ getent passwd i2pd >/dev/null || \
|
||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Mon Aug 24 2021 r4sas <r4sas@i2pmail.org> - 2.39.0-2
|
* 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
|
||||||
|
|
||||||
|
* Mon Nov 29 2021 orignal <i2porignal@yandex.ru> - 2.40.0
|
||||||
|
- update to 2.40.0
|
||||||
|
|
||||||
|
* Tue Aug 24 2021 r4sas <r4sas@i2pmail.org> - 2.39.0-2
|
||||||
- changed if statements to cover fedora 35
|
- changed if statements to cover fedora 35
|
||||||
|
|
||||||
* Mon Aug 23 2021 orignal <i2porignal@yandex.ru> - 2.39.0
|
* Mon Aug 23 2021 orignal <i2porignal@yandex.ru> - 2.39.0
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
Name: i2pd
|
Name: i2pd
|
||||||
Version: 2.39.0
|
Version: 2.42.1
|
||||||
Release: 2%{?dist}
|
Release: 1%{?dist}
|
||||||
Summary: I2P router written in C++
|
Summary: I2P router written in C++
|
||||||
Conflicts: i2pd-git
|
Conflicts: i2pd-git
|
||||||
|
|
||||||
|
@ -54,8 +54,14 @@ cd build
|
||||||
%endif
|
%endif
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
%if 0%{?fedora} >= 35
|
%if 0%{?rhel} == 9
|
||||||
pushd redhat-linux-build
|
pushd redhat-linux-build
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%if 0%{?fedora} >= 35
|
||||||
|
%if 0%{?fedora} < 37
|
||||||
|
pushd redhat-linux-build
|
||||||
|
%endif
|
||||||
%else
|
%else
|
||||||
%if 0%{?fedora} >= 33
|
%if 0%{?fedora} >= 33
|
||||||
pushd %{_target_platform}
|
pushd %{_target_platform}
|
||||||
|
@ -68,10 +74,16 @@ pushd build
|
||||||
|
|
||||||
make %{?_smp_mflags}
|
make %{?_smp_mflags}
|
||||||
|
|
||||||
%if 0%{?fedora} >= 33
|
%if 0%{?rhel} == 9
|
||||||
popd
|
popd
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
%if 0%{?fedora} >= 33
|
||||||
|
%if 0%{?fedora} < 37
|
||||||
|
popd
|
||||||
|
%endif
|
||||||
|
%endif
|
||||||
|
|
||||||
%if 0%{?mageia} > 7
|
%if 0%{?mageia} > 7
|
||||||
popd
|
popd
|
||||||
%endif
|
%endif
|
||||||
|
@ -79,8 +91,14 @@ popd
|
||||||
%install
|
%install
|
||||||
pushd build
|
pushd build
|
||||||
|
|
||||||
%if 0%{?fedora} >= 35
|
%if 0%{?rhel} == 9
|
||||||
pushd redhat-linux-build
|
pushd redhat-linux-build
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%if 0%{?fedora} >= 35
|
||||||
|
%if 0%{?fedora} < 37
|
||||||
|
pushd redhat-linux-build
|
||||||
|
%endif
|
||||||
%else
|
%else
|
||||||
%if 0%{?fedora} >= 33
|
%if 0%{?fedora} >= 33
|
||||||
pushd %{_target_platform}
|
pushd %{_target_platform}
|
||||||
|
@ -143,7 +161,19 @@ getent passwd i2pd >/dev/null || \
|
||||||
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Mon Aug 24 2021 r4sas <r4sas@i2pmail.org> - 2.39.0-2
|
* 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
|
||||||
|
|
||||||
|
* Mon Nov 29 2021 orignal <i2porignal@yandex.ru> - 2.40.0
|
||||||
|
- update to 2.40.0
|
||||||
|
|
||||||
|
* Tue Aug 24 2021 r4sas <r4sas@i2pmail.org> - 2.39.0-2
|
||||||
- changed if statements to cover fedora 35
|
- changed if statements to cover fedora 35
|
||||||
|
|
||||||
* Mon Aug 23 2021 orignal <i2porignal@yandex.ru> - 2.39.0
|
* Mon Aug 23 2021 orignal <i2porignal@yandex.ru> - 2.39.0
|
||||||
|
|
|
@ -1,35 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021-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
|
||||||
|
*
|
||||||
|
******************************************************************
|
||||||
|
*
|
||||||
|
* This is style sheet for webconsole, with @media selectors for adaptive
|
||||||
|
* view on desktop and mobile devices, respecting preferred user's color
|
||||||
|
* scheme used in system/browser.
|
||||||
|
*
|
||||||
|
* Minified copy of that style sheet is bundled inside i2pd sources.
|
||||||
|
*/
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--main-bg-color: #fafafa;
|
||||||
|
--main-text-color: #103456;
|
||||||
|
--main-link-color: #894c84;
|
||||||
|
--main-link-hover-color: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: dark) {
|
||||||
|
:root {
|
||||||
|
--main-bg-color: #242424;
|
||||||
|
--main-text-color: #17ab5c;
|
||||||
|
--main-link-color: #bf64b7;
|
||||||
|
--main-link-hover-color: #000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
font: 100%/1.5em sans-serif;
|
font: 100%/1.5em sans-serif;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 1.5em;
|
padding: 1.5em;
|
||||||
background: #FAFAFA;
|
background: var(--main-bg-color);
|
||||||
color: #103456;
|
color: var(--main-text-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
a, .slide label {
|
a, .slide label {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #894C84;
|
color: var(--main-link-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
a:hover, .slide label:hover {
|
a:hover, .slide label:hover, button[type=submit]:hover {
|
||||||
color: #FAFAFA;
|
color: var(--main-link-hover-color);
|
||||||
background: #894C84;
|
background: var(--main-link-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
a.button {
|
a.button {
|
||||||
-webkit-appearance: button;
|
|
||||||
-moz-appearance: button;
|
|
||||||
appearance: button;
|
appearance: button;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
border: 1px solid #894C84;
|
border: 1px solid var(--main-link-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
font-size: 2.5em;
|
font-size: 2.5em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin: 1em 0;
|
margin: 1em 0;
|
||||||
color: #894C84;
|
color: var(--main-link-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
|
@ -42,6 +72,7 @@ a.button {
|
||||||
display: block;
|
display: block;
|
||||||
float: left;
|
float: left;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
padding: 4px;
|
||||||
max-width: 12em;
|
max-width: 12em;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
@ -63,8 +94,9 @@ a.button {
|
||||||
.content {
|
.content {
|
||||||
float: left;
|
float: left;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
margin-left: 4em;
|
margin-left: 2em;
|
||||||
max-width: 48em;
|
padding: 4px;
|
||||||
|
max-width: 50em;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +119,7 @@ a.button {
|
||||||
caption {
|
caption {
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #894C84;
|
color: var(--main-link-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
table {
|
table {
|
||||||
|
@ -105,6 +137,8 @@ table.services {
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
|
background-color: var(--main-bg-color);
|
||||||
|
color: var(--main-text-color);
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,24 +167,45 @@ textarea {
|
||||||
color: #56B734;
|
color: #56B734;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button[type=submit] {
|
||||||
|
background-color: transparent;
|
||||||
|
color: var(--main-link-color);
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 5px;
|
||||||
|
border: 1px solid var(--main-link-color);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, select, select option {
|
||||||
|
background-color: var(--main-bg-color);
|
||||||
|
color: var(--main-link-color);
|
||||||
|
padding: 5px;
|
||||||
|
border: 1px solid var(--main-link-color);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:focus, select:focus, select option:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=number]::-webkit-inner-spin-button {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 1150px) { /* adaptive style */
|
@media screen and (max-width: 1150px) { /* adaptive style */
|
||||||
.wrapper {
|
.wrapper {
|
||||||
max-width: 58em;
|
max-width: 58em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu {
|
|
||||||
max-width: 10em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
margin-left: 2em;
|
max-width: 40em;
|
||||||
max-width: 42em;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 980px) {
|
@media screen and (max-width: 980px) {
|
||||||
body {
|
body {
|
||||||
padding: 1.5em 0 0 0;
|
font: 100%/1.2em sans-serif;
|
||||||
|
padding: 1.2em 0 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu {
|
.menu {
|
||||||
|
@ -178,9 +233,7 @@ textarea {
|
||||||
}
|
}
|
||||||
|
|
||||||
a, .slide label {
|
a, .slide label {
|
||||||
/* margin-right: 10px; */
|
|
||||||
display: block;
|
display: block;
|
||||||
/* font-size: 18px; */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
|
@ -193,13 +246,12 @@ textarea {
|
||||||
}
|
}
|
||||||
|
|
||||||
a.button {
|
a.button {
|
||||||
-webkit-appearance: button;
|
|
||||||
-moz-appearance: button;
|
|
||||||
appearance: button;
|
appearance: button;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
border: 1px solid #894c84;
|
border: 2px solid var(--main-link-color);
|
||||||
|
border-radius: 5px;
|
||||||
width: -webkit-fill-available;
|
width: -webkit-fill-available;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,8 +259,7 @@ textarea {
|
||||||
width: 35%;
|
width: 35%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
border: 2px solid #ccc;
|
border: 2px solid var(--main-link-color);
|
||||||
-webkit-border-radius: 5px;
|
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
@ -221,17 +272,16 @@ textarea {
|
||||||
textarea {
|
textarea {
|
||||||
width: -webkit-fill-available;
|
width: -webkit-fill-available;
|
||||||
height: auto;
|
height: auto;
|
||||||
padding:5px;
|
padding: 5px;
|
||||||
border:2px solid #ccc;
|
border: 2px solid var(--main-link-color);
|
||||||
-webkit-border-radius: 5px;
|
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
button[type=submit] {
|
button[type=submit] {
|
||||||
padding: 5px 15px;
|
padding: 5px 15px;
|
||||||
background: #ccc;
|
background: transparent;
|
||||||
border: 0 none;
|
border: 2px solid var(--main-link-color);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
-webkit-border-radius: 5px;
|
-webkit-border-radius: 5px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -58,12 +58,16 @@ namespace util
|
||||||
bool Daemon_Singleton::IsService () const
|
bool Daemon_Singleton::IsService () const
|
||||||
{
|
{
|
||||||
bool service = false;
|
bool service = false;
|
||||||
#ifndef _WIN32
|
|
||||||
i2p::config::GetOption("service", service);
|
i2p::config::GetOption("service", service);
|
||||||
#endif
|
|
||||||
return service;
|
return service;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Daemon_Singleton::setDataDir(std::string path)
|
||||||
|
{
|
||||||
|
if (path != "")
|
||||||
|
DaemonDataDir = path;
|
||||||
|
}
|
||||||
|
|
||||||
bool Daemon_Singleton::init(int argc, char* argv[]) {
|
bool Daemon_Singleton::init(int argc, char* argv[]) {
|
||||||
return init(argc, argv, nullptr);
|
return init(argc, argv, nullptr);
|
||||||
}
|
}
|
||||||
|
@ -73,8 +77,14 @@ namespace util
|
||||||
i2p::config::Init();
|
i2p::config::Init();
|
||||||
i2p::config::ParseCmdline(argc, argv);
|
i2p::config::ParseCmdline(argc, argv);
|
||||||
|
|
||||||
std::string config; i2p::config::GetOption("conf", config);
|
std::string config; i2p::config::GetOption("conf", config);
|
||||||
std::string datadir; i2p::config::GetOption("datadir", datadir);
|
std::string datadir;
|
||||||
|
if(DaemonDataDir != "") {
|
||||||
|
datadir = DaemonDataDir;
|
||||||
|
} else {
|
||||||
|
i2p::config::GetOption("datadir", datadir);
|
||||||
|
}
|
||||||
|
|
||||||
i2p::fs::DetectDataDir(datadir, IsService());
|
i2p::fs::DetectDataDir(datadir, IsService());
|
||||||
i2p::fs::Init();
|
i2p::fs::Init();
|
||||||
|
|
||||||
|
@ -99,9 +109,9 @@ namespace util
|
||||||
|
|
||||||
certsdir = i2p::fs::GetCertsDir();
|
certsdir = i2p::fs::GetCertsDir();
|
||||||
|
|
||||||
std::string logs = ""; i2p::config::GetOption("log", logs);
|
std::string logs = ""; i2p::config::GetOption("log", logs);
|
||||||
std::string logfile = ""; i2p::config::GetOption("logfile", logfile);
|
std::string logfile = ""; i2p::config::GetOption("logfile", logfile);
|
||||||
std::string loglevel = ""; i2p::config::GetOption("loglevel", loglevel);
|
std::string loglevel = ""; i2p::config::GetOption("loglevel", loglevel);
|
||||||
bool logclftime; i2p::config::GetOption("logclftime", logclftime);
|
bool logclftime; i2p::config::GetOption("logclftime", logclftime);
|
||||||
|
|
||||||
/* setup logging */
|
/* setup logging */
|
||||||
|
@ -118,26 +128,26 @@ namespace util
|
||||||
|
|
||||||
i2p::log::Logger().SetLogLevel(loglevel);
|
i2p::log::Logger().SetLogLevel(loglevel);
|
||||||
if (logstream) {
|
if (logstream) {
|
||||||
LogPrint(eLogInfo, "Log: will send messages to std::ostream");
|
LogPrint(eLogInfo, "Log: Sending messages to std::ostream");
|
||||||
i2p::log::Logger().SendTo (logstream);
|
i2p::log::Logger().SendTo (logstream);
|
||||||
} else if (logs == "file") {
|
} else if (logs == "file") {
|
||||||
if (logfile == "")
|
if (logfile == "")
|
||||||
logfile = i2p::fs::DataDirPath("i2pd.log");
|
logfile = i2p::fs::DataDirPath("i2pd.log");
|
||||||
LogPrint(eLogInfo, "Log: will send messages to ", logfile);
|
LogPrint(eLogInfo, "Log: Sending messages to ", logfile);
|
||||||
i2p::log::Logger().SendTo (logfile);
|
i2p::log::Logger().SendTo (logfile);
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
} else if (logs == "syslog") {
|
} else if (logs == "syslog") {
|
||||||
LogPrint(eLogInfo, "Log: will send messages to syslog");
|
LogPrint(eLogInfo, "Log: Sending messages to syslog");
|
||||||
i2p::log::Logger().SendTo("i2pd", LOG_DAEMON);
|
i2p::log::Logger().SendTo("i2pd", LOG_DAEMON);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
// use stdout -- default
|
// use stdout -- default
|
||||||
}
|
}
|
||||||
|
|
||||||
LogPrint(eLogNone, "i2pd v", VERSION, " starting");
|
LogPrint(eLogNone, "i2pd v", VERSION, " (", I2P_VERSION, ") starting...");
|
||||||
LogPrint(eLogDebug, "FS: main config file: ", config);
|
LogPrint(eLogDebug, "FS: Main config file: ", config);
|
||||||
LogPrint(eLogDebug, "FS: data directory: ", datadir);
|
LogPrint(eLogDebug, "FS: Data directory: ", datadir);
|
||||||
LogPrint(eLogDebug, "FS: certificates directory: ", certsdir);
|
LogPrint(eLogDebug, "FS: Certificates directory: ", certsdir);
|
||||||
|
|
||||||
bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation);
|
bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation);
|
||||||
bool aesni; i2p::config::GetOption("cpuext.aesni", aesni);
|
bool aesni; i2p::config::GetOption("cpuext.aesni", aesni);
|
||||||
|
@ -151,11 +161,7 @@ namespace util
|
||||||
|
|
||||||
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
bool ipv6; i2p::config::GetOption("ipv6", ipv6);
|
||||||
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
bool ipv4; i2p::config::GetOption("ipv4", ipv4);
|
||||||
#ifdef MESHNET
|
|
||||||
// manual override for meshnet
|
|
||||||
ipv4 = false;
|
|
||||||
ipv6 = true;
|
|
||||||
#endif
|
|
||||||
// ifname -> address
|
// ifname -> address
|
||||||
std::string ifname; i2p::config::GetOption("ifname", ifname);
|
std::string ifname; i2p::config::GetOption("ifname", ifname);
|
||||||
if (ipv4 && i2p::config::IsDefault ("address4"))
|
if (ipv4 && i2p::config::IsDefault ("address4"))
|
||||||
|
@ -204,7 +210,7 @@ namespace util
|
||||||
uint16_t port; i2p::config::GetOption("port", port);
|
uint16_t port; i2p::config::GetOption("port", port);
|
||||||
if (!i2p::config::IsDefault("port"))
|
if (!i2p::config::IsDefault("port"))
|
||||||
{
|
{
|
||||||
LogPrint(eLogInfo, "Daemon: accepting incoming connections at port ", port);
|
LogPrint(eLogInfo, "Daemon: Accepting incoming connections at port ", port);
|
||||||
i2p::context.UpdatePort (port);
|
i2p::context.UpdatePort (port);
|
||||||
}
|
}
|
||||||
i2p::context.SetSupportsV6 (ipv6);
|
i2p::context.SetSupportsV6 (ipv6);
|
||||||
|
@ -244,6 +250,18 @@ namespace util
|
||||||
if (!ipv4 && !ipv6)
|
if (!ipv4 && !ipv6)
|
||||||
i2p::context.SetStatus (eRouterStatusMesh);
|
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);
|
bool transit; i2p::config::GetOption("notransit", transit);
|
||||||
i2p::context.SetAcceptsTunnels (!transit);
|
i2p::context.SetAcceptsTunnels (!transit);
|
||||||
|
@ -252,7 +270,7 @@ namespace util
|
||||||
|
|
||||||
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
|
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
|
||||||
if (isFloodfill) {
|
if (isFloodfill) {
|
||||||
LogPrint(eLogInfo, "Daemon: router will be floodfill");
|
LogPrint(eLogInfo, "Daemon: Router configured as floodfill");
|
||||||
i2p::context.SetFloodfill (true);
|
i2p::context.SetFloodfill (true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -267,7 +285,7 @@ namespace util
|
||||||
if (bandwidth[0] >= 'K' && bandwidth[0] <= 'X')
|
if (bandwidth[0] >= 'K' && bandwidth[0] <= 'X')
|
||||||
{
|
{
|
||||||
i2p::context.SetBandwidth (bandwidth[0]);
|
i2p::context.SetBandwidth (bandwidth[0]);
|
||||||
LogPrint(eLogInfo, "Daemon: bandwidth set to ", i2p::context.GetBandwidthLimit (), "KBps");
|
LogPrint(eLogInfo, "Daemon: Bandwidth set to ", i2p::context.GetBandwidthLimit (), "KBps");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -275,18 +293,18 @@ namespace util
|
||||||
if (value > 0)
|
if (value > 0)
|
||||||
{
|
{
|
||||||
i2p::context.SetBandwidth (value);
|
i2p::context.SetBandwidth (value);
|
||||||
LogPrint(eLogInfo, "Daemon: bandwidth set to ", i2p::context.GetBandwidthLimit (), " KBps");
|
LogPrint(eLogInfo, "Daemon: Bandwidth set to ", i2p::context.GetBandwidthLimit (), " KBps");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint(eLogInfo, "Daemon: unexpected bandwidth ", bandwidth, ". Set to 'low'");
|
LogPrint(eLogInfo, "Daemon: Unexpected bandwidth ", bandwidth, ". Set to 'low'");
|
||||||
i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_LOW_BANDWIDTH2);
|
i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_LOW_BANDWIDTH2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (isFloodfill)
|
else if (isFloodfill)
|
||||||
{
|
{
|
||||||
LogPrint(eLogInfo, "Daemon: floodfill bandwidth set to 'extra'");
|
LogPrint(eLogInfo, "Daemon: Floodfill bandwidth set to 'extra'");
|
||||||
i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2);
|
i2p::context.SetBandwidth (i2p::data::CAPS_FLAG_EXTRA_BANDWIDTH2);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -301,12 +319,12 @@ namespace util
|
||||||
std::string family; i2p::config::GetOption("family", family);
|
std::string family; i2p::config::GetOption("family", family);
|
||||||
i2p::context.SetFamily (family);
|
i2p::context.SetFamily (family);
|
||||||
if (family.length () > 0)
|
if (family.length () > 0)
|
||||||
LogPrint(eLogInfo, "Daemon: family set to ", family);
|
LogPrint(eLogInfo, "Daemon: Router family set to ", family);
|
||||||
|
|
||||||
bool trust; i2p::config::GetOption("trust.enabled", trust);
|
bool trust; i2p::config::GetOption("trust.enabled", trust);
|
||||||
if (trust)
|
if (trust)
|
||||||
{
|
{
|
||||||
LogPrint(eLogInfo, "Daemon: explicit trust enabled");
|
LogPrint(eLogInfo, "Daemon: Explicit trust enabled");
|
||||||
std::string fam; i2p::config::GetOption("trust.family", fam);
|
std::string fam; i2p::config::GetOption("trust.family", fam);
|
||||||
std::string routers; i2p::config::GetOption("trust.routers", routers);
|
std::string routers; i2p::config::GetOption("trust.routers", routers);
|
||||||
bool restricted = false;
|
bool restricted = false;
|
||||||
|
@ -336,18 +354,18 @@ namespace util
|
||||||
pos = comma + 1;
|
pos = comma + 1;
|
||||||
}
|
}
|
||||||
while (comma != std::string::npos);
|
while (comma != std::string::npos);
|
||||||
LogPrint(eLogInfo, "Daemon: setting restricted routes to use ", idents.size(), " trusted routers");
|
LogPrint(eLogInfo, "Daemon: Setting restricted routes to use ", idents.size(), " trusted routers");
|
||||||
i2p::transport::transports.RestrictRoutesToRouters(idents);
|
i2p::transport::transports.RestrictRoutesToRouters(idents);
|
||||||
restricted = idents.size() > 0;
|
restricted = idents.size() > 0;
|
||||||
}
|
}
|
||||||
if(!restricted)
|
if(!restricted)
|
||||||
LogPrint(eLogError, "Daemon: no trusted routers of families specified");
|
LogPrint(eLogError, "Daemon: No trusted routers of families specified");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hidden; i2p::config::GetOption("trust.hidden", hidden);
|
bool hidden; i2p::config::GetOption("trust.hidden", hidden);
|
||||||
if (hidden)
|
if (hidden)
|
||||||
{
|
{
|
||||||
LogPrint(eLogInfo, "Daemon: using hidden mode");
|
LogPrint(eLogInfo, "Daemon: Hidden mode enabled");
|
||||||
i2p::data::netdb.SetHidden(true);
|
i2p::data::netdb.SetHidden(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,7 +378,7 @@ namespace util
|
||||||
bool Daemon_Singleton::start()
|
bool Daemon_Singleton::start()
|
||||||
{
|
{
|
||||||
i2p::log::Logger().Start();
|
i2p::log::Logger().Start();
|
||||||
LogPrint(eLogInfo, "Daemon: starting NetDB");
|
LogPrint(eLogInfo, "Daemon: Starting NetDB");
|
||||||
i2p::data::netdb.Start();
|
i2p::data::netdb.Start();
|
||||||
|
|
||||||
bool upnp; i2p::config::GetOption("upnp.enabled", upnp);
|
bool upnp; i2p::config::GetOption("upnp.enabled", upnp);
|
||||||
|
@ -377,19 +395,20 @@ namespace util
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
|
||||||
|
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
|
||||||
bool ssu; i2p::config::GetOption("ssu", ssu);
|
bool ssu; i2p::config::GetOption("ssu", ssu);
|
||||||
bool checkInReserved; i2p::config::GetOption("reservedrange", checkInReserved);
|
bool checkInReserved; i2p::config::GetOption("reservedrange", checkInReserved);
|
||||||
LogPrint(eLogInfo, "Daemon: starting Transports");
|
LogPrint(eLogInfo, "Daemon: Starting Transports");
|
||||||
if(!ssu) LogPrint(eLogInfo, "Daemon: ssu disabled");
|
if(!ssu) LogPrint(eLogInfo, "Daemon: SSU disabled");
|
||||||
if(!ntcp2) LogPrint(eLogInfo, "Daemon: ntcp2 disabled");
|
if(!ntcp2) LogPrint(eLogInfo, "Daemon: NTCP2 disabled");
|
||||||
|
|
||||||
i2p::transport::transports.SetCheckReserved(checkInReserved);
|
i2p::transport::transports.SetCheckReserved(checkInReserved);
|
||||||
i2p::transport::transports.Start(ntcp2, ssu);
|
i2p::transport::transports.Start(ntcp2, ssu, ssu2);
|
||||||
if (i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
|
if (i2p::transport::transports.IsBoundSSU() || i2p::transport::transports.IsBoundNTCP2())
|
||||||
LogPrint(eLogInfo, "Daemon: Transports started");
|
LogPrint(eLogInfo, "Daemon: Transports started");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "Daemon: failed to start Transports");
|
LogPrint(eLogError, "Daemon: Failed to start Transports");
|
||||||
/** shut down netdb right away */
|
/** shut down netdb right away */
|
||||||
i2p::transport::transports.Stop();
|
i2p::transport::transports.Stop();
|
||||||
i2p::data::netdb.Stop();
|
i2p::data::netdb.Stop();
|
||||||
|
@ -400,7 +419,7 @@ namespace util
|
||||||
if (http) {
|
if (http) {
|
||||||
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
|
std::string httpAddr; i2p::config::GetOption("http.address", httpAddr);
|
||||||
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
|
uint16_t httpPort; i2p::config::GetOption("http.port", httpPort);
|
||||||
LogPrint(eLogInfo, "Daemon: starting webconsole at ", httpAddr, ":", httpPort);
|
LogPrint(eLogInfo, "Daemon: Starting Webconsole at ", httpAddr, ":", httpPort);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
d.httpServer = std::unique_ptr<i2p::http::HTTPServer>(new i2p::http::HTTPServer(httpAddr, httpPort));
|
d.httpServer = std::unique_ptr<i2p::http::HTTPServer>(new i2p::http::HTTPServer(httpAddr, httpPort));
|
||||||
|
@ -408,16 +427,16 @@ namespace util
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Daemon: failed to start webconsole: ", ex.what ());
|
LogPrint (eLogError, "Daemon: Failed to start Webconsole: ", ex.what ());
|
||||||
ThrowFatal ("Unable to start webconsole at ", httpAddr, ":", httpPort, ": ", ex.what ());
|
ThrowFatal ("Unable to start webconsole at ", httpAddr, ":", httpPort, ": ", ex.what ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
LogPrint(eLogInfo, "Daemon: starting Tunnels");
|
LogPrint(eLogInfo, "Daemon: Starting Tunnels");
|
||||||
i2p::tunnel::tunnels.Start();
|
i2p::tunnel::tunnels.Start();
|
||||||
|
|
||||||
LogPrint(eLogInfo, "Daemon: starting Client");
|
LogPrint(eLogInfo, "Daemon: Starting Client");
|
||||||
i2p::client::context.Start ();
|
i2p::client::context.Start ();
|
||||||
|
|
||||||
// I2P Control Protocol
|
// I2P Control Protocol
|
||||||
|
@ -425,7 +444,7 @@ namespace util
|
||||||
if (i2pcontrol) {
|
if (i2pcontrol) {
|
||||||
std::string i2pcpAddr; i2p::config::GetOption("i2pcontrol.address", i2pcpAddr);
|
std::string i2pcpAddr; i2p::config::GetOption("i2pcontrol.address", i2pcpAddr);
|
||||||
uint16_t i2pcpPort; i2p::config::GetOption("i2pcontrol.port", i2pcpPort);
|
uint16_t i2pcpPort; i2p::config::GetOption("i2pcontrol.port", i2pcpPort);
|
||||||
LogPrint(eLogInfo, "Daemon: starting I2PControl at ", i2pcpAddr, ":", i2pcpPort);
|
LogPrint(eLogInfo, "Daemon: Starting I2PControl at ", i2pcpAddr, ":", i2pcpPort);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
d.m_I2PControlService = std::unique_ptr<i2p::client::I2PControlService>(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort));
|
d.m_I2PControlService = std::unique_ptr<i2p::client::I2PControlService>(new i2p::client::I2PControlService (i2pcpAddr, i2pcpPort));
|
||||||
|
@ -433,7 +452,7 @@ namespace util
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Daemon: failed to start I2PControl: ", ex.what ());
|
LogPrint (eLogError, "Daemon: Failed to start I2PControl: ", ex.what ());
|
||||||
ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ());
|
ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -442,10 +461,10 @@ namespace util
|
||||||
|
|
||||||
bool Daemon_Singleton::stop()
|
bool Daemon_Singleton::stop()
|
||||||
{
|
{
|
||||||
LogPrint(eLogInfo, "Daemon: shutting down");
|
LogPrint(eLogInfo, "Daemon: Shutting down");
|
||||||
LogPrint(eLogInfo, "Daemon: stopping Client");
|
LogPrint(eLogInfo, "Daemon: Stopping Client");
|
||||||
i2p::client::context.Stop();
|
i2p::client::context.Stop();
|
||||||
LogPrint(eLogInfo, "Daemon: stopping Tunnels");
|
LogPrint(eLogInfo, "Daemon: Stopping Tunnels");
|
||||||
i2p::tunnel::tunnels.Stop();
|
i2p::tunnel::tunnels.Stop();
|
||||||
|
|
||||||
if (d.UPnP)
|
if (d.UPnP)
|
||||||
|
@ -460,18 +479,18 @@ namespace util
|
||||||
d.m_NTPSync = nullptr;
|
d.m_NTPSync = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogPrint(eLogInfo, "Daemon: stopping Transports");
|
LogPrint(eLogInfo, "Daemon: Stopping Transports");
|
||||||
i2p::transport::transports.Stop();
|
i2p::transport::transports.Stop();
|
||||||
LogPrint(eLogInfo, "Daemon: stopping NetDB");
|
LogPrint(eLogInfo, "Daemon: Stopping NetDB");
|
||||||
i2p::data::netdb.Stop();
|
i2p::data::netdb.Stop();
|
||||||
if (d.httpServer) {
|
if (d.httpServer) {
|
||||||
LogPrint(eLogInfo, "Daemon: stopping HTTP Server");
|
LogPrint(eLogInfo, "Daemon: Stopping HTTP Server");
|
||||||
d.httpServer->Stop();
|
d.httpServer->Stop();
|
||||||
d.httpServer = nullptr;
|
d.httpServer = nullptr;
|
||||||
}
|
}
|
||||||
if (d.m_I2PControlService)
|
if (d.m_I2PControlService)
|
||||||
{
|
{
|
||||||
LogPrint(eLogInfo, "Daemon: stopping I2PControl");
|
LogPrint(eLogInfo, "Daemon: Stopping I2PControl");
|
||||||
d.m_I2PControlService->Stop ();
|
d.m_I2PControlService->Stop ();
|
||||||
d.m_I2PControlService = nullptr;
|
d.m_I2PControlService = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,27 +20,33 @@ namespace util
|
||||||
class Daemon_Singleton_Private;
|
class Daemon_Singleton_Private;
|
||||||
class Daemon_Singleton
|
class Daemon_Singleton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
virtual bool init(int argc, char* argv[], std::shared_ptr<std::ostream> logstream);
|
virtual bool init (int argc, char* argv[], std::shared_ptr<std::ostream> logstream);
|
||||||
virtual bool init(int argc, char* argv[]);
|
virtual bool init (int argc, char* argv[]);
|
||||||
virtual bool start();
|
virtual bool start ();
|
||||||
virtual bool stop();
|
virtual bool stop ();
|
||||||
virtual void run () {};
|
virtual void run () {};
|
||||||
|
|
||||||
bool isDaemon;
|
virtual void setDataDir (std::string path);
|
||||||
bool running;
|
|
||||||
|
|
||||||
protected:
|
bool isDaemon;
|
||||||
|
bool running;
|
||||||
|
|
||||||
Daemon_Singleton();
|
protected:
|
||||||
virtual ~Daemon_Singleton();
|
|
||||||
|
|
||||||
bool IsService () const;
|
Daemon_Singleton ();
|
||||||
|
virtual ~Daemon_Singleton ();
|
||||||
|
|
||||||
// d-pointer for httpServer, httpProxy, etc.
|
bool IsService () const;
|
||||||
class Daemon_Singleton_Private;
|
|
||||||
Daemon_Singleton_Private &d;
|
// d-pointer for httpServer, httpProxy, etc.
|
||||||
|
class Daemon_Singleton_Private;
|
||||||
|
Daemon_Singleton_Private &d;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::string DaemonDataDir;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(QT_GUI_LIB) // check if QT
|
#if defined(QT_GUI_LIB) // check if QT
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -160,7 +160,7 @@ namespace http {
|
||||||
if (level == "none" || level == "error" || level == "warn" || level == "info" || level == "debug")
|
if (level == "none" || level == "error" || level == "warn" || level == "info" || level == "debug")
|
||||||
i2p::log::Logger().SetLogLevel(level);
|
i2p::log::Logger().SetLogLevel(level);
|
||||||
else {
|
else {
|
||||||
LogPrint(eLogError, "HTTPServer: unknown loglevel set attempted");
|
LogPrint(eLogError, "HTTPServer: Unknown loglevel set attempted");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
i2p::log::Logger().Reopen ();
|
i2p::log::Logger().Reopen ();
|
||||||
|
@ -182,7 +182,7 @@ namespace http {
|
||||||
" <meta charset=\"UTF-8\">\r\n"
|
" <meta charset=\"UTF-8\">\r\n"
|
||||||
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n"
|
" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n"
|
||||||
" <link rel=\"shortcut icon\" href=\"" << itoopieFavicon << "\">\r\n"
|
" <link rel=\"shortcut icon\" href=\"" << itoopieFavicon << "\">\r\n"
|
||||||
" <title>Purple I2P " VERSION " Webconsole</title>\r\n";
|
" <title>Purple I2P Webconsole</title>\r\n";
|
||||||
GetStyles(s);
|
GetStyles(s);
|
||||||
s <<
|
s <<
|
||||||
"</head>\r\n"
|
"</head>\r\n"
|
||||||
|
@ -196,8 +196,10 @@ namespace http {
|
||||||
if (i2p::context.IsFloodfill ())
|
if (i2p::context.IsFloodfill ())
|
||||||
s << " <a href=\"" << webroot << "?page=" << HTTP_PAGE_LEASESETS << "\">" << tr("LeaseSets") << "</a><br>\r\n";
|
s << " <a href=\"" << webroot << "?page=" << HTTP_PAGE_LEASESETS << "\">" << tr("LeaseSets") << "</a><br>\r\n";
|
||||||
s <<
|
s <<
|
||||||
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TUNNELS << "\">" << tr("Tunnels") << "</a><br>\r\n"
|
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TUNNELS << "\">" << tr("Tunnels") << "</a><br>\r\n";
|
||||||
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSIT_TUNNELS << "\">" << tr("Transit Tunnels") << "</a><br>\r\n"
|
if (i2p::context.AcceptsTunnels () || i2p::tunnel::tunnels.CountTransitTunnels())
|
||||||
|
s << " <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSIT_TUNNELS << "\">" << tr("Transit Tunnels") << "</a><br>\r\n";
|
||||||
|
s <<
|
||||||
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_TRANSPORTS << "\">" << tr ("Transports") << "</a><br>\r\n"
|
" <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";
|
" <a href=\"" << webroot << "?page=" << HTTP_PAGE_I2P_TUNNELS << "\">" << tr("I2P tunnels") << "</a><br>\r\n";
|
||||||
if (i2p::client::context.GetSAMBridge ())
|
if (i2p::client::context.GetSAMBridge ())
|
||||||
|
@ -295,10 +297,10 @@ namespace http {
|
||||||
s << " (" << (double) i2p::transport::transports.GetTransitBandwidth () / 1024 << " " << tr(/* tr: Kibibit/s */ "KiB/s") << ")<br>\r\n";
|
s << " (" << (double) i2p::transport::transports.GetTransitBandwidth () / 1024 << " " << tr(/* tr: Kibibit/s */ "KiB/s") << ")<br>\r\n";
|
||||||
s << "<b>" << tr("Data path") << ":</b> " << i2p::fs::GetUTF8DataDir() << "<br>\r\n";
|
s << "<b>" << tr("Data path") << ":</b> " << i2p::fs::GetUTF8DataDir() << "<br>\r\n";
|
||||||
s << "<div class='slide'>";
|
s << "<div class='slide'>";
|
||||||
if((outputFormat == OutputFormatEnum::forWebConsole) || !includeHiddenContent) {
|
if ((outputFormat == OutputFormatEnum::forWebConsole) || !includeHiddenContent) {
|
||||||
s << "<label for=\"slide-info\">" << tr("Hidden content. Press on text to see.") << "</label>\r\n<input type=\"checkbox\" id=\"slide-info\" />\r\n<div class=\"slidecontent\">\r\n";
|
s << "<label for=\"slide-info\">" << tr("Hidden content. Press on text to see.") << "</label>\r\n<input type=\"checkbox\" id=\"slide-info\" />\r\n<div class=\"slidecontent\">\r\n";
|
||||||
}
|
}
|
||||||
if(includeHiddenContent) {
|
if (includeHiddenContent) {
|
||||||
s << "<b>" << tr("Router Ident") << ":</b> " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "<br>\r\n";
|
s << "<b>" << tr("Router Ident") << ":</b> " << i2p::context.GetRouterInfo().GetIdentHashBase64() << "<br>\r\n";
|
||||||
if (!i2p::context.GetRouterInfo().GetProperty("family").empty())
|
if (!i2p::context.GetRouterInfo().GetProperty("family").empty())
|
||||||
s << "<b>" << tr("Router Family") << ":</b> " << i2p::context.GetRouterInfo().GetProperty("family") << "<br>\r\n";
|
s << "<b>" << tr("Router Family") << ":</b> " << i2p::context.GetRouterInfo().GetProperty("family") << "<br>\r\n";
|
||||||
|
@ -307,41 +309,42 @@ namespace http {
|
||||||
s << "<b>"<< tr("Our external address") << ":</b>" << "<br>\r\n<table class=\"extaddr\"><tbody>\r\n";
|
s << "<b>"<< tr("Our external address") << ":</b>" << "<br>\r\n<table class=\"extaddr\"><tbody>\r\n";
|
||||||
for (const auto& address : i2p::context.GetRouterInfo().GetAddresses())
|
for (const auto& address : i2p::context.GetRouterInfo().GetAddresses())
|
||||||
{
|
{
|
||||||
s << "<tr>\r\n";
|
s << "<tr>\r\n<td>";
|
||||||
if (address->IsNTCP2 () && !address->IsPublishedNTCP2 ())
|
|
||||||
{
|
|
||||||
s << "<td>NTCP2";
|
|
||||||
if (address->host.is_v6 ()) s << "v6";
|
|
||||||
s << "</td><td>" << tr("supported") << "</td>\r\n</tr>\r\n";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
switch (address->transportStyle)
|
switch (address->transportStyle)
|
||||||
{
|
{
|
||||||
case i2p::data::RouterInfo::eTransportNTCP:
|
case i2p::data::RouterInfo::eTransportNTCP:
|
||||||
{
|
s << "NTCP2";
|
||||||
s << "<td>NTCP";
|
break;
|
||||||
if (address->IsPublishedNTCP2 ()) s << "2";
|
|
||||||
if (address->host.is_v6 ()) s << "v6";
|
|
||||||
s << "</td>\r\n";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case i2p::data::RouterInfo::eTransportSSU:
|
case i2p::data::RouterInfo::eTransportSSU:
|
||||||
{
|
s << "SSU";
|
||||||
s << "<td>SSU";
|
break;
|
||||||
if (address->host.is_v6 ())
|
case i2p::data::RouterInfo::eTransportSSU2:
|
||||||
s << "v6";
|
s << "SSU2";
|
||||||
s << "</td>\r\n";
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
s << "<td>" << tr("Unknown") << "</td>\r\n";
|
s << tr("Unknown");
|
||||||
}
|
}
|
||||||
s << "<td>" << address->host.to_string() << ":" << address->port << "</td>\r\n</tr>\r\n";
|
if (address->IsV6 ())
|
||||||
|
{
|
||||||
|
if (address->IsV4 ()) s << "v4";
|
||||||
|
s << "v6";
|
||||||
|
}
|
||||||
|
s << "</td>\r\n";
|
||||||
|
if (address->published)
|
||||||
|
s << "<td>" << address->host.to_string() << ":" << address->port << "</td>\r\n";
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s << "<td>" << tr("supported");
|
||||||
|
if (address->port)
|
||||||
|
s << " :" << address->port;
|
||||||
|
s << "</td>\r\n";
|
||||||
|
}
|
||||||
|
s << "</tr>\r\n";
|
||||||
}
|
}
|
||||||
s << "</tbody></table>\r\n";
|
s << "</tbody></table>\r\n";
|
||||||
}
|
}
|
||||||
s << "</div>\r\n</div>\r\n";
|
s << "</div>\r\n</div>\r\n";
|
||||||
if(outputFormat == OutputFormatEnum::forQtUi) {
|
if (outputFormat == OutputFormatEnum::forQtUi) {
|
||||||
s << "<br>";
|
s << "<br>";
|
||||||
}
|
}
|
||||||
s << "<b>" << tr("Routers") << ":</b> " << i2p::data::netdb.GetNumRouters () << " ";
|
s << "<b>" << tr("Routers") << ":</b> " << i2p::data::netdb.GetNumRouters () << " ";
|
||||||
|
@ -355,7 +358,7 @@ namespace http {
|
||||||
s << "<b>" << tr("Client Tunnels") << ":</b> " << std::to_string(clientTunnelCount) << " ";
|
s << "<b>" << tr("Client Tunnels") << ":</b> " << std::to_string(clientTunnelCount) << " ";
|
||||||
s << "<b>" << tr("Transit Tunnels") << ":</b> " << std::to_string(transitTunnelCount) << "<br>\r\n<br>\r\n";
|
s << "<b>" << tr("Transit Tunnels") << ":</b> " << std::to_string(transitTunnelCount) << "<br>\r\n<br>\r\n";
|
||||||
|
|
||||||
if(outputFormat==OutputFormatEnum::forWebConsole) {
|
if (outputFormat==OutputFormatEnum::forWebConsole) {
|
||||||
bool httpproxy = i2p::client::context.GetHttpProxy () ? true : false;
|
bool httpproxy = i2p::client::context.GetHttpProxy () ? true : false;
|
||||||
bool socksproxy = i2p::client::context.GetSocksProxy () ? true : false;
|
bool socksproxy = i2p::client::context.GetSocksProxy () ? true : false;
|
||||||
bool bob = i2p::client::context.GetBOBCommandChannel () ? true : false;
|
bool bob = i2p::client::context.GetBOBCommandChannel () ? true : false;
|
||||||
|
@ -416,7 +419,7 @@ namespace http {
|
||||||
s << "</div>\r\n</div>\r\n";
|
s << "</div>\r\n</div>\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dest->IsPublic())
|
if (dest->IsPublic() && token && !dest->IsEncryptedLeaseSet ())
|
||||||
{
|
{
|
||||||
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
|
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
|
||||||
auto base32 = dest->GetIdentHash ().ToBase32 ();
|
auto base32 = dest->GetIdentHash ().ToBase32 ();
|
||||||
|
@ -430,7 +433,7 @@ namespace http {
|
||||||
"</form>\r\n<small>" << tr("<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.") << "</small>\r\n</div>\r\n</div>\r\n<br>\r\n";
|
"</form>\r\n<small>" << tr("<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.") << "</small>\r\n</div>\r\n</div>\r\n<br>\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dest->GetNumRemoteLeaseSets())
|
if (dest->GetNumRemoteLeaseSets())
|
||||||
{
|
{
|
||||||
s << "<div class='slide'><label for='slide-lease'><b>" << tr("LeaseSets") << ":</b> <i>" << dest->GetNumRemoteLeaseSets ()
|
s << "<div class='slide'><label for='slide-lease'><b>" << tr("LeaseSets") << ":</b> <i>" << dest->GetNumRemoteLeaseSets ()
|
||||||
<< "</i></label>\r\n<input type=\"checkbox\" id=\"slide-lease\" />\r\n<div class=\"slidecontent\">\r\n<table><thead><th>"<< tr("Address") << "</th><th>" << tr("Type") << "</th><th>" << tr("EncType") << "</th></thead><tbody class=\"tableitem\">";
|
<< "</i></label>\r\n<input type=\"checkbox\" id=\"slide-lease\" />\r\n<div class=\"slidecontent\">\r\n<table><thead><th>"<< tr("Address") << "</th><th>" << tr("Type") << "</th><th>" << tr("EncType") << "</th></thead><tbody class=\"tableitem\">";
|
||||||
|
@ -446,8 +449,18 @@ namespace http {
|
||||||
s << "<b>" << tr("Inbound tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
s << "<b>" << tr("Inbound tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
||||||
for (auto & it : pool->GetInboundTunnels ()) {
|
for (auto & it : pool->GetInboundTunnels ()) {
|
||||||
s << "<div class=\"listitem\">";
|
s << "<div class=\"listitem\">";
|
||||||
it->Print(s);
|
// for each tunnel hop if not zero-hop
|
||||||
if(it->LatencyIsKnown())
|
if (it->GetNumHops ())
|
||||||
|
{
|
||||||
|
it->VisitTunnelHops(
|
||||||
|
[&s](std::shared_ptr<const i2p::data::IdentityEx> hopIdent)
|
||||||
|
{
|
||||||
|
s << "⇒ " << i2p::data::GetIdentHashAbbreviation (hopIdent->GetIdentHash ()) << " ";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
s << "⇒ " << it->GetTunnelID () << ":me";
|
||||||
|
if (it->LatencyIsKnown())
|
||||||
s << " ( " << it->GetMeanLatency() << tr(/* tr: Milliseconds */ "ms") << " )";
|
s << " ( " << it->GetMeanLatency() << tr(/* tr: Milliseconds */ "ms") << " )";
|
||||||
ShowTunnelDetails(s, it->GetState (), false, it->GetNumReceivedBytes ());
|
ShowTunnelDetails(s, it->GetState (), false, it->GetNumReceivedBytes ());
|
||||||
s << "</div>\r\n";
|
s << "</div>\r\n";
|
||||||
|
@ -456,8 +469,18 @@ namespace http {
|
||||||
s << "<b>" << tr("Outbound tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
s << "<b>" << tr("Outbound tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
||||||
for (auto & it : pool->GetOutboundTunnels ()) {
|
for (auto & it : pool->GetOutboundTunnels ()) {
|
||||||
s << "<div class=\"listitem\">";
|
s << "<div class=\"listitem\">";
|
||||||
it->Print(s);
|
s << it->GetTunnelID () << ":me ⇒";
|
||||||
if(it->LatencyIsKnown())
|
// for each tunnel hop if not zero-hop
|
||||||
|
if (it->GetNumHops ())
|
||||||
|
{
|
||||||
|
it->VisitTunnelHops(
|
||||||
|
[&s](std::shared_ptr<const i2p::data::IdentityEx> hopIdent)
|
||||||
|
{
|
||||||
|
s << " " << i2p::data::GetIdentHashAbbreviation (hopIdent->GetIdentHash ()) << " ⇒";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (it->LatencyIsKnown())
|
||||||
s << " ( " << it->GetMeanLatency() << tr("ms") << " )";
|
s << " ( " << it->GetMeanLatency() << tr("ms") << " )";
|
||||||
ShowTunnelDetails(s, it->GetState (), false, it->GetNumSentBytes ());
|
ShowTunnelDetails(s, it->GetState (), false, it->GetNumSentBytes ());
|
||||||
s << "</div>\r\n";
|
s << "</div>\r\n";
|
||||||
|
@ -630,8 +653,17 @@ namespace http {
|
||||||
s << "<b>" << tr("Inbound tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
s << "<b>" << tr("Inbound tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
||||||
for (auto & it : i2p::tunnel::tunnels.GetInboundTunnels ()) {
|
for (auto & it : i2p::tunnel::tunnels.GetInboundTunnels ()) {
|
||||||
s << "<div class=\"listitem\">";
|
s << "<div class=\"listitem\">";
|
||||||
it->Print(s);
|
if (it->GetNumHops ())
|
||||||
if(it->LatencyIsKnown())
|
{
|
||||||
|
it->VisitTunnelHops(
|
||||||
|
[&s](std::shared_ptr<const i2p::data::IdentityEx> hopIdent)
|
||||||
|
{
|
||||||
|
s << "⇒ " << i2p::data::GetIdentHashAbbreviation (hopIdent->GetIdentHash ()) << " ";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
s << "⇒ " << it->GetTunnelID () << ":me";
|
||||||
|
if (it->LatencyIsKnown())
|
||||||
s << " ( " << it->GetMeanLatency() << tr("ms") << " )";
|
s << " ( " << it->GetMeanLatency() << tr("ms") << " )";
|
||||||
ShowTunnelDetails(s, it->GetState (), (it->GetTunnelPool () == ExplPool), it->GetNumReceivedBytes ());
|
ShowTunnelDetails(s, it->GetState (), (it->GetTunnelPool () == ExplPool), it->GetNumReceivedBytes ());
|
||||||
s << "</div>\r\n";
|
s << "</div>\r\n";
|
||||||
|
@ -640,8 +672,18 @@ namespace http {
|
||||||
s << "<b>" << tr("Outbound tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
s << "<b>" << tr("Outbound tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
||||||
for (auto & it : i2p::tunnel::tunnels.GetOutboundTunnels ()) {
|
for (auto & it : i2p::tunnel::tunnels.GetOutboundTunnels ()) {
|
||||||
s << "<div class=\"listitem\">";
|
s << "<div class=\"listitem\">";
|
||||||
it->Print(s);
|
s << it->GetTunnelID () << ":me ⇒";
|
||||||
if(it->LatencyIsKnown())
|
// for each tunnel hop if not zero-hop
|
||||||
|
if (it->GetNumHops ())
|
||||||
|
{
|
||||||
|
it->VisitTunnelHops(
|
||||||
|
[&s](std::shared_ptr<const i2p::data::IdentityEx> hopIdent)
|
||||||
|
{
|
||||||
|
s << " " << i2p::data::GetIdentHashAbbreviation (hopIdent->GetIdentHash ()) << " ⇒";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (it->LatencyIsKnown())
|
||||||
s << " ( " << it->GetMeanLatency() << tr("ms") << " )";
|
s << " ( " << it->GetMeanLatency() << tr("ms") << " )";
|
||||||
ShowTunnelDetails(s, it->GetState (), (it->GetTunnelPool () == ExplPool), it->GetNumSentBytes ());
|
ShowTunnelDetails(s, it->GetState (), (it->GetTunnelPool () == ExplPool), it->GetNumSentBytes ());
|
||||||
s << "</div>\r\n";
|
s << "</div>\r\n";
|
||||||
|
@ -713,7 +755,7 @@ namespace http {
|
||||||
|
|
||||||
void ShowTransitTunnels (std::stringstream& s)
|
void ShowTransitTunnels (std::stringstream& s)
|
||||||
{
|
{
|
||||||
if(i2p::tunnel::tunnels.CountTransitTunnels())
|
if (i2p::tunnel::tunnels.CountTransitTunnels())
|
||||||
{
|
{
|
||||||
s << "<b>" << tr("Transit Tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
s << "<b>" << tr("Transit Tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
||||||
for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ())
|
for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ())
|
||||||
|
@ -736,7 +778,7 @@ namespace http {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Sessions>
|
template<typename Sessions>
|
||||||
static void ShowNTCPTransports (std::stringstream& s, const Sessions& sessions, const std::string name)
|
static void ShowTransportSessions (std::stringstream& s, const Sessions& sessions, const std::string name)
|
||||||
{
|
{
|
||||||
std::stringstream tmp_s, tmp_s6; uint16_t cnt = 0, cnt6 = 0;
|
std::stringstream tmp_s, tmp_s6; uint16_t cnt = 0, cnt6 = 0;
|
||||||
for (const auto& it: sessions )
|
for (const auto& it: sessions )
|
||||||
|
@ -749,6 +791,8 @@ namespace http {
|
||||||
<< it.second->GetRemoteEndpoint ().address ().to_string ();
|
<< it.second->GetRemoteEndpoint ().address ().to_string ();
|
||||||
if (!it.second->IsOutgoing ()) tmp_s << " ⇒ ";
|
if (!it.second->IsOutgoing ()) tmp_s << " ⇒ ";
|
||||||
tmp_s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
|
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;
|
tmp_s << "</div>\r\n" << std::endl;
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
|
@ -760,6 +804,8 @@ namespace http {
|
||||||
<< "[" << it.second->GetRemoteEndpoint ().address ().to_string () << "]";
|
<< "[" << it.second->GetRemoteEndpoint ().address ().to_string () << "]";
|
||||||
if (!it.second->IsOutgoing ()) tmp_s6 << " ⇒ ";
|
if (!it.second->IsOutgoing ()) tmp_s6 << " ⇒ ";
|
||||||
tmp_s6 << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
|
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;
|
tmp_s6 << "</div>\r\n" << std::endl;
|
||||||
cnt6++;
|
cnt6++;
|
||||||
}
|
}
|
||||||
|
@ -786,7 +832,7 @@ namespace http {
|
||||||
{
|
{
|
||||||
auto sessions = ntcp2Server->GetNTCP2Sessions ();
|
auto sessions = ntcp2Server->GetNTCP2Sessions ();
|
||||||
if (!sessions.empty ())
|
if (!sessions.empty ())
|
||||||
ShowNTCPTransports (s, sessions, "NTCP2");
|
ShowTransportSessions (s, sessions, "NTCP2");
|
||||||
}
|
}
|
||||||
auto ssuServer = i2p::transport::transports.GetSSUServer ();
|
auto ssuServer = i2p::transport::transports.GetSSUServer ();
|
||||||
if (ssuServer)
|
if (ssuServer)
|
||||||
|
@ -828,6 +874,13 @@ namespace http {
|
||||||
s << "</div>\r\n</div>\r\n";
|
s << "</div>\r\n</div>\r\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
auto ssu2Server = i2p::transport::transports.GetSSU2Server ();
|
||||||
|
if (ssu2Server)
|
||||||
|
{
|
||||||
|
auto sessions = ssu2Server->GetSSU2Sessions ();
|
||||||
|
if (!sessions.empty ())
|
||||||
|
ShowTransportSessions (s, sessions, "SSU2");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowSAMSessions (std::stringstream& s)
|
void ShowSAMSessions (std::stringstream& s)
|
||||||
|
@ -840,7 +893,7 @@ namespace http {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sam->GetSessions ().size ())
|
if (sam->GetSessions ().size ())
|
||||||
{
|
{
|
||||||
s << "<b>" << tr("SAM sessions") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
s << "<b>" << tr("SAM sessions") << ":</b><br>\r\n<div class=\"list\">\r\n";
|
||||||
for (auto& it: sam->GetSessions ())
|
for (auto& it: sam->GetSessions ())
|
||||||
|
@ -1039,7 +1092,7 @@ namespace http {
|
||||||
if (expected == provided) return true;
|
if (expected == provided) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
LogPrint(eLogWarning, "HTTPServer: auth failure from ", m_Socket->remote_endpoint().address ());
|
LogPrint(eLogWarning, "HTTPServer: Auth failure from ", m_Socket->remote_endpoint().address ());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1049,7 +1102,7 @@ namespace http {
|
||||||
std::string content;
|
std::string content;
|
||||||
HTTPRes res;
|
HTTPRes res;
|
||||||
|
|
||||||
LogPrint(eLogDebug, "HTTPServer: request: ", req.uri);
|
LogPrint(eLogDebug, "HTTPServer: Request: ", req.uri);
|
||||||
|
|
||||||
if (needAuth && !CheckAuth(req)) {
|
if (needAuth && !CheckAuth(req)) {
|
||||||
res.code = 401;
|
res.code = 401;
|
||||||
|
@ -1057,6 +1110,7 @@ namespace http {
|
||||||
SendReply(res, content);
|
SendReply(res, content);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool strictheaders;
|
bool strictheaders;
|
||||||
i2p::config::GetOption("http.strictheaders", strictheaders);
|
i2p::config::GetOption("http.strictheaders", strictheaders);
|
||||||
if (strictheaders)
|
if (strictheaders)
|
||||||
|
@ -1079,6 +1133,7 @@ namespace http {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTML head start
|
// HTML head start
|
||||||
ShowPageHead (s);
|
ShowPageHead (s);
|
||||||
if (req.uri.find("page=") != std::string::npos) {
|
if (req.uri.find("page=") != std::string::npos) {
|
||||||
|
@ -1199,7 +1254,7 @@ namespace http {
|
||||||
else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL)
|
else if (cmd == HTTP_COMMAND_SHUTDOWN_CANCEL)
|
||||||
{
|
{
|
||||||
i2p::context.SetAcceptsTunnels (true);
|
i2p::context.SetAcceptsTunnels (true);
|
||||||
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
|
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
|
||||||
Daemon.gracefulShutdownInterval = 0;
|
Daemon.gracefulShutdownInterval = 0;
|
||||||
#elif defined(WIN32_APP)
|
#elif defined(WIN32_APP)
|
||||||
i2p::win32::StopGracefulShutdown ();
|
i2p::win32::StopGracefulShutdown ();
|
||||||
|
@ -1231,7 +1286,7 @@ namespace http {
|
||||||
{
|
{
|
||||||
if (dest)
|
if (dest)
|
||||||
{
|
{
|
||||||
if(dest->DeleteStream (streamID))
|
if (dest->DeleteStream (streamID))
|
||||||
s << "<b>" << tr("SUCCESS") << "</b>: " << tr("Stream closed") << "<br>\r\n<br>\r\n";
|
s << "<b>" << tr("SUCCESS") << "</b>: " << tr("Stream closed") << "<br>\r\n<br>\r\n";
|
||||||
else
|
else
|
||||||
s << "<b>" << tr("ERROR") << "</b>: " << tr("Stream not found or already was closed") << "<br>\r\n<br>\r\n";
|
s << "<b>" << tr("ERROR") << "</b>: " << tr("Stream not found or already was closed") << "<br>\r\n<br>\r\n";
|
||||||
|
@ -1377,7 +1432,7 @@ namespace http {
|
||||||
pass[i] = alnum[random[i] % (sizeof(alnum) - 1)];
|
pass[i] = alnum[random[i] % (sizeof(alnum) - 1)];
|
||||||
}
|
}
|
||||||
i2p::config::SetOption("http.pass", pass);
|
i2p::config::SetOption("http.pass", pass);
|
||||||
LogPrint(eLogInfo, "HTTPServer: password set to ", pass);
|
LogPrint(eLogInfo, "HTTPServer: Password set to ", pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_IsRunning = true;
|
m_IsRunning = true;
|
||||||
|
@ -1391,7 +1446,13 @@ namespace http {
|
||||||
void HTTPServer::Stop ()
|
void HTTPServer::Stop ()
|
||||||
{
|
{
|
||||||
m_IsRunning = false;
|
m_IsRunning = false;
|
||||||
|
|
||||||
|
boost::system::error_code ec;
|
||||||
|
m_Acceptor.cancel(ec);
|
||||||
|
if (ec)
|
||||||
|
LogPrint (eLogDebug, "HTTPServer: Error while cancelling operations on acceptor: ", ec.message ());
|
||||||
m_Acceptor.close();
|
m_Acceptor.close();
|
||||||
|
|
||||||
m_Service.stop ();
|
m_Service.stop ();
|
||||||
if (m_Thread)
|
if (m_Thread)
|
||||||
{
|
{
|
||||||
|
@ -1412,7 +1473,7 @@ namespace http {
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "HTTPServer: runtime exception: ", ex.what ());
|
LogPrint (eLogError, "HTTPServer: Runtime exception: ", ex.what ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1427,15 +1488,13 @@ namespace http {
|
||||||
void HTTPServer::HandleAccept(const boost::system::error_code& ecode,
|
void HTTPServer::HandleAccept(const boost::system::error_code& ecode,
|
||||||
std::shared_ptr<boost::asio::ip::tcp::socket> newSocket)
|
std::shared_ptr<boost::asio::ip::tcp::socket> newSocket)
|
||||||
{
|
{
|
||||||
if (ecode)
|
if (!ecode)
|
||||||
|
CreateConnection(newSocket);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if(newSocket) newSocket->close();
|
if (newSocket) newSocket->close();
|
||||||
LogPrint(eLogError, "HTTP Server: error handling accept ", ecode.message());
|
LogPrint(eLogError, "HTTP Server: Error handling accept: ", ecode.message());
|
||||||
if(ecode != boost::asio::error::operation_aborted)
|
|
||||||
Accept();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
CreateConnection(newSocket);
|
|
||||||
Accept ();
|
Accept ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,8 +98,8 @@ namespace http
|
||||||
void ShowSAMSessions (std::stringstream& s);
|
void ShowSAMSessions (std::stringstream& s);
|
||||||
void ShowI2PTunnels (std::stringstream& s);
|
void ShowI2PTunnels (std::stringstream& s);
|
||||||
void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token);
|
void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token);
|
||||||
void ShowSAMSession (std::stringstream& s, const std::string& id);
|
void ShowSAMSession (std::stringstream& s, const std::string& id);
|
||||||
void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id);
|
void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id);
|
||||||
} // http
|
} // http
|
||||||
} // i2p
|
} // i2p
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -34,50 +34,58 @@ namespace http
|
||||||
// bundled style sheet
|
// bundled style sheet
|
||||||
const std::string internalCSS =
|
const std::string internalCSS =
|
||||||
"<style>\r\n"
|
"<style>\r\n"
|
||||||
" body { font: 100%/1.5em sans-serif; margin: 0; padding: 1.5em; background: #FAFAFA; color: #103456; }\r\n"
|
":root { --main-bg-color: #fafafa; --main-text-color: #103456; --main-link-color: #894c84; --main-link-hover-color: #fafafa; }\r\n"
|
||||||
" a, .slide label { text-decoration: none; color: #894C84; }\r\n"
|
"@media (prefers-color-scheme: dark) { :root { --main-bg-color: #242424; --main-text-color: #17ab5c; --main-link-color: #bf64b7; --main-link-hover-color: #000000; } }\r\n"
|
||||||
" a:hover, .slide label:hover { color: #FAFAFA; background: #894C84; }\r\n"
|
"body { font: 100%/1.5em sans-serif; margin: 0; padding: 1.5em; background: var(--main-bg-color); color: var(--main-text-color); }\r\n"
|
||||||
" a.button { -webkit-appearance: button; -moz-appearance: button; appearance: button; text-decoration: none;\r\n"
|
"a, .slide label { text-decoration: none; color: var(--main-link-color); }\r\n"
|
||||||
" padding: 0 5px; border: 1px solid #894C84; }\r\n"
|
"a:hover, .slide label:hover, button[type=submit]:hover { color: var(--main-link-hover-color); background: var(--main-link-color); }\r\n"
|
||||||
" .header { font-size: 2.5em; text-align: center; margin: 1em 0; color: #894C84; }\r\n"
|
"a.button { appearance: button; text-decoration: none; padding: 0 5px; border: 1px solid var(--main-link-color); }\r\n"
|
||||||
" .wrapper { margin: 0 auto; padding: 1em; max-width: 64em; }\r\n"
|
".header { font-size: 2.5em; text-align: center; margin: 1em 0; color: var(--main-link-color); }\r\n"
|
||||||
" .menu { display: block; float: left; overflow: hidden; max-width: 12em; white-space: nowrap; text-overflow: ellipsis; }\r\n"
|
".wrapper { margin: 0 auto; padding: 1em; max-width: 64em; }\r\n"
|
||||||
" .listitem { display: block; font-family: monospace; font-size: 1.2em; white-space: nowrap; }\r\n"
|
".menu { display: block; float: left; overflow: hidden; padding: 4px; max-width: 12em; white-space: nowrap; text-overflow: ellipsis ;}\r\n"
|
||||||
" .tableitem { font-family: monospace; font-size: 1.2em; white-space: nowrap; }\r\n"
|
".listitem { display: block; font-family: monospace; font-size: 1.2em; white-space: nowrap; }\r\n"
|
||||||
" .content { float: left; font-size: 1em; margin-left: 4em; max-width: 48em; overflow: auto; }\r\n"
|
".tableitem { font-family: monospace; font-size: 1.2em; white-space: nowrap; }\r\n"
|
||||||
" .tunnel.established { color: #56B734; } .tunnel.expiring { color: #D3AE3F; }\r\n"
|
".content { float: left; font-size: 1em; margin-left: 2em; padding: 4px; max-width: 50em; overflow: auto; }\r\n"
|
||||||
" .tunnel.failed { color: #D33F3F; } .tunnel.building { color: #434343; }\r\n"
|
".tunnel.established { color: #56B734; }\r\n"
|
||||||
" caption { font-size: 1.5em; text-align: center; color: #894C84; }\r\n"
|
".tunnel.expiring { color: #D3AE3F; }\r\n"
|
||||||
" table { display: table; border-collapse: collapse; text-align: center; }\r\n"
|
".tunnel.failed { color: #D33F3F; }\r\n"
|
||||||
" table.extaddr { text-align: left; } table.services { width: 100%; }\r\n"
|
".tunnel.building { color: #434343; }\r\n"
|
||||||
" textarea { word-break: break-all; }\r\n"
|
"caption { font-size: 1.5em; text-align: center; color: var(--main-link-color); }\r\n"
|
||||||
" .streamdest { width: 120px; max-width: 240px; overflow: hidden; text-overflow: ellipsis;}\r\n"
|
"table { display: table; border-collapse: collapse; text-align: center; }\r\n"
|
||||||
" .slide div.slidecontent, .slide [type=\"checkbox\"] { display: none; }\r\n"
|
"table.extaddr { text-align: left; }\r\n"
|
||||||
" .slide [type=\"checkbox\"]:checked ~ div.slidecontent { display: block; margin-top: 0; padding: 0; }\r\n"
|
"table.services { width: 100%; }\r\n"
|
||||||
" .disabled { color: #D33F3F; } .enabled { color: #56B734; }\r\n"
|
"textarea { background-color: var(--main-bg-color); color: var(--main-text-color); word-break: break-all; }\r\n"
|
||||||
" @media screen and (max-width: 1150px) {\r\n" /* adaptive style */
|
".streamdest { width: 120px; max-width: 240px; overflow: hidden; text-overflow: ellipsis; }\r\n"
|
||||||
" .wrapper { max-width: 58em; } .menu { max-width: 10em; }\r\n"
|
".slide div.slidecontent, .slide [type=\"checkbox\"] { display: none; }\r\n"
|
||||||
" .content { margin-left: 2em; max-width: 42em; }\r\n"
|
".slide [type=\"checkbox\"]:checked ~ div.slidecontent { display: block; margin-top: 0; padding: 0; }\r\n"
|
||||||
" }\r\n"
|
".disabled { color: #D33F3F; }\r\n"
|
||||||
" @media screen and (max-width: 980px) {\r\n"
|
".enabled { color: #56B734; }\r\n"
|
||||||
" body { padding: 1.5em 0 0 0; }\r\n"
|
"button[type=submit] { background-color: transparent; color: var(--main-link-color); text-decoration: none;\r\n"
|
||||||
" .menu { width: 100%; max-width: unset; display: block; float: none; position: unset; font-size: 16px;\r\n"
|
" padding: 5px; border: 1px solid var(--main-link-color); font-size: 14px; }\r\n"
|
||||||
" text-align: center; }\r\n"
|
"input, select, select option { background-color: var(--main-bg-color); color: var(--main-link-color); padding: 5px;\r\n"
|
||||||
" .menu a, .commands a { display: inline-block; padding: 4px; }\r\n"
|
" border: 1px solid var(--main-link-color); font-size: 14px; }\r\n"
|
||||||
" .content { float: none; margin-left: unset; margin-top: 16px; max-width: 100%; width: 100%;\r\n"
|
"input:focus, select:focus, select option:focus { outline: none; }\r\n"
|
||||||
" text-align: center; }\r\n"
|
"input[type=number]::-webkit-inner-spin-button { -webkit-appearance: none; }\r\n"
|
||||||
" a, .slide label { /* margin-right: 10px; */ display: block; /* font-size: 18px; */ }\r\n"
|
"@media screen and (max-width: 1150px) { /* adaptive style */\r\n"
|
||||||
" .header { margin: unset; font-size: 1.5em; } small {display: block}\r\n"
|
" .wrapper { max-width: 58em; }\r\n"
|
||||||
" a.button { -webkit-appearance: button; -moz-appearance: button; appearance: button; text-decoration: none;\r\n"
|
" .content { max-width: 40em; }\r\n"
|
||||||
" margin-top: 10px; padding: 6px; border: 1px solid #894c84; width: -webkit-fill-available; }\r\n"
|
"}\r\n"
|
||||||
" input, select { width: 35%; text-align: center; padding: 5px;\r\n"
|
"@media screen and (max-width: 980px) { body { font: 100%/1.2em sans-serif; padding: 1.2em 0 0 0; }\r\n"
|
||||||
" border: 2px solid #ccc; -webkit-border-radius: 5px; border-radius: 5px; font-size: 18px; }\r\n"
|
" .menu { width: 100%; max-width: unset; display: block; float: none; position: unset; font-size: 16px; text-align: center; }\r\n"
|
||||||
" table.extaddr { margin: auto; text-align: unset; }\r\n"
|
" .menu a, .commands a { display: inline-block; padding: 4px; }\r\n"
|
||||||
" textarea { width: -webkit-fill-available; height: auto; padding:5px; border:2px solid #ccc;\r\n"
|
" .content { float: none; margin-left: unset; margin-top: 16px; max-width: 100%; width: 100%; text-align: center; }\r\n"
|
||||||
" -webkit-border-radius: 5px; border-radius: 5px; font-size: 12px; }\r\n"
|
" a, .slide label { display: block; }\r\n"
|
||||||
" button[type=submit] { padding: 5px 15px; background: #ccc; border: 0 none; cursor: pointer;\r\n"
|
" .header { margin: unset; font-size: 1.5em; }\r\n"
|
||||||
" -webkit-border-radius: 5px; border-radius: 5px; position: relative; height: 36px; display: -webkit-inline-box; margin-top: 10px; }\r\n"
|
" small { display: block; }\r\n"
|
||||||
" }\r\n"
|
" a.button { appearance: button; text-decoration: none; margin-top: 10px; padding: 6px; border: 2px solid var(--main-link-color);\r\n"
|
||||||
|
" border-radius: 5px; width: -webkit-fill-available; }\r\n"
|
||||||
|
" input, select { width: 35%; text-align: center; padding: 5px; border: 2px solid var(--main-link-color); border-radius: 5px; font-size: 18px; }\r\n"
|
||||||
|
" table.extaddr { margin: auto; text-align: unset; }\r\n"
|
||||||
|
" textarea { width: -webkit-fill-available; height: auto; padding: 5px; border: 2px solid var(--main-link-color);\r\n"
|
||||||
|
" border-radius: 5px; font-size: 12px; }\r\n"
|
||||||
|
" button[type=submit] { padding: 5px 15px; background: transparent; border: 2px solid var(--main-link-color); cursor: pointer;\r\n"
|
||||||
|
" border-radius: 5px; position: relative; height: 36px; display: -webkit-inline-box; margin-top: 10px; }\r\n"
|
||||||
|
"}\r\n"
|
||||||
"</style>\r\n";
|
"</style>\r\n";
|
||||||
|
|
||||||
// for external style sheet
|
// for external style sheet
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
/*
|
||||||
|
* 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 <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <openssl/x509.h>
|
#include <openssl/x509.h>
|
||||||
|
@ -48,39 +56,38 @@ namespace client
|
||||||
if (i2pcp_key.at(0) != '/')
|
if (i2pcp_key.at(0) != '/')
|
||||||
i2pcp_key = i2p::fs::DataDirPath(i2pcp_key);
|
i2pcp_key = i2p::fs::DataDirPath(i2pcp_key);
|
||||||
if (!i2p::fs::Exists (i2pcp_crt) || !i2p::fs::Exists (i2pcp_key)) {
|
if (!i2p::fs::Exists (i2pcp_crt) || !i2p::fs::Exists (i2pcp_key)) {
|
||||||
LogPrint (eLogInfo, "I2PControl: creating new certificate for control connection");
|
LogPrint (eLogInfo, "I2PControl: Creating new certificate for control connection");
|
||||||
CreateCertificate (i2pcp_crt.c_str(), i2pcp_key.c_str());
|
CreateCertificate (i2pcp_crt.c_str(), i2pcp_key.c_str());
|
||||||
} else {
|
} else {
|
||||||
LogPrint(eLogDebug, "I2PControl: using cert from ", i2pcp_crt);
|
LogPrint(eLogDebug, "I2PControl: Using cert from ", i2pcp_crt);
|
||||||
}
|
}
|
||||||
m_SSLContext.set_options (boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::single_dh_use);
|
m_SSLContext.set_options (boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::single_dh_use);
|
||||||
m_SSLContext.use_certificate_file (i2pcp_crt, boost::asio::ssl::context::pem);
|
m_SSLContext.use_certificate_file (i2pcp_crt, boost::asio::ssl::context::pem);
|
||||||
m_SSLContext.use_private_key_file (i2pcp_key, boost::asio::ssl::context::pem);
|
m_SSLContext.use_private_key_file (i2pcp_key, boost::asio::ssl::context::pem);
|
||||||
|
|
||||||
// handlers
|
// handlers
|
||||||
m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler;
|
m_MethodHandlers["Authenticate"] = &I2PControlService::AuthenticateHandler;
|
||||||
m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler;
|
m_MethodHandlers["Echo"] = &I2PControlService::EchoHandler;
|
||||||
m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler;
|
m_MethodHandlers["I2PControl"] = &I2PControlService::I2PControlHandler;
|
||||||
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
|
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
|
||||||
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
|
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
|
||||||
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
|
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
|
||||||
m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
|
m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
|
||||||
|
|
||||||
// I2PControl
|
// I2PControl
|
||||||
m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler;
|
m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler;
|
||||||
|
|
||||||
// RouterInfo
|
// RouterInfo
|
||||||
m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler;
|
m_RouterInfoHandlers["i2p.router.uptime"] = &I2PControlService::UptimeHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler;
|
m_RouterInfoHandlers["i2p.router.version"] = &I2PControlService::VersionHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler;
|
m_RouterInfoHandlers["i2p.router.status"] = &I2PControlService::StatusHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler;
|
m_RouterInfoHandlers["i2p.router.netdb.knownpeers"] = &I2PControlService::NetDbKnownPeersHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler;
|
m_RouterInfoHandlers["i2p.router.netdb.activepeers"] = &I2PControlService::NetDbActivePeersHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.net.bw.inbound.1s"] = &I2PControlService::InboundBandwidth1S;
|
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.bw.outbound.1s"] = &I2PControlService::OutboundBandwidth1S;
|
||||||
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
|
m_RouterInfoHandlers["i2p.router.net.status"] = &I2PControlService::NetStatusHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler;
|
m_RouterInfoHandlers["i2p.router.net.tunnels.participating"] = &I2PControlService::TunnelsParticipatingHandler;
|
||||||
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] =
|
m_RouterInfoHandlers["i2p.router.net.tunnels.successrate"] = &I2PControlService::TunnelsSuccessRateHandler;
|
||||||
&I2PControlService::TunnelsSuccessRateHandler;
|
|
||||||
m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes;
|
m_RouterInfoHandlers["i2p.router.net.total.received.bytes"] = &I2PControlService::NetTotalReceivedBytes;
|
||||||
m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes;
|
m_RouterInfoHandlers["i2p.router.net.total.sent.bytes"] = &I2PControlService::NetTotalSentBytes;
|
||||||
|
|
||||||
|
@ -96,10 +103,10 @@ namespace client
|
||||||
// ClientServicesInfo
|
// ClientServicesInfo
|
||||||
m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler;
|
m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler;
|
||||||
m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler;
|
m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler;
|
||||||
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
|
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
|
||||||
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
|
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
|
||||||
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
|
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
|
||||||
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
|
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
I2PControlService::~I2PControlService ()
|
I2PControlService::~I2PControlService ()
|
||||||
|
@ -142,7 +149,7 @@ namespace client
|
||||||
try {
|
try {
|
||||||
m_Service.run ();
|
m_Service.run ();
|
||||||
} catch (std::exception& ex) {
|
} catch (std::exception& ex) {
|
||||||
LogPrint (eLogError, "I2PControl: runtime exception: ", ex.what ());
|
LogPrint (eLogError, "I2PControl: Runtime exception: ", ex.what ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,10 +167,10 @@ namespace client
|
||||||
Accept ();
|
Accept ();
|
||||||
|
|
||||||
if (ecode) {
|
if (ecode) {
|
||||||
LogPrint (eLogError, "I2PControl: accept error: ", ecode.message ());
|
LogPrint (eLogError, "I2PControl: Accept error: ", ecode.message ());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LogPrint (eLogDebug, "I2PControl: new request from ", socket->lowest_layer ().remote_endpoint ());
|
LogPrint (eLogDebug, "I2PControl: New request from ", socket->lowest_layer ().remote_endpoint ());
|
||||||
Handshake (socket);
|
Handshake (socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +183,7 @@ namespace client
|
||||||
void I2PControlService::HandleHandshake (const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> socket)
|
void I2PControlService::HandleHandshake (const boost::system::error_code& ecode, std::shared_ptr<ssl_socket> socket)
|
||||||
{
|
{
|
||||||
if (ecode) {
|
if (ecode) {
|
||||||
LogPrint (eLogError, "I2PControl: handshake error: ", ecode.message ());
|
LogPrint (eLogError, "I2PControl: Handshake error: ", ecode.message ());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//std::this_thread::sleep_for (std::chrono::milliseconds(5));
|
//std::this_thread::sleep_for (std::chrono::milliseconds(5));
|
||||||
|
@ -202,7 +209,7 @@ namespace client
|
||||||
{
|
{
|
||||||
if (ecode)
|
if (ecode)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "I2PControl: read error: ", ecode.message ());
|
LogPrint (eLogError, "I2PControl: Read error: ", ecode.message ());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -225,7 +232,7 @@ namespace client
|
||||||
}
|
}
|
||||||
if (ss.eof ())
|
if (ss.eof ())
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "I2PControl: malformed request, HTTP header expected");
|
LogPrint (eLogError, "I2PControl: Malformed request, HTTP header expected");
|
||||||
return; // TODO:
|
return; // TODO:
|
||||||
}
|
}
|
||||||
std::streamoff rem = contentLength + ss.tellg () - bytes_transferred; // more bytes to read
|
std::streamoff rem = contentLength + ss.tellg () - bytes_transferred; // more bytes to read
|
||||||
|
@ -250,7 +257,7 @@ namespace client
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "I2PControl: unknown method ", method);
|
LogPrint (eLogWarning, "I2PControl: Unknown method ", method);
|
||||||
response << "{\"id\":null,\"error\":";
|
response << "{\"id\":null,\"error\":";
|
||||||
response << "{\"code\":-32601,\"message\":\"Method not found\"},";
|
response << "{\"code\":-32601,\"message\":\"Method not found\"},";
|
||||||
response << "\"jsonrpc\":\"2.0\"}";
|
response << "\"jsonrpc\":\"2.0\"}";
|
||||||
|
@ -259,7 +266,7 @@ namespace client
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "I2PControl: exception when handle request: ", ex.what ());
|
LogPrint (eLogError, "I2PControl: Exception when handle request: ", ex.what ());
|
||||||
std::ostringstream response;
|
std::ostringstream response;
|
||||||
response << "{\"id\":null,\"error\":";
|
response << "{\"id\":null,\"error\":";
|
||||||
response << "{\"code\":-32700,\"message\":\"" << ex.what () << "\"},";
|
response << "{\"code\":-32700,\"message\":\"" << ex.what () << "\"},";
|
||||||
|
@ -268,7 +275,7 @@ namespace client
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "I2PControl: handle request unknown exception");
|
LogPrint (eLogError, "I2PControl: Handle request unknown exception");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -278,11 +285,16 @@ namespace client
|
||||||
ss << "\"" << name << "\":" << value;
|
ss << "\"" << name << "\":" << value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2PControlService::InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value) const
|
void I2PControlService::InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value, bool quotes) const
|
||||||
{
|
{
|
||||||
ss << "\"" << name << "\":";
|
ss << "\"" << name << "\":";
|
||||||
if (value.length () > 0)
|
if (value.length () > 0)
|
||||||
ss << "\"" << value << "\"";
|
{
|
||||||
|
if (quotes)
|
||||||
|
ss << "\"" << value << "\"";
|
||||||
|
else
|
||||||
|
ss << value;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ss << "null";
|
ss << "null";
|
||||||
}
|
}
|
||||||
|
@ -329,7 +341,7 @@ namespace client
|
||||||
std::shared_ptr<ssl_socket> socket, std::shared_ptr<I2PControlBuffer> buf)
|
std::shared_ptr<ssl_socket> socket, std::shared_ptr<I2PControlBuffer> buf)
|
||||||
{
|
{
|
||||||
if (ecode) {
|
if (ecode) {
|
||||||
LogPrint (eLogError, "I2PControl: write error: ", ecode.message ());
|
LogPrint (eLogError, "I2PControl: Write error: ", ecode.message ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,7 +391,7 @@ namespace client
|
||||||
|
|
||||||
void I2PControlService::PasswordHandler (const std::string& value)
|
void I2PControlService::PasswordHandler (const std::string& value)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "I2PControl: new password=", value, ", to make it persistent you should update your config!");
|
LogPrint (eLogWarning, "I2PControl: New password=", value, ", to make it persistent you should update your config!");
|
||||||
m_Password = value;
|
m_Password = value;
|
||||||
m_Tokens.clear ();
|
m_Tokens.clear ();
|
||||||
}
|
}
|
||||||
|
@ -406,7 +418,7 @@ namespace client
|
||||||
|
|
||||||
void I2PControlService::UptimeHandler (std::ostringstream& results)
|
void I2PControlService::UptimeHandler (std::ostringstream& results)
|
||||||
{
|
{
|
||||||
InsertParam (results, "i2p.router.uptime", std::to_string (i2p::context.GetUptime ()*1000LL));
|
InsertParam (results, "i2p.router.uptime", std::to_string (i2p::context.GetUptime ()*1000LL), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2PControlService::VersionHandler (std::ostringstream& results)
|
void I2PControlService::VersionHandler (std::ostringstream& results)
|
||||||
|
@ -466,7 +478,7 @@ namespace client
|
||||||
|
|
||||||
void I2PControlService::NetTotalSentBytes (std::ostringstream& results)
|
void I2PControlService::NetTotalSentBytes (std::ostringstream& results)
|
||||||
{
|
{
|
||||||
InsertParam (results, "i2p.router.net.total.sent.bytes", (double)i2p::transport::transports.GetTotalSentBytes ());
|
InsertParam (results, "i2p.router.net.total.sent.bytes", (double)i2p::transport::transports.GetTotalSentBytes ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -494,7 +506,7 @@ namespace client
|
||||||
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(1)); // 1 second to make sure response has been sent
|
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(1)); // 1 second to make sure response has been sent
|
||||||
m_ShutdownTimer.async_wait (
|
m_ShutdownTimer.async_wait (
|
||||||
[](const boost::system::error_code& ecode)
|
[](const boost::system::error_code& ecode)
|
||||||
{
|
{
|
||||||
Daemon.running = 0;
|
Daemon.running = 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -508,7 +520,7 @@ namespace client
|
||||||
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(timeout + 1)); // + 1 second
|
m_ShutdownTimer.expires_from_now (boost::posix_time::seconds(timeout + 1)); // + 1 second
|
||||||
m_ShutdownTimer.async_wait (
|
m_ShutdownTimer.async_wait (
|
||||||
[](const boost::system::error_code& ecode)
|
[](const boost::system::error_code& ecode)
|
||||||
{
|
{
|
||||||
Daemon.running = 0;
|
Daemon.running = 0;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -577,11 +589,11 @@ namespace client
|
||||||
|
|
||||||
// save cert
|
// save cert
|
||||||
if ((f = fopen (crt_path, "wb")) != NULL) {
|
if ((f = fopen (crt_path, "wb")) != NULL) {
|
||||||
LogPrint (eLogInfo, "I2PControl: saving new cert to ", crt_path);
|
LogPrint (eLogInfo, "I2PControl: Saving new cert to ", crt_path);
|
||||||
PEM_write_X509 (f, x509);
|
PEM_write_X509 (f, x509);
|
||||||
fclose (f);
|
fclose (f);
|
||||||
} else {
|
} else {
|
||||||
LogPrint (eLogError, "I2PControl: can't write cert: ", strerror(errno));
|
LogPrint (eLogError, "I2PControl: Can't write cert: ", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
// save key
|
// save key
|
||||||
|
@ -590,12 +602,12 @@ namespace client
|
||||||
PEM_write_PrivateKey (f, pkey, NULL, NULL, 0, NULL, NULL);
|
PEM_write_PrivateKey (f, pkey, NULL, NULL, 0, NULL, NULL);
|
||||||
fclose (f);
|
fclose (f);
|
||||||
} else {
|
} else {
|
||||||
LogPrint (eLogError, "I2PControl: can't write key: ", strerror(errno));
|
LogPrint (eLogError, "I2PControl: Can't write key: ", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
X509_free (x509);
|
X509_free (x509);
|
||||||
} else {
|
} else {
|
||||||
LogPrint (eLogError, "I2PControl: can't create RSA key for certificate");
|
LogPrint (eLogError, "I2PControl: Can't create RSA key for certificate");
|
||||||
}
|
}
|
||||||
EVP_PKEY_free (pkey);
|
EVP_PKEY_free (pkey);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -65,7 +65,7 @@ namespace client
|
||||||
|
|
||||||
void InsertParam (std::ostringstream& ss, const std::string& name, int value) const;
|
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, double value) const;
|
||||||
void InsertParam (std::ostringstream& ss, const std::string& name, const std::string& 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;
|
void InsertParam (std::ostringstream& ss, const std::string& name, const boost::property_tree::ptree& value) const;
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace transport
|
||||||
{
|
{
|
||||||
if (m_IsRunning)
|
if (m_IsRunning)
|
||||||
{
|
{
|
||||||
LogPrint(eLogInfo, "UPnP: stopping");
|
LogPrint(eLogInfo, "UPnP: Stopping");
|
||||||
m_IsRunning = false;
|
m_IsRunning = false;
|
||||||
m_Timer.cancel ();
|
m_Timer.cancel ();
|
||||||
m_Service.stop ();
|
m_Service.stop ();
|
||||||
|
@ -46,7 +46,7 @@ namespace transport
|
||||||
void UPnP::Start()
|
void UPnP::Start()
|
||||||
{
|
{
|
||||||
m_IsRunning = true;
|
m_IsRunning = true;
|
||||||
LogPrint(eLogInfo, "UPnP: starting");
|
LogPrint(eLogInfo, "UPnP: Starting");
|
||||||
m_Service.post (std::bind (&UPnP::Discover, this));
|
m_Service.post (std::bind (&UPnP::Discover, this));
|
||||||
std::unique_lock<std::mutex> l(m_StartedMutex);
|
std::unique_lock<std::mutex> l(m_StartedMutex);
|
||||||
m_Thread.reset (new std::thread (std::bind (&UPnP::Run, this)));
|
m_Thread.reset (new std::thread (std::bind (&UPnP::Run, this)));
|
||||||
|
@ -72,7 +72,7 @@ namespace transport
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "UPnP: runtime exception: ", ex.what ());
|
LogPrint (eLogError, "UPnP: Runtime exception: ", ex.what ());
|
||||||
PortMapping ();
|
PortMapping ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ namespace transport
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
isError = err != UPNPDISCOVER_SUCCESS;
|
isError = err != UPNPDISCOVER_SUCCESS;
|
||||||
#else // MINIUPNPC_API_VERSION >= 8
|
#else // MINIUPNPC_API_VERSION >= 8
|
||||||
err = 0;
|
err = 0;
|
||||||
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
|
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
|
||||||
isError = m_Devlist == NULL;
|
isError = m_Devlist == NULL;
|
||||||
|
@ -106,7 +106,7 @@ namespace transport
|
||||||
|
|
||||||
if (isError)
|
if (isError)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "UPnP: unable to discover Internet Gateway Devices: error ", err);
|
LogPrint (eLogError, "UPnP: Unable to discover Internet Gateway Devices: error ", err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,22 +117,22 @@ namespace transport
|
||||||
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
|
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
|
||||||
if(err != UPNPCOMMAND_SUCCESS)
|
if(err != UPNPCOMMAND_SUCCESS)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "UPnP: unable to get external address: error ", err);
|
LogPrint (eLogError, "UPnP: Unable to get external address: error ", err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "UPnP: found Internet Gateway Device ", m_upnpUrls.controlURL);
|
LogPrint (eLogError, "UPnP: Found Internet Gateway Device ", m_upnpUrls.controlURL);
|
||||||
if (!m_externalIPAddress[0])
|
if (!m_externalIPAddress[0])
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "UPnP: found Internet Gateway Device doesn't know our external address");
|
LogPrint (eLogError, "UPnP: Found Internet Gateway Device doesn't know our external address");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "UPnP: unable to find valid Internet Gateway Device: error ", err);
|
LogPrint (eLogError, "UPnP: Unable to find valid Internet Gateway Device: error ", err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +183,7 @@ namespace transport
|
||||||
err = CheckMapping (strPort.c_str (), strType.c_str ());
|
err = CheckMapping (strPort.c_str (), strType.c_str ());
|
||||||
if (err != UPNPCOMMAND_SUCCESS) // if mapping not found
|
if (err != UPNPCOMMAND_SUCCESS) // if mapping not found
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "UPnP: possibly port ", strPort, " is not forwarded: return code ", err);
|
LogPrint (eLogDebug, "UPnP: Port ", strPort, " is possibly not forwarded: return code ", err);
|
||||||
|
|
||||||
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
|
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
|
||||||
err = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), NULL, NULL);
|
err = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), NULL, NULL);
|
||||||
|
@ -192,18 +192,18 @@ namespace transport
|
||||||
#endif
|
#endif
|
||||||
if (err != UPNPCOMMAND_SUCCESS)
|
if (err != UPNPCOMMAND_SUCCESS)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "UPnP: port forwarding to ", m_NetworkAddr, ":", strPort, " failed: return code ", err);
|
LogPrint (eLogError, "UPnP: Port forwarding to ", m_NetworkAddr, ":", strPort, " failed: return code ", err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogInfo, "UPnP: port successfully forwarded (", m_externalIPAddress ,":", strPort, " type ", strType, " -> ", m_NetworkAddr ,":", strPort ,")");
|
LogPrint (eLogInfo, "UPnP: Port successfully forwarded (", m_externalIPAddress ,":", strPort, " type ", strType, " -> ", m_NetworkAddr ,":", strPort ,")");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "UPnP: external forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device");
|
LogPrint (eLogDebug, "UPnP: External forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace transport
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void Discover ();
|
void Discover ();
|
||||||
int CheckMapping (const char* port, const char* type);
|
int CheckMapping (const char* port, const char* type);
|
||||||
void PortMapping ();
|
void PortMapping ();
|
||||||
void TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
|
void TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
|
||||||
void CloseMapping ();
|
void CloseMapping ();
|
||||||
|
@ -80,7 +80,7 @@ namespace transport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // USE_UPNP
|
#else // USE_UPNP
|
||||||
namespace i2p {
|
namespace i2p {
|
||||||
namespace transport {
|
namespace transport {
|
||||||
/* class stub */
|
/* class stub */
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "Tunnel.h"
|
#include "Tunnel.h"
|
||||||
#include "RouterContext.h"
|
#include "RouterContext.h"
|
||||||
#include "ClientContext.h"
|
#include "ClientContext.h"
|
||||||
|
#include "Transports.h"
|
||||||
|
|
||||||
void handle_signal(int sig)
|
void handle_signal(int sig)
|
||||||
{
|
{
|
||||||
|
@ -54,6 +55,14 @@ void handle_signal(int sig)
|
||||||
case SIGPIPE:
|
case SIGPIPE:
|
||||||
LogPrint(eLogInfo, "SIGPIPE received");
|
LogPrint(eLogInfo, "SIGPIPE received");
|
||||||
break;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +81,8 @@ namespace i2p
|
||||||
|
|
||||||
if (pid < 0) // error
|
if (pid < 0) // error
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "Daemon: could not fork: ", strerror(errno));
|
LogPrint(eLogError, "Daemon: Could not fork: ", strerror(errno));
|
||||||
|
std::cerr << "i2pd: Could not fork: " << strerror(errno) << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,13 +91,15 @@ namespace i2p
|
||||||
int sid = setsid();
|
int sid = setsid();
|
||||||
if (sid < 0)
|
if (sid < 0)
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "Daemon: could not create process group.");
|
LogPrint(eLogError, "Daemon: Could not create process group.");
|
||||||
|
std::cerr << "i2pd: Could not create process group." << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::string d = i2p::fs::GetDataDir();
|
std::string d = i2p::fs::GetDataDir();
|
||||||
if (chdir(d.c_str()) != 0)
|
if (chdir(d.c_str()) != 0)
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "Daemon: could not chdir: ", strerror(errno));
|
LogPrint(eLogError, "Daemon: Could not chdir: ", strerror(errno));
|
||||||
|
std::cerr << "i2pd: Could not chdir: " << strerror(errno) << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,14 +114,14 @@ namespace i2p
|
||||||
uint16_t nfiles; i2p::config::GetOption("limits.openfiles", nfiles);
|
uint16_t nfiles; i2p::config::GetOption("limits.openfiles", nfiles);
|
||||||
getrlimit(RLIMIT_NOFILE, &limit);
|
getrlimit(RLIMIT_NOFILE, &limit);
|
||||||
if (nfiles == 0) {
|
if (nfiles == 0) {
|
||||||
LogPrint(eLogInfo, "Daemon: using system limit in ", limit.rlim_cur, " max open files");
|
LogPrint(eLogInfo, "Daemon: Using system limit in ", limit.rlim_cur, " max open files");
|
||||||
} else if (nfiles <= limit.rlim_max) {
|
} else if (nfiles <= limit.rlim_max) {
|
||||||
limit.rlim_cur = nfiles;
|
limit.rlim_cur = nfiles;
|
||||||
if (setrlimit(RLIMIT_NOFILE, &limit) == 0) {
|
if (setrlimit(RLIMIT_NOFILE, &limit) == 0) {
|
||||||
LogPrint(eLogInfo, "Daemon: set max number of open files to ",
|
LogPrint(eLogInfo, "Daemon: Set max number of open files to ",
|
||||||
nfiles, " (system limit is ", limit.rlim_max, ")");
|
nfiles, " (system limit is ", limit.rlim_max, ")");
|
||||||
} else {
|
} else {
|
||||||
LogPrint(eLogError, "Daemon: can't set max number of open files: ", strerror(errno));
|
LogPrint(eLogError, "Daemon: Can't set max number of open files: ", strerror(errno));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LogPrint(eLogError, "Daemon: limits.openfiles exceeds system limit: ", limit.rlim_max);
|
LogPrint(eLogError, "Daemon: limits.openfiles exceeds system limit: ", limit.rlim_max);
|
||||||
|
@ -122,11 +134,11 @@ namespace i2p
|
||||||
if (cfsize <= limit.rlim_max) {
|
if (cfsize <= limit.rlim_max) {
|
||||||
limit.rlim_cur = cfsize;
|
limit.rlim_cur = cfsize;
|
||||||
if (setrlimit(RLIMIT_CORE, &limit) != 0) {
|
if (setrlimit(RLIMIT_CORE, &limit) != 0) {
|
||||||
LogPrint(eLogError, "Daemon: can't set max size of coredump: ", strerror(errno));
|
LogPrint(eLogError, "Daemon: Can't set max size of coredump: ", strerror(errno));
|
||||||
} else if (cfsize == 0) {
|
} else if (cfsize == 0) {
|
||||||
LogPrint(eLogInfo, "Daemon: coredumps disabled");
|
LogPrint(eLogInfo, "Daemon: coredumps disabled");
|
||||||
} else {
|
} else {
|
||||||
LogPrint(eLogInfo, "Daemon: set max size of core files to ", cfsize / 1024, "Kb");
|
LogPrint(eLogInfo, "Daemon: Set max size of core files to ", cfsize / 1024, "Kb");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LogPrint(eLogError, "Daemon: limits.coresize exceeds system limit: ", limit.rlim_max);
|
LogPrint(eLogError, "Daemon: limits.coresize exceeds system limit: ", limit.rlim_max);
|
||||||
|
@ -143,14 +155,16 @@ namespace i2p
|
||||||
pidFH = open(pidfile.c_str(), O_RDWR | O_CREAT, 0600);
|
pidFH = open(pidfile.c_str(), O_RDWR | O_CREAT, 0600);
|
||||||
if (pidFH < 0)
|
if (pidFH < 0)
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "Daemon: could not create pid file ", pidfile, ": ", strerror(errno));
|
LogPrint(eLogError, "Daemon: Could not create pid file ", pidfile, ": ", strerror(errno));
|
||||||
|
std::cerr << "i2pd: Could not create pid file " << pidfile << ": " << strerror(errno) << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
if (lockf(pidFH, F_TLOCK, 0) != 0)
|
if (lockf(pidFH, F_TLOCK, 0) != 0)
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "Daemon: could not lock pid file ", pidfile, ": ", strerror(errno));
|
LogPrint(eLogError, "Daemon: Could not lock pid file ", pidfile, ": ", strerror(errno));
|
||||||
|
std::cerr << "i2pd: Could not lock pid file " << pidfile << ": " << strerror(errno) << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -159,12 +173,16 @@ namespace i2p
|
||||||
ftruncate(pidFH, 0);
|
ftruncate(pidFH, 0);
|
||||||
if (write(pidFH, pid, strlen(pid)) < 0)
|
if (write(pidFH, pid, strlen(pid)) < 0)
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "Daemon: could not write pidfile: ", strerror(errno));
|
LogPrint(eLogError, "Daemon: Could not write pidfile ", pidfile, ": ", strerror(errno));
|
||||||
|
std::cerr << "i2pd: Could not write pidfile " << pidfile << ": " << strerror(errno) << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gracefulShutdownInterval = 0; // not specified
|
gracefulShutdownInterval = 0; // not specified
|
||||||
|
|
||||||
|
// handle signal TSTP
|
||||||
|
bool handleTSTP; i2p::config::GetOption("unix.handle_sigtstp", handleTSTP);
|
||||||
|
|
||||||
// Signal handler
|
// Signal handler
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
sa.sa_handler = handle_signal;
|
sa.sa_handler = handle_signal;
|
||||||
|
@ -176,6 +194,11 @@ namespace i2p
|
||||||
sigaction(SIGTERM, &sa, 0);
|
sigaction(SIGTERM, &sa, 0);
|
||||||
sigaction(SIGINT, &sa, 0);
|
sigaction(SIGINT, &sa, 0);
|
||||||
sigaction(SIGPIPE, &sa, 0);
|
sigaction(SIGPIPE, &sa, 0);
|
||||||
|
if (handleTSTP)
|
||||||
|
{
|
||||||
|
sigaction(SIGTSTP, &sa, 0);
|
||||||
|
sigaction(SIGCONT, &sa, 0);
|
||||||
|
}
|
||||||
|
|
||||||
return Daemon_Singleton::start();
|
return Daemon_Singleton::start();
|
||||||
}
|
}
|
||||||
|
|
25
debian/changelog
vendored
25
debian/changelog
vendored
|
@ -1,3 +1,28 @@
|
||||||
|
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
|
||||||
|
|
||||||
|
-- r4sas <r4sas@i2pmail.org> Sun, 20 Feb 2022 13:00:00 +0000
|
||||||
|
|
||||||
|
i2pd (2.40.0-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* updated to version 2.40.0/0.9.52
|
||||||
|
|
||||||
|
-- orignal <orignal@i2pmail.org> Mon, 29 Nov 2021 16:00:00 +0000
|
||||||
|
|
||||||
i2pd (2.39.0-1) unstable; urgency=medium
|
i2pd (2.39.0-1) unstable; urgency=medium
|
||||||
|
|
||||||
* updated to version 2.39.0/0.9.51
|
* updated to version 2.39.0/0.9.51
|
||||||
|
|
18
debian/patches/02-upnp.patch
vendored
18
debian/patches/02-upnp.patch
vendored
|
@ -2,16 +2,16 @@ Description: Enable UPnP usage in package
|
||||||
Author: r4sas <r4sas@i2pmail.org>
|
Author: r4sas <r4sas@i2pmail.org>
|
||||||
|
|
||||||
Reviewed-By: r4sas <r4sas@i2pmail.org>
|
Reviewed-By: r4sas <r4sas@i2pmail.org>
|
||||||
Last-Update: 2021-01-16
|
Last-Update: 2022-03-23
|
||||||
|
|
||||||
--- i2pd.orig/Makefile
|
--- i2pd.orig/Makefile
|
||||||
+++ i2pd/Makefile
|
+++ i2pd/Makefile
|
||||||
@@ -21,7 +21,7 @@ include filelist.mk
|
@@ -31,7 +31,7 @@ include filelist.mk
|
||||||
USE_AESNI := $(or $(USE_AESNI),yes)
|
|
||||||
USE_STATIC := $(or $(USE_STATIC),no)
|
|
||||||
USE_MESHNET := $(or $(USE_MESHNET),no)
|
|
||||||
-USE_UPNP := $(or $(USE_UPNP),no)
|
|
||||||
+USE_UPNP := $(or $(USE_UPNP),yes)
|
|
||||||
DEBUG := $(or $(DEBUG),yes)
|
|
||||||
|
|
||||||
ifeq ($(DEBUG),yes)
|
USE_AESNI := $(or $(USE_AESNI),yes)
|
||||||
|
USE_STATIC := $(or $(USE_STATIC),no)
|
||||||
|
-USE_UPNP := $(or $(USE_UPNP),no)
|
||||||
|
+USE_UPNP := $(or $(USE_UPNP),yes)
|
||||||
|
DEBUG := $(or $(DEBUG),yes)
|
||||||
|
|
||||||
|
# for debugging purposes only, when commit hash needed in trunk builds in i2pd version string
|
||||||
|
|
9
debian/rules
vendored
9
debian/rules
vendored
|
@ -1,16 +1,13 @@
|
||||||
#!/usr/bin/make -f
|
#!/usr/bin/make -f
|
||||||
#export DH_VERBOSE=1
|
#export DH_VERBOSE=1
|
||||||
|
|
||||||
|
|
||||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||||
|
|
||||||
|
|
||||||
include /usr/share/dpkg/architecture.mk
|
include /usr/share/dpkg/architecture.mk
|
||||||
|
|
||||||
export DEB_CXXFLAGS_MAINT_APPEND = -Wall -pedantic -O3
|
export DEB_CXXFLAGS_MAINT_APPEND = -Wall -pedantic
|
||||||
|
|
||||||
export DEB_LDFLAGS_MAINT_APPEND =
|
export DEB_LDFLAGS_MAINT_APPEND =
|
||||||
|
|
||||||
|
|
||||||
%:
|
%:
|
||||||
dh $@ --parallel
|
dh $@ --parallel
|
||||||
|
|
||||||
|
override_dh_auto_install:
|
||||||
|
|
215
i18n/Armenian.cpp
Normal file
215
i18n/Armenian.cpp
Normal file
|
@ -0,0 +1,215 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, 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"
|
||||||
|
|
||||||
|
// Armenian localization file
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace i18n
|
||||||
|
{
|
||||||
|
namespace armenian // language namespace
|
||||||
|
{
|
||||||
|
// language name in lowercase
|
||||||
|
static std::string language = "armenian";
|
||||||
|
|
||||||
|
// 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", "ԿիԲ"},
|
||||||
|
{"MiB", "ՄիԲ"},
|
||||||
|
{"GiB", "ԳիԲ"},
|
||||||
|
{"building", "կառուցվում է"},
|
||||||
|
{"failed", "Անհաջող"},
|
||||||
|
{"expiring", "Լրանում է"},
|
||||||
|
{"established", "կարգավոյված է"},
|
||||||
|
{"unknown", "անհայտ"},
|
||||||
|
{"exploratory", "հետազոտոկան"},
|
||||||
|
{"<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", "Ցանցի կարգավիճակ"},
|
||||||
|
{"Network status v6", "Ցանցի կարգավիճակ v6"},
|
||||||
|
{"Stopping in", "Դադարում"},
|
||||||
|
{"Family", "Խմբատեսակ"},
|
||||||
|
{"Tunnel creation success rate", "Հաջողությամբ կառուցված թունելներ"},
|
||||||
|
{"Received", "Ստացվել է"},
|
||||||
|
{"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", "Floodfills-ներ"},
|
||||||
|
{"Client Tunnels", "Oգտատիրական թունելներ"},
|
||||||
|
{"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> արդյունքի տողը կարող է օգտագործվել միայն 2LD տիրույթներ գրանցելու համար (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", "Չսպառված Lease-եր"},
|
||||||
|
{"Gateway", "Դարպաս"},
|
||||||
|
{"TunnelID", "Թունելի ID"},
|
||||||
|
{"EndDate", "Ավարտ"},
|
||||||
|
{"not floodfill", "ոչ 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", "Ստորև Դուք կարող եք գտնել այս հոսթը jump ծառայությունների միջոցով"},
|
||||||
|
{"Invalid request", "Սխալ հարցում"},
|
||||||
|
{"Proxy unable to parse your request", "Պրոկսին չի կարող հասկանալ Ձեր հարցումը"},
|
||||||
|
{"addresshelper is not supported", "addresshelper-ը համատեղելի չէ"},
|
||||||
|
{"Host", "Հոսթ"},
|
||||||
|
{"added to router's addressbook from helper", "Ավելացված է երթուղիչի հասցեագրքում helper-ի միջոցով"},
|
||||||
|
{"Click here to proceed:", "Շարունակելու համար սեղմեք այստեղ"},
|
||||||
|
{"Continue", "Շարունակել"},
|
||||||
|
{"Addresshelper found", "addresshelper-ը գնտված է"},
|
||||||
|
{"already in router's addressbook", "արդեն առկա է երթուղիչի հասցեագրքում"},
|
||||||
|
{"Click here to update record:", "Սեղմեկ այստեղ որպեսզի թարվացնեք գրառումը"},
|
||||||
|
{"invalid request uri", "Սխալ ձևավորված URI հարցում"},
|
||||||
|
{"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", "արտաքին պրոքսիի անհայտ URL"},
|
||||||
|
{"cannot resolve upstream proxy", "Չհաջողվեց որոշել վերադաս պրոկսին"},
|
||||||
|
{"hostname too long", "Հոսթի անունը չափազանց երկար է"},
|
||||||
|
{"cannot connect to upstream socks proxy", "չհաջողվեց միանալ վերադաս socks պրոկսիին"},
|
||||||
|
{"Cannot negotiate with socks proxy", "Չհաջողվեց պայմանավորվել վերադաս socks պրոկսիի հետ"},
|
||||||
|
{"CONNECT error", "Սխալ CONNECT հարցում"},
|
||||||
|
{"Failed to Connect", "Միանալ չhաջողվեց"},
|
||||||
|
{"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
|
102
i18n/French.cpp
Normal file
102
i18n/French.cpp
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* 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", "echoué"},
|
||||||
|
{"expiring", "expiré"},
|
||||||
|
{"established", "établi"},
|
||||||
|
{"unknown", "inconnu"},
|
||||||
|
{"exploratory", "exploratoire"},
|
||||||
|
{"<b>i2pd</b> webconsole", "Console web <b>i2pd</b>"},
|
||||||
|
{"Main page", "Page principale"},
|
||||||
|
{"Router commands", "Commandes du routeur"},
|
||||||
|
{"Local Destinations", "Destinations locales"},
|
||||||
|
{"Tunnels", "Tunnels"},
|
||||||
|
{"Transit Tunnels", "Tunnels transitoires"},
|
||||||
|
{"I2P tunnels", "Tunnels I2P"},
|
||||||
|
{"SAM sessions", "Sessions SAM"},
|
||||||
|
{"ERROR", "ERREUR"},
|
||||||
|
{"OK", "OK"},
|
||||||
|
{"Firewalled", "Derrière un pare-feu"},
|
||||||
|
{"Error", "Erreur"},
|
||||||
|
{"Offline", "Hors ligne"},
|
||||||
|
{"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"},
|
||||||
|
{"Hidden content. Press on text to see.", "Contenu caché. Cliquez sur le texte pour regarder."},
|
||||||
|
{"Router Ident", "Identifiant du routeur"},
|
||||||
|
{"Router Family", "Famille du routeur"},
|
||||||
|
{"Version", "Version"},
|
||||||
|
{"Our external address", "Notre adresse externe"},
|
||||||
|
{"Client Tunnels", "Tunnels clients"},
|
||||||
|
{"Services", "Services"},
|
||||||
|
{"Enabled", "Activé"},
|
||||||
|
{"Disabled", "Désactivé"},
|
||||||
|
{"Encrypted B33 address", "Adresse B33 chiffrée"},
|
||||||
|
{"Domain", "Domaine"},
|
||||||
|
{"<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"},
|
||||||
|
{"ms", "ms"},
|
||||||
|
{"Outbound tunnels", "Tunnels sortants"},
|
||||||
|
{"Destination", "Destination"},
|
||||||
|
{"Local Destination", "Destination locale"},
|
||||||
|
{"", ""},
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
215
i18n/German.cpp
Normal file
215
i18n/German.cpp
Normal file
|
@ -0,0 +1,215 @@
|
||||||
|
/*
|
||||||
|
* 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"
|
||||||
|
|
||||||
|
// German localization file
|
||||||
|
|
||||||
|
namespace i2p
|
||||||
|
{
|
||||||
|
namespace i18n
|
||||||
|
{
|
||||||
|
namespace german // language namespace
|
||||||
|
{
|
||||||
|
// language name in lowercase
|
||||||
|
static std::string language = "german";
|
||||||
|
|
||||||
|
// 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 Bau"},
|
||||||
|
{"failed", "fehlgeschlagen"},
|
||||||
|
{"expiring", "läuft ab in"},
|
||||||
|
{"established", "hergestellt"},
|
||||||
|
{"unknown", "Unbekannt"},
|
||||||
|
{"exploratory", "erforschende"},
|
||||||
|
{"<b>i2pd</b> webconsole", "<b>i2pd</b> Webkonsole"},
|
||||||
|
{"Main page", "Startseite"},
|
||||||
|
{"Router commands", "Router Befehle"},
|
||||||
|
{"Local Destinations", "Lokale Destination"},
|
||||||
|
{"LeaseSets", "LeaseSets"},
|
||||||
|
{"Tunnels", "Tunnel"},
|
||||||
|
{"Transit Tunnels", "Transittunnel"},
|
||||||
|
{"Transports", "Transporte"},
|
||||||
|
{"I2P tunnels", "I2P Tunnel"},
|
||||||
|
{"SAM sessions", "SAM Sitzungen"},
|
||||||
|
{"ERROR", "FEHLER"},
|
||||||
|
{"OK", "OK"},
|
||||||
|
{"Testing", "Testen"},
|
||||||
|
{"Firewalled", "Hinter eine Firewall"},
|
||||||
|
{"Unknown", "Unbekannt"},
|
||||||
|
{"Proxy", "Proxy"},
|
||||||
|
{"Mesh", "Mesh"},
|
||||||
|
{"Error", "Fehler"},
|
||||||
|
{"Clock skew", "Zeitabweichung"},
|
||||||
|
{"Offline", "Offline"},
|
||||||
|
{"Symmetric NAT", "Symmetrisches NAT"},
|
||||||
|
{"Uptime", "Laufzeit"},
|
||||||
|
{"Network status", "Netzwerkstatus"},
|
||||||
|
{"Network status v6", "Netzwerkstatus v6"},
|
||||||
|
{"Stopping in", "Stoppt in"},
|
||||||
|
{"Family", "Familie"},
|
||||||
|
{"Tunnel creation success rate", "Erfolgsrate der Tunnelerstellung"},
|
||||||
|
{"Received", "Eingegangen"},
|
||||||
|
{"KiB/s", "KiB/s"},
|
||||||
|
{"Sent", "Gesendet"},
|
||||||
|
{"Transit", "Transit"},
|
||||||
|
{"Data path", "Datenpfad"},
|
||||||
|
{"Hidden content. Press on text to see.", "Versteckter Inhalt. Klicke hier, um ihn zu sehen."},
|
||||||
|
{"Router Ident", "Routeridentität"},
|
||||||
|
{"Router Family", "Routerfamilie"},
|
||||||
|
{"Router Caps", "Routerattribute"},
|
||||||
|
{"Version", "Version"},
|
||||||
|
{"Our external address", "Unsere externe Adresse"},
|
||||||
|
{"supported", "unterstützt"},
|
||||||
|
{"Routers", "Router"},
|
||||||
|
{"Floodfills", "Floodfills"},
|
||||||
|
{"Client Tunnels", "Klienttunnel"},
|
||||||
|
{"Services", "Services"},
|
||||||
|
{"Enabled", "Aktiviert"},
|
||||||
|
{"Disabled", "Deaktiviert"},
|
||||||
|
{"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."},
|
||||||
|
{"Address", "Adresse"},
|
||||||
|
{"Type", "Typ"},
|
||||||
|
{"EncType", "Verschlüsselungstyp"},
|
||||||
|
{"Inbound tunnels", "Eingehende Tunnel"},
|
||||||
|
{"ms", "ms"},
|
||||||
|
{"Outbound tunnels", "Ausgehende Tunnel"},
|
||||||
|
{"Tags", "Tags"},
|
||||||
|
{"Incoming", "Eingehend"},
|
||||||
|
{"Outgoing", "Ausgehend"},
|
||||||
|
{"Destination", "Destination"},
|
||||||
|
{"Amount", "Anzahl"},
|
||||||
|
{"Incoming Tags", "Eingehende Tags"},
|
||||||
|
{"Tags sessions", "Tags Sitzungen"},
|
||||||
|
{"Status", "Status"},
|
||||||
|
{"Local Destination", "Lokale Destination"},
|
||||||
|
{"Streams", "Streams"},
|
||||||
|
{"Close stream", "Stream schließen"},
|
||||||
|
{"I2CP session not found", "I2CP Sitzung nicht gefunden"},
|
||||||
|
{"I2CP is not enabled", "I2CP ist nicht aktiviert"},
|
||||||
|
{"Invalid", "Ungültig"},
|
||||||
|
{"Store type", "Speichertyp"},
|
||||||
|
{"Expires", "Ablaufdatum"},
|
||||||
|
{"Non Expired Leases", "Nicht abgelaufene Leases"},
|
||||||
|
{"Gateway", "Gateway"},
|
||||||
|
{"TunnelID", "TunnelID"},
|
||||||
|
{"EndDate", "Enddatum"},
|
||||||
|
{"not floodfill", "kein Floodfill"},
|
||||||
|
{"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"},
|
||||||
|
{"Start graceful shutdown", "Starte das kontrollierte Herunterfahren"},
|
||||||
|
{"Force shutdown", "Herunterfahren erzwingen"},
|
||||||
|
{"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", "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"},
|
||||||
|
{"Server Tunnels", "Servertunnel"},
|
||||||
|
{"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", "Destination nicht gefunden"},
|
||||||
|
{"StreamID can't be null", "StreamID kann nicht null sein"},
|
||||||
|
{"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 Kommandoliste"},
|
||||||
|
{"Register at reg.i2p", "Auf reg.i2p registrieren"},
|
||||||
|
{"Description", "Beschreibung"},
|
||||||
|
{"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 einen der Jump-Services unten finden"},
|
||||||
|
{"Invalid request", "Ungültige Anfrage"},
|
||||||
|
{"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"},
|
||||||
|
{"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 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", "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"},
|
||||||
|
{"cannot connect to upstream socks proxy", "Kann keine Verbindung zum Upstream-Socks-Proxy herstellen"},
|
||||||
|
{"Cannot negotiate with socks proxy", "Kann nicht mit Socks-Proxy verhandeln"},
|
||||||
|
{"CONNECT error", "CONNECT-Fehler"},
|
||||||
|
{"Failed to Connect", "Verbindung konnte nicht hergestellt werden"},
|
||||||
|
{"socks proxy error", "Socks-Proxy-Fehler"},
|
||||||
|
{"failed to send request to upstream", "Anfrage an den Upstream zu senden ist gescheitert"},
|
||||||
|
{"No Reply From socks proxy", "Keine Antwort vom Socks-Proxy"},
|
||||||
|
{"cannot connect", "kann nicht verbinden"},
|
||||||
|
{"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 aufbaunen, vielleicht ist es offline. Versuche es später noch einmal."},
|
||||||
|
{"", ""},
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::map<std::string, std::vector<std::string>> plurals
|
||||||
|
{
|
||||||
|
{"days", {"Tag", "Tage"}},
|
||||||
|
{"hours", {"Stunde", "Stunden"}},
|
||||||
|
{"minutes", {"Minute", "Minuten"}},
|
||||||
|
{"seconds", {"Sekunde", "Sekunden"}},
|
||||||
|
{"", {"", ""}},
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, The PurpleI2P Project
|
* Copyright (c) 2021-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, The PurpleI2P Project
|
* Copyright (c) 2021-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -72,19 +72,25 @@ namespace i18n
|
||||||
|
|
||||||
// Add localization here with language name as namespace
|
// Add localization here with language name as namespace
|
||||||
namespace afrikaans { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
namespace afrikaans { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||||
|
namespace armenian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||||
namespace english { 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 russian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
namespace russian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||||
namespace turkmen { 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 ukrainian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||||
namespace uzbek { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
namespace uzbek { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* That map contains international language name lower-case and name in it's language
|
* That map contains international language name lower-case, name in it's language and it's code
|
||||||
*/
|
*/
|
||||||
static std::map<std::string, langData> languages
|
static std::map<std::string, langData> languages
|
||||||
{
|
{
|
||||||
{ "afrikaans", {"Afrikaans", "af", i2p::i18n::afrikaans::GetLocale} },
|
{ "afrikaans", {"Afrikaans", "af", i2p::i18n::afrikaans::GetLocale} },
|
||||||
|
{ "armenian", {"հայերէն", "hy", i2p::i18n::armenian::GetLocale} },
|
||||||
{ "english", {"English", "en", i2p::i18n::english::GetLocale} },
|
{ "english", {"English", "en", i2p::i18n::english::GetLocale} },
|
||||||
|
{ "french", {"Français", "fr", i2p::i18n::french::GetLocale} },
|
||||||
|
{ "german", {"Deutsch", "de", i2p::i18n::german::GetLocale} },
|
||||||
{ "russian", {"русский язык", "ru", i2p::i18n::russian::GetLocale} },
|
{ "russian", {"русский язык", "ru", i2p::i18n::russian::GetLocale} },
|
||||||
{ "turkmen", {"türkmen dili", "tk", i2p::i18n::turkmen::GetLocale} },
|
{ "turkmen", {"türkmen dili", "tk", i2p::i18n::turkmen::GetLocale} },
|
||||||
{ "ukrainian", {"украї́нська мо́ва", "uk", i2p::i18n::ukrainian::GetLocale} },
|
{ "ukrainian", {"украї́нська мо́ва", "uk", i2p::i18n::ukrainian::GetLocale} },
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace russian // language namespace
|
||||||
// See for language plural forms here:
|
// See for language plural forms here:
|
||||||
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
|
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
|
||||||
static int plural (int n) {
|
static int plural (int n) {
|
||||||
return n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;
|
return n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::map<std::string, std::string> strings
|
static std::map<std::string, std::string> strings
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, The PurpleI2P Project
|
* Copyright (c) 2021-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -198,7 +198,6 @@ namespace turkmen // language namespace
|
||||||
|
|
||||||
static std::map<std::string, std::vector<std::string>> plurals
|
static std::map<std::string, std::vector<std::string>> plurals
|
||||||
{
|
{
|
||||||
// ShowUptime
|
|
||||||
{"days", {"gün", "gün"}},
|
{"days", {"gün", "gün"}},
|
||||||
{"hours", {"sagat", "sagat"}},
|
{"hours", {"sagat", "sagat"}},
|
||||||
{"minutes", {"minut", "minut"}},
|
{"minutes", {"minut", "minut"}},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021, The PurpleI2P Project
|
* Copyright (c) 2021-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -34,20 +34,21 @@ namespace uzbek // language namespace
|
||||||
{"KiB", "KiB"},
|
{"KiB", "KiB"},
|
||||||
{"MiB", "MiB"},
|
{"MiB", "MiB"},
|
||||||
{"GiB", "GiB"},
|
{"GiB", "GiB"},
|
||||||
{"building", "qurilish"},
|
{"building", "yaratilmoqda"},
|
||||||
{"failed", "muvaffaqiyatsiz"},
|
{"failed", "muvaffaqiyatsiz"},
|
||||||
{"expiring", "muddati tugaydi"},
|
{"expiring", "muddati tugaydi"},
|
||||||
{"established", "aloqa o'rnatildi"},
|
{"established", "aloqa o'rnatildi"},
|
||||||
{"unknown", "noma'lum"},
|
{"unknown", "noma'lum"},
|
||||||
{"exploratory", "tadqiqiy"},
|
{"exploratory", "tadqiqiy"},
|
||||||
{"<b>i2pd</b> webconsole", "<b>i2pd</b> veb -konsoli"},
|
{"<b>i2pd</b> webconsole", "<b>i2pd</b> veb-konsoli"},
|
||||||
{"Main page", "Asosiy sahifa"},
|
{"Main page", "Asosiy sahifa"},
|
||||||
{"Router commands", "Router buyruqlari"},
|
{"Router commands", "Router buyruqlari"},
|
||||||
|
{"Local Destinations", "Mahalliy joylanishlar"},
|
||||||
{"LeaseSets", "LeaseSets"},
|
{"LeaseSets", "LeaseSets"},
|
||||||
{"Tunnels", "Tunnellar"},
|
{"Tunnels", "Tunnellar"},
|
||||||
{"Transit Tunnels", "Tranzit Tunellar"},
|
{"Transit Tunnels", "Tranzit Tunellari"},
|
||||||
{"Transports", "Transportlar"},
|
{"Transports", "Transportlar"},
|
||||||
{"I2P tunnels", "I2P tunnellar"},
|
{"I2P tunnels", "I2P tunnellari"},
|
||||||
{"SAM sessions", "SAM sessiyalari"},
|
{"SAM sessions", "SAM sessiyalari"},
|
||||||
{"ERROR", "XATO"},
|
{"ERROR", "XATO"},
|
||||||
{"OK", "OK"},
|
{"OK", "OK"},
|
||||||
|
@ -70,25 +71,25 @@ namespace uzbek // language namespace
|
||||||
{"KiB/s", "KiB/s"},
|
{"KiB/s", "KiB/s"},
|
||||||
{"Sent", "Yuborilgan"},
|
{"Sent", "Yuborilgan"},
|
||||||
{"Transit", "Tranzit"},
|
{"Transit", "Tranzit"},
|
||||||
{"Data path", "Ma'lumotlar yo'li"},
|
{"Data path", "Ma'lumotlar joylanishi"},
|
||||||
{"Hidden content. Press on text to see.", "Yashirin tarkib. Ko'rish uchun matn ustida bosing."},
|
{"Hidden content. Press on text to see.", "Yashirin tarkib. Ko'rish uchun matn ustida bosing."},
|
||||||
{"Router Ident", "Router identifikatori"},
|
{"Router Ident", "Router identifikatori"},
|
||||||
{"Router Family", "Router Oila"},
|
{"Router Family", "Router oilasi"},
|
||||||
{"Router Caps", "Router bayroqlari"},
|
{"Router Caps", "Router Bayroqlari"},
|
||||||
{"Version", "Versiya"},
|
{"Version", "Versiya"},
|
||||||
{"Our external address", "Bizning tashqi manzilimiz"},
|
{"Our external address", "Bizning tashqi manzilimiz"},
|
||||||
{"supported", "qo'llab -quvvatlanadi"},
|
{"supported", "qo'llab-quvvatlanadi"},
|
||||||
{"Routers", "Routerlar"},
|
{"Routers", "Routerlar"},
|
||||||
{"Floodfills", "Floodfills"},
|
{"Floodfills", "Floodfills"},
|
||||||
{"Client Tunnels", "Mijoz tunellari"},
|
{"Client Tunnels", "Mijoz Tunellari"},
|
||||||
{"Services", "Xizmatlar"},
|
{"Services", "Xizmatlar"},
|
||||||
{"Enabled", "Yoqilgan"},
|
{"Enabled", "Yoqilgan"},
|
||||||
{"Disabled", "O'chirilgan"},
|
{"Disabled", "O'chirilgan"},
|
||||||
{"Encrypted B33 address", "Shifrlangan B33 manzil"},
|
{"Encrypted B33 address", "Shifrlangan B33 manzil"},
|
||||||
{"Address registration line", "Manzilni ro'yxatga olish liniyasi"},
|
{"Address registration line", "Manzilni ro'yxatga olish liniyasi"},
|
||||||
{"Domain", "Domen"},
|
{"Domain", "Domen"},
|
||||||
{"Generate", "Varatish"},
|
{"Generate", "Yaratish"},
|
||||||
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Eslatma:</b> natija satridan faqat 2LD domenlarini ro'yxatdan o'tkazish uchun foydalanish mumkin (example.i2p). Subdomenlarni ro'yxatdan o'tkazish uchun i2pd-tools dan foydalaning."},
|
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Eslatma:</b> natija satridan faqat 2LD domenlarini ro'yxatdan o'tkazish uchun foydalanish mumkin (example.i2p). Subdomenlarni ro'yxatdan o'tkazish uchun 'i2pd-tools'dan foydalaning."},
|
||||||
{"Address", "Manzil"},
|
{"Address", "Manzil"},
|
||||||
{"Type", "Turi"},
|
{"Type", "Turi"},
|
||||||
{"EncType", "ShifrlashTuri"},
|
{"EncType", "ShifrlashTuri"},
|
||||||
|
@ -99,10 +100,11 @@ namespace uzbek // language namespace
|
||||||
{"Incoming", "Kiruvchi"},
|
{"Incoming", "Kiruvchi"},
|
||||||
{"Outgoing", "Chiquvchi"},
|
{"Outgoing", "Chiquvchi"},
|
||||||
{"Destination", "Manzilgoh"},
|
{"Destination", "Manzilgoh"},
|
||||||
{"Amount", "Yig'indi"},
|
{"Amount", "Soni"},
|
||||||
{"Incoming Tags", "Kiruvchi teglar"},
|
{"Incoming Tags", "Kiruvchi teglar"},
|
||||||
{"Tags sessions", "Teglar sessiyalari"},
|
{"Tags sessions", "Teglar sessiyalari"},
|
||||||
{"Status", "Holat"},
|
{"Status", "Holat"},
|
||||||
|
{"Local Destination", "Mahalliy joylanish"},
|
||||||
{"Streams", "Strim"},
|
{"Streams", "Strim"},
|
||||||
{"Close stream", "Strimni o'chirish"},
|
{"Close stream", "Strimni o'chirish"},
|
||||||
{"I2CP session not found", "I2CP sessiyasi topilmadi"},
|
{"I2CP session not found", "I2CP sessiyasi topilmadi"},
|
||||||
|
@ -117,14 +119,15 @@ namespace uzbek // language namespace
|
||||||
{"not floodfill", "floodfill emas"},
|
{"not floodfill", "floodfill emas"},
|
||||||
{"Queue size", "Navbat hajmi"},
|
{"Queue size", "Navbat hajmi"},
|
||||||
{"Run peer test", "Sinovni boshlang"},
|
{"Run peer test", "Sinovni boshlang"},
|
||||||
{"Decline transit tunnels", "Tranzit tunnellarni rad etish"},
|
{"Decline transit tunnels", "Tranzit tunnellarini rad etish"},
|
||||||
{"Accept transit tunnels", "Tranzit tunnellarni qabul qilish"},
|
{"Accept transit tunnels", "Tranzit tunnellarni qabul qilish"},
|
||||||
{"Cancel graceful shutdown", "Yumshoq to'xtashni bekor qiling"},
|
{"Cancel graceful shutdown", "Yumshoq to'xtashni bekor qilish"},
|
||||||
{"Start graceful shutdown", "Yumshoq to'xtashni boshlang"},
|
{"Start graceful shutdown", "Yumshoq to'xtashni boshlash"},
|
||||||
{"Force shutdown", "Bizning tashqi manzilimiz"},
|
{"Force shutdown", "Majburiy to'xtatish"},
|
||||||
{"Reload external CSS styles", "Tashqi CSS uslublarini qayta yuklang"},
|
{"Reload external CSS styles", "Tashqi CSS uslublarini qayta yuklang"},
|
||||||
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Eslatma:</b> bu erda qilingan har qanday harakat doimiy emas va konfiguratsiya fayllarini o'zgartirmaydi."},
|
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Eslatma:</b> shu yerda qilingan har qanday harakat doimiy emas va konfiguratsiya fayllarini o'zgartirmaydi."},
|
||||||
{"Transit tunnels limit", "Tranzit tunellar chegarasi"},
|
{"Logging level", "Jurnal darajasi"},
|
||||||
|
{"Transit tunnels limit", "Tranzit tunellarning chegarasi"},
|
||||||
{"Change", "O'zgartirish"},
|
{"Change", "O'zgartirish"},
|
||||||
{"Change language", "Tilni o'zgartirish"},
|
{"Change language", "Tilni o'zgartirish"},
|
||||||
{"no transit tunnels currently built", "qurilgan tranzit tunnellari yo'q"},
|
{"no transit tunnels currently built", "qurilgan tranzit tunnellari yo'q"},
|
||||||
|
@ -142,8 +145,8 @@ namespace uzbek // language namespace
|
||||||
{"Stream not found or already was closed", "Strim topilmadi yoki allaqachon yopilgan"},
|
{"Stream not found or already was closed", "Strim topilmadi yoki allaqachon yopilgan"},
|
||||||
{"Destination not found", "Yo'nalish topilmadi"},
|
{"Destination not found", "Yo'nalish topilmadi"},
|
||||||
{"StreamID can't be null", "StreamID bo'sh bo'lishi mumkin emas"},
|
{"StreamID can't be null", "StreamID bo'sh bo'lishi mumkin emas"},
|
||||||
{"Return to destination page", "Belgilangan sahifaga qaytish"},
|
{"Return to destination page", "Manzilgoh sahifasiga qaytish"},
|
||||||
{"You will be redirected in 5 seconds", "Siz 5 soniyada qayta yo'naltirilasiz"},
|
{"You will be redirected in 5 seconds", "Siz 5 soniya ichida qayta yo'naltirilasiz"},
|
||||||
{"Transit tunnels count must not exceed 65535", "Tranzit tunnellar soni 65535 dan oshmasligi kerak"},
|
{"Transit tunnels count must not exceed 65535", "Tranzit tunnellar soni 65535 dan oshmasligi kerak"},
|
||||||
{"Back to commands list", "Buyruqlar ro'yxatiga qaytish"},
|
{"Back to commands list", "Buyruqlar ro'yxatiga qaytish"},
|
||||||
{"Register at reg.i2p", "Reg.i2p-da ro'yxatdan o'ting"},
|
{"Register at reg.i2p", "Reg.i2p-da ro'yxatdan o'ting"},
|
||||||
|
@ -159,29 +162,35 @@ namespace uzbek // language namespace
|
||||||
{"Proxy info", "Proksi ma'lumotlari"},
|
{"Proxy info", "Proksi ma'lumotlari"},
|
||||||
{"Proxy error: Host not found", "Proksi xatosi: Xost topilmadi"},
|
{"Proxy error: Host not found", "Proksi xatosi: Xost topilmadi"},
|
||||||
{"Remote host not found in router's addressbook", "Masofaviy xost yo'riqnoma manzillar kitobida topilmadi"},
|
{"Remote host not found in router's addressbook", "Masofaviy xost yo'riqnoma manzillar kitobida topilmadi"},
|
||||||
|
{"You may try to find this host on jump services below", "Siz xost quyida o'tish xizmatlari orqali topishga harakat qilishingiz mumkin"},
|
||||||
{"Invalid request", "Noto‘g‘ri so‘rov"},
|
{"Invalid request", "Noto‘g‘ri so‘rov"},
|
||||||
{"Proxy unable to parse your request", "Proksi sizning so'rovingizni tahlil qila olmaydi"},
|
{"Proxy unable to parse your request", "Proksi sizning so'rovingizni aniqlab ololmayapti"},
|
||||||
{"addresshelper is not supported", "addresshelper qo'llab -quvvatlanmaydi"},
|
{"addresshelper is not supported", "addresshelper qo'llab -quvvatlanmaydi"},
|
||||||
{"Host", "Xost"},
|
{"Host", "Xost"},
|
||||||
|
{"added to router's addressbook from helper", "'helper'dan routerning 'addressbook'ga qo'shildi"},
|
||||||
|
{"Click here to proceed:", "Davom etish uchun shu yerni bosing:"},
|
||||||
|
{"Continue", "Davom etish"},
|
||||||
{"Addresshelper found", "Addresshelper topildi"},
|
{"Addresshelper found", "Addresshelper topildi"},
|
||||||
|
{"already in router's addressbook", "allaqachon 'addressbook'da yozilgan"},
|
||||||
|
{"Click here to update record:", "Yozuvni yangilash uchun shu yerni bosing:"},
|
||||||
{"invalid request uri", "noto'g'ri URI so'rovi"},
|
{"invalid request uri", "noto'g'ri URI so'rovi"},
|
||||||
{"Can't detect destination host from request", "So‘rov orqali manzil xostini aniqlab bo'lmayapti"},
|
{"Can't detect destination host from request", "So‘rov orqali manzil xostini aniqlab bo'lmayapti"},
|
||||||
{"Outproxy failure", "Tashqi proksi muvaffaqiyatsizligi"},
|
{"Outproxy failure", "Tashqi proksi muvaffaqiyatsizligi"},
|
||||||
{"bad outproxy settings", "noto'g'ri tashqi proksi -server sozlamalari"},
|
{"bad outproxy settings", "noto'g'ri tashqi proksi-server sozlamalari"},
|
||||||
{"not inside I2P network, but outproxy is not enabled", "I2P tarmog'ida emas, lekin tashqi proksi yoqilmagan"},
|
{"not inside I2P network, but outproxy is not enabled", "I2P tarmog'ida emas, lekin tashqi proksi yoqilmagan"},
|
||||||
{"unknown outproxy url", "noma'lum outproxy url"},
|
{"unknown outproxy url", "noma'lum outproxy url"},
|
||||||
{"cannot resolve upstream proxy", "yuqoridagi proksi -serverni aniqlab olib bolmaydi"},
|
{"cannot resolve upstream proxy", "yuqoridagi 'proxy-server'ni aniqlab olib bolmayapti"},
|
||||||
{"hostname too long", "xost nomi juda uzun"},
|
{"hostname too long", "xost nomi juda uzun"},
|
||||||
{"cannot connect to upstream socks proxy", "yuqori soks proksi -serveriga ulanib bo'lmaydi"},
|
{"cannot connect to upstream socks proxy", "yuqori 'socks proxy'ga ulanib bo'lmayapti"},
|
||||||
{"Cannot negotiate with socks proxy", "Soks proksi bilan muzokara olib bo'lmaydi"},
|
{"Cannot negotiate with socks proxy", "'Socks proxy' bilan muzokara olib bo'lmaydi"},
|
||||||
{"CONNECT error", "CONNECT xatosi"},
|
{"CONNECT error", "CONNECT xatosi"},
|
||||||
{"Failed to Connect", "Ulanmadi"},
|
{"Failed to Connect", "Ulanib bo'lmayapti"},
|
||||||
{"socks proxy error", "soks proksi xatosi"},
|
{"socks proxy error", "'socks proxy' xatosi"},
|
||||||
{"failed to send request to upstream", "yuqori http proksi-serveriga ulanib bo'lmadi"},
|
{"failed to send request to upstream", "yuqori http proksi-serveriga so'rovni uborib bo'lmadi"},
|
||||||
{"No Reply From socks proxy", "Soks-proksidan javob yo'q"},
|
{"No Reply From socks proxy", "'Socks proxy'dan javob yo'q"},
|
||||||
{"cannot connect", "ulab bo'lmaydi"},
|
{"cannot connect", "ulanib bo'lmaydi"},
|
||||||
{"http out proxy not implemented", "tashqi HTTP proksi -serverni qo'llab -quvvatlash amalga oshirilmagan"},
|
{"http out proxy not implemented", "tashqi HTTP proksi-serverni qo'llab-quvvatlash amalga oshirilmagan"},
|
||||||
{"cannot connect to upstream http proxy", "yuqori http proksi-serveriga ulanib bo'lmadi"},
|
{"cannot connect to upstream http proxy", "yuqori http 'proxy-server'iga ulanib bo'lmayapti"},
|
||||||
{"Host is down", "Xost ishlamayapti"},
|
{"Host is down", "Xost ishlamayapti"},
|
||||||
{"Can't create connection to requested host, it may be down. Please try again later.", "Talab qilingan xost bilan aloqa o'rnatilmadi, u ishlamay qolishi mumkin. Iltimos keyinroq qayta urinib ko'ring."},
|
{"Can't create connection to requested host, it may be down. Please try again later.", "Talab qilingan xost bilan aloqa o'rnatilmadi, u ishlamay qolishi mumkin. Iltimos keyinroq qayta urinib ko'ring."},
|
||||||
{"", ""},
|
{"", ""},
|
||||||
|
@ -189,10 +198,10 @@ namespace uzbek // language namespace
|
||||||
|
|
||||||
static std::map<std::string, std::vector<std::string>> plurals
|
static std::map<std::string, std::vector<std::string>> plurals
|
||||||
{
|
{
|
||||||
{"days", {"kun", "kunlar"}},
|
{"days", {"kun", "kun"}},
|
||||||
{"hours", {"soat", "soat"}},
|
{"hours", {"soat", "soat"}},
|
||||||
{"minutes", {"daqiqa", "daqiqalar"}},
|
{"minutes", {"daqiqa", "daqiqa"}},
|
||||||
{"seconds", {"soniya", "soniyalar"}},
|
{"seconds", {"soniya", "soniya"}},
|
||||||
{"", {"", ""}},
|
{"", {"", ""}},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -185,10 +185,7 @@ namespace data
|
||||||
if (InCount && !m)
|
if (InCount && !m)
|
||||||
outCount = 3 * n;
|
outCount = 3 * n;
|
||||||
else
|
else
|
||||||
{
|
|
||||||
outCount = 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
ps = (unsigned char *)(InBuffer + InCount - 1);
|
ps = (unsigned char *)(InBuffer + InCount - 1);
|
||||||
while ( *ps-- == P64 )
|
while ( *ps-- == P64 )
|
||||||
|
@ -196,7 +193,7 @@ namespace data
|
||||||
ps = (unsigned char *)InBuffer;
|
ps = (unsigned char *)InBuffer;
|
||||||
|
|
||||||
if (outCount > len)
|
if (outCount > len)
|
||||||
return -1;
|
return 0;
|
||||||
|
|
||||||
pd = OutBuffer;
|
pd = OutBuffer;
|
||||||
auto endOfOutBuffer = OutBuffer + outCount;
|
auto endOfOutBuffer = OutBuffer + outCount;
|
||||||
|
|
|
@ -24,8 +24,8 @@ namespace data {
|
||||||
size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen);
|
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);
|
size_t Base64EncodingBufferSize(const size_t input_size);
|
||||||
|
|
||||||
std::string ToBase64Standard (const std::string& in); // using standard table, for Proxy-Authorization
|
std::string ToBase64Standard (const std::string& in); // using standard table, for Proxy-Authorization
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -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)
|
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
|
// blind is BlindEncodedPublicKeyECDSA or BlindEncodedPrivateKeyECDSA
|
||||||
{
|
{
|
||||||
size_t publicKeyLength = 0;
|
size_t publicKeyLength = 0;
|
||||||
EC_GROUP * group = nullptr;
|
EC_GROUP * group = nullptr;
|
||||||
switch (sigType)
|
switch (sigType)
|
||||||
{
|
{
|
||||||
|
@ -122,7 +122,7 @@ namespace data
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
LogPrint (eLogError, "Blinding: signature type ", (int)sigType, " is not ECDSA");
|
LogPrint (eLogError, "Blinding: Signature type ", (int)sigType, " is not ECDSA");
|
||||||
}
|
}
|
||||||
if (group)
|
if (group)
|
||||||
{
|
{
|
||||||
|
@ -146,7 +146,10 @@ namespace data
|
||||||
m_PublicKey.resize (len);
|
m_PublicKey.resize (len);
|
||||||
memcpy (m_PublicKey.data (), identity->GetSigningPublicKeyBuffer (), len);
|
memcpy (m_PublicKey.data (), identity->GetSigningPublicKeyBuffer (), len);
|
||||||
m_SigType = identity->GetSigningKeyType ();
|
m_SigType = identity->GetSigningKeyType ();
|
||||||
m_BlindedSigType = m_SigType;
|
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 = m_SigType;
|
||||||
}
|
}
|
||||||
|
|
||||||
BlindedPublicKey::BlindedPublicKey (const std::string& b33):
|
BlindedPublicKey::BlindedPublicKey (const std::string& b33):
|
||||||
|
@ -156,7 +159,7 @@ namespace data
|
||||||
size_t l = i2p::data::Base32ToByteStream (b33.c_str (), b33.length (), addr, 40);
|
size_t l = i2p::data::Base32ToByteStream (b33.c_str (), b33.length (), addr, 40);
|
||||||
if (l < 32)
|
if (l < 32)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Blinding: malformed b33 ", b33);
|
LogPrint (eLogError, "Blinding: Malformed b33 ", b33);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32_t checksum = crc32 (0, addr + 3, l - 3);
|
uint32_t checksum = crc32 (0, addr + 3, l - 3);
|
||||||
|
@ -186,10 +189,10 @@ namespace data
|
||||||
memcpy (m_PublicKey.data (), addr + offset, len);
|
memcpy (m_PublicKey.data (), addr + offset, len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Blinding: public key in b33 address is too short for signature type ", (int)m_SigType);
|
LogPrint (eLogError, "Blinding: Public key in b33 address is too short for signature type ", (int)m_SigType);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Blinding: unknown signature type ", (int)m_SigType, " in b33");
|
LogPrint (eLogError, "Blinding: Unknown signature type ", (int)m_SigType, " in b33");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string BlindedPublicKey::ToB33 () const
|
std::string BlindedPublicKey::ToB33 () const
|
||||||
|
@ -256,7 +259,7 @@ namespace data
|
||||||
publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH;
|
publicKeyLength = i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LogPrint (eLogError, "Blinding: can't blind signature type ", (int)m_SigType);
|
LogPrint (eLogError, "Blinding: Can't blind signature type ", (int)m_SigType);
|
||||||
}
|
}
|
||||||
return publicKeyLength;
|
return publicKeyLength;
|
||||||
}
|
}
|
||||||
|
@ -286,7 +289,7 @@ namespace data
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
LogPrint (eLogError, "Blinding: can't blind signature type ", (int)m_SigType);
|
LogPrint (eLogError, "Blinding: Can't blind signature type ", (int)m_SigType);
|
||||||
}
|
}
|
||||||
return publicKeyLength;
|
return publicKeyLength;
|
||||||
}
|
}
|
||||||
|
@ -324,7 +327,7 @@ namespace data
|
||||||
SHA256_Final ((uint8_t *)hash, &ctx);
|
SHA256_Final ((uint8_t *)hash, &ctx);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Blinding: blinded key type ", (int)m_BlindedSigType, " is not supported");
|
LogPrint (eLogError, "Blinding: Blinded key type ", (int)m_BlindedSigType, " is not supported");
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,8 +28,8 @@ namespace data
|
||||||
|
|
||||||
const uint8_t * GetPublicKey () const { return m_PublicKey.data (); };
|
const uint8_t * GetPublicKey () const { return m_PublicKey.data (); };
|
||||||
size_t GetPublicKeyLen () const { return m_PublicKey.size (); };
|
size_t GetPublicKeyLen () const { return m_PublicKey.size (); };
|
||||||
SigningKeyType GetSigType () const { return m_SigType; };
|
SigningKeyType GetSigType () const { return m_SigType; };
|
||||||
SigningKeyType GetBlindedSigType () const { return m_BlindedSigType; };
|
SigningKeyType GetBlindedSigType () const { return m_BlindedSigType; };
|
||||||
bool IsValid () const { return GetSigType (); }; // signature type 0 means invalid
|
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
|
void GetSubcredential (const uint8_t * blinded, size_t len, uint8_t * subcredential) const; // 32 bytes
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -61,7 +61,7 @@ namespace config {
|
||||||
("service", bool_switch()->default_value(false), "Router will use system folders like '/var/lib/i2pd' (default: disabled)")
|
("service", bool_switch()->default_value(false), "Router will use system folders like '/var/lib/i2pd' (default: disabled)")
|
||||||
("notransit", bool_switch()->default_value(false), "Router will not accept transit tunnels at startup (default: disabled)")
|
("notransit", bool_switch()->default_value(false), "Router will not accept transit tunnels at startup (default: disabled)")
|
||||||
("floodfill", bool_switch()->default_value(false), "Router will be floodfill (default: disabled)")
|
("floodfill", bool_switch()->default_value(false), "Router will be floodfill (default: disabled)")
|
||||||
("bandwidth", value<std::string>()->default_value(""), "Bandwidth limit: integer in KBps or letters: L (32), O (256), P (2048), X (>9000)")
|
("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)")
|
("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")
|
("ntcp", bool_switch()->default_value(false), "Ignored. Always false")
|
||||||
("ssu", bool_switch()->default_value(true), "Enable SSU transport (default: enabled)")
|
("ssu", bool_switch()->default_value(true), "Enable SSU transport (default: enabled)")
|
||||||
|
@ -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.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.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.transittunnels", value<uint16_t>()->default_value(2500), "Maximum active transit sessions (default:2500)")
|
||||||
("limits.ntcpsoft", value<uint16_t>()->default_value(0), "Threshold to start probabilistic backoff with ntcp sessions (default: use system limit)")
|
("limits.ntcpsoft", value<uint16_t>()->default_value(0), "Ignored")
|
||||||
("limits.ntcphard", value<uint16_t>()->default_value(0), "Maximum number of ntcp sessions (default: use system limit)")
|
("limits.ntcphard", value<uint16_t>()->default_value(0), "Ignored")
|
||||||
("limits.ntcpthreads", value<uint16_t>()->default_value(1), "Maximum number of threads used by NTCP DH worker (default: 1)")
|
("limits.ntcpthreads", value<uint16_t>()->default_value(1), "Ignored")
|
||||||
;
|
;
|
||||||
|
|
||||||
options_description httpserver("HTTP Server options");
|
options_description httpserver("HTTP Server options");
|
||||||
|
@ -109,6 +109,8 @@ namespace config {
|
||||||
("httpproxy.outbound.length", value<std::string>()->default_value("3"), "HTTP proxy outbound tunnel length")
|
("httpproxy.outbound.length", value<std::string>()->default_value("3"), "HTTP proxy outbound tunnel length")
|
||||||
("httpproxy.inbound.quantity", value<std::string>()->default_value("5"), "HTTP proxy inbound tunnels quantity")
|
("httpproxy.inbound.quantity", value<std::string>()->default_value("5"), "HTTP proxy inbound tunnels quantity")
|
||||||
("httpproxy.outbound.quantity", value<std::string>()->default_value("5"), "HTTP proxy outbound tunnels quantity")
|
("httpproxy.outbound.quantity", value<std::string>()->default_value("5"), "HTTP proxy outbound tunnels quantity")
|
||||||
|
("httpproxy.inbound.lengthVariance", value<std::string>()->default_value("0"), "HTTP proxy inbound tunnels length variance")
|
||||||
|
("httpproxy.outbound.lengthVariance", value<std::string>()->default_value("0"), "HTTP proxy outbound tunnels length variance")
|
||||||
("httpproxy.latency.min", value<std::string>()->default_value("0"), "HTTP proxy min latency for tunnels")
|
("httpproxy.latency.min", value<std::string>()->default_value("0"), "HTTP proxy min latency for tunnels")
|
||||||
("httpproxy.latency.max", value<std::string>()->default_value("0"), "HTTP proxy max latency for tunnels")
|
("httpproxy.latency.max", value<std::string>()->default_value("0"), "HTTP proxy max latency for tunnels")
|
||||||
("httpproxy.outproxy", value<std::string>()->default_value(""), "HTTP proxy upstream out proxy url")
|
("httpproxy.outproxy", value<std::string>()->default_value(""), "HTTP proxy upstream out proxy url")
|
||||||
|
@ -130,6 +132,8 @@ namespace config {
|
||||||
("socksproxy.outbound.length", value<std::string>()->default_value("3"), "SOCKS proxy outbound tunnel length")
|
("socksproxy.outbound.length", value<std::string>()->default_value("3"), "SOCKS proxy outbound tunnel length")
|
||||||
("socksproxy.inbound.quantity", value<std::string>()->default_value("5"), "SOCKS proxy inbound tunnels quantity")
|
("socksproxy.inbound.quantity", value<std::string>()->default_value("5"), "SOCKS proxy inbound tunnels quantity")
|
||||||
("socksproxy.outbound.quantity", value<std::string>()->default_value("5"), "SOCKS proxy outbound tunnels quantity")
|
("socksproxy.outbound.quantity", value<std::string>()->default_value("5"), "SOCKS proxy outbound tunnels quantity")
|
||||||
|
("socksproxy.inbound.lengthVariance", value<std::string>()->default_value("0"), "SOCKS proxy inbound tunnels length variance")
|
||||||
|
("socksproxy.outbound.lengthVariance", value<std::string>()->default_value("0"), "SOCKS proxy outbound tunnels length variance")
|
||||||
("socksproxy.latency.min", value<std::string>()->default_value("0"), "SOCKS proxy min latency for tunnels")
|
("socksproxy.latency.min", value<std::string>()->default_value("0"), "SOCKS proxy min latency for tunnels")
|
||||||
("socksproxy.latency.max", value<std::string>()->default_value("0"), "SOCKS proxy max latency for tunnels")
|
("socksproxy.latency.max", value<std::string>()->default_value("0"), "SOCKS proxy max latency for tunnels")
|
||||||
("socksproxy.outproxy.enabled", value<bool>()->default_value(false), "Enable or disable SOCKS outproxy")
|
("socksproxy.outproxy.enabled", value<bool>()->default_value(false), "Enable or disable SOCKS outproxy")
|
||||||
|
@ -203,28 +207,36 @@ namespace config {
|
||||||
("reseed.zipfile", value<std::string>()->default_value(""), "Path to local .zip file to reseed from")
|
("reseed.zipfile", value<std::string>()->default_value(""), "Path to local .zip file to reseed from")
|
||||||
("reseed.proxy", value<std::string>()->default_value(""), "url for reseed proxy, supports http/socks")
|
("reseed.proxy", value<std::string>()->default_value(""), "url for reseed proxy, supports http/socks")
|
||||||
("reseed.urls", value<std::string>()->default_value(
|
("reseed.urls", value<std::string>()->default_value(
|
||||||
"https://reseed.i2p-projekt.de/,"
|
"https://reseed2.i2p.net/,"
|
||||||
"https://reseed.diva.exchange/,"
|
"https://reseed.diva.exchange/,"
|
||||||
"https://reseed-fr.i2pd.xyz/,"
|
"https://reseed-fr.i2pd.xyz/,"
|
||||||
"https://reseed.memcpy.io/,"
|
"https://reseed.memcpy.io/,"
|
||||||
"https://reseed.onion.im/,"
|
"https://reseed.onion.im/,"
|
||||||
"https://i2pseed.creativecowpat.net:8443/,"
|
"https://i2pseed.creativecowpat.net:8443/,"
|
||||||
"https://reseed.i2pgit.org/,"
|
"https://reseed.i2pgit.org/,"
|
||||||
"https://i2p.novg.net/"
|
"https://i2p.novg.net/,"
|
||||||
|
"https://banana.incognet.io/,"
|
||||||
|
"https://reseed-pl.i2pd.xyz/,"
|
||||||
|
"https://www2.mk16.de/"
|
||||||
), "Reseed URLs, separated by comma")
|
), "Reseed URLs, separated by comma")
|
||||||
("reseed.yggurls", value<std::string>()->default_value(
|
("reseed.yggurls", value<std::string>()->default_value(
|
||||||
"http://[324:71e:281a:9ed3::ace]:7070/,"
|
"http://[324:71e:281a:9ed3::ace]:7070/,"
|
||||||
"http://[301:65b9:c7cd:9a36::1]:18801/,"
|
"http://[301:65b9:c7cd:9a36::1]:18801/,"
|
||||||
"http://[320:8936:ec1a:31f1::216]/"
|
"http://[320:8936:ec1a:31f1::216]/,"
|
||||||
|
"http://[306:3834:97b9:a00a::1]/,"
|
||||||
|
"http://[316:f9e0:f22e:a74f::216]/"
|
||||||
), "Reseed URLs through the Yggdrasil, separated by comma")
|
), "Reseed URLs through the Yggdrasil, separated by comma")
|
||||||
;
|
;
|
||||||
|
|
||||||
options_description addressbook("AddressBook options");
|
options_description addressbook("AddressBook options");
|
||||||
addressbook.add_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(
|
("addressbook.defaulturl", value<std::string>()->default_value(
|
||||||
"http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/hosts.txt"
|
"http://shx5vqsw7usdaunyzr2qmes2fq37oumybpudrd4jjj4e4vk4uusa.b32.i2p/hosts.txt"
|
||||||
), "AddressBook subscription URL for initial setup")
|
), "AddressBook subscription URL for initial setup")
|
||||||
("addressbook.subscriptions", value<std::string>()->default_value("http://reg.i2p/hosts.txt"), "AddressBook subscriptions URLs, separated by comma")
|
("addressbook.subscriptions", value<std::string>()->default_value(
|
||||||
|
"http://reg.i2p/hosts.txt"
|
||||||
|
), "AddressBook subscriptions URLs, separated by comma")
|
||||||
("addressbook.hostsfile", value<std::string>()->default_value(""), "File to dump addresses in hosts.txt format");
|
("addressbook.hostsfile", value<std::string>()->default_value(""), "File to dump addresses in hosts.txt format");
|
||||||
|
|
||||||
options_description trust("Trust options");
|
options_description trust("Trust options");
|
||||||
|
@ -260,6 +272,13 @@ namespace config {
|
||||||
("ntcp2.proxy", value<std::string>()->default_value(""), "Proxy URL for NTCP2 transport")
|
("ntcp2.proxy", value<std::string>()->default_value(""), "Proxy URL for NTCP2 transport")
|
||||||
;
|
;
|
||||||
|
|
||||||
|
options_description ssu2("SSU2 Options");
|
||||||
|
ssu2.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)")
|
||||||
|
;
|
||||||
|
|
||||||
options_description nettime("Time sync options");
|
options_description nettime("Time sync options");
|
||||||
nettime.add_options()
|
nettime.add_options()
|
||||||
("nettime.enabled", value<bool>()->default_value(false), "Disable time sync (default: disabled)")
|
("nettime.enabled", value<bool>()->default_value(false), "Disable time sync (default: disabled)")
|
||||||
|
@ -268,8 +287,9 @@ namespace config {
|
||||||
"1.pool.ntp.org,"
|
"1.pool.ntp.org,"
|
||||||
"2.pool.ntp.org,"
|
"2.pool.ntp.org,"
|
||||||
"3.pool.ntp.org"
|
"3.pool.ntp.org"
|
||||||
), "Comma separated list of NTCP servers")
|
), "Comma separated list of NTP servers")
|
||||||
("nettime.ntpsyncinterval", value<int>()->default_value(72), "NTP sync interval in hours (default: 72)")
|
("nettime.ntpsyncinterval", value<int>()->default_value(72), "NTP sync interval in hours (default: 72)")
|
||||||
|
("nettime.frompeers", value<bool>()->default_value(true), "Sync clock from transport peers (default: enabled)")
|
||||||
;
|
;
|
||||||
|
|
||||||
options_description persist("Network information persisting options");
|
options_description persist("Network information persisting options");
|
||||||
|
@ -291,6 +311,13 @@ namespace config {
|
||||||
("meshnets.yggaddress", value<std::string>()->default_value(""), "Yggdrasil address to publish")
|
("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
|
m_OptionsDesc
|
||||||
.add(general)
|
.add(general)
|
||||||
.add(limits)
|
.add(limits)
|
||||||
|
@ -309,10 +336,14 @@ namespace config {
|
||||||
.add(websocket) // deprecated
|
.add(websocket) // deprecated
|
||||||
.add(exploratory)
|
.add(exploratory)
|
||||||
.add(ntcp2)
|
.add(ntcp2)
|
||||||
|
.add(ssu2)
|
||||||
.add(nettime)
|
.add(nettime)
|
||||||
.add(persist)
|
.add(persist)
|
||||||
.add(cpuext)
|
.add(cpuext)
|
||||||
.add(meshnets)
|
.add(meshnets)
|
||||||
|
#ifdef __linux__
|
||||||
|
.add(unix_specific)
|
||||||
|
#endif
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,16 +29,16 @@ namespace config {
|
||||||
extern boost::program_options::variables_map m_Options;
|
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.
|
* Should be called before any Parse* functions.
|
||||||
*/
|
*/
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Parse cmdline parameters, and show help if requested
|
* @brief Parse cmdline parameters, and show help if requested
|
||||||
* @param argc Cmdline arguments count, should be passed from main().
|
* @param argc Cmdline arguments count, should be passed from main().
|
||||||
* @param argv Cmdline parameters array, 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
|
* If --help is given in parameters, shows its list with description
|
||||||
* and terminates the program with exitcode 0.
|
* and terminates the program with exitcode 0.
|
||||||
|
@ -52,8 +52,8 @@ namespace config {
|
||||||
void ParseCmdline(int argc, char* argv[], bool ignoreUnknown = false);
|
void ParseCmdline(int argc, char* argv[], bool ignoreUnknown = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Load and parse given config file
|
* @brief Load and parse given config file
|
||||||
* @param path Path to config file
|
* @param path Path to config file
|
||||||
*
|
*
|
||||||
* If error occurred when opening file path is points to,
|
* If error occurred when opening file path is points to,
|
||||||
* we show the error message and terminate program.
|
* we show the error message and terminate program.
|
||||||
|
@ -67,14 +67,14 @@ namespace config {
|
||||||
void ParseConfig(const std::string& path);
|
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();
|
void Finalize();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Accessor to parameters by name
|
* @brief Accessor to parameters by name
|
||||||
* @param name Name of the requested parameter
|
* @param name Name of the requested parameter
|
||||||
* @param value Variable where to store option
|
* @param value Variable where to store option
|
||||||
* @return this function returns false if parameter not found
|
* @return this function returns false if parameter not found
|
||||||
*
|
*
|
||||||
* Example: uint16_t port; GetOption("sam.port", port);
|
* Example: uint16_t port; GetOption("sam.port", port);
|
||||||
|
@ -98,9 +98,9 @@ namespace config {
|
||||||
bool GetOptionAsAny(const std::string& name, boost::any& value);
|
bool GetOptionAsAny(const std::string& name, boost::any& value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set value of given parameter
|
* @brief Set value of given parameter
|
||||||
* @param name Name of settable parameter
|
* @param name Name of settable parameter
|
||||||
* @param value New parameter value
|
* @param value New parameter value
|
||||||
* @return true if value set up successful, false otherwise
|
* @return true if value set up successful, false otherwise
|
||||||
*
|
*
|
||||||
* Example: uint16_t port = 2827; SetOption("bob.port", port);
|
* Example: uint16_t port = 2827; SetOption("bob.port", port);
|
||||||
|
@ -116,8 +116,8 @@ namespace config {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check is value explicitly given or default
|
* @brief Check is value explicitly given or default
|
||||||
* @param name Name of checked parameter
|
* @param name Name of checked parameter
|
||||||
* @return true if value set to default, false otherwise
|
* @return true if value set to default, false otherwise
|
||||||
*/
|
*/
|
||||||
bool IsDefault(const char *name);
|
bool IsDefault(const char *name);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -1277,7 +1277,7 @@ namespace crypto
|
||||||
EVP_PKEY_CTX_set1_hkdf_key (pctx, tempKey, len);
|
EVP_PKEY_CTX_set1_hkdf_key (pctx, tempKey, len);
|
||||||
}
|
}
|
||||||
if (info.length () > 0)
|
if (info.length () > 0)
|
||||||
EVP_PKEY_CTX_add1_hkdf_info (pctx, info.c_str (), info.length ());
|
EVP_PKEY_CTX_add1_hkdf_info (pctx, (const uint8_t *)info.c_str (), info.length ());
|
||||||
EVP_PKEY_derive (pctx, out, &outLen);
|
EVP_PKEY_derive (pctx, out, &outLen);
|
||||||
EVP_PKEY_CTX_free (pctx);
|
EVP_PKEY_CTX_free (pctx);
|
||||||
#else
|
#else
|
||||||
|
@ -1305,6 +1305,16 @@ namespace crypto
|
||||||
SHA256_Final (m_H, &ctx);
|
SHA256_Final (m_H, &ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NoiseSymmetricState::MixHash (const std::vector<std::pair<uint8_t *, size_t> >& bufs)
|
||||||
|
{
|
||||||
|
SHA256_CTX ctx;
|
||||||
|
SHA256_Init (&ctx);
|
||||||
|
SHA256_Update (&ctx, m_H, 32);
|
||||||
|
for (const auto& it: bufs)
|
||||||
|
SHA256_Update (&ctx, it.first, it.second);
|
||||||
|
SHA256_Final (m_H, &ctx);
|
||||||
|
}
|
||||||
|
|
||||||
void NoiseSymmetricState::MixKey (const uint8_t * sharedSecret)
|
void NoiseSymmetricState::MixKey (const uint8_t * sharedSecret)
|
||||||
{
|
{
|
||||||
HKDF (m_CK, sharedSecret, 32, "", m_CK);
|
HKDF (m_CK, sharedSecret, 32, "", m_CK);
|
||||||
|
@ -1320,7 +1330,7 @@ namespace crypto
|
||||||
SHA256_Init (&ctx);
|
SHA256_Init (&ctx);
|
||||||
SHA256_Update (&ctx, hh, 32);
|
SHA256_Update (&ctx, hh, 32);
|
||||||
SHA256_Update (&ctx, pub, 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)
|
void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub)
|
||||||
|
@ -1336,7 +1346,7 @@ namespace crypto
|
||||||
|
|
||||||
void InitNoiseXKState (NoiseSymmetricState& state, const uint8_t * pub)
|
void InitNoiseXKState (NoiseSymmetricState& state, const uint8_t * pub)
|
||||||
{
|
{
|
||||||
static const uint8_t protocolNameHash[] =
|
static const uint8_t protocolNameHash[32] =
|
||||||
{
|
{
|
||||||
0x72, 0xe8, 0x42, 0xc5, 0x45, 0xe1, 0x80, 0x80, 0xd3, 0x9c, 0x44, 0x93, 0xbb, 0x91, 0xd7, 0xed,
|
0x72, 0xe8, 0x42, 0xc5, 0x45, 0xe1, 0x80, 0x80, 0xd3, 0x9c, 0x44, 0x93, 0xbb, 0x91, 0xd7, 0xed,
|
||||||
0xf2, 0x28, 0x98, 0x17, 0x71, 0x21, 0x8c, 0x1f, 0x62, 0x4e, 0x20, 0x6f, 0x28, 0xd3, 0x2f, 0x71
|
0xf2, 0x28, 0x98, 0x17, 0x71, 0x21, 0x8c, 0x1f, 0x62, 0x4e, 0x20, 0x6f, 0x28, 0xd3, 0x2f, 0x71
|
||||||
|
@ -1349,6 +1359,21 @@ namespace crypto
|
||||||
InitNoiseState (state, protocolNameHash, hh, pub);
|
InitNoiseState (state, protocolNameHash, hh, pub);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InitNoiseXKState1 (NoiseSymmetricState& state, const uint8_t * pub)
|
||||||
|
{
|
||||||
|
static const uint8_t protocolNameHash[32] =
|
||||||
|
{
|
||||||
|
0xb1, 0x37, 0x22, 0x81, 0x74, 0x23, 0xa8, 0xfd, 0xf4, 0x2d, 0xf2, 0xe6, 0x0e, 0xd1, 0xed, 0xf4,
|
||||||
|
0x1b, 0x93, 0x07, 0x1d, 0xb1, 0xec, 0x24, 0xa3, 0x67, 0xf7, 0x84, 0xec, 0x27, 0x0d, 0x81, 0x32
|
||||||
|
}; // 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,
|
||||||
|
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)
|
void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub)
|
||||||
{
|
{
|
||||||
static const uint8_t protocolNameHash[32] =
|
static const uint8_t protocolNameHash[32] =
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -29,21 +29,25 @@
|
||||||
#include "CPU.h"
|
#include "CPU.h"
|
||||||
|
|
||||||
// recognize openssl version and features
|
// recognize openssl version and features
|
||||||
#if ((OPENSSL_VERSION_NUMBER < 0x010100000) || defined(LIBRESSL_VERSION_NUMBER)) // 1.0.2 and below or LibreSSL
|
#if (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER >= 0x3050200fL)) // LibreSSL 3.5.2 and above
|
||||||
# define LEGACY_OPENSSL 1
|
# define LEGACY_OPENSSL 0
|
||||||
# define X509_getm_notBefore X509_get_notBefore
|
#elif ((OPENSSL_VERSION_NUMBER < 0x010100000) || defined(LIBRESSL_VERSION_NUMBER)) // 1.0.2 and below or LibreSSL
|
||||||
# define X509_getm_notAfter X509_get_notAfter
|
# define LEGACY_OPENSSL 1
|
||||||
|
# define X509_getm_notBefore X509_get_notBefore
|
||||||
|
# define X509_getm_notAfter X509_get_notAfter
|
||||||
#else
|
#else
|
||||||
# define LEGACY_OPENSSL 0
|
# define LEGACY_OPENSSL 0
|
||||||
# if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
|
# if (OPENSSL_VERSION_NUMBER >= 0x010101000) // 1.1.1
|
||||||
# define OPENSSL_HKDF 1
|
# define OPENSSL_HKDF 1
|
||||||
# define OPENSSL_EDDSA 1
|
# define OPENSSL_EDDSA 1
|
||||||
# define OPENSSL_X25519 1
|
# define OPENSSL_X25519 1
|
||||||
# define OPENSSL_SIPHASH 1
|
# if (OPENSSL_VERSION_NUMBER != 0x030000000) // 3.0.0, regression in SipHash
|
||||||
# endif
|
# define OPENSSL_SIPHASH 1
|
||||||
# if !defined OPENSSL_NO_CHACHA && !defined OPENSSL_NO_POLY1305 // some builds might not include them
|
# endif
|
||||||
# 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
|
#endif
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
|
@ -104,7 +108,7 @@ namespace crypto
|
||||||
BN_CTX * m_Ctx;
|
BN_CTX * m_Ctx;
|
||||||
uint8_t m_PrivateKey[32];
|
uint8_t m_PrivateKey[32];
|
||||||
#endif
|
#endif
|
||||||
bool m_IsElligatorIneligible = false; // true if definitly ineligible
|
bool m_IsElligatorIneligible = false; // true if definitely ineligible
|
||||||
};
|
};
|
||||||
|
|
||||||
// ElGamal
|
// ElGamal
|
||||||
|
@ -315,11 +319,13 @@ namespace crypto
|
||||||
uint8_t m_H[32] /*h*/, m_CK[64] /*[ck, k]*/;
|
uint8_t m_H[32] /*h*/, m_CK[64] /*[ck, k]*/;
|
||||||
|
|
||||||
void MixHash (const uint8_t * buf, size_t len);
|
void MixHash (const uint8_t * buf, size_t len);
|
||||||
|
void MixHash (const std::vector<std::pair<uint8_t *, size_t> >& bufs);
|
||||||
void MixKey (const uint8_t * sharedSecret);
|
void MixKey (const uint8_t * sharedSecret);
|
||||||
};
|
};
|
||||||
|
|
||||||
void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_N (tunnels, router)
|
void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_N (tunnels, router)
|
||||||
void InitNoiseXKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_XK (NTCP2)
|
void InitNoiseXKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_XK (NTCP2)
|
||||||
|
void InitNoiseXKState1 (NoiseSymmetricState& state, const uint8_t * pub); // Noise_XK (SSU2)
|
||||||
void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_IK (ratchets)
|
void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_IK (ratchets)
|
||||||
|
|
||||||
// init and terminate
|
// init and terminate
|
||||||
|
@ -379,7 +385,7 @@ inline int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g)
|
||||||
if (dh->p) BN_free (dh->p);
|
if (dh->p) BN_free (dh->p);
|
||||||
if (dh->q) BN_free (dh->q);
|
if (dh->q) BN_free (dh->q);
|
||||||
if (dh->g) BN_free (dh->g);
|
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)
|
inline int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key)
|
||||||
{
|
{
|
||||||
|
|
|
@ -324,7 +324,7 @@ namespace datagram
|
||||||
|
|
||||||
auto path = m_RoutingSession->GetSharedRoutingPath();
|
auto path = m_RoutingSession->GetSharedRoutingPath();
|
||||||
if (path && m_RoutingSession->IsRatchets () &&
|
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);
|
m_RoutingSession->SetSharedRoutingPath (nullptr);
|
||||||
path = nullptr;
|
path = nullptr;
|
||||||
|
@ -371,8 +371,6 @@ namespace datagram
|
||||||
{
|
{
|
||||||
// no current path, make one
|
// no current path, make one
|
||||||
path = std::make_shared<i2p::garlic::GarlicRoutingPath>();
|
path = std::make_shared<i2p::garlic::GarlicRoutingPath>();
|
||||||
path->outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel();
|
|
||||||
if (!path->outboundTunnel) return nullptr;
|
|
||||||
|
|
||||||
if (m_RemoteLeaseSet)
|
if (m_RemoteLeaseSet)
|
||||||
{
|
{
|
||||||
|
@ -386,6 +384,11 @@ namespace datagram
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
auto leaseRouter = i2p::data::netdb.FindRouter (path->remoteLease->tunnelGateway);
|
||||||
|
path->outboundTunnel = m_LocalDestination->GetTunnelPool()->GetNextOutboundTunnel(nullptr,
|
||||||
|
leaseRouter ? leaseRouter->GetCompatibleTransports (false) : (i2p::data::RouterInfo::CompatibleTransports)i2p::data::RouterInfo::eAllTransports);
|
||||||
|
if (!path->outboundTunnel) return nullptr;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -13,7 +13,6 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
#include "Config.h"
|
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "FS.h"
|
#include "FS.h"
|
||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
|
@ -35,6 +34,8 @@ namespace client
|
||||||
int inQty = DEFAULT_INBOUND_TUNNELS_QUANTITY;
|
int inQty = DEFAULT_INBOUND_TUNNELS_QUANTITY;
|
||||||
int outLen = DEFAULT_OUTBOUND_TUNNEL_LENGTH;
|
int outLen = DEFAULT_OUTBOUND_TUNNEL_LENGTH;
|
||||||
int outQty = DEFAULT_OUTBOUND_TUNNELS_QUANTITY;
|
int outQty = DEFAULT_OUTBOUND_TUNNELS_QUANTITY;
|
||||||
|
int inVar = DEFAULT_INBOUND_TUNNELS_LENGTH_VARIANCE;
|
||||||
|
int outVar = DEFAULT_OUTBOUND_TUNNELS_LENGTH_VARIANCE;
|
||||||
int numTags = DEFAULT_TAGS_TO_SEND;
|
int numTags = DEFAULT_TAGS_TO_SEND;
|
||||||
std::shared_ptr<std::vector<i2p::data::IdentHash> > explicitPeers;
|
std::shared_ptr<std::vector<i2p::data::IdentHash> > explicitPeers;
|
||||||
try
|
try
|
||||||
|
@ -53,10 +54,16 @@ namespace client
|
||||||
it = params->find (I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY);
|
it = params->find (I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY);
|
||||||
if (it != params->end ())
|
if (it != params->end ())
|
||||||
outQty = std::stoi(it->second);
|
outQty = std::stoi(it->second);
|
||||||
|
it = params->find (I2CP_PARAM_INBOUND_TUNNELS_LENGTH_VARIANCE);
|
||||||
|
if (it != params->end ())
|
||||||
|
inVar = std::stoi(it->second);
|
||||||
|
it = params->find (I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE);
|
||||||
|
if (it != params->end ())
|
||||||
|
outVar = std::stoi(it->second);
|
||||||
it = params->find (I2CP_PARAM_TAGS_TO_SEND);
|
it = params->find (I2CP_PARAM_TAGS_TO_SEND);
|
||||||
if (it != params->end ())
|
if (it != params->end ())
|
||||||
numTags = std::stoi(it->second);
|
numTags = std::stoi(it->second);
|
||||||
LogPrint (eLogInfo, "Destination: parameters for tunnel set to: ", inQty, " inbound (", inLen, " hops), ", outQty, " outbound (", outLen, " hops), ", numTags, " tags");
|
LogPrint (eLogInfo, "Destination: Parameters for tunnel set to: ", inQty, " inbound (", inLen, " hops), ", outQty, " outbound (", outLen, " hops), ", numTags, " tags");
|
||||||
it = params->find (I2CP_PARAM_RATCHET_INBOUND_TAGS);
|
it = params->find (I2CP_PARAM_RATCHET_INBOUND_TAGS);
|
||||||
if (it != params->end ())
|
if (it != params->end ())
|
||||||
SetNumRatchetInboundTags (std::stoi(it->second));
|
SetNumRatchetInboundTags (std::stoi(it->second));
|
||||||
|
@ -86,9 +93,7 @@ namespace client
|
||||||
if (it != params->end ())
|
if (it != params->end ())
|
||||||
{
|
{
|
||||||
// oveeride isPublic
|
// oveeride isPublic
|
||||||
bool dontpublish = false;
|
m_IsPublic = (it->second != "true");
|
||||||
i2p::config::GetOption (it->second, dontpublish);
|
|
||||||
m_IsPublic = !dontpublish;
|
|
||||||
}
|
}
|
||||||
it = params->find (I2CP_PARAM_LEASESET_TYPE);
|
it = params->find (I2CP_PARAM_LEASESET_TYPE);
|
||||||
if (it != params->end ())
|
if (it != params->end ())
|
||||||
|
@ -112,7 +117,7 @@ namespace client
|
||||||
m_LeaseSetPrivKey.reset (new i2p::data::Tag<32>());
|
m_LeaseSetPrivKey.reset (new i2p::data::Tag<32>());
|
||||||
if (m_LeaseSetPrivKey->FromBase64 (it->second) != 32)
|
if (m_LeaseSetPrivKey->FromBase64 (it->second) != 32)
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "Destination: invalid value i2cp.leaseSetPrivKey ", it->second);
|
LogPrint(eLogError, "Destination: Invalid value i2cp.leaseSetPrivKey ", it->second);
|
||||||
m_LeaseSetPrivKey.reset (nullptr);
|
m_LeaseSetPrivKey.reset (nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -120,10 +125,10 @@ namespace client
|
||||||
}
|
}
|
||||||
catch (std::exception & ex)
|
catch (std::exception & ex)
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "Destination: unable to parse parameters for destination: ", ex.what());
|
LogPrint(eLogError, "Destination: Unable to parse parameters for destination: ", ex.what());
|
||||||
}
|
}
|
||||||
SetNumTags (numTags);
|
SetNumTags (numTags);
|
||||||
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (inLen, outLen, inQty, outQty);
|
m_Pool = i2p::tunnel::tunnels.CreateTunnelPool (inLen, outLen, inQty, outQty, inVar, outVar);
|
||||||
if (explicitPeers)
|
if (explicitPeers)
|
||||||
m_Pool->SetExplicitPeers (explicitPeers);
|
m_Pool->SetExplicitPeers (explicitPeers);
|
||||||
if(params)
|
if(params)
|
||||||
|
@ -136,7 +141,7 @@ namespace client
|
||||||
auto minlatency = std::stoi(itr->second);
|
auto minlatency = std::stoi(itr->second);
|
||||||
if ( minlatency > 0 && maxlatency > 0 ) {
|
if ( minlatency > 0 && maxlatency > 0 ) {
|
||||||
// set tunnel pool latency
|
// set tunnel pool latency
|
||||||
LogPrint(eLogInfo, "Destination: requiring tunnel latency [", minlatency, "ms, ", maxlatency, "ms]");
|
LogPrint(eLogInfo, "Destination: Requiring tunnel latency [", minlatency, "ms, ", maxlatency, "ms]");
|
||||||
m_Pool->RequireLatency(minlatency, maxlatency);
|
m_Pool->RequireLatency(minlatency, maxlatency);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,7 +256,7 @@ namespace client
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Destination: remote LeaseSet expired");
|
LogPrint (eLogWarning, "Destination: Remote LeaseSet expired");
|
||||||
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
|
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
|
||||||
m_RemoteLeaseSets.erase (ident);
|
m_RemoteLeaseSets.erase (ident);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -331,6 +336,22 @@ namespace client
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LeaseSetDestination::SubmitECIESx25519Key (const uint8_t * key, uint64_t tag)
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t k[32];
|
||||||
|
uint64_t t;
|
||||||
|
} data;
|
||||||
|
memcpy (data.k, key, 32);
|
||||||
|
data.t = tag;
|
||||||
|
auto s = shared_from_this ();
|
||||||
|
m_Service.post ([s,data](void)
|
||||||
|
{
|
||||||
|
s->AddECIESx25519Key (data.k, data.t);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void LeaseSetDestination::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
|
void LeaseSetDestination::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
|
||||||
{
|
{
|
||||||
m_Service.post (std::bind (&LeaseSetDestination::HandleGarlicMessage, shared_from_this (), msg));
|
m_Service.post (std::bind (&LeaseSetDestination::HandleGarlicMessage, shared_from_this (), msg));
|
||||||
|
@ -396,7 +417,7 @@ namespace client
|
||||||
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
|
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
|
||||||
auto it = m_RemoteLeaseSets.find (key);
|
auto it = m_RemoteLeaseSets.find (key);
|
||||||
if (it != m_RemoteLeaseSets.end () &&
|
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;
|
leaseSet = it->second;
|
||||||
if (leaseSet->IsNewer (buf + offset, len - offset))
|
if (leaseSet->IsNewer (buf + offset, len - offset))
|
||||||
|
@ -555,16 +576,9 @@ namespace client
|
||||||
shared_from_this (), std::placeholders::_1));
|
shared_from_this (), std::placeholders::_1));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto outbound = m_Pool->GetNextOutboundTunnel ();
|
if (!m_Pool->GetInboundTunnels ().size () || !m_Pool->GetOutboundTunnels ().size ())
|
||||||
if (!outbound)
|
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Destination: Can't publish LeaseSet. No outbound tunnels");
|
LogPrint (eLogError, "Destination: Can't publish LeaseSet. Destination is not ready");
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto inbound = m_Pool->GetNextInboundTunnel ();
|
|
||||||
if (!inbound)
|
|
||||||
{
|
|
||||||
LogPrint (eLogError, "Destination: Can't publish LeaseSet. No inbound tunnels");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto floodfill = i2p::data::netdb.GetClosestFloodfill (leaseSet->GetIdentHash (), m_ExcludedFloodfills);
|
auto floodfill = i2p::data::netdb.GetClosestFloodfill (leaseSet->GetIdentHash (), m_ExcludedFloodfills);
|
||||||
|
@ -574,6 +588,33 @@ namespace client
|
||||||
m_ExcludedFloodfills.clear ();
|
m_ExcludedFloodfills.clear ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
auto outbound = m_Pool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false));
|
||||||
|
auto inbound = m_Pool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true));
|
||||||
|
if (!outbound || !inbound)
|
||||||
|
{
|
||||||
|
LogPrint (eLogInfo, "Destination: No compatible tunnels with ", floodfill->GetIdentHash ().ToBase64 (), ". Trying another floodfill");
|
||||||
|
m_ExcludedFloodfills.insert (floodfill->GetIdentHash ());
|
||||||
|
floodfill = i2p::data::netdb.GetClosestFloodfill (leaseSet->GetIdentHash (), m_ExcludedFloodfills);
|
||||||
|
if (floodfill)
|
||||||
|
{
|
||||||
|
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 ());
|
m_ExcludedFloodfills.insert (floodfill->GetIdentHash ());
|
||||||
LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ());
|
LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ());
|
||||||
RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4);
|
RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4);
|
||||||
|
@ -618,7 +659,7 @@ namespace client
|
||||||
auto ls = GetLeaseSetMt ();
|
auto ls = GetLeaseSetMt ();
|
||||||
if (!ls)
|
if (!ls)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Destination: couldn't verify LeaseSet for ", GetIdentHash().ToBase32());
|
LogPrint (eLogWarning, "Destination: Couldn't verify LeaseSet for ", GetIdentHash().ToBase32());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto s = shared_from_this ();
|
auto s = shared_from_this ();
|
||||||
|
@ -630,7 +671,7 @@ namespace client
|
||||||
if (*ls == *leaseSet)
|
if (*ls == *leaseSet)
|
||||||
{
|
{
|
||||||
// we got latest LeasetSet
|
// we got latest LeasetSet
|
||||||
LogPrint (eLogDebug, "Destination: published LeaseSet verified for ", s->GetIdentHash().ToBase32());
|
LogPrint (eLogDebug, "Destination: Published LeaseSet verified for ", s->GetIdentHash().ToBase32());
|
||||||
s->m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_REGULAR_VERIFICATION_INTERNAL));
|
s->m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_REGULAR_VERIFICATION_INTERNAL));
|
||||||
s->m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, s, std::placeholders::_1));
|
s->m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, s, std::placeholders::_1));
|
||||||
return;
|
return;
|
||||||
|
@ -639,7 +680,7 @@ namespace client
|
||||||
LogPrint (eLogDebug, "Destination: LeaseSet is different than just published for ", s->GetIdentHash().ToBase32());
|
LogPrint (eLogDebug, "Destination: LeaseSet is different than just published for ", s->GetIdentHash().ToBase32());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogWarning, "Destination: couldn't find published LeaseSet for ", s->GetIdentHash().ToBase32());
|
LogPrint (eLogWarning, "Destination: Couldn't find published LeaseSet for ", s->GetIdentHash().ToBase32());
|
||||||
// we have to publish again
|
// we have to publish again
|
||||||
s->Publish ();
|
s->Publish ();
|
||||||
});
|
});
|
||||||
|
@ -751,10 +792,10 @@ namespace client
|
||||||
std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request)
|
std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request)
|
||||||
{
|
{
|
||||||
if (!request->replyTunnel || !request->replyTunnel->IsEstablished ())
|
if (!request->replyTunnel || !request->replyTunnel->IsEstablished ())
|
||||||
request->replyTunnel = m_Pool->GetNextInboundTunnel ();
|
request->replyTunnel = m_Pool->GetNextInboundTunnel (nullptr, nextFloodfill->GetCompatibleTransports (true));
|
||||||
if (!request->replyTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no inbound tunnels found");
|
if (!request->replyTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no inbound tunnels found");
|
||||||
if (!request->outboundTunnel || !request->outboundTunnel->IsEstablished ())
|
if (!request->outboundTunnel || !request->outboundTunnel->IsEstablished ())
|
||||||
request->outboundTunnel = m_Pool->GetNextOutboundTunnel ();
|
request->outboundTunnel = m_Pool->GetNextOutboundTunnel (nullptr, nextFloodfill->GetCompatibleTransports (false));
|
||||||
if (!request->outboundTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no outbound tunnels found");
|
if (!request->outboundTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no outbound tunnels found");
|
||||||
|
|
||||||
if (request->replyTunnel && request->outboundTunnel)
|
if (request->replyTunnel && request->outboundTunnel)
|
||||||
|
@ -910,7 +951,7 @@ namespace client
|
||||||
for (auto& it: encryptionKeyTypes)
|
for (auto& it: encryptionKeyTypes)
|
||||||
{
|
{
|
||||||
auto encryptionKey = new EncryptionKey (it);
|
auto encryptionKey = new EncryptionKey (it);
|
||||||
if (isPublic)
|
if (IsPublic ())
|
||||||
PersistTemporaryKeys (encryptionKey, isSingleKey);
|
PersistTemporaryKeys (encryptionKey, isSingleKey);
|
||||||
else
|
else
|
||||||
encryptionKey->GenerateKeys ();
|
encryptionKey->GenerateKeys ();
|
||||||
|
@ -925,7 +966,7 @@ namespace client
|
||||||
m_StandardEncryptionKey.reset (encryptionKey);
|
m_StandardEncryptionKey.reset (encryptionKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPublic)
|
if (IsPublic ())
|
||||||
LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created");
|
LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created");
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -938,7 +979,7 @@ namespace client
|
||||||
m_StreamingAckDelay = std::stoi(it->second);
|
m_StreamingAckDelay = std::stoi(it->second);
|
||||||
it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS);
|
it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS);
|
||||||
if (it != params->end ())
|
if (it != params->end ())
|
||||||
i2p::config::GetOption (it->second, m_IsStreamingAnswerPings);
|
m_IsStreamingAnswerPings = (it->second == "true");
|
||||||
|
|
||||||
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
|
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
|
||||||
{
|
{
|
||||||
|
@ -966,7 +1007,7 @@ namespace client
|
||||||
}
|
}
|
||||||
catch (std::exception & ex)
|
catch (std::exception & ex)
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "Destination: unable to parse parameters for destination: ", ex.what());
|
LogPrint(eLogError, "Destination: Unable to parse parameters for destination: ", ex.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1042,7 +1083,7 @@ namespace client
|
||||||
LogPrint (eLogError, "Destination: Missing raw datagram destination");
|
LogPrint (eLogError, "Destination: Missing raw datagram destination");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LogPrint (eLogError, "Destination: Data: unexpected protocol ", buf[9]);
|
LogPrint (eLogError, "Destination: Data: Unexpected protocol ", buf[9]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1050,7 +1091,7 @@ namespace client
|
||||||
{
|
{
|
||||||
if (!streamRequestComplete)
|
if (!streamRequestComplete)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Destination: request callback is not specified in CreateStream");
|
LogPrint (eLogError, "Destination: Request callback is not specified in CreateStream");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto leaseSet = FindLeaseSet (dest);
|
auto leaseSet = FindLeaseSet (dest);
|
||||||
|
@ -1074,7 +1115,7 @@ namespace client
|
||||||
{
|
{
|
||||||
if (!streamRequestComplete)
|
if (!streamRequestComplete)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Destination: request callback is not specified in CreateStream");
|
LogPrint (eLogError, "Destination: Request callback is not specified in CreateStream");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto s = GetSharedFromThis ();
|
auto s = GetSharedFromThis ();
|
||||||
|
@ -1282,7 +1323,7 @@ namespace client
|
||||||
if (m_StandardEncryptionKey && m_StandardEncryptionKey->decryptor)
|
if (m_StandardEncryptionKey && m_StandardEncryptionKey->decryptor)
|
||||||
return m_StandardEncryptionKey->decryptor->Decrypt (encrypted, data);
|
return m_StandardEncryptionKey->decryptor->Decrypt (encrypted, data);
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Destinations: decryptor is not set");
|
LogPrint (eLogError, "Destinations: Decryptor is not set");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -53,6 +53,10 @@ namespace client
|
||||||
const int DEFAULT_INBOUND_TUNNELS_QUANTITY = 5;
|
const int DEFAULT_INBOUND_TUNNELS_QUANTITY = 5;
|
||||||
const char I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY[] = "outbound.quantity";
|
const char I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY[] = "outbound.quantity";
|
||||||
const int DEFAULT_OUTBOUND_TUNNELS_QUANTITY = 5;
|
const int DEFAULT_OUTBOUND_TUNNELS_QUANTITY = 5;
|
||||||
|
const char I2CP_PARAM_INBOUND_TUNNELS_LENGTH_VARIANCE[] = "inbound.lengthVariance";
|
||||||
|
const int DEFAULT_INBOUND_TUNNELS_LENGTH_VARIANCE = 0;
|
||||||
|
const char I2CP_PARAM_OUTBOUND_TUNNELS_LENGTH_VARIANCE[] = "outbound.lengthVariance";
|
||||||
|
const int DEFAULT_OUTBOUND_TUNNELS_LENGTH_VARIANCE = 0;
|
||||||
const char I2CP_PARAM_EXPLICIT_PEERS[] = "explicitPeers";
|
const char I2CP_PARAM_EXPLICIT_PEERS[] = "explicitPeers";
|
||||||
const int STREAM_REQUEST_TIMEOUT = 60; //in seconds
|
const int STREAM_REQUEST_TIMEOUT = 60; //in seconds
|
||||||
const char I2CP_PARAM_TAGS_TO_SEND[] = "crypto.tagsToSend";
|
const char I2CP_PARAM_TAGS_TO_SEND[] = "crypto.tagsToSend";
|
||||||
|
@ -134,6 +138,7 @@ namespace client
|
||||||
|
|
||||||
// override GarlicDestination
|
// override GarlicDestination
|
||||||
bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag);
|
bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag);
|
||||||
|
void SubmitECIESx25519Key (const uint8_t * key, uint64_t tag);
|
||||||
void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg);
|
void ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg);
|
||||||
void ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
void ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg);
|
||||||
void SetLeaseSetUpdated ();
|
void SetLeaseSetUpdated ();
|
||||||
|
|
|
@ -314,7 +314,7 @@ namespace garlic
|
||||||
GetOwner ()->HandleECIESx25519GarlicClove (buf + offset, size);
|
GetOwner ()->HandleECIESx25519GarlicClove (buf + offset, size);
|
||||||
break;
|
break;
|
||||||
case eECIESx25519BlkNextKey:
|
case eECIESx25519BlkNextKey:
|
||||||
LogPrint (eLogDebug, "Garlic: next key");
|
LogPrint (eLogDebug, "Garlic: Next key");
|
||||||
if (receiveTagset)
|
if (receiveTagset)
|
||||||
HandleNextKey (buf + offset, size, receiveTagset);
|
HandleNextKey (buf + offset, size, receiveTagset);
|
||||||
else
|
else
|
||||||
|
@ -322,7 +322,7 @@ namespace garlic
|
||||||
break;
|
break;
|
||||||
case eECIESx25519BlkAck:
|
case eECIESx25519BlkAck:
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "Garlic: ack");
|
LogPrint (eLogDebug, "Garlic: Ack");
|
||||||
int numAcks = size >> 2; // /4
|
int numAcks = size >> 2; // /4
|
||||||
auto offset1 = offset;
|
auto offset1 = offset;
|
||||||
for (auto i = 0; i < numAcks; i++)
|
for (auto i = 0; i < numAcks; i++)
|
||||||
|
@ -334,24 +334,24 @@ namespace garlic
|
||||||
}
|
}
|
||||||
case eECIESx25519BlkAckRequest:
|
case eECIESx25519BlkAckRequest:
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "Garlic: ack request");
|
LogPrint (eLogDebug, "Garlic: Ack request");
|
||||||
m_AckRequests.push_back ({receiveTagset->GetTagSetID (), index});
|
m_AckRequests.push_back ({receiveTagset->GetTagSetID (), index});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case eECIESx25519BlkTermination:
|
case eECIESx25519BlkTermination:
|
||||||
LogPrint (eLogDebug, "Garlic: termination");
|
LogPrint (eLogDebug, "Garlic: Termination");
|
||||||
if (GetOwner ())
|
if (GetOwner ())
|
||||||
GetOwner ()->RemoveECIESx25519Session (m_RemoteStaticKey);
|
GetOwner ()->RemoveECIESx25519Session (m_RemoteStaticKey);
|
||||||
if (receiveTagset) receiveTagset->Expire ();
|
if (receiveTagset) receiveTagset->Expire ();
|
||||||
break;
|
break;
|
||||||
case eECIESx25519BlkDateTime:
|
case eECIESx25519BlkDateTime:
|
||||||
LogPrint (eLogDebug, "Garlic: datetime");
|
LogPrint (eLogDebug, "Garlic: Datetime");
|
||||||
break;
|
break;
|
||||||
case eECIESx25519BlkOptions:
|
case eECIESx25519BlkOptions:
|
||||||
LogPrint (eLogDebug, "Garlic: options");
|
LogPrint (eLogDebug, "Garlic: Options");
|
||||||
break;
|
break;
|
||||||
case eECIESx25519BlkPadding:
|
case eECIESx25519BlkPadding:
|
||||||
LogPrint (eLogDebug, "Garlic: padding");
|
LogPrint (eLogDebug, "Garlic: Padding");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LogPrint (eLogWarning, "Garlic: Unknown block type ", (int)blk);
|
LogPrint (eLogWarning, "Garlic: Unknown block type ", (int)blk);
|
||||||
|
@ -381,7 +381,7 @@ namespace garlic
|
||||||
newTagset->NextSessionTagRatchet ();
|
newTagset->NextSessionTagRatchet ();
|
||||||
m_SendTagset = newTagset;
|
m_SendTagset = newTagset;
|
||||||
m_SendForwardKey = false;
|
m_SendForwardKey = false;
|
||||||
LogPrint (eLogDebug, "Garlic: next send tagset ", newTagset->GetTagSetID (), " created");
|
LogPrint (eLogDebug, "Garlic: Next send tagset ", newTagset->GetTagSetID (), " created");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogDebug, "Garlic: Unexpected next key ", keyID);
|
LogPrint (eLogDebug, "Garlic: Unexpected next key ", keyID);
|
||||||
|
@ -424,7 +424,7 @@ namespace garlic
|
||||||
GenerateMoreReceiveTags (newTagset, (GetOwner () && GetOwner ()->GetNumRatchetInboundTags () > 0) ?
|
GenerateMoreReceiveTags (newTagset, (GetOwner () && GetOwner ()->GetNumRatchetInboundTags () > 0) ?
|
||||||
GetOwner ()->GetNumRatchetInboundTags () : ECIESX25519_MAX_NUM_GENERATED_TAGS);
|
GetOwner ()->GetNumRatchetInboundTags () : ECIESX25519_MAX_NUM_GENERATED_TAGS);
|
||||||
receiveTagset->Expire ();
|
receiveTagset->Expire ();
|
||||||
LogPrint (eLogDebug, "Garlic: next receive tagset ", tagsetID, " created");
|
LogPrint (eLogDebug, "Garlic: Next receive tagset ", tagsetID, " created");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,7 +446,7 @@ namespace garlic
|
||||||
m_NextSendRatchet->key = i2p::transport::transports.GetNextX25519KeysPair ();
|
m_NextSendRatchet->key = i2p::transport::transports.GetNextX25519KeysPair ();
|
||||||
|
|
||||||
m_SendForwardKey = true;
|
m_SendForwardKey = true;
|
||||||
LogPrint (eLogDebug, "Garlic: new send ratchet ", m_NextSendRatchet->newKey ? "new" : "old", " key ", m_NextSendRatchet->keyID, " created");
|
LogPrint (eLogDebug, "Garlic: New send ratchet ", m_NextSendRatchet->newKey ? "new" : "old", " key ", m_NextSendRatchet->keyID, " created");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ECIESX25519AEADRatchetSession::NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen, bool isStatic)
|
bool ECIESX25519AEADRatchetSession::NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen, bool isStatic)
|
||||||
|
@ -534,7 +534,7 @@ namespace garlic
|
||||||
LogPrint (eLogError, "Garlic: Can't encode elligator");
|
LogPrint (eLogError, "Garlic: Can't encode elligator");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
memcpy (m_NSREncodedKey, out + offset, 56); // for possible next NSR
|
memcpy (m_NSREncodedKey, out + offset, 32); // for possible next NSR
|
||||||
memcpy (m_NSRH, m_H, 32);
|
memcpy (m_NSRH, m_H, 32);
|
||||||
offset += 32;
|
offset += 32;
|
||||||
// KDF for Reply Key Section
|
// KDF for Reply Key Section
|
||||||
|
@ -618,7 +618,7 @@ namespace garlic
|
||||||
bool ECIESX25519AEADRatchetSession::HandleNewOutgoingSessionReply (uint8_t * buf, size_t len)
|
bool ECIESX25519AEADRatchetSession::HandleNewOutgoingSessionReply (uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
// we are Alice
|
// we are Alice
|
||||||
LogPrint (eLogDebug, "Garlic: reply received");
|
LogPrint (eLogDebug, "Garlic: Reply received");
|
||||||
const uint8_t * tag = buf;
|
const uint8_t * tag = buf;
|
||||||
buf += 8; len -= 8; // tag
|
buf += 8; len -= 8; // tag
|
||||||
uint8_t bepk[32]; // Bob's ephemeral key
|
uint8_t bepk[32]; // Bob's ephemeral key
|
||||||
|
@ -700,7 +700,7 @@ namespace garlic
|
||||||
uint64_t tag = m_SendTagset->GetNextSessionTag ();
|
uint64_t tag = m_SendTagset->GetNextSessionTag ();
|
||||||
if (!tag)
|
if (!tag)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Garlic: can't create new ECIES-X25519-AEAD-Ratchet tag for send tagset");
|
LogPrint (eLogError, "Garlic: Can't create new ECIES-X25519-AEAD-Ratchet tag for send tagset");
|
||||||
if (GetOwner ())
|
if (GetOwner ())
|
||||||
GetOwner ()->RemoveECIESx25519Session (m_RemoteStaticKey);
|
GetOwner ()->RemoveECIESx25519Session (m_RemoteStaticKey);
|
||||||
return false;
|
return false;
|
||||||
|
@ -776,7 +776,7 @@ namespace garlic
|
||||||
if (receiveTagset->IsNS ())
|
if (receiveTagset->IsNS ())
|
||||||
{
|
{
|
||||||
// our of sequence NSR
|
// our of sequence NSR
|
||||||
LogPrint (eLogDebug, "Garlic: check for out of order NSR with index ", index);
|
LogPrint (eLogDebug, "Garlic: Check for out of order NSR with index ", index);
|
||||||
if (receiveTagset->GetNextIndex () - index < ECIESX25519_NSR_NUM_GENERATED_TAGS/2)
|
if (receiveTagset->GetNextIndex () - index < ECIESX25519_NSR_NUM_GENERATED_TAGS/2)
|
||||||
GenerateMoreReceiveTags (receiveTagset, ECIESX25519_NSR_NUM_GENERATED_TAGS);
|
GenerateMoreReceiveTags (receiveTagset, ECIESX25519_NSR_NUM_GENERATED_TAGS);
|
||||||
return HandleNewOutgoingSessionReply (buf, len);
|
return HandleNewOutgoingSessionReply (buf, len);
|
||||||
|
@ -912,7 +912,7 @@ namespace garlic
|
||||||
{
|
{
|
||||||
if (payloadLen > I2NP_MAX_MESSAGE_SIZE)
|
if (payloadLen > I2NP_MAX_MESSAGE_SIZE)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Garlic: payload length ", payloadLen, " is too long");
|
LogPrint (eLogError, "Garlic: Payload length ", payloadLen, " is too long");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
m_LastSentTimestamp = ts;
|
m_LastSentTimestamp = ts;
|
||||||
|
@ -1056,7 +1056,7 @@ namespace garlic
|
||||||
auto tag = GetOwner ()->AddECIESx25519SessionNextTag (receiveTagset);
|
auto tag = GetOwner ()->AddECIESx25519SessionNextTag (receiveTagset);
|
||||||
if (!tag)
|
if (!tag)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Garlic: can't create new ECIES-X25519-AEAD-Ratchet tag for receive tagset");
|
LogPrint (eLogError, "Garlic: Can't create new ECIES-X25519-AEAD-Ratchet tag for receive tagset");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
* Copyright (c) 2013-2021, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
|
@ -213,7 +212,7 @@ namespace garlic
|
||||||
uint8_t m_NSREncodedKey[32], m_NSRH[32], m_NSRKey[32]; // new session reply, for incoming only
|
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;
|
std::shared_ptr<i2p::crypto::X25519Keys> m_EphemeralKeys;
|
||||||
SessionState m_State = eSessionStateNew;
|
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
|
m_LastSentTimestamp = 0; // in milliseconds
|
||||||
std::shared_ptr<RatchetTagSet> m_SendTagset, m_NSRSendTagset;
|
std::shared_ptr<RatchetTagSet> m_SendTagset, m_NSRSendTagset;
|
||||||
std::unique_ptr<i2p::data::IdentHash> m_Destination;// TODO: might not need it
|
std::unique_ptr<i2p::data::IdentHash> m_Destination;// TODO: might not need it
|
||||||
|
@ -230,7 +229,7 @@ namespace garlic
|
||||||
{
|
{
|
||||||
return m_Destination ? *m_Destination : i2p::data::IdentHash ();
|
return m_Destination ? *m_Destination : i2p::data::IdentHash ();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// single session for all incoming messages
|
// single session for all incoming messages
|
||||||
class RouterIncomingRatchetSession: public ECIESX25519AEADRatchetSession
|
class RouterIncomingRatchetSession: public ECIESX25519AEADRatchetSession
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace crypto
|
||||||
BN_add (l, l, tmp);
|
BN_add (l, l, tmp);
|
||||||
BN_sub_word (two_252_2, 2); // 2^252 - 2
|
BN_sub_word (two_252_2, 2); // 2^252 - 2
|
||||||
|
|
||||||
// -121665*inv(121666)
|
// -121665*inv(121666)
|
||||||
d = BN_new ();
|
d = BN_new ();
|
||||||
BN_set_word (tmp, 121666);
|
BN_set_word (tmp, 121666);
|
||||||
BN_mod_inverse (tmp, tmp, q, ctx);
|
BN_mod_inverse (tmp, tmp, q, ctx);
|
||||||
|
@ -61,7 +61,7 @@ namespace crypto
|
||||||
BN_mod (By, By, q, ctx); // % q
|
BN_mod (By, By, q, ctx); // % q
|
||||||
|
|
||||||
// precalculate Bi256 table
|
// precalculate Bi256 table
|
||||||
Bi256Carry = { Bx, By }; // B
|
Bi256Carry = { Bx, By }; // B
|
||||||
for (int i = 0; i < 32; i++)
|
for (int i = 0; i < 32; i++)
|
||||||
{
|
{
|
||||||
Bi256[i][0] = Bi256Carry; // first point
|
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 (!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); }
|
if (!t2) { t2 = BN_CTX_get (ctx); BN_mul (t2, p2.x, p2.y, ctx); }
|
||||||
BN_mul (t3, t1, t2, 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)
|
if (p1.z)
|
||||||
{
|
{
|
||||||
|
@ -264,9 +264,9 @@ namespace crypto
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BN_mul (t2, p.x, p.y, ctx); // t = x*y
|
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)
|
if (p.z)
|
||||||
BN_sqr (z2, p.z, ctx); // z2 = D = z^2
|
BN_sqr (z2, p.z, ctx); // z2 = D = z^2
|
||||||
else
|
else
|
||||||
|
@ -349,7 +349,7 @@ namespace crypto
|
||||||
BN_mod_inverse (y, p.z, q, ctx);
|
BN_mod_inverse (y, p.z, q, ctx);
|
||||||
BN_mod_mul (x, p.x, y, q, ctx); // x = x/z
|
BN_mod_mul (x, p.x, y, q, ctx); // x = x/z
|
||||||
BN_mod_mul (y, p.y, y, q, ctx); // y = y/z
|
BN_mod_mul (y, p.y, y, q, ctx); // y = y/z
|
||||||
return EDDSAPoint{x, y};
|
return EDDSAPoint{x, y};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return EDDSAPoint{BN_dup (p.x), BN_dup (p.y)};
|
return EDDSAPoint{BN_dup (p.x), BN_dup (p.y)};
|
||||||
|
@ -506,13 +506,13 @@ namespace crypto
|
||||||
std::swap (z2, z3);
|
std::swap (z2, z3);
|
||||||
}
|
}
|
||||||
BN_mod_inverse (z2, z2, q, ctx);
|
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_mod_mul(res, x2, z2, q, ctx);
|
||||||
BN_CTX_end (ctx);
|
BN_CTX_end (ctx);
|
||||||
return res;
|
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);
|
BIGNUM * p1 = DecodeBN<32> (p);
|
||||||
uint8_t k[32];
|
uint8_t k[32];
|
||||||
|
@ -524,7 +524,7 @@ namespace crypto
|
||||||
BN_free (p1); BN_free (n); BN_free (q1);
|
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);
|
BIGNUM *p1 = BN_new (); BN_set_word (p1, 9);
|
||||||
uint8_t k[32];
|
uint8_t k[32];
|
||||||
|
|
|
@ -85,8 +85,8 @@ namespace crypto
|
||||||
EDDSAPoint DecodePublicKey (const uint8_t * buf, BN_CTX * ctx) const;
|
EDDSAPoint DecodePublicKey (const uint8_t * buf, BN_CTX * ctx) const;
|
||||||
void EncodePublicKey (const EDDSAPoint& publicKey, uint8_t * buf, BN_CTX * ctx) const;
|
void EncodePublicKey (const EDDSAPoint& publicKey, uint8_t * buf, BN_CTX * ctx) const;
|
||||||
#if !OPENSSL_X25519
|
#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 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 ScalarMulB (const uint8_t * e, uint8_t * buf, BN_CTX * ctx) const;
|
||||||
#endif
|
#endif
|
||||||
void BlindPublicKey (const uint8_t * pub, const uint8_t * seed, uint8_t * blinded); // for encrypted LeaseSet2, pub - 32, seed - 64, blinded - 32
|
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
|
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
|
||||||
|
|
|
@ -189,7 +189,7 @@ namespace crypto
|
||||||
// assume a < p, so don't check for a % p = 0, but a = 0 only
|
// assume a < p, so don't check for a % p = 0, but a = 0 only
|
||||||
if (BN_is_zero(a)) return 0;
|
if (BN_is_zero(a)) return 0;
|
||||||
BIGNUM * r = BN_CTX_get (ctx);
|
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))
|
if (BN_is_word(r, 1))
|
||||||
return 1;
|
return 1;
|
||||||
else if (BN_is_zero(r))
|
else if (BN_is_zero(r))
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -60,10 +60,38 @@ namespace fs {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DetectDataDir(const std::string & cmdline_param, bool isService) {
|
void DetectDataDir(const std::string & cmdline_param, bool isService) {
|
||||||
|
// with 'datadir' option
|
||||||
if (cmdline_param != "") {
|
if (cmdline_param != "") {
|
||||||
dataDir = cmdline_param;
|
dataDir = cmdline_param;
|
||||||
return;
|
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
|
#ifdef _WIN32
|
||||||
wchar_t localAppData[MAX_PATH];
|
wchar_t localAppData[MAX_PATH];
|
||||||
|
|
||||||
|
@ -117,12 +145,10 @@ namespace fs {
|
||||||
dataDir = std::string (ext) + "/" + appName;
|
dataDir = std::string (ext) + "/" + appName;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif // ANDROID
|
||||||
// otherwise use /data/files
|
// use /home/user/.i2pd or /tmp/i2pd
|
||||||
char *home = getenv("HOME");
|
char *home = getenv("HOME");
|
||||||
if (isService) {
|
if (home != NULL && strlen(home) > 0) {
|
||||||
dataDir = "/var/lib/" + appName;
|
|
||||||
} else if (home != NULL && strlen(home) > 0) {
|
|
||||||
dataDir = std::string(home) + "/." + appName;
|
dataDir = std::string(home) + "/." + appName;
|
||||||
} else {
|
} else {
|
||||||
dataDir = "/tmp/" + appName;
|
dataDir = "/tmp/" + appName;
|
||||||
|
|
12
libi2pd/FS.h
12
libi2pd/FS.h
|
@ -83,8 +83,8 @@ namespace fs {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set datadir either from cmdline option or using autodetection
|
* @brief Set datadir either from cmdline option or using autodetection
|
||||||
* @param cmdline_param Value of cmdline parameter --datadir=<something>
|
* @param cmdline_param Value of cmdline parameter --datadir=<something>
|
||||||
* @param isService Value of cmdline parameter --service
|
* @param isService Value of cmdline parameter --service
|
||||||
*
|
*
|
||||||
* Examples of autodetected paths:
|
* Examples of autodetected paths:
|
||||||
*
|
*
|
||||||
|
@ -93,11 +93,11 @@ namespace fs {
|
||||||
* Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/
|
* Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/
|
||||||
* Unix: /var/lib/i2pd/ (system=1) >> ~/.i2pd/ or /tmp/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
|
* @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:
|
* Examples of autodetected paths:
|
||||||
*
|
*
|
||||||
|
@ -106,7 +106,7 @@ namespace fs {
|
||||||
* Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/certificates
|
* Mac: /Library/Application Support/i2pd/ or ~/Library/Application Support/i2pd/certificates
|
||||||
* Unix: /var/lib/i2pd/certificates (system=1) >> ~/.i2pd/ or /tmp/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
|
* @brief Create subdirectories inside datadir
|
||||||
|
@ -115,7 +115,7 @@ namespace fs {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get list of files in directory
|
* @brief Get list of files in directory
|
||||||
* @param path Path to directory
|
* @param path Path to directory
|
||||||
* @param files Vector to store found files
|
* @param files Vector to store found files
|
||||||
* @return true on success and false if directory not exists
|
* @return true on success and false if directory not exists
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -88,7 +88,7 @@ namespace data
|
||||||
}
|
}
|
||||||
EVP_PKEY_free (pkey);
|
EVP_PKEY_free (pkey);
|
||||||
if (verifier && cn)
|
if (verifier && cn)
|
||||||
m_SigningKeys[cn] = verifier;
|
m_SigningKeys.emplace (cn, std::make_pair(verifier, m_SigningKeys.size () + 1));
|
||||||
}
|
}
|
||||||
SSL_free (ssl);
|
SSL_free (ssl);
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ namespace data
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Families::VerifyFamily (const std::string& family, const IdentHash& ident,
|
bool Families::VerifyFamily (const std::string& family, const IdentHash& ident,
|
||||||
const char * signature, const char * key)
|
const char * signature, const char * key) const
|
||||||
{
|
{
|
||||||
uint8_t buf[100], signatureBuf[64];
|
uint8_t buf[100], signatureBuf[64];
|
||||||
size_t len = family.length (), signatureLen = strlen (signature);
|
size_t len = family.length (), signatureLen = strlen (signature);
|
||||||
|
@ -137,11 +137,19 @@ namespace data
|
||||||
Base64ToByteStream (signature, signatureLen, signatureBuf, 64);
|
Base64ToByteStream (signature, signatureLen, signatureBuf, 64);
|
||||||
auto it = m_SigningKeys.find (family);
|
auto it = m_SigningKeys.find (family);
|
||||||
if (it != m_SigningKeys.end ())
|
if (it != m_SigningKeys.end ())
|
||||||
return it->second->Verify (buf, len, signatureBuf);
|
return it->second.first->Verify (buf, len, signatureBuf);
|
||||||
// TODO: process key
|
// TODO: process key
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FamilyID Families::GetFamilyID (const std::string& family) const
|
||||||
|
{
|
||||||
|
auto it = m_SigningKeys.find (family);
|
||||||
|
if (it != m_SigningKeys.end ())
|
||||||
|
return it->second.second;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
std::string CreateFamilySignature (const std::string& family, const IdentHash& ident)
|
std::string CreateFamilySignature (const std::string& family, const IdentHash& ident)
|
||||||
{
|
{
|
||||||
auto filename = i2p::fs::DataDirPath("family", (family + ".key"));
|
auto filename = i2p::fs::DataDirPath("family", (family + ".key"));
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -19,6 +19,7 @@ namespace i2p
|
||||||
{
|
{
|
||||||
namespace data
|
namespace data
|
||||||
{
|
{
|
||||||
|
typedef int FamilyID;
|
||||||
class Families
|
class Families
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -27,7 +28,8 @@ namespace data
|
||||||
~Families ();
|
~Families ();
|
||||||
void LoadCertificates ();
|
void LoadCertificates ();
|
||||||
bool VerifyFamily (const std::string& family, const IdentHash& ident,
|
bool VerifyFamily (const std::string& family, const IdentHash& ident,
|
||||||
const char * signature, const char * key = nullptr);
|
const char * signature, const char * key = nullptr) const;
|
||||||
|
FamilyID GetFamilyID (const std::string& family) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -35,7 +37,7 @@ namespace data
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::map<std::string, std::shared_ptr<i2p::crypto::Verifier> > m_SigningKeys;
|
std::map<std::string, std::pair<std::shared_ptr<i2p::crypto::Verifier>, FamilyID> > m_SigningKeys; // family -> (verifier, id)
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string CreateFamilySignature (const std::string& family, const IdentHash& ident);
|
std::string CreateFamilySignature (const std::string& family, const IdentHash& ident);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -271,7 +271,7 @@ namespace garlic
|
||||||
(*numCloves)++;
|
(*numCloves)++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (msg) // clove message ifself if presented
|
if (msg) // clove message itself if presented
|
||||||
{
|
{
|
||||||
size += CreateGarlicClove (payload + size, msg, m_Destination ? m_Destination->IsDestination () : false);
|
size += CreateGarlicClove (payload + size, msg, m_Destination ? m_Destination->IsDestination () : false);
|
||||||
(*numCloves)++;
|
(*numCloves)++;
|
||||||
|
@ -293,14 +293,14 @@ namespace garlic
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
if (isDestination)
|
if (isDestination)
|
||||||
{
|
{
|
||||||
buf[size] = eGarlicDeliveryTypeDestination << 5;// delivery instructions flag destination
|
buf[size] = eGarlicDeliveryTypeDestination << 5;// delivery instructions flag destination
|
||||||
size++;
|
size++;
|
||||||
memcpy (buf + size, m_Destination->GetIdentHash (), 32);
|
memcpy (buf + size, m_Destination->GetIdentHash (), 32);
|
||||||
size += 32;
|
size += 32;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
buf[size] = 0;// delivery instructions flag local
|
buf[size] = 0;// delivery instructions flag local
|
||||||
size++;
|
size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,13 +484,18 @@ namespace garlic
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GarlicDestination::SubmitECIESx25519Key (const uint8_t * key, uint64_t tag)
|
||||||
|
{
|
||||||
|
AddECIESx25519Key (key, tag);
|
||||||
|
}
|
||||||
|
|
||||||
void GarlicDestination::HandleGarlicMessage (std::shared_ptr<I2NPMessage> msg)
|
void GarlicDestination::HandleGarlicMessage (std::shared_ptr<I2NPMessage> msg)
|
||||||
{
|
{
|
||||||
uint8_t * buf = msg->GetPayload ();
|
uint8_t * buf = msg->GetPayload ();
|
||||||
uint32_t length = bufbe32toh (buf);
|
uint32_t length = bufbe32toh (buf);
|
||||||
if (length > msg->GetLength ())
|
if (length > msg->GetLength ())
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "Garlic: message length ", length, " exceeds I2NP message length ", msg->GetLength ());
|
LogPrint (eLogWarning, "Garlic: Message length ", length, " exceeds I2NP message length ", msg->GetLength ());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto mod = length & 0x0f; // %16
|
auto mod = length & 0x0f; // %16
|
||||||
|
@ -519,7 +524,7 @@ namespace garlic
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogWarning, "Garlic: message length ", length, " is less than 32 bytes");
|
LogPrint (eLogWarning, "Garlic: Message length ", length, " is less than 32 bytes");
|
||||||
}
|
}
|
||||||
if (!found) // assume new session
|
if (!found) // assume new session
|
||||||
{
|
{
|
||||||
|
@ -542,18 +547,18 @@ namespace garlic
|
||||||
auto session = std::make_shared<ECIESX25519AEADRatchetSession> (this, false); // incoming
|
auto session = std::make_shared<ECIESX25519AEADRatchetSession> (this, false); // incoming
|
||||||
if (!session->HandleNextMessage (buf, length, nullptr, 0))
|
if (!session->HandleNextMessage (buf, length, nullptr, 0))
|
||||||
{
|
{
|
||||||
// try to gererate more tags for last tagset
|
// try to generate more tags for last tagset
|
||||||
if (m_LastTagset && (m_LastTagset->GetNextIndex () - m_LastTagset->GetTrimBehind () < 3*ECIESX25519_MAX_NUM_GENERATED_TAGS))
|
if (m_LastTagset && (m_LastTagset->GetNextIndex () - m_LastTagset->GetTrimBehind () < 3*ECIESX25519_MAX_NUM_GENERATED_TAGS))
|
||||||
{
|
{
|
||||||
uint64_t missingTag; memcpy (&missingTag, buf, 8);
|
uint64_t missingTag; memcpy (&missingTag, buf, 8);
|
||||||
auto maxTags = std::max (m_NumRatchetInboundTags, ECIESX25519_MAX_NUM_GENERATED_TAGS);
|
auto maxTags = std::max (m_NumRatchetInboundTags, ECIESX25519_MAX_NUM_GENERATED_TAGS);
|
||||||
LogPrint (eLogWarning, "Garlic: trying to generate more ECIES-X25519-AEAD-Ratchet tags");
|
LogPrint (eLogWarning, "Garlic: Trying to generate more ECIES-X25519-AEAD-Ratchet tags");
|
||||||
for (int i = 0; i < maxTags; i++)
|
for (int i = 0; i < maxTags; i++)
|
||||||
{
|
{
|
||||||
auto nextTag = AddECIESx25519SessionNextTag (m_LastTagset);
|
auto nextTag = AddECIESx25519SessionNextTag (m_LastTagset);
|
||||||
if (!nextTag)
|
if (!nextTag)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Garlic: can't create new ECIES-X25519-AEAD-Ratchet tag for last tagset");
|
LogPrint (eLogError, "Garlic: Can't create new ECIES-X25519-AEAD-Ratchet tag for last tagset");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (nextTag == missingTag)
|
if (nextTag == missingTag)
|
||||||
|
@ -567,7 +572,7 @@ namespace garlic
|
||||||
if (!found) m_LastTagset = nullptr;
|
if (!found) m_LastTagset = nullptr;
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
|
LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -586,7 +591,7 @@ namespace garlic
|
||||||
if (it->second.tagset->HandleNextMessage (buf, len, it->second.index))
|
if (it->second.tagset->HandleNextMessage (buf, len, it->second.index))
|
||||||
m_LastTagset = it->second.tagset;
|
m_LastTagset = it->second.tagset;
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
|
LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message");
|
||||||
m_ECIESx25519Tags.erase (it);
|
m_ECIESx25519Tags.erase (it);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -629,7 +634,7 @@ namespace garlic
|
||||||
SHA256 (buf, payloadSize, digest);
|
SHA256 (buf, payloadSize, digest);
|
||||||
if (memcmp (payloadHash, digest, 32)) // payload hash doesn't match
|
if (memcmp (payloadHash, digest, 32)) // payload hash doesn't match
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Garlic: wrong payload hash");
|
LogPrint (eLogError, "Garlic: Wrong payload hash");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HandleGarlicPayload (buf, payloadSize, from);
|
HandleGarlicPayload (buf, payloadSize, from);
|
||||||
|
@ -639,7 +644,7 @@ namespace garlic
|
||||||
{
|
{
|
||||||
if (len < 1)
|
if (len < 1)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Garlic: payload is too short");
|
LogPrint (eLogError, "Garlic: Payload is too short");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int numCloves = buf[0];
|
int numCloves = buf[0];
|
||||||
|
@ -654,7 +659,7 @@ namespace garlic
|
||||||
if (flag & 0x80) // encrypted?
|
if (flag & 0x80) // encrypted?
|
||||||
{
|
{
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
LogPrint (eLogWarning, "Garlic: clove encrypted");
|
LogPrint (eLogWarning, "Garlic: Clove encrypted");
|
||||||
buf += 32;
|
buf += 32;
|
||||||
}
|
}
|
||||||
ptrdiff_t offset = buf - buf1;
|
ptrdiff_t offset = buf - buf1;
|
||||||
|
@ -662,35 +667,35 @@ namespace garlic
|
||||||
switch (deliveryType)
|
switch (deliveryType)
|
||||||
{
|
{
|
||||||
case eGarlicDeliveryTypeLocal:
|
case eGarlicDeliveryTypeLocal:
|
||||||
LogPrint (eLogDebug, "Garlic: type local");
|
LogPrint (eLogDebug, "Garlic: Type local");
|
||||||
if (offset > (int)len)
|
if (offset > (int)len)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Garlic: message is too short");
|
LogPrint (eLogError, "Garlic: Message is too short");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
HandleI2NPMessage (buf, len - offset);
|
HandleI2NPMessage (buf, len - offset);
|
||||||
break;
|
break;
|
||||||
case eGarlicDeliveryTypeDestination:
|
case eGarlicDeliveryTypeDestination:
|
||||||
LogPrint (eLogDebug, "Garlic: type destination");
|
LogPrint (eLogDebug, "Garlic: Type destination");
|
||||||
buf += 32; // destination. check it later or for multiple destinations
|
buf += 32; // destination. check it later or for multiple destinations
|
||||||
offset = buf - buf1;
|
offset = buf - buf1;
|
||||||
if (offset > (int)len)
|
if (offset > (int)len)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Garlic: message is too short");
|
LogPrint (eLogError, "Garlic: Message is too short");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
HandleI2NPMessage (buf, len - offset);
|
HandleI2NPMessage (buf, len - offset);
|
||||||
break;
|
break;
|
||||||
case eGarlicDeliveryTypeTunnel:
|
case eGarlicDeliveryTypeTunnel:
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "Garlic: type tunnel");
|
LogPrint (eLogDebug, "Garlic: Type tunnel");
|
||||||
// gwHash and gwTunnel sequence is reverted
|
// gwHash and gwTunnel sequence is reverted
|
||||||
uint8_t * gwHash = buf;
|
uint8_t * gwHash = buf;
|
||||||
buf += 32;
|
buf += 32;
|
||||||
offset = buf - buf1;
|
offset = buf - buf1;
|
||||||
if (offset + 4 > (int)len)
|
if (offset + 4 > (int)len)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Garlic: message is too short");
|
LogPrint (eLogError, "Garlic: Message is too short");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
uint32_t gwTunnel = bufbe32toh (buf);
|
uint32_t gwTunnel = bufbe32toh (buf);
|
||||||
|
@ -721,32 +726,32 @@ namespace garlic
|
||||||
{
|
{
|
||||||
if (offset > (int)len)
|
if (offset > (int)len)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Garlic: message is too short");
|
LogPrint (eLogError, "Garlic: Message is too short");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i2p::transport::transports.SendMessage (ident,
|
i2p::transport::transports.SendMessage (ident,
|
||||||
CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len - offset)));
|
CreateI2NPMessage (buf, GetI2NPMessageLength (buf, len - offset)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogWarning, "Garlic: type router for inbound tunnels not supported");
|
LogPrint (eLogWarning, "Garlic: Type router for inbound tunnels not supported");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
LogPrint (eLogWarning, "Garlic: unknown delivery type ", (int)deliveryType);
|
LogPrint (eLogWarning, "Garlic: Unknown delivery type ", (int)deliveryType);
|
||||||
}
|
}
|
||||||
if (offset > (int)len)
|
if (offset > (int)len)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Garlic: message is too short");
|
LogPrint (eLogError, "Garlic: Message is too short");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
buf += GetI2NPMessageLength (buf, len - offset); // I2NP
|
buf += GetI2NPMessageLength (buf, len - offset); // I2NP
|
||||||
buf += 4; // CloveID
|
buf += 4; // CloveID
|
||||||
buf += 8; // Date
|
buf += 8; // Date
|
||||||
buf += 3; // Certificate
|
buf += 3; // Certificate
|
||||||
offset = buf - buf1;
|
offset = buf - buf1;
|
||||||
if (offset > (int)len)
|
if (offset > (int)len)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Garlic: clove is too long");
|
LogPrint (eLogError, "Garlic: Clove is too long");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
len -= offset;
|
len -= offset;
|
||||||
|
@ -780,7 +785,7 @@ namespace garlic
|
||||||
session = it->second;
|
session = it->second;
|
||||||
if (session->IsInactive (i2p::util::GetSecondsSinceEpoch ()))
|
if (session->IsInactive (i2p::util::GetSecondsSinceEpoch ()))
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "Garlic: session restarted");
|
LogPrint (eLogDebug, "Garlic: Session restarted");
|
||||||
session = nullptr;
|
session = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -840,7 +845,7 @@ namespace garlic
|
||||||
it->second->GetSharedRoutingPath (); // delete shared path if necessary
|
it->second->GetSharedRoutingPath (); // delete shared path if necessary
|
||||||
if (!it->second->CleanupExpiredTags ())
|
if (!it->second->CleanupExpiredTags ())
|
||||||
{
|
{
|
||||||
LogPrint (eLogInfo, "Routing session to ", it->first.ToBase32 (), " deleted");
|
LogPrint (eLogInfo, "Garlic: Routing session to ", it->first.ToBase32 (), " deleted");
|
||||||
it->second->SetOwner (nullptr);
|
it->second->SetOwner (nullptr);
|
||||||
it = m_Sessions.erase (it);
|
it = m_Sessions.erase (it);
|
||||||
}
|
}
|
||||||
|
@ -925,7 +930,7 @@ namespace garlic
|
||||||
if (session)
|
if (session)
|
||||||
{
|
{
|
||||||
session->MessageConfirmed (msgID);
|
session->MessageConfirmed (msgID);
|
||||||
LogPrint (eLogDebug, "Garlic: message ", msgID, " acknowledged");
|
LogPrint (eLogDebug, "Garlic: Message ", msgID, " acknowledged");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1019,7 +1024,7 @@ namespace garlic
|
||||||
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
uint32_t ts = i2p::util::GetSecondsSinceEpoch ();
|
||||||
for (auto it: files)
|
for (auto it: files)
|
||||||
if (ts >= i2p::fs::GetLastUpdateTime (it) + INCOMING_TAGS_EXPIRATION_TIMEOUT)
|
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)
|
void GarlicDestination::HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len)
|
||||||
|
@ -1030,7 +1035,7 @@ namespace garlic
|
||||||
switch (deliveryType)
|
switch (deliveryType)
|
||||||
{
|
{
|
||||||
case eGarlicDeliveryTypeDestination:
|
case eGarlicDeliveryTypeDestination:
|
||||||
LogPrint (eLogDebug, "Garlic: type destination");
|
LogPrint (eLogDebug, "Garlic: Type destination");
|
||||||
buf += 32; // TODO: check destination
|
buf += 32; // TODO: check destination
|
||||||
#if (__cplusplus >= 201703L) // C++ 17 or higher
|
#if (__cplusplus >= 201703L) // C++ 17 or higher
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
|
@ -1038,7 +1043,7 @@ namespace garlic
|
||||||
// no break here
|
// no break here
|
||||||
case eGarlicDeliveryTypeLocal:
|
case eGarlicDeliveryTypeLocal:
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "Garlic: type local");
|
LogPrint (eLogDebug, "Garlic: Type local");
|
||||||
I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid
|
I2NPMessageType typeID = (I2NPMessageType)(buf[0]); buf++; // typeid
|
||||||
int32_t msgID = bufbe32toh (buf); buf += 4; // msgID
|
int32_t msgID = bufbe32toh (buf); buf += 4; // msgID
|
||||||
buf += 4; // expiration
|
buf += 4; // expiration
|
||||||
|
@ -1046,19 +1051,19 @@ namespace garlic
|
||||||
if (offset <= (int)len)
|
if (offset <= (int)len)
|
||||||
HandleCloveI2NPMessage (typeID, buf, len - offset, msgID);
|
HandleCloveI2NPMessage (typeID, buf, len - offset, msgID);
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Garlic: clove is too long");
|
LogPrint (eLogError, "Garlic: Clove is too long");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case eGarlicDeliveryTypeTunnel:
|
case eGarlicDeliveryTypeTunnel:
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "Garlic: type tunnel");
|
LogPrint (eLogDebug, "Garlic: Type tunnel");
|
||||||
// gwHash and gwTunnel sequence is reverted
|
// gwHash and gwTunnel sequence is reverted
|
||||||
const uint8_t * gwHash = buf;
|
const uint8_t * gwHash = buf;
|
||||||
buf += 32;
|
buf += 32;
|
||||||
ptrdiff_t offset = buf - buf1;
|
ptrdiff_t offset = buf - buf1;
|
||||||
if (offset + 13 > (int)len)
|
if (offset + 13 > (int)len)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Garlic: message is too short");
|
LogPrint (eLogError, "Garlic: Message is too short");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
uint32_t gwTunnel = bufbe32toh (buf); buf += 4;
|
uint32_t gwTunnel = bufbe32toh (buf); buf += 4;
|
||||||
|
@ -1079,7 +1084,7 @@ namespace garlic
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
LogPrint (eLogWarning, "Garlic: unexpected delivery type ", (int)deliveryType);
|
LogPrint (eLogWarning, "Garlic: Unexpected delivery type ", (int)deliveryType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1105,7 +1110,7 @@ namespace garlic
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogInfo, "Garlic: ECIESx25519 session with static key ", staticKeyTag.ToBase64 (), " already exists");
|
LogPrint (eLogInfo, "Garlic: ECIESx25519 session with static key ", staticKeyTag.ToBase64 (), " already exists");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -245,6 +245,7 @@ namespace garlic
|
||||||
void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag
|
void AddSessionKey (const uint8_t * key, const uint8_t * tag); // one tag
|
||||||
void AddECIESx25519Key (const uint8_t * key, uint64_t tag); // one tag
|
void AddECIESx25519Key (const uint8_t * key, uint64_t tag); // one tag
|
||||||
virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread
|
virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread
|
||||||
|
virtual void SubmitECIESx25519Key (const uint8_t * key, uint64_t tag); // from different thread
|
||||||
void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID);
|
void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID);
|
||||||
uint64_t AddECIESx25519SessionNextTag (ReceiveRatchetTagSetPtr tagset);
|
uint64_t AddECIESx25519SessionNextTag (ReceiveRatchetTagSetPtr tagset);
|
||||||
void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session);
|
void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session);
|
||||||
|
|
|
@ -96,7 +96,7 @@ namespace crypto
|
||||||
EC_POINT * C = EC_POINT_new (m_Group);
|
EC_POINT * C = EC_POINT_new (m_Group);
|
||||||
EC_POINT_mul (m_Group, C, z1, pub, z2, ctx); // z1*P + z2*pub
|
EC_POINT_mul (m_Group, C, z1, pub, z2, ctx); // z1*P + z2*pub
|
||||||
BIGNUM * x = BN_CTX_get (ctx);
|
BIGNUM * x = BN_CTX_get (ctx);
|
||||||
GetXY (C, x, nullptr); // Cx
|
GetXY (C, x, nullptr); // Cx
|
||||||
BN_mod (x, x, q, ctx); // Cx % q
|
BN_mod (x, x, q, ctx); // Cx % q
|
||||||
bool ret = !BN_cmp (x, r); // Cx = r ?
|
bool ret = !BN_cmp (x, r); // Cx = r ?
|
||||||
EC_POINT_free (C);
|
EC_POINT_free (C);
|
||||||
|
@ -111,8 +111,8 @@ namespace crypto
|
||||||
BN_CTX * ctx = BN_CTX_new ();
|
BN_CTX * ctx = BN_CTX_new ();
|
||||||
BN_CTX_start (ctx);
|
BN_CTX_start (ctx);
|
||||||
EC_POINT * C = EC_POINT_new (m_Group); // C = k*P = (rx, ry)
|
EC_POINT * C = EC_POINT_new (m_Group); // C = k*P = (rx, ry)
|
||||||
EC_POINT * Q = nullptr;
|
EC_POINT * Q = nullptr;
|
||||||
if (EC_POINT_set_compressed_coordinates_GFp (m_Group, C, r, isNegativeY ? 1 : 0, ctx))
|
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 * S = EC_POINT_new (m_Group); // S = s*P
|
||||||
EC_POINT_mul (m_Group, S, s, nullptr, nullptr, ctx);
|
EC_POINT_mul (m_Group, S, s, nullptr, nullptr, ctx);
|
||||||
|
|
|
@ -279,7 +279,7 @@ namespace http
|
||||||
method = tokens[0];
|
method = tokens[0];
|
||||||
uri = tokens[1];
|
uri = tokens[1];
|
||||||
version = tokens[2];
|
version = tokens[2];
|
||||||
expect = HEADER_LINE;
|
expect = HEADER_LINE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -363,7 +363,7 @@ namespace http
|
||||||
return false; /* no header */
|
return false; /* no header */
|
||||||
if (it->second.find("gzip") != std::string::npos)
|
if (it->second.find("gzip") != std::string::npos)
|
||||||
return true; /* gotcha! */
|
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 true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -409,7 +409,7 @@ namespace http
|
||||||
/* all ok */
|
/* all ok */
|
||||||
version = tokens[0];
|
version = tokens[0];
|
||||||
status = tokens[2];
|
status = tokens[2];
|
||||||
expect = HEADER_LINE;
|
expect = HEADER_LINE;
|
||||||
} else {
|
} else {
|
||||||
std::string line = str.substr(pos, eol - pos);
|
std::string line = str.substr(pos, eol - pos);
|
||||||
auto p = parse_header_line(line);
|
auto p = parse_header_line(line);
|
||||||
|
@ -460,7 +460,7 @@ namespace http
|
||||||
case 304: ptr = "Not Modified"; break;
|
case 304: ptr = "Not Modified"; break;
|
||||||
case 307: ptr = "Temporary Redirect"; break;
|
case 307: ptr = "Temporary Redirect"; break;
|
||||||
/* client error */
|
/* client error */
|
||||||
case 400: ptr = "Bad Request"; break;
|
case 400: ptr = "Bad Request"; break;
|
||||||
case 401: ptr = "Unauthorized"; break;
|
case 401: ptr = "Unauthorized"; break;
|
||||||
case 403: ptr = "Forbidden"; break;
|
case 403: ptr = "Forbidden"; break;
|
||||||
case 404: ptr = "Not Found"; break;
|
case 404: ptr = "Not Found"; break;
|
||||||
|
@ -471,7 +471,7 @@ namespace http
|
||||||
case 502: ptr = "Bad Gateway"; break;
|
case 502: ptr = "Bad Gateway"; break;
|
||||||
case 503: ptr = "Not Implemented"; break;
|
case 503: ptr = "Not Implemented"; break;
|
||||||
case 504: ptr = "Gateway Timeout"; break;
|
case 504: ptr = "Gateway Timeout"; break;
|
||||||
default: ptr = "Unknown Status"; break;
|
default: ptr = "Unknown Status"; break;
|
||||||
}
|
}
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,7 +161,7 @@ namespace http
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Merge HTTP response content with Transfer-Encoding: chunked
|
* @brief Merge HTTP response content with Transfer-Encoding: chunked
|
||||||
* @param in Input stream
|
* @param in Input stream
|
||||||
* @param out Output stream
|
* @param out Output stream
|
||||||
* @return true on success, false otherwise
|
* @return true on success, false otherwise
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -38,20 +38,7 @@ namespace i2p
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> NewI2NPTunnelMessage (bool endpoint)
|
std::shared_ptr<I2NPMessage> NewI2NPTunnelMessage (bool endpoint)
|
||||||
{
|
{
|
||||||
I2NPMessage * msg = nullptr;
|
return i2p::tunnel::tunnels.NewI2NPTunnelMessage (endpoint);
|
||||||
if (endpoint)
|
|
||||||
{
|
|
||||||
// should fit two tunnel message + tunnel gateway header, enough for one garlic encrypted streaming packet
|
|
||||||
msg = new I2NPMessageBuffer<2*i2p::tunnel::TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + TUNNEL_GATEWAY_HEADER_SIZE + 28>(); // reserved for alignment and NTCP 16 + 6 + 6
|
|
||||||
msg->Align (6);
|
|
||||||
msg->offset += TUNNEL_GATEWAY_HEADER_SIZE; // reserve room for TunnelGateway header
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
msg = new I2NPMessageBuffer<i2p::tunnel::TUNNEL_DATA_MSG_SIZE + I2NP_HEADER_SIZE + 34>(); // reserved for alignment and NTCP 16 + 6 + 12
|
|
||||||
msg->Align (12);
|
|
||||||
}
|
|
||||||
return std::shared_ptr<I2NPMessage>(msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> NewI2NPMessage (size_t len)
|
std::shared_ptr<I2NPMessage> NewI2NPMessage (size_t len)
|
||||||
|
@ -88,7 +75,7 @@ namespace i2p
|
||||||
{
|
{
|
||||||
auto msg = NewI2NPMessage (len);
|
auto msg = NewI2NPMessage (len);
|
||||||
if (msg->Concat (buf, len) < len)
|
if (msg->Concat (buf, len) < len)
|
||||||
LogPrint (eLogError, "I2NP: message length ", len, " exceeds max length ", msg->maxLen);
|
LogPrint (eLogError, "I2NP: Message length ", len, " exceeds max length ", msg->maxLen);
|
||||||
msg->FillI2NPMessageHeader (msgType, replyMsgID);
|
msg->FillI2NPMessageHeader (msgType, replyMsgID);
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
@ -103,7 +90,7 @@ namespace i2p
|
||||||
msg->from = from;
|
msg->from = from;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "I2NP: message length ", len, " exceeds max length");
|
LogPrint (eLogError, "I2NP: Message length ", len, " exceeds max length");
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +171,7 @@ namespace i2p
|
||||||
std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest,
|
std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest,
|
||||||
const std::set<i2p::data::IdentHash>& excludedFloodfills,
|
const std::set<i2p::data::IdentHash>& excludedFloodfills,
|
||||||
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel, const uint8_t * replyKey,
|
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 ();
|
int cnt = excludedFloodfills.size ();
|
||||||
auto m = cnt > 7 ? NewI2NPMessage () : NewI2NPShortMessage ();
|
auto m = cnt > 7 ? NewI2NPMessage () : NewI2NPShortMessage ();
|
||||||
|
@ -642,7 +629,7 @@ namespace i2p
|
||||||
// we send it to reply tunnel
|
// we send it to reply tunnel
|
||||||
transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
|
||||||
CreateTunnelGatewayMsg (bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_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
|
else
|
||||||
{
|
{
|
||||||
|
@ -698,7 +685,7 @@ namespace i2p
|
||||||
htobe16buf (payload + TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET, len);
|
htobe16buf (payload + TUNNEL_GATEWAY_HEADER_LENGTH_OFFSET, len);
|
||||||
msg->len += TUNNEL_GATEWAY_HEADER_SIZE;
|
msg->len += TUNNEL_GATEWAY_HEADER_SIZE;
|
||||||
if (msg->Concat (buf, len) < len)
|
if (msg->Concat (buf, len) < len)
|
||||||
LogPrint (eLogError, "I2NP: tunnel gateway buffer overflow ", msg->maxLen);
|
LogPrint (eLogError, "I2NP: Tunnel gateway buffer overflow ", msg->maxLen);
|
||||||
msg->FillI2NPMessageHeader (eI2NPTunnelGateway);
|
msg->FillI2NPMessageHeader (eI2NPTunnelGateway);
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
@ -729,7 +716,7 @@ namespace i2p
|
||||||
msg->offset += gatewayMsgOffset;
|
msg->offset += gatewayMsgOffset;
|
||||||
msg->len += gatewayMsgOffset;
|
msg->len += gatewayMsgOffset;
|
||||||
if (msg->Concat (buf, len) < len)
|
if (msg->Concat (buf, len) < len)
|
||||||
LogPrint (eLogError, "I2NP: tunnel gateway buffer overflow ", msg->maxLen);
|
LogPrint (eLogError, "I2NP: Tunnel gateway buffer overflow ", msg->maxLen);
|
||||||
msg->FillI2NPMessageHeader (msgType, replyMsgID); // create content message
|
msg->FillI2NPMessageHeader (msgType, replyMsgID); // create content message
|
||||||
len = msg->GetLength ();
|
len = msg->GetLength ();
|
||||||
msg->offset -= gatewayMsgOffset;
|
msg->offset -= gatewayMsgOffset;
|
||||||
|
@ -744,13 +731,13 @@ namespace i2p
|
||||||
{
|
{
|
||||||
if (len < I2NP_HEADER_SIZE_OFFSET + 2)
|
if (len < I2NP_HEADER_SIZE_OFFSET + 2)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "I2NP: message length ", len, " is smaller than header");
|
LogPrint (eLogError, "I2NP: Message length ", len, " is smaller than header");
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
auto l = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET) + I2NP_HEADER_SIZE;
|
auto l = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET) + I2NP_HEADER_SIZE;
|
||||||
if (l > len)
|
if (l > len)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "I2NP: message length ", l, " exceeds buffer length ", len);
|
LogPrint (eLogError, "I2NP: Message length ", l, " exceeds buffer length ", len);
|
||||||
l = len;
|
l = len;
|
||||||
}
|
}
|
||||||
return l;
|
return l;
|
||||||
|
@ -760,18 +747,18 @@ namespace i2p
|
||||||
{
|
{
|
||||||
if (len < I2NP_HEADER_SIZE)
|
if (len < I2NP_HEADER_SIZE)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "I2NP: message length ", len, " is smaller than header");
|
LogPrint (eLogError, "I2NP: Message length ", len, " is smaller than header");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint8_t typeID = msg[I2NP_HEADER_TYPEID_OFFSET];
|
uint8_t typeID = msg[I2NP_HEADER_TYPEID_OFFSET];
|
||||||
uint32_t msgID = bufbe32toh (msg + I2NP_HEADER_MSGID_OFFSET);
|
uint32_t msgID = bufbe32toh (msg + I2NP_HEADER_MSGID_OFFSET);
|
||||||
LogPrint (eLogDebug, "I2NP: msg received len=", len,", type=", (int)typeID, ", msgID=", (unsigned int)msgID);
|
LogPrint (eLogDebug, "I2NP: Msg received len=", len,", type=", (int)typeID, ", msgID=", (unsigned int)msgID);
|
||||||
uint8_t * buf = msg + I2NP_HEADER_SIZE;
|
uint8_t * buf = msg + I2NP_HEADER_SIZE;
|
||||||
auto size = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET);
|
auto size = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET);
|
||||||
len -= I2NP_HEADER_SIZE;
|
len -= I2NP_HEADER_SIZE;
|
||||||
if (size > len)
|
if (size > len)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "I2NP: payload size ", size, " exceeds buffer length ", len);
|
LogPrint (eLogError, "I2NP: Payload size ", size, " exceeds buffer length ", len);
|
||||||
size = len;
|
size = len;
|
||||||
}
|
}
|
||||||
switch (typeID)
|
switch (typeID)
|
||||||
|
@ -815,13 +802,8 @@ namespace i2p
|
||||||
break;
|
break;
|
||||||
case eI2NPGarlic:
|
case eI2NPGarlic:
|
||||||
{
|
{
|
||||||
if (msg->from)
|
if (msg->from && msg->from->GetTunnelPool ())
|
||||||
{
|
msg->from->GetTunnelPool ()->ProcessGarlicMessage (msg);
|
||||||
if (msg->from->GetTunnelPool ())
|
|
||||||
msg->from->GetTunnelPool ()->ProcessGarlicMessage (msg);
|
|
||||||
else
|
|
||||||
LogPrint (eLogInfo, "I2NP: Local destination for garlic doesn't exist anymore");
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
i2p::context.ProcessGarlicMessage (msg);
|
i2p::context.ProcessGarlicMessage (msg);
|
||||||
break;
|
break;
|
||||||
|
@ -860,7 +842,7 @@ namespace i2p
|
||||||
Flush ();
|
Flush ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2NPMessagesHandler::PutNextMessage (std::shared_ptr<I2NPMessage> msg)
|
void I2NPMessagesHandler::PutNextMessage (std::shared_ptr<I2NPMessage>&& msg)
|
||||||
{
|
{
|
||||||
if (msg)
|
if (msg)
|
||||||
{
|
{
|
||||||
|
|
|
@ -150,7 +150,7 @@ namespace tunnel
|
||||||
std::shared_ptr<i2p::tunnel::InboundTunnel> from;
|
std::shared_ptr<i2p::tunnel::InboundTunnel> from;
|
||||||
|
|
||||||
I2NPMessage (): buf (nullptr),len (I2NP_HEADER_SIZE + 2),
|
I2NPMessage (): buf (nullptr),len (I2NP_HEADER_SIZE + 2),
|
||||||
offset(2), maxLen (0), from (nullptr) {}; // reserve 2 bytes for NTCP header
|
offset(2), maxLen (0), from (nullptr) {}; // reserve 2 bytes for NTCP header
|
||||||
|
|
||||||
// header accessors
|
// header accessors
|
||||||
uint8_t * GetHeader () { return GetBuffer (); };
|
uint8_t * GetHeader () { return GetBuffer (); };
|
||||||
|
@ -274,8 +274,8 @@ namespace tunnel
|
||||||
uint32_t replyTunnelID, bool exploratory = false, std::set<i2p::data::IdentHash> * excludedPeers = nullptr);
|
uint32_t replyTunnelID, bool exploratory = false, std::set<i2p::data::IdentHash> * excludedPeers = nullptr);
|
||||||
std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest,
|
std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest,
|
||||||
const std::set<i2p::data::IdentHash>& excludedFloodfills,
|
const std::set<i2p::data::IdentHash>& excludedFloodfills,
|
||||||
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel,
|
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel,
|
||||||
const uint8_t * replyKey, const uint8_t * replyTag, bool replyECIES = false);
|
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> 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);
|
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);
|
||||||
|
@ -301,7 +301,7 @@ namespace tunnel
|
||||||
public:
|
public:
|
||||||
|
|
||||||
~I2NPMessagesHandler ();
|
~I2NPMessagesHandler ();
|
||||||
void PutNextMessage (std::shared_ptr<I2NPMessage> msg);
|
void PutNextMessage (std::shared_ptr<I2NPMessage>&& msg);
|
||||||
void Flush ();
|
void Flush ();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -50,42 +50,3 @@ uint64_t be64toh(uint64_t big64)
|
||||||
return u64.raw_value;
|
return u64.raw_value;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* it can be used in Windows 8
|
|
||||||
#include <Winsock2.h>
|
|
||||||
|
|
||||||
uint16_t htobe16(uint16_t int16)
|
|
||||||
{
|
|
||||||
return htons(int16);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t htobe32(uint32_t int32)
|
|
||||||
{
|
|
||||||
return htonl(int32);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t htobe64(uint64_t int64)
|
|
||||||
{
|
|
||||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/jj710199%28v=vs.85%29.aspx
|
|
||||||
//return htonll(int64);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint16_t be16toh(uint16_t big16)
|
|
||||||
{
|
|
||||||
return ntohs(big16);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t be32toh(uint32_t big32)
|
|
||||||
{
|
|
||||||
return ntohl(big32);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t be64toh(uint64_t big64)
|
|
||||||
{
|
|
||||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/jj710199%28v=vs.85%29.aspx
|
|
||||||
//return ntohll(big64);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*/
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2020, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -13,10 +13,11 @@
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__NetBSD__)
|
#if defined(__FreeBSD__) || defined(__NetBSD__)
|
||||||
#include <sys/endian.h>
|
#include <sys/endian.h>
|
||||||
|
|
||||||
#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__GLIBC__)
|
#elif defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__GLIBC__)
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
#elif defined(__APPLE__) && defined(__MACH__)
|
|
||||||
|
|
||||||
|
#elif defined(__APPLE__) && defined(__MACH__)
|
||||||
#include <libkern/OSByteOrder.h>
|
#include <libkern/OSByteOrder.h>
|
||||||
|
|
||||||
#define htobe16(x) OSSwapHostToBigInt16(x)
|
#define htobe16(x) OSSwapHostToBigInt16(x)
|
||||||
|
@ -34,6 +35,22 @@
|
||||||
#define be64toh(x) OSSwapBigToHostInt64(x)
|
#define be64toh(x) OSSwapBigToHostInt64(x)
|
||||||
#define le64toh(x) OSSwapLittleToHostInt64(x)
|
#define le64toh(x) OSSwapLittleToHostInt64(x)
|
||||||
|
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
#define htobe16(x) __builtin_bswap16(x)
|
||||||
|
#define htole16(x) (x)
|
||||||
|
#define be16toh(x) __builtin_bswap16(x)
|
||||||
|
#define le16toh(x) (x)
|
||||||
|
|
||||||
|
#define htobe32(x) __builtin_bswap32(x)
|
||||||
|
#define htole32(x) (x)
|
||||||
|
#define be32toh(x) __builtin_bswap32(x)
|
||||||
|
#define le32toh(x) (x)
|
||||||
|
|
||||||
|
#define htobe64(x) __builtin_bswap64(x)
|
||||||
|
#define htole64(x) (x)
|
||||||
|
#define be64toh(x) __builtin_bswap64(x)
|
||||||
|
#define le64toh(x) (x)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define NEEDS_LOCAL_ENDIAN
|
#define NEEDS_LOCAL_ENDIAN
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
|
@ -19,7 +19,8 @@ namespace data
|
||||||
Identity& Identity::operator=(const Keys& keys)
|
Identity& Identity::operator=(const Keys& keys)
|
||||||
{
|
{
|
||||||
// copy public and signing keys together
|
// copy public and signing keys together
|
||||||
memcpy (publicKey, keys.publicKey, sizeof (publicKey) + sizeof (signingKey));
|
memcpy (publicKey, keys.publicKey, sizeof (publicKey));
|
||||||
|
memcpy (signingKey, keys.signingKey, sizeof (signingKey));
|
||||||
memset (certificate, 0, sizeof (certificate));
|
memset (certificate, 0, sizeof (certificate));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -63,7 +64,7 @@ namespace data
|
||||||
{
|
{
|
||||||
case SIGNING_KEY_TYPE_ECDSA_SHA256_P256:
|
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);
|
RAND_bytes (m_StandardIdentity.signingKey, padding);
|
||||||
memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::ECDSAP256_KEY_LENGTH);
|
memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::ECDSAP256_KEY_LENGTH);
|
||||||
break;
|
break;
|
||||||
|
@ -214,7 +215,7 @@ namespace data
|
||||||
{
|
{
|
||||||
if (len < DEFAULT_IDENTITY_SIZE)
|
if (len < DEFAULT_IDENTITY_SIZE)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Identity: buffer length ", len, " is too small");
|
LogPrint (eLogError, "Identity: Buffer length ", len, " is too small");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
memcpy (&m_StandardIdentity, buf, DEFAULT_IDENTITY_SIZE);
|
memcpy (&m_StandardIdentity, buf, DEFAULT_IDENTITY_SIZE);
|
||||||
|
@ -508,7 +509,7 @@ namespace data
|
||||||
if (m_Public->GetSignatureLen () + ret > len) return 0;
|
if (m_Public->GetSignatureLen () + ret > len) return 0;
|
||||||
if (!m_Public->Verify (offlineInfo, keyLen + 6, buf + ret))
|
if (!m_Public->Verify (offlineInfo, keyLen + 6, buf + ret))
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Identity: offline signature verification failed");
|
LogPrint (eLogError, "Identity: Offline signature verification failed");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
ret += m_Public->GetSignatureLen ();
|
ret += m_Public->GetSignatureLen ();
|
||||||
|
@ -787,7 +788,7 @@ namespace data
|
||||||
keys.m_OfflineSignature.resize (pubKeyLen + m_Public->GetSignatureLen () + 6);
|
keys.m_OfflineSignature.resize (pubKeyLen + m_Public->GetSignatureLen () + 6);
|
||||||
htobe32buf (keys.m_OfflineSignature.data (), expires); // expires
|
htobe32buf (keys.m_OfflineSignature.data (), expires); // expires
|
||||||
htobe16buf (keys.m_OfflineSignature.data () + 4, type); // type
|
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
|
Sign (keys.m_OfflineSignature.data (), pubKeyLen + 6, keys.m_OfflineSignature.data () + 6 + pubKeyLen); // signature
|
||||||
// recreate signer
|
// recreate signer
|
||||||
keys.m_Signer = nullptr;
|
keys.m_Signer = nullptr;
|
||||||
|
|
|
@ -120,7 +120,7 @@ namespace data
|
||||||
CryptoKeyType GetCryptoKeyType () const;
|
CryptoKeyType GetCryptoKeyType () const;
|
||||||
void DropVerifier () const; // to save memory
|
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);
|
void RecalculateIdentHash(uint8_t * buff=nullptr);
|
||||||
|
|
||||||
static i2p::crypto::Verifier * CreateVerifier (SigningKeyType keyType);
|
static i2p::crypto::Verifier * CreateVerifier (SigningKeyType keyType);
|
||||||
|
@ -222,7 +222,7 @@ namespace data
|
||||||
RoutingDestination () {};
|
RoutingDestination () {};
|
||||||
virtual ~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 void Encrypt (const uint8_t * data, uint8_t * encrypted) const = 0; // encrypt data for
|
||||||
virtual bool IsDestination () const = 0; // for garlic
|
virtual bool IsDestination () const = 0; // for garlic
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ namespace data
|
||||||
size_t size = m_Identity->GetFullLen ();
|
size_t size = m_Identity->GetFullLen ();
|
||||||
if (size > m_BufferLen)
|
if (size > m_BufferLen)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "LeaseSet: identity length ", size, " exceeds buffer size ", m_BufferLen);
|
LogPrint (eLogError, "LeaseSet: Identity length ", size, " exceeds buffer size ", m_BufferLen);
|
||||||
m_IsValid = false;
|
m_IsValid = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -80,10 +80,10 @@ namespace data
|
||||||
}
|
}
|
||||||
uint8_t num = m_Buffer[size];
|
uint8_t num = m_Buffer[size];
|
||||||
size++; // num
|
size++; // num
|
||||||
LogPrint (eLogDebug, "LeaseSet: read num=", (int)num);
|
LogPrint (eLogDebug, "LeaseSet: Read num=", (int)num);
|
||||||
if (!num || num > MAX_NUM_LEASES)
|
if (!num || num > MAX_NUM_LEASES)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "LeaseSet: incorrect number of leases", (int)num);
|
LogPrint (eLogError, "LeaseSet: Rncorrect number of leases", (int)num);
|
||||||
m_IsValid = false;
|
m_IsValid = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ namespace data
|
||||||
}
|
}
|
||||||
if (!m_ExpirationTime)
|
if (!m_ExpirationTime)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "LeaseSet: all leases are expired. Dropped");
|
LogPrint (eLogWarning, "LeaseSet: All leases are expired. Dropped");
|
||||||
m_IsValid = false;
|
m_IsValid = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ namespace data
|
||||||
}
|
}
|
||||||
else if (!m_Identity->Verify (m_Buffer, signedSize, leases))
|
else if (!m_Identity->Verify (m_Buffer, signedSize, leases))
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "LeaseSet: verification failed");
|
LogPrint (eLogWarning, "LeaseSet: Verification failed");
|
||||||
m_IsValid = false;
|
m_IsValid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -274,7 +274,7 @@ namespace data
|
||||||
{
|
{
|
||||||
if (len <= m_BufferLen) m_BufferLen = len;
|
if (len <= m_BufferLen) m_BufferLen = len;
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "LeaseSet2: actual buffer size ", len , " exceeds full buffer size ", 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):
|
LeaseSet2::LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases, CryptoKeyType preferredCrypto):
|
||||||
|
@ -331,7 +331,7 @@ namespace data
|
||||||
m_TransientVerifier = ProcessOfflineSignature (identity, buf, len, offset);
|
m_TransientVerifier = ProcessOfflineSignature (identity, buf, len, offset);
|
||||||
if (!m_TransientVerifier)
|
if (!m_TransientVerifier)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "LeaseSet2: offline signature failed");
|
LogPrint (eLogError, "LeaseSet2: Offline signature failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -378,7 +378,7 @@ namespace data
|
||||||
bool verified = verifier->Verify (buf - 1, signatureOffset + 1, buf + signatureOffset);
|
bool verified = verifier->Verify (buf - 1, signatureOffset + 1, buf + signatureOffset);
|
||||||
const_cast<uint8_t *>(buf)[-1] = c;
|
const_cast<uint8_t *>(buf)[-1] = c;
|
||||||
if (!verified)
|
if (!verified)
|
||||||
LogPrint (eLogWarning, "LeaseSet2: verification failed");
|
LogPrint (eLogWarning, "LeaseSet2: Verification failed");
|
||||||
return verified;
|
return verified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -489,7 +489,7 @@ namespace data
|
||||||
m_TransientVerifier = ProcessOfflineSignature (blindedVerifier, buf, len, offset);
|
m_TransientVerifier = ProcessOfflineSignature (blindedVerifier, buf, len, offset);
|
||||||
if (!m_TransientVerifier)
|
if (!m_TransientVerifier)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "LeaseSet2: offline signature failed");
|
LogPrint (eLogError, "LeaseSet2: Offline signature failed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -515,7 +515,7 @@ namespace data
|
||||||
key->GetBlindedKey (date, blinded.data ());
|
key->GetBlindedKey (date, blinded.data ());
|
||||||
if (memcmp (blindedPublicKey, blinded.data (), blindedKeyLen))
|
if (memcmp (blindedPublicKey, blinded.data (), blindedKeyLen))
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "LeaseSet2: blinded public key doesn't match");
|
LogPrint (eLogError, "LeaseSet2: Blinded public key doesn't match");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -569,7 +569,7 @@ namespace data
|
||||||
ReadFromBuffer (innerPlainText.data () + 1, lenInnerPlaintext - 1);
|
ReadFromBuffer (innerPlainText.data () + 1, lenInnerPlaintext - 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "LeaseSet2: unexpected LeaseSet type ", (int)innerPlainText[0], " inside encrypted LeaseSet");
|
LogPrint (eLogError, "LeaseSet2: Unexpected LeaseSet type ", (int)innerPlainText[0], " inside encrypted LeaseSet");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -582,7 +582,7 @@ namespace data
|
||||||
// helper for ExtractClientAuthData
|
// helper for ExtractClientAuthData
|
||||||
static inline bool GetAuthCookie (const uint8_t * authClients, int numClients, const uint8_t * okm, uint8_t * authCookie)
|
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++)
|
for (int i = 0; i < numClients; i++)
|
||||||
{
|
{
|
||||||
if (!memcmp (okm + 44, authClients + i*40, 8)) // clientID_i
|
if (!memcmp (okm + 44, authClients + i*40, 8)) // clientID_i
|
||||||
|
@ -606,7 +606,7 @@ namespace data
|
||||||
{
|
{
|
||||||
const uint8_t * ephemeralPublicKey = buf + offset; offset += 32; // ephemeralPublicKey
|
const uint8_t * ephemeralPublicKey = buf + offset; offset += 32; // ephemeralPublicKey
|
||||||
uint16_t numClients = bufbe16toh (buf + offset); offset += 2; // clients
|
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)
|
if (offset > len)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "LeaseSet2: Too many clients ", numClients, " in DH auth data");
|
LogPrint (eLogError, "LeaseSet2: Too many clients ", numClients, " in DH auth data");
|
||||||
|
@ -632,7 +632,7 @@ namespace data
|
||||||
{
|
{
|
||||||
const uint8_t * authSalt = buf + offset; offset += 32; // authSalt
|
const uint8_t * authSalt = buf + offset; offset += 32; // authSalt
|
||||||
uint16_t numClients = bufbe16toh (buf + offset); offset += 2; // clients
|
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)
|
if (offset > len)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "LeaseSet2: Too many clients ", numClients, " in PSK auth data");
|
LogPrint (eLogError, "LeaseSet2: Too many clients ", numClients, " in PSK auth data");
|
||||||
|
@ -653,7 +653,7 @@ namespace data
|
||||||
LogPrint (eLogError, "LeaseSet2: Can't calculate authCookie: psk_i is not provided");
|
LogPrint (eLogError, "LeaseSet2: Can't calculate authCookie: psk_i is not provided");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "LeaseSet2: unknown client auth type ", (int)flag);
|
LogPrint (eLogError, "LeaseSet2: Unknown client auth type ", (int)flag);
|
||||||
}
|
}
|
||||||
return offset - 1;
|
return offset - 1;
|
||||||
}
|
}
|
||||||
|
@ -737,7 +737,7 @@ namespace data
|
||||||
htobe64buf (m_Buffer + offset, ts);
|
htobe64buf (m_Buffer + offset, ts);
|
||||||
offset += 8; // end date
|
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):
|
LocalLeaseSet::LocalLeaseSet (std::shared_ptr<const IdentityEx> identity, const uint8_t * buf, size_t len):
|
||||||
|
@ -768,7 +768,7 @@ namespace data
|
||||||
size_t size = ident.GetFullLen ();
|
size_t size = ident.GetFullLen ();
|
||||||
if (size > sz)
|
if (size > sz)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "LeaseSet: identity length ", size, " exceeds buffer size ", sz);
|
LogPrint (eLogError, "LeaseSet: Identity length ", size, " exceeds buffer size ", sz);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// encryption key
|
// encryption key
|
||||||
|
@ -779,7 +779,7 @@ namespace data
|
||||||
++size;
|
++size;
|
||||||
if (!numLeases || numLeases > MAX_NUM_LEASES)
|
if (!numLeases || numLeases > MAX_NUM_LEASES)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "LeaseSet: incorrect number of leases", (int)numLeases);
|
LogPrint (eLogError, "LeaseSet: Incorrect number of leases", (int)numLeases);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const uint8_t * leases = ptr + size;
|
const uint8_t * leases = ptr + size;
|
||||||
|
@ -984,7 +984,7 @@ namespace data
|
||||||
m_StoreHash = blindedKey->GetStoreHash ();
|
m_StoreHash = blindedKey->GetStoreHash ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "LeaseSet2: couldn't extract inner layer");
|
LogPrint (eLogError, "LeaseSet2: Couldn't extract inner layer");
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalEncryptedLeaseSet2::CreateClientAuthData (const uint8_t * subcredential, int authType, std::shared_ptr<std::vector<AuthPublicKey> > authKeys, const uint8_t * authCookie, uint8_t * authData) const
|
void LocalEncryptedLeaseSet2::CreateClientAuthData (const uint8_t * subcredential, int authType, std::shared_ptr<std::vector<AuthPublicKey> > authKeys, const uint8_t * authCookie, uint8_t * authData) const
|
||||||
|
@ -995,7 +995,7 @@ namespace data
|
||||||
ek.GenerateKeys (); // esk and epk
|
ek.GenerateKeys (); // esk and epk
|
||||||
memcpy (authData, ek.GetPublicKey (), 32); authData += 32; // epk
|
memcpy (authData, ek.GetPublicKey (), 32); authData += 32; // epk
|
||||||
htobe16buf (authData, authKeys->size ()); authData += 2; // num clients
|
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);
|
memcpy (authInput + 64, subcredential, 36);
|
||||||
for (auto& it: *authKeys)
|
for (auto& it: *authKeys)
|
||||||
{
|
{
|
||||||
|
|
|
@ -128,8 +128,8 @@ namespace data
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
validate lease set buffer signature and extract expiration timestamp
|
* validate lease set buffer signature and extract expiration timestamp
|
||||||
@returns true if the leaseset is well formed and signature is valid
|
* @returns true if the leaseset is well formed and signature is valid
|
||||||
*/
|
*/
|
||||||
bool LeaseSetBufferValidate(const uint8_t * ptr, size_t sz, uint64_t & expires);
|
bool LeaseSetBufferValidate(const uint8_t * ptr, size_t sz, uint64_t & expires);
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ namespace log {
|
||||||
|
|
||||||
#ifndef _WIN32
|
#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
|
* @return syslog priority LOG_*, as defined in syslog.h
|
||||||
*/
|
*/
|
||||||
static inline int GetSyslogPrio (enum LogLevel l) {
|
static inline int GetSyslogPrio (enum LogLevel l) {
|
||||||
|
@ -113,11 +113,11 @@ namespace log {
|
||||||
|
|
||||||
std::string str_tolower(std::string s) {
|
std::string str_tolower(std::string s) {
|
||||||
std::transform(s.begin(), s.end(), s.begin(),
|
std::transform(s.begin(), s.end(), s.begin(),
|
||||||
// static_cast<int(*)(int)>(std::tolower) // wrong
|
// static_cast<int(*)(int)>(std::tolower) // wrong
|
||||||
// [](int c){ return std::tolower(c); } // wrong
|
// [](int c){ return std::tolower(c); } // wrong
|
||||||
// [](char c){ return std::tolower(c); } // wrong
|
// [](char c){ return std::tolower(c); } // wrong
|
||||||
[](unsigned char c){ return std::tolower(c); } // correct
|
[](unsigned char c){ return std::tolower(c); } // correct
|
||||||
);
|
);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,10 +129,10 @@ namespace log {
|
||||||
else if (level == "info") { m_MinLevel = eLogInfo; }
|
else if (level == "info") { m_MinLevel = eLogInfo; }
|
||||||
else if (level == "debug") { m_MinLevel = eLogDebug; }
|
else if (level == "debug") { m_MinLevel = eLogDebug; }
|
||||||
else {
|
else {
|
||||||
LogPrint(eLogError, "Log: unknown loglevel: ", level);
|
LogPrint(eLogError, "Log: Unknown loglevel: ", level);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LogPrint(eLogInfo, "Log: min messages level set to ", level);
|
LogPrint(eLogInfo, "Log: Logging level set to ", level);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * Log::TimeAsString(std::time_t t) {
|
const char * Log::TimeAsString(std::time_t t) {
|
||||||
|
@ -170,7 +170,7 @@ namespace log {
|
||||||
break;
|
break;
|
||||||
case eLogStdout:
|
case eLogStdout:
|
||||||
default:
|
default:
|
||||||
std::cout << TimeAsString(msg->timestamp)
|
std::cout << TimeAsString(msg->timestamp)
|
||||||
<< "@" << short_tid
|
<< "@" << short_tid
|
||||||
<< "/" << LogMsgColors[msg->level] << g_LogLevelStr[msg->level] << LogMsgColors[eNumLogLevels]
|
<< "/" << LogMsgColors[msg->level] << g_LogLevelStr[msg->level] << LogMsgColors[eNumLogLevels]
|
||||||
<< " - " << msg->text << std::endl;
|
<< " - " << msg->text << std::endl;
|
||||||
|
@ -212,7 +212,7 @@ namespace log {
|
||||||
m_LogStream = os;
|
m_LogStream = os;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LogPrint(eLogError, "Log: can't open file ", path);
|
LogPrint(eLogError, "Log: Can't open file ", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::SendTo (std::shared_ptr<std::ostream> os) {
|
void Log::SendTo (std::shared_ptr<std::ostream> os) {
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace log {
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum LogType m_Destination;
|
enum LogType m_Destination;
|
||||||
enum LogLevel m_MinLevel;
|
enum LogLevel m_MinLevel;
|
||||||
std::shared_ptr<std::ostream> m_LogStream;
|
std::shared_ptr<std::ostream> m_LogStream;
|
||||||
std::string m_Logfile;
|
std::string m_Logfile;
|
||||||
|
@ -75,7 +75,7 @@ namespace log {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Makes formatted string from unix timestamp
|
* @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
|
* This function internally caches the result for last provided value
|
||||||
*/
|
*/
|
||||||
|
@ -86,52 +86,52 @@ namespace log {
|
||||||
Log ();
|
Log ();
|
||||||
~Log ();
|
~Log ();
|
||||||
|
|
||||||
LogType GetLogType () { return m_Destination; };
|
LogType GetLogType () { return m_Destination; };
|
||||||
LogLevel GetLogLevel () { return m_MinLevel; };
|
LogLevel GetLogLevel () { return m_MinLevel; };
|
||||||
|
|
||||||
void Start ();
|
void Start ();
|
||||||
void Stop ();
|
void Stop ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets minimal allowed level for log messages
|
* @brief Sets minimal allowed level for log messages
|
||||||
* @param level String with wanted minimal msg level
|
* @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
|
* @brief Sets log destination to logfile
|
||||||
* @param path Path to logfile
|
* @param path Path to logfile
|
||||||
*/
|
*/
|
||||||
void SendTo (const std::string &path);
|
void SendTo (const std::string &path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets log destination to given output stream
|
* @brief Sets log destination to given output stream
|
||||||
* @param os Output stream
|
* @param os Output stream
|
||||||
*/
|
*/
|
||||||
void SendTo (std::shared_ptr<std::ostream> os);
|
void SendTo (std::shared_ptr<std::ostream> os);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets format for timestamps in log
|
* @brief Sets format for timestamps in log
|
||||||
* @param format String with timestamp format
|
* @param format String with timestamp format
|
||||||
*/
|
*/
|
||||||
void SetTimeFormat (std::string format) { m_TimeFormat = format; };
|
void SetTimeFormat (std::string format) { m_TimeFormat = format; };
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
/**
|
/**
|
||||||
* @brief Sets log destination to syslog
|
* @brief Sets log destination to syslog
|
||||||
* @param name Wanted program name
|
* @param name Wanted program name
|
||||||
* @param facility Wanted log category
|
* @param facility Wanted log category
|
||||||
*/
|
*/
|
||||||
void SendTo (const char *name, int facility);
|
void SendTo (const char *name, int facility);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Format log message and write to output stream/syslog
|
* @brief Format log message and write to output stream/syslog
|
||||||
* @param msg Pointer to processed message
|
* @param msg Pointer to processed message
|
||||||
*/
|
*/
|
||||||
void Append(std::shared_ptr<i2p::log::LogMsg> &);
|
void Append(std::shared_ptr<i2p::log::LogMsg> &);
|
||||||
|
|
||||||
/** @brief Reopen log file */
|
/** @brief Reopen log file */
|
||||||
void Reopen();
|
void Reopen();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -144,8 +144,8 @@ namespace log {
|
||||||
*/
|
*/
|
||||||
struct LogMsg {
|
struct LogMsg {
|
||||||
std::time_t timestamp;
|
std::time_t timestamp;
|
||||||
std::string text; /**< message text as single string */
|
std::string text; /**< message text as single string */
|
||||||
LogLevel level; /**< message level */
|
LogLevel level; /**< message level */
|
||||||
std::thread::id tid; /**< id of thread that generated message */
|
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) {}
|
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();
|
Log & Logger();
|
||||||
|
|
||||||
typedef std::function<void (const std::string&)> ThrowFunction;
|
typedef std::function<void (const std::string&)> ThrowFunction;
|
||||||
ThrowFunction GetThrowFunction ();
|
ThrowFunction GetThrowFunction ();
|
||||||
void SetThrowFunction (ThrowFunction f);
|
void SetThrowFunction (ThrowFunction f);
|
||||||
} // log
|
} // log
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
#include "HTTP.h"
|
#include "HTTP.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
#ifdef __linux__
|
#if defined(__linux__) && !defined(_NETINET_IN_H)
|
||||||
#include <linux/in6.h>
|
#include <linux/in6.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -59,14 +59,14 @@ namespace transport
|
||||||
|
|
||||||
void NTCP2Establisher::KDF1Bob ()
|
void NTCP2Establisher::KDF1Bob ()
|
||||||
{
|
{
|
||||||
KeyDerivationFunction1 (GetRemotePub (), i2p::context.GetStaticKeys (), i2p::context.GetNTCP2StaticPublicKey (), GetRemotePub ());
|
KeyDerivationFunction1 (GetRemotePub (), i2p::context.GetNTCP2StaticKeys (), i2p::context.GetNTCP2StaticPublicKey (), GetRemotePub ());
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTCP2Establisher::KeyDerivationFunction2 (const uint8_t * sessionRequest, size_t sessionRequestLen, const uint8_t * epub)
|
void NTCP2Establisher::KeyDerivationFunction2 (const uint8_t * sessionRequest, size_t sessionRequestLen, const uint8_t * epub)
|
||||||
{
|
{
|
||||||
MixHash (sessionRequest + 32, 32); // encrypted payload
|
MixHash (sessionRequest + 32, 32); // encrypted payload
|
||||||
|
|
||||||
int paddingLength = sessionRequestLen - 64;
|
int paddingLength = sessionRequestLen - 64;
|
||||||
if (paddingLength > 0)
|
if (paddingLength > 0)
|
||||||
MixHash (sessionRequest + 64, paddingLength);
|
MixHash (sessionRequest + 64, paddingLength);
|
||||||
MixHash (epub, 32);
|
MixHash (epub, 32);
|
||||||
|
@ -91,7 +91,7 @@ namespace transport
|
||||||
void NTCP2Establisher::KDF3Alice ()
|
void NTCP2Establisher::KDF3Alice ()
|
||||||
{
|
{
|
||||||
uint8_t inputKeyMaterial[32];
|
uint8_t inputKeyMaterial[32];
|
||||||
i2p::context.GetStaticKeys ().Agree (GetRemotePub (), inputKeyMaterial);
|
i2p::context.GetNTCP2StaticKeys ().Agree (GetRemotePub (), inputKeyMaterial);
|
||||||
MixKey (inputKeyMaterial);
|
MixKey (inputKeyMaterial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ namespace transport
|
||||||
// m3p2Len
|
// m3p2Len
|
||||||
auto bufLen = i2p::context.GetRouterInfo ().GetBufferLen ();
|
auto bufLen = i2p::context.GetRouterInfo ().GetBufferLen ();
|
||||||
m3p2Len = bufLen + 4 + 16; // (RI header + RI + MAC for now) TODO: implement options
|
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)
|
// fill m3p2 payload (RouterInfo block)
|
||||||
m_SessionConfirmedBuffer = new uint8_t[m3p2Len + 48]; // m3p1 is 48 bytes
|
m_SessionConfirmedBuffer = new uint8_t[m3p2Len + 48]; // m3p1 is 48 bytes
|
||||||
uint8_t * m3p2 = m_SessionConfirmedBuffer + 48;
|
uint8_t * m3p2 = m_SessionConfirmedBuffer + 48;
|
||||||
|
@ -195,8 +195,9 @@ namespace transport
|
||||||
MixHash (m3p2, m3p2Len); //h = SHA256(h || ciphertext)
|
MixHash (m3p2, m3p2Len); //h = SHA256(h || ciphertext)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NTCP2Establisher::ProcessSessionRequestMessage (uint16_t& paddingLen)
|
bool NTCP2Establisher::ProcessSessionRequestMessage (uint16_t& paddingLen, bool& clockSkew)
|
||||||
{
|
{
|
||||||
|
clockSkew = false;
|
||||||
// decrypt X
|
// decrypt X
|
||||||
i2p::crypto::CBCDecryption decryption;
|
i2p::crypto::CBCDecryption decryption;
|
||||||
decryption.SetKey (i2p::context.GetIdentHash ());
|
decryption.SetKey (i2p::context.GetIdentHash ());
|
||||||
|
@ -232,7 +233,8 @@ namespace transport
|
||||||
if (tsA < ts - NTCP2_CLOCK_SKEW || tsA > ts + NTCP2_CLOCK_SKEW)
|
if (tsA < ts - NTCP2_CLOCK_SKEW || tsA > ts + NTCP2_CLOCK_SKEW)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "NTCP2: SessionRequest time difference ", (int)(ts - tsA), " exceeds clock skew");
|
LogPrint (eLogWarning, "NTCP2: SessionRequest time difference ", (int)(ts - tsA), " exceeds clock skew");
|
||||||
return false;
|
clockSkew = true;
|
||||||
|
// we send SessionCreate to let Alice know our time and then close session
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -318,14 +320,15 @@ namespace transport
|
||||||
}
|
}
|
||||||
|
|
||||||
NTCP2Session::NTCP2Session (NTCP2Server& server, std::shared_ptr<const i2p::data::RouterInfo> in_RemoteRouter,
|
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),
|
TransportSession (in_RemoteRouter, NTCP2_ESTABLISH_TIMEOUT),
|
||||||
m_Server (server), m_Socket (m_Server.GetService ()),
|
m_Server (server), m_Socket (m_Server.GetService ()),
|
||||||
m_IsEstablished (false), m_IsTerminated (false),
|
m_IsEstablished (false), m_IsTerminated (false),
|
||||||
m_Establisher (new NTCP2Establisher),
|
m_Establisher (new NTCP2Establisher),
|
||||||
m_SendSipKey (nullptr), m_ReceiveSipKey (nullptr),
|
|
||||||
#if OPENSSL_SIPHASH
|
#if OPENSSL_SIPHASH
|
||||||
m_SendMDCtx(nullptr), m_ReceiveMDCtx (nullptr),
|
m_SendMDCtx(nullptr), m_ReceiveMDCtx (nullptr),
|
||||||
|
#else
|
||||||
|
m_SendSipKey (nullptr), m_ReceiveSipKey (nullptr),
|
||||||
#endif
|
#endif
|
||||||
m_NextReceivedLen (0), m_NextReceivedBuffer (nullptr), m_NextSendBuffer (nullptr),
|
m_NextReceivedLen (0), m_NextReceivedBuffer (nullptr), m_NextSendBuffer (nullptr),
|
||||||
m_NextReceivedBufferSize (0), m_ReceiveSequenceNumber (0), m_SendSequenceNumber (0),
|
m_NextReceivedBufferSize (0), m_ReceiveSequenceNumber (0), m_SendSequenceNumber (0),
|
||||||
|
@ -336,8 +339,8 @@ namespace transport
|
||||||
m_Establisher->m_RemoteIdentHash = GetRemoteIdentity ()->GetIdentHash ();
|
m_Establisher->m_RemoteIdentHash = GetRemoteIdentity ()->GetIdentHash ();
|
||||||
if (addr)
|
if (addr)
|
||||||
{
|
{
|
||||||
memcpy (m_Establisher->m_RemoteStaticKey, addr->ntcp2->staticKey, 32);
|
memcpy (m_Establisher->m_RemoteStaticKey, addr->s, 32);
|
||||||
memcpy (m_Establisher->m_IV, addr->ntcp2->iv, 16);
|
memcpy (m_Establisher->m_IV, addr->i, 16);
|
||||||
m_RemoteEndpoint = boost::asio::ip::tcp::endpoint (addr->host, addr->port);
|
m_RemoteEndpoint = boost::asio::ip::tcp::endpoint (addr->host, addr->port);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -352,8 +355,6 @@ namespace transport
|
||||||
delete[] m_NextReceivedBuffer;
|
delete[] m_NextReceivedBuffer;
|
||||||
delete[] m_NextSendBuffer;
|
delete[] m_NextSendBuffer;
|
||||||
#if OPENSSL_SIPHASH
|
#if OPENSSL_SIPHASH
|
||||||
if (m_SendSipKey) EVP_PKEY_free (m_SendSipKey);
|
|
||||||
if (m_ReceiveSipKey) EVP_PKEY_free (m_ReceiveSipKey);
|
|
||||||
if (m_SendMDCtx) EVP_MD_CTX_destroy (m_SendMDCtx);
|
if (m_SendMDCtx) EVP_MD_CTX_destroy (m_SendMDCtx);
|
||||||
if (m_ReceiveMDCtx) EVP_MD_CTX_destroy (m_ReceiveMDCtx);
|
if (m_ReceiveMDCtx) EVP_MD_CTX_destroy (m_ReceiveMDCtx);
|
||||||
#endif
|
#endif
|
||||||
|
@ -373,7 +374,7 @@ namespace transport
|
||||||
transports.PeerDisconnected (shared_from_this ());
|
transports.PeerDisconnected (shared_from_this ());
|
||||||
m_Server.RemoveNTCP2Session (shared_from_this ());
|
m_Server.RemoveNTCP2Session (shared_from_this ());
|
||||||
m_SendQueue.clear ();
|
m_SendQueue.clear ();
|
||||||
LogPrint (eLogDebug, "NTCP2: session terminated");
|
LogPrint (eLogDebug, "NTCP2: Session terminated");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,7 +418,7 @@ namespace transport
|
||||||
void NTCP2Session::DeleteNextReceiveBuffer (uint64_t ts)
|
void NTCP2Session::DeleteNextReceiveBuffer (uint64_t ts)
|
||||||
{
|
{
|
||||||
if (m_NextReceivedBuffer && !m_IsReceiving &&
|
if (m_NextReceivedBuffer && !m_IsReceiving &&
|
||||||
ts > m_LastActivityTimestamp + NTCP2_RECEIVE_BUFFER_DELETION_TIMEOUT)
|
ts > m_LastActivityTimestamp + NTCP2_RECEIVE_BUFFER_DELETION_TIMEOUT)
|
||||||
{
|
{
|
||||||
delete[] m_NextReceivedBuffer;
|
delete[] m_NextReceivedBuffer;
|
||||||
m_NextReceivedBuffer = nullptr;
|
m_NextReceivedBuffer = nullptr;
|
||||||
|
@ -454,7 +455,7 @@ namespace transport
|
||||||
(void) bytes_transferred;
|
(void) bytes_transferred;
|
||||||
if (ecode)
|
if (ecode)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "NTCP2: couldn't send SessionRequest message: ", ecode.message ());
|
LogPrint (eLogWarning, "NTCP2: Couldn't send SessionRequest message: ", ecode.message ());
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -477,9 +478,16 @@ namespace transport
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "NTCP2: SessionRequest received ", bytes_transferred);
|
LogPrint (eLogDebug, "NTCP2: SessionRequest received ", bytes_transferred);
|
||||||
uint16_t paddingLen = 0;
|
uint16_t paddingLen = 0;
|
||||||
if (m_Establisher->ProcessSessionRequestMessage (paddingLen))
|
bool clockSkew = false;
|
||||||
|
if (m_Establisher->ProcessSessionRequestMessage (paddingLen, clockSkew))
|
||||||
{
|
{
|
||||||
if (paddingLen > 0)
|
if (clockSkew)
|
||||||
|
{
|
||||||
|
// we don't care about padding, send SessionCreated and close session
|
||||||
|
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
|
if (paddingLen <= NTCP2_SESSION_REQUEST_MAX_SIZE - 64) // session request is 287 bytes max
|
||||||
{
|
{
|
||||||
|
@ -488,7 +496,7 @@ namespace transport
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "NTCP2: SessionRequest padding length ", (int)paddingLen, " is too long");
|
LogPrint (eLogWarning, "NTCP2: SessionRequest padding length ", (int)paddingLen, " is too long");
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -541,7 +549,7 @@ namespace transport
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "NTCP2: SessionCreated padding length ", (int)paddingLen, " is too long");
|
LogPrint (eLogWarning, "NTCP2: SessionCreated padding length ", (int)paddingLen, " is too long");
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -584,7 +592,7 @@ namespace transport
|
||||||
(void) bytes_transferred;
|
(void) bytes_transferred;
|
||||||
if (ecode)
|
if (ecode)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "NTCP2: couldn't send SessionConfirmed message: ", ecode.message ());
|
LogPrint (eLogWarning, "NTCP2: Couldn't send SessionConfirmed message: ", ecode.message ());
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -611,7 +619,7 @@ namespace transport
|
||||||
(void) bytes_transferred;
|
(void) bytes_transferred;
|
||||||
if (ecode)
|
if (ecode)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "NTCP2: couldn't send SessionCreated message: ", ecode.message ());
|
LogPrint (eLogWarning, "NTCP2: Couldn't send SessionCreated message: ", ecode.message ());
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -654,7 +662,7 @@ namespace transport
|
||||||
// process RI
|
// process RI
|
||||||
if (buf[0] != eNTCP2BlkRouterInfo)
|
if (buf[0] != eNTCP2BlkRouterInfo)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "NTCP2: unexpected block ", (int)buf[0], " in SessionConfirmed");
|
LogPrint (eLogWarning, "NTCP2: Unexpected block ", (int)buf[0], " in SessionConfirmed");
|
||||||
Terminate ();
|
Terminate ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -682,7 +690,7 @@ namespace transport
|
||||||
auto addr = ri.GetNTCP2AddressWithStaticKey (m_Establisher->m_RemoteStaticKey);
|
auto addr = ri.GetNTCP2AddressWithStaticKey (m_Establisher->m_RemoteStaticKey);
|
||||||
if (!addr)
|
if (!addr)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "NTCP2: No NTCP2 address wth static key found in SessionConfirmed");
|
LogPrint (eLogError, "NTCP2: No NTCP2 address with static key found in SessionConfirmed");
|
||||||
Terminate ();
|
Terminate ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -711,17 +719,19 @@ namespace transport
|
||||||
void NTCP2Session::SetSipKeys (const uint8_t * sendSipKey, const uint8_t * receiveSipKey)
|
void NTCP2Session::SetSipKeys (const uint8_t * sendSipKey, const uint8_t * receiveSipKey)
|
||||||
{
|
{
|
||||||
#if OPENSSL_SIPHASH
|
#if OPENSSL_SIPHASH
|
||||||
m_SendSipKey = EVP_PKEY_new_raw_private_key (EVP_PKEY_SIPHASH, nullptr, sendSipKey, 16);
|
EVP_PKEY * sipKey = EVP_PKEY_new_raw_private_key (EVP_PKEY_SIPHASH, nullptr, sendSipKey, 16);
|
||||||
m_SendMDCtx = EVP_MD_CTX_create ();
|
m_SendMDCtx = EVP_MD_CTX_create ();
|
||||||
EVP_PKEY_CTX *ctx = nullptr;
|
EVP_PKEY_CTX *ctx = nullptr;
|
||||||
EVP_DigestSignInit (m_SendMDCtx, &ctx, nullptr, nullptr, m_SendSipKey);
|
EVP_DigestSignInit (m_SendMDCtx, &ctx, nullptr, nullptr, sipKey);
|
||||||
EVP_PKEY_CTX_ctrl (ctx, -1, EVP_PKEY_OP_SIGNCTX, EVP_PKEY_CTRL_SET_DIGEST_SIZE, 8, nullptr);
|
EVP_PKEY_CTX_ctrl (ctx, -1, EVP_PKEY_OP_SIGNCTX, EVP_PKEY_CTRL_SET_DIGEST_SIZE, 8, nullptr);
|
||||||
|
EVP_PKEY_free (sipKey);
|
||||||
|
|
||||||
m_ReceiveSipKey = EVP_PKEY_new_raw_private_key (EVP_PKEY_SIPHASH, nullptr, receiveSipKey, 16);
|
sipKey = EVP_PKEY_new_raw_private_key (EVP_PKEY_SIPHASH, nullptr, receiveSipKey, 16);
|
||||||
m_ReceiveMDCtx = EVP_MD_CTX_create ();
|
m_ReceiveMDCtx = EVP_MD_CTX_create ();
|
||||||
ctx = nullptr;
|
ctx = nullptr;
|
||||||
EVP_DigestSignInit (m_ReceiveMDCtx, &ctx, NULL, NULL, m_ReceiveSipKey);
|
EVP_DigestSignInit (m_ReceiveMDCtx, &ctx, NULL, NULL, sipKey);
|
||||||
EVP_PKEY_CTX_ctrl (ctx, -1, EVP_PKEY_OP_SIGNCTX, EVP_PKEY_CTRL_SET_DIGEST_SIZE, 8, nullptr);
|
EVP_PKEY_CTX_ctrl (ctx, -1, EVP_PKEY_OP_SIGNCTX, EVP_PKEY_CTRL_SET_DIGEST_SIZE, 8, nullptr);
|
||||||
|
EVP_PKEY_free (sipKey);
|
||||||
#else
|
#else
|
||||||
m_SendSipKey = sendSipKey;
|
m_SendSipKey = sendSipKey;
|
||||||
m_ReceiveSipKey = receiveSipKey;
|
m_ReceiveSipKey = receiveSipKey;
|
||||||
|
@ -747,7 +757,7 @@ namespace transport
|
||||||
if (IsTerminated ()) return;
|
if (IsTerminated ()) return;
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
const int one = 1;
|
const int one = 1;
|
||||||
setsockopt(m_Socket.native_handle(), IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
|
setsockopt(m_Socket.native_handle(), IPPROTO_TCP, TCP_QUICKACK, &one, sizeof(one));
|
||||||
#endif
|
#endif
|
||||||
boost::asio::async_read (m_Socket, boost::asio::buffer(&m_NextReceivedLen, 2), boost::asio::transfer_all (),
|
boost::asio::async_read (m_Socket, boost::asio::buffer(&m_NextReceivedLen, 2), boost::asio::transfer_all (),
|
||||||
std::bind(&NTCP2Session::HandleReceivedLength, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
|
std::bind(&NTCP2Session::HandleReceivedLength, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
|
||||||
|
@ -758,7 +768,7 @@ namespace transport
|
||||||
if (ecode)
|
if (ecode)
|
||||||
{
|
{
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
LogPrint (eLogWarning, "NTCP2: receive length read error: ", ecode.message ());
|
LogPrint (eLogWarning, "NTCP2: Receive length read error: ", ecode.message ());
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -773,7 +783,7 @@ namespace transport
|
||||||
#endif
|
#endif
|
||||||
// m_NextReceivedLen comes from the network in BigEndian
|
// m_NextReceivedLen comes from the network in BigEndian
|
||||||
m_NextReceivedLen = be16toh (m_NextReceivedLen) ^ le16toh (m_ReceiveIV.key);
|
m_NextReceivedLen = be16toh (m_NextReceivedLen) ^ le16toh (m_ReceiveIV.key);
|
||||||
LogPrint (eLogDebug, "NTCP2: received length ", m_NextReceivedLen);
|
LogPrint (eLogDebug, "NTCP2: Received length ", m_NextReceivedLen);
|
||||||
if (m_NextReceivedLen >= 16)
|
if (m_NextReceivedLen >= 16)
|
||||||
{
|
{
|
||||||
CreateNextReceivedBuffer (m_NextReceivedLen);
|
CreateNextReceivedBuffer (m_NextReceivedLen);
|
||||||
|
@ -790,7 +800,7 @@ namespace transport
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "NTCP2: received length ", m_NextReceivedLen, " is too short");
|
LogPrint (eLogError, "NTCP2: Received length ", m_NextReceivedLen, " is too short");
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -813,7 +823,7 @@ namespace transport
|
||||||
if (ecode)
|
if (ecode)
|
||||||
{
|
{
|
||||||
if (ecode != boost::asio::error::operation_aborted)
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
LogPrint (eLogWarning, "NTCP2: receive read error: ", ecode.message ());
|
LogPrint (eLogWarning, "NTCP2: Receive read error: ", ecode.message ());
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -825,7 +835,7 @@ namespace transport
|
||||||
CreateNonce (m_ReceiveSequenceNumber, nonce); m_ReceiveSequenceNumber++;
|
CreateNonce (m_ReceiveSequenceNumber, nonce); m_ReceiveSequenceNumber++;
|
||||||
if (i2p::crypto::AEADChaCha20Poly1305 (m_NextReceivedBuffer, m_NextReceivedLen-16, nullptr, 0, m_ReceiveKey, nonce, m_NextReceivedBuffer, m_NextReceivedLen, false))
|
if (i2p::crypto::AEADChaCha20Poly1305 (m_NextReceivedBuffer, m_NextReceivedLen-16, nullptr, 0, m_ReceiveKey, nonce, m_NextReceivedBuffer, m_NextReceivedLen, false))
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "NTCP2: received message decrypted");
|
LogPrint (eLogDebug, "NTCP2: Received message decrypted");
|
||||||
ProcessNextFrame (m_NextReceivedBuffer, m_NextReceivedLen-16);
|
ProcessNextFrame (m_NextReceivedBuffer, m_NextReceivedLen-16);
|
||||||
m_IsReceiving = false;
|
m_IsReceiving = false;
|
||||||
ReceiveLength ();
|
ReceiveLength ();
|
||||||
|
@ -856,10 +866,10 @@ namespace transport
|
||||||
switch (blk)
|
switch (blk)
|
||||||
{
|
{
|
||||||
case eNTCP2BlkDateTime:
|
case eNTCP2BlkDateTime:
|
||||||
LogPrint (eLogDebug, "NTCP2: datetime");
|
LogPrint (eLogDebug, "NTCP2: Datetime");
|
||||||
break;
|
break;
|
||||||
case eNTCP2BlkOptions:
|
case eNTCP2BlkOptions:
|
||||||
LogPrint (eLogDebug, "NTCP2: options");
|
LogPrint (eLogDebug, "NTCP2: Options");
|
||||||
break;
|
break;
|
||||||
case eNTCP2BlkRouterInfo:
|
case eNTCP2BlkRouterInfo:
|
||||||
{
|
{
|
||||||
|
@ -875,25 +885,29 @@ namespace transport
|
||||||
LogPrint (eLogError, "NTCP2: I2NP block is too long ", size);
|
LogPrint (eLogError, "NTCP2: I2NP block is too long ", size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
auto nextMsg = NewI2NPMessage (size);
|
auto nextMsg = (frame[offset] == eI2NPTunnelData) ? NewI2NPTunnelMessage (true) : NewI2NPMessage (size);
|
||||||
nextMsg->Align (12); // for possible tunnel msg
|
|
||||||
nextMsg->len = nextMsg->offset + size + 7; // 7 more bytes for full I2NP header
|
nextMsg->len = nextMsg->offset + size + 7; // 7 more bytes for full I2NP header
|
||||||
memcpy (nextMsg->GetNTCP2Header (), frame + offset, size);
|
if (nextMsg->len <= nextMsg->maxLen)
|
||||||
nextMsg->FromNTCP2 ();
|
{
|
||||||
m_Handler.PutNextMessage (nextMsg);
|
memcpy (nextMsg->GetNTCP2Header (), frame + offset, size);
|
||||||
|
nextMsg->FromNTCP2 ();
|
||||||
|
m_Handler.PutNextMessage (std::move (nextMsg));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogError, "NTCP2: I2NP block is too long for I2NP message");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case eNTCP2BlkTermination:
|
case eNTCP2BlkTermination:
|
||||||
if (size >= 9)
|
if (size >= 9)
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "NTCP2: termination. reason=", (int)(frame[offset + 8]));
|
LogPrint (eLogDebug, "NTCP2: Termination. reason=", (int)(frame[offset + 8]));
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogWarning, "NTCP2: Unexpected termination block size ", size);
|
LogPrint (eLogWarning, "NTCP2: Unexpected termination block size ", size);
|
||||||
break;
|
break;
|
||||||
case eNTCP2BlkPadding:
|
case eNTCP2BlkPadding:
|
||||||
LogPrint (eLogDebug, "NTCP2: padding");
|
LogPrint (eLogDebug, "NTCP2: Padding");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LogPrint (eLogWarning, "NTCP2: Unknown block type ", (int)blk);
|
LogPrint (eLogWarning, "NTCP2: Unknown block type ", (int)blk);
|
||||||
|
@ -905,7 +919,7 @@ namespace transport
|
||||||
|
|
||||||
void NTCP2Session::SetNextSentFrameLength (size_t frameLen, uint8_t * lengthBuf)
|
void NTCP2Session::SetNextSentFrameLength (size_t frameLen, uint8_t * lengthBuf)
|
||||||
{
|
{
|
||||||
#if OPENSSL_SIPHASH
|
#if OPENSSL_SIPHASH
|
||||||
EVP_DigestSignInit (m_SendMDCtx, nullptr, nullptr, nullptr, nullptr);
|
EVP_DigestSignInit (m_SendMDCtx, nullptr, nullptr, nullptr, nullptr);
|
||||||
EVP_DigestSignUpdate (m_SendMDCtx, m_SendIV.buf, 8);
|
EVP_DigestSignUpdate (m_SendMDCtx, m_SendIV.buf, 8);
|
||||||
size_t l = 8;
|
size_t l = 8;
|
||||||
|
@ -915,7 +929,7 @@ namespace transport
|
||||||
#endif
|
#endif
|
||||||
// length must be in BigEndian
|
// length must be in BigEndian
|
||||||
htobe16buf (lengthBuf, frameLen ^ le16toh (m_SendIV.key));
|
htobe16buf (lengthBuf, frameLen ^ le16toh (m_SendIV.key));
|
||||||
LogPrint (eLogDebug, "NTCP2: sent length ", frameLen);
|
LogPrint (eLogDebug, "NTCP2: Sent length ", frameLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTCP2Session::SendI2NPMsgs (std::vector<std::shared_ptr<I2NPMessage> >& msgs)
|
void NTCP2Session::SendI2NPMsgs (std::vector<std::shared_ptr<I2NPMessage> >& msgs)
|
||||||
|
@ -968,7 +982,7 @@ namespace transport
|
||||||
{
|
{
|
||||||
// allocate send buffer
|
// allocate send buffer
|
||||||
m_NextSendBuffer = new uint8_t[287]; // can be any size > 16, we just allocate 287 frequently
|
m_NextSendBuffer = new uint8_t[287]; // can be any size > 16, we just allocate 287 frequently
|
||||||
// crate padding block
|
// create padding block
|
||||||
auto paddingLen = CreatePaddingBlock (totalLen, m_NextSendBuffer, 287 - 16);
|
auto paddingLen = CreatePaddingBlock (totalLen, m_NextSendBuffer, 287 - 16);
|
||||||
// and padding block to encrypt and send
|
// and padding block to encrypt and send
|
||||||
if (paddingLen)
|
if (paddingLen)
|
||||||
|
@ -1110,7 +1124,13 @@ namespace transport
|
||||||
|
|
||||||
void NTCP2Session::SendTermination (NTCP2TerminationReason reason)
|
void NTCP2Session::SendTermination (NTCP2TerminationReason reason)
|
||||||
{
|
{
|
||||||
if (!m_SendKey || !m_SendSipKey) return;
|
if (!m_SendKey ||
|
||||||
|
#if OPENSSL_SIPHASH
|
||||||
|
!m_SendMDCtx
|
||||||
|
#else
|
||||||
|
!m_SendSipKey
|
||||||
|
#endif
|
||||||
|
) return;
|
||||||
m_NextSendBuffer = new uint8_t[49]; // 49 = 12 bytes message + 16 bytes MAC + 2 bytes size + up to 19 padding block
|
m_NextSendBuffer = new uint8_t[49]; // 49 = 12 bytes message + 16 bytes MAC + 2 bytes size + up to 19 padding block
|
||||||
// termination block
|
// termination block
|
||||||
m_NextSendBuffer[2] = eNTCP2BlkTermination;
|
m_NextSendBuffer[2] = eNTCP2BlkTermination;
|
||||||
|
@ -1143,21 +1163,21 @@ namespace transport
|
||||||
SendQueue ();
|
SendQueue ();
|
||||||
else if (m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE)
|
else if (m_SendQueue.size () > NTCP2_MAX_OUTGOING_QUEUE_SIZE)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "NTCP2: outgoing messages queue size to ",
|
LogPrint (eLogWarning, "NTCP2: Outgoing messages queue size to ",
|
||||||
GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE);
|
GetIdentHashBase64(), " exceeds ", NTCP2_MAX_OUTGOING_QUEUE_SIZE);
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTCP2Session::SendLocalRouterInfo ()
|
void NTCP2Session::SendLocalRouterInfo (bool update)
|
||||||
{
|
{
|
||||||
if (!IsOutgoing ()) // we send it in SessionConfirmed
|
if (update || !IsOutgoing ()) // we send it in SessionConfirmed for ougoing session
|
||||||
m_Server.GetService ().post (std::bind (&NTCP2Session::SendRouterInfo, shared_from_this ()));
|
m_Server.GetService ().post (std::bind (&NTCP2Session::SendRouterInfo, shared_from_this ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
NTCP2Server::NTCP2Server ():
|
NTCP2Server::NTCP2Server ():
|
||||||
RunnableServiceWithWork ("NTCP2"), m_TerminationTimer (GetService ()),
|
RunnableServiceWithWork ("NTCP2"), m_TerminationTimer (GetService ()),
|
||||||
m_ProxyType(eNoProxy), m_Resolver(GetService ())
|
m_ProxyType(eNoProxy), m_Resolver(GetService ())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1223,7 +1243,7 @@ namespace transport
|
||||||
m_NTCP2V6Acceptor->open (boost::asio::ip::tcp::v6());
|
m_NTCP2V6Acceptor->open (boost::asio::ip::tcp::v6());
|
||||||
m_NTCP2V6Acceptor->set_option (boost::asio::ip::v6_only (true));
|
m_NTCP2V6Acceptor->set_option (boost::asio::ip::v6_only (true));
|
||||||
m_NTCP2V6Acceptor->set_option (boost::asio::socket_base::reuse_address (true));
|
m_NTCP2V6Acceptor->set_option (boost::asio::socket_base::reuse_address (true));
|
||||||
#ifdef __linux__
|
#if defined(__linux__) && !defined(_NETINET_IN_H)
|
||||||
if (!m_Address6 && !m_YggdrasilAddress) // only if not binded to address
|
if (!m_Address6 && !m_YggdrasilAddress) // only if not binded to address
|
||||||
{
|
{
|
||||||
// Set preference to use public IPv6 address -- tested on linux, not works on windows, and not tested on others
|
// Set preference to use public IPv6 address -- tested on linux, not works on windows, and not tested on others
|
||||||
|
@ -1249,7 +1269,7 @@ namespace transport
|
||||||
}
|
}
|
||||||
catch ( std::exception & ex )
|
catch ( std::exception & ex )
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "NTCP2: failed to bind to v6 port ", address->port, ": ", ex.what());
|
LogPrint(eLogError, "NTCP2: Failed to bind to v6 port ", address->port, ": ", ex.what());
|
||||||
ThrowFatal ("Unable to start IPv6 NTCP2 transport at port ", address->port, ": ", ex.what ());
|
ThrowFatal ("Unable to start IPv6 NTCP2 transport at port ", address->port, ": ", ex.what ());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1290,7 +1310,7 @@ namespace transport
|
||||||
auto it = m_NTCP2Sessions.find (ident);
|
auto it = m_NTCP2Sessions.find (ident);
|
||||||
if (it != m_NTCP2Sessions.end ())
|
if (it != m_NTCP2Sessions.end ())
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "NTCP2: session to ", ident.ToBase64 (), " already exists");
|
LogPrint (eLogWarning, "NTCP2: Session to ", ident.ToBase64 (), " already exists");
|
||||||
if (incoming)
|
if (incoming)
|
||||||
// replace by new session
|
// replace by new session
|
||||||
it->second->Terminate ();
|
it->second->Terminate ();
|
||||||
|
@ -1359,7 +1379,7 @@ namespace transport
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
conn->GetSocket ().bind (*localAddress, ec);
|
conn->GetSocket ().bind (*localAddress, ec);
|
||||||
if (ec)
|
if (ec)
|
||||||
LogPrint (eLogError, "NTCP2: can't bind to ", localAddress->address ().to_string (), ": ", ec.message ());
|
LogPrint (eLogError, "NTCP2: Can't bind to ", localAddress->address ().to_string (), ": ", ec.message ());
|
||||||
}
|
}
|
||||||
conn->GetSocket ().async_connect (conn->GetRemoteEndpoint (), std::bind (&NTCP2Server::HandleConnect, this, std::placeholders::_1, conn, timer));
|
conn->GetSocket ().async_connect (conn->GetRemoteEndpoint (), std::bind (&NTCP2Server::HandleConnect, this, std::placeholders::_1, conn, timer));
|
||||||
}
|
}
|
||||||
|
@ -1528,7 +1548,7 @@ namespace transport
|
||||||
{
|
{
|
||||||
if (ecode)
|
if (ecode)
|
||||||
{
|
{
|
||||||
LogPrint(eLogWarning, "NTCP2: failed to connect to proxy ", ecode.message());
|
LogPrint(eLogWarning, "NTCP2: Failed to connect to proxy ", ecode.message());
|
||||||
timer->cancel();
|
timer->cancel();
|
||||||
conn->Terminate();
|
conn->Terminate();
|
||||||
return;
|
return;
|
||||||
|
@ -1545,7 +1565,7 @@ namespace transport
|
||||||
(void) transferred;
|
(void) transferred;
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
LogPrint(eLogWarning, "NTCP2: socks5 write error ", ec.message());
|
LogPrint(eLogWarning, "NTCP2: SOCKS5 write error ", ec.message());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
auto readbuff = std::make_shared<std::vector<uint8_t> >(2);
|
auto readbuff = std::make_shared<std::vector<uint8_t> >(2);
|
||||||
|
@ -1554,7 +1574,7 @@ namespace transport
|
||||||
{
|
{
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "NTCP2: socks5 read error ", ec.message());
|
LogPrint(eLogError, "NTCP2: SOCKS5 read error ", ec.message());
|
||||||
timer->cancel();
|
timer->cancel();
|
||||||
conn->Terminate();
|
conn->Terminate();
|
||||||
return;
|
return;
|
||||||
|
@ -1568,14 +1588,14 @@ namespace transport
|
||||||
}
|
}
|
||||||
else if ((*readbuff)[1] == 0xff)
|
else if ((*readbuff)[1] == 0xff)
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "NTCP2: socks5 proxy rejected authentication");
|
LogPrint(eLogError, "NTCP2: SOCKS5 proxy rejected authentication");
|
||||||
timer->cancel();
|
timer->cancel();
|
||||||
conn->Terminate();
|
conn->Terminate();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LogPrint(eLogError, "NTCP2:", (int)(*readbuff)[1]);
|
LogPrint(eLogError, "NTCP2:", (int)(*readbuff)[1]);
|
||||||
}
|
}
|
||||||
LogPrint(eLogError, "NTCP2: socks5 server gave invalid response");
|
LogPrint(eLogError, "NTCP2: SOCKS5 server gave invalid response");
|
||||||
timer->cancel();
|
timer->cancel();
|
||||||
conn->Terminate();
|
conn->Terminate();
|
||||||
});
|
});
|
||||||
|
@ -1603,7 +1623,7 @@ namespace transport
|
||||||
{
|
{
|
||||||
(void) transferred;
|
(void) transferred;
|
||||||
if(ec)
|
if(ec)
|
||||||
LogPrint(eLogError, "NTCP2: http proxy write error ", ec.message());
|
LogPrint(eLogError, "NTCP2: HTTP proxy write error ", ec.message());
|
||||||
});
|
});
|
||||||
|
|
||||||
boost::asio::streambuf * readbuff = new boost::asio::streambuf;
|
boost::asio::streambuf * readbuff = new boost::asio::streambuf;
|
||||||
|
@ -1612,7 +1632,7 @@ namespace transport
|
||||||
{
|
{
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "NTCP2: http proxy read error ", ec.message());
|
LogPrint(eLogError, "NTCP2: HTTP proxy read error ", ec.message());
|
||||||
timer->cancel();
|
timer->cancel();
|
||||||
conn->Terminate();
|
conn->Terminate();
|
||||||
}
|
}
|
||||||
|
@ -1630,10 +1650,10 @@ namespace transport
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint(eLogError, "NTCP2: http proxy rejected request ", res.code);
|
LogPrint(eLogError, "NTCP2: HTTP proxy rejected request ", res.code);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint(eLogError, "NTCP2: http proxy gave malformed response");
|
LogPrint(eLogError, "NTCP2: HTTP proxy gave malformed response");
|
||||||
timer->cancel();
|
timer->cancel();
|
||||||
conn->Terminate();
|
conn->Terminate();
|
||||||
delete readbuff;
|
delete readbuff;
|
||||||
|
@ -1642,7 +1662,7 @@ namespace transport
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
LogPrint(eLogError, "NTCP2: unknown proxy type, invalid state");
|
LogPrint(eLogError, "NTCP2: Unknown proxy type, invalid state");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1683,7 +1703,7 @@ namespace transport
|
||||||
{
|
{
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "NTCP2: failed to write handshake to socks proxy ", ec.message());
|
LogPrint(eLogError, "NTCP2: Failed to write handshake to socks proxy ", ec.message());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1693,7 +1713,7 @@ namespace transport
|
||||||
{
|
{
|
||||||
if(e)
|
if(e)
|
||||||
{
|
{
|
||||||
LogPrint(eLogError, "NTCP2: socks proxy read error ", e.message());
|
LogPrint(eLogError, "NTCP2: SOCKS proxy read error ", e.message());
|
||||||
}
|
}
|
||||||
else if(transferred == sz)
|
else if(transferred == sz)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -107,7 +107,7 @@ namespace transport
|
||||||
void CreateSessionConfirmedMessagePart1 (const uint8_t * nonce);
|
void CreateSessionConfirmedMessagePart1 (const uint8_t * nonce);
|
||||||
void CreateSessionConfirmedMessagePart2 (const uint8_t * nonce);
|
void CreateSessionConfirmedMessagePart2 (const uint8_t * nonce);
|
||||||
|
|
||||||
bool ProcessSessionRequestMessage (uint16_t& paddingLen);
|
bool ProcessSessionRequestMessage (uint16_t& paddingLen, bool& clockSkew);
|
||||||
bool ProcessSessionCreatedMessage (uint16_t& paddingLen);
|
bool ProcessSessionCreatedMessage (uint16_t& paddingLen);
|
||||||
bool ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce);
|
bool ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce);
|
||||||
bool ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf);
|
bool ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf);
|
||||||
|
@ -148,7 +148,7 @@ namespace transport
|
||||||
void ClientLogin (); // Alice
|
void ClientLogin (); // Alice
|
||||||
void ServerLogin (); // Bob
|
void ServerLogin (); // Bob
|
||||||
|
|
||||||
void SendLocalRouterInfo (); // after handshake
|
void SendLocalRouterInfo (bool update); // after handshake or by update
|
||||||
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
void SendI2NPMessages (const std::vector<std::shared_ptr<I2NPMessage> >& msgs);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -205,7 +205,6 @@ namespace transport
|
||||||
uint8_t m_Kab[32], m_Kba[32], m_Sipkeysab[32], m_Sipkeysba[32];
|
uint8_t m_Kab[32], m_Kba[32], m_Sipkeysab[32], m_Sipkeysba[32];
|
||||||
const uint8_t * m_SendKey, * m_ReceiveKey;
|
const uint8_t * m_SendKey, * m_ReceiveKey;
|
||||||
#if OPENSSL_SIPHASH
|
#if OPENSSL_SIPHASH
|
||||||
EVP_PKEY * m_SendSipKey, * m_ReceiveSipKey;
|
|
||||||
EVP_MD_CTX * m_SendMDCtx, * m_ReceiveMDCtx;
|
EVP_MD_CTX * m_SendMDCtx, * m_ReceiveMDCtx;
|
||||||
#else
|
#else
|
||||||
const uint8_t * m_SendSipKey, * m_ReceiveSipKey;
|
const uint8_t * m_SendSipKey, * m_ReceiveSipKey;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -66,8 +66,8 @@ namespace data
|
||||||
if (it != m_RouterInfos.end ())
|
if (it != m_RouterInfos.end ())
|
||||||
{
|
{
|
||||||
// remove own router
|
// remove own router
|
||||||
m_RouterInfos.erase (it);
|
|
||||||
m_Floodfills.remove (it->second);
|
m_Floodfills.remove (it->second);
|
||||||
|
m_RouterInfos.erase (it);
|
||||||
}
|
}
|
||||||
// insert own router
|
// insert own router
|
||||||
m_RouterInfos.emplace (i2p::context.GetIdentHash (), i2p::context.GetSharedRouterInfo ());
|
m_RouterInfos.emplace (i2p::context.GetIdentHash (), i2p::context.GetSharedRouterInfo ());
|
||||||
|
@ -107,7 +107,10 @@ namespace data
|
||||||
{
|
{
|
||||||
i2p::util::SetThreadName("NetDB");
|
i2p::util::SetThreadName("NetDB");
|
||||||
|
|
||||||
uint32_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0;
|
uint64_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0;
|
||||||
|
uint64_t lastProfilesCleanup = i2p::util::GetSecondsSinceEpoch ();
|
||||||
|
int16_t profilesCleanupVariance = 0;
|
||||||
|
|
||||||
while (m_IsRunning)
|
while (m_IsRunning)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -118,7 +121,7 @@ namespace data
|
||||||
int numMsgs = 0;
|
int numMsgs = 0;
|
||||||
while (msg)
|
while (msg)
|
||||||
{
|
{
|
||||||
LogPrint(eLogDebug, "NetDb: got request with type ", (int) msg->GetTypeID ());
|
LogPrint(eLogDebug, "NetDb: Got request with type ", (int) msg->GetTypeID ());
|
||||||
switch (msg->GetTypeID ())
|
switch (msg->GetTypeID ())
|
||||||
{
|
{
|
||||||
case eI2NPDatabaseStore:
|
case eI2NPDatabaseStore:
|
||||||
|
@ -138,7 +141,7 @@ namespace data
|
||||||
HandleNTCP2RouterInfoMsg (msg);
|
HandleNTCP2RouterInfoMsg (msg);
|
||||||
break;
|
break;
|
||||||
default: // WTF?
|
default: // WTF?
|
||||||
LogPrint (eLogError, "NetDb: unexpected message type ", (int) msg->GetTypeID ());
|
LogPrint (eLogError, "NetDb: Unexpected message type ", (int) msg->GetTypeID ());
|
||||||
//i2p::HandleI2NPMessage (msg);
|
//i2p::HandleI2NPMessage (msg);
|
||||||
}
|
}
|
||||||
if (numMsgs > 100) break;
|
if (numMsgs > 100) break;
|
||||||
|
@ -155,6 +158,7 @@ namespace data
|
||||||
m_Requests.ManageRequests ();
|
m_Requests.ManageRequests ();
|
||||||
lastManageRequest = ts;
|
lastManageRequest = ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ts - lastSave >= 60) // save routers, manage leasesets and validate subscriptions every minute
|
if (ts - lastSave >= 60) // save routers, manage leasesets and validate subscriptions every minute
|
||||||
{
|
{
|
||||||
if (lastSave)
|
if (lastSave)
|
||||||
|
@ -164,12 +168,20 @@ namespace data
|
||||||
}
|
}
|
||||||
lastSave = ts;
|
lastSave = ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT)
|
if (ts - lastDestinationCleanup >= i2p::garlic::INCOMING_TAGS_EXPIRATION_TIMEOUT)
|
||||||
{
|
{
|
||||||
i2p::context.CleanupDestination ();
|
i2p::context.CleanupDestination ();
|
||||||
lastDestinationCleanup = ts;
|
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
|
// publish
|
||||||
if (!m_HiddenMode && i2p::transport::transports.IsOnline ())
|
if (!m_HiddenMode && i2p::transport::transports.IsOnline ())
|
||||||
{
|
{
|
||||||
|
@ -195,6 +207,7 @@ namespace data
|
||||||
lastPublish = ts;
|
lastPublish = ts;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ts - lastExploratory >= 30) // exploratory every 30 seconds
|
if (ts - lastExploratory >= 30) // exploratory every 30 seconds
|
||||||
{
|
{
|
||||||
auto numRouters = m_RouterInfos.size ();
|
auto numRouters = m_RouterInfos.size ();
|
||||||
|
@ -216,7 +229,7 @@ namespace data
|
||||||
}
|
}
|
||||||
catch (std::exception& ex)
|
catch (std::exception& ex)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "NetDb: runtime exception: ", ex.what ());
|
LogPrint (eLogError, "NetDb: Runtime exception: ", ex.what ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,7 +356,7 @@ namespace data
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "NetDb: new LeaseSet validation failed: ", ident.ToBase32());
|
LogPrint (eLogError, "NetDb: New LeaseSet validation failed: ", ident.ToBase32());
|
||||||
}
|
}
|
||||||
return updated;
|
return updated;
|
||||||
}
|
}
|
||||||
|
@ -373,7 +386,7 @@ namespace data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "NetDb: new LeaseSet2 validation failed: ", ident.ToBase32());
|
LogPrint (eLogError, "NetDb: New LeaseSet2 validation failed: ", ident.ToBase32());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,7 +443,7 @@ namespace data
|
||||||
int riLen = ri->GetBufferLen();
|
int riLen = ri->GetBufferLen();
|
||||||
if(!i2p::data::netdb.AddRouterInfo(riData, riLen)) {
|
if(!i2p::data::netdb.AddRouterInfo(riData, riLen)) {
|
||||||
// bad router info
|
// bad router info
|
||||||
LogPrint(eLogError, "NetDb: bad router info");
|
LogPrint(eLogError, "NetDb: Bad router info");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_FloodfillBootstrap = ri;
|
m_FloodfillBootstrap = ri;
|
||||||
|
@ -445,7 +458,7 @@ namespace data
|
||||||
|
|
||||||
void NetDb::ReseedFromFloodfill(const RouterInfo & ri, int numRouters, int numFloodfills)
|
void NetDb::ReseedFromFloodfill(const RouterInfo & ri, int numRouters, int numFloodfills)
|
||||||
{
|
{
|
||||||
LogPrint(eLogInfo, "NetDB: reseeding from floodfill ", ri.GetIdentHashBase64());
|
LogPrint(eLogInfo, "NetDB: Reseeding from floodfill ", ri.GetIdentHashBase64());
|
||||||
std::vector<std::shared_ptr<i2p::I2NPMessage> > requests;
|
std::vector<std::shared_ptr<i2p::I2NPMessage> > requests;
|
||||||
|
|
||||||
i2p::data::IdentHash ourIdent = i2p::context.GetIdentHash();
|
i2p::data::IdentHash ourIdent = i2p::context.GetIdentHash();
|
||||||
|
@ -472,13 +485,13 @@ namespace data
|
||||||
i2p::transport::transports.SendMessages(ih, requests);
|
i2p::transport::transports.SendMessages(ih, requests);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NetDb::LoadRouterInfo (const std::string & path)
|
bool NetDb::LoadRouterInfo (const std::string& path, uint64_t ts)
|
||||||
{
|
{
|
||||||
auto r = std::make_shared<RouterInfo>(path);
|
auto r = std::make_shared<RouterInfo>(path);
|
||||||
if (r->GetRouterIdentity () && !r->IsUnreachable () && r->HasValidAddresses ())
|
if (r->GetRouterIdentity () && !r->IsUnreachable () && r->HasValidAddresses () &&
|
||||||
|
ts < r->GetTimestamp () + 24*60*60*NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT*1000LL)
|
||||||
{
|
{
|
||||||
r->DeleteBuffer ();
|
r->DeleteBuffer ();
|
||||||
r->ClearProperties (); // properties are not used for regular routers
|
|
||||||
if (m_RouterInfos.emplace (r->GetIdentHash (), r).second)
|
if (m_RouterInfos.emplace (r->GetIdentHash (), r).second)
|
||||||
{
|
{
|
||||||
if (r->IsFloodfill () && r->IsEligibleFloodfill ())
|
if (r->IsFloodfill () && r->IsEligibleFloodfill ())
|
||||||
|
@ -487,7 +500,7 @@ namespace data
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint(eLogWarning, "NetDb: RI from ", path, " is invalid. Delete");
|
LogPrint(eLogWarning, "NetDb: RI from ", path, " is invalid or too old. Delete");
|
||||||
i2p::fs::Remove(path);
|
i2p::fs::Remove(path);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -568,11 +581,11 @@ namespace data
|
||||||
m_RouterInfos.clear ();
|
m_RouterInfos.clear ();
|
||||||
m_Floodfills.clear ();
|
m_Floodfills.clear ();
|
||||||
|
|
||||||
m_LastLoad = i2p::util::GetSecondsSinceEpoch();
|
uint64_t ts = i2p::util::GetMillisecondsSinceEpoch();
|
||||||
std::vector<std::string> files;
|
std::vector<std::string> files;
|
||||||
m_Storage.Traverse(files);
|
m_Storage.Traverse(files);
|
||||||
for (const auto& path : files)
|
for (const auto& path : files)
|
||||||
LoadRouterInfo(path);
|
LoadRouterInfo (path, ts);
|
||||||
|
|
||||||
LogPrint (eLogInfo, "NetDb: ", m_RouterInfos.size(), " routers loaded (", m_Floodfills.size (), " floodfils)");
|
LogPrint (eLogInfo, "NetDb: ", m_RouterInfos.size(), " routers loaded (", m_Floodfills.size (), " floodfils)");
|
||||||
}
|
}
|
||||||
|
@ -596,10 +609,9 @@ namespace data
|
||||||
{
|
{
|
||||||
if (it.second == own) continue; // skip own
|
if (it.second == own) continue; // skip own
|
||||||
std::string ident = it.second->GetIdentHashBase64();
|
std::string ident = it.second->GetIdentHashBase64();
|
||||||
std::string path = m_Storage.Path(ident);
|
|
||||||
if (it.second->IsUpdated ())
|
if (it.second->IsUpdated ())
|
||||||
{
|
{
|
||||||
it.second->SaveToFile (path);
|
it.second->SaveToFile (m_Storage.Path(ident));
|
||||||
it.second->SetUpdated (false);
|
it.second->SetUpdated (false);
|
||||||
it.second->SetUnreachable (false);
|
it.second->SetUnreachable (false);
|
||||||
it.second->DeleteBuffer ();
|
it.second->DeleteBuffer ();
|
||||||
|
@ -608,7 +620,7 @@ namespace data
|
||||||
}
|
}
|
||||||
// make router reachable back if too few routers or floodfills
|
// make router reachable back if too few routers or floodfills
|
||||||
if (it.second->IsUnreachable () && (total - deletedCount < NETDB_MIN_ROUTERS ||
|
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);
|
it.second->SetUnreachable (false);
|
||||||
// find & mark expired routers
|
// find & mark expired routers
|
||||||
if (!it.second->IsReachable () && it.second->IsSSU (false))
|
if (!it.second->IsReachable () && it.second->IsSSU (false))
|
||||||
|
@ -630,11 +642,13 @@ namespace data
|
||||||
}
|
}
|
||||||
} // m_RouterInfos iteration
|
} // m_RouterInfos iteration
|
||||||
|
|
||||||
|
m_RouterInfoBuffersPool.CleanUpMt ();
|
||||||
|
|
||||||
if (updatedCount > 0)
|
if (updatedCount > 0)
|
||||||
LogPrint (eLogInfo, "NetDb: saved ", updatedCount, " new/updated routers");
|
LogPrint (eLogInfo, "NetDb: Saved ", updatedCount, " new/updated routers");
|
||||||
if (deletedCount > 0)
|
if (deletedCount > 0)
|
||||||
{
|
{
|
||||||
LogPrint (eLogInfo, "NetDb: deleting ", deletedCount, " unreachable routers");
|
LogPrint (eLogInfo, "NetDb: Deleting ", deletedCount, " unreachable routers");
|
||||||
// clean up RouterInfos table
|
// clean up RouterInfos table
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(m_RouterInfosMutex);
|
std::unique_lock<std::mutex> l(m_RouterInfosMutex);
|
||||||
|
@ -666,7 +680,7 @@ namespace data
|
||||||
auto dest = m_Requests.CreateRequest (destination, false, requestComplete); // non-exploratory
|
auto dest = m_Requests.CreateRequest (destination, false, requestComplete); // non-exploratory
|
||||||
if (!dest)
|
if (!dest)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "NetDb: destination ", destination.ToBase64(), " is requested already");
|
LogPrint (eLogWarning, "NetDb: Destination ", destination.ToBase64(), " is requested already");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -674,15 +688,15 @@ namespace data
|
||||||
if (floodfill)
|
if (floodfill)
|
||||||
{
|
{
|
||||||
if (direct && !floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) &&
|
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
|
direct = false; // floodfill can't be reached directly
|
||||||
if (direct)
|
if (direct)
|
||||||
transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ()));
|
transports.SendMessage (floodfill->GetIdentHash (), dest->CreateRequestMessage (floodfill->GetIdentHash ()));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto pool = i2p::tunnel::tunnels.GetExploratoryPool ();
|
auto pool = i2p::tunnel::tunnels.GetExploratoryPool ();
|
||||||
auto outbound = pool ? pool->GetNextOutboundTunnel () : nullptr;
|
auto outbound = pool ? pool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false)) : nullptr;
|
||||||
auto inbound = pool ? pool->GetNextInboundTunnel () : nullptr;
|
auto inbound = pool ? pool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true)) : nullptr;
|
||||||
if (outbound && inbound)
|
if (outbound && inbound)
|
||||||
outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, dest->CreateRequestMessage (floodfill, inbound));
|
outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, dest->CreateRequestMessage (floodfill, inbound));
|
||||||
else
|
else
|
||||||
|
@ -705,10 +719,10 @@ namespace data
|
||||||
auto dest = m_Requests.CreateRequest (destination, exploritory, requestComplete); // non-exploratory
|
auto dest = m_Requests.CreateRequest (destination, exploritory, requestComplete); // non-exploratory
|
||||||
if (!dest)
|
if (!dest)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "NetDb: destination ", destination.ToBase64(), " is requested already");
|
LogPrint (eLogWarning, "NetDb: Destination ", destination.ToBase64(), " is requested already");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LogPrint(eLogInfo, "NetDb: destination ", destination.ToBase64(), " being requested directly from ", from.ToBase64());
|
LogPrint(eLogInfo, "NetDb: Destination ", destination.ToBase64(), " being requested directly from ", from.ToBase64());
|
||||||
// direct
|
// direct
|
||||||
transports.SendMessage (from, dest->CreateRequestMessage (nullptr, nullptr));
|
transports.SendMessage (from, dest->CreateRequestMessage (nullptr, nullptr));
|
||||||
}
|
}
|
||||||
|
@ -732,7 +746,7 @@ namespace data
|
||||||
IdentHash ident (buf + DATABASE_STORE_KEY_OFFSET);
|
IdentHash ident (buf + DATABASE_STORE_KEY_OFFSET);
|
||||||
if (ident.IsZero ())
|
if (ident.IsZero ())
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "NetDb: database store with zero ident, dropped");
|
LogPrint (eLogDebug, "NetDb: Database store with zero ident, dropped");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint32_t replyToken = bufbe32toh (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET);
|
uint32_t replyToken = bufbe32toh (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET);
|
||||||
|
@ -751,14 +765,14 @@ namespace data
|
||||||
if (outbound)
|
if (outbound)
|
||||||
outbound->SendTunnelDataMsg (buf + offset, tunnelID, deliveryStatus);
|
outbound->SendTunnelDataMsg (buf + offset, tunnelID, deliveryStatus);
|
||||||
else
|
else
|
||||||
LogPrint (eLogWarning, "NetDb: no outbound tunnels for DatabaseStore reply found");
|
LogPrint (eLogWarning, "NetDb: No outbound tunnels for DatabaseStore reply found");
|
||||||
}
|
}
|
||||||
offset += 32;
|
offset += 32;
|
||||||
}
|
}
|
||||||
// we must send reply back before this check
|
// we must send reply back before this check
|
||||||
if (ident == i2p::context.GetIdentHash ())
|
if (ident == i2p::context.GetIdentHash ())
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "NetDb: database store with own RouterInfo received, dropped");
|
LogPrint (eLogDebug, "NetDb: Database store with own RouterInfo received, dropped");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
size_t payloadOffset = offset;
|
size_t payloadOffset = offset;
|
||||||
|
@ -771,24 +785,24 @@ namespace data
|
||||||
{
|
{
|
||||||
if (storeType == NETDB_STORE_TYPE_LEASESET) // 1
|
if (storeType == NETDB_STORE_TYPE_LEASESET) // 1
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "NetDb: store request: LeaseSet for ", ident.ToBase32());
|
LogPrint (eLogDebug, "NetDb: Store request: LeaseSet for ", ident.ToBase32());
|
||||||
updated = AddLeaseSet (ident, buf + offset, len - offset);
|
updated = AddLeaseSet (ident, buf + offset, len - offset);
|
||||||
}
|
}
|
||||||
else // all others are considered as LeaseSet2
|
else // all others are considered as LeaseSet2
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "NetDb: store request: LeaseSet2 of type ", storeType, " for ", ident.ToBase32());
|
LogPrint (eLogDebug, "NetDb: Store request: LeaseSet2 of type ", storeType, " for ", ident.ToBase32());
|
||||||
updated = AddLeaseSet2 (ident, buf + offset, len - offset, storeType);
|
updated = AddLeaseSet2 (ident, buf + offset, len - offset, storeType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else // RouterInfo
|
else // RouterInfo
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "NetDb: store request: RouterInfo");
|
LogPrint (eLogDebug, "NetDb: Store request: RouterInfo");
|
||||||
size_t size = bufbe16toh (buf + offset);
|
size_t size = bufbe16toh (buf + offset);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
if (size > MAX_RI_BUFFER_SIZE || size > len - offset)
|
if (size > MAX_RI_BUFFER_SIZE || size > len - offset)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "NetDb: invalid RouterInfo length ", (int)size);
|
LogPrint (eLogError, "NetDb: Invalid RouterInfo length ", (int)size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint8_t uncompressed[MAX_RI_BUFFER_SIZE];
|
uint8_t uncompressed[MAX_RI_BUFFER_SIZE];
|
||||||
|
@ -797,7 +811,7 @@ namespace data
|
||||||
updated = AddRouterInfo (ident, uncompressed, uncompressedSize);
|
updated = AddRouterInfo (ident, uncompressed, uncompressedSize);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LogPrint (eLogInfo, "NetDb: decompression failed ", uncompressedSize);
|
LogPrint (eLogInfo, "NetDb: Decompression failed ", uncompressedSize);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -872,7 +886,7 @@ namespace data
|
||||||
m_Requests.RequestComplete (ident, nullptr);
|
m_Requests.RequestComplete (ident, nullptr);
|
||||||
}
|
}
|
||||||
else if(!m_FloodfillBootstrap)
|
else if(!m_FloodfillBootstrap)
|
||||||
LogPrint (eLogWarning, "NetDb: requested destination for ", key, " not found");
|
LogPrint (eLogWarning, "NetDb: Requested destination for ", key, " not found");
|
||||||
|
|
||||||
// try responses
|
// try responses
|
||||||
for (int i = 0; i < num; i++)
|
for (int i = 0; i < num; i++)
|
||||||
|
@ -887,7 +901,7 @@ namespace data
|
||||||
if (!r || i2p::util::GetMillisecondsSinceEpoch () > r->GetTimestamp () + 3600*1000LL)
|
if (!r || i2p::util::GetMillisecondsSinceEpoch () > r->GetTimestamp () + 3600*1000LL)
|
||||||
{
|
{
|
||||||
// router with ident not found or too old (1 hour)
|
// router with ident not found or too old (1 hour)
|
||||||
LogPrint (eLogDebug, "NetDb: found new/outdated router. Requesting RouterInfo ...");
|
LogPrint (eLogDebug, "NetDb: Found new/outdated router. Requesting RouterInfo...");
|
||||||
if(m_FloodfillBootstrap)
|
if(m_FloodfillBootstrap)
|
||||||
RequestDestinationFrom(router, m_FloodfillBootstrap->GetIdentHash(), true);
|
RequestDestinationFrom(router, m_FloodfillBootstrap->GetIdentHash(), true);
|
||||||
else
|
else
|
||||||
|
@ -928,14 +942,14 @@ namespace data
|
||||||
excluded += 2;
|
excluded += 2;
|
||||||
if (numExcluded > 512)
|
if (numExcluded > 512)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "NetDb: number of excluded peers", numExcluded, " exceeds 512");
|
LogPrint (eLogWarning, "NetDb: Number of excluded peers", numExcluded, " exceeds 512");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> replyMsg;
|
std::shared_ptr<I2NPMessage> replyMsg;
|
||||||
if (lookupType == DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP)
|
if (lookupType == DATABASE_LOOKUP_TYPE_EXPLORATORY_LOOKUP)
|
||||||
{
|
{
|
||||||
LogPrint (eLogInfo, "NetDb: exploratory close to ", key, " ", numExcluded, " excluded");
|
LogPrint (eLogInfo, "NetDb: Exploratory close to ", key, " ", numExcluded, " excluded");
|
||||||
std::set<IdentHash> excludedRouters;
|
std::set<IdentHash> excludedRouters;
|
||||||
for (int i = 0; i < numExcluded; i++)
|
for (int i = 0; i < numExcluded; i++)
|
||||||
{
|
{
|
||||||
|
@ -957,14 +971,13 @@ namespace data
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (lookupType == DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP ||
|
if (lookupType == DATABASE_LOOKUP_TYPE_ROUTERINFO_LOOKUP ||
|
||||||
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)
|
lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)
|
||||||
{
|
{
|
||||||
auto router = FindRouter (ident);
|
auto router = FindRouter (ident);
|
||||||
if (router)
|
if (router)
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "NetDb: requested RouterInfo ", key, " found");
|
LogPrint (eLogDebug, "NetDb: Requested RouterInfo ", key, " found");
|
||||||
if (!router->GetBuffer ())
|
PopulateRouterInfoBuffer (router);
|
||||||
router->LoadBuffer (m_Storage.Path (router->GetIdentHashBase64 ()));
|
|
||||||
if (router->GetBuffer ())
|
if (router->GetBuffer ())
|
||||||
replyMsg = CreateDatabaseStoreMsg (router);
|
replyMsg = CreateDatabaseStoreMsg (router);
|
||||||
}
|
}
|
||||||
|
@ -977,11 +990,11 @@ namespace data
|
||||||
if (!leaseSet)
|
if (!leaseSet)
|
||||||
{
|
{
|
||||||
// no lease set found
|
// no lease set found
|
||||||
LogPrint(eLogDebug, "NetDb: requested LeaseSet not found for ", ident.ToBase32());
|
LogPrint(eLogDebug, "NetDb: Requested LeaseSet not found for ", ident.ToBase32());
|
||||||
}
|
}
|
||||||
else if (!leaseSet->IsExpired ()) // we don't send back our LeaseSets
|
else if (!leaseSet->IsExpired ()) // we don't send back our LeaseSets
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "NetDb: requested LeaseSet ", key, " found");
|
LogPrint (eLogDebug, "NetDb: Requested LeaseSet ", key, " found");
|
||||||
replyMsg = CreateDatabaseStoreMsg (ident, leaseSet);
|
replyMsg = CreateDatabaseStoreMsg (ident, leaseSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1026,10 +1039,10 @@ namespace data
|
||||||
replyMsg = garlic.WrapSingleMessage (replyMsg);
|
replyMsg = garlic.WrapSingleMessage (replyMsg);
|
||||||
}
|
}
|
||||||
if (!replyMsg)
|
if (!replyMsg)
|
||||||
LogPrint (eLogError, "NetDb: failed to wrap message");
|
LogPrint (eLogError, "NetDb: Failed to wrap message");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint(eLogWarning, "NetDb: encrypted reply requested but no tags provided");
|
LogPrint(eLogWarning, "NetDb: Encrypted reply requested but no tags provided");
|
||||||
}
|
}
|
||||||
auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool ();
|
auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool ();
|
||||||
auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr;
|
auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr;
|
||||||
|
@ -1063,14 +1076,14 @@ namespace data
|
||||||
|
|
||||||
uint8_t randomHash[32];
|
uint8_t randomHash[32];
|
||||||
std::vector<i2p::tunnel::TunnelMessageBlock> msgs;
|
std::vector<i2p::tunnel::TunnelMessageBlock> msgs;
|
||||||
LogPrint (eLogInfo, "NetDb: exploring new ", numDestinations, " routers ...");
|
LogPrint (eLogInfo, "NetDb: Exploring new ", numDestinations, " routers ...");
|
||||||
for (int i = 0; i < numDestinations; i++)
|
for (int i = 0; i < numDestinations; i++)
|
||||||
{
|
{
|
||||||
RAND_bytes (randomHash, 32);
|
RAND_bytes (randomHash, 32);
|
||||||
auto dest = m_Requests.CreateRequest (randomHash, true); // exploratory
|
auto dest = m_Requests.CreateRequest (randomHash, true); // exploratory
|
||||||
if (!dest)
|
if (!dest)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "NetDb: exploratory destination is requested already");
|
LogPrint (eLogWarning, "NetDb: Exploratory destination is requested already");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto floodfill = GetClosestFloodfill (randomHash, dest->GetExcludedPeers ());
|
auto floodfill = GetClosestFloodfill (randomHash, dest->GetExcludedPeers ());
|
||||||
|
@ -1122,15 +1135,15 @@ namespace data
|
||||||
m_PublishExcluded.insert (floodfill->GetIdentHash ());
|
m_PublishExcluded.insert (floodfill->GetIdentHash ());
|
||||||
m_PublishReplyToken = replyToken;
|
m_PublishReplyToken = replyToken;
|
||||||
if (floodfill->IsReachableFrom (i2p::context.GetRouterInfo ()) || // are we able to connect?
|
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
|
// send directly
|
||||||
transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken));
|
transports.SendMessage (floodfill->GetIdentHash (), CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// otherwise through exploratory
|
// otherwise through exploratory
|
||||||
auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool ();
|
auto exploratoryPool = i2p::tunnel::tunnels.GetExploratoryPool ();
|
||||||
auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel () : nullptr;
|
auto outbound = exploratoryPool ? exploratoryPool->GetNextOutboundTunnel (nullptr, floodfill->GetCompatibleTransports (false)) : nullptr;
|
||||||
auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel () : nullptr;
|
auto inbound = exploratoryPool ? exploratoryPool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true)) : nullptr;
|
||||||
if (inbound && outbound)
|
if (inbound && outbound)
|
||||||
outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0,
|
outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0,
|
||||||
CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound));
|
CreateDatabaseStoreMsg (i2p::context.GetSharedRouterInfo (), replyToken, inbound));
|
||||||
|
@ -1189,6 +1202,16 @@ 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
|
std::shared_ptr<const RouterInfo> NetDb::GetRandomSSUV6Router () const
|
||||||
{
|
{
|
||||||
return GetRandomRouter (
|
return GetRandomRouter (
|
||||||
|
@ -1261,7 +1284,7 @@ namespace data
|
||||||
return it->second;
|
return it->second;
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
// still not found, try from the begining
|
// still not found, try from the beginning
|
||||||
it = m_RouterInfos.begin ();
|
it = m_RouterInfos.begin ();
|
||||||
while (it != it1 && it != m_RouterInfos.end ())
|
while (it != it1 && it != m_RouterInfos.end ())
|
||||||
{
|
{
|
||||||
|
@ -1269,7 +1292,7 @@ namespace data
|
||||||
return it->second;
|
return it->second;
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
// still not found, try to the begining
|
// still not found, try to the beginning
|
||||||
it = it2;
|
it = it2;
|
||||||
while (it != m_RouterInfos.end ())
|
while (it != m_RouterInfos.end ())
|
||||||
{
|
{
|
||||||
|
@ -1363,7 +1386,8 @@ namespace data
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouterInFamily(const std::string & fam) const {
|
std::shared_ptr<const RouterInfo> NetDb::GetRandomRouterInFamily (FamilyID fam) const
|
||||||
|
{
|
||||||
return GetRandomRouter(
|
return GetRandomRouter(
|
||||||
[fam](std::shared_ptr<const RouterInfo> router)->bool
|
[fam](std::shared_ptr<const RouterInfo> router)->bool
|
||||||
{
|
{
|
||||||
|
@ -1408,5 +1432,11 @@ namespace data
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NetDb::PopulateRouterInfoBuffer (std::shared_ptr<RouterInfo> r)
|
||||||
|
{
|
||||||
|
if (!r || r->GetBuffer ()) return;
|
||||||
|
r->LoadBuffer (m_Storage.Path (r->GetIdentHashBase64 ()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2021, The PurpleI2P Project
|
* Copyright (c) 2013-2022, The PurpleI2P Project
|
||||||
*
|
*
|
||||||
* This file is part of Purple i2pd project and licensed under BSD3
|
* This file is part of Purple i2pd project and licensed under BSD3
|
||||||
*
|
*
|
||||||
|
@ -30,6 +30,7 @@
|
||||||
#include "NetDbRequests.h"
|
#include "NetDbRequests.h"
|
||||||
#include "Family.h"
|
#include "Family.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
|
@ -41,6 +42,7 @@ namespace data
|
||||||
const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65 * 60;
|
const int NETDB_INTRODUCEE_EXPIRATION_TIMEOUT = 65 * 60;
|
||||||
const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours
|
const int NETDB_MIN_EXPIRATION_TIMEOUT = 90 * 60; // 1.5 hours
|
||||||
const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours
|
const int NETDB_MAX_EXPIRATION_TIMEOUT = 27 * 60 * 60; // 27 hours
|
||||||
|
const int NETDB_MAX_OFFLINE_EXPIRATION_TIMEOUT = 180; // in days
|
||||||
const int NETDB_PUBLISH_INTERVAL = 60 * 40;
|
const int NETDB_PUBLISH_INTERVAL = 60 * 40;
|
||||||
const int NETDB_PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds
|
const int NETDB_PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds
|
||||||
const int NETDB_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15;
|
const int NETDB_MAX_PUBLISH_EXCLUDED_FLOODFILLS = 15;
|
||||||
|
@ -88,13 +90,14 @@ namespace data
|
||||||
std::shared_ptr<const RouterInfo> GetRandomRouter (std::shared_ptr<const RouterInfo> compatibleWith, bool reverse) const;
|
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> 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> 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> 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> GetRandomIntroducer (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::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::vector<IdentHash> GetClosestFloodfills (const IdentHash& destination, size_t num,
|
||||||
std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
|
std::set<IdentHash>& excluded, bool closeThanUsOnly = false) const;
|
||||||
std::shared_ptr<const RouterInfo> GetClosestNonFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
|
std::shared_ptr<const RouterInfo> GetClosestNonFloodfill (const IdentHash& destination, const std::set<IdentHash>& excluded) const;
|
||||||
std::shared_ptr<const RouterInfo> GetRandomRouterInFamily(const std::string & fam) const;
|
std::shared_ptr<const RouterInfo> GetRandomRouterInFamily (FamilyID fam) const;
|
||||||
void SetUnreachable (const IdentHash& ident, bool unreachable);
|
void SetUnreachable (const IdentHash& ident, bool unreachable);
|
||||||
|
|
||||||
void PostI2NPMsg (std::shared_ptr<const I2NPMessage> msg);
|
void PostI2NPMsg (std::shared_ptr<const I2NPMessage> msg);
|
||||||
|
@ -120,13 +123,15 @@ namespace data
|
||||||
size_t VisitRandomRouterInfos(RouterInfoFilter f, RouterInfoVisitor v, size_t n);
|
size_t VisitRandomRouterInfos(RouterInfoFilter f, RouterInfoVisitor v, size_t n);
|
||||||
|
|
||||||
void ClearRouterInfos () { m_RouterInfos.clear (); };
|
void ClearRouterInfos () { m_RouterInfos.clear (); };
|
||||||
|
std::shared_ptr<RouterInfo::Buffer> NewRouterInfoBuffer () { return m_RouterInfoBuffersPool.AcquireSharedMt (); };
|
||||||
|
void PopulateRouterInfoBuffer (std::shared_ptr<RouterInfo> r);
|
||||||
|
|
||||||
uint32_t GetPublishReplyToken () const { return m_PublishReplyToken; };
|
uint32_t GetPublishReplyToken () const { return m_PublishReplyToken; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void Load ();
|
void Load ();
|
||||||
bool LoadRouterInfo (const std::string & path);
|
bool LoadRouterInfo (const std::string& path, uint64_t ts);
|
||||||
void SaveUpdated ();
|
void SaveUpdated ();
|
||||||
void Run (); // exploratory thread
|
void Run (); // exploratory thread
|
||||||
void Explore (int numDestinations);
|
void Explore (int numDestinations);
|
||||||
|
@ -153,7 +158,6 @@ namespace data
|
||||||
std::list<std::shared_ptr<RouterInfo> > m_Floodfills;
|
std::list<std::shared_ptr<RouterInfo> > m_Floodfills;
|
||||||
|
|
||||||
bool m_IsRunning;
|
bool m_IsRunning;
|
||||||
uint64_t m_LastLoad;
|
|
||||||
std::thread * m_Thread;
|
std::thread * m_Thread;
|
||||||
i2p::util::Queue<std::shared_ptr<const I2NPMessage> > m_Queue; // of I2NPDatabaseStoreMsg
|
i2p::util::Queue<std::shared_ptr<const I2NPMessage> > m_Queue; // of I2NPDatabaseStoreMsg
|
||||||
|
|
||||||
|
@ -175,6 +179,8 @@ namespace data
|
||||||
|
|
||||||
std::set<IdentHash> m_PublishExcluded;
|
std::set<IdentHash> m_PublishExcluded;
|
||||||
uint32_t m_PublishReplyToken = 0;
|
uint32_t m_PublishReplyToken = 0;
|
||||||
|
|
||||||
|
i2p::util::MemoryPoolMt<RouterInfo::Buffer> m_RouterInfoBuffersPool;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern NetDb netdb;
|
extern NetDb netdb;
|
||||||
|
|
|
@ -60,7 +60,7 @@ namespace data
|
||||||
void Start ();
|
void Start ();
|
||||||
void Stop ();
|
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);
|
void RequestComplete (const IdentHash& ident, std::shared_ptr<RouterInfo> r);
|
||||||
std::shared_ptr<RequestedDestination> FindRequest (const IdentHash& ident) const;
|
std::shared_ptr<RequestedDestination> FindRequest (const IdentHash& ident) const;
|
||||||
void ManageRequests ();
|
void ManageRequests ();
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue