Compare commits

..

No commits in common. 'openssl' and '2.46.0' have entirely different histories.

@ -30,10 +30,3 @@ indent_size = 4
indent_style = space
indent_size = 2
trim_trailing_whitespace = false
[*.yml]
indent_style = space
indent_size = 2
[*.patch]
trim_trailing_whitespace = false

@ -1,61 +1,32 @@
name: Build Debian packages
on:
push:
branches:
- '*'
paths:
- .github/workflows/build-deb.yml
- contrib/**
- daemon/**
- debian/**
- i18n/**
- libi2pd/**
- libi2pd_client/**
- Makefile
- Makefile.linux
tags:
- '*'
pull_request:
branches:
- '*'
on: [push, pull_request]
jobs:
build:
name: ${{ matrix.dist }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
dist: ['buster', 'bullseye', 'bookworm']
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Commit Hash
id: commit
uses: prompt/actions-commit-hash@v3.0.0
- name: Build package
uses: jtdor/build-deb-action@v1
- name: change debian changelog
run: |
sudo apt-get update
sudo apt-get install devscripts
debchange -v "`git describe --tags`-${{ matrix.dist }}" -b -M --distribution ${{ matrix.dist }} "trunk build"
- uses: jtdor/build-deb-action@v1
with:
docker-image: debian:${{ matrix.dist }}-slim
buildpackage-opts: --build=binary --no-sign
before-build-hook: debchange --controlmaint --local "+${{ steps.commit.outputs.short }}~${{ matrix.dist }}" -b --distribution ${{ matrix.dist }} "CI build"
extra-build-deps: devscripts git
- name: Upload package
uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v3
with:
name: i2pd_${{ matrix.dist }}
path: debian/artifacts/i2pd_*.deb
- name: Upload debugging symbols
uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v3
with:
name: i2pd-dbgsym_${{ matrix.dist }}
path: debian/artifacts/i2pd-dbgsym_*.deb

@ -1,37 +1,16 @@
name: Build on FreeBSD
on:
push:
branches:
- '*'
paths:
- .github/workflows/build-freebsd.yml
- build/CMakeLists.txt
- build/cmake_modules/**
- daemon/**
- i18n/**
- libi2pd/**
- libi2pd_client/**
- Makefile
- Makefile.bsd
tags:
- '*'
pull_request:
branches:
- '*'
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
runs-on: macos-12
name: with UPnP
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: actions/checkout@v2
- name: Test in FreeBSD
id: test
uses: vmactions/freebsd-vm@v1
uses: vmactions/freebsd-vm@v0.3.0
with:
usesh: true
mem: 2048
@ -42,9 +21,8 @@ jobs:
cd build
cmake -DWITH_UPNP=ON -DCMAKE_BUILD_TYPE=Release .
gmake -j2
- name: Upload artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v2
with:
name: i2pd-freebsd
path: build/i2pd
path: build/i2pd

@ -1,45 +1,21 @@
name: Build on OSX
on:
push:
branches:
- '*'
paths:
- .github/workflows/build-osx.yml
- daemon/**
- i18n/**
- libi2pd/**
- libi2pd_client/**
- Makefile
- Makefile.homebrew
tags:
- '*'
pull_request:
branches:
- '*'
on: [push, pull_request]
jobs:
build:
name: With USE_UPNP=${{ matrix.with_upnp }}
runs-on: macOS-latest
strategy:
fail-fast: true
matrix:
with_upnp: ['yes', 'no']
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install required formulae
- uses: actions/checkout@v2
- name: install packages
run: |
find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete
brew update
brew install boost miniupnpc openssl@1.1
- name: List installed formulae
run: brew list
- name: Build application
- name: build application
run: make HOMEBREW=1 USE_UPNP=${{ matrix.with_upnp }} PREFIX=$GITHUB_WORKSPACE/output -j3

@ -1,80 +0,0 @@
name: Build on Windows with MSVC
on:
push:
branches:
- '*'
paths:
- .github/workflows/build-windows-msvc.yml
- build/CMakeLists.txt
- build/cmake_modules/**
- daemon/**
- i18n/**
- libi2pd/**
- libi2pd_client/**
- Win32/**
tags:
- '*'
pull_request:
branches:
- '*'
jobs:
build:
name: Build
runs-on: windows-latest
env:
boost_path: ${{ github.workspace }}\boost_1_83_0
openssl_path: ${{ github.workspace }}\openssl_3_2_1
strategy:
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Build and install zlib
run: |
powershell -Command "(Invoke-WebRequest -Uri https://raw.githubusercontent.com/r4sas/zlib.install/master/install.bat -OutFile install_zlib.bat)"
powershell -Command "(Get-Content install_zlib.bat) | Set-Content install_zlib.bat" # fixing line endings
set BUILD_TYPE=Debug
./install_zlib.bat
set BUILD_TYPE=Release
./install_zlib.bat
del install_zlib.bat
- name: Install Boost
run: |
powershell -Command "(Start-BitsTransfer -Source https://sourceforge.net/projects/boost/files/boost-binaries/1.83.0/boost_1_83_0-msvc-14.3-64.exe/download -Destination boost_1_83_0-msvc-14.3-64.exe)"
./boost_1_83_0-msvc-14.3-64.exe /DIR="${{env.boost_path}}" /VERYSILENT /SUPPRESSMSGBOXES /SP-
- name: Install OpenSSL
run: |
powershell -Command "(Start-BitsTransfer -Source https://slproweb.com/download/Win64OpenSSL-3_2_1.exe -Destination Win64OpenSSL-3_2_1.exe)"
./Win64OpenSSL-3_2_1.exe /DIR="${{env.openssl_path}}" /TASKS="copytobin" /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-
- name: Make copy of the OpenSSL libraries for CMake
run: |
dir ${{ github.workspace }}
dir ${{env.openssl_path}}\lib\VC
dir ${{env.openssl_path}}\lib\VC\x64\
dir ${{env.openssl_path}}\lib\VC\x64\MTd\
xcopy /s /y "${{env.openssl_path}}\lib\VC\x64\MTd" "${{env.openssl_path}}\lib"
- name: Configure
working-directory: build
run: cmake -DBoost_ROOT="${{env.boost_path}}" -DOPENSSL_ROOT_DIR="${{env.openssl_path}}" -DWITH_STATIC=ON .
- name: Build
working-directory: build
run: cmake --build . --config Debug -- -m
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: i2pd-msvc
path: build/Debug/i2pd.*

@ -1,25 +1,6 @@
name: Build on Windows
on:
push:
branches:
- '*'
paths:
- .github/workflows/build-windows.yml
- build/CMakeLists.txt
- build/cmake_modules/**
- daemon/**
- i18n/**
- libi2pd/**
- libi2pd_client/**
- Win32/**
- Makefile
- Makefile.mingw
tags:
- '*'
pull_request:
branches:
- '*'
on: [push, pull_request]
defaults:
run:
@ -27,215 +8,68 @@ defaults:
jobs:
build:
name: ${{ matrix.arch }}
name: Building using ${{ matrix.arch }} toolchain
runs-on: windows-latest
strategy:
fail-fast: false
fail-fast: true
matrix:
include: [
{ msystem: UCRT64, arch: ucrt-x86_64, arch_short: x64-ucrt, compiler: gcc },
{ msystem: CLANG64, arch: clang-x86_64, arch_short: x64-clang, compiler: clang },
{ msystem: MINGW64, arch: x86_64, arch_short: x64, compiler: gcc },
{ msystem: MINGW32, arch: i686, arch_short: x86, compiler: gcc }
{ msystem: UCRT64, arch: ucrt-x86_64, arch_short: x64-ucrt },
{ msystem: MINGW64, arch: x86_64, arch_short: x64 },
{ msystem: MINGW32, arch: i686, arch_short: x86 }
]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/checkout@v2
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.msystem }}
install: base-devel git mingw-w64-${{ matrix.arch }}-${{ matrix.compiler }} 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
- name: Install additional clang packages
if: ${{ matrix.msystem == 'CLANG64' }}
run: pacman --noconfirm -S mingw-w64-${{ matrix.arch }}-gcc-compat
- 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 -j3
- name: Upload artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v2
with:
name: i2pd-${{ matrix.arch_short }}.exe
path: i2pd.exe
build-cmake:
name: CMake ${{ matrix.arch }}
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
include: [
{ msystem: UCRT64, arch: ucrt-x86_64, arch_short: x64-ucrt, compiler: gcc },
{ msystem: CLANG64, arch: clang-x86_64, arch_short: x64-clang, compiler: clang },
{ msystem: MINGW64, arch: x86_64, arch_short: x64, compiler: gcc },
{ msystem: MINGW32, arch: i686, arch_short: x86, compiler: gcc }
]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.msystem }}
install: base-devel git mingw-w64-${{ matrix.arch }}-cmake mingw-w64-${{ matrix.arch }}-ninja mingw-w64-${{ matrix.arch }}-${{ matrix.compiler }} mingw-w64-${{ matrix.arch }}-boost mingw-w64-${{ matrix.arch }}-openssl mingw-w64-${{ matrix.arch }}-miniupnpc
update: true
- name: Build application
run: |
cd build
cmake -DWITH_GIT_VERSION=ON -DWITH_STATIC=ON -DWITH_UPNP=ON -DCMAKE_BUILD_TYPE=Release .
cmake --build . -- -j3
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: i2pd-cmake-${{ matrix.arch_short }}.exe
path: build/i2pd.exe
build-xp:
name: XP
name: Building for Windows XP
runs-on: windows-latest
strategy:
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- 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
cache: true
update: true
- name: Clone MinGW packages repository
run: git clone https://github.com/msys2/MINGW-packages
# headers
- name: Get headers package version
id: version-headers
run: |
echo "version=$(pacman -Si mingw-w64-i686-headers-git | grep -Po '^Version\s*: \K.+')" >> $GITHUB_OUTPUT
- name: Cache headers package
uses: actions/cache@v4
id: cache-headers
with:
path: MINGW-packages/mingw-w64-headers-git/*.zst
key: winxp-headers-${{ steps.version-headers.outputs.version }}
- name: Build WinXP-capable headers package
if: steps.cache-headers.outputs.cache-hit != 'true'
- name: Build WinXP-capable CRT packages
run: |
cd MINGW-packages/mingw-w64-headers-git
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 --nocheck
- name: Install headers package
run: pacman --noconfirm -U MINGW-packages/mingw-w64-headers-git/mingw-w64-i686-*-any.pkg.tar.zst
# CRT
- name: Get crt package version
id: version-crt
run: |
echo "version=$(pacman -Si mingw-w64-i686-crt-git | grep -Po '^Version\s*: \K.+')" >> $GITHUB_OUTPUT
- name: Cache crt package
uses: actions/cache@v4
id: cache-crt
with:
path: MINGW-packages/mingw-w64-crt-git/*.zst
key: winxp-crt-${{ steps.version-crt.outputs.version }}
- name: Build WinXP-capable crt package
if: steps.cache-crt.outputs.cache-hit != 'true'
run: |
cd MINGW-packages/mingw-w64-crt-git
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm --nocheck
- name: Install crt package
run: pacman --noconfirm -U MINGW-packages/mingw-w64-crt-git/mingw-w64-i686-*-any.pkg.tar.zst
# winpthreads
- name: Get winpthreads package version
id: version-winpthreads
run: |
echo "version=$(pacman -Si mingw-w64-i686-winpthreads-git | grep -Po '^Version\s*: \K.+')" >> $GITHUB_OUTPUT
- name: Cache winpthreads package
uses: actions/cache@v4
id: cache-winpthreads
with:
path: MINGW-packages/mingw-w64-winpthreads-git/*.zst
key: winxp-winpthreads-${{ steps.version-winpthreads.outputs.version }}
- name: Build WinXP-capable winpthreads package
if: steps.cache-winpthreads.outputs.cache-hit != 'true'
run: |
cd MINGW-packages/mingw-w64-winpthreads-git
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm --nocheck
- name: Install winpthreads package
run: pacman --noconfirm -U MINGW-packages/mingw-w64-winpthreads-git/mingw-w64-i686-*-any.pkg.tar.zst
# OpenSSL
- name: Get openssl package version
id: version-openssl
run: |
echo "version=$(pacman -Si mingw-w64-i686-openssl | grep -Po '^Version\s*: \K.+')" >> $GITHUB_OUTPUT
- name: Cache openssl package
uses: actions/cache@v4
id: cache-openssl
with:
path: MINGW-packages/mingw-w64-openssl/*.zst
key: winxp-openssl-${{ steps.version-openssl.outputs.version }}
- name: Build WinXP-capable openssl package
if: steps.cache-openssl.outputs.cache-hit != 'true'
run: |
cd MINGW-packages/mingw-w64-openssl
gpg --recv-keys D894E2CE8B3D79F5
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm --nocheck
- name: Install openssl package
run: pacman --noconfirm -U MINGW-packages/mingw-w64-openssl/mingw-w64-i686-*-any.pkg.tar.zst
# Boost
- name: Get boost package version
id: version-boost
run: |
echo "version=$(pacman -Si mingw-w64-i686-boost | grep -Po '^Version\s*: \K.+')" >> $GITHUB_OUTPUT
- name: Cache boost package
uses: actions/cache@v4
id: cache-boost
with:
path: MINGW-packages/mingw-w64-boost/*.zst
key: winxp-winpthreads-${{ steps.version-boost.outputs.version }}
- name: Build WinXP-capable boost package
if: steps.cache-boost.outputs.cache-hit != 'true'
run: |
cd MINGW-packages/mingw-w64-boost
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm --nocheck
- name: Install boost package
run: pacman --noconfirm -U MINGW-packages/mingw-w64-boost/mingw-w64-i686-*-any.pkg.tar.zst
# Building i2pd
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@v4
uses: actions/upload-artifact@v2
with:
name: i2pd-xp.exe
path: i2pd.exe

@ -1,65 +1,38 @@
name: Build on Ubuntu
on:
push:
branches:
- '*'
paths:
- .github/workflows/build.yml
- build/CMakeLists.txt
- build/cmake_modules/**
- daemon/**
- i18n/**
- libi2pd/**
- libi2pd_client/**
- Makefile
- Makefile.linux
tags:
- '*'
pull_request:
branches:
- '*'
on: [push, pull_request]
jobs:
build-make:
name: Make with USE_UPNP=${{ matrix.with_upnp }}
runs-on: ubuntu-latest
runs-on: ubuntu-18.04
strategy:
fail-fast: true
matrix:
with_upnp: ['yes', 'no']
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: actions/checkout@v2
- name: install packages
run: |
sudo add-apt-repository ppa:mhier/libboost-latest
sudo apt-get update
sudo apt-get install build-essential libboost-all-dev libminiupnpc-dev libssl-dev zlib1g-dev
sudo apt-get install build-essential libboost1.74-dev libminiupnpc-dev libssl-dev zlib1g-dev
- name: build application
run: make USE_UPNP=${{ matrix.with_upnp }} -j3
build-cmake:
name: CMake with -DWITH_UPNP=${{ matrix.with_upnp }}
runs-on: ubuntu-latest
runs-on: ubuntu-18.04
strategy:
fail-fast: true
matrix:
with_upnp: ['ON', 'OFF']
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: actions/checkout@v2
- name: install packages
run: |
sudo add-apt-repository ppa:mhier/libboost-latest
sudo apt-get update
sudo apt-get install build-essential cmake libboost-all-dev libminiupnpc-dev libssl-dev zlib1g-dev
sudo apt-get install build-essential cmake libboost1.74-dev libminiupnpc-dev libssl-dev zlib1g-dev
- name: build application
run: |
cd build

@ -5,22 +5,11 @@ on:
branches:
- openssl
- docker
paths:
- .github/workflows/docker.yml
- contrib/docker/**
- contrib/certificates/**
- daemon/**
- i18n/**
- libi2pd/**
- libi2pd_client/**
- Makefile
- Makefile.linux
tags:
- '*'
jobs:
build:
name: Building container for ${{ matrix.platform }}
runs-on: ubuntu-latest
permissions:
packages: write
@ -36,44 +25,42 @@ jobs:
]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build container for ${{ matrix.archname }}
uses: docker/build-push-action@v5
with:
context: ./contrib/docker
file: ./contrib/docker/Dockerfile
platforms: ${{ matrix.platform }}
push: true
tags: |
purplei2p/i2pd:latest-${{ matrix.archname }}
ghcr.io/purplei2p/i2pd:latest-${{ matrix.archname }}
provenance: false
- name: Checkout
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build container for ${{ matrix.archname }}
uses: docker/build-push-action@v3
with:
context: ./contrib/docker
file: ./contrib/docker/Dockerfile
platforms: ${{ matrix.platform }}
push: true
tags: |
purplei2p/i2pd:latest-${{ matrix.archname }}
ghcr.io/purplei2p/i2pd:latest-${{ matrix.archname }}
provenance: false
push:
name: Pushing merged manifest
runs-on: ubuntu-latest
permissions:
packages: write
contents: read
@ -81,60 +68,60 @@ jobs:
needs: build
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create and push latest manifest image to Docker Hub
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
inputs: purplei2p/i2pd:latest
images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7
push: true
- name: Create and push latest manifest image to GHCR
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
inputs: ghcr.io/purplei2p/i2pd:latest
images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7
push: true
- name: Store release version to env
if: ${{ startsWith(github.ref, 'refs/tags/') }}
run: echo "RELEASE_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV
- name: Create and push release manifest to Docker Hub
if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
inputs: purplei2p/i2pd:latest,purplei2p/i2pd:latest-release,purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7
push: true
- name: Create and push release manifest to GHCR
if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
inputs: ghcr.io/purplei2p/i2pd:latest,ghcr.io/purplei2p/i2pd:latest-release,ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7
push: true
- name: Checkout
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create and push latest manifest image to Docker Hub
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
inputs: purplei2p/i2pd:latest
images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7
push: true
- name: Create and push latest manifest image to GHCR
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
inputs: ghcr.io/purplei2p/i2pd:latest
images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7
push: true
- name: Store release version to env
if: ${{ startsWith(github.ref, 'refs/tags/') }}
run: echo "RELEASE_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV
- name: Create and push release manifest to Docker Hub
if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
inputs: purplei2p/i2pd:latest,purplei2p/i2pd:latest-release,purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7
push: true
- name: Create and push release manifest to GHCR
if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
inputs: ghcr.io/purplei2p/i2pd:latest,ghcr.io/purplei2p/i2pd:latest-release,ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7
push: true

@ -1,194 +1,6 @@
# for this file format description,
# see https://github.com/olivierlacan/keep-a-changelog
## [2.52.0] - 2024-05-12
### Added
- Separate threads for persisting RouterInfos and profiles to disk
- Give preference to address with direct connection
- Exclude addresses with incorrect static or intro key
- Avoid two firewalled routers in the row in tunnel
- Drop unsolicited database search replies
### Changed
- Increase number of hashes to 16 in exploratory lookup reply
- Reduce number of a RouterInfo lookup attempts to 5
- Reset stream RTO if outbound tunnel was changed
- Insert previously excluded floodfill back when successfully connected
- Increase maximum stream resend attempts to 9
- Reply to exploratory lookups with only confirmed routers if low tunnel build rate
- Don't accept too old RouterInfo
- Build client tunnels through confirmed routers only if low tunnel build rate
- Manage netDb requests more frequently
- Don't reply with closer than us only floodfills for lookup
### Fixed
- Crash on router lookup if exploratory pool is not ready
- Race condition in excluded peers for next lookup
- Excessive number of lookups for same destination
- Race condition with transport peers during shutdown
- Corrupted RouterInfo files
## [2.51.0] - 2024-04-06
### Added
- Non-blocking mode for UDP sockets
- Set SSU2 socket buffer size based on bandwidth limit
- Encrypted tunnel tests
- Support for multiple UDP server tunnels on one destination
- Publish medium congestion indication
- Local domain sockets for SOCKS proxy upstream
- Tunnel status "declined" in web console
- SAM error reply "Incompatible crypto" if remote destination has incompatible crypto
- Reduce amount of traffic by handling local message drops
- Keep SSU2 socket open even if it fails to bind
- Lower SSU2 resend traffic spikes
- Expiration for messages in SSU2 send queue
- Use EWMA for stream RTT estimation
- Request choking delay if too many NACKs in stream
- Allow 0ms latency for tunnel
- Randomize tunnels selection for tests
### Changed
- Upstream SOCKS proxy from SOCKS4 to SOCKS5
- Transit tunnels limit to 4 bytes. Default value to 10K
- Reply CANT_REACH_PEER if connect to ourselves in SAM
- Don't send already expired I2NP messages
- Use monotonic timer to measure tunnel test latency
- Standard NTCP2 frame doesn't exceed 16K
- Always send request through tunnels in case of restricted routes
- Don't delete connected routers from NetDb
- Send lookup reply directly to reply tunnel gateway if possible
- Reduce unreachable router ban interval to 8 minutes
- Don't request banned routers / don't try to connect to unreachable router
- Consider 'M' routers as low bandwidth
- Limit minimal received SSU2 packet size to 40 bytes
- Bob picks peer test session only if Charlie's address supports peer testing
- Reject peer test msg 2 if peer testing is not supported
- Don't request termination if SSU2 session was not established
- Set maximum SSU2 queue size depending on RTT value
- New streaming RTT calculation algorithm
- Don't double initial RTO for streams when changing tunnels
- Restore failed tunnel if test or data for inbound tunnel received
- Don't fail last remaining tunnel in pool
- Publish LeasetSet again if local destination was not ready or no tunnels
- Make more attempts to pick high bandwidth hop for client tunnel
- Reduced SSU2 session termination timeout to 165 seconds
- Reseeds list
### Fixed
- ECIESx25519 symmetric key tagset early expiration
- Encrypted LeaseSet lookup
- Outbound tunnel build fails if it's endpoint is the same as reply tunnel gateway
- I2PControl RouterManager returns invalid JSON when unknown params are passed
- Mix of data between different UDP sessions on the same server
- TARGET_OS_SIMULATOR check
- Handling of "reservedrange" param
- New NTCP2 session gets teminated upon termination of old one
- New SSU2 session gets teminated upon termination of old one
- Peer test to non-supporting router
- Streaming ackThrough off 1 if number of NACKs exceeds 255
- Race condition in ECIESx25519 tags table
- Good tunnel becomes failed
- Crash when packet comes to terminated stream
- Stream hangs during LeaseSet update
## [2.50.2] - 2024-01-06
###Fixed
- Crash with OpenSSL 3.2.0
- False positive clock skew detection
## [2.50.1] - 2023-12-23
###Fixed
- Support for new EdDSA usage behavior in OpenSSL 3.2.0
## [2.50.0] - 2023-12-18
### Added
- Support of concurrent ACCEPTs on SAM 3.1
- Haiku OS support
- Low bandwidth and far routers can expire before 1 hour
### Changed
- Don't pick too active peer for first hop
- Try peer test again if status is Unknown
- Send peer tests with random delay
- Reseeds list
### Fixed
- XSS vulnerability in addresshelper
- Publishing NAT64 ipv6 addresses
- Deadlock in AsyncSend callback
## [2.49.0] - 2023-09-18
### Added
- Handle SOCK5 authorization with empty user/password
- Drop incoming transport sessions from too old or from future routers
- Memory pool for router profiles
- Allow 0 hops in explicitPeers
### Changed
- Separate network and testing status
- Remove AVX code
- Improve NTCP2 transport session logging
- Select router with ipv4 for tunnel endpoint
- Consider all addresses non-published for U and H routers even if they have host/port
- Don't pick completely unreachable routers for tunnels
- Exclude SSU1 introducers from SSU2 addresses
- Don't create paired inbound tunnel if length is different
- Remove introducer from RouterInfo after 60 minutes
- Reduce SSU2 keep alive interval and add keep alive interval variance
- Don't pick too old sessions for introducer
### Fixed
- Version of the subnegotiation in user/password SOCKS5 response
- Send keepalive for existing session with introducer
- Buffer offset for EVP_EncryptFinal_ex() to include outlen
- Termination block size processing for transport sessions
- Crash if deleted BOB destination was shared between few BOB sessions
- Introducers with zero tag
- Padding for SSU2 path response
## [2.48.0] - 2023-06-12
### Added
- Allow user/password authentication method for SOCK5 proxy
- Publish reject all congestion cap 'G' if transit is not accepted
- 'critical' log level
- Print b32 on webconsole destination page
- Webconsole button to drop a remote LeaseSet
- limits.zombies param - minimum percentage of successfully created tunnels for routers cleanup
- Recognize real routers if successfully connected or responded to tunnel build request
### Changed
- Bypass slow transport sessions for first hop selection
- Limit AESNI inline asm to x86/x64
- Create smaller I2NP packets if possible
- Make router unreachable if AEAD tag verification fails in SessionCreated
- Don't include a router to floodfills list until it's confirmed as real
- Drop LeaseSet store request if not floodfill
- Bypass medium congestion('D') routers for client tunnels
- Publish encrypted RouterInfo through tunnels
- Check if s is valid x25519 public key
- Check if socket is open before sending data in SSU2
### Fixed
- Webconsole empty page if destination is not found
- i2p.streaming.answerPings param
- Reload tunnels
- Address caps for unspecified ipv6 address
- Incomplete HTTP headers in I2P tunnels
- SSU2 socket network exceptions on Windows
- Use of 'server' type tunnel port as inport (#1936)
## [2.47.0] - 2023-03-11
### Added
- Congestion caps
- SAM UDP port parameter
- Support domain addresses for yggdrasil reseeds
### Changed
- DHT for floodfills instead plain list
- Process router's messages in separate thread
- Don't publish non-reachable router
- Send and check target destination in first streaming SYN packet
- Reseeds list
### Fixed
- Memory leak in windows network state detection
- Reseed attempts from invalid address
## [2.46.1] - 2023-02-20
### Fixed
- Race condition while getting router's peer profile
- Creation of new router.info
- Displaying LeaseSets in the webconsole
- Crash when processing ACK request
## [2.46.0] - 2023-02-15
### Added
- Limit number of acked SSU2 packets to 511

@ -1,4 +1,4 @@
Copyright (c) 2013-2023, The PurpleI2P Project
Copyright (c) 2013-2020, The PurpleI2P Project
All rights reserved.

@ -67,22 +67,17 @@ else ifneq (, $(findstring linux, $(SYS))$(findstring gnu, $(SYS)))
else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS)))
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
include Makefile.bsd
else ifneq (, $(findstring haiku, $(SYS)))
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
include Makefile.haiku
else # not supported
$(error Not supported platform)
endif
INCFLAGS += -I$(LIB_SRC_DIR) -I$(LIB_CLIENT_SRC_DIR) -I$(LANG_SRC_DIR)
DEFINES += -DOPENSSL_SUPPRESS_DEPRECATED
NEEDED_CXXFLAGS += -MMD -MP
ifeq ($(USE_GIT_VERSION),yes)
GIT_VERSION := $(shell git describe --tags)
DEFINES += -DGITVER=$(GIT_VERSION)
NEEDED_CXXFLAGS += -DGITVER=\"$(GIT_VERSION)\"
endif
NEEDED_CXXFLAGS += -MMD -MP -I$(LIB_SRC_DIR) -I$(LIB_CLIENT_SRC_DIR) -I$(LANG_SRC_DIR) -DOPENSSL_SUPPRESS_DEPRECATED
LIB_OBJS += $(patsubst %.cpp,obj/%.o,$(LIB_SRC))
LIB_CLIENT_OBJS += $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC))
LANG_OBJS += $(patsubst %.cpp,obj/%.o,$(LANG_SRC))
@ -115,13 +110,13 @@ wrapper: api_client $(SHLIB_WRAP) $(ARLIB_WRAP)
## custom FLAGS to work at build-time.
obj/%.o: %.cpp | mk_obj_dir
$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(DEFINES) $(INCFLAGS) -c -o $@ $<
$(CXX) $(CXXFLAGS) $(NEEDED_CXXFLAGS) $(INCFLAGS) -c -o $@ $<
# '-' is 'ignore if missing' on first run
-include $(DEPS)
$(I2PD): $(DAEMON_OBJS) $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG)
$(CXX) $(DEFINES) $(LDFLAGS) -o $@ $^ $(LDLIBS)
$(CXX) -o $@ $(LDFLAGS) $^ $(LDLIBS)
$(SHLIB): $(LIB_OBJS)
ifneq ($(USE_STATIC),yes)

@ -6,13 +6,7 @@ CXXFLAGS ?= ${CXX_DEBUG} -Wall -Wextra -Wno-unused-parameter -pedantic -Wno-misl
## (e.g. -fstack-protector-strong -Wformat -Werror=format-security), we do not want to remove
## -std=c++11. If you want to remove this variable please do so in a way that allows setting
## custom FLAGS to work at build-time.
CXXVER := $(shell $(CXX) -dumpversion)
ifeq (${CXXVER}, "4.2.1") # older clang always returned 4.2.1
NEEDED_CXXFLAGS = -std=c++11
else # newer versions support C++17
NEEDED_CXXFLAGS = -std=c++17
endif
DEFINES = -D_GLIBCXX_USE_NANOSLEEP=1
NEEDED_CXXFLAGS = -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1
INCFLAGS = -I/usr/include/ -I/usr/local/include/
LDFLAGS = ${LD_DEBUG} -Wl,-rpath,/usr/local/lib -L/usr/local/lib
LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread

@ -1,10 +0,0 @@
CXX = g++
CXXFLAGS := -Wall -std=c++11
INCFLAGS = -I/system/develop/headers
DEFINES = -D_DEFAULT_SOURCE -D_GNU_SOURCE
LDLIBS = -lbe -lbsd -lnetwork -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
ifeq ($(USE_UPNP),yes)
DEFINES += -DUSE_UPNP
LDLIBS += -lminiupnpc
endif

@ -1,40 +1,41 @@
# root directory holding homebrew
BREWROOT = /opt/homebrew
BREWROOT = /usr/local
BOOSTROOT = ${BREWROOT}/opt/boost
SSLROOT = ${BREWROOT}/opt/openssl@1.1
UPNPROOT = ${BREWROOT}/opt/miniupnpc
CXXFLAGS = ${CXX_DEBUG} -Wall -std=c++11 -DMAC_OSX -Wno-overloaded-virtual
INCFLAGS = -I${SSLROOT}/include -I${BOOSTROOT}/include
LDFLAGS = ${LD_DEBUG}
CXXFLAGS ?= ${CXX_DEBUG} -Wall -Wno-overloaded-virtual
NEEDED_CXXFLAGS ?= -std=c++11
INCFLAGS ?= -I${SSLROOT}/include -I${BOOSTROOT}/include
LDFLAGS ?= ${LD_DEBUG}
DEFINES += -DMAC_OSX
ifndef TRAVIS
CXX = clang++
endif
ifeq ($(USE_STATIC),yes)
LDLIBS = -lz ${SSLROOT}/lib/libcrypto.a ${SSLROOT}/lib/libssl.a ${BOOSTROOT}/lib/libboost_system.a ${BOOSTROOT}/lib/libboost_date_time.a ${BOOSTROOT}/lib/libboost_filesystem.a ${BOOSTROOT}/lib/libboost_program_options.a
ifeq ($(USE_UPNP),yes)
LDLIBS += ${UPNPROOT}/lib/libminiupnpc.a
endif
LDLIBS += -lpthread -ldl
LDLIBS = -lz ${SSLROOT}/lib/libcrypto.a ${SSLROOT}/lib/libssl.a ${BOOSTROOT}/lib/libboost_system.a ${BOOSTROOT}/lib/libboost_date_time.a ${BOOSTROOT}/lib/libboost_filesystem.a ${BOOSTROOT}/lib/libboost_program_options.a -lpthread
else
LDFLAGS += -L${SSLROOT}/lib -L${BOOSTROOT}/lib
LDLIBS = -lz -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread
ifeq ($(USE_UPNP),yes)
LDFLAGS += -L${UPNPROOT}/lib
LDLIBS += -lminiupnpc
endif
endif
ifeq ($(USE_UPNP),yes)
DEFINES += -DUSE_UPNP
LDFLAGS += -ldl
CXXFLAGS += -DUSE_UPNP
INCFLAGS += -I${UPNPROOT}/include
ifeq ($(USE_STATIC),yes)
LDLIBS += ${UPNPROOT}/lib/libminiupnpc.a
else
LDFLAGS += -L${UPNPROOT}/lib
LDLIBS += -lminiupnpc
endif
endif
# OSX Notes
# http://www.hutsby.net/2011/08/macs-with-aes-ni.html
# Seems like all recent Mac's have AES-NI, after firmware upgrade 2.2
# Found no good way to detect it from command line. TODO: Might be some osx sysinfo magic
ifeq ($(USE_AESNI),yes)
ifneq (, $(findstring i386, $(SYS))$(findstring i686, $(SYS))$(findstring x86_64, $(SYS))) # only x86-based CPU supports that
NEEDED_CXXFLAGS += -maes
DEFINES += -D__AES__
endif
CXXFLAGS += -D__AES__ -maes
endif
install: all

@ -58,13 +58,12 @@ endif
# UPNP Support (miniupnpc 1.5 and higher)
ifeq ($(USE_UPNP),yes)
DEFINES += -DUSE_UPNP
NEEDED_CXXFLAGS += -DUSE_UPNP
endif
ifeq ($(USE_AESNI),yes)
ifneq (, $(findstring i386, $(SYS))$(findstring i686, $(SYS))$(findstring x86_64, $(SYS))) # only x86-based CPU supports that
NEEDED_CXXFLAGS += -maes
DEFINES += -D__AES__
NEEDED_CXXFLAGS += -D__AES__ -maes
endif
endif

@ -4,50 +4,49 @@ USE_WIN32_APP := yes
WINDRES = windres
CXXFLAGS := $(CXX_DEBUG) -fPIC -msse
INCFLAGS := -I$(DAEMON_SRC_DIR) -IWin32
LDFLAGS := ${LD_DEBUG} -static -fPIC -msse
INCFLAGS = -I$(DAEMON_SRC_DIR) -IWin32
LDFLAGS := ${LD_DEBUG} -static
NEEDED_CXXFLAGS += -std=c++17
DEFINES += -DWIN32_LEAN_AND_MEAN
NEEDED_CXXFLAGS += -std=c++17 -DWIN32_LEAN_AND_MEAN
# Boost libraries suffix
BOOST_SUFFIX = -mt
# UPNP Support
ifeq ($(USE_UPNP),yes)
DEFINES += -DUSE_UPNP -DMINIUPNP_STATICLIB
CXXFLAGS += -DUSE_UPNP -DMINIUPNP_STATICLIB
LDLIBS = -lminiupnpc
endif
LDLIBS += \
$(MINGW_PREFIX)/lib/libboost_system-mt.a \
$(MINGW_PREFIX)/lib/libboost_date_time-mt.a \
$(MINGW_PREFIX)/lib/libboost_filesystem-mt.a \
$(MINGW_PREFIX)/lib/libboost_program_options-mt.a \
$(MINGW_PREFIX)/lib/libssl.a \
$(MINGW_PREFIX)/lib/libcrypto.a \
$(MINGW_PREFIX)/lib/libz.a \
-lboost_system$(BOOST_SUFFIX) \
-lboost_date_time$(BOOST_SUFFIX) \
-lboost_filesystem$(BOOST_SUFFIX) \
-lboost_program_options$(BOOST_SUFFIX) \
-lssl \
-lcrypto \
-lz \
-lwsock32 \
-lws2_32 \
-liphlpapi \
-lcrypt32 \
-lgdi32 \
-liphlpapi \
-lole32 \
-luuid \
-lpthread
ifeq ($(USE_WIN32_APP), yes)
DEFINES += -DWIN32_APP
NEEDED_CXXFLAGS += -DWIN32_APP
LDFLAGS += -mwindows
DAEMON_RC += Win32/Resource.rc
DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC))
endif
ifeq ($(USE_WINXP_FLAGS), yes)
DEFINES += -DWINVER=0x0501 -D_WIN32_WINNT=0x0501
NEEDED_CXXFLAGS += -DWINVER=0x0501 -D_WIN32_WINNT=0x0501
endif
ifeq ($(USE_AESNI),yes)
NEEDED_CXXFLAGS += -maes
LDFLAGS += -maes
DEFINES += -D__AES__
NEEDED_CXXFLAGS += -D__AES__ -maes
endif
ifeq ($(USE_ASLR),yes)
@ -55,4 +54,4 @@ ifeq ($(USE_ASLR),yes)
endif
obj/%.o : %.rc | mk_obj_dir
$(WINDRES) $(DEFINES) $(INCFLAGS) --preprocessor-arg=-MMD --preprocessor-arg=-MP --preprocessor-arg=-MF$@.d -i $< -o $@
$(WINDRES) -i $< -o $@

@ -1,10 +1,10 @@
CXX = clang++
CXXFLAGS := ${CXX_DEBUG} -Wall -std=c++11
CXXFLAGS := ${CXX_DEBUG} -Wall -std=c++11 -DMAC_OSX
INCFLAGS = -I/usr/local/include
DEFINES := -DMAC_OSX
LDFLAGS := -Wl,-rpath,/usr/local/lib -L/usr/local/lib
LDFLAGS += -Wl,-dead_strip
LDFLAGS += -Wl,-dead_strip_dylibs
LDFLAGS += -Wl,-bind_at_load
ifeq ($(USE_STATIC),yes)
LDLIBS = -lz /usr/local/lib/libcrypto.a /usr/local/lib/libssl.a /usr/local/lib/libboost_system.a /usr/local/lib/libboost_date_time.a /usr/local/lib/libboost_filesystem.a /usr/local/lib/libboost_program_options.a -lpthread
@ -14,7 +14,7 @@ endif
ifeq ($(USE_UPNP),yes)
LDFLAGS += -ldl
DEFINES += -DUSE_UPNP
CXXFLAGS += -DUSE_UPNP
ifeq ($(USE_STATIC),yes)
LDLIBS += /usr/local/lib/libminiupnpc.a
else
@ -22,12 +22,8 @@ ifeq ($(USE_UPNP),yes)
endif
endif
OSARCH = $(shell uname -p)
ifneq ($(OSARCH),powerpc)
ifeq ($(USE_AESNI),yes)
CXXFLAGS += -D__AES__ -maes
else
CXXFLAGS += -msse
endif
ifeq ($(USE_AESNI),yes)
CXXFLAGS += -D__AES__ -maes
else
CXXFLAGS += -msse
endif

@ -99,23 +99,13 @@ Current status: [![Crowdin](https://badges.crowdin.net/i2pd/localized.svg)](http
Donations
---------
**E-Mail**: ```i2porignal at yandex.com```
**BTC**: ```3MDoGJW9TLMTCDGrR9bLgWXfm6sjmgy86f```
**LTC**: ```LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59```
**ETH**: ```0x9e5bac70d20d1079ceaa111127f4fb3bccce379d```
**GST**: ```GbD2JSQHBHCKLa9WTHmigJRpyFgmBj4woG```
**DASH**: ```Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF```
**ZEC**: ```t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ```
**ANC**: ```AQJYweYYUqM1nVfLqfoSMpUMfzxvS4Xd7z```
**XMR**: ```497pJc7X4xqKvcLBLpSUtRgWqMMyo24u4btCos3cak6gbMkpobgSU6492ztUcUBghyeHpYeczB55s38NpuHoH5WGNSPDRMH```
BTC: 3MDoGJW9TLMTCDGrR9bLgWXfm6sjmgy86f
LTC: LKQirrYrDeTuAPnpYq5y7LVKtywfkkHi59
ETH: 0x9e5bac70d20d1079ceaa111127f4fb3bccce379d
DASH: Xw8YUrQpYzP9tZBmbjqxS3M97Q7v3vJKUF
ZEC: t1cTckLuXsr1dwVrK4NDzfhehss4NvMadAJ
GST: GbD2JSQHBHCKLa9WTHmigJRpyFgmBj4woG
XMR: 497pJc7X4xqKvcLBLpSUtRgWqMMyo24u4btCos3cak6gbMkpobgSU6492ztUcUBghyeHpYeczB55s38NpuHoH5WGNSPDRMH
License
-------

@ -47,7 +47,7 @@ namespace util
I2PService service((PSTR)SERVICE_NAME);
if (!I2PService::Run(service))
{
LogPrint(eLogCritical, "Daemon: Service failed to run w/err 0x%08lx\n", GetLastError());
LogPrint(eLogError, "Daemon: Service failed to run w/err 0x%08lx\n", GetLastError());
return false;
}
return false;
@ -64,7 +64,7 @@ namespace util
//setlocale(LC_ALL, "Russian");
setlocale(LC_TIME, "C");
#ifdef WIN32_APP
if (!i2p::win32::StartWin32App (isDaemon)) return false;
if (!i2p::win32::StartWin32App ()) return false;
#endif
bool ret = Daemon_Singleton::start();
if (ret && i2p::log::Logger().GetLogType() == eLogFile)

@ -1,36 +1,36 @@
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
#include "winres.h"
#undef APSTUDIO_READONLY_SYMBOLS
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
MAINICON ICON "mask.ico"
#endif // English (United States) resources
#ifndef APSTUDIO_INVOKED
#include "Resource.rc2"
#endif // not APSTUDIO_INVOKED
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
#include "winres.h"
#undef APSTUDIO_READONLY_SYMBOLS
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#ifdef APSTUDIO_INVOKED
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
MAINICON ICON "mask.ico"
#endif // English (United States) resources
#ifndef APSTUDIO_INVOKED
#include "Resource.rc2"
#endif // not APSTUDIO_INVOKED

@ -2,7 +2,7 @@
#error this file is not editable by Microsoft Visual C++
#endif //APSTUDIO_INVOKED
#include "version.h"
#include "../libi2pd/version.h"
VS_VERSION_INFO VERSIONINFO
FILEVERSION I2PD_VERSION_MAJOR,I2PD_VERSION_MINOR,I2PD_VERSION_MICRO,I2PD_VERSION_PATCH
@ -25,7 +25,7 @@ BEGIN
VALUE "FileDescription", "C++ I2P daemon"
VALUE "FileVersion", I2PD_VERSION
VALUE "InternalName", CODENAME
VALUE "LegalCopyright", "Copyright (C) 2013-2023, The PurpleI2P Project"
VALUE "LegalCopyright", "Copyright (C) 2013-2022, The PurpleI2P Project"
VALUE "OriginalFilename", "i2pd"
VALUE "ProductName", "Purple I2P"
VALUE "ProductVersion", I2P_VERSION

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2024, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -45,7 +45,6 @@ namespace i2p
namespace win32
{
DWORD g_GracefulShutdownEndtime = 0;
bool g_isWinService;
static void ShowPopupMenu (HWND hWnd, POINT *curpos, int wDefaultItem)
{
@ -145,37 +144,30 @@ namespace win32
s << bytes << " Bytes\n";
}
static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, bool testing, RouterError error)
static void ShowNetworkStatus (std::stringstream& s, RouterStatus status)
{
switch (status)
{
case eRouterStatusOK: s << "OK"; break;
case eRouterStatusTesting: s << "Test"; break;
case eRouterStatusFirewalled: s << "FW"; break;
case eRouterStatusUnknown: s << "Unk"; break;
case eRouterStatusProxy: s << "Proxy"; break;
case eRouterStatusMesh: s << "Mesh"; break;
default: s << "Unk";
};
if (testing)
s << " (Test)";
if (error != eRouterErrorNone)
if (i2p::context.GetError () != eRouterErrorNone)
{
switch (error)
switch (i2p::context.GetError ())
{
case eRouterErrorClockSkew:
s << " - " << tr("Clock skew");
s << " - Clock skew";
break;
case eRouterErrorOffline:
s << " - " << tr("Offline");
s << " - Offline";
break;
case eRouterErrorSymmetricNAT:
s << " - " << tr("Symmetric NAT");
break;
case eRouterErrorFullConeNAT:
s << " - " << tr("Full cone NAT");
break;
case eRouterErrorNoDescriptors:
s << " - " << tr("No Descriptors");
s << " - Symmetric NAT";
break;
default: ;
}
@ -186,11 +178,11 @@ namespace win32
{
s << "\n";
s << "Status: ";
ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetTesting(), i2p::context.GetError ());
ShowNetworkStatus (s, i2p::context.GetStatus ());
if (i2p::context.SupportsV6 ())
{
s << " / ";
ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetTestingV6(), i2p::context.GetErrorV6 ());
ShowNetworkStatus (s, i2p::context.GetStatusV6 ());
}
s << "; ";
s << "Success Rate: " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate() << "%\n";
@ -355,9 +347,6 @@ namespace win32
}
}
}
#if (__cplusplus >= 201703L) // C++ 17 or higher
[[fallthrough]];
#endif
}
case WM_TRAYICON:
{
@ -427,9 +416,8 @@ namespace win32
return DefWindowProc( hWnd, uMsg, wParam, lParam);
}
bool StartWin32App (bool isWinService)
bool StartWin32App ()
{
g_isWinService = isWinService;
if (FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd")))
{
MessageBox(NULL, TEXT("I2Pd is running already"), TEXT("Warning"), MB_OK);
@ -458,9 +446,7 @@ namespace win32
MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST);
return false;
}
// COM requires message loop to work, which is not implemented in service mode
if (!g_isWinService)
SubscribeToEvents();
SubscribeToEvents();
return true;
}
@ -480,8 +466,7 @@ namespace win32
HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"));
if (hWnd)
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_EXIT, 0), 0);
else if(!g_isWinService)
UnSubscribeFromEvents();
// UnSubscribeFromEvents(); // TODO: understand why unsubscribing crashes app
UnregisterClass (I2PD_WIN32_CLASSNAME, GetModuleHandle(NULL));
}

@ -17,7 +17,7 @@ namespace win32
{
extern DWORD g_GracefulShutdownEndtime;
bool StartWin32App (bool isWinService);
bool StartWin32App ();
void StopWin32App ();
int RunWin32App ();
bool GracefulShutdown ();

@ -15,7 +15,6 @@ IUnknown *pUnknown = nullptr;
INetworkListManager *pNetworkListManager = nullptr;
IConnectionPointContainer *pCPContainer = nullptr;
IConnectionPoint *pConnectPoint = nullptr;
CNetworkListManagerEvent *pNetEvent = nullptr;
DWORD Cookie = 0;
void SubscribeToEvents()
@ -30,11 +29,7 @@ void SubscribeToEvents()
if (SUCCEEDED(Result))
{
VARIANT_BOOL IsConnect = VARIANT_FALSE;
#if defined(_MSC_VER)
Result = pNetworkListManager->get_IsConnectedToInternet(&IsConnect);
#else
Result = pNetworkListManager->IsConnectedToInternet(&IsConnect);
#endif
if (SUCCEEDED(Result)) {
i2p::transport::transports.SetOnline (true);
LogPrint(eLogInfo, "NetState: Current state: ", IsConnect == VARIANT_TRUE ? "connected" : "disconnected");
@ -46,8 +41,8 @@ void SubscribeToEvents()
Result = pCPContainer->FindConnectionPoint(IID_INetworkListManagerEvents, &pConnectPoint);
if(SUCCEEDED(Result))
{
pNetEvent = new CNetworkListManagerEvent;
Result = pConnectPoint->Advise((IUnknown *)pNetEvent, &Cookie);
CNetworkListManagerEvent *NetEvent = new CNetworkListManagerEvent;
Result = pConnectPoint->Advise((IUnknown *)NetEvent, &Cookie);
if (SUCCEEDED(Result))
LogPrint(eLogInfo, "NetState: Successfully subscribed to NetworkListManagerEvent messages");
else
@ -64,7 +59,6 @@ void SubscribeToEvents()
void UnSubscribeFromEvents()
{
LogPrint(eLogInfo, "NetState: Unsubscribing from NetworkListManagerEvents");
try
{
if (pConnectPoint) {
@ -72,25 +66,14 @@ void UnSubscribeFromEvents()
pConnectPoint->Release();
}
if (pNetEvent)
{
pNetEvent->Release();
}
if (pCPContainer)
{
pCPContainer->Release();
}
if (pNetworkListManager)
{
pNetworkListManager->Release();
}
if (pUnknown)
{
pUnknown->Release();
}
CoUninitialize();
}

@ -15,7 +15,7 @@
#include "Log.h"
#include "Transports.h"
class CNetworkListManagerEvent final : public INetworkListManagerEvents
class CNetworkListManagerEvent : public INetworkListManagerEvents
{
public:
CNetworkListManagerEvent() : m_ref(1) { }
@ -23,15 +23,17 @@ public:
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)
{
HRESULT Result = S_OK;
if (IsEqualIID(riid, IID_IUnknown)) {
*ppvObject = (IUnknown *)this;
} else if (IsEqualIID(riid ,IID_INetworkListManagerEvents)) {
*ppvObject = (INetworkListManagerEvents *)this;
} else {
return E_NOINTERFACE;
Result = E_NOINTERFACE;
}
AddRef();
return S_OK;
return Result;
}
ULONG STDMETHODCALLTYPE AddRef()

@ -21,7 +21,7 @@ BOOL I2PService::isService()
HWINSTA hWinStation = GetProcessWindowStation();
if (hWinStation != NULL)
{
USEROBJECTFLAGS uof = { FALSE, FALSE, 0 };
USEROBJECTFLAGS uof = { 0 };
if (GetUserObjectInformation(hWinStation, UOI_FLAGS, &uof, sizeof(USEROBJECTFLAGS), NULL) && ((uof.dwFlags & WSF_VISIBLE) == 0))
{
bIsService = TRUE;
@ -119,12 +119,12 @@ void I2PService::Start(DWORD dwArgc, PSTR *pszArgv)
}
catch (DWORD dwError)
{
LogPrint(eLogCritical, "Win32Service: Start error: ", dwError);
LogPrint(eLogError, "Win32Service: Start error: ", dwError);
SetServiceStatus(SERVICE_STOPPED, dwError);
}
catch (...)
{
LogPrint(eLogCritical, "Win32Service: failed to start: ", EVENTLOG_ERROR_TYPE);
LogPrint(eLogError, "Win32Service: failed to start: ", EVENTLOG_ERROR_TYPE);
SetServiceStatus(SERVICE_STOPPED);
}
}
@ -162,7 +162,7 @@ void I2PService::Stop()
}
catch (...)
{
LogPrint(eLogCritical, "Win32Service: Failed to stop: ", EVENTLOG_ERROR_TYPE);
LogPrint(eLogError, "Win32Service: Failed to stop: ", EVENTLOG_ERROR_TYPE);
SetServiceStatus(dwOriginalState);
}
}
@ -191,12 +191,12 @@ void I2PService::Pause()
}
catch (DWORD dwError)
{
LogPrint(eLogCritical, "Win32Service: Pause error: ", dwError);
LogPrint(eLogError, "Win32Service: Pause error: ", dwError);
SetServiceStatus(SERVICE_RUNNING);
}
catch (...)
{
LogPrint(eLogCritical, "Win32Service: Failed to pause: ", EVENTLOG_ERROR_TYPE);
LogPrint(eLogError, "Win32Service: Failed to pause: ", EVENTLOG_ERROR_TYPE);
SetServiceStatus(SERVICE_RUNNING);
}
}
@ -215,12 +215,12 @@ void I2PService::Continue()
}
catch (DWORD dwError)
{
LogPrint(eLogCritical, "Win32Service: Continue error: ", dwError);
LogPrint(eLogError, "Win32Service: Continue error: ", dwError);
SetServiceStatus(SERVICE_PAUSED);
}
catch (...)
{
LogPrint(eLogCritical, "Win32Service: Failed to resume: ", EVENTLOG_ERROR_TYPE);
LogPrint(eLogError, "Win32Service: Failed to resume: ", EVENTLOG_ERROR_TYPE);
SetServiceStatus(SERVICE_PAUSED);
}
}
@ -238,11 +238,11 @@ void I2PService::Shutdown()
}
catch (DWORD dwError)
{
LogPrint(eLogCritical, "Win32Service: Shutdown error: ", dwError);
LogPrint(eLogError, "Win32Service: Shutdown error: ", dwError);
}
catch (...)
{
LogPrint(eLogCritical, "Win32Service: Failed to shut down: ", EVENTLOG_ERROR_TYPE);
LogPrint(eLogError, "Win32Service: Failed to shut down: ", EVENTLOG_ERROR_TYPE);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

11
build/.gitignore vendored

@ -2,12 +2,7 @@
/CMakeFiles/
/Testing/
/tests/
/.ninja_*
/arch.c
/build.ninja
/i2pd
/i2pd.exe
/i2pd.exe.debug
/libi2pd.a
/libi2pdclient.a
/libi2pdlang.a
@ -17,11 +12,7 @@
/CPackSourceConfig.cmake
/CTestTestfile.cmake
/install_manifest.txt
/Makefile
/arch.c
# windows build script
i2pd*.zip
build*.log
# MVS project files
*.vcxproj
*.vcxproj.filters
*.sln

@ -1,32 +1,14 @@
cmake_minimum_required(VERSION 3.7)
if(${CMAKE_VERSION} VERSION_LESS 3.22)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
else()
cmake_policy(VERSION 3.22)
endif()
cmake_policy(VERSION 3.7)
project("i2pd")
# for debugging
#set(CMAKE_VERBOSE_MAKEFILE on)
# paths
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules")
set(CMAKE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..")
set(LIBI2PD_SRC_DIR ${CMAKE_SOURCE_DIR}/libi2pd)
set(LIBI2PD_CLIENT_SRC_DIR ${CMAKE_SOURCE_DIR}/libi2pd_client)
set(LANG_SRC_DIR ${CMAKE_SOURCE_DIR}/i18n)
set(DAEMON_SRC_DIR ${CMAKE_SOURCE_DIR}/daemon)
include(Version)
set_version("${LIBI2PD_SRC_DIR}/version.h" PROJECT_VERSION)
project(
i2pd
VERSION ${PROJECT_VERSION}
HOMEPAGE_URL "https://i2pd.website/"
LANGUAGES C CXX
)
# Win32 build with cmake is not supported
if(WIN32 OR MSVC OR MSYS OR MINGW)
message(SEND_ERROR "cmake build for windows is not supported. Please use MSYS2 with makefiles in project root.")
endif()
# configurable options
option(WITH_AESNI "Use AES-NI instructions set" ON)
@ -44,22 +26,27 @@ IF(BUILD_TESTING)
enable_testing()
ENDIF()
# paths
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules")
set(CMAKE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..")
# Handle paths nicely
include(GNUInstallDirs)
# Architecture
# architecture
include(TargetArch)
target_architecture(ARCHITECTURE)
include(CheckAtomic)
if(WITH_STATIC)
if(MSVC)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()
endif()
set(LIBI2PD_SRC_DIR ../libi2pd)
set(LIBI2PD_CLIENT_SRC_DIR ../libi2pd_client)
set(LANG_SRC_DIR ../i18n)
set(DAEMON_SRC_DIR ../daemon)
include_directories(${LIBI2PD_SRC_DIR})
include_directories(${LIBI2PD_CLIENT_SRC_DIR})
include_directories(${LANG_SRC_DIR})
include_directories(${DAEMON_SRC_DIR})
FILE(GLOB LIBI2PD_SRC ${LIBI2PD_SRC_DIR}/*.cpp)
add_library(libi2pd ${LIBI2PD_SRC})
set_target_properties(libi2pd PROPERTIES PREFIX "")
@ -70,9 +57,11 @@ if(WITH_LIBRARY)
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT Libraries)
# TODO Make libi2pd available to 3rd party projects via CMake as imported target
# FIXME This pulls stdafx
# install(EXPORT libi2pd DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()
include_directories(${LIBI2PD_CLIENT_SRC_DIR})
FILE(GLOB CLIENT_SRC ${LIBI2PD_CLIENT_SRC_DIR}/*.cpp)
add_library(libi2pdclient ${CLIENT_SRC})
set_target_properties(libi2pdclient PROPERTIES PREFIX "")
@ -85,7 +74,6 @@ if(WITH_LIBRARY)
COMPONENT Libraries)
endif()
include_directories(${LANG_SRC_DIR})
FILE(GLOB LANG_SRC ${LANG_SRC_DIR}/*.cpp)
add_library(libi2pdlang ${LANG_SRC})
set_target_properties(libi2pdlang PROPERTIES PREFIX "")
@ -98,8 +86,6 @@ if(WITH_LIBRARY)
COMPONENT Libraries)
endif()
include_directories(${DAEMON_SRC_DIR})
set(DAEMON_SRC
"${DAEMON_SRC_DIR}/Daemon.cpp"
"${DAEMON_SRC_DIR}/HTTPServer.cpp"
@ -109,22 +95,6 @@ set(DAEMON_SRC
"${DAEMON_SRC_DIR}/UPnP.cpp"
)
if(WIN32)
set(WIN32_SRC_DIR ${CMAKE_SOURCE_DIR}/Win32)
include_directories(${WIN32_SRC_DIR})
list(APPEND DAEMON_SRC
"${WIN32_SRC_DIR}/DaemonWin32.cpp"
"${WIN32_SRC_DIR}/Win32App.cpp"
"${WIN32_SRC_DIR}/Win32Service.cpp"
"${WIN32_SRC_DIR}/Win32NetState.cpp"
)
file(GLOB WIN32_RC ${WIN32_SRC_DIR}/*.rc)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWIN32_APP -DWIN32_LEAN_AND_MEAN -DNOMINMAX")
endif()
if(WITH_UPNP)
add_definitions(-DUSE_UPNP)
endif()
@ -132,44 +102,30 @@ endif()
if(WITH_GIT_VERSION)
include(GetGitRevisionDescription)
git_describe(GIT_VERSION)
add_definitions(-DGITVER=${GIT_VERSION})
add_definitions(-DGITVER="${GIT_VERSION}")
endif()
if(APPLE)
add_definitions(-DMAC_OSX)
endif()
if(HAIKU)
add_definitions(-D_DEFAULT_SOURCE -D_GNU_SOURCE)
endif()
if(MSVC)
add_definitions(-DWINVER=0x0600)
add_definitions(-D_WIN32_WINNT=0x0600)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch -Wno-unused-parameter")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic")
# TODO: The following is incompatible with static build and enabled hardening for OpenWRT.
# Multiple definitions of __stack_chk_fail(libssp & libc)
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -flto -s -ffunction-sections -fdata-sections")
set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections") # -flto is added from above
# check for c++17 & c++11 support
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++17" CXX17_SUPPORTED)
CHECK_CXX_COMPILER_FLAG("-std=c++11" CXX11_SUPPORTED)
if(CXX17_SUPPORTED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
elseif(CXX11_SUPPORTED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch -Wno-unused-parameter -Wno-uninitialized")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic")
# TODO: The following is incompatible with static build and enabled hardening for OpenWRT.
# Multiple definitions of __stack_chk_fail(libssp & libc)
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -flto -s")
endif()
set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -ffunction-sections -fdata-sections")
set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections") # -flto is added from above
# check for c++17 & c++11 support
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++17" CXX17_SUPPORTED)
CHECK_CXX_COMPILER_FLAG("-std=c++11" CXX11_SUPPORTED)
if(CXX17_SUPPORTED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
elseif(CXX11_SUPPORTED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
else()
message(SEND_ERROR "C++17 nor C++11 standard not seems to be supported by compiler. Too old version?")
endif()
message(SEND_ERROR "C++17 nor C++11 standard not seems to be supported by compiler. Too old version?")
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
@ -201,11 +157,8 @@ endif()
# Note: AES-NI and AVX is available on x86-based CPU's.
# Here also ARM64 implementation, but currently we don't support it.
# MSVC is not supported due to different ASM processing, so we hope OpenSSL has its own checks to run optimized code.
if(WITH_AESNI AND (ARCHITECTURE MATCHES "x86_64" OR ARCHITECTURE MATCHES "i386"))
if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes")
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes")
add_definitions(-D__AES__)
endif()
@ -235,36 +188,10 @@ set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
if(WITH_STATIC)
if(NOT MSVC)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
endif()
set(Boost_USE_STATIC_LIBS ON)
if(MSVC)
set(Boost_USE_STATIC_RUNTIME ON)
else()
set(Boost_USE_STATIC_RUNTIME OFF)
endif()
if(MSVC)
set(OPENSSL_MSVC_STATIC_RT ON)
endif()
set(Boost_USE_STATIC_RUNTIME ON)
set(OPENSSL_USE_STATIC_LIBS ON)
set(ZLIB_USE_STATIC_LIBS ON)
if(MSVC)
set(ZLIB_NAMES zlibstatic zlibstat)
else()
set(ZLIB_NAMES libz zlibstatic zlibstat zlib z)
endif()
if(WITH_UPNP)
set(MINIUPNPC_USE_STATIC_LIBS ON)
add_definitions(-DMINIUPNP_STATICLIB)
endif()
set(BUILD_SHARED_LIBS OFF)
if(${CMAKE_CXX_COMPILER} MATCHES ".*-openwrt-.*")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
# set(CMAKE_THREAD_LIBS_INIT "gcc_eh -Wl,--whole-archive -lpthread -Wl,--no-whole-archive")
@ -274,23 +201,17 @@ else()
# TODO: Consider separate compilation for LIBI2PD_SRC for library.
# No need in -fPIC overhead for binary if not interested in library
# HINT: revert c266cff CMakeLists.txt: compilation speed up
if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
endif()
add_definitions(-DBOOST_ATOMIC_DYN_LINK -DBOOST_SYSTEM_DYN_LINK -DBOOST_FILESYSTEM_DYN_LINK -DBOOST_PROGRAM_OPTIONS_DYN_LINK -DBOOST_DATE_TIME_DYN_LINK -DBOOST_REGEX_DYN_LINK)
if(WIN32)
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_STATIC_RUNTIME OFF)
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
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()
find_package(Boost REQUIRED COMPONENTS system filesystem program_options date_time OPTIONAL_COMPONENTS atomic)
if(NOT DEFINED Boost_FOUND)
find_package(Boost COMPONENTS system filesystem program_options date_time REQUIRED)
if(NOT DEFINED Boost_INCLUDE_DIRS)
message(SEND_ERROR "Boost is not found, or your boost version was below 1.46. Please download Boost!")
endif()
find_package(OpenSSL REQUIRED)
if(NOT DEFINED OPENSSL_FOUND)
if(NOT DEFINED OPENSSL_INCLUDE_DIR)
message(SEND_ERROR "Could not find OpenSSL. Please download and install it first!")
endif()
@ -315,6 +236,8 @@ endif()
# load includes
include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR})
include(CheckAtomic)
# show summary
message(STATUS "---------------------------------------")
message(STATUS "Build type : ${CMAKE_BUILD_TYPE}")
@ -330,34 +253,16 @@ message(STATUS " LIBRARY : ${WITH_LIBRARY}")
message(STATUS " BINARY : ${WITH_BINARY}")
message(STATUS " STATIC BUILD : ${WITH_STATIC}")
message(STATUS " UPnP : ${WITH_UPNP}")
if(WITH_GIT_VERSION)
message(STATUS " GIT VERSION : ${WITH_GIT_VERSION} (${GIT_VERSION})")
else()
message(STATUS " GIT VERSION : ${WITH_GIT_VERSION}")
endif()
message(STATUS " ADDRSANITIZER : ${WITH_ADDRSANITIZER}")
message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}")
message(STATUS "---------------------------------------")
if(WITH_BINARY)
if(WIN32)
add_executable("${PROJECT_NAME}" WIN32 ${DAEMON_SRC} ${WIN32_RC})
else()
add_executable("${PROJECT_NAME}" ${DAEMON_SRC})
endif()
if(WIN32)
list(APPEND MINGW_EXTRA "wsock32" "ws2_32" "iphlpapi")
# OpenSSL may require Crypt32 library on MSVC build, which is not added by CMake lesser than 3.21
if(MSVC AND ${CMAKE_VERSION} VERSION_LESS 3.21)
list(APPEND MINGW_EXTRA "crypt32")
endif()
endif()
add_executable("${PROJECT_NAME}" ${DAEMON_SRC})
if(WITH_STATIC)
if(NOT MSVC)
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-static")
endif()
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-static")
endif()
if(WITH_HARDENING AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
@ -370,18 +275,11 @@ if(WITH_BINARY)
list(REMOVE_AT Boost_LIBRARIES -1)
endif()
# synchronization library is incompatible with Windows 7
if(WIN32)
get_target_property(BOOSTFSLIBS Boost::filesystem INTERFACE_LINK_LIBRARIES)
list(REMOVE_ITEM BOOSTFSLIBS synchronization)
set_target_properties(Boost::filesystem PROPERTIES INTERFACE_LINK_LIBRARIES "${BOOSTFSLIBS}")
endif()
if(WITH_STATIC)
set(DL_LIB ${CMAKE_DL_LIBS})
endif()
target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto ${MINIUPNPC_LIBRARY} ZLIB::ZLIB Threads::Threads ${MINGW_EXTRA} ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES})
target_link_libraries("${PROJECT_NAME}" libi2pd libi2pdclient libi2pdlang ${Boost_LIBRARIES} OpenSSL::SSL OpenSSL::Crypto ${MINIUPNPC_LIBRARY} ZLIB::ZLIB Threads::Threads ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES})
install(TARGETS "${PROJECT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Runtime)
set(APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}")

@ -18,7 +18,7 @@ set(archdetect_c_code "
|| defined(_M_ARM64) \\
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 8)
#error cmake_ARCH arm64
#elif defined(__ARM_ARCH_7__) \\
#if defined(__ARM_ARCH_7__) \\
|| defined(__ARM_ARCH_7A__) \\
|| defined(__ARM_ARCH_7R__) \\
|| defined(__ARM_ARCH_7M__) \\

@ -1,16 +0,0 @@
# read version
function(set_version version_file output_var)
file(READ "${version_file}" version_data)
string(REGEX MATCH "I2PD_VERSION_MAJOR ([0-9]*)" _ ${version_data})
set(version_major ${CMAKE_MATCH_1})
string(REGEX MATCH "I2PD_VERSION_MINOR ([0-9]*)" _ ${version_data})
set(version_minor ${CMAKE_MATCH_1})
string(REGEX MATCH "I2PD_VERSION_MICRO ([0-9]*)" _ ${version_data})
set(version_micro ${CMAKE_MATCH_1})
set(${output_var} "${version_major}.${version_minor}.${version_micro}" PARENT_SCOPE)
endfunction()

@ -1,42 +0,0 @@
# _________________________________________
# / Copy this file to the right location \
# | then load with: |
# | |
# | apparmor_parser -r -W |
# | /etc/apparmor.d/docker-i2pd |
# | |
# | docker run --security-opt |
# | "apparmor=docker-i2pd" ... |
# | purplei2p/i2pd |
# | |
# \ And "aa-status" to verify it's loaded. /
# -----------------------------------------
# \ ^__^
# \ (oo)\_______
# (__)\ )\/\
# ||----w |
# || ||
#include <tunables/global>
profile docker-i2pd flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
#include <abstractions/openssl>
#include <abstractions/nameservice>
/bin/busybox ix,
/usr/local/bin/i2pd ix,
/entrypoint.sh ixr,
/i2pd_certificates/** r,
/home/i2pd/data/** rw,
/home/i2pd/data/i2pd.pid k,
deny /home/i2pd/data/i2pd.conf w,
deny /home/i2pd/data/tunnels.conf w,
deny /home/i2pd/data/tunnels.d/** w,
deny /home/i2pd/data/certificates/** w,
deny /home/i2pd/data/i2pd.log r,
}

@ -1,34 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIF1zCCA7+gAwIBAgIRAMDqFR09Xuj8ZUu+oetSvAEwDQYJKoZIhvcNAQELBQAw
dTELMAkGA1UEBhMCWFgxCzAJBgNVBAcTAlhYMQswCQYDVQQJEwJYWDEeMBwGA1UE
ChMVSTJQIEFub255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxHjAcBgNVBAMM
FWFkbWluQHN0b3JteWNsb3VkLm9yZzAeFw0yNDAxMjUxNDE1MzBaFw0zNDAxMjUx
NDE1MzBaMHUxCzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgx
HjAcBgNVBAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMR4w
HAYDVQQDDBVhZG1pbkBzdG9ybXljbG91ZC5vcmcwggIiMA0GCSqGSIb3DQEBAQUA
A4ICDwAwggIKAoICAQDbGX+GikPzQXr9zvkrhfO9g0l49KHLNQhUKYqd6T+PfnGo
Fm0d3ZZVVQZ045vWgroOXDGGZZWxUIlb2inRaR2DF1TxN3pPYt59RgY9ZQ9+TL7o
isY91krCRygY8EcAmHIjlfZQ9dBVcL7CfyT0MYZA5Efee9+NDHSewTfQP9T2faIE
83Fcyd93a2mIHYjKUbJnojng/wgsy8srbsEuuTok4MIQmDj+B5nz+za2FgI0/ydh
srlMt4aGJF4/DIem9z9d0zBCOkwrmtFIzjNF1mOSA8ES4m5YnKA/y9rZlRidLPGu
prbXhPVnqHeOnHMz2QCw1wbVo504kl0bMqyEz2tVWsO9ep7iZoQs2xkFAEaegYNT
QLUpwVGlyuq3wXXwopFRffOSimGSazICwWI6j+K0pOtgefNJaWrqKYvtkj1SbK2L
LBNUIENz6VnB7KPRckuX6zxC8PpOiBK9BcftfO+xAz/wC6qq3riBPw30KKSym0nC
Zp5KciDn4Phtw9PGq8Bkl8SyWl0jtFnfTB1tzJkisf2qKcNHaFTEe2JW763YLbh/
AU+8X8evFu40qLgvOgKoyy5DLy6i8zetX+3t9K0Fxt9+Vzzq6lm5V/RS8iIPPn+M
q1/3Z5kD0KQBG9h/Gl8BH+lB71ZxPAOZ3SMu8DJZcxBLVmDWqQPCr5CKnoz0swID
AQABo2IwYDAOBgNVHQ8BAf8EBAMCAoQwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsG
AQUFBwMBMA8GA1UdEwEB/wQFMAMBAf8wHgYDVR0OBBcEFWFkbWluQHN0b3JteWNs
b3VkLm9yZzANBgkqhkiG9w0BAQsFAAOCAgEARWOJ69vTHMneSXYscha+4Ytjg0RM
faewJNEGj8qy/Qvh9si2bWYNPRK6BlbHFS7pRYBLAnhaeLBGVv1CCR6GUMMe74zQ
UuMeAoWU6qMDmB3GfYoZJh8sIxpwHqyJeTdeccRbZ4sX4F6u3IHPXYiU/AgbYqH7
pYXQg2lCjXZYaDFAlEf5SlYUDOhhXe5kR8Edhlrsu32/JzA1DQK0JjxKCBp+DQmA
ltdOpQtAg03fHP4ssdj7VvjIDl28iIlATwBvHrdNm7T0tYWn6TWhvxbRqvfTxfaH
MvxnPdIJwNP4/9TyQkwjwHb1h+ucho3CnxI/AxspdOvT1ElMhP6Ce6rcS9pk11Rl
x0ChsqpWwDg7KYpg0qZFSKCTBp4zBq9xoMJ6BQcgMfyl736WbsCzFTEyfifp8beg
NxUa/Qk7w7cuSPGyMIKNOmOR7FLlFbtocy8sXVsUQdqnp/edelufdNe39U9uNtY6
yoXI9//Tc6NgOwy2Oyia0slZ5qHRkB7e4USXMRzJ3p4q9eCVKjAJs81Utp7O2U+9
vhbhwWP8CAnNTT1E5WS6EKtfrdqF7wjkV+noPGLDGmrXi01J1fSMAjMfVO+7/LOL
UN+G4ybKWnEhhOO27yidN8Xx6UrCS23DBlPPQAeA74dTsTExiOxf1o1EXzcQiMyO
LAj3/Ojbi1xkWhI=
-----END CERTIFICATE-----

@ -1,34 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIF2TCCA8GgAwIBAgIQIHQPtSoFU+cUpYD8PZaWZjANBgkqhkiG9w0BAQsFADB2
MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK
ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEfMB0GA1UEAwwW
YXJuYXZiaGF0dDI4OEBtYWlsLmkycDAeFw0yMzAxMjUxODUzNDFaFw0zMzAxMjUx
ODUzNDFaMHYxCzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgx
HjAcBgNVBAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMR8w
HQYDVQQDDBZhcm5hdmJoYXR0Mjg4QG1haWwuaTJwMIICIjANBgkqhkiG9w0BAQEF
AAOCAg8AMIICCgKCAgEAtwG73sC0jYd3fgEzZh0SveAdUd5yD35nINJRrdPSrSwY
n3i1qGe3fNLj877PvUDU+qiHH0fFZfyFkXTaq3TUp1u4YkmvaoPHy6FZlojB08lK
FBm+iJ1hifQ7MFmvIKUGv+cjlN6xSoQ0U6B2QOy6iZnBgFZ/7jbRY4iZOIj7VJtY
aodeHfy0bWe447VJovbkUi7NJPFZQS65LMcAIWcWTxrC0Gj8SmdxL3a5+hxpmmg0
+KCQvWQDdxAQjsc16sgUCdUc6cWYO4yw9H6fgdq9GJX+LnXR9OB58GsAjjlLlFoI
CZxdARDpoqcIj6AoKIanALf8yfbIyrqqJE47cuaqV9bht5MWKnXbwHplEkT4ZNkh
PnRDia7B5HY3uwbt39CBm264PEWXvWG2sozTWKQqBjmMN2cj/NFDUEqKv6BggMY1
HcqxWFKRcgKCtRvrmTmfp5l0/ou+OtUaFUg0a6Qhtb93Hj10vK6wZzidBqj0ggzB
eJDI95b89u8JgzRoOBriuMKTc91WTkOvBLkB3dgUbUpx2p8KHjvf/pppBH9u0oxp
qJFFK840DbnJydEvjKezeVe5Ax6YRSRxyEdKzRoWdvKVxb3qBBKMdCKTYEPxHPBu
JMEQVUCXJMti++1KEiQGhcfWvLyT7OewbcIZNk9XWNrxlKcGrTp9AOwaaNC5m1kC
AwEAAaNjMGEwDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggr
BgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB8GA1UdDgQYBBZhcm5hdmJoYXR0Mjg4
QG1haWwuaTJwMA0GCSqGSIb3DQEBCwUAA4ICAQAHiK0ld/1PF9DIhutD660/bzBg
mF2Z76hcBqDZ8tnQai/u/RXYrH9wso9BYyrVsvk3fr6tpGT49Ian0MVpPOxMoTU2
oBEmQlYrfclQLFsOLmA0y2r1ggXzIrt69jB710Vhwdnz09oOE8rS4E2T5oDD8Wvy
Kony+AarRceqtkOlzyquc42KjzdrbHsosF7G2iGhNI6t+T3BfWJ+Q+d5sj3OIh6e
gSfvHL44E4vZt6dtofRN3MAZ60kNLF5YWyaUo3Snv9Lso1IwIz3AVr5ehv+8sFL/
KxaXdkZ5Yn2YUX7p1t4VQd+eXVPYjf1befg4PvrwSkylu3Jpee3fllZSKXeSVx9x
jpJiq5vIakqk22pnWb1Vn7xzSW1vtEG7QLjobOr1WrcGiwdv+HKiWcXJXDzKoWXs
h3VEfr51Kap8cIJv+D6lJIG9IcIhiQ6CXWBmtjWJvbdVwFBy1/3Fhaou9liHi+gK
4Yh5a5OGCzc7xjtpGaTmoLEz7NzDNOdd/r840qRDOh70izzmFZd5Gwq4hoVcPJcS
EAySwtgqK0/4d0zDd2Wg9ASJV9DnDf8QuSmHZgZ9Efs47XcWz9TvkWUS1E66AJsN
mmI1NDQ3mv3dv5+WPq+dqqYFsnx3xWL1g5Z3buk0opeuXMzoHwM7UfN8h7Q1M5+t
+XBgkaYA4iEwYKqlCQ==
-----END CERTIFICATE-----

@ -1,33 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFvjCCA6agAwIBAgIQBnsUOmOu2oZZIwHBmQc1BDANBgkqhkiG9w0BAQsFADBt
MIIFvjCCA6agAwIBAgIQIDtv8tGMh0FyB2w5XjfZxTANBgkqhkiG9w0BAQsFADBt
MQswCQYDVQQGEwJYWDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR4wHAYDVQQK
ExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEWMBQGA1UEAwwN
aWdvckBub3ZnLm5ldDAeFw0yMzAxMjgxNDM4MzFaFw0zMzAxMjgxNDM4MzFaMG0x
aWdvckBub3ZnLm5ldDAeFw0xNzA3MjQxODI4NThaFw0yNzA3MjQxODI4NThaMG0x
CzAJBgNVBAYTAlhYMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgxHjAcBgNVBAoT
FUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoGA1UECxMDSTJQMRYwFAYDVQQDDA1p
Z29yQG5vdmcubmV0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvLkf
bM3uiYfp9m0vgdoftyXtk2/9bHf3u5iaM0WfoJIsw1iizo/mxJl+Iy7SxLC16nV0
v5FpncVv+Z8x9dgoAYVuLq9zKfsAbpj6kuxAqw6vJMlD1TiIL3nSODV9BJLk47X5
tmvoOSj9BgvemYThTE3nj+DbuJRW5q90KyBV/LdLrQJX3k5R3FFL5tTad2LKFNZ4
vEOcYwwx6mvrkJ2lly6bAQUCtfc648Jyq+NO3Rba1fmn7gcP9zXXc5KYsj/ovyY2
OaocSF5wMhzBuPxO+M2HqbYLMAkc6/GesGds8Rm8wofuhJoI5YtqJuLKZm6nQXSc
fx6PKgbKcTIUWNFMsxyfghz9hpbg0rkvC7PtfAjtV0yaDtUum1eZeNEx1HbRWN2n
TQNCVuv0yaKC41qxqzhEybkdjL9JlgUh7VuskaCelB0lz+kgYjGu8ezOa0ua2iKq
4FC/1MbPulxN8NOt4pmbGqqoxmCdShp38wdnOBM3DsAS9f0JaQZd4CDyY4DCSfVn
xPdWk31+VXVt3Ixh1EUqZWYTRSsZApkCyYzkiZ/qPGG6FR9Hq2SuhC5o4P44k7eo
6wwBWD8a5RjsZhvr05E5yBrKXh/PjLwmtG73QC+ouR54/5xtedvdTwNS94FnNctX
FT6QGZnRwCkhPaRe1oQMzP+88pGoCfO33GBAuwUCAwEAAaNaMFgwDgYDVR0PAQH/
Z29yQG5vdmcubmV0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxst4
cam3YibBtQHGPCPX13uRQti56U3XZytSZntaKrUFmJxjt41Q/mOy3KYo+lBvhfDF
x3tWKjgP9LJOJ28zvddFhZVNxqZRjcnAoPuSOVCw88g01D9OAasKF11hCfdxZP6h
vGm8WCnjD8KPcYFxJC4HJUiFeProAwuTzEAESTRk4CAQe3Ie91JspuqoLUc5Qxlm
w5QpjnjfZY4kaVHmZDKGIZDgNIt5v85bu4pWwZ6O+o90xQqjxvjyz/xccIec3sHw
MHJ8h8ZKMokCKEJTaRWBvdeNXki7nf3gUy/3GjYQlzo0Nxk/Hw4svPcA+eL0AYiy
Jn83bIB5VToW2zYUdV4u3qHeAhEg8Y7HI0kKcSUGm9AQXzbzP8YCHxi0sbb0GAJy
f1Xf3XzoPfT64giD8ReUHhwKpyMB6uvG/NfWSZAzeAO/NT7DAwXpKIVQdkVdqy8b
mvHvjf9/kWKOirA2Nygf3r79Vbg2mqbYC/b63XI9hheU689+O7qyhTEhNz+11X0d
Zax7UPrLrwOeB9TNfEnztsmrHNdv2n+KcOO2o11Wvz2nHP9g+dgwoZSD1ZEpFzWP
0sD5knKLwAL/64qLlAQ1feqW7hMr80IADcKjLSODkIDIIGm0ksXqEzTjz1JzbRDq
jUjq7EAlkw3G69rv1gHxIntllJRQidAqecyWHOMCAwEAAaNaMFgwDgYDVR0PAQH/
BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8E
BTADAQH/MBYGA1UdDgQPBA1pZ29yQG5vdmcubmV0MA0GCSqGSIb3DQEBCwUAA4IC
AQCteAb5/bqhHr/i5CJbDzlofprXFC826c19GxQ/9Hw0kA52l0J9Q8Vz8Vy7VQyP
QNa8MCv6FeNy8a/wXp6cafyFsBtvehVQO8lFlpCgMEl2Bma43+GaCwkrM6bFNXeW
iQ9h4e1KjsUZ8cQDNEcamiJ80+xbMhBrj5bAZwKmZs8MoGEMyXKEZmcmwA+/fy1c
cx4izsOsmRXmEHXsvB9ydJHZZeKW8+r0DAtgPslwXuXHG6MuBQo7dKCqn+iMxHXV
Jxriq3yvNffdGx4maSLJrjQ1ealt/UMzql7huVSItnVFWoYf7GAELXNJ/PmqVyaK
q11LQ8W/Aud6s/bblaJrFJnK8PbPpaw4RvHoWVLYaZYmQnV2msWs5EuESBlEADbv
UklQXLMc2f9HKWPA5678nvYPrmu8IL5pMkAxgGRqmd+7vCz4lU9M5z3HObU+WRBt
qEMYyXywV8o3tbmnlDS5S5Xxf+tLZn1cxz3ZrmcHPHDbLBNdvszF3CTJH/R2sQvD
bizvYJM+p5F+GWM5mt6w0HrOut5MRlpOws/NRrkbijuVA/A45nzTtKplIFYE3qe8
q5SAbwYLc8cJcZCN3PxtWwbEv81V33abMt5QcjnWGLH5t2+1Z2KLCgKLSCQTxM8s
zBPHtUe8qtSQaElnNLILYbtJ1w67dPnGYTphHihC+CXjBg==
AQADyPaec28qc1HQtAV5dscJr47k92RTfvan+GEgIwyQDHZQm38eyTb05xipQCdk
5ruUDFXLB5qXXFJKUbQM6IpaktmWDJqk4Zn+1nGbtFEbKgrF55pd63+NQer5QW9o
3+dGj0eZJa3HX5EBkd2r7j2LFuB6uxv3r/xiTeHaaflCnsmyDLfb7axvYhyEzHQS
AUi1bR+ln+dXewdtuojqc1+YmVGDgzWZK2T0oOz2E21CpZUDiP3wv9QfMaotLEal
zECnbhS++q889inN3GB4kIoN6WpPpeYtTV+/r7FLv9+KUOV1s2z6mxIqC5wBFhZs
0Sr1kVo8hB/EW/YYhDp99LoAOjIO6nn1h+qttfzBYr6C16j+8lGK2A12REJ4LiUQ
cQI/0zTjt2C8Ns6ueNzMLQN1Mvmlg1Z8wIB7Az7jsIbY2zFJ0M5qR5VJveTj33K4
4WSbC/zMWOBYHTVBvGmc6JGhu5ZUTZ+mWP7QfimGu+tdhvtrybFjE9ROIE/4yFr6
GkxEyt0UY87TeKXJ/3KygvkMwdvqGWiZhItb807iy99+cySujtbGfF2ZXYGjBXVW
dJOVRbyGQkHh6lrWHQM4ntBv4x+5QA+OAan5PBF3tcDx1vefPx+asYslbOXpzII5
qhvoQxuRs6j5jsVFG6RdsKNeQAt87Mb2u2zK2ZakMdyD1w==
-----END CERTIFICATE-----

@ -1,32 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIFdTCCA12gAwIBAgIEQ5vCxzANBgkqhkiG9w0BAQ0FADBrMQswCQYDVQQGEwJY
WDELMAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMR4wHAYDVQQKDBVJMlAgQW5vbnlt
b3VzIE5ldHdvcmsxDDAKBgNVBAsMA0kyUDEUMBIGA1UEAwwLbHNAbWFpbC5pMnAw
HhcNMjMxMDE2MjAwNTA5WhcNMzMxMDEzMjAwNTA5WjBrMQswCQYDVQQGEwJYWDEL
MAkGA1UECAwCWFgxCzAJBgNVBAcMAlhYMR4wHAYDVQQKDBVJMlAgQW5vbnltb3Vz
IE5ldHdvcmsxDDAKBgNVBAsMA0kyUDEUMBIGA1UEAwwLbHNAbWFpbC5pMnAwggIi
MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDPcbKRtf4PzrDa0iRit0XrwnmA
2c1fJhkBipdPor7gMOAlkR82H1lkZSizR7kTZnr7vYqjDrOQr7bl5Dy3qo8/YCbZ
jsnUCTIIgIJQUxUlR40RjaSXphqzUEiXKHR6b0RahhFisQ3hlbbgzSch5YgSLKws
hOLi+eDSXw+HlwHlWFlT1XOKxSTJ/F3Bv40gxqZVC2pbxiPOeRZHQ6Ojw75lxTSF
gww2WzgztiWt4X9BO1yepnVqhAVRPmTfGUMfKzq9jkMzZKeQFV4uZSP9nCqzEpYd
WNDUfpTWiAQ9F+BwFXGusXXA3tGVwS7s6IEoiJFM5fsoJYfRoWGh3/1eirhBXW7U
M6oubMSTADyrvfjLfJBMmMnc2hNblRlKr0ZKUjMfv8cnyT4kQxlXLAHHXY2P89TM
TEVODkU48gnv6tC4t1JCb1/Da+3yVMjNX6rCzQfUwnLFrWthrwiI0NivAKFtiZjq
w1/ZQcYke2YyeqcfXMn+NTUA22Sm2mJoMo7jUf+rbM9Pi27/DncJgRGj5qwY0D3S
gc7829EjuZNPttGBmae1EmO7WQMB32cqdmItnV2FXpMhnn9h0u5H52kYqwn+mdtc
dTJRcbfKG1RTr3UjFISaTwL8qigMIkVXIzcpnr/R/sSeEs8xCqfsJ6rb4dCyFx+M
hqQcOCL5tumyd4W/LQIDAQABoyEwHzAdBgNVHQ4EFgQUgfaOG5HCnlW82wZ5BahL
GRO06igwDQYJKoZIhvcNAQENBQADggIBAKdVpqS9qF7gGotgXaVA1iP5YNsWlTvG
daGqeA/87//U21W6gpq82FhzsmsvUtXZfIeVIlDPI7WNDzS+A3K/KKrwM7dLgSie
r9eMl3D8WYPU95QF4mAlRyl7PCCsYoVjyvfro0iq3/iudIA5476rjfLdTXRi5hAT
qemPj0S+6sRjKEldRtGXrQATFlvLIWVYpgHijdDDx5M2hAz2y0mFxlDZTlA4BhL4
DwtGlVKmbc2x5MvIQM4UhbQqkxYS4gXnzf5Qx9QIytHfTr/hmbrkhKR1GCO31BSk
x9LhZxdI8LlwKSo6YgwXEB9E0M/tplaK9iZJFv4HPYLZrVJpb4IklMumyLMrgW5P
fR0dgKn+R9lk0emJ1Cu+qyyzf1vsLycYBwaEztINn4VK+/HfDFpnVCvJOyNuDmj5
KBLIoGdGoVfylmnc+e8zAXe+DY41fgniHMISOO78P8Bx9vTB+rhqnOUr9MzlUxPB
sKGjbXy2YynEqiGb+9g344v/+ukTSDenqTPHVzJ5uOi0iedy+3ASzUNN6GJocovP
167VOhwaETM0FwiKe0VdZRLLbbZ79CtJC0tmgcgPQPRa9Ldr6KN7u1J3D6lUp6zl
byPom10ueKONRb36t7ai79l2SEUZRSMkx6AXIU0JJ1SMtQtav7b5LkpYJfdL7+vO
dDx2/Za0VmdD
-----END CERTIFICATE-----

@ -1,5 +1,2 @@
This forder contain files required for building debian packages.
The trunk repository is contains the packaging files for the latest stable version of Debian (if we not forgot to update them).
Files in subdirectories contains fixes to make possible to build package on specific versions of Debian/Ubuntu. They are used when building the release package.
This forder contain systemd unit files.
To use systemd daemon control, place files from this directory to debian folder before building package.

@ -1,18 +0,0 @@
Source: i2pd
Section: net
Priority: optional
Maintainer: r4sas <r4sas@i2pmail.org>
Build-Depends: debhelper (>= 11~), libboost-system-dev (>= 1.46), libboost-date-time-dev (>= 1.46), libboost-filesystem-dev (>= 1.46), libboost-program-options-dev (>= 1.46), libminiupnpc-dev, libssl-dev, zlib1g-dev
Standards-Version: 4.2.0
Homepage: http://i2pd.website/
Vcs-Git: git://github.com/PurpleI2P/i2pd.git
Vcs-Browser: https://github.com/PurpleI2P/i2pd
Package: i2pd
Architecture: any
Pre-Depends: ${misc:Pre-Depends}, adduser
Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base,
Description: Full-featured C++ implementation of I2P client.
I2P (Invisible Internet Protocol) is a universal anonymous network layer. All
communications over I2P are anonymous and end-to-end encrypted, participants
don't reveal their real IP addresses.

@ -1,18 +0,0 @@
Source: i2pd
Section: net
Priority: optional
Maintainer: r4sas <r4sas@i2pmail.org>
Build-Depends: debhelper (>= 9), libboost-system-dev (>= 1.46), libboost-date-time-dev (>= 1.46), libboost-filesystem-dev (>= 1.46), libboost-program-options-dev (>= 1.46), libminiupnpc-dev, libssl-dev, zlib1g-dev
Standards-Version: 3.9.8
Homepage: http://i2pd.website/
Vcs-Git: git://github.com/PurpleI2P/i2pd.git
Vcs-Browser: https://github.com/PurpleI2P/i2pd
Package: i2pd
Architecture: any
Pre-Depends: ${misc:Pre-Depends}, adduser
Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base,
Description: Full-featured C++ implementation of I2P client.
I2P (Invisible Internet Protocol) is a universal anonymous network layer. All
communications over I2P are anonymous and end-to-end encrypted, participants
don't reveal their real IP addresses.

@ -1,17 +0,0 @@
Description: Enable UPnP usage in package
Author: r4sas <r4sas@i2pmail.org>
Reviewed-By: r4sas <r4sas@i2pmail.org>
Last-Update: 2022-03-23
--- i2pd.orig/Makefile
+++ i2pd/Makefile
@@ -31,7 +31,7 @@ include filelist.mk
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

@ -1,19 +0,0 @@
Description: Disable LogsDirectory and LogsDirectoryMode options in service
Author: r4sas <r4sas@i2pmail.org>
Reviewed-By: r4sas <r4sas@i2pmail.org>
Last-Update: 2023-05-17
--- a/contrib/i2pd.service
+++ b/contrib/i2pd.service
@@ -8,8 +8,8 @@ User=i2pd
Group=i2pd
RuntimeDirectory=i2pd
RuntimeDirectoryMode=0700
-LogsDirectory=i2pd
-LogsDirectoryMode=0700
+#LogsDirectory=i2pd
+#LogsDirectoryMode=0700
Type=forking
ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --tunnelsdir=/etc/i2pd/tunnels.conf.d --pidfile=/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service
ExecReload=/bin/sh -c "kill -HUP $MAINPID"

@ -1,2 +0,0 @@
01-upnp.patch
02-service.patch

@ -1,18 +0,0 @@
#!/usr/bin/make -f
#export DH_VERBOSE=1
export DEB_BUILD_MAINT_OPTIONS=hardening=+all
include /usr/share/dpkg/architecture.mk
ifeq ($(DEB_HOST_ARCH),i386)
export DEB_BUILD_OPTIONS=parallel=1
endif
export DEB_CXXFLAGS_MAINT_APPEND=-Wall -pedantic
export DEB_LDFLAGS_MAINT_APPEND=
%:
dh $@ --parallel
override_dh_auto_install:

@ -1,18 +0,0 @@
Source: i2pd
Section: net
Priority: optional
Maintainer: r4sas <r4sas@i2pmail.org>
Build-Depends: debhelper (>= 9), libboost-system-dev (>= 1.46), libboost-date-time-dev (>= 1.46), libboost-filesystem-dev (>= 1.46), libboost-program-options-dev (>= 1.46), libminiupnpc-dev, libssl-dev, zlib1g-dev
Standards-Version: 3.9.8
Homepage: http://i2pd.website/
Vcs-Git: git://github.com/PurpleI2P/i2pd.git
Vcs-Browser: https://github.com/PurpleI2P/i2pd
Package: i2pd
Architecture: any
Pre-Depends: ${misc:Pre-Depends}, adduser
Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base,
Description: Full-featured C++ implementation of I2P client.
I2P (Invisible Internet Protocol) is a universal anonymous network layer. All
communications over I2P are anonymous and end-to-end encrypted, participants
don't reveal their real IP addresses.

@ -1,17 +0,0 @@
Description: Enable UPnP usage in package
Author: r4sas <r4sas@i2pmail.org>
Reviewed-By: r4sas <r4sas@i2pmail.org>
Last-Update: 2022-03-23
--- i2pd.orig/Makefile
+++ i2pd/Makefile
@@ -31,7 +31,7 @@ include filelist.mk
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

@ -1,19 +0,0 @@
Description: Disable LogsDirectory and LogsDirectoryMode options in service
Author: r4sas <r4sas@i2pmail.org>
Reviewed-By: r4sas <r4sas@i2pmail.org>
Last-Update: 2023-05-17
--- a/contrib/i2pd.service
+++ b/contrib/i2pd.service
@@ -8,8 +8,8 @@ User=i2pd
Group=i2pd
RuntimeDirectory=i2pd
RuntimeDirectoryMode=0700
-LogsDirectory=i2pd
-LogsDirectoryMode=0700
+#LogsDirectory=i2pd
+#LogsDirectoryMode=0700
Type=forking
ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --tunnelsdir=/etc/i2pd/tunnels.conf.d --pidfile=/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service
ExecReload=/bin/sh -c "kill -HUP $MAINPID"

@ -1,2 +0,0 @@
01-upnp.patch
02-service.patch

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

@ -1,8 +0,0 @@
type = bgprocess
run-as = i2pd
command = /usr/bin/i2pd --conf=/var/lib/i2pd/i2pd.conf --pidfile=/var/lib/i2pd/i2pd.pid --daemon --service
smooth-recovery = true
depends-on = ntpd
# uncomment if you want to use i2pd with yggdrasil
# depends-on = yggdrasil
pid-file = /var/lib/i2pd/i2pd.pid

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: i2pd\n"
"Report-Msgid-Bugs-To: https://github.com/PurpleI2P/i2pd/issues\n"
"POT-Creation-Date: 2023-06-10 01:25\n"
"POT-Creation-Date: 2023-01-19 04:18\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
@ -18,28 +18,28 @@ msgstr ""
"X-Poedit-SearchPath-0: daemon/HTTPServer.cpp\n"
"X-Poedit-SearchPath-1: libi2pd_client/HTTPProxy.cpp\n"
#: daemon/HTTPServer.cpp:107
#: daemon/HTTPServer.cpp:106
#, c-format
msgid "%d day"
msgid_plural "%d days"
msgstr[0] ""
msgstr[1] ""
#: daemon/HTTPServer.cpp:111
#: daemon/HTTPServer.cpp:110
#, c-format
msgid "%d hour"
msgid_plural "%d hours"
msgstr[0] ""
msgstr[1] ""
#: daemon/HTTPServer.cpp:115
#: daemon/HTTPServer.cpp:114
#, c-format
msgid "%d minute"
msgid_plural "%d minutes"
msgstr[0] ""
msgstr[1] ""
#: daemon/HTTPServer.cpp:118
#: daemon/HTTPServer.cpp:117
#, c-format
msgid "%d second"
msgid_plural "%d seconds"
@ -47,578 +47,560 @@ msgstr[0] ""
msgstr[1] ""
#. tr: Kibibyte
#: daemon/HTTPServer.cpp:126
#: daemon/HTTPServer.cpp:125 daemon/HTTPServer.cpp:153
#, c-format
msgid "%.2f KiB"
msgstr ""
#. tr: Mebibyte
#: daemon/HTTPServer.cpp:128
#: daemon/HTTPServer.cpp:127
#, c-format
msgid "%.2f MiB"
msgstr ""
#. tr: Gibibyte
#: daemon/HTTPServer.cpp:130
#: daemon/HTTPServer.cpp:129
#, c-format
msgid "%.2f GiB"
msgstr ""
#: daemon/HTTPServer.cpp:147
#: daemon/HTTPServer.cpp:146
msgid "building"
msgstr ""
#: daemon/HTTPServer.cpp:148
#: daemon/HTTPServer.cpp:147
msgid "failed"
msgstr ""
#: daemon/HTTPServer.cpp:149
#: daemon/HTTPServer.cpp:148
msgid "expiring"
msgstr ""
#: daemon/HTTPServer.cpp:150
#: daemon/HTTPServer.cpp:149
msgid "established"
msgstr ""
#: daemon/HTTPServer.cpp:151
#: daemon/HTTPServer.cpp:150
msgid "unknown"
msgstr ""
#: daemon/HTTPServer.cpp:153
#: daemon/HTTPServer.cpp:152
msgid "exploratory"
msgstr ""
#. tr: Webconsole page title
#: daemon/HTTPServer.cpp:185
#: daemon/HTTPServer.cpp:183
msgid "Purple I2P Webconsole"
msgstr ""
#: daemon/HTTPServer.cpp:190
#: daemon/HTTPServer.cpp:188
msgid "<b>i2pd</b> webconsole"
msgstr ""
#: daemon/HTTPServer.cpp:193
#: daemon/HTTPServer.cpp:191
msgid "Main page"
msgstr ""
#: daemon/HTTPServer.cpp:194 daemon/HTTPServer.cpp:742
#: daemon/HTTPServer.cpp:192 daemon/HTTPServer.cpp:712
msgid "Router commands"
msgstr ""
#: daemon/HTTPServer.cpp:195 daemon/HTTPServer.cpp:395
#: daemon/HTTPServer.cpp:407
#: daemon/HTTPServer.cpp:193 daemon/HTTPServer.cpp:387
#: daemon/HTTPServer.cpp:399
msgid "Local Destinations"
msgstr ""
#: daemon/HTTPServer.cpp:197 daemon/HTTPServer.cpp:365
#: daemon/HTTPServer.cpp:454 daemon/HTTPServer.cpp:474
#: daemon/HTTPServer.cpp:636 daemon/HTTPServer.cpp:682
#: daemon/HTTPServer.cpp:686
#: daemon/HTTPServer.cpp:195 daemon/HTTPServer.cpp:357
#: daemon/HTTPServer.cpp:443 daemon/HTTPServer.cpp:449
#: daemon/HTTPServer.cpp:609 daemon/HTTPServer.cpp:652
#: daemon/HTTPServer.cpp:656
msgid "LeaseSets"
msgstr ""
#: daemon/HTTPServer.cpp:199 daemon/HTTPServer.cpp:692
#: daemon/HTTPServer.cpp:197 daemon/HTTPServer.cpp:662
msgid "Tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:201 daemon/HTTPServer.cpp:372
#: daemon/HTTPServer.cpp:813 daemon/HTTPServer.cpp:830
#: daemon/HTTPServer.cpp:199 daemon/HTTPServer.cpp:364
#: daemon/HTTPServer.cpp:781 daemon/HTTPServer.cpp:797
msgid "Transit Tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:203 daemon/HTTPServer.cpp:898
#: daemon/HTTPServer.cpp:201 daemon/HTTPServer.cpp:855
msgid "Transports"
msgstr ""
#: daemon/HTTPServer.cpp:204
#: daemon/HTTPServer.cpp:202
msgid "I2P tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:206 daemon/HTTPServer.cpp:927
#: daemon/HTTPServer.cpp:937
#: daemon/HTTPServer.cpp:204 daemon/HTTPServer.cpp:884
#: daemon/HTTPServer.cpp:894
msgid "SAM sessions"
msgstr ""
#: daemon/HTTPServer.cpp:222 daemon/HTTPServer.cpp:1329
#: daemon/HTTPServer.cpp:1332 daemon/HTTPServer.cpp:1335
#: daemon/HTTPServer.cpp:1362 daemon/HTTPServer.cpp:1365
#: daemon/HTTPServer.cpp:1379 daemon/HTTPServer.cpp:1424
#: daemon/HTTPServer.cpp:1427 daemon/HTTPServer.cpp:1430
#: daemon/HTTPServer.cpp:220 daemon/HTTPServer.cpp:1278
#: daemon/HTTPServer.cpp:1281 daemon/HTTPServer.cpp:1284
#: daemon/HTTPServer.cpp:1298 daemon/HTTPServer.cpp:1343
#: daemon/HTTPServer.cpp:1346 daemon/HTTPServer.cpp:1349
msgid "ERROR"
msgstr ""
#: daemon/HTTPServer.cpp:229
#: daemon/HTTPServer.cpp:227
msgid "OK"
msgstr ""
#: daemon/HTTPServer.cpp:230
#: daemon/HTTPServer.cpp:228
msgid "Testing"
msgstr ""
#: daemon/HTTPServer.cpp:231
#: daemon/HTTPServer.cpp:229
msgid "Firewalled"
msgstr ""
#: daemon/HTTPServer.cpp:232 daemon/HTTPServer.cpp:235
#: daemon/HTTPServer.cpp:336
#: daemon/HTTPServer.cpp:230 daemon/HTTPServer.cpp:233
#: daemon/HTTPServer.cpp:329
msgid "Unknown"
msgstr ""
#: daemon/HTTPServer.cpp:233 daemon/HTTPServer.cpp:382
#: daemon/HTTPServer.cpp:383 daemon/HTTPServer.cpp:1003
#: daemon/HTTPServer.cpp:1011
#: daemon/HTTPServer.cpp:231 daemon/HTTPServer.cpp:374
#: daemon/HTTPServer.cpp:375 daemon/HTTPServer.cpp:952
#: daemon/HTTPServer.cpp:961
msgid "Proxy"
msgstr ""
#: daemon/HTTPServer.cpp:234
#: daemon/HTTPServer.cpp:232
msgid "Mesh"
msgstr ""
#: daemon/HTTPServer.cpp:242
#: daemon/HTTPServer.cpp:240
msgid "Clock skew"
msgstr ""
#: daemon/HTTPServer.cpp:245
#: daemon/HTTPServer.cpp:243
msgid "Offline"
msgstr ""
#: daemon/HTTPServer.cpp:248
#: daemon/HTTPServer.cpp:246
msgid "Symmetric NAT"
msgstr ""
#: daemon/HTTPServer.cpp:251
#: daemon/HTTPServer.cpp:249
msgid "Full cone NAT"
msgstr ""
#: daemon/HTTPServer.cpp:254
#: daemon/HTTPServer.cpp:252
msgid "No Descriptors"
msgstr ""
#: daemon/HTTPServer.cpp:263
#: daemon/HTTPServer.cpp:261
msgid "Uptime"
msgstr ""
#: daemon/HTTPServer.cpp:266
#: daemon/HTTPServer.cpp:264
msgid "Network status"
msgstr ""
#: daemon/HTTPServer.cpp:271
#: daemon/HTTPServer.cpp:269
msgid "Network status v6"
msgstr ""
#: daemon/HTTPServer.cpp:277 daemon/HTTPServer.cpp:284
#: daemon/HTTPServer.cpp:275 daemon/HTTPServer.cpp:282
msgid "Stopping in"
msgstr ""
#: daemon/HTTPServer.cpp:291
#: daemon/HTTPServer.cpp:289
msgid "Family"
msgstr ""
#: daemon/HTTPServer.cpp:292
#: daemon/HTTPServer.cpp:290
msgid "Tunnel creation success rate"
msgstr ""
#: daemon/HTTPServer.cpp:296
msgid "Total tunnel creation success rate"
msgstr ""
#: daemon/HTTPServer.cpp:298
#: daemon/HTTPServer.cpp:291
msgid "Received"
msgstr ""
#. tr: Kibibyte/s
#: daemon/HTTPServer.cpp:300 daemon/HTTPServer.cpp:303
#: daemon/HTTPServer.cpp:306
#: daemon/HTTPServer.cpp:293 daemon/HTTPServer.cpp:296
#: daemon/HTTPServer.cpp:299
#, c-format
msgid "%.2f KiB/s"
msgstr ""
#: daemon/HTTPServer.cpp:301
#: daemon/HTTPServer.cpp:294
msgid "Sent"
msgstr ""
#: daemon/HTTPServer.cpp:304
#: daemon/HTTPServer.cpp:297
msgid "Transit"
msgstr ""
#: daemon/HTTPServer.cpp:307
#: daemon/HTTPServer.cpp:300
msgid "Data path"
msgstr ""
#: daemon/HTTPServer.cpp:310
#: daemon/HTTPServer.cpp:303
msgid "Hidden content. Press on text to see."
msgstr ""
#: daemon/HTTPServer.cpp:314
#: daemon/HTTPServer.cpp:307
msgid "Router Ident"
msgstr ""
#: daemon/HTTPServer.cpp:316
#: daemon/HTTPServer.cpp:309
msgid "Router Family"
msgstr ""
#: daemon/HTTPServer.cpp:317
#: daemon/HTTPServer.cpp:310
msgid "Router Caps"
msgstr ""
#: daemon/HTTPServer.cpp:318
#: daemon/HTTPServer.cpp:311
msgid "Version"
msgstr ""
#: daemon/HTTPServer.cpp:319
#: daemon/HTTPServer.cpp:312
msgid "Our external address"
msgstr ""
#. tr: Shown when router doesn't publish itself and have "Firewalled" state
#: daemon/HTTPServer.cpp:349
#: daemon/HTTPServer.cpp:341
msgid "supported"
msgstr ""
#: daemon/HTTPServer.cpp:363
#: daemon/HTTPServer.cpp:355
msgid "Routers"
msgstr ""
#: daemon/HTTPServer.cpp:364
#: daemon/HTTPServer.cpp:356
msgid "Floodfills"
msgstr ""
#: daemon/HTTPServer.cpp:371 daemon/HTTPServer.cpp:987
#: daemon/HTTPServer.cpp:363 daemon/HTTPServer.cpp:938
msgid "Client Tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:381
#: daemon/HTTPServer.cpp:373
msgid "Services"
msgstr ""
#: daemon/HTTPServer.cpp:382 daemon/HTTPServer.cpp:383
#: daemon/HTTPServer.cpp:384 daemon/HTTPServer.cpp:385
#: daemon/HTTPServer.cpp:386 daemon/HTTPServer.cpp:387
#: daemon/HTTPServer.cpp:374 daemon/HTTPServer.cpp:375
#: daemon/HTTPServer.cpp:376 daemon/HTTPServer.cpp:377
#: daemon/HTTPServer.cpp:378 daemon/HTTPServer.cpp:379
msgid "Enabled"
msgstr ""
#: daemon/HTTPServer.cpp:382 daemon/HTTPServer.cpp:383
#: daemon/HTTPServer.cpp:384 daemon/HTTPServer.cpp:385
#: daemon/HTTPServer.cpp:386 daemon/HTTPServer.cpp:387
#: daemon/HTTPServer.cpp:374 daemon/HTTPServer.cpp:375
#: daemon/HTTPServer.cpp:376 daemon/HTTPServer.cpp:377
#: daemon/HTTPServer.cpp:378 daemon/HTTPServer.cpp:379
msgid "Disabled"
msgstr ""
#: daemon/HTTPServer.cpp:434
#: daemon/HTTPServer.cpp:422
msgid "Encrypted B33 address"
msgstr ""
#: daemon/HTTPServer.cpp:442
#: daemon/HTTPServer.cpp:431
msgid "Address registration line"
msgstr ""
#: daemon/HTTPServer.cpp:447
#: daemon/HTTPServer.cpp:436
msgid "Domain"
msgstr ""
#: daemon/HTTPServer.cpp:448
#: daemon/HTTPServer.cpp:437
msgid "Generate"
msgstr ""
#: daemon/HTTPServer.cpp:449
#: daemon/HTTPServer.cpp:438
msgid ""
"<b>Note:</b> result string can be used only for registering 2LD domains "
"(example.i2p). For registering subdomains please use i2pd-tools."
msgstr ""
#: daemon/HTTPServer.cpp:457
#: daemon/HTTPServer.cpp:444
msgid "Address"
msgstr ""
#: daemon/HTTPServer.cpp:459
#: daemon/HTTPServer.cpp:444
msgid "Type"
msgstr ""
#: daemon/HTTPServer.cpp:460
#: daemon/HTTPServer.cpp:444
msgid "EncType"
msgstr ""
#: daemon/HTTPServer.cpp:467
msgid "Expire LeaseSet"
msgstr ""
#: daemon/HTTPServer.cpp:479 daemon/HTTPServer.cpp:697
#: daemon/HTTPServer.cpp:454 daemon/HTTPServer.cpp:667
msgid "Inbound tunnels"
msgstr ""
#. tr: Milliseconds
#: daemon/HTTPServer.cpp:494 daemon/HTTPServer.cpp:514
#: daemon/HTTPServer.cpp:711 daemon/HTTPServer.cpp:731
#: daemon/HTTPServer.cpp:469 daemon/HTTPServer.cpp:489
#: daemon/HTTPServer.cpp:681 daemon/HTTPServer.cpp:701
#, c-format
msgid "%dms"
msgstr ""
#: daemon/HTTPServer.cpp:499 daemon/HTTPServer.cpp:716
#: daemon/HTTPServer.cpp:474 daemon/HTTPServer.cpp:686
msgid "Outbound tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:521
#: daemon/HTTPServer.cpp:496
msgid "Tags"
msgstr ""
#: daemon/HTTPServer.cpp:522
#: daemon/HTTPServer.cpp:497
msgid "Incoming"
msgstr ""
#: daemon/HTTPServer.cpp:529 daemon/HTTPServer.cpp:535
#: daemon/HTTPServer.cpp:504 daemon/HTTPServer.cpp:510
msgid "Outgoing"
msgstr ""
#: daemon/HTTPServer.cpp:532 daemon/HTTPServer.cpp:551
#: daemon/HTTPServer.cpp:507 daemon/HTTPServer.cpp:526
msgid "Destination"
msgstr ""
#: daemon/HTTPServer.cpp:532 daemon/HTTPServer.cpp:814
#: daemon/HTTPServer.cpp:507
msgid "Amount"
msgstr ""
#: daemon/HTTPServer.cpp:540
#: daemon/HTTPServer.cpp:515
msgid "Incoming Tags"
msgstr ""
#: daemon/HTTPServer.cpp:548 daemon/HTTPServer.cpp:554
#: daemon/HTTPServer.cpp:523 daemon/HTTPServer.cpp:529
msgid "Tags sessions"
msgstr ""
#: daemon/HTTPServer.cpp:551
#: daemon/HTTPServer.cpp:526
msgid "Status"
msgstr ""
#: daemon/HTTPServer.cpp:561 daemon/HTTPServer.cpp:621
#: daemon/HTTPServer.cpp:536 daemon/HTTPServer.cpp:594
msgid "Local Destination"
msgstr ""
#: daemon/HTTPServer.cpp:572 daemon/HTTPServer.cpp:960
#: daemon/HTTPServer.cpp:547 daemon/HTTPServer.cpp:917
msgid "Streams"
msgstr ""
#: daemon/HTTPServer.cpp:595
#: daemon/HTTPServer.cpp:570
msgid "Close stream"
msgstr ""
#: daemon/HTTPServer.cpp:613 daemon/HTTPServer.cpp:1430
msgid "Such destination is not found"
msgstr ""
#: daemon/HTTPServer.cpp:626
#: daemon/HTTPServer.cpp:599
msgid "I2CP session not found"
msgstr ""
#: daemon/HTTPServer.cpp:629
#: daemon/HTTPServer.cpp:602
msgid "I2CP is not enabled"
msgstr ""
#: daemon/HTTPServer.cpp:658
#: daemon/HTTPServer.cpp:628
msgid "Invalid"
msgstr ""
#: daemon/HTTPServer.cpp:661
#: daemon/HTTPServer.cpp:631
msgid "Store type"
msgstr ""
#: daemon/HTTPServer.cpp:662
#: daemon/HTTPServer.cpp:632
msgid "Expires"
msgstr ""
#: daemon/HTTPServer.cpp:667
#: daemon/HTTPServer.cpp:637
msgid "Non Expired Leases"
msgstr ""
#: daemon/HTTPServer.cpp:670
#: daemon/HTTPServer.cpp:640
msgid "Gateway"
msgstr ""
#: daemon/HTTPServer.cpp:671
#: daemon/HTTPServer.cpp:641
msgid "TunnelID"
msgstr ""
#: daemon/HTTPServer.cpp:672
#: daemon/HTTPServer.cpp:642
msgid "EndDate"
msgstr ""
#: daemon/HTTPServer.cpp:682
#: daemon/HTTPServer.cpp:652
msgid "floodfill mode is disabled"
msgstr ""
#: daemon/HTTPServer.cpp:693
#: daemon/HTTPServer.cpp:663
msgid "Queue size"
msgstr ""
#: daemon/HTTPServer.cpp:743
#: daemon/HTTPServer.cpp:713
msgid "Run peer test"
msgstr ""
#: daemon/HTTPServer.cpp:744
#: daemon/HTTPServer.cpp:714
msgid "Reload tunnels configuration"
msgstr ""
#: daemon/HTTPServer.cpp:747
#: daemon/HTTPServer.cpp:717
msgid "Decline transit tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:749
#: daemon/HTTPServer.cpp:719
msgid "Accept transit tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:753 daemon/HTTPServer.cpp:758
#: daemon/HTTPServer.cpp:723 daemon/HTTPServer.cpp:728
msgid "Cancel graceful shutdown"
msgstr ""
#: daemon/HTTPServer.cpp:755 daemon/HTTPServer.cpp:760
#: daemon/HTTPServer.cpp:725 daemon/HTTPServer.cpp:730
msgid "Start graceful shutdown"
msgstr ""
#: daemon/HTTPServer.cpp:763
#: daemon/HTTPServer.cpp:733
msgid "Force shutdown"
msgstr ""
#: daemon/HTTPServer.cpp:764
#: daemon/HTTPServer.cpp:734
msgid "Reload external CSS styles"
msgstr ""
#: daemon/HTTPServer.cpp:767
#: daemon/HTTPServer.cpp:737
msgid ""
"<b>Note:</b> any action done here are not persistent and not changes your "
"config files."
msgstr ""
#: daemon/HTTPServer.cpp:770
#: daemon/HTTPServer.cpp:739
msgid "Logging level"
msgstr ""
#: daemon/HTTPServer.cpp:779
#: daemon/HTTPServer.cpp:747
msgid "Transit tunnels limit"
msgstr ""
#: daemon/HTTPServer.cpp:784 daemon/HTTPServer.cpp:803
#: daemon/HTTPServer.cpp:752 daemon/HTTPServer.cpp:771
msgid "Change"
msgstr ""
#: daemon/HTTPServer.cpp:791
#: daemon/HTTPServer.cpp:759
msgid "Change language"
msgstr ""
#: daemon/HTTPServer.cpp:830
#: daemon/HTTPServer.cpp:797
msgid "no transit tunnels currently built"
msgstr ""
#: daemon/HTTPServer.cpp:921 daemon/HTTPServer.cpp:944
#: daemon/HTTPServer.cpp:878 daemon/HTTPServer.cpp:901
msgid "SAM disabled"
msgstr ""
#: daemon/HTTPServer.cpp:937
#: daemon/HTTPServer.cpp:894
msgid "no sessions currently running"
msgstr ""
#: daemon/HTTPServer.cpp:950
#: daemon/HTTPServer.cpp:907
msgid "SAM session not found"
msgstr ""
#: daemon/HTTPServer.cpp:955
#: daemon/HTTPServer.cpp:912
msgid "SAM Session"
msgstr ""
#: daemon/HTTPServer.cpp:1020
#: daemon/HTTPServer.cpp:969
msgid "Server Tunnels"
msgstr ""
#: daemon/HTTPServer.cpp:1036
#: daemon/HTTPServer.cpp:985
msgid "Client Forwards"
msgstr ""
#: daemon/HTTPServer.cpp:1050
#: daemon/HTTPServer.cpp:999
msgid "Server Forwards"
msgstr ""
#: daemon/HTTPServer.cpp:1250
#: daemon/HTTPServer.cpp:1199
msgid "Unknown page"
msgstr ""
#: daemon/HTTPServer.cpp:1269
#: daemon/HTTPServer.cpp:1218
msgid "Invalid token"
msgstr ""
#: daemon/HTTPServer.cpp:1327 daemon/HTTPServer.cpp:1359
#: daemon/HTTPServer.cpp:1414 daemon/HTTPServer.cpp:1454
#: daemon/HTTPServer.cpp:1276 daemon/HTTPServer.cpp:1333
#: daemon/HTTPServer.cpp:1373
msgid "SUCCESS"
msgstr ""
#: daemon/HTTPServer.cpp:1327
#: daemon/HTTPServer.cpp:1276
msgid "Stream closed"
msgstr ""
#: daemon/HTTPServer.cpp:1329
#: daemon/HTTPServer.cpp:1278
msgid "Stream not found or already was closed"
msgstr ""
#: daemon/HTTPServer.cpp:1332 daemon/HTTPServer.cpp:1365
#: daemon/HTTPServer.cpp:1281
msgid "Destination not found"
msgstr ""
#: daemon/HTTPServer.cpp:1335
#: daemon/HTTPServer.cpp:1284
msgid "StreamID can't be null"
msgstr ""
#: daemon/HTTPServer.cpp:1337 daemon/HTTPServer.cpp:1367
#: daemon/HTTPServer.cpp:1432
#: daemon/HTTPServer.cpp:1286 daemon/HTTPServer.cpp:1351
msgid "Return to destination page"
msgstr ""
#: daemon/HTTPServer.cpp:1338 daemon/HTTPServer.cpp:1368
#: daemon/HTTPServer.cpp:1381 daemon/HTTPServer.cpp:1456
#: daemon/HTTPServer.cpp:1287 daemon/HTTPServer.cpp:1300
#: daemon/HTTPServer.cpp:1375
#, c-format
msgid "You will be redirected in %d seconds"
msgstr ""
#: daemon/HTTPServer.cpp:1359
msgid "LeaseSet expiration time updated"
msgstr ""
#: daemon/HTTPServer.cpp:1362
msgid "LeaseSet is not found or already expired"
msgstr ""
#: daemon/HTTPServer.cpp:1379
#: daemon/HTTPServer.cpp:1298
#, c-format
msgid "Transit tunnels count must not exceed %d"
msgstr ""
#: daemon/HTTPServer.cpp:1380 daemon/HTTPServer.cpp:1455
#: daemon/HTTPServer.cpp:1299 daemon/HTTPServer.cpp:1374
msgid "Back to commands list"
msgstr ""
#: daemon/HTTPServer.cpp:1416
#: daemon/HTTPServer.cpp:1335
msgid "Register at reg.i2p"
msgstr ""
#: daemon/HTTPServer.cpp:1417
#: daemon/HTTPServer.cpp:1336
msgid "Description"
msgstr ""
#: daemon/HTTPServer.cpp:1417
#: daemon/HTTPServer.cpp:1336
msgid "A bit information about service on domain"
msgstr ""
#: daemon/HTTPServer.cpp:1418
#: daemon/HTTPServer.cpp:1337
msgid "Submit"
msgstr ""
#: daemon/HTTPServer.cpp:1424
#: daemon/HTTPServer.cpp:1343
msgid "Domain can't end with .b32.i2p"
msgstr ""
#: daemon/HTTPServer.cpp:1427
#: daemon/HTTPServer.cpp:1346
msgid "Domain must end with .i2p"
msgstr ""
#: daemon/HTTPServer.cpp:1450
#: daemon/HTTPServer.cpp:1349
msgid "Such destination is not found"
msgstr ""
#: daemon/HTTPServer.cpp:1369
msgid "Unknown command"
msgstr ""
#: daemon/HTTPServer.cpp:1454
#: daemon/HTTPServer.cpp:1373
msgid "Command accepted"
msgstr ""
@ -642,20 +624,20 @@ msgstr ""
msgid "You may try to find this host on jump services below"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:333 libi2pd_client/HTTPProxy.cpp:348
#: libi2pd_client/HTTPProxy.cpp:417 libi2pd_client/HTTPProxy.cpp:460
#: libi2pd_client/HTTPProxy.cpp:309 libi2pd_client/HTTPProxy.cpp:324
#: libi2pd_client/HTTPProxy.cpp:392 libi2pd_client/HTTPProxy.cpp:435
msgid "Invalid request"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:333
#: libi2pd_client/HTTPProxy.cpp:309
msgid "Proxy unable to parse your request"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:348
#: libi2pd_client/HTTPProxy.cpp:324
msgid "Addresshelper is not supported"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:373
#: libi2pd_client/HTTPProxy.cpp:349
#, c-format
msgid ""
"Host %s is <font color=red>already in router's addressbook</font>. <b>Be "
@ -663,121 +645,121 @@ msgid ""
"<a href=\"%s%s%s&update=true\">Continue</a>."
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:375
#: libi2pd_client/HTTPProxy.cpp:351
msgid "Addresshelper forced update rejected"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:382
#: libi2pd_client/HTTPProxy.cpp:358
#, c-format
msgid ""
"To add host <b>%s</b> in router's addressbook, click here: <a "
"href=\"%s%s%s\">Continue</a>."
"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s"
"\">Continue</a>."
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:384
#: libi2pd_client/HTTPProxy.cpp:360
msgid "Addresshelper request"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:393
#: libi2pd_client/HTTPProxy.cpp:369
#, c-format
msgid ""
"Host %s added to router's addressbook from helper. Click here to proceed: <a "
"href=\"%s\">Continue</a>."
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:395
#: libi2pd_client/HTTPProxy.cpp:370
msgid "Addresshelper adding"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:402
#: libi2pd_client/HTTPProxy.cpp:377
#, c-format
msgid ""
"Host %s is <font color=red>already in router's addressbook</font>. Click "
"here to update record: <a href=\"%s%s%s&update=true\">Continue</a>."
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:404
#: libi2pd_client/HTTPProxy.cpp:379
msgid "Addresshelper update"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:417
#: libi2pd_client/HTTPProxy.cpp:392
msgid "Invalid request URI"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:460
#: libi2pd_client/HTTPProxy.cpp:435
msgid "Can't detect destination host from request"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:477 libi2pd_client/HTTPProxy.cpp:481
#: libi2pd_client/HTTPProxy.cpp:452 libi2pd_client/HTTPProxy.cpp:456
msgid "Outproxy failure"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:477
#: libi2pd_client/HTTPProxy.cpp:452
msgid "Bad outproxy settings"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:480
#: libi2pd_client/HTTPProxy.cpp:455
#, c-format
msgid "Host %s is not inside I2P network, but outproxy is not enabled"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:569
#: libi2pd_client/HTTPProxy.cpp:544
msgid "Unknown outproxy URL"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:575
#: libi2pd_client/HTTPProxy.cpp:550
msgid "Cannot resolve upstream proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:583
#: libi2pd_client/HTTPProxy.cpp:558
msgid "Hostname is too long"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:610
#: libi2pd_client/HTTPProxy.cpp:585
msgid "Cannot connect to upstream SOCKS proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:616
#: libi2pd_client/HTTPProxy.cpp:591
msgid "Cannot negotiate with SOCKS proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:658
#: libi2pd_client/HTTPProxy.cpp:633
msgid "CONNECT error"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:658
#: libi2pd_client/HTTPProxy.cpp:633
msgid "Failed to connect"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:669 libi2pd_client/HTTPProxy.cpp:695
#: libi2pd_client/HTTPProxy.cpp:644 libi2pd_client/HTTPProxy.cpp:670
msgid "SOCKS proxy error"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:677
#: libi2pd_client/HTTPProxy.cpp:652
msgid "Failed to send request to upstream"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:698
#: libi2pd_client/HTTPProxy.cpp:673
msgid "No reply from SOCKS proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:705
#: libi2pd_client/HTTPProxy.cpp:680
msgid "Cannot connect"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:705
#: libi2pd_client/HTTPProxy.cpp:680
msgid "HTTP out proxy not implemented"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:706
#: libi2pd_client/HTTPProxy.cpp:681
msgid "Cannot connect to upstream HTTP proxy"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:739
#: libi2pd_client/HTTPProxy.cpp:714
msgid "Host is down"
msgstr ""
#: libi2pd_client/HTTPProxy.cpp:739
#: libi2pd_client/HTTPProxy.cpp:714
msgid ""
"Can't create connection to requested host, it may be down. Please try again "
"later."

@ -2,17 +2,12 @@
---
```
xgettext --omit-header -ctr: -ktr -kntr:1,2 daemon/HTTPServer.cpp libi2pd_client/HTTPProxy.cpp
xgettext --omit-header -ctr: -ktr -ktr:1,2 daemon/HTTPServer.cpp libi2pd_client/HTTPProxy.cpp
```
Regex for transforming gettext translations to our format:
---
```
in: ^(\"|#[:.,]|msgctxt)(.*)$\n
out: <to empty line>
```
```
in: msgid\ \"(.*)\"\nmsgid_plural\ \"(.*)\"\nmsgstr\[0\]\ \"(.*)\"\n(msgstr\[1\]\ \"(.*)\"\n)?(msgstr\[2\]\ \"(.*)\"\n)?(msgstr\[3\]\ \"(.*)\"\n)?(msgstr\[4\]\ \"(.*)\"\n)?(msgstr\[5\]\ \"(.*)\"\n)?
out: #{"$2", {"$3", "$5", "$7", "$9", "$11"}},\n
@ -23,6 +18,10 @@ in: msgid\ \"(.*)\"\nmsgstr\ \"(.*)\"\n
out: {"$1", "$2"},\n
```
```
in: ^#[:.,](.*)$\n
out: <to empty line>
```
```
in: \n\n

@ -19,7 +19,7 @@
## Default: ~/.i2pd/certificates or /var/lib/i2pd/certificates
# certsdir = /var/lib/i2pd/certificates
## Where to write pidfile (default: /run/i2pd.pid, not used in Windows)
## Where to write pidfile (default: i2pd.pid, not used in Windows)
# pidfile = /run/i2pd.pid
## Logging configuration section
@ -31,16 +31,15 @@
## * file - log entries to a file
## * syslog - use syslog, see man 3 syslog
# log = file
## Path to logfile (default: autodetect)
## Path to logfile (default - autodetect)
# logfile = /var/log/i2pd/i2pd.log
## Log messages above this level (debug, info, *warn, error, critical, none)
## Log messages above this level (debug, info, *warn, error, none)
## If you set it to none, logging will be disabled
# loglevel = warn
## Write full CLF-formatted date and time to log (default: write only time)
# logclftime = true
## Daemon mode. Router will go to background after start. Ignored on Windows
## (default: true)
# daemon = true
## Specify a family, router belongs to (default - none)
@ -71,60 +70,58 @@
## don't just uncomment this
# port = 4567
## Enable communication through ipv4 (default: true)
## Enable communication through ipv4
ipv4 = true
## Enable communication through ipv6 (default: false)
## Enable communication through ipv6
ipv6 = false
## Enable SSU transport
ssu = false
## Bandwidth configuration
## L limit bandwidth to 32 KB/sec, O - to 256 KB/sec, P - to 2048 KB/sec,
## L limit bandwidth to 32KBs/sec, O - to 256KBs/sec, P - to 2048KBs/sec,
## X - unlimited
## 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. Value can be set to
## integer in kilobytes, it will apply that limit and flag will be used
## from next upper limit (example: if you set 4096 flag will be X, but real
## limit will be 4096 KB/s). Same can be done when floodfill mode is used,
## but keep in mind that low values may be negatively evaluated by Java
## router algorithms.
## 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
## Max % of bandwidth limit for transit. 0-100 (default: 100)
## Max % of bandwidth limit for transit. 0-100. 100 by default
# share = 100
## Router will not accept transit tunnels, disabling transit traffic completely
## (default: false)
## (default = false)
# notransit = true
## Router will be floodfill (default: false)
## Router will be floodfill
## Note: that mode uses much more network connections and CPU!
# floodfill = true
[ntcp2]
## Enable NTCP2 transport (default: true)
## Enable NTCP2 transport (default = true)
# enabled = true
## Publish address in RouterInfo (default: true)
## Publish address in RouterInfo (default = true)
# published = true
## Port for incoming connections (default is global port option value)
# port = 4567
[ssu2]
## Enable SSU2 transport (default: true)
## Enable SSU2 transport
# enabled = true
## Publish address in RouterInfo (default: true)
## Publish address in RouterInfo
# published = true
## Port for incoming connections (default is global port option value)
## Port for incoming connections (default is global port option value or port + 1 if SSU is enabled)
# port = 4567
[http]
## Web Console settings
## Enable the Web Console (default: true)
## Uncomment and set to 'false' to disable Web Console
# enabled = true
## Address and port service will listen on (default: 127.0.0.1:7070)
# address = 127.0.0.1
# port = 7070
## Path to web console (default: /)
## Address and port service will listen on
address = 127.0.0.1
port = 7070
## Path to web console, default "/"
# webroot = /
## Enable Web Console authentication (default: false)
## Uncomment following lines to enable Web Console authentication
## You should not use Web Console via public networks without additional encryption.
## HTTP authentication is not encryption layer!
# auth = true
@ -132,17 +129,16 @@ ipv6 = false
# pass = changeme
## Select webconsole language
## Currently supported english (default), afrikaans, armenian, chinese, czech, french,
## german, italian, polish, portuguese, russian, spanish, turkish, turkmen, ukrainian
## and uzbek languages
## german, italian, russian, spanish, turkmen, ukrainian and uzbek languages
# lang = english
[httpproxy]
## Enable the HTTP proxy (default: true)
## Uncomment and set to 'false' to disable HTTP Proxy
# enabled = true
## Address and port service will listen on (default: 127.0.0.1:4444)
# address = 127.0.0.1
# port = 4444
## Optional keys file for proxy local destination (default: http-proxy-keys.dat)
## Address and port service will listen on
address = 127.0.0.1
port = 4444
## Optional keys file for proxy local destination
# keys = http-proxy-keys.dat
## Enable address helper for adding .i2p domains with "jump URLs" (default: true)
## You should disable this feature if your i2pd HTTP Proxy is public,
@ -153,15 +149,15 @@ ipv6 = false
## httpproxy section also accepts I2CP parameters, like "inbound.length" etc.
[socksproxy]
## Enable the SOCKS proxy (default: true)
## Uncomment and set to 'false' to disable SOCKS Proxy
# enabled = true
## Address and port service will listen on (default: 127.0.0.1:4447)
# address = 127.0.0.1
# port = 4447
## Optional keys file for proxy local destination (default: socks-proxy-keys.dat)
## Address and port service will listen on
address = 127.0.0.1
port = 4447
## Optional keys file for proxy local destination
# keys = socks-proxy-keys.dat
## Socks outproxy. Example below is set to use Tor for all connections except i2p
## Enable using of SOCKS outproxy (works only with SOCKS4, default: false)
## Uncomment and set to 'true' to enable using of SOCKS outproxy
# outproxy.enabled = false
## Address and port of outproxy
# outproxy = 127.0.0.1
@ -169,34 +165,33 @@ ipv6 = false
## socksproxy section also accepts I2CP parameters, like "inbound.length" etc.
[sam]
## Enable the SAM bridge (default: true)
# enabled = false
## Address and ports service will listen on (default: 127.0.0.1:7656, udp: 7655)
## Comment or set to 'false' to disable SAM Bridge
enabled = true
## Address and port service will listen on
# address = 127.0.0.1
# port = 7656
# portudp = 7655
[bob]
## Enable the BOB command channel (default: false)
## Uncomment and set to 'true' to enable BOB command channel
# enabled = false
## Address and port service will listen on (default: 127.0.0.1:2827)
## Address and port service will listen on
# address = 127.0.0.1
# port = 2827
[i2cp]
## Enable the I2CP protocol (default: false)
## Uncomment and set to 'true' to enable I2CP protocol
# enabled = false
## Address and port service will listen on (default: 127.0.0.1:7654)
## Address and port service will listen on
# address = 127.0.0.1
# port = 7654
[i2pcontrol]
## Enable the I2PControl protocol (default: false)
## Uncomment and set to 'true' to enable I2PControl protocol
# enabled = false
## Address and port service will listen on (default: 127.0.0.1:7650)
## Address and port service will listen on
# address = 127.0.0.1
# port = 7650
## Authentication password (default: itoopie)
## Authentication password. "itoopie" by default
# password = itoopie
[precomputation]
@ -207,11 +202,11 @@ ipv6 = false
[upnp]
## Enable or disable UPnP: automatic port forwarding (enabled by default in WINDOWS, ANDROID)
# enabled = false
## Name i2pd appears in UPnP forwardings list (default: I2Pd)
## Name i2pd appears in UPnP forwardings list (default = I2Pd)
# name = I2Pd
[meshnets]
## Enable connectivity over the Yggdrasil network (default: false)
## Enable connectivity over the Yggdrasil network
# yggdrasil = false
## You can bind address from your Yggdrasil subnet 300::/64
## The address must first be added to the network interface
@ -219,13 +214,13 @@ ipv6 = false
[reseed]
## Options for bootstrapping into I2P network, aka reseeding
## Enable reseed data verification (default: true)
## Enable or disable reseed data verification.
verify = true
## URLs to request reseed data from, separated by comma
## Default: "mainline" I2P Network reseeds
# urls = https://reseed.i2p-projekt.de/,https://i2p.mooo.com/netDb/,https://netdb.i2p2.no/
## Reseed URLs through the Yggdrasil, separated by comma
# yggurls = http://[324:71e:281a:9ed3::ace]:7070/
# yggurls = http://[324:9de3:fea4:f6ac::ace]:7070/
## Path to local reseed data file (.su3) for manual reseeding
# file = /path/to/i2pseeds.su3
## or HTTPS URL to reseed from
@ -235,7 +230,7 @@ verify = true
## If you run i2pd behind a proxy server, set proxy server for reseeding here
## Should be http://address:port or socks://address:port
# proxy = http://127.0.0.1:8118
## Minimum number of known routers, below which i2pd triggers reseeding (default: 25)
## Minimum number of known routers, below which i2pd triggers reseeding. 25 by default
# threshold = 25
[addressbook]
@ -255,13 +250,13 @@ verify = true
# coresize = 0
[trust]
## Enable explicit trust options. (default: false)
## Enable explicit trust options. false by default
# enabled = true
## Make direct I2P connections only to routers in specified Family.
# family = MyFamily
## Make direct I2P connections only to routers specified here. Comma separated list of base64 identities.
# routers =
## Should we hide our router from other routers? (default: false)
## Should we hide our router from other routers? false by default
# hidden = true
[exploratory]
@ -280,6 +275,8 @@ verify = true
[cpuext]
## Use CPU AES-NI instructions set when work with cryptography when available (default: true)
# aesni = true
## Force usage of CPU instructions set, even if they not found (default: false)
## Use CPU AVX instructions set when work with cryptography when available (default: true)
# avx = true
## Force usage of CPU instructions set, even if they not found
## DO NOT TOUCH that option if you really don't know what are you doing!
# force = false

@ -1,7 +1,7 @@
%define git_hash %(git rev-parse HEAD | cut -c -7)
Name: i2pd-git
Version: 2.52.0
Version: 2.46.0
Release: git%{git_hash}%{?dist}
Summary: I2P router written in C++
Conflicts: i2pd
@ -28,11 +28,9 @@ Requires: logrotate
Requires: systemd
Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd
%description
C++ implementation of I2P.
%prep
%setup -q -n i2pd-openssl
@ -40,56 +38,72 @@ C++ implementation of I2P.
%build
cd build
%if 0%{?rhel} == 7
%cmake3 \
%cmake3 \
-DWITH_LIBRARY=OFF \
-DWITH_UPNP=ON \
-DWITH_HARDENING=ON \
-DBUILD_SHARED_LIBS:BOOL=OFF
%else
%cmake \
%cmake \
-DWITH_LIBRARY=OFF \
-DWITH_UPNP=ON \
-DWITH_HARDENING=ON \
%if 0%{?fedora} > 29
%if 0%{?fedora} > 29
-DBUILD_SHARED_LIBS:BOOL=OFF \
.
%else
%else
-DBUILD_SHARED_LIBS:BOOL=OFF
%endif
%endif
%endif
%if 0%{?rhel} == 9
pushd redhat-linux-build
%endif
%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln}
pushd redhat-linux-build
%if 0%{?fedora} >= 35
pushd redhat-linux-build
%else
%if 0%{?fedora} >= 33
pushd %{_target_platform}
%endif
%if 0%{?fedora} >= 33
pushd %{_target_platform}
%endif
%endif
%if 0%{?mageia} > 7
pushd build
%endif
%if 0%{?mageia} > 7
pushd build
%endif
make %{?_smp_mflags}
%if 0%{?rhel} == 9 || 0%{?fedora} >= 33 || 0%{?mageia} > 7
popd
%if 0%{?rhel} == 9
popd
%endif
%if 0%{?fedora} >= 33
popd
%endif
%if 0%{?mageia} > 7
popd
%endif
%install
pushd build
%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln}
pushd redhat-linux-build
%if 0%{?rhel} == 9
pushd redhat-linux-build
%endif
%if 0%{?fedora} >= 35
pushd redhat-linux-build
%else
%if 0%{?fedora} >= 33
pushd %{_target_platform}
%endif
%if 0%{?fedora} >= 33
pushd %{_target_platform}
%endif
%endif
%if 0%{?mageia}
pushd build
%endif
%if 0%{?mageia}
pushd build
%endif
chrpath -d i2pd
@ -144,33 +158,6 @@ getent passwd i2pd >/dev/null || \
%changelog
* Sun May 12 2024 orignal <orignal@i2pmail.org> - 2.52.0
- update to 2.52.0
* Sat Apr 06 2024 orignal <orignal@i2pmail.org> - 2.51.0
- update to 2.51.0
* Sat Jan 06 2024 orignal <orignal@i2pmail.org> - 2.50.2
- update to 2.50.2
* Sat Dec 23 2023 r4sas <r4sas@i2pmail.org> - 2.50.1
- update to 2.50.1
* Mon Dec 18 2023 orignal <orignal@i2pmail.org> - 2.50.0
- update to 2.50.0
* Mon Sep 18 2023 orignal <orignal@i2pmail.org> - 2.49.0
- update to 2.49.0
* Mon Jun 12 2023 orignal <orignal@i2pmail.org> - 2.48.0
- update to 2.48.0
* Sat Mar 11 2023 orignal <orignal@i2pmail.org> - 2.47.0
- update to 2.47.0
* Mon Feb 20 2023 r4sas <r4sas@i2pmail.org> - 2.46.1
- update to 2.46.1
* Wed Feb 15 2023 orignal <orignal@i2pmail.org> - 2.46.0
- update to 2.46.0

@ -1,5 +1,5 @@
Name: i2pd
Version: 2.52.0
Version: 2.46.0
Release: 1%{?dist}
Summary: I2P router written in C++
Conflicts: i2pd-git
@ -26,11 +26,9 @@ Requires: logrotate
Requires: systemd
Requires(pre): %{_sbindir}/useradd %{_sbindir}/groupadd
%description
C++ implementation of I2P.
%prep
%setup -q
@ -38,56 +36,71 @@ C++ implementation of I2P.
%build
cd build
%if 0%{?rhel} == 7
%cmake3 \
%cmake3 \
-DWITH_LIBRARY=OFF \
-DWITH_UPNP=ON \
-DWITH_HARDENING=ON \
-DBUILD_SHARED_LIBS:BOOL=OFF
%else
%cmake \
%cmake \
-DWITH_LIBRARY=OFF \
-DWITH_UPNP=ON \
-DWITH_HARDENING=ON \
%if 0%{?fedora} > 29
%if 0%{?fedora} > 29
-DBUILD_SHARED_LIBS:BOOL=OFF \
.
%else
%else
-DBUILD_SHARED_LIBS:BOOL=OFF
%endif
%endif
%endif
%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln}
pushd redhat-linux-build
%if 0%{?rhel} == 9
pushd redhat-linux-build
%endif
%if 0%{?fedora} >= 35
pushd redhat-linux-build
%else
%if 0%{?fedora} >= 33
pushd %{_target_platform}
%endif
%if 0%{?fedora} >= 33
pushd %{_target_platform}
%endif
%endif
%if 0%{?mageia} > 7
pushd build
%endif
%if 0%{?mageia} > 7
pushd build
%endif
make %{?_smp_mflags}
%if 0%{?rhel} == 9 || 0%{?fedora} >= 33 || 0%{?mageia} > 7
popd
%if 0%{?rhel} == 9
popd
%endif
%if 0%{?fedora} >= 33
popd
%endif
%if 0%{?mageia} > 7
popd
%endif
%install
pushd build
%if 0%{?rhel} == 9 || 0%{?fedora} >= 35 || 0%{?eln}
pushd redhat-linux-build
%if 0%{?rhel} == 9
pushd redhat-linux-build
%endif
%if 0%{?fedora} >= 35
pushd redhat-linux-build
%else
%if 0%{?fedora} >= 33
pushd %{_target_platform}
%endif
%if 0%{?fedora} >= 33
pushd %{_target_platform}
%endif
%endif
%if 0%{?mageia}
pushd build
%endif
%if 0%{?mageia}
pushd build
%endif
chrpath -d i2pd
@ -142,33 +155,6 @@ getent passwd i2pd >/dev/null || \
%changelog
* Sun May 12 2024 orignal <orignal@i2pmail.org> - 2.52.0
- update to 2.52.0
* Sat Apr 06 2024 orignal <orignal@i2pmail.org> - 2.51.0
- update to 2.51.0
* Sat Jan 06 2024 orignal <orignal@i2pmail.org> - 2.50.2
- update to 2.50.2
* Sat Dec 23 2023 r4sas <r4sas@i2pmail.org> - 2.50.1
- update to 2.50.1
* Mon Dec 18 2023 orignal <orignal@i2pmail.org> - 2.50.0
- update to 2.50.0
* Mon Sep 18 2023 orignal <orignal@i2pmail.org> - 2.49.0
- update to 2.49.0
* Mon Jun 12 2023 orignal <orignal@i2pmail.org> - 2.48.0
- update to 2.48.0
* Sat Mar 11 2023 orignal <orignal@i2pmail.org> - 2.47.0
- update to 2.47.0
* Mon Feb 20 2023 r4sas <r4sas@i2pmail.org> - 2.46.1
- update to 2.46.1
* Wed Feb 15 2023 orignal <orignal@i2pmail.org> - 2.46.0
- update to 2.46.0

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2024, The PurpleI2P Project
* Copyright (c) 2013-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -150,20 +150,17 @@ namespace util
bool precomputation; i2p::config::GetOption("precomputation.elgamal", precomputation);
bool aesni; i2p::config::GetOption("cpuext.aesni", aesni);
bool avx; i2p::config::GetOption("cpuext.avx", avx);
bool forceCpuExt; i2p::config::GetOption("cpuext.force", forceCpuExt);
bool ssu; i2p::config::GetOption("ssu", ssu);
if (!ssu && i2p::config::IsDefault ("precomputation.elgamal"))
precomputation = false; // we don't elgamal table if no ssu, unless it's specified explicitly
i2p::crypto::InitCrypto (precomputation, aesni, forceCpuExt);
i2p::crypto::InitCrypto (precomputation, aesni, avx, forceCpuExt);
i2p::transport::InitAddressFromIface (); // get address4/6 from interfaces
int netID; i2p::config::GetOption("netid", netID);
i2p::context.SetNetID (netID);
bool checkReserved; i2p::config::GetOption("reservedrange", checkReserved);
i2p::transport::transports.SetCheckReserved(checkReserved);
i2p::context.Init ();
i2p::transport::InitTransports ();
@ -179,16 +176,16 @@ namespace util
bool transit; i2p::config::GetOption("notransit", transit);
i2p::context.SetAcceptsTunnels (!transit);
uint32_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);
uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);
if (isFloodfill && i2p::config::IsDefault ("limits.transittunnels"))
transitTunnels *= 2; // double default number of transit tunnels for floodfill
i2p::tunnel::tunnels.SetMaxNumTransitTunnels (transitTunnels);
SetMaxNumTransitTunnels (transitTunnels);
/* this section also honors 'floodfill' flag, if set above */
std::string bandwidth; i2p::config::GetOption("bandwidth", bandwidth);
if (bandwidth.length () > 0)
{
if (bandwidth.length () == 1 && ((bandwidth[0] >= 'K' && bandwidth[0] <= 'P') || bandwidth[0] == 'X' ))
if (bandwidth[0] >= 'K' && bandwidth[0] <= 'X')
{
i2p::context.SetBandwidth (bandwidth[0]);
LogPrint(eLogInfo, "Daemon: Bandwidth set to ", i2p::context.GetBandwidthLimit (), "KBps");
@ -272,7 +269,7 @@ namespace util
if (hidden)
{
LogPrint(eLogInfo, "Daemon: Hidden mode enabled");
i2p::context.SetHidden(true);
i2p::data::netdb.SetHidden(true);
}
std::string httpLang; i2p::config::GetOption("http.lang", httpLang);
@ -302,16 +299,18 @@ namespace util
bool ntcp2; i2p::config::GetOption("ntcp2.enabled", ntcp2);
bool ssu2; i2p::config::GetOption("ssu2.enabled", ssu2);
bool checkInReserved; i2p::config::GetOption("reservedrange", checkInReserved);
LogPrint(eLogInfo, "Daemon: Starting Transports");
if(!ssu2) LogPrint(eLogInfo, "Daemon: SSU2 disabled");
if(!ntcp2) LogPrint(eLogInfo, "Daemon: NTCP2 disabled");
i2p::transport::transports.SetCheckReserved(checkInReserved);
i2p::transport::transports.Start(ntcp2, ssu2);
if (i2p::transport::transports.IsBoundSSU2() || i2p::transport::transports.IsBoundNTCP2())
LogPrint(eLogInfo, "Daemon: Transports started");
else
{
LogPrint(eLogCritical, "Daemon: Failed to start Transports");
LogPrint(eLogError, "Daemon: Failed to start Transports");
/** shut down netdb right away */
i2p::transport::transports.Stop();
i2p::data::netdb.Stop();
@ -330,17 +329,15 @@ namespace util
}
catch (std::exception& ex)
{
LogPrint (eLogCritical, "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 ());
}
}
LogPrint(eLogInfo, "Daemon: Starting Tunnels");
i2p::tunnel::tunnels.Start();
LogPrint(eLogInfo, "Daemon: Starting Router context");
i2p::context.Start();
LogPrint(eLogInfo, "Daemon: Starting Client");
i2p::client::context.Start ();
@ -357,7 +354,7 @@ namespace util
}
catch (std::exception& ex)
{
LogPrint (eLogCritical, "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 ());
}
}
@ -369,8 +366,6 @@ namespace util
LogPrint(eLogInfo, "Daemon: Shutting down");
LogPrint(eLogInfo, "Daemon: Stopping Client");
i2p::client::context.Stop();
LogPrint(eLogInfo, "Daemon: Stopping Router context");
i2p::context.Stop();
LogPrint(eLogInfo, "Daemon: Stopping Tunnels");
i2p::tunnel::tunnels.Stop();

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2024, The PurpleI2P Project
* Copyright (c) 2013-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -87,7 +87,6 @@ namespace http {
const char HTTP_COMMAND_GET_REG_STRING[] = "get_reg_string";
const char HTTP_COMMAND_SETLANGUAGE[] = "setlanguage";
const char HTTP_COMMAND_RELOAD_CSS[] = "reload_css";
const char HTTP_COMMAND_EXPIRELEASE[] = "expirelease";
static std::string ConvertTime (uint64_t time)
{
@ -133,19 +132,23 @@ namespace http {
static void ShowTunnelDetails (std::stringstream& s, enum i2p::tunnel::TunnelState eState, bool explr, int bytes)
{
std::string state, stateText;
switch (eState)
{
switch (eState) {
case i2p::tunnel::eTunnelStateBuildReplyReceived :
case i2p::tunnel::eTunnelStatePending : state = "building"; break;
case i2p::tunnel::eTunnelStateBuildFailed : state = "failed"; stateText = "declined"; break;
case i2p::tunnel::eTunnelStateTestFailed : state = "failed"; stateText = "test failed"; break;
case i2p::tunnel::eTunnelStateBuildFailed :
case i2p::tunnel::eTunnelStateTestFailed :
case i2p::tunnel::eTunnelStateFailed : state = "failed"; break;
case i2p::tunnel::eTunnelStateExpiring : state = "expiring"; break;
case i2p::tunnel::eTunnelStateEstablished : state = "established"; break;
default: state = "unknown"; break;
}
if (stateText.empty ()) stateText = tr(state);
if (state == "building") stateText = tr("building");
else if (state == "failed") stateText = tr("failed");
else if (state == "expiring") stateText = tr("expiring");
else if (state == "established") stateText = tr("established");
else stateText = tr("unknown");
s << "<span class=\"tunnel " << state << "\"> " << stateText << ((explr) ? " (" + tr("exploratory") + ")" : "") << "</span>, ";
ShowTraffic(s, bytes);
s << "\r\n";
@ -153,7 +156,7 @@ namespace http {
static void SetLogLevel (const std::string& level)
{
if (level == "none" || level == "critical" || level == "error" || level == "warn" || level == "info" || level == "debug")
if (level == "none" || level == "error" || level == "warn" || level == "info" || level == "debug")
i2p::log::Logger().SetLogLevel(level);
else {
LogPrint(eLogError, "HTTPServer: Unknown loglevel set attempted");
@ -218,19 +221,18 @@ namespace http {
s << "<b>" << tr("ERROR") << ":</b>&nbsp;" << string << "<br>\r\n";
}
static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, bool testing, RouterError error)
static void ShowNetworkStatus (std::stringstream& s, RouterStatus status, RouterError error)
{
switch (status)
{
case eRouterStatusOK: s << tr("OK"); break;
case eRouterStatusTesting: s << tr("Testing"); break;
case eRouterStatusFirewalled: s << tr("Firewalled"); break;
case eRouterStatusUnknown: s << tr("Unknown"); break;
case eRouterStatusProxy: s << tr("Proxy"); break;
case eRouterStatusMesh: s << tr("Mesh"); break;
default: s << tr("Unknown");
}
if (testing)
s << " (" << tr("Testing") << ")";
if (error != eRouterErrorNone)
{
switch (error)
@ -261,12 +263,12 @@ namespace http {
ShowUptime(s, i2p::context.GetUptime ());
s << "<br>\r\n";
s << "<b>" << tr("Network status") << ":</b> ";
ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetTesting(), i2p::context.GetError ());
ShowNetworkStatus (s, i2p::context.GetStatus (), i2p::context.GetError ());
s << "<br>\r\n";
if (i2p::context.SupportsV6 ())
{
s << "<b>" << tr("Network status v6") << ":</b> ";
ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetTestingV6(), i2p::context.GetErrorV6 ());
ShowNetworkStatus (s, i2p::context.GetStatusV6 (), i2p::context.GetErrorV6 ());
s << "<br>\r\n";
}
#if ((!defined(WIN32) && !defined(QT_GUI_LIB) && !defined(ANDROID)) || defined(ANDROID_BINARY))
@ -419,12 +421,8 @@ namespace http {
static void ShowLeaseSetDestination (std::stringstream& s, std::shared_ptr<const i2p::client::LeaseSetDestination> dest, uint32_t token)
{
s << "<b>Base32:</b><br>\r\n<textarea readonly cols=\"80\" rows=\"1\">";
s << dest->GetIdentHash ().ToBase32 () << "</textarea><br>\r\n<br>\r\n";
s << "<b>Base64:</b><br>\r\n<textarea readonly cols=\"80\" rows=\"8\">";
s << dest->GetIdentity ()->ToBase64 () << "</textarea><br>\r\n<br>\r\n";
if (dest->IsEncryptedLeaseSet ())
{
i2p::data::BlindedPublicKey blinded (dest->GetIdentity (), dest->IsPerClientAuth ());
@ -436,11 +434,12 @@ namespace http {
if (dest->IsPublic() && token && !dest->IsEncryptedLeaseSet ())
{
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
auto base32 = dest->GetIdentHash ().ToBase32 ();
s << "<div class='slide'><label for='slide-regaddr'><b>" << tr("Address registration line") << "</b></label>\r\n<input type=\"checkbox\" id=\"slide-regaddr\" />\r\n<div class=\"slidecontent\">\r\n"
"<form method=\"get\" action=\"" << webroot << "\">\r\n"
" <input type=\"hidden\" name=\"cmd\" value=\"" << HTTP_COMMAND_GET_REG_STRING << "\">\r\n"
" <input type=\"hidden\" name=\"token\" value=\"" << token << "\">\r\n"
" <input type=\"hidden\" name=\"b32\" value=\"" << dest->GetIdentHash ().ToBase32 () << "\">\r\n"
" <input type=\"hidden\" name=\"b32\" value=\"" << base32 << "\">\r\n"
" <b>" << tr("Domain") << ":</b>\r\n<input type=\"text\" maxlength=\"67\" name=\"name\" placeholder=\"domain.i2p\" required>\r\n"
" <button type=\"submit\">" << tr("Generate") << "</button>\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";
@ -449,23 +448,9 @@ namespace http {
if (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 style=\"width:5px;\">&nbsp;</th>" // LeaseSet expiration button column
<< "<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\">";
for(auto& it: dest->GetLeaseSets ())
{
s << "<tr>"
<< "<td>" << it.first.ToBase32 () << "</td>"
<< "<td><a class=\"button\" href=\"/?cmd=" << HTTP_COMMAND_EXPIRELEASE<< "&b32=" << dest->GetIdentHash ().ToBase32 ()
<< "&lease=" << it.first.ToBase32 () << "&token=" << token << "\" title=\"" << tr("Expire LeaseSet") << "\"> &#10008; </a></td>"
<< "<td>" << (int)it.second->GetStoreType () << "</td>"
<< "<td>" << (int)it.second->GetEncryptionType () <<"</td>"
<< "</tr>\r\n";
}
s << "<tr><td>" << it.first.ToBase32 () << "</td><td>" << (int)it.second->GetStoreType () << "</td><td>" << (int)it.second->GetEncryptionType () <<"</td></tr>\r\n";
s << "</tbody></table>\r\n</div>\r\n</div>\r\n<br>\r\n";
} else
s << "<b>" << tr("LeaseSets") << ":</b> <i>0</i><br>\r\n<br>\r\n";
@ -606,8 +591,6 @@ namespace http {
}
s << "</tbody>\r\n</table>";
}
else
ShowError(s, tr("Such destination is not found"));
}
void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id)
@ -642,10 +625,7 @@ namespace http {
if (storeType == i2p::data::NETDB_STORE_TYPE_LEASESET)
ls.reset (new i2p::data::LeaseSet (leaseSet->GetBuffer(), leaseSet->GetBufferLen()));
else
{
ls.reset (new i2p::data::LeaseSet2 (storeType));
ls->Update (leaseSet->GetBuffer(), leaseSet->GetBufferLen(), false);
}
ls.reset (new i2p::data::LeaseSet2 (storeType, leaseSet->GetBuffer(), leaseSet->GetBufferLen()));
if (!ls) return;
s << "<div class=\"leaseset listitem";
if (ls->IsExpired())
@ -765,14 +745,13 @@ namespace http {
auto loglevel = i2p::log::Logger().GetLogLevel();
s << "<b>" << tr("Logging level") << "</b><br>\r\n";
s << " <a class=\"button" << (loglevel == eLogNone ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=none&token=" << token << "\"> none </a> \r\n";
s << " <a class=\"button" << (loglevel == eLogCritical ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=critical&token=" << token << "\"> critical </a> \r\n";
s << " <a class=\"button" << (loglevel == eLogError ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=error&token=" << token << "\"> error </a> \r\n";
s << " <a class=\"button" << (loglevel == eLogWarning ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=warn&token=" << token << "\"> warn </a> \r\n";
s << " <a class=\"button" << (loglevel == eLogInfo ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=info&token=" << token << "\"> info </a> \r\n";
s << " <a class=\"button" << (loglevel == eLogDebug ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=debug&token=" << token << "\"> debug </a><br>\r\n<br>\r\n";
uint32_t maxTunnels = i2p::tunnel::tunnels.GetMaxNumTransitTunnels ();
s << " <a class=\"button" << (loglevel == eLogNone ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=none&token=" << token << "\"> none </a> \r\n";
s << " <a class=\"button" << (loglevel == eLogError ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=error&token=" << token << "\"> error </a> \r\n";
s << " <a class=\"button" << (loglevel == eLogWarning ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=warn&token=" << token << "\"> warn </a> \r\n";
s << " <a class=\"button" << (loglevel == eLogInfo ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=info&token=" << token << "\"> info </a> \r\n";
s << " <a class=\"button" << (loglevel == eLogDebug ? " selected" : "") << "\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=debug&token=" << token << "\"> debug </a><br>\r\n<br>\r\n";
uint16_t maxTunnels = GetMaxNumTransitTunnels ();
s << "<b>" << tr("Transit tunnels limit") << "</b><br>\r\n";
s << "<form method=\"get\" action=\"" << webroot << "\">\r\n";
s << " <input type=\"hidden\" name=\"cmd\" value=\"" << HTTP_COMMAND_LIMITTRANSIT << "\">\r\n";
@ -856,7 +835,6 @@ namespace http {
tmp_s << " [itag:" << it->GetRelayTag () << "]";
if (it->GetSendQueueSize () > 0)
tmp_s << " [queue:" << it->GetSendQueueSize () << "]";
if (it->IsSlow ()) tmp_s << " [slow]";
tmp_s << "</div>\r\n" << std::endl;
cnt++;
}
@ -975,42 +953,34 @@ namespace http {
void ShowI2PTunnels (std::stringstream& s)
{
std::string webroot; i2p::config::GetOption("http.webroot", webroot);
auto& clientTunnels = i2p::client::context.GetClientTunnels ();
s << "<b>" << tr("Client Tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
for (auto& it: i2p::client::context.GetClientTunnels ())
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
s << "<div class=\"listitem\"><a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << it.second->GetName () << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "</div>\r\n"<< std::endl;
}
auto httpProxy = i2p::client::context.GetHttpProxy ();
if (httpProxy)
{
auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash();
s << "<div class=\"listitem\"><a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "HTTP " << tr("Proxy") << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "</div>\r\n"<< std::endl;
}
auto socksProxy = i2p::client::context.GetSocksProxy ();
if (!clientTunnels.empty () || httpProxy || socksProxy)
if (socksProxy)
{
s << "<b>" << tr("Client Tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
if (!clientTunnels.empty ())
{
for (auto& it: clientTunnels)
{
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
s << "<div class=\"listitem\"><a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << it.second->GetName () << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "</div>\r\n"<< std::endl;
}
}
if (httpProxy)
{
auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash();
s << "<div class=\"listitem\"><a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "HTTP " << tr("Proxy") << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "</div>\r\n"<< std::endl;
}
if (socksProxy)
{
auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash();
s << "<div class=\"listitem\"><a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "SOCKS " << tr("Proxy") << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "</div>\r\n"<< std::endl;
}
s << "</div>\r\n";
auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash();
s << "<div class=\"listitem\"><a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << "SOCKS " << tr("Proxy") << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "</div>\r\n"<< std::endl;
}
s << "</div>\r\n";
auto& serverTunnels = i2p::client::context.GetServerTunnels ();
if (!serverTunnels.empty ()) {
@ -1337,41 +1307,11 @@ namespace http {
res.add_header("Refresh", redirect.c_str());
return;
}
else if (cmd == HTTP_COMMAND_EXPIRELEASE)
{
std::string b32 = params["b32"];
std::string lease = params["lease"];
i2p::data::IdentHash ident, leaseident;
ident.FromBase32 (b32);
leaseident.FromBase32 (lease);
auto dest = i2p::client::context.FindLocalDestination (ident);
if (dest)
{
auto leaseset = dest->FindLeaseSet (leaseident);
if (leaseset)
{
leaseset->ExpireLease ();
s << "<b>" << tr("SUCCESS") << "</b>:&nbsp;" << tr("LeaseSet expiration time updated") << "<br>\r\n<br>\r\n";
}
else
s << "<b>" << tr("ERROR") << "</b>:&nbsp;" << tr("LeaseSet is not found or already expired") << "<br>\r\n<br>\r\n";
}
else
s << "<b>" << tr("ERROR") << "</b>:&nbsp;" << tr("Destination not found") << "<br>\r\n<br>\r\n";
s << "<a href=\"" << webroot << "?page=local_destination&b32=" << b32 << "\">" << tr("Return to destination page") << "</a><br>\r\n";
s << "<p>" << tr("You will be redirected in %d seconds", COMMAND_REDIRECT_TIMEOUT) << "</b>";
redirect = std::to_string(COMMAND_REDIRECT_TIMEOUT) + "; url=" + webroot + "?page=local_destination&b32=" + b32;
res.add_header("Refresh", redirect.c_str());
return;
}
else if (cmd == HTTP_COMMAND_LIMITTRANSIT)
{
uint32_t limit = std::stoul(params["limit"], nullptr);
if (limit > 0 && limit <= TRANSIT_TUNNELS_LIMIT)
i2p::tunnel::tunnels.SetMaxNumTransitTunnels (limit);
SetMaxNumTransitTunnels (limit);
else {
s << "<b>" << tr("ERROR") << "</b>:&nbsp;" << tr("Transit tunnels count must not exceed %d", TRANSIT_TUNNELS_LIMIT) << "\r\n<br>\r\n<br>\r\n";
s << "<a href=\"" << webroot << "?page=commands\">" << tr("Back to commands list") << "</a>\r\n<br>\r\n";

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2024, The PurpleI2P Project
* Copyright (c) 2013-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -25,7 +25,7 @@ namespace http
const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192;
const int TOKEN_EXPIRATION_TIMEOUT = 30; // in seconds
const int COMMAND_REDIRECT_TIMEOUT = 5; // in seconds
const int TRANSIT_TUNNELS_LIMIT = 1000000;
const int TRANSIT_TUNNELS_LIMIT = 65535;
class HTTPConnection: public std::enable_shared_from_this<HTTPConnection>
{

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2024, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -338,11 +338,10 @@ namespace client
{
for (auto it = params.begin (); it != params.end (); it++)
{
if (it != params.begin ()) results << ",";
LogPrint (eLogDebug, "I2PControl: RouterManager request: ", it->first);
auto it1 = m_RouterManagerHandlers.find (it->first);
if (it1 != m_RouterManagerHandlers.end ())
{
if (it != params.begin ()) results << ",";
if (it1 != m_RouterManagerHandlers.end ()) {
(this->*(it1->second))(results);
} else
LogPrint (eLogError, "I2PControl: RouterManager unknown request: ", it->first);

@ -1,15 +1,10 @@
/*
* Copyright (c) 2013-2024, 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
*/
#ifdef USE_UPNP
#include <string>
#include <thread>
#include <boost/thread/thread.hpp>
#include <boost/asio.hpp>
#include "Log.h"
#include "RouterContext.h"
@ -171,11 +166,11 @@ namespace transport
if (address && !address->host.is_v6 () && address->port)
TryPortMapping (address);
}
m_Timer.expires_from_now (boost::posix_time::minutes(UPNP_PORT_FORWARDING_INTERVAL)); // every 20 minutes
m_Timer.expires_from_now (boost::posix_time::minutes(20)); // every 20 minutes
m_Timer.async_wait ([this](const boost::system::error_code& ecode)
{
if (ecode != boost::asio::error::operation_aborted)
PortMapping ();
PortMapping ();
});
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2024, The PurpleI2P Project
* Copyright (c) 2013-2020, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -28,8 +28,7 @@ namespace i2p
namespace transport
{
const int UPNP_RESPONSE_TIMEOUT = 2000; // in milliseconds
const int UPNP_PORT_FORWARDING_INTERVAL = 20; // in minutes
enum
{
UPNP_IGD_NONE = 0,

@ -162,27 +162,18 @@ namespace i2p
#ifndef ANDROID
if (lockf(pidFH, F_TLOCK, 0) != 0)
#else
struct flock fl;
fl.l_len = 0;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
if (fcntl(pidFH, F_SETLK, &fl) != 0)
#endif
{
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;
}
#endif
char pid[10];
sprintf(pid, "%d\n", getpid());
ftruncate(pidFH, 0);
if (write(pidFH, pid, strlen(pid)) < 0)
{
LogPrint(eLogCritical, "Daemon: Could not write pidfile ", 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;
}

60
debian/changelog vendored

@ -1,63 +1,3 @@
i2pd (2.52.0-1) unstable; urgency=medium
* updated to version 2.52.0
-- orignal <orignal@i2pmail.org> Sun, 12 May 2024 16:00:00 +0000
i2pd (2.51.0-1) unstable; urgency=medium
* updated to version 2.51.0/0.9.62
-- orignal <orignal@i2pmail.org> Sat, 06 Apr 2024 16:00:00 +0000
i2pd (2.50.2-1) unstable; urgency=medium
* updated to version 2.50.2/0.9.61
-- orignal <orignal@i2pmail.org> Sat, 06 Jan 2024 16:00:00 +0000
i2pd (2.50.1-1) unstable; urgency=medium
* updated to version 2.50.1/0.9.61
-- r4sas <r4sas@i2pmail.org> Sat, 23 Dec 2023 18:30:00 +0000
i2pd (2.50.0-1) unstable; urgency=medium
* updated to version 2.50.0/0.9.61
-- orignal <orignal@i2pmail.org> Mon, 18 Dec 2023 16:00:00 +0000
i2pd (2.49.0-1) unstable; urgency=medium
* updated to version 2.49.0/0.9.60
-- orignal <orignal@i2pmail.org> Mon, 18 Sep 2023 16:00:00 +0000
i2pd (2.48.0-1) unstable; urgency=high
* updated to version 2.48.0/0.9.59
-- orignal <orignal@i2pmail.org> Mon, 12 Jun 2023 16:00:00 +0000
i2pd (2.47.0-1) unstable; urgency=high
* updated to version 2.47.0/0.9.58
-- orignal <orignal@i2pmail.org> Sat, 11 Mar 2023 16:00:00 +0000
i2pd (2.46.1-2) unstable; urgency=critical
* re-pushed release due to new critical bug
-- r4sas <r4sas@i2pmail.org> Mon, 20 Feb 2023 23:40:00 +0000
i2pd (2.46.1-1) unstable; urgency=high
* updated to version 2.46.1/0.9.57
-- r4sas <r4sas@i2pmail.org> Mon, 20 Feb 2023 02:45:00 +0000
i2pd (2.46.0-1) unstable; urgency=high
* updated to version 2.46.0/0.9.57

2
debian/i2pd.1 vendored

@ -64,7 +64,7 @@ The network interface to bind to for IPv4 connections
The network interface to bind to for IPv6 connections
.TP
\fB\-\-ipv4=\fR
Enable communication through ipv4 (\fIenabled\fR by default)
Enable communication through ipv6 (\fIenabled\fR by default)
.TP
\fB\-\-ipv6\fR
Enable communication through ipv6 (\fIdisabled\fR by default)

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022-2024, The PurpleI2P Project
* Copyright (c) 2022-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -69,7 +69,6 @@ namespace chinese // language namespace
{"Stopping in", "距停止还有:"},
{"Family", "家族"},
{"Tunnel creation success rate", "隧道创建成功率"},
{"Total tunnel creation success rate", "当前隧道创建成功率"},
{"Received", "已接收"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "已发送"},
@ -96,7 +95,6 @@ namespace chinese // language namespace
{"Address", "地址"},
{"Type", "类型"},
{"EncType", "加密类型"},
{"Expire LeaseSet", "到期租约集"},
{"Inbound tunnels", "入站隧道"},
{"%dms", "%dms"},
{"Outbound tunnels", "出站隧道"},
@ -111,7 +109,6 @@ namespace chinese // language namespace
{"Local Destination", "本地目标"},
{"Streams", ""},
{"Close stream", "断开流"},
{"Such destination is not found", "找不到此目标"},
{"I2CP session not found", "未找到 I2CP 会话"},
{"I2CP is not enabled", "I2CP 未启用"},
{"Invalid", "无效"},
@ -153,8 +150,6 @@ namespace chinese // language namespace
{"StreamID can't be null", "StreamID 不能为空"},
{"Return to destination page", "返回目标页面"},
{"You will be redirected in %d seconds", "您将在%d秒内被重定向"},
{"LeaseSet expiration time updated", "租约集到期时间已更新"},
{"LeaseSet is not found or already expired", "租约集未找到或已过期"},
{"Transit tunnels count must not exceed %d", "中转隧道数量限制为 %d"},
{"Back to commands list", "返回命令列表"},
{"Register at reg.i2p", "在 reg.i2p 注册域名"},
@ -163,6 +158,7 @@ namespace chinese // language namespace
{"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", "代理错误"},

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022-2024, The PurpleI2P Project
* Copyright (c) 2022-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -36,18 +36,18 @@ namespace czech // language namespace
{"%.2f GiB", "%.2f GiB"},
{"building", "vytváří se"},
{"failed", "selhalo"},
{"expiring", "vyprší platnost"},
{"expiring", "končící"},
{"established", "vytvořeno"},
{"unknown", "neznámý"},
{"exploratory", "průzkumné"},
{"Purple I2P Webconsole", "Purple I2P webová konzole"},
{"<b>i2pd</b> webconsole", "<b>i2pd</b> webová konzole"},
{"Purple I2P Webconsole", "Purple I2P Webkonsole"},
{"<b>i2pd</b> webconsole", "<b>i2pd</b> webkonsole"},
{"Main page", "Hlavní stránka"},
{"Router commands", "Router příkazy"},
{"Local Destinations", "Místní cíle"},
{"LeaseSets", "Sety pronájmu"},
{"Local Destinations", "Lokální destinace"},
{"LeaseSets", "LeaseSety"},
{"Tunnels", "Tunely"},
{"Transit Tunnels", "Tranzitní tunely"},
{"Transit Tunnels", "Transitní tunely"},
{"Transports", "Transporty"},
{"I2P tunnels", "I2P tunely"},
{"SAM sessions", "SAM relace"},
@ -61,21 +61,18 @@ namespace czech // language namespace
{"Clock skew", "Časová nesrovnalost"},
{"Offline", "Offline"},
{"Symmetric NAT", "Symetrický NAT"},
{"Full cone NAT", "Full cone NAT"},
{"No Descriptors", "Žádné popisovače"},
{"Uptime", "Doba provozu"},
{"Network status", "Stav sítě"},
{"Network status v6", "Stav sítě v6"},
{"Network status", "Status sítě"},
{"Network status v6", "Status sítě v6"},
{"Stopping in", "Zastavuji za"},
{"Family", "Rodina"},
{"Tunnel creation success rate", "Úspěšnost vytváření tunelů"},
{"Total tunnel creation success rate", "Celková míra úspěšnosti vytváření tunelů"},
{"Received", "Přijato"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "Odesláno"},
{"Transit", "Tranzit"},
{"Data path", "Cesta k datovým souborům"},
{"Hidden content. Press on text to see.", "Skrytý obsah. Pro zobrazení klikněte sem."},
{"Data path", "Cesta k data souborům"},
{"Hidden content. Press on text to see.", "Skrytý kontent. Pro zobrazení, klikni na text."},
{"Router Ident", "Routerová Identita"},
{"Router Family", "Rodina routerů"},
{"Router Caps", "Omezení Routerů"},
@ -96,7 +93,6 @@ namespace czech // language namespace
{"Address", "Adresa"},
{"Type", "Typ"},
{"EncType", "EncType"},
{"Expire LeaseSet", "Zrušit platnost setu pronájmu"},
{"Inbound tunnels", "Příchozí tunely"},
{"%dms", "%dms"},
{"Outbound tunnels", "Odchozí tunely"},
@ -107,24 +103,21 @@ namespace czech // language namespace
{"Amount", "Množství"},
{"Incoming Tags", "Příchozí štítky"},
{"Tags sessions", "Relace štítků"},
{"Status", "Stav"},
{"Local Destination", "Místní cíl"},
{"Status", "Status"},
{"Local Destination", "Lokální Destinace"},
{"Streams", "Toky"},
{"Close stream", "Uzavřít tok"},
{"Such destination is not found", "Takováto destinace nebyla nalezena"},
{"I2CP session not found", "I2CP relace nenalezena"},
{"I2CP is not enabled", "I2CP není zapnuto"},
{"Invalid", "Neplatný"},
{"Store type", "Druh uložení"},
{"Expires", "Vyprší"},
{"Non Expired Leases", "Pronájmy, kterým nevypršela platnost"},
{"Non Expired Leases", "Nevypršené Leasy"},
{"Gateway", "Brána"},
{"TunnelID", "ID tunelu"},
{"EndDate", "Datum ukončení"},
{"floodfill mode is disabled", "režim floodfill je vypnut"},
{"Queue size", "Velikost fronty"},
{"Run peer test", "Spustit peer test"},
{"Reload tunnels configuration", "Znovu načíst nastavení tunelů"},
{"Decline transit tunnels", "Odmítnout tranzitní tunely"},
{"Accept transit tunnels", "Přijmout tranzitní tunely"},
{"Cancel graceful shutdown", "Zrušit hladké vypnutí"},
@ -152,17 +145,14 @@ namespace czech // language namespace
{"Destination not found", "Destinace nenalezena"},
{"StreamID can't be null", "StreamID nemůže být null"},
{"Return to destination page", "Zpět na stránku destinací"},
{"You will be redirected in %d seconds", "Budete přesměrováni za %d sekund"},
{"LeaseSet expiration time updated", "Aktualizován čas vypršení platnosti setu pronájmu"},
{"LeaseSet is not found or already expired", "Set pronájmu není k nalezení nebo již vypršela jeho platnost"},
{"Transit tunnels count must not exceed %d", "Počet tranzitních tunelů nesmí překročit %d"},
{"Back to commands list", "Zpět na seznam příkazů"},
{"Back to commands list", "Zpět na list příkazů"},
{"Register at reg.i2p", "Zaregistrovat na reg.i2p"},
{"Description", "Popis"},
{"A bit information about service on domain", "Trochu informací o službě na doméně"},
{"Submit", "Odeslat"},
{"Domain can't end with .b32.i2p", "Doména nesmí končit na .b32.i2p"},
{"Domain must end with .i2p", "Doména musí končit s .i2p"},
{"Such destination is not found", "Takováto destinace nebyla nalezena"},
{"Unknown command", "Neznámý příkaz"},
{"Command accepted", "Příkaz přijat"},
{"Proxy error", "Chyba proxy serveru"},
@ -172,15 +162,6 @@ namespace czech // language namespace
{"You may try to find this host on jump services below", "Můžete se pokusit najít tohoto hostitele na startovacích službách níže"},
{"Invalid request", "Neplatný požadavek"},
{"Proxy unable to parse your request", "Proxy server nemohl zpracovat váš požadavek"},
{"Addresshelper is not supported", "Addresshelper není podporován"},
{"Host %s is <font color=red>already in router's addressbook</font>. <b>Be careful: source of this URL may be harmful!</b> Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "Hostitel %s je <font color=red>již v adresáři routeru</font>. <b>Buďte opatrní: zdroj této URL může být škodlivý!</b> Klikněte zde pro aktualizaci záznamu: <a href=\"%s%s%s&update=true\">Pokračovat</a>."},
{"Addresshelper forced update rejected", "Addresshelperem vynucená aktualizace zamítnuta"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Pro přidání hostitele <b>%s</b> do adresáře routeru, klikněte zde: <a href=\"%s%s%s\">Pokračovat</a>."},
{"Addresshelper request", "Požadavek Addresshelperu"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "Hostitel %s přidán do adresáře routeru od pomocníka. Klikněte zde pro pokračování: <a href=\"%s\">Pokračovat</a>."},
{"Addresshelper adding", "Addresshelper přidávání"},
{"Host %s is <font color=red>already in router's addressbook</font>. Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "Hostitel %s je <font color=red>již v adresáři routeru</font>. Klikněte zde pro aktualizaci záznamu: <a href=\"%s%s%s&update=true\">Pokračovat</a>."},
{"Addresshelper update", "Addresshelper aktualizace"},
{"Invalid request URI", "Neplatný URI požadavek"},
{"Can't detect destination host from request", "Nelze zjistit cílového hostitele z požadavku"},
{"Outproxy failure", "Outproxy selhání"},

@ -1,5 +1,5 @@
/*
* Copyright (c) 2022-2024, The PurpleI2P Project
* Copyright (c) 2022-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -58,7 +58,7 @@ namespace french // language namespace
{"Unknown", "Inconnu"},
{"Proxy", "Proxy"},
{"Mesh", "Maillé"},
{"Clock skew", "Décalage de l'horloge"},
{"Clock skew", "Horloge décalée"},
{"Offline", "Hors ligne"},
{"Symmetric NAT", "NAT symétrique"},
{"Full cone NAT", "NAT à cône complet"},
@ -68,8 +68,7 @@ namespace french // language namespace
{"Network status v6", "État du réseau v6"},
{"Stopping in", "Arrêt dans"},
{"Family", "Famille"},
{"Tunnel creation success rate", "Taux de création de tunnel réussie"},
{"Total tunnel creation success rate", "Taux total de création de tunnel réussie"},
{"Tunnel creation success rate", "Taux de succès de création de tunnels"},
{"Received", "Reçu"},
{"%.2f KiB/s", "%.2f Kio/s"},
{"Sent", "Envoyé"},
@ -92,11 +91,10 @@ namespace french // language namespace
{"Address registration line", "Ligne d'inscription de l'adresse"},
{"Domain", "Domaine"},
{"Generate", "Générer"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Note :</b> La chaîne résultante peut seulement être utilisée pour enregistrer les domaines 2LD (exemple.i2p). Pour enregistrer des sous-domaines, veuillez utiliser i2pd-tools."},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Note:</b> La chaîne résultante peut seulement être utilisée pour enregistrer les domaines 2LD (exemple.i2p). Pour enregistrer des sous-domaines, veuillez utiliser i2pd-tools."},
{"Address", "Adresse"},
{"Type", "Type"},
{"EncType", "EncType"},
{"Expire LeaseSet", "Expirer le jeu de baux"},
{"Inbound tunnels", "Tunnels entrants"},
{"%dms", "%dms"},
{"Outbound tunnels", "Tunnels sortants"},
@ -111,7 +109,6 @@ namespace french // language namespace
{"Local Destination", "Destination locale"},
{"Streams", "Flux"},
{"Close stream", "Fermer le flux"},
{"Such destination is not found", "Cette destination est introuvable"},
{"I2CP session not found", "Session I2CP introuvable"},
{"I2CP is not enabled", "I2CP est désactivé"},
{"Invalid", "Invalide"},
@ -131,7 +128,7 @@ namespace french // language namespace
{"Start graceful shutdown", "Démarrer l'arrêt gracieux"},
{"Force shutdown", "Forcer l'arrêt"},
{"Reload external CSS styles", "Rafraîchir les styles CSS externes"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Note :</b> Toute action effectuée ici n'est pas permanente et ne modifie pas vos fichiers de configuration."},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Note:</b> Toute action effectuée ici n'est pas permanente et ne modifie pas vos fichiers de configuration."},
{"Logging level", "Niveau de journalisation"},
{"Transit tunnels limit", "Limite sur les tunnels transitoires"},
{"Change", "Changer"},
@ -153,8 +150,6 @@ namespace french // language namespace
{"StreamID can't be null", "StreamID ne peut pas être vide"},
{"Return to destination page", "Retourner à la page de destination"},
{"You will be redirected in %d seconds", "Vous serez redirigé dans %d secondes"},
{"LeaseSet expiration time updated", "Temps d'expiration du jeu de baux mis à jour"},
{"LeaseSet is not found or already expired", "Le jeu de baux est introuvable ou a déjà expiré"},
{"Transit tunnels count must not exceed %d", "Le nombre de tunnels de transit ne doit pas excéder %d"},
{"Back to commands list", "Retour à la liste des commandes"},
{"Register at reg.i2p", "Inscription à reg.i2p"},
@ -163,23 +158,24 @@ namespace french // language namespace
{"Submit", "Soumettre"},
{"Domain can't end with .b32.i2p", "Le domaine ne peut pas terminer par .b32.i2p"},
{"Domain must end with .i2p", "Le domaine doit terminer par .i2p"},
{"Such destination is not found", "Cette destination est introuvable"},
{"Unknown command", "Commande inconnue"},
{"Command accepted", "Commande acceptée"},
{"Proxy error", "Erreur de proxy"},
{"Proxy info", "Information sur le proxy"},
{"Proxy error: Host not found", "Erreur de proxy : Hôte introuvable"},
{"Proxy error: Host not found", "Erreur de proxy: Hôte introuvable"},
{"Remote host not found in router's addressbook", "Hôte distant introuvable dans le carnet d'adresse du routeur"},
{"You may try to find this host on jump services below", "Vous pouvez essayer de trouver cet hôte sur des services de redirection ci-dessous"},
{"Invalid request", "Requête invalide"},
{"Proxy unable to parse your request", "Proxy incapable de comprendre votre requête"},
{"Addresshelper is not supported", "Assistant d'adresse non supporté"},
{"Host %s is <font color=red>already in router's addressbook</font>. <b>Be careful: source of this URL may be harmful!</b> Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "L'hôte %s est <font color=red>déjà dans le carnet d'adresses du routeur</font>. <b>Attention : la source de cette URL peut être nuisible !</b> Cliquez ici pour mettre à jour l'enregistrement : <a href=\"%s%s%s&update=true\">Continuer</a>."},
{"Host %s is <font color=red>already in router's addressbook</font>. <b>Be careful: source of this URL may be harmful!</b> Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "L'hôte %s est <font color=red>déjà dans le carnet d'adresses du routeur</font>. <b>Attention : la source de cette URL peut être nuisible !</b> Cliquez ici pour mettre à jour l'enregistrement : <a href=\"%s%s%s&update=true\">Continuer</a>."},
{"Addresshelper forced update rejected", "Mise à jour forcée des assistants d'adresses rejetée"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Pour ajouter l'hôte <b>%s</b> au carnet d'adresses du routeur, cliquez ici : <a href=\"%s%s%s\">Continuer</a>."},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Pour ajouter l'hôte <b>%s</b> au carnet d'adresses du routeur, cliquez ici : <a href=\"%s%s%s\">Continuer</a>."},
{"Addresshelper request", "Demande à l'assistant d'adresse"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "L'hôte %s a été ajouté au carnet d'adresses du routeur depuis l'assistant. Cliquez ici pour continuer : <a href=\"%s\">Continuer</a>."},
{"Addresshelper adding", "Ajout de l'assistant d'adresse"},
{"Host %s is <font color=red>already in router's addressbook</font>. Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "L'hôte %s est <font color=red>déjà dans le carnet d'adresses du routeur</font>. Cliquez ici pour mettre à jour le dossier : <a href=\"%s%s%s&update=true\">Continuer</a>."},
{"Host %s is <font color=red>already in router's addressbook</font>. Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "L'hôte %s est <font color=red>déjà dans le carnet d'adresses du routeur</font>. Cliquez ici pour mettre à jour le dossier : <a href=\"%s%s%s&update=true\">Continuer</a>."},
{"Addresshelper update", "Mise à jour de l'assistant d'adresse"},
{"Invalid request URI", "URI de la requête invalide"},
{"Can't detect destination host from request", "Impossible de détecter l'hôte de destination à partir de la requête"},

@ -61,7 +61,6 @@ namespace german // language namespace
{"Clock skew", "Zeitabweichung"},
{"Offline", "Offline"},
{"Symmetric NAT", "Symmetrisches NAT"},
{"No Descriptors", "Keine Beschreibungen"},
{"Uptime", "Laufzeit"},
{"Network status", "Netzwerkstatus"},
{"Network status v6", "Netzwerkstatus v6"},
@ -117,10 +116,8 @@ namespace german // language namespace
{"Gateway", "Gateway"},
{"TunnelID", "TunnelID"},
{"EndDate", "Enddatum"},
{"floodfill mode is disabled", "Floodfill Modus ist deaktiviert"},
{"Queue size", "Größe der Warteschlange"},
{"Run peer test", "Peer-Test durchführen"},
{"Reload tunnels configuration", "Tunnel Konfiguration neu laden"},
{"Decline transit tunnels", "Transittunnel ablehnen"},
{"Accept transit tunnels", "Transittunnel akzeptieren"},
{"Cancel graceful shutdown", "Beende das kontrollierte Herunterfahren"},
@ -148,8 +145,6 @@ namespace german // language namespace
{"Destination not found", "Ziel nicht gefunden"},
{"StreamID can't be null", "StreamID kann nicht null sein"},
{"Return to destination page", "Zurück zur Ziel-Seite"},
{"You will be redirected in %d seconds", "Du wirst umgeleitet in %d Sekunden"},
{"Transit tunnels count must not exceed %d", "Die Anzahl der Transittunnel darf nicht über %d gehen"},
{"Back to commands list", "Zurück zur Befehlsliste"},
{"Register at reg.i2p", "Auf reg.i2p registrieren"},
{"Description", "Beschreibung"},
@ -167,15 +162,6 @@ namespace german // language namespace
{"You may try to find this host on jump services below", "Vielleicht kannst du diesen Host auf einem der nachfolgenden Jump-Services finden"},
{"Invalid request", "Ungültige Anfrage"},
{"Proxy unable to parse your request", "Proxy konnte die Anfrage nicht verarbeiten"},
{"Addresshelper is not supported", "Adresshelfer wird nicht unterstützt"},
{"Host %s is <font color=red>already in router's addressbook</font>. <b>Be careful: source of this URL may be harmful!</b> Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "Host %s ist <font color=red>bereits im Adressbuch des Routers</font>. <b>Vorsicht: Die Quelle dieser URL kann schädlich sein!</b> Klicken Sie hier, um den Datensatz zu aktualisieren: <a href=\"%s%s%s&update=true\">Weiter</a>."},
{"Addresshelper forced update rejected", "Adresshelfer gezwungene Aktualisierung abgelehnt"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Um den Host <b>%s</b> im Adressbuch des Routers hinzuzufügen, klicken Sie hier: <a href=\"%s%s%s\">Weiter</a>."},
{"Addresshelper request", "Adresshelfer gefunden"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "Host %s wurde vom Helfer zum Adressbuch des Routers hinzugefügt. Klicken Sie hier, um fortzufahren: <a href=\"%s\">Weiter</a>."},
{"Addresshelper adding", "Adresshelfer hinzufügen"},
{"Host %s is <font color=red>already in router's addressbook</font>. Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "Host %s ist <font color=red>bereits im Adressbuch des Routers</font>. Klicken Sie hier, um den Eintrag zu aktualisieren: <a href=\"%s%s%s&update=true\">Weiter</a>."},
{"Addresshelper update", "Adresshelfer aktualisieren"},
{"Invalid request URI", "Ungültige Anfrage-URI"},
{"Can't detect destination host from request", "Kann den Ziel-Host von der Anfrage nicht erkennen"},
{"Outproxy failure", "Outproxy-Fehler"},

@ -95,8 +95,9 @@ std::string tr (TValue&& arg, TArgs&&... args)
std::string tr_str = i2p::i18n::translate(std::forward<TValue>(arg));
size_t size = std::snprintf(NULL, 0, tr_str.c_str(), std::forward<TArgs>(args)...);
size = size + 1;
std::string str(size, 0);
std::snprintf(&str.front(), size + 1, tr_str.c_str(), std::forward<TArgs>(args)...);
std::snprintf(&str.front(), size, tr_str.c_str(), std::forward<TArgs>(args)...);
return str;
}
@ -126,8 +127,9 @@ std::string ntr (TValue&& arg, TValue2&& arg2, int& n, TArgs&&... args)
std::string tr_str = i2p::i18n::translate(std::forward<TValue>(arg), std::forward<TValue2>(arg2), std::forward<int>(n));
size_t size = std::snprintf(NULL, 0, tr_str.c_str(), std::forward<TArgs>(args)...);
size = size + 1;
std::string str(size, 0);
std::snprintf(&str.front(), size + 1, tr_str.c_str(), std::forward<TArgs>(args)...);
std::snprintf(&str.front(), size, tr_str.c_str(), std::forward<TArgs>(args)...);
return str;
}

@ -61,15 +61,12 @@ namespace italian // language namespace
{"Clock skew", "Orologio disallineato"},
{"Offline", "Disconnesso"},
{"Symmetric NAT", "NAT simmetrico"},
{"Full cone NAT", "Cono completo NAT"},
{"No Descriptors", "Nessun descrittore"},
{"Uptime", "In funzione da"},
{"Network status", "Stato della rete"},
{"Network status v6", "Stato della rete v6"},
{"Stopping in", "Arresto in"},
{"Family", "Famiglia"},
{"Tunnel creation success rate", "Percentuale di tunnel creati con successo"},
{"Total tunnel creation success rate", "Percentuale di successo totale nella creazione del tunnel"},
{"Received", "Ricevuti"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "Inviati"},
@ -96,7 +93,6 @@ namespace italian // language namespace
{"Address", "Indirizzo"},
{"Type", "Tipologia"},
{"EncType", "Tipo di crittografia"},
{"Expire LeaseSet", "Scadenza LeaseSet"},
{"Inbound tunnels", "Tunnel in entrata"},
{"%dms", "%dms"},
{"Outbound tunnels", "Tunnel in uscita"},
@ -111,7 +107,6 @@ namespace italian // language namespace
{"Local Destination", "Destinazione locale"},
{"Streams", "Flussi"},
{"Close stream", "Interrompi il flusso"},
{"Such destination is not found", "Questa destinazione non è stata trovata"},
{"I2CP session not found", "Sessione I2CP non trovata"},
{"I2CP is not enabled", "I2CP non è abilitato"},
{"Invalid", "Invalido"},
@ -121,7 +116,6 @@ namespace italian // language namespace
{"Gateway", "Gateway"},
{"TunnelID", "TunnelID"},
{"EndDate", "Data di fine"},
{"floodfill mode is disabled", "la modalità floodfill è disabilitata"},
{"Queue size", "Dimensione della coda"},
{"Run peer test", "Esegui il test dei peer"},
{"Reload tunnels configuration", "Ricarica la configurazione dei tunnel"},
@ -153,8 +147,6 @@ namespace italian // language namespace
{"StreamID can't be null", "Lo StreamID non può essere null"},
{"Return to destination page", "Ritorna alla pagina di destinazione"},
{"You will be redirected in %d seconds", "Sarai reindirizzato tra %d secondi"},
{"LeaseSet expiration time updated", "Tempo di scadenza LeaseSet aggiornato"},
{"LeaseSet is not found or already expired", "LeaseSet non trovato o già scaduto"},
{"Transit tunnels count must not exceed %d", "Il conteggio dei tunnel di transito non deve superare %d"},
{"Back to commands list", "Ritorna alla lista dei comandi"},
{"Register at reg.i2p", "Registra a reg.i2p"},
@ -163,6 +155,7 @@ namespace italian // language namespace
{"Submit", "Invia"},
{"Domain can't end with .b32.i2p", "I domini non possono terminare con .b32.i2p"},
{"Domain must end with .i2p", "I domini devono terminare con .i2p"},
{"Such destination is not found", "Questa destinazione non è stata trovata"},
{"Unknown command", "Comando sconosciuto"},
{"Command accepted", "Comando accettato"},
{"Proxy error", "Errore del proxy"},
@ -172,15 +165,8 @@ namespace italian // language namespace
{"You may try to find this host on jump services below", "Si può provare a trovare questo host sui servizi di salto qui sotto"},
{"Invalid request", "Richiesta non valida"},
{"Proxy unable to parse your request", "Il proxy non è in grado di elaborare la tua richiesta"},
{"Addresshelper is not supported", "Addresshelper non è supportato"},
{"Host %s is <font color=red>already in router's addressbook</font>. <b>Be careful: source of this URL may be harmful!</b> Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "L'host %s è <font color=red>già nella rubrica del router</font>. <b>Attenzione: la fonte di questo URL potrebbe essere dannosa!</b> Fai clic qui per aggiornare il record: <a href=\"%s%s%s&update=true\">Continua</a>."},
{"Addresshelper forced update rejected", "Aggiornamento forzato dell'helper degli indirizzi rifiutato"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Per aggiungere host <b>%s</b> nella rubrica del router, clicca qui: <a href=\"%s%s%s\">Continua</a>."},
{"Addresshelper request", "Richiesta di indirizzo helper"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "L'host %s viene aggiunto alla rubrica del router dall'helper. Fai clic qui per procedere: <a href=\"%s\">Continua</a>."},
{"Addresshelper adding", "Aggiunta di Addresshelper"},
{"Host %s is <font color=red>already in router's addressbook</font>. Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "L'host %s è <font color=red>già nella rubrica del router</font>. Clicca qui per aggiornare il record: <a href=\"%s%s%s&update=true\">Continua</a>."},
{"Addresshelper update", "Aggiornamento dell'helper degli indirizzi"},
{"Invalid request URI", "URI della richiesta non valido"},
{"Can't detect destination host from request", "Impossibile determinare l'host di destinazione dalla richiesta"},
{"Outproxy failure", "Fallimento del proxy di uscita"},

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023-2024, The PurpleI2P Project
* Copyright (c) 2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -31,186 +31,22 @@ namespace polish // language namespace
static std::map<std::string, std::string> strings
{
{"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"},
{"%.2f GiB", "%.2f GiB"},
{"building", "Kompilowanie"},
{"failed", "nieudane"},
{"expiring", "wygasający"},
{"established", "ustanowiony"},
{"unknown", "nieznany"},
{"exploratory", "eksploracyjny"},
{"Purple I2P Webconsole", "Konsola webowa Purple I2P"},
{"<b>i2pd</b> webconsole", "<b>i2pd</b> konsola webowa"},
{"Main page", "Strona główna"},
{"Router commands", "Komendy routera"},
{"Local Destinations", "Lokalne miejsca docelowe"},
{"LeaseSets", "ZestawyNajmu"},
{"Tunnels", "Tunele"},
{"Transit Tunnels", "Tunele Tranzytu"},
{"Transports", "Transportery"},
{"I2P tunnels", "Tunele I2P"},
{"SAM sessions", "Sesje SAM"},
{"ERROR", "BŁĄD"},
{"OK", "Ok"},
{"Testing", "Testowanie"},
{"Firewalled", "Za zaporą sieciową"},
{"Unknown", "Nieznany"},
{"Proxy", "Proxy"},
{"Mesh", "Sieć"},
{"Clock skew", "Przesunięcie czasu"},
{"Offline", "Offline"},
{"Symmetric NAT", "Symetryczny NAT"},
{"Full cone NAT", "Pełny stożek NAT"},
{"No Descriptors", "Brak deskryptorów"},
{"Uptime", "Czas pracy"},
{"Network status", "Stan sieci"},
{"Network status v6", "Stan sieci v6"},
{"Stopping in", "Zatrzymywanie za"},
{"Family", "Rodzina"},
{"Tunnel creation success rate", "Wskaźnik sukcesu tworzenia tunelu"},
{"Total tunnel creation success rate", "Całkowity wskaźnik sukcesu tworzenia tunelu"},
{"Received", "Odebrano"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "Wysłane"},
{"Transit", "Tranzyt"},
{"Data path", "Ścieżka do danych"},
{"Hidden content. Press on text to see.", "Ukryta zawartość. Naciśnij tekst, aby zobaczyć."},
{"Router Ident", "Identyfikator routera"},
{"Router Family", "Rodzina routera"},
{"Router Caps", "Możliwości routera"},
{"Version", "Wersja"},
{"Our external address", "Nasz zewnętrzny adres"},
{"supported", "wspierane"},
{"Routers", "Routery"},
{"Floodfills", "Floodfille"},
{"Client Tunnels", "Tunele Klienta"},
{"Services", "Usługi"},
{"Enabled", "Aktywny"},
{"Disabled", "Wyłączony"},
{"Encrypted B33 address", "Zaszyfrowany adres B33"},
{"Address registration line", "Linia rejestracji adresu"},
{"Domain", "Domena"},
{"Generate", "Generuj"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Uwaga:</b> wynik string może być używany tylko do rejestracji domen 2LD (przykład.i2p). Do rejestracji subdomen należy użyć narzędzi i2pd."},
{"Address", "Adres"},
{"Type", "Typ"},
{"EncType", "TypEnkrypcji"},
{"Expire LeaseSet", "Wygaśnij LeaseSet"},
{"Inbound tunnels", "Tunele przychodzące"},
{"%dms", "%dms"},
{"Outbound tunnels", "Tunele wychodzące"},
{"Tags", "Tagi"},
{"Incoming", "Przychodzące"},
{"Outgoing", "Wychodzące"},
{"Destination", "Miejsce docelowe"},
{"Amount", "Ilość"},
{"Incoming Tags", "Przychodzące tagi"},
{"Tags sessions", "Sesje tagów"},
{"Status", "Status"},
{"Local Destination", "Lokalne miejsce docelowe"},
{"Streams", "Strumienie"},
{"Close stream", "Zamknij strumień"},
{"Such destination is not found", "Nie znaleziono takiego miejsca docelowego"},
{"I2CP session not found", "Sesja I2CP nie została znaleziona"},
{"I2CP is not enabled", "I2CP nie jest włączone"},
{"Invalid", "Niepoprawny"},
{"Store type", "Rodzaj przechowywania"},
{"Expires", "Wygasa za"},
{"Non Expired Leases", "Leasingi niewygasłe"},
{"Gateway", "Brama"},
{"TunnelID", "IDTunelu"},
{"EndDate", "DataZakończenia"},
{"floodfill mode is disabled", "tryb floodfill jest wyłączony"},
{"Queue size", "Wielkość kolejki"},
{"Run peer test", "Wykonaj test peer"},
{"Reload tunnels configuration", "Załaduj ponownie konfigurację tuneli"},
{"Decline transit tunnels", "Odrzuć tunele tranzytowe"},
{"Accept transit tunnels", "Akceptuj tunele tranzytowe"},
{"Cancel graceful shutdown", "Anuluj łagodne wyłączenie"},
{"Start graceful shutdown", "Rozpocznij łagodne wyłączenie"},
{"Force shutdown", "Wymuś wyłączenie"},
{"Reload external CSS styles", "Odśwież zewnętrzne style CSS"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Uwaga:</b> każda akcja wykonana tutaj nie jest trwała i nie zmienia Twoich plików konfiguracyjnych."},
{"Logging level", "Poziom logowania"},
{"Transit tunnels limit", "Limit tuneli tranzytowych"},
{"Change", "Zmień"},
{"Change language", "Zmień język"},
{"no transit tunnels currently built", "brak obecnie zbudowanych tuneli tranzytowych"},
{"SAM disabled", "SAM wyłączony"},
{"no sessions currently running", "brak aktualnie uruchomionych sesji"},
{"SAM session not found", "Sesja SAM nie została znaleziona"},
{"SAM Session", "Sesja SAM"},
{"Server Tunnels", "Tunele Serwera"},
{"Client Forwards", "Przekierowania Klienta"},
{"Server Forwards", "Przekierowania Serwera"},
{"Unknown page", "Nieznana strona"},
{"Invalid token", "Nieprawidłowy token"},
{"SUCCESS", "SUKCES"},
{"Stream closed", "Strumień zamknięty"},
{"Stream not found or already was closed", "Strumień nie został znaleziony lub został już zamknięty"},
{"Destination not found", "Nie znaleziono punktu docelowego"},
{"StreamID can't be null", "StreamID nie może być null"},
{"Return to destination page", "Wróć do strony miejsca docelowego"},
{"You will be redirected in %d seconds", "Zostaniesz prekierowany za %d sekund"},
{"LeaseSet expiration time updated", "Zaktualizowano czas wygaśnięcia LeaseSet"},
{"LeaseSet is not found or already expired", "LeaseSet nie został znaleziony lub już wygasł"},
{"Transit tunnels count must not exceed %d", "Liczba tuneli tranzytowych nie może przekraczać %d"},
{"Back to commands list", "Powrót do listy poleceń"},
{"Register at reg.i2p", "Zarejestruj się na reg.i2p"},
{"Description", "Opis"},
{"A bit information about service on domain", "Trochę informacji o usłudze w domenie"},
{"Submit", "Zatwierdź"},
{"Domain can't end with .b32.i2p", "Domena nie może kończyć się na .b32.i2p"},
{"Domain must end with .i2p", "Domena musi kończyć się na .i2p"},
{"Unknown command", "Nieznana komenda"},
{"Command accepted", "Polecenie zaakceptowane"},
{"Proxy error", "Błąd serwera proxy"},
{"Proxy info", "Informacje o proxy"},
{"Proxy error: Host not found", "Błąd proxy: Nie znaleziono hosta"},
{"Remote host not found in router's addressbook", "Nie znaleziono zdalnego hosta w książce adresowej routera"},
{"You may try to find this host on jump services below", "Możesz znaleźć tego hosta na poniższych usługach skoku"},
{"Invalid request", "Nieprawidłowe żądanie"},
{"Proxy unable to parse your request", "Serwer proxy nie może przetworzyć Twojego żądania"},
{"Addresshelper is not supported", "Adresshelper nie jest obsługiwany"},
{"Host %s is <font color=red>already in router's addressbook</font>. <b>Be careful: source of this URL may be harmful!</b> Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "Host %s <font color=red>jest już w książce adresowej routera</font>. <b>Uważaj: źródło tego adresu URL może być szkodliwe!</b> Kliknij tutaj, aby zaktualizować rekord: <a href=\"%s%s%s&update=true\">Kontynuuj</a>."},
{"Addresshelper forced update rejected", "Wymuszona aktualizacja Addreshelper odrzucona"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Aby dodać host <b>%s</b> w książce adresowej routera, kliknij tutaj: <a href=\"%s%s%s\">Kontynuuj</a>."},
{"Addresshelper request", "Prośba Addresshelper"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "Host %s dodany do książki adresowej routera od pomocnika. Kliknij tutaj, aby kontynuować: <a href=\"%s\">Kontynuuj</a>."},
{"Addresshelper adding", "Dodawanie Addresshelper"},
{"Host %s is <font color=red>already in router's addressbook</font>. Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "Host %s jest <font color=red>już w książce adresowej routera</font>. Kliknij tutaj, aby zaktualizować rekord: <a href=\"%s%s%s&update=true\">Kontynuuj</a>."},
{"Addresshelper update", "Aktualizacja Adresshelper"},
{"Invalid request URI", "Nieprawidłowe URI żądania"},
{"Can't detect destination host from request", "Nie można wykryć hosta docelowego z żądania"},
{"Outproxy failure", "Błąd proxy wyjściowego"},
{"Bad outproxy settings", "Błędne ustawienia proxy wyjściowych"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Host %s nie jest wewnątrz sieci I2P, a proxy wyjściowe nie jest włączone"},
{"Unknown outproxy URL", "Nieznany adres URL proxy wyjściowego"},
{"Cannot resolve upstream proxy", "Nie można rozwiązać serwera proxy upstream"},
{"Hostname is too long", "Nazwa hosta jest zbyt długa"},
{"Cannot connect to upstream SOCKS proxy", "Nie można połączyć się z proxy SOCKS upstream"},
{"Cannot negotiate with SOCKS proxy", "Nie można negocjować z proxy SOCKS"},
{"CONNECT error", "Błąd POŁĄCZENIE"},
{"Failed to connect", "Nie udało się połączyć"},
{"SOCKS proxy error", "Błąd proxy SOCKS"},
{"Failed to send request to upstream", "Nie udało się wysłać żądania do upstream"},
{"No reply from SOCKS proxy", "Brak odpowiedzi od serwera proxy SOCKS"},
{"Cannot connect", "Nie można się połączyć"},
{"HTTP out proxy not implemented", "Serwer wyjściowy proxy HTTP nie został zaimplementowany"},
{"Cannot connect to upstream HTTP proxy", "Nie można połączyć się z proxy HTTP upstream"},
{"Host is down", "Host jest niedostępny"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Nie można utworzyć połączenia z żądanym hostem, może być wyłączony. Spróbuj ponownie później."},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"%d days", {"%d dzień", "%d dni", "%d dni", "%d dni"}},
{"%d hours", {"%d godzina", "%d godziny", "%d godzin", "%d godzin"}},
{"%d minutes", {"%d minuta", "%d minuty", "%d minut", "%d minut"}},
{"%d seconds", {"%d sekunda", "%d sekundy", "%d sekund", "%d sekund"}},
{"", {"", "", "", ""}},
{"", {"", "", ""}},
};
std::shared_ptr<const i2p::i18n::Locale> GetLocale()

@ -1,5 +1,5 @@
/*
* Copyright (c) 2023-2024, The PurpleI2P Project
* Copyright (c) 2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -58,7 +58,7 @@ namespace portuguese // language namespace
{"Unknown", "Desconhecido"},
{"Proxy", "Proxy"},
{"Mesh", "Malha"},
{"Clock skew", "Desvio de Relógio"},
{"Clock skew", "Defasagem do Relógio"},
{"Offline", "Desligado"},
{"Symmetric NAT", "NAT Simétrico"},
{"Full cone NAT", "Full cone NAT"},
@ -69,12 +69,11 @@ namespace portuguese // language namespace
{"Stopping in", "Parando em"},
{"Family", "Família"},
{"Tunnel creation success rate", "Taxa de sucesso na criação de túneis"},
{"Total tunnel creation success rate", "Taxa total de sucesso na criação de túneis"},
{"Received", "Recebido"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "Enviado"},
{"Transit", "Trânsito"},
{"Data path", "Diretório de dados"},
{"Data path", "Caminho dos dados"},
{"Hidden content. Press on text to see.", "Conteúdo oculto. Clique no texto para revelar."},
{"Router Ident", "Identidade do Roteador"},
{"Router Family", "Família do Roteador"},
@ -96,7 +95,6 @@ namespace portuguese // language namespace
{"Address", "Endereço"},
{"Type", "Tipo"},
{"EncType", "Tipo de Criptografia"},
{"Expire LeaseSet", "Expirar LeaseSet"},
{"Inbound tunnels", "Túneis de Entrada"},
{"%dms", "%dms"},
{"Outbound tunnels", "Túneis de Saída"},
@ -106,12 +104,11 @@ namespace portuguese // language namespace
{"Destination", "Destinos"},
{"Amount", "Quantidade"},
{"Incoming Tags", "Etiquetas de Entrada"},
{"Tags sessions", "Sessões de Etiquetas"},
{"Tags sessions", "Sessões de etiquetas"},
{"Status", "Estado"},
{"Local Destination", "Destino Local"},
{"Local Destination", "Destinos Locais"},
{"Streams", "Fluxos"},
{"Close stream", "Fechar fluxo"},
{"Such destination is not found", "Tal destino não foi encontrado"},
{"I2CP session not found", "Sessão do I2CP não encontrada"},
{"I2CP is not enabled", "I2CP não está ativado"},
{"Invalid", "Inválido"},
@ -125,15 +122,15 @@ namespace portuguese // language namespace
{"Queue size", "Tamanho da fila"},
{"Run peer test", "Executar teste de peers"},
{"Reload tunnels configuration", "Recarregar a configuração dos túneis"},
{"Decline transit tunnels", "Negar túneis de trânsito"},
{"Accept transit tunnels", "Aceitar túneis de trânsito"},
{"Decline transit tunnels", "Negar túnel de trânsito"},
{"Accept transit tunnels", "Aceitar túnel de trânsito"},
{"Cancel graceful shutdown", "Cancelar desligamento gracioso"},
{"Start graceful shutdown", "Iniciar desligamento gracioso"},
{"Force shutdown", "Forçar desligamento"},
{"Reload external CSS styles", "Recarregar estilos CSS externos"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b> Nota: </b> Qualquer ação feita aqui não será permanente e não altera os seus arquivos de configuração."},
{"Logging level", "Nível de registro"},
{"Transit tunnels limit", "Limite de túneis de trânsito"},
{"Transit tunnels limit", "Limite nos túneis de trânsito"},
{"Change", "Mudar"},
{"Change language", "Trocar idioma"},
{"no transit tunnels currently built", "Nenhum túnel de trânsito construido no momento"},
@ -148,43 +145,42 @@ namespace portuguese // language namespace
{"Invalid token", "Token Inválido"},
{"SUCCESS", "SUCESSO"},
{"Stream closed", "Fluxo fechado"},
{"Stream not found or already was closed", "Fluxo não encontrado ou já fechado"},
{"Stream not found or already was closed", "Fluxo não encontrado ou já encerrado"},
{"Destination not found", "Destino não encontrado"},
{"StreamID can't be null", "StreamID não pode ser nulo"},
{"Return to destination page", "Retornar para à página de destino"},
{"You will be redirected in %d seconds", "Você será redirecionado em %d segundos"},
{"LeaseSet expiration time updated", "Tempo de validade do LeaseSet atualizado"},
{"LeaseSet is not found or already expired", "LeaseSet não foi encontrado ou já expirou"},
{"Transit tunnels count must not exceed %d", "A contagem de túneis de trânsito não deve exceder %d"},
{"Back to commands list", "Voltar para a lista de comandos"},
{"Register at reg.i2p", "Registrar em reg.i2p"},
{"Register at reg.i2p", "Registrar na reg.i2p"},
{"Description", "Descrição"},
{"A bit information about service on domain", "Algumas informações sobre o serviço no domínio"},
{"Submit", "Enviar"},
{"Domain can't end with .b32.i2p", "O domínio não pode terminar com .b32.i2p"},
{"Domain must end with .i2p", "O domínio não pode terminar com .i2p"},
{"Such destination is not found", "Tal destino não foi encontrado"},
{"Unknown command", "Comando desconhecido"},
{"Command accepted", "Comando aceito"},
{"Proxy error", "Erro no proxy"},
{"Proxy info", "Informações do proxy"},
{"Proxy error: Host not found", "Erro no proxy: Host não encontrado"},
{"Remote host not found in router's addressbook", "O host remoto não foi encontrado no livro de endereços do roteador"},
{"You may try to find this host on jump services below", "Você pode tentar encontrar este host nos serviços de jump abaixo"},
{"You may try to find this host on jump services below", "Você pode tentar encontrar este host nos jump services abaixo"},
{"Invalid request", "Requisição inválida"},
{"Proxy unable to parse your request", "O proxy foi incapaz de processar a sua requisição"},
{"Addresshelper is not supported", "O Auxiliar de Endereços não é suportado"},
{"Host %s is <font color=red>already in router's addressbook</font>. <b>Be careful: source of this URL may be harmful!</b> Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "O host %s já <font color=red>está no catálogo de endereços do roteador</font>. <b>Cuidado: a fonte desta URL pode ser perigosa!</b> Clique aqui para atualizar o registro: <a href=\"%s%s%s&update=true\">Continuar</a>."},
{"Addresshelper forced update rejected", "A atualização forçada do Auxiliar de Endereços foi rejeitada"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Para adicionar o host <b> %s </b> ao catálogo de endereços do roteador, clique aqui: <a href='%s%s%s'>Continuar </a>."},
{"Addresshelper request", "Requisição ao Auxiliar de Endereços"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "O host %s foi adicionado ao catálogo de endereços do roteador por um auxiliar. Clique aqui para prosseguir: <a href='%s'> Continuar </a>."},
{"Addresshelper request", "Requisição do Auxiliar de Endereços"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "O host %s foi adicionado ao catálogo de endereços do roteador por um auxiliar. Clique aqui para proceder: <a href='%s'> Continuar </a>."},
{"Addresshelper adding", "Auxiliar de Endereço adicionando"},
{"Host %s is <font color=red>already in router's addressbook</font>. Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "O host %s já <font color=red>está no catálogo de endereços do roteador </font>. Clique aqui para atualizar o registro: <a href=\"%s%s%s&update=true\">Continuar</a>."},
{"Addresshelper update", "Atualização do Auxiliar de Endereços"},
{"Invalid request URI", "A URI de requisição é inválida"},
{"Can't detect destination host from request", "Incapaz de detectar o host de destino da requisição"},
{"Outproxy failure", "Falha no outproxy"},
{"Bad outproxy settings", "Má configurações do outproxy"},
{"Bad outproxy settings", "Configurações ruins de outproxy"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "O host %s não está dentro da rede I2P, mas o outproxy não está ativado"},
{"Unknown outproxy URL", "URL de outproxy desconhecida"},
{"Cannot resolve upstream proxy", "Não é possível resolver o proxy de entrada"},

@ -69,7 +69,6 @@ namespace russian // language namespace
{"Stopping in", "Остановка через"},
{"Family", "Семейство"},
{"Tunnel creation success rate", "Успешно построенных туннелей"},
{"Total tunnel creation success rate", "Общий процент успешно построенных туннелей"},
{"Received", "Получено"},
{"%.2f KiB/s", "%.2f КиБ/с"},
{"Sent", "Отправлено"},
@ -96,7 +95,6 @@ namespace russian // language namespace
{"Address", "Адрес"},
{"Type", "Тип"},
{"EncType", "ТипШифр"},
{"Expire LeaseSet", "Просрочить Лизсет"},
{"Inbound tunnels", "Входящие туннели"},
{"%dms", "%dмс"},
{"Outbound tunnels", "Исходящие туннели"},
@ -111,7 +109,6 @@ namespace russian // language namespace
{"Local Destination", "Локальное назначение"},
{"Streams", "Стримы"},
{"Close stream", "Закрыть стрим"},
{"Such destination is not found", "Такая точка назначения не найдена"},
{"I2CP session not found", "I2CP сессия не найдена"},
{"I2CP is not enabled", "I2CP не включен"},
{"Invalid", "Некорректный"},
@ -153,8 +150,6 @@ namespace russian // language namespace
{"StreamID can't be null", "StreamID не может быть пустым"},
{"Return to destination page", "Вернуться на страницу точки назначения"},
{"You will be redirected in %d seconds", "Вы будете переадресованы через %d секунд"},
{"LeaseSet expiration time updated", "Время действия LeaseSet обновлено"},
{"LeaseSet is not found or already expired", "Лизсет не найден или время действия уже истекло"},
{"Transit tunnels count must not exceed %d", "Число транзитных туннелей не должно превышать %d"},
{"Back to commands list", "Вернуться к списку команд"},
{"Register at reg.i2p", "Зарегистрировать на reg.i2p"},
@ -163,6 +158,7 @@ namespace russian // language namespace
{"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", "Ошибка прокси"},

@ -61,8 +61,6 @@ namespace swedish // language namespace
{"Clock skew", "Tidsförskjutning"},
{"Offline", "Nedkopplad"},
{"Symmetric NAT", "Symmetrisk NAT"},
{"Full cone NAT", "Full kon NAT"},
{"No Descriptors", "Inga Beskrivningar"},
{"Uptime", "Upptid"},
{"Network status", "Nätverkstillstånd"},
{"Network status v6", "Nätverkstillstånd v6"},
@ -109,7 +107,6 @@ namespace swedish // language namespace
{"Local Destination", "Lokal Plats"},
{"Streams", "Strömmar"},
{"Close stream", "Stäng strömmen"},
{"Such destination is not found", "En sådan plats hittas ej"},
{"I2CP session not found", "I2CP-period hittades inte"},
{"I2CP is not enabled", "I2CP är inte påslaget"},
{"Invalid", "Ogiltig"},
@ -119,10 +116,8 @@ namespace swedish // language namespace
{"Gateway", "Gateway"},
{"TunnelID", "TunnelID"},
{"EndDate", "EndDate"},
{"floodfill mode is disabled", "Floodfill läget är inaktiverat"},
{"Queue size", "Köstorlek"},
{"Run peer test", "Utför utsiktstest"},
{"Reload tunnels configuration", "Ladda om tunnelkonfiguration"},
{"Decline transit tunnels", "Avvisa förmedlande tunnlar"},
{"Accept transit tunnels", "Tillåt förmedlande tunnlar"},
{"Cancel graceful shutdown", "Avbryt välvillig avstängning"},
@ -159,6 +154,7 @@ namespace swedish // language namespace
{"Submit", "Skicka"},
{"Domain can't end with .b32.i2p", "Domänen får inte sluta med .b32.i2p"},
{"Domain must end with .i2p", "Domänen måste sluta med .i2p"},
{"Such destination is not found", "En sådan plats hittas ej"},
{"Unknown command", "Okänt kommando"},
{"Command accepted", "Kommando accepterades"},
{"Proxy error", "Proxyfel"},
@ -169,14 +165,6 @@ namespace swedish // language namespace
{"Invalid request", "Ogiltig förfrågan"},
{"Proxy unable to parse your request", "Proxyt kan inte behandla din förfrågan"},
{"Addresshelper is not supported", "Adresshjälparen stöds ej"},
{"Host %s is <font color=red>already in router's addressbook</font>. <b>Be careful: source of this URL may be harmful!</b> Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "Värd %s är <font color=red>redan i routerns adressbok</font>. <b>Var försiktig: källan till denna URL kan vara skadlig!</b> Klicka här för att uppdatera registreringen: <a href=\"%s%s%s&update=true\">Fortsätt</a>."},
{"Addresshelper forced update rejected", "Tvingad uppdatering av adresshjälparen nekad"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "För att lägga till värd <b>%s</b> i routerns adressbok, klicka här: <a href=\"%s%s%s\">Fortsätt</a>."},
{"Addresshelper request", "Adresshjälpare förfrågan"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "Värd %s tillagd i routerns adressbok från hjälparen. Klicka här för att fortsätta: <a href=\"%s\">Fortsätt</a>."},
{"Addresshelper adding", "Adresshjälpare tilläggning"},
{"Host %s is <font color=red>already in router's addressbook</font>. Click here to update record: <a href=\"%s%s%s&update=true\">Continue</a>.", "Värd %s är <font color=red>redan i routerns adressbok</font>. Klicka här för att uppdatera registreringen: <a href=\"%s%s%s&update=true\">Fortsätt</a>."},
{"Addresshelper update", "Adresshjälpare uppdatering"},
{"Invalid request URI", "Ogiltig förfrågnings-URI"},
{"Can't detect destination host from request", "Kan inte upptäcka platsvärden från förfrågan"},
{"Outproxy failure", "Utproxyfel"},

@ -69,7 +69,6 @@ namespace ukrainian // language namespace
{"Stopping in", "Зупинка через"},
{"Family", "Сімейство"},
{"Tunnel creation success rate", "Успішно побудованих тунелів"},
{"Total tunnel creation success rate", "Загальна кількість створених тунелів"},
{"Received", "Отримано"},
{"%.2f KiB/s", "%.2f КіБ/с"},
{"Sent", "Відправлено"},
@ -96,7 +95,6 @@ namespace ukrainian // language namespace
{"Address", "Адреса"},
{"Type", "Тип"},
{"EncType", "ТипШифр"},
{"Expire LeaseSet", "Завершити LeaseSet"},
{"Inbound tunnels", "Вхідні тунелі"},
{"%dms", "%dмс"},
{"Outbound tunnels", "Вихідні тунелі"},
@ -111,7 +109,6 @@ namespace ukrainian // language namespace
{"Local Destination", "Локальні Призначення"},
{"Streams", "Потоки"},
{"Close stream", "Закрити потік"},
{"Such destination is not found", "Така точка призначення не знайдена"},
{"I2CP session not found", "I2CP сесія не знайдена"},
{"I2CP is not enabled", "I2CP не увікнуто"},
{"Invalid", "Некоректний"},
@ -153,8 +150,6 @@ namespace ukrainian // language namespace
{"StreamID can't be null", "Ідентифікатор потоку не може бути порожнім"},
{"Return to destination page", "Повернутися на сторінку точки призначення"},
{"You will be redirected in %d seconds", "Ви будете переадресовані через %d секунд"},
{"LeaseSet expiration time updated", "Час закінчення LeaseSet оновлено"},
{"LeaseSet is not found or already expired", "LeaseSet не знайдено або вже закінчився"},
{"Transit tunnels count must not exceed %d", "Кількість транзитних тунелів не повинна перевищувати %d"},
{"Back to commands list", "Повернутися до списку команд"},
{"Register at reg.i2p", "Зареєструвати на reg.i2p"},
@ -163,6 +158,7 @@ namespace ukrainian // language namespace
{"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", "Помилка проксі"},

@ -69,7 +69,6 @@ namespace uzbek // language namespace
{"Stopping in", "Ichida to'xtatish"},
{"Family", "Oila"},
{"Tunnel creation success rate", "Tunnel yaratish muvaffaqiyat darajasi"},
{"Total tunnel creation success rate", "Tunnel yaratishning umumiy muvaffaqiyat darajasi"},
{"Received", "Qabul qilindi"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "Yuborilgan"},
@ -96,7 +95,6 @@ namespace uzbek // language namespace
{"Address", "Manzil"},
{"Type", "Turi"},
{"EncType", "ShifrlashTuri"},
{"Expire LeaseSet", "LeaseSet muddati tugaydi"},
{"Inbound tunnels", "Kirish tunnellari"},
{"%dms", "%dms"},
{"Outbound tunnels", "Chiquvchi tunnellar"},
@ -111,7 +109,6 @@ namespace uzbek // language namespace
{"Local Destination", "Mahalliy joylanish"},
{"Streams", "Strim"},
{"Close stream", "Strimni o'chirish"},
{"Such destination is not found", "Bunday yo'nalish topilmadi"},
{"I2CP session not found", "I2CP sessiyasi topilmadi"},
{"I2CP is not enabled", "I2CP yoqilmagan"},
{"Invalid", "Noto'g'ri"},
@ -153,8 +150,6 @@ namespace uzbek // language namespace
{"StreamID can't be null", "StreamID bo'sh bo'lishi mumkin emas"},
{"Return to destination page", "Manzilgoh sahifasiga qaytish"},
{"You will be redirected in %d seconds", "Siz %d soniyadan song boshqa yonalishga yonaltirilasiz"},
{"LeaseSet expiration time updated", "LeaseSet amal qilish muddati yangilandi"},
{"LeaseSet is not found or already expired", "LeaseSet topilmadi yoki muddati tugagan"},
{"Transit tunnels count must not exceed %d", "Tranzit tunnellar soni %d dan oshmasligi kerak"},
{"Back to commands list", "Buyruqlar ro'yxatiga qaytish"},
{"Register at reg.i2p", "Reg.i2p-da ro'yxatdan o'ting"},
@ -163,6 +158,7 @@ namespace uzbek // language namespace
{"Submit", "Yuborish"},
{"Domain can't end with .b32.i2p", "Domen .b32.i2p bilan tugashi mumkin emas"},
{"Domain must end with .i2p", "Domen .i2p bilan tugashi kerak"},
{"Such destination is not found", "Bunday yo'nalish topilmadi"},
{"Unknown command", "Noma'lum buyruq"},
{"Command accepted", "Buyruq qabul qilindi"},
{"Proxy error", "Proksi xatosi"},

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2023, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -28,11 +28,6 @@ namespace data
return T32;
}
bool IsBase32 (char ch)
{
return (ch >= 'a' && ch <= 'z') || (ch >= '2' && ch <= '7');
}
static void iT64Build(void);
/*
@ -60,11 +55,6 @@ namespace data
return T64;
}
bool IsBase64 (char ch)
{
return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '-' || ch == '~';
}
/*
* Reverse Substitution Table (built in run time)
*/
@ -197,9 +187,6 @@ namespace data
else
return 0;
if(*InBuffer == P64)
return 0;
ps = (unsigned char *)(InBuffer + InCount - 1);
while ( *ps-- == P64 )
outCount--;
@ -282,7 +269,7 @@ namespace data
size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen)
{
unsigned int tmp = 0, bits = 0;
int tmp = 0, bits = 0;
size_t ret = 0;
for (size_t i = 0; i < len; i++)
{
@ -311,7 +298,7 @@ namespace data
size_t ByteStreamToBase32 (const uint8_t * inBuf, size_t len, char * outBuf, size_t outLen)
{
size_t ret = 0, pos = 1;
unsigned int bits = 8, tmp = inBuf[0];
int bits = 8, tmp = inBuf[0];
while (ret < outLen && (bits > 0 || pos < len))
{
if (bits < 5)

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2023, The PurpleI2P Project
* Copyright (c) 2013-2020, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -19,11 +19,9 @@ namespace data {
size_t Base64ToByteStream (const char * InBuffer, size_t InCount, uint8_t * OutBuffer, size_t len );
const char * GetBase32SubstitutionTable ();
const char * GetBase64SubstitutionTable ();
bool IsBase64 (char ch);
size_t Base32ToByteStream (const char * inBuf, size_t len, uint8_t * outBuf, size_t outLen);
size_t ByteStreamToBase32 (const uint8_t * InBuf, size_t len, char * outBuf, size_t outLen);
bool IsBase32 (char ch);
/**
* Compute the size for a buffer to contain encoded base64 given that the size of the input is input_size bytes

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2023, The PurpleI2P Project
* Copyright (c) 2013-2020, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -7,62 +7,52 @@
*/
#include "CPU.h"
#if defined(__x86_64__) || defined(__i386__)
#include <cpuid.h>
#endif
#include "Log.h"
#ifndef bit_AES
#define bit_AES (1 << 25)
#define bit_AES (1 << 25)
#endif
#if defined(__GNUC__) && __GNUC__ < 6 && IS_X86
#include <cpuid.h>
#ifndef bit_AVX
#define bit_AVX (1 << 28)
#endif
#ifdef _MSC_VER
#include <intrin.h>
#endif
namespace i2p
{
namespace cpu
{
bool aesni = false;
bool avx = false;
inline bool cpu_support_aes()
void Detect(bool AesSwitch, bool AvxSwitch, bool force)
{
#if IS_X86
#if defined(__clang__)
# if (__clang_major__ >= 6)
__builtin_cpu_init();
# endif
return __builtin_cpu_supports("aes");
#elif (defined(__GNUC__) && __GNUC__ >= 6)
__builtin_cpu_init();
return __builtin_cpu_supports("aes");
#elif (defined(__GNUC__) && __GNUC__ < 6)
int cpu_info[4];
bool flag = false;
__cpuid(0, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]);
if (cpu_info[0] >= 0x00000001) {
__cpuid(0x00000001, cpu_info[0], cpu_info[1], cpu_info[2], cpu_info[3]);
flag = ((cpu_info[2] & bit_AES) != 0);
}
return flag;
#elif defined(_MSC_VER)
int cpu_info[4];
__cpuid(cpu_info, 1);
return ((cpu_info[2] & bit_AES) != 0);
#if defined(__x86_64__) || defined(__i386__)
int info[4];
__cpuid(0, info[0], info[1], info[2], info[3]);
if (info[0] >= 0x00000001) {
__cpuid(0x00000001, info[0], info[1], info[2], info[3]);
#if defined (_WIN32) && (WINVER == 0x0501) // WinXP
if (AesSwitch && force) { // only if forced
#else
if ((info[2] & bit_AES && AesSwitch) || (AesSwitch && force)) {
#endif
aesni = true;
}
#if defined (_WIN32) && (WINVER == 0x0501) // WinXP
if (AvxSwitch && force) { // only if forced
#else
if ((info[2] & bit_AVX && AvxSwitch) || (AvxSwitch && force)) {
#endif
return false;
}
void Detect(bool AesSwitch, bool force)
{
if ((cpu_support_aes() && AesSwitch) || (AesSwitch && force)) {
aesni = true;
avx = true;
}
}
#endif // defined(__x86_64__) || defined(__i386__)
LogPrint(eLogInfo, "AESNI ", (aesni ? "enabled" : "disabled"));
LogPrint(eLogInfo, "AVX ", (avx ? "enabled" : "disabled"));
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2023, The PurpleI2P Project
* Copyright (c) 2013-2020, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -9,31 +9,14 @@
#ifndef LIBI2PD_CPU_H
#define LIBI2PD_CPU_H
#if defined(_M_AMD64) || defined(__x86_64__) || defined(_M_IX86) || defined(__i386__)
# define IS_X86 1
# if defined(_M_AMD64) || defined(__x86_64__)
# define IS_X86_64 1
# else
# define IS_X86_64 0
# endif
#else
# define IS_X86 0
# define IS_X86_64 0
#endif
#if defined(__AES__) && !defined(_MSC_VER) && IS_X86
# define SUPPORTS_AES 1
#else
# define SUPPORTS_AES 0
#endif
namespace i2p
{
namespace cpu
{
extern bool aesni;
extern bool avx;
void Detect(bool AesSwitch, bool force);
void Detect(bool AesSwitch, bool AvxSwitch, bool force);
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2024, The PurpleI2P Project
* Copyright (c) 2013-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -77,8 +77,7 @@ namespace config {
limits.add_options()
("limits.coresize", value<uint32_t>()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)")
("limits.openfiles", value<uint16_t>()->default_value(0), "Maximum number of open files (0 - use system default)")
("limits.transittunnels", value<uint32_t>()->default_value(10000), "Maximum active transit tunnels (default:10000)")
("limits.zombies", value<double>()->default_value(0), "Minimum percentage of successfully created tunnels under which tunnel cleanup is paused (default [%]: 0.00)")
("limits.transittunnels", value<uint16_t>()->default_value(5000), "Maximum active transit tunnels (default:5000)")
("limits.ntcpsoft", value<uint16_t>()->default_value(0), "Ignored")
("limits.ntcphard", value<uint16_t>()->default_value(0), "Ignored")
("limits.ntcpthreads", value<uint16_t>()->default_value(1), "Ignored")
@ -150,8 +149,7 @@ namespace config {
sam.add_options()
("sam.enabled", value<bool>()->default_value(true), "Enable or disable SAM Application bridge")
("sam.address", value<std::string>()->default_value("127.0.0.1"), "SAM listen address")
("sam.port", value<uint16_t>()->default_value(7656), "SAM listen TCP port")
("sam.portudp", value<uint16_t>()->default_value(0), "SAM listen UDP port")
("sam.port", value<uint16_t>()->default_value(7656), "SAM listen port")
("sam.singlethread", value<bool>()->default_value(true), "Sessions run in the SAM bridge's thread")
;
@ -193,7 +191,7 @@ namespace config {
options_description precomputation("Precomputation options");
precomputation.add_options()
("precomputation.elgamal",
#if (defined(_M_AMD64) || defined(__x86_64__))
#if defined(__x86_64__)
value<bool>()->default_value(false),
#else
value<bool>()->default_value(true),
@ -205,7 +203,7 @@ namespace config {
reseed.add_options()
("reseed.verify", value<bool>()->default_value(false), "Verify .su3 signature")
("reseed.threshold", value<uint16_t>()->default_value(25), "Minimum number of known routers before requesting reseed")
("reseed.floodfill", value<std::string>()->default_value(""), "Ignored. Always empty")
("reseed.floodfill", value<std::string>()->default_value(""), "Path to router info of floodfill to reseed from")
("reseed.file", value<std::string>()->default_value(""), "Path to local .su3 file or HTTPS URL 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")
@ -217,20 +215,17 @@ namespace config {
"https://reseed.onion.im/,"
"https://i2pseed.creativecowpat.net:8443/,"
"https://reseed.i2pgit.org/,"
"https://i2p.novg.net/,"
"https://banana.incognet.io/,"
"https://reseed-pl.i2pd.xyz/,"
"https://www2.mk16.de/,"
"https://i2p.ghativega.in/,"
"https://i2p.novg.net/,"
"https://reseed.stormycloud.org/"
"https://www2.mk16.de/"
), "Reseed URLs, separated by comma")
("reseed.yggurls", value<std::string>()->default_value(
"http://[324:71e:281a:9ed3::ace]:7070/,"
"http://[301:65b9:c7cd:9a36::1]:18801/,"
"http://[320:8936:ec1a:31f1::216]/,"
"http://[306:3834:97b9:a00a::1]/,"
"http://[316:f9e0:f22e:a74f::216]/,"
"http://[300:eaff:7fab:181b::e621]:7170"
"http://[316:f9e0:f22e:a74f::216]/"
), "Reseed URLs through the Yggdrasil, separated by comma")
;
@ -310,7 +305,7 @@ namespace config {
options_description cpuext("CPU encryption extensions options");
cpuext.add_options()
("cpuext.aesni", bool_switch()->default_value(true), "Use auto detection for AESNI CPU extensions. If false, AESNI will be not used")
("cpuext.avx", bool_switch()->default_value(false), "Deprecated option")
("cpuext.avx", bool_switch()->default_value(true), "Use auto detection for AVX CPU extensions. If false, AVX will be not used")
("cpuext.force", bool_switch()->default_value(false), "Force usage of CPU extensions. Useful when cpuinfo is not available on virtual machines")
;

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2023, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -28,7 +28,6 @@
#include "I2PEndian.h"
#include "Log.h"
namespace i2p
{
namespace crypto
@ -160,7 +159,7 @@ namespace crypto
// DH/ElGamal
#if !IS_X86_64
#if !defined(__x86_64__)
const int ELGAMAL_SHORT_EXPONENT_NUM_BITS = 226;
const int ELGAMAL_SHORT_EXPONENT_NUM_BYTES = ELGAMAL_SHORT_EXPONENT_NUM_BITS/8+1;
#endif
@ -362,7 +361,7 @@ namespace crypto
BIGNUM * b1 = BN_CTX_get (ctx);
BIGNUM * b = BN_CTX_get (ctx);
// select random k
#if IS_X86_64
#if defined(__x86_64__)
BN_rand (k, ELGAMAL_FULL_EXPONENT_NUM_BITS, -1, 1); // full exponent for x64
#else
BN_rand (k, ELGAMAL_SHORT_EXPONENT_NUM_BITS, -1, 1); // short exponent of 226 bits
@ -429,7 +428,7 @@ namespace crypto
void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub)
{
#if IS_X86 || defined(_MSC_VER)
#if defined(__x86_64__) || defined(__i386__) || defined(_MSC_VER)
RAND_bytes (priv, 256);
#else
// lower 226 bits (28 bytes and 2 bits) only. short exponent
@ -556,7 +555,7 @@ namespace crypto
}
// AES
#if SUPPORTS_AES
#ifdef __AES__
#define KeyExpansion256(round0,round1) \
"pshufd $0xff, %%xmm2, %%xmm2 \n" \
"movaps %%xmm1, %%xmm4 \n" \
@ -581,7 +580,7 @@ namespace crypto
"movaps %%xmm3, "#round1"(%[sched]) \n"
#endif
#if SUPPORTS_AES
#ifdef __AES__
void ECBCryptoAESNI::ExpandKey (const AESKey& key)
{
__asm__
@ -622,7 +621,7 @@ namespace crypto
#endif
#if SUPPORTS_AES
#ifdef __AES__
#define EncryptAES256(sched) \
"pxor (%["#sched"]), %%xmm0 \n" \
"aesenc 16(%["#sched"]), %%xmm0 \n" \
@ -643,18 +642,16 @@ namespace crypto
void ECBEncryption::Encrypt (const ChipherBlock * in, ChipherBlock * out)
{
#if SUPPORTS_AES
#ifdef __AES__
if(i2p::cpu::aesni)
{
__asm__
(
"movups (%[in]), %%xmm0 \n"
EncryptAES256(sched)
"movups %%xmm0, (%[out]) \n"
:
: [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out)
: "%xmm0", "memory"
);
(
"movups (%[in]), %%xmm0 \n"
EncryptAES256(sched)
"movups %%xmm0, (%[out]) \n"
: : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory"
);
}
else
#endif
@ -663,7 +660,7 @@ namespace crypto
}
}
#if SUPPORTS_AES
#ifdef __AES__
#define DecryptAES256(sched) \
"pxor 224(%["#sched"]), %%xmm0 \n" \
"aesdec 208(%["#sched"]), %%xmm0 \n" \
@ -684,18 +681,16 @@ namespace crypto
void ECBDecryption::Decrypt (const ChipherBlock * in, ChipherBlock * out)
{
#if SUPPORTS_AES
#ifdef __AES__
if(i2p::cpu::aesni)
{
__asm__
(
"movups (%[in]), %%xmm0 \n"
DecryptAES256(sched)
"movups %%xmm0, (%[out]) \n"
:
: [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out)
: "%xmm0", "memory"
);
(
"movups (%[in]), %%xmm0 \n"
DecryptAES256(sched)
"movups %%xmm0, (%[out]) \n"
: : [sched]"r"(GetKeySchedule ()), [in]"r"(in), [out]"r"(out) : "%xmm0", "memory"
);
}
else
#endif
@ -704,7 +699,7 @@ namespace crypto
}
}
#if SUPPORTS_AES
#ifdef __AES__
#define CallAESIMC(offset) \
"movaps "#offset"(%[shed]), %%xmm0 \n" \
"aesimc %%xmm0, %%xmm0 \n" \
@ -713,7 +708,7 @@ namespace crypto
void ECBEncryption::SetKey (const AESKey& key)
{
#if SUPPORTS_AES
#ifdef __AES__
if(i2p::cpu::aesni)
{
ExpandKey (key);
@ -727,30 +722,28 @@ namespace crypto
void ECBDecryption::SetKey (const AESKey& key)
{
#if SUPPORTS_AES
#ifdef __AES__
if(i2p::cpu::aesni)
{
ExpandKey (key); // expand encryption key first
// then invert it using aesimc
__asm__
(
CallAESIMC(16)
CallAESIMC(32)
CallAESIMC(48)
CallAESIMC(64)
CallAESIMC(80)
CallAESIMC(96)
CallAESIMC(112)
CallAESIMC(128)
CallAESIMC(144)
CallAESIMC(160)
CallAESIMC(176)
CallAESIMC(192)
CallAESIMC(208)
:
: [shed]"r"(GetKeySchedule ())
: "%xmm0", "memory"
);
(
CallAESIMC(16)
CallAESIMC(32)
CallAESIMC(48)
CallAESIMC(64)
CallAESIMC(80)
CallAESIMC(96)
CallAESIMC(112)
CallAESIMC(128)
CallAESIMC(144)
CallAESIMC(160)
CallAESIMC(176)
CallAESIMC(192)
CallAESIMC(208)
: : [shed]"r"(GetKeySchedule ()) : "%xmm0", "memory"
);
}
else
#endif
@ -761,28 +754,28 @@ namespace crypto
void CBCEncryption::Encrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
{
#if SUPPORTS_AES
#ifdef __AES__
if(i2p::cpu::aesni)
{
__asm__
(
"movups (%[iv]), %%xmm1 \n"
"1: \n"
"movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched)
"movaps %%xmm0, %%xmm1 \n"
"movups %%xmm0, (%[out]) \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"dec %[num] \n"
"jnz 1b \n"
"movups %%xmm1, (%[iv]) \n"
:
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
: "%xmm0", "%xmm1", "cc", "memory"
);
(
"movups (%[iv]), %%xmm1 \n"
"1: \n"
"movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched)
"movaps %%xmm0, %%xmm1 \n"
"movups %%xmm0, (%[out]) \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"dec %[num] \n"
"jnz 1b \n"
"movups %%xmm1, (%[iv]) \n"
:
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
: "%xmm0", "%xmm1", "cc", "memory"
);
}
else
#endif
@ -806,22 +799,22 @@ namespace crypto
void CBCEncryption::Encrypt (const uint8_t * in, uint8_t * out)
{
#if SUPPORTS_AES
#ifdef __AES__
if(i2p::cpu::aesni)
{
__asm__
(
"movups (%[iv]), %%xmm1 \n"
"movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched)
"movups %%xmm0, (%[out]) \n"
"movups %%xmm0, (%[iv]) \n"
:
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out)
: "%xmm0", "%xmm1", "memory"
);
(
"movups (%[iv]), %%xmm1 \n"
"movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched)
"movups %%xmm0, (%[out]) \n"
"movups %%xmm0, (%[iv]) \n"
:
: [iv]"r"((uint8_t *)m_LastBlock), [sched]"r"(m_ECBEncryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out)
: "%xmm0", "%xmm1", "memory"
);
}
else
#endif
@ -830,29 +823,29 @@ namespace crypto
void CBCDecryption::Decrypt (int numBlocks, const ChipherBlock * in, ChipherBlock * out)
{
#if SUPPORTS_AES
#ifdef __AES__
if(i2p::cpu::aesni)
{
__asm__
(
"movups (%[iv]), %%xmm1 \n"
"1: \n"
"movups (%[in]), %%xmm0 \n"
"movaps %%xmm0, %%xmm2 \n"
DecryptAES256(sched)
"pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n"
"movaps %%xmm2, %%xmm1 \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"dec %[num] \n"
"jnz 1b \n"
"movups %%xmm1, (%[iv]) \n"
:
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
);
(
"movups (%[iv]), %%xmm1 \n"
"1: \n"
"movups (%[in]), %%xmm0 \n"
"movaps %%xmm0, %%xmm2 \n"
DecryptAES256(sched)
"pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n"
"movaps %%xmm2, %%xmm1 \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"dec %[num] \n"
"jnz 1b \n"
"movups %%xmm1, (%[iv]) \n"
:
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(numBlocks)
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
);
}
else
#endif
@ -876,22 +869,22 @@ namespace crypto
void CBCDecryption::Decrypt (const uint8_t * in, uint8_t * out)
{
#if SUPPORTS_AES
#ifdef __AES__
if(i2p::cpu::aesni)
{
__asm__
(
"movups (%[iv]), %%xmm1 \n"
"movups (%[in]), %%xmm0 \n"
"movups %%xmm0, (%[iv]) \n"
DecryptAES256(sched)
"pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n"
:
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out)
: "%xmm0", "%xmm1", "memory"
);
(
"movups (%[iv]), %%xmm1 \n"
"movups (%[in]), %%xmm0 \n"
"movups %%xmm0, (%[iv]) \n"
DecryptAES256(sched)
"pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n"
:
: [iv]"r"((uint8_t *)m_IV), [sched]"r"(m_ECBDecryption.GetKeySchedule ()),
[in]"r"(in), [out]"r"(out)
: "%xmm0", "%xmm1", "memory"
);
}
else
#endif
@ -900,34 +893,34 @@ namespace crypto
void TunnelEncryption::Encrypt (const uint8_t * in, uint8_t * out)
{
#if SUPPORTS_AES
#ifdef __AES__
if(i2p::cpu::aesni)
{
__asm__
(
// encrypt IV
"movups (%[in]), %%xmm0 \n"
EncryptAES256(sched_iv)
"movaps %%xmm0, %%xmm1 \n"
// double IV encryption
EncryptAES256(sched_iv)
"movups %%xmm0, (%[out]) \n"
// encrypt data, IV is xmm1
"1: \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched_l)
"movaps %%xmm0, %%xmm1 \n"
"movups %%xmm0, (%[out]) \n"
"dec %[num] \n"
"jnz 1b \n"
:
: [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.ECB().GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
: "%xmm0", "%xmm1", "cc", "memory"
);
(
// encrypt IV
"movups (%[in]), %%xmm0 \n"
EncryptAES256(sched_iv)
"movaps %%xmm0, %%xmm1 \n"
// double IV encryption
EncryptAES256(sched_iv)
"movups %%xmm0, (%[out]) \n"
// encrypt data, IV is xmm1
"1: \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"movups (%[in]), %%xmm0 \n"
"pxor %%xmm1, %%xmm0 \n"
EncryptAES256(sched_l)
"movaps %%xmm0, %%xmm1 \n"
"movups %%xmm0, (%[out]) \n"
"dec %[num] \n"
"jnz 1b \n"
:
: [sched_iv]"r"(m_IVEncryption.GetKeySchedule ()), [sched_l]"r"(m_LayerEncryption.ECB().GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
: "%xmm0", "%xmm1", "cc", "memory"
);
}
else
#endif
@ -941,35 +934,35 @@ namespace crypto
void TunnelDecryption::Decrypt (const uint8_t * in, uint8_t * out)
{
#if SUPPORTS_AES
#ifdef __AES__
if(i2p::cpu::aesni)
{
__asm__
(
// decrypt IV
"movups (%[in]), %%xmm0 \n"
DecryptAES256(sched_iv)
"movaps %%xmm0, %%xmm1 \n"
// double IV encryption
DecryptAES256(sched_iv)
"movups %%xmm0, (%[out]) \n"
// decrypt data, IV is xmm1
"1: \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"movups (%[in]), %%xmm0 \n"
"movaps %%xmm0, %%xmm2 \n"
DecryptAES256(sched_l)
"pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n"
"movaps %%xmm2, %%xmm1 \n"
"dec %[num] \n"
"jnz 1b \n"
:
: [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.ECB().GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
);
(
// decrypt IV
"movups (%[in]), %%xmm0 \n"
DecryptAES256(sched_iv)
"movaps %%xmm0, %%xmm1 \n"
// double IV encryption
DecryptAES256(sched_iv)
"movups %%xmm0, (%[out]) \n"
// decrypt data, IV is xmm1
"1: \n"
"add $16, %[in] \n"
"add $16, %[out] \n"
"movups (%[in]), %%xmm0 \n"
"movaps %%xmm0, %%xmm2 \n"
DecryptAES256(sched_l)
"pxor %%xmm1, %%xmm0 \n"
"movups %%xmm0, (%[out]) \n"
"movaps %%xmm2, %%xmm1 \n"
"dec %[num] \n"
"jnz 1b \n"
:
: [sched_iv]"r"(m_IVDecryption.GetKeySchedule ()), [sched_l]"r"(m_LayerDecryption.ECB().GetKeySchedule ()),
[in]"r"(in), [out]"r"(out), [num]"r"(63) // 63 blocks = 1008 bytes
: "%xmm0", "%xmm1", "%xmm2", "cc", "memory"
);
}
else
#endif
@ -998,7 +991,7 @@ namespace crypto
EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce);
EVP_EncryptUpdate(ctx, NULL, &outlen, ad, adLen);
EVP_EncryptUpdate(ctx, buf, &outlen, msg, msgLen);
EVP_EncryptFinal_ex(ctx, buf + outlen, &outlen);
EVP_EncryptFinal_ex(ctx, buf, &outlen);
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, buf + msgLen);
}
else
@ -1292,9 +1285,9 @@ namespace crypto
}
}*/
void InitCrypto (bool precomputation, bool aesni, bool force)
void InitCrypto (bool precomputation, bool aesni, bool avx, bool force)
{
i2p::cpu::Detect (aesni, force);
i2p::cpu::Detect (aesni, avx, force);
#if LEGACY_OPENSSL
SSL_library_init ();
#endif
@ -1304,7 +1297,7 @@ namespace crypto
CRYPTO_set_locking_callback (OpensslLockingCallback);*/
if (precomputation)
{
#if IS_X86_64
#if defined(__x86_64__)
g_ElggTable = new BIGNUM * [ELGAMAL_FULL_EXPONENT_NUM_BYTES][255];
PrecalculateElggTable (g_ElggTable, ELGAMAL_FULL_EXPONENT_NUM_BYTES);
#else
@ -1319,7 +1312,7 @@ namespace crypto
if (g_ElggTable)
{
DestroyElggTable (g_ElggTable,
#if IS_X86_64
#if defined(__x86_64__)
ELGAMAL_FULL_EXPONENT_NUM_BYTES
#else
ELGAMAL_SHORT_EXPONENT_NUM_BYTES

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2023, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -150,7 +150,7 @@ namespace crypto
};
#if SUPPORTS_AES
#ifdef __AES__
class ECBCryptoAESNI
{
public:
@ -167,7 +167,7 @@ namespace crypto
};
#endif
#if SUPPORTS_AES
#ifdef __AES__
class ECBEncryption: public ECBCryptoAESNI
#else
class ECBEncryption
@ -183,7 +183,7 @@ namespace crypto
AES_KEY m_Key;
};
#if SUPPORTS_AES
#ifdef __AES__
class ECBDecryption: public ECBCryptoAESNI
#else
class ECBDecryption
@ -307,7 +307,7 @@ namespace crypto
void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_IK (ratchets)
// init and terminate
void InitCrypto (bool precomputation, bool aesni, bool force);
void InitCrypto (bool precomputation, bool aesni, bool avx, bool force);
void TerminateCrypto ();
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2024, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -19,7 +19,7 @@ namespace i2p
namespace datagram
{
DatagramDestination::DatagramDestination (std::shared_ptr<i2p::client::ClientDestination> owner, bool gzip):
m_Owner (owner), m_DefaultReceiver (nullptr), m_DefaultRawReceiver (nullptr), m_Gzip (gzip)
m_Owner (owner), m_Receiver (nullptr), m_RawReceiver (nullptr), m_Gzip (gzip)
{
if (m_Gzip)
m_Deflator.reset (new i2p::data::GzipDeflator);
@ -119,79 +119,19 @@ namespace datagram
void DatagramDestination::HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len)
{
auto r = FindRawReceiver(toPort);
if (r)
r (fromPort, toPort, buf, len);
if (m_RawReceiver)
m_RawReceiver (fromPort, toPort, buf, len);
else
LogPrint (eLogWarning, "DatagramDestination: no receiver for raw datagram");
}
void DatagramDestination::SetReceiver (const Receiver& receiver, uint16_t port)
{
std::lock_guard<std::mutex> lock(m_ReceiversMutex);
m_ReceiversByPorts[port] = receiver;
if (!m_DefaultReceiver) {
m_DefaultReceiver = receiver;
m_DefaultReceiverPort = port;
}
}
void DatagramDestination::ResetReceiver (uint16_t port)
{
std::lock_guard<std::mutex> lock(m_ReceiversMutex);
m_ReceiversByPorts.erase (port);
if (m_DefaultReceiverPort == port) {
m_DefaultReceiver = nullptr;
m_DefaultReceiverPort = 0;
}
}
void DatagramDestination::SetRawReceiver (const RawReceiver& receiver, uint16_t port)
{
std::lock_guard<std::mutex> lock(m_RawReceiversMutex);
m_RawReceiversByPorts[port] = receiver;
if (!m_DefaultRawReceiver) {
m_DefaultRawReceiver = receiver;
m_DefaultRawReceiverPort = port;
}
}
void DatagramDestination::ResetRawReceiver (uint16_t port)
{
std::lock_guard<std::mutex> lock(m_RawReceiversMutex);
m_RawReceiversByPorts.erase (port);
if (m_DefaultRawReceiverPort == port) {
m_DefaultRawReceiver = nullptr;
m_DefaultRawReceiverPort = 0;
}
}
DatagramDestination::Receiver DatagramDestination::FindReceiver(uint16_t port)
{
std::lock_guard<std::mutex> lock(m_ReceiversMutex);
Receiver r = nullptr;
Receiver r = m_Receiver;
auto itr = m_ReceiversByPorts.find(port);
if (itr != m_ReceiversByPorts.end())
r = itr->second;
else {
r = m_DefaultReceiver;
}
return r;
}
DatagramDestination::RawReceiver DatagramDestination::FindRawReceiver(uint16_t port)
{
std::lock_guard<std::mutex> lock(m_RawReceiversMutex);
RawReceiver r = nullptr;
auto itr = m_RawReceiversByPorts.find(port);
if (itr != m_RawReceiversByPorts.end())
r = itr->second;
else {
r = m_DefaultRawReceiver;
}
return r;
}
@ -485,7 +425,7 @@ namespace datagram
if (m)
send.push_back(i2p::tunnel::TunnelMessageBlock{i2p::tunnel::eDeliveryTypeTunnel,routingPath->remoteLease->tunnelGateway, routingPath->remoteLease->tunnelID, m});
}
routingPath->outboundTunnel->SendTunnelDataMsgs(send);
routingPath->outboundTunnel->SendTunnelDataMsg(send);
}
m_SendQueue.clear();
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2024, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -126,12 +126,14 @@ namespace datagram
void HandleDataMessagePayload (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len, bool isRaw = false);
void SetReceiver (const Receiver& receiver) { m_Receiver = receiver; };
void ResetReceiver () { m_Receiver = nullptr; };
void SetReceiver (const Receiver& receiver, uint16_t port);
void ResetReceiver (uint16_t port);
void SetReceiver (const Receiver& receiver, uint16_t port) { std::lock_guard<std::mutex> lock(m_ReceiversMutex); m_ReceiversByPorts[port] = receiver; };
void ResetReceiver (uint16_t port) { std::lock_guard<std::mutex> lock(m_ReceiversMutex); m_ReceiversByPorts.erase (port); };
void SetRawReceiver (const RawReceiver& receiver, uint16_t port);
void ResetRawReceiver (uint16_t port);
void SetRawReceiver (const RawReceiver& receiver) { m_RawReceiver = receiver; };
void ResetRawReceiver () { m_RawReceiver = nullptr; };
std::shared_ptr<DatagramSession::Info> GetInfoForRemote(const i2p::data::IdentHash & remote);
@ -148,26 +150,20 @@ namespace datagram
void HandleDatagram (uint16_t fromPort, uint16_t toPort, uint8_t *const& buf, size_t len);
void HandleRawDatagram (uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
/** find a receiver by port, if none by port is found try default receiever, otherwise returns nullptr */
Receiver FindReceiver(uint16_t port);
RawReceiver FindRawReceiver(uint16_t port);
private:
std::shared_ptr<i2p::client::ClientDestination> m_Owner;
Receiver m_Receiver; // default
RawReceiver m_RawReceiver; // default
bool m_Gzip; // gzip compression of data messages
std::mutex m_SessionsMutex;
std::map<i2p::data::IdentHash, DatagramSession_ptr > m_Sessions;
Receiver m_DefaultReceiver;
RawReceiver m_DefaultRawReceiver;
uint16_t m_DefaultReceiverPort;
uint16_t m_DefaultRawReceiverPort;
std::mutex m_ReceiversMutex;
std::mutex m_RawReceiversMutex;
std::unordered_map<uint16_t, Receiver> m_ReceiversByPorts;
std::unordered_map<uint16_t, RawReceiver> m_RawReceiversByPorts;
std::map<uint16_t, Receiver> m_ReceiversByPorts;
bool m_Gzip; // gzip compression of data messages
i2p::data::GzipInflator m_Inflator;
std::unique_ptr<i2p::data::GzipDeflator> m_Deflator;
std::vector<uint8_t> m_From, m_Signature;

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2024, The PurpleI2P Project
* Copyright (c) 2013-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -108,7 +108,7 @@ namespace client
if (authType >= i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_NONE && authType <= i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK)
m_AuthType = authType;
else
LogPrint (eLogError, "Destination: Unknown auth type: ", authType);
LogPrint (eLogError, "Destination: Unknown auth type ", authType);
}
}
it = params->find (I2CP_PARAM_LEASESET_PRIV_KEY);
@ -117,7 +117,7 @@ namespace client
m_LeaseSetPrivKey.reset (new i2p::data::Tag<32>());
if (m_LeaseSetPrivKey->FromBase64 (it->second) != 32)
{
LogPrint(eLogCritical, "Destination: Invalid value i2cp.leaseSetPrivKey: ", it->second);
LogPrint(eLogError, "Destination: Invalid value i2cp.leaseSetPrivKey ", it->second);
m_LeaseSetPrivKey.reset (nullptr);
}
}
@ -262,6 +262,17 @@ namespace client
return nullptr;
}
}
else
{
auto ls = i2p::data::netdb.FindLeaseSet (ident);
if (ls && !ls->IsExpired ())
{
ls->PopulateLeases (); // since we don't store them in netdb
std::lock_guard<std::mutex> _lock(m_RemoteLeaseSetsMutex);
m_RemoteLeaseSets[ident] = ls;
return ls;
}
}
return nullptr;
}
@ -367,12 +378,9 @@ namespace client
HandleDataMessage (payload, len);
break;
case eI2NPDeliveryStatus:
// we assume tunnel tests non-encrypted
HandleDeliveryStatusMessage (bufbe32toh (payload + DELIVERY_STATUS_MSGID_OFFSET));
break;
case eI2NPTunnelTest:
if (m_Pool)
m_Pool->ProcessTunnelTest (bufbe32toh (payload + TUNNEL_TEST_MSGID_OFFSET), bufbe64toh (payload + TUNNEL_TEST_TIMESTAMP_OFFSET));
break;
case eI2NPDatabaseStore:
HandleDatabaseStoreMessage (payload, len);
break;
@ -410,7 +418,6 @@ namespace client
}
i2p::data::IdentHash key (buf + DATABASE_STORE_KEY_OFFSET);
std::shared_ptr<i2p::data::LeaseSet> leaseSet;
std::shared_ptr<LeaseSetRequest> request;
switch (buf[DATABASE_STORE_TYPE_OFFSET])
{
case i2p::data::NETDB_STORE_TYPE_LEASESET: // 1
@ -466,59 +473,34 @@ namespace client
case i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2: // 5
{
auto it2 = m_LeaseSetRequests.find (key);
if (it2 != m_LeaseSetRequests.end ())
{
request = it2->second;
m_LeaseSetRequests.erase (it2);
if (request->requestedBlindedKey)
if (it2 != m_LeaseSetRequests.end () && it2->second->requestedBlindedKey)
{
auto ls2 = std::make_shared<i2p::data::LeaseSet2> (buf + offset, len - offset,
it2->second->requestedBlindedKey, m_LeaseSetPrivKey ? ((const uint8_t *)*m_LeaseSetPrivKey) : nullptr , GetPreferredCryptoType ());
if (ls2->IsValid () && !ls2->IsExpired ())
{
auto ls2 = std::make_shared<i2p::data::LeaseSet2> (buf + offset, len - offset,
request->requestedBlindedKey, m_LeaseSetPrivKey ? ((const uint8_t *)*m_LeaseSetPrivKey) : nullptr , GetPreferredCryptoType ());
if (ls2->IsValid () && !ls2->IsExpired ())
{
leaseSet = ls2;
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
m_RemoteLeaseSets[ls2->GetIdentHash ()] = ls2; // ident is not key
m_RemoteLeaseSets[key] = ls2; // also store as key for next lookup
}
else
LogPrint (eLogError, "Destination: New remote encrypted LeaseSet2 failed");
leaseSet = ls2;
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
m_RemoteLeaseSets[ls2->GetIdentHash ()] = ls2; // ident is not key
m_RemoteLeaseSets[key] = ls2; // also store as key for next lookup
}
else
{
// publishing verification doesn't have requestedBlindedKey
auto localLeaseSet = GetLeaseSetMt ();
if (localLeaseSet->GetStoreHash () == key)
{
auto ls = std::make_shared<i2p::data::LeaseSet2> (i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2,
localLeaseSet->GetBuffer (), localLeaseSet->GetBufferLen (), false);
leaseSet = ls;
}
else
LogPrint (eLogWarning, "Destination: Encrypted LeaseSet2 received for request without blinded key");
}
LogPrint (eLogError, "Destination: New remote encrypted LeaseSet2 failed");
}
else
LogPrint (eLogWarning, "Destination: Couldn't find request for encrypted LeaseSet2");
LogPrint (eLogInfo, "Destination: Couldn't find request for encrypted LeaseSet2");
break;
}
default:
LogPrint (eLogError, "Destination: Unexpected client's DatabaseStore type ", buf[DATABASE_STORE_TYPE_OFFSET], ", dropped");
}
if (!request)
{
auto it1 = m_LeaseSetRequests.find (key);
if (it1 != m_LeaseSetRequests.end ())
{
request = it1->second;
m_LeaseSetRequests.erase (it1);
}
}
if (request)
auto it1 = m_LeaseSetRequests.find (key);
if (it1 != m_LeaseSetRequests.end ())
{
request->requestTimeoutTimer.cancel ();
request->Complete (leaseSet);
it1->second->requestTimeoutTimer.cancel ();
if (it1->second) it1->second->Complete (leaseSet);
m_LeaseSetRequests.erase (it1);
}
}
@ -531,43 +513,38 @@ namespace client
if (it != m_LeaseSetRequests.end ())
{
auto request = it->second;
for (int i = 0; i < num; i++)
bool found = false;
if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST)
{
i2p::data::IdentHash peerHash (buf + 33 + i*32);
if (!request->excluded.count (peerHash) && !i2p::data::netdb.FindRouter (peerHash))
for (int i = 0; i < num; i++)
{
LogPrint (eLogInfo, "Destination: Found new floodfill, request it");
i2p::data::netdb.RequestDestination (peerHash, nullptr, false); // through exploratory
i2p::data::IdentHash peerHash (buf + 33 + i*32);
if (!request->excluded.count (peerHash) && !i2p::data::netdb.FindRouter (peerHash))
{
LogPrint (eLogInfo, "Destination: Found new floodfill, request it");
i2p::data::netdb.RequestDestination (peerHash, nullptr, false); // through exploratory
}
}
auto floodfill = i2p::data::netdb.GetClosestFloodfill (key, request->excluded);
if (floodfill)
{
LogPrint (eLogInfo, "Destination: Requesting ", key.ToBase64 (), " at ", floodfill->GetIdentHash ().ToBase64 ());
if (SendLeaseSetRequest (key, floodfill, request))
found = true;
}
}
SendNextLeaseSetRequest (key, request);
if (!found)
{
LogPrint (eLogInfo, "Destination: ", key.ToBase64 (), " was not found on ", MAX_NUM_FLOODFILLS_PER_REQUEST, " floodfills");
request->Complete (nullptr);
m_LeaseSetRequests.erase (key);
}
}
else
LogPrint (eLogWarning, "Destination: Request for ", key.ToBase64 (), " not found");
}
void LeaseSetDestination::SendNextLeaseSetRequest (const i2p::data::IdentHash& key,
std::shared_ptr<LeaseSetRequest> request)
{
bool found = false;
if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST)
{
auto floodfill = i2p::data::netdb.GetClosestFloodfill (key, request->excluded);
if (floodfill)
{
LogPrint (eLogInfo, "Destination: Requesting ", key.ToBase64 (), " at ", floodfill->GetIdentHash ().ToBase64 ());
if (SendLeaseSetRequest (key, floodfill, request))
found = true;
}
}
if (!found)
{
LogPrint (eLogInfo, "Destination: ", key.ToBase64 (), " was not found on ", MAX_NUM_FLOODFILLS_PER_REQUEST, " floodfills");
request->Complete (nullptr);
m_LeaseSetRequests.erase (key);
}
}
void LeaseSetDestination::HandleDeliveryStatusMessage (uint32_t msgID)
{
if (msgID == m_PublishReplyToken)
@ -612,7 +589,12 @@ namespace client
shared_from_this (), std::placeholders::_1));
return;
}
auto floodfill = i2p::data::netdb.GetClosestFloodfill (leaseSet->GetStoreHash (), m_ExcludedFloodfills);
if (!m_Pool->GetInboundTunnels ().size () || !m_Pool->GetOutboundTunnels ().size ())
{
LogPrint (eLogError, "Destination: Can't publish LeaseSet. Destination is not ready");
return;
}
auto floodfill = i2p::data::netdb.GetClosestFloodfill (leaseSet->GetIdentHash (), m_ExcludedFloodfills);
if (!floodfill)
{
LogPrint (eLogError, "Destination: Can't publish LeaseSet, no more floodfills found");
@ -623,39 +605,26 @@ namespace client
auto inbound = m_Pool->GetNextInboundTunnel (nullptr, floodfill->GetCompatibleTransports (true));
if (!outbound || !inbound)
{
if (!m_Pool->GetInboundTunnels ().empty () && !m_Pool->GetOutboundTunnels ().empty ())
{
LogPrint (eLogInfo, "Destination: No compatible tunnels with ", floodfill->GetIdentHash ().ToBase64 (), ". Trying another floodfill");
m_ExcludedFloodfills.insert (floodfill->GetIdentHash ());
floodfill = i2p::data::netdb.GetClosestFloodfill (leaseSet->GetStoreHash (), m_ExcludedFloodfills);
if (floodfill)
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)
{
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");
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 more floodfills found");
}
LogPrint (eLogError, "Destination: Can't publish LeaseSet. No outbound tunnels");
}
else
LogPrint (eLogDebug, "Destination: No tunnels in pool");
LogPrint (eLogError, "Destination: Can't publish LeaseSet, no more floodfills found");
if (!floodfill || !outbound || !inbound)
{
// we can't publish now
m_ExcludedFloodfills.clear ();
m_PublishReplyToken = 1; // dummy non-zero value
// try again after a while
LogPrint (eLogInfo, "Destination: Can't publish LeasetSet because destination is not ready. Try publishing again after ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds");
m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT));
m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer,
shared_from_this (), std::placeholders::_1));
return;
}
}
@ -663,19 +632,10 @@ namespace client
LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ());
RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4);
auto msg = WrapMessageForRouter (floodfill, i2p::CreateDatabaseStoreMsg (leaseSet, m_PublishReplyToken, inbound));
auto s = shared_from_this ();
msg->onDrop = [s]()
{
s->GetService ().post([s]()
{
s->m_PublishConfirmationTimer.cancel ();
s->HandlePublishConfirmationTimer (boost::system::error_code());
});
};
m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT));
m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer,
shared_from_this (), std::placeholders::_1));
outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, msg);
outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg);
m_LastSubmissionTime = ts;
}
@ -688,7 +648,7 @@ namespace client
m_PublishReplyToken = 0;
if (GetIdentity ()->GetCryptoKeyType () == i2p::data::CRYPTO_KEY_TYPE_ELGAMAL)
{
LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds or failed. will try again");
LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again");
Publish ();
}
else
@ -801,7 +761,7 @@ namespace client
void LeaseSetDestination::RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> requestedBlindedKey)
{
std::unordered_set<i2p::data::IdentHash> excluded;
std::set<i2p::data::IdentHash> excluded;
auto floodfill = i2p::data::netdb.GetClosestFloodfill (dest, excluded);
if (floodfill)
{
@ -873,18 +833,9 @@ namespace client
AddECIESx25519Key (replyKey, replyTag);
else
AddSessionKey (replyKey, replyTag);
auto msg = WrapMessageForRouter (nextFloodfill,
CreateLeaseSetDatabaseLookupMsg (dest, request->excluded, request->replyTunnel, replyKey, replyTag, isECIES));
auto s = shared_from_this ();
msg->onDrop = [s, dest, request]()
{
s->GetService ().post([s, dest, request]()
{
s->SendNextLeaseSetRequest (dest, request);
});
};
request->outboundTunnel->SendTunnelDataMsgs (
auto msg = WrapMessageForRouter (nextFloodfill, CreateLeaseSetDatabaseLookupMsg (dest,
request->excluded, request->replyTunnel, replyKey, replyTag, isECIES));
request->outboundTunnel->SendTunnelDataMsg (
{
i2p::tunnel::TunnelMessageBlock
{
@ -979,7 +930,7 @@ namespace client
bool isPublic, const std::map<std::string, std::string> * params):
LeaseSetDestination (service, isPublic, params),
m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
m_IsStreamingAnswerPings (DEFAULT_ANSWER_PINGS), m_LastPort (0),
m_IsStreamingAnswerPings (DEFAULT_ANSWER_PINGS),
m_DatagramDestination (nullptr), m_RefCounter (0),
m_ReadyChecker(service)
{
@ -1049,7 +1000,7 @@ namespace client
m_StreamingAckDelay = std::stoi(it->second);
it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS);
if (it != params->end ())
m_IsStreamingAnswerPings = std::stoi (it->second); // 1 for true
m_IsStreamingAnswerPings = (it->second == "true");
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
{
@ -1063,12 +1014,12 @@ namespace client
else if (authType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK)
ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_PSK, params);
else
LogPrint (eLogError, "Destination: Unexpected auth type: ", authType);
LogPrint (eLogError, "Destination: Unexpected auth type ", authType);
if (m_AuthKeys->size ())
LogPrint (eLogInfo, "Destination: ", m_AuthKeys->size (), " auth keys read");
else
{
LogPrint (eLogCritical, "Destination: No auth keys read for auth type: ", authType);
LogPrint (eLogError, "Destination: No auth keys read for auth type ", authType);
m_AuthKeys = nullptr;
}
}
@ -1077,7 +1028,7 @@ namespace client
}
catch (std::exception & ex)
{
LogPrint(eLogCritical, "Destination: Unable to parse parameters for destination: ", ex.what());
LogPrint(eLogError, "Destination: Unable to parse parameters for destination: ", ex.what());
}
}
@ -1096,30 +1047,22 @@ namespace client
void ClientDestination::Stop ()
{
LogPrint(eLogDebug, "Destination: Stopping destination ", GetIdentHash().ToBase32(), ".b32.i2p");
LeaseSetDestination::Stop ();
m_ReadyChecker.cancel();
LogPrint(eLogDebug, "Destination: -> Stopping Streaming Destination");
m_StreamingDestination->Stop ();
//m_StreamingDestination->SetOwner (nullptr);
m_StreamingDestination = nullptr;
LogPrint(eLogDebug, "Destination: -> Stopping Streaming Destination by ports");
for (auto& it: m_StreamingDestinationsByPorts)
{
it.second->Stop ();
//it.second->SetOwner (nullptr);
}
m_StreamingDestinationsByPorts.clear ();
m_LastStreamingDestination = nullptr;
if (m_DatagramDestination)
{
LogPrint(eLogDebug, "Destination: -> Stopping Datagram Destination");
delete m_DatagramDestination;
m_DatagramDestination = nullptr;
}
LogPrint(eLogDebug, "Destination: -> Stopping done");
}
void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len)
@ -1139,15 +1082,9 @@ namespace client
case PROTOCOL_TYPE_STREAMING:
{
// streaming protocol
if (toPort != m_LastPort || !m_LastStreamingDestination)
{
m_LastStreamingDestination = GetStreamingDestination (toPort);
if (!m_LastStreamingDestination)
m_LastStreamingDestination = m_StreamingDestination; // if no destination on port use default
m_LastPort = toPort;
}
if (m_LastStreamingDestination)
m_LastStreamingDestination->HandleDataMessagePayload (buf, length);
auto dest = GetStreamingDestination (toPort);
if (dest)
dest->HandleDataMessagePayload (buf, length);
else
LogPrint (eLogError, "Destination: Missing streaming destination");
}
@ -1171,7 +1108,7 @@ namespace client
}
}
void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, uint16_t port)
void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port)
{
if (!streamRequestComplete)
{
@ -1201,7 +1138,7 @@ namespace client
}
}
void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> dest, uint16_t port)
void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port)
{
if (!streamRequestComplete)
{
@ -1220,7 +1157,7 @@ namespace client
}
template<typename Dest>
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStreamSync (const Dest& dest, uint16_t port)
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStreamSync (const Dest& dest, int port)
{
volatile bool done = false;
std::shared_ptr<i2p::stream::Stream> stream;
@ -1244,17 +1181,17 @@ namespace client
return stream;
}
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (const i2p::data::IdentHash& dest, uint16_t port)
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (const i2p::data::IdentHash& dest, int port)
{
return CreateStreamSync (dest, port);
}
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, uint16_t port)
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port)
{
return CreateStreamSync (dest, port);
}
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, uint16_t port)
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, int port)
{
if (m_StreamingDestination)
return m_StreamingDestination->CreateNewOutgoingStream (remote, port);
@ -1291,7 +1228,7 @@ namespace client
});
}
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::GetStreamingDestination (uint16_t port) const
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::GetStreamingDestination (int port) const
{
if (port)
{
@ -1299,9 +1236,8 @@ namespace client
if (it != m_StreamingDestinationsByPorts.end ())
return it->second;
}
else // if port is zero, use default destination
return m_StreamingDestination;
return nullptr;
// if port is zero or not found, use default destination
return m_StreamingDestination;
}
void ClientDestination::AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor)
@ -1329,7 +1265,7 @@ namespace client
m_StreamingDestination->AcceptOnce (acceptor);
}
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::CreateStreamingDestination (uint16_t port, bool gzip)
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::CreateStreamingDestination (int port, bool gzip)
{
auto dest = std::make_shared<i2p::stream::StreamingDestination> (GetSharedFromThis (), port, gzip);
if (port)
@ -1339,7 +1275,7 @@ namespace client
return dest;
}
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::RemoveStreamingDestination (uint16_t port)
std::shared_ptr<i2p::stream::StreamingDestination> ClientDestination::RemoveStreamingDestination (int port)
{
if (port)
{
@ -1400,7 +1336,7 @@ namespace client
f1.write ((char *)keys->priv, 256);
return;
}
LogPrint(eLogCritical, "Destinations: Can't save keys to ", path);
LogPrint(eLogError, "Destinations: Can't save keys to ", path);
}
void ClientDestination::CreateNewLeaseSet (const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels)
@ -1477,7 +1413,7 @@ namespace client
if (pubKey.FromBase64 (it.second.substr (pos+1)))
m_AuthKeys->push_back (pubKey);
else
LogPrint (eLogCritical, "Destination: Unexpected auth key: ", it.second.substr (pos+1));
LogPrint (eLogError, "Destination: Unexpected auth key ", it.second.substr (pos+1));
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2024, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -14,8 +14,7 @@
#include <mutex>
#include <memory>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <string>
#include <functional>
#include <boost/asio.hpp>
@ -97,7 +96,7 @@ namespace client
struct LeaseSetRequest
{
LeaseSetRequest (boost::asio::io_service& service): requestTime (0), requestTimeoutTimer (service) {};
std::unordered_set<i2p::data::IdentHash> excluded;
std::set<i2p::data::IdentHash> excluded;
uint64_t requestTime;
boost::asio::deadline_timer requestTimeoutTimer;
std::list<RequestComplete> requestComplete;
@ -176,7 +175,6 @@ namespace client
void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> requestedBlindedKey = nullptr);
bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request);
void SendNextLeaseSetRequest (const i2p::data::IdentHash& key, std::shared_ptr<LeaseSetRequest> request);
void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest);
void HandleCleanupTimer (const boost::system::error_code& ecode);
void CleanupRemoteLeaseSets ();
@ -186,8 +184,8 @@ namespace client
boost::asio::io_service& m_Service;
mutable std::mutex m_RemoteLeaseSetsMutex;
std::unordered_map<i2p::data::IdentHash, std::shared_ptr<i2p::data::LeaseSet> > m_RemoteLeaseSets;
std::unordered_map<i2p::data::IdentHash, std::shared_ptr<LeaseSetRequest> > m_LeaseSetRequests;
std::map<i2p::data::IdentHash, std::shared_ptr<i2p::data::LeaseSet> > m_RemoteLeaseSets;
std::map<i2p::data::IdentHash, std::shared_ptr<LeaseSetRequest> > m_LeaseSetRequests;
std::shared_ptr<i2p::tunnel::TunnelPool> m_Pool;
std::mutex m_LeaseSetMutex;
@ -195,7 +193,7 @@ namespace client
bool m_IsPublic;
uint32_t m_PublishReplyToken;
uint64_t m_LastSubmissionTime; // in seconds
std::unordered_set<i2p::data::IdentHash> m_ExcludedFloodfills; // for publishing
std::set<i2p::data::IdentHash> m_ExcludedFloodfills; // for publishing
boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer,
m_PublishDelayTimer, m_CleanupTimer;
@ -243,15 +241,15 @@ namespace client
int GetRefCounter () const { return m_RefCounter; };
// streaming
std::shared_ptr<i2p::stream::StreamingDestination> CreateStreamingDestination (uint16_t port, bool gzip = true); // additional
std::shared_ptr<i2p::stream::StreamingDestination> GetStreamingDestination (uint16_t port = 0) const;
std::shared_ptr<i2p::stream::StreamingDestination> RemoveStreamingDestination (uint16_t port);
std::shared_ptr<i2p::stream::StreamingDestination> CreateStreamingDestination (int port, bool gzip = true); // additional
std::shared_ptr<i2p::stream::StreamingDestination> GetStreamingDestination (int port = 0) const;
std::shared_ptr<i2p::stream::StreamingDestination> RemoveStreamingDestination (int port);
// following methods operate with default streaming destination
void CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, uint16_t port = 0);
void CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> dest, uint16_t port = 0);
std::shared_ptr<i2p::stream::Stream> CreateStream (const i2p::data::IdentHash& dest, uint16_t port = 0); // sync
std::shared_ptr<i2p::stream::Stream> CreateStream (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, uint16_t port = 0); // sync
std::shared_ptr<i2p::stream::Stream> CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, uint16_t port = 0);
void CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port = 0);
void CreateStream (StreamRequestComplete streamRequestComplete, std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port = 0);
std::shared_ptr<i2p::stream::Stream> CreateStream (const i2p::data::IdentHash& dest, int port = 0); // sync
std::shared_ptr<i2p::stream::Stream> CreateStream (std::shared_ptr<const i2p::data::BlindedPublicKey> dest, int port = 0); // sync
std::shared_ptr<i2p::stream::Stream> CreateStream (std::shared_ptr<const i2p::data::LeaseSet> remote, int port = 0);
void SendPing (const i2p::data::IdentHash& to);
void SendPing (std::shared_ptr<const i2p::data::BlindedPublicKey> to);
void AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor);
@ -287,7 +285,7 @@ namespace client
void ReadAuthKey (const std::string& group, const std::map<std::string, std::string> * params);
template<typename Dest>
std::shared_ptr<i2p::stream::Stream> CreateStreamSync (const Dest& dest, uint16_t port);
std::shared_ptr<i2p::stream::Stream> CreateStreamSync (const Dest& dest, int port);
private:
@ -299,7 +297,6 @@ namespace client
bool m_IsStreamingAnswerPings;
std::shared_ptr<i2p::stream::StreamingDestination> m_StreamingDestination; // default
std::map<uint16_t, std::shared_ptr<i2p::stream::StreamingDestination> > m_StreamingDestinationsByPorts;
std::shared_ptr<i2p::stream::StreamingDestination> m_LastStreamingDestination; uint16_t m_LastPort; // for server tunnels
i2p::datagram::DatagramDestination * m_DatagramDestination;
int m_RefCounter; // how many clients(tunnels) use this destination

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2024, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -117,12 +117,6 @@ namespace garlic
return session->HandleNextMessage (buf, len, shared_from_this (), index);
}
bool ReceiveRatchetTagSet::IsSessionTerminated () const
{
return !m_Session || m_Session->IsTerminated ();
}
SymmetricKeyTagSet::SymmetricKeyTagSet (GarlicDestination * destination, const uint8_t * key):
ReceiveRatchetTagSet (nullptr), m_Destination (destination)
{
@ -341,8 +335,7 @@ namespace garlic
case eECIESx25519BlkAckRequest:
{
LogPrint (eLogDebug, "Garlic: Ack request");
if (receiveTagset)
m_AckRequests.push_back ({receiveTagset->GetTagSetID (), index});
m_AckRequests.push_back ({receiveTagset->GetTagSetID (), index});
break;
}
case eECIESx25519BlkTermination:
@ -863,7 +856,7 @@ namespace garlic
payloadLen += msg->GetPayloadLength () + 13;
if (m_Destination) payloadLen += 32;
}
if (GetLeaseSetUpdateStatus () == eLeaseSetSubmitted && ts > GetLeaseSetSubmissionTime () + LEASESET_CONFIRMATION_TIMEOUT)
if (GetLeaseSetUpdateStatus () == eLeaseSetSubmitted && ts > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT)
{
// resubmit non-confirmed LeaseSet
SetLeaseSetUpdateStatus (eLeaseSetUpdated);
@ -1154,9 +1147,9 @@ namespace garlic
return len;
}
std::shared_ptr<I2NPMessage> WrapECIESX25519Message (std::shared_ptr<I2NPMessage> msg, const uint8_t * key, uint64_t tag)
std::shared_ptr<I2NPMessage> WrapECIESX25519Message (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag)
{
auto m = NewI2NPMessage ((msg ? msg->GetPayloadLength () : 0) + 128);
auto m = NewI2NPMessage ();
m->Align (12); // in order to get buf aligned to 16 (12 + 4)
uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length
size_t offset = 0;
@ -1174,21 +1167,15 @@ namespace garlic
htobe32buf (m->GetPayload (), offset);
m->len += offset + 4;
m->FillI2NPMessageHeader (eI2NPGarlic);
if (msg->onDrop)
{
// move onDrop to the wrapping I2NP messages
m->onDrop = msg->onDrop;
msg->onDrop = nullptr;
}
return m;
}
std::shared_ptr<I2NPMessage> WrapECIESX25519MessageForRouter (std::shared_ptr<I2NPMessage> msg, const uint8_t * routerPublicKey)
std::shared_ptr<I2NPMessage> WrapECIESX25519MessageForRouter (std::shared_ptr<const I2NPMessage> msg, const uint8_t * routerPublicKey)
{
// Noise_N, we are Alice, routerPublicKey is Bob's
i2p::crypto::NoiseSymmetricState noiseState;
i2p::crypto::InitNoiseNState (noiseState, routerPublicKey);
auto m = NewI2NPMessage ((msg ? msg->GetPayloadLength () : 0) + 128);
auto m = NewI2NPMessage ();
m->Align (12); // in order to get buf aligned to 16 (12 + 4)
uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length
size_t offset = 0;
@ -1217,12 +1204,6 @@ namespace garlic
htobe32buf (m->GetPayload (), offset);
m->len += offset + 4;
m->FillI2NPMessageHeader (eI2NPGarlic);
if (msg->onDrop)
{
// move onDrop to the wrapping I2NP messages
m->onDrop = msg->onDrop;
msg->onDrop = nullptr;
}
return m;
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2024, The PurpleI2P Project
* Copyright (c) 2013-2021, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -86,8 +86,7 @@ namespace garlic
virtual bool IsIndexExpired (int index) const;
virtual bool HandleNextMessage (uint8_t * buf, size_t len, int index);
virtual bool IsSessionTerminated () const;
private:
int m_TrimBehindIndex = 0;
@ -102,10 +101,9 @@ namespace garlic
SymmetricKeyTagSet (GarlicDestination * destination, const uint8_t * key);
bool IsIndexExpired (int index) const override { return false; };
bool HandleNextMessage (uint8_t * buf, size_t len, int index) override;
bool IsSessionTerminated () const override { return false; }
bool IsIndexExpired (int index) const { return false; };
bool HandleNextMessage (uint8_t * buf, size_t len, int index);
private:
GarlicDestination * m_Destination;
@ -247,8 +245,8 @@ namespace garlic
i2p::crypto::NoiseSymmetricState m_CurrentNoiseState;
};
std::shared_ptr<I2NPMessage> WrapECIESX25519Message (std::shared_ptr<I2NPMessage> msg, const uint8_t * key, uint64_t tag);
std::shared_ptr<I2NPMessage> WrapECIESX25519MessageForRouter (std::shared_ptr<I2NPMessage> msg, const uint8_t * routerPublicKey);
std::shared_ptr<I2NPMessage> WrapECIESX25519Message (std::shared_ptr<const I2NPMessage> msg, const uint8_t * key, uint64_t tag);
std::shared_ptr<I2NPMessage> WrapECIESX25519MessageForRouter (std::shared_ptr<const I2NPMessage> msg, const uint8_t * routerPublicKey);
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2023, The PurpleI2P Project
* Copyright (c) 2013-2020, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -413,7 +413,7 @@ namespace crypto
BIGNUM * y = BN_new ();
BN_bin2bn (buf1, EDDSA25519_PUBLIC_KEY_LENGTH, y);
BIGNUM * x = RecoverX (y, ctx);
if ((bool)BN_is_bit_set (x, 0) != isHighestBitSet)
if (BN_is_bit_set (x, 0) != isHighestBitSet)
BN_sub (x, q, x); // x = q - x
BIGNUM * z = BN_new (), * t = BN_new ();
BN_one (z); BN_mod_mul (t, x, y, q, ctx); // pre-calculate t

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2024, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -9,11 +9,6 @@
#include <algorithm>
#include <boost/filesystem.hpp>
#if defined(MAC_OSX)
#include <boost/system/system_error.hpp>
#include <TargetConditionals.h>
#endif
#ifdef _WIN32
#include <shlobj.h>
#include <windows.h>
@ -54,11 +49,7 @@ namespace fs {
const std::string GetUTF8DataDir () {
#ifdef _WIN32
#if (BOOST_VERSION >= 108500)
boost::filesystem::path path (dataDir);
#else
boost::filesystem::wpath path (dataDir);
#endif
auto loc = boost::filesystem::path::imbue(std::locale( std::locale(), new std::codecvt_utf8_utf16<wchar_t>() ) ); // convert path to UTF-8
auto dataDirUTF8 = path.string();
boost::filesystem::path::imbue(loc); // Return locale settings back
@ -91,11 +82,7 @@ namespace fs {
}
else
{
#if (BOOST_VERSION >= 108500)
dataDir = boost::filesystem::path(commonAppData).string() + "\\" + appName;
#else
dataDir = boost::filesystem::wpath(commonAppData).string() + "\\" + appName;
#endif
}
#else
dataDir = "/var/lib/" + appName;
@ -120,11 +107,7 @@ namespace fs {
}
else
{
#if (BOOST_VERSION >= 108500)
auto execPath = boost::filesystem::path(localAppData).parent_path();
#else
auto execPath = boost::filesystem::wpath(localAppData).parent_path();
#endif
// if config file exists in .exe's folder use it
if(boost::filesystem::exists(execPath/"i2pd.conf")) // TODO: magic string
@ -143,11 +126,7 @@ namespace fs {
}
else
{
#if (BOOST_VERSION >= 108500)
dataDir = boost::filesystem::path(localAppData).string() + "\\" + appName;
#else
dataDir = boost::filesystem::wpath(localAppData).string() + "\\" + appName;
#endif
}
}
}
@ -157,14 +136,6 @@ namespace fs {
dataDir = (home != NULL && strlen(home) > 0) ? home : "";
dataDir += "/Library/Application Support/" + appName;
return;
#elif defined(__HAIKU__)
char *home = getenv("HOME");
if (home != NULL && strlen(home) > 0) {
dataDir = std::string(home) + "/config/settings/" + appName;
} else {
dataDir = "/tmp/" + appName;
}
return;
#else /* other unix */
#if defined(ANDROID)
const char * ext = getenv("EXTERNAL_STORAGE");
@ -272,22 +243,8 @@ namespace fs {
auto p = root + i2p::fs::dirSep + prefix1 + chars[i];
if (boost::filesystem::exists(p))
continue;
#if TARGET_OS_SIMULATOR
// ios simulator fs says it is case sensitive, but it is not
boost::system::error_code ec;
if (boost::filesystem::create_directory(p, ec))
continue;
switch (ec.value()) {
case boost::system::errc::file_exists:
case boost::system::errc::success:
continue;
default:
throw boost::system::system_error( ec, __func__ );
}
#else
if (boost::filesystem::create_directory(p))
continue; /* ^ throws exception on failure */
#endif
return false;
}
return true;

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2023, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -88,7 +88,7 @@ namespace data
}
EVP_PKEY_free (pkey);
if (verifier && cn)
m_SigningKeys.emplace (cn, std::make_pair(verifier, (int)m_SigningKeys.size () + 1));
m_SigningKeys.emplace (cn, std::make_pair(verifier, m_SigningKeys.size () + 1));
}
SSL_free (ssl);
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2024, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -80,7 +80,7 @@ namespace garlic
void GarlicRoutingSession::CleanupUnconfirmedLeaseSet (uint64_t ts)
{
if (m_LeaseSetUpdateMsgID && ts*1000LL > m_LeaseSetSubmissionTime + LEASESET_CONFIRMATION_TIMEOUT)
if (m_LeaseSetUpdateMsgID && ts*1000LL > m_LeaseSetSubmissionTime + LEASET_CONFIRMATION_TIMEOUT)
{
if (GetOwner ())
GetOwner ()->RemoveDeliveryStatusSession (m_LeaseSetUpdateMsgID);
@ -232,7 +232,7 @@ namespace garlic
if (GetOwner ())
{
// resubmit non-confirmed LeaseSet
if (GetLeaseSetUpdateStatus () == eLeaseSetSubmitted && ts > GetLeaseSetSubmissionTime () + LEASESET_CONFIRMATION_TIMEOUT)
if (GetLeaseSetUpdateStatus () == eLeaseSetSubmitted && ts > GetLeaseSetSubmissionTime () + LEASET_CONFIRMATION_TIMEOUT)
{
SetLeaseSetUpdateStatus (eLeaseSetUpdated);
SetSharedRoutingPath (nullptr); // invalidate path since leaseset was not confirmed
@ -588,7 +588,7 @@ namespace garlic
auto it = m_ECIESx25519Tags.find (tag);
if (it != m_ECIESx25519Tags.end ())
{
if (it->second.tagset && it->second.tagset->HandleNextMessage (buf, len, it->second.index))
if (it->second.tagset->HandleNextMessage (buf, len, it->second.index))
m_LastTagset = it->second.tagset;
else
LogPrint (eLogError, "Garlic: Can't handle ECIES-X25519-AEAD-Ratchet message");
@ -709,7 +709,7 @@ namespace garlic
else
LogPrint (eLogError, "Garlic: Tunnel pool is not set for inbound tunnel");
if (tunnel) // we have sent it through an outbound tunnel
tunnel->SendTunnelDataMsgTo (gwHash, gwTunnel, msg);
tunnel->SendTunnelDataMsg (gwHash, gwTunnel, msg);
else
LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove");
}
@ -887,7 +887,8 @@ namespace garlic
}
else
{
if (it->second.tagset->IsSessionTerminated ())
auto session = it->second.tagset->GetSession ();
if (!session || session->IsTerminated())
{
it = m_ECIESx25519Tags.erase (it);
numExpiredTags++;
@ -1074,7 +1075,7 @@ namespace garlic
{
auto tunnel = GetTunnelPool ()->GetNextOutboundTunnel ();
if (tunnel)
tunnel->SendTunnelDataMsgTo (gwHash, gwTunnel, CreateI2NPMessage (typeID, buf, len - offset, msgID));
tunnel->SendTunnelDataMsg (gwHash, gwTunnel, CreateI2NPMessage (typeID, buf, len - offset, msgID));
else
LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove");
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2024, The PurpleI2P Project
* Copyright (c) 2013-2022, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -50,7 +50,7 @@ namespace garlic
const int INCOMING_TAGS_EXPIRATION_TIMEOUT = 960; // 16 minutes
const int OUTGOING_TAGS_EXPIRATION_TIMEOUT = 720; // 12 minutes
const int OUTGOING_TAGS_CONFIRMATION_TIMEOUT = 10; // 10 seconds
const int LEASESET_CONFIRMATION_TIMEOUT = 4000; // in milliseconds
const int LEASET_CONFIRMATION_TIMEOUT = 4000; // in milliseconds
const int ROUTING_PATH_EXPIRATION_TIMEOUT = 30; // 30 seconds
const int ROUTING_PATH_MAX_NUM_TIMES_USED = 100; // how many times might be used
@ -221,7 +221,7 @@ namespace garlic
struct ECIESX25519AEADRatchetIndexTagset
{
int index;
ReceiveRatchetTagSetPtr tagset; // null if used
ReceiveRatchetTagSetPtr tagset;
};
class GarlicDestination: public i2p::data::LocalDestination

@ -139,7 +139,7 @@ namespace data
if (m_IsDirty) deflateReset (&m_Deflator);
m_IsDirty = true;
size_t offset = 0;
int err = 0;
int err;
for (const auto& it: bufs)
{
m_Deflator.next_in = const_cast<uint8_t *>(it.first);

@ -93,18 +93,15 @@ namespace http
std::size_t pos_c = 0; /* < work position */
if(url.at(0) != '/' || pos_p > 0) {
std::size_t pos_s = 0;
/* schema */
pos_c = url.find("://");
if (pos_c != std::string::npos) {
schema = url.substr(0, pos_c);
pos_p = pos_c + 3;
}
/* user[:pass] */
pos_s = url.find('/', pos_p); /* find first slash */
pos_c = url.find('@', pos_p); /* find end of 'user' or 'user:pass' part */
if (pos_c != std::string::npos && (pos_s == std::string::npos || pos_s > pos_c)) {
std::size_t delim = url.find(':', pos_p);
if (delim && delim != std::string::npos && delim < pos_c) {
@ -116,28 +113,21 @@ namespace http
}
pos_p = pos_c + 1;
}
/* hostname[:port][/path] */
if (url.at(pos_p) == '[') // ipv6
if (url[pos_p] == '[') // ipv6
{
auto pos_b = url.find(']', pos_p);
if (pos_b == std::string::npos) return false;
ipv6 = true;
pos_c = url.find_first_of(":/", pos_b);
}
else
pos_c = url.find_first_of(":/", pos_p);
if (pos_c == std::string::npos) {
/* only hostname, without post and path */
host = ipv6 ?
url.substr(pos_p + 1, url.length() - 1) :
url.substr(pos_p, std::string::npos);
host = url.substr(pos_p, std::string::npos);
return true;
} else if (url.at(pos_c) == ':') {
host = ipv6 ?
url.substr(pos_p + 1, pos_c - pos_p - 2) :
url.substr(pos_p, pos_c - pos_p);
host = url.substr(pos_p, pos_c - pos_p);
/* port[/path] */
pos_p = pos_c + 1;
pos_c = url.find('/', pos_p);
@ -157,9 +147,7 @@ namespace http
pos_p = pos_c;
} else {
/* start of path part found */
host = ipv6 ?
url.substr(pos_p + 1, pos_c - pos_p - 2) :
url.substr(pos_p, pos_c - pos_p);
host = url.substr(pos_p, pos_c - pos_p);
pos_p = pos_c;
}
}
@ -224,18 +212,10 @@ namespace http
} else if (user != "") {
out += user + "@";
}
if (ipv6) {
if (port) {
out += "[" + host + "]:" + std::to_string(port);
} else {
out += "[" + host + "]";
}
if (port) {
out += host + ":" + std::to_string(port);
} else {
if (port) {
out += host + ":" + std::to_string(port);
} else {
out += host;
}
out += host;
}
}
out += path;

@ -36,9 +36,8 @@ namespace http
bool hasquery;
std::string query;
std::string frag;
bool ipv6;
URL(): schema(""), user(""), pass(""), host(""), port(0), path(""), hasquery(false), query(""), frag(""), ipv6(false) {};
URL(): schema(""), user(""), pass(""), host(""), port(0), path(""), hasquery(false), query(""), frag("") {};
/**
* @brief Tries to parse url from string

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2024, The PurpleI2P Project
* Copyright (c) 2013-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
@ -36,11 +36,6 @@ namespace i2p
return std::make_shared<I2NPMessageBuffer<I2NP_MAX_SHORT_MESSAGE_SIZE> >();
}
std::shared_ptr<I2NPMessage> NewI2NPMediumMessage ()
{
return std::make_shared<I2NPMessageBuffer<I2NP_MAX_MEDIUM_MESSAGE_SIZE> >();
}
std::shared_ptr<I2NPMessage> NewI2NPTunnelMessage (bool endpoint)
{
return i2p::tunnel::tunnels.NewI2NPTunnelMessage (endpoint);
@ -48,10 +43,7 @@ namespace i2p
std::shared_ptr<I2NPMessage> NewI2NPMessage (size_t len)
{
len += I2NP_HEADER_SIZE + 2;
if (len <= I2NP_MAX_SHORT_MESSAGE_SIZE) return NewI2NPShortMessage ();
if (len <= I2NP_MAX_MEDIUM_MESSAGE_SIZE) return NewI2NPMediumMessage ();
return NewI2NPMessage ();
return (len < I2NP_MAX_SHORT_MESSAGE_SIZE - I2NP_HEADER_SIZE - 2) ? NewI2NPShortMessage () : NewI2NPMessage ();
}
void I2NPMessage::FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID, bool checksum)
@ -72,15 +64,11 @@ namespace i2p
SetExpiration (i2p::util::GetMillisecondsSinceEpoch () + I2NP_MESSAGE_EXPIRATION_TIMEOUT);
}
bool I2NPMessage::IsExpired (uint64_t ts) const
bool I2NPMessage::IsExpired () const
{
auto ts = i2p::util::GetMillisecondsSinceEpoch ();
auto exp = GetExpiration ();
return (ts > exp + I2NP_MESSAGE_CLOCK_SKEW) || (ts < exp - 3*I2NP_MESSAGE_CLOCK_SKEW); // check if expired or too far in future
}
bool I2NPMessage::IsExpired () const
{
return IsExpired (i2p::util::GetMillisecondsSinceEpoch ());
}
std::shared_ptr<I2NPMessage> CreateI2NPMessage (I2NPMessageType msgType, const uint8_t * buf, size_t len, uint32_t replyMsgID)
@ -115,17 +103,6 @@ namespace i2p
return newMsg;
}
std::shared_ptr<I2NPMessage> CreateTunnelTestMsg (uint32_t msgID)
{
auto m = NewI2NPShortMessage ();
uint8_t * buf = m->GetPayload ();
htobe32buf (buf + TUNNEL_TEST_MSGID_OFFSET, msgID);
htobe64buf (buf + TUNNEL_TEST_TIMESTAMP_OFFSET, i2p::util::GetMonotonicMicroseconds ());
m->len += TUNNEL_TEST_SIZE;
m->FillI2NPMessageHeader (eI2NPTunnelTest);
return m;
}
std::shared_ptr<I2NPMessage> CreateDeliveryStatusMsg (uint32_t msgID)
{
auto m = NewI2NPShortMessage ();
@ -147,10 +124,9 @@ namespace i2p
}
std::shared_ptr<I2NPMessage> CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from,
uint32_t replyTunnelID, bool exploratory, std::unordered_set<i2p::data::IdentHash> * excludedPeers)
uint32_t replyTunnelID, bool exploratory, std::set<i2p::data::IdentHash> * excludedPeers)
{
int cnt = excludedPeers ? excludedPeers->size () : 0;
auto m = cnt > 7 ? NewI2NPMessage () : NewI2NPShortMessage ();
auto m = excludedPeers ? NewI2NPMessage () : NewI2NPShortMessage ();
uint8_t * buf = m->GetPayload ();
memcpy (buf, key, 32); // key
buf += 32;
@ -171,6 +147,7 @@ namespace i2p
if (excludedPeers)
{
int cnt = excludedPeers->size ();
htobe16buf (buf, cnt);
buf += 2;
for (auto& it: *excludedPeers)
@ -192,7 +169,7 @@ namespace i2p
}
std::shared_ptr<I2NPMessage> CreateLeaseSetDatabaseLookupMsg (const i2p::data::IdentHash& dest,
const std::unordered_set<i2p::data::IdentHash>& excludedFloodfills,
const std::set<i2p::data::IdentHash>& excludedFloodfills,
std::shared_ptr<const i2p::tunnel::InboundTunnel> replyTunnel, const uint8_t * replyKey,
const uint8_t * replyTag, bool replyECIES)
{
@ -376,6 +353,21 @@ namespace i2p
return !msg->GetPayload ()[DATABASE_STORE_TYPE_OFFSET]; // 0- RouterInfo
}
static uint16_t g_MaxNumTransitTunnels = DEFAULT_MAX_NUM_TRANSIT_TUNNELS; // TODO:
void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels)
{
if (maxNumTransitTunnels > 0 && g_MaxNumTransitTunnels != maxNumTransitTunnels)
{
LogPrint (eLogDebug, "I2NP: Max number of transit tunnels set to ", maxNumTransitTunnels);
g_MaxNumTransitTunnels = maxNumTransitTunnels;
}
}
uint16_t GetMaxNumTransitTunnels ()
{
return g_MaxNumTransitTunnels;
}
static bool HandleBuildRequestRecords (int num, uint8_t * records, uint8_t * clearText)
{
for (int i = 0; i < num; i++)
@ -384,20 +376,13 @@ namespace i2p
if (!memcmp (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)i2p::context.GetRouterInfo ().GetIdentHash (), 16))
{
LogPrint (eLogDebug, "I2NP: Build request record ", i, " is ours");
if (!i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText))
{
LogPrint (eLogWarning, "I2NP: Failed to decrypt tunnel build record");
return false;
}
if (!memcmp ((const uint8_t *)i2p::context.GetIdentHash (), clearText + ECIES_BUILD_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32) && // if next ident is now ours
!(clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG)) // and not endpoint
{
LogPrint (eLogWarning, "I2NP: Next ident is ours in tunnel build record");
return false;
}
if (!i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText)) return false;
uint8_t retCode = 0;
// replace record to reply
if (i2p::context.AcceptsTunnels () && i2p::context.GetCongestionLevel (false) < CONGESTION_LEVEL_FULL)
if (i2p::context.AcceptsTunnels () &&
i2p::tunnel::tunnels.GetTransitTunnels ().size () <= g_MaxNumTransitTunnels &&
!i2p::transport::transports.IsBandwidthExceeded () &&
!i2p::transport::transports.IsTransitBandwidthExceeded ())
{
auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
@ -449,11 +434,6 @@ namespace i2p
{
int num = buf[0];
LogPrint (eLogDebug, "I2NP: VariableTunnelBuild ", num, " records");
if (num > i2p::tunnel::MAX_NUM_RECORDS)
{
LogPrint (eLogError, "I2NP: Too many records in VaribleTunnelBuild message ", num);
return;
}
if (len < num*TUNNEL_BUILD_RECORD_SIZE + 1)
{
LogPrint (eLogError, "I2NP: VaribleTunnelBuild message of ", num, " records is too short ", len);
@ -507,11 +487,6 @@ namespace i2p
{
int num = buf[0];
LogPrint (eLogDebug, "I2NP: TunnelBuildReplyMsg of ", num, " records replyMsgID=", replyMsgID);
if (num > i2p::tunnel::MAX_NUM_RECORDS)
{
LogPrint (eLogError, "I2NP: Too many records in TunnelBuildReply message ", num);
return;
}
size_t recordSize = isShort ? SHORT_TUNNEL_BUILD_RECORD_SIZE : TUNNEL_BUILD_RECORD_SIZE;
if (len < num*recordSize + 1)
{
@ -543,11 +518,6 @@ namespace i2p
{
int num = buf[0];
LogPrint (eLogDebug, "I2NP: ShortTunnelBuild ", num, " records");
if (num > i2p::tunnel::MAX_NUM_RECORDS)
{
LogPrint (eLogError, "I2NP: Too many records in ShortTunnelBuild message ", num);
return;
}
if (len < num*SHORT_TUNNEL_BUILD_RECORD_SIZE + 1)
{
LogPrint (eLogError, "I2NP: ShortTunnelBuild message of ", num, " records is too short ", len);
@ -602,24 +572,19 @@ namespace i2p
memcpy (ivKey, noiseState.m_CK + 32, 32);
}
else
{
if (!memcmp ((const uint8_t *)i2p::context.GetIdentHash (), clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // if next ident is now ours
{
LogPrint (eLogWarning, "I2NP: Next ident is ours in short request record");
return;
}
memcpy (ivKey, noiseState.m_CK , 32);
}
// check if we accept this tunnel
std::shared_ptr<i2p::tunnel::TransitTunnel> transitTunnel;
uint8_t retCode = 0;
if (!i2p::context.AcceptsTunnels () || i2p::context.GetCongestionLevel (false) >= CONGESTION_LEVEL_FULL)
retCode = 30;
if (!i2p::context.AcceptsTunnels () ||
i2p::tunnel::tunnels.GetTransitTunnels ().size () > g_MaxNumTransitTunnels ||
i2p::transport::transports.IsBandwidthExceeded () ||
i2p::transport::transports.IsTransitBandwidthExceeded ())
retCode = 30;
if (!retCode)
{
// create new transit tunnel
transitTunnel = i2p::tunnel::CreateTransitTunnel (
auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
bufbe32toh (clearText + SHORT_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET),
@ -653,22 +618,11 @@ namespace i2p
reply += SHORT_TUNNEL_BUILD_RECORD_SIZE;
}
// send reply
auto onDrop = [transitTunnel]()
{
if (transitTunnel)
{
auto t = transitTunnel->GetCreationTime ();
if (t > i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT)
// make transit tunnel expired
transitTunnel->SetCreationTime (t - i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT);
}
};
if (isEndpoint)
{
auto replyMsg = NewI2NPShortMessage ();
replyMsg->Concat (buf, len);
replyMsg->FillI2NPMessageHeader (eI2NPShortTunnelBuildReply, bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET));
if (transitTunnel) replyMsg->onDrop = onDrop;
if (memcmp ((const uint8_t *)i2p::context.GetIdentHash (),
clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, 32)) // reply IBGW is not local?
{
@ -686,21 +640,15 @@ namespace i2p
uint32_t tunnelID = bufbe32toh (clearText + SHORT_REQUEST_RECORD_NEXT_TUNNEL_OFFSET);
auto tunnel = i2p::tunnel::tunnels.GetTunnel (tunnelID);
if (tunnel)
{
tunnel->SendTunnelDataMsg (replyMsg);
tunnel->FlushTunnelDataMsgs ();
}
else
LogPrint (eLogWarning, "I2NP: Tunnel ", tunnelID, " not found for short tunnel build reply");
}
}
else
{
auto msg = CreateI2NPMessage (eI2NPShortTunnelBuild, buf, len,
bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET));
if (transitTunnel) msg->onDrop = onDrop;
transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET, msg);
}
transports.SendMessage (clearText + SHORT_REQUEST_RECORD_NEXT_IDENT_OFFSET,
CreateI2NPMessage (eI2NPShortTunnelBuild, buf, len,
bufbe32toh (clearText + SHORT_REQUEST_RECORD_SEND_MSG_ID_OFFSET)));
return;
}
record += SHORT_TUNNEL_BUILD_RECORD_SIZE;
@ -760,11 +708,7 @@ namespace i2p
return msg;
}
else
{
auto newMsg = CreateTunnelGatewayMsg (tunnelID, msg->GetBuffer (), msg->GetLength ());
if (msg->onDrop) newMsg->onDrop = msg->onDrop;
return newMsg;
}
return CreateTunnelGatewayMsg (tunnelID, msg->GetBuffer (), msg->GetLength ());
}
std::shared_ptr<I2NPMessage> CreateTunnelGatewayMsg (uint32_t tunnelID, I2NPMessageType msgType,
@ -802,38 +746,46 @@ namespace i2p
return l;
}
void HandleTunnelBuildI2NPMessage (std::shared_ptr<I2NPMessage> msg)
void HandleI2NPMessage (uint8_t * msg, size_t len)
{
if (msg)
if (len < I2NP_HEADER_SIZE)
{
uint8_t typeID = msg->GetTypeID();
uint32_t msgID = msg->GetMsgID();
LogPrint (eLogDebug, "I2NP: Handling tunnel build message with len=", msg->GetLength(),", type=", (int)typeID, ", msgID=", (unsigned int)msgID);
uint8_t * payload = msg->GetPayload();
auto size = msg->GetPayloadLength();
switch (typeID)
{
case eI2NPVariableTunnelBuild:
HandleVariableTunnelBuildMsg (msgID, payload, size);
break;
case eI2NPShortTunnelBuild:
HandleShortTunnelBuildMsg (msgID, payload, size);
break;
case eI2NPVariableTunnelBuildReply:
HandleTunnelBuildReplyMsg (msgID, payload, size, false);
break;
case eI2NPShortTunnelBuildReply:
HandleTunnelBuildReplyMsg (msgID, payload, size, true);
break;
case eI2NPTunnelBuild:
HandleTunnelBuildMsg (payload, size);
break;
case eI2NPTunnelBuildReply:
// TODO:
break;
default:
LogPrint (eLogError, "I2NP: Unexpected message with type", (int)typeID, " during handling TBM; skipping");
}
LogPrint (eLogError, "I2NP: Message length ", len, " is smaller than header");
return;
}
uint8_t typeID = msg[I2NP_HEADER_TYPEID_OFFSET];
uint32_t msgID = bufbe32toh (msg + I2NP_HEADER_MSGID_OFFSET);
LogPrint (eLogDebug, "I2NP: Msg received len=", len,", type=", (int)typeID, ", msgID=", (unsigned int)msgID);
uint8_t * buf = msg + I2NP_HEADER_SIZE;
auto size = bufbe16toh (msg + I2NP_HEADER_SIZE_OFFSET);
len -= I2NP_HEADER_SIZE;
if (size > len)
{
LogPrint (eLogError, "I2NP: Payload size ", size, " exceeds buffer length ", len);
size = len;
}
switch (typeID)
{
case eI2NPVariableTunnelBuild:
HandleVariableTunnelBuildMsg (msgID, buf, size);
break;
case eI2NPShortTunnelBuild:
HandleShortTunnelBuildMsg (msgID, buf, size);
break;
case eI2NPVariableTunnelBuildReply:
HandleTunnelBuildReplyMsg (msgID, buf, size, false);
break;
case eI2NPShortTunnelBuildReply:
HandleTunnelBuildReplyMsg (msgID, buf, size, true);
break;
case eI2NPTunnelBuild:
HandleTunnelBuildMsg (buf, size);
break;
case eI2NPTunnelBuildReply:
// TODO:
break;
default:
LogPrint (eLogWarning, "I2NP: Unexpected message ", (int)typeID);
}
}
@ -846,12 +798,10 @@ namespace i2p
switch (typeID)
{
case eI2NPTunnelData:
if (!msg->from)
i2p::tunnel::tunnels.PostTunnelData (msg);
i2p::tunnel::tunnels.PostTunnelData (msg);
break;
case eI2NPTunnelGateway:
if (!msg->from)
i2p::tunnel::tunnels.PostTunnelData (msg);
i2p::tunnel::tunnels.PostTunnelData (msg);
break;
case eI2NPGarlic:
{
@ -862,18 +812,10 @@ namespace i2p
break;
}
case eI2NPDatabaseStore:
// forward to netDb if came directly or through exploratory tunnel as response to our request
if (!msg->from || !msg->from->GetTunnelPool () || msg->from->GetTunnelPool ()->IsExploratory ())
i2p::data::netdb.PostI2NPMsg (msg);
break;
case eI2NPDatabaseSearchReply:
if (!msg->from || !msg->from->GetTunnelPool () || msg->from->GetTunnelPool ()->IsExploratory ())
i2p::data::netdb.PostDatabaseSearchReplyMsg (msg);
break;
case eI2NPDatabaseLookup:
// forward to netDb if floodfill and came directly
if (!msg->from && i2p::context.IsFloodfill ())
i2p::data::netdb.PostI2NPMsg (msg);
// forward to netDb
i2p::data::netdb.PostI2NPMsg (msg);
break;
case eI2NPDeliveryStatus:
{
@ -883,25 +825,17 @@ namespace i2p
i2p::context.ProcessDeliveryStatusMessage (msg);
break;
}
case eI2NPTunnelTest:
if (msg->from && msg->from->GetTunnelPool ())
msg->from->GetTunnelPool ()->ProcessTunnelTest (msg);
break;
case eI2NPVariableTunnelBuild:
case eI2NPTunnelBuild:
case eI2NPShortTunnelBuild:
// forward to tunnel thread
if (!msg->from)
i2p::tunnel::tunnels.PostTunnelData (msg);
break;
case eI2NPVariableTunnelBuildReply:
case eI2NPTunnelBuild:
case eI2NPTunnelBuildReply:
case eI2NPShortTunnelBuild:
case eI2NPShortTunnelBuildReply:
// forward to tunnel thread
i2p::tunnel::tunnels.PostTunnelData (msg);
break;
default:
LogPrint(eLogError, "I2NP: Unexpected I2NP message with type ", int(typeID), " during handling; skipping");
HandleI2NPMessage (msg->GetBuffer (), msg->GetLength ());
}
}
}

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

Loading…
Cancel
Save