Compare commits

..

2 Commits

Author SHA1 Message Date
R4SAS
58e351f5d9 use 15s average bw for transit limits check
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-12-12 18:22:16 +03:00
R4SAS
2a01ad953c calculate bandwidth every 1 and 15 seconds
Signed-off-by: R4SAS <r4sas@i2pmail.org>
2022-12-12 08:12:23 +03:00
158 changed files with 3232 additions and 6669 deletions

View File

@@ -1,36 +0,0 @@
# editorconfig.org
root = true
[*]
# Unix style files
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[Makefile,Makefile.*]
indent_style = tab
indent_size = 4
[*.cmd]
indent_style = space
indent_size = 2
end_of_line = crlf
[*.{h,cpp}]
indent_style = tab
indent_size = 4
[*.rc]
indent_style = space
indent_size = 4
[*.{md,markdown}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = false
[*.yml]
indent_style = space
indent_size = 2

View File

@@ -6,34 +6,27 @@ jobs:
build: build:
name: ${{ matrix.dist }} name: ${{ matrix.dist }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
fail-fast: false
matrix: matrix:
dist: ['buster', 'bullseye', 'bookworm'] dist: ['buster', 'bullseye', 'bookworm']
steps: steps:
- name: Checkout - uses: actions/checkout@v2
uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
- name: change debian changelog
- name: Build package run: |
uses: jtdor/build-deb-action@v1 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: with:
docker-image: debian:${{ matrix.dist }}-slim docker-image: debian:${{ matrix.dist }}-slim
buildpackage-opts: --build=binary --no-sign buildpackage-opts: --build=binary --no-sign
before-build-hook: debchange --controlmaint --local "+${{ github.sha }}~${{ matrix.dist }}" -b --distribution ${{ matrix.dist }} "CI build" - uses: actions/upload-artifact@v3
extra-build-deps: devscripts git
- name: Upload package
uses: actions/upload-artifact@v3
with: with:
name: i2pd_${{ matrix.dist }} name: i2pd_${{ matrix.dist }}
path: debian/artifacts/i2pd_*.deb path: debian/artifacts/i2pd_*.deb
- uses: actions/upload-artifact@v3
- name: Upload debugging symbols
uses: actions/upload-artifact@v3
with: with:
name: i2pd-dbgsym_${{ matrix.dist }} name: i2pd-dbgsym_${{ matrix.dist }}
path: debian/artifacts/i2pd-dbgsym_*.deb path: debian/artifacts/i2pd-dbgsym_*.deb

View File

@@ -6,11 +6,8 @@ jobs:
build: build:
runs-on: macos-12 runs-on: macos-12
name: with UPnP name: with UPnP
steps: steps:
- name: Checkout - uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Test in FreeBSD - name: Test in FreeBSD
id: test id: test
uses: vmactions/freebsd-vm@v0.3.0 uses: vmactions/freebsd-vm@v0.3.0
@@ -24,9 +21,8 @@ jobs:
cd build cd build
cmake -DWITH_UPNP=ON -DCMAKE_BUILD_TYPE=Release . cmake -DWITH_UPNP=ON -DCMAKE_BUILD_TYPE=Release .
gmake -j2 gmake -j2
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v2
with: with:
name: i2pd-freebsd name: i2pd-freebsd
path: build/i2pd path: build/i2pd

View File

@@ -6,21 +6,15 @@ jobs:
build: build:
name: With USE_UPNP=${{ matrix.with_upnp }} name: With USE_UPNP=${{ matrix.with_upnp }}
runs-on: macOS-latest runs-on: macOS-latest
strategy: strategy:
fail-fast: true fail-fast: true
matrix: matrix:
with_upnp: ['yes', 'no'] with_upnp: ['yes', 'no']
steps: steps:
- name: Checkout - uses: actions/checkout@v2
uses: actions/checkout@v3
- name: install packages - name: install packages
run: | run: |
find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete
brew update brew update
brew install boost miniupnpc openssl@1.1 brew install boost miniupnpc openssl@1.1
- name: build application - name: build application
run: make HOMEBREW=1 USE_UPNP=${{ matrix.with_upnp }} PREFIX=$GITHUB_WORKSPACE/output -j3 run: make HOMEBREW=1 USE_UPNP=${{ matrix.with_upnp }} PREFIX=$GITHUB_WORKSPACE/output -j3

View File

@@ -1,52 +0,0 @@
name: Build on Windows with MSVC
on: [push, pull_request]
jobs:
build:
name: Build
runs-on: windows-latest
strategy:
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v3
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
uses: crazy-max/ghaction-chocolatey@v2
with:
args: install boost-msvc-14.3
- name: Install OpenSSL
uses: crazy-max/ghaction-chocolatey@v2
with:
args: install openssl
- name: Configure
working-directory: build
run: cmake -DWITH_STATIC=ON .
- name: Build
working-directory: build
run: cmake --build . --config Debug -- -m
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: i2pd-msvc
path: build/Debug/i2pd.*

View File

@@ -8,106 +8,44 @@ defaults:
jobs: jobs:
build: build:
name: ${{ matrix.arch }} name: Building using ${{ matrix.arch }} toolchain
runs-on: windows-latest runs-on: windows-latest
strategy: strategy:
fail-fast: false fail-fast: true
matrix: matrix:
include: [ include: [
{ msystem: UCRT64, arch: ucrt-x86_64, arch_short: x64-ucrt, compiler: gcc }, { msystem: UCRT64, arch: ucrt-x86_64, arch_short: x64-ucrt },
{ msystem: CLANG64, arch: clang-x86_64, arch_short: x64-clang, compiler: clang }, { msystem: MINGW64, arch: x86_64, arch_short: x64 },
{ msystem: MINGW64, arch: x86_64, arch_short: x64, compiler: gcc }, { msystem: MINGW32, arch: i686, arch_short: x86 }
{ msystem: MINGW32, arch: i686, arch_short: x86, compiler: gcc }
] ]
steps: steps:
- name: Checkout - uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup MSYS2 - name: Setup MSYS2
uses: msys2/setup-msys2@v2 uses: msys2/setup-msys2@v2
with: with:
msystem: ${{ matrix.msystem }} 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 update: true
- name: Install additional clang packages
if: ${{ matrix.msystem == 'CLANG64' }}
run: pacman --noconfirm -S mingw-w64-${{ matrix.arch }}-gcc-compat
- name: Build application - name: Build application
run: | run: |
mkdir -p obj/Win32 obj/libi2pd obj/libi2pd_client obj/daemon mkdir -p obj/Win32 obj/libi2pd obj/libi2pd_client obj/daemon
make USE_UPNP=yes DEBUG=no USE_GIT_VERSION=yes -j3 make USE_UPNP=yes DEBUG=no USE_GIT_VERSION=yes -j3
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v2
with: with:
name: i2pd-${{ matrix.arch_short }}.exe name: i2pd-${{ matrix.arch_short }}.exe
path: i2pd.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@v3
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@v3
with:
name: i2pd-cmake-${{ matrix.arch_short }}.exe
path: build/i2pd.exe
build-xp: build-xp:
name: XP name: Building for Windows XP
runs-on: windows-latest runs-on: windows-latest
strategy:
fail-fast: false
steps: steps:
- name: Checkout - uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup MSYS2 - name: Setup MSYS2
uses: msys2/setup-msys2@v2 uses: msys2/setup-msys2@v2
with: with:
msystem: MINGW32 msystem: MINGW32
install: base-devel git mingw-w64-i686-gcc mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-miniupnpc install: base-devel git mingw-w64-i686-gcc mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-miniupnpc
update: true update: true
- name: Build WinXP-capable CRT packages - name: Build WinXP-capable CRT packages
run: | run: |
git clone https://github.com/msys2/MINGW-packages git clone https://github.com/msys2/MINGW-packages
@@ -126,14 +64,12 @@ jobs:
pacman --noconfirm -U mingw-w64-i686-libwinpthread-git-*-any.pkg.tar.zst mingw-w64-i686-winpthreads-git-*-any.pkg.tar.zst pacman --noconfirm -U mingw-w64-i686-libwinpthread-git-*-any.pkg.tar.zst mingw-w64-i686-winpthreads-git-*-any.pkg.tar.zst
popd popd
popd popd
- name: Build application - name: Build application
run: | run: |
mkdir -p obj/Win32 obj/libi2pd obj/libi2pd_client obj/daemon mkdir -p obj/Win32 obj/libi2pd obj/libi2pd_client obj/daemon
make USE_UPNP=yes DEBUG=no USE_GIT_VERSION=yes USE_WINXP_FLAGS=yes -j3 make USE_UPNP=yes DEBUG=no USE_GIT_VERSION=yes USE_WINXP_FLAGS=yes -j3
- name: Upload artifacts - name: Upload artifacts
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v2
with: with:
name: i2pd-xp.exe name: i2pd-xp.exe
path: i2pd.exe path: i2pd.exe

View File

@@ -5,43 +5,34 @@ on: [push, pull_request]
jobs: jobs:
build-make: build-make:
name: Make with USE_UPNP=${{ matrix.with_upnp }} name: Make with USE_UPNP=${{ matrix.with_upnp }}
runs-on: ubuntu-latest runs-on: ubuntu-18.04
strategy: strategy:
fail-fast: true fail-fast: true
matrix: matrix:
with_upnp: ['yes', 'no'] with_upnp: ['yes', 'no']
steps: steps:
- name: Checkout - uses: actions/checkout@v2
uses: actions/checkout@v3
- name: install packages - name: install packages
run: | run: |
sudo add-apt-repository ppa:mhier/libboost-latest
sudo apt-get update 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 - name: build application
run: make USE_UPNP=${{ matrix.with_upnp }} -j3 run: make USE_UPNP=${{ matrix.with_upnp }} -j3
build-cmake: build-cmake:
name: CMake with -DWITH_UPNP=${{ matrix.with_upnp }} name: CMake with -DWITH_UPNP=${{ matrix.with_upnp }}
runs-on: ubuntu-latest runs-on: ubuntu-18.04
strategy: strategy:
fail-fast: true fail-fast: true
matrix: matrix:
with_upnp: ['ON', 'OFF'] with_upnp: ['ON', 'OFF']
steps: steps:
- name: Checkout - uses: actions/checkout@v2
uses: actions/checkout@v3
- name: install packages - name: install packages
run: | run: |
sudo add-apt-repository ppa:mhier/libboost-latest
sudo apt-get update 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 - name: build application
run: | run: |
cd build cd build

View File

@@ -10,7 +10,6 @@ on:
jobs: jobs:
build: build:
name: Building container for ${{ matrix.platform }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
packages: write packages: write
@@ -27,7 +26,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v2
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2 uses: docker/setup-qemu-action@v2
@@ -58,12 +57,9 @@ jobs:
tags: | tags: |
purplei2p/i2pd:latest-${{ matrix.archname }} purplei2p/i2pd:latest-${{ matrix.archname }}
ghcr.io/purplei2p/i2pd:latest-${{ matrix.archname }} ghcr.io/purplei2p/i2pd:latest-${{ matrix.archname }}
provenance: false
push: push:
name: Pushing merged manifest
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
packages: write packages: write
contents: read contents: read
@@ -72,7 +68,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v2
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2 uses: docker/setup-qemu-action@v2
@@ -94,37 +90,51 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Create and push latest manifest image to Docker Hub - name: Create and push latest manifest image to Docker Hub
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master uses: Noelware/docker-manifest-action@master
with: with:
inputs: purplei2p/i2pd:latest base-image: purplei2p/i2pd:latest
images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 extra-images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7
push: true push: true
- name: Create and push latest manifest image to GHCR - name: Create and push latest manifest image to GHCR
if: ${{ !startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master uses: Noelware/docker-manifest-action@master
with: with:
inputs: ghcr.io/purplei2p/i2pd:latest base-image: 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 extra-images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7
push: true push: true
- name: Store release version to env - name: Store release version to env
if: ${{ startsWith(github.ref, 'refs/tags/') }} if: ${{ startsWith(github.ref, 'refs/tags/') }}
run: echo "RELEASE_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV run: echo "RELEASE_VERSION=${GITHUB_REF:10}" >> $GITHUB_ENV
- name: Create and push release manifest to Docker Hub - name: Create and push release manifest image to Docker Hub
if: ${{ startsWith(github.ref, 'refs/tags/') }} if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master uses: Noelware/docker-manifest-action@master
with: with:
inputs: purplei2p/i2pd:latest,purplei2p/i2pd:latest-release,purplei2p/i2pd:release-${{ env.RELEASE_VERSION }} base-image: purplei2p/i2pd:latest-release
images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7 extra-images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7
push: true push: true
- name: Create and push release manifest to GHCR - name: Create and push release manifest image to GHCR
if: ${{ startsWith(github.ref, 'refs/tags/') }} if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master uses: Noelware/docker-manifest-action@master
with: with:
inputs: ghcr.io/purplei2p/i2pd:latest,ghcr.io/purplei2p/i2pd:latest-release,ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }} base-image: ghcr.io/purplei2p/i2pd:latest-release
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 extra-images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7
push: true
- name: Create and push versioned manifest image to Docker Hub
if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
base-image: purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
extra-images: purplei2p/i2pd:latest-amd64,purplei2p/i2pd:latest-i386,purplei2p/i2pd:latest-arm64,purplei2p/i2pd:latest-armv7
push: true
- name: Create and push versioned manifest image to GHCR
if: ${{ startsWith(github.ref, 'refs/tags/') }}
uses: Noelware/docker-manifest-action@master
with:
base-image: ghcr.io/purplei2p/i2pd:release-${{ env.RELEASE_VERSION }}
extra-images: ghcr.io/purplei2p/i2pd:latest-amd64,ghcr.io/purplei2p/i2pd:latest-i386,ghcr.io/purplei2p/i2pd:latest-arm64,ghcr.io/purplei2p/i2pd:latest-armv7
push: true push: true

View File

@@ -1,103 +1,6 @@
# for this file format description, # for this file format description,
# see https://github.com/olivierlacan/keep-a-changelog # see https://github.com/olivierlacan/keep-a-changelog
## [2.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
- Localization to Swedish, Portuguese, Turkish, Polish
- Periodically send Datetime block in NTCP2 and SSU2
- Don't select random port from reserved
- In memory table for peer profiles
- Store if router was unreachable in it's peer profile
- Show IPv6 addresses in square brackets in webconsole
- Check referer when processing Addresshelper
### Changed
- Algorithm for tunnel creation success rate calculation
- Drop incoming NTCP2 and SSU2 connection if published IP doesn't match actual endpoint
- Exclude actually unreachable router from netdb for 2 hours
- Select first hop from high bandwidth peers for client tunnels
- Drop too long or too short LeaseSet
- Delete router from netdb if became invalid after update
- Terminate existing session if clock skew detected
- Close previous UDP socket if open before reopening
- Minimal version for floodfill is 0.9.51
- Sort transports by endpoints in webconsole
### Fixed
- Deadlock during processing I2NP block with Garlic in ECIES encrypted message to router
- Race condition with encrypted LeaseSets
- HTTP query detection
- Connection attempts to IPs from invalid ranges
- Publish "0.0.0.0" in RouterInfo
- Crash upon receiving PeerTest 7
- Tunnels for closed SAM session socket
- Missing NTCP2 address in RouterInfo if enabled back
## [2.45.1] - 2023-01-11
### Added
- Full Cone NAT status error
### Changed
- Drop duplicated I2NP messages in SSU2
- Set rejection code 30 if tunnel with id already exists
- Network status is always OK if peer test msg 5 received
### Fixed
- UPnP crash if SSU2 or NTCP2 is disabled
- Crash on termination for some platforms
## [2.45.0] - 2023-01-03
### Added
- Test for Symmetric NAT with peer test msgs 6 and 7
- Webconsole "No Descriptors" router error state
- 1 and 15 seconds bandwidth calculation for i2pcontrol
- Show non-zero send queue size for transports in web console
- Compressible padding for I2P addresses
- Localization to Czech
- Don't accept incoming session from invalid/reserved addresses for NTCP2 and SSU2
- Limit simultaneous tunnel build requests by 4 per pool
### Changed
- Removed SSU support
- Reduced bandwidth calculation interval from 60 to 15 seconds
- Increased default max transit tunnels number from 2500 to 5000 or 10000 for floodfill
- Transit tunnels limit is doubled if floodfill mode is enabled
- NTCP2 and SSU2 timestamps are rounded to seconds
- Drop RouterInfos and LeaseSets with timestamp from future
- Don't delete unreachable routers if tunnel creation success rate is too low
- Refuse duplicated incoming pending NTCP2 session from same IP
- Don't send SSU2 termination again if termination received block received
- Handle standard network error for SSU2 without throwing an exception
- Don't select overloaded peer for next tunnel
- Remove "X-Requested-With" in HTTP Proxy for non-AJAX requests
### Fixed
- File descriptors leak
- Random crash on AddressBook update
- Crash if incorrect LeaseSet size
- Spamming to log if no descriptors
- ::1 address in RouterInfo
- SSU2 network error handling (especially for Windows)
- Race condition with pending outgoing SSU2 sessions
- RTT self-reduction for long-live streams
## [2.44.0] - 2022-11-20 ## [2.44.0] - 2022-11-20
### Added ### Added
- SSL connection for server I2P tunnels - SSL connection for server I2P tunnels
@@ -108,7 +11,7 @@
- SSU2 send and verify path challenge - SSU2 send and verify path challenge
- Configurable ssu2.mtu4 and ssu2.mtu6 - Configurable ssu2.mtu4 and ssu2.mtu6
### Changed ### Changed
- SSU2 is enabled and SSU is disabled by default - SSU2 is enbaled and SSU is disabled by default
- Separate network status and error - Separate network status and error
- Random selection between NTCP2 and SSU2 priority - Random selection between NTCP2 and SSU2 priority
- Added notbob.i2p to jump services - Added notbob.i2p to jump services

View File

@@ -47,10 +47,6 @@ else
LD_DEBUG = -s LD_DEBUG = -s
endif endif
ifneq (, $(DESTDIR))
PREFIX = $(DESTDIR)
endif
ifneq (, $(findstring darwin, $(SYS))) ifneq (, $(findstring darwin, $(SYS)))
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
ifeq ($(HOMEBREW),1) ifeq ($(HOMEBREW),1)
@@ -71,15 +67,13 @@ else # not supported
$(error Not supported platform) $(error Not supported platform)
endif 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) ifeq ($(USE_GIT_VERSION),yes)
GIT_VERSION := $(shell git describe --tags) GIT_VERSION := $(shell git describe --tags)
DEFINES += -DGITVER=$(GIT_VERSION) NEEDED_CXXFLAGS += -DGITVER=\"$(GIT_VERSION)\"
endif 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_OBJS += $(patsubst %.cpp,obj/%.o,$(LIB_SRC))
LIB_CLIENT_OBJS += $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC)) LIB_CLIENT_OBJS += $(patsubst %.cpp,obj/%.o,$(LIB_CLIENT_SRC))
LANG_OBJS += $(patsubst %.cpp,obj/%.o,$(LANG_SRC)) LANG_OBJS += $(patsubst %.cpp,obj/%.o,$(LANG_SRC))
@@ -112,17 +106,17 @@ wrapper: api_client $(SHLIB_WRAP) $(ARLIB_WRAP)
## custom FLAGS to work at build-time. ## custom FLAGS to work at build-time.
obj/%.o: %.cpp | mk_obj_dir 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 # '-' is 'ignore if missing' on first run
-include $(DEPS) -include $(DEPS)
$(I2PD): $(DAEMON_OBJS) $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG) $(I2PD): $(DAEMON_OBJS) $(ARLIB) $(ARLIB_CLIENT) $(ARLIB_LANG)
$(CXX) -o $@ $(DEFINES) $(LDFLAGS) $^ $(LDLIBS) $(CXX) -o $@ $(LDFLAGS) $^ $(LDLIBS)
$(SHLIB): $(LIB_OBJS) $(SHLIB): $(LIB_OBJS) $(SHLIB_LANG)
ifneq ($(USE_STATIC),yes) ifneq ($(USE_STATIC),yes)
$(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS) $(CXX) $(LDFLAGS) -shared -o $@ $^ $(LDLIBS) $(SHLIB_LANG)
endif endif
$(SHLIB_CLIENT): $(LIB_CLIENT_OBJS) $(SHLIB) $(SHLIB_LANG) $(SHLIB_CLIENT): $(LIB_CLIENT_OBJS) $(SHLIB) $(SHLIB_LANG)

View File

@@ -6,8 +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 ## (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 ## -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. ## custom FLAGS to work at build-time.
NEEDED_CXXFLAGS = -std=c++11 NEEDED_CXXFLAGS = -std=c++11 -D_GLIBCXX_USE_NANOSLEEP=1
DEFINES = -D_GLIBCXX_USE_NANOSLEEP=1
INCFLAGS = -I/usr/include/ -I/usr/local/include/ INCFLAGS = -I/usr/include/ -I/usr/local/include/
LDFLAGS = ${LD_DEBUG} -Wl,-rpath,/usr/local/lib -L/usr/local/lib 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 LDLIBS = -lcrypto -lssl -lz -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread

View File

@@ -20,11 +20,7 @@ else ifeq ($(shell expr match ${CXXVER} "4\.[8-9]"),3) # gcc 4.8 - 4.9
else ifeq ($(shell expr match ${CXXVER} "[5-6]"),1) # gcc 5 - 6 else ifeq ($(shell expr match ${CXXVER} "[5-6]"),1) # gcc 5 - 6
NEEDED_CXXFLAGS += -std=c++11 NEEDED_CXXFLAGS += -std=c++11
LDLIBS = -latomic LDLIBS = -latomic
else ifeq ($(shell expr match ${CXXVER} "[7-9]"),1) # gcc 7 - 9 else ifeq ($(shell expr match ${CXXVER} "[1,7-9]"),1) # gcc >= 7
NEEDED_CXXFLAGS += -std=c++17
LDLIBS = -latomic
else ifeq ($(shell expr match ${CXXVER} "1[0-9]"),2) # gcc 10+
# NEEDED_CXXFLAGS += -std=c++20
NEEDED_CXXFLAGS += -std=c++17 NEEDED_CXXFLAGS += -std=c++17
LDLIBS = -latomic LDLIBS = -latomic
else # not supported else # not supported
@@ -58,13 +54,12 @@ endif
# UPNP Support (miniupnpc 1.5 and higher) # UPNP Support (miniupnpc 1.5 and higher)
ifeq ($(USE_UPNP),yes) ifeq ($(USE_UPNP),yes)
DEFINES += -DUSE_UPNP NEEDED_CXXFLAGS += -DUSE_UPNP
endif endif
ifeq ($(USE_AESNI),yes) ifeq ($(USE_AESNI),yes)
ifneq (, $(findstring i386, $(SYS))$(findstring i686, $(SYS))$(findstring x86_64, $(SYS))) # only x86-based CPU supports that ifneq (, $(findstring i386, $(SYS))$(findstring i686, $(SYS))$(findstring x86_64, $(SYS))) # only x86-based CPU supports that
NEEDED_CXXFLAGS += -maes NEEDED_CXXFLAGS += -D__AES__ -maes
DEFINES += -D__AES__
endif endif
endif endif

View File

@@ -4,18 +4,17 @@ USE_WIN32_APP := yes
WINDRES = windres WINDRES = windres
CXXFLAGS := $(CXX_DEBUG) -fPIC -msse CXXFLAGS := $(CXX_DEBUG) -fPIC -msse
INCFLAGS := -I$(DAEMON_SRC_DIR) -IWin32 INCFLAGS = -I$(DAEMON_SRC_DIR) -IWin32
LDFLAGS := ${LD_DEBUG} -static LDFLAGS := ${LD_DEBUG} -static
NEEDED_CXXFLAGS += -std=c++17 NEEDED_CXXFLAGS += -std=c++17 -DWIN32_LEAN_AND_MEAN
DEFINES += -DWIN32_LEAN_AND_MEAN
# Boost libraries suffix # Boost libraries suffix
BOOST_SUFFIX = -mt BOOST_SUFFIX = -mt
# UPNP Support # UPNP Support
ifeq ($(USE_UPNP),yes) ifeq ($(USE_UPNP),yes)
DEFINES += -DUSE_UPNP -DMINIUPNP_STATICLIB CXXFLAGS += -DUSE_UPNP -DMINIUPNP_STATICLIB
LDLIBS = -lminiupnpc LDLIBS = -lminiupnpc
endif endif
@@ -36,19 +35,18 @@ LDLIBS += \
-lpthread -lpthread
ifeq ($(USE_WIN32_APP), yes) ifeq ($(USE_WIN32_APP), yes)
DEFINES += -DWIN32_APP NEEDED_CXXFLAGS += -DWIN32_APP
LDFLAGS += -mwindows LDFLAGS += -mwindows
DAEMON_RC += Win32/Resource.rc DAEMON_RC += Win32/Resource.rc
DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC)) DAEMON_OBJS += $(patsubst %.rc,obj/%.o,$(DAEMON_RC))
endif endif
ifeq ($(USE_WINXP_FLAGS), yes) ifeq ($(USE_WINXP_FLAGS), yes)
DEFINES += -DWINVER=0x0501 -D_WIN32_WINNT=0x0501 NEEDED_CXXFLAGS += -DWINVER=0x0501 -D_WIN32_WINNT=0x0501
endif endif
ifeq ($(USE_AESNI),yes) ifeq ($(USE_AESNI),yes)
NEEDED_CXXFLAGS += -maes NEEDED_CXXFLAGS += -D__AES__ -maes
DEFINES += -D__AES__
endif endif
ifeq ($(USE_ASLR),yes) ifeq ($(USE_ASLR),yes)
@@ -56,4 +54,4 @@ ifeq ($(USE_ASLR),yes)
endif endif
obj/%.o : %.rc | mk_obj_dir obj/%.o : %.rc | mk_obj_dir
$(WINDRES) $(DEFINES) $(INCFLAGS) --preprocessor-arg=-MMD --preprocessor-arg=-MP --preprocessor-arg=-MF$@.d -i $< -o $@ $(WINDRES) -i $< -o $@

View File

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

View File

@@ -69,12 +69,12 @@ Build instructions:
**Supported systems:** **Supported systems:**
* GNU/Linux (Debian, Ubuntu, etc) - [![Build on Ubuntu](https://github.com/PurpleI2P/i2pd/actions/workflows/build.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build.yml) * GNU/Linux - [![Build on Ubuntu](https://github.com/PurpleI2P/i2pd/actions/workflows/build.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build.yml)
* CentOS, Fedora, Mageia - [![Build Status](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/status_image/last_build.png)](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/) * CentOS / Fedora / Mageia - [![Build Status](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/status_image/last_build.png)](https://copr.fedorainfracloud.org/coprs/supervillain/i2pd/package/i2pd-git/)
* Alpine, ArchLinux, openSUSE, Gentoo, etc. * Alpine, ArchLinux, openSUSE, Gentoo, Debian, Ubuntu, etc.
* Windows - [![Build on Windows](https://github.com/PurpleI2P/i2pd/actions/workflows/build-windows.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build-windows.yml) * Windows - [![Build on Windows](https://github.com/PurpleI2P/i2pd/actions/workflows/build-windows.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build-windows.yml)
* Mac OS - [![Build on OSX](https://github.com/PurpleI2P/i2pd/actions/workflows/build-osx.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build-osx.yml) * Mac OS X - [![Build on OSX](https://github.com/PurpleI2P/i2pd/actions/workflows/build-osx.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build-osx.yml)
* Docker image - [![Build containers](https://github.com/PurpleI2P/i2pd/actions/workflows/docker.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/docker.yml) * Docker image - [![Build Status](https://img.shields.io/docker/cloud/build/purplei2p/i2pd)](https://hub.docker.com/r/purplei2p/i2pd/builds/) [![Build containers](https://github.com/PurpleI2P/i2pd/actions/workflows/docker.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/docker.yml)
* Snap - [![i2pd](https://snapcraft.io/i2pd/badge.svg)](https://snapcraft.io/i2pd) [![i2pd](https://snapcraft.io/i2pd/trending.svg?name=0)](https://snapcraft.io/i2pd) * Snap - [![i2pd](https://snapcraft.io/i2pd/badge.svg)](https://snapcraft.io/i2pd) [![i2pd](https://snapcraft.io/i2pd/trending.svg?name=0)](https://snapcraft.io/i2pd)
* FreeBSD - [![Build on FreeBSD](https://github.com/PurpleI2P/i2pd/actions/workflows/build-freebsd.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build-freebsd.yml) * FreeBSD - [![Build on FreeBSD](https://github.com/PurpleI2P/i2pd/actions/workflows/build-freebsd.yml/badge.svg)](https://github.com/PurpleI2P/i2pd/actions/workflows/build-freebsd.yml)
* Android - [![Android CI](https://github.com/PurpleI2P/i2pd-android/actions/workflows/android.yml/badge.svg)](https://github.com/PurpleI2P/i2pd-android/actions/workflows/android.yml) * Android - [![Android CI](https://github.com/PurpleI2P/i2pd-android/actions/workflows/android.yml/badge.svg)](https://github.com/PurpleI2P/i2pd-android/actions/workflows/android.yml)

View File

@@ -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 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -29,7 +29,7 @@ namespace util
setlocale(LC_CTYPE, ""); setlocale(LC_CTYPE, "");
SetConsoleCP(1251); SetConsoleCP(1251);
SetConsoleOutputCP(1251); SetConsoleOutputCP(1251);
//setlocale(LC_ALL, "Russian"); setlocale(LC_ALL, "Russian");
setlocale(LC_TIME, "C"); setlocale(LC_TIME, "C");
i2p::log::SetThrowFunction ([](const std::string& s) i2p::log::SetThrowFunction ([](const std::string& s)
@@ -47,7 +47,7 @@ namespace util
I2PService service((PSTR)SERVICE_NAME); I2PService service((PSTR)SERVICE_NAME);
if (!I2PService::Run(service)) 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;
} }
return false; return false;
@@ -61,10 +61,10 @@ namespace util
setlocale(LC_CTYPE, ""); setlocale(LC_CTYPE, "");
SetConsoleCP(1251); SetConsoleCP(1251);
SetConsoleOutputCP(1251); SetConsoleOutputCP(1251);
//setlocale(LC_ALL, "Russian"); setlocale(LC_ALL, "Russian");
setlocale(LC_TIME, "C"); setlocale(LC_TIME, "C");
#ifdef WIN32_APP #ifdef WIN32_APP
if (!i2p::win32::StartWin32App (isDaemon)) return false; if (!i2p::win32::StartWin32App ()) return false;
#endif #endif
bool ret = Daemon_Singleton::start(); bool ret = Daemon_Singleton::start();
if (ret && i2p::log::Logger().GetLogType() == eLogFile) if (ret && i2p::log::Logger().GetLogType() == eLogFile)

View File

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

View File

@@ -45,7 +45,6 @@ namespace i2p
namespace win32 namespace win32
{ {
DWORD g_GracefulShutdownEndtime = 0; DWORD g_GracefulShutdownEndtime = 0;
bool g_isWinService;
static void ShowPopupMenu (HWND hWnd, POINT *curpos, int wDefaultItem) static void ShowPopupMenu (HWND hWnd, POINT *curpos, int wDefaultItem)
{ {
@@ -417,9 +416,8 @@ namespace win32
return DefWindowProc( hWnd, uMsg, wParam, lParam); return DefWindowProc( hWnd, uMsg, wParam, lParam);
} }
bool StartWin32App (bool isWinService) bool StartWin32App ()
{ {
g_isWinService = isWinService;
if (FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"))) if (FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd")))
{ {
MessageBox(NULL, TEXT("I2Pd is running already"), TEXT("Warning"), MB_OK); MessageBox(NULL, TEXT("I2Pd is running already"), TEXT("Warning"), MB_OK);
@@ -448,8 +446,6 @@ namespace win32
MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST); MessageBox(NULL, "Failed to create main window", TEXT("Warning!"), MB_ICONERROR | MB_OK | MB_TOPMOST);
return false; return false;
} }
// COM requires message loop to work, which is not implemented in service mode
if (!g_isWinService)
SubscribeToEvents(); SubscribeToEvents();
return true; return true;
} }
@@ -470,8 +466,7 @@ namespace win32
HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd")); HWND hWnd = FindWindow (I2PD_WIN32_CLASSNAME, TEXT("i2pd"));
if (hWnd) if (hWnd)
PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_EXIT, 0), 0); PostMessage (hWnd, WM_COMMAND, MAKEWPARAM(ID_EXIT, 0), 0);
else if(!g_isWinService) // UnSubscribeFromEvents(); // TODO: understand why unsubscribing crashes app
UnSubscribeFromEvents();
UnregisterClass (I2PD_WIN32_CLASSNAME, GetModuleHandle(NULL)); UnregisterClass (I2PD_WIN32_CLASSNAME, GetModuleHandle(NULL));
} }

View File

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

View File

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

View File

@@ -19,18 +19,21 @@ class CNetworkListManagerEvent : public INetworkListManagerEvents
{ {
public: public:
CNetworkListManagerEvent() : m_ref(1) { } CNetworkListManagerEvent() : m_ref(1) { }
~CNetworkListManagerEvent() { }
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject)
{ {
HRESULT Result = S_OK;
if (IsEqualIID(riid, IID_IUnknown)) { if (IsEqualIID(riid, IID_IUnknown)) {
*ppvObject = (IUnknown *)this; *ppvObject = (IUnknown *)this;
} else if (IsEqualIID(riid ,IID_INetworkListManagerEvents)) { } else if (IsEqualIID(riid ,IID_INetworkListManagerEvents)) {
*ppvObject = (INetworkListManagerEvents *)this; *ppvObject = (INetworkListManagerEvents *)this;
} else { } else {
return E_NOINTERFACE; Result = E_NOINTERFACE;
} }
AddRef(); AddRef();
return S_OK;
return Result;
} }
ULONG STDMETHODCALLTYPE AddRef() ULONG STDMETHODCALLTYPE AddRef()

View File

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

14
build/.gitignore vendored
View File

@@ -1,13 +1,6 @@
# Various generated files # Various generated files
/CMakeFiles/ /CMakeFiles/
/Testing/
/tests/
/.ninja_*
/arch.c
/build.ninja
/i2pd /i2pd
/i2pd.exe
/i2pd.exe.debug
/libi2pd.a /libi2pd.a
/libi2pdclient.a /libi2pdclient.a
/libi2pdlang.a /libi2pdlang.a
@@ -15,13 +8,8 @@
/CMakeCache.txt /CMakeCache.txt
/CPackConfig.cmake /CPackConfig.cmake
/CPackSourceConfig.cmake /CPackSourceConfig.cmake
/CTestTestfile.cmake
/install_manifest.txt /install_manifest.txt
/Makefile /arch.c
# windows build script # windows build script
i2pd*.zip i2pd*.zip
build*.log build*.log
# MVS project files
*.vcxproj
*.vcxproj.filters
*.sln

View File

@@ -1,32 +1,14 @@
cmake_minimum_required(VERSION 3.7) cmake_minimum_required(VERSION 3.7)
cmake_policy(VERSION 3.7)
if(${CMAKE_VERSION} VERSION_LESS 3.22) project("i2pd")
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
else()
cmake_policy(VERSION 3.22)
endif()
# for debugging # for debugging
#set(CMAKE_VERBOSE_MAKEFILE on) #set(CMAKE_VERBOSE_MAKEFILE on)
# paths # Win32 build with cmake is not supported
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules") if(WIN32 OR MSVC OR MSYS OR MINGW)
set(CMAKE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..") message(SEND_ERROR "cmake build for windows is not supported. Please use MSYS2 with makefiles in project root.")
endif()
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 CXX
)
# configurable options # configurable options
option(WITH_AESNI "Use AES-NI instructions set" ON) option(WITH_AESNI "Use AES-NI instructions set" ON)
@@ -38,28 +20,28 @@ option(WITH_UPNP "Include support for UPnP client" OFF)
option(WITH_GIT_VERSION "Use git commit info as version" OFF) option(WITH_GIT_VERSION "Use git commit info as version" OFF)
option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF) option(WITH_ADDRSANITIZER "Build with address sanitizer unix only" OFF)
option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF) option(WITH_THREADSANITIZER "Build with thread sanitizer unix only" OFF)
option(BUILD_TESTING "Build tests" OFF)
IF(BUILD_TESTING) # paths
enable_testing() set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules")
ENDIF() set(CMAKE_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..")
#Handle paths nicely #Handle paths nicely
include(GNUInstallDirs) include(GNUInstallDirs)
# Architecture # architecture
include(TargetArch) include(TargetArch)
target_architecture(ARCHITECTURE) target_architecture(ARCHITECTURE)
include(CheckAtomic) set(LIBI2PD_SRC_DIR ../libi2pd)
set(LIBI2PD_CLIENT_SRC_DIR ../libi2pd_client)
if(WITH_STATIC) set(LANG_SRC_DIR ../i18n)
if(MSVC) set(DAEMON_SRC_DIR ../daemon)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()
endif()
include_directories(${LIBI2PD_SRC_DIR}) 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) FILE(GLOB LIBI2PD_SRC ${LIBI2PD_SRC_DIR}/*.cpp)
add_library(libi2pd ${LIBI2PD_SRC}) add_library(libi2pd ${LIBI2PD_SRC})
set_target_properties(libi2pd PROPERTIES PREFIX "") set_target_properties(libi2pd PROPERTIES PREFIX "")
@@ -70,9 +52,11 @@ if(WITH_LIBRARY)
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT Libraries) 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() endif()
include_directories(${LIBI2PD_CLIENT_SRC_DIR})
FILE(GLOB CLIENT_SRC ${LIBI2PD_CLIENT_SRC_DIR}/*.cpp) FILE(GLOB CLIENT_SRC ${LIBI2PD_CLIENT_SRC_DIR}/*.cpp)
add_library(libi2pdclient ${CLIENT_SRC}) add_library(libi2pdclient ${CLIENT_SRC})
set_target_properties(libi2pdclient PROPERTIES PREFIX "") set_target_properties(libi2pdclient PROPERTIES PREFIX "")
@@ -85,7 +69,6 @@ if(WITH_LIBRARY)
COMPONENT Libraries) COMPONENT Libraries)
endif() endif()
include_directories(${LANG_SRC_DIR})
FILE(GLOB LANG_SRC ${LANG_SRC_DIR}/*.cpp) FILE(GLOB LANG_SRC ${LANG_SRC_DIR}/*.cpp)
add_library(libi2pdlang ${LANG_SRC}) add_library(libi2pdlang ${LANG_SRC})
set_target_properties(libi2pdlang PROPERTIES PREFIX "") set_target_properties(libi2pdlang PROPERTIES PREFIX "")
@@ -98,8 +81,6 @@ if(WITH_LIBRARY)
COMPONENT Libraries) COMPONENT Libraries)
endif() endif()
include_directories(${DAEMON_SRC_DIR})
set(DAEMON_SRC set(DAEMON_SRC
"${DAEMON_SRC_DIR}/Daemon.cpp" "${DAEMON_SRC_DIR}/Daemon.cpp"
"${DAEMON_SRC_DIR}/HTTPServer.cpp" "${DAEMON_SRC_DIR}/HTTPServer.cpp"
@@ -109,22 +90,6 @@ set(DAEMON_SRC
"${DAEMON_SRC_DIR}/UPnP.cpp" "${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")
endif()
if(WITH_UPNP) if(WITH_UPNP)
add_definitions(-DUSE_UPNP) add_definitions(-DUSE_UPNP)
endif() endif()
@@ -132,33 +97,24 @@ endif()
if(WITH_GIT_VERSION) if(WITH_GIT_VERSION)
include(GetGitRevisionDescription) include(GetGitRevisionDescription)
git_describe(GIT_VERSION) git_describe(GIT_VERSION)
add_definitions(-DGITVER=${GIT_VERSION}) add_definitions(-DGITVER="${GIT_VERSION}")
endif() endif()
if(APPLE) if(APPLE)
add_definitions(-DMAC_OSX) add_definitions(-DMAC_OSX)
endif() endif()
if(MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Winvalid-pch -Wno-unused-parameter")
add_definitions(-DWINVER=0x0600)
add_definitions(-D_WIN32_WINNT=0x0600)
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") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -pedantic")
# TODO: The following is incompatible with static build and enabled hardening for OpenWRT. # TODO: The following is incompatible with static build and enabled hardening for OpenWRT.
# Multiple definitions of __stack_chk_fail(libssp & libc) # 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 -ffunction-sections -fdata-sections")
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 set(CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "-Wl,--gc-sections") # -flto is added from above
# check for c++17 & c++11 support # check for c++17 & c++11 support
include(CheckCXXCompilerFlag) include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++17" CXX17_SUPPORTED) CHECK_CXX_COMPILER_FLAG("-std=c++17" CXX17_SUPPORTED)
CHECK_CXX_COMPILER_FLAG("-std=c++11" CXX11_SUPPORTED) CHECK_CXX_COMPILER_FLAG("-std=c++11" CXX11_SUPPORTED)
if(CXX17_SUPPORTED) if(CXX17_SUPPORTED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17")
elseif(CXX11_SUPPORTED) elseif(CXX11_SUPPORTED)
@@ -166,7 +122,6 @@ else()
else() else()
message(SEND_ERROR "C++17 nor C++11 standard not seems to be supported by compiler. Too old version?") message(SEND_ERROR "C++17 nor C++11 standard not seems to be supported by compiler. Too old version?")
endif() endif()
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe")
@@ -197,12 +152,6 @@ endif()
# Note: AES-NI and AVX is available on x86-based CPU's. # Note: AES-NI and AVX is available on x86-based CPU's.
# Here also ARM64 implementation, but currently we don't support it. # Here also ARM64 implementation, but currently we don't support it.
# MSVC is not supported.
if(MSVC)
message(STATUS "AES-NI is not supported on MSVC, option was disabled")
set(WITH_AESNI OFF)
endif()
if(WITH_AESNI AND (ARCHITECTURE MATCHES "x86_64" OR ARCHITECTURE MATCHES "i386")) if(WITH_AESNI AND (ARCHITECTURE MATCHES "x86_64" OR ARCHITECTURE MATCHES "i386"))
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes")
add_definitions(-D__AES__) add_definitions(-D__AES__)
@@ -222,48 +171,23 @@ if(WITH_THREADSANITIZER)
endif() endif()
endif() endif()
# Use std::atomic instead of GCC builtins on macOS PowerPC:
# For more information refer to: https://github.com/PurpleI2P/i2pd/issues/1726#issuecomment-1306335111 # Enable usage of STD's Atomic instead of Boost's on PowerPC
# This has been fixed in Boost 1.81, nevertheless we retain the setting for the sake of compatibility. # For more information refer to https://github.com/PurpleI2P/i2pd/issues/1726#issuecomment-1306335111
if(APPLE AND CMAKE_OSX_ARCHITECTURES MATCHES "ppc") if(ARCHITECTURE MATCHES "ppc")
add_definitions(-DBOOST_SP_USE_STD_ATOMIC) add_definitions(-DBOOST_SP_USE_STD_ATOMIC)
endif() endif()
# libraries # libraries
set(THREADS_PREFER_PTHREAD_FLAG ON) set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
if(WITH_STATIC) if(WITH_STATIC)
if(NOT MSVC)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
endif()
set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_LIBS ON)
if(MSVC)
set(Boost_USE_STATIC_RUNTIME ON) set(Boost_USE_STATIC_RUNTIME ON)
else()
set(Boost_USE_STATIC_RUNTIME OFF)
endif()
if(MSVC)
set(OPENSSL_MSVC_STATIC_RT ON)
endif()
set(OPENSSL_USE_STATIC_LIBS 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) set(BUILD_SHARED_LIBS OFF)
if(${CMAKE_CXX_COMPILER} MATCHES ".*-openwrt-.*") if(${CMAKE_CXX_COMPILER} MATCHES ".*-openwrt-.*")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
# set(CMAKE_THREAD_LIBS_INIT "gcc_eh -Wl,--whole-archive -lpthread -Wl,--no-whole-archive") # set(CMAKE_THREAD_LIBS_INIT "gcc_eh -Wl,--whole-archive -lpthread -Wl,--no-whole-archive")
@@ -273,23 +197,17 @@ else()
# TODO: Consider separate compilation for LIBI2PD_SRC for library. # TODO: Consider separate compilation for LIBI2PD_SRC for library.
# No need in -fPIC overhead for binary if not interested in library # No need in -fPIC overhead for binary if not interested in library
# HINT: revert c266cff CMakeLists.txt: compilation speed up # HINT: revert c266cff CMakeLists.txt: compilation speed up
if(NOT MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
endif() add_definitions(-DBOOST_SYSTEM_DYN_LINK -DBOOST_FILESYSTEM_DYN_LINK -DBOOST_PROGRAM_OPTIONS_DYN_LINK -DBOOST_DATE_TIME_DYN_LINK -DBOOST_REGEX_DYN_LINK)
add_definitions(-DBOOST_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()
endif() endif()
find_package(Boost REQUIRED COMPONENTS system filesystem program_options date_time OPTIONAL_COMPONENTS atomic) find_package(Boost COMPONENTS system filesystem program_options date_time REQUIRED)
if(NOT DEFINED Boost_FOUND) if(NOT DEFINED Boost_INCLUDE_DIRS)
message(SEND_ERROR "Boost is not found, or your boost version was below 1.46. Please download Boost!") message(SEND_ERROR "Boost is not found, or your boost version was below 1.46. Please download Boost!")
endif() endif()
find_package(OpenSSL REQUIRED) 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!") message(SEND_ERROR "Could not find OpenSSL. Please download and install it first!")
endif() endif()
@@ -314,6 +232,8 @@ endif()
# load includes # load includes
include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR}) include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR})
include(CheckAtomic)
# show summary # show summary
message(STATUS "---------------------------------------") message(STATUS "---------------------------------------")
message(STATUS "Build type : ${CMAKE_BUILD_TYPE}") message(STATUS "Build type : ${CMAKE_BUILD_TYPE}")
@@ -335,25 +255,11 @@ message(STATUS " THREADSANITIZER : ${WITH_THREADSANITIZER}")
message(STATUS "---------------------------------------") message(STATUS "---------------------------------------")
if(WITH_BINARY) if(WITH_BINARY)
if(WIN32)
add_executable("${PROJECT_NAME}" WIN32 ${DAEMON_SRC} ${WIN32_RC})
else()
add_executable("${PROJECT_NAME}" ${DAEMON_SRC}) 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()
if(WITH_STATIC) if(WITH_STATIC)
if(NOT MSVC)
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-static") set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-static")
endif() endif()
endif()
if(WITH_HARDENING AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") if(WITH_HARDENING AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-z relro -z now") set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-z relro -z now")
@@ -365,24 +271,13 @@ if(WITH_BINARY)
list(REMOVE_AT Boost_LIBRARIES -1) list(REMOVE_AT Boost_LIBRARIES -1)
endif() 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) if(WITH_STATIC)
set(DL_LIB ${CMAKE_DL_LIBS}) set(DL_LIB ${CMAKE_DL_LIBS})
endif() 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 ${DL_LIB} ${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) install(TARGETS "${PROJECT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Runtime)
set(APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}") set(APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
set(DIRS "${Boost_LIBRARY_DIR};${OPENSSL_INCLUDE_DIR}/../bin;${ZLIB_INCLUDE_DIR}/../bin;/mingw32/bin") set(DIRS "${Boost_LIBRARY_DIR};${OPENSSL_INCLUDE_DIR}/../bin;${ZLIB_INCLUDE_DIR}/../bin;/mingw32/bin")
endif() endif()
if(BUILD_TESTING)
add_subdirectory(${CMAKE_SOURCE_DIR}/tests ${CMAKE_CURRENT_BINARY_DIR}/tests)
endif()

View File

@@ -1,23 +1,18 @@
# atomic builtins are required for threading support. # atomic builtins are required for threading support.
INCLUDE(CheckCXXSourceCompiles) INCLUDE(CheckCXXSourceCompiles)
INCLUDE(CheckLibraryExists)
# Sometimes linking against libatomic is required for atomic ops, if # Sometimes linking against libatomic is required for atomic ops, if
# the platform doesn't support lock-free atomics. # the platform doesn't support lock-free atomics.
function(check_working_cxx_atomics varname) function(check_working_cxx_atomics varname)
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -std=c++11") set(CMAKE_REQUIRED_FLAGS "-std=c++11")
CHECK_CXX_SOURCE_COMPILES(" CHECK_CXX_SOURCE_COMPILES("
#include <atomic> #include <atomic>
std::atomic<int> x; std::atomic<int> x;
std::atomic<short> y;
std::atomic<char> z;
int main() { int main() {
++z; return x;
++y;
return ++x;
} }
" ${varname}) " ${varname})
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS}) set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
@@ -32,7 +27,6 @@ function(check_working_cxx_atomics64 varname)
std::atomic<uint64_t> x (0); std::atomic<uint64_t> x (0);
int main() { int main() {
uint64_t i = x.load(std::memory_order_relaxed); uint64_t i = x.load(std::memory_order_relaxed);
(void)i;
return 0; return 0;
} }
" ${varname}) " ${varname})
@@ -40,10 +34,9 @@ int main() {
endfunction(check_working_cxx_atomics64) endfunction(check_working_cxx_atomics64)
# Check for (non-64-bit) atomic operations. # This isn't necessary on MSVC, so avoid command-line switch annoyance
if(MSVC) # by only running on GCC-like hosts.
set(HAVE_CXX_ATOMICS_WITHOUT_LIB True) if (LLVM_COMPILER_IS_GCC_COMPATIBLE)
else()
# First check if atomics work without the library. # First check if atomics work without the library.
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB) check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB)
# If not, check if the library exists, and atomics work with it. # If not, check if the library exists, and atomics work with it.
@@ -65,8 +58,9 @@ endif()
if(MSVC) if(MSVC)
set(HAVE_CXX_ATOMICS64_WITHOUT_LIB True) set(HAVE_CXX_ATOMICS64_WITHOUT_LIB True)
else() else()
# First check if atomics work without the library.
check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB) check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITHOUT_LIB)
endif()
# If not, check if the library exists, and atomics work with it. # If not, check if the library exists, and atomics work with it.
if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB) if(NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB)
check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64) check_library_exists(atomic __atomic_load_8 "" HAVE_CXX_LIBATOMICS64)
@@ -74,11 +68,10 @@ else()
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB) check_working_cxx_atomics64(HAVE_CXX_ATOMICS64_WITH_LIB)
if (NOT HAVE_CXX_ATOMICS64_WITH_LIB) if (NOT HAVE_CXX_ATOMICS64_WITH_LIB)
message(FATAL_ERROR "Host compiler must support 64-bit std::atomic!") message(FATAL_ERROR "Host compiler must support std::atomic!")
endif() endif()
else() else()
message(FATAL_ERROR "Host compiler appears to require libatomic for 64-bit operations, but cannot find it.") message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.")
endif()
endif() endif()
endif() endif()
@@ -87,6 +80,7 @@ endif()
## assumes C++11 <atomic> works. ## assumes C++11 <atomic> works.
CHECK_CXX_SOURCE_COMPILES(" CHECK_CXX_SOURCE_COMPILES("
#ifdef _MSC_VER #ifdef _MSC_VER
#include <Intrin.h> /* Workaround for PR19898. */
#include <windows.h> #include <windows.h>
#endif #endif
int main() { int main() {

View File

@@ -1,55 +0,0 @@
# - Try to find the CHECK libraries
# Once done this will define
#
# CHECK_FOUND - system has check
# CHECK_INCLUDE_DIRS - the check include directory
# CHECK_LIBRARIES - check library
#
# Copyright (c) 2007 Daniel Gollub <gollub@b1-systems.de>
# Copyright (c) 2007-2009 Bjoern Ricks <bjoern.ricks@gmail.com>
#
# Redistribution and use is allowed according to the terms of the New
# BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
INCLUDE( FindPkgConfig )
IF ( Check_FIND_REQUIRED )
SET( _pkgconfig_REQUIRED "REQUIRED" )
ELSE( Check_FIND_REQUIRED )
SET( _pkgconfig_REQUIRED "" )
ENDIF ( Check_FIND_REQUIRED )
IF ( CHECK_MIN_VERSION )
PKG_SEARCH_MODULE( CHECK ${_pkgconfig_REQUIRED} check>=${CHECK_MIN_VERSION} )
ELSE ( CHECK_MIN_VERSION )
PKG_SEARCH_MODULE( CHECK ${_pkgconfig_REQUIRED} check )
ENDIF ( CHECK_MIN_VERSION )
# Look for CHECK include dir and libraries
IF( NOT CHECK_FOUND AND NOT PKG_CONFIG_FOUND )
FIND_PATH( CHECK_INCLUDE_DIRS check.h )
FIND_LIBRARY( CHECK_LIBRARIES NAMES check )
IF ( CHECK_INCLUDE_DIRS AND CHECK_LIBRARIES )
SET( CHECK_FOUND 1 )
IF ( NOT Check_FIND_QUIETLY )
MESSAGE ( STATUS "Found CHECK: ${CHECK_LIBRARIES}" )
ENDIF ( NOT Check_FIND_QUIETLY )
ELSE ( CHECK_INCLUDE_DIRS AND CHECK_LIBRARIES )
IF ( Check_FIND_REQUIRED )
MESSAGE( FATAL_ERROR "Could NOT find CHECK" )
ELSE ( Check_FIND_REQUIRED )
IF ( NOT Check_FIND_QUIETLY )
MESSAGE( STATUS "Could NOT find CHECK" )
ENDIF ( NOT Check_FIND_QUIETLY )
ENDIF ( Check_FIND_REQUIRED )
ENDIF ( CHECK_INCLUDE_DIRS AND CHECK_LIBRARIES )
ENDIF( NOT CHECK_FOUND AND NOT PKG_CONFIG_FOUND )
# Hide advanced variables from CMake GUIs
MARK_AS_ADVANCED( CHECK_INCLUDE_DIRS CHECK_LIBRARIES )

View File

@@ -1,4 +1,4 @@
# Copyright (c) 2017-2023, The PurpleI2P Project # Copyright (c) 2017-2022, The PurpleI2P Project
# This file is part of Purple i2pd project and licensed under BSD3 # This file is part of Purple i2pd project and licensed under BSD3
# See full license text in LICENSE file at top of project tree # See full license text in LICENSE file at top of project tree
@@ -18,7 +18,7 @@ set(archdetect_c_code "
|| defined(_M_ARM64) \\ || defined(_M_ARM64) \\
|| (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 8) || (defined(__TARGET_ARCH_ARM) && __TARGET_ARCH_ARM-0 >= 8)
#error cmake_ARCH arm64 #error cmake_ARCH arm64
#elif defined(__ARM_ARCH_7__) \\ #if defined(__ARM_ARCH_7__) \\
|| defined(__ARM_ARCH_7A__) \\ || defined(__ARM_ARCH_7A__) \\
|| defined(__ARM_ARCH_7R__) \\ || defined(__ARM_ARCH_7R__) \\
|| defined(__ARM_ARCH_7M__) \\ || defined(__ARM_ARCH_7M__) \\
@@ -83,13 +83,13 @@ function(target_architecture output_var)
# First let's normalize the order of the values # First let's normalize the order of the values
# Note that it's not possible to compile PowerPC applications if you are using # Note that it's not possible to compile PowerPC applications if you are using
# the OS X SDK version 10.7 or later - you'll need 10.4/10.5/10.6 for that, so we # the OS X SDK version 10.6 or later - you'll need 10.4/10.5 for that, so we
# disable it by default. Also, ppc64 is not supported in 10.6. # disable it by default
# See this page for more information: # See this page for more information:
# http://stackoverflow.com/questions/5333490/how-can-we-restore-ppc-ppc64-as-well-as-full-10-4-10-5-sdk-support-to-xcode-4 # http://stackoverflow.com/questions/5333490/how-can-we-restore-ppc-ppc64-as-well-as-full-10-4-10-5-sdk-support-to-xcode-4
# Architecture defaults to i386 or ppc on OS X 10.5 and earlier, depending on the CPU type detected at runtime. # Architecture defaults to i386 or ppc on OS X 10.5 and earlier, depending on the CPU type detected at runtime.
# On OS X 10.6+ the default is x86_64 if the CPU supports it, i386 otherwise; 10.6 also supports ppc. # On OS X 10.6+ the default is x86_64 if the CPU supports it, i386 otherwise.
foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES}) foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES})
if("${osx_arch}" STREQUAL "ppc" AND ppc_support) if("${osx_arch}" STREQUAL "ppc" AND ppc_support)
@@ -133,11 +133,11 @@ function(target_architecture output_var)
enable_language(C) enable_language(C)
# Detect the architecture in a rather creative way... # Detect the architecture in a rather creative way...
# This compiles a small C program which is a series of ifdefs that selects # This compiles a small C program which is a series of ifdefs that selects a
# a particular #error preprocessor directive whose message string contains # particular #error preprocessor directive whose message string contains the
# the target architecture. The program will always fail to compile (both because # target architecture. The program will always fail to compile (both because
# file is not a valid C program, and obviously because of the presence of # file is not a valid C program, and obviously because of the presence of the
# the #error preprocessor directives... but by exploiting the preprocessor in this # #error preprocessor directives... but by exploiting the preprocessor in this
# way, we can detect the correct target architecture even when cross-compiling, # way, we can detect the correct target architecture even when cross-compiling,
# since the program itself never needs to be run (only the compiler/preprocessor) # since the program itself never needs to be run (only the compiler/preprocessor)
try_run( try_run(

View File

@@ -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()

View File

@@ -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-----

View File

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

View File

@@ -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

View File

@@ -60,8 +60,8 @@ RUN apk update \
RUN apk --no-cache add boost-filesystem boost-system boost-program_options boost-date_time boost-thread boost-iostreams openssl miniupnpc musl-utils libstdc++ RUN apk --no-cache add boost-filesystem boost-system boost-program_options boost-date_time boost-thread boost-iostreams openssl miniupnpc musl-utils libstdc++
# 3. Copy preconfigured config file and entrypoint # 3. Copy preconfigured config file and entrypoint
COPY i2pd-docker.conf "$DATA_DIR/i2pd.conf" COPY i2pd-docker.conf "$I2PD_HOME/i2pd.conf"
RUN chown i2pd:nobody "$DATA_DIR/i2pd.conf" RUN chown i2pd:nobody "$I2PD_HOME/i2pd.conf"
COPY entrypoint.sh /entrypoint.sh COPY entrypoint.sh /entrypoint.sh
RUN chmod a+x /entrypoint.sh RUN chmod a+x /entrypoint.sh

File diff suppressed because it is too large Load Diff

View File

@@ -19,7 +19,7 @@ out: {"$1", "$2"},\n
``` ```
``` ```
in: ^#[:.,](.*)$\n in: ^#[:.](.*)$\n
out: <to empty line> out: <to empty line>
``` ```

View File

@@ -33,7 +33,7 @@
# log = file # log = file
## Path to logfile (default - autodetect) ## Path to logfile (default - autodetect)
# logfile = /var/log/i2pd/i2pd.log # 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 ## If you set it to none, logging will be disabled
# loglevel = warn # loglevel = warn
## Write full CLF-formatted date and time to log (default: write only time) ## Write full CLF-formatted date and time to log (default: write only time)
@@ -122,15 +122,12 @@ port = 7070
## Path to web console, default "/" ## Path to web console, default "/"
# webroot = / # webroot = /
## Uncomment following lines to enable Web Console authentication ## 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 # auth = true
# user = i2pd # user = i2pd
# pass = changeme # pass = changeme
## Select webconsole language ## Select webconsole language
## Currently supported english (default), afrikaans, armenian, chinese, czech, french, ## Currently supported english (default), afrikaans, armenian, chinese, french,
## german, italian, polish, portuguese, russian, spanish, turkish, turkmen, ukrainian ## german, italian, russian, spanish, turkmen, ukrainian and uzbek languages
## and uzbek languages
# lang = english # lang = english
[httpproxy] [httpproxy]
@@ -142,8 +139,6 @@ port = 4444
## Optional keys file for proxy local destination ## Optional keys file for proxy local destination
# keys = http-proxy-keys.dat # keys = http-proxy-keys.dat
## Enable address helper for adding .i2p domains with "jump URLs" (default: true) ## Enable address helper for adding .i2p domains with "jump URLs" (default: true)
## You should disable this feature if your i2pd HTTP Proxy is public,
## because anyone could spoof the short domain via addresshelper and forward other users to phishing links
# addresshelper = true # addresshelper = true
## Address of a proxy server inside I2P, which is used to visit regular Internet ## Address of a proxy server inside I2P, which is used to visit regular Internet
# outproxy = http://false.i2p # outproxy = http://false.i2p
@@ -168,10 +163,9 @@ port = 4447
[sam] [sam]
## Comment or set to 'false' to disable SAM Bridge ## Comment or set to 'false' to disable SAM Bridge
enabled = true enabled = true
## Address and ports service will listen on ## Address and port service will listen on
# address = 127.0.0.1 # address = 127.0.0.1
# port = 7656 # port = 7656
# portudp = 7655
[bob] [bob]
## Uncomment and set to 'true' to enable BOB command channel ## Uncomment and set to 'true' to enable BOB command channel
@@ -243,9 +237,8 @@ verify = true
# subscriptions = http://reg.i2p/hosts.txt,http://identiguy.i2p/hosts.txt,http://stats.i2p/cgi-bin/newhosts.txt,http://rus.i2p/hosts.txt # subscriptions = http://reg.i2p/hosts.txt,http://identiguy.i2p/hosts.txt,http://stats.i2p/cgi-bin/newhosts.txt,http://rus.i2p/hosts.txt
[limits] [limits]
## Maximum active transit sessions (default: 5000) ## Maximum active transit sessions (default:2500)
## This value is doubled if floodfill mode is enabled! # transittunnels = 2500
# transittunnels = 5000
## Limit number of open file descriptors (0 - use system limit) ## Limit number of open file descriptors (0 - use system limit)
# openfiles = 0 # openfiles = 0
## Maximum size of corefile in Kb (0 - use system limit) ## Maximum size of corefile in Kb (0 - use system limit)

View File

@@ -29,7 +29,7 @@ SendSIGKILL=yes
#TimeoutStopSec=10m #TimeoutStopSec=10m
# If you have problems with hanging i2pd, you can try increase this # If you have problems with hanging i2pd, you can try increase this
LimitNOFILE=8192 LimitNOFILE=4096
# To enable write of coredump uncomment this # To enable write of coredump uncomment this
#LimitCORE=infinity #LimitCORE=infinity

View File

@@ -1,7 +1,7 @@
%define git_hash %(git rev-parse HEAD | cut -c -7) %define git_hash %(git rev-parse HEAD | cut -c -7)
Name: i2pd-git Name: i2pd-git
Version: 2.47.0 Version: 2.44.0
Release: git%{git_hash}%{?dist} Release: git%{git_hash}%{?dist}
Summary: I2P router written in C++ Summary: I2P router written in C++
Conflicts: i2pd Conflicts: i2pd
@@ -158,21 +158,6 @@ getent passwd i2pd >/dev/null || \
%changelog %changelog
* 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
* Wed Jan 11 2023 orignal <orignal@i2pmail.org> - 2.45.1
- update to 2.45.1
* Tue Jan 3 2023 orignal <orignal@i2pmail.org> - 2.45.0
- update to 2.45.0
* Sun Nov 20 2022 orignal <orignal@i2pmail.org> - 2.44.0 * Sun Nov 20 2022 orignal <orignal@i2pmail.org> - 2.44.0
- update to 2.44.0 - update to 2.44.0

View File

@@ -1,5 +1,5 @@
Name: i2pd Name: i2pd
Version: 2.47.0 Version: 2.44.0
Release: 1%{?dist} Release: 1%{?dist}
Summary: I2P router written in C++ Summary: I2P router written in C++
Conflicts: i2pd-git Conflicts: i2pd-git
@@ -155,21 +155,6 @@ getent passwd i2pd >/dev/null || \
%changelog %changelog
* 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
* Wed Jan 11 2023 orignal <orignal@i2pmail.org> - 2.45.1
- update to 2.45.1
* Tue Jan 3 2023 orignal <orignal@i2pmail.org> - 2.45.0
- update to 2.45.0
* Sun Nov 20 2022 orignal <orignal@i2pmail.org> - 2.44.0 * Sun Nov 20 2022 orignal <orignal@i2pmail.org> - 2.44.0
- update to 2.44.0 - update to 2.44.0

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021-2023, The PurpleI2P Project * Copyright (c) 2021-2022, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -43,7 +43,7 @@ a, .slide label {
color: var(--main-link-color); color: var(--main-link-color);
} }
a:hover, a.button.selected, .slide label:hover, button[type=submit]:hover { a:hover, .slide label:hover, button[type=submit]:hover {
color: var(--main-link-hover-color); color: var(--main-link-hover-color);
background: var(--main-link-color); background: var(--main-link-color);
} }

View File

@@ -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 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -165,21 +165,20 @@ namespace util
i2p::transport::InitTransports (); i2p::transport::InitTransports ();
bool transit; i2p::config::GetOption("notransit", transit);
i2p::context.SetAcceptsTunnels (!transit);
uint16_t transitTunnels; i2p::config::GetOption("limits.transittunnels", transitTunnels);
SetMaxNumTransitTunnels (transitTunnels);
bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill); bool isFloodfill; i2p::config::GetOption("floodfill", isFloodfill);
if (isFloodfill) if (isFloodfill) {
{
LogPrint(eLogInfo, "Daemon: Router configured as floodfill"); LogPrint(eLogInfo, "Daemon: Router configured as floodfill");
i2p::context.SetFloodfill (true); i2p::context.SetFloodfill (true);
} }
else else
{
i2p::context.SetFloodfill (false); i2p::context.SetFloodfill (false);
}
bool transit; i2p::config::GetOption("notransit", transit);
i2p::context.SetAcceptsTunnels (!transit);
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);
/* this section also honors 'floodfill' flag, if set above */ /* this section also honors 'floodfill' flag, if set above */
std::string bandwidth; i2p::config::GetOption("bandwidth", bandwidth); std::string bandwidth; i2p::config::GetOption("bandwidth", bandwidth);
@@ -269,7 +268,7 @@ namespace util
if (hidden) if (hidden)
{ {
LogPrint(eLogInfo, "Daemon: Hidden mode enabled"); LogPrint(eLogInfo, "Daemon: Hidden mode enabled");
i2p::context.SetHidden(true); i2p::data::netdb.SetHidden(true);
} }
std::string httpLang; i2p::config::GetOption("http.lang", httpLang); std::string httpLang; i2p::config::GetOption("http.lang", httpLang);
@@ -310,7 +309,7 @@ namespace util
LogPrint(eLogInfo, "Daemon: Transports started"); LogPrint(eLogInfo, "Daemon: Transports started");
else else
{ {
LogPrint(eLogCritical, "Daemon: Failed to start Transports"); LogPrint(eLogError, "Daemon: Failed to start Transports");
/** shut down netdb right away */ /** shut down netdb right away */
i2p::transport::transports.Stop(); i2p::transport::transports.Stop();
i2p::data::netdb.Stop(); i2p::data::netdb.Stop();
@@ -329,17 +328,15 @@ namespace util
} }
catch (std::exception& ex) 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 ()); ThrowFatal ("Unable to start webconsole at ", httpAddr, ":", httpPort, ": ", ex.what ());
} }
} }
LogPrint(eLogInfo, "Daemon: Starting Tunnels"); LogPrint(eLogInfo, "Daemon: Starting Tunnels");
i2p::tunnel::tunnels.Start(); i2p::tunnel::tunnels.Start();
LogPrint(eLogInfo, "Daemon: Starting Router context");
i2p::context.Start();
LogPrint(eLogInfo, "Daemon: Starting Client"); LogPrint(eLogInfo, "Daemon: Starting Client");
i2p::client::context.Start (); i2p::client::context.Start ();
@@ -356,7 +353,7 @@ namespace util
} }
catch (std::exception& ex) 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 ()); ThrowFatal ("Unable to start I2PControl service at ", i2pcpAddr, ":", i2pcpPort, ": ", ex.what ());
} }
} }
@@ -368,8 +365,6 @@ namespace util
LogPrint(eLogInfo, "Daemon: Shutting down"); LogPrint(eLogInfo, "Daemon: Shutting down");
LogPrint(eLogInfo, "Daemon: Stopping Client"); LogPrint(eLogInfo, "Daemon: Stopping Client");
i2p::client::context.Stop(); i2p::client::context.Stop();
LogPrint(eLogInfo, "Daemon: Stopping Router context");
i2p::context.Stop();
LogPrint(eLogInfo, "Daemon: Stopping Tunnels"); LogPrint(eLogInfo, "Daemon: Stopping Tunnels");
i2p::tunnel::tunnels.Stop(); i2p::tunnel::tunnels.Stop();

View File

@@ -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 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -87,6 +87,8 @@ namespace http {
const char HTTP_COMMAND_GET_REG_STRING[] = "get_reg_string"; const char HTTP_COMMAND_GET_REG_STRING[] = "get_reg_string";
const char HTTP_COMMAND_SETLANGUAGE[] = "setlanguage"; const char HTTP_COMMAND_SETLANGUAGE[] = "setlanguage";
const char HTTP_COMMAND_RELOAD_CSS[] = "reload_css"; const char HTTP_COMMAND_RELOAD_CSS[] = "reload_css";
const char HTTP_PARAM_SAM_SESSION_ID[] = "id";
const char HTTP_PARAM_ADDRESS[] = "address";
static std::string ConvertTime (uint64_t time) static std::string ConvertTime (uint64_t time)
{ {
@@ -103,18 +105,18 @@ namespace http {
int num; int num;
if ((num = seconds / 86400) > 0) { if ((num = seconds / 86400) > 0) {
s << ntr("%d day", "%d days", num, num) << ", "; s << num << " " << tr("day", "days", num) << ", ";
seconds -= num * 86400; seconds -= num * 86400;
} }
if ((num = seconds / 3600) > 0) { if ((num = seconds / 3600) > 0) {
s << ntr("%d hour", "%d hours", num, num) << ", "; s << num << " " << tr("hour", "hours", num) << ", ";
seconds -= num * 3600; seconds -= num * 3600;
} }
if ((num = seconds / 60) > 0) { if ((num = seconds / 60) > 0) {
s << ntr("%d minute", "%d minutes", num, num) << ", "; s << num << " " << tr("minute", "minutes", num) << ", ";
seconds -= num * 60; seconds -= num * 60;
} }
s << ntr("%d second", "%d seconds", seconds, seconds); s << seconds << " " << tr("second", "seconds", seconds);
} }
static void ShowTraffic (std::stringstream& s, uint64_t bytes) static void ShowTraffic (std::stringstream& s, uint64_t bytes)
@@ -122,11 +124,11 @@ namespace http {
s << std::fixed << std::setprecision(2); s << std::fixed << std::setprecision(2);
auto numKBytes = (double) bytes / 1024; auto numKBytes = (double) bytes / 1024;
if (numKBytes < 1024) if (numKBytes < 1024)
s << tr(/* tr: Kibibyte */ "%.2f KiB", numKBytes); s << numKBytes << " " << tr(/* tr: Kibibit */ "KiB");
else if (numKBytes < 1024 * 1024) else if (numKBytes < 1024 * 1024)
s << tr(/* tr: Mebibyte */ "%.2f MiB", numKBytes / 1024); s << numKBytes / 1024 << " " << tr(/* tr: Mebibit */ "MiB");
else else
s << tr(/* tr: Gibibyte */ "%.2f GiB", numKBytes / 1024 / 1024); s << numKBytes / 1024 / 1024 << " " << tr(/* tr: Gibibit */ "GiB");
} }
static void ShowTunnelDetails (std::stringstream& s, enum i2p::tunnel::TunnelState eState, bool explr, int bytes) static void ShowTunnelDetails (std::stringstream& s, enum i2p::tunnel::TunnelState eState, bool explr, int bytes)
@@ -150,13 +152,12 @@ namespace http {
else stateText = tr("unknown"); else stateText = tr("unknown");
s << "<span class=\"tunnel " << state << "\"> " << stateText << ((explr) ? " (" + tr("exploratory") + ")" : "") << "</span>, "; s << "<span class=\"tunnel " << state << "\"> " << stateText << ((explr) ? " (" + tr("exploratory") + ")" : "") << "</span>, ";
ShowTraffic(s, bytes); s << " " << (int) (bytes / 1024) << "&nbsp;" << tr(/* tr: Kibibit */ "KiB") << "\r\n";
s << "\r\n";
} }
static void SetLogLevel (const std::string& level) 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); i2p::log::Logger().SetLogLevel(level);
else { else {
LogPrint(eLogError, "HTTPServer: Unknown loglevel set attempted"); LogPrint(eLogError, "HTTPServer: Unknown loglevel set attempted");
@@ -235,6 +236,7 @@ namespace http {
} }
if (error != eRouterErrorNone) if (error != eRouterErrorNone)
{ {
s << "<br>";
switch (error) switch (error)
{ {
case eRouterErrorClockSkew: case eRouterErrorClockSkew:
@@ -246,9 +248,6 @@ namespace http {
case eRouterErrorSymmetricNAT: case eRouterErrorSymmetricNAT:
s << " - " << tr("Symmetric NAT"); s << " - " << tr("Symmetric NAT");
break; break;
case eRouterErrorFullConeNAT:
s << " - " << tr("Full cone NAT");
break;
case eRouterErrorNoDescriptors: case eRouterErrorNoDescriptors:
s << " - " << tr("No Descriptors"); s << " - " << tr("No Descriptors");
break; break;
@@ -289,20 +288,15 @@ namespace http {
if (family.length () > 0) if (family.length () > 0)
s << "<b>"<< tr("Family") << ":</b> " << family << "<br>\r\n"; s << "<b>"<< tr("Family") << ":</b> " << family << "<br>\r\n";
s << "<b>" << tr("Tunnel creation success rate") << ":</b> " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () << "%<br>\r\n"; s << "<b>" << tr("Tunnel creation success rate") << ":</b> " << i2p::tunnel::tunnels.GetTunnelCreationSuccessRate () << "%<br>\r\n";
bool isTotalTCSR;
i2p::config::GetOption("http.showTotalTCSR", isTotalTCSR);
if (isTotalTCSR) {
s << "<b>" << tr("Total tunnel creation success rate") << ":</b> " << i2p::tunnel::tunnels.GetTotalTunnelCreationSuccessRate() << "%<br/>\r\n";
}
s << "<b>" << tr("Received") << ":</b> "; s << "<b>" << tr("Received") << ":</b> ";
ShowTraffic (s, i2p::transport::transports.GetTotalReceivedBytes ()); ShowTraffic (s, i2p::transport::transports.GetTotalReceivedBytes ());
s << " (" << tr(/* tr: Kibibyte/s */ "%.2f KiB/s", (double) i2p::transport::transports.GetInBandwidth15s () / 1024) << ")<br>\r\n"; s << " (" << (double) i2p::transport::transports.GetInBandwidth15s () / 1024 << " " << tr(/* tr: Kibibit/s */ "KiB/s") << ")<br>\r\n";
s << "<b>" << tr("Sent") << ":</b> "; s << "<b>" << tr("Sent") << ":</b> ";
ShowTraffic (s, i2p::transport::transports.GetTotalSentBytes ()); ShowTraffic (s, i2p::transport::transports.GetTotalSentBytes ());
s << " (" << tr(/* tr: Kibibyte/s */ "%.2f KiB/s", (double) i2p::transport::transports.GetOutBandwidth15s () / 1024) << ")<br>\r\n"; s << " (" << (double) i2p::transport::transports.GetOutBandwidth15s () / 1024 << " " << tr(/* tr: Kibibit/s */ "KiB/s") << ")<br>\r\n";
s << "<b>" << tr("Transit") << ":</b> "; s << "<b>" << tr("Transit") << ":</b> ";
ShowTraffic (s, i2p::transport::transports.GetTotalTransitTransmittedBytes ()); ShowTraffic (s, i2p::transport::transports.GetTotalTransitTransmittedBytes ());
s << " (" << tr(/* tr: Kibibyte/s */ "%.2f KiB/s", (double) i2p::transport::transports.GetTransitBandwidth15s () / 1024) << ")<br>\r\n"; s << " (" << (double) i2p::transport::transports.GetTransitBandwidth15s () / 1024 << " " << tr(/* tr: Kibibit/s */ "KiB/s") << ")<br>\r\n";
s << "<b>" << tr("Data path") << ":</b> " << i2p::fs::GetUTF8DataDir() << "<br>\r\n"; s << "<b>" << tr("Data path") << ":</b> " << i2p::fs::GetUTF8DataDir() << "<br>\r\n";
s << "<div class='slide'>"; s << "<div class='slide'>";
if ((outputFormat == OutputFormatEnum::forWebConsole) || !includeHiddenContent) { if ((outputFormat == OutputFormatEnum::forWebConsole) || !includeHiddenContent) {
@@ -321,7 +315,6 @@ namespace http {
{ {
for (const auto& address : *addresses) for (const auto& address : *addresses)
{ {
if (!address) continue;
s << "<tr>\r\n<td>"; s << "<tr>\r\n<td>";
switch (address->transportStyle) switch (address->transportStyle)
{ {
@@ -334,18 +327,17 @@ namespace http {
default: default:
s << tr("Unknown"); s << tr("Unknown");
} }
bool v6 = address->IsV6 (); if (address->IsV6 ())
if (v6)
{ {
if (address->IsV4 ()) s << "v4"; if (address->IsV4 ()) s << "v4";
s << "v6"; s << "v6";
} }
s << "</td>\r\n"; s << "</td>\r\n";
if (address->published) if (address->published)
s << "<td>" << (v6 ? "[" : "") << address->host.to_string() << (v6 ? "]:" : ":") << address->port << "</td>\r\n"; s << "<td>" << address->host.to_string() << ":" << address->port << "</td>\r\n";
else else
{ {
s << "<td>" << tr(/* tr: Shown when router doesn't publish itself and have "Firewalled" state */ "supported"); s << "<td>" << tr("supported");
if (address->port) if (address->port)
s << " :" << address->port; s << " :" << address->port;
s << "</td>\r\n"; s << "</td>\r\n";
@@ -473,7 +465,7 @@ namespace http {
} }
s << "&#8658; " << it->GetTunnelID () << ":me"; s << "&#8658; " << it->GetTunnelID () << ":me";
if (it->LatencyIsKnown()) if (it->LatencyIsKnown())
s << " ( " << tr(/* tr: Milliseconds */ "%dms", it->GetMeanLatency()) << " )"; s << " ( " << it->GetMeanLatency() << tr(/* tr: Milliseconds */ "ms") << " )";
ShowTunnelDetails(s, it->GetState (), false, it->GetNumReceivedBytes ()); ShowTunnelDetails(s, it->GetState (), false, it->GetNumReceivedBytes ());
s << "</div>\r\n"; s << "</div>\r\n";
} }
@@ -493,26 +485,22 @@ namespace http {
); );
} }
if (it->LatencyIsKnown()) if (it->LatencyIsKnown())
s << " ( " << tr("%dms", it->GetMeanLatency()) << " )"; s << " ( " << it->GetMeanLatency() << tr("ms") << " )";
ShowTunnelDetails(s, it->GetState (), false, it->GetNumSentBytes ()); ShowTunnelDetails(s, it->GetState (), false, it->GetNumSentBytes ());
s << "</div>\r\n"; s << "</div>\r\n";
} }
} }
s << "<br>\r\n"; s << "<br>\r\n";
s << "<b>" << tr("Tags") << "</b><br>\r\n" s << "<b>" << tr("Tags") << "</b><br>\r\n" << tr("Incoming") << ": <i>" << dest->GetNumIncomingTags () << "</i><br>\r\n";
<< tr("Incoming") << ": <i>" << dest->GetNumIncomingTags () << "</i><br>\r\n";
if (!dest->GetSessions ().empty ()) { if (!dest->GetSessions ().empty ()) {
std::stringstream tmp_s; uint32_t out_tags = 0; std::stringstream tmp_s; uint32_t out_tags = 0;
for (const auto& it: dest->GetSessions ()) { for (const auto& it: dest->GetSessions ()) {
tmp_s << "<tr><td>" << i2p::client::context.GetAddressBook ().ToAddress(it.first) << "</td><td>" << it.second->GetNumOutgoingTags () << "</td></tr>\r\n"; tmp_s << "<tr><td>" << i2p::client::context.GetAddressBook ().ToAddress(it.first) << "</td><td>" << it.second->GetNumOutgoingTags () << "</td></tr>\r\n";
out_tags += it.second->GetNumOutgoingTags (); out_tags += it.second->GetNumOutgoingTags ();
} }
s << "<div class='slide'><label for='slide-tags'>" << tr("Outgoing") << ": <i>" << out_tags << "</i></label>\r\n" s << "<div class='slide'><label for='slide-tags'>" << tr("Outgoing") << ": <i>" << out_tags << "</i></label>\r\n<input type=\"checkbox\" id=\"slide-tags\" />\r\n"
<< "<input type=\"checkbox\" id=\"slide-tags\" />\r\n" << "<div class=\"slidecontent\">\r\n<table>\r\n<thead><th>" << tr("Destination") << "</th><th>" << tr("Amount") << "</th></thead>\r\n<tbody class=\"tableitem\">\r\n" << tmp_s.str () << "</tbody></table>\r\n</div>\r\n</div>\r\n";
<< "<div class=\"slidecontent\">\r\n"
<< "<table>\r\n<thead><th>" << tr("Destination") << "</th><th>" << tr("Amount") << "</th></thead>\r\n"
<< "<tbody class=\"tableitem\">\r\n" << tmp_s.str () << "</tbody></table>\r\n</div>\r\n</div>\r\n";
} else } else
s << tr("Outgoing") << ": <i>0</i><br>\r\n"; s << tr("Outgoing") << ": <i>0</i><br>\r\n";
s << "<br>\r\n"; s << "<br>\r\n";
@@ -527,11 +515,8 @@ namespace http {
tmp_s << "<tr><td>" << i2p::client::context.GetAddressBook ().ToAddress(it.second->GetDestination ()) << "</td><td>" << it.second->GetState () << "</td></tr>\r\n"; tmp_s << "<tr><td>" << i2p::client::context.GetAddressBook ().ToAddress(it.second->GetDestination ()) << "</td><td>" << it.second->GetState () << "</td></tr>\r\n";
ecies_sessions++; ecies_sessions++;
} }
s << "<div class='slide'><label for='slide-ecies-sessions'>" << tr("Tags sessions") << ": <i>" << ecies_sessions << "</i></label>\r\n" s << "<div class='slide'><label for='slide-ecies-sessions'>" << tr("Tags sessions") << ": <i>" << ecies_sessions << "</i></label>\r\n<input type=\"checkbox\" id=\"slide-ecies-sessions\" />\r\n"
<< "<input type=\"checkbox\" id=\"slide-ecies-sessions\" />\r\n" << "<div class=\"slidecontent\">\r\n<table>\r\n<thead><th>" << tr("Destination") << "</th><th>" << tr("Status") << "</th></thead>\r\n<tbody class=\"tableitem\">\r\n" << tmp_s.str () << "</tbody></table>\r\n</div>\r\n</div>\r\n";
<< "<div class=\"slidecontent\">\r\n<table>\r\n"
<< "<thead><th>" << tr("Destination") << "</th><th>" << tr("Status") << "</th></thead>\r\n"
<< "<tbody class=\"tableitem\">\r\n" << tmp_s.str () << "</tbody></table>\r\n</div>\r\n</div>\r\n";
} else } else
s << tr("Tags sessions") << ": <i>0</i><br>\r\n"; s << tr("Tags sessions") << ": <i>0</i><br>\r\n";
s << "<br>\r\n"; s << "<br>\r\n";
@@ -554,7 +539,7 @@ namespace http {
<< tr("Streams") << tr("Streams")
<< "</caption>\r\n<thead>\r\n<tr>" << "</caption>\r\n<thead>\r\n<tr>"
<< "<th style=\"width:25px;\">StreamID</th>" << "<th style=\"width:25px;\">StreamID</th>"
<< "<th style=\"width:5px;\">&nbsp;</th>" // Stream closing button column << "<th style=\"width:5px;\" \\>" // Stream closing button column
<< "<th class=\"streamdest\">Destination</th>" << "<th class=\"streamdest\">Destination</th>"
<< "<th>Sent</th>" << "<th>Sent</th>"
<< "<th>Received</th>" << "<th>Received</th>"
@@ -625,10 +610,7 @@ namespace http {
if (storeType == i2p::data::NETDB_STORE_TYPE_LEASESET) if (storeType == i2p::data::NETDB_STORE_TYPE_LEASESET)
ls.reset (new i2p::data::LeaseSet (leaseSet->GetBuffer(), leaseSet->GetBufferLen())); ls.reset (new i2p::data::LeaseSet (leaseSet->GetBuffer(), leaseSet->GetBufferLen()));
else else
{ ls.reset (new i2p::data::LeaseSet2 (storeType, leaseSet->GetBuffer(), leaseSet->GetBufferLen()));
ls.reset (new i2p::data::LeaseSet2 (storeType));
ls->Update (leaseSet->GetBuffer(), leaseSet->GetBufferLen(), false);
}
if (!ls) return; if (!ls) return;
s << "<div class=\"leaseset listitem"; s << "<div class=\"leaseset listitem";
if (ls->IsExpired()) if (ls->IsExpired())
@@ -659,7 +641,7 @@ namespace http {
} }
else if (!i2p::context.IsFloodfill ()) else if (!i2p::context.IsFloodfill ())
{ {
s << "<b>" << tr("LeaseSets") << ":</b> " << tr(/* Message on LeaseSets page */ "floodfill mode is disabled") << ".<br>\r\n"; s << "<b>" << tr("LeaseSets") << ":</b> " << tr("not floodfill") << ".<br>\r\n";
} }
else else
{ {
@@ -688,7 +670,7 @@ namespace http {
} }
s << "&#8658; " << it->GetTunnelID () << ":me"; s << "&#8658; " << it->GetTunnelID () << ":me";
if (it->LatencyIsKnown()) if (it->LatencyIsKnown())
s << " ( " << tr("%dms", it->GetMeanLatency()) << " )"; s << " ( " << it->GetMeanLatency() << tr("ms") << " )";
ShowTunnelDetails(s, it->GetState (), (it->GetTunnelPool () == ExplPool), it->GetNumReceivedBytes ()); ShowTunnelDetails(s, it->GetState (), (it->GetTunnelPool () == ExplPool), it->GetNumReceivedBytes ());
s << "</div>\r\n"; s << "</div>\r\n";
} }
@@ -708,7 +690,7 @@ namespace http {
); );
} }
if (it->LatencyIsKnown()) if (it->LatencyIsKnown())
s << " ( " << tr("%dms", it->GetMeanLatency()) << " )"; s << " ( " << it->GetMeanLatency() << tr("ms") << " )";
ShowTunnelDetails(s, it->GetState (), (it->GetTunnelPool () == ExplPool), it->GetNumSentBytes ()); ShowTunnelDetails(s, it->GetState (), (it->GetTunnelPool () == ExplPool), it->GetNumSentBytes ());
s << "</div>\r\n"; s << "</div>\r\n";
} }
@@ -746,21 +728,19 @@ namespace http {
s << "<br>\r\n<small>" << tr("<b>Note:</b> any action done here are not persistent and not changes your config files.") << "</small>\r\n<br>\r\n"; s << "<br>\r\n<small>" << tr("<b>Note:</b> any action done here are not persistent and not changes your config files.") << "</small>\r\n<br>\r\n";
auto loglevel = i2p::log::Logger().GetLogLevel();
s << "<b>" << tr("Logging level") << "</b><br>\r\n"; 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\" 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\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=error&token=" << token << "\"> error </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\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=warn&token=" << token << "\"> warn </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\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=info&token=" << token << "\"> info </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\" href=\"" << webroot << "?cmd=" << HTTP_COMMAND_LOGLEVEL << "&level=debug&token=" << token << "\"> debug </a><br>\r\n<br>\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 = i2p::tunnel::tunnels.GetMaxNumTransitTunnels (); uint16_t maxTunnels = GetMaxNumTransitTunnels ();
s << "<b>" << tr("Transit tunnels limit") << "</b><br>\r\n"; s << "<b>" << tr("Transit tunnels limit") << "</b><br>\r\n";
s << "<form method=\"get\" action=\"" << webroot << "\">\r\n"; s << "<form method=\"get\" action=\"" << webroot << "\">\r\n";
s << " <input type=\"hidden\" name=\"cmd\" value=\"" << HTTP_COMMAND_LIMITTRANSIT << "\">\r\n"; s << " <input type=\"hidden\" name=\"cmd\" value=\"" << HTTP_COMMAND_LIMITTRANSIT << "\">\r\n";
s << " <input type=\"hidden\" name=\"token\" value=\"" << token << "\">\r\n"; s << " <input type=\"hidden\" name=\"token\" value=\"" << token << "\">\r\n";
s << " <input type=\"number\" min=\"0\" max=\"" << TRANSIT_TUNNELS_LIMIT <<"\" name=\"limit\" value=\"" << maxTunnels << "\">\r\n"; s << " <input type=\"number\" min=\"0\" max=\"65535\" name=\"limit\" value=\"" << maxTunnels << "\">\r\n";
s << " <button type=\"submit\">" << tr("Change") << "</button>\r\n"; s << " <button type=\"submit\">" << tr("Change") << "</button>\r\n";
s << "</form>\r\n<br>\r\n"; s << "</form>\r\n<br>\r\n";
@@ -790,71 +770,56 @@ namespace http {
{ {
if (i2p::tunnel::tunnels.CountTransitTunnels()) if (i2p::tunnel::tunnels.CountTransitTunnels())
{ {
s << "<b>" << tr("Transit Tunnels") << ":</b><br>\r\n"; s << "<b>" << tr("Transit Tunnels") << ":</b><br>\r\n<div class=\"list\">\r\n";
s << "<table><thead><th>&#8658;</th><th>ID</th><th>&#8658;</th><th>" << tr("Amount") << "</th></thead><tbody class=\"tableitem\">";
for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ()) for (const auto& it: i2p::tunnel::tunnels.GetTransitTunnels ())
{ {
s << "<div class=\"listitem\">\r\n";
if (std::dynamic_pointer_cast<i2p::tunnel::TransitTunnelGateway>(it)) if (std::dynamic_pointer_cast<i2p::tunnel::TransitTunnelGateway>(it))
s << "<tr><td></td><td>" << it->GetTunnelID () << "</td><td>&#8658;</td><td>"; s << it->GetTunnelID () << " &#8658; ";
else if (std::dynamic_pointer_cast<i2p::tunnel::TransitTunnelEndpoint>(it)) else if (std::dynamic_pointer_cast<i2p::tunnel::TransitTunnelEndpoint>(it))
s << "<tr><td>&#8658;</td><td>" << it->GetTunnelID () << "</td><td></td><td>"; s << " &#8658; " << it->GetTunnelID ();
else else
s << "<tr><td>&#8658;</td><td>" << it->GetTunnelID () << "</td><td>&#8658;</td><td>"; s << " &#8658; " << it->GetTunnelID () << " &#8658; ";
ShowTraffic(s, it->GetNumTransmittedBytes ()); s << " " << it->GetNumTransmittedBytes () << "</div>\r\n";
s << "</td></tr>\r\n";
} }
s << "</tbody></table>\r\n"; s << "</div>\r\n";
} }
else else
{ {
s << "<b>" << tr("Transit Tunnels") << ":</b> " << tr(/* Message on transit tunnels page */ "no transit tunnels currently built") << ".<br>\r\n"; s << "<b>" << tr("Transit Tunnels") << ":</b> " << tr("no transit tunnels currently built") << ".<br>\r\n";
} }
} }
template<typename Sessions> template<typename Sessions>
static void ShowTransportSessions (std::stringstream& s, const Sessions& sessions, const std::string name) static void ShowTransportSessions (std::stringstream& s, const Sessions& sessions, const std::string name)
{ {
auto comp = [](typename Sessions::mapped_type a, typename Sessions::mapped_type b) std::stringstream tmp_s, tmp_s6; uint16_t cnt = 0, cnt6 = 0;
{ return a->GetRemoteEndpoint() < b->GetRemoteEndpoint(); };
std::set<typename Sessions::mapped_type, decltype(comp)> sortedSessions(comp);
for (const auto& it: sessions ) for (const auto& it: sessions )
{ {
auto ret = sortedSessions.insert(it.second); auto endpoint = it.second->GetRemoteEndpoint ();
if (!ret.second) if (it.second && it.second->IsEstablished () && endpoint.address ().is_v4 ())
LogPrint(eLogError, "HTTPServer: Duplicate remote endpoint detected: ", (*ret.first)->GetRemoteEndpoint());
}
std::stringstream tmp_s, tmp_s6; uint16_t cnt = 0, cnt6 = 0;
for (const auto& it: sortedSessions)
{
auto endpoint = it->GetRemoteEndpoint ();
if (it && it->IsEstablished () && endpoint.address ().is_v4 ())
{ {
tmp_s << "<div class=\"listitem\">\r\n"; tmp_s << "<div class=\"listitem\">\r\n";
if (it->IsOutgoing ()) tmp_s << " &#8658; "; if (it.second->IsOutgoing ()) tmp_s << " &#8658; ";
tmp_s << i2p::data::GetIdentHashAbbreviation (it->GetRemoteIdentity ()->GetIdentHash ()) << ": " tmp_s << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": "
<< endpoint.address ().to_string () << ":" << endpoint.port (); << endpoint.address ().to_string () << ":" << endpoint.port ();
if (!it->IsOutgoing ()) tmp_s << " &#8658; "; if (!it.second->IsOutgoing ()) tmp_s << " &#8658; ";
tmp_s << " [" << it->GetNumSentBytes () << ":" << it->GetNumReceivedBytes () << "]"; tmp_s << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
if (it->GetRelayTag ()) if (it.second->GetRelayTag ())
tmp_s << " [itag:" << it->GetRelayTag () << "]"; tmp_s << " [itag:" << it.second->GetRelayTag () << "]";
if (it->GetSendQueueSize () > 0)
tmp_s << " [queue:" << it->GetSendQueueSize () << "]";
if (it->IsSlow ()) tmp_s << " [slow]";
tmp_s << "</div>\r\n" << std::endl; tmp_s << "</div>\r\n" << std::endl;
cnt++; cnt++;
} }
if (it && it->IsEstablished () && endpoint.address ().is_v6 ()) if (it.second && it.second->IsEstablished () && endpoint.address ().is_v6 ())
{ {
tmp_s6 << "<div class=\"listitem\">\r\n"; tmp_s6 << "<div class=\"listitem\">\r\n";
if (it->IsOutgoing ()) tmp_s6 << " &#8658; "; if (it.second->IsOutgoing ()) tmp_s6 << " &#8658; ";
tmp_s6 << i2p::data::GetIdentHashAbbreviation (it->GetRemoteIdentity ()->GetIdentHash ()) << ": " tmp_s6 << i2p::data::GetIdentHashAbbreviation (it.second->GetRemoteIdentity ()->GetIdentHash ()) << ": "
<< "[" << endpoint.address ().to_string () << "]:" << endpoint.port (); << "[" << endpoint.address ().to_string () << "]:" << endpoint.port ();
if (!it->IsOutgoing ()) tmp_s6 << " &#8658; "; if (!it.second->IsOutgoing ()) tmp_s6 << " &#8658; ";
tmp_s6 << " [" << it->GetNumSentBytes () << ":" << it->GetNumReceivedBytes () << "]"; tmp_s6 << " [" << it.second->GetNumSentBytes () << ":" << it.second->GetNumReceivedBytes () << "]";
if (it->GetRelayTag ()) if (it.second->GetRelayTag ())
tmp_s6 << " [itag:" << it->GetRelayTag () << "]"; tmp_s6 << " [itag:" << it.second->GetRelayTag () << "]";
if (it->GetSendQueueSize () > 0)
tmp_s6 << " [queue:" << it->GetSendQueueSize () << "]";
tmp_s6 << "</div>\r\n" << std::endl; tmp_s6 << "</div>\r\n" << std::endl;
cnt6++; cnt6++;
} }
@@ -914,7 +879,7 @@ namespace http {
s << "</div>\r\n"; s << "</div>\r\n";
} }
else else
s << "<b>" << tr("SAM sessions") << ":</b> " << tr(/* Message on SAM sessions page */ "no sessions currently running") << ".<br>\r\n"; s << "<b>" << tr("SAM sessions") << ":</b> " << tr("no sessions currently running") << ".<br>\r\n";
} }
void ShowSAMSession (std::stringstream& s, const std::string& id) void ShowSAMSession (std::stringstream& s, const std::string& id)
@@ -1023,7 +988,7 @@ namespace http {
for (auto& it: serverForwards) for (auto& it: serverForwards)
{ {
auto& ident = it.second->GetLocalDestination ()->GetIdentHash(); auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
s << "<div class=\"listitem\"><a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">"; s << "<a href=\"" << webroot << "?page=" << HTTP_PAGE_LOCAL_DESTINATION << "&b32=" << ident.ToBase32 () << "\">";
s << it.second->GetName () << "</a> &#8656; "; s << it.second->GetName () << "</a> &#8656; ";
s << i2p::client::context.GetAddressBook ().ToAddress(ident); s << i2p::client::context.GetAddressBook ().ToAddress(ident);
s << "</div>\r\n"<< std::endl; s << "</div>\r\n"<< std::endl;
@@ -1233,7 +1198,7 @@ namespace http {
url.parse_query(params); url.parse_query(params);
std::string webroot; i2p::config::GetOption("http.webroot", webroot); std::string webroot; i2p::config::GetOption("http.webroot", webroot);
std::string redirect = std::to_string(COMMAND_REDIRECT_TIMEOUT) + "; url=" + webroot + "?page=commands"; std::string redirect = "5; url=" + webroot + "?page=commands";
std::string token = params["token"]; std::string token = params["token"];
if (token.empty () || m_Tokens.find (std::stoi (token)) == m_Tokens.end ()) if (token.empty () || m_Tokens.find (std::stoi (token)) == m_Tokens.end ())
@@ -1307,20 +1272,20 @@ namespace http {
s << "<b>" << tr("ERROR") << "</b>:&nbsp;" << tr("StreamID can't be null") << "<br>\r\n<br>\r\n"; s << "<b>" << tr("ERROR") << "</b>:&nbsp;" << tr("StreamID can't be null") << "<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 << "<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>"; s << "<p>" << tr("You will be redirected in 5 seconds") << "</b>";
redirect = std::to_string(COMMAND_REDIRECT_TIMEOUT) + "; url=" + webroot + "?page=local_destination&b32=" + b32; redirect = "5; url=" + webroot + "?page=local_destination&b32=" + b32;
res.add_header("Refresh", redirect.c_str()); res.add_header("Refresh", redirect.c_str());
return; return;
} }
else if (cmd == HTTP_COMMAND_LIMITTRANSIT) else if (cmd == HTTP_COMMAND_LIMITTRANSIT)
{ {
uint32_t limit = std::stoul(params["limit"], nullptr); uint32_t limit = std::stoul(params["limit"], nullptr);
if (limit > 0 && limit <= TRANSIT_TUNNELS_LIMIT) if (limit > 0 && limit <= 65535)
i2p::tunnel::tunnels.SetMaxNumTransitTunnels (limit); SetMaxNumTransitTunnels (limit);
else { 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 << "<b>" << tr("ERROR") << "</b>:&nbsp;" << tr("Transit tunnels count must not exceed 65535") << "\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"; s << "<a href=\"" << webroot << "?page=commands\">" << tr("Back to commands list") << "</a>\r\n<br>\r\n";
s << "<p>" << tr("You will be redirected in %d seconds", COMMAND_REDIRECT_TIMEOUT) << "</b>"; s << "<p>" << tr("You will be redirected in 5 seconds") << "</b>";
res.add_header("Refresh", redirect.c_str()); res.add_header("Refresh", redirect.c_str());
return; return;
} }
@@ -1395,7 +1360,7 @@ namespace http {
s << "<b>" << tr("SUCCESS") << "</b>:&nbsp;" << tr("Command accepted") << "<br><br>\r\n"; s << "<b>" << tr("SUCCESS") << "</b>:&nbsp;" << tr("Command accepted") << "<br><br>\r\n";
s << "<a href=\"" << webroot << "?page=commands\">" << tr("Back to commands list") << "</a><br>\r\n"; s << "<a href=\"" << webroot << "?page=commands\">" << tr("Back to commands list") << "</a><br>\r\n";
s << "<p>" << tr("You will be redirected in %d seconds", COMMAND_REDIRECT_TIMEOUT) << "</b>"; s << "<p>" << tr("You will be redirected in 5 seconds") << "</b>";
res.add_header("Refresh", redirect.c_str()); res.add_header("Refresh", redirect.c_str());
} }

View File

@@ -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 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -24,8 +24,6 @@ namespace http
{ {
const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192; const size_t HTTP_CONNECTION_BUFFER_SIZE = 8192;
const int TOKEN_EXPIRATION_TIMEOUT = 30; // in seconds const int TOKEN_EXPIRATION_TIMEOUT = 30; // in seconds
const int COMMAND_REDIRECT_TIMEOUT = 5; // in seconds
const int TRANSIT_TUNNELS_LIMIT = 65535;
class HTTPConnection: public std::enable_shared_from_this<HTTPConnection> class HTTPConnection: public std::enable_shared_from_this<HTTPConnection>
{ {

View File

@@ -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 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -38,7 +38,7 @@ namespace http
"@media (prefers-color-scheme: dark) { :root { --main-bg-color: #242424; --main-text-color: #17ab5c; --main-link-color: #bf64b7; --main-link-hover-color: #000000; } }\r\n" "@media (prefers-color-scheme: dark) { :root { --main-bg-color: #242424; --main-text-color: #17ab5c; --main-link-color: #bf64b7; --main-link-hover-color: #000000; } }\r\n"
"body { font: 100%/1.5em sans-serif; margin: 0; padding: 1.5em; background: var(--main-bg-color); color: var(--main-text-color); }\r\n" "body { font: 100%/1.5em sans-serif; margin: 0; padding: 1.5em; background: var(--main-bg-color); color: var(--main-text-color); }\r\n"
"a, .slide label { text-decoration: none; color: var(--main-link-color); }\r\n" "a, .slide label { text-decoration: none; color: var(--main-link-color); }\r\n"
"a:hover, a.button.selected, .slide label:hover, button[type=submit]:hover { color: var(--main-link-hover-color); background: var(--main-link-color); }\r\n" "a:hover, .slide label:hover, button[type=submit]:hover { color: var(--main-link-hover-color); background: var(--main-link-color); }\r\n"
"a.button { appearance: button; text-decoration: none; padding: 0 5px; border: 1px solid var(--main-link-color); }\r\n" "a.button { appearance: button; text-decoration: none; padding: 0 5px; border: 1px solid var(--main-link-color); }\r\n"
".header { font-size: 2.5em; text-align: center; margin: 1em 0; color: var(--main-link-color); }\r\n" ".header { font-size: 2.5em; text-align: center; margin: 1em 0; color: var(--main-link-color); }\r\n"
".wrapper { margin: 0 auto; padding: 1em; max-width: 64em; }\r\n" ".wrapper { margin: 0 auto; padding: 1em; max-width: 64em; }\r\n"

View File

@@ -163,7 +163,7 @@ namespace transport
if (!a) return; if (!a) return;
for (const auto& address : *a) for (const auto& address : *a)
{ {
if (address && !address->host.is_v6 () && address->port) if (!address->host.is_v6 () && address->port)
TryPortMapping (address); TryPortMapping (address);
} }
m_Timer.expires_from_now (boost::posix_time::minutes(20)); // every 20 minutes m_Timer.expires_from_now (boost::posix_time::minutes(20)); // every 20 minutes
@@ -215,7 +215,7 @@ namespace transport
if (!a) return; if (!a) return;
for (const auto& address : *a) for (const auto& address : *a)
{ {
if (address && !address->host.is_v6 () && address->port) if (!address->host.is_v6 () && address->port)
CloseMapping (address); CloseMapping (address);
} }
} }

View File

@@ -173,7 +173,7 @@ namespace i2p
ftruncate(pidFH, 0); ftruncate(pidFH, 0);
if (write(pidFH, pid, strlen(pid)) < 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; std::cerr << "i2pd: Could not write pidfile " << pidfile << ": " << strerror(errno) << std::endl;
return false; return false;
} }

41
debian/changelog vendored
View File

@@ -1,44 +1,3 @@
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
-- orignal <orignal@i2pmail.org> Wed, 15 Feb 2023 19:00:00 +0000
i2pd (2.45.1-1) unstable; urgency=medium
* updated to version 2.45.1/0.9.57
-- orignal <orignal@i2pmail.org> Wed, 11 Jan 2023 19:00:00 +0000
i2pd (2.45.0-1) unstable; urgency=high
* updated to version 2.45.0/0.9.57
* compat level 12
* standards version 4.3.0
* increased nofile limit in service and init.d to 8192
* added conffiles
* removed #1210 patch
-- r4sas <r4sas@i2pmail.org> Tue, 3 Jan 2023 18:00:00 +0000
i2pd (2.44.0-1) unstable; urgency=medium i2pd (2.44.0-1) unstable; urgency=medium
* updated to version 2.44.0/0.9.56 * updated to version 2.44.0/0.9.56

2
debian/compat vendored
View File

@@ -1 +1 @@
12 9

4
debian/control vendored
View File

@@ -2,8 +2,8 @@ Source: i2pd
Section: net Section: net
Priority: optional Priority: optional
Maintainer: r4sas <r4sas@i2pmail.org> Maintainer: r4sas <r4sas@i2pmail.org>
Build-Depends: debhelper (>= 12~), clang, cmake, 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 Build-Depends: debhelper (>= 9), dpkg-dev (>= 1.17.2~), gcc (>= 4.7) | clang (>= 3.3), libboost-system-dev (>= 1.46), libboost-date-time-dev (>= 1.46), libboost-filesystem-dev (>= 1.46), libboost-program-options-dev (>= 1.46), libminiupnpc-dev, libssl-dev, zlib1g-dev
Standards-Version: 4.3.0 Standards-Version: 3.9.8
Homepage: http://i2pd.website/ Homepage: http://i2pd.website/
Vcs-Git: git://github.com/PurpleI2P/i2pd.git Vcs-Git: git://github.com/PurpleI2P/i2pd.git
Vcs-Browser: https://github.com/PurpleI2P/i2pd Vcs-Browser: https://github.com/PurpleI2P/i2pd

12
debian/copyright vendored
View File

@@ -1,19 +1,23 @@
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: i2pd Upstream-Name: i2pd
Source: https://github.com/PurpleI2P/i2pd Source: https://github.com/PurpleI2P
Files: * Files: *
Copyright: 2013-2023 The PurpleI2P Project Copyright: 2013-2020 PurpleI2P
License: BSD-3-clause License: BSD-3-clause
Files: debian/* Files: debian/*
Copyright: 2013-2015 Kill Your TV <killyourtv@i2pmail.org> Copyright: 2013-2015 Kill Your TV <killyourtv@i2pmail.org>
2014-2016 hagen <hagen@i2pmail.org> 2014-2016 hagen <hagen@i2pmail.org>
2016-2023 R4SAS <r4sas@i2pmail.org> 2016-2020 R4SAS <r4sas@i2pmail.org>
2017-2023 Yangfl <mmyangfl@gmail.com> 2017-2020 Yangfl <mmyangfl@gmail.com>
License: GPL-2+ License: GPL-2+
License: BSD-3-clause License: BSD-3-clause
Copyright (c) 2013-2017, The PurpleI2P Project
.
All rights reserved.
.
Redistribution and use in source and binary forms, with or without modification, are Redistribution and use in source and binary forms, with or without modification, are
permitted provided that the following conditions are met: permitted provided that the following conditions are met:
. .

2
debian/i2pd.default vendored
View File

@@ -8,4 +8,4 @@ I2PD_ENABLED="yes"
DAEMON_OPTS="" DAEMON_OPTS=""
# If you have problems with hunging i2pd, you can try enable this # If you have problems with hunging i2pd, you can try enable this
ulimit -n 8192 ulimit -n 4096

3
debian/i2pd.install vendored
View File

@@ -1,6 +1,7 @@
obj-*/i2pd usr/sbin/ i2pd usr/sbin/
contrib/i2pd.conf etc/i2pd/ contrib/i2pd.conf etc/i2pd/
contrib/tunnels.conf etc/i2pd/ contrib/tunnels.conf etc/i2pd/
contrib/subscriptions.txt etc/i2pd/
contrib/certificates/ usr/share/i2pd/ contrib/certificates/ usr/share/i2pd/
contrib/tunnels.d/README etc/i2pd/tunnels.conf.d/ contrib/tunnels.d/README etc/i2pd/tunnels.conf.d/
contrib/apparmor/usr.sbin.i2pd etc/apparmor.d contrib/apparmor/usr.sbin.i2pd etc/apparmor.d

1
debian/i2pd.links vendored
View File

@@ -1,4 +1,5 @@
etc/i2pd/i2pd.conf var/lib/i2pd/i2pd.conf etc/i2pd/i2pd.conf var/lib/i2pd/i2pd.conf
etc/i2pd/tunnels.conf var/lib/i2pd/tunnels.conf etc/i2pd/tunnels.conf var/lib/i2pd/tunnels.conf
etc/i2pd/subscriptions.txt var/lib/i2pd/subscriptions.txt
etc/i2pd/tunnels.conf.d var/lib/i2pd/tunnels.d etc/i2pd/tunnels.conf.d var/lib/i2pd/tunnels.d
usr/share/i2pd/certificates var/lib/i2pd/certificates usr/share/i2pd/certificates var/lib/i2pd/certificates

27
debian/patches/01-fix-1210.patch vendored Normal file
View File

@@ -0,0 +1,27 @@
Description: fix #1210
Disables two options, which not presented in old systemd versions
Author: r4sas <r4sas@i2pmail.org>
Bug: https://github.com/PurpleI2P/i2pd/issues/1210
Reviewed-By: r4sas <r4sas@i2pmail.org>
Last-Update: 2020-05-25
Index: i2pd/contrib/i2pd.service
===================================================================
--- i2pd.orig/contrib/i2pd.service
+++ i2pd/contrib/i2pd.service
@@ -6,10 +6,10 @@ After=network.target
[Service]
User=i2pd
Group=i2pd
-RuntimeDirectory=i2pd
-RuntimeDirectoryMode=0700
-LogsDirectory=i2pd
-LogsDirectoryMode=0700
+#RuntimeDirectory=i2pd
+#RuntimeDirectoryMode=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"

17
debian/patches/02-upnp.patch vendored Normal file
View File

@@ -0,0 +1,17 @@
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

2
debian/patches/series vendored Normal file
View File

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

15
debian/rules vendored
View File

@@ -7,20 +7,7 @@ include /usr/share/dpkg/architecture.mk
export DEB_CXXFLAGS_MAINT_APPEND = -Wall -pedantic export DEB_CXXFLAGS_MAINT_APPEND = -Wall -pedantic
export DEB_LDFLAGS_MAINT_APPEND = export DEB_LDFLAGS_MAINT_APPEND =
export CC=clang
export CXX=clang++
%: %:
dh $@ --buildsystem=cmake dh $@ --parallel
override_dh_auto_clean:
dh_auto_clean --buildsystem=cmake --sourcedirectory=build/
override_dh_auto_configure:
dh_auto_configure --buildsystem=cmake --sourcedirectory=build/ -- \
-DWITH_UPNP=ON
override_dh_auto_build:
dh_auto_build --buildsystem=cmake
override_dh_auto_install: override_dh_auto_install:

3
debian/watch vendored
View File

@@ -1,4 +1,3 @@
version=4 version=4 opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%i2pd-$1.tar.gz%" \
opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%i2pd-$1.tar.gz%" \
https://github.com/PurpleI2P/i2pd/tags \ https://github.com/PurpleI2P/i2pd/tags \
(?:.*?/)?(\d[\d.]*)\.tar\.gz debian uupdate (?:.*?/)?(\d[\d.]*)\.tar\.gz debian uupdate

View File

@@ -64,10 +64,10 @@ namespace afrikaans // language namespace
static std::map<std::string, std::vector<std::string>> plurals static std::map<std::string, std::vector<std::string>> plurals
{ {
{"%d days", {"%d dag", "%d dae"}}, {"days", {"dag", "dae"}},
{"%d hours", {"%d uur", "%d ure"}}, {"hours", {"uur", "ure"}},
{"%d minutes", {"%d minuut", "%d minute"}}, {"minutes", {"minuut", "minute"}},
{"%d seconds", {"%d seconde", "%d sekondes"}}, {"seconds", {"seconde", "sekondes"}},
{"", {"", ""}}, {"", {"", ""}},
}; };

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021-2023, The PurpleI2P Project * Copyright (c) 2021, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -31,16 +31,15 @@ namespace armenian // language namespace
static std::map<std::string, std::string> strings static std::map<std::string, std::string> strings
{ {
{"%.2f KiB", "%.2f ԿիԲ"}, {"KiB", "ԿիԲ"},
{"%.2f MiB", "%.2f ՄիԲ"}, {"MiB", "ՄիԲ"},
{"%.2f GiB", "%.2f ԳիԲ"}, {"GiB", "ԳիԲ"},
{"building", "կառուցվում է"}, {"building", "կառուցվում է"},
{"failed", "Անհաջող"}, {"failed", "Անհաջող"},
{"expiring", "Լրանում է"}, {"expiring", "Լրանում է"},
{"established", "կարգավոյված է"}, {"established", "կարգավոյված է"},
{"unknown", "անհայտ"}, {"unknown", "անհայտ"},
{"exploratory", "հետազոտոկան"}, {"exploratory", "հետազոտոկան"},
{"Purple I2P Webconsole", "Վեբ-կոնսոլ Purple I2P"},
{"<b>i2pd</b> webconsole", "Վեբ-կոնսոլ <b>i2pd</b>"}, {"<b>i2pd</b> webconsole", "Վեբ-կոնսոլ <b>i2pd</b>"},
{"Main page", "Գլխավոր էջ"}, {"Main page", "Գլխավոր էջ"},
{"Router commands", "Երթուղիչի հրահանգներ"}, {"Router commands", "Երթուղիչի հրահանգներ"},
@@ -58,10 +57,10 @@ namespace armenian // language namespace
{"Unknown", "Անհայտ"}, {"Unknown", "Անհայտ"},
{"Proxy", "Պրոկսի"}, {"Proxy", "Պրոկսի"},
{"Mesh", "MESH-ցանց"}, {"Mesh", "MESH-ցանց"},
{"Error", "Սխալ"},
{"Clock skew", "Ոչ ճշգրիտ ժամանակ"}, {"Clock skew", "Ոչ ճշգրիտ ժամանակ"},
{"Offline", "Օֆլայն"}, {"Offline", "Օֆլայն"},
{"Symmetric NAT", "Սիմետրիկ NAT"}, {"Symmetric NAT", "Սիմետրիկ NAT"},
{"Full cone NAT", "Full cone NAT"},
{"Uptime", "Առկայություն"}, {"Uptime", "Առկայություն"},
{"Network status", "Ցանցի կարգավիճակ"}, {"Network status", "Ցանցի կարգավիճակ"},
{"Network status v6", "Ցանցի կարգավիճակ v6"}, {"Network status v6", "Ցանցի կարգավիճակ v6"},
@@ -69,7 +68,7 @@ namespace armenian // language namespace
{"Family", "Խմբատեսակ"}, {"Family", "Խմբատեսակ"},
{"Tunnel creation success rate", "Հաջողությամբ կառուցված թունելներ"}, {"Tunnel creation success rate", "Հաջողությամբ կառուցված թունելներ"},
{"Received", "Ստացվել է"}, {"Received", "Ստացվել է"},
{"%.2f KiB/s", "%.2f ԿիԲ/վ"}, {"KiB/s", "ԿիԲ/վ"},
{"Sent", "Ուղարկվել է"}, {"Sent", "Ուղարկվել է"},
{"Transit", "Տարանցում"}, {"Transit", "Տարանցում"},
{"Data path", "Տվյալների ուղին"}, {"Data path", "Տվյալների ուղին"},
@@ -90,12 +89,12 @@ namespace armenian // language namespace
{"Address registration line", "Հասցեի գրանցման տող"}, {"Address registration line", "Հասցեի գրանցման տող"},
{"Domain", "Տիրույթ"}, {"Domain", "Տիրույթ"},
{"Generate", "Գեներացնել"}, {"Generate", "Գեներացնել"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b> Նշում. </b> արդյունքի տողը կարող է օգտագործվել միայն 2LD տիրույթներ գրանցելու համար (example.i2p): Ենթատիրույթներ գրանցելու համար խնդրում ենք օգտագործել i2pd-tools գործիքակազմը:"}, {"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b> Նշում. </b> արդյունքի տողը կարող է օգտագործվել միայն 2LD տիրույթներ գրանցելու համար (example.i2p): Ենթատիրույթներ գրանցելու համար խնդրում ենք օգտագործել i2pd-tools գործիքակազմը"},
{"Address", "Հասցե"}, {"Address", "Հասցե"},
{"Type", "Տեսակը"}, {"Type", "Տեսակը"},
{"EncType", "Գաղտնագրի տեսակը"}, {"EncType", "Գաղտնագրի տեսակը"},
{"Inbound tunnels", "Մուտքային թունելներ"}, {"Inbound tunnels", "Մուտքային թունելներ"},
{"%dms", "%dմլվ"}, {"ms", "մլվ"},
{"Outbound tunnels", "Ելքային թունելներ"}, {"Outbound tunnels", "Ելքային թունելներ"},
{"Tags", "Թեգեր"}, {"Tags", "Թեգեր"},
{"Incoming", "Մուտքային"}, {"Incoming", "Մուտքային"},
@@ -117,6 +116,7 @@ namespace armenian // language namespace
{"Gateway", "Դարպաս"}, {"Gateway", "Դարպաս"},
{"TunnelID", "Թունելի ID"}, {"TunnelID", "Թունելի ID"},
{"EndDate", "Ավարտ"}, {"EndDate", "Ավարտ"},
{"not floodfill", "ոչ floodfill-ներ"},
{"Queue size", "Հերթի չափսը"}, {"Queue size", "Հերթի չափսը"},
{"Run peer test", "Գործարկել փորձարկումը"}, {"Run peer test", "Գործարկել փորձարկումը"},
{"Decline transit tunnels", "Մերժել տարանցիկ թունելներ"}, {"Decline transit tunnels", "Մերժել տարանցիկ թունելներ"},
@@ -146,7 +146,10 @@ namespace armenian // language namespace
{"Destination not found", "Հասցեի վայրը չի գտնվել"}, {"Destination not found", "Հասցեի վայրը չի գտնվել"},
{"StreamID can't be null", "StreamID-ն չի կարող լինել դատարկ"}, {"StreamID can't be null", "StreamID-ն չի կարող լինել դատարկ"},
{"Return to destination page", "Վերադառնալ նախորդ էջի հասցե"}, {"Return to destination page", "Վերադառնալ նախորդ էջի հասցե"},
{"You will be redirected in 5 seconds", "Դուք կտեղափոխվեք 5 վայրկյանից"},
{"Transit tunnels count must not exceed 65535", "Տարանցիկ թունելների քանակը չպետք է գերազանցի 65535-ը"},
{"Back to commands list", "Վերադառնալ հրահանգների ցուցակ"}, {"Back to commands list", "Վերադառնալ հրահանգների ցուցակ"},
{"Register at reg.i2p", "Գրանցել reg.i2p-ում"},
{"Description", "Նկարագրություն"}, {"Description", "Նկարագրություն"},
{"A bit information about service on domain", "Մի փոքր տեղեկատվություն տիրոիյթում գտնվող ծառայության մասին"}, {"A bit information about service on domain", "Մի փոքր տեղեկատվություն տիրոիյթում գտնվող ծառայության մասին"},
{"Submit", "Ուղարկվել"}, {"Submit", "Ուղարկվել"},
@@ -162,35 +165,43 @@ namespace armenian // language namespace
{"You may try to find this host on jump services below", "Ստորև Դուք կարող եք գտնել այս հոսթը jump ծառայությունների միջոցով"}, {"You may try to find this host on jump services below", "Ստորև Դուք կարող եք գտնել այս հոսթը jump ծառայությունների միջոցով"},
{"Invalid request", "Սխալ հարցում"}, {"Invalid request", "Սխալ հարցում"},
{"Proxy unable to parse your request", "Պրոկսին չի կարող հասկանալ Ձեր հարցումը"}, {"Proxy unable to parse your request", "Պրոկսին չի կարող հասկանալ Ձեր հարցումը"},
{"Invalid request URI", "Սխալ ձևավորված URI հարցում"}, {"addresshelper is not supported", "addresshelper-ը համատեղելի չէ"},
{"Host", "Հոսթ"},
{"added to router's addressbook from helper", "Ավելացված է երթուղիչի հասցեագրքում helper-ի միջոցով"},
{"Click here to proceed:", "Շարունակելու համար սեղմեք այստեղ"},
{"Continue", "Շարունակել"},
{"Addresshelper found", "addresshelper-ը գնտված է"},
{"already in router's addressbook", "արդեն առկա է երթուղիչի հասցեագրքում"},
{"Click here to update record:", "Սեղմեկ այստեղ որպեսզի թարվացնեք գրառումը"},
{"invalid request uri", "Սխալ ձևավորված URI հարցում"},
{"Can't detect destination host from request", "Չհաջողվեց հայնտաբերեկ վայրի հասցեն նշված հարցմամբ"}, {"Can't detect destination host from request", "Չհաջողվեց հայնտաբերեկ վայրի հասցեն նշված հարցմամբ"},
{"Outproxy failure", "Սխալ արտաքին պրոքսի"}, {"Outproxy failure", "Սխալ արտաքին պրոքսի"},
{"Bad outproxy settings", "Սխալ արտաքին պրոկսի կարգավորումներ"}, {"bad outproxy settings", "Սխալ արտաքին պրոկսի կարգավորումներ"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Հոսթ %s Հարցումը I2P ցանցից դուրս է, բայց արտաքին պրոքսին միացված չէ"}, {"not inside I2P network, but outproxy is not enabled", "Հարցումը I2P ցանցից դուրս է, բայց արտաքին պրոքսին միացված չէ"},
{"Unknown outproxy URL", "Արտաքին պրոքսիի անհայտ URL"}, {"unknown outproxy url", "արտաքին պրոքսիի անհայտ URL"},
{"Cannot resolve upstream proxy", "Չհաջողվեց որոշել վերադաս պրոկսին"}, {"cannot resolve upstream proxy", "Չհաջողվեց որոշել վերադաս պրոկսին"},
{"Hostname is too long", "Հոսթի անունը չափազանց երկար է"}, {"hostname too long", "Հոսթի անունը չափազանց երկար է"},
{"Cannot connect to upstream SOCKS proxy", "Չհաջողվեց միանալ վերադաս SOCKS պրոկսի սերվերին"}, {"cannot connect to upstream socks proxy", "չհաջողվեց միանալ վերադաս socks պրոկսիին"},
{"Cannot negotiate with SOCKS proxy", "Չհաջողվեց պայմանավորվել վերադաս SOCKS պրոկսիի հետ"}, {"Cannot negotiate with socks proxy", "Չհաջողվեց պայմանավորվել վերադաս socks պրոկսիի հետ"},
{"CONNECT error", "Սխալ CONNECT հարցում"}, {"CONNECT error", "Սխալ CONNECT հարցում"},
{"Failed to connect", "Միանալ չhաջողվեց"}, {"Failed to Connect", "Միանալ չhաջողվեց"},
{"SOCKS proxy error", "Սխալ SOCKS պրոկսի"}, {"socks proxy error", "Սխալ SOCKS պրոկսի"},
{"Failed to send request to upstream", "Չհաջողվեց հարցումն ուղարկել վերադաս պրոկսիին"}, {"failed to send request to upstream", "Չհաջողվեց հարցումն ուղարկել վերադաս պրոկսիին"},
{"No reply from SOCKS proxy", "Բացակայում է պատասխանը SOCKS պրոկսի սերվերի կողմից"}, {"No Reply From socks proxy", "Բացակայում է պատասխանը SOCKS պրոկսի սերվերի կողմից"},
{"Cannot connect", "Հնարավոր չե միանալ"}, {"cannot connect", "Հնարավոր չե միանալ"},
{"HTTP out proxy not implemented", "Արտաքին HTTP պրոկսին դեռ իրականացված չէ"}, {"http out proxy not implemented", "Արտաքին http պրոկսին դեռ իրականացված չէ"},
{"Cannot connect to upstream HTTP proxy", "Չհաջողվեց միանալ վերադաս HTTP պրոկսի սերվերին"}, {"cannot connect to upstream http proxy", "Չհաջողվեց միանալ վերադաս http պրոկսի սերվերին"},
{"Host is down", "Հոսթն անհասանելի է"}, {"Host is down", "Հոսթն անհասանելի է"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Հոսթի հետ կապը հաստատել չհաջողվեց, հնարավոր է այն անջատված է, փորձեք միանալ քիչ ուշ:"}, {"Can't create connection to requested host, it may be down. Please try again later.", "Հոսթի հետ կապը հաստատել չհաջողվեց, հնարավոր է այն անջատված է, փորձեք միանալ քիչ ուշ"},
{"", ""}, {"", ""},
}; };
static std::map<std::string, std::vector<std::string>> plurals static std::map<std::string, std::vector<std::string>> plurals
{ {
{"%d days", {"%d օր", "%d օր"}}, {"days", {"օր", "օր"}},
{"%d hours", {"%d ժամ", "%d ժամ"}}, {"hours", {"ժամ", "ժամ"}},
{"%d minutes", {"%d րոպե", "%d րոպե"}}, {"minutes", {"րոպե", "րոպե"}},
{"%d seconds", {"%d վարկյան", "%d վարկյան"}}, {"seconds", {"վարկյան", "վարկյան"}},
{"", {"", ""}}, {"", {"", ""}},
}; };

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022-2023, The PurpleI2P Project * Copyright (c) 2022, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -13,6 +13,7 @@
#include "I18N.h" #include "I18N.h"
// Simplified Chinese localization file // Simplified Chinese localization file
// This is an example translation file without strings in it.
namespace i2p namespace i2p
{ {
@@ -31,9 +32,9 @@ namespace chinese // language namespace
static std::map<std::string, std::string> strings static std::map<std::string, std::string> strings
{ {
{"%.2f KiB", "%.2f KiB"}, {"KiB", "KiB"},
{"%.2f MiB", "%.2f MiB"}, {"MiB", "MiB"},
{"%.2f GiB", "%.2f GiB"}, {"GiB", "GiB"},
{"building", "正在构建"}, {"building", "正在构建"},
{"failed", "连接失败"}, {"failed", "连接失败"},
{"expiring", "即将过期"}, {"expiring", "即将过期"},
@@ -45,7 +46,7 @@ namespace chinese // language namespace
{"Main page", "主页"}, {"Main page", "主页"},
{"Router commands", "路由命令"}, {"Router commands", "路由命令"},
{"Local Destinations", "本地目标"}, {"Local Destinations", "本地目标"},
{"LeaseSets", ""}, {"LeaseSets", ""},
{"Tunnels", "隧道"}, {"Tunnels", "隧道"},
{"Transit Tunnels", "中转隧道"}, {"Transit Tunnels", "中转隧道"},
{"Transports", "传输"}, {"Transports", "传输"},
@@ -57,12 +58,11 @@ namespace chinese // language namespace
{"Firewalled", "受到防火墙限制"}, {"Firewalled", "受到防火墙限制"},
{"Unknown", "未知"}, {"Unknown", "未知"},
{"Proxy", "代理"}, {"Proxy", "代理"},
{"Mesh", "组网"}, {"Mesh", "Mesh组网"},
{"Error", "错误"},
{"Clock skew", "时钟偏移"}, {"Clock skew", "时钟偏移"},
{"Offline", "离线"}, {"Offline", "离线"},
{"Symmetric NAT", "对称 NAT"}, {"Symmetric NAT", "对称 NAT"},
{"Full cone NAT", "全锥型NAT"},
{"No Descriptors", "无描述符"},
{"Uptime", "运行时间"}, {"Uptime", "运行时间"},
{"Network status", "IPv4 网络状态"}, {"Network status", "IPv4 网络状态"},
{"Network status v6", "IPv6 网络状态"}, {"Network status v6", "IPv6 网络状态"},
@@ -70,7 +70,7 @@ namespace chinese // language namespace
{"Family", "家族"}, {"Family", "家族"},
{"Tunnel creation success rate", "隧道创建成功率"}, {"Tunnel creation success rate", "隧道创建成功率"},
{"Received", "已接收"}, {"Received", "已接收"},
{"%.2f KiB/s", "%.2f KiB/s"}, {"KiB/s", "KiB/s"},
{"Sent", "已发送"}, {"Sent", "已发送"},
{"Transit", "中转"}, {"Transit", "中转"},
{"Data path", "数据文件路径"}, {"Data path", "数据文件路径"},
@@ -91,12 +91,12 @@ namespace chinese // language namespace
{"Address registration line", "地址域名注册"}, {"Address registration line", "地址域名注册"},
{"Domain", "域名"}, {"Domain", "域名"},
{"Generate", "生成"}, {"Generate", "生成"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>注意:</b> 结果字符串只能用于注册级域名(例如example.i2p)。若需注册三级域名,请使用 i2pd-tools。"}, {"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>注意:</b> 结果字符串只能用于注册级域名(例如example.i2p)。若需注册域名,请使用 i2pd-tools。"},
{"Address", "地址"}, {"Address", "地址"},
{"Type", "类型"}, {"Type", "类型"},
{"EncType", "加密类型"}, {"EncType", "加密类型"},
{"Inbound tunnels", "入站隧道"}, {"Inbound tunnels", "入站隧道"},
{"%dms", "%dms"}, {"ms", "毫秒"},
{"Outbound tunnels", "出站隧道"}, {"Outbound tunnels", "出站隧道"},
{"Tags", "标签"}, {"Tags", "标签"},
{"Incoming", "传入"}, {"Incoming", "传入"},
@@ -118,10 +118,9 @@ namespace chinese // language namespace
{"Gateway", "网关"}, {"Gateway", "网关"},
{"TunnelID", "隧道 ID"}, {"TunnelID", "隧道 ID"},
{"EndDate", "结束日期"}, {"EndDate", "结束日期"},
{"floodfill mode is disabled", "洪泛已禁用"}, {"not floodfill", "洪泛"},
{"Queue size", "队列大小"}, {"Queue size", "队列大小"},
{"Run peer test", "运行节点测试"}, {"Run peer test", "运行节点测试"},
{"Reload tunnels configuration", "重新载入隧道配置"},
{"Decline transit tunnels", "拒绝中转隧道"}, {"Decline transit tunnels", "拒绝中转隧道"},
{"Accept transit tunnels", "允许中转隧道"}, {"Accept transit tunnels", "允许中转隧道"},
{"Cancel graceful shutdown", "取消平滑关闭"}, {"Cancel graceful shutdown", "取消平滑关闭"},
@@ -129,7 +128,7 @@ namespace chinese // language namespace
{"Force shutdown", "强制停止"}, {"Force shutdown", "强制停止"},
{"Reload external CSS styles", "重载外部 CSS 样式"}, {"Reload external CSS styles", "重载外部 CSS 样式"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>注意:</b> 此处完成的任何操作都不是永久的,不会更改您的配置文件。"}, {"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>注意:</b> 此处完成的任何操作都不是永久的,不会更改您的配置文件。"},
{"Logging level", "日志级别"}, {"Logging level", "日志记录级别"},
{"Transit tunnels limit", "中转隧道限制"}, {"Transit tunnels limit", "中转隧道限制"},
{"Change", "修改"}, {"Change", "修改"},
{"Change language", "更改语言"}, {"Change language", "更改语言"},
@@ -149,8 +148,8 @@ namespace chinese // language namespace
{"Destination not found", "找不到目标"}, {"Destination not found", "找不到目标"},
{"StreamID can't be null", "StreamID 不能为空"}, {"StreamID can't be null", "StreamID 不能为空"},
{"Return to destination page", "返回目标页面"}, {"Return to destination page", "返回目标页面"},
{"You will be redirected in %d seconds", "您将在%d秒内被重定向"}, {"You will be redirected in 5 seconds", "您将在5秒内被重定向"},
{"Transit tunnels count must not exceed %d", "中转隧道数量限制为 %d"}, {"Transit tunnels count must not exceed 65535", "中转隧道数量不能超过 65535"},
{"Back to commands list", "返回命令列表"}, {"Back to commands list", "返回命令列表"},
{"Register at reg.i2p", "在 reg.i2p 注册域名"}, {"Register at reg.i2p", "在 reg.i2p 注册域名"},
{"Description", "描述"}, {"Description", "描述"},
@@ -165,36 +164,35 @@ namespace chinese // language namespace
{"Proxy info", "代理信息"}, {"Proxy info", "代理信息"},
{"Proxy error: Host not found", "代理错误:未找到主机"}, {"Proxy error: Host not found", "代理错误:未找到主机"},
{"Remote host not found in router's addressbook", "在路由地址簿中未找到远程主机"}, {"Remote host not found in router's addressbook", "在路由地址簿中未找到远程主机"},
{"You may try to find this host on jump services below", "您可以尝试在下方的跳转服务中找到主机"}, {"You may try to find this host on jump services below", "您可以尝试在下方的跳转服务中找到主机"},
{"Invalid request", "无效请求"}, {"Invalid request", "无效请求"},
{"Proxy unable to parse your request", "代理无法解析您的请求"}, {"Proxy unable to parse your request", "代理无法解析您的请求"},
{"Addresshelper is not supported", "不支持地址助手"}, {"addresshelper is not supported", "不支持地址助手"},
{"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>.", "主机 %s <font color=red>已在路由地址簿中</font>。<b>请注意:此地址的来源可能是有害的!</b>点击此处更新记录:<a href=\"%s%s%s&update=true\">继续</a>"}, {"Host", "主机"},
{"Addresshelper forced update rejected", "地址助手强制更新被拒绝"}, {"added to router's addressbook from helper", "将此地址从地址助手添加到路由地址簿"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "若要在路由器地址簿中添加主机 <b>%s</b> 请点击这里: <a href=\"%s%s%s\">继续</a>"}, {"Click here to proceed:", "点击此处继续:"},
{"Addresshelper request", "请求地址助手"}, {"Continue", "继续"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "主机 %s 已通过地址助手添加到路由地址簿中。点击此处继续:<a href=\"%s\">继续</a>"}, {"Addresshelper found", "已找到地址助手"},
{"Addresshelper adding", "正在添加地址助手"}, {"already in router's addressbook", "已在路由地址簿中"},
{"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>.", "主机 %s <font color=red>已在路由地址簿中</font>。点击此处更新记录:<a href=\"%s%s%s&update=true\">继续</a>"}, {"Click here to update record:", "点击此处更新地址簿记录"},
{"Addresshelper update", "更新地址助手"}, {"invalid request uri", "无效的 URL 请求"},
{"Invalid request URI", "无效的 URI 请求"},
{"Can't detect destination host from request", "无法从请求中检测到目标主机"}, {"Can't detect destination host from request", "无法从请求中检测到目标主机"},
{"Outproxy failure", "出口代理故障"}, {"Outproxy failure", "出口代理故障"},
{"Bad outproxy settings", "错误的出口代理设置"}, {"bad outproxy settings", "错误的出口代理设置"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "主机 %s 不在 I2P 网络内,但出口代理未启用"}, {"not inside I2P network, but outproxy is not enabled", "该地址不在 I2P 网络内,但未启用出口代理"},
{"Unknown outproxy URL", "未知的出口代理地址"}, {"unknown outproxy url", "未知的出口代理地址"},
{"Cannot resolve upstream proxy", "无法解析上游代理"}, {"cannot resolve upstream proxy", "无法解析上游代理"},
{"Hostname is too long", "主机名过长"}, {"hostname too long", "主机名过长"},
{"Cannot connect to upstream SOCKS proxy", "无法连接到上游 SOCKS 代理"}, {"cannot connect to upstream socks proxy", "无法连接到上游 socks 代理"},
{"Cannot negotiate with SOCKS proxy", "无法与 SOCKS 代理协商"}, {"Cannot negotiate with socks proxy", "无法与 socks 代理协商"},
{"CONNECT error", "连接错误"}, {"CONNECT error", "连接错误"},
{"Failed to connect", "连接失败"}, {"Failed to Connect", "连接失败"},
{"SOCKS proxy error", "SOCKS 代理错误"}, {"socks proxy error", "socks 代理错误"},
{"Failed to send request to upstream", "向上游发送请求失败"}, {"failed to send request to upstream", "向上游发送请求失败"},
{"No reply from SOCKS proxy", "没有来自 SOCKS 代理的回复"}, {"No Reply From socks proxy", "没有来自 socks 代理的回复"},
{"Cannot connect", "无法连接"}, {"cannot connect", "无法连接"},
{"HTTP out proxy not implemented", "HTTP 出口代理未实现"}, {"http out proxy not implemented", "http 出口代理未实现"},
{"Cannot connect to upstream HTTP proxy", "无法连接到上游 HTTP 代理"}, {"cannot connect to upstream http proxy", "无法连接到上游 http 代理"},
{"Host is down", "主机已关闭"}, {"Host is down", "主机已关闭"},
{"Can't create connection to requested host, it may be down. Please try again later.", "无法创建到目标主机的连接。主机可能已下线,请稍后再试。"}, {"Can't create connection to requested host, it may be down. Please try again later.", "无法创建到目标主机的连接。主机可能已下线,请稍后再试。"},
{"", ""}, {"", ""},
@@ -202,10 +200,10 @@ namespace chinese // language namespace
static std::map<std::string, std::vector<std::string>> plurals static std::map<std::string, std::vector<std::string>> plurals
{ {
{"%d days", {"%d 天"}}, {"days", {""}},
{"%d hours", {"%d 小"}}, {"hours", {""}},
{"%d minutes", {"%d 分钟"}}, {"minutes", {""}},
{"%d seconds", {"%d "}}, {"seconds", {""}},
{"", {""}}, {"", {""}},
}; };

View File

@@ -1,204 +0,0 @@
/*
* Copyright (c) 2022-2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#include <map>
#include <vector>
#include <string>
#include <memory>
#include "I18N.h"
// Czech localization file
namespace i2p
{
namespace i18n
{
namespace czech // language namespace
{
// language name in lowercase
static std::string language = "czech";
// See for language plural forms here:
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
static int plural (int n) {
return (n == 1) ? 0 : (n >= 2 && n <= 4) ? 1 : 2;
}
static std::map<std::string, std::string> strings
{
{"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"},
{"%.2f GiB", "%.2f GiB"},
{"building", "vytváří se"},
{"failed", "selhalo"},
{"expiring", "končící"},
{"established", "vytvořeno"},
{"unknown", "neznámý"},
{"exploratory", "průzkumné"},
{"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", "Lokální destinace"},
{"LeaseSets", "LeaseSety"},
{"Tunnels", "Tunely"},
{"Transit Tunnels", "Transitní tunely"},
{"Transports", "Transporty"},
{"I2P tunnels", "I2P tunely"},
{"SAM sessions", "SAM relace"},
{"ERROR", "CHYBA"},
{"OK", "OK"},
{"Testing", "Testuji"},
{"Firewalled", "Za Firewallem"},
{"Unknown", "Neznámý"},
{"Proxy", "Proxy"},
{"Mesh", "Síť"},
{"Clock skew", "Časová nesrovnalost"},
{"Offline", "Offline"},
{"Symmetric NAT", "Symetrický NAT"},
{"Uptime", "Doba provozu"},
{"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ů"},
{"Received", "Přijato"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "Odesláno"},
{"Transit", "Tranzit"},
{"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ů"},
{"Version", "Verze"},
{"Our external address", "Naše externí adresa"},
{"supported", "podporováno"},
{"Routers", "Routery"},
{"Floodfills", "Floodfilly"},
{"Client Tunnels", "Klientské tunely"},
{"Services", "Služby"},
{"Enabled", "Zapnuto"},
{"Disabled", "Vypnuto"},
{"Encrypted B33 address", "Šifrovaná adresa B33"},
{"Address registration line", "Registrační řádek adresy"},
{"Domain", "Doména"},
{"Generate", "Vygenerovat"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Poznámka:</b> výsledný řetězec může být použit pouze pro registraci 2LD domén (example.i2p). Pro registraci subdomén použijte prosím i2pd-tools."},
{"Address", "Adresa"},
{"Type", "Typ"},
{"EncType", "EncType"},
{"Inbound tunnels", "Příchozí tunely"},
{"%dms", "%dms"},
{"Outbound tunnels", "Odchozí tunely"},
{"Tags", "Štítky"},
{"Incoming", "Příchozí"},
{"Outgoing", "Odchozí"},
{"Destination", "Destinace"},
{"Amount", "Množství"},
{"Incoming Tags", "Příchozí štítky"},
{"Tags sessions", "Relace štítků"},
{"Status", "Status"},
{"Local Destination", "Lokální Destinace"},
{"Streams", "Toky"},
{"Close stream", "Uzavřít tok"},
{"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", "Nevypršené Leasy"},
{"Gateway", "Brána"},
{"TunnelID", "ID tunelu"},
{"EndDate", "Datum ukončení"},
{"Queue size", "Velikost fronty"},
{"Run peer test", "Spustit peer test"},
{"Decline transit tunnels", "Odmítnout tranzitní tunely"},
{"Accept transit tunnels", "Přijmout tranzitní tunely"},
{"Cancel graceful shutdown", "Zrušit hladké vypnutí"},
{"Start graceful shutdown", "Zahájit hladké vypnutí"},
{"Force shutdown", "Vynutit vypnutí"},
{"Reload external CSS styles", "Znovu načíst externí CSS"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Poznámka:</b> žádná vykonaná akce zde není trvalá a nemění konfigurační soubory."},
{"Logging level", "Úroveň logování"},
{"Transit tunnels limit", "Limit tranzitních tunelů"},
{"Change", "Změnit"},
{"Change language", "Změnit jazyk"},
{"no transit tunnels currently built", "Žádný tranzitní tunel není momentálně vytvořen"},
{"SAM disabled", "SAM vypnutý"},
{"no sessions currently running", "Momentálně nejsou spuštěné žádné relace"},
{"SAM session not found", "SAM relace nenalezena"},
{"SAM Session", "SAM Relace"},
{"Server Tunnels", "Server Tunely"},
{"Client Forwards", "Přesměrování Klienta"},
{"Server Forwards", "Přesměrování Serveru"},
{"Unknown page", "Neznámá stránka"},
{"Invalid token", "Neplatný token"},
{"SUCCESS", "ÚSPĚCH"},
{"Stream closed", "Tok uzavřen"},
{"Stream not found or already was closed", "Tok nenalezen nebo byl již uzavřen"},
{"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í"},
{"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"},
{"Proxy info", "Proxy informace"},
{"Proxy error: Host not found", "Chyba proxy serveru: Hostitel nenalezen"},
{"Remote host not found in router's addressbook", "Vzdálený hostitel nebyl nalezen v adresáři routeru"},
{"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"},
{"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í"},
{"Bad outproxy settings", "Špatné outproxy nastavení"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Hostitel %s není uvnitř I2P sítě a outproxy není nastavena"},
{"Unknown outproxy URL", "Neznámá outproxy URL"},
{"Cannot resolve upstream proxy", "Nelze rozluštit upstream proxy server"},
{"Hostname is too long", "Název hostitele je příliš dlouhý"},
{"Cannot connect to upstream SOCKS proxy", "Nelze se připojit k upstream SOCKS proxy serveru"},
{"Cannot negotiate with SOCKS proxy", "Nelze vyjednávat se SOCKS proxy serverem"},
{"CONNECT error", "Chyba PŘIPOJENÍ"},
{"Failed to connect", "Připojení se nezdařilo"},
{"SOCKS proxy error", "Chyba SOCKS proxy serveru"},
{"Failed to send request to upstream", "Odeslání žádosti upstream serveru se nezdařilo"},
{"No reply from SOCKS proxy", "Žádná odpověď od SOCKS proxy serveru"},
{"Cannot connect", "Nelze se připojit"},
{"HTTP out proxy not implemented", "HTTP out proxy není implementován"},
{"Cannot connect to upstream HTTP proxy", "Nelze se připojit k upstream HTTP proxy serveru"},
{"Host is down", "Hostitel je nedostupný"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Připojení k požadovanému hostiteli nelze vytvořit, může být nedostupný. Zkuste to, prosím, znovu později."},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"%d days", {"%d den", "%d dny", "%d dní", "%d dní"}},
{"%d hours", {"%d hodina", "%d hodiny", "%d hodin", "%d hodin"}},
{"%d minutes", {"%d minuta", "%d minuty", "%d minut", "%d minut"}},
{"%d seconds", {"%d vteřina", "%d vteřiny", "%d vteřin", "%d vteřin"}},
{"", {"", "", "", ""}},
};
std::shared_ptr<const i2p::i18n::Locale> GetLocale()
{
return std::make_shared<i2p::i18n::Locale>(language, strings, plurals, [] (int n)->int { return plural(n); });
}
} // language
} // i18n
} // i2p

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022-2023, The PurpleI2P Project * Copyright (c) 2022, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -31,9 +31,9 @@ namespace french // language namespace
static std::map<std::string, std::string> strings static std::map<std::string, std::string> strings
{ {
{"%.2f KiB", "%.2f Kio"}, {"KiB", "Kio"},
{"%.2f MiB", "%.2f Mio"}, {"MiB", "Mio"},
{"%.2f GiB", "%.2f Gio"}, {"GiB", "Gio"},
{"building", "En construction"}, {"building", "En construction"},
{"failed", "échoué"}, {"failed", "échoué"},
{"expiring", "expiré"}, {"expiring", "expiré"},
@@ -58,11 +58,10 @@ namespace french // language namespace
{"Unknown", "Inconnu"}, {"Unknown", "Inconnu"},
{"Proxy", "Proxy"}, {"Proxy", "Proxy"},
{"Mesh", "Maillé"}, {"Mesh", "Maillé"},
{"Error", "Erreur"},
{"Clock skew", "Horloge décalée"}, {"Clock skew", "Horloge décalée"},
{"Offline", "Hors ligne"}, {"Offline", "Hors ligne"},
{"Symmetric NAT", "NAT symétrique"}, {"Symmetric NAT", "NAT symétrique"},
{"Full cone NAT", "NAT à cône complet"},
{"No Descriptors", "Aucuns Descripteurs"},
{"Uptime", "Temps de fonctionnement"}, {"Uptime", "Temps de fonctionnement"},
{"Network status", "État du réseau"}, {"Network status", "État du réseau"},
{"Network status v6", "État du réseau v6"}, {"Network status v6", "État du réseau v6"},
@@ -70,7 +69,7 @@ namespace french // language namespace
{"Family", "Famille"}, {"Family", "Famille"},
{"Tunnel creation success rate", "Taux de succès de création de tunnels"}, {"Tunnel creation success rate", "Taux de succès de création de tunnels"},
{"Received", "Reçu"}, {"Received", "Reçu"},
{"%.2f KiB/s", "%.2f Kio/s"}, {"KiB/s", "kio/s"},
{"Sent", "Envoyé"}, {"Sent", "Envoyé"},
{"Transit", "Transité"}, {"Transit", "Transité"},
{"Data path", "Emplacement des données"}, {"Data path", "Emplacement des données"},
@@ -82,7 +81,6 @@ namespace french // language namespace
{"Our external address", "Notre adresse externe"}, {"Our external address", "Notre adresse externe"},
{"supported", "supporté"}, {"supported", "supporté"},
{"Routers", "Routeurs"}, {"Routers", "Routeurs"},
{"Floodfills", "Remplisseurs"},
{"Client Tunnels", "Tunnels clients"}, {"Client Tunnels", "Tunnels clients"},
{"Services", "Services"}, {"Services", "Services"},
{"Enabled", "Activé"}, {"Enabled", "Activé"},
@@ -94,9 +92,8 @@ namespace french // language namespace
{"<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"}, {"Address", "Adresse"},
{"Type", "Type"}, {"Type", "Type"},
{"EncType", "EncType"},
{"Inbound tunnels", "Tunnels entrants"}, {"Inbound tunnels", "Tunnels entrants"},
{"%dms", "%dms"}, {"ms", "ms"},
{"Outbound tunnels", "Tunnels sortants"}, {"Outbound tunnels", "Tunnels sortants"},
{"Tags", "Balises"}, {"Tags", "Balises"},
{"Incoming", "Entrant"}, {"Incoming", "Entrant"},
@@ -118,10 +115,8 @@ namespace french // language namespace
{"Gateway", "Passerelle"}, {"Gateway", "Passerelle"},
{"TunnelID", "ID du tunnel"}, {"TunnelID", "ID du tunnel"},
{"EndDate", "Date de fin"}, {"EndDate", "Date de fin"},
{"floodfill mode is disabled", "le mode de remplissage est désactivé"},
{"Queue size", "Longueur de la file"}, {"Queue size", "Longueur de la file"},
{"Run peer test", "Lancer test des pairs"}, {"Run peer test", "Lancer test des pairs"},
{"Reload tunnels configuration", "Recharger la configuration des tunnels"},
{"Decline transit tunnels", "Refuser les tunnels transitoires"}, {"Decline transit tunnels", "Refuser les tunnels transitoires"},
{"Accept transit tunnels", "Accepter les tunnels transitoires"}, {"Accept transit tunnels", "Accepter les tunnels transitoires"},
{"Cancel graceful shutdown", "Annuler l'arrêt gracieux"}, {"Cancel graceful shutdown", "Annuler l'arrêt gracieux"},
@@ -139,8 +134,6 @@ namespace french // language namespace
{"SAM session not found", "session SAM introuvable"}, {"SAM session not found", "session SAM introuvable"},
{"SAM Session", "Session SAM"}, {"SAM Session", "Session SAM"},
{"Server Tunnels", "Tunnels serveurs"}, {"Server Tunnels", "Tunnels serveurs"},
{"Client Forwards", "Transmission du client"},
{"Server Forwards", "Transmission du serveur"},
{"Unknown page", "Page inconnue"}, {"Unknown page", "Page inconnue"},
{"Invalid token", "Jeton invalide"}, {"Invalid token", "Jeton invalide"},
{"SUCCESS", "SUCCÈS"}, {"SUCCESS", "SUCCÈS"},
@@ -149,8 +142,8 @@ namespace french // language namespace
{"Destination not found", "Destination introuvable"}, {"Destination not found", "Destination introuvable"},
{"StreamID can't be null", "StreamID ne peut pas être vide"}, {"StreamID can't be null", "StreamID ne peut pas être vide"},
{"Return to destination page", "Retourner à la page de destination"}, {"Return to destination page", "Retourner à la page de destination"},
{"You will be redirected in %d seconds", "Vous serez redirigé dans %d secondes"}, {"You will be redirected in 5 seconds", "Vous allez être redirigé dans cinq secondes"},
{"Transit tunnels count must not exceed %d", "Le nombre de tunnels de transit ne doit pas excéder %d"}, {"Transit tunnels count must not exceed 65535", "Le nombre de tunnels transitoires ne doit pas dépasser 65535"},
{"Back to commands list", "Retour à la liste des commandes"}, {"Back to commands list", "Retour à la liste des commandes"},
{"Register at reg.i2p", "Inscription à reg.i2p"}, {"Register at reg.i2p", "Inscription à reg.i2p"},
{"Description", "Description"}, {"Description", "Description"},
@@ -168,33 +161,32 @@ namespace french // language namespace
{"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"}, {"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"}, {"Invalid request", "Requête invalide"},
{"Proxy unable to parse your request", "Proxy incapable de comprendre votre requête"}, {"Proxy unable to parse your request", "Proxy incapable de comprendre votre requête"},
{"Addresshelper is not supported", "Assistant d'adresse non supporté"}, {"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", "Hôte"},
{"Addresshelper forced update rejected", "Mise à jour forcée des assistants d'adresses rejetée"}, {"added to router's addressbook from helper", "Ajouté au carnet d'adresse du routeur par l'assistant"},
{"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>."}, {"Click here to proceed:", "Cliquez ici pour continuer:"},
{"Addresshelper request", "Demande à l'assistant d'adresse"}, {"Continue", "Continuer"},
{"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 found", "Assistant d'adresse trouvé"},
{"Addresshelper adding", "Ajout de l'assistant d'adresse"}, {"already in router's addressbook", "déjà dans le carnet d'adresses du routeur"},
{"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>."}, {"Click here to update record:", "Cliquez ici pour mettre à jour le carnet d'adresse:"},
{"Addresshelper update", "Mise à jour de l'assistant d'adresse"}, {"invalid request uri", "uri de la requête invalide"},
{"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"}, {"Can't detect destination host from request", "Impossible de détecter l'hôte de destination à partir de la requête"},
{"Outproxy failure", "Échec de proxy de sortie"}, {"Outproxy failure", "Échec de proxy de sortie"},
{"Bad outproxy settings", "Mauvaise configuration du proxy de sortie"}, {"bad outproxy settings", "Mauvaise configuration du proxy de sortie"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Hôte %s pas dans le réseau I2P, mais le proxy de sortie n'est pas activé"}, {"not inside I2P network, but outproxy is not enabled", "pas dans le réseau I2P, mais le proxy de sortie n'est pas activé"},
{"Unknown outproxy URL", "URL du proxy de sortie inconnu"}, {"unknown outproxy url", "URL du proxy de sortie inconnu"},
{"Cannot resolve upstream proxy", "Impossible de résoudre l'adresse du proxy en amont"}, {"cannot resolve upstream proxy", "impossible de résoudre l'adresse du proxy en amont"},
{"Hostname is too long", "Nom d'hôte trop long"}, {"hostname too long", "nom d'hôte trop long"},
{"Cannot connect to upstream SOCKS proxy", "Impossible de se connecter au proxy SOCKS en amont"}, {"cannot connect to upstream socks proxy", "impossible de se connecter au proxy socks en amont"},
{"Cannot negotiate with SOCKS proxy", "Impossible de négocier avec le proxy SOCKS"}, {"Cannot negotiate with socks proxy", "Impossible de négocier avec le proxy socks"},
{"CONNECT error", "Erreur de connexion"}, {"CONNECT error", "Erreur de connexion"},
{"Failed to connect", "Échec de connexion"}, {"Failed to Connect", "Échec de connexion"},
{"SOCKS proxy error", "Erreur de proxy SOCKS"}, {"socks proxy error", "Erreur de proxy socks"},
{"Failed to send request to upstream", "Erreur lors de l'envoie de la requête en amont"}, {"failed to send request to upstream", "Erreur lors de l'envoie de la requête en amont"},
{"No reply from SOCKS proxy", "Pas de réponse du proxy SOCKS"}, {"No Reply From socks proxy", "Pas de réponse du proxy socks"},
{"Cannot connect", "Impossible de connecter"}, {"cannot connect", "impossible de connecter"},
{"HTTP out proxy not implemented", "Proxy de sortie HTTP non implémenté"}, {"http out proxy not implemented", "Proxy de sortie HTTP non implémenté"},
{"Cannot connect to upstream HTTP proxy", "Impossible de se connecter au proxy HTTP en amont"}, {"cannot connect to upstream http proxy", "impossible de se connecter au proxy HTTP en amont"},
{"Host is down", "Hôte hors service"}, {"Host is down", "Hôte hors service"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Impossible d'établir une connexion avec l'hôte, il est peut-être hors service. Veuillez réessayer plus tard."}, {"Can't create connection to requested host, it may be down. Please try again later.", "Impossible d'établir une connexion avec l'hôte, il est peut-être hors service. Veuillez réessayer plus tard."},
{"", ""}, {"", ""},
@@ -202,10 +194,10 @@ namespace french // language namespace
static std::map<std::string, std::vector<std::string>> plurals static std::map<std::string, std::vector<std::string>> plurals
{ {
{"%d days", {"%d jour", "%d jours"}}, {"days", {"jour", "jours"}},
{"%d hours", {"%d heure", "%d heures"}}, {"hours", {"heure", "heures"}},
{"%d minutes", {"%d minute", "%d minutes"}}, {"minutes", {"minute", "minutes"}},
{"%d seconds", {"%d seconde", "%d secondes"}}, {"seconds", {"seconde", "secondes"}},
{"", {"", ""}}, {"", {"", ""}},
}; };

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022-2023, The PurpleI2P Project * Copyright (c) 2022, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -31,9 +31,9 @@ namespace german // language namespace
static std::map<std::string, std::string> strings static std::map<std::string, std::string> strings
{ {
{"%.2f KiB", "%.2f KiB"}, {"KiB", "KiB"},
{"%.2f MiB", "%.2f MiB"}, {"MiB", "MiB"},
{"%.2f GiB", "%.2f GiB"}, {"GiB", "GiB"},
{"building", "In Bau"}, {"building", "In Bau"},
{"failed", "fehlgeschlagen"}, {"failed", "fehlgeschlagen"},
{"expiring", "läuft ab"}, {"expiring", "läuft ab"},
@@ -58,10 +58,10 @@ namespace german // language namespace
{"Unknown", "Unbekannt"}, {"Unknown", "Unbekannt"},
{"Proxy", "Proxy"}, {"Proxy", "Proxy"},
{"Mesh", "Mesh"}, {"Mesh", "Mesh"},
{"Error", "Fehler"},
{"Clock skew", "Zeitabweichung"}, {"Clock skew", "Zeitabweichung"},
{"Offline", "Offline"}, {"Offline", "Offline"},
{"Symmetric NAT", "Symmetrisches NAT"}, {"Symmetric NAT", "Symmetrisches NAT"},
{"No Descriptors", "Keine Beschreibungen"},
{"Uptime", "Laufzeit"}, {"Uptime", "Laufzeit"},
{"Network status", "Netzwerkstatus"}, {"Network status", "Netzwerkstatus"},
{"Network status v6", "Netzwerkstatus v6"}, {"Network status v6", "Netzwerkstatus v6"},
@@ -69,7 +69,7 @@ namespace german // language namespace
{"Family", "Familie"}, {"Family", "Familie"},
{"Tunnel creation success rate", "Erfolgsrate der Tunnelerstellung"}, {"Tunnel creation success rate", "Erfolgsrate der Tunnelerstellung"},
{"Received", "Eingegangen"}, {"Received", "Eingegangen"},
{"%.2f KiB/s", "%.2f KiB/s"}, {"KiB/s", "KiB/s"},
{"Sent", "Gesendet"}, {"Sent", "Gesendet"},
{"Transit", "Transit"}, {"Transit", "Transit"},
{"Data path", "Datenpfad"}, {"Data path", "Datenpfad"},
@@ -95,7 +95,7 @@ namespace german // language namespace
{"Type", "Typ"}, {"Type", "Typ"},
{"EncType", "Verschlüsselungstyp"}, {"EncType", "Verschlüsselungstyp"},
{"Inbound tunnels", "Eingehende Tunnel"}, {"Inbound tunnels", "Eingehende Tunnel"},
{"%dms", "%dms"}, {"ms", "ms"},
{"Outbound tunnels", "Ausgehende Tunnel"}, {"Outbound tunnels", "Ausgehende Tunnel"},
{"Tags", "Tags"}, {"Tags", "Tags"},
{"Incoming", "Eingehend"}, {"Incoming", "Eingehend"},
@@ -117,10 +117,9 @@ namespace german // language namespace
{"Gateway", "Gateway"}, {"Gateway", "Gateway"},
{"TunnelID", "TunnelID"}, {"TunnelID", "TunnelID"},
{"EndDate", "Enddatum"}, {"EndDate", "Enddatum"},
{"floodfill mode is disabled", "Floodfill Modus ist deaktiviert"}, {"not floodfill", "kein Floodfill"},
{"Queue size", "Größe der Warteschlange"}, {"Queue size", "Größe der Warteschlange"},
{"Run peer test", "Peer-Test durchführen"}, {"Run peer test", "Peer-Test durchführen"},
{"Reload tunnels configuration", "Tunnel Konfiguration neu laden"},
{"Decline transit tunnels", "Transittunnel ablehnen"}, {"Decline transit tunnels", "Transittunnel ablehnen"},
{"Accept transit tunnels", "Transittunnel akzeptieren"}, {"Accept transit tunnels", "Transittunnel akzeptieren"},
{"Cancel graceful shutdown", "Beende das kontrollierte Herunterfahren"}, {"Cancel graceful shutdown", "Beende das kontrollierte Herunterfahren"},
@@ -148,8 +147,8 @@ namespace german // language namespace
{"Destination not found", "Ziel nicht gefunden"}, {"Destination not found", "Ziel nicht gefunden"},
{"StreamID can't be null", "StreamID kann nicht null sein"}, {"StreamID can't be null", "StreamID kann nicht null sein"},
{"Return to destination page", "Zurück zur Ziel-Seite"}, {"Return to destination page", "Zurück zur Ziel-Seite"},
{"You will be redirected in %d seconds", "Du wirst umgeleitet in %d Sekunden"}, {"You will be redirected in 5 seconds", "Du wirst in 5 Sekunden weitergeleitet"},
{"Transit tunnels count must not exceed %d", "Die Anzahl der Transittunnel darf nicht über %d gehen"}, {"Transit tunnels count must not exceed 65535", "Es darf maximal 65535 Transittunnel geben"},
{"Back to commands list", "Zurück zur Befehlsliste"}, {"Back to commands list", "Zurück zur Befehlsliste"},
{"Register at reg.i2p", "Auf reg.i2p registrieren"}, {"Register at reg.i2p", "Auf reg.i2p registrieren"},
{"Description", "Beschreibung"}, {"Description", "Beschreibung"},
@@ -167,33 +166,32 @@ 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"}, {"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"}, {"Invalid request", "Ungültige Anfrage"},
{"Proxy unable to parse your request", "Proxy konnte die Anfrage nicht verarbeiten"}, {"Proxy unable to parse your request", "Proxy konnte die Anfrage nicht verarbeiten"},
{"Addresshelper is not supported", "Adresshelfer wird nicht unterstützt"}, {"addresshelper is not supported", "Addresshelfer 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>."}, {"Host", "Host"},
{"Addresshelper forced update rejected", "Adresshelfer gezwungene Aktualisierung abgelehnt"}, {"added to router's addressbook from helper", "vom Helfer zum Router-Adressbuch hinzugefügt"},
{"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>."}, {"Click here to proceed:", "Klicke hier um fortzufahren:"},
{"Addresshelper request", "Adresshelfer gefunden"}, {"Continue", "Fortsetzen"},
{"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 found", "Adresshelfer gefunden"},
{"Addresshelper adding", "Adresshelfer hinzufügen"}, {"already in router's addressbook", "bereits im Adressbuch des Routers"},
{"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>."}, {"Click here to update record:", "Klicke hier, um den Eintrag zu aktualisieren:"},
{"Addresshelper update", "Adresshelfer aktualisieren"}, {"invalid request uri", "ungültige Anfrage-URI"},
{"Invalid request URI", "Ungültige Anfrage-URI"},
{"Can't detect destination host from request", "Kann den Ziel-Host von der Anfrage nicht erkennen"}, {"Can't detect destination host from request", "Kann den Ziel-Host von der Anfrage nicht erkennen"},
{"Outproxy failure", "Outproxy-Fehler"}, {"Outproxy failure", "Outproxy-Fehler"},
{"Bad outproxy settings", "Ungültige Outproxy-Einstellungen"}, {"bad outproxy settings", "ungültige Outproxy-Einstellungen"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Host %s außerhalb des I2P-Netzwerks, aber Outproxy ist nicht aktiviert"}, {"not inside I2P network, but outproxy is not enabled", "außerhalb des I2P-Netzwerks, aber Outproxy ist nicht aktiviert"},
{"Unknown outproxy URL", "Unbekannte Outproxy-URL"}, {"unknown outproxy url", "unbekannte Outproxy-URL"},
{"Cannot resolve upstream proxy", "Kann den Upstream-Proxy nicht auflösen"}, {"cannot resolve upstream proxy", "kann den Upstream-Proxy nicht auflösen"},
{"Hostname is too long", "Hostname zu lang"}, {"hostname too long", "Hostname zu lang"},
{"Cannot connect to upstream SOCKS proxy", "Kann keine Verbindung zum Upstream-SOCKS-Proxy herstellen"}, {"cannot connect to upstream socks proxy", "Kann keine Verbindung zum Upstream-Socks-Proxy herstellen"},
{"Cannot negotiate with SOCKS proxy", "Kann nicht mit SOCKS-Proxy verhandeln"}, {"Cannot negotiate with socks proxy", "Kann nicht mit Socks-Proxy verhandeln"},
{"CONNECT error", "CONNECT-Fehler"}, {"CONNECT error", "CONNECT-Fehler"},
{"Failed to connect", "Verbindung konnte nicht hergestellt werden"}, {"Failed to Connect", "Verbindung konnte nicht hergestellt werden"},
{"SOCKS proxy error", "SOCKS-Proxy-Fehler"}, {"socks proxy error", "Socks-Proxy-Fehler"},
{"Failed to send request to upstream", "Anfrage an den Upstream zu senden ist gescheitert"}, {"failed to send request to upstream", "Anfrage an den Upstream zu senden ist gescheitert"},
{"No reply from SOCKS proxy", "Keine Antwort vom SOCKS-Proxy"}, {"No Reply From socks proxy", "Keine Antwort vom Socks-Proxy"},
{"Cannot connect", "Kann nicht verbinden"}, {"cannot connect", "kann nicht verbinden"},
{"HTTP out proxy not implemented", "HTTP-Outproxy nicht implementiert"}, {"http out proxy not implemented", "HTTP-Outproxy nicht implementiert"},
{"Cannot connect to upstream HTTP proxy", "Kann nicht zu Upstream-HTTP-Proxy verbinden"}, {"cannot connect to upstream http proxy", "Kann nicht zu Upstream-HTTP-Proxy verbinden"},
{"Host is down", "Host ist offline"}, {"Host is down", "Host ist offline"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Konnte keine Verbindung zum angefragten Host aufbauen, vielleicht ist er offline. Versuche es später noch mal."}, {"Can't create connection to requested host, it may be down. Please try again later.", "Konnte keine Verbindung zum angefragten Host aufbauen, vielleicht ist er offline. Versuche es später noch mal."},
{"", ""}, {"", ""},
@@ -201,10 +199,10 @@ namespace german // language namespace
static std::map<std::string, std::vector<std::string>> plurals static std::map<std::string, std::vector<std::string>> plurals
{ {
{"%d days", {"%d Tag", "%d Tage"}}, {"days", {"Tag", "Tage"}},
{"%d hours", {"%d Stunde", "%d Stunden"}}, {"hours", {"Stunde", "Stunden"}},
{"%d minutes", {"%d Minute", "%d Minuten"}}, {"minutes", {"Minute", "Minuten"}},
{"%d seconds", {"%d Sekunde", "%d Sekunden"}}, {"seconds", {"Sekunde", "Sekunden"}},
{"", {"", ""}}, {"", {"", ""}},
}; };

View File

@@ -1,12 +1,11 @@
/* /*
* Copyright (c) 2021-2023, The PurpleI2P Project * Copyright (c) 2021-2022, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
* See full license text in LICENSE file at top of project tree * See full license text in LICENSE file at top of project tree
*/ */
#include <clocale>
#include "ClientContext.h" #include "ClientContext.h"
#include "I18N_langs.h" #include "I18N_langs.h"
#include "I18N.h" #include "I18N.h"
@@ -19,15 +18,9 @@ namespace i18n
{ {
const auto it = i2p::i18n::languages.find(lang); const auto it = i2p::i18n::languages.find(lang);
if (it == i2p::i18n::languages.end()) // fallback if (it == i2p::i18n::languages.end()) // fallback
{
i2p::client::context.SetLanguage (i2p::i18n::english::GetLocale()); i2p::client::context.SetLanguage (i2p::i18n::english::GetLocale());
setlocale(LC_NUMERIC, "english");
}
else else
{
i2p::client::context.SetLanguage (it->second.LocaleFunc()); i2p::client::context.SetLanguage (it->second.LocaleFunc());
setlocale(LC_NUMERIC, lang.c_str()); // set decimal point based on language
}
} }
std::string translate (const std::string& arg) std::string translate (const std::string& arg)

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021-2023, The PurpleI2P Project * Copyright (c) 2021-2022, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -74,62 +74,10 @@ namespace i18n
} // i18n } // i18n
} // i2p } // i2p
/** template<typename... TArgs>
* @brief Get translation of string std::string tr (TArgs&&... args)
* @param arg String with message
*/
template<typename TValue>
std::string tr (TValue&& arg)
{ {
return i2p::i18n::translate(std::forward<TValue>(arg)); return i2p::i18n::translate(std::forward<TArgs>(args)...);
}
/**
* @brief Get translation of string and format it
* @param arg String with message
* @param args Array of arguments for string formatting
*/
template<typename TValue, typename... TArgs>
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)...);
std::string str(size, 0);
std::snprintf(&str.front(), size + 1, tr_str.c_str(), std::forward<TArgs>(args)...);
return str;
}
/**
* @brief Get translation of string with plural forms
* @param arg String with message in singular form
* @param arg2 String with message in plural form
* @param n Integer, used for selection of form
*/
template<typename TValue, typename TValue2>
std::string ntr (TValue&& arg, TValue2&& arg2, int& n)
{
return i2p::i18n::translate(std::forward<TValue>(arg), std::forward<TValue2>(arg2), std::forward<int>(n));
}
/**
* @brief Get translation of string with plural forms and format it
* @param arg String with message in singular form
* @param arg2 String with message in plural form
* @param n Integer, used for selection of form
* @param args Array of arguments for string formatting
*/
template<typename TValue, typename TValue2, typename... TArgs>
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)...);
std::string str(size, 0);
std::snprintf(&str.front(), size + 1, tr_str.c_str(), std::forward<TArgs>(args)...);
return str;
} }
#endif // __I18N_H__ #endif // __I18N_H__

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021-2023, The PurpleI2P Project * Copyright (c) 2021-2022, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -26,17 +26,12 @@ namespace i18n
namespace afrikaans { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); } namespace afrikaans { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace armenian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); } namespace armenian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace chinese { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); } namespace chinese { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace czech { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace english { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); } namespace english { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace french { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); } namespace french { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace german { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); } namespace german { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace italian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); } namespace italian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace polish { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace portuguese { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace russian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); } namespace russian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace spanish { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); } namespace spanish { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace swedish { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace turkish { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace turkmen { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); } namespace turkmen { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace ukrainian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); } namespace ukrainian { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
namespace uzbek { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); } namespace uzbek { std::shared_ptr<const i2p::i18n::Locale> GetLocale (); }
@@ -49,17 +44,12 @@ namespace i18n
{ "afrikaans", {"Afrikaans", "af", i2p::i18n::afrikaans::GetLocale} }, { "afrikaans", {"Afrikaans", "af", i2p::i18n::afrikaans::GetLocale} },
{ "armenian", {"hայերէն", "hy", i2p::i18n::armenian::GetLocale} }, { "armenian", {"hայերէն", "hy", i2p::i18n::armenian::GetLocale} },
{ "chinese", {"简体字", "zh-CN", i2p::i18n::chinese::GetLocale} }, { "chinese", {"简体字", "zh-CN", i2p::i18n::chinese::GetLocale} },
{ "czech", {"čeština", "cs", i2p::i18n::czech::GetLocale} },
{ "english", {"English", "en", i2p::i18n::english::GetLocale} }, { "english", {"English", "en", i2p::i18n::english::GetLocale} },
{ "french", {"Français", "fr", i2p::i18n::french::GetLocale} }, { "french", {"Français", "fr", i2p::i18n::french::GetLocale} },
{ "german", {"Deutsch", "de", i2p::i18n::german::GetLocale} }, { "german", {"Deutsch", "de", i2p::i18n::german::GetLocale} },
{ "italian", {"Italiano", "it", i2p::i18n::italian::GetLocale} }, { "italian", {"Italiano", "it", i2p::i18n::italian::GetLocale} },
{ "polish", {"Polski", "pl", i2p::i18n::polish::GetLocale} },
{ "portuguese", {"Português", "pt", i2p::i18n::portuguese::GetLocale} },
{ "russian", {"Русский язык", "ru", i2p::i18n::russian::GetLocale} }, { "russian", {"Русский язык", "ru", i2p::i18n::russian::GetLocale} },
{ "spanish", {"Español", "es", i2p::i18n::spanish::GetLocale} }, { "spanish", {"Español", "es", i2p::i18n::spanish::GetLocale} },
{ "swedish", {"Svenska", "sv", i2p::i18n::swedish::GetLocale} },
{ "turkish", {"Türk dili", "tr", i2p::i18n::turkish::GetLocale} },
{ "turkmen", {"Türkmen dili", "tk", i2p::i18n::turkmen::GetLocale} }, { "turkmen", {"Türkmen dili", "tk", i2p::i18n::turkmen::GetLocale} },
{ "ukrainian", {"Украї́нська мо́ва", "uk", i2p::i18n::ukrainian::GetLocale} }, { "ukrainian", {"Украї́нська мо́ва", "uk", i2p::i18n::ukrainian::GetLocale} },
{ "uzbek", {"Oʻzbek", "uz", i2p::i18n::uzbek::GetLocale} }, { "uzbek", {"Oʻzbek", "uz", i2p::i18n::uzbek::GetLocale} },

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022-2023, The PurpleI2P Project * Copyright (c) 2022, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -31,9 +31,9 @@ namespace italian // language namespace
static std::map<std::string, std::string> strings static std::map<std::string, std::string> strings
{ {
{"%.2f KiB", "%.2f KiB"}, {"KiB", "KiB"},
{"%.2f MiB", "%.2f MiB"}, {"MiB", "MiB"},
{"%.2f GiB", "%.2f GiB"}, {"GiB", "GiB"},
{"building", "in costruzione"}, {"building", "in costruzione"},
{"failed", "fallito"}, {"failed", "fallito"},
{"expiring", "in scadenza"}, {"expiring", "in scadenza"},
@@ -58,11 +58,10 @@ namespace italian // language namespace
{"Unknown", "Sconosciuto"}, {"Unknown", "Sconosciuto"},
{"Proxy", "Proxy"}, {"Proxy", "Proxy"},
{"Mesh", "Mesh"}, {"Mesh", "Mesh"},
{"Error", "Errore"},
{"Clock skew", "Orologio disallineato"}, {"Clock skew", "Orologio disallineato"},
{"Offline", "Disconnesso"}, {"Offline", "Disconnesso"},
{"Symmetric NAT", "NAT simmetrico"}, {"Symmetric NAT", "NAT simmetrico"},
{"Full cone NAT", "Cono completo NAT"},
{"No Descriptors", "Nessun descrittore"},
{"Uptime", "In funzione da"}, {"Uptime", "In funzione da"},
{"Network status", "Stato della rete"}, {"Network status", "Stato della rete"},
{"Network status v6", "Stato della rete v6"}, {"Network status v6", "Stato della rete v6"},
@@ -70,7 +69,7 @@ namespace italian // language namespace
{"Family", "Famiglia"}, {"Family", "Famiglia"},
{"Tunnel creation success rate", "Percentuale di tunnel creati con successo"}, {"Tunnel creation success rate", "Percentuale di tunnel creati con successo"},
{"Received", "Ricevuti"}, {"Received", "Ricevuti"},
{"%.2f KiB/s", "%.2f KiB/s"}, {"KiB/s", "KiB/s"},
{"Sent", "Inviati"}, {"Sent", "Inviati"},
{"Transit", "Transitati"}, {"Transit", "Transitati"},
{"Data path", "Percorso dati"}, {"Data path", "Percorso dati"},
@@ -96,7 +95,7 @@ namespace italian // language namespace
{"Type", "Tipologia"}, {"Type", "Tipologia"},
{"EncType", "Tipo di crittografia"}, {"EncType", "Tipo di crittografia"},
{"Inbound tunnels", "Tunnel in entrata"}, {"Inbound tunnels", "Tunnel in entrata"},
{"%dms", "%dms"}, {"ms", "ms"},
{"Outbound tunnels", "Tunnel in uscita"}, {"Outbound tunnels", "Tunnel in uscita"},
{"Tags", "Tag"}, {"Tags", "Tag"},
{"Incoming", "In entrata"}, {"Incoming", "In entrata"},
@@ -118,10 +117,9 @@ namespace italian // language namespace
{"Gateway", "Gateway"}, {"Gateway", "Gateway"},
{"TunnelID", "TunnelID"}, {"TunnelID", "TunnelID"},
{"EndDate", "Data di fine"}, {"EndDate", "Data di fine"},
{"floodfill mode is disabled", "la modalità floodfill è disabilitata"}, {"not floodfill", "no floodfill"},
{"Queue size", "Dimensione della coda"}, {"Queue size", "Dimensione della coda"},
{"Run peer test", "Esegui il test dei peer"}, {"Run peer test", "Esegui il test dei peer"},
{"Reload tunnels configuration", "Ricarica la configurazione dei tunnel"},
{"Decline transit tunnels", "Rifiuta tunnel di transito"}, {"Decline transit tunnels", "Rifiuta tunnel di transito"},
{"Accept transit tunnels", "Accetta tunnel di transito"}, {"Accept transit tunnels", "Accetta tunnel di transito"},
{"Cancel graceful shutdown", "Annulla l'interruzione controllata"}, {"Cancel graceful shutdown", "Annulla l'interruzione controllata"},
@@ -149,8 +147,8 @@ namespace italian // language namespace
{"Destination not found", "Destinazione non trovata"}, {"Destination not found", "Destinazione non trovata"},
{"StreamID can't be null", "Lo StreamID non può essere null"}, {"StreamID can't be null", "Lo StreamID non può essere null"},
{"Return to destination page", "Ritorna alla pagina di destinazione"}, {"Return to destination page", "Ritorna alla pagina di destinazione"},
{"You will be redirected in %d seconds", "Sarai reindirizzato tra %d secondi"}, {"You will be redirected in 5 seconds", "Verrai reindirizzato in 5 secondi"},
{"Transit tunnels count must not exceed %d", "Il conteggio dei tunnel di transito non deve superare %d"}, {"Transit tunnels count must not exceed 65535", "Il numero di tunnel di transito non può superare i 65535"},
{"Back to commands list", "Ritorna alla lista dei comandi"}, {"Back to commands list", "Ritorna alla lista dei comandi"},
{"Register at reg.i2p", "Registra a reg.i2p"}, {"Register at reg.i2p", "Registra a reg.i2p"},
{"Description", "Descrizione"}, {"Description", "Descrizione"},
@@ -168,33 +166,32 @@ 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"}, {"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"}, {"Invalid request", "Richiesta non valida"},
{"Proxy unable to parse your request", "Il proxy non è in grado di elaborare la tua richiesta"}, {"Proxy unable to parse your request", "Il proxy non è in grado di elaborare la tua richiesta"},
{"Addresshelper is not supported", "Addresshelper non è supportato"}, {"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>."}, {"Host", "Host"},
{"Addresshelper forced update rejected", "Aggiornamento forzato dell'helper degli indirizzi rifiutato"}, {"added to router's addressbook from helper", "aggiunto alla rubrica tramite l'helper"},
{"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>."}, {"Click here to proceed:", "Clicca qui per procedere:"},
{"Addresshelper request", "Richiesta di indirizzo helper"}, {"Continue", "Continua"},
{"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 found", "Addresshelper trovato"},
{"Addresshelper adding", "Aggiunta di Addresshelper"}, {"already in router's addressbook", "già presente nella rubrica del router"},
{"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>."}, {"Click here to update record:", "Clicca qui per aggiornare l'elemento:"},
{"Addresshelper update", "Aggiornamento dell'helper degli indirizzi"}, {"invalid request uri", "uri della richiesta non valido"},
{"Invalid request URI", "URI della richiesta non valido"},
{"Can't detect destination host from request", "Impossibile determinare l'host di destinazione dalla richiesta"}, {"Can't detect destination host from request", "Impossibile determinare l'host di destinazione dalla richiesta"},
{"Outproxy failure", "Fallimento del proxy di uscita"}, {"Outproxy failure", "Fallimento del proxy di uscita"},
{"Bad outproxy settings", "Impostazioni errate del proxy di uscita"}, {"bad outproxy settings", "impostazioni errate del proxy di uscita"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Host %s non all'interno della rete I2P, ma il proxy di uscita non è abilitato"}, {"not inside I2P network, but outproxy is not enabled", "non all'interno della rete I2P, ma il proxy di uscita non è abilitato"},
{"Unknown outproxy URL", "URL del proxy di uscita sconosciuto"}, {"unknown outproxy url", "url del proxy di uscita sconosciuto"},
{"Cannot resolve upstream proxy", "Impossibile identificare il flusso a monte del proxy"}, {"cannot resolve upstream proxy", "impossibile identificare il flusso a monte del proxy"},
{"Hostname is too long", "Il nome dell'host è troppo lungo"}, {"hostname too long", "il nome dell'host è troppo lungo"},
{"Cannot connect to upstream SOCKS proxy", "Impossibile connettersi al flusso a monte del proxy SOCKS"}, {"cannot connect to upstream socks proxy", "impossibile connettersi al flusso a monte del proxy socks"},
{"Cannot negotiate with SOCKS proxy", "Impossibile negoziare con il proxy SOCKS"}, {"Cannot negotiate with socks proxy", "Impossibile negoziare con il proxy socks"},
{"CONNECT error", "Errore di connessione"}, {"CONNECT error", "Errore di connessione"},
{"Failed to connect", "Connessione fallita"}, {"Failed to Connect", "Connessione fallita"},
{"SOCKS proxy error", "Errore del proxy SOCKS"}, {"socks proxy error", "errore del proxy socks"},
{"Failed to send request to upstream", "Invio della richiesta a monte non riuscito"}, {"failed to send request to upstream", "invio della richiesta a monte non riuscito"},
{"No reply from SOCKS proxy", "Nessuna risposta dal proxy SOCKS"}, {"No Reply From socks proxy", "Nessuna risposta dal proxy socks"},
{"Cannot connect", "Impossibile connettersi"}, {"cannot connect", "impossibile connettersi"},
{"HTTP out proxy not implemented", "Proxy HTTP di uscita non implementato"}, {"http out proxy not implemented", "proxy http di uscita non implementato"},
{"Cannot connect to upstream HTTP proxy", "Impossibile connettersi al flusso a monte del proxy HTTP"}, {"cannot connect to upstream http proxy", "impossibile connettersi al proxy http a monte"},
{"Host is down", "L'host è offline"}, {"Host is down", "L'host è offline"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Impossibile creare la connessione all'host richiesto, probabilmente è offline. Riprova più tardi."}, {"Can't create connection to requested host, it may be down. Please try again later.", "Impossibile creare la connessione all'host richiesto, probabilmente è offline. Riprova più tardi."},
{"", ""}, {"", ""},
@@ -202,10 +199,10 @@ namespace italian // language namespace
static std::map<std::string, std::vector<std::string>> plurals static std::map<std::string, std::vector<std::string>> plurals
{ {
{"%d days", {"%d giorno", "%d giorni"}}, {"days", {"giorno", "giorni"}},
{"%d hours", {"%d ora", "%d ore"}}, {"hours", {"ora", "ore"}},
{"%d minutes", {"%d minuto", "%d minuti"}}, {"minutes", {"minuto", "minuti"}},
{"%d seconds", {"%d secondo", "%d secondi"}}, {"seconds", {"secondo", "secondi"}},
{"", {"", ""}}, {"", {"", ""}},
}; };

View File

@@ -1,59 +0,0 @@
/*
* Copyright (c) 2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#include <map>
#include <vector>
#include <string>
#include <memory>
#include "I18N.h"
// Polish localization file
namespace i2p
{
namespace i18n
{
namespace polish // language namespace
{
// language name in lowercase
static std::string language = "polish";
// See for language plural forms here:
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
static int plural (int n) {
return (n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2);
}
static std::map<std::string, std::string> strings
{
{"building", "Kompilowanie"},
{"failed", "nieudane"},
{"expiring", "wygasający"},
{"established", "ustanowiony"},
{"Main page", "Strona główna"},
{"Router commands", "Komendy routera"},
{"Tunnels", "Tunele"},
{"OK", "Ok"},
{"Uptime", "Czas pracy"},
{"Sent", "Wysłane"},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"", {"", "", ""}},
};
std::shared_ptr<const i2p::i18n::Locale> GetLocale()
{
return std::make_shared<i2p::i18n::Locale>(language, strings, plurals, [] (int n)->int { return plural(n); });
}
} // language
} // i18n
} // i2p

View File

@@ -1,219 +0,0 @@
/*
* Copyright (c) 2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#include <map>
#include <vector>
#include <string>
#include <memory>
#include "I18N.h"
// Portuguese localization file
namespace i2p
{
namespace i18n
{
namespace portuguese // language namespace
{
// language name in lowercase
static std::string language = "portuguese";
// See for language plural forms here:
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
static int plural (int n) {
return n != 1 ? 1 : 0;
}
static std::map<std::string, std::string> strings
{
{"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"},
{"%.2f GiB", "%.2f GiB"},
{"building", "construindo"},
{"failed", "falhou"},
{"expiring", "expirando"},
{"established", "estabelecido"},
{"unknown", "desconhecido"},
{"exploratory", "exploratório"},
{"Purple I2P Webconsole", "Webconsole Purple I2P"},
{"<b>i2pd</b> webconsole", "webconsole <b>i2pd</b>"},
{"Main page", "Página Principal"},
{"Router commands", "Comandos do Roteador"},
{"Local Destinations", "Destinos Locais"},
{"LeaseSets", "LeaseSets"},
{"Tunnels", "Túneis"},
{"Transit Tunnels", "Túneis de Trânsito"},
{"Transports", "Transportes"},
{"I2P tunnels", "Túneis I2P"},
{"SAM sessions", "Sessões do SAM"},
{"ERROR", "ERRO"},
{"OK", "OK"},
{"Testing", "Testando"},
{"Firewalled", "Sob Firewall"},
{"Unknown", "Desconhecido"},
{"Proxy", "Proxy"},
{"Mesh", "Malha"},
{"Clock skew", "Defasagem do Relógio"},
{"Offline", "Desligado"},
{"Symmetric NAT", "NAT Simétrico"},
{"Full cone NAT", "Full cone NAT"},
{"No Descriptors", "Sem Descritores"},
{"Uptime", "Tempo Ativo"},
{"Network status", "Estado da rede"},
{"Network status v6", "Estado da rede v6"},
{"Stopping in", "Parando em"},
{"Family", "Família"},
{"Tunnel creation success rate", "Taxa 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 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"},
{"Router Caps", "Limites do Roteador"},
{"Version", "Versão"},
{"Our external address", "Nosso endereço externo"},
{"supported", "suportado"},
{"Routers", "Roteadores"},
{"Floodfills", "Modo Inundação"},
{"Client Tunnels", "Túneis de Clientes"},
{"Services", "Serviços"},
{"Enabled", "Ativado"},
{"Disabled", "Desativado"},
{"Encrypted B33 address", "Endereço B33 criptografado"},
{"Address registration line", "Linha de cadastro de endereço"},
{"Domain", "Domínio"},
{"Generate", "Gerar"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b> Nota: </b>A string resultante só pode ser usada para registrar domínios 2LD (exemplo.i2p). Para registrar subdomínios por favor utilize o i2pd-tools."},
{"Address", "Endereço"},
{"Type", "Tipo"},
{"EncType", "Tipo de Criptografia"},
{"Inbound tunnels", "Túneis de Entrada"},
{"%dms", "%dms"},
{"Outbound tunnels", "Túneis de Saída"},
{"Tags", "Etiquetas"},
{"Incoming", "Entradas"},
{"Outgoing", "Saídas"},
{"Destination", "Destinos"},
{"Amount", "Quantidade"},
{"Incoming Tags", "Etiquetas de Entrada"},
{"Tags sessions", "Sessões de etiquetas"},
{"Status", "Estado"},
{"Local Destination", "Destinos Locais"},
{"Streams", "Fluxos"},
{"Close stream", "Fechar fluxo"},
{"I2CP session not found", "Sessão do I2CP não encontrada"},
{"I2CP is not enabled", "I2CP não está ativado"},
{"Invalid", "Inválido"},
{"Store type", "Tipo de armazenamento"},
{"Expires", "Expira em"},
{"Non Expired Leases", "Sessões não expiradas"},
{"Gateway", "Gateway"},
{"TunnelID", "TunnelID"},
{"EndDate", "Data final"},
{"floodfill mode is disabled", "Mode de inundação está desativado"},
{"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"},
{"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"},
{"Change", "Mudar"},
{"Change language", "Trocar idioma"},
{"no transit tunnels currently built", "Nenhum túnel de trânsito construido no momento"},
{"SAM disabled", "SAM desativado"},
{"no sessions currently running", "Nenhuma sessão funcionando no momento"},
{"SAM session not found", "Nenhuma sessão do SAM encontrada"},
{"SAM Session", "Sessão do SAM"},
{"Server Tunnels", "Túneis de Servidor"},
{"Client Forwards", "Túneis de Cliente"},
{"Server Forwards", "Encaminhamentos de Servidor"},
{"Unknown page", "Página desconhecida"},
{"Invalid token", "Token Inválido"},
{"SUCCESS", "SUCESSO"},
{"Stream closed", "Fluxo 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"},
{"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 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 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 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", "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"},
{"Hostname is too long", "O hostname é muito longo"},
{"Cannot connect to upstream SOCKS proxy", "Não é possível se conectar ao proxy SOCKS de entrada"},
{"Cannot negotiate with SOCKS proxy", "Não é possível negociar com o proxy SOCKS"},
{"CONNECT error", "Erro de CONEXÃO"},
{"Failed to connect", "Falha ao conectar"},
{"SOCKS proxy error", "Erro no proxy SOCKS"},
{"Failed to send request to upstream", "Falha ao enviar requisição para o fluxo de entrada"},
{"No reply from SOCKS proxy", "Sem resposta do proxy SOCKS"},
{"Cannot connect", "Impossível conectar"},
{"HTTP out proxy not implemented", "proxy de saída HTTP não implementado"},
{"Cannot connect to upstream HTTP proxy", "Não é possível conectar ao proxy HTTP de entrada"},
{"Host is down", "Host está desligado"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Não é possível se conectar ao host requisitado, talvez ele esteja for do ar. Por favor, tente novamente mais tarde."},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"%d days", {"%d Dia", "%d Dias"}},
{"%d hours", {"%d hora", "%d horas"}},
{"%d minutes", {"%d minuto", "%d minutos"}},
{"%d seconds", {"%d Segundo", "%d segundos"}},
{"", {"", ""}},
};
std::shared_ptr<const i2p::i18n::Locale> GetLocale()
{
return std::make_shared<i2p::i18n::Locale>(language, strings, plurals, [] (int n)->int { return plural(n); });
}
} // language
} // i18n
} // i2p

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021-2023, The PurpleI2P Project * Copyright (c) 2021, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -31,16 +31,15 @@ namespace russian // language namespace
static std::map<std::string, std::string> strings static std::map<std::string, std::string> strings
{ {
{"%.2f KiB", "%.2f КиБ"}, {"KiB", "КиБ"},
{"%.2f MiB", "%.2f МиБ"}, {"MiB", "МиБ"},
{"%.2f GiB", "%.2f ГиБ"}, {"GiB", "ГиБ"},
{"building", "строится"}, {"building", "строится"},
{"failed", "неудачный"}, {"failed", "неудачный"},
{"expiring", "истекает"}, {"expiring", "истекает"},
{"established", "работает"}, {"established", "работает"},
{"unknown", "неизвестно"}, {"unknown", "неизвестно"},
{"exploratory", "исследовательский"}, {"exploratory", "исследовательский"},
{"Purple I2P Webconsole", "Веб-консоль Purple I2P"},
{"<b>i2pd</b> webconsole", "Веб-консоль <b>i2pd</b>"}, {"<b>i2pd</b> webconsole", "Веб-консоль <b>i2pd</b>"},
{"Main page", "Главная"}, {"Main page", "Главная"},
{"Router commands", "Команды роутера"}, {"Router commands", "Команды роутера"},
@@ -58,11 +57,10 @@ namespace russian // language namespace
{"Unknown", "Неизвестно"}, {"Unknown", "Неизвестно"},
{"Proxy", "Прокси"}, {"Proxy", "Прокси"},
{"Mesh", "MESH-сеть"}, {"Mesh", "MESH-сеть"},
{"Error", "Ошибка"},
{"Clock skew", "Не точное время"}, {"Clock skew", "Не точное время"},
{"Offline", "Оффлайн"}, {"Offline", "Оффлайн"},
{"Symmetric NAT", "Симметричный NAT"}, {"Symmetric NAT", "Симметричный NAT"},
{"Full cone NAT", "Full cone NAT"},
{"No Descriptors", "Нет дескрипторов"},
{"Uptime", "В сети"}, {"Uptime", "В сети"},
{"Network status", "Сетевой статус"}, {"Network status", "Сетевой статус"},
{"Network status v6", "Сетевой статус v6"}, {"Network status v6", "Сетевой статус v6"},
@@ -70,7 +68,7 @@ namespace russian // language namespace
{"Family", "Семейство"}, {"Family", "Семейство"},
{"Tunnel creation success rate", "Успешно построенных туннелей"}, {"Tunnel creation success rate", "Успешно построенных туннелей"},
{"Received", "Получено"}, {"Received", "Получено"},
{"%.2f KiB/s", "%.2f КиБ/с"}, {"KiB/s", "КиБ/с"},
{"Sent", "Отправлено"}, {"Sent", "Отправлено"},
{"Transit", "Транзит"}, {"Transit", "Транзит"},
{"Data path", "Путь к данным"}, {"Data path", "Путь к данным"},
@@ -96,7 +94,7 @@ namespace russian // language namespace
{"Type", "Тип"}, {"Type", "Тип"},
{"EncType", "ТипШифр"}, {"EncType", "ТипШифр"},
{"Inbound tunnels", "Входящие туннели"}, {"Inbound tunnels", "Входящие туннели"},
{"%dms", "%dмс"}, {"ms", "мс"},
{"Outbound tunnels", "Исходящие туннели"}, {"Outbound tunnels", "Исходящие туннели"},
{"Tags", "Теги"}, {"Tags", "Теги"},
{"Incoming", "Входящие"}, {"Incoming", "Входящие"},
@@ -118,10 +116,9 @@ namespace russian // language namespace
{"Gateway", "Шлюз"}, {"Gateway", "Шлюз"},
{"TunnelID", "ID туннеля"}, {"TunnelID", "ID туннеля"},
{"EndDate", "Заканчивается"}, {"EndDate", "Заканчивается"},
{"floodfill mode is disabled", "режим флудфила отключен"}, {"not floodfill", "не флудфил"},
{"Queue size", "Размер очереди"}, {"Queue size", "Размер очереди"},
{"Run peer test", "Запустить тестирование"}, {"Run peer test", "Запустить тестирование"},
{"Reload tunnels configuration", "Перезагрузить конфигурацию туннелей"},
{"Decline transit tunnels", "Отклонять транзитные туннели"}, {"Decline transit tunnels", "Отклонять транзитные туннели"},
{"Accept transit tunnels", "Принимать транзитные туннели"}, {"Accept transit tunnels", "Принимать транзитные туннели"},
{"Cancel graceful shutdown", "Отменить плавную остановку"}, {"Cancel graceful shutdown", "Отменить плавную остановку"},
@@ -149,8 +146,8 @@ namespace russian // language namespace
{"Destination not found", "Точка назначения не найдена"}, {"Destination not found", "Точка назначения не найдена"},
{"StreamID can't be null", "StreamID не может быть пустым"}, {"StreamID can't be null", "StreamID не может быть пустым"},
{"Return to destination page", "Вернуться на страницу точки назначения"}, {"Return to destination page", "Вернуться на страницу точки назначения"},
{"You will be redirected in %d seconds", "Вы будете переадресованы через %d секунд"}, {"You will be redirected in 5 seconds", "Вы будете переадресованы через 5 секунд"},
{"Transit tunnels count must not exceed %d", "Число транзитных туннелей не должно превышать %d"}, {"Transit tunnels count must not exceed 65535", "Число транзитных туннелей не должно превышать 65535"},
{"Back to commands list", "Вернуться к списку команд"}, {"Back to commands list", "Вернуться к списку команд"},
{"Register at reg.i2p", "Зарегистрировать на reg.i2p"}, {"Register at reg.i2p", "Зарегистрировать на reg.i2p"},
{"Description", "Описание"}, {"Description", "Описание"},
@@ -168,33 +165,32 @@ namespace russian // language namespace
{"You may try to find this host on jump services below", "Вы можете попробовать найти узел через джамп сервисы ниже"}, {"You may try to find this host on jump services below", "Вы можете попробовать найти узел через джамп сервисы ниже"},
{"Invalid request", "Некорректный запрос"}, {"Invalid request", "Некорректный запрос"},
{"Proxy unable to parse your request", "Прокси не может разобрать ваш запрос"}, {"Proxy unable to parse your request", "Прокси не может разобрать ваш запрос"},
{"Addresshelper is not supported", "Addresshelper не поддерживается"}, {"addresshelper is not supported", "addresshelper не поддерживается"},
{"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>.", "Узел %s <font color=red>уже в адресной книге роутера</font>. <b>Будьте осторожны: источник данной ссылки может быть вредоносным!</b> Нажмите здесь, чтобы обновить запись: <a href=\"%s%s%s&update=true\">Продолжить</a>."}, {"Host", "Узел"},
{"Addresshelper forced update rejected", "Принудительное обновление через Addresshelper отклонено"}, {"added to router's addressbook from helper", "добавлен в адресную книгу роутера через хелпер"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Чтобы добавить узел <b>%s</b> в адресную книгу роутера, нажмите здесь: <a href=\"%s%s%s\"родолжить</a>."}, {"Click here to proceed:", "Нажмите здесь, чтобы продолжить:"},
{"Addresshelper request", "Запрос добавления Addresshelper"}, {"Continue", "Продолжить"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "Узел %s добавлен в адресную книгу роутера через хелпер. Нажмите здесь, чтобы продолжить: <a href=\"%s\">Продолжить</a>."}, {"Addresshelper found", "Найден addresshelper"},
{"Addresshelper adding", "Добавление Addresshelper"}, {"already in router's addressbook", "уже в адресной книге роутера"},
{"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>.", "Узел %s <font color=red>уже в адресной книге роутера</font>. Нажмите здесь, чтобы обновить запись: <a href=\"%s%s%s&update=true\">Продолжить</a>."}, {"Click here to update record:", "Нажмите здесь, чтобы обновить запись:"},
{"Addresshelper update", "Обновление записи через Addresshelper"}, {"invalid request uri", "некорректный URI запроса"},
{"Invalid request URI", "Некорректный URI запроса"},
{"Can't detect destination host from request", "Не удалось определить адрес назначения из запроса"}, {"Can't detect destination host from request", "Не удалось определить адрес назначения из запроса"},
{"Outproxy failure", "Ошибка внешнего прокси"}, {"Outproxy failure", "Ошибка внешнего прокси"},
{"Bad outproxy settings", "Некорректные настройки внешнего прокси"}, {"bad outproxy settings", "некорректные настройки внешнего прокси"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Узел %s не в I2P сети, но внешний прокси не включен"}, {"not inside I2P network, but outproxy is not enabled", "не в I2P сети, но внешний прокси не включен"},
{"Unknown outproxy URL", "Неизвестный URL внешнего прокси"}, {"unknown outproxy url", "неизвестный URL внешнего прокси"},
{"Cannot resolve upstream proxy", "Не удается определить вышестоящий прокси"}, {"cannot resolve upstream proxy", "не удается определить вышестоящий прокси"},
{"Hostname is too long", "Имя хоста слишком длинное"}, {"hostname too long", "имя хоста слишком длинное"},
{"Cannot connect to upstream SOCKS proxy", "Не удалось подключиться к вышестоящему SOCKS прокси серверу"}, {"cannot connect to upstream socks proxy", "не удается подключиться к вышестоящему SOCKS прокси"},
{"Cannot negotiate with SOCKS proxy", "Не удается договориться с вышестоящим SOCKS прокси"}, {"Cannot negotiate with socks proxy", "Не удается договориться с вышестоящим SOCKS прокси"},
{"CONNECT error", "Ошибка CONNECT запроса"}, {"CONNECT error", "Ошибка CONNECT запроса"},
{"Failed to connect", "Не удалось соединиться"}, {"Failed to Connect", "Не удалось подключиться"},
{"SOCKS proxy error", "Ошибка SOCKS прокси"}, {"socks proxy error", "ошибка SOCKS прокси"},
{"Failed to send request to upstream", "Не удалось отправить запрос вышестоящему прокси серверу"}, {"failed to send request to upstream", "не удалось отправить запрос вышестоящему прокси"},
{"No reply from SOCKS proxy", "Нет ответа от SOCKS прокси сервера"}, {"No Reply From socks proxy", "Нет ответа от SOCKS прокси сервера"},
{"Cannot connect", "Не удалось подключиться"}, {"cannot connect", "не удалось подключиться"},
{"HTTP out proxy not implemented", "Поддержка внешнего HTTP прокси сервера не реализована"}, {"http out proxy not implemented", "поддержка внешнего HTTP прокси сервера не реализована"},
{"Cannot connect to upstream HTTP proxy", "Не удалось подключиться к вышестоящему HTTP прокси серверу"}, {"cannot connect to upstream http proxy", "не удалось подключиться к вышестоящему HTTP прокси серверу"},
{"Host is down", "Узел недоступен"}, {"Host is down", "Узел недоступен"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Не удалось установить соединение к запрошенному узлу, возможно он не в сети. Попробуйте повторить запрос позже."}, {"Can't create connection to requested host, it may be down. Please try again later.", "Не удалось установить соединение к запрошенному узлу, возможно он не в сети. Попробуйте повторить запрос позже."},
{"", ""}, {"", ""},
@@ -202,10 +198,10 @@ namespace russian // language namespace
static std::map<std::string, std::vector<std::string>> plurals static std::map<std::string, std::vector<std::string>> plurals
{ {
{"%d days", {"%d день", "%d дня", "%d дней"}}, {"days", {"день", "дня", "дней"}},
{"%d hours", {"%d час", "%d часа", "%d часов"}}, {"hours", {"час", "часа", "часов"}},
{"%d minutes", {"%d минуту", "%d минуты", "%d минут"}}, {"minutes", {"минуту", "минуты", "минут"}},
{"%d seconds", {"%d секунду", "%d секунды", "%d секунд"}}, {"seconds", {"секунду", "секунды", "секунд"}},
{"", {"", "", ""}}, {"", {"", "", ""}},
}; };

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022-2023, The PurpleI2P Project * Copyright (c) 2022, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -31,9 +31,9 @@ namespace spanish // language namespace
static std::map<std::string, std::string> strings static std::map<std::string, std::string> strings
{ {
{"%.2f KiB", "%.2f KiB"}, {"KiB", "KiB"},
{"%.2f MiB", "%.2f MiB"}, {"MiB", "MiB"},
{"%.2f GiB", "%.2f GiB"}, {"GiB", "GiB"},
{"building", "pendiente"}, {"building", "pendiente"},
{"failed", "fallido"}, {"failed", "fallido"},
{"expiring", "expiró"}, {"expiring", "expiró"},
@@ -58,6 +58,7 @@ namespace spanish // language namespace
{"Unknown", "Desconocido"}, {"Unknown", "Desconocido"},
{"Proxy", "Proxy"}, {"Proxy", "Proxy"},
{"Mesh", "Malla"}, {"Mesh", "Malla"},
{"Error", "Error"},
{"Clock skew", "Reloj desfasado"}, {"Clock skew", "Reloj desfasado"},
{"Offline", "Desconectado"}, {"Offline", "Desconectado"},
{"Symmetric NAT", "NAT simétrico"}, {"Symmetric NAT", "NAT simétrico"},
@@ -68,7 +69,7 @@ namespace spanish // language namespace
{"Family", "Familia"}, {"Family", "Familia"},
{"Tunnel creation success rate", "Tasa de éxito de creación de túneles"}, {"Tunnel creation success rate", "Tasa de éxito de creación de túneles"},
{"Received", "Recibido"}, {"Received", "Recibido"},
{"%.2f KiB/s", "%.2f KiB/s"}, {"KiB/s", "KiB/s"},
{"Sent", "Enviado"}, {"Sent", "Enviado"},
{"Transit", "Tránsito"}, {"Transit", "Tránsito"},
{"Data path", "Ruta de datos"}, {"Data path", "Ruta de datos"},
@@ -94,7 +95,7 @@ namespace spanish // language namespace
{"Type", "Tipo"}, {"Type", "Tipo"},
{"EncType", "TipoEncrip"}, {"EncType", "TipoEncrip"},
{"Inbound tunnels", "Túneles entrantes"}, {"Inbound tunnels", "Túneles entrantes"},
{"%dms", "%dms"}, {"ms", "ms"},
{"Outbound tunnels", "Túneles salientes"}, {"Outbound tunnels", "Túneles salientes"},
{"Tags", "Etiquetas"}, {"Tags", "Etiquetas"},
{"Incoming", "Entrante"}, {"Incoming", "Entrante"},
@@ -116,6 +117,7 @@ namespace spanish // language namespace
{"Gateway", "Puerta de enlace"}, {"Gateway", "Puerta de enlace"},
{"TunnelID", "TunnelID"}, {"TunnelID", "TunnelID"},
{"EndDate", "FechaVenc"}, {"EndDate", "FechaVenc"},
{"not floodfill", "no inundado"},
{"Queue size", "Tamaño de cola"}, {"Queue size", "Tamaño de cola"},
{"Run peer test", "Ejecutar prueba de par"}, {"Run peer test", "Ejecutar prueba de par"},
{"Decline transit tunnels", "Rechazar túneles de tránsito"}, {"Decline transit tunnels", "Rechazar túneles de tránsito"},
@@ -145,6 +147,8 @@ namespace spanish // language namespace
{"Destination not found", "Destino no encontrado"}, {"Destination not found", "Destino no encontrado"},
{"StreamID can't be null", "StreamID no puede ser nulo"}, {"StreamID can't be null", "StreamID no puede ser nulo"},
{"Return to destination page", "Volver a la página de destino"}, {"Return to destination page", "Volver a la página de destino"},
{"You will be redirected in 5 seconds", "Serás redirigido en 5 segundos"},
{"Transit tunnels count must not exceed 65535", "La cantidad de túneles de tránsito no puede exceder 65535"},
{"Back to commands list", "Volver a lista de comandos"}, {"Back to commands list", "Volver a lista de comandos"},
{"Register at reg.i2p", "Registrar en reg.i2p"}, {"Register at reg.i2p", "Registrar en reg.i2p"},
{"Description", "Descripción"}, {"Description", "Descripción"},
@@ -162,24 +166,32 @@ namespace spanish // language namespace
{"You may try to find this host on jump services below", "Puede intentar encontrar este dominio en los siguientes servicios de salto"}, {"You may try to find this host on jump services below", "Puede intentar encontrar este dominio en los siguientes servicios de salto"},
{"Invalid request", "Solicitud inválida"}, {"Invalid request", "Solicitud inválida"},
{"Proxy unable to parse your request", "Proxy no puede procesar su solicitud"}, {"Proxy unable to parse your request", "Proxy no puede procesar su solicitud"},
{"Invalid request URI", "URI de solicitud inválida"}, {"addresshelper is not supported", "ayudante de dirección no soportado"},
{"Host", "Dominio"},
{"added to router's addressbook from helper", "añadido a la libreta de direcciones desde el ayudante"},
{"Click here to proceed:", "Haga clic aquí para continuar:"},
{"Continue", "Continuar"},
{"Addresshelper found", "Se encontró ayudante de dirección"},
{"already in router's addressbook", "ya se encontró en libreta de direcciones"},
{"Click here to update record:", "Haga clic aquí para actualizar el registro:"},
{"invalid request uri", "uri de solicitud inválida"},
{"Can't detect destination host from request", "No se puede detectar el host de destino de la solicitud"}, {"Can't detect destination host from request", "No se puede detectar el host de destino de la solicitud"},
{"Outproxy failure", "Fallo en el proxy saliente"}, {"Outproxy failure", "Fallo en el proxy saliente"},
{"Bad outproxy settings", "Configuración de outproxy incorrecta"}, {"bad outproxy settings", "configuración de outproxy incorrecta"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Dominio %s no está dentro de la red I2P, pero el proxy de salida no está activado"}, {"not inside I2P network, but outproxy is not enabled", "no está dentro de la red I2P, pero el proxy de salida no está activado"},
{"Unknown outproxy URL", "URL de proxy outproxy desconocido"}, {"unknown outproxy url", "url de proxy outproxy desconocido"},
{"Cannot resolve upstream proxy", "No se puede resolver el proxy de upstream"}, {"cannot resolve upstream proxy", "no se puede resolver el proxy de upstream"},
{"Hostname is too long", "Nombre de dominio muy largo"}, {"hostname too long", "nombre de dominio muy largo"},
{"Cannot connect to upstream SOCKS proxy", "No se puede conectar al proxy SOCKS principal"}, {"cannot connect to upstream socks proxy", "no se puede conectar al proxy socks principal"},
{"Cannot negotiate with SOCKS proxy", "No se puede negociar con el proxy SOCKS"}, {"Cannot negotiate with socks proxy", "No se puede negociar con el proxy socks"},
{"CONNECT error", "Error de CONNECT"}, {"CONNECT error", "Error de CONNECT"},
{"Failed to connect", "Error al conectar"}, {"Failed to Connect", "Error al Conectar"},
{"SOCKS proxy error", "Error de proxy SOCKS"}, {"socks proxy error", "error de proxy socks"},
{"Failed to send request to upstream", "No se pudo enviar petición al principal"}, {"failed to send request to upstream", "no se pudo enviar petición al principal"},
{"No reply from SOCKS proxy", "Sin respuesta del proxy SOCKS"}, {"No Reply From socks proxy", "Sin respuesta del proxy socks"},
{"Cannot connect", "No se puede conectar"}, {"cannot connect", "no se puede conectar"},
{"HTTP out proxy not implemented", "Proxy externo HTTP no implementado"}, {"http out proxy not implemented", "proxy externo http no implementado"},
{"Cannot connect to upstream HTTP proxy", "No se puede conectar al proxy HTTP principal"}, {"cannot connect to upstream http proxy", "no se puede conectar al proxy http principal"},
{"Host is down", "Servidor caído"}, {"Host is down", "Servidor caído"},
{"Can't create connection to requested host, it may be down. Please try again later.", "No se puede crear la conexión al servidor solicitado, puede estar caído. Intente de nuevo más tarde."}, {"Can't create connection to requested host, it may be down. Please try again later.", "No se puede crear la conexión al servidor solicitado, puede estar caído. Intente de nuevo más tarde."},
{"", ""}, {"", ""},
@@ -187,10 +199,10 @@ namespace spanish // language namespace
static std::map<std::string, std::vector<std::string>> plurals static std::map<std::string, std::vector<std::string>> plurals
{ {
{"%d days", {"%d día", "%d días"}}, {"days", {"día", "días"}},
{"%d hours", {"%d hora", "%d horas"}}, {"hours", {"hora", "horas"}},
{"%d minutes", {"%d minuto", "%d minutos"}}, {"minutes", {"minuto", "minutos"}},
{"%d seconds", {"%d segundo", "%d segundos"}}, {"seconds", {"segundo", "segundos"}},
{"", {"", ""}}, {"", {"", ""}},
}; };

View File

@@ -1,208 +0,0 @@
/*
* Copyright (c) 2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#include <map>
#include <vector>
#include <string>
#include <memory>
#include "I18N.h"
// Swedish localization file
namespace i2p
{
namespace i18n
{
namespace swedish // language namespace
{
// language name in lowercase
static std::string language = "swedish";
// See for language plural forms here:
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
static int plural (int n) {
return n != 1 ? 1 : 0;
}
static std::map<std::string, std::string> strings
{
{"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"},
{"%.2f GiB", "%.2f GiB"},
{"building", "bygger"},
{"failed", "misslyckad"},
{"expiring", "utgår"},
{"established", "upprättad"},
{"unknown", "okänt"},
{"exploratory", "utforskande"},
{"Purple I2P Webconsole", "Purple I2P Webbkonsoll"},
{"<b>i2pd</b> webconsole", "<b>i2pd</b>-Webbkonsoll"},
{"Main page", "Huvudsida"},
{"Router commands", "Routerkommandon"},
{"Local Destinations", "Lokala Platser"},
{"LeaseSets", "Hyresuppsättningar"},
{"Tunnels", "Tunnlar"},
{"Transit Tunnels", "Förmedlande Tunnlar"},
{"Transports", "Transporter"},
{"I2P tunnels", "I2P-tunnlar"},
{"SAM sessions", "SAM-perioder"},
{"ERROR", "FEL"},
{"OK", "OK"},
{"Testing", "Prövar"},
{"Firewalled", "Bakom Brandvägg"},
{"Unknown", "Okänt"},
{"Proxy", "Proxy"},
{"Mesh", "Mesh"},
{"Clock skew", "Tidsförskjutning"},
{"Offline", "Nedkopplad"},
{"Symmetric NAT", "Symmetrisk NAT"},
{"Uptime", "Upptid"},
{"Network status", "Nätverkstillstånd"},
{"Network status v6", "Nätverkstillstånd v6"},
{"Stopping in", "Avstängd om"},
{"Family", "Familj"},
{"Tunnel creation success rate", "Andel framgångsrika tunnlar"},
{"Received", "Mottaget"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "Skickat"},
{"Transit", "Förmedlat"},
{"Data path", "Sökväg"},
{"Hidden content. Press on text to see.", "Dolt innehåll. Tryck för att visa."},
{"Router Ident", "Routeridentitet"},
{"Router Family", "Routerfamilj"},
{"Router Caps", "Routerbegränsningar"},
{"Version", "Version"},
{"Our external address", "Vår externa adress"},
{"supported", "stöds"},
{"Routers", "Routrar"},
{"Floodfills", "Översvämningsfyllare"},
{"Client Tunnels", "Klienttunnlar"},
{"Services", "Tjänster"},
{"Enabled", "Påslaget"},
{"Disabled", "Avslaget"},
{"Encrypted B33 address", "Krypterad B33-Adress"},
{"Address registration line", "Adressregistreringsrad"},
{"Domain", "Domän"},
{"Generate", "Skapa"},
{"<b>Note:</b> result string can be used only for registering 2LD domains (example.i2p). For registering subdomains please use i2pd-tools.", "<b>Uppmärksamma:</b> den resulterande strängen kan enbart användas för att registrera 2LD-domäner (exempel.i2p). För att registrera underdomäner, vänligen använd i2pd-tools."},
{"Address", "Adress"},
{"Type", "Typ"},
{"EncType", "EncTyp"},
{"Inbound tunnels", "Ingående Tunnlar"},
{"%dms", "%dms"},
{"Outbound tunnels", "Utgående Tunnlar"},
{"Tags", "Taggar"},
{"Incoming", "Ingående"},
{"Outgoing", "Utgående"},
{"Destination", "Plats"},
{"Amount", "Mängd"},
{"Incoming Tags", "Ingående Taggar"},
{"Tags sessions", "Tagg-perioder"},
{"Status", "Tillstånd"},
{"Local Destination", "Lokal Plats"},
{"Streams", "Strömmar"},
{"Close stream", "Stäng strömmen"},
{"I2CP session not found", "I2CP-period hittades inte"},
{"I2CP is not enabled", "I2CP är inte påslaget"},
{"Invalid", "Ogiltig"},
{"Store type", "Lagringstyp"},
{"Expires", "Utgångsdatum"},
{"Non Expired Leases", "Ickeutgångna Hyresuppsättningar"},
{"Gateway", "Gateway"},
{"TunnelID", "TunnelID"},
{"EndDate", "EndDate"},
{"Queue size", "Köstorlek"},
{"Run peer test", "Utför utsiktstest"},
{"Decline transit tunnels", "Avvisa förmedlande tunnlar"},
{"Accept transit tunnels", "Tillåt förmedlande tunnlar"},
{"Cancel graceful shutdown", "Avbryt välvillig avstängning"},
{"Start graceful shutdown", "Påbörja välvillig avstängning"},
{"Force shutdown", "Tvingad avstängning"},
{"Reload external CSS styles", "Ladda om externa CSS-stilar"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Uppmärksamma:</b> inga ändringar här är beständiga eller påverkar dina inställningsfiler."},
{"Logging level", "Protokollförningsnivå"},
{"Transit tunnels limit", "Begränsa förmedlande tunnlar"},
{"Change", "Ändra"},
{"Change language", "Ändra språk"},
{"no transit tunnels currently built", "inga förmedlande tunnlar har byggts"},
{"SAM disabled", "SAM avslaget"},
{"no sessions currently running", "inga perioder igång"},
{"SAM session not found", "SAM-perioder hittades ej"},
{"SAM Session", "SAM-period"},
{"Server Tunnels", "Värdtunnlar"},
{"Client Forwards", "Klientförpassningar"},
{"Server Forwards", "Värdförpassningar"},
{"Unknown page", "Okänd sida"},
{"Invalid token", "Ogiltig polett"},
{"SUCCESS", "FRAMGÅNG"},
{"Stream closed", "Ström stängd"},
{"Stream not found or already was closed", "Strömmen hittades inte eller var redan avslutad"},
{"Destination not found", "Plats hittades ej"},
{"StreamID can't be null", "Ström-ID kan inte vara null"},
{"Return to destination page", "Återvänd till platssidan"},
{"You will be redirected in %d seconds", "Du omdirigeras inom %d sekunder"},
{"Transit tunnels count must not exceed %d", "Förmedlande tunnlar får inte överstiga %d"},
{"Back to commands list", "Tillbaka till kommandolistan"},
{"Register at reg.i2p", "Registrera vid reg.i2p"},
{"Description", "Beskrivning"},
{"A bit information about service on domain", "Ett stycke information om domänens tjänst"},
{"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"},
{"Proxy info", "Proxyinfo"},
{"Proxy error: Host not found", "Proxyfel: Värden hittades ej"},
{"Remote host not found in router's addressbook", "Främmande värd hittades inte i routerns adressbok"},
{"You may try to find this host on jump services below", "Du kan försöka att hitta värden genom hopptjänsterna nedan"},
{"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"},
{"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"},
{"Bad outproxy settings", "Ogiltig utproxyinställning"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Värd %s är inte inom I2P-näverket, men utproxy är inte påslaget"},
{"Unknown outproxy URL", "okänt Utproxy-URL"},
{"Cannot resolve upstream proxy", "Hittar inte uppströmsproxyt"},
{"Hostname is too long", "Värdnamnet är för långt"},
{"Cannot connect to upstream SOCKS proxy", "Kan inte ansluta till uppström SOCKS-proxy"},
{"Cannot negotiate with SOCKS proxy", "Kan inte förhandla med SOCKSproxyt"},
{"CONNECT error", "CONNECT-fel"},
{"Failed to connect", "Anslutningen misslyckades"},
{"SOCKS proxy error", "SOCKSproxyfel"},
{"Failed to send request to upstream", "Förfrågan uppströms kunde ej skickas"},
{"No reply from SOCKS proxy", "Fick inget svar från SOCKSproxyt"},
{"Cannot connect", "Kan inte ansluta"},
{"HTTP out proxy not implemented", "HTTP-Utproxy ej implementerat"},
{"Cannot connect to upstream HTTP proxy", "Kan inte ansluta till uppströms HTTP-proxy"},
{"Host is down", "Värden är nere"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Kan inte ansluta till värden, den kan vara nere. Vänligen försök senare."},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"%d days", {"%d dag", "%d dagar"}},
{"%d hours", {"%d timme", "%d timmar"}},
{"%d minutes", {"%d minut", "%d minuter"}},
{"%d seconds", {"%d sekund", "%d sekunder"}},
{"", {"", ""}},
};
std::shared_ptr<const i2p::i18n::Locale> GetLocale()
{
return std::make_shared<i2p::i18n::Locale>(language, strings, plurals, [] (int n)->int { return plural(n); });
}
} // language
} // i18n
} // i2p

View File

@@ -1,114 +0,0 @@
/*
* Copyright (c) 2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*/
#include <map>
#include <vector>
#include <string>
#include <memory>
#include "I18N.h"
// Turkish localization file
namespace i2p
{
namespace i18n
{
namespace turkish // language namespace
{
// language name in lowercase
static std::string language = "turkish";
// See for language plural forms here:
// https://localization-guide.readthedocs.io/en/latest/l10n/pluralforms.html
static int plural (int n) {
return n != 1 ? 1 : 0;
}
static std::map<std::string, std::string> strings
{
{"%.2f KiB", "%.2f KiB"},
{"%.2f MiB", "%.2f MiB"},
{"%.2f GiB", "%.2f GiB"},
{"building", "kuruluyor"},
{"failed", "başarısız"},
{"expiring", "süresi geçiyor"},
{"established", "kurulmuş"},
{"unknown", "bilinmeyen"},
{"Purple I2P Webconsole", "Mor I2P Webkonsolu"},
{"<b>i2pd</b> webconsole", "<b>i2pd</b> webkonsolu"},
{"Main page", "Ana sayfa"},
{"Router commands", "Router komutları"},
{"Local Destinations", "Yerel Hedefler"},
{"Tunnels", "Tüneller"},
{"Transit Tunnels", "Transit Tünelleri"},
{"Transports", "Taşıma"},
{"I2P tunnels", "I2P tünelleri"},
{"SAM sessions", "SAM oturumları"},
{"ERROR", "HATA"},
{"OK", "TAMAM"},
{"Testing", "Test ediliyor"},
{"Firewalled", "Güvenlik Duvarı Kısıtlaması"},
{"Unknown", "Bilinmeyen"},
{"Proxy", "Proxy"},
{"Clock skew", "Saat sorunu"},
{"Offline", "Çevrimdışı"},
{"Symmetric NAT", "Simetrik NAT"},
{"Full cone NAT", "Full cone NAT"},
{"No Descriptors", "Tanımlayıcı Yok"},
{"Uptime", "Bağlantı süresi"},
{"Network status", "Ağ durumu"},
{"Network status v6", "Ağ durumu v6"},
{"Family", "Aile"},
{"Tunnel creation success rate", "Tünel oluşturma başarı oranı"},
{"Received", "Alındı"},
{"%.2f KiB/s", "%.2f KiB/s"},
{"Sent", "Gönderildi"},
{"Transit", "Transit"},
{"Data path", "Veri yolu"},
{"Hidden content. Press on text to see.", "Gizlenmiş içerik. Görmek için yazıya tıklayınız."},
{"Router Family", "Router Familyası"},
{"Decline transit tunnels", "Transit tünellerini reddet"},
{"Accept transit tunnels", "Transit tünellerini kabul et"},
{"Cancel graceful shutdown", "Düzgün durdurmayı iptal Et"},
{"Start graceful shutdown", "Düzgün durdurmayı başlat"},
{"Force shutdown", "Durdurmaya zorla"},
{"Reload external CSS styles", "Harici CSS stilini yeniden yükle"},
{"<b>Note:</b> any action done here are not persistent and not changes your config files.", "<b>Not:</b> burada yapılan ayarların hiçbiri kalıcı değildir ve ayar dosyalarınızı değiştirmez."},
{"Logging level", "Kayıt tutma seviyesi"},
{"Transit tunnels limit", "Transit tünel limiti"},
{"Change", "Değiştir"},
{"Change language", "Dil değiştir"},
{"no transit tunnels currently built", "kurulmuş bir transit tüneli bulunmamakta"},
{"SAM disabled", "SAM devre dışı"},
{"no sessions currently running", "hiçbir oturum şu anda çalışmıyor"},
{"SAM session not found", "SAM oturumu bulunamadı"},
{"SAM Session", "SAM oturumu"},
{"Server Tunnels", "Sunucu Tünelleri"},
{"Unknown page", "Bilinmeyen sayfa"},
{"Invalid token", "Geçersiz token"},
{"SUCCESS", "BAŞARILI"},
{"", ""},
};
static std::map<std::string, std::vector<std::string>> plurals
{
{"%d days", {"%d gün", "%d gün"}},
{"%d hours", {"%d saat", "%d saat"}},
{"%d minutes", {"%d dakika", "%d dakika"}},
{"%d seconds", {"%d saniye", "%d saniye"}},
{"", {"", ""}},
};
std::shared_ptr<const i2p::i18n::Locale> GetLocale()
{
return std::make_shared<i2p::i18n::Locale>(language, strings, plurals, [] (int n)->int { return plural(n); });
}
} // language
} // i18n
} // i2p

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021-2023, The PurpleI2P Project * Copyright (c) 2021-2022, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -31,16 +31,15 @@ namespace turkmen // language namespace
static std::map<std::string, std::string> strings static std::map<std::string, std::string> strings
{ {
{"%.2f KiB", "%.2f KiB"}, {"KiB", "KiB"},
{"%.2f MiB", "%.2f MiB"}, {"MiB", "MiB"},
{"%.2f GiB", "%.2f GiB"}, {"GiB", "GiB"},
{"building", "bina"}, {"building", "bina"},
{"failed", "şowsuz"}, {"failed", "şowsuz"},
{"expiring", "möhleti gutarýar"}, {"expiring", "möhleti gutarýar"},
{"established", "işleýär"}, {"established", "işleýär"},
{"unknown", "näbelli"}, {"unknown", "näbelli"},
{"exploratory", "gözleg"}, {"exploratory", "gözleg"},
{"Purple I2P Webconsole", "Web konsoly Purple I2P"},
{"<b>i2pd</b> webconsole", "Web konsoly <b>i2pd</b>"}, {"<b>i2pd</b> webconsole", "Web konsoly <b>i2pd</b>"},
{"Main page", "Esasy sahypa"}, {"Main page", "Esasy sahypa"},
{"Router commands", "Marşrutizator buýruklary"}, {"Router commands", "Marşrutizator buýruklary"},
@@ -58,6 +57,7 @@ namespace turkmen // language namespace
{"Unknown", "Näbelli"}, {"Unknown", "Näbelli"},
{"Proxy", "Proksi"}, {"Proxy", "Proksi"},
{"Mesh", "MESH-tor"}, {"Mesh", "MESH-tor"},
{"Error", "Ýalňyşlyk"},
{"Clock skew", "Takyk wagt däl"}, {"Clock skew", "Takyk wagt däl"},
{"Offline", "Awtonom"}, {"Offline", "Awtonom"},
{"Symmetric NAT", "Simmetriklik NAT"}, {"Symmetric NAT", "Simmetriklik NAT"},
@@ -68,7 +68,7 @@ namespace turkmen // language namespace
{"Family", "Maşgala"}, {"Family", "Maşgala"},
{"Tunnel creation success rate", "Gurlan teneller üstünlikli gurlan teneller"}, {"Tunnel creation success rate", "Gurlan teneller üstünlikli gurlan teneller"},
{"Received", "Alnan"}, {"Received", "Alnan"},
{"%.2f KiB/s", "%.2f KiB/s"}, {"KiB/s", "KiB/s"},
{"Sent", "Ýerleşdirildi"}, {"Sent", "Ýerleşdirildi"},
{"Transit", "Tranzit"}, {"Transit", "Tranzit"},
{"Data path", "Maglumat ýoly"}, {"Data path", "Maglumat ýoly"},
@@ -94,7 +94,7 @@ namespace turkmen // language namespace
{"Type", "Görnüş"}, {"Type", "Görnüş"},
{"EncType", "Şifrlemek görnüşi"}, {"EncType", "Şifrlemek görnüşi"},
{"Inbound tunnels", "Gelýän tuneller"}, {"Inbound tunnels", "Gelýän tuneller"},
{"%dms", "%dms"}, {"ms", "ms"},
{"Outbound tunnels", "Çykýan tuneller"}, {"Outbound tunnels", "Çykýan tuneller"},
{"Tags", "Bellikler"}, {"Tags", "Bellikler"},
{"Incoming", "Gelýän"}, {"Incoming", "Gelýän"},
@@ -116,6 +116,7 @@ namespace turkmen // language namespace
{"Gateway", "Derweze"}, {"Gateway", "Derweze"},
{"TunnelID", "Tuneliň ID"}, {"TunnelID", "Tuneliň ID"},
{"EndDate", "Gutarýar"}, {"EndDate", "Gutarýar"},
{"not floodfill", "fludfil däl"},
{"Queue size", "Nobatyň ululygy"}, {"Queue size", "Nobatyň ululygy"},
{"Run peer test", "Synag başlaň"}, {"Run peer test", "Synag başlaň"},
{"Decline transit tunnels", "Tranzit tunellerini ret ediň"}, {"Decline transit tunnels", "Tranzit tunellerini ret ediň"},
@@ -145,6 +146,8 @@ namespace turkmen // language namespace
{"Destination not found", "Niýetlenen ýeri tapylmady"}, {"Destination not found", "Niýetlenen ýeri tapylmady"},
{"StreamID can't be null", "StreamID boş bolup bilmez"}, {"StreamID can't be null", "StreamID boş bolup bilmez"},
{"Return to destination page", "Barmaly nokadynyň nokadyna gaýdyp geliň"}, {"Return to destination page", "Barmaly nokadynyň nokadyna gaýdyp geliň"},
{"You will be redirected in 5 seconds", "5 sekuntdan soň täzeden ugrukdyrylarsyňyz"},
{"Transit tunnels count must not exceed 65535", "Tranzit tagtalaryň sany 65535-den geçmeli däldir"},
{"Back to commands list", "Topar sanawyna dolan"}, {"Back to commands list", "Topar sanawyna dolan"},
{"Register at reg.i2p", "Reg.i2P-de hasaba duruň"}, {"Register at reg.i2p", "Reg.i2P-de hasaba duruň"},
{"Description", "Beýany"}, {"Description", "Beýany"},
@@ -162,24 +165,32 @@ namespace turkmen // language namespace
{"You may try to find this host on jump services below", "Aşakdaky böküş hyzmatlarynda bu öý eýesini tapmaga synanyşyp bilersiňiz"}, {"You may try to find this host on jump services below", "Aşakdaky böküş hyzmatlarynda bu öý eýesini tapmaga synanyşyp bilersiňiz"},
{"Invalid request", "Nädogry haýyş"}, {"Invalid request", "Nädogry haýyş"},
{"Proxy unable to parse your request", "Proksi haýyşyňyzy derňäp bilmeýär"}, {"Proxy unable to parse your request", "Proksi haýyşyňyzy derňäp bilmeýär"},
{"Invalid request URI", "Nädogry haýyş URI"}, {"addresshelper is not supported", "Salgylandyryjy goldanok"},
{"Host", "Adres"},
{"added to router's addressbook from helper", "marşruteriň adresini kömekçiden goşdy"},
{"Click here to proceed:", "Dowam etmek bu ýerde basyň:"},
{"Continue", "Dowam et"},
{"Addresshelper found", "Forgelper tapyldy"},
{"already in router's addressbook", "marşruteriň adres kitaby"},
{"Click here to update record:", "Recordazgyny täzelemek üçin bu ýerde basyň:"},
{"invalid request uri", "nädogry haýyş URI"},
{"Can't detect destination host from request", "Haýyşdan barmaly ýerini tapyp bilemok"}, {"Can't detect destination host from request", "Haýyşdan barmaly ýerini tapyp bilemok"},
{"Outproxy failure", "Daşarky proksi ýalňyşlyk"}, {"Outproxy failure", "Daşarky proksi ýalňyşlyk"},
{"Bad outproxy settings", "Daşarky Daşarky proksi sazlamalary nädogry"}, {"bad outproxy settings", "daşarky daşarky proksi sazlamalary nädogry"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Adres %s I2P torunda däl, ýöne daşarky proksi goşulmaýar"}, {"not inside I2P network, but outproxy is not enabled", "I2P torunda däl, ýöne daşarky proksi goşulmaýar"},
{"Unknown outproxy URL", "Näbelli daşarky proksi URL"}, {"unknown outproxy url", "näbelli daşarky proksi URL"},
{"Cannot resolve upstream proxy", "Has ýokary proksi kesgitläp bilmeýär"}, {"cannot resolve upstream proxy", "has ýokary proksi kesgitläp bilmeýär"},
{"Hostname is too long", "Hoster eýesi ady gaty uzyn"}, {"hostname too long", "hoster eýesi ady gaty uzyn"},
{"Cannot connect to upstream SOCKS proxy", "Ýokary jorap SOCKS proksi bilen birigip bolmaýar"}, {"cannot connect to upstream socks proxy", "ýokary jorap SOCKS proksi bilen birigip bolmaýar"},
{"Cannot negotiate with SOCKS proxy", "Iň ýokary jorap SOCKS proksi bilen ylalaşyp bilmeýärler"}, {"Cannot negotiate with socks proxy", "Iň ýokary jorap SOCKS proksi bilen ylalaşyp bilmeýärler"},
{"CONNECT error", "Bagyr haýyşy säwligi"}, {"CONNECT error", "Bagyr haýyşy säwligi"},
{"Failed to connect", "Birikdirip bilmedi"}, {"Failed to Connect", "Birikdirip bilmedi"},
{"SOCKS proxy error", "SOCKS proksi ýalňyşlygy"}, {"socks proxy error", "socks proksi ýalňyşlygy"},
{"Failed to send request to upstream", "Öý eýesi proksi üçin haýyş iberip bilmedi"}, {"failed to send request to upstream", "öý eýesi proksi üçin haýyş iberip bilmedi"},
{"No reply from SOCKS proxy", "Jorap SOCKS proksi serwerinden hiç hili jogap ýok"}, {"No Reply From socks proxy", "Jorap proksi serwerinden hiç hili jogap ýok"},
{"Cannot connect", "Birikdirip bilmedi"}, {"cannot connect", "birikdirip bilmedi"},
{"HTTP out proxy not implemented", "Daşarky HTTP proksi serwerini goldamak amala aşyrylmaýar"}, {"http out proxy not implemented", "daşarky HTTP proksi serwerini goldamak amala aşyrylmaýar"},
{"Cannot connect to upstream HTTP proxy", "Ýokary jorap HTTP proksi bilen birigip bolmaýar"}, {"cannot connect to upstream http proxy", "ýokary akym HTTP proksi serwerine birigip bilmedi"},
{"Host is down", "Salgy elýeterli däl"}, {"Host is down", "Salgy elýeterli däl"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Talap edilýän salgyda birikmäni gurup bilmedim, onlaýn bolup bilmez. Soňra haýyşy soň gaýtalamaga synanyşyň."}, {"Can't create connection to requested host, it may be down. Please try again later.", "Talap edilýän salgyda birikmäni gurup bilmedim, onlaýn bolup bilmez. Soňra haýyşy soň gaýtalamaga synanyşyň."},
{"", ""}, {"", ""},
@@ -187,10 +198,10 @@ namespace turkmen // language namespace
static std::map<std::string, std::vector<std::string>> plurals static std::map<std::string, std::vector<std::string>> plurals
{ {
{"%d days", {"%d gün", "%d gün"}}, {"days", {"gün", "gün"}},
{"%d hours", {"%d sagat", "%d sagat"}}, {"hours", {"sagat", "sagat"}},
{"%d minutes", {"%d minut", "%d minut"}}, {"minutes", {"minut", "minut"}},
{"%d seconds", {"%d sekunt", "%d sekunt"}}, {"seconds", {"sekunt", "sekunt"}},
{"", {"", ""}}, {"", {"", ""}},
}; };

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021-2023, The PurpleI2P Project * Copyright (c) 2021, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -31,16 +31,15 @@ namespace ukrainian // language namespace
static std::map<std::string, std::string> strings static std::map<std::string, std::string> strings
{ {
{"%.2f KiB", "%.2f КіБ"}, {"KiB", "КіБ"},
{"%.2f MiB", "%.2f МіБ"}, {"MiB", "МіБ"},
{"%.2f GiB", "%.2f ГіБ"}, {"GiB", "ГіБ"},
{"building", "будується"}, {"building", "будується"},
{"failed", "невдалий"}, {"failed", "невдалий"},
{"expiring", "завершується"}, {"expiring", "завершується"},
{"established", "працює"}, {"established", "працює"},
{"unknown", "невідомо"}, {"unknown", "невідомо"},
{"exploratory", "дослідницький"}, {"exploratory", "дослідницький"},
{"Purple I2P Webconsole", "Веб-консоль Purple I2P"},
{"<b>i2pd</b> webconsole", "Веб-консоль <b>i2pd</b>"}, {"<b>i2pd</b> webconsole", "Веб-консоль <b>i2pd</b>"},
{"Main page", "Головна"}, {"Main page", "Головна"},
{"Router commands", "Команди маршрутизатора"}, {"Router commands", "Команди маршрутизатора"},
@@ -58,11 +57,10 @@ namespace ukrainian // language namespace
{"Unknown", "Невідомо"}, {"Unknown", "Невідомо"},
{"Proxy", "Проксі"}, {"Proxy", "Проксі"},
{"Mesh", "MESH-мережа"}, {"Mesh", "MESH-мережа"},
{"Error", "Помилка"},
{"Clock skew", "Неточний час"}, {"Clock skew", "Неточний час"},
{"Offline", "Офлайн"}, {"Offline", "Офлайн"},
{"Symmetric NAT", "Симетричний NAT"}, {"Symmetric NAT", "Симетричний NAT"},
{"Full cone NAT", "Повний NAT"},
{"No Descriptors", "Немає Описів"},
{"Uptime", "У мережі"}, {"Uptime", "У мережі"},
{"Network status", "Мережевий статус"}, {"Network status", "Мережевий статус"},
{"Network status v6", "Мережевий статус v6"}, {"Network status v6", "Мережевий статус v6"},
@@ -70,7 +68,7 @@ namespace ukrainian // language namespace
{"Family", "Сімейство"}, {"Family", "Сімейство"},
{"Tunnel creation success rate", "Успішно побудованих тунелів"}, {"Tunnel creation success rate", "Успішно побудованих тунелів"},
{"Received", "Отримано"}, {"Received", "Отримано"},
{"%.2f KiB/s", "%.2f КіБ/с"}, {"KiB/s", "КіБ/с"},
{"Sent", "Відправлено"}, {"Sent", "Відправлено"},
{"Transit", "Транзит"}, {"Transit", "Транзит"},
{"Data path", "Шлях до даних"}, {"Data path", "Шлях до даних"},
@@ -96,7 +94,7 @@ namespace ukrainian // language namespace
{"Type", "Тип"}, {"Type", "Тип"},
{"EncType", "ТипШифр"}, {"EncType", "ТипШифр"},
{"Inbound tunnels", "Вхідні тунелі"}, {"Inbound tunnels", "Вхідні тунелі"},
{"%dms", "%dмс"}, {"ms", "мс"},
{"Outbound tunnels", "Вихідні тунелі"}, {"Outbound tunnels", "Вихідні тунелі"},
{"Tags", "Теги"}, {"Tags", "Теги"},
{"Incoming", "Вхідні"}, {"Incoming", "Вхідні"},
@@ -118,10 +116,9 @@ namespace ukrainian // language namespace
{"Gateway", "Шлюз"}, {"Gateway", "Шлюз"},
{"TunnelID", "ID тунеля"}, {"TunnelID", "ID тунеля"},
{"EndDate", "Закінчується"}, {"EndDate", "Закінчується"},
{"floodfill mode is disabled", "режим floodfill вимкнено"}, {"not floodfill", "не флудфіл"},
{"Queue size", "Розмір черги"}, {"Queue size", "Розмір черги"},
{"Run peer test", "Запустити тестування"}, {"Run peer test", "Запустити тестування"},
{"Reload tunnels configuration", "Перезавантажити налаштування тунелів"},
{"Decline transit tunnels", "Відхиляти транзитні тунелі"}, {"Decline transit tunnels", "Відхиляти транзитні тунелі"},
{"Accept transit tunnels", "Ухвалювати транзитні тунелі"}, {"Accept transit tunnels", "Ухвалювати транзитні тунелі"},
{"Cancel graceful shutdown", "Скасувати плавну зупинку"}, {"Cancel graceful shutdown", "Скасувати плавну зупинку"},
@@ -149,8 +146,8 @@ namespace ukrainian // language namespace
{"Destination not found", "Точка призначення не знайдена"}, {"Destination not found", "Точка призначення не знайдена"},
{"StreamID can't be null", "Ідентифікатор потоку не може бути порожнім"}, {"StreamID can't be null", "Ідентифікатор потоку не може бути порожнім"},
{"Return to destination page", "Повернутися на сторінку точки призначення"}, {"Return to destination page", "Повернутися на сторінку точки призначення"},
{"You will be redirected in %d seconds", "Ви будете переадресовані через %d секунд"}, {"You will be redirected in 5 seconds", "Ви будете переадресовані через 5 секунд"},
{"Transit tunnels count must not exceed %d", "Кількість транзитних тунелів не повинна перевищувати %d"}, {"Transit tunnels count must not exceed 65535", "Кількість транзитних тунелів не повинна перевищувати 65535"},
{"Back to commands list", "Повернутися до списку команд"}, {"Back to commands list", "Повернутися до списку команд"},
{"Register at reg.i2p", "Зареєструвати на reg.i2p"}, {"Register at reg.i2p", "Зареєструвати на reg.i2p"},
{"Description", "Опис"}, {"Description", "Опис"},
@@ -168,33 +165,32 @@ namespace ukrainian // language namespace
{"You may try to find this host on jump services below", "Ви можете спробувати знайти дану адресу на джамп сервісах нижче"}, {"You may try to find this host on jump services below", "Ви можете спробувати знайти дану адресу на джамп сервісах нижче"},
{"Invalid request", "Некоректний запит"}, {"Invalid request", "Некоректний запит"},
{"Proxy unable to parse your request", "Проксі не може розібрати ваш запит"}, {"Proxy unable to parse your request", "Проксі не може розібрати ваш запит"},
{"Addresshelper is not supported", "Адресна книга не підтримується"}, {"addresshelper is not supported", "addresshelper не підтримується"},
{"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>.", "Хост %s <font color=red>вже в адресній книзі маршрутизатора</font>. <b>Будьте обережні: джерело цієї адреси може зашкодити!</b> Натисніть тут, щоб оновити запис: <a href=\"%s%s%s&update=true\">Продовжити</a>."}, {"Host", "Адреса"},
{"Addresshelper forced update rejected", "Адресна книга відхилила примусове оновлення"}, {"added to router's addressbook from helper", "доданий в адресну книгу маршрутизатора через хелпер"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Щоб додати хост <b>%s</b> в адресі маршрутизатора, натисніть тут: <a href=\"%s%s%s\"родовжити</a>."}, {"Click here to proceed:", "Натисніть тут щоб продовжити:"},
{"Addresshelper request", "Запит на адресну сторінку"}, {"Continue", "Продовжити"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "Хост %s доданий в адресну книгу маршрутизатора від помічника. Натисніть тут, щоб продовжити: <a href=\"%s\">Продовжити</a>."}, {"Addresshelper found", "Знайдено addresshelper"},
{"Addresshelper adding", "Адреса додана"}, {"already in router's addressbook", "вже в адресній книзі маршрутизатора"},
{"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>.", "Хост %s <font color=red>вже в адресній книзі маршрутизатора</font>. Натисніть тут, щоб оновити запис: <a href=\"%s%s%s&update=true\">Продовжити</a>."}, {"Click here to update record:", "Натисніть тут щоб оновити запис:"},
{"Addresshelper update", "Оновлення адресної книги"}, {"invalid request uri", "некоректний URI запиту"},
{"Invalid request URI", "Некоректний URI запиту"},
{"Can't detect destination host from request", "Не вдалось визначити адресу призначення з запиту"}, {"Can't detect destination host from request", "Не вдалось визначити адресу призначення з запиту"},
{"Outproxy failure", "Помилка зовнішнього проксі"}, {"Outproxy failure", "Помилка зовнішнього проксі"},
{"Bad outproxy settings", "Некоректні налаштування зовнішнього проксі"}, {"bad outproxy settings", "некоректні налаштування зовнішнього проксі"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Адрес %s не в I2P мережі, але зовнішній проксі не включений"}, {"not inside I2P network, but outproxy is not enabled", "не в I2P мережі, але зовнішній проксі не включений"},
{"Unknown outproxy URL", "Невідомий URL зовнішнього проксі"}, {"unknown outproxy url", "невідомий URL зовнішнього проксі"},
{"Cannot resolve upstream proxy", "Не вдається визначити висхідний проксі"}, {"cannot resolve upstream proxy", "не вдається визначити висхідний проксі"},
{"Hostname is too long", "Ім'я вузла надто довге"}, {"hostname too long", "ім'я вузла надто довге"},
{"Cannot connect to upstream SOCKS proxy", "Не вдалося підключитися до висхідного SOCKS проксі сервера"}, {"cannot connect to upstream socks proxy", "не вдається підключитися до висхідного SOCKS проксі"},
{"Cannot negotiate with SOCKS proxy", "Не вдається домовитися з висхідним SOCKS проксі"}, {"Cannot negotiate with socks proxy", "Не вдається домовитися з висхідним SOCKS проксі"},
{"CONNECT error", "Помилка CONNECT запиту"}, {"CONNECT error", "Помилка CONNECT запиту"},
{"Failed to connect", "Не вдалося підключитися"}, {"Failed to Connect", "Не вдалося підключитися"},
{"SOCKS proxy error", "Помилка SOCKS проксі"}, {"socks proxy error", "помилка SOCKS проксі"},
{"Failed to send request to upstream", "Не вдалося відправити запит висхідному проксі"}, {"failed to send request to upstream", "не вдалося відправити запит висхідному проксі"},
{"No reply from SOCKS proxy", "Немає відповіді від SOCKS проксі сервера"}, {"No Reply From socks proxy", "Немає відповіді від SOCKS проксі сервера"},
{"Cannot connect", "Не вдалося підключитися"}, {"cannot connect", "не вдалося підключитися"},
{"HTTP out proxy not implemented", "Підтримка зовнішнього HTTP проксі сервера не реалізована"}, {"http out proxy not implemented", "підтримка зовнішнього HTTP проксі сервера не реалізована"},
{"Cannot connect to upstream HTTP proxy", "Не вдалося підключитися до висхідного HTTP проксі сервера"}, {"cannot connect to upstream http proxy", "не вдалося підключитися до висхідного HTTP проксі сервера"},
{"Host is down", "Вузол недоступний"}, {"Host is down", "Вузол недоступний"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Не вдалося встановити з'єднання до запитаного вузла, можливо він не в мережі. Спробуйте повторити запит пізніше."}, {"Can't create connection to requested host, it may be down. Please try again later.", "Не вдалося встановити з'єднання до запитаного вузла, можливо він не в мережі. Спробуйте повторити запит пізніше."},
{"", ""}, {"", ""},
@@ -202,10 +198,10 @@ namespace ukrainian // language namespace
static std::map<std::string, std::vector<std::string>> plurals static std::map<std::string, std::vector<std::string>> plurals
{ {
{"%d days", {"%d день", "%d дня", "%d днів"}}, {"days", {"день", "дня", "днів"}},
{"%d hours", {"%d годину", "%d години", "%d годин"}}, {"hours", {"годину", "години", "годин"}},
{"%d minutes", {"%d хвилину", "%d хвилини", "%d хвилин"}}, {"minutes", {"хвилину", "хвилини", "хвилин"}},
{"%d seconds", {"%d секунду", "%d секунди", "%d секунд"}}, {"seconds", {"секунду", "секунди", "секунд"}},
{"", {"", "", ""}}, {"", {"", "", ""}},
}; };

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2021-2023, The PurpleI2P Project * Copyright (c) 2021-2022, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -31,16 +31,15 @@ namespace uzbek // language namespace
static std::map<std::string, std::string> strings static std::map<std::string, std::string> strings
{ {
{"%.2f KiB", "%.2f KiB"}, {"KiB", "KiB"},
{"%.2f MiB", "%.2f MiB"}, {"MiB", "MiB"},
{"%.2f GiB", "%.2f GiB"}, {"GiB", "GiB"},
{"building", "yaratilmoqda"}, {"building", "yaratilmoqda"},
{"failed", "muvaffaqiyatsiz"}, {"failed", "muvaffaqiyatsiz"},
{"expiring", "muddati tugaydi"}, {"expiring", "muddati tugaydi"},
{"established", "aloqa o'rnatildi"}, {"established", "aloqa o'rnatildi"},
{"unknown", "noma'lum"}, {"unknown", "noma'lum"},
{"exploratory", "tadqiqiy"}, {"exploratory", "tadqiqiy"},
{"Purple I2P Webconsole", "Veb-konsoli Purple I2P"},
{"<b>i2pd</b> webconsole", "<b>i2pd</b> veb-konsoli"}, {"<b>i2pd</b> webconsole", "<b>i2pd</b> veb-konsoli"},
{"Main page", "Asosiy sahifa"}, {"Main page", "Asosiy sahifa"},
{"Router commands", "Router buyruqlari"}, {"Router commands", "Router buyruqlari"},
@@ -58,11 +57,10 @@ namespace uzbek // language namespace
{"Unknown", "Notanish"}, {"Unknown", "Notanish"},
{"Proxy", "Proksi"}, {"Proxy", "Proksi"},
{"Mesh", "Mesh To'r"}, {"Mesh", "Mesh To'r"},
{"Error", "Xato"},
{"Clock skew", "Aniq vaqt emas"}, {"Clock skew", "Aniq vaqt emas"},
{"Offline", "Oflayn"}, {"Offline", "Oflayn"},
{"Symmetric NAT", "Simmetrik NAT"}, {"Symmetric NAT", "Simmetrik NAT"},
{"Full cone NAT", "Full cone NAT"},
{"No Descriptors", "Deskriptorlar yo'q"},
{"Uptime", "Ish vaqti"}, {"Uptime", "Ish vaqti"},
{"Network status", "Tarmoq holati"}, {"Network status", "Tarmoq holati"},
{"Network status v6", "Tarmoq holati v6"}, {"Network status v6", "Tarmoq holati v6"},
@@ -70,7 +68,7 @@ namespace uzbek // language namespace
{"Family", "Oila"}, {"Family", "Oila"},
{"Tunnel creation success rate", "Tunnel yaratish muvaffaqiyat darajasi"}, {"Tunnel creation success rate", "Tunnel yaratish muvaffaqiyat darajasi"},
{"Received", "Qabul qilindi"}, {"Received", "Qabul qilindi"},
{"%.2f KiB/s", "%.2f KiB/s"}, {"KiB/s", "KiB/s"},
{"Sent", "Yuborilgan"}, {"Sent", "Yuborilgan"},
{"Transit", "Tranzit"}, {"Transit", "Tranzit"},
{"Data path", "Ma'lumotlar joylanishi"}, {"Data path", "Ma'lumotlar joylanishi"},
@@ -96,7 +94,7 @@ namespace uzbek // language namespace
{"Type", "Turi"}, {"Type", "Turi"},
{"EncType", "ShifrlashTuri"}, {"EncType", "ShifrlashTuri"},
{"Inbound tunnels", "Kirish tunnellari"}, {"Inbound tunnels", "Kirish tunnellari"},
{"%dms", "%dms"}, {"ms", "ms"},
{"Outbound tunnels", "Chiquvchi tunnellar"}, {"Outbound tunnels", "Chiquvchi tunnellar"},
{"Tags", "Teglar"}, {"Tags", "Teglar"},
{"Incoming", "Kiruvchi"}, {"Incoming", "Kiruvchi"},
@@ -118,10 +116,9 @@ namespace uzbek // language namespace
{"Gateway", "Kirish yo'li"}, {"Gateway", "Kirish yo'li"},
{"TunnelID", "TunnelID"}, {"TunnelID", "TunnelID"},
{"EndDate", "Tugash Sanasi"}, {"EndDate", "Tugash Sanasi"},
{"floodfill mode is disabled", "floodfill rejimi o'chirilgan"}, {"not floodfill", "floodfill emas"},
{"Queue size", "Navbat hajmi"}, {"Queue size", "Navbat hajmi"},
{"Run peer test", "Sinovni boshlang"}, {"Run peer test", "Sinovni boshlang"},
{"Reload tunnels configuration", "Tunnel konfiguratsiyasini qayta yuklash"},
{"Decline transit tunnels", "Tranzit tunnellarini rad etish"}, {"Decline transit tunnels", "Tranzit tunnellarini rad etish"},
{"Accept transit tunnels", "Tranzit tunnellarni qabul qilish"}, {"Accept transit tunnels", "Tranzit tunnellarni qabul qilish"},
{"Cancel graceful shutdown", "Yumshoq to'xtashni bekor qilish"}, {"Cancel graceful shutdown", "Yumshoq to'xtashni bekor qilish"},
@@ -149,8 +146,8 @@ namespace uzbek // language namespace
{"Destination not found", "Yo'nalish topilmadi"}, {"Destination not found", "Yo'nalish topilmadi"},
{"StreamID can't be null", "StreamID bo'sh bo'lishi mumkin emas"}, {"StreamID can't be null", "StreamID bo'sh bo'lishi mumkin emas"},
{"Return to destination page", "Manzilgoh sahifasiga qaytish"}, {"Return to destination page", "Manzilgoh sahifasiga qaytish"},
{"You will be redirected in %d seconds", "Siz %d soniyadan song boshqa yonalishga yonaltirilasiz"}, {"You will be redirected in 5 seconds", "Siz 5 soniya ichida qayta yo'naltirilasiz"},
{"Transit tunnels count must not exceed %d", "Tranzit tunnellar soni %d dan oshmasligi kerak"}, {"Transit tunnels count must not exceed 65535", "Tranzit tunnellar soni 65535 dan oshmasligi kerak"},
{"Back to commands list", "Buyruqlar ro'yxatiga qaytish"}, {"Back to commands list", "Buyruqlar ro'yxatiga qaytish"},
{"Register at reg.i2p", "Reg.i2p-da ro'yxatdan o'ting"}, {"Register at reg.i2p", "Reg.i2p-da ro'yxatdan o'ting"},
{"Description", "Tavsif"}, {"Description", "Tavsif"},
@@ -168,33 +165,32 @@ namespace uzbek // language namespace
{"You may try to find this host on jump services below", "Siz xost quyida o'tish xizmatlari orqali topishga harakat qilishingiz mumkin"}, {"You may try to find this host on jump services below", "Siz xost quyida o'tish xizmatlari orqali topishga harakat qilishingiz mumkin"},
{"Invalid request", "Notogri sorov"}, {"Invalid request", "Notogri sorov"},
{"Proxy unable to parse your request", "Proksi sizning so'rovingizni aniqlab ololmayapti"}, {"Proxy unable to parse your request", "Proksi sizning so'rovingizni aniqlab ololmayapti"},
{"Addresshelper is not supported", "Addresshelper qo'llab-quvvatlanmaydi"}, {"addresshelper is not supported", "addresshelper qo'llab -quvvatlanmaydi"},
{"Host %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>.", "%s xosti <font color=red>allaqachon routerning manzillar kitobida</font>. <b>Ehtiyot bo'ling: bu URL manbasi zararli bo'lishi mumkin!</b> Yozuvni yangilash uchun bu yerni bosing: <a href=\"%s%s%s&update=true\">Davom etish</a>."}, {"Host", "Xost"},
{"Addresshelper forced update rejected", "Addresshelperni majburiy yangilash rad etildi"}, {"added to router's addressbook from helper", "'helper'dan routerning 'addressbook'ga qo'shildi"},
{"To add host <b>%s</b> in router's addressbook, click here: <a href=\"%s%s%s\">Continue</a>.", "Routerning manzillar kitobiga <b>%s</b> xostini qo'shish uchun bu yerni bosing: <a href=\"%s%s%s\">Davom etish</a>."}, {"Click here to proceed:", "Davom etish uchun shu yerni bosing:"},
{"Addresshelper request", "Addresshelper so'rovi"}, {"Continue", "Davom etish"},
{"Host %s added to router's addressbook from helper. Click here to proceed: <a href=\"%s\">Continue</a>.", "Yordamchidan router manzillar kitobiga %s xost qoshildi. Davom etish uchun bu yerga bosing: <a href=\"%s\">Davom etish</a>."}, {"Addresshelper found", "Addresshelper topildi"},
{"Addresshelper adding", "Addresshelperni qo'shish"}, {"already in router's addressbook", "allaqachon 'addressbook'da yozilgan"},
{"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>.", "%s xosti <font color=red>allaqachon routerning manzillar kitobida</font>. Yozuvni yangilash uchun shu yerni bosing: <a href=\"%s%s%s&update=true\">Davom etish</a>."}, {"Click here to update record:", "Yozuvni yangilash uchun shu yerni bosing:"},
{"Addresshelper update", "Addresshelperni yangilash"}, {"invalid request uri", "noto'g'ri URI so'rovi"},
{"Invalid request URI", "Noto'g'ri URI so'rovi"},
{"Can't detect destination host from request", "Sorov orqali manzil xostini aniqlab bo'lmayapti"}, {"Can't detect destination host from request", "Sorov orqali manzil xostini aniqlab bo'lmayapti"},
{"Outproxy failure", "Tashqi proksi muvaffaqiyatsizligi"}, {"Outproxy failure", "Tashqi proksi muvaffaqiyatsizligi"},
{"Bad outproxy settings", "Noto'g'ri tashqi proksi-server sozlamalari"}, {"bad outproxy settings", "noto'g'ri tashqi proksi-server sozlamalari"},
{"Host %s is not inside I2P network, but outproxy is not enabled", "Xost %s I2P tarmog'ida emas, lekin tashqi proksi yoqilmagan"}, {"not inside I2P network, but outproxy is not enabled", "I2P tarmog'ida emas, lekin tashqi proksi yoqilmagan"},
{"Unknown outproxy URL", "Noma'lum outproxy URL"}, {"unknown outproxy url", "noma'lum outproxy url"},
{"Cannot resolve upstream proxy", "Yuqoridagi 'proxy-server'ni aniqlab olib bolmayapti"}, {"cannot resolve upstream proxy", "yuqoridagi 'proxy-server'ni aniqlab olib bolmayapti"},
{"Hostname is too long", "Xost nomi juda uzun"}, {"hostname too long", "xost nomi juda uzun"},
{"Cannot connect to upstream SOCKS proxy", "Yuqori 'SOCKS proxy'ga ulanib bo'lmayapti"}, {"cannot connect to upstream socks proxy", "yuqori 'socks proxy'ga ulanib bo'lmayapti"},
{"Cannot negotiate with SOCKS proxy", "'SOCKS proxy' bilan muzokara olib bo'lmaydi"}, {"Cannot negotiate with socks proxy", "'Socks proxy' bilan muzokara olib bo'lmaydi"},
{"CONNECT error", "CONNECT xatosi"}, {"CONNECT error", "CONNECT xatosi"},
{"Failed to connect", "Ulanib bo'lmayapti"}, {"Failed to Connect", "Ulanib bo'lmayapti"},
{"SOCKS proxy error", "'SOCKS proxy' xatosi"}, {"socks proxy error", "'socks proxy' xatosi"},
{"Failed to send request to upstream", "Yuqori proksi-serveriga so'rovni uborib bo'lmadi"}, {"failed to send request to upstream", "yuqori http proksi-serveriga so'rovni uborib bo'lmadi"},
{"No reply from SOCKS proxy", "'SOCKS proxy'dan javob yo'q"}, {"No Reply From socks proxy", "'Socks proxy'dan javob yo'q"},
{"Cannot connect", "Ulanib bo'lmaydi"}, {"cannot connect", "ulanib bo'lmaydi"},
{"HTTP out proxy not implemented", "Tashqi HTTP proksi-serverni qo'llab-quvvatlash amalga oshirilmagan"}, {"http out proxy not implemented", "tashqi HTTP proksi-serverni qo'llab-quvvatlash amalga oshirilmagan"},
{"Cannot connect to upstream HTTP proxy", "Yuqori 'HTTP proxy'ga ulanib bo'lmayapti"}, {"cannot connect to upstream http proxy", "yuqori http 'proxy-server'iga ulanib bo'lmayapti"},
{"Host is down", "Xost ishlamayapti"}, {"Host is down", "Xost ishlamayapti"},
{"Can't create connection to requested host, it may be down. Please try again later.", "Talab qilingan xost bilan aloqa o'rnatilmadi, u ishlamay qolishi mumkin. Iltimos keyinroq qayta urinib ko'ring."}, {"Can't create connection to requested host, it may be down. Please try again later.", "Talab qilingan xost bilan aloqa o'rnatilmadi, u ishlamay qolishi mumkin. Iltimos keyinroq qayta urinib ko'ring."},
{"", ""}, {"", ""},
@@ -202,10 +198,10 @@ namespace uzbek // language namespace
static std::map<std::string, std::vector<std::string>> plurals static std::map<std::string, std::vector<std::string>> plurals
{ {
{"%d days", {"%d kun", "%d kun"}}, {"days", {"kun", "kun"}},
{"%d hours", {"%d soat", "%d soat"}}, {"hours", {"soat", "soat"}},
{"%d minutes", {"%d daqiqa", "%d daqiqa"}}, {"minutes", {"daqiqa", "daqiqa"}},
{"%d seconds", {"%d soniya", "%d soniya"}}, {"seconds", {"soniya", "soniya"}},
{"", {"", ""}}, {"", {"", ""}},
}; };

View File

@@ -135,7 +135,7 @@ namespace data
//---------------------------------------------------------- //----------------------------------------------------------
const uint8_t B33_TWO_BYTES_SIGTYPE_FLAG = 0x01; const uint8_t B33_TWO_BYTES_SIGTYPE_FLAG = 0x01;
// const uint8_t B33_PER_SECRET_FLAG = 0x02; // not used for now const uint8_t B33_PER_SECRET_FLAG = 0x02; // not used for now
const uint8_t B33_PER_CLIENT_AUTH_FLAG = 0x04; const uint8_t B33_PER_CLIENT_AUTH_FLAG = 0x04;
BlindedPublicKey::BlindedPublicKey (std::shared_ptr<const IdentityEx> identity, bool clientAuth): BlindedPublicKey::BlindedPublicKey (std::shared_ptr<const IdentityEx> identity, bool clientAuth):

View File

@@ -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 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -45,7 +45,7 @@ namespace config {
("logclftime", bool_switch()->default_value(false), "Write full CLF-formatted date and time to log (default: disabled, write only time)") ("logclftime", bool_switch()->default_value(false), "Write full CLF-formatted date and time to log (default: disabled, write only time)")
("family", value<std::string>()->default_value(""), "Specify a family, router belongs to") ("family", value<std::string>()->default_value(""), "Specify a family, router belongs to")
("datadir", value<std::string>()->default_value(""), "Path to storage of i2pd data (RI, keys, peer profiles, ...)") ("datadir", value<std::string>()->default_value(""), "Path to storage of i2pd data (RI, keys, peer profiles, ...)")
("host", value<std::string>()->default_value(""), "External IP") ("host", value<std::string>()->default_value("0.0.0.0"), "External IP")
("ifname", value<std::string>()->default_value(""), "Network interface to bind to") ("ifname", value<std::string>()->default_value(""), "Network interface to bind to")
("ifname4", value<std::string>()->default_value(""), "Network interface to bind to for ipv4") ("ifname4", value<std::string>()->default_value(""), "Network interface to bind to for ipv4")
("ifname6", value<std::string>()->default_value(""), "Network interface to bind to for ipv6") ("ifname6", value<std::string>()->default_value(""), "Network interface to bind to for ipv6")
@@ -77,7 +77,7 @@ namespace config {
limits.add_options() limits.add_options()
("limits.coresize", value<uint32_t>()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)") ("limits.coresize", value<uint32_t>()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)")
("limits.openfiles", value<uint16_t>()->default_value(0), "Maximum number of open files (0 - use system default)") ("limits.openfiles", value<uint16_t>()->default_value(0), "Maximum number of open files (0 - use system default)")
("limits.transittunnels", value<uint16_t>()->default_value(5000), "Maximum active transit tunnels (default:5000)") ("limits.transittunnels", value<uint16_t>()->default_value(2500), "Maximum active transit sessions (default:2500)")
("limits.ntcpsoft", value<uint16_t>()->default_value(0), "Ignored") ("limits.ntcpsoft", value<uint16_t>()->default_value(0), "Ignored")
("limits.ntcphard", value<uint16_t>()->default_value(0), "Ignored") ("limits.ntcphard", value<uint16_t>()->default_value(0), "Ignored")
("limits.ntcpthreads", value<uint16_t>()->default_value(1), "Ignored") ("limits.ntcpthreads", value<uint16_t>()->default_value(1), "Ignored")
@@ -95,7 +95,6 @@ namespace config {
("http.hostname", value<std::string>()->default_value("localhost"), "Expected hostname for WebUI") ("http.hostname", value<std::string>()->default_value("localhost"), "Expected hostname for WebUI")
("http.webroot", value<std::string>()->default_value("/"), "WebUI root path (default: / )") ("http.webroot", value<std::string>()->default_value("/"), "WebUI root path (default: / )")
("http.lang", value<std::string>()->default_value("english"), "WebUI language (default: english )") ("http.lang", value<std::string>()->default_value("english"), "WebUI language (default: english )")
("http.showTotalTCSR", value<bool>()->default_value(false), "Show additional value with total TCSR since router's start (default: false)")
; ;
options_description httpproxy("HTTP Proxy options"); options_description httpproxy("HTTP Proxy options");
@@ -149,8 +148,7 @@ namespace config {
sam.add_options() sam.add_options()
("sam.enabled", value<bool>()->default_value(true), "Enable or disable SAM Application bridge") ("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.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.port", value<uint16_t>()->default_value(7656), "SAM listen port")
("sam.portudp", value<uint16_t>()->default_value(0), "SAM listen UDP port")
("sam.singlethread", value<bool>()->default_value(true), "Sessions run in the SAM bridge's thread") ("sam.singlethread", value<bool>()->default_value(true), "Sessions run in the SAM bridge's thread")
; ;
@@ -216,11 +214,10 @@ namespace config {
"https://reseed.onion.im/," "https://reseed.onion.im/,"
"https://i2pseed.creativecowpat.net:8443/," "https://i2pseed.creativecowpat.net:8443/,"
"https://reseed.i2pgit.org/," "https://reseed.i2pgit.org/,"
"https://i2p.novg.net/,"
"https://banana.incognet.io/," "https://banana.incognet.io/,"
"https://reseed-pl.i2pd.xyz/," "https://reseed-pl.i2pd.xyz/,"
"https://www2.mk16.de/," "https://www2.mk16.de/"
"https://i2p.ghativega.in/,"
"https://i2p.novg.net/"
), "Reseed URLs, separated by comma") ), "Reseed URLs, separated by comma")
("reseed.yggurls", value<std::string>()->default_value( ("reseed.yggurls", value<std::string>()->default_value(
"http://[324:71e:281a:9ed3::ace]:7070/," "http://[324:71e:281a:9ed3::ace]:7070/,"
@@ -287,7 +284,7 @@ namespace config {
options_description nettime("Time sync options"); options_description nettime("Time sync options");
nettime.add_options() nettime.add_options()
("nettime.enabled", value<bool>()->default_value(false), "Enable NTP time sync (default: disabled)") ("nettime.enabled", value<bool>()->default_value(false), "Disable time sync (default: disabled)")
("nettime.ntpservers", value<std::string>()->default_value( ("nettime.ntpservers", value<std::string>()->default_value(
"0.pool.ntp.org," "0.pool.ntp.org,"
"1.pool.ntp.org," "1.pool.ntp.org,"

View File

@@ -159,10 +159,8 @@ namespace crypto
// DH/ElGamal // DH/ElGamal
#if !defined(__x86_64__)
const int ELGAMAL_SHORT_EXPONENT_NUM_BITS = 226; const int ELGAMAL_SHORT_EXPONENT_NUM_BITS = 226;
const int ELGAMAL_SHORT_EXPONENT_NUM_BYTES = ELGAMAL_SHORT_EXPONENT_NUM_BITS/8+1; const int ELGAMAL_SHORT_EXPONENT_NUM_BYTES = ELGAMAL_SHORT_EXPONENT_NUM_BITS/8+1;
#endif
const int ELGAMAL_FULL_EXPONENT_NUM_BITS = 2048; const int ELGAMAL_FULL_EXPONENT_NUM_BITS = 2048;
const int ELGAMAL_FULL_EXPONENT_NUM_BYTES = ELGAMAL_FULL_EXPONENT_NUM_BITS/8; const int ELGAMAL_FULL_EXPONENT_NUM_BYTES = ELGAMAL_FULL_EXPONENT_NUM_BITS/8;

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, The PurpleI2P Project * Copyright (c) 2013-2021, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -425,7 +425,7 @@ namespace datagram
if (m) if (m)
send.push_back(i2p::tunnel::TunnelMessageBlock{i2p::tunnel::eDeliveryTypeTunnel,routingPath->remoteLease->tunnelGateway, routingPath->remoteLease->tunnelID, 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(); m_SendQueue.clear();
} }

View File

@@ -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 * 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) if (authType >= i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_NONE && authType <= i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK)
m_AuthType = authType; m_AuthType = authType;
else else
LogPrint (eLogError, "Destination: Unknown auth type: ", authType); LogPrint (eLogError, "Destination: Unknown auth type ", authType);
} }
} }
it = params->find (I2CP_PARAM_LEASESET_PRIV_KEY); it = params->find (I2CP_PARAM_LEASESET_PRIV_KEY);
@@ -117,7 +117,7 @@ namespace client
m_LeaseSetPrivKey.reset (new i2p::data::Tag<32>()); m_LeaseSetPrivKey.reset (new i2p::data::Tag<32>());
if (m_LeaseSetPrivKey->FromBase64 (it->second) != 32) if (m_LeaseSetPrivKey->FromBase64 (it->second) != 32)
{ {
LogPrint(eLogCritical, "Destination: Invalid value i2cp.leaseSetPrivKey: ", it->second); LogPrint(eLogError, "Destination: Invalid value i2cp.leaseSetPrivKey ", it->second);
m_LeaseSetPrivKey.reset (nullptr); m_LeaseSetPrivKey.reset (nullptr);
} }
} }
@@ -399,11 +399,6 @@ namespace client
void LeaseSetDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len) void LeaseSetDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len)
{ {
if (len < DATABASE_STORE_HEADER_SIZE)
{
LogPrint (eLogError, "Destination: Database store msg is too short ", len);
return;
}
uint32_t replyToken = bufbe32toh (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET); uint32_t replyToken = bufbe32toh (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET);
size_t offset = DATABASE_STORE_HEADER_SIZE; size_t offset = DATABASE_STORE_HEADER_SIZE;
if (replyToken) if (replyToken)
@@ -411,11 +406,6 @@ namespace client
LogPrint (eLogInfo, "Destination: Reply token is ignored for DatabaseStore"); LogPrint (eLogInfo, "Destination: Reply token is ignored for DatabaseStore");
offset += 36; offset += 36;
} }
if (offset > len || len > i2p::data::MAX_LS_BUFFER_SIZE + offset)
{
LogPrint (eLogError, "Destination: Database store message is too long ", len);
return;
}
i2p::data::IdentHash key (buf + DATABASE_STORE_KEY_OFFSET); i2p::data::IdentHash key (buf + DATABASE_STORE_KEY_OFFSET);
std::shared_ptr<i2p::data::LeaseSet> leaseSet; std::shared_ptr<i2p::data::LeaseSet> leaseSet;
switch (buf[DATABASE_STORE_TYPE_OFFSET]) switch (buf[DATABASE_STORE_TYPE_OFFSET])
@@ -477,15 +467,12 @@ namespace client
{ {
auto ls2 = std::make_shared<i2p::data::LeaseSet2> (buf + offset, len - offset, auto ls2 = std::make_shared<i2p::data::LeaseSet2> (buf + offset, len - offset,
it2->second->requestedBlindedKey, m_LeaseSetPrivKey ? ((const uint8_t *)*m_LeaseSetPrivKey) : nullptr , GetPreferredCryptoType ()); it2->second->requestedBlindedKey, m_LeaseSetPrivKey ? ((const uint8_t *)*m_LeaseSetPrivKey) : nullptr , GetPreferredCryptoType ());
if (ls2->IsValid () && !ls2->IsExpired ()) if (ls2->IsValid ())
{ {
leaseSet = ls2;
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
m_RemoteLeaseSets[ls2->GetIdentHash ()] = ls2; // ident is not key m_RemoteLeaseSets[ls2->GetIdentHash ()] = ls2; // ident is not key
m_RemoteLeaseSets[key] = ls2; // also store as key for next lookup m_RemoteLeaseSets[key] = ls2; // also store as key for next lookup
leaseSet = ls2;
} }
else
LogPrint (eLogError, "Destination: New remote encrypted LeaseSet2 failed");
} }
else else
LogPrint (eLogInfo, "Destination: Couldn't find request for encrypted LeaseSet2"); LogPrint (eLogInfo, "Destination: Couldn't find request for encrypted LeaseSet2");
@@ -635,7 +622,7 @@ namespace client
m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT)); m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT));
m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer, m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer,
shared_from_this (), std::placeholders::_1)); shared_from_this (), std::placeholders::_1));
outbound->SendTunnelDataMsgTo (floodfill->GetIdentHash (), 0, msg); outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg);
m_LastSubmissionTime = ts; m_LastSubmissionTime = ts;
} }
@@ -775,20 +762,12 @@ namespace client
{ {
request->requestTime = ts; request->requestTime = ts;
if (!SendLeaseSetRequest (dest, floodfill, request)) if (!SendLeaseSetRequest (dest, floodfill, request))
{
// try another
LogPrint (eLogWarning, "Destination: Couldn't send LeaseSet request to ", floodfill->GetIdentHash ().ToBase64 (), ". Trying another");
request->excluded.insert (floodfill->GetIdentHash ());
floodfill = i2p::data::netdb.GetClosestFloodfill (dest, request->excluded);
if (!SendLeaseSetRequest (dest, floodfill, request))
{ {
// request failed // request failed
LogPrint (eLogWarning, "Destination: LeaseSet request for ", dest.ToBase32 (), " was not sent");
m_LeaseSetRequests.erase (ret.first); m_LeaseSetRequests.erase (ret.first);
if (requestComplete) requestComplete (nullptr); if (requestComplete) requestComplete (nullptr);
} }
} }
}
else // duplicate else // duplicate
{ {
LogPrint (eLogInfo, "Destination: Request of LeaseSet ", dest.ToBase64 (), " is pending already"); LogPrint (eLogInfo, "Destination: Request of LeaseSet ", dest.ToBase64 (), " is pending already");
@@ -813,11 +792,11 @@ namespace client
std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request) std::shared_ptr<const i2p::data::RouterInfo> nextFloodfill, std::shared_ptr<LeaseSetRequest> request)
{ {
if (!request->replyTunnel || !request->replyTunnel->IsEstablished ()) if (!request->replyTunnel || !request->replyTunnel->IsEstablished ())
request->replyTunnel = m_Pool->GetNextInboundTunnel (nullptr, nextFloodfill->GetCompatibleTransports (false)); // outbound from floodfill request->replyTunnel = m_Pool->GetNextInboundTunnel (nullptr, nextFloodfill->GetCompatibleTransports (true));
if (!request->replyTunnel) LogPrint (eLogWarning, "Destination: Can't send LeaseSet request, no compatible inbound tunnels found"); if (!request->replyTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no inbound tunnels found");
if (!request->outboundTunnel || !request->outboundTunnel->IsEstablished ()) if (!request->outboundTunnel || !request->outboundTunnel->IsEstablished ())
request->outboundTunnel = m_Pool->GetNextOutboundTunnel (nullptr, nextFloodfill->GetCompatibleTransports (true)); // inbound from floodfill request->outboundTunnel = m_Pool->GetNextOutboundTunnel (nullptr, nextFloodfill->GetCompatibleTransports (false));
if (!request->outboundTunnel) LogPrint (eLogWarning, "Destination: Can't send LeaseSet request, no compatible outbound tunnels found"); if (!request->outboundTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no outbound tunnels found");
if (request->replyTunnel && request->outboundTunnel) if (request->replyTunnel && request->outboundTunnel)
{ {
@@ -835,7 +814,7 @@ namespace client
AddSessionKey (replyKey, replyTag); AddSessionKey (replyKey, replyTag);
auto msg = WrapMessageForRouter (nextFloodfill, CreateLeaseSetDatabaseLookupMsg (dest, auto msg = WrapMessageForRouter (nextFloodfill, CreateLeaseSetDatabaseLookupMsg (dest,
request->excluded, request->replyTunnel, replyKey, replyTag, isECIES)); request->excluded, request->replyTunnel, replyKey, replyTag, isECIES));
request->outboundTunnel->SendTunnelDataMsgs ( request->outboundTunnel->SendTunnelDataMsg (
{ {
i2p::tunnel::TunnelMessageBlock i2p::tunnel::TunnelMessageBlock
{ {
@@ -930,7 +909,7 @@ namespace client
bool isPublic, const std::map<std::string, std::string> * params): bool isPublic, const std::map<std::string, std::string> * params):
LeaseSetDestination (service, isPublic, params), LeaseSetDestination (service, isPublic, params),
m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY), 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_DatagramDestination (nullptr), m_RefCounter (0),
m_ReadyChecker(service) m_ReadyChecker(service)
{ {
@@ -1000,7 +979,7 @@ namespace client
m_StreamingAckDelay = std::stoi(it->second); m_StreamingAckDelay = std::stoi(it->second);
it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS); it = params->find (I2CP_PARAM_STREAMING_ANSWER_PINGS);
if (it != params->end ()) if (it != params->end ())
m_IsStreamingAnswerPings = std::stoi (it->second); // 1 for true m_IsStreamingAnswerPings = (it->second == "true");
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
{ {
@@ -1014,12 +993,12 @@ namespace client
else if (authType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK) else if (authType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK)
ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_PSK, params); ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_PSK, params);
else else
LogPrint (eLogError, "Destination: Unexpected auth type: ", authType); LogPrint (eLogError, "Destination: Unexpected auth type ", authType);
if (m_AuthKeys->size ()) if (m_AuthKeys->size ())
LogPrint (eLogInfo, "Destination: ", m_AuthKeys->size (), " auth keys read"); LogPrint (eLogInfo, "Destination: ", m_AuthKeys->size (), " auth keys read");
else 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; m_AuthKeys = nullptr;
} }
} }
@@ -1028,7 +1007,7 @@ namespace client
} }
catch (std::exception & ex) 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());
} }
} }
@@ -1058,7 +1037,6 @@ namespace client
//it.second->SetOwner (nullptr); //it.second->SetOwner (nullptr);
} }
m_StreamingDestinationsByPorts.clear (); m_StreamingDestinationsByPorts.clear ();
m_LastStreamingDestination = nullptr;
if (m_DatagramDestination) if (m_DatagramDestination)
{ {
delete m_DatagramDestination; delete m_DatagramDestination;
@@ -1083,15 +1061,9 @@ namespace client
case PROTOCOL_TYPE_STREAMING: case PROTOCOL_TYPE_STREAMING:
{ {
// streaming protocol // streaming protocol
if (toPort != m_LastPort || !m_LastStreamingDestination) auto dest = GetStreamingDestination (toPort);
{ if (dest)
m_LastStreamingDestination = GetStreamingDestination (toPort); dest->HandleDataMessagePayload (buf, length);
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);
else else
LogPrint (eLogError, "Destination: Missing streaming destination"); LogPrint (eLogError, "Destination: Missing streaming destination");
} }
@@ -1166,25 +1138,19 @@ namespace client
template<typename Dest> template<typename Dest>
std::shared_ptr<i2p::stream::Stream> ClientDestination::CreateStreamSync (const Dest& dest, int 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; std::shared_ptr<i2p::stream::Stream> stream;
std::condition_variable streamRequestComplete; std::condition_variable streamRequestComplete;
std::mutex streamRequestCompleteMutex; std::mutex streamRequestCompleteMutex;
std::unique_lock<std::mutex> l(streamRequestCompleteMutex);
CreateStream ( CreateStream (
[&done, &streamRequestComplete, &streamRequestCompleteMutex, &stream](std::shared_ptr<i2p::stream::Stream> s) [&streamRequestComplete, &streamRequestCompleteMutex, &stream](std::shared_ptr<i2p::stream::Stream> s)
{ {
stream = s; stream = s;
std::unique_lock<std::mutex> l(streamRequestCompleteMutex); std::unique_lock<std::mutex> l(streamRequestCompleteMutex);
streamRequestComplete.notify_all (); streamRequestComplete.notify_all ();
done = true;
}, },
dest, port); dest, port);
while (!done)
{
std::unique_lock<std::mutex> l(streamRequestCompleteMutex);
if (!done)
streamRequestComplete.wait (l); streamRequestComplete.wait (l);
}
return stream; return stream;
} }
@@ -1243,9 +1209,8 @@ namespace client
if (it != m_StreamingDestinationsByPorts.end ()) if (it != m_StreamingDestinationsByPorts.end ())
return it->second; return it->second;
} }
else // if port is zero, use default destination // if port is zero or not found, use default destination
return m_StreamingDestination; return m_StreamingDestination;
return nullptr;
} }
void ClientDestination::AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor) void ClientDestination::AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor)
@@ -1344,7 +1309,7 @@ namespace client
f1.write ((char *)keys->priv, 256); f1.write ((char *)keys->priv, 256);
return; 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) void ClientDestination::CreateNewLeaseSet (const std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> >& tunnels)
@@ -1421,7 +1386,7 @@ namespace client
if (pubKey.FromBase64 (it.second.substr (pos+1))) if (pubKey.FromBase64 (it.second.substr (pos+1)))
m_AuthKeys->push_back (pubKey); m_AuthKeys->push_back (pubKey);
else else
LogPrint (eLogCritical, "Destination: Unexpected auth key: ", it.second.substr (pos+1)); LogPrint (eLogError, "Destination: Unexpected auth key ", it.second.substr (pos+1));
} }
} }
} }

View File

@@ -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 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -297,7 +297,6 @@ namespace client
bool m_IsStreamingAnswerPings; bool m_IsStreamingAnswerPings;
std::shared_ptr<i2p::stream::StreamingDestination> m_StreamingDestination; // default std::shared_ptr<i2p::stream::StreamingDestination> m_StreamingDestination; // default
std::map<uint16_t, std::shared_ptr<i2p::stream::StreamingDestination> > m_StreamingDestinationsByPorts; 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; i2p::datagram::DatagramDestination * m_DatagramDestination;
int m_RefCounter; // how many clients(tunnels) use this destination int m_RefCounter; // how many clients(tunnels) use this destination

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, The PurpleI2P Project * Copyright (c) 2013-2021, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -335,7 +335,6 @@ namespace garlic
case eECIESx25519BlkAckRequest: case eECIESx25519BlkAckRequest:
{ {
LogPrint (eLogDebug, "Garlic: Ack request"); LogPrint (eLogDebug, "Garlic: Ack request");
if (receiveTagset)
m_AckRequests.push_back ({receiveTagset->GetTagSetID (), index}); m_AckRequests.push_back ({receiveTagset->GetTagSetID (), index});
break; break;
} }
@@ -1150,7 +1149,7 @@ namespace garlic
std::shared_ptr<I2NPMessage> WrapECIESX25519Message (std::shared_ptr<const 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) m->Align (12); // in order to get buf aligned to 16 (12 + 4)
uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length
size_t offset = 0; size_t offset = 0;
@@ -1176,7 +1175,7 @@ namespace garlic
// Noise_N, we are Alice, routerPublicKey is Bob's // Noise_N, we are Alice, routerPublicKey is Bob's
i2p::crypto::NoiseSymmetricState noiseState; i2p::crypto::NoiseSymmetricState noiseState;
i2p::crypto::InitNoiseNState (noiseState, routerPublicKey); 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) m->Align (12); // in order to get buf aligned to 16 (12 + 4)
uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length uint8_t * buf = m->GetPayload () + 4; // 4 bytes for length
size_t offset = 0; size_t offset = 0;

View File

@@ -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 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -413,7 +413,7 @@ namespace crypto
BIGNUM * y = BN_new (); BIGNUM * y = BN_new ();
BN_bin2bn (buf1, EDDSA25519_PUBLIC_KEY_LENGTH, y); BN_bin2bn (buf1, EDDSA25519_PUBLIC_KEY_LENGTH, y);
BIGNUM * x = RecoverX (y, ctx); 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 BN_sub (x, q, x); // x = q - x
BIGNUM * z = BN_new (), * t = BN_new (); BIGNUM * z = BN_new (), * t = BN_new ();
BN_one (z); BN_mod_mul (t, x, y, q, ctx); // pre-calculate t BN_one (z); BN_mod_mul (t, x, y, q, ctx); // pre-calculate t

View File

@@ -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 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -88,7 +88,7 @@ namespace data
} }
EVP_PKEY_free (pkey); EVP_PKEY_free (pkey);
if (verifier && cn) if (verifier && cn)
m_SigningKeys.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); SSL_free (ssl);
} }

View File

@@ -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 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -709,7 +709,7 @@ namespace garlic
else else
LogPrint (eLogError, "Garlic: Tunnel pool is not set for inbound tunnel"); LogPrint (eLogError, "Garlic: Tunnel pool is not set for inbound tunnel");
if (tunnel) // we have sent it through an outbound tunnel if (tunnel) // we have sent it through an outbound tunnel
tunnel->SendTunnelDataMsgTo (gwHash, gwTunnel, msg); tunnel->SendTunnelDataMsg (gwHash, gwTunnel, msg);
else else
LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove"); LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove");
} }
@@ -1075,7 +1075,7 @@ namespace garlic
{ {
auto tunnel = GetTunnelPool ()->GetNextOutboundTunnel (); auto tunnel = GetTunnelPool ()->GetNextOutboundTunnel ();
if (tunnel) if (tunnel)
tunnel->SendTunnelDataMsgTo (gwHash, gwTunnel, CreateI2NPMessage (typeID, buf, len - offset, msgID)); tunnel->SendTunnelDataMsg (gwHash, gwTunnel, CreateI2NPMessage (typeID, buf, len - offset, msgID));
else else
LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove"); LogPrint (eLogWarning, "Garlic: No outbound tunnels available for garlic clove");
} }

View File

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

View File

@@ -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 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -93,18 +93,15 @@ namespace http
std::size_t pos_c = 0; /* < work position */ std::size_t pos_c = 0; /* < work position */
if(url.at(0) != '/' || pos_p > 0) { if(url.at(0) != '/' || pos_p > 0) {
std::size_t pos_s = 0; std::size_t pos_s = 0;
/* schema */ /* schema */
pos_c = url.find("://"); pos_c = url.find("://");
if (pos_c != std::string::npos) { if (pos_c != std::string::npos) {
schema = url.substr(0, pos_c); schema = url.substr(0, pos_c);
pos_p = pos_c + 3; pos_p = pos_c + 3;
} }
/* user[:pass] */ /* user[:pass] */
pos_s = url.find('/', pos_p); /* find first slash */ pos_s = url.find('/', pos_p); /* find first slash */
pos_c = url.find('@', pos_p); /* find end of 'user' or 'user:pass' part */ 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)) { if (pos_c != std::string::npos && (pos_s == std::string::npos || pos_s > pos_c)) {
std::size_t delim = url.find(':', pos_p); std::size_t delim = url.find(':', pos_p);
if (delim && delim != std::string::npos && delim < pos_c) { if (delim && delim != std::string::npos && delim < pos_c) {
@@ -116,28 +113,21 @@ namespace http
} }
pos_p = pos_c + 1; pos_p = pos_c + 1;
} }
/* hostname[:port][/path] */ /* hostname[:port][/path] */
if (url.at(pos_p) == '[') // ipv6 if (url[pos_p] == '[') // ipv6
{ {
auto pos_b = url.find(']', pos_p); auto pos_b = url.find(']', pos_p);
if (pos_b == std::string::npos) return false; if (pos_b == std::string::npos) return false;
ipv6 = true;
pos_c = url.find_first_of(":/", pos_b); pos_c = url.find_first_of(":/", pos_b);
} }
else else
pos_c = url.find_first_of(":/", pos_p); pos_c = url.find_first_of(":/", pos_p);
if (pos_c == std::string::npos) { if (pos_c == std::string::npos) {
/* only hostname, without post and path */ /* only hostname, without post and path */
host = ipv6 ? host = url.substr(pos_p, std::string::npos);
url.substr(pos_p + 1, url.length() - 1) :
url.substr(pos_p, std::string::npos);
return true; return true;
} else if (url.at(pos_c) == ':') { } else if (url.at(pos_c) == ':') {
host = ipv6 ? host = url.substr(pos_p, pos_c - pos_p);
url.substr(pos_p + 1, pos_c - pos_p - 2) :
url.substr(pos_p, pos_c - pos_p);
/* port[/path] */ /* port[/path] */
pos_p = pos_c + 1; pos_p = pos_c + 1;
pos_c = url.find('/', pos_p); pos_c = url.find('/', pos_p);
@@ -157,9 +147,7 @@ namespace http
pos_p = pos_c; pos_p = pos_c;
} else { } else {
/* start of path part found */ /* start of path part found */
host = ipv6 ? host = url.substr(pos_p, pos_c - pos_p);
url.substr(pos_p + 1, pos_c - pos_p - 2) :
url.substr(pos_p, pos_c - pos_p);
pos_p = pos_c; pos_p = pos_c;
} }
} }
@@ -172,7 +160,6 @@ namespace http
return true; return true;
} else if (url.at(pos_c) == '?') { } else if (url.at(pos_c) == '?') {
/* found query part */ /* found query part */
hasquery = true;
path = url.substr(pos_p, pos_c - pos_p); path = url.substr(pos_p, pos_c - pos_p);
pos_p = pos_c + 1; pos_p = pos_c + 1;
pos_c = url.find('#', pos_p); pos_c = url.find('#', pos_p);
@@ -224,25 +211,15 @@ namespace http
} else if (user != "") { } else if (user != "") {
out += user + "@"; out += user + "@";
} }
if (ipv6) {
if (port) {
out += "[" + host + "]:" + std::to_string(port);
} else {
out += "[" + host + "]";
}
} else {
if (port) { if (port) {
out += host + ":" + std::to_string(port); out += host + ":" + std::to_string(port);
} else { } else {
out += host; out += host;
} }
} }
}
out += path; out += path;
if (hasquery) // add query even if it was empty
out += "?";
if (query != "") if (query != "")
out += query; out += "?" + query;
if (frag != "") if (frag != "")
out += "#" + frag; out += "#" + frag;
return out; return out;
@@ -370,14 +347,6 @@ namespace http
return ""; return "";
} }
size_t HTTPReq::GetNumHeaders (const std::string& name) const
{
size_t num = 0;
for (auto& it : headers)
if (it.first == name) num++;
return num;
}
bool HTTPRes::is_chunked() const bool HTTPRes::is_chunked() const
{ {
auto it = headers.find("Transfer-Encoding"); auto it = headers.find("Transfer-Encoding");

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, The PurpleI2P Project * Copyright (c) 2013-2021, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -33,12 +33,10 @@ namespace http
std::string host; std::string host;
unsigned short int port; unsigned short int port;
std::string path; std::string path;
bool hasquery;
std::string query; std::string query;
std::string frag; 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(""), query(""), frag("") {};
/** /**
* @brief Tries to parse url from string * @brief Tries to parse url from string
@@ -103,8 +101,6 @@ namespace http
void RemoveHeader (const std::string& name, const std::string& exempt); // remove all headers starting with name, but exempt void RemoveHeader (const std::string& name, const std::string& exempt); // remove all headers starting with name, but exempt
void RemoveHeader (const std::string& name) { RemoveHeader (name, ""); }; void RemoveHeader (const std::string& name) { RemoveHeader (name, ""); };
std::string GetHeader (const std::string& name) const; std::string GetHeader (const std::string& name) const;
size_t GetNumHeaders (const std::string& name) const;
size_t GetNumHeaders () const { return headers.size (); };
}; };
struct HTTPRes : HTTPMsg { struct HTTPRes : HTTPMsg {

View File

@@ -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 * 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> >(); 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) std::shared_ptr<I2NPMessage> NewI2NPTunnelMessage (bool endpoint)
{ {
return i2p::tunnel::tunnels.NewI2NPTunnelMessage (endpoint); return i2p::tunnel::tunnels.NewI2NPTunnelMessage (endpoint);
@@ -48,10 +43,7 @@ namespace i2p
std::shared_ptr<I2NPMessage> NewI2NPMessage (size_t len) std::shared_ptr<I2NPMessage> NewI2NPMessage (size_t len)
{ {
len += I2NP_HEADER_SIZE + 2; return (len < I2NP_MAX_SHORT_MESSAGE_SIZE - I2NP_HEADER_SIZE - 2) ? NewI2NPShortMessage () : NewI2NPMessage ();
if (len <= I2NP_MAX_SHORT_MESSAGE_SIZE) return NewI2NPShortMessage ();
if (len <= I2NP_MAX_MEDIUM_MESSAGE_SIZE) return NewI2NPMediumMessage ();
return NewI2NPMessage ();
} }
void I2NPMessage::FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID, bool checksum) void I2NPMessage::FillI2NPMessageHeader (I2NPMessageType msgType, uint32_t replyMsgID, bool checksum)
@@ -134,8 +126,7 @@ namespace i2p
std::shared_ptr<I2NPMessage> CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from, std::shared_ptr<I2NPMessage> CreateRouterInfoDatabaseLookupMsg (const uint8_t * key, const uint8_t * from,
uint32_t replyTunnelID, bool exploratory, std::set<i2p::data::IdentHash> * excludedPeers) uint32_t replyTunnelID, bool exploratory, std::set<i2p::data::IdentHash> * excludedPeers)
{ {
int cnt = excludedPeers ? excludedPeers->size () : 0; auto m = excludedPeers ? NewI2NPMessage () : NewI2NPShortMessage ();
auto m = cnt > 7 ? NewI2NPMessage () : NewI2NPShortMessage ();
uint8_t * buf = m->GetPayload (); uint8_t * buf = m->GetPayload ();
memcpy (buf, key, 32); // key memcpy (buf, key, 32); // key
buf += 32; buf += 32;
@@ -156,6 +147,7 @@ namespace i2p
if (excludedPeers) if (excludedPeers)
{ {
int cnt = excludedPeers->size ();
htobe16buf (buf, cnt); htobe16buf (buf, cnt);
buf += 2; buf += 2;
for (auto& it: *excludedPeers) for (auto& it: *excludedPeers)
@@ -361,6 +353,21 @@ namespace i2p
return !msg->GetPayload ()[DATABASE_STORE_TYPE_OFFSET]; // 0- RouterInfo 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) static bool HandleBuildRequestRecords (int num, uint8_t * records, uint8_t * clearText)
{ {
for (int i = 0; i < num; i++) for (int i = 0; i < num; i++)
@@ -372,7 +379,10 @@ namespace i2p
if (!i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText)) return false; if (!i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText)) return false;
uint8_t retCode = 0; uint8_t retCode = 0;
// replace record to reply // replace record to reply
if (i2p::context.AcceptsTunnels () && !i2p::context.IsHighCongestion ()) if (i2p::context.AcceptsTunnels () &&
i2p::tunnel::tunnels.GetTransitTunnels ().size () <= g_MaxNumTransitTunnels &&
!i2p::transport::transports.IsBandwidthExceeded () &&
!i2p::transport::transports.IsTransitBandwidthExceeded ())
{ {
auto transitTunnel = i2p::tunnel::CreateTransitTunnel ( auto transitTunnel = i2p::tunnel::CreateTransitTunnel (
bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET), bufbe32toh (clearText + ECIES_BUILD_REQUEST_RECORD_RECEIVE_TUNNEL_OFFSET),
@@ -382,8 +392,7 @@ namespace i2p
clearText + ECIES_BUILD_REQUEST_RECORD_IV_KEY_OFFSET, clearText + ECIES_BUILD_REQUEST_RECORD_IV_KEY_OFFSET,
clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG, clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG,
clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG); clearText[ECIES_BUILD_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG);
if (!i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel)) i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel);
retCode = 30;
} }
else else
retCode = 30; // always reject with bandwidth reason (30) retCode = 30; // always reject with bandwidth reason (30)
@@ -549,8 +558,7 @@ namespace i2p
return; return;
} }
auto& noiseState = i2p::context.GetCurrentNoiseState (); auto& noiseState = i2p::context.GetCurrentNoiseState ();
uint8_t replyKey[32]; // AEAD/Chacha20/Poly1305 uint8_t replyKey[32], layerKey[32], ivKey[32];
i2p::crypto::AESKey layerKey, ivKey; // AES
i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelReplyKey", noiseState.m_CK); i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelReplyKey", noiseState.m_CK);
memcpy (replyKey, noiseState.m_CK + 32, 32); memcpy (replyKey, noiseState.m_CK + 32, 32);
i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelLayerKey", noiseState.m_CK); i2p::crypto::HKDF (noiseState.m_CK, nullptr, 0, "SMTunnelLayerKey", noiseState.m_CK);
@@ -566,7 +574,10 @@ namespace i2p
// check if we accept this tunnel // check if we accept this tunnel
uint8_t retCode = 0; uint8_t retCode = 0;
if (!i2p::context.AcceptsTunnels () || i2p::context.IsHighCongestion ()) if (!i2p::context.AcceptsTunnels () ||
i2p::tunnel::tunnels.GetTransitTunnels ().size () > g_MaxNumTransitTunnels ||
i2p::transport::transports.IsBandwidthExceeded () ||
i2p::transport::transports.IsTransitBandwidthExceeded ())
retCode = 30; retCode = 30;
if (!retCode) if (!retCode)
{ {
@@ -578,8 +589,7 @@ namespace i2p
layerKey, ivKey, layerKey, ivKey,
clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG, clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_GATEWAY_FLAG,
clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG); clearText[SHORT_REQUEST_RECORD_FLAG_OFFSET] & TUNNEL_BUILD_RECORD_ENDPOINT_FLAG);
if (!i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel)) i2p::tunnel::tunnels.AddTransitTunnel (transitTunnel);
retCode = 30;
} }
// encrypt reply // encrypt reply

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, The PurpleI2P Project * Copyright (c) 2013-2021, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -140,7 +140,6 @@ namespace tunnel
const size_t I2NP_MAX_MESSAGE_SIZE = 62708; const size_t I2NP_MAX_MESSAGE_SIZE = 62708;
const size_t I2NP_MAX_SHORT_MESSAGE_SIZE = 4096; const size_t I2NP_MAX_SHORT_MESSAGE_SIZE = 4096;
const size_t I2NP_MAX_MEDIUM_MESSAGE_SIZE = 16384;
const unsigned int I2NP_MESSAGE_EXPIRATION_TIMEOUT = 8000; // in milliseconds (as initial RTT) const unsigned int I2NP_MESSAGE_EXPIRATION_TIMEOUT = 8000; // in milliseconds (as initial RTT)
const unsigned int I2NP_MESSAGE_CLOCK_SKEW = 60*1000; // 1 minute in milliseconds const unsigned int I2NP_MESSAGE_CLOCK_SKEW = 60*1000; // 1 minute in milliseconds
@@ -263,7 +262,6 @@ namespace tunnel
std::shared_ptr<I2NPMessage> NewI2NPMessage (); std::shared_ptr<I2NPMessage> NewI2NPMessage ();
std::shared_ptr<I2NPMessage> NewI2NPShortMessage (); std::shared_ptr<I2NPMessage> NewI2NPShortMessage ();
std::shared_ptr<I2NPMessage> NewI2NPMediumMessage ();
std::shared_ptr<I2NPMessage> NewI2NPTunnelMessage (bool endpoint); std::shared_ptr<I2NPMessage> NewI2NPTunnelMessage (bool endpoint);
std::shared_ptr<I2NPMessage> NewI2NPMessage (size_t len); std::shared_ptr<I2NPMessage> NewI2NPMessage (size_t len);
@@ -310,6 +308,10 @@ namespace tunnel
std::vector<std::shared_ptr<I2NPMessage> > m_TunnelMsgs, m_TunnelGatewayMsgs; std::vector<std::shared_ptr<I2NPMessage> > m_TunnelMsgs, m_TunnelGatewayMsgs;
}; };
const uint16_t DEFAULT_MAX_NUM_TRANSIT_TUNNELS = 2500;
void SetMaxNumTransitTunnels (uint16_t maxNumTransitTunnels);
uint16_t GetMaxNumTransitTunnels ();
} }
#endif #endif

View File

@@ -36,23 +36,6 @@
#define le64toh(x) OSSwapLittleToHostInt64(x) #define le64toh(x) OSSwapLittleToHostInt64(x)
#elif defined(_WIN32) #elif defined(_WIN32)
#if defined(_MSC_VER)
#include <stdlib.h>
#define htobe16(x) _byteswap_ushort(x)
#define htole16(x) (x)
#define be16toh(x) _byteswap_ushort(x)
#define le16toh(x) (x)
#define htobe32(x) _byteswap_ulong(x)
#define htole32(x) (x)
#define be32toh(x) _byteswap_ulong(x)
#define le32toh(x) (x)
#define htobe64(x) _byteswap_uint64(x)
#define htole64(x) (x)
#define be64toh(x) _byteswap_uint64(x)
#define le64toh(x) (x)
#else
#define htobe16(x) __builtin_bswap16(x) #define htobe16(x) __builtin_bswap16(x)
#define htole16(x) (x) #define htole16(x) (x)
#define be16toh(x) __builtin_bswap16(x) #define be16toh(x) __builtin_bswap16(x)
@@ -67,7 +50,6 @@
#define htole64(x) (x) #define htole64(x) (x)
#define be64toh(x) __builtin_bswap64(x) #define be64toh(x) __builtin_bswap64(x)
#define le64toh(x) (x) #define le64toh(x) (x)
#endif
#else #else
#define NEEDS_LOCAL_ENDIAN #define NEEDS_LOCAL_ENDIAN

View File

@@ -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 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -49,21 +49,29 @@ namespace data
IdentityEx::IdentityEx(const uint8_t * publicKey, const uint8_t * signingKey, SigningKeyType type, CryptoKeyType cryptoType) IdentityEx::IdentityEx(const uint8_t * publicKey, const uint8_t * signingKey, SigningKeyType type, CryptoKeyType cryptoType)
{ {
uint8_t randomPaddingBlock[32]; /*uint8_t randomPaddingBlock[32];
RAND_bytes (randomPaddingBlock, 32); RAND_bytes (randomPaddingBlock, 32);*/
if (cryptoType == CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) if (cryptoType == CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)
{ {
memcpy (m_StandardIdentity.publicKey, publicKey ? publicKey : randomPaddingBlock, 32); /*memcpy (m_StandardIdentity.publicKey, publicKey ? publicKey : randomPaddingBlock, 32);
for (int i = 0; i < 7; i++) // 224 bytes for (int i = 0; i < 7; i++) // 224 bytes
memcpy (m_StandardIdentity.publicKey + 32*(i + 1), randomPaddingBlock, 32); memcpy (m_StandardIdentity.publicKey + 32*(i + 1), randomPaddingBlock, 32);*/
if (publicKey)
{
memcpy (m_StandardIdentity.publicKey, publicKey, 32);
RAND_bytes (m_StandardIdentity.publicKey + 32, 224);
}
else
RAND_bytes (m_StandardIdentity.publicKey, 256);
} }
else else
{ {
if (publicKey) if (publicKey)
memcpy (m_StandardIdentity.publicKey, publicKey, 256); memcpy (m_StandardIdentity.publicKey, publicKey, 256);
else else
for (int i = 0; i < 8; i++) // 256 bytes RAND_bytes (m_StandardIdentity.publicKey, 256);
memcpy (m_StandardIdentity.publicKey + 32*i, randomPaddingBlock, 32); /*for (int i = 0; i < 8; i++) // 256 bytes
memcpy (m_StandardIdentity.publicKey + 32*i, randomPaddingBlock, 32);*/
} }
if (type != SIGNING_KEY_TYPE_DSA_SHA1) if (type != SIGNING_KEY_TYPE_DSA_SHA1)
{ {
@@ -102,8 +110,9 @@ namespace data
case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519: case SIGNING_KEY_TYPE_REDDSA_SHA512_ED25519:
{ {
size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32 size_t padding = 128 - i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH; // 96 = 128 - 32
for (int i = 0; i < 3; i++) // 96 bytes /*for (int i = 0; i < 3; i++) // 96 bytes
memcpy (m_StandardIdentity.signingKey + 32*i, randomPaddingBlock, 32); memcpy (m_StandardIdentity.signingKey + 32*i, randomPaddingBlock, 32);*/
RAND_bytes (m_StandardIdentity.signingKey, 96);
memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH); memcpy (m_StandardIdentity.signingKey + padding, signingKey, i2p::crypto::EDDSA25519_PUBLIC_KEY_LENGTH);
break; break;
} }
@@ -187,6 +196,7 @@ namespace data
IdentityEx::~IdentityEx () IdentityEx::~IdentityEx ()
{ {
delete m_Verifier;
} }
IdentityEx& IdentityEx::operator=(const IdentityEx& other) IdentityEx& IdentityEx::operator=(const IdentityEx& other)
@@ -200,8 +210,9 @@ namespace data
if (m_ExtendedLen > MAX_EXTENDED_BUFFER_SIZE) m_ExtendedLen = MAX_EXTENDED_BUFFER_SIZE; if (m_ExtendedLen > MAX_EXTENDED_BUFFER_SIZE) m_ExtendedLen = MAX_EXTENDED_BUFFER_SIZE;
memcpy (m_ExtendedBuffer, other.m_ExtendedBuffer, m_ExtendedLen); memcpy (m_ExtendedBuffer, other.m_ExtendedBuffer, m_ExtendedLen);
} }
delete m_Verifier;
m_Verifier = nullptr; m_Verifier = nullptr;
CreateVerifier ();
return *this; return *this;
} }
@@ -210,10 +221,11 @@ namespace data
{ {
m_StandardIdentity = standard; m_StandardIdentity = standard;
m_IdentHash = m_StandardIdentity.Hash (); m_IdentHash = m_StandardIdentity.Hash ();
m_ExtendedLen = 0; m_ExtendedLen = 0;
delete m_Verifier;
m_Verifier = nullptr; m_Verifier = nullptr;
CreateVerifier ();
return *this; return *this;
} }
@@ -246,8 +258,8 @@ namespace data
m_ExtendedLen = 0; m_ExtendedLen = 0;
SHA256(buf, GetFullLen (), m_IdentHash); SHA256(buf, GetFullLen (), m_IdentHash);
delete m_Verifier;
m_Verifier = nullptr; m_Verifier = nullptr;
CreateVerifier ();
return GetFullLen (); return GetFullLen ();
} }
@@ -283,6 +295,7 @@ namespace data
size_t IdentityEx::GetSigningPublicKeyLen () const size_t IdentityEx::GetSigningPublicKeyLen () const
{ {
if (!m_Verifier) CreateVerifier ();
if (m_Verifier) if (m_Verifier)
return m_Verifier->GetPublicKeyLen (); return m_Verifier->GetPublicKeyLen ();
return 128; return 128;
@@ -297,6 +310,7 @@ namespace data
size_t IdentityEx::GetSigningPrivateKeyLen () const size_t IdentityEx::GetSigningPrivateKeyLen () const
{ {
if (!m_Verifier) CreateVerifier ();
if (m_Verifier) if (m_Verifier)
return m_Verifier->GetPrivateKeyLen (); return m_Verifier->GetPrivateKeyLen ();
return GetSignatureLen ()/2; return GetSignatureLen ()/2;
@@ -304,12 +318,14 @@ namespace data
size_t IdentityEx::GetSignatureLen () const size_t IdentityEx::GetSignatureLen () const
{ {
if (!m_Verifier) CreateVerifier ();
if (m_Verifier) if (m_Verifier)
return m_Verifier->GetSignatureLen (); return m_Verifier->GetSignatureLen ();
return i2p::crypto::DSA_SIGNATURE_LENGTH; return i2p::crypto::DSA_SIGNATURE_LENGTH;
} }
bool IdentityEx::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const bool IdentityEx::Verify (const uint8_t * buf, size_t len, const uint8_t * signature) const
{ {
if (!m_Verifier) CreateVerifier ();
if (m_Verifier) if (m_Verifier)
return m_Verifier->Verify (buf, len, signature); return m_Verifier->Verify (buf, len, signature);
return false; return false;
@@ -366,10 +382,9 @@ namespace data
return nullptr; return nullptr;
} }
void IdentityEx::CreateVerifier () void IdentityEx::CreateVerifier () const
{
if (!m_Verifier)
{ {
if (m_Verifier) return; // don't create again
auto verifier = CreateVerifier (GetSigningKeyType ()); auto verifier = CreateVerifier (GetSigningKeyType ());
if (verifier) if (verifier)
{ {
@@ -387,8 +402,32 @@ namespace data
delete[] signingKey; delete[] signingKey;
} }
} }
m_Verifier.reset (verifier); UpdateVerifier (verifier);
} }
void IdentityEx::UpdateVerifier (i2p::crypto::Verifier * verifier) const
{
bool del = false;
{
std::lock_guard<std::mutex> l(m_VerifierMutex);
if (!m_Verifier)
m_Verifier = verifier;
else
del = true;
}
if (del)
delete verifier;
}
void IdentityEx::DropVerifier () const
{
i2p::crypto::Verifier * verifier;
{
std::lock_guard<std::mutex> l(m_VerifierMutex);
verifier = m_Verifier;
m_Verifier = nullptr;
}
delete verifier;
} }
std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> IdentityEx::CreateEncryptor (CryptoKeyType keyType, const uint8_t * key) std::shared_ptr<i2p::crypto::CryptoKeyEncryptor> IdentityEx::CreateEncryptor (CryptoKeyType keyType, const uint8_t * key)

View File

@@ -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 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -13,7 +13,9 @@
#include <string.h> #include <string.h>
#include <string> #include <string>
#include <memory> #include <memory>
#include <atomic>
#include <vector> #include <vector>
#include <mutex>
#include "Base.h" #include "Base.h"
#include "Signature.h" #include "Signature.h"
#include "CryptoKey.h" #include "CryptoKey.h"
@@ -116,6 +118,7 @@ namespace data
SigningKeyType GetSigningKeyType () const; SigningKeyType GetSigningKeyType () const;
bool IsRSA () const; // signing key type bool IsRSA () const; // signing key type
CryptoKeyType GetCryptoKeyType () const; CryptoKeyType GetCryptoKeyType () const;
void DropVerifier () const; // to save memory
bool operator == (const IdentityEx & other) const { return GetIdentHash() == other.GetIdentHash(); } bool operator == (const IdentityEx & other) const { return GetIdentHash() == other.GetIdentHash(); }
void RecalculateIdentHash(uint8_t * buff=nullptr); void RecalculateIdentHash(uint8_t * buff=nullptr);
@@ -125,13 +128,15 @@ namespace data
private: private:
void CreateVerifier (); void CreateVerifier () const;
void UpdateVerifier (i2p::crypto::Verifier * verifier) const;
private: private:
Identity m_StandardIdentity; Identity m_StandardIdentity;
IdentHash m_IdentHash; IdentHash m_IdentHash;
std::unique_ptr<i2p::crypto::Verifier> m_Verifier; mutable i2p::crypto::Verifier * m_Verifier = nullptr;
mutable std::mutex m_VerifierMutex;
size_t m_ExtendedLen; size_t m_ExtendedLen;
uint8_t m_ExtendedBuffer[MAX_EXTENDED_BUFFER_SIZE]; uint8_t m_ExtendedBuffer[MAX_EXTENDED_BUFFER_SIZE];
}; };

View File

@@ -1,372 +0,0 @@
/*
* Copyright (c) 2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*
*/
#include "KadDHT.h"
namespace i2p
{
namespace data
{
DHTNode::DHTNode ():
zero (nullptr), one (nullptr)
{
}
DHTNode::~DHTNode ()
{
if (zero) delete zero;
if (one) delete one;
}
void DHTNode::MoveRouterUp (bool fromOne)
{
DHTNode *& side = fromOne ? one : zero;
if (side)
{
if (router) router = nullptr; // shouldn't happen
router = side->router;
side->router = nullptr;
delete side;
side = nullptr;
}
}
DHTTable::DHTTable ():
m_Size (0)
{
m_Root = new DHTNode;
}
DHTTable::~DHTTable ()
{
delete m_Root;
}
void DHTTable::Clear ()
{
m_Size = 0;
delete m_Root;
m_Root = new DHTNode;
}
void DHTTable::Insert (const std::shared_ptr<RouterInfo>& r)
{
if (!r) return;
return Insert (r, m_Root, 0);
}
void DHTTable::Insert (const std::shared_ptr<RouterInfo>& r, DHTNode * root, int level)
{
if (root->router)
{
if (root->router->GetIdentHash () == r->GetIdentHash ())
{
root->router = r; // replace
return;
}
auto r2 = root->router;
root->router = nullptr; m_Size--;
int bit1, bit2;
do
{
bit1 = r->GetIdentHash ().GetBit (level);
bit2 = r2->GetIdentHash ().GetBit (level);
if (bit1 == bit2)
{
if (bit1)
{
if (root->one) return; // something wrong
root->one = new DHTNode;
root = root->one;
}
else
{
if (root->zero) return; // something wrong
root->zero = new DHTNode;
root = root->zero;
}
level++;
}
}
while (bit1 == bit2);
if (!root->zero)
root->zero = new DHTNode;
if (!root->one)
root->one = new DHTNode;
if (bit1)
{
Insert (r2, root->zero, level + 1);
Insert (r, root->one, level + 1);
}
else
{
Insert (r2, root->one, level + 1);
Insert (r, root->zero, level + 1);
}
}
else
{
if (!root->zero && !root->one)
{
root->router = r; m_Size++;
return;
}
int bit = r->GetIdentHash ().GetBit (level);
if (bit)
{
if (!root->one)
root->one = new DHTNode;
Insert (r, root->one, level + 1);
}
else
{
if (!root->zero)
root->zero = new DHTNode;
Insert (r, root->zero, level + 1);
}
}
}
bool DHTTable::Remove (const IdentHash& h)
{
return Remove (h, m_Root, 0);
}
bool DHTTable::Remove (const IdentHash& h, DHTNode * root, int level)
{
if (root)
{
if (root->router && root->router->GetIdentHash () == h)
{
root->router = nullptr;
m_Size--;
return true;
}
int bit = h.GetBit (level);
if (bit)
{
if (root->one && Remove (h, root->one, level + 1))
{
if (root->one->IsEmpty ())
{
delete root->one;
root->one = nullptr;
if (root->zero && root->zero->router)
root->MoveRouterUp (false);
}
else if (root->one->router && !root->zero)
root->MoveRouterUp (true);
return true;
}
}
else
{
if (root->zero && Remove (h, root->zero, level + 1))
{
if (root->zero->IsEmpty ())
{
delete root->zero;
root->zero = nullptr;
if (root->one && root->one->router)
root->MoveRouterUp (true);
}
else if (root->zero->router && !root->one)
root->MoveRouterUp (false);
return true;
}
}
}
return false;
}
std::shared_ptr<RouterInfo> DHTTable::FindClosest (const IdentHash& h, const Filter& filter) const
{
if (filter) m_Filter = filter;
auto r = FindClosest (h, m_Root, 0);
m_Filter = nullptr;
return r;
}
std::shared_ptr<RouterInfo> DHTTable::FindClosest (const IdentHash& h, DHTNode * root, int level) const
{
bool split = false;
do
{
if (root->router)
return (!m_Filter || m_Filter (root->router)) ? root->router : nullptr;
split = root->zero && root->one;
if (!split)
{
if (root->zero) root = root->zero;
else if (root->one) root = root->one;
else return nullptr;
level++;
}
}
while (!split);
int bit = h.GetBit (level);
if (bit)
{
if (root->one)
{
auto r = FindClosest (h, root->one, level + 1);
if (r) return r;
}
if (root->zero)
{
auto r = FindClosest (h, root->zero, level + 1);
if (r) return r;
}
}
else
{
if (root->zero)
{
auto r = FindClosest (h, root->zero, level + 1);
if (r) return r;
}
if (root->one)
{
auto r = FindClosest (h, root->one, level + 1);
if (r) return r;
}
}
return nullptr;
}
std::vector<std::shared_ptr<RouterInfo> > DHTTable::FindClosest (const IdentHash& h, size_t num, const Filter& filter) const
{
std::vector<std::shared_ptr<RouterInfo> > vec;
if (num > 0)
{
if (filter) m_Filter = filter;
FindClosest (h, num, m_Root, 0, vec);
m_Filter = nullptr;
}
return vec;
}
void DHTTable::FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector<std::shared_ptr<RouterInfo> >& hashes) const
{
if (hashes.size () >= num) return;
bool split = false;
do
{
if (root->router)
{
if (!m_Filter || m_Filter (root->router))
hashes.push_back (root->router);
return;
}
split = root->zero && root->one;
if (!split)
{
if (root->zero) root = root->zero;
else if (root->one) root = root->one;
else return;
level++;
}
}
while (!split);
int bit = h.GetBit (level);
if (bit)
{
if (root->one)
FindClosest (h, num, root->one, level + 1, hashes);
if (hashes.size () < num && root->zero)
FindClosest (h, num, root->zero, level + 1, hashes);
}
else
{
if (root->zero)
FindClosest (h, num, root->zero, level + 1, hashes);
if (hashes.size () < num && root->one)
FindClosest (h, num, root->one, level + 1, hashes);
}
}
void DHTTable::Cleanup (const Filter& filter)
{
if (filter)
{
m_Filter = filter;
Cleanup (m_Root);
m_Filter = nullptr;
}
else
Clear ();
}
void DHTTable::Cleanup (DHTNode * root)
{
if (!root) return;
if (root->router)
{
if (!m_Filter || !m_Filter (root->router))
{
m_Size--;
root->router = nullptr;
}
return;
}
if (root->zero)
{
Cleanup (root->zero);
if (root->zero->IsEmpty ())
{
delete root->zero;
root->zero = nullptr;
}
}
if (root->one)
{
Cleanup (root->one);
if (root->one->IsEmpty ())
{
delete root->one;
root->one = nullptr;
if (root->zero && root->zero->router)
root->MoveRouterUp (false);
}
else if (root->one->router && !root->zero)
root->MoveRouterUp (true);
}
}
void DHTTable::Print (std::stringstream& s)
{
Print (s, m_Root, 0);
}
void DHTTable::Print (std::stringstream& s, DHTNode * root, int level)
{
if (!root) return;
s << std::string (level, '-');
if (root->router)
{
if (!root->zero && !root->one)
s << '>' << GetIdentHashAbbreviation (root->router->GetIdentHash ());
else
s << "error";
}
s << std::endl;
if (root->zero)
{
s << std::string (level, '-') << "0" << std::endl;
Print (s, root->zero, level + 1);
}
if (root->one)
{
s << std::string (level, '-') << "1" << std::endl;
Print (s, root->one, level + 1);
}
}
}
}

View File

@@ -1,74 +0,0 @@
/*
* Copyright (c) 2023, The PurpleI2P Project
*
* This file is part of Purple i2pd project and licensed under BSD3
*
* See full license text in LICENSE file at top of project tree
*
*/
#ifndef KADDHT_H__
#define KADDHT_H__
#include <memory>
#include <vector>
#include <sstream>
#include <functional>
#include "RouterInfo.h"
// Kademlia DHT (XOR distance)
namespace i2p
{
namespace data
{
struct DHTNode
{
DHTNode * zero, * one;
std::shared_ptr<RouterInfo> router;
DHTNode ();
~DHTNode ();
bool IsEmpty () const { return !zero && !one && !router; };
void MoveRouterUp (bool fromOne);
};
class DHTTable
{
typedef std::function<bool (const std::shared_ptr<RouterInfo>&)> Filter;
public:
DHTTable ();
~DHTTable ();
void Insert (const std::shared_ptr<RouterInfo>& r);
bool Remove (const IdentHash& h);
std::shared_ptr<RouterInfo> FindClosest (const IdentHash& h, const Filter& filter = nullptr) const;
std::vector<std::shared_ptr<RouterInfo> > FindClosest (const IdentHash& h, size_t num, const Filter& filter = nullptr) const;
void Print (std::stringstream& s);
size_t GetSize () const { return m_Size; };
void Clear ();
void Cleanup (const Filter& filter);
private:
void Insert (const std::shared_ptr<RouterInfo>& r, DHTNode * root, int level); // recursive
bool Remove (const IdentHash& h, DHTNode * root, int level);
std::shared_ptr<RouterInfo> FindClosest (const IdentHash& h, DHTNode * root, int level) const;
void FindClosest (const IdentHash& h, size_t num, DHTNode * root, int level, std::vector<std::shared_ptr<RouterInfo> >& hashes) const;
void Cleanup (DHTNode * root);
void Print (std::stringstream& s, DHTNode * root, int level);
private:
DHTNode * m_Root;
size_t m_Size;
// transient
mutable Filter m_Filter;
};
}
}
#endif

View File

@@ -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 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -50,7 +50,7 @@ namespace data
void LeaseSet::ReadFromBuffer (bool readIdentity, bool verifySignature) void LeaseSet::ReadFromBuffer (bool readIdentity, bool verifySignature)
{ {
if (readIdentity || !m_Identity) if (readIdentity || !m_Identity)
m_Identity = netdb.NewIdentity (m_Buffer, m_BufferLen); m_Identity = std::make_shared<IdentityEx>(m_Buffer, m_BufferLen);
size_t size = m_Identity->GetFullLen (); size_t size = m_Identity->GetFullLen ();
if (size + 256 > m_BufferLen) if (size + 256 > m_BufferLen)
{ {
@@ -76,7 +76,7 @@ namespace data
LogPrint (eLogDebug, "LeaseSet: Read num=", (int)num); LogPrint (eLogDebug, "LeaseSet: Read num=", (int)num);
if (!num || num > MAX_NUM_LEASES) if (!num || num > MAX_NUM_LEASES)
{ {
LogPrint (eLogError, "LeaseSet: Incorrect number of leases", (int)num); LogPrint (eLogError, "LeaseSet: Rncorrect number of leases", (int)num);
m_IsValid = false; m_IsValid = false;
return; return;
} }
@@ -315,9 +315,9 @@ namespace data
{ {
// standard LS2 header // standard LS2 header
std::shared_ptr<const IdentityEx> identity; std::shared_ptr<const IdentityEx> identity;
if (readIdentity || !GetIdentity ()) if (readIdentity)
{ {
identity = netdb.NewIdentity (buf, len); identity = std::make_shared<IdentityEx>(buf, len);
SetIdentity (identity); SetIdentity (identity);
} }
else else
@@ -366,8 +366,6 @@ namespace data
VerifySignature (identity, buf, len, offset); VerifySignature (identity, buf, len, offset);
SetIsValid (verified); SetIsValid (verified);
} }
else
SetIsValid (true);
offset += m_TransientVerifier ? m_TransientVerifier->GetSignatureLen () : identity->GetSignatureLen (); offset += m_TransientVerifier ? m_TransientVerifier->GetSignatureLen () : identity->GetSignatureLen ();
if (offset > len) { if (offset > len) {
LogPrint (eLogWarning, "LeaseSet2: short buffer: wanted ", int(offset), "bytes, have ", int(len)); LogPrint (eLogWarning, "LeaseSet2: short buffer: wanted ", int(offset), "bytes, have ", int(len));

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2023, The PurpleI2P Project * Copyright (c) 2013-2021, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -145,7 +145,6 @@ namespace data
{ {
public: public:
LeaseSet2 (uint8_t storeType): LeaseSet (true), m_StoreType (storeType) {}; // for update
LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases = true, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ELGAMAL); LeaseSet2 (uint8_t storeType, const uint8_t * buf, size_t len, bool storeLeases = true, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ELGAMAL);
LeaseSet2 (const uint8_t * buf, size_t len, std::shared_ptr<const BlindedPublicKey> key, const uint8_t * secret = nullptr, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ELGAMAL); // store type 5, called from local netdb only LeaseSet2 (const uint8_t * buf, size_t len, std::shared_ptr<const BlindedPublicKey> key, const uint8_t * secret = nullptr, CryptoKeyType preferredCrypto = CRYPTO_KEY_TYPE_ELGAMAL); // store type 5, called from local netdb only
uint8_t GetStoreType () const { return m_StoreType; }; uint8_t GetStoreType () const { return m_StoreType; };

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013-2022, The PurpleI2P Project * Copyright (c) 2013-2020, The PurpleI2P Project
* *
* This file is part of Purple i2pd project and licensed under BSD3 * This file is part of Purple i2pd project and licensed under BSD3
* *
@@ -21,9 +21,8 @@ namespace log {
static const char * g_LogLevelStr[eNumLogLevels] = static const char * g_LogLevelStr[eNumLogLevels] =
{ {
"none", // eLogNone "none", // eLogNone
"critical", // eLogCritical
"error", // eLogError "error", // eLogError
"warn", // eLogWarning "warn", // eLogWarn
"info", // eLogInfo "info", // eLogInfo
"debug" // eLogDebug "debug" // eLogDebug
}; };
@@ -33,16 +32,15 @@ namespace log {
* @note Using ISO 6429 (ANSI) color sequences * @note Using ISO 6429 (ANSI) color sequences
*/ */
#ifdef _WIN32 #ifdef _WIN32
static const char *LogMsgColors[] = { "", "", "", "", "", "", "" }; static const char *LogMsgColors[] = { "", "", "", "", "", "" };
#else /* UNIX */ #else /* UNIX */
static const char *LogMsgColors[] = { static const char *LogMsgColors[] = {
"\033[1;32m", /* none: green */ [eLogNone] = "\033[0m", /* reset */
"\033[1;41m", /* critical: red background */ [eLogError] = "\033[1;31m", /* red */
"\033[1;31m", /* error: red */ [eLogWarning] = "\033[1;33m", /* yellow */
"\033[1;33m", /* warning: yellow */ [eLogInfo] = "\033[1;36m", /* cyan */
"\033[1;36m", /* info: cyan */ [eLogDebug] = "\033[1;34m", /* blue */
"\033[1;34m", /* debug: blue */ [eNumLogLevels] = "\033[0m", /* reset */
"\033[0m" /* reset */
}; };
#endif #endif
@@ -55,7 +53,6 @@ namespace log {
int priority = LOG_DEBUG; int priority = LOG_DEBUG;
switch (l) { switch (l) {
case eLogNone : priority = LOG_CRIT; break; case eLogNone : priority = LOG_CRIT; break;
case eLogCritical: priority = LOG_CRIT; break;
case eLogError : priority = LOG_ERR; break; case eLogError : priority = LOG_ERR; break;
case eLogWarning : priority = LOG_WARNING; break; case eLogWarning : priority = LOG_WARNING; break;
case eLogInfo : priority = LOG_INFO; break; case eLogInfo : priority = LOG_INFO; break;
@@ -127,13 +124,12 @@ namespace log {
void Log::SetLogLevel (const std::string& level_) { void Log::SetLogLevel (const std::string& level_) {
std::string level=str_tolower(level_); std::string level=str_tolower(level_);
if (level == "none") { m_MinLevel = eLogNone; } if (level == "none") { m_MinLevel = eLogNone; }
else if (level == "critical") { m_MinLevel = eLogCritical; }
else if (level == "error") { m_MinLevel = eLogError; } else if (level == "error") { m_MinLevel = eLogError; }
else if (level == "warn") { m_MinLevel = eLogWarning; } else if (level == "warn") { m_MinLevel = eLogWarning; }
else if (level == "info") { m_MinLevel = eLogInfo; } else if (level == "info") { m_MinLevel = eLogInfo; }
else if (level == "debug") { m_MinLevel = eLogDebug; } else if (level == "debug") { m_MinLevel = eLogDebug; }
else { else {
LogPrint(eLogCritical, "Log: Unknown loglevel: ", level); LogPrint(eLogError, "Log: Unknown loglevel: ", level);
return; return;
} }
LogPrint(eLogInfo, "Log: Logging level set to ", level); LogPrint(eLogInfo, "Log: Logging level set to ", level);
@@ -216,7 +212,7 @@ namespace log {
m_LogStream = os; m_LogStream = os;
return; return;
} }
LogPrint(eLogCritical, "Log: Can't open file ", path); LogPrint(eLogError, "Log: Can't open file ", path);
} }
void Log::SendTo (std::shared_ptr<std::ostream> os) { void Log::SendTo (std::shared_ptr<std::ostream> os) {

View File

@@ -27,7 +27,6 @@
enum LogLevel enum LogLevel
{ {
eLogNone = 0, eLogNone = 0,
eLogCritical,
eLogError, eLogError,
eLogWarning, eLogWarning,
eLogInfo, eLogInfo,

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